【手摸手学 RAG】从零开始,和我一起搭建一个RAG知识库问答机器人

举报
胡琦 发表于 2025/10/05 10:43:08 2025/10/05
【摘要】 从零开始,和我一起搭建一个RAG知识库问答机器人

大家好,我是胡琦。

上次我们聊了如何“升级”RAG的检索系统,很多小伙伴表示意犹未尽,想知道一个完整的RAG应用到底是如何从零搭建的。

安排!

本篇,我们就以Datawhale的开源项目all-in-rag中的实战项目为例,完整地走一遍从环境配置到最终应用的全流程。您不需要任何高深的AI背景,只要跟着我的步骤,就能亲手“孕育”出一个属于你自己的知识库问答机器人。

准备好了吗?让我们开始吧!

第一步:谋定而后动 —— 架构设计与环境准备

任何一个项目,开工前都要先画好“蓝图”。我们的RAG问答机器人也不例外。它的工作流程非常清晰:

图片来源: all-in-rag

  1. 数据准备:把我们的私有知识(比如一堆PDF、Markdown文档)加载进来,并切割成小片段(Chunks)。
  2. 索引构建:用Embedding模型把每个文本片段“向量化”,然后存入向量数据库,建立索引。
  3. 检索:当用户提问时,同样将问题向量化,然后去向量数据库里找到最相似的几个文本片段。
  4. 生成:把原始问题和检索到的文本片段一起“喂”给大语言模型(LLM),让它生成最终的、人性化的答案。

蓝图有了,接下来就是准备“工具箱”。你需要一个安装了Python的环境,然后在项目目录下创建一个 requirements.txt 文件,写入以下内容:

langchain==0.3.26
langchain-huggingface==0.3.1
langchain-text-splitters==0.3.8
langchain-unstructured==0.1.6
langchain-community==0.3.27
faiss-cpu>=1.7.0
unstructured==0.18.11
Markdown==3.8.2
sentence-transformers>=3.0.0
lazy_loader==0.4
rank_bm25==0.2.2
openai>=1.86.0,<2.0.0

然后打开终端,一行命令把所有依赖都装好:

pip install -r requirements.txt

小贴士langchain 和相关依赖为我们提供了文档读取、LLM等能力,faiss-cpu 则是我们要用到的向量数据库。

第二步:精雕细琢 —— 知识库“原料”处理

万丈高楼平地起,知识库就是我们RAG机器人的“地基”。这里的关键是加载切分

1. 加载文档
我们的知识可能分散在各种格式的文档里。不用怕,LangChain 提供了强大的DirectoryLoader,可以帮我们自动识别并加载一个文件夹下所有支持的文档。

from langchain_community.document_loaders import DirectoryLoader

# 设置你的知识库路径
DATA_PATH = "your_knowledge_base_path/"

# 创建一个加载器,它会自动处理路径下的 .md, .txt, .pdf 等文件
loader = DirectoryLoader(DATA_PATH, silent_errors=True)
raw_documents = loader.load()

print(f"成功加载了 {len(raw_documents)} 份文档。")

2. 文本切分(Chunking)
一篇长文档直接丢给模型,效果会很差。我们需要把它切分成大小适中、语义完整的“知识块”。这里我们选用RecursiveCharacterTextSplitter,它会智能地尝试按段落、句子等方式切分,尽可能保持语义完整。

from langchain.text_splitter import RecursiveCharacterTextSplitter

# 初始化一个文本切分器
text_splitter = RecursiveCharacterTextSplitter(
    chunk_size=500,  # 每个chunk的大小
    chunk_overlap=50, # 相邻chunk的重叠大小
    separators=["\n\n", "\n", " ", ""] # 分隔符
)

# 开始切分
documents = text_splitter.split_documents(raw_documents)
print(f"文档被切分成了 {len(documents)} 个片段。")

好了,我们的“原料”已经处理完毕,变成了一块块高质量的“知识砖块”,随时可以用来构建我们的知识大厦了。

第三步:建立索引 —— 让知识“井井有条”

现在,我们需要把这些文本“砖块”转换成机器能理解的数学语言——向量,并存入一个可以被快速检索的数据库中。

1. 选择Embedding模型
Embedding模型是连接自然语言和向量空间的“桥梁”。市面上有很多优秀的选择,这里我们使用社区广泛应用的 bge-large-zh-v1.5,它在中英文上都有很好的表现。

from langchain_community.embeddings import HuggingFaceEmbeddings

# 指定我们要用的Embedding模型
embedding_model_name = 'BAAI/bge-large-zh-v1.5'

# 初始化Embedding模型
embeddings = HuggingFaceEmbeddings(
    model_name=embedding_model_name,
    model_kwargs={'device': 'cpu'}, # 如果你有GPU,可以改成 'cuda'
    encode_kwargs={'normalize_embeddings': True}
)

2. 构建向量数据库
FAISS 是一个非常高效的向量相似度搜索库。我们用它来存储并索引我们的文档向量。

from langchain_community.vectorstores import FAISS

# 使用我们准备好的文档片段和Embedding模型,构建FAISS索引
vectorstore = FAISS.from_documents(documents, embeddings)

# [可选] 我们可以把建好的索引存到本地,下次就不用重新构建了
vectorstore.save_local("faiss_index_directory")

# 加载方式:
# vectorstore = FAISS.load_local("faiss_index_directory", embeddings, allow_dangerous_deserialization=True)

# 把它变成一个检索器(Retriever)
retriever = vectorstore.as_retriever()

到这里,我们RAG系统的“检索”核心已经打造完毕!它已经具备了根据问题,快速找到相关知识的能力。

第四步:注入灵魂 —— 让机器人“开口说话”

最后一步,就是请出我们的大语言模型(LLM),让它扮演“大脑”的角色,整理检索到的信息,并用流畅的语言回答用户的问题。

1. 加载LLM
你可以选择任何你喜欢的LLM,比如ChatGLMQwen等。这里我们以加载一个本地模型为例。

from langchain_community.llms import Ollama # 假设我们用Ollama来加载本地模型

# 初始化一个LLM
llm = Ollama(model="qwen:7b-chat") # 替换成你自己的模型

2. 创建问答链(QA Chain)
LangChain 已经为我们封装好了标准的RetrievalQA链,它能完美地把“检索器”和“LLM”串联起来。

from langchain.chains import RetrievalQA

# 创建一个问答链
qa_chain = RetrievalQA.from_chain_type(
    llm=llm,
    chain_type="stuff", # "stuff"模式会把所有检索到的内容一次性塞给LLM
    retriever=retriever # 使用我们第三步创建的检索器
)

# 让我们来问个问题!
question = "请问,RAG系统中的混合检索是什么?"
answer = qa_chain.invoke(question)

print(answer)

效果拔群! 我们的机器人会根据我们提供的知识库,精准地回答出混合检索的定义和作用。

至此我们已经亲手完整地搭建了一个RAG应用。回顾一下我们的旅程:

  1. 规划架构,准备好开发环境。
  2. 处理数据,将原始文档制作成高质量的“知识砖块”。
  3. 建立索引,打造了一个高效的检索引擎。
  4. 串联生成,为机器人注入LLM的“灵魂”,让它能言善道。

是不是很有成就感?

当然,这只是一个起点。接下来,你还可以继续探索:

  • 优化前端:用StreamlitGradio为它穿上一件漂亮的外衣。
  • 模型替换:尝试不同的Embedding模型和LLM,看看效果有何不同。
  • 高级检索:集成我们上一篇讲到的混合检索、重排等高级技巧。

技术的魅力就在于不断探索和创造。希望这篇笔记能为你打开一扇通往更广阔AI世界的大门。动手试试吧,期待看到您的分享!

详细代码请参考: datawhalechina/all-in-rag/code/C8

本文基于[datawhalechina/all-in-rag]项目整理,仅代表个人学习心得,不代表任何官方观点。小伙伴们有疑问欢迎交流讨论,一起学习一起进步!

【声明】本内容来自华为云开发者社区博主,不代表华为云及华为云开发者社区的观点和立场。转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息,否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。