TypeChat

GitHub官网介绍:TypeChat is a library that makes it easy to build natural language interfaces using types.

GitHub官网:GitHub - microsoft/TypeChat: TypeChat is a library that makes it easy to build natural language interfaces using types.

写在前面

先聊点其他的吧。我们之前确实有类似的需求:从一段文字中抽取特定字段(属性)的信息,组成一个JSON对象。举个例子吧:

从下方<content>内的文本中提取出以下信息: 姓名,性别,年龄,地址 。
结果输出JSON结构,无法提取的内容,使用null来表示。
<content>
大家好,我是来自河北省唐山市的张三,大家都能看出来是吧,我是个男的,今年18岁了,非常喜欢听音乐,爱打乒乓球、羽毛球等,谢谢大家
</content>
            

上面的内容是我们弄的提示词,也修改过好几版,这里就不一一列举了。我们希望得到的回答如下(至少得包含):

{
    "name": "张三",
    "gender": "男",
    "age": 18,
    "address": "河北省唐山市"
}
//  或者
{
    "姓名": "张三",
    "性别": "男",
    "年龄": 18,
    "地址": "河北省唐山市"
}
            

FastChat + ChatGLM3-6B 的返回结果

针对这里的测试,ChatGLM3-6B的回答还可以,除了地址没有找出来(也可能是描述的问题)。不过这仅仅是简单的例子,实际内容要复杂的多,测试了ChatGLM3-2BChatGLM3-6BBaichuan2-7B-ChatQwen-7B-Chat这些模型,提示词模板也换了不少,效果不是很理想,回答不是很稳定,直到后来用了Qwen-72B-Chat才稳定一点。

OPENAI_API

TypeChat在这里正式开始,首先上场的是API。

OPENAI_API_KEY咱是没有啊!这里采用FastChat+ChatGLM3-6B来兼容OPENAI_API,具体怎么操作你可以查看:FastChat - xiaodu114.github.io

如何使用

有两种使用方式:一是 GitHub 下载源码,自己编译;二是作为类库,直接使用npm安装

源码方式

下载并编译

下载源码有个好处就是其中包含了几个示例,这里项目的位置如下:

TypeChat 项目目录

TypeChat 项目编译之前

在项目的typescript目录打开终端,并执行npm install命令,没想到示例项目也直接编译了

TypeChat 项目编译之后

创建 .env文件

这里配置OPENAI相关的一些环境变量,内容如下:

OPENAI_MODEL=chatglm3-6b
OPENAI_API_KEY=null
OPENAI_ENDPOINT=http://IP:Port/v1/chat/completions
            

运行示例项目 coffeeShop

将上面的.env文件拷贝到typescript\examples\coffeeShop下,并在此处处打开终端,你可以尝试下面的命令:

#   这里需要你手动输入“提示词”
node ./dist/main.js

#   这里会遍历 input.txt 文件中的问题
node ./dist/main.js ./dist/input.txt
            

TypeChat 项目编译之后,node ./dist/main.js ./dist/input.txt 输出结果

注意:这里开始测试的时候会提示一些JSON的问题,所以打印了一下API的返回结果。

类库方式

在自己写示例之前,看了一下上面示例项目 coffeeShop 的源码,大概了解了一下实现过程,如下:

TypeChat 项目中 coffeeShop 示例项目

这种方式使用起来就比较熟悉了,创建一个前端项目,直接npm install typechat就行了。示例代码如下:

import { createJsonTranslator, createLanguageModel } from "typechat";

const model = createLanguageModel({
    OPENAI_MODEL: "chatglm3-6b",
    OPENAI_API_KEY: "null",
    OPENAI_ENDPOINT: "http://IP地址:端口/v1/chat/completions"
});

const translator = createJsonTranslator(
    model,
    `
    interface Student {
        姓名: string | null;
        性别: string | null;
        年龄: number | null;
        地址: string | null;
    }
    `,
    "Student"
);
let prompt = translator.createRequestPrompt("大家好,我是来自河北省唐山市的张三,大家都能看出来是吧,我是个男的,今年18岁了,非常喜欢听音乐,爱打乒乓球、羽毛球等,谢谢大家");
console.log("--------------------------------------------------------- 提示词:");
console.log(prompt);
const response = await model.complete(prompt);
console.log("--------------------------------------------------------- 返回结果:");
console.log(response);
            

TypeChat 测试项目,输出结果截图

感觉这里最重要的就是translator.createRequestPrompt这个方法了,或者换个说法:我们想要的。这里也找了一下他是如何组装prompt的,如下:

//  下方的代码位置:typescript\src\typechat.ts
function createRequestPrompt(request: string) {
    return `You are a service that translates user requests into JSON objects of type "${validator.getTypeName()}" according to the following TypeScript definitions:\n` +
    `\`\`\`\n${validator.getSchemaText()}\`\`\`\n` + 
    `The following is a user request:\n` + 
    `"""\n${request}\n"""\n` + 
`The following is the user request translated into a JSON object with 2 spaces of indentation and no properties with the value undefined:\n`;
}
            

后面在慢慢看看项目的其他内容