OpenAI Function calling

开篇

原文出处

最近 OpenAI 在 6 月 13 号发布了新 feature,主要针对模型进行了优化,提供了 function calling 的功能,该 feature 对于很多集成 OpenAI 的应用来说绝对是一个“神器”。

Prompt 的演进

如果初看 OpenAI 官网对function calling的介绍,似乎不足以体现它的重要性。为了更进一步理解它的作用,我们先来简单回顾一下在使用 OPenAI 时 Prompt 是如何演进的。

Prompt 1.0

OpenAI Function calling_第1张图片

还记得 chatGPT 在最一开始大火时,除了 AI 强大的能力作为一个吸引点之外,“低门槛的要求使得所有人都可以使用”也扮演着至关重要的角色。也正是如此,大家不再对 AI 感到陌生,借助和 AI 对话,随便一个 Prompt 就可以让使用者直接或间接的获得帮助。

但是随着使用深度的增加,大家慢慢发现chatGPT有时会思维发散,往往不能聚焦关键问题,甚至会“无言乱语”。

在此之上,1.0 版本的 Prompt 出现,它要求对话开始前需要设定上下文。在这样的提示下,AI 能够有较好的表现,并且不再发散,可以解决较为简单的问题。

Prompt 2.0

OpenAI Function calling_第2张图片

随着使用场景的复杂化,单纯的设置一个上下文给chatGPT已经远远不够。你必须给“足”上下文,最简单的方式就是提供exmaple,这种做法的背后逻辑和 COT(Chain of Thought)是一样的。

2.0 版本的 Prompt 是使用最广泛的也是最可靠的。

Prompt 3.0

OpenAI Function calling_第3张图片

3.0 版本的 Prompt 并非比 2.0 要高级,只是在需求上不一样。因为随着大量 AI 工具和 OpenAI 集成,想要充分利用 AI 的能力,让更多的系统和模块和你结合,就必须得提取参数或者返回特定的输出。

因此,3.0 聚焦更多的是集成。

Function calling

Prompt 在迭代到 3.0 版本后,AI 的缺点已经一览无遗。虽然chatGPT有大量的知识储备,但它的数据都是预训练的,由于不能联网,所以它并不是“无所不知”的。

因此,集成第三方系统对模型的赋能就成为了当下众多 AI 应用的首要方案。可赋能就代表得知道用户到底要知道什么,这就是 3.0 版本的努力方向。但是 3.0 的版本其实并不能非常稳定的输出特定格式,或者即便格式可以固定,json 数据的类型也不能很好的控制。比如上面的 3.0 例子里,不是所有的 AI 模型都能稳定输出price: 1500,也有可能是$1500(Bard)。
也许你会觉得1500$1500的差异并不大,大不了可以处理一下前缀之类的问题,那就大错特错了。因为这是作为 不同模块(或系统)链接的桥梁,就如同 API 之间集成的契约一般,必须有严格的定义。

一个典型的例子就是前段时间大火的Auto-GPT, 在 3.5 turbo 的模型下,它很难完成一个任务,往往会陷入无限的循环,主要的原因就是它需要非常严格的上下文衔接来集成各种 command,但凡有一丁儿点的差异都会导致“连接”失败。

在此背景下,function calling出现了。

它允许用户定义一个或多个 function 描述,该描述满足 API doc 的规范,定义了参数的类型和含义。AI 在经过 function calling 的调教后,可以准确的理解这种规范并按照上下文去决定是否可以“命中”该方法,如果“命中”,则会返回该方法的参数。

到此它已经解决了参数提取的问题,但并没有结束。此时开发者可以利用这个参数去集成第三方系统,获取特定的信息然后把结果反馈给模型,这样模型就有了这个方法的输入和输出,看起来像是模型“执行”了该方法,而实际是模型被动的获取了它没有的知识。

最后,AI 根据新获得的知识和信息,给用户输出最后的结果。

Example: DB 搜索

