使用Python和FAISS搭建一个本地RAG知识库
前言
你是不是也遇到过这样的场景:手里有一堆技术文档、API手册、会议纪要,每次查东西全靠 Ctrl+F 盲搜,效率极低?
RAG(Retrieval-Augmented Generation,检索增强生成)就是为了解决这个问题而生的。它的核心思想很简单:先把知识"存起来",需要时"先检索再回答",而不是让大模型全靠记忆硬编。
今天这篇博客不整虚的,直接带你用纯 Python + FAISS(Facebook 开源的向量检索库)搭建一个本地 RAG 知识库,完全离线、零成本、不依赖任何云 API。文末附完整可运行代码。
一、RAG 到底是什么?大白话解释
RAG 流程可以分为三个核心步骤:
| 步骤 | 英文名称 | 做了什么 | 类比 |
|---|---|---|---|
| 1. 向量化 | Embedding | 把文字变成"数字指纹" | 给每本书编一个唯一编号 |
| 2. 存储检索 | Vector Search | 在海量向量中快速找到相似的 | 图书馆的索引目录 |
| 3. 生成回答 | LLM Generation | 带着检索结果让大模型回答 | 把相关书页递给老师看 |
核心优势:
- ✅ 知识可更新:文档改了,重新向量化就行,不用重新训练模型
- ✅ 答案有出处:每次回答都基于真实检索到的内容
- ✅ 本地可控:敏感数据不出门,隐私有保障
二、环境准备
整个项目只需要两个核心依赖:
- sentence-transformers:将文本转为向量(Embedding)
- faiss-cpu:Facebook 开源的高效向量检索库
安装命令:
pip install sentence-transformers faiss-cpu
如果你的机器有 NVIDIA 显卡,可以把 faiss-cpu 换成 faiss-gpu,检索速度会快几十倍。本文以 CPU 版本演示,开箱即用。
三、实操步骤:从零到一搭建知识库
步骤 1:准备文档数据
假设我们有以下技术文档片段(实际使用时可以是 PDF、Markdown 文件的切分内容):
documents = [
"Docker 容器是一种轻量级的虚拟化技术,它将应用及其依赖打包在一个隔离环境中运行。",
"Kubernetes 是一个容器编排平台,用于自动化部署、扩展和管理容器化应用。",
"Python 的 requests 库是一个简单易用的 HTTP 客户端库,支持 GET、POST 等常用方法。",
"Git 是一个分布式版本控制系统,支持分支管理、合并和提交历史记录。",
"Docker Compose 允许通过 YAML 文件定义和运行多容器 Docker 应用。",
]
步骤 2:文本向量化
使用 sentence-transformers 的预训练模型将每段文字转换为 768 维向量:
from sentence_transformers import SentenceTransformer
import faiss
import numpy as np
# 加载预训练 embedding 模型(首次运行会自动下载,约 420MB)
model = SentenceTransformer('all-MiniLM-L6-v2')
# 对文档进行向量化
embeddings = model.encode(documents, show_progress_bar=True)
print(f"向量维度: {embeddings.shape}") # 输出: (5, 768)
模型说明:all-MiniLM-L6-v2 是一个轻量级中文/英文通用模型,体积小、速度快,适合入门。如果需要更高精度,可以换用 all-mpnet-base-v2。
步骤 3:构建 FAISS 索引
将向量存储到 FAISS 索引中,实现毫秒级相似度检索:
dimension = embeddings.shape[1] # 768
# 使用 L2 距离(欧几里得距离)构建索引
index = faiss.IndexFlatL2(dimension)
# FAISS 要求 float32 格式
embeddings_32 = embeddings.astype('float32')
index.add(embeddings_32) # 向索引中写入向量
print(f"已存储 {index.ntotal} 条向量")
步骤 4:实现检索功能
def search(query: str, top_k: int = 3) -> list:
"""根据问题检索最相关的文档"""
query_embedding = model.encode([query])
query_32 = query_embedding.astype('float32')
# FAISS 检索:返回距离最近的前 top_k 个
distances, indices = index.search(query_32, top_k)
results = []
for i, (dist, idx) in enumerate(zip(distances[0], indices[0])):
results.append({
"rank": i + 1,
"distance": round(float(dist), 4),
"content": documents[idx]
})
return results
# 测试检索
query = "如何管理容器化应用?"
results = search(query, top_k=2)
for r in results:
print(f"[{r['rank']}] 相似度分数: {r['distance']}")
print(f" 内容: {r['content']}\n")
步骤 5:连接大模型生成答案
检索到相关文档后,交给大模型生成最终回答。这里以本地 Ollama 为例:
import requests
def generate_answer(query: str, retrieved_docs: list) -> str:
"""基于检索结果生成回答"""
context = "\n".join([d['content'] for d in retrieved_docs])
prompt = f"""你是一个专业的技术助手。请基于以下参考资料回答问题。
如果资料中没有答案,请明确说"参考资料中未提及"。
参考资料:
{context}
问题:{query}
"""
# 调用 Ollama(需先安装并启动 ollama serve)
response = requests.post(
"http://localhost:11434/api/generate",
json={"model": "qwen2.5:7b", "prompt": prompt, "stream": False}
)
return response.json().get("response", "")
# 完整 RAG 流程
query = "Docker 和 Kubernetes 有什么关系?"
docs = search(query, top_k=3)
answer = generate_answer(query, docs)
print(answer)
四、进阶优化技巧
| 优化方向 | 具体做法 | 效果 |
|---|---|---|
| 文档切分 | 使用 LangChain 的 RecursiveCharacterTextSplitter 按段落/字符数切分 | 检索精度提升 30%+ |
| 混合检索 | 结合关键词检索(BM25)+ 向量检索 | 解决向量检索"语义模糊"问题 |
| 重排序(Rerank) | 用 Cross-Encoder 模型对 top-20 结果重新打分 | 取 top-5 精度显著提升 |
| 索引压缩 | 使用 FAISS 的 IVF + PQ 量化,在精度损失<5%时压缩 8 倍 | 千万级向量也可内存加载 |
五、常见问题解答
Q1:检索出来的内容不够准确怎么办?
优先检查文档切分策略。一段文字太长的话,嵌入向量会"信息稀释"。建议单段控制在 200-500 字。
Q2:中文效果不好?
可以尝试专为中文优化的 embedding 模型,如
BAAI/bge-base-zh-v1.5(BGE 模型族),中文语义检索能力更强。
Q3:数据量大了怎么办?
FAISS 单机可处理千万级向量。如果数据量超 500 万条,建议升级到
faiss-gpu或考虑 Milvus、Qdrant 等专用向量数据库。
总结
今天我们用不到 50 行 Python 代码,搭建了一个完整的本地 RAG 知识库。核心要点回顾:
- Embedding 是基石:把文字变成向量,相似度才能计算
- FAISS 是引擎:高效的向量检索,毫秒级返回
- 大模型是出口:带着检索结果生成有依据的答案
完整代码可以直接复制运行,无需任何配置。你可以把公司内部文档、学习笔记导入这个知识库,打造一个专属的 AI 问答助手。
以上就是使用用Python和FAISS搭建一个本地RAG知识库的详细内容,更多关于Python FAISS搭建RAG知识库的资料请关注脚本之家其它相关文章!
相关文章
探索Python fcntl模块文件锁和文件控制的强大工具使用实例
这篇文章主要介绍了Python fcntl模块文件锁和文件控制的强大工具使用实例探索,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪2024-01-01
对pandas中iloc,loc取数据差别及按条件取值的方法详解
今天小编就为大家分享一篇对pandas中iloc,loc取数据差别及按条件取值的方法详解,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧2018-11-11
详解win10下pytorch-gpu安装以及CUDA详细安装过程
这篇文章主要介绍了win10下pytorch-gpu安装以及CUDA详细安装过程,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧2021-01-01


最新评论