Skip to content

向量化与语义检索

想象一下,你正在跟一个写作 Agent 说:"帮我查一下官方依据,看看这个项目能不能用第一人称写标题。"

它跑去资料库翻了一圈,回来告诉你:"没找到。"你亲自打开规范手册,发现第二章明明写着"标题避免使用第一人称,正文可以有条件使用"。问题出在哪?你的查询里说的是"第一人称",文档里写的是"避免使用我、我们、本文认为"——字面没撞上,但意思其实是一样的。

这就是关键词搜索的软肋。Agent 要想真正理解任务,不能只靠"查字典",而得学会"猜意思"。向量化与语义检索,做的就是把资料从"文字"变成"可比较的意思",让系统根据语义召回相关片段,而不是被表达差异挡在门外。

1. 为什么 Agent 系统需要语义检索

一个稳定运行的 Agent 工作流,常常会接到各种各样的资料需求:

  • Research Agent 需要找官方文档、论文、产品说明和项目内部知识库。
  • Planning Agent 需要参考历史产物里稳定的结构组织方式。
  • Style Agent 需要读取项目词表、禁用表达、格式习惯和案例写法。
  • Execution Agent 需要把资料转成产物,但不能把资料原样拼贴进去。
  • Review Agent 需要调出过去的反馈,检查事实、语气、证据和重复表达。

如果只用关键词搜索,系统会卡在几个常见问题上。用户说"官方依据",资料库里可能写的是"vendor docs"或"API reference";用户说"减少返工",历史产物里可能写的是"降低返修轮次";用户说"语气偏克制",规范里可能写的是"避免夸张承诺"。这些表达字面不同,但任务里指向同一组语义。

语义检索要解决的就是这类问题:让系统根据意思召回资料,再交给 Agent 判断、引用、改写和核查。

2. 先画一张整体地图

在深入每个概念之前,先看一下资料从入库到被 Agent 使用的完整旅程:

text
资料入库
  -> 清洗和 chunk
  -> 生成 Embedding
  -> 写入向量库 + metadata

任务查询
  -> 解析目标、对象、项目、时间
  -> metadata 过滤
  -> hybrid search 召回候选
  -> rerank 精排
  -> 按资料角色组装上下文
  -> 交给 Agent 使用

这条链路里的每个环节都在解决一个具体问题:

环节解决的问题
Embedding让不同表达但意思相近的文字能被找到
Chunk让每个被召回的片段都能独立理解
Metadata给检索加上来源、时间、可信度等边界
Hybrid search同时覆盖语义改写和精确术语
Rerank从"相关"中挑出"对这次任务有用"
角色分组区分事实、约束、参考写法,避免混用

后面的章节会按这条链路逐个展开。

3. Embedding:把资料变成可比较的表示

Embedding(嵌入)是把文本转换成一组数字向量的过程。在 Agent 系统里,我们主要用它做检索。

可以先用一个简化例子建立直觉:

文本简化向量更接近的含义
「减少返修轮次」[0.81, 0.76]改稿效率
「降低重复修改」[0.79, 0.74]改稿效率
「品牌语气保持克制」[0.22, 0.87]表达规范
「避免夸张承诺」[0.24, 0.84]表达规范

上面的二维向量只是为了说明方向和距离。实际模型通常输出更高维度的向量,例如 768 维、1536 维或 3072 维。维度由模型决定,向量数据库索引创建后也需要固定维度。

在生产实践中,1024 维左右是常见默认选择;Matryoshka 类模型允许在 256–512 维截断以节省存储,代价通常较小。选型时更要关注领域匹配度:通用模型在公开榜单上往往只差 1–2 分,但在法律、医疗、代码等垂直语料上,专用模型或经过领域微调的模型通常能拉开更大差距。此外,不少现代 embedding 模型会区分 query 与 document 输入类型,分别编码通常能进一步提升检索效果。

在 Agent 系统里,被向量化的对象通常是可独立使用的知识片段:

  • 官方文档中的一个能力说明、限制条件或参数解释。
  • 历史产物中的一个论证段落、案例段落或结构组织方式。
  • 项目规范中的一条语气规则、禁用词或推荐表达。
  • 审稿反馈中的一个问题类型,例如「证据不足」「结构过满」「引用不清」。

Embedding 的作用,是把这些片段放进同一个可比较的空间里。后续检索时,查询也会被转换成向量,然后在这个空间里找距离更近的片段。

4. 相似度:从「字面匹配」转成「语义接近」

Embedding 之后,两段文本是否相关就变成了两个向量是否接近。常见度量包括余弦相似度、欧氏距离和点积。

余弦相似度关注两个向量方向是否接近:

