AI 基建
0%
第十一部分 · 实践与运营 · 第 86 章

检索与文档智能

作者Changkun Ou
阅读时长约 13 分钟

模型要和它从未训练过的数据对话,靠的是检索;而决定哪些数据能到达模型面前的,是文档智能这道前门。实践层接在 第 44 章第 46 章 之下:那两章讲检索为何有效、上下文窗口如何组装,这里处理 2026 年的工具选择与接线。这两半其实是同一条流水线:一份 PDF 变成结构化文本,结构化文本变成向量库里的嵌入,一次查询把对的分块取回来,重排器在它们进入提示词之前排好序。上游任何一处出错,都会悄无声息地污染下游的一切。

2026-06-21T23:30:35.323894 image/svg+xml Matplotlib v3.11.0, https://matplotlib.org/ 0.0 0.2 0.4 0.6 0.8 1.0 可回答证据保留量 解析 分块 嵌入 检索 引用
图 86.1. 文档智能流水线的示意图。解析、分块、嵌入、检索与引用每一步都会丢弃一些证据,因此早期结构很重要。理想化保留证据,非实测。
截至 2026 年中

这是一份带日期的快照(2026-06)。下文每一个排名、价格、版本号与基准分数都易变、都标了来源,其中许多出自厂商博文或混用多版本的聚合站点,彼此并不一致。请把它们当作方向性参考,先采纳那些更持久的判断(类别、权衡、如何选、如何接),引用具体数值之前对照一手来源核实当下的值。

流水线,以及为何解析质量先决定上限

这条流水线从摄取开始。图 86.2 画出了从原始文档到回答的整条路径。

cluster_Ingest 摄取 离线 cluster_Query 查询 在线 D 文档 PDF 扫描件、Office 文件 P 解析与 OCR VLM 或流水线 D->P X 结构化抽取 符合模式的对象 P->X C 分块与嵌入 P->C VDB 向量库 X->VDB C->VDB F RRF 融合 VDB->F Q 用户或智能体查询 H 混合检索 Q->H H->VDB RR 重排 F->RR CTX Top-k 上下文 RR->CTX LLM 生成器或智能体 CTX->LLM A 回答 LLM->A EVAL 评估 RAGAS 或 LangSmith EVAL->H EVAL->RR EVAL->A
图 86.2. 检索与文档智能流水线,从原始文档到有依据的回答。摄取在离线,查询在在线,评估观测两者。

顺序之所以要紧,是因为最大的数据丢失和最安静的错误都发生在解析这一步,而不是检索那一步。双栏的一页若被压平成交错的行,财务表若被打碎成散文,下游再好的嵌入模型和重排器也救不回这些结构。到 2026 年中,向量库本身已接近通用商品:近似最近邻搜索(HNSW、IVF、DiskANN 的各种变体)随处可见,很少成为瓶颈。差异化已经转移到三处,前端的解析质量、中间的嵌入与重排质量,还有底层的成本架构(内存常驻还是对象存储)。我们就按流水线顺序处理这两半,先文档智能,再检索栈。

下层约束

无论生成器多强,检索器都为回答的忠实度封了顶,而解析器又为检索器封了顶。功夫花在这里,胜过其上几乎任何提示词或模型层面的改动。第二条约束来自下层:一旦智能体(第 85 章)把检索当工具用、每个任务里调用许多次,单次查询的延迟与成本就不再是事后才想的事,而成了设计约束,这正是对象存储那条成本曲线值得在意的原因。

文档智能:从凌乱文件到干净数据

文档智能把 PDF、扫描件、截图或 office 文件转成机器可读的结构:按阅读顺序排好的文本、按单元格拆开的表格、以 LaTeX 表示的公式、键值对,最终落成一个遵循模式的有类型对象。到 2026 年,这一领域分成了三个架构阵营,外加一个横切关注点。

  1. 经典 CV 与 光学字符识别(OCR) 流水线。 这里的 OCR 是从像素里识别文字,再放进多阶段流程:版面检测、OCR、表格重建、阅读顺序组装。确定性强、可调试、快,但碰上异常版面就脆。Marker、MinerU、PaddleOCR、unstructured 与各家云 API 都属此类。
  2. 端到端文档 VLM。 单个图文到文的模型一次性吐出整篇结构化文档(Markdown、HTML 表格、LaTeX)。它们主导着开放榜单,通常很小(sub-2B),还能和对话模型部署在同一套服务集群上(第 82 章)。跑起来更省事,但它丢掉一列时也更难查。
  3. 智能体文档平台。 托管服务把 OCR、视觉语言模型(VLM)(用图像和文本一起解析页面的模型)、纠错回路与结构化抽取一并封在 API 和 SLA 之后。用自托管,换来困难文档上的准确率与合规性。

