☰
从收藏夹到问答机器人:个人知识库+Agent+RAG实战全记录
2026/10/8 4:32:26 网站建设 项目流程

从“收藏了一堆文章却回答不了自己”这件事开始,我折腾了一整个周末,最后做了一个能用的个人知识库问答机器人。整个项目下来,我对“Agent 到底解决了什么问题”这个热词的理解完全是重写的。市面上讲 Agent 的资料很多,但大多停留在概念上,真正落到“我有一堆文档,我要让机器帮我答问题”这个朴素需求上的实操教程太少。这篇文章是我自己的项目记录,不谈虚的,只讲我在搭建过程中怎么选型、怎么入库、怎么编排 Agent 流程,以及在 Dify、RAG、结构化知识库、KG 知识库这些概念里踩过的坑和最终的决定。如果你也想做一个“能回答自己私人资料”的东西,这篇文章应该能帮你省下不少时间。

1. 先搞清楚:你要做的是“知识库”还是“Agent”

1.1 一个真实的失败案例:把文档塞进去不等于能问答

我第一次做个人知识库的时候,思路极其朴素:把 PDF、Markdown、公众号文章全部扔进一个向量数据库,然后接上大模型接口,用户提问,系统把相关片段捞出来拼进 prompt,让模型回答。听起来没毛病,但实际用起来完全是另一个体验。

我收集了大概 200 篇关于 AI 编程、Agent 开发、RAG 架构的文章,丢进去建了索引,然后问了一个很日常的问题:“我想在 Mac 上搭一个本地 RAG 知识库,有哪些工具推荐?”系统返回的答案是《如何搭建 Python 虚拟环境》里的某段内容,加上一篇介绍向量数据库原理的文章片段。从相关性上看,这些片段确实都跟“搭建”“Python”“数据库”沾边,但完全不是同一个问题。这就是纯 RAG 管道的经典局限:它做的是“文本相似度匹配”,而不是“理解你的意图并组织答案”。

1.2 Agent 与纯 RAG 管道的分工边界

后来我才意识到,知识库问答机器人这个需求,天然分成两个层次:低层是“找得准”,高层是“答得对”。“找得准”靠检索,也就是 RAG 管道的本事;“答得对”靠推理和多步规划,这才是 Agent 存在的意义。

举一个我项目里后来遇到的实际例子:用户问“我收藏的文章里,有没有提过 Claude 的 Agent Skills 机制和传统 function calling 的区别?”如果是纯 RAG 管道,它会把问题拆成“Claude”“Agent Skills”“function calling”这几个关键词去检索,返回的可能是三篇分别提到这几个词的文章片段,然后模型胡乱拼一个答案。但我最后做成 Agent 后,整个过程变成:先调用检索工具查“Agent Skills”,又调一次检索工具查“function calling”,再根据两批结果做对照,最后发现我收藏的某篇文章里确实有一段专门比较两者的内容,才给出有出处的答案。

这就是 Agent 的核心价值:它能把“检索”变成一种可以被调用、被组合、被决策的工具,而不是一次性拉数据的死流程。个人知识库问答机器人,名字叫“问答”,本质上是一个“检索—判断—再检索—综合”的循环,不引入 Agent 层面的编排,就永远只能做个加强版搜索框。

1.3 我最终采用的总体架构

基于上面的认知,我最终确定的架构分三层:

  • 入口层:一个 Web 界面加一个 API 接口,负责接收用户问题;
  • 编排层:Agent 本体,承担意图判断、工具选择和多轮调用;
  • 知识层:知识库加检索工具,内部再细分结构化数据表、向量索引和关系图谱。

这三层里,最容易被忽视、也最值得花时间的是知识层。因为 Agent 再聪明,知识层里没有对路的资料,它也答不出什么东西。这就像你雇了一个博士生替你查资料,但你的资料库本身乱七八糟,他再会查也白搭。

2. 三种知识库形态:结构化、RAG、KG 不是选择题而是场景题

2.1 结构化知识库:适合强规则、强权限的场景

