札记 / FIELD NOTES

手搓轻量 RAG 笔记:为什么我选择本地小模型向量化 + 云端推理?

径舟的技术选型复盘:放弃向量数据库和云端 Embedding,用 100MB 的本地小模型加一块 NumPy 矩阵,换来零部署、能离线、学生电脑跑得动的检索链路。

日期
2026-09-06
阅读
约 3 分钟

从限制出发,而不是从技术出发

做径舟之前,我认真用过 ima 和 NotebookLM。它们都很好用,但都有一个共同的前提:你得接受它们的形态——源文件数量有上限,必须联网,数据要上传到别人的服务器。我想做的东西很简单:学生把几份课件 PDF 拖进去,用自己的话提问,系统跨文档找出相关段落,给出带来源的回答。在自己的电脑上跑,教室里没网也能用。

目标一旦具体到这份上,技术选型反而容易了:所有"强大但重"的方案都可以划掉。

看懂别人的架构,然后扔掉它们的依赖列表

调研阶段我读了两个开源知识库项目。SurfSense 用 Next.js + PostgreSQL + pgvector + Celery + Redis,挂了 27 个外部数据连接器;open-notebook 用 FastAPI + Next.js + SurrealDB。都是好工程,但都是企业级形态——为一个"上传几份课件"的场景,引入五六个服务进程,就像为了泡一碗面先盖一间厨房。

我把它们的 RAG 流程图看懂了:分块、嵌入、检索、拼上下文、生成。然后把依赖列表扔掉,从零搭最小可行栈。

三个关键取舍

向量存储:NumPy 内存矩阵,不要数据库。 ChromaDB 功能完善,但要多一个进程和持久化层。我的目标场景单次上传不超过 10 份 PDF,语义块总量很小——NumPy 一次矩阵点积就是全部检索计算,毫秒级返回。而且向量先做 L2 归一化,点积就直接等于余弦相似度,连额外的距离函数都省了。零依赖,零配置。初版连持久化都不做,进程关掉一切归零;后来才把索引落盘,重启不必重传——但那是后话了。

嵌入模型:本地小模型,不要云端 Embedding。 云端 Embedding API 意味着每次索引都要联网、按量计费,还有数据出境的问题。我选了智源开源的 bge-small-zh-v1.5:100MB,纯 CPU 推理,中文语义相似度评测表现很好。首次启动通过国内镜像下载,之后完全离线。代价是嵌入计算吃 CPU——5MB 的 PDF 最初索引要 12 秒,用线程池加批处理压到了 3 秒。这是整个项目里最有"手搓"手感的一段优化。

分块与生成:段落优先,云端大模型只做最后一步。 先按自然段落切,再按 2048 字符窗口合并,相邻块保留 512 字符重叠,避免一个概念被从中间截断。提问编码成向量后取 Top-8 段落,按"文档名 + 片段编号"拼进提示词,要求模型仅基于文档回答并标注来源,DeepSeek 流式输出,前端打字机呈现。

轻量不是简陋

回头看,这条链路的每一笔都是"把复杂度花在该花的地方":检索留在本地,因为那是隐私和低门槛所在;生成放在云端,因为那是大模型不可替代的能力所在。径舟后来能在一周内搭出初版、拿到两个班级去给真实的同学用,靠的不是技术堆料,而是从一开始就没给自己背上多余的重量。

工具如此,做事也一样。

来信 ↗