一、问题

我们希望LLM的回答的结果具有格式,最好是JSON格式(Python字典), 这样有利于后续的调用。

#普通格式
姓名 张三
年龄 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 安装

pip install instructor

2.3 样例

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,本章节的代码是可以运行出结果的。 不做过多解释,直接上代码,大家看运行结果。

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

{
  "name": "张三",
  "age": 34,
  "hobby": [
    "打篮球",
    "踢足球",
    "游泳",
    "打游戏"
  ]
}

resp的数据类型为UserDetail, 是代码中是我们定义的 UserDetail 类。该类具有一些方法,也可直接 resp.dict() 转化为dict


查看 resp 的数据类型

print(resp.dict())
print(type(resp.dict()))

Run

{'name': '张三', 'age': 34, 'hobby': ['打篮球', '踢足球', '游泳', '打游戏']}
<class 'dict'>


精选内容