现在很多文章把知识库概念炒得很玄,但剥开来看,个人能用的知识库存放形态无非三种:结构化知识库、RAG 知识库、KG(知识图谱)知识库。我在项目早期完全没有区分它们,什么资料都往向量库里塞,结果是很多本应该“精确命中”的问题被搞成了“模糊匹配”。

结构化知识库其实就是传统的关系型数据库,用表格存数据,靠字段精确匹配。它的特点是没有“语义理解”,但有极高的确定性和权限控制能力。比如你自己的读书清单、项目进度表、账单记录,这类“有明确字段、需要精确查询”的信息,就应该放进结构化知识库,而不是切成 chunk 去向量化。

我举个例子:我的知识库里有份表格记录“每周读的论文清单”,有标题、作者、阅读日期、打分四个字段。用户问“我上周给哪篇论文打了 8 分?”如果用向量检索去查,检索系统很可能返回一堆“论文推荐”文章片段,答得驴唇不对马嘴。但如果用 Agent 搭配 SQL 工具去查结构化库,一句 SELECT 就出来了,而且绝对准确。

2.2 RAG 知识库:非结构化资料的默认选项

RAG 知识库,准确说是“向量检索增强生成”,针对的是文本型、非结构化资料。个人项目里最常见的就是文章、笔记、PDF、网页存档。它的原理大家可以简单理解为三句话:先把文本切成小段(chunk),用 Embedding 模型把每段转成一个高维向量,用户提问时把问题也转成向量,然后找向量空间里距离最近的几个 chunk 喂给大模型。

这套机制的优势是非结构化资料不需要人工整理,扔进去就行;劣势是语义匹配的上限取决于 Embedding 模型和切块策略。我项目里大部分资料走的是这条路线,实际效果是:对“某篇文章大意”“某个概念的介绍”这类问题表现很好,对“数字统计”“两篇文章对比”这类问题经常翻车。翻车的原因不是 RAG 本身不行,而是这类问题超出了“按语义片段取回”的能力范围,需要 Agent 多做几步。

2.3 KG 知识库:多跳关系的杀手锏

KG 知识库是我在热搜词里看到“kg知识库”后才去认真补的课。它的核心不是文本,是实体和关系,结构类似“节点—边—节点”的图:比如“Dify”是一个实体,“支持”是一个关系,“知识库流水线”是另一个实体,于是有了“Dify—支持—知识库流水线”这条边。

KG 适合什么场景?答案是“多跳关系查询”。比如“哪些工具支持构建知识库流水线,同时又是开源协议?”

这类问题在纯 RAG 里很难一次到位,因为你不知道答案分布在哪些文本片段里;但在 KG 里就是简单的图遍历。代价也很明显:建图谱需要抽取实体和关系,要么靠模型自动抽取(费 token 且需要校验),要么人工维护(费时间)。个人项目如果不是以关系查询为强需求,我不建议一开始就上 KG,成本远高于收益。

三类知识库我列了一个表,方便大家对照:

类型数据形态适合回答的问题采集与维护成本个人项目优先级
结构化知识库表格、字段化数据精确查询、统计、权限过滤低建议先做
RAG 知识库非结构化文本语义查找、内容概述、知识解答中主力,投入最多
KG 知识库实体关系图关系推理、多跳问答、因果链高有特定需求再做

2.4 个人知识库该落在哪一档

按我这次的实践经验,个人知识库问答机器人最合适的起步组合是:结构化库存事实类清单,RAG 库存文本类资料,KG 暂时不做但有需求时可以通过 Agent 动态调取外部图谱服务。这套组合的逻辑很简单:用结构化数据保底精度,用 RAG 摊薄覆盖面,用 Agent 在两者之间做路由。数据库选型这几条路是:SQLite 做结构化,Chroma 或 qdrant 做向量,Neo4j 或轻量的 networkx 做关系图。个人项目千万别一上来就分布式的,没必要。

3. 从“微信收藏吃灰”到“库里可检索的资产”:入库全流程