贯穿这些路径的关注点是结构化抽取:从解析后的文本,走到一个遵循 JSON Schema 的有类型对象。约束解码与校验库,正是在这里与解析交汇。

下表是浓缩视图,版本与许可的细节放在一手来源里。

工具 阵营 许可 / 部署 何时选它
Docling (IBM) 流水线工具包 MIT 工具包,Apache-2.0 模型,自托管 想要一条许可宽松、开箱即用、输出对 RAG 友好、OCR 可替换的 OSS 流水线
Granite-Docling-258M 端到端 VLM Apache-2.0,自托管 Docling 内成本高效的自托管转换;许可最宽松;可容忍边缘部署
PaddleOCR-VL (Baidu) 端到端 VLM Apache-2.0,自托管 当能部署 VLM 时,开源整页解析中同类最佳的准确率
dots.ocrDeepSeek-OCRMinerUGLM-OCR 端到端 VLM Apache-2.0(核对权重),自托管 自托管的版面感知解析;DeepSeek-OCR 用于超高吞吐
Mistral OCR 3 托管 OCR 模型 商业 API,可按需自托管 想要扁平的低单页价、一个欧盟厂商,外加一条自托管的逃生通道
Reducto 智能体平台 商业 SaaS + 本地部署 对抗性强的企业文档(密集表格、手写、表单),且有 SOC 2 / HIPAA / 零留存需求
LlamaParse / LlamaCloud 智能体平台 托管 SaaS,按额度计费 已在用 LlamaIndex,想要分级的解析质量(Fast 到 Agentic Plus)外加抽取
Lectio(latere.ai) 智能体平台 作者自己的;托管 Latere 技术栈的一个示范案例(第 75 章):逐页实时解析,且每个元素都能回溯到原文出处。已披露为作者自己的;仅作示范,并非中立推荐
unstructured 流水线 + 托管 Apache-2.0 + 托管 难点是格式繁杂(数百种来源类型),而非某一份最难的 PDF
Azure / AWS / Google doc-AI 云文档 AI 托管,按页计费 深耕某朵云,想要预置抽取器与免费层,又不愿做模型运维
Marker / Surya (Datalab) 流水线 代码 OSS,权重 OpenRAIL-M 带营收上限 研究、个人或小创业用途;商用前先读权重许可

表里刻意漏掉了一个选项。Gemini Flash 或 Pro 这类通用前沿 VLM,不搭任何流水线也能很好地解析页面,它是 2026 年多数对比里的基线。它的单页成本高于专用的小型 OCR VLM,碰上密集表格还可能产生幻觉或悄悄丢内容。所以「直接把页面发给前沿 VLM」是个真实而简单的选项,该拿它跟前述专家对标,而不是直接当默认。

还有一种更彻底的设计,干脆跳过解析。ColPali 一路的视觉检索,用视觉语言检索器直接嵌入页面图像,再用后期交互匹配来打分(与下文检索一节针对文本描述的是同一种机制),最后把检索到的页面交给一个直接读像素的 VLM 生成器 (Faysse et al. 2024);Cohere Embed v4 的图像模式以单向量嵌入走的也是这条路。到 2026 年,这已是视觉密集语料的一条标准备选,它也给「解析质量领跑」加了一个限定:既然不解析,上游就没有环节能给检索器封顶。不过代价只是挪了位置,并没有消失:页面图像嵌入的存储与查询更贵,生成器必须是 VLM,而结构化抽取、带出处的引用,以及语料的任何纯文本复用,仍然离不开解析。

结构化抽取

页面一旦解析完,把它变成有类型对象就是一个正交的选择,只沿一条轴展开:解码器在不在自己手里?

