fix: inference geo cost on anthropic (#5072) - #5088
Conversation
|
|
This stack of pull requests is managed by Graphite. Learn more about stacking. |
Confidence Score: 5/5This looks safe to merge.
Important Files Changed
Reviews (3): Last reviewed commit: "fix: inference geo cost on anthropic (#5..." | Re-trigger Greptile |
b900b3a to
19fb627
Compare
|
Caution Review failedThe pull request is closed. ℹ️ Recent review info⚙️ Run configurationConfiguration used: Path: .coderabbit.yaml Review profile: CHILL Plan: Pro Plus Run ID: 📒 Files selected for processing (17)
📝 WalkthroughSummary by CodeRabbit
WalkthroughAnthropic usage handling now propagates web-search counts, served speed, and inference geography through streaming and response conversions. Model pricing persists and applies an inference-geography multiplier to token costs, with configstore and custom-pricing support. ChangesAnthropic usage propagation
Estimated code review effort: 4 (Complex) | ~45 minutes Sequence Diagram(s)sequenceDiagram
participant Anthropic
participant BifrostStreaming
participant UsageBilling
participant ModelPricing
Anthropic->>BifrostStreaming: stream usage with Speed, InferenceGeo, and web-search counts
BifrostStreaming->>UsageBilling: accumulate usage and served-tier metadata
UsageBilling->>ModelPricing: derive pricing tier
ModelPricing->>UsageBilling: apply US multiplier to token costs
Possibly related PRs
Suggested reviewers: 🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Warning There were issues while running some tools. Please review the errors and either fix the tool's configuration or disable the tool if it's a critical failure. 🔧 golangci-lint (2.12.2)level=error msg="[linters_context] typechecking error: pattern ./...: directory prefix . does not contain main module or its selected dependencies" Comment |
Merge activity
|
The base branch was changed.
## Summary Adds support for Anthropic's data-residency billing feature (`inference_geo`). When Anthropic serves inference in the US (`inference_geo: "us"`), a 1.1x multiplier is applied to all token and cache costs. This PR propagates the `inference_geo` field through the full response pipeline (chat, responses, streaming, passthrough) and wires it into the cost computation layer, including a new database column and UI override field. A secondary fix ensures Anthropic server-tool web search request counts (`ServerToolUse.WebSearchRequests`) are correctly forwarded and billed in both streaming and non-streaming paths, where previously the count could be lost when the terminal chunk overwrote the accumulated usage. ## Changes - **`inference_geo` propagation**: `InferenceGeo *string` added to `BifrostChatResponse`, `BifrostResponsesResponse`, and `BifrostPassthroughUsage`. The field is forwarded from `AnthropicUsage` in all conversion paths: non-streaming chat, non-streaming responses, streaming chat (captured across events and set on the final chunk), streaming responses (`message_delta`), and passthrough. - **Data-residency multiplier in cost computation**: `serviceTier` gains an `inferenceGeoUS bool` flag. `tierFromResponse` now accepts and evaluates `inferenceGeo`. `computeTextCost` applies `InferenceGeoUSMultiplier` to token/cache costs only — the flat per-search fee is intentionally excluded. - **Database migration**: `migrationAddInferenceGeoMultiplierColumn` adds `inference_geo_us_multiplier` to `TableModelPricing`. The column is included in the pricing sync update list and mapped through `convertEntryToTablePricing` / `convertTablePricingToEntry`. - **Web search billing fix**: `accumulateAnthropicResponsesUsage` now carries `ServerToolUse.WebSearchRequests` into the accumulator so the count survives the terminal-chunk overwrite on streamed Responses requests. The non-streaming chat converter also forwards the count into `CompletionTokensDetails.NumSearchQueries`. - **UI**: `inference_geo_us_multiplier` added to the custom pricing override sheet and `PricingOverridePatch` TypeScript type. - **Tests**: New unit tests cover the accumulator web-search fix, chat/responses converter forwarding of `InferenceGeo` and web search counts, multiplier application (including the no-multiplier-column safe no-op), and `tierFromResponse` geo detection (case-insensitive). ## Type of change - [ ] Bug fix - [x] Feature - [ ] Refactor - [ ] Documentation - [ ] Chore/CI ## Affected areas - [x] Core (Go) - [ ] Transports (HTTP) - [x] Providers/Integrations - [ ] Plugins - [x] UI (React) - [ ] Docs ## How to test ```sh # Core/Transports go test ./core/providers/anthropic/... ./framework/modelcatalog/datasheet/... # UI cd ui pnpm i || npm i pnpm build || npm run build ``` To validate end-to-end: send a request to an Anthropic model with data residency enabled. The response should include `inference_geo: "us"` and the computed cost should reflect the 1.1x multiplier on token/cache costs, with the per-search fee unchanged. ## Breaking changes - [ ] Yes - [x] No ## Security considerations No auth, secrets, or PII implications. The `inference_geo` value is sourced from Anthropic's API response and used only for billing computation. ## Checklist - [ ] I read `docs/contributing/README.md` and followed the guidelines - [x] I added/updated tests where appropriate - [ ] I updated documentation where needed - [x] I verified builds succeed (Go and UI) - [ ] I verified the CI pipeline passes locally if applicable
19fb627 to
41d99a8
Compare
## Summary Adds end-to-end support for Anthropic's data-residency billing feature (`inference_geo`). When Anthropic serves a request with `inference_geo: "us"`, a 1.1× multiplier is applied to all token and cache costs. This PR propagates the `inference_geo` field from the Anthropic API response through all converter paths (chat, responses, streaming, passthrough) and wires it into the cost engine so US-residency requests bill correctly. It also fixes a related streaming bug where web search request counts were lost on the terminal chunk of streamed Responses requests, causing web search to go unbilled. ## Changes - **`inference_geo` field propagation**: Added `InferenceGeo *string` to `BifrostChatResponse`, `BifrostResponsesResponse`, and `BifrostPassthroughUsage` schemas. All Anthropic converters (`ToBifrostChatResponse`, `ToBifrostResponsesResponse`, `ToBifrostResponsesStream`, passthrough usage) now forward `inference_geo` from the provider's usage block. - **Streaming terminal chunk fix**: In both `HandleAnthropicChatCompletionStreaming` and `HandleAnthropicResponsesStream`, `servedSpeed` and `servedInferenceGeo` are captured across events and re-applied to the terminal chunk. The terminal `response.completed` chunk is built fresh with no served modifiers, so without this re-apply, fast-mode and data-residency billing silently fell back to standard rates. - **Web search count accumulation fix**: `accumulateAnthropicResponsesUsage` now carries `ServerToolUse.WebSearchRequests` into both the response usage accumulator and the mirrored billed usage. Previously the per-event count was overwritten by the terminal chunk's fresh usage, causing web search to go unbilled on streamed Responses requests. - **Cost engine**: `serviceTier` gains an `inferenceGeoUS bool` field. `tierFromResponse` accepts a third `inferenceGeo *string` argument and sets `inferenceGeoUS` when the value is `"us"` (case-insensitive). `computeTextCost` applies `InferenceGeoUSMultiplier` to all token/cache costs when `inferenceGeoUS` is true; the flat per-search fee is intentionally excluded from the multiplier. - **Database migration**: Adds `inference_geo_us_multiplier` column to `TableModelPricing` via a new migration step. The column is included in pricing sync, override patching, and the entry↔table conversion helpers. - **UI**: Exposes `inference_geo_us_multiplier` as a configurable field in the custom pricing override sheet. - **Tests**: New unit tests cover the accumulator web-search fix, the chat and responses converters forwarding `inference_geo` and web search counts, the cost engine multiplier logic (including the safe no-op when the column is unpopulated), `tierFromResponse` for `inferenceGeoUS`, and an end-to-end streaming test (`TestResponsesStream_TerminalChunkCarriesServedModifiers`) that replays `message_start → message_delta → message_stop` and asserts the terminal billed chunk carries `speed`, `inference_geo`, web search count, and cache-creation tokens. ## Type of change - [ ] Bug fix - [x] Feature - [ ] Refactor - [ ] Documentation - [ ] Chore/CI ## Affected areas - [x] Core (Go) - [ ] Transports (HTTP) - [x] Providers/Integrations - [ ] Plugins - [x] UI (React) - [ ] Docs ## How to test ```sh # Core/Transports go test ./core/providers/anthropic/... ./framework/modelcatalog/datasheet/... # UI cd ui pnpm i pnpm build ``` To validate end-to-end: send a chat or responses request to an Anthropic model with data residency enabled. Confirm the response carries `inference_geo: "us"` and that the billed cost reflects the 1.1× multiplier on token/cache costs with the per-search fee unchanged. For streaming, confirm the terminal chunk carries both `speed` and `inference_geo` after `message_stop`. The `inference_geo_us_multiplier` column must be populated in the model pricing datasheet for the multiplier to apply; if the column is `null`, billing is a safe no-op (standard rates). ## Breaking changes - [x] No `tierFromResponse` gains a third parameter but is an internal function. All call sites have been updated. ## Related issues ## Security considerations No auth, secrets, or PII implications. The multiplier is a pricing configuration value stored in the existing model pricing table with the same access controls as other pricing columns. ## Checklist - [ ] I read `docs/contributing/README.md` and followed the guidelines - [x] I added/updated tests where appropriate - [ ] I updated documentation where needed - [x] I verified builds succeed (Go and UI) - [ ] I verified the CI pipeline passes locally if applicable
## Summary Adds end-to-end support for Anthropic's data-residency billing feature (`inference_geo`). When Anthropic serves a request with `inference_geo: "us"`, a 1.1× multiplier is applied to all token and cache costs. This PR propagates the `inference_geo` field from the Anthropic API response through all converter paths (chat, responses, streaming, passthrough) and wires it into the cost engine so US-residency requests bill correctly. It also fixes a related streaming bug where web search request counts were lost on the terminal chunk of streamed Responses requests, causing web search to go unbilled. ## Changes - **`inference_geo` field propagation**: Added `InferenceGeo *string` to `BifrostChatResponse`, `BifrostResponsesResponse`, and `BifrostPassthroughUsage` schemas. All Anthropic converters (`ToBifrostChatResponse`, `ToBifrostResponsesResponse`, `ToBifrostResponsesStream`, passthrough usage) now forward `inference_geo` from the provider's usage block. - **Streaming terminal chunk fix**: In both `HandleAnthropicChatCompletionStreaming` and `HandleAnthropicResponsesStream`, `servedSpeed` and `servedInferenceGeo` are captured across events and re-applied to the terminal chunk. The terminal `response.completed` chunk is built fresh with no served modifiers, so without this re-apply, fast-mode and data-residency billing silently fell back to standard rates. - **Web search count accumulation fix**: `accumulateAnthropicResponsesUsage` now carries `ServerToolUse.WebSearchRequests` into both the response usage accumulator and the mirrored billed usage. Previously the per-event count was overwritten by the terminal chunk's fresh usage, causing web search to go unbilled on streamed Responses requests. - **Cost engine**: `serviceTier` gains an `inferenceGeoUS bool` field. `tierFromResponse` accepts a third `inferenceGeo *string` argument and sets `inferenceGeoUS` when the value is `"us"` (case-insensitive). `computeTextCost` applies `InferenceGeoUSMultiplier` to all token/cache costs when `inferenceGeoUS` is true; the flat per-search fee is intentionally excluded from the multiplier. - **Database migration**: Adds `inference_geo_us_multiplier` column to `TableModelPricing` via a new migration step. The column is included in pricing sync, override patching, and the entry↔table conversion helpers. - **UI**: Exposes `inference_geo_us_multiplier` as a configurable field in the custom pricing override sheet. - **Tests**: New unit tests cover the accumulator web-search fix, the chat and responses converters forwarding `inference_geo` and web search counts, the cost engine multiplier logic (including the safe no-op when the column is unpopulated), `tierFromResponse` for `inferenceGeoUS`, and an end-to-end streaming test (`TestResponsesStream_TerminalChunkCarriesServedModifiers`) that replays `message_start → message_delta → message_stop` and asserts the terminal billed chunk carries `speed`, `inference_geo`, web search count, and cache-creation tokens. ## Type of change - [ ] Bug fix - [x] Feature - [ ] Refactor - [ ] Documentation - [ ] Chore/CI ## Affected areas - [x] Core (Go) - [ ] Transports (HTTP) - [x] Providers/Integrations - [ ] Plugins - [x] UI (React) - [ ] Docs ## How to test ```sh # Core/Transports go test ./core/providers/anthropic/... ./framework/modelcatalog/datasheet/... # UI cd ui pnpm i pnpm build ``` To validate end-to-end: send a chat or responses request to an Anthropic model with data residency enabled. Confirm the response carries `inference_geo: "us"` and that the billed cost reflects the 1.1× multiplier on token/cache costs with the per-search fee unchanged. For streaming, confirm the terminal chunk carries both `speed` and `inference_geo` after `message_stop`. The `inference_geo_us_multiplier` column must be populated in the model pricing datasheet for the multiplier to apply; if the column is `null`, billing is a safe no-op (standard rates). ## Breaking changes - [x] No `tierFromResponse` gains a third parameter but is an internal function. All call sites have been updated. ## Related issues ## Security considerations No auth, secrets, or PII implications. The multiplier is a pricing configuration value stored in the existing model pricing table with the same access controls as other pricing columns. ## Checklist - [ ] I read `docs/contributing/README.md` and followed the guidelines - [x] I added/updated tests where appropriate - [ ] I updated documentation where needed - [x] I verified builds succeed (Go and UI) - [ ] I verified the CI pipeline passes locally if applicable

Summary
Adds end-to-end support for Anthropic's data-residency billing feature (
inference_geo). When Anthropic serves a request withinference_geo: "us", a 1.1× multiplier is applied to all token and cache costs. This PR propagates theinference_geofield from the Anthropic API response through all converter paths (chat, responses, streaming, passthrough) and wires it into the cost engine so US-residency requests bill correctly. It also fixes a related streaming bug where web search request counts were lost on the terminal chunk of streamed Responses requests, causing web search to go unbilled.Changes
inference_geofield propagation: AddedInferenceGeo *stringtoBifrostChatResponse,BifrostResponsesResponse, andBifrostPassthroughUsageschemas. All Anthropic converters (ToBifrostChatResponse,ToBifrostResponsesResponse,ToBifrostResponsesStream, passthrough usage) now forwardinference_geofrom the provider's usage block.HandleAnthropicChatCompletionStreamingandHandleAnthropicResponsesStream,servedSpeedandservedInferenceGeoare captured across events and re-applied to the terminal chunk. The terminalresponse.completedchunk is built fresh with no served modifiers, so without this re-apply, fast-mode and data-residency billing silently fell back to standard rates.accumulateAnthropicResponsesUsagenow carriesServerToolUse.WebSearchRequestsinto both the response usage accumulator and the mirrored billed usage. Previously the per-event count was overwritten by the terminal chunk's fresh usage, causing web search to go unbilled on streamed Responses requests.serviceTiergains aninferenceGeoUS boolfield.tierFromResponseaccepts a thirdinferenceGeo *stringargument and setsinferenceGeoUSwhen the value is"us"(case-insensitive).computeTextCostappliesInferenceGeoUSMultiplierto all token/cache costs wheninferenceGeoUSis true; the flat per-search fee is intentionally excluded from the multiplier.inference_geo_us_multipliercolumn toTableModelPricingvia a new migration step. The column is included in pricing sync, override patching, and the entry↔table conversion helpers.inference_geo_us_multiplieras a configurable field in the custom pricing override sheet.inference_geoand web search counts, the cost engine multiplier logic (including the safe no-op when the column is unpopulated),tierFromResponseforinferenceGeoUS, and an end-to-end streaming test (TestResponsesStream_TerminalChunkCarriesServedModifiers) that replaysmessage_start → message_delta → message_stopand asserts the terminal billed chunk carriesspeed,inference_geo, web search count, and cache-creation tokens.Type of change
Affected areas
How to test
To validate end-to-end: send a chat or responses request to an Anthropic model with data residency enabled. Confirm the response carries
inference_geo: "us"and that the billed cost reflects the 1.1× multiplier on token/cache costs with the per-search fee unchanged. For streaming, confirm the terminal chunk carries bothspeedandinference_geoaftermessage_stop.The
inference_geo_us_multipliercolumn must be populated in the model pricing datasheet for the multiplier to apply; if the column isnull, billing is a safe no-op (standard rates).Breaking changes
tierFromResponsegains a third parameter but is an internal function. All call sites have been updated.Related issues
Security considerations
No auth, secrets, or PII implications. The multiplier is a pricing configuration value stored in the existing model pricing table with the same access controls as other pricing columns.
Checklist
docs/contributing/README.mdand followed the guidelines