Skip to content

Fix/fast pricing#153

Merged
james-6-23 merged 4 commits into
james-6-23:mainfrom
abwuge:fix/fast-pricing
May 23, 2026
Merged

Fix/fast pricing#153
james-6-23 merged 4 commits into
james-6-23:mainfrom
abwuge:fix/fast-pricing

Conversation

@abwuge
Copy link
Copy Markdown
Contributor

@abwuge abwuge commented May 22, 2026

修复fast模式下计价错误的问题

Summary by CodeRabbit

  • New Features

    • "Fast" service tier now receives the same priority pricing when priority pricing is enabled.
    • Billing now records a distinct billing service tier (separable from the visible service tier) so billed amounts reflect the determined billing tier.
  • Tests

    • Added coverage validating billing-tier selection and that billed amounts for "fast" and "priority" behave as expected.

Review Change Stack

Copilot AI review requested due to automatic review settings May 22, 2026 23:25
@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 22, 2026

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 67972d36-c041-43aa-b8b3-3c9d0af35f79

📥 Commits

Reviewing files that changed from the base of the PR and between f16059a and ceea611.

📒 Files selected for processing (4)
  • database/billing_test.go
  • database/sqlite_test.go
  • proxy/translator.go
  • proxy/translator_test.go

📝 Walkthrough

Walkthrough

This PR introduces a billing service tier concept that decouples cost calculation from the actual or requested service tier. A new resolver function normalizes tiers for billing, pricing rules now treat fast tier like priority, and all request handlers log a computed billing tier override when usage is recorded.

Changes

Billing Service Tier Separation

Layer / File(s) Summary
Billing tier resolution helper
proxy/translator.go, proxy/translator_test.go
New resolveBillingServiceTier() function normalizes actual and requested service tiers to a unified billing tier, mapping both priority and fast to the same billing value. Comprehensive table-driven tests verify behavior across tier combinations.
Pricing rule updates for fast tier and priority multiplier
database/billing.go, database/billing_test.go
Pricing entries for GPT-5.5 and GPT-5.4 are reformatted. Priority pricing logic now treats fast as eligible alongside priority. Priority tier no longer gets a dedicated multiplier; it falls through to the default 1.0 while flex retains 0.5. Tests verify fast tier receives priority pricing and that no invented multiplier is applied when priority pricing is unknown.
UsageLogInput schema and database cost calculation
database/postgres.go, database/sqlite_test.go
UsageLogInput gains a BillingServiceTier field for optional override. InsertUsageLog selects billing tier from that field with fallback to ServiceTier, then uses it to compute accountBilled. SQLite test verifies billing is calculated from the billing tier even when ServiceTier differs.
Request handler logging integration
proxy/handler.go
Four request handlers compute billingServiceTier via resolveBillingServiceTier() and include it in UsageLogInput.BillingServiceTier. The /v1/responses, /v1/responses/compact, and /v1/chat/completions endpoints all follow this pattern.

Sequence Diagram(s)

sequenceDiagram
  participant Handler as Request Handler
  participant Translator as resolveBillingServiceTier
  participant UsageLog as UsageLogInput
  participant DB as InsertUsageLog
  participant BillingCalc as calculateCost
  
  Handler->>Translator: resolveBillingServiceTier(actualTier, requestedTier)
  Translator-->>Handler: billingServiceTier
  Handler->>UsageLog: set BillingServiceTier field
  Handler->>DB: InsertUsageLog(UsageLogInput{..., BillingServiceTier})
  DB->>BillingCalc: calculateCost(..., billingServiceTier)
  BillingCalc-->>DB: accountBilled
  DB-->>Handler: usage logged with computed cost
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Poem

🐰 A rabbit hops through billing tiers,
Where fast and priority align,
One tier for logic, one for billing—
Clean separation, oh how divine!
Honest costs now hop in line.

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 15.38% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'Fix/fast pricing' directly relates to the PR's main objective of fixing pricing calculations for fast-mode requests, as confirmed by the commit message and detailed changes across billing and handler logic.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Note

