1. 厂商AI能力对比这件事,到底在比什么
“厂商AI能力对比”这个标题,乍一看像是咨询公司的报告选题,但我第一次认真做这件事,是因为一个很具体的场景:团队要选一个基础模型接入自己的产品,候选名单拉出来有七八家,每一家官网都写着“行业领先”“性能卓越”“全面超越”,销售给的PPT一个比一个漂亮,但真正落到我们自己的业务语料上,谁强谁弱,谁也说不清。那段时间我几乎把主流厂商的文档翻了个遍,也踩了不少坑,最后沉淀出一套自己的对比方法。这篇文章就把这套方法完整拆开讲,从对比维度怎么定、测试集怎么造、指标怎么算,到实际跑下来各家表现出的性格差异,以及那些只有真正上手才会发现的隐藏成本。
先说清楚这件事的定位。厂商AI能力对比,本质上不是给厂商排座次,而是给自己的业务找匹配。同一个模型,做长文档摘要可能很稳,做多轮工具调用可能就频繁出错;有的厂商API响应快但上下文窗口小,有的窗口大但单价高得离谱。所以对比的核心不是“谁第一”,而是“在我的约束条件下谁最合适”。约束条件包括预算、延迟要求、数据合规要求、并发量、是否需要微调、是否要求私有化部署等等。把这些约束先列清楚,再去比能力,才不会陷入参数党的自我感动。
适合读这篇内容的人,我大致分三类。第一类是正在做技术选型的工程师或技术负责人,需要一套可复现的评测流程;第二类是产品经理,想理解不同模型的能力边界,以便设计功能时知道哪些能做哪些不能做;第三类是对这个领域好奇的开发者,想自己动手跑一遍对比,建立直观感受。不管哪一类,我都建议你先把“对比”这件事当成一个工程项目来做,而不是当成一次购物比价。工程项目意味着有明确的验收标准、可重复的流程、可量化的结果,以及一份能说服别人的报告。
我见过太多团队在这一步偷懒,直接看某个公开榜单的排名就定了,结果上线后发现榜单第一的模型在自己的场景里表现平平。原因很简单,公开榜单的测试集和你的业务分布往往差得很远。榜单考的是通用知识问答和推理,你的业务可能是客服对话、合同审阅、代码补全,分布完全不同。所以这篇内容的主线就是:如何从零搭建一套贴合自己业务的厂商AI能力对比体系,并且把结论落到可执行的选型决策上。
2. 对比维度怎么定:从业务约束反推评测项
2.1 先列约束,再列能力
很多人一上来就列能力维度,什么语言理解、逻辑推理、代码生成、多模态,列了二十项,最后发现根本测不完,也没法加权。我的做法反过来:先把业务约束列出来,再从约束反推需要测哪些能力。约束通常分四类。
第一类是成本约束。包括每百万token的输入输出单价、是否有阶梯定价、缓存命中是否打折、批量调用是否有优惠。这里有个容易忽略的点:不同厂商的token计算方式不一样,同样一段中文,有的按字符估算,有的按分词后计算,实际消耗可能差百分之二三十。所以比价不能只看标价,要用同一段真实语料跑一遍,看实际计费token数。
第二类是性能约束。包括首token延迟、生成速度(tokens per second)、并发上限、限流策略。首token延迟对交互式产品极其关键,用户等超过两秒就会觉得卡;生成速度对长文生成场景关键,速度慢意味着用户要盯着屏幕等很久。这两个指标要分开测,不能混为一谈。
第三类是能力约束。这才是通常说的“AI能力”,包括指令遵循、长上下文理解、结构化输出稳定性、多轮对话一致性、工具调用准确率、代码生成正确率等。注意,这些能力必须结合你的业务场景来选,不是越多越好。
第四类是工程约束。包括API稳定性、文档质量、SDK成熟度、是否支持流式输出、是否支持函数调用、是否有内容审核接口、故障时的降级方案等。这一类最容易被忽略,但往往决定上线后的运维成本。
2.2 把约束翻译成可测量的指标
约束列完之后,每一项都要翻译成可测量的指标。我举几个例子说明这个翻译过程。
“成本要可控”翻译成:在业务典型请求分布下,每千次请求的平均成本,以及P99请求的成本。为什么要看P99?因为有些请求输入特别长,会把成本拉高,只看平均值会低估风险。
“响应要快”翻译成:首token延迟的P50和P95,以及生成速度的均值。P95比均值更能反映用户体验,因为用户对慢的那几次印象最深。
“输出要稳定”翻译成:在结构化输出任务上,JSON解析成功率;在多轮对话中,指代消解准确率;在长文档任务中,关键信息召回率。这些指标都需要自己造测试集来测,没有现成的。
“工程要可靠”翻译成:连续调用一千次的失败率、超时率、限流触发次数。这个测试比较耗时,但非常值得做,因为很多问题只在长时间运行后才暴露。
我一般会把这些指标整理成一张表,左边是约束,右边是对应指标和测量方法。这张表就是后续所有测试的纲领,避免测着测着跑偏。
2.3 权重分配:没有绝对公平,只有业务适配
指标定完之后,要给每个指标分配权重。这里必须说清楚一个原则:权重没有客观标准,完全取决于你的业务。一个做实时语音助手的产品,首token延迟的权重可能占到百分之四十;一个做离线文档分析的产品,延迟权重可能只有百分之五,而长上下文召回率的权重能到百分之三十。
我的做法是让业务方来定权重,而不是技术方拍脑袋。具体操作是:把指标列出来,让产品、运营、技术各出一个人,各自独立打分,然后对齐差异。差异大的地方往往就是大家理解不一致的地方,正好借这个机会把需求聊清楚。比如技术觉得延迟不重要,产品觉得延迟是生命线,这种分歧必须在选型前解决,否则选完了还会吵。
权重定完之后,每个模型的综合得分就是各指标归一化后加权求和。归一化的方法我一般用min-max,把每个指标在候选模型中的最小值和最大值找出来,映射到0到1之间。注意,对于“越小越好”的指标(如延迟、成本),要反向归一化。这样算出来的分数才有可比性。
3. 测试集怎么造:让评测结果真正有说服力
3.1 为什么不能用公开榜单
公开榜单的问题我在前面提过,这里展开说。公开榜单的测试集通常有几个特点:题目经过清洗、答案明确、分布均匀、以英文为主。而真实业务数据往往是:噪声大、答案模糊、分布倾斜、以中文为主、夹杂大量专业术语和内部黑话。用公开榜单测出来的排名,迁移到业务上经常失效。
我做过一个对比实验,同一个模型在某个公开推理榜单上排前三,但在我们自己的合同条款抽取任务上,准确率还不如一个排名靠后的模型。原因是合同文本有大量固定格式和法律术语,公开榜单根本没覆盖这类分布。所以我的结论很明确:公开榜单可以看,但只能作为初筛,不能作为决策依据。
3.2 自建测试集的四个来源
自建测试集我一般从四个来源收集样本。第一个来源是线上真实请求日志,这是最贴近业务的,但要注意脱敏和采样偏差。第二个来源是业务方提供的典型case,产品经理和运营手里往往有一批“这个必须做对”的例子。第三个来源是边界case,也就是那些容易出错的、模棱两可的、需要多步推理的例子,这类样本最能拉开模型差距。第四个来源是合成数据,用强模型生成一批样本再人工校验,适合冷启动阶段样本不足的情况。
四个来源的比例我一般控制在:真实日志百分之四十,典型case百分之三十,边界case百分之二十,合成数据百分之十。真实日志保证分布贴近,典型case保证关键场景覆盖,边界case保证区分度,合成数据补充长尾。
3.3 标注规范与一致性校验
测试集造好之后要标注。标注这件事听起来简单,做起来极容易出问题。我踩过的坑包括:标注员对“正确”的理解不一致、多轮对话的标注标准不统一、开放式问题的参考答案过于单一导致误判。
解决办法是写一份标注规范,把每个任务的判定标准写清楚,并且给出正例和反例。比如“信息抽取任务”要明确:字段缺失算不算错、字段值有细微差异算不算对、多个答案时如何判定。规范写完之后,先让两个标注员独立标一百条,算一下一致率,如果低于百分之九十,就回去改规范,直到一致率达标再全面铺开。
对于开放式生成任务,单一参考答案确实不公平。我的做法是改用评分制,从相关性、完整性、流畅性三个维度各打一到五分,由两个标注员独立打分取平均。虽然主观,但比精确匹配合理得多。
3.4 测试集的版本管理
测试集是要迭代的。业务在变,模型在更新,测试集如果一成不变,很快就会过时。我一般给测试集打版本号,每次业务有重大变化或者模型有重大更新时,就评估是否需要新增样本。新增样本要单独标记,这样在对比时可以看出模型在新旧样本上的表现差异。
还有一个细节:测试集要留一部分作为“保留集”,平时不参与调优,只在最终决策时用。这是为了防止过拟合,也就是针对测试集反复调prompt,最后分数很好看但实际效果一般。保留集的比例我一般留百分之二十。
4. 实操过程:从零跑完一轮完整对比
4.1 环境准备与统一调用层
正式开测之前,先搭一个统一的调用层。这一步的目的是屏蔽各家API的差异,让后续测试代码只写一遍。统一调用层要处理的事情包括:认证方式差异、请求格式差异、响应格式差异、错误码差异、重试逻辑、超时设置、并发控制。
我用Python写了一个简单的抽象层,核心是一个基类,定义generate方法,各家厂商实现各自的子类。这样测试脚本只依赖基类,换模型只需要换配置。代码结构大致如下。
class BaseProvider: def __init__(self, config): self.config = config self.client = self._build_client() def _build_client(self): raise NotImplementedError def generate(self, prompt, **kwargs): raise NotImplementedError def generate_batch(self, prompts, **kwargs): results = [] for p in prompts: try: results.append(self.generate(p, **kwargs)) except Exception as e: results.append({"error": str(e)}) return results重试逻辑我一般设置三次,指数退避,初始间隔一秒。超时设置根据场景定,交互式场景设十秒,离线场景设六十秒。并发控制用信号量,避免触发限流。
4.2 参数对齐:让对比尽量公平
不同厂商的默认参数不一样,直接对比不公平。我一般把能对齐的参数对齐,不能对齐的记录下来。能对齐的包括:温度(统一设零或零点一,保证可复现)、最大输出长度(统一设一个足够大的值)、top_p(统一设一)。不能对齐的包括:各家特有的惩罚项、系统提示词的处理方式、上下文截断策略。
温度设零是为了可复现,但要注意有些厂商在温度为零时仍然有随机性,这时候要跑多次取平均。最大输出长度要设得足够大,避免因为截断导致误判,但也不能太大,否则浪费成本。我一般设成业务典型输出的两倍。
系统提示词的处理方式差异很大,有的厂商把系统提示词和用户输入拼在一起,有的分开处理。这个差异会影响指令遵循的表现,所以测试时要统一用同一种写法,并且在报告里注明。
4.3 跑测与数据记录
跑测阶段最重要的是记录完整。我一般记录以下字段:模型名、请求时间、输入token数、输出token数、首token延迟、总延迟、输出内容、是否报错、错误信息。这些字段存成结构化数据,方便后续分析。
首token延迟的测量需要流式接口,非流式接口只能测总延迟。如果厂商不支持流式,我会在报告里注明,并且用总延迟作为参考。生成速度用输出token数除以生成时间(总延迟减去首token延迟)来算。
跑测过程中要注意限流。我一般先用小批量试探,摸清限流阈值,再决定并发数。如果触发限流,要记录触发时的请求量和时间,这也是工程约束的一部分。
4.4 结果分析与可视化
跑完之后就是分析。我一般先看整体得分,再看分项得分,最后看具体case。整体得分给一个全局印象,分项得分看各家性格,具体case看失败模式。
可视化我一般用雷达图展示各维度得分,用箱线图展示延迟分布,用表格展示成本和成功率。雷达图适合给非技术方看,箱线图适合技术方分析,表格适合存档。
分析时要注意区分“能力不足”和“工程问题”。比如某个模型在长上下文任务上表现差,可能是能力不足,也可能是上下文截断策略有问题。要具体看失败case才能判断。
5. 实测下来各家表现出的性格差异
5.1 指令遵循:有的听话,有的自作主张
指令遵循是我最看重的维度之一,因为业务场景往往有严格的格式要求。实测下来,不同模型在这方面的差异非常明显。有的模型你让它输出JSON,它就老老实实输出JSON,连标点都不多;有的模型你让它输出JSON,它先给你来一段“好的,以下是为您生成的JSON”,然后再输出,导致解析失败。
这个差异在简单任务上不明显,在复杂指令上就放大了。比如一个指令包含多个约束:用中文、输出JSON、字段名固定、不要解释、不要markdown代码块。能全部满足的模型不多。我的应对方法是把约束拆成多条,逐条测试,找出每个模型能稳定满足的约束组合。
还有一个现象是“过度帮助”。有的模型看到你的指令有歧义,会主动帮你补全,结果补的方向和你的预期不一致。这在创意场景是优点,在严谨场景是缺点。所以选型时要看你的场景需不需要这种主动性。
5.2 长上下文:窗口大不等于用得好
长上下文是这两年各家都在卷的指标,从几万token卷到几十万甚至上百万。但实测下来,窗口大和用得好是两回事。有的模型窗口标称很大,但把关键信息放在中间位置时,召回率明显下降,这就是所谓的“中间迷失”。有的模型窗口小一些,但关键信息召回很稳。
我测试长上下文的方法叫“大海捞针”:在一段长文本里随机插入一个关键事实,然后提问,看模型能不能找到。插入位置从开头到结尾均匀分布,每个位置测多次。结果画成曲线,就能看出模型的注意力分布。
实测发现,大部分模型在开头和结尾的召回率明显高于中间。差异在于中间部分的衰减程度。衰减慢的模型适合做长文档分析,衰减快的模型即使窗口大也不适合。所以选型时不能只看窗口大小,要看实际召回曲线。
5.3 结构化输出:稳定性比能力更重要
结构化输出是工程上最常用的能力,因为下游系统需要解析。这个维度的关键不是“能不能输出JSON”,而是“能不能稳定输出可解析的JSON”。实测下来,稳定性差异很大。
我测过连续一千次结构化输出,有的模型解析成功率百分之九十九点五,有的只有百分之九十五。别小看这百分之四点五的差距,在每天百万次调用的量级下,就是四万五千次失败,运维成本完全不同。
影响稳定性的因素包括:输出长度(越长越容易出错)、字段数量(越多越容易漏)、嵌套深度(越深越容易格式错)。我的应对方法是:能不用嵌套就不用嵌套,字段数量控制在十个以内,输出长度超过一定阈值就分段生成。另外,prompt里加一句“只输出JSON,不要任何其他内容”能显著提升稳定性,但不是所有模型都吃这一套。
5.4 工具调用:准确率和容错率要分开看
工具调用(function calling)是构建智能体的基础能力。这个维度要分两个指标看:准确率和容错率。准确率是指模型选对工具、填对参数的比例;容错率是指模型在参数缺失或格式错误时,能否自我纠正。
实测发现,有的模型准确率高但容错率低,一旦参数错了就一路错下去;有的模型准确率一般但容错率高,能根据错误信息调整。后者在实际系统中往往更好用,因为真实环境里工具报错是常态。
工具调用的测试要造多轮场景,不能只测单轮。单轮调用谁都会,多轮调用中保持上下文一致、正确传递中间结果,才是难点。我一般造五到十轮的工具调用链,看模型能不能走完。
6. 常见问题与排查技巧实录
6.1 对比结果不可复现怎么办
不可复现是最常见的问题,原因通常有三个:温度没设零、厂商侧有随机性、测试集顺序影响。温度没设零好解决,设零就行。厂商侧随机性比较麻烦,有的厂商即使温度为零,底层也有采样,这时候只能多跑几次取平均,并且在报告里注明方差。测试集顺序影响是指模型对前面的样本有“记忆”,虽然API是无状态的,但同一批次内的请求可能共享缓存,导致结果不同。解决办法是打乱顺序,或者每次请求之间加延迟。
6.2 成本算不准怎么办
成本算不准通常是因为token计算方式不同。解决办法是用同一段语料,分别调用各家的token计数接口(如果有),或者用各家提供的分词工具算。如果没有计数接口,就用实际调用后的账单反推。我一般会跑一批固定语料,记录实际计费token数,算出各家的“实际单价”,再和标价对比。实测下来,实际单价和标价的偏差在百分之十到百分之三十之间,不能忽略。
6.3 延迟波动大怎么办
延迟波动大是常态,尤其是共享资源的API。解决办法是分时段测,比如早中晚各测一轮,看波动规律。另外要区分首token延迟和总延迟,前者受网络影响大,后者受生成长度影响大。如果延迟波动超过可接受范围,就要考虑是否有降级方案,比如超时后切换到备用模型。
6.4 模型更新导致结果变化怎么办
模型更新是好事,但会让之前的对比结果失效。我的做法是给每次对比打上模型版本号,模型更新后重新跑关键指标,看是否有回归。如果业务对稳定性要求极高,可以考虑锁定版本,但要注意锁定版本可能错过能力提升。这个权衡要看业务阶段,早期可以追新,成熟期求稳。
6.5 常见问题速查表
| 问题 | 可能原因 | 排查方法 | 解决方向 |
|---|---|---|---|
| 结果不可复现 | 温度非零、厂商随机性、缓存 | 设温度为零、多跑取平均、打乱顺序 | 记录方差、注明随机性 |
| 成本超预期 | token计算差异、长请求拉高均值 | 用真实语料实测、看P99成本 | 优化prompt、设置长度上限 |
| 延迟波动大 | 共享资源、网络抖动、生成长度 | 分时段测、区分首token和总延迟 | 设超时降级、错峰调用 |
| 结构化输出失败 | 输出过长、字段过多、嵌套过深 | 看失败case的共性 | 简化结构、分段生成 |
| 长上下文召回差 | 中间迷失、截断策略 | 大海捞针测试、看召回曲线 | 关键信息前置、分段处理 |
| 工具调用出错 | 参数格式、多轮一致性 | 造多轮链、看错误传播 | 加校验、加容错提示 |
7. 选型决策:从对比结果到最终方案
7.1 单一模型还是多模型组合
对比完之后,经常发现没有哪个模型在所有维度都领先。这时候要考虑多模型组合。组合的方式有三种:按任务路由、按难度路由、按成本路由。按任务路由是指不同任务用不同模型,比如摘要用A,代码用B。按难度路由是指简单请求用便宜模型,复杂请求用强模型。按成本路由是指优先用便宜模型,失败后升级到强模型。
组合的代价是工程复杂度上升,需要维护路由逻辑、统一输出格式、处理模型间差异。所以不是所有场景都值得组合。我的经验是:如果业务场景单一,选一个综合最优的就行;如果场景多样且差异大,组合的收益能覆盖复杂度成本。
7.2 如何写一份能说服人的选型报告
选型报告的结构我一般这样组织:先讲业务约束和评测目标,再讲评测方法和测试集,然后讲各维度结果,最后讲推荐方案和风险。关键是每个结论都要有数据支撑,不能只说“A比B好”,要说“在X任务上,A的准确率是百分之九十二,B是百分之八十五,差异在百分之九十五置信水平下显著”。
报告里要专门有一节讲风险,包括模型更新的风险、成本超支的风险、限流的风险、供应商锁定的风险。风险要给出应对方案,比如备用模型、成本预警、多供应商策略。
7.3 上线后的持续监控
选型不是一次性的,上线后要持续监控。监控指标包括:实际成本、实际延迟、失败率、用户反馈。这些指标要和选型时的预期对比,偏差大就要重新评估。我一般设置月度回顾,看是否需要调整模型或参数。
监控还有一个作用是发现新能力。厂商会不定期更新模型,新能力可能解锁新场景。所以监控不只是防守,也是进攻。
8. 一些踩坑之后的个人体会
做厂商AI能力对比这件事,我最大的体会是:不要追求一次做到完美,要追求每次都比上次更贴近业务。第一轮对比可能很粗糙,测试集只有几十条,指标只有三四个,但只要跑起来了,就能发现很多纸面上看不到的问题。第二轮再补测试集、加指标、调权重,逐步逼近真实需求。
另一个体会是:对比的过程比结果更有价值。在造测试集、定指标、分析失败case的过程中,团队会对业务需求有更清晰的理解。很多时候,对比做完之后,大家发现原来争论不休的问题,其实是因为对需求的理解不一致。这种对齐的价值,甚至超过选型本身。
最后一个体会是关于心态。厂商AI能力对比没有终点,模型在更新,业务在变化,今天的结论明天可能就过时了。所以不要把对比当成一次性任务,要当成一个持续运行的系统。系统可以简单,但要有,要能持续产出信号。这样当业务需要调整时,你手里有数据,心里有底。
如果让我给一个最实用的建议,那就是:先跑起来,再优化。不要等测试集完美了再开始,不要等指标齐全了再动手。用最小的成本跑通一轮,拿到第一批数据,然后基于数据迭代。这个过程本身,就是最好的学习。