news 2026/4/3 4:52:07

LangChain框架利弊分析:大模型应用开发是否真的需要框架?

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
LangChain框架利弊分析:大模型应用开发是否真的需要框架?

简介

文章探讨了LangChain框架在大模型应用开发中的适用性。作者指出框架存在的意义在于封装重复劳动、沉淀最佳实践和统一代码风格,但同时也指出盲目引入框架可能带来的问题。通过对LangChain的API设计分析,作者认为其存在不一致且冗长的问题,容易掩盖底层逻辑,增加理解难度。文章建议开发者在简单场景下优先考虑原生SDK实现,只有在需要复杂任务调度和编排时才考虑使用框架。


需要提前说明,存在广义和狭义两类对LangChain的定义。狭义上的LangChain即等同于在本章中我们使用到的LangChain框架,而广义上的LangChain代指的是LangChain技术厂牌,旗下包含 LangChain、LangSmith(一个用于调试、测试、监控大模型应用的平台)、LangGraph(一款用于制作包含管理复杂工作流的大模型应用的框架) 等多种产品。本小节所谈论到各种问题仅限于LangChain 框架本身而非代指所有与它有关的产品。

为什么我们需要框架

既然在第4章中我们已经借助OpenAI SDK完成了想要实现的功能,为什么还需要引入额外的代码库?在我看来框架以及类库存在最根本的意义,是对重复劳动的封装

Loadsh是所有前端项目内必不可或缺的类库,它之所以被广泛采用并非因为其中的某个高精尖的技术特性,而是提供了许多常用开箱即用的功能,例如对数组去重、合并,对数据类型进行判断等等。去实现这类工具类函数并非什么难事,那为什么我们选择直接使用一款第三方类库而非是亲自去实现它?很简单,因为这能够帮助你节省大量的时间精力——对于此类功能你我的代码实现,乃至 Lodash 的代码实现不会有太大差异,在最终效果一致的情况下,考虑到专业的开源团队有足够的精力对代码提供稳定的持续保障,选择它们自然也就是顺理成章的事情。另一方面绝大部分的开发者在实际工作中承担的是以业务向导开发任务,能够编写工具代码的时间精力有限,市面上开箱即用的现成工具也就成了我们的不二之选。这便是是大多数框架之所以存在的底层逻辑。

除此之外,框架的另一层价值在于它代表对经验的沉淀,对模式的封装

平心而论,在任何编程语言之下去实现一整套API服务并非难事,但为什么倾向去选择既有的API服务框架,例如Node.js里Express.js或者Python中的FastAPI?一分部原因来自于上述所说对时间精力的节省,更重要的是,尊循框架本身也等同于尊循最佳实践。

代码是有好坏之分的,我们所常常听到的可读性、时间效率、可拓展性等等便是区分好与坏的重要指标。那些能够带来好结果的行为通常被人们逐渐整理为最佳实践,而那些带来坏影响的行为则被称之为反模式或者坏味道。遗憾的是这类知识点的习得大部分来自于开发经验的积累,可如果团队中不同的成员水平参差不齐怎么办?那么很可能具有坏味道的代码便被不小心的注入代码库中——而框架则通过将开发者的代码限制在既定的约束内,杜绝了部分该类问题的发生。MVC(Model-View-Controller) 框架便是一个再合适不过的例子,你也许并不清楚 MVC 模式解决了什么样的问题,但该知识盲点并不妨碍你可以将代码拆分为不同的Model、View和Controller组件。如果你好奇 MVC 是否真的相比其他开发方式更加优秀,不妨尝试摒弃MVC框架并利用原生代码实现同样的一组功能,并不断的优化它。我相信在几个迭代之后,你摸索出来的最优解会与MVC不谋而合。

