本地LLM部署
High Contrast
Dark Mode
Light Mode
Sepia
Forest
2 min read458 words

本地LLM部署

在自己的机器上运行LLM,无需依赖云服务。

为什么本地部署?

本地部署优势

优势 说明
隐私安全 数据不离开本地
成本为零 无需API费用
无网络依赖 离线可用
无限调用 没有速率限制
自定义 可修改模型

本地部署劣势

Ollama部署

Ollama是最简单的本地LLM部署工具。

安装Ollama

# macOS
curl -fsSL https://ollama.com/install.sh | sh
# Linux
curl -fsSL https://ollama.com/install.sh | sh
# Windows
# 下载: https://ollama.com/download
# 验证安装
ollama --version

下载模型

# 查看可用模型
ollama list
# 下载模型
ollama pull mistral      # 7B参数,约4GB
ollama pull llama3       # 8B参数,约4.5GB
ollama pull qwen2        # 7B参数,约4GB
ollama pull codellama    # 7B参数,代码模型,约3.8GB
# 量化模型(更小)
ollama pull mistral:7b-q4_0  # 4-bit量化,约2.3GB

使用Ollama

# 命令行交互
ollama run mistral
# 查看模型信息
ollama show mistral
# 删除模型
ollama rm mistral
# 更新模型
ollama pull mistral

Python集成

from langchain_community.llms import Ollama
# 初始化
llm = Ollama(model="mistral")
# 生成文本
response = llm.invoke("用Python写一个快速排序")
print(response)
# 流式输出
for chunk in llm.stream("讲一个短故事"):
print(chunk, end="", flush=True)

Streamlit应用

import streamlit as st
from langchain_community.llms import Ollama
st.title("🤖 本地LLM聊天")
# 侧边栏
with st.sidebar:
model_name = st.selectbox(
"选择模型",
["mistral", "llama3", "qwen2", "codellama"]
)
temperature = st.slider("温度", 0.0, 2.0, 0.7)
# 初始化
@st.cache_resource
def get_llm(model, temp):
return Ollama(model=model, temperature=temp)
llm = get_llm(model_name, temperature)
# 对话历史
if "messages" not in st.session_state:
st.session_state.messages = []
# 显示历史
for message in st.session_state.messages:
with st.chat_message(message["role"]):
st.markdown(message["content"])
# 用户输入
if prompt := st.chat_input("输入消息..."):
with st.chat_message("user"):
st.markdown(prompt)
st.session_state.messages.append({"role": "user", "content": prompt})
# 生成回复
with st.chat_message("assistant"):
with st.spinner("思考中..."):
response = llm.invoke(prompt)
st.markdown(response)
st.session_state.messages.append({"role": "assistant", "content": response})

运行:

streamlit run ollama_chat.py

vLLM部署

vLLM是高性能推理引擎,适合生产环境。

安装vLLM

# 需要CUDA环境
pip install vllm

使用vLLM

from vllm import LLM, SamplingParams
# 初始化模型
llm = LLM(
model="mistralai/Mistral-7B-Instruct-v0.2",
tensor_parallel_size=1,  # GPU数量
max_model_len=4096
)
# 采样参数
sampling_params = SamplingParams(
temperature=0.7,
top_p=0.9,
max_tokens=500
)
# 生成
prompts = ["写一个Python函数计算斐波那契数列"]
outputs = llm.generate(prompts, sampling_params)
for output in outputs:
print(f"输出: {output.outputs[0].text}")

启动API服务

# 启动vLLM API服务
python -m vllm.entrypoints.api_server \
--model mistralai/Mistral-7B-Instruct-v0.2 \
--host 0.0.0.0 \
--port 8000 \
--tensor-parallel-size 1
# 访问API
curl http://localhost:8000/generate \
-H "Content-Type: application/json" \
-d '{
"prompt": "Hello, my name is",
"max_tokens": 50
}'

llama.cpp部署

llama.cpp支持CPU推理,无GPU也能运行。

安装llama.cpp

# 克隆仓库
git clone https://github.com/ggerganov/llama.cpp
cd llama.cpp
# 编译
make
# 或使用Python绑定
pip install llama-cpp-python

下载模型文件

# 下载GGUF格式模型
wget https://huggingface.co/TheBloke/Mistral-7B-Instruct-v0.2-GGUF/resolve/main/mistral-7b-instruct-v0.2.Q4_K_M.gguf

使用llama.cpp

