【第二周】RAG与Agent实战08:提示词优化案例_金融文本匹配判断

在构建RAG(检索增强生成)系统时,一个常见的痛点是:检索到的文档片段与用户问题看似相关,实则答非所问 。如果将这些低质量的片段直接喂给大模型生成答案,会导致"幻觉"或错误的结论。

因此,在生成答案之前,增加一个**"文本匹配判断"(或称相关性重排序/过滤)的步骤至关重要。
本文将通过一个
金融文本匹配**的实战案例,演示如何利用 Few-Shot Prompting(少样本提示)
结构化输入格式,训练大模型精准判断两段文本是否在语义上匹配(即:这段文档是否能回答这个问题/是否与这段描述一致)。

🎯 案例目标

任务 :给定两个句子(Sentence A 和 Sentence B),判断它们在语义上是否匹配

  • 匹配(是):两句表达的核心事实、意图或主题一致,即使措辞不同。
  • 不匹配(不是):两句谈论的是完全不同的主题,或者事实冲突。

应用场景

  • RAG 检索过滤:判断检索到的文档片段是否与用户 Query 相关。
  • 去重:判断两条新闻是否在报道同一件事。
  • 事实核查:判断公告内容与市场传言是否一致。

输出要求:仅输出"是"或"不是",便于程序逻辑判断。

💡 核心技术策略

1. 语义匹配 vs 关键词匹配

传统的搜索引擎基于关键词匹配(如都包含"股票"、"上涨"),但往往无法理解深层语义。

  • 例子:"公司更赚钱了"vs"利润上升"。
  • 传统搜索:可能因为词汇不同而漏判。
  • 大模型 :能理解"更赚钱"等同于"利润上升",判定为匹配
    本案例利用大模型的语义理解能力,解决关键词匹配的局限性。

2. 正负样本均衡的 Few-Shot

在构建示例数据 examples_data 时,我们特意准备了:

  • 正样本("是"):包含同义词替换、句式重组但语义一致的案例。
  • 负样本("不是") :包含虽然都是金融领域,但主题完全无关(如"黄金"vs"外汇","降息"vs"新能源")的案例。
    这种均衡的示例能让模型学会区分"相关"与"无关"的边界,避免模型倾向于一直回答"是"。

3. 明确的输入分隔符

在 Prompt 中,我们使用 句子1: [...] 句子2: [...] 的格式,并用方括号 [] 包裹具体文本。

  • 作用:清晰界定两个输入对象的边界,防止模型混淆哪部分是参照物,哪部分是待判断对象。特别是在文本中包含标点符号时,分隔符能有效避免解析错误。

4. 极简输出约束

System Prompt 明确要求:"回答是或不是"。

  • 目的 :将复杂的推理过程内化,只输出布尔值结果。这使得后续代码可以直接通过 if response == "是" 进行逻辑分支处理,无需正则提取。

📝 完整代码解析

python 复制代码
import os
from openai import OpenAI

# 1. 初始化客户端
client = OpenAI(
    api_key=os.getenv("DASHSCOPE_API_KEY"),
    base_url="https://dashscope.aliyuncs.com/compatible-mode/v1"
    # 如果使用本地模型,可取消下面注释
    # base_url="http://localhost:11434/v1"
)

# 2. 准备 Few-Shot 示例数据
# 字典结构:Key为标签("是"/"不是"),Value为元组列表 (句子1, 句子2)
examples_data = {
    "是": [
        # 正样本:同义改写,核心事实一致
        ("公司ABC发布了季度财报,显示盈利增长。", "财报披露,公司ABC利润上升。"),
        ("公司ITCAST发布了年度财报,显示盈利大幅度增长。", "财报披露,公司ITCAST更赚钱了。")
    ],
    "不是": [
        # 负样本:虽然都是金融,但主题完全不同
        ("黄金价格下跌,投资者抛售。", "外汇市场交易额创下新高。"),
        ("央行降息,刺激经济增长。", "新能源技术的创新。")
    ]
}

# 3. 待测试的提问数据
questions = [
    # 测试1:语义匹配("大涨"/"乐观" <-> "持续上涨"/"满意")
    ("利率上升,影响房地产市场。", "高利率对房地产有一定的冲击。"),
    # 测试2:语义不匹配("油价" vs "智能城市")
    ("油价大幅度下跌,能源公司面临挑战。", "未来智能城市的建设趋势越加明显。"),
    # 测试3:语义匹配(情感与事实的一致性)
    ("股票市场今日大涨,投资者乐观。", "持续上涨的市场让投资者感到满意。")
]

# 4. 构建 Messages 列表
# System Prompt: 定义任务、输入格式及输出约束
messages = [
    {"role": "system", "content": "你帮我完成文本匹配,我给你2个句子,被[]包围,你判断它们是否匹配,回答是或不是,请参考如下示例:"},
]

# 动态添加 Few-Shot 示例
# 遍历字典,将正负样本交替或连续加入上下文
for key, value in examples_data.items():
    for t in value:
        # 构造标准化的输入格式:句子1: [...] 句子2: [...]
        user_content = f"句子1: [{t[0]}] 句子2: [{t[1]}]"
        messages.append({"role": "user", "content": user_content})
        messages.append({"role": "assistant", "content": key})

print("🚀 开始金融文本匹配判断测试...\n")

# 5. 循环测试
for i, q in enumerate(questions, 1):
    # 构造当前请求
    current_input = f"按照上述示例,回答这2个句子的情况。句子1: [{q[0]}],句子2: [{q[1]}]"
    current_messages = messages + [{"role": "user", "content": current_input}]
    
    try:
        response = client.chat.completions.create(
            model="qwen-plus",
            messages=current_messages,
            temperature=0.0  # 🔥 关键:设置为0,确保判断逻辑稳定,无随机性
        )
        
        result = response.choices[0].message.content.strip()
        
        # 简单清洗,防止模型输出多余标点
        if result.endswith("。"):
            result = result[:-1]
            
        print(f"[测试 {i}]")
        print(f"句子1: {q[0]}")
        print(f"句子2: {q[1]}")
        print(f"✅ 匹配结果:{result}")
        print("-" * 60)

    except Exception as e:
        print(f"[测试 {i}] 调用出错:{e}\n")

🔍 深度原理解析

1. 为什么需要 Few-Shot 而不仅仅是 Zero-Shot?

虽然大模型本身具备语义理解能力,但在特定领域(如金融)或特定任务(严格二分类)中,Zero-Shot(直接问)可能会出现以下问题:

  • 标准不一:模型可能认为"有点关系"就算"是",而我们需要的是"核心事实一致"才算"是"。
  • 输出格式漂移:模型可能输出"是的,它们匹配"、"匹配"、"True"等多种格式,增加代码处理难度。
  • 负样本敏感度低:如果没有负样本示例,模型可能倾向于对所有金融相关的文本都回答"是"。

通过提供正负样本对,我们明确地向模型展示了"什么样的相似算匹配"以及"什么样的不同算不匹配",校准了模型的判断阈值。

2. 输入格式的标准化

代码中使用了 句子1: [...] 句子2: [...] 的模板。

  • 优势:这种格式具有极强的鲁棒性。即使句子内部包含逗号、句号甚至方括号(只要成对),模型也能清晰地识别出两个独立的输入单元。这对于处理复杂的金融长文本尤为重要。

3. Temperature = 0.0 的决定性作用

文本匹配是一个逻辑判断任务,而非创作任务。

  • 如果 temperature 较高,模型可能会在"是"与"不是"之间摇摆,导致相同的输入在不同次运行中得到不同结果。
  • 设置 temperature=0.0 强制模型选择概率最高的 token,确保判断结果的确定性可复现性

📊 运行结果

运行代码后,您将看到模型能够精准识别语义相似性,忽略表面词汇的差异:

text 复制代码
🚀 开始金融文本匹配判断测试...

[测试 1]
句子1: 利率上升,影响房地产市场。
句子2: 高利率对房地产有一定的冲击。
✅ 匹配结果:是
------------------------------------------------------------

[测试 2]
句子1: 油价大幅度下跌,能源公司面临挑战。
句子2: 未来智能城市的建设趋势越加明显。
✅ 匹配结果:不是
------------------------------------------------------------

[测试 3]
句子1: 股票市场今日大涨,投资者乐观。
句子2: 持续上涨的市场让投资者感到满意。
✅ 匹配结果:是
------------------------------------------------------------

🚀 总结

本案例展示了如何利用大模型构建高精度的语义匹配过滤器,这是提升 RAG 系统效果的关键一步:

  1. 语义理解:超越关键词匹配,真正理解文本背后的含义。
  2. 示例引导:通过正负样本对(Few-Shot),校准模型的判断标准。
  3. 格式规范:使用清晰的分隔符和严格的输出约束,便于工程化集成。
  4. 稳定性控制 :利用 temperature=0 确保逻辑判断的一致性。

在实际的 RAG 流程中,您可以将此模块置于"检索"之后、"生成"之前。只有当匹配结果为"是"时,才将该文档片段作为上下文发送给大模型生成最终答案,从而大幅减少幻觉,提升回答的准确性。

相关推荐
XiaoMaColtAI3 小时前
Math Modeling Skill:我做了一个专门用于数学建模类比赛的 Skill
agent
Tony Bai4 小时前
【AI 智能体时代的软件工程】07 任务工程:告别 Prompt,建立“自治契约”
人工智能·prompt
对许4 小时前
NOTE08
金融
Jackson__4 小时前
Agent Skill 和 Rules 有什么区别?
前端·agent·ai编程
Lw中6 小时前
大模型生成内容出错
人工智能·rag·大模型应用开发
程序员Leo6 小时前
OpenClaw 配置指南:DeepSeek 与 飞书集成
后端·agent
sg_knight7 小时前
OpenClaw 能做什么?几个真实使用场景说明
算法·ai·大模型·llm·agent·openclaw·小龙虾
每天的每一天7 小时前
交易所-域划分的一些思考
金融·系统架构·区块链
xier_ran8 小时前
【第二周】RAG与Agent实战:01提示词工程(Prompt Engineering)核心思想详解
语言模型·prompt