跳到主要内容

第十九节 — 演化与版本管理

这一节回答:FinBayes 各类资产(接口契约 / 数据 schema / Prompt / Provider / 工具)如何演化?如何保证升级时不打破现有用户的状态与体验?

五类需要版本化的资产

资产类型演化频率版本化策略
接口契约中(每次外部 API 调整)semver(major.minor.patch)+ contract_version 字段
数据 schema(State Store)低(破坏性变更稀有)schema_version + migration 脚本
Prompt(System / 任务模板)高(持续迭代)见 ADR-009(待定)
Provider 池(LLM / 数据 Provider)配置文件版本 + Provider Adapter 内部适配
工具池(Capability Registry)tool_version + 工具退役流程

各类资产的演化策略不同 —— 接口契约要严格 semver、数据 schema 要带 migration、Prompt 要支持快速迭代但留可回溯能力、Provider 与工具池要支持热插拔。


接口契约的版本化

哪些是"接口契约"

接口契约位置
入口 HTTP / WebSocket APIOpenAPI schema
MCP Server 暴露的工具MCP tool schema
Channel Adapter 接收的事件各 Channel 的 webhook schema
内部子系统间(CHAP-09 各接口)Python 函数签名 + Pydantic 数据对象
Provider Adapter 内部统一 OpenAI-compatible schema

Semver 语义

版本变更含义
major破坏性变更:删除字段 / 改字段语义 / 改方法签名 / 改错误码语义
minor向后兼容增加:新增 optional 字段 / 新增方法 / 新增错误码
patch修 bug、不动接口形态

字段级演化规则

关键约束

  • 不向已发布的接口悄悄改字段语义(即使字段名 / 类型不变)
  • 删字段前必须先 deprecated 一个 minor 版本,给用户 / 实施 Agent 升级窗口
  • 每次 major 升级附升级指南(自动转换工具 + 手动迁移说明)

Contract Version 在协议消息中

每条 API 消息含 contract_version 字段:

行为触发
同 major 不同 minor服务端兼容处理(缺失字段用默认值)
不同 major服务端拒绝,返回 INVALID_CONTRACT_VERSION + 当前服务端支持的版本范围
缺失 contract_version服务端按"最低支持版本"处理或拒绝

数据 Schema 的版本化(State Store)

Schema Migration 流程

关键约束

  • migration 脚本单向(只有 up,没有自动 down —— 降级靠从 bak 恢复,避免双向 migration 的复杂性)
  • migration 必须幂等(重复运行不损坏数据)—— 实现机制:
    1. DDL 层幂等:所有 CREATE TABLE / CREATE INDEXIF NOT EXISTS;所有 ALTER TABLE ADD COLUMN 先查 PRAGMA table_info 跳过已存在列
    2. 运行时层幂等:migration runner 启动时读 schema_metadata.migration_history(JSON 数组),跳过已记录的 migration 文件名
    3. 事务层:每个 migration 脚本在单一事务内执行,失败 ROLLBACK + 不写入 history;成功 COMMIT + 追加到 history
  • migration 失败时全量回滚到 bak,不留中间状态
  • 用户能看到 migration 进度(不是黑盒等待)

Schema 元表

State Store 含一张元表 schema_metadata

字段含义
schema_version当前 DB schema 版本
finbayes_version上次写入此 DB 的 FinBayes 程序版本
migrated_at上次 migration 时间戳
migration_history历次 migration 记录(from / to / timestamp / 备份位置)

Prompt 版本化(ADR-009 决策位置)

Prompt 既是"代码"(程序行为的关键决定因素)又是"数据"(频繁迭代 + 与提示词工程并行进化)。

两个候选策略

策略优点缺点
A. Prompt as Code:Prompt 进 Git,与代码同 release 周期版本可追溯 / Review gate 覆盖 / CI 跑得过迭代慢 / Prompt 工程师等不及 release / 大文件 diff 噪音
B. Prompt as Data:Prompt 存独立资源(YAML / DB),运行时加载迭代快 / Prompt 工程师独立工作难追溯 / Review 难 / 版本错位风险

初步倾向(待 ADR-009 确认):混合

  • 关键 Prompt(System Prompt / 任务路由模板 / 输出契约 schema)走策略 A(进代码仓 + Review gate)
  • 实验性 Prompt(个性化模板 / A/B 候选 prompt)走策略 B(YAML + 版本字段 + 审计追踪)
  • 切换在每条 Prompt 自描述的 delivery_mode: code | data

Prompt 演化的可观测要求(无论哪种策略)

每次 Prompt 变更必须可追溯:

字段含义
prompt_id全局唯一标识
prompt_versionsemver
activated_at启用时间
author作者 / Git commit 引用
eval_score上线前评估分数(详见 CHAP-21 评估闭环)
rollback_target如需回滚指向的上一版本

prompt_id 命名约定

prompt_id 采用三段式:<subsystem>.<purpose>.<variant>

含义取值示例
subsystem所属子系统orchestration / cognition / evidence / clarify
purpose用途类型system / task_template / output_schema / judge
variant变体标识main / compact / verbose / experimental_a

示例:

  • cognition.system.main — 综合层主 System Prompt
  • orchestration.task_template.synthesis — Task Orchestration 用的综合任务模板
  • clarify.system.main — clarify 工具 System Prompt
  • cognition.judge.counter_evidence_v1 — 评估 judge prompt(反方证据维度,详见 CHAP-21)

