1.1 为什么要用LangChain


1.1 为什么要用 LangChain:从手工作坊到装配线

本节摘要:LangChain 是为大模型应用准备的应用开发框架,它把提示管理、链式调用、记忆、检索、工具调用做成标准组件。本节从一个裸调接口的翻车现场出发,讲清"没有装配线"的四种典型痛苦,并给出该不该用它的判断边界。

一次典型的翻车现场

先看一段真实程度很高的代码。某团队要做"客户咨询自动回复",第一版直接裸调模型接口,核心逻辑长这样:

import os from openai import OpenAI # 裸调接口:把所有工序手工揉在一个函数里 client = OpenAI(api_key=os.environ["MODEL_API_KEY"]) history = [] # 用一个全局列表手工维护对话历史 def reply(question: str) -> str: # 工序一:手工拼提示词,字符串越长越难维护 prompt = "你是一名客服。请礼貌回答用户问题。\n" prompt += "\n".join(history[-6:]) # 工序二:手工裁剪历史 prompt += f"\n用户:{question}\n客服:" # 工序三:手工调用、手工取返回值 resp = client.chat.completions.create( model="gpt-3.5-turbo", messages=[{"role": "user", "content": prompt}], temperature=0.3, ) answer = resp.choices[0].message.content # 工序四:手工回写历史 history.append(f"用户:{question}") history.append(f"客服:{answer}") return answer print(reply("你们的退货流程是什么?")) # 输出示例:您好,关于退货流程:自签收之日起7天内可申请退货……

演示当天一切正常。两周后问题集中爆发:历史超过模型上下文上限,半夜接口超时没人重试;产品要求"回答必须附带知识库条款",提示词拼接到三百多行;测试想批量跑两百个用例,发现逻辑全焊死在这个函数里。这就是手工作坊的处境——不是做不出来,而是每加一道需求,胶水代码就厚一层。

四种痛苦,对应四类零件

把上面的现场抽象一下,裸开发的痛苦可以归成四类,LangChain 的模块划分恰好一一对应:

痛苦类型 手工作坊的表现 LangChain 的对应零件
提示词失控 字符串拼接散落各处,改一处漏三处 PromptTemplate 提示模板
流程焊死 调用、解析、重试揉成一团,无法复用 Chain 链与 LCEL 表达式
状态散架 全局变量存历史,多用户立刻串味 Memory 记忆模块
能力封闭 想接知识库、搜索、计算器就得自造协议 Retrieval 检索、Tool 工具、Agent 代理

LangChain 诞生于 2022 年 10 月,作者 Harrison Chase 的初衷很朴素:大家在模型之上反复写着同样的胶水代码,不如把"模型的输入输出"和"应用的工作流"解耦。两年多时间它成了这个领域事实上的零件标准——不是因为框架本身多精巧,而是因为它抢先定义了工位。

装配线视角的一句话定义

LangChain 可以用一句话讲清:它是一条把"模型调用"组织成"生产流程"的装配线,链是传送带,其他一切都是工位。

同一个客服需求,搬上装配线后是这样:

import os from langchain_openai import ChatOpenAI from langchain_core.prompts import ChatPromptTemplate from langchain_core.output_parsers import StrOutputParser from langchain_core.runnables import RunnableWithMessageHistory from langchain_core.chat_history import InMemoryChatMessageHistory # 动力单元:模型只声明一次,换型号改这一行 llm = ChatOpenAI(model="gpt-3.5-turbo", temperature=0.3) # 工艺单:提示词变成带占位符的模板,与代码解耦 prompt = ChatPromptTemplate.from_messages([ ("system", "你是一名客服。请礼貌回答用户问题。"), ("placeholder", "{chat_history}"), ("human", "{question}"), ]) # 传送带:用管道符把工艺单、动力单元、质检规整三道工序锁在一起 chain = prompt | llm | StrOutputParser() # 工序记录本:历史管理交给框架,按会话编号隔离 store = {} def get_history(session_id: str): if session_id not in store: store[session_id] = InMemoryChatMessageHistory() return store[session_id] chat = RunnableWithMessageHistory(chain, get_history, input_messages_key="question", history_messages_key="chat_history") answer = chat.invoke({"question": "你们的退货流程是什么?"}, config={"configurable": {"session_id": "user-001"}}) print(answer) # 输出示例:您好,关于退货流程:自签收之日起7天内可申请退货……

代码行数没有减少多少,但性质变了:提示词是独立零件,可以单独版本管理;历史按会话隔离,多用户不再串味;中间任何一道工序都能替换或测试。这就是"产线"与"作坊"的差别——不是更短,而是可拆、可换、可质检

⚠️ 常见误区:把 LangChain 当"更强的模型调用器"。它不提升模型能力,只组织你的工程。期望它让回答变聪明的项目,通常失望而归。

哪些项目不该上这条装配线

框架有成本,装配线不是免费午餐。三类场景我会劝你别急着用:

  • 一次性脚本:跑一次就扔的数据清洗、单页报告生成,裸调接口五十行解决,引框架反而增加安装与学习负担;
  • 延迟极端敏感的直通场景:一问一答、无历史、无检索的简单封装,中间层越多,排障路径越长;
  • 团队已自研了等价中间层:迁移的收益要和迁移成本对账,别为了简历好看而重构。

反过来,只要你的应用满足"多轮对话、挂知识库、要调外部工具、有评测需求"中的两条以上,装配线的收益就开始压倒成本。第4章的端到端案例会让你看到这条成本曲线的具体形状。

常见问题

问:LangChain 和直接用模型官方库冲突吗?
不冲突。LangChain 的模型类底层就是调用官方接口,官方库更新的能力,通常几周内会被适配进来。可以把 LangChain 理解为包在官方接口外面的一层工位适配器。

问:LangChain、LlamaIndex、AutoGen 怎么选?
侧重不同:LangChain 是通用装配线,零件最全;LlamaIndex 偏重检索与数据索引;AutoGen 偏重多代理协作。主产线选 LangChain、检索密集场景补 LlamaIndex,是工程里常见的组合。

动手验证:算一笔迁移账

拿你手头任何一个裸调模型的小项目,做一次十分钟盘点:数出拼接提示词的位置、维护历史的位置、解析返回值的位置,各有多少处。三处以上,就值得在读完本教程后试一次迁移——这笔账比任何宣传文案都诚实。

下一节我们把整条装配线的零件一次性摊开,给每个工位发一张"铭牌":职责是什么、接口长什么样、在哪个章节会被打开细讲。


作者与出处
原作者: 灏天文库
来源:灏天文库
整理: 灏天文库整理
由灏天文库平台收录,内容或由平台用户上传,仅供学习交流
发布者: 作者: 灏天文库 转发
评论区 (0)
U