关键词:大模型评测、模型排行榜、LLM-as-judge、聚合 API、Python 实战
适用:已经做过一轮横评,想把「跑一遍」升级成「可复用的打分榜单」

一、为什么需要排行榜,而不是一次性横评

上一篇我们用一份代码把 Claude / GPT / DeepSeek / Qwen / Kimi 在同一道题上跑了一遍,看到的是「单次印象」。但真实选型要看多维度的稳定表现:代码写得对不对、推理准不准、长文本抓不抓得住重点、中文理解到不到位。

如果每次都靠人肉看输出,既慢又主观。本文在聚合 API 的基础上,加两样东西:

  1. LLM-as-judge:用一个强模型当「裁判」,给每个回答按维度打分;
  2. 自动校验:客观题(代码、数学)用程序直接验证对错。

最后把分数聚合成一张排行榜,模型换名字就能复跑,厂商更新模型后随时重排。

二、环境准备

pip install openai

登录 TokenPortal 控制台创建 API Key,只显示一次,存好。控制台入口与模型清单来我主页查看。base_url 指向平台网关(以控制台「API 文档」页为准,本文用 https://api.tokenportal.ai/v1 占位)。

三、核心思路

题库(多维度) ──▶ 候选模型逐题作答 ──▶ 两份结果
                                      ├─ 客观题:程序自动校验(对/错)
                                      └─ 主观题:裁判模型 LLM-as-judge 打分
                                                │
                                                ▼
                                       聚合 → 排行榜(按维度 + 综合)

关键点:候选模型和裁判模型走同一个网关,换模型只改 model 一行,不需要再对接第二家 SDK。

四、核心代码

4.1 候选模型 + 题库

import time, json, re
from openai import OpenAI

client = OpenAI(api_key="你的_KEY", base_url="https://api.tokenportal.ai/v1")

# 想评谁往这里加——换模型只改名字
candidates = [
    "anthropic/claude-opus-4.8",
    "openai/gpt-5.5",
    "deepseek/deepseek-v4-pro",
    "qwen/qwen3.7-max",
    "moonshotai/kimi-k3",
    "zhipu/glm-5.2",
    "google/gemini-3.1-pro-preview",
    "minimax/minimax-m3",
    "baidu/ernie-5.1",
]

# 裁判模型:单独走网关,挑一个综合强的
JUDGE = "openai/gpt-5.5"

# 题库:每题带 维度 与 客观校验方式
# check=None 走裁判打分;"code" 跑单元测试;"math:答案" 正则比对
tasks = [
    {"dim": "代码", "prompt": "用 Python 写函数 is_palindrome(s),忽略大小写和非字母数字字符,返回布尔值。只给代码。", "check": "code"},
    {"dim": "推理", "prompt": "鸡兔同笼:共 35 只,94 只脚。问鸡和兔各几只?只给最终答案:鸡X只,兔Y只。", "check": "math:23,12"},
    {"dim": "长文本", "prompt": "请用 3 句话总结以下内容的核结论:(此处放一段长文)。", "check": None},
    {"dim": "中文理解", "prompt": "『他差一点没赶上火车』与『他差一点赶上火车』意思相同吗?简要解释。", "check": None},
]

4.2 作答 + 客观校验

def ask(model, prompt):
    t0 = time.time()
    r = client.chat.completions.create(model=model, messages=[{"role": "user", "content": prompt}])
    dt = time.time() - t0
    return r.choices[0].message.content, r.usage, dt

def auto_check(kind, answer):
    """客观题自动校验,返回 1.0 / 0.0"""
    if kind == "code":
        # 抽出代码块,能定义函数且回文判断正确即给分
        try:
            m = re.search(r"def is_palindrome.*", answer, re.S)
            if not m: return 0.0
            ns = {}
            exec(m.group(0), ns)
            f = ns.get("is_palindrome")
            ok = f and f("A man, a plan, a canal: Panama") is True and f("hello") is False
            return 1.0 if ok else 0.0
        except Exception:
            return 0.0
    if kind and kind.startswith("math:"):
        want = kind.split(":", 1)[1]
        return 1.0 if want.replace(" ", "") in answer.replace(" ", "") else 0.0
    return None  # 主观题,交给裁判

4.3 裁判模型打分(LLM-as-judge)

def judge_score(prompt, answer):
    sys = ("你是严谨的评测裁判。请从准确性(0-5)、完整性(0-5)、表达清晰度(0-5)三项打分,"
           "并给一句话理由。只输出 JSON:{\"acc\":0,\"comp\":0,\"clarity\":0,\"reason\":\"\"}")
    r = client.chat.completions.create(
        model=JUDGE,
        messages=[{"role": "system", "content": sys},
                  {"role": "user", "content": f"题目:{prompt}\n回答:{answer}"}],
    )
    try:
        j = json.loads(re.search(r"\{.*\}", r.choices[0].message.content, re.S).group(0))
        return (j["acc"] + j["comp"] + j["clarity"]) / 15.0  # 归一化到 0-1
    except Exception:
        return 0.0

4.4 跑全流程,生成排行榜

board = {m: {"score": 0.0, "n": 0, "cost": 0, "latency": 0.0} for m in candidates}

for m in candidates:
    for t in tasks:
        ans, usage, dt = ask(m, t["prompt"])
        auto = auto_check(t["check"], ans)
        s = auto if auto is not None else judge_score(t["prompt"], ans)
        board[m]["score"] += s
        board[m]["n"] += 1
        board[m]["cost"] += (usage.completion_tokens or 0)
        board[m]["latency"] += dt

# 综合分 = 平均分;按分数降序排
ranking = sorted(
    ((m, round(v["score"] / v["n"], 3), v["cost"], round(v["latency"] / v["n"], 2))
     for m, v in board.items()),
    key=lambda x: x[1], reverse=True,
)

print(f"{'排名':<4}{'模型':<28}{'综合分':<8}{'用量(token)':<12}{'平均延迟(s)':<10}")
for i, (m, sc, c, lt) in enumerate(ranking, 1):
    print(f"{i:<4}{m:<28}{sc:<8}{c:<12}{lt:<10}")

跑完你会得到一张类似这样的表(数值为示意):

排名  模型                       综合分   用量(token)   平均延迟(s)
1     openai/gpt-5.5            0.91     1820         2.31
2     anthropic/claude-opus-4.8 0.89     2010         2.78
3     deepseek/deepseek-v4-pro  0.84     1540         1.96
...

五、进阶:按维度拆榜

综合分容易被「全能型」模型拉高,但很多团队只关心某一个场景。把 boarddim 分组统计,就能产出分场景榜单

from collections import defaultdict
by_dim = defaultdict(lambda: defaultdict(float))
for m in candidates:
    for t in tasks:
        ans, _, _ = ask(m, t["prompt"])
        auto = auto_check(t["check"], ans)
        s = auto if auto is not None else judge_score(t["prompt"], ans)
        by_dim[t["dim"]][m] += s

for dim, scores in by_dim.items():
    print(f"\n【{dim}榜】")
    for m, sc in sorted(scores.items(), key=lambda x: x[1], reverse=True):
        print(f"  {m:<28}{round(sc, 3)}")

这样你选型时就不是看一张总榜,而是「写代码看代码榜、做长文摘要看长文本榜」——更有指导意义。

六、小结

用聚合 API 做评测排行榜,优势很实在:

  • 一个接口跑全部候选:换 model 就换大脑,重排榜单只要改一行;
  • 裁判与候选同网关:LLM-as-judge 不用再单独接一家;
  • 覆盖广:Anthropic、OpenAI、Google、DeepSeek、阿里通义、月之暗面、智谱、MiniMax、百度等主流厂商通吃;
  • 有折扣:部分模型在平台上有折扣(如 Anthropic 系列低至 5 折),高频评测成本也压得住;
  • 可开票、官方货源、稳定,做公司级选型报告也站得住脚。

更多推荐