text
cosine_similarity(A, B) = dot(A, B) / (norm(A) * norm(B))

值越接近 1,通常表示语义越接近。它不太关心向量长度,因此常用于文本检索。

欧氏距离关注两个向量在空间里的直线距离:

text
euclidean_distance(A, B) = sqrt(sum((A_i - B_i)^2))

值越小,表示距离越近。点积则把方向和长度都纳入计算,是否合适取决于模型训练方式和向量库配置。

Agent 系统里,相似度分数只能说明「候选资料可能相关」,不能说明「资料一定正确」或「可以直接引用」。比如查询「RAG 检索质量」时,可能同时召回:

  • 一篇官方文档,说明 File Search、向量库或检索参数。
  • 一篇历史产物,写过类似结构。
  • 一条审稿反馈,指出「引用了二手博客,缺少官方来源」。

这三条都可能相似,但它们在任务里的用途不同。官方文档适合支撑事实,历史产物适合参考结构,审稿反馈适合约束质量。相似度解决召回,产物质量还需要来源类型、时间、可信度和上下文位置一起判断。

5. chunk:检索质量从切分开始

语义检索常见的第一步是 chunk,也就是把长文档切成较小片段。RAG 的基本思路,是让生成模型在回答前访问外部知识;工程实现里,外部知识通常不会整篇塞给模型,而是先切分、索引、检索,再把命中的片段放入上下文。

chunk 太大,召回结果会混杂多个主题。比如把整本规范手册作为一个 chunk,查询「标题能不能用第一人称」时,系统可能把使命陈述、标点规范、案例写法一起带回来。模型看到了很多文字,却没有看到足够聚焦的答案。

chunk 太小,也会丢掉判断所需的上下文。比如只切出「不要承诺确定结果」这一句,Agent 可能不知道这是对营销文案、产品说明,还是客户案例的约束。

可以按资料类型设计 chunk 粒度:

资料类型常见切分单位保留的上下文
官方文档一个功能说明、限制条件或参数段落文档 URL、章节标题、版本、更新时间
历史产物一个论证段、案例段或小节产物标题、栏目、目标对象、发布时间
项目规范一条规则加正反例适用场景、禁用表达、推荐表达
审稿反馈一条问题和对应修改建议产物类型、问题类别、严重程度、审稿时间

chunk 的目标,是让每个片段在被单独召回时仍然能被正确理解。这个目标会直接影响后续 rerank 和生成质量:候选片段如果切得不稳定,重排序模型也只能在一组不稳定材料里挑选。

在通用文本场景中,512–1024 token 的固定窗口配合 10–20% 的重叠是常见的起点;代码、表格、法律条文等结构化文档通常需要按语法边界或条款边界切分。切分策略没有统一最优解,应在具体语料上通过 recall 等指标验证。Anthropic 的 Contextual Retrieval 做法是在每个 chunk 前附加一句由 LLM 生成的文档级上下文摘要,再一起嵌入;实验报告显示,仅此一步就能把检索失败率降低约 35%,结合 BM25 和重排序后能降低约 67%。

6. metadata:让语义检索带上边界

metadata 是跟向量一起存储的结构化信息。向量数据库通常支持在向量上存 metadata,并通过 metadata 做过滤。

在 Agent 系统里,metadata 至少需要回答几个问题:

  • 这条资料来自哪里:official_docproject_guidepast_productreview_feedback
  • 资料属于哪个项目、品牌、语言和目标对象。
  • 资料是什么时间产生或更新的。
  • 资料能否引用给最终用户,还是只能用于内部参考。
  • 资料的可信度、审稿状态和过期状态。

一个写入向量库的片段可以长这样:

typescript
await vectorIndex.upsert([
  {
    id: "doc_openai_embeddings_001",
    values: embedding,
    metadata: {
      text: "Embeddings 可用于搜索、聚类、推荐、异常检测和分类。",
      sourceType: "official_doc",
      sourceName: "OpenAI Embeddings Guide",
      url: "https://developers.openai.com/api/docs/guides/embeddings",
      projectId: "agent-framework",
      language: "zh-CN",
      updatedAt: "2026-07-17",
      trustLevel: "high",
      citationAllowed: true,
    },
  },
]);

查询时也可以先过滤,再做向量相似度搜索:

typescript
const matches = await vectorIndex.query(queryEmbedding, {
  topK: 12,
  returnMetadata: "all",
  filter: {
    projectId: "agent-framework",
    language: "zh-CN",
    citationAllowed: true,
    trustLevel: "high",
  },
});

metadata 的价值在于把检索边界提前。Agent 如果先召回一堆来源混杂的内容,再靠生成模型临场判断哪些能用,事实来源和内部参考很容易被混在一起。能用结构化条件确定的范围,应该在检索阶段就收窄。

7. hybrid search:同时利用关键词和语义

语义检索能处理表达差异,但它也有盲点。Agent 任务里经常会出现专有名词、版本号、API 参数、法规条款、产品 SKU、人名和固定标题。它们不一定需要「理解意思」,更需要精确命中。

hybrid search 通常把两类检索合起来:

  • 稀疏检索:BM25、关键词、全文索引,适合精确名词、编号、参数和原文短语。
  • 稠密检索:Embedding 向量,适合语义相近、表达不同、同义改写和跨语言线索。

两类结果通常用 Reciprocal Rank Fusion(RRF)合并,它不需要归一化不同检索器的分数,k=60 是常见的默认参数。BM25 能补上 embedding 在精确术语上的召回缺口,而 embedding 能补上关键词在改写、同义表达上的缺口。在多个公开评估中,hybrid 检索比纯稠密检索的 recall@10 通常能提升几个到十几个百分点,但具体提升幅度取决于语料领域和查询分布。

例如查询「File Search 默认 chunk 策略和 rerank 设置」,关键词检索更容易抓住 File Searchchunkrerank 这些术语;向量检索更容易找到「检索工具如何把文件切分后用于回答」这类没有完全同词的说明。两者合并后,系统可以先召回更宽的一批候选,再交给 rerank 精排。

hybrid search 适合这些场景:

  • 官方文档检索:专有名词必须准,解释段落也要能召回。
  • 历史产物检索:标题和栏目可用关键词,表达结构更适合语义。
  • 审稿反馈检索:问题标签可用关键词,类似反馈原因更适合语义。
  • 项目规范检索:禁用词需要精确匹配,语气倾向需要语义匹配。

hybrid search 的目标,是降低漏掉关键资料的概率。召回之后仍然需要排序、去重和可信度判断。

8. rerank:把候选资料按任务重新排序

向量库的 Top-K 结果是第一轮候选,不一定是最终应该注入 Prompt 的材料。rerank(重排序)会拿「查询 + 候选片段」重新判断相关性,通常比单纯向量距离更贴近当前任务。

embedding 检索阶段使用的通常是 bi-encoder:查询和文档被独立编码后再比较,速度快但精度有限;rerank 阶段使用的 cross-encoder 则把查询和文档拼接后一起计算,能捕捉更细粒度的匹配关系,但速度更慢,因此只用在候选漏斗的最后一步。在生产实践中,rerank 常被看作性价比最高的质量杠杆之一,因为它能把第一轮召回的 top-100 候选进一步压缩到 top-5 或 top-10,再交给生成模型。

可以把检索过程拆成两层:

  1. 召回层:用向量检索、关键词检索和 metadata 过滤找出 20 到 100 条候选。
  2. 精排层:用 rerank 模型或 LLM 按任务意图、来源可信度、时间和可引用性选出 5 到 10 条。

Agent 任务里的 rerank 不应该只看语义相关,还要看资料角色:

候选资料相似度来源可信度对任务的作用是否优先
OpenAI Embeddings 官方文档支撑 Embedding 定义和模型维度优先
历史文章中的 RAG 比喻段落参考表达节奏次优先
旧审稿意见「不要照搬文档」约束生成方式优先
过期博客里的参数说明可能误导事实降权

这个排序逻辑和产物质量直接相关。资料相似但来源弱,容易写出看似专业、实际不可靠的段落;资料可信但不贴任务,也会让产物变成资料堆砌。rerank 的意义,是把「相关」进一步拆成「对这次任务有用」。

9. 从资料库到产物:一条可维护的数据流

把前面的概念串起来,Agent 系统里的检索链路可以这样组织:

text
资料入库
  -> 清洗正文、保留标题和来源
  -> 按资料类型切分 chunk
  -> 生成 Embedding
  -> 写入向量库和 metadata

任务到来
  -> 解析目标、对象、项目、语言、时效要求
  -> 构造查询
  -> metadata 过滤
  -> hybrid search 召回
  -> rerank 精排
  -> 按资料角色组装上下文
  -> 交给研究、规划、执行和审稿 Agent

这里有一个容易忽略的点:注入给模型的上下文如果只是一串资料片段,各个 Agent 会共享同一堆材料,却缺少用途边界。更稳妥的做法,是把资料按角色分组:

text
【必须遵守】
- 项目规则:避免夸张承诺;不要使用「颠覆」「极致」。
- 审稿反馈:产物需要区分官方事实、作者判断和产品建议。

