放弃LangChain后,我们的AI Agent开发效率提升了3倍:聊聊框架选型的血泪教训

在这里插入图片描述

在AI Agent开发领域,LangChain曾是无数团队的首选框架。2023年初,我们Octomind团队也跟风采用了这款当时风头正劲的工具,用它搭建多LLM驱动的AI Agent,实现Playwright端到端测试的自动生成与修复。彼时的LangChain组件丰富、社区活跃,还承诺"让开发者从想法到代码只需一个下午",听起来完美契合我们的需求。

但经过12个月的生产环境实战,我们最终在2024年彻底移除了LangChain。这个决定并非一时冲动,而是无数次调试、妥协与反思后的必然选择。放弃框架后,我们用模块化构建块重构了代码,不仅让代码库变得简洁清晰,团队的开发幸福感和迭代速度也实现了质的飞跃。今天,我想分享这段经历背后的故事、我们踩过的坑,以及对AI应用开发框架选型的深度思考。

初识LangChain:从惊艳到失望的12个月

2023年,AI Agent技术还处于快速迭代期,市面上成熟的开发工具寥寥无几。LangChain凭借其一站式解决方案脱颖而出,它整合了LLM调用、提示词管理、工具链集成、向量数据库对接等核心功能,几乎覆盖了AI应用开发的全流程。对于当时急于验证产品思路的我们来说,这样的"全能框架"无疑是救命稻草。

初期的开发体验确实如宣传般顺畅。我们借助LangChain的现成组件,快速搭建了第一个版本的测试生成Agent。不需要关心不同LLM的API差异,不用手动处理提示词模板和输出解析,框架已经封装好了所有细节。那段时间,我们得以集中精力优化业务逻辑,比如测试用例的发现规则、Playwright代码的生成质量,产品原型很快就达到了可演示的状态。

但随着产品需求逐渐复杂,LangChain的蜜月期也戛然而止。我们开始需要更灵活的Agent架构:比如让主Agent能动态生成子Agent并协同工作,让多个专业Agent之间实现信息交互,或者根据LLM的输出结果动态调整可用工具集。这时我们发现,LangChain的高-level抽象开始成为束缚。

为了实现这些定制化需求,我们不得不深入LangChain的内部源码。但这款框架的设计理念就是"隐藏细节",很多底层逻辑被层层抽象包裹,想要修改某个行为往往需要改动多处关联代码。有一次,我们只是想在Agent执行工具后增加一个自定义的日志记录步骤,却花了整整三天时间梳理清楚LangChain的执行流程,最后不得不通过修改框架源码的方式实现需求,这显然违背了框架"降低开发成本"的初衷。

更令人困扰的是,LangChain的抽象层时常出现"过度设计"的问题。一个简单的功能,用原生API几行代码就能实现,用LangChain反而需要引入多个额外的抽象概念,写更多的样板代码。这种"为了抽象而抽象"的设计,在产品迭代后期逐渐成为开发效率的绊脚石。

抽象层的陷阱:LangChain的核心痛点

LangChain的核心问题,在于其抽象设计与AI应用开发的实际需求存在根本性矛盾。好的抽象应该简化开发、降低认知负担,但LangChain的抽象却往往适得其反,这一点在我们的实际开发中体现得淋漓尽致。

过度抽象导致代码复杂度飙升

我们以一个简单的"英文转意大利语"功能为例,对比原生OpenAI API和LangChain的实现方式。

用原生OpenAI包的代码非常直观:导入OpenAI类,创建客户端实例,构造消息列表,调用API并获取结果。整个过程只有一个类和一次函数调用,剩下的都是标准Python语法,任何有基础的开发者都能一眼看懂。

而LangChain的实现则完全不同:需要导入ChatOpenAI、ChatPromptTemplate、StrOutputParser三个类,先定义提示词模板,再创建输出解析器,最后用LangChain自定义的LCEL语法(通过重载Python的|运算符)构建链条,才能完成同样的功能。

表面上看,LangChain的代码似乎更"规整",但实际上却引入了三个不必要的抽象概念:Prompt templates(提示词模板)、Output parsers(输出解析器)、Chains(链条)。这些抽象没有带来任何实际收益,反而让代码量增加、逻辑变绕。对于生产环境来说,每多一个抽象层,就多一层调试难度,一旦出现问题,开发者需要先理解框架的抽象逻辑,再定位问题所在,大大增加了排障成本。

