资讯详情

资讯详情

RAG从入门到实战(五):Embedding 与向量检索,一文理解文本如何被找到

RAG从入门到实战五Embedding 与向量检索一文理解文本如何被找到文章目录RAG从入门到实战五Embedding 与向量检索一文理解文本如何被找到前言一、关键词匹配为什么不总够用二、Embedding 是什么三、向量检索流程3.1 离线建立知识库3.2 在线检索相关片段四、常见相似度和距离4.1 点积Dot Product4.2 余弦相似度Cosine Similarity代码示例不用模型计算余弦相似度4.3 欧氏距离Euclidean Distance五、使用远程 Embedding 接口检索六、精确检索与近似最近邻6.1 精确检索6.2 近似最近邻ANN七、如何选择 Embedding 模型八、为什么向量检索会失败九、相似度阈值能否决定是否回答十、总结参考资料前言前面几篇介绍了文档解析、切分与文档侧优化。当知识库中有很多片段时系统如何从中找到与用户问题相关的内容一种常见方式是先用Embedding 模型将文本转换为向量再根据向量距离或相似度查找候选片段。这叫作向量检索。本文会回答文本为什么可以转换为向量余弦相似度、点积和欧氏距离有什么区别向量检索的完整过程是什么如何选择模型、定位检索失败文中的二维向量只是为了演示计算不是真实文本的模型输出示例文档均为虚构内容。一、关键词匹配为什么不总够用假设知识库中有一段员工入职满一年后每年可申请 5 天带薪年假。用户可能问我工作一年了能休几天带薪假问题和原文没有完全相同的表述但表达的意思比较接近。关键词检索可以依赖分词、同义词、词频统计等方法改善匹配向量检索则尝试把文本映射到一个可计算的表示空间通过向量之间的关系发现语义相关性。两者并不互相排斥专有名词、型号、错误码等场景往往也需要精确匹配。后续会介绍混合检索。二、Embedding 是什么Embedding 模型把输入转换为一组数值一段文本 → Embedding 模型 → 向量 [0.12, -0.34, 0.56, ...]这些数值共同构成文本的表示。不同模型的维度和训练方法可能不同单个维度通常不能直接解释为某个明确的人类概念。使用适合检索任务的模型时希望“问题”和“能够回答它的文档片段”在模型规定的度量方式下更容易被匹配到。但需要注意相似或相关是模型给出的检索信号不等于事实一致。相反结论的句子也可能因为主题相同而彼此接近。向量不是可直接读懂的知识也不能保证保存文本中的每一个细节。模型效果受语言、领域、文档长度和训练方式影响。例如“产品 A 支持退款”和“产品 A 不支持退款”主题接近但关键信息相反。检索到哪条、适用哪个版本仍需要结合原始文档和评估。三、向量检索流程向量检索通常有离线与在线两个阶段离线文档 → 切分 → 文档向量化 → 保存片段、向量和元数据 → 建立索引 在线用户问题 → 查询向量化 → 向量搜索 → 返回候选片段 → 后续排序与生成3.1 离线建立知识库解析文档并按合适的策略切分。为每个片段分配稳定的 ID保留标题、章节、版本等元数据。按模型要求构造文档输入生成向量。将向量和片段 ID 等信息存储并建立合适的索引。3.2 在线检索相关片段接收用户问题。按模型要求构造查询输入生成查询向量。在同一个兼容的向量空间中搜索。返回 Top-K 候选再按业务需要进行过滤、重排序、上下文扩展与生成。有些检索模型对查询和文档要求不同的前缀或编码方法例如分别使用 query/document 编码接口。应遵循该模型的官方说明而不是无条件把两个输入按相同方式处理。四、常见相似度和距离设向量为a和b。4.1 点积Dot Product点积是对应维度乘积之和a · b a₁b₁ a₂b₂ ... aₙbₙ点积同时受到方向和向量长度影响。某些模型就是针对点积训练的不能一概认为必须先归一化。4.2 余弦相似度Cosine Similarity余弦相似度衡量向量方向的接近程度cos(a, b) (a · b) / (||a|| × ||b||)对非零向量结果范围通常为[-1, 1]越接近 1表示方向越接近。零向量没有定义良好的余弦相似度需要显式处理。当a和b都被 L2 归一化为单位向量时点积与余弦相似度相等。但是否应该归一化仍应看模型和向量库要求。代码示例不用模型计算余弦相似度这个例子只依赖 Python 标准库向量是手工构造的演示数据importmathdefcosine_similarity(a,b):iflen(a)!len(b)ornota:raiseValueError(向量必须非空且维度相同)dotsum(x*yforx,yinzip(a,b))norm_amath.sqrt(sum(x*xforxina))norm_bmath.sqrt(sum(y*yforyinb))ifnorm_a0ornorm_b0:raiseValueError(零向量无法计算余弦相似度)returndot/(norm_a*norm_b)if__name____main__:query[1.0,0.0]candidates{片段 A:[0.9,0.1],片段 B:[0.0,1.0],片段 C:[-1.0,0.0],}results[(name,cosine_similarity(query,vector))forname,vectorincandidates.items()]forname,scoreinsorted(results,keylambdaitem:item[1],reverseTrue):print(name,round(score,3))预期排序为 A、B、C对应的相似度约为0.994、0.0、-1.0。真实 Embedding 往往有更多维且向量取值和含义由模型决定不能用这个二维例子推断实际检索质量。4.3 欧氏距离Euclidean Distance欧氏距离衡量向量空间中的直线距离d(a, b) √[(a₁-b₁)² (a₂-b₂)² ... (aₙ-bₙ)²]通常距离越小向量越接近。对单位向量而言||a - b||² 2 - 2 × cos(a, b)因此在所有向量都已单位归一化且比较对象相同的条件下按余弦相似度降序与按欧氏距离升序会得到相同排序并列值可能有不同的平局处理。不同数据库返回的是相似度、距离还是变换后的分数应查看其文档不要只凭数值大小猜测。五、使用远程 Embedding 接口检索第二篇已经演示了一个内存检索流程。本篇使用阿里云百炼DashScopeEmbeddings通过 API 获取向量不需要下载本地模型。先安装依赖pipinstall-Ulangchain-community dashscope numpy版本提示此示例使用langchain-community集成。该包在部分版本中会提示停止积极维护后续请根据 LangChain 和百炼官方文档选择适用的集成方式记录并固定验证过的依赖版本。远程接口的模型可用性、权限与费用以服务商实际情况为准。在 PowerShell 中设置密钥。下面的“你的百炼密钥”是占位符请在自己的运行环境中替换为你申请的实际密钥不要直接使用占位文字$env:DASHSCOPE_API_KEY 你的百炼密钥不要将真实密钥写入文章、截图或公开仓库调用需要网络、已开通的服务和可能产生的费用。不同 SDK 版本的接口可能变化请以当前文档为准。importnumpyasnpfromlangchain_community.embeddingsimportDashScopeEmbeddings chunks[{id:leave,text:员工入职满一年后每年可申请5天带薪年假。},{id:travel,text:员工出差结束后30天内提交报销申请。},{id:device,text:员工借用笔记本电脑需要填写设备申请。},]question工作满一年可以休几天带薪假modelDashScopeEmbeddings(modeltext-embedding-v4)doc_vectorsnp.asarray(model.embed_documents([item[text]foriteminchunks]),dtypefloat)query_vectornp.asarray(model.embed_query(question),dtypefloat)doc_normsnp.linalg.norm(doc_vectors,axis1)query_normnp.linalg.norm(query_vector)ifnp.any(doc_norms0)orquery_norm0:raiseValueError(Embedding 返回了零向量无法计算余弦相似度)scores(doc_vectors/doc_norms[:,None])(query_vector/query_norm)forindexinnp.argsort(-scores)[:2]:print(chunks[index][id],f{scores[index]:.4f},chunks[index][text])示例中的模型名称不代表它对所有中文知识库都是最优选择。实际输出分数和排序会随模型、服务版本及输入变化应使用具有代表性的问题集进行检验。请留意问题和文本会发送至服务提供方敏感文档应先确认授权和数据处理要求。此例中所有片段在内存里精确计算数据量大时可以考虑使用向量数据库管理和搜索但仍需要权衡效果、延迟与资源。六、精确检索与近似最近邻6.1 精确检索对所有候选向量计算距离或相似度再选出前 K 个。优点是容易理解并可作为比较基线当数据量很大时计算成本可能较高。6.2 近似最近邻ANN近似最近邻索引通过额外的数据结构减少需要比较的候选数量目标是在可接受的召回损失下获得更低的延迟。常见索引思路包括 IVF、HNSW 等具体实现与参数取决于所用数据库。例如IVF 的搜索范围、HNSW 的搜索参数通常会影响速度与召回但不能脱离具体产品版本给出通用最佳值。应在相同数据集、过滤条件和距离度量下与精确检索结果对照评估 ANN 的召回和延迟。注意区分ANN 召回近似搜索是否找到了精确向量搜索本应返回的近邻。业务检索召回返回的片段是否包含真正回答用户问题所需的证据。前者很高不代表 Embedding 模型、切分策略和文档内容就一定适合业务。七、如何选择 Embedding 模型不要仅看排行榜分数或向量维度。建议结合以下因素语言与领域中文、英文、混合语言以及法律、代码、产品文档等领域表现是否符合需求。任务类型是否适合“短问题检索长文档”这种非对称检索查询/文档前缀是否有要求。输入长度模型对长文本的截断规则是什么片段是否经常超过限制。部署与成本本地或 API、GPU/CPU 性能、吞吐、隐私要求和调用成本。向量维度与索引维度影响存储和计算但维度更高不必然代表效果更好。许可证与版本是否允许目标用途模型版本、依赖和下载来源是否可追溯。真实测试集效果使用自己的问题和证据标注比较检索质量、延迟与成本。替换 Embedding 模型时一般需要用新模型重新编码文档并重建或迁移索引。即便两个模型维度相同向量也不一定处于可互相比较的空间。迁移期间可以保留旧索引用于对照并规划切换和回滚。八、为什么向量检索会失败现象可能原因排查方向原文存在但没召回解析错误、切分不合理、模型不适配先核查原文和片段再检查向量表示召回主题相近但结论相反的片段语义相关不等于逻辑一致检查条件、否定词、版本结合重排序和证据核验产品编号或错误码不准确向量表示不擅长部分精确匹配考虑关键词或结构化字段过滤分数高但仍不能回答片段主题相似但证据不完整检查原文、相邻片段、上下文扩展更换模型后结果异常查询和文档向量不兼容、索引未重建核查模型版本、前缀、归一化和距离配置加上权限过滤后结果变少过滤条件、可见文档或索引配置问题先确认用户应有权限不能通过放宽权限解决九、相似度阈值能否决定是否回答可以把分数阈值作为一个参考信号但不要把某个数值当作所有模型、所有数据和所有距离度量通用的“正确率”。阈值会受模型、数据分布、查询类型和索引实现影响。即使分数高证据也可能过期、错误或只回答了问题的一部分。实际系统应基于标注样本校准阈值并结合来源、版本、证据充分性及拒答策略。十、总结Embedding 把文本映射为向量向量检索利用指定度量方式查找相关候选片段。一个可靠的检索系统仍要关注解析和切分是否保留了正确的原文与条件。文档与查询是否使用兼容的模型、前缀和距离度量。ANN 的速度与召回是否满足要求。检索到的内容是否真正支持答案。下一篇将使用 Milvus 介绍向量数据的存储、索引和检索并说明不同部署方式与版本可能存在的差异。参考资料阿里云百炼文档https://help.aliyun.com/zh/model-studio/向量余弦相似度与归一化scikit-learn 文档https://scikit-learn.org/stable/modules/generated/sklearn.metrics.pairwise.cosine_similarity.html
觉得有用,分享给同行:

为您的企业打造数字门面

稳重轻奢商务风格,端正雅致视觉,长效耐看不易过时。

立即咨询 →