代理(Agents) #

代理是 LangChain 中最强大的功能之一,它让 LLM 能够自主决策、调用工具、执行复杂任务。

代理概述 #

text
┌─────────────────────────────────────────────────────────────┐
│                    什么是代理?                              │
├─────────────────────────────────────────────────────────────┤
│                                                             │
│  普通链:                                                    │
│  输入 ───> 固定流程 ───> 输出                               │
│                                                             │
│  代理:                                                     │
│  输入 ───> LLM 思考 ───> 决策 ───> 执行工具 ───> 观察       │
│                    │                                        │
│                    └──> 循环直到完成任务                    │
│                                                             │
│  代理可以:                                                  │
│  ✅ 自主选择使用哪个工具                                    │
│  ✅ 决定是否需要更多信息                                    │
│  ✅ 多步骤完成任务                                          │
│  ✅ 处理意外情况                                            │
│                                                             │
└─────────────────────────────────────────────────────────────┘

代理工作原理 #

text
┌─────────────────────────────────────────────────────────────┐
│                    ReAct 模式                               │
├─────────────────────────────────────────────────────────────┤
│                                                             │
│  用户: "北京今天天气怎么样?温度是多少?"                    │
│                                                             │
│  思考: 我需要查询北京的天气信息                             │
│  行动: get_weather("北京")                                  │
│  观察: 北京今天晴,温度 25°C,湿度 45%                      │
│                                                             │
│  思考: 我已经获得了天气信息,可以回答用户了                 │
│  回答: 北京今天天气晴朗,温度是 25°C,湿度 45%。            │
│                                                             │
└─────────────────────────────────────────────────────────────┘

创建代理 #

使用 LangGraph(推荐) #

LangGraph 是 LangChain 新一代的代理框架,提供更灵活的控制:

python
from langgraph.prebuilt import create_react_agent
from langchain_openai import ChatOpenAI

model = ChatOpenAI(model="gpt-4o-mini")

# 定义工具
from langchain_core.tools import tool

@tool
def get_weather(city: str) -> str:
    """获取指定城市的天气信息"""
    weather_data = {
        "北京": "晴,25°C",
        "上海": "多云,28°C",
        "广州": "雨,30°C"
    }
    return weather_data.get(city, f"未找到{city}的天气信息")

@tool
def calculate(expression: str) -> float:
    """计算数学表达式"""
    try:
        return eval(expression)
    except:
        return "计算错误"

# 创建代理
tools = [get_weather, calculate]
agent = create_react_agent(model, tools)

# 运行
result = agent.invoke({
    "messages": [("user", "北京今天天气怎么样?")]
})

print(result["messages"][-1].content)

使用 AgentExecutor #

python
from langchain.agents import AgentExecutor, create_tool_calling_agent
from langchain_core.prompts import ChatPromptTemplate

model = ChatOpenAI(model="gpt-4o-mini")

prompt = ChatPromptTemplate.from_messages([
    ("system", "你是一个有帮助的助手"),
    ("human", "{input}"),
    ("placeholder", "{agent_scratchpad}"),
])

tools = [get_weather, calculate]

agent = create_tool_calling_agent(model, tools, prompt)
agent_executor = AgentExecutor(agent=agent, tools=tools, verbose=True)

result = agent_executor.invoke({"input": "北京天气怎么样?"})
print(result["output"])
text
┌─────────────────────────────────────────────────────────────┐
│                    代理执行流程                              │
├─────────────────────────────────────────────────────────────┤
│                                                             │
│  1. 接收用户输入                                            │
│         │                                                   │
│         ▼                                                   │
│  2. LLM 分析任务,决定是否需要工具                          │
│         │                                                   │
│    ┌────┴────┐                                              │
│    │         │                                              │
│  不需要    需要工具                                          │
│    │         │                                              │
│    │         ▼                                              │
│    │    3. 选择并执行工具                                   │
│    │         │                                              │
│    │         ▼                                              │
│    │    4. 获取工具输出                                     │
│    │         │                                              │
│    │         ▼                                              │
│    │    5. LLM 分析结果,决定下一步                         │
│    │         │                                              │
│    │    ┌────┴────┐                                         │
│    │    │         │                                         │
│    │  继续    任务完成                                      │
│    │    │         │                                         │
│    └────┼─────────┘                                         │
│         │                                                   │
│         ▼                                                   │
│  6. 返回最终答案                                            │
│                                                             │
└─────────────────────────────────────────────────────────────┘

