AI编程项目腐烂周期:建立可复现实验管理机制
1. 为什么你的 AI 编程项目正在悄悄腐烂1.1 一个让人后背发凉的普遍现象我见过太多这样的项目了。半年前跑得风生水起的 AI 应用现在打开代码仓库一看连作者自己都不敢动。模型调用散落在十几个文件里Prompt 硬编码在业务逻辑中间向量库的 schema 改了三次但没人记得哪次是最终版评估脚本跑出来的分数和线上表现完全是两回事。更可怕的是团队里没人能说清楚这个系统到底在什么情况下会出错。这不是个例。我接触过的 AI 编程项目从个人 side project 到几十人协作的产品线几乎都逃不过这个规律前三个月是蜜月期三到六个月开始出现裂缝六个月之后如果没有刻意维护项目就会进入一种“能跑但不敢碰”的僵尸状态。我管这个叫 AI 项目的腐烂周期。传统软件项目也会腐烂但 AI 项目的腐烂速度要快得多而且腐烂的方式更隐蔽。传统代码腐烂你至少能看到函数越来越长、依赖越来越乱、测试覆盖率越来越低。AI 项目的腐烂往往发生在“看不见”的地方数据分布悄悄漂移了Prompt 对某个边缘 case 的容忍度下降了模型版本更新后行为变了但你的代码一行没改测试全绿线上却在慢慢变差。1.2 腐烂的根源不是技术债是“实验债”大部分人会把这个问题归结为技术债。我觉得这个归因不够准确。技术债是“知道该怎么做但没时间做”而 AI 项目里更致命的是实验债——你做了大量实验试了各种模型、各种 Prompt、各种检索策略但实验过程没有被系统化地记录和沉淀。举个具体的例子。假设你在做一个基于大模型的文档问答系统。第一周你试了三种 chunk size发现 512 效果最好。第二周你换了 embedding 模型发现之前的最优 chunk size 变了但你没重新跑对比实验。第三周你加了一个 rerank 模块效果提升了但没人记得提升是因为 rerank 本身还是因为 rerank 恰好弥补了 chunk size 不合适带来的问题。到了第四周你想优化回答质量面对的是一个由几十个相互耦合的决策组成的黑箱你根本不知道动哪个参数会带来什么影响。实验债的可怕之处在于它不会让你的代码报错但会让你的项目失去可演进性。你没法做有意义的迭代因为每次改动都是在赌而不是在做工程。1.3 这件事到底是什么建立 AI 项目的“可复现实验层”说了这么多问题那“这件事”到底是什么我的答案是为你的 AI 编程项目建立一套可复现的实验管理机制。这不是某个具体的工具或框架而是一套贯穿项目始终的工作方式核心目标是让每一次实验都可追溯、可对比、可复现。具体来说它包含四个层面数据层训练数据、评估数据、Prompt 模板、检索语料全部版本化管理每次实验明确记录用了哪个版本。配置层模型参数、检索参数、后处理逻辑全部从代码中抽离成配置文件实验时记录完整配置快照。评估层建立稳定的评估集和评估指标每次实验自动跑评估结果入库支持横向对比。决策层基于评估结果做决策而不是凭感觉。每次决策记录“为什么选 A 不选 B”形成决策日志。这套机制听起来不复杂但真正落地需要克服很多工程细节。接下来我会逐层拆解把每个环节的实操要点和踩坑经验都讲清楚。2. 数据与配置的版本化管理实操2.1 为什么 Git 管不好 AI 项目的数据和配置很多人的第一反应是版本管理用 Git 不就行了代码用 Git 管数据用 DVC 或者 Git LFS 管配置直接写在代码里。我一开始也是这么想的直到被现实反复教育。Git 管代码没问题但 AI 项目里真正决定行为的东西往往不在代码里。你的 Prompt 模板可能是一个几百行的文本文件你的评估集可能是几千条 JSONL你的检索语料可能是几十万条向量。这些东西用 Git 管会带来两个问题一是仓库体积爆炸clone 一次要等半天二是 diff 不可读你没法从 Git diff 里看出“这次实验到底改了什么”。更关键的是AI 项目的实验频率远高于传统项目。你可能一天跑几十次实验每次实验的配置组合都不一样。如果用 Git 分支来管理实验很快就会出现几百个分支合并冲突处理到崩溃。我的做法是代码用 Git数据和配置用专门的实验管理工具两者通过实验 ID 关联。具体选什么工具后面会说先讲清楚原则。2.2 数据版本化不只是存一份快照数据版本化听起来简单实际做起来有很多细节。我见过最常见的错误做法是每次实验前把数据复制一份加上日期后缀。这样做的结果是磁盘里堆了几十个数据副本没人知道哪个对应哪次实验而且大部分数据其实是重复的。正确的做法是内容寻址存储。简单说就是根据数据内容的哈希值来存储相同内容只存一份不同版本通过哈希值区分。这样既能保证每次实验都能精确复现当时的数据又不会浪费存储空间。具体到实操层面你需要管理的数据类型包括数据类型版本化要点常见坑训练/微调数据记录原始数据来源、清洗脚本版本、最终哈希清洗脚本改了但没记录导致数据无法复现评估集评估集一旦确定就冻结新增 case 走新版本边评估边改评估集导致分数不可比Prompt 模板每个模板独立版本号变更记录原因模板改了一个词但没记录效果变化无法归因检索语料记录语料来源、更新时间、embedding 模型版本语料更新后没重新 embedding检索结果错乱向量索引索引与语料、embedding 模型绑定版本换了 embedding 模型但没重建索引检索质量暴跌我特别想强调评估集的冻结。很多人做 AI 项目时评估集是“活”的——发现模型在某个 case 上表现不好就把这个 case 加进评估集。这样做短期内看起来模型在进步但实际上你是在用不断变化的尺子量身高分数完全没有可比性。正确的做法是评估集分训练集和保留集训练集可以随时加 case 用于调试保留集一旦确定就冻结只在版本升级时整体替换。2.3 配置管理把“魔法数字”关进笼子AI 项目里到处都是“魔法数字”temperature 设 0.7top_k 设 5chunk size 设 512相似度阈值设 0.8。这些数字散落在代码各处改一个要全局搜索而且改完之后没人记得之前是多少。我的做法是所有可调参数必须出现在配置文件中代码里不允许出现硬编码的魔法数字。配置文件用 YAML 或 JSON 都行关键是要有层级结构并且每次实验时自动保存完整配置快照。一个典型的配置文件结构大概长这样experiment: name: rerank_v2_chunk768 description: 测试 rerank 模块在更大 chunk size 下的效果 base_config: configs/base_v3.yaml model: provider: openai_compatible name: gpt-4-turbo temperature: 0.3 max_tokens: 2048 retrieval: chunk_size: 768 chunk_overlap: 128 top_k: 10 rerank: enabled: true model: bge-reranker-v2 top_n: 5 evaluation: dataset: eval_sets/qa_v2_frozen.jsonl metrics: [faithfulness, answer_relevance, context_precision]这样做的好处是每次实验的完整配置都可以序列化保存配合实验 ID 存入数据库。半年后你想知道“当时那个效果最好的配置到底是什么”直接查实验记录就行不用去翻聊天记录或者回忆。注意配置文件里不要放密钥。密钥用环境变量管理配置文件里只放非敏感的配置项。我见过有人把 API key 写进配置文件然后提交到仓库后果不用我多说。2.4 实验追踪让每次实验都有迹可循配置和数据都版本化了接下来需要把它们和实验结果关联起来。这就是实验追踪工具要做的事。市面上有几种选择我简单对比一下工具类型代表方案适合场景注意事项轻量级自建SQLite 本地文件个人项目、小团队需要自己写记录逻辑但灵活可控专业实验平台MLflow、Weights Biases团队协作、需要可视化学习成本较高注意数据安全云厂商方案各云平台的实验管理服务已在特定云生态内注意锁定风险迁移成本高我个人的建议是个人项目从 SQLite 自建开始团队项目直接上专业平台。自建的好处是你完全掌控数据而且写记录逻辑的过程本身会逼你想清楚“到底要记录什么”。专业平台的好处是开箱即用可视化做得好团队协作方便。不管选哪种核心要记录的信息包括实验 ID、时间戳、配置快照、数据版本、评估结果、备注。备注字段特别重要一定要写清楚“这次实验想验证什么假设”否则一个月后你看到一堆实验记录根本不知道当时在试什么。3. 评估体系AI 项目最容易被忽视的基础设施3.1 没有稳定评估一切优化都是玄学我敢说评估体系是 AI 编程项目里投入产出比最高、但被最多人忽视的基础设施。大部分人做 AI 项目时评估方式是“打开几个 case 看看效果”或者“让产品经理试用一下”。这种方式在项目早期还能凑合一旦进入迭代阶段就完全不够用了。原因很简单人的判断是不稳定的。你今天心情好觉得模型回答得不错明天心情差同样的回答你就觉得不行。而且你不可能记住上周模型在某个 case 上的具体表现没法做纵向对比。更致命的是当你有几十个 case 要评估时人工评估的成本高到不可接受你只能抽样看几个抽样偏差会让你的判断完全失真。稳定评估体系的核心是自动化评估 人工校准。自动化评估负责覆盖大量 case给出可比的分数人工校准负责定期检查自动化评估是否偏离了真实质量。两者结合才能在保证效率的同时不失去判断力。3.2 评估集构建少即是多精胜于泛构建评估集是件苦活但值得花时间。我的经验是评估集的质量比数量重要得多100 条精心设计的 case 比 10000 条随机抽样的 case 有用。评估集的设计要覆盖几个维度典型场景用户最常问的问题类型占评估集的 40% 左右。边缘场景不常见但重要的 case比如多轮对话中的指代消解、模糊查询、包含否定条件的查询占 30%。对抗场景故意设计来挑战模型的 case比如包含错误前提的问题、需要拒绝回答的问题占 20%。回归场景之前版本出过问题的 case确保修复后不再复发占 10%。每条评估 case 需要包含输入用户问题 上下文、期望输出参考答案或评分标准、评估指标用哪些指标来评。期望输出不一定是唯一答案对于开放式问题可以给出评分 rubric让评估模型按 rubric 打分。实操心得评估集构建初期我建议用“真实用户日志 人工标注”的方式。从线上日志里采样真实问题人工写出期望答案。这样构建的评估集最贴近实际使用场景。纯人工编造的 case 往往过于理想化和真实分布差距很大。3.3 自动化评估指标选对指标比调参更重要AI 项目的评估指标可以分几类每类适合不同的场景指标类型代表指标适合场景局限性字符串匹配Exact Match、F1有标准答案的抽取式任务对同义表达不友好语义相似度BERTScore、Embedding 相似度开放式生成任务高相似度不等于高质量模型评估LLM-as-Judge复杂生成任务的质量评估评估模型本身有偏差人工评估评分 rubric最终质量把关成本高不可大规模我的建议是组合使用用字符串匹配做快速筛选用语义相似度做粗筛用 LLM-as-Judge 做精细评估定期用人工评估校准。三层评估的成本和精度递增可以根据实验阶段灵活选择。LLM-as-Judge 是现在很流行的做法但有几个坑要注意。第一评估模型和被评估模型不能是同一个否则会有自我偏好。第二评估 prompt 要设计得足够具体不能只说“请评估回答质量”要给出明确的评分维度和标准。第三要定期用人工评估检查 LLM 评估的准确性如果发现偏差要及时调整评估 prompt。3.4 评估结果管理让分数会说话评估跑完了结果怎么管理我的做法是所有评估结果入库支持按实验、按指标、按时间维度查询和对比。一个典型的评估结果记录包含实验 ID、评估集版本、各指标分数、每条 case 的详细结果、评估时间。有了这些数据你可以做很多有价值的分析对比不同实验的指标变化判断改动是否有效。查看某个指标下降时具体是哪些 case 变差了定位问题。追踪指标随时间的变化趋势发现模型漂移。分析不同场景下的表现差异找到薄弱环节。我特别推荐做一个评估看板把关键指标的趋势图、实验对比图、case 级别的 diff 都可视化出来。这样每次实验后你花几分钟看一眼看板就能掌握全局不用去翻原始数据。4. 从实验到上线的决策流程4.1 实验管理不是目的做出好决策才是前面讲了数据、配置、评估的管理这些都是手段。真正的目的是基于可靠的信息做出高质量的决策。AI 项目里的决策包括要不要换模型、要不要加 rerank、chunk size 调大还是调小、Prompt 怎么改。每个决策都应该是数据驱动的而不是拍脑袋。我见过太多团队在决策时犯两种错误一种是过度依赖直觉觉得“这个改动感觉会有效”就直接上另一种是过度依赖单一指标看到某个指标涨了就认为改动有效忽略了其他指标的下降。正确的决策流程应该是提出假设 → 设计实验 → 跑评估 → 分析结果 → 做决策 → 记录决策理由。这个流程听起来很重但实际上熟练之后一次实验从设计到出结论可能只需要一两个小时。4.2 如何设计一个有信息量的实验实验设计的关键是控制变量。一次只改一个因素这样才能把效果变化归因到具体的改动上。如果你同时改了 chunk size 和 rerank 配置效果提升了你根本不知道是哪个改动带来的。但现实中很多改动是相互关联的。比如你换了 embedding 模型chunk size 的最优值可能也变了。这时候你需要做网格实验固定其他变量遍历 embedding 模型和 chunk size 的组合找到最优组合。网格实验的成本较高但能帮你理解参数之间的交互关系。还有一种情况是你想验证一个较大的改动比如从 RAG 架构换成 Agent 架构。这种改动涉及多个模块没法控制单一变量。我的做法是先做小规模验证在评估集的一个子集上跑对比实验如果效果明显更好再扩大到全量评估集。这样可以用较低成本快速筛选方向。实操心得实验设计时一定要提前想清楚“什么结果会让你改变决策”。如果无论结果如何你都会做这个改动那这个实验就没必要做。我见过有人花了一周跑实验最后结论是“还是按原计划来吧”这就是典型的无效实验。4.3 决策记录给未来的自己留一封信每次做完决策一定要记录决策日志。内容包括决策背景、考虑的选项、评估结果、最终选择、选择理由、预期效果、实际效果后续补充。决策日志的价值在于它让你在几个月后回顾时能理解当时为什么做了那个选择。AI 项目的迭代速度很快三个月前的决策背景可能已经完全变了。如果没有决策日志你可能会重复踩坑或者在不理解原因的情况下推翻一个其实正确的决策。我自己的决策日志模板大概是这样的决策 ID: D20240115-01 背景: 评估发现多轮对话场景下指代消解准确率只有 62% 选项: A. 在 Prompt 中加入对话历史摘要 B. 使用专门的指代消解模型预处理 C. 微调主模型 评估结果: A: 准确率提升到 78%但 token 消耗增加 40% B: 准确率提升到 85%但增加 200ms 延迟 C: 准确率提升到 82%需要标注数据和训练时间 决策: 选 A因为延迟敏感且 token 成本可接受 预期: 准确率 78%延迟不变成本增加 15% 实际: 准确率 76%延迟不变成本增加 18%后续补充这个模板看起来简单但坚持记录能帮你避免大量重复决策和方向性错误。4.4 上线前的检查清单实验做完了决策也做了准备上线。上线前我建议过一遍检查清单配置是否已固化到生产配置文件而不是实验配置评估集上的表现是否达到上线标准有没有指标明显下降是否做了小流量灰度灰度期间的监控指标是否正常回滚方案是否准备好如果出问题多久能回滚决策日志是否已记录后续效果追踪的指标是否已定义这份清单看起来基础但我见过太多项目因为跳过其中某一项而出问题。特别是回滚方案AI 项目的回滚往往比传统项目复杂因为涉及模型版本、索引版本、配置版本的同步回滚不提前准备好出事时手忙脚乱。5. 常见问题与排查技巧实录5.1 实验复现不了怎么办这是最常见的问题。你记录了一个实验效果很好想复现结果跑出来分数差很多。排查思路按优先级排列第一检查数据版本。最常见的原因是评估集或检索语料变了。确认实验记录里的数据哈希值和当前使用的是否一致。如果用了 DVC 之类的工具直接 checkout 到对应版本。第二检查配置快照。有时候配置文件改了但没提交或者环境变量不同导致行为差异。确认实验记录里的完整配置和当前运行配置一致。第三检查模型版本。如果你用的是 API 模型模型可能已经更新了。API 模型的不确定性是 AI 项目的一个固有难题我的做法是关键实验尽量用固定版本的模型或者至少记录模型的具体版本号。第四检查随机种子。如果涉及随机采样种子不同会导致结果不同。确保实验记录里包含了所有随机种子。第五检查依赖版本。库的版本更新可能导致行为变化。用 lock 文件锁定依赖版本。如果以上都检查了还是复现不了那可能是环境差异导致的。这时候需要更细粒度的日志记录每一步的中间结果逐步定位差异点。5.2 评估分数和线上表现不一致这个问题也很常见。评估集上分数很高上线后用户反馈不好。原因可能有几个评估集分布和线上分布不一致。评估集是你精心构建的但线上用户的提问方式可能完全不同。解决方法是定期从线上采样真实 case补充到评估集中。评估指标和业务目标不一致。你优化的指标可能不是用户真正关心的。比如你优化了回答的语义相似度但用户其实更在意回答是否简洁。解决方法是定期做人工评估校准自动化指标和真实质量的相关性。线上环境有额外约束。比如延迟限制导致你用了更小的模型或者并发压力导致检索结果被截断。解决方法是评估时模拟线上环境或者直接做线上 A/B 测试。5.3 实验太多管理不过来当实验数量增长到几百上千个时管理会变得困难。我的经验是建立实验命名规范和分类体系。命名规范比如{模块}_{改动内容}_{版本号}例如retrieval_chunk768_v2。分类体系比如按模块分检索、生成、后处理、按目的分效果优化、性能优化、成本优化。另外定期清理无效实验。那些没有产生决策价值的实验可以归档或删除避免干扰。但删除前要确认没有其他实验依赖它的数据或配置。5.4 团队协作中的实验管理个人做实验管理相对简单团队协作会复杂很多。核心问题是如何让不同人的实验可对比、可复用。我的建议是统一实验管理工具和记录规范建立共享的评估集和基线配置。每个人做实验时都基于同一个基线配置用同一个评估集记录到同一个实验库。这样不同人的实验结果可以直接对比。另外建立实验评审机制。重要的实验结论要经过评审才能进入决策避免个人偏差。评审时重点看实验设计是否合理、评估是否充分、结论是否有数据支撑。5.5 常见问题速查表问题现象可能原因排查步骤解决方案实验复现不了数据/配置/模型版本不一致逐项对比实验记录严格版本化管理评估分数虚高评估集泄漏或过拟合检查评估集是否参与训练冻结保留集线上效果差分布不一致或环境差异采样线上 case 对比补充评估集模拟线上环境实验管理混乱缺乏命名和分类规范审查实验记录建立规范和分类体系团队协作困难工具和规范不统一统一工具和流程建立共享基线和评审机制6. 把这套机制跑起来的最小行动方案6.1 第一周建立最小可用的实验记录不要一上来就追求大而全的方案。第一周的目标很简单让每次实验都有记录。用一个 SQLite 数据库建一张 experiments 表字段包括实验 ID、时间、配置 JSON、评估分数、备注。每次跑实验时写几行代码把信息插进去。这一步的关键是养成习惯。哪怕记录得不完美也比不记录强。我见过太多人想等“方案完善了再开始记录”结果永远没开始。6.2 第二周冻结评估集从现有数据中整理出 50-100 条评估 case人工标注期望输出冻结为 v1 版本。写一个评估脚本输入是模型输出输出是各指标分数。把这个脚本接入实验记录流程每次实验自动跑评估。评估集不需要一开始就很完美。先跑起来后续可以迭代。但一旦冻结就不要随意修改新增 case 走新版本。6.3 第三周配置外置和版本化把代码里的魔法数字全部抽到配置文件中。配置文件纳入版本管理每次实验保存完整快照。这一步可能需要重构一些代码但值得投入。6.4 第四周建立决策日志和复盘机制开始记录决策日志。每周花半小时复盘本周的实验和决策看看有没有遗漏的记录有没有可以优化的流程。这个复盘习惯能帮你持续改进实验管理机制。6.5 持续迭代根据项目规模调整方案项目规模小的时候SQLite 本地文件就够了。项目变大后可以考虑迁移到专业实验管理平台。但核心原则不变数据版本化、配置外置化、评估自动化、决策记录化。我在多个项目中反复验证过这套机制的有效性。最直观的感受是当实验管理跑起来之后迭代速度不是变慢了而是变快了。因为你知道每次改动的影响是什么不用反复试错不用回滚来回去查历史。前期投入的时间在后续迭代中会加倍回报。最后分享一个我踩过的坑不要试图一次性把所有东西都管理起来。我刚开始做实验管理时想把所有数据、所有配置、所有评估都纳入体系结果复杂度爆炸自己都不想用。后来改成渐进式先管最重要的再逐步扩展反而坚持下来了。实验管理这件事可持续比完美更重要。