一次个人 RAG 探索的功能解析与实践总结
先说明一下背景:我本身只是前端开发者,这次更多是站在使用和实现结合的角度,去做一轮个人 RAG 探索。Agent 在这里主要承担了辅助搭建、整理链路和帮助落地实现的角色,并不是我已经完整掌握了整套 Agent 体系。
这篇内容也只从当前这次探索出发,只看已经落地的功能、背后的实现思路,以及后续还能怎么继续打磨。很多理解仍然比较朴素,更接近一次阶段性记录。
整体结构
flowchart LR
A[前端 Vue 3] --> B[FastAPI]
B --> C[文档解析]
B --> D[检索与重排]
D --> E[Agent 生成]
B --> F[ChromaDB]
G[Electron] --> A
G --> B
一、技术选型
这次探索采用的是前端、后端、桌面壳分层的方式:
- Vue 3 负责聊天、知识库、设置等交互界面
- FastAPI 负责文档解析、向量入库、检索、重排和流式输出
- Electron 负责桌面承载和本地后端启动
我最后保留这套组合,主要是因为它足够直接:
- Vue 3 适合处理聊天流、知识库树、任务轮询和设置页这些状态型界面
- FastAPI 同时能覆盖 JSON API、文件上传、后台任务和 SSE
- ChromaDB 适合本地持久化,验证完整链路成本低
- Chat、Embedding、Reranker 解耦后,方便分别替换和调试
- Electron 补上了本地启动、配置保存和桌面分发这层体验
技术选型关系图
flowchart TD
A[Vue 3] -->|页面交互| B[聊天页 知识库页 设置页]
C[FastAPI] -->|提供| D[上传接口]
C --> E[聊天接口]
C --> F[健康检查]
G[ChromaDB] -->|存储| H[文本块 + metadata]
I[Chat Model] --> C
J[Embedding Model] --> C
K[Reranker] --> C
L[Electron] -->|承载| A
L -->|拉起| C
选择重点
| 部分 | 为什么这样选 |
|---|---|
| Vue 3 | 状态多,适合组合式组织 |
| FastAPI | 上传、流式、任务都能一起处理 |
| ChromaDB | 本地优先,验证成本低 |
| 模型解耦 | 方便单独替换 Chat / Embedding / Reranker |
| Electron | 把本地使用体验补完整 |
二、核心逻辑
这次探索的重点不是让模型自由发挥,而是尽量让回答建立在知识库证据上。对我来说,这也是最重要的一点,因为如果不能把回答和证据尽量绑定起来,后面的体验再完整,可信度也会比较有限。
整体链路可以概括成三步:
- 先把文档处理成可检索数据
- 再从知识库中召回和筛选证据
- 最后把证据交给模型生成答案
核心链路图
flowchart LR
A[上传文档] --> B[结构化解析]
B --> C[二次切分]
C --> D[写入 ChromaDB]
E[用户提问] --> F[知识空间判断]
F --> G[query expansion]
G --> H[向量召回]
H --> I[rerank + 过滤]
I --> J{证据够不够}
J -->|否| K[直接拒答]
J -->|是| L[Agent 生成]
L --> M[答案 + 来源]
1. 文档入库
这一段我最关注四件事:
- 先按文件类型做结构化解析,而不是直接粗切
- 保留章节、页码、段落、标题路径这些位置信息
- 在 embedding 前再做一次 token 级切分
- 用知识空间自动补全 metadata,减少重复输入
另外,PDF 和 Word 中的图片也会进入处理链路。不过当前实现主要还是做图片提取和来源展示,还没有真正把图片识别成文本再参与检索。
当前没有直接接入 OCR,我自己的考虑主要还是偏务实:先把正文解析、检索和来源追踪这条主链路跑稳。因为一旦加上 OCR,就会带来额外依赖、上传耗时和误识别噪声。如果没有先把 OCR 结果的评估和清洗做好,很容易让检索结果变得更杂。
入库流程图
flowchart TD
A[文档上传] --> B[按类型解析]
B --> C[提取章节与位置]
C --> D[生成初始文本块]
D --> E[拼接知识空间 metadata]
E --> F[embedding 二次切分]
F --> G[图片处理]
G --> H[写入向量库]
2. 检索与回答
聊天链路看起来是流式输出,但真正顺序其实是先检索、后生成。流式只是交互表现,内部第一步并不是立刻调用大模型,而是先判断检索范围和证据质量。
后端会先做:
- 知识空间判断
- 问题扩写
- query expansion
- 向量召回
- reranker 重排
- 证据充分性判断
我自己比较看重这里的几个判断点:
- metadata filters
- 显式标识符检查
- 核心概念覆盖率判断
- 距离阈值控制
- 单文档 chunk 数限制
这些限制的作用都很一致,就是尽量把“像答案但不可靠”的结果挡在生成阶段之前。只有证据够了,才进入生成;证据不够,就直接拒答。最后输出时还会再清洗一遍,去掉思维链、提示词残留和内部标签。
关于问题扩写,我觉得十分重要,用户的问题可谓是千奇百怪甚至带有网络用语和梗,这加大了LLM理解的难度,所以在正式查询之前需要对用户的问题进行一次扩展,比如生成2-3个语义相似,表达不同的问题(更加书面化正式化的用语),因为一般能被收录到知识库的文档都是较正式的文件。
回答决策图
flowchart TD
A[用户问题] --> B[识别知识空间]
B --> C[扩写查询]
C --> D[召回候选]
D --> E[重排]
E --> F[证据检查]
F -->|不足| G[拒答]
F -->|足够| H[生成答案]
H --> I[清洗输出]
I --> J[返回答案和来源]
3. 来源追踪
回答不是只返回一段文本,还会把来源一起带回来,包括:
- 文档名
- 摘要
- 页码
- 章节
- 关联图片
这一点很关键,因为知识库问答真正有价值的地方,不只是“答出来”,而是“能回到证据”。
三、实际效果
从当前结果来看,这次探索已经有几个比较明确的收获。当然这些收获更多还是阶段性的。
- 知识库侧有了知识空间、任务进度、未归类迁移和文档统计
- 桌面化后,本地配置、本地数据目录和内置后端被统一管理
- 聊天侧能明确展示检索进度、答案输出和来源依据
- 顺便测试下知识库管理
四、未来优化方向
1. 提升知识空间路由准确率
当前已经有自动识别和澄清机制,但多空间相似场景下,仍然有继续优化的空间。后续可以考虑让路由判断更多结合历史会话和空间摘要,而不只是当前问题文本。
2. 优化文档解析质量
现在已经能处理主流文档和图片提取,但复杂表格、截图密集文档、层级不规范的 Markdown 仍然值得继续打磨。尤其是结构化抽取质量,会直接影响后续检索表现。如果后面补上真正的 OCR 链路,图片类资料的覆盖面还会更完整。
3. 强化检索评估机制
当前已经有距离阈值、覆盖率和 reranker,但还缺少一套更系统的离线评估方法。后续如果补上标准问答集和检索评测,会更容易判断调参是否真的有效。
4. 继续打磨来源体验
现在已经能回看来源摘要和关联图片,但未来还可以继续增强,比如更明确地标出命中段落、章节层级,以及同一答案中不同来源各自贡献了什么信息。
5. 降低配置成本
当前设置页已经能管理大部分运行参数,但对第一次接触 RAG 的使用者来说,Embedding、Reranker、Chat 的配置门槛还是偏高。后续可以考虑提供更清晰的默认模板和预设策略。