一、问题
我们希望LLM的回答的结果具有格式,最好是JSON格式(Python字典), 这样有利于后续的调用。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
#普通格式 姓名 张三 年龄 34 兴趣 打篮球、踢足球、游泳、打游戏 #JSON格式 { "name": "张三", "age": 34, "hobby": [ "打篮球", "踢足球", "游泳", "打游戏" ] } |
如何从 「普通格式」转为 结构化的「JSON格式」?这里就用到 Instructor库 。
二、Instructor介绍
Instructor 是一个 Python 库,它使处理大型语言模型 (LLM) 的结构化输出变得轻而易举。它建立在 Pydantic 之上,提供了一个简单、透明且用户友好的 API 来管理验证、重试和流式响应。
2.1 Instructor的主要特征
- 定义输出样式:指定 Pydantic 模型来定义 LLM 输出的结构
- 失败重试管理:轻松配置请求失败的重试次数
- 样式验证:使用 Pydantic 验证确保 LLM 响应符合您的期望
- 灵活的后端:与 OpenAI 之外的各种 LLM 提供商无缝集成
2.2 安装
1 |
pip install instructor |
2.3 样例
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
import instructor from pydantic import BaseModel from openai import OpenAI # Define your desired output structure class UserInfo(BaseModel): name: str age: int # Patch the OpenAI client client = instructor.from_openai(OpenAI()) # Extract structured data from natural language user_info = client.chat.completions.create( model="gpt-3.5-turbo", response_model=UserInfo, messages=[{"role": "user", "content": "John Doe is 30 years old."}], ) print(user_info.name) #> John Doe print(user_info.age) #> 30 |
注意,本部分的样例仅供观看,因为chatGPT 限制中国大陆用户使用,所以不论是你还是大邓,运行此代码会失败。但文章末尾会提供本地电脑可运行的实验代码。
三、结构化输出实验
3.1 环境配置
假设已在本地安装Ollama软件, 也使用ollama安装了相应的大语言模型(如qwen2:7b、llama3.1:8b等)。 如果之前没有进行这些操作, 请阅读 教程 | 如何使用 Ollama 下载 & 使用本地大语言模型
3.2 代码
只要完成2.2、3.1,本章节的代码是可以运行出结果的。 不做过多解释,直接上代码,大家看运行结果。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 |
from openai import OpenAI from pydantic import BaseModel from typing import List import os import instructor #结构化输出 class UserDetail(BaseModel): name: str age: int hobby: List[str] #Prompt提示 PROMPT_TEXT = "根据自我介绍文本内容,从中提取出姓名、年龄、兴趣" #实验数据 introduction_text = '我是张三,今年34岁, 来自黑龙江省, 我的兴趣爱好有打篮球、踢足球、游泳、打游戏。' client = instructor.from_openai( OpenAI( base_url="http://localhost:11434/v1", api_key="NA", # required, but unused ), mode = instructor.Mode.JSON, ) resp = client.chat.completions.create( model = "qwen2:7b", messages=[ {"role": "system", "content": PROMPT_TEXT}, {"role": "user", "content": introduction_text} ], response_model = UserDetail, max_retries = 3 ) print(resp.model_dump_json(indent=2)) |
Run
1 2 3 4 5 6 7 8 9 10 |
{ "name": "张三", "age": 34, "hobby": [ "打篮球", "踢足球", "游泳", "打游戏" ] } |
resp的数据类型为UserDetail, 是代码中是我们定义的 UserDetail 类。该类具有一些方法,也可直接 resp.dict() 转化为dict
查看 resp 的数据类型
1 2 |
print(resp.dict()) print(type(resp.dict())) |
Run
1 2 |
{'name': '张三', 'age': 34, 'hobby': ['打篮球', '踢足球', '游泳', '打游戏']} <class 'dict'> |