LangChain 是目前做 LLM 应用开发绕不开的一个框架也是很多人从“调用模型 API”走向“开发一个完整 AI 功能”时最先遇到的一层抽象。如果你已经能调通模型接口但不知道接下来该怎么组织提示词、怎么让模型使用工具、怎么搭一个能跑的 Agent 项目这篇文章就是按这个顺序来写的先讲 Model 基础调用再拆 Agent 的原理最后给出一个可以直接运行验证的实战项目并补充批量任务、报错排查和 LangGraph 的边界。文章里的代码基于常见的 LangChain 写法接口细节在不同版本里可能调整。这也正是 LangChain 初学者最容易困惑的地方网上教程很多但 API 一变旧教程就失效。我的建议是不要死记代码先抓住 Model、Tool、Agent 这三条主线再根据当前版本文档做微调。1. 先搞清楚 LangChain 到底解决什么问题为什么入门要围绕 Model 和 Agent1.1 LangChain 不是大模型而是开发框架很多人刚接触 LangChain 时会有一个误解以为它是个大模型或者是个能自动提升模型效果的工具。实际上LangChain 更像是一个“粘合层”负责把下面这些能力组织起来模型调用通过统一的接口去调用不同厂商的大模型。提示词管理把 PromptTemplate、System Prompt、Few-shot 示例组织成结构化内容。工具调用让模型在推理过程中选择并调用外部函数。记忆能力在多轮对话里保存和检索历史消息。文档处理加载、切分、向量化文档为 RAG 做准备。对外接口把上面的流程封装成服务或命令行工具。换句话说LangChain 本身不提供大模型也不提供向量数据库。它提供的是“把模型和周边能力组合起来”的框架。这个定位决定了你入门时要学的不是某一个魔法函数而是组件之间的关系。1.2 Model、Agent、LangGraph 分别对应什么阶段从标题里的三个关键词就能看出这条学习主线Model 是基础调用Agent 是模型调用工具的完整运行时LangGraph 则是在更复杂场景下对流程做编排。Model 阶段只做“请求-响应”。你把文本发给模型模型返回文本。适合理解 API 参数、成本、延迟和输出格式。Agent 阶段模型不再只回答文本而是可以根据任务目标选择工具调用工具观察工具返回结果再决定下一步。这是 LLM 应用从“聊天”走向“干活”的关键一步。LangGraph 阶段当流程包含循环、分支、人工确认、状态持久化时普通的 Agent 调用链会变得难维护。LangGraph 提供更底层、更可控的图结构编排能力。所以标题里的“Model 基础调用 Agent 完整项目实战”其实就是 LangChain 入门最合理的路径先跑通模型再让模型学会用工具。LangGraph 可以作为第二阶段再学。1.3 为什么我用“能不能稳定复现”来评价 LangChain 教程LangChain 的版本迭代速度很快网上很多教程可能还停留在旧的initialize_agent写法而官方文档已经转向推荐create_agent或create_react_agent。这带来一个很现实的问题照着教程抄代码不代表能跑通。我的建议是看教程时先看以下三点是否说明当前 LangChain 版本和 Python 版本。是否给出最小可运行样例而不是只贴一段片段。是否解释了参数含义而不是只让你“复制粘贴然后运行”。如果一篇教程能满足这三点它的时效性通常不会太差。下面的内容也按这个标准来组织。2. 先把 Model 调用跑通环境准备、最小示例和关键参数2.1 环境准备Python、虚拟环境和依赖安装Model 调用是所有后续内容的基础。我建议不要在全系统的 Python 环境里直接装依赖而是先创建一个虚拟环境避免把依赖关系搞乱。mkdir langchain-demo cd langchain-demo python -m venv .venv source .venv/bin/activate # Windows 在 PowerShell 里执行 .venv\Scripts\Activate.ps1虚拟环境做好后安装基础依赖pip install langchain langchain-openai python-dotenv这里解释一下为什么需要这几个包langchain核心框架提供 Prompt、Agent、Chain 等组件。langchain-openai通过 OpenAI 兼容协议调用模型的封装很多国内模型服务也支持这个协议。python-dotenv用于读取.env文件中的 API Key避免把密钥硬编码到代码里。如果你的模型提供方不支持 OpenAI 兼容协议就需要换成对应的 LangChain 集成包。在常见场景下先通过langchain-openai跑通是最快的路径。2.2 最小示例一段代码完成模型调用在项目目录下创建一个.env文件写入你实际可用的 API Key。这里以OPENAI_API_KEY为例不同服务商的变量名可能不一样但思路一致。OPENAI_API_KEY你的密钥然后创建model_demo.pyimport os from dotenv import load_dotenv from langchain_openai import ChatOpenAI load_dotenv() llm ChatOpenAI( modelgpt-4o-mini, # 以你的环境实际可用模型为准 temperature0.7, ) response llm.invoke(用一句话解释什么是 LangChain) print(response.content)运行之后正常结果是一段文本内容。如果报错优先看这几个方向API Key 是否正确。模型名是否真实存在。网络是否能够访问对应的模型服务。是否需要在ChatOpenAI里指定base_url。这里有一个很容易踩的坑很多模型服务提供了“OpenAI 兼容接口”但不是所有接口字段都一样。比如有的服务要求额外传reasoning_content有的不支持某些参数。遇到 400 错误不要急着怀疑 LangChain先看错误信息里具体是哪个字段被拒绝了。2.3 核心参数temperature、max_tokens 和 streamingModel 调用看起来简单但参数对结果影响很大。下面是我实际测试时最常用的几个参数整理成表格方便对照。参数作用常见用法temperature控制随机性值越高输出越发散越低越稳定创意写作可以用 0.8-1.0提取事实用 0-0.3max_tokens限制输出的最大 token 数控制成本和时间长文摘要时要调高简单问答可以调低streaming是否启用流式输出逐 token 返回结果Web 对话场景建议开启批处理场景可以关闭timeout请求超时时间避免服务无响应时一直卡住生产环境建议设置比如 30 到 60 秒很多初学者会忽略一个现象同样的提示词同一天内连续调用两次结果可能不同。这不一定是代码问题很大概率是temperature设置太高。如果你在做信息提取、分类、代码生成这类任务建议先把temperature降到 0.2 左右让输出更稳定。流式输出的写法也值得了解。先记住一句结论单次调用适合验证流式输出适合交互。流式示例如下for chunk in llm.stream(写一段关于 Agent 的介绍50 字以内): print(chunk.content, end)这个逻辑对后续 Agent 项目也有用因为 Agent 执行过程可能比较长用户在界面上如果长时间看到空白体验会很差。2.4 为什么先跑通单次调用再谈 Agent我每次开始一个新的 LangChain 项目都会先做一次最基础的模型调用确认模型名、Key、网络、参数都没问题然后再往上加 Prompt、Tool、Agent。这样做的原因是Agent 的报错链条比单次调用长得多。如果你在 Agent 阶段遇到“模型返回不合法 JSON”“工具输出解析失败”这类问题很难判断是模型问题还是框架问题。而先跑通llm.invoke()至少把基础层排除了。测试顺序建议是先单次调用再流式调用再自定义 Prompt最后接 Tool。3. Agent 的原理模型怎么学会调用工具3.1 为什么模型不能直接执行动作大模型的本质是一个文本生成器它并不具备“执行动作”的能力。你让它“查当前时间”它能输出一段关于怎么查时间的说明但不能真正读取系统时钟。你让它“计算 123 * 456”它可能会算错因为它本质上是预测下一个 token不是真的在运行计算器。Agent 的思路就是不要求模型直接完成这些操作而是让模型学会“告诉框架我要调用哪个工具工具参数是什么”然后由代码真正执行工具把结果返回给模型。模型负责决策代码负责执行。这个分工非常重要。理解了这个你再看 Agent 相关代码就不会觉得神秘。3.2 ReAct 循环思考、行动、观察LangChain 里最常见的 Agent 模式是 ReAct核心循环包含三个阶段Thought思考模型根据当前任务和已有信息决定下一步怎么做。Action行动模型输出一个工具调用意图包括工具名和参数。Observation观察代码执行工具后把结果返回给模型模型继续思考。这个循环会一直持续直到模型认为已经得到最终答案输出 Final Answer。你可以把 Agent 理解成一个“带工具的模型循环”模型不是一次性给出答案而是通过多轮决策逼近目标。启动 Agent 后你可以开启 verbose 日志观察每一步发生了什么。这是排查 Agent 问题最直接的手段。3.3 Tool 是 Agent 的关键名字、描述、参数缺一不可一个工具在 LangChain 里可以很简单就是一个 Python 函数加上一点元数据。但对模型来说最关键的并不是函数里写了什么而是名字、描述和参数说明。原因很简单模型是通过描述来选工具的。如果两个工具的描述太模糊模型可能选错。如果参数说明不清楚模型可能传错参数。实际测试中我发现工具描述写得越具体Agent 选对工具的概率越高。所以给工具写描述时不要只写“获取时间”而应该写“获取当前系统时间返回格式可以由 format 参数指定适合回答现在几点、今天日期等问题”。描述越贴近真实使用场景模型越容易判断应该调用它。4. 完整项目实战做一个带工具调用的问答 Agent4.1 项目目标与最小场景下面这个项目目标是做一个“能使用工具的问答 Agent”。它至少包含两个工具获取当前系统时间。执行简单的四则运算并返回可靠的计算结果。这两个工具都不需要外部服务不依赖网络适合作为 Agent 入门练习。跑通之后你可以替换成自己的业务函数。4.2 定义自定义工具在 LangChain 里最方便的方式是使用tool装饰器。from langchain_core.tools import tool from datetime import datetime tool def get_current_time(format: str %Y-%m-%d %H:%M:%S) - str: 获取当前系统时间返回指定格式的日期时间字符串。 适合回答“现在几点”“今天几号”等时间相关的问题。 return datetime.now().strftime(format) tool def calculator(expression: str) - str: 执行简单的四则运算表达式。expression 是一个合法数学表达式 例如 123 * 456 或 (1 2) * 3返回计算结果。 try: result eval(expression, {__builtins__: {}}, {}) return str(result) except Exception as e: return f计算失败请检查表达式{e}这里要提醒一句calculator里使用eval只是为了教学演示不要直接在公开服务里使用否则会有代码注入风险。实践中应该用ast解析或者专门的表达式计算库。这个点很重要Agent 的工具本质上是给模型开放的“能力边界”边界越窄越安全。4.3 组装 Agent 并执行新版 LangChain 推荐使用create_react_agent它需要三个输入模型、工具列表、一个符合 ReAct 格式的提示词模板。提示词模板可以直接用官方 hub 的模板也可以保存成本地模板。from langchain.agents import create_react_agent, AgentExecutor from langchain import hub from langchain_openai import ChatOpenAI tools [get_current_time, calculator] llm ChatOpenAI( modelgpt-4o-mini, temperature0, ) prompt hub.pull(hwchase17/react) agent create_react_agent(llm, tools, prompt) executor AgentExecutor(agentagent, toolstools, verboseTrue) result executor.invoke({input: 现在几点了另外帮我算一下 123 乘以 456 等于多少。}) print(result[output])如果你无法访问 hub可以把hwchase17/react模板内容保存成本地变量。重点是模板必须包含{input}、{agent_scratchpad}以及 Thought/Action/Observation 的循环格式否则 Agent 无法正常执行。如果你的 LangChain 版本比较旧可能会看到很多文章使用initialize_agentfrom langchain.agents import initialize_agent, AgentType agent initialize_agent( toolstools, llmllm, agentAgentType.ZERO_SHOT_REACT_DESCRIPTION, verboseTrue, )这两种写法在不同版本里都可能遇到。我的建议是如果你是新装的环境优先按新版create_react_agent来写如果用老代码遇到弃用警告不要慌把警告信息读完整通常它会告诉你应该迁移到哪个新函数。4.4 运行验证怎么判断 Agent 真的在调用工具执行上面代码后如果verboseTrue控制台会输出完整的 ReAct 过程。你应该能看到类似下面的信息结构模型先输出一个 Thought。然后输出 Action内容包含工具名和参数。框架执行工具后输出 Observation。最终输出 Final Answer。验证 Agent 是否正常工作不只看最终结果还要看工具是否真的被调用。比如问“现在几点了”如果最终输出的是一个生成式回答而不是当前真实时间说明工具可能没有被正确调用或者模型没有把工具结果作为最终答案依据。这时可以先手动调用工具验证print(get_current_time.invoke({}))如果工具本身返回正常再检查提示词格式和工具描述。4.5 把项目从“跑通”变成“可用”的几个细节跑通 Agent 之后别急着扩展功能。先做下面几件事连续跑 10 次同样的问题看结果是否稳定。换几个不同说法的问题看模型能否正确选工具。关掉 verbose确认日志输出是否足够排查问题。记录每次调用的大致耗时和 token 消耗。这些数据比“项目能跑”更有价值因为后续接入真实业务时稳定性判断全靠它们。5. 从 Demo 到生产批量任务、失败重试和资源控制5.1 批量任务不能只是“循环调用”很多人在本地 Demo 里逐个调用模型觉得简单。但真正做批量任务时不能只是写一个 for 循环因为会遇到几个实际问题中间某个批次报错前面的结果是否要重新跑。输出结果如何命名和保存避免覆盖。连续大量请求时模型服务是否限流。任务日志散落各处出问题时难追溯。下面是一个更稳妥的批量处理思路import json from pathlib import Path questions [ 现在几点了, 计算 12 * 34, 计算 56 / 8, ] results [] for idx, question in enumerate(questions): try: resp executor.invoke({input: question}) results.append({ index: idx, input: question, output: resp[output], status: success, }) except Exception as e: results.append({ index: idx, input: question, output: str(e), status: failed, }) Path(output).mkdir(exist_okTrue) with open(output/results.json, w, encodingutf-8) as f: json.dump(results, f, ensure_asciiFalse, indent2)这个示例里最关键的不是循环而是三点把单条结果和错误都记录下来统一输出目录每条数据带索引。这样批量任务失败后不需要从头再跑只需要看失败项。5.2 失败重试先看错误原因再决定要不要重试有些错误重试能解决比如网络抖动、限流、临时超时。有些错误重试没有意义比如模型名写错、API Key 无效、提示词格式不合法。所以不要写一个“无限重试”的循环。更合理的做法是捕获异常记录错误。如果是超时、限流、临时不可用可以等待一段时间后重试比如最多 3 次。如果是参数错误、401 鉴权失败、400 参数不合法直接标记失败不重试。这也是 Agent 项目经常遇到的模型在 Agent 执行中途返回了非法格式Agent 会尝试重新解析但如果一直失败就要考虑是不是工具描述不够清楚、模型版本能力不足、或者上下文里已经积累了太多无关历史。5.3 日志、超时和资源占用生产环境中我一般会关注四个数据数据作用单次请求耗时判断服务是否迟迟不返回token 消耗控制成本判断是否超出上下文窗口错误类型分布区分是模型问题、工具问题还是输入问题QPS 与并发数避免请求过多被限流如果你的机器配置不高并发数不要一上来就拉满。可以先并发 2 到 3 个请求观察资源占用和延迟再逐步增加。Agent 场景还有一个容易被忽略的问题上下文窗口。每次工具调用都会把 Thought、Action、Observation 写进对话历史如果任务很长token 消耗会快速增长。低配置环境不一定能稳定跑长任务这不是 LangChain 的 bug而是模型上下文和成本限制。5.4 不是所有场景都需要 Agent我一直强调一句话先判断是否真的需要 Agent。如果你的任务只是“固定格式的问答”用普通 Prompt Model 调用就足够了引入 Agent 反而会增加延迟和出错概率。只有满足下面至少一条才值得用 Agent需要实时数据比如系统时间、外部接口的查询结果。不能提前确定需要的工具和调用顺序。需要根据中间结果决定下一步动作。需要把多步工具结果汇总后回答用户。如果只是做文档问答优先考虑 RAG而不是强行套 Agent。RAG 解决“模型没学过的知识”的问题Agent 解决“需要执行动作”的问题两者不是同一个东西。6. 常见报错、排查链路以及一条更稳的学习路线6.1 报错不一定是大模型或 LangChain 的错Agent 项目的报错链比较长很多人一遇到错误就怀疑 LangChain 版本太老或模型不够聪明。实际上很多报错来自非常基础的地方。问题现象优先排查方向直接 ImportError是否安装了对应集成包例如langchain-openai400 错误提示模型名不支持当前模型服务支持哪些模型名401 鉴权错误API Key 是否正确环境变量是否加载一直超时网络条件、timeout设置、服务端是否过载Agent 不调用工具直接回答工具描述是否清晰Prompt 模板是否正确Agent 调用工具后越跑越偏查看 verbose 日志看模型是否把 Observation 误当成最终结果上下文超长对话历史是否无限增长历史消息是否需要裁剪批量任务中间失败看失败项的输入格式和具体错误再决定是否重试排查顺序我建议固定下来先看现象再看输入再看环境再看参数最后才怀疑框架。6.2 模型名“不存在”或“不支持”这类问题很多模型服务在升级后旧模型名会被下架或者同一个服务商在 OpenAI 兼容接口和专用接口里支持的模型名不一样。这时报错会直接提示模型名不存在或不被支持。处理思路去模型服务商官网查看当前支持的模型列表。确认当前接口是不是 OpenAI 兼容接口。确认代码里配置的base_url是否指向正确的服务地址。不要在多个接口之间混用模型名。这个问题很常见但通常不是代码逻辑问题静下心比对一遍配置就能解决。6.3 LangChain 和 LangGraph 怎么选很多初学者纠结要不要直接学 LangGraph。我的回答是先把 LangChain 的 Model 和 Agent 跑熟再学 LangGraph。LangGraph 适合的场景是流程复杂、状态多、需要人工介入或分支循环的 Agent。比如一个客服机器人需要不断判断用户意图走到不同子流程并且中途要保存状态这时候用 LangGraph 会更清晰。但如果只是“模型 两三个工具”的相对简单应用直接用 LangChain 的 AgentExecutor 就够了。强行上 LangGraph会发现学习成本明显增加而收益不明显。6.4 给入门者的学习路线Model - Prompt - RAG - Agent - LangGraph最后给一条相对稳的学习路线不需要一次学完Model先掌握模型调用的基本参数能跑通单次调用和流式调用。Prompt学习写系统提示词、使用 PromptTemplate理解输出格式对后处理的影响。RAG如果目标是做知识库问答再学文档加载、切分、向量检索。Agent理解 ReAct 循环自己写工具让模型学会调用工具。LangGraph当流程复杂到 AgentExecutor 不好维护时再迁移到图编排。这条路线的好处是每一层都建立在前面已经验证过的基础上。很多学了半年 LangChain 还觉得不会做项目的人往往是跳过了 Prompt 和 Tool 的细节直接去抄大项目代码结果一跑就崩。真正落地 LangChain 项目时最该盯住的不是“我用了哪个最新框架”而是输入格式、工具边界、日志记录和失败重试。这几个点理顺了哪怕框架接口变了你也能很快迁移过去。