AI 技术迭代的速度很快,团队在追赶大模型浪潮时,往往会把“快速上线”“全面重构”“All in AI”当作第一优先级。但每次技术变革背后都有一批被遗忘的资产,它们可能是运行多年的老系统、沉淀已久的历史数据、已经验证过的测试方法,也可能是团队踩坑后总结出来的业务规则。这些资产,我习惯把它们称作 AI 时代里的“墓地”。它们不是没有价值,而是常常被默认“应该被牺牲”。
这篇文章想聊的是:当我们推动 AI 工程化落地时,到底牺牲了什么、哪些东西值得保留,以及如何用一套可执行的取舍框架来做决策。
1. 背景与核心概念:什么是 AI 时代的“墓地”
先来解释标题里的“Cemeteries”。墓地给人的感觉是沉寂、过时、被废弃,但在 AI 语境下,我想用它指代那些“还活着、但没有被 AI 转型计划充分尊重”的既有资产。
它们通常包括四类:
- 遗留系统与旧技术栈:运行了多年的单体应用、老接口、自研规则引擎。
- 测试与评估体系:传统机器学习指标、回归用例、人工验收规范。
- 历史数据与知识资产:客户工单、产品文档、故障复盘记录、FAQ 库。
- 可控性与安全边界:权限模型、审计日志、审批流程、回滚机制。
AI 项目推进得快,团队容易产生一种错觉:过去的东西都是拖累,大模型可以解决一切。于是“旧系统推翻重写”“旧指标全部替换”“旧数据简单清洗后喂给大模型”“权限尽量放开给 Agent”。这种思路的出发点不是错,但执行得太粗暴,就会把有价值的“墓地”连根拔起。
我们在工程里常说的“技术债”,本质上就是这些墓地没有被妥善处理。差异在于:技术债通常是被动欠下的,而这个时代的“墓地”往往是主动牺牲掉的,代价更隐蔽。
所以,这篇文章不是反对 AI 落地,而是讨论一个更冷静的问题:在 AI 转型中,哪些东西应该被牺牲,哪些东西应该被迁移,哪些东西应该被当成知识养料重新启用。
2. 遗留系统与旧技术栈:重建还是迁移
2.1 为什么 AI 项目总是想“重写”
很多团队在引入大模型后,第一反应是把业务流程重做一遍。因为大模型应用的调用链与传统应用差异很大,需要涉及向量数据库、Prompt 管理、Agent 编排、流式输出等新组件,老系统不一定接得住。
但“接不住”不等于“没价值”。一个运行稳定、业务规则清晰的旧系统,往往包含了很多没有写进文档的隐性逻辑。直接推翻重写,相当于把一张有历史标记的地图扔掉,再重新画一张更容易迷路的新图。
正确的做法是给旧系统做一次“可替换性评估”,先搞清楚哪些模块只是“老旧但稳定”,哪些模块才是“真正阻碍 AI 改造的瓶颈”。
2.2 可替换性评估脚本
下面给出一个简单的 Python 脚本思路,用来扫描服务依赖清单,从维护成本、业务稳定性、AI 替代潜力三个维度评估系统中各模块的替换优先级。
# 文件路径:scripts/assess_replace_priority.py """ 功能:根据依赖、维护成本、AI 替代潜力评估遗留模块替换优先级 用法:python assess_replace_priority.py modules.csv """ import sys import csv def load_modules(path): modules = [] with open(path, newline="", encoding="utf-8") as f: reader = csv.DictReader(f) for row in reader: modules.append(row) return modules def assess(module): """ 返回 replace_score:分数越高,越适合主动替换 """ maintenance_cost = int(module.get("maintenance_cost", 3)) # 1-5,5 表示维护成本极高 dependency_risk = int(module.get("dependency_risk", 3)) # 1-5,5 表示依赖旧技术栈严重 ai_opportunity = int(module.get("ai_opportunity", 3)) # 1-5,5 表示 AI 替代潜力很高 business_stability = int(module.get("business_stability", 4)) # 1-5,5 表示业务极其稳定 # 旧技术栈依赖越高、维护成本越高,越应该被替换 tech_debt_score = maintenance_cost * 0.4 + dependency_risk * 0.6 # 业务稳定性越高,越需要谨慎,避免在核心链路上激进重构 stability_penalty = business_stability * 0.5 replace_score = ai_opportunity * 0.7 + tech_debt_score * 0.3 - stability_penalty return round(replace_score, 2) if __name__ == "__main__": if len(sys.argv) < 2: print("请传入 CSV 文件路径,例如:python assess_replace_priority.py modules.csv") sys.exit(1) module_list = load_modules(sys.argv[1]) for m in module_list: print(f"{m['module_name']}: 替换优先级得分 {assess(m)}")示例 CSV 内容modules.csv:
module_name,maintenance_cost,dependency_risk,ai_opportunity,business_stability rule_engine,5,5,5,2 order_service,3,2,4,5 report_generator,4,4,3,3运行结果类似:
rule_engine: 替换优先级得分 5.0 order_service: 替换优先级得分 3.0 report_generator: 替换优先级得分 2.6这个脚本的价值不在于给出绝对答案,而在于把“替换决定”从印象流变成可量化讨论。团队可以在评审会上对齐每一项打分,而不是产品经理说“重写”就重写,研发说“保留”就保留。
2.3 渐进迁移比一刀切更安全
对于高替换优先级的模块,建议采用绞杀者模式(Strangler Fig Pattern),也就是在旧系统旁边新建 AI 能力模块,通过网关逐步把流量切到新模块,直到旧模块不再被调用。
对于业务稳定性高的模块,即便技术上看着旧,也建议先做“接口兼容层”,让新 AI 服务与旧核心逻辑并行运行一段时间,通过灰度对比再决定是否彻底下线。
这一步的核心原则是:留下迁移路径,而不是留下废墟。
3. 测试与评估体系:旧指标要不要陪葬
3.1 传统指标在大模型时代遇到的问题
在传统机器学习项目中,模型输出是分类标签或数值,评估指标相对成熟,比如准确率、精确率、召回率、F1、AUC 等。
但到了大模型时代,模型输出是自然语言,一个 Prompt 可以生成几百字的回答,没有固定标签,传统的“预测值对比真实值”评估方式往往失灵。
于是很多团队干脆把旧评估体系扔掉,完全依赖“人工抽看”或“大模型自己打分”。这会带来两个新问题:
- 人工抽看覆盖不全,回归风险容易被漏掉。
- 大模型打分虽然高效,但评分标准不稳定,同一个答案换一个 Prompt 模板,分数可能完全不同。
3.2 双轨评估思路
更稳妥的做法是双轨评估:传统指标继续覆盖结构化输出部分,大模型评估覆盖语义质量部分,两边数据同时上报到同一个评估看板。
下面是一个简化示例,展示如何对同一个任务输出分别计算传统指标和语义评分:
# 文件路径:scripts/evaluation/dual_track_eval.py """ 双轨评估演示: - track1: 传统指标,适用于结构化字段 - track2: 大模型语义评分,适用于自然语言回答 """ import re def exact_match_score(prediction, ground_truth): """传统指标:精确匹配""" return 1.0 if prediction.strip() == ground_truth.strip() else 0.0 def keyword_recall(prediction, ground_truth): """传统指标:关键词召回率,适合抽取类任务""" keywords = set(re.findall(r"[\u4e00-\u9fa5a-zA-Z0-9]+", ground_truth)) if not keywords: return 0.0 hit = [k for k in keywords if k in prediction] return round(len(hit) / len(keywords), 4) def llm_semantic_score(prediction, ground_truth): """ 模拟大模型语义评分接口。 实际使用时可以替换为真实的 LLM 调用,并配置明确的评分 Prompt。 """ # 示例思路:这里用文本相似度近似,真实项目应调用大模型进行打分 common = set(prediction) & set(ground_truth) return round(len(common) / max(len(set(prediction)), len(set(ground_truth)), 1), 4) if __name__ == "__main__": pred = "订单已发货,预计三天内到达" truth = "包裹已经发出,预计三天左右送到您手中" print("精确匹配:", exact_match_score(pred, truth)) print("关键词召回:", keyword_recall(pred, truth)) print("语义评分(示例):", llm_semantic_score(pred, truth))这段代码强调的是“评估体系需要分层”,而不是用某一个指标包打天下。真正生产中可以把传统指标和 LLM 打分结果都写入 JSONL 文件,再汇总到 BI 看板做趋势分析。
3.3 旧回归集不能丢
很多团队在引入大模型后,把积累多年的回归测试集和人工标注样本量束之高阁,理由是“这些样本太老了,不适合新模型”。
但旧回归集是团队的“历史考卷”,即使新模型能力更强,也应该把旧考卷跑一遍,看看是哪些题目从不会变成了会,哪些题目以前会、现在反而不会了。这种对比能帮助团队发现大模型升级带来的“能力回退”,也就是 Regression。
建议把旧回归集转成统一评测集,分为“必须稳定通过”和“参考观察”两类,每次模型 Prompt 或 Agent 流程变更都要跑一遍。
4. 历史数据与知识资产:从墓地到养料
4.1 历史数据不是累赘,而是知识库的原料
企业在过去几年积累了大量的工单、产品文档、FAQ、故障复盘,很多数据在传统业务里只是被“存着”,没有被充分利用。AI 落地时,这些历史数据恰恰是构建 RAG 知识库和微调数据集的宝贵原料。
但直接把这些数据丢给大模型,会带来两个问题:第一是数据质量参差不齐,包含大量过时、重复、甚至错误的信息;第二是权限边界不清晰,部分数据可能包含敏感信息,不能随便被模型读取。
4.2 文档切分与质量初筛示例
以 RAG 知识库为例,第一步是对文档做切分。切分质量直接决定检索质量,这里给出一个基础版本的切分脚本:
# 文件路径:scripts/kb/chunk_documents.py """ 功能:将 Markdown / 纯文本文档按标题和段落切分为 chunk,并输出简单质量指标 """ import re from pathlib import Path def split_markdown_by_headings(text): """ 按标题切分,保留标题层级信息。 返回 [(heading, content), ...] """ lines = text.splitlines() sections = [] current_heading = "未分类" current_content = [] for line in lines: heading_match = re.match(r"^(#{1,3})\s+(.*)", line) if heading_match: if current_content: sections.append((current_heading, "\n".join(current_content))) current_heading = heading_match.group(2) current_content = [] else: current_content.append(line) if current_content: sections.append((current_heading, "\n".join(current_content))) return sections def chunk_quality_check(section): """ 简单质量检查:空内容、过短内容、重复内容 """ heading, content = section content = content.strip() if not content: return "empty" if len(content) < 20: return "too_short" if len(set(content.split())) < 5: return "low_diversity" return "ok" if __name__ == "__main__": input_path = Path("docs/sample.md") text = input_path.read_text(encoding="utf-8") sections = split_markdown_by_headings(text) print(f"共切分 {len(sections)} 个片段:") for heading, content in sections: status = chunk_quality_check((heading, content)) print(f"[{status}] {heading} 长度={len(content)}")这个脚本虽然简单,但反映了知识库建设中最重要的一件事:先盘点、再清洗、后入库。很多团队跳过清洗直接灌入向量数据库,上线后才发现检索结果质量很差,根源往往就是切分太随意。
4.3 旧知识的重新组织
历史数据不应该被当成“一次性燃料”直接塞给 Prompt,而应该被组织成持续演进的知识资产。具体做法是建立“知识入库审批”流程:
- 定义数据来源,比如工单系统、产品文档库、故障库。
- 设置数据质量门槛,过时、重复、敏感数据先标记。
- 按业务域建立知识目录,而不是把所有数据放进一个大池子。
- 定期抽查 RAG 检索结果,把错误答案反哺回知识库做修正。
这样,历史数据才真正从“墓地”变为“养料”。
5. 可控性与安全边界:不能牺牲的“墓地主权”
5.1 AI Agent 越自主,越需要强管控
AI Agent 的典型特征是“自主行动”:根据目标拆解任务、调用工具、读取数据、执行操作。如果不对这种自主性做限制,出现故障时的影响范围会远超传统脚本。
实践中最常见的失控场景包括:
- Agent 拿到一个权限过大的 API Key,误删了生产环境数据。
- Agent 在循环调用中产生了大量外部请求,造成费用飙升。
- Agent 修改了配置,但没有留下可追溯的审计记录。
这些问题的根因不是模型不聪明,而是我们把传统系统里的安全边界也一起“牺牲”了。
5.2 最小权限与审批门禁
在权限控制上,原则是:AI Agent 能拿到的权限,不能超过完成目标任务所需的最小权限。这里给出一个简化版的高风险操作审批示例:
# 文件路径:scripts/agent/approval_gate.py """ 功能:在 Agent 执行高风险操作之前,进入人工审批状态 """ from enum import Enum class RiskLevel(Enum): LOW = 1 MID = 2 HIGH = 3 def evaluate_risk(action, target, operator): """ 根据操作类型、目标对象、操作者身份评估风险等级 """ risk = RiskLevel.LOW if action in ("delete", "update", "grant_permission"): risk = RiskLevel.HIGH elif action in ("create", "restart"): risk = RiskLevel.MID # 操作者不是系统管理员时,风险等级上调 if operator != "admin" and risk.value < RiskLevel.HIGH.value: risk = RiskLevel(risk.value + 1) # 涉及生产环境核心表时,至少要求 MID if target.startswith("prod_core_") and risk.value < RiskLevel.MID.value: risk = RiskLevel.MID return risk class AgentRunner: def __init__(self): self.approval_required = [] def execute(self, action, target, operator): risk = evaluate_risk(action, target, operator) print(f"风险等级:{risk.name} 操作:{action} 目标:{target}") if risk == RiskLevel.HIGH: # 阻塞执行,进入人工审批队列 self.approval_required.append((action, target, operator)) print("已进入人工审批,任务暂停。") return False # 低风险操作直接执行 print("已执行。") return True if __name__ == "__main__": agent = AgentRunner() agent.execute("delete", "prod_core_order", "user_wang") agent.execute("query", "prod_core_order", "user_wang")这段代码是 Agent 安全设计的最基本形态:在工具调用链路中加入风险判断。生产环境里还需要结合真实的权限校验服务、审计日志和审批系统,但核心思想是一致的——把安全决策从“模型的自由发挥”中拿出来,放到可审计、可干预的工程层。
5.3 不可牺牲的三件事
不管 AI 怎么演进,下面三件事都建议保留:
- 审计日志:每个 Agent 动作都要有 trace_id,能够回答“谁在什么时间做了什么事”。
- 回滚机制:Agent 修改过的配置、状态、数据都要有快照,至少能恢复到操作前。
- 人类审批点:对删除、授权、转账、发布等高危动作,保留人工确认环节。
这三点不是限制 AI 效率,而是给 AI 失控时留一条安全通道。
6. 工程取舍框架:该保留什么,该埋葬什么
与其每次遇到“要不要重构”都争论不休,不如建立一套团队通用的取舍框架。
6.1 资产盘点
先把系统里的资产分门别类列出来:
| 资产类型 | 典型例子 | 是否需要 AI 参与 |
|---|---|---|
| 核心业务逻辑 | 订单状态机、结算规则 | 不一定,保持稳定优先 |
| 辅助决策逻辑 | 风控规则、推荐排序 | 适合引入 AI 增强 |
| 数据管道 | ETL、数据同步 | 可以渐进优化 |
| 交互入口 | 客服、工单、搜索 | 适合 AI 重构 |
| 知识类资产 | FAQ、文档、工单库 | 适合 RAG 化 |
6.2 四象限决策
把上面的资产按“业务稳定性”和“AI 替代潜力”两个维度放进四象限:
| 象限 | AI 替代潜力高 | AI 替代潜力低 |
|---|---|---|
| 业务稳定性高 | 并行增强,灰度上线 | 保持维护,暂不重构 |
| 业务稳定性低 | 重点替换,快速试错 | 优先现代化改造 |
对应策略:
- AI 替代潜力高 + 稳定性高:做“增强模式”,让 AI 当辅助,不完全接管。
- AI 替代潜力高 + 稳定性低:适合做试点,快速验证价值。
- AI 替代潜力低 + 稳定性高:别动它,稳定就是最大的收益。
- AI 替代潜力低 + 稳定性低:考虑整体现代化,而不是只接大模型。
6.3 成本收益评估
决策前建议至少评估五项:
- 改造成本:新链路构建、数据迁移、模型 Prompt 调优成本。
- 维护成本:新系统上线后的持续运维成本。
- 风险成本:替换核心模块可能带来的业务中断风险。
- 机会收益:AI 带来的效率提升、体验提升。
- 团队学习成本:团队成员需要多长时间掌握新架构。
其中第 3 项和第 5 项最容易被低估,建议在立项文档里单独列出。
7. 常见误区与排查清单
7.1 几个常见的危险信号
| 现象 | 可能原因 | 解决思路 |
|---|---|---|
| “AI 原生”项目上线后频繁出错 | 旧系统业务规则没有完整迁移 | 先做规则穷举,把旧系统当作需求文档 |
| 大模型答案时好时坏,无法回归 | 只用人工看效果,没有固定评测集 | 建立双轨评估集,定期跑回归 |
| RAG 检索结果混乱 | 文档直接灌入,未做清洗和切分 | 建立知识库准入标准,先清洗再入库 |
| Agent 经常误操作 | 权限给太大,缺少审批门禁 | 实施最小权限,增加人工审批点 |
| 团队上线速度越来越慢 | 旧知识丢失,遇到问题重新踩坑 | 建立团队 Wiki 与故障复盘库 |
7.2 排查顺序建议
如果你的 AI 项目已经出现问题,可以按这个顺序排查:
- 先看数据链路,确认喂给模型的数据是否完整、正确。
- 再评估模型输出,用固定评测集跑一遍,不要只看一两个例子。
- 接着检查权限,确认 Agent 是否拿到了超出任务范围的权限。
- 最后看审计日志,定位具体是哪个环节出现了偏差。
大部分问题不是出在模型推理能力上,而是出在数据、评测与控制链路上。
8. 最佳实践与工程建议
8.1 双轨并行,灰度过渡
在 AI 改造过程中,不要一步完成切换。建议新旧系统并行运行一段时间,新系统流量从 5%、20%、50%、100% 逐步递增。每个阶段都对比指标,确认不低于旧系统再继续放量。
8.2 为旧系统建立“拆迁档案”
在决定替换某套旧系统前,先把下面内容整理成文档:
- 系统架构图与数据流。
- 核心业务规则清单,尤其是代码里藏着的隐式规则。
- 历史故障记录与对应解法。
- 已知的技术债和待办事项。
- 关键接口的调用方清单。
这份“拆迁档案”不仅服务于迁移过程,以后新系统出问题时还能回头对照。
8.3 评测集是 AI 项目的“底线工程”
每个 AI 项目都应该维护三个评测集:
- 冒烟集:每次改动后跑,快速发现明显问题。
- 回归集:覆盖历史缺陷,防止能力回退。
- 挑战集:收集线上新出现的失败样本,持续补充。
评测集需要持续迭代,不是一次性工作。
8.4 知识库与数据治理并行
RAG 项目能不能做好,七分靠数据治理,三分靠模型能力。建议安排专门的数据质量负责人,而不是让算法工程师兼任。知识库的权限模型要与公司权限体系打通,避免敏感数据越权流出。
8.5 可观测性建设要提前
AI 应用的日志比传统应用更复杂,因为链路里有模型调用、Prompt 版本、向量检索、上下文拼接等多个环节。建议至少记录:
- 每一次 LLM 调用的输入输出和 token 消耗。
- 使用的 Prompt 版本号。
- 检索到的知识片段及置信度。
- Agent 的决策路径,即调用了哪些工具、先后顺序如何。
有了这些数据,线上出问题时才能快速定位。
9. 总结
回到标题,我们真的在为了 AI 牺牲墓地吗?答案取决于团队自己。
技术浪潮里,真正危险的不是技术进步,而是为了技术进步而忘记保留经验。那些看似要被“埋葬”的老系统、旧数据、旧指标、旧规则,经过合理迁移、清洗、编排之后,往往能成为 AI 项目启动时最扎实的地基。
建议你的团队现在做一件事:花半天时间整理一份“墓地清单”,盘点哪些系统在被忽略、哪些数据在被闲置、哪些测试方法在被淘汰。然后把清单放进 AI 改造项目的第一份文档里。
不是所有东西都值得抢救,但值得抢救的东西,不应该被随便牺牲。