一个完全看不懂的GPU 老项目,Codex 居然真能救场

人生常态就是有时候突然来个紧急需求。

昨天下午,产品经理找到我说,有一批历史音频节目要补字幕,项目已经在服务器上跑了很久,只是我第一次接触。

得,先别管它为什么临到测试前一天才找我,先干吧。

(信息同步是千古难题)

01 脑子一片空白打开项目

我打开目录,先看到几个 Python 文件,然后是 Shell、定时任务、CSV、对象存储和一堆名字差不多的脚本。

最麻烦的是,每个文件单独看好像都认识,放在一起就完全不知道谁先谁后。

如果按我以前的节奏,大概会先读两天代码,再找人确认两天,最后挑一条数据小心翼翼地试。

这次我把整个项目交给 Codex,说得也很直白:我第一次进来,完全不了解,请讲到小白也能听懂。画个 HTML给我。

几分钟后,我第一次看到了这个项目的全貌。

02 我以为只有两个脚本

我最开始的理解特别粗糙:这个项目是不是就两个脚本?

一个负责把音频转成文字,先丢进某个中间存储。

另一个拿着名单,从中间存储里把结果捞出来,再放到最终位置。

Codex 顺着入口函数和上传函数继续找,结果比我想的多一层。

项目里其实有三种走法:日常定时生产、人工直接补字幕、历史 CSV 迁移。

三种脚本最后都能得到字幕,但它们消耗的资源、读取的名单和中间经过的位置并不一样。

这一下解释了我前面很多困惑。

有些脚本会重新跑 Whisper,占用 GPU;有些只是整理现成文本,根本不会碰模型。

03 那个中间存储,到底图什么

我又卡在一个很朴素的问题上:既然字幕最终要放到结果存储,为什么还要多绕一个中间存储?

Codex 把两段代码放在一起解释,我才明白中间存储留下的是模型计算后的原始结果。

后面的发布脚本可以慢慢整理格式、补时间轴、重新上传。

发布哪一步失败了,也不用重新花 GPU 时间把音频再听一遍。

节目名单
↓
查询节目与音频
↓
Whisper 使用 GPU 转写
↓
中间结果存储
↓
整理成最终字幕
↓
最终结果存储

我接着问:那什么时候会出现中间结果已经有了,最终字幕却没有?

答案一下列出了好几个现实情况:发布任务没跑、节目不在那份名单里、CSV 解析失败、上传中断,或者两边格式已经变过。

这类问题以前我可能会盯着代码调试半天,梳理逻辑结构,这次 codex 只花了 1分钟。

04 人工脚本为什么能抄近路

继续看最开始它给我的小白版本说明 HTML文档,我又发现项目里还有一个手工补字幕脚本,它居然可以绕过中间存储。

我第一反应是:那前面的中间存储岂不是多余?

我追问一下,它立马告诉我这是个临时工,它很适合补一条节目,或者临时补一个专辑。但是效率不如主流成批跑得快。日常生产更在乎可恢复和可追踪,所以愿意多保留一层中间结果。

05 第一条命令就翻车了

把链路看明白以后,我挑了一条节目做测试。

命令刚敲下去,马上报错。

ModuleNotFoundError,找不到 faster_whisper。

我当时第一反应是项目缺依赖,甚至开始想要不要装包。

Codex 看完报错,先问我当前在哪个 Python 环境里。

终端前面明晃晃写看 Dase,我之前完全没注意。

我跑了一次 conda 环境列表,果然还有一个专门为 Whisper 准备的环境。

conda env list
conda activate whisper
python -c "import faster_whisper; print('ok')"

切换以后,同一条命令直接往下跑了。

这个坑很小,但如果我当时在 base 里重新安装一套依赖,后面可能会多出一个谁也说不清的环境。

06 我开始追着 Codex 问很笨的问题

项目跑起来以后,我没有突然变成专家。

我只是开始敢问那些以前觉得“是不是太基础了”的问题。

这个参数能不能传多个 ID?最多能传多少?

同一个专辑会跑所有节目吗?已经有字幕的会跳过吗?

GPU 参数写 0,到底是物理卡 0,还是当前可见设备里的第一张?

