☰
RAG知识库问答系统实战:从文本分段到部署
2026/10/28 6:47:05 网站建设 项目流程

在开始写正文之前,我想先和你明确一个关键问题:这类“把特定领域知识做成 AI 问答应用”的项目,在技术圈里其实非常典型。它的核心并不是宗教文本本身,而是一套完整的 RAG(检索增强生成)工程链路:从文本数字化、分段、向量化,到检索、重排序、大模型生成,再到内容校验和部署上线。这篇文章我会以 Sikhbani.ai 为引子,把这一类“特定文本 + AI 问答”项目的完整实现思路、技术选型、代码示例和工程坑点都拆开讲清楚。

如果你正准备做一个基于某本书、某个文档集、某个知识库的 AI 问答系统,这篇文章应该能帮你少走不少弯路。

1. 这篇文章真正要解决的问题

先问一个最实际的问题:你为什么要关注 Sikhbani.ai 这个项目?

表面上,它是一个“询问 Sri Guru Granth Sahib”的 AI 工具,核心功能是让用户用自然语言提问,然后基于锡克教经典文本给出回答。但如果我们把宗教背景剥离掉,这个项目的本质是一个典型到不能再典型的RAG 应用:把一本或多本特定书籍数字化,切分成块,建立索引,然后用大模型做检索式问答。

这个模式并不是什么新鲜事。过去两年里,类似的“把 X 变成 AI 问答机器人”的项目你肯定见过不少,比如:

  • 把公司内部技术文档做成 AI 客服;
  • 把法律条文做成 AI 法律助手;
  • 把产品说明书做成 AI 售后问答;
  • 把一本学术专著做成 AI 阅读助手。

它们的底层逻辑完全一样。所以,Sikhbani.ai 真正的价值,与其说是在宗教领域,不如说它是RAG 应用开发的一个可参考样本。

那么,这类项目到底解决了什么痛点?

在没有 RAG 之前,如果我们想基于一本书做问答,只能靠人肉翻阅,或者做关键词搜索。关键词搜索的体验很生硬,比如你输入“什么是业力”,传统搜索引擎返回的是包含“业力”这个词的片段,但很可能不包含你真正想知道的内容。而 RAG 的流程是:先把你的问题转换成向量,然后在文本库里做语义检索,找到相关内容,再交给大模型生成一个连贯、自然的回答。

这中间最大的变化是:从关键词匹配变成了语义理解。这也是为什么这类项目值得技术人关注。

本文会从以下几个方面展开:

  1. 拆解 Sikhbani.ai 这类项目的核心架构,重点讲 RAG 的链路;
  2. 讲清楚数据准备阶段有哪些坑,尤其是长文本分段策略;
  3. 给出一个最小可运行的代码示例,包括文本加载、向量化、检索和问答;
  4. 说明如何在本地验证效果;
  5. 列出常见问题和排查思路;
  6. 最后,给出生产环境部署时的一些工程建议。

如果你是 AI 应用开发者、准备做知识库问答系统的工程师、或者正在学习 RAG 技术,这篇文章值得收藏备用。

2. Sikhbani.ai 类项目的核心架构与原理

2.1 它本质上是一个什么系统

Sikhbani.ai 从功能上看是一个问答系统。但它的底层,是一套完整的知识库问答系统,通常包含以下模块:

  • 数据源:原始文本,如电子书、文档、网页抓取内容、PDF 扫描件。
  • 文档处理器:负责把原始文本清洗、分段、格式化。
  • 向量化模块:把文本转换成向量表示,供后续语义检索使用。
  • 向量数据库:存储向量,并支持高效的相似度检索。
  • 检索模块:接收用户问题向量,从向量库中找出最相关的文本块。
  • 生成模块:把检索到的文本块拼接到 Prompt 中,调用大模型生成最终回答。
  • 校验与后处理:检查回答是否基于提供的资料,是否包含幻觉内容。

其中,最核心的链路是检索增强生成(Retrieval-Augmented Generation,RAG)。

2.2 什么是 RAG,为什么它必须存在

这里需要多解释一下 RAG,因为它是整个系统的地基。

大语言模型(LLM)虽然强大,但它有一个天生的局限:它的知识来自训练数据,所以它并不知道你给它的那本书里的具体内容。你不能指望一个训练好的模型记住《Sri Guru Granth Sahib》几百年前原文的每一个细节,更不可能指望它记住你公司内部的技术文档。

解决这个问题有两个思路:

  1. 微调(Fine-tuning):把书里的知识直接训练进模型参数里。这个方案成本高、周期长,而且一旦书的内容更新,又得重新训练。
  2. RAG:不改变模型参数,而是在问答时先把相关资料“检索”出来,再把这些资料连同问题一起交给模型,让它基于资料回答。

RAG 是目前更主流、更轻量的方案。它的优点很明显:

  • 答案可溯源,模型可以说“根据检索到的文本,原文是……”
  • 资料更新时,只需要刷新向量库,不需要重训模型;
  • 对模型本身的要求不高,可复用现有大模型 API。

Sikhbani.ai 这类项目之所以能落地,核心就是因为 RAG 能有效解决“模型不知道特定文本内容”的问题。

2.3 完整流程是什么样的

以“询问 Sri Guru Granth Sahib”中的一个问题为例,整个流程如下:

  1. 用户输入问题(比如“关于慈悲,经典里是怎么说的?”)。
  2. 系统将问题文本转成向量。
  3. 系统在向量数据库中检索最相关的文档块,比如找到原文中关于慈悲的几个段落。
  4. 系统把这些问题和文档块组合成一个 Prompt,例如:
以下是从经典中检索到的内容: [内容块1] [内容块2] 请基于以上内容回答问题:关于慈悲,经典里是怎么说的? 如果检索内容中不包含答案,请说明没有找到相关资料。
  1. 大模型根据 Prompt 生成回答。
  2. 系统把回答返回给用户,同时可以附上来源引用。

这就是整个系统的核心逻辑。

2.4 需要特别留意的概念:向量与相似度检索

很多新手到这里会卡在“向量”这个概念上。

通俗理解:向量就是把一段文字变成一组数字。比如“慈悲”可以被编码成[0.12, 0.44, 0.87, ...],而“爱心”的向量可能和它距离很近。这样,系统就可以通过计算向量之间的距离(如余弦相似度)来判断两段文本语义是否相近。

你不需要自己实现向量化算法,目前主流的做法是调用现有的 Embedding 模型,比如:

  • OpenAI 的 text-embedding-3-small / text-embedding-3-large;
  • 开源的 BGE、M3E、text2vec 等模型;
  • 各云厂商提供的 Embedding API。

在代码里,你只需要调用一个接口,得到一串数组,然后存储到向量数据库里。

2.5 这一类项目与传统全文搜索的对比

维度传统全文搜索RAG 语义检索
匹配方式关键词/字面匹配语义匹配
对用户输入的要求必须包含关键词自然语言即可
回答形式返回片段列表生成连贯回答
是否能溯源能,直接定位原文能,但需要设计引用机制
实现复杂度较低较高
适合场景精确查找、版本管理问答、理解、总结

从这个表能看出,RAG 不是来替代全文搜索的,而是解决“自然语言问答”这个更高阶需求的。

3. 环境准备与前置条件

在动手写代码之前,我们需要把环境准备好。这里以一个本地开发环境为例,重点演示通用思路,具体版本以你实际项目为准。

3.1 基础环境

建议使用以下环境:

  • 操作系统:macOS / Linux / Windows(Windows 上注意路径和终端兼容性)
  • Python:3.10 或更高版本
  • 包管理工具:pip 或 poetry
  • 大模型 API:可调用 OpenAI 兼容接口或其他大模型接口(本地也可用 Ollama 等工具)
  • 向量数据库:项目初期可以用 Chroma、FAISS、Qdrant,支持本地运行,不需要单独部署服务

这里不推荐一上来就上分布式向量数据库,因为那会引入额外的运维成本。先用本地轻量方案把链路跑通,再根据数据量迁移到生产级组件。

3.2 安装依赖

创建一个虚拟环境,并安装必要的库。

python -m venv venv source venv/bin/activate # Windows 下用 venv\Scripts\activate pip install langchain langchain-community chromadb sentence-transformers pypdf python-dotenv openai

说明:

  • langchain:目前最流行的 RAG 开发框架,封装了很多常用组件;
  • langchain-community:提供社区支持的集成类;
  • chromadb:本地向量数据库;
  • sentence-transformers:用于加载开源 Embedding 模型;
  • pypdf:用于解析 PDF 文件;
  • python-dotenv:用于管理环境变量;
  • openai:调用 OpenAI 兼容接口。

3.3 配置环境变量

在项目根目录创建.env文件:

# .env OPENAI_API_KEY=sk-xxxxxxxxx OPENAI_BASE_URL=https://api.openai.com/v1

如果你使用的是国内云厂商的大模型服务,OPENAI_BASE_URL可以改成对应服务的地址。这里的重点是,我们要用 OpenAI 兼容的接口格式,这样代码可以复用。

加载环境变量:

from dotenv import load_dotenv load_dotenv()

4. 数据准备与文本分段策略

数据准备是整个项目中最容易被低估的环节。很多人以为把 PDF 喂进去就完事了,结果检索效果一塌糊涂。问题往往出在文本分段上。

4.1 数据清洗

原始文本通常是不干净的,尤其是扫描版 PDF:

  • 有页眉页脚、页码;
  • 有 OCR 识别错误;
  • 不同的章节之间有多余空白;
  • 可能包含注释、标点符号问题。

你需要先做清洗工作,正则表达式是最常用的工具。比如删除多余空行、去除页码、合并断行等。

import re def clean_text(text: str) -> str: # 去掉多余空格和空行 text = re.sub(r'\n\s*\n+', '\n', text) # 去掉行尾多余空格 text = re.sub(r'[ \t]+$', '', text, flags=re.MULTILINE) # 去掉常见页码格式 text = re.sub(r'\n\s*\d{1,3}\s*\n', '\n', text) return text.strip()

这一步做得好不好,直接影响后续向量化的质量。

4.2 分段策略

分段是 RAG 项目里最重要的知识之一。分段太短,语义不完整;分段太长,噪声太多,检索命中率下降。

主流的策略有以下几种:

策略说明适用场景
固定长度分段按字符数/词数切分,比如每 500 字符一段通用场景,实现简单
按段落分段以自然段落为单位切分书本文本、结构化文档
按标题/章节分段根据文档结构切分法律条文、技术手册、典籍
滑动窗口分段相邻分段之间有重叠,比如 500 字符一段,重叠 100 字符避免切断语义完整句子

在实际项目中,我推荐一个可落地的组合:

  1. 优先按章节/大标题切分,保证每个一级块有明确主题;
  2. 在一级块内,按段落或者固定长度进一步切分;
  3. 设置重叠区域,防止句子被切断。

LangChain 提供了现成的文本分割器,比如RecursiveCharacterTextSplitter。

from langchain.text_splitter import RecursiveCharacterTextSplitter text_splitter = RecursiveCharacterTextSplitter( chunk_size=800, chunk_overlap=100, separators=["\n\n", "\n", "。", "!", "?", ".", "!", "?", ",", ",", " ", ""] ) chunks = text_splitter.split_text(cleaned_text) print(f"分割得到 {len(chunks)} 个文本块")

这里有几个参数值得注意:

  • chunk_size=800:每个文本块目标长度是 800 字符。这个值不是固定的,要看你的 Embedding 模型和最终效果。太小会截断语义,太大会包含无关信息。
  • chunk_overlap=100:相邻块之间保留 100 字符的重叠,防止关键信息恰好落在切分边界上。
  • separators:优先按段落、句子切分,避免在中途切断语义。

在 Sikhbani.ai 这类基于典籍的项目中,文本本身可能非常古老,句式与现代语言差异较大。这种情况下,建议保留原始文本的段落结构,不要过度切碎,因为每一段可能包含相对完整的哲学思想。

4.3 元数据管理

向量数据库中的每一条记录,除了向量本身,还应该包含元数据。比如:

  • 文本来源文件;
  • 章节编号;
  • 原文页码;
  • 文本块在原文中的位置。

这些元数据在后续做答案溯源时非常有用。Sikhbani.ai 如果需要给用户展示“原文出处”,就离不开这一步。

docs = [ { "content": chunk, "metadata": { "source": "gurbani_text.pdf", "chapter": "section_1", "chunk_index": i } } for i, chunk in enumerate(chunks) ]

5. 完整示例代码实现

下面我们用一个最小的完整示例,演示“本地文本 → 向量化 → 检索 → 问答”的全流程。这个示例不涉及具体的宗教文本,以通用中文语料为例,你可以把它替换成你自己的数据。

5.1 文本加载与处理

我们先准备一段示例文本,保存为book.txt:

第一章:万物起源 在人类文明的长河中,对于万物起源的追问从未停止。许多经典文献从不同的视角给出了回答。 第二章:慈悲与智慧 慈悲与智慧被认为是修行路上的两个重要支柱。缺乏智慧的慈悲容易流于盲目,缺乏慈悲的智慧则可能变得冷漠。 第三章:行动与结果 每一个行动都会带来相应的结果。经典强调,行动不仅包括外在的身体行为,也包括内在的思想和意图。

使用 LangChain 的文本加载器和分割器处理它。

# 文件路径:rag_pipeline.py from langchain.text_splitter import RecursiveCharacterTextSplitter from langchain_community.vectorstores import Chroma from langchain_community.embeddings import HuggingFaceEmbeddings from langchain_openai import ChatOpenAI from langchain.chains import RetrievalQA # 1. 加载文本 with open("book.txt", "r", encoding="utf-8") as f: text = f.read() # 2. 清洗文本 import re def clean_text(text: str) -> str: text = re.sub(r'\n\s*\n+', '\n', text) text = re.sub(r'[ \t]+$', '', text, flags=re.MULTILINE) return text.strip() text = clean_text(text) # 3. 文本分段 text_splitter = RecursiveCharacterTextSplitter( chunk_size=200, chunk_overlap=30, separators=["\n\n", "\n", "。", "!", "?", ".", "!", "?", ",", ",", " ", ""] ) chunks = text_splitter.split_text(text) print(f"分段数量: {len(chunks)}")

5.2 初始化 Embedding 模型与向量数据库

这里使用开源的sentence-transformers模型做本地向量化,避免依赖外部 Embedding API。

# 续上,初始化 Embedding embedding_model = HuggingFaceEmbeddings( model_name="BAAI/bge-small-zh-v1.5" ) # 创建向量数据库 vectorstore = Chroma.from_texts( texts=chunks, embedding=embedding_model, persist_directory="./chroma_db", collection_name="book_knowledge" ) print("向量库构建完成")

persist_directory指定了向量库持久化的目录。第一次运行会下载 Embedding 模型,需要一点时间。之后运行会直接复用本地模型。

5.3 构建检索问答链路

接下来,我们用大模型生成最终回答。

# 续上,初始化大模型 llm = ChatOpenAI( model="gpt-4o-mini", temperature=0.2 ) # 构建问答链 qa_chain = RetrievalQA.from_chain_type( llm=llm, chain_type="stuff", retriever=vectorstore.as_retriever(search_kwargs={"k": 3}), return_source_documents=True, verbose=True )

chain_type有很多种,对于文本块数量不多的场景,stuff最简单,就是直接把检索到的所有文本块拼在一起放进 Prompt。如果检索到的块很多,超过了模型上下文长度,就需要换用map_reduce或refine等策略。

5.4 提问并输出结果

question = "经典里怎么描述慈悲?" result = qa_chain.invoke({"query": question}) print("回答:", result["result"]) print("\n参考来源:") for doc in result["source_documents"]: print("-" * 40) print(doc.page_content)

5.5 完整代码汇总

为了方便你直接运行,我把上面所有步骤合并成一个脚本。

# 文件路径:rag_pipeline.py import re from dotenv import load_dotenv load_dotenv() from langchain.text_splitter import RecursiveCharacterTextSplitter from langchain_community.vectorstores import Chroma from langchain_community.embeddings import HuggingFaceEmbeddings from langchain_openai import ChatOpenAI from langchain.chains import RetrievalQA def clean_text(text: str) -> str: text = re.sub(r'\n\s*\n+', '\n', text) text = re.sub(r'[ \t]+$', '', text, flags=re.MULTILINE) return text.strip() def main(): with open("book.txt", "r", encoding="utf-8") as f: text = f.read() text = clean_text(text) text_splitter = RecursiveCharacterTextSplitter( chunk_size=200, chunk_overlap=30, separators=["\n\n", "\n", "。", "!", "?", ".", "!", "?", ",", ",", " ", ""] ) chunks = text_splitter.split_text(text) embedding_model = HuggingFaceEmbeddings( model_name="BAAI/bge-small-zh-v1.5" ) vectorstore = Chroma.from_texts( texts=chunks, embedding=embedding_model, persist_directory="./chroma_db", collection_name="book_knowledge" ) llm = ChatOpenAI( model="gpt-4o-mini", temperature=0.2 ) qa_chain = RetrievalQA.from_chain_type( llm=llm, chain_type="stuff", retriever=vectorstore.as_retriever(search_kwargs={"k": 3}), return_source_documents=True, verbose=True ) while True: question = input("\n请输入你的问题(输入 exit 退出):").strip() if question.lower() == "exit": break if not question: continue result = qa_chain.invoke({"query": question}) print("回答:", result["result"]) print("\n参考来源:") for doc in result["source_documents"]: print("-" * 40) print(doc.page_content) if __name__ == "__main__": main()

6. 运行结果与效果验证

6.1 运行方式

python rag_pipeline.py

6.2 预期输出

程序启动后,会先构建向量库,然后进入交互式问答。输入问题后,应该看到类似下面的输出:

请输入你的问题(输入 exit 退出):经典里怎么描述慈悲? 回答: 经典中描述慈悲时,提到慈悲与智慧被认为是修行路上的两个重要支柱。缺乏智慧的慈悲容易流于盲目,缺乏慈悲的智慧则可能变得冷漠。 参考来源: ---------------------------------------- 第二章:慈悲与智慧 慈悲与智慧被认为是修行路上的两个重要支柱。缺乏智慧的慈悲容易流于盲目,缺乏慈悲的智慧则可能变得冷漠。

6.3 如何判断系统是否成功

判断标准有以下几点:

  1. 回答是否基于检索到的文本,而不是凭空生成;
  2. 参考来源是否和问题相关;
  3. 回答是否连贯、自然;
  4. 如果文本库中没有相关内容,系统是否如实回答“没有找到相关资料”,而不是编造。

6.4 效果不佳时如何定位

如果检索到的内容不对,或者回答质量差,按照下面顺序排查:

  1. 先看检索到的参考来源是否相关。如果来源不对,问题出在 Embedding 或分段策略上;
  2. 如果来源对但回答不好,问题出在 Prompt 模板或大模型选择上;
  3. 如果来源对,但内容被截断,问题出在分段大小上;
  4. 如果向量库检索速度慢,检查向量数据库索引类型。

7. 常见问题与排查思路

问题现象可能原因排查方式解决方案
回答与文本库无关Embedding 模型与文本语言不匹配检查 Embedding 模型是否支持目标语言选择合适的中文/多语 Embedding 模型
检索不到相关内容分段太粗或太细打印检索到的 source_documents 内容调整 chunk_size 和 chunk_overlap
回答重复或互相矛盾检索到多个语义相似但答案不同的段落检查分段的唯一性,排除重复数据增加去重逻辑或调整相似度阈值
构建向量库时内存不足文本量太大,一次性加载全部分批处理文本,监控内存使用使用批量向量化或分布式处理
大模型 API 调用失败未配置 API Key 或者限流查看返回错误信息检查环境变量、重试策略、限流设置
首次运行下载模型很慢网络原因查看下载进度使用镜像源或预先下载模型
检索结果不稳定向量随机性或多条文本相似多次测试同一问题,查看检索结果增加重排序层或调整 top-k 参数

8. 从 Sikhbani.ai 看 RAG 应用的关键设计选择

到这里,我们已经跑通了一个最小 RAG 系统。但把它做成一个真正可用的产品,还有几个关键设计决策要讲。

8.1 如何处理“经典文本”的特殊性

Sikhbani.ai 所针对的文本类型,是流传已久的经典文献。这类文本通常有以下特点:

  • 语言风格古老,与现代口语差异大;
  • 存在多种译本或注释版本;
  • 上下文依赖强,单看一句话容易误解;
  • 引用需要精确,不能随意释义。

这意味着,做这类知识库时,不能简单使用通用文本分割器。更合理的做法是:

  • 保留原文的完整段落,不要过度切分;
  • 在分段时保留章节上下文,或者在元数据中标注章节关系;
  • 对引文做精确匹配,确保回答中引用的句子确实存在于原文中;
  • 如果存在多个版本,明确版本信息,避免混淆。

8.2 检索质量的提升:重排序(Rerank)

基础的向量检索返回 Top-K 个相关文本块。但“语义相关”并不一定等于“对当前问题有用”。一个更成熟的做法是加入重排序环节。

流程变成这样:

  1. 用向量检索召回候选文本块,比如召回 10 个;
  2. 用重排序模型(如 BGE-Reranker、Cohere Rerank)对这 10 个候选重新打分;
  3. 选择最相关的 3 到 5 个作为最终 Prompt 的上下文。

这样做能明显提升回答质量,代价是增加一些推理延迟。在 Sikhbani.ai 这类对回答准确性要求较高的场景中,重排序很值得加入。

LangChain 中重排序可以通过CrossEncoderReranker来实现。这里只给出一个集成思路,具体 API 以最新版 LangChain 文档为准。核心思想是增加一个Retriever包装层,在检索后、生成前插入重排序。

8.3 如何控制大模型的“幻觉”

RAG 虽然缓解了“模型不知道”的问题,但并没有彻底消除幻觉。模型在生成回答时,仍然可能:

  • 不严格按照检索到的内容回答;
  • 添加自己的“知识”;
  • 在检索内容不足时强行编造。

控制幻觉的几个有效措施:

  1. Prompt 中明确约束:要求“只根据提供的文本回答,如果文本中没有,请明确说没有找到相关资料”;
  2. 降低温度参数:temperature设置在 0.1 到 0.3 之间,让输出更确定;
  3. 输出后校验:检查回答中的关键论点是否能在检索到的文本中找到依据;
  4. 提供溯源:在应用界面展示“参考来源”,让用户自行判断可信度。

8.4 embedding 模型、向量数据库与大模型的选择

这三者选型是 RAG 项目里最核心的决策点。

Embedding 模型:取决于文本语言和领域。对于中文经典文献,可以尝试开源模型如 BGE、M3E,也可以使用商业 API。你需要关注的是:

  • 支持的文本长度上限;
  • 向量维度;
  • 语义理解质量;
  • 推理速度。

向量数据库:项目初期用 Chroma、FAISS 足够;数据量超过百万级,再考虑 Qdrant、Milvus、Weaviate 等服务化组件。生产环境必须考虑备份、监控和权限管理。

大模型:如果追求回答质量,可以用 GPT 系列或顶级国产模型;如果追求数据隐私和成本,可以用开源模型本地部署,比如 Qwen、Llama 系列。需要根据文本语言、上下文长度、回答风格来评估。

8.5 完整生产架构长什么样

一个适合真实用户使用的版本,大约是这样的:

用户 → 前端问答界面 → API 网关 → 问答服务 ↓ 检索服务(向量检索 + 重排序) ↓ 向量数据库 ↓ 大模型服务(LLM) ↓ 回答 + 来源 → 返回前端

在这个架构中,问答服务负责调度,检索服务负责找资料,大模型负责生成答案。前端界面只是薄薄一层,核心价值都在服务端。

9. 部署与上线的最佳实践

如果你不想只停留在本地跑通,而是想把它做成一个线上服务,有几个工程问题必须提前考虑。

9.1 使用 API 服务的方式暴露能力

不要把 RAG 代码直接写在 Web 框架里。更好的做法是把它封装成一个独立的服务,通过 HTTP 接口对外提供。

最小化的 FastAPI 服务示例:

# 文件路径:api.py from fastapi import FastAPI from pydantic import BaseModel app = FastAPI() class QueryRequest(BaseModel): question: str top_k: int = 3 class QueryResponse(BaseModel): answer: str sources: list[str] @app.post("/ask", response_model=QueryResponse) async def ask(request: QueryRequest): # 这里调用你训练好的 QA 链路 result = qa_chain.invoke({"query": request.question}) sources = [doc.page_content for doc in result["source_documents"]] return QueryResponse(answer=result["result"], sources=sources)

这样就完成了从“脚本”到“服务”的跃迁。注意在真实项目中,应该把qa_chain初始化为全局变量,避免每次请求都重新加载模型和向量库。

9.2 缓存与性能

同一种问题可能被很多用户反复询问。为了避免每次都调用大模型,可以增加缓存:

  • 对用户问题进行语义哈希(或简单文本哈希);
  • 如果命中缓存,直接返回历史回答;
  • 设置缓存过期时间。

这能显著降低 API 成本和响应时间。

9.3 版本管理与回滚

RAG 系统里,向量库构建完成后应该“不可变”。每次更新文档时,不要直接修改原向量库,而是:

  1. 构建新的向量库集合;
  2. 在服务中切换集合名称;
  3. 如果效果不佳,可以一键回滚到旧版本。

这在生产环境中非常重要,能避免“更新完知识库后回答质量反而下降”的问题。

9.4 安全与合规

如果这个系统部署给真实用户,必须注意:

  • 内容审核:用户输入和系统输出都需要做内容安全检测;
  • 权限管理:不是所有用户都应该看到所有内容;
  • 日志与审计:记录谁在什么时间问了什么问题,用于追溯;
  • 数据隐私:不要把人名、机构名等敏感信息持久化,除非确实需要。

这一点在 Sikhbani.ai 这类涉及经典文本解读的项目中尤其重要,因为同一个问题可能被不同背景的用户问出来,回答需要中立、稳妥、尊重原典。

9.5 监控与评估

上线后,你需要持续监控:

  • 检索相关性:随机抽查检索命中的文本块是否合理;
  • 回答质量:定期人工评分;
  • 响应延迟:检索耗时、生成耗时、总耗时;
  • 成本:token 消耗、API 费用。

建议维护一个评测集,包含问题、预期来源、预期回答要点。每次改动系统后,用评测集回归,确认没有引入退化。

10. 总结与后续学习方向

这篇文章从 Sikhbani.ai 这个具体项目切入,拆解了类 RAG 知识库问答系统的完整技术链路。核心要点可以归纳如下:

第一,Sikhbani.ai 本质上是“特定文本语料 + 向量检索 + 大模型生成”的标准 RAG 应用,它把“让 AI 理解一本特定的书”这件事变成了可复制的工程方案。

第二,这个系统的关键成功因素不在大模型本身,而在数据准备、分段策略、检索质量和 Prompt 设计。原始文本清洗不到位、分段不合理,再强的模型也无济于事。

第三,做真实产品时,回答准确性比回答的“文采”更重要。重排序、低温度、来源引用和内容校验,是控制幻觉的实用手段。

第四,工程上,先本地跑通,再封装服务,再做缓存、版本管理和监控,是一条稳妥的演进路径。

对于正在学习 RAG 的人来说,下一步可以按这个顺序深入:

  1. 把本文的示例代码跑通,替换成自己的文档试试;
  2. 尝试不同的分段策略和 Embedding 模型,感受检索效果的变化;
  3. 加入重排序模型,对比加入前后回答质量;
  4. 试着把服务封装成 FastAPI 接口;
  5. 进一步学习文档问答的进阶技术,比如多跳问答、表格问答、Agent 与工具调用。

如果你想做的是 Sikhbani.ai 这样基于经典文献的问答系统,请特别注意原文引用精确性和上下文完整性。可以在技术方案之外,多研究一下文献学中常用的文本索引和注疏结构,这会让你的知识库设计更符合真实使用场景。

在动手实践时,先从一个最小版本开始,跑通全流程,再逐步优化。RAG 这条链路看起来组件很多,但实际上每一步都有成熟的开源方案可以复用。真正决定项目上限的,不是模型有多大,而是你对数据理解和检索质量的控制能力。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询