• OpenAI的多函数调用(Multiple Function Calling)简介


      我在六月份写了一篇关于GPT 函数调用(Function calling) 的博客https://blog.csdn.net/xindoo/article/details/131262670,其中介绍了函数调用的方法,但之前的函数调用,在一轮对话中只能调用一个函数。就在上周,OpenAI在开发者大会上,升级了函数调用的功能,在新的gpt-3.5和gpt-4模型中,可以在单次对话中调用多个函数了,而且在python SDK中也提供了并发函数调用相关的接口,无疑这将大幅减少大语言模型和现实世界之间交互的开发复杂度,接下来就让我用一个具体的示例,带你了解下OpenAI的新特性。
    在这里插入图片描述
      这里假设我需要利用gpt实现一个百度、谷歌、必应三个搜索引擎搜索结果汇总的功能。我现在有以下的几个搜索函数(我们假装已经实现了从分别从百度、谷歌、必应获取搜索结果的逻辑)。

    def search_baidu(keyword):
        """从百度搜索引擎中搜索关键词"""
        return f"{keyword}是一个技术博主"
    
    def search_google(keyword):
        """从谷歌搜索引擎中搜索关键词"""
        return f"{keyword}是一个后端工程师"
    
    def search_bing(keyword):
        """从必应搜索引擎中搜索关键词"""
        return f"{keyword}是一个Python爱好者"
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

      接下来我们需要将这三个搜索函数按照openai给定的格式用json字符串描述出来,具体可以参考官方文档,我这里直接给出上面三个函数的json描述。

    tools = [
        {
            "type": "function",
            "function": {
                "name": "search_baidu",
                "description": "从百度搜索引擎中搜索关键词",
                "parameters": {
                    "type": "object",
                    "properties": {
                        "keyword": {
                            "type": "string",
                            "description": "搜索关键词",
                        }
                    },
                    "required": ["keyword"],
                },
            }
        },    
        {
            "type": "function",
            "function": {
                "name": "search_google",
                "description": "从google搜索引擎中搜索关键词",
                "parameters": {
                    "type": "object",
                    "properties": {
                        "keyword": {
                            "type": "string",
                            "description": "搜索关键词",
                        }
                    },
                    "required": ["keyword"],
                },
            }
        },        
        {
            "type": "function",
            "function": {
                "name": "search_bing",
                "description": "从bing搜索引擎中搜索关键词",
                "parameters": {
                    "type": "object",
                    "properties": {
                        "keyword": {
                            "type": "string",
                            "description": "搜索关键词",
                        }
                    },
                    "required": ["keyword"],
                },
            }
        }
    ]
    available_functions = { "search_baidu": search_baidu, "search_google": search_google, "search_bing": search_bing } 
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54

      上面这个的目的是将所有函数的作用和使用方法(入参)描述给gpt,让gpt知道如何去调用。available_functions是为了保存函数名和函数的映射关系,方便我们后续通过函数名去调用函数。

      接下来我们实现一个函数,其功能就是给定一个关键词(keyword),返回百度、谷歌、必应三个搜索引擎搜索结果的汇总,这要在之前的函数调用方式下,你必须通过多轮对话获取到所有需要调用的函数,然后将结果汇总后在发给gpt。而在支持了多函数调用后,仅需要一轮对话就可以完成所有的功能,完整的代码如下:

    from openai import OpenAI
    import json
    client = OpenAI(base_url='https://thales.xindoo.xyz/openai/v1/')
    
    def search(keyword):
        messages = [{"role": "user", "content": f"汇总下百度、谷歌、必应三个搜索引擎关于'{keyword}'的结果"}]
        # 发起首次请求,告诉gpt要做什么,已经有哪些函数可以调动 
        response = client.chat.completions.create(
            model="gpt-3.5-turbo-1106",
            messages=messages,
            tools=tools,
            tool_choice="auto", 
        )
        response_message = response.choices[0].message
        tool_calls = response_message.tool_calls
        # 检查是否需要调用函数
        if tool_calls:
            # 解析所有需要调用的函数及参数
            messages.append(response_message)  # 注意这里要将openai的回复也拼接到消息列表里
            # 将所有函数调用的结果拼接到消息列表里
            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(**function_args)
                messages.append(
                    {
                        "tool_call_id": tool_call.id,
                        "role": "tool",
                        "name": function_name,
                        "content": function_response,
                    }
                ) 
            second_response = client.chat.completions.create(
                model="gpt-3.5-turbo-1106",
                messages=messages,
            )  
            return second_response.choices[0].message.content
        
    print(search("xindoo"))
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40

      输出的结果是根据百度、谷歌和必应三个搜索引擎的结果,'xindoo'可能是一个技术博主、后端工程师以及Python爱好者。

    这里需要提醒以下两点:

    1. 目前只有gpt-4-1106-preview和gpt-3.5-turbo-1106两个模式支持单词对话同时调用多个模型的,其他模型均不支持。
    2. openAI改变了api中传递function的参数,废弃了 functions和 function_call,改用了tools和tool_choice两个新参数,我猜测是为了未来增加更多的工具支持。

      这里额外说下,上面的三个函数调用是串行调用,如果每个函数都比较耗时的话,会增加整体的调用时长,而在最新的assistant api中增加了并行执行函数的api,这个我们放到下篇文章中讲解。

  • 相关阅读:
    小程序里.vue界面中传值的两种方式
    MFC Windows 程序设计[153]之多样的文档视图
    第五章 路由技术及应用
    物联网技术融合:ZETA联盟会员推出支持ZETA通信协议的BLE蓝牙网关
    DevEco中被忽略的实用功能
    【附源码】计算机毕业设计java招聘信息管理平台设计与实现
    牛客网SQL157
    《疯狂塔防物语》新一轮边玩边赚活动来了,仅面向战斗卡 NFT 持有人开放!
    【Java 小知识】Request、Servlet
    IPv6协议基本概念
  • 原文地址:https://blog.csdn.net/xindoo/article/details/134483093