结构化提取指令:让 LLM 从非结构化文本中抽取 Schema

FreeGuideOnline 最新 2026-06-23

结构化提取指令:让 LLM 从非结构化文本中抽取 Schema

什么是结构化提取

结构化提取(Structured Extraction)是指从自由文本、网页、PDF、对话记录等非结构化内容中,精准抽取出符合预定义格式的结构化数据。简单来说,就是让大语言模型(LLM)充当一个“智能解析器”,把杂乱信息转换成整齐的字段与值。

例如,给一段产品描述:

“2024款极光蓝运动跑鞋,原价1299,现价899,仅限3天,库存紧张。”

提取后应得到:

{
  "product_name": "极光蓝运动跑鞋",
  "model_year": 2024,
  "original_price": 1299,
  "current_price": 899,
  "deal_validity_days": 3,
  "in_stock": true
}

结构化提取与你可能熟悉的“文本摘要”“关键词提取”有本质区别:它输出的是严格遵循 schema 的数据结构,而不是自由文本。

为什么需要结构化提取指令

  1. 数据管道自动化
    企业有大量非结构化数据(报告、邮件、合同),需要转换成数据库或 API 的格式。手动标注成本高、速度慢,LLM 可以用一组提取指令批量完成。

  2. 可控性与可靠性
    明确告诉模型你要什么字段、什么类型,可以极大地减少幻觉和错误,让输出整齐划一,方便后续代码处理。

  3. 下游应用整合
    结构化数据可以无缝写入表格、触发工作流、生成报表。非结构化文本则无法直接用于自动化流程。

  4. 保护隐私与合规
    通过精确提取特定字段,你不需要把完整文档暴露给下游系统,只传递必要信息。

如何编写结构化提取指令

编写高质量提取指令的关键是:清晰定义 Schema、给出示例、施加输出约束。通常包含以下部分。

1. 明确任务陈述

一句话告诉模型要做什么。例如:

“请从以下客户投诉邮件中提取关键信息,并以 JSON 格式输出。”

2. 定义提取字段(Schema)

用自然语言详细描述每一个字段的含义、类型和格式要求。推荐使用表格或列表描述,确保无歧义。

字段名 类型 说明
customer_name string 客户全名,若未提及则为空字符串
complaint_category enum 取值为 ["产品缺陷","物流延迟","退款问题","其他"]
order_id string 订单号,格式为 # 后跟 6 位数字,若无则为 null
urgency_level integer 1~5 的整数,1 为最不紧急,5 为非常紧急,根据语气判断
requested_action string 客户期望的解决方式,最多一句话概括

这种 Schema 定义方式既适合人类阅读,也能有效约束 LLM。

3. 添加少样本示例(Few-shot)

提供 1~3 个高质量的输入-输出对,可以极大提升提取准确率。示例应覆盖常见的边界情况(缺失字段、多值、模糊表达)。

示例输入:

“你好,我的订单#123456的鞋子开胶了,三天前收到的,这质量也太差了。请尽快给我换一双新的,否则我只能退款了。非常生气!”

示例输出:

{
  "customer_name": "",
  "complaint_category": "产品缺陷",
  "order_id": "#123456",
  "urgency_level": 4,
  "requested_action": "换货或退款"
}

4. 标定输出格式

明确要求模型仅输出纯 JSON,且不要包含任何解释、markdown 代码块标记。可以这样写:

“你只应输出一个有效的 JSON 对象,不要包含其他文字。不要使用 ```json 标记。”

5. 处理缺失与异常

提前规定如何处理缺失值。例如:“如果原文中没有提及订单号,则将 order_id 设置为 null。”“如果无法判断类别,请使用‘其他’。”

完整指令模板

以下是一个可直接使用的通用指令模板:

你是一个数据提取专家。请严格按照提供的 Schema 从以下文本中提取信息。

## Schema
- full_name: string, 人员姓名,缺失则为空字符串
- birth_date: string, 出生日期,格式 YYYY-MM-DD,缺失则为 null
- email: string, 电子邮箱,缺失则为 null
- phone: string, 电话号码(仅保留数字,不含分隔符),缺失则为 null
- notes: string, 其它关键信息的一句话摘要,无特殊情况则为 ""

## 要求
1. 只输出一个 JSON 对象,没有其他文字。
2. 不要用 markdown 代码块包裹。
3. 严格遵守字段类型与格式。

## 示例
输入:
"张三,1990年5月生,电话是138-1234-5678,邮箱 zhangsan@example.com,爱好摄影。"
输出:
{"full_name":"张三","birth_date":"1990-05-01","email":"zhangsan@example.com","phone":"13812345678","notes":"爱好摄影"}

现在,请从以下文本中提取信息:
{待处理的文本}

常见陷阱与最佳实践

❌ 陷阱 1:Schema 不清晰

如果只说“提取姓名、日期”,模型可能返回多种格式。一定要给出精确的类型和格式示例

❌ 陷阱 2:一次性要求太多字段

字段越多,模型遗漏或幻觉的概率越高。可以考虑分步提取:先提取核心实体,再基于第一次输出补充细节。

❌ 陷阱 3:忽略数据验证

虽然 LLM 尽力输出符合 Schema 的数据,但仍可能出现格式错误或类型不匹配。始终在代码层加验证,例如用 Pydantic 或 JSON Schema 校验。

❌ 陷阱 4:让模型自由发挥

如果没有约束输出格式,模型常会添加“这是提取的结果:”等前缀。务必在指令中强制指定只输出原始 JSON,并用 API 的 response_format 参数(如果平台支持)来锁定 JSON 模式。

✅ 最佳实践一览

  • 使用函数调用(Function Calling)或 JSON 模式:如果所用 LLM 支持,直接传递 JSON Schema 定义,比纯自然语言指令更可靠。
  • 提示中提供 Schema 的 JSON 结构:不仅用文字描述,还用示例 JSON 展示目标结构。
  • 对于枚举值,用英文定义标签:避免大小写、翻译问题,例如用 "defect" 而非 "产品缺陷",最后由代码映射。
  • 考虑使用评分或置信度:要求模型为每个提取字段返回置信度(0-1),方便后续人工复核。
  • 处理长文本时进行分块:对于超过上下文长度的文档,先拆分段落,再合并提取结果。

实战:批量解析会议纪要

假设你有一堆会议记录文本,需要提取行动项。Schema 可以设计为:

{
  "meeting_date": "string (YYYY-MM-DD)",
  "attendees": ["string"],
  "action_items": [
    {
      "task": "string",
      "assignee": "string",
      "deadline": "string (YYYY-MM-DD) or null",
      "priority": "high | medium | low"
    }
  ]
}

配合如下指令段落:

请提取会议记录中的行动项。每个行动项包含任务描述、负责人、截止日期和优先级(high/medium/low)。
会议日期和参会人列表也要提取。
输出一个 JSON 对象,结构为:
{
  "meeting_date": "...",
  "attendees": ["..."],
  "action_items": [{"task": "...", "assignee": "...", "deadline": "...", "priority": "..."}]
}
如果某项没有明确说明,deadline 为 null,priority 默认为 medium。
只输出 JSON,不添加额外内容。

进阶:结合代码实现自动化

用 Python 和 OpenAI API(或其他兼容接口)可以直接将结构化提取嵌入流水线:

import openai, json

def extract_info(text, schema_description):
    response = openai.ChatCompletion.create(
        model="gpt-4-turbo",
        messages=[
            {"role": "system", "content": f"你是一个数据提取助手。严格按以下Schema提取:\n{schema_description}\n只输出JSON,无其他文字。"},
            {"role": "user", "content": text}
        ],
        temperature=0,
        response_format={"type": "json_object"}  # 强制 JSON 输出
    )
    return json.loads(response.choices[0].message.content)

注意设置 temperature=0 以获得确定性最高的输出,并使用 response_format 确保格式。

总结

结构化提取指令把 LLM 从“语言生成器”变成了“数据工厂”。核心要领:

  • Schema 即契约:定义越精确,结果越可靠。
  • 示例是黄金:哪怕只给一个示例,效果也常远超纯描述。
  • 输出格式绑死:用自然语言约束 + API 参数双重锁定。
  • 后处理不可少:永远校验提取结果,确保符合业务要求。

掌握这些技巧后,你就能用 LLM 轻松搭建各种数据采集中台、文档解析器和智能助手了。