为什么我们需要推崇最佳实践?因为上面所说的种种关于代码“好”的指标,都指向软件工程的最终目的:**提升代码的可维护性。倘若你继续探究,会发现它代表的不过是最朴素的降本增效思想,通过使代码变得易于修改,来降低维护的维护成本以及提升其交付速率。**而最佳实践是达成这个目标的重要途径。

提升代码可维护性的另一个手段也同样是框架带来的第三类优势:统一团队代码风格。如果你让十位来自不同背景不同经验的程序员来实现同一组功能,你会得到十套不同类型的代码。虽然独一无二的代码对于个体来说代表着他颇具个性的一面,但来对于由一个团队集体维护的项目来说却是噩梦,因为这意味着其中的每一位团队成员为了理解他人所写的代码,都要提前了解其他团队成员的代码风格和流派,这会给项目的开发过程带来不小的负担。所以让团队站在同一起跑线上,对尽可能能多的问题达成一致,有助于将代码知识传递下去。最理想的情况便是由不同成员的产出的代码都犹如同一人所写。框架是解决此类问题的一个手段,另一类常见实践便是在代码库甚至IDE中内置格式检查工具。

综上所述,节省开发成本、封装最佳实践、统一代码风格是我们优先选择框架的原因,其旨在提升代码的可维护性。扩展到更广的层面,这套逻辑同样适用于我们依赖的各类云服务。从无服务计算(Serverless Computing)再到低代码平台(Low Code Platform)——技术并非凭空被发明出来,他们是经验的化身。

何谓好的框架

GitHub上的收藏数量、代码库的更新频率、版本的发布速度等等显性指标,当然都可以成为判断的开源框架的好坏标准。而在数值之外还有什么是我们值得关注的?这里给出两点我的建议。首先,最好的框架理应是没有框架。

许多项目在搭建之初出于惯性,优先想要回答的问题是选择哪一款框架而不是我们是否需要框架,这给项目带来了不必要的负担。许多人忽略了框架的引入是存在代价的,学习成本便是其中之一。回想一下你第一次熟悉某个技术框架时的经历,肯定充满坎坷:去学习定义不同类型的组件,学习如何进行组件间的通信,在论坛上提问如何实现你想实现的功能等等。问题不在于代价本身,而在于付出与收益是否等价。在我的工作经历中,框架带来的负面影响的事例不在少数,例如团队经理盲目选择了某个时髦框架,却因为没有团队成员精通该框架的缘故,导致开发中总是有代码被分配到了错误的职责,或者采用了官方不推荐的反模式。又例如开发人员还需定期对框架进行升级。注意此类升级并非是对开发者无感的,因为框架自身升级过程中难免会引入破坏性修改,这会导致项目代码与框架的集成失效。因此由框架升级而引发的项目本身的代码改动和小范围的回归测试都在所难免。这些都应该计算在引入框架的成本中。

其次,好的框架应该容易让人们把事情做对,难以把事情做错。

如果你选择的框架团队内鲜有人能够理解它的概念,更很少有人难把它按照最佳实践写对,这并非是一个好兆头。无论它号称能够提升多少倍性能或者减少多少人天的成本,显而易见至少在你的团队是可望不可及的。项目说到底是由一群人来维护,我们应该尽可能的降低项目的门槛用于容纳不同层次的开发者。如果项目的绝大部分问题都依赖团队的某个明星程序员来解决,亦或是项目质量完全依靠团队经理来把控,你应该为对此感到警惕。

前端领域中的Redux就是一个很好的反面例子,如果你有兴趣将Redux文档与当下同样流行的 Flux 框架文档进行比较(例如 Mobx,Zustand,Akita),就会发现学习Redux需要掌握的概念相比其他竞品来说复杂的令人发指,稍不小心便会踏入官方不推荐的反模式中。这也是Redux Toolkit诞生的原因,它旨在解决原生Redux高度的抽象以及缺少最佳实践的问题,通过丰富模板代码来帮助开发者迅速找到常规问题的解决方案。如今官方早已将Redux Toolkit作为学习和使用Redux的首选平替。

