多模态检索不是一个问题
“多模态 RAG”通常把多个任务混在一起:
- 文本查图:“找到带红色急停按钮的产品照片。”
- 图片查文:“找到解释这张警告标志照片的手册章节。”
- 视觉文档检索:“找到包含季度利润率图表及脚注的页面。”
- 精确文本检索:“找到发票
ACME-2026-00417。” - 混合证据检索:“结合接线图、参数表和修订说明解释操作步骤。”
单个索引无法天然解决全部问题。全局图文向量擅长识别大范围视觉语义,却可能漏掉很小的编号;OCR 加 BM25 能找到编号,却可能丢失版面关系;页面图像延迟交互保留更多视觉结构,但索引内存更高,后续仍要设计证据提取。
生产目标不是“把图片放进向量数据库”,而是:
检索有权限、带版本、包含足够图文上下文的证据,并让最终答案可核验。
需要先了解整体流程时,可阅读多模态 RAG 入门与架构指南。本文专注检索设计和评测。
三条互补检索路径
路径 A:图文共享向量空间
CLIP通过对比学习把图片和自然语言描述映射到共享表示空间。类似双编码器可支持:
- 文本查询图片;
- 图片查询文字;
- 通过对齐空间执行以图搜图或 Caption 相似搜索;
- 每个资产只保存一个全局向量,快速执行 ANN 召回。
优势:
- 索引和候选生成效率较高;
- 擅长宽泛语义匹配;
- 适合照片、商品、场景和插图;
- 文本查图与图片查文路径对称。
局限:
- 小字、精确编号、表格和细粒度空间关系可能被压缩进一个向量;
- 分数会随模型、预处理、语言和语料变化;
- 视觉相似不等于能够支持用户所问事实。
CLIP 是模型家族与训练方法,并不保证所有衍生 Checkpoint 的许可证、语言支持、输入尺寸和分数校准完全相同。
路径 B:视觉文档延迟交互
ColPali发表于 ICLR 2025。它将文档页面图像编码成多个向量,再让 Query Token Vector 与 Page Vector 做延迟交互。简化相关性函数为:
score(query, page) =
对每个 query vector i 求和 (
在所有 page vector j 上取 max similarity(query_i, page_j)
)
与每页单向量检索不同,不同 Query Token 可以匹配页面的不同视觉区域,因此能够保留表格、图形、字体和版式信号。
ColPali 论文还引入 ViDoRe 视觉文档页面检索基准,并在论文指定数据集和协议下报告了很强的结果。但论文不能证明任意 ColPali Checkpoint 都优于所有 OCR 流水线,更不能推出“任何环境索引快 3 倍”或“2026 年最佳模型”。
实际代价:
- 每页多向量会提高索引内存;
- 候选评分比单向量余弦检索更昂贵;
- 页面级召回后仍需区域定位或证据提取;
- 精确文本与策略过滤仍可能依赖 OCR 或元数据;
- 索引端与查询端的模型、预处理版本必须一致。
路径 C:文字、版面与元数据检索
OCR 并未过时,它提供视觉向量无法保证的能力:
- 精确 ID、金额、日期、条款和错误码;
- Phrase 与 Boolean Search;
- 确定性语言或文档类型过滤;
- 文本高亮和无障碍输出;
- 脱敏与合规复核;
- 可引用的词法证据。
一条实用文字路径可以包含:
- 带 Bounding Box 和 Confidence 的 OCR Token;
- PDF 等文档原生文字;
- BM25 或其他词法检索;
- Text Embedding;
- Layout-aware Chunk;
- 文档元数据与 ACL 字段。
不要在无记录的情况下静默偏好 OCR 或原生 PDF Text。应保存来源类型与抽取版本,评测才能定位具体失败路径。
生产检索架构
摄取
-> 不可变资产 ID 与版本 ID
-> 页面渲染与图片 Hash
-> 原生文本 / OCR 与 Region
-> 元数据与 ACL 规范化
-> 图文全局向量
-> 页面多向量
-> 词法 / 文本向量
查询
-> 身份与权限过滤
-> 查询分类
-> 多路径并行召回
-> 各路径 Top-k 与 Provenance
-> 排名融合或校准融合
-> 可选的证据感知重排
-> 页面 / Region 证据包
-> 生成答案
-> 引用与支持度验证
权限必须在召回前生效
Tenant、用户、Legal Hold、地区与文档状态过滤应进入 Candidate Generation,而不是在排序后处理。先召回再过滤会:
- 通过延迟或结果数量泄露对象存在;
- 导致返回条数不足;
- 让无权候选影响 Reranker 或生成模型;
- 污染缓存和 Trace。
每条结果应携带授权决策或 Query Scope ID,做到可审计但不在日志中泄露正文。
所有表示共享同一证据身份
同一页的不同表示必须关联同一个 ID:
{
"asset_id": "manual-42",
"version_id": "sha256:...",
"page": 17,
"region_id": "p17-r08",
"source_uri": "s3://approved/manual-42.pdf",
"render_hash": "sha256:...",
"native_text_version": "pdf-parser-4.2",
"ocr_version": "ocr-7.1",
"image_encoder": "clip-checkpoint@digest",
"page_encoder": "colpali-checkpoint@digest",
"acl_scope": "tenant-7:engineering",
"indexed_at": "2026-10-03T08:00:00Z"
}
如果没有共享身份,同一页面会作为三个无关候选进入上下文。应在分配最终 Context Budget 前,按证据身份去重。
不要直接平均原始分数
BM25、Cosine Similarity 与 Late Interaction MaxSim 的量纲和分布不同。即使都是余弦分数,不同模型也可能使用不同归一化、维度和训练目标。下面公式没有校准证据时是无效的:
final = 0.4 * bm25 + 0.3 * clip_cosine + 0.3 * colpali_maxsim
这些 Weight 看起来精确,却没有稳定含义。
Reciprocal Rank Fusion
Reciprocal Rank Fusion使用候选位置而不是原始分数:
RRF(document) = 对所有 ranker r 求和 (weight_r / (k + rank_r(document)))
当多个 Retriever 分数不可比时,RRF 是可靠基线。它不要求 Score Calibration,也不会让某个异常大的原始分数独占结果。但常量 k、路径权重、Candidate Depth 与去重规则仍需评测。
Go 实现
package main
import (
"fmt"
"sort"
)
type RankedItem struct {
ID string
}
type FusedItem struct {
ID string
Score float64
}
func reciprocalRankFusion(
lists [][]RankedItem,
weights []float64,
k float64,
) []FusedItem {
scores := make(map[string]float64)
for listIndex, items := range lists {
weight := 1.0
if listIndex < len(weights) {
weight = weights[listIndex]
}
seen := make(map[string]bool)
for itemIndex, item := range items {
if item.ID == "" || seen[item.ID] {
continue
}
seen[item.ID] = true
rank := float64(itemIndex + 1)
scores[item.ID] += weight / (k + rank)
}
}
fused := make([]FusedItem, 0, len(scores))
for id, score := range scores {
fused = append(fused, FusedItem{ID: id, Score: score})
}
sort.Slice(fused, func(i, j int) bool {
if fused[i].Score == fused[j].Score {
return fused[i].ID < fused[j].ID
}
return fused[i].Score > fused[j].Score
})
return fused
}
func main() {
lists := [][]RankedItem{
{{ID: "page-17"}, {ID: "page-8"}, {ID: "page-31"}},
{{ID: "page-8"}, {ID: "page-17"}, {ID: "page-22"}},
}
for _, item := range reciprocalRankFusion(lists, []float64{1, 1}, 60) {
fmt.Printf("%s %.6f\n", item.ID, item.Score)
}
}
代码中的 Duplicate Guard 防止单个 Retriever 重复返回同一文档来提高分数。生产结构还应携带 Path、Rank、Raw Score、Evidence Version 和 ACL Scope。
何时使用校准或学习式融合
只有具备代表性标签时,才使用校准分数或 Learning-to-Rank。特征可以包括:
- 各路径 Rank 与 Score;
- OCR Confidence;
- Query Type;
- Language 与 Document Class;
- 图片质量;
- 多路径一致性;
- 时效与版本匹配。
训练和测试应按文档或时间分割,避免近重复泄漏。如果同一模板同时进入 Train 和 Test,Fuser 可能看似准确,却在新供应商、新语言或新扫描类型上失败。
避免脆弱的查询路由
Router 可以节省费用,但也创造新的召回失败。先使用可解释策略:
| Query 信号 | 候选路径 |
|---|---|
| 精确编号、引号短语、金额 | 词法 + Text Embedding |
| 视觉属性或场景 | 图文共享向量 |
| 表格、图表、表单、版面关系 | 页面延迟交互 + OCR |
| 图片查询 | Image-to-image / 共享空间 |
| 含糊混合请求 | 所有有权限路径,再融合 |
记录实际选择路径,并评估 Router Recall:路由是否排除了唯一包含相关证据的路径?如果低成本 Router 系统性漏掉少数语言或扫描文档,它没有节省真实成本。
为生成阶段打包证据
检索结果不能只是一组 Vector,应生成证据包:
{
"evidence_id": "manual-42@sha256:...#page=17®ion=p17-r08",
"retrieval_paths": [
{"name": "bm25", "rank": 4},
{"name": "colpali", "rank": 1}
],
"page_image": "signed://...",
"region": {"x": 0.14, "y": 0.28, "width": 0.62, "height": 0.31},
"text": "经过审批的 OCR 或原生文本片段",
"source_title": "Pump Service Manual",
"revision": "2026-08-14",
"acl_scope": "tenant-7:engineering"
}
生成模型只能接收有权限证据,并获得足够邻近上下文来理解 Region。最终引用应指向 Evidence ID,不能使用模型临时生成的页码标签。
图表和表格应同时保留 Page Crop 与文字。OCR 可能展平行列关系,只有图片又难以精确引用;两者组合通常更有价值。
检索评测
标签单位必须匹配产品
- 媒体搜索使用 Asset Level;
- 视觉文档检索使用 Page Level;
- UI 需要高亮时使用 Region Level;
- 必须联合多页回答时使用 Evidence Set Level。
语料存在多个合理结果时,应标注多个 Relevant Item。Hard Negative 应来自同一模板、产品家族、月份或相似版面,而不是只用明显不相关文档。
必须覆盖的 Query 切片
- 模态:Text-to-image、Image-to-text、Text-to-page、Mixed;
- 内容:照片、示意图、图表、表格、表单、密集正文;
- 文字质量:原生文字、清晰 OCR、劣化扫描、手写;
- 语言与文字系统;
- 精确编号与语义描述;
- 单跳与多证据;
- 现行文档与废弃版本;
- 高频与稀有模板;
- 有权与无权证据;
- 正常内容与 Prompt Injection。
一个全局平均数可能掩盖高风险切片的零召回。
检索指标
| 指标 | 回答的问题 |
|---|---|
| Recall@k | 候选集合中是否包含相关证据? |
| MRR | 第一个相关结果出现得多早? |
| nDCG@k | 分级相关结果是否排序合理? |
| Precision@k | 上下文预算中有多少内容真正有用? |
| Duplicate Rate | 多种表示是否浪费 Slot? |
| Unauthorized Candidate Rate | 无权证据是否进入排序? |
| Stale-version Rate | 是否选择了已废弃版本? |
样本量允许时应报告置信区间或 Bootstrap Range。每份报告都要固定 Corpus Snapshot 以及准确 Encoder/Index 配置。
端到端 RAG 指标
检索质量和答案质量必须分开:
- Evidence Sufficiency;
- Citation Precision 与 Recall;
- Claim-to-evidence Entailment;
- Unsupported Claim Rate;
- 证据不足时拒答;
- 精确字段准确率;
- 视觉 Region 归因;
- 每个有证据答案的延迟与成本。
即使 Recall@k 很高,流畅回答也可能没有依据;反过来,召回缺失也不能靠更强生成模型稳定补救。
更完整的框架参见 RAG 评测指南,文本检索调优可参考混合检索与重排序指南。
运行指标
质量不是唯一门禁:
| 阶段 | 需要记录的运行证据 |
|---|---|
| 摄取 | Pages/Minute、失败、OCR Confidence、渲染确定性 |
| 索引 | Vectors/Page、Bytes/Page、构建时间、Peak Memory |
| 检索 | p50/p95/p99、Candidate Depth、Cache Hit |
| 重排 | Batch Size、加速器内存、Timeout Rate |
| 生成 | Evidence Token、Image Token、Unsupported Claim |
| 时效 | Source-to-searchable Delay、Stale-version Rate |
| 成本 | 每索引页、每查询、每有证据答案 |
没有 Checkpoint、精度、Batch Size、页面分辨率、向量数、硬件与软件版本,就不应发布固定 VRAM 或延迟需求。
漂移与变更管理
“对齐漂移”应表示可测变化,而不是所有搜索质量下降的通用解释。需要监控:
- 各切片 Query 分布;
- 语料中的语言、模板与图片质量;
- OCR 与 Renderer 版本;
- Embedding Checkpoint 与 Preprocessing;
- Index 参数与 Quantization;
- 固定 Canary Set 的各路径 Recall;
- Score 与 Rank 分布;
- 多路径分歧;
- Unsupported Answer Rate。
用新 Encoder 重建索引,却继续用旧 Encoder 查询,是明确合约错误。应使用版本化索引、Dual-read 评测和原子流量切换。
Model、OCR、Rendering、Chunking、Fusion 或 ACL 任一变化,都应触发新评测。回滚时恢复完整兼容的 Index 与 Query Stack,不能只回滚一个组件。
安全与隐私
多模态证据可能包含:
- 可见个人信息或业务秘密;
- 隐藏 PDF Layer;
- EXIF 与文档元数据;
- 二维码和嵌入 URL;
- 文字或像素中的 Prompt Injection;
- 针对 Parser 的恶意文件;
- 跨租户近重复内容。
控制措施:
- 在隔离摄取环境扫描和规范化文件;
- 删除不需要的元数据;
- 严格控制原件访问,只索引经过批准的派生物;
- Candidate Generation 前执行 ACL;
- 把 OCR 和图片中的指令视为不可信证据;
- 绝不根据检索内容授予工具权限;
- 对日志和评测导出脱敏;
- 删除传播到派生物、索引、缓存与备份;
- 验证 Signed Evidence URL 具有短有效期并绑定租户。
选型清单
不要先问“哪个模型最好”,先回答:
- 检索单位是 Asset、Page、Region 还是 Evidence Set?
- 需要哪些 Query Direction?
- 哪些语言、版面和扫描质量重要?
- 精确标识是否属于业务关键路径?
- Index Memory 与 p95 Latency 上限是什么?
- 数据能否离开部署边界?
- 数据更新后多久必须可搜索?
- 哪些标注切片和失败成本决定验收?
然后至少比较:
- Lexical/Native-text Baseline;
- Text Embedding Baseline;
- Global Image-text Embedding Baseline;
- 场景需要时加入 Page-image Late Interaction;
- Rank Fusion Baseline;
- 标签充分后再引入 Learned Reranker。
Embedding 向量指南解释向量行为,多模态图文流水线指南覆盖上游图像与文字处理。
一手资料
- CLIP:从自然语言监督中学习可迁移视觉模型
- Sigmoid Loss for Language Image Pre-Training
- ColPali:使用视觉语言模型进行高效文档检索
- ViDoRe 基准与模型
- Reciprocal Rank Fusion 论文
总结
生产级多模态 RAG 需要多份明确合约:每种表示负责召回什么证据,不可比分数如何融合,每个页面或 Region 如何追溯到带版本来源,哪个权限过滤生效,以及哪套标注评测可以证明变更。CLIP 类共享向量、ColPali 类延迟交互与 OCR/词法检索是互补工具。真正合适的是满足实测业务约束的系统,而不是附带最大未经验证提升数字的模型。