跳至正文

模型调用账本与核对 ​

本页阅读位置

完成第一轮对话后,按当前业务需求深入。Spring 常规声明优先使用 RegistrationManifest 与注解;本页的底层 register / publish 或直连方法供协议细化与兼容集成参考。

查询和界面入口 ​

在管理页面「运行记录→详情→模型调用账本」查看固定模型、绑定、尝试、价目版本和用量。无工具执行的任务也能显示模型账本;分页每次 10 条。管理凭据可审计读取本应用任务;普通业务用户仅查询自己的任务,并继续遵守会话权限失效和业务历史权限。

接口用途
GET /v1/apps/{app}/runs/{runId}/model-invocationsitems 与 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配置策略或上一次失败代码
statusRUNNING、RESPONDED、FAILED、SKIPPED、UNKNOWN;RESPONDED 不保证后续业务或输出验证成功
sendStateNOT_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 表示只有部分或没有账单证据。不同币种分开,平台不自动换算、推断折扣或认证供应商账单。

人工核对 ​

  1. 先向供应商查询原 invocationId/请求标识的用量或账单,保留可核验依据。
  2. 等待任务终结,在详情点击「核对供应商用量」,填写完整输入/输出/总 Token、原因和依据。
  3. 实际账单币种与金额可选;金额必须是非负十进制字符串,不接受科学计数、正负符号或超过 12 位小数。
  4. 登记后查看有效计量、配置金额和供应商差额。核对不会重新生成回复、重放工具或改变任务终态。
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
结论独立记录每次模型尝试,依据供应商原始证据核对未知计量
证据故障切换、流式中断保留用量、子调用、重复读取、权限、归档与人工核对行为测试
适用版本:0.1 发布线 · 最近核对:2026-10-09 · SparkTide 产品文档

汇聚智能,驱动涌现。