
LangChain 是一个专门为大语言模型应用开发设计的开源框架。它提供了一套完整的工具和组件,帮助开发者构建基于大语言的复杂应用程序,如智能对话系统、知识问答平台、内容生成工具等。 LangChain 的设计基于几个关键理念:模块化、可组合性和扩展性。它将复杂的语言模型应用开发过程分解为多个独立的组件,每个组件负责特定的功能,开发者可以根据需要灵活选择和组合这些组件。基础内容可参考《构建AI智能体:解密LangChain中的RAG架构:让AI模型突破局限学会“翻书”答题》


LangChain 将多个组件智能地串联起来,以完成复杂任务。其中最关键的角色是 Agent,它是整个工作流的大脑,负责协调和控制流程。上述流程可以分解为以下几个关键阶段:
2.1 输入与接收
2.2 决策与执行循环 - 核心部分
2.3 输出与记忆更新
组件 | 角色 | 关键职责 |
|---|---|---|
Input | 起点 | 接收用户提出的自然语言问题或指令 |
Agent | 大脑 | 接收输入,统筹整个处理过程,决定执行步骤 |
Memory | 记忆库 | 为 Agent 和大模型提供之前的对话历史或关键信息作为上下文 |
大模型 | 推理引擎 | 根据输入、记忆和上一步的观察进行推理,决定调用工具或直接回答 |
Tools | 手脚 | 执行具体的任务(如计算、搜索、查数据库等),并将结果返回给大模型 |
Output | 终点 | 输出最终生成的答案或结果给用户 |
Update Memory | 闭环 | 将本轮有价值的对话内容保存下来,为后续交互提供上下文,实现连贯性 |
Tools 是 LangChain 中让语言模型与外部世界交互的接口。它们本质上是包装了特定功能的函数,为大模型提供超越其固有知识的能力,模型通过描述来理解这个工具能做什么,包含三个核心要素:
每个 Tool 包含三个基本要素:
class Tool:
name: str # 工具的唯一标识符
description: str # 功能的详细描述,用于LLM理解何时使用
func: Callable # 实际执行功能的函数
类别 | 代表工具 | 核心功能 | 应用场景 |
|---|---|---|---|
搜索检索类 | GoogleSearch, Wikipedia | 信息查询和获取 | 研究、事实核查 |
计算分析类 | PythonREPL, Calculator | 数据处理和计算 | 数据分析、科学计算 |
数据存储类 | SQLDatabase, CSVLoader | 数据库操作 | 业务系统集成 |
API服务类 | Requests, OpenWeatherMap | 外部服务调用 | 第三方服务集成 |
文件操作类 | FileTool, DirectoryTool | 文件系统管理 | 文档处理、数据导入导出 |

