第十八节 — 可观测性
这一节回答:FinBayes 通过什么手段让"系统正在做什么 / 为什么这样做 / 是否健康"对用户与工程都可见?
两类可观测对象
| 对象 | 看什么 | 谁看 |
|---|---|---|
| 认知过程可观测 | 任务为什么走 LLM A 而不是 B / 为什么这次降级 / 这条 Judgment 怎么形成 / 反方为什么是这些 | 用户视角为主 |
| 系统运行可观测 | 延迟 / 错误率 / 成本 / 并发负载 / 缓存命中率 | 工程视角为主 |
FinBayes 的本地优先定位要求两类都做 —— 但侧重点不同:认知过程可观测直接服务用户信任与复盘,系统运行可观测支撑工程化排障。
审计 trail(认知过程可观测的主载体)
审计 trail 的存储位置详见 CHAP-15。这一节聚焦全景视图与用户可查阅维度。
记录的事件类型
| 事件类型 | 关键字段 |
|---|---|
| 任务执行 | task_id / type / 输入摘要 / 输出摘要 / Provider 调用链 / 成本 / 时长 / 关联 Session |
| Provider 调用 | provider_id / model / token 数(输入/输出)/ 成本 / 是否走 fallback / 失败原因 |
| 降级事件 | 触发层级(L1→L2 等)/ 触发原因 / 时间戳 / 关联 task |
| 状态变更 | object_type / object_id / before / after / 触发事件 / 时间戳 |
| 用户主动动作 | 确认候选 / 修改画像 / 删除 Session / 等 + 时间戳 |
| 边界拒收 | 时间戳 + 入口 + 识别类型(不含具体凭证内容) |
| 主动信号触发 | 关联 Judgment Record / 失效条件被触及的事件 / 通知投递路径 |
用户视角的可查阅维度
用户能问的问题与对应查询:
| 用户问题 | 对应查询 |
|---|---|
| "我刚才那次提问为什么这么慢?" | task_id → Provider 调用链 + 各步耗时 |
| "为什么这次走了本地模型?" | task_id → 降级事件链(L1 → L2 触发原因) |
| "这条 Judgment 是怎么形成的?" | judgment_id → 关联 task → 证据来源 → 综合层依据 |
| "为什么 FinBayes 拒收了我刚才贴的内容?" | session_id → 边界拒收事件(仅识别类型) |
| "我这周用了多少 Provider 成本?" | 时间范围 + user_id → Provider 调用聚合 |
| "FinBayes 怎么静默地改了我的画像?" | profile.history → 历次画像更新事件 + 触发任务 |
用户可见的不变量
- 审计 trail 不含凭证字符串(边界拒收事件只标"识别为凭证类,已拒收")
- 审计 trail 不含完整 LLM 输入输出(仅含摘要 + token 数 + 关键字段;完整内容仅 debug 模式留存 N 天)
- 审计 trail 是用户的资产(导出 / 删除 / 归档由用户决定)
任务 trace(贯穿子系统的因果链)
每个认知任务有一个唯一 task_id,贯穿所有子系统调用。
这张图表达什么:task_id 是横向贯穿所有子系统的相关 ID;每个子系统产生的事件都标 task_id(+ 子调用的 tool_call_id / llm_call_id),用户或工程可基于 task_id 重建完整因果链。
这张图特意不表达什么:trace 的存储格式(在 CHAP-15);分布式 trace(本地优先单机不需要)。
Trace ID 体系
| ID | 范围 | 用途 |
|---|---|---|
session_id | Session 生命周期 | 关联同一会话内的所有 task |
task_id | 单个 task | 一次认知请求的全链路 |
tool_call_id | 单次工具调用 | LLM Function Calling 的工具调用追踪 |
llm_call_id | 单次 LLM 调用 | 多次 LLM 调用(如综合层多采样)的区分 |
trace_id | 跨 session 的相关任务(主动信号触发新任务) | 主动信号链路追踪 |
指标体系
FinBayes 关注的指标分四类:
性能指标
| 指标 | 含义 | 用途 |
|---|---|---|
task_latency_first_screen | 首屏响应时间 | 用户体验核心 |
task_latency_complete | 任务完整完成时间 | 看流式输出全长 |
llm_call_latency | 单次 LLM 调用延迟 | 看 Provider 健康 |
tool_call_latency | 单次工具调用延迟 | 看外部数据 Provider 健康 |
concurrent_tasks | 当前并发任务数 | 看负载 |
成本指标
| 指标 | 含义 | 用途 |
|---|---|---|
provider_token_usage | 各 Provider token 用量 | 成本核算 + 用户预算可见 |
provider_cost_estimate | 各 Provider 估算成本 | 用户成本主权 |
cache_hit_rate | L3 缓存命中率 | 看降本效果 |
可靠性指标
| 指标 | 含义 | 用途 |
|---|---|---|
degradation_rate_by_layer | L1→L2 / L2→L3 / L3→L4 触发率 | 看降级链健康 |
provider_failure_rate | 各 Provider 失败率 | Provider 健康对比 |
boundary_reject_rate | 边界拒收率 | 看是否有异常输入模式 |
state_store_write_failure | State Store 写入失败次数 | 看 SQLite 健康 |
认知质量指标(间接)
| 指标 | 含义 | 用途 |
|---|---|---|
self_consistency_divergence | Self-consistency 多采样分歧度 | 高分歧 = 任务难 / 综合层不收敛 |
evidence_completeness | 综合层使用的证据数 / 应用证据数 | 看反方 / 风险覆盖完整度 |
clarify_rate | 触发 clarify 工具的比例 | 高 = 输入意图不清 / 用户体验需改进 |
user_action_on_candidate_rate | 候选状态被用户确认 vs 拒绝 vs 编辑的比例 | 看 candidate 阶段质量 |
约束:所有指标 per-user 维度独立计算(不跨用户聚合)。
用户视角的可观测 UI
CLI / TUI
| 命令 | 显示 |
|---|---|
finbayes status | 当前 Provider Readiness / Cache 状态 / State Store 健康 |
finbayes trace <task_id> | 单个 task 完整链路(Provider 调用 / 工具调用 / 降级事件 / 时长) |
finbayes audit list [--since=7d] | 时间范围内的审计事件 |
finbayes cost report [--since=30d] | 时间范围内的 Provider 成本汇总 |
finbayes session show <id> | Session 内所有 task 与状态变更概览 |
Web UI
- Session 详情页:每条 task 旁边显示"trace 入口",点击查看该 task 的 Provider 调用链 + 降级事件 + 关键时长
- Judgment Record 详情:显示"为什么形成这个判断"—— 关联 task 的证据来源 + 综合层依据 + Provider
- 全局健康 banner:Provider 池状态 / Cache 命中率 / 最近降级事件(如有)
工程视角的可观测
日志分级
| 级别 | 用途 | 是否默认开启 |
|---|---|---|
ERROR | 不可恢复的失败 | ✅ |
WARN | 降级 / 重试 / 边界识别 | ✅ |
INFO | 任务开始 / 完成 / 关键节点 | ✅ |
DEBUG | LLM 调用入参出参摘要 / 工具调用参数 | ❌(用户主动开) |
TRACE | LLM 完整 prompt / 完整响应 | ❌(用户主动开,明示日志会含完整内容) |
日志脱敏
不管什么级别,日志都不写入:
- LLM Provider API key / Channel token / 任何认证凭证
- 凭证类内容(边界拒收的具体字符串)
- 完整用户画像(仅摘要 / hash)
DEBUG / TRACE 级别开启时给用户明示警告("日志将包含完整 LLM 入参出参,请注意敏感数据")。
异常上报
第一阶段不引入云端异常上报服务(如 Sentry)—— 单机部署不应把异常发到第三方。
替代方案:
- runtime 在严重异常时本地保存 crash report(用户可选择上报)
- 用户主动
finbayes diagnostic export打包审计 trail + 配置 + crash report(敏感字段脱敏)供反馈
Provider 调用的精细观测
LLM Provider 调用是成本与延迟的主要来源,需要精细观测:
| 观测点 | 字段 |
|---|---|
| 调用前 | provider_id / model / 任务类型 / 是否走 fallback / 缓存是否命中 |
| 调用中 | latency_to_first_token(流式响应)/ 是否流式中断 |
| 调用后 | input_token_count / output_token_count / estimated_cost / 是否结构化输出校验通过 |
| 失败时 | 失败类型(鉴权 / 限流 / 超时 / 5xx / 解析失败)/ 是否触发降级 / 关联 fallback 调用 |
每次 Provider 调用进入审计 trail(含上述全部字段),可被用户查询 / 工程聚合。
降级原因的可观测
每次降级(详见 CHAP-13)都进入审计 trail 含:
- 降级层级(L1 / L1' / L2 / L3 / L4)
- 触发原因(具体错误码 + 错误消息脱敏)
- 时间戳
- 关联 task_id
用户视角的呈现:在受到降级影响的 task 输出末尾加 banner "本次因 [原因] 走 [层级] 模式,结果质量可能下降",并提供"点击查看完整降级链"。
测试可观测性
测试体系(详见 CHAP-20)依赖可观测性:
- 单元测试:mock Provider 调用,断言审计事件按预期写入
- 集成测试:跑端到端任务,校验 trace 完整性
- 评估闭环(详见 CHAP-21):基于审计 trail 的离线分析(如 "上周 self-consistency 分歧度趋势")
第一阶段不做的可观测能力
明示不做:
- 分布式 trace(OpenTelemetry 等)—— 单机不需要
- 云端日志聚合(Datadog / Loki)—— 本地优先违背
- A/B 测试框架 —— 第一阶段单用户场景不必要
- 实时 metric dashboard(如 Prometheus + Grafana)—— 用户视角 UI 已够
这些都不是不可演化(接口契约不变),只是第一阶段不抢答(详见 CHAP-19 演化与版本管理)。
与其他章节的关系
- 审计 trail 的存储位置与 schema → CHAP-15 数据存储划分
- 任务 trace 的进程内传递 → CHAP-09 Task Orchestration 子系统
- 降级事件的产生 → CHAP-13 故障与降级路径
- 边界事件的产生 → CHAP-17 边界与安全
- Provider 调用观测的具体字段 → CHAP-09 Provider Adapter 子系统
- 可观测性如何支撑测试 → CHAP-20 测试体系
- 可观测性如何支撑评估闭环 → CHAP-21 评估闭环