From 4c8dc0954c7fdd43f7df952f1816d0852c18c303 Mon Sep 17 00:00:00 2001 From: iomgaa Date: Thu, 30 Jul 2026 12:14:48 -0400 Subject: [PATCH] =?UTF-8?q?docs:=20usage=5Fsource=20=E4=B8=89=E6=80=81?= =?UTF-8?q?=E4=B8=8E=20EST=5FTOKENS=20=E9=99=8D=E4=B8=BA=E5=8F=AF=E9=80=89?= =?UTF-8?q?(v1.0.3)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 指南-遥测与成本: 新增三态表与 cost NULL 口径,缺口查询必须带 cache_hit 限定 - 解释-治理行为: 有效预扣量的派生规则;点明限流保守与计费诚实是两回事 - 参考-配置键: EST_TOKENS 由必填降为可选调优覆盖 - 参考-公共API: usage_source 三态、SourceConfig.effective_est_tokens() - 指南-Embedding: 缺 usage 时记 unavailable 而非估算值 - Home: 版本号 v1.0.3(安装命令用 1.0.* 无需改) --- Home.md | 2 +- 参考-公共API.md | 4 ++-- 参考-配置键.md | 4 ++-- 指南-Embedding.md | 2 +- 指南-遥测与成本.md | 23 ++++++++++++++++++++++- 解释-治理行为.md | 4 +++- 6 files changed, 31 insertions(+), 8 deletions(-) diff --git a/Home.md b/Home.md index 6816975..76a6c29 100644 --- a/Home.md +++ b/Home.md @@ -2,7 +2,7 @@ 实验室统一的大语言模型调度与中转库:LLM / VLM / OCR / Embedding 共用同一套生产级治理栈(多源多账号、限流、错误分类重试、熔断、响应缓存、流式看门狗、遥测与成本)。治理单位是**一次模型调用**;任务编排与业务解析留在业务侧。 -当前版本 **v1.0.2**,已通过 GovDoc-SaaS 与 CHSAnalyzer 两个真实项目的全量迁移验收。 +当前版本 **v1.0.3**,已通过 GovDoc-SaaS 与 CHSAnalyzer 两个真实项目的全量迁移验收。 ## 文档地图(按你此刻要干什么选入口) diff --git a/参考-公共API.md b/参考-公共API.md index 3d61262..35b1538 100644 --- a/参考-公共API.md +++ b/参考-公共API.md @@ -23,7 +23,7 @@ | cache_hit | bool | 是否缓存命中 | | call_id | str | 遥测主键 | | cost | float\|None | 按价格表折算(缺表为 None) | -| usage_source | str | measured / estimated | +| usage_source | str | measured / estimated / unavailable(v1.0.3 起三态,口径见 [[指南-遥测与成本]]) | | structured_data | Any\|None | `structured=` 时的校验结果 | ## EmbeddingClient @@ -53,7 +53,7 @@ | 导出 | 用途 | |---|---| | `GatewaySettings` / `EmbeddingSettings` / `OcrSettings` | `from_env` 的解析产物;高级场景可自行构造后走 `from_settings` | -| `SourceConfig` | 单源完整配置(构造期校验不变式) | +| `SourceConfig` | 单源完整配置(构造期校验不变式)。方法 `effective_est_tokens() -> int`:TPM 入场预扣量,显式 `est_tokens > 0` 优先,否则按 `max(1, tpm // 60)` 派生,`tpm=0` 时为 0(v1.0.3 新增) | | `ProviderProfile` / `DEFAULT_PROFILES` | provider 方言注册表(thinking 注入方式、思考流字段等);自定义 provider 经 `registry=` 传入 | | `PricingTable` / `ModelPrice` | 价格表(成本折算) | diff --git a/参考-配置键.md b/参考-配置键.md index a7c6230..9282a1b 100644 --- a/参考-配置键.md +++ b/参考-配置键.md @@ -8,8 +8,8 @@ |---|---|---| | BASE_URL / API_KEY / MODEL | ✔ | 无鉴权服务 API_KEY 填占位 `none` | | TIMEOUT_S | ✔(或平铺 `LLM_TIMEOUT` 兜底) | 单次调用墙钟上限;须 ≤ `PGW_LEASE_TTL_S` | -| MAX_CONCURRENCY / RPM / TPM | | 0/缺省=不启用;TPM>0 时 EST_TOKENS 必填 | -| EST_TOKENS | TPM 启用时 ✔ | TPM 预扣依据,按实际结算退款 | +| MAX_CONCURRENCY / RPM / TPM | | 0/缺省=不启用;照供应商配额页填即可,无需搭配 EST_TOKENS | +| EST_TOKENS | | **可选调优覆盖**(v1.0.3 起由必填降为可选)。TPM 入场预扣量,按实际用量结算退款;不填时库按 `max(1, TPM // 60)` 派生——即"一次调用约占一秒钟的配额份额",任何配额规模都收敛到约 60 个在途 | | TTFT_TIMEOUT_S / INTER_TOKEN_TIMEOUT_S | | 流式看门狗,成对配;0 < inter < ttft < timeout | | ENABLE_THINKING | | 三态: 缺省不注入 / true 注入开 / false 注入关 | | MISSING_DONE | | SSE 缺 `[DONE]`: `retry`(默认)/ `salvage`(打捞已收内容) | diff --git a/指南-Embedding.md b/指南-Embedding.md index 3a1f12f..4df843a 100644 --- a/指南-Embedding.md +++ b/指南-Embedding.md @@ -27,5 +27,5 @@ await embed.aclose() ``` - 超过 `BATCH_SIZE` 的输入自动分批发送、结果按序合并;每批独立走治理(某批瞬时失败只重试该批); -- 上游缺 usage 时按估算标记 `usage_source="estimated"`,不静默填 0; +- 上游缺 usage 时记 `usage_source="unavailable"` 且 cost 为 NULL,不静默填 0 也不编估算值(v1.0.3 起;分批场景下任一批不可得则整批响应记 `unavailable`,详见 [[指南-遥测与成本]]); - 需要 ndarray 的业务侧自己 `np.asarray(resp.vectors, dtype=np.float32)`——库不依赖 numpy。 diff --git a/指南-遥测与成本.md b/指南-遥测与成本.md index e32e423..7635145 100644 --- a/指南-遥测与成本.md +++ b/指南-遥测与成本.md @@ -19,12 +19,22 @@ PGW_TELEMETRY_SQLITE_PATH=logs/telemetry.db # sqlite 时必填 | 链路 | call_id(主键,幂等)/ parent_call_id / session_id | | 身份 | model / provider / source_name | | 内容 | messages / response / thinking(多模态 part 摘要落库,不存原图) | -| 用量 | prompt_tokens / completion_tokens / usage_source(measured/estimated) | +| 用量 | prompt_tokens / completion_tokens / usage_source(三态,见下) | | 时延 | latency_ms / ttft_ms / max_inter_token_ms | | 结果 | cache_hit / error(异常类名前缀,如 `TransientError: ...`)/ cost | `session_id`/`parent_call_id` 由调用方传入(`client.chat(..., session_id=...)`),用于把一次业务任务下的多次调用串成链。 +## usage_source 三态(v1.0.3 起) + +| 值 | 含义 | 什么时候出现 | cost | +|---|---|---|---| +| `measured` | 用量帧完整可信 | 正常路径;OCR 成功行(0 token 是事实,不是未知) | 按 token 换算 | +| `estimated` | 有实测数字但可信度降级 | 打捞路径:收到 usage 帧但流被截断(`MISSING_DONE=salvage`) | 按 token 换算 | +| `unavailable` | 用量信息不可得 | 上游没返回 usage 帧、失败的尝试、终态失败 | **NULL** | + +v1.0.3 前只有前两态,且上游缺 usage 时库会拿配置的 `EST_TOKENS` 当实测值记账——那是个"最坏情形上界",按它计费只会系统性虚高。现在这类行如实记 `0/0` + `unavailable` + `cost=NULL`。历史数据里的 `estimated` 行语义不变、照常可读。 + ## 成本 ```bash @@ -37,6 +47,17 @@ PGW_PRICING_PATH=config/prices.json 配了价格表后每行遥测带 `cost`(元);缓存命中 token=0 天然零成本。缺价格表时 cost 恒 None,不报错。 +**cost 的口径**:产生了真实调用、但用量不可得的行 `cost` 为 NULL——库不会编一个数字,免得"免费"与"未知"在数据上混为一谈。缓存命中行**不在此列**:它没产生新调用,`0.0` 是事实,所以即便 `usage_source='unavailable'`,cost 仍是 `0.0`。 + +因此 `SUM(cost)` 天然跳过不可得的行,而账目缺口要这样量化: + +```sql +SELECT COUNT(*) FROM llm_calls +WHERE usage_source = 'unavailable' AND cache_hit = false; +``` + +`AND cache_hit = false` 不可省 —— 漏掉它会把本无缺口的缓存命中行灌进来,度量偏高。若你的成本汇总此前依赖"cost 非空"这个隐含假设,升级到 v1.0.3 时请复核。 + ## 降级方向 遥测后端不可用 → warning 后静默丢弃该行,**绝不影响业务调用**。共享后端注意:不要在真实批跑期间并发跑库的集成测试(时序隔离,详见主仓库 CLAUDE.md)。 diff --git a/解释-治理行为.md b/解释-治理行为.md index 7f6cd71..0d1f9f5 100644 --- a/解释-治理行为.md +++ b/解释-治理行为.md @@ -24,4 +24,6 @@ ## 限流的结算语义 -TPM 预扣入场(按 EST_TOKENS),完成后按实际 usage **落回 acquire 时刻的窗口**多退少补;瞬时失败按估算保守结算,4xx/源死全额退款。拒绝零副作用:六道闸任一不过,已过的闸不留计数。并发槽带租约,进程死亡后自动回收。 +TPM 按**有效预扣量**入场——显式配了 `EST_TOKENS` 就用它,没配则按 `max(1, TPM // 60)` 派生(v1.0.3 起;此前 TPM>0 时 `EST_TOKENS` 必填)。完成后按实际 usage **落回 acquire 时刻的窗口**多退少补;瞬时失败按预扣量保守结算,4xx/源死/取消全额退款。拒绝零副作用:六道闸任一不过,已过的闸不留计数。并发槽带租约,进程死亡后自动回收。 + +上游没返回 usage 帧时,结算仍按预扣量走(差额为 0,押金留存)——**这与遥测口径是两回事**:限流侧宁可保守占额,遥测侧则如实记 `usage_source='unavailable'` 且 cost 为 NULL,不拿预扣量冒充实测用量([[指南-遥测与成本]])。同一个数字曾同时充当这两个角色,而"保守"在限流语境是安全的、在计费语境只会让账单虚高,故 v1.0.3 拆开二者。