博主未授权任何人或组织机构转载博主任何原创文章,感谢各位对原创的支持!
博主链接

本人就职于国际知名终端厂商,负责modem芯片研发。
在5G早期负责终端数据业务层、核心网相关的开发工作,目前牵头6G技术研究。


博客内容主要围绕:
       5G/6G协议讲解
       高级C语言讲解
       Rust语言讲解



工具调用模式学习笔记

一、工具调用模式介绍

       要使智能体真正有用并与现实世界或外部系统交互,它们需要具备使用工具的能力。工具调用模式通常通过函数调用的机制实现,它使智能体能够与外部API、数据库、服务甚至执行代码进行交互。它允许智能体的核心LLM根据用户的请求或任务的当前状态来决定何时以及如何使用特定的外部功能。该过程通常包括:

  1. 工具定义:向LLM定义和描述外部功能或能力。这个描述包括函数的用途、名称、接收的参数,以及它们的类型和描述;
  2. LLM决策:LLM接收用户的请求和可用的工具定义。基于对请求和工具的理解,LLM决定是否需要调用一个或多个工具来完成请求;
  3. 函数调用生成:如果LLM决定使用某个工具,它将生成一个结构化输出(通常是JSON对象),该输出指定要调用的工具名称和要传递给它的参数,这些参数是从用户的请求中提取的;
  4. 工具执行:智能体框架或编排层获取此结构化输出。它标识被请求的工具,并使用提供的参数实际执行的外部函数;
  5. 观察/结果:工具执行的输出或结果返回给智能体;
  6. LLM处理(可选但常见):LLM接收工具的输出作为上下文,并使用它来制定对用户的最终响应或决定工作流中的下一步(这可能涉及调用另一个工具,反思或提供最终答案)。

       这种模式是基本且必需的,因为它打破了LLM训练数据的限制,允许模型访问最新的信息,执行内部无法进行的计算,与用户特定的数据交互,或触发真实世界的动作

       函数调用是一种技术机制,它弥合了LLM的推理能力和大量可用的外部功能之间的差距。虽然“函数调用”恰当地描述了调用特定的、预定义的代码函数,但考虑“工具调用”这个更广泛的概念是有用的。这个更宽泛的术语承认,智能体的能力可以扩展到远远超出简单的功能执行。

       “工具”可以是传统的函数,但也可以是复杂的API端点、对数据库的请求,甚至是指向另一个专门智能体的指令。这种观点允许我们设想更复杂的系统,例如,主智能体可以将复杂的数据分析任务委托给专用的“分析师智能体”,或通过其API查询外部知识库。从“工具调用”的角度思考,可以更好地捕捉智能体的全部潜力,以充当跨数字资源和其他智能实体的多样化生态系统的协调器。

       使用工具是构建强大的、交互式的、具有外部感知能力的智能体的基础模式

二、常见应用案例

工具使用模式适用于几乎任何场景,其中智能体需要超越生成文本来执行操作或检索特定的动态信息:

  1. 从外部源进行信息检索
    • 访问实时数据或LLM训练数据中不存在的信息
      • 使用场景:天气智能体
        • 工具:天气API,获取位置并返回当前天气情况
        • 智能体流程:用户询问,“伦敦的天气是什么?”,LLM识别天气工具的需求,使用“伦敦”调用该工具,工具返回数据,LLM将数据格式化为用户友好的响应。
  2. 与数据库和API交互
    • 对结构化数据执行查询、更新或其他操作
      • 用例:电子商务代理
        • 工具:用于检查产品库存、获取订单状态或处理付款的API调用
        • 智能体流程:用户询问“产品X在库存中吗?”,LLM调用库存API,工具返回库存计数,LLM告诉用户库存状态。
  3. 执行计算和数据分析
    • 使用外部计算器、数据分析库或统计工具
      • 用例:金融智能体
        • 工具:计算器功能,股票市场数据API,电子表格工具
        • 智能体流程:用户询问“AAPL的当前价格是多少,并计算如果我以150美元购买100股的潜在利润?”,LLM调用stock API,获取当前价格,然后调用计算器工具,获取结果,格式化响应。
  4. 发送信息
    • 发送电子邮件、消息或调用外部通信服务的API
      • 用例:个人助理智能体
        • 工具:邮件发送API
        • 智能体流程:用户说,“发送一封电子邮件给约翰关于明天的会议”,LLM调用一个电子邮件工具,从请求中提取收件人、主题和正文。
  5. 执行代码
    • 在安全的环境中运行代码片段以执行特定的任务
      • 用例:编码助理智能体
        • 工具:代码解释器
        • 智能体流程:用户提供一个Python片段并问,“这段代码做什么?”,LLM使用解释器工具运行代码并分析其输出。
  6. 控制其他系统或设备
    • 与智能家居设备、物联网平台或其他连接系统进行交互
      • 用例:智能家居智能体
        • 工具:智能灯控制接口
        • 智能体流程:用户说“关掉客厅的灯”LLM使用命令和目标设备调用智能家居工具。工具的使用将语言模型从文本生成器转换为能够在数字或物理世界中感知、推理和行动的代理(见下图)。

在这里插入图片描述

三、示例代码

       在LangChain框架内实现工具调用是一个两阶段的过程。最初,定义一个或多个工具,通常通过封装现有的Python函数或其他可运行组件。随后,这些工具被绑定到语言模型,从而赋予模型在确定需要外部函数调用来完成用户查询时生成结构化工具使用请求的能力。

       下面的实现将演示这一原则,首先定义一个简单的函数来模拟信息检索工具。接下来,将构建并配置一个智能体,以利用此工具响应用户输入。

import os
import nest_asyncio
import asyncio

