从自然语言到结构化数据的提取

前言

LLM 的输出通常是自然语言文本,但在实际应用中,我们经常需要将其转换为结构化数据(JSON、数据库记录等)。本文将介绍多种实现结构化输出的方法和最佳实践。


结构化输出概述

为什么需要结构化输出

┌─────────────────────────────────────────────────────────────────┐
│                    结构化输出应用场景                             │
├─────────────────────────────────────────────────────────────────┤
│                                                                 │
│  信息提取 ──────────────────────────────────────────────────   │
│  │ • 从文本中提取实体和关系                                      │
│  │ • 简历解析、发票识别                                          │
│  │                                                              │
│  API 响应 ──────────────────────────────────────────────────   │
│  │ • 返回格式化的 JSON 数据                                      │
│  │ • 与前端或其他系统对接                                        │
│  │                                                              │
│  流程自动化 ────────────────────────────────────────────────   │
│  │ • 提取参数调用下游函数                                        │
│  │ • 表单自动填充                                               │
│                                                                 │
└─────────────────────────────────────────────────────────────────┘

实现方式对比

方式 可靠性 灵活性 适用场景
Prompt 约束 简单场景
JSON Mode 标准 JSON
Function Calling 很高 复杂结构
Structured Outputs 最高 严格模式要求
Pydantic + Instructor 很高 很高 生产环境

Prompt 约束方式

基础 JSON 输出

from openai import OpenAI
import json

client = OpenAI()

def extract_with_prompt(text: str) -> dict:
    """使用 Prompt 约束提取结构化数据"""
    
    prompt = f"""从以下文本中提取信息,以 JSON 格式返回。

文本:
{text}

请提取以下信息并以 JSON 格式返回:
- name: 人名
- age: 年龄(数字)
- occupation: 职业
- skills: 技能列表

只返回 JSON,不要其他内容。

JSON:"""

    response = client.chat.completions.create(
        model="gpt-4",
        messages=[{"role": "user", "content": prompt}],
        temperature=0  # 降低随机性
    )
    
    # 解析 JSON
    try:
        result = json.loads(response.choices[0].message.content)
        return result
    except json.JSONDecodeError:
        # 尝试提取 JSON 部分
        content = response.choices[0].message.content
        start = content.find('{')
        end = content.rfind('}') + 1
        if start != -1 and end > start:
            return json.loads(content[start:end])
        raise
---

#### 生产级方案:Instructor + Pydantic

在生产环境中直接解析字符串是非常脆弱的`Instructor` 是目前最流行的库它通过 Pydantic 模型定义结构并自动处理重试逻辑

#### 核心优势
- **类型安全**直接返回 Pydantic 对象支持 IDE 补全
- **自动重试**如果 LLM 返回的 JSON 不符合 SchemaInstructor 会自动将错误信息反馈给模型并要求重试
- **验证逻辑**支持 Pydantic  `Field` 验证和自定义验证器

#### 代码实现

