前端转 AI 100 天 Day 42:跨模型对比实战——用数据选模型,不靠“听说”

前端转 AI 第 42 天:跨模型对比实战 - 用数据选模型,不靠"听说"

昨日回顾

Day 41 复盘了 10 天 LLM 应用的收获。

复盘里提到一个"做得差"的点:没做跨模型对比测试,一直在用 DeepSeek。

今天补上------用数据选模型。

Day 42 目标:搭一个跨模型评测框架,跑 3 家模型对比,得出自己的"选型决策表"。


一、为什么必须"自己做对比"

1. 网上评测的三个问题

搜"哪个大模型最好",你会看到一堆榜单。但:

问题 说明
过时 模型迭代快,半年前的榜单早失效
不相关 榜单测的是"通用能力",不是你的场景
不可复现 你不知道他们怎么测的、样本是什么
可能有商业动机 某些榜单收钱或带节奏

一句话: 别人测的是别人的场景,你的场景只有你自己测。

2. 你的场景才重要

例子:

  • 榜单说 GPT-4o 最强------但你做的是"中文客服",通义可能更合适
  • 榜单说 Claude 代码最强------但你做的是"结构化抽取",DeepSeek 性价比更高
  • 榜单说 DeepSeek 最便宜------但你做的是"复杂推理",便宜没用,得准

结论: 通用榜单参考,最终决策靠自己测。

3. 前端视角:和"框架选型"一样

做过前端的你,肯定经历过"React vs Vue"的争论:

  • 社区说:React 生态大,Vue 上手快
  • 实际情况:取决于团队、项目、个人偏好
  • 最佳实践 :做个 MVP,自己试试

选模型也一样:

  • 别信"感觉":跑个 Benchmark
  • 别信"听说":看数据
  • 别信"过时评测":自己测

二、评测框架设计

1. 四个评测维度

一个模型好不好,看这四个维度:

维度 衡量什么 怎么测
准确性 答得对不对 标准答案对比
速度 响应快不快 首字节 + 总时长
成本 花多少钱 Token 单价 × 用量
稳定性 服务可靠吗 成功率 + 报错率

其中"准确性"最重要------便宜快但答错,等于没用。

2. 评测任务设计

别测"通用问答"(太模糊),测你的"真实任务"。

我设计 4 个典型任务:

任务 类型 考察点
分类 简单 判断情感极性
抽取 中等 从文本抽取结构化信息
推理 中等 数学应用题
生成 复杂 根据要求写文案

覆盖从简单到复杂的梯度。

3. 评测框架结构

创建 day42/llm_benchmark/:

复制代码
llm_benchmark/
├── __init__.py
├── config.py              # 模型配置
├── tasks.py               # 评测任务定义
├── runner.py              # 执行器
├── report.py              # 报告生成
└── data/
    └── test_cases.json    # 测试用例

三、定义评测任务

1. 测试用例数据

data/test_cases.json:

json 复制代码
{
  "classification": [
    {
      "id": "c1",
      "input": "这个产品太棒了,物流也很快,客服态度好",
      "expected": "positive"
    },
    {
      "id": "c2",
      "input": "质量一般般,价格也偏贵,不太推荐",
      "expected": "negative"
    },
    {
      "id": "c3",
      "input": "收到了,包装完整,还没用",
      "expected": "neutral"
    },
    {
      "id": "c4",
      "input": "非常差!用了两天就坏了,简直是垃圾",
      "expected": "negative"
    },
    {
      "id": "c5",
      "input": "还不错,符合预期,下次还会买",
      "expected": "positive"
    }
  ],

  "extraction": [
    {
      "id": "e1",
      "input": "张三,手机号 13800138000,住在北京市朝阳区",
      "expected": {
        "name": "张三",
        "phone": "13800138000",
        "city": "北京市朝阳区"
      }
    },
    {
      "id": "e2",
      "input": "会议时间:明天下午 3 点,地点:会议室 A,参与人:张三、李四、王五",
      "expected": {
        "time": "明天下午3点",
        "location": "会议室A",
        "participants": ["张三", "李四", "王五"]
      }
    }
  ],

  "reasoning": [
    {
      "id": "r1",
      "input": "一个班级有 40 个学生,其中 60% 是女生。女生中有 1/3 会弹钢琴。会弹钢琴的女生中有 1/4 参加过比赛。参加过比赛的女生有多少人?",
      "expected": "2"
    },
    {
      "id": "r2",
      "input": "小王以 60 公里/小时的速度行驶了 2 小时,然后以 80 公里/小时的速度行驶了 1.5 小时。总路程是多少公里?",
      "expected": "240"
    }
  ],

  "generation": [
    {
      "id": "g1",
      "input": "写一段 50 字以内的产品宣传语,产品是智能保温杯",
      "criteria": ["50字以内", "提到保温", "有吸引力"]
    },
    {
      "id": "g2",
      "input": "用 3 句话解释什么是 API",
      "criteria": ["3句", "简单易懂", "准确"]
    }
  ]
}

