第3章:基于LlamaIndex+Ollama+ChromaDB搭建本地简单RAG问答系统

一、代码详细解析:

(一)代码整体概述

本地私有化部署的检索增强生成(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嵌入模型适配),分别对应导入ChromaVectorStoreOllamaOllamaEmbedding

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系统核心由三大组件构成,各组件分工明确、轻量易用:

  1. LlamaIndex:作为RAG框架,负责文档加载、文本分割、向量索引构建、查询流程调度,简化RAG系统的开发复杂度;
  2. Ollama:轻量级大模型部署工具,可一键拉取并运行各类开源大模型(如Gemma3、Llama2)和嵌入模型,无需复杂的环境配置;
  3. 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
问答系统已退出

五、优化与扩展方向

  1. 模型升级 :若设备性能允许,可将gemma3:1b替换为llama3:8bgemma3:7b等更大模型,提升回答质量;
  2. 文档格式扩展 :LlamaIndex支持pdf、docx等格式,只需修改input_files中的文件路径,无需修改核心代码;
  3. 文本分割优化 :可根据文档类型调整chunk_sizechunk_overlap,例如技术文档可适当增大分片尺寸;
  4. 检索策略优化 :可修改查询引擎的检索参数(如similarity_top_k),调整返回的相似文本数量,平衡回答准确性与速度;
  5. 界面美化:可结合Gradio、Streamlit搭建可视化界面,替代命令行交互,提升使用体验。

六、总结

本文通过LlamaIndex、Ollama和ChromaDB,快速搭建了一套本地私有化RAG问答系统,全程无需云服务,既保障了数据隐私安全,又能高效问答本地文档。该系统适合个人学习、小型团队内部文档查询、专业领域知识库搭建等场景,且具备良好的扩展性,可根据需求灵活优化。

相关推荐
geneculture2 小时前
融智学:重构认知与实践的智慧体系
大数据·人工智能·融智学的重要应用·信智序位·人类智力·融智时代(杂志)
智源研究院官方账号2 小时前
智源数字孪生心脏升级:全自动跨尺度心脏毒性推演,构建“可计算”的药物研发未来
人工智能
代码游侠2 小时前
应用——UDP 网络编程
linux·运维·开发语言·学习·算法
私人珍藏库2 小时前
[吾爱大神原创工具] PythonEnvManager - Python 环境管理工具 [更新自定义扫描路径]
开发语言·python
前端程序猿之路2 小时前
AI大模型应用开发之Prompt 工程
人工智能·python·深度学习·机器学习·prompt·ai编程·提示词
呆萌很2 小时前
PyCharm 中使用 Anaconda
python
AI科技星2 小时前
光速的几何本质与运动极限:基于张祥前统一场论对光子及有质量粒子运动的统一诠释
数据结构·人工智能·经验分享·算法·计算机视觉
梦想的旅途22 小时前
外部群消息监听的轮询与 Hook 机制对比
人工智能·自动化·企业微信
唐装鼠2 小时前
Rust Turbofish 语法详解(deepseek)
开发语言·后端·rust