一次个人 RAG 探索的功能解析与实践总结

0 阅读6分钟

一次个人 RAG 探索的功能解析与实践总结

先说明一下背景:我本身只是前端开发者,这次更多是站在使用和实现结合的角度,去做一轮个人 RAG 探索。Agent 在这里主要承担了辅助搭建、整理链路和帮助落地实现的角色,并不是我已经完整掌握了整套 Agent 体系。

这篇内容也只从当前这次探索出发,只看已经落地的功能、背后的实现思路,以及后续还能怎么继续打磨。很多理解仍然比较朴素,更接近一次阶段性记录。

c058bd9c251acf4580b064fba4d5c3a2.png

整体结构

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把本地使用体验补完整

二、核心逻辑

这次探索的重点不是让模型自由发挥,而是尽量让回答建立在知识库证据上。对我来说,这也是最重要的一点,因为如果不能把回答和证据尽量绑定起来,后面的体验再完整,可信度也会比较有限。

整体链路可以概括成三步:

  1. 先把文档处理成可检索数据
  2. 再从知识库中召回和筛选证据
  3. 最后把证据交给模型生成答案

核心链路图

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. 来源追踪

回答不是只返回一段文本,还会把来源一起带回来,包括:

  • 文档名
  • 摘要
  • 页码
  • 章节
  • 关联图片

这一点很关键,因为知识库问答真正有价值的地方,不只是“答出来”,而是“能回到证据”。

三、实际效果

从当前结果来看,这次探索已经有几个比较明确的收获。当然这些收获更多还是阶段性的。

  • 知识库侧有了知识空间、任务进度、未归类迁移和文档统计

df47b7cc9b896c113586c1197db7ecf5.png

  • 桌面化后,本地配置、本地数据目录和内置后端被统一管理

6db2b1812f782b20a6f9477143cacc14.png

  • 聊天侧能明确展示检索进度、答案输出和来源依据
  • 顺便测试下知识库管理

image.png

image.png

5b38331a5e7e31162818147157cd1f3d.png

四、未来优化方向

1. 提升知识空间路由准确率

当前已经有自动识别和澄清机制,但多空间相似场景下,仍然有继续优化的空间。后续可以考虑让路由判断更多结合历史会话和空间摘要,而不只是当前问题文本。

2. 优化文档解析质量

现在已经能处理主流文档和图片提取,但复杂表格、截图密集文档、层级不规范的 Markdown 仍然值得继续打磨。尤其是结构化抽取质量,会直接影响后续检索表现。如果后面补上真正的 OCR 链路,图片类资料的覆盖面还会更完整。

3. 强化检索评估机制

当前已经有距离阈值、覆盖率和 reranker,但还缺少一套更系统的离线评估方法。后续如果补上标准问答集和检索评测,会更容易判断调参是否真的有效。

4. 继续打磨来源体验

现在已经能回看来源摘要和关联图片,但未来还可以继续增强,比如更明确地标出命中段落、章节层级,以及同一答案中不同来源各自贡献了什么信息。

5. 降低配置成本

当前设置页已经能管理大部分运行参数,但对第一次接触 RAG 的使用者来说,Embedding、Reranker、Chat 的配置门槛还是偏高。后续可以考虑提供更清晰的默认模板和预设策略。