Skip to content

feat: 支持按模型配置 token 价格,聚合 API 模型同步时自动创建零价格规则#279

Open
panzeyu2013 wants to merge 1 commit into
qxcnm:mainfrom
panzeyu2013:feature/model-price-rules-config
Open

feat: 支持按模型配置 token 价格,聚合 API 模型同步时自动创建零价格规则#279
panzeyu2013 wants to merge 1 commit into
qxcnm:mainfrom
panzeyu2013:feature/model-price-rules-config

Conversation

@panzeyu2013
Copy link
Copy Markdown
Contributor

变更摘要

  • 问题:聚合 API(如 DeepSeek、Mistral)的模型同步后缺少 model_price_rules 记录,导致定价引擎匹配失败,estimated_cost_usd 始终为 null(前端显示 price_status: "missing"),钱包不扣费,成本统计无法正常工作。

  • 根因auto_associate_source_modelscrates/service/src/apikey/apikey_models.rs:821)在同步聚合 API 模型时只创建了 platform model 目录条目和 model_source_mapping 路由映射,没有创建价格规则。定价引擎 estimate_cost_usd_for_log 先查 DB rules → 未命中 → fallback 硬编码 PRICE_SEEDS → 也未命中 → 返回 None → 0.0

  • 方案:同步时自动为聚合 API 模型创建价格规则(价格均为 0),并支持用户在模型编辑弹窗中手动设置价格。用户规则 priority=20000,确定性 ID=user-{slug},确保覆盖所有自动创建和官方 seed 规则。


改动范围

  • Frontend
  • Desktop / Tauri
  • Service
  • Gateway / Protocol Adapter
  • Docs / Governance
  • Workflow / Release

主要文件

Rust 后端(4 个文件)

  • crates/core/src/rpc/types.rs

    • 新增 ModelPriceRuleEntry
    • 新增 ModelPriceRuleListResult
    • 新增 ModelPriceRuleUpsertInput
  • crates/service/src/quota/read.rs

    • 新增 list_model_price_rules
    • 新增 read_model_price_rule
    • 新增 upsert_model_price_rule
    • 新增 price_rule_entry 辅助函数
  • crates/service/src/rpc_dispatch/quota.rs

    • 新增 quota/modelPriceRules/list
    • 新增 quota/modelPriceRule/read
    • 新增 quota/modelPriceRule/upsert
    • 三个 RPC 路由
  • crates/service/src/apikey/apikey_models.rs

    • 新增 ensure_model_price_rules_for_aggregate_api
    • 在聚合 API 模型同步时自动创建零价格规则
    • 通过 existing_patterns HashSet 先查后插
    • 已有任意规则(含用户编辑、官方 seed、其他聚合 API 同步的)则跳过,确保不覆盖
    • 修复了原有 for source_model in source_models 的 borrow-after-move 编译错误

前端(5 个文件)

  • apps/src/lib/api/account-client.ts

    • 新增 ModelPriceRuleEntry
    • 新增 ModelPriceRuleUpsertPayload
    • 新增 listModelPriceRules
    • 新增 readModelPriceRule
    • 新增 upsertModelPriceRule
  • apps/src/lib/api/transport-web-commands.ts

    • 新增 service_model_price_rules_list
    • 新增 service_model_price_rule_read
    • 新增 service_model_price_rule_upsert
    • 三个 web 命令映射
  • apps/src/components/modals/model-catalog-modal.tsx

    • 在“保留本地覆写”开关和“高级 JSON”之间新增 3 个价格输入框
      • 输入价格
      • 缓存输入价格
      • 输出价格
    • 单位:USD / 1M tokens
    • 保存模型时通过 onSavePriceRule 回调同步写入规则
  • apps/src/hooks/useManagedModels.ts

    • 新增 saveModelPriceRule hook 方法
  • apps/src/app/models/page.tsx

    • 解构并传递 onSavePriceRule

桌面端 Tauri(2 个文件)

  • apps/src-tauri/src/commands/apikey.rs

    • 新增 service_model_price_rules_list
    • 新增 service_model_price_rule_read
    • 新增 service_model_price_rule_upsert
    • 三个 #[tauri::command]
  • apps/src-tauri/src/commands/registry.rs

    • invoke_handler! 宏中注册上述三个命令

验证

  • pnpm -C apps run test
  • pnpm -C apps run build
  • pnpm -C apps run test:ui
  • cargo test --workspace
  • 其他本地验证已说明

已执行的实际验证:

Rust 编译检查

cargo check --workspace

结果:0 errors, 0 warnings (0.82s)

Rust 全部测试

cargo test --workspace

结果:1122 tests passed, 0 failed, 0 ignored

前端构建

pnpm -C apps run build

结果:12 static pages, 0 errors

桌面端构建(含 Tauri)

pnpm -C apps run build:desktop

结果:12 static pages, Tauri commands registered, 0 errors


风险与影响面

直接影响

  • 定价引擎:

    • 无改动(model_pricing.rs 不变)
    • 已有 DB rules 优先 + seeds fallback 逻辑自动匹配新增规则
  • 请求日志:

    • 无改动(request_log.rsaggregate_api.rsproxy.rs 等均不变)
  • OpenAI account 同步:

    • 无影响(仅 source_kind == "aggregate_api" 触发)
  • 官方模型定价:

    • 无影响
    • 用户规则 priority=20000
    • 自动创建 priority=-10
    • 官方 seed priority≈9999
    • 排序关系:20000 > 9999 > -10
    • 用户规则优先,无用户规则时 seed 仍生效

边界注意

  • 修复前:

    • 聚合 API 模型 cost=0
    • 钱包不扣费
    • 用户零感知
  • 修复后:

    • 价格默认为 0
    • cost 仍为 0
    • 钱包仍不扣费(base_cost_usd <= 0.0 跳过)
    • 用户必须手动设价后才会产生实际扣费
  • 重同步保护:

    • existing_patterns 包含所有已启用规则的 model_pattern
    • 已有规则一律 skip
    • 不会覆盖用户手动设置的价格
  • 编辑已有模型:

    • 当前版本打开编辑弹窗时价格字段为空(已知限制)
    • 后续迭代可增加价格回填
    • 保存时只发送有值的字段

备注

  • 自动创建的 rule 标识:

    • source: "aggregate_api_sync"
    • priority=-10
  • 官方 seed:

    • source: "official_seed"
  • 用户规则:

    • source: "custom"
    • priority=20000
  • 分层关系清晰

  • 用户 upsert 使用 ID:

    • user-{model_pattern}
  • 特性:

    • 确定性
    • 可重入
    • 不创建重复规则

…egate API models

- Auto-create model_price_rules (price=0) when syncing aggregate API models
- Only insert on first sync, never overwrite existing user-set prices
- Add RPC endpoints: quota/modelPriceRules/list, read, upsert
- Add price input fields (input/cached/output per 1M tokens) to model edit modal
- Register Tauri commands for desktop support
- User-created rules use priority=20000,ID=user-{slug} to override official seeds
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.

1 participant