搭建你的第一座“模型工厂”——5分钟部署开源大模型
用Ollama部署开源模型,整个过程不超过5分钟。但跑起来只是第一步——这篇还会带你做一件事:在同一台机器上部署两个不同尺寸的模型,跑同一组问题,填一份模型选型对比表。以后你做技术选型时,这一套方法直接复用。
3.1 安装Ollama
Ollama是目前对开发者最友好的本地模型管理工具,一条命令就能拉取和运行模型。它提供类似Docker的使用体验,但没有容器那一层复杂度。
macOS / Windows
直接去 ollama.com 下载安装包,双击安装。装完后菜单栏会出现一个羊驼图标,后台服务自动启动。
Linux bash curl -fsSL https://ollama.com/install.sh | sh装完验证一下:
bash ollama --version # 输出类似:ollama version 0.5.73.2 拉取并运行第一个模型
我们选用阿里开源的Qwen2.5系列,中文问答能力在开源模型里属于第一梯队。先拉7B版本:
bash ollama pull qwen2.5:7b7b表示70亿参数,压缩后约4~5GB,8GB内存的机器能跑但会占满,16GB内存比较从容。
拉完后直接对话:
bash ollama run qwen2.5:7b你会进入一个交互式终端,直接打字提问:
text >>> 用一句话解释Java的GC机制模型会逐字输出回答。退出按Ctrl + D或输入/bye。
如果下载速度慢,可以使用镜像加速。Ollama默认从它的官方仓库拉取,国内用户可设置环境变量:
bash # 一些社区提供的加速镜像,按需选用 export OLLAMA_HOST=0.0.0.0:114343.3 用代码调用Ollama
终端里聊只能测试,真正开发要通过API。Ollama启动后默认监听http://localhost:11434,接口兼容OpenAI格式,可以直接用我们第2篇写的chat_completion_stream来调。
但既然Ollama有自己的轻量API,这里给出一个更直接的封装,方便后续调用。
python """ ollama_client.py Ollama模型的Python客户端封装 本文件对应 stage01_env/ollama_client.py """ import httpx import json from typing import AsyncIterator, Optional class OllamaClient: """封装Ollama的聊天和生成接口。""" def __init__(self, base_url: str = "http://localhost:11434"): self.base_url = base_url.rstrip("/") # ---------- 同步版 ---------- def chat_sync(self, model: str, messages: list[dict]) -> str: """ 同步对话,返回完整回答。 用于脚本、测试、不需要流式的场景。 """ url = f"{self.base_url}/api/chat" payload = { "model": model, "messages": messages, "stream": False, } with httpx.Client(timeout=120.0) as client: response = client.post(url, json=payload) response.raise_for_status() data = response.json() return data["message"]["content"] # ---------- 异步流式版 ---------- async def chat_stream(self, model: str, messages: list[dict]) -> AsyncIterator[str]: """ 异步流式对话,逐token返回。 适用于Web服务、实时对话界面。 """ url = f"{self.base_url}/api/chat" payload = { "model": model, "messages": messages, "stream": True, } async with httpx.AsyncClient(timeout=120.0) as client: async with client.stream("POST", url, json=payload) as response: response.raise_for_status() async for line in response.aiter_lines(): try: chunk = json.loads(line) content = chunk.get("message", {}).get("content", "") if content: yield content except json.JSONDecodeError: continue # ---------- 工具方法 ---------- def list_models(self) -> list[dict]: """列出本地已安装的模型。""" url = f"{self.base_url}/api/tags" with httpx.Client() as client: response = client.get(url) response.raise_for_status() return response.json().get("models", []) def pull_model(self, model_name: str) -> None: """ 拉取模型(同步,会阻塞直到完成)。 如果需要进度,调用方可以改用异步流式版本。 """ url = f"{self.base_url}/api/pull" payload = {"name": model_name, "stream": False} with httpx.Client(timeout=600.0) as client: response = client.post(url, json=payload) response.raise_for_status()测试一下:
python import asyncio async def test_ollama(): client = OllamaClient() msgs = [{"role": "user", "content": "什么是RAG?用两句话说清楚"}] async for token in client.chat_stream("qwen2.5:7b", msgs): print(token, end="", flush=True) asyncio.run(test_ollama())3.4 实战:模型选型对比实验
好了,现在来做真正有价值的事。同一台机器,部署两个不同尺寸的模型,跑同一组测试问题,然后填一份对比表。这一套你以后在自己项目里做模型选型,可以直接照搬。
3.4.1 拉取两个对比模型
bash # 7B版本(主力) ollama pull qwen2.5:7b # 1.5B轻量版本(对比用) ollama pull qwen2.5:1.5b1.5B版本只有约1GB大小,内存占用小,但回答质量会有所下降。具体差距多少?数据说话。
3.4.2 编写对比测试脚本
python """ model_benchmark.py 对比不同模型在相同问题上的表现 本文件对应 stage01_env/model_benchmark.py """ import asyncio import time from ollama_client import OllamaClient # 测试问题集:覆盖不同难度和类型 TEST_QUESTIONS = [ # 简单事实型 "什么是Java的垃圾回收机制?", # 知识解释型 "请解释微服务架构中的服务发现原理", # 代码生成型 "用Python写一个快速排序函数,带注释", # 逻辑推理型 "如果数据库查询变慢,可能有哪些原因?", # 中文理解型 "请用中文总结Spring Boot的三大核心特性", ] MODELS = ["qwen2.5:7b", "qwen2.5:1.5b"] async def benchmark_single_model(client: OllamaClient, model: str, questions: list[str]) -> list[dict]: """对单个模型跑全部测试问题,返回带性能数据的结果。""" results = [] for i, question in enumerate(questions): print(f" [{model}] 测试 {i+1}/{len(questions)}: {question[:40]}...") messages = [{"role": "user", "content": question}] start = time.perf_counter() full_response = "" token_count = 0 first_token_time = None async for token in client.chat_stream(model, messages): if first_token_time is None: first_token_time = time.perf_counter() full_response += token token_count += 1 end = time.perf_counter() total_time = end - start ttft = first_token_time - start if first_token_time else 0 results.append({ "question": question, "model": model, "response": full_response, "total_time_sec": round(total_time, 2), "first_token_sec": round(ttft, 2), "token_count": token_count, # tokens/s 计算(排除首个token等待) "tokens_per_sec": round( (token_count - 1) / (total_time - ttft), 2 ) if total_time > ttft and token_count > 1 else 0, }) # 每个问题之间休息1秒,避免显存/CPU飙满 await asyncio.sleep(1) return results def print_comparison_table(all_results: dict[str, list[dict]]): """打印对比汇总表。""" print("\n" + "=" * 80) print("模型选型对比报告") print("=" * 80) for model in MODELS: results = all_results[model] avg_total = sum(r["total_time_sec"] for r in results) / len(results) avg_ttft = sum(r["first_token_sec"] for r in results) / len(results) avg_tokens = sum(r["token_count"] for r in results) / len(results) avg_tps = sum(r["tokens_per_sec"] for r in results) / len(results) print(f"\n📦 模型: {model}") print(f" 平均总耗时: {avg_total:.2f} 秒") print(f" 平均首token延迟: {avg_ttft:.2f} 秒") print(f" 平均回复长度: {avg_tokens:.0f} tokens") print(f" 平均生成速度: {avg_tps:.2f} tokens/s") # 定性对比展示(取第一个问题的回答作为样例) print("\n" + "-" * 40) print("定性对比(第1题回答节选)") print("-" * 40) q0 = TEST_QUESTIONS[0] for model in MODELS: resp = all_results[model][0]["response"] print(f"\n[{model}] {q0}") # 截取前200字 print(f" → {resp[:200]}...") async def main(): client = OllamaClient() # 确保模型已安装 installed = [m["name"] for m in client.list_models()] for model in MODELS: if model not in installed: print(f"模型 {model} 未安装,正在拉取...") client.pull_model(model) all_results = {} for model in MODELS: print(f"\n▶ 开始测试模型: {model}") all_results[model] = await benchmark_single_model( client, model, TEST_QUESTIONS ) print_comparison_table(all_results) if __name__ == "__main__": asyncio.run(main())3.4.3 运行对比测试
bash cd stage01_env python model_benchmark.py刚开始跑,1.5B版本速度会明显快,7B版本会明显慢(尤其是8GB内存的机器上)。最终你会得到类似这样的对比表:
text 📦 模型: qwen2.5:7b 平均总耗时: 12.35 秒 平均首token延迟: 2.10 秒 平均回复长度: 218 tokens 平均生成速度: 21.5 tokens/s 📦 模型: qwen2.5:1.5b 平均总耗时: 4.20 秒 平均首token延迟: 0.60 秒 平均回复长度: 145 tokens 平均生成速度: 40.3 tokens/s然后看定性部分:7B的回答更完整、更准确,尤其是"逻辑推理型"问题上差异明显;1.5B会偏简短,有时会跑题或遗漏关键点。
3.5 结论与选型建议
这张对比表直接告诉我们什么时候该选什么模型:
| 场景 | 推荐 | 理由 |
|---|---|---|
| 本地开发测试 | 1.5B | 启动快、不卡机、能验证链路是否通 |
| 生产问答 | 7B或更大 | 质量明显更优,用户愿意等2秒 |
| 实时对话/嵌入式 | 1.5B | 首token延迟低,体感流畅 |
| 批量数据处理 | 7B | 单次质量优先 |
当然这台机器的实际表现取决于你的CPU(GPU)、内存。后续我们在第5篇开始构建RAG核心时,我会把Embedding模型也纳入类似对比,让你对整个AI链路里每一步的模型选型都心里有数。
3.6 常见问题
Q:8GB内存能跑7B吗?
能,但跑起来后系统会频繁换页,生成速度掉到个位数token/s。建议至少16GB。
Q:想用GPU加速怎么办?
Ollama检测到NVIDIA显卡会自动启用CUDA。如果是Mac M系列芯片,会自动用Metal。使用ollama ps可以看当前模型是否在用GPU。
Q:模型下载太慢?
可以设置代理或使用国内镜像。另外有人会分享模型文件的离线包,用ollama create从本地文件导入,具体可查Ollama文档。
本篇文章源码:
stage01_env/ollama_client.py— Ollama客户端封装stage01_env/model_benchmark.py— 模型选型对比脚本
