有一次做批量封面,大家反复说同一句话:“一次做 8 张。”这句话听起来已经很具体了,数量也有了,动作也有了,似乎只差把功能跑起来。但真正开始核对需求时,我发现这 8 张并没有指向同一种结果。
一种理解是:上传 1 张参考图,让系统围绕同一个人生成 8 张候选图,最后从中挑 1 张。另一种理解是:一次上传多张参考图,每张图对应 1 个人,最后每个人只得到 1 张图。两种做法都可以被说成“一次做 8 张”,可它们的输入、人物和输出关系完全不同。
这次沟通里,需求先是“确认一次提交多张参考图,能不能生成不同人物的图片”,后来又专门指出,“一张图生成 8 张”和“多张参考图每人一张”不是同一件事。接着,规则又变得更细:每个人最多先做 1 张,只有质量不稳定或不合格时,才为这个人补做另一张。最后还确认,这两种批量方式以后都会存在。问题到这里才真正露出来:缺的不是一个按钮,而是一套描述数量关系的语言。
同一个数量,可能指向不同的关系
人很容易先听见数量,再忽略数量之间的关系。“做 8 张”说的是输出总数,却没有说明这些输出由什么输入产生,也没有说明输出是否要和某个具体人物绑定。执行者如果只抓住“8”,就会自然地把它翻译成并发数,或者翻译成同一个人的 8 个候选版本。
这也是这次最容易发生的误判。表面上看,任务只是把生成次数从 1 改成 8;实际上,任务可能是在处理 8 个不同的人。前者的核心是同一输入的多样性,后者的核心是输入与人物之间的一一对应。一个是“1 对多”,另一个是“多对多中的一对一分组”。如果不先分清,后面即使代码运行成功,也可能得到完全错误的成品。
批量任务不能只描述“要多少张”,还必须描述“哪一个输入对应哪一个输出”。
我后来会强迫自己把需求拆成 4 个问题:输入有几张,里面有几个人;每个人要几张;输出总数怎么算;失败后是重做这个人,还是重新生成整批。这样一来,“一次做 8 张”就不再是需求,而只是一个待解释的数字。
先固定输入对象,再谈生成数量
第一步不是问系统能不能批量,而是确认输入对象。这里至少有 3 种常见情况。
第 1 种,只有 1 张参考图,目标是为同一个人物生成 N 张候选图。这时输出数量通常是 N,所有结果都属于同一个人,生成后的选择发生在同一组内部。
第 2 种,有 N 张参考图,每张图对应不同人物,目标是每人生成 1 张。这时输出数量仍然可能是 N,但每一张输出必须能追溯到自己的输入,不能把所有参考图混成一个人的素材。
第 3 种,有多张参考图,但每张图并不一定代表 1 个人。有的图可能是人物,有的图可能是服装、场景或风格参考。此时“参考图数量”甚至不能直接等同于“人物数量”。如果把每张图都当成一个人,就会在最开始把分组方式弄错。
因此我会把输入写成一句完整的话:“本次有 8 张参考图,8 张分别对应 8 个人,每个人先生成 1 张。”或者:“本次只有 1 张人物参考图,要为这 1 个人生成 8 张候选。”两句话的数字相同,执行含义却已经被固定下来。
一个人一张,不等于一张图一张
“每个人 1 张”描述的是人物和输出的关系;“每张参考图 1 张”描述的是输入和输出的关系。很多时候两者恰好相同,所以更容易被混用。但它们不是同一个概念。
比如,一个人的参考素材可能有正面、侧面和生活照 3 张。需求可能是用这 3 张图共同生成这个人的 1 张封面。此时是“3 张输入对应 1 个人,最后输出 1 张”。如果把它理解成“每张参考图都生成 1 张”,就会错误地产生 3 张结果。
反过来,也可能有 8 张参考图,确实分别属于 8 个人,要求每人 1 张。这里需要的是 8 个独立的小任务,而不是 1 个任务里让系统自由组合 8 张参考图。输入数量和人物数量相等,只是当前案例里的巧合,不能把它当成永远成立的规则。
这件事让我重新意识到,需求中的名词也需要有归属。“一张”到底修饰参考图、人物,还是输出结果?如果一句话里这 3 个对象没有被分别说出来,数字越明确,误解反而可能越稳定。
质量不稳时,补发也要绑定到人
这次还有一个容易被忽略的边界:每个人最多先做 1 张,只有这一张质量不稳定或不合格时,才为这个人补做另一张。它不是简单地把总数量从 8 改成 16,也不是一开始就给每个人准备 2 个候选。
这里真正的规则是“按人补发”。第 3 个人的结果有问题,只补第 3 个人;第 1、2、4 个人已经合格,就不因为别人失败而重新生成。这样既控制了用量,也保留了已经通过检查的结果。
如果不处理这条关系,最直接的后果是生成数量失控。原本希望 8 个人各有 1 张,最后可能变成每个人 2 张;更糟的是,失败原因和补发结果无法对应,执行者也不知道哪一张是第一次结果,哪一张是质量修复。等到人工挑选时,大家会以为只是“多了几张图”,其实已经丢失了任务边界。
我选择“先每人 1 张,失败再按人补 1 张”,是因为它把质量判断放在第一次结果之后,而且不会让正常的人承担额外生成成本。这个决定也要求结果保存时带上最基本的对应关系:人物编号、初次结果、是否通过、补发结果。没有这些信息,所谓“补发”仍然只是口头规则。
最容易走的错误捷径
最容易误判的做法,是听到“一次做 8 张”就把 8 当成并发数,直接调用原来“一张图生成多张”的流程。这个捷径看起来最快,因为代码可能早就能跑通,参数也只需要改一个数字。但它默认了所有输入和输出是一对多,而这正是尚未确认的部分。
另一个捷径,是看到多张参考图就把它们全部塞进同一个生成任务,期待系统自己理解每张图属于谁。这样做把最重要的分组判断交给了一个不应该负责分组的环节。生成模型也许会给出看起来不错的图片,却不能保证每个人都得到自己的结果,更不能保证结果与输入一一对应。
还有一种相反的过度设计:为了避免歧义,把所有可能的组合都做成复杂开关。界面里出现“输入分组模式、人物模式、候选模式、失败重试模式”等一长串选项,但用户仍然不知道自己该选哪一个。真正要解决的不是增加术语,而是把有限的几种关系用普通话说清楚,再让用户在无法确定时选择。
速度最快的动作,不一定是最快完成任务;如果起点的数量关系错了,后面的自动化只会更快地产出错误结果。
我把需求整理成一张关系卡
后来我形成了一个很简单的数量关系卡。它不需要复杂工具,先在提交前写 4 行话就够了。
第 1 行写输入对象:“有几张参考图,哪些图属于同一个人。”第 2 行写分组规则:“按人物分组,还是按单张参考图分组。”第 3 行写输出目标:“每个人 1 张,还是每个人 N 张候选。”第 4 行写失败补发:“谁失败补谁,还是整批重做。”
如果这 4 行能直接算出输出数量,需求通常已经比较清楚。例如,8 个人、每人先 1 张,预期输出就是 8 张;如果最多允许每人补 1 张,上限是 16 张,但不是默认输出 16 张。又例如,1 个人、1 张参考图、生成 8 张候选,预期输出是 8 张,但 8 张都属于同一个人。
遇到歧义时,我不会继续用一句“你是要哪种”把判断压力推回去,而是给出有限选项:“A:1 张参考图生成 8 张候选;B:8 张参考图分别对应 8 个人,每人 1 张;C:多张图共同对应 1 个人,只生成 1 张;D:先每人 1 张,失败的人再单独补 1 张。”让对方直接选择,或者指出这 4 种之外的关系。
这套方法的价值不在于把所有未来情况都预先做成按钮,而在于把自然语言中的省略暴露出来。一张数量关系卡,应该在付出生成成本之前,先把输入、人物、输出和补发规则锁在同一条线上。
下次我会怎么做
下次再听到“批量做 8 张”,我不会立刻把它转成并发任务。我会先追问 4 个可计算的问题:这 8 张参考图里有几个人?同一个人是否有多张参考图?每个人要 1 张还是要多张候选?质量不稳时补哪一个人,补几次?
如果对方暂时说不清,我就把“一对多”“多对一”“一人一张”“按人补发”这几种关系并排列出来,请对方选定。选定以前,我只做预检和关系确认,不进入真正的生成或消耗用量的动作。
这件事让我重新意识到,很多自动化失败并不是能力不足,而是输入和输出之间少了一根看不见的线。表面上我是在核对图片数量,其实我是在确认每个结果应该对谁负责。真正难的不是让系统一次生成更多,而是让它知道“更多”究竟属于谁。
我更愿意把它看成一种工作习惯,而不是一个技巧:先说清对象,再说清数量;先固定对应关系,再讨论速度;先定义失败后的边界,再决定是否补发。一个流程成熟的标志,不是它能把 8 张图跑出来,而是下一次面对同样的数字时,所有人都能立刻知道这 8 张分别意味着什么。