RAG从零开始
1. 什么是RAG?
RAG(Retrieval-Augmented Generation):检索增强生成,是给 LLM 喂 “专属资料” 的一套标准化流程。
核心三要素:
- 检索(Retrieval):从海量资料里找和用户问题最相关的内容
- 增强(Augmented ):把找到的内容拼接上提示词喂给 LLM
- 生成(Generation):让LLM基于这个增强后的提示词给出答案
大白话: 以前LLM是“闭卷考试”,RAG让它变成了“开卷考试”——允许它先翻书,再答题。
2. 为什么需要RAG
大语言模型(LLM)很强大,但它们有一个致命弱点:知识是静态的。
- 训练时学习:把海量数据喂给模型,让它记住,但是缺点是:它不知道训练后发生的事,成本高。
- 推理时学习:在回答问题时临时“查资料”。遇到没见过的专业领域,会“编造”答案(这叫
幻觉)。
试想:现在公司有一个一百万页的PDF文档,里面的数据是绝密的,此时如果一次性丢给LLM会咋样?
- Token消耗量爆炸!!!
- 信息泄露!!!
RAG 的核心价值在于:让大模型可以访问私有化、实时化数据,同时减少Token消耗
3. 核心组件
- 嵌入模型(Embedding Model):把文字转换成一串数字(向量)
- 向量数据库:存储所有文档片段的向量,并支持快速相似度搜索
- 大语言模型(gpt、豆包…):根据增强后的提示词生成答案
4. RAG的工作原理

【前置知识】
- 什么是向量:就是一串数字,例如:
[0.12, -0.45, 0.67, …]- 向量化:将文字转化成向量,例如:你好! → [0.11, 0.33, …]
- 意义:计算机无法直接比较两句话的相似度,但可以比较数字。向量让语义变成了可计算的数学对象。
- 计算向量相似度的方法:
余弦相似度(最常用)、欧式距离、点积
【完整步骤】:
- 文档分片:把500页的PDF切成小段(比如按段落或500字一段)。因为大模型一次能处理的内容有限,分片后检索更精准。
- 文档向量化:每个小段通过嵌入模型转成一串数字(向量),存进向量数据库,方便后续搜索。
- 用户提问向量化:用户输入的问题也用同一个嵌入模型转成向量。
- 相似度计算:用余弦相似度公式算出【问题向量】和【每个文档向量】的相似度。
- 检索 Top-K:把相似度从高到低排序,挑出最相关的 K 个文档片段,这些就是给大模型参考的资料。
- 构建提示词:把挑出来的文档片段和用户问题拼成一个完整提示词
- 生成答案:把提示词发给大模型(如DeepSeek、GPT)。模型根据资料组织语言,生成自然、准确的回答。
- 返回答案:把最终答案展示给用户。整个过程用户感知不到背后检索,只觉得模型“懂”他的问题。
5. 手搓极简RAG系统
5.1文件结构:

