公司动态
大模型能力体检:用自建评测集识别AI虚假繁荣
这两年做 AI 应用开发一个越来越强烈的感受是很多“看起来很强”的 AI 产品经不起一次可复现的评估。演示片里什么都能完成一旦接到真实业务场景问题就集中暴露出来回答不稳定、逻辑断链、稍微换个问法就失败甚至连基本的评测集都过不了。这篇内容会以工程视角拆解“AI 虚假繁荣”到底来自哪里并给出一个可以自己运行的大模型能力体检方案帮助你判断一个模型、一个 Agent 项目或一个 AI 应用究竟是真实有效还是只有“展示效果”。文章适合正在做 AI 应用开发、模型选型、Agent 落地的同学阅读。你不一定需要很深的机器学习基础但需要有 Python 环境和一点点命令行操作经验。读完你会掌握一套可复现的评估思路自建评测集、调用模型、记录输出、分析失败案例并最终用工程方法过滤掉那些“虚火”信号。1. AI 虚假繁荣到底是什么从现象到本质1.1 两种繁荣怎么区分先区分一个概念真实繁荣和虚假繁荣并不是“技术有没有价值”的对立而是“反馈闭环是否完整”的对立。真实繁荣通常表现为模型能力提升推理成本下降评估指标稳定应用在线上能跑通并且带来可量化的业务收益。整个过程存在完整反馈模型上线采集数据人工标注发现问题再迭代。就算某个环节不够好至少团队能看到真实数据在指导下一步方向。虚假繁荣则更倾向于优化“高光时刻”的可见性。比如一个演示视频里模型流畅地完成了一套复杂任务但视频剪掉了中间 3 次失败重试又比如一个模型在公开榜单上排名靠前但在你自建的业务评测集上表现平平再比如一个“AI Agent”产品看似自主规划实际每一步都由预设脚本控制模型只在中间做了一次关键词匹配。我不会直接否定这些现象因为有些能力确实还在进步。但从工程角度看如果“表现好”不能被复现、不能被归因、不能被评估那它顶多算“展示效果”还不足以支撑技术选型或业务决策。1.2 虚假繁荣的典型来源根据我观察到的项目案例虚假繁荣通常有几类来源第一类是评测集泄漏。模型在预训练阶段见过测试集中的题目于是分数高得离谱。很多公开榜单只能作为参考不能直接当成业务选型的唯一依据。第二类是演示视频和成功案例的剪裁。给投资人、给领导看的时候往往会挑表现最好的 3 个结果失败案例不会被放进同一个视频里。这是商业展示的正常行为但如果团队内部也把这种“最好结果”当成真实能力就会产生误判。第三类是“包壳式”AI 应用。产品外面套了 AI 外壳里面实际是规则匹配、数据库查询甚至有人在后台人工回答。这种做法不一定没有商业价值但如果它假装成纯 AI 能力就会误导技术评估。第四类是 Agent 演示脚本化。所谓 AI Agent 在演示环境里“自主规划”实际上每一步的候选动作已经被固定好了模型只是选择了路线 A 或路线 B。这种项目学习价值很高但离真正的通用智能体差距明显。第五类是榜单刷分和参赛刷题。公开榜单是评估的辅助工具不是目标的替代品。当所有团队都针对同一个测试集优化时分数的含金量就会越来越低。你看这些来源有一个共同点它们都在优化“外在指标”而不是优化“业务问题”。1.3 为什么开发者更容易被误导普通开发者不是不想验证而是验证成本常常被低估。对一个中小团队来说搭一个可靠的评估环境需要时间需要数据需要标注还需要跑很多次实验。相比之下看一个现成的榜单或 Demo 视频成本最低所以最容易形成依赖。还有一个原因是大模型 API 更新很快同一个模型在不同日期、不同参数下输出差异很大。如果团队不固定版本、不固定推理参数、不记录输入输出那么前一次评测的有效性会迅速下降。你很难说清楚模型到底进步了还是仅仅因为这次运气好。更隐蔽的一点是一旦团队已经对外展示了“宣传口径”内部就容易为了维持一致性而忽略坏消息。哪怕有人发现评估结果并不好也会先怀疑自己的测试方法有问题而不是怀疑宣传结论有问题。这就是工程上需要“用数据代替感觉”的原因。2. 识别前需要准备什么最小评估环境2.1 运行环境我们需要一个能够调用大模型 API 的 Python 环境。常见组合是Python 3.9 及以上版本openaiPython SDK或者任何兼容 OpenAI 接口的 SDK本地模型服务比如 Ollama、vLLM也可以直接使用云端 API一个用于存放评测集和结果的目录版本不是越新越好关键是保持固定。以 OpenAI SDK 为例不同大版本之间接口可能有变化下面代码基于openai1.0.0的接口风格如果你的版本不同需要按实际情况调整。# requirements.txt openai1.0.0这里不引入 pandas 这样的重依赖因为评测逻辑并不复杂用标准库写起来更轻量也更容易被别人复用。2.2 本地模型 vs 云 API在评估 AI 能力时本地模型和云 API 各有优缺点。本地部署的好处是隐私可控、离线可用、请求日志完整适合私有数据评测。通过 Ollama 或 vLLM 启动服务后可以用base_url指向本地地址把模型标识换成你拉取的具体模型名称。云 API 的好处是接入简单、模型规格丰富、不需要自己维护 GPU 服务但缺点是模型版本可能被服务方更新导致同一个model名称背后的权重、参数量、微调策略发生变化。为了应对这种不确定性每次评测时都要记录请求时间、模型名称、请求参数以及可用的模型版本信息。2.3 为什么需要自建评测集公开榜单有参考价值但它回答不了“这个模型能帮我解决业务问题吗”。真实业务场景里的问题往往带有很多领域术语、格式要求、边界条件这些在公开测试集里不一定覆盖。自建评测集的核心价值是可归因。你可以准确说明每个测试用例的来源、预期答案、修改时间。当模型表现变化时你能定位是哪一类问题变好了哪一类问题变差了而不是笼统地说“模型能力提升了”。自建评测集不需要一开始就很大20 条高质量用例就比 1 万条无来源的噪声数据更有用。关键在于持续维护和版本管理。3. 用代码给大模型做“能力体检”3.1 模型调用通用函数先写一个通用的模型调用函数。它的作用是接收一个问题和参数返回模型生成的文本同时把错误信息抛出来方便我们记录。# src/client_utils.py from openai import OpenAI def create_client(base_url: str, api_key: str) - OpenAI: 创建 OpenAI 兼容客户端。 如果使用本地 Ollamabase_url 通常是 http://localhost:11434/v1 如果使用 vLLMbase_url 通常是你自己启动的服务地址。 return OpenAI(base_urlbase_url, api_keyapi_key) def ask_model(client: OpenAI, model: str, prompt: str, temperature: float 0.2, max_tokens: int 512) - str: 调用 chat 接口并返回模型回答文本。 response client.chat.completions.create( modelmodel, messages[ {role: user, content: prompt} ], temperaturetemperature, max_tokensmax_tokens, ) return response.choices[0].message.content.strip()关键参数说明temperature0.2控制随机性。用于评测时建议调低让输出更稳定。max_tokens512限制输出长度避免过长的回答影响后续判断。base_url和api_key根据服务来源设置。本地服务通常不校验 key但结构上仍然保留。3.2 设计能反映“真实能力”的 Prompt 模板在实际业务中问题往往不是一句简单的话而是带有任务约束的。比如“请从以下文本中提取客户名称只输出名称”和“这段文本里有什么重要信息”两种问法带来的难度完全不同。因此评测用例里最好既包含原始问题也包含任务约束。下面是一个可以复用的模板# src/prompt_template.py SYSTEM_PROMPT 你是一个严谨的评估助手。请根据用户的问题给出准确、简洁的回答。 def build_question(case: dict) - str: 根据评测用例生成发送给模型的问题。 if case.get(instruction): return f{case[instruction]}\n\n问题{case[question]} return case[question]在评测集中增加instruction字段可以更贴近真实业务。比如对代码解释类问题指令是“用中文回答”对事实判断类问题指令是“只回答对或不对”。3.3 逐条评测并记录结果接下来编写一个循环评测脚本。它会读取 JSON 评测集逐条调用模型把回答、是否通过、耗时写入 CSV 文件。这类记录是后面做对比分析的基础。# src/evaluator.py import argparse import csv import json import time from client_utils import create_client, ask_model def judge(pred: str, expected: str) - bool: 简单判断预测文本是否包含期望答案。 注意这只是演示用判断逻辑实际项目需要按题型扩展。 if not pred: return False expected expected.strip() pred pred.strip() return expected in pred or pred in expected def run_eval(config_path, model, base_url, api_key, output_path): client create_client(base_url, api_key) cases json.load(open(config_path, encodingutf-8)) with open(output_path, w, newline, encodingutf-8) as f: writer csv.writer(f) writer.writerow([ case_id, type, question, expected, prediction, pass, latency ]) for case in cases: question case[question] expected case[expected] start time.time() try: pred ask_model(client, model, question) passed judge(pred, expected) except Exception as exc: pred fERROR: {exc} passed False latency round(time.time() - start, 2) writer.writerow([ case[id], case[type], question, expected, pred, passed, latency ]) print(f{case[id]} - {PASS if passed else FAIL} | {latency}s) print(f评测结果已写入 {output_path}) if __name__ __main__: parser argparse.ArgumentParser(description大模型能力体检脚本) parser.add_argument(--config, defaultdata/eval_cases.json) parser.add_argument(--model, defaultqwen2.5:7b) parser.add_argument(--base-url, defaulthttp://localhost:11434/v1) parser.add_argument(--api-key, defaultnot-needed) parser.add_argument(--output, defaultresults/result.csv) args parser.parse_args() run_eval( config_pathargs.config, modelargs.model, base_urlargs.base_url, api_keyargs.api_key, output_pathargs.output, )这段代码的核心不是“能跑”而是把每次评测的上下文保存下来。之后无论模型怎么更新、Prompt 怎么调整你都能回到历史结果里找原因。4. 实战案例给模型做一次“健康检查”4.1 创建项目结构建议把评测工程化而不是随手写一个脚本。我这里使用的目录结构如下ai-health-check/ ├── data/ │ └── eval_cases.json ├── src/ │ ├── client_utils.py │ ├── prompt_template.py │ └── evaluator.py ├── results/ │ └── result.csv └── requirements.txtdata目录放评测集src目录放代码results目录放每次评测结果。这样可以避免把数据和代码混在一起。4.2 准备一份评测集下面是一份演示用评测集覆盖数学、逻辑、常识、代码、事实判定和文本抽取等类型。你可以直接复制也可以替换成自己业务里的真实问题。[ { id: case_001, type: math, instruction: 请只输出最终答案不要写计算过程。, question: 一辆汽车从A地到B地全程120公里。去程速度60公里/小时返程速度40公里/小时。请问往返全程的平均速度是多少公里/小时, expected: 48 }, { id: case_002, type: logic, instruction: 请只输出星期几。, question: 如果今天是星期三那么100天后是星期几, expected: 星期五 }, { id: case_003, type: history, instruction: 请按时间先后排序四个朝代之间用顿号分隔。, question: 请按时间先后给下面四个朝代排序唐、秦、宋、汉。, expected: 秦、汉、唐、宋 }, { id: case_004, type: code, instruction: 请用简洁中文解释。, question: Python 中列表(list)和元组(tuple)最核心的区别是什么, expected: 元组是不可变 }, { id: case_005, type: fact, instruction: 请只回答“对”或“不对”。, question: “太阳从西边升起。”这句话描述的是可能发生的事件对吗, expected: 不对 }, { id: case_006, type: logic, instruction: 请根据题目中的逻辑关系回答。, question: 所有猫都爱吃鱼Tom是一只猫。请问Tom是否爱吃鱼, expected: 爱吃鱼 }, { id: case_007, type: extract, instruction: 请只输出人名。, question: 从这句话中抽取人名李明昨天去北京参加会议。, expected: 李明 }, { id: case_008, type: knowledge, instruction: 请用一句话回答。, question: 地球绕太阳公转一圈大约需要多长时间, expected: 一年 } ]在设计评测集时有几个原则每条用例都要有明确预期答案哪怕预期答案是“不知道”或“无法确认”。每条用例都要有类型方便统计哪类能力弱。每条用例都要能追溯来源。你可以把来源写进 JSON 的source字段或者放到 Git 提交记录里。4.3 运行评估先安装依赖。pip install -r requirements.txt然后运行评估脚本。如果你使用的是本地 Ollama 服务可以直接执行python src/evaluator.py \ --model qwen2.5:7b \ --base-url http://localhost:11434/v1 \ --output results/result.csv如果使用的是云端 OpenAI 兼容服务就把--base-url和--api-key换成实际值。需要注意不要把密钥硬编码到脚本里建议通过环境变量读取。预期输出大致如下case_001 - PASS | 1.23s case_002 - PASS | 0.98s case_003 - FAIL | 1.01s ... 评测结果已写入 results/result.csv这里的结果会随模型和参数变化不需要追求固定输出。第一次跑通脚本比第一次拿到高分更重要。4.4 从结果反推“繁荣信号”拿到了 CSV 结果怎么判断一个模型是不是“虚高”我建议按下面三步分析第一步看整体通过率。如果整体通过率很低说明模型在当前任务上并不靠谱所谓“强能力”至少没有覆盖这些用例。第二步按类型拆分。如果数学题全对、逻辑题全错说明模型可能在计算语料上表现好但在推理链路上有薄弱点。第三步看失败模式。读一读失败用例的预测文本。有些失败是“答案错误”有些是“输出格式不对”有些是“直接放弃回答”这些情况对产品设计的影响完全不同。更直接的“虚高信号”是同一个模型在公开榜单上分数很高但在你自建评测集上分数明显下滑。不一定是模型刷分也可能是你的评测集风格与公开榜单不同但至少说明选型时需要谨慎。4.5 怎样判断评测集本身是否可靠评测集也可能有质量问题。常见情况包括预期答案写错导致正确结果被误判为错误。问题本身有歧义模型回答的是另一个合理角度。判断逻辑太粗糙比如用“包含匹配”时期望答案“48”可能被“480”误匹配。所以每次评测后不要急着改 Prompt先检查失败样本。如果大量失败来自评测集问题说明需要先迭代数据质量而不是模型能力。5. 常见问题与排查思路在跑“大模型能力体检”时我遇到过不少问题这里整理成一张排查表。问题现象常见原因解决思路请求一直超时模型体积过大本地服务推理慢换小尺寸模型或检查 GPU 显存占用返回空内容max_tokens设置太小或请求被内容策略拦截调大max_tokens检查输入是否触发拦截输出格式混乱没有在用例里声明输出格式限制在instruction里增加格式要求或使用结构化输出评测分数高但线上效果差评测集与真实业务分布不一致自建业务评测集增加人工标注样本结果无法复现模型版本/参数未被固定随机性过高固定模型 ID、temperature、seed记录全部请求参数本地服务没有启动忘掉运行 Ollama/vLLM 服务先访问http://localhost:11434确认服务状态另外如果你在跑评测的时候遇到调用失败可以用一个带重试的封装函数减少临时网络抖动带来的干扰。import time from openai import OpenAI def ask_model_with_retry(client: OpenAI, model: str, prompt: str, retries: int 2, **kwargs) - str: 调用模型并支持简单重试。 for attempt in range(retries): try: response client.chat.completions.create( modelmodel, messages[{role: user, content: prompt}], **kwargs, ) return response.choices[0].message.content.strip() except Exception: if attempt retries - 1: raise time.sleep(2) return 需要注意的是重试不能掩盖所有问题。如果同一个错误持续出现比如密钥无效、模型名写错、服务未启动那么问题出在环境配置而不是网络抖动。6. 工程与团队实践怎样避免自己成为“虚假繁荣”的制造者6.1 评测集、模型版本、推理参数三件套在团队里做 AI 工程实践时我建议把以下三样东西当成“合同”固定下来。评测集用 Git 管理每次改动都留提交记录。模型版本记录准确的模型名、版本号或服务端模型摘要。推理参数记录 temperature、max_tokens、seed、top_p 等。缺少任何一项历史评测结果都会变得不可比较。很多团队说“新版模型比旧版好”但实际只是把 temperature 从 0.2 调成了 0.8这种对比没有任何工程意义。6.2 让评测跑在 CI 里如果团队已经有一定基础设施可以把上面的evaluator.py接到 CI 中。每次改动评测集或更换模型时自动跑一遍并把结果归档。下面是一个 GitHub Actions 示例仅演示流程具体步骤需要按项目实际调整。name: model-eval on: workflow_dispatch: jobs: eval: runs-on: ubuntu-latest steps: - uses: actions/checkoutv4 - uses: actions/setup-pythonv5 with: python-version: 3.11 - name: Install dependencies run: | pip install -r requirements.txt - name: Run evaluation run: | python src/evaluator.py \ --model qwen2.5:7b \ --base-url http://localhost:11434/v1CI 的价值不是让评测变“自动”而是让评估结果可追溯。一旦模型出现回归你能立刻知道是哪次改动导致。6.3 对 AI Agent 和自动化流程保持怀疑AI Agent 是当前很热的方向也最容易出现“演示级繁荣”。一个 Agent 在演示环境里看起来会拆分任务、调用工具、整理结果但如果把它放到生产环境可能立刻出现工具权限边界不清、步骤不可恢复、日志缺失等问题。因此评估 Agent 时要额外关注工具调用是否真实发生而不是有一个人工“影子系统”在背后处理。中间结果是否有日志能否回放整个决策过程。失败时能否回滚到安全状态避免误操作。动作是否被沙箱隔离权限是否最小化。我也看过不少开源项目比如 AI 小镇这类模拟智能体社交行为的项目展示效果很有趣适合学习多 Agent 系统的交互逻辑但把它直接等同于生产级多 Agent 协作能力就有点过于乐观了。把实验项目当学习样例没问题把实验项目当生产依据需要谨慎。6.4 数据与安全边界在构建评测集和做模型评估时还要注意数据和权限安全。评测数据里的用户信息需要脱敏不能为了评测方便直接把生产数据明文复制出来。API 密钥要放在环境变量或密钥管理服务中不要提交到代码仓库。如果评测过程中涉及删除或修改数据先备份并在测试环境验证。如果使用云 API 评估私有数据先确认数据合规边界判断是否允许传输。这些内容看起来和“虚假繁荣”无关但一旦数据出现问题评测过程就可能被迫中断前面积累的工程能力也会失去意义。7. 总结与下一步学习路线这篇文章的核心观点很简单AI 是否繁荣不能靠演示出来的“高光时刻”判断而要靠可复现的评估和工程闭环判断。我们可以把大模型能力体检脚本作为起点先建立自己的评测集再逐步加入更复杂的判断逻辑、多模型对比、回归测试和线上可观测性。如果你正在做模型选型下一步可以学习 RAG 的离线评估重点看检索质量对生成质量的影响如果你正在做 Agent 开发下一步可以研究工具调用的权限边界、沙箱环境和失败恢复机制如果你正在做 AI 产品经理下一步可以设计一套包含用户任务完成率、单次会话成本、人工介入率的核心指标而不是只盯着 Demo 播放量。技术演进很快今天表现好的模型下个月可能被新版本取代也可能因为部署方式改变而变弱。唯一能穿越这些变化的是一套你自己能解释、能复现、能迭代的评估基线。最后我建议你动手做一件事把上面这份eval_cases.json替换成日常业务中真实的 20 个问题然后跑一次评估脚本。不要只看通过率一定要逐条读失败样本。当你的团队开始把失败 case 当成迭代依据而不是当成“不能展示的意外”那么你大概率已经在做真实的 AI 工程而不是在制造虚假繁荣了。