基于LangChain与SGLang的本地知识库开发实战
本文介绍了一个完全本地化的RAG系统构建方案,基于LangChain框架和A40 48G显卡资源实现。系统采用的技术栈包括Ubuntu 22.04、Conda环境管理、SGLang推理框架、Chroma向量数据库等。详细阐述了环境配置步骤(包括系统更新、Conda安装、Python环境创建)和核心组件安装(LangChain、SGLang、PyTorch等)。文章提供了文档处理模块和向量存储模块的
·
作者:吴业亮
博客:wuyeliang.blog.csdn.net
系统架构概述
本方案将构建一个完全本地化、数据隐私安全的检索增强生成(RAG)系统。系统通过LangChain框架协调各个组件,利用您本地的A40 48G显卡资源,实现高效的文档处理和智能问答功能。
技术栈选型
| 组件 | 选型 | 说明 |
|---|---|---|
| 操作系统 | Ubuntu 22.04 LTS | 稳定的基础环境 |
| 环境管理 | Conda | Python环境隔离与管理 |
| 大模型推理 | SGLang | 高性能推理运行时,优化LLM执行效率 |
| 开发框架 | LangChain | LLM应用开发框架,提供RAG核心组件 |
| 向量数据库 | Chroma | 轻量级、嵌入式向量数据库 |
| Embedding模型 | BGE系列或Sentence-Transformers | 生成文本向量表示 |
| Web框架 | Gradio/FastAPI | 提供用户友好的交互界面 |
核心数据流
- 文档处理流程:本地文档 → 文本加载与清洗 → 智能分块 → 向量化 → 向量存储
- 问答流程:用户提问 → 查询向量化 → 向量相似性检索 → 提示词构建 → LLM生成 → 结果返回
环境准备与配置
1. Ubuntu 22.04基础环境配置
首先确保系统已更新并安装必要的依赖包:
sudo apt update && sudo apt upgrade -y
sudo apt install -y wget git build-essential libgl1-mesa-glx libegl1-mesa libxrandr2 libxss1 libxcursor1 libxcomposite1 libasound2 libxi6 libxtst6
2. Conda环境安装与配置
按照以下步骤安装Anaconda并配置环境:
# 下载Anaconda(选择最新Python 3.10+版本)
wget https://repo.anaconda.com/archive/Anaconda3-2024.10-1-Linux-x86_64.sh
# 安装Anaconda
bash Anaconda3-2024.10-1-Linux-x86_64.sh
# 安装过程中一路回车并确认许可协议,最后输入yes完成安装
# 激活Conda配置
source ~/.bashrc
# 验证安装
conda --version
若安装后无法识别conda命令,需手动添加环境变量到~/.bashrc文件末尾:
export PATH="~/anaconda3/bin:$PATH"
export PATH="/home/$USER/anaconda3/bin:$PATH" # 根据实际安装路径调整
source ~/.bashrc
配置国内镜像源加速下载:
conda config --add channels https://mirrors.tuna.tsinghua.edu.cn/anaconda/pkgs/free
conda config --add channels https://mirrors.tuna.tsinghua.edu.cn/anaconda/pkgs/main
3. 创建专用Python环境
# 创建Python 3.10环境
conda create -n rag_system python=3.10 -y
# 激活环境
conda activate rag_system
核心组件安装与配置
1. 安装LangChain及相关依赖
# 核心框架
pip install langchain langchain-community langchain-core
# 文档处理库(支持PDF、Word、Markdown等格式)
pip install pypdf python-docx markdown unstructured
# 文本分割与处理
pip install tiktoken sentence-transformers
# 向量数据库
pip install chromadb
2. 安装SGLang并配置本地模型
SGLang是一个专门优化大语言模型推理的高性能运行时,特别适合复杂的提示词结构和RAG场景。
# 安装SGLang
pip install sglang
# 安装PyTorch(根据CUDA版本选择)
pip install torch torchvision torchaudio --index-url https://download.pytorch.org/whl/cu121
# 安装vLLM后端(SGLang常用后端)
pip install vllm
3. 下载并配置本地大模型
利用A40 48G显卡的强大显存,您可以部署7B-13B参数规模的量化模型:
# 创建模型存储目录
mkdir -p models/local_llm
# 示例:下载一个适合A40显卡的模型(如Qwen7B-Chat或Llama2-7B-Chat)
# 模型文件应放置到models目录下
模型选型建议:
- Qwen2.5-7B-Chat:中文支持优秀,性能均衡
- Llama2-7B-Chat:英文任务表现出色,社区支持好
- DeepSeek-R1-7B:专门优化推理能力
4. 验证CUDA环境
A40显卡需要正确的CUDA驱动支持:
# 检查显卡驱动和可支持的最高CUDA版本
nvidia-smi
# 如果未安装驱动,先安装推荐驱动
sudo apt install nvidia-driver-550
# 验证PyTorch能否识别GPU
python -c "import torch; print(f'CUDA可用: {torch.cuda.is_available()}'); print(f'设备数量: {torch.cuda.device_count()}'); print(f'当前设备: {torch.cuda.current_device()}')"
知识库系统实现
1. 文档处理模块
创建document_processor.py:
import os
from langchain.document_loaders import (
PyPDFLoader,
Docx2txtLoader,
TextLoader,
UnstructuredMarkdownLoader
)
from langchain.text_splitter import RecursiveCharacterTextSplitter
class DocumentProcessor:
def __init__(self, chunk_size=500, chunk_overlap=50):
self.text_splitter = RecursiveCharacterTextSplitter(
chunk_size=chunk_size,
chunk_overlap=chunk_overlap,
separators=["\n\n", "\n", "。", "!", "?", ".", ".", " ", ""]
)
def load_documents(self, directory_path):
"""加载目录下的所有支持格式文档"""
documents = []
for filename in os.listdir(directory_path):
file_path = os.path.join(directory_path, filename)
ext = os.path.splitext(filename)[1].lower()
try:
if ext == ".pdf":
loader = PyPDFLoader(file_path)
elif ext == ".docx":
loader = Docx2txtLoader(file_path)
elif ext == ".md":
loader = UnstructuredMarkdownLoader(file_path)
elif ext == ".txt":
loader = TextLoader(file_path, encoding='utf-8')
else:
print(f"跳过不支持的文件格式: {filename}")
continue
loaded_docs = loader.load()
documents.extend(loaded_docs)
print(f"成功加载: {filename}, 文档数: {len(loaded_docs)}")
except Exception as e:
print(f"加载文档 {filename} 时出错: {str(e)}")
return documents
def split_documents(self, documents):
"""分割文档为适当大小的块"""
return self.text_splitter.split_documents(documents)
2. 向量存储模块
创建vector_store.py:
from langchain.vectorstores import Chroma
from langchain.embeddings import HuggingFaceEmbeddings
class VectorStoreManager:
def __init__(self, persist_directory="./chroma_db"):
self.persist_directory = persist_directory
# 使用本地Embedding模型
self.embeddings = HuggingFaceEmbeddings(
model_name="BAAI/bge-small-zh-v1.5", # 中文优化模型
model_kwargs={'device': 'cuda'},
encode_kwargs={'normalize_embeddings': True}
)
def create_vector_store(self, documents):
"""创建向量存储"""
vector_store = Chroma.from_documents(
documents=documents,
embedding=self.embeddings,
persist_directory=self.persist_directory
)
vector_store.persist()
return vector_store
def load_existing_store(self):
"""加载已存在的向量存储"""
return Chroma(
persist_directory=self.persist_directory,
embedding_function=self.embeddings
)
3. SGLang模型集成
创建sglang_llm.py:
import os
from langchain.llms.base import LLM
from typing import Optional, List, Any, Mapping
from sglang import RuntimeEndpoint
class SGLangLLM(LLM):
"""自定义SGLang本地模型集成"""
def __init__(self, model_path: str, host: str = "http://localhost", port: int = 30000):
self.endpoint = RuntimeEndpoint(f"{host}:{port}")
self.model_path = model_path
super().__init__()
def _call(self, prompt: str, stop: Optional[List[str]] = None) -> str:
# 使用SGLang执行模型推理
response = self.endpoint.generate(
prompt,
temperature=0.1,
max_tokens=2048,
stop=stop
)
return response.text.strip()
@property
def _llm_type(self) -> str:
return "sglang-local"
4. RAG链实现
创建rag_system.py:
from langchain.chains import RetrievalQA
from langchain.prompts import PromptTemplate
from sglang_llm import SGLangLLM
from vector_store import VectorStoreManager
class RAGSystem:
def __init__(self, model_path, vector_store_dir="./chroma_db"):
self.llm = SGLangLLM(model_path=model_path)
self.vector_store_mgr = VectorStoreManager(vector_store_dir)
self.vector_store = self.vector_store_mgr.load_existing_store()
self.qa_chain = self._setup_rag_chain()
def _setup_rag_chain(self):
"""设置RAG链"""
prompt_template = """你是一个专业的本地知识库助手。请严格根据以下上下文信息回答问题。如果上下文没有足够信息,请如实告知,不要编造信息。
上下文:
{context}
问题:{question}
请根据上下文提供准确、简洁的回答:"""
PROMPT = PromptTemplate(
template=prompt_template,
input_variables=["context", "question"]
)
return RetrievalQA.from_chain_type(
llm=self.llm,
chain_type="stuff",
retriever=self.vector_store.as_retriever(
search_type="similarity",
search_kwargs={"k": 4, "score_threshold": 0.6}
),
chain_type_kwargs={"prompt": PROMPT},
return_source_documents=True
)
def query(self, question: str) -> dict:
"""执行查询"""
return self.qa_chain({"query": question})
Web系统开发
使用Gradio创建友好的用户界面,创建app.py:
import gradio as gr
from rag_system import RAGSystem
import os
# 初始化RAG系统
rag_system = RAGSystem(
model_path="./models/your_local_model", # 替换为实际模型路径
vector_store_dir="./chroma_db"
)
def chat_interface(question, history):
"""处理用户问答"""
if not question.strip():
return "请输入问题"
try:
result = rag_system.query(question)
answer = result["result"]
# 添加参考来源显示
sources = "\n\n参考来源:"
for i, doc in enumerate(result["source_documents"]):
source_info = f"文档{i+1}: {os.path.basename(doc.metadata.get('source', '未知'))}"
sources += f"\n- {source_info}"
return answer + sources
except Exception as e:
return f"处理问题时出错:{str(e)}"
def build_web_interface():
"""构建Gradio Web界面"""
with gr.Blocks(
title="本地知识库AI助手",
theme=gr.themes.Soft(),
css="""
.message { font-size: 16px; }
.title { text-align: center; }
"""
) as demo:
gr.Markdown(
"""
# <div class="title">本地知识库AI助手</div>
> 基于LangChain + SGLang构建,数据完全本地处理
"""
)
with gr.Row():
with gr.Column(scale=4):
chatbot = gr.Chatbot(
label="问答对话",
height=500,
show_copy_button=True
)
msg = gr.Textbox(
label="输入您的问题",
placeholder="请输入关于您知识库的问题...",
lines=2
)
with gr.Column(scale=1):
gr.Markdown("### 系统信息")
gr.Markdown(f"**模型状态**: 已加载")
gr.Markdown(f"**知识库**: 已就绪")
gr.Markdown(f"**硬件**: A40 48GB GPU")
clear_btn = gr.Button("清空对话", variant="secondary")
# 事件处理
def respond(message, chat_history):
response = chat_interface(message, chat_history)
chat_history.append((message, response))
return "", chat_history
msg.submit(respond, [msg, chatbot], [msg, chatbot])
clear_btn.click(lambda: None, None, chatbot, queue=False)
return demo
if __name__ == "__main__":
# 启动Web服务
demo = build_web_interface()
demo.launch(
server_name="0.0.0.0",
server_port=7860,
share=False
)
系统部署与运行
1. 项目结构组织
local_rag_system/
├── app.py # 主应用入口
├── document_processor.py # 文档处理模块
├── vector_store.py # 向量存储管理
├── sglang_llm.py # SGLang模型集成
├── rag_system.py # RAG核心逻辑
├── requirements.txt # 依赖列表
├── knowledge_base/ # 知识库文档目录
├── models/ # 本地模型存储
└── chroma_db/ # 向量数据库持久化目录
2. 安装依赖文件
创建requirements.txt:
langchain>=0.1.0
langchain-community>=0.0.1
langchain-core>=0.1.0
chromadb>=0.4.0
sentence-transformers>=2.2.0
gradio>=4.0.0
sglang>=0.1.0
vllm>=0.3.0
torch>=2.0.0
accelerate>=0.20.0
pypdf>=3.0.0
python-docx>=1.1.0
unstructured>=0.10.0
3. 启动脚本
创建启动脚本start_server.sh:
#!/bin/bash
# 激活Conda环境
conda activate rag_system
# 启动SGLang服务端(假设已下载模型)
python -m sglang.launch_server --model-path ./models/your_model --port 30000 --host 0.0.0.0 &
# 等待服务端启动
sleep 30
# 启动Gradio Web界面
python app.py
赋予执行权限并运行:
chmod +x start_server.sh
./start_server.sh
性能优化建议
-
GPU内存优化:
- 使用模型量化(4-bit/8-bit)减少显存占用
- 调整批处理大小平衡吞吐量和延迟
- 启用FlashAttention优化注意力计算
-
检索优化:
- 尝试不同分块策略(技术文档300-500字,长报告800-1200字)
- 使用混合检索(语义+关键词)提升召回率
- 实现重排序(re-ranking)改善结果相关性
-
生成优化:
- 设计约束性提示词减少模型幻觉
- 设置合适的temperature参数(0.1-0.3提高准确性)
- 使用流式输出改善用户体验
故障排除
常见问题解决:
- CUDA内存不足:减小批处理大小,使用模型量化
- 检索效果差:调整分块大小,尝试不同Embedding模型
- 模型加载失败:检查模型文件完整性,确认格式兼容性
- Web界面无法访问:检查防火墙设置,确认端口7860可访问
更多推荐



所有评论(0)