```python
import instructor
from pydantic import BaseModel, Field, validator
from typing import List, Optional
from openai import OpenAI

# 1. 定义数据模型
class Skill(BaseModel):
    name: str
    level: str = Field(description="技能熟练度,如:入门, 熟练, 精通")

class UserProfile(BaseModel):
    name: str = Field(..., description="用户的真实姓名")
    age: int = Field(..., ge=0, le=120)
    occupation: Optional[str]
    skills: List[Skill]
    
    @validator("name")
    def name_must_be_capitalized(cls, v):
        if not v[0].isupper():
            raise ValueError("姓名首字母必须大写")
        return v

# 2. 封装 Instructor 客户端
client = instructor.patch(OpenAI())

def extract_user_info(text: str) -> UserProfile:
    """使用 Instructor 提取结构化数据"""
    return client.chat.completions.create(
        model="gpt-4o",
        response_model=UserProfile,
        messages=[
            {"role": "system", "content": "你是一个专业的数据提取助手。"},
            {"role": "user", "content": f"提取以下文本中的用户信息:{text}"}
        ],
        max_retries=3  # 自动重试次数
    )

# 示例
text = "张三(Zhang San),今年 28 岁,是一名高级软件工程师。他精通 Python 和 Go 语言。"
try:
    user = extract_user_info(text)
    print(f"姓名: {user.name}, 年龄: {user.age}")
    for skill in user.skills:
        print(f"- 技能: {skill.name} ({skill.level})")
except Exception as e:
    print(f"提取失败: {e}")

OpenAI Structured Outputs (Strict Mode)

OpenAI 推出的 json_schema 模式(Strict Mode)在模型层面保证了输出 100% 符合定义的 Schema。

为什么它比普通 JSON Mode 强?

  • 100% 合规性:通过约束解码(Constrained Decoding)技术,模型在生成每一个 Token 时都会被限制在符合 Schema 的范围内。
  • 拒绝生成非法 JSON:模型无法生成不符合定义的字段或类型。

代码实现

from pydantic import BaseModel
from openai import OpenAI

client = OpenAI()

class CalendarEvent(BaseModel):
    name: str
    date: str
    participants: list[str]

# 使用 strict=True 开启严格模式
completion = client.beta.chat.completions.parse(
    model="gpt-4o-2024-08-06",
    messages=[
        {"role": "system", "content": "提取日历事件信息。"},
        {"role": "user", "content": "明天下午 2 点和王总在 3 号会议室开会,讨论 Q4 计划。"},
    ],
    response_format=CalendarEvent,
)

event = completion.choices[0].message.parsed
print(event.name)  # 输出: 会议

本地模型的结构化输出:Outlines 与 Guidance

如果你使用的是本地模型(如 Llama 3, Qwen),可以使用 OutlinesGuidance 库。它们通过修改模型的 Logits(概率分布)来强制模型输出符合正则表达式或 JSON Schema 的内容。

Outlines 示例

import outlines

model = outlines.models.transformers("meta-llama/Meta-Llama-3-8B-Instruct")

# 定义 Schema
prompt = "提取以下文本中的城市和人口:上海有 2400 万人。"
schema = """{
    "title": "CityInfo",
    "type": "object",
    "properties": {
        "city": {"type": "string"},
        "population": {"type": "integer"}
    }
}"""

# 强制生成符合 Schema 的 JSON
generator = outlines.generate.json(model, schema)
result = generator(prompt)
print(result)

最佳实践与避坑指南

  1. Temperature 设置为 0:结构化输出需要极高的确定性。
  2. 提供 Few-shot 示例:在 Prompt 中提供 1-2 个正确的 JSON 样例,能显著提升复杂结构的提取成功率。
  3. 处理长文本:如果文本过长,建议先进行分段提取,最后再汇总。
  4. 容错处理:即使使用了严格模式,也要在代码中加入 try-except,处理网络超时或模型拒绝回答的情况。
  5. Schema 简化:不要定义过于复杂的嵌套结构,模型在处理深层嵌套时更容易出错。

总结

结构化输出是连接 LLM 与传统软件系统的桥梁。

  • 简单任务:使用 JSON Mode。
  • 生产环境:首选 Instructor + Pydantic
  • 极致可靠性:使用 OpenAI Structured Outputs (Strict)
  • 本地模型:使用 Outlines 进行 Logit 约束。

掌握这些工具,你就能将 LLM 变成一个强大的、可预测的数据处理引擎。

使用

text = “张三,28岁,是一名资深软件工程师,精通 Python、Java 和机器学习。” result = extract_with_prompt(text) print(result)

{‘name’: ‘张三’, ‘age’: 28, ‘occupation’: ‘软件工程师’, ‘skills’: [‘Python’, ‘Java’, ‘机器学习’]}


#### Few-shot 示例

```python
def extract_with_examples(text: str) -> dict:
    """使用 Few-shot 示例提高准确性"""
    
    prompt = f"""从文本中提取人物信息。

示例 1:
输入:李明是一位35岁的医生,擅长心脏外科手术。
输出:name

示例 2:
输入:25岁的王芳在互联网公司做产品经理,负责用户增长。
输出:name

现在请处理:
输入:{text}
输出:"""

    response = client.chat.completions.create(
        model="gpt-4",
        messages=[{"role": "user", "content": prompt}],
        temperature=0
    )
    
    return json.loads(response.choices[0].message.content)

JSON Mode

OpenAI JSON Mode

from openai import OpenAI

client = OpenAI()

def extract_json_mode(text: str) -> dict:
    """使用 JSON Mode 确保输出为有效 JSON"""
    
    response = client.chat.completions.create(
        model="gpt-4-turbo-preview",
        response_format={"type": "json_object"},  # 启用 JSON Mode
        messages=[
            {
                "role": "system",
                "content": "你是一个信息提取助手,始终以 JSON 格式返回结果。"
            },
            {
                "role": "user",
                "content": f"""从以下文本提取人物信息:

文本:{text}

返回格式:
name
}}"""
            }
        ]
    )
    
    return json.loads(response.choices[0].message.content)

