一、代码详细解析:
(一)代码整体概述
本地私有化部署的检索增强生成(RAG)问答系统 :无需依赖第三方云服务,通过LlamaIndex作为RAG框架、Ollama部署本地大模型和嵌入模型、ChromaDB作为向量数据库,实现对本地文档(./data/wenxin.txt)的智能问答。核心流程为「文档加载→文本分割→向量存储→智能查询」,全程在本地环境运行,保障数据隐私安全。
(二)逐段代码解析
1. 编码声明与依赖导入
python
# -*- coding: utf-8 -*-
import chromadb
# check "llama-index" version->:0.14.10
from llama_index.core import VectorStoreIndex,StorageContext
from llama_index.core import SimpleDirectoryReader,Settings
from llama_index.core.node_parser import SentenceSplitter
# Need->:pip install llama-index-vector-stores-chroma
from llama_index.vector_stores.chroma import ChromaVectorStore
# Need->:pip install llama-index-llms-ollama
from llama_index.llms.ollama import Ollama
# Need->:pip install llama-index-embeddings-ollama
from llama_index.embeddings.ollama import OllamaEmbedding
- 编码声明:
# -*- coding: utf-8 -*-确保脚本支持中文编码,避免中文乱码问题; - 核心依赖导入说明:
chromadb:导入ChromaDB向量数据库,用于存储文本嵌入向量;- LlamaIndex核心模块:
VectorStoreIndex(向量存储索引)、StorageContext(存储上下文)、SimpleDirectoryReader(本地文档读取器)、Settings(全局配置类)、SentenceSplitter(文本分割器); - 独立适配包:因LlamaIndex≥0.10.0拆分了功能模块,需单独安装
llama-index-vector-stores-chroma(Chroma向量存储适配)、llama-index-llms-ollama(Ollama大模型适配)、llama-index-embeddings-ollama(Ollama嵌入模型适配),分别对应导入ChromaVectorStore、Ollama、OllamaEmbedding。
2. 全局模型配置(Settings)
python
# Set model & embedding
Settings.llm = Ollama(model="gemma3:1b")
Settings.embed_model = OllamaEmbedding(model_name="milkey/dmeta-embedding-zh:f16")
Settings.llm:配置本地大语言模型,使用Ollama部署的gemma3:1b模型(Google推出的轻量级大模型,10亿参数,适合本地低配设备运行,兼顾效果与速度);Settings.embed_model:配置文本嵌入模型,使用Ollama的milkey/dmeta-embedding-zh:f16(专为中文优化的轻量级嵌入模型,半精度存储,体积小、速度快,适合中文文本向量化);- 作用:全局配置生效,后续LlamaIndex的所有组件都会复用该模型配置,无需重复定义。
3. 本地文档加载
python
# load document
reader = SimpleDirectoryReader(input_files=["./data/wenxin.txt"])
documents = reader.load_data()
SimpleDirectoryReader:LlamaIndex内置的文档读取器,支持多种格式(txt、pdf、docx等),此处指定读取./data/wenxin.txt本地文本文件;load_data():执行文档加载,将文件内容转换为LlamaIndex可处理的Document对象列表,后续用于文本分割。
4. 文本分割(Node Parsing)
python
# split document
node_parser = SentenceSplitter(chunk_size=100,chunk_overlap=50)
nodes = node_parser.get_nodes_from_documents(documents,show_progress=False)
SentenceSplitter:基于句子的文本分割器,解决大模型上下文长度限制问题,同时保证语义完整性;chunk_size=100:每个文本分片(chunk)的最大令牌数约为100(对应中文约50-100字);chunk_overlap=50:相邻分片重叠50个令牌,避免语义割裂,提升检索准确性;
get_nodes_from_documents:将加载的文档分割为Node对象(LlamaIndex的基础数据单元,包含文本内容、元数据等信息),show_progress=False关闭进度条显示。
5. ChromaDB向量数据库初始化
python
# prepare verctor index
chroma = chromadb.PersistentClient(path="./chroma_db")
chroma.delete_collection(name="ragdb")
collection = chroma.get_or_create_collection(name="ragdb")
metadata = {"hnsw:space":"cosine"}
vector_store = ChromaVectorStore(chroma_collection=collection)
chromadb.PersistentClient(path="./chroma_db"):创建ChromaDB持久化客户端,数据存储在./chroma_db目录,重启程序后数据不丢失(区别于临时内存客户端);chroma.delete_collection(name="ragdb"):删除已存在的ragdb集合(避免重复运行时数据冗余,可根据需求注释该句保留历史数据);get_or_create_collection(name="ragdb"):创建(若不存在则获取)名为ragdb的向量集合,用于存储文本嵌入向量;metadata={"hnsw:space":"cosine"}:设置向量检索的相似度计算方式为余弦相似度(适用于文本语义匹配,常用还有欧氏距离、点积);ChromaVectorStore:将ChromaDB集合封装为LlamaIndex可识别的向量存储对象,建立LlamaIndex与ChromaDB的桥梁。
6. 向量索引构建
python
# 准备向量存储索引
storage_context = StorageContext.from_defaults(vector_store=vector_store)
index = VectorStoreIndex(nodes,storage_context=storage_context)
StorageContext.from_defaults(vector_store=vector_store):创建存储上下文,指定使用上述ChromaDB向量存储作为数据存储载体;VectorStoreIndex:构建向量存储索引,将分割后的Node对象转换为嵌入向量,并存入ChromaDB的ragdb集合中,完成「文本→向量」的存储流程。
7. 智能查询引擎构建与交互式问答
python
# 构造查询
query_engine = index.as_query_engine()
while True:
user_input = input("输入你的问题:")
if user_input.lower() == "exit":
break
response = query_engine.query(user_input)
print("AI助手: ",response.response)
index.as_query_engine():将向量索引转换为查询引擎,封装了「向量检索→上下文拼接→大模型生成」的完整RAG流程;- 交互式问答循环:
- 无限循环接收用户输入,输入
exit(不区分大小写)则退出程序; query_engine.query(user_input):执行查询,内部流程为「用户问题向量化→在ChromaDB中检索相似文本→将相似文本作为上下文拼接给大模型→大模型基于上下文生成回答」;response.response:获取大模型生成的最终回答内容并打印。
- 无限循环接收用户输入,输入
二、手把手搭建本地私有化RAG问答系统(LlamaIndex+Ollama+ChromaDB)
在大语言模型时代,检索增强生成(RAG)是解决大模型"幻觉"、提升专业领域问答准确性的核心技术。但很多同学担心第三方云服务的数据隐私问题,或是受限于网络环境无法使用在线API。今天,我们就来手把手搭建一套本地私有化部署的RAG问答系统,全程无需依赖任何云服务,基于LlamaIndex、Ollama和ChromaDB,轻松实现对本地文档的智能问答,兼顾数据安全与问答效果。
一、技术栈选型说明
本次搭建的RAG系统核心由三大组件构成,各组件分工明确、轻量易用:
- LlamaIndex:作为RAG框架,负责文档加载、文本分割、向量索引构建、查询流程调度,简化RAG系统的开发复杂度;
- Ollama:轻量级大模型部署工具,可一键拉取并运行各类开源大模型(如Gemma3、Llama2)和嵌入模型,无需复杂的环境配置;
- ChromaDB:轻量级开源向量数据库,专为存储和检索嵌入向量设计,支持持久化存储,适合本地部署和小规模应用。
二、前期准备
1. 环境要求
- Python 3.8及以上版本;
- 足够的磁盘空间(模型+数据约5-10GB,根据模型大小调整,
gemma3:1b仅需约2GB空间)。
2. 安装必备工具与依赖
(1)安装Ollama
- 下载地址:Ollama官方网站,根据操作系统选择对应安装包(Windows/Mac/Linux);
- 安装完成后,打开终端执行
ollama --version,验证安装成功。
(2)拉取所需模型
Ollama需提前拉取大语言模型和嵌入模型,终端执行以下命令:
bash
# 拉取Gemma3:1b大模型(轻量级,适合本地运行)
ollama pull gemma3:1b
# 拉取中文嵌入模型milkey/dmeta-embedding-zh:f16
ollama pull milkey/dmeta-embedding-zh:f16
(3)安装Python依赖包
创建并激活Python虚拟环境(可选,推荐),然后安装所需依赖:
bash
# 核心框架LlamaIndex(指定稳定版本0.14.10)
pip install llama-index==0.14.10
# ChromaDB向量数据库
pip install chromadb
# LlamaIndex与ChromaDB适配包
pip install llama-index-vector-stores-chroma
# LlamaIndex与Ollama大模型适配包
pip install llama-index-llms-ollama
# LlamaIndex与Ollama嵌入模型适配包
pip install llama-index-embeddings-ollama
# 国内镜像源加速(可选,解决下载慢)
pip install -i https://mirrors.aliyun.com/pypi/simple/ 上述包名
3. 准备本地文档
在项目根目录下创建data文件夹,放入需要问答的本地文档(本文以wenxin.txt为例,支持txt、pdf、docx等多种格式)。
三、核心代码实现与解析
下面我们逐行解析核心代码,同时完成系统搭建,所有代码可直接复制使用。
1. 项目结构
最终项目结构如下,清晰简洁,便于维护:
├── data/
│ └── wenxin.txt # 本地问答文档
├── chroma_db/ # ChromaDB持久化数据目录(自动生成)
└── rag_demo.py # 核心代码文件
2. 完整代码与关键解析
python
# -*- coding: utf-8 -*-
import chromadb
# LlamaIndex核心模块导入
from llama_index.core import VectorStoreIndex, StorageContext
from llama_index.core import SimpleDirectoryReader, Settings
from llama_index.core.node_parser import SentenceSplitter
# ChromaDB向量存储适配
from llama_index.vector_stores.chroma import ChromaVectorStore
# Ollama大模型适配
from llama_index.llms.ollama import Ollama
# Ollama嵌入模型适配
from llama_index.embeddings.ollama import OllamaEmbedding
# 1. 全局模型配置:指定本地大模型和嵌入模型
Settings.llm = Ollama(model="gemma3:1b") # 本地大模型
Settings.embed_model = OllamaEmbedding(model_name="milkey/dmeta-embedding-zh:f16") # 中文嵌入模型
# 2. 加载本地文档
reader = SimpleDirectoryReader(input_files=["./data/wenxin.txt"])
documents = reader.load_data()
print(f"文档加载完成,共加载 {len(documents)} 个文档对象")
# 3. 文本分割:解决大模型上下文限制
node_parser = SentenceSplitter(chunk_size=100, chunk_overlap=50)
nodes = node_parser.get_nodes_from_documents(documents, show_progress=False)
print(f"文本分割完成,共生成 {len(nodes)} 个文本分片")
# 4. 初始化ChromaDB向量数据库
chroma = chromadb.PersistentClient(path="./chroma_db") # 持久化存储
chroma.delete_collection(name="ragdb") # 清空历史集合(可选)
collection = chroma.get_or_create_collection(name="ragdb") # 创建向量集合
vector_store = ChromaVectorStore(chroma_collection=collection) # 封装为LlamaIndex向量存储
# 5. 构建向量索引:将文本分片转换为向量并存储
storage_context = StorageContext.from_defaults(vector_store=vector_store)
index = VectorStoreIndex(nodes, storage_context=storage_context)
print("向量索引构建完成,文本已转换为向量存入ChromaDB")
# 6. 创建查询引擎:封装RAG完整流程
query_engine = index.as_query_engine()
# 7. 交互式问答循环
print("===== 本地RAG问答系统已启动,输入exit退出 =====")
while True:
user_input = input("输入你的问题:")
if user_input.lower() == "exit":
print("问答系统已退出")
break
# 执行查询并返回结果
response = query_engine.query(user_input)
print("AI助手: ", response.response)
print("-" * 50)
关键代码亮点解析
- 全局配置:通过
Settings统一配置模型,无需重复传递参数,简化代码; - 文本分割:
SentenceSplitter按句子分割,设置chunk_overlap避免语义割裂,提升检索准确性; - 持久化存储:ChromaDB使用
PersistentClient,数据保存在本地,重启程序不丢失; - 交互式循环:支持持续问答,输入
exit即可退出,使用便捷。
四、运行与测试
1. 运行代码
在终端进入项目根目录,执行以下命令启动系统:
bash
python rag_demo.py
2. 测试问答
系统启动后,会提示"输入你的问题",此时可输入与wenxin.txt相关的问题,例如:
===== 本地RAG问答系统已启动,输入exit退出 =====
输入你的问题:文档中提到的核心观点是什么?
AI助手: XXX(基于文档内容生成的回答)
--------------------------------------------------
输入你的问题:exit
问答系统已退出
五、优化与扩展方向
- 模型升级 :若设备性能允许,可将
gemma3:1b替换为llama3:8b、gemma3:7b等更大模型,提升回答质量; - 文档格式扩展 :LlamaIndex支持pdf、docx等格式,只需修改
input_files中的文件路径,无需修改核心代码; - 文本分割优化 :可根据文档类型调整
chunk_size和chunk_overlap,例如技术文档可适当增大分片尺寸; - 检索策略优化 :可修改查询引擎的检索参数(如
similarity_top_k),调整返回的相似文本数量,平衡回答准确性与速度; - 界面美化:可结合Gradio、Streamlit搭建可视化界面,替代命令行交互,提升使用体验。
六、总结
本文通过LlamaIndex、Ollama和ChromaDB,快速搭建了一套本地私有化RAG问答系统,全程无需云服务,既保障了数据隐私安全,又能高效问答本地文档。该系统适合个人学习、小型团队内部文档查询、专业领域知识库搭建等场景,且具备良好的扩展性,可根据需求灵活优化。