AirLLM: 用 4GB 显存体验 Kimi K3 大模型

2026年8月3日

项目简介

AirLLM 是一个面向大语言模型推理的 Python 工具,它的核心思路不是把整个模型一次性塞进显存,而是把模型拆成更细的层级,在推理时按需加载。这样一来,我们就能在很低的显存环境里尝试运行 70B、235B、671B,甚至 Kimi K3 这类更夸张的 MoE 大模型。

Kimi K3 最近很受关注,原因也很直接:它属于超大规模 MoE 模型,参数规模很大,但每个 token 实际只会路由到一部分专家。AirLLM 正好利用了这一点,通过专家级别的流式加载,避免把完整模型一次性放进显存。

这篇文章我们一起来搭一个最小项目:先跑通 Kimi K3 推理,再把它封装成一个简单 HTTP API。最后也会聊一下什么时候适合本地低显存推理,什么时候直接使用 Defapi 这类兼容接口会更省事。

难度: 中级 | 时长: 30-60 分钟 | 收获: 理解 AirLLM 的低显存推理流程,并跑通一个 Kimi K3 最小推理服务

目标读者画像

  • 想在单卡、低显存机器上体验超大模型的开发者
  • 想评估 Kimi K3、DeepSeek-V3、Qwen3-235B 这类模型推理成本的工程师
  • 正在做 AI 应用原型,希望先本地验证模型效果的人
  • 需要把本地模型封装成 API,再接入 Agent、RAG 或业务系统的开发者

核心依赖与环境

Kimi K3 对环境比较挑,我们先把依赖边界说清楚:

依赖建议版本说明
Python3.10+建议使用虚拟环境隔离依赖
NVIDIA Driver支持 CUDA 12需要能正常运行 CUDA 12 版本 PyTorch
PyTorchCUDA 12 构建Kimi K3 依赖链更适合 CUDA 12
transformers4.56.xKimi K3 的远程模型代码对版本有要求
airllm最新版使用 AutoModel 统一加载模型
compressed-tensors最新版Kimi K3 相关权重格式会用到
flash-attn兼容 CUDA 12Kimi K3 模型代码通常会要求 flash attention

WARNING

AirLLM 可以降低显存占用,但不会让模型文件变小。首次运行会下载并拆分模型,磁盘空间和网络质量依然很关键。Kimi K3 这类模型体积巨大,建议先准备充足的模型缓存空间。

完整项目结构树

我们先准备一个最小项目,结构保持简单:

airllm-kimi-k3-demo/
├── .env.example
├── requirements.txt
├── run_kimi_k3.py
├── server.py
└── README.md

1. 创建 Python 虚拟环境

先创建目录和虚拟环境:

mkdir airllm-kimi-k3-demo
cd airllm-kimi-k3-demo

python -m venv .venv
source .venv/bin/activate

Windows PowerShell 可以这样激活:

mkdir airllm-kimi-k3-demo
cd airllm-kimi-k3-demo

python -m venv .venv
.venv\Scripts\Activate.ps1

确认 Python 版本:

python --version

建议输出至少是 Python 3.10.x。如果你机器上有多个 Python 版本,可以用 py -3.10 -m venv .venv 明确指定。

2. 安装 AirLLM 和 Kimi K3 依赖

新建 requirements.txt

airllm
accelerate
sentencepiece
safetensors
compressed-tensors
python-dotenv
fastapi
uvicorn[standard]

先安装 PyTorch。以 CUDA 12.1 为例:

pip install --upgrade pip
pip install torch torchvision torchaudio --index-url https://download.pytorch.org/whl/cu121

再安装核心依赖:

pip install -r requirements.txt
pip install "transformers>=4.56,<4.57"

最后安装 flash-attn

pip install flash-attn --no-build-isolation

TIP

如果 flash-attn 编译很慢,先确认当前环境里能正确 import torch,并且 torch.version.cuda 显示的是 CUDA 12 系列。Kimi K3 这类模型的依赖更偏工程环境,不建议直接在混乱的全局 Python 环境里安装。

3. 配置模型权限和缓存目录

有些 Hugging Face 模型需要登录或授权。我们准备一个 .env.example

