Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Skip to content

feat: 在使用日志中记录上游实际模型#810

Open
alfadb wants to merge 3 commits intoWei-Shaw:mainfrom
alfadb:feat/upstream-model-tracking
Open

feat: 在使用日志中记录上游实际模型#810
alfadb wants to merge 3 commits intoWei-Shaw:mainfrom
alfadb:feat/upstream-model-tracking

Conversation

@alfadb
Copy link
Contributor

@alfadb alfadb commented Mar 6, 2026

概要

  • usage_logs 表新增 upstream_model 可空字段(迁移 068),记录模型映射后上游实际使用的模型,与用户请求的模型区分开
  • 在所有网关服务(Anthropic、OpenAI HTTP、OpenAI WebSocket v2)的 ForwardResult 中传递上游模型信息
  • 在管理后台使用日志表中展示上游模型列,方便管理员查看路由情况

动机

当配置了模型映射(如用户请求 gpt-4o 但实际映射到 gpt-4o-mini)时,管理员无法看到上游实际使用了哪个模型。本 PR 通过在使用日志中同时记录请求模型和实际模型来提供这一可见性。

变更内容

后端

  • SchemaUsageLog Ent schema 新增 upstream_model 可选字符串字段 + 迁移文件 068_add_upstream_model.sql
  • Service 层ForwardResult 新增 UpstreamModel 字段;所有网关服务(Antigravity、OpenAI、OpenAI WS v2)均已填充
  • RepositoryCreateUsageLog 在有值时写入 upstream_model
  • DTOUsageLogResponse 包含 upstream_model 供 API 消费者使用

前端

  • 管理后台使用日志表新增"上游模型"列
  • 添加中英文 i18n 翻译

测试计划

  • 已有单元测试已更新以适配新字段
  • 手动验证:创建模型映射,发起请求,确认 upstream_model 正确记录
  • 验证迁移在全新数据库上能正常执行

🤖 Generated with Claude Code

Copilot AI review requested due to automatic review settings March 6, 2026 07:45
@alfadb alfadb changed the title feat: track upstream model in usage logs feat: 在使用日志中记录上游实际模型 Mar 6, 2026
Copy link
Contributor

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

This PR adds visibility into model mapping by tracking the actual upstream model (upstream_model) used after model mapping, separately from the user-requested model. When a user requests gpt-4o but it's mapped to gpt-4o-mini, both models are now logged.

Changes:

  • New nullable upstream_model column in usage_logs table (migration 068) plus full Ent schema, mutation, predicates, and runtime support
  • ForwardResult and OpenAIForwardResult now carry UpstreamModel; all gateway services (Anthropic, Antigravity, OpenAI HTTP, OpenAI WebSocket v2) populate it only when mapping was applied
  • Admin UI and Excel export show upstream model; backend DTO and repository wiring updated accordingly

Reviewed changes

Copilot reviewed 26 out of 26 changed files in this pull request and generated 1 comment.

Show a summary per file
File Description
backend/migrations/068_add_upstream_model.sql Adds upstream_model VARCHAR(100) column
backend/ent/schema/usage_log.go Adds Optional/Nillable upstream_model field (MaxLen 100)
backend/ent/usagelog.go Generated entity with UpstreamModel *string field + scan/assign logic
backend/ent/usagelog/usagelog.go Field constant, validator, Columns list, and ordering function
backend/ent/usagelog/where.go Generated predicates for upstream_model field
backend/ent/usagelog_create.go Generated create/upsert builder methods for upstream_model
backend/ent/usagelog_update.go Generated update builder + validation for upstream_model
backend/ent/mutation.go Mutation struct field and all mutation methods; fixes GroupMutation capacity
backend/ent/migrate/schema.go Column definition and updated foreign key/index column references
backend/ent/runtime/runtime.go Updated field index offsets for all validators/defaults
backend/internal/service/usage_log.go Adds UpstreamModel *string to UsageLog service struct
backend/internal/service/gateway_service.go ForwardResult.UpstreamModel field; sets it in Forward/forwardAnthropicAPIKeyPassthrough; uses it for billing
backend/internal/service/antigravity_gateway_service.go Sets UpstreamModel in Forward and ForwardGemini when mapping occurs
backend/internal/service/openai_gateway_service.go OpenAIForwardResult.UpstreamModel; sets it in Forward; uses it for billing in RecordUsage
backend/internal/service/openai_ws_forwarder.go Sets UpstreamModel in forwardOpenAIWSV2 and ProxyResponsesWebSocketFromClient
backend/internal/repository/usage_log_repo.go Adds upstream_model to SELECT/INSERT and scan logic
backend/internal/handler/dto/types.go Adds UpstreamModel *string to AdminUsageLog DTO
backend/internal/handler/dto/mappers.go Maps l.UpstreamModel to AdminUsageLog.UpstreamModel
backend/internal/service/gateway_anthropic_apikey_passthrough_test.go Updated tests to pass both originalModel and reqModel to forwardAnthropicAPIKeyPassthrough
backend/internal/service/antigravity_gateway_service_test.go Updated assertions: Model = original, UpstreamModel = mapped
backend/internal/repository/usage_log_repo_request_type_test.go Added sqlmock.AnyArg() and sql.NullString{} for upstream_model in mock tests
frontend/src/types/index.ts Adds upstream_model?: string | null to AdminUsageLog interface
frontend/src/components/admin/usage/UsageTable.vue Shows upstream_model inline below the model name in the #cell-model slot
frontend/src/views/admin/UsageView.vue Adds upstream_model as a separate column in the Excel export
frontend/src/i18n/locales/en.ts Adds upstreamModel: 'Upstream Model' i18n key
frontend/src/i18n/locales/zh.ts Adds upstreamModel: '上游模型' i18n key

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

Comment on lines 6563 to +6566
} else if result.MediaType == "prompt" {
cost = &CostBreakdown{}
} else if result.ImageCount > 0 {
// 图片生成计费
// 图片生成计费:使用上游模型名(映射后的模型名)查找价格
Copy link

Copilot AI Mar 6, 2026

Choose a reason for hiding this comment

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

In RecordUsage (gateway_service.go), the billing for Sora video models (CalculateSoraVideoCost) uses result.Model (the user-requested model), while the billing for images and tokens was updated in this PR to use result.UpstreamModel when available. The Sora video billing path (which lives just above the changed else if result.ImageCount > 0 branch) remains unchanged, so if a Sora video model is subject to model mapping, billing would use the wrong pre-mapped model name. The result.Model argument to CalculateSoraVideoCost should also prefer result.UpstreamModel when set.

Copilot uses AI. Check for mistakes.
@alfadb alfadb force-pushed the feat/upstream-model-tracking branch from f4116f7 to 9ab2f99 Compare March 6, 2026 23:31
alfadb and others added 3 commits March 7, 2026 19:35
Add upstream_model field to usage logs to distinguish between the
user-requested model and the actual model used after mapping. This
gives admins visibility into model routing behavior.

- Add upstream_model nullable column via migration 068
- Regenerate Ent ORM code for the new field
- Update ForwardResult to carry UpstreamModel separately from Model
- Update test assertions for the new field layout

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
WSv2 single-turn (forwardOpenAIWSV2) and multi-turn
(ProxyResponsesWebSocketFromClient/sendAndRelay) paths were returning
OpenAIForwardResult without UpstreamModel, causing upstream_model to
always be NULL in usage_logs for WebSocket-based requests even when
model mapping occurred.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@alfadb alfadb force-pushed the feat/upstream-model-tracking branch from 9ab2f99 to 23df753 Compare March 7, 2026 11:43
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.

2 participants