从零搭出能回答"自己文档"的 RAG:179 行代码,成本不到 1 毛
为什么做这个项目
我是研一学生,目标是 2027 年暑期实习。一直想做点"能真正回答问题"的 AI 项目,而不是 demo 级的调用示例。VisionRAG 的设想是做一个图文混合的检索问答系统:企业里有大量图文混排文档,传统关键词检索找不到图,纯文本 RAG 又丢图像信息------最终产品要让每个答案都能溯源到具体图片和段落。
这个目标太远,所以第一周我只做一件事:先让 RAG 跑起来(纯文本版 v0)。这篇文章记录这 5 天(实际用了 3 天)的过程、代码和踩过的坑。
什么是 RAG
RAG(Retrieval-Augmented Generation,检索增强生成)解决大模型的一个老毛病:知识停在训练时点,新资料它不知道,还会瞎编。做法是:先把资料切块、转成向量存起来(建索引);用户提问时,把问题也转成向量,找出最相关的几个片段;再把片段和问题一起交给大模型,让它"看着资料"回答。
五步链路:加载 → 分块 → 嵌入 → 检索 → 生成。
5 天过程
- D1 :uv 装环境、git 建仓、配
.env、第一次调通 DeepSeek API - D2 :把项目拆成
config.py / llm.py / main.py三层,首次跑通对话 - D3:流式输出、温度参数、API 成本计费、防崩兜底、多轮记忆------还抓出一个"每句话调两次 API"的烧钱 bug
- D4:写最小 RAG------4 篇短文分块嵌入建索引,余弦相似度检索,3 个测试问题 top-1 全部命中
- D5:把检索片段拼进提示词生成答案,v0 端到端跑通------问"今天天气"它会老实说不知道
- D6 :整理结构、写 README、补
.env.example(还修了一个 gitignore 的坑)
技术核心:三段加起来不到 40 行
嵌入(embedding)就是把文字变成一串数字(向量),我管它叫"语义身份证":意思相近的句子,向量方向也接近。检索 = 拿问题的身份证,跟所有候选比方向像不像。
余弦相似度衡量两个向量方向有多像,公式就三行:
python
def cos_sim(a: list[float], b: list[float]) -> float:
dot = sum(x * y for x, y in zip(a, b))
na = math.sqrt(sum(x * x for x in a))
nb = math.sqrt(sum(y * y for y in b))
return dot / (na * nb)
生成环节的核心是提示词组装------把检索到的片段拼进模板,再让模型回答:
python
prompt = f"""请基于以下资料回答用户问题。如果资料里没有答案,请直接说不知道。
资料:
{context}
问题:{question}"""
最后那句话是关键:"没有答案就说不知道"。实测问"今天上海天气怎么样",模型回答"不知道。资料中没有上海天气的信息。"------RAG 系统最重要的品行不是"能答",而是"不乱编"。
踩过的坑(全是真金白银)
1. 每句话被调了两次 API(最烧钱):给聊天加防崩代码时,旧的调用没删,导致一句话被调两次 API------回答出现两份,花费 double。排查套路:现象(两次回答)→ 假设(两次调用)→ 读代码证实(run() 里有两个 stream_chat)。
2. 把 >>> 敲进了 PowerShell :终端和 Python 解释器是两回事。PS> 开头是操作系统命令;先输入 python 进入解释器,出现 >>> 才能敲 Python 代码。看起来弱智,但第一天真踩了。
3. .env.example 被 gitignore 吞了 :.env(真密钥,不能上传)和 .env.example(空模板,应该上传)长得太像,规则 .env.* 把模板也误杀了。加一行 !.env.example(感叹号 = 例外)救回来。教训:"文件存在" ≠ "文件会被提交" ,改完 .gitignore 必查 git status。
4. 零宽空格(U+200B):一个看不见的字符 :从网页复制代码时会带进一个不可见字符,导致 if __name__ == "__main__": 永远为 False。踩了两次才学会排查:len('__main__') 应该是 8,多 1 就是有脏字符。现在关键代码一律手敲。
数据说话
- 代码量:179 行(8 个文件),完整跑通一个 RAG 问答
- git 提交:11 次,每次提交都是一天的边界
- 欠债清单:21 条------遇到不懂的先记下来,S2 阶段集中清偿。这是我学到的工程习惯:不装懂
- 检索质量:3 个测试问题 top-1 全部命中(相似度 0.66 / 0.77 / 0.73)
- API 成本:不到 1 毛(约 0.02~0.05 元,口径:按未命中缓存计费估算)
下一步
- v1:检索质量优化------混合检索(关键词 + 向量)、Rerank、加评测(Recall@k、Faithfulness)
- v2:多模态------图像索引 + VLM 问答
- v3:服务化------FastAPI + Docker + 追踪
结尾
代码在 GitHub:github.com/huruxia/vis... 踩坑全集(DEBT.md):github.com/huruxia/vis...
感谢看完。有任何问题欢迎交流,尤其是分块策略和检索评测------那是 RAG 里最值得实验的部分。