# 使用
text = "赵雷是一名29岁的数据科学家,在阿里巴巴工作3年了。"
result = extract_json_mode(text)
print(result)

JSON Schema 约束

def extract_with_schema(text: str) -> dict:
    """使用 JSON Schema 定义结构"""
    
    schema = {
        "type": "object",
        "properties": {
            "name": {"type": "string", "description": "人物姓名"},
            "age": {"type": "integer", "description": "年龄"},
            "occupation": {"type": "string", "description": "职业"},
            "company": {"type": "string", "description": "公司名称"},
            "experience_years": {"type": "integer", "description": "工作年限"}
        },
        "required": ["name", "occupation"]
    }
    
    response = client.chat.completions.create(
        model="gpt-4-turbo-preview",
        response_format={"type": "json_object"},
        messages=[
            {
                "role": "system",
                "content": f"""提取信息并以 JSON 返回。
遵循以下 Schema:
{json.dumps(schema, ensure_ascii=False, indent=2)}"""
            },
            {
                "role": "user",
                "content": f"文本:{text}"
            }
        ]
    )
    
    return json.loads(response.choices[0].message.content)

Structured Outputs(结构化输出)

OpenAI Structured Outputs

OpenAI 最新的结构化输出功能,提供 100% 可靠的 JSON Schema 遵循:

from openai import OpenAI
from pydantic import BaseModel
from typing import List, Optional

client = OpenAI()

# 定义数据模型
class Person(BaseModel):
    name: str
    age: int
    occupation: str
    skills: List[str]
    company: Optional[str] = None

def extract_structured(text: str) -> Person:
    """使用 Structured Outputs 提取"""
    
    completion = client.beta.chat.completions.parse(
        model="gpt-4o-2024-08-06",
        messages=[
            {
                "role": "system",
                "content": "从文本中提取人物信息。"
            },
            {
                "role": "user",
                "content": text
            }
        ],
        response_format=Person  # 直接传入 Pydantic 模型
    )
    
    return completion.choices[0].message.parsed

# 使用
text = "陈伟是腾讯的高级算法工程师,今年32岁,擅长 NLP 和推荐系统。"
person = extract_structured(text)
print(f"姓名: {person.name}")
print(f"年龄: {person.age}")
print(f"技能: {person.skills}")

复杂嵌套结构

from pydantic import BaseModel, Field
from typing import List, Optional
from enum import Enum

class SkillLevel(str, Enum):
    beginner = "beginner"
    intermediate = "intermediate"
    advanced = "advanced"
    expert = "expert"

class Skill(BaseModel):
    name: str
    level: SkillLevel
    years: int = Field(description="使用该技能的年数")

class Education(BaseModel):
    school: str
    degree: str
    major: str
    graduation_year: int

class WorkExperience(BaseModel):
    company: str
    position: str
    start_year: int
    end_year: Optional[int] = None
    responsibilities: List[str]

class Resume(BaseModel):
    """简历结构"""
    name: str
    email: Optional[str] = None
    phone: Optional[str] = None
    summary: str = Field(description="个人简介")
    education: List[Education]
    experience: List[WorkExperience]
    skills: List[Skill]

def parse_resume(resume_text: str) -> Resume:
    """解析简历"""
    
    completion = client.beta.chat.completions.parse(
        model="gpt-4o-2024-08-06",
        messages=[
            {
                "role": "system",
                "content": "你是一个专业的简历解析器,从简历文本中提取结构化信息。"
            },
            {
                "role": "user",
                "content": resume_text
            }
        ],
        response_format=Resume
    )
    
    return completion.choices[0].message.parsed

# 使用
resume_text = """
张三
邮箱:[email protected]
电话:13800138000

个人简介:
5年经验的全栈工程师,专注于 Web 开发和云原生技术。

教育背景:
- 北京大学 计算机科学 硕士 2018年毕业
- 清华大学 软件工程 学士 2016年毕业

工作经历:
1. 字节跳动 高级工程师 2020-至今
   - 负责核心业务系统架构设计
   - 带领5人团队完成微服务改造

2. 阿里巴巴 工程师 2018-2020
   - 开发电商推荐系统
   - 优化系统性能,QPS提升200%

技能:
- Python (专家级,6年)
- JavaScript (高级,5年)
- Kubernetes (中级,3年)
"""