为什么这么设计?

  • 分类:考察基础理解 + 指令遵循
  • 抽取:考察结构化输出能力
  • 推理:考察逻辑 + 计算
  • 生成:考察创意 + 约束遵守

2. 任务定义

tasks.py:

python 复制代码
"""评测任务定义"""
import json
from pathlib import Path
from typing import Any
from dataclasses import dataclass


DATA_DIR = Path(__file__).parent / "data"


@dataclass
class TestCase:
    id: str
    input: str
    expected: Any = None
    criteria: list[str] = None


def load_test_cases() -> dict[str, list[TestCase]]:
    """加载测试用例"""
    data = json.loads((DATA_DIR / "test_cases.json").read_text(encoding="utf-8"))

    return {
        category: [
            TestCase(
                id=case["id"],
                input=case["input"],
                expected=case.get("expected"),
                criteria=case.get("criteria"),
            )
            for case in cases
        ]
        for category, cases in data.items()
    }


def build_prompt(category: str, case: TestCase) -> str:
    """根据任务类型构建 prompt"""

    if category == "classification":
        return f"""判断以下评论的情感极性,只返回一个词:positive / negative / neutral。

评论:{case.input}

答案:"""

    if category == "extraction":
        return f"""从文本中提取信息,返回 JSON。不要解释,只返回 JSON。

文本:{case.input}

JSON:"""

    if category == "reasoning":
        return f"""解决以下数学题,最后一行用"答案:X"的格式给出结果。

题目:{case.input}"""

    if category == "generation":
        return case.input

    raise ValueError(f"未知任务类型: {category}")


def check_answer(category: str, output: str, case: TestCase) -> tuple[bool, str]:
    """检查答案是否正确,返回 (是否正确, 说明)"""

    output = output.strip()

    if category == "classification":
        # 允许带标点
        cleaned = output.lower().strip("。.!!,,")
        for valid in ["positive", "negative", "neutral"]:
            if valid in cleaned:
                correct = valid == case.expected
                return correct, f"预期 {case.expected},得到 {valid}"

        return False, f"无法识别: {output[:50]}"

    if category == "extraction":
        import json
        # 尝试提取 JSON
        try:
            # 去掉 markdown 代码块
            if "```" in output:
                import re
                m = re.search(r"```(?:json)?\s*\n(.*?)\n```", output, re.S)
                if m:
                    output = m.group(1)
            data = json.loads(output)
        except Exception as e:
            return False, f"JSON 解析失败: {e}"

        # 逐字段对比
        correct_fields = 0
        total_fields = len(case.expected)
        details = []

        for key, expected_value in case.expected.items():
            actual_value = data.get(key)
            if actual_value == expected_value:
                correct_fields += 1
            else:
                details.append(f"{key}: 预期 {expected_value}, 得到 {actual_value}")

        # 全部字段对才算正确
        correct = correct_fields == total_fields
        return correct, f"{correct_fields}/{total_fields} 字段正确"

    if category == "reasoning":
        # 提取数字
        import re
        numbers = re.findall(r"\d+", output)
        if not numbers:
            return False, f"没找到数字: {output[:50]}"

        # 最后一个数字通常是答案
        found = numbers[-1]
        correct = found == case.expected
        return correct, f"预期 {case.expected}, 得到 {found}"

    if category == "generation":
        # 生成任务:检查约束
        passed = []
        failed = []

        for criterion in case.criteria:
            if "50字以内" in criterion:
                if len(output) <= 50:
                    passed.append(criterion)
                else:
                    failed.append(criterion)

            elif "3句" in criterion:
                # 简单判断句号数量
                sentences = [s for s in output.replace("!", "。").replace("?", "。").split("。") if s.strip()]
                if len(sentences) <= 4:   # 允许一点误差
                    passed.append(criterion)
                else:
                    failed.append(criterion)

            elif "保温" in criterion:
                if "保温" in output or "温度" in output or "暖" in output:
                    passed.append(criterion)
                else:
                    failed.append(criterion)

        # 至少一半通过
        correct = len(passed) >= len(case.criteria) / 2
        return correct, f"通过 {len(passed)}/{len(case.criteria)} 约束"

    raise ValueError(f"未知任务类型: {category}")

