AI工程化的“基座能力”?—— 聊聊GPT Function Calling

最近AI大模型火出了圈,很多人惊叹它的智能程度。但大多数人都以为它的能力主要在“聊天”、“写文案”这方面。然而实际它能做的远远更多。

Chat GPT是当今世界上最智能的模型,它前段时间推出了“插件”的概念,其实就是AI工程化的一个基础能力。配合AI的能力,可以通过自然语言来搜索、购物、预定等等,AI从此不止局限于聊聊天。只是“插件”只能构建和运行在官网上,无法在更大范围的场景落地。

于是很多人加入了探索基于AI构建工程化的思路,笔者本人也是其中之一。最近GPT又开放了一个叫Function Calling的新能力,这篇文章主要介绍工程化的整体思路和Function Calling的一些调研、测试。

AI工程基于JSON的思路

在Function Calling出现之前,一般是使用Prompt来让Chat GPT返回JSON内容供下游工程消费。核心的思路如图:

比如auto-gpt的prompt


You should only respond in JSON format as described below

RESPONSE FORMAT:
{
    "thoughts":
    {
        "text": "thought",
        "reasoning": "reasoning",
        "plan": "- short bulleted\
list that conveys\
long-term plan",
        "criticism": "constructive self-criticism",
        "speak": "thoughts summary to say to user"
    },
    "command": {
        "name": "command name",
        "args":{
            "arg name": "value"
        }
    }
}

Ensure the response can be parsed by Python json.loads

langchian的prompt:

response_schemas = [
    ResponseSchema(name="answer", description="answer to the user's question"),
    ResponseSchema(name="source", description="source used to answer the user's question, should be a website.")
]
output_parser = StructuredOutputParser.from_response_schemas(response_schemas)

format_instructions = output_parser.get_format_instructions()
prompt = PromptTemplate(
    template="answer the users question as best as possible.\n{format_instructions}\n{question}",
    input_variables=["question"],
    partial_variables={"format_instructions": format_instructions}
)

def get_format_instructions(self) -> str:
    schema_str = "\n".join(
        [_get_sub_string(schema) for schema in self.response_schemas]
    )
    return STRUCTURED_FORMAT_INSTRUCTIONS.format(format=schema_str)
    
def _get_sub_string(schema: ResponseSchema) -> str:
    return line_template.format(
        name=schema.name, description=schema.description, type="string"
    )
    
STRUCTURED_FORMAT_INSTRUCTIONS = """The output should be a markdown code snippet formatted in the following schema:

```json
{{
{format}
}}
```"""

然而,Chat GPT返回的JSON内容并不稳定,存在很多问题,需要工程化的思路去解决

典型的几个case:

  1. 返回的json有json以外的内容,如中文解释 + json输出
  2. 返回的json有注释(偶现),不是合法的json
  3. 返回的json格式不对(偶现),比如两个json,但不是json数组
  4. 返回的json内容不对
  5. 意图识别失败,无法返回我们需要的json,返回的是自然语言

Function Calling介绍

基本介绍

最近OPENAI推出了Function Calling的功能,

简单来讲,最新的模型(gpt-3.5-turbo-0613和gpt-4-0613)经过了官方的fine-tune优化,既能检测输入时何时应调用函数,又能以符合函数签名的方式响应JSON

这里有两个要点:

  1. 自动检测何时响应,如果参数没有解析出来,是可以通过上下文对话补全信息来响应的。

  2. 以符合函数签名的方式来响应JSON。代表了返回的响应是一种固定的格式,一定是合法的JSON。

能力和API要点总结

经过阅读一些材料,总结一下FunctionCalling的能力和API调用的要点:

  1. 可以一次定义多个function
  2. params是json schema的形式。json-schema.apifox.cn/
  3. 可以配合system prompt
  4. 可以理解上下文连续对话
  5. function_call参数说明:当设置为“none”时,模型不会调用任何函数,而是直接响应给最终用户。当设置为“auto”时,模型可以自行选择是向最终用户响应还是调用一个函数。通过指定一个具体的函数(如{“name”:”my_function”}),则强制模型调用该函数。当没有函数存在时,默认值为“none”。当存在函数时,默认值为“auto”。

