我在实际项目中用 LangGraph 构建智能代理已经一年多了,第一次接触 ReAct 模式时被各种专业术语搞得头晕。今天我决定用最直白的话,从零开始教大家搭建一个能真正工作的 ReAct 代理。整个过程我们使用 HolySheep AI 作为后端 API 提供商,国内直连延迟<50ms,价格更是比官方渠道便宜 85% 以上。

一、ReAct 模式到底是什么?

简单说,ReAct = Reasoning + Acting。它让 AI 不是一次性给你答案,而是像人类一样边想边做:先想一下“我现在要做什么”,然后执行一个动作,再根据结果调整策略。

举个例子,你要 AI 帮你查天气然后决定穿什么衣服:

这就是 ReAct 的核心循环。LangGraph 就是帮你把这个循环用代码固定下来,让 AI 能自动执行多步骤任务。

二、环境准备

我的电脑是 Windows 系统,Python 3.10。先安装必要的库,打开命令行输入:

pip install langchain-core langchain-holysheep langgraph

如果没有特殊网络需求,连接 HolySheheep AI 的服务完全不需要代理。它的服务器就在国内,我实测延迟只有 42ms,比之前用 OpenAI 的 300ms+ 快了 7 倍多。

三、实战:构建你的第一个 ReAct 代理

3.1 初始化 HolySheheep API 连接

这是最基础的一步,拿到你的 API Key 后,配置 LangChain 的连接:

import os
from langchain_holysheep import ChatHolySheep
from langchain_core.messages import HumanMessage, SystemMessage

设置 API Key(请替换成你自己的)

os.environ["HOLYSHEEP_API_KEY"] = "YOUR_HOLYSHEEP_API_KEY"

初始化模型

llm = ChatHolySheep( base_url="https://api.holysheep.ai/v1", model="gpt-4.1", api_key=os.environ["HOLYSHEEP_API_KEY"], temperature=0.7 )

简单测试

messages = [HumanMessage(content="你好,简单介绍一下你自己")] response = llm.invoke(messages) print(response.content)

运行后如果看到模型回复,说明连接成功。我在第一次配置时遇到 Key 填错的问题,常见报错排查章节会详细说明。

3.2 定义工具(Tools)

ReAct 的强大之处在于它能调用外部工具。我们先定义两个简单的工具:计算器和搜索引擎。

from langchain_core.tools import tool

@tool
def calculator(expression: str) -> str:
    """执行数学计算。输入应该是数学表达式,如 '2 + 2' 或 '10 * 5'"""
    try:
        result = eval(expression)
        return f"计算结果:{result}"
    except Exception as e:
        return f"计算错误:{str(e)}"

@tool  
def search_info(query: str) -> str:
    """搜索信息。输入应该是你想查询的问题"""
    # 这里简化处理,实际项目可以接入真实搜索 API
    if "天气" in query:
        return "北京今天晴,26度,适合户外活动"
    elif "股票" in query:
        return "上证指数:3156点,涨幅0.8%"
    else:
        return f"关于'{query}'的信息:这是搜索结果的占位符"

收集所有工具

tools = [calculator, search_info]

绑定工具到模型

llm_with_tools = llm.bind_tools(tools)

3.3 构建 ReAct 循环逻辑

这是核心部分。我会一步步教大家用 LangGraph 构建状态机,让 AI 自动在思考和行动之间切换。

from typing import Annotated, Literal, TypedDict
from langgraph.graph import StateGraph, START, END
from langgraph.graph.message import add_messages

class AgentState(TypedDict):
    messages: Annotated[list, add_messages]

def should_continue(state: AgentState) -> Literal["action", "end"]:
    """判断是否需要继续执行工具"""
    last_message = state["messages"][-1]
    # 如果最后一条消息没有 tool_calls,说明已经得到最终答案
    if hasattr(last_message, "tool_calls") and last_message.tool_calls:
        return "action"
    return "end"

def call_model(state: AgentState) -> AgentState:
    """调用模型进行思考"""
    response = llm_with_tools.invoke(state["messages"])
    return {"messages": [response]}

def take_action(state: AgentState) -> AgentState:
    """执行工具并返回结果"""
    last_message = state["messages"][-1]
    tool_calls = last_message.tool_calls
    
    results = []
    for tool_call in tool_calls:
        tool_name = tool_call["name"]
        tool_args = tool_call["args"]
        
        # 查找并调用对应工具
        for t in tools:
            if t.name == tool_name:
                result = t.invoke(tool_args)
                results.append(
                    HumanMessage(content=f"[{tool_name}] 返回:{result}", 
                               name=tool_name)
                )
                break
    
    return {"messages": results}

构建图

graph = StateGraph(AgentState) graph.add_node("model", call_model) graph.add_node("action", take_action) graph.add_edge(START, "model") graph.add_conditional_edges("model", should_continue, {"action": "action", "end": END}) graph.add_edge("action", "model") react_agent = graph.compile()

3.4 运行 ReAct 代理

# 创建一个简单的测试问题
question = "北京现在的天气怎么样?如果气温超过20度,我想出门跑步,请告诉我适合吗?"

可视化思考过程

for event in react_agent.stream({"messages": [HumanMessage(content=question)]}): for node_name, node_data in event.items(): print(f"\n=== {node_name.upper()} ===") if "messages" in node_data: for msg in node_data["messages"]: if hasattr(msg, "content"): print(f"内容: {msg.content}") if hasattr(msg, "tool_calls") and msg.tool_calls: print(f"工具调用: {msg.tool_calls}")

运行后你应该能看到完整的 ReAct 循环:模型先思考“需要查天气”,调用 search_info 工具,拿到天气数据后再判断是否适合跑步。这就是 ReAct 的魅力——透明、可调试。

四、实战案例:构建多步骤研究代理

刚才的例子比较简单。现在我要教大家构建一个真正有用的研究代理,它会自动搜索多个信息源、汇总数据、给出建议。

# 扩展工具集
@tool
def search_academic(query: str) -> str: