# 路线 6:模型资源与费用 代码依据:2026-09-30 当前工作区。学习场景:多个商家的咨询和记忆提取同时等待模型,平台需要分配并发额度,并保存每次调用的 token 与人民币费用。 图中的后端路径相对 `src/zhifu/`。连续箭头表示当前进程内的调用或标明条件的执行步骤;间断箭头标注框架回调、网络请求或持久记录之间的联系。框架负责调用 `BudgetCallback`,阅读时注意调用来源。返回[路线目录](README.md)。 ## 图 6A:工作进程申请并发额度 ```mermaid flowchart TD A1["6A-1 modules/agent_runtime/worker.py
main → execute_one
开始一次任务处理"] A2["6A-2 modules/agent_runtime/business_wait.py
reconcile
检查业务等待事件"] A3["6A-3 modules/agent_runtime/worker.py
claim
开始领取事务"] A4["6A-4 modules/agent_runtime/capacity.py
reservations
锁定并发策略并读取商家预留"] A5["6A-5 modules/agent_runtime/worker.py
claim 内部
选择租户、重新统计并发、锁定运行"] A6["6A-6 modules/agent_runtime/capacity.py
acquire
检查全局、交互、后台与租户预留"] A7["Redis state
CAPACITY_SCRIPT 原子更新有效额度"] A8["6A-8 modules/agent_runtime/worker.py
claim 内部
RUNNING、lease_token、lease_until"] A9["6A-9 modules/agent_runtime/runtime.py
build_graph
由 execute_one 调用 graph.ainvoke"] A10["6A-10 modules/agent_runtime/capacity.py
release
execute_one 的 finally 释放额度"] A11["本次没有取得任务
execute_one 返回 False"] A1 --> A2 A1 -->|reconcile 返回后| A3 A3 --> A4 A4 -->|返回预留配置,继续 claim| A5 A5 -->|存在有效候选| A6 A5 -->|没有候选或租户已满| A11 A6 -.->|Redis eval| A7 A7 -.->|取得额度| A8 A7 -.->|额度不足| A11 A8 -->|领取事务提交后返回运行与租约| A9 A9 -->|成功、失败或取消后的 finally| A10 A11 -->|finally| A10 ``` 源码导航: - 6A-1、6A-3、6A-5、6A-8:[worker.main](G:/leon/miaoa/workspace/shuh-ai/zhifu-platform/src/zhifu/modules/agent_runtime/worker.py:210)、[execute_one](G:/leon/miaoa/workspace/shuh-ai/zhifu-platform/src/zhifu/modules/agent_runtime/worker.py:137)、[claim](G:/leon/miaoa/workspace/shuh-ai/zhifu-platform/src/zhifu/modules/agent_runtime/worker.py:28)。关注 `TenantDispatch.selected_at`、`TenantQuota` 与 `AgentRun.lease_token`。 - 6A-2:[business_wait.reconcile](G:/leon/miaoa/workspace/shuh-ai/zhifu-platform/src/zhifu/modules/agent_runtime/business_wait.py),具体业务恢复见[路线 2](02-agent-runtime.md)。 - 6A-4、6A-6、6A-10:[reservations](G:/leon/miaoa/workspace/shuh-ai/zhifu-platform/src/zhifu/modules/agent_runtime/capacity.py:62)、[acquire](G:/leon/miaoa/workspace/shuh-ai/zhifu-platform/src/zhifu/modules/agent_runtime/capacity.py:75)、[release](G:/leon/miaoa/workspace/shuh-ai/zhifu-platform/src/zhifu/modules/agent_runtime/capacity.py:110)。沿 `state.eval` 阅读同文件的 `CAPACITY_SCRIPT` 与 `RELEASE_SCRIPT`。 - 6A-9:[build_graph](G:/leon/miaoa/workspace/shuh-ai/zhifu-platform/src/zhifu/modules/agent_runtime/runtime.py:244)。额度取得之后才进入图执行。 租户调度优先照顾尚未用完预留额度的商家,随后参考上次领取时间;租户内部按照创建时间与运行标识选择任务。`claim` 取得租户锁后重新检查并发数量。Redis 将全局、交互、后台和租户预留放在一次 Lua 调用内判断。 记忆任务从 [memory.worker.execute_one](G:/leon/miaoa/workspace/shuh-ai/zhifu-platform/src/zhifu/modules/memory/worker.py:205) 进入,同样调用 `reservations` 和 `acquire`,使用 `background` 分类;只有成功取得额度才进入 `execute_claimed`。取得的额度在 `finally` 释放。Redis 额度还有有效期限,工作进程中断后的记录由后续申请清理。 ## 图 6B:一次模型调用的预占与结算 ```mermaid flowchart TD B1["6B-1 modules/agent_runtime/runtime.py
build_graph 内部 model
保存 ModelAttempt,调用 ainvoke"] B2["6B-2 modules/agent_runtime/budget_callback.py
BudgetCallback.on_chat_model_start
估算输入与最大输出"] B3["6B-3 modules/agent_runtime/budget.py
reserve 内部依次调用 lock_tenant、account
保存 token 预占"] B4["6B-4 modules/billing/ledger.py
reserve_money
按已批准价格保存金额预占"] B5["供应商模型服务
实际请求与 usage"] B6["6B-6 modules/agent_runtime/budget_callback.py
BudgetCallback.on_llm_end
读取 usage_metadata"] B7["6B-7 modules/agent_runtime/budget_callback.py
BudgetCallback.on_llm_error
记录未知用量"] B8["6B-8 modules/agent_runtime/budget.py
change_entry
结算 token 或保留 UNKNOWN"] B9["6B-9 modules/billing/ledger.py
settle_money → charge
结算金额或保留 UNKNOWN"] B10["6B-10 modules/agent_runtime/runtime.py
model 返回处理
独立保存 ModelAttempt.usage,继续业务检查"] B11["6B-11 modules/agent_runtime/budget.py
mark_pending_unknown
取消或恢复时检查未结算尝试"] B12["预占事务终止
预算错误向上传播"] B1 -.->|LangChain 请求前回调| B2 B2 --> B3 --> B4 B4 -.->|预占事务成功后,SDK 发送 HTTP| B5 B3 -->|token 不足| B12 B4 -->|金额不足或缺少已批准价格| B12 B5 -.->|LangChain 成功回调| B6 B5 -.->|LangChain 错误回调| B7 B6 --> B8 B7 --> B8 B8 --> B9 B9 -->|成功回调结束,ainvoke 返回| B10 B1 -->|外层执行被取消或发生异常| B11 B11 --> B8 ``` 源码导航: - 6B-1、6B-10:[build_graph.model](G:/leon/miaoa/workspace/shuh-ai/zhifu-platform/src/zhifu/modules/agent_runtime/runtime.py:284)。寻找 `attempt_id`、`callbacks`、`max_retries=0` 与返回后的独立事务。 - 6B-2、6B-6、6B-7:[on_chat_model_start](G:/leon/miaoa/workspace/shuh-ai/zhifu-platform/src/zhifu/modules/agent_runtime/budget_callback.py:49)、[on_llm_end](G:/leon/miaoa/workspace/shuh-ai/zhifu-platform/src/zhifu/modules/agent_runtime/budget_callback.py:74)、[on_llm_error](G:/leon/miaoa/workspace/shuh-ai/zhifu-platform/src/zhifu/modules/agent_runtime/budget_callback.py:82)。`raise_error` 与 `run_inline` 让预算检查在发送之前完成。 - 6B-3、6B-8、6B-11:[reserve](G:/leon/miaoa/workspace/shuh-ai/zhifu-platform/src/zhifu/modules/agent_runtime/budget.py:70)、[change_entry](G:/leon/miaoa/workspace/shuh-ai/zhifu-platform/src/zhifu/modules/agent_runtime/budget.py:106)、[mark_pending_unknown](G:/leon/miaoa/workspace/shuh-ai/zhifu-platform/src/zhifu/modules/agent_runtime/budget.py:168)。 - 6B-4、6B-9:[reserve_money](G:/leon/miaoa/workspace/shuh-ai/zhifu-platform/src/zhifu/modules/billing/ledger.py:46)、[settle_money](G:/leon/miaoa/workspace/shuh-ai/zhifu-platform/src/zhifu/modules/billing/ledger.py:77)、[charge](G:/leon/miaoa/workspace/shuh-ai/zhifu-platform/src/zhifu/modules/billing/ledger.py:32)。 `reserve` 使用独立事务,在租户锁保护下同时处理 token 与金额。存在 `MoneyPolicy` 时才启用人民币预算;已启用金额预算却没有对应 `BillingRoute` 会拒绝调用。价格保存在每次 `MoneyEntry.price` 中,结算读取该次调用的价格快照。 输入预估使用序列化字节数与协议余量,输出使用配置上限。实际结算使用供应商 `usage_metadata`,缓存 token 单独参与金额计算。金额使用整数微元,每次请求汇总后向上取整。 没有 usage 时保留预占并登记 `UNKNOWN`。`change_entry` 对重复的相同 usage 返回原状态;不同 usage 产生冲突。人工释放后收到有效迟到 usage,仍然记录已经发生的消耗。模型用量的事务先完成,之后的业务权限复验仍可能拒绝答复提交。 ## 图 6C:账单差异与费用审批 ```mermaid flowchart TD C1["6C-1 modules/billing/api.py
import_statement
授权并检查导入幂等标识"] C2["6C-2 modules/billing/statements.py
compare
按费用记录比较金额、token 和模型"] C3["BillingStatement
保存账单,返回比较结果"] C4["6C-4 modules/billing/api.py
submit
员工提交 RECONCILE 申请"] C5["6C-5 modules/billing/statements.py
validate_evidence
核对账单明细与申请"] C6["BillingChange
PENDING,保存申请人与原目标版本"] C7["6C-7 modules/billing/api.py
decide
另一员工审批并复验权限、版本及期限"] C8["6C-8 modules/billing/api.py
apply_change → validate_evidence
再次核对证据"] C9["6C-9 modules/billing/ledger.py
reconcile
更新费用、账户与审计"] C10["BillingChange
APPROVED 或 REJECTED"] C1 --> C2 -->|比较通过后继续 import_statement| C3 C3 -.->|员工查看差异,另一次 HTTP 提交| C4 C4 --> C5 -->|返回后保存申请| C6 C6 -.->|审批员工发起独立 HTTP 请求| C7 C7 -->|批准| C8 C8 -->|证据校验成功后| C9 C9 -->|返回 decide,同一事务保存审批结果| C10 C7 -->|拒绝| C10 ``` 源码导航: - 6C-1、6C-4、6C-7、6C-8:[import_statement](G:/leon/miaoa/workspace/shuh-ai/zhifu-platform/src/zhifu/modules/billing/api.py:371)、[submit](G:/leon/miaoa/workspace/shuh-ai/zhifu-platform/src/zhifu/modules/billing/api.py:74)、[decide](G:/leon/miaoa/workspace/shuh-ai/zhifu-platform/src/zhifu/modules/billing/api.py:191)、[apply_change](G:/leon/miaoa/workspace/shuh-ai/zhifu-platform/src/zhifu/modules/billing/api.py:136)。每个入口都经由 [authorize](G:/leon/miaoa/workspace/shuh-ai/zhifu-platform/src/zhifu/modules/billing/api.py:46) 检查对应权限。 - 6C-2、6C-5:[compare](G:/leon/miaoa/workspace/shuh-ai/zhifu-platform/src/zhifu/modules/billing/statements.py:28)、[validate_evidence](G:/leon/miaoa/workspace/shuh-ai/zhifu-platform/src/zhifu/modules/billing/statements.py:87)。 - 6C-9:[ledger.reconcile](G:/leon/miaoa/workspace/shuh-ai/zhifu-platform/src/zhifu/modules/billing/ledger.py:113)。预算和价格申请也通过 `submit`、`decide`,分别进入 `apply_change` 的 `BUDGET` 与 `PRICE` 分支。 账单比较产生 `MATCHED`、`DIFFERENT`、`UNKNOWN`、`UNLINKED` 或 `ROUTE_MISMATCH`,比较操作只返回差异。费用变更由独立审批请求触发,申请人不能审批自己的申请。批准操作、费用调整和审计记录共用事务。 ## 关键数据与状态 - [AgentRun、ModelAttempt、TokenAccount、TokenEntry](G:/leon/miaoa/workspace/shuh-ai/zhifu-platform/src/zhifu/modules/agent_runtime/models.py):运行可以包含多次模型尝试。`ModelAttempt.id` 传给回调作为 `reference_id`;LangChain 回调的 `run_id.bytes` 用作 `TokenEntry.id` 和 `MoneyEntry.id`。 - [MoneyPolicy、BillingRoute、MoneyAccount、MoneyEntry](G:/leon/miaoa/workspace/shuh-ai/zhifu-platform/src/zhifu/modules/billing/models.py):分别记录金额预算、已批准价格、当日账户和单次调用金额。 - 并发额度在 Redis 记录,同时数据库保存任务租约;token 与金额账户分别记录 `reserved` 和 `consumed`。并发额度释放与费用结算具有各自的记录和条件。 ## 阅读检查 1. 在 `claim` 中找到租户选择、重新统计并发和 Redis 申请的位置,解释不同锁与额度检查分别保护什么。 2. 从 `ModelAttempt.id` 跟踪到 `TokenEntry.reference_id`,说明一次运行、多次尝试和回调标识之间的关系。 3. 沿 `UNKNOWN`、重复 usage、迟到 usage 和人工审批四种情况,指出费用记录怎样变化,以及每次变化所属的事务。 ## 测试阅读入口 以下文件用于追踪预期行为;本文编写时只阅读用例,没有执行其中的业务请求。 - [test_tenant_dispatch.py](G:/leon/miaoa/workspace/shuh-ai/zhifu-platform/tests/test_tenant_dispatch.py)、[test_capacity_quotas.py](G:/leon/miaoa/workspace/shuh-ai/zhifu-platform/tests/test_capacity_quotas.py):租户调度与预留额度。 - [test_token_budget.py](G:/leon/miaoa/workspace/shuh-ai/zhifu-platform/tests/test_token_budget.py)、[test_interrupted_model_budget.py](G:/leon/miaoa/workspace/shuh-ai/zhifu-platform/tests/test_interrupted_model_budget.py):预算、未知用量与中断处理。 - [test_money_budget.py](G:/leon/miaoa/workspace/shuh-ai/zhifu-platform/tests/test_money_budget.py)、[test_billing_statements.py](G:/leon/miaoa/workspace/shuh-ai/zhifu-platform/tests/test_billing_statements.py):人民币费用、账单与双人审批。