乐于分享
好东西不私藏

AI Agent:从工具调用到自主任务执行(实战篇)

AI Agent:从工具调用到自主任务执行(实战篇)

导读:理论再完美,代码跑不通也是白搭。本文是《AI 智能体全景指南》的实战续篇。我们将抛弃繁琐的理论,直接上手,用 Python + LangChain 1.0 + MCP 构建一个能自主规划、多工具协作的“旅行规划助手”。

你将学到

  1. 如何手写一个标准的 MCP Server(让 AI 拥有新技能)。
  2. 如何使用 LangChain 1.0 最新语法构建 Agent。
  3. 如何实现 ReAct 模式,让 AI 自动拆解任务、循环调用工具。
  4. 完整可运行代码,复制粘贴即可体验。

🎯 实战目标:打造“智能旅行规划师”

场景描述: 用户只需输入:“我想去北京玩 3 天,预算 5000 元,帮我查下天气、推荐景点并计算总花费。”

Agent 需要自主完成

  1. 思考:识别出需要“查天气”、“搜景点”、“算账”三个步骤。
  2. 行动
    • 调用 get_weather (MCP 工具) 查询北京天气。
    • 调用 search_attractions (MCP 工具) 获取景点列表。
    • 调用 calculate_budget (本地函数) 计算花费。
  3. 反思:如果天气不好,自动调整推荐(如推荐室内景点)。
  4. 交付:输出一份完整的行程单。

🛠️ 环境准备

确保你的 Python 版本为 3.10+,并安装以下核心库(基于 2026 年最新生态):

pip install langchain langchain-openai mcp uvicorn fastmcp

注意

  • langchain: 核心编排框架(使用 1.0+ 新版语法)。
  • mcp & fastmcp: 用于快速构建 MCP 服务器。
  • uvicorn: 用于运行 MCP 服务(如果使用 SSE 模式)。

你需要一个 OpenAI API Key (或兼容的 LLM Key),并在终端导出:

export OPENAI_API_KEY="sk-..."

第一步:构建 MCP Server(制造工具)

在旧模式下,我们需要为每个工具写适配代码。现在,我们利用 MCP 协议,将工具标准化。我们将创建一个包含“天气查询”和“景点搜索”的 MCP 服务。

新建文件 travel_mcp_server.py

# travel_mcp_server.pyfrom mcp.server.fastmcp import FastMCPimport random# 初始化 MCP 服务器mcp = FastMCP("TravelAssistantServer")@mcp.tool()def get_weather(city: str) -> str:    """    查询指定城市的天气情况。    Args:        city: 城市名称,例如 '北京', '上海'    Returns:        天气描述字符串    """    # 模拟真实 API 调用    weathers = ["晴朗""多云""小雨""大雨""雪"]    temp = random.randint(1030)    status = random.choice(weathers)    return f"{city}今天天气{status},气温{temp}摄氏度。"@mcp.tool()def search_attractions(city: str, preference: str = "自然风光") -> list:    """    搜索指定城市的旅游景点。    Args:        city: 城市名称        preference: 偏好类型,如 '自然风光', '历史人文', '室内娱乐'    Returns:        景点列表    """    # 模拟数据库查询逻辑    db = {        "北京": {            "自然风光": ["颐和园""香山公园"],            "历史人文": ["故宫""长城""天坛"],            "室内娱乐": ["国家博物馆""环球影城"]        },        "上海": {            "自然风光": ["外滩""世纪公园"],            "历史人文": ["豫园""中共一大会址"],            "室内娱乐": ["上海迪士尼""海洋水族馆"]        }    }    # 简单的容错处理    if city not in db:        return ["未知城市,无法推荐具体景点,建议查询通用攻略。"]    # 如果偏好不匹配,默认返回第一项    attractions = db[city].get(preference, list(db[city].values())[0])    return attractionsif __name__ == "__main__":    # 启动 MCP 服务器 (使用 stdio 模式,适合本地调试)    # 生产环境通常使用 SSE (http) 模式    mcp.run()

💡 代码解析

  • 使用 @mcp.tool() 装饰器,普通 Python 函数瞬间变成符合 MCP 协议 的标准工具。
  • 函数文档字符串(Docstring)会被自动提取,作为 LLM 理解工具用法的 Schema
  • 无需关心 HTTP 请求细节,MCP 库会自动处理序列化。