LangChain 的 Tools 系统为大型语言模型提供了强大的能力扩展机制,不仅突破模型限制,而且极大的增强应用能力。通过合理使用内置工具、开发自定义工具、实施有效的工具管理策略,可以构建出功能丰富、性能优异、稳定可靠的AI应用系统。关键成功因素包括:清晰的工具设计、完善的错误处理、性能优化措施以及持续的工具生态建设。
Memory 是 LangChain 中用于存储和检索对话历史的组件,使 AI 应用能够记住先前的交互。它解决了大型语言模型固有的无状态问题,让对话能够保持上下文连贯性。核心功能包括:
2.1 ConversationBufferMemory
from langchain.memory import ConversationBufferMemory
memory = ConversationBufferMemory()
memory.save_context({"input": "你好"}, {"output": "你好!我是AI助手。"})
memory.save_context({"input": "你叫什么名字?"}, {"output": "我叫minhuan。"})
# 查看内存内容
print(memory.load_memory_variables({}))
# 输出: {'history': 'Human: 你好\nAI: 你好!我是AI助手。\nHuman: 你叫什么名字?\nAI: 我叫minhuan。'}2.2 ConversationBufferWindowMemory
from langchain.memory import ConversationBufferWindowMemory
# 只保留最近2轮对话
memory = ConversationBufferWindowMemory(k=2)
memory.save_context({"input": "你好"}, {"output": "你也好"})
memory.save_context({"input": "高兴遇见你"}, {"output": "也很高兴遇见你"})
memory.save_context({"input": "再见!"}, {"output": "好的,再见!"})
print(memory.load_memory_variables({}))
# 输出: {'history': 'Human: 高兴遇见你\nAI: 也很高兴遇见你\nHuman: 再见!\nAI: 好的,再见!'}2.3 ConversationSummaryMemory
from langchain.memory import ConversationSummaryMemory
from langchain_community.chat_models.tongyi import ChatTongyi
llm = ChatTongyi(model="qwen-max", dashscope_api_key="你的API_KEY")
memory = ConversationSummaryMemory(llm=llm)
# 添加多轮对话
for i in range(5):
memory.save_context(
{"input": f"问题{i}: 关于天气的讨论"},
{"output": f"回答{i}: 今天天气晴朗,温度适宜"}
)
print(memory.load_memory_variables({}))
# 输出: {'history': '摘要: 对话主要讨论了天气情况,多次提到今天天气晴朗且温度适宜。'} 2.4 ConversationEntityMemory
from langchain.memory import ConversationEntityMemory
from langchain.memory.prompt import ENTITY_EXTRACTION_PROMPT, ENTITY_SUMMARIZATION_PROMPT
memory = ConversationEntityMemory(llm=llm)
# 添加包含实体的对话
memory.save_context(
{"input": "张三喜欢在北京工作"},
{"output": "北京是个好城市"}
)
memory.save_context(
{"input": "李四在上海读书"},
{"output": "上海有很多好大学"}
)
# 查看记忆的实体
print(memory.load_memory_variables({"input": "张三在哪里工作?"}))
# 输出会包含实体信息,如: {'history': '...', 'entities': {'张三': '张三喜欢在北京工作'}}2.5 VectorStoreRetrieverMemory
from langchain.memory import VectorStoreRetrieverMemory
from langchain_community.vectorstores import FAISS
from langchain_community.embeddings import HuggingFaceEmbeddings
from langchain.schema import Document
import os
# 初始化嵌入模型
# embeddings = HuggingFaceEmbeddings(model_name="sentence-transformers/all-MiniLM-L6-v2")
embeddings = HuggingFaceEmbeddings(model_name="D:/modelscope/hub/models/sentence-transformers/paraphrase-MiniLM-L6-v2")
# 创建或加载 FAISS 向量存储
persist_directory = "./faiss_db"
if os.path.exists(persist_directory):
# 如果存在已有的 FAISS 索引,则加载
vectorstore = FAISS.load_local(
persist_directory,
embeddings,
allow_dangerous_deserialization=True
)
print("已加载现有的 FAISS 向量数据库")
else:
# 否则创建新的向量存储
# 初始时可以添加一些空文档或示例文档
initial_docs = [Document(page_content="初始文档", metadata={"type": "initial"})]
vectorstore = FAISS.from_documents(initial_docs, embeddings)
# 保存向量存储到本地
vectorstore.save_local(persist_directory)
print("创建了新的 FAISS 向量数据库")
# 创建基于 FAISS 向量存储的记忆系统
memory = VectorStoreRetrieverMemory(
retriever=vectorstore.as_retriever(
search_type="similarity",
search_kwargs={"k": 3} # 检索最相关的3条记忆
)
)
# 保存记忆
memory.save_context(
{"input": "我最喜欢的颜色是蓝色"},
{"output": "好的,已记住你喜欢的颜色"}
)
# 保存更多记忆示例
memory.save_context(
{"input": "我来自北京"},
{"output": "北京是中国的首都,很繁华的城市"}
)
memory.save_context(
{"input": "我喜欢吃苹果和香蕉"},
{"output": "水果很健康,已记住你的喜好"}
)
# 回忆记忆 - 基于语义相似性搜索
query = "我喜欢什么颜色?"
memories = memory.load_memory_variables({"input": query})
print(f"查询: '{query}'")
print("检索到的记忆:", memories)
# 测试另一个查询
query = "我来自哪里?"
memories = memory.load_memory_variables({"input": query})
print(f"\n查询: '{query}'")
print("检索到的记忆:", memories)
# 保存向量存储的更改
vectorstore.save_local(persist_directory)
print("\n记忆已保存到FAISS数据库")
LangChain 的 Memory 系统为构建有状态的 AI 应用提供了强大基础。通过合理选择和组合不同的 Memory 类型,可以创建出能够理解上下文、记住用户偏好、并提供个性化体验的智能应用。
关键要点:
ReAct(Reasoning + Acting)是一个让大型语言模型能够进行推理并采取行动的框架。它是 LangChain 中 Agent(代理)的核心工作模式,使大模型不仅能够生成文本,还能智能地决定何时以及如何使用外部工具来解决问题。
ReAct 框架的核心思想是模仿人类解决问题的过程:
这个过程会循环进行,直到问题被解决。
3.1 基本工作流程

