LangChain vs 自己撸框架:选择与组合策略

在工程讨论里,经常会出现这样的问题:要不要用 LangChain?要用到什么程度?要不要自己写一套更轻的 orchestrator?
这一篇不站队,只想从几个维度拆开这件事:LangChain 带来的收益有哪些、潜在代价有哪些,以及在不同规模和阶段的项目里,如何做一个相对务实的选择与组合。

先承认一个事实:LangChain 作为一个通用框架,必然是「大而全」的:

  • 支持多种模型厂商、多种向量库、多种存储与工具;
  • 提供 RAG、工具调用、Agent、多步链路、观测等一整套抽象。

这意味着:

  • 在需要这些能力时,可以直接拿现成的组件来拼;
  • 在只需要非常简单功能时,引入整个框架可能显得有点「杀鸡用牛刀」。

在做选择前,比较重要的一点是先评估清楚:

  • 当前项目到底需要多少「跨组件组合」能力;
  • 对未来扩展和演进的预期有多强。

从前几篇拆出来的内容,可以归纳出几个主要收益点:

  • 抽象出一组通用模块
    • Model、PromptTemplate、OutputParser、VectorStore、Retriever、Tool、Agent、Runnable 等;
    • 让这些东西成为可以组合与替换的「积木」。
  • 提升可观测性与可调试性
    • 在链路中的每一步前后挂钩子,记录 prompt、输出、检索命中、时延、错误等;
    • 为后续评估、重放、A/B 提供基础设施。
  • 降低「换底层」的成本
    • 换模型供应商、换向量库、换存储后端,通常只需要动「适配层」和构造部分;
    • 上层业务链路可以保持稳定。
  • 提供一套「共识化的架构语言」
    • 团队内部交流时,可以直接说「这里是一个 RAG Retriever」「这里有一个 Tool + Agent」「这里是一条 Runnable 链」,避免每个项目各讲各话。

这些收益,在项目进入「需要持续演进和多次迭代」阶段时会更明显。

引入 LangChain 也并非没有成本,常见的代价包括:

  • 学习与心智负担
    • 团队成员需要理解框架的核心抽象;
    • 对已有架构有一定「侵入性」,需要调整原有代码层次。
  • 调试路径变长
    • 出现错误时,需要区分是业务逻辑问题、模型问题,还是框架使用方式问题;
    • 对不熟悉框架的同学,排查成本会更高。
  • 版本演进带来的不确定性
    • 框架自身在快速演进时,可能会有 API 调整或推荐写法变化;
    • 项目需要在「跟进新版本」和「锁定稳定版本」之间做平衡。

在做决策前,需要把这些潜在成本和预期收益一起放在桌面上评估。

有一些类型的项目,框架带来的收益往往会压过成本:

  • 多数据源 + 多种检索方式的 RAG 系统
    • 需要同时对接文件、Wiki、数据库、多种向量库;
    • 需要在不同场景下调整 Retriever 组合与权重。
  • 需要复杂工具调用和 Agent 能力
    • 有多类业务工具(API、DB、脚本)需要暴露给模型;
    • 决策路径复杂、需要多步规划与回溯。
  • 中长期演进的「平台型」项目
    • 不是一次性脚本,而是一个长期演进的应用/平台;
    • 预计会频繁尝试不同 prompt、不同链路、不同评估指标。

在这些场景中,LangChain 带来的「组合能力 + 观测能力 + 生态支持」往往能明显缩短迭代时间。

同样也有不少项目,其实不需要一上来就引入完整框架:

  • 单模型、单数据源、单场景的小工具
    • 比如一个只对接某个内部 API 的问答 Bot;
    • 或者一个本地脚本,帮忙批量生成某类文案。
  • 已存在成熟架构,只是加一点「模型能力」
    • 原有系统已经有清晰的数据层、服务层、控制层;
    • 只是在某个步骤调用一次模型做补全/分类/打分。

在这些情况下,更推荐:

  • 先为模型调用写一个简单的适配层和少量工具函数;
  • 明确输入输出、日志打点与错误处理;
  • 把复杂度控制在当前需求范围内。

如果后续需求增长,再逐步考虑引入 LangChain 的某些模块,而不是一口气把整个框架搬进来。

在实践中,一个较为稳妥的路线是:

  • 业务层只依赖「自定义服务接口」,不直接依赖 LangChain 具体模块
    • 比如定义一个 QuestionAnsweringServiceCodeReviewServiceSearchService
    • 内部实现可以用 LangChain 组合出 RAG/Agent 链,也可以是自写 pipeline。
  • LangChain 作为「实现细节」存在于某个子模块中
    • 这样一来,即便未来决定用其他框架(如 LlamaIndex、Semantic Kernel)或自研方案替代,只需替换实现层;
    • 上层业务无需感知底层 orchestrator 的变化。

这种组合策略可以:

  • 既享受 LangChain 的组合与观测能力;
    +- 又避免让整个项目「紧耦合」在某一个框架之上。

可以用几句话结束这一篇:

  • 「用 LangChain」和「自己撸一层」并不是互斥关系,关键在于如何分层
    • 业务逻辑层关注的是「要完成什么任务」;
    • 模型调用层可以选择用 LangChain 或自研 orchestrator 实现;
    • 底层模型/向量库/数据源层则由适配模块统一封装。
  • 在需求简单、迭代压力不大时,轻量封装往往更直接;
  • 在需求复杂、需要频繁实验和多种组合时,引入 LangChain 这类框架则更能发挥优势。

真正值得投入精力的,是弄清楚当前项目在哪里、未来可能走向哪里,然后在合适的层次里引入合适程度的抽象,而不是简单地在「要不要用 LangChain」上做二元选择。