Copilot was unable to run its full agentic suite in this review.

This PR separates user-visible service tier normalization from billing tier calculation so usage logs can bill based on upstream-reported tiers while still presenting a consistent UI tier.

Changes:

  • Adds resolveBillingServiceTier and unit tests to compute billing tier independently from UI tier.
  • Propagates BillingServiceTier through request handlers into UsageLogInput.
  • Updates billing logic so fast uses priority pricing when available, and removes the old “priority multiplier” fallback.

Reviewed changes

Copilot reviewed 7 out of 7 changed files in this pull request and generated 3 comments.

Show a summary per file
File Description
proxy/translator.go Introduces resolveBillingServiceTier to decouple billing tier resolution from UI tier normalization.
proxy/translator_test.go Adds table-driven tests validating billing-tier resolution rules.
proxy/handler.go Records both resolved UI tier and billing tier in usage logs.
database/postgres.go Bills using BillingServiceTier when provided; extends UsageLogInput accordingly.
database/billing.go Treats fast as eligible for priority pricing; removes priority multiplier behavior.
database/billing_test.go Adds coverage for fast priority pricing and “no invented priority multiplier” behavior.
database/sqlite_test.go Adds regression test asserting billed amount depends on BillingServiceTier.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread proxy/translator.go
Comment on lines +1809 to +1823
actualTier = strings.ToLower(strings.TrimSpace(actualTier))
switch actualTier {
case "priority", "fast":
return "priority"
case "default", "auto", "flex", "scale":
return actualTier
}

requestedTier = strings.ToLower(strings.TrimSpace(requestedTier))
switch requestedTier {
case "priority", "fast":
return "priority"
default:
return requestedTier
}
Comment thread proxy/translator.go Outdated
Comment on lines +1806 to +1807
// report a concrete tier, or when it confirms priority. If upstream downgrades
// to default, billing must follow the actual default tier.
Comment thread database/sqlite_test.go Outdated
Comment on lines +788 to +793
if logs[0].ServiceTier != "fast" || logs[0].AccountBilled != wantPriority {
t.Fatalf("priority-billed fast log = tier %q billed %.12f, want tier fast billed %.12f", logs[0].ServiceTier, logs[0].AccountBilled, wantPriority)
}
if logs[1].ServiceTier != "fast" || logs[1].AccountBilled != wantDefault {
t.Fatalf("default-billed fast log = tier %q billed %.12f, want tier fast billed %.12f", logs[1].ServiceTier, logs[1].AccountBilled, wantDefault)
}
Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (2)
database/billing_test.go (1)

103-120: ⚡ Quick win

Add a fast fallback test when priority prices are unavailable.

You already cover priority fallback on gpt-4o; adding the same assertion for fast closes the exact new branch added in billing logic.

Proposed test-case addition
 		{
 			name:         "does not invent priority multiplier when priority price is unknown",
 			model:        "gpt-4o",
 			serviceTier:  "priority",
 			inputTokens:  1000,
 			outputTokens: 500,
 			cachedTokens: 200,
 			want:         0.0075,
 		},