3.1 素材采集:顺手才是第一原则

热搜词里有一条“如何把微信公众号看到文章保存到知识库”,我猜这是很多人的真实痛点。我在项目中的胃口也很朴素:刷公众号觉得有用的文章、浏览器里存的网页、PDF 电子书、Obsidian 笔记,四类素材都要能进知识库。

我的经验是采集链路一定要短,短到“复制链接”就算完成了。为这个目标,我用了两条路:一条是浏览器插件一键保存正文到本地 Markdown;另一条是在 Obsidian 里做每日阅读记录,凡是当天收集的资料统一丢进一个“待入库”文件夹。包括前面提到的“obsidian和trae搭建知识库”这种热词能火,本质原因就是 Obsidian 这种本地 Markdown 生态特别适合做个人知识库前置层,笔记天然是 Markdown,不需要复杂格式转换。

关于“把微信公众号文章保存到知识库”,我特别想提醒大家注意正文提取的准确性。公众号文章的网页结构比较多样,直接抓 HTML 经常带上一堆推荐阅读、广告位、页面脚本。我实操下来的做法分三步:

  • 先用通用正文提取脚本处理网页,输出 Markdown;
  • 人工快速扫一眼开头和结尾,去掉明显无关的段落;
  • 再把干净版本存入“待入库”文件夹。

这一步虽然烦,但从源头保证数据质量的效果远好过后期清洗。脏数据进知识库,后续每个环节都会付出代价。

3.2 清洗与分块:Chunk 不是切绳,是切藕

素材收集完,下一步是分块(Chunking)。这一步可以说是 RAG 知识库最影响问答质量、又最不容易被人重视的环节。很多人直接拿长度参数切,比如每 500 个字符一刀切,结果一个完整的概念被从中间断成两半,检索片段语义残缺,回答自然东拼西凑。

我的经验是可以把分块想成切藕而不是切绳:藕断丝连,每一块要保留上下文线索。具体的策略组合如下:

  • 按结构优先切,Markdown 的一二级标题是天然边界,标题下的内容如果太长再按段落切;
  • 设定分块大小 400 到 800 字(中文)之间,太大容易带进无关内容,太小则语义碎片化;
  • 设置块与块之间 64 到 128 字的重叠(overlap),把上下文丝线留住;
  • 代码片段、表格、列表单独处理,避免被切散。

实际做出来之后,我对比过同一份资料“只按长度切”和“按结构切”两种方案的检索效果。同样一个问题,按结构切的方案返回的前三段里有一段是正中要害的,按长度切的方案返回的三段全都差一点意思。这个对比让我确认了:分块策略不是一个可以在配置里敷衍的参数,它决定了检索质量的天花板。

3.3 向量化与索引:Dify 流水线的配置细节

向量化这一步,我最后是放在了 Dify 里做的,效果比手动调库顺滑很多。热搜词里“dify知识库流水线”出现的频率很高,可见大家也都在关注这个方向。

Dify 建知识库的流程比较直观:创建一个空知识库,选 Embedding 模型,上传文档,它会自动完成分段、向量化、索引。我用的 Embedding 模型是开源的 text2vec 系列,原因是本地部署无额外 API 费用,且中文效果够用。如果你不介意云端 API 成本,也可以用 OpenAI 的 text-embedding-3-small,效果更稳,但国内调用需要注意网络环境合规问题(尽量选择自己的合规环境),这部分我不展开。

索引方式我选的是“高质量”模式,也就是向量索引加全文索引的双路检索。这样做的好处是既支持语义查找,也支持关键词精确匹配。我在实践中发现很多“人名、型号、版本号”这类专有名词靠向量检索容易出偏,加上关键词召回互为兜底,明显提高了命中率。

3.4 入库后的召回率体检

这个环节是从“把教程抄完”到“真的能用”的关键分水岭:入库以后必须做召回率体检。我建完库后整理了 30 个自己平时真正会问的问题,逐一问机器人,记录答案是否有原文依据,是否答非所问。一轮下来,问题清单让我很沮丧:30 个问题里只有 14 个是满意的,7 个完全答错,9 个答得勉强可用。