resume = parse_resume(resume_text)
print(f"姓名: {resume.name}")
print(f"教育: {len(resume.education)}")
print(f"经历: {len(resume.experience)}")

Pydantic + Instructor

Instructor 库

Instructor 是一个专门用于结构化输出的库,提供更好的开发体验:

pip install instructor
import instructor
from openai import OpenAI
from pydantic import BaseModel, Field
from typing import List

# 初始化 Instructor 客户端
client = instructor.from_openai(OpenAI())

class Product(BaseModel):
    """产品信息"""
    name: str = Field(description="产品名称")
    price: float = Field(description="价格(元)")
    category: str = Field(description="产品类别")
    features: List[str] = Field(description="产品特点")

def extract_product(description: str) -> Product:
    """从描述中提取产品信息"""
    
    product = client.chat.completions.create(
        model="gpt-4",
        response_model=Product,
        messages=[
            {
                "role": "user",
                "content": f"从以下产品描述中提取信息:\n\n{description}"
            }
        ]
    )
    
    return product

# 使用
description = """
新款 iPhone 15 Pro Max 现已上市!售价 9999 元起。
作为苹果最新旗舰手机,它配备了 A17 Pro 芯片、
钛金属边框、4800万像素主摄和 USB-C 接口。
"""

product = extract_product(description)
print(product.model_dump_json(indent=2))

带验证的提取

from pydantic import BaseModel, Field, field_validator
from typing import List
import instructor
from openai import OpenAI

client = instructor.from_openai(OpenAI())

class OrderItem(BaseModel):
    product: str
    quantity: int = Field(ge=1, description="数量必须大于0")
    unit_price: float = Field(ge=0, description="单价必须非负")
    
    @property
    def total(self) -> float:
        return self.quantity * self.unit_price

class Order(BaseModel):
    order_id: str = Field(pattern=r"^ORD-\d{6}$", description="订单号格式:ORD-XXXXXX")
    customer_name: str
    items: List[OrderItem]
    
    @field_validator('customer_name')
    @classmethod
    def validate_name(cls, v):
        if len(v) < 2:
            raise ValueError("客户名称至少2个字符")
        return v
    
    @property
    def total_amount(self) -> float:
        return sum(item.total for item in self.items)

def parse_order(text: str) -> Order:
    """解析订单信息"""
    
    return client.chat.completions.create(
        model="gpt-4",
        response_model=Order,
        messages=[
            {
                "role": "system",
                "content": "从文本中提取订单信息。如果没有订单号,生成格式为 ORD-XXXXXX 的订单号。"
            },
            {
                "role": "user",
                "content": text
            }
        ],
        max_retries=3  # 验证失败时自动重试
    )

# 使用
order_text = """
客户张伟下单了以下商品:
- 苹果 x 5个,每个 8 元
- 香蕉 x 3斤,每斤 6 元
- 西瓜 x 1个,15 元
"""

order = parse_order(order_text)
print(f"订单号: {order.order_id}")
print(f"客户: {order.customer_name}")
print(f"总金额: {order.total_amount}")

流式结构化输出

from instructor import Partial
from pydantic import BaseModel
from typing import List

class Article(BaseModel):
    title: str
    summary: str
    key_points: List[str]
    conclusion: str

def stream_article_extraction(text: str):
    """流式提取文章结构"""
    
    for partial_article in client.chat.completions.create_partial(
        model="gpt-4",
        response_model=Article,
        messages=[
            {
                "role": "user",
                "content": f"分析以下文章并提取结构化信息:\n\n{text}"
            }
        ],
        stream=True
    ):
        # partial_article 是部分填充的 Article 对象
        print(f"当前状态: {partial_article}")
        yield partial_article

# 使用
for partial in stream_article_extraction(article_text):
    if partial.title:
        print(f"标题: {partial.title}")
    if partial.key_points:
        print(f"要点数: {len(partial.key_points)}")

Function Calling 方式

定义函数 Schema

from openai import OpenAI
import json

client = OpenAI()

# 定义函数 Schema
tools = [
    {
        "type": "function",
        "function": {
            "name": "extract_meeting_info",
            "description": "从文本中提取会议信息",
            "parameters": {
                "type": "object",
                "properties": {
                    "title": {
                        "type": "string",
                        "description": "会议主题"
                    },
                    "date": {
                        "type": "string",
                        "description": "会议日期,格式 YYYY-MM-DD"
                    },
                    "time": {
                        "type": "string",
                        "description": "会议时间,格式 HH:MM"
                    },
                    "location": {
                        "type": "string",
                        "description": "会议地点"
                    },
                    "participants": {
                        "type": "array",
                        "items": {"type": "string"},
                        "description": "参会人员列表"
                    },
                    "agenda": {
                        "type": "array",
                        "items": {"type": "string"},
                        "description": "会议议程"
                    }
                },
                "required": ["title", "date", "time"]
            }
        }
    }
]

