lwlwilliam

大模型使用工具的能力怎么来的

2026/04/09 人工智能

大模型会提供一个叫Tool Calls(也有的叫Function Calls)的功能,看起来很神奇,实际上就是LLM根据对话内容提取出需要使用的工具及其参数,再将其以结构化的形式返回给客户端,客户端通过响应的内容判断是否存在“使用工具”这个操作,如果存在,则从中获取所需使用的“工具名”及“参数”来使用工具。

看以下python写的一个示例。

import json
import os
import sys
from openai import OpenAI

API_KEY = "sk-xxx"
client = OpenAI(api_key=API_KEY, base_url="https://api.deepseek.com")

ESC = "\033"
COLOR_FAIL = ESC + "[31m"
COLOR_SUCCESS = ESC + "[32m"
MSG_FAIL = "fail"
MSG_SUCCESS = "success"
RESET = ESC + "[0m"


def pretty_msg(msg, color=COLOR_FAIL):
    """美化提示"""
    colors = {MSG_FAIL: COLOR_FAIL, MSG_SUCCESS: COLOR_SUCCESS}
    color = COLOR_FAIL if colors.get(color) is None else colors.get(color)
    return f"{color}{msg}{RESET}"


def code(name):
    """执行代码生成任务"""
    try:
        print(COLOR_FAIL + "+" * 50 + "\n" + COLOR_SUCCESS, sep="", end="")
        os.system('ls -l ~')
        print(COLOR_FAIL + "-" * 50 + RESET, sep="")
        return "用 {} 写一个简单的字符串反转函数".format(name)
    except Exception as e:
        print(pretty_msg("内部执行错误: {}".format(str(e))))
        sys.exit(1)


def safe_chat_completion(**kwargs):
    """安全的 API 调用包装器"""
    try:
        return client.chat.completions.create(**kwargs)
    except Exception as e:
        print(pretty_msg("调用失败: {}".format(str(e))))
        sys.exit(1)


def main(content):
    """主函数"""
    print("正在处理请求...")
    content = "如果你从这段话'{}'中获取到编程语言的名称,就调用 code 函数,并将编程语言的名称作为 name 参数。".format(content)

    # 第一次调用:检测是否需要调用工具
    response = safe_chat_completion(
        model="deepseek-chat",
        messages=[
            {"role": "system", "content": "You are a helpful assistant."},
            {"role": "user", "content": content},
        ],
        tools=[
            {
                "type": "function",
                "function": {
                    "name": "code",
                    "parameters": {
                        "type": "object",
                        "properties": {
                            "name": {
                                "type": "string",
                            }
                        },
                        "required": ["name"]
                    }
                },
            }
        ],
        tool_choice="auto"
    )

    message = response.choices[0].message

    # 输出第一次响应
    if message.content:
        print('first:', message.content)
    else:
        print('first: (无文本内容)')

    # 处理工具调用
    if hasattr(message, 'tool_calls') and message.tool_calls:
        for tool_call in message.tool_calls:
            if tool_call.function.name == "code":
                try:
                    arguments = json.loads(tool_call.function.arguments)
                    name = arguments.get("name", "未知语言")
                    result = code(name)

                    # 第二次调用:带工具结果的流式响应
                    second_response = safe_chat_completion(
                        model="deepseek-chat",
                        messages=[
                            {"role": "system", "content": "You are a helpful assistant."},
                            {"role": "user", "content": content},
                            message,  # 模型的 tool call 响应
                            {
                                "role": "tool",
                                "tool_call_id": tool_call.id,
                                "content": result
                            }
                        ],
                        stream=True
                    )

                    print("\nsecond:")
                    for chunk in second_response:
                        if chunk.choices[0].delta.content:
                            print(chunk.choices[0].delta.content, end="")
                    print()  # 换行

                except json.JSONDecodeError:
                    print(pretty_msg("错误:无法解析工具调用参数"))
                    sys.exit(1)
                except KeyError as e:
                    print(pretty_msg("错误:缺少必需参数 {}".format(str(e))))
                    sys.exit(1)
                except Exception as e:
                    print(pretty_msg("执行错误 {}".format(str(e))))
                    sys.exit(1)
    else:
        if message.content:
            print('first:', message.content)
        else:
            print("未检测到工具调用")


if __name__ == "__main__":
    try:
        content = "你知道吗?python 是世界最好的语言。"
        main(content)
    except KeyboardInterrupt:
        print(pretty_msg("用户中断执行"))
        sys.exit(1)
    except Exception as e:
        print(pretty_msg("未预期的错误:{}".format(str(e))))
        sys.exit(1)

以上代码会从让LLM从用户的对话中判断是否存在编程语言的名称,如果存在,则返回Tool Calls响应,客户端针对该响应进行调用code工具,再将code工具的返回内容进行再次对话。

可以看到code其实就是一个普通的python函数,code里面当然可以做其它“神奇”的操作,如打开浏览器做爬虫等。关键点就是第一次请求将code函数作为工具传给了大模型,这时候就需要大模型自行判断是否返回一个工具调用的响应了。如果返回工具调用响应,客户端则可以根据响应使用相应的工具,再根据工具的处理结果进行后续与大模型交互等操作。

Search

    Table of Contents