2026/10/12 16:21:03

Llama 3测试结果新鲜出炉,Llama 3位列第五,GTP-4-Turbo第一:用TaoToken统一Key复现LMSYS Elo榜单

Llama 3测试结果新鲜出炉,Llama 3位列第五,GTP-4-Turbo第一:用TaoToken统一Key复现LMSYS Elo榜单 1. 从 LMSYS 榜单说起Llama 3 第五、GPT-4-Turbo 第一到底怎么算出来的LMSYS Chatbot Arena 的榜单最近又更新了Llama 3 冲到了总榜第五前面是 GPT-4 的三个版本和 Claude 3 Opus而 GPT-4-Turbo 稳坐第一。很多人看到这个结果第一反应是「凭什么」第二反应是「我能不能自己跑一遍验证一下」。这篇就带你从 Elo 评分机制讲起然后用 TaoToken 的统一 Key 把多个模型接进来写一个最小可用的对战脚本亲手复现一轮榜单结论。先说清楚 LMSYS 的评测逻辑不然后面写代码会一头雾水。它和 MMLU、HumanEval 那种固定题库的 Benchmark 完全不同核心是「匿名对战 人工投票」。你在 Chatbot Arena 界面输入一个问题系统随机抽两个模型界面上只显示「模型 A」和「模型 B」你根本不知道背后是谁。两个模型各给一个回答你来判断哪个更好、还是平手、还是都不行。只有你投完票模型身份才会揭晓。这种设计的好处是避免了「品牌偏见」——如果告诉你这是 GPT-4你可能会不自觉地打高分。匿名之后投票结果相对更接近真实体验。LMSYS 目前收集了近 75 万轮有效对战覆盖 89 款模型Llama 3 参与了约 1.27 万次GPT-4 系列最多的一个版本参与了 6.8 万次。样本量差距这么大所以榜单用的是 Elo 而不是简单胜率。Elo 系统本来是国际象棋用来算棋手相对水平的。LMSYS 的做法是所有模型初始分设为 1000然后根据每场对战的预期胜率和实际结果来修正分数。预期胜率 E 由两个模型的当前分差决定实际得分 S 取 1赢、0输、0.5平。每场之后按R_new R_old K * (S - E)更新K 是调整系数。跑完所有有效数据就得到每个模型的 Elo 分。但原始 Elo 有个问题对战顺序会影响结果稳定性不够。LMSYS 团队后来用 Bootstrap 重复采样做了修正还给出了置信区间。所以你看到的榜单分数其实是统计修正后的结果不是简单累加。这也是为什么 Llama 3 只靠 70B 参数就能排到第五——它在英文单项里甚至和 GPT-4 打平反超了 GPT-4-0125 那个版本。理解了这套机制你就知道「复现榜单」不是要跑 75 万轮而是搭一个能匿名对战、能记录胜负、能算 Elo 的最小系统。下面我用 TaoToken 的统一 Key 来做因为它的 Base URL 兼容 OpenAI 格式一个 Key 就能调 GPT-4-Turbo、Claude 3、Llama 3 这些模型省得你去每个平台单独申请。2. TaoToken 前置准备统一 Key 怎么拿、Base URL 怎么填TaoToken 的核心价值是「一个 Key 调多家模型」接口协议兼容 OpenAI 的/v1/chat/completions所以你现有的 OpenAI SDK 代码基本不用改只换 Base URL 和 Key 就行。对我们要做的 Elo 对战脚本来说这意味着可以用同一套请求逻辑去调不同厂商的模型代码量大幅减少。第一步是拿 Key。打开官网 https://taotoken.net/?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_content 注册登录后进控制台在 API Keys 页面创建一个新 Key。建议给这个 Key 起个名字比如elo-arena-test方便后面区分。创建完立刻复制保存页面刷新后就不再完整显示了。第二步是确认 Base URL。TaoToken 的 API 地址是 https://taotoken.net/api 注意这里不带任何查询参数。如果你用的是 OpenAI 官方 SDKbase_url填https://taotoken.net/api/v1如果你用 requests 直接发 HTTP 请求完整端点就是https://taotoken.net/api/v1/chat/completions。这个/v1不能省否则会 404。第三步是确认你要调的模型 ID。TaoToken 的模型列表在控制台或者文档页能查到常见的包括gpt-4-turbo、gpt-4-1106-preview、claude-3-opus-20240229、llama-3-70b-instruct这些。注意模型 ID 要写全比如 Claude 3 Opus 的完整 ID 带日期后缀写错了会报 model not found。如果你用 Claude Code 或者 Cline 这类工具配置方式略有不同。Claude Code 需要设置环境变量ANTHROPIC_BASE_URL和ANTHROPIC_API_KEY但 TaoToken 的接口是 OpenAI 兼容格式所以更推荐用支持 OpenAI 协议的客户端。Cline 的话在设置里选「OpenAI Compatible」Base URL 填https://taotoken.net/api/v1API Key 填你的 TaoToken KeyModel ID 填你要用的模型。对于 Codex 类的工具配置文件通常在~/.codex/auth.json格式是这样的{ openai_api_key: sk-你的TaoTokenKey, base_url: https://taotoken.net/api/v1 }注意auth.json里的字段名可能是openai_api_key也可能是api_key取决于你用的具体工具版本。填完之后跑一个简单的codex chat测试一下能不能通。这里有个坑要提醒TaoToken 的 Key 是统一鉴权的但不同模型可能有不同的速率限制。你在做 Elo 对战的时候如果短时间内并发调多个模型可能会触发限流。建议在对战脚本里加个简单的 sleep或者用队列串行发请求。我实测下来串行跑 20 轮对战大概 3-5 分钟完全够用。另外TaoToken 的计费是按 token 算的不同模型单价不一样。GPT-4-Turbo 比 Llama 3 贵不少所以如果你要跑大量对战建议先用小样本测试脚本逻辑确认没问题再放大。控制台的用量页面可以实时看消耗。3. 可复制配置Base URL、Key、Model ID 三件套 对战脚本这一节给你可以直接复制粘贴的配置和代码。先明确三件套配置项值Base URLhttps://taotoken.net/api/v1API Key你在控制台创建的sk-开头的 KeyModel ID 示例gpt-4-turbo、claude-3-opus-20240229、llama-3-70b-instruct如果你用环境变量管理可以这样写.env文件TAOTOKEN_BASE_URLhttps://taotoken.net/api/v1 TAOTOKEN_API_KEYsk-你的Key然后 Python 脚本里用os.getenv读取。下面是对战脚本的核心部分我把它拆成「调模型」和「算 Elo」两块。先看调模型的函数import os import time import requests from typing import Optional BASE_URL os.getenv(TAOTOKEN_BASE_URL, https://taotoken.net/api/v1) API_KEY os.getenv(TAOTOKEN_API_KEY) def call_model(model_id: str, prompt: str, temperature: float 0.7) - Optional[str]: headers { Authorization: fBearer {API_KEY}, Content-Type: application/json } payload { model: model_id, messages: [{role: user, content: prompt}], temperature: temperature, max_tokens: 1024 } try: resp requests.post( f{BASE_URL}/chat/completions, headersheaders, jsonpayload, timeout60 ) resp.raise_for_status() data resp.json() return data[choices][0][message][content] except requests.exceptions.HTTPError as e: print(fHTTP error for {model_id}: {e.response.status_code} - {e.response.text}) return None except Exception as e: print(fError calling {model_id}: {e}) return None注意max_tokens设成 1024 是为了控制成本实际对战的时候回答太长反而不好比较。temperature用 0.7 是让回答有点变化但又不至于太离谱。然后是 Elo 计算部分import math def expected_score(r_a: float, r_b: float) - float: return 1 / (1 math.pow(10, (r_b - r_a) / 400)) def update_elo(r_a: float, r_b: float, score_a: float, k: float 32) - tuple: e_a expected_score(r_a, r_b) e_b 1 - e_a r_a_new r_a k * (score_a - e_a) r_b_new r_b k * ((1 - score_a) - e_b) return r_a_new, r_b_newscore_a取 1 表示 A 赢0 表示 B 赢0.5 表示平局。K 系数用 32 是常见默认值LMSYS 实际用的 K 可能更小但对我们小样本复现来说 32 够了。接下来是对战主循环。为了模拟匿名对战我们随机抽两个模型但投票环节没法真的找人所以这里用「裁判模型」来打分。你可以用一个强模型比如 GPT-4-Turbo 当裁判给它两个匿名回答让它判断哪个更好。这样虽然不如真人投票但能跑通流程。import random MODELS [ gpt-4-turbo, gpt-4-1106-preview, claude-3-opus-20240229, llama-3-70b-instruct ] def judge(question: str, answer_a: str, answer_b: str) - str: judge_prompt f你是一个公正的评测裁判。用户问题是{question} 模型A的回答{answer_a} 模型B的回答{answer_b} 请判断哪个回答更好只输出 A、B 或 tie。 result call_model(gpt-4-turbo, judge_prompt, temperature0.0) if result: result result.strip().upper() if A in result and B not in result: return A elif B in result and A not in result: return B return tie def run_battle(question: str, model_a: str, model_b: str) - str: ans_a call_model(model_a, question) ans_b call_model(model_b, question) if ans_a is None or ans_b is None: return tie # 随机交换位置消除位置偏见 if random.random() 0.5: verdict judge(question, ans_a, ans_b) return verdict else: verdict judge(question, ans_b, ans_a) if verdict A: return B elif verdict B: return A return tie注意这里做了位置交换因为裁判模型可能有「偏好第一个回答」的偏见。交换之后要把结果映射回来。最后是跑多轮对战并更新 Elodef main(): elo {m: 1000.0 for m in MODELS} questions [ 解释一下什么是 Transformer 的注意力机制, 用 Python 写一个快速排序, 为什么天空是蓝色的, 介绍一下量子纠缠, 如何优化 SQL 查询性能 ] rounds 20 for i in range(rounds): q random.choice(questions) a, b random.sample(MODELS, 2) result run_battle(q, a, b) if result A: score_a 1.0 elif result B: score_a 0.0 else: score_a 0.5 elo[a], elo[b] update_elo(elo[a], elo[b], score_a) print(fRound {i1}: {a} vs {b} - {result}, Elo: {a}{elo[a]:.1f}, {b}{elo[b]:.1f}) time.sleep(1) # 避免限流 print(\nFinal Elo:) for m, r in sorted(elo.items(), keylambda x: -x[1]): print(f{m}: {r:.1f}) if __name__ __main__: main()这个脚本跑 20 轮大概消耗几万 token成本可控。跑完之后你会得到一个自己的小榜单虽然样本量远不如 LMSYS但能验证「Llama 3 在英文任务上确实能和 GPT-4 掰手腕」这个结论。4. 验证请求跑通第一轮对战并检查返回结构配置写好了先别急着跑完整脚本。第一步是验证单个模型的请求能不能通。用 curl 发一个最小请求curl -X POST https://taotoken.net/api/v1/chat/completions \ -H Authorization: Bearer sk-你的Key \ -H Content-Type: application/json \ -d { model: llama-3-70b-instruct, messages: [{role: user, content: Say hello in one word.}], max_tokens: 10 }如果返回类似这样的结构说明通了{ id: chatcmpl-xxx, object: chat.completion, created: 1714000000, model: llama-3-70b-instruct, choices: [ { index: 0, message: { role: assistant, content: Hello }, finish_reason: stop } ], usage: { prompt_tokens: 12, completion_tokens: 2, total_tokens: 14 } }重点看choices[0].message.content有没有内容usage里的 token 数是否合理。如果content是空的可能是max_tokens设太小或者模型 ID 写错了。然后跑 Python 脚本的第一轮。建议先把rounds改成 1MODELS只留两个比如gpt-4-turbo和llama-3-70b-instruct。跑完看输出Round 1: gpt-4-turbo vs llama-3-70b-instruct - A, Elo: gpt-4-turbo1016.0, llama-3-70b-instruct984.0如果裁判判 GPT-4-Turbo 赢Elo 会往上涨Llama 3 往下降。这符合直觉。但一轮说明不了什么至少要跑 20 轮以上而且问题要多样化不能全是同一类。我实测下来裁判模型用 GPT-4-Turbo 的时候对代码类问题的判断比较准但对创意写作类问题有时候会给出「tie」。这其实也反映了 Elo 系统的一个特点平局也会影响分数只是影响比胜负小。跑完 20 轮后你可能会发现 Llama 3 的 Elo 没有想象中那么低。这是因为我们用的裁判模型本身也有偏好而且问题集太小。LMSYS 的 75 万轮对战之所以可信就是因为样本量大、投票人多、问题分布广。我们这个小脚本主要是验证流程不是真的去挑战官方榜单。如果你想更接近真实复现可以做两件事一是把问题集扩大到 100 条以上覆盖代码、数学、写作、知识问答等类别二是用多个裁判模型投票取多数结果。这样虽然还是不如真人但比单裁判稳定。还有一个细节LMSYS 只统计 battle 模式的匿名投票side-by-side 模式的结果不计入榜单。我们的脚本模拟的是 battle 模式但裁判知道自己在当裁判这跟真人匿名投票还是有区别。所以结论只能作为参考不能当成官方数据的替代。5. 常见报错排查401、local proxy failed、reading choices、OAuth跑脚本的过程中最容易遇到这几类报错我一个个说怎么排查。401 Unauthorized这是最常见的。先检查 Key 有没有复制完整sk-开头后面有没有多余空格。然后确认请求头是Authorization: Bearer sk-xxx不是Authorization: sk-xxx。如果 Key 没问题检查 Base URL 是不是写成了https://taotoken.net/api而漏了/v1。还有一种情况是 Key 被删了或者过期了去控制台重新创建一个。local proxy failed / connection refused这个报错通常出现在你本地设置了 HTTP 代理但代理没开或者配置不对。Python 的 requests 会读取HTTP_PROXY和HTTPS_PROXY环境变量。如果你不需要代理在脚本开头加import os os.environ.pop(HTTP_PROXY, None) os.environ.pop(HTTPS_PROXY, None)或者直接在 requests 里加proxies{http: None, https: None}。注意这里说的是本地网络配置问题不是让你去搞什么特殊网络工具就是单纯把不需要的代理设置清掉。reading choices 报错 / KeyError: choices这说明返回的 JSON 里没有choices字段。先打印完整的resp.text看看返回了什么。常见原因是模型 ID 写错了接口返回了错误信息而不是正常结果。比如你把llama-3-70b-instruct写成了llama3-70b就会报 model not found。另一个原因是max_tokens设成了 0 或者负数导致没有生成内容。还有一种可能是请求体里messages格式不对比如role写成了user以外的值。OAuth 相关报错如果你用 Claude Code 或者某些 CLI 工具可能会遇到 OAuth token 过期的问题。这类工具通常有自己的认证流程但如果你是通过 TaoToken 接入应该用 API Key 而不是 OAuth。检查一下工具的配置文件把认证方式改成 API Key。比如 Claude Code 的环境变量应该是ANTHROPIC_API_KEY而不是 OAuth token。如果工具强制要求 OAuth那就换一个支持 OpenAI 兼容接口的客户端比如 Cline 或者 Continue。429 Too Many Requests这是限流了。TaoToken 对不同模型有不同的 RPM 限制。解决办法是在每次请求之间加time.sleep(1)或者更长。如果并发量确实大可以考虑升级套餐或者错峰跑。超时 timeoutGPT-4-Turbo 和 Claude 3 Opus 这类大模型响应比较慢尤其是生成长文本的时候。把timeout从 60 秒调到 120 秒试试。如果还是超时检查一下你的网络到 TaoToken 的延迟可以用curl -w %{time_total}测一下。返回内容为空但没报错有时候finish_reason是length说明max_tokens太小内容被截断了。把max_tokens调大比如 2048。还有一种情况是模型返回了空字符串这可能是触发了内容安全策略换个问法试试。排查的时候记住一个原则先看 HTTP 状态码再看返回体最后看请求体。大部分问题出在请求体上——模型 ID、Key、Base URL 这三样检查一遍基本能解决 80% 的报错。6. 用统一 Key 把评测流程跑起来Elo 榜单看起来复杂但拆开就是「匿名对战 投票 统计算分」三步。LMSYS 用 75 万轮对战和 Bootstrap 修正把这件事做到了可信我们自己跑的时候不需要那么大规模重点是理解机制、跑通流程。TaoToken 在这个场景里的价值是省去了多平台注册和鉴权的麻烦。一个 Key、一个 Base URL就能在同一个脚本里调 GPT-4-Turbo、Claude 3 Opus、Llama 3 这些模型。你不需要为每个厂商写一套请求逻辑也不用管理多个 Key 的轮换。如果你想继续深入可以试试这几个方向把问题集换成你自己的业务数据看看在你的场景下哪个模型表现更好把裁判逻辑从单模型改成多模型投票减少偏见或者把 Elo 计算换成 Bradley-Terry 模型那个在统计上更严谨。代码和配置都在上面了复制过去改改 Key 就能跑。跑完记得去控制台看看用量别一不小心跑超了。