代理类型 #

1. ReAct Agent #

推理+行动模式:

python
from langchain.agents import create_react_agent

prompt = ChatPromptTemplate.from_messages([
    ("system", """你是一个有帮助的助手。

你可以使用以下工具:
{tools}

使用以下格式:

Question: 用户的问题
Thought: 你应该思考做什么
Action: 要使用的工具,必须是 [{tool_names}] 之一
Action Input: 工具的输入
Observation: 工具的输出
... (这个 Thought/Action/Action Input/Observation 可以重复 N 次)
Thought: 我现在知道最终答案了
Final Answer: 最终答案"""),
    ("human", "{input}\n{agent_scratchpad}")
])

agent = create_react_agent(model, tools, prompt)

2. Function Calling Agent #

使用模型的函数调用能力:

python
from langchain.agents import create_tool_calling_agent

# OpenAI、Claude 等模型原生支持函数调用
agent = create_tool_calling_agent(model, tools, prompt)
agent_executor = AgentExecutor(agent=agent, tools=tools)

result = agent_executor.invoke({
    "input": "计算 123 * 456"
})

3. Structured Chat Agent #

处理复杂结构化输入:

python
from langchain.agents import create_structured_chat_agent

@tool
def search_product(
    name: str,
    category: str = None,
    min_price: float = None,
    max_price: float = None
) -> str:
    """搜索产品
    
    Args:
        name: 产品名称
        category: 产品类别
        min_price: 最低价格
        max_price: 最高价格
    """
    return f"搜索结果: {name}, 类别: {category}, 价格范围: {min_price}-{max_price}"

agent = create_structured_chat_agent(model, [search_product], prompt)

4. OpenAI Tools Agent #

专门为 OpenAI 模型优化:

python
from langchain.agents import create_openai_tools_agent

agent = create_openai_tools_agent(model, tools, prompt)

工具定义 #

使用 @tool 装饰器 #

python
from langchain_core.tools import tool

@tool
def search_web(query: str) -> str:
    """搜索网络获取信息
    
    Args:
        query: 搜索关键词
    """
    return f"搜索结果: {query}"

@tool
def get_current_time() -> str:
    """获取当前时间"""
    from datetime import datetime
    return datetime.now().strftime("%Y-%m-%d %H:%M:%S")

@tool
def send_email(to: str, subject: str, body: str) -> str:
    """发送邮件
    
    Args:
        to: 收件人邮箱
        subject: 邮件主题
        body: 邮件正文
    """
    return f"邮件已发送至 {to}"

使用 StructuredTool #

python
from langchain.tools import StructuredTool
from pydantic import BaseModel, Field

class CalculatorInput(BaseModel):
    a: float = Field(description="第一个数字")
    b: float = Field(description="第二个数字")
    operation: str = Field(description="运算类型: add, subtract, multiply, divide")

def calculator_func(a: float, b: float, operation: str) -> float:
    operations = {
        "add": a + b,
        "subtract": a - b,
        "multiply": a * b,
        "divide": a / b if b != 0 else "除数不能为零"
    }
    return operations.get(operation, "未知操作")

calculator = StructuredTool(
    name="calculator",
    description="执行数学运算",
    func=calculator_func,
    args_schema=CalculatorInput
)

工具类 #

python
from langchain.tools import BaseTool
from typing import Optional, Type

