项目实现 · 统一目录总图
总图采用一棵 backend 目录树。同一文件夹只出现一次,模块编号表示教程归属;目录内部用左右区域区分模块。图 1 模板文件保持原样,总图使用该模板当前的文件、类与函数内容。
目录合并
| 目录 | 模块归属 | 内容 |
|---|---|---|
| indexing/ | 模块 2 左;模块 1 右 | 解析、HTML、编码、Writer;Milvus 与父块 Store |
| rag/ | 模块 4 左;模块 3 右 | LangGraph 证据工作流;召回、合并、精排与改写 |
| chat/ | 模块 7 左;模块 6 右 | 对话编排;Runtime、请求 ctx、会话存储 |
| tools/ | 模块 5 | 知识与天气 Tool |
| schemas/ | 模块 6 | Chat、Trace、HITL 协议 |
| infra/、db/、env.py | 模块 1 | 连接与缓存、ORM 模型、环境加载 |
箭头含义
- 实线:函数调用或 LangGraph 的节点调度。
- 虚线:数据 / 对象传递,包括 ctx、模型、证据、状态和批量记录。
- 远距离使用编号引用,避免穿越多个模块。
4.F33表示模块 4 里的 F33;内部冒号表示目标步骤。 - 工厂返回闭包 Tool,传入 ctx 不表示立即执行检索。Writer 调用编码和写入服务,EmbeddingService 不直接调用 MilvusStore。
- 图 1 文件本身的图形、文本与连线不修改;总图只重新安排文件位置,合并目录,并重建少量近处连线。
主流程
- 问答调用:Service 执行 Agent → 知识 Tool → RAG 图 → 检索入口 → 知识存储;证据逐级返回后由 Agent 回答,Service 保存。
- ctx 传递:Service 创建 → Runtime 接收 → 知识 Tool 闭包绑定 → RAG 节点共享;步骤事件经 Queue 返回流式 Service。
- 入库数据:DocumentLoader 输出三级 Chunk;教程调用方先筛选 L1/L2 写 PG / Redis,再筛选 L3,经 Writer 编码、组装后写 Milvus。
- HITL:metadata 保存任务与快照 → 下一轮用户补充 → 专用入口重建状态并检索评分 → Service 依据新证据直接回答或继续追问。
子图
- [[source/_posts/LLM/2_RAG/project/img/详细实现/图_1数据存储模块]]。
- [[source/_posts/LLM/2_RAG/project/img/详细实现/图_2文档入库模块]]。
- [[source/_posts/LLM/2_RAG/project/img/详细实现/图_3检索模块]]。
- [[source/_posts/LLM/2_RAG/project/img/详细实现/图_4RAG工作流模块]]。
- [[source/_posts/LLM/2_RAG/project/img/详细实现/图_5工具层模块]]。
- [[source/_posts/LLM/2_RAG/project/img/详细实现/图_6Agent状态管理模块]]。
- [[source/_posts/LLM/2_RAG/project/img/详细实现/图_7Agent对话编排模块]]。
类、函数均保留;简单函数一句,复杂函数只写主要实现阶段。右侧保留后续模块空间。
跨模块接口
| 来源 | 目标 | 类型与内容 |
|---|---|---|
7.F23 chat_with_agent |
6.F05 ChatRequestContext.for_sync |
调用:创建请求 ctx |
7.F24 chat_with_agent_stream |
6.F06 ChatRequestContext.for_stream |
调用:绑定 Queue / loop |
7.F23 chat_with_agent |
6.F25 create_agent_for_request |
调用:装配 Agent |
6.F25 create_agent_for_request |
5.F01 make_search_knowledge_base |
调用:创建绑定 ctx 的 Tool |
5.F02 make_search_knowledge_base.search_knowledge_base |
4.F33 run_rag_graph |
调用:执行证据工作流 |
5.F02 make_search_knowledge_base.search_knowledge_base |
6.F08 ChatRequestContext.store_rag_trace |
调用:存入 Trace / 快照 |
6.F07 ChatRequestContext.emit_rag_step |
7.F24 chat_with_agent_stream |
传递:Queue 中的 rag_step 事件 |
4.F11 retrieve_initial |
3.F05 retrieve_documents |
调用:初检;改写和恢复检索也复用同一入口 |
3.F05 retrieve_documents |
2.F19 EmbeddingService.get_embeddings |
调用:Query 编码 |
3.F05 retrieve_documents |
1.F28 MilvusStore.hybrid_retrieve |
调用:L3 混合召回;异常后走 Dense 降级 |
3.F09 _merge_to_parent_level |
1.F40 ParentChunkStore.get_documents_by_ids |
调用:回查父块全文 |
2.F21 MilvusWriter.write_documents |
1.F20 MilvusStore.init_collection |
调用:按维度初始化集合 |
2.F21 MilvusWriter.write_documents |
1.F22 MilvusStore.insert |
调用:批量插入 L3 记录 |
2.F19 EmbeddingService.get_embeddings |
2.F21 MilvusWriter.write_documents |
传递:Dense 向量,供 Writer 组装记录 |
7.F23 chat_with_agent |
6.F18 ConversationStorage.save |
调用:保存历史、metadata 与本轮 Trace |
Excalidraw Data
Text Elements
项目实现 · SuperMew 0.1.0 ^2bf96144
总图只保留一棵 backend/:同名目录合并,目录内部按模块左右分区;类与函数按模板粒度展开。 ^927aa4df
实线 = 调用 / 节点调度 虚线 = 数据 / 对象传递 远处关系按“模块号.Fxx”定位,不画长线。 ^56b6953d
问答:主要调用链 ^69f126c1
Service 执行本轮 Agent ^8ccd59d3
7.F23 / 7.F24 ^81c5cda8
执行由 Runtime 装配的 Agent.invoke / astream。 ^dd7cde08
Agent 调用知识 Tool ^af1c46dd
5.F02 ^e3f5198d
先检查本轮一次检索预算。 ^ce040f6b
Tool 调用 RAG 图 ^389b60f3
4.F33 ^a64425de
判断复杂度,检索、评分与路由。 ^de305354
图节点调用检索入口 ^608f9c91
3.F05 ^7d8e5cd8
Query 编码,召回并组织证据。 ^545361bf
检索调用知识存储 ^cc1e8a95
1.F28 / 1.F40 ^cadbbd62
Milvus 召回 L3;必要时回查 L1 / L2。 ^78866b6a
证据逐级返回给 Agent 生成回答,Service 再保存 AI 消息与 Trace。天气 Tool 单独查询天气,不进入知识库。 ^eac9e8c9
本轮对象:ctx 传递 ^9d5209bb
Service 创建请求 ctx ^345b97e7
6.F05 / 6.F06 ^87bf79cb
用户、会话、工具预算;流式请求另有 Queue / loop。 ^6870f211
Runtime 装配 Agent ^386f1495
6.F25 ^35f64d82
接收 ctx,交给知识工具工厂。 ^75d2a53d
知识工具闭包绑定 ctx ^0f3b425e
5.F01 ^82b8195c
Tool 共享本轮预算与检索记录。 ^d06bf5e8
RAG 节点共享 ctx ^09a7ca40
4.F33 ^d72c8e16
上报步骤;Trace 与快照经 Tool 暂存到 ctx。 ^08c11724
虚线只表示同一个请求对象的传递;工厂创建 Tool,并不执行内部检索。Queue 中的步骤事件由流式 Service 消费。 ^dcd306b9
文档入库:父块数据流 ^f89c67aa
DocumentLoader 解析并分块 ^91c74bf9
2.F06 ^cce16c86
输出 L1 / L2 / L3 及父子关联 ID。 ^3bb80f19
教程调用方筛选 parent_docs ^281d79f6
第 2 篇 test_full_indexing_pipeline 示例。 ^927dfd38
选择 L1 / L2,再交给父块 Store。 ^8e9e8a0d
ParentChunkStore 保存父块 ^180da810
1.F39 ^833dac78
父块全文进入 PostgreSQL,并同步到 Redis。 ^ee0a7bbf
这是数据流;实际写入由教程调用方发起。DocumentLoader 自身只解析和分块。父块先于叶块保存。 ^1d3987c2
文档入库:叶块数据流 ^01e449c5
调用方筛选 leaf_docs ^1d4ad548
从同一批 Chunk 选择 L3。 ^24c14cbb
交给 MilvusWriter 分批处理。 ^c91dc7f3
Writer 提取正文 ^e1a0f14f
2.F21 ^689a63f6
从批次中取出 texts。 ^9804e89f
EmbeddingService 编码 ^7f3012a4
2.F19 ^c36ab6aa
正文转换为 Dense 向量。 ^51cc8d01
Writer 组装 insert_data ^422190ff
2.F21 ^e783eced
合并向量、正文、来源与关联 ID。 ^5bd2c9b5
MilvusStore 写入记录 ^dd55d85e
1.F22 ^67ee5970
Milvus 由正文生成 BM25 稀疏向量。 ^4709916e
虚线表示文本、向量与记录的传递。Writer 调用编码和写入服务;EmbeddingService 不直接调用 MilvusStore。 ^b0df70ad
跨轮 HITL:状态与证据传递 ^46c49c92
会话 metadata 保存待补充任务 ^2bae02d6
7.F07 ^871667bf
追问、选项、原问题和必填恢复快照。 ^211346d1
下一轮取快照与用户补充 ^243ee265
7.F16 ^9d235c0c
合入原问题,进入专用恢复入口。 ^4b66d56a
重建状态并重新检索评分 ^8cad991d
4.F32 ^7a8a8f6b
跳过外层 Agent 和复杂度分类。 ^8bd45976
Service 接收新证据 / 状态 ^132be970
7.F17 ^03b4a93c
直接回答,或保存新任务继续追问。 ^502213e6
恢复快照不保存全文。SSE 的 [DONE] 先发出,随后才更新笔记并最终保存消息。 ^6d62d1e2
backend/:统一后端实现 ^751b7096
目录只出现一次;模块号是教程归属,F / C / P 编号用于查找。 ^46f188b0
chat/:会话与运行时 ^2ea9775c
模块 7 · 对话编排 ^03335ca0
[[7_代码实现_Agent 对话编排|P01 service.py:同步 / 流式对话、跨轮 HITL 与长期笔记]] ^2a240d6e
-
导入 storage、请求 ctx、共享模型与 Agent 工厂。 ^c01d9c74
-
设置最近历史窗口为 6 条,维护会话 pending_hitl。 ^03fd8f81
同步入口与长期笔记 ^42064c55
F23 chat_with_agent():同步执行一轮对话 ^7ec34edb
-
读取历史、长期笔记和待处理 HITL。 〔调用 F10〕 ^171d7b37
-
创建 ctx,重置预算,先保存用户消息。 ^6c9ee10d
-
普通路径执行 Agent;有效 HITL 快照走专用恢复与回答。 〔调用 F11 / F16 / F17 / F18〕 ^2447d651
-
整理 Trace,需要补充时生成标准追问与新任务。 〔调用 F07〕 ^9a723bc0
-
更新标题、长期笔记与 pending_hitl。 〔调用 F21 / F19 / F22〕 ^f33a3325
-
保存 AI 消息和 Trace,关闭 ctx。 ^02d1b6aa
F18 _build_context_messages():组合短期历史与长期笔记 ^6efe5e93
-
保留最近 6 条历史消息。 ^eef3814c
-
依次加入长期笔记、最近历史和当前问题。 ^6e42f483
F21 generate_session_title():本地生成会话标题 ^adeda0e7
- 清理首问,截取前 16 个字符作为标题。 ^c3f9a235
F19 _should_update_persistent_note():判断是否维护长期笔记 ^390e829d
- 已有笔记或历史超过 6 条时需要更新。 ^dcd28f9f
F22 _update_persistent_note_sync():用 FAST_MODEL 压缩长期记忆 ^d321bba2
-
组合旧笔记、本轮问答与首次建笔记时的历史。 〔调用 F12〕 ^80f2ebe2
-
调用摘要模型合并为约 500 字内笔记;失败保留旧笔记。 ^118d73ce
F20 update_persistent_note():异步更新长期笔记 ^b0c4deea
- 在线程池中执行同步笔记更新。 〔调用 F22〕 ^2f93cd12
流式入口与证据回答 ^5b694bf2
F24 chat_with_agent_stream():流式执行一轮对话 ^bb485ea8
-
读取会话状态,创建 Queue / ctx,先保存用户消息。 ^ab09ba29
-
HITL 路径在线程池恢复检索,按新证据回答或继续追问。 ^630d9215
-
普通路径创建 Agent,首轮发标题,启动 Worker。 〔调用 F25〕 ^344b7b21
-
持续消费 Queue,发送 SSE;结束时清理未完成 Worker。 ^ec890952
-
整理 Trace / HITL 事件,发送 [DONE]。 〔调用 F08〕 ^8e0b96e8
-
更新长期笔记与 metadata,保存 AI 消息和 Trace。 〔调用 F20〕 ^35ccc540
-
关闭本轮 ctx。 ^f8fbc620
F25 _agent_worker():生产流式内容与结束信号 ^f16e1df8
-
迭代 Agent 输出,过滤工具调用块,只提取 AI 文本。 ^405ba948
-
若 Trace 要求 HITL,抑制普通回答。 〔调用 F01〕 ^40140dd8
-
否则累积文本并写入 Queue。 〔传递 F24:4〕 ^61905a8d
-
异常时发送错误事件;结束时写入终止信号。 ^7c1273fc
F12 _extract_ai_content():统一提取模型文本 ^65a127e3
- 从字符串或混合内容块中提取文本。 ^0ab85952
F13 _format_retrieved_chunks():整理恢复检索的证据 ^3603b540
- 给片段编号,拼接文件、页码与正文。 〔传递 F14:2〕 ^e23add8d
F14 _build_resume_answer_messages():构造恢复后的回答输入 ^dd5652a7
-
整理新证据,约束模型依据证据并带编号引用。 〔调用 F13〕 ^b8e66b6b
-
组合原问题、追问与用户补充,生成模型消息。 ^dca6ef79
F15 _no_knowledge_response():无可靠知识时的固定提示 ^f74001a6
- 告知当前证据不足,暂时无法回答。 ^ea474999
跨轮 HITL 恢复 ^56b2a666
F10 _current_pending_hitl():读取有效的待补充任务 ^56a325af
- 按 PendingHitlState 校验 metadata 中的任务,无效则忽略。 ^72879ee0
F11 _pending_resume_state():取得恢复快照 ^c0cb357f
- 从待处理任务中复制 resume_state。 ^83f173a5
F06 _existing_hitl_answers():整理此前用户补充 ^abc3e97a
- 从待处理任务中提取有效的已补充答案。 ^56bb231e
F09 _build_hitl_resume_query():构造兼容路径的继续请求 ^11bff081
-
组合原问题、追问与此前补充。 〔调用 F06〕 ^948d2d0d
-
加入本轮补充,提示继续原任务。 ^3013aa9d
F16 _resume_rag_from_hitl_sync():调用专用 RAG 恢复入口 ^adb2c93f
-
取出有效快照。 〔调用 F11〕 ^73ea63eb
-
携带用户补充与 ctx,调用 resume_rag_from_hitl()。 ^a30db3d9
F17 _answer_resumed_rag_sync():依据恢复证据直接回答 ^ebea25db
-
无可用证据时给出无知识提示。 〔调用 F15〕 ^14da9a17
-
有证据时构造回答输入,调用主模型并提取文本。 〔调用 F14 / F12〕 ^91dba5e2
HITL 任务与事件构造 ^626e1633
F07 _build_pending_hitl():构建待处理 HITL 任务 ^01ee414e
-
提取追问、选项与路由。 〔调用 F03 / F04 / F02〕 ^a9f54a1e
-
加入原问题、补充历史、恢复快照和任务标识。 ^15b26e3d
-
按 PendingHitlState 校验。 ^b2dbc241
F03 _hitl_prompt_from_trace():获取追问文本 ^e2b6d32b
- 采用 Trace 的追问,缺失时按类型生成默认提示。 〔调用 F02〕 ^4ae4bfaa
F02 _hitl_route_from_trace():识别追问类型 ^ffe5eca4
- 区分补充条件 clarify 与选择方向 scope_select。 ^ba2ec629
F04 _hitl_options_from_trace():整理方向选项 ^aa7f300a
- 清理选项列表,去除空项。 ^1776aaf5
F05 _format_hitl_message():组合可保存的追问 ^0adfd515
- 把追问与可选方向组合为消息正文。 ^3b0ce0ab
F08 _build_hitl_event():构建对外 HITL 事件 ^e918b5c7
- 提取任务标识、追问、选项与状态,不暴露恢复快照。 ^c9bcc79a
F01 _is_hitl_trace():识别待补充状态 ^7ebe16c2
- 根据 Trace 的状态或路由判断是否需要 HITL。 ^d60f1127
模块 6 · 运行状态与存储 ^bce32bf0
[[6_代码实现_Agent 状态管理|P04 runtime.py:共享模型与按请求创建 Agent]] ^1474b11f
-
初始化共享主模型 model 与摘要模型 fast_model。 〔传递 F25:2〕 ^824508bb
-
定义工具使用规则与回答提示词。 ^af7ad419
F25 create_agent_for_request():装配本轮 Agent ^e7ef05a1
-
将 ctx 绑定到知识工具。 ^18dd7c81
-
组合主模型、知识 Tool、天气 Tool 与系统提示词。 ^e80ec15f
[[6_代码实现_Agent 状态管理|P02 request_context.py:一次请求共享的运行状态]] ^369d54b9
- Service 创建本轮 ctx,显式传给 Tool 与 RAG。 ^16d61700
C15 ChatRequestContext:请求内的状态与事件容器 ^abadfd3e
-
属性:用户 / 会话、Queue / loop、Trace、工具预算、计时。 ^ed18c80f
-
并发:RLock 保护共享状态,事件循环负责跨线程投递。 ^8333156e
F05 for_sync():创建同步请求 ctx ^56722000
- 设置用户与会话,不绑定事件队列。 ^4654f4bc
F06 for_stream():创建流式请求 ctx ^f6f961f1
- 绑定用户、会话、输出 Queue 与当前事件循环。 ^f5b74b17
F07 emit_rag_step():向 SSE 队列发送检索步骤 ^16546427
-
在锁内检查请求状态,记录步骤与累计耗时。 ^bdb3d0ba
-
组装步骤与子问题分组信息。 ^3fa6874a
-
通过事件循环,线程安全地写入 Queue。 ^905aa303
F08 store_rag_trace():暂存本轮 Trace 与快照 ^61b953f4
-
规范 Trace,校验可选恢复快照。 〔调用 F04 / C06〕 ^a526f6be
-
在锁内写入本轮暂存结果。 ^8507fd38
F09 take_rag_trace():取走本轮检索记录 ^45bdc55d
- 在锁内读取 Trace 与快照,随后清空暂存。 ^7c52ef27
F10 peek_rag_trace():只读查看本轮检索记录 ^b8550961
- 在锁内查看暂存,不清空。 ^dd82495c
F11 reset_knowledge_tool_budget():重置知识工具预算 ^12dcc00b
- 将本轮知识工具使用次数归零。 ^aa2dc36a
F12 acquire_knowledge_tool_slot():限制一轮只检索一次 ^884419c7
- 在锁内检查并占用一次知识工具名额。 ^9295a3cc
F13 close():关闭本轮 ctx ^269aeebf
- 停用请求,释放 Queue 与事件循环引用。 ^ffc1f4c6
[[6_代码实现_Agent 状态管理|P03 storage.py:PostgreSQL 会话存储与 Redis 缓存]] ^d51f7743
-
复用关系库模型、会话工厂和 Redis cache。 ^63bd5878
-
创建共享 storage = ConversationStorage()。 〔调用 C16〕 ^632e4af9
C16 ConversationStorage:会话存储与缓存接口 ^fb27ae11
-
功能:全量保存、历史读取、会话列表与删除。 ^9bbe0596
-
存储:PostgreSQL 持久化,Redis 缓存消息和列表。 ^3a75f634
F18 save():覆盖保存会话与全量历史 ^a8601a52
-
按用户查找或创建会话,合并传入的 metadata。 ^3554afce
-
删除旧消息,重写本轮提供的全部历史与消息 Trace。 ^a86e8e91
-
提交 PostgreSQL。 ^9fa83e09
-
刷新消息缓存,清除会话列表缓存。 〔调用 F14 / F15〕 ^314aa9b6
F19 load():读取供模型使用的历史 ^fae98980
-
优先读消息缓存,未命中则查询并缓存消息记录。 〔调用 F23〕 ^93a33213
-
转换为 LangChain 消息列表。 〔调用 F16〕 ^50fad32f
F20 load_with_meta():读取历史与会话元数据 ^39f28b2f
-
调用 load() 读取模型消息。 〔调用 F19〕 ^dba58015
-
从 PostgreSQL 读取对应 metadata。 ^e61ebf13
F16 _to_langchain_messages():把历史记录转为模型消息 ^5837de69
- 按消息类型构造 Human / AI / System Message。 ^5f328c03
F23 get_session_messages():读取完整历史消息记录 ^e6490c3a
-
优先读缓存,并规范其中的 Trace。 〔调用 F17〕 ^bc4ab975
-
未命中则按消息顺序查询 PostgreSQL。 ^9660b573
-
整理正文、时间与 Trace,写入缓存。 ^d8db659e
F17 _normalize_message_records():规范历史消息 Trace ^f2006ece
- 逐条规范消息记录中的 rag_trace。 〔调用 F04〕 ^8257cbe6
F21 list_sessions():获取会话 ID 列表 ^cfa4a963
- 从会话摘要列表提取 session_id。 〔调用 F22〕 ^4cbff851
F22 list_session_infos():读取会话摘要列表 ^44a69389
-
优先读列表缓存。 ^79caa3d7
-
未命中则查询用户会话,按更新时间倒序排列。 ^6ef0fea5
-
整理标题、时间和消息数,写入缓存。 ^ac1c6cd1
F24 delete_session():删除用户会话及缓存 ^d5ea4835
-
按用户与会话 ID 查询记录。 ^3f11b850
-
删除会话并提交,级联删除消息。 ^5326f598
-
清除消息缓存和会话列表缓存。 ^5ebe833f
F14 _messages_cache_key():生成消息缓存键 ^5d983bcf
- 拼接 chat_messages:用户:会话。 ^b3e4fa04
F15 _sessions_cache_key():生成会话列表缓存键 ^484da79f
- 拼接 chat_sessions:用户。 ^1a5768da
rag/:证据决策与检索算法 ^efc3a2a3
模块 4 · RAG 工作流 ^91e11b31
[[4_代码实现_RAG Pipeline|P01 pipeline.py:RAG 检索、评分与路由工作流]] ^5b7f636b
-
定义图状态、复杂度与证据评分协议。 ^ceb776df
-
注册节点与路由,编译共享 rag_graph。 〔调用 F29〕 〔传递 F33:1〕 ^429c5875
C01 EvidenceGrade:证据评分协议 ^1297263a
-
属性:相关性、可回答性、歧义、置信度与路由。 ^80e59079
-
补充信息:评分原因、缺失条件、追问与选项。 ^19f3141f
C03 RAGState:图执行共享状态 ^6cc34d7b
-
检索:原问题、当前 Query、证据、上下文。 ^cb6163fe
-
决策:评分、路由、改写次数、复杂度。 ^05efb377
-
并行:子问题与子结果;运行时:请求 ctx 与步骤分组。 ^1de906ef
C02 ComplexityResult:问题规划协议 ^26b4485a
-
属性:simple / complex、判断原因、子问题列表。 ^d5743084
-
约束:最多 4 个子问题。 ^14a1d233
启动、状态与快照 ^6cb01444
F33 run_rag_graph():正常 RAG 执行入口 ^fff31331
-
初始化本轮状态,调用共享 rag_graph。 〔调用 F10〕 ^7f3d6c29
-
需要用户补充时附上恢复快照。 〔调用 F06 / F07〕 ^e0d7b192
F29 build_rag_graph():组装 LangGraph 工作流 ^dab2fef0
-
注册图节点,以复杂度判断为入口。 ^75735af8
-
简单链:初检 → 评分 → 可选一次改写再检索。 ^119d2554
-
复杂链:并行子检索与评分 → 汇总;编译工作流。 ^e35a1a01
F10 _initial_state():初始化图状态 ^b1222f0e
-
设置问题、Query、证据与路由等初始值。 ^394b9737
-
绑定请求 ctx,初始化改写次数和子问题状态。 ^90bbb0b1
F06 _is_hitl_result():判断是否需要用户补充 ^824b8b2d
- 根据结果或 Trace 中的状态、路由识别 HITL。 ^e672431e
F07 _build_hitl_resume_state():构建跨轮恢复快照 ^83545f3c
-
提取原问题、路由、改写次数与子问题规划。 ^26f9bd47
-
按 HitlResumeState 校验为最小快照。 ^2aa480bf
F09 _emit():上报 RAG 进度 ^96b82e93
- 通过请求 ctx 发送步骤与子问题分组信息。 ^995ba4b1
分类、召回与并行子问题 ^0c0faeae
F23 classify_complexity():判断复杂度并规划子问题 ^6c17bbf0
-
先尝试本地简单问题规则。 〔调用 F22〕 ^f09fec01
-
未命中时调用 FAST_MODEL,复杂问题最多规划 4 个子问题。 〔调用 F02〕 〔传递 F25:1〕 ^6a70c78f
F22 _simple_question_fast_path_reason():本地识别明确的简单问题 ^ae4c99d4
-
根据长度、简单事实与复杂意图标记判断。 ^b818dff3
-
明确简单时命中快速路径,其余交给模型。 ^b88ad923
F02 _get_complexity_model():获取复杂度规划模型 ^ca12df88
- 按需创建并复用 FAST_MODEL。 ^f65c91a4
F11 retrieve_initial():执行首次检索 ^19fb2c11
-
调用检索入口获取证据与检索信息。 ^08da8585
-
将证据整理为上下文。 〔调用 F03〕 ^11d76445
-
写入初检 Trace,并上报检索步骤。 ^b59a648e
F03 _format_docs():整理带来源的证据上下文 ^30cc9425
- 给证据编号,拼接来源、页码与正文。 ^1a4ae952
F24 prepare_sub_questions():准备并展示子问题 ^7aae0dd1
- 整理已规划的子问题,并逐条上报。 〔调用 F26〕 ^de7796e5
F25 _route_after_complexity():选择简单或复杂路径 ^2c0f2e66
- 简单问题进入初检;复杂问题进入子问题分发。 〔调用 F11 / F24〕 ^8c262ea8
F26 _fanout_sub_questions():分发并行子任务 ^23dce3f0
-
为每个子问题创建独立状态,共享请求 ctx。 〔调用 F10〕 ^40e7a647
-
通过 Send 分发到 rag_sub_agent。 〔调用 F27〕 ^7b895aee
F27 rag_sub_agent():执行单个子问题 ^42fac62c
-
依次执行初检和证据评分,不做查询改写。 〔调用 F11 / F19〕 ^9ec3b67e
-
汇集该题证据与状态,交给汇总节点。 ^87875861
证据评分与决策路由 ^e35fe4b7
F19 grade_documents_node():评分证据并决定下一步 ^7f358257
-
无证据直接生成无知识评分;有证据调用评分模型。 〔调用 F16 / F01〕 ^d157ec8b
-
校正模型路由,更新评分状态与 Trace。 〔调用 F17 / F18〕 〔传递 F13:1〕 ^7927368e
-
HITL 或无知识时清空对外证据;上报决策步骤。 ^934757f3
F16 _grade_for_no_docs():无证据时跳过评分模型 ^7c31727e
- 直接生成无知识的评分结果。 ^fe83b801
F01 _get_grader_model():获取证据评分模型 ^c5d35d0f
- 按需创建并复用 GRADE_MODEL。 ^a5e0c32e
F17 _resolve_route():按确定性规则校正路由 ^75d52ab6
-
无证据或主题无关:no_knowledge。 ^48f1a27d
-
缺条件:clarify;方向不唯一:scope_select。 ^d7ef9a75
-
支持回答则 answer;子问题不进入改写。 ^d9da678b
-
主问题有预算可 rewrite;预算用尽后按证据转澄清或无知识。 ^06489a0c
F18 _grade_update():整理评分与路由更新 ^cbbc4b28
-
将路由转换为检索状态,必要时生成追问。 〔调用 F14 / F15〕 ^d9c909f2
-
组合评分、缺失条件、选项等状态字段。 ^5d88a2c9
F14 _retrieval_status_for_route():将路由映射为展示状态 ^47812b2f
- 将 answer / rewrite / HITL / no_knowledge 转为检索状态。 ^58d9fb94
F15 _default_hitl_prompt():生成用户补充提示 ^fff2bcfa
- 优先采用评分模型的追问,否则按缺失条件或选择方向生成。 ^de70539e
F13 _route_after_grade():决定是否进入改写 ^9f3a6bd2
- 路由为 rewrite 时进入改写,否则结束本次图执行。 ^8a11f0d5
改写、恢复与收尾 ^77033feb
F20 rewrite_question_node():在一次预算内改写问题 ^3264a092
-
检查是否还有改写预算。 ^cdbddc0b
-
调用 Step-back / HyDE 改写并校验新 Query。 ^e411b589
-
增加改写次数,保存方法与新 Query。 〔传递 F21:1〕 ^bf36f1b7
F21 retrieve_rewritten():按新 Query 再次检索 ^2005097c
-
用改写后的 Query 调用检索入口。 ^924aaa00
-
更新证据、上下文与改写检索 Trace。 〔调用 F19〕 ^2c6cafbb
F28 synthesis():汇总子问题证据 ^0d50ba10
-
收集可回答子问题的证据,保序去重。 ^0fd8d937
-
合并上下文与各子问题 Trace。 ^88db97a1
-
有证据则可回答;否则继续 HITL 或判为无知识。 ^1c8eca90
F32 resume_rag_from_hitl():跨轮补充后的恢复入口 ^4b816870
-
根据快照与用户补充重建状态。 〔调用 F30〕 ^53831170
-
执行针对性检索与评分,跳过复杂度判断。 〔调用 F31〕 ^f8e2abec
-
仍需补充时生成下一轮快照。 〔调用 F07〕 ^67cb7659
F30 _state_from_resume():按快照重建检索状态 ^446ea812
-
校验快照,将用户补充合入原问题。 〔调用 F08〕 ^f8ca0b91
-
初始化新状态,恢复改写次数、规划信息和恢复 Trace。 〔调用 F10〕 ^cb1b1475
F08 _refined_question_for_hitl():把用户补充合入原问题 ^cfe4a612
- 合并原问题与本轮补充,避免重复拼接。 ^89041dd1
F31 _retrieve_resume_query():补充问题的针对性检索 ^7c1b1fc4
-
按补充后的问题检索,整理证据与上下文。 ^e8fcabdf
-
记录针对性检索 Trace,再执行证据评分。 〔调用 F19〕 ^48360262
F12 _route_after_initial():初检后路由(未接入主流程) ^0f0f64b1
- 指定下一步为证据评分。 ^dee44364
F05 _copy_jsonable_docs():批量复制证据(未接入主流程) ^59ee6916
- 逐条调用证据字段复制函数。 〔调用 F04〕 ^13cde1c3
F04 _copy_jsonable_doc():复制证据字段(未接入主流程) ^104b3569
- 按白名单复制正文、来源和分数字段。 ^0292bd49
模块 3 · 检索与改写 ^06bd1e62
[[3_代码实现_检索模块|P01 utils.py:召回、合并、精排与查询改写]] ^45716c3d
-
读取召回、父块合并、精排与改写配置。 ^30296f09
-
复用编码模型,创建 MilvusStore 与父块 Store。 ^a68ae53e
C01 RewritePlan:查询改写协议 ^3065e1d4
-
属性:method、退步问题、HyDE 假设文档。 〔传递 F19:1〕 ^ce91af38
-
约束:只选择一种方法,并填写对应内容。 ^5aa284fe
召回入口与收尾 ^6cd3376d
F05 retrieve_documents():检索入口:召回并组织证据 ^24dd3467
-
确定候选数,只召回 L3 叶块。 〔调用 F04〕 ^db2339a7
-
将 Query 编码为 Dense 向量。 ^f4efe989
-
先混合召回;召回或后处理异常时降级为 Dense。 ^6d9744bd
-
调用统一后处理,形成最终证据与检索记录。 〔调用 F06〕 ^09508d6d
F04 resolve_candidate_k():确定召回候选池大小 ^2a9eece6
-
优先使用配置的候选数,否则按 Top-K 的倍数计算。 ^4bdee1ea
-
候选数至少为最终 Top-K。 ^79fa8014
F06 _finalize_retrieval():合并 → 精排 → 阈值过滤 ^251eaaa2
-
在完整候选池中合并父块。 〔调用 F08〕 ^5d39b65a
-
可选精排,截取 Top-K。 〔调用 F14〕 ^0c7e28f5
-
按分数阈值过滤,数量不足不补齐。 〔调用 F15〕 ^9af470cf
F17 retrieval_trace_fields():提取检索过程记录 ^01f96e69
- 按白名单提取需要写入 Trace 的检索字段。 ^17e427ca
L3 → L2 → L1 合并 ^461b2fbf
F08 _auto_merge_candidates():执行两级父块合并 ^9aa0133f
-
开启合并时,先执行 L3 → L2。 〔调用 F07 / F09〕 ^5e847033
-
再执行 L2 → L1,记录合并统计。 〔传递 F14:1〕 ^af0d9d13
F09 _merge_to_parent_level():用完整父块替换命中的子块 ^37a41dae
-
按 parent_chunk_id 分组,筛出达到数量阈值的组。 ^d4a213ee
-
批量回查对应父块全文。 ^35fb516b
-
用父块替换同组子块,保留最高分;缺失父块则保留子块。 〔调用 F11〕 ^ecb21f9b
F11 _merge_rank_score_into():合并证据分数 ^52729619
- 比较来源与目标分数,保留较高值。 〔调用 F10〕 ^0cbc33f4
F07 _empty_merge_meta():初始化合并统计 ^16d08a24
- 记录合并开关、阈值与初始计数。 ^8e6619f8
精排、排序与阈值 ^8e6589c3
F14 _rerank_documents():可选精排并截取 Top-K ^a91acd41
-
启用精排时,用 Query 与候选正文请求 Rerank API。 〔调用 F13〕 ^25742bb2
-
按精排结果重排候选,记录精排分数并取 Top-K。 ^7b67d861
-
未启用或请求失败时,按原有效分数排序取 Top-K。 〔调用 F12〕 ^3dfd2663
F13 _get_rerank_endpoint():规范精排接口地址 ^f7a60e27
- 在配置的 Host 后补齐 /v1/rerank。 ^ef1622f5
F12 _sort_by_rank_score():按分数排序 ^ac4b9d72
- 按有效分数降序排列。 〔调用 F10〕 ^a8f91ad8
F10 _effective_score():取有效排序分数 ^de7b5077
- 优先使用 rerank_score,否则使用召回 score。 ^65a30acb
F15 _meets_rerank_min_score():判断证据是否达标 ^a950c2ff
- 比较有效分数与最低分数阈值。 〔调用 F10〕 ^13c9e7df
单次改写与公共辅助 ^7a406692
F19 rewrite_query_once():生成一次查询改写 ^8f182b98
-
调用 FAST_MODEL,生成 RewritePlan。 〔调用 F18〕 ^ab4d632a
-
选择 Step-back 或 HyDE,校验内容互斥。 ^f284b00f
-
将原问题与辅助文本拼成新 Query;HyDE 只用于检索。 ^af1f5459
F18 _get_rewrite_model():获取 FAST_MODEL 改写模型 ^c0b4e2cd
- 按需创建并复用改写模型。 ^8d699c9e
F16 dedupe_documents():合并重复证据 ^aad22b69
-
按 Chunk ID 去重,缺失时用来源与正文识别。 ^69574390
-
保留首次出现位置,重复项保留较高分。 〔调用 F11〕 ^a26355b2
F01 _optional_env():读取有效的可选配置 ^62dd5bcc
- 读取环境变量,过滤空值和示例占位符。 ^88395095
F02 _read_positive_int_env():读取正整数配置 ^bedac19e
- 读取并限制为正整数,无效时采用默认值。 ^d3c2d130
F03 _read_float_env():读取浮点配置 ^0b3b731c
- 读取浮点参数,无效时采用默认值。 ^9e97f880
indexing/:文档解析、编码与知识库存取 ^312dfb39
模块 2 · 文档入库 ^27b98dff
[[2_代码实现_文档入库|P01 document_loader.py:文档解析、清洗与三级分块]] ^b0d46771
- 定义文本清洗函数和三级分块服务。 ^7994211f
F01 sanitize_text():清洗文档文本 ^2be60fab
-
Unicode NFC 标准化。 ^5cb4761f
-
去除不可见字符、控制字符与私有区乱码。 ^d51c41ab
-
清除不完整的 UTF-8 代理项。 ^0dd79972
C01 DocumentLoader:文档加载与三级分块服务 ^ccaf2553
-
属性:L1、L2、L3 三个递归分块器。 ^ee637c61
-
功能:单文件解析、文件夹批量解析、三级分块。 ^84fb3e0e
F02 init():初始化三级分块器 ^3a5f5e63
-
设置 L1 / L2 / L3 的块大小与重叠长度。 ^948e692a
-
创建三个递归文本分块器。 〔传递 F04:1〕 ^a349de6e
F07 load_documents_from_folder():批量读取文件夹中的文档 ^957c2a1b
-
遍历支持的文件,逐个调用 load_document()。 〔调用 F06〕 ^d2b2631b
-
汇总分块;失败文件跳过。 ^d7b00bbb
F06 load_document():按文件类型解析并分块 ^2ffd2d2a
-
根据后缀选择 PDF / Word / Excel / HTML 解析器。 ^469add1e
-
读取为 LangChain Document;HTML 走章节解析。 〔调用 F16〕 ^2b961495
-
统一清洗、分块,得到三级 Chunk。 〔调用 F05〕 ^eb8f6834
F05 _load_from_langchain_docs():将解析结果转换为三级分块 ^a5f5ec04
-
逐页提取正文与文件、页码等来源信息。 ^d6dfe219
-
清洗正文及来源字段。 〔调用 F01〕 ^0b2d4735
-
调用三级分块,汇总全部 Chunk。 〔调用 F04〕 ^7335711d
F04 _split_page_to_three_levels():按父子关系切出三级 Chunk ^8554a792
-
整页切成 L1,记录 root_chunk_id。 〔调用 F03〕 ^f63fe460
-
每个 L1 再切 L2,记录 parent / root ID。 ^f850ab95
-
每个 L2 再切 L3,补齐关联 ID 与块序号。 ^dc739fd8
F03 _build_chunk_id():生成分块 ID ^8ebc7b3b
- 按 文件名::页码::层级::序号 拼接 chunk_id。 ^d6d729cc
[[2_代码实现_文档入库|P04 milvus_writer.py:批量编码并写入 Milvus]] ^d52064a1
- 组合 EmbeddingService 与 MilvusStore。 ^68382dd7
C03 MilvusWriter:文档向量化与写入服务 ^165f9789
-
属性:embedding_service、milvus_manager。 ^ae12bbba
-
功能:文档批量编码、记录组装、写入和进度回调。 ^f27e418f
F20 init():绑定编码和存储服务 ^7b7640f2
- 保存传入或默认的 EmbeddingService、MilvusStore。 ^de9a4046
F21 write_documents():按批次写入文档分块 ^4c53a24f
-
获取向量维度,初始化 Milvus 集合。 ^a0e39580
-
分批提取文本,调用 EmbeddingService 编码。 〔调用 F19〕 ^1dcfc82a
-
组合向量、正文、来源与 Chunk 关联字段。 ^cad4d253
-
批量插入 Milvus,更新处理进度。 ^185c9fb2
[[2_代码实现_文档入库|P02 html_processor.py:把 HTML 正文转换为章节 Document]] ^9e5128aa
- HTML 读取 → 去噪 → 正文提取 → 章节切分。 ^aeb338ff
F16 load_html_for_document_loader():适配 DocumentLoader 的输入 ^e9b8e5d6
-
调用 HTML 章节解析。 〔调用 F15〕 ^0876c843
-
将章节包装为 Document,附章节页码和来源。 ^57d79b3d
F15 parse_html_file_to_sections():完成 HTML 正文与章节解析 ^c95cba56
-
读取并解析 HTML,清理噪声。 〔调用 F08 / F09〕 ^cc829737
-
选择正文区域,提取标题并线性化正文。 〔调用 F10 / F13 / F12〕 ^8ece0ee4
-
按章节切分。 〔调用 F14〕 ^0bf3bea4
F08 _read_html_text():按网页编码读取 HTML ^8e42da30
- 识别 BOM / charset,选择编码解码文件。 ^cdcc80e3
F09 _strip_noise():去除网页噪声 ^ba8a7454
- 删除脚本、样式、嵌入标签与注释。 ^55195e81
F10 _pick_root():选择正文区域 ^c57181c2
- 按 main → article → body 的顺序选正文。 ^728f2474
F13 _doc_title():提取网页标题 ^b704fa5c
- 读取 title 标签文本。 ^585a3845
F12 _linearize_blocks():按原顺序提取正文 ^9187d7cc
-
先把 br 转为换行。 〔调用 F11〕 ^ebb406b6
-
依次提取标题、段落、列表等,保留标题层级。 ^9da27429
-
结构化文本过少时改用纯文本正文。 〔传递 F14:1〕 ^14e20873
F11 _br_to_newlines():保留网页换行 ^09f9dc97
- 将 br 标签替换为换行符。 ^7e989ec3
F14 _split_into_sections():按二级标题切分章节 ^c5fcfcd9
-
按二级标题拆分正文。 ^aae3ed1b
-
为各章节添加标题与页码;无章节则作为一页。 ^21e294ba
[[2_代码实现_文档入库|P03 embedding.py:共享文本向量化服务]] ^a8750f68
- 创建全进程共享的 embedding_service。 〔调用 F18〕 〔传递 F20:1〕 ^72199698
F17 _create_dense_embedder():加载本地 Dense 模型 ^c0d8a501
-
读取模型与设备配置,默认 bge-m3。 ^ca622def
-
创建启用向量归一化的 HuggingFaceEmbeddings。 ^fbed8dd2
C02 EmbeddingService:文本向量化服务 ^96be2a87
-
属性:共享的 Dense 编码模型。 ^aee49dea
-
功能:文档与 Query 使用同一模型编码。 ^97798f3f
F18 init():初始化向量编码器 ^e10804fc
- 加载并保存 _embedder。 〔调用 F17〕 〔传递 F19:1〕 ^6839e6b5
F19 get_embeddings():批量文本编码 ^f7f2fc75
- 调用模型,将文本列表编码为 Dense 向量。 〔传递 F21:3〕 ^284108d9
模块 1 · 知识存储 ^f7b46df0
📍P05 milvus_client.py:无状态 Store 配合短生命周期 Milvus 连接 ^c33ed148
定义向量数据库配置 ^4f756427
F13 milvus_client_session():在一次上下文中管理客户端连接 ^b582edc6
- 根据配置创建并返回数据库连接对象 〔→ F12〕 ^cf10640d
F14 _normalize_filter():避免查询为空 ^d0aa006c
- strip() 清理过滤表达式
- 空值替换为 id >= 0 ^801b4198
F36 get_milvus_store():懒创建并返回共享 Milus 实例 ^70589204
-
全局变量:创建 MilvusStore()。 〔→ F15〕 ^5becbf34
-
向量数据库封装: ^e3a1ca03
连接向量数据库 ^b607e2e6
条件过滤处理 ^b43d528b
向量数据库操作 ^7f961928
C06 MilvusSettings:不可变的连接与集合配置 ^306da7a0
F12 from_env():从环境变量生成 Milvus 配置 ^32f8201f
-
从环境变量生成 Milvus 配置 ^932581e2
-
定义属性: 主机,端口,表名,url,超时时间 ^3a40944e
-
定义初始化配置函数 ^d2a0f30a
C07 MilvusStore:向量数据库读写、检索与连接回调的统一入口 ^83834632
- 只持有 _settings,@property 暴露 collection_name。
- 一个类对应一个表 ^bfa181d9
F15 init():初始化配置 ^bc895606
1.初始化向量数据库配置 ^bac6ad26
F16 collection_name:获取表名 ^ff0eb2c7
- 从配置获取表名 ^12d2effd
F17 _run():统一封装的执行函数 ^a8efd039
-
获取当前Milvus客户端 〔→ F13〕 ^59e427f9
-
执行操作 ^3e751be8
F18 session():复用同一条连接 ^a270fb1d
-
with 进入 milvus_client 〔→ F13〕 ^6c3b8dc8
-
yield client 给调用方复用,退出上下文后关闭连接。 ^2d0c61b3
F22 insert():批量插入 ^7a432d52
- 批量插入回调 〔→ F17〕 ^2d56e865
F27 get_chunks_by_ids():根据Chunk ID 查询 ^a631b8dd
- 根据Chunk ID 查询chunk ^a427b33f
F32 delete():删除记录 ^64c75567
- 删除回调 〔→ F17〕 ^e4f7f8bb
F33 has_collection():表是否存在 ^220f6c60
- 回调判断表是否存在 〔→ F17〕 ^f6e19a92
F34 drop_collection():删除表 ^ed86ed6c
- 回调删除 〔→ F17 ,F35〕 ^2e4acc42
F35 _drop():删除表 ^4d8cf6fe
- 表存在则删除 ^04ac61dc
F20 init_collection():数据库初始化,无表则建表 ^07727d3e
-
获取向量维度,默认 1024 ^1add9b72
-
执行初始化 ^1d9fa624
F21 _init():调用建表函数 ^1cca13f0
- 调用建表函数 〔→ F19〕 ^937c33cb
F23 query():单次查询 ^c29b4464
-
规范表达式 〔→ F14〕 ^58a964ff
-
根据表达式和搜索字段回调查询 〔→ F24 / F17〕 ^36a7c6cd
F24 _query():在客户端上执行查询 ^3f5249f7
- 通过客户端执行查询(有最大查询数量) ^6500543c
F25 query_all():分页查询(复用同一次连接) ^80a2aa57
-
规范表达式 〔→ F14〕 ^2cd38b34
-
根据表达式和搜索字段回调查询 〔→ F26 / F17〕 ^116d8cac
F26 _query_all():按 offset 连续拉取所有结果 ^82a1b922
- 循环加偏移量分批查询(有单次最大查询数量)
- 适合查询有大量数据,比如某个文档的所有chunk ^747460f6
F19 ensure_collection():建表、初始化双索引 ^c40ac0e2
- 定义表格字段: id,密集向量,稀疏向量,L3文本,文件名, 文件类型,文件路径,页码,chunk序号, chunkid,父chunkid,根chunkid,块级别
- 定义稀疏向量计算方式:BM25
- 建立密集向量索引: HNSW,内积相似度, 节点最大连接数,候选队列大小
- 建立稀疏向量索引
- 创建表 ^16657293
F23 query():单次查询 ^6ade7303
-
规范表达式 〔→ F14〕 ^1d9367de
-
根据表达式和搜索字段回调查询 〔→ F24 / F17〕 ^d37ce84f
F24 _query():在客户端上执行查询 ^70f1fdcc
- 通过客户端执行查询(有最大查询数量) ^78a7c420
F30 dense_retrieve():向量检索 ^0f1534bd
-
回调检索函数 〔→ F31 / F17〕 ^b543f6f8
-
返回检索结果 ^8ebb2c6e
F31 _search():执行向量检索 ^992a706e
- 执行检索,检索参数: 距离度量,候选队列长度,top_k,过滤条件 ^a3206b55
F28 hybrid_retrieve():混合检索 ^dd02d82a
-
回调检索函数 〔→ F29 / F17〕 ^c3011d66
-
返回检索结果 ^fbd2c5a8
F31 _search():执行混合检索 ^8e69bca2
-
执行检索,检索参数: 向量检索请求, 稀疏检索请求,top_k,重排序 ^3531d71c
-
定义向量检索请求(有参数)
-
定义稀疏检索请求(有参数)
-
定义重排方式 ^e9e2cdce
📍P06 parent_chunk_store.py:组合 PostgreSQL 与 Redis 存取父块 ^a34df85a
- 导入共享 redis cache、数据库会话、父块表模型。 ^5b859274
C08 ParentChunkStore:基于 PostgreSQL + Redis 的父级分块存储 ^6f1b0f18
- 优先redis读取,写入同步更新,提供如下功能: 1. 父块写入/更新 2. 父块查询 3. 批量删除父块 ^59542fc4
F39 upsert_documents():批量往数据库、redis更新或插入父块 ^c9e7f3ff
-
创建 SessionLocal() 数据库会话。[P02:3] ^d691e01c
-
逐条读取输入的chunk: ^0ff23396
-
组装准备写入字段
-
数据库已有则更新,无则插入 ^c0a01e67
-
写入redis 〔→ F38 / F09〕 ^b28144a4
F40 get_documents_by_ids():根据 id查询块,先redis后数据库 ^cfeb8e12
-
先查redis 记录命中结果和缺失 ID 〔→ F38 / F08〕 ^33bfb2dc
-
若有缺失 ID,创建会话,使用数据库一次查询 ^a19b110b
-
缺失者写入Redis 〔→ F37〕 ^576ded7b
F41 delete_by_filename():按文件名批量删除数据库记录、redis ^015f1085
-
查询该文件的父块及 ID 列表 ^d76284b7
-
批量删除并提交 PG,然后逐 ID 删除 Redis ^695639c4
F37 _to_dict():把数据库记录转为python字典 ^be2efa17
- 把数据库记录转为python字典 ^4180e4eb
F38 _cache_key():生成块的redis key ^7bafb71e
- 把 chunk_id 拼为 parent_chunk:chunk_id
- 此时未加前缀 ^4dd3c506
tools/:Agent 可调用工具 ^08d66b30
模块 5 · 知识与天气 ^ee9ef1b0
[[5_代码实现_工具层|P01 knowledge.py:把请求 ctx 绑定为知识工具]] ^617aea93
- 由 Runtime 为每个请求创建独立的知识 Tool。 ^8eff1c5f
F01 make_search_knowledge_base():创建本轮知识 Tool ^8384ed8b
- 用闭包绑定 ctx,将内部函数包装为 LangChain Tool。 〔传递 F02〕 ^704a747a
F02 search_knowledge_base():执行知识检索工具 ^085dd02b
-
申请本轮一次知识工具调用名额。 ^c38739f2
-
执行 RAG 图,收集证据与检索状态。 ^7b847755
-
将 Trace 和恢复快照写入 ctx。 ^925f77f1
-
按状态提供证据、HITL 追问或无知识提示。 ^9bd2c190
[[5_代码实现_工具层|P02 weather.py:高德天气查询与 Tool 包装]] ^da5826d1
- 读取天气 API 配置,对外提供天气 Tool。 ^51b18157
F04 get_current_weather_tool():LangChain 天气 Tool ^2b9d0238
- 把 Tool 参数转交给普通天气查询函数。 〔调用 F03〕 ^c68b5098
F03 get_current_weather():请求并整理天气信息 ^c20912b1
-
检查地区、查询类型和 API 配置。 ^7a274efa
-
请求高德天气接口。 ^e480cac9
-
按实时天气 / 预报整理结果;失败时给出错误提示。 ^95f5405f
[[5_代码实现_工具层|P03 init.py:统一工具导出名称]] ^986575e3
-
导出知识工具工厂 make_search_knowledge_base。 ^44141f07
-
将天气 Tool 包装器以 get_current_weather 名称导出。 〔传递 F04〕 ^6dd048cb
schemas/:交换数据协议 ^53e291b3
模块 6 · Chat / Trace / HITL 协议 ^356c8551
[[6_代码实现_Agent 状态管理|P01 chat.py:会话、Trace 与 HITL 数据协议]] ^afb58c56
-
定义请求、消息、Trace 与 HITL 数据类。 ^dba09cc1
-
提供 Trace 规范化函数,供交换与存储前使用。 ^d4f20218
C01 StrictSchema:协议基类 ^3e2b8238
- 约束:禁止未声明字段。 ^30624969
C04 RagSubTrace:单个子问题的 Trace ^8715f117
- 继承公共 Trace 字段。 ^90fd31cf
C07 PendingHitlState:等待用户补充的任务 ^8773541a
-
属性:任务 ID、原问题、追问、选项、已补充答案、创建时间。 ^5dcf7529
-
约束:必须包含 HitlResumeState 恢复快照。 ^601ec55f
C10 MessageInfo:历史消息 ^1ae16381
- 属性:type、content、timestamp、rag_trace。 ^99e2acd0
C13 SessionListResponse:会话列表 ^31aaff4f
- 属性:sessions,元素为 SessionInfo。 ^10a75657
C02 RetrievedChunk:Trace 中的单条证据 ^754deeed
- 属性:来源文件、页码、正文、召回分、排名、精排分。 〔传递 F01:1〕 ^191c9749
C05 RagTrace:完整问题的 Trace ^1f9882df
- 继承公共字段,增加 sub_traces 子轨迹列表。 ^a926edb1
C08 ChatRequest:问答请求 ^88dad1ef
- 属性:message、session_id。 ^21e98bdd
C11 SessionMessagesResponse:会话消息列表 ^01e796e0
- 属性:messages,元素为 MessageInfo。 ^643190fd
C14 SessionDeleteResponse:会话删除结果 ^2e3ace3f
- 属性:session_id、message。 ^f24e453f
C03 RagTraceFields:主 / 子 Trace 公共字段 ^933a8735
-
检索:Query、候选、合并、精排及各阶段证据。 ^65daaea5
-
决策:评分、改写、HITL、复杂度与子问题规划。 ^ff2e7101
C06 HitlResumeState:最小恢复快照 ^10d5c2fd
- 属性:原问题、HITL 路由与状态、改写次数、复杂度和子问题。 ^bc1f6512
C09 ChatResponse:问答结果 ^cbb4ef7c
- 属性:response、rag_trace。 ^162344a6
C12 SessionInfo:会话摘要 ^b6955442
- 属性:session_id、title、updated_at、message_count。 ^6d1c787e
F04 normalize_rag_trace():规范主 Trace 与嵌套子 Trace ^53f6395a
-
清理主 Trace 的公共字段。 〔调用 F02〕 ^99e2cf84
-
逐条规范子 Trace,再按 RagTrace 校验。 〔调用 F03〕 ^98ee7f5b
F03 normalize_rag_sub_trace():规范子问题 Trace ^531b5c1e
- 清理公共字段,按 RagSubTrace 校验。 〔调用 F02〕 ^fe597037
F02 _normalize_trace_fields():规范 Trace 公共字段 ^ec17861d
-
保留协议声明的字段。 ^2cf58459
-
统一规范各检索阶段的证据列表。 〔调用 F01〕 ^b884fca0
F01 _normalize_chunks():规范证据列表 ^b0680808
- 过滤证据字段,按 RetrievedChunk 校验。 ^b75dde84
infra/:关系库连接与缓存接口 ^20459861
模块 1 · 共享基础设施 ^a2e8de1d
📍P02 database.py:配置 PostgreSQL 引擎 ^c4adce7d
-
engine:链接数据库创建的引擎对象。 〔→ P02:3 / F03 / F04:2〕 ^c3cb3e22
-
编译字符清洗正则;在 engine 上注册 before_cursor_execute 监听器。 ^eb74dfdd
-
SessionLocal:创建session工厂,统一数据库会话,禁用自动 flush / 自动提交,提交后对象不过 期。 〔→ F39:1 / F40:2 / F41:1〕 ^382a3d3e
-
Base:生成 ORM 声明基类,用于后续继承创建表。 〔→ P04:1 / F04:2〕 ^9cfca5ab
before_cursor_execute():在 SQL 执行前净化SQL参数 ^3bd2e2c4
-
清洗参数 ^de14d7a4
-
返回清洗结果 ^bb82edda
F04 init_db():数据库初始化并创建尚不存在的表 ^7f898115
- 通过数据库引擎创建基本表/初始化数据库 ^583d9bbc
_clean_nul_chars():递归清洗字符串 ^0e13c301
- 字符串先做 Unicode NFC 标准化。
- 删除零宽字符、BOM 和不可见方向控制字符。
- 删除正则覆盖的非排版控制字符与 PUA 私有区字符。
- 用 UTF-8 ignore 编解码去除残损代理项;异常时逐字符排除代理项。 ^d0ec01f5
📍P03 cache.py:Redis 缓存读取、写入、删除 ^e6800eac
- 创建共享包装对象;Redis 客户端在首次使用时才建立。 〔→ F05〕 ^c814bca6
C01 RedisCache:提供Redis缓存接口 ^a807e56b
F06 _get_client():获取 Redis 客户端 ^be8b5e62
- 有客户端则复用,无则根据redis url新建 ^9c75aa55
F07 _key():给所有key加上前缀 ^d653be19
- 给所有key加上前缀 ^ba735e26
F08 get_json():读取数据 ^e86d97a1
- 通过key读取数据〔→ F06 / F07〕
- 用json.loads() 解码
- 返回python对象 ^ca93dbc3
F09 set_json():写入数据 ^6b89d6e6
- 用 json.dumps读取python对象 〔→ F06〕
- 设置过期时间 ^81324134
F10 delete():删除key ^cc823e93
- 删除key。 〔→ F06〕 ^34227ac7
F11 delete_pattern():按模式批量删除key ^d80c47ba
- pattern加前缀,批量删除匹配的key。 〔→ F06〕 ^118a2db3
F05 init():初始化redis配置 ^10c8248f
- redis url
- 所有key的前缀
- 缓存过期时间(TTL)
- redis 客户端 ^57306e05
db/:关系数据库模型 ^a2ee6bb6
模块 1 · ORM 模型 ^ad30991a
📍P04 models.py:定义四张 ORM 表 ^46f2fe72
-
从 database.py 导入同一个 Base实例 〔→ C02 / C03 / C04 / C05〕 ^00532d12
-
定义四个继承 Base 的类 ^db7d815f
C02 User:用户表 ^e2f810b4
- 属性:id, 用户名,密码哈希,角色,生日
- 约束:用户删除时级联删除其会话。 ^59fa5c0a
C03 ChatSession:会话表 ^cf78ee6c
- 属性:id,用户id,会话id,元数据json,更新时间,创建时间
- 约束: (用户id,会话id)联合唯一, 外键:用户id 删除会话级联删除消息。 ^3904ca9b
C04 ChatMessage:消息表 ^1a3e6c2c
- 属性:id,会话id,类型,内容,时间戳,rag轨迹
- 约束: 外键:会话id ^27c7d342
C05 ParentChunk:父块表(L1/L2) ^07bd5836
- 属性:id,内容,来源文件名,文件类型,文件路径, 页码,父id,根id,块级别,块内序号,更新时间 ^49a79ffe
模块 1 · 环境加载(backend 根目录) ^9b636343
📍P01 env.py:统一加载项目根目录环境变量 ^0a341437
-
获取项目根目录;导入本文件本身不会读取 .env。 ^de369873
-
应用入口或独立脚本先调用 load_env(),再导入依赖环境变量的模 块。 ^eabe8fd5
load_env():只加载一次 .env ^721199e7
-
若 _LOADED 已为 True,说明导入过,直接返回。 ^5cd8a475
-
调用 load_dotenv(PROJECT_ROOT / ".env") 读取配置。 ^22cf1fb0
-
将 _LOADED 置 True,后续调用不重复加载。 ^b224a469
后续模块预留区 ^200db4db
API / 鉴权 / 前端等 当前只展开第 1~7 篇 ^328f8ef3
图 1 文件保持原样;总图采用你修改后的文件内容。其余六图按同一粒度重写。 ^e15c7d25
Element Links
8ccd59d3: [[source/_posts/LLM/2_RAG/project/img/详细实现/图_7Agent对话编排模块]]
af1c46dd: [[source/_posts/LLM/2_RAG/project/img/详细实现/图_5工具层模块]]
389b60f3: [[source/_posts/LLM/2_RAG/project/img/详细实现/图_4RAG工作流模块]]
608f9c91: [[source/_posts/LLM/2_RAG/project/img/详细实现/图_3检索模块]]
cc1e8a95: [[source/_posts/LLM/2_RAG/project/img/详细实现/图_1数据存储模块]]
345b97e7: [[source/_posts/LLM/2_RAG/project/img/详细实现/图_6Agent状态管理模块]]
386f1495: [[source/_posts/LLM/2_RAG/project/img/详细实现/图_6Agent状态管理模块]]
0f3b425e: [[source/_posts/LLM/2_RAG/project/img/详细实现/图_5工具层模块]]
09a7ca40: [[source/_posts/LLM/2_RAG/project/img/详细实现/图_4RAG工作流模块]]
91c74bf9: [[source/_posts/LLM/2_RAG/project/img/详细实现/图_2文档入库模块]]
281d79f6: [[source/_posts/LLM/2_RAG/project/img/详细实现/图_2文档入库模块]]
180da810: [[source/_posts/LLM/2_RAG/project/img/详细实现/图_1数据存储模块]]
1d4ad548: [[source/_posts/LLM/2_RAG/project/img/详细实现/图_2文档入库模块]]
e1a0f14f: [[source/_posts/LLM/2_RAG/project/img/详细实现/图_2文档入库模块]]
7f3012a4: [[source/_posts/LLM/2_RAG/project/img/详细实现/图_2文档入库模块]]
422190ff: [[source/_posts/LLM/2_RAG/project/img/详细实现/图_2文档入库模块]]
dd55d85e: [[source/_posts/LLM/2_RAG/project/img/详细实现/图_1数据存储模块]]
2bae02d6: [[source/_posts/LLM/2_RAG/project/img/详细实现/图_7Agent对话编排模块]]
243ee265: [[source/_posts/LLM/2_RAG/project/img/详细实现/图_7Agent对话编排模块]]
8cad991d: [[source/_posts/LLM/2_RAG/project/img/详细实现/图_4RAG工作流模块]]
132be970: [[source/_posts/LLM/2_RAG/project/img/详细实现/图_7Agent对话编排模块]]
03335ca0: [[source/_posts/LLM/2_RAG/project/img/详细实现/图_7Agent对话编排模块]]
2a240d6e: [[7_代码实现_Agent 对话编排]]
bce32bf0: [[source/_posts/LLM/2_RAG/project/img/详细实现/图_6Agent状态管理模块]]
1474b11f: [[6_代码实现_Agent 状态管理]]
369d54b9: [[6_代码实现_Agent 状态管理]]
d51f7743: [[6_代码实现_Agent 状态管理]]
91e11b31: [[source/_posts/LLM/2_RAG/project/img/详细实现/图_4RAG工作流模块]]
5b7f636b: [[4_代码实现_RAG Pipeline]]
06bd1e62: [[source/_posts/LLM/2_RAG/project/img/详细实现/图_3检索模块]]
45716c3d: [[3_代码实现_检索模块]]
27b98dff: [[source/_posts/LLM/2_RAG/project/img/详细实现/图_2文档入库模块]]
b0d46771: [[2_代码实现_文档入库]]
d52064a1: [[2_代码实现_文档入库]]
9e5128aa: [[2_代码实现_文档入库]]
a8750f68: [[2_代码实现_文档入库]]
f7b46df0: [[source/_posts/LLM/2_RAG/project/img/详细实现/图_1数据存储模块]]
c33ed148: [[1_项目设计#1)milvus_client.py]]
a34df85a: [[1_项目设计#2)parent_chunk_store.py]]
ee9ef1b0: [[source/_posts/LLM/2_RAG/project/img/详细实现/图_5工具层模块]]
617aea93: [[5_代码实现_工具层]]
da5826d1: [[5_代码实现_工具层]]
986575e3: [[5_代码实现_工具层]]
356c8551: [[source/_posts/LLM/2_RAG/project/img/详细实现/图_6Agent状态管理模块]]
afb58c56: [[6_代码实现_Agent 状态管理]]
a2e8de1d: [[source/_posts/LLM/2_RAG/project/img/详细实现/图_1数据存储模块]]
c4adce7d: [[1_项目设计#1)database.py]]
e6800eac: [[1_项目设计#2)cache.py]]
ad30991a: [[source/_posts/LLM/2_RAG/project/img/详细实现/图_1数据存储模块]]
46f2fe72: [[1_项目设计#1)models.py]]
0a341437: [[1_项目设计#1)env.py]]
%%
Drawing
1 | N4IgLgngDgpiBcIYA8DGBDANgSwCYCd0B3EAGhADcZ8BnbAewDsEAmcm+gV31TkQAswYKDXgB6MSgw4CxAHSp6AWzJJMMJTEZgaCANqg8CECwBGAMwCcANgCMAFnurIsY2BRhVyBPYAc5CAQAZjYQIjwwfgQAViD7cn4YbABzQRjfOX8QdEZk9QQABnYwfHoAaxgAYXpMenxjAGJbFiCC+wB2VVN0VDLk0s5GXGra+sQSnJoodHwtT3JzbExMAGV |
%%