Skip to content

fix(billing): make Responses image generation prices configurable - #6471

Open
chenyoubei wants to merge 1 commit into
QuantumNous:mainfrom
chenyoubei:fix/responses-image-generation-pricing
Open

fix(billing): make Responses image generation prices configurable#6471
chenyoubei wants to merge 1 commit into
QuantumNous:mainfrom
chenyoubei:fix/responses-image-generation-pricing

Conversation

@chenyoubei

@chenyoubei chenyoubei commented Jul 25, 2026

Copy link
Copy Markdown

⚠️ 提交说明 / PR Notice

Important

本 PR 由 chenyoubei 提交;过程中使用 AI 辅助,所有代码、测试和说明均已由提交者人工复核。

📝 变更描述 / Description

基于最新 main 已引入的统一工具附加费架构,补全 Responses API 图片生成工具按实际请求参数计价的能力。

  • 从原始 image_generation 工具声明中记录 qualitysize
  • 非流式和流式响应通过现有图片调用计数器收集上游返回的实际参数;响应缺失或返回 auto 时保留请求参数。
  • 同一响应生成多张不同档位图片时,按每个去重后的 quality / size 组合分别累计和计价,不会把全部图片套用最后一张的价格。
  • 新增 GetImageGenerationToolPriceForModel(modelName, quality, size)
    • 优先查找 image_generation/<quality>/<size>
    • 同样支持现有的最长模型前缀匹配;
    • 未配置该档位、参数未知或为 auto 时回退到 image_generation
  • 保持最新 main 的默认行为不变:未配置具体档位时仍使用 image_generation = 150(单位为 $/1K calls)。
  • 显式配置为 0 的具体档位会终止查找并禁用该档位收费,不会错误回退到默认价格。

例如,若某个上游把 gpt-5.5* 的托管图片工具路由到 GPT Image 2,可在现有“工具价格”设置中配置:

{
  "image_generation:gpt-5.5*": 211,
  "image_generation/high/1024x1024:gpt-5.5*": 211,
  "image_generation/high/1024x1536:gpt-5.5*": 165,
  "image_generation/high/1536x1024:gpt-5.5*": 165
}

代码不猜测 OpenAI 内部最终使用的图片模型;管理员可以按 Responses 模型前缀、质量和尺寸显式配置并审计计费规则。

🚀 变更类型 / Type of change

  • 🐛 Bug 修复 (Bug fix)
  • ✨ 新功能 (New feature)
  • ⚡ 性能优化 / 重构 (Refactor)
  • 📝 文档更新 (Documentation)

🔗 关联任务 / Related Issue

✅ 提交前检查项 / Checklist

  • 人工确认: 已人工整理并核对描述,没有直接粘贴未经处理的输出。
  • 非重复提交: 已搜索现有 Issues 与 PRs;gpt-image-2的output token计费有严重bug #4474feat(billing): support dynamic media model pricing #6054 的协议路径及计费对象不同。
  • Bug fix 说明: 已提交并关联对应 Issue。
  • 变更理解: 已核对 Responses 请求参数、非流式/流式图片调用计数、结构化工具附加费、模型前缀索引及显式零值语义。
  • 范围聚焦: 仅修改 Responses 图片工具参数元数据、价格解析及对应测试。
  • 本地验证: 已运行完整 Go 测试、前端类型检查、相关格式/lint 检查和生产构建。
  • 安全合规: 不包含任何凭据或用户数据,默认价格和未配置档位的行为保持与最新 main 一致。

📸 运行证明 / Proof of Work

go test ./...                                                        PASS
bun run typecheck                                                    PASS
oxfmt --check src/features/system-settings/models/tool-price-settings.tsx PASS
oxlint -c .oxlintrc.json src/features/system-settings/models/tool-price-settings.tsx PASS
bun run build                                                        PASS

新增回归测试覆盖:

  • 请求工具声明中的 quality / size 提取。
  • 流式重复事件只计一次,同时允许最终响应补全实际图片参数。
  • 同一响应包含多个不同图片档位时分别累计和结算。
  • 响应缺失或为 auto 时保留请求参数。
  • 图片档位按 Responses 模型最长前缀覆盖。
  • 未配置档位回退到现有 image_generation 默认价格。
  • 具体档位显式设为 0 时不回退、不收费。

