跳到正文

Embedding 怎么实现语义召回?

RAG 中查询与文档向量化,余弦相似度计算及优化考量

原题:请详细说明在RAG系统中,如何利用嵌入模型将查询和文档映射到向量空间,并结合相似度计算方法(如余弦相似度)实现相关文档的高效语义召回,要求阐述技术流程、关键组件作用及实际应用中的优化考量。

向量检索 · 字节真题

回答与解析

核心流程

1. 文档向量化(离线)

  • 文档分块:按语义/固定长度切分,控制chunk大小(通常256-512 tokens)
  • Embedding编码:用预训练模型(如BGE、M3E、OpenAI-ada)将文本映射为稠密向量
  • 关键:领域数据建议微调Embedding模型,解决分布偏移

2. 向量索引构建

  • 存储:向量数据库(Milvus、Faiss、Pinecone)或近似最近邻索引(HNSW、IVF)
  • HNSW:图索引,查询快、精度高,适合动态更新场景

3. 查询检索(在线)

  • 查询向量化:同一Embedding模型编码,保证查询-文档同空间
  • ANN检索:Top-K近似最近邻,非暴力全量计算
  • 相似度计算:余弦相似度 = (A·B)/(||A||·||B||),值域[-1,1],实际取Top-K

关键优化点

优化方向 具体手段
召回质量 混合检索(向量+关键词BM25)、查询改写、多向量表示
精度提升 两阶段检索(粗排+精排/Cross-Encoder重排序)
效率优化 量化(FP32→FP16/INT8)、索引分区、缓存热点查询
领域适配 Embedding微调、Hard Negative Mining

余弦相似度的选择逻辑

  • 归一化后等价于点积,计算高效
  • 对向量长度不敏感,适合语义匹配(关注方向而非幅度)
  • 替代方案:欧氏距离(关注绝对差异)、点积(需预归一化)

学习建议

建议先掌握向量嵌入和余弦相似度的基本概念,再结合RAG架构理解检索流程,通过动手实践使用Sentence-BERT等模型进行文本编码和相似度计算来加深理解。

口语版讲法(约4分钟)

  • 本质定位:端到端语义匹配
  • 流程拆解:离线分块+向量化,在线检索+重排
  • 落地优化:混合检索、领域微调、效率取舍
  • 风险与边界:分块策略、模型失配、上线校验

这道题其实问的是怎么用向量把文本变成数学上可比较的东西,再快速找到最相关的文档。说白了,就是怎么把语义匹配工程化。核心就是三件事:先把文档和查询都映射到同一个向量空间,然后用近似搜索代替暴力比对,最后在精度和效率之间做取舍。

先说流程。离线阶段,我会把文档按语义切块,比如256到512个token一段,太短上下文不够,太长噪音多。然后用同一个Embedding模型,比如BGE或者M3E,把每段文本编码成稠密向量。这里有个前提:如果领域很特殊,比如金融合同或者医疗病历,通用模型效果会差,得做微调。切块也不是一刀切,固定长度适合通用场景,但要是文档结构性强,像操作手册或者法律条款,我会优先用语义切分,按段落或者标题来,避免把完整的概念切碎。

向量存进向量数据库,比如Faiss或者Milvus。索引我一般选HNSW,图结构,查询快、精度高,而且支持动态增删,适合线上经常更新。但HNSW内存消耗大,如果向量几十亿,就得用IVF加量化来压缩,不过精度会掉一点。

在线阶段,用户查询进来,用同样的Embedding模型编码,然后做ANN搜索,也就是近似最近邻,不用跟所有文档比。相似度我常用余弦相似度,因为它关注方向,对向量长度不敏感,适合语义匹配。但有一点要注意:如果模型输出的向量已经归一化了,那余弦和点积等价,选计算更快的就行。

但纯向量检索有硬伤:对同义词或者拼写错误还行,但精确匹配比如订单号、错误码就抓瞎。所以真正落地我会上Hybrid Search,向量加关键词,比如BM25,两条路都跑,结果融合。举个例子,客服场景用户说“我退款了但没到账”,向量能召回相似语义的退款政策,BM25能精确命中“退款”这个词。如果只做向量,那精确信息的召回率会低得没法用。

还有一个常见失败场景:查询很短,比如就一个词“退款”,向量召回的结果可能偏,因为语义太宽。这时候我会加查询改写,用大模型把查询扩写成更具体的句子,或者用多向量表示,让查询和文档多角度匹配。

精度方面,检索完会有一个重排阶段。向量检索是Bi-Encoder,速度快但精度一般;重排用Cross-Encoder,把查询和每个候选文档拼在一起算分,精度高但慢。所以我会先向量粗召回几百个,再用Cross-Encoder精排到Top-10。重排是性价比很高的优化,能显著提升最终效果。

效率上,向量可以量化,从FP32降到FP16甚至INT8,内存少一半,速度也快。但量化会损失精度,需要评估是否在可接受范围。另外,热点查询可以缓存,比如常见问题直接返回预计算结果,不用每次都跑检索。

对了,还有一个容易被忽视的点:分块策略对召回影响很大。比如固定切分可能把一句话拆到两块里,导致检索时上下文丢失。我会把零重叠、短窗口与较长窗口作为候选,用同一评测集比较边界证据完整率、召回、存储与去重成本。但重叠多了存储和计算都翻倍,需要权衡。这个其实牵涉到文档结构和模型上下文长度,挺有意思的,可以展开聊聊。

最后说我的判断:RAG不是银弹,它适合知识密集型但不需要深度推理的场景。如果知识库频繁更新,或者查询高度依赖精确匹配,我会搭配关键词或者甚至用微调模型。上线前我会特别关注召回率指标,比如Recall@K,还有延迟,确保在用户容忍范围内。如果效果不行,优先查分块策略和Embedding模型是否匹配领域,而不是盲目调参数。

关键一句:分块策略(滑动窗口+重叠)对召回质量的影响,以及存储和计算的权衡

面试官还可能这样问

  1. 问法 1 · 场景切入

    假设你在做电商客服的智能问答系统,用户问“我昨天买的手机怎么还没到”,系统需要从海量售后文档里找到相关回答。你会怎么把用户的查询和文档都变成向量,然后高效地召回最相关的几条?

  2. 问法 2 · 层层追问

    RAG里怎么做语义召回?……你先说说怎么把文档和查询转成向量?……那向量化之后怎么快速找到最相似的?……如果用余弦相似度,为什么选它而不是欧氏距离?

  3. 问法 3 · 直球架构

    请详细说明RAG系统中,如何用嵌入模型映射查询和文档到向量空间,并结合余弦相似度实现高效语义召回?包括技术流程、关键组件作用和实际优化点,比如索引、分块、精度效率平衡。

同模块相关题目