文档
开发指南
Tool Call 使用建议

使用 Tool Call 扩展你的应用能力

大模型虽然掌握了丰富的知识,但在特定领域,例如时效性较高的资讯类和天气预报,或者需要严密科学计算,以及特定行业的知识,当它们匮乏这部分知识时,它们可能会编造看似真实但实则虚假的信息。

为解决这一问题。阶跃大模型提供了 Tool call 工具,Tool call 可以扩展语言模型的功能,使其能够执行额外的操作,如搜索信息、科学计算、访问数据库等。这样模型可以为用户提供更精准的信息,帮助开发者更好地处理业务需求。

除了获取信息以外, Tool Call 还可以帮助开发者生成函数调用签名,开发者通过对调用签名的处理,实现扩展应用能力,让你的应用除了对话,还可以完成各项不同的能力。

实现原理 & 参考

在使用 Tool Call 时,我们可以选择两个方向来思考 Tool Call 帮助我们扩展应用能力:

  • 使用 Tool Call 获取大模型自身训练不包含的信息,丰富上下文,精确回答内容;
  • 使用 Tool Call 操作本地应用程序,执行特定业务操作。

前者主要通过 Tool Call 调用预定义好的函数,以获得更加精确的信息,帮助大模型补全上下文,从而生成更加精确的回答。 后者则是通过 Tool Call 调用本地应用程序,执行特定的业务操作,以实现更加丰富的功能。

使用 Tool Call 获取信息

这里我们以助手类应用的常见技能 —— 查询天气为例,我们需要构建一个可以通过自然语言,查询天气的能力。

你需要做以下四步:

  • 第一步,需要准备好查询天气接口的地址和密钥,构造查询天气的 Function;
  • 第二步,构建 get_weather 工具定义查询天气 Function 的功能;
  • 第三步,阶跃大模型识别用户查询天气的意图时,根据提示语给出查询参数;
  • 第四步,使用大模型返回的参数调用查天气接口,获取准确的天气信息。

参考代码:以 Python 为例

from openai import OpenAI
import requests
import json
 
# 初始化 查询天气的接口参数,这里我使用的是高德查询天气接口,各位开发者可以按需自行选择供应商进行实现
get_weather_url = "https://restapi.amap.com/v3/weather/weatherInfo?parameters"
get_weather_key = "YourGaoDeAPIkey"
COMPLETION_MODEL= "step-1-8k"
 
# 初始化 阶跃星辰 Client
STEPFUN_KEY = "YourAPIkey"
client = OpenAI(base_url="https://api.stepfun.com/v1", api_key=STEPFUN_KEY)
 
 
# 初始化查询天气的函数
def get_weather(city):
    params = {
        "city": city,
        "key": get_weather_key,
        "extensions": "base",  # 获取实时天气
    }
    response = requests.get(url=get_weather_url, params=params)  # 实时天气
    if response.status_code == 200:
        data = response.json()
        print(data)
        # weather = data.get ('lives')[0].get ('weather')  # 当前天气现象
        # temperature = data ['lives'][0].get ('temperature')  # 当前温度
        # print ( f"{city} 现在的天气是 {weather} 温度是 {temperature}°C.")
    else:
        print("对不起,我无法获取这个地点的天气。")
 
 
# 构建 get_weather 函数说明
tools = [
    {
        "type": "function",
        "function": {
            "name": "get_weather",
            "description": "查询天气",
            "parameters": {
                "type": "object",
                "properties": {
                    "city": {"type": "string", "description": "城市名称(必须为汉字)"}
                },
                "required": ["city"],
            },
        },
    }
]
 
 
# 调用补全接口进行补全
def query_weather(prompt):
    completion = client.chat.completions.create(
        model=COMPLETION_MODEL,
        messages=[{"role": "user", "content": prompt}],
        ## 自动选择是否调用外部函数
        tool_choice="auto",
        tools=tools,
    )
    # print (completion.choices [0].message.content.strip ())
    print(completion)
    # 判断是否命中查询天气 Function
    if completion.choices[0].message.content.strip() == "":
        if completion.choices[0].message.tool_calls[0].function.name == "get_weather":
            # 获取参数
            city_name = json.loads(
                completion.choices[0].message.tool_calls[0].function.arguments
            )
            # 调用 Function
            get_weather(city_name["city"])
        else:
            print("未命中查询天气 Tool")
    else:
        print("抱歉出错了")
        # print (completion.choices [0].message.content.strip ())
 
 
