What is typechat?
Typechat 是微软开放的用于让大语言模型输出符合类型定义的稳定结果的库,可以将用户的自然语言输入转换为结构化的数据用于业务应用.
Typechat的实现
以Typechat提供的coffeeShop案例说明,这一个咖啡馆点单的实现场景,当用户输入自然语言的时候,Typechat 将会根据提供的数据类型定义,返回对应的数据类。比如输入I want a mocha.(我想要一杯摩卡),Typechat将会返回以下结果数据,表示一杯摩卡的饮料菜单,结果以稳定的结构化数据呈现,所以逻辑可以对其进行很好的处理。
>>> I want a mocha. { "type": "Cart", "items": [ { "type": "LineItem", "product": { "type": "LatteDrink", "name": "mocha" }, "quantity": 1 } ] }
Typechat 的基本流程如下:
Typechat的实际实现逻辑,本质上还是通过prompt 来控制llm的输入和输出,从而达到返回指定结构数据效果,以下其Prompt提示词,提示词整体可以分为以下几部份:
- instruction:声明llm的能力和角色,并确定输入的数据协议以typescript的形式
- Schema:实际为typescript中数据接口的定义
- Output instruction:指定用户的原始输入,并指导llm 按照上述的数据协议返回JSON结果
python 风格的Typechat实现
Pydantic & json schema
pydantic 是一个用于数据解析和验证的Python库,可以很好的的进行数据模型的定义和数据类型检验,如以下使用pydantic 进行CoffeeDrink 的数据类定义,对于每个属性的描述和默认直可以通过pydantic Field 类进行定义。
class CoffeeDrink(BaseModel): type: Literal["CoffeeDrink"] = Field(default="CoffeeDrink", description="Specify the type of coffee drink") name: Literal["cappuccino", "flat white", "latte", "latte macchiato", "mocha", "chai latte"] = Field(None, description="Specify the name of the coffee drink") count: int = Field(1, description="Specify the selected drink quantity")
pydantic 提供了将数据类转换为jsonschema的方法,可以通过调用类函数
model_json_schema
进行生成,CoffeeDrink 的jsonschema 结果如下;>>> CoffeeDrink.model_json_schema() { "properties": { "type": { "const": "CoffeeDrink", "default": "CoffeeDrink", "description": "Specify the type of coffee drink", "enum": [ "CoffeeDrink" ], "title": "Type", "type": "string" }, "name": { "default": null, "description": "Specify the name of the coffee drink", "enum": [ "cappuccino", "flat white", "latte", "latte macchiato", "mocha", "chai latte" ], "title": "Name", "type": "string" }, "count": { "default": 1, "description": "Specify the selected drink quantity", "title": "Count", "type": "integer" } }, "title": "CoffeeDrink", "type": "object" }
jsonshema 可以以json格式很好的对数据类进行结构化的描述,同样的,对于GPT等模型,也能够很好的理解jsonshema 关于数据类的定义。
数据转换
整体数据转换的流程还是与原生Typechat的转换流程类似,只是将起TypeScript的接口定义数据类更改为使用json schema。
当输入以上提示词之后,结果一般是包含JSON的回复,可以通过
{
和 }
作为起始和结尾符号进行提取。
提取后的json结果,可以使用pydantic 的
model_validate
函数将其转换为数据类。但有时候也存在数据类校验失败和json格式错误的情况,可以回复openai ,让起进行修正,如下提示词,其中{error_message}
为错误信息。The JSON program object is invalid for the following reason: ''' {error_message} ''' The following is a revised JSON program object:
函数调用
类似于openai的jsonschema 的tool call 函数调用方法,可以通过Typechat的方式来实现函数调用,如下CoffeeDrink类中添加一个
add_sugar
方法来给顾客添加糖。class CoffeeDrink(BaseModel): type: Literal["CoffeeDrink"] = Field(default="CoffeeDrink", description="Specify the type of coffee drink") name: Literal["cappuccino", "flat white", "latte", "latte macchiato", "mocha", "chai latte"] = Field(None, description="Specify the name of the coffee drink") count: int = Field(1, description="Specify the selected drink quantity") def add_sugar(self, customer: Customer): """ add some sugar to coffee Returns: """ return "add sugar success"
比如输入
Add a little sugar to Tom's coffee
表示给Tom
的咖啡中添加一点糖,其中生成的函数调用提示词如下:其中function call 的json schema 生成自以下数据类:
class FunctionCall(BaseModel): name: str = Field(description="Specify the function name to be called") arguments: str = Field(default={},description="Specifies the parameters of the function call, JSON characters converted from a dictionary of type python") class ToolCall(BaseModel): type: Literal["function"] = "function" functions: List[FunctionCall] = Field(default=[],description="Specify function call object, If you need multiple functions, please sort them in order.")
输入封装好的提示词之后,gpt会按照ToolCall 数据定义来返回数据结构,本地根据函数名称,找到对应的函数,并输入参数执行;
执行后的结果,可以返回给openai 或者自己处理,以下为openai的返回结果.
User> [ExecResult(func='add_sugar', result='add sugar success', status='success')] ``` exec status: success result: add sugar success ``` Aisistant> The sugar has been successfully added to Tom's coffee.
总结
Typechat 提供了一个很好的控制llm输出的方法,减少了结果的不确定性,并能稳定提供结构化的结果,可以很好的优化llm应用的稳定性的问题;关于以上代码的实现,已经上传到GitHub仓库中了 typingchat 。
Thanks for seeing this