引言:RAG——chunking+向量数据库+大语言模型。面对大模型上下文有限的情况下所做的妥协
RAG RAG(Retrieval-Augmented Generation) 是一种结合了信息检索 和文本生成 的AI技术。
它通过在生成回答之前先检索相关的外部知识,来提高大语言模型回答的准确性和时效性。
简单来说RAG是一个向量数据库+嵌入模型
RAG本质要解决的问题
有时候我们的问题是有一部分文档做支撑的,比如公司的某SOP,当你的问题是关于这些时,那么大模型没有此上文依赖,就会一本正经的胡说八道。
RAG就是为了解决这个问题而提出的,可以把文档中相关于我们问题的一部分抽取出来,询问大模型,然后大模型再给出他的回答。
RAG其实是在面对大模型上下文有限的情况下所做的妥协
RAG的核心组件 RAG系统主要由两个核心组件构成:
R——检索器,从大量文档或知识库中找到与用户问题最相关的信息,一般使用向量数据库
G——生成器,基于检索到的相关信息生成最终回答,依赖LLM(chatgpt、deepseek)
RAG系统架构全貌 很多人以为RAG就是”向量数据库+模型”,这个理解基本正确,但实际上RAG是一个更复杂的系统。
RAG系统的典型工作流程如下:
1 用户问题 → 文档预处理 → 向量化 → 相似度检索 → 上下文增强 → 生成回答
文档预处理 :将文档切分成小块(chunking ),清理和格式化文本,去除噪声内容,转换为向量
chunking这一步非常关键,决定了我们建立向量的质量 !
切割的方式有很多种,比如按字数、按句子等
但每种方式都有其缺点,比如按句子划分“我是李白。我爱作诗“,在这种情况下,用户提问李白喜欢做什么,与“我爱作诗”可能就会差很远。
向量化存储 :使用嵌入模型(如OpenAI Embeddings、Sentence-BERT)将文档块转换为向量,然后存储到向量数据库中
嵌入:将非结构化数据转换成计算机可以理解的数值数据(向量)的过程
切块后的向量维度一般是固定的,比如text-embedding-3-small转换后的向量维度一般在1000维
用户查询处理 :将用户问题也转换为向量表示,在向量空间中计算相似度
计算向量之间的距离或角度来判断向量的偏差,进而找到TopK,得到最准确的答案
一般在系统内会预设提示词(System promote ),比如:你是一个程序员,你精通xxx,请你回答问题
检索相关文档 :找出最相关的Top-K个文档块,通常K=3到10之间
上下文构建 :将检索到的文档内容与用户问题组合,形成完整的prompt
生成最终回答 :大语言模型基于增强后的上下文生成回答、确保回答基于检索到的事实信息
完整架构图 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 ┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐ │ 文档输入 │ │ 用户查询 │ │ 最终回答 │ │ (PDF/Word/ │ │ "RAG是什么?" │ │ "RAG是一种..." │ │ Web/...) │ │ │ │ │ └─────────┬───────┘ └─────────┬───────┘ └─────────┬───────┘ │ │ ▲ ▼ ▼ │ ┌─────────────────┐ ┌─────────────────┐ │ │ 文档处理模块 │ │ 查询处理模块 │ │ │ • 文本清理 │ │ • 查询理解 │ │ │ • 文档分块 │ │ • 查询扩展 │ │ │ • 元数据提取 │ │ • 意图识别 │ │ └─────────┬───────┘ └─────────┬───────┘ │ │ │ │ ▼ ▼ │ ┌─────────────────┐ ┌─────────────────┐ │ │ 嵌入模型 │ │ 嵌入模型 │ │ │ • 文档向量化 │ │ • 查询向量化 │ │ │ • 批量处理 │ │ • 实时处理 │ │ └─────────┬───────┘ └─────────┬───────┘ │ │ │ │ ▼ ▼ │ ┌─────────────────┐ ┌─────────────────┐ │ │ 向量数据库 │◄───┤ 检索引擎 │ │ │ • 向量存储 │ │ • 相似度搜索 │ │ │ • 索引管理 │ │ • 结果排序 │ │ │ • 元数据存储 │ │ • 结果过滤 │ │ └─────────────────┘ └─────────┬───────┘ │ │ │ ▼ │ ┌─────────────────┐ │ │ 上下文构建 │ │ │ • 文档整合 │ │ │ • Prompt工程 │ │ │ • 长度控制 │ │ └─────────┬───────┘ │ │ │ ▼ │ ┌─────────────────┐ │ │ 生成模型 │──────────────┘ │ • 文本生成 │ │ • 答案合成 │ │ • 质量控制 │ └─────────────────┘
为什么不只是”向量数据库+模型”? 简化理解(适合学习):
完整实现(适合生产):
1 2 RAG = 文档处理 + 嵌入模型 + 向量数据库 + 检索引擎 + 上下文管理 + 生成模型 + 质量控制 + 系统编排
文档处理pipeline :不同格式文档的解析、文本清理和标准化、智能分块策略
检索优化 :查询理解和扩展、多轮检索策略、结果重排序(Re-ranking)
上下文管理 :长度控制(避免超出模型限制)、信息去重和整合、Prompt模板管理
质量控制 :回答相关性检测、幻觉检测和过滤、置信度评估
系统编排 :错误处理和恢复、性能监控、缓存机制
各组件的作用占比
组件
重要性
复杂度
对效果的影响
向量数据库
⭐⭐⭐⭐⭐
⭐⭐⭐
40%
生成模型
⭐⭐⭐⭐⭐
⭐⭐
30%
文档处理
⭐⭐⭐⭐
⭐⭐⭐⭐
15%
检索优化
⭐⭐⭐
⭐⭐⭐⭐
10%
上下文管理
⭐⭐⭐
⭐⭐⭐
5%
关键洞察:
向量数据库和生成模型确实是核心,占70%的效果
但剩余30%的优化往往决定了系统的实用性
生产级RAG系统需要考虑所有组件的协同工作
开源框架
LangChain
最流行的RAG开发框架
丰富的文档加载器和向量存储支持
易于集成各种LLM
LlamaIndex
专注于数据连接和索引
强大的查询引擎
支持复杂的文档结构
Haystack
Deepset开发的开源框架
企业级解决方案
强大的pipeline管理
向量数据库 什么是向量数据库? 向量数据库(Vector Database) 是一种专门用于存储、索引和查询高维向量数据的数据库系统。
在RAG和AI应用中,它是实现语义搜索的核心技术。
核心概念:向量、嵌入、相似度计算 1. 向量(Vector) :向量是一组数字组成的数组,代表数据的数学表示
示例:[0.1, 0.8, -0.3, 0.5, ...](通常有几百到几千个维度)
可以将文本、图像等非结构化数据转换为计算机可以理解的数值形式(非结构化数据转为可理解的数值形式)
2. 嵌入(Embedding) :使用AI模型将文本转换为向量的过程
语义相似的文本会产生相似的向量
1 2 3 "RAG是什么?" → [0.1, 0.8, -0.3, 0.5, ...] "什么是RAG?" → [0.1, 0.7, -0.2, 0.6, ...] (相似向量) "今天天气好" → [0.9, 0.1, 0.8, -0.4, ...] (不同向量)
3. 相似度计算
相似度计算是向量数据库的核心,决定了能否准确找到相关文档。以下是三种主要的相似度计算方法:
余弦相似度(Cosine Similarity) - 最常用的方法
原理 :计算两个向量之间的夹角余弦值
公式 :cos(θ) = (A·B) / (|A| × |B|)
取值范围 :-1 到 1,值越接近1越相似
优势 :不受向量长度影响,适合文本相似度
具体例子:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 vector_A = [1 , 2 , 3 ] vector_B = [1 , 2 , 2 ] vector_C = [4 , 0 , 1 ] import mathdef cosine_similarity (v1, v2 ): dot_product = sum (a*b for a,b in zip (v1,v2)) norm_a = math.sqrt(sum (a*a for a in v1)) norm_b = math.sqrt(sum (a*a for a in v2)) return dot_product / (norm_a * norm_b) sim_AB = cosine_similarity(vector_A, vector_B) sim_AC = cosine_similarity(vector_A, vector_C)
欧几里得距离(Euclidean Distance)
原理 :计算两点间的直线距离
公式 :d = √[(x₁-x₂)² + (y₁-y₂)² + ... + (n₁-n₂)²]
取值范围 :0 到 ∞,值越小越相似
特点 :受向量长度和维度影响较大
具体例子:
1 2 3 4 5 6 7 8 9 10 def euclidean_distance (v1, v2 ): return math.sqrt(sum ((a-b)**2 for a,b in zip (v1,v2))) dist_AB = euclidean_distance(vector_A, vector_B) dist_AC = euclidean_distance(vector_A, vector_C) sim_AB = 1 / (1 + dist_AB) sim_AC = 1 / (1 + dist_AC)
点积(Dot Product)
原理 :向量对应元素相乘后求和
公式 :A·B = a₁×b₁ + a₂×b₂ + ... + aₙ×bₙ
特点 :计算最快,但受向量长度影响
适用 :向量已归一化的场景
具体例子:
1 2 3 4 5 6 7 8 9 10 def dot_product (v1, v2 ): return sum (a*b for a,b in zip (v1,v2)) norm_A = [0.27 , 0.53 , 0.80 ] norm_B = [0.35 , 0.70 , 0.60 ] norm_C = [0.95 , 0.00 , 0.24 ] dot_AB = dot_product(norm_A, norm_B) dot_AC = dot_product(norm_A, norm_C)
实际应用中的选择:
方法
优势
劣势
适用场景
余弦相似度
不受长度影响,语义准确
计算稍复杂
文本搜索、推荐系统
欧几里得距离
直观易懂,几何意义明确
受维度影响大
图像识别、聚类分析
点积
计算最快,内存友好
需要归一化预处理
大规模实时搜索
RAG系统中的选择 :
推荐 :余弦相似度(90%的RAG系统都使用)
原因 :文本向量通常关注方向而非长度,余弦相似度能更好地捕捉语义相似性
优化 :可以预先归一化向量,然后使用点积代替余弦相似度计算
PS:向量归一化(Vector Normalization)
定义 :将向量转换为单位向量(长度为1)的过程,保持方向不变
目的 :消除向量长度差异,让相似度计算更准确
公式 :v_norm = v / |v|,其中 |v| = √(v₁² + v₂² + ... + vₙ²)
归一化示例:
1 2 3 4 5 6 7 8 9 10 11 12 vector = [3 , 4 , 0 ] length = √(3 ² + 4 ² + 0 ²) = √25 = 5 normalized = [3 /5 , 4 /5 , 0 /5 ] = [0.6 , 0.8 , 0.0 ] text_vector = [1 , 2 , 3 , 4 ] length = √(1 ² + 2 ² + 3 ² + 4 ²) = √30 = 5.477 normalized = [0.183 , 0.365 , 0.548 , 0.730 ]
归一化的优势:
公平比较 :不同长度的文本产生的向量可以公平比较
计算简化 :归一化后,余弦相似度 = 点积,计算更快
数值稳定 :避免因向量长度差异导致的数值不稳定
语义专注 :突出向量方向(语义),忽略大小(文本长度)
归一化对相似度计算的影响:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 short_text = [1 , 1 , 1 ] long_text = [2 , 2 , 2 ] dot_product = 1 *2 + 1 *2 + 1 *2 = 6 short_norm = [0.577 , 0.577 , 0.577 ] long_norm = [0.577 , 0.577 , 0.577 ] normalized_dot = 0.577 *0.577 + 0.577 *0.577 + 0.577 *0.577 = 1.0
向量数据库工作原理 存储阶段:
1 文档 → 分块 → 嵌入模型 → 向量 → 向量数据库
查询阶段:
1 用户问题 → 嵌入模型 → 查询向量 → 相似度搜索 → 相关文档
为什么需要向量数据库? 1. 语义搜索能力
传统搜索:基于关键词匹配,而向量搜索基于语义理解
示例:查询”如何做饭?”能找到”烹饪方法”、”cooking tips”等相关内容
2. 多语言支持
理解同义词和概念
支持跨语言查询
处理语言变体和方言
3. 高效检索
专门的索引结构(HNSW、IVF等)
快速的相似度计算
支持大规模数据检索
性能考虑 1. 向量维度
更高维度:更精确,但存储和计算开销大
常见维度:384、768、1536(取决于嵌入模型)
需要在精度和性能间平衡
2. 索引类型
HNSW :高精度,适合查询密集型应用
IVF :适合大规模数据,支持近似搜索
LSH :局部敏感哈希,适合快速近似搜索
3. 存储优化
量化 :减少存储空间,牺牲少量精度
压缩 :平衡精度和性能
分片 :支持分布式存储和查询
市场主流向量数据库对比 🏆 市场份额排名(2024年)
排名
产品
市场份额
类型
主要优势
🥇
Pinecone
~35%
云托管
易用性、性能、企业功能
🥈
Chroma
~25%
开源
轻量级、Python友好
🥉
Weaviate
~15%
开源+云
功能丰富、多模态
4️⃣
Qdrant
~12%
开源+云
高性能、Rust编写
5️⃣
Milvus
~8%
开源+云
企业级、大规模
6️⃣
其他
~5%
各种
FAISS、OpenSearch等
🥇 最受欢迎:Pinecone
✅ 市场占有率最高,生态最成熟;托管服务,零运维成本;性能优秀,延迟低;企业级功能完善
❌ 成本较高,按使用量付费;供应商锁定风险
🥈 开源首选:Chroma
✅ 开源社区最活跃;极易上手,5分钟可部署;本地开发友好
❌ 功能相对简单;不适合大规模生产
🤔 特殊提及:Neo4j不是传统向量数据库 ,而是图数据库,但:
Neo4j 5.0+ 新增向量索引功能
主要用于图+向量混合查询
适合知识图谱+RAG结合的场景
如果只做向量搜索,不推荐使用
向量数据库演示代码 为了更好地理解向量数据库的工作原理,我们提供了一个简化的演示程序:
核心方法:嵌入 + 相似度计算
1 2 3 4 5 6 7 8 9 10 11 12 13 def simple_hash_embedding (text, dimension=5 ): """简单的哈希嵌入(仅用于演示概念)""" return [hash (text + str (i)) % 100 / 100.0 for i in range (dimension)] def cosine_similarity (v1, v2 ): """计算余弦相似度""" dot = sum (a*b for a,b in zip (v1,v2)) norm1 = math.sqrt(sum (a*a for a in v1)) norm2 = math.sqrt(sum (a*a for a in v2)) if norm1 == 0 or norm2 == 0 : return 0 return dot / (norm1 * norm2)
完整案例
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 def vector_database_demo (): """向量数据库工作原理演示""" print ("🔍 向量数据库概念演示" ) print ("=" * 40 ) documents = [ "RAG是什么?RAG是一种AI技术" , "向量数据库用于存储向量数据" , "Python是一种编程语言" , "机器学习需要大量数据" ] print ("📚 步骤1:文档向量化" ) doc_vectors = [] for i, doc in enumerate (documents): vector = simple_hash_embedding(doc) doc_vectors.append(vector) print (f"文档{i+1 } : {doc} " ) print (f" 向量: {[round (v, 3 ) for v in vector]} " ) print ("\n🔍 步骤2:查询处理" ) queries = ["什么是RAG?" , "数据库" , "编程" ] for query in queries: print (f"\n查询: '{query} '" ) query_vector = simple_hash_embedding(query) print (f"查询向量: {[round (v, 3 ) for v in query_vector]} " ) similarities = [] for i, doc_vector in enumerate (doc_vectors): sim = cosine_similarity(query_vector, doc_vector) similarities.append((sim, i, documents[i])) similarities.sort(key=lambda x: x[0 ], reverse=True ) print ("📊 相似度排序结果:" ) for sim, idx, doc in similarities: print (f" 文档{idx+1 } : {sim:.3 f} - {doc} " ) print (f"🎯 最相关文档: 文档{similarities[0 ][1 ]+1 } " ) if __name__ == "__main__" : vector_database_demo()
运行示例输出:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 🔍 向量数据库概念演示 ======================================== 📚 步骤1:文档向量化 文档1: RAG是什么?RAG是一种AI技术 向量: [0.68, 0.8, 0.4, 0.08, 0.72] 文档2: 向量数据库用于存储向量数据 向量: [0.9, 0.71, 0.2, 0.59, 0.13] 🔍 步骤2:查询处理 查询: '什么是RAG?' 查询向量: [0.34, 0.95, 0.9, 0.65, 0.74] 📊 相似度排序结果: 文档1: 0.866 - RAG是什么?RAG是一种AI技术 文档2: 0.748 - 向量数据库用于存储向量数据 🎯 最相关文档: 文档1
这个演示展示了:
文档向量化 :将文本转换为数值向量
查询向量化 :用户问题也转换为向量
相似度计算 :通过数学方法找到最相关的文档
结果排序 :按相似度高低排列搜索结果
虽然这是一个简化的示例,但它准确地反映了向量数据库在RAG系统中的核心工作原理。
大语言模型选择 RAG系统中的生成模型(LLM)负责基于检索到的上下文生成最终回答。不同模型有各自的特点和适用场景。
中文用DS,英文用GPT
模型
成本
中文能力
上下文长度
RAG适配度
推荐指数
DeepSeek-V3
⭐⭐⭐⭐⭐
⭐⭐⭐⭐⭐
64K
⭐⭐⭐⭐⭐
⭐⭐⭐⭐⭐
GPT-4o
⭐⭐
⭐⭐⭐⭐
128K
⭐⭐⭐⭐⭐
⭐⭐⭐⭐
Claude-3.5
⭐⭐⭐
⭐⭐⭐⭐
200K
⭐⭐⭐⭐⭐
⭐⭐⭐⭐
GPT-3.5
⭐⭐⭐⭐
⭐⭐⭐
16K
⭐⭐⭐⭐
⭐⭐⭐
本地模型
⭐⭐⭐⭐⭐
⭐⭐⭐
变化
⭐⭐⭐
⭐⭐⭐
LangChain框架深度解析 什么是LangChain? LangChain 是目前最流行的大语言模型应用开发框架 ,由Harrison Chase在2022年创建。它的核心理念是**”链式组合”**,将不同的组件(如模型、数据源、工具等)串联起来,构建复杂的AI应用。
LangChain架构体系 1 2 3 4 5 6 7 8 9 用户查询 → 🔗 RetrievalQA Chain ↓ 📄 DirectoryLoader → ✂️ RecursiveCharacterTextSplitter ↓ 🧮 Embeddings Model → 🗄️ Vector Store (Chroma) ↓ 🔍 Similarity Retriever → 📝 Custom Prompt Template ↓ 🤖 LLM Model (DeepSeek) → 💬 Structured Response
LangChain关键组件详解 1. 📄 Document Loaders(文档加载器) 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 from langchain_community.document_loaders import ( DirectoryLoader, PDFLoader, CSVLoader, WebBaseLoader, GitHubIssuesLoader ) loader = DirectoryLoader( "documents/" , glob="**/*.txt" , loader_cls=TextLoader, show_progress=True )
2. ✂️ Text Splitters(文本分割器) 1 2 3 4 5 6 7 8 9 10 11 12 from langchain.text_splitter import ( RecursiveCharacterTextSplitter, TokenTextSplitter, MarkdownHeaderTextSplitter, CodeTextSplitter ) text_splitter = RecursiveCharacterTextSplitter( chunk_size=1000 , chunk_overlap=200 , separators=["\n\n" , "\n" , "。" , " " ] )
3. 🗄️ Vector Stores(向量存储) 1 2 3 4 5 6 7 8 9 10 11 12 13 from langchain_community.vectorstores import ( Chroma, Pinecone, FAISS, Weaviate, Qdrant ) vectorstore = Chroma.from_documents( documents=splits, embedding=embeddings, persist_directory="./chroma_db" )
4. 🔗 Chains(链) 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 from langchain.chains import ( RetrievalQA, ConversationalRetrievalChain, LLMChain, SequentialChain ) qa_chain = RetrievalQA.from_chain_type( llm=llm, chain_type="stuff" , retriever=retriever )
5. 🤖 Agents(智能体) 1 2 3 4 5 6 7 8 9 10 11 12 from langchain.agents import ( AgentExecutor, create_react_agent, create_tool_calling_agent ) agent = create_react_agent( llm=llm, tools=[search_tool, calculator_tool], prompt=agent_prompt )