1. 五亿token到手之后,我为什么选择批量做小游戏
拿到智谱赠送的五亿token额度那天,我盯着后台的用量面板看了很久。五亿token是什么概念?按一次对话平均消耗两千token来算,理论上能跑二十五万次请求。如果拿来做代码生成,一个中等复杂度的项目消耗两三万token,那也能支撑上万次完整的代码生成任务。这个量级对于个人开发者来说,几乎等于把"试错成本"这个顾虑彻底抹掉了。
我当时的想法很直接:既然额度管够,那就找一个能批量验证、快速出成果、且能覆盖多种编程范式的方向。思来想去,小游戏是最合适的载体。原因有三:第一,单个游戏的代码量可控,通常几百到两千行就能跑起来,适合用大模型一次性生成;第二,游戏逻辑天然包含状态管理、输入处理、渲染循环、碰撞检测这些通用编程模式,能全面检验模型的代码能力;第三,游戏有明确的"能跑/不能跑"判定标准,不需要复杂的测试框架,打开浏览器就知道成没成。
于是就有了这个周末的计划:用智谱的GLM系列模型配合zcode工具链,批量生成七十二个小游戏,全部开源。这篇文章不是来炫耀成果的,而是把这七十二个游戏从零到跑通的完整过程拆开讲——包括我怎么设计批量生成的流水线、怎么处理模型输出的各种意外、怎么在几百个文件里做质量筛选,以及踩过的那些坑。如果你手里也有一批token额度不知道怎么花,或者想了解大模型批量代码生成的实际工程细节,这篇应该能给你一些参考。
2. 批量生成流水线的设计:从单次对话到七十二个产物
2.1 为什么不能一个游戏一个游戏手动聊
最开始我确实想过偷懒,直接在对话界面里一个个让模型写。试了三个之后就放弃了。问题不在于模型写得不好,而在于手动流程的摩擦成本太高:每次要重新描述需求、要复制粘贴代码、要手动建文件、要改文件名、要记录哪个游戏对应哪次对话。一个游戏平均花十五分钟在"非生成"的杂事上,七十二个就是十八个小时,一个周末根本不够。
更关键的是,手动模式下你没法保证生成条件的一致性。第一个游戏你可能说"写一个贪吃蛇",第十个游戏你可能说"用HTML5 Canvas写一个带计分和加速机制的贪吃蛇游戏",提示词的细微差异会导致输出质量波动,最后你根本分不清是模型能力问题还是提示词问题。
所以我决定做一条批量化流水线。核心思路是:把"游戏需求"抽象成结构化的配置,把"生成"抽象成一次API调用,把"落盘"抽象成脚本自动处理。这样每个游戏的生成条件完全一致,唯一变量就是游戏类型本身。
2.2 流水线的四个核心模块
整条流水线我拆成了四个模块,每个模块职责单一,方便单独调试。
需求配置模块:用一个JSON文件描述所有七十二个游戏。每个游戏包含字段:游戏名称、英文标识、核心玩法描述、技术栈要求、特殊机制要求。比如贪吃蛇的配置大概是这样的:
{ "name": "贪吃蛇", "slug": "snake", "gameplay": "玩家控制蛇在网格中移动,吃到食物后身体变长,撞墙或撞到自己则游戏结束", "tech": "HTML5 Canvas + 原生JavaScript,单文件", "features": ["计分", "速度随长度递增", "方向键控制", "暂停功能"] }这个配置文件是整个流水线的输入源,后面所有步骤都从这里读数据。
提示词组装模块:根据配置生成发给模型的提示词。这里有个关键设计——我把提示词分成了"固定模板"和"变量填充"两部分。固定模板里写死了输出格式要求(比如"只输出一个完整的HTML文件,不要解释,不要markdown代码块标记"),变量部分才填入具体游戏需求。这样做的好处是输出格式高度可控,后面解析起来省事。
API调用模块:负责实际发起请求。我用的是智谱的API接口,模型选的glm-5.3-flash,主要是看中它在代码生成上的响应速度和稳定性。这里要处理几个工程问题:并发控制(不能一次性发七十二个请求把额度打满)、失败重试(网络抖动或限流导致的失败要自动重试)、超时处理(有些复杂游戏生成时间较长)。我设的是并发数五,单次超时一百二十秒,失败重试三次。
落盘与索引模块:把模型返回的内容写成文件,同时生成一个索引页。索引页是个简单的HTML,列出所有游戏名称和链接,方便一次性浏览全部成果。这个模块还要做基础校验:检查返回内容是否包含HTML标签、文件大小是否在合理范围、有没有明显的截断。
2.3 并发数为什么定在五而不是更高
这里展开说一下并发数的选择。理论上你可以把七十二个请求一次性全发出去,但实际会遇到两个问题。一是API侧的限流策略,虽然额度够,但单位时间内的请求频率通常有上限,发太快会触发限流导致大量失败。二是本地处理能力,每个返回结果都要解析、校验、写文件,并发太高会导致内存和IO压力集中。
我实测下来,并发五是一个比较舒服的平衡点。七十二个游戏分十五批左右跑完,总耗时大概四十分钟,其中大部分时间花在等待模型生成上。如果你追求更快,可以试并发八到十,但要相应增加重试次数和错误处理逻辑。再高就不建议了,收益递减明显,反而增加排查成本。
提示:并发数不是越高越好。批量任务里,稳定跑完比跑得快更重要。一次失败重试的成本,往往比降低并发多花的时间更高。
3. 提示词工程:让模型稳定输出可运行的单文件游戏
3.1 输出格式约束是第一条生命线
批量生成最怕的不是模型写得差,而是模型写得好但格式不对。比如它给你返回一段带markdown代码块标记的内容,或者前面加一段"好的,我来帮你写一个贪吃蛇游戏"的说明,你的自动落盘脚本就得额外做清洗。清洗逻辑越复杂,出错的概率越高。
所以我在提示词里把格式约束放在了最前面,而且用了比较强硬的措辞。大意是:你是一个代码生成器,只输出一个完整的、可直接在浏览器打开的HTML文件,从<!DOCTYPE html>开始到</html>结束,不要有任何额外文字,不要用代码块包裹。这个约束加上few-shot示例(我给了一个极简的示例输出),基本能把格式问题压到百分之五以下。
剩下那百分之五的格式异常,我在落盘模块里做了兜底处理:如果检测到内容以代码块标记开头,就自动剥离;如果检测到内容前面有非HTML文本,就找到第一个<符号开始截取。这套组合拳下来,七十二个游戏里只有两个需要人工介入。
3.2 技术栈锁定能大幅降低不确定性
小游戏的技术栈选择很多:可以用纯Canvas、可以用DOM操作、可以用WebGL、可以引入第三方库。如果不锁定,模型每次可能选不同的方案,导致代码风格不统一,后期维护和阅读都麻烦。
我的做法是在提示词里明确要求:使用HTML5 Canvas加原生JavaScript,不引入任何外部依赖,所有代码写在一个HTML文件里。这个约束带来三个好处:一是零依赖意味着打开就能跑,不需要配环境;二是单文件意味着索引页可以直接用iframe嵌入,浏览体验统一;三是原生JS意味着代码量可控,不会因为引入库而产生大量样板代码。
实测下来,这个约束执行得相当好。七十二个游戏里,有六十八个是完全符合的,另外四个里有两个用了内联的CSS动画代替Canvas(对于某些游戏其实更合适),有两个引入了一个CDN上的轻量库(我手动改成了原生实现)。整体符合率超过百分之九十四。
3.3 玩法描述的颗粒度怎么把握
这是我在调试过程中反复调整的一个点。描述太粗,模型会自由发挥,生成的东西可能偏离预期;描述太细,等于我自己把逻辑写了一遍,失去了用模型的意义。
我的经验是:描述清楚"核心循环"和"胜负条件"就够了,中间的实现细节交给模型。比如贪吃蛇,我只需要说"蛇在网格中移动,吃食物变长,撞墙或撞自己结束",不需要说"用二维数组存储蛇身坐标,每帧根据方向更新头部位置"。后者是模型应该自己决定的实现细节。
但有一类信息必须写清楚,就是"特殊机制"。比如某个游戏要求"每吃五个食物速度提升一档",这种非默认行为如果不写,模型不会主动加。所以我的配置里专门有个features字段,用来列这些额外要求。这个字段的颗粒度控制在"一句话能说清一个机制"的程度。
3.4 处理模型"自作主张"加功能的情况
批量生成到第二十几个游戏的时候,我发现有些游戏模型会额外加一些我没要求的功能。比如一个简单的打砖块游戏,它自己加了关卡系统和道具掉落。这些功能本身不坏,但会导致代码量膨胀,有些还引入了bug。
我的处理策略分两种。如果加的功能不影响核心玩法且代码能跑,我就保留,当作意外收获。如果加的功能导致代码跑不起来,我就在提示词里加一句"只实现上述功能,不要添加额外机制",然后重新生成。这个约束加上之后,输出就规矩多了。
这里有个心得:模型加功能往往是因为它在训练数据里见过类似游戏的"完整版",它倾向于输出一个"完整"的实现。你要做的不是批评它,而是明确告诉它边界在哪里。
4. 七十二个游戏跑下来,模型在哪些地方翻车了
4.1 物理模拟类游戏是重灾区
七十二个游戏里,翻车最集中的是涉及物理模拟的类型,比如弹球、抛体运动、碰撞反弹。模型在处理这类问题时,经常出现两种错误:一是速度向量更新逻辑写反,导致球往错误方向弹;二是碰撞检测的边界条件处理不当,导致球卡在墙壁里或者穿透。
我印象最深的是一个"打砖块"游戏,模型写的碰撞检测是这样的:当球的位置超出边界时,反转速度方向。逻辑上没错,但它没有考虑球在一帧内移动距离超过边界厚度的情况,导致球高速运动时会直接穿墙。修复方法是在检测到越界后,把球的位置重置到边界内侧,而不是只反转方向。
这类问题的根源在于,模型对"连续运动在离散帧中如何正确处理"这个经典问题理解不够深。它在生成代码时更多是在模仿见过的代码模式,而不是真正推导物理过程。所以涉及物理的游戏,我建议生成后一定要手动跑一遍,重点看高速运动和边界情况。
4.2 状态管理在复杂游戏里容易乱
简单游戏的状态很少,一个分数、一个游戏状态标志就够了。但稍微复杂一点的游戏,比如带多关卡、多道具、多敌人类型的,状态就多了。模型在这种情况下容易出现状态更新不同步的问题。
具体表现是:某个状态变量在A处更新了,但B处还在用旧值;或者两个状态变量之间的约束关系被破坏(比如"生命值为零时游戏结束"这个约束,在某个分支里没检查)。这类bug不会导致游戏崩溃,但会导致行为诡异,比如角色死了还能动、分数不增加等。
我的应对方法是在提示词里加一句"确保所有状态更新在同一个游戏循环内完成,避免跨帧的状态依赖"。这句话不能完全杜绝问题,但能减少一部分。剩下的还是得靠人工测试。
4.3 输入处理的边界情况经常被忽略
键盘输入处理看起来简单,但边界情况不少。比如同时按下多个方向键怎么办?按住不放和连续点击怎么区分?游戏暂停时输入要不要响应?模型生成的代码在这些地方经常有疏漏。
一个典型例子是"俄罗斯方块",模型写的旋转逻辑在方块靠近右边界时会出错,因为旋转后可能超出边界,但代码没有做边界修正。另一个例子是"贪吃蛇",快速连续按相反方向键会导致蛇直接掉头撞到自己,因为代码没有做"禁止反向"的判断。
这些问题的修复都不难,但需要你实际玩一遍才能发现。所以我的建议是:每个游戏生成后,至少玩两分钟,把所有按键都试一遍,特别是边界情况。
4.4 代码截断:批量生成最隐蔽的坑
这个问题值得单独说。批量生成时,如果模型输出较长,有可能在达到最大token限制时被截断。截断的代码往往看起来"差不多完整",因为HTML结构可能闭合了,但JavaScript逻辑只写了一半。
我遇到过一个游戏,HTML和CSS都完整,JavaScript写到了游戏循环就断了,后面的碰撞检测和计分逻辑全没了。打开浏览器能看到画面,但游戏没法玩。这种问题在批量场景下特别隐蔽,因为你不一定有时间逐个打开测试。
我的解决方案是在落盘模块里加了一个简单的完整性检查:统计function关键字出现次数、检查是否有明显的未闭合括号、检查文件末尾是否是</html>。这三个检查能过滤掉大部分截断情况。对于通过检查但仍有问题的,就靠索引页的批量预览来发现。
5. 从七十二个产物里做质量筛选的实操方法
5.1 先做机器可判定的初筛
七十二个游戏不可能每个都仔细看,所以第一步是用脚本做初筛。我写了几个检查项:文件大小是否在合理范围(太小可能是空文件,太大可能是模型跑偏了)、是否包含<canvas>或游戏循环相关关键字、是否有语法错误(用Node.js的--check参数快速验证JavaScript部分)。
这一步能过滤掉大约百分之十的明显问题产物。剩下的百分之九十进入下一轮。
5.2 用索引页做批量目视检查
初筛之后,我生成了一个索引页,把所有游戏用iframe嵌入,每个iframe给一个固定尺寸。打开这个页面,七十二个游戏同时加载,哪个白屏、哪个报错、哪个画面明显不对,一眼就能看出来。
这个方法效率极高。我花了大概二十分钟就把七十二个游戏过了一遍,标记出十几个有问题的。有问题的里面,又分"完全跑不起来"和"能跑但行为异常"两类,前者优先修,后者看时间。
5.3 人工试玩只针对高价值游戏
全部试玩不现实,也没必要。我的策略是:从七十二个里挑出二十个左右"有代表性"的游戏做深度试玩,包括所有物理类、所有状态复杂的、以及随机抽样的简单游戏。这二十个试玩下来,基本能摸清这批产物的整体质量水平。
试玩的时候我会记录具体问题,比如"贪吃蛇反向按键导致自杀"、"打砖块高速穿墙"、"俄罗斯方块旋转越界"。这些记录后来成了我修bug的清单,也成了这篇文章的素材。
5.4 修复策略:能自动修的自动修,不能的标记出来
对于格式类问题(比如多余的代码块标记、文件头尾有多余文字),我写了脚本自动修。对于逻辑类问题,我分两种处理:简单的(比如加一个边界判断)手动改;复杂的(比如重写碰撞检测)就标记为"已知问题",在README里说明。
这里有个取舍:不是所有bug都值得修。七十二个游戏里,有五个我判断修复成本高于价值,就直接标记了。开源项目里,诚实地标注已知问题比假装完美更有价值。
6. 开源这批产物时我做的几件事
6.1 目录结构要让人一眼看懂
开源项目的目录结构直接影响别人的第一印象。我的结构是这样的:根目录放README和索引页,games/目录下每个游戏一个文件夹,文件夹名用英文slug,里面放index.html和可选的README.md。这种结构的好处是,别人clone下来直接打开根目录的index.html就能浏览全部游戏,想找某个特定游戏也能通过文件夹名快速定位。
README里我写了三部分:项目简介(一句话说清这是什么)、如何运行(其实就是打开HTML文件)、已知问题列表。已知问题列表我列了五个,都是修复成本较高的,写清楚反而显得专业。
6.2 给每个游戏加一句玩法说明
索引页里每个游戏下面我加了一行说明,写清楚操作方式和核心玩法。比如"贪吃蛇:方向键控制,吃食物变长,撞墙结束"。这一行字看起来不起眼,但能大幅降低别人的理解成本。没有这行字,别人得打开游戏自己摸索;有了这行字,扫一眼就知道要不要点进去。
6.3 开源协议的选择
这批产物我选了MIT协议。原因很简单:这些代码主要是模型生成的,我做的事情是配置、筛选和修复,独创性有限。用MIT协议最宽松,别人想怎么用都行,符合开源社区对这类"工具产物"的预期。
如果你也要开源类似的批量生成产物,我的建议是选宽松协议。因为这类项目的价值在于"数量和多样性",不在于单个游戏的代码质量。宽松协议能让更多人受益,也符合开源精神。
7. 关于token消耗和成本的实际账
7.1 五亿token实际用了多少
七十二个游戏跑完,加上中间的重试和调试,我实际消耗的token大概在一亿两千万左右。平均每个游戏消耗约一百六十万token,这个数字比预想的高,主要原因是有些游戏生成失败后重试了多次,以及部分复杂游戏的输出确实很长。
剩下的三亿多token我没浪费,后来用来做了一些代码解释和文档生成的任务。但就这批游戏而言,一亿两千万的消耗对应七十二个可运行的产物,性价比是相当高的。
7.2 如果按付费算这笔账
假设按标准API价格来算,一亿两千万token的成本大概在几十到一百多块之间(具体取决于模型和计费方式)。七十二个游戏,平均每个游戏成本一两块钱。这个成本对比人工写代码的时间成本,优势非常明显。一个熟练开发者写一个这样的小游戏,怎么也得一两个小时,按人力成本算远不止一两块钱。
当然,这里有个前提:模型生成的代码需要人工筛选和修复。如果算上这部分时间,单个游戏的综合成本会上升。但即便如此,批量生成的效率优势依然存在,因为筛选和修复可以批量化、流程化,而从头写代码不行。
7.3 token额度使用的几个经验
第一,批量任务要留出重试余量。我原本以为五亿token用不完,实际跑下来发现重试消耗比预想的多,所以额度规划要留百分之三十左右的buffer。
第二,不同模型的token消耗差异很大。glm-5.3-flash在代码生成上比较"话少",输出直接是代码,没有多余解释,这能省不少token。如果你用的模型喜欢加解释,消耗会明显上升。
第三,批量任务建议分批跑,不要一次性全发。分批跑的好处是能及时发现系统性问题(比如提示词有歧义导致某类游戏普遍失败),及时调整,避免浪费额度。
8. 这套流水线还能怎么扩展
8.1 扩展到其他类型的代码生成
这套流水线的核心逻辑是"结构化配置加批量API调用加自动落盘",这个逻辑不限于游戏。你可以把配置换成"数据处理脚本"、"爬虫模板"、"API接口示例",同样能批量生成。我后来用同样的思路生成了一批Python数据处理脚本,效果也不错。
关键是要找到那种"有明确输入输出、单个产物规模可控、质量可自动判定"的场景。游戏符合这三个条件,所以适合。如果你的场景里产物质量很难自动判定,那批量生成的价值就会打折扣。
8.2 加入自动测试环节
目前我的流水线里,质量检查还是半自动的。下一步可以加入自动测试:用无头浏览器加载每个游戏,模拟按键操作,检查是否有JavaScript报错、画面是否正常渲染。这样能把初筛的自动化程度再提高一截。
不过自动测试也有局限,它能发现"跑不起来"的问题,但发现不了"能跑但不好玩"的问题。后者还是得靠人工。所以自动测试是辅助,不是替代。
8.3 用模型做代码审查
还有一个有意思的扩展方向:用模型来审查模型生成的代码。具体做法是把生成的代码再发给模型,让它找出潜在的bug和改进点。这个方法我试了几个游戏,确实能发现一些我漏掉的问题,比如未处理的边界情况、可以优化的循环逻辑。
但要注意,模型审查也有误报。它有时候会把正确的代码标记为有问题,或者提出一些不切实际的改进建议。所以模型审查的结果只能作为参考,最终判断还是得靠人。
9. 给想复现这套流程的人几条实在建议
如果你手里也有一批token额度,想复现类似的批量生成项目,我有几条从这次实践中总结的建议。
第一条,先跑通一个再批量。不要一上来就写七十二个的配置,先用一个游戏把整条流水线跑通,确认API调用、格式解析、落盘、索引页都没问题,再扩展到批量。我这次就是先跑通了贪吃蛇,才敢批量铺开。
第二条,提示词里的格式约束要放在最前面,措辞要强硬。模型对开头的内容更敏感,把最重要的约束放前面,执行率明显更高。
第三条,并发数从低往高试。先设三,跑通了再往上加。不要一上来就设十,出了问题你分不清是并发太高还是别的原因。
第四条,落盘模块一定要做完整性检查。截断是批量生成最隐蔽的坑,不做检查你会在一堆"看起来完整"的文件里浪费时间。
第五条,质量筛选要分层。机器初筛、目视批量检查、人工深度试玩,三层下来,既能保证覆盖率,又不会累死自己。
第六条,开源时诚实标注已知问题。不要假装完美,把没修的问题写清楚,反而能建立信任。别人看到你连已知问题都列出来了,会觉得这个项目靠谱。
最后说一句关于token额度的心态。额度多的时候容易贪心,想什么都做。但批量生成的价值不在于"生成了多少",而在于"有多少能真正用起来"。七十二个游戏里,我判断真正质量过关、可以直接拿去用的,大概有五十个左右。这个比例我已经很满意了。与其追求数量上的好看,不如把筛选和修复做扎实,让每个开源出去的产物都对得起别人的时间。