HF_TOKEN=hf_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
HF_HOME=/data/huggingface
AIRLLM_MODEL_ID=moonshotai/Kimi-K3

实际使用时复制一份:

cp .env.example .env

Windows PowerShell:

Copy-Item .env.example .env

然后填入自己的 Hugging Face Token。模型 ID 需要以官方实际发布的仓库名为准,如果你使用的是镜像仓库或内部同步仓库,也可以直接改成对应的 repo id。

WARNING

不要把 .env 提交到 Git 仓库。模型 Token 属于敏感信息,泄露后可能导致私有模型权限被滥用。

4. 编写最小 Kimi K3 推理脚本

新建 run_kimi_k3.py

import os

from dotenv import load_dotenv
from airllm import AutoModel


def main() -> None:
    """加载 Kimi K3 并执行一次最小文本生成。"""
    load_dotenv()

    model_id = os.getenv("AIRLLM_MODEL_ID", "moonshotai/Kimi-K3")
    hf_token = os.getenv("HF_TOKEN")

    # 控制输入长度,先用短 prompt 跑通链路,避免首次验证时等待太久。
    max_length = 256

    # AutoModel 会自动识别模型类型;hf_token 用于访问需要授权的模型仓库。
    model = AutoModel.from_pretrained(
        model_id,
        hf_token=hf_token,
        profiling_mode=True,
    )

    prompt = "用三句话解释 AirLLM 为什么能降低大模型推理显存。"

    # tokenizer 仍然使用 Hugging Face 风格,迁移成本比较低。
    input_tokens = model.tokenizer(
        [prompt],
        return_tensors="pt",
        return_attention_mask=False,
        truncation=True,
        max_length=max_length,
        padding=False,
    )

    # AirLLM 推理时会按层加载权重;max_new_tokens 先设小一点,便于快速验证。
    generation_output = model.generate(
        input_tokens["input_ids"].cuda(),
        max_new_tokens=128,
        use_cache=True,
        return_dict_in_generate=True,
    )

    output = model.tokenizer.decode(
        generation_output.sequences[0],
        skip_special_tokens=True,
    )

    print(output)


if __name__ == "__main__":
    main()

运行:

python run_kimi_k3.py

首次运行通常会比较慢,因为 AirLLM 需要下载模型、分析权重文件,并把模型拆成后续可按层加载的格式。你会发现第二次运行会明显顺畅一些,因为模型缓存和拆分结果已经准备好了。

5. 观察显存和磁盘占用

打开另一个终端观察显存:

nvidia-smi -l 1

你关注两个指标:

Memory-Usage
GPU-Util

如果一切正常,显存不会像传统 transformers.from_pretrained() 那样瞬间被完整模型撑爆。AirLLM 的做法更像是“边走边取”,需要哪一层、哪一部分专家,就把对应权重加载进来,用完再释放。

再观察磁盘:

du -sh "$HF_HOME"

Windows PowerShell 可以用:

Get-ChildItem $env:HF_HOME -Recurse | Measure-Object Length -Sum

TIP

低显存推理不是免费午餐。AirLLM 把压力从显存转移到磁盘 IO、CPU 内存和模型缓存上,所以 SSD 速度会直接影响体验。

6. 开启压缩参数

AirLLM 支持通过 compression 参数降低权重加载体积。我们可以在初始化模型时加入 4bit

model = AutoModel.from_pretrained(
    model_id,
    hf_token=hf_token,
    compression="4bit",  # 使用 4bit 权重压缩,降低加载体积并改善部分场景速度
    profiling_mode=True,
)

如果你想更保守,可以先试 8bit

model = AutoModel.from_pretrained(
    model_id,
    hf_token=hf_token,
    compression="8bit",  # 8bit 更保守,速度和精度之间更平衡
    profiling_mode=True,
)

通常我们会这样选:

场景建议
只是体验 Kimi K3 能不能跑不开压缩,先确认链路
磁盘 IO 明显拖慢尝试 8bit
更关注速度和低成本验证尝试 4bit
要做严肃评测固定参数,多轮对比输出质量

WARNING

压缩会改变权重加载方式,虽然很多推理任务影响很小,但如果你在做模型评测、长文本推理或敏感业务验证,一定要保留未压缩版本作为基准。

