切换主题
模型调用账本与核对
本页阅读位置
完成第一轮对话后,按当前业务需求深入。Spring 常规声明优先使用 RegistrationManifest 与注解;本页的底层 register / publish 或直连方法供协议细化与兼容集成参考。
查询和界面入口
在管理页面「运行记录→详情→模型调用账本」查看固定模型、绑定、尝试、价目版本和用量。无工具执行的任务也能显示模型账本;分页每次 10 条。管理凭据可审计读取本应用任务;普通业务用户仅查询自己的任务,并继续遵守会话权限失效和业务历史权限。
| 接口 | 用途 |
|---|---|
| GET /v1/apps/{app}/runs/{runId}/model-invocations | items 与 summary;limit 默认 50,1–100;offset 默认 0,0–1000000;列表不携带核对历史数组 |
| GET /v1/apps/{app}/model-invocations/ | 单次明细及 reconciliationHistory,最多 100 次核对记录 |
| POST /v1/apps/{app}/model-invocations/{invocationId}/reconcile | 应用/平台管理员登记核对;If-Match 为当前调用 revision;任务须终结,调用须进入发送边界 |
所有接口需要 Bearer 凭据。事件重连/重放不增加调用或费用,归档删除事件后账本仍可查。旧任务 coverage=LEGACY,不补造历史调用;新任务 coverage=COMPLETE,表示启用账本,不表示全部用量已知。
读懂调用和汇总
| 字段 | 意义 |
|---|---|
| id / invocationId | 同一调用的唯一标识,贯穿出站幂等头;不同候选和子调用分别登记 |
| stepId / attempt | 本次逻辑生成步骤与该步骤候选序号;候选容量筛选也可能登记 SKIPPED |
| agentCallId / parentAgentCallId / depth / agentId | 根与子智能体调用关系,根 parent 为 null |
| binding / model / provider | 实际精确版本,model/provider 含作用域 scope |
| selectionReason | 配置策略或上一次失败代码 |
| status | RUNNING、RESPONDED、FAILED、SKIPPED、UNKNOWN;RESPONDED 不保证后续业务或输出验证成功 |
| sendState | NOT_SENT 没有进入发送边界;SENT 表示可能已被接收,不是供应商收到的证明 |
| outputStarted | 是否开始文字或工具片段输出;此后不允许故障切换 |
| inputHash | 发送内容摘要;不保存或返回原始提示词、用户内容或服务密钥 |
| pricing / pricingVersion / pricingHash | 固定价目、模型版本与价目摘要;没有配置时 pricing={} |
| usage / usageSource / cost | 原始计量回执与配置费用;缺失 token 为 null,原始数据不被人工核对覆盖 |
| effectiveUsage / effectiveUsageSource / effectiveCost | 当前核对后的计量;来源 NOT_SENT、UNKNOWN、PROVIDER 或 PROVIDER_RECONCILIATION |
| reconciliation / reconciliationHistory | 当前核对与历史,保存操作者、时间、原因及供应商依据 |
| costDifference | 可比币种时供应商账单减配置费用;缺少价目或币种不同返回 null |
| createdAt / sentAt / receiptAt / finishedAt | 毫秒时间;未达到该边界的字段可缺省 |
| revision | 用于核对并发检查的当前整数修订 |
summary 按唯一调用 ID 汇总。invocations、sent、notSent 是数量;unknownCostInvocations 仅计入发送边界后没有完整计价数据的调用。providerUsage 按字段累计,任何相关调用缺回执时该字段为 null;NOT_SENT 不计量、不冒充收费未知。
cost 仅在全部已发送调用都有必要计量与价目时返回配置费用;否则 null。knownConfiguredAmounts 单独列出已知部分,不能当成完整总费用。providerBilledAmounts 为登记的供应商金额;billedComplete=false 表示只有部分或没有账单证据。不同币种分开,平台不自动换算、推断折扣或认证供应商账单。
人工核对
- 先向供应商查询原 invocationId/请求标识的用量或账单,保留可核验依据。
- 等待任务终结,在详情点击「核对供应商用量」,填写完整输入/输出/总 Token、原因和依据。
- 实际账单币种与金额可选;金额必须是非负十进制字符串,不接受科学计数、正负符号或超过 12 位小数。
- 登记后查看有效计量、配置金额和供应商差额。核对不会重新生成回复、重放工具或改变任务终态。
http
POST /v1/apps/customer-service/model-invocations/model_example/reconcile
Authorization: Bearer <管理凭据>
If-Match: 7
Content-Type: application/json
{
"providerUsage":{"prompt_tokens":100,"completion_tokens":20,"total_tokens":120},
"billedCost":{"currency":"USD","amount":"0.00014"},
"providerRequestId":"supplier-receipt-example",
"reason":"按供应商原始回执核对",
"evidence":"invoice-example / receipt-example"
}用量为 0–1000000000 的整数,总量不得小于输入与输出之和。reason/evidence 必须非空,最多 1024/2048 字符;请求标识可选,1–256 字符。不要填写密钥或完整业务内容。412 表示记录已变更,应重新读取并核对;不能重用旧修订反复覆盖。NOT_SENT 禁止登记虚构供应商计量。费用未知时必须保留 null,不用零“消除”未知状态。
人工核对只更新独立账本和当前 Run 展示汇总,历史 usage.updated/model.completed 事件保持原始内容。重新读取账本获取最新核对结果。
Java 和 Kotlin SDK
java
var page = client.modelInvocations(runId, 50, 0).toCompletableFuture().join();
var item = client.modelInvocation(invocationId).toCompletableFuture().join();
var evidence = ModelUsageReconciliation.builder(100, 20, 120,
"按原始回执核对", "invoice-example")
.billedCost("USD", "0.00014")
.providerRequestId("supplier-receipt-example").build();
// revision 取最新明细,client 使用管理凭据。
client.reconcileModelInvocation(invocationId, evidence,
((Number) item.get("revision")).longValue()).toCompletableFuture().join();kotlin
val page = client.listModelInvocations(runId)
val item = client.getModelInvocation(invocationId)
val evidence = ModelUsageReconciliation.builder(100, 20, 120,
"按原始回执核对", "invoice-example").build()
client.recordModelReconciliation(invocationId, evidence,
(item["revision"] as Number).toLong())导入 dev.sparktide.sdk.ModelUsageReconciliation 与 dev.sparktide.sdk.kotlin 下的三个扩展。Java 接口返回 CompletionStage<Map<String,Object>>,Kotlin 返回挂起 Map。SDK 检查字段、分页和修订,不替代服务端授权;写请求不自动重试。
部署、迁移与回滚
升级前备份数据库,服务启动通过 Flyway 增量执行 V10。V10 只增加表和索引,旧任务不造历史账本。事件归档与账本生命周期分离,归档不删除财务证据。回滚服务保留 V10 表,不降级删除调用或核对记录;供应商已经接收的调用和费用无法通过回滚代码撤销。隔离 H2 测试不替代目标 PostgreSQL 升级和真实供应商结算验收。
前端只读查询
ts
const page = await client.modelInvocations(run.id, { limit: 20, offset: 0, signal });
const invocation = await client.modelInvocation(page.items[0].id, { signal });前端客户端保留未知值和十进制金额,分页与取消行为见前端 SDK。取消查询不取消任务,查询失败不重新创建 Run;浏览器不要存管理凭据,核对由管理页面或可信后台执行。
文档来源与验证记录
| 字段 | 内容 |
|---|---|
| 状态 | 已确认 |
| 日期 | 2026-09-30 |
| 来源 | ModelInvocations、V10、SDK 和账本专项测试 |
| 责任人 | 项目维护者 |
| 关联任务 | M07 |
| 结论 | 独立记录每次模型尝试,依据供应商原始证据核对未知计量 |
| 证据 | 故障切换、流式中断保留用量、子调用、重复读取、权限、归档与人工核对行为测试 |