定时任务里调用的 Shell,又偷偷用了哪个 Python?

我问得越细,Codex 给出的答案就越接近一条可以执行的命令。

它会去找 argparse、add_argument、CUDA_VISIBLE_DEVICES、upload、exists、cron 这些词,再顺着调用往下追。

我第一次发现,不用先学会整个项目,也能问出一个足够具体、可以马上验证的问题。

07 五百个专辑把事情放大了

单条节目跑通后,全量任务终于摆到了桌面上。

CSV 里有500个专辑。

大多数专辑有几十条节目,最多的超过一百条,加起来是一万多条音频。

我一开始想把所有专辑 ID 一次性塞给原脚本,又担心查询太大、日志太乱,中间失败也不好接着跑。

然后我又想在外面包一层 Shell。核心 Python不动,Shell 只负责分批、指定GPU、写日志和失败重跑。这么一想,风险反而比手工粘贴一条超长命令低。

codex 像一位经验丰富资深导师,明确支持了我的第二条想法,帮我分析了优点和缺点。

08 40 分钟 15 条,算完反而冷静

我先让一小批节目跑起来。

40 分钟左右,完成了 15条。

这个速度让我很兴奋,至少说明整条路已经通了。

Codex 顺手帮我算了一下:单卡平均每小时大约二十多条。

再乘上可用 GPU 数量,全量时间大致就有了。

这种带误差的估算,已经足够拿来排机器了。

09 三台机器、五张卡,终于拼起来

我把能用的机器情况一台台补给 Codex。

机器 A 只有一张卡,机器 B 和机器 C 各有两张,项目目录还不一样。

显存这里我又闹了一个小乌龙。

我看到“已用 4361 MiB/总计 15109 MiB”,脱口而出只剩 5 GB。(其实只是随便说了一个余量)

Codex没有盲目听信我的指令,它帮我重新一减,明明还剩十个 GB 左右。

这类低级错误放在脑子里很容易滑过去,写进对话后立刻就能被纠正。

任务分配也没有简单按专辑数量五等分。

因为有的专辑二十条,有的一百多条,按节目总数分才不会让一张卡提前下班,另一张卡还在熬夜。

最后是五个任务组,每张 GPU 对应一个进程,预计工作量几乎齐平。

10 五份脚本真被它写出来了

当机器、目录、GPU、Python 环境和节目统计都给齐以后,Codex 开始直接写脚本。

它没有只给一段示意代码,直接写出了五份可以放到对应机器运行的 Shell。

它把 500个专辑分完,又检查了一遍重复和遗漏。

每份脚本知道自己用哪张 GPU,也知道自己该跑哪些批次。

Python 环境不存在会提前报错,模型库导入失败也会停下来。

某个批次失败时,它会记到日志里,再继续下一个批次。

脚本还留了 START_BATCH 和 END_BATCH,我可以单独补跑某一段。

我给它的是报错、目录和三台机器;它还给我一张数据地图,以及五份能直接运行的脚本。

原本我要手工分名单、数节目、拼参数、检查重复,现在这些机械活一次做完了。

我只需要继续确认服务器上的真实环境,以及有没有别的任务正在占 GPU。

写在最后:Codex 最实用的地方

回头看今天的工作,五份 Shell 当然很省事,但写代码还不是这次最让我惊喜的部分。

我觉得自己今天状态很好,我可以毫无负担地一直追问 codex 关于项目的一切问题。

为什么有中间存储?为什么这个脚本能绕过去?这行日志算完成了吗?这个目录缺文件要紧吗?

现实里找同事问这么细,我多少会担心打断别人,也会怕问题显得太基础。

Codex不会嫌烦。

我给它源码,它帮我找线索;我给它报错,它帮我缩小范围;我给它机器和名单,它把方案拼成脚本。

过去我可能要花几天才敢碰这个项目。

这次一天之内,我已经知道数据怎么走、脚本怎么选、环境怎么切、结果去哪里看。

Codex 又一次成功的救场。

AI 真实的在生产价值,新的时代真的一切都不一样了。


原载:微信公众号「荒岛书生codedoctor」 · 首发:2026-07-24。本文按原稿整理为网页阅读版,保留发表时的产品版本、案例与数据口径。