☰
从提示词工程到LangChain智能体:完整学习路线与实战指南
2026/10/22 8:10:09 网站建设 项目流程

作为一个在AI应用开发领域摸爬滚打了几年的从业者,我越来越明显地感觉到,2024年之后,纯靠调Prompt、套壳调用API已经很难做出有壁垒的东西了。真正的分水岭在于——你能不能构建一个能自主规划、调用工具、甚至在多步骤任务中自我纠错的智能体系统。而LangChain,正是目前串联这整条技术链路最主流的框架之一。但LangChain的学习路径非常陡峭,网上资料杂七杂八,很多人一上来就啃Agent和记忆机制,结果被源码和各种抽象概念劝退。这篇内容,我想根据自己的实际项目经验,梳理一条从提示词工程到智能体的完整学习路线,其中会有代码示例、容易踩的坑排查思路,以及我对工具选型的一些思考。

1. 为什么现在必须重新理解提示词工程

不把提示词工程当回事,后面搭建Agent一定吃亏。我见过不少开发者跳过Prompt直接上手LangChain的链式调用,最后遇到输出格式不稳定、模型不遵循指令时,根本分不清是框架的问题还是Prompt设计的问题。

1.1 提示词工程的本质是约束与引导

提示词工程的本质,不是“把问题问清楚”,而是“给模型划定一个高精度的输出空间”。大语言模型本质上是一个概率推理系统,它的输出空间极其庞大,如果你不把答案限制在能用代码解析的结构内,那么后续所有逻辑都会被打乱。

我举个例子。早期我做一个信息抽取任务,当时设计了一个Prompt让模型“提取合同里的关键条款”,模型确实提取了,但每次格式都不一样,有时候用JSON,有时候用自然语言,解析代码写得无比痛苦。后来我改了思路,在Prompt里直接规定:

prompt = """ 从以下合同中提取关键条款,并严格按照给定的JSON结构返回: { "party_a": "甲方名称", "party_b": "乙方名称", "amount": "合同金额", "effective_date": "生效日期" } 合同内容如下: {contract_text} 注意:只返回JSON,不要包含任何解释或Markdown标记。 """

加上“只返回JSON”和明确的结构定义之后,解析成功率直接逼近百分百。这个改动带来的启发是:提示词工程的核心修炼是限制性描述,而不是开放式描述。

1.2 提示词工程的能力层次

按照我的理解,提示词工程可以分成几个层次。第一层是上下文构造,知道怎么把背景知识、用户输入、历史对话拼接到Prompt里。第二层是输出格式化,能让模型稳定输出JSON、函数签名或特定代码结构。第三层是思维链引导,让模型在复杂任务中先推理再作答,或者通过Few-shot样本教会模型特定行为的模式。

LangChain里有一个很有意思的组件叫PromptTemplate,它能帮助你把这些工程经验固化下来。比如在LangChain中,我们可以这样定义一个带输出解析器的Prompt:

from langchain.prompts import PromptTemplate from langchain.output_parsers import StructuredOutputParser, ResponseSchema response_schemas = [ ResponseSchema(name="answer", description="问题的答案"), ResponseSchema(name="source", description="答案来源,必须是URL") ] output_parser = StructuredOutputParser.from_response_schemas(response_schemas) format_instructions = output_parser.get_format_instructions() prompt = PromptTemplate( template="回答用户的问题。\n{format_instructions}\n问题:{question}", input_variables=["question"], partial_variables={"format_instructions": format_instructions} )

从这个例子就能看出来,LangChain做的第一件事,就是把提示词工程里的“输出格式化”这一层,通过框架级的OutputParser固化下来。所以我始终认为,LangChain学习的第一站,不是Chain也不是Agent,而是PromptTemplate和OutputParser。把这两块吃透,后面的路才会顺畅。

2. LangChain入门:别被抽象概念带偏

LangChain的抽象层次非常多,模型接口、消息类型、链、代理、记忆、回调、向量存储,每一层都有大量的封装。新手特别容易在这些抽象概念里迷失,我的建议只有一个:从模型调用开始,先跑通一个最简单的对话,再看链、看工具。

2.1 先理解模型的标准化封装

LangChain最重要的价值之一,是提供了统一的模型调用接口。不管底层是OpenAI的模型还是开源的本地模型,在LangChain里都统一成Interface。这带来的直接好处是业务代码跟模型厂商解耦,切换模型时不需要大规模改动业务逻辑。

