用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.7

3.2 拉取并运行第一个模型

我们选用阿里开源的 Qwen2.5 系列,中文问答能力在开源模型里属于第一梯队。先拉7B版本:

bash

ollama pull qwen2.5:7b

7b 表示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:11434

3.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.5b

1.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 — 模型选型对比脚本

Logo

AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。

更多推荐