假设我们想利用 AI 在 DB 层建立搜索接口,我们可以按照以下步骤:

    1. 将 DB 的 meta 数据作为上下文,定义 ask_database 的方法规范
{
  "functions": [
    {
      "name": "ask_database",
      "description": "Use this function to answer user questions about music. Output should be a fully formed SQL query.",
      "parameters": {
        "type": "object",
        "properties": {
          "query": {
            "type": "string",
            "description": "SQL query extracting info to answer the user\\'s question.SQL should be written using this database schema:\"Table name: album_tb; Columns: album(string), published_at(string), likes(string)\".The query should be returned in plain text, not in JSON."
          }
        },
        "required": ["query"]
      }
    }
  ]
}
    1. 设定 system 上下文,提示模型如果 user 的 prompt 无法命中 function 的话就不要强行“脑补”

这很有用,说明不是所有的 Prompt 都需要被 function 来解析,有点类似 if else,这样可以回归到正常的对话中。

{
  "role": "system",
  "content": "Don't make assumptions about what values to plug into functions. Ask for clarification if a user request is ambiguous."
}
    1. 提问
{
  "role": "user",
  "content": "What are the top 2 the albums"
}
    1. 模型命中 function 并且返回解析的参数
{
  "role": "assistant",
  "content": null,
  "function_call": {
    "name": "ask_database",
    "arguments": "{\n  \"query\": \"SELECT * FROM album_tb ORDER BY likes DESC LIMIT 5\"\n}"
  }
}
    1. 查询 DB,将数据返回给我模型(赋能)
{
  "role": "function",
  "name": "ask_database",
  "content": "[{\"album\":\"Tanya\",\"published_at\":\"2000-01-01\",\"likes\":\"10000\"},{\"artist\":\"Im OK\",\"published_at\":\"1999-01-01\",\"likes\":\"20000\"}]"
}
    1. 模型根据新的知识储备响应用户的 Prompt
{
  "role": "assistant",
  "content": "The top 2 albums are \"Im OK\" with 20,000 likes and \"Tanya\" with 10,000 likes."
}
    1. 再次提问,测试新的知识储备是否被模型深刻理解
{
  "role": "user",
  "content": "What are the most popular one"
}
    1. 模型可以准确的在新的知识储备进行搜索
{
  "role": "assistant",
  "content": "The most popular album is \"Im OK\" with 20000 likes."
}

完整的 API 请求如下:

{
	"model": "gpt-3.5-turbo-0613",
	"messages": [
		{
			"role": "system",
			"content": "Don't make assumptions about what values to plug into functions. Ask for clarification if a user request is ambiguous."
		},
		{
			"role": "user",
			"content": "What are the top 2 the albums"
		},
		{
			"role": "assistant",
			"content": null,
			"function_call": {
					"name": "ask_database",
					"arguments": "{\n  \"query\": \"SELECT * FROM album_tb ORDER BY likes DESC LIMIT 5\"\n}"
				}
		},
		{
			"role": "function",
			"name": "ask_database",
			"content": "[{\"album\":\"Tanya\",\"published_at\":\"2000-01-01\",\"likes\":\"10000\"},{\"artist\":\"Im OK\",\"published_at\":\"19999-01-01\",\"likes\":\"20000\"}]"

		},
		{
			"role": "user",
			"content": "What are the most popular one"
		}
	],
	"functions": [
		{
			"name": "ask_database",
			"description": "Use this function to answer user questions about music. Output should be a fully formed SQL query.",
			"parameters": {
				"type": "object",
				"properties": {
					"query": {
						"type": "string",
						"description": "SQL query extracting info to answer the user\\'s question.SQL should be written using this database schema:\"Table name: album_tb; Columns: album(string), published_at(string), likes(string)\".The query should be returned in plain text, not in JSON."
					}
				},
				"required": [
					"query"
				]
			}
		}
	]
}

模型

OpenAI 在 6 月 13 号的 release 中,专门针对 function calling 发布了新的模型,无论是价格还是上下文的长度都有比较大的变化,以下为 3.5(免费)的模型列表:

OpenAI Function calling_第4张图片

最后

function calling 对与模型精准的理解 Prompt 和集成外部知识储备系统绝对是一个强大的工具,未来 Prompt 的趋势肯定也会朝着个方向去设计,拭目以待吧。

你可能感兴趣的:(AI,chatgpt,AI,OpenAI,FunctionCalling)