我最早做实验时用的是一个本地部署的开源模型,通过Ollama跑起来,接入LangChain只需很短的一段配置:

from langchain_community.llms import Ollama llm = Ollama( model="qwen2.5:7b", temperature=0.7, top_p=0.9 ) response = llm.invoke("请简单介绍一下递归神经网络") print(response)

这里注意一点,LangChain分成langchain-core、langchain-community、langchain合作伙伴包几个不同层级。很多初学者从老教程里看到了from langchain.llms import OpenAI,结果发现新版根本跑不通,因为这些模型实现已经迁移到langchain-openai或langchain-community里了。所以与其去记过时的API,不如养成一个习惯:需要哪个厂商的模型,就先查对应最新的包路径。

2.2 链:从单次调用到编排

当我需要让模型依次执行多个步骤时,就会用到Chain。链的核心价值是编排,它可以将提示词模板、模型、输出解析器,甚至多个子链拼装成一条流水线。

举一个实用场景:我需要做一个“论文摘要生成器”,要求先提取文章核心论点,再翻译成英文,最后生成一段适合发推特的摘要。如果用原生API调用,我得写一堆胶水代码管理中间结果,流程一多就乱。但用LangChain的LLMChain,能把每一步都封装起来,看起来更清晰:

from langchain.prompts import PromptTemplate from langchain.chains import LLMChain from langchain_openai import ChatOpenAI llm = ChatOpenAI(model="gpt-4o-mini", temperature=0.3) extract_prompt = PromptTemplate( input_variables=["text"], template="请提取以下文章的核心论点,控制在100字内:{text}" ) translate_prompt = PromptTemplate( input_variables=["points"], template="请将以下核心论点翻译成英文:{points}" ) summary_prompt = PromptTemplate( input_variables=["translated"], template="请基于以下英文内容,生成一条适合发推特的摘要:{translated}" ) chain = LLMChain(llm=llm, prompt=extract_prompt) | translate_prompt | summary_prompt result = chain.invoke({"text": article_text})

看到一个关键点了吗?LangChain用|运算符将不同的Prompt和Chain串联起来,这是新版本里让链式结构变得非常优雅的设计。从单次Prompt调用到链式编排,你的应用能力会升一个台阶。

2.3 可观测性:别忘了回调机制

很多初学者在跑通链之后,就直接闷头往下做,完全不管运行过程。等到模型返回格式不对、链走到一半报错的时候,整个程序黑盒一样,非常难排查。LangChain提供了一个全局回调机制,可以把LLM的输入输出、链的执行情况暴露给你。

from langchain.callbacks import StdOutCallbackHandler handler = StdOutCallbackHandler() llm = ChatOpenAI(model="gpt-4o-mini", callbacks=[handler])

这个Handler运行的时候,会在控制台打印完整的数据流转过程。我通常在开发阶段必开这个开关,调试效率能提升不少。等到上线阶段再换成自定义的日志回调,把关键节点信息写到日志服务里去。

3. Agent认知架构:工具、记忆与规划

学完Chain之后,会碰到整个LangChain体系中最有难度、也最有魅力的部分——Agent。但直接上手Agent代码你会觉得像在看天书,因为Agent的底层涉及三个核心认知模块:工具(Tools)、记忆(Memory)、规划(Planning)。这三个概念吃不透,Agent的代码就是一堆魔法变量。

3.1 工具:给模型装上手脚

Agent区别于普通Chain的关键,在于它可以使用外部工具。大模型本身只能输出文本,不能查数据库、不能调用搜索接口、不能执行代码,但通过工具机制,模型可以把决策转成一次可执行的调用。

LangChain里自定义一个工具非常简单,最常用的方式是@tool装饰器:

from langchain.tools import tool import requests @tool def get_weather(city: str) -> str: """获取指定城市的当前天气信息""" response = requests.get(f"https://api.weather.com/v1/city/{city}/now") return response.json() tools = [get_weather]

这里有个核心细节:工具的docstring非常重要,因为LLM会通过docstring理解这个工具是干什么的、参数应该怎么填。如果你写得不清楚,模型就不知道该什么时候调用这个工具,甚至可能把参数传错。

另外,在构建Agent时,我还经常使用LangChain内置的工具包,比如让模型能执行Python代码的PythonREPLTool、能检索本地文件的FileSearchTool。给模型配上这些能力之后,它就不只是一个“嘴强王者”,而是真的能在你的环境里干活了。

3.2 记忆:别让模型失忆

