TypeChat 用一句话概括,就是用了它你可以让大语言模型(比如 ChatGPT)将自然语言转换成特定类型的 JSON 数据。
我们在使用 ChatGPT 的时候,大致流程如下:
假如我们需要 ChatGPT 按照我们输入的 prompt,输出指定格式的 JSON 数据,我们在 prompt 里将我们的要求描述清楚就行,比如
好像没什么问题,很听话。
我们再看一个例子
{ "filters": [ { "component": "select", "key": "店铺名称", "label": "店铺名称", "placeholder": "请输入" }, { "component": "select", "key": "店铺编码", "label": "店铺编码", "placeholder": "请输入" }, { "component": "select", "key": "店铺门头编码", "label": "店铺门头编码", "placeholder": "请输入" }, { "component": "select", "key": "所在区域", "label": "所在区域", "placeholder": "全部" } ], "columns": [ { "slot": false, "title": "店铺编码", "dataIndex": "店铺编码", "key": "店铺编码" }, { "slot": false, "title": "店铺名称", "dataIndex": "店铺名称", "key": "店铺名称" }, { "slot": false, "title": "店铺业务范围", "dataIndex": "店铺业务范围", "key": "店铺业务范围" }, { "slot": false, "title": "店铺类型", "dataIndex": "店铺类型", "key": "店铺类型" }, { "slot": false, "title": "所在区域", "dataIndex": "所在区域", "key": "所在区域" }, { "slot": false, "title": "详细地址", "dataIndex": "详细地址", "key": "详细地址" } ], "pagination": { "show": true, "page": "page", "size": "size", "total": "result.total" }, "includeModifyModal": false, "fetchName": "fetchTableList", "result": "[\"result\"][\"records\"]", "serviceName": "getTableList" }
我们需要 ChatGPT 把上面 JSON 数据中 filters 字段中的 key 字段的值翻译为英文,使用驼峰语法。columns 字段中的 key、dataIndex 字段的值翻译为英文,使用驼峰语法。
我们的 prompt 可以这么写:
{ "filters": [ { "component": "select", "key": "店铺名称", "label": "店铺名称", "placeholder": "请输入" }, { "component": "select", "key": "店铺编码", "label": "店铺编码", "placeholder": "请输入" }, { "component": "select", "key": "店铺门头编码", "label": "店铺门头编码", "placeholder": "请输入" }, { "component": "select", "key": "所在区域", "label": "所在区域", "placeholder": "全部" } ], "columns": [ { "slot": false, "title": "店铺编码", "dataIndex": "店铺编码", "key": "店铺编码" }, { "slot": false, "title": "店铺名称", "dataIndex": "店铺名称", "key": "店铺名称" }, { "slot": false, "title": "店铺业务范围", "dataIndex": "店铺业务范围", "key": "店铺业务范围" }, { "slot": false, "title": "店铺类型", "dataIndex": "店铺类型", "key": "店铺类型" }, { "slot": false, "title": "所在区域", "dataIndex": "所在区域", "key": "所在区域" }, { "slot": false, "title": "详细地址", "dataIndex": "详细地址", "key": "详细地址" } ], "pagination": { "show": true, "page": "page", "size": "size", "total": "result.total" }, "includeModifyModal": false, "fetchName": "fetchTableList", "result": "[\"result\"][\"records\"]", "serviceName": "getTableList" } 将这段 json 中,filters 字段中的 key 字段的值翻译为英文,使用驼峰语法,label、placeholder 字段的值保留中文。 columns 字段中的 key、dataIndex 字段的值翻译为英文,使用驼峰语法,title 字段的值保留中文。 返回翻译后的 markdown 语法的代码块
最后面的那段话已经经过了几次修改,我们看下 ChatGPT 返回的内容:
{ "filters": [ { "component": "select", "storeName": "店铺名称", "label": "店铺名称", "placeholder": "请输入" }, { "component": "select", "storeCode": "店铺编码", "label": "店铺编码", "placeholder": "请输入" }, { "component": "select", "storeDoorCode": "店铺门头编码", "label": "店铺门头编码", "placeholder": "请输入" }, { "component": "select", "area": "所在区域", "label": "所在区域", "placeholder": "全部" } ], "columns": [ { "slot": false, "title": "店铺编码", "storeCode": "店铺编码", "key": "storeCode" }, { "slot": false, "title": "店铺名称", "storeName": "店铺名称", "key": "storeName" }, { "slot": false, "title": "店铺业务范围", "storeBusinessScope": "店铺业务范围", "key": "storeBusinessScope" }, { "slot": false, "title": "店铺类型", "storeType": "店铺类型", "key": "storeType" }, { "slot": false, "title": "所在区域", "area": "所在区域", "key": "area" }, { "slot": false, "title": "详细地址", "detailedAddress": "详细地址", "key": "detailedAddress" } ], "pagination": { "show": true, "page": "page", "size": "size", "total": "result.total" }, "includeModifyModal": false, "fetchName": "fetchTableList", "result": "[\"result\"][\"records\"]", "serviceName": "getTableList" }
filters 里的 key 字段哪去了?columns 里 dataIndex 字段哪去了?
这只是我遇到的各种情况里的一种,当然也有成功的,反正就是很玄学,可能是我半年 prompt 练习生的水平不够吧。
如果我们用 TypeChat 会怎么样呢?
直接看效果 :
完美。
TypeChat 的大致原理如下:
其实就是在 prompt 拼上了一个 TS 类型,要求 ChatGPT 按照 TS 类型声明输出 JSON。背后还会构建一个 TS 程序去进行校验,如果校验失败就把错误信息也加到 prompt 里,让 ChatGPT 再处理一次。
上面生成的 prompt 跟 TypeChat 生成的有些区别,我并没有直接使用 TypeChat,为了方便在我的项目里使用就抄了一份进行修改,在生成 prompt 的里加上了 “按照字段的注释进行处理” 这一要求。修改后的代码: https://github.com/lowcode-scaffold/lowcode-materials/blob/master/share/TypeChatSlim/index.ts
在 TS 类型的字段注释里还可以加入更离谱的东西来要求 ChatGPT 去处理,比如之前弄的一个根据聊天记录生成日程安排的小 demo,在字段注释里加上当前时间,让 ChatGPT 根据会话内容推算出具体的日期。TS 类型定义如下:
const res = await translate({ schema: `export type SchedulType = { /** * 时间,格式:YYYY-MM-DD HH:mm:ss,当前时间为 ${new Date().toLocaleString()},请推算出正确的时间 */ time: string; /** * 活动主题 */ todo: string; /** * 地点 */ addr: string; /** * 活动的全体参与人 */ participant: string[]; };`, typeName: 'SchedulType', request: `根据下面的聊天记录,生成日程安排:${message.data}`, createChatCompletion: createChatCompletionForScript, showWebview: true, });
聊天记录中只说到了周六下午两点,ChatGPT 根据字段注释里的当前时间正确推算出了日程的具体日期。
受到 TypeChat 的启发,借助 JSON Schema 实现了一个 JSONSchemaChat,原理差不多,效果如下: