RAG实战:从零搭建企业知识库问答系统
在日常业务中我们积累了大量文档、手册、聊天记录、工单和内部规范真正需要用的时候却经常搜不到、找不到、答不准。把大模型直接接进来它虽然能说会道但对自己不知道的企业内部知识经常会一本正经地“编答案”。解决这个问题的常用方案就是 RAG。这篇文章会从 RAG 的核心概念讲起带着你从环境准备、原理拆解、代码实现、效果优化一直走到常见问题排查尽量用一套闭环的流程把知识库搭建这件事讲透。1. 为什么企业知识库需要 RAG1.1 大模型看似强大但有两个明显短板通用大模型经过海量数据的预训练确实具备了很强的语言理解、逻辑推理和文本生成能力。但当我们拿它做企业内部问答时通常会遇到两类问题第一类是“不知道”企业内部的产品文档、运维记录、项目复盘、客服话术这部分内容不会出现在大模型的公开训练数据里。模型没见过的知识它自然无法准确回答。第二类是“不懂装懂”大模型本质上是在做下一个词的预测当它没有足够依据时会倾向于生成一段听起来流畅、但内容可能是虚构的回答这就是我们常说的“幻觉”。如果直接拿通用大模型去做企业知识问答效果一定不稳定。你问它一个内部系统的上线时间它可能给你编一个日期出来你问它某个流程的负责人它可能给你捏造一个人名。这在生产环境中是不可接受的。1.2 RAG 的基本思路RAG 的全称是 Retrieval-Augmented Generation中文叫“检索增强生成”。核心思想非常直白在让大模型回答问题之前先从一个外部知识库中检索出与问题相关的资料片段把这些片段作为上下文一起交给大模型让大模型基于“检索到的证据”来生成答案。可以把它理解为给大模型开卷考试。模型不需要把所有知识背下来只需要知道去哪里翻资料以及如何根据资料进行归纳总结。这样既能缓解幻觉问题也能让模型回答企业内部的最新信息因为知识库的内容是可以随时更新的。1.3 RAG 与微调的区别不少同学会问为什么不用微调Fine-tuning呢微调是把新知识“存进”模型的参数里适合学习某种表达风格、输出格式、专业术语但它需要准备大量高质量的训练样本训练成本高而且更新知识时需要重新训练。RAG 不需要修改模型参数知识以文本形式放在外部向量库中更新知识只需要增删改文档成本低、见效快特别适合企业内部文档问答、客服辅助、知识管理这类场景。微调和 RAG 并不是互斥关系。实际项目中有人会先用 RAG 解决知识来源问题再用微调统一回答风格和输出格式。但对于大多数知识库需求RAG 是最快落地的方案。2. 环境准备与版本说明在动手写代码之前先把运行环境准备好。这里以 Python 示例为主因为 RAG 生态里大部分工具链都对 Python 支持得最好。2.1 基础运行环境操作系统Windows 10/11、macOS、Linux 都可以本文示例代码不依赖特定系统。Python 版本建议 3.9 或以上。如果电脑里有多个 Python 版本推荐用 conda 或 venv 单独创建虚拟环境避免依赖冲突。包管理工具pip或者使用 poetry、uv 这类更现代的依赖管理工具。版本需要根据你的项目实际情况调整本文示例以常见环境为例重点演示配置思路不要把某一个版本号当成硬性规定。2.2 安装核心依赖需要安装的核心库包括LangChain 或 LlamaIndex负责编排 RAG 流程。向量数据库客户端比如 Chroma、FAISS、Milvus、Qdrant、pgvector。Embedding 模型库比如 sentence-transformers。大模型 API SDK 或本地推理依赖。如果暂时没有大模型 API可以先使用 OpenAI 兼容接口也可以部署本地模型代替。文章里的代码会尽量把模型调用部分封装成配置项方便替换。pip install langchain langchain-community langchain-openai pip install chromadb faiss-cpu sentence-transformers pip install pypdf docx2txt这里简单说明一下每个库的作用langchain核心编排库提供文档加载、文本分割、向量存储、检索链等模块。langchain-community社区维护的第三方集成。langchain-openai用来调用 OpenAI 兼容接口如 GPT 系列或国内支持该协议的模型。chromadb/faiss-cpu向量数据库和向量索引库二选一或都用都可以。sentence-transformers加载本地 Embedding 模型。pypdf、docx2txt解析 PDF 和 Word 文档。2.3 模型选型建议RAG 流程中最核心的模型有两类Embedding 模型负责把文本转换成向量。如果你的场景是中英文混合可以考虑 BGE、M3E、text-embedding-ada-002 等如果只处理英文选择面会更广。本地部署时要注意显存和推理速度线上 API 则要关注调用成本和单位时间限额。生成模型负责最终回答。可以使用 OpenAI 的 GPT 系列也可以使用国内大模型平台的 API还可以通过 Ollama、vLLM 等工具本地部署开源模型。这里不绑定任何一家厂商重点是理解模型在链路里的角色。实际选型时需要综合考虑成本、数据合规、响应速度和回答质量。2.4 示例项目结构本文实战部分会按照下面的目录组织代码rag_demo/ ├── config.py # 全局配置包括模型名称、向量库路径等 ├── requirements.txt # Python 依赖 ├── build_knowledge.py # 知识库构建脚本 ├── query_knowledge.py # 问答检索脚本 ├── rerank_demo.py # Rerank 排序优化示例 └── docs/ # 存放需要入库的文档3. 核心原理拆解在写代码之前我们需要先把 RAG 的关键环节逐个拆开理解每一步在做什么以及为什么这样做。3.1 文档加载RAG 的第一步是把各种格式的资料读取成纯文本。常见的格式包括Markdown、TXT、PDF、Word、HTML甚至数据库中的文本字段。不同格式有不同的解析库。PDF 在解析时容易出现表格错乱、多栏排版串行的问题Word 的 docx 格式本质上是 XML 压缩包用 python-docx 解析比较稳定HTML 则需要去除标签只提取正文内容。文档加载本身看似简单但却是知识库质量的重要起点。如果加载出来的文本是乱码或者缺字后面的分块和向量化都会受影响。3.2 文本分块大模型的上下文窗口是有限的向量检索的匹配粒度也不适合整篇文档直接入库。所以我们需要把长文档切成一个个“块”。分块没有绝对正确的参数通常根据业务场景调整。比如按固定字符数切分比如每块 300 到 800 字块与块之间设置重叠区域。按段落切分以 Markdown 标题或空行为边界。按语义切分使用 embedding 计算句子相似度把相似内容聚合在一起。分块太小检索到的上下文信息不完整模型可能看不懂前因后果分块太大检索精度下降而且可能塞进很多无关内容浪费上下文窗口。实践中需要反复测试。3.3 向量化向量化是指用 Embedding 模型把一段文本转换成一串浮点数。比如一个 768 维的向量可以粗略理解为文本在语义空间中的坐标。向量化的关键要求是语义相近的文本向量距离也应该相近。这样当用户输入一个查询问题时系统才能通过向量相似度找到最相关的文本块。Embedding 模型和生成模型是两回事。不要以为“问答模型很聪明所以向量化也用它”Embedding 有专门的模型需要根据语言、领域、效果做选择。3.4 向量存储向量化之后文本块对应的向量需要被保存下来。向量数据库的核心能力是支持高性能的相似度检索。常见的向量库包括Chroma轻量、适合本地学习和原型开发。FAISSMeta 开源的向量索引库性能高常与 LangChain 搭配使用。Milvus分布式向量数据库适合大规模生产环境。QdrantRust 写的向量数据库性能不错部署也简单。pgvectorPostgreSQL 的扩展适合已经在用 PostgreSQL 的团队。选择向量库时要考虑数据量、并发量、部署复杂度、运维成本和团队熟悉度。小项目用 Chroma 或 FAISS 足够在线服务化场景则建议使用 Milvus、Qdrant 或云厂商提供的向量数据库。3.5 检索与生成用户输入问题后系统会把问题也用同一个 Embedding 模型转成向量然后到向量库里做相似度检索取回 top-k 个最相关的文本块。接下来系统把这些文本块拼接成 Prompt和用户问题一起发送给大模型。大模型根据给定资料生成最终答案。这个流程看起来简单但工程化之后会有很多细节如何做多路召回、如何做重排序、如何处理无答案的情况、如何设计 Prompt 让模型只依据资料回答这些都会直接影响最终效果。4. 手把手实现一个完整 RAG 知识库下面进入实操环节。我们会实现一个最简但完整可运行的 RAG 流程包含知识库构建和问答检索两个脚本。4.1 创建项目结构先在任意目录下创建项目文件夹mkdir rag_demo cd rag_demo然后在rag_demo下创建docs目录放入几篇测试文档比如公司产品介绍、操作手册等格式不限txt、md、pdf 都可以。同时创建requirements.txtlangchain0.2.0 langchain-community0.2.0 langchain-openai0.1.0 chromadb0.4.0 pypdf4.0.0 docx2txt0.8 sentence-transformers2.2.0版本号只是参考实际安装时以你环境能解析到的最新稳定版本为准。4.2 编写全局配置创建config.py用来统一管理模型名称、向量库持久化路径等参数# 文件路径rag_demo/config.py import os # 这里假设你使用的是 OpenAI 兼容接口 # 如果使用本地模型或国内大模型请按实际地址和 key 修改 LLM_API_KEY os.getenv(LLM_API_KEY, your-api-key) LLM_BASE_URL os.getenv(LLM_BASE_URL, https://api.openai.com/v1) LLM_MODEL os.getenv(LLM_MODEL, gpt-4o-mini) # Embedding 模型这里使用本地模型避免上传文档内容到外部服务 EMBEDDING_MODEL os.getenv(EMBEDDING_MODEL, BAAI/bge-small-zh-v1.5) # 向量库持久化目录 PERSIST_DIR os.getenv(PERSIST_DIR, ./chroma_db) # 检索返回的文本块数量 TOP_K 4这里把 API Key 的读取方式设置成环境变量避免把密钥直接写在代码里。Embedding 模型用了 BGE 系列的中文模型本地运行不需要额外申请接口。4.3 编写知识库构建脚本创建build_knowledge.py核心逻辑包括加载文档、文本分块、向量化、写入向量库。# 文件路径rag_demo/build_knowledge.py from langchain_community.document_loaders import DirectoryLoader, TextLoader from langchain.text_splitter import RecursiveCharacterTextSplitter from langchain_community.embeddings import HuggingFaceEmbeddings from langchain_community.vectorstores import Chroma from config import EMBEDDING_MODEL, PERSIST_DIR def build_knowledge_base(): # 1. 加载 docs 目录下的所有文本文件 loader DirectoryLoader( ./docs, glob**/*.txt, loader_clsTextLoader, loader_kwargs{encoding: utf-8}, ) documents loader.load() print(f加载到 {len(documents)} 个文档) # 2. 文本分块 text_splitter RecursiveCharacterTextSplitter( chunk_size400, chunk_overlap80, separators[\n\n, \n, 。, , , , , , ], ) chunks text_splitter.split_documents(documents) print(f分块后共 {len(chunks)} 个文本块) # 3. 初始化本地 Embedding 模型 embeddings HuggingFaceEmbeddings(model_nameEMBEDDING_MODEL) # 4. 构建向量库并持久化 vectorstore Chroma.from_documents( documentschunks, embeddingembeddings, persist_directoryPERSIST_DIR, ) vectorstore.persist() print(f向量库已写入 {PERSIST_DIR}) if __name__ __main__: build_knowledge_base()这段代码里需要注意几个点DirectoryLoader可以批量加载目录下的文件。这里以.txt为例如果你有 PDF 和 Word则需要扩展 loader。如果要加载 PDF可以使用PyPDFLoaderfrom langchain_community.document_loaders import PyPDFLoader loader PyPDFLoader(docs/产品手册.pdf) documents loader.load()RecursiveCharacterTextSplitter是常用的文本分割器。它按优先级顺序尝试用不同分隔符切分文本尽量保留语义完整的块。chunk_size400表示块的大致字符数chunk_overlap80表示相邻块之间有 80 个字符的重叠避免切断关键信息。4.4 编写问答检索脚本创建query_knowledge.py核心逻辑包括加载向量库、问题向量化、相似度检索、拼接 Prompt、调用大模型生成回答。# 文件路径rag_demo/query_knowledge.py from langchain_community.embeddings import HuggingFaceEmbeddings from langchain_community.vectorstores import Chroma from langchain_openai import ChatOpenAI from langchain_core.prompts import ChatPromptTemplate from langchain_core.output_parsers import StrOutputParser from langchain_core.runnables import RunnablePassthrough from config import EMBEDDING_MODEL, PERSIST_DIR, LLM_API_KEY, LLM_BASE_URL, LLM_MODEL, TOP_K def create_rag_chain(): # 1. 加载已有向量库 embeddings HuggingFaceEmbeddings(model_nameEMBEDDING_MODEL) vectorstore Chroma( persist_directoryPERSIST_DIR, embedding_functionembeddings, ) # 2. 构造检索器 retriever vectorstore.as_retriever(search_kwargs{k: TOP_K}) # 3. 初始化大模型 llm ChatOpenAI( modelLLM_MODEL, api_keyLLM_API_KEY, base_urlLLM_BASE_URL, temperature0.2, ) # 4. 定义 Prompt 模板 prompt ChatPromptTemplate.from_messages([ (system, 你是一个严谨的问答助手。请只根据下面的资料回答问题 不要编造资料中没有的内容。如果资料不足以回答请直接说明资料中没有相关信息。\n\n 资料内容\n{context}), (human, 用户问题{question}), ]) # 5. 组装 RAG 链路 rag_chain ( {context: retriever, question: RunnablePassthrough()} | prompt | llm | StrOutputParser() ) return rag_chain if __name__ __main__: chain create_rag_chain() while True: question input(请输入问题输入 exit 退出) if question.strip().lower() exit: break answer chain.invoke(question) print(回答:, answer) print(- * 50)这里的核心是rag_chain的组装过程{context: retriever, question: RunnablePassthrough()}表示把用户问题同时传给检索器和下游。retriever负责检索相关文本块结果会作为上下文传入 Prompt。| prompt将检索结果和原始问题填充进 Prompt 模板。| llm调用大模型生成答案。| StrOutputParser()将模型输出解析成纯文本。4.5 运行与验证在docs目录下准备一个测试文件demo.txt内容例如企业知识库系统支持文档上传、自动分块、语义检索和智能问答功能。 系统采用 RAG 架构可以对接多种大模型接口。 知识库更新后无需重新训练模型只需要重新导入文档即可生效。然后依次运行python build_knowledge.py python query_knowledge.py运行build_knowledge.py时如果一切正常你会看到类似输出加载到 1 个文档 分块后共 3 个文本块 向量库已写入 ./chroma_db运行query_knowledge.py后输入问题请输入问题知识库更新后需要重新训练模型吗正常情况下大模型应该基于检索到的文本块回答“不需要重新训练”而不会凭空编造。整个流程跑通后你已经拥有一个最简 RAG 知识库的骨架。接下来要做的就是优化效果、补全工程能力、接入真实业务数据。5. 检索质量优化Rerank 与混合检索基础版本的 RAG 可以运行但遇到真实业务数据时检索质量往往不够用。常见问题包括检索结果前几名不相关、关键信息被分散在不同块里、问题表述和文档写法差异大导致匹配失败。下面介绍两个常用的优化手段。5.1 为什么需要 Rerank向量检索速度快但它的相似度计算是“粗排”并不能完全代表答案的相关性。比如用户问“系统的登录超时时间怎么配置”向量检索可能召回一段介绍系统架构的文档因为里面提到了“登录”和“时间”但并不是真正的配置说明。Rerank 的思路是先用向量检索快速召回 top-20 或 top-50 的候选块再用一个更强大的排序模型逐条计算问题和文本块的相关性重新排序后只保留 top-5。这样既能利用向量检索的速度又能利用重排序模型的精度。5.2 Rerank 实现示例可以使用FlagEmbedding中的 BGE-Reranker 模型。安装依赖pip install FlagEmbedding示例代码如下# 文件路径rag_demo/rerank_demo.py from FlagEmbedding import FlagReranker # 加载本地 rerank 模型 reranker FlagReranker(BAAI/bge-reranker-base, use_fp16True) def rerank_documents(query: str, documents: list[str], top_k: int 3): # 构造 (query, document) 的配对 pairs [[query, doc] for doc in documents] # 计算相关度分数 scores reranker.compute_score(pairs) # 按分数从高到低排序 sorted_results sorted( zip(documents, scores), keylambda x: x[1], reverseTrue, ) return sorted_results[:top_k] if __name__ __main__: # 模拟检索器返回的原始候选文本 candidates [ 系统默认登录超时时间为30分钟可在配置文件中修改。, 系统支持多种登录方式包括账号密码和单点登录。, 配置文件位于 etc 目录下修改后需要重启服务。, ] query 登录超时时间在哪里配置 top_results rerank_documents(query, candidates, top_k2) for doc, score in top_results: print(f分数: {score:.4f} | 文本: {doc})Rerank 模型的推理成本比 Embedding 高所以通常只对 top-k 候选结果做重排而不是对全量文档做重排。5.3 混合检索与多路召回向量检索擅长语义匹配但它对关键词、编号、代码片段、精确术语的匹配并不总是理想。比如用户搜索“错误码 40001”向量检索可能不理解这个具体编号的含义但关键词检索可以精确命中。混合检索的思路是同时使用关键词检索和向量检索再把两路结果合并去重、重新排序。在 LangChain 中可以通过EnsembleRetriever实现from langchain.retrievers import EnsembleRetriever from langchain_community.retrievers import BM25Retriever from langchain_community.vectorstores import Chroma from langchain_community.embeddings import HuggingFaceEmbeddings from config import EMBEDDING_MODEL, PERSIST_DIR # 构造向量检索器 embeddings HuggingFaceEmbeddings(model_nameEMBEDDING_MODEL) vectorstore Chroma(persist_directoryPERSIST_DIR, embedding_functionembeddings) vector_retriever vectorstore.as_retriever(search_kwargs{k: 10}) # 构造 BM25 关键词检索器 bm25_retriever BM25Retriever.from_texts( [系统默认登录超时时间为30分钟。, 配置文件位于 etc 目录下。] ) bm25_retriever.k 10 # 融合两路检索结果 ensemble_retriever EnsembleRetriever( retrievers[bm25_retriever, vector_retriever], weights[0.3, 0.7], )BM25 是经典的关键词检索算法可以把它理解为“升级版的关键词匹配”。混合检索能兼顾语义和关键词但检索结果的融合策略需要根据实际数据调参。6. 从演示到工程化Agentic RAG 与开源框架当基础 RAG 跑通之后下一个问题是怎么把它变成一个真正能用的产品6.1 什么是 Agentic RAG传统的 RAG 是“一次检索、一次生成”的直线流程。Agentic RAG 则引入 Agent 的概念让系统具备判断、规划和多步检索的能力。比如用户问“今年第二季度客户投诉最多的是哪类问题”简单的 RAG 很难回答这种需要多步聚合的问题。Agentic RAG 可以先把问题拆解成多个子查询分别检索“二季度投诉记录”和“投诉分类标准”再根据检索结果综合回答。Agentic RAG 的优点是更灵活能处理复杂问题缺点是链路变长、稳定性下降、Token 消耗增加。建议先把基础 RAG 的效果做稳定再考虑引入 Agent 能力。6.2 开源知识库框架的选择如果不想从零开发可以使用一些成熟的开源框架快速搭建Dify提供了可视化的工作流编排可以配置知识库、模型、Agent适合快速搭建业务应用。搜索热词中提到的“Dify 完成政务 RAG 知识库实践”本质上就是利用 Dify 的可视化流程快速落地一套知识库再针对政务数据做清洗和权限控制。RAGFlow深度文档理解的 RAG 引擎对 PDF 表格、版面解析做得比较好。AnythingLLM适合个人和团队快速搭建私有知识库。这些框架的优点是上手快、功能全缺点是定制自由度不如自己写代码。实际项目中可以把它们当作快速原型工具等流程验证通过后再决定是否自研。6.3 知识库工程化的关键模块除了核心的 RAG 链路工程化还需要关注文档更新支持定时任务或事件触发增量更新向量库。权限控制不同角色只能检索自己权限范围内的文档。日志和监控记录每一次检索的召回结果、最终答案、用户反馈。反馈闭环让用户对回答点赞或点踩把高质量问答沉淀成评测集。这些模块可以和公司现有的运维体系、账号体系做集成而不只是单独运行一个问答服务。7. 常见问题与排查思路在 RAG 知识库的搭建和上线过程中很多问题都是重复出现的。下面整理一份高频问题清单方便排查。问题现象常见原因解决思路回答内容与知识库无关检索召回结果不相关检查 Embedding 模型效果、分块大小、top_k加入 Rerank模型仍然编造答案Prompt 未强调只能基于资料回答在 Prompt 中明确“资料中没有就回答不知道”检索结果全是同一个文档文档分块过大或向量库索引异常减小 chunk_size增加检索结果的多样性文档更新后检索不到新内容向量库没有增量更新建立增量导入流程更新后重新写入向量库本地部署 Embedding 模型速度慢模型过大或 CPU 推理使用更小的模型或部署 GPU 推理服务PDF 表格内容识别混乱PDF 解析器对表格支持不佳尝试不同解析工具或先转成 Markdown 再入库API 调用超时网络或大模型响应过慢设置超时重试考虑流式输出更换更快的模型单条知识太长导致上下文爆炸分块过大或检索结果过多调小 chunk_size减少 top_k启用 Rerank 压缩上下文下面展开讲几个最常见的问题。7.1 模型回答“一本正经地胡说八道”即使加了 RAG模型仍然可能编造答案。常见原因是 Prompt 没有明确约束。建议在系统 Prompt 中加入类似表述你是一个严谨的问答助手。请只根据给定的资料内容回答问题。 如果资料中没有足够的信息请明确回答“资料中没有相关信息” 不要自行推断或编造答案。如果加了约束还是出现幻觉可以检查检索到的上下文是否真的包含答案。有时候是检索环节根本没召回正确内容模型在“没有资料”的情况下被迫硬答。7.2 文档导入后检索不到这种情况通常是因为向量库没有更新。如果你的build_knowledge.py是重新创建向量库那就需要重新运行构建脚本。如果用了持久化存储需要确认是否可以增量添加文档。增量新增文档的示例思路from langchain_community.vectorstores import Chroma from langchain_community.embeddings import HuggingFaceEmbeddings from config import EMBEDDING_MODEL, PERSIST_DIR embeddings HuggingFaceEmbeddings(model_nameEMBEDDING_MODEL) vectorstore Chroma(persist_directoryPERSIST_DIR, embedding_functionembeddings) # new_docs 是经过分块后的新文档列表 vectorstore.add_documents(new_docs) vectorstore.persist()7.3 Embedding 模型选择不当不同 Embedding 模型的语义理解能力差异很大。通用模型可能在专业领域的效果不佳如果知识库内容偏垂直领域可以尝试领域微调过的 Embedding 模型。评估 Embedding 效果的方式可以很简单准备一批问题人工判断检索结果是否相关统计命中率。有条件的团队可以构建标准评测集把“问题-正确答案块”作为测试数据。7.4 Dify 升级后知识库保存报错如果你使用的是 Dify可能会遇到升级后无法保存知识库或修改知识库时报 Internal Server Error。这类问题大多数和数据库结构变更、版本不匹配有关。建议先查看 Dify 容器日志确认具体报错信息。常见处理方式包括检查 Docker 镜像版本和数据库迁移是否完成。查看向量数据库连接配置是否改变。备份数据后重新执行数据库迁移命令。遇到这类问题优先翻日志不要盲目重置数据。8. 最佳实践与工程建议RAG 知识库的难点不在跑通 demo而在于上线后效果稳定、数据可靠、运维可控。下面是一些从实际项目中沉淀下来的建议。8.1 知识库质量管理知识库的输入质量决定输出质量。建议在导入前做数据清洗去重同一份文档反复导入会导致检索冗余。格式统一统一标题层级、段落分割、标点符号。去除噪声删除页眉页脚、水印、广告、无关链接。敏感信息处理在导入前识别并脱敏身份证号、手机号、银行账号等信息。8.2 检索策略的调优优先级如果回答效果不好调优顺序应该是先看数据质量文档是否准确、完整、最新。再看分块策略chunk 大小和 overlap 是否合理。然后看检索策略top_k、混合检索、Rerank 是否需要。最后看 Prompt模型是否理解了“只依据资料回答”的约束。再看生成模型是否需要换更大的模型或本地微调。很多人一上来就换大模型其实大部分效果问题都出在数据、分块和检索环节。8.3 安全与权限企业知识库通常包含敏感数据需要注意以下几点最小权限原则用户只能访问与其角色相关的文档。数据合规在使用云 API 时确认文档内容是否可以上传至第三方服务。如果不能需要本地部署 Embedding 模型和生成模型。审计日志记录每一次问答的内容、检索结果和使用者方便追溯。防注入用户可能在问题中写入攻击性 Prompt需要做输入过滤和输出校验。8.4 评估体系建设没有评测就没有优化方向。建议从第一天就沉淀评测集。评测集可以是 CSV 格式包含“问题、标准答案、相关文档标题”。每次改动后跑一遍评测集统计回答准确率、检索命中率、幻觉率等指标。question,answer,source_doc 登录超时时间在哪里配置,系统默认登录超时时间为30分钟可在配置文件中修改,系统配置手册.md 如何添加新用户,在用户管理页面点击新增用户并填写信息,用户操作指南.md评估既可以用人工抽样也可以让大模型辅助打分但最终要有人工确认。8.5 成本控制RAG 的成本主要来自 Embedding 调用、向量存储、大模型生成和 Rerank 模型。优化方向包括缓存高频问题相同或相似问题直接返回缓存答案。压缩上下文只把 Rerank 之后最相关的文本块传给大模型。本地部署小模型对简单问题用小模型回答复杂问题再用大模型。批处理 Embedding建库时批量向量化降低接口调用次数。9. 总结与下一步这篇文章从 RAG 的基本概念开始逐步拆解了文档加载、文本分块、向量化、向量存储、检索、生成这几个核心环节并带你实现了一个完整的本地知识库问答系统。在此基础上又补充了 Rerank、混合检索、Agentic RAG、开源框架选型和工程化建议覆盖了从入门到落地的主要路径。如果你刚开始学先把 demo 跑通理解流程里的每一个模块然后拿一份真实业务数据做效果测试。遇到问题不要急着换模型优先排查文档质量和检索效果。下一步可以深入研究 Embedding 模型选型、Rerank 排序、评估体系建设、以及 LangChain 或 LlamaIndex 的进阶用法。如果项目场景比较复杂再考虑学习 Dify、RAGFlow 等开源框架用可视化方式提升开发效率或者调研 Agentic RAG 在多步问答中的落地方式。动手实践是掌握 RAG 最快的方式。你可以先从自己的文档开始搭一个私人知识库再逐步扩展到团队和企业场景。如果这篇文章对你有帮助欢迎收藏备用也欢迎在评论区交流搭建过程中遇到的问题。