
过去一段时间,语言模型的强大之处有目共睹。gpt-35-turbo 和 gpt-4 模型以前所未有的能力,让越来越多的企业借助模型的力量,在各色新场景中取得成功。模型本身的强大,加之与其它系统和工具集成的能力,助力用户实现更多功能。
Azure OpenAI 服务正式推出 Function Calling(函数调用)功能,并为最新的0613版本的 gpt-35-turbo 和 gpt-4 提供了根据请求描述生成结构化 JSON 输出的能力。基于用户指定的函数,模型能够以一种原生方式构建 API 调用和结构化数据输出。需要注意的是,虽然模型可以生成调用,但执行和控制权仍在用户手中。

最新版本的 gpt-35-turbo 和 gpt-4 已经经过微调,学会了如何处理函数。如果用户在请求中指定了一个或多个函数,模型将根据提示的上下文确定是否应该调用这些函数。当模型确定应该调用某个函数时,它会通过一个包含该函数参数的 JSON 对象进行响应。
总体上,使用函数的过程可以分为三个步骤:
‣ 步骤1:使用函数和用户输入,调用对话生成 API。
‣ 步骤2:通过模型反馈结果去调用你的 API 或函数。
‣ 步骤3:再次调用对话生成 API,将之前的函数反馈结果包含在内,以获得最终结果。

函数调用提供了以下几种新用例场景。
从数据源或 API 检索数据
函数调用最常见的场景之一是编写调用程序去从搜索索引、数据库或 API 中检索数据,响应用户输入。无论是想利用来自网络、自己的文档或其它数据源的数据,用户都可以使用函数调用,来确定何时需要用附加数据来增强 Prompts(提示)。
示例
messages= [{"role": "user", "content": "Find beachfront hotels in San Diego for less than $300 a month with free breakfast."}]functions= [{"name": "search_hotels","description": "Retrieves hotels from the search index based on the parameters provided","parameters": {"type": "object","properties": {"location": {"type": "string","description": "The location of the hotel (i.e. Seattle, WA)"},"max_price": {"type": "number","description": "The maximum price for the hotel"},"features": {"type": "string","description": "A comma separated list of features (i.e. beachfront, free wifi, etc.)"}},"required": ["location"],},}]response = openai.ChatCompletion.create(engine="gpt-35-turbo-0613",messages=messages,functions=functions,function_call="auto",)print(response['choices'][0]['message'])
响应
{"role": "assistant","function_call": {"name": "search_hotels","arguments": "{\n \"location\": \"San Diego\",\n \"max_price\": 300, \n \"features\": \"beachfront, free breakfast\"\n}"}}
集成 API 或其它工具
函数调用还可以用来添加新的技能,增强模型的能力。例如,为模型提供访问函数的权限,以执行计算或其它大语言模型(LLM)本身不擅长的任务。通过定义这些函数,用户能够可靠地与各种外部 API 或已经在代码中定义的函数进行交互。
函数调用还可以用于执行诸如向数据库写入数据、下订单或发送通知等操作。然而,在实现此类功能之前,了解模型出现错误所带来的影响至关重要。通常情况下,我们建议用户在允许模型执行有风险的操作之前,始终进行用户确认流程。
示例
messages= [{ "role": "user", "content": "Last month Fabrikam made $73,846 in sales. Based on that, what would the annual run rate be?"}]functions= [{"name": "calculator","description": "A simple calculator","parameters": {"type": "object","properties": {"num1": {"type": "number"},"num2": {"type": "number"},"operator": {"type": "string", "enum": ["+", "-", "*", "/", "**", "sqrt"]},},"required": ["num1", "num2", "operator"],},}]response = openai.ChatCompletion.create(engine="gpt-35-turbo-0613",messages=messages,functions=functions,function_call="auto",)print(response['choices'][0]['message'])
响应
{"role": "assistant","function_call": {"name": "calculator","arguments": "{\n \"num1\": 73846,\n \"num2\": 12,\n \"operator\": \"*\"\n}"}}
创建结构化输出
目前,这些模型已经能够输出 JSON,但通常需要额外的解析。如果模型偶尔在响应中以类似"Here is the JSON:"的方式开始或在响应中添加其它文本,可能会比较棘手。
函数调用提供了一种更可靠的方法,让模型从文本中创建结构化的 JSON 输出。当需要从文本中提炼观点,或需要经由整理,让输出变得更易理解时,该功能将十分有价值。
示例
messages= [{"role": "system", "content": "Assistant is a large language model designed to extract structured data from text."},{"role": "user", "content": "There are many fruits that were found on the recently discovered planet Goocrux. There are neoskizzles that grow there, which are purple and taste like candy. There are also loheckles, which are a grayish blue fruit and are very tart, a little bit like a lemon. Pounits are a bright green color and are more savory than sweet. There are also plenty of loopnovas which are a neon pink flavor and taste like cotton candy. Finally, there are fruits called glowls, which have a very sour and bitter taste which is acidic and caustic, and a pale orange tinge to them."}]functions= [{"name": "extract_fruit","type": "function","description": "Extract fruit names from text.","parameters": {"type": "object","properties": {"fruits": {"type": "array","items": {"type": "object","properties": {"fruit": {"type": "string", "description": "The name of the fruit." },"color": {"type": "string", "description": "The color of the fruit." },"flavor": {"type": "string", "description": "The flavor of the fruit."}},"required": ["fruit", "color", "flavor"]}}},"required": ["fruits"]}}]response = openai.ChatCompletion.create(engine="gpt-35-turbo-0613",messages=messages,functions=functions,function_call={"name": "extract_fruit"}, # force the model to call the function)print(response['choices'][0]['message'])
响应
{"fruits": [{"fruit": "neoskizzles", "color": "purple", "flavor": "candy"},{"fruit": "loheckles", "color": "grayish blue", "flavor": "tart"},{"fruit": "pounits", "color": "bright green", "flavor": "savory"},{"fruit": "loopnovas", "color": "neon pink", "flavor": "cotton candy"},{"fruit": "glowls", "color": "pale orange", "flavor": "sour and bitter"}]}

像所有人工智能系统一样,使用函数调用将语言模型与其它工具和系统集成,会有一定的潜在风险。关键在于我们要了解函数调用可能带来的风险,并采取相关措施确保负责任地使用这些功能。
以下建议可以帮助用户安全、可靠地使用函数调用:
‣ 验证函数调用:始终验证模型生成的函数调用。包括检查参数、被调用的函数,并确保调用与预期的操作一致。
‣ 使用可信数据和工具:只使用来自可信和经过验证的数据源的数据。如果函数的输出中包含不可信数据,可能会导致模型按照不符合用户意图的方式编写函数调用。
‣ 遵循最小权限原则:只授予函数执行其工作所需的最低权限。这样可以降低函数被误用或利用时的潜在影响。例如,如果需要使用函数调用来查询数据库,用户应为应用程序授予数据库的只读访问权限。同时,不应仅依靠函数定义中的排除能力作为安全控制手段。
‣ 考虑实际影响:要意识到用户计划执行的函数调用的实际影响,特别是那些触发执行代码、更新数据库或发送通知等操作的函数调用。
‣ 实施用户确认步骤:特别是对于涉及执行动作的函数,建议在执行动作之前进行用户确认。
▲ 左滑了解更多函数调用相关信息









