首页 > 教程攻略 > ai资讯 >RAG必备知识:OpenAI官宣结构化输出|结构化输出工具大汇总

RAG必备知识:OpenAI官宣结构化输出|结构化输出工具大汇总

来源:互联网 时间:2026-08-24 13:58:22

OpenAI 官方正式宣布:API 开始支持结构化输出了。这个功能需求非常普遍,现在总算落地。

具体来说,API 引入的结构化输出让模型能够严格按照开发者提供的 JSON 模式生成数据。让大型语言模型(LLM)输出结构化内容,在 NLP 领域一直是重要目标——把自然语言转换成表格、数据库条目、JSON 对象这类有明确格式的数据。这不仅能提高输出的可预测性和可用性,还能在各种应用场景中大大增强实用性。结构化输出有助于减少误差,提升数据处理效率,确保与其他系统和集成时的一致性和兼容性。对于自动化工作流、数据分析、NLP 任务以及智能助手等场景,这个特性尤其关键。

亲自试了一下,真香。再也不用为模型返回的格式不固定而发愁了。

确保 LLM 返回结构化的输出,很多时候是刚需。因为模型的输出通常要喂给下游应用程序,需要特定的参数才能正常工作。如果输出的数据不可靠,下游调用就容易翻车。结构化的输出能保证数据一致、准确,还能提升整体系统的效率和性能。数据处理、分析和集成都会更顺畅,决策和业务流程优化也就有了更好的支撑。

下面通过几个示例来感受一下。

示例一:用于思维链数学辅导的结构化输出

from pydantic import BaseModel
from openai import OpenAI

client = OpenAI()

class Step(BaseModel):
    explanation: str
    output: str

class MathReasoning(BaseModel):
    steps: list[Step]
    final_answer: str

completion = client.beta.chat.completions.parse(
    model="gpt-4o-2024-08-06",
    messages=[
        {"role": "system", "content": "You are a helpful math tutor. Guide the user through the solution step by step."},
        {"role": "user", "content": "how can I solve 8x + 7 = -23"}
    ],
    response_format=MathReasoning,
)

math_reasoning = completion.choices[0].message.parsed

返回结果如下:

{"steps": [{"explanation": "Start with the equation 8x + 7 = -23.","output": "8x + 7 = -23"},{"explanation": "Subtract 7 from both sides to isolate the term with the variable.","output": "8x = -23 - 7"},{"explanation": "Simplify the right side of the equation.","output": "8x = -30"},{"explanation": "Divide both sides by 8 to solve for x.","output": "x = -30 / 8"},{"explanation": "Simplify the fraction.","output": "x = -15 / 4"}],"final_answer": "x = -15 / 4"}

示例二:定义结构化字段,从非结构化输入(例如检索论文)中提取信息

from pydantic import BaseModel
from openai import OpenAI

client = OpenAI()

class ResearchPaperExtraction(BaseModel):
    title: str
    authors: list[str]
    abstract: str
    keywords: list[str]

completion = client.beta.chat.completions.parse(
    model="gpt-4o-2024-08-06",
    messages=[
        {"role": "system", "content": "You are an expert at structured data extraction. You will be given unstructured text from a research paper and should convert it into the given structure."},
        {"role": "user", "content": "..."}
    ],
    response_format=ResearchPaperExtraction,
)

research_paper = completion.choices[0].message.parsed

返回结果如下:

{"title": "Application of Quantum Algorithms in Interstellar Na vigation: A New Frontier","authors": ["Dr. Stella Voyager","Dr. Nova Star","Dr. Lyra Hunter"],"abstract": "This paper investigates the utilization of quantum algorithms to improve interstellar na vigation systems. By leveraging quantum superposition and entanglement, our proposed na vigation system can calculate optimal tra vel paths through space-time anomalies more efficiently than classical methods. Experimental simulations suggest a significant reduction in tra vel time and fuel consumption for interstellar missions.","keywords": ["Quantum algorithms","interstellar na vigation","space-time anomalies","quantum superposition","quantum entanglement","space tra vel"]}

结构化输出其实是 JSON 模式的进化版。两者都能保证生成有效的 JSON,但只有结构化输出能确保完全符合定义的 schema。Chat Completions API、Assistants API、Fine-tuning API 和 Batch API 都同时支持结构化输出和 JSON 模式。

建议尽可能始终使用结构化输出,而不是退回到 JSON 模式。不过需要注意,只有 gpt-4o-mini、gpt-4o-mini-2024-07-18 和 gpt-4o-2024-08-06 这几个模型快照以及更高版本才支持结构化输出。

