图_3检索模块 · 详细实现
对应 [[3_代码实现_检索模块]]。按图 1 模板粒度,只写主要实现步骤。
读图方式
- 蓝底是文件,紫底是类,灰底是函数;标题与主要步骤分开,框宽随文字收紧。简单函数一句,复杂函数按主要处理阶段分步。
- 实线箭头表示调用(含 LangGraph 的节点调度),虚线箭头表示数据或对象传递。远距离用
〔调用 F07〕/〔传递 F07:2〕引用,避免拉长线。 - F / C / P 分别表示函数、类、文件;冒号后的数字指目标步骤。编号只用于定位,不表示执行次序。
- 省略普通返回、逐字段转换和重复异常处理;保留会影响业务走向的降级、HITL、终止等分支。
文件与函数索引
P01 · backend/rag/utils.py
召回、合并、精排与查询改写。
- F01
_optional_env()(源码 14 行):读取有效的可选配置。 - F02
_read_positive_int_env()(源码 44 行):读取正整数配置。 - F03
_read_float_env()(源码 56 行):读取浮点配置。 - F04
resolve_candidate_k()(源码 101 行):确定召回候选池大小。 - F05
retrieve_documents()(源码 432 行):检索入口:召回并组织证据。 - F06
_finalize_retrieval()(源码 401 行):合并 → 精排 → 阈值过滤。 - F07
_empty_merge_meta()(源码 213 行):初始化合并统计。 - F08
_auto_merge_candidates()(源码 224 行):执行两级父块合并。 - F09
_merge_to_parent_level()(源码 173 行):用完整父块替换命中的子块。 - F10
_effective_score()(源码 136 行):取有效排序分数。 - F11
_merge_rank_score_into()(源码 154 行):合并证据分数。 - F12
_sort_by_rank_score()(源码 244 行):按分数排序。 - F13
_get_rerank_endpoint()(源码 129 行):规范精排接口地址。 - F14
_rerank_documents()(源码 263 行):可选精排并截取 Top-K。 - F15
_meets_rerank_min_score()(源码 147 行):判断证据是否达标。 - F16
dedupe_documents()(源码 248 行):合并重复证据。 - F17
retrieval_trace_fields()(源码 124 行):提取检索过程记录。 - F18
_get_rewrite_model()(源码 354 行):获取 FAST_MODEL 改写模型。 - F19
rewrite_query_once()(源码 370 行):生成一次查询改写。 - C01
RewritePlan:查询改写协议。
调用与对象传递对照
| 出发位置 | 目标 | 类型 | 关系 |
|---|---|---|---|
| F05 · 第 1 步 | F04 resolve_candidate_k |
实线 · 调用 | 调用 |
| F05 · 第 4 步 | F06 _finalize_retrieval |
实线 · 调用 | 调用 |
| F06 · 第 1 步 | F08 _auto_merge_candidates |
实线 · 调用 | 调用 |
| F06 · 第 2 步 | F14 _rerank_documents |
实线 · 调用 | 调用 |
| F06 · 第 3 步 | F15 _meets_rerank_min_score |
实线 · 调用 | 调用 |
| F08 · 第 1 步 | F07 _empty_merge_meta |
实线 · 调用 | 调用 |
| F08 · 第 1 步 | F09 _merge_to_parent_level |
实线 · 调用 | 调用 |
| F09 · 第 3 步 | F11 _merge_rank_score_into |
实线 · 调用 | 调用 |
| F11 · 第 1 步 | F10 _effective_score |
实线 · 调用 | 调用 |
| F12 · 第 1 步 | F10 _effective_score |
实线 · 调用 | 调用 |
| F15 · 第 1 步 | F10 _effective_score |
实线 · 调用 | 调用 |
| F14 · 第 1 步 | F13 _get_rerank_endpoint |
实线 · 调用 | 调用 |
| F14 · 第 3 步 | F12 _sort_by_rank_score |
实线 · 调用 | 调用 |
| F16 · 第 2 步 | F11 _merge_rank_score_into |
实线 · 调用 | 调用 |
| F19 · 第 1 步 | F18 _get_rewrite_model |
实线 · 调用 | 调用 |
| F08 · 第 2 步 | F14:1 _rerank_documents |
虚线 · 传递 | 合并后的候选证据 |
| C01 · 第 1 步 | F19:1 rewrite_query_once |
虚线 · 传递 | 结构化输出协议 |
[[source/_posts/LLM/2_RAG/project/img/详细实现/项目实现|查看项目实现总图]]。概要图仍保留在“实现”文件夹。
Excalidraw Data
Text Elements
backend/:本模块的后端实现 ^2a1bf0ac
rag/:召回并组织证据决策工作流 ^a96e15cd
[[3_代码实现_检索模块|P01 utils.py:检索核心操作:召回、合并、精排与查询改写]] ^70f0c5d1
-
读取召回、父块合并、精排与改写配置。 ^49b54c61
-
复用embedding模型,创建 MilvusStore 与父块 Store。 ^7de8b2ef
召回入口 ^10ae3af0
F05 retrieve_documents():检索入口:召回并组织证据 ^bb2e9b7b
-
确定候选数,召回等级(只召回 L3 ) 〔调用 F04〕 ^e2afdcae
-
将 Query 编码为 Dense 向量。 ^c321ff2d
-
先混合召回;异常时降级为 Dense(调用milvus客户端) ^b323ee05
-
调用统一后处理,形成最终证据与检索记录。 〔调用 F06〕 ^00a8c516
F04 resolve_candidate_k():确定召回候选池大小 ^3e4fda32
-
优先使用配置的候选数,否则按 Top-K 的倍数计算。 ^be20bd6e
-
候选数至少为最终 Top-K。 ^84fadf41
F06 _finalize_retrieval():合并 → 精排 → 阈值过滤 ^d6522885
-
对召回结果合并父块,防止结果碎片化。 〔调用 F08〕 ^3fc566d0
-
可选重排,截取 Top-K。 〔调用 F14〕 ^557b1c10
-
按分数阈值过滤,数量不足不补齐。 〔调用 F15〕 ^62750c85
F17 retrieval_trace_fields():提取检索过程记录 ^d9e021d3
- 按白名单提取需要写入 Trace 的检索字段。 ^d25d32a9
L3 → L2 → L1 合并(从下往上) ^a053ba64
F08 _auto_merge_candidates():执行两级父块合并 ^67494940
-
执行 L3 → L2,L2 → L1合并 〔F09〕 ^823c3c4c
-
再执行 L2 → L1,记录合并统计 ^ae04ba52
F09 _merge_to_parent_level():用完整父块替换命中的子块 ^39adb678
-
按 parent_chunk_id 分组,筛出达到数量阈值的组。 ^3c315c14
-
批量回查对应父块全文。 ^b6432af7
-
用父块替换同组子块,保留最高分;缺失父块则保留子块。 〔调用 F11〕 ^79d899f6
F11 _merge_rank_score_into():父块取子块最高分 ^cfd23899
- 获取子块分数 〔调用 F10〕 ^f8aa1252
F07 _empty_merge_meta():初始化合并统计 ^c9a1b698
- 记录检索块合并开关、阈值与初始计数。 ^caf57b48
精排、排序与阈值(从下往上) ^65d1a7fa
F14 _rerank_documents():可选精排并截取 Top-K ^b7d3f044
-
启用精排时,用 Query 与候选正文请求 Rerank API。 〔调用 F13〕 ^2edc421c
-
按精排结果重排候选,记录精排分数并取 Top-K。 ^fb561e24
-
未启用或请求失败时,按原有效分数排序取 Top-K。 〔调用 F12〕 ^6be4d194
F13 _get_rerank_endpoint():获取精排模型接口地址 ^5b3af2e5
- 在配置的 Host 后补齐 /v1/rerank。 ^87feb994
F12 _sort_by_rank_score():按分数排序 ^3b7a84d6
- 按有效分数降序排列。 〔调用 F10〕 ^caad71cc
F10 _effective_score():取有效排序分数 ^f829cc36
- 优先使用 rerank_score,否则使用召回 score。 ^b229dc30
F15 _meets_rerank_min_score():判断证据是否达标 ^014b7742
- 比较有效分数与最低分数阈值。 〔调用 F10〕 ^a97fbfd8
重写与公共辅助 ^4449459d
F19 rewrite_query_once():查询重写 ^7d12cfef
-
让模型选择重写方式并输出结果(输出校验): step back / HyDE ^32aabfc8
-
返回重写 Query以及重写模型的输出 ^795865f1
F18 _get_rewrite_model():获取重写模型 ^726bf595
- 按需创建并复用改写模型。 ^053a77ed
F16 dedupe_documents():子问题合并时,子块去重 ^cac19c6b
-
按 Chunk ID 去重,缺失时用来源与正文识别。 ^ae5aef03
-
保留首次出现位置,重复项保留较高分。 〔调用 F11〕 ^c7c38762
F01 _optional_env():读取有效的可选配置 ^177f327d
- 读取环境变量,过滤空值和示例占位符。 ^c65d2db8
F02 _read_positive_int_env():读取正整数配置 ^dd56714d
- 读取并限制为正整数,无效时采用默认值。 ^4167c790
F03 _read_float_env():读取浮点配置 ^87513115
-
读取浮点参数,无效时采用默认值。 ^3ff4cded
-
记录合并配置 〔调用 F07〕 ^VqihvTaZ
-
比较源与目标分数,保留较高值(这里要判断用初始检索分数还是rerank分数,单次检索合并肯定在rerank前,但是复杂问题分成子问题后就不同了) ^MtNLwjYm
本模块包含两个功能: 1. 召回检索入口 2. rag pipeline 辅助函数: 文档去重 检索trace 查询重写 ^5EOSoVvr
-
复杂问题拆后每个子问题可能检索到重复的L3,为了防止干扰子块到父块的合并,需要去重 ^YgXOTZSQ
-
获取重写模型〔调用 F18〕 ^7o8Jf9nc
-
定义重写模型输出结构
-
定义重写提示词 ^n0pEdLYu
C01 RewritePlan:查询改写协议 ^fJbp6k44
-
属性:method、退步问题、HyDE 假设文档。 〔传递 F19:1〕 ^6zShMGda
-
约束:只选择一种方法,并填写对应内容。 ^Bd72SqVT
Element Links
70f0c5d1: [[3_代码实现_检索模块]]
%%
Drawing
1 | N4KAkARALgngDgUwgLgAQQQDwMYEMA2AlgCYBOuA7hADTgQBuCpAzoQPYB2KqATLZMzYBXUtiRoIACyhQ4zZAHoFAc0JRJQgEYA6bGwC2CgF7N6hbEcK4OCtptbErHALRY8RMpWdx8Q1TdIEfARcZgRmBShcZQUebR4ATm0ARho6IIR9BA4oZm4AbXAwUDBSiBJuCAAGbGwAMzrkgFYqtNLIWERKwOwojmVgtrLMbgAWKv4ymG4Equ0E0Z4AZiqA |
%%