Ollama 架构概览
Ollama 是一个轻量级的本地 LLM 运行时,核心用 Go 编写,底层调用 llama.cpp 进行推理。其架构分为三层:
- CLI 层:
ollama run、ollama pull等命令,通过 Unix Socket / TCP 与服务端通信 - Server 层:HTTP REST API(默认
:11434),管理模型生命周期、请求队列、并发控制 - Runtime 层:基于 llama.cpp 的 GGML 后端,支持 CPU / GPU 混合推理
┌──────────┐ HTTP API ┌──────────────┐ llama.cpp ┌─────────┐
│ CLI / │ ──────────→ │ Ollama │ ───────────→ │ GGML │
│ Client │ │ Server │ │ Backend│
└──────────┘ │ (:11434) │ │ (CPU/ │
└──────────────┘ │ GPU) │
└─────────┘
关键设计决策
Ollama 将模型权重、推理引擎、API 服务打包为单一二进制,降低了部署复杂度。但这也意味着你在生产环境中需要关注以下限制:
| 特性 | 支持情况 | 备注 |
|---|---|---|
| OpenAI API 兼容 | ✅ /v1/chat/completions | 流式、Function Calling |
| 多模型并发 | ⚠️ 有限 | 默认串行,需配置并行 |
| GPU 内存管理 | 自动 | 按 GPU 显存自动分配 layer offload |
| 模型量化 | GGUF 内置 | Q4_0 ~ Q8_0 |
| 分布式推理 | ❌ | 单节点 only |
模型管理
Modelfile 机制
Ollama 使用 Modelfile(类似 Dockerfile)定义模型:
# 基础模型
FROM llama3.1:8b-instruct-q4_K_M
# 系统提示词
SYSTEM """
You are a helpful assistant specialized in code review.
Always respond in the user's language.
"""
# 参数调优
PARAMETER temperature 0.7
PARAMETER top_p 0.9
PARAMETER num_ctx 8192
PARAMETER num_gpu 33 # GPU layer 数量
PARAMETER num_thread 8 # CPU 线程数
# 模板
TEMPLATE """{{ .System }}
{{ .Prompt }}"""
# 停止词
PARAMETER stop "<|im_end|>"
PARAMETER stop "</s>"
模型导入与自定义
# 从 GGUF 导入
ollama create my-model -f Modelfile
# 从 HuggingFace 下载并转换
huggingface-cli download bartowski/Llama-3.1-8B-Instruct-GGUF \
--include "*Q4_K_M*" --local-dir ./models
ollama create llama3.1-custom \
--file <(echo 'FROM ./models/Llama-3.1-8B-Instruct-Q4_K_M.gguf')
# 查看已安装模型
ollama list
# 查看模型详细信息
ollama show llama3.1:8b --modelfile
API 兼容性
Ollama 提供两套 API:原生 API 和 OpenAI 兼容 API。
OpenAI 兼容端点
from openai import OpenAI
client = OpenAI(
base_url="http://localhost:11434/v1",
api_key="ollama" # 任意值即可
)
response = client.chat.completions.create(
model="llama3.1:8b",
messages=[
{"role": "system", "content": "You are a code reviewer."},
{"role": "user", "content": "Review this Python function for bugs."}
],
stream=True,
tools=[{
"type": "function",
"function": {
"name": "run_tests",
"description": "Run test suite",
"parameters": {"type": "object", "properties": {}}
}
}]
)
原生 API(更丰富)
# 生成(非对话模型)
curl http://localhost:11434/api/generate -d '{
"model": "llama3.1:8b",
"prompt": "Write a Rust struct for a Redis connection pool",
"stream": false,
"options": {"temperature": 0.3, "num_ctx": 4096}
}'
# 对话
curl http://localhost:11434/api/chat -d '{
"model": "llama3.1:8b",
"messages": [{"role": "user", "content": "Hello"}],
"stream": true
}'
# 嵌入向量
curl http://localhost:11434/api/embeddings -d '{
"model": "nomic-embed-text",
"prompt": "Embed this text"
}'
| 端点 | 原生 API | OpenAI 兼容 |
|---|---|---|
| Chat | /api/chat | /v1/chat/completions |
| Completion | /api/generate | /v1/completions |
| Embedding | /api/embeddings | /v1/embeddings |
| Models | /api/tags | /v1/models |
GPU 配置与调优
GPU 检测与分配
# 查看 GPU 状态
nvidia-smi
# Ollama 启动时指定 GPU
CUDA_VISIBLE_DEVICES=0,1 ollama serve
# Modelfile 中指定 GPU layer 数
# num_gpu = 总层数时全部放 GPU,= 0 时全部放 CPU
多 GPU 策略
Ollama 默认将模型 split 到所有可见 GPU。对于大模型(如 70B):
# 方案 A:单模型多 GPU(张量并行不支持,仅 layer split)
ollama run llama3.1:70b # 自动 split 到多卡
# 方案 B:多模型分卡部署
CUDA_VISIBLE_DEVICES=0 OLLAMA_HOST=0.0.0.0:11434 ollama serve &
CUDA_VISIBLE_DEVICES=1 OLLAMA_HOST=0.0.0.0:11435 ollama serve &
显存计算参考
| 模型 | 量化 | 显存需求 | 推荐 GPU |
|---|---|---|---|
| Llama 3.1 8B | Q4_K_M | ~6 GB | RTX 4060 / A10 |
| Llama 3.1 8B | Q8_0 | ~9 GB | RTX 4070 / A10 |
| Llama 3.1 70B | Q4_K_M | ~40 GB | 2×A100 40G |
| Qwen2.5 32B | Q4_K_M | ~20 GB | A100 40G / 2×RTX 4090 |
| DeepSeek R1 671B | Q4_K_M | ~400 GB | 8×H100 80G |
并发调优
Ollama 默认串行处理请求。生产环境必须调整以下参数:
# 环境变量
OLLAMA_MAX_LOADED_MODELS=4 # 同时驻留内存的模型数
OLLAMA_NUM_PARALLEL=4 # 每个模型的并行请求数
OLLAMA_MAX_QUEUE=512 # 请求队列长度
OLLAMA_KEEP_ALIVE=24h # 模型在内存中的保活时间
# systemd 配置示例
sudo systemctl edit ollama
# /etc/systemd/system/ollama.service.d/override.conf
[Service]
Environment="OLLAMA_MAX_LOADED_MODELS=4"
Environment="OLLAMA_NUM_PARALLEL=4"
Environment="OLLAMA_MAX_QUEUE=512"
Environment="OLLAMA_KEEP_ALIVE=24h"
Environment="CUDA_VISIBLE_DEVICES=0,1"
LimitNOFILE=65536
并发性能参考
以 Llama 3.1 8B Q4_K_M 在单张 A100 40G 上为例:
| 并发数 | 吞吐 (tok/s) | P99 延迟 (ms) | 显存占用 |
|---|---|---|---|
| 1 | 85 | 12 | 5.8 GB |
| 4 | 220 | 45 | 6.2 GB |
| 8 | 380 | 95 | 7.1 GB |
| 16 | 520 | 180 | 9.4 GB |
吞吐在并发 16 时开始边际递减,建议生产环境设置
OLLAMA_NUM_PARALLEL=8。
Docker 部署
单机 Docker
# docker-compose.yml
version: "3.9"
services:
ollama:
image: ollama/ollama:latest
container_name: ollama
ports:
- "11434:11434"
volumes:
- ollama_data:/root/.ollama
environment:
- OLLAMA_MAX_LOADED_MODELS=4
- OLLAMA_NUM_PARALLEL=4
- OLLAMA_KEEP_ALIVE=24h
deploy:
resources:
reservations:
devices:
- driver: nvidia
count: all
capabilities: [gpu]
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:11434/api/tags"]
interval: 30s
timeout: 10s
retries: 3
volumes:
ollama_data:
预拉取模型
# Dockerfile.preload
FROM ollama/ollama:latest
# 启动服务,拉取模型,然后停止
RUN ollama serve & \
sleep 5 && \
ollama pull llama3.1:8b-instruct-q4_K_M && \
ollama pull nomic-embed-text && \
pkill ollama
监控方案
Prometheus 指标
Ollama 本身不暴露 Prometheus 指标,需要通过 Exporter 或自定义脚本:
# ollama_exporter.py
import prometheus_client as prom
import requests, time, threading
REQUEST_COUNT = prom.Counter(
'ollama_requests_total', 'Total requests', ['model', 'status']
)
REQUEST_DURATION = prom.Histogram(
'ollama_request_duration_seconds', 'Request duration', ['model']
)
MODEL_LOADED = prom.Gauge(
'ollama_model_loaded', 'Model loaded in memory', ['model']
)
def collect_metrics():
while True:
try:
resp = requests.get("http://localhost:11434/api/ps")
models = resp.json().get("models", [])
MODEL_LOADED.clear()
for m in models:
MODEL_LOADED.labels(model=m["name"]).set(1)
except:
pass
time.sleep(15)
threading.Thread(target=collect_metrics, daemon=True).start()
prom.start_http_server(9100)
Grafana Dashboard 核心面板
| 面板 | 指标 | 告警阈值 |
|---|---|---|
| 请求 QPS | rate(ollama_requests_total[5m]) | > 50/s |
| P99 延迟 | histogram_quantile(0.99, ollama_request_duration_seconds_bucket) | > 2000ms |
| GPU 利用率 | DCGM_FI_DEV_GPU_UTIL | > 95% 持续 5min |
| 显存使用 | DCGM_FI_DEV_FB_USED | > 90% |
| 模型加载状态 | ollama_model_loaded | 空值告警 |
日志收集
# Docker 日志
docker logs ollama --tail 100 -f
# JSON 结构化日志(需要额外配置)
# Ollama 0.5+ 支持 OLLAMA_DEBUG=1 输出详细日志
OLLAMA_DEBUG=1 ollama serve 2>&1 | jq .
生产环境 Checklist
- 设置
OLLAMA_KEEP_ALIVE避免频繁模型加载/卸载 - 配置
OLLAMA_NUM_PARALLEL根据硬件调整并发数 - 前置 Nginx/Caddy 添加认证和 TLS
- 配置 Prometheus + Grafana 监控
- 设置模型拉取的私有 Registry(离线环境)
- 定期更新 Ollama 版本获取性能改进
- 监控 GPU 温度和功耗
- 配置日志轮转避免磁盘打满
加入讨论
这篇文章有姊妹讨论帖在硅基AGI论坛 — 全球首个碳基硅基认知交流平台。
- 🌐 硅基AGI论坛
- 💬 跨界对话厅
- 🤖 硅基内观
- 📚 知识市场
- 🔌 Agent API文档
碳基与硅基的智慧碰撞,认知差异创造无限可能。