记忆是Agent落地时最容易被低估的环节。我们平时跟LLM对话时,模型本身是“无状态”的,它不记得你上一轮说了什么。但一个真正的智能体系统,必须有记忆能力。

LangChain里的Memory体系做过多次重构,老版本中常见的ConversationBufferMemory在新版已经做了调整,现在是基于BaseChatMessageHistory来管理会话历史。我在项目中更推荐使用持久化的消息历史,比如用Redis或数据库来存储,这样用户重连之后对话上下文还在。

记忆模块的一个常见坑是上下文膨胀。如果你把无限的对话历史全塞给模型,Token成本会越来越高,响应也会变慢。我的习惯是加一个摘要记忆机制:当历史超过N轮时,先把旧历史压缩成摘要,再作为背景信息传给模型。这样语义信息不丢,Token消耗也控制得住。

3.3 规划:让模型学会拆解问题

如果说工具和记忆是Agent的“肌肉”和“骨骼”,那么规划能力就是Agent的“大脑”。目前最主流的规划范式是ReAct,即推理+行动交替进行。模型先思考接下来该做什么,然后调用工具,看到工具返回结果后继续思考,直到最后得出结论。

LangChain的Agent封装了ReAct的完整循环,你不需要自己写这个循环,但要理解它背后发生的事:

  • 模型接收用户任务
  • 根据工具描述选择要调用的工具
  • 生成工具调用参数并执行
  • 把工具结果喂回给模型
  • 模型继续推理,决定下一步行动
  • 直到模型认为任务完成,输出最终答案

这个循环逻辑,我强烈建议初学者用最简单的代码自己实现一遍,哪怕只用几十行代码模拟这个循环过程,也能对Agent有非常直观的理解。直接上框架反而会迷失在抽象层里。

4. 从ReAct到自主智能体:核心代码与流程解析

前面储备好工具、记忆、规划这几个概念后,就可以正式拼装Agent了。我把自己常用的一套智能体构造流程拆开来讲,这套结构在多个项目里验证过,稳定性不错。

4.1 用create_agent快速构造智能体

新版LangChain推荐使用create_agent方法来构造一个带工具的Agent:

from langchain.agents import create_agent from langchain_openai import ChatOpenAI from langchain.memory import ConversationBufferMemory llm = ChatOpenAI(model="gpt-4o", temperature=0) memory = ConversationBufferMemory(memory_key="chat_history", return_messages=True) agent = create_agent( llm=llm, tools=[get_weather, python_repl_tool], memory=memory, system_prompt="你是一位智能助手,可以获取实时天气,也可以编写代码解决数学问题。" ) response = agent.invoke({"input": "计算北京未来一周平均气温,并说明是否适合户外跑步?"}) print(response["output"])

这个例子里值得注意的有两点。第一,system_prompt决定了Agent的性格边界和任务边界,写得越清楚,Agent跑偏的概率越小。第二,memory_key要和创建Prompt时使用的变量名保持一致,否则历史消息无法注入,很多奇怪的报错也是从这里来的。

4.2 AgentExecutor与手动控制循环

除了高层封装,LangAgent也提供更底层的AgentExecutor,它负责维护Agent的迭代循环,包括最大迭代次数、处理工具调用的中间异常等。我一般会在以下两种场景下手动配置AgentExecutor:一是任务步骤较多,需要限制模型推理轮数以防死循环;二是需要精细控制工具调用的容错策略。

from langchain.agents import AgentExecutor agent_executor = AgentExecutor( agent=agent, tools=[get_weather, python_repl_tool], max_iterations=5, early_stopping_method="generate", handle_parsing_errors=True, verbose=True )

handle_parsing_errors=True特别有用。当模型输出的内容不能被解析成标准工具调用时,如果不开启容错,整个Agent会直接崩溃;开了之后,框架会自动把错误信息反馈给模型,让模型自己修正。

4.3 让智能体具备多步骤任务闭环

做完上面这些,Agent已经具备“对话+单轮工具调用”的能力,但这离真正的“交付复杂任务”还有差距。比如任务是“查找某个领域的最新论文,总结成报告,发送到指定的接口”,这至少包含搜索、总结、调用接口发送三个环节,中间每一步都可能出问题。

我的做法是给Agent设计一个任务清单型Prompt结构,让它先将大任务拆成子步骤,然后逐步执行:

你将完成一个研究报告任务,请先列出步骤清单,然后逐个执行: 步骤1:搜索给定主题的最新论文 步骤2:逐篇提取核心观点 步骤3:汇总生成报告Markdown 步骤4:调用send_report工具发送报告 每完成一步,请简要说明结果,再进入下一步。

