LangChain vs LlamaIndex vs DSPy:AI 应用框架选型指南
开篇:一个真实的选型困境
2025 年初,我所在的团队接到一个需求:构建一套企业内部知识库问答系统,要求支持 PDF、Word、网页等多源文档检索,同时还要能调用内部 API 完成「查订单、改库存」这类操作。技术 Leader 在周会上撂下一句话:“你们看看 LangChain 能不能搞定?不行就换个框架。”
三个月后,我们完成了四轮技术验证——从 LangChain 到 LlamaIndex,再到 DSPy,最终三个框架各有用途。这段经历让我深刻认识到:AI 应用框架没有银弹,选型的关键不是谁功能多,而是谁最贴合你的问题形态。
本文将从实际开发视角出发,系统对比 LangChain、LlamaIndex、DSPy 三大框架的定位差异、核心设计哲学、代码实战和适用场景。我不会照搬官网文档,而是结合团队真实的踩坑经验,帮你避开「选错框架、重构三次」的悲剧。
三大框架的定位差异
在深入代码之前,先搞清一个关键问题:这三个框架从根源上解决的是不同类型的问题。
| 维度 | LangChain | LlamaIndex | DSPy |
|---|---|---|---|
| 核心问题 | 如何将 LLM 与外部工具/数据串联成复杂工作流 | 如何高效地从非结构化数据中检索信息并生成回答 | 如何用少量标注自动优化 prompt 和 pipeline |
| 抽象层级 | 中等(链 + 工具 + Agent) | 低到中(索引 + 检索器 + 查询引擎) | 高(声明式程序,编译器自动优化) |
| 典型场景 | Agent 工作流、多步骤推理、工具调用 | 企业知识库、文档问答、SQL 查询 | 复杂 prompt 调优、多步推理优化、评测驱动开发 |
| 学习曲线 | 中等(模块多但文档完善) | 较平缓(概念集中,API 直观) | 较陡(需要理解编译器和优化器概念) |
| 灵活性 | 高(模块化设计,可自由组合) | 中等(索引驱动,自由度受限) | 极高(程序即 pipeline,编译器自动优化) |
理解这些差异后,你会发现一个有趣的事实:很多团队之所以觉得 LangChain"太重",其实是在用 Agent 框架做检索任务——这就像用 React 写静态网页,不是框架的错,是选型错了。
LangChain:将 LLM 打造成编排引擎
核心设计哲学
LangChain 的本质是链式编排。它的核心抽象是Chain:一段带有输入输出的可组合逻辑。你可以把多个 Chain 串联起来,形成一个端到端的工作流——Prompt → LLM → Output Parser → Tool → LLM → Output。
从 v0.1 到 v0.3,LangChain 经历了痛苦的 API 重构。最显著的变化是引入了LangGraph:一个有向图模型,彻底取代了旧版AgentExecutor。我现在推荐的 LangChain 最佳实践就是:用 LangGraph 定义工作流,用 LangChain 的 Tool 和 Prompt 模块作为节点。
实战:一个可运行的智能客服 Agent
以下代码展示了一个完整的 LangGraph Agent,它能够查询知识库文档,也能调用外部 API 修改订单状态:
fromtypingimportTypedDict,Annotated,Sequenceimportoperatorfromlanggraph.graphimportStateGraph,ENDfromlanggraph.prebuiltimportToolExecutorfromlangchain_core.toolsimporttoolfromlangchain_core.messagesimportHumanMessage,AIMessage,ToolMessagefromlangchain_openaiimportChatOpenAI# ---------- 定义工具 ----------@tooldefquery_knowledge_base(question:str)->str:"""从企业内部知识库检索文档内容"""# 实际项目中这里接向量数据库returnf"根据知识库查询:「{question}」的相关信息是..."@tooldefmodify_order_status(order_id:str,new_status:str)->str:"""修改订单状态,status 可选: pending/shipped/completed/cancelled"""# 实际项目中接企业内部 APIreturnf"订单{order_id}状态已更新为{new_status}"tools=[query_knowledge_base,modify_order_status]tool_executor=ToolExecutor(tools)# ---------- 定义状态 ----------classAgentState(TypedDict):messages:Annotated[Sequence[HumanMessage|AIMessage|ToolMessage],operator.add]# ---------- 节点函数 ----------defagent_node(state:AgentState):llm=ChatOpenAI(model="gpt-4o",temperature=0)llm_with_tools=llm.bind_tools(tools)response=llm_with_tools.invoke(state["messages"])return{"messages":[response]}deftool_node(state:AgentState):last_message=state["messages"][-1]tool_calls=last_message.tool_calls results=[]fortcintool_calls:result=tool_executor.invoke(tc)results.append(ToolMessage(content=str(result),tool_call_id=tc["id"]))return{"messages":results}def