无 GPU 环境下的 RAG 系统搭建实践
最近我在研究如何在没有 GPU 的服务器上部署本地知识库。很多教程都默认你有一块好显卡,但现实是不少人手头只有 CPU 服务器。经过一番折腾,我总结出了这套方案。
一、硬件准备(最低配置)
我先说说硬件要求。没有 GPU 并不意味着配置可以很低,实际上 CPU 推理对内存的依赖更大。
计算设备
- CPU:Intel i7 12代 / AMD Ryzen 7 5800X 或更高
- RAM:32GB DDR4(建议64GB+以提升大模型推理效率)
- 存储:1TB NVMe SSD(存储大模型权重和知识库)
- 网络:千兆局域网
我踩过的坑
- 内存一定要够大,我最初用 16GB 跑 7B 模型直接 OOM 了,后来加到 64GB 才稳定
- SSD 很重要,模型加载时间从机械硬盘的几分钟缩短到 SSD 的十几秒
- 多线程要配置好,默认配置下 Python 可能只用了一半的 CPU 核心
二、软件环境搭建
我选的是 Ubuntu 22.04 LTS,稳定且社区支持好。
1. 操作系统
# 首先更新系统
sudo apt update && sudo apt upgrade -y
sudo apt install build-essential zlib1g-dev libssl-dev libffi-dev wget curl
2. Python环境
我用 Miniconda 而不是完整版 Anaconda,因为它轻量很多。
# 安装 Miniconda
wget https://repo.anaconda.com/miniconda/Miniconda3-latest-Linux-x86_64.sh
bash Miniconda3-latest-Linux-x86_64.sh
# 创建专用 Python 环境
conda create -n knowledge_base python=3.10
conda activate knowledge_base
3. 安装关键依赖
注意这里用的是 CPU 版本的 PyTorch:
pip install torch torchvision torchaudio --index-url https://download.pytorch.org/whl/cpu
pip install transformers==4.32.0 sentence-transformers faiss-cpu langchain
pip install llama-cpp-python # 这是 CPU 推理的核心
4. 安装编译工具
这一步很容易漏掉,但 OpenMP 支持对性能影响很大:
# 安装 GCC 编译器和 libgomp 库(用于 OpenMP 支持)
conda install -c anaconda gcc_linux-64 gxx_linux-64
conda install -c conda-forge libgomp
三、模型选择与部署(仅支持CPU)
这是我测试过的几个模型,都能在纯 CPU 环境下运行。
1. 适合CPU运行的模型
| 模型 | 适用场景 | 最低RAM需求 |
|---|---|---|
| ChatGLM3-6B-CPU | 中文问答 | 32GB |
| Mistral-7B-Instruct-v0.2-GGUF | 轻量级LLM | 16GB |
| Llama-3-8B-Instruct-GGUF | 通用智能 | 64GB |
| Qwen-1.8B-Chat | 超低资源环境 | 8GB |
注意:GGUF 格式是优化后的低资源推理模型格式,CPU 推理必备。
2. 下载并转换模型
首先要编译 llama.cpp,现在必须用 cmake,make 方式已经不支持了:
git clone https://github.com/ggerganov/llama.cpp
cd llama.cpp && make -j$(nproc)
下载模型需要先在 HuggingFace 注册并获取 token:
# 下载并转换模型(以 Mistral 7B 为例)
from huggingface_hub import snapshot_download
snapshot_download(repo_id="mistralai/Mistral-7B-Instruct-v0.2", local_dir="./mistral")
# 转换为 GGUF 格式
python llama.cpp/convert-hf-to-gguf.py mistral/ --outfile mistral.gguf
3. 运行CPU推理
我推荐 4-bit 量化,内存占用能减少一半以上:
# 4-bit 量化(减少RAM占用)
./llama.cpp/quantize mistral.gguf mistral-q4_0.gguf q4_0
# 启动模型服务(启用CPU优化)
./llama.cpp/server -m mistral-q4_0.gguf --port 8000 --threads $(nproc)
四、知识库构建
这部分我用的是 LangChain + FAISS 的组合,简单有效。
1. 数据预处理
from langchain.document_loaders import DirectoryLoader
from langchain.text_splitter import RecursiveCharacterTextSplitter
loader = DirectoryLoader('./docs', glob="**/*.txt")
documents = loader.load()
text_splitter = RecursiveCharacterTextSplitter(
chunk_size=500, chunk_overlap=50, separators=["\n\n", "\n", "。", "!", "?"]
)
splits = text_splitter.split_documents(documents)
2. 构建向量数据库
from langchain.embeddings import HuggingFaceEmbeddings
from langchain.vectorstores import FAISS
embeddings = HuggingFaceEmbeddings(model_name="BAAI/bge-small-zh-v1.5") # 适合CPU
vectorstore = FAISS.from_documents(splits, embeddings)
vectorstore.save_local("faiss_index")
五、RAG增强实现
RAG(检索增强生成)是知识库问答的核心,我的配置如下:
from langchain.chains import RetrievalQA
from langchain.prompts import PromptTemplate
prompt_template = """基于以下上下文和你的知识,用中文回答:
上下文:{context}
问题:{question}
答案:"""
QA_CHAIN_PROMPT = PromptTemplate.from_template(prompt_template)
qa_chain = RetrievalQA.from_chain_type(
llm, retriever=vectorstore.as_retriever(), chain_type_kwargs={"prompt": QA_CHAIN_PROMPT}
)
六、API系统部署
知识库跑起来后,还需要对外提供服务。我用 FastAPI 做接口,Nginx 做反向代理。
1. API接口(FastAPI)
from fastapi import FastAPI
from pydantic import BaseModel
app = FastAPI()
class Query(BaseModel):
question: str
user_id: str
@app.post("/ask")
async def ask(query: Query):
result = qa_chain({"query": query.question})
return {"answer": result["result"], "sources": result["source_documents"]}
# 启动命令
# uvicorn main:app --host 0.0.0.0 --port 7860 --workers 2
2. 反向代理(Nginx)
我用 Nginx 做 HTTPS 和负载均衡:
server {
listen 443 ssl;
server_name knowledge.example.com;
ssl_certificate /etc/ssl/certs/knowledge.pem;
ssl_certificate_key /etc/ssl/private/knowledge.key;
location / {
proxy_pass http://localhost:7860;
proxy_set_header X-Real-IP $remote_addr;
}
}
七、优化与监控
纯 CPU 推理性能有限,优化很重要。
1. 推理性能优化
OpenBLAS 对矩阵运算加速明显:
# 安装 CPU 计算库
sudo apt install libopenblas-dev libomp-dev
# 启用 Pytorch 线程优化
export OMP_NUM_THREADS=$(nproc)
export MKL_NUM_THREADS=$(nproc)
2. 监控系统(Prometheus + Grafana)
我用 Docker 快速部署监控:
docker run -d --name prometheus -p 9090:9090 -v ./prometheus.yml:/etc/prometheus/prometheus.yml prom/prometheus
docker run -d --name grafana -p 3000:3000 grafana/grafana-enterprise
八、增量知识库更新
知识库不是一次性的,需要支持增量更新:
def update_knowledge(file_path):
new_docs = loader.load(file_path)
new_splits = text_splitter.split_documents(new_docs)
vectorstore.add_documents(new_splits)
vectorstore.save_local("faiss_index")
九、扩展方案
后续我还计划做的事情。
1. 分布式部署
如果单机性能不够,可以用 Ray 做分布式:
# Ray CPU 集群优化
ray start --head --port=6379 --dashboard-port=8265
ray start --address='192.168.1.100:6379'
2. 浏览器插件
为了方便使用,我还写了个简单的浏览器插件:
chrome.runtime.onMessage.addListener((request, sender, sendResponse) => {
if (request.action === "query") {
fetch('https://knowledge-base/api/ask', {
method: 'POST',
headers: {'Authorization': 'Bearer ' + token},
body: JSON.stringify({question: request.question})
}).then(response => sendResponse(response.json()))
}
});
总结
这套方案的核心是:
- GGUF 格式 + llama.cpp:让大模型能在 CPU 上跑起来
- 4-bit 量化:大幅减少内存占用
- LangChain + FAISS:构建高效的向量检索
- FastAPI + Nginx:提供生产级 API 服务
实测下来,7B 模型在 64GB 内存的服务器上推理速度大约 2-3 tokens/s,虽然比 GPU 慢很多,但对于内部知识库场景完全够用了。
版权声明: 如无特别声明,本文版权归 sshipanoo 所有,转载请注明本文链接。
(采用 CC BY-NC-SA 4.0 许可协议进行授权)
本文标题:《 Python 本地知识库部署(仅 CPU) 》
本文链接:http://localhost:3015/ai/Python%E6%9C%AC%E5%9C%B0%E9%83%A8%E7%BD%B2%E7%9F%A5%E8%AF%86%E5%BA%93.html
本文最后一次更新为 天前,文章中的某些内容可能已过时!