这种引导式的Prompt,配合AgentExecutor里的max_iterations,能最大程度保证任务在可控范围内完成。注意:不要把步骤写得太死,要给模型留出在中间步骤发现问题时修正方案的弹性空间。

5. 方案选型对比:LangChain vs 其他框架

聊到Agent框架,总绕不开LangChain到底值不值得学的问题。市面上还有LlamaIndex、AutoGen、以及一些轻量级的编排框架,每次技术讨论,大家都吵得不可开交。我的立场很明确:场景不同,选型应该不同。

5.1 LangChain适合什么

LangChain适合需要深度编排、多工具调用、并且希望快速验证业务逻辑的项目。它的生态最全,无论是连接外部知识库的Loader、各种向量库的适配器,还是几十种现成的工具链,都能帮你省下大量造轮子的时间。它的缺点也很明显:抽象层次多,学习曲线陡峭,版本迭代快,代码迁移工作量不小。

5.2 什么时候不要用LangChain

如果你的项目只用到一两个固定的模型调用,场景简单,那我建议直接裸写API调用,或者用一个非常薄的封装层就够了。引入LangChain反而会让代码变重,调试路径变长。

如果你的核心诉求是处理超大规模的文档检索,LlamaIndex在索引结构和检索策略上比LangChain更专注,效果也更出色。如果你需要多个Agent之间进行深度的交互和博弈,那AutoGen这类多智能体框架可能更适合。

我给团队的建议是:拉一张需求清单去打分,如果涉及工具调用、多步骤编排、模型切换,LangChain的性价比极高;如果只是教科书级别的Demo,别被框架绑架。

6. 项目落地实践:信息汇聚智能体案例

理论讲再多,不如直接看一个真实案例。我前阵子做了一个“信息汇聚与报告自动生成”的智能体,整体跑在LangChain之上,核心功能是:接收用户输入的主题,自动从多个信息源获取内容,经过筛选整合,最终生成结构化报告。这里完整说说它是怎么设计的。

6.1 整体需求拆解与工具配置

这个任务的技术难点有两块:第一,信息源的格式和可信度不一致,需要做内容过滤;第二,报告要输出为固定格式,不能随便生成。因此我设计了三个工具:

  • search_web(query):调用搜索API获取网页摘要列表
  • fetch_content(url):获取目标网页正文并清洗HTML
  • generate_report(sections):将结构化内容渲染成Markdown报告

三个工具的docstring都写得很详细,并且标注了参数的类型和含义,这样模型能准确生成调用参数。

6.2 提示词策略与Memory配合

在Agent的system prompt里,我明确设定了信息质量标准:优先采纳有明确来源的内容,过滤广告类、无来源的推测性内容。同时为了让Agent记住用户的历史偏好,我在Memory里存了用户历史查询主题和最终报告风格,这样第二次对话时,Agent会自动沿用用户喜欢的报告结构。

这一步做下来,用户体感非常明显,Agent从一个“偶尔好用”的玩具变成了一个“真的懂你”的工具。

6.3 落地过程中踩过的坑

这个项目里最有价值的其实是那些踩坑经验。第一个坑是信息源内容过长导致Token超限。搜索接口返回的网页正文动辄几万字,直接全塞给模型,很快就把上下文窗口撑爆了。后来我加了一步内容截断和摘要的预处理链路,先让模型对每篇内容提取核心段,再把核心段拼进最终Prompt,问题彻底解决。

第二个坑是工具调用循环空转。当模型调用搜索工具后,偶尔会不基于搜索结果继续推理,而是直接重复调用同一个搜索工具,浪费时间和费用。解决办法就是限制max_iterations,并且在Prompt中严厉强调“得到搜索结果后必须基于结果继续,不能重复调用工具”。

第三个坑是模型“幻觉”来源。汇总报告的时候,模型偶尔会编造出一些看起来像是搜索结果但实际不存在的链接。我是通过对工具返回内容打标签的方案解决的——把带链接的内容用特殊标记圈起来,Prompt要求模型只允许引用这些标记内的内容,超出标记范围的引用视为无效。

7. 常见问题与排查技巧实录

这一节把我在各个项目里被问得最多,也实际踩过的问题集中整理一下。这些不一定会出现在官方文档里,但都是实操里真实会遇到的坎。

7.1 工具调用参数总是传错怎么办

