检索与排序模型训练指南

给没有信息检索背景的工程同学:从“为什么要先召回再排序”开始,理解 embedding、reranker、训练数据、loss、负样本、评估指标,以及我们如何把它用在“好故事照片检索”上。

读者:工程同学零背景 场景:相册故事检索 重点:训练思路而非论文复现 建议阅读时长:40-70 分钟
Start Here

0. 先建立直觉:检索和排序不是一件事

如果相册里有 10 万张照片,用户给一张封面图或一个叙事角度,我们最终想找出“最能补出好故事”的几张图。系统通常不会让一个大模型把 10 万张图逐张看完,而是拆成两步。

Retriever:先把可能相关的找出来

它像一个很快的粗筛器。目标是从全相册里找出 top 100 或 top 500 个候选。它更在意“别漏掉可能对的”,所以关注 recall。

  • 输入:query、封面图描述、故事角度
  • 输出:一批候选照片 ID
  • 常见模型:embedding / sparse / multi-vector
  • 优势:快、便宜、可以离线建索引

Ranker / Reranker:再判断谁更值得排前面

它像一个更慢但更细的评审。只看 retriever 给出的少量候选,判断哪张图与封面图之间真的有故事价值。

  • 输入:query、封面、候选、候选间对比
  • 输出:重排后的候选顺序或故事组合
  • 常见模型:CrossEncoder、LTR、LLM judge
  • 优势:判断细关系,上限更高
一句话记住:

Retriever 负责“找到可能的”,Ranker 负责“选出最好的”。训练时也要分开想:retriever 学的是相似空间,ranker 学的是排序偏好。

System View

1. 两阶段系统长什么样

一个典型线上链路可以这样拆。照片本身不一定每次都进模型;更常见的是先离线生成 VLM card,把图像内容变成可检索、可排序的文本和结构化字段。

1. 离线理解图片 用 VLM 给每张图生成人物、地点、动作、场景、时间线索、情绪、事件摘要。
2. 建索引 把 VLM card、story features、时间地点人物字段写进向量索引或倒排索引。
3. 在线召回 根据 query 与封面图,快速拿到 top K 候选,K 通常是 50-500。
4. 精排或重排 用 ranker 看 cover-candidate 的关系,判断事实成立、逻辑成立、是否有叙事收益。
5. 输出组合 去重、多样性控制、成本控制,最后输出 1-3 张补图或一组故事。
为什么不直接用一个大模型端到端做完?

可以做实验,但线上通常太慢、太贵、不可控。拆成 retriever + ranker 后,可以把大部分计算前移到离线索引,把在线大模型调用压到少量候选上。

Retriever Training

2. Retriever 怎么训练

Retriever 的核心目标是:让“同一个检索意图下应该被找到的候选”在向量空间里更近,让不该被找到的候选更远。

Bi-encoder / Dense Embedding

query 和 candidate 分别编码成向量,然后算 cosine 或 dot product。适合大规模检索,因为 candidate 可以提前离线编码。

Sparse / Lexical Retrieval

更像 BM25 或关键词匹配,擅长精准词、名字、地点、OCR、专有名词。常和 dense 混合。

Multi-vector / Late Interaction

不是一张图一个向量,而是多段描述或多个 token 向量。召回更细,但索引和计算成本更高。

Retriever 训练样本长什么样

最常见的数据形式是 anchor、positive、negative。anchor 是检索请求,positive 是应该被召回的图,negative 是不应该被召回的图。

{
  "anchor": "query: 找出这张聚餐照片背后的准备过程。cover: 大家坐在餐桌前举杯。",
  "positive": "candidate: 厨房里有人在切菜,桌上有半成品和餐具。",
  "hard_negative": "candidate: 另一张餐桌合影,人物相同,但没有提供新信息。"
}

常见 loss 怎么理解

Loss 白话解释 适合数据 注意点
Contrastive / InfoNCE 让正样本比一批负样本更靠近 anchor。 大量 anchor-positive 对。 batch 里的其他 positive 会被当作负样本,要小心 false negative。
MultipleNegativesRankingLoss 把同 batch 里的其他样本当负例,工程上很常用。 成对正样本,标注成本较低。 batch 越大通常越好,但显存也更吃紧。
Triplet Loss 要求 anchor-positive 距离小于 anchor-negative,且有一个 margin。 已经有明确正负样本。 负样本太简单,模型学不到东西;太难且有误,会训练歪。
Distillation 让 retriever 学一个更强 teacher/reranker 的打分。 已有强 ranker 或 LLM judge 可批量打伪标签。 teacher 的偏差会被学生继承,需要保留人工评估集。
对我们最重要的点:

