尧图建网站 尧图建网站 YAOTU WEB BUILD 免费咨询
ARTICLE DETAIL

资讯详情

深耕网站建设与建站编程的一线实战洞察。

RAG技术详解:如何为LLM构建外挂知识库解决幻觉与信息滞后问题

RAG技术详解:如何为LLM构建外挂知识库解决幻觉与信息滞后问题 1. 项目概述当大模型遇上“外挂大脑”最近和不少做AI应用落地的朋友聊天大家普遍遇到一个头疼的问题自家的通用大模型比如GPT-4、Claude或者一些开源模型在回答专业领域问题时要么“一本正经地胡说八道”要么信息陈旧过时。比如你问它公司内部最新的产品政策文档细节它可能给你编造一个或者咨询某个特定行业的标准它给出的答案可能是两年前的旧版本。这背后的核心原因是这些大模型的“知识”截止于其训练数据的时间点且无法动态获取和精准利用私有、最新的信息。这就引出了我们今天要深入拆解的“RAG”技术。RAG全称是检索增强生成。你可以把它理解成给大模型装上一个“外挂知识库”或“实时搜索引擎”。它的工作模式非常直观当用户提出一个问题时系统不是让大模型直接凭空生成答案而是先从这个外挂的、可控的知识库可以是你的文档、数据库、网页中快速检索出与问题最相关的几段信息。然后把这些检索到的“证据”或“参考资料”连同用户的问题一起作为提示词喂给大模型让它基于这些给定的、可靠的上下文来组织语言生成最终答案。这样做的好处是革命性的。首先它极大地缓解了“幻觉”问题因为答案的素材来源于你提供的真实文档大模型更像一个优秀的“信息整合与表述者”而非“虚构者”。其次它实现了知识的动态更新你只需要更新知识库模型就能立即获取最新信息无需耗费巨资重新训练模型。最后它保护了隐私和知识产权你可以将敏感或私有的数据放在本地知识库中无需上传到公开的模型服务端。因此RAG迅速成为了构建企业级、专业化AI问答、客服、知识助手等应用的首选架构。接下来我们就从设计思路到实操细节完整地走一遍RAG系统的构建之路。2. RAG系统核心架构与设计思路拆解一个完整的RAG系统远不止是“检索”加“生成”那么简单。它是一条精心设计的流水线每个环节的选择都直接影响最终效果。我们可以将其核心架构拆解为三个关键阶段知识库的预处理与嵌入、查询时的检索、以及最终的增强生成。2.1 知识库的预处理与嵌入打好“地基”这是RAG系统的“离线准备”阶段决定了知识库的质量和检索效率。核心目标是将非结构化的原始文本如PDF、Word、网页、Markdown转化为便于快速检索的数学向量形式。第一步文档加载与切分你不能把一整本几百页的PDF直接扔给系统。首先需要使用文档加载器如LangChain的PyPDFLoader、UnstructuredFileLoader读取文件内容。接着是最关键的一步——文本切分。这里有个核心权衡切分得太碎如每段50字会丢失上下文信息导致检索到的片段无法支撑完整答案切分得太大如每章几千字又会引入大量无关噪声稀释关键信息并增加后续嵌入和检索的成本。实操心得切分策略是门艺术我常用的策略是“递归式切分”。先按大标题如##分割成中等块约500-1000字再对每个中块按句子或自然段落进行二次细切约100-200字并保留一定的重叠区域如50字。这样既能保证检索片段的上下文完整性又能提高命中精度。工具上LangChain的RecursiveCharacterTextSplitter非常好用可以按字符递归分割并设置chunk_size和chunk_overlap参数。第二步文本向量化嵌入切分后的文本块需要通过嵌入模型转化为固定维度的向量比如768维或1536维。这个向量就是这段文本在数学空间中的“坐标”语义相近的文本其向量在空间中的距离通常用余弦相似度衡量也越近。模型选型考量通用vs领域专用OpenAI的text-embedding-ada-002通用性很强。但对于法律、医疗等专业领域使用在该领域语料上微调过的嵌入模型如BGE-M3、jina-embeddings效果往往更佳。维度与性能维度越高通常表征能力越强但存储和计算成本也越高。1536维的模型比384维的模型更精细但也更“吃”资源。本地部署出于数据安全和成本考虑许多团队选择开源模型本地部署如all-MiniLM-L6-v2平衡性能与速度、bge-large-zh中文优。第三步向量存储生成的海量向量需要被高效存储和检索。这就是向量数据库的用武之地。它将向量和对应的原始文本块及其元数据如来源文件名、页码一起存储并建立高效的索引如HNSW、IVF-Flat以便在毫秒级时间内完成相似性搜索。主流向量数据库选型对比数据库核心特点适用场景Chroma轻量、易用、开源与LangChain集成极佳快速原型验证中小规模项目Pinecone全托管云服务高性能自动扩缩容生产环境追求稳定和免运维Weaviate开源支持混合搜索向量关键词内置模块化需要结合关键词过滤的复杂检索Qdrant开源Rust编写性能优异过滤功能强大对性能和复杂过滤有高要求的项目Milvus开源专为海量向量搜索设计分布式架构超大规模向量数据亿级以上对于大多数从0到1的项目我建议从Chroma开始它的简单性让你能快速聚焦在业务逻辑而非基础设施上。当数据量达到百万级且对检索速度和稳定性要求极高时再考虑迁移到Pinecone或Qdrant。2.2 查询与检索精准定位“证据”当用户提问时系统实时工作流启动。用户的查询问题首先会被送入同一个嵌入模型转化为查询向量。随后系统在向量数据库中执行相似性搜索找出与查询向量最相似的K个文本块例如前5个。这里的K是一个重要参数它决定了提供给大模型的上下文数量。注意事项检索并非唯向量论单纯的向量相似度检索有时会“失灵”尤其是当用户查询包含特定关键词、日期或编号时。因此混合检索变得越来越重要。例如可以同时进行向量检索找到语义相似的文本。关键词检索BM25找到包含查询关键词的文本。 最后将两者的结果按分数融合如 Reciprocal Rank Fusion。Weaviate和Elasticsearch都能很好地支持这种混合模式。2.3 增强生成基于上下文的“精加工”检索到的Top K个文本块将与原始的用户问题一起被精心构造成一个“提示词”送给大语言模型。这个提示词的模板设计至关重要直接决定了答案的质量。一个经典的提示词模板如下请基于以下提供的上下文信息回答用户的问题。如果上下文中的信息不足以回答问题请直接说“根据已知信息无法回答该问题”不要编造信息。 上下文信息 {context_text_1} {context_text_2} ... 用户问题{user_question} 请用中文给出专业、清晰的回答这里{context_text}就是检索到的文本块拼接而成。这个模板明确指示了模型严格遵循上下文抑制幻觉。大模型选型你可以使用云端API如GPT-4、Claude-3也可以本地部署开源模型如Qwen、Llama、ChatGLM。对于企业内部应用本地部署在数据安全和控制力上优势明显。选择时需权衡效果、成本、响应速度和部署复杂度。3. 核心细节解析与进阶优化技巧基础的RAG流程搭建起来后你会发现效果可能并不稳定。这时就需要深入各个环节进行“精调”。以下是几个关键的优化方向。3.1 检索质量优化让召回更准检索是RAG的“生命线”如果检索不到相关文档再强的大模型也无力回天。查询重写与扩展用户的原始查询可能很简短或模糊。例如“这个产品怎么样”可以重写为“请介绍[产品名称]的功能特点、用户评价和价格信息”。可以使用一个小型LLM如GPT-3.5-turbo来执行此任务自动优化查询语句。元数据过滤在检索时加入筛选条件。比如当用户问“2023年的财务报告”你可以在向量搜索时附加过滤器WHERE year 2023 AND doc_type report。这能极大排除无关文档提升精度。这要求你在预处理阶段就为每个文本块打好标签元数据。多向量检索除了对整段文本进行嵌入还可以对文本中的关键实体、摘要或不同维度分别生成向量并存储。检索时从多个维度进行查询和融合能更全面地捕捉相关性。3.2 上下文管理与提示工程让生成更稳即使检索到了相关文档如何有效地利用它们也是一门学问。上下文窗口与排序大模型有上下文长度限制。当检索出多个相关片段时需要按相关性分数排序并选择最重要的几个确保总长度不超限。有时相关性最高的片段不一定包含答案的全部要素可能需要多片段互补。提示词工程进阶指定角色“你是一位专业的法律顾问请基于以下合同条款...”分步思考“请先总结上下文中的关键事实然后基于这些事实推理出答案。”引用来源要求模型在回答中注明依据来自哪个文档的哪一部分如“[来自《产品手册V2.1》第5页]”这增加了答案的可信度和可追溯性。后处理与验证对模型生成的答案可以增加一个验证步骤。例如用另一个轻量级模型或规则判断答案是否与提供的上下文矛盾或者是否包含了上下文中未出现的关键断言。3.3 评估体系构建如何衡量RAG的好坏没有评估优化就无从谈起。RAG的评估是多维度的检索阶段评估命中率对于一组标准问题检索到的Top K文档中是否包含正确答案的片段平均排名正确答案片段在检索结果中的平均位置排名越靠前越好。生成阶段评估忠实度生成的答案在多大程度上严格遵循了提供的上下文是否引入了未提及的信息幻觉这可以通过让模型自己判断“答案中的陈述是否都能从上下文中找到支持”来量化。答案相关性答案是否直接、完整地解决了用户的问题有用性人工评估答案是否清晰、专业、有用。可以构建一个包含标准问题集、对应的答案和支撑文档的测试集定期运行自动化评估脚本监控系统效果的变化。4. 从零到一手把手搭建一个简易RAG系统我们以处理一组公司内部的Markdown格式产品文档为例使用LangChain和Chroma搭建一个本地可运行的RAG问答系统。4.1 环境准备与依赖安装首先创建一个新的Python环境并安装核心库。# 创建并激活虚拟环境可选 python -m venv rag_env source rag_env/bin/activate # Linux/Mac # rag_env\Scripts\activate # Windows # 安装核心依赖 pip install langchain langchain-community langchain-chroma # LangChain核心及Chroma集成 pip install sentence-transformers # 用于本地嵌入模型 pip install pypdf # 如果需要处理PDF pip install tiktoken # 用于文本切分计数 pip install openai # 如果使用OpenAI的模型4.2 知识库构建与向量化假设我们的产品文档都在./product_docs/目录下格式为.md。# rag_ingest.py from langchain_community.document_loaders import DirectoryLoader, TextLoader from langchain.text_splitter import RecursiveCharacterTextSplitter from langchain.embeddings.sentence_transformer import SentenceTransformerEmbeddings from langchain.vectorstores import Chroma # 1. 加载文档 loader DirectoryLoader(./product_docs/, glob**/*.md, loader_clsTextLoader) documents loader.load() print(f成功加载 {len(documents)} 个文档) # 2. 切分文本 text_splitter RecursiveCharacterTextSplitter( chunk_size500, # 每个文本块约500字符 chunk_overlap50, # 块之间重叠50字符保持上下文连贯 length_functionlen, separators[\n\n, \n, 。, , , , , , ] # 中文优先分割符 ) chunks text_splitter.split_documents(documents) print(f切分为 {len(chunks)} 个文本块) # 3. 初始化嵌入模型使用本地开源模型 embedding_function SentenceTransformerEmbeddings(model_nameall-MiniLM-L6-v2) # 如果使用OpenAI则替换为 # from langchain_openai import OpenAIEmbeddings # embedding_function OpenAIEmbeddings(modeltext-embedding-ada-002) # 4. 创建并持久化向量数据库 vector_db Chroma.from_documents( documentschunks, embeddingembedding_function, persist_directory./chroma_db # 向量数据库存储路径 ) vector_db.persist() # 保存到磁盘 print(知识库向量化完成已保存至 ./chroma_db)运行这个脚本后你的所有文档知识就被处理并存储在了./chroma_db目录中。4.3 构建检索问答链接下来我们构建一个可以接受用户查询并返回答案的链。# rag_query.py from langchain.embeddings.sentence_transformer import SentenceTransformerEmbeddings from langchain.vectorstores import Chroma from langchain.chains import RetrievalQA from langchain_community.llms import Ollama # 假设使用本地Ollama运行的Llama3 # 如果使用OpenAI则替换为 # from langchain_openai import ChatOpenAI # 1. 加载已存在的向量数据库 embedding_function SentenceTransformerEmbeddings(model_nameall-MiniLM-L6-v2) vector_db Chroma(persist_directory./chroma_db, embedding_functionembedding_function) # 2. 初始化大语言模型 # 使用本地Ollama模型需提前在本地运行Ollama并pull模型 llm Ollama(modelllama3:8b, temperature0.1) # temperature调低使输出更确定 # 如果使用OpenAI则替换为 # llm ChatOpenAI(model_namegpt-3.5-turbo, temperature0) # 3. 创建检索问答链 qa_chain RetrievalQA.from_chain_type( llmllm, chain_typestuff, # 最常用的方式将所有检索到的上下文“塞”进提示词 retrievervector_db.as_retriever( search_typesimilarity, # 相似度搜索 search_kwargs{k: 4} # 检索最相关的4个文本块 ), return_source_documentsTrue, # 返回源文档便于追溯 chain_type_kwargs{ prompt: PROMPT # 这里可以传入自定义的提示词模板后文会定义 } ) # 4. 自定义提示词模板以更好地控制模型行为 from langchain.prompts import PromptTemplate template 你是一个专业的产品知识助手。请严格根据以下提供的上下文信息来回答问题。如果上下文信息不足以回答问题请直接说“根据已知信息无法回答该问题”不要编造任何信息。 上下文信息 {context} 问题{question} 请用中文给出清晰、准确的回答 PROMPT PromptTemplate( templatetemplate, input_variables[context, question] ) # 5. 问答函数 def ask_question(question): result qa_chain({query: question}) print(f问题{question}) print(f\n答案{result[result]}) print(f\n来源参考) for i, doc in enumerate(result[source_documents]): print(f[{i1}] 来自文件{doc.metadata.get(source, 未知)} (片段内容摘要{doc.page_content[:100]}...)) print(- * 50) # 6. 测试 if __name__ __main__: ask_question(我们产品的主要优势是什么) ask_question(如何配置产品的XX功能) ask_question(请告诉我明天的天气。) # 一个知识库外的问题运行rag_query.py你就可以与你的产品文档知识库进行对话了。对于知识库内的问题它会基于文档生成答案并列出来源对于知识库外的问题如天气它会按照提示词要求回答“无法回答”。5. 生产环境挑战与常见问题排查将RAG从Demo推向生产会遇到一系列更复杂的问题。以下是典型问题及解决思路。5.1 检索效果不佳总是找不到正确答案问题表现回答明显错误或答非所问检查发现检索到的文档不相关。排查与解决检查文本切分这是最常见的原因。查看检索到的原始文本块是否因为切分过碎导致信息不完整或者切分过大导致关键信息被淹没调整chunk_size和chunk_overlap参数并考虑按章节、标题等语义边界进行切分。评估嵌入模型你的嵌入模型是否适合你的文本领域尝试用一些标准问题-文档对测试不同嵌入模型如text-embedding-ada-002vsbge-large-zh的检索召回率。引入混合检索在向量检索的基础上增加关键词如BM25检索。对于包含具体产品型号、代码、错误码的查询关键词检索往往更直接有效。优化查询实现一个“查询理解”层。在用户查询送入检索器之前先用一个小模型对其进行重写、扩展或纠错。例如将口语化的“咋用”扩展为“如何使用”。5.2 大模型无视上下文依然产生幻觉问题表现检索到了正确的文档但模型生成的答案却包含了文档中没有的内容。排查与解决强化提示词指令在提示词中明确、强硬地要求模型“必须且仅能”依据上下文。使用“严禁”、“不得”等词汇。可以尝试让模型分两步思考“第一步从上下文中找出所有相关事实。第二步基于这些事实组织答案。”检查上下文长度和位置如果检索到的上下文太长或太靠后模型可能会“忽略”。尝试减少k值只保留最相关的1-3个片段。或者在构造提示词时将最关键的上下文放在最前面。更换或微调模型不同模型遵循指令的能力不同。一般来说更大的模型如GPT-4比小模型如某些7B模型更“听话”。如果使用开源模型可以考虑用你的领域数据对模型进行指令微调强化其遵循上下文回答的能力。后处理校验增加一个校验步骤用另一个模型或规则检查生成答案中的关键事实是否都能在提供的上下文中找到出处。5.3 系统响应速度慢延迟高问题表现从提问到获得答案耗时过长如5秒用户体验差。排查与解决向量检索优化索引类型在向量数据库如Chroma中尝试不同的索引类型如HNSW在构建速度和检索速度、精度之间取得平衡。量化使用向量量化技术在可接受的精度损失下大幅减少向量存储空间和计算距离的时间。大模型推理优化模型量化对本地部署的LLM使用GPTQ、AWQ等量化技术将模型从FP16转换为INT4/INT8能显著提升推理速度并降低显存消耗。推理引擎使用vLLM、TGI等高性能推理引擎它们支持连续批处理、PagedAttention等技术能极大提高吞吐量。架构异步化将检索、LLM调用等耗时操作设计为异步流程避免阻塞。对于Web应用可以使用像LangChain的RunnableLambda配合异步框架。5.4 如何处理多模态与复杂文档问题场景知识库中包含大量图片、表格的PDF或PPT文件单纯提取文字丢失了大量关键信息。解决思路使用多模态加载器采用Unstructured库或Azure Document Intelligence等服务它们能更好地解析PDF中的版面信息将文字、表格转为Markdown格式、图片描述通过OCR一起提取出来。多模态嵌入与检索对于图片可以使用CLIP等模型进行图像编码与文本向量一起存入多模态向量数据库。当用户查询涉及图表内容时系统可以同时检索相关的文本和图像片段。多模态生成使用GPT-4V、Gemini Pro Vision等多模态大模型作为生成器。在提示词中不仅可以提供文本上下文还可以提供检索到的相关图片的Base64编码让模型“看到”并描述图表内容。RAG技术正在快速发展新的模式和优化方法层出不穷如更复杂的递归检索、智能路由判断问题类型选择不同检索策略、自省式RAG让模型评估检索结果的质量并决定是否重试等。但万变不离其宗核心依然是高质量的知识预处理、精准的检索和可控的生成。从本文介绍的基础架构出发理解每个环节的原理和调优方法你就能搭建出适合自己业务场景的、可靠的“外挂知识库”系统。在实际项目中我最大的体会是不要一味追求最前沿的论文方案而是要先构建一个端到端可运行的基线系统然后通过扎实的评估和迭代针对你最痛的瓶颈点进行优化这样才能最高效地让大模型真正为你所用。
返回列表