2.7 KiB
2.7 KiB
type, node_id, title, date
| type | node_id | title | date |
|---|---|---|---|
| design | design:response-observability-fields | 响应可观测字段扩展(Issue #3) | 2026-07-31 |
响应可观测字段扩展(Issue #3)
全文见 2026-07-31-response-observability-fields-design.md。来源: Gitea Issue #3(下游 dissect 的调用审计需求)。
选定方案
| 决策 | 选定 | 关键理由 |
|---|---|---|
| A 采集路径 | TransportResult 追加 cached_prompt_tokens / model_reported 强类型字段,解析留在 openai_compat.py |
OpenAI 报文格式知识不出 transports/,middleware 只做搬运(P7) |
| B 缓存命中语义 | 原样回放;度量口径必须带 cache_hit = false |
与 _rehydrate 既有口径一致——它只覆写时序字段,model/prompt_tokens 全回放 |
| C 缓存单价 | ModelPrice 加可选 cached_input_per_1m,cost() 加可选参 |
旧价格表与 embedding.py:419 三参调用零改动;未配置该档时不猜折扣率,退化为全额计价 |
| D 遥测扩列 | 端口 18 → 20 字段;DDL 加列 + 初始化期幂等补列 | CREATE TABLE IF NOT EXISTS 不会给旧库补列,INSERT 会逐行 warning 丢弃——遥测全失却无硬失败提示 |
被否决的备选
| 备选 | 否决原因 |
|---|---|
A1 往 raw 里塞约定键 |
dict[str, Any] 沦为隐式契约,且 middleware 要懂 OpenAI 嵌套结构 |
| A3 middleware 内解析 raw | 报文格式知识进 middleware,新增非 OpenAI 兼容 transport 时会分叉,违反分层 |
| B2 命中时置 None / B3 混合 | 与同层 prompt_tokens 的回放行为不一致,下游要记两套规则 |
C2 cost() 直接收 LLMResponse |
pricing.py 会反向依赖 types.py,且纯函数难单测 |
| D2 只改 DDL、文档写「删表重建」 | 已建表的开发机/下游只会看到降级 warning,排查成本高 |
| D3 引入 alembic 迁移框架 | 新增依赖违反「依赖极简」铁律,规模严重不匹配 |
独立审查修正(2026-07-31)
Codex CLI 安装损坏(vendor 二进制缺失),改由全新上下文的 Claude subagent 审。三条问题全部核实属实并已折回设计:
- PG 缺列时不是结构性短路,而是逐行 warning(
_failed仅在_ensure_ready置位)。 - SQLite 补列若塞进
__init__现有 try,异常会让_conn停在None→ recorder 永久 no-op。已定纪律: 独立 try、置于self._conn = conn之后、duplicate column 视为成功。 - 「端口无默认值 → 漏改即报错」不成立(无 mypy,8 个 fake 全是
**fields)。改为新增「emitter 实参键集合 ==_COLUMNS」契约测试兜底——否则KeyError会被_record的except Exception吞成 warning,静默丢遥测。