命名约定避免:

  • 同名跨子系统冲突(subsystem 前缀强制)
  • 实验 prompt 与生产 prompt 混淆(variant 后缀显式 experimental_*
  • A/B 测试时 prompt_id 混淆(variant 用 _a / _b / 而非数字)

详细 ADR-009 待写。


Provider 池演化

新增 Provider

约束

  • 新增 Provider 不动 runtime 业务代码(仅在 Provider Adapter Pool 层)
  • 新增 Provider 不影响现有 contract_version
  • 用户既有的 Provider 偏好顺序保留 / 升级时仅追加可用 Provider 不强制重排

Provider 退役

步骤内容
1. 标 deprecated用户配置中显示警告:"Provider X 将于版本 Y 移除"
2. 引导迁移提供"自动迁移到等效 Provider"建议(如 Provider X → Y)
3. 一个 major 版本后移除仍配置该 Provider 的用户启动时明示 + 引导重配

Provider API 变化(Provider 端)

LLM Provider(如 OpenAI)调整 API 时:

  • Provider Adapter 内部适配(patch / minor 版本)
  • runtime 业务代码不变
  • 用户感知:通常无感(除非 Provider 端废弃旧接口强制迁移)

工具池演化

新增工具

工具通过 Capability Registry 注册(详见 CHAP-09)。新增工具流程:

步骤内容
1. 工具实现实现 schema + 调用逻辑
2. 标 category严格枚举(read_only / analysis / synthesis / clarify / 等),无 execution 选项
3. Review gate人工审查工具用途 + schema 校验(自动 grep 执行类参数名)
4. 注册到 Registryruntime 启动时通过 Registry 装载
5. Self-consistency 测试LLM Function Calling 能否正确选择该工具(避免新工具拉低意图识别准确度)

工具退役

步骤内容
1. 标 deprecatedLLM 工具池 schema 中加 deprecated: true + 替代工具指向
2. 兼容期现有 task 仍可调用,但 LLM 优先选替代工具
3. 移除一个 minor 版本后移除(任何引用旧工具的状态对象 / Judgment 仍可读,只是不能再调用)

工具 schema 变更

新增 optional 参数:minor;改 required 参数 / 改返回 schema:major。


Concept 退役流程

战略层已禁入概念不允许进入主分支(CHAP-02 + CHAP-17)。但未来若某战略概念被明确退役(如"任务类型清单"扩展),工程层需要支持。

退役流程

步骤内容
1. 战略层 ADR在 governance 层写战略级 ADR 明示退役 + 替代
2. 加入 verify-kb 禁词表自动 grep 拦截
3. 状态对象兼容已有的引用旧概念的状态对象不破坏(只读 + 在 UI 中标"历史概念")
4. 文档归档旧概念相关文档移到 _archive/,frontmatter 标 legacy
5. 用户感知给一个 release 的过渡期 + 明示提醒

升级流程的工程承接

详见 CHAP-14 升级流程。这里强调演化角度:

升级路径接口契约数据 schemaPromptProvider工具
patch(bug 修复)不变不变可能变不变不变
minor(兼容增强)兼容新增兼容新增频繁变可能新增可能新增 / deprecated
major(破坏性变更)可破坏 + 升级指南migration 必备可能重写可能新增 / 退役可能新增 / 退役

约束:每次 release 的 changelog 必须按上述五类资产清晰罗列变更。


演化中的不变量

无论怎么演化,下列不变量永远不变

不变量演化中的保护
凭证不变量(不收不存不训练)任何接口 / schema / Prompt / 工具变更都不能引入凭证字段或凭证类参数
不直接下单 / 不持账户凭证工具池禁止注册执行类工具(即使新增 category)
不替用户决策综合层输出契约必须含反方 / 风险 / 失效条件(不能因"简化"删除)
用户数据主权任何数据 schema 变更都不能让用户失去查看 / 修改 / 删除权
本地优先任何架构演化(如未来加云端)都不能让本地优先用户失能

这些是战略级硬约束,演化策略必须服从战略层(详见 CHAP-02 上位继承与不变量)。


版本管理的可观测

每次资产变更都进入审计 trail / 元数据表:

资产追溯位置
接口契约OpenAPI / Pydantic schema 在 Git 历史 + contract_version 在消息中
数据 schemaschema_metadata 表 + Git 历史
PromptPrompt 自描述字段 + 审计 trail "prompt_version_changed" 事件
Providerproviders.yaml 在 Git 历史 + 用户配置文件版本
工具Capability Registry 的工具元数据 + 审计 trail "tool_registered/deprecated" 事件

与其他章节的关系

  • 战略级不变量演化中的保护 → CHAP-02 上位继承与不变量
  • 升级流程的部署形态承接 → CHAP-14 部署形态
  • Schema migration 的存储承接 → CHAP-15 数据存储划分
  • 接口契约消息体 contract_version → CHAP-16 通信协议
  • Review gate 的工程承接 → CHAP-17 边界与安全
  • 变更的审计可见性 → CHAP-18 可观测性
  • 评估如何驱动 Prompt 演化 → CHAP-21 评估闭环
  • ADR-009 Prompt 是代码还是数据 → 待写