ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

RAG知识梳理(1)

RAG知识梳理(1) 作者没有四次元口袋的蓝胖日期2026-09-27标签RAG, 文档切分, Embedding, AI应用开发RAG知识梳理(1RAGRetrieval-Augmented Generation是当前 AI 应用开发中最热门的技术之一。它通过先检索、再生成的方式让大模型能够基于外部知识库回答问题有效解决了模型知识过时和幻觉问题。本系列分为上下两篇从零讲解 RAG 的核心技术环节。上篇聚焦两个基础模块——文档切分和Embedding向量检索它们是 RAG 的地基直接决定了检索的精度和最终回答质量。核心掌握文档切分策略chunk_size/chunk_overlap/separators、Embedding原理与余弦相似度、常用模型选择。一、文档切分TextSplitter1.1 为什么要切分大模型的上下文窗口是有限的即使GPT-4有128K也不是无限的而且把整个文档塞进Prompt会导致检索不精确信息太多模型抓不住重点成本爆炸Token数量直接决定API调用费用效率低下每次问答都处理全部文档完全没必要所以正确的做法是把文档切成小块每次只检索最相关的几个小块送给模型。1.2 核心参数切分有两个关键参数理解透了基本就掌握了chunk_size每个块的最大字符数/Token数 chunk_overlap相邻块之间的重叠字符数 示例chunk_size10, overlap2 原文ABCDEFGHIGKLMNOP 块1ABCDEFGHIJ ← 10个字符 块2HIJKLMNO ← 从第9个字符开始overlap2 块3KLMNOP ← 继续滑动overlap 的作用防止关键信息被切断。比如一句话刚好跨在两个块的边界overlap 可以保证两个块都包含这句话的完整内容。1.3 RecursiveCharacterTextSplitter这是最常用的切分器它按照递归优先级尝试多种分隔符fromlangchain.text_splitterimportRecursiveCharacterTextSplitter# 默认按这个顺序尝试切分段落→行→句子→字符text_splitterRecursiveCharacterTextSplitter(chunk_size500,# 每块最大500个字符chunk_overlap50,# 相邻块重叠50个字符length_functionlen,# 长度计算方式默认len也可以用tiktoken按token计算separators[\n\n,\n,。, ,]# 分隔符优先级)# 示例文档textSpring Boot 是由 Pivotal 团队提供的全新框架其设计目的是简化新 Spring 应用的初始搭建和开发过程。 该框架使用了特定的方式来进行配置从而使开发人员不再需要定义样板化的配置文件。 Spring Boot 的核心特性包括自动配置、起步依赖、内嵌服务器、Actuator监控等。 通过这些特性Spring Boot 可以以最小的配置快速启动一个 web 应用。 Spring Cloud 是建立在 Spring Boot 基础之上的一套微服务架构解决方案。 它为分布式系统中的配置管理、服务发现、负载均衡、熔断器等提供了简单易用的编程模型。chunkstext_splitter.split_text(text)fori,chunkinenumerate(chunks):print(f\n--- 块{i1}---)print(chunk)# 处理代码文件时可以指定适合的分隔符python_splitterRecursiveCharacterTextSplitter.from_language(languagepython,# 自动使用适合Python的分隔符def、class、import等chunk_size1000,chunk_overlap100)# 也可以按Token切分更精确fromlangchain.text_splitterimportRecursiveCharacterTextSplitter token_splitterRecursiveCharacterTextSplitter.from_tiktoken_encoder(chunk_size200,# 200个Tokenchunk_overlap20,encoding_namecl100k_base# GPT-4/GPT-3.5使用的编码)1.4 其他常用Splitter# CharacterTextSplitter最简单的按字符切分不递归fromlangchain.text_splitterimportCharacterTextSplitter simple_splitterCharacterTextSplitter(separator\n\n,chunk_size500,chunk_overlap50)# MarkdownHeaderTextSplitter按Markdown标题层级切分fromlangchain.text_splitterimportMarkdownHeaderTextSplitter md_splitterMarkdownHeaderTextSplitter(headers_to_split_on[(#,标题1),(##,标题2),(###,标题3),])# 适合处理Markdown文档能保留标题层级信息1.5 关键注意点chunk_size 的选择太小会丢失上下文语义一句话可能被截断太大会引入噪声一个块包含多个主题。通常 200~1000 之间需要根据实际文档调优。overlap 不要太大一般取 chunk_size 的 10%~20%。overlap 太大导致存储和计算浪费。中文文档注意中文没有天然的空格分词分隔符可以加上中文标点如。、、。二、向量检索Embedding原理2.1 什么是EmbeddingEmbedding嵌入是把文本映射到一个高维向量空间的过程。相似含义的文本在向量空间中的距离也更近。文本 → Embedding模型 → 高维向量如1536维的浮点数数组 Java多线程编程 → [0.023, -0.041, 0.087, ..., 0.015] 1536个数字 Python并发编程 → [0.019, -0.038, 0.091, ..., 0.012] 与上面相近 今天天气不错 → [-0.056, 0.072, -0.033, ..., 0.044] 与上面差距大2.2 相似度计算有了向量表示后就可以用数学方法计算文本之间的相似度importnumpyasnp# 两个文本的向量表示简化为3维示意vec_anp.array([0.023,-0.041,0.087])# Java多线程vec_bnp.array([0.019,-0.038,0.091])# Python并发vec_cnp.array([-0.056,0.072,-0.033])# 天气不错# 余弦相似度最常用cos(θ) A·B / (|A|×|B|)defcosine_similarity(a,b):returnnp.dot(a,b)/(np.linalg.norm(a)*np.linalg.norm(b))print(fA vs B技术类:{cosine_similarity(vec_a,vec_b):.4f})# 约0.99很相似print(fA vs C无关:{cosine_similarity(vec_a,vec_c):.4f})# 约-0.82不相似核心思想RAG 检索的本质就是把用户问题转成向量然后在向量数据库中找到与问题向量最相似的文档块。2.3 在LangChain中使用Embeddingfromlangchain.embeddingsimportOpenAIEmbeddings# 创建Embedding模型embeddingsOpenAIEmbeddings(modeltext-embedding-3-small)# 单个文本转向量vectorembeddings.embed_query(什么是Spring的IoC)print(f向量维度:{len(vector)})# 1536print(f前5个值:{vector[:5]})# [0.023, -0.041, ...]# 多个文本批量转向量vectorsembeddings.embed_documents([Spring IoC是控制反转由容器管理对象的创建和依赖,Spring AOP是面向切面编程用于解耦横切关注点,Spring Boot简化了Spring应用的配置和部署,])print(f批量生成:{len(vectors)}个向量每个维度{len(vectors[0])})# 其他可选的Embedding模型# OpenAIfromlangchain.embeddingsimportOpenAIEmbeddings openai_embOpenAIEmbeddings(modeltext-embedding-3-small)# 本地模型不依赖API免费fromlangchain.embeddingsimportHuggingFaceEmbeddings hf_embHuggingFaceEmbeddings(model_nameBAAI/bge-small-zh-v1.5)# bge系列是中文效果很好的开源Embedding模型# Coherefromlangchain.embeddingsimportCohereEmbeddings cohere_embCohereEmbeddings(modelembed-multilingual-v3.0)2.4 面试要点Embedding 是 RAG 的核心环节。面试时需要能说清楚本质文本→高维向量语义相近则向量相近检索原理问题转成向量和文档向量算余弦相似度常用模型OpenAI text-embedding-3、开源的 BGE 系列维度通常 768~3072 维维度越高表达力越强但计算成本也越高️ 思维导图速览文档切分与Embedding ├── 文档切分 │ ├── 为什么切分控制Token、精确检索、降低成本 │ ├── 核心参数 │ │ ├── chunk_size每块最大字符数通常200~1000 │ │ └── chunk_overlap相邻块重叠通常取chunk_size的10%~20% │ ├── RecursiveCharacterTextSplitter最常用 │ │ ├── 递归尝试段落→行→句子→字符 │ │ ├── 支持按语言切分Python/Java等 │ │ └── 支持按Token切分tiktoken编码 │ └── 其他Splitter │ ├── CharacterTextSplitter简单按字符切分 │ └── MarkdownHeaderTextSplitter按标题层级切分 │ ├── Embedding向量检索 │ ├── 本质文本 → 高维向量语义相近 → 向量相近 │ ├── 相似度计算 │ │ ├── 余弦相似度最常用cos(θ) A·B / (|A|×|B|) │ │ └── 值域 [-1, 1]越接近1越相似 │ ├── LangChain使用 │ │ ├── embed_query()单文本转向量 │ │ └── embed_documents()批量转向量 │ └── 常用模型 │ ├── OpenAI text-embedding-3-small商用首选 │ ├── BAAI/bge-small-zh-v1.5中文开源首选 │ └── Cohere embed-multilingual-v3.0多语言 │ └── 面试要点 ├── 切分策略的选择依据 ├── Embedding的本质与检索原理 └── 常用模型及其特点 写在最后学习建议切分是 RAG 的第一道关卡切分质量直接决定了后续检索的上限。建议从RecursiveCharacterTextSplitter入手chunk_size 先设 500overlap 设 50然后根据实际效果调优。Embedding 理解本质即可不需要推导数学公式但要清楚文本→向量→算相似度这个流程以及为什么语义相近的文本向量也相近。中文场景推荐 BGE如果不想每次都调 OpenAI API可以用 BGE 系列的开源模型中文效果很好本地部署零成本。和下一篇配合看下篇会讲解向量数据库FAISS/Chroma和完整的文档问答流程两篇合在一起就是 RAG 基础的全部知识。面试高频问题速答QRAG 中文档为什么要切分chunk_size 怎么选因为大模型上下文有限且全量文档送入会引入噪声、增加成本。切分后每次只检索最相关的几个块送给模型。chunk_size 通常在 200~1000 字符之间太小会破坏语义完整性太大会引入无关信息。chunk_overlap 一般取 chunk_size 的 10%~20%防止关键信息被边界截断。QEmbedding 是什么RAG 中起什么作用Embedding 是把文本映射为高维向量的过程语义相近的文本在向量空间中距离也近。在 RAG 中Embedding 负责两个关键环节离线索引时把文档块转为向量存入向量库在线问答时把用户问题转为向量用于相似度检索。常用模型有 OpenAI text-embedding-3 和开源的 BGE 系列。QRecursiveCharacterTextSplitter 为什么最常用因为它按递归优先级尝试多种分隔符段落→行→句子→字符尽量在语义完整的边界处切分避免把一句话拦腰截断。同时还支持按编程语言语法结构切分、按 Token 数切分等高级用法覆盖面最广。Q余弦相似度是什么为什么用余弦而不是欧氏距离余弦相似度衡量两个向量夹角的余弦值范围 [-1, 1]只关注方向不关注长度。在文本 Embedding 中向量的模长往往没有语义意义不同长度的文本模长不同所以用余弦比欧氏距离更合理。
返回列表