5.2 准备工作
-
初始化项目
npm init -
我们需要一个轻量级 embedding 模型库
@xenova/transformers:npm install @xenova/transformers -
准备知识库
苹果是一种水果,富含维生素C。 香蕉是一种热带水果,富含钾元素。 北京是中国的首都,有故宫和长城。 Python是一种编程语言,适合数据分析。 JavaScript是一种前端编程语言。 MCP是模型上下文协议,让LLM具备调用外部工具的能力。 RAG是检索增强生成技术,让LLM能够查阅外部知识库。
5.3 工具函数
/**
* ReadFile.js -- 读取知识库文件
* 这里只是简单的把文件内容读出来并直接返回去,一般来说正常情况下还需要对文件内容进行分片处理
*/
import fs from 'fs';
export function ReadFile() {
const filePath = '../data/knowledge.txt';
const content = fs.readFileSync(filePath, 'utf-8');
const documents = content.split('\n').filter(line => line.trim());
return documents;
}
/**
* CalcCosinSimilarity.js -- 余弦相似度计算函数。
*/
export function cosineSimilarity(a, b) {
let dot = 0, normA = 0, normB = 0;
for (let i = 0; i < a.length; i++) {
dot += a[i] * b[i];
normA += a[i] * a[i];
normB += b[i] * b[i];
}
return dot / (Math.sqrt(normA) * Math.sqrt(normB));
}
5.4 RAG
-
Embedding:加载嵌入模型,提供向量化函数
import { pipeline } from '@xenova/transformers'; let embedder = null; export async function initEmbedder() { if (!embedder) embedder = await pipeline('feature-extraction', 'Xenova/all-MiniLM-L6-v2'); return embedder; } export async function getEmbedding(text) { const model = await initEmbedder(); const result = await model(text, { pooling: 'mean', normalize: true }); return Array.from(result.data); } -
Retrieve: 检索前 k 个最相似的结果
import { getEmbedding } from './Embedding.js'; import { cosineSimilarity } from '../utils/CalcCosinSimilarity.js'; export async function retrieve(query, documents, docVectors, topK = 2) { const queryVector = await getEmbedding(query); const similarities = docVectors.map((vec, idx) => ({ text: documents[idx], score: cosineSimilarity(queryVector, vec) })); similarities.sort((a, b) => b.score - a.score); return similarities.slice(0, topK); } -
Generate:拼接提示词,增强检索
export function generatePrompt(question, context) { const contextText = context.map(doc => doc.text).join('\n'); return ` 基于以下参考资料回答问题: 【参考资料】 ${contextText} 【问题】 ${question} 【回答】 .... `; }
5.5 极简 RAG系统
- 加载Embedding模型:使用 Xenova/all-MiniLM-L6-v2(一个轻量级的嵌入模型)
- 用户提问Question
- 对Question向量化:将用户的问题文本转换为数字向量(embedding)
- 构建向量数据库:读取知识库文件,并将知识库中的所有文档也转换为向量
- 检索:计算问题向量与每个文档向量的相似度,找出前三条最相似的向量
- 增强:用找到的三条最相似的文档,拼接出完整的提示词
- 生成:将提示词交给大模型,生成最终答案
import readline from 'readline';
import { ReadFile } from '../utils/ReadFile.js';
import { getEmbedding, initEmbedder } from './Embedding.js';
import { retrieve } from './Retrieve.js';
import { generatePrompt } from './Generate.js';
// 延迟函数,模拟处理过程
const delay = (ms) => new Promise(resolve => setTimeout(resolve, ms));
async function main() {
// 1. 初始化嵌入模型
console.log('\n[步骤 1/7] 初始化嵌入模型...');
await delay(500);
await initEmbedder();
await delay(300);
// 2. 用户输入问题
const rl = readline.createInterface({
input: process.stdin,
output: process.stdout
});
const question = await new Promise((resolve) => {
rl.question('[步骤 2/7] 请输入您的问题: ', (answer) => {
rl.close();
resolve(answer);
});
});
await delay(500);
// 3. 计算问题向量
console.log('[步骤 3/7] 将问题转换为向量...');
await delay(800);
const queryVector = await getEmbedding(question);
console.log(`✓ 向量维度: ${queryVector.length}`);
console.log(`✓ 向量值: [${queryVector.slice(0, 5).map(v => v.toFixed(3)).join(', ')}...]\n\n`);
await delay(500);
// 4. 加载知识库并构建向量数据库
console.log('[步骤 4/7] 构建向量数据库...');
await delay(500);
const documents = ReadFile();
console.log('');
// 构建向量数据库
const vectorDatabase = [];
const docVectors = [];
for (let i = 0; i < documents.length; i++) {
const doc = documents[i];
const vec = await getEmbedding(doc);
docVectors.push(vec);
// 添加到向量数据库
vectorDatabase.push({
doc: doc,
vec: vec.slice(0, 8).map(v => parseFloat(v.toFixed(3))) // 只保留前8维用于展示
});
await delay(300);
}
// 打印整个向量数据库
console.log('📊 向量数据库构建完成:\n');
vectorDatabase.forEach((item, index) => {
const vecStr = `[${item.vec.join(', ')}...]`;
console.log(`doc: ${item.doc} vec: ${vecStr}\n`);
});
console.log('');
await delay(500);
// 5. 语义检索
console.log('[步骤 5/7] 语义检索最相关的文档...');
await delay(800);
const topDocs = await retrieve(question, documents, docVectors, 3);
topDocs.forEach((doc, i) => {
console.log(` ${i + 1}. [相似度 ${(doc.score * 100).toFixed(1)}%] ${doc.text}`);
});
console.log('');
await delay(800);
// 6. 拼接提示词
console.log('\n[步骤 6/7] 生成提示词...');
await delay(600);
const prompt = generatePrompt(question, topDocs);
console.log('─'.repeat(30),'prompt', '─'.repeat(30));
console.log(prompt);
console.log('─'.repeat(66));
console.log('');
await delay(500);
// 7. 生成回答
console.log('[步骤 7/7] GPT模型回答中...');
await delay(800);
// 模拟大模型回答,这里直接返回相似度最高的那句话
const answer = topDocs[0].text;
const similarity = (topDocs[0].score * 100).toFixed(1);
console.log(`\n💡 最终回答:${answer},相似度:${similarity}%`);
}
main();
【控制台输出】

6. RAG的常见优化点
虽然上面的流程能跑通,但实际生产中有很多优化手段:
| 问题 | 优化方法 |
|---|---|
| 文档太长 | 合理分块(chunking),比如按段落、按500字切分 |
| 检索不准 | 改用多路召回(关键词+向量),或使用重排模型(reranker) |
| 提示词太乱 | 对检索结果做结构化处理,控制长度 |
| 答案无来源 | 在答案中标注引用文档编号 |
| 实时性要求高 | 缓存常见问题,使用更快的嵌入模型 |
7. 总结
RAG的本质,就是给大语言模型配一个外部知识库,让它不再依赖训练时的记忆,而是实时查阅资料后作答。现在市面上所有主流AI应用(如企业知识库、智能客服、AI搜索)背后几乎都有RAG的影子。
- 核心流程:检索 → 增强 → 生成
- 核心组件:嵌入模型 + 向量数据库 + LLM
- 核心价值:Token消耗减少、实时更新、可解释
RAG的架构深处,藏着比技术更深的生存智慧——检索、增强、生成,这何尝不是我们面对人生时的那套隐秘算法?
检索不是盲目翻书,而是灵魂在记忆碎片中的自我辨认:在万千回响中找到最贴近当下的那一页,知道该翻开哪一本,更知道该合上哪一本。增强不是堆砌,而是认知边界的温柔拓荒——把外来的智慧拼接进既有框架,不吞没、不僭越,只为新的理解留出恰好容身的缝隙。
而生成,是所有准备之后的克制:引用而不抄袭,借鉴而不失独立。我们穷尽一生检索前人的智慧、增强自己的认知,不过是为了在开口的那一刻,说出一句既带着世界的温度、又印着自己指纹的话。
AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。
更多推荐



所有评论(0)