RAG技术解析:从原理到实践,构建可靠的企业级AI知识问答系统
1. 从“幻觉”到“靠谱”:为什么我们需要RAG?
如果你最近在捣鼓大语言模型,不管是ChatGPT、Claude还是开源的Llama、Qwen,肯定都遇到过同一个让人头疼的问题:它一本正经地胡说八道。你问它一个非常具体、需要精确数据或专业知识的问题,比如“我们公司去年Q3的销售数据是多少?”或者“根据最新的《民法典》第1078条,协议离婚的具体流程是什么?”,它可能会给你编造出一套看似合理、实则完全错误的信息。这种现象在AI圈里被称为“幻觉”。模型就像一个知识渊博但记忆力时好时坏、还喜欢添油加醋的“大忽悠”,它的回答是基于训练数据中的统计规律“生成”的,而不是基于事实“检索”的。
这就是RAG技术诞生的核心驱动力。RAG,全称Retrieval-Augmented Generation,中文叫“检索增强生成”。这个名字听起来有点学术,但它的理念非常直观:给大模型装上一个“外部知识库大脑”。当模型需要回答问题时,不再是仅凭自己“记忆”里的东西硬编,而是先派一个“小助手”(检索器)去指定的、可靠的知识库(比如你的公司文档、产品手册、法律条文数据库)里查找相关的资料。找到这些“证据”后,再把它们和问题一起交给大模型,让它基于这些确凿的证据来组织语言、生成答案。
简单来说,传统LLM是“凭感觉答题”,而RAG是“开卷考试,并且要求引用原文”。后者显然在事实准确性、时效性和专业性上,有着碾压性的优势。这也是为什么RAG迅速成为了企业级AI应用,尤其是客服、知识管理、法律、金融等严肃场景的“标配”技术栈。它完美地弥补了大模型在“知识更新慢”(训练成本高,无法实时更新)、“私有数据不可知”(模型没见过你的内部资料)和“事实准确性差”这三大核心短板。
2. RAG的核心工作流:一次完整的“开卷考试”是如何进行的?
理解RAG,最好的方式就是拆解它处理一个用户查询的完整流程。这个过程可以清晰地分为四个阶段:知识库准备 -> 问题检索 -> 上下文增强 -> 答案生成。我们用一个具体的例子来贯穿说明:假设你为公司搭建了一个内部技术文档问答机器人,知识库是所有Markdown格式的API文档。
2.1 第一阶段:构建“外部大脑”——知识库的向量化
在考试开始前,你得先把“课本”(知识库)准备好,并且做成方便快速查阅的格式。对于RAG来说,这个格式就是“向量”。
第一步:文档加载与切分你的原始知识可能是PDF、Word、网页、数据库,甚至是会议录音转写的文本。首先,你需要用工具(如LangChain的Document Loaders,或直接使用Python的PyPDF2、docx库)把这些不同格式的文件加载成统一的纯文本。但一整本书不能直接塞给检索器,需要切成大小合适的“片段”(Chunks)。这个“切片”很有讲究:
- 太大:一个片段包含的信息太多,不够精准,可能会引入无关噪声。
- 太小:信息碎片化,可能丢失关键上下文(比如一个函数的定义和它的参数说明被切到了两个片段里)。
常见的策略是按固定字符数(如500-1000字符)重叠切分,或者按语义段落(如Markdown的标题)切分。重叠(Overlap)是为了避免把连贯的语义硬生生切断。例如,前一个片段取1-1000字符,下一个片段可以从800字符开始,取到1800字符,这样两个片段之间有200字符的重叠,保证了上下文的连续性。
第二步:文本转向量(Embedding)这是RAG的“魔法”所在。切分好的文本片段,需要通过一个Embedding模型(如BGE、text-embedding-ada-002)转换成一组高维度的数字向量(比如1024维)。你可以把这个向量理解为这段文本在“语义空间”里的一个坐标点。语义相近的文本,它们的向量坐标在空间里的距离也会很近。
例如,“如何连接数据库”和“数据库配置教程”这两个句子,经过Embedding模型计算后,它们的向量在空间中的距离会很近。而“如何连接数据库”和“今天天气真好”的向量距离则会非常远。这个过程是离线的,一次性将所有知识库片段转换成向量并存储起来,就建好了我们的“向量数据库”(Vector Database),常见的工具有Pinecone、Chroma、Milvus、Qdrant,甚至可以用PGVector插件让PostgreSQL直接支持向量检索。
注意:Embedding模型的选择至关重要。不同模型在不同语言、不同领域的语义理解能力有差异。例如,
BGE(BAAI General Embedding)系列在中文场景下表现通常优于一些通用英文模型。选择时需要考虑你的知识库主要是什么语言、什么领域。
2.2 第二阶段:接到问题,快速“翻书”——检索相关片段
当用户提问“FastAPI如何实现JWT认证?”时,RAG系统开始工作。
第一步:问题向量化系统会用同一个Embedding模型,将用户的问题“FastAPI如何实现JWT认证?”也转换成一个向量。这个向量,就是我们在“语义空间”里要寻找的目标坐标。
第二步:向量相似度搜索系统拿着这个“问题向量”,去向量数据库里进行相似度搜索。计算它和知识库中所有“文档片段向量”之间的距离(常用余弦相似度或点积)。然后,返回距离最近的Top-K个片段(比如Top-3或Top-5)。这就像是在说:“在所有的课本段落里,找出和‘如何实现JWT认证’这个话题最相关的3段话。”
这个过程是毫秒级的,得益于向量数据库针对相似度搜索的优化索引(如HNSW、IVF-PQ),即使面对百万级的知识库,也能快速返回结果。
2.3 第三阶段:组织“答题材料”——上下文构建与增强
检索到的Top-K个片段,就是我们的“证据”。但直接把它们拼在一起扔给大模型,可能还不够。这里有几个常见的增强策略:
- 重排序(Re-ranking):第一步的向量检索是“粗筛”,主要看语义相似。但语义相似不一定代表答案最相关。例如,可能检索到了一个讲“JWT原理”的片段和一个讲“FastAPI JWT具体代码”的片段,后者显然更直接有用。这时可以引入一个更精细但计算量也更大的“重排序模型”(如
bge-reranker),对Top-K的结果进行二次打分和排序,选出最相关的1-2个片段,提升最终答案的精准度。 - 元数据过滤:在切片时,可以为每个片段附加元数据,比如
{“source”: “security.md”, “section”: “authentication”}。在检索时,除了语义搜索,还可以加上过滤条件,比如“只从security.md文件中检索”,这样可以确保答案的权威性和来源一致性。 - 上下文窗口管理:大模型(LLM)的输入有长度限制(上下文窗口)。我们需要把用户的问题和检索到的相关片段,以及可能的系统指令(如“请根据以下资料回答问题”),组合成一个不超过窗口长度的提示词(Prompt)。这就需要精心设计Prompt模板,并合理取舍检索到的片段内容。
2.4 第四阶段:生成最终答案——大模型的“临门一脚”
现在,我们有了一个精心构建的Prompt,它大致长这样:
你是一个技术文档助手。请严格根据提供的上下文信息来回答问题。如果上下文信息不足以回答问题,请直接说“根据现有资料无法回答该问题”。 上下文信息: 1. [来自 security.md 的片段1:FastAPI 的 OAuth2 与 JWT 集成概述...] 2. [来自 api_auth.py 示例代码的片段2:from fastapi import Depends, HTTPException...] 问题:FastAPI如何实现JWT认证? 请基于以上上下文回答:我们将这个Prompt发送给大模型(如GPT-4、Claude 3,或本地部署的Qwen、Llama)。由于提供了确切的上下文,大模型生成答案的“幻觉”概率被极大降低。它会像一位严谨的学者,引用你给的资料,组织成通顺、专业的回答,甚至可以直接给出可运行的代码片段。
至此,一次完整的RAG流程结束。用户得到了一个准确、有据可查的答案,而不是模型凭空想象的产物。
3. 超越基础:高级RAG模式与Agentic RAG
基础的RAG流程已经能解决大部分问题,但在复杂场景下,我们还需要更智能的“考试策略”。这就是高级RAG和近期火热的Agentic RAG(智能体驱动的RAG)发挥作用的地方。
3.1 当一次检索不够时:迭代检索与查询改写
基础RAG假设用户的一次提问是精准的。但现实中,用户的问题可能模糊、冗长或包含歧义。例如,用户问:“那个东西怎么用?”(“那个东西”指代不明)。直接拿这个问题去检索,效果肯定很差。
查询改写/扩展(Query Rewriting/Expansion):在检索前,先让LLM对原始查询进行优化。比如,将“那个东西怎么用?”结合对话历史,改写成“请问FastAPI中的依赖注入系统(Dependency Injection)具体如何使用?”。
- 技术实现:可以设计一个简单的Prompt,如“请将以下用户查询改写成更适合进行知识库检索的版本:{原始查询}”。甚至可以利用LLM生成多个不同角度的改写查询,分别进行检索,然后合并结果,这被称为“查询扩展”。
迭代检索(Iterative Retrieval):有时候,第一轮检索到的信息不足以回答问题,但可以从中提炼出新的、更具体的查询线索。例如,用户问“如何搭建一个RAG系统?”,第一轮检索返回的片段提到了需要“向量数据库”和“Embedding模型”。系统可以自动生成一个新查询“Chroma向量数据库和BGE Embedding模型的具体配置步骤是什么?”,进行第二轮检索,将两轮的结果合并后,再生成最终答案。这模拟了人类逐步深入查阅资料的过程。
3.2 让RAG拥有“思考”能力:Agentic RAG
这是将AI Agent(智能体)的思想融入RAG。传统的RAG是线性的流程(检索->生成),而Agentic RAG则赋予系统“规划”和“工具使用”的能力。
你可以把Agentic RAG想象成一个拥有RAG作为核心工具的研究员。当接到一个复杂任务时(例如,“为我们新产品设计一个基于RAG的客服系统方案,并评估成本”),它不会直接去检索,而是先“思考”(规划):
- 任务分解:这个任务可以分解为:a) RAG客服系统的技术架构;b) 各组件(LLM、Embedding模型、向量数据库)的选型对比;c) 云服务与本地部署的成本估算。
- 计划执行:对于子任务a,它决定使用“RAG 架构图”、“客服系统设计”等关键词去检索。对于子任务b,它可能需要调用一个“成本计算器”工具,或者去检索不同云服务商的定价页面。
- 循环与验证:它可能执行多轮检索、工具调用,甚至自我验证中间结果是否充分,直到收集齐所有必要信息。
- 综合报告:最后,它综合所有检索到的资料和工具计算的结果,生成一份结构完整的方案报告。
框架支持:实现Agentic RAG通常需要借助LangGraph、Dify Workflow、AutoGen这类框架。它们允许你以“流程图”或“工作流”的方式,定义智能体的决策逻辑、工具调用条件和循环路径,从而处理非常复杂的、多步骤的问答任务。例如,在Dify中,你可以设计一个Workflow,先将用户问题分类,如果是技术问题则走RAG分支,如果是计算问题则调用Python代码工具,最后将结果汇总输出到Word文档。
3.3 优化检索质量:重排序与混合搜索
我们之前提到了重排序(Re-ranking),这里再深入一下。为什么需要它?因为语义相似 ≠ 答案相关。
假设你的问题是:“苹果公司最新财报的营收是多少?”。
- 片段A:一篇新闻,标题是“苹果发布新品iPhone”,内容主要讲产品,末尾提了一句“该公司上季度营收良好”。
- 片段B:一篇财经报道,标题是“苹果Q4财报分析”,里面详细列出了营收数据、同比增长率、各业务线贡献。
在向量相似度上,片段A(因为含有“苹果”、“营收”等词)和片段B可能得分都很高。但显然,片段B才是能直接回答问题的“黄金片段”。重排序模型就是一个更精细的“相关性判别器”,它通常是一个经过微调的、参数较小的模型(如Cross-Encoder架构),专门用于对“问题-文档对”进行相关性打分。经过它的二次排序,片段B会被排到最前面,从而让LLM获得最优质的上下文。
混合搜索(Hybrid Search):这是另一种强大的优化手段。它结合了两种搜索方式:
- 稠密检索(Dense Retrieval):就是我们一直讲的基于向量的语义搜索。优点在于理解语义,能处理“换个说法”的查询。
- 稀疏检索(Sparse Retrieval):传统的关键词搜索,如BM25算法。它精确匹配词汇,对于包含特定术语、代码、产品型号的查询非常有效。
例如,查询“Python中asyncio.create_task的用法”,稀疏检索能精准命中包含这个精确函数名的文档。而查询“怎么异步执行任务”,稠密检索则能更好地理解其语义。混合搜索将两者的结果按权重合并,取长补短,显著提升了检索的召回率。
4. 从理论到实践:搭建你的第一个RAG系统
了解了原理,我们动手搭建一个最简单的RAG系统。这里我们使用目前最流行的组合之一:LangChain(框架) + Chroma(向量数据库) + OpenAI Embeddings(Embedding模型) + GPT-3.5/4(LLM)。你也可以将OpenAI的组件替换为开源的,例如用BGE的Embedding模型和Qwen的LLM。
4.1 环境准备与依赖安装
首先,确保你的Python环境(建议3.8以上)并安装必要的库。我们将使用langchain的核心包以及处理文档、向量库和OpenAI集成的相关组件。
pip install langchain langchain-community langchain-openai chromadb pypdflangchain: 核心框架。langchain-community: 社区维护的第三方集成。langchain-openai: OpenAI模型的官方集成。chromadb: 轻量级、易用的向量数据库。pypdf: 用于读取PDF文档。
注意:如果你使用开源模型,安装的包会不同。例如,使用
BGEEmbedding和QwenLLM,可能需要安装langchain-huggingface,transformers,sentence-transformers等。
4.2 第一步:加载与切分文档
我们假设你有一个名为product_manual.pdf的产品手册。首先,将它加载并切分成片段。
from langchain_community.document_loaders import PyPDFLoader from langchain.text_splitter import RecursiveCharacterTextSplitter # 1. 加载PDF文档 loader = PyPDFLoader("path/to/your/product_manual.pdf") documents = loader.load() # 2. 初始化文本分割器 # chunk_size: 每个片段的最大字符数 # chunk_overlap: 片段之间的重叠字符数,用于保持上下文连贯 text_splitter = RecursiveCharacterTextSplitter( chunk_size=1000, chunk_overlap=200, length_function=len, separators=["\n\n", "\n", "。", "!", "?", ";", ",", " ", ""] # 中文友好的分隔符 ) # 3. 执行切分 docs = text_splitter.split_documents(documents) print(f"原始文档被切分成了 {len(docs)} 个片段。")关键参数解析:
chunk_size=1000:这个值不是固定的。对于普通文本,500-1500是常见范围。对于代码,可能需要更小(200-500)。你需要根据你的文档内容和后续使用的Embedding模型的最大输入长度来调整。chunk_overlap=200:重叠是为了防止一个完整的句子或概念被拦腰切断。通常设置为chunk_size的10%-20%。separators:定义了按什么标志来分割。这里配置了从中段落落到词语的多级分隔符,RecursiveCharacterTextSplitter会按这个顺序尝试分割,直到满足chunk_size要求。对于中文,加入了句号、感叹号等作为分隔符很重要。
4.3 第二步:向量化存储,构建知识库
接下来,我们选择一个Embedding模型将文本片段转换成向量,并存入Chroma数据库。
from langchain_openai import OpenAIEmbeddings from langchain_community.vectorstores import Chroma import os # 设置你的OpenAI API Key (请替换成你自己的,或使用环境变量) os.environ["OPENAI_API_KEY"] = "your-openai-api-key-here" # 1. 初始化Embedding模型 # 这里使用OpenAI的 text-embedding-ada-002 模型 embeddings = OpenAIEmbeddings(model="text-embedding-ada-002") # 2. 将切分好的文档片段进行向量化,并存入Chroma向量数据库 # persist_directory 指定数据库持久化存储的路径 vectorstore = Chroma.from_documents( documents=docs, embedding=embeddings, persist_directory="./chroma_db" # 数据将保存在本地`chroma_db`文件夹 ) # 3. 将向量数据库持久化到磁盘 vectorstore.persist() print("知识库向量化完成,已保存至 ./chroma_db")如果你想使用开源BGE模型,代码会有所不同:
from langchain_huggingface import HuggingFaceEmbeddings embeddings = HuggingFaceEmbeddings( model_name="BAAI/bge-large-zh-v1.5", # 使用中文优化的BGE模型 model_kwargs={'device': 'cpu'}, # 或 'cuda' encode_kwargs={'normalize_embeddings': True} # 归一化,提升相似度计算效果 ) # 后续的 Chroma.from_documents 用法相同实操心得:
text-embedding-ada-002是OpenAI的通用Embedding模型,效果稳定,但需付费且网络要求高。BGE系列是优秀的开源替代,尤其在中文场景下表现突出,可以本地部署,数据隐私有保障。选择时需权衡效果、成本、隐私和部署复杂度。
4.4 第三步:创建检索链,实现问答
知识库建好后,我们创建一个检索式问答链。这个链会自动完成“检索相关文档 -> 组合Prompt -> 调用LLM生成答案”的整个过程。
from langchain_openai import ChatOpenAI from langchain.chains import RetrievalQA from langchain.prompts import PromptTemplate # 1. 从磁盘加载已创建的向量数据库 vectorstore = Chroma( persist_directory="./chroma_db", embedding_function=embeddings # 必须使用和创建时相同的embedding模型 ) # 2. 将向量数据库转换为检索器(Retriever) # search_kwargs 可以控制返回的文档数量,这里返回最相关的3个片段 retriever = vectorstore.as_retriever(search_kwargs={"k": 3}) # 3. 定义LLM(这里使用GPT-3.5-Turbo) llm = ChatOpenAI(model="gpt-3.5-turbo", temperature=0) # temperature=0 使输出更确定、更少随机性,适合事实性问答。 # 4. (可选但推荐)自定义Prompt模板,让LLM更好地遵循指令 prompt_template = """ 请严格根据以下提供的上下文信息来回答问题。如果你不知道答案,就回答“我不知道”,不要编造信息。 上下文: {context} 问题:{question} 请基于上下文给出答案: """ PROMPT = PromptTemplate( template=prompt_template, input_variables=["context", "question"] ) # 5. 创建检索问答链 qa_chain = RetrievalQA.from_chain_type( llm=llm, chain_type="stuff", # “stuff”模式简单地将所有检索到的文档拼接到Prompt中 retriever=retriever, chain_type_kwargs={"prompt": PROMPT}, # 使用我们自定义的Prompt return_source_documents=True # 返回源文档,方便追溯答案来源 ) # 6. 进行问答 query = "你们的产品支持哪些支付方式?" result = qa_chain.invoke({"query": query}) print("问题:", query) print("\n答案:", result["result"]) print("\n--- 来源文档 ---") for i, doc in enumerate(result["source_documents"]): print(f"\n片段 {i+1} (来自: {doc.metadata.get('source', 'N/A')}):") print(doc.page_content[:300] + "...") # 打印前300个字符代码解读与避坑点:
chain_type="stuff":这是最简单直接的模式,把所有检索到的文档内容全部塞进Prompt。它的缺点是受限于LLM的上下文窗口长度。如果检索到的文档总长度超过窗口,会报错。对于更长的上下文,可以考虑map_reduce或refine等链类型,它们会以更复杂的方式处理多文档。return_source_documents=True:强烈建议开启。这让你能查看生成答案所依据的原始文本片段,是验证答案准确性、调试检索效果的关键。- 温度参数
temperature:在事实性问答中,通常设置为0或接近0(如0.1),以减少LLM的“创造性”和随机性,让答案更忠实于上下文。
运行这段代码,你的第一个RAG问答系统就搭建完成了!它会从你的产品手册PDF中寻找关于支付方式的信息,并生成基于手册内容的答案。
5. 避坑指南:RAG实践中常见的“坑”与优化策略
搭建一个能跑的RAG demo很简单,但要让它真正在生产环境稳定、准确地工作,会遇到不少挑战。下面是我在实践中总结的几个关键“坑”和应对策略。
5.1 检索质量不佳:根源往往是数据预处理
“垃圾进,垃圾出”(Garbage in, garbage out)在RAG中体现得淋漓尽致。如果检索到的文档片段质量差,LLM再强也生成不出好答案。
- 坑1:切片策略不当。这是最常见的问题。切片太大,答案不精准;切片太小,信息不完整。
- 优化:不要只用固定字符切分。尝试语义切片。可以使用
langchain的SemanticChunker,它基于句子间的语义相似度进行切分,能更好地保持一个完整思想的连贯性。或者,对于结构化文档(如Markdown、HTML),使用RecursiveCharacterTextSplitter并设置separators为["#", "##", "###", "\n\n", "\n"],使其按标题层级进行切分,这样每个切片通常是一个逻辑小节。
- 优化:不要只用固定字符切分。尝试语义切片。可以使用
- 坑2:文本噪声过多。PDF中常有页眉、页脚、页码、无关图表说明等。
- 优化:在加载和切片后,增加一个清洗和标准化的步骤。可以用正则表达式去除特定的噪声模式,或者使用
Unstructured这类更强大的库,它能更好地解析PDF的布局,提取主体文本。对于网页内容,使用BeautifulSoup提取特定标签内的文本。
- 优化:在加载和切片后,增加一个清洗和标准化的步骤。可以用正则表达式去除特定的噪声模式,或者使用
- 坑3:关键信息被切碎。比如一个表格、一个代码块被切到了两个片段里。
- 优化:针对特定内容类型定制切片逻辑。例如,检测到代码块(```)或表格标记时,尝试将它们作为一个整体保留在一个片段内,即使这会导致该片段略微超过预设的
chunk_size。
- 优化:针对特定内容类型定制切片逻辑。例如,检测到代码块(```)或表格标记时,尝试将它们作为一个整体保留在一个片段内,即使这会导致该片段略微超过预设的
5.2 Embedding模型“水土不服”
不同的Embedding模型在不同类型文本上的表现差异很大。
- 现象:检索结果看似相关,但总是差一点,不是最核心的那段。
- 排查与优化:
- 领域适配:如果你的知识库是高度专业化的(如医学论文、法律条文),通用Embedding模型可能不够用。考虑在专业语料上对开源Embedding模型(如BGE)进行微调(Fine-tuning),这能显著提升在该领域的检索精度。
- 多语言问题:如果你的知识库是中英文混合的,确保使用的Embedding模型是多语言或针对中文优化的。
text-embedding-ada-002对英文支持更好,而BGE-large-zh系列对中文更友好。 - 测试与评估:构建一个小型的测试集,包含一系列问题及其在知识库中对应的“标准答案”片段。然后运行你的RAG系统,看检索器能否稳定地召回这些标准片段。可以用“命中率”(Hit Rate)和“平均倒数排名”(MRR)等指标来量化评估。
5.3 LLM的“叛逆”与Prompt工程
即使给了正确的上下文,LLM有时也会“无视”它,按照自己的“记忆”来回答,或者回答得啰嗦、格式不对。
- 坑:Prompt指令不够强硬。像“请参考以下上下文”这种温和的指令,对于强大的LLM约束力不够。
- 优化:设计更强有力的、结构清晰的Prompt。
- 明确角色:
“你是一个严谨的客服助手,必须严格依据给定的产品手册内容回答问题。” - 严格限制:
“你的回答必须且只能基于提供的上下文。如果上下文没有提及,你必须回答‘根据产品手册,该信息未提及。’严禁编造任何信息。” - 指定格式:
“请先给出简短结论,然后分点列出依据。依据需引用上下文中的原文(用引号标注)。” - 提供示例:在Prompt中加入一两个“示例”(Few-shot Learning),展示你期望的问答格式和严谨程度。
- 明确角色:
- 另一个策略:后处理与验证。在LLM生成答案后,可以增加一个验证步骤。例如,用另一个轻量级的模型或规则,检查答案中的关键事实是否能在源文档中找到直接支持。如果支持度太低,可以触发重新检索或直接返回“无法回答”。
5.4 系统扩展性与成本
当知识库文档达到百万、千万级别时,简单的向量相似度搜索可能变慢,调用商用LLM API的成本也会成为问题。
- 检索性能:对于海量数据,需要选择支持高性能索引的向量数据库,如
Milvus、Qdrant、Weaviate。它们支持基于HNSW(近似最近邻)等算法的索引,能在毫秒内从十亿级向量中完成搜索。 - 成本控制:
- LLM调用:对于内部应用,可以考虑使用开源LLM本地部署,如Qwen、Llama、ChatGLM。虽然效果可能略逊于顶级商用模型,但对于垂直领域、有高质量上下文支撑的RAG任务,通常已经足够,且能彻底解决数据隐私和长期成本问题。
- Embedding调用:Embedding的调用次数与文档更新频率和查询量成正比。如果使用按量付费的API,这是一笔持续开销。将开源Embedding模型(如BGE)部署在本地或公司内网,是控制成本、保障数据安全的有效手段。
- 缓存机制:对常见的、重复的查询结果进行缓存,可以大幅减少对LLM和检索器的调用。
RAG不是一个“一劳永逸”的框架,而是一个需要持续调优的系统。从数据清洗、切片策略、Embedding模型选型,到检索算法、Prompt设计、LLM选择,每一个环节都影响着最终效果。最好的方法是从一个简单的原型开始,用真实的业务问题去测试它,观察它在哪里出错,然后针对性地去优化那个环节。这个过程本身,就是对“如何让AI更可靠地运用知识”这一命题最深刻的理解。