发布时间:2026/7/16 10:02:32
目录一、环境搭建从 “能跑起来” 开始1. 环境配置核心要点2. 模型连接密钥安全与接口适配3. 第一个最小程序验证链路通畅性二、核心基础模型、消息、调用与链1. 模型不是 “模型本身”而是 “客户端封装”2. 消息聊天模型的输入单元3. 输出解析从 AIMessage 到可用格式三、工具调用Agent 的前置核心能力1. 工具定义让模型 “看懂” 工具能力2. 工具绑定把 “工具说明书” 交给模型3. 工具调用循环模拟 Agent 的最小逻辑四、LangChain 核心组件搭建 LLM 应用的 “积木”1. Messages对话上下文的载体2. PromptTemplate提示词的标准化管理3. MessagesPlaceholder历史消息的动态插入4. OutputParser结构化输出的核心工具五、RAG让大模型读懂私有资料1. 文档加载把外部文件转为 Document 对象2. 文本切分平衡检索精度与语义完整性3. 向量生成与存储让文本 “可检索”4. 检索器统一的检索接口5. 最小 RAG 闭环让模型 “基于资料回答”六、从 RAG 到 Agent让模型自主决策是否检索1. 将 Retriever 封装为工具2. 绑定检索工具到模型3. 模拟 Agent 决策流程七、学习总结与下一步规划1. 核心认知LangChain 的本质2. 已落地的核心 Demo3. 下一步学习 LangGraph 构建复杂 Agent八、初学者的学习建议结语作为一名 AI 应用开发学习者在大模型应用开发的浪潮中LangChain 始终是绕不开的核心工具。起初我对它的认知仅停留在 “和大模型、RAG、Agent 绑定出现的框架” 这个模糊概念上直到亲手搭建环境、编写代码、跑通一个个 demo才真正拆解了 LangChain 的底层逻辑 —— 它不是神秘的智能体也不是某类大模型而是一套让 LLM 应用开发标准化、模块化的工具箱。本文将以初学者的视角完整还原从环境搭建到 Agent 雏形落地的学习全过程希望能为同样入门 LangChain 的开发者提供一份可落地的参考。一、环境搭建从 “能跑起来” 开始学习任何框架的第一步都不是死记概念而是让代码先跑通。大模型应用依赖包繁多为了避免环境冲突我选择轻量的 Miniconda 而非完整 Anaconda为 LangChain 专门创建隔离环境。1. 环境配置核心要点Python 版本的选择是第一个需要注意的细节。虽然 Python 3.13 已发布但 AI 生态包对 3.11/3.12 的兼容性更稳定因此我最终选择 3.11 版本# 创建并激活专属conda环境 conda create -n agent-dev python3.11 conda activate agent-dev项目目录规划在D:\code\langchain随后安装基础依赖包。由于国内开发者常用阿里云百炼而非 OpenAI 官方 API核心依赖只需安装 LangChain 核心库、OpenAI 兼容接口包和环境变量管理包pip install langchain langchain-openai python-dotenv2. 模型连接密钥安全与接口适配阿里云百炼提供 OpenAI 兼容接口因此仍可使用 LangChain 的ChatOpenAI类调用模型但需要配置base_url和 API Key。这里有个关键原则API Key 绝对不能硬编码在代码中。我在项目根目录创建.env文件存储密钥DASHSCOPE_API_KEY你的百炼APIKey通过python-dotenv加载环境变量再初始化模型客户端import os from dotenv import load_dotenv from langchain_openai import ChatOpenAI # 加载环境变量 load_dotenv() # 初始化百炼模型客户端 model ChatOpenAI( modelqwen-plus, # 通义千问增强版 api_keyos.getenv(DASHSCOPE_API_KEY), base_urlhttps://dashscope.aliyuncs.com/compatible-mode/v1, )3. 第一个最小程序验证链路通畅性写一行简单的调用代码验证环境、依赖、密钥、模型连接是否全部正常# 第一次调用模型 response model.invoke(你好请用一句话介绍你自己。) print(response.content)当终端打印出通义千问的回复时整个基础链路就通了。这个阶段不需要理解复杂概念核心目标是确认 “模型能被调用”—— 这是后续所有操作的基础。二、核心基础模型、消息、调用与链环境跑通后需要拆解 LangChain 的核心调用逻辑。这一阶段的核心可以总结为一条链路模型 model → 消息 messages → invoke 调用 → AIMessage → 输出解析 → chain。1. 模型不是 “模型本身”而是 “客户端封装”ChatOpenAI创建的并非大模型本身而是一个标准化的 Python 客户端。LangChain 的核心价值之一就是用统一的接口封装不同供应商的大模型OpenAI、百炼、智谱等开发者无需为每个平台适配调用逻辑。2. 消息聊天模型的输入单元聊天模型的输入不是简单字符串而是消息列表。LangChain 定义了多种消息类型覆盖大模型交互的全场景SystemMessage系统指令定义模型的身份和行为准则HumanMessage用户输入代表人类的提问或指令AIMessage模型输出是调用模型后的返回结果ToolMessage工具执行结果Agent 场景中会频繁用到。示例代码清晰展示了消息列表的构建方式from langchain_core.messages import SystemMessage, HumanMessage # 构建消息列表 messages [ SystemMessage(content你是一个耐心的中文老师用通俗的语言解释技术概念。), HumanMessage(content解释一下 LangChain 是什么。), ] # 调用模型 result model.invoke(messages) print(result.content)需要注意的是invoke()返回的不是字符串而是AIMessage对象除了content字段还包含response_metadata响应元数据、usage_metadata用量统计、tool_calls工具调用指令等关键信息 —— 其中tool_calls是实现 Agent 的核心。3. 输出解析从 AIMessage 到可用格式如果只需要字符串结果无需手动提取contentLangChain 提供StrOutputParser简化操作from langchain_core.output_parsers import StrOutputParser # 初始化解析器 parser StrOutputParser() # 构建链模型调用 → 输出解析 chain model | parser # 调用链 result chain.invoke(messages) print(result) # 直接输出字符串这里的|是 LangChain Expression LanguageLCEL的核心语法代表将多个 “可运行组件Runnable” 串联。模型、解析器、链都是 Runnable因此都能通过.invoke()调用 —— 这是 LangChain 组件化设计的核心体现。三、工具调用Agent 的前置核心能力Agent 的本质是 “模型决策 工具执行 结果反馈” 的循环而工具调用是理解这一逻辑的关键。大模型本身只能生成文本无法执行代码、查询数据库或访问外部接口工具调用的作用就是让模型学会 “请求外部能力”再由程序执行并反馈结果。1. 工具定义让模型 “看懂” 工具能力LangChain 通过tool装饰器快速定义工具工具的名称、参数类型、文档字符串至关重要 —— 模型不会读取工具内部代码而是通过这些信息理解工具功能from langchain_core.tools import tool # 定义加法工具 tool def add(a: int, b: int) - int: Add two integers. return a b # 定义乘法工具 tool def multiply(a: int, b: int) - int: Multiply two integers. return a * b2. 工具绑定把 “工具说明书” 交给模型绑定工具并非执行工具而是将工具的元信息名称、参数、描述传递给模型让模型判断是否需要调用# 工具列表 tools [add, multiply] # 绑定工具到模型 model_with_tools model.bind_tools(tools)3. 工具调用循环模拟 Agent 的最小逻辑当用户提问 “9 乘 6 等于多少5 加 3 等于多少” 时模型会返回包含tool_calls的响应而非直接回答。我们可以手动实现工具执行逻辑模拟 Agent 的核心循环# 用户问题 messages [HumanMessage(content9乘6等于多少5加3等于多少)] # 模型生成工具调用指令 ai_msg model_with_tools.invoke(messages) # 构建工具映射方便根据名称查找工具 tool_map {tool.name: tool for tool in tools} # 执行工具调用 for tool_call in ai_msg.tool_calls: # 获取工具和参数 selected_tool tool_map[tool_call[name]] tool_args tool_call[args] # 执行工具 tool_result selected_tool.invoke(tool_args) # 将工具执行结果封装为ToolMessage加入消息列表 messages.append(ToolMessage(contentstr(tool_result), tool_call_idtool_call[id])) # 模型基于工具结果生成最终回答 final_msg model_with_tools.invoke(messages) print(final_msg.content) # 输出9乘6等于545加3等于8这个循环就是 Agent 的最小原理用户问题 → 模型生成工具调用指令 → 程序执行工具 → 工具结果反馈给模型 → 模型生成最终回答。理解这一逻辑就掌握了 Agent 的核心本质。四、LangChain 核心组件搭建 LLM 应用的 “积木”如果说工具调用是 Agent 的 “灵魂”LangChain 的核心组件就是搭建应用的 “积木”。这些组件将模型调用、提示词、消息、解析器等环节抽象化让复杂应用的开发变得模块化。1. Messages对话上下文的载体Messages 不仅是单次交互的输入更是多轮对话的上下文容器。模型在多轮交互中看到的是完整的消息列表而非孤立的一句话。但大模型的上下文窗口有限后续需处理消息裁剪、过滤、合并等问题避免上下文溢出。2. PromptTemplate提示词的标准化管理硬编码提示词会导致维护困难PromptTemplate将提示词结构与变量分离提升复用性from langchain_core.prompts import ChatPromptTemplate # 定义提示词模板 prompt ChatPromptTemplate.from_messages([ (system, 你是一个{role}回答必须用中文且简洁易懂。), (human, 请解释这个概念{topic}), ]) # 传入变量生成消息 messages prompt.invoke({role: Python 老师, topic: Runnable}) print(messages)3. MessagesPlaceholder历史消息的动态插入多轮对话中历史消息需要动态插入提示词MessagesPlaceholder实现这一需求from langchain_core.prompts import MessagesPlaceholder # 包含历史消息的提示词模板 prompt ChatPromptTemplate.from_messages([ (system, 你是一个学习助手根据历史对话回答问题。), MessagesPlaceholder(history), # 历史消息占位符 (human, {input}), ]) # 模拟历史对话 history [ HumanMessage(content什么是LangChain), AIMessage(contentLangChain是LLM应用开发的工具箱。), ] # 生成消息列表 messages prompt.invoke({ history: history, input: 它的核心优势是什么 })这一组件是实现多轮对话 Agent 的关键。4. OutputParser结构化输出的核心工具除了StrOutputParserLangChain 还提供多种解析器满足不同场景JsonOutputParser将模型输出解析为 Python 字典with_structured_output让模型直接返回 Pydantic 对象自定义解析器适配复杂的输出格式。结构化输出是信息抽取、API 返回、数据库入库等场景的核心需求示例如下from langchain_core.output_parsers import JsonOutputParser from pydantic import BaseModel, Field # 定义结构化输出模型 class ConceptExplain(BaseModel): name: str Field(description概念名称) definition: str Field(description概念定义) advantage: str Field(description核心优势) # 初始化解析器 parser JsonOutputParser(pydantic_objectConceptExplain) # 构建提示词包含解析器指令 prompt ChatPromptTemplate.from_messages([ (system, f请按照指定格式输出{parser.get_format_instructions()}), (human, 解释一下LangChain的核心优势), ]) # 构建链 chain prompt | model | parser # 调用链 result chain.invoke({}) print(result) # 返回ConceptExplain对象五、RAG让大模型读懂私有资料RAG检索增强生成是解决大模型 “知识过期” 和 “幻觉” 的核心方案其本质是 “先检索私有资料再让模型基于资料回答”。完整的 RAG 流程可拆解为加载文档 → 切分文本 → 生成向量 → 存入向量库 → 检索相关片段 → 构造提示词 → 调用模型 → 解析输出。1. 文档加载把外部文件转为 Document 对象LangChain 的Document对象是处理私有资料的基础包含page_content正文和metadata元信息如来源、页码。以加载本地 Markdown 文件为例from langchain_community.document_loaders import UnstructuredMarkdownLoader # 加载Markdown文件 loader UnstructuredMarkdownLoader(langchain_notes.md) docs loader.load() # 查看Document结构 print(docs[0].page_content[:100]) # 正文前100字 print(docs[0].metadata) # 元信息metadata的价值在于模型回答时可追溯资料来源提升回答可信度。2. 文本切分平衡检索精度与语义完整性长文档无法直接输入模型或生成向量需切分为小块。RecursiveCharacterTextSplitter是最常用的切分工具核心参数为chunk_size块大小和chunk_overlap块重叠—— 重叠的作用是避免重要上下文被切断from langchain_text_splitters import RecursiveCharacterTextSplitter # 初始化切分器 text_splitter RecursiveCharacterTextSplitter( chunk_size500, # 每个块500字符 chunk_overlap50, # 相邻块重叠50字符 ) # 切分文档 splits text_splitter.split_documents(docs) print(f切分后共{len(splits)}个块)切块大小需根据场景调整块太大检索不精确块太小语义易破碎。3. 向量生成与存储让文本 “可检索”嵌入模型Embeddings将文本转为向量语义相近的文本向量距离更近。学习阶段可使用本地HashEmbeddings仅用于理解流程生产环境需用专业模型如百炼、BGEfrom langchain_community.embeddings import HashEmbeddings from langchain_community.vectorstores import InMemoryVectorStore # 初始化嵌入模型 embeddings HashEmbeddings() # 生成向量并存入内存向量库 vector_store InMemoryVectorStore.from_documents( documentssplits, embeddingembeddings, )学习阶段用InMemoryVectorStore即可生产环境可选择 Chroma、FAISS、Redis、Milvus 等。4. 检索器统一的检索接口Retriever 封装了向量库的检索逻辑提供 “输入查询 → 输出相关 Document 列表” 的统一接口# 初始化检索器返回Top3相关文档 retriever vector_store.as_retriever(search_kwargs{k: 3}) # 检索相关文档 docs retriever.invoke(RAG的典型流程是什么) print(f检索到{len(docs)}条相关文档)5. 最小 RAG 闭环让模型 “基于资料回答”将检索器、提示词、模型、解析器串联形成完整 RAG 链路from langchain_core.runnables import RunnablePassthrough # 格式化检索结果为字符串 def format_docs(docs): return \n\n.join(doc.page_content for doc in docs) # 定义RAG提示词 prompt ChatPromptTemplate.from_messages([ (system, 你只能根据给定资料回答问题资料不足时明确说明。), (human, 问题{question}\n\n资料\n{context}), ]) # 构建RAG链 rag_chain ( {context: retriever | format_docs, question: RunnablePassthrough()} | prompt | model | StrOutputParser() ) # 调用RAG链 answer rag_chain.invoke(RAG的典型流程是什么) print(answer)这个闭环的核心价值在于模型回答完全基于检索到的私有资料避免幻觉当问题超出资料范围时模型会明确说明 “资料中没有足够信息”。六、从 RAG 到 Agent让模型自主决策是否检索固定 RAG 链的问题是 “无论问题是否需要都先检索”而 Agent 的思路是 “让模型自主判断是否调用工具包括检索器”。只需将 Retriever 包装为工具即可实现 Agent 雏形。1. 将 Retriever 封装为工具tool def search_langchain_notes(query: str) - str: Search local LangChain learning notes to answer questions. docs retriever.invoke(query) return format_docs(docs)2. 绑定检索工具到模型# 绑定检索工具 model_with_rag_tool model.bind_tools([search_langchain_notes])3. 模拟 Agent 决策流程# 用户问题 messages [HumanMessage(contentRAG的典型流程是什么)] # 模型判断是否调用检索工具 ai_msg model_with_rag_tool.invoke(messages) print(f是否调用工具{bool(ai_msg.tool_calls)}) # 执行检索工具 if ai_msg.tool_calls: for tool_call in ai_msg.tool_calls: if tool_call[name] search_langchain_notes: # 执行检索 tool_result search_langchain_notes.invoke(tool_call[args]) # 反馈结果给模型 messages.append(ToolMessage(contenttool_result, tool_call_idtool_call[id])) # 模型基于检索结果生成回答 final_msg model_with_rag_tool.invoke(messages) print(final_msg.content)此时流程变为用户问题 → 模型判断是否调用检索工具 → 执行检索 → 反馈结果 → 模型回答 —— 这就是 Agent 的雏形。七、学习总结与下一步规划1. 核心认知LangChain 的本质经过这段时间的学习我对 LangChain 的认知从 “抽象名词” 变为 “可落地的组件库”LangChain 不是模型而是 LLM 应用开发的标准化工具箱核心组件模型、消息、提示词、解析器、工具、检索器都是 Runnable可通过 LCEL 灵活串联Agent 不是魔法而是 “模型决策 工具执行” 的循环RAG 是 “检索 生成” 的组合流程可封装为 Agent 的一个工具。2. 已落地的核心 Demo通过逐个拆解组件我完成了以下关键 Demo覆盖 LangChain 核心场景main.py基础模型调用prompt_demo.py消息与提示词模板output_parser_demo.py输出解析与结构化输出document_splitter_demo.py文档加载与文本切分vector_store_demo.py向量生成与检索rag_demo.py最小 RAG 闭环retriever_tool_agent_demo.pyRetriever 作为工具的 Agent 雏形。这些 Demo 验证了一个核心学习方法先拆解每个组件的输入、输出和场景再组合成复杂应用远比直接背概念更有效。3. 下一步学习 LangGraph 构建复杂 Agent手写工具调用循环仅适用于简单场景复杂 Agent 需要状态管理、工具循环、多步推理、记忆持久化等能力 —— 这正是 LangGraph 的核心价值。如果说 LangChain 的组件是 “积木”LangGraph 就是 “搭建复杂机器的图纸”它能实现对话状态的持久化管理工具调用的自动循环多分支的条件执行人工确认环节的插入错误恢复与重试执行轨迹的可视化观察。八、初学者的学习建议先跑通再理解不要一开始就纠结概念先搭建环境、跑通最小模型调用建立正向反馈拆解组件学习逐个实现模型、提示词、解析器、工具、检索器的小 Demo搞清楚每个组件的输入输出重视 LCEL掌握|和 Runnable 的核心逻辑这是 LangChain 组件组合的基础从工具调用理解 AgentAgent 的核心是工具调用循环先手动实现这个循环再学习 LangGraph 的自动化方案RAG 先做最小闭环先实现 “加载 - 切分 - 向量 - 检索 - 生成” 的基础流程再优化检索精度、切分策略等细节。结语LangChain 的学习过程是从 “知其然” 到 “知其所以然” 的过程。它不是一套需要死记硬背的 API而是一套让 LLM 应用开发更高效的方法论。从第一次调用模型到理解 Agent 的雏形我最大的收获不是掌握了多少 API而是理解了 “如何将大模型的能力与外部工具结合解决实际问题”。后续我会继续深入 LangGraph将这些零散的 Demo 升级为可维护的 Agent 项目也会持续记录学习过程与各位开发者共勉。