
动手落地AI:我的第一个四行代码构建RAG应用
用 LlamaIndex 四行代码跑通第一个 RAG 应用,并逐行拆解这四行背后的加载、切片向量化、检索策略与生成合成。
TL;DR
过去我对 RAG 的理解一直停留在架构图上,知道要有数据处理、向量数据库、检索生成,但真正参与项目时总有隔靴搔痒的感觉。 这周我跟着教程亲手写出了第一个 Naïve RAG 应用,发现在 LlamaIndex 下它只有四行代码。 这篇文章逐行拆解这四行分别对应 RAG 的哪个核心组件、每行背后藏着哪些可调参数, 以及从能跑的 Demo 到能商用的产品之间,还差哪些工作。
目录
在很长一段时间里,我对 RAG 的理解停留在架构图上:我知道要有数据处理、要有向量数据库、要有检索生成。
但在真正参加一个 AI 项目开发时,我就会有一种隔靴搔痒的感觉。不懂代码逻辑,这似乎成了我深入理解 AI 边界的最大阻碍。
这周,我做了一个决定:打破这个边界。我跟着教程,亲手用 Python 写出了我的第一个 RAG 应用(Naïve RAG 应用)。
曾经以为隔着座山的 RAG 开发,原来只隔着这四行代码。今天这篇文章,我想通过这四行代码,解剖 RAG 的真实运作机理。
见证奇迹的四行代码
如果我不亲手去尝试,我不敢相信,传说中复杂的 RAG 系统,在 LlamaIndex 这个框架下,可以被浓缩到如此极致:
# 1. 加载数据documents = SimpleDirectoryReader("./data").load_data()
# 2. 构建索引(切片 + 向量化 + 存储)index = VectorStoreIndex.from_documents(documents)
# 3. 构建查询引擎(检索策略)query_engine = index.as_query_engine()
# 4. 提问并生成response = query_engine.query("晨光的名字是什么")但我们不能只看到热闹。这四行代码,其实分别对应了 RAG 架构中四个最核心的组件。接下来,让我们逐行拆解。
第一行:数据的入口
documents = SimpleDirectoryReader("./data").load_data()这一行代码在做什么?它在把我们人类能看懂的 PDF、Word、TXT,变成机器能处理的对象。
技术拆解:SimpleDirectoryReader 是 LlamaIndex 的搬运工。它不仅是读取文件,更是把非结构化的数据标准化。
Garbage In, Garbage Out:在实操中我发现,这行代码虽然简单,但也是最容易翻车的地方。如果你喂给它一个排版复杂的 PDF(比如双栏论文或带有复杂表格的财报),它读出来的可能是一堆乱码。这让我深刻理解了:
RAG 产品的护城河,往往不在模型端,而在数据处理端。谁能把复杂文档解析得更干净,谁的 RAG 效果就更好。
第二行:构建大脑(Indexing)
index = VectorStoreIndex.from_documents(documents)这是含金量最高的一行代码。它在后台悄悄完成了三件大事:Chunking(切片)、Embedding(嵌入)和 Storage(存储)。
技术拆解:
- 切片:它把长文档切成一个个小块(Node),就像把一本书撕成一页页笔记。
- 向量化:它调用 Embedding 模型(如 OpenAI 或 BGE),把这些文字片段变成一串串数字(向量)。
- 存储:它把这些向量存进内存或向量数据库中,建立索引。
成本与效果的权衡:这里有一个关键参数值得关注——chunk_size(切片大小)。
- 切得太碎?语义不连贯,模型看不懂。
- 切得太大?包含噪音多,而且检索一次消耗的 Token 多,成本飙升。
这行代码背后,其实是我们在做检索颗粒度和 Token 成本之间的博弈。
第三行:定义检索策略(Retrieval)
query_engine = index.as_query_engine()这一行定义了系统怎么找答案。
技术拆解:默认情况下,它采用的是向量相似度检索。当用户提问时,系统会把问题也变成向量,然后去数据库里计算距离,找出最接近的几个片段。
Top_K 的艺术:这里隐藏着一个参数 similarity_top_k(默认为 2),意思是找出最相似的 2 个片段给大模型。
- 如果是做法律咨询,可能需要把 K 调大(比如 5),确保信息不遗漏(高召回);
- 如果是做闲聊,K 小一点(比如 1)可能反应更快。
需要根据业务场景来定义这个 K 值。
第四行:生成回答(合成)
response = query_engine.query("你的问题...")最后这一行,才是大模型真正登场的时刻。
技术拆解:这一步发生了什么?框架在后台做了一个「Prompt 拼凑」的工作。它把第三步检索到的知识片段和你的问题,填入到一个预设的 Prompt 模板中:
请基于以下背景信息:(检索到的片段),回答用户的问题……
RAG 真相:RAG 并不是大模型学会了知识,它只是在做一场开卷考试。它的本质是:检索系统 + 阅读理解系统。
从 Demo 到 Product:四行代码之外的世界
虽然四行代码就能跑通 Demo,但通过这次学习,我更清醒地认识到,要把它变成一个可商用的产品,还需要做多少工作:
- 数据持久化:Demo 里的索引在内存里,程序一关就没了。做产品必须引入 FAISS 或 Milvus 等向量数据库,把知识存下来。
- 复杂解析:简单的 Reader 搞不定表格,我们需要引入 LlamaParse 或 MinerU 这样的高级解析工具。
- 效果评测:不能靠肉眼看回答好不好,需要引入自动化评测机制。
写在最后
这次手搓代码的经历,对我来说是一次视角的重构。
以前看 RAG,我看的是架构图上的一个个方框;现在看 RAG,我看到的是一个个可调节的参数,是一行行数据流动的逻辑:
解析器 → 切片策略 → 向量数据库(FAISS)→ Embedding 模型 → 检索策略 → 生成模式这每一个环节,都是可以优化的战场。
这一次手搓代码的经历,让我对 AI 产品有了全新的掌控感。不要被代码吓倒——在 AI 时代,代码正在变得越来越像自然语言。
行动是缓解焦虑的唯一解药。哪怕只写四行代码,也感到自己好像比昨天更强了一点。
核心结论
标注「判断」「假设」的是我的看法而非事实;标注「已推翻」的保留在这里,不删除。
引用本文
晨旭,《动手落地AI:我的第一个四行代码构建RAG应用》,晨光里的AI,2025-11-22
[晨旭:《动手落地AI:我的第一个四行代码构建RAG应用》](https://chenxu.xin/writing/first-rag-in-four-lines)