-
Notifications
You must be signed in to change notification settings - Fork 1.4k
Deprecate Usage in favour of RequestUsage and RunUsage
#2378
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
PR Change SummaryIntroduced a new Usage interface to enhance compatibility with the genai-prices library.
Modified Files
How can I customize these reviews?Check out the Hyperlint AI Reviewer docs for more information on how to customize the review. If you just want to ignore it on this PR, you can add the Note specifically for link checks, we only check the first 30 links in a file and we cache the results for several hours (for instance, if you just added a page, you might experience this). Our recommendation is to add |
Docs Preview
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull Request Overview
This PR deprecates the old Usage class and introduces two new classes: RequestUsage and RunUsage. The main purpose is to work with the genai-prices library by providing more precise usage tracking. It also renames several token-related fields for consistency.
- Deprecates
pydantic_ai.usage.Usagein favor ofRequestUsage(for individual model requests) andRunUsage(for complete agent runs) - Renames token fields from
request_tokens/response_tokenstoinput_tokens/output_tokenswith deprecation warnings - Updates
ModelResponseto useprovider_detailsandprovider_request_idinstead ofvendor_detailsandvendor_id
Reviewed Changes
Copilot reviewed 65 out of 66 changed files in this pull request and generated 2 comments.
Show a summary per file
| File | Description |
|---|---|
| tests/test_usage_limits.py | Updates tests to use new RequestUsage and RunUsage classes, including tests for deprecated field warnings |
| tests/test_toolsets.py | Simple import update from Usage to RunUsage |
| tests/test_tools.py | Updates import and usage expectations from Usage to RequestUsage |
| tests/test_streaming.py | Updates imports and test assertions to use new usage classes |
| tests/test_mcp.py | Updates usage assertions and model response field names throughout MCP tests |
| tests/test_history_processor.py | Updates usage expectations in history processor tests |
| tests/test_direct.py | Updates direct model request tests to use RequestUsage |
| tests/test_agent.py | Comprehensive updates across agent tests for new usage classes and field names |
| tests/test_a2a.py | Simple usage class update in agent-to-agent tests |
| tests/models/test_openai_responses.py | Updates OpenAI model response tests with new usage classes and field names |
| tests/models/test_openai.py | Extensive updates to OpenAI model tests for new usage tracking |
| tests/models/test_model_test.py | Updates test model usage expectations |
| tests/models/test_model_function.py | Updates function model tests with new usage classes |
| tests/models/test_mistral.py | Updates Mistral model tests with new usage tracking and field names |
| tests/models/test_mcp_sampling.py | Removes usage assertions in MCP sampling tests |
| tests/models/test_instrumented.py | Updates instrumented model tests to use RequestUsage |
| tests/models/test_huggingface.py | Updates HuggingFace model tests with new usage classes |
| tests/models/test_groq.py | Updates Groq model tests with new usage tracking |
Tip: Customize your code reviews with copilot-instructions.md. Create the file or learn how to get started.
Usage in favour of RequestUsage and RunUsage to work with genai-pricesUsage in favour of RequestUsage and RunUsage
| class RequestUsage(UsageBase): | ||
| """LLM usage associated with a single request. | ||
| This is an implementation of `genai_prices.types.AbstractUsage` so it can be used to calculate the price of the |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why it doesn't inherit the protocol?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pyright complains with things like error: "input_tokens" incorrectly overrides property of same name in class "AbstractUsage"
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Shouldn't we use property here as well to match it?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I understand we don't want to delay things, but it seems weird to not use the abstract class.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
even genai-prices is like this with the concrete Usage class.
these attributes are writable, so we'd need a getter and setter for each, and __init__ and __eq__. dataclasses are too helpful here.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If not even the one in genai-prices use it, what's the point? Is it even type safe if you use AbstractUsage?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
functions like calc_price in genai-prices expect this protocol, and having the relevant attributes means the protocol is satisfied automatically, so e.g. RequestUsage is accepted by those functions.
Closes #2352
pydantic_ai.usage.Usage.AgentRunResult.usage()now returns aRunUsagewhileModelResponse.usageis aRequestUsage. The two classes are very similar, but prices should only be calculated using aRequestUsage. The classes also differ slightly from the oldUsage:request_tokenstoinput_tokensandresponse_tokenstooutput_tokenswith deprecation warnings. Similar renames apply to theUsageLimitsconstructor.None, they all default to0except fordetailswhich defaults to{}.ModelResponse:vendor_detailstoprovider_detailsandvendor_idtoprovider_request_idinModelResponsewith deprecation warnings.ModelResponse.price()method to calculate the actual cost of a single request using https://github.com/pydantic/genai-prices.ModelResponse.provider_namefield