<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
  <channel>
    <title>多模态 on 方糖猫Blog</title>
    <link>https://ftmao.com/blog/tags/%E5%A4%9A%E6%A8%A1%E6%80%81/</link>
    <description>AI 视频、AI Agent 与工程实践笔记</description>
    <generator>Hugo</generator>
    <language>zh-CN</language>
    <lastBuildDate>Fri, 28 Aug 2026 10:00:00 +0800</lastBuildDate><atom:link href="https://ftmao.com/blog/tags/%E5%A4%9A%E6%A8%A1%E6%80%81/index.xml" rel="self" type="application/rss+xml" /><item>
      <title>Netflix MAPS 笔记：让推荐模型「看见」素材，冷启动就不冷了</title>
      <link>https://ftmao.com/blog/posts/netflix-maps-multimodal-personalization/</link>
      <pubDate>Fri, 28 Aug 2026 10:00:00 +0800</pubDate>
      <guid>https://ftmao.com/blog/posts/netflix-maps-multimodal-personalization/</guid>
      <description>&lt;h1 id=&#34;netflix-maps-笔记让推荐模型看见素材冷启动就不冷了&#34;&gt;Netflix MAPS 笔记：让推荐模型「看见」素材，冷启动就不冷了&lt;/h1&gt;
&lt;blockquote&gt;
&lt;p&gt;原文：&lt;a href=&#34;https://netflixtechblog.com/maps-netflixs-multimodal-asset-personalization-at-scale-32f96320785e&#34;&gt;MAPS: Netflix&amp;rsquo;s Multimodal Asset Personalization at Scale&lt;/a&gt;
目标读者：做推荐、搜推广或 AI 应用的工程师，尤其是被冷启动、离线线上不一致折磨过的人。
阅读目标：搞清楚 Netflix 怎么用多模态向量把素材个性化的冷启动问题「绕」过去，以及那套消融实验和代理任务的方法论为什么值得抄。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;hr&gt;
&lt;h2 id=&#34;问题本身素材是个不透明的-id&#34;&gt;〇、问题本身：素材是个不透明的 ID&lt;/h2&gt;
&lt;p&gt;Netflix 把海报、视频预览这些视觉线索统称为素材（asset），给每个会员挑哪张海报，本身就是一个个性化问题。老模型回答「老标题挑哪张图」回答得很好，但「新标题刚上线怎么办」回答得很差：模型只从历史交互里学习，每张素材在它眼里只是一个不透明的 ID，图里画了什么人、什么色调，它一概看不见。于是新剧上线时素材没有任何历史，只能加大探索流量去「刷数据」，其余时候退回人气启发式——完全不认你的口味。这就是教科书式的冷启动。&lt;/p&gt;
&lt;p&gt;原文的解法一句话：&lt;strong&gt;让模型看见并听见它要推荐的东西&lt;/strong&gt;。新素材一到手就有向量，而向量空间已经承载了会员对相似素材的偏好，所以个性化在接近上线的那一刻就能启动，不用等交互慢慢堆出来。&lt;/p&gt;
&lt;h2 id=&#34;一海报个性化让模型看图&#34;&gt;一、海报个性化：让模型看图&lt;/h2&gt;
&lt;p&gt;做法直接到近乎朴素：用预训练的 CLIP 把每张海报编码成一个 768 维向量，和素材原有的可学习 ID 向量&lt;strong&gt;拼接&lt;/strong&gt;，作为素材的最终表示。就这一个改动。&lt;/p&gt;
&lt;p&gt;效果的关键在于迁移：会员对「某位喜剧演员的脸」「某种配色」的偏好，本来写在图片向量空间里而不是绑死在素材 ID 上，所以新剧海报一编码完，这些偏好立刻生效——哪怕这张图从没给任何人展示过。冷启动从盲区变成了「向量空间对此早有意见」。&lt;/p&gt;
&lt;h2 id=&#34;二五个模型合成一个&#34;&gt;二、五个模型合成一个&lt;/h2&gt;
&lt;p&gt;第二个收益更工程化。同一部剧的海报要铺到五个画布上（billboard、vertical-box、horizontal-panel、short-panel、landscape-panel），裁剪比例各不相同。ID 时代的模型不知道这些裁剪图是同一幕戏，信号无法在画布之间流动，于是历史上每个画布各训一个模型，各自承受各自的冷启动。&lt;/p&gt;
&lt;p&gt;CLIP 向量对裁剪、缩放、宽高比基本不变，同一幕戏的五个版本映射到几乎同一个向量——壁垒没了，五个模型合成一个，高流量画布学到的偏好立刻灌溉稀疏画布。收益最大的恰恰正是数据最少的画布。&lt;/p&gt;
&lt;p&gt;合并带来一个新问题：五个画布的曝光量天差地别，直接按原始计数混训，高流量画布和高频交互类型会淹没一切，本想帮扶的稀疏画布反而最吃亏；手工调权重又换来一堆拍脑袋超参。Netflix 的做法是&lt;strong&gt;奖励加权&lt;/strong&gt;：每条训练样本按其交互类型的长期奖励分（来自 Netflix 既有的长期奖励建模）加权。交互类型在各画布分布不均，按长期价值加权之后，画布配比自动重平衡——画布按「它驱动的交互的长期价值」贡献梯度，而不是按曝光量。没有手工权重，模型优化目标从「最高频的短期动作」换成了「长期会员满意度」。&lt;/p&gt;
&lt;div class=&#34;code-block&#34;&gt;
    &lt;button class=&#34;code-copy&#34; type=&#34;button&#34; hidden aria-label=&#34;Copy code to clipboard&#34;&gt;
      &lt;span class=&#34;code-copy-label&#34; aria-hidden=&#34;true&#34;&gt;Copy&lt;/span&gt;
    &lt;/button&gt;
    &lt;pre tabindex=&#34;0&#34;&gt;&lt;code class=&#34;language-mermaid&#34; data-lang=&#34;mermaid&#34;&gt;flowchart TD
    IMG[&amp;#34;新海报上线&amp;#34;] --&amp;gt; CLIP[&amp;#34;CLIP 图像编码器&amp;lt;br/&amp;gt;输出 768 维向量&amp;#34;]
    ID[&amp;#34;素材 ID 向量&amp;#34;] --&amp;gt; CONCAT[&amp;#34;拼接成素材表示&amp;#34;]
    CLIP --&amp;gt; CONCAT
    CONCAT --&amp;gt; MODEL[&amp;#34;统一模型&amp;lt;br/&amp;gt;五个画布共享&amp;#34;]
    HOT[&amp;#34;高流量画布&amp;lt;br/&amp;gt;billboard 等&amp;#34;] --&amp;gt;|&amp;#34;交互信号沿向量空间迁移&amp;#34;| MODEL
    MODEL --&amp;gt;|&amp;#34;长期奖励加权混训&amp;#34;| SPARSE[&amp;#34;稀疏画布直接受益&amp;lt;br/&amp;gt;short-panel 等&amp;#34;]
    style MODEL fill:#fff3cd
    style SPARSE fill:#e8f5e9&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;&lt;h2 id=&#34;三离线评估ips-与探索流量&#34;&gt;三、离线评估：IPS 与探索流量&lt;/h2&gt;
&lt;p&gt;这套结果能信，前提是评估干净。用当前线上策略的日志评估新模型是有偏的：线上策略偏爱某些素材，日志记录的是「策略选了什么」，不是「会员从全集里会选什么」。和线上策略意见不合的新模型会被冤枉——它会挑的曝光在日志里几乎不存在。&lt;/p&gt;
&lt;p&gt;Netflix 用一小股&lt;strong&gt;随机探索流量&lt;/strong&gt;做 IPS（逆倾向评分）：随机策略按已知分布在候选素材里采样，倾向分在服务时刻精确记录，而不是事后估计。每条观测按倾向分的倒数加权，被探索流量压稀的曝光得到相应抬升，得到候选策略的无偏奖励估计。原文有句话值得划线：&lt;strong&gt;倾向分由构造保证已知而非事后建模，是离线数字能跟踪线上结果的最大单一原因。&lt;/strong&gt; 候选模型必须在 IPS（相对线上基线的比值）上先赢，才配拿 A/B 流量。&lt;/p&gt;
&lt;h2 id=&#34;四消融实验两个成分缺一不可&#34;&gt;四、消融实验：两个成分缺一不可&lt;/h2&gt;
&lt;p&gt;「图片向量」和「模型合并」两个想法捆在一起，Netflix 分开消融，对照老的五模型系统：V1 只加图片向量（仍是五个画布模型），V2 只合并（统一模型但纯 ID），V3 两者都要。离线指标上 ±1% 以内不算显著，V1、V2 单独做基本都在噪声带里；线上全平台跑了至少四周的 A/B 给出更清楚的分界线：&lt;strong&gt;V1、V2 双双不显著，只有 V3 拿到统计显著的提升&lt;/strong&gt;——V3 就是今天线上跑的版本。&lt;/p&gt;
&lt;p&gt;原因也讲得透：V1 告诉单画布模型素材长什么样，但稀疏画布样本太少，教不会它怎么用这条信息；V2 数据够了，但全是 ID 信号，新素材没有。V3 两者兼有，成熟画布教会共享模型「CLIP 向量如何映射到会员偏好」，这个映射直接迁移到稀疏画布。效果是相乘不是相加——V3 在 short-panel 上的提升（5.691%）超过 V1 与 V2 之和。原文的教训写得很直白：&lt;strong&gt;下结论「内容特征没用」之前，先找第二个阻塞因子。&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;真实考验来自产品侧：Netflix 十年来最大的电视首页改版，让 short-panel 一夜之间成为主战场——即将吃下最多曝光的画布恰好历史数据最少。V3 赶在改版前上线，配合一个月的 holdback A/B，核心发现指标和播放时长双双显著增长，且增幅比稳态消融更大。&lt;/p&gt;
&lt;h2 id=&#34;五查询感知的海报排序&#34;&gt;五、查询感知的海报排序&lt;/h2&gt;
&lt;p&gt;浏览时你的长期口味是对的信号，搜索时不是：搜某个演员时你要的是带他的海报，哪怕你的广义口味另有指向。搜索页的意图写在 query 里，海报应当响应它。&lt;/p&gt;
&lt;p&gt;因为 CLIP 把文本和图像投进了同一个向量空间，这件事近乎白送：直接算 query 的文本向量与素材图像向量的余弦相似度，和原有个性化分数按权重 α（0 到 1，线上 A/B 调）混合。第一项是「我们认为你喜欢什么」，第二项是「你刚开口要什么」。没有任何额外建模——向量本来就在素材表示里，排序时加一个相似度项而已。&lt;/p&gt;
&lt;h2 id=&#34;六视频预览mediafm&#34;&gt;六、视频预览：MediaFM&lt;/h2&gt;
&lt;p&gt;视频预览比静态图难：吸引力来自运动、节奏、对白、配乐，单帧说不清。第一版内容感知方案 SeqCLIP 只取各帧的 CLIP 向量求平均——看得见长相，听不见声音，而对白和音乐恰恰扛着预览片的大半调性。&lt;/p&gt;
&lt;p&gt;补全这块的是 MediaFM，Netflix 第一个自研多模态地基模型，在 8000 万个镜头（shot）上训练，每个镜头融合三路信号成一个向量：视觉走 SeqCLIP，音频走预训练语音音频编码器，文本是字幕经大规模文本模型编码。接入方式和 CLIP 一样：把向量拼进素材表示，不需要新基建。&lt;/p&gt;
&lt;p&gt;离线 IPS 和五周全平台 A/B 给出一致的排序：&lt;strong&gt;MediaFM ＞ SeqCLIP ＞ 纯 ID&lt;/strong&gt;，每加一层内容感知都有收益，TV 端收益最大。音频和定时文本是 SeqCLIP 这类纯视觉编码器够不到的，这部分增量是真的。MediaFM 已作为默认视频预览向量全平台上线。&lt;/p&gt;
&lt;div class=&#34;code-block&#34;&gt;
    &lt;button class=&#34;code-copy&#34; type=&#34;button&#34; hidden aria-label=&#34;Copy code to clipboard&#34;&gt;
      &lt;span class=&#34;code-copy-label&#34; aria-hidden=&#34;true&#34;&gt;Copy&lt;/span&gt;
    &lt;/button&gt;
    &lt;pre tabindex=&#34;0&#34;&gt;&lt;code class=&#34;language-mermaid&#34; data-lang=&#34;mermaid&#34;&gt;flowchart LR
    subgraph FM[&amp;#34;MediaFM 多模态地基模型&amp;lt;br/&amp;gt;8000 万镜头训练&amp;#34;]
        V[&amp;#34;视觉&amp;lt;br/&amp;gt;SeqCLIP 帧向量平均&amp;#34;] --&amp;gt; FUSE[&amp;#34;融合成镜头级向量&amp;#34;]
        A[&amp;#34;音频&amp;lt;br/&amp;gt;预训练语音音频编码器&amp;#34;] --&amp;gt; FUSE
        T[&amp;#34;文本&amp;lt;br/&amp;gt;字幕经大规模文本模型&amp;#34;] --&amp;gt; FUSE
    end
    FUSE --&amp;gt; STORE[&amp;#34;Embedding Store&amp;lt;br/&amp;gt;训练与推理同源 无偏斜&amp;#34;]
    STORE --&amp;gt; PROBE[&amp;#34;线性探针代理任务&amp;lt;br/&amp;gt;仅凭向量预测去偏人气赢家&amp;#34;]
    PROBE --&amp;gt;|&amp;#34;跑赢随机猜测才放行&amp;#34;| AB[&amp;#34;离线 IPS + 线上 A/B&amp;lt;br/&amp;gt;MediaFM ＞ SeqCLIP ＞ 纯 ID&amp;#34;]
    style PROBE fill:#fff3cd&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;&lt;h2 id=&#34;七便宜地挑向量线性探针&#34;&gt;七、便宜地挑向量：线性探针&lt;/h2&gt;
&lt;p&gt;新向量层出不穷，端到端试验太贵——数据工程、重训、数周 A/B 流量，不可能每个候选都走全程。Netflix 用一个便宜问题把漏斗口收窄：&lt;strong&gt;仅凭内容向量，能不能预测一个朴素无个性化策略下哪张素材会赢？&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;做法：固定一批标题，用探索数据按倾向分去偏后找出每个标题的人气赢家，打成二值标签；然后只用一个线性探针从素材向量恢复这个标签（标准二值交叉熵），不带标题、演员等任何元数据。保持线性和纯向量是刻意的——它隔离出「人气驱动因子有多少真的编码进了向量」。向量若抓住了人气的语义驱动，线性分类器就该能认出赢家；抓不住，探针就和随机猜测一样，而后者正是它的及格线。&lt;/p&gt;
&lt;p&gt;这个探针先把一大批候选剪到两个决赛选手（SeqCLIP 和最强 MediaFM 变体），再送全程评估。三条信号——探针准确率、离线 IPS、线上 A/B——对两个选手的排序完全一致，所以现在每个 MediaFM 新版本发布前都得先过探针这一关。&lt;/p&gt;
&lt;h2 id=&#34;八embedding-store让一切成立的地基&#34;&gt;八、Embedding Store：让一切成立的地基&lt;/h2&gt;
&lt;p&gt;所有向量——CLIP、SeqCLIP、MediaFM——都活在 Netflix Embedding Store 里（Netflix AI Platform 的组件）。地基模型把原始素材编码成向量只做一次，Store 用同一接口喂给所有下游；关键性质是&lt;strong&gt;训练时和在线推理时服务的是完全相同的向量&lt;/strong&gt;，模型学到的和线上见到的之间没有 skew。&lt;/p&gt;
&lt;p&gt;另一个性质是解耦：新向量（或老向量的新版本）注册、回填、验证全部独立进行，不碰任何消费方的训练和推理代码，下游靠配置即可启用。CLIP 进海报模型、同一批向量撑起查询感知排序、MediaFM 滚进视频预览模型，各自是独立变更而不是跨团队迁移。下一步目标是把 Store 推向图文视频统一的语义空间，做跨模态检索和跨界面统一排序。&lt;/p&gt;
&lt;h2 id=&#34;工程实践联想&#34;&gt;工程实践联想&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;冷启动的最优解常常是换表示，不是加探索。&lt;/strong&gt; 探索流量和人气回退都是在「ID 无知」的框架里打补丁；一旦实体有了内容向量，偏好沿向量空间迁移，问题在表示层就消掉了。做实体冷启动（新商品、新文档、新用户）时先问：这个实体有没有一个下游模型读得懂的内容表示。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;「特征没用」往往是因为别处先堵着。&lt;/strong&gt; V1 的失败不是图片向量没信息，是稀疏画布样本不够教模型用；V2 的失败不是合并不对，是 ID 信号对不上新素材。多因素实验里单变量不显著，先怀疑第二个阻塞因子，别急着枪毙特征。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;评估体系的纯度比模型重要。&lt;/strong&gt; IPS 能跟踪线上结果，靠的是倾向分在服务时刻由构造已知——日志里事后估出来的倾向分自带一层建模误差。值得为评估专门留一股随机探索流量，这笔钱花在刀刃上。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;用廉价代理任务给昂贵实验把关。&lt;/strong&gt; 线性探针 + 随机基线，成本几乎为零，却和端到端 A/B 给出了一致排序。任何「候选方案多、全量验证贵」的场景（选向量、选特征、选模型结构）都该先架一道这样的探针。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;向量服务要当成基础设施来建。&lt;/strong&gt; 训练推理同源、版本注册回填独立、下游配置即用——这三条让「换向量」从跨团队项目降级为一次配置变更。Embedding Store 这类组件才是多模态落地真正的护城河，模型本身反而不是。&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id=&#34;本篇小结&#34;&gt;本篇小结&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;问题&lt;/strong&gt;：素材个性化的冷启动——老模型把素材当不透明 ID，新素材只能靠探索流量和人气启发式硬扛。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;海报&lt;/strong&gt;：CLIP 768 维向量拼接 ID 向量，偏好沿向量空间即时迁移；五个画布模型合并为一个，混训按交互类型的长期奖励分加权，画布按长期价值而非曝光量贡献。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;评估&lt;/strong&gt;：专门探索流量 + IPS，倾向分服务时刻已知，离线数字才跟得上线上。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;消融&lt;/strong&gt;：V1（仅向量）、V2（仅合并）线上均不显著，V3（两者兼有）显著胜出，short-panel 提升 5.691% 且超过 V1+V2 之和；电视首页改版实战中 holdback A/B 证实收益更大。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;搜索&lt;/strong&gt;：query 文本向量与素材图像向量的余弦相似度，按 α 与个性化分数混合，零额外建模。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;视频&lt;/strong&gt;：MediaFM（8000 万镜头，视觉+音频+文本三模态）＞ SeqCLIP ＞ 纯 ID，TV 端收益最大，已全平台默认上线。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;方法论&lt;/strong&gt;：线性探针代理任务廉价筛选向量，三条信号排序一致后成为 MediaFM 发版门禁；Embedding Store 保证训练推理同源、解耦上下游。&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;参考资料&#34;&gt;参考资料&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://netflixtechblog.com/maps-netflixs-multimodal-asset-personalization-at-scale-32f96320785e&#34;&gt;MAPS: Netflix&amp;rsquo;s Multimodal Asset Personalization at Scale&lt;/a&gt;（原文，Netflix TechBlog）。&lt;/li&gt;
&lt;li&gt;Radford et al., &amp;ldquo;Learning Transferable Visual Models From Natural Language Supervision&amp;rdquo;（CLIP 原始论文，文中海报向量与图文共空间的来源）。&lt;/li&gt;
&lt;li&gt;Netflix TechBlog 关于长期奖励建模（long-term reward modeling）与 Netflix AI Platform / Embedding Store 的相关文章（原文内引用，用于奖励加权与向量基础设施）。&lt;/li&gt;
&lt;/ul&gt;
</description>
    </item>
    <item>
      <title>AI 工程师的 Prompt 工程：不是玄学，是工程实践</title>
      <link>https://ftmao.com/blog/posts/prompt/</link>
      <pubDate>Mon, 23 Mar 2026 19:00:00 +0800</pubDate>
      <guid>https://ftmao.com/blog/posts/prompt/</guid>
      <description>&lt;h1 id=&#34;ai-工程师的-prompt-工程不是玄学是工程实践&#34;&gt;AI 工程师的 Prompt 工程：不是玄学，是工程实践&lt;/h1&gt;
&lt;blockquote&gt;
&lt;p&gt;很多人觉得 Prompt Engineering 就是&amp;quot;怎么跟 AI 说话&amp;quot;，甚至有人把它当成玄学。但在工程实践中，&lt;strong&gt;Prompt 本质上是在设计人与大模型之间的接口协议&lt;/strong&gt;，是 LLM 应用的核心代码之一，需要版本管理、回归测试、性能评估。这篇文章结合两个真实项目——AI 视频生成管线（方糖猫 / GeekCast Engine）和一套我开发的 AI 结对编程 Prompt 规则库（keframework-aidev-promptkit）——分享沉淀下来的 Prompt 工程方法。不罗列模板，只讲可落地、可评估、可迭代的系统能力。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;hr&gt;
&lt;h2 id=&#34;一prompt-是接口不是提示语&#34;&gt;一、Prompt 是接口，不是提示语&lt;/h2&gt;
&lt;p&gt;很多团队把 Prompt 写在代码的某个字符串里，或者放在在线编辑器的临时文本框里调试。这种方式在小原型阶段没问题，但一旦进入生产环境，就会暴露出三个问题：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;不可追溯&lt;/strong&gt;：某个版本上线后效果变差，你不知道是哪一句提示被改了。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;不可回归&lt;/strong&gt;：更新模型或调整业务逻辑后，旧用例是否还成立？没人说得清。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;不可协作&lt;/strong&gt;：产品、运营、工程师各自改一版，最后没人能说出&amp;quot;正确版本&amp;quot;是什么。&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;所以在 AI 应用里，Prompt 的地位等同于传统代码：&lt;/p&gt;
&lt;table&gt;
	&lt;thead&gt;
			&lt;tr&gt;
					&lt;th&gt;传统代码&lt;/th&gt;
					&lt;th&gt;Prompt&lt;/th&gt;
			&lt;/tr&gt;
	&lt;/thead&gt;
	&lt;tbody&gt;
			&lt;tr&gt;
					&lt;td&gt;需要版本控制&lt;/td&gt;
					&lt;td&gt;需要版本控制&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;需要测试&lt;/td&gt;
					&lt;td&gt;需要回归测试&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;需要 Code Review&lt;/td&gt;
					&lt;td&gt;需要效果 Review&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;会引入 Bug&lt;/td&gt;
					&lt;td&gt;会引入幻觉、格式错误&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;有架构分层&lt;/td&gt;
					&lt;td&gt;也有分层（系统规则 / 模式规则 / 领域规范）&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;有 CI/CD&lt;/td&gt;
					&lt;td&gt;有评测集 + 回归流水线&lt;/td&gt;
			&lt;/tr&gt;
	&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;更进一步，可以把 Prompt 看作一个函数签名：&lt;/p&gt;
&lt;div class=&#34;code-block&#34;&gt;
    &lt;button class=&#34;code-copy&#34; type=&#34;button&#34; hidden aria-label=&#34;Copy code to clipboard&#34;&gt;
      &lt;span class=&#34;code-copy-label&#34; aria-hidden=&#34;true&#34;&gt;Copy&lt;/span&gt;
    &lt;/button&gt;
    &lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;f(context, instruction, constraints, examples) → output&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;&lt;ul&gt;
&lt;li&gt;&lt;code&gt;context&lt;/code&gt;：模型需要知道的背景信息&lt;/li&gt;
&lt;li&gt;&lt;code&gt;instruction&lt;/code&gt;：明确要做什么&lt;/li&gt;
&lt;li&gt;&lt;code&gt;constraints&lt;/code&gt;：输出格式、长度、风格、禁止事项&lt;/li&gt;
&lt;li&gt;&lt;code&gt;examples&lt;/code&gt;：少量示例，帮助模型快速对齐预期&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;设计 Prompt 时，首先考虑的不是&amp;quot;这句话够不够自然&amp;quot;，而是&lt;strong&gt;输入是否完整、输出是否可解析、边界是否可控&lt;/strong&gt;。当你开始用接口设计的思路写 Prompt，很多所谓&amp;quot;玄学&amp;quot;就会消失。&lt;/p&gt;
&lt;p&gt;我们的做法：&lt;strong&gt;每个 Prompt 都是一个独立文件，纳入 Git 管理，有版本历史、有变更日志（CHANGELOG）、有配套评测。&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;下面先看一个完整的真实样本。&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id=&#34;二真实样本解剖一个-ai-开发的-prompt-规则库&#34;&gt;二、真实样本解剖：一个 AI 开发的 Prompt 规则库&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;keframework-aidev-promptkit&lt;/code&gt; 是一套给 AI 结对编程工具（Cline / RooCode / Cursor / Windsurf）使用的 Prompt 规则库。它的目标不是&amp;quot;让 AI 聊天更聪明&amp;quot;，而是&lt;strong&gt;让 AI 像一个严格遵守工程规范的高级开发一样工作&lt;/strong&gt;：读需求、做澄清、出方案、拆计划、写代码、跑测试、留文档，全流程可追溯。&lt;/p&gt;
&lt;p&gt;它的目录结构本身就是一套 Prompt 架构：&lt;/p&gt;
&lt;div class=&#34;code-block&#34;&gt;
    &lt;button class=&#34;code-copy&#34; type=&#34;button&#34; hidden aria-label=&#34;Copy code to clipboard&#34;&gt;
      &lt;span class=&#34;code-copy-label&#34; aria-hidden=&#34;true&#34;&gt;Copy&lt;/span&gt;
    &lt;/button&gt;
    &lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;keframework-aidev-promptkit/
├── prompt_rules/              # 规则源文件（Single Source of Truth）
│   ├── common/                # 所有模式都加载的通用规则
│   │   ├── common_general_rules.md   # 输出语言、状态标记等&amp;#34;宪法&amp;#34;
│   │   └── common_memory.md          # Memory Bank 机制
│   ├── plan_architect/        # PLAN/架构模式专用规则
│   │   └── plan_architect_planning.md
│   ├── act_code/              # ACT/编码模式专用规则
│   │   └── act_code_implement.md
│   └── spec/                  # 技术规范（Java 后端、Vue、数据库、API…）
├── ai_work/spec/              # 规范在项目内的落盘位置（只读引用）
├── docs/                      # 配置指南、开发全流程指南、Review 指南
└── CHANGELOG.md               # Prompt 资产自身的变更日志&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;&lt;p&gt;用一张图看清它的分层：&lt;/p&gt;
&lt;div class=&#34;code-block&#34;&gt;
    &lt;button class=&#34;code-copy&#34; type=&#34;button&#34; hidden aria-label=&#34;Copy code to clipboard&#34;&gt;
      &lt;span class=&#34;code-copy-label&#34; aria-hidden=&#34;true&#34;&gt;Copy&lt;/span&gt;
    &lt;/button&gt;
    &lt;pre tabindex=&#34;0&#34;&gt;&lt;code class=&#34;language-mermaid&#34; data-lang=&#34;mermaid&#34;&gt;graph TD
    subgraph 规则分层[&amp;#34;Prompt 规则分层（prompt_rules/）&amp;#34;]
        C[&amp;#34;common/&amp;lt;br/&amp;gt;通用规则 + Memory Bank&amp;lt;br/&amp;gt;alwaysApply: true&amp;#34;]
        P[&amp;#34;plan_architect/&amp;lt;br/&amp;gt;规划模式规则&amp;#34;]
        A[&amp;#34;act_code/&amp;lt;br/&amp;gt;实现模式规则&amp;#34;]
        S[&amp;#34;spec/&amp;lt;br/&amp;gt;技术规范（只读上下文）&amp;#34;]
    end

    subgraph 工具适配[&amp;#34;工具适配层（复制分发）&amp;#34;]
        ROO[&amp;#34;.roo/rules&amp;lt;br/&amp;gt;.roo/rules-code&amp;lt;br/&amp;gt;.roo/rules-architect&amp;#34;]
        CLINE[&amp;#34;.clinerules/ACT&amp;lt;br/&amp;gt;.clinerules/PLAN&amp;#34;]
        CURSOR[&amp;#34;.cursor/rules/&amp;#34;]
    end

    subgraph 项目内上下文[&amp;#34;项目内上下文（ai_work/）&amp;#34;]
        MEM[&amp;#34;Memory Bank&amp;lt;br/&amp;gt;project_brief / task_plan&amp;lt;br/&amp;gt;active_context / learnings&amp;#34;]
        SPEC2[&amp;#34;ai_work/spec/&amp;lt;br/&amp;gt;技术规范副本（全模式只读）&amp;#34;]
    end

    C --&amp;gt; ROO &amp;amp; CLINE &amp;amp; CURSOR
    P --&amp;gt; ROO &amp;amp; CLINE &amp;amp; CURSOR
    A --&amp;gt; ROO &amp;amp; CLINE &amp;amp; CURSOR
    S --&amp;gt; SPEC2
    C -.定义机制.-&amp;gt; MEM&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;&lt;p&gt;这个结构里藏着几个关键设计决策，下面逐一拆解。&lt;/p&gt;
&lt;h3 id=&#34;21-决策一按加载时机分层而不是按主题堆砌&#34;&gt;2.1 决策一：按&amp;quot;加载时机&amp;quot;分层，而不是按主题堆砌&lt;/h3&gt;
&lt;p&gt;规则分三类的依据是&lt;strong&gt;何时生效&lt;/strong&gt;：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;common/&lt;/code&gt;：永远生效（规则文件头部带 YAML frontmatter：&lt;code&gt;alwaysApply: true&lt;/code&gt;）&lt;/li&gt;
&lt;li&gt;&lt;code&gt;plan_architect/&lt;/code&gt;：只在 PLAN/架构模式生效&lt;/li&gt;
&lt;li&gt;&lt;code&gt;act_code/&lt;/code&gt;：只在 ACT/编码模式生效&lt;/li&gt;
&lt;li&gt;&lt;code&gt;spec/&lt;/code&gt;：不注入 System Prompt，而是落盘为项目文件，由规则要求 AI &lt;strong&gt;按需读取、全程只读&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;这和软件架构里的分层同理：全局常量、按请求注入的拦截器、按需加载的配置。如果把所有规则塞进一个巨大的 System Prompt，AI 在长会话中会逐渐&amp;quot;遗忘&amp;quot;靠后的指令——规则分层本质是&lt;strong&gt;注意力预算管理&lt;/strong&gt;。&lt;/p&gt;
&lt;h3 id=&#34;22-决策二规则源文件与工具解耦&#34;&gt;2.2 决策二：规则源文件与工具解耦&lt;/h3&gt;
&lt;p&gt;同一套规则通过脚本复制到不同工具的约定目录（&lt;code&gt;.roo/&lt;/code&gt;、&lt;code&gt;.clinerules/&lt;/code&gt;、&lt;code&gt;.cursor/rules/&lt;/code&gt;），工具各自加载。这保证：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;规则只有一份源文件，改一处全工具生效&lt;/li&gt;
&lt;li&gt;工具升级或更换时规则资产不丢失&lt;/li&gt;
&lt;li&gt;可以针对某个工具做薄薄的适配层，而不动核心规则&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;23-决策三prompt-资产自己有-changelog&#34;&gt;2.3 决策三：Prompt 资产自己有 CHANGELOG&lt;/h3&gt;
&lt;p&gt;这个仓库维护了 &lt;code&gt;CHANGELOG.md&lt;/code&gt; / &lt;code&gt;CHANGELOG_cn.md&lt;/code&gt;，记录类似这样的条目：&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;加强规划与实现阶段文档衔接：&lt;code&gt;plan_architect_planning.md&lt;/code&gt; 明确规划输出需结构化、无歧义，直接作为实现输入，且实现必须严格遵循，任何偏离需回溯并更新规划。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;注意这条日志的写法：不是&amp;quot;优化了提示词&amp;quot;，而是&lt;strong&gt;像 API 变更一样描述行为契约的变化&lt;/strong&gt;。这就是&amp;quot;Prompt 是代码&amp;quot;在资产管理层面的落地。&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id=&#34;三上下文工程比提示词本身更重要&#34;&gt;三、上下文工程：比提示词本身更重要&lt;/h2&gt;
&lt;p&gt;大模型的能力边界，很大程度上由上下文决定。同样的模型，给不同的上下文，表现可能天差地别。上下文工程至少包含四件事：会话间的记忆延续、相关性管理、知识缺口补足、超长任务的分段策略。&lt;/p&gt;
&lt;h3 id=&#34;31-memory-bank解决会话间记忆清零&#34;&gt;3.1 Memory Bank：解决会话间记忆清零&lt;/h3&gt;
&lt;p&gt;AI Coding 工具的根本限制是&lt;strong&gt;会话之间记忆清零，单次会话上下文有限&lt;/strong&gt;。promptkit 的解法是 Memory Bank：一组结构化 Markdown 文件，作为 AI 的唯一事实来源（sole context source）。&lt;/p&gt;
&lt;div class=&#34;code-block&#34;&gt;
    &lt;button class=&#34;code-copy&#34; type=&#34;button&#34; hidden aria-label=&#34;Copy code to clipboard&#34;&gt;
      &lt;span class=&#34;code-copy-label&#34; aria-hidden=&#34;true&#34;&gt;Copy&lt;/span&gt;
    &lt;/button&gt;
    &lt;pre tabindex=&#34;0&#34;&gt;&lt;code class=&#34;language-mermaid&#34; data-lang=&#34;mermaid&#34;&gt;graph TD
    PB[&amp;#34;project_brief.md&amp;lt;br/&amp;gt;项目范围与目标（事实源头）&amp;#34;] --&amp;gt; PR[&amp;#34;design/product_requirements.md&amp;lt;br/&amp;gt;PRD：产品需求&amp;#34;]
    PR --&amp;gt; AR[&amp;#34;spec/architecture_spec.md&amp;lt;br/&amp;gt;系统架构、组件关系&amp;#34;]
    AR --&amp;gt; TC[&amp;#34;spec/technical_spec.md&amp;lt;br/&amp;gt;技术栈与约束&amp;#34;]
    TC --&amp;gt; TP[&amp;#34;task/task_plan.md&amp;lt;br/&amp;gt;任务 backlog 与进度&amp;#34;]
    TP --&amp;gt; AC[&amp;#34;task/active_context.md&amp;lt;br/&amp;gt;当前焦点、最近变更、下一步&amp;#34;]
    AC --&amp;gt; LE[&amp;#34;task/learnings.md&amp;lt;br/&amp;gt;错误/修复/模式 学习日志&amp;#34;]&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;&lt;p&gt;&lt;strong&gt;读写权限按模式划分——这是最容易被忽视的设计：&lt;/strong&gt;&lt;/p&gt;
&lt;table&gt;
	&lt;thead&gt;
			&lt;tr&gt;
					&lt;th&gt;文件&lt;/th&gt;
					&lt;th&gt;PLAN 模式&lt;/th&gt;
					&lt;th&gt;ACT 模式&lt;/th&gt;
			&lt;/tr&gt;
	&lt;/thead&gt;
	&lt;tbody&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;project_brief.md&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;可编辑&lt;/td&gt;
					&lt;td&gt;&lt;strong&gt;只读&lt;/strong&gt;&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;design/&lt;/code&gt;（PRD、实现设计）&lt;/td&gt;
					&lt;td&gt;可编辑&lt;/td&gt;
					&lt;td&gt;&lt;strong&gt;只读&lt;/strong&gt;&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;spec/&lt;/code&gt;（架构、技术规范）&lt;/td&gt;
					&lt;td&gt;&lt;strong&gt;全模式只读&lt;/strong&gt;&lt;/td&gt;
					&lt;td&gt;&lt;strong&gt;全模式只读&lt;/strong&gt;&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;task/task_plan.md&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;可编辑&lt;/td&gt;
					&lt;td&gt;可编辑&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;task/active_context.md&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;可编辑&lt;/td&gt;
					&lt;td&gt;可编辑&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;task/learnings.md&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;可编辑&lt;/td&gt;
					&lt;td&gt;可编辑&lt;/td&gt;
			&lt;/tr&gt;
	&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;为什么要这样设计？因为&lt;strong&gt;没有一个写代码的 Agent 会自觉地不去改需求文档&lt;/strong&gt;。如果 ACT 模式可以改 &lt;code&gt;spec/&lt;/code&gt;，AI 遇到&amp;quot;规范和代码冲突&amp;quot;时往往会悄悄改规范来迁就代码——这在工程上是灾难。用 Prompt 规则把权限写死，等于给 AI 上了文件系统级别的 ACL。&lt;/p&gt;
&lt;p&gt;规则还定义了人类可触发的显式命令：&lt;code&gt;read memory bank&lt;/code&gt; / &lt;code&gt;rmb&lt;/code&gt;（会话开始恢复全部上下文）、&lt;code&gt;update memory bank&lt;/code&gt; / &lt;code&gt;umb&lt;/code&gt;（里程碑完成后落盘进度）。这把&amp;quot;上下文管理&amp;quot;从 AI 的隐式行为变成了&lt;strong&gt;人和 AI 共享的显式协议&lt;/strong&gt;。&lt;/p&gt;
&lt;h3 id=&#34;32-相关性优先于信息量&#34;&gt;3.2 相关性优先于信息量&lt;/h3&gt;
&lt;p&gt;很多人误以为上下文越长越好，于是把整个文档、整段对话历史都塞进去。实际上，&lt;strong&gt;无关信息会稀释注意力，降低关键细节的召回概率。&lt;/strong&gt; 尤其是在长上下文窗口下，模型对中间位置的信息敏感度会下降。&lt;/p&gt;
&lt;p&gt;在 RAG 系统里，我们会对检索结果做重排序，只保留最相关的片段；在 Agent 任务中，我们会维护一个精简的&amp;quot;工作记忆&amp;quot;，定期丢弃已经完成、不再影响后续决策的中间结果。Memory Bank 的七个文件刻意保持&amp;quot;简洁而完备&amp;quot;，也是同一个道理。&lt;/p&gt;
&lt;h3 id=&#34;33-用-rag-补足预训练知识的缺口&#34;&gt;3.3 用 RAG 补足预训练知识的缺口&lt;/h3&gt;
&lt;p&gt;大模型的训练数据有截止日期，且不会包含你的私有文档、最新产品资料、内部知识库。直接问模型&amp;quot;我们公司上个月上线了哪些功能&amp;quot;，它要么胡说，要么拒绝回答。&lt;/p&gt;
&lt;p&gt;我们在短视频生成平台里搭建了基于 ChromaDB 的本地素材库：把品牌素材、历史优质脚本、风格指南等向量化，生成任务触发时先做语义检索，再把检索结果注入 Prompt。这样模型不是在&amp;quot;回忆&amp;quot;，而是在&amp;quot;依据材料创作&amp;quot;。&lt;/p&gt;
&lt;h3 id=&#34;34-长文本要分段模型负责局部应用层负责全局&#34;&gt;3.4 长文本要分段：模型负责局部，应用层负责全局&lt;/h3&gt;
&lt;p&gt;当任务超出单次 Token 上限，或者单次生成难以保证一致性时，不要硬塞。GeekCast Engine 处理长视频口播稿时，采用了&amp;quot;分段生成 + 本地组装&amp;quot;的策略：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;按语义把口播稿切分成若干段&lt;/li&gt;
&lt;li&gt;每段独立调用 LLM 生成视觉元素规划&lt;/li&gt;
&lt;li&gt;在应用层做冲突检测、风格统一和最终组装&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;这个思路和分布式系统里的 MapReduce 很像：&lt;strong&gt;模型负责局部计算，应用层负责全局协调。&lt;/strong&gt;&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id=&#34;四工作流即-promptplan--act-双模式&#34;&gt;四、工作流即 Prompt：PLAN / ACT 双模式&lt;/h2&gt;
&lt;p&gt;promptkit 最核心的思想是：&lt;strong&gt;不指望 AI 自由发挥，而是把软件工程流程编码进 Prompt&lt;/strong&gt;。PLAN 和 ACT 两个模式各有一段专属规则，规则里直接画出了执行流程。&lt;/p&gt;
&lt;h3 id=&#34;41-plan-模式流程&#34;&gt;4.1 PLAN 模式流程&lt;/h3&gt;
&lt;div class=&#34;code-block&#34;&gt;
    &lt;button class=&#34;code-copy&#34; type=&#34;button&#34; hidden aria-label=&#34;Copy code to clipboard&#34;&gt;
      &lt;span class=&#34;code-copy-label&#34; aria-hidden=&#34;true&#34;&gt;Copy&lt;/span&gt;
    &lt;/button&gt;
    &lt;pre tabindex=&#34;0&#34;&gt;&lt;code class=&#34;language-mermaid&#34; data-lang=&#34;mermaid&#34;&gt;flowchart TD
    Start([开始]) --&amp;gt; Read[读取全部 Memory Bank 核心文件]
    Read --&amp;gt; Check{上下文完整?}
    Check --&amp;gt;|否| Create[补齐缺失文件/计划]
    Create --&amp;gt; Clarify
    Check --&amp;gt;|是| Clarify[&amp;#34;&amp;amp;lt;CLARIFICATION&amp;amp;gt;&amp;lt;br/&amp;gt;反复澄清，消除所有歧义&amp;#34;]
    Clarify --&amp;gt; Reason[&amp;#34;&amp;amp;lt;STEP BY STEP REASONING&amp;amp;gt;&amp;lt;br/&amp;gt;分解问题、多方案权衡&amp;#34;]
    Reason --&amp;gt; Present[&amp;#34;&amp;amp;lt;REASONING PRESENTATION&amp;amp;gt;&amp;lt;br/&amp;gt;呈现计划：假设、取舍、步骤&amp;#34;]
    Present --&amp;gt; Verify{人确认计划?}
    Verify --&amp;gt;|否| Clarify
    Verify --&amp;gt;|是| Update[更新 Memory Bank&amp;lt;br/&amp;gt;落盘结构化计划]&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;&lt;h3 id=&#34;42-act-模式流程&#34;&gt;4.2 ACT 模式流程&lt;/h3&gt;
&lt;div class=&#34;code-block&#34;&gt;
    &lt;button class=&#34;code-copy&#34; type=&#34;button&#34; hidden aria-label=&#34;Copy code to clipboard&#34;&gt;
      &lt;span class=&#34;code-copy-label&#34; aria-hidden=&#34;true&#34;&gt;Copy&lt;/span&gt;
    &lt;/button&gt;
    &lt;pre tabindex=&#34;0&#34;&gt;&lt;code class=&#34;language-mermaid&#34; data-lang=&#34;mermaid&#34;&gt;flowchart TD
    Start([开始]) --&amp;gt; Read[读取 Memory Bank&amp;lt;br/&amp;gt;spec/ 与 design/ 只读]
    Read --&amp;gt; Analyze[&amp;#34;&amp;amp;lt;ANALYZE CODE&amp;amp;gt;&amp;lt;br/&amp;gt;依赖分析 + 端到端流程分析&amp;#34;]
    Analyze --&amp;gt; Plan[&amp;#34;&amp;amp;lt;PLAN CODE&amp;amp;gt;&amp;lt;br/&amp;gt;结构化提案，等待确认&amp;#34;]
    Plan --&amp;gt; Sim[&amp;#34;&amp;amp;lt;SIMULATION ANALYSIS&amp;amp;gt;&amp;lt;br/&amp;gt;Dry run 推演副作用&amp;#34;]
    Sim --&amp;gt; Valid{模拟通过?}
    Valid --&amp;gt;|否| Fix[修复并重新模拟]
    Fix --&amp;gt; Sim
    Valid --&amp;gt;|是| Impl[&amp;#34;&amp;amp;lt;MAKE CHANGES&amp;amp;gt;&amp;lt;br/&amp;gt;单逻辑变更，增量提交&amp;#34;]
    Impl --&amp;gt; Test[&amp;#34;&amp;amp;lt;TESTING&amp;amp;gt;&amp;lt;br/&amp;gt;单元测试 + 回归测试&amp;#34;]
    Test --&amp;gt; Update[更新 active_context&amp;lt;br/&amp;gt;与 learnings]&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;&lt;h3 id=&#34;43-xml-标签作为行为锚点&#34;&gt;4.3 XML 标签作为&amp;quot;行为锚点&amp;quot;&lt;/h3&gt;
&lt;p&gt;注意规则里大量使用 &lt;code&gt;&amp;lt;CLARIFICATION&amp;gt;&lt;/code&gt;、&lt;code&gt;&amp;lt;SIMULATION ANALYSIS&amp;gt;&lt;/code&gt;、&lt;code&gt;&amp;lt;NO BREAKAGE ASSERTION&amp;gt;&lt;/code&gt; 这类自定义 XML 标签。这不是装饰，而是一种经过验证的 Prompt 技巧：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;标签把&amp;quot;阶段&amp;quot;显式化，AI 输出时会自报当前处于哪个阶段，&lt;strong&gt;方便人审查 AI 是否跳步&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;标签给 LLM 提供了清晰的注意力锚点，比自然语言段落里的祈使句更不容易被忽略&lt;/li&gt;
&lt;li&gt;标签名形成词汇表后，人可以缩写指令：&amp;ldquo;先做 &lt;code&gt;&amp;lt;ANALYZE CODE&amp;gt;&lt;/code&gt; 再动手&amp;rdquo;，沟通成本骤降&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;举两个有代表性的片段（译注，原文为英文）：&lt;/p&gt;
&lt;div class=&#34;code-block&#34;&gt;
    &lt;button class=&#34;code-copy&#34; type=&#34;button&#34; hidden aria-label=&#34;Copy code to clipboard&#34;&gt;
      &lt;span class=&#34;code-copy-label&#34; aria-hidden=&#34;true&#34;&gt;Copy&lt;/span&gt;
    &lt;/button&gt;
    &lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-xml&#34; data-lang=&#34;xml&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;CLARIFICATION&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;- 永远主动追问澄清和细节。
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;- 识别所有不明确的需求，逐一追问。
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;- 对所有假设提问，消除全部歧义。
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;- 提出我没想到的方案，预判我的需求。
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;- 只有百分之百清晰后，才进入方案阶段。
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;/CLARIFICATION&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;div class=&#34;code-block&#34;&gt;
    &lt;button class=&#34;code-copy&#34; type=&#34;button&#34; hidden aria-label=&#34;Copy code to clipboard&#34;&gt;
      &lt;span class=&#34;code-copy-label&#34; aria-hidden=&#34;true&#34;&gt;Copy&lt;/span&gt;
    &lt;/button&gt;
    &lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-xml&#34; data-lang=&#34;xml&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;NO&lt;/span&gt; &lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;BREAKAGE&lt;/span&gt; &lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;ASSERTION&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;提出变更后，自己运行测试并确认通过。
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;不要依赖用户来做这件事，并且要确信不会破坏用户现有代码。
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;&amp;lt;&lt;/span&gt;/NO BREAKAGE ASSERTION&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;p&gt;可以看到，这些规则写的不是&amp;quot;提示&amp;quot;，而是&lt;strong&gt;带强制语气的行为规范&lt;/strong&gt;——和给新员工发的《开发规范》没有区别。&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id=&#34;五规划到实现的交接协议&#34;&gt;五、规划到实现的交接协议&lt;/h2&gt;
&lt;p&gt;Prompt 工程里最难的不是&amp;quot;让 AI 生成好内容&amp;quot;，而是&lt;strong&gt;让 AI 的上一轮输出成为下一轮可严格执行的输入&lt;/strong&gt;。promptkit 对此定义了一套交接协议（Handoff Protocol）。&lt;/p&gt;
&lt;h3 id=&#34;51-结构化计划输出&#34;&gt;5.1 结构化计划输出&lt;/h3&gt;
&lt;p&gt;PLAN 模式的产出必须是 YAML 或 Markdown 表格，每个 phase/step 有固定字段：&lt;/p&gt;
&lt;div class=&#34;code-block&#34;&gt;
    &lt;button class=&#34;code-copy&#34; type=&#34;button&#34; hidden aria-label=&#34;Copy code to clipboard&#34;&gt;
      &lt;span class=&#34;code-copy-label&#34; aria-hidden=&#34;true&#34;&gt;Copy&lt;/span&gt;
    &lt;/button&gt;
    &lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-yaml&#34; data-lang=&#34;yaml&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;id&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;P3-S2&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;name&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;Implement login endpoint&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;description&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;Add POST /login endpoint for user authentication&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;source_requirement&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;PRD-REQ-12&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;entry_conditions&lt;/span&gt;: [&lt;span style=&#34;color:#ae81ff&#34;&gt;P2 completed, API spec approved]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;exit_conditions&lt;/span&gt;: [&lt;span style=&#34;color:#ae81ff&#34;&gt;Unit tests pass, Docs updated, Code reviewed]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;responsible&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;AI&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;test_cases&lt;/span&gt;: [&lt;span style=&#34;color:#ae81ff&#34;&gt;test_P3_S2_login]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;status&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;planned&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;requirement_version&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;v1.2&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;change_log&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  - {&lt;span style=&#34;color:#f92672&#34;&gt;date: 2024-06-01, author: AI, change&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;Initial creation&amp;#39;&lt;/span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;h3 id=&#34;52-全链路可追溯&#34;&gt;5.2 全链路可追溯&lt;/h3&gt;
&lt;div class=&#34;code-block&#34;&gt;
    &lt;button class=&#34;code-copy&#34; type=&#34;button&#34; hidden aria-label=&#34;Copy code to clipboard&#34;&gt;
      &lt;span class=&#34;code-copy-label&#34; aria-hidden=&#34;true&#34;&gt;Copy&lt;/span&gt;
    &lt;/button&gt;
    &lt;pre tabindex=&#34;0&#34;&gt;&lt;code class=&#34;language-mermaid&#34; data-lang=&#34;mermaid&#34;&gt;graph LR
    PRD[&amp;#34;PRD-REQ-12&amp;lt;br/&amp;gt;需求条目&amp;#34;] --&amp;gt; STEP[&amp;#34;P3-S2&amp;lt;br/&amp;gt;计划步骤&amp;#34;]
    STEP --&amp;gt; CODE[&amp;#34;user_login_P3_S2.java&amp;lt;br/&amp;gt;实现代码&amp;#34;]
    STEP --&amp;gt; TEST[&amp;#34;test_P3_S2_login.java&amp;lt;br/&amp;gt;测试代码&amp;#34;]
    STEP --&amp;gt; COMMIT[&amp;#34;feat(P3-S2): ...&amp;lt;br/&amp;gt;提交信息&amp;#34;]
    STEP --&amp;gt; LOG[&amp;#34;change_log&amp;lt;br/&amp;gt;变更记录&amp;#34;]&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;&lt;p&gt;规则强制：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;每个 step 必须引用至少一个 PRD 需求 ID；每条需求必须被至少一个 step 覆盖&lt;/li&gt;
&lt;li&gt;代码文件、测试文件、commit message 全部携带 step ID&lt;/li&gt;
&lt;li&gt;实现阶段发现计划有问题，&lt;strong&gt;必须暂停并回溯更新计划，不允许擅自偏离&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;每个 phase 的 exit 条件包含&amp;quot;单元测试通过、覆盖率 ≥ 90%&amp;quot;，而不是把测试堆到最后&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;这套东西眼熟吗？它就是把传统项目管理里的**需求追踪矩阵（RTM）**搬进了 Prompt。AI 输出的结构化程度，决定了它在下一阶段的可控性。&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id=&#34;六从单次问答到-agent-编排&#34;&gt;六、从单次问答到 Agent 编排&lt;/h2&gt;
&lt;p&gt;当你让 AI 做一个复杂任务时，单次 Prompt 往往不够。真正难的不是让模型&amp;quot;回答&amp;quot;，而是让它&lt;strong&gt;按照正确的路径完成任务，并在出错时恢复&lt;/strong&gt;。&lt;/p&gt;
&lt;h3 id=&#34;61-react让模型想一步做一步&#34;&gt;6.1 ReAct：让模型&amp;quot;想一步、做一步&amp;quot;&lt;/h3&gt;
&lt;p&gt;ReAct（Reasoning + Acting）是我们用得最多的模式。它的核心不是一次性生成最终答案，而是让模型在每一步都输出：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Thought&lt;/strong&gt;：当前怎么想&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Action&lt;/strong&gt;：下一步要调用什么工具&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Observation&lt;/strong&gt;：工具返回了什么结果&lt;/li&gt;
&lt;/ul&gt;
&lt;div class=&#34;code-block&#34;&gt;
    &lt;button class=&#34;code-copy&#34; type=&#34;button&#34; hidden aria-label=&#34;Copy code to clipboard&#34;&gt;
      &lt;span class=&#34;code-copy-label&#34; aria-hidden=&#34;true&#34;&gt;Copy&lt;/span&gt;
    &lt;/button&gt;
    &lt;pre tabindex=&#34;0&#34;&gt;&lt;code class=&#34;language-mermaid&#34; data-lang=&#34;mermaid&#34;&gt;flowchart LR
    T[&amp;#34;Thought&amp;lt;br/&amp;gt;当前怎么想&amp;#34;] --&amp;gt; A[&amp;#34;Action&amp;lt;br/&amp;gt;调用什么工具&amp;#34;]
    A --&amp;gt; O[&amp;#34;Observation&amp;lt;br/&amp;gt;工具返回结果&amp;#34;]
    O --&amp;gt; D{任务完成?}
    D --&amp;gt;|否| T
    D --&amp;gt;|是| F[&amp;#34;Final Answer&amp;lt;br/&amp;gt;输出最终结果&amp;#34;]&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;&lt;p&gt;比如一个短视频生成任务，Agent 的规划可能是：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;读取用户输入的主题和风格要求&lt;/li&gt;
&lt;li&gt;检索素材库，找到匹配的背景音乐和视觉素材&lt;/li&gt;
&lt;li&gt;生成脚本初稿&lt;/li&gt;
&lt;li&gt;检查脚本长度是否符合平台要求&lt;/li&gt;
&lt;li&gt;如果不符合，进行压缩或扩展&lt;/li&gt;
&lt;li&gt;输出最终脚本并进入渲染队列&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;每一步都有明确的输入输出和异常处理路径。这比一个&amp;quot;请帮我生成视频&amp;quot;的大而全 Prompt 可靠得多。&lt;/p&gt;
&lt;h3 id=&#34;62-异常恢复与降级策略&#34;&gt;6.2 异常恢复与降级策略&lt;/h3&gt;
&lt;p&gt;真实生产环境里，模型调用可能失败、工具返回可能异常、生成的 JSON 可能解析失败。我们在 Agent 层设计了：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;重试机制&lt;/strong&gt;：对临时性错误进行指数退避重试&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;降级策略&lt;/strong&gt;：如果主模型调用失败，切换到备用模型或简化流程&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;边界控制&lt;/strong&gt;：当模型输出偏离预期时，通过约束模板和校验规则及时拦截&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;这些不是 Prompt 本身能解决的，但好的 Prompt 设计会为这些机制留出接口——比如让模型以固定 JSON 格式输出，就是为了后续程序化处理。&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id=&#34;七控制幻觉与讨好倾向&#34;&gt;七、控制幻觉与讨好倾向&lt;/h2&gt;
&lt;p&gt;大模型有两个常见毛病：一是&lt;strong&gt;胡说八道还一本正经&lt;/strong&gt;（幻觉），二是&lt;strong&gt;倾向于说你想听的&lt;/strong&gt;（讨好倾向）。作为工程师，不能指望用户每次都火眼金睛，必须在系统层做防控。&lt;/p&gt;
&lt;h3 id=&#34;71-要求依据而不是要求答案&#34;&gt;7.1 要求依据，而不是要求答案&lt;/h3&gt;
&lt;p&gt;当你让模型做判断时，不要只问&amp;quot;对不对&amp;quot;，而要问&amp;quot;为什么对&amp;quot;、&amp;ldquo;依据是什么&amp;rdquo;。在 RAG 场景里，我们会让模型引用它使用的素材片段；在代码评审场景里，我们会让模型指出具体行号和修改理由。&lt;/p&gt;
&lt;p&gt;一个实用技巧是：&lt;strong&gt;让模型先列出置信度，再给出结论。&lt;/strong&gt; 低置信度的输出可以直接进入人工复核队列。&lt;/p&gt;
&lt;h3 id=&#34;72-用中性提问对抗诱导&#34;&gt;7.2 用中性提问对抗诱导&lt;/h3&gt;
&lt;p&gt;避免在 Prompt 里夹带倾向性表述。比如不要问&amp;quot;这个方案是不是很好&amp;quot;，而要问&amp;quot;这个方案的优缺点是什么，适用场景和潜在风险分别是什么&amp;quot;。&lt;/p&gt;
&lt;p&gt;在涉及评分、排序、比较的任务里，提前定义清晰的评分标准，并让模型逐项说明得分理由。这比一个总体分数更有信息量，也更容易发现偏差。&lt;/p&gt;
&lt;h3 id=&#34;73-多模型交叉验证&#34;&gt;7.3 多模型交叉验证&lt;/h3&gt;
&lt;p&gt;对于关键决策，可以让不同模型分别评估，再对结果做一致性检查。这个方法成本高，但在高风险场景（如医疗、金融、安全审核）里值得考虑。&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id=&#34;八多模态提示文本只是入口&#34;&gt;八、多模态提示：文本只是入口&lt;/h2&gt;
&lt;p&gt;在短视频生成和口播剪辑项目里，我们大量接触了图像、音频、视频与文本的协同。多模态提示有几个值得注意的工程经验。&lt;/p&gt;
&lt;h3 id=&#34;81-图像理解的整体-细节偏差&#34;&gt;8.1 图像理解的&amp;quot;整体-细节&amp;quot;偏差&lt;/h3&gt;
&lt;p&gt;AI 读图时往往先把握整体构图，对局部细节容易遗漏。如果任务依赖细节（比如识别小字、检测图标），可以：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;裁剪放大关键区域后单独输入&lt;/li&gt;
&lt;li&gt;提供多张不同角度或不同尺度的图片&lt;/li&gt;
&lt;li&gt;在 Prompt 中明确指定&amp;quot;请重点描述左上角的文字&amp;quot;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;82-图像生成的提示词工程&#34;&gt;8.2 图像生成的提示词工程&lt;/h3&gt;
&lt;p&gt;扩散模型对文本描述非常敏感。直接写&amp;quot;一只猫在草地上&amp;quot;，结果可能平平无奇。更好的做法是用一个文本模型先把需求扩写成结构化描述：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;主体&lt;/strong&gt;：什么猫、姿态、表情&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;场景&lt;/strong&gt;：草地类型、光线、天气、时间&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;风格&lt;/strong&gt;：写实、插画、赛博朋克、宫崎骏动画&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;镜头&lt;/strong&gt;：特写、中景、鸟瞰、景深效果&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;也可以上传参考图，让模型先描述参考图的风格，再把描述作为提示词用于生成。&lt;/p&gt;
&lt;h3 id=&#34;83-视频生成需要时间维度的上下文&#34;&gt;8.3 视频生成需要&amp;quot;时间维度&amp;quot;的上下文&lt;/h3&gt;
&lt;p&gt;相比单张图片，视频多了一个时间轴。生成视频脚本或分镜时，Prompt 里要包含：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;每个镜头的起止时间&lt;/li&gt;
&lt;li&gt;画面过渡方式&lt;/li&gt;
&lt;li&gt;音频与画面的对齐点&lt;/li&gt;
&lt;li&gt;字幕出现和消失的节拍&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;我们在方糖猫里把这些问题模板化，让 Agent 分步骤输出分镜表、配音稿、字幕轴，再交给 Remotion + FFmpeg 渲染流水线执行。&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id=&#34;九另一个视角生成管线里的-prompt-迭代&#34;&gt;九、另一个视角：生成管线里的 Prompt 迭代&lt;/h2&gt;
&lt;p&gt;如果说 promptkit 展示的是&amp;quot;规范驱动&amp;quot;的 Prompt 工程，那么 GeekCast Engine 的视觉规划 Prompt 展示的是&amp;quot;数据驱动&amp;quot;的迭代路径。两者互补。&lt;/p&gt;
&lt;h3 id=&#34;91-v1基础版&#34;&gt;9.1 V1：基础版&lt;/h3&gt;
&lt;div class=&#34;code-block&#34;&gt;
    &lt;button class=&#34;code-copy&#34; type=&#34;button&#34; hidden aria-label=&#34;Copy code to clipboard&#34;&gt;
      &lt;span class=&#34;code-copy-label&#34; aria-hidden=&#34;true&#34;&gt;Copy&lt;/span&gt;
    &lt;/button&gt;
    &lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;请为以下口播文案规划视觉元素。

文案：{script}

可选元素：TitleCard, BRoll, QuoteCard, CodeBlock, ListCard, TalkingHead

请输出 JSON 数组。&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;&lt;p&gt;&lt;strong&gt;问题&lt;/strong&gt;：LLM 输出解释性文字；JSON 格式不稳定；对每种元素的用途理解不一致。&lt;/p&gt;
&lt;h3 id=&#34;92-v2结构化版&#34;&gt;9.2 V2：结构化版&lt;/h3&gt;
&lt;div class=&#34;code-block&#34;&gt;
    &lt;button class=&#34;code-copy&#34; type=&#34;button&#34; hidden aria-label=&#34;Copy code to clipboard&#34;&gt;
      &lt;span class=&#34;code-copy-label&#34; aria-hidden=&#34;true&#34;&gt;Copy&lt;/span&gt;
    &lt;/button&gt;
    &lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;你是一名专业的口播视频剪辑师。请根据文案为每个句子规划视觉元素。

可用元素及定义：
- TitleCard: 章节开头或核心观点强调
- BRoll: 补充说明画面
- QuoteCard: 名言、数据引用
- CodeBlock: 代码展示
- ListCard: 多要点展示
- TalkingHead: 保持说话人画面

文案：{script}

请输出 JSON 数组，每个元素包含 sentence_index, element_type, reason, suggested_content。
不要输出任何解释性文字。&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;&lt;p&gt;&lt;strong&gt;改进&lt;/strong&gt;：明确角色、定义每个元素、明确输出格式。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;仍有问题&lt;/strong&gt;：复杂文案处理不好；长文案超出 Token 限制。&lt;/p&gt;
&lt;h3 id=&#34;93-v3分段--schema-约束版&#34;&gt;9.3 V3：分段 + Schema 约束版&lt;/h3&gt;
&lt;div class=&#34;code-block&#34;&gt;
    &lt;button class=&#34;code-copy&#34; type=&#34;button&#34; hidden aria-label=&#34;Copy code to clipboard&#34;&gt;
      &lt;span class=&#34;code-copy-label&#34; aria-hidden=&#34;true&#34;&gt;Copy&lt;/span&gt;
    &lt;/button&gt;
    &lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;你是一名专业的口播视频剪辑师。请根据文案为每个句子规划视觉元素。

[元素定义...]

请输出严格符合以下 JSON Schema 的数组：
{schema}

注意：
1. 不要输出任何解释性文字
2. 每句文案只选择一种最合适的视觉元素
3. 如果句子包含代码或技术术语，优先使用 CodeBlock
4. 如果句子引用名言或数据，优先使用 QuoteCard

文案：{script}&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;&lt;p&gt;&lt;strong&gt;改进&lt;/strong&gt;：加入 JSON Schema、增加选择规则、配合后端 Pydantic 校验。&lt;/p&gt;
&lt;h3 id=&#34;94-迭代路径总结&#34;&gt;9.4 迭代路径总结&lt;/h3&gt;
&lt;div class=&#34;code-block&#34;&gt;
    &lt;button class=&#34;code-copy&#34; type=&#34;button&#34; hidden aria-label=&#34;Copy code to clipboard&#34;&gt;
      &lt;span class=&#34;code-copy-label&#34; aria-hidden=&#34;true&#34;&gt;Copy&lt;/span&gt;
    &lt;/button&gt;
    &lt;pre tabindex=&#34;0&#34;&gt;&lt;code class=&#34;language-mermaid&#34; data-lang=&#34;mermaid&#34;&gt;flowchart LR
    V1[&amp;#34;V1 基础版&amp;lt;br/&amp;gt;格式不稳定&amp;#34;] --&amp;gt;|问题驱动| V2[&amp;#34;V2 结构化版&amp;lt;br/&amp;gt;角色+定义+格式&amp;#34;]
    V2 --&amp;gt;|评测驱动| V3[&amp;#34;V3 Schema 约束版&amp;lt;br/&amp;gt;规则+后端校验&amp;#34;]
    V3 --&amp;gt;|失败样本回流| EVAL[评测集扩充]
    EVAL --&amp;gt; V4[&amp;#34;下一版本...&amp;#34;]&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;&lt;p&gt;三次迭代的共同规律：&lt;strong&gt;每一版都是先在生产/评测中暴露问题，再有针对性地加约束&lt;/strong&gt;——而不是一开始就写一个&amp;quot;完美&amp;quot;的长 Prompt。这和 promptkit 用 CHANGELOG 记录行为契约变更，是同一个方法论的两面。&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id=&#34;十prompt-版本管理与加载&#34;&gt;十、Prompt 版本管理与加载&lt;/h2&gt;
&lt;h3 id=&#34;101-文件组织&#34;&gt;10.1 文件组织&lt;/h3&gt;
&lt;div class=&#34;code-block&#34;&gt;
    &lt;button class=&#34;code-copy&#34; type=&#34;button&#34; hidden aria-label=&#34;Copy code to clipboard&#34;&gt;
      &lt;span class=&#34;code-copy-label&#34; aria-hidden=&#34;true&#34;&gt;Copy&lt;/span&gt;
    &lt;/button&gt;
    &lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;prompts/
├── visual_plan/
│   ├── v1.md
│   ├── v2.md
│   └── v3.md
├── storyboard/
│   ├── v1.md
│   └── v2.md
├── query_rewrite/
│   └── v1.md
└── README.md&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;&lt;p&gt;每个 Prompt 文件头部包含：版本号、适用模型、使用场景、输入变量说明、输出格式要求、变更记录。&lt;/p&gt;
&lt;h3 id=&#34;102-加载与渲染&#34;&gt;10.2 加载与渲染&lt;/h3&gt;
&lt;div class=&#34;code-block&#34;&gt;
    &lt;button class=&#34;code-copy&#34; type=&#34;button&#34; hidden aria-label=&#34;Copy code to clipboard&#34;&gt;
      &lt;span class=&#34;code-copy-label&#34; aria-hidden=&#34;true&#34;&gt;Copy&lt;/span&gt;
    &lt;/button&gt;
    &lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;import&lt;/span&gt; os
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;class&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;PromptManager&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;def&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;__init__&lt;/span&gt;(self, base_path&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;prompts&amp;#34;&lt;/span&gt;):
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        self&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;base_path &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; base_path
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;def&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;load&lt;/span&gt;(self, name: str, version: str) &lt;span style=&#34;color:#f92672&#34;&gt;-&amp;gt;&lt;/span&gt; str:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        path &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; os&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;path&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;join(self&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;base_path, name, &lt;span style=&#34;color:#e6db74&#34;&gt;f&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;{&lt;/span&gt;version&lt;span style=&#34;color:#e6db74&#34;&gt;}&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;.md&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#66d9ef&#34;&gt;with&lt;/span&gt; open(path, &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;r&amp;#34;&lt;/span&gt;, encoding&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;utf-8&amp;#34;&lt;/span&gt;) &lt;span style=&#34;color:#66d9ef&#34;&gt;as&lt;/span&gt; f:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#66d9ef&#34;&gt;return&lt;/span&gt; f&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;read()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;def&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;render&lt;/span&gt;(self, name: str, version: str, variables: dict) &lt;span style=&#34;color:#f92672&#34;&gt;-&amp;gt;&lt;/span&gt; str:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        template &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; self&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;load(name, version)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#66d9ef&#34;&gt;return&lt;/span&gt; template&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;format(&lt;span style=&#34;color:#f92672&#34;&gt;**&lt;/span&gt;variables)&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;h3 id=&#34;103-常用设计模式速查&#34;&gt;10.3 常用设计模式速查&lt;/h3&gt;
&lt;table&gt;
	&lt;thead&gt;
			&lt;tr&gt;
					&lt;th&gt;模式&lt;/th&gt;
					&lt;th&gt;适用场景&lt;/th&gt;
					&lt;th&gt;要点&lt;/th&gt;
			&lt;/tr&gt;
	&lt;/thead&gt;
	&lt;tbody&gt;
			&lt;tr&gt;
					&lt;td&gt;角色 + 任务 + 格式&lt;/td&gt;
					&lt;td&gt;结构化输出&lt;/td&gt;
					&lt;td&gt;最简单，80% 场景够用&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;Chain-of-Thought&lt;/td&gt;
					&lt;td&gt;需要推理的复杂任务&lt;/td&gt;
					&lt;td&gt;显式列出思考步骤&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;Few-shot&lt;/td&gt;
					&lt;td&gt;格式复杂或需要风格&lt;/td&gt;
					&lt;td&gt;示例控制在 2-3 个&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;动态 Few-shot&lt;/td&gt;
					&lt;td&gt;有素材库可检索&lt;/td&gt;
					&lt;td&gt;从 RAG 召回相似示例拼入 Prompt&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;ReAct&lt;/td&gt;
					&lt;td&gt;需要工具调用的 Agent 任务&lt;/td&gt;
					&lt;td&gt;Thought/Action/Observation 循环&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;模式化规则注入&lt;/td&gt;
					&lt;td&gt;AI Coding 场景&lt;/td&gt;
					&lt;td&gt;按 PLAN/ACT 等模式加载不同规则（见第四节）&lt;/td&gt;
			&lt;/tr&gt;
	&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;动态 Few-shot 的实现：&lt;/p&gt;
&lt;div class=&#34;code-block&#34;&gt;
    &lt;button class=&#34;code-copy&#34; type=&#34;button&#34; hidden aria-label=&#34;Copy code to clipboard&#34;&gt;
      &lt;span class=&#34;code-copy-label&#34; aria-hidden=&#34;true&#34;&gt;Copy&lt;/span&gt;
    &lt;/button&gt;
    &lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;def&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;build_dynamic_prompt&lt;/span&gt;(query: str, examples: list[str]) &lt;span style=&#34;color:#f92672&#34;&gt;-&amp;gt;&lt;/span&gt; str:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    prompt &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;以下是几个类似场景的处理示例：&lt;/span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;\n\n&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;for&lt;/span&gt; i, ex &lt;span style=&#34;color:#f92672&#34;&gt;in&lt;/span&gt; enumerate(examples, &lt;span style=&#34;color:#ae81ff&#34;&gt;1&lt;/span&gt;):
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        prompt &lt;span style=&#34;color:#f92672&#34;&gt;+=&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;f&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;示例 &lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;{&lt;/span&gt;i&lt;span style=&#34;color:#e6db74&#34;&gt;}&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;：&lt;/span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;\n&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;{&lt;/span&gt;ex&lt;span style=&#34;color:#e6db74&#34;&gt;}&lt;/span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;\n\n&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    prompt &lt;span style=&#34;color:#f92672&#34;&gt;+=&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;f&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;现在请处理：&lt;/span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;\n&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;{&lt;/span&gt;query&lt;span style=&#34;color:#e6db74&#34;&gt;}&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;return&lt;/span&gt; prompt&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;hr&gt;
&lt;h2 id=&#34;十一评估与回归没有评测集就没有迭代资格&#34;&gt;十一、评估与回归：没有评测集就没有迭代资格&lt;/h2&gt;
&lt;p&gt;提示工程最难的部分不是写出第一版 Prompt，而是&lt;strong&gt;持续知道它在变差，并及时修复&lt;/strong&gt;。&lt;/p&gt;
&lt;h3 id=&#34;111-评测数据集&#34;&gt;11.1 评测数据集&lt;/h3&gt;
&lt;p&gt;收集一批代表性用例，覆盖正常输入、边界输入、异常输入：&lt;/p&gt;
&lt;div class=&#34;code-block&#34;&gt;
    &lt;button class=&#34;code-copy&#34; type=&#34;button&#34; hidden aria-label=&#34;Copy code to clipboard&#34;&gt;
      &lt;span class=&#34;code-copy-label&#34; aria-hidden=&#34;true&#34;&gt;Copy&lt;/span&gt;
    &lt;/button&gt;
    &lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-json&#34; data-lang=&#34;json&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;[
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;&amp;#34;input&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;大家好，今天讲 AI 视频生成...&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;&amp;#34;expected&amp;#34;&lt;/span&gt;: [
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      {&lt;span style=&#34;color:#f92672&#34;&gt;&amp;#34;sentence_index&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;0&lt;/span&gt;, &lt;span style=&#34;color:#f92672&#34;&gt;&amp;#34;element_type&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;TitleCard&amp;#34;&lt;/span&gt;},
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      {&lt;span style=&#34;color:#f92672&#34;&gt;&amp;#34;sentence_index&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;2&lt;/span&gt;, &lt;span style=&#34;color:#f92672&#34;&gt;&amp;#34;element_type&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;CodeBlock&amp;#34;&lt;/span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    ]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;]&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;h3 id=&#34;112-分任务定义可量化的指标&#34;&gt;11.2 分任务定义可量化的指标&lt;/h3&gt;
&lt;p&gt;不同任务的关注点不同：&lt;/p&gt;
&lt;table&gt;
	&lt;thead&gt;
			&lt;tr&gt;
					&lt;th&gt;任务类型&lt;/th&gt;
					&lt;th&gt;核心指标&lt;/th&gt;
			&lt;/tr&gt;
	&lt;/thead&gt;
	&lt;tbody&gt;
			&lt;tr&gt;
					&lt;td&gt;通用生成任务&lt;/td&gt;
					&lt;td&gt;格式合规率、语义准确率、字段完整率、Token 消耗、平均延迟&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;RAG 任务&lt;/td&gt;
					&lt;td&gt;召回率、准确率、回答相关性&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;Agent 任务&lt;/td&gt;
					&lt;td&gt;任务完成率、平均步数、异常恢复率&lt;/td&gt;
			&lt;/tr&gt;
	&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;除了技术指标，还要跟踪业务指标。我们在短视频生成平台里跟踪：渲染成功率、用户二次编辑率、单视频平均 Token 成本。这些指标会反过来指导 Prompt 优化方向。&lt;/p&gt;
&lt;h3 id=&#34;113-回归测试脚本&#34;&gt;11.3 回归测试脚本&lt;/h3&gt;
&lt;div class=&#34;code-block&#34;&gt;
    &lt;button class=&#34;code-copy&#34; type=&#34;button&#34; hidden aria-label=&#34;Copy code to clipboard&#34;&gt;
      &lt;span class=&#34;code-copy-label&#34; aria-hidden=&#34;true&#34;&gt;Copy&lt;/span&gt;
    &lt;/button&gt;
    &lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;def&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;run_prompt_regression&lt;/span&gt;(prompt_version: str, test_cases: list):
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    results &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; []
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;for&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;case&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;in&lt;/span&gt; test_cases:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        output &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; llm_call(&lt;span style=&#34;color:#66d9ef&#34;&gt;case&lt;/span&gt;[&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;input&amp;#34;&lt;/span&gt;], prompt_version)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        parsed &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; parse_output(output)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        results&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;append({
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;case_id&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#66d9ef&#34;&gt;case&lt;/span&gt;[&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;id&amp;#34;&lt;/span&gt;],
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;format_valid&amp;#34;&lt;/span&gt;: is_valid_format(parsed),
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;semantic_score&amp;#34;&lt;/span&gt;: compare_with_expected(parsed, &lt;span style=&#34;color:#66d9ef&#34;&gt;case&lt;/span&gt;[&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;expected&amp;#34;&lt;/span&gt;]),
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;token_count&amp;#34;&lt;/span&gt;: count_tokens(output),
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;latency&amp;#34;&lt;/span&gt;: measure_latency()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        })
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;return&lt;/span&gt; summarize(results)&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;h3 id=&#34;114-合并门禁&#34;&gt;11.4 合并门禁&lt;/h3&gt;
&lt;p&gt;每次修改 Prompt 前：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;复制当前版本为新版本&lt;/li&gt;
&lt;li&gt;在评测集上跑回归测试&lt;/li&gt;
&lt;li&gt;对比新版本和旧版本的指标&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;只有指标不下降才合并&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;这套流程和代码的 CI 门禁完全同构。promptkit 的 CHANGELOG + 这里的回归脚本，一个管&amp;quot;规则资产&amp;quot;，一个管&amp;quot;生成资产&amp;quot;，合起来才是完整的 Prompt 版本管理。&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id=&#34;十二成本控制prompt-也是成本中心&#34;&gt;十二、成本控制：Prompt 也是成本中心&lt;/h2&gt;
&lt;p&gt;长 Prompt 和高轮次调用都会直接转化为模型费用。优化 Prompt 不只是为了效果更好，也是为了更便宜。&lt;/p&gt;
&lt;h3 id=&#34;121-模型路由&#34;&gt;12.1 模型路由&lt;/h3&gt;
&lt;p&gt;不是所有任务都需要最强的模型：&lt;/p&gt;
&lt;table&gt;
	&lt;thead&gt;
			&lt;tr&gt;
					&lt;th&gt;任务&lt;/th&gt;
					&lt;th&gt;模型&lt;/th&gt;
					&lt;th&gt;原因&lt;/th&gt;
			&lt;/tr&gt;
	&lt;/thead&gt;
	&lt;tbody&gt;
			&lt;tr&gt;
					&lt;td&gt;简单格式提取&lt;/td&gt;
					&lt;td&gt;DeepSeek-V3 / GPT-3.5&lt;/td&gt;
					&lt;td&gt;便宜、够快&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;复杂创意规划&lt;/td&gt;
					&lt;td&gt;GPT-4 / Claude 3.5&lt;/td&gt;
					&lt;td&gt;质量高&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;代码相关任务&lt;/td&gt;
					&lt;td&gt;Claude 3.5+&lt;/td&gt;
					&lt;td&gt;代码能力强&lt;/td&gt;
			&lt;/tr&gt;
	&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;promptkit 的 README 里也有同样的分层建议：讨论需求用带搜索的 Chat 工具，规划设计用分析能力强的模型，编码用代码能力强的模型。&lt;strong&gt;按阶段选模型，而不是一个模型打全场。&lt;/strong&gt;&lt;/p&gt;
&lt;h3 id=&#34;122-prompt-压缩&#34;&gt;12.2 Prompt 压缩&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;删除冗余说明&lt;/li&gt;
&lt;li&gt;用更短的变量名&lt;/li&gt;
&lt;li&gt;Few-shot 示例控制在 2-3 个&lt;/li&gt;
&lt;li&gt;长文案先分段，再分别处理&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;123-缓存&#34;&gt;12.3 缓存&lt;/h3&gt;
&lt;div class=&#34;code-block&#34;&gt;
    &lt;button class=&#34;code-copy&#34; type=&#34;button&#34; hidden aria-label=&#34;Copy code to clipboard&#34;&gt;
      &lt;span class=&#34;code-copy-label&#34; aria-hidden=&#34;true&#34;&gt;Copy&lt;/span&gt;
    &lt;/button&gt;
    &lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;def&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;cached_llm_call&lt;/span&gt;(query: str, prompt_version: str):
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    key &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; hash(&lt;span style=&#34;color:#e6db74&#34;&gt;f&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;{&lt;/span&gt;prompt_version&lt;span style=&#34;color:#e6db74&#34;&gt;}&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;:&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;{&lt;/span&gt;query&lt;span style=&#34;color:#e6db74&#34;&gt;}&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    cached &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; redis&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;get(key)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;if&lt;/span&gt; cached:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#66d9ef&#34;&gt;return&lt;/span&gt; cached
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    result &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; llm_call(query, prompt_version)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    redis&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;setex(key, &lt;span style=&#34;color:#ae81ff&#34;&gt;3600&lt;/span&gt;, result)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;return&lt;/span&gt; result&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;p&gt;两个注意点：缓存 key 里必须带 &lt;code&gt;prompt_version&lt;/code&gt;——Prompt 变了，缓存就必须失效；同样的思路也适用于其他生成产物，比如我们按文案 hash 缓存 TTS 结果，避免重复合成。&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id=&#34;十三踩过的坑&#34;&gt;十三、踩过的坑&lt;/h2&gt;
&lt;h3 id=&#34;131-prompt-里塞了太多信息&#34;&gt;13.1 Prompt 里塞了太多信息&lt;/h3&gt;
&lt;p&gt;早期一个 Prompt 要同时做意图分析、视觉规划、素材推荐，结果哪一项都做得不好。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;解决&lt;/strong&gt;：拆成多个专门 Prompt，每个只负责一个任务。promptkit 把 PLAN 和 ACT 拆成两套规则文件，是同一件事。&lt;/p&gt;
&lt;h3 id=&#34;132-过度依赖-llm-做判断&#34;&gt;13.2 过度依赖 LLM 做判断&lt;/h3&gt;
&lt;p&gt;有些规则明确的判断（比如句子长度、是否包含代码关键字），完全可以用代码做，没必要让 LLM 判断。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;解决&lt;/strong&gt;：规则用代码，创意用 LLM。&lt;/p&gt;
&lt;h3 id=&#34;133-没有记录失败案例&#34;&gt;13.3 没有记录失败案例&lt;/h3&gt;
&lt;p&gt;线上遇到解析失败的 Prompt 输出，没有系统收集，导致同样的问题反复出现。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;解决&lt;/strong&gt;：建立失败样本库，定期补充到评测集中。promptkit 的 &lt;code&gt;learnings.md&lt;/code&gt; 是同一个思想在 AI Coding 场景的落地——让 AI 把自己犯过的错写下来，下次会话先读。&lt;/p&gt;
&lt;h3 id=&#34;134-忽视不同模型的差异&#34;&gt;13.4 忽视不同模型的差异&lt;/h3&gt;
&lt;p&gt;同一个 Prompt 在 DeepSeek 上表现好，在 GPT-4 上可能出问题。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;解决&lt;/strong&gt;：为不同模型维护微调后的 Prompt 版本；评测集要覆盖所有生产用模型。&lt;/p&gt;
&lt;h3 id=&#34;135-让-ai-自己改规范&#34;&gt;13.5 让 AI 自己改规范&lt;/h3&gt;
&lt;p&gt;AI 遇到&amp;quot;规范与实现冲突&amp;quot;时，倾向于悄悄改规范迁就实现。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;解决&lt;/strong&gt;：把规范目录在规则里声明为&lt;strong&gt;全模式只读&lt;/strong&gt;（promptkit 的 &lt;code&gt;ai_work/spec/&lt;/code&gt; 就是这么做的），规范的变更只能由人发起。&lt;/p&gt;
&lt;h3 id=&#34;136-规划与实现脱节&#34;&gt;13.6 规划与实现脱节&lt;/h3&gt;
&lt;p&gt;AI 在 PLAN 模式出了漂亮的方案，到了 ACT 模式就自由发挥，交付物和计划对不上。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;解决&lt;/strong&gt;：用交接协议强制——实现必须引用计划中的 step ID，发现计划不可行必须暂停回溯，不允许擅自偏离（见第五节）。&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id=&#34;十四prompt-工程的核心原则&#34;&gt;十四、Prompt 工程的核心原则&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;把 Prompt 当接口设计&lt;/strong&gt;：输入完整、输出可解析、边界可控，像设计函数签名一样设计 Prompt&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;把 Prompt 当代码管理&lt;/strong&gt;：版本控制、CHANGELOG、测试、Review 缺一不可&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;按加载时机分层&lt;/strong&gt;：全局规则 / 模式规则 / 只读规范，分开管理注意力预算&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;上下文要显式化&lt;/strong&gt;：Memory Bank 这类结构化上下文文件，比依赖会话记忆可靠得多&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;相关性优先于信息量&lt;/strong&gt;：无关上下文会稀释注意力，检索结果要重排序，工作记忆要定期清理&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;流程编码进 Prompt&lt;/strong&gt;：不要指望 AI 自觉遵守工程流程，把流程画成它必须执行的步骤&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;复杂任务编排成步骤&lt;/strong&gt;：用 ReAct 等模式拆解任务、设计异常恢复，而不是一个大 Prompt 包打天下&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;要求依据，而非答案&lt;/strong&gt;：让模型给置信度、引用素材、指出行号，低置信度进人工队列&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;AI 之间的交接要有协议&lt;/strong&gt;：结构化输出 + ID 追溯 + 暂停回溯机制&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;简单任务优先用代码&lt;/strong&gt;：不要让 LLM 做规则能做的事&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;输出必须可校验&lt;/strong&gt;：Schema + 后端校验是底线&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;用数据驱动优化&lt;/strong&gt;：评测集、技术指标 + 业务指标、回归门禁&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;收集失败样本&lt;/strong&gt;：失败案例是最值钱的评测集增量&lt;/li&gt;
&lt;/ol&gt;
&lt;hr&gt;
&lt;h2 id=&#34;十五总结&#34;&gt;十五、总结&lt;/h2&gt;
&lt;p&gt;Prompt Engineering 不是玄学，也不是简单的&amp;quot;提示词技巧&amp;quot;。它至少是三层东西的组合：&lt;/p&gt;
&lt;div class=&#34;code-block&#34;&gt;
    &lt;button class=&#34;code-copy&#34; type=&#34;button&#34; hidden aria-label=&#34;Copy code to clipboard&#34;&gt;
      &lt;span class=&#34;code-copy-label&#34; aria-hidden=&#34;true&#34;&gt;Copy&lt;/span&gt;
    &lt;/button&gt;
    &lt;pre tabindex=&#34;0&#34;&gt;&lt;code class=&#34;language-mermaid&#34; data-lang=&#34;mermaid&#34;&gt;graph TD
    L3[&amp;#34;工程管理层&amp;lt;br/&amp;gt;版本控制 / CHANGELOG / 评测回归 / 成本路由&amp;#34;]
    L2[&amp;#34;系统设计层&amp;lt;br/&amp;gt;规则分层 / Memory Bank / 双模式工作流 / 交接协议 / Agent 编排&amp;#34;]
    L1[&amp;#34;文本技巧层&amp;lt;br/&amp;gt;角色设定 / CoT / Few-shot / Schema 约束&amp;#34;]
    L3 --&amp;gt; L2 --&amp;gt; L1&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;&lt;p&gt;大多数人讨论的&amp;quot;Prompt 技巧&amp;quot;只在最底层打转；真正把 LLM 应用做稳定的团队，都在上两层下功夫：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;系统设计层&lt;/strong&gt;：Prompt 决定 Agent 能做什么、不能做什么，读写权限、模式切换、交接协议、异常恢复都是架构决策&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;工程管理层&lt;/strong&gt;：Prompt 是需要版本、测试、评估、变更日志管理的资产，也是直接的成本中心&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;方糖猫的视觉规划 Prompt 从 V1 到 V3 提升的是单点输出质量；promptkit 用一套规则库约束的是整个 AI 开发流程的行为。两者路径不同，结论一致：&lt;strong&gt;Prompt 工程的天花板不在&amp;quot;会不会写提示词&amp;quot;，而在&amp;quot;有没有把它当工程做&amp;quot;。&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;所以，不要花太多时间寻找&amp;quot;万能 Prompt&amp;quot;。更值钱的能力是：&lt;strong&gt;把业务问题拆解成模型能稳定执行的子任务，再用工程化的方法把它变成可交付、可维护的系统。&lt;/strong&gt;&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;&lt;em&gt;如果你也在做 LLM 应用开发或 AI Coding 落地，欢迎交流 Prompt 版本管理、规则分层和回归测试的经验。&lt;/em&gt;&lt;/p&gt;
</description>
    </item>
    
  </channel>
</rss>