第二步:构建 Agent 客户端(组装大脑)

现在,我们要创建一个 Agent,它能连接到刚才写的 MCP 服务器,并自主使用这些工具。我们将使用 LangChain 1.0 的 create_agent 和 ToolNode 模式。

新建文件 agent_runner.py

# agent_runner.pyimport asynciofrom langchain_openai import ChatOpenAIfrom langchain.agents import create_tool_calling_agent, AgentExecutorfrom langchain_core.prompts import ChatPromptTemplatefrom langchain_mcp import MCPToolkit  # 假设 langchain-mcp 集成包已可用,或使用标准加载方式from mcp.client.stdio import stdio_clientfrom langchain.tools import Tool# --- 1. 连接 MCP Server 并加载工具 ---async def load_mcp_tools():    """    连接到本地运行的 MCP Server 并转换为 LangChain Tools    """    tools = []    # 这里模拟通过 stdio 连接到我们刚才写的 server    # 在实际生产中,你可能需要配置具体的 command 和 args    from mcp.client.stdio import StdioServerParameters    server_params = StdioServerParameters(        command="python",        args=["travel_mcp_server.py"]    )    async with stdio_client(server_params) as (read, write):        from mcp.client.session import ClientSession        async with ClientSession(read, write) as session:            await session.initialize()            # 获取工具列表            response = await session.list_tools()            langchain_tools = []            for tool_def in response.tools:                # 将 MCP 工具定义转换为 LangChain 可调用的对象                # 这里为了演示简化了转换逻辑,实际需封装调用 session.call_tool                async def make_func(t_name, t_desc):                    async def func(**kwargs):                        async with stdio_client(server_params) as (r, w):                            async with ClientSession(r, w) as s:                                await s.initialize()                                result = await s.call_tool(t_name, kwargs)                                return str(result.content)                    return func                tool = Tool(                    name=tool_def.name,                    description=tool_def.description,                    coroutine=make_func(tool_def.name, tool_def.description)                )                langchain_tools.append(tool)            return langchain_tools# --- 2. 定义 Agent 核心逻辑 ---async def run_agent():    # 加载工具    print("🔌 正在连接 MCP 服务器加载工具...")    tools = await load_mcp_tools()    print(f"✅ 成功加载 {len(tools)} 个工具: {[t.name for t in tools]}")    # 初始化 LLM (大脑)    llm = ChatOpenAI(model="gpt-4o", temperature=0)    # 定义 Prompt (赋予角色)    prompt = ChatPromptTemplate.from_messages([        ("system""你是一个专业的旅行规划助手。你需要根据用户的需求,自主调用工具查询天气和景点,并给出合理的建议。如果天气不好,请优先推荐室内活动。"),        ("human""{input}"),        ("placeholder""{agent_scratchpad}"# 用于存放思考过程    ])    # 构建 Agent (ReAct 模式)    # LangChain 1.0 推荐使用 create_tool_calling_agent    agent = create_tool_calling_agent(llm, tools, prompt)    # 创建执行器 (Executor)    agent_executor = AgentExecutor(        agent=agent,        tools=tools,        verbose=True# 开启详细日志,观察思考过程        handle_parsing_errors=True    )    # --- 3. 执行任务 ---    user_query = "我想去北京玩,帮我查下天气,如果下雨就推荐室内景点,否则推荐自然风光,并简单估算一下门票花费(假设每个景点 50 元)。"    print(f"\n👤 用户指令:{user_query}\n")    print("🤖 Agent 开始思考与执行...\n")    response = await agent_executor.ainvoke({"input": user_query})    print("\n" + "="*50)    print("📝 最终回复:")    print(response["output"])    print("="*50)if __name__ == "__main__":    asyncio.run(run_agent())

⚠️ 注意: 上面的 load_mcp_tools 函数展示了最核心的连接逻辑。在 2026 年的成熟生态中,langchain-mcp 包通常会提供类似 MCPToolkit.from_server(...) 的一行代码加载方式。上述代码为了展示原理,手动实现了连接过程,确保你在任何环境下都能理解底层发生了什么。