如果想让检索阶段更早识别“好故事”,不要只训练“语义相似”。训练目标要包含 information gain、narrative payoff、逻辑关系、人物/时间/地点关系这些 story-aware 正负样本。

Ranker Training

3. Ranker / Reranker 怎么训练

Ranker 的目标不是从全库找候选,而是在同一个 query 的候选列表里,把更好的排在更前面。因此它天然需要“同一个 query 下的候选组”。

Pointwise

每个候选单独打分。比如 0=不成立,1=普通,2=可用,3=好故事。简单、容易起步。

Pairwise

告诉模型 A 比 B 好。更贴近人类偏好,适合从“设为最佳”或人工 winner 转训练样本。

Listwise

直接学习整个候选列表的排序,优化 NDCG 这类排序指标。数据要求更高。

两类 ranker:特征模型和神经模型

Learning-to-Rank 特征模型

输入一堆特征,比如时间距离、人物重合、地点关系、G 模型提取的 story feature,然后用 XGBoost/LightGBM 学排序。

  • 优点:训练快、可解释、CPU 即可
  • 缺点:上限受限于手工特征
  • 适合:先验证哪些 story features 真有用

CrossEncoder 神经 reranker

把 query、cover card、candidate card 放到同一个模型里,让模型通过 cross-attention 看它们之间的细关系。

  • 优点:表达能力强,能理解复杂关系
  • 缺点:在线慢,通常只能重排 top K
  • 适合:训练 I 组偏好模型或 G 的升级版

Pairwise 样本示例

{
  "query_id": "album1_val_021",
  "input": {
    "query": "找出封面图背后更有故事的信息",
    "cover_card": "一个孩子站在舞台中央,台下有人观看。",
    "candidate_a": "后台有人帮孩子整理服装,能解释表演前准备。",
    "candidate_b": "另一张舞台正面照,内容与封面高度重复。"
  },
  "label": "candidate_a > candidate_b",
  "reason": "A 提供了封面没有的新信息,并与封面存在过程-结果关系。"
}
工程直觉:

如果你只是想验证“哪些字段有用”,先训 LTR。要追求故事判断上限,再训 CrossEncoder。要把能力前移到召回层,再用 ranker 的结果蒸馏 retriever。

Data Design

4. 训练数据怎么准备

训练数据不是“每张图一个标签”,而是“某个检索任务下,某张候选图是否能和封面图组成好故事”。同一张图在不同 query 下可能好,也可能不好。

推荐统一样本格式

{
  "query_id": "album1_val_001",
  "album_id": "album1",
  "cover_photo_id": "IMG_1001.JPG",
  "candidate_photo_id": "IMG_2033.JPG",
  "query_text": "给封面图找一张能补充故事背景的照片",
  "story_angle": "过程 / 结果 / 反差 / 关系 / 隐藏上下文",
  "cover_vlm_card": {
    "summary": "封面里三个人在餐桌前合影。",
    "people": ["adult_1", "adult_2", "child_1"],
    "scene": "室内餐厅",
    "visible_event": "聚餐合影"
  },
  "candidate_vlm_card": {
    "summary": "厨房里有人在准备食材,桌上有餐具和半成品。",
    "people": ["adult_1"],
    "scene": "厨房",
    "visible_event": "做饭准备"
  },
  "retrieval_features": {
    "source_method": "B/C/F/G/E",
    "retrieval_rank": 7,
    "retrieval_score": 0.73
  },
  "story_features": {
    "context_grounding": 1,
    "logical_link": 1,
    "intent_alignment": 1,
    "information_gain": 2,
    "narrative_payoff": 3,
    "multi_image_cost": 1
  },
  "human_label": {
    "validity": "成立",
    "story_value_score": 3,
    "failure_reason": "",
    "preference_winner": false
  }
}

从人工标注转成训练标签