from langchain_ollama import ChatOllama
from langchain_core.prompts import ChatPromptTemplate
from langchain_core.tools import tool as langchain_tool
from langchain_core.messages import SystemMessage, HumanMessage
from langchain_classic.agents import create_tool_calling_agent, AgentExecutor


# --- Configuration ---
# Load environment variables from .env file (for OPENAI_API_KEY)
try:
    llm = ChatOllama(
        model="qwen",
        validate_model_on_init=True,
        temperature=0.8,
        num_predict=2000,
        base_url="http://xxx.xxx.xxx.xxx:yyy"
        # other params ...
    )
except Exception as e:
    print(f"Error initializing language model: {e}")
    llm = None


# --- Define a Tool ---
@langchain_tool
def search_information(query: str) -> str:
    """
    Provides factual information on a given topic. Use this tool to
    find answers to phrases
    like 'capital of France' or 'weather in London?'.
    """
    print(f"\n--- 🛠  Tool Called: search_information with query:'{query}' ---")


    # Simulate a search tool with a dictionary of predefined results.
    simulated_results = {
        "weather in london": "The weather in London is currently cloudy with a temperature of 15°C.",
        "capital of france": "The capital of France is Paris.",
        "population of earth": "The estimated population of Earth is around 8 billion people.",
        "tallest mountain": "Mount Everest is the tallest mountain above sea level.",
        "default": f"Simulated search result for '{query}': No specific information found, but the topic seems interesting."
    }

    result = simulated_results.get(query.lower(), simulated_results["default"])

    print(f"--- TOOL RESULT: {result} ---")
    return result
tools = [search_information]


# --- Create a Tool-Calling Agent ---
if llm:
    # This prompt template requires an `agent_scratchpad` placeholder for the agent's internal steps.
    agent_prompt = ChatPromptTemplate.from_messages([
        ("system", "You are a helpful assistant."),
        ("human", "{input}"),
        ("placeholder", "{agent_scratchpad}"),
    ])

    # Create the agent, binding the LLM, tools, and prompt together.
    agent = create_tool_calling_agent(llm, tools, agent_prompt)

    # AgentExecutor is the runtime that invokes the agent and executes the chosen tools.
    # The 'tools' argument is not needed here as they are already bound to the agent.
    agent_executor = AgentExecutor(agent=agent, verbose=True, tools=tools)


async def run_agent_with_tool(query: str):
    """Invokes the agent executor with a query and prints the final response."""
    print(f"\n--- 🏃 Running Agent with Query: '{query}' ---")

    try:
        response = await agent_executor.ainvoke({"input": query})
        print("\n--- ✅ Final Agent Response ---")
        print(response["output"])
    except Exception as e:
        print(f"\n🛑 An error occurred during agent execution: {e}")


async def main():
    """Runs all agent queries concurrently."""
    tasks = [
        run_agent_with_tool("What is the capital of France?"),
        run_agent_with_tool("What's the weather like in London?"),
        run_agent_with_tool("Tell me something about dogs.") # Should trigger the default tool response
    ]
    await asyncio.gather(*tasks)


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

       该代码使用LangChain库和Qwen3-vl模型设置了一个工具调用智能体。它定义了一个search_information工具,模拟为特定查询提供答案。该工具预定义了“伦敦天气”、“法国首都”和“地球人口”的响应,以及其他查询的默认响应。初始化ChatOllama模型,确保它具有调用工具的能力。创建一个ChatPromptTemplate来指导智能体的交互。create_tool_calling_agent函数用于将语言模型、工具和提示组合到一个智能体中。然后设置一个AgentExecutor来管理智能体的执行和工具调用。run_agent_with_tool异步函数被定义为使用给定的查询调用智能体并打印结果。main异步函数准备多个并发执行的查询。这些查询旨在测试search_information工具的特定响应和默认响应。最后,asyncio.run(main())调用执行所有代理任务。该代码包括在继续设置和执行智能体之前检查是否成功初始化LLM。

运行图片

四、经验总结

       LLM是强大的文本生成器,但它们从根本上与外部世界脱节。他们的知识是静态的,受限于他们所训练的数据,并且他们缺乏执行行动或检索实时信息的能力。这种固有的限制使它们无法完成需要与外部API、数据库或服务交互的任务。如果没有与这些外部系统的桥梁,它们解决现实问题的效用就会受到严重限制。

       工具调用模式,通常通过函数调用实现,为这个问题提供了标准化的解决方案。通过以一种LLM可以理解的方式描述可用的外部功能或“工具”来工作。根据用户的请求,智能体LLM可以决定是否需要一个工具,并生成一个结构化数据对象(如JSON),指定调用哪个函数以及使用什么参数。编排层执行此函数调用,检索结果,并将其反馈给LLM。这允许LLM将最新的外部信息或行动结果纳入其最终响应,有效地赋予其行动能力。

       经验法则:当智能体需要突破LLM的内部知识并与外部世界交互时,使用工具调用模式。这对于需要实时数据的任务(例如,检查天气、股票价格)、访问私有或专有信息(例如,查询公司的数据库)、执行精确计算、执行代码或在其他系统中触发操作(例如,发送电子邮件、控制智能设备)是必不可少的。

在这里插入图片描述

总结

       工具调用模式是一个关键的架构原则,用于扩展大型语言模型的功能范围,超出其固有的文本生成能力。通过为模型配备与外部软件和数据源接口的能力,这种范式允许智能体执行操作、执行计算,并从其他系统检索信息。这个过程包括模型在确定需要调用外部工具时生成一个结构化请求来完成用户的查询。



在这里插入图片描述

Logo

有“AI”的1024 = 2048,欢迎大家加入2048 AI社区

更多推荐