3.2 结构化输出格式
ReAct 要求大模型按照特定格式进行输出,以便系统能够解析和执行:
Thought: [大模型分析当前情况,决定下一步行动]
Action: [要使用的工具名称]
Action Input: [工具的输入参数]
Observation: [工具执行的结果]
...(这个循环可以重复多次)
Thought: 我现在有最终答案了
Final Answer: [最终的回答]假设用户问:"1989年出生是多少岁了?然后在平方根是多少?"
ReAct 框架的处理过程:


2.2.1 依赖管理与环境设置
def check_and_install_dependencies():
"""检查并安装必要的依赖"""
required_packages = [
"langchain",
"langchain-community",
"langchain-core",
"dashscope",
"wikipedia",
"pydantic>=2.0.0",
"typing-extensions>=4.0.0"
]
# ... 检查并安装缺失的包2.2.2 大模型初始化与配置
def initialize_llm():
"""初始化Qwen语言模型"""
try:
# 获取API密钥,如果环境变量不存在则提示用户
api_key = os.environ.get("DASHSCOPE_API_KEY")
if not api_key:
print_formatted_log("WARNING", "环境变量 DASHSCOPE_API_KEY 未设置")
print_formatted_log("INFO", "请输入通义千问API密钥:")
api_key = input().strip()
# ... 设置环境变量
# 初始化模型
llm = ChatTongyi(
model="qwen-max",
dashscope_api_key=api_key
)
return llm
except Exception as e:
logger.error(f"初始化语言模型失败: {str(e)}")
raise2.2.3 工具系统实现
def initialize_tools(llm):
"""初始化所有可用工具"""
# 初始化 Wikipedia 工具(带错误处理)
try:
wikipedia_api_wrapper = WikipediaAPIWrapper()
wikipedia_tool = WikipediaQueryRun(api_wrapper=wikipedia_api_wrapper)
except ImportError as e:
logger.warning(f"无法加载 Wikipedia 工具: {str(e)}")
# 创建替代工具
# 自定义工具
custom_tools = [
Tool(
name="SquareRootCalculator",
func=calculate_square_root,
description="当需要计算一个数的平方根时使用此工具..."
),
Tool(
name="StringReverser",
func=reverse_string,
description="当需要反转一个字符串时使用此工具。输入应该是一个字符串。"
),
Tool(
name="TimeGetter",
func=get_current_time,
description="当需要获取当前日期和时间时使用此工具。输入可以是空字符串或任何内容。"
)
# ... 其他工具
]
# 组合所有工具
tools = []
if wikipedia_tool:
tools.append(wikipedia_tool)
tools.extend(custom_tools)
return tools2.2.4 自定义工具函数
# 2. 自定义工具函数
def calculate_square_root(input_str):
"""计算一个数的平方根"""
logger.info(f"调用 calculate_square_root 工具,输入: {input_str}")
try:
number = float(input_str)
result = math.sqrt(number)
logger.info(f"计算平方根成功: {number} 的平方根是 {result}")
return result
except ValueError:
error_msg = f"输入 '{input_str}' 不是有效的数字"
logger.error(error_msg)
return error_msg
def reverse_string(input_str):
"""反转字符串"""
logger.info(f"调用 reverse_string 工具,输入: {input_str}")
result = input_str[::-1]
logger.info(f"字符串反转成功: '{input_str}' 反转为 '{result}'")
return result2.2.5 记忆系统实现
def initialize_memory():
"""初始化对话记忆"""
memory = ConversationBufferMemory(
memory_key="chat_history",
output_key="output", # 显式设置输出键
return_messages=True
)
return memory2.2.6 ReAct 代理创建
def create_agent(llm, tools, memory):
"""创建React Agent"""
# ReAct 提示模板
template = """
你是一个多功能AI助手,可以使用多种工具解决问题...
可用的工具:
{tools}
使用格式:
Thought: 我需要使用工具吗?...
Action: 要执行的动作...
Action Input: 工具的输入...
Observation: 工具执行的结果...
...
"""
# 创建提示模板
prompt = PromptTemplate(
template=template,
input_variables=["chat_history", "input", "agent_scratchpad"],
partial_variables={
"tool_names": ", ".join([tool.name for tool in tools]),
"tools": "\n".join([f"{tool.name}: {tool.description}" for tool in tools])
}
)
# 创建代理执行器
agent_executor = AgentExecutor(
agent=create_react_agent(llm, tools, prompt),
tools=tools,
memory=memory,
verbose=True,
handle_parsing_errors=True,
max_iterations=5, # 防止无限循环
return_intermediate_steps=True # 避免回调错误
)
return agent_executor2.2.7 自定义回调系统
class CustomCallbackHandler(BaseCallbackHandler):
"""自定义回调处理器,用于处理LangChain的回调事件"""
def on_chain_start(self, serialized, inputs, **kwargs):
"""链开始时的回调"""
# 添加对 serialized 为 None 的检查
if serialized is not None and hasattr(serialized, "get"):
chain_type = serialized.get("name", "未知链")
logger.info(f"开始执行链: {chain_type}")
# ... 其他回调方法(on_tool_start, on_llm_start等)2.2.8 主程序与用户交互
def main():
"""主函数"""
# 初始化所有组件
llm = initialize_llm()
tools = initialize_tools(llm)
memory = initialize_memory()
agent_executor = create_agent(llm, tools, memory)
# 主循环
while True:
user_input = input("\nYou: ").strip()
if user_input.lower() == 'exit':
break # 退出程序
if user_input.lower() == 'history':
# 显示对话历史
history = memory.load_memory_variables({})
if 'chat_history' in history and history['chat_history']:
print_formatted_log("INFO", "对话历史:")
for msg in history['chat_history']:
role = "Human" if msg.type == "human" else "AI"
print_formatted_log("DEBUG", f" {role}: {msg.content}")
continue
# 处理用户请求
try:
response = agent_executor.invoke(
{"input": user_input},
{"callbacks": CallbackManager([CustomCallbackHandler()])}
)
if "output" in response:
print_formatted_log("SUCCESS", f"Assistant: {response['output']}")
except Exception as e:
logger.error(f"执行Agent时出错: {str(e)}")
print_formatted_log("ERROR", f"执行失败: {str(e)}")2.2.9 使用示例
运行程序后,用户可以:
这个实现展示了如何构建一个健壮、功能丰富的LangChain多工具智能体,适合作为更复杂应用的基础框架。
启动成功的提示信息,供初始化了5个工具:
[INFO] ==================================================
[INFO] LangChain多工具智能体启动
[INFO] ==================================================
2025-09-13 14:12:04,249 - LangChainAgent - INFO - Qwen语言模型初始化成功
2025-09-13 14:12:04,250 - LangChainAgent - INFO - 开始初始化工具
2025-09-13 14:12:04,250 - LangChainAgent - INFO - 搜狗百科工具加载成功
2025-09-13 14:12:04,251 - LangChainAgent - INFO - 共初始化了 5 个工具
2025-09-13 14:12:04,251 - LangChainAgent - INFO - 工具 1: SogouBaikeSearch - 搜索搜狗百科的工具。输入应该是一个搜索查询。
2025-09-13 14:12:04,251 - LangChainAgent - INFO - 工具 2: SquareRootCalculator - 当需要计算一个数的平方根时使用此工具。输入应该是一个数字。
2025-09-13 14:12:04,252 - LangChainAgent - INFO - 工具 3: StringReverser - 当需要反转一个字符串时使用此工具。输入应该是一个字符串。
2025-09-13 14:12:04,252 - LangChainAgent - INFO - 工具 4: TimeGetter - 当需要获取当前日期和时间时使用此工具。输入可以是空字符串或任何内容。
2025-09-13 14:12:04,253 - LangChainAgent - INFO - 工具 5: RequestsGetTool - 当需要获取网页内容时使用此工具。输入应该是一个有效的URL,以http://或https://开头
。
2025-09-13 14:12:04,254 - LangChainAgent - INFO - 对话记忆系统初始化成功
2025-09-13 14:12:04,256 - LangChainAgent - INFO - React Agent创建成功
2025-09-13 14:12:04,257 - LangChainAgent - INFO - Agent执行器创建成功
[SUCCESS] 系统初始化完成,多工具AI助手已就绪
[INFO] 可用工具:
[INFO] 1. SogouBaikeSearch: 搜索搜狗百科的工具。输入应该是一个搜索查询。
[INFO] 2. SquareRootCalculator: 当需要计算一个数的平方根时使用此工具。输入应该是一个数字。
[INFO] 3. StringReverser: 当需要反转一个字符串时使用此工具。输入应该是一个字符串。
[INFO] 4. TimeGetter: 当需要获取当前日期和时间时使用此工具。输入可以是空字符串或任何内容。
[INFO] 5. RequestsGetTool: 当需要获取网页内容时使用此工具。输入应该是一个有效的URL,以http://或https://开头。
[INFO] 输入 'exit' 退出程序,输入 'history' 查看对话历史输入查询语句:1989年出生是多少岁了?然后在平方根是多少?
结果显示:
You: 1989年出生是多少岁了?然后在平方根是多少?
2025-09-13 14:13:03,194 - LangChainAgent - INFO - 用户输入: 1989年出生是多少岁了?然后在平方根是多少?
[INFO] 处理中...
2025-09-13 14:13:03,197 - LangChainAgent - INFO - 开始执行链: 未知链
Thought: 要回答这个问题,首先我需要计算1989年出生的人到现在(2023年假设)是多少岁了。这可以通过从当前年份减去出生年份来得到。之后,我还需要计算这个年龄的平
方根。为了获取当前年份,我将使用TimeGetter工具;然后利用得到的信息计算年龄,并最后通过SquareRootCalculator工具来求得该年龄的平方根。
Action: TimeGetter
Action Input: 2025-09-13 14:13:11,219 - LangChainAgent - INFO - 调用 get_current_time 工具
2025-09-13 14:13:11,220 - LangChainAgent - INFO - 当前时间: 2025年09月13日 14:13:11
2025年09月13日 14:13:11现在我们知道当前年份是2025年。接下来,我将用2025年来减去1989年来计算年龄。
\[ 年龄 = 2025 - 1989 \]
这将给出一个人如果在1989年出生的话到2025年的年龄是多少。然后,我会使用SquareRootCalculator工具来计算这个年龄的平方根。
Action: SquareRootCalculator
Action Input: 362025-09-13 14:13:15,690 - LangChainAgent - INFO - 调用 calculate_square_root 工具,输入: 36
2025-09-13 14:13:15,691 - LangChainAgent - INFO - 计算平方根成功: 36.0 的平方根是 6.0
6.0我现在已经知道了1989年出生的人到2025年的年龄是36岁,并且计算出了这个年龄的平方根为6.0。
Final Answer: 一个1989年出生的人到2025年将是36岁,这个年龄的平方根大约是6.0。
2025-09-13 14:13:19,637 - LangChainAgent - INFO - 链执行完成,输出为字典类型
> Finished chain.
[SUCCESS] Assistant: 一个1989年出生的人到2025年将是36岁,这个年龄的平方根大约是6.0。下面我直接输入一个网页地址,看看工具调用过程:

自动分析并使用了 RequestsGetTool工具,获取回来了网页内容;
接下来,继续输入指令“输出标题内容”,看看它是否产生了记忆,可以直接输出标题:
You: 输出标题内容
2025-09-13 14:19:52,281 - LangChainAgent - INFO - 用户输入: 输出标题内容
[INFO] 处理中...
2025-09-13 14:19:52,285 - LangChainAgent - INFO - 开始执行链: 未知链
Thought: 为了获取网页的具体标题内容,我需要使用RequestsGetTool工具来抓取页面信息。
Action: RequestsGetTool
Action Input: 404 14:19:55,655 - LangChainAgent - INFO - 调用 requests_get_tool 工具,URL: 构建AI智能体:十八、解密LangChain中的RAG架构:让AI模型突破局限学会“翻书”答题-CSDN博客
2025-09-13 14:19:56,070 - LangChainAgent - INFO - HTTP请求成功,返回内容长度: 169991 字符
状态码: 200
内容类型: text/html;charset=utf-8
内容预览:
<!DOCTYPE html>
<html lang="zh-CN">
......
<meta name="keywords" content="构建AI智能体:十八、解密LangChain中的RAG架构:让AI模型突破局限学会“翻书”答题">
<meta name="description" cont...我已经找到了网页的标题内容。
Final Answer: 构建AI智能体:十八、解密LangChain中的RAG架构:让AI模型突破局限学会“翻书”答题-CSDN博客
2025-09-13 14:19:58,233 - LangChainAgent - INFO - 链执行完成,输出为字典类型基于上下文的记忆,完成了指令内容
Tools、Memory和ReAct框架的协同工作构成了LangChain最强大的能力体现,三者通过精密的协作机制实现智能应用的完整功能闭环。在这个协同体系中,数据流遵循着精心设计的路径:
这种协同机制的实际应用需要精心设计的架构,通常采用分层设计理念,包括:
性能优化策略也需要贯穿整个架构,包括Tools的异步执行和缓存机制、Memory的分层存储和压缩策略、以及ReAct的迭代控制和超时管理。监控和日志系统也至关重要,需要跟踪每个组件的性能指标和使用情况,为持续优化提供数据支持。这种精心设计的协同工作模式使得构建的AI应用不仅功能强大,而且高效可靠,能够处理各种复杂场景下的智能任务需求。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。