五、大模型工具调用

工具调用(Tool Use)或称函数调用(Function Calling)是大规模语言模型(LLM)领域的一个关键进步,它极大地拓宽了模型的应用边界,使其能够从一个纯粹的文本生成器升级为能够执行任务获取外部信息的智能代理(Agent)。

5.1 工具调用核心概念

  • 定义: 工具调用机制允许LLM在处理用户请求时,识别出需要执行特定外部操作(例如查询数据库、发送邮件、调用第三方API)才能准确回答或完成任务。
  • 工作流程:
    1. 工具/函数注册: 开发者向LLM提供一个可用的工具列表及其描述(Schema),描述要清晰地说明函数的功能、名称和所需的参数。
    2. 意图识别与参数生成: LLM根据用户输入和工具描述,判断是否需要调用某个工具。如果需要,它会生成一个符合该工具规范的JSON或代码片段,其中包含正确的函数名参数
    3. 实际执行(模型不执行): 模型只负责生成调用代码/JSON。实际的执行由外部的应用程序或开发者环境负责。
    4. 结果反馈与最终回答: 应用程序将工具执行的结果(例如API的返回数据)回传给LLM。LLM将这个结果作为新的上下文,生成最终、准确的自然语言回答。

5.2 为什么需要工具调用

工具调用机制解决了LLM固有的两大限制:

  1. 解决信息滞后性(知识边界): LLM的知识截止于其训练数据的日期。通过调用实时的API(如天气、新闻、股票),模型能够获取到最新的、实时的信息。
  2. 解决事实幻觉(Hallucination): 对于需要精确计算、逻辑查询或获取外部事实的任务,调用专门的工具(如计算器、数据库)可以确保答案的准确性可信度

5.3 获取开放API密钥

这里用获取天气的示例进行演示,如果不利用外部工具,问大模型天气它是没法回答的。

高德开放平台地址:https://lbs.amap.com/

5.3.1 新建 API 接口密钥

登录-控制台-应用管理-我的应用-添加Key

5.3.2 APIKEY 配置填写

Key名称-服务平台-Web服务

提交后会生成一个密钥

到这里我门成功得到了所需要的API密钥。

5.4 工具调用流程

工具调用流程主要包含五个步骤:

  1. 使用模型可以调用的工具向模型发出请求
  2. 接收来自模型的工具调用
  3. 使用来自工具调用的输入,在应用程序端执行代码
  4. 使用工具输出向模型发出第二个请求
  5. 接收模型的最终响应(或更多工具调用)

5.5 示例:获取实时天气

如下图所示,API KEY 要修改成上述我们获取的自己的密钥。

具体代码

# 示例:查询天气
import requests
import json
from openai import OpenAI

# ====== 配置部分 ======
AMAP_API_KEY = "your_API_KEY"
client = OpenAI()

# ====== 本地函数:获取天气 ======
def get_city_weather(city: str):
    """
    输入城市名(中文或英文),返回实况天气信息
    """
    # 先通过高德地理编码 API 获取城市 adcode
    geo_url = f"<https://restapi.amap.com/v3/geocode/geo?address={city}&key={AMAP_API_KEY}>"
    geo_resp = requests.get(geo_url).json()
    if geo_resp.get("status") == "1" and geo_resp.get("geocodes"):
        adcode = geo_resp["geocodes"][0]["adcode"]
    else:
        return f"无法获取城市 {city} 的编码"

    # 再通过天气 API 获取天气
    url = f"<https://restapi.amap.com/v3/weather/weatherInfo?key={AMAP_API_KEY}&city={adcode}&extensions=base&output=JSON>"
    response = requests.get(url).json()
    print("response:", response)

    if response.get("status") == "1" and response.get("lives"):
        live = response["lives"][0]
        return f"{live['province']}{live['city']} 天气:{live['weather']},气温 {live['temperature']}℃,{live['winddirection']}风 {live['windpower']}级,湿度 {live['humidity']}%(更新时间 {live['reporttime']})"
    else:
        return f"对不起,无法获取到 {city} 的天气信息。"

# ====== 定义工具(函数调用声明) ======
tools = [
    {
        "type": "function",
        "function": {
            "name": "get_city_weather",
            "description": "获取给定城市的实时天气",
            "parameters": {
                "type": "object",
                "properties": {
                    "city": {
                        "type": "string",
                        "description": "需要查询天气的城市(可以是中文或英文,例如 北京 或 Beijing)"
                    }
                },
                "required": ["city"]
            }
        }
    }
]

# ====== 初始 Prompt ======
messages = [
    {"role": "user", "content": "济南今天的天气怎么样?"}
]

# ====== 第一次调用 GPT,可能触发工具调用 ======
response = client.chat.completions.create(
    model="gpt-3.5-turbo",
    messages=messages,
    tools=tools,
)

response_message = response.choices[0].message
print("response_message:", response_message)

tool_calls = response_message.tool_calls
print("tool_calls:", tool_calls)

# ====== 如果 GPT 要调用工具,就执行本地函数 ======
if tool_calls:
    messages.append(response_message)  # 先把 assistant 的 tool_call 消息加进去

    available_functions = {
        "get_city_weather": get_city_weather
    }

    for tool_call in tool_calls:
        function_name = tool_call.function.name
        function_to_call = available_functions[function_name]
        function_args = json.loads(tool_call.function.arguments)
        function_response = function_to_call(city=function_args.get("city"))

        # 把工具执行结果返回给 GPT
        messages.append({
            "tool_call_id": tool_call.id,
            "role": "tool",
            "name": function_name,
            "content": str(function_response)
        })

    # ====== 再次调用 GPT,让它生成自然语言答案 ======
    second_response = client.chat.completions.create(
        model="gpt-3.5-turbo",
        messages=messages,
    )
    print("最终回答:", second_response.choices[0].message.content)

如果觉得本文对您有所帮助,请 关注 点赞收藏,后续会持续给大家分享自己所学所得,一起进步。

Logo

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

更多推荐