原始标注 可转成什么训练信号 用途
validity = 不成立 负样本,pointwise label=0 教模型识别事实不支撑、逻辑不成立的候选。
validity = 成立score = 2/3 正样本或中高分样本 教模型识别可用故事补图。
同组内 A 分数高于 B pairwise:A > B 训练 reranker 的偏好排序。
人工设为最佳 winner 样本,和同组其他候选组成 pairwise 强化“最终更想选哪张”。
failure_reason 错误类型标签 做诊断、分桶评估,也可训练多任务模型。
最小可用标注台:

每个候选只需要三个核心输入:是否成立、故事价值 1-3 分、是否本组最佳。原因和 tag 是加分项,不是第一阶段必须项。

Hard Negatives

5. 负样本为什么关键

检索模型最怕学到“表面相关”。例如候选图和封面图都有同一个人、同一个地点,但它没有新信息,也没有过程、因果、反差或隐藏上下文。

Easy Negative

完全不相关的图。例如封面是生日聚会,负样本是海边风景。太简单,只能教模型基础语义。

Hard Negative

看起来相关但不是好故事。例如同一场生日的重复合影,没有新增信息。

False Negative

被当成负样本,但其实也可以组成好故事。这类样本会伤害训练,要通过人评或规则过滤。

我们该怎么挖 hard negative

  1. 先用 B/C/F/G 或线上 agent 召回 top 50。
  2. 人工或 LLM/reranker 判断哪些“相关但不好”。
  3. 把它们作为 hard negative,而不是随机负样本。
  4. 每个正样本配 3-10 个 hard negatives,早期不用太多。
  5. 每次模型更新后重新挖 hard negatives,因为模型会犯新的错。
训练质量的分水岭:

真正让模型学会“好故事”的,往往不是正样本,而是那些“很像对但其实不好”的负样本。

Story-aware Search

6. 好故事照片检索怎么落地

我们的目标不是复现通用搜索论文,而是找出更适合故事组合的照片。因此训练目标要围绕“故事价值”,而不是只围绕“语义相关”。

哪些能力可以前移到索引

能力 能否前移到索引 原因 实现方式
人物、地点、时间、事件类型 可以 单图就能提取,离线稳定。 结构化字段 + sparse/dense index。
是否提供新信息 部分可以 需要和封面图比较,但候选图可先存“信息类型”。 离线存 feature tags,在线做轻量匹配。
过程 / 结果 / 因果关系 部分可以 候选图可标记为过程或结果,但具体关系依赖 cover。 story role embedding + rerank 校准。
反差、隐藏上下文、叙事 payoff 较难完全前移 高度依赖 cover-candidate 对比和用户意图。 保留给 pairwise reranker 或 LLM judge。
多张图是否值得 不适合完全前移 取决于候选组合之间是否重复。 最后一层做多样性与组合优化。

推荐的长期形态

G/I 产生监督信号 人工分数 + G 的 story feature + 线上 agent 结果,形成训练集。
训练轻量 LTR 先验证哪些 story features 真正预测人评分。
训练 CrossEncoder 学习 cover-candidate 的细粒度故事关系。
蒸馏到 Retriever 把高价值候选拉近,把伪相关候选推远。
线上保留小 rerank 即使前移召回,也保留轻量重排兜底复杂关系。
Model Choices

7. Base Model 怎么选

选模型不要只看榜单。我们的输入是中文/英文混合 VLM card、可能比较长、还要理解故事关系,所以要看多语言、长上下文、训练便利性、推理成本。

模型 适合做什么 为什么 建议
Qwen3-Reranker-0.6B 主 reranker / I 组训练 0.6B、100+ 语言、32k context,适合长 VLM card 和指令式排序。 首选,用 LoRA/QLoRA 起步。
BAAI/bge-reranker-v2-m3 稳定 reranker 对照组 和 bge-m3 检索体系一致,0.6B,工程资料多。 作为 baseline 横评。
BAAI/bge-m3 Retriever / embedding 支持 dense、sparse、multi-vector,适合多语言 VLM card 检索。 继续作为检索基线。
Qwen3-Reranker-4B/8B Teacher / 离线打分 上限更高,但训练和在线成本更高。 先不线上化,用于蒸馏或上限评估。
ColBERT / Late Interaction 高质量多向量检索 比单向量表达更细,适合复杂 query-document 匹配。 数据量更大后再做。
Evaluation

