openai function call stream调用指南

openai function call stream调用指南

首先支持了 function call 且支持多个function并行调用的模型有:gpt-4-turbo-preview, gpt-4-0125-preview, gpt-4-1106-preview, gpt-3.5-turbo-0125, and gpt-3.5-turbo-1106
所谓并行就是每次要调用的function可以同时进行,而不是串行。

function call支持流式处理,可以做到打印机效果

具体例子可以参考一个开源项目:
点击跳转
https://github.com/XingYu-Zhong/ChineseStockGPT

准备工作

需要准备一份tools的json文件,用来描述每个function的功能和需要输入的参数

ex:

tools = [
    {
        "type": "function",
        "function": {
            "name": "get_current_weather",
            "description": "Get the current weather",
            "parameters": {
                "type": "object",
                "properties": {
                    "location": {
                        "type": "string",
                        "description": "The city and state, e.g. San Francisco, CA",
                    },
                    "format": {
                        "type": "string",
                        "enum": ["celsius", "fahrenheit"],
                        "description": "The temperature unit to use. Infer this from the users location.",
                    },
                },
                "required": ["location", "format"],
            },
        }
    },
    {
        "type": "function",
        "function": {
            "name": "get_n_day_weather_forecast",
            "description": "Get an N-day weather forecast",
            "parameters": {
                "type": "object",
                "properties": {
                    "location": {
                        "type": "string",
                        "description": "The city and state, e.g. San Francisco, CA",
                    },
                    "format": {
                        "type": "string",
                        "enum": ["celsius", "fahrenheit"],
                        "description": "The temperature unit to use. Infer this from the users location.",
                    },
                    "num_days": {
                        "type": "integer",
                        "description": "The number of days to forecast",
                    }
                },
                "required": ["location", "format", "num_days"]
            },
        }
    },
]

调用方式(流式)

需要传入模型名字,消息数组,工具数组,流式参数,同时也可以传入tool_choice这个参数来指定工具效用,一般可以不填,让gpt直接根据messages来选择

stream = await client.chat.completions.create(
            model=model,
            messages=one_message,
            tools=tools,
            stream=True
        )

流式处理比较麻烦,需要自己处理调用工具的流式数据,这里给出一个简单的例子

func_call_list = []
async for part in stream:
    if token := part.choices[0].delta.content:
        await msg.stream_token(token)
    delta= part.choices[0].delta
    if delta.tool_calls:
        for tcchunk in delta.tool_calls:
            if len(func_call_list) <= tcchunk.index:
                func_call_list.append({
                    "id": "",
                    "name": "",
                    "type": "function", 
                    "function": { "name": "", "arguments": "" } 
                })
            tc = func_call_list[tcchunk.index]
            if tcchunk.id:
                tc["id"] += tcchunk.id
            if tcchunk.function.name:
                tc["function"]["name"] += tcchunk.function.name
            if tcchunk.function.arguments:
                tc["function"]["arguments"] += tcchunk.function.arguments 

选择工具按理来说是可以不用流式处理这么麻烦的,但是很有可能当前用户的message根本不需要调用工具,然后gpt直接回答流式处理就应该直接输入给前端,所以在第一次就需要流式处理数据。

处理完数据后我们需要判断是否调用了工具,按照上述写法,我们只需要判断func_call_list是否为空即可,因为如果调用了工具,那么func_call_list中至少会有一个元素。
调用工具的话第一件事就要把func_call_list加入message数组里。

        message_history.append(
            {"role": "assistant", "tool_calls": func_call_list}
        )

类似这样,这一步必须加入,要不然后面无法对接上。

然后我们去for tool_call in func_call_list:然后去调用函数获得结果后需要把结果添加到message里

 message_history.append(
    {
        "tool_call_id": tool_call['id'],
        "role": "tool",
        "name": function_name,
        "content": str(function_response),
    }
)

最后我们在去调用openai

stream = await client.chat.completions.create(
    model=model,
    messages=message_history,
    tools=tools,
    tool_choice=None,
    stream=True
)
async for part in stream:
    if token := part.choices[0].delta.content or "":
        await msg.stream_token(token)
message_history.append({"role": "assistant", "content": msg.content})
await msg.update()

总结

对于function call,我们会调用两次openai接口,如果有function需要调用的情况下,如果没有就只会调用一次openai接口。

参考

  • https://cookbook.openai.com/examples/how_to_call_functions_with_chat_models
  • https://cookbook.openai.com/examples/how_to_call_functions_for_knowledge_retrieval
  • https://platform.openai.com/docs/guides/function-calling
  • 12
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值