7. 封装成一个简单 HTTP API

本地脚本跑通后,我们通常会希望把它接到应用里。下面用 FastAPI 做一个最小服务。

新建 server.py

import os
from typing import List, Literal

from dotenv import load_dotenv
from fastapi import FastAPI
from pydantic import BaseModel
from airllm import AutoModel


class ChatMessage(BaseModel):
    """OpenAI 风格的消息结构,方便后续替换为兼容 API。"""
    role: Literal["system", "user", "assistant"]
    content: str


class ChatRequest(BaseModel):
    """最小聊天请求,只保留教程需要的字段。"""
    messages: List[ChatMessage]
    max_tokens: int = 256


class ChatResponse(BaseModel):
    """返回文本结果,先保持简单,便于调试。"""
    text: str


load_dotenv()

app = FastAPI(title="AirLLM Kimi K3 Demo")

model_id = os.getenv("AIRLLM_MODEL_ID", "moonshotai/Kimi-K3")
hf_token = os.getenv("HF_TOKEN")

# 服务启动时加载模型;真实生产环境可以加健康检查和懒加载。
model = AutoModel.from_pretrained(
    model_id,
    hf_token=hf_token,
    profiling_mode=False,
)


def build_prompt(messages: List[ChatMessage]) -> str:
    """把多轮消息拼成一个简单 prompt,后续可替换为模型官方 chat template。"""
    lines: list[str] = []
    for message in messages:
        lines.append(f"{message.role}: {message.content}")
    lines.append("assistant:")
    return "\n".join(lines)


@app.post("/chat", response_model=ChatResponse)
def chat(request: ChatRequest) -> ChatResponse:
    """执行一次 Kimi K3 文本生成。"""
    prompt = build_prompt(request.messages)

    input_tokens = model.tokenizer(
        [prompt],
        return_tensors="pt",
        return_attention_mask=False,
        truncation=True,
        max_length=1024,
        padding=False,
    )

    generation_output = model.generate(
        input_tokens["input_ids"].cuda(),
        max_new_tokens=request.max_tokens,
        use_cache=True,
        return_dict_in_generate=True,
    )

    text = model.tokenizer.decode(
        generation_output.sequences[0],
        skip_special_tokens=True,
    )

    return ChatResponse(text=text)

启动服务:

uvicorn server:app --host 0.0.0.0 --port 8000

调用测试:

curl -X POST http://localhost:8000/chat \
  -H "Content-Type: application/json" \
  -d '{
    "messages": [
      {
        "role": "user",
        "content": "用中文解释 Kimi K3 这类 MoE 模型为什么适合按专家流式加载。"
      }
    ],
    "max_tokens": 200
  }'

现在我们已经有了一个最小 API。它还不算生产级,但足够用于本地实验、Agent 原型、Prompt 调试和模型效果对比。

8. 本地推理和 Defapi 接口怎么取舍

AirLLM 的价值很明确:它让我们能用低显存机器摸到超大模型,尤其适合学习、验证、评测和离线实验。但生产环境还要考虑吞吐、延迟、并发、模型更新、容灾和运维成本。

如果你只是想快速把模型能力接到应用里,或者需要 OpenAI/Anthropic/Gemini 风格的统一 API,Defapi 会更轻。它的优势是价格通常只有官方的一半,并且常见模型基本兼容这些协议:

  • v1/chat/completions
  • v1/messages
  • v1beta/models/

比如我们可以把上面的本地 /chat 调用抽象成一个统一客户端。开发阶段走本地 AirLLM,线上环境切到 Defapi:

import os
import requests


def ask_model(prompt: str) -> str:
    """根据环境变量选择本地推理或 Defapi 兼容接口。"""
    provider = os.getenv("MODEL_PROVIDER", "local")

    if provider == "defapi":
        response = requests.post(
            "https://api.defapi.org/api/v1/chat/completions",
            headers={
                "Authorization": f"Bearer {os.environ['DEFAPI_API_KEY']}",
                "Content-Type": "application/json",
            },
            json={
                "model": os.getenv("DEFAPI_MODEL", "anthropic/claude-sonnet-4.5"),
                "messages": [{"role": "user", "content": prompt}],
                "temperature": 0.7,
            },
            timeout=60,
        )
        response.raise_for_status()
        return response.json()["choices"][0]["message"]["content"]

    response = requests.post(
        "http://localhost:8000/chat",
        json={
            "messages": [{"role": "user", "content": prompt}],
            "max_tokens": 256,
        },
        timeout=300,
    )
    response.raise_for_status()
    return response.json()["text"]