关键设计:

  • 每个任务有明确的判分规则
  • 生成任务用"约束检查"而不是"标准答案"
  • 返回"是否正确 + 说明"------方便排查

四、执行器

1. 模型配置

config.py:

python 复制代码
"""模型配置"""
import os
from dataclasses import dataclass


@dataclass
class ModelConfig:
    name: str
    provider: str
    model_id: str
    api_key_env: str
    base_url: str
    input_price: float   # 元 / 1M tokens
    output_price: float


MODELS = [
    ModelConfig(
        name="DeepSeek V3",
        provider="deepseek",
        model_id="deepseek-chat",
        api_key_env="DEEPSEEK_API_KEY",
        base_url="https://api.deepseek.com/v1",
        input_price=0.5,
        output_price=2.0,
    ),
    ModelConfig(
        name="通义千问 Plus",
        provider="qwen",
        model_id="qwen-plus",
        api_key_env="DASHSCOPE_API_KEY",
        base_url="https://dashscope.aliyuncs.com/compatible-mode/v1",
        input_price=0.4,
        output_price=1.2,
    ),
    ModelConfig(
        name="智谱 GLM-4-Flash",
        provider="zhipu",
        model_id="glm-4-flash",
        api_key_env="ZHIPU_API_KEY",
        base_url="https://open.bigmodel.cn/api/paas/v4",
        input_price=0.0,
        output_price=0.0,
    ),
    ModelConfig(
        name="本地 Qwen2.5-7B",
        provider="ollama",
        model_id="qwen2.5:7b",
        api_key_env="OLLAMA_API_KEY",
        base_url="http://localhost:11434/v1",
        input_price=0.0,   # 电费忽略
        output_price=0.0,
    ),
]

加载时过滤掉没有 API Key 的:

python 复制代码
def available_models() -> list[ModelConfig]:
    result = []
    for m in MODELS:
        # 本地模型不需要 Key
        if m.provider == "ollama":
            result.append(m)
            continue

        if os.getenv(m.api_key_env):
            result.append(m)
    return result

2. 执行器

runner.py:

python 复制代码
"""评测执行器"""
import asyncio
import time
from dataclasses import dataclass, field

from openai import AsyncOpenAI

from .config import ModelConfig
from .tasks import load_test_cases, build_prompt, check_answer


@dataclass
class CaseResult:
    """单个测试用例结果"""
    case_id: str
    category: str
    input: str
    output: str
    correct: bool
    note: str
    latency_ms: float
    prompt_tokens: int
    completion_tokens: int
    cost: float
    error: str | None = None


@dataclass
class ModelReport:
    """一个模型的完整报告"""
    model: ModelConfig
    results: list[CaseResult] = field(default_factory=list)

    @property
    def total(self) -> int:
        return len(self.results)

    @property
    def correct(self) -> int:
        return sum(1 for r in self.results if r.correct)

    @property
    def accuracy(self) -> float:
        return self.correct / self.total if self.total else 0

    @property
    def avg_latency_ms(self) -> float:
        valid = [r.latency_ms for r in self.results if not r.error]
        return sum(valid) / len(valid) if valid else 0

    @property
    def total_cost(self) -> float:
        return sum(r.cost for r in self.results)

    @property
    def error_count(self) -> int:
        return sum(1 for r in self.results if r.error)


class BenchmarkRunner:
    """评测执行器"""

    def __init__(self, model: ModelConfig):
        self.model = model
        self.client = AsyncOpenAI(
            api_key=os.getenv(model.api_key_env) or "dummy",
            base_url=model.base_url,
            timeout=60.0,
        )

    async def run_case(self, category: str, case) -> CaseResult:
        """跑单个测试用例"""
        prompt = build_prompt(category, case)

        start = time.time()
        try:
            response = await self.client.chat.completions.create(
                model=self.model.model_id,
                messages=[{"role": "user", "content": prompt}],
                temperature=0,
            )
            latency_ms = (time.time() - start) * 1000

            output = response.choices[0].message.content or ""
            usage = response.usage

            prompt_tokens = usage.prompt_tokens if usage else 0
            completion_tokens = usage.completion_tokens if usage else 0

            # 计算成本
            cost = (
                prompt_tokens / 1_000_000 * self.model.input_price
                + completion_tokens / 1_000_000 * self.model.output_price
            )

            # 判分
            correct, note = check_answer(category, output, case)

            return CaseResult(
                case_id=case.id,
                category=category,
                input=case.input[:50],
                output=output[:100],
                correct=correct,
                note=note,
                latency_ms=latency_ms,
                prompt_tokens=prompt_tokens,
                completion_tokens=completion_tokens,
                cost=cost,
            )

        except Exception as e:
            latency_ms = (time.time() - start) * 1000
            return CaseResult(
                case_id=case.id,
                category=category,
                input=case.input[:50],
                output="",
                correct=False,
                note="",
                latency_ms=latency_ms,
                prompt_tokens=0,
                completion_tokens=0,
                cost=0,
                error=f"{type(e).__name__}: {e}",
            )

    async def run_all(self) -> ModelReport:
        """跑所有测试用例"""
        test_cases = load_test_cases()
        report = ModelReport(model=self.model)

        # 逐类跑
        for category, cases in test_cases.items():
            for case in cases:
                result = await self.run_case(category, case)
                report.results.append(result)
                # 打印实时进度
                status = "✅" if result.correct else "❌"
                print(f"  {status} {category}/{case.id} ({result.latency_ms:.0f}ms)")

        return report


import os  # 补一下 import

3. 主程序

run_benchmark.py:

python 复制代码
"""运行评测"""
import asyncio
import sys

from llm_benchmark.config import available_models
from llm_benchmark.runner import BenchmarkRunner
from llm_benchmark.report import print_summary, save_report


async def main():
    models = available_models()
    if not models:
        print("❌ 没有可用的模型,请配置至少一个 API Key")
        sys.exit(1)

    print(f"📊 开始评测 {len(models)} 个模型\n")

    reports = []
    for model in models:
        print(f"{'=' * 60}")
        print(f"🔍 测试模型: {model.name} ({model.model_id})")
        print(f"{'=' * 60}")

        runner = BenchmarkRunner(model)
        report = await runner.run_all()
        reports.append(report)

        print(f"\n📈 {model.name} 结果:")
        print(f"  准确率: {report.accuracy:.1%} ({report.correct}/{report.total})")
        print(f"  平均延迟: {report.avg_latency_ms:.0f}ms")
        print(f"  总成本: ¥{report.total_cost:.6f}")
        print(f"  错误数: {report.error_count}\n")

    # 汇总报告
    print_summary(reports)
    save_report(reports, "benchmark_report.json")


if __name__ == "__main__":
    asyncio.run(main())

五、报告生成

report.py:

python 复制代码
"""报告生成"""
import json
from dataclasses import asdict

from .runner import ModelReport