Summary by CodeRabbit

  • New Features

    • Added support for tracking image-generation quality and size options.
    • Image-generation usage now records separate counts for different quality and size combinations.
    • Added model- and tier-specific pricing for image-generation requests, with fallback pricing when no tier is configured.
  • Bug Fixes

    • Improved quota and surcharge calculations using the most accurate available image-generation options.
    • Preserved request options when response data does not provide usable values.
    • Added safeguards for invalid or unsupported pricing values.

@coderabbitai

coderabbitai Bot commented Jul 25, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review

Walkthrough

Image-generation quality and size now flow from Responses requests and outputs into built-in tool usage records. Quota calculation selects model-specific configurable image-generation prices, including per-tier overrides and fallback pricing.

Changes

Image-generation pricing flow

Layer / File(s) Summary
Capture image-generation request metadata
relay/common/relay_info.go, relay/common/relay_info_test.go
Responses image-generation tools record quality and size in built-in tool metadata, with request parsing coverage.
Resolve response image options
relay/common/tool_usage.go, relay/common/tool_usage_test.go
Observed outputs are deduplicated into normalized tiers; response options override request values when usable, while omitted options preserve request metadata.
Apply configurable model-aware pricing
setting/operation_setting/tools.go, setting/operation_setting/tools_price_test.go, service/text_quota.go, service/text_quota_test.go
Image-generation surcharge pricing uses model, quality, and size overrides, preserves explicit zero prices, and falls back to configured defaults.

Estimated code review effort: 3 (Moderate) | ~20 minutes

Sequence Diagram(s)

sequenceDiagram
  participant ResponsesRequest
  participant GenRelayInfoResponses
  participant ImageGenerationCallCounter
  participant TextQuota
  participant OperationSettings
  ResponsesRequest->>GenRelayInfoResponses: provide quality and size
  GenRelayInfoResponses->>ImageGenerationCallCounter: retain request options
  ImageGenerationCallCounter->>ImageGenerationCallCounter: observe and aggregate response tiers
  ImageGenerationCallCounter->>TextQuota: commit billable tool usage
  TextQuota->>OperationSettings: resolve model, quality, and size price
Loading

Suggested reviewers: calcium-ion

Poem

A rabbit hops through image lore,
With sizes tucked behind the door.
Quality blooms, response calls chime,
Model prices hop in time.
Fallback coins rest in their nest—
The billing burrow’s now well-dressed.

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 33.33% 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 is concise and accurately summarizes the main billing-related change to configurable Responses image generation pricing.
Linked Issues check ✅ Passed The changes implement configurable Responses image generation pricing, including model-prefix, quality/size lookup, and request fallback as required by #6470.
Out of Scope Changes check ✅ Passed The added tests and refactors stay focused on image-generation billing and pricing lookup, with no clear unrelated scope creep.
✨ 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.

@chenyoubei
chenyoubei force-pushed the fix/responses-image-generation-pricing branch from 922b306 to e93cefb Compare July 28, 2026 02:19

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 1

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
relay/common/tool_usage_test.go (1)

53-67: 📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

Guard the reserved-names assertions with require, not a conditional skip.

info.ResponsesUsageInfo is always initialized unconditionally inside CountBillableToolCall (see tool_usage.go lines 28-32) before any reserved-name filtering happens, so the if info.ResponsesUsageInfo != nil guard here is always true — but if that ever regressed, the assertions would be silently skipped rather than failing the test.