# 查询天气
query_weather("上海现在的天气怎么样?")
 

返回结果

# 返回值结果
# 首先大模型通过意图识别到需要调用 Tool Call,所以在 tool_calls 里给出了需要调用的函数名称,以及参数
{
    "id": "291c59ebf4017a937a2a42a8ed52581f.c2669ebc05a491c70f821b4e568b6433",
    "object": "chat.completion",
    "created": 1722505763,
    "model": "step-1-8k",
    "choices": [
        {
            "index": 0,
            "message": {
                "role": "assistant",
                "content": "",
                "tool_calls": [
                    {
                        "id": "call_brg23SRcTgmpm_V0jfP-iA",
                        "type": "function",
                        "function": {
                            "name": "get_weather",
                            "arguments": "{\"city\": \" 上海 \"}"
                        }
                    }
                ]
            },
            "finish_reason": "stop"
        }
    ],
    "usage": {
        "cached_tokens": 48,
        "prompt_tokens": 94,
        "completion_tokens": 16,
        "total_tokens": 110
    }
}
# 接着使用大模型给出的参数调用查询天气接口,获得准确的天气
{
    "status": "1",
    "count": "1",
    "info": "OK",
    "infocode": "10000",
    "lives": [
        {
            "province": "上海",
            "city": "上海市",
            "adcode": "310000",
            "weather": "晴",
            "temperature": "37",
            "winddirection": "西北",
            "windpower": "≤3",
            "humidity": "42",
            "reporttime": "2024-08-02 10:01:14",
            "temperature_float": "37.0",
            "humidity_float": "42.0"
        }
    ]
}

# 继续拼接作为上下文信息放入 Messages,让大模型进行补全。

使用 Tool Call 执行任务

当应用需要扩展其能力,不仅仅是获取数据时,则可以通过 Tool Call 能力,为你的应用增加一些神奇的能力,从而帮助用户更进一步展示不同的能力。

这里我们同样以助手类应用为例,我们可以实现一个通过自然语言发送电子邮件的能力。你需要做以下几步:

  • 第一步,在本地构建出一个发送邮件的 Function ,并实现发送邮件相关功能;
  • 第二步,构建 send_email 工具定义发送邮件的功能;
  • 第三步,阶跃大模型识别用户发送邮件的意图时,根据提示语给出查询参数;
  • 第四步,使用大模型返回的参数调用发送电子邮件。
参考代码:以 Python & Swift 为例

本地的发送邮件的 Function

func sendEmail (subject:String, body: String, recipient: String) {
    // 调用 MFMailComposeViewController 来发送邮件
}

服务端调用阶跃星辰大模型的参考代码

from openai import OpenAI
 
 
# 初始化 阶跃星辰 Client
STEPFUN_KEY = "YourAPIkey"
client = OpenAI(base_url="https://api.stepfun.com/v1", api_key=STEPFUN_KEY)
 
# 构建 sendEmail 函数说明
tools = [
    {
        "type": "function",
        "function": {
            "name": "senEmail",
            "description": "这个函数可以用于向特定的用户发送包含特定内容的电子邮件",
            "parameters": {
                "type": "object",
                "properties": {
                    "subject": {
                        "type": "string",
                        "description": "邮件的标题,不可以超过 255 个字",
                    },
                    "body": {
                        "type": "string",
                        "description": "邮件内容,不可以超过 4096 个子",
                    },
                    "recipient": {"type": "string", "description": "收件人"},
                },
                "required": ["subject", "body", "recipient"],
            },
        },
    }
]
 
 
# 调用阶跃星辰 API 生成接口调用方法
def get_call_sign(user_input):
    completion = client.chat.completions.create(
        model=COMPLETION_MODEL,
        messages=[{"role": "user", "content": user_input}],
        ## 自动选择是否调用外部函数
        tool_choice="auto",
        tools=tools,
    )
    if completion.choices[0].message.content.strip() == "":
        if completion.choices[0].message.tool_calls[0].function.name == "senEmail":
            # 获取参数
            arguments = json.loads(
                completion.choices[0].message.tool_calls[0].function.arguments
            )
            # 触发本地调用函数
            send_to_client("sendEmail", arguments)
 

注意事项

  • 构造 Tool 的时候请注意将 Function 的 description 描述清楚,以便于大模型清晰的知道 Function 的功能,这样能提高命中率;
  • Function 入参的 description 也需要备注清楚(建议说明入参是中文还是英文),以便于大模型生成有效的参数供使用。