AI 基础 | | 约 24 分钟 | 9,402 字

小模型的大用处:SLM 在边缘设备上的应用

了解小语言模型的优势、本地部署方案和实际应用

不是所有任务都需要 GPT-4

我们常常陷入一个误区:用最大的模型解决所有问题。但现实是,很多任务根本不需要 70B 甚至 7B 的模型。

场景:判断用户输入是否包含敏感词
GPT-4o:准确率 99.5%,延迟 800ms,成本 $0.003/次
Phi-3 mini (3.8B):准确率 98.8%,延迟 50ms,成本 $0(本地运行)

差距 0.7%,但速度快 16 倍,成本为零。

小语言模型(Small Language Model,SLM)通常指参数量在 0.5B 到 4B 之间的模型。它们体积小、速度快、可以在消费级硬件甚至手机上运行。


主流小模型

Microsoft Phi 系列

Phi 系列是微软研究院的代表作,证明了”数据质量比数据数量更重要”。

模型参数量特点
Phi-11.3B代码生成专精
Phi-22.7B通用能力提升
Phi-3 mini3.8B接近 Mixtral 8x7B 水平
Phi-3 small7B更强的推理能力
Phi-3.5 mini3.8B多语言增强
Phi-4 mini3.8B推理能力大幅提升

Phi 的核心理念:

传统思路:更多数据 + 更大模型 = 更好性能
Phi 的思路:更好的数据 + 合理的模型大小 = 出色性能

Phi 使用了精心筛选的"教科书级"训练数据,
而不是简单地爬取整个互联网。

Google Gemma 系列

模型参数量特点
Gemma 2B2B轻量级
Gemma 7B7B平衡之选
Gemma 2 2B2B性能提升
Gemma 2 9B9B接近大模型水平
Gemma 31B/4B/12B/27B多模态支持

Qwen 小模型

模型参数量特点
Qwen2.5 0.5B0.5B极致轻量
Qwen2.5 1.5B1.5B手机可运行
Qwen2.5 3B3B平衡之选

其他值得关注的小模型

模型参数量开发者特点
SmolLM2135M/360M/1.7BHuggingFace极小模型
TinyLlama1.1B社区Llama 架构的小版本
StableLM1.6B/3BStability AI稳定性好
Llama 3.21B/3BMetaLlama 家族的小成员

小模型的优势

1. 隐私保护

数据完全不离开本地设备:

云端 API 模式:
用户数据 → 互联网 → 云服务器 → 模型处理 → 互联网 → 返回结果
                ↑ 数据暴露风险

本地 SLM 模式:
用户数据 → 本地模型处理 → 返回结果
           ↑ 数据从未离开设备

2. 延迟极低

# 延迟对比(典型值)
latency_comparison = {
    "云端 GPT-4o": "500-2000ms(含网络延迟)",
    "云端 GPT-4o mini": "200-800ms",
    "本地 Phi-3 mini (GPU)": "20-100ms",
    "本地 Phi-3 mini (CPU)": "100-500ms",
    "本地 Qwen2.5 0.5B (CPU)": "30-150ms",
}

3. 零边际成本

# 成本对比:每天 10 万次调用
cost_comparison = {
    "GPT-4o": {
        "单次": 0.003,
        "日成本": 300,
        "月成本": 9000,
    },
    "GPT-4o mini": {
        "单次": 0.0002,
        "日成本": 20,
        "月成本": 600,
    },
    "本地 SLM": {
        "单次": 0,  # 边际成本为零
        "日成本": 0,
        "月成本": 0,  # 只有硬件和电费的固定成本
        "硬件成本": "一次性 $500-2000",
    },
}

4. 离线可用

不依赖网络连接,适合:

  • 飞机上、地铁里等无网络环境
  • 网络不稳定的偏远地区
  • 对网络依赖敏感的关键系统
  • 军事、医疗等特殊场景

本地部署实战

使用 Ollama 部署

# 安装 Ollama(macOS)
brew install ollama

# 下载小模型
ollama pull phi3:mini          # Phi-3 mini 3.8B
ollama pull qwen2.5:1.5b      # Qwen 2.5 1.5B
ollama pull gemma2:2b          # Gemma 2 2B
ollama pull llama3.2:1b        # Llama 3.2 1B