你也许会疑惑为什么我们要花如此长的篇幅聊框架决策中的种种考量,因为接下来你将看到我是如何运用这些原则来选择出我们心仪的大模型框架的。

你也许不需要框架

在回答选 A 还是选 B 之前,我还是想不厌其烦的提醒各位:也许你并不需要框架。我们不妨回顾以一下第四章中借助OpenAI SDK实现与大模型进行对话的代码示例,代码如下所示

from openai import OpenAI from dotenv import load_dotenv load_dotenv() client = OpenAI() completion = client.chat.completions.create( model="gpt-4o-mini", messages=[ {"role": "system", "content": "You are a helpful assistant."}, { "role": "user", "content": "What's your name?", } ] )
我们可以轻松的将这段代码使用其他框架进行改写,使用 LangChain重写之后的代码如下所示:
from langchain.prompts \ import SystemMessagePromptTemplate, \ HumanMessagePromptTemplate, \ ChatPromptTemplate from langchain_openai import ChatOpenAI llm = ChatOpenAI(model_name="gpt-3.5-turbo", temperature=0.5) prompt = ChatPromptTemplate.from_messages([ SystemMessagePromptTemplate.from_template("You are a helpful assistant."), HumanMessagePromptTemplate.from_template("What's your name?") ]) chain = prompt | llm
即使你从未学习过LangChain,也不妨碍你理解这段代码的逻辑。与原版相比其最大的不同在于将传递给 大模型的消息使用模板组件进行了封装,原代码中的 SystemMessage HumanMessage SystemMessagePromptTemplate和 HumanMessagePromptTemplate

例如在实际的使用场景中,”You are a helpful assistant” 这类用于指定角色的提示语通常是固定的,我们便可以选择利用模板固化下来,将用户的输入提取为变量。依据上述思路修改之后的代码如下所示:

prompt = ChatPromptTemplate.from_messages([ SystemMessagePromptTemplate.from_template("You are a helpful assistant"), HumanMessagePromptTemplate.from_template("{user_input}") ])
注意上述代码中用户的提问内容已经被替换为了变量 user_input
chain = prompt | llm res = chain.invoke({ "user_input": "Explain LLM like I'm 5" })
在这个例子里,我展示了LangChain在提示语生成方面能够提供的能力,但我想提出的问题是,这个特性真的是你需要的吗?所有OpenAPI中的概念被平移到了LangChain当中被再次定义,以 |

我的建议是,如果你的应用针对的是单一场景,无需灵活多变的提示语句,便不必将提示语句封装为模板。即使你想将提示语句抽象为模板,框架并非是唯一的方式。Python 原生自带的 f-string 语法据支持将表达式内嵌于子符串中,如下所示,人名被提取为变量。

user_name = "Alice" greeting = f"""Hello {user_name}, welcome to the data science tutorial!"""
如果你不确定框架会给你带来何种优势,盲目的将其引入便会产生我在上一小节中提到的那些弊端。在上述代码中你已经看到,种种大模型概念在LangChain中被再次封装,却看不到由此带来的额外收益。事实上OpenAI作为开放平台,它本身就已经提供了足够多的接口来完成大部分常见需求。考虑到OpenAI SDK作为官方出品的类库,它们更新频率和更新质量肯定会比由社区维护的开源类库更加稳定,因此优先使用第一方类库也是项目质量的无形保障。

我越来越多的在有关大模型应用开发的论坛中,在Hacker News社区里看到开发者们在逐渐达成此类共识:大多数时候你无需依赖框架来开发大模型应用。框架的优势体现原型的搭建、任务的调度与编排上。

为什么不推荐 LangChain

无论是OpenAI还是Google Gemini,官方自身提供的能力始终存在着上限,我们需要在社区中寻找突破点。