Function Calling 测试

Case 1 基础测试:查询天气

入参:

出参:

Case 2 上下文

这里官方参考prompt:

Don’t make assumptions about what values to plug into functions. Ask for clarification if a user request is ambiguous.

推测必填参数:

description设置默认值:

prompt让gpt引导用户补充信息澄清:

上下文获取最终解析信息

Case 3 嵌套参数对象

根据官方的说法,parameters只要符合json schema规范就行,那我们可以用嵌套的形式来定义一个对象参数。

函数定义:

入参:

出参:

看起来很ok!

Case 4 返回IDL

官方是给DB表schema,返回sql的例子。这里我测试一下返回IDL的case。

入参:

输出:

解析一下,看起来也很ok:

局限性

1 准确率还是依赖模型本身

参数推理还是依赖模型本身的能力,有时候会推理错误。比如下图,就把“今天”推测到了location参数里面。

2 Prompt并不是完全有效,有时候会推测默认值

期望是让用户上下文沟通补全。但有时候chat gpt还是会自作主张,推测默认值:

3 function_call为none的时候不生效

按照官方文档的说法,function_call设置为none的时候应该不调用function,但实际测试下来不是这样的。这块有知道原因的朋友可以留言交流一下。

4 无法使用示例对话提升准确率

在之前我们使用Prompt + JSON输出的方式的时候,可以使用一些示例对话来增加AI输出的准确率,但现在改成了function calling的话,输出就不是assistant 的文本内容了,而是在单独的字段里面,所以few shot也就不那么好使了。

使用技巧

function_calling有其规定的出入参,如何和我们的代码更好地结合起来?

对于function定义,它是一个json schema定义,我们可以使用AI辅助我们来快速生成符合条件的json schema,类似这样:

另一方面,我们还可以使用反射等方式,来自动根据代码生成json schema,类似这样:

这种方式不能自动转换出description这个带有语义的内容。所以其实还是更推荐上面那种方式,产出后自己根据需要修改,然后存库,调用的时候json反序列化填充到api接口里。

同样的道理,我们也可以把Chat GPT的出参,利用反射来执行对应的方法调用:

function calling调研结论

1 更方便

因为产出一定是一个合法的json,不用自己处理很多异常情况,不用裁剪不要的自然语言。

2 更稳定

大多数时候比Prompt更稳定,尤其是在需要多轮上下文对话的时候,Prompt在多轮上下文之后准确率会明显降低,除非手动在最新的调用补充JSON定义。但function_calling是放在函数调用里面的,每次都会传入,所以整体上会更稳定。

可以说在大多数情况下,使用function calling来实现工程化的能力是一个最优的选择。它也降低了AI工程化的门槛,可以预料到在未来不远的一段时间内,基于AI构建的工程应用将迎来一个爆发期。

广告时间

这里给自己搭建的一个AI对话网站AiChatRoom(地址bot.aichatroom.cn)打个广告,可以国内直接使用Chat GPT,无需梯子,无需注册Chat GPT账号。支持的模型很多,包括最新的3.5-0613和3.5-16k,还支持GPT 4、AI绘画等。直接打开网站注册就能免费试用,感兴趣的朋友可以点进去看看~

© 版权声明
THE END
喜欢就支持一下吧
点赞0

Warning: mysqli_query(): (HY000/3): Error writing file '/tmp/MYIDI1vJ' (Errcode: 28 - No space left on device) in /www/wwwroot/583.cn/wp-includes/class-wpdb.php on line 2345
admin的头像-五八三
评论 抢沙发
头像
欢迎您留下宝贵的见解!
提交
头像

昵称

图形验证码
取消
昵称代码图片