升级一个SDK,15个文件报错,4个供应商接口全变。第二次发生时,作者知道还会有第三次。

他定了一条铁律:整个代码库只允许2个文件导入LLM SDK。结果下次升级只改了2个文件,28个文件纹丝不动。更意外的是,这次重构删掉688行代码,只新增192行——但真正的收获不是SDK解耦,而是发现自己把7种认知操作重复写了21遍。

SDK瘟疫:从"小升级"到"全天救火"

SDK瘟疫:从"小升级"到"全天救火"

作者的项目是个24/7运行的个人助手,处理邮件分拣、会议准备、晨间简报、CRM更新、社媒情报、求职者打分等任务,全部由一个持久化工作流引擎调度,核心就是大量LLM调用。

重构前的依赖结构像一张蜘蛛网:

活动层(Activity Layer):21个文件直接内嵌SDK调用,每个文件都从"ai"和"@ai-sdk/*"导入generateText()、generateObject()、tool()

路由层(ModelRouter):负责模型选择和预算控制,但返回的是原始SDK模型对象,活动层直接拿来用

供应商层:@ai-sdk/anthropic、@ai-sdk/openai等

SDK同时出现在路由层和活动层,意味着升级成本呈指数级扩散。Vercel AI SDK从v4到v6的改动清单很机械:maxTokens改成maxOutputTokens,CoreMessage改成ModelMessage,generateObject()废弃,tool调用的args改成input——但分散在15+个文件的不同用法里,漏改一个就是运行时崩溃,编译器不会提醒你。

更隐蔽的是提示词瘟疫。5个活动用5种不同结构做内容分类,9个活动用9种不同方式注入语气。改了一处的分类提示,得记得去另外4处同步。作者「经常忘记」。

两文件隔离法:把供应商变成可插拔的电源

两文件隔离法:把供应商变成可插拔的电源

新架构的核心是端口与适配器模式(Ports and Adapters),作者把它比作电源插座:

整个代码库只有Adapter和Provider Registry两个文件知道SDK存在

18个活动文件、10个代理文件、全部工作流对供应商、模型、SDK细节零感知

具体实现分三层:

端口层定义抽象接口:generateText、generateObject、tool调用全部标准化,返回结构固定。活动层只依赖这些接口,像电器只认插座形状,不关心电网来自火电还是风电。

适配器层做翻译:每个供应商一个适配器,把OpenAI的格式、Anthropic的格式、本地模型的格式,全部转成端口层的标准结构。SDK升级时,只改适配器内部的映射逻辑。

注册表层管路由:根据预算、任务类型、延迟要求选择模型,但返回的是端口抽象而非原始SDK对象。切换供应商变成改配置,不是改代码。

效果立竿见影。下一次SDK升级,改动范围从15+文件压缩到2个文件。28个业务文件零变更,编译通过即部署。

意外收获:7种认知操作的"标准化手术"

意外收获:7种认知操作的"标准化手术"

SDK解耦完成后,作者发现更深层的问题:21处LLM调用不是在解决21个不同问题,而是在用21种略有差异的方式重复实现7种基础操作。

分类(Classify):给内容打标签,判断优先级

起草(Draft):生成回复、摘要、报告

评分(Score):数值化评估质量、匹配度、风险

摘要(Summarize):压缩长文本

提取(Extract):结构化抽取实体、日期、关键信息

规划(Plan):分解任务步骤

分析(Analyze):推理、归因、趋势判断

原来每个活动都内嵌了"分类"的完整实现——提示词结构、温度参数、重试逻辑、错误处理,全部手写。5个分类调用就是5份独立代码,改进一处,四处遗漏。

作者把这7种操作提取成标准工具,像编程语言的内置函数。活动层不再写"怎么调用模型做分类",而是直接调用classify(content, options),内部实现统一优化。提示词版本管理、A/B测试、成本监控,全部收敛到7个入口。

从"供应商锁定"到"认知层锁定"

从"供应商锁定"到"认知层锁定"

这次重构的终局数据很克制:192行新增,688行删除。净减500行代码,但复杂度下降了一个数量级。

作者的原话是:「解决SDK耦合暴露了一个更大的问题——我在21个地方重复实现7种认知操作。修复这个比SDK隔离本身更有价值。」

这指向一个被忽视的架构陷阱。大家忙着讨论"不要被OpenAI锁定",却很少有人意识到:提示词工程、链式调用模式、认知任务分解方式,这些才是真正难以迁移的资产。换个供应商只是改API端点,换个认知架构才是伤筋动骨。

两文件隔离法的本质,是把"认知层"和"执行层"彻底切开。活动文件描述"我要分类这批邮件",适配器文件决定"用哪个模型、什么温度、怎么重试"。前者稳定,后者随技术迭代频繁变动。

当你的代码库里有21个generateText调用时,你拥有的是21份需要独立维护的债务。当这21个调用收敛到7个标准操作时,你拥有的是可组合、可优化、可审计的认知基础设施。

作者最后提到,他的个人助手现在处理着比 refactor 前多3倍的LLM调用量,但维护成本反而下降了。下一次供应商推出新模型,他的改动范围是两个文件——而竞争对手可能还在翻找那15个散落在各处的调用点。

你的代码库里,有多少个generateText在自由生长?