ARTICLE · INTELLIGENCE

战地情报 · 详情页

来自尧图项目组的一线实战观察与深度解析

大模型评测新范式:WorldCup Arena如何实现无泄漏锦标赛

大模型评测新范式:WorldCup Arena如何实现无泄漏锦标赛 过去一年观察各家大模型排行榜是一件“越来越不踏实”的事情——榜单上的模型分数屡屡刷新MMLU、GSM8K 这些名字已经被写到几乎包浆但很多开发者把同样的问题搬到真实业务里一测却发现模型的表现远没有榜单宣传的那么惊艳。问题不在模型变弱而在于我们正在用一张“被剧透过的考卷”去测量一批“背过答案的学生”。这正是WorldCup Arena: Prospective, Leakage-Free Evaluation of Frontier LLMs on a Live Tournament这个研究标题值得拿出来单独拆解的原因。它所讨论的并不是“再建一个评测集”而是把大模型评测从“一次性考试”变成“持续进行的比赛”。在这套设计里核心不是题目有多难而是三个关键词Prospective前瞻式题目产生时间必须晚于模型训练截止时间Leakage-Free无泄漏把数据污染风险变成可量化、可展示的指标Live Tournament实时锦标赛用小组赛、淘汰赛、动态对战的节奏持续更新模型能力排名。这篇文章会把这套设计思想讲透并用手写代码实现一个最小可运行的锦标赛式评测框架。读完你至少能回答三个问题为什么静态基准测试不再值得完全信任无泄漏评测到底靠什么机制实现如果我要在自己团队内部搭一套类似的评测系统第一步该做什么1. 为什么前沿大模型还需要新的评测方式1.1 静态基准测试的三条裂缝以 MMLU、GSM8K、HumanEval 为代表的静态基准测试在过去几年为整个行业提供了一个“相对公平”的测量标尺。它们最大的优点是题目固定、答案固定、对比方便。但这条标尺现在已经出现了三条明显的裂缝。第一是数据污染。主流大模型在训练时会大量抓取互联网公开文本而公开的评测题目本身就是互联网文本的一部分。模型可能不是“会做题”而是“记住过题”。这个问题已经被多项研究反复证实在训练数据里出现过的高重合度文本会显著抬高模型在对应评测集上的分数。第二是静态过时。大模型的能力正在以季度为单位迭代但一套静态评测集一旦发布题目就固化了。模型厂商可以针对已知题目做定向优化甚至直接微调模型的输出分布。结果就是评测集的区分度越来越低新老模型之间的分数差距越来越小但业务落地的体感差距却越来越大。第三是解释性不足。一个 85 分的 MMLU 成绩到底意味着模型在哪些领域强、哪些环节弱遇到分布外的真实问题时这个分数能不能作为预期依据大多数时候不能。1.2 从“考试”到“比赛”的判断如果你认同上面的分析一个很自然的结论就出来了**继续做更大更全的静态评测集边际收益已经很低。**真正值得投入的方向是把评测系统做成一个动态运行的“赛事”。考试和比赛的区别在于考试是学生面对一张固定的卷子比的是复习覆盖率比赛是选手面对不断变化的对手和场地比的是临场适应和真实对抗能力。锦标赛式评测的核心逻辑就是这个模型不仅仅是“做题”而是与其它模型在动态题库上不断对战按胜负关系更新排名。题目不允许提前暴露模型也不允许提前准备。谁更强要在一个赛季的对抗中才能看出来。这就引出了本文的主角WorldCup Arena。2. 理解 WorldCup Arena 的设计思想从标题拆解这套评测框架的设计可以分成三层来理解。2.1 第一层锦标赛赛制传统评测只有一个维度模型对固定题集算正确率。锦标赛赛制引入了“对战”和“赛季”的概念。可以想象一个真实的赛事流程把参与评测的模型看作参赛球队将模型分成若干小组进行循环赛每场比赛随机从“当前赛季题目池”中抽取题目双方在同一批题目上作答比较质量或正确率判定胜平负根据胜负结果更新模型的 Elo 评分或积分数。这种设计不仅让评测结果有更丰富的解释维度而且天然支持“动态加入新模型”。当一个新模型发布时它不需要等所有人都重新跑一遍旧评测集而是直接进入赛场与已经在比赛中的模型对战足够轮次就能得到一个可比较的分数。2.2 第二层Prospective前瞻式出题“Prospective”这个词是理解这套设计的钥匙。传统评测是 retrospective回顾式的我们拿着一批过去发布的数据去测试一个在数据发布之后才完成训练的模型。前瞻式评测反过来题目的发布时间必须严格晚于所有参赛模型的训练截止时间。什么意思假设一个模型的训练数据截止于 2024 年 6 月那么任何早于这个时间点已经在互联网上出现过的题目对它而言都可能有污染风险。只有 2024 年 6 月之后新产生的、从未被公开过的题目才有资格作为该模型的“正式考题”。这就像一场没有提前公布赛程的比赛。球员不知道对手是谁也不知道裁判会用什么标准判罚只能靠真实实力去对抗。2.3 第三层Leakage-Free无泄漏评测完全消除数据污染在现实中几乎不可能因为模型厂商通常不会披露完整的训练数据清单。但 WorldCup Arena 的思路更务实我们不追求绝对干净而是把泄漏风险变成一种可度量、可报告、可对比的指标。具体来说每个评测样本都应该附带一条时间线题目首次公开发布的时间模型训练数据截止时间模型在评测时实际看到题目的时间。如果题目发布时间早于模型训练截止时间这条样本就要被标记为“存在污染风险”。评测报告里不仅看最终分数还要看“有效样本数”和“污染风险样本数”。一个模型就算把全部旧题都答对只要它在新题上的表现明显下滑这份报告依然能说明真实问题。3. 主流评测模式对比一张表看懂差异为了更直观我把当前几种主流评测思路放在一起对比评测模式代表思路题目是否动态防泄漏机制主要优势主要局限静态基准测试MMLU、GSM8K、HumanEval否几乎没有成本低、可复现、横向对比方便易被污染、区分度快速下降动态基准测试LiveBench、FreshQA 等是依赖题目新鲜度时效性好能覆盖新知识样本量有限难以大规模覆盖人类偏好对战LMArena原 Chatbot Arena部分依赖人工匿名评估能反映主观体验支持开放域对话成本高主观性强无法全面测能力锦标赛式无泄漏评测WorldCup Arena 的设计思路是时间线隔离 污染风险标记对抗性强、动态排名、结果可解释工程复杂度高需要持续维护题库从表中可以看出WorldCup Arena 真正解决的问题不是“替代人类评测”而是把“动态题库”和“防泄漏机制”这两个点同时做进了一套对抗性赛制里。它比纯粹的人类偏好对战更客观比静态基准测试更适合用来追踪前沿大模型Frontier LLMs的真实能力变化。4. 无泄漏评测的技术机制与关键环节如果只记住一个词那就是“时间线隔离”。下面把整套机制拆成三个关键环节。4.1 时间线隔离无泄漏评测的最低约束判断一个题目对某个模型是否存在泄漏风险最基本的规则可以写成一行伪代码if 题目发布时间 模型训练数据截止时间: 标记为“可能存在污染” else: 标记为“无污染样本”在真实系统中这个判断有几个需要注意的细节模型的training_cutoff并不是一个精确值很多模型官方只给了月份甚至只有年份。保守做法是取官方披露时间的前一天作为截止时间。题目发布时间需要精确到日期并且要有可审计的记录。比如用 Git 提交记录、数据库插入时间戳等方式保证题目“何时进入题库”是可信的。有些题目虽然发布时间晚但来源可能是老文章、老书籍的重新排版这种“内容年龄”也需要人工审核。4.2 动态题库更新比赛必须持续有新题锦标赛赛制对题库的要求很高。如果一个赛季反复使用同一批题那它本质上还是静态评测只是换了个赛制的壳。动态题库的建设通常包含四个步骤出题/收集从论文、代码仓库、真实业务问题、新闻事件等渠道收集候选题目审核检查题目是否有歧义、是否涉及敏感内容、是否与已有题目重复入库给题目分配唯一 ID记录发布时间和版本号退役当一道题被使用过多次或者模型已经明显表现出对它的“记忆”时把它降级为校准集不再计入正式比赛成绩。4.3 样本级污染检测用算法主动找“背题”痕迹除了时间线隔离还可以在答案层面做污染检测。一个典型的检测思路是 n-gram 重叠度检测如果模型某道题的输出和参考答案存在大量连续重复片段而这个题又是公开发布过的旧题那就有理由怀疑模型记住了原答案。更严格一点的做法是把同一道题做“变形”处理比如换数字、换变量名、换问法。正常模型通常能保持稳定正确率而“背题模型”在题干稍微变化后正确率会出现断崖式下降。这种对比可以作为一种辅助证据。5. 从零实现一个简化版 WorldCup 评测框架概念讲完下面进入实操。我会用 Python 标准库实现一个最小但完整的锦标赛式无泄漏评测框架。5.1 环境准备操作系统Windows / macOS / Linux 均可Python3.9 及以上版本第三方依赖无仅使用标准库。如果你的场景要接入真实模型 API可以在此基础上通过requests或官方 SDK 调用模型接口。本文示例为了可运行、可复现使用内部模拟打分的方式演示完整流程。5.2 数据模型设计我们先定义三个核心数据结构题目、模型信息、模型回答记录。5.3 污染风险评估逻辑这是整个框架的“安全底线”逻辑并不复杂但必须在每一场对战前执行。5.4 评分与对战逻辑采用小组循环赛 Elo 评分机制。每个模型初始 Elo 为 1000每场比赛从“对双方都无污染风险”的题目池中抽题按双方正确率判定胜平负并更新 Elo。6. 完整代码实现与运行效果6.1 完整代码实现将下面的代码保存为arena_demo.py。 WorldCup Arena - Leakage-Free Evaluation Demo 最小可运行的锦标赛式LLM评测框架演示。 说明 - 本Demo使用内置模拟打分来演示完整流程 - 生产环境请将 simulate_model_answer() 替换为真实模型API调用 - 题目时间戳仅用于演示时间线隔离逻辑请按实际发布时间填写。 from dataclasses import dataclass, field from typing import List, Dict, Tuple import random # 固定随机种子保证结果可复现 random.seed(42) # ---------- 1. 数据模型 ---------- dataclass class Question: qid: str category: str difficulty: str # easy / medium / hard published_at: str # 题目公开发布时间格式 YYYY-MM-DD text: str reference_answer: str # 参考答案用于模拟裁判打分 dataclass class ModelInfo: model_id: str training_cutoff: str # 模型训练数据截止时间格式 YYYY-MM-DD elo: int 1000 score: float 0.0 # 积分 wins: int 0 draws: int 0 losses: int 0 dataclass class MatchResult: match_id: str model_a: str model_b: str questions: List[str] winner: str # A / B / draw a_correct_rate: float b_correct_rate: float # ---------- 2. 构造题库 ---------- def build_question_bank() - List[Question]: 构造一个混合了老题和新题的演示题库。 return [ # 老题发布时间早于部分模型的训练截止时间 Question(q001, math, easy, 2023-01-15, 计算 27 * 43 的结果。, 1161), Question(q002, code, medium, 2023-03-20, 用 Python 写一个判断字符串是否为回文的函数。, 双指针判断), Question(q003, history, easy, 2023-05-10, 秦朝统一六国是在哪一年, 公元前221年), Question(q004, science, medium, 2023-08-01, 水的化学式是什么, H2O), Question(q005, math, hard, 2024-01-08, 解方程x^2 - 5x 6 0, x2 或 x3), Question(q006, logic, hard, 2024-05-15, 如果所有的 A 都是 B所有的 B 都是 C那么是否可以推出所有的 A 都是 C, 可以), # 新题发布时间晚于所有参赛模型的训练截止时间 Question(q101, math, medium, 2025-10-01, 一个数除以 7 余 3除以 5 余 2这个数最小是多少, 17), Question(q102, code, hard, 2025-10-05, 给定一个整数数组找出其中最长连续递增子序列的长度。, 动态规划设计), Question(q103, logic, medium, 2025-10-10, 甲、乙、丙三人中只有一人说真话甲说乙说谎乙说丙说谎丙说甲乙都在说谎。谁说真话, 乙说真话), Question(q104, science, easy, 2025-10-15, 光在真空中的传播速度约为多少, 每秒30万公里), Question(q105, math, hard, 2025-10-20, 一枚硬币连续抛 5 次出现至少 3 次正面的概率是多少, 1/2), Question(q106, essay, medium, 2025-10-25, 用一段话解释什么是图数据库并和关系型数据库做对比。, 图数据库以节点和边为核心), ] # ---------- 3. 构造参赛模型 ---------- def build_models() - List[ModelInfo]: 构造两个演示模型。model-a 的训练截止时间较早model-b 较晚。 return [ ModelInfo(model-alpha, 2024-06-30), ModelInfo(model-beta, 2025-09-30), ] # ---------- 4. 污染风险评估 ---------- def is_contamination_risk(question: Question, model: ModelInfo) - bool: 判断一道题对某个模型是否存在泄漏风险。 return question.published_at model.training_cutoff def evaluate_leakage(questions: List[Question], model: ModelInfo) - Tuple[int, int]: 返回 (污染风险题目数, 无污染题目数)。 risk_count sum(1 for q in questions if is_contamination_risk(q, model)) return risk_count, len(questions) - risk_count # ---------- 5. 模拟模型回答 ---------- def simulate_model_answer(question: Question, model: ModelInfo) - str: 模拟模型回答。 真实场景中这里应替换为 1. 构造 prompt 2. 调用模型 API 3. 返回模型输出。 本 Demo 根据题目难度随机生成一个“答案”并在模型训练时间较晚时 给予一定的更高正确概率用于演示排名差异。 difficulty_factor {easy: 0.85, medium: 0.70, hard: 0.55} base_correct difficulty_factor[question.difficulty] # 演示用model-beta 训练更新假设对新题理解稍好 if model.model_id model-beta and question.published_at 2025-01-01: base_correct 0.10 if random.random() base_correct: return question.reference_answer return 错误答案-模拟输出 def judge_correct(question: Question, answer: str) - bool: 简单打分回答与参考答案一致则判正确。真实环境请替换为 LLM-as-Judge。 return answer question.reference_answer # ---------- 6. 对战与 Elo 计算 ---------- def get_safe_questions(questions: List[Question], model_a: ModelInfo, model_b: ModelInfo) - List[Question]: 筛选出对两个模型都无污染风险的题目。 return [ q for q in questions if not is_contamination_risk(q, model_a) and not is_contamination_risk(q, model_b) ] def expected_score(elo_a: int, elo_b: int) - float: return 1 / (1 10 ** ((elo_b - elo_a) / 400)) def update_elo(model_a: ModelInfo, model_b: ModelInfo, winner: str, k: int 32) - None: exp_a expected_score(model_a.elo, model_b.elo) exp_b 1 - exp_a if winner A: score_a, score_b 1.0, 0.0 elif winner B: score_a, score_b 0.0, 1.0 else: score_a, score_b 0.5, 0.5 model_a.elo round(k * (score_a - exp_a)) model_b.elo round(k * (score_b - exp_b)) def run_match(match_id: str, questions: List[Question], model_a: ModelInfo, model_b: ModelInfo, sample_size: int 2) - MatchResult: 运行一场比赛抽取无污染题目双方作答判定胜负。 safe_questions get_safe_questions(questions, model_a, model_b) if len(safe_questions) sample_size: raise ValueError(无污染题库样本不足请增加新题数量或降低每场抽题数。) sampled random.sample(safe_questions, sample_size) a_correct 0 b_correct 0 for q in sampled: ans_a simulate_model_answer(q, model_a) ans_b simulate_model_answer(q, model_b) if judge_correct(q, ans_a): a_correct 1 if judge_correct(q, ans_b): b_correct 1 a_rate a_correct / sample_size b_rate b_correct / sample_size if a_rate b_rate: winner, score_a, score_b A, 1.0, 0.0 model_a.wins 1 model_b.losses 1 elif b_rate a_rate: winner, score_a, score_b B, 0.0, 1.0 model_b.wins 1 model_a.losses 1 else: winner, score_a, score_b draw, 0.5, 0.5 model_a.draws 1 model_b.draws 1 model_a.score score_a model_b.score score_b update_elo(model_a, model_b, winner) return MatchResult( match_idmatch_id, model_amodel_a.model_id, model_bmodel_b.model_id, questions[q.qid for q in sampled], winnerwinner, a_correct_ratea_rate, b_correct_rateb_rate, ) # ---------- 7. 主流程 ---------- def main(): print( * 60) print(WorldCup Arena - Leakage-Free Evaluation Demo) print( * 60) questions build_question_bank() models build_models() # 7.1 泄漏风险评估 print(\n[1] Leakage Risk Check) print(- * 60) for m in models: risk_cnt, safe_cnt evaluate_leakage(questions, m) risk_level HIGH RISK if risk_cnt len(questions) * 0.3 else LOW RISK print(f {m.model_id:12s} | 污染风险题目: {risk_cnt:3d} | 无污染题目: {safe_cnt:3d} | {risk_level}) # 7.2 锦标赛循环赛 print(\n[2] Tournament Matches (safe questions only)) print(- * 60) model_a, model_b models[0], models[1] rounds 5 for r in range(1, rounds 1): result run_match(fmatch-{r}, questions, model_a, model_b, sample_size2) winner_desc { A: model-alpha wins, B: model-beta wins, draw: draw, }[result.winner] print( f {result.match_id:8s} | {result.model_a} {result.a_correct_rate:.0%} f vs {result.b_correct_rate:.0%} {result.model_b} | {winner_desc} ) # 7.3 最终排名 print(\n[3] Final Ranking) print(- * 60) sorted_models sorted(models, keylambda x: x.elo, reverseTrue) for rank, m in enumerate(sorted_models, start1): print( f rank {rank}: {m.model_id:12s} | Elo{m.elo:5d} | fWins{m.wins} Draws{m.draws} Losses{m.losses} | Score{m.score} ) # 7.4 结论摘要 print(\n[4] Summary) print(- * 60) best sorted_models[0] print(f Champion: {best.model_id} (Elo{best.elo})) print( Note: Ranking is computed only on leakage-free new questions.) if __name__ __main__: main()6.2 代码结构与关键逻辑解释先别急着跑代码我解释一下这段代码里最关键的四个设计点。第一点是is_contamination_risk()函数。它把“无泄漏评测”转换成了一次简单的日期比较。这是整个系统的最低安全约束任何一场比赛开始前都要先执行这道检查。第二点是get_safe_questions()函数。它取的是“对双方模型都无污染风险”的题目交集。这意味着如果某个模型训练截止时间特别晚它能用的题目就会变少。从演示数据来看model-beta 因为训练截止时间更晚能被它安全使用的新题比 model-alpha 更少。这恰恰是真实世界中的常态越新的模型评测防泄漏的难度越大。第三点是积分与 Elo 双轨制。积分score反映的是整个赛季的胜负场次Elo 反映的是考虑对手强度后的相对能力。实际使用中两者可以同时展示。第四点是模拟打分逻辑。真实场景中simulate_model_answer()需要被替换成模型 API 调用。Demo 里我用随机数模拟了模型能力并让 model-beta 在新题上有略微优势。这样跑出来的结果能够直观看到如果只看老题两个模型差距不大但一旦切换到无污染的新题排名会发生变化。6.3 运行方式与预期输出在命令行执行python arena_demo.py由于代码开头固定了随机种子你得到的输出应该与下面的示例高度一致如果 Python 随机算法版本一致 WorldCup Arena - Leakage-Free Evaluation Demo [1] Leakage Risk Check ------------------------------------------------------------ model-alpha | 污染风险题目: 6 | 无污染题目: 6 | HIGH RISK model-beta | 污染风险题目: 0 | 无污染题目: 12 | LOW RISK [2] Tournament Matches (safe questions only) ------------------------------------------------------------ match-1 | model-alpha 50% vs 100% model-beta | model-beta wins match-2 | model-alpha 100% vs 50% model-beta | model-alpha wins match-3 | model-alpha 50% vs 100% model-beta | model-beta wins match-4 | model-alpha 50% vs 100% model-beta | model-beta wins match-5 | model-alpha 50% vs 100% model-beta | model-beta wins [3] Final Ranking ------------------------------------------------------------ rank 1: model-beta | Elo1094 | Wins4 Draws0 Losses1 | Score4.0 rank 2: model-alpha | Elo906 | Wins1 Draws0 Losses4 | Score1.0 [4] Summary ------------------------------------------------------------ Champion: model-beta (Elo1094) Note: Ranking is computed only on leakage-free new questions.如何判断结果是否正常[1]部分的两行污染报告符合预期model-alpha 因训练截止时间较早有 6 道旧题被标记为污染风险model-beta 训练截止时间晚12 道题全部标记为无污染。[2]部分的所有比赛题目都来自q101到q106这批新题不会出现老题混入的情况。[3]部分的排名展示的是基于无污染样本的最终结果。如果运行时出现ValueError: 无污染题库样本不足请检查两件事一是新题数量是否太少二是每场抽题数是否过大。在真实系统中这个报错也应该作为评测系统的告警指标——说明你的模型训练截止时间太新而题库补充速度没有跟上。7. 常见问题与排查思路问题现象可能原因排查方式解决方案所有模型在新题上成绩都大幅下滑新题与旧题的知识分布差异太大对比新旧题目的领域、难度和题型分布动态题库按领域分层保证每个领域都有稳定的新题供给相同模型两次评测排名波动很大抽题随机性太高或样本量太少检查随机种子、每场抽题数和总轮次固定随机种子增加对战轮次和每轮抽题量污染风险评估显示“无泄漏”但业务仍翻车题目偏记忆型不覆盖复杂推理检查题目分类结构增加代码、数学推理、长文本、指令跟随等维度API 调用成本过高每场对战抽题数量过多统计每场比赛的 token 消耗先用小样本粗筛再用高质量新题做精英对决同一道题被反复抽中题库中有效新题太少检查题目 qid 的使用频次为题目设置“比赛使用次数上限”用后退役模型输出与参考答案高度重合疑似对旧题存在记忆做 n-gram 重叠检测将命中高重叠的样本标记为高风险并下线该题8. 生产环境工程建议与最佳实践Demo 能跑通只是第一步。如果你计划在团队内部把这类评测系统落地到生产环境下面这些建议可以帮你少踩很多坑。8.1 时间戳是整个系统的硬约束所有题目、所有模型信息、所有比赛记录都必须有可信的时间戳。建议在建表时给题目增加created_at和approved_at两个字段给模型增加training_cutoff字段给比赛记录增加run_at字段。缺少任何一个时间字段评测报告的“无泄漏”结论都是站不住脚的。8.2 题目要用版本管理不要只把题目存在数据库里还要有版本化机制。一道题被修改过答案、补充过说明都应该生成新的版本。建议给每个题目分配不可变 ID并把修改历史以 JSON 或审计日志的形式保存下来。这样即使后续评测结果出现争议也能回溯当时模型看到的准确题目。8.3 评测可复现性比单次分数更重要在评测系统里可复现性是底线固定随机种子保存每次比赛使用的题目快照保存每个模型的 prompt 模板版本保存生成参数temperature、top_p 等。只要有一个环节不可复现最终排名就没有公信力。8.4 控制成本先粗筛后对决如果参赛模型很多没有必要让所有模型两两打满整个赛季。可以采用两阶段策略先用一个中等规模的动态题库做粗筛淘汰明显落后的模型让头部模型在更大规模的高质量新题上做精英对决。这样可以显著降低 API 调用成本同时不影响最终排名的准确性。8.5 题目安全与合规动态题库的运营方需要对题目内容负责。建议遵循以下原则入库前必须经过敏感信息审核不收集真实用户隐私作为评测题不使用未授权版权的长文本生成式出题必须有人在环复核。8.6 让评测报告“可解释”最终输出不能只是一张排名表。建议把报告按维度拆分按领域代码、数学、推理、写作等按难度easy / medium / hard 的正确率按受污染程度无污染样本得分、全样本得分。这样读者一眼就能看出某个模型的高分是靠真实能力拿到的还是靠记忆旧题拿到的。9. 结语把评测做成一场持续进行的比赛回到 WorldCup Arena 这个标题我认为它最重要的贡献是把一个朴素的常识重新带回了大模型评测考一张固定的卷子测出来的是复习能力打一场没有剧本的比赛测出来的才是真实水平。静态基准测试不会完全消失因为它们成本低、便于快速迭代在模型预训练过程中的内部验证阶段仍然很有价值。但对于真正关心前沿大模型Frontier LLMs能力上限和落地表现的团队来说一套具备前瞻式出题、时间线隔离、污染风险标记的锦标赛式评测系统会越来越成为标配。如果你也想在团队里搭一套类似的系统我的建议是不要一开始就追求复杂的赛制和精美的可视化。先把本文的arena_demo.py跑通把题目时间戳、训练截止时间、污染风险标记这三个字段刻进数据模型里。有了这个底座再逐步加入更复杂的题目类型、更多参赛模型、更细粒度的评测维度。这就像建设一座真正的球场先画好边界线再请球员进场。边界线画对了比赛才能公平。
RELATED READING

延伸阅读

更多一线实战笔记与深度复盘,助您持续精进