更糟糕的是,LangChain习惯于在抽象之上再叠加抽象。比如它的Agent类本身就依赖Chains、Tools、Memory等多个抽象组件,而每个组件内部又有自己的抽象逻辑。这导致我们在使用时,常常需要在嵌套的抽象层级中来回穿梭,才能搞清楚一个简单功能的实现路径。调试时,动辄几百行的框架内部调用栈,让我们耗费大量时间在理解框架代码上,而非解决业务问题。

灵活性缺失,难以适配复杂需求

AI应用开发的核心特点是"快速迭代"和"需求多变",尤其是在Agent领域,新的交互模式、架构设计层出不穷。但LangChain的抽象层过于僵化,难以适配这些动态变化的需求。

我们曾尝试将单一的顺序型Agent架构,升级为更灵活的多Agent协作架构。比如让一个主Agent负责拆解任务,然后 spawn 多个子Agent分别处理不同的子任务,最后汇总结果。但LangChain的Agent类本质上是一个封闭的执行流程,不支持动态生成子Agent,也没有提供Agent之间通信的原生机制。我们不得不通过各种"hack"手段绕过框架限制,比如用外部存储模拟Agent状态共享,这不仅增加了代码复杂度,还引入了很多潜在的bug。

另一个典型场景是动态调整Agent的可用工具。我们的业务需求是,根据LLM的输出结果和特定业务逻辑,实时增减Agent能调用的工具集。但LangChain的Agent在初始化时就固定了工具列表,运行时无法动态修改,也不支持外部观察Agent的内部状态。最终,我们不得不放弃这个需求,将功能简化为LangChain能支持的形式——这无疑是框架限制了产品的进化。

好的框架应该是"赋能者",而不是"束缚者"。就像requests库对http.client的封装,通过合理的抽象简化了API调用流程,让开发者用更少的代码实现更多功能。而LangChain的抽象则是"反向赋能",用更复杂的方式实现简单的功能,完全违背了抽象的初衷。

框架迭代与业务需求的脱节

AI和LLM领域的技术迭代速度极快,几乎每周都有新的概念、新的模型、新的最佳实践出现。作为一个早期框架,LangChain的抽象设计很难跟上这些变化。

LangChain的核心组件在设计时,基于的是2022-2023年的AI技术现状。但随着多模态模型、函数调用增强、RAG优化等技术的快速发展,很多早期的抽象设计已经过时。比如它的Output parsers最初是为处理文本输出设计的,当我们需要处理多模态模型的图片输出时,就不得不重新编写大量适配代码。

更麻烦的是,LangChain的版本更新常常带来不兼容的变更。我们曾多次遭遇框架升级后,原有代码无法运行的情况。由于框架封装了太多底层细节,我们无法提前预判这些变更的影响,每次升级都需要投入大量时间进行适配。这对于需要快速响应市场的产品来说,无疑是巨大的拖累。

跳出框架思维:AI应用开发的另一种可能

放弃LangChain后,我们面临一个关键问题:没有了框架,该如何构建AI Agent?经过一段时间的探索,我们发现,大多数AI应用其实根本不需要复杂的框架,用模块化的构建块同样能高效开发,甚至更加灵活。

AI应用的核心组件其实很简单

LangChain用长长的组件列表,营造了一种"AI应用开发很复杂"的错觉。但实际上,大多数AI应用所需的核心组件非常简洁:

  1. LLM通信客户端:用于和各种大模型交互,比如OpenAI、Anthropic的官方SDK,或者开源模型的调用库。
  2. 函数/工具集:用于让Agent具备实际操作能力,比如文件处理、API调用、数据库查询等。
  3. 向量数据库:用于RAG(检索增强生成)功能,存储和查询知识库。
  4. 可观测性平台:用于追踪Agent的执行流程、评估输出质量、调试问题。

除此之外的其他功能,要么是这些核心组件的辅助工具(比如文本分割、嵌入生成工具),要么是常规的应用开发任务(比如数据持久化、缓存管理、文件处理)。这些功能都可以通过轻量的第三方库或自定义代码实现,完全不需要依赖庞大的框架。