# 交互式对话
ollama run phi3:mini

# API 调用
curl http://localhost:11434/api/chat -d '{
  "model": "phi3:mini",
  "messages": [{"role": "user", "content": "什么是递归?"}],
  "stream": false
}'

在 Node.js 中使用

// 使用 Ollama 的 JavaScript SDK
import { Ollama } from "ollama";

const ollama = new Ollama({ host: "http://localhost:11434" });

async function chat(message: string): Promise<string> {
  const response = await ollama.chat({
    model: "phi3:mini",
    messages: [{ role: "user", content: message }],
  });
  return response.message.content;
}

// 流式响应
async function streamChat(message: string) {
  const response = await ollama.chat({
    model: "phi3:mini",
    messages: [{ role: "user", content: message }],
    stream: true,
  });

  for await (const part of response) {
    process.stdout.write(part.message.content);
  }
}

在 Python 中使用

import ollama

# 简单调用
response = ollama.chat(
    model="phi3:mini",
    messages=[{"role": "user", "content": "解释什么是 API"}]
)
print(response["message"]["content"])

# 带 System Prompt
response = ollama.chat(
    model="qwen2.5:1.5b",
    messages=[
        {"role": "system", "content": "你是一个代码审查助手,只关注代码质量问题。"},
        {"role": "user", "content": "审查这段代码:\ndef add(a,b): return a+b"}
    ]
)

在浏览器中运行(WebLLM)

// 使用 WebLLM 在浏览器中运行小模型
import { CreateMLCEngine } from "@mlc-ai/web-llm";

async function runInBrowser() {
  // 加载模型(首次需要下载)
  const engine = await CreateMLCEngine("Phi-3-mini-4k-instruct-q4f16_1-MLC");

  const response = await engine.chat.completions.create({
    messages: [{ role: "user", content: "Hello!" }],
  });

  console.log(response.choices[0].message.content);
}

实际应用场景

1. 代码补全

小模型在代码补全场景表现出色,因为补全通常只需要理解局部上下文:

# 使用 Qwen2.5-Coder 1.5B 做代码补全
def code_completion(prefix: str, suffix: str = "") -> str:
    response = ollama.generate(
        model="qwen2.5-coder:1.5b",
        prompt=f"<|fim_prefix|>{prefix}<|fim_suffix|>{suffix}<|fim_middle|>",
        options={"temperature": 0.2, "num_predict": 100},
    )
    return response["response"]

# 示例
prefix = """def fibonacci(n):
    if n <= 1:
        return n
    """
completion = code_completion(prefix)
# 输出: "return fibonacci(n-1) + fibonacci(n-2)"

2. 文本分类

def classify_text(text: str, categories: list[str]) -> str:
    categories_str = "、".join(categories)
    response = ollama.chat(
        model="phi3:mini",
        messages=[{
            "role": "user",
            "content": f"将以下文本分类为 {categories_str} 之一。只输出类别名称。\n\n文本:{text}"
        }],
        options={"temperature": 0},
    )
    return response["message"]["content"].strip()

# 使用
result = classify_text(
    "这个产品质量太差了,用了一天就坏了",
    ["正面", "负面", "中性"]
)
print(result)  # "负面"

3. 信息提取

import json

def extract_entities(text: str) -> dict:
    response = ollama.chat(
        model="qwen2.5:3b",
        messages=[{
            "role": "system",
            "content": "从文本中提取实体信息,以 JSON 格式输出。"
        }, {
            "role": "user",
            "content": f"提取以下文本中的人名、地点和日期:\n{text}"
        }],
        format="json",
        options={"temperature": 0},
    )
    return json.loads(response["message"]["content"])

result = extract_entities("张三于 2024 年 3 月 15 日在北京参加了技术大会。")
# {"人名": ["张三"], "地点": ["北京"], "日期": ["2024年3月15日"]}

4. 文本摘要

def summarize(text: str, max_length: int = 100) -> str:
    response = ollama.chat(
        model="phi3:mini",
        messages=[{
            "role": "user",
            "content": f"用不超过 {max_length} 字总结以下内容:\n\n{text}"
        }],
        options={"temperature": 0.3},
    )
    return response["message"]["content"]