class WeatherTool(BaseTool):
    name = "get_weather"
    description = "获取指定城市的天气信息"
    
    def _run(self, city: str) -> str:
        return f"{city}今天晴,温度 25°C"
    
    async def _arun(self, city: str) -> str:
        return self._run(city)

内置工具 #

搜索工具 #

python
from langchain_community.tools import (
    DuckDuckGoSearchRun,
    GoogleSearchAPIWrapper,
    BingSearchAPIWrapper,
)

# DuckDuckGo(免费)
search = DuckDuckGoSearchRun()
result = search.run("LangChain 是什么")

# Google Search(需要 API Key)
from langchain_community.utilities import GoogleSearchAPIWrapper
search = GoogleSearchAPIWrapper()

Python REPL #

python
from langchain_experimental.tools import PythonREPLTool

python_repl = PythonREPLTool()
result = python_repl.run("print([x**2 for x in range(10)])")

文件操作 #

python
from langchain_community.tools import (
    ReadFileTool,
    WriteFileTool,
    ListDirectoryTool,
)

read_file = ReadFileTool()
write_file = WriteFileTool()
list_dir = ListDirectoryTool()

数据库查询 #

python
from langchain_community.tools.sql_database.tool import (
    QuerySQLDataBaseTool,
    InfoSQLDatabaseTool,
    ListSQLDatabaseTool,
)

from langchain_community.utilities import SQLDatabase

db = SQLDatabase.from_uri("sqlite:///mydb.db")

query_tool = QuerySQLDataBaseTool(db=db)
info_tool = InfoSQLDatabaseTool(db=db)
list_tool = ListSQLDatabaseTool(db=db)

高级代理模式 #

多工具协作 #

python
@tool
def search_database(query: str) -> str:
    """搜索数据库"""
    return f"数据库结果: {query}"

@tool
def search_api(query: str) -> str:
    """调用 API"""
    return f"API 结果: {query}"

@tool
def combine_results(db_result: str, api_result: str) -> str:
    """合并多个来源的结果"""
    return f"合并结果:\n数据库: {db_result}\nAPI: {api_result}"

tools = [search_database, search_api, combine_results]
agent = create_react_agent(model, tools)

带记忆的代理 #

python
from langgraph.checkpoint.memory import MemorySaver
from langgraph.prebuilt import create_react_agent

checkpointer = MemorySaver()

agent = create_react_agent(
    model,
    tools,
    checkpointer=checkpointer
)

# 使用会话 ID 保持记忆
config = {"configurable": {"thread_id": "user-123"}}

result1 = agent.invoke(
    {"messages": [("user", "我叫张三")]},
    config=config
)

result2 = agent.invoke(
    {"messages": [("user", "我叫什么?")]},
    config=config
)

人工确认 #

python
from langgraph.prebuilt import create_react_agent
from langgraph.checkpoint.memory import MemorySaver
from langgraph.types import interrupt

@tool
def send_email_with_confirmation(to: str, subject: str, body: str) -> str:
    """发送邮件(需要人工确认)"""
    # 中断等待人工确认
    approved = interrupt({
        "question": f"确认发送邮件至 {to}?",
        "subject": subject,
        "body": body
    })
    
    if approved:
        return f"邮件已发送至 {to}"
    else:
        return "邮件发送已取消"

checkpointer = MemorySaver()
agent = create_react_agent(model, [send_email_with_confirmation], checkpointer=checkpointer)

# 运行到需要确认时暂停
result = agent.invoke(
    {"messages": [("user", "发送邮件给 test@example.com")]},
    config={"configurable": {"thread_id": "session-1"}}
)