8. 怎么评估训练有没有用

检索和排序要分层评估。一个模型可能 recall 很高,但最后故事质量一般;另一个模型可能 top 1 好,但候选池太窄。

检索层指标

Recall@KMRRNDCG@K。回答:好候选有没有被召回,位置靠不靠前。

故事层指标

pass@2usable@2、人工最佳率、平均故事分。回答:最终给人的组合好不好。

线上指标

延迟、成本、fallback 率、用户采纳、编辑率、重复率。回答:能不能稳定上线。

训练评估的基本纪律

  1. query_id 切 train/valid/test,不要随机按行切,否则同一个 query 泄漏。
  2. 保留一份人工 golden set,不要让 teacher 伪标签污染最终评估。
  3. 评估要同时看 recall 和 story quality,避免只优化一个指标。
  4. 每个方法都记录 latency 和 cost,否则离线好看但线上不可用。
  5. 对失败样本分桶:事实不成立、逻辑不成立、重复、无新增信息、候选池漏召。
Scale

9. 数据量与机器资源

下面是工程上比较现实的估算。真实成本会受 VLM card 长度、batch size、LoRA 配置、GPU 型号影响。

阶段 数据量 机器资源 产出
Smoke Test 200-500 条候选评分 CPU 或本地 Mac 训练轻量 LTR,验证特征方向。
第一版可用 reranker 1000-3000 条候选评分 1 张 24GB GPU,LoRA/QLoRA 0.6B reranker 可初步排序。
稳定 reranker 5000-20000 条候选评分或 pairwise 1-2 张 24GB/48GB GPU 可用于离线重排和线上小流量。
Retriever 微调 10000+ 正样本,每个 3-20 个 hard negatives 24GB 可试,48GB/80GB 更稳 把 story-aware 能力前移到检索层。
多向量 / 图文模型 更大规模图文或 VLM card 数据 多 GPU,索引成本也上升 长期上限探索,不建议第一阶段做。
当前我们的位置:

现有人工标注适合先训/验证轻量 LTR,不适合直接微调 embedding 上线。下一步最值得补的是更多 query group 的人工偏好数据。

Learning Plan

10. 推荐学习与落地路线

如果你是零背景工程同学,建议不要从论文公式开始。先按下面路径学习,每一步都能对应到工程产物。

第 1 天:理解系统分层

看懂 retriever、ranker、candidate pool、top K、Recall@K、NDCG。产物:能画出我们的线上链路。

第 2 天:理解训练数据

把人工 CSV 转成 pointwise、pairwise、hard negative 三种数据。产物:一个训练集 JSONL。

第 3 天:训轻量 LTR

用 XGBoost/LightGBM 学 story features。产物:特征重要性、valid NDCG、失败样本分析。

第 4-5 天:跑 CrossEncoder baseline

用 Qwen3-Reranker-0.6B 或 bge-reranker 做 zero-shot/少量 LoRA。产物:和 G/F/B/C 的对比。

第 2 周:扩大标注与 hard negative

每个 query 标 5-10 个候选,累计 1000-3000 条。产物:第一版稳定 reranker。

第 3-4 周:蒸馏到 retriever

用 reranker 给候选池打伪标签,再训练 story-aware embedding。产物:更好的 Recall@K 和更低 rerank 压力。

References

参考资料:按学习顺序看

Sentence Transformers:Embedding Loss Overview

学习 MultipleNegativesRankingLoss、Triplet Loss、embedding 训练格式。

打开文档

Sentence Transformers:CrossEncoder Training

学习 reranker 训练、hard negative mining、query-document pair 格式。

打开文档

XGBoost Learning to Rank

学习 qidrank:ndcg、LambdaMART 排序训练。

打开文档

BGE-M3

了解 dense、sparse、multi-vector 三种检索能力如何统一在一个 embedding 模型里。

打开模型页

Qwen3-Reranker-0.6B

了解我们建议作为 I 组主 reranker base 的模型规格和用法。

打开模型页

BGE Reranker v2 M3

适合作为 reranker baseline,与 bge-m3 检索体系对照。

打开模型页

ColBERT

理解 late interaction 和 multi-vector retrieval 的经典做法。

打开论文

Dense Retrieval 里的 False Negative 问题

理解为什么 hard negative 质量会影响 embedding 训练。

打开论文