from llama_cpp import Llama
# 初始化
llm = Llama(
model_path="mistral-7b-instruct-v0.2.Q4_K_M.gguf",
n_ctx=4096,  # 上下文长度
n_gpu_layers=-1  # -1表示所有层使用GPU
)
# 生成
output = llm(
"Q: 写一个Python函数计算阶乘\nA:",
max_tokens=200,
stop=["Q:", "\n"],
echo=True
)
print(output['choices'][0]['text'])

Web界面

# 启动Web服务器
python -m llama_cpp.server \
--model mistral-7b-instruct-v0.2.Q4_K_M.gguf \
--host 0.0.0.0 \
--port 8000
# 访问 http://localhost:8000

硬件要求

不同模型的硬件需求

模型 参数量 推荐显存 最小显存
Mistral-7B 7B 16GB 8GB
Llama-3-8B 8B 16GB 8GB
Qwen-7B 7B 16GB 8GB
CodeLlama-7B 7B 16GB 8GB
Llama-3-70B 70B 48GB 24GB

量化后需求

量化 显存占用 性能损失
FP16 100% 0%
INT8 50% <1%
INT4 25% 2-5%

性能优化

1. KV Cache

from vllm import LLM, SamplingParams
llm = LLM(
model="mistralai/Mistral-7B-Instruct-v0.2",
enable_prefix_caching=True  # 启用前缀缓存
)

2. 批处理

# 批量推理
prompts = ["问题1", "问题2", "问题3"]
outputs = llm.generate(prompts, sampling_params)

3. 多GPU

# 使用4个GPU
python -m vllm.entrypoints.api_server \
--model mistralai/Mistral-7B-Instruct-v0.2 \
--tensor-parallel-size 4

实践项目

本地RAG系统

import streamlit as st
from langchain_community.llms import Ollama
from langchain_community.vectorstores import Chroma
from langchain_community.embeddings import OllamaEmbeddings
from langchain.text_splitter import RecursiveCharacterTextSplitter
# 配置
st.set_page_config(page_title="本地RAG", layout="wide")
# 初始化
@st.cache_resource
def get_llm():
return Ollama(model="mistral")
@st.cache_resource
def get_embeddings():
return OllamaEmbeddings()
@st.cache_resource
def get_vectorstore():
return Chroma(
persist_directory="./chroma_db",
embedding_function=get_embeddings()
)
llm = get_llm()
embeddings = get_embeddings()
vectorstore = get_vectorstore()
# 上传文档
st.sidebar.title("📚 知识库管理")
uploaded_files = st.sidebar.file_uploader(
"上传文档",
type=["txt", "md"],
accept_multiple_files=True
)
if uploaded_files:
texts = [f.read().decode("utf-8") for f in uploaded_files]
# 分割
splitter = RecursiveCharacterTextSplitter(chunk_size=1000, chunk_overlap=200)
chunks = splitter.create_documents(texts)
# 添加到向量库
vectorstore.add_documents(chunks)
st.sidebar.success(f"添加了 {len(chunks)} 个文档块")
# 主界面
st.title("🔍 本地RAG查询")
query = st.text_input("输入你的问题...")
if query:
# 检索
retriever = vectorstore.as_retriever(search_kwargs={"k": 3})
docs = retriever.invoke(query)
# 构建上下文
context = "\n\n".join([doc.page_content for doc in docs])
# 生成回答
prompt = f"""
基于以下信息回答问题:
{context}
问题:{query}
回答:
"""
with st.spinner("生成中..."):
response = llm.invoke(prompt)
st.markdown("### 📝 回答")
st.markdown(response)
st.markdown("### 📚 参考来源")
for i, doc in enumerate(docs, 1):
st.markdown(f"{i}. {doc.page_content[:200]}...")

故障排查

问题1: 显存不足

# 解决方案:使用量化模型
ollama pull mistral:7b-q4_0
# 或减少上下文长度
--max-model-len 2048

问题2: 推理速度慢

# 解决方案:减少批大小
--max-num-seqs 8
# 或使用更小的模型
ollama pull phi3-mini  # 3.8B参数

问题3: 编译错误

# 解决方案:安装正确版本
pip install --upgrade pip
pip install --upgrade setuptools wheel

学习要点

✅ Ollama是最简单的本地LLM部署方式 ✅ vLLM适合高性能生产环境 ✅ llama.cpp支持CPU推理 ✅ 量化可以显著降低显存需求 ✅ 本地RAG结合向量数据库和本地LLM ✅ 硬件要求与模型大小和量化相关


下一步: 学习 云端部署 ☁️