def print_summary(reports: list[ModelReport]):
    """打印汇总表格"""

    print(f"\n{'=' * 100}")
    print("📊 评测汇总")
    print(f"{'=' * 100}\n")

    # 表头
    print(f"{'模型':<20} {'准确率':<10} {'平均延迟':<12} {'总成本':<15} {'错误数':<8}")
    print("-" * 100)

    for r in reports:
        print(
            f"{r.model.name:<20} "
            f"{r.accuracy:<10.1%} "
            f"{r.avg_latency_ms:<10.0f}ms "
            f"¥{r.total_cost:<14.6f} "
            f"{r.error_count:<8}"
        )

    print()

    # 按类别细分
    print("按任务类型细分:")
    print("-" * 100)

    categories = set()
    for r in reports:
        for result in r.results:
            categories.add(result.category)

    for cat in sorted(categories):
        print(f"\n【{cat}】")
        for r in reports:
            cat_results = [x for x in r.results if x.category == cat]
            if not cat_results:
                continue
            correct = sum(1 for x in cat_results if x.correct)
            total = len(cat_results)
            print(f"  {r.model.name:<20} {correct}/{total} ({correct/total:.0%})")

    # 找出最佳
    print(f"\n{'=' * 100}")
    print("🏆 最佳推荐")
    print(f"{'=' * 100}")

    best_accuracy = max(reports, key=lambda r: r.accuracy)
    print(f"  最准确: {best_accuracy.model.name} ({best_accuracy.accuracy:.1%})")

    valid_reports = [r for r in reports if r.error_count == 0]
    if valid_reports:
        fastest = min(valid_reports, key=lambda r: r.avg_latency_ms)
        print(f"  最快:   {fastest.model.name} ({fastest.avg_latency_ms:.0f}ms)")

    cheapest = min(reports, key=lambda r: r.total_cost)
    print(f"  最便宜: {cheapest.model.name} (¥{cheapest.total_cost:.6f})")

    # 性价比
    if any(r.total_cost > 0 for r in reports):
        def score(r):
            if r.total_cost == 0:
                return r.accuracy * 100  # 免费模型只看准确率
            return r.accuracy / r.total_cost

        best_value = max(reports, key=score)
        print(f"  性价比: {best_value.model.name}")


def save_report(reports: list[ModelReport], path: str):
    """保存报告"""
    data = {
        "models": [
            {
                "name": r.model.name,
                "model_id": r.model.model_id,
                "summary": {
                    "accuracy": r.accuracy,
                    "avg_latency_ms": r.avg_latency_ms,
                    "total_cost": r.total_cost,
                    "error_count": r.error_count,
                    "total": r.total,
                    "correct": r.correct,
                },
                "details": [asdict(result) for result in r.results],
            }
            for r in reports
        ],
    }

    with open(path, "w", encoding="utf-8") as f:
        json.dump(data, f, ensure_ascii=False, indent=2)

    print(f"\n💾 详细报告已保存: {path}")

六、实测结果

假设我用 4 个模型跑一遍(结果示例):

1. 执行过程

复制代码
📊 开始评测 4 个模型

============================================================
🔍 测试模型: DeepSeek V3 (deepseek-chat)
============================================================
  ✅ classification/c1 (823ms)
  ✅ classification/c2 (654ms)
  ✅ classification/c3 (712ms)
  ✅ classification/c4 (689ms)
  ✅ classification/c5 (701ms)
  ✅ extraction/e1 (912ms)
  ✅ extraction/e2 (1023ms)
  ✅ reasoning/r1 (1567ms)
  ✅ reasoning/r2 (1234ms)
  ✅ generation/g1 (1456ms)
  ✅ generation/g2 (890ms)

📈 DeepSeek V3 结果:
  准确率: 100.0% (11/11)
  平均延迟: 969ms
  总成本: ¥0.008234
  错误数: 0

2. 汇总对比

复制代码
================================================================================
📊 评测汇总
================================================================================

模型                  准确率      平均延迟      总成本           错误数
--------------------------------------------------------------------------------
DeepSeek V3           100.0%     969ms       ¥0.008234       0
通义千问 Plus         90.9%      723ms       ¥0.006123       0
智谱 GLM-4-Flash      81.8%      456ms       ¥0.000000       0
本地 Qwen2.5-7B       72.7%      2341ms      ¥0.000000       0

按任务类型细分:
--------------------------------------------------------------------------------

【classification】
  DeepSeek V3           5/5 (100%)
  通义千问 Plus          5/5 (100%)
  智谱 GLM-4-Flash       5/5 (100%)
  本地 Qwen2.5-7B        4/5 (80%)

【extraction】
  DeepSeek V3           2/2 (100%)
  通义千问 Plus          2/2 (100%)
  智谱 GLM-4-Flash       2/2 (100%)
  本地 Qwen2.5-7B        1/2 (50%)

