一文讀懂LLM基于JSON Schema的結構化輸出
什么是基于JSON Schema的結構化輸出
大語言模型通常會生成無特定結構的自由格式文本,在能夠有效使用之前需要進行大量的后期處理。這種不可預測性會導致錯誤、浪費時間并增加成本。
OpenAI推出基于JSON Schema的結構化輸出以解決這一問題。結構化輸出確保模型響應遵循嚴格的格式,減少錯誤,并使將大語言模型集成到需要一致的、機器可讀數據的應用程序中變得更加容易,對于一致性和準確性至關重要的任務其輸出更為可靠。
通常情況下,大語言模型基于概率預測逐個生成文本標記。不過,如果需要以特定格式生成文本,這種方法就不太適用了。結構化輸出通過預定義的規則或模式來引導這一過程,使每個標記都符合所需的結構。
如何使用基于JSON Schema的結構化輸出
并非所有的模型都支持基于JSON Schema的結構化輸出。經測試,文心一言支持結構化輸出。通義千問、豆包、deepseek還不支持。
下面以輸出方程求解過程的結構化輸出為例,闡述OpenAI Python SDK使用結構化輸出的兩種方法。
先準備好開發環境,以windows開發環境為例:
設置Python開發環境
安裝uv。uv是一個用Rust編寫的極其快速的Python包和項目管理器。
powershell -ExecutionPolicy ByPass -c "irm https://astral.sh/uv/install.ps1 | iex"
創建python虛擬環境(假設項目目錄為structured-output)
# Create a new directory for our project
uv init structured-output
cd structured-output
# Create virtual environment and activate it
uv venv
.venv\Scripts\activate
# Install dependencies
uv add openai python-dotenv
設置環境變量
創建.env,.env內容如下(注意修改OPENAI_API_KEY為您的key)
OPENAI_API_KEY=your_api_key_here
OPENAI_BASE_URL=https://qianfan.baidubce.com/v2
MODEL_NAME=ernie-3.5-128k
把.env添加到.gitignore
結構化輸出方法1:手工定義Schema
通過設置chat completion的response_format打開結構化輸出。response_format的格式為:
{
type: "json_schema",
json_schema: {
"strict": true,
"schema": ...
}
}
完整例子如下:
import os
from openai import OpenAI
from dotenv import load_dotenv
load_dotenv() # load environment variables from .env
client = OpenAI()
chat_completion = client.chat.completions.create(
messages=[
{
"role": "system",
"content": "你是一位數學老師。一步步引導用戶完成解題過程"
},
{
"role": "user",
"content": "我該如何解7x + 6 = 41這個方程"
}
],
model=os.getenv("MODEL_NAME"),
response_format={
"type": "json_schema",
"json_schema": {
"name": "math_response",
"schema": {
"type": "object",
"properties": {
"steps": {
"type": "array",
"items": {
"type": "object",
"properties": {
"explanation": {"type": "string"},
"output": {"type": "string"}
},
"required": ["explanation", "output"],
"additionalProperties": False
}
},
"final_answer": {"type": "string"}
},
"required": ["steps", "final_answer"],
"additionalProperties": False
},
"strict": True
}
},
)
content = chat_completion.choices[0].message.content
print(content)
輸出結果如下:
{
"final_answer":"x = 5",
"steps":[
{
"explanation":"首先,我們需要將方程中的常數項移至等式的另一邊,使方程左側只剩下未知數x的系數和x本身。",
"output":"7x = 41 - 6"
},
{
"explanation":"進行減法運算,簡化方程。",
"output":"7x = 35"
},
{
"explanation":"接下來,我們需要將x的系數化為1,以求解x的值。為此,我們將方程兩邊同時除以7。",
"output":"x = 35 ÷ 7"
},
{
"explanation":"進行除法運算,得出x的值。",
"output":"x = 5"
}
]
}
結構化輸出方法2:使用自定義的pydantic模型
通過設置chat completion的response_format為自定義的pydantic
模型MathReasoning
完整例子如下:
import os
from openai import OpenAI
from dotenv import load_dotenv
from pydantic import BaseModel
class Step(BaseModel):
explanation: str
output: str
class MathReasoning(BaseModel):
steps: list[Step]
final_answer: str
load_dotenv() # load environment variables from .env
client = OpenAI()
chat_completion = client.beta.chat.completions.parse(
messages=[
{
"role": "system",
"content": "你是一位樂于助人的數學老師。一步步引導用戶完成解題過程"
},
{
"role": "user",
"content": "我該如何解7x + 6 = 41這個方程"
}
],
model=os.getenv("MODEL_NAME"),
response_format=MathReasoning,
)
math_reasoning = chat_completion.choices[0].message.parsed
print(math_reasoning.model_dump_json(indent=4))
輸出結果為:
{
"steps":[
{
"explanation":"首先,我們需要將方程中的常數項移至等式的另一邊。從7x + 6 = 41開始,我們可以從兩邊同時減去6。",
"output":"7x + 6 - 6 = 41 - 6"
},
{
"explanation":"簡化上一步的等式,得到7x = 35。",
"output":"7x = 35"
},
{
"explanation":"接下來,我們需要解出x的值。為此,我們可以將方程兩邊同時除以7。",
"output":"7x / 7 = 35 / 7"
},
{
"explanation":"簡化上一步的等式,得到x = 5。",
"output":"x = 5"
}
],
"final_answer":"x = 5"
}
JSON Schema結構化輸出 VS JSON模式
JSON Schema結構化輸出是JSON模式的進階版本。JSON模式是通過設置response_format為{ "type": "json_object" }
打開。使用JSON模式時,你必須始終通過對話中的某些消息(例如系統消息)指示模型生成JSON。JSON 模式不能保證輸出符合任何特定的模式。
總結
JSON Schema結構化輸出提供了一個強大的解決方案,可確保您的大語言模型生成可靠、可預測且機器可讀的回復。結構化輸出有助于您在不同應用程序中保持一致的數據格式,從而更輕松地管理復雜的工作流程。