As per coding guidelines, **/*_test.go tests should "prefer deterministic table tests with explicit inputs and exact outputs" — replace the conditional with a direct require.NotNil so a regression fails loudly.

✅ Proposed fix
 	info.CountBillableToolCall(dto.BuildInCallFunctionCall, dto.BuildInToolWebSearchPreview)
 	info.CountBillableToolCall(dto.BuildInCallFunctionCall, dto.BuildInToolFileSearch)
 	info.CountBillableToolCall(dto.BuildInCallFunctionCall, dto.BuildInToolGoogleSearch)
 	info.CountBillableToolCall(dto.BuildInCallFunctionCall, dto.BuildInToolImageGeneration)

-	if info.ResponsesUsageInfo != nil {
-		assert.NotContains(t, info.ResponsesUsageInfo.BuiltInTools, dto.BuildInToolWebSearchPreview)
-		assert.NotContains(t, info.ResponsesUsageInfo.BuiltInTools, dto.BuildInToolFileSearch)
-		assert.NotContains(t, info.ResponsesUsageInfo.BuiltInTools, dto.BuildInToolGoogleSearch)
-		assert.NotContains(t, info.ResponsesUsageInfo.BuiltInTools, dto.BuildInToolImageGeneration)
-	}
+	require.NotNil(t, info.ResponsesUsageInfo)
+	assert.NotContains(t, info.ResponsesUsageInfo.BuiltInTools, dto.BuildInToolWebSearchPreview)
+	assert.NotContains(t, info.ResponsesUsageInfo.BuiltInTools, dto.BuildInToolFileSearch)
+	assert.NotContains(t, info.ResponsesUsageInfo.BuiltInTools, dto.BuildInToolGoogleSearch)
+	assert.NotContains(t, info.ResponsesUsageInfo.BuiltInTools, dto.BuildInToolImageGeneration)
🤖 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 `@relay/common/tool_usage_test.go` around lines 53 - 67, Replace the
conditional guard around the reserved-tool assertions in
TestCountBillableToolCallFunctionCallSkipsReservedNames with require.NotNil on
info.ResponsesUsageInfo, then keep the existing assert.NotContains checks
unconditional so initialization regressions fail loudly.

Source: Coding guidelines

🤖 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 `@relay/common/tool_usage.go`:
- Around line 79-198: Update ImageGenerationCallCounter to track deduplicated
completed outputs by each observed non-auto quality/size combination instead of
retaining only the last values. Update Commit to transfer every tier’s count and
quality/size metadata into the billing representation consumed by
non-image-generation surcharge pricing, while preserving request-level capping
and existing deduplication. Ensure auto or missing dimensions follow the
established default tier behavior.

---

Outside diff comments:
In `@relay/common/tool_usage_test.go`:
- Around line 53-67: Replace the conditional guard around the reserved-tool
assertions in TestCountBillableToolCallFunctionCallSkipsReservedNames with
require.NotNil on info.ResponsesUsageInfo, then keep the existing
assert.NotContains checks unconditional so initialization regressions fail
loudly.
🪄 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: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 4d185b60-ad80-4d4c-b043-cf2b8cd06bb1

📥 Commits

Reviewing files that changed from the base of the PR and between 922b306 and e93cefb.

📒 Files selected for processing (4)
  • relay/common/relay_info.go
  • relay/common/relay_info_test.go
  • relay/common/tool_usage.go
  • relay/common/tool_usage_test.go
🚧 Files skipped from review as they are similar to previous changes (2)
  • relay/common/relay_info.go
  • relay/common/relay_info_test.go

Comment thread relay/common/tool_usage.go
@chenyoubei
chenyoubei force-pushed the fix/responses-image-generation-pricing branch 3 times, most recently from be6bbc7 to 1741325 Compare July 28, 2026 02:40

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 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 `@relay/common/relay_info_test.go`:
- Line 51: Update the test request setup in the relevant test to use
httptest.NewRequestWithContext instead of httptest.NewRequest, add the context
import, and pass context.Background() explicitly while preserving the existing
POST method, URL, and nil body.
🪄 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: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 7b848d30-e073-4ce5-8825-baa506bfd87b

📥 Commits

Reviewing files that changed from the base of the PR and between be6bbc7 and 1741325.

📒 Files selected for processing (8)
  • relay/common/relay_info.go
  • relay/common/relay_info_test.go
  • relay/common/tool_usage.go
  • relay/common/tool_usage_test.go
  • service/text_quota.go
  • service/text_quota_test.go
  • setting/operation_setting/tools.go
  • setting/operation_setting/tools_price_test.go
🚧 Files skipped from review as they are similar to previous changes (6)
  • service/text_quota_test.go
  • relay/common/relay_info.go
  • setting/operation_setting/tools.go
  • setting/operation_setting/tools_price_test.go
  • service/text_quota.go
  • relay/common/tool_usage.go

Comment thread relay/common/relay_info_test.go Outdated
@chenyoubei
chenyoubei force-pushed the fix/responses-image-generation-pricing branch from 1741325 to bc0ab3d Compare July 28, 2026 02:49
@chenyoubei

Copy link
Copy Markdown
Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Jul 28, 2026

Copy link
Copy Markdown
Contributor
✅ Action performed

Review finished.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@chenyoubei
chenyoubei force-pushed the fix/responses-image-generation-pricing branch from bc0ab3d to 51a2f4b Compare August 22, 2026 14:33
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.

bug: Responses 图片生成工具固定使用 GPT Image 1 价格

1 participant