【可引用事实】
- OpenAI Embeddings 文档:Embedding 可用于搜索、聚类、推荐、异常检测和分类。
- Cloudflare Vectorize 文档:索引创建时需要指定维度和距离度量;查询可带 metadata filter。

【可参考写法】
- 历史产物《AI 工作流的评审机制》:先拆业务问题,再解释模块分工。

这样做能减少两类问题。第一,模型把历史产物当成事实来源的概率会下降。第二,模型更容易区分「必须遵守的约束」和「可以参考的表达」。

10. 来源可信度与产物质量

语义检索让资料更容易被找回,但产物质量还取决于资料如何被使用。可以把检索结果分成四层:

  1. 官方文档、论文、标准和项目源码:适合支撑事实、能力边界和参数说明。
  2. 内部项目手册、PRD、审稿规范:适合约束语气、结构和交付标准。
  3. 历史产物、复盘、案例库:适合参考表达方式、论证节奏和对象假设。
  4. 社区文章、二手博客、未审稿资料:适合启发选题,不适合直接支撑关键事实。

检索系统可以把这些层级写进 metadata,并在 rerank 时加权。比如同样命中「Embedding 维度」,官方文档应该排在二手博客前面;同样命中「项目语气」,规范手册应该排在历史产物前面;同样命中「审稿意见」,最近且同类型产物的反馈应该排在很久以前的泛化建议前面。

这套机制也能降低资料复写风险。风险通常来自两个动作:直接照搬资料句子,或用相同结构复刻历史产物。检索阶段可以给出依据,但生成阶段需要明确区分:

  • 事实可以引用,但要标明来源。
  • 观点需要结合当前任务重新组织。
  • 历史产物只能参考结构和节奏,不能复用原句。
  • 项目规范是约束,不是模板。
  • 审稿反馈用于发现风险,不是把产物写成检查清单。

语义检索如果只追求「相似」,会把旧产物拉得太近;同时考虑来源、资料角色和可信度后,Agent 更容易把资料作为依据,而不是贴着资料复写。

11. 可观测性:检索效果需要被检查

系统上线后,检索质量不能只靠主观体感。至少需要记录几类信息:

  • 查询文本、查询意图和使用的 metadata filter。
  • 召回结果、相似度分数、rerank 分数和最终注入的片段。
  • 每条片段的来源类型、更新时间、可信度和是否被引用。
  • 审稿 Agent 对事实、语气、结构和引用的反馈。
  • 人类最终保留、删除或改写了哪些检索资料。

这些记录能帮助团队定位问题。比如产物缺少官方依据,可能是 metadata 过滤过宽或官方资料未入库;产物过度贴近旧稿,可能是历史产物权重过高;产物引用过期参数,可能是 updatedAt 没有参与排序;产物事实准确但读起来像资料摘要,可能是上下文分组没有区分「可引用事实」和「可参考写法」。

评估时建议优先使用自己业务里的真实查询-答案对,而非完全依赖公开 RAG 榜单,因为后者与生产分布往往存在差异。RAGAS 等框架提供了 faithfulness、context precision/recall、answer relevance 等自动化指标,适合作为持续监控的起点;同时用人工标注的小样本集定期校准,能避免自动指标漂移。

语义检索的评估也可以从几个简单指标开始:

指标含义什么时候用
Recall@K正确资料是否出现在前 K 个候选里检查漏召回问题
MRR第一条正确资料排得是否足够靠前检查排序质量
引用通过率审稿后保留下来的引用占比检查资料可用性
返修原因分布事实错误、来源不明、语气不符、重复旧稿分别占多少定位优化方向

这些指标不需要一次做得很复杂。先把检索过程记录下来,再从真实审稿反馈里抽样,就能逐步知道应该调 chunk、metadata、hybrid search,还是 rerank。

12. 总结

回到开头那个场景:Agent 没找到"第一人称",不是因为它笨,而是因为我们只给了它关键词匹配的能力。

向量化与语义检索在 Agent 系统里承担的是资料调度工作。Embedding 让不同表达可以被放到同一个语义空间里比较;相似度搜索负责召回可能相关的片段;chunk 决定片段是否可理解;metadata 决定检索边界;hybrid search 降低漏召回;rerank 把候选资料重新排序到当前任务上。

检索结果需要带着来源角色进入 Agent 流程。官方文档支撑事实,项目规范约束表达,历史产物参考结构,审稿反馈提示风险。这样组织之后,Agent 生成的产物更容易做到三件事:事实有依据,语气有边界,表达不像资料拼贴。

一句话总结:语义检索不是让 Agent 找到"最像"的资料,而是让它找到"对这次任务有用、可追溯、可信任"的资料。

基于 MIT 协议开源