然后我做了两件事,第一件是打开 Dify 的检索测试界面,依次输入这些问题,看真实召回的前 5 个 chunk 到底是什么。凡是正确答案明明在库里但没召回出来的,就调整分块方式;凡是答错的但召回内容是相关的,就优化提示词让模型不要乱发挥。第二件,是一些反复召不回的内容,我直接把它单独拎出来,手工调整它的分段结构,重新入库。这个笨办法确实有效,第二轮测试满意率提高到了 25 个。我想说的是不要相信默认配置,任何知识库都要拿“我自己的真实问题”来检验,不然上线就是自欺欺人。

4. 把知识库挂到 Agent 上:Dify 流水线实操与编排细节

4.1 可视化编排里的三个核心节点

知识库准备好之后,最核心的工作就是把知识库作为工具接到 Agent 编排上。我用的是 Dify 里的“工作流”模式,相比直接对话模式,工作流对每个环节有更强的控制力,便于排查问题。编排思路大致是三个节点:

  • 问题理解节点:接收用户输入,先做意图分类,判断是查事实清单(走结构化工具)、查文章知识(走 RAG 检索)还是需要多轮对比(走完整 Agent 循环);
  • 知识检索节点:调用知识库检索工具,设置 top_k(返回多少条)、score 阈值,把检索结果整理成可读文本;
  • 答案生成节点:把系统提示词、检索到的资料、对话历史一起组织成最终 prompt,交给大模型输出。

这三个节点的顺序不是摆设。问题理解节点如果做得粗糙,后续两个节点再努力也救不回来。我的做法是给分类 prompt 里写清楚决策规则,比如“如果用户问题里包含日期、打分、名单等字眼,优先走结构化查询”,并且要求模型输出 JSON 格式的分类结果,方便下游分支。

4.2 Skill 与 Tool 的设计:要不要给 Agent“开外挂”

随着对 Agent 的理解加深,我发现只接一个知识库检索工具是不够的,比如用户要我“把今天的笔记里提到的三个工具做个对比表”,这需要 Agent 有生成表格、甚至落盘输出的能力。在当前的主流框架里,这种可复用能力越来越倾向于做成 Skill,而不是零散的工具调用。热搜词里那条“claude agent skills: a first principles deep dive”很能说明问题:业界正在把“给 Agent 加技能”当成一等的设计单元来对待。

我在 Dify 里虽然没有直接使用文件型的 Skill 文件,但等效地做了两件事:一是把“生成对比表”“生成摘要卡片”这类固定任务封装成了自定义工具,Agent 需要在合适时机调用;二是把系统提示词里关于“何时用检索、何时用工具、何时直接答”的规则写得尽量明确,相当于隐性技能。核心设计原则是:工具宁少勿多,每个工具的输入输出描述都要写清楚,否则 Agent 会乱调。

4.3 提示词与上下文窗口的博弈

个人知识库问答第二大坑是上下文管理。大模型的窗口是有限的,个人知识库的检索结果往往又臭又长。如果每次把 5 段、每段 800 字的资料全部塞进 prompt,模型会迷失在细节里,甚至被无关内容带偏。我的配置经验是:检索返回 top_k 默认 4 到 5 条,每条长度控制在 600 字内,允许重叠但不能超限。在提示词里明确告诉模型“只能基于提供的资料回答,如果资料中没有相关信息,请直接说明不知道,不要尝试编造”。

这类提示词的写法有一个关键细节:要给模型一个“拒绝通道”。没有拒绝通道的模型,在资料不足时会强行拼凑答案,制造幻觉。我在提示词里专门加了一句话:“当现有资料不足以回答时,你可以回答‘我的知识库中暂未找到相关信息’,并可以建议用户换一种问法。如果你硬答,我不会给你加分。”实测加了这句话后,无依据乱说的情况少了很多。

4.4 关于 Token 消耗的账

