AI 调教师:聊聊 TypeChat 以及ChatGPT 形式化输出

Untitled

Typescript 之父(微软)在 7月 21 号发布了一个有趣的项目—— Typechat。旨在使用 AI 来连接自然语言和应用的 Schema / API。说白话就是使用 Typescript 类型信息来约束 ChatGPT 输出内容的结构。

我们早已见证过 ChatGPT 的强大,如果想要对接到我们已有的软件系统,通常会要求它输出 JSON 这类形式化、结构化的数据。如果你调教过 ChatGPT 就会发现, 它的输出结果往往没那么靠谱。为了让它输出符合要求的内容,我们需要给出足够的上下文信息和示例,并且这个调教过程也比较玄学。

本文就来看看 Typechat 是如何让 ChatGPT 输出符合需求的内容

ChatGPT 的能力和缺陷

ChatGPT 看起来很擅长处理代码

扮演一个 linux 终端

扮演一个 linux 终端

扮演一个 Javascript 执行器

扮演一个 Javascript 执行器

扮演 Typescript

扮演 Typescript

这能说明 ChatGPT 的预训练集中包含了丰富的编程语言相关的内容。

连续对话和纠错机制

Untitled

众所周知, ChatGPT 生成的内容存在一定的随机性和不稳定性,很难一步到位。读者们作为开发者我们经常使用它来生成代码,应该能够体会到。

这个问题怎么解决呢?大概有以下几个方向

  • 可以和 ChatGPT 连续对话,引导它,反问它、纠正它
  • 给 ChatGPT 提供更详细的上下文信息
  • 使用一些对话的技巧:Chain of thought, 让 ChatGPT 学习推理的过程
  • 模型微调。

最后是平常心,开放地对待, AI 不是无所不能的,我们可能用尽的所有技巧, 也可能无法令人满意的答案。

DSL 输出

如果我们想要让 AI 连接到其他生态,比如连接到软件系统、控制硬件设备、实现各种自动化流程,在现在这个阶段,我们需要让 ChatGPT 输出结构化的数据,比如 JSON、XML、或者其他常见的 DSL。

Untitled

就像我们开头说的 “ Typechat 旨在使用 AI 来连接自然语言和应用的 Schema / API”, 结合上面的流程图理解,你应该就能体会到这句话的意思。AI 在这里就是一个连接者,让用户可以使用自然语言和我们的应用系统进行交互,AI 在这里的责任就是将自然语言翻译为我们应用系统能够处理的 DSL

ChatGPT 已经具备这样的能力:

绘制 mermaid 流程图

绘制 mermaid 流程图

输出 JSON

输出 JSON

如果你要求输出更复杂的数据结构,则需要使用 Few-shot Prompt 等手段,在受限的 Token 范围内,给 ChatGPT足够的案例和上下文信息。

除此之外,OpenAI 官方在 613 版本的 GPT 3.5 和 4 带来了函数调用的能力(Function Calling), 可以帮助开发者通过 API 方式实现类似于 ChatGPT 插件的数据交互能力。让开发者可以使用 JSON Schema 来描述你的函数接口,GPT 会根据用户的输入,决定调用哪个函数,并组装符合 Schema 要求的 JSON 数据。

以下是 OpenAI 的官方示例:


    1. 🔴 函数接口定义
    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"],
            },
        }
    ]

    1. 🔴 用户输入
    messages = [{"role": "user", "content": "What's the weather like in Boston?"}]
    1. 调用
    response = openai.ChatCompletion.create(
        model="gpt-3.5-turbo-0613",
        messages=messages,
        functions=functions,
        function_call="auto",  # auto is default, but we'll be explicit
    )

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

    1. 🔴 GPT 会告诉你最终需要调用哪个函数以及它的参数,也可能不会调用任何东西
    if response_message.get("function_call"):

gpt-3.5-turbo-0613、gpt-4-0613 针对 Function calling 这种场景做了微调,实际上这些 ‘函数’ 也是注入到 system prompt 里面,同样会占用请求的 Token。在旧的版本理论上也可以实现类似的效果。我会在后续的文章中专门介绍 Function calling。

实际上,Function Calling 还是不完美,比如无法保证严格按照我们给定的 JSON Schema 输出,不支持复杂的 JSON Schema,缺乏灵活性等等。现在我们开始介绍本文的主角 —— typechat