模型传错工具参数,一般有两个原因:一是工具函数的输入参数描述不清楚,二是Tool的docstring缺少参数类型说明。排查思路是先打印模型实际生成的工具调用参数,对比期望值,差异一目了然。如果差异大,优先改写工具docstring,把每个参数的意义和可选值范围都写清楚。不要试图通过更复杂的Parser去修复,破窗效应会放大问题。

另外有个小技巧,可以在工具的装饰器上直接加上类型注解,这样框架能把类型信息自动整合进Prompt里,显著减少参数类型错误。

@tool def search_web(query: str, max_results: int = 5) -> str: """在互联网上搜索给定的主题,返回前max_results条结果摘要。""" ...

7.2 智能体陷入死循环怎么处理

这个问题在上述案例中已经提过,再补充一个排查技巧:Agent循环大概率是“推理不收敛”。在模型得出结果之前,它需要尝试多种中间步骤,但模型可能因为工具反馈信息不足,迟迟无法进入最终回答阶段。

处理方案有几个,普通场景直接设置max_iterations硬上限;进阶场景我可以让工具返回更结构化的结果,在结果中直接附上“是否完成”标识,这样模型能更快决策;还有一种策略是把大任务显式拆分成子任务链,避免让一个Agent从头扛到尾。

7.3 对话记忆遗漏或错乱

记忆出问题,大多是消息历史管理不当导致的。排查时先看Memory中有没有内容,再看返回的消息类型是否为HumanMessage/AIMessage结构。如果发现多轮对话后模型“失忆”,大概率是memory_key拼接错误,或者消息历史没有正确传递给Prompt。把Agent内部的Prompt模板打出来看一遍,基本就能定位。

7.4 模型返回内容解析失败

输出解析失败,很多人会去调OutputParser,但我更建议先从Prompt侧找原因。解析失败往往是因为Prompt本身给了模型太多自由发挥的空间,比如没有示例、没有格式约束、或者要求了模型做不到的格式。最稳妥的办法是Few-shot:给一个“输入 -> 输出”示例,然后让模型照葫芦画瓢。我在实际项目中发现,加一个Few-shot示例能减少八成的解析异常。

7.5 成本失控

Agent跑起来之后,单次对话的Token消耗可能远远高于预期。我的经验是给Agent配备一个“预算管理”机制:每次任务开始前计算剩余Token预算,如果任务复杂度过高,自动降级为只使用摘要内容,或者跳过部分非核心步骤。LangChain的回调系统可以统计每次调用的Token数,用这个数据做费用监控非常方便。

8. 学习路线图与能力进阶建议

聊了这么多,最后说说整个学习路线应该怎么走。我给团队新人定的学习路径,大致分为四个阶段,每个阶段都需要完成一个可演示的Demo才算过关。

8.1 阶段一:基础提示词工程与LangChain API摸底

这个阶段的重点是熟悉LangChain的基本组件:PromptTemplate、ChatModel、OutputParser。建议完成一个任务:做一个能回答用户问题并附带来源链接的对话机器人。这个Demo不涉及工具和记忆,但能帮你跑通框架的核心流程。

8.2 阶段二:链式编排与检索增强

第二个阶段要掌握LCEL(LangChain Expression Language),会用|管道符组合多条链,并且接入一个向量数据库完成RAG。建议任务:做一个基于私有文档的问答机器人。这里面会涉及到文本切分、向量化、检索、生成四个环节,做完之后对RAG的完整流程理解会非常透彻。

8.3 阶段三:工具与记忆

第三阶段,接触Agent的构成模块。完成一个能够调用搜索API和计算器工具的对话助手,并且给它加上持久化记忆能力。这个阶段的核心目标是理解“模型如何通过工具调用扩展自己的能力边界”。

8.4 阶段四:自主Agent与项目工程化

最后阶段,直接把Agent应用到一个小型真实项目中,要求其拥有任务拆分能力、容错能力和成本控制能力。做完这个阶段,你基本上就具备了独立负责Agent项目的开发能力。

从提示词工程走到智能体开发,是一条布满了陷阱但也非常有意思的路。刚开始跑通一个Agent的时候,那种感觉确实挺奇妙的,好像你创造了一个能自己动手解决实际问题的小助手。但随着项目复杂度上升,你又会发现,所谓智能体,本质上还是你需要精心设计它的思维边界、工具边界和反馈机制。模型负责聪明,而你要负责可靠。这条路上没有捷径,动手写代码、调试、试错,是唯一让我感觉真正成长的方式。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询