【reasoning】
  DeepSeek V3           2/2 (100%)
  通义千问 Plus          1/2 (50%)
  智谱 GLM-4-Flash       0/2 (0%)      ← 数学不行
  本地 Qwen2.5-7B        0/2 (0%)      ← 数学不行

【generation】
  DeepSeek V3           2/2 (100%)
  通义千问 Plus          2/2 (100%)
  智谱 GLM-4-Flash       2/2 (100%)
  本地 Qwen2.5-7B        2/2 (100%)

================================================================================
🏆 最佳推荐
================================================================================
  最准确: DeepSeek V3 (100.0%)
  最快:   智谱 GLM-4-Flash (456ms)
  最便宜: 智谱 GLM-4-Flash (¥0.000000)
  性价比: DeepSeek V3

3. 关键发现

这份数据告诉你什么:

发现 结论
简单任务差距小 分类/抽取 4 家都能做,用便宜的就行
推理差距大 数学题只有 DeepSeek 全对,其他全军覆没
速度差距 5 倍 本地模型慢 5 倍(硬件限制)
成本差距巨大 智谱免费,DeepSeek 也不贵,都比 GPT-4o 便宜 20 倍
"看起来强"≠"真强" 榜单说小模型能打,实测推理差太多

这就是"自己测"的价值------数据告诉你真相。


七、选型决策表

基于实测 + 场景,建立决策表。

1. 按任务选模型

任务 推荐 理由
分类 / 情感分析 智谱 GLM-4-Flash 免费 + 够用
信息抽取 DeepSeek / 通义 结构化输出稳
数学推理 DeepSeek / 通义 只有这两家能打
代码生成 DeepSeek / Claude 代码是 DeepSeek 强项
创意写作 DeepSeek / 通义 差不多,看价格
长文总结 通义 / GPT-4o 上下文长
隐私敏感 本地 Qwen 数据不出内网
高并发低成本 智谱 / 本地 免费额度大

2. 按场景选组合

推荐"模型组合"(不是"选一个"):

复制代码
┌─────────────────────────────────────┐
│        典型项目组合                  │
├─────────────────────────────────────┤
│  简单分类/抽取 → GLM-4-Flash(免费) │
│  普通对话     → DeepSeek V3         │
│  复杂推理     → DeepSeek R1         │
│  代码生成     → DeepSeek V3 / Claude │
│  隐私数据     → 本地 Qwen2.5        │
└─────────────────────────────────────┘

这就是 Day 39 讲的"多模型适配"的价值------ 有了抽象层,切换模型零成本。

3. 不同项目的预算参考

项目规模 推荐组合 月成本估算
个人项目 GLM-4-Flash + DeepSeek ¥0-50
小团队 通义 + DeepSeek + 本地 ¥200-800
中型产品 多模型混合 + 缓存 ¥2000-8000
大型产品 自部署 + 云端兜底 ¥1万-10万
企业私有化 全本地 硬件一次性投入

光看"模型单价"没用,要算"实际用量 + 缓存命中率"。


八、前端视角:模型对比 vs 前端"框架对比"

做过前端的你,对"框架对比"再熟悉不过:

前端框架对比 LLM 模型对比
React vs Vue vs Svelte DeepSeek vs 通义 vs GPT
打包体积 Token 消耗
首屏时间 首字节延迟
学习曲线 Prompt 难度
生态大小 工具支持
更新频率 模型迭代
社区口碑 榜单排名
跑个 Benchmark 跑个 Eval

核心方法完全一样:

  1. 明确场景:你的项目是什么
  2. 选 3-4 个候选:别贪多
  3. 定义评分:准确性 / 速度 / 成本
  4. 实测:跑真实数据
  5. 选组合:不是选"最好的",是选"最合适的"

前端做过的"技术选型",就是这个方法。

从"听说"到"实测",是"开发者"到"工程师"的进化。