def extract_meeting(text: str) -> dict:
    """使用 Function Calling 提取会议信息"""
    
    response = client.chat.completions.create(
        model="gpt-4",
        messages=[
            {
                "role": "system",
                "content": "你是一个会议信息提取助手。"
            },
            {
                "role": "user",
                "content": f"请从以下文本中提取会议信息:\n\n{text}"
            }
        ],
        tools=tools,
        tool_choice={"type": "function", "function": {"name": "extract_meeting_info"}}
    )
    
    # 解析函数调用结果
    tool_call = response.choices[0].message.tool_calls[0]
    return json.loads(tool_call.function.arguments)

# 使用
text = """
提醒:明天下午2点在3楼会议室有产品评审会。
参会人员:张经理、李工、王设计师
议程:
1. Q3产品规划汇报
2. 新功能演示
3. 讨论下一步计划
"""

meeting = extract_meeting(text)
print(json.dumps(meeting, ensure_ascii=False, indent=2))

多函数选择

tools = [
    {
        "type": "function",
        "function": {
            "name": "extract_person",
            "description": "提取人物信息",
            "parameters": {
                "type": "object",
                "properties": {
                    "name": {"type": "string"},
                    "age": {"type": "integer"},
                    "occupation": {"type": "string"}
                },
                "required": ["name"]
            }
        }
    },
    {
        "type": "function",
        "function": {
            "name": "extract_company",
            "description": "提取公司信息",
            "parameters": {
                "type": "object",
                "properties": {
                    "name": {"type": "string"},
                    "industry": {"type": "string"},
                    "employee_count": {"type": "integer"}
                },
                "required": ["name"]
            }
        }
    },
    {
        "type": "function",
        "function": {
            "name": "extract_event",
            "description": "提取事件信息",
            "parameters": {
                "type": "object",
                "properties": {
                    "event_type": {"type": "string"},
                    "date": {"type": "string"},
                    "description": {"type": "string"}
                },
                "required": ["event_type"]
            }
        }
    }
]

def smart_extract(text: str) -> dict:
    """智能选择合适的提取函数"""
    
    response = client.chat.completions.create(
        model="gpt-4",
        messages=[
            {
                "role": "user",
                "content": f"从以下文本提取关键信息:\n\n{text}"
            }
        ],
        tools=tools,
        tool_choice="auto"  # 让模型自动选择
    )
    
    results = []
    for tool_call in response.choices[0].message.tool_calls:
        results.append({
            "type": tool_call.function.name,
            "data": json.loads(tool_call.function.arguments)
        })
    
    return results

实体关系抽取

知识图谱构建

from pydantic import BaseModel
from typing import List, Optional
import instructor
from openai import OpenAI

client = instructor.from_openai(OpenAI())

class Entity(BaseModel):
    """实体"""
    name: str
    type: str  # Person, Organization, Location, etc.
    description: Optional[str] = None

class Relation(BaseModel):
    """关系"""
    subject: str  # 主体实体名称
    predicate: str  # 关系类型
    object: str  # 客体实体名称
    confidence: float = 1.0

class KnowledgeGraph(BaseModel):
    """知识图谱"""
    entities: List[Entity]
    relations: List[Relation]

def extract_knowledge_graph(text: str) -> KnowledgeGraph:
    """从文本构建知识图谱"""
    
    return client.chat.completions.create(
        model="gpt-4",
        response_model=KnowledgeGraph,
        messages=[
            {
                "role": "system",
                "content": """从文本中提取实体和关系,构建知识图谱。
实体类型包括:Person(人物)、Organization(组织)、Location(地点)、Event(事件)、Product(产品)
关系类型包括:works_at(就职于)、located_in(位于)、founded(创立)、acquired(收购)、partners_with(合作)等"""
            },
            {
                "role": "user",
                "content": text
            }
        ]
    )

# 使用
text = """
2023年,阿里巴巴集团在杭州宣布成立达摩院,由张勇担任首席技术官。
达摩院与清华大学建立了战略合作关系,共同研究人工智能技术。
同年,达摩院发布了通义千问大模型,在业界引起广泛关注。
"""

