前几天,Anthropic 公开了一个数字:他们内部约 95% 的 business analytics 查询,已经由 Claude 自动处理,整体准确率大约 95%。
看到这个数字,很多人第一反应是:Claude 的 SQL 写得真准,模型能力太强了。
但如果你仔细看 Anthropic 自己是怎么讲的,你会发现,他们不是在炫耀模型能力。他们在讲一件更根本的事——数据不是软件。
这个判断,恰好也解释了另一个同样棘手的问题:为什么那么多团队用 AI 改造老系统,改出来的东西看着像模像样,一上线就出问题。
两个场景,同一个坑。
代码 Agent 和数据 Agent,风险结构完全不同
先讲为什么"数据不是软件"。
写代码是一个开放解空间。一个功能可以有多种实现方式,只要接口对、测试过、运行结果符合预期,这段代码就可以接受。而且软件世界有很多兜底机制——语法错了会报错,类型不对会报错,单元测试不过会暴露,CI 失败会拦住。虽然这些机制不是万能的,但它们形成了一层层的防护网。
数据分析不一样。
很多业务问题,最后只有一个正确答案,也只有一个正确来源。更麻烦的是,你经常没有一个确定性的办法马上证明这个答案是对的。
SQL 可以没有任何语法错误,查询可以顺利执行,返回的数字可以很合理。但如果它用了错的口径、错的数据源、旧的字段、漏了一个排除条件,答案就是错的。
这种错,不一定会报错。
举个例子。你问 Agent:"上个月利润是多少?"
它写了一段 SQL,从收入表减去成本表,跑出来一个数。语法没问题,执行没问题,结果看起来也很专业。
但如果它用的是运营口径不是财务口径,如果它没扣掉退款和折扣,如果它用了上个月已经废弃的成本字段,如果它没排除内部测试订单——这个利润数字就不能拿来决策。
问题不在 SQL。问题在 SQL 背后的业务语义。
Anthropic 把这个问题总结得很清楚:分析准确率是上下文和验证问题,不是代码生成问题。 模型会写 SQL,只是入场券。
三类失败,指向同一个根源
Anthropic 把他们遇到的大多数不准确回答,收敛成三种主要失败模式。
第一类:概念和实体的歧义。
用户说"活跃用户",数据系统里对应的是成百上千张表、字段、派生指标和历史版本。Agent 如果不知道哪个字段最能回答问题,就会猜。猜出来的结果通常不会显得离谱——它会找一个看起来相关的表,写一段看起来合理的 SQL,给出一个看起来可信的答案。这反而更麻烦,因为错得不够明显。
第二类:数据过期。
企业数据一直在变。口径会改,Schema 会改,数据源会迁移。一张表可能被替换,一个字段可能被废弃,一个指标可能换了计算方式。如果 Agent 还拿着旧知识回答,它不一定会报错,它可能只是返回一个细微但错误的答案。
就像拿着上个月的地铁图,在今天的城市里导航。线路看着完整,站名也像真的,但某个站已经改名,某段线路已经调整——你按图走,未必马上发现错。
第三类:检索失败。
正确信息可能就在数据模型里,字段注释也写了,文档里也提过。但搜索空间太大,Agent 找不到。企业数据系统不是一本保存完好的手册,它更像一座堆满档案的仓库。答案确实在里面,但如果索引不好、命名混乱、相关文档太多,Agent 就可能拿不到最该看的那一页。
更危险的是,它找不到正确答案,就会找一个相似答案顶上。
这三类失败摆在一起,你会发现它们都不是单纯的 SQL 生成问题。
历史系统AI改造,掉进的是同一个坑
现在我们来说历史系统。
很多团队用 AI 改造老系统时,思路是类似的:让 AI 读一遍旧代码,然后重写一遍。听起来很合理,老代码用新架构重写,性能更好,维护更方便。
但这里有一个隐藏的前提:旧代码本身是对的。
真实世界里,老系统的代码里充满了"历史遗留"——那些因为临时 bug 打的补丁、因为某个已经离职的同事写的 workaround、因为旧系统本身的缺陷做的补偿逻辑。这些代码能跑,但不代表它们是对的。它们只是"在那个时间点、那个上下文里能解决问题"。
如果你让 AI 读这些代码,然后生成新代码,AI 会把这些历史债务原封不动地继承下来。
而且,和数据 Agent 的情况一模一样——AI 生成的新代码语法不会错,结构可能还更漂亮了,测试也能过。但业务逻辑可能就是错的。
举个例子。一个老系统里有一段 if 分支,注释写着"临时修复线上问题,后续需要优化"。五年过去了,没人知道那个问题的来龙去脉,也没人敢删。新工程师让 AI 重写这个模块,AI 读了旧代码,把这段逻辑原封不动地搬到了新系统里。新系统跑得飞快,但那个本不该存在的分支,现在变成了新系统的"祖传代码"。
再比如,一个字段叫 status,在 v1 版本里表示"用户状态(启用/禁用)",v2 版本改成了"审核状态(待审/通过/驳回)",v3 版本又加了一层含义。三套逻辑共用一个字段,靠上下文区分。AI 读代码的时候,它会按照当前的代码逻辑去理解这个字段,但它不知道这段历史。如果它重写的时候选择了"最简洁"的实现方式,很可能就把那些靠上下文区分的边界情况丢掉了。
和数据 Agent 的三类失败对照来看:
• **概念歧义** → 老系统里"这个模块到底干什么的",和新系统里"这个模块应该干什么",可能不是同一件事
• **数据过期** → 旧代码里能跑的逻辑,放到新环境、新数据源里,可能已经不适用
• **检索失败** → 文档散落在各处,需求文档、技术方案、群聊记录、离职同事的交接邮件——正确答案存在,但 AI 摸不到
这些都是同一个根源:AI 容易生成"看起来对"的东西,但"看起来对"和"实际上对"之间,隔着整个组织的上下文。
所以,难的不是写,是知道哪个是对的
无论是在做数据 Agent 还是做历史系统 AI 改造,最容易犯的错误就是:把问题简化成了"生成能力够不够强"。
数据团队说:"让 Claude 直接写 SQL 查数,不就自助分析了吗?"
开发团队说:"让 AI 读一遍旧代码直接重写,不就完成改造了吗?"
这两种思路共享同一个幻觉:把上下文问题当成了生成问题。
代码 Agent 能成功,是因为软件工程经过几十年的发展,已经建立了一套完整的验证体系——测试、CI、类型系统、代码审查。这些机制让 AI 的"猜"有了纠错空间。
数据分析和老系统改造缺少这样的体系。数据对不对,没有编译期检查;老系统的业务逻辑对不对,没有回归测试覆盖所有历史场景。AI 的"猜"一旦出错,没有第二道防线兜住。
所以 Anthropic 那句"数据不是软件",对历史系统改造同样成立。
代码是写出来的,上下文是攒出来的。AI 能写好代码,但上下文得人给它搭好。
如果你正在做数据 Agent,不要只盯着 SQL 生成能力,先问自己:Agent 知不知道哪一个数才是公司当前承认的答案?
如果你正在用 AI 改造老系统,不要只盯着代码生成能力,先问自己:AI 知不知道那段看起来多余的 if 分支,当年是谁、为什么写在那里的?
真正难的不是生成。是分辨"哪个是对的"。
而这件事,目前还没有编译器能帮你检查。
如果你也在做数据 Agent 或老系统 AI 改造,欢迎留言聊聊你们踩过的坑。
觉得有启发?点个 在看,转发给同样在跟历史债务死磕的同事 🤝