文章目录
创作不易,请各位看官顺手点点关注,不胜感激 。
引言:从“调用API”到“构建智能”
LangChain的真正魅力在于组织和编排AI的能力,将一个通用的语言模型,升级为一个能使用工具、拥有记忆、并能自主决策的智能体(Agent)。
本章将带你在5分钟内,从零开始构建一个多功能的智能问答助手。(对于已配置好Python环境的开发者,整个过程仅需5分钟)
我们将构建的智能体能够:
- 🤖 深度理解:不止于表面,能理解用户的复杂意图。
- 🛠️ 调用工具:能查询实时天气、进行数学计算、上网搜索未知信息。
- 📝 拥有记忆:能记住之前的对话,进行有上下文的交流。
- 🤔 自主决策:能根据问题,智能地决定何时使用何种工具。
通过这个实战项目,你将真正掌握LangChain的核心思想和现代工程实践,为后续构建更复杂的AI应用(如RAG、AI数据分析师等)打下坚实的基础。
环境准备:工欲善其事,必先利其器
1. 系统要求
- Python版本:3.8 或更高版本
- 操作系统:Windows、macOS、Linux 均可
- 网络环境:需要能访问OpenAI API
2. 依赖安装
强烈推荐在虚拟环境中进行安装,这能确保项目依赖的纯净,避免与其他项目或系统库产生冲突。
# 创建项目目录
mkdir langchain-quickstart
cd langchain-quickstart
# 创建虚拟环境
python -m venv venv
# 激活虚拟环境
# Windows:
venv\Scripts\activate
# macOS/Linux:
source venv/bin/activate
# 安装核心依赖
pip install langchain>=0.2.0 langchain-openai>=0.1.0 langchain-community>=0.2.0
pip install python-dotenv==1.0.0 numexpr>=2.8.0 serpapi
3. 配置API密钥
为了安全地管理您的密钥,我们将其存储在环境变量文件中。在项目根目录下创建一个名为 .env
的文件。
# .env 文件内容
OPENAI_API_KEY="your_openai_api_key_here"
SERPAPI_API_KEY="your_serpapi_key_here" # 可选,用于搜索功能
核心概念速览:搭建智能体的“乐高积木”
在开始编码前,让我们用更生动的比喻来理解LangChain的几个核心组件:
组件 | 比喻 | 解释 |
---|---|---|
🧠 LLM | “AI的大脑” | 这是我们应用的核心智能来源,如同一个知识渊博但没有手脚的专家。它负责理解、推理和生成文本。 |
🔗 LCEL (Runnable) | “乐高连接器” | LangChain Expression Language是新一代的组装方式。它像乐高积木的连接栓,让你用 ` |
🛠️ Tool | “大脑的手脚” | 如果LLM是大脑,工具就是它的手、脚、眼睛和耳朵。工具让LLM能够与外部世界交互,执行计算、搜索、访问API等大脑本身做不到的操作。 |
🤖 Agent | “智能体本身” | Agent是大脑、手脚和行动逻辑的结合体。它是一个完整的“人”,能理解指令,自主决定“该用哪只手”(哪个工具)来完成任务。 |
💭 Memory | “短期记忆” | 它让我们的智能体不再是“金鱼”,能够记住对话的上下文。这对于多轮对话和理解后续问题至关重要。 |
现在,让我们用这些“乐高积木”来搭建我们的应用。
动手实践:一步步构建智能问答助手
我们将把整个过程分解,详细讲解每一步的意义。
步骤1:导入我们的“积木”
首先,创建一个 main.py
文件,并导入所有需要的库和模块。
# main.py
import os
import logging
from dotenv import load_dotenv
# --- LangChain 核心组件 ---
# LLM: 我们选择OpenAI的模型
from langchain_openai import ChatOpenAI
# 工具: 定义和使用工具的基础
from langchain.tools import Tool
# 记忆: 用于存储对话历史
from langchain.memory import ConversationBufferMemory
# Agent: 构建和执行智能体的核心
from langchain.agents import AgentExecutor, create_openai_tools_agent
# Prompt: 构造复杂的提示
from langchain_core.prompts import ChatPromptTemplate, MessagesPlaceholder
# --- 社区和第三方库 ---
# 搜索工具的具体实现
from langchain_community.utilities import SerpAPIWrapper
# 安全的数学计算库
import numexpr as ne
# 加载环境变量,让应用能获取到API密钥
load_dotenv()
# 配置基础日志,方便调试
logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s')
【讲解】:这里我们分门别类地导入了所需模块。langchain_openai
负责与OpenAI模型交互,langchain.agents
提供了构建现代智能体的函数,而 langchain_community
则包含了像搜索这类由社区贡献的实用工具。
步骤2:定义智能体的“超能力”——创建工具
我们的智能体需要一些超越语言模型本身的能力。我们将通过定义“工具”来实现。
# main.py (续)
# 工具1:天气查询
@Tool
def get_weather(city: str) -> str:
"""当需要查询天气时,调用此工具。输入应该是城市名称。"""
# 这是一个模拟实现,真实应用中可以对接真实的天气API
weather_data = {"北京": "晴,15-25°C", "上海": "多云,18-28°C", "广州": "小雨,20-26°C"}
return weather_data.get(city, f"抱歉,我没有“{city}”的天气数据。")
# 工具2:安全计算器
@Tool
def calculator(expression: str) -> str:
"""当需要进行数学计算时,调用此工具。输入应该是一个合法的数学表达式。"""
try:
return str(ne.evaluate(expression).item())
except Exception as e:
return f"计算错误: {e}"
# 工具3:在线搜索 (动态创建)
def create_search_tool():
if os.getenv("SERPAPI_API_KEY"):
logging.info("检测到SERPAPI_API_KEY,启用真实搜索工具。")
search = SerpAPIWrapper()
return Tool(name="在线搜索", description="当需要回答关于实时事件、最新信息或模型未知知识的问题时,使用此工具进行在线搜索。", func=search.run)
else:
logging.warning("未检测到SERPAPI_API_KEY,使用模拟搜索。")
@Tool
def mock_search(query: str) -> str:
"""模拟搜索工具,用于演示。"""
return f"关于“{query}”的模拟搜索结果:LangChain是一个强大的AI开发框架。"
return mock_search
tools = [get_weather, calculator, create_search_tool()]
【讲解】:
@Tool
装饰器: 这是定义工具最简洁的方式。它会自动将一个Python函数转换成LangChain可以使用的Tool
对象。- 文档字符串(Docstring)的重要性: 注意看每个函数下面的文档字符串,如
"""当需要查询天气时..."""
。这至关重要! Agent不是通过函数名,而是通过阅读这个描述来理解工具的功能和使用时机。描述写得越清晰、准确,Agent就越“聪明”。 - 动态工具创建: 我们检查了
SERPAPI_API_KEY
是否存在,从而动态决定是提供一个能真正上网的SerpAPIWrapper
工具,还是一个用于演示的模拟工具。这让我们的应用更具灵活性。
步骤3:初始化“大脑”和“记忆”
现在,我们需要为智能体配置核心的语言模型和记忆模块。
# main.py (续)
# 初始化大语言模型 (大脑)
llm = ChatOpenAI(
model="gpt-3.5-turbo",
temperature=0.7, # 控制回答的创造性,0表示最保守,1表示最奔放
)
# 初始化记忆模块 (短期记忆)
# `memory_key`必须与后面prompt中的占位符名称一致
memory = ConversationBufferMemory(memory_key="chat_history", return_messages=True)
【讲解】:
ChatOpenAI
: 我们选择了gpt-3.5-turbo
,因为它在速度、成本和性能之间取得了很好的平衡。temperature
是一个很有趣的参数,你可以尝试调整它来观察AI回答风格的变化。ConversationBufferMemory
: 这是最基础的记忆类型,它会原封不动地存储所有对话历史。对于长对话,可能会消耗大量Token。在进阶教程中,我们会学习更高效的记忆类型,如摘要记忆、窗口记忆等。
步骤4:构建智能体的“神经中枢”——Agent核心
这是最关键的一步,我们将使用LCEL(LangChain Expression Language)来组装我们的Agent。
# main.py (续)
# 1. 创建提示模板 (Prompt Template) - 这是Agent的行动指南
# MessagesPlaceholder是特殊占位符,用于插入一个消息列表
prompt = ChatPromptTemplate.from_messages([
("system", "你是一个强大的AI助手。你需要根据用户的请求,决定是否使用工具来辅助回答。"),
MessagesPlaceholder(variable_name="chat_history"),
("user", "{input}"),
MessagesPlaceholder(variable_name="agent_scratchpad"), # Agent的思考过程和工具输出
])
# 2. 创建Agent核心 (Runnable)
# 将LLM、工具和提示组合在一起
agent = create_openai_tools_agent(llm, tools, prompt)
# 3. 创建Agent执行器 (Executor)
# 这是最终的可运行对象,它负责调用Agent并执行其选择的工具
agent_executor = AgentExecutor(
agent=agent,
tools=tools,
memory=memory,
verbose=True, # 打印详细的执行过程,非常适合调试
handle_parsing_errors=True # 自动处理一些输出解析错误,增强稳定性
)
【讲解】:
- 提示模板 (
ChatPromptTemplate
): 这不仅仅是一段固定的文本,它是Agent的“行为准则”。system
: 定义了Agent的基本角色和指令。MessagesPlaceholder("chat_history")
: 告诉Agent在这里要插入对话历史。user, "{input}"
: 代表当前用户的输入。MessagesPlaceholder("agent_scratchpad")
: 这是Agent的“草稿纸”。它用来记录Agent的思考过程、调用了哪个工具、以及工具返回了什么结果。这是Agent进行推理的关键。
create_openai_tools_agent
: 这个函数是现代LangChain的推荐做法。它将LLM、工具列表和我们精心设计的Prompt“绑定”在一起,创建了一个知道如何使用工具的Agent核心逻辑。AgentExecutor
: 如果说agent
是决策者,那么agent_executor
就是执行者。它构建了一个完整的循环:接收用户输入 -> 交给Agent决策 -> 如果Agent决定用工具,就去执行工具 -> 将工具结果返回给Agent -> Agent再次决策… 直到任务完成,生成最终答案。verbose=True
会让我们能清晰地看到这个循环的每一步。
步骤5:创建交互界面并运行!
最后,我们编写一个简单的命令行界面来与我们的智能体互动。
# main.py (续)
def chat_with_agent():
"""主函数,运行聊天界面"""
print("\n" + "="*60)
print("🎉 欢迎使用LangChain智能问答助手!")
print(" - 我可以查天气、做计算、上网搜索。")
print(" - 输入 'quit' 或 'exit' 退出程序。")
print("="*60 + "\n")
while True:
try:
user_input = input("🙋 你: ").strip()
if user_input.lower() in ['quit', 'exit', '退出']:
print("\n👋 感谢使用,再见!")
break
if not user_input:
continue
# 调用AgentExecutor来处理输入
# invoke方法返回一个包含所有步骤信息的字典
response = agent_executor.invoke({"input": user_input})
print(f"\n🤖 助手: {response['output']}\n")
print("-" * 50)
except Exception as e:
logging.error(f"发生错误: {e}", exc_info=True)
print(f"\n❌ 出现错误: {e}")
if __name__ == "__main__":
chat_with_agent()
【讲解】:
agent_executor.invoke()
: 这是我们与Agent交互的入口。我们传递一个字典,其中"input"
键对应着Prompt中的{input}
占位符。response['output']
:invoke
方法返回的是一个字典,其中包含了丰富的调试信息,如输入、输出、中间步骤等。我们通常将'output'
键对应的值展示给用户。
【附】完整代码整合
为了方便您直接复制和完整运行,这里提供了整合了以上所有步骤的完整 main.py
文件。
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
LangChain快速入门示例:智能问答助手 (v2.1 - 终极版)
功能特性:
- 天气查询 (模拟)
- 数学计算 (安全)
- 信息搜索 (真实API或模拟)
- 对话记忆
- 智能工具选择 (基于现代LCEL)
作者: LangChain实战专栏
版本: 2.1.0
"""
import os
import logging
from dotenv import load_dotenv
# --- LangChain 核心组件 ---
from langchain_openai import ChatOpenAI
from langchain.tools import Tool
from langchain.memory import ConversationBufferMemory
from langchain.agents import AgentExecutor, create_openai_tools_agent
from langchain_core.prompts import ChatPromptTemplate, MessagesPlaceholder
# --- 社区和第三方库 ---
from langchain_community.utilities import SerpAPIWrapper
import numexpr as ne
def setup_logging():
"""配置基础日志"""
logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s')
def create_tools():
"""创建一个工具列表,供Agent使用"""
@Tool
def get_weather(city: str) -> str:
"""当需要查询天气时,调用此工具。输入应该是城市名称。"""
weather_data = {"北京": "晴,15-25°C", "上海": "多云,18-28°C", "广州": "小雨,20-26°C"}
return weather_data.get(city, f"抱歉,我没有“{city}”的天气数据。")
@Tool
def calculator(expression: str) -> str:
"""当需要进行数学计算时,调用此工具。输入应该是一个合法的数学表达式。"""
try:
return str(ne.evaluate(expression).item())
except Exception as e:
return f"计算错误: {e}"
if os.getenv("SERPAPI_API_KEY"):
logging.info("检测到SERPAPI_API_KEY,启用真实搜索工具。")
search = SerpAPIWrapper()
search_tool = Tool(name="在线搜索", description="当需要回答关于实时事件、最新信息或模型未知知识的问题时,使用此工具进行在线搜索。", func=search.run)
else:
logging.warning("未检测到SERPAPI_API_KEY,使用模拟搜索。")
@Tool
def mock_search(query: str) -> str:
"""模拟搜索工具,用于演示。"""
return f"关于“{query}”的模拟搜索结果:LangChain是一个强大的AI开发框架。"
search_tool = mock_search
return [get_weather, calculator, search_tool]
def main():
"""应用主入口"""
setup_logging()
load_dotenv()
# 1. 初始化组件
tools = create_tools()
llm = ChatOpenAI(model="gpt-3.5-turbo", temperature=0.7)
memory = ConversationBufferMemory(memory_key="chat_history", return_messages=True)
# 2. 创建Agent
prompt = ChatPromptTemplate.from_messages([
("system", "你是一个强大的AI助手。你需要根据用户的请求,决定是否使用工具来辅助回答。"),
MessagesPlaceholder(variable_name="chat_history"),
("user", "{input}"),
MessagesPlaceholder(variable_name="agent_scratchpad"),
])
agent = create_openai_tools_agent(llm, tools, prompt)
agent_executor = AgentExecutor(
agent=agent,
tools=tools,
memory=memory,
verbose=True,
handle_parsing_errors=True
)
# 3. 启动聊天循环
print("\n" + "="*60)
print("🎉 欢迎使用LangChain智能问答助手!")
print(" - 我可以查天气、做计算、上网搜索。")
print(" - 输入 'quit' 或 'exit' 退出程序。")
print("="*60 + "\n")
while True:
try:
user_input = input("🙋 你: ").strip()
if user_input.lower() in ['quit', 'exit', '退出']:
print("\n👋 感谢使用,再见!")
break
if not user_input:
continue
response = agent_executor.invoke({"input": user_input})
print(f"\n🤖 助手: {response['output']}\n")
print("-" * 50)
except Exception as e:
logging.error(f"发生错误: {e}", exc_info=True)
print(f"\n❌ 出现错误: {e}")
if __name__ == "__main__":
main()
深度解析:Agent是如何“思考”的?
当你设置了 verbose=True
并向Agent提问(例如:“上海今天天气怎么样?适合穿短袖吗?”)时,你会看到一段非常有趣的输出。这揭示了Agent的“内心活动”。让我们来解读一下这个过程:
-
> Entering new AgentExecutor chain…
- 执行器接收到你的问题:“上海今天天气怎么样?适合穿短袖吗?”
-
LLM的第一次思考 (Thought):
- 模型分析问题,发现它包含两个部分:1. 查询上海天气;2. 根据天气判断是否适合穿短袖。
- 它意识到自己不知道实时的天气,但它有一个
get_weather
工具。 - 决策: 调用
get_weather
工具,输入参数为"上海"
。
-
执行工具 (Action & Observation):
AgentExecutor
捕获到这个决策,暂停LLM,并执行get_weather("上海")
函数。- 函数返回结果:
"多云,18-28°C"
。这个结果被称为Observation(观察)。
-
LLM的第二次思考 (Thought):
AgentExecutor
将工具的返回结果(观察)重新交给LLM,并附上原始问题。- 现在,LLM掌握了新的信息:
"上海天气是多云,18-28°C"
。 - 它回顾整个问题:“上海今天天气怎么样?适合穿短袖吗?”。
- 它已经回答了第一部分。对于第二部分,它利用自己的常识进行推理:“28°C的最高温度对于大多数人来说,穿短袖是合适的。”
- 决策: 我已经拥有足够的信息来回答用户了,不需要再调用其他工具。
-
生成最终答案 (Final Answer):
- LLM组织语言,生成一个完整、友好的回答,例如:“上海今天是多云,温度在18到28摄氏度之间。最高28度的天气,白天穿短袖是完全合适的,不过早晚可能会有点凉,建议带一件薄外套。”
-
> Finished chain.
- 执行器将最终答案返回给用户,并结束本次调用。
这个“思考 -> 行动 -> 观察 -> 再思考”的循环,就是所有LangChain Agent工作的核心模式,也被称为**ReAct (Reasoning and Acting)**框架。
总结与展望
🎉 恭喜你!不仅构建了您的第一个LangChain应用,更重要的是,深入理解了其背后的工作原理。
回顾一下已掌握的技能:
- 现代化的Agent构建: 使用LCEL、
create_openai_tools_agent
和AgentExecutor
搭建应用。 - 强大的工具系统: 学会了如何为AI赋予外部能力,并理解了
description
的重要性。 - 上下文记忆: 实现了能进行多轮对话的记忆管理。
- 原理级理解: 洞悉了Agent “思考-行动-观察” 的ReAct工作流。
🌟 如果这篇文章对您有深刻的启发,请点赞收藏,并分享给更多渴望探索AI开发的朋友!