[智能体设计模式] 第五章 :函数调用

目录

工具使用模式:智能体的外部交互核心机制

典型流程

实践应用与场景

[1. 外部信息检索](#1. 外部信息检索)

[2. 与数据库和 API 交互](#2. 与数据库和 API 交互)

[3. 计算与数据分析](#3. 计算与数据分析)

[4. 发送通讯](#4. 发送通讯)

[5. 执行代码](#5. 执行代码)

[6. 控制其他系统或设备](#6. 控制其他系统或设备)

实战代码示例(LangChain)

代码解析


工具使用模式:智能体的外部交互核心机制

工具使用模式通常通过"函数调用"机制实现,使智能体能够与外部 API、数据库、服务甚至执行代码进行交互。它允许智能体核心的 LLM 根据用户请求或任务当前状态,决定何时以及如何调用特定的外部函数。

典型流程

  1. 工具定义:向 LLM 描述外部函数或能力,包括函数用途、名称、参数类型及说明。
  2. LLM 决策:LLM 接收用户请求和可用工具定义,根据理解判断是否需要调用一个或多个工具来完成请求。
  3. 函数调用生成:如果 LLM 决定使用工具,会生成结构化输出(通常为 JSON),指定要调用的工具名称及参数(从用户请求中提取)。
  4. 工具执行:智能体框架或编排层拦截结构化输出,识别请求的工具并用提供的参数实际执行外部函数。
  5. 观察/结果:工具执行的输出或结果返回给智能体。
  6. LLM 处理(可选但常见):LLM 将工具输出作为上下文,用于生成最终回复或决定下一步(可能再次调用工具、反思或直接答复)。

实践应用与场景

工具使用模式几乎适用于所有智能体需要超越文本生成、执行动作或获取动态信息的场景:

1. 外部信息检索

获取 LLM 训练数据之外的实时数据或信息。

  • 案例:天气智能体
  • 工具:天气 API,输入地点返回当前天气
  • 流程:用户问"伦敦天气如何?",LLM 识别需要天气工具,调用工具,工具返回数据,LLM 格式化回复。

2. 与数据库和 API 交互

查询、更新或操作结构化数据。

  • 案例:电商智能体
  • 工具:查询库存、订单状态、支付等 API
  • 流程:用户问"X 产品有货吗?",LLM 调用库存 API,工具返回库存数,LLM 告知用户。

3. 计算与数据分析

使用外部计算器、数据分析库或统计工具。

  • 案例:金融智能体
  • 工具:计算器函数、股票数据 API、表格工具
  • 流程:用户问"AAPL 当前价格及买入 100 股的潜在利润",LLM 调用股票 API,再调用计算器工具,整合结果回复。

4. 发送通讯

发送邮件、消息或调用外部通讯服务 API。

  • 案例:个人助理智能体
  • 工具:邮件发送 API
  • 流程:用户说"给 John 发会议邮件",LLM 提取收件人、主题、正文,调用邮件工具。

5. 执行代码

在安全环境中运行代码片段完成特定任务。

  • 案例:编程助手智能体
  • 工具:代码解释器
  • 流程:用户提供 Python 代码并问"这段代码做什么?",LLM 用解释器工具运行并分析输出。

6. 控制其他系统或设备

操作智能家居、物联网平台等。

  • 案例:智能家居智能体
  • 工具:控制智能灯的 API
  • 流程:用户说"关闭客厅灯",LLM 调用智能家居工具,传递命令和目标设备。

工具使用让语言模型从文本生成器转变为具备感知、推理和行动能力的智能体(见图1)。


实战代码示例(LangChain)

在 LangChain 框架中实现工具使用分为两步:首先定义工具(通常封装现有 Python 函数或可运行组件),然后将工具绑定到语言模型,使模型在需要时能生成结构化的工具调用请求。

以下代码演示了如何定义一个信息检索工具,并构建一个能使用该工具的智能体。运行需安装 LangChain 核心库和模型相关包,并配置 API 密钥。

python 复制代码
import os
import getpass
import asyncio
import nest_asyncio
from typing import List
from dotenv import load_dotenv
import logging

from langchain_google_genai import ChatGoogleGenerativeAI
from langchain_core.prompts import ChatPromptTemplate
from langchain_core.tools import tool as langchain_tool
from langchain.agents import create_tool_calling_agent, AgentExecutor

# 安全输入 API 密钥并设置为环境变量
os.environ["GOOGLE_API_KEY"] = getpass.getpass("输入你的 Google API 密钥:")
os.environ["OPENAI_API_KEY"] = getpass.getpass("输入你的 OpenAI API 密钥:")

try:
    # 初始化具备工具调用能力的模型
    llm = ChatGoogleGenerativeAI(model="gemini-2.0-flash", temperature=0)
    print(f" 语言模型已初始化:{llm.model}")
except Exception as e:
    print(f" 初始化语言模型出错:{e}")
    llm = None

# --- 定义工具 ---
@langchain_tool
def search_information(query: str) -> str:
    """
    根据主题提供事实信息。用于回答如"法国首都"或"伦敦天气?"等问题。
    """
    print(f"\n---  工具调用:search_information, 查询:'{query}' ---")
    # 用预设结果模拟搜索工具
    simulated_results = {
        "weather in london": "伦敦当前天气多云,气温 15°C。",
        "capital of france": "法国的首都是巴黎。",
        "population of earth": "地球人口约 80 亿。",
        "tallest mountain": "珠穆朗玛峰是世界最高的山峰。",
        "default": f"模拟搜索 '{query}':未找到具体信息,但该主题很有趣。"
    }
    result = simulated_results.get(query.lower(), simulated_results["default"])
    print(f"--- 工具结果:{result} ---")
    return result

tools = [search_information]

# --- 创建工具调用 Agent ---
if llm:
    agent_prompt = ChatPromptTemplate.from_messages([
        ("system", "你是一个乐于助人的助手。"),
        ("human", "{input}"),
        ("placeholder", "{agent_scratchpad}"),
    ])

    agent = create_tool_calling_agent(llm, tools, agent_prompt)
    agent_executor = AgentExecutor(agent=agent, verbose=True, tools=tools)

    async def run_agent_with_tool(query: str):
        """用 Agent 执行查询并打印最终回复。"""
        print(f"\n---  Agent 运行查询:'{query}' ---")
        try:
            response = await agent_executor.ainvoke({"input": query})
            print("\n--- ✅ Agent 最终回复 ---")
            print(response["output"])
        except Exception as e:
            print(f"\n Agent 执行出错:{e}")

    async def main():
        """并发运行多个 Agent 查询。"""
        tasks = [
            run_agent_with_tool("法国的首都是什么?"),
            run_agent_with_tool("伦敦天气如何?"),
            run_agent_with_tool("说说狗的相关信息。")  # 触发默认工具回复
        ]
        await asyncio.gather(*tasks)

    nest_asyncio.apply()
    asyncio.run(main())

代码解析

该代码使用 LangChain 和 Google Gemini 模型创建了一个工具调用智能体,核心逻辑如下:

  1. 环境配置与模型初始化 :通过 getpass 安全输入 Google API 密钥和 OpenAI API 密钥,初始化 ChatGoogleGenerativeAI 模型(选用 gemini-2.0-flash,低温度保证输出确定性)。
  2. 工具定义 :使用 @langchain_tool 装饰器定义 search_information 工具,功能是根据查询提供事实信息。内部通过预设的 simulated_results 字典模拟搜索结果,支持常见查询(如天气、首都)和默认回复。
  3. 智能体创建
    • 定义 agent_prompt 模板,包含系统提示、用户输入占位符和智能体草稿区(agent_scratchpad,用于记录工具调用过程);
    • create_tool_calling_agent 绑定模型、工具和提示模板,生成具备工具调用能力的智能体;
    • AgentExecutor 管理智能体的执行流程,开启 verbose=True 可查看详细调用日志。
  1. 运行与测试
    • run_agent_with_tool 异步函数接收用户查询,调用智能体并输出最终回复;
    • main 函数并发运行多个测试查询,验证工具对特定请求的精准响应和默认回复逻辑;
    • 通过 nest_asyncio.apply() 解决异步嵌套问题,确保并发任务正常执行。

整体实现了"用户查询 → LLM 决策 → 工具调用 → 结果整合 → 最终回复"的完整工具使用流程,展示了智能体如何通过外部工具扩展自身能力。

相关推荐
lapiii3582 小时前
[智能体设计模式] 第 1 章:提示链(Prompt Chaining)
设计模式·prompt
昨天的猫3 小时前
《拒绝重复代码!模板模式教你优雅复用算法骨架》
后端·设计模式
L.EscaRC3 小时前
ArkTS分布式设计模式浅析
分布式·设计模式·arkts
Arva .4 小时前
责任链设计模式->规则树
设计模式
WKP94184 小时前
命令设计模式
设计模式
Leinwin5 小时前
Azure Storage Discovery(国际版)正式发布
microsoft·azure
软泡芙5 小时前
【.NET10】正式发布!微软开启智能开发生态新纪元
人工智能·microsoft·.net
lapiii3588 小时前
[智能体设计模式] 第4章:反思(Reflection)
人工智能·python·设计模式
颜酱19 小时前
理解编程范式(前端角度)
设计模式