我们用这种思路重构了代码:用OpenAI的官方SDK直接调用模型,用自定义的简单类封装工具集,用Pinecone作为向量数据库,用LangSmith(虽然来自LangChain团队,但可以独立使用)做可观测性。重构后的代码库体积减少了40%,执行速度提升了25%,更重要的是,每个部分的逻辑都清晰可控,再也不用为了适配框架而妥协需求。

无框架开发的优势:灵活、可控、易迭代

可能有人会质疑:没有框架,初期开发速度会不会变慢?确实,相比于直接套用LangChain的现成组件,从零搭建工具链需要更多的前期投入,比如需要自己处理不同LLM的API差异,自己实现简单的提示词管理逻辑。但这种投入是一次性的,而且带来的长期收益远大于短期成本。

首先是灵活性极大提升。我们可以根据业务需求,自由设计Agent的架构和执行流程,而不用被框架的固定模式束缚。比如现在我们可以轻松实现动态工具调整、多Agent协作、子Agent生成等复杂功能,这些在LangChain中几乎是不可能完成的任务。

其次是代码可控性增强。每个组件都是我们自己选择或实现的,我们完全理解其内部逻辑,出现问题时能快速定位并修复。调试时,调用栈简洁清晰,再也不用在框架代码中"大海捞针"。

最后是迭代速度加快。没有了框架的限制,我们可以快速尝试新的技术和思路。比如当出现新的大模型时,我们只需集成其官方SDK,就能快速替换原有模型;当需要优化RAG流程时,只需修改向量数据库相关的代码,不会影响其他模块。这种模块化的架构,让我们的产品能够快速响应技术变化和市场需求。

当然,无框架开发并不意味着"拒绝一切封装"。我们会对常用功能进行简单的封装,比如将LLM调用逻辑封装成一个通用函数,将提示词模板存储在配置文件中。但这种封装是轻量级的、透明的,完全服务于业务需求,而不是为了遵循框架的设计规范。

什么时候才需要框架?

经过这段经历,我们对AI应用开发框架的选型有了更清晰的认知:框架并非不可或缺,关键在于产品的发展阶段和需求复杂度。

对于早期原型验证阶段,LangChain这类框架确实能发挥作用。这个阶段的核心目标是快速验证想法,不需要考虑复杂的定制化需求,框架的现成组件可以帮助开发者节省大量时间,快速做出可演示的产品。

但当产品进入生产阶段,或者需求变得复杂时,框架的弊端就会逐渐显现。这时,模块化的构建块方案会更加合适,它能提供更好的灵活性、可控性和可扩展性,支持产品长期迭代进化。

另外,如果你的应用场景非常简单,比如只是简单的LLM调用、提示词模板管理,没有复杂的Agent逻辑,那么LangChain也可以作为一个轻量工具使用。但如果涉及到多Agent协作、动态工具调整、复杂流程控制等高级功能,建议尽早放弃框架,采用自定义架构。

模块化构建块:我们现在的开发模式

放弃LangChain后,我们采用了"模块化构建块"的开发模式,这种模式让我们的团队效率提升了3倍,产品迭代速度也显著加快。具体来说,我们的架构包含以下几个核心部分:

核心构建块:独立、可替换的组件

每个核心功能都被设计成一个独立的模块化组件,组件之间通过简单清晰的接口通信,互不依赖。

  1. LLM适配层:我们封装了一个统一的LLM客户端,内部适配不同厂商的模型(OpenAI、Anthropic、Gemini等)。这个客户端提供统一的调用接口,上层业务代码无需关心底层使用的是哪个模型,切换模型时只需修改配置文件。
  2. 提示词管理模块:我们没有使用LangChain的Prompt templates,而是用简单的Python字典存储提示词模板,支持动态填充参数。同时,我们将提示词版本化管理,方便追踪迭代历史,回滚到最优版本。
  3. 工具集模块:每个工具都是一个独立的类,实现统一的run方法。Agent可以根据需求动态加载或卸载工具,工具的输出结果也采用标准化格式,方便Agent解析处理。
  4. 向量数据库模块:封装了向量数据库的增删改查操作,支持不同向量数据库(Pinecone、Weaviate等)的无缝切换。同时集成了文本分割、嵌入生成等辅助功能,形成完整的RAG工具链。
  5. 可观测性模块:集成了日志记录、流程追踪、结果评估等功能。每个Agent的执行过程都会被详细记录,包括输入输出、工具调用记录、LLM响应时间等,方便我们快速定位问题、优化性能。

