<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title><![CDATA[闲的蛋疼，更新下上篇故事的前述-一张 12GB 显卡上的 47 小时：一次手术课件项目里被漏掉的那一段]]></title><description><![CDATA[<blockquote>
<p dir="auto">这篇是给 <a href="https://lcz.me/topic/1148">《零代码接单一个月后，我为什么选择止损：一次手术课件 Vibe Coding 项目复盘》</a> 补的一段记录。</p>
</blockquote>
<p dir="auto">那篇复盘是Codex侧（GPT5.6SOL）写的，我在开头留了一句话：<strong>"此文由 GPT5.6SOL 撰写，它缺少了一开始我使用本地 Agent 迭代时候的上下文"</strong>。</p>
<p dir="auto">缺的正是最重要的那一段——项目最开始，把甲方给的云端方案往<strong>一张 12GB 显卡</strong>上落的那 47 小时。那一段的代码、交付包、视频产物、文件时间戳和会话账目都还在机器上，所以下面不是回忆，是可核对的记录。</p>
<hr />
<h2>一、那两天到底要解决什么</h2>
<p dir="auto">甲方给的是一个已经在云端跑通的方案。落到本地只有两个硬约束：</p>
<ol>
<li><strong>一张 3080Ti，12GB 显存</strong>（不是 24G，不是 A100），要跑 LTX-2.3 <strong>22B</strong> 图生视频模型；</li>
<li>交付物很具体：<strong>一个能在 ComfyUI 里跑通的纯官方节点工作流 JSON，加一段手机录制的一键生产过程视频</strong>。</li>
</ol>
<p dir="auto">没有设计文档，没有验收清单，没有"效果达到什么程度算过"。</p>
<p dir="auto">最后这一条，是整件事真正的病根，后面还会回来要账。</p>
<hr />
<h2>二、47 小时里发生了什么</h2>
<p dir="auto">工作窗口是 <strong>7/15 13:10 → 7/17 12:34</strong>，10 个会话。其中出交付包、出成片的密集迭代，是 <strong>7/15 22:58 → 7/16 14:18 那 15.5 小时</strong>。</p>
<ul>
<li><strong>07-15 13:10 起</strong> — 拆解甲方那份带私有节点依赖的工作流，确定它在 12GB 卡上的可行边界。</li>
<li><strong>07-15 22:58</strong> — 第一版可跑通的 JSON（27KB）。</li>
<li><strong>07-15 23:04</strong> — 试了那个"最优雅"的方案：用 ComfyUI 的 List 隐式循环，一条工作流跑完 6 个场景再合并。<strong>当天就被实测否掉了</strong>（原因见第四节第一条）。</li>
<li><strong>07-15 23:27 — V2：改架构。</strong> 放弃"在画布内部做统一管线"，改成「外部 Python 调度器 + 单场景模板」。</li>
<li><strong>07-16 00:23 / 00:51</strong> — V3（显存优化）、V4（首次完整无 OOM 跑通），三个交付包（v2/v3/v4）在 90 分钟内连发。</li>
<li><strong>07-16 02:44</strong> — V3 实测。这一次会话跑了 916 条消息、455 次工具调用。</li>
<li><strong>07-16 10:00–11:13</strong> — V4 实测：首次产出完整合成片（1.05MB / 36.5 秒）。</li>
<li><strong>07-16 12:05–14:18</strong> — V5：加"四级裁图链"，出移交文档，成片 1.16MB。</li>
<li><strong>07-17 00:25</strong> — 补超分链（384×288 → 高清）。</li>
<li><strong>07-17 12:34</strong> — 甲方真正在意的那个要求第一次露头："<strong>识别缝线范围</strong>"。</li>
</ul>
<p dir="auto"><strong>交出的是：一份能跑的产线 + 一段合成好的课件动画。</strong></p>
<hr />
<h2>三、那几天换了多少模型？账目在这里</h2>
<p dir="auto">复盘里记得"换了好几个模型"。会话库把这件事记成了数字。</p>
<p dir="auto"><strong>整个 7 月到 8 月，本地 Agent 侧真实调用过的模型共 13 条记录（跨 provider，9 个模型族）</strong>：gemini-pro-agent、gemini-3-flash-agent、gemini-3.6-flash(-high)、claude-sonnet-4-6、deepseek-v4-pro、deepseek-v4-flash、glm-5.2（两个 provider）、grok-4.3、grok-3-mini-fast。</p>
<p dir="auto">而<strong>这一支</strong>（7/15–7/17，10 个会话）实际落在 3 个模型上：</p>
<ul>
<li><code>gemini-pro-agent</code> — 1,178 次调用 / 938.8 万 token</li>
<li><code>gemini-3-flash-agent</code> — 429 次调用 / 472.8 万 token</li>
<li><code>deepseek-v4-pro</code> — 49 次调用 / 9.8 万 token</li>
</ul>
<p dir="auto"><strong>合计：2,684 条消息，1,656 次 API 调用，1,421 万 token，记录的现金成本 0 元。</strong></p>
<p dir="auto">这段账目最有价值的地方，不是数字，是它证明了一件事：</p>
<blockquote>
<p dir="auto"><strong>换了这么多模型，没有换掉任何一条失败原因。</strong></p>
</blockquote>
<p dir="auto">第四节那 7 条坑，逐条追溯，没有一条跟"模型不够聪明"有关：</p>
<ul>
<li>List 隐式循环失效，是 ComfyUI 的节点语义问题；</li>
<li>6 张图被拍扁成一个 batch，是工作流的拓扑问题；</li>
<li>VLM 返回坐标格式漂移，用云端模型还是本地模型都一样，缺的是容错代码；</li>
<li>384×288 / 12fps，是 12GB 显存算出来的上限；</li>
<li>验收标准没定义，那是流程，不是模型。</li>
</ul>
<p dir="auto"><strong>换模型是当时最容易做、也最没用的一件事。</strong> 那 47 小时里真正起作用的那次动作（V2 改架构），跟模型毫无关系。</p>
<hr />
<h2>四、技术上有用的部分</h2>
<p dir="auto"><strong>1. ComfyUI 的 List 隐式循环，在定制节点上会失效。</strong></p>
<p dir="auto">理论上往下游塞一个 List 会触发隐式循环，但工作流里的缩放/视频节点内部把 List 拍扁成了 batch=6。表现是耗时 <strong>167 秒</strong>（正好等于一次生成的时间），而且 6 张图被强行杂糅——模型开始脑补：第一次生出一个<strong>戴着白色眼罩的女人</strong>，把医学线稿图像海盗眼罩一样糊在眼睛上；改掉提示词重跑，它又脑补出一个<strong>穿白 T 恤的男人</strong>。</p>
<blockquote>
<p dir="auto"><strong>模型看到的不是"六张图"，是"一帧"。</strong> 要把一张线稿动起来，就得一张一张喂——"批量"这个动作必须由画布外面的调度器来做。</p>
</blockquote>
<p dir="auto">这也是 V2 那次架构掉头的直接原因，而这次掉头是那 47 小时里唯一被后续验证为正确的判断：<strong>画布上永远只有一个场景的模板，复杂度全部关在 Python 里</strong>。结果是 6 个场景在 12GB 卡上连续跑完、零 OOM。</p>
<p dir="auto"><strong>2. VLM 给的坐标不可信，但可用。</strong></p>
<p dir="auto">实际跑通的是"VLM 出坐标 + 程序做后处理"：VLM 会把 <code>1</code> 写成 <code>"Scene 1"</code>，bbox 字段名会漂（<code>ymin</code> / <code>top</code>），偶尔还嵌套数组；加了 8% 边距扩展之后又出现负值越界，导致 OpenCV 保存空图直接崩。</p>
<blockquote>
<p dir="auto"><strong>把它当"不稳定的专家建议"，不要当结构化 API。</strong></p>
</blockquote>
<p dir="auto"><strong>3. 裁图最终是四级兜底链</strong>：CV 自适应（5 档阈值 + NMS 合并）→ VLM 统一检测 + 场景映射 → VLM 传统裁图 → 硬编码坐标。低对比度扫描件上 CV 会整体失效，所以必须能一键降级到人工坐标。</p>
<p dir="auto"><strong>4. 甲方的工作流带私有节点依赖</strong>（<code>329:xxx</code> 形式的引用、XB 系列、ROCm 补丁、sageattention）。最后决定<strong>全剔除，只留官方节点 + GGUF 加载器</strong>——牺牲一点画质，换"能在任何一台干净机器上装起来"。</p>
<p dir="auto"><strong>5.</strong> <code>wait_for_completion</code> 只检查 <code>gifs/</code> 目录，而视频产物落在 <code>videos/</code> 里，脚本永远等不到结果。</p>
<p dir="auto"><strong>6.</strong> 帧数没有注入 <code>EmptyLTXVLatentVideo</code>，出来的视频长度和场景对不上。</p>
<p dir="auto"><strong>7.</strong> 高频重试会让 <code>/free</code> 返回 500，显存疑似没完全释放——12GB 跑 22B 时的常态，只能靠控制并发躲开。</p>
<hr />
<h2>五、结束时留下的硬数据</h2>
<ul>
<li><strong>代码</strong>：6 个 Python 文件 / <strong>1,186 行</strong>（编排 131 + 裁图 311 + VLM 检测 473 + 提交 136 + 解析 118 + 合并 17）</li>
<li><strong>工作流模板</strong>：<strong>19 个节点</strong>，纯官方节点 + GGUF 加载器</li>
<li><strong>渲染参数</strong>：配置 384×256（实际输出 384×288，LTX 按 32 对齐）/ 20 steps / 12 fps / VAE 分块 128 / UNet 换出 96 块 / NAG 8.0</li>
<li><strong>最终成片</strong>：<strong>384×288 / 12fps / 36.5 秒 / 438 帧 / h264</strong></li>
<li><strong>交付包</strong>：4 个（最小的 5.6KB）；工作区总占用 <strong>约 7.5MB</strong></li>
</ul>
<p dir="auto">对照原文里的后期数据（工作区 62GB / 269 个文件 / 115,875 行 / 101 个审计目录 / V17 约 50GB）：</p>
<blockquote>
<p dir="auto"><strong>阶段零用 1,186 行、7.5MB 工作区，把片子做出来了；后期用 115,875 行、62GB 工作区，过不了验收。</strong></p>
</blockquote>
<p dir="auto">这不是模型变笨了，是流程变了。</p>
<hr />
<h2>六、没解决的四个问题（照实列）</h2>
<ol>
<li>裁图坐标仍偏紧（8% 边距不够，应提到 12–15%）；</li>
<li>CV 投影法兜底没实现，当时只存在于讨论里；</li>
<li>VLM 会把页脚误检成第 6 个子图；</li>
<li><strong>384×288 / 12fps 是这张卡的上限</strong>——不是审美选择，是显存算出来的。要 1920×1080 / 30fps，只能换卡或多卡。</li>
</ol>
<hr />
<h2>七、这段记录唯一的新增结论</h2>
<p dir="auto">那 47 小时交出去的东西是**"能跑通"**：产线跑得动、片子出得来、工作流能在别人的机器上装起来。</p>
<p dir="auto">交不出去的东西，是甲方真正要的**"手术逻辑正确性"<strong>——它在 7/17 才第一次以"识别缝线范围"的形式出现，而且</strong>从头到尾没有被写成一条可判定的验收条件**。当时的对话里，没有一句话是"什么样的画面算通过"。</p>
<p dir="auto">开工前我没有把验收条件钉死，这是我的责任。后果就是复盘里那一段：需求只能以"我觉得不对"的形式反复出现；而它每出现一次，当下唯一能做的事就是——<strong>再加一道检查</strong>。检查越来越严，产出越来越远。</p>
<p dir="auto">如果这个项目重来一次，先写下这五行，再动第一行代码：</p>
<pre><code>验收条件（化整为零，逐条可判）：
1. 输入：一张扫描件 + 一份 Markdown → 输出 6 段场景视频 + 1 段合成片
2. 尺寸 / 帧率：___（阶段零实测：384×288 / 12fps 是 12GB 卡的上限）
3. 每帧必须与对应子图"同构"：无新增解剖结构、无新增文字、无人物出现
4. 关键步骤顺序：与 Markdown 的 6 个场景一一对应（顺序错 = 不通过）
5. 修改轮次：___ 轮以内；超出即重新评估范围或终止
</code></pre>
<p dir="auto">第 3 条就是"手术逻辑正确性"的可判定版本——它不需要人去"感觉对不对"，只要拿原图逐帧点一遍。<strong>如果第一天就有这五条，"感觉不对"最多只能推翻一次。</strong></p>
<p dir="auto">顺带一句：那套后来一路加到 v4 的质检门，<strong>不是被设计进来的</strong>。7/17 的对话里它已经被明确拒绝过一次——"我们不需要 qa 系统，只需要把视觉模型提供接口出来给外部调用就行"。它是在没人写下验收条件的情况下，被"每次觉得不对就加一道检查"的惯性，一次一道，慢慢长出来的。</p>
<hr />
<p dir="auto"><strong>结语</strong></p>
<p dir="auto">那 47 小时里，我在做的事情是"把东西跑通"，那是该做的部分。</p>
<p dir="auto">真正让这个项目亏钱的，不是模型（换了 13 个都没用）、不是 12GB 显存、也不是谁写的提示词，而是<strong>从头到尾没有一个人把"通过"这个词定义成一句可以判定的话</strong>。</p>
<p dir="auto">所以，补上那段被漏掉的记录之后，我想说的其实只有一句：</p>
<blockquote>
<p dir="auto"><strong>动手写第一行代码之前，先写下"什么叫做完"。那是最便宜的保险。</strong></p>
</blockquote>
<hr />
<p dir="auto"><em>本文是 <a href="https://lcz.me/topic/1148">《零代码接单一个月后，我为什么选择止损》</a> 的补记。所有数字来自本地产物时间戳、ffprobe 实测与会话账目。</em></p>
]]></description><link>https://lcz.me/topic/1793</link><generator>RSS for Node</generator><lastBuildDate>Fri, 25 Sep 2026 21:28:12 GMT</lastBuildDate><atom:link href="https://lcz.me/topic/1793.rss" rel="self" type="application/rss+xml"/><pubDate>Fri, 18 Sep 2026 03:58:02 GMT</pubDate><ttl>60</ttl><item><title><![CDATA[Reply to 闲的蛋疼，更新下上篇故事的前述-一张 12GB 显卡上的 47 小时：一次手术课件项目里被漏掉的那一段 on Fri, 18 Sep 2026 05:49:24 GMT]]></title><description><![CDATA[<p dir="auto">我好像有折腾过。。。。<a href="https://github.com/karuvanan/LTX-2.3-i2v-Enhanced_Prompt-webui-comfyui-connector" rel="nofollow ugc">https://github.com/karuvanan/LTX-2.3-i2v-Enhanced_Prompt-webui-comfyui-connector</a></p>
]]></description><link>https://lcz.me/post/19014</link><guid isPermaLink="true">https://lcz.me/post/19014</guid><dc:creator><![CDATA[imbiplaza ASUS]]></dc:creator><pubDate>Fri, 18 Sep 2026 05:49:24 GMT</pubDate></item></channel></rss>