跳到主要内容
TypeChat

发布 TypeChat 0.1.0

2024 年 3 月 25 日,作者:Daniel Rosenwasser

今天我们发布了 TypeChat for TypeScript 和 JavaScript 的新版本。要获取它,您可以运行

npm install typechat

回顾一下,TypeChat 是一个实验性库,用于从 AI 语言模型获取结构化输出(如 JSON)。它的工作原理是使用程序中的类型来指导语言模型,然后使用这些相同的类型来确保响应与您的类型匹配。当它们不匹配时,TypeChat 可以使用验证错误来指导语言模型修复其响应。您可以阅读我们最初的发布博客文章以获取更多详细信息,但我们也应该能够在这里让您快速了解情况。

以下是 TypeChat for TypeScript 的一些新功能。

可插拔验证器

TypeChat 的原始版本实际上利用了 TypeScript 架构文件的原始内容。它看起来像这样

// Load up the contents of our "Response" schema.
const schema = fs.readFileSync(path.join(__dirname, "sentimentSchema.ts"), "utf8");
const translator = typechat.createJsonTranslator<SomeType>(model, schema, "SomeType");

// Process requests interactively.
typechat.processRequests("> ", /*inputFile*/ undefined, async (request) => {
    const response = await translator.translate(request);

    if (response.success) {
        console.log(`❌ ${response.message}`);
        return;
    }

    console.log("The request was translated into the following value:")
    console.log(response.data);
});

这有效,但存在一些问题

  1. 架构文件必须是自包含的。所有内容都必须在同一个文件中供 TypeChat 使用。

  2. 如果您未在原地运行,架构文件也必须存在。

    如果您没有使用 ts-node、tsx 或 tsimp 等工具,这通常意味着需要将架构文件复制到输出目录中。

  3. 架构是固定的。虽然可以即时生成文本架构,但这是一项容易出错的任务。

虽然使用文本 TypeScript 架构有很多符合人体工程学的优点,但我们探讨了是否可以增加一些灵活性,并对 TypeChat 进行了一些更改。

首先,我们将 `TypeChatJsonTranslator` 的一部分拆分成了更细粒度的概念:`TypeChatJsonValidator`。`TypeChatJsonValidator` 负责生成字符串架构表示以指导语言模型,并实际确保返回的数据与某种类型匹配。这意味着要构建 `TypeChatJsonTranslator`,您需要首先创建 `TypeChatJsonValidator`;但这也意味着验证器是可互换的。现在使用它看起来像这样

import fs from "fs";
import path from "path";

import { createLanguageModel, createJsonTranslator } from "typechat";
import { createTypeScriptJsonValidator } from "typechat/ts";

import { SentimentResponse } from "./sentimentSchema";

const model = createLanguageModel(process.env);
const schema = fs.readFileSync(path.join(__dirname, "sentimentSchema.ts"), "utf8");
const validator = createTypeScriptJsonValidator<SentimentResponse>(schema, "SentimentResponse");
const translator = createJsonTranslator(model, validator);

translator.translate("hello world!").then(response => {
    if (!response.success) {
        console.log(response.message);
        return;
    }
    console.log(`The sentiment is ${response.data.sentiment}`);
});

请注意,我们不是将架构传递给 `createJsonTranslator`,而是将其传递给 `createTypeScriptJsonValidator`,我们需要从 `typechat/ts` 导入它。然后需要将创建的验证器传递给 `createJsonTranslator`。

对于现有对 `createJsonTranslator` 的调用,您可能会看到类似以下消息

TS2554: 预期 2 个参数,但得到了 3 个。

您需要删除类型名称,并用验证器替换参数架构。这是有效的差异

  import { createJsonTranslator, createLanguageModel, processRequests } from "typechat";
+ import { createTypeScriptJsonValidator } from "typechat/ts";
  import { SentimentResponse } from "./sentimentSchema";

  // ...

- const translator = createJsonTranslator<SentimentResponse>(model, schema, "Sentiment")
+ const validator = createTypeScriptJsonValidator<SentimentResponse>(schema, "SentimentResponse");
+ const translator = createJsonTranslator(model, validator);

  // ...

Zod 验证器

第二个更改建立在可插拔验证器的基础上:TypeChat 使从 Zod 架构创建验证器成为可能。如果您不熟悉 Zod,它是一个在 TypeScript/JavaScript 生态系统中用于验证数据的流行库。该库的一个优点是,当 Zod 类型验证器对象被构建时,可以从中派生出静态类型。但对于 TypeChat 而言,其更显著的优点是能够动态构建架构。

要使用基于 Zod 的架构,我们首先需要创建一些 Zod 类型验证器对象,并创建一个定义我们打算使用的所有验证器的对象。

// sentimentSchema.ts

import { z } from "zod";

export const SentimentResponse = z.object({
    sentiment: z.enum(["negative", "neutral", "positive"])
        .describe("The sentiment of the text")
});

// Maps the property "SentimentResponse" to the above Zod validator.
export const SentimentSchema = {
    SentimentResponse
};

请注意,虽然 TypeScript 架构文件可以使用原始 JavaScript/TypeScript `// comment` 语法,但 TypeChat 会根据我们传递给 `.describe()` 调用的任何内容从 Zod 生成注释。

接下来,我们必须构建一个 TypeChat Zod 验证器。我们传入类型对象映射,并指定我们希望模型遵循的类型

// main.ts

import { createJsonTranslator, createLanguageModel } from "typechat";
import { createZodJsonValidator } from "typechat/zod";

import { SentimentSchema } from "./sentimentSchema";

const model = createLanguageModel(process.env);
const validator = createZodJsonValidator(SentimentSchema, "SentimentResponse");
const translator = createJsonTranslator(model, validator);

translator.translate("hello world!").then(response => {
    if (!response.success) {
        console.log(response.message);
        return;
    }
    console.log(`The sentiment is ${response.data.sentiment}`);
});

就是这样!

虽然使用 Zod 架构有很多优点,但您可能仍然喜欢编写纯 TypeScript 架构的人体工程学。两种选项都适用。

有关更多信息,请参阅 GitHub 上的更改

一个 `validateInstance` 钩子

TypeChat 的另一个新增功能是 `TypeChatJsonTranslator` 上的 `validateInstance` 钩子。它允许您在内部验证器执行的验证之外添加额外的验证级别。

import { createJsonTranslator, error, success } from "typechat";

// ...

const translator = createJsonTranslator(model, validator);
translator.validateInstance = summary => {
    for (const person of summary.people) {
        if (person.age < 0) {
            return error(
                `'{person.name}' has a negative age, that doesn't make sense.`
            )
        }
    }
    return success(summary)
}

如果 `validateInstance` 返回一个 TypeChat `Error`,那么翻译器将使用该消息来修复 AI 响应。

您可以在 GitHub 上查看此更改的具体细节

其他更改

需要注意的其他更改是

  • `TypeChatJsonProgram` 和相关函数,例如 `createModuleTextFromProgram`、`evaluateJsonProgram` 和 `createProgramTranslator` 都位于 `typechat/ts` 中(参阅 PR)。
  • 用于创建类似 REPL 提示的 `processRequests` 函数现在位于 `typechat/interactive` 中(参阅 PR)。

下一步是什么?

我们将根据收到的反馈努力改进 TypeChat。我们还在努力将 TypeChat 带到其他语言生态系统,如 Python 和 .NET,敬请关注近期发展。

试用 TypeChat,并在 GitHub 上告诉我们您的想法,您可以在那里提交问题或在我们的讨论论坛中发布主题!