大家最关心的价格嘛……看起来优化空间不大,挤牙膏的感觉,不太理想(笑)。

在此之前,从 LLM 获取结构化输出的方法在 GitHub 上已经能搜到不少。

LangChain 和 LlamaIndex 也提供了大量结构化输出的方式,下面整理一下这些已有的方案。

LangChain 的结构化输出方式

JSON 输出

:LangChain 支持通过特定格式和标签生成 JSON 格式数据,方便后续处理和分析。

from typing import List
from langchain.prompts import PromptTemplate
from langchain_community.chat_models import ChatOpenAI
from langchain_core.output_parsers import JsonOutputParser
from langchain_core.pydantic_v1 import BaseModel, Field

model = ChatOpenAI(temperature=0)

# 定义所需的数据结构
class Joke(BaseModel):
    setup: str = Field(description="问题以设置笑话")
    punchline: str = Field(description="回答以解决笑话")

# 以提示模型填充数据结构的查询意图
joke_query = "Tell me a joke."

# 设置解析器+将说明注入提示模板
parser = JsonOutputParser(pydantic_object=Joke)

prompt = PromptTemplate(
    template="回答用户的查询。\n{format_instructions}\n{query}\n",
    input_variables=["query"],
    partial_variables={"format_instructions": parser.get_format_instructions()},
)

chain = prompt | model | parser

chain.invoke({"query": joke_query})

表格数据

:可以生成 CSV 或 Excel 格式的表格数据,适用于各种数据分析和报告需求。

from langchain.output_parsers import CommaSeparatedListOutputParser
from langchain.prompts import PromptTemplate
from langchain_community.chat_models import ChatOpenAI

output_parser = CommaSeparatedListOutputParser()

format_instructions = output_parser.get_format_instructions()
prompt = PromptTemplate(
    template="List five {subject}.\n{format_instructions}",
    input_variables=["subject"],
    partial_variables={"format_instructions": format_instructions}
)

model = OpenAI(temperature=0)

_input = prompt.format(subject="ice cream fla vors")
output = model(_input)

result = output_parser.parse(output)

# 输出:
# ['Vanilla', 'Chocolate', 'Strawberry', 'Mint Chocolate Chip', 'Cookies and Cream']

API 集成

:通过与其他 API 集成,实现结构化数据的自动化传输和处理。

from langchain_community.chat_models import ChatOpenAI
from langchain_community.utils.openai_functions import (
    convert_pydantic_to_openai_function,
)
from langchain_core.prompts import ChatPromptTemplate
from langchain_core.pydantic_v1 import BaseModel, Field, validator

class Joke(BaseModel):
    setup: str = Field(description="问题以设置笑话")
    punchline: str = Field(description="回答以解决笑话")

openai_functions = [convert_pydantic_to_openai_function(Joke)]

model = ChatOpenAI(temperature=0)

prompt = ChatPromptTemplate.from_messages(
    [("system", "You are a helpful assistant"), ("user", "{input}")]
)

Pydantic 声明

:使用 Pydantic 声明你的数据模型。Pydantic 的 BaseModel 就像 Python 的数据类,但具有实际的类型检查和强制转换。

from typing import List

from langchain.output_parsers import PydanticOutputParser
from langchain.prompts import PromptTemplate
from langchain_community.chat_models import ChatOpenAI
from langchain_core.pydantic_v1 import BaseModel, Field, validator

model = ChatOpenAI(temperature=0)

# 定义你期望的数据结构
class Joke(BaseModel):
    setup: str = Field(description="设立笑话的问题")
    punchline: str = Field(description="解决笑话的答案")

    # 你可以轻松地用Pydantic添加自定义验证逻辑
    @validator("setup")
    def question_ends_with_question_mark(cls, field):
        if field[-1] != "?":
            raise ValueError("问题格式不正确!")
        return field

# 并且一个旨在提示语言模型填充数据结构的查询
joke_query = "给我讲个笑话。"

# 设置解析器 + 将指令注入提示模板
parser = PydanticOutputParser(pydantic_object=Joke)

prompt = PromptTemplate(
    template="回答用户查询。\n{format_instructions}\n{query}\n",
    input_variables=["query"],
    partial_variables={"format_instructions": parser.get_format_instructions()},
)

chain = prompt | model | parser

chain.invoke({"query": joke_query})