AI Day 51
AI Day 51: 实战(1):本地大模型部署全流程 — 从安装到API服务
AI Day 51: 实战(1):本地大模型部署全流程 — 从安装到API服务
2026-05-22
日期: 2026-05-22 | 阶段: 第五阶段 · 动手实战 (Day 51-60) | 主题: Local LLM Deployment
学习路径 / Learning Path
AI/LLM 深度技术学习 60天计划
├── 第一阶段:模型基础 (Day 1-15) ✅
│ ├── Day 1: Transformer与LLM基础 ✅
│ ├── Day 2: 量化与本地部署 ✅
│ ├── Day 3: 训练全流程 ✅
│ ├── Day 4: Prompt Engineering ✅
│ ├── Day 5: RAG架构 ✅
│ ├── Day 6: 向量数据库与Embedding ✅
│ ├── Day 7: 微调技术 ✅
│ ├── Day 8: 推理优化 ✅
│ ├── Day 9: 长上下文技术 ✅
│ ├── Day 10: 多模态模型 ✅
│ ├── Day 11: 推理模型 ✅
│ ├── Day 12: Agent框架 ✅
│ ├── Day 13: MCP协议 ✅
│ ├── Day 14: 模型评估 ✅
│ └── Day 15: 阶段一总结 ✅
├── 第二阶段:工程实践 (Day 16-30) ✅
│ ├── Day 16: LLM应用架构 ✅
│ ├── Day 17: 安全与护栏 ✅
│ ├── Day 18: 可观测性 ✅
│ ├── Day 19: 生产RAG·解析与分块 ✅
│ ├── Day 20: 生产RAG·检索与重排 ✅
│ ├── Day 21: 生产RAG·评估与迭代 ✅
│ ├── Day 22: Agent状态与恢复 ✅
│ ├── Day 23: Agent成本优化 ✅
│ ├── Day 24: 多Agent系统 ✅
│ ├── Day 25: Agent测试部署 ✅
│ ├── Day 26: LLM成本工程 ✅
│ ├── Day 27: 多模型编排 ✅
│ ├── Day 28: LLM应用测试 ✅
│ ├── Day 29: 企业LLM平台 ✅
│ └── Day 30: 阶段二总结 ✅
├── 第三阶段:金融零售AI应用 (Day 31-42) ✅
│ ├── Day 31: 金融AI风控 ✅
│ ├── Day 32: 智能投顾与量化 ✅
│ ├── Day 33: 合规与RegTech ✅
│ ├── Day 34: 信贷AI全链路 ✅
│ ├── Day 35: 金融AI总结 ✅
│ ├── Day 36: 零售AI推荐 ✅
│ ├── Day 37: 智能客服 ✅
│ ├── Day 38: 供应链AI ✅
│ ├── Day 39: 智能营销 ✅
│ ├── Day 40: 零售AI总结 ✅
│ ├── Day 41: CeFi×DeFi×AI融合 ✅
│ └── Day 42: AI融合案例与职业 ✅
├── 第四阶段:面试冲刺 (Day 43-50) ✅
│ ├── Day 43: 系统设计·LLM平台 ✅
│ ├── Day 44: 系统设计·RAG系统 ✅
│ ├── Day 45: 系统设计·Agent系统 ✅
│ ├── Day 46: 系统设计·推荐系统 ✅
│ ├── Day 47: 面试·产品AI ✅
│ ├── Day 48: 面试·架构AI ✅
│ ├── Day 49: 面试·行为AI ✅
│ └── Day 50: 学习总结 ✅
└── 第五阶段:动手实战 (Day 51-60)
├── Day 51: 本地大模型部署全流程 ← 你在这里
├── Day 52: RAG系统实战:从文档到问答
├── Day 53: RAG进阶:评估优化与生产化
├── Day 54: LoRA微调实战:训练你的专属模型
├── Day 55: Agent开发实战:构建工具调用Agent
├── Day 56: MCP Server开发:扩展AI能力边界
├── Day 57: 多模态应用:图文理解与文档分析
├── Day 58: AI应用全栈开发:前后端集成
├── Day 59: 性能调优与成本实战
└── Day 60: 总结与作品集
核心概念 / Core Concepts
动手 = 最好的学习 / Hands-on = Best Learning
前50天的学习路径回顾:
Day 1-15: 理论基础 — 知道 "是什么"
Day 16-30: 工程实践 — 理解 "怎么做"
Day 31-42: 领域应用 — 明白 "做什么"
Day 43-50: 面试冲刺 — 能够 "讲出来"
Day 51-60: 动手实战 — 真正 "做出来" ← 现在开始!
为什么在最后才动手?
常见错误路径:
Day 1 就开始装 Ollama → 玩两天觉得好酷 → 不知道下一步做什么 → 放弃
正确路径(我们走的):
50天理论+工程+应用 → 带着明确目标动手 → 每一步都知道为什么
区别在于:
- 你现在知道 Q4_K_M 量化意味着什么(Day 2 学的)
- 你现在知道 KV Cache 为什么占显存(Day 8 学的)
- 你现在知道 Embedding 和向量检索的原理(Day 6 学的)
- 你现在知道 Prompt Engineering 的最佳实践(Day 4 学的)
理论50天 → 验证时刻 / 50 Days Theory → Verification Time
今天开始的10天,是对前50天学习的终极验证:
验证清单:
├── Day 51: 量化理论 → 实际部署不同量化模型,感受差异
├── Day 52: RAG架构 → 用自己的笔记构建真实RAG系统
├── Day 53: 评估方法 → 用RAGAS量化评估RAG效果
├── Day 54: 微调理论 → 实际LoRA微调一个模型
├── Day 55: Agent架构 → 构建可工作的Tool-Calling Agent
├── Day 56: MCP协议 → 开发真实的MCP Server
├── Day 57: 多模态理论 → 实际处理图片和文档
├── Day 58: 应用架构 → 前后端集成完整应用
├── Day 59: 优化理论 → 实测性能瓶颈并优化
└── Day 60: 全部整合 → 形成可展示的作品集
今天的核心目标:
输入:一台 Windows 电脑(8GB+ 显存的 NVIDIA GPU)
输出:一个可通过 API 调用的本地 LLM 服务
具体目标:
1. Ollama 安装并运行第一个模型
2. 对比 4 个不同模型的表现
3. 搭建 OpenAI 兼容的 API 服务
4. 了解 llama.cpp 底层运行
5. 掌握显存管理技巧
知识点1:Ollama 安装与使用 / Ollama Installation & Usage
为什么选择 Ollama?/ Why Ollama?
本地LLM部署工具对比:
工具 | 易用性 | 性能 | 灵活性 | 生态
-------------|--------|--------|--------|--------
Ollama | ★★★★★ | ★★★★ | ★★★ | ★★★★★ ← 首选
llama.cpp | ★★ | ★★★★★ | ★★★★★ | ★★★★
vLLM | ★★★ | ★★★★★ | ★★★★ | ★★★★
LocalAI | ★★★ | ★★★★ | ★★★★ | ★★★
LM Studio | ★★★★★ | ★★★★ | ★★ | ★★★
Ollama 胜出原因:
- 一行命令启动模型
- 内置 OpenAI 兼容 API
- 底层就是 llama.cpp(性能有保障)
- 生态丰富(Open WebUI / Dify / LangChain 都支持)
Windows 安装步骤 / Installation on Windows
# 方法1:官方安装包(推荐)
# 1. 访问 https://ollama.ai/download
# 2. 下载 Windows 安装包
# 3. 双击安装,一路 Next
# 4. 安装完成后自动启动服务
# 方法2:winget 安装
winget install Ollama.Ollama
# 方法3:如果你用 WSL2
curl -fsSL https://ollama.ai/install.sh | sh
安装验证:
# 打开命令行/终端
ollama --version
# 输出类似: ollama version is 0.6.x
# 检查服务是否运行
curl http://localhost:11434
# 输出: Ollama is running
Windows 特别注意:
常见问题与解决:
1. GPU 未被识别
原因: NVIDIA 驱动版本太老
解决: 更新到最新 Game Ready / Studio Driver
验证: nvidia-smi 能正常显示 GPU 信息
2. 端口被占用
原因: 其他服务占了 11434
解决: 设置环境变量 OLLAMA_HOST=0.0.0.0:11435
3. 模型下载慢
原因: 默认走国外 CDN
解决: 设置 OLLAMA_MODELS 路径到大容量磁盘
考虑使用代理加速下载
4. 显存不足
原因: 模型太大 / 其他程序占用显存
解决: 关闭浏览器GPU加速,先试小模型
常用命令 / Common Commands
# === 模型管理 ===
# 拉取模型(下载到本地)
ollama pull qwen2.5:7b-instruct-q4_K_M
ollama pull llama3.3:8b-instruct-q4_K_M
# 运行模型(自动下载 + 启动交互对话)
ollama run qwen2.5:7b
# 列出已下载的模型
ollama list
# 显示模型详情
ollama show qwen2.5:7b
# 删除模型
ollama rm qwen2.5:7b
# === 服务管理 ===
# 启动 Ollama 服务(Windows 通常自动启动)
ollama serve
# === 模型运行 ===
# 交互式对话
ollama run qwen2.5:7b
>>> 你好,介绍一下你自己
# 单次调用(管道输入)
echo "解释什么是Transformer" | ollama run qwen2.5:7b
# 从文件输入
ollama run qwen2.5:7b < prompt.txt
# 设置系统提示
ollama run qwen2.5:7b --system "你是一个金融分析师"
# === 复制和自定义 ===
# 基于已有模型创建副本
ollama cp qwen2.5:7b my-finance-model
模型库浏览 / Model Library
Ollama 模型库 (https://ollama.ai/library) 核心模型:
通用对话:
├── qwen2.5:7b — 阿里通义,中文最强 ★★★★★
├── llama3.3:8b — Meta,英文底座最强 ★★★★★
├── phi-4-mini:3.8b — 微软,小而精 ★★★★
├── gemma2:9b — Google,均衡 ★★★★
├── mistral:7b — Mistral AI,欧洲血统 ★★★★
└── deepseek-r1:7b — DeepSeek,推理强 ★★★★
代码专用:
├── qwen2.5-coder:7b — 代码能力突出
├── codellama:7b — Meta代码模型
└── deepseek-coder-v2:lite — DeepSeek代码
Embedding:
├── nomic-embed-text — 通用文本Embedding
├── bge-m3 — 多语言Embedding
└── mxbai-embed-large — 高质量Embedding
多模态(带视觉):
├── llava:7b — 基础视觉对话
├── llama3.2-vision:11b — Meta视觉模型
└── minicpm-v:8b — 面壁智能视觉
模型命名规则:
模型名:参数量-变体-量化
例如: qwen2.5:7b-instruct-q4_K_M
- 7b = 70亿参数
- instruct = 指令微调版
- q4_K_M = 4bit量化(K-quant Medium)
自定义 Modelfile / Custom Modelfile
# 文件名: Modelfile.finance-analyst
# 用途: 创建一个金融分析师模型
# 基础模型
FROM qwen2.5:7b-instruct-q4_K_M
# 系统提示
SYSTEM """你是一位资深金融分析师,专注于:
1. DeFi协议分析和评估
2. 传统金融与Web3的桥接
3. 风控和合规问题
4. 数据驱动的投资分析
回答时请:
- 用中文回答,关键术语附英文原文
- 提供数据支撑的分析
- 考虑风险因素
- 给出可执行的建议"""
# 模型参数
PARAMETER temperature 0.3
PARAMETER top_p 0.9
PARAMETER top_k 40
PARAMETER num_ctx 4096
PARAMETER repeat_penalty 1.1
PARAMETER stop "<|im_end|>"
# 对话模板(Qwen格式)
TEMPLATE """{{ if .System }}<|im_start|>system
{{ .System }}<|im_end|>
{{ end }}{{ if .Prompt }}<|im_start|>user
{{ .Prompt }}<|im_end|>
{{ end }}<|im_start|>assistant
{{ .Response }}<|im_end|>
"""
# 创建自定义模型
ollama create finance-analyst -f Modelfile.finance-analyst
# 运行自定义模型
ollama run finance-analyst
>>> 分析Aave V3的利率模型设计
# 验证模型信息
ollama show finance-analyst
知识点2:第一个本地模型 / Your First Local Model
推荐首选:Qwen2.5-7B-Instruct Q4 / Recommended: Qwen2.5-7B
为什么选 Qwen2.5-7B 作为第一个模型?
1. 中文能力最强 — 我们很多笔记是中英混合的
2. 7B 参数适中 — 8GB 显存刚好能跑
3. Q4 量化成熟 — 质量损失可接受
4. Instruct 版本 — 开箱即用,无需额外微调
Day 2 学的量化知识现在用上了:
- FP16: 7B × 2 bytes = 14GB → 显存不够
- Q8: 7B × 1 byte = 7GB → 勉强能跑
- Q4: 7B × 0.5 byte = 3.5GB → 舒适运行 ✓
- KV Cache 额外需要约 0.5-1GB
- 总计约 4-5GB 显存 → 8GB 显卡完全OK
下载与运行 / Download and Run
# Step 1: 下载模型(约 4.4GB)
ollama pull qwen2.5:7b-instruct-q4_K_M
# 下载过程观察:
# pulling manifest
# pulling 8de95da68dc4... 100% ▕████████████████▏ 4.4 GB
# pulling 62fbfd9ed093... 100% ▕████████████████▏ 182 B
# pulling c156170b718e... 100% ▕████████████████▏ 11 KB
# verifying sha256 digest
# writing manifest
# success
# Step 2: 运行模型
ollama run qwen2.5:7b-instruct-q4_K_M
# Step 3: 开始对话测试
>>> 你好!请用一段话介绍什么是DeFi
第一次对话测试 / First Conversation Tests
测试1: 基础中文对话
>>> 用简洁的语言解释什么是智能合约
预期观察:
- 首次加载需要几秒(模型加载到显存)
- 后续对话秒级响应
- 中文流畅度如何?
---
测试2: 英文能力
>>> Explain the difference between Optimistic Rollup and ZK Rollup in 3 sentences
预期观察:
- 英文是否流畅?
- 技术概念是否准确?
---
测试3: 代码能力
>>> 写一个Python函数,用aiohttp异步请求Ethereum JSON-RPC获取最新区块号
预期观察:
- 代码是否可运行?
- 是否处理了异常?
- 代码风格如何?
---
测试4: 推理能力
>>> 一个DeFi协议TVL从10亿跌到1亿,可能的原因有哪些?按可能性排序分析
预期观察:
- 是否有逻辑性?
- 分析是否全面?
- 是否有深度?
观察关键指标 / Key Metrics to Watch
# 在另一个终端监控 GPU
nvidia-smi -l 1 # 每秒刷新
# 关注这些指标:
GPU-Util: 生成时应该 80-100%
Memory-Usage: qwen2.5:7b Q4 约占 4.5-5GB
Temperature: 长时间运行注意温度
Power: 功耗变化
性能观察记录表:
指标 | 你的观测值 | 参考值
------------------|-----------|--------
模型加载时间 | ___ 秒 | 3-8秒
首Token延迟(TTFT) | ___ 秒 | 0.5-2秒
生成速度(tokens/s) | ___ t/s | 20-40 t/s (Q4, RTX 3060/4060)
显存占用 | ___ GB | 4.5-5.5GB
GPU利用率(生成时) | ___ % | 80-100%
Day 8 学过的指标,现在亲眼验证:
- TTFT (Time to First Token) — 用户感知的等待时间
- TPS (Tokens per Second) — 阅读体验的关键
- 这两个指标直接决定用户体验!
知识点3:模型对比实验 / Model Comparison Experiment
实验设计 / Experiment Design
目的:用同一套测试问题,对比不同模型的表现
方法:控制变量(同一台机器、同样的问题、同样的参数)
测试模型(4个):
1. Qwen2.5-7B-Instruct (Q4_K_M) — 阿里,中文标杆
2. Llama3.3-8B-Instruct (Q4_K_M) — Meta,英文标杆
3. Phi-4-mini (3.8B, Q4_K_M) — 微软,小模型代表
4. Gemma2-9B-Instruct (Q4_K_M) — Google,均衡选手
# 下载所有测试模型
ollama pull qwen2.5:7b-instruct-q4_K_M
ollama pull llama3.3:8b-instruct-q4_K_M
ollama pull phi4-mini:3.8b-q4_K_M
ollama pull gemma2:9b-instruct-q4_K_M
# 确认全部下载完成
ollama list
测试问题集 / Test Questions
准备 5 类问题,每类 1 题:
Q1 [中文理解]:
"解释DeFi中的'无常损失'概念,用一个具体数字例子说明"
Q2 [英文理解]:
"Compare the pros and cons of Account Abstraction (ERC-4337)
vs native smart contract wallets"
Q3 [代码生成]:
"Write a Python function that calculates the impermanent loss
given initial and current price ratio. Include docstring and
type hints."
Q4 [逻辑推理]:
"一个DEX协议想要设计代币激励来吸引流动性提供者。
但过高的代币奖励会导致抛压。请设计一个平衡方案,
并分析其博弈均衡。"
Q5 [信息提取]:
"从以下审计报告摘要中提取所有HIGH和CRITICAL风险项:
[此处粘贴一段审计报告文本]"
对比执行脚本 / Comparison Script
"""
model_comparison.py
对比多个本地模型的表现
"""
import requests
import time
import json
OLLAMA_URL = "http://localhost:11434/api/generate"
MODELS = [
"qwen2.5:7b-instruct-q4_K_M",
"llama3.3:8b-instruct-q4_K_M",
"phi4-mini:3.8b-q4_K_M",
"gemma2:9b-instruct-q4_K_M",
]
QUESTIONS = [
{
"category": "中文理解",
"prompt": "解释DeFi中的'无常损失'概念,用一个具体数字例子说明",
},
{
"category": "English",
"prompt": "Compare Account Abstraction (ERC-4337) vs native smart contract wallets in 5 bullet points",
},
{
"category": "代码生成",
"prompt": "Write a Python function that calculates impermanent loss given initial and current price ratio. Include docstring and type hints.",
},
{
"category": "逻辑推理",
"prompt": "一个DEX协议想设计代币激励吸引LP,但过高奖励会导致抛压。请设计一个平衡方案并分析博弈均衡。",
},
]
def test_model(model: str, prompt: str) -> dict:
"""测试单个模型,返回响应和性能指标"""
start_time = time.time()
response = requests.post(OLLAMA_URL, json={
"model": model,
"prompt": prompt,
"stream": False,
"options": {
"temperature": 0.7,
"num_ctx": 2048,
}
})
total_time = time.time() - start_time
result = response.json()
return {
"model": model,
"response": result.get("response", ""),
"total_time": round(total_time, 2),
"eval_count": result.get("eval_count", 0),
"eval_duration_ns": result.get("eval_duration", 0),
"tokens_per_second": round(
result.get("eval_count", 0) /
(result.get("eval_duration", 1) / 1e9), 1
) if result.get("eval_duration") else 0,
}
def run_comparison():
"""运行完整对比测试"""
results = []
for q in QUESTIONS:
print(f"\n{'='*60}")
print(f"测试类别: {q['category']}")
print(f"{'='*60}")
for model in MODELS:
print(f"\n 测试模型: {model}...")
result = test_model(model, q["prompt"])
result["category"] = q["category"]
results.append(result)
print(f" 耗时: {result['total_time']}s")
print(f" 速度: {result['tokens_per_second']} tokens/s")
print(f" 回答前100字: {result['response'][:100]}...")
# 保存结果
with open("comparison_results.json", "w", encoding="utf-8") as f:
json.dump(results, f, ensure_ascii=False, indent=2)
print("\n\n结果已保存到 comparison_results.json")
return results
if __name__ == "__main__":
run_comparison()
对比结果模板 / Comparison Results Template
模型对比结果表(请填入你的实测数据):
┌─────────────────┬──────────┬──────────┬──────────┬──────────┐
│ 指标 │ Qwen2.5 │ Llama3.3 │ Phi-4 │ Gemma2 │
│ │ 7B │ 8B │ 3.8B │ 9B │
├─────────────────┼──────────┼──────────┼──────────┼──────────┤
│ 模型大小(GB) │ ~4.4 │ ~4.9 │ ~2.2 │ ~5.4 │
│ 显存占用(GB) │ ___ │ ___ │ ___ │ ___ │
│ 加载时间(s) │ ___ │ ___ │ ___ │ ___ │
│ 生成速度(t/s) │ ___ │ ___ │ ___ │ ___ │
├─────────────────┼──────────┼──────────┼──────────┼──────────┤
│ 中文质量 (1-5) │ ___ │ ___ │ ___ │ ___ │
│ 英文质量 (1-5) │ ___ │ ___ │ ___ │ ___ │
│ 代码质量 (1-5) │ ___ │ ___ │ ___ │ ___ │
│ 推理能力 (1-5) │ ___ │ ___ │ ___ │ ___ │
├─────────────────┼──────────┼──────────┼──────────┼──────────┤
│ 综合评分 (1-5) │ ___ │ ___ │ ___ │ ___ │
│ 推荐场景 │ 中文对话 │ 英文任务 │ 轻量推理 │ 通用任务 │
└─────────────────┴──────────┴──────────┴──────────┴──────────┘
参考评分标准:
5 = 接近GPT-4水平
4 = 完全可用,偶有小问题
3 = 基本可用,需要优化prompt
2 = 勉强可用,频繁出错
1 = 不可用
预期结论(需要你的实测验证):
- 中文场景: Qwen2.5 >> 其他(中文训练数据多)
- 英文场景: Llama3.3 ≈ Gemma2 > Qwen2.5 > Phi-4
- 代码场景: Qwen2.5 ≈ Llama3.3 > Phi-4 > Gemma2
- 推理场景: Gemma2 ≈ Qwen2.5 > Llama3.3 > Phi-4
- 速度: Phi-4 >> 其他(参数量只有一半)
知识点4:API 服务搭建 / API Service Setup
Ollama REST API / Ollama REST API
Ollama 自带 REST API,启动服务后自动可用:
API 端点一览:
┌──────────────────────────────────────────────────────────┐
│ POST /api/generate — 文本生成(单轮) │
│ POST /api/chat — 对话生成(多轮) │
│ POST /api/embeddings — 生成Embedding │
│ GET /api/tags — 列出已下载模型 │
│ POST /api/show — 显示模型信息 │
│ POST /api/pull — 拉取模型 │
│ DELETE /api/delete — 删除模型 │
└──────────────────────────────────────────────────────────┘
OpenAI 兼容格式 / OpenAI-Compatible Format
Ollama 提供 OpenAI 兼容的 API:
端点: http://localhost:11434/v1/chat/completions
格式: 与 OpenAI API 完全一致
这意味着:
- 任何支持 OpenAI API 的库/工具都能直接使用
- LangChain / LlamaIndex / Dify 无缝对接
- 切换本地↔云端只需改一个 URL
# 使用 curl 测试 OpenAI 兼容 API
curl http://localhost:11434/v1/chat/completions \
-H "Content-Type: application/json" \
-d '{
"model": "qwen2.5:7b-instruct-q4_K_M",
"messages": [
{"role": "system", "content": "你是一个Web3产品分析师"},
{"role": "user", "content": "分析Uniswap V3的集中流动性设计"}
],
"temperature": 0.7,
"max_tokens": 500
}'
Python 调用示例 / Python Examples
"""
ollama_api_demo.py
演示 Ollama API 的各种调用方式
"""
# === 方式1: 使用 requests 直接调用 ===
import requests
import json
def chat_basic(prompt: str, model: str = "qwen2.5:7b") -> str:
"""基础对话调用"""
response = requests.post(
"http://localhost:11434/api/generate",
json={
"model": model,
"prompt": prompt,
"stream": False,
"options": {
"temperature": 0.7,
"num_ctx": 4096,
}
}
)
return response.json()["response"]
# 使用
result = chat_basic("什么是闪电贷攻击?")
print(result)
# === 方式2: 使用 OpenAI SDK(推荐) ===
from openai import OpenAI
client = OpenAI(
base_url="http://localhost:11434/v1",
api_key="ollama", # Ollama 不需要真实 key
)
def chat_openai_style(
messages: list[dict],
model: str = "qwen2.5:7b",
temperature: float = 0.7,
) -> str:
"""OpenAI 兼容方式调用"""
response = client.chat.completions.create(
model=model,
messages=messages,
temperature=temperature,
max_tokens=1000,
)
return response.choices[0].message.content
# 使用
messages = [
{"role": "system", "content": "你是一个DeFi协议分析师"},
{"role": "user", "content": "评估Aave V3的风险参数设计"},
]
result = chat_openai_style(messages)
print(result)
# === 方式3: 使用 ollama Python 库 ===
import ollama
def chat_ollama_lib(prompt: str) -> str:
"""使用 ollama 官方 Python 库"""
response = ollama.chat(
model="qwen2.5:7b",
messages=[
{"role": "user", "content": prompt},
]
)
return response["message"]["content"]
# 使用
result = chat_ollama_lib("解释AMM的x*y=k公式")
print(result)
# === 方式4: 生成 Embedding ===
def get_embedding(text: str) -> list[float]:
"""获取文本的Embedding向量"""
response = requests.post(
"http://localhost:11434/api/embeddings",
json={
"model": "nomic-embed-text",
"prompt": text,
}
)
return response.json()["embedding"]
# 使用
embedding = get_embedding("DeFi lending protocol risk assessment")
print(f"Embedding维度: {len(embedding)}") # 768 for nomic-embed-text
流式响应处理 / Streaming Response
"""
streaming_demo.py
流式响应处理 — 实现打字机效果
"""
import requests
import json
import sys
def stream_chat(prompt: str, model: str = "qwen2.5:7b"):
"""流式对话 — 逐 Token 输出"""
response = requests.post(
"http://localhost:11434/api/generate",
json={
"model": model,
"prompt": prompt,
"stream": True, # 关键:开启流式
},
stream=True, # requests 也要开启流式
)
full_response = ""
for line in response.iter_lines():
if line:
data = json.loads(line)
token = data.get("response", "")
full_response += token
# 实时打印(打字机效果)
sys.stdout.write(token)
sys.stdout.flush()
# 检查是否结束
if data.get("done", False):
print() # 换行
# 打印性能统计
print(f"\n--- 性能统计 ---")
print(f"总Token数: {data.get('eval_count', 'N/A')}")
eval_ns = data.get('eval_duration', 0)
if eval_ns:
tps = data['eval_count'] / (eval_ns / 1e9)
print(f"生成速度: {tps:.1f} tokens/s")
break
return full_response
# === OpenAI SDK 流式版本 ===
from openai import OpenAI
client = OpenAI(
base_url="http://localhost:11434/v1",
api_key="ollama",
)
def stream_chat_openai(messages: list[dict], model: str = "qwen2.5:7b"):
"""OpenAI 兼容的流式调用"""
stream = client.chat.completions.create(
model=model,
messages=messages,
stream=True, # 开启流式
)
full_response = ""
for chunk in stream:
if chunk.choices[0].delta.content:
token = chunk.choices[0].delta.content
full_response += token
sys.stdout.write(token)
sys.stdout.flush()
print()
return full_response
if __name__ == "__main__":
print("=== Ollama 原生流式 ===")
stream_chat("用3句话解释什么是Layer 2 Rollup")
print("\n\n=== OpenAI 兼容流式 ===")
stream_chat_openai([
{"role": "user", "content": "用3句话解释什么是MEV"}
])
流式 vs 非流式的选择:
场景 | 推荐 | 原因
-----------------------|----------|----------------------------------
聊天界面 | 流式 ✓ | 打字机效果,用户体验好
批量处理 | 非流式 ✓ | 代码简单,方便统计
RAG 系统 | 流式 ✓ | 用户等待时间感知更短
API 后端 | 都行 | 取决于前端是否需要流式
自动化脚本 | 非流式 ✓ | 需要完整响应做后处理
Day 16 讲的 LLM 应用架构中提到过:
TTFT 决定用户等待体验
流式输出让 TTFT 从"整体响应时间"降到"首Token时间"
这就是为什么 ChatGPT 是逐字显示的
知识点5:llama.cpp 进阶 / llama.cpp Advanced
为什么还要学 llama.cpp?/ Why Learn llama.cpp?
Ollama 底层就是 llama.cpp,但 Ollama 做了很多封装。
直接用 llama.cpp 的场景:
1. 极致性能调优 — Ollama 的默认参数不一定最优
2. 自定义量化 — 用特定方法量化 HuggingFace 模型
3. 特殊模型格式 — 有些模型 Ollama 还没收录
4. 服务器部署 — llama.cpp 的 server 模式更灵活
5. 理解底层 — 面试时能讲清楚推理引擎原理
手动加载 GGUF 模型 / Loading GGUF Models
# Step 1: 安装 llama-cpp-python(带GPU加速)
# Windows + CUDA:
pip install llama-cpp-python \
--extra-index-url https://abetlen.github.io/llama-cpp-python/whl/cu124
# 或者从源码编译(更灵活):
CMAKE_ARGS="-DGGML_CUDA=on" pip install llama-cpp-python
# Step 2: 下载 GGUF 模型(从 HuggingFace)
# 推荐模型: https://huggingface.co/Qwen/Qwen2.5-7B-Instruct-GGUF
# 下载 qwen2.5-7b-instruct-q4_k_m.gguf
# Step 3: Python 中使用
"""
llama_cpp_demo.py
直接使用 llama.cpp Python 绑定
"""
from llama_cpp import Llama
# 加载模型(关键参数)
llm = Llama(
model_path="./models/qwen2.5-7b-instruct-q4_k_m.gguf",
# 上下文长度 — 决定能处理多长的输入
n_ctx=4096, # 默认512太小,建议4096
# GPU层数 — 决定多少层放GPU(剩余放CPU)
n_gpu_layers=-1, # -1 = 全部放GPU(推荐)
# 0 = 纯CPU(无GPU时)
# 20 = 部分放GPU(显存不够时)
# CPU线程数 — 影响CPU计算部分的速度
n_threads=8, # 建议 = CPU物理核心数
# 批处理大小 — 影响预填充速度
n_batch=512, # 默认512,一般不用改
# 其他选项
verbose=True, # 显示加载详情
seed=42, # 随机种子(可复现)
)
# === 文本生成 ===
output = llm(
"解释什么是预言机(Oracle)在区块链中的作用:",
max_tokens=500,
temperature=0.7,
top_p=0.9,
top_k=40,
repeat_penalty=1.1,
stop=["<|im_end|>", "\n\n\n"],
)
print(output["choices"][0]["text"])
# === Chat 格式 ===
output = llm.create_chat_completion(
messages=[
{"role": "system", "content": "你是Web3架构分析师"},
{"role": "user", "content": "对比Optimistic和ZK Rollup的架构差异"},
],
max_tokens=800,
temperature=0.7,
)
print(output["choices"][0]["message"]["content"])
# === 获取 Embedding ===
embedding = llm.create_embedding("DeFi lending protocol")
print(f"Embedding shape: {len(embedding['data'][0]['embedding'])}")
参数调优详解 / Parameter Tuning
关键参数对性能的影响:
┌─────────────────┬───────────────────┬─────────────────────────────┐
│ 参数 │ 影响 │ 调优建议 │
├─────────────────┼───────────────────┼─────────────────────────────┤
│ n_ctx │ 上下文窗口长度 │ 越大越占显存 │
│ │ 决定输入+输出上限 │ KV Cache = 2×n_layers× │
│ │ │ n_heads×head_dim×n_ctx │
│ │ │ 4096是个好平衡点 │
├─────────────────┼───────────────────┼─────────────────────────────┤
│ n_gpu_layers │ GPU卸载层数 │ -1全放GPU(最快) │
│ │ 更多层→更快 │ 显存不够时逐步减少 │
│ │ │ Qwen2.5-7B有32层 │
├─────────────────┼───────────────────┼─────────────────────────────┤
│ n_threads │ CPU线程数 │ = 物理核心数(非逻辑核心) │
│ │ 影响CPU部分速度 │ 过多反而更慢(上下文切换) │
├─────────────────┼───────────────────┼─────────────────────────────┤
│ n_batch │ 批处理大小 │ 影响Prefill速度 │
│ │ Prefill时并行度 │ 512是个好默认值 │
├─────────────────┼───────────────────┼─────────────────────────────┤
│ temperature │ 生成随机性 │ 0.0=确定性, 1.0=高随机 │
│ │ │ 分析任务: 0.1-0.3 │
│ │ │ 创意任务: 0.7-0.9 │
├─────────────────┼───────────────────┼─────────────────────────────┤
│ top_p │ 核采样阈值 │ 0.9 通常比 top_k 更好 │
│ top_k │ 保留前K个Token │ 40 是常用值 │
├─────────────────┼───────────────────┼─────────────────────────────┤
│ repeat_penalty │ 重复惩罚 │ 1.0=不惩罚, 1.1=轻微惩罚 │
│ │ │ 防止模型陷入重复循环 │
└─────────────────┴───────────────────┴─────────────────────────────┘
Ollama vs llama.cpp 性能对比 / Performance Comparison
"""
performance_comparison.py
对比 Ollama 和 llama.cpp 的性能差异
"""
import time
import requests
from llama_cpp import Llama
PROMPT = "详细解释以太坊的Gas机制,包括EIP-1559的改进"
def test_ollama(prompt: str, n_runs: int = 3) -> dict:
"""测试 Ollama 性能"""
times = []
tps_list = []
for i in range(n_runs):
start = time.time()
resp = requests.post(
"http://localhost:11434/api/generate",
json={"model": "qwen2.5:7b", "prompt": prompt, "stream": False}
).json()
elapsed = time.time() - start
times.append(elapsed)
if resp.get("eval_duration"):
tps = resp["eval_count"] / (resp["eval_duration"] / 1e9)
tps_list.append(tps)
return {
"avg_time": sum(times) / len(times),
"avg_tps": sum(tps_list) / len(tps_list) if tps_list else 0,
}
def test_llama_cpp(prompt: str, n_runs: int = 3) -> dict:
"""测试 llama.cpp 性能"""
llm = Llama(
model_path="./models/qwen2.5-7b-instruct-q4_k_m.gguf",
n_ctx=4096,
n_gpu_layers=-1,
n_threads=8,
verbose=False,
)
times = []
tps_list = []
for i in range(n_runs):
start = time.time()
output = llm(prompt, max_tokens=500, temperature=0.7)
elapsed = time.time() - start
times.append(elapsed)
tokens = output["usage"]["completion_tokens"]
tps_list.append(tokens / elapsed)
return {
"avg_time": sum(times) / len(times),
"avg_tps": sum(tps_list) / len(tps_list),
}
# 运行对比
print("Testing Ollama...")
ollama_result = test_ollama(PROMPT)
print("Testing llama.cpp...")
llamacpp_result = test_llama_cpp(PROMPT)
print(f"\n{'='*50}")
print(f"{'指标':<20} {'Ollama':<15} {'llama.cpp':<15}")
print(f"{'='*50}")
print(f"{'平均耗时(s)':<20} {ollama_result['avg_time']:<15.2f} {llamacpp_result['avg_time']:<15.2f}")
print(f"{'平均速度(t/s)':<20} {ollama_result['avg_tps']:<15.1f} {llamacpp_result['avg_tps']:<15.1f}")
预期对比结果:
指标 | Ollama | llama.cpp (调优)
----------------|---------------|------------------
首次加载 | 自动管理 | 需手动加载
生成速度 | 略慢 (5-10%) | 基准线
显存管理 | 自动 | 手动精确控制
多模型切换 | 自动卸载/加载 | 需要手动管理
API 兼容性 | OpenAI 兼容 | 需要额外配置
易用性 | ★★★★★ | ★★
生产部署 | 适合原型 | 适合性能敏感场景
结论:
- 开发和原型阶段 → Ollama(省时间)
- 生产和性能要求高 → llama.cpp 或 vLLM
- 学习和理解底层 → llama.cpp(必须了解)
知识点6:显存管理实战 / GPU Memory Management
8GB 显存下的最优配置 / Optimal Config for 8GB VRAM
8GB 显存预算分配(以 RTX 3060/4060 为例):
总显存: 8192 MB
├── 系统/驱动保留: ~500 MB
├── 模型权重: 模型大小决定
├── KV Cache: 上下文长度决定
└── 运行时缓冲: ~200-500 MB
可用显存 ≈ 7200 MB
不同模型的显存消耗:
┌───────────────────────┬──────────┬──────────┬──────────┐
│ 模型 │ 权重 │ KV(4K) │ 总占用 │
├───────────────────────┼──────────┼──────────┼──────────┤
│ Phi-4-mini 3.8B Q4 │ ~2.2 GB │ ~0.3 GB │ ~3.0 GB │
│ Qwen2.5-7B Q4 │ ~4.4 GB │ ~0.5 GB │ ~5.5 GB │
│ Llama3.3-8B Q4 │ ~4.9 GB │ ~0.5 GB │ ~6.0 GB │
│ Gemma2-9B Q4 │ ~5.4 GB │ ~0.6 GB │ ~6.5 GB │
│ Qwen2.5-14B Q4 │ ~8.1 GB │ ~0.8 GB │ ~9.5 GB │ ← 超了!
└───────────────────────┴──────────┴──────────┴──────────┘
8GB 显存的最优组合:
- 主力模型: Qwen2.5-7B Q4(中文任务)
- 备选模型: Llama3.3-8B Q4(英文任务)
- 轻量模型: Phi-4-mini Q4(速度优先任务)
- Embedding: nomic-embed-text(768维,很小)
注意:不要同时运行两个大模型!
Ollama 会自动卸载不活跃的模型,但切换需要重新加载
nvidia-smi 监控 / nvidia-smi Monitoring
# 基础监控(每秒刷新)
nvidia-smi -l 1
# 只看显存使用
nvidia-smi --query-gpu=memory.used,memory.free,memory.total \
--format=csv -l 1
# 详细进程信息
nvidia-smi --query-compute-apps=pid,name,used_memory \
--format=csv
# 持续监控到文件(后台运行)
nvidia-smi --query-gpu=timestamp,memory.used,utilization.gpu,power.draw \
--format=csv -l 5 > gpu_monitor.csv &
"""
gpu_monitor.py
实时GPU监控工具
"""
import subprocess
import time
import sys
def get_gpu_info() -> dict:
"""获取GPU信息"""
result = subprocess.run(
[
"nvidia-smi",
"--query-gpu=memory.used,memory.free,memory.total,"
"utilization.gpu,temperature.gpu,power.draw",
"--format=csv,noheader,nounits"
],
capture_output=True, text=True
)
values = result.stdout.strip().split(", ")
return {
"memory_used_mb": int(values[0]),
"memory_free_mb": int(values[1]),
"memory_total_mb": int(values[2]),
"gpu_util_pct": int(values[3]),
"temperature_c": int(values[4]),
"power_w": float(values[5]),
}
def monitor_loop(interval: float = 1.0):
"""持续监控GPU状态"""
print(f"{'Time':>8} | {'VRAM Used':>10} | {'VRAM Free':>10} | "
f"{'GPU%':>5} | {'Temp':>5} | {'Power':>7}")
print("-" * 65)
while True:
info = get_gpu_info()
used_pct = info["memory_used_mb"] / info["memory_total_mb"] * 100
# 显存使用率高时用红色提示
vram_warning = " !!!" if used_pct > 90 else ""
print(
f"{time.strftime('%H:%M:%S'):>8} | "
f"{info['memory_used_mb']:>6} MB | "
f"{info['memory_free_mb']:>6} MB | "
f"{info['gpu_util_pct']:>4}% | "
f"{info['temperature_c']:>3}°C | "
f"{info['power_w']:>5.1f} W"
f"{vram_warning}"
)
time.sleep(interval)
if __name__ == "__main__":
try:
monitor_loop()
except KeyboardInterrupt:
print("\nMonitoring stopped.")
多模型切换策略 / Multi-Model Switching Strategy
Ollama 的自动管理机制:
默认行为:
1. 请求模型A → 加载模型A到显存
2. 请求模型B → 检查显存是否够
├── 够 → 同时保留A和B(如果你有16GB+)
└── 不够 → 卸载A,加载B
3. 再请求模型A → 重新加载(有延迟)
关键环境变量:
OLLAMA_MAX_LOADED_MODELS=1 # 最多同时加载几个模型
OLLAMA_NUM_PARALLEL=1 # 单模型并发请求数
OLLAMA_KEEP_ALIVE=5m # 空闲多久后卸载模型
"""
smart_model_router.py
智能模型路由:根据任务类型选择最优模型
"""
from enum import Enum
from openai import OpenAI
client = OpenAI(base_url="http://localhost:11434/v1", api_key="ollama")
class TaskType(Enum):
CHINESE_CHAT = "chinese_chat"
ENGLISH_CHAT = "english_chat"
CODE_GEN = "code_generation"
QUICK_ANSWER = "quick_answer"
EMBEDDING = "embedding"
# 任务→模型映射
MODEL_MAP = {
TaskType.CHINESE_CHAT: "qwen2.5:7b", # 中文最强
TaskType.ENGLISH_CHAT: "llama3.3:8b", # 英文最强
TaskType.CODE_GEN: "qwen2.5-coder:7b", # 代码专用
TaskType.QUICK_ANSWER: "phi4-mini:3.8b", # 速度最快
TaskType.EMBEDDING: "nomic-embed-text", # Embedding
}
def smart_chat(
prompt: str,
task_type: TaskType = TaskType.CHINESE_CHAT,
temperature: float = 0.7,
) -> str:
"""根据任务类型自动选择模型"""
model = MODEL_MAP[task_type]
response = client.chat.completions.create(
model=model,
messages=[{"role": "user", "content": prompt}],
temperature=temperature,
)
return response.choices[0].message.content
# === 使用示例 ===
# 中文分析
result = smart_chat(
"分析Uniswap V3的集中流动性对LP的影响",
task_type=TaskType.CHINESE_CHAT,
temperature=0.3, # 分析任务低温度
)
# 快速回答
result = smart_chat(
"What is ERC-4337?",
task_type=TaskType.QUICK_ANSWER,
)
# 代码生成
result = smart_chat(
"Write a Solidity function for ERC20 token transfer with fee",
task_type=TaskType.CODE_GEN,
)
显存优化技巧总结:
1. 减少上下文长度
n_ctx: 4096 → 2048 可节省约 0.3-0.5GB
只在需要长输入时才用大 n_ctx
2. 使用更小的量化
Q4_K_M → Q3_K_M 可节省约 20% 显存
但质量会有明显下降,不推荐
3. 部分CPU卸载
n_gpu_layers: -1 → 28(32层放28层到GPU)
4层放CPU,速度下降约15%,省约1GB
4. 关闭不必要的GPU程序
浏览器GPU加速 → 关闭
其他GPU程序 → 关闭
Windows桌面合成 → 无法关闭但影响不大
5. 单模型策略
OLLAMA_MAX_LOADED_MODELS=1
确保只有一个模型在显存中
6. Flash Attention
Ollama 和 llama.cpp 默认开启
可以减少 KV Cache 的显存消耗
今日思考 / Today's Reflections
思考1:本地部署 vs 云端 API 的真正取舍 / Local vs Cloud Trade-offs
经过实际部署,重新审视本地 vs 云端的选择:
本地部署的真实优势:
├── 隐私: 数据完全不出本机(金融场景关键)
├── 成本: 长期使用几乎零边际成本
├── 延迟: 无网络开销(局域网场景)
└── 控制: 可精确控制模型参数和行为
本地部署的真实痛点:
├── 质量: 7B 模型 vs GPT-4/Claude 差距明显
├── 运维: 需要管理硬件、驱动、模型更新
├── 扩展: 单卡并发有限
└── 投资: 好显卡不便宜(RTX 4090 = 1万+)
实际决策框架:
┌─────────────────┬──────────────┬──────────────┐
│ 场景 │ 推荐方案 │ 原因 │
├─────────────────┼──────────────┼──────────────┤
│ 敏感数据处理 │ 本地 │ 合规要求 │
│ 高质量分析 │ 云端 API │ 质量差距大 │
│ 开发调试 │ 本地 │ 免费无限调用 │
│ 生产服务 │ 云端/私有部署│ 可靠性+扩展 │
│ RAG 原型 │ 本地 │ 快速迭代 │
│ 面向用户产品 │ 云端 │ 质量决定体验 │
└─────────────────┴──────────────┴──────────────┘
最佳实践是混合架构(Day 27 多模型编排学过的):
- 简单任务 → 本地小模型(快+免费)
- 复杂任务 → 云端大模型(质量+可靠)
- 敏感数据 → 本地处理(合规)
- 非敏感数据 → 云端处理(效率)
思考2:模型选择的"够用就好"原则 / "Good Enough" Model Selection
今天对比了 4 个模型后的感悟:
错误思维: "一定要用最好的模型"
正确思维: "用最合适的模型"
实际案例:
- 文本分类任务 → Phi-4-mini 3.8B 就够了
速度快 3 倍,准确率只差 2%
- 中文客服问答 → Qwen2.5-7B 完全够用
不需要 GPT-4 级别
- 复杂金融分析 → 才需要 Claude/GPT-4
本地模型确实不够
这就是 Day 26 "成本工程" 学到的:
ROI = 任务价值 / 模型成本
很多场景下,小模型的 ROI 更高
思考3:从"知道"到"会做"的质变 / From "Knowing" to "Doing"
Day 2 学量化时,我记住了:
"Q4_K_M 将每个权重压缩到 4 bit"
今天实际部署后,我真正理解了:
"Q4_K_M 意味着 7B 模型只占 4.4GB,能在我的 8GB 卡上跑"
"同一个模型 Q4 vs Q8 速度差 30%,质量差感知不大"
"KV Cache 随上下文线性增长,4K 和 8K 差距可量化"
这就是动手实战的价值:
理论: "Transformer 的自注意力机制复杂度是 O(n²)"
实践: "我把 n_ctx 从 4096 开到 8192,显存多了 0.5GB,速度也慢了"
理论: "流式输出可以降低 TTFT"
实践: "用户第一个字 0.8 秒就出来了,体验确实好很多"
后面 9 天的动手实践,每一天都会有这种"啊原来如此"的时刻。
学习资源 / Resources
官方文档
- Ollama 官网: https://ollama.ai
- Ollama GitHub: https://github.com/ollama/ollama
- Ollama Python 库: https://github.com/ollama/ollama-python
- llama.cpp: https://github.com/ggerganov/llama.cpp
- llama-cpp-python: https://github.com/abetlen/llama-cpp-python
模型资源
- Ollama 模型库: https://ollama.ai/library
- HuggingFace GGUF 模型: https://huggingface.co/models?library=gguf
- Qwen2.5 官方: https://github.com/QwenLM/Qwen2.5
- TheBloke (经典量化): https://huggingface.co/TheBloke
社区工具
- Open WebUI: https://github.com/open-webui/open-webui — Ollama 的 Web 界面
- AnythingLLM: https://github.com/Mintplex-Labs/anything-llm — 本地 RAG 平台
- LM Studio: https://lmstudio.ai — GUI 模型管理工具
性能基准
- llm-benchmark: https://github.com/XiongjieDai/gpu-benchmarks-on-llm-inference
- LocalLLM 性能表: https://github.com/NielsRogge/Transformers-Tutorials
明日预告 / Tomorrow's Preview
Day 52: RAG系统实战 — 让AI回答你的文档问题
明天我们要做一件真正有用的事:
用自己的 251 篇架构笔记 + 90 篇 Web3 笔记,构建一个 RAG 系统
你将能问:
"Day 44 讲的 RAG 系统设计要点是什么?"
"架构计划中关于支付系统的内容有哪些?"
"DeFi风控和传统金融风控的差异总结?"
需要提前准备:
1. 确保 Ollama 正常运行(今天已完成)
2. 安装: pip install chromadb langchain sentence-transformers
3. 确认所有笔记文件在 docs/ 目录下
这将是前 51 天所有知识的综合运用:
- Day 5 的 RAG 架构理论
- Day 6 的向量数据库知识
- Day 19-21 的生产 RAG 实践
- Day 51 的本地模型部署(今天)
Day 51 完成! 从零到一,你现在拥有了一个可通过 API 调用的本地 LLM 服务。 这是后续所有实战项目的基础设施。明天开始构建真正有用的 RAG 系统!