1. 引言:什么是 AI Agent?
在人工智能领域,AI Agent(智能体)是指能够感知环境、自主决策并执行行动以实现特定目标的程序实体。与传统脚本或简单 API 调用不同,AI Agent 具备规划、记忆、工具使用和反思等高级能力,使其能够处理复杂的多步骤任务。
LangChain 作为一个强大的框架,为构建此类 Agent 提供了模块化、可扩展的组件,大大降低了开发门槛。本文将带你从零开始,使用 LangChain 构建一个具备基础能力的 AI Agent。
2. 环境准备与安装
首先,确保你的 Python 环境版本在 3.8 及以上。我们使用 pip 安装必要的包:
pip install langchain langchain-openai langchain-community此外,你需要一个 OpenAI API 密钥(或其他兼容 LangChain 的 LLM 服务密钥)来驱动 Agent 的“大脑”。将其设置为环境变量:
export OPENAI_API_KEY='your-api-key-here'3. 核心组件解析
在 LangChain 中,构建一个 Agent 通常涉及以下几个核心部分:
- LLM (大语言模型):Agent 的决策核心,如 GPT-4。
- Tools (工具):Agent 可以调用的外部函数,如搜索、计算、数据库查询。
- Agent Executor:运行 Agent 的引擎,负责协调 LLM 的思考、工具调用和结果处理。
- Memory (记忆):使 Agent 能够在多轮对话中记住上下文。
- Prompt Template (提示词模板):指导 LLM 如何思考、规划和选择工具。
4. 构建你的第一个 Agent
让我们构建一个能进行数学计算和网络搜索的简单 Agent。
4.1 定义工具
首先,我们创建两个工具:一个计算器和一个搜索工具(这里用 DuckDuckGo 搜索作为示例)。
from langchain.tools import Tool from langchain_community.tools import DuckDuckGoSearchRun import math def calculator(input_str: str) -> str: """计算一个数学表达式。""" try: # 安全评估数学表达式 result = eval(input_str, {"builtins": {}}, {"math": math}) return str(result) except Exception as e: return f"计算错误: {e}" 创建工具实例 calc_tool = Tool( name="Calculator", func=calculator, description="用于计算数学表达式,例如:'3 * 5 + 2' 或 'math.sqrt(16)'。" ) search_tool = DuckDuckGoSearchRun() 工具列表 tools = [calc_tool, search_tool]4.2 初始化 LLM 和 Agent
我们使用 OpenAI 的模型,并选择 LangChain 内置的“零样本反应式”Agent 类型,它适合简单工具调用。
from langchain_openai import ChatOpenAI from langchain.agents import initialize_agent, AgentType llm = ChatOpenAI(model="gpt-3.5-turbo", temperature=0) agent = initialize_agent( tools, llm, agent=AgentType.ZERO_SHOT_REACT_DESCRIPTION, # 使用零样本反应式策略 verbose=True, # 打印详细思考过程 handle_parsing_errors=True # 优雅处理解析错误 )4.3 运行 Agent
现在,你可以向 Agent 提问了!
result = agent.run("请先计算 15 的平方根,然后搜索一下 LangChain 的最新版本是什么。") print(result)当verbose=True时,你将在控制台看到 Agent 的完整思考链(ReAct 模式):
- Thought:我需要先计算平方根,然后再搜索。
- Action:调用 Calculator 工具,输入 “math.sqrt(15)”。
- Observation:工具返回计算结果 “3.872983346207417”。
- Thought:现在我需要搜索 LangChain 的最新版本。
- Action:调用 DuckDuckGo Search 工具。
- Observation:搜索返回相关信息。
- Final Answer:整合信息并给出最终回答。
5. 为 Agent 添加记忆能力
上面的 Agent 是“无状态”的。为了让它在多轮对话中记住上下文,我们需要引入 Memory。
from langchain.memory import ConversationBufferMemory memory = ConversationBufferMemory(memory_key="chat_history", return_messages=True) 重新初始化带记忆的 Agent agent_with_memory = initialize_agent( tools, llm, agent=AgentType.CONVERSATIONAL_REACT_DESCRIPTION, # 使用支持对话的 Agent 类型 verbose=True, memory=memory, handle_parsing_errors=True ) 第一轮对话 response1 = agent_with_memory.run("我的名字是小明。") print(response1) 第二轮对话,Agent 会记得上一轮的内容 response2 = agent_with_memory.run("我刚才说我叫什么名字?") print(response2) # 应该能回答“小明”6. 进阶:自定义工具与复杂工作流
LangChain 的强大之处在于其模块化。你可以轻松集成自定义 API、数据库或任何函数作为工具。
6.1 自定义工具示例:获取天气
import requests def get_weather(city: str) -> str: """获取指定城市的天气(模拟函数)。""" # 这里应调用真实的天气 API,此处为模拟 weather_data = { "北京": "晴,25°C", "上海": "多云,23°C", "深圳": "阵雨,28°C" } return weather_data.get(city, f"未找到{city}的天气信息") weather_tool = Tool( name="GetWeather", func=get_weather, description="根据城市名称查询天气,输入格式:'城市名',例如:'北京'。" ) 将新工具加入列表,重新创建 Agent advanced_tools = [calc_tool, search_tool, weather_tool] advanced_agent = initialize_agent(advanced_tools, llm, agent=AgentType.ZERO_SHOT_REACT_DESCRIPTION, verbose=True) result = advanced_agent.run("今天北京的天气怎么样?然后计算一下 98 除以 7。") print(result)6.2 使用 Agent 执行序列(Sequential Chain)
对于更复杂的任务,你可以将多个 Agent 或 LLM 调用串联起来。
from langchain.chains import LLMChain, SimpleSequentialChain from langchain.prompts import PromptTemplate 第一个链:生成问题 template1 = """你是一个问题生成器。根据主题:{topic},生成一个有趣的问题。只输出问题。""" prompt1 = PromptTemplate(input_variables=["topic"], template=template1) chain1 = LLMChain(llm=llm, prompt=prompt1) 第二个链:回答问题 template2 = """你是一个知识渊博的助手。请回答以下问题:{question}。回答要简洁。""" prompt2 = PromptTemplate(input_variables=["question"], template=template2) chain2 = LLMChain(llm=llm, prompt=prompt2) 组合成序列链 overall_chain = SimpleSequentialChain(chains=[chain1, chain2], verbose=True) final_output = overall_chain.run("黑洞") print(final_output)7. 调试与最佳实践
- 设置
verbose=True:在开发阶段,务必开启详细日志,以观察 Agent 的思考过程,便于定位问题。 - 清晰的工具描述:为每个工具提供准确、具体的
description,这是 LLM 能否正确选择工具的关键。 - 错误处理:使用
handle_parsing_errors=True或自定义错误处理逻辑,避免 Agent 因工具调用失败而崩溃。 - 令牌数管理:注意 Agent 运行过程中的上下文长度,过长的记忆或中间步骤可能导致超出模型限制。
- 从简单开始:先用 1-2 个工具构建最小可行 Agent,验证流程后再逐步增加复杂性。