作者|冬梅、核子可乐
TypeScript 之父也玩大模型,新项目开启大模型对话新方式。
过去几个月来,人们对于最新一波大语言模型的巨大热情已经席卷世界。但对于聊天助手这种最直接的应用场景来说,如何将这些模型有效集成至现有应用界面当中仍是个棘手难题。
换句话说,我们该如何用自然语言界面增强传统 UI?如何使用 AI 接收用户请求,并将其转化为应用程序能够运行的内容?我们又该怎样保障自己的应用安全可靠,证明工作成果值得开发者和用户信赖?
为了解决上述难题,C# 和 TypeScript 首席开发人员、微软技术研究员 Anders Hejlsberg 组成的团队于 7 月 20 日发布了 TypeChat,这是一款可以轻松使用类型构建自然语言界面的实验性工具库。它使用代码库中的类型定义来检索类型安全的结构化 AI 响应。
TypeChat 一推出后,立即在开发者群中引来对诸多关注。开发者们在 Twitter 和 Hack News 平台上进行了激烈讨论,有人看好,有人唱衰。
在 Hack News 上,一位名叫的 verdverm 开发者认为:“以我的经验来看,根据模式实现灵活的结构化输出,提示词的质量看起来不那么好,还有其他值得怀疑的决策。而且有价值地利用工程时间的确要评估候选抽象对象,并且考虑长期采用他们的成本。在这种情况下,TypeChat 似乎没有那么节省精力,这意味着很多大模型的旋钮是无法控制的,权衡之下这不是一个好的方案”。
当然,也有不少开发者看好 TypeChat。有网友认为大语言模型仅从人类已经做过的事情中学习,而且编程语言是严苛的,具备可“纠错性”,可以让 ChatGPT 输出更加稳定。如果由具有适当软件知识的人来提示,那么我们将获得漂亮且易于理解的代码。TypeChat 就是利用了这一点。“其他编程语言也可以轻松实现类似的效果,相信很快其他语言应该也会有类似的库出来。”
另一位名叫 paxys 的开发者也高度看好 Anders Hejlsberg 的想法。他称:“结构化请求和 100% 响应是大模型的下一步发展方向。人们已经厌倦了聊天机器人。能够插入任何后端而不用担心文本解析和提示将是令人兴奋的。”
尽管开发者们 TypeChat 褒贬不一,但不得不承认的是,现阶段 TypeChat 的价值在于将非结构化数据转化为结构化数据并确保其满足模式约束。
项目地址:https://github.com/microsoft/TypeChat
TypeChat 能干什么?
构建自然语言界面传统上一直很困难。这些应用程序通常依赖复杂的决策树来确定意图并收集采取行动所需的输入。大型语言模型 (LLM) 使我们能够从用户那里获取自然语言输入并匹配意图,从而使这一切变得更加容易。这带来了其自身的挑战,包括需要限制模型的回复以确保安全、构建模型的响应以进行进一步处理,以及确保模型的回复有效。提示工程旨在解决这些问题,但随着提示尺寸的增加,学习曲线会变得陡峭,并且脆弱性也会增加。
TypeChat 很重要的一个工作就是用模式工程取代了提示工程。
只需定义代表自然语言应用程序支持的意图的类型。这可以是简单的情感分类界面,也可以是更复杂的示例,例如购物车或音乐应用程序的类型。例如,要向架构添加其他意图,开发人员可以向可区分联合添加其他类型。为了使模式分层,开发人员可以使用“元模式”根据用户输入选择一个或多个子模式。
定义类型后,TypeChat 将通过以下方式处理其余部分:
- 使用类型构建 LLM 提示。
- 验证 LLM 响应是否符合架构。如果验证失败,则通过进一步的语言模型交互修复不合格的输出。
- 简洁地总结实例并确认其与用户意图一致。
从现在起,用户可以运行以下命令来启动并运行 TypeChat:
代码语言:javascript复制npm install typechat
并将其与任意语言模型对接起来,并与应用配合使用。
提示词设计与解析
当前这波大语言模型浪潮已经基本掌握了人类语言的奥秘,比如世界通行的英语。以往,解析自然语言是项极其困难的任务。无论如何用“以项目符号列表的形式响应”等规则设计提示词,效果往往都不尽如人意。尽管自然语言其实拥有自己的结构,但传统软件却很难根据原始文本重建起这样的体系。
但令人惊喜的是,在要求大语言模型以 JSON 形式做出回复时,它们却往往能给出相当合理的答案。
用户:
将以下请求转换为 JSON。
我能要一份蓝莓松饼加一杯大杯拿铁咖啡吗?
仅以 JSON 格式响应,如下所示:
代码语言:javascript复制{
"items": [
{ "name": "croissant", "quantity": 2 },
{ "name": "latte", "quantity": 1, "size": "tall" }
]
}
聊天机器人:
代码语言:javascript复制{
"items": [
{
"name": "blueberry muffin",
"quantity": 1
},
{
"name": "latte",
"quantity": 1,
"size": "grande"
}
]
}
由此可见,效果还是不错的,虽然这个示例有点太理想,但仍然证明大语言模型确实有助于启发语言结构。接下来的问题是,这里既没有定义 AI 应该普遍返回的内容,也没有提供可以验证的结果。那该怎么办?
答案是,添加类型即可。
幸运的是,类型能够解决这些麻烦。研究人员发现,由于大语言模型在应用场景中已经接触过大量类型定义,因此可以将类型作为 AI 响应的重要指引。考虑到用户非常熟悉且经常会用到 JSON(JavaScript 对象表示),所以这里尝试在提示词中直接使用 TypeScript 类型:
用户:
将以下请求转换为 JSON。
我能要一份蓝莓松饼加一杯大杯拿铁咖啡吗?
以能够满足 Response 类型的 JSON 进行响应:
代码语言:javascript复制type Response = {
items: Item[];
};
type Item = {
name: string;
quantity: number;
size?: string;
notes?: string;
}
聊天机器人:
代码语言:javascript复制{
"items": [
{
"name": "blueberry muffin",
"quantity": 1
},
{
"name": "latte",
"quantity": 1,
"size": "grande"
}
]
}
这真是太棒了。TypeScript 明显特别适合精确描述 JSON。但问题是,如果语言模型出错并做出不符合类型的响应,又会发生怎样的状况?
因为这些类型都是有效的 TypeScript 代码,所以我们可以使用 TypeScript 编译器本体对响应结果做验证!实际上,编译器给出的错误反馈甚至可以用来指导修正。在整合起来之后,我们就能获得一个强大的类型正确响应获取流程,以供应用进一步处理、用户加以验证。
换句话说,类型就是解决问题的突破口。
初识 TypeChat
这种将人类提示词跟“响应模式”相结合的技术虽不敢说独一无二,但仍具有巨大的潜力空间。在尝试将用户意图转换为结构化数据的过程中,研究人员发现 TypeScript 非常适合这项任务。
因此他们对这种方法的越来越有信心,为了证明这一点,研发团队决定发布 TypeChat 库,帮助大家轻松在应用程序中使用这种方法。如果各位想要立即尝试,TypeChat 目前已经登陆 npm,为您提供用于快速原型设计、模式验证和修复的工具。
以下基本代码可将 TypeChat 接入大语言模型,进而确定句子为否定、中性还是肯定。
代码语言:javascript复制// ./src/sentimentSchema.ts
// The following is a schema definition for determining the sentiment of a some user input.
export interface SentimentResponse {
/** The sentiment of the text. */
sentiment: "negative" | "neutral" | "positive";
}
// ./src/main.ts
import * as fs from "fs";
import * as path from "path";
import dotenv from "dotenv";
import * as typechat from "typechat";
import { SentimentResponse } from "./sentimentSchema";
// Load environment variables.
dotenv.config({ path: path.join(__dirname, "../.env") });
// Create a language model based on the environment variables.
const model = typechat.createLanguageModel(process.env);
// Load up the contents of our "Response" schema.
const schema = fs.readFileSync(path.join(__dirname, "sentimentSchema.ts"), "utf8");
const translator = typechat.createJsonTranslator<SentimentResponse>(model, schema, "SentimentResponse");
// Process requests interactively.
typechat.processRequests("