既然是个人项目,成本也得算清楚。有些用户看到“ai agent token是什么意思”“token 消耗”这类问题,说明很多人一开始就被 token 概念搞晕过。Token 可以理解为模型处理文本的最基本单位,中文差不多一个字对应一个到两个 token,我自己粗略估算过,每次问答:

  • 系统提示词约占 300 到 500 token;
  • 检索结果约占 2500 到 4000 token;
  • 对话历史约占 1000 到 2000 token;
  • 模型输出约占 200 到 500 token。

一次完整问答的成本其实大头在检索结果上。所以我在编排时做了个小优化:如果问题在知识库中召回质量很高,就直接裁剪冗余片段,只保留得分最高的两条;如果问题本身是闲聊,就干脆不触发知识库检索,直接走普通对话。这套“先分类、再按需检索”的流程能把平均单次 token 消耗降下来 40% 以上。个人项目虽然单个请求不贵,但天天用积累下来也是笔不小的数字。

5. 我踩过的坑:检索噪声、幻觉和知识库排队

5.1 检索结果不对:先怀疑 Embedding,再怀疑排序

做知识库问答,最让人抓狂的坑是“库里明明有答案,机器人答不出来”。以前我总第一时间怪大模型,后来发现八成问题出在检索层。有一次我问“Dify 里怎么搭建知识库流水线”,系统返回的片段居然是介绍 Agent 工作流原理的。打开检索测试一看,前几名召回的相关度分数都很低但模型还是把它们塞给了我。

排查链路是这样的:先在 Dify 里单测检索,看没有大模型参与时到底返回了哪些片段。发现分数偏低后,我先换了 Embedding 模型(从偏通用的模型换成更适合中文语料的模型),效果有提升但不明显;随后我怀疑是分块问题,检查那段资料,发现原本在 Markdown 里分得很清楚的三个小节,被切块工具直接合并成了一段 1500 字的巨块,关键词被稀释,匹配分数自然上不去。重切之后,同一问题的召回结果直接命中目标段落。

这里给大家一个排查顺序建议:

  • 先在知识库检索页面看召回片段是不是答非所问;
  • 如果召回不对,先调整分块和索引;
  • 如果召回是对的,再优化提示词和生成参数;
  • 最后才考虑换大模型。顺序反了,往往白烧 token。

5.2 幻觉不是模型的问题,是你没给它“退路”

关于幻觉,我的观点可能跟主流不太一样。很多人一遇到机器人胡编就骂模型不行,但在个人知识库这个场景里,幻觉的根源往往是:prompt 没有定义“不知道”的出口。我在初版提示词里写的是“请回答用户的问题”,别的什么都没限制,于是模型即使没找到资料,也会依靠训练时的常识硬答。

举一个我踩过的具体例子:用户问“我知识库里有没有收藏过关于 Rust 语言做 Agent 的文章”,实际上我确实收藏过一篇,但分块切坏了导致没召回。模型没有检索到,却利用自身知识聊了一段 Rust 写 Agent 的优势,回答得很顺滑但完全不是我的知识库内容。这种回答对用户来说是极大的误导。修复方法除了改善检索,更重要的是 prompt 重构。我后来在提示词里加了一条硬性约束:“除非用户明确要求,否则回答内容必须来自检索到的资料。如果资料中没有,请直接说明‘未在知识库中找到’。”加完之后,幻觉式回答的出现频率直线下降。

5.3 Dify 知识库排队问题与批量任务处理

热搜词里“dify知识库排队中”是一个很有画面的词,我初期也遇到过。当时我一次性往 Dify 知识库里传了 50 多篇文章,界面显示“排队中”然后很久没动静。排查后发现,本质上是批量任务同时触发 Embedding 模型并发限制,Dify 在等待模型服务响应。个人项目没有接入高并发 API,就会出现排队。

