简单学习 --> Rag
一、 RAG 的本质为大模型外接“动态内存”在计算机架构中CPU 的算力再强也受限于 L1/L2 缓存和内存的大小。LLM大语言模型同理它的权重矩阵模型本身相当于只读存储器ROM而它的上下文窗口Context Window相当于极其昂贵的运行内存RAM。RAG检索增强生成的核心思想是绝不修改 ROM不微调大模型而是通过外部系统实时将最相关的数据加载到 RAM 中供 LLM 进行即时计算与推理。例子:大模型LLM是一个智商高达 150 但“没背过你们公司业务手册”的学霸。 用户提问时如果直接让他裸考直接问 LLM他可能会胡编乱造幻觉。RAG 就是学霸的场外书童。书童飞速去图书馆向量数据库翻出相关的 3 页资料复印下来连同考卷一起递给学霸。学霸看着这 3 页资料总结出完美答案。RAG 工作流意图捕获拦截用户的查询请求。知识寻址借助向量引擎在庞大知识库中定位到最相关的“知识块”。上下文组装将找到的“知识块”拼接到系统提示词Prompt中。推理输出LLM 基于刚刚被注入的背景知识生成回复。二、 主流技术架构与选型在实际工程落地中架构选型主要考虑运维成本和掌控力的平衡。方案类型技术栈示例适用场景与优缺点全云服务 (主流)OpenAI API Pinecone/Zilliz 纯 Python / LangChain推荐。开发快无需关心底层扩容。缺点是数据出境或依赖第三方厂商。半云服务 (企业常用)LLM API LlamaIndex 私有部署向量数据库 (如 Milvus/Qdrant)平衡之选。模型用云端保证智商数据留在本地库保证隐私。全本地化 (研究向)本地部署 Llama 3 本地向量数据库 LangChain门槛高。适合对数据安全极度敏感或做底层研究的团队对硬件算力要求极高。为什么向量数据库推荐用云服务和传统 MySQL 一样一旦数据量变大向量数据库也需要面对分布式架构、主从同步、读写分离、高可用等问题。向量检索极耗内存和 CPU云服务能有效转嫁高昂的运维和机器成本。三、 向量数据库的三部曲向量数据库的本质可以概括为将万物映射为坐标Embedding用数学计算距离Similarity并修筑高速公路Indexing以实现海量秒查。1. 核心灵魂万物皆坐标 (Embeddings)计算机无法理解人类语言中的“相似”但能理解空间中坐标点的距离。Embedding 就是把文本压缩成一个固定维度的数组。代码解析文本转向量from langchain_community.embeddings import HuggingFaceBgeEmbeddings # 初始化 BGE 模型 (目前开源界语义理解极强的轻量级模型) model_name BAAI/bge-small-zh-v1.5 embeddings HuggingFaceBgeEmbeddings(model_namemodel_name) # 定义要处理的文本 text_a Java Spring Boot的AOP拦截器怎么写 text_b Python中如何使用装饰器实现切面编程 text_c 今天晚上的夜宵打算吃小龙虾。 # 将文本转化为高维向量 (执行 Embedding 过程) vec_a embeddings.embed_query(text_a) # 打印结果你会看到一个拥有多个浮点数的列表这就是它的GPS坐标 print(f文本A的向量维度: {len(vec_a)} 维) print(f截取前三维: {vec_a[:3]})2. 检索原理计算相似度 (Similarity Search)找到相关内容的本质是在高维空间中找寻距离最近的两个点。最常用的尺子是余弦相似度Cosine Similarity它关注向量夹角的大小另一把常用的尺子是点乘Dot Product。补充概念什么是点乘点乘是两个向量对应维度相乘后再相加的数学过程。公式为A⋅B∑i1naibi。物理意义它衡量了两个向量在相同方向上的“协同程度”。在向量库中的应用如果向量在存入前已经做过归一化长度都变为 1那么点乘的值就完全等于余弦相似度。计算点乘的硬件资源消耗通常低于计算夹角因此被广泛使用。代码解析手写点乘计算相似度from scipy.spatial import distance import numpy as np # 假设我们将刚刚生成的三个文本向量化为了 numpy 数组 # vec_a (Java AOP) 和 vec_b (Python 装饰器) 都在讲编程范式 # vec_c (吃小龙虾) 完全无关 # 计算余弦相似度 (1 - 余弦距离) # 值越接近 1表示极其相似越接近 0表示毫无关联 sim_ab 1 - distance.cosine(vec_a, vec_b) sim_ac 1 - distance.cosine(vec_a, vec_c) print(fJava编程 vs Python编程 的语义相似度: {sim_ab:.4f}) # 得分很高 print(fJava编程 vs 吃小龙虾 的语义相似度: {sim_ac:.4f}) # 得分极低3. 性能关键建立索引 (Indexing / ANN)全量对比计算暴力搜索太慢。现代向量库使用ANN近似最近邻算法其中最主流的是HNSW算法。它构建了一个多层的图结构类似于“先坐高铁到大城市再坐公交到具体街道”从而实现毫秒级检索。四、 维度、模型与兼容性模型兼容性铁律写入和查询必须使用同一个 Embedding 模型。不同模型提取特征的逻辑完全不同跨模型对比就像拿美元面值直接对比日元面值毫无意义。维度选择常见的维度有 384、768、1536 等。维度越高能表达的语义细节越丰富但存储和计算成本呈线性增加。目前通用 RAG 任务中768 到 1536 维是平衡性能与成本的最优解。五、 文本切片 (Chunking)操作系统的“内存分页”逻辑这是 RAG 系统工程落地中最容易翻车的环节。大模型的上下文窗口有限我们必须把知识库切分为标准的“块”Chunk再喂给它这类似于操作系统的内存分页Paging。场景 A长文档的智能切片 (递归切分)如果是整本书或长篇论文我们不能粗暴地按固定字数一刀切这会切断上下文的逻辑。业界主流做法是递归切分并保留重叠区Overlap。例子:怎么切战斧牛排你不能把一整块战斧牛排一口吞下Token 超限你得切块。 如果你闭着眼睛按重量乱砍可能会直接把骨头和肉的连接处剁碎把一句话从中间截断。 递归切分就是有技巧地沿着筋络切优先按段落切段落太大再按句子切。而**重叠区Overlap**就是保证每一块肉上都连着一点上一块的肉筋这样吃的时候LLM理解时才知道这两块肉原本是连在一起的。代码示例LangChain 递归字符切分器from langchain.text_splitter import RecursiveCharacterTextSplitter long_document 这里是长达十万字的技术文档原文... # 实例化高级文本切分器 splitter RecursiveCharacterTextSplitter( chunk_size500, # 每个块的最大容量限制 (牛排块大小) chunk_overlap50, # 设置 50 个字符的冗余重叠区 (连带的肉筋) separators[\n\n, \n, 。, , ] # 切分优先级优先保证段落完整 ) chunks splitter.create_documents([long_document])场景 B离散短文本 (FAQ) 的精准映射针对类似[华为手机好不好, 苹果手机好不好]这种已经具有高度独立语义的短句。工程铁律绝不合并一定要确保“一个语义单元 一个 Chunk”。例子:不要把 MM 豆融化成巧克力砖FAQ 问答对本身就是一颗颗完整的 MM 豆有着独立的颜色和味道。如果你因为觉得单颗太小非要把 100 颗不同的 MM 豆加热融化成一个 500g 的巧克力大砖块大 Chunk等你想吃红色的豆子时拿出来的全都是一堆大杂烩这就是严重的注意力污染Noise。代码示例针对 FAQ 数据的精准切分from langchain.text_splitter import CharacterTextSplitter faq_text 华为手机好不好答信号好拍照强。 苹果手机好不好答生态好录像强。 今天下雨吗答不下。 # 针对离散数据的强硬切分策略 faq_splitter CharacterTextSplitter( separator\n, # 仅以换行符作为唯一物理边界 chunk_size10, # 设积极小值逼迫切分器在每一个换行符处都必须切断 chunk_overlap0 # 独立数据绝对不允许重叠污染 ) faq_chunks faq_splitter.create_documents([faq_text.strip()]) # 输出结果将是绝对干净的三条独立记录彼此互不干扰。六、 LlamaIndex 的底层逻辑List Index Vector Index在框架层面针对不同的数据量索引方式也有区别索引类型原理是否需要 Embedding 模型适用场景Vector Index计算所有文本的向量坐标通过空间距离进行检索只提取 Top-K 给 LLM。是海量文档、长文本、常规 RAG 场景。List Index直接将所有文本按顺序拼接成一个列表。查询时把整个列表内容直接塞进 Prompt 交给 LLM 处理。否数据量极小总 Token 小于大模型上下文窗口上限、或者要求严格按顺序总结的场景。总结来说RAG 系统的上限由检索的精准度Embedding 质量 Chunking 策略决定而下限由LLM 自身的逻辑推理能力决定。您的这套笔记已经非常清晰地覆盖了这一闭环。