RAG 从入门到实战:文本切分、向量检索、多模态,一篇文章打通全流程

📅 2026/7/5 1:46:48
RAG 从入门到实战:文本切分、向量检索、多模态,一篇文章打通全流程
导语如果你正在搭建一个知识库问答系统、客服机器人或者让大模型「学会」你的内部文档那 RAGRetrieval-Augmented Generation是你绕不开的技术栈。过去一年里RAG 从一个研究概念变成了落地标配——2025 年的行业调研数据显示超过 70% 的 LLM 应用在生产环境中采用了 RAG 架构。这篇文章从最基础的概念讲起一路走到多模态 RAG 和线上部署包含可以直接运行的代码。这篇文章适合谁看有 Python 基础、了解基本的大模型 API 调用想从零搭建一个自己的 RAG 系统。读完这篇文章你能做到的理解 RAG 的完整工作流程——从用户提问到答案返回每一步在做什么、为什么这么做掌握 5 个核心组件的选型逻辑——文本切分用多细、向量模型用哪个、数据库选什么、检索怎么召回、大模型选哪个拿到一份可以直接运行的代码——基于 LangChain Chroma DeepSeek/Qwen覆盖文档加载、切分、向量化、检索、生成的完整链路了解多模态 RAG 的落地方式——图片搜索、图文联合检索、视觉问答等进阶玩法看完这篇文章你仍然不会熟悉的分布式 RAG 系统调优、大规模千万级向量集群运维、RAG 评估框架的具体搭建。这些话题每个都可以单独写一篇本文先把单机可跑的全流程打通。RAG 解决了什么问题大模型有两个天生的短板一是知识截止于训练数据的时间点二是遇到不知道的事情会「编造」答案幻觉。RAG 的思路很直接——不给模型凭空发挥的机会。每次用户提问时先从外部知识库检索相关信息把这些信息作为上下文注入到提示词里再让模型基于这些材料回答。一个经典的比喻RAG 就像给大模型开卷考试。模型不需要把所有知识背下来只需要知道去哪里找答案、怎么组织找到的材料。过去三年 RAG 的演进其实反映了整个行业对 LLM 应用的理解变化2023 — 朴素 RAG文档切碎、向量化、相似度检索、拼进 Prompt。能用但很容易搜到不相关的内容答案质量随缘。2024 — 模块化 RAG加了查询改写、重排序、Hybrid 检索、多轮对话管理。每一步都可以独立优化效果稳定很多。2025 — 多模态 Agentic RAG支持图片、表格、代码等非文本数据的检索和生成。RAG 不再只是「文本搜文本」而是多模态信息的一个路由层。RAG 核心流程拆解整个 RAG 流程可以拆成两条线索引线离线文档 → 切分 Chunks → 向量化 Embedding → 存入向量数据库。这条线只在首次搭建或文档更新时跑一次。查询线在线用户提问 → 向量检索 → 召回结果重排序 → 组装 Prompt → 大模型生成回答。这条线每次用户提问都会走一遍。两条线分开看每条线上的组件都可以独立选型和优化。下面从索引线开始逐个拆解。文本切分——RAG 的第一道关卡文本怎么切是 RAG 系统里最容易忽视、但影响最大的环节。切得太碎语义不完整切得太粗一条 Chunk 包含太多无关信息检索噪音大。实践中常用的几种切分策略固定长度切分按字符或 Token 数硬切比如每 512 个字符一段。简单直接但会在句子中间断开破坏语义完整性。通常设 10%-15% 的重叠Overlap来缓解断句问题。递归字符切分按\n\n→\n→ 句号 → 分号的优先级逐级回退。这是 LangChain 默认的切分方式能在大部分场景下保持段落和句子的完整性。推荐 Chunk Size 设为 500-1000Overlap 100-200。语义切分通过嵌入向量的相似度变化来判断话题边界。当连续两个句子的向量夹角超过某个阈值时认为话题切换了。这种方式更智能但需要额外的模型推理开销。Late Chunking延迟切分先对整个文档做向量化再切分让每个 Chunk 保留全局上下文信息。这种方法在 2024 年底的 Cohere 论文中被提出实测在长文档检索上有明显提升缺点是推理成本更高。选型上没有银弹。技术类文档代码、API 文档建议用 500-800 字符的递归切分自然语言文档报告、文章建议用 800-1200 字符的语义切分。如果文档格式统一PDF、Markdown优先按标题层级结构切分效果通常比纯文本切分好一个档次。向量模型选型——谁把文字变成了坐标选向量模型的核心指标有两个检索质量和推理性能。不同语言的模型差异很大中文场景不要直接套英文模型。当前主流方案BGEBAAIBAAI 出品的系列模型中文场景首选。BGE-large-zh-v1.5 在 MTEB中文上长期占据前排768 维支持 512 Token 输入推理速度适中。适合绝大多数中文 RAG 场景。BCEmaidalun1020专门针对中文和代码场景优化的 BERT 类模型。在中文检索任务上对 BGE 系列有一定优势参数量更小推理更快。如果文档以代码和技术文档为主BCE 是值得优先试的选项。text-embedding-3-smallOpenAI1536 维API 调用不需要本地 GPU。缺点是每次检索都要走网络、有 API 成本但嵌入质量很稳定。适合英文或双语场景中文不如 BGE/BCE。GTEAlibaba阿里出品的多语言 Embedding 模型GTE-Qwen2 在 C-MTEB 上表现很好。与通义系列模型配合使用有加成。模型中文质量向量维度输入长度推荐场景BGE-large-zh-v1.5⭐⭐⭐⭐⭐768512通用中文 RAGBCE-embedding-base_v1⭐⭐⭐⭐⭐768512中文 代码text-embedding-3-small⭐⭐⭐⭐512-15368192双语/纯英文GTE-Qwen2⭐⭐⭐⭐⭐768-20488192多语言长文档选型建议中文项目默认从 BGE-large-zh-v1.5 起步。如果文档以代码为主换成 BCE。如果预算允许且需要处理超长文档超过 512 TokenGTE-Qwen2 支持 8192 Token 输入是杀手级特性。向量数据库选型——检索背后的基础设施向量数据库存储 Embedding 向量并提供近似最近邻ANN检索。不同的库在部署复杂度、性能、成本上差异很大。方案部署方式适合规模Filter 支持推荐场景Chroma嵌入式≤ 100 万基础开发原型、个人项目MilvusDocker 集群亿级丰富生产环境、大规模QdrantDocker 单机/集群千万级丰富中小型生产、Rust 高性能PineconeSaaS亿级丰富不想运维、预算充足的团队PGVectorPostgreSQL 插件≤ 50 万原生 SQL已有 PG、数据结构化选型建议刚开始做原型用 Chroma零配置、零运维pip install 就能跑。进入生产阶段数据量在百万级以内且团队熟悉 Docker上 Qdrant数据量大千万级以上上 Milvus。不想管运维Pinecone。如果团队已经重度使用 PostgreSQLPGVector 是最省事的选择。检索召回策略——如何找到最相关的内容把文档切碎、向量化、存进数据库之后最关键的问题来了用户问一个问题怎么从成千上万条 Chunks 里找到最相关的那几条纯向量检索Dense Retrieval把用户问题用同样的向量模型编码去向量数据库里做 ANN 搜索。最常用但依赖向量模型的质量对语义相近但表达方式不同的 Query 容易漏检。稀疏检索Sparse Retrieval用 BM25 之类的关键词匹配算法检索。优点是精确匹配强对专有名词、缩写、产品名效果好。缺点是语义理解为零。好消息是稀疏检索和向量检索可以互补。Hybrid 检索把向量检索和 BM25 的结果合并用加权平均或 RRFReciprocal Rank Fusion做融合。权重分配上技术文档场景建议 BM25 权重高一些0.4-0.5因为专有名词匹配很重要开放域问答场景向量检索权重高一些0.6-0.7。重排序RerankingHybrid 检索可能召回 20-50 条结果但大模型的上下文窗口放不下这么多。重排序是用一个专门的 Cross-Encoder 模型对这几十条结果逐一打分选出最相关的 top-K 条交给大模型。这是 RAG 系统中性价比最高的优化——加一个 Reranker 通常能把答案准确率提升 5-15 个百分点而推理成本只增加几毫秒。推荐方案BGE-reranker-v2-m3中文、Cohere Rerank 3英文、BCE-reranker-base_v1中文代码。查询改写Query Rewriting用户的问题通常很简短像「报销流程是什么」「怎么部署」直接拿去检索效果不好。查询改写在把原始问题交给检索系统之前先让大模型做一次扩展——把问题补充完整、拆成多个子问题、或者用同义词扩展。这是 Multi-Step RAG 的核心套路之一。大模型选型——生成质量的最后一道关RAG 的生成质量取决于两个因素检索到的内容是否相关以及大模型是否能基于这些内容正确生成。用闭源模型还是开源模型可以从三个维度权衡上下文长度长上下文的模型能接受更多的检索结果。Claude200K、GPT-4o128K、DeepSeek-V3128K都支持一次塞入大量资料。开源的 Qwen2.5-72B128K和 GLM-4-9B128K也追上了。建议选 128K 的模型这样 Reranker 之后可以放心地保留 15-20 条 Chunks。指令遵循能力RAG 场景下模型需要严格「只看提供的材料不要自己编」。指令遵循能力弱的模型容易无视检索结果自己发挥。Claude Sonnet 和 GPT-4o 在这方面的表现最好开源的 DeepSeek-V3 和 Qwen2.5-72B 紧随其后。中文能力中文场景下 DeepSeek 和通义千问系列是最稳妥的选择。DeepSeek-V3 在中文知识问答上甚至能和 GPT-4o 打平API 价格低一个数量级。选型建议个人/小团队做 RAG 原型用 DeepSeek API便宜、中文好、128K 上下文。生产环境且预算充足Claude 或 GPT-4o。需要私有化部署Qwen2.5-72B 或 DeepSeek-V3 本地跑。从零搭建 RAG 系统——完整代码实战下面用 Python 跑通一个完整的 RAG 流水线文档加载 → 文本切分 → 向量化 → 存入 Chroma → 检索 → 生成回答。项目结构textrag-demo/├── .env # API Key 配置├── ingest.py # 索引线文档处理 入库├── query.py # 查询线检索 生成├── requirements.txt # 依赖└── data/ # 源文档目录安装依赖bashpip install langchain langchain-community langchain-chroma chromadb sentence-transformers python-dotenv配置 .envtext# 选用的 Embedding 模型默认用 BGEEMBEDDING_MODELBAAI/bge-large-zh-v1.5# LLM API 配置用 DeepSeek 示例LLM_API_KEYyour_deepseek_api_keyLLM_BASE_URLhttps://api.deepseek.comLLM_MODELdeepseek-chat索引线文档处理与入库python# ingest.pyimport osfrom dotenv import load_dotenvfrom langchain_community.document_loaders import DirectoryLoader, TextLoaderfrom langchain.text_splitter import RecursiveCharacterTextSplitterfrom langchain_community.embeddings import HuggingFaceBgeEmbeddingsfrom langchain_chroma import Chromaload_dotenv()# 1. 加载文档loader DirectoryLoader( ./data, glob**/*.md, loader_clsTextLoader, loader_kwargs{encoding: utf-8})docs loader.load()print(f加载了 {len(docs)} 个文档)# 2. 文本切分text_splitter RecursiveCharacterTextSplitter( chunk_size500, chunk_overlap100, separators[\n\n, \n, 。, , , , ], length_functionlen)chunks text_splitter.split_documents(docs)print(f切分为 {len(chunks)} 个 Chunks)# 3. 初始化 Embedding 模型model_name os.getenv(EMBEDDING_MODEL, BAAI/bge-large-zh-v1.5)embeddings HuggingFaceBgeEmbeddings( model_namemodel_name, model_kwargs{device: cpu}, encode_kwargs{normalize_embeddings: True})# 4. 存入 Chromapersist_dir ./chroma_dbvector_store Chroma.from_documents( documentschunks, embeddingembeddings, persist_directorypersist_dir)print(f向量库已持久化到 {persist_dir})查询线检索与生成python# query.pyimport osfrom dotenv import load_dotenvfrom langchain_community.embeddings import HuggingFaceBgeEmbeddingsfrom langchain_chroma import Chromafrom openai import OpenAIload_dotenv()# 加载向量库model_name os.getenv(EMBEDDING_MODEL, BAAI/bge-large-zh-v1.5)embeddings HuggingFaceBgeEmbeddings( model_namemodel_name, model_kwargs{device: cpu}, encode_kwargs{normalize_embeddings: True})vector_store Chroma( persist_directory./chroma_db, embedding_functionembeddings)# 初始化 LLMclient OpenAI( api_keyos.getenv(LLM_API_KEY), base_urlos.getenv(LLM_BASE_URL))def rag_query(question: str, k: int 5) - str: # 检索 results vector_store.similarity_search(question, kk) contexts \n\n.join([doc.page_content for doc in results]) # 组装 Prompt prompt f你是一个知识库问答助手。请基于以下资料回答问题。如果资料中没有相关信息请直接说不知道。资料{contexts}问题{question}请基于以上资料回答 # 生成 response client.chat.completions.create( modelos.getenv(LLM_MODEL, deepseek-chat), messages[{role: user, content: prompt}], temperature0.3, max_tokens2048 ) return response.choices[0].message.contentif __name__ __main__: while True: q input(\n请输入问题输入 q 退出) if q.lower() q: break answer rag_query(q) print(f\n回答\n{answer})大功告成。把文档放进data/目录跑一次python ingest.py建库然后python query.py就能开始问答了。加入 Hybrid 检索和 Reranker基础版跑通之后加 Hybrid 和 Reranker 是投入产出比最高的升级。bashpip install rank-bm25python# 在 query.py 中添加 Hybrid 检索 Rerankerfrom typing import Listfrom langchain_chroma import Chromafrom rank_bm25 import BM25Okapiimport jiebadef hybrid_search(question: str, k: int 20) - List[str]: # Dense 检索 dense_results vector_store.similarity_search(question, kk) dense_texts [doc.page_content for doc in dense_results] # Sparse 检索(BM25) tokenized_docs [list(jieba.cut(doc.page_content)) for doc in dense_results] bm25 BM25Okapi(tokenized_docs) tokenized_query list(jieba.cut(question)) bm25_scores bm25.get_scores(tokenized_query) sparse_indices sorted( range(len(bm25_scores)), keylambda i: bm25_scores[i], reverseTrue )[:k] sparse_texts [dense_texts[i] for i in sparse_indices] # RRF 融合 all_texts list(dict.fromkeys(dense_texts sparse_texts)) return all_texts[:k]# 用 Cross-Encoder 重排序from sentence_transformers import CrossEncoderreranker CrossEncoder(BAAI/bge-reranker-v2-m3)def rerank(query: str, candidates: List[str], top_k: int 5) - List[str]: pairs [[query, doc] for doc in candidates] scores reranker.predict(pairs) ranked sorted(zip(candidates, scores), keylambda x: x[1], reverseTrue) return [doc for doc, _ in ranked[:top_k]]把这段加入后rag_query函数里的检索替换为rerank(question, hybrid_search(question, k20), top_k5)答案质量会有明显提升。⚠️ **Reranker 显存占用** Cross-Encoder 模型推理比 Bi-Encoder 慢而且显存消耗随候选文档数量线性增长。如果 CPU 推理建议候选数不超过 30 条单条不超过 512 Token。有 GPU 的话BGE-reranker-v2-m3 在 FP16 下显存占用不到 2GB。进阶多模态 RAG文本 RAG 跑通之后下一个方向是让系统理解图片、表格、甚至是音视频。两种实现路径路径一图文统一嵌入。用多模态 Embedding 模型如 CLIP、SigLIP、Nomic Embed Vision把图片和文本映射到同一个向量空间。检索时用户的文本 Query 可以直接匹配图片。适用于「按语义搜图片」的场景。路径二先提取后检索。用 VLM视觉语言模型如 GPT-4o、Qwen-VL、CogVLM2把图片转成文字描述然后走标准文本 RAG 流程。适用于「基于图文混合文档做问答」的场景比如产品手册中既有文字说明又有示意图。两种路径的实际结合方案在 2025 年逐渐成熟——先用多模态 Embedding 做粗筛再用 VLM 做细读。比如用户问「这张架构图里的数据库层用了什么技术」粗筛找出相关图片细读让 VLM 仔细解读图片内容。python# 多模态 RAG图片转文字后检索from openai import OpenAIimport base64client OpenAI(api_key...)def image_to_text(image_path: str) - str: with open(image_path, rb) as f: img_b64 base64.b64encode(f.read()).decode() response client.chat.completions.create( modelgpt-4o, messages[{ role: user, content: [ {type: text, text: 请详细描述这张图片的内容列出所有关键文字元素}, {type: image_url, image_url: { url: fdata:image/png;base64,{img_b64} }} ] }] ) return response.choices[0].message.content# 对每张图片生成文字描述与文本 Chunks 一起索引# 检索时同时搜文本和图片描述流程不变部署上线把 RAG 系统包装成一个可调用的 API 服务用 FastAPI 最直接。python# api.pyfrom fastapi import FastAPI, Queryfrom pydantic import BaseModelfrom query import rag_queryapp FastAPI(titleRAG API)class QueryRequest(BaseModel): question: str top_k: int 5class QueryResponse(BaseModel): question: str answer: strapp.post(/rag, response_modelQueryResponse)async def ask(request: QueryRequest): answer rag_query(request.question, krequest.top_k) return QueryResponse(questionrequest.question, answeranswer)app.get(/health)async def health(): return {status: ok}启动服务bashpip install fastapi uvicornuvicorn api:app --host 0.0.0.0 --port 8000调用方式bashcurl -X POST http://localhost:8000/rag \ -H Content-Type: application/json \ -d {question: 报销流程是什么, top_k: 5}Docker 部署dockerfileFROM python:3.11-slimWORKDIR /appCOPY requirements.txt .RUN pip install --no-cache-dir -r requirements.txtCOPY . .# Chroma 持久化目录、模型缓存需要持久卷VOLUME [/app/chroma_db, /root/.cache]CMD [uvicorn, api:app, --host, 0.0.0.0, --port, 8000]bashdocker build -t rag-demo .docker run -d -p 8000:8000 -v ./chroma_db:/app/chroma_db rag-demo⚠️ **模型加载时间** HuggingFace 模型首次加载会下载权重镜像启动后可能需要 1-3 分钟才能响应第一个请求。建议用VOLUME持久化/root/.cache/目录避免每次重启都重新下载。避坑指南⚠️ **Chunk Size 过大或过小** Chunk Size 设到 2000一条 Chunk 包含三四段内容检索命中率看起来高但送入 LLM 的上下文噪声太大答案反而变差。Chunk Size 小于 200语义碎片化严重LLM 接不上上下文。500-800 字符是不容易出错的安全区间。⚠️ **中文场景用英文 Embedding 模型** 用text-embedding-ada-002或all-MiniLM-L6-v2做中文 RAG中文检索准确率会掉 10-20 个百分点。中文文本先做分词再送入 BGE 或 BCE效果比直接送入 OpenAI 的英文 Embedding 好很多。⚠️ **只有 Dense 检索没有 Reranker** 向量检索召回 top-10 的结果里排第三的可能比排第五的更适合。Reranker 可以用 Cross-Encoder 做更精确的语义匹配把真正相关的结果顶到前面。不加 Reranker生成质量完全取决于向量模型的排序能力没有纠错机制。⚠️ **检索结果直接拼入 Prompt不做筛选** 如果一条 Chunks 和问题完全无关但被召回了LLM 可能会被「带偏」。用 Reranker 设一个置信度阈值低于阈值的 Chunks 直接丢弃。如果最终有效上下文不足让 LLM 回答资料中没有相关信息而不是强行编造。⚠️ **上下文窗口塞满 Chunks** 模型有 128K 上下文不代表要把 128K 都用完。实测经验将 top-5 到 top-10 条精排后的 Chunks 送入模型质量标准控制在 4000-6000 Token 以内生成效果最稳定。上下文塞得越满模型越容易在无关细节中迷失。总结两句话RAG 不是把文档切碎塞进向量库就完事了。文本怎么切、向量模型选哪个、检索出来怎么重排、最终怎么组装 Prompt每一层的选择都会影响最终效果。从 BGE Chroma 500 字 Chunk 起步加上 Hybrid 检索和 Reranker这套组合能覆盖绝大多数知识库问答场景。多模态 RAG 的门槛正在快速降低图文统一检索的方向值得持续关注。学AI大模型的正确顺序千万不要搞错了2026年AI风口已来各行各业的AI渗透肉眼可见超多公司要么转型做AI相关产品要么高薪挖AI技术人才机遇直接摆在眼前有往AI方向发展或者本身有后端编程基础的朋友直接冲AI大模型应用开发转岗超合适就算暂时不打算转岗了解大模型、RAG、Prompt、Agent这些热门概念能上手做简单项目也绝对是求职加分王给大家整理了超全最新的AI大模型应用开发学习清单和资料手把手帮你快速入门学习路线:✅大模型基础认知—大模型核心原理、发展历程、主流模型GPT、文心一言等特点解析✅核心技术模块—RAG检索增强生成、Prompt工程实战、Agent智能体开发逻辑✅开发基础能力—Python进阶、API接口调用、大模型开发框架LangChain等实操✅应用场景开发—智能问答系统、企业知识库、AIGC内容生成工具、行业定制化大模型应用✅项目落地流程—需求拆解、技术选型、模型调优、测试上线、运维迭代✅面试求职冲刺—岗位JD解析、简历AI项目包装、高频面试题汇总、模拟面经以上6大模块看似清晰好上手实则每个部分都有扎实的核心内容需要吃透我把大模型的学习全流程已经整理好了抓住AI时代风口轻松解锁职业新可能希望大家都能把握机遇实现薪资/职业跃迁这份完整版的大模型 AI 学习资料已经上传CSDN朋友们如果需要可以微信扫描下方CSDN官方认证二维码免费领取【保证100%免费】