天天看点

OpenAI 的 GPT 简化版: 函数调用

作者:吉祥庄钢铁侠

ChatGPT 革命

在这个人工智能不断进步的时代,在讨论软件工程的最新发展时,几乎不可能忽视 ChatGPT 的影响。开放人工智能(OpenAI)的创意及其颠覆性的潜力,已被科技行业的众多软件工程师和高管迅速整合,其中既有巨型科技企业,也有蓄势待发的新兴初创公司。从创建和完善会话式人工智能的开创性努力开始,OpenAI 已经成为几乎整个科技领域必不可少的工具。

OpenAI 拥抱现代工作流程

OpenAI 意识到 GPT 模型在众多软件工程工作流程中所发挥的巨大作用,因此采取了大胆而前瞻性的举措,利用一种称为函数调用的新功能来升级其人工智能模型的功能。

起初,我以为这只是炒作。我的意思是,我已经在后台针对特定用例开发了多步骤工作流,并已通过相应的前端应用程序进行引导。但这是一个全面、高维护的流程,工作流程越长,出错的几率就越高。(概率法则,对吧?) 试想一下,做出的更改会影响下游其他部分的其他提示。

考虑一下预订航班的聊天机器人。像 "预订 8 月 25 日从纽约飞往旧金山的航班 "这样的用户输入需要先解析意图(预订航班),然后请求特定的格式和变量类型进行解析,最后确保收到的所有值和类型都是正确的。只有这样,我们才能更有信心地调用我们的原始函数,并期待最好的结果。

现在,如果我们不需要考虑曲解、幻觉或仅仅是由于生成词的概率而偏离最初预期的反应的可能性,所有这些听起来都很完美。这正是函数调用的用处所在。

函数调用解密

函数调用允许开发人员从现有代码(无论是前端代码还是后端代码)中提供对函数名称的特定引用,并允许 GPT 在响应过程中考虑是否以及何时需要使用该函数。这包括两个部分:函数和 function_call。这两个部分都是变量,可以与完成 API 请求正文一起传递。

{
    apiKey: OPENAI_API_KEY,
        model: "gpt-3.5-turbo",
            functions: [
              {
                      name: "get_current_weather",
                      description: "Get the current weather in a given location",
                      parameters: {
                                type: "object",
                                properties: {
                                            location: {
                                                          type: "string",
                                                          description: "The city and state, e.g. San Francisco, CA",
                                                        },
                                            unit: { type: "string", enum: ["celsius", "fahrenheit"] },
                                          },
                                required: ["location"],
                              },
                    },
                ],
                function_call: "auto",
}
           

函数指的是作为附加属性传入 API 请求的函数引用数组(列表)。从上面的 JSON(作为配置传入)中可以看出,这些引用采用对象(字典)格式,带有相关的键和值,使 GPT 可以了解它们的用途、预期逻辑和输入/输出格式。GPT 会解析以下属性:

  1. 名称: 要考虑的函数的具体名称。
  2. 描述: 对函数功能的简短描述,用于 ChatGPT 的推理。
  3. 参数: 函数接受的参数,以 JSON 模式中的对象(字典)形式描述。每个对象应包括类型和属性(或枚举列表)。您还可以用单独的列表定义哪些是必需的。

函数调用是指 GPT 使用预定义函数或考虑一系列函数的直接指令。该属性的默认值为 auto,这意味着它会从函数列表中的可用选项中进行评估,并自动决定调用哪个最合适。或者,开发人员也可以编写一个特定的 "function_name "来代替。

在这两种情况下,开发人员都需要手动设置对 GPT 函数的处理,除非它足够简单,GPT 可以在没有实际引用的情况下自行完成大部分逻辑。响应将包括一个直接的 function_call 标记,开发人员可以使用该标记来确定 GPT 何时决定需要函数调用,并对其进行适当处理。请看 OpenAI 团队自己的示例:

response = openai.ChatCompletion.create(
      model="gpt-3.5-turbo-0613",
      messages=messages,
      functions=functions,
      function_call="auto",  # auto is default
  )

response_message = response["choices"][0]["message"]

if response_message.get("function_call"):
    available_functions = {
              "get_current_weather": get_current_weather,
              ...other functions
    }
    function_name = response_message["function_call"]["name"]
    fuction_to_call = available_functions[function_name]
    function_args = json.loads(response_message["function_call"]["arguments"])
    function_response = fuction_to_call(
              location=function_args.get("location"),
              unit=function_args.get("unit"),
          )