# 人工确认后继续
result = agent.invoke(
    {"messages": [("user", "确认")]},  # 或 "取消"
    config={"configurable": {"thread_id": "session-1"}}
)
text
┌─────────────────────────────────────────────────────────────┐
│                    人工确认流程                              │
├─────────────────────────────────────────────────────────────┤
│                                                             │
│  用户: "发送邮件给 test@example.com"                        │
│              │                                              │
│              ▼                                              │
│  Agent: 选择 send_email_with_confirmation 工具              │
│              │                                              │
│              ▼                                              │
│  ┌─────────────────────┐                                    │
│  │  等待人工确认       │                                    │
│  │  "确认发送邮件?"   │                                    │
│  └──────────┬──────────┘                                    │
│             │                                               │
│      ┌──────┴──────┐                                        │
│      │             │                                        │
│   确认           取消                                        │
│      │             │                                        │
│      ▼             ▼                                        │
│   发送邮件      取消发送                                     │
│                                                             │
└─────────────────────────────────────────────────────────────┘

完整示例 #

智能助手 #

python
from langgraph.prebuilt import create_react_agent
from langchain_openai import ChatOpenAI
from langchain_core.tools import tool
from datetime import datetime

model = ChatOpenAI(model="gpt-4o-mini")

@tool
def get_current_time() -> str:
    """获取当前时间"""
    return datetime.now().strftime("%Y-%m-%d %H:%M:%S")

@tool
def get_weather(city: str) -> str:
    """获取城市天气"""
    weather_data = {
        "北京": "晴,25°C",
        "上海": "多云,28°C",
        "广州": "雨,30°C"
    }
    return weather_data.get(city, f"未找到{city}的天气")

@tool
def calculate(expression: str) -> str:
    """计算数学表达式"""
    try:
        result = eval(expression)
        return str(result)
    except Exception as e:
        return f"计算错误: {e}"

@tool
def search_web(query: str) -> str:
    """搜索网络"""
    return f"关于'{query}'的搜索结果..."

@tool
def create_reminder(task: str, time: str) -> str:
    """创建提醒"""
    return f"已创建提醒: {task} 于 {time}"

tools = [get_current_time, get_weather, calculate, search_web, create_reminder]

agent = create_react_agent(model, tools)

# 测试
queries = [
    "现在几点了?",
    "北京今天天气怎么样?",
    "计算 123 * 456",
    "搜索 LangChain 教程",
    "提醒我下午3点开会"
]

for query in queries:
    result = agent.invoke({"messages": [("user", query)]})
    print(f"问题: {query}")
    print(f"回答: {result['messages'][-1].content}")
    print("-" * 50)

调试与监控 #

详细输出 #

python
# AgentExecutor 方式
agent_executor = AgentExecutor(
    agent=agent,
    tools=tools,
    verbose=True  # 打印详细执行过程
)

# LangGraph 方式
result = agent.invoke(
    {"messages": [("user", "问题")]},
    config={"callbacks": [handler]}
)

使用 LangSmith #

python
import os

os.environ["LANGCHAIN_TRACING_V2"] = "true"
os.environ["LANGCHAIN_API_KEY"] = "your-key"

# 所有执行会自动记录到 LangSmith

最佳实践 #

1. 清晰的工具描述 #

python
@tool
def search_product(query: str, category: str = None) -> str:
    """搜索产品信息
    
    根据关键词搜索产品数据库。
    可以指定类别进行过滤。
    
    Args:
        query: 搜索关键词,如产品名称或描述
        category: 可选,产品类别,如 '电子产品'、'服装'
    
    Returns:
        匹配的产品列表
    """
    pass

2. 错误处理 #

python
@tool
def api_call(endpoint: str) -> str:
    """调用 API"""
    try:
        # API 调用逻辑
        return "成功"
    except Exception as e:
        return f"API 调用失败: {str(e)}"

3. 限制迭代次数 #

python
agent_executor = AgentExecutor(
    agent=agent,
    tools=tools,
    max_iterations=5,  # 最大迭代次数
    handle_parsing_errors=True  # 处理解析错误
)

下一步 #

最后更新:2026-03-30