机制 何时选它
Outlines / XGrammar 服务器内的约束解码(guided_json 在 vLLM/SGLang 上自托管,想要硬性的模式保证、零事后解析
Instructor 在 provider SDK 之上做 Pydantic 校验与自动重试 调用托管模型,想要简单的校验与重试
BAML 对近似 JSON 的输出做 Schema-Aligned Parsing 模型返回畸形但接近的 JSON,想要提示词纪律加上宽容的解析

选择解析器

决策有四条轴:文档难度、自托管还是 API、体量与成本、合规。

  • 自托管文档 VLM(PaddleOCR-VL、dots.ocr、DeepSeek-OCR、Granite-Docling、MinerU),当能跑 GPU、不想要按页账单、需要数据留在自己的 VPC、且文档属于「正常难度」时:学术论文、报告、图文混排。把它们部署在 vLLM/SGLang 上,约束解码也能一起接入。
  • Docling 工具包作为最稳的纯 OSS 默认:一条许可宽松、输出对 RAG 友好、可换入 Granite-Docling 的流水线。
  • Mistral OCR 3,当想要一个扁平低单页价(据 Mistral 2025 年 12 月,约每 1k 页 2 美元,批处理约半价)、又是欧盟厂商的托管 API 时。
  • Reducto 或 LlamaParse Agentic,当文档确实对抗性强、准确率比单页成本更要紧、且想要现成的纠错回路、SLA 与合规而不必自建时。
  • unstructured,当问题出在格式繁杂,而非某一份最难的 PDF。
  • 云文档 AI(Azure、AWS、Google),当已在某朵云内,或需要某个特定的预置抽取器(发票、收据、证件、信贷)时。

当约束解码就在服务器内部时,一次自托管的解析加上符合模式的抽取,就是一个请求:

# vLLM / SGLang 兼容 OpenAI 的调用:模式约束抽取
resp = client.chat.completions.create(
    model="paddleocr-vl",                 # 本地部署在 vLLM 上
    messages=[{"role": "user", "content": [
        {"type": "image_url", "image_url": {"url": page_png_data_uri}},
        {"type": "text", "text": "Extract the invoice as JSON."}]}],
    extra_body={"guided_json": Invoice.model_json_schema()},  # Outlines / XGrammar
)

检索栈:向量库、嵌入、重排、混合检索

嵌入(或者说向量)就是一串数字,用来抓住一段文本的语义,于是语义相近的文本在这个数字空间里彼此靠近,整套栈都搭在这一个想法之上。向量库的周围还坐着另外三块:把文本(以及越来越多的图像与 PDF)转成向量的嵌入模型、为求精度而给候选集重新打分的重排器,以及把摄取、分块、检索、融合与提示词组装接到一起的 RAG 框架。

向量库

第一个问题几乎总是:是不是已经在跑 Postgres?下表是浓缩的,基准与定价的细节放在一手来源里,且这些数据全是厂商自报、对版本敏感。

是什么 许可 何时选它
pgvector (+ pgvectorscale) 带 HNSW/IVFFlat 的 Postgres 扩展;pgvectorscale 加上磁盘常驻的 StreamingDiskANN 与标签过滤 OSS (PostgreSQL) 已在跑 Postgres,语料在数千万向量以内。多数 RAG 的正确默认
Qdrant Rust 原生向量库;强过滤、量化、ACORN Apache-2.0 + 云 不在 Postgres 上,想要快速的自托管引擎,还需要大量元数据过滤与数据驻留
Weaviate 原生向量库,自带原生混合检索(BM25 + 向量)与内建向量化模块 BSD-3 + 云 想要内建的混合检索与嵌入生成,少写胶水代码
Milvus / Zilliz 分布式、存算分离、十亿级;Zilliz 是托管云 Apache-2.0 + 托管 确实身处数亿到数十亿向量,且有运维能力
Pinecone 托管 serverless;为重读负载提供 Dedicated Read Nodes 专有 SaaS 想要全托管、愿为零运维付费、看重可预测的扩展
Turbopuffer 基于对象存储、带缓存的托管向量 + 搜索 专有 SaaS 规模成本主导,数据多为冷且突发,或租户/命名空间数量很大
LanceDB 基于 Lance 列式格式的进程内嵌入式库;多模态 Apache-2.0 + 云 边缘、桌面、notebook,或那些运行服务器属于负担的多模态流水线
Chroma 轻量 OSS 库,开发体验优先 Apache-2.0 + 云 原型或小型 RAG,简单比规模更要紧(先验证上限)
Vespa / Elasticsearch / OpenSearch 带向量支持的完整搜索引擎 Apache-2.0 / Elastic 检索其实是搜索(复杂排序、推荐),或已在运营其中之一

这些选型背后的权衡,即便产品本身一直在迭代也仍然持久。**单一系统还是原生向量库:**带向量的 Postgres 少了一个活动部件(运维、备份、一致性、连接),代价是峰值 ANN 吞吐有所损失,对多数团队这笔交易是划算的。**内存还是对象存储:**经典向量库把工作集放在内存(快、贵),对象存储优先的设计(Turbopuffer,以及 pgvectorscale 与 Milvus 里磁盘常驻的 DiskANN)则以一点延迟,换来大型或冷语料上低得多的成本。**托管还是自托管:**托管换来零运维与可预测的扩展,自托管换来成本掌控、数据驻留,以及没有单次查询的加价。**规模下的过滤:**如果多数查询是「向量搜索,但只限于这个租户、这个日期范围或这个权限集」,那么带过滤的召回与带过滤的延迟,就比原始 ANN 速度更要紧,Qdrant(ACORN)和 pgvectorscale(标签过滤)正是为此而造。

嵌入与重排

数据库返回的,是嵌入模型当初编码下的内容,而重排器负责修正顺序。功夫花在这里,通常胜过换数据库。把嵌入模型当作一等的、带版本的依赖来看:换它,就意味着对整个语料重新嵌入。

下文的 MTEB 与 MMTEB 分数,在不同榜单或版本间不可直接比较(英文榜、多语榜,以及旧版与现版的任务集,用的是不同的任务数),所以更高的数字未必就更适合自己的用例。这里的备注是方向性的。

模型 厂商 开源 / API 备注(截至 2026)
OpenAI text-embedding-3-large / -small OpenAI API 无聊但安全的默认;支持广泛,Matryoshka 维度截断(嵌入经过专门训练,只留前 k 个数字也仍能检索得很好);-small 便宜,对许多应用够用
Cohere Embed v4 Cohere API 多模态(文本 + 图像),约 128K 上下文,100+ 语言,Matryoshka 维度;强力的企业默认
Voyage 4 家族 Voyage AI (MongoDB) API;nano 开放权重 2026 年 1 月;跨模型共享嵌入空间,有领域变体(代码/法律/金融);MongoDB Atlas 上的默认
Gemini Embedding 2 Google API(预览) 2026 年 3 月起原生多模态:文本、图像、视频、音频、PDF 共享一个嵌入空间;接替 gemini-embedding-001(据聚合站点曾位于英文 MTEB 榜前列)。引用前核实榜单位置
Qwen3-Embedding Alibaba 开源 (Apache-2.0) 非英文与自托管的最佳开源默认;长上下文;据称位于 MMTEB 前列
BGE-M3 BAAI 开源 (MIT) 多语且多功能(dense/sparse/ColBERT 合一);可靠的自托管基线
Cohere Rerank 4 (Fast / Pro) Cohere API 重排器;32K 上下文,多语,最广的生产履历;在 Bedrock/Azure/OCI 上
Voyage rerank-2.5 Voyage AI API 重排器;大免费层;在 MongoDB Atlas 上的自然搭配
mxbai-rerank v2 Mixedbread 开源 (Apache-2.0) 最佳开源自托管重排器;基于 Qwen2.5 的交叉编码器

混合检索与重排:2026 年的共识

2026 年的默认检索策略是混合加重排

  • 混合检索并行跑 BM25(稀疏、精确词)与稠密向量搜索,再把两份排序列表融合,通常用倒数排名融合score = sum 1 / (k + rank),按惯例取 k = 60。BM25 抓住稠密向量会模糊掉的精确匹配(代码、名称、罕见词),稠密则抓住 BM25 会错过的释义与概念。按排名来融合,绕开了分数尺度不兼容的问题。
  • 重排取融合后的前 50 至 100 个候选,用一个同时读查询和文档的交叉编码器重新打分,把前 5 至 10 个送进提示词。后期交互模型(ColBERT 风格、MaxSim)夹在稠密检索与交叉编码器重排之间:做词元级匹配,文档表示又可以预先算好,给一篇文档打分时,是把每个查询词元与文档词元的最佳匹配逐一相加。
  • 可以在重排前用 MMR(Maximal Marginal Relevance,最大边际相关,每次挑下一个分块时看的是相关度减去与已选分块的重叠)去一遍重,免得上下文窗口被几近相同的分块占掉。

一个最小的 pgvector 混合检索,嵌入与重排的调用都走网关(见连接):

-- chunks(id, doc_id, content, embedding vector(1024), tsv tsvector)
WITH dense AS (                          -- 稠密候选 (HNSW / DiskANN)
  SELECT id, RANK() OVER (ORDER BY embedding <=> :query_vec) AS r
  FROM chunks ORDER BY embedding <=> :query_vec LIMIT 100
),
sparse AS (                              -- 稀疏候选 (BM25 式)
  SELECT id, RANK() OVER (ORDER BY ts_rank_cd(tsv, plainto_tsquery(:q)) DESC) AS r
  FROM chunks WHERE tsv @@ plainto_tsquery(:q) LIMIT 100
)
SELECT c.id, c.content,                  -- 倒数排名融合, k = 60
       COALESCE(1.0/(60+dense.r),0) + COALESCE(1.0/(60+sparse.r),0) AS rrf
FROM chunks c
LEFT JOIN dense  ON dense.id  = c.id
LEFT JOIN sparse ON sparse.id = c.id
WHERE dense.id IS NOT NULL OR sparse.id IS NOT NULL
ORDER BY rrf DESC
LIMIT 50;  -- 把这 50 个交给重排器, 为提示词保留前 5-10 个

RRF 中的 k 会改变合并行为:小 k 让每份列表的头部占主导,大 k 抹平权重,使两份列表的一致程度变得更要紧。

# 倒数排名融合:score = sum 1 / (k + rank),rank 从 1 开始。
bm25  = ["d3", "d1", "d7", "d2"]   # 稀疏,精确词排序
dense = ["d2", "d3", "d5", "d1"]   # 稠密,语义排序
k = 60

def rrf(lists, k):
    score = {}
    for ranked in lists:
        for rank, doc in enumerate(ranked, start=1):
            score[doc] = score.get(doc, 0.0) + 1.0 / (k + rank)
    return sorted(score.items(), key=lambda kv: kv[1], reverse=True)

for doc, s in rrf([bm25, dense], k):
    in_both = doc in bm25 and doc in dense
    print(f"{doc}  rrf={s:.5f}  {'(in both lists)' if in_both else ''}")
# d3 领先:在两份列表里都不是第 1,但都稳居前列。

框架

在编排层,2026 年常见的搭法是:LlamaIndex(MIT)做摄取与检索,应用一旦带智能体性,就用 LangGraph(MIT)做编排与智能体;想要显式、可测试的生产流水线时用 Haystack(Apache-2.0);想把检索加提示词编译并优化、而不是手工调参时用 DSPy。从第一天起就接入 RAGASLangSmith。没有评估的检索只是在猜,这正是评估实践那一章(第 87 章)所主张的。

尚有争议

给这些工具排名的基准,可靠性低得反常。主要的 OCR 基准 OmniDocBench,在 2026 年被广泛认为已经饱和(Jerry Liu / LlamaIndex),而公开的 OCR 榜单并不能预测它在财务、法律或保险文档上的表现。MTEB 分数在其英文、多语与旧版榜单间互不可比。几乎每一项向量库的延迟、吞吐与成本声明,都是厂商自报、未经独立验证的。实践上的后果是:用一小份带标注的集合,在自己的文档上验证任何解析器或嵌入选择,把榜单位置当作入围信号,永远别当作决策。

一个合理的默认(2026)

对一个在 2026 年中开始搭这套栈的典型团队来说(带观点,日期 2026-06):

  • 文档智能:两层结构。 默认层是自托管 OSS:Docling 当流水线,配一个小型开源文档 VLM(PaddleOCR-VL,或者要最宽松许可就用 Granite-Docling)部署在 vLLM 上,搭配 Outlines/XGrammarguided_json 做符合模式的抽取。升级层把评估标记为低置信度的页面(密集表格、手写、糟糕扫描件)路由到 ReductoLlamaParse Agentic,或者用 Mistral OCR 3 当便宜的托管兜底。要是根本跑不了 GPU,就把 Mistral OCR 3 当默认,跳过 OSS 层。
  • 向量库:在现有的 Postgres 上用 pgvector,跨入数千万向量时加上 pgvectorscale。要是不在 Postgres 上,Qdrant 是默认的原生向量替代;要是拒绝运行任何基础设施,就选 PineconeTurbopuffer(后者用在规模成本或多租户主导时)。
  • 嵌入:从一个强力的 API 模型起步(text-embedding-3-large 走安全路线,Cohere Embed v4 走多模态/长上下文,Voyage 4 在 MongoDB Atlas 上),等到需要自托管、数据驻留或非英文深度时,再改用开源权重(Qwen3-Embedding 或 BGE-M3)。
  • 检索策略:混合(BM25 + 稠密)配 RRF,然后重排。 在调任何奇技淫巧之前,先把重排器加上(托管的 Cohere Rerank 4,或自托管的 mxbai-rerank v2)。它往往是单项 ROI 最高的改动。
  • 框架:LlamaIndex 做摄取与检索,带智能体性就用 LangGraph 做编排,RAGAS 或 LangSmith 从第一天起接入。

理由是:尽量少上新基础设施,把质量预算花在见效的地方(解析质量、嵌入、混合、重排),同时留一条干净的升级路径。以后可以换库而不用重写流水线,但没法给一个从未度量过的解析器和检索器去毒。

连接

检索位于智能体或生成器之下、模型网关(gateway)之旁,文档智能则在摄取边缘再往外一步。统一的接缝是网关。嵌入模型、重排器与自托管文档 VLM,都不过是被服务的模型(第 82 章),所以理想情况下应当通过模型网关去调它们,与对话流量并列。这样一来,嵌入、重排与解析的调用就和对话调用一样,被打上密钥、做了预算、受到观测,而把 text-embedding-3-large 换成自托管的 bge-m3,或在困难页面上把 PaddleOCR-VL 换成 Mistral OCR,就是一次路由改动,而非代码改动。整条栈端到端的连接,第 88 章 会专门展开,本章只强调其中一处接缝。解析输出进入抽取与分块,两者都进入向量库,库供检索使用,检索再把上下文交给生成器或智能体,评估则观测检索与最终回答。一次糟糕的解析会破坏它之上的每一层,正因如此,解析质量是检索与智能体要操心的事,而不是预处理时才想起的环节。

一手来源

向量库:

嵌入与重排:

混合检索与 RAG 框架:

文档智能:

延伸阅读

  • Khattab & Zaharia, “ColBERT: Efficient and Effective Passage Search via Contextualized Late Interaction over BERT,” 2020. arXiv:2004.12832
  • Faysse et al., “ColPali: Efficient Document Retrieval with Vision Language Models” (免解析的视觉文档检索:页面图像上的后期交互嵌入;ICLR 2025), 2024. arXiv:2407.01449
  • Singh et al., “Agentic Retrieval-Augmented Generation: A Survey on Agentic RAG,” 2025. arXiv:2501.09136
  • Xu et al., “A Survey of Model Architectures in Information Retrieval,” 2025. arXiv:2502.14822
    综述信息检索模型架构从传统词项方法到基于 Transformer 和大语言模型(LLM)方法的演进,涵盖主干模型与检索-重排系统架构设计。
  • Liu, “OmniDocBench is Saturated: What's Next for OCR Benchmarks,” 2026. llamaindex.ai
    LlamaIndex 博客文章指出,OmniDocBench 文档光学字符识别基准已近饱和(最高分达 94.6
  • OpenDataLab, “OmniDocBench project” (benchmark, versions, metrics), n.d.. github.com
    OmniDocBench 是 CVPR 2025 提出的综合性文档解析评测基准,覆盖多样化真实文档类型与版面。
  • MTEB, “MTEB / MMTEB leaderboard and methodology,” n.d.. huggingface.co
    MTEB Leaderboard 是一个 Hugging Face Space,对嵌入模型在多种语言和检索任务上进行排名。

评论

登录后评论