研究者讲述比较Kimi K3不同推理服务商的评测如何耗资逾1600美元,以及过程中的经验教训。
AI translation, not an official translation. Refer to the original for technical details.
Adapted from @daRubberDuckiee# 我在运行这次评测时几乎浪费了1000美元。以下是我的收获。
Kimi K3于7月下旬发布时,我最初构建了一个将Kimi K3与Sonnet 5进行比较的评测。在我将博客发布到Braintrust约一小时后,我们不得不将其撤下,因为其他推理服务商——他们显然对我有意见——已经宣布支持Kimi K3。
他们在宣传Kimi在其平台上的速度和可靠性,而我最初的表述和数据已经过时,因为我的评测是在Moonshot上运行Kimi K3的。这意味着,如果在其他服务栈上运行,Kimi K3的表现可能会更好;或者,在我运行评测的那个周末,Moonshot正面临流量过载。这种不确定性使得我最初评测中的数据存在太多疑问,让我们无法放心地发布。
我确实在个人X账号上发布了那篇文章,你可以在这里找到它。(https://x.com/compose/articles/edit/2085806036557111296)
那是我第一次意识到,为开放权重模型提供服务的推理栈会成为评测中的一个影响因素——因为我此前只评测过GPT、Claude和Gemini等闭源模型,对于这些模型,你无需担心背后的基础设施,因为它们只有一个选项。
因此,我没有比较模型本身,而是比较了服务栈:Moonshot、Fireworks和Baseten,三者均提供Kimi K3的推理服务。
这个决定让我经历了长达一个月、令我质疑自己神智的过程。但在终于为此画上句号之后,我想聊聊我在运行评测的最佳实践方面学到了什么——包括该做的和不该做的。
顺便一提,如果你想阅读那篇官方博客(正是它让我质疑自己的神智),其中包含本次评测的方法论和结果,可以在这里找到。(https://www.braintrust.dev/evals/kimi-k3-serving-stacks)
→ 这次评测为何如此昂贵
每次评测运行耗时长、成本高。我设置了20个任务,每个任务是基于截图使用Figma MCP服务器创建一个HTML页面。每个任务针对每个服务栈运行三次,因此每个服务商预计有60次运行。
平均而言,Fireworks的一次运行耗时13.8分钟,Moonshot的一次运行耗时16.2分钟。由于最终的服务商运行使用了并发数1,完整的60次运行对于Fireworks约需13小时49分钟的代理运行时间,对于Moonshot则约需16小时14分钟。
最终,我在Baseten上花费了542.60美元,在Fireworks上花费了661.82美元,在Moonshot上花费了400美元,合计1604.42美元。
我回顾了服务栈项目中所有活跃和已归档的实验,包括冒烟测试和未完成的尝试。
当我在这里说"浪费的钱"时,我指的是花费在未能进入最终保留分析的运行上的钱。我将进入最终分析的运行与完整记录的任务运行集合进行比较,以找出总花费中"浪费的钱"所占的百分比。
\small
\begin{array}{l|r|r|r|r|r}
\textbf{服务栈} &
\begin{array}{c}\textbf{所有已记录的}\\\textbf{任务运行}\end{array} &
\begin{array}{c}\textbf{保留在}\\\textbf{最终分析中}\end{array} &
\begin{array}{c}\textbf{未保留的}\\\textbf{运行次数}\end{array} &
\textbf{总费用} &
\begin{array}{c}\textbf{未保留运行的}\\\textbf{估计支出}\end{array}
\\ \hline
\text{Baseten} & 24 & 7 & 17 & \$542.60 & \$384.34 \\
\text{Fireworks} & 235 & 60 & 175 & \$661.82 & \$492.84 \\
\text{Moonshot} & 85 & 60 & 25 & \$400 & \$117.65 \\
\hline
\textbf{总计} & \mathbf{344} & \mathbf{127} & \mathbf{217} &
\mathbf{\$1{,}604.42} & \mathbf{\$994.83}
\end{array}
因此,在整个项目中我记录的 344 次任务运行里,只有 127 次进入了最终分析。粗略估计,我在最终未使用的运行上花费了约 995 美元,约占总费用的 63%。
显然,这只是一个估算。有些冒烟测试是必要的,用于了解哪里出了问题;而某些失败的运行实际花费可能高于或低于典型运行。但这件事的教训是:我花了大量金钱去学习本可以用更低成本获得的经验。
→ 我得到的教训
1. 在完整运行之前先进行大量冒烟测试。
我最大的失误,是为了找出评测配置中的低级错误,进行了太多次完整评测运行的迭代。例如,我不得不添加一个代理来将温度固定为 1,因为 Moonshot 的 Kimi K3 要求如此;我不得不添加浏览器 User-Agent,才能让 Fireworks 的请求通过 Cloudflare;还不得不修改超时清理逻辑,确保终止一个 agent 运行时也会同时终止其 MCP 子进程。
这些问题本可以通过冒烟测试发现,但我却因此浪费了数百美元。
我之前从未运行过如此昂贵的评测,因此为自己的粗心付出了沉重代价。
1. 在完整运行之前,先验证速率限制和账户层级。
在我第一次完整的 Baseten 运行中,评测因为很快触发速率限制而失败。Baseten 返回了 653 个 HTTP 429 错误(意为"请求过多"),60 次预计运行中只完成了 7 次。
Baseten 的文档说明,429 错误可能由每分钟请求数或每分钟 token 数触发。其 Basic 已验证层级和 Pro 层级列出的限制为 120 RPM 和 500,000 TPM。相关文档在此。
问题在于,我仍然无法确定自己究竟触发了哪个限制,因为我没有保留速率限制响应头,也没有记录请求级别的 token 使用量。请求速率低于文档标注的 RPM 上限,因此更可能的解释是 token 吞吐量超限。
我选择的任务对 token 消耗非常密集。每次 agent 请求都包含不断增长的对话内容、工具 schema、截图和之前的工具结果。因此,这不仅是服务栈的问题,也是任务选择的问题。
这造成了类似"地板效应"的情况——任务在能够区分各提供商质量之前,就已触及操作层面的瓶颈。(https://docs.baseten.co/inference/model-apis/pricing-and-limits)
1. 对延迟进行多次测量。
另一个最佳实践是:在对延迟进行基准测试时,仅运行一次基准是不够的。更好的做法是在不同天、不同时段运行,并交替测试各提供商,而不是在测完一个提供商的全部批次后再测下一个。
这是因为服务栈在不同时间可能存在不同的流量、排队或批处理行为。
感谢我的同事 Izzy,他在对我的研究进行深度同行评审时指出了这一点。
1. 删除失败的运行记录。
由于某些运行中途被我终止,或因层级限制而失败,我在 Braintrust 中留下了几个未完成的实验。这些记录在一段时间内作为调试依据还算有用,但后来逐渐堆积,使项目变得杂乱,也干扰了后续分析。
当我让 agent 使用 Braintrust CLI 或 MCP 分析结果时,它有时会不小心将这些未完成的运行纳入分析范围。下一次,我会将无效运行存档或明确打上标签,以便清晰地标识哪些运行可以用于分析。
1. 并发会改变工作负载。
我们在尝试同时运行多个 agent 任务时,也遇到了吞吐量问题。在 agentic eval 中,每次运行都可能发出大量上下文不断增长的长请求,因此提高并发度所带来的 token 吞吐量峰值,往往远超预期。
最终的 provider 运行将并发度设为 1,因为在使用 Fireworks 和 Moonshot 时,并发度为 2 时就已经触达 token 速率限制。
1. 控制你的 eval 环境。
中途,我将本地运行于笔记本电脑的 Paper MCP 切换为托管在云端的 Figma MCP。Paper MCP 是个失误,因为它会受到我打开的应用程序、机器负载以及同时运行的 agent 数量的影响。
这让 Figma MCP 成为此次服务栈 eval 更合适的选择,但这本是我在运行第一次冒烟测试之前,就应该在任务设计阶段考虑到的问题。
1. 不要直接从冒烟测试跳到三次完整试验。
我直接从冒烟测试跳到了对每个 provider 运行 20 个任务、每个任务三次试验的完整测试。这意味着每个 provider 需要跑 60 次,而我甚至还不清楚该设置能否在规模上正常运行,也不知道不同 provider 之间是否存在可观察到的差异。
更合理的流程应该是:先运行冒烟测试,再以每个任务一次试验的方式进行一轮完整的薄跑。到那时,我可以先审视成本和早期质量结果,直觉上判断出是否真的存在值得深入衡量的差异。
尽管我并不乐意把钱白白送给 Baseten、Moonshot 和 Fireworks,而不是用来好好血拼一番或攒下半台 iPhone Duo,但这些都是用真金白银换来的教训,只会让我日后的 eval 体验越来越好。希望你也能从我的失误中有所收获 🙂