+		{
+			name:         "fast tier falls back to standard pricing when priority price is unknown",
+			model:        "gpt-4o",
+			serviceTier:  "fast",
+			inputTokens:  1000,
+			outputTokens: 500,
+			cachedTokens: 200,
+			want:         0.0075,
+		},
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@database/billing_test.go` around lines 103 - 120, Add a test case in
billing_test.go to cover the new branch where the "fast" serviceTier falls back
to priority prices when priority prices are unavailable: insert a table entry
mirroring the existing "does not invent priority multiplier when priority price
is unknown" case but with serviceTier set to "fast", model "gpt-4o", inputTokens
1000, outputTokens 500, cachedTokens 200 and want 0.0075; place it alongside the
other cases so the test that drives the billing calculation (the same test table
used by the CalculateCost / billing logic) verifies the fast-tier fallback
behavior.
proxy/translator_test.go (1)

60-81: ⚡ Quick win

Add a regression case for unknown concrete upstream tiers.

Please add a case where actual is non-empty unknown (e.g., "burst") and requested is "fast"; expected billing tier should be "burst".

Suggested test case
 tests := []struct {
   name      string
   actual    string
   requested string
   want      string
 }{
   {name: "actual priority wins", actual: "priority", requested: "fast", want: "priority"},
   {name: "actual default downgrade wins", actual: "default", requested: "fast", want: "default"},
+  {name: "unknown concrete actual tier wins", actual: "burst", requested: "fast", want: "burst"},
   {name: "requested fast fallback bills priority", actual: "", requested: "fast", want: "priority"},
   {name: "requested priority fallback bills priority", actual: "", requested: "priority", want: "priority"},
   {name: "default stays default", actual: "default", requested: "", want: "default"},
 }
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@proxy/translator_test.go` around lines 60 - 81, Add a regression test in
TestResolveBillingServiceTier to cover unknown concrete upstream tiers: include
a test case with name like "unknown actual stays", actual: "burst", requested:
"fast", want: "burst" so resolveBillingServiceTier("burst","fast") returns
"burst"; update the tests slice inside TestResolveBillingServiceTier (the
table-driven tests) to include this case referencing the existing
TestResolveBillingServiceTier and resolveBillingServiceTier identifiers.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@proxy/translator.go`:
- Around line 1808-1823: The function resolveBillingServiceTier currently only
treats a small allowlist of actualTier values as concrete; change it so any
non-empty upstream actualTier is honored as the concrete billing tier: trim and
lowercase actualTier, if the result is non-empty then map known synonyms ("fast"
-> "priority") but otherwise return the normalized actualTier; only when
actualTier is empty fall back to normalizing and mapping requestedTier. Update
the logic in resolveBillingServiceTier to perform this check using the existing
actualTier and requestedTier variables and existing mapping rules.

---

Nitpick comments:
In `@database/billing_test.go`:
- Around line 103-120: Add a test case in billing_test.go to cover the new
branch where the "fast" serviceTier falls back to priority prices when priority
prices are unavailable: insert a table entry mirroring the existing "does not
invent priority multiplier when priority price is unknown" case but with
serviceTier set to "fast", model "gpt-4o", inputTokens 1000, outputTokens 500,
cachedTokens 200 and want 0.0075; place it alongside the other cases so the test
that drives the billing calculation (the same test table used by the
CalculateCost / billing logic) verifies the fast-tier fallback behavior.

In `@proxy/translator_test.go`:
- Around line 60-81: Add a regression test in TestResolveBillingServiceTier to
cover unknown concrete upstream tiers: include a test case with name like
"unknown actual stays", actual: "burst", requested: "fast", want: "burst" so
resolveBillingServiceTier("burst","fast") returns "burst"; update the tests
slice inside TestResolveBillingServiceTier (the table-driven tests) to include
this case referencing the existing TestResolveBillingServiceTier and
resolveBillingServiceTier identifiers.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: f303c129-ddeb-4eb8-90cf-bce5457f54c1

📥 Commits

Reviewing files that changed from the base of the PR and between 0627e0b and f16059a.

📒 Files selected for processing (7)
  • database/billing.go
  • database/billing_test.go
  • database/postgres.go
  • database/sqlite_test.go
  • proxy/handler.go
  • proxy/translator.go
  • proxy/translator_test.go

Comment thread proxy/translator.go
@james-6-23 james-6-23 merged commit d2e4f85 into james-6-23:main May 23, 2026
6 checks passed
@abwuge abwuge deleted the fix/fast-pricing branch May 23, 2026 06:02
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants