DeepRead-项目介绍

DeepRead:把 RAG 做成「会深读、能自证」的研究 Agent

仓库:https://github.com/xliu14462-commits/deepread-agent

一个本地自托管的个人知识库研究代理:你把论文和资料扔进去,它不只会"检索+拼凑",而是像一个认真的研究生一样------先规划、再检索、逐条验证自己写下的每个论断、标注每一处引用的原文出处;证据不足时坦白说"没找到",而不是硬编。

本文完整介绍这个项目的初衷、使用方式、架构与核心技术实现、数据存储设计,以及开发过程中踩过的真实坑。写给想深入了解这个项目的技术读者。

项目速览

维度 数据
代码规模 后端 ~23,000 行 Python / 前端 ~7,500 行 Vue3(单人开发)
数据模型 15 张 MySQL 核心表,16 个 Alembic 迁移,5 个专职存储(MySQL/Qdrant/ES/Redis/MinIO)
Agent 能力 22 个内置工具,L0-L3 复杂度路由,ReAct + Plan + Reflection + Self-Correction 四层元认知
研究编排 LangGraph 驱动 Planner→Researcher→Writer→Reviewer 四类研究角色接力,支持增量重研与死锁检测
知识增强 知识图谱(igraph:Leiden 社区/PageRank/多跳遍历/数值矛盾检测)+ GraphRAG 双检索 + 渐进式合成
质量门禁 实测 :871 个后端测试 + 149 个前端测试全绿,行覆盖率 83%(CI 门禁 80%),ruff lint/format 与 mypy 全量通过
交付 GitHub Actions 三段流水线(PR 质量 → main 集成/安全/评测回归 → tag 发镜像),Docker Compose 一键起 8 个基础设施

配图:对话过程流式卡片截图 / 引用角标悬浮原文 / 知识图谱视图 / 研究报告页面。


### 目录

  • [DeepRead:把 RAG 做成「会深读、能自证」的研究 Agent](#目录 DeepRead:把 RAG 做成「会深读、能自证」的研究 Agent 项目速览 @TOC 一、初衷:我对「检索增强问答」的三个不满 二、DeepRead 是什么,能用来干什么 2.1 产品形态与功能全景 2.2 使用方式:从零到一次问答 2.3 一次提问背后发生的事 三、总体架构 四、核心技术实现 4.1 文档处理管线:异步、三写与版式感知切分 4.2 混合检索:RRF 融合、精排、反馈加权与两级缓存 4.3 Agent 运行时:function-calling ReAct 循环 4.4 工具层:注册表、DAG 调度器与作用域安全 4.5 元认知:复杂度路由、计划、反思、自校验 4.6 成本与性能工程 4.7 可靠性:流式、中断恢复与落库时机 4.8 研究模式编排(LangGraph 四角色接力) 4.9 知识图谱与 GraphRAG 4.10 渐进式合成与分层记忆 4.11 安全设计 4.12 LLM 抽象层 4.13 评测框架 4.14 个人 MCP 接入 4.15 关键选型:为什么自研、为什么这么存 五、数据存储设计 5.1 选型与职责分工 5.2 MySQL 表设计(15 张核心表) 5.3 一致性哲学的三个具体机制 5.4 Redis 的三个角色与降级 5.5 已知取舍与盲区(主动交代) 六、工程质量:测试、CI 与交付 七、踩过的坑:这些问题教会我的事 八、技术要点索引 九、未来优化方向)
  • [项目速览](#目录 DeepRead:把 RAG 做成「会深读、能自证」的研究 Agent 项目速览 @TOC 一、初衷:我对「检索增强问答」的三个不满 二、DeepRead 是什么,能用来干什么 2.1 产品形态与功能全景 2.2 使用方式:从零到一次问答 2.3 一次提问背后发生的事 三、总体架构 四、核心技术实现 4.1 文档处理管线:异步、三写与版式感知切分 4.2 混合检索:RRF 融合、精排、反馈加权与两级缓存 4.3 Agent 运行时:function-calling ReAct 循环 4.4 工具层:注册表、DAG 调度器与作用域安全 4.5 元认知:复杂度路由、计划、反思、自校验 4.6 成本与性能工程 4.7 可靠性:流式、中断恢复与落库时机 4.8 研究模式编排(LangGraph 四角色接力) 4.9 知识图谱与 GraphRAG 4.10 渐进式合成与分层记忆 4.11 安全设计 4.12 LLM 抽象层 4.13 评测框架 4.14 个人 MCP 接入 4.15 关键选型:为什么自研、为什么这么存 五、数据存储设计 5.1 选型与职责分工 5.2 MySQL 表设计(15 张核心表) 5.3 一致性哲学的三个具体机制 5.4 Redis 的三个角色与降级 5.5 已知取舍与盲区(主动交代) 六、工程质量:测试、CI 与交付 七、踩过的坑:这些问题教会我的事 八、技术要点索引 九、未来优化方向)
  • [@TOC(目录)](#目录 DeepRead:把 RAG 做成「会深读、能自证」的研究 Agent 项目速览 @TOC 一、初衷:我对「检索增强问答」的三个不满 二、DeepRead 是什么,能用来干什么 2.1 产品形态与功能全景 2.2 使用方式:从零到一次问答 2.3 一次提问背后发生的事 三、总体架构 四、核心技术实现 4.1 文档处理管线:异步、三写与版式感知切分 4.2 混合检索:RRF 融合、精排、反馈加权与两级缓存 4.3 Agent 运行时:function-calling ReAct 循环 4.4 工具层:注册表、DAG 调度器与作用域安全 4.5 元认知:复杂度路由、计划、反思、自校验 4.6 成本与性能工程 4.7 可靠性:流式、中断恢复与落库时机 4.8 研究模式编排(LangGraph 四角色接力) 4.9 知识图谱与 GraphRAG 4.10 渐进式合成与分层记忆 4.11 安全设计 4.12 LLM 抽象层 4.13 评测框架 4.14 个人 MCP 接入 4.15 关键选型:为什么自研、为什么这么存 五、数据存储设计 5.1 选型与职责分工 5.2 MySQL 表设计(15 张核心表) 5.3 一致性哲学的三个具体机制 5.4 Redis 的三个角色与降级 5.5 已知取舍与盲区(主动交代) 六、工程质量:测试、CI 与交付 七、踩过的坑:这些问题教会我的事 八、技术要点索引 九、未来优化方向)
  • [一、初衷:我对「检索增强问答」的三个不满](#目录 DeepRead:把 RAG 做成「会深读、能自证」的研究 Agent 项目速览 @TOC 一、初衷:我对「检索增强问答」的三个不满 二、DeepRead 是什么,能用来干什么 2.1 产品形态与功能全景 2.2 使用方式:从零到一次问答 2.3 一次提问背后发生的事 三、总体架构 四、核心技术实现 4.1 文档处理管线:异步、三写与版式感知切分 4.2 混合检索:RRF 融合、精排、反馈加权与两级缓存 4.3 Agent 运行时:function-calling ReAct 循环 4.4 工具层:注册表、DAG 调度器与作用域安全 4.5 元认知:复杂度路由、计划、反思、自校验 4.6 成本与性能工程 4.7 可靠性:流式、中断恢复与落库时机 4.8 研究模式编排(LangGraph 四角色接力) 4.9 知识图谱与 GraphRAG 4.10 渐进式合成与分层记忆 4.11 安全设计 4.12 LLM 抽象层 4.13 评测框架 4.14 个人 MCP 接入 4.15 关键选型:为什么自研、为什么这么存 五、数据存储设计 5.1 选型与职责分工 5.2 MySQL 表设计(15 张核心表) 5.3 一致性哲学的三个具体机制 5.4 Redis 的三个角色与降级 5.5 已知取舍与盲区(主动交代) 六、工程质量:测试、CI 与交付 七、踩过的坑:这些问题教会我的事 八、技术要点索引 九、未来优化方向)
  • [二、DeepRead 是什么,能用来干什么](#目录 DeepRead:把 RAG 做成「会深读、能自证」的研究 Agent 项目速览 @TOC 一、初衷:我对「检索增强问答」的三个不满 二、DeepRead 是什么,能用来干什么 2.1 产品形态与功能全景 2.2 使用方式:从零到一次问答 2.3 一次提问背后发生的事 三、总体架构 四、核心技术实现 4.1 文档处理管线:异步、三写与版式感知切分 4.2 混合检索:RRF 融合、精排、反馈加权与两级缓存 4.3 Agent 运行时:function-calling ReAct 循环 4.4 工具层:注册表、DAG 调度器与作用域安全 4.5 元认知:复杂度路由、计划、反思、自校验 4.6 成本与性能工程 4.7 可靠性:流式、中断恢复与落库时机 4.8 研究模式编排(LangGraph 四角色接力) 4.9 知识图谱与 GraphRAG 4.10 渐进式合成与分层记忆 4.11 安全设计 4.12 LLM 抽象层 4.13 评测框架 4.14 个人 MCP 接入 4.15 关键选型:为什么自研、为什么这么存 五、数据存储设计 5.1 选型与职责分工 5.2 MySQL 表设计(15 张核心表) 5.3 一致性哲学的三个具体机制 5.4 Redis 的三个角色与降级 5.5 已知取舍与盲区(主动交代) 六、工程质量:测试、CI 与交付 七、踩过的坑:这些问题教会我的事 八、技术要点索引 九、未来优化方向)
  • [2.1 产品形态与功能全景](#目录 DeepRead:把 RAG 做成「会深读、能自证」的研究 Agent 项目速览 @TOC 一、初衷:我对「检索增强问答」的三个不满 二、DeepRead 是什么,能用来干什么 2.1 产品形态与功能全景 2.2 使用方式:从零到一次问答 2.3 一次提问背后发生的事 三、总体架构 四、核心技术实现 4.1 文档处理管线:异步、三写与版式感知切分 4.2 混合检索:RRF 融合、精排、反馈加权与两级缓存 4.3 Agent 运行时:function-calling ReAct 循环 4.4 工具层:注册表、DAG 调度器与作用域安全 4.5 元认知:复杂度路由、计划、反思、自校验 4.6 成本与性能工程 4.7 可靠性:流式、中断恢复与落库时机 4.8 研究模式编排(LangGraph 四角色接力) 4.9 知识图谱与 GraphRAG 4.10 渐进式合成与分层记忆 4.11 安全设计 4.12 LLM 抽象层 4.13 评测框架 4.14 个人 MCP 接入 4.15 关键选型:为什么自研、为什么这么存 五、数据存储设计 5.1 选型与职责分工 5.2 MySQL 表设计(15 张核心表) 5.3 一致性哲学的三个具体机制 5.4 Redis 的三个角色与降级 5.5 已知取舍与盲区(主动交代) 六、工程质量:测试、CI 与交付 七、踩过的坑:这些问题教会我的事 八、技术要点索引 九、未来优化方向)
  • [2.2 使用方式:从零到一次问答](#目录 DeepRead:把 RAG 做成「会深读、能自证」的研究 Agent 项目速览 @TOC 一、初衷:我对「检索增强问答」的三个不满 二、DeepRead 是什么,能用来干什么 2.1 产品形态与功能全景 2.2 使用方式:从零到一次问答 2.3 一次提问背后发生的事 三、总体架构 四、核心技术实现 4.1 文档处理管线:异步、三写与版式感知切分 4.2 混合检索:RRF 融合、精排、反馈加权与两级缓存 4.3 Agent 运行时:function-calling ReAct 循环 4.4 工具层:注册表、DAG 调度器与作用域安全 4.5 元认知:复杂度路由、计划、反思、自校验 4.6 成本与性能工程 4.7 可靠性:流式、中断恢复与落库时机 4.8 研究模式编排(LangGraph 四角色接力) 4.9 知识图谱与 GraphRAG 4.10 渐进式合成与分层记忆 4.11 安全设计 4.12 LLM 抽象层 4.13 评测框架 4.14 个人 MCP 接入 4.15 关键选型:为什么自研、为什么这么存 五、数据存储设计 5.1 选型与职责分工 5.2 MySQL 表设计(15 张核心表) 5.3 一致性哲学的三个具体机制 5.4 Redis 的三个角色与降级 5.5 已知取舍与盲区(主动交代) 六、工程质量:测试、CI 与交付 七、踩过的坑:这些问题教会我的事 八、技术要点索引 九、未来优化方向)
  • [2.3 一次提问背后发生的事](#目录 DeepRead:把 RAG 做成「会深读、能自证」的研究 Agent 项目速览 @TOC 一、初衷:我对「检索增强问答」的三个不满 二、DeepRead 是什么,能用来干什么 2.1 产品形态与功能全景 2.2 使用方式:从零到一次问答 2.3 一次提问背后发生的事 三、总体架构 四、核心技术实现 4.1 文档处理管线:异步、三写与版式感知切分 4.2 混合检索:RRF 融合、精排、反馈加权与两级缓存 4.3 Agent 运行时:function-calling ReAct 循环 4.4 工具层:注册表、DAG 调度器与作用域安全 4.5 元认知:复杂度路由、计划、反思、自校验 4.6 成本与性能工程 4.7 可靠性:流式、中断恢复与落库时机 4.8 研究模式编排(LangGraph 四角色接力) 4.9 知识图谱与 GraphRAG 4.10 渐进式合成与分层记忆 4.11 安全设计 4.12 LLM 抽象层 4.13 评测框架 4.14 个人 MCP 接入 4.15 关键选型:为什么自研、为什么这么存 五、数据存储设计 5.1 选型与职责分工 5.2 MySQL 表设计(15 张核心表) 5.3 一致性哲学的三个具体机制 5.4 Redis 的三个角色与降级 5.5 已知取舍与盲区(主动交代) 六、工程质量:测试、CI 与交付 七、踩过的坑:这些问题教会我的事 八、技术要点索引 九、未来优化方向)
  • [三、总体架构](#目录 DeepRead:把 RAG 做成「会深读、能自证」的研究 Agent 项目速览 @TOC 一、初衷:我对「检索增强问答」的三个不满 二、DeepRead 是什么,能用来干什么 2.1 产品形态与功能全景 2.2 使用方式:从零到一次问答 2.3 一次提问背后发生的事 三、总体架构 四、核心技术实现 4.1 文档处理管线:异步、三写与版式感知切分 4.2 混合检索:RRF 融合、精排、反馈加权与两级缓存 4.3 Agent 运行时:function-calling ReAct 循环 4.4 工具层:注册表、DAG 调度器与作用域安全 4.5 元认知:复杂度路由、计划、反思、自校验 4.6 成本与性能工程 4.7 可靠性:流式、中断恢复与落库时机 4.8 研究模式编排(LangGraph 四角色接力) 4.9 知识图谱与 GraphRAG 4.10 渐进式合成与分层记忆 4.11 安全设计 4.12 LLM 抽象层 4.13 评测框架 4.14 个人 MCP 接入 4.15 关键选型:为什么自研、为什么这么存 五、数据存储设计 5.1 选型与职责分工 5.2 MySQL 表设计(15 张核心表) 5.3 一致性哲学的三个具体机制 5.4 Redis 的三个角色与降级 5.5 已知取舍与盲区(主动交代) 六、工程质量:测试、CI 与交付 七、踩过的坑:这些问题教会我的事 八、技术要点索引 九、未来优化方向)
  • [四、核心技术实现](#目录 DeepRead:把 RAG 做成「会深读、能自证」的研究 Agent 项目速览 @TOC 一、初衷:我对「检索增强问答」的三个不满 二、DeepRead 是什么,能用来干什么 2.1 产品形态与功能全景 2.2 使用方式:从零到一次问答 2.3 一次提问背后发生的事 三、总体架构 四、核心技术实现 4.1 文档处理管线:异步、三写与版式感知切分 4.2 混合检索:RRF 融合、精排、反馈加权与两级缓存 4.3 Agent 运行时:function-calling ReAct 循环 4.4 工具层:注册表、DAG 调度器与作用域安全 4.5 元认知:复杂度路由、计划、反思、自校验 4.6 成本与性能工程 4.7 可靠性:流式、中断恢复与落库时机 4.8 研究模式编排(LangGraph 四角色接力) 4.9 知识图谱与 GraphRAG 4.10 渐进式合成与分层记忆 4.11 安全设计 4.12 LLM 抽象层 4.13 评测框架 4.14 个人 MCP 接入 4.15 关键选型:为什么自研、为什么这么存 五、数据存储设计 5.1 选型与职责分工 5.2 MySQL 表设计(15 张核心表) 5.3 一致性哲学的三个具体机制 5.4 Redis 的三个角色与降级 5.5 已知取舍与盲区(主动交代) 六、工程质量:测试、CI 与交付 七、踩过的坑:这些问题教会我的事 八、技术要点索引 九、未来优化方向)
  • [4.1 文档处理管线:异步、三写与版式感知切分](#目录 DeepRead:把 RAG 做成「会深读、能自证」的研究 Agent 项目速览 @TOC 一、初衷:我对「检索增强问答」的三个不满 二、DeepRead 是什么,能用来干什么 2.1 产品形态与功能全景 2.2 使用方式:从零到一次问答 2.3 一次提问背后发生的事 三、总体架构 四、核心技术实现 4.1 文档处理管线:异步、三写与版式感知切分 4.2 混合检索:RRF 融合、精排、反馈加权与两级缓存 4.3 Agent 运行时:function-calling ReAct 循环 4.4 工具层:注册表、DAG 调度器与作用域安全 4.5 元认知:复杂度路由、计划、反思、自校验 4.6 成本与性能工程 4.7 可靠性:流式、中断恢复与落库时机 4.8 研究模式编排(LangGraph 四角色接力) 4.9 知识图谱与 GraphRAG 4.10 渐进式合成与分层记忆 4.11 安全设计 4.12 LLM 抽象层 4.13 评测框架 4.14 个人 MCP 接入 4.15 关键选型:为什么自研、为什么这么存 五、数据存储设计 5.1 选型与职责分工 5.2 MySQL 表设计(15 张核心表) 5.3 一致性哲学的三个具体机制 5.4 Redis 的三个角色与降级 5.5 已知取舍与盲区(主动交代) 六、工程质量:测试、CI 与交付 七、踩过的坑:这些问题教会我的事 八、技术要点索引 九、未来优化方向)
  • [4.2 混合检索:RRF 融合、精排、反馈加权与两级缓存](#目录 DeepRead:把 RAG 做成「会深读、能自证」的研究 Agent 项目速览 @TOC 一、初衷:我对「检索增强问答」的三个不满 二、DeepRead 是什么,能用来干什么 2.1 产品形态与功能全景 2.2 使用方式:从零到一次问答 2.3 一次提问背后发生的事 三、总体架构 四、核心技术实现 4.1 文档处理管线:异步、三写与版式感知切分 4.2 混合检索:RRF 融合、精排、反馈加权与两级缓存 4.3 Agent 运行时:function-calling ReAct 循环 4.4 工具层:注册表、DAG 调度器与作用域安全 4.5 元认知:复杂度路由、计划、反思、自校验 4.6 成本与性能工程 4.7 可靠性:流式、中断恢复与落库时机 4.8 研究模式编排(LangGraph 四角色接力) 4.9 知识图谱与 GraphRAG 4.10 渐进式合成与分层记忆 4.11 安全设计 4.12 LLM 抽象层 4.13 评测框架 4.14 个人 MCP 接入 4.15 关键选型:为什么自研、为什么这么存 五、数据存储设计 5.1 选型与职责分工 5.2 MySQL 表设计(15 张核心表) 5.3 一致性哲学的三个具体机制 5.4 Redis 的三个角色与降级 5.5 已知取舍与盲区(主动交代) 六、工程质量:测试、CI 与交付 七、踩过的坑:这些问题教会我的事 八、技术要点索引 九、未来优化方向)
  • [4.3 Agent 运行时:function-calling ReAct 循环](#目录 DeepRead:把 RAG 做成「会深读、能自证」的研究 Agent 项目速览 @TOC 一、初衷:我对「检索增强问答」的三个不满 二、DeepRead 是什么,能用来干什么 2.1 产品形态与功能全景 2.2 使用方式:从零到一次问答 2.3 一次提问背后发生的事 三、总体架构 四、核心技术实现 4.1 文档处理管线:异步、三写与版式感知切分 4.2 混合检索:RRF 融合、精排、反馈加权与两级缓存 4.3 Agent 运行时:function-calling ReAct 循环 4.4 工具层:注册表、DAG 调度器与作用域安全 4.5 元认知:复杂度路由、计划、反思、自校验 4.6 成本与性能工程 4.7 可靠性:流式、中断恢复与落库时机 4.8 研究模式编排(LangGraph 四角色接力) 4.9 知识图谱与 GraphRAG 4.10 渐进式合成与分层记忆 4.11 安全设计 4.12 LLM 抽象层 4.13 评测框架 4.14 个人 MCP 接入 4.15 关键选型:为什么自研、为什么这么存 五、数据存储设计 5.1 选型与职责分工 5.2 MySQL 表设计(15 张核心表) 5.3 一致性哲学的三个具体机制 5.4 Redis 的三个角色与降级 5.5 已知取舍与盲区(主动交代) 六、工程质量:测试、CI 与交付 七、踩过的坑:这些问题教会我的事 八、技术要点索引 九、未来优化方向)
  • [4.4 工具层:注册表、DAG 调度器与作用域安全](#目录 DeepRead:把 RAG 做成「会深读、能自证」的研究 Agent 项目速览 @TOC 一、初衷:我对「检索增强问答」的三个不满 二、DeepRead 是什么,能用来干什么 2.1 产品形态与功能全景 2.2 使用方式:从零到一次问答 2.3 一次提问背后发生的事 三、总体架构 四、核心技术实现 4.1 文档处理管线:异步、三写与版式感知切分 4.2 混合检索:RRF 融合、精排、反馈加权与两级缓存 4.3 Agent 运行时:function-calling ReAct 循环 4.4 工具层:注册表、DAG 调度器与作用域安全 4.5 元认知:复杂度路由、计划、反思、自校验 4.6 成本与性能工程 4.7 可靠性:流式、中断恢复与落库时机 4.8 研究模式编排(LangGraph 四角色接力) 4.9 知识图谱与 GraphRAG 4.10 渐进式合成与分层记忆 4.11 安全设计 4.12 LLM 抽象层 4.13 评测框架 4.14 个人 MCP 接入 4.15 关键选型:为什么自研、为什么这么存 五、数据存储设计 5.1 选型与职责分工 5.2 MySQL 表设计(15 张核心表) 5.3 一致性哲学的三个具体机制 5.4 Redis 的三个角色与降级 5.5 已知取舍与盲区(主动交代) 六、工程质量:测试、CI 与交付 七、踩过的坑:这些问题教会我的事 八、技术要点索引 九、未来优化方向)
  • [4.5 元认知:复杂度路由、计划、反思、自校验](#目录 DeepRead:把 RAG 做成「会深读、能自证」的研究 Agent 项目速览 @TOC 一、初衷:我对「检索增强问答」的三个不满 二、DeepRead 是什么,能用来干什么 2.1 产品形态与功能全景 2.2 使用方式:从零到一次问答 2.3 一次提问背后发生的事 三、总体架构 四、核心技术实现 4.1 文档处理管线:异步、三写与版式感知切分 4.2 混合检索:RRF 融合、精排、反馈加权与两级缓存 4.3 Agent 运行时:function-calling ReAct 循环 4.4 工具层:注册表、DAG 调度器与作用域安全 4.5 元认知:复杂度路由、计划、反思、自校验 4.6 成本与性能工程 4.7 可靠性:流式、中断恢复与落库时机 4.8 研究模式编排(LangGraph 四角色接力) 4.9 知识图谱与 GraphRAG 4.10 渐进式合成与分层记忆 4.11 安全设计 4.12 LLM 抽象层 4.13 评测框架 4.14 个人 MCP 接入 4.15 关键选型:为什么自研、为什么这么存 五、数据存储设计 5.1 选型与职责分工 5.2 MySQL 表设计(15 张核心表) 5.3 一致性哲学的三个具体机制 5.4 Redis 的三个角色与降级 5.5 已知取舍与盲区(主动交代) 六、工程质量:测试、CI 与交付 七、踩过的坑:这些问题教会我的事 八、技术要点索引 九、未来优化方向)
  • [4.6 成本与性能工程](#目录 DeepRead:把 RAG 做成「会深读、能自证」的研究 Agent 项目速览 @TOC 一、初衷:我对「检索增强问答」的三个不满 二、DeepRead 是什么,能用来干什么 2.1 产品形态与功能全景 2.2 使用方式:从零到一次问答 2.3 一次提问背后发生的事 三、总体架构 四、核心技术实现 4.1 文档处理管线:异步、三写与版式感知切分 4.2 混合检索:RRF 融合、精排、反馈加权与两级缓存 4.3 Agent 运行时:function-calling ReAct 循环 4.4 工具层:注册表、DAG 调度器与作用域安全 4.5 元认知:复杂度路由、计划、反思、自校验 4.6 成本与性能工程 4.7 可靠性:流式、中断恢复与落库时机 4.8 研究模式编排(LangGraph 四角色接力) 4.9 知识图谱与 GraphRAG 4.10 渐进式合成与分层记忆 4.11 安全设计 4.12 LLM 抽象层 4.13 评测框架 4.14 个人 MCP 接入 4.15 关键选型:为什么自研、为什么这么存 五、数据存储设计 5.1 选型与职责分工 5.2 MySQL 表设计(15 张核心表) 5.3 一致性哲学的三个具体机制 5.4 Redis 的三个角色与降级 5.5 已知取舍与盲区(主动交代) 六、工程质量:测试、CI 与交付 七、踩过的坑:这些问题教会我的事 八、技术要点索引 九、未来优化方向)
  • [4.7 可靠性:流式、中断恢复与落库时机](#目录 DeepRead:把 RAG 做成「会深读、能自证」的研究 Agent 项目速览 @TOC 一、初衷:我对「检索增强问答」的三个不满 二、DeepRead 是什么,能用来干什么 2.1 产品形态与功能全景 2.2 使用方式:从零到一次问答 2.3 一次提问背后发生的事 三、总体架构 四、核心技术实现 4.1 文档处理管线:异步、三写与版式感知切分 4.2 混合检索:RRF 融合、精排、反馈加权与两级缓存 4.3 Agent 运行时:function-calling ReAct 循环 4.4 工具层:注册表、DAG 调度器与作用域安全 4.5 元认知:复杂度路由、计划、反思、自校验 4.6 成本与性能工程 4.7 可靠性:流式、中断恢复与落库时机 4.8 研究模式编排(LangGraph 四角色接力) 4.9 知识图谱与 GraphRAG 4.10 渐进式合成与分层记忆 4.11 安全设计 4.12 LLM 抽象层 4.13 评测框架 4.14 个人 MCP 接入 4.15 关键选型:为什么自研、为什么这么存 五、数据存储设计 5.1 选型与职责分工 5.2 MySQL 表设计(15 张核心表) 5.3 一致性哲学的三个具体机制 5.4 Redis 的三个角色与降级 5.5 已知取舍与盲区(主动交代) 六、工程质量:测试、CI 与交付 七、踩过的坑:这些问题教会我的事 八、技术要点索引 九、未来优化方向)
  • [4.8 研究模式编排(LangGraph 四角色接力)](#目录 DeepRead:把 RAG 做成「会深读、能自证」的研究 Agent 项目速览 @TOC 一、初衷:我对「检索增强问答」的三个不满 二、DeepRead 是什么,能用来干什么 2.1 产品形态与功能全景 2.2 使用方式:从零到一次问答 2.3 一次提问背后发生的事 三、总体架构 四、核心技术实现 4.1 文档处理管线:异步、三写与版式感知切分 4.2 混合检索:RRF 融合、精排、反馈加权与两级缓存 4.3 Agent 运行时:function-calling ReAct 循环 4.4 工具层:注册表、DAG 调度器与作用域安全 4.5 元认知:复杂度路由、计划、反思、自校验 4.6 成本与性能工程 4.7 可靠性:流式、中断恢复与落库时机 4.8 研究模式编排(LangGraph 四角色接力) 4.9 知识图谱与 GraphRAG 4.10 渐进式合成与分层记忆 4.11 安全设计 4.12 LLM 抽象层 4.13 评测框架 4.14 个人 MCP 接入 4.15 关键选型:为什么自研、为什么这么存 五、数据存储设计 5.1 选型与职责分工 5.2 MySQL 表设计(15 张核心表) 5.3 一致性哲学的三个具体机制 5.4 Redis 的三个角色与降级 5.5 已知取舍与盲区(主动交代) 六、工程质量:测试、CI 与交付 七、踩过的坑:这些问题教会我的事 八、技术要点索引 九、未来优化方向)
  • [4.9 知识图谱与 GraphRAG](#目录 DeepRead:把 RAG 做成「会深读、能自证」的研究 Agent 项目速览 @TOC 一、初衷:我对「检索增强问答」的三个不满 二、DeepRead 是什么,能用来干什么 2.1 产品形态与功能全景 2.2 使用方式:从零到一次问答 2.3 一次提问背后发生的事 三、总体架构 四、核心技术实现 4.1 文档处理管线:异步、三写与版式感知切分 4.2 混合检索:RRF 融合、精排、反馈加权与两级缓存 4.3 Agent 运行时:function-calling ReAct 循环 4.4 工具层:注册表、DAG 调度器与作用域安全 4.5 元认知:复杂度路由、计划、反思、自校验 4.6 成本与性能工程 4.7 可靠性:流式、中断恢复与落库时机 4.8 研究模式编排(LangGraph 四角色接力) 4.9 知识图谱与 GraphRAG 4.10 渐进式合成与分层记忆 4.11 安全设计 4.12 LLM 抽象层 4.13 评测框架 4.14 个人 MCP 接入 4.15 关键选型:为什么自研、为什么这么存 五、数据存储设计 5.1 选型与职责分工 5.2 MySQL 表设计(15 张核心表) 5.3 一致性哲学的三个具体机制 5.4 Redis 的三个角色与降级 5.5 已知取舍与盲区(主动交代) 六、工程质量:测试、CI 与交付 七、踩过的坑:这些问题教会我的事 八、技术要点索引 九、未来优化方向)
  • [4.10 渐进式合成与分层记忆](#目录 DeepRead:把 RAG 做成「会深读、能自证」的研究 Agent 项目速览 @TOC 一、初衷:我对「检索增强问答」的三个不满 二、DeepRead 是什么,能用来干什么 2.1 产品形态与功能全景 2.2 使用方式:从零到一次问答 2.3 一次提问背后发生的事 三、总体架构 四、核心技术实现 4.1 文档处理管线:异步、三写与版式感知切分 4.2 混合检索:RRF 融合、精排、反馈加权与两级缓存 4.3 Agent 运行时:function-calling ReAct 循环 4.4 工具层:注册表、DAG 调度器与作用域安全 4.5 元认知:复杂度路由、计划、反思、自校验 4.6 成本与性能工程 4.7 可靠性:流式、中断恢复与落库时机 4.8 研究模式编排(LangGraph 四角色接力) 4.9 知识图谱与 GraphRAG 4.10 渐进式合成与分层记忆 4.11 安全设计 4.12 LLM 抽象层 4.13 评测框架 4.14 个人 MCP 接入 4.15 关键选型:为什么自研、为什么这么存 五、数据存储设计 5.1 选型与职责分工 5.2 MySQL 表设计(15 张核心表) 5.3 一致性哲学的三个具体机制 5.4 Redis 的三个角色与降级 5.5 已知取舍与盲区(主动交代) 六、工程质量:测试、CI 与交付 七、踩过的坑:这些问题教会我的事 八、技术要点索引 九、未来优化方向)
  • [4.11 安全设计](#目录 DeepRead:把 RAG 做成「会深读、能自证」的研究 Agent 项目速览 @TOC 一、初衷:我对「检索增强问答」的三个不满 二、DeepRead 是什么,能用来干什么 2.1 产品形态与功能全景 2.2 使用方式:从零到一次问答 2.3 一次提问背后发生的事 三、总体架构 四、核心技术实现 4.1 文档处理管线:异步、三写与版式感知切分 4.2 混合检索:RRF 融合、精排、反馈加权与两级缓存 4.3 Agent 运行时:function-calling ReAct 循环 4.4 工具层:注册表、DAG 调度器与作用域安全 4.5 元认知:复杂度路由、计划、反思、自校验 4.6 成本与性能工程 4.7 可靠性:流式、中断恢复与落库时机 4.8 研究模式编排(LangGraph 四角色接力) 4.9 知识图谱与 GraphRAG 4.10 渐进式合成与分层记忆 4.11 安全设计 4.12 LLM 抽象层 4.13 评测框架 4.14 个人 MCP 接入 4.15 关键选型:为什么自研、为什么这么存 五、数据存储设计 5.1 选型与职责分工 5.2 MySQL 表设计(15 张核心表) 5.3 一致性哲学的三个具体机制 5.4 Redis 的三个角色与降级 5.5 已知取舍与盲区(主动交代) 六、工程质量:测试、CI 与交付 七、踩过的坑:这些问题教会我的事 八、技术要点索引 九、未来优化方向)
  • [4.12 LLM 抽象层](#目录 DeepRead:把 RAG 做成「会深读、能自证」的研究 Agent 项目速览 @TOC 一、初衷:我对「检索增强问答」的三个不满 二、DeepRead 是什么,能用来干什么 2.1 产品形态与功能全景 2.2 使用方式:从零到一次问答 2.3 一次提问背后发生的事 三、总体架构 四、核心技术实现 4.1 文档处理管线:异步、三写与版式感知切分 4.2 混合检索:RRF 融合、精排、反馈加权与两级缓存 4.3 Agent 运行时:function-calling ReAct 循环 4.4 工具层:注册表、DAG 调度器与作用域安全 4.5 元认知:复杂度路由、计划、反思、自校验 4.6 成本与性能工程 4.7 可靠性:流式、中断恢复与落库时机 4.8 研究模式编排(LangGraph 四角色接力) 4.9 知识图谱与 GraphRAG 4.10 渐进式合成与分层记忆 4.11 安全设计 4.12 LLM 抽象层 4.13 评测框架 4.14 个人 MCP 接入 4.15 关键选型:为什么自研、为什么这么存 五、数据存储设计 5.1 选型与职责分工 5.2 MySQL 表设计(15 张核心表) 5.3 一致性哲学的三个具体机制 5.4 Redis 的三个角色与降级 5.5 已知取舍与盲区(主动交代) 六、工程质量:测试、CI 与交付 七、踩过的坑:这些问题教会我的事 八、技术要点索引 九、未来优化方向)
  • [4.13 评测框架](#目录 DeepRead:把 RAG 做成「会深读、能自证」的研究 Agent 项目速览 @TOC 一、初衷:我对「检索增强问答」的三个不满 二、DeepRead 是什么,能用来干什么 2.1 产品形态与功能全景 2.2 使用方式:从零到一次问答 2.3 一次提问背后发生的事 三、总体架构 四、核心技术实现 4.1 文档处理管线:异步、三写与版式感知切分 4.2 混合检索:RRF 融合、精排、反馈加权与两级缓存 4.3 Agent 运行时:function-calling ReAct 循环 4.4 工具层:注册表、DAG 调度器与作用域安全 4.5 元认知:复杂度路由、计划、反思、自校验 4.6 成本与性能工程 4.7 可靠性:流式、中断恢复与落库时机 4.8 研究模式编排(LangGraph 四角色接力) 4.9 知识图谱与 GraphRAG 4.10 渐进式合成与分层记忆 4.11 安全设计 4.12 LLM 抽象层 4.13 评测框架 4.14 个人 MCP 接入 4.15 关键选型:为什么自研、为什么这么存 五、数据存储设计 5.1 选型与职责分工 5.2 MySQL 表设计(15 张核心表) 5.3 一致性哲学的三个具体机制 5.4 Redis 的三个角色与降级 5.5 已知取舍与盲区(主动交代) 六、工程质量:测试、CI 与交付 七、踩过的坑:这些问题教会我的事 八、技术要点索引 九、未来优化方向)
  • [4.14 个人 MCP 接入](#目录 DeepRead:把 RAG 做成「会深读、能自证」的研究 Agent 项目速览 @TOC 一、初衷:我对「检索增强问答」的三个不满 二、DeepRead 是什么,能用来干什么 2.1 产品形态与功能全景 2.2 使用方式:从零到一次问答 2.3 一次提问背后发生的事 三、总体架构 四、核心技术实现 4.1 文档处理管线:异步、三写与版式感知切分 4.2 混合检索:RRF 融合、精排、反馈加权与两级缓存 4.3 Agent 运行时:function-calling ReAct 循环 4.4 工具层:注册表、DAG 调度器与作用域安全 4.5 元认知:复杂度路由、计划、反思、自校验 4.6 成本与性能工程 4.7 可靠性:流式、中断恢复与落库时机 4.8 研究模式编排(LangGraph 四角色接力) 4.9 知识图谱与 GraphRAG 4.10 渐进式合成与分层记忆 4.11 安全设计 4.12 LLM 抽象层 4.13 评测框架 4.14 个人 MCP 接入 4.15 关键选型:为什么自研、为什么这么存 五、数据存储设计 5.1 选型与职责分工 5.2 MySQL 表设计(15 张核心表) 5.3 一致性哲学的三个具体机制 5.4 Redis 的三个角色与降级 5.5 已知取舍与盲区(主动交代) 六、工程质量:测试、CI 与交付 七、踩过的坑:这些问题教会我的事 八、技术要点索引 九、未来优化方向)
  • [4.15 关键选型:为什么自研、为什么这么存](#目录 DeepRead:把 RAG 做成「会深读、能自证」的研究 Agent 项目速览 @TOC 一、初衷:我对「检索增强问答」的三个不满 二、DeepRead 是什么,能用来干什么 2.1 产品形态与功能全景 2.2 使用方式:从零到一次问答 2.3 一次提问背后发生的事 三、总体架构 四、核心技术实现 4.1 文档处理管线:异步、三写与版式感知切分 4.2 混合检索:RRF 融合、精排、反馈加权与两级缓存 4.3 Agent 运行时:function-calling ReAct 循环 4.4 工具层:注册表、DAG 调度器与作用域安全 4.5 元认知:复杂度路由、计划、反思、自校验 4.6 成本与性能工程 4.7 可靠性:流式、中断恢复与落库时机 4.8 研究模式编排(LangGraph 四角色接力) 4.9 知识图谱与 GraphRAG 4.10 渐进式合成与分层记忆 4.11 安全设计 4.12 LLM 抽象层 4.13 评测框架 4.14 个人 MCP 接入 4.15 关键选型:为什么自研、为什么这么存 五、数据存储设计 5.1 选型与职责分工 5.2 MySQL 表设计(15 张核心表) 5.3 一致性哲学的三个具体机制 5.4 Redis 的三个角色与降级 5.5 已知取舍与盲区(主动交代) 六、工程质量:测试、CI 与交付 七、踩过的坑:这些问题教会我的事 八、技术要点索引 九、未来优化方向)
  • [五、数据存储设计](#目录 DeepRead:把 RAG 做成「会深读、能自证」的研究 Agent 项目速览 @TOC 一、初衷:我对「检索增强问答」的三个不满 二、DeepRead 是什么,能用来干什么 2.1 产品形态与功能全景 2.2 使用方式:从零到一次问答 2.3 一次提问背后发生的事 三、总体架构 四、核心技术实现 4.1 文档处理管线:异步、三写与版式感知切分 4.2 混合检索:RRF 融合、精排、反馈加权与两级缓存 4.3 Agent 运行时:function-calling ReAct 循环 4.4 工具层:注册表、DAG 调度器与作用域安全 4.5 元认知:复杂度路由、计划、反思、自校验 4.6 成本与性能工程 4.7 可靠性:流式、中断恢复与落库时机 4.8 研究模式编排(LangGraph 四角色接力) 4.9 知识图谱与 GraphRAG 4.10 渐进式合成与分层记忆 4.11 安全设计 4.12 LLM 抽象层 4.13 评测框架 4.14 个人 MCP 接入 4.15 关键选型:为什么自研、为什么这么存 五、数据存储设计 5.1 选型与职责分工 5.2 MySQL 表设计(15 张核心表) 5.3 一致性哲学的三个具体机制 5.4 Redis 的三个角色与降级 5.5 已知取舍与盲区(主动交代) 六、工程质量:测试、CI 与交付 七、踩过的坑:这些问题教会我的事 八、技术要点索引 九、未来优化方向)
  • [5.1 选型与职责分工](#目录 DeepRead:把 RAG 做成「会深读、能自证」的研究 Agent 项目速览 @TOC 一、初衷:我对「检索增强问答」的三个不满 二、DeepRead 是什么,能用来干什么 2.1 产品形态与功能全景 2.2 使用方式:从零到一次问答 2.3 一次提问背后发生的事 三、总体架构 四、核心技术实现 4.1 文档处理管线:异步、三写与版式感知切分 4.2 混合检索:RRF 融合、精排、反馈加权与两级缓存 4.3 Agent 运行时:function-calling ReAct 循环 4.4 工具层:注册表、DAG 调度器与作用域安全 4.5 元认知:复杂度路由、计划、反思、自校验 4.6 成本与性能工程 4.7 可靠性:流式、中断恢复与落库时机 4.8 研究模式编排(LangGraph 四角色接力) 4.9 知识图谱与 GraphRAG 4.10 渐进式合成与分层记忆 4.11 安全设计 4.12 LLM 抽象层 4.13 评测框架 4.14 个人 MCP 接入 4.15 关键选型:为什么自研、为什么这么存 五、数据存储设计 5.1 选型与职责分工 5.2 MySQL 表设计(15 张核心表) 5.3 一致性哲学的三个具体机制 5.4 Redis 的三个角色与降级 5.5 已知取舍与盲区(主动交代) 六、工程质量:测试、CI 与交付 七、踩过的坑:这些问题教会我的事 八、技术要点索引 九、未来优化方向)
  • [5.2 MySQL 表设计(15 张核心表)](#目录 DeepRead:把 RAG 做成「会深读、能自证」的研究 Agent 项目速览 @TOC 一、初衷:我对「检索增强问答」的三个不满 二、DeepRead 是什么,能用来干什么 2.1 产品形态与功能全景 2.2 使用方式:从零到一次问答 2.3 一次提问背后发生的事 三、总体架构 四、核心技术实现 4.1 文档处理管线:异步、三写与版式感知切分 4.2 混合检索:RRF 融合、精排、反馈加权与两级缓存 4.3 Agent 运行时:function-calling ReAct 循环 4.4 工具层:注册表、DAG 调度器与作用域安全 4.5 元认知:复杂度路由、计划、反思、自校验 4.6 成本与性能工程 4.7 可靠性:流式、中断恢复与落库时机 4.8 研究模式编排(LangGraph 四角色接力) 4.9 知识图谱与 GraphRAG 4.10 渐进式合成与分层记忆 4.11 安全设计 4.12 LLM 抽象层 4.13 评测框架 4.14 个人 MCP 接入 4.15 关键选型:为什么自研、为什么这么存 五、数据存储设计 5.1 选型与职责分工 5.2 MySQL 表设计(15 张核心表) 5.3 一致性哲学的三个具体机制 5.4 Redis 的三个角色与降级 5.5 已知取舍与盲区(主动交代) 六、工程质量:测试、CI 与交付 七、踩过的坑:这些问题教会我的事 八、技术要点索引 九、未来优化方向)
  • [5.3 一致性哲学的三个具体机制](#目录 DeepRead:把 RAG 做成「会深读、能自证」的研究 Agent 项目速览 @TOC 一、初衷:我对「检索增强问答」的三个不满 二、DeepRead 是什么,能用来干什么 2.1 产品形态与功能全景 2.2 使用方式:从零到一次问答 2.3 一次提问背后发生的事 三、总体架构 四、核心技术实现 4.1 文档处理管线:异步、三写与版式感知切分 4.2 混合检索:RRF 融合、精排、反馈加权与两级缓存 4.3 Agent 运行时:function-calling ReAct 循环 4.4 工具层:注册表、DAG 调度器与作用域安全 4.5 元认知:复杂度路由、计划、反思、自校验 4.6 成本与性能工程 4.7 可靠性:流式、中断恢复与落库时机 4.8 研究模式编排(LangGraph 四角色接力) 4.9 知识图谱与 GraphRAG 4.10 渐进式合成与分层记忆 4.11 安全设计 4.12 LLM 抽象层 4.13 评测框架 4.14 个人 MCP 接入 4.15 关键选型:为什么自研、为什么这么存 五、数据存储设计 5.1 选型与职责分工 5.2 MySQL 表设计(15 张核心表) 5.3 一致性哲学的三个具体机制 5.4 Redis 的三个角色与降级 5.5 已知取舍与盲区(主动交代) 六、工程质量:测试、CI 与交付 七、踩过的坑:这些问题教会我的事 八、技术要点索引 九、未来优化方向)
  • [5.4 Redis 的三个角色与降级](#目录 DeepRead:把 RAG 做成「会深读、能自证」的研究 Agent 项目速览 @TOC 一、初衷:我对「检索增强问答」的三个不满 二、DeepRead 是什么,能用来干什么 2.1 产品形态与功能全景 2.2 使用方式:从零到一次问答 2.3 一次提问背后发生的事 三、总体架构 四、核心技术实现 4.1 文档处理管线:异步、三写与版式感知切分 4.2 混合检索:RRF 融合、精排、反馈加权与两级缓存 4.3 Agent 运行时:function-calling ReAct 循环 4.4 工具层:注册表、DAG 调度器与作用域安全 4.5 元认知:复杂度路由、计划、反思、自校验 4.6 成本与性能工程 4.7 可靠性:流式、中断恢复与落库时机 4.8 研究模式编排(LangGraph 四角色接力) 4.9 知识图谱与 GraphRAG 4.10 渐进式合成与分层记忆 4.11 安全设计 4.12 LLM 抽象层 4.13 评测框架 4.14 个人 MCP 接入 4.15 关键选型:为什么自研、为什么这么存 五、数据存储设计 5.1 选型与职责分工 5.2 MySQL 表设计(15 张核心表) 5.3 一致性哲学的三个具体机制 5.4 Redis 的三个角色与降级 5.5 已知取舍与盲区(主动交代) 六、工程质量:测试、CI 与交付 七、踩过的坑:这些问题教会我的事 八、技术要点索引 九、未来优化方向)
  • [5.5 已知取舍与盲区(主动交代)](#目录 DeepRead:把 RAG 做成「会深读、能自证」的研究 Agent 项目速览 @TOC 一、初衷:我对「检索增强问答」的三个不满 二、DeepRead 是什么,能用来干什么 2.1 产品形态与功能全景 2.2 使用方式:从零到一次问答 2.3 一次提问背后发生的事 三、总体架构 四、核心技术实现 4.1 文档处理管线:异步、三写与版式感知切分 4.2 混合检索:RRF 融合、精排、反馈加权与两级缓存 4.3 Agent 运行时:function-calling ReAct 循环 4.4 工具层:注册表、DAG 调度器与作用域安全 4.5 元认知:复杂度路由、计划、反思、自校验 4.6 成本与性能工程 4.7 可靠性:流式、中断恢复与落库时机 4.8 研究模式编排(LangGraph 四角色接力) 4.9 知识图谱与 GraphRAG 4.10 渐进式合成与分层记忆 4.11 安全设计 4.12 LLM 抽象层 4.13 评测框架 4.14 个人 MCP 接入 4.15 关键选型:为什么自研、为什么这么存 五、数据存储设计 5.1 选型与职责分工 5.2 MySQL 表设计(15 张核心表) 5.3 一致性哲学的三个具体机制 5.4 Redis 的三个角色与降级 5.5 已知取舍与盲区(主动交代) 六、工程质量:测试、CI 与交付 七、踩过的坑:这些问题教会我的事 八、技术要点索引 九、未来优化方向)
  • [六、工程质量:测试、CI 与交付](#目录 DeepRead:把 RAG 做成「会深读、能自证」的研究 Agent 项目速览 @TOC 一、初衷:我对「检索增强问答」的三个不满 二、DeepRead 是什么,能用来干什么 2.1 产品形态与功能全景 2.2 使用方式:从零到一次问答 2.3 一次提问背后发生的事 三、总体架构 四、核心技术实现 4.1 文档处理管线:异步、三写与版式感知切分 4.2 混合检索:RRF 融合、精排、反馈加权与两级缓存 4.3 Agent 运行时:function-calling ReAct 循环 4.4 工具层:注册表、DAG 调度器与作用域安全 4.5 元认知:复杂度路由、计划、反思、自校验 4.6 成本与性能工程 4.7 可靠性:流式、中断恢复与落库时机 4.8 研究模式编排(LangGraph 四角色接力) 4.9 知识图谱与 GraphRAG 4.10 渐进式合成与分层记忆 4.11 安全设计 4.12 LLM 抽象层 4.13 评测框架 4.14 个人 MCP 接入 4.15 关键选型:为什么自研、为什么这么存 五、数据存储设计 5.1 选型与职责分工 5.2 MySQL 表设计(15 张核心表) 5.3 一致性哲学的三个具体机制 5.4 Redis 的三个角色与降级 5.5 已知取舍与盲区(主动交代) 六、工程质量:测试、CI 与交付 七、踩过的坑:这些问题教会我的事 八、技术要点索引 九、未来优化方向)
  • [七、踩过的坑:这些问题教会我的事](#目录 DeepRead:把 RAG 做成「会深读、能自证」的研究 Agent 项目速览 @TOC 一、初衷:我对「检索增强问答」的三个不满 二、DeepRead 是什么,能用来干什么 2.1 产品形态与功能全景 2.2 使用方式:从零到一次问答 2.3 一次提问背后发生的事 三、总体架构 四、核心技术实现 4.1 文档处理管线:异步、三写与版式感知切分 4.2 混合检索:RRF 融合、精排、反馈加权与两级缓存 4.3 Agent 运行时:function-calling ReAct 循环 4.4 工具层:注册表、DAG 调度器与作用域安全 4.5 元认知:复杂度路由、计划、反思、自校验 4.6 成本与性能工程 4.7 可靠性:流式、中断恢复与落库时机 4.8 研究模式编排(LangGraph 四角色接力) 4.9 知识图谱与 GraphRAG 4.10 渐进式合成与分层记忆 4.11 安全设计 4.12 LLM 抽象层 4.13 评测框架 4.14 个人 MCP 接入 4.15 关键选型:为什么自研、为什么这么存 五、数据存储设计 5.1 选型与职责分工 5.2 MySQL 表设计(15 张核心表) 5.3 一致性哲学的三个具体机制 5.4 Redis 的三个角色与降级 5.5 已知取舍与盲区(主动交代) 六、工程质量:测试、CI 与交付 七、踩过的坑:这些问题教会我的事 八、技术要点索引 九、未来优化方向)
  • [八、技术要点索引](#目录 DeepRead:把 RAG 做成「会深读、能自证」的研究 Agent 项目速览 @TOC 一、初衷:我对「检索增强问答」的三个不满 二、DeepRead 是什么,能用来干什么 2.1 产品形态与功能全景 2.2 使用方式:从零到一次问答 2.3 一次提问背后发生的事 三、总体架构 四、核心技术实现 4.1 文档处理管线:异步、三写与版式感知切分 4.2 混合检索:RRF 融合、精排、反馈加权与两级缓存 4.3 Agent 运行时:function-calling ReAct 循环 4.4 工具层:注册表、DAG 调度器与作用域安全 4.5 元认知:复杂度路由、计划、反思、自校验 4.6 成本与性能工程 4.7 可靠性:流式、中断恢复与落库时机 4.8 研究模式编排(LangGraph 四角色接力) 4.9 知识图谱与 GraphRAG 4.10 渐进式合成与分层记忆 4.11 安全设计 4.12 LLM 抽象层 4.13 评测框架 4.14 个人 MCP 接入 4.15 关键选型:为什么自研、为什么这么存 五、数据存储设计 5.1 选型与职责分工 5.2 MySQL 表设计(15 张核心表) 5.3 一致性哲学的三个具体机制 5.4 Redis 的三个角色与降级 5.5 已知取舍与盲区(主动交代) 六、工程质量:测试、CI 与交付 七、踩过的坑:这些问题教会我的事 八、技术要点索引 九、未来优化方向)
  • [九、未来优化方向](#目录 DeepRead:把 RAG 做成「会深读、能自证」的研究 Agent 项目速览 @TOC 一、初衷:我对「检索增强问答」的三个不满 二、DeepRead 是什么,能用来干什么 2.1 产品形态与功能全景 2.2 使用方式:从零到一次问答 2.3 一次提问背后发生的事 三、总体架构 四、核心技术实现 4.1 文档处理管线:异步、三写与版式感知切分 4.2 混合检索:RRF 融合、精排、反馈加权与两级缓存 4.3 Agent 运行时:function-calling ReAct 循环 4.4 工具层:注册表、DAG 调度器与作用域安全 4.5 元认知:复杂度路由、计划、反思、自校验 4.6 成本与性能工程 4.7 可靠性:流式、中断恢复与落库时机 4.8 研究模式编排(LangGraph 四角色接力) 4.9 知识图谱与 GraphRAG 4.10 渐进式合成与分层记忆 4.11 安全设计 4.12 LLM 抽象层 4.13 评测框架 4.14 个人 MCP 接入 4.15 关键选型:为什么自研、为什么这么存 五、数据存储设计 5.1 选型与职责分工 5.2 MySQL 表设计(15 张核心表) 5.3 一致性哲学的三个具体机制 5.4 Redis 的三个角色与降级 5.5 已知取舍与盲区(主动交代) 六、工程质量:测试、CI 与交付 七、踩过的坑:这些问题教会我的事 八、技术要点索引 九、未来优化方向)

一、初衷:我对「检索增强问答」的三个不满

用惯了各种「RAG 知识库问答」产品之后,我积累了三个具体的不满,DeepRead 就是冲着解决它们去的:

不满一:一问一答太浅。 经典 RAG 是"检索 top-k 片段 → 一次生成",这在"这篇论文的结论是什么"这类单点问题上够用,但在"对比 A 和 B 两种方法在各自数据集上的指标口径"、"验证 Table 3 的数值能否复算"这类需要多步推理的问题上直接失效------它没有规划、没有迭代检索、没有自我检查,检索一次不行就摆烂。

不满二:幻觉没有约束机制。 大多数产品对幻觉的处理是"祈祷模型别编"。我想做的是把约束做成机制:答案写完后,系统自动把答案拆成原子论断(claims),逐条回到原文验证语义支撑度,支撑不住的部分要么触发重新生成、要么明确标注「未验证」给用户看。宁可少答,不可错答。

不满三:回答不可溯源。 "根据文档内容......"这种回答对研究者毫无价值。我需要每一句关键论断后面都挂着 [chunk:123] 这样的角标,点开能直接看到原文段落、所在文档、章节路径甚至页码------把 LLM 的输出重新锚定回物理证据。

同时我还想要一个工程上的自我要求:不做一个 demo,做一个能长期运行、可观测、可回放、可评测的系统。所以这个项目从第一天就带上了 trace 全量记录、token/成本计量、评测框架与回归检测、CI 流水线------这些"重"的部分恰恰是我做这个项目最想练习的部分。

二、DeepRead 是什么,能用来干什么

2.1 产品形态与功能全景

DeepRead 是一个 Web 应用(FastAPI 后端 + Vue3 前端),本地自托管,自带 LLM API Key。核心功能:

功能 说明
知识库管理 多知识库、多文档(PDF/DOCX/PPTX/Markdown/HTML/LaTeX/纯文本/CSV/XLSX,支持贴 URL 入库),文档可按库启用/停用、软删除
深度问答(对话模式) ReAct Agent 基于所选知识库作答,答案带 [chunk:ID] 引用角标,过程(思考/工具调用/自省/自校验)全程流式可见、事后可回放
研究报告(研究模式) 派一个课题,LangGraph 编排 Planner/Researcher/Writer/Reviewer 四类研究角色接力产出结构化研究报告,审稿不通过自动增量重研,可导出 Markdown
知识图谱 文档入库自动抽取实体/关系(6 类节点、6 类关系),支持多跳遍历、路径查询、核心实体排序(PageRank)、社区发现(Leiden),并做跨文档数值矛盾检测
GraphRAG 检索 图问题自动注入图谱概览;local search(实体定位+多跳邻居)与 global search(社区报告 map-reduce)两种图增强检索
渐进式知识合成 知识库随文档增加自动升级合成产物:1 篇起库级摘要 → 3 篇方法对比 → 5 篇研究脉络 → 10 篇综述初稿
分层记忆 情景记忆(对话摘要)+ 语义记忆(用户偏好),向量召回注入新会话;90 天未召回降权、180 天归档
个人 MCP 接入 一个 MCP 端点 + 长期令牌,把 Claude Desktop / Cursor 等 MCP 客户端直接接到自己的知识库上(只读工具子集)
工作流模板 内置论文精读/审稿/复现/对比等 8 种 YAML DAG 工作流模板,每步指定工具白名单
评测与回归 10+ 维度打分(工具选择 F1、引用命中率、幻觉率、诚实弃答率、效率、LLM-as-Judge 完整性/准确性等),两次运行自动出回归 diff 报告

2.2 使用方式:从零到一次问答

部署(Docker 起基础设施,业务进程本地跑,便于开发调试):

bash 复制代码
# 1. 基础设施一键拉起:MySQL / Redis / RabbitMQ / ES(带IK中文分词) /
#    Qdrant / MinIO / TEI(embedding) / SearXNG(自托管搜索)
docker compose -f docker/docker-compose.yml up -d

# 2. 后端
cp .env.example .env          # 填 LLM_API_KEY 等
uv sync                       # Python 3.12 + uv 管理依赖
alembic upgrade head          # 建表(16 个迁移,含数据修复类迁移)
uvicorn src.api.main:app --port 8000
python -m src.document.worker # 独立 worker 进程:文档解析 + KG 生成双队列

# 3. 前端
cd frontend && npm ci && npm run dev   # Vite, http://localhost:5173

系统是本地单用户形态:没有注册 / 登录 / 多用户隔离,启动即用------首次请求自动创建一个固定的本地用户,知识库、文档、会话、记忆、模型配置全部挂在这一行用户记录下(users 表保留单行,因为下游十余张表的外键都指向它)。曾经实现过 local/hosted 双模式(JWT + 邮箱验证码),在明确"本地自托管"的产品定位后把 hosted 半边整体拆除------对一个本地工具,前后端合计上千行的多用户代码是纯负资产。

日常使用流程

  1. 建知识库 → 上传文档(或贴 arXiv 链接)。上传接口秒回 pending,后台 worker 异步完成解析、切分、向量化、索引、KG 抽取、合成产物刷新,前端轮询状态看进度;
  2. 选一个或多个知识库,直接提问。前端逐字流式渲染答案,思考气泡、工具调用卡片(含参数、耗时、结果)、计划卡片、自省与自校验卡片穿插展示------Agent 的整个推理过程是透明的;
  3. 需要深挖时切换研究模式,派课题(可选 quick/standard/deep 三档深度),看着子任务逐个完成、评审打回、增量修订,最后导出报告;
  4. 每轮对话结束后可以查看 trace 回放 (按 message_id 精确配对问答与推理步骤)、用量明细(prompt/completion token 与成本估算),可以对答案点赞/点踩(反馈会回流成检索加权)。

2.3 一次提问背后发生的事

这一节单独拎出来,因为它最能说明系统的复杂度。用户问:

"对比这两篇论文的注意力机制设计,各自的消融实验里哪个组件贡献最大?"

  1. 入口:用户输入过 injection 检测(只观测不阻断,用户是主体)→ 校验所选知识库归属 → 建会话(或 CAS 抢占续接)→ 载入最近 10 轮历史(超 18000 字符按预算裁最旧)→ 召回与问题相关的用户记忆注入 system prompt;
  2. 复杂度路由:先走规则(≤20 字且含"什么/谁/多少"等标记 → 直接 L1),否则小模型分级 L0~L3 + 判断是否"图问题"。这个例子是典型的 L2 多步推理,且命中"对比"关键词会附加图谱上下文(PageRank 核心实体 + 社区分组,纯算法零 LLM 成本);
  3. 规划:L2 启用 Planner------小模型产出 2~6 步结构化计划(Pydantic 校验 + DAG 校验,不合法回灌错误重试 2 次,仍失败降级无计划),注入 system prompt 作为软约束(保留 Agent 自主性);
  4. ReAct 循环 :大模型用原生 function calling 决策,一次可以发起多个工具调用,调度器按依赖分层并行执行。这个例子里 Agent 可能:list_kb_documents 看库全貌 → retrieve_chunks(detail=summary) 看检索概览(省 token)→ retrieve_chunks(ids=[...]) 取关键片段全文 → get_table 取两张消融表 → calc 复算贡献差值 → 生成带 [chunk:ID] 角标的对比答案;
  5. 过程治理:每 3 步 Reflection 自省(偏了就回滚上下文到上一个稳定检查点,连续 2 次偏离就重规划);Observation 超长自动分级压缩;预算剩余不足 10% 进入收敛模式(不再发起新工具调用);同一参数的检索直接命中会话级缓存;
  6. 自校验 :答案生成后,Self-Correction 把答案拆成至多 8 条原子论断,逐条调 cite 工具回到原文算语义支撑度(embedding 余弦,≥0.55 支撑 / ≥0.35 弱支撑 / 否则无支撑)。无支撑占比超过 20% 就带着"哪些论断没有证据"的指引重新生成;逃逸时在答案尾部明确标注「⚠️ 以下声明未能验证」;
  7. 收尾 :引用元数据(文档标题/章节/原文预览/页码)逐条推给前端做角标;assistant 消息、trace、token 用量、成本、被引用文档的 citation_count 全部落库;会话状态机走到 done

整个过程用户在前端实时看到每一拍。如果中途关掉页面,现场快照已存 Redis(TTL 24h),重新续接这个会话时会收到 session_restored 事件告知上次进度。

三、总体架构

复制代码
┌────────────────── 前端 Vue3 + Pinia + Vite ──────────────────┐
│  对话视图(流式渲染) │ 研究视图 │ 知识库(文档/图谱/合成/信任) │
│  记忆管理 │ 历史回放 │ 设置(多厂商 Key/模型/重排/嵌入)        │
└───────────────────────────┬──────────────────────────────────┘
                            │ REST + SSE(fetch 流式解析,手写帧解析器)
┌───────────────────────────▼──────────────────────────────────┐
│                      FastAPI(api 进程)                       │
│  chat(SSE) research(SSE) kb documents memories users settings │
├──────────────────────────────────────────────────────────────┤
│                      Agent 运行时(runtime)                   │
│  复杂度路由 ─ Planner ─ ReAct循环 ─ Reflection ─ SelfCorrect  │
│       │            (预算/早退/压缩/缓存/上下文管理/计量)       │
│       └── 工具调度器(DAG分层并行/重试/降级) ── HITL门控        │
├────────────────────────┬─────────────────────────────────────┤
│  工具注册表(22 个工具,JSON Schema 校验,MCP 兼容双视图)     │
│  LangGraph 研究编排(Planner→Researcher→Writer→Reviewer)     │
├────────────────────────┴─────────────────────────────────────┤
│  LLM 门面:OpenAI兼容/Anthropic/Gemini 三协议 + 用户Key优先链  │
│           + DSML 流式标签过滤 + 辅助调用计量(MeteredLLM)       │
├──────────────────────────────────────────────────────────────┤
│  文档管线(解析/切分/三写) 混合检索(RRF+rerank) KG(igraph)      │
│  渐进式合成 分层记忆 评测框架 工作流引擎 沙箱(Docker)          │
└──────┬─────────┬──────────┬─────────┬──────────┬─────────────┘
    MySQL     Qdrant      ES       Redis    RabbitMQ    MinIO
   (唯一源)  (向量检索) (关键词+IK) (缓存/热状态) (异步任务) (原始文件)
                   ↕ worker 进程(解析队列 + KG 队列,双线程消费)

技术栈:Python 3.12(uv 管理依赖)/ FastAPI / SQLAlchemy 2.0(async+sync 双会话)/ Alembic / LangGraph / httpx / Qdrant / Elasticsearch 8 + IK / RabbitMQ(pika) / Redis / MinIO / Docker SDK / igraph(社区检测与 PageRank)/ jsonschema / cryptography(AES-GCM) / pytest;前端 Vue3 + Pinia + Vue Router + Vite,前端也有自己的单测(SSE 解析器、store、工具函数均为纯函数可测)。

几个贯穿全局的设计原则:

  • MySQL 是唯一数据源,其余全是可重建的派生索引(详见第五节);
  • 降级优先于失败:Redis 挂了不影响检索、向量服务挂了退关键词、rerank 挂了退 RRF、反思失败默认 on_track、语义记忆提炼失败跳过......几乎所有外围依赖都有"失败不阻塞主流程"的显式路径,日志留痕;
  • 辅助 LLM 调用也计量 :路由/规划/反思/压缩/自校验这些"幕后"调用通过 MeteredLLM 代理包装,token 与成本全部计入会话账单,用量可解释。

四、核心技术实现

4.1 文档处理管线:异步、三写与版式感知切分

上传链路刻意做成异步 :API 把文件存 MinIO、写 DB、发 RabbitMQ 消息后立刻返回,用户不等解析。worker 进程(独立于 API,双线程分别消费 document.parsekg.generate 两个队列)完成重活:

复制代码
MinIO取文件 → 解析(多格式) → 注入检测(命中高危→隔离) → 版式感知切分
    → MySQL(chunks) 先提交 → Qdrant(向量) → ES(全文) → 标done
    → 失效该库检索缓存 → 刷新合成产物 → KG抽取(另一队列)

几个值得展开的点:

  • Prompt Injection 入库隔离 :文档是不可信外部内容。解析出的所有 block 逐一过注入检测(中英双语 30+ 正则模式),命中高危模式直接隔离------标记后跳过 chunks/索引写入,这篇文档永远进不了检索,从根上切断"上传恶意文档 → RAG 召回 → 劫持 Agent"的攻击链;
  • 版式感知切分 :表格块整体成 chunk 绝不切断(跨块的表格没法用);长文本块按句边界切、目标 ~800 字符(≈512 token 的免 tokenizer 近似)、相邻 chunk 重叠 1 句防语义断裂;每个 chunk 带 section_path(如 Method > 3.2 Attention)、页码、类型(text/table/equation/figure)元数据,结构化工具(get_table/get_equation)靠这些元数据工作;
  • 三写的顺序经过设计 :MySQL chunks 先提交,再删旧索引、写新索引。早期版本把"删 Qdrant/ES"放在 DB 事务内,一旦 commit 失败回滚,旧 chunks 还在但旧索引已被删------文档从检索中永久消失。现在的顺序保证任一步失败检索至少保留一侧,重解析可自愈;Qdrant/ES 本身非事务这个残余盲区由 scripts/rebuild_index.py 从 MySQL 全量重建兜底;
  • 崩溃恢复 :worker 启动时把卡在 parsing 状态的文档(进程被 kill 的残留)重置为 pending 并重新投递,避免文档永久卡死在"解析中"。

4.2 混合检索:RRF 融合、精排、反馈加权与两级缓存

检索是 RAG 的地基,DeepRead 在这条链上叠了六层:

  1. 双路召回:Qdrant 向量检索(query embedding,按库内 enabled+未软删的 doc_ids 过滤)+ ES 关键词检索(IK 中文分词)。两路互为降级:任何一路服务故障不阻塞另一路;
  2. RRF 融合score(d) = Σ 1/(60 + rank),倒数排名融合无需分数校准,是向量分(余弦)与 BM25 分不可直接比较时的标准解法。候选池取 top_k×3,给精排留空间;
  3. Rerank 精排:支持 TEI(自托管,多语言 ONNX reranker)与 OpenAI 兼容 rerank API,设置页可配;精排结果做越界索引过滤(rerank 服务异常数据会导致索引回绕错选内容),失败回退 RRF 顺序;
  4. 反馈加权 :用户对答案的点赞/点踩按文档粒度回流------boost = 1 + 0.05×(up−down) + 0.2×(可信度−1),clamp 到 0.5, 1.5,rerank 主导顺序时只作同分 tie-breaker。这是一个轻量的"用户纠错参与排序"闭环;
  5. 多样性重排:每篇文档最多保留 2 条进最终结果,避免 top-k 全被同一文档霸占(对比类问题尤其需要多文档证据);
  6. 两级缓存 :检索结果缓存(Redis,TTL 30min,key 含 kb 版本号------文档增删/重解析时 INCR 版本号即整体失效,杜绝"刚上传的文档查不到");查询改写缓存(TTL 24h)。另外会话内存里还有一层工具级缓存(见 4.6)。

此外 retrieve_chunks 工具本身是渐进式 的:detail=summary 只返回单行摘要(关键词周边截取,~120 字符),Agent 先花小钱看概览、判断哪些值得细看,再用 ids=[...] 精准取全文------相比"一次返回全文",设计目标为单次检索 token 降 70%+。长/多意图查询(>40 字或含"和/与/对比"等标记)还会用小模型改写成至多 3 个聚焦查询,分别检索后按 chunk_id 合并去重。

4.3 Agent 运行时:function-calling ReAct 循环

运行时核心是一个 ~1000 行的 ReactLoop,几个与教科书 ReAct 不同的工程决策:

  • 原生 function calling,不解析文本 :Thought/Action 不靠正则从模型输出里抠,直接用 OpenAI tools 协议。结构稳定,不会被模型措辞变化打破。为此还处理了 DeepSeek 特有的 DSML 问题(模型偶尔把工具调用以全角竖线标签形式输出在正文里而非 tool_calls 字段,见第七节);
  • 单轮多 Action 批处理 :模型一次返回多个 tool_calls 时全部交给调度器并行执行(同波 asyncio.gather),3 轮 ReAct 压缩成 1 轮。前端按 spec_id 配对工具调用与结果卡片,并行也不会挂错;
  • 流式的谨慎处理:模型同轮输出的 content 在发起工具调用时其实是"思考",所以流式增量先攒着不发,确认本轮无工具调用才作为答案推送------用户不会看到一段话先出现又被工具调用"吃掉"的诡异体验;
  • 收敛与预算 :步数上限(12)与 token 预算(L1 8K/L2 16K/L3 64K 三档)双约束;预算剩余不足 10% 进入收敛模式(后续轮次 tools=None);任一约束触顶后强制收敛------带着"请基于已收集的证据直接作答"的指令再问一次,拿"当前最佳答案"而不是空手而归。

4.4 工具层:注册表、DAG 调度器与作用域安全

22 个内置工具覆盖检索(retrieve/lookup/list_documents)、阅读(summarize/compare/parse_figure/locate_structural/get_table/get_equation)、验证(calc/cite/code_exec)、图谱(query_kg/traverse_kg/find_contradictions/graph_local/global/rank/find_path)、合成(synthesize)、交互(ask_user)与网络(search_web)。

每个工具是一个结构化 ToolDef:JSON Schema 入参(执行前校验,非法参数不进函数体;LLM 常把数字传成字符串的问题在 schema 层做类型强转)、危险级别(safe/caution/dangerous)、超时、重试策略(指数退避)、降级 fallback、成本估计。注册表对外提供两种视图:OpenAI tools 定义(给 ReAct)与 MCP tools/list(给外部 MCP 客户端)。

调度器 把一批带依赖的工具调用当 DAG 处理:Kahn 分层拓扑排序(有环直接报错),同波并行;单节点失败→可重试异常指数退避重试→仍失败走 fallback 工具→最终失败标 error,其下游标 skipped 不执行。一个细节:超时不重试------工具在 asyncio.to_thread 里跑,超时后底层线程无法取消,重试会造成重复副作用。

作用域安全 是工具层最重要的设计:Agent 的工具参数由模型生成、不可信build_scoped_registry 按会话作用域包装所有按 kb_id/doc_id/chunk_id 访问数据的工具------越权调用不抛异常,而是返回结构化错误进入 Observation,让 Agent 自己换用合法 id 继续(抛异常会打断整轮)。纯对话模式(未选知识库)直接从注册表移除全部 KB 类工具,否则 Agent 会反复撞墙空转到预算耗尽。

4.5 元认知:复杂度路由、计划、反思、自校验

这是项目最有"Agent 味"的部分,四个组件各管一段:

复杂度路由(入口分级) :短事实问题(≤20 字含"什么/谁/多少"标记)规则直判 L1 跳过 LLM;否则小模型分级 L0~L3 并判断是否图问题;分类失败降级 L2(安全侧:宁可多跑不要答错)。L0 走专门的快路径:单次多库并行检索 top-6 + 小模型直答,跳过规划/反思/工具循环全流程,简单问题 0 规划成本。

Planner(Plan-then-Execute) :L2/L3 先出结构化计划(step_id/description/tool_hint/depends_on),Pydantic + DAG 校验,不合法把错误信息回灌重试(最多 2 次),仍失败降级无计划 ReAct。计划注入 system prompt 是软约束 ------给 Agent 结构化思路可循,不强制硬执行每一步,保留自主性。Reflection 产出的 plan_amendment 会真正写回计划。

Reflection(周期性自省) :每 3 步一次,小模型基于客观信号(最近 trace 摘要 + 已检索证据数)判断 on_track / deviated / needs_more_evidence。关键是结论真正生效而不只是发个 SSE 事件:gaps 注入 messages 影响下轮决策;首次偏离→回滚上下文到上一个稳定检查点(同时清空工具缓存与证据计数------被裁掉的工具结果不再可信)并注入纠偏指引;连续 2 次偏离→触发重规划,无执行器则降级强制收敛;on_track 时更新检查点。

Self-Correction(答案自校验) :生成后把答案拆成 ≤8 条原子论断,逐条调 cite 回原文验证(embedding 余弦支撑度:≥0.55 supported / ≥0.35 weak / 否则 unsupported),幻觉率(unsupported 占比)>20% 且轮次未超限时带指引重新生成;超限逃逸,答案尾部标注「未验证声明」与「弱支撑声明」清单。刻意用客观信号(cite 支撑度)而非 LLM 自评 confidence------后者校准极差是业界共识。

4.6 成本与性能工程

Agent 应用绕不开"太贵太慢",这套组合拳是专门为它设计的(下表收益列为设计目标值,来自各模块设计时的估算,可通过评测框架复现验证;文中已实测的数字是测试数与覆盖率,见第六节):

机制 做法 设计收益
复杂度路由 简单问题走 L0/L1 快路径,不规划不反思 简单问答近乎零元认知开销
Early Exit L1 首次检索证据覆盖度 ≥ 阈值直接生成 跳过多余轮次
渐进式检索 summary 先看概览、ids 再取全文 单次检索 token ↓ 70%+
Observation 分级压缩 <400 原文 / <2000 规则提取关键字段 / 更长 LLM 摘要(压缩前先过注入过滤,防污染压缩调用) 每轮 Observation 占用 ↓ 60%+
上下文窗口管理 超预算时旧消息 LLM 摘要;system(含 Plan) 与用户原始问题锚定不动;tool_calls/tool 配对边界安全裁剪 长会话不爆上下文且不丢目标锚
会话级工具缓存 同参数检索/查询直接命中(回滚时清空防脏命中) 重复调用 ↓ 15~25%
大小模型分工 主循环大模型,路由/规划/反思/压缩/自校验全走小模型 元认知成本压到最低
全链路计量 MeteredLLM 代理包装,辅助调用也进账单 用量可解释、可核算

4.7 可靠性:流式、中断恢复与落库时机

流式与状态管理是这类系统最容易翻车的地方,DeepRead 的处理:

  • SSE 手写帧 (后端手写 event:/data:,前端因为 EventSource 只支持 GET 而用 fetch + ReadableStream 手写解析器------纯函数、脏帧静默丢弃、处理多字节字符被拆在 chunk 边界的情况);
  • 中断三通道 :用户点停止(置 asyncio.Event,循环每步检查,挂起的 HITL Future 秒级 resolve 而非等满 5 分钟超时)/ 客户端断开(CancelledError)/ 服务重启(启动时把卡在 executing 的会话批量复位为 error);
  • 热状态恢复 :HITL 挂起、用户中断、客户端断开三种"未完成现场"把 state_snapshot(问题/进度/用量/trace)落 Redis(TTL 24h),续接会话时推 session_restored;正常结束立即清热状态,防止下次误恢复旧现场;
  • 并发抢占 :续接会话用 UPDATE sessions SET status='executing' WHERE id=? AND status!='executing' 的 CAS 语义防同一会话并发执行;
  • 落库时机 :流结束后的落库用独立的 数据库会话(请求级会话的生命周期与流式响应 teardown 不宜耦合);研究模式的落库放在 finally 里但用独立 task 执行------客户端断连时生成器被取消,finally 里的 await 会被再次取消,内联落库会中途夭折、会话永远停在 executing(这是实际修过的 bug)。

4.8 研究模式编排(LangGraph 四角色接力)

研究模式用 LangGraph 把一次课题编排成四类研究角色的接力:planner → researcher → writer → reviewer(其中只有 researcher 在跑完整的 Agent 循环,planner/writer/reviewer 是各自角色的结构化 LLM 调用------按角色分工而非"更多 Agent"来设计,是刻意的选择)。reviewer 条件路由------无缺陷结束,有缺陷回到 researcher 增量重研

  • 增量重研 是核心设计:Reviewer 被要求把每个缺陷的 location 锚定到子任务 id。重研时只为缺陷相关子任务生成研究目标,只重研这些目标(复用已有证据),Writer 的 patch_mode 只重写缺陷段。配合死锁检测(同一 location 的缺陷连续两轮出现→判定修不动,跳过对应子任务避免无限循环)与超轮收尾(达 max_revisions 在报告尾部标注未解决缺陷),这套机制把"打回重做"的成本控制在增量范围;
  • 节点 = 运行时实例:researcher 的每个子任务跑一个完整的自研 ReactLoop(带作用域工具注册表),LangGraph 只负责图结构与路由,节点内部全是自己的运行时------这个桥接让两套系统各司其职;
  • 状态膨胀控制:ResearchState(LangGraph 共享状态)只存节点退出时的摘要产物(evidence 摘要/plan/draft/defects/审计消息),节点内完整 message history 不进共享层,但 token/成本聚合计数器必须带上(否则研究链路无用量可查);
  • 并发与深度:子任务信号量限并发 3(防 LLM 请求打爆);quick/standard/deep 三档预设控制子任务数(1-2/2-4/3-6)、单子任务预算(8K/16K/24K)与总超时(120/300/600s)。

4.9 知识图谱与 GraphRAG

文档入库后(异步队列)自动抽取 KG:NER 初筛(规则实体词典,省 LLM 成本)→ LLM 按句批抽三元组 → 实体对齐(小写归一 + embedding 模糊对齐,kb_id+normalized+type 唯一约束防重复节点)→ 写图(每条边带证据原文与置信度)→ 跨文档数值矛盾检测

矛盾检测做了两层口径治理:accuracy/precision/recall/F1 等指标可能以 0~1 小数或 0~100 百分数两种口径出现,先统一成小数;只有同一指标且同一数据集 在不同文档的数值差异超阈值(0.1)才建 contradicts 边------数据集上下文未知时不建(宁可不建也不要跨域硬比),可疑低值(如 accuracy<0.2,可能是错误率)单独标注提示核对。

读取侧是标准 GraphRAG 双检索,基于 igraph(C 核心):

  • local_search:实体定位(优先 Qdrant 实体向量语义召回------换个说法也能命中;失败退子串匹配)→ 内存 BFS 多跳邻居 → PageRank 加权排序;
  • global_search :优先读预计算的层级社区报告 (建图时 Leiden 层级聚类、逐社区 LLM 生成报告,按图签名 节点数:边数:最大id 自动过期)做 map-reduce------map 按批从社区报告提取与问题相关的要点(保留社区编号与具体实体/指标),reduce 归纳成全局回答;无报告时降级现场摘要路径。

单库子图一次性拉进内存构建 igraph,按 (kb_id, 节点数, 边数) 缓存------文档变化导致计数变化即自动失效,无需显式 invalidation。

4.10 渐进式合成与分层记忆

渐进式合成 :每个知识库维护一份持续演进 的合成产物,文档量到阈值自动升档:1 篇 digest(库级摘要)→ 3 篇 comparison(方法对比表)→ 5 篇 narrative(研究脉络,基于 KG 关系)→ 10 篇 survey(可导出的综述初稿)。文档集合变化把产物置 stale,下次访问惰性重建(非全量重算)。素材侧做了不少脏数据防御:乱码/编码损坏检测(UTF-8 双重误读的 mojibake 特征、锟斤拷标记、控制字符)跳过、公式降级占位、材料上限 30 篇防 token 爆炸,prompt 里显式声明"素材未覆盖的部分注明、不许编造"。

分层记忆:工作记忆(会话内存,不落库)/ 情景记忆(会话结束 LLM 摘要写入;系统兜底的"未找到证据"轮不写------失败经验被召回注入等于持续给 Agent 灌错误先验)/ 语义记忆(从近期情景记忆提炼的用户偏好,重要性更高)。存储双写 MySQL + Qdrant(用户过滤的向量召回),向量命中优先按相关性排序、不足按最近召回补足。遗忘策略:90 天未召回重要性×0.5,180 天归档(软删保留 trace)。

4.11 安全设计

安全不是一层而是一组纵深:

  1. Prompt injection 三层防御 :入库检测隔离(文档命中高危模式永远进不了检索)→ 运行时工具输出过滤(Observation 回灌前替换注入模式并加数据隔离标记,且在 LLM 压缩之前过滤------否则带注入的 observation 会先污染压缩调用)→ 工具调用意图校验(参数里藏着注入模式直接拒绝执行,结构化错误进 Observation 让 Agent 换路);
  2. HITL 门控 :dangerous 工具(如 code_exec)执行前弹确认卡片,只有明确白名单的回答("允许/确认/approve/...")放行,拒绝/超时/中断一律 blocked 并提示"不要重试同一操作,换其它工具";
  3. Docker 沙箱code_exec 在一次性容器里跑------断网(network_mode=none)、rootfs 只读(仅 /tmp 可写 64M tmpfs)、512M 内存 / 1 CPU cgroup 限额、30s 超时强杀、执行完 force remove,镜像缺失自动降级 python:3.12-slim;
  4. 数据面隔离 :本地单用户形态(无登录面,唯一的入口就是本机端口);数据访问仍保留 owner 过滤、会话级工具作用域校验、文档软删后全面退出检索、resolve_citations 按 kb_ids 过滤防引用越权------单用户下这些校验恒真,属于零成本的防御性保留,也是未来若做多用户时的现成边界;
  5. 密钥安全 :设置页保存的 Key AES-256-GCM 加密落库(主密钥 = SHA-256(SECRET_KEY),格式带 v1: 版本前缀留换算法余地,解密失败降级回 .env 不炸请求);MCP 个人令牌只存 SHA-256 哈希,明文仅签发时返回一次;
  6. 其它:SSRF 防护(URL 入库抓取层)、上传大小预拒(按 Content-Length 在读内存前拒绝)。

4.12 LLM 抽象层

统一门面 LLMClient(chat/chat_stream/model_for)下挂三个 provider:OpenAI 兼容(覆盖 DeepSeek/Kimi/通义/智谱/Ollama/vLLM 等一切 /chat/completions)、Anthropic 原生、Gemini 原生,全部 httpx 手写(含流式 SSE 解析、tool_calls 增量按 index 拼接、瞬时错误 429/5xx 指数退避------流式已产出增量后不重试防重复推送、推理模型 reasoning_content 单独收集)。设置页有厂商目录(预填 base_url 与模型建议值)+ 多套配置档案(llm_profiles,可保存多厂商配置一键切换)。

Key 解析优先链很讲究:小档调用走 小档Key → 大档Key → .env 逐级回退,base_url/协议同理;用户级客户端不缓存 (Key 可随时改,按请求现建保证即时生效);请求上下文用 contextvars 把当前用户带进工具层------无 user 参数的调用点(summarize/query_kg 等)也能用上当前用户自己的 Key,成本归属明确。

4.13 评测框架

可信的行为必须可以被度量。评测框架跑测试集(每条 case 一次完整 ReactLoop)产出 10+ 维度:工具选择 F1/精确率/召回率(精标 case)、引用命中率(引用的 chunk 是否在标注集合内)、幻觉率(引用了不存在的 chunk 即计)、完成率、效率分(token/耗时/工具次数)、诚实弃答率(insufficient 类 case,考"敢说不知道")、证据覆盖度、矛盾报告分,以及 LLM-as-Judge 的完整性/准确性两维。多次运行自动出回归 diff 报告(哪个指标升了降了一目了然)。检索侧另有独立的 recall/MRR/nDCG 指标脚本与黄金集。

4.14 个人 MCP 接入

一个 MCP 端点(POST /api/v1/mcp):长期令牌(SHA-256 哈希落库)校验后把本地用户设为 LLM 上下文,暴露只读工具子集(检索/术语/摘要/图谱查询/合成读取),全部走用户自己的 Key 与模型配置------Claude Desktop / Cursor 可以直接把你的知识库当工具用,且成本归属清晰。合成读取优先命中缓存(零 LLM 消耗)。

4.15 关键选型:为什么自研、为什么这么存

技术选型里最常被追问的不是「用了什么」而是「为什么不用现成的」,这里集中回答四个:

  • 为什么 ReAct 循环自研而不用 LangChain Agent / OpenAI Agents SDK? 三层考虑:①核心循环只有 ~1000 行,自研让我对每一步(流式攒发、收敛模式、HITL 门控插桩点、Observation 压缩时机)有完全控制,框架的抽象在这些插桩点上反而是阻力;②可测试性------ReactLoop 的全部协作者(registry/llm/reflector/...)都是构造函数注入,FakeLLM 脚本化回放就能端到端测整个循环,871 个测试里相当一部分直接得益于这个设计;③锁定成本低于学习成本------LangChain 的 Agent 抽象迭代很快,自研内核 + 协议层(OpenAI tools)跟标准走,不被框架版本绑架。
  • 为什么研究编排又用了 LangGraph? 研究模式需要的是图结构 + 条件路由 + 状态通道这些纯编排语义,不是推理语义------这恰好是 LangGraph 做的、且它对"条件边/节点/共享 state"的模型足够成熟。所以分工是:LangGraph 管图,节点内部跑自研 ReactLoop("节点 = 运行时实例")。用不用框架的判断标准是"这个抽象是否恰好匹配我的问题域"。
  • 为什么 MySQL + Qdrant + ES 三件套,而不是 PG + pgvector 一把梭? 单库一把梭确实是更简单的架构,选三件套有三个理由:①场景需要混合检索------向量召回和 BM25 关键词召回各自强项明显(术语精确匹配 vs 语义泛化),ES 的 IK 中文分词是刚需,PG 的全文检索对中文支持要自己挂插件另配;②"唯一源 + 派生索引"的架构里,Qdrant/ES 是可整体重建的缓存性质组件,MySQL 保证业务数据的事务性------这个一致性模型(见第五节)比单一数据库更清晰地匹配了"检索是服务、数据是资产"的分层;③自托管场景下 Qdrant/ES 都是单容器起服务,运维成本没有想象中高。代价是三写的原子性盲区,用写入顺序设计 + 重建脚本消化------这是明确的 trade-off,不是免费午餐。
  • 为什么自建评测而不是用 RAGAS / DeepEval? 核心差异:通用框架评的是"检索+生成",但 DeepRead 的核心行为是Agent 决策(工具选得对不对、敢不敢弃答、引用是否命中标注集),这些维度(工具选择 F1、诚实弃答率)需要 trace 级别的埋点,通用框架拿不到内部事件流。自建 10+ 维 scorer 直接挂在自研运行时的事件协议上,顺带获得了回归 diff 报告能力。

五、数据存储设计

5.1 选型与职责分工

存储 角色 存什么 一致性要求
MySQL 8 唯一数据源 全部业务实体(下表) 强一致,Alembic 迁移管理
Qdrant 派生索引 chunk 向量(collection chunks)、实体向量(kg_entities)、记忆向量(memories 可全量重建
Elasticsearch 8 + IK 派生索引 chunk 全文(关键词检索路) 可全量重建
Redis 缓存与热状态 检索结果缓存(30min)、查询改写缓存(24h)、kb 版本号、会话中断快照(24h) 全部可丢(降级路径)
RabbitMQ 异步任务 document.parse / kg.generate 两个队列 至少一次投递 + 消费端幂等
MinIO 对象存储 原始文件(docs/{owner}/{doc}/original.* 引用由 documents.file_key 维护

这个划分的核心哲学:MySQL 是唯一源,其它一切都是派生索引 。Qdrant 的 point id 直接复用 MySQL chunk_id;删文档 = 软删 deleted_at + 清派生索引;换 embedding 模型(维度变化)不需要迁移数据------rebuild_index.py 从 MySQL 全量重嵌重建即可。代价是"三写"的原子性盲区(见 4.1),用写入顺序设计 + 兜底脚本消化。

5.2 MySQL 表设计(15 张核心表)

复制代码
users ──┬── knowledge_bases ──< kb_documents >── documents ──< chunks
        │        │                                  │
        │        ├──< kg_nodes ──< kg_edges          ├──< kg_community_reports
        │        ├──< synthesis_products             └── (软删 deleted_at)
        │        └──< session_scopes >── sessions ──< messages
        ├──< memories                                      └──< traces
        └──< llm_profiles

几张关键表的设计意图:

  • users :单用户形态下只有一行固定本地用户(email/password_hash 列闲置保留,避免无意义的迁移),但这行是全局配置的载体------五类加密 Key 列(大档/小档/rerank/embedding/search,全部 AES-GCM 密文)、preferences JSON(模型/服务覆盖项)、MCP 令牌哈希。
  • documentsparse_status 状态机(pending→parsing→done/failed)驱动前端轮询;meta JSON 列放解析页数/结构质量/KG 状态等长尾元数据;deleted_at 软删(chunks 保留供审计,检索作用域全部按 deleted_at IS NULL 过滤);
  • chunksseq 保证切分顺序可复现;section_path 章节路径;type(text/table/equation/figure/reference);extra JSON 放 page_range/table_ref 等结构化扩展------结构化工具全靠这列工作;
  • kb_documents :多对多关联表但不止是关联------enabled(文档级开关,关掉即退出检索作用域)、src_credibility(来源可信度)、citation_count/feedback_up/feedback_down(检索加权与信任报告的数据源)、added_by(用户手动 vs Agent 自动归库);(kb_id, doc_id) 唯一约束;
  • sessions / session_scopes / messages / traces :会话与知识库多对多(作用域);messages 的 citations JSON 直接落引用元数据、feedback 落点赞;traces 的 message_id 把每轮推理步骤与 assistant 消息精确配对(历史回放按此重建),steps 是完整决策树(tool 调用含全量 result,接口默认只回 800 字符预览防载荷爆炸,?full=1 取原文);
  • kg_nodes / kg_edges :节点 (kb_id, normalized, type) 唯一(normalized = 小写归一实体名,对齐依据);边带 source_doc_id(证据溯源)+ confidence + evidence 原文;
  • kg_community_reports :GraphRAG 预计算社区报告,(kb_id, level, community_id) 唯一,signature 记录生成时图签名做过期检测;
  • synthesis_products(kb_id, level) 唯一,stale 标记驱动惰性重建;
  • memoriestype(episodic/semantic)、importance(遗忘降权)、last_recalled(遗忘时钟)、deprecated(归档软删);
  • llm_profiles :多厂商配置档案(协议/大小模型/加密 Key),is_active 一键切换。

5.3 一致性哲学的三个具体机制

  1. 写入顺序:DB 提交 → 删旧索引 → 写新索引 → 标 done。任何一步失败检索至少保留一侧,reparse 自愈;
  2. 缓存版本号失效 :文档集合任何变化(归库/移出/启停/重解析完成)INCR deepread:kb_version:{kb_id},检索缓存 key 含版本号,旧缓存整体失效------不需要遍历删除,也不存在"该失效没失效"的窗口;
  3. 图缓存签名 :KG 内存图缓存以 (kb_id, 节点数, 边数) 为 key,文档变化→计数变化→缓存自动 miss。

5.4 Redis 的三个角色与降级

检索缓存(miss 即重算,Redis 挂了只是变慢)/ 查询改写缓存(同上)/ 会话热状态(挂了丢失"中断恢复"能力,但会话照常能跑)。所有 Redis 操作超时 1~3 秒、异常静默降级------Redis 从来不是系统的可用性依赖

5.5 已知取舍与盲区(主动交代)

  • HITL Future 注册表是进程内 dict------单进程部署够用,多副本需要换 Redis pub/sub;
  • Qdrant/ES 非事务,极小概率 MySQL 提交成功但索引写入失败(rebuild_index 兜底);
  • token 计数用字符数近似(中文 1 字/token、英文 4 字符/token 折中 3),不引 tokenizer 依赖,阈值留了余量。

六、工程质量:测试、CI 与交付

以下数字均为当前仓库实测,非目标值:

  • 测试 :后端 76 个测试文件 / 871 个用例 全绿,前端 22 个文件 / 149 个用例 全绿;后端行覆盖率实测 83%(CI 门禁 80%,低于即挂)。测试策略上,调度器/注册表/RRF/切分器这类纯逻辑直接单测;LLM 相关用可脚本化回放的 FakeLLM;集成测试拉真实 MySQL/Redis/SearXNG/沙箱容器;
  • 静态检查:ruff(lint + format)与 mypy(80 个模块)全量通过,CI 强制;
  • CI/CD 三段流水线 (GitHub Actions):PR/push 跑 lint → typecheck → 单测(覆盖率门禁) → 前端测试与构建 → Docker 镜像构建;合入 main 追加集成测试(真实 MySQL/Redis + Docker 沙箱 code_exec + SearXNG 服务测试)、安全回归 (注入/意图校验/隔离专门跑)、评测框架回归;打 tag 触发 GHCR 镜像发布与可选 SSH 自动部署(部署后健康探针自检);
  • 数据库迁移:16 个 Alembic 迁移,含数据修复类迁移(如 memory 枚举值口径统一);
  • 配置分层:密钥与连接走 .env(环境变量优先),产品可调参数走 config.yaml(版本化),重叠项 env 覆盖 yaml------同一份配置在本地 localhost 与容器网络服务名下都能跑;
  • 可观测性:结构化日志中间件、全链路 trace、会话级 token/成本账单、健康/就绪探针分离。

七、踩过的坑:这些问题教会我的事

这部分是我认为这个项目里最有价值的部分------每个坑都是真实踩过、定位过、修复过的。每条附一个「定位信号」:这个 bug 最先在哪里露出马脚;复盘问题时,「怎么发现的」往往比「怎么修的」信息量更大、更值得记录。

1. SQLAlchemy Enum 的名与值。 ORM 的 Enum(SomeEnum) 默认按成员CHAT)存取,而迁移脚本建的是值枚举('chat')。MySQL ENUM 大小写不敏感会把 CHAT 归一成 chat,读回时按名查找直接 LookupError。修法:values_callable 显式按 value 落库,并统一全项目的枚举口径。

定位信号:读回实体时 LookupError,且只在 MySQL 环境复现------SQLite 测试库全绿,差点漏掉。

2. LangGraph 条件边里改 state 不生效。 langgraph≥1.x 的条件路由函数里修改 state 不会写回通道(变更静默丢失)。修法:所有状态变更(计轮次/patch_mode/研究目标)移到 reviewer 节点 返回值里完成,路由函数只读纯路由。以及节点函数返回 coroutine 会被当非法返回值,必须 async def 包一层------不能 asyncio.run(事件循环里嵌套调用报错)。

定位信号:reviewer 打回后 revision_count 始终为 0、patch_mode 不生效,节点内日志一切正常------变更在路由函数里被静默吞了。

3. 生成器取消时 finally 里的 await 被二次取消。 研究模式客户端断连,SSE 生成器被取消,finally 里的落库 await 也跟着被取消------落库中途夭折,会话永远停在 executing。修法:落库交给独立的 create_task(强引用防 GC),并给会话状态加了启动时兜底恢复。

定位信号:会话状态长时间停在 executing,finalize 函数的日志"有进入无退出"。

4. HITL 的先有鸡还是先有蛋。 loop 预推 HITL_REQUEST 事件后才执行 ask_user 工具,但用户可能在工具真正执行前就提交回答------那时 Future 注册表还是空的,接口 404,回答丢失。修法:先登记 Future 再发事件 ,工具侧复用已完成的 Future(await 已完成的 Future 立即返回)而不是新建。

定位信号:用户"秒答"时偶发 404,慢一点回答则一切正常------典型的时序窗口问题。

5. DeepSeek 拒绝空 assistant 消息。 把"content 与 tool_calls 均为空"的 assistant 消息回灌历史直接 400。修法分两层:消息序列化前过滤 + 空正文回填占位符。

定位信号:响应体里明确写着 "content or tool_calls must be set",且只在 Self-Correction 重生成轮出现(那轮历史里带着推理模型的空正文消息)。

6. DeepSeek 的 DSML 工具调用怪癖。 模型偶尔把工具调用以 <|DSML|tool_calls> 全角竖线标签输出在正文里而非 API 字段------工具没执行,模型却以为自己调过了。修法:写了一个流式有状态过滤器 ,跨 chunk 边界缓冲标签片段、把 DSML 块从正文流里剥离、flush 时解析成结构化 tool_calls。

定位信号:正文里出现全角竖线标签、Agent 声称"已检索"但工具调用计数为 0。

7. 推理模型把 max_tokens 烧在思考上。 DeepSeek-R1 类模型偶发输出空正文(思考过程耗尽输出预算),导致 Planner 降级、Reviewer 空洞地"零缺陷通过"、合成产物为空。修法分三层:空正文重试一次;合成用大 max_tokens;Writer 加显式指令重试。同时空答案有统一兜底文案,且该轮不写记忆 (失败经验被召回注入等于持续灌错误先验)。

定位信号:finish_reason=length 且 reasoning_content 很长而 content 为空------日志里一目了然。

8. 本地 embedding 模型的联网探测卡死 DB 事务。 sentence-transformers 构造时若 HF 不可达,在线探测会长时间挂起------而它发生在 worker 的 DB 事务里,行锁被占死。修法:优先 local_files_only=True 离线加载,缓存缺失才联网。

定位信号:worker 日志长时间停在 SentenceTransformer 构造,MySQL 侧看到行锁等待------两边的"卡住"对上号才定位到。

9. rerank 服务返回越界索引。 精排结果按 index 引用候选列表,服务异常数据会让索引回绕错选内容且不报错。修法:引用前过滤越界/负索引。

定位信号:检索结果内容与 query 明显不相关,对比 rerank 响应里的 index 与候选数------超了。

10. 上下文压缩把用户原始问题摘要掉了。 滑动窗口压缩后多轮对话里原始问题消失,反思与检索失去目标锚。修法:第一条 user 消息与 system(含 Plan)一样锚定不压缩;同时裁剪起点回退到不拆散 assistant(tool_calls)/tool 配对的位置------拆散配对是协议非法消息。

定位信号:多轮之后模型开始答非所问,dump messages 发现首条 user 消息早已被摘要掉。

11. 回滚后的脏缓存。 Reflection 判定偏离会回滚上下文,但被裁掉的工具调用结果还在会话缓存里------Agent 换路后命中旧结果等于继续走老路。修法:回滚时同步清空工具缓存与证据计数。

定位信号:回滚后 Agent 又拿到同一条旧结果,缓存命中计数 +1------日志把两件事的时间线连起来了。

12. RabbitMQ worker 崩溃的文档状态残留。 进程被 kill 后文档永远卡在 parsing。修法:worker 启动时扫描 PARSING 残留重置重投。

定位信号:文档状态长时间"解析中",且重启 worker 后依然如此------直到加了启动扫描。

八、技术要点索引

按技术方向罗列这个项目涉及、且可以展开讨论的要点的索引:

  • LLM 应用工程:function calling ReAct、流式 SSE(前后端两端的手写实现)、结构化输出校验与重试、研究编排(LangGraph 与自研运行时的桥接)、上下文工程(窗口管理/分级压缩/锚定)、成本工程(分级路由/早退/缓存/大小模型分工/全链路计量);
  • RAG 与检索:混合检索(向量+关键词)、RRF 融合、rerank 精排、查询改写与扩展、渐进式检索、反馈加权、GraphRAG(社区检测/PageRank/预计算报告 map-reduce);
  • 可信与安全:Self-Correction 逐论断验证、引用溯源、prompt injection 纵深防御、HITL 门控、Docker 沙箱、密钥加密存储(AES-GCM)、SSRF/越权校验;
  • 后端工程:FastAPI 异步、SQLAlchemy 2.0 双会话模式(async API + sync worker)、Alembic 迁移、消息队列驱动的异步管线、幂等与崩溃恢复、状态机设计、CAS 并发控制、asyncio 取消语义与生成器生命周期;
  • 数据系统:多存储选型与职责划分、唯一源+派生索引的一致性策略、缓存失效设计(版本号/签名)、Qdrant/ES/Redis/MinIO 的实际使用;
  • 前端工程:Vue3 + Pinia 状态机、fetch 流式解析、事件驱动的增量渲染、断线重连与历史回放(trace 重建);
  • 工程化:1020 个测试(871 后端 + 149 前端)与 83% 实测覆盖率、ruff/mypy 全量通过、GitHub Actions 三段流水线(含安全回归与评测回归)、Docker Compose 多服务编排(profiles 控制可选组件)、uv 依赖管理。

九、未来优化方向

项目目前是一个可长期自用的完整系统,但改进空间同样明确,按优先级排列:

  1. 评测基线公示:评测框架已就绪但缺少公开基线数字。计划自建一个小型学术问答集(20~30 条精标 case),把引用命中率、幻觉率、工具选择 F1 的实测结果跑出来放进仓库------让第四章的所有设计有可复现的证据。
  2. Self-Correction 精度升级:目前用 embedding 余弦做「声明↔原文」支撑度粗筛(阈值 0.55/0.35 按中文学术文本标定),计划换 cross-encoder 蕴含模型做精判,减少「语义相近但实际不支撑」的误判。
  3. 研究模式的细粒度流式:研究模式目前只推节点级进度(规划/研究/写作/评审),researcher 子任务内部的工具调用与思考事件不外推;计划把这些事件透传到前端,让研究过程像对话一样全程可见。
  4. 检索链路补强:精排容器(tei-rerank)改为默认启用;查询改写目前依赖远端小模型,可换本地 Ollama 消除外部依赖;ES 关键词召回加同义词扩展。
  5. 图谱抽取质量:NER 初筛目前是规则实体词典(配置里已预留 GLiNER 档位),计划切换到开源 NER 模型,并给实体对齐补别名表,减少同一实体的变体分裂成多个节点的情况。
  6. 长会话记忆压缩:跨轮历史目前是确定性的字符预算裁剪,长会话信息损失明显;可升级为分层摘要------旧轮压缩成要点、近期轮保留原文。
  7. 引用定位到页:citation 元数据已带页码(chunk 的 page 信息),前端还停留在段落悬浮卡;计划接 PDF 原文渲染,实现点击角标跳转到对应页并高亮。
  8. 分发体验:补一段 90 秒演示视频(对话全过程 + 引用悬浮 + 研究模式);探索桌面端打包(如 Tauri),把「clone + docker compose + uv sync」压缩成双击安装。
相关推荐
YM52e2 小时前
鸿蒙 ArkTS 实战|网络常用漫剧主角名称分类表:26 位主角 8 大分类 + 搜索筛选
学习·华为·harmonyos
深蓝海拓2 小时前
基于QtPy (PySide6) 的PLC-HMI工程实战记录(五)为当前动作画面的信号连接变量
网络·笔记·python·学习·pyqt
云贝教育-郑老师3 小时前
Oracle 块清除(Block Cleanout):commit 之后,数据块里的“战场“谁来打扫?
数据库·学习·oracle
敢敢のwings3 小时前
世界模型与FlashWorld:从“在梦中学习“到秒级3D场景生成
android·学习·3d
那年窗外下的雪.3 小时前
AIDC 学习日志|第 14 天|MAC Flapping 与 EVPN 多归属分层排障
网络·git·学习·macos·github·spine
薛定e的猫咪4 小时前
(arXiv 2026)GLiBRL :可学习基函数的深度贝叶斯元强化学习 ----待补充
人工智能·深度学习·学习·算法·机器学习
sunshine22 girl4 小时前
Angular7,9,学习笔记一 创建项目,基本语法
笔记·学习
小雪崩4 小时前
嵌入式学习 day30:minilog
linux·c语言·学习
xiaoxiangsiyan4 小时前
现代大型虚拟化智慧园区整体架构EVPN‑VXLAN落地全解
运维·网络·学习·架构