Feedback-Learning-RAG

离线集覆盖不了线上真实问法,同一类失败会重复出现。根因是没有把点踩/纠错变成训练与硬负例。本方法从日志构造样本再更新检索或重排。标注噪声会放大,需与 Benchmark 回归一起门禁。

本文属于 RAG 工程框架中的「5 在线运营与成本治理」环节,聚焦「Feedback Learning(反馈学习)」方法。

定位

维度 内容
角色 日志 → 硬负例 / 微调
输入 → 输出 点踩日志 → 训练样本 → 灰度模型
默认组合 LangSmith / Phoenix 采集 → 离线训练
何时不用 流量极低、标注不可信

核心机制

从日志挖 $(q,d^+,d^-)$,更新后必须过冻结 Benchmark 再灰度。

实现路径与心智:点踩、纠错、改写日志变成对比样本,更新检索/重排后灰度。底层心智:线上失败分布才是真训练集,离线评测集只是代理。不能「有反馈就立刻全量」。

优缺点

  • 优点:打到真实长尾。
  • 缺点:噪声标签会放大错误。

契约与走通样例

输入

1
{"log": {"q": "siRNA 多久", "shown": "C-review", "user": "thumbs_down", "correct": "C-48h"}}

中间量

硬负例:$(q, d^+=C\text{-}48h, d^-=C\text{-}review)$。微调后该问 rank 从 7 到 2。回归集 Recall@5 未掉。

输出

1
{"samples_added": 1, "gate": "pass", "rollout": "5%"}

社区实现

LangSmith / Arize Phoenix。风险:把「答得太长」点踩当成检索负例。

工程落地

最小可运行示例

复制为 .py 后直接运行(仅标准库)。点踩不一定是检索错误;只有「金标准未进 Top-k」才进硬负例。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
"""从日志挖硬负例,离线回归不过则拒绝训练。"""
from __future__ import annotations

from dataclasses import dataclass


@dataclass
class ClickLog:
"""一条在线反馈。生产对应埋点表。"""

query: str
shown: list[str]
gold: str
thumbs_down: bool


def build_hard_negatives(logs: list[ClickLog]) -> list[tuple[str, str, str]]:
"""输出 (query, positive, negative)。风格点踩不进入。"""
rows = []
for log in logs:
if not log.thumbs_down:
continue
if log.gold in log.shown:
continue
neg = log.shown[0] if log.shown else ""
if neg:
rows.append((log.query, log.gold, neg))
return rows


def regress(dev_pairs: list[tuple[str, str, str]], new_pairs: list[tuple[str, str, str]]) -> bool:
"""教学用:新样本不得冲掉 dev 查询。生产对应 Benchmark 门禁。"""
dev_q = {q for q, _, _ in dev_pairs}
return any(q in dev_q for q, _, _ in new_pairs)


def feedback_to_train(logs: list[ClickLog], dev_pairs: list[tuple[str, str, str]]) -> list[tuple[str, str, str]]:
rows = build_hard_negatives(logs)
if regress(dev_pairs, rows):
raise RuntimeError("offline gate failed")
return rows


if __name__ == "__main__":
logs = [
ClickLog("GAPDH 时程", ["P-review"], "P-GAPDH-01-C1", True),
ClickLog("GAPDH 时程", ["P-GAPDH-01-C1"], "P-GAPDH-01-C1", True), # 金标准已在,忽略
]
print(feedback_to_train(logs, dev_pairs=[("unrelated", "a", "b")]))

参数

参数 起点 影响
负例来源 点踩+明确纠错 不要把风格点踩当 $d^-$
灰度 5% 起 全量前看护栏

失效—信号—螺丝

  • 噪声标签:螺丝:人工抽检、过滤非检索点踩。
  • 过拟合线上几天:螺丝:锁盲测集。
  • 跳过回归:螺丝:强制 Benchmark 门禁。

规模(100 篇生物学 PDF)

一轮构造+微调约 2–12 GPU·h(视自动化)。训练 GPU 16–24 GB

-------------本文结束感谢您的阅读-------------