这两天我给 ClarkLab 的工作笔记加了一个 AI 问答功能。
技术上没什么花头。Markdown 切片,Embedding,pgvector,DeepSeek,接起来能回答问题。
但跑通以后我才发现,真正折腾人的根本不是 RAG 本身。
是后面那些事——回答到底能不能信?应该引用哪篇原文?没找到答案的时候要不要硬答?问答框放多大合适?AI 在这个页面里到底应该是主角还是配角?
这些事,没有任何一篇教程提到过。
为什么想加这个功能
最近我一直在整理这些年做项目攒下来的东西。
无人机、GIS、YOLO、AI 识别、图斑核查、项目交付……有些是踩过的坑,有些是反复验证过的判断,写成 Markdown 一篇篇放到 ClarkLab 上。
文章慢慢多了以后,有个很尴尬的事:我自己都开始记不住以前写过什么了。
有一次我想找那篇"照片 GPS 为什么不等于目标位置"的笔记,明明记得写过,翻了半天才找到。
当时就想,能不能直接问它?不是搜索引擎那种关键词匹配,而是用大白话问一句,它能从笔记里翻出答案,顺便告诉我答案藏在哪几篇里。
第一版做得很快
链路很简单:
Markdown 切片 → Embedding → PostgreSQL + pgvector → 向量检索 → 拼上下文 → 大模型 → 回答。
就是把每篇笔记切成文本块,调 Embedding 接口变成向量,存进 pgvector,建 HNSW 索引。用户提问的时候,问题也变成向量,去库里找最相似的几块,拼成上下文丢给大模型。
跑通那天我试了一句"无人机 GPS 为什么不能定位目标",它真从《照片里的 GPS,为什么不等于目标位置》里找到了答案,还顺带把《无人机照片、视频和 OSD 为什么要对时间》也拉出来做了补充。
当时挺高兴的,觉得这事就算完了。
高兴了大概十分钟
它说的对,但我不知道从哪来的
第一版出来的回答就是一段文字,看着挺像那么回事。
但有个问题:我不知道它到底是从哪篇笔记里翻出来的。
我自己问的当然可以一篇篇去翻,但如果以后别人用呢?万一回答有误呢?
没有来源的 RAG,说到底还是让我重新相信一次 AI。跟直接问 ChatGPT 没什么本质区别。
所以加了引用。现在回答后面会列出参考了哪些笔记,带标题、相关度分数,点一下能跳原文。
参考来源 3
01 《照片里的 GPS,为什么不等于目标位置》
工作笔记 相关度 0.87 查看原文 →
02 《无人机照片、视频和 OSD 为什么要对时间》
工作笔记 相关度 0.79 查看原文 →
03 《高点视频目标经纬度计算,到底在算什么》
工作笔记 相关度 0.74 查看原文 →
有了这个,回答才有个落脚点。不然你看到一个答案,还得自己去验证,那费这劲干嘛。
不知道就说不知道
后来又试了个问题:"无人机目标定位精度到底能做到多少厘米?"
大模型本身当然能编一段出来。但我笔记里其实没有完整的精度测试数据。
这时候如果它用自带的知识补了一段,看着好像挺厉害,但那东西不是从我的知识库里来的,我也没办法验证。
所以我加了个约束:检索出来的相关度低于 0.35,就直接说"当前工作笔记里没有足够信息",不硬编。
切片这个事,比我想象的麻烦
一开始我按固定长度切,每 500 字符一刀。
结果很多笔记的核心结论刚好被切断了。前半段讲背景,后半段讲判断,中间一刀下去,检索到的块既没上下文也没结论。
后来改成按段落和标题结构切,尽量保持完整的语义单元。同时每篇笔记最多取 3 个块,上下文总长度不超过 3500 tokens。
改完以后回答明显靠谱了,不太会出现"说了一半突然跑偏"的情况。
UI 上来回改了好几版
功能跑通以后,我又在界面上纠结了很久。
一开始的想法是,既然 Ask ClarkLab 是新功能,那就放大。于是做了个巨大的区域,放在笔记页面最顶上,大输入框、快捷提问、占了一整屏。
做完看着挺像 AI 产品的。
但越看越别扭。
这个页面叫"工作笔记"啊。结果用户一打开,最抢眼的是个输入框,笔记列表反而被挤到下面去了。
我盯着屏幕看了半天,觉得不对。这个页面的主角应该是笔记,AI 是个辅助工具,不能喧宾夺主。
后来改成一个小入口卡片,点一下打开右侧聊天抽屉,可以一边看文章一边追问。
这个改动代码量很小,但我觉得是这两天做的最对的一个决定。
为什么没用 Dify
最开始也看过 Dify、RAGFlow。
如果只是快速搭一个企业知识库,它们确实方便,拖拖拽拽半天就能跑起来。
但 ClarkLab 很小,也很私人。我更想知道一条问题是怎么被检索出来的,数据怎么存的,文章怎么更新进知识库,引用怎么从回答回到原文。
所以最后还是自己一行行搭的。没有用现成的知识库平台,也没有套什么高级框架。
文件 → 切片 → 向量 → 检索 → 大模型 → 回答加引用。
每一层我都说得清,这就够了。
后来我发现这个事可以是个闭环
现在的工作方式大概是这样的:
我写一篇新笔记,放到 Markdown 目录里。部署的时候 Knowledge Indexer 自动把新文章切片、Embedding、存进 pgvector。有人来提问,系统从知识库里检索相关片段,交给大模型生成回答,后面附上参考来源。如果知识库里没有足够信息,就直接说没有,不硬编。
但我觉得更有意思的是后面那一步。
如果一个问题被问了好几次,但知识库始终回答不好,那说明什么?
说明这个问题我还没写清楚,或者根本没写过。
这其实是在提醒我:这个题值得再写一篇。
这样一来,ClarkLab 就不只是"我写文章别人看"了,而是变成了"我写 → 用户问 → 发现哪里还缺 → 我继续写"。
最后
这两天折腾下来,最大的感受是 RAG 本身真没那么复杂。Embedding、向量库、大模型,现在都有成熟方案,代码量不大,一个周末能跑通。
麻烦的是那些没人教你的事:引用怎么做,边界在哪,界面怎么摆,什么时候该闭嘴不答。
对我来说,这个 AI 现在就像一个坐在书架旁边的人。我问一句,它帮我翻出以前写过的东西,告诉我答案大概在哪几页。
至于那些我还没写下来的问题,它最好老老实实说:这个你还没写过。
ClarkLab 工作笔记:clarklab.cn/notes/