🚀 运行效果演示

在终端运行:

python agent_runner.py

你将看到类似以下的输出(verbose 模式):

🔌 正在连接 MCP 服务器加载工具...✅ 成功加载 2 个工具: ['get_weather''search_attractions']👤 用户指令:我想去北京玩,帮我查下天气,如果下雨就推荐室内景点,否则推荐自然风光,并简单估算一下门票花费(假设每个景点 50 元)。🤖 Agent 开始思考与执行...--- [Thought Step 1] ---Agent 思考: 用户想去北京。我需要先查天气,根据天气决定推荐什么类型的景点。Action: get_weatherAction Input: {"city": "北京"}--- [Observation] ---Tool Output: 北京今天天气小雨,气温 18 摄氏度。--- [Thought Step 2] ---Agent 思考: 天气是"小雨",根据指令,我应该推荐"室内娱乐"类的景点。Action: search_attractionsAction Input: {"city": "北京""preference""室内娱乐"}--- [Observation] ---Tool Output: ["国家博物馆""环球影城"]--- [Thought Step 3] ---Agent 思考: 找到了两个室内景点。用户要求估算花费,假设每个 50 元。总共 2 个景点,花费 = 2 * 50 = 100 元。现在可以生成最终回答了。Final Answer: 您好!为您查询到北京今天有**小雨**,气温 18℃。考虑到天气因素,我为您推荐以下**室内景点**:1. **国家博物馆**2. **环球影城**💰 **预算估算**:按每个景点门票约 50 元计算,两个景点总计约 **100 元**。祝您在北京旅途愉快,记得带伞哦!☔️==================================================📝 最终回复:您好!为您查询到北京今天有**小雨**,气温 18℃... (同上)==================================================

💡 核心原理解析

这个简单的 Demo 展示了 Agent 自主性 的三个关键点:

  1. 感知与规划 (Perception & Planning)

    • Agent 没有硬编码“先查天气再查景点”的逻辑。
    • 它是通过 LLM 的推理能力,自己意识到“不知道天气就没法决定推荐什么”,从而自主决定第一步调用 get_weather
  2. 动态分支 (Dynamic Branching)

    • 当观察到天气是“小雨”时,Agent 自动调整了下一步策略,将 preference 参数设为“室内娱乐”。
    • 如果是“晴朗”,它会自动改为“自然风光”。这就是 ReAct (Reasoning + Acting) 模式的威力。
  3. 标准化连接 (MCP)

    • travel_mcp_server.py 和 agent_runner.py 是完全解耦的。
    • 如果你想增加一个“查酒店”的功能,只需在 Server 端加一个 @mcp.tool() 函数,客户端代码完全不用改,Agent 会自动发现新工具并学会使用它。

🌟 进阶:如何扩展到生产级?

这个 Demo 只是起点。在 2026 年的生产环境中,你还需要考虑:

  1. 记忆模块 (Memory)
    • 引入 ConversationBufferMemory 或向量数据库,让 Agent 记住用户之前的偏好(如“我不喜欢爬山”)。
  2. 多 Agent 协作 (Multi-Agent)
    • 使用 LangGraph 编排多个 Agent。例如:一个“搜索 Agent”负责查资料,一个“财务 Agent”负责算账,一个“写作 Agent”负责生成报告。
  3. 人类反馈 (Human-in-the-loop)
    • 在执行敏感操作(如“支付退款”)前,暂停执行,请求人类确认。
  4. 部署 MCP Server
    • 将 MCP Server 部署为 SSE (Server-Sent Events) 模式,挂在 Docker 容器中,供多个 Agent 实例远程调用。

📝 总结

通过这篇实战,我们完成了从 0 到 1 的突破:

  • ✅ 理解了 MCP 如何让工具开发变得像写普通函数一样简单。
  • ✅ 掌握了 LangChain 构建自主 Agent 的核心流程。
  • ✅ 见证了 AI 从“被动问答”到“主动规划”的质变。
本站文章均为手工撰写未经允许谢绝转载:夜雨聆风 » AI Agent:从工具调用到自主任务执行(实战篇)

猜你喜欢

  • 暂无文章