毋庸置疑LangChain是时下风头最劲的框架之一,我相信在你能够搜索到的有关大模型应用开发的教程中,与LangChain有关的课程一定占据了相当大的比例。但你可能没有留意到的是,近些年业内对于LangChain的批评声音却变得越来越多,LangChain的颓势在愈发显现。

最直观的便是Thoughtworks技术雷达(Technology Radar)对于 LangChain 态度的变化。技术雷达是科技领域咨询公司Thoughtworks每年两次定期发布的技术趋势指南。在每一期发布的指南中他们会对新兴技术的成熟度与潜力进行打分,读者可以将技术所属的成熟度状态(如试验、评估、采纳、淘汰)来作为技术选型的参考之一。LangChain于2023年4月入选第28期技术雷达,成熟度状态为“评估”;在2024年4月第30期技术雷达中成熟度则被降至“暂缓”,即不推荐在项目上引入;在2024年10月第31期技术雷达中 LangChain被彻底移除。LangChain 被淘汰的理由在它的评级被降至“暂缓”时给出了充分的说明:

……然而,我们还发现其存在 API 设计不一致且冗长的情况。因此,它经常会掩盖底层实际发生的情况,使得开发者难以理解和控制 LLMs 及其周围的各种模式在背后实际是如何工作的……

这里所说的API并非是狭义上的HTTP API,而是指广义上代码间的通信接口。考虑到API是代码与框架的主要沟通方式,欠佳的 API 设计意味对开发者而言项目与框架集成之路将变得困难重重。这里的批评也并非空穴来风,接下来我用一个例子来说明 LangChain API 存在的问题。

在提示工程中有一类技巧叫做few shot,即在编写的提示语句中有意包含一些范例,便于大模型更好的推测我们的意图以给出更为精准的答案。例如在向模型询问“big”的反义词之前,在提示语句中提前给出反义词的相关事例,具体提示如下:

Give the antonym of every input

Input: happy

Output: sad

Input: tall

Output: short

Input: energetic

Output: lethargic

Input: sunny

Output: gloomy

Input: windy

Output: calm

Input: big

Output:

大模型在读到诸多事例之后,即刻就会领悟到我们想要简短直接的回答,并且答案必须契合“Input/Output”这类格式。用原生的Python将上述的提示语抽象为代码实现也非难事,实现代码如下所示:

def generate_few_shot_prompt(pairs): prompt = "Give the antonym of every input\n\n" for pair in pairs: input_word = pair['input'] output_word = pair['output'] prompt += f"Input: {input_word}\nOutput: {output_word}\n\n" return prompt
在调用该方法时,只需要将所有事例的input和ouput值组装成字典结构,然后以成数组形式传入函数中即可,代码如下所示:
pairs = [ {"input": "happy", "output": "sad"}, {"input": "tall", "output": "short"}, {"input": "energetic", "output": "lethargic"}, {"input": "sunny", "output": "gloomy"}, {"input": "windy", "output": "calm"}, {"input": "big", "output": ""} ] few_shot_prompt = generate_few_shot_prompt(pairs)
那现在不妨看看在LangChain框架之下应该如何实现上述功能。LangChain few shot这类业务场景提供了名为 FewShotPromptTemplate
from langchain_core.example_selectors \ import LengthBasedExampleSelector from langchain_core.prompts \ import FewShotPromptTemplate, PromptTemplate examples = [ {"input": "happy", "output": "sad"}, {"input": "tall", "output": "short"}, {"input": "energetic", "output": "lethargic"}, {"input": "sunny", "output": "gloomy"}, {"input": "windy", "output": "calm"}, ] example_prompt = PromptTemplate( input_variables=["input", "output"], template="Input: {input}\nOutput: {output}", ) prompt = FewShotPromptTemplate( examples=examples, example_prompt=example_prompt, prefix="Give the antonym of every input", suffix="Input: {adjective}\nOutput:", input_variables=["adjective"], ) print(prompt.format(adjective="big"))
我们对上述代码稍作分析,来理解在 LangChain 中是如何实现上述功能的:
  • 需要在代码库中同时引入PromptTemplateFewShotPromptTemplate模板组件。

  • PromptTemplate

    用于创建常规提示,包含模板内容与变量定义,它与few shot场景无关。

  • FewShotPromptTemplate

    虽然从名称上同为“模板”,但实际上它去更像是原模版的“封装”或者“改善”工具。因为从使用方式上看,它不仅为原模版补充了前缀部分(prefix)和提问部分(suffix),还负责将诸多事例(examples)注入进提示语中。

也就是说为了生成出一个带有特定模式的提示语句,在LangChain中我们需要引入两个模板组件(PromptTemplateFewShotPromptTemplate),定义三个模板变量(PromptTemplate中的inputoutputFewShotPromptTemplate中的adjective),还需要保证事例中数据格式与模板的变量格式相匹配。

很显然这么做过于复杂了,别忘了我们只是想生成一个具有特定模式的字符串而已。在更早的代码中看到我已经展示了如何在无需学习额外知识的情况下,用更短的代码达成同样的效果。

将few shot固化在代码中的做法本来就有待商榷,因为包括few shot、chain of thought、least to most 等等各类提示语技巧,本质上是解决问题的种种思路,它们为代码实现提供了无数种可能性。而将思路固化在框架中的做法似乎是反其道而行之,反而给这个技巧的发挥套上了枷锁。

更可怕的是 LangChain还提供了几乎一模一样的兄弟组件FewShotPromptWithTemplates,仅仅是为了支持将模板作为参数传入,例如我可以将原子符串类型的prefixsuffix变量替换为模板,代码如下所示:

# 在这里 prefix 与suffix 不再是上段代码中简单的子符串, # 而是被定义为可以用于生成提示语的模板 prefix_template = PromptTemplate( input_variables=["say_hi"], template="{say_hi}, Give the antonym of every input\n\n" ) suffix_template = PromptTemplate( input_variables=["adjective"], template="Input: {adjective}\nOutput:" ) few_shot_prompt_with_templates = FewShotPromptWithTemplates( # ...... input_variables=["adjective", "say_hi"], prefix=prefix_template, suffix=suffix_template ) new_input = { "adjective": "big", "say_hi": "Hello" } prompt = few_shot_prompt_with_templates.format(**new_input)
在我看来这是一处明显的API设计失误,正确的做法应该是让组件去兼容更多种可能性(例如前端的DOM 选择器 querySelecor

有几篇对 LangChain 批评的文章影响力颇大,比如 why we no longer use LangChain for building our AI agents 以及 The Problem With LangChain,前者在 Hacker News 上引起了广泛的讨论,后者也被技术雷达所引用。如果大家有兴趣可以通过这些材料来更进一步的理解 LangChain 当前所存在的其他问题。

读者福利:如果大家对大模型感兴趣,这套大模型学习资料一定对你有用

对于0基础小白入门:

如果你是零基础小白,想快速入门大模型是可以考虑的。

一方面是学习时间相对较短,学习内容更全面更集中。
二方面是可以根据这些资料规划好学习计划和方向。

包括:大模型学习线路汇总、学习阶段,大模型实战案例,大模型学习视频,人工智能、机器学习、大模型书籍PDF。带你从零基础系统性的学好大模型!

😝一直在更新,更多的大模型学习和面试资料已经上传带到CSDN的官方了,有需要的朋友可以扫描下方二维码免费领取【保证100%免费】👇👇

👉AI大模型学习路线汇总👈

大模型学习路线图,整体分为7个大的阶段:(全套教程文末领取哈)

第一阶段:从大模型系统设计入手,讲解大模型的主要方法;

第二阶段:在通过大模型提示词工程从Prompts角度入手更好发挥模型的作用;

第三阶段:大模型平台应用开发借助阿里云PAI平台构建电商领域虚拟试衣系统;

第四阶段:大模型知识库应用开发以LangChain框架为例,构建物流行业咨询智能问答系统;

第五阶段:大模型微调开发借助以大健康、新零售、新媒体领域构建适合当前领域大模型;

第六阶段:以SD多模态大模型为主,搭建了文生图小程序案例;

第七阶段:以大模型平台应用与开发为主,通过星火大模型,文心大模型等成熟大模型构建大模型行业应用。

👉大模型实战案例👈

光学理论是没用的,要学会跟着一起做,要动手实操,才能将自己的所学运用到实际当中去,这时候可以搞点实战案例来学习。

👉大模型视频和PDF合集👈

观看零基础学习书籍和视频,看书籍和视频学习是最快捷也是最有效果的方式,跟着视频中老师的思路,从基础到深入,还是很容易入门的。

👉学会后的收获:👈

• 基于大模型全栈工程实现(前端、后端、产品经理、设计、数据分析等),通过这门课可获得不同能力;

• 能够利用大模型解决相关实际项目需求:大数据时代,越来越多的企业和机构需要处理海量数据,利用大模型技术可以更好地处理这些数据,提高数据分析和决策的准确性。因此,掌握大模型应用开发技能,可以让程序员更好地应对实际项目需求;

• 基于大模型和企业数据AI应用开发,实现大模型理论、掌握GPU算力、硬件、LangChain开发框架和项目实战技能,学会Fine-tuning垂直训练大模型(数据准备、数据蒸馏、大模型部署)一站式掌握;

• 能够完成时下热门大模型垂直领域模型训练能力,提高程序员的编码能力:大模型应用开发需要掌握机器学习算法、深度学习框架等技术,这些技术的掌握可以提高程序员的编码能力和分析能力,让程序员更加熟练地编写高质量的代码。

👉获取方式:

😝一直在更新,更多的大模型学习和面试资料已经上传带到CSDN的官方了,有需要的朋友可以扫描下方二维码免费领取【保证100%免费】👇👇

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/3/31 9:03:50

列表操作陷阱:Python索引与修改避坑指南!

列表操作陷阱:Python索引与修改避坑指南 引言 在Python编程中,列表(list)是最灵活、最常用的数据结构之一。[1]然而,正是由于其灵活性和易用性,许多开发者在列表操作中常常陷入各种陷阱。从简单的索引越界到…

作者头像 李华
网站建设 2026/3/30 1:57:44

3个理由告诉你为什么《韭菜的自我修养》是投资新手的必读宝典

3个理由告诉你为什么《韭菜的自我修养》是投资新手的必读宝典 【免费下载链接】韭菜的自我修养电子版资源介绍分享 《韭菜的自我修养》电子版资源介绍本仓库提供《韭菜的自我修养》一书的电子版资源下载,包括PDF、MOBI和EPUB格式,方便读者在不同设备上阅…

作者头像 李华
网站建设 2026/3/30 23:45:59

数据挖掘学习新纪元:韩家炜第四版PPT课件完整指南

数据挖掘学习新纪元:韩家炜第四版PPT课件完整指南 【免费下载链接】数据挖掘概念与技术韩家炜第四版PPT课件全 《数据挖掘:概念与技术》韩家炜第四版 PPT 课件,完整覆盖原书12章内容,专为数据挖掘学习者设计。课件基于2022年最新版…

作者头像 李华
网站建设 2026/3/24 17:52:43

9、Unix/Linux 系统维护与备份策略全解析

Unix/Linux 系统维护与备份策略全解析 1. 系统信息查看 在日常系统维护中,我们首先要了解系统的基本信息。例如在 10:47 am 时,系统已运行 27 天 50 分钟,有 1 个用户,负载平均值为 0.18、0.26、0.20。 2. syslog 信息解读 一个配置良好的 syslog 是任何 *NIX 系统中最重…

作者头像 李华