2026个人知识库搭建指南:基于LlamaIndex与ChromaDB的本地开源方案
摘要
介绍在Windows上搭建完全本地RAG系统的方案。核心采用LlamaIndex、ChromaDB和Ollama本地模型,无
在Windows系统上构建一个完全离线的RAG(检索增强生成)应用,无需担心云服务费用或API密钥管理。本方案基于LlamaIndex、ChromaDB和Ollama本地模型,提供从环境搭建到生产级代码的完整实现路径。
一、环境准备(Conda)
使用Conda创建独立的Python环境,确保依赖库版本隔离,避免潜在的冲突。
1. 创建虚拟环境
通过Anaconda Prompt或系统终端,执行以下命令创建并激活名为“rag”的虚拟环境:
# 创建Python 3.11的虚拟环境
conda create -n rag python=3.11 -y
# 激活环境
conda activate rag
2. 安装核心依赖(一次性复制粘贴)
环境激活后,一次性安装所有必要的Python包。以下版本组合经过测试,兼容性稳定。
# 基础框架
pip install llama-index==0.12.0
# 从 llama-index 0.10 版本开始,向量存储被拆分为独立的集成包:
pip install llama-index-vector-stores-chroma
# 向量数据库
pip install chromadb==0.5.20
# 本地嵌入模型(中文优化)
pip install llama-index-embeddings-huggingface==0.4.0
# 本地大模型(Ollama)
pip install llama-index-llms-ollama==0.5.0
# 文档解析
pip install pypdf # PDF支持
pip install python-docx # Word支持
# 其他工具
pip install tiktoken # Token计算
二、安装Ollama(本地大模型)
Ollama简化了本地大型语言模型的部署与管理,是离线运行LLM的核心工具。
步骤
- 下载安装包:访问Ollama官网(ollama.com),下载Windows版本并安装。默认安装到C盘即可,无需额外配置。
- 拉取模型:安装完成后,打开CMD或PowerShell,拉取一个适合你电脑配置的模型。例如:
# 拉取轻量级模型(约3GB,适合8G内存的电脑)
ollama pull llama3.2
# 或者拉取对中文支持更好的模型(约4GB)
ollama pull qwen2.5:7b
安装完成后,可以运行以下命令验证:
ollama list
# 如果成功,会显示类似:llama3.2 或 qwen2.5:7b
三、完整项目结构
建议采用以下目录结构来组织项目,便于代码管理和维护。
rag_project/
├── data/ # 存放你的文档(PDF/Word/TXT等)
│ ├── 员工手册.pdf
│ └── 产品说明.docx
├── chroma_db/ # 向量数据库存储目录(自动创建)
├── app.py # 主程序(可选,用于集成)
├── query.py # 交互式查询脚本
└── rebuild.py # 重建索引工具
四、完整代码
将以下核心代码文件保存到你的项目目录中,构成完整的RAG应用骨架。
1. 配置文件 `config.py`
集中管理所有路径、模型和检索参数,方便后续调整和优化。
"""配置参数 - 全部免费,零API Key"""
import os
# 路径配置
DATA_DIR = "./data" # 文档文件夹
CHROMA_PATH = "./chroma_db" # 向量库本地存储
COLLECTION_NAME = "my_knowledge" # 集合名称
# 模型配置(完全本地,无需网络)
EMBED_MODEL = "BAAI/bge-small-zh-v1.5" # 中文嵌入模型,约100MB
LLM_MODEL = "llama3.2" # 或 "qwen2.5:7b"
# RAG参数
CHUNK_SIZE = 500 # 分块大小(字符)
CHUNK_OVERLAP = 50 # 块间重叠(用于保持上下文连贯)
TOP_K = 3 # 检索最相关的Top 3个文本片段
2. 核心模块 `rag_engine.py`
RAG系统的核心引擎,封装了初始化、索引构建、查询和文档管理的全部功能。
"""RAG引擎 - 封装所有逻辑"""
import os
import chromadb
from config import *
from llama_index.core import (VectorStoreIndex, SimpleDirectoryReader,
Settings, StorageContext, Document)
from llama_index.core.node_parser import SentenceSplitter
from llama_index.vector_stores.chroma import ChromaVectorStore
from llama_index.embeddings.huggingface import HuggingFaceEmbedding
from llama_index.llms.ollama import Ollama
class RAGEngine:
def __init__(self):
"""初始化:加载模型、连接数据库"""
print("???? 正在初始化RAG引擎...")
# 1. 配置本地嵌入模型(首次运行会自动下载,约100MB)
print(f"???? 加载嵌入模型: {EMBED_MODEL}")
Settings.embed_model = HuggingFaceEmbedding(
model_name=EMBED_MODEL,
trust_remote_code=True
)
# 2. 配置本地大模型(通过Ollama)
print(f"???? 连接Ollama模型: {LLM_MODEL}")
Settings.llm = Ollama(
model=LLM_MODEL,
request_timeout=120.0,
temperature=0.7 # 控制创造性,0更确定,1更随机
)
# 3. 连接ChromaDB(本地文件存储,无需服务器)
print(f"????️ 连接向量数据库: {CHROMA_PATH}")
self.chroma_client = chromadb.PersistentClient(path=CHROMA_PATH)
self.collection = self.chroma_client.get_or_create_collection(
name=COLLECTION_NAME,
metadata={"hnsw:space": "cosine"} # 使用余弦相似度进行检索
)
self.vector_store = ChromaVectorStore(chroma_collection=self.collection)
# 4. 构建或加载索引
self.index = self._build_index()
print("✅ 初始化完成!\n")
def _build_index(self):
"""构建或加载向量索引"""
storage_context = StorageContext.from_defaults(vector_store=self.vector_store)
# 检查是否已有数据
if self.collection.count() > 0:
print(f"???? 发现已有索引,加载 {self.collection.count()} 条记录")
return VectorStoreIndex.from_vector_store(
vector_store=self.vector_store,
storage_context=storage_context
)
# 新建索引
print("????️ 创建新索引...")
if not os.path.exists(DATA_DIR) or not os.listdir(DATA_DIR):
raise FileNotFoundError(f"请先将文档放入 {DATA_DIR} 文件夹")
# 加载文档(自动识别PDF/Word/TXT等格式)
print(f"???? 正在读取文档...")
documents = SimpleDirectoryReader(
DATA_DIR,
required_exts=[".pdf", ".docx", ".doc", ".txt", ".md"],
filename_as_id=True
).load_data()
print(f" 找到 {len(documents)} 个文件")
# 设置文档处理管道(分块)
parser = SentenceSplitter(
chunk_size=CHUNK_SIZE,
chunk_overlap=CHUNK_OVERLAP,
paragraph_separator="\n\n"
)
# 构建索引(自动完成分块、向量化、存储)
index = VectorStoreIndex.from_documents(
documents,
storage_context=storage_context,
transformations=[parser],
show_progress=True
)
print(f"✅ 索引创建完成,共 {self.collection.count()} 个片段")
return index
def query(self, question: str) -> dict:
"""查询知识库"""
# 配置检索器
retriever = self.index.as_retriever(
similarity_top_k=TOP_K,
vector_store_query_mode="default"
)
# 创建查询引擎
query_engine = self.index.as_query_engine(
retriever=retriever,
response_mode="compact", # 紧凑模式,节省token
verbose=False
)
# 执行查询
print(f"???? 查询: {question}")
response = query_engine.query(question)
return {
"answer": str(response),
"sources": [node.node.metadata.get("file_name", "未知")
for node in response.source_nodes],
"chunks": [node.text[:200] + "..." for node in response.source_nodes]
}
def add_document(self, file_path: str):
"""动态添加单个文档"""
from llama_index.core import SimpleDirectoryReader
documents = SimpleDirectoryReader(input_files=[file_path]).load_data()
for doc in documents:
self.index.insert(doc)
print(f"✅ 已添加: {os.path.basename(file_path)}")
def get_stats(self):
"""获取知识库统计"""
return {
"文档片段数": self.collection.count(),
"嵌入模型": EMBED_MODEL,
"大模型": LLM_MODEL,
"存储路径": os.path.abspath(CHROMA_PATH)
}
3. 交互式查询 `query.py`
通过命令行与你的本地知识库进行交互式问答。
"""交互式查询界面"""
from rag_engine import RAGEngine
def main():
# 初始化(首次运行会下载嵌入模型,约100MB)
engine = RAGEngine()
# 显示统计
print("???? 知识库状态:")
for k, v in engine.get_stats().items():
print(f" {k}: {v}")
print("\n" + "="*50)
# 交互循环
print("???? 输入问题(输入 'quit' 退出,输入 'stats' 查看统计)\n")
while True:
try:
question = input("❓ 你的问题: ").strip()
if question.lower() == 'quit':
print("???? 再见!")
break
elif question.lower() == 'stats':
print(engine.get_stats())
continue
elif not question:
continue
# 执行查询
result = engine.query(question)
print(f"\n???? 回答:\n{result['answer']}\n")
print("???? 参考来源:")
for i, (src, chunk) in enumerate(zip(result['sources'], result['chunks']), 1):
print(f" [{i}] {src}")
print(f" 片段: {chunk}\n")
print("-"*50)
except KeyboardInterrupt:
print("\n???? 再见!")
break
except Exception as e:
print(f"❌ 错误: {e}")
if __name__ == "__main__":
main()
4. 索引重建工具 `rebuild.py`
当源文档更新后,使用此脚本清空现有向量索引并从头构建。
"""重建索引(文档更新后使用)"""
import shutil
import os
from config import CHROMA_PATH
from rag_engine import RAGEngine
def main():
print("⚠️ 警告: 这将删除现有索引并重建")
confirm = input("确认删除并重建? (yes/no): ")
if confirm.lower() != 'yes':
print("已取消")
return
# 删除旧数据库
if os.path.exists(CHROMA_PATH):
shutil.rmtree(CHROMA_PATH)
print(f"????️ 已删除: {CHROMA_PATH}")
# 重新初始化(自动重建)
engine = RAGEngine()
print("✅ 重建完成")
if __name__ == "__main__":
main()
5. 批量导入工具 `batch_import.py`
用于将指定文件夹内的大量文档快速导入到知识库中。
"""批量导入文件夹中的文档"""
import os
from rag_engine import RAGEngine
def main():
engine = RAGEngine()
folder = input("请输入要导入的文件夹路径: ").strip()
if not os.path.exists(folder):
print("❌ 路径不存在")
return
files = [f for f in os.listdir(folder)
if f.endswith(('.pdf', '.docx', '.doc', '.txt', '.md'))]
print(f"找到 {len(files)} 个文档")
for f in files:
full_path = os.path.join(folder, f)
try:
engine.add_document(full_path)
except Exception as e:
print(f"❌ 导入失败 {f}: {e}")
print(f"\n✅ 导入完成,当前共 {engine.get_stats()['文档片段数']} 个片段")
if __name__ == "__main__":
main()
五、快速开始步骤
按照以下步骤,快速启动并运行你的本地RAG系统。
1. 创建项目文件夹
建议在非系统盘(如D盘或E盘)创建项目,以避免潜在的权限问题。
# 在D盘创建项目文件夹
mkdir D:\rag_project
cd D:\rag_project
# 创建必要的子文件夹
mkdir data
mkdir chroma_db
2. 保存代码
将上面四个Python文件(`config.py`, `rag_engine.py`, `query.py`, `rebuild.py`, `batch_import.py`)保存到刚创建的`D:\rag_project`目录下。
3. 放入测试文档
准备一些测试文档,如公司制度、产品手册或技术文档,放入`data`文件夹。
4. 运行
在项目目录下打开命令行,确保已激活`rag`虚拟环境,运行查询脚本:
python query.py
程序将首次初始化,下载嵌入模型并构建向量索引,之后即可开始问答交互。
六、预期输出
成功运行后,你将在命令行看到类似以下的交互过程:
???? 正在初始化RAG引擎...
???? 加载嵌入模型: BAAI/bge-small-zh-v1.5
???? 连接Ollama模型: llama3.2
????️ 连接向量数据库: ./chroma_db
????️ 创建新索引...
???? 正在读取文档...
找到 3 个文件
✅ 索引创建完成,共 15 个片段
✅ 初始化完成!
???? 知识库状态:
文档片段数: 15
嵌入模型: BAAI/bge-small-zh-v1.5
大模型: llama3.2
存储路径: D:\rag_project\chroma_db
==================================================
???? 输入问题(输入 'quit' 退出,输入 'stats' 查看统计)
❓ 你的问题: 公司的年假有多少天?
???? 查询: 公司的年假有多少天?
???? 回答:
根据《员工手册》规定,入职满1年可享受5天带薪年假,满10年可享受10天...
???? 参考来源:
[1] 员工手册.pdf
片段: 第五章 休假制度 5.1 年假规定:员工累计工作已满1年不满10年的,年休假5天...
[2] 人力资源政策.docx
片段: 年假申请流程:提前3天在OA系统提交申请,经部门主管审批...
--------------------------------------------------
七、常见问题
| 问题 | 解决 |
|---|---|
Ollama connection refused |
确保Ollama后台服务已启动(任务栏应有羊驼图标),或在命令行运行 ollama serve |
| 中文显示乱码 | 在CMD窗口输入 chcp 65001 切换到UTF-8编码 |
| 内存不足 | 尝试更小的模型:ollama pull llama3.2:1b(仅需约1GB内存) |
| 导入PDF失败 | 尝试安装 pip install pypdf2,或者将PDF文件转换为TXT格式 |
八、零成本确认清单
- ✅ LlamaIndex:开源框架,免费。
- ✅ ChromaDB:向量数据库本地运行,免费。
- ✅ 嵌入模型:从Hugging Face本地下载,免费。
- ✅ 大模型:通过Ollama在本地运行,免费。
- ✅ 文档解析库:如pypdf,开源免费。
总成本:0元。整个过程无需任何API Key,所有计算和存储都在你的本地电脑上完成。
来源:互联网
本网站新闻资讯均来自公开渠道,力求准确但不保证绝对无误,内容观点仅代表作者本人,与本站无关。若涉及侵权,请联系我们处理。本站保留对声明的修改权,最终解释权归本站所有。