QAnything 阅读优化策略05——检索 检索Retrieval检索是从知识库中找到与用户查询最相关的文档的过程。QAnything 采用宽召回 → 精排序 → 严过滤三段式检索层层递进平衡召回率与精确率。一、是什么检索是从知识库中找到与用户查询最相关的文档的过程。核心输入归一化后的查询向量 知识库索引核心输出经过过滤和排序的相关文档列表二、为什么重要检索决定了 RAG 的天花板生成只能逼近这个天花板。核心矛盾召回率 vs 精确率检索多了 → 噪音多LLM 被无关信息干扰大海捞针问题检索少了 → 遗漏关键信息回答不完整与传统方案的对比优化点传统方案传统方案的问题QAnything 方案优势检索方式仅向量检索遗漏专有名词、数字等精确匹配向量检索 BM25 双路召回语义 精确匹配互补结果合并两路结果直接拼接同一文档出现两次浪费 TokenMilvus 在前 ES 独有追加无重复Token 更节省分数融合RRF 或加权融合Milvus0~1和 BM25无界量纲不同融合无意义不做分数融合交给 Rerank 统一排避免量纲差异导致的排序错误排序精度仅用向量余弦相似度排序query 和 doc 独立编码交互深度不足Rerank 交叉编码器联合编码每层注意力交互排序更精确过滤策略单一阈值如 top-k 或 score 0.5top-k 固定数量可能引入噪音单一阈值无法检测质量断崖两层过滤绝对阈值 0.28 梯度断裂 50%保底 检测断崖过滤更精准去重方式按 doc_id 去重不同文件相同段落如法规原文无法去重按 page_content 内容去重跨文件重复内容也能去重断连处理Milvus 断连 → 返回空结果用户看到无结果体验差空结果时自动重连重试连接中断自动恢复HTTP 重试无重试或固定间隔重试网络抖动直接失败指数退避1s→2s→4s给服务端恢复时间三、怎么做QAnything 采用三段式检索宽召回 → 精排序 → 严过滤阶段一宽召回3.1 Milvus 向量检索语义级问题需要理解同义词和概念相似如AI和人工智能。方案使用 HNSW 索引进行近似最近邻搜索。# HNSW 索引在 64 个候选点中精确搜索search_params{params:{ef:64}}# 按知识库分区过滤exprfkb_id in{partition_keys}# 检索流程query → embedding → HNSW 搜索 → top_k 子块 → 映射回父块HNSW 原理分层图结构高层快速定位低层精确搜索ef64在 64 个候选点中搜索平衡速度和精度3.2 Elasticsearch BM25 关键词检索精确级问题向量检索容易遗漏精确关键词如专有名词 “Qwen2.5”、数字 “¥0.008”。方案使用 BM25 算法进行精确关键词匹配。# BM25 策略基于倒排索引的精确匹配es_storeElasticsearchStore(strategyBM25RetrievalStrategy())filter[{terms:{metadata.kb_id.keyword:partition_keys}}]es_sub_docsawaites_store.asimilarity_search(query,ktop_k,filterfilter)BM25 核心原理TF词频一个词在文档中出现越多 → 越重要IDF逆文档频率一个词在整个语料中出现越少 → 越有区分度向量检索 vs BM25 对比特性向量检索BM25理解同义词是否精确匹配弱强适合场景语义类问题精确关键词速度快快3.3 去重合并不做分数融合问题两路检索结果可能重复浪费 Token。方案Milvus 在前语义质量更稳定ES 独有的追加。# Milvus 在前ES 独有的追加milvus_doc_ids[d.metadata[id_key]fordinquery_docs]fordines_sub_docs:ifdoc_idnotinmilvus_doc_ids:es_ids.append(doc_id)query_docs.extend(es_docs)为什么不做分数融合Milvus 分数 余弦相似度0~1ES 分数 BM25可以是负数或很大的数量纲不同直接融合无意义交给 Rerank 统一排序阶段二精排序3.4 Rerank 交叉编码器精排问题向量检索的粗排分数不够精确。方案使用交叉编码器对候选文档进行精排。特性双编码器向量模型交叉编码器Rerank编码方式query 和 doc 独立编码query 和 doc 拼接后联合编码交互深度只在最后算余弦相似度每一层都有注意力交互精度较粗更精确速度快可预计算慢每对重新计算角色大规模初筛少量候选精排为什么不用交叉编码器做初筛交叉编码器需要对每个 (query, doc) 对重新计算无法预计算如果知识库有 100 万条文档交叉编码器要计算 100 万次不现实3.5 Rerank 异常降级try:docsawaitself.rerank.arerank_documents(query,docs)exceptException:# 降级用 embedding 余弦相似度打分embed1awaitself.embeddings.aembed_query(query)fordocindocs:embed2awaitself.embeddings.aembed_query(doc.page_content)doc.metadata[score]cosine_similarity(embed1,embed2)3.6 Embedding/Rerank 客户端并发批处理# 大批量拆成多个小批次并发发送tasks[self._get_embedding_async(session,texts[i:ibatch_size])foriinrange(0,len(texts),batch_size)]resultsawaitasyncio.gather(*tasks)# 并发等待阶段三严过滤3.7 第一层——绝对阈值过滤问题去掉绝对不相关的噪音文档。# 保留 rerank 分数 0.28 的文档filtered[docfordocindocsifdoc.metadata[score]0.28]# 如果过滤后为空保留全部总比什么都不返回好0.28 的含义经验阈值低于此分数的文档基本不相关。3.8 第二层——梯度断裂检测问题在保留的文档中找到高质量和低质量的分界线。saved_docs[docs[0]]# 最高分文档fordocindocs[1:]:relative_diff(saved_docs[0].score-doc.score)/saved_docs[0].scoreifrelative_diff0.5:# 50% 质量断崖break# 后面的全不要else:saved_docs.append(doc)执行示例分数: [0.92, 0.85, 0.80, 0.40, 0.35] 0.92 → 保留最高分 0.85 → (0.92-0.85)/0.92 7.6% 50% → 保留 0.80 → (0.92-0.80)/0.92 13% 50% → 保留 0.40 → (0.92-0.40)/0.92 56.5% 50% → 截断 最终保留: [0.92, 0.85, 0.80]两层配合的逻辑只用绝对阈值可能所有文档都 0.28 但后面几个已经很差只用相对差异如果都很低如 [0.35, 0.30, 0.28]相对差异不大但都不该要两层组合先保底去绝对噪音再检测断裂去相对噪音3.9 内容级去重# 按 page_content 文本内容去重非 doc_iddefdeduplicate_documents(source_docs):unique_docsset()fordocinsource_docs:ifdoc.page_contentnotinunique_docs:unique_docs.add(doc.page_content)deduplicated_docs.append(doc)为什么不用 doc_id不同文件可能有完全相同的段落如法规原文按内容去重更有效。3.10 已删除文档过滤 默认分数兜底# 过滤已删除的文档ifretriever.mysql_client.is_deleted_file(doc.metadata[file_id]):continue# 没有分数的文档用位置倒序兜底ifscorenotindoc.metadata:doc.metadata[score]1-(idx/len(query_docs))3.11 Milvus 自动重连 HTTP 重试# Milvus 空结果时重建连接iflen(query_docs)0:retriever.vectorstore_clientVectorStoreMilvusClient()query_docsawaitretriever.get_retrieved_documents(...)# HTTP 指数退避重试retryRetry(total3,backoff_factor1,status_forcelist[500,502,503,504])# 重试间隔1s → 2s → 4s四、解决的问题汇总阶段手段解决的问题宽召回Milvus 向量检索语义级文档匹配宽召回ES BM25 检索精确关键词匹配宽召回去重合并两路结果重复精排序Rerank 交叉编码器粗排精度不足精排序异常降级Rerank 服务故障精排序客户端并发批处理大批量推理效率严过滤绝对阈值 ≥ 0.28绝对噪音严过滤梯度断裂 50%相对噪音严过滤内容级去重跨文件相同段落严过滤已删除过滤数据一致性鲁棒性自动重连Milvus 连接中断鲁棒性HTTP 指数退避网络不稳定

相关新闻

最新新闻

SerenityOS 命令行选项解析指南:getopt 与 getopt_long 用法、返回值与底层实现

SerenityOS 命令行选项解析指南:getopt 与 getopt_long 用法、返回值与底层实现

SerenityOS 命令行选项解析指南:getopt 与 getopt_long 用法、返回值与底层实现 【免费下载链接】serenity The Serenity Operating System 🐞 项目地址: https://gitcode.com/GitHub_Trending/se/serenity 导读 本文以 getopt(3) 手册 为核心&a…

2026/9/25 12:45:43
轻量服务器还是ECS?大促云服务器选购与避坑实战指南

轻量服务器还是ECS?大促云服务器选购与避坑实战指南

每年大促节点,群里永远有人在问同一个问题:“38元的轻量服务器到底怎么抢?为什么我每次点进去都是已售罄?68元直购和99元的ECS我到底选哪个?”作为一个常年帮团队和自己采购云服务器的老用户,我太清楚这种纠…

2026/9/24 14:25:52
为 AI 代理的 Review 动作编写 Cedar 审批门控策略:review-agent-governance 策略编写实战指南

为 AI 代理的 Review 动作编写 Cedar 审批门控策略:review-agent-governance 策略编写实战指南

为 AI 代理的 Review 动作编写 Cedar 审批门控策略:review-agent-governance 策略编写实战指南 【免费下载链接】agents Multi-harness agentic plugin marketplace for Claude Code, Codex, Cursor, OpenCode, GitHub Copilot, and Google Antigravity 项目地址:…

2026/9/26 3:42:08
PaddleOCR 手写数学公式识别算法 CAN 实战指南:Counting-Aware Network 训练、评估与推理部署

PaddleOCR 手写数学公式识别算法 CAN 实战指南:Counting-Aware Network 训练、评估与推理部署

PaddleOCR 手写数学公式识别算法 CAN 实战指南:Counting-Aware Network 训练、评估与推理部署 【免费下载链接】PaddleOCR Turn any PDF or image document into structured data for your AI. A powerful, lightweight OCR toolkit that bridges the gap between i…

2026/9/26 11:37:29
Spring源码解析:构造器注入的类型转换与候选匹配机制

Spring源码解析:构造器注入的类型转换与候选匹配机制

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/9/26 4:08:27
openai-agents-python 多模型接入指南:深入解析 AnyLLMModel 适配层与 any-llm 路由

openai-agents-python 多模型接入指南:深入解析 AnyLLMModel 适配层与 any-llm 路由

openai-agents-python 多模型接入指南:深入解析 AnyLLMModel 适配层与 any-llm 路由 【免费下载链接】openai-agents-python A lightweight, powerful framework for multi-agent workflows 项目地址: https://gitcode.com/GitHub_Trending/op/openai-agents-pyth…

2026/9/25 15:49:36

日新闻

周新闻