LangChain 学习笔记 10:接入很多模型,不等于系统真的可替换

LangChain 的一大特点是集成丰富:聊天模型、Embedding、向量库、Loader、Retriever 和工具都能找到不同实现。刚开始看会觉得,只要接口统一,底层服务就可以随时替换。

真正做迁移时才会发现,“代码能跑”只代表第一关通过。不同服务在能力、数据和运维上的差异,并不会因为套了一层框架就消失。

统一接口解决了什么

框架可以把常见操作整理成相近形状,例如模型调用、批处理、流式输出、添加文档和相似度检索。上层流程因此可以围绕“聊天模型”或“Retriever”编程,而不是到处写供应商 SDK。

这对原型开发很有帮助,也能减少重复适配代码。但统一接口更像插座标准,并不能保证接上的每台设备性能相同。

模型替换要检查能力差异

从模型 A 换到模型 B 时,至少要重新确认:

  • 是否支持工具调用、结构化输出和图片输入;
  • 消息角色与流式事件是否一致;
  • 上下文长度、限流和超时策略;
  • 同一 Prompt 的输出质量与稳定性;
  • token 计算、价格和延迟。

如果业务依赖工具并行调用,就不能只定义一个“所有模型都有 generate 方法”的最低公分母接口。适配层还应暴露所需能力,并在启动或调用前检查。

向量库迁移更像数据迁移

向量库的差异不仅是查询函数名。索引算法、距离度量、过滤语法、多租户方式、备份恢复和一致性都可能不同。

更换 Embedding 模型时,还涉及向量维度和空间变化,通常需要重建索引。即使 Embedding 不变,迁移向量库也要验证元数据、文档 ID、删除语义和 top-k 排序是否一致。

我会把这些版本一起写进索引清单:

{
  "embedding_model": "example-embedding-v2",
  "dimension": 1536,
  "distance": "cosine",
  "chunking_version": "manual-v3",
  "created_at": "2026-07-30"
}

没有这些信息,几个月后很难解释某批向量是怎样生成的。

薄适配层仍然值得保留

即使已经使用 LangChain,我也倾向在业务项目中保留很薄的一层,例如 ChatService、EmbeddingService 和 KnowledgeRetriever。

这层接口只暴露业务真正需要的能力:生成客服草稿、生成文档向量、按权限检索知识。框架升级或供应商变化时,修改集中在基础设施层,业务代码不必直接感知每个类名变化。

适配层不要追求覆盖供应商全部功能。共性能力走统一接口,确实需要的特殊能力通过明确扩展点提供,并用测试说明它不能被任意实现替换。

“可替换”必须通过测试证明

我会准备一套契约测试:相同输入能否返回约定结构,超时和错误能否映射到统一类型,过滤条件是否生效,流式结果是否完整。

在契约测试之外,还需要业务评测。模型换了以后分类准确率是否下降?向量库迁移后标准问题的召回率是否变化?这些才决定替换是否真正成功。

这章给我的启发

集成的价值不是把所有供应商伪装成完全相同,而是把差异集中到可管理的位置。

统一契约让上层代码稳定,能力声明提醒我们差异仍然存在,版本记录和回归测试则保证迁移不是一次碰运气。类名会过时,供应商也会变化;这些工程习惯才是更长期的资产。

posted @ 2026-08-01 18:26  Hazy_star  阅读(6)  评论(0)    收藏  举报