5. 本地 RAG 系统

# 完全本地化的 RAG 系统
import ollama
import numpy as np

class LocalRAG:
    def __init__(self, model="phi3:mini", embed_model="nomic-embed-text"):
        self.model = model
        self.embed_model = embed_model
        self.documents = []
        self.embeddings = []

    def add_document(self, text: str):
        """添加文档到知识库"""
        self.documents.append(text)
        # 使用本地 Embedding 模型
        response = ollama.embeddings(
            model=self.embed_model,
            prompt=text
        )
        self.embeddings.append(response["embedding"])

    def query(self, question: str, top_k: int = 3) -> str:
        """查询知识库"""
        # 1. 获取问题的 Embedding
        q_response = ollama.embeddings(
            model=self.embed_model,
            prompt=question
        )
        q_embedding = q_response["embedding"]

        # 2. 找到最相关的文档
        similarities = [
            np.dot(q_embedding, doc_emb) /
            (np.linalg.norm(q_embedding) * np.linalg.norm(doc_emb))
            for doc_emb in self.embeddings
        ]
        top_indices = np.argsort(similarities)[-top_k:][::-1]
        context = "\n".join(self.documents[i] for i in top_indices)

        # 3. 用本地模型生成回答
        response = ollama.chat(
            model=self.model,
            messages=[{
                "role": "system",
                "content": f"根据以下上下文回答问题。如果上下文中没有答案,说明不知道。\n\n上下文:\n{context}"
            }, {
                "role": "user",
                "content": question
            }]
        )
        return response["message"]["content"]

# 使用
rag = LocalRAG()
rag.add_document("我们的退货政策是 7 天无理由退货...")
rag.add_document("会员积分可以在下次购物时抵扣...")
answer = rag.query("你们的退货政策是什么?")

性能与大小的权衡

Benchmark 对比

模型参数量MMLUHumanEvalGSM8K
Phi-3 mini3.8B69%59%82%
Gemma 2 2B2B52%35%55%
Qwen2.5 3B3B65%52%75%
Llama 3.2 3B3B63%48%72%
Mistral 7B7B63%30%52%

注意:Phi-3 mini (3.8B) 在多个 Benchmark 上超过了 Mistral 7B,说明模型质量不完全取决于参数量。

什么时候小模型不够用

场景小模型表现建议
简单分类优秀用小模型
信息提取良好用小模型
代码补全良好用小模型
复杂推理较差用大模型
长文档理解较差用大模型
创意写作一般用大模型
多轮对话一般视复杂度而定

优化小模型性能的技巧

1. 精心设计 Prompt

小模型对 Prompt 更敏感,需要更明确的指令:

# ❌ 对小模型来说太模糊
prompt_bad = "分析一下这段文字"

# ✅ 明确、具体的指令
prompt_good = """任务:情感分类
输入:用户评论
输出:只输出"正面"、"负面"或"中性"三个词之一

评论:这个产品还不错
分类:"""

2. 使用 Few-shot 示例

prompt = """将评论分类为正面/负面/中性。

评论:太好了,非常满意!
分类:正面

评论:质量一般,不推荐
分类:负面

评论:还行吧,凑合用
分类:中性

评论:{user_input}
分类:"""

3. 控制输出格式

# 限制输出长度和格式
response = ollama.chat(
    model="phi3:mini",
    messages=[{"role": "user", "content": prompt}],
    options={
        "temperature": 0,      # 确定性输出
        "num_predict": 10,     # 限制输出长度
        "stop": ["\n", "。"],  # 遇到换行或句号就停止
    },
)

总结

小模型正在改变我们使用 AI 的方式:

  • 不是所有任务都需要大模型,很多场景下 3B 参数就够了
  • 本地运行意味着零延迟、零成本、完全隐私
  • Phi、Gemma、Qwen 等小模型在特定任务上表现出色
  • Ollama 让本地部署变得像安装一个 App 一样简单
  • 小模型 + 精心设计的 Prompt = 出色的性价比

最好的模型不是最大的那个,而是在你的约束条件下表现最好的那个。小模型的价值,在于让 AI 真正触手可及。

评论

加载中...

相关文章

分享:

评论

加载中...