这种模块化设计的最大优势是"可替换性"。每个组件都可以根据业务需求或技术发展,随时替换为更合适的实现。比如当有新的向量数据库出现时,我们只需实现新的适配类,就能替换掉旧的数据库,不需要修改上层业务代码。

Agent架构:轻量核心+灵活扩展

我们的Agent核心非常简洁,只负责三个核心功能:任务解析、工具选择、结果整合。没有复杂的内部状态管理,也没有固定的执行流程,而是通过配置文件和外部规则,动态调整Agent的行为。

比如在多Agent协作场景中,主Agent会根据任务类型,动态生成对应的子Agent。每个子Agent都有自己的工具集和提示词模板,完成任务后将结果返回给主Agent,主Agent再进行汇总整理。这种架构完全基于业务逻辑设计,没有受到任何框架的限制。

在动态工具调整方面,我们通过外部规则引擎实现需求。Agent在执行任务时,会根据当前的任务状态和LLM的输出结果,查询规则引擎,获取当前可用的工具列表。这种方式不仅灵活,而且易于维护,规则的修改不需要重启服务,直接生效。

开发流程:快速迭代+持续优化

模块化架构让我们的开发流程变得更加高效。我们采用"小步快跑"的迭代模式,每个迭代周期只聚焦于一个核心功能的优化,由于组件之间低耦合,修改一个模块不会影响其他部分,大大降低了迭代风险。

同时,我们建立了完善的测试体系。每个模块化组件都有独立的单元测试,确保其功能正确性;Agent的核心流程有集成测试,验证组件之间的协作是否顺畅;生产环境中,我们通过可观测性模块收集数据,持续监控Agent的运行状态,发现问题及时优化。

这种开发模式,让我们能够快速响应市场变化和用户反馈。比如有用户提出需要支持特定类型的测试用例生成,我们只需新增一个对应的工具类和提示词模板,就能快速实现这个功能,整个过程不到一天就能完成。

总结:框架是工具,不是信仰

回顾这段放弃LangChain的经历,我们最大的收获不是找到了解决AI Agent开发的"银弹",而是明白了一个道理:框架是工具,不是信仰。选择框架的核心标准,应该是它能否解决你的实际问题,能否提升开发效率,而不是它的知名度或社区热度。

LangChain在特定场景下确实有其价值,比如快速原型验证、简单场景开发。但对于需要长期迭代、需求复杂的生产级应用来说,它的过度抽象和灵活性缺失,会逐渐成为发展的瓶颈。这时,放弃框架,采用模块化的构建块方案,反而能让开发更高效、产品更灵活。

当然,这种选择并非适合所有团队。如果你的团队规模较小、技术储备有限,或者产品处于早期阶段,LangChain这类框架依然是不错的选择。但如果你的团队有一定的技术能力,且产品需要长期迭代进化,那么提前规划模块化架构,或许能让你少走很多弯路。

AI技术的发展速度远超想象,未来可能会出现更优秀的开发框架,也可能模块化开发会成为主流。但无论技术如何变化,"以业务需求为核心,选择最适合的工具"这个原则永远不会过时。希望我们的经历能给正在进行AI应用开发的你,带来一些有价值的参考。

最后,如果你正在纠结是否使用LangChain,或者想搭建模块化的AI Agent架构,不妨从最小化的原型开始尝试。先用框架快速验证想法,当需求变得复杂时,再逐步拆解模块,迁移到自定义架构。这种渐进式的过渡方式,既能保证开发效率,又能降低转型风险。毕竟,适合自己产品的,才是最好的开发方案。

英文原文链接:
https://octomind.dev/blog/why-we-no-longer-use-langchain-for-building-our-ai-agents

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小程故事多_80

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值