在金融领域的 RAG(检索增强生成)和 Agent
系统中,非结构化文本的结构化提取 是最常见的需求之一。我们需要从杂乱的新闻、公告或研报中,精准地提取出"时间"、"股票代码"、"价格"、"成交量"等关键字段,并将其转换为程序可直接处理的
JSON 格式。 然而,金融文本往往存在表述多样、单位不统一(人民币/美元)、甚至关键信息缺失的情况。如何让大模型稳定输出符合 Schema
定义的 JSON 数据? 本文将通过一个金融信息抽取 的实战案例,深入讲解如何结合 Few-Shot
Prompting(少样本提示) 、Schema 约束 以及 缺失值处理策略,构建高鲁棒性的信息抽取管道。
🎯 案例目标
任务:从一段金融新闻文本中,提取以下 5 个关键字段:
- 日期
- 股票名称
- 开盘价
- 收盘价
- 成交量
核心挑战:
- 格式统一 :必须输出标准的 JSON 字符串,方便
json.loads()解析。 - 缺失处理 :如果原文未提及某项信息(如只说了开盘价没说收盘价),不能瞎编,需返回特定标记(如
'原文未提及')。 - 单位保留:价格可能包含"人民币"、"美元"等单位,需原样保留以便后续换算。
💡 核心技术策略
1. 动态 Schema 注入
我们将需要提取的字段列表 schema 直接嵌入到 System Prompt 中。这使得提示词具有灵活性,如果需要提取新字段(如"涨跌幅"),只需修改列表即可,无需重写整个 Prompt。
2. Few-Shot 示例构造
代码中准备了两个典型的示例(Example):
- 示例 1:包含所有字段的完整情况(A股,人民币)。
- 示例 2 :包含不同货币单位的情况(美股,美元)。
通过展示"输入文本 -> 标准 JSON 输出"的映射,让模型学会提取逻辑和格式规范。
3. 防御性缺失值处理
在 System Prompt 中明确指令:"如果某些信息不存在,用'原文未提及'表示 "。
这是防止模型产生幻觉(Hallucination)的关键。对于金融数据,准确性高于一切,不知道就是不知道,绝不能由模型猜测。
4. Python json.dumps 辅助构建
在构建 Few-Shot 的 Assistant 回复时,我们使用 Python 的 json.dumps() 函数将字典转换为 JSON 字符串。
- 好处:确保示例中的 JSON 格式绝对标准(双引号、转义字符处理),避免手动拼接字符串可能产生的格式错误,给模型提供最完美的"模仿对象"。
📝 完整代码解析
python
import os
import json
from openai import OpenAI
# 1. 初始化客户端
client = OpenAI(
api_key=os.getenv("DASHSCOPE_API_KEY"),
base_url="https://dashscope.aliyuncs.com/compatible-mode/v1"
)
# 2. 定义提取 schema (想要提取哪些字段)
schema = ['日期', '股票名称', '开盘价', '收盘价', '成交量']
# 3. 准备 Few-Shot 示例数据
# 每个示例包含 "content" (原始文本) 和 "answers" (标准答案字典)
examples_data = [
{
"content": "2023-01-10, 股市震荡。股票强大科技A股今日开盘价100人民币,一度飙升至105人民币,随后回落至98人民币,最终以102人民币收盘,成交量达到520000。",
"answers": {
"日期": "2023-01-10",
"股票名称": "强大科技A股",
"开盘价": "100人民币",
"收盘价": "102人民币",
"成交量": "520000"
}
},
{
"content": "2024-05-16, 股市利好。股票英伟达美股今日开盘价105美元,一度飙升至109美元,随后回落至100美元,最终以116美元收盘,成交量达到3560000。",
"answers": {
"日期": "2024-05-16",
"股票名称": "英伟达美股",
"开盘价": "105美元",
"收盘价": "116美元",
"成交量": "3560000"
}
}
]
# 4. 待测试的提问数据
questions = [
# 情况 A: 信息完整
"2025-06-16, 股市利好。股票传智教育A股今日开盘价66人民币,一度飙升至70人民币,随后回落至65人民币,最终以68人民币收盘,成交量达到123000。",
# 情况 B: 信息缺失 (缺少成交量),测试模型的防御性
"2025-06-06, 股市利好。股票黑马程序员A股今日开盘价200人民币,一度飙升至211人民币,随后回落至201人民币,最终以206人民币收盘。"
]
# 5. 构建 Messages 列表
# System Prompt: 定义任务、Schema、输出格式及缺失值处理规则
messages = [
{"role": "system", "content": f"你帮我完成信息抽取,我给你句子,你抽取{schema}信息,按JSON字符串输出,如果某些信息不存在,用'原文未提及'表示,请参考如下示例:"},
]
# 动态添加 Few-Shot 示例
# 关键点:使用 json.dumps 确保示例的输出部分是标准的 JSON 字符串
for example in examples_data:
messages.append({"role": "user", "content": example["content"]})
# ensure_ascii=False 保证中文正常显示,不被转义为 \uXXXX
messages.append({"role": "assistant", "content": json.dumps(example["answers"], ensure_ascii=False)})
print("🚀 开始金融信息抽取测试...\n")
# 6. 循环测试
for i, q in enumerate(questions, 1):
# 构造当前请求:历史消息 + 当前问题
current_messages = messages + [{"role": "user", "content": f"按照上述示例,抽取这个句子的信息:{q}"}]
try:
response = client.chat.completions.create(
model="qwen-plus",
messages=current_messages,
temperature=0.0 # 🔥 关键:设置为0,确保输出格式严格一致,无随机性
)
raw_output = response.choices[0].message.content.strip()
print(f"[测试 {i}] 输入:{q[:40]}...")
print(f"模型原始输出:\n{raw_output}")
# 【验证】尝试解析验证是否为合法 JSON
try:
# 清理可能存在的 markdown 标记
if raw_output.startswith("```json"):
raw_output = raw_output[7:-3]
elif raw_output.startswith("```"):
raw_output = raw_output[3:-3]
data = json.loads(raw_output)
print(f"✅ JSON 解析成功!提取结果:{data}")
# 检查缺失值处理
if "原文未提及" in data.values():
print("⚠️ 检测到缺失字段,已正确标记为'原文未提及'")
except json.JSONDecodeError:
print("❌ JSON 解析失败,模型输出格式可能有误")
print("-" * 50)
except Exception as e:
print(f"[测试 {i}] 调用出错:{e}\n")

🔍 深度原理解析
1. 为什么使用 json.dumps 构建示例?
在代码中,我们没有手动写 JSON 字符串,而是:
python
json.dumps(example["answers"], ensure_ascii=False)
- 原因:手动拼接 JSON 字符串极易出错(比如忘记转义双引号、逗号位置错误)。如果 Few-Shot 示例中的 JSON 格式本身有误,模型就会"有样学样",输出错误的格式。
- 效果:利用 Python 标准库生成完美的 JSON 字符串作为示例,给模型树立"标杆",大幅提高模型输出格式的规范性。
2. 缺失值处理的艺术
测试数据中的第 2 条故意去掉了"成交量"。
- 若无指令 :模型可能会根据上下文瞎编一个数字,或者输出
null,甚至报错。 - 有指令 :
如果某些信息不存在,用'原文未提及'表示。 - 结果 :模型会输出
"成交量": "原文未提及"。这对于后续业务逻辑非常重要,程序可以据此判断该条数据不完整,需要进行人工复核或标记为低置信度。
3. Temperature = 0.0 的重要性
信息抽取是确定性任务。
- 我们不需要模型发挥创造力去改写句子。
- 我们需要它像正则表达式一样精准,但比正则更智能(能理解语义)。
- 设置
temperature=0.0能最大程度减少输出波动,确保每次运行得到的 JSON 结构完全一致。
🚀 总结
本案例展示了如何利用大模型进行高质量的结构化信息抽取:
- Schema 驱动:灵活定义提取字段。
- Few-Shot 引导:通过高质量示例规范输出格式。
- Python 辅助 :利用
json.dumps确保示例的标准性。 - 鲁棒性设计:显式处理缺失数据,防止幻觉。
这一模式是构建金融知识库、自动化报表生成、以及 Agent 决策系统的数据基石。掌握了它,您就可以轻松将海量的非结构化文本转化为高价值的结构化数据资产。