大模型很聪明,但它的知识有截止日期,而且不知道你手机里存了什么。RAG——检索增强生成(Retrieval-Augmented Generation)——就是解决这个问题的:先从你的文档里搜出相关片段,再把片段连同问题一起喂给模型,让模型基于你的资料来回答。
本篇从零搭建一个完整的本地 RAG 系统:文档切分、向量嵌入、ChromaDB 存储、相似度检索、最后接入 LLM 生成带引用的回答。全程在 Termux 上运行,所有数据不出手机。可以配合上一篇的 llama.cpp 本地模型,做到完全离线。
RAG 的核心思路很朴素:模型回答问题之前,先去文档库里"翻一下书",找到相关内容再作答。整个流程分两大阶段:索引阶段(把文档灌进向量库,只做一次)和 查询阶段(每次提问都走一遍)。
一个最小 RAG 系统需要四种角色:
| 组件 | 作用 | 本篇选型 |
|---|---|---|
| 嵌入模型 | 把文本转成向量(数字数组),相似的文本向量距离近 | bge-small-zh-v1.5(中文、轻量、本地) |
| 向量数据库 | 存储向量,支持快速相似度搜索 | ChromaDB v1.5.9(纯 Python、本地持久化) |
| 文本分块器 | 把长文档切成合适大小的片段 | RecursiveCharacterTextSplitter |
| LLM 生成器 | 根据检索到的文档和问题生成最终回答 | DeepSeek API(在线)/ llama.cpp(离线) |
RAG 需要的 Python 包比较多,在 Termux 原生环境就能装,不需要 proot。主要是三个部分:向量数据库(ChromaDB)、嵌入模型(sentence-transformers)、LLM 客户端(openai SDK)。
pkg install python-numpy python-scipy嵌入模型决定了向量质量,直接影响检索准确度。中文场景下 BAAI 的 bge 系列是首选。手机端推荐从轻量的 small 版本开始。
| 模型 | 体积 | 向量维度 | 推荐场景 |
|---|---|---|---|
| bge-small-zh-v1.5 ⭐ | ~100 MB | 512 维 | 手机端首选,速度快 |
| bge-base-zh-v1.5 | ~400 MB | 768 维 | 质量更高,内存充足时用 |
| bge-large-zh-v1.5 | ~1.3 GB | 1024 维 | 旗舰机且追求精度 |
RAG 的第一步是把文档吃进来。长文档不能直接嵌入——上下文长度有限制,而且大块文本向量不精准。必须切成一段段的"小块"(chunk),每段单独向量化。
最简单的是纯文本(.txt)和 Markdown(.md),直接读文件内容即可。如果有 PDF 或 Word 文档,可以用 pypdf 和 docx2txt 解析。
分块是 RAG 里最影响效果的环节之一。块太大,单块内信息杂,检索不准;块太小,上下文不完整,模型看不懂。chunk_overlap(块间重叠)是为了避免一句话被从中间切断,导致语义断裂。
"。"、"!"、"?" 等中文标点,确保尽量在完整句子处切分。文档切好后,下一步是把每一块文本转成向量(embedding),再存进向量数据库。向量数据库的厉害之处在于——你提问时也转成向量,然后它能在百万级数据里快速找出最相似的几个向量,这就是相似度检索。
向量库建好后,查询就很简单了——把问题也转成向量,让 ChromaDB 找出最相似的前 K 个文档块。
检索到相关文档后,最后一步是把文档和问题一起拼进 prompt,让 LLM 基于资料回答。核心就是构造一个好的系统提示词,明确告诉模型:"只能用给你的资料回答,如果资料里没有就说不知道,不要编造。"
上一篇学的 llama.cpp server 在这里派上用场了。只要改两行代码,把 base_url 指到本地,就能完全离线跑 RAG。
理论讲完了,现在用一个完整的实战项目把前面的内容串起来:把你的 Termux 学习笔记(Markdown 文件)导入 RAG,做一个能回答"第 15 篇讲了什么"、"怎么用 proot-distro 装 Ubuntu"这类问题的个人知识库。
到这里,阶段六的三篇就全部完成了。从调用云端 API,到本地运行大模型,再到搭建个人知识库,你已经掌握了在手机上做 AI 应用的完整技能树。后续阶段还会深入更多实战场景,但这三篇打下的基础,足够你探索绝大多数 AI 应用的可能性。