messages.append(
  {
            "role": "function",
            "name": function_name,
            "content": function_response,
  }
  )
           

现在,你可以说,多提示工作流程(想想 LangChain)可以轻松帮助解决其中的一些限制,这并不完全错误。但请记住,OpenAI API 的请求每小时、每天和每月都有限制。在决定使用许多前置程序和指令来过滤输入和输出时,还存在令牌成本的因素。但最重要的还是时间延迟因素。根据令牌的长度,一个请求很容易让我们等待几秒钟。试想一下,在做出响应之前,我们需要通过中间处理来获得多个人工智能响应。

因此,归根结底,它有助于简化从提示到响应的流程,而无需过多插手中间的过滤器和中间件。毕竟,在我们的工作流程中使用人工智能的整体目标就是将重复性任务和复杂问题解决的重任交给他人,不是吗?

好处说明

至少从我个人的实验来看,函数调用确实带来了一系列令人印象深刻的好处,极大地改善了软件工程师的工作流程,使编码更高效、更不易出错、更能适应复杂的场景。下面是我的一些观察结果:

  1. 优化解析和处理步骤: 在传统的应用场景中,人工智能应用程序需要解释用户输入、提取关键数据、格式化数据,然后根据这些数据执行函数。有了函数调用,解析和处理用户输入所需的工作就大大减少了,GPT 现在可以直接将用户意图映射到相应的函数,从而减少了对复杂、易出错的工作流程的需求。
  2. 减少应用程序接口设置开销: 函数调用无需大量中间件、过滤策略或提示链,从而减少了设置应用程序接口的开销。通过函数调用,模型可以处理函数的执行,从而避免了多次 API 调用,简化了逻辑。
  3. 降低令牌成本: 由于函数调用不需要这些更复杂的提示链,因此消耗的令牌更少。这意味着您可以用更少的令牌实现更多的功能,从而降低更全面的生产工作流程的成本。
  4. 提高响应的准确性:通过指定 GPT 要调用或考虑的确切函数,开发人员可以大大减少在一系列重要步骤中出现误解和幻觉的机会。这将带来更准确、更可靠的结果,增强用户的信任感。
  5. 简化工作流程变更: 当工作流程发生变化或发展时,调整人工智能的行为可能是一个繁琐且容易出错的过程。然而,有了函数调用,只需更改函数定义,就能轻松处理这些更新。提高响应的准确性:通过指定 GPT 要调用或考虑的确切函数,开发人员可以大大减少在一系列重要步骤中出现误解和幻觉的机会。这将带来更准确、更可靠的结果,增强用户的信任感。

挑战与专业技巧

不过,函数调用虽然具有革命性,但也并非没有挑战:

函数设置和处理的复杂性: 函数调用的初始设置可能有点棘手,尤其是对于那些刚接触 GPT 模型的人来说。这包括设置函数引用和处理函数调用响应。最重要的一点是,函数调用允许 GPT 对函数进行推理并引用其调用,但不能直接执行。我们需要适当处理这些调用。

  1. 提示:在进入复杂场景之前,先从简单的函数和简单的响应开始。这将帮助您了解 ChatGPT 如何解释函数以及如何处理响应。

过度拟合的可能性: 根据使用函数调用的方式和时间,GPT 可能会过度使用某些函数,而对其他函数使用不足。这可能会导致重复响应,并限制输出的多样性。

  1. 提示:实施定期监控,并尝试使用不同的描述和参数,以了解它们如何影响函数调用。

广泛测试的必要性: 鉴于函数调用的复杂性及其对输出的重大影响,有必要进行广泛的测试,以确保响应的准确性和函数调用的正确处理。

  1. 小贴士 自动化单元测试可以大大减少大量测试所需的时间和精力。考虑通过持续集成建立一个测试套件,确保函数调用的所有选项都能按预期运行。

人工智能进步的新曙光

我们所看到的进步,尤其是在函数调用方面的进步,充分说明了一件事:人工智能的发展才刚刚起步。随着我们将这些工具更深入地集成到我们的流程中,人类直觉和机器处理之间的界限将不断模糊。人工智能潜力巨大,前景光明。下一步是什么?只有时间(也许还有下一次 ChatGPT 的迭代)会告诉我们答案。

继续阅读