我的解决方案比较务实:控制并发、分批处理。把 50 篇分成 5 批,每批 10 篇,中间隔一会儿再传;另外建了多个知识库分主题上传,比如“AI编程”“Agent开发”“效率工具”“个人管理”各建一个库,每个库的资源占用更均衡,问答时还能按主题路由,命中率更高。这个拆分带来的额外好处是:向量空间更聚焦,语义相似度计算更准。混合主题的大知识库,检索时经常被无关主题的文本干扰,拆开之后连 top_k 都能减少一个,效果反而更好。

5.4 知识更新的脏数据处理

个人知识库不是建完就完了,它需要持续更新。我大概是每周往里加 5 到 10 篇新文章,但前两天发现一个很隐蔽的问题:同一篇文章在浏览器插件保存和公众号文章保存时各进了一次库,两个版本略有差别,检索时两个版本都命中,模型综合了两个版本的信息,给出一个拼凑的回答,其中旧版本里过时的说法被当成了依据。

应对脏数据,我的办法是给每篇资料打上唯一标识,比如来源链接的 MD5 值,入库前先查重,重复的就跳过。对于已经入库的资料,如果发现有错误需要修正,我直接在 Dify 里删除旧文档重新上传新版本,不会存两份。另外,我还在知识库字段里加了一个“最后更新时间”的标签,回答问题时让模型优先参考时间更新的资料。这套流程听起来很基础,但确实能解决 90% 的知识库维护脏数据问题。

6. 个人知识库 Agent 的往后两步:记忆与轻量落地

6.1 Agent 记忆:从无状态到有状态

当前这个版本的个人知识库机器人还属于“无状态”的 Agent:你问一句,它查一次知识库组织一句答案,对话之间没有记忆。这种状态在小范围问答里够用,但一旦用户连续问“上次你说过的那个工具是什么来着”,它就傻眼了。热搜词里“agent记忆”热度很高,说明大家都在关心怎么让 Agent 记住上下文甚至长期偏好。

Dify 本身提供会话历史变量,可以在多轮对话里保留最近几轮的问答摘要。我的进阶方向是实现真正的“记忆”:不只是记住对话,还要记住用户偏好和未完成的任务。比如用户上次问“帮我找几篇讲 Agent 架构的文章”,他想要的是偏入门还是偏深入,这个偏好如果能被记忆并影响后续检索排序,体验会好很多。这个方向目前的实现方案是用摘要型记忆:每轮对话结束后让模型把关键信息压缩成短文本存下来,下次问答时拿出来作为上下文参考。成本不大,效果提升明显。

6.2 轻量化方案:本地文件加开源编排工具

不是所有人都想折腾可视化工作流。我的电脑性能一般,也试过更轻量的方案:全本地做。思路是用 Obsidian 作为知识库前置层,再用 Python 脚本配合一个支持工具调用的 Agent 框架(热搜词里提到的“搭建本地知识库”“怎么在mac上搭建rag知识库”都是这类需求),把检索、问答做到命令行里。流程是:先把 Obsidian 仓库里的 Markdown 文件全部扫描,用本地 Embedding 模型转成向量存进本地向量库,再写一个查询函数,由 Agent 判断何时调用。

这套方案的好处是:免费、私密、离线可用、数据完全在自己手里。缺点是灵活性不如 Dify,没有现成的可视化调试界面,出了问题排错更费劲。如果你只是想体验 Agent 交互和知识库检索,且愿意写点 Python,这条路线也值得试。我自己是两条路线并行的:重资料和日常问答走 Dify,零散想法和技术验证走本地脚本,各取所长。

6.3 从个人项目延伸出去的场景

做完这个项目,我最大的感受是:个人知识库问答机器人这个方向的价值被严重低估了。它表面上只是“给文档加了一个问答界面”,实际上是把零散的信息资产激活成了可服务自己的数字助手。我下一步打算做的场景有两个:一个是把“每周阅读清单”和“论文打分表”接到知识库里,让 Agent 每周自动生成一份阅读复盘;另一个是让知识库回应“我什么时候收藏过某个具体观点”,把它变成个人记忆的搜索引擎。如果你也在做类似的项目,我建议不要贪多,先把一个问题闭环做透,会比搭一个花架子更有收获。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询