这种写法的好处是边界很清楚:本地模型负责探索和验证,Defapi 负责稳定、统一、低成本地接入线上模型。对 OpenClaw、RAG 服务、自动化 Agent 来说,这种双模式很实用。

常见问题排查

1. flash-attn 安装失败怎么办?

先确认 PyTorch 能正常识别 CUDA:

python -c "import torch; print(torch.__version__); print(torch.version.cuda); print(torch.cuda.is_available())"

如果 torch.cuda.is_available()False,先别急着装 flash-attn,应该先修 PyTorch、驱动和 CUDA 版本。Kimi K3 这类模型建议使用 CUDA 12 构建,避免 CUDA 13 暂时没有合适预编译包导致编译失败。

2. transformers 版本报错怎么办?

把版本固定在 4.56.x:

pip uninstall -y transformers
pip install "transformers>=4.56,<4.57"

然后重新运行:

python run_kimi_k3.py

如果你看到模型远程代码加载失败,通常就是 transformers 版本和模型代码不匹配。

3. Hugging Face 下载失败怎么办?

先确认 Token 是否可用:

huggingface-cli whoami

如果没有登录:

huggingface-cli login

也可以只用 .env 里的 HF_TOKEN。如果模型需要申请访问权限,要先在模型页面同意协议。

4. 磁盘空间不足怎么办?

AirLLM 首次运行会下载原始权重,还会生成拆分后的模型文件。你可以把缓存目录放到更大的磁盘:

export HF_HOME=/mnt/models/huggingface

或者在 .env 中配置:

HF_HOME=/mnt/models/huggingface

如果磁盘依然吃紧,可以尝试 AirLLM 的 delete_original=True,只保留转换后的文件:

model = AutoModel.from_pretrained(
    model_id,
    hf_token=hf_token,
    delete_original=True,  # 转换完成后删除原始权重,节省磁盘空间
)

5. 首次运行为什么特别慢?

这是正常现象。首次运行包括下载权重、读取索引、拆分模型、写入缓存等步骤。第二次运行会复用缓存,速度会好很多。

可以打开 profiling:

model = AutoModel.from_pretrained(
    model_id,
    hf_token=hf_token,
    profiling_mode=True,  # 输出加载和推理耗时,方便定位瓶颈
)

如果耗时主要在磁盘读取,换更快的 NVMe SSD 往往比换更大显存更有效。

6. 显存没有降到预期怎么办?

先确认代码没有混用传统加载方式:

from airllm import AutoModel

model = AutoModel.from_pretrained(model_id)

不要混用传统加载方式:

from transformers import AutoModelForCausalLM

model = AutoModelForCausalLM.from_pretrained(model_id)

后者会走传统加载路径,很容易直接把显存打满。

7. API 服务并发一高就卡住怎么办?

本地低显存推理更适合串行实验,不适合直接承接高并发。最简单的做法是先限制并发:

uvicorn server:app --host 0.0.0.0 --port 8000 --workers 1

如果你需要更稳定的生产调用,可以把线上请求切到 Defapi,本地 AirLLM 保留给评测和调试。

扩展阅读 / 进阶方向

  • 对比 Kimi K3、DeepSeek-V3、Qwen3-235B 在 AirLLM 下的加载时间、显存和输出质量。
  • 把 FastAPI 服务改造成 OpenAI 兼容的 /v1/chat/completions 接口。
  • 接入 Defapi,用 v1/chat/completionsv1/messages 统一管理线上模型调用。
  • 为 AirLLM 服务加队列,避免多个请求一起争抢磁盘 IO 和 GPU。
  • 在 OpenClaw 或其他 Agent 框架中配置本地模型和云端模型,根据任务复杂度动态选择。
Updated 2026年8月3日