kg = extract_knowledge_graph(text)

print("实体:")
for entity in kg.entities:
    print(f"  - {entity.name} ({entity.type})")

print("\n关系:")
for relation in kg.relations:
    print(f"  - {relation.subject} --[{relation.predicate}]--> {relation.object}")

表格数据提取

from pydantic import BaseModel
from typing import List
import instructor
from openai import OpenAI

client = instructor.from_openai(OpenAI())

class TableRow(BaseModel):
    """表格行"""
    values: List[str]

class Table(BaseModel):
    """表格结构"""
    headers: List[str]
    rows: List[TableRow]
    
    def to_dict_list(self) -> List[dict]:
        """转换为字典列表"""
        return [
            dict(zip(self.headers, row.values))
            for row in self.rows
        ]

def extract_table(text: str) -> Table:
    """从文本中提取表格数据"""
    
    return client.chat.completions.create(
        model="gpt-4",
        response_model=Table,
        messages=[
            {
                "role": "user",
                "content": f"从以下文本中提取表格数据:\n\n{text}"
            }
        ]
    )

# 使用
text = """
2023年第三季度各部门业绩:
销售部完成了1200万的销售额,同比增长15%;
技术部完成了8个项目,成本控制在500万以内;
市场部获得了50万新用户,转化率达到12%。
"""

table = extract_table(text)
print("表格数据:")
for row in table.to_dict_list():
    print(row)

最佳实践

选择合适的方法

┌─────────────────────────────────────────────────────────────────┐
│                    结构化输出方法选择                             │
├─────────────────────────────────────────────────────────────────┤
│                                                                 │
│  简单提取 ─────────────> Prompt 约束 / JSON Mode               │
│  │                                                              │
│  中等复杂度 ───────────> Function Calling                       │
│  │                                                              │
│  复杂结构 + 验证 ──────> Instructor + Pydantic                  │
│  │                                                              │
│  严格 Schema 遵循 ─────> Structured Outputs (GPT-4o)            │
│                                                                 │
└─────────────────────────────────────────────────────────────────┘

提高准确性

# 1. 使用详细的 Field 描述
class Person(BaseModel):
    name: str = Field(
        description="人物的完整姓名,包括姓和名",
        examples=["张三", "李明"]
    )
    age: int = Field(
        ge=0, le=150,
        description="年龄,必须是正整数"
    )

# 2. 提供示例
messages = [
    {
        "role": "system",
        "content": """提取人物信息。

示例输入:小王今年25岁,在北京工作。
示例输出:{"name": "小王", "age": 25, "location": "北京"}"""
    },
    {"role": "user", "content": text}
]

# 3. 分步提取
def extract_complex(text: str):
    # 先提取基本信息
    basic = extract_basic_info(text)
    # 再提取详细信息
    details = extract_details(text, context=basic)
    # 合并结果
    return merge_results(basic, details)

错误处理

from pydantic import ValidationError
import instructor

def safe_extract(text: str, max_retries: int = 3):
    """带错误处理的提取"""
    
    for attempt in range(max_retries):
        try:
            result = client.chat.completions.create(
                model="gpt-4",
                response_model=MyModel,
                messages=[{"role": "user", "content": text}],
                max_retries=2
            )
            return result
            
        except ValidationError as e:
            print(f"验证错误 (尝试 {attempt + 1}): {e}")
            # 可以修改提示重试
            
        except Exception as e:
            print(f"提取失败: {e}")
            
    return None

总结

结构化输出是 LLM 应用与业务系统集成的关键:

方法 优点 缺点 推荐场景
Prompt 约束 简单灵活 不稳定 原型开发
JSON Mode 保证有效 JSON Schema 控制弱 简单 API
Function Calling 可靠性高 配置繁琐 工具调用
Structured Outputs 最可靠 需要新模型 严格场景
Instructor 开发体验好 依赖库 生产环境

关键原则:

  1. 定义清晰的数据模型
  2. 提供充分的字段描述
  3. 实现完善的验证逻辑
  4. 处理边界情况和错误

参考资源

版权声明: 如无特别声明,本文版权归 sshipanoo 所有,转载请注明本文链接。

(采用 CC BY-NC-SA 4.0 许可协议进行授权)

本文标题:《 LLM应用开发——结构化输出 》

本文链接:http://localhost:3015/ai/%E7%BB%93%E6%9E%84%E5%8C%96%E8%BE%93%E5%87%BA.html

本文最后一次更新为 天前,文章中的某些内容可能已过时!