一文读懂LLM基于JSON Schema的结构化输出

一文读懂LLM基于JSON Schema结构化输出
该文章已生成可运行项目,

OpenAI推出基于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"
  • 1.

创建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
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
设置环境变量

创建.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
  • 1.
  • 2.
  • 3.

把.env添加到.gitignore

结构化输出方法1:手工定义Schema

通过设置chat completion的response_format打开结构化输出。response_format的格式为:

复制

{
    type: "json_schema", 
    json_schema: {
        "strict": true, 
        "schema": ...
    } 
}
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.

完整例子如下:

复制

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)
  • 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.
  • 44.
  • 45.
  • 46.
  • 47.
  • 48.
  • 49.
  • 50.

输出结果如下:

复制

{
    "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"
        }
    ]
}
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.
结构化输出方法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))
  • 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.

输出结果为:

复制

{
    "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"
}
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.

JSON Schema结构化输出 VS JSON模式

JSON Schema结构化输出是JSON模式的进阶版本。JSON模式是通过设置response_format为{ "type": "json_object" }打开。使用JSON模式时,你必须始终通过对话中的某些消息(例如系统消息)指示模型生成JSON。JSON 模式不能保证输出符合任何特定的模式。

总结

JSON Schema结构化输出提供了一个强大的解决方案,可确保您的大语言模型生成可靠、可预测且机器可读的回复。结构化输出有助于您在不同应用程序中保持一致的数据格式,从而更轻松地管理复杂的工作流程。

本文章已经生成可运行项目
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值