网站首页 > 基础教程 正文
尊敬的诸位!我是一名物联网工程师。关注我,持续分享最新物联网与AI资讯和开发实战。期望与您携手探寻物联网与 AI 的无尽可能
今天我想和各位分享一个实用的项目:如何使用LangChain和Ollama构建一个完全本地化的RAG(检索增强生成)系统。作为技术从业者,我们经常需要从大量文档中快速获取信息,而这个知识库助手正是为解决这一痛点而设计的。
什么是RAG?为什么需要本地部署?
RAG(检索增强生成)是一种将文档检索与大语言模型结合的技术。与单纯依赖LLM相比,RAG通过检索相关文档来增强生成内容的准确性和相关性。
而本地部署有以下几个优势:
- 数据隐私得到保障
- 无需网络连接即可使用
- 没有API调用费用
- 可以完全自定义和调整
接下来让我们一步步解析这个知识库系统的实现。
技术栈概览
这个项目使用了以下技术:
- LangChain: 用于构建RAG工作流
- Ollama: 本地运行开源大语言模型
- Chroma: 向量数据库,用于存储和检索文档嵌入
- Phi-3: 微软开源的高性能LLM,通过Ollama本地部署
代码解析
1. 导入必要库和初始化
from langchain_community.document_loaders import DirectoryLoader, TextLoader
from langchain.text_splitter import RecursiveCharacterTextSplitter
from langchain_community.vectorstores import Chroma
from langchain_core.prompts import ChatPromptTemplate
from langchain_ollama.llms import OllamaLLM
from langchain_ollama.embeddings import OllamaEmbeddings
from langchain.memory import ConversationBufferMemory
from langchain_core.output_parsers import StrOutputParser
import os
import shutil
import sys
这部分导入了构建RAG系统所需的各种组件,包括文档加载器、文本分割器、向量存储、提示模板等。
2. KnowledgeBase类设计
class KnowledgeBase:
def __init__(self, docs_dir="knowledge_base", db_dir="knowledge_base_index"):
self.docs_dir = docs_dir
self.db_dir = db_dir
self.embeddings = OllamaEmbeddings(
model="phi3:latest",
base_url="http://localhost:11434"
)
self.initialize_dirs()
这个类是整个系统的核心,负责:
- 管理文档和索引的目录
- 初始化嵌入模型(这里使用Phi-3通过Ollama生成嵌入)
- 设置和维护整个知识库结构
3. 目录初始化和示例文档创建
def initialize_dirs(self):
"""初始化目录结构"""
os.makedirs(self.docs_dir, exist_ok=True)
# 创建示例文档
self.create_sample_docs()
def create_sample_docs(self):
"""创建示例文档"""
samples = {
"python.txt": """
Python编程语言简介:
Python是一种高级编程语言,以其简洁、易读的语法著称。
主要特点:
1. 简单易学
2. 丰富的库支持
3. 跨平台兼容
4. 面向对象
""",
# 其他示例文档...
}
for filename, content in samples.items():
filepath = os.path.join(self.docs_dir, filename)
with open(filepath, 'w', encoding='utf-8') as f:
f.write(content.strip())
这部分代码负责创建知识库目录并添加一些示例文档。在实际使用中,你可以将自己的文档放入该目录。
4. 文档加载和向量化
def load_documents(self):
"""加载文档"""
loader = DirectoryLoader(
self.docs_dir,
glob="**/*.txt",
loader_cls=TextLoader,
loader_kwargs={'encoding': 'utf-8'}
)
documents = loader.load()
# 文本分割
text_splitter = RecursiveCharacterTextSplitter(
chunk_size=500,
chunk_overlap=50
)
splits = text_splitter.split_documents(documents)
# 创建向量存储
if os.path.exists(self.db_dir):
shutil.rmtree(self.db_dir)
self.vectordb = Chroma.from_documents(
documents=splits,
embedding=self.embeddings,
persist_directory=self.db_dir
)
这部分代码执行RAG系统中最关键的步骤:
- 加载目录中的所有txt文档
- 将文档分割成较小的文本块(这里设置为500字符)
- 为每个文本块创建向量嵌入
- 将向量存储在Chroma数据库中
这样就建立了可以进行语义搜索的知识库索引。
5. 设置检索链
def setup_retrieval_chain(self, model):
"""设置检索链"""
template = """你是一个专业的知识库助手。
基于以下上下文信息回答用户问题。
如果无法从上下文中找到答案,请说明无法回答。
上下文信息:
{context}
问题:{question}
请给出清晰、准确的回答。"""
prompt = ChatPromptTemplate.from_messages([
("system", template)
])
self.chain = (
{"context": lambda x: self.vectordb.similarity_search(x["question"]),
"question": lambda x: x["question"]}
| prompt
| model
| StrOutputParser()
)
这部分使用LangChain的链式API设计了整个RAG流程:
- 根据用户问题执行相似性搜索,获取相关文档
- 将这些文档作为上下文信息传给模型
- 使用预设模板生成提示
- 将提示传给语言模型并解析回答
6. 主函数和交互逻辑
def main():
try:
print("初始化个人知识库...")
# 初始化知识库
kb = KnowledgeBase()
kb.load_documents()
# 初始化模型
model = OllamaLLM(
model="phi3:latest",
temperature=0.1,
num_ctx=2048,
)
# 设置检索链
kb.setup_retrieval_chain(model)
print("\n知识库助手已启动!")
print("示例问题:")
# 示例问题提示...
while True:
question = input("\n请输入问题: ").strip()
if not question:
continue
if question.lower() == 'quit':
break
print("\n正在查找答案...\n")
try:
response = kb.chain.invoke({"question": question})
print("答案:")
print("-" * 50)
print(response)
print("-" * 50)
except Exception as e:
print(f"查询出错: {str(e)}")
except Exception as e:
print(f"程序错误: {str(e)}")
print("\n按回车键继续...")
input()
主函数负责初始化知识库、设置模型和启动交互式问答循环。用户可以输入问题,系统会检索相关信息并生成回答。
如何使用这个项目
- 安装依赖:确保已安装LangChain、Chroma等依赖库
- 安装Ollama:从ollama.ai下载并安装
- 拉取模型:运行ollama pull phi3获取Phi-3模型
- 运行程序:执行python knowledge_base.py启动知识库助手
- 添加自己的文档:将文本文件放入knowledge_base目录
扩展和优化思路
这个基础版本可以有多种扩展方向:
- 支持更多文档格式:PDF、Word、Markdown等
- 改进文本分割策略:基于语义或结构的分割
- 添加记忆功能:保存对话历史以支持多轮问答
- 实现网页界面:使用Flask或Streamlit构建UI
- 自定义向量索引:尝试不同的向量数据库如FAISS或Milvus
与读者互动
各位技术爱好者,你们有遇到过哪些文档管理和信息检索的痛点?对这个本地RAG系统有什么改进建议?
记得关注我的账号,获取更多关于物联网、AI和RAG系统的实战项目和技术解析。我会持续带来真实可用的技术分享,帮大家避开套路,掌握核心技术。
猜你喜欢
- 2025-03-10 go语言text/template标准库
- 2025-03-10 Python 的os和shutil包简介
- 2025-03-10 前端代码质量-圈复杂度原理和实践
- 2025-03-10 近2万字详解JAVA NIO2文件操作,过瘾
- 2025-03-10 这两个Python库,轻而易举就能实现MP4与GIF格式互转,太好用了
- 2025-03-10 Python技巧之实现智能文件整理,轻松分类图片、文档、视频等
- 2025-03-10 Python之Pandas使用系列(八):读写Excel文件的各种技巧
- 2025-03-10 Python 实现 批量 复制指定PDF文件 到指定文件夹并批量打印出来
- 2025-03-10 深入理解 Linux 位置无关代码 PIC
- 2025-03-10 什么是微调?如何用微调模型完成图像分类?
- 05-14CSS基础知识(一) CSS入门
- 05-14CSS是什么? CSS和HTML有什么关系?
- 05-14什么是CSS3?
- 05-14CSS如何画一个三角形?
- 05-14初识CSS——CSS三角制作
- 05-14Wordpress建站教程:给图片添加CSS样式
- 05-14HTML和HTML5,css和css3的区别有哪些?
- 05-14Html中Css样式Ⅱ
- 最近发表
- 标签列表
-
- jsp (69)
- pythonlist (60)
- gitpush (78)
- gitreset (66)
- python字典 (67)
- dockercp (63)
- gitclone命令 (63)
- dockersave (62)
- linux命令大全 (65)
- mysql教程 (60)
- pythonif (86)
- location.href (69)
- deletesql (62)
- c++模板 (62)
- linuxgzip (68)
- 字符串连接 (73)
- nginx配置文件详解 (61)
- html标签 (69)
- c++初始化列表 (64)
- mysqlinnodbmyisam区别 (63)
- arraylistadd (66)
- console.table (62)
- mysqldatesub函数 (63)
- window10java环境变量设置 (66)
- c++虚函数和纯虚函数的区别 (66)