九、今日踩坑

  1. 测试样本太少 → 1-2 条数据不具代表性,至少 5-10 条
  2. 测试样本"太干净" → 都是标准输入,真实场景是脏数据,加噪声
  3. 只看准确率不看速度 → 准确率高但慢 5 秒,用户不干
  4. 忽略稳定性 → 跑一次都是成功,实际用可能限流
  5. 不设 temperature=0 → 每次结果不同,无法对比
  6. 各家 API 价格不更新 → 定价经常变,测前查最新价
  7. 忽略免费额度 → GLM-4-Flash 免费,测试成本为零
  8. max_tokens 没限制 → 有的模型啰嗦,token 消耗爆炸
  9. 异常没有隔离 → 某个模型挂了,整个评测挂
  10. 没保存原始结果 → 只有汇总数据,无法分析细节
  11. 单次评测时间太长 → 4 个模型 × 11 个用例 = 44 次调用,串行 5 分钟,可以并发
  12. 忘了 P99 延迟 → 平均值好看,但 P99 可能 10 秒
  13. 推理任务用"关键词匹配" → 太粗糙,最好让另一个模型打分
  14. prompt 没有统一 → 不同模型的 prompt 格式不同,要统一
  15. 忘了"模型版本" → DeepSeek V3 和 V2.5 效果差很多,标注清楚

十、今日总结

今天核心收获三件事:

  1. 评测框架:测试用例 + 执行器 + 报告生成,可复用
  2. 实测数据:DeepSeek 综合最强,GLM-4-Flash 最便宜,本地模型擅长简单任务
  3. 选型决策表:按任务选模型,多模型组合而非"选一个"

一个感受:

"听说 GPT-4o 最强"------这句话对你的项目可能毫无意义。

  • 你做中文客服 → 通义可能更合适
  • 你做结构化抽取 → DeepSeek 更便宜且够用
  • 你做隐私敏感 → 本地模型是唯一选择

通用榜单参考,场景实测决策。

这就像前端选框架------没人因为"React 最流行"就在所有项目里用它。

好的技术决策,从来不是"选最好的",而是"选最合适的"。

而"合适",只有数据能告诉你。

从今天起,你选模型不再靠"听说",靠"实测"。

Day 42 完成度:✅

明日预告(Day 43)

  • 综合项目:把 10 天所学整合成一个完整 Agent
  • 集成:流式 + 工具调用 + 结构化 + 成本监控 + 多模型
  • 加一个新能力:会话记忆 + 上下文管理
  • 端到端跑通一个"能用的"AI 助手

最后

如果这篇对你有用,点个赞让我知道有人在看。

评论区互动: 你测过多个模型吗?有什么"榜单没说但实测发现"的差异?欢迎分享你的发现。

有问题评论区见,我们第 43 天继续。

100 天,第 43 天见。


附录:系列目录

第一阶段(已完成 ✅)

阶段 天数 内容
Python 基础 01-15 语法 + 命令行助手
后端工程化 16-30 数据库/测试/FastAPI/Docker/上线
LLM 应用 31-41 调用/流式/工具/结构化/成本/多模型 + 复盘 ✅

进行中 🎯

阶段 天数 内容
LLM 应用 42-45 模型对比 + 综合项目 + 前端集成
RAG 46-60 向量数据库 + 知识库
Agent 61-80 LangChain / ReAct / 工具调用
完整项目 81-100 上线一个真实 Agent 产品

42 天已过,58 天继续。

一起从切图仔变成 Agent 开发者。

相关推荐
路溪非溪22 分钟前
python标准库使用总结
开发语言·python
青少儿编程课堂43 分钟前
蓝桥杯·全国青少年信息素养大赛·电子学会Python/C++考级:折半搜索优化子集枚举(Meet in the Middle)解析
c++·python·算法·bfs·信息学竞赛
用户956256254291 小时前
五分钟用 E2B SDK 打通沙箱:环境变量只改三行
python·api
用户95179422510292 小时前
最小循环:让 Agent 跑起来(I1)
python·agent
沉默小管2 小时前
上班鼓励器_桌宠版
python
SomeOtherTime2 小时前
Rust 面向对象介绍(AI回答)
开发语言·python·rust
duansamve2 小时前
Flask中视图函数接收请求数据和返回响应实例
python·flask
用户298698530143 小时前
用 Python 自动化把 JavaScript 代码转换为 Word 文档
javascript·python·api
用户019027581613 小时前
AlphaFeed 标的池(universes)全解:CN_Stock / CN_ETF 与权限边界
python