<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
  <channel>
    <title>Prompt Engineering on 方糖猫Blog</title>
    <link>https://ftmao.com/blog/tags/prompt-engineering/</link>
    <description>AI 视频、AI Agent 与工程实践笔记</description>
    <generator>Hugo</generator>
    <language>zh-CN</language>
    <lastBuildDate>Thu, 02 Apr 2026 15:00:00 +0800</lastBuildDate><atom:link href="https://ftmao.com/blog/tags/prompt-engineering/index.xml" rel="self" type="application/rss+xml" /><item>
      <title>LLM 输出 JSON 不稳定：Schema &#43; 重试的实战方案</title>
      <link>https://ftmao.com/blog/posts/goodjson/</link>
      <pubDate>Thu, 02 Apr 2026 15:00:00 +0800</pubDate>
      <guid>https://ftmao.com/blog/posts/goodjson/</guid>
      <description>&lt;h1 id=&#34;llm-输出-json-不稳定schema--重试的实战方案&#34;&gt;LLM 输出 JSON 不稳定：Schema + 重试的实战方案&lt;/h1&gt;
&lt;blockquote&gt;
&lt;p&gt;做 AI Agent 或 LLM 应用时，一个高频需求是让模型输出结构化数据。比如 Agent 需要 LLM 决定调用哪个 Tool、视觉规划需要输出 JSON 数组、代码生成需要返回固定格式的片段。但 LLM 输出 JSON 很容易出问题：格式错乱、字段缺失、类型不对、多了句废话。这篇文章分享我们是如何把结构化输出成功率从 75% 左右提升到 98% 以上的。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;hr&gt;
&lt;h2 id=&#34;一问题的普遍性&#34;&gt;一、问题的普遍性&lt;/h2&gt;
&lt;p&gt;我们先看几个真实遇到的 LLM 输出：&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;场景 1：Agent 决定调用 Tool&lt;/strong&gt;&lt;/p&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 style=&#34;color:#f92672&#34;&gt;&amp;#34;tool&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;RetrieveMaterials&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;params&amp;#34;&lt;/span&gt;: {&lt;span style=&#34;color:#f92672&#34;&gt;&amp;#34;query&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;海边日落&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;/code&gt;&lt;/pre&gt;&lt;/div&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&gt;我决定调用 RetrieveMaterials 工具，参数是 {&amp;#34;query&amp;#34;: &amp;#34;海边日落&amp;#34;}。&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;&lt;p&gt;&lt;strong&gt;场景 2：视觉规划输出 JSON 数组&lt;/strong&gt;&lt;/p&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 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 style=&#34;color:#f92672&#34;&gt;&amp;#34;content&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;/code&gt;&lt;/pre&gt;&lt;/div&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;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 style=&#34;color:#f92672&#34;&gt;&amp;#34;result&amp;#34;&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 style=&#34;color:#f92672&#34;&gt;&amp;#34;content&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&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;p&gt;&lt;strong&gt;场景 3：字段类型错误&lt;/strong&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 style=&#34;color:#f92672&#34;&gt;&amp;#34;duration&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;30秒&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;/code&gt;&lt;/pre&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;p&gt;期望是数字：&lt;code&gt;30&lt;/code&gt;。&lt;/p&gt;
&lt;p&gt;这些输出人都看得懂，但程序解析不了。不解决的话，LLM 应用根本跑不稳。&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id=&#34;二常见的四层解决方案&#34;&gt;二、常见的四层解决方案&lt;/h2&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;flowchart TD
    A[&amp;#34;第一层：Prompt 设计（明确格式 + Few-shot）&amp;#34;] --&amp;gt; B[&amp;#34;第二层：JSON Schema / Function Calling 约束&amp;#34;]
    B --&amp;gt; C[&amp;#34;第三层：后端 Pydantic 校验&amp;#34;]
    C --&amp;gt; D[&amp;#34;第四层：自动重试 + 降级&amp;#34;]&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;&lt;p&gt;单层都不够，必须组合使用。&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id=&#34;三第一层prompt-设计&#34;&gt;三、第一层：Prompt 设计&lt;/h2&gt;
&lt;h3 id=&#34;31-明确输出格式&#34;&gt;3.1 明确输出格式&lt;/h3&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;请直接输出 JSON，不要包含任何解释性文字。
JSON 格式如下：
{
  &amp;#34;tool&amp;#34;: &amp;#34;工具名称&amp;#34;,
  &amp;#34;params&amp;#34;: {
    &amp;#34;参数名&amp;#34;: &amp;#34;参数值&amp;#34;
  }
}&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;&lt;h3 id=&#34;32-few-shot-示例&#34;&gt;3.2 Few-shot 示例&lt;/h3&gt;
&lt;p&gt;在 Prompt 里给 2-3 个正确示例，效果提升明显：&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;示例 1：
输入：用户想要一个海边日落视频
输出：{&amp;#34;tool&amp;#34;: &amp;#34;RetrieveMaterials&amp;#34;, &amp;#34;params&amp;#34;: {&amp;#34;query&amp;#34;: &amp;#34;海边日落&amp;#34;}}

示例 2：
输入：用户想要删除视频中的语气词
输出：{&amp;#34;tool&amp;#34;: &amp;#34;RemoveFillers&amp;#34;, &amp;#34;params&amp;#34;: {&amp;#34;aggressive&amp;#34;: false}}&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;&lt;h3 id=&#34;33-限制输出长度&#34;&gt;3.3 限制输出长度&lt;/h3&gt;
&lt;p&gt;对于简单任务，明确要求 LLM 不要展开：&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;输出必须严格符合上述 JSON 格式，总长度不超过 200 个字符。&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;&lt;hr&gt;
&lt;h2 id=&#34;四第二层json-schema-约束&#34;&gt;四、第二层：JSON Schema 约束&lt;/h2&gt;
&lt;h3 id=&#34;41-什么是-json-schema&#34;&gt;4.1 什么是 JSON Schema&lt;/h3&gt;
&lt;p&gt;JSON Schema 是一种描述 JSON 数据结构的规范。你可以把它传给 LLM，让模型按这个结构输出。&lt;/p&gt;
&lt;p&gt;DeepSeek、GPT-4、Claude 3 都支持 JSON Schema 或 Function Calling。&lt;/p&gt;
&lt;h3 id=&#34;42-我们的-schema-示例&#34;&gt;4.2 我们的 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;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;visual_plan_schema &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:#e6db74&#34;&gt;&amp;#34;type&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;array&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;items&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;type&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;object&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;properties&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;sentence_index&amp;#34;&lt;/span&gt;: {&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;type&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;integer&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;element_type&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;type&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;string&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;enum&amp;#34;&lt;/span&gt;: [&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;TitleCard&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;BRoll&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;QuoteCard&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;CodeBlock&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;ListCard&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;TalkingHead&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 style=&#34;color:#e6db74&#34;&gt;&amp;#34;reason&amp;#34;&lt;/span&gt;: {&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;type&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;string&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;suggested_content&amp;#34;&lt;/span&gt;: {&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;type&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;string&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 style=&#34;color:#e6db74&#34;&gt;&amp;#34;required&amp;#34;&lt;/span&gt;: [&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;sentence_index&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;element_type&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;reason&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;/code&gt;&lt;/pre&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;h3 id=&#34;43-deepseek-调用示例&#34;&gt;4.3 DeepSeek 调用示例&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; openai
&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;client &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; openai&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;OpenAI(
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    api_key&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;your-api-key&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    base_url&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;https://api.deepseek.com/v1&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;response &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; client&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;chat&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;completions&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;create(
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    model&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;deepseek-chat&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    messages&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:#e6db74&#34;&gt;&amp;#34;role&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;system&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;content&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;你是一个专业的视频剪辑规划助手。&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;role&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;user&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;content&amp;#34;&lt;/span&gt;: prompt}
&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;    response_format&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:#e6db74&#34;&gt;&amp;#34;type&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;json_schema&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;json_schema&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;name&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;visual_plan&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;schema&amp;#34;&lt;/span&gt;: visual_plan_schema
&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;    temperature&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;0.2&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;result &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; json&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;loads(response&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;choices[&lt;span style=&#34;color:#ae81ff&#34;&gt;0&lt;/span&gt;]&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;message&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;content)&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;h3 id=&#34;44-function-calling&#34;&gt;4.4 Function Calling&lt;/h3&gt;
&lt;p&gt;Function Calling 本质上也是让 LLM 输出结构化的函数调用参数：&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;response &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; client&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;chat&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;completions&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;create(
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    model&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;deepseek-chat&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    messages&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;[{&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;role&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;user&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;content&amp;#34;&lt;/span&gt;: prompt}],
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    tools&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&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;type&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;function&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;function&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;name&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;plan_visual_elements&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;description&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;为口播视频规划视觉元素&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;parameters&amp;#34;&lt;/span&gt;: visual_plan_schema
&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;    tool_choice&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;{&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;type&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;function&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;function&amp;#34;&lt;/span&gt;: {&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;name&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;plan_visual_elements&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;tool_call &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; response&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;choices[&lt;span style=&#34;color:#ae81ff&#34;&gt;0&lt;/span&gt;]&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;message&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;tool_calls[&lt;span style=&#34;color:#ae81ff&#34;&gt;0&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; json&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;loads(tool_call&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;function&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;arguments)&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;p&gt;Function Calling 的好处是模型更清楚自己在做什么，输出稳定性通常更好。&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id=&#34;五第三层pydantic-后端校验&#34;&gt;五、第三层：Pydantic 后端校验&lt;/h2&gt;
&lt;p&gt;即使 LLM 支持 Schema，也不能 100% 保证输出合法。后端必须用 Pydantic 做严格校验。&lt;/p&gt;
&lt;h3 id=&#34;51-模型定义&#34;&gt;5.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;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;from&lt;/span&gt; pydantic &lt;span style=&#34;color:#f92672&#34;&gt;import&lt;/span&gt; BaseModel, Field, field_validator
&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;from&lt;/span&gt; typing &lt;span style=&#34;color:#f92672&#34;&gt;import&lt;/span&gt; Literal
&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;VisualElement&lt;/span&gt;(BaseModel):
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    sentence_index: int &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; Field(ge&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;0&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    element_type: Literal[&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;TitleCard&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;BRoll&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;QuoteCard&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;CodeBlock&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;ListCard&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;TalkingHead&amp;#34;&lt;/span&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    reason: str &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; Field(min_length&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;5&lt;/span&gt;, max_length&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;200&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    suggested_content: str &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;&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 style=&#34;color:#a6e22e&#34;&gt;@field_validator&lt;/span&gt;(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;suggested_content&amp;#39;&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:#a6e22e&#34;&gt;@classmethod&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;validate_content&lt;/span&gt;(cls, v, info):
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        element_type &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; info&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;data&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;get(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;element_type&amp;#39;&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;if&lt;/span&gt; element_type &lt;span style=&#34;color:#f92672&#34;&gt;==&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;TitleCard&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;and&lt;/span&gt; len(v) &lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;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:#66d9ef&#34;&gt;raise&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;ValueError&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:#66d9ef&#34;&gt;return&lt;/span&gt; v
&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;VisualPlan&lt;/span&gt;(BaseModel):
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    elements: list[VisualElement]&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;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;parse_visual_plan&lt;/span&gt;(raw_output: str) &lt;span style=&#34;color:#f92672&#34;&gt;-&amp;gt;&lt;/span&gt; VisualPlan:
&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;try&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        data &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; json&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;loads(raw_output)
&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;except&lt;/span&gt; json&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;JSONDecodeError &lt;span style=&#34;color:#66d9ef&#34;&gt;as&lt;/span&gt; e:
&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;raise&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;ValueError&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;JSON 解析失败: &lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;{&lt;/span&gt;e&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&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#75715e&#34;&gt;# 兼容 LLM 外层多套一层 result 的情况&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;if&lt;/span&gt; isinstance(data, dict) &lt;span style=&#34;color:#f92672&#34;&gt;and&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;result&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;in&lt;/span&gt; data &lt;span style=&#34;color:#f92672&#34;&gt;and&lt;/span&gt; isinstance(data[&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;result&amp;#34;&lt;/span&gt;], list):
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        data &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; data[&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;result&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 style=&#34;color:#66d9ef&#34;&gt;return&lt;/span&gt; VisualPlan(elements&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;data)&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;h3 id=&#34;53-常见兼容处理&#34;&gt;5.3 常见兼容处理&lt;/h3&gt;
&lt;p&gt;实际生产中会见到各种「不标准」的输出，我们做了几个兼容：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;去掉 Markdown 代码块标记 &lt;code&gt;json ... &lt;/code&gt;&lt;/li&gt;
&lt;li&gt;去掉多余的前缀说明文字&lt;/li&gt;
&lt;li&gt;兼容外层多套一层 &lt;code&gt;{&amp;quot;result&amp;quot;: [...]}&lt;/code&gt; 的情况&lt;/li&gt;
&lt;li&gt;兼容中文字段名（如果 Prompt 不小心用了中文）&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h2 id=&#34;六第四层自动重试--降级&#34;&gt;六、第四层：自动重试 + 降级&lt;/h2&gt;
&lt;h3 id=&#34;61-重试策略&#34;&gt;6.1 重试策略&lt;/h3&gt;
&lt;p&gt;当校验失败时，不要直接报错，而是把错误信息回传给 LLM，让它重新生成。&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:#f92672&#34;&gt;from&lt;/span&gt; tenacity &lt;span style=&#34;color:#f92672&#34;&gt;import&lt;/span&gt; retry, stop_after_attempt, wait_exponential
&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:#a6e22e&#34;&gt;@retry&lt;/span&gt;(
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    stop&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;stop_after_attempt(&lt;span style=&#34;color:#ae81ff&#34;&gt;3&lt;/span&gt;),
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    wait&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;wait_exponential(multiplier&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;1&lt;/span&gt;, min&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;1&lt;/span&gt;, max&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;5&lt;/span&gt;),
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    retry&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;retry_if_exception_type(&lt;span style=&#34;color:#a6e22e&#34;&gt;ValueError&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;def&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;generate_with_retry&lt;/span&gt;(prompt: str, schema: dict) &lt;span style=&#34;color:#f92672&#34;&gt;-&amp;gt;&lt;/span&gt; dict:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    raw &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; llm&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;generate(prompt, response_format&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;schema)
&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;try&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; parse_visual_plan(raw)
&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;except&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;ValueError&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;as&lt;/span&gt; e:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#75715e&#34;&gt;# 把错误信息加入 Prompt，重新生成&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\n&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;e&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;请严格按照 JSON Schema 输出。&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;raise&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;62-温度参数调整&#34;&gt;6.2 温度参数调整&lt;/h3&gt;
&lt;p&gt;重试时降低 temperature，让输出更稳定：&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;temperature_schedule &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; [&lt;span style=&#34;color:#ae81ff&#34;&gt;0.2&lt;/span&gt;, &lt;span style=&#34;color:#ae81ff&#34;&gt;0.1&lt;/span&gt;, &lt;span style=&#34;color:#ae81ff&#34;&gt;0.0&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;63-降级方案&#34;&gt;6.3 降级方案&lt;/h3&gt;
&lt;p&gt;如果 3 次重试都失败，不能卡住，要有降级：&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;safe_generate_visual_plan&lt;/span&gt;(script: str) &lt;span style=&#34;color:#f92672&#34;&gt;-&amp;gt;&lt;/span&gt; VisualPlan:
&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;try&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; generate_with_retry(script)
&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;except&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;Exception&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:#75715e&#34;&gt;# 降级：所有句子保持 TalkingHead&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; VisualPlan(elements&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;            VisualElement(
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                sentence_index&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;i,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                element_type&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;TalkingHead&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                reason&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;LLM 规划失败，降级为默认方案&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 style=&#34;color:#66d9ef&#34;&gt;for&lt;/span&gt; i &lt;span style=&#34;color:#f92672&#34;&gt;in&lt;/span&gt; range(len(script&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;split(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;。&amp;#39;&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;p&gt;这样至少能保证系统不崩，用户可以拿到一个基础版本的视频。&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id=&#34;七完整代码示例&#34;&gt;七、完整代码示例&lt;/h2&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; json
&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;from&lt;/span&gt; pydantic &lt;span style=&#34;color:#f92672&#34;&gt;import&lt;/span&gt; BaseModel, Field
&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;from&lt;/span&gt; typing &lt;span style=&#34;color:#f92672&#34;&gt;import&lt;/span&gt; Literal
&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;VisualElement&lt;/span&gt;(BaseModel):
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    sentence_index: int &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; Field(ge&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;0&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    element_type: Literal[&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;TitleCard&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;BRoll&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;QuoteCard&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;CodeBlock&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;ListCard&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;TalkingHead&amp;#34;&lt;/span&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    reason: str &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; Field(min_length&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;5&lt;/span&gt;, max_length&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;200&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    suggested_content: str &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;&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 style=&#34;color:#66d9ef&#34;&gt;def&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;clean_llm_output&lt;/span&gt;(raw: 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;    &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;&amp;#34;&amp;#34;清理 LLM 可能产生的多余格式&amp;#34;&amp;#34;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    raw &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; raw&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;strip()
&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; raw&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;startswith(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;```&amp;#34;&lt;/span&gt;):
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        raw &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; raw&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;strip(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;`&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;if&lt;/span&gt; raw&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;startswith(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;json&amp;#34;&lt;/span&gt;):
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            raw &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; raw[&lt;span style=&#34;color:#ae81ff&#34;&gt;4&lt;/span&gt;:]&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;strip()
&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; raw
&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;robust_parse&lt;/span&gt;(raw: str) &lt;span style=&#34;color:#f92672&#34;&gt;-&amp;gt;&lt;/span&gt; list[VisualElement]:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    raw &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; clean_llm_output(raw)
&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;try&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        data &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; json&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;loads(raw)
&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;except&lt;/span&gt; json&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;JSONDecodeError:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#75715e&#34;&gt;# 尝试找到第一个 [ 和最后一个 ]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        start &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; raw&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;find(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;[&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        end &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; raw&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;rfind(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;]&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;if&lt;/span&gt; start &lt;span style=&#34;color:#f92672&#34;&gt;!=&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;-&lt;/span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;1&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;and&lt;/span&gt; end &lt;span style=&#34;color:#f92672&#34;&gt;!=&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;-&lt;/span&gt;&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;            data &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; json&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;loads(raw[start:end&lt;span style=&#34;color:#f92672&#34;&gt;+&lt;/span&gt;&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;        &lt;span style=&#34;color:#66d9ef&#34;&gt;else&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;raise&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:#75715e&#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;if&lt;/span&gt; isinstance(data, dict):
&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; key &lt;span style=&#34;color:#f92672&#34;&gt;in&lt;/span&gt; [&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;result&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;data&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;elements&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;if&lt;/span&gt; key &lt;span style=&#34;color:#f92672&#34;&gt;in&lt;/span&gt; data &lt;span style=&#34;color:#f92672&#34;&gt;and&lt;/span&gt; isinstance(data[key], list):
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                data &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; data[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;break&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;if&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;not&lt;/span&gt; isinstance(data, list):
&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;raise&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;ValueError&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;type(data)&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&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; [VisualElement(&lt;span style=&#34;color:#f92672&#34;&gt;**&lt;/span&gt;item) &lt;span style=&#34;color:#66d9ef&#34;&gt;for&lt;/span&gt; item &lt;span style=&#34;color:#f92672&#34;&gt;in&lt;/span&gt; data]&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;在我们实际使用中，这套四层方案的效果如下：&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;纯 Prompt 约束&lt;/td&gt;
					&lt;td&gt;约 75%&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;+ JSON Schema&lt;/td&gt;
					&lt;td&gt;约 90%&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;+ Pydantic 校验 + 重试&lt;/td&gt;
					&lt;td&gt;约 98%&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;+ 降级方案&lt;/td&gt;
					&lt;td&gt;系统可用性 99.9%+&lt;/td&gt;
			&lt;/tr&gt;
	&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;（待补充真实数据）&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id=&#34;九踩过的坑&#34;&gt;九、踩过的坑&lt;/h2&gt;
&lt;h3 id=&#34;91-schema-太复杂导致模型懵&#34;&gt;9.1 Schema 太复杂导致模型懵&lt;/h3&gt;
&lt;p&gt;早期的 Schema 有 20 多个字段，模型输出经常漏字段。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;解决&lt;/strong&gt;：Schema 只保留必要字段，非必要字段放 &lt;code&gt;metadata&lt;/code&gt; 或后续步骤再补。&lt;/p&gt;
&lt;h3 id=&#34;92-中文标点导致-json-解析失败&#34;&gt;9.2 中文标点导致 JSON 解析失败&lt;/h3&gt;
&lt;p&gt;LLM 输出中文引号或中文逗号，导致 JSON 解析失败。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;解决&lt;/strong&gt;：在 Prompt 里明确说明用英文标点，后端做字符替换兼容。&lt;/p&gt;
&lt;h3 id=&#34;93-模型输出超长&#34;&gt;9.3 模型输出超长&lt;/h3&gt;
&lt;p&gt;复杂任务下，LLM 输出解释性文字 + JSON，超出 Schema 控制。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;解决&lt;/strong&gt;：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;明确要求「只输出 JSON，不要解释」&lt;/li&gt;
&lt;li&gt;设置 &lt;code&gt;max_tokens&lt;/code&gt; 上限&lt;/li&gt;
&lt;li&gt;后端做截断和清洗&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;94-不同模型-schema-支持不一致&#34;&gt;9.4 不同模型 Schema 支持不一致&lt;/h3&gt;
&lt;p&gt;DeepSeek、GPT、Claude 对 JSON Schema 的支持细节不同。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;解决&lt;/strong&gt;：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;统一封装 LLM 调用层&lt;/li&gt;
&lt;li&gt;对不同模型做适配&lt;/li&gt;
&lt;li&gt;尽量使用 Function Calling，兼容性更好&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h2 id=&#34;十总结&#34;&gt;十、总结&lt;/h2&gt;
&lt;p&gt;LLM 输出结构化数据不稳定，不是模型不行，而是&lt;strong&gt;提示、约束、校验、重试&lt;/strong&gt;四个环节必须闭环。我们的经验是：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Prompt 要明确要求格式&lt;/strong&gt;，别指望模型自己猜&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;JSON Schema / Function Calling 是第二层保险&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;后端 Pydantic 校验必不可少&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;/ol&gt;
&lt;p&gt;这套方案不只适用于视频生成，几乎所有 LLM Agent 应用都需要。&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;&lt;em&gt;如果你在 LLM 结构化输出方面也踩过坑，欢迎在评论区分享。&lt;/em&gt;&lt;/p&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>
    <item>
      <title>把 Claude Code 用成工程杠杆：落地心得</title>
      <link>https://ftmao.com/blog/posts/claude-code-engineering-practice/</link>
      <pubDate>Sat, 10 Jan 2026 15:00:00 +0800</pubDate>
      <guid>https://ftmao.com/blog/posts/claude-code-engineering-practice/</guid>
      <description>&lt;h1 id=&#34;把-claude-code-用成工程杠杆落地心得&#34;&gt;把 Claude Code 用成工程杠杆：落地心得&lt;/h1&gt;
&lt;blockquote&gt;
&lt;p&gt;我做软件工程 18 年了，在华为和 IBM 做过电信级系统，近四年又一头扎进 AI 工程化，主导过 AI Agent 短视频生成平台和自动化口播剪辑平台。Claude Code 是我最近半年每天都在用的主力工具。它不是替代工程师的魔法，而是一把需要正确握持的杠杆。这篇文章聊聊我怎么把它落地到工程工作流里。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;hr&gt;
&lt;h2 id=&#34;一先思考再输入&#34;&gt;一、先思考，再输入&lt;/h2&gt;
&lt;p&gt;很多人打开 Claude Code 的第一件事就是开始打字。这往往是最贵的错误。&lt;/p&gt;
&lt;p&gt;我现在的习惯是：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;写功能前，先想清楚模块边界、数据流、异常路径；&lt;/li&gt;
&lt;li&gt;重构前，先定义&amp;quot;目标形态&amp;quot;是什么；&lt;/li&gt;
&lt;li&gt;调试前，先列出我已知的事实和假设。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;然后按 &lt;code&gt;Shift+Tab&lt;/code&gt; 两次进入 &lt;strong&gt;Plan 模式&lt;/strong&gt;，把这些思考丢给 Claude。&lt;/p&gt;
&lt;p&gt;Plan 模式不是让 Claude 替我想，而是让它在我已经梳理好的框架里填充细节、发现盲点、提出反例。输入越清晰，输出越可用。这个道理听起来简单，但真正做到的人不多。&lt;/p&gt;
&lt;p&gt;如果你觉得自己还不具备独立想架构的能力，我的建议是：先从描述问题开始，和 Claude 反复对话，让它帮你把模糊的想法磨成可执行的方案。对话是双向的，不是单向许愿。&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id=&#34;二架构描述决定代码质量&#34;&gt;二、架构描述决定代码质量&lt;/h2&gt;
&lt;p&gt;&amp;ldquo;给我做一个认证系统&amp;rdquo; 和 &amp;ldquo;基于现有 User 模型实现邮箱密码登录，会话存 Redis 24 小时过期，给 /api/protected 加中间件&amp;rdquo;，得到的结果天差地别。&lt;/p&gt;
&lt;p&gt;AI 生成代码的问题，往往不在于模型不够聪明，而在于你给的目标太宽泛。自由度太大，模型就会按照它自己的理解去填补，而这些填补常常和你的工程习惯、团队规范、历史包袱不一致。&lt;/p&gt;
&lt;p&gt;我在方糖猫的项目里深有体会。AI Agent 的渲染流水线涉及 Java API 服务、Python Worker、RocketMQ、Remotion 渲染、FFmpeg 后处理多个环节。如果我只说&amp;quot;帮我实现一个视频生成任务调度&amp;quot;，Claude 可能会写出一个看起来合理但完全不符合我们现有架构的方案。但如果我把状态机、消息格式、失败重试策略、SSE 进度推送方式都描述清楚，它就能写出可以直接接入系统的代码。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;好的 Prompt 不是文学，是需求文档的浓缩版。&lt;/strong&gt;&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id=&#34;三claudemd给-ai-的入职培训&#34;&gt;三、CLAUDE.md：给 AI 的入职培训&lt;/h2&gt;
&lt;p&gt;CLAUDE.md 是 Claude Code 会话启动时自动读取的文件。它的作用很像新员工入职手册，但比那更关键：因为它决定了 Claude 在你项目里的&amp;quot;默认行为&amp;quot;。&lt;/p&gt;
&lt;p&gt;我花了点时间打磨自己的 CLAUDE.md，几条原则：&lt;/p&gt;
&lt;h3 id=&#34;1-保持简短&#34;&gt;1. 保持简短&lt;/h3&gt;
&lt;p&gt;Claude 能稳定遵循的指令数量有限，系统提示已经占了一部分。写太多，它只会随机忽略。我的 CLAUDE.md 一般不超过两屏。&lt;/p&gt;
&lt;h3 id=&#34;2-只写项目特有信息&#34;&gt;2. 只写项目特有信息&lt;/h3&gt;
&lt;p&gt;不要解释&amp;quot;组件目录是什么&amp;quot;这种通用知识。要写真正影响决策的东西：关键 bash 命令、构建脚本、测试命令、提交规范、技术约束。&lt;/p&gt;
&lt;h3 id=&#34;3-写为什么不只是做什么&#34;&gt;3. 写&amp;quot;为什么&amp;quot;，不只是&amp;quot;做什么&amp;quot;&lt;/h3&gt;
&lt;p&gt;比如：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;差：&amp;ldquo;使用 Java 17&amp;rdquo;。&lt;/li&gt;
&lt;li&gt;好：&amp;ldquo;使用 Java 17，因为部分依赖在 Java 21 下存在兼容性问题，计划在 Q4 统一升级。&amp;rdquo;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;原因能让 Claude 在你没想到的地方做出正确判断。&lt;/p&gt;
&lt;h3 id=&#34;4-持续更新&#34;&gt;4. 持续更新&lt;/h3&gt;
&lt;p&gt;工作时长按 &lt;code&gt;#&lt;/code&gt; 键，Claude 会自动把指令写进 CLAUDE.md。我的标准是：当我第二次纠正同一个问题时，就把它固化为规则。&lt;/p&gt;
&lt;p&gt;坏的 CLAUDE.md 像写给新人的文档；好的 CLAUDE.md 像写给&amp;quot;未来失忆的自己&amp;quot;的笔记。&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id=&#34;四上下文窗口不是越用越好&#34;&gt;四、上下文窗口不是越用越好&lt;/h2&gt;
&lt;p&gt;Opus 4.5 的上下文窗口很长，但很多人忽略了一个事实：&lt;strong&gt;上下文用到 20%–40% 时，输出质量就开始下降了。&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;每次消息、每个文件、每段生成代码、每次工具输出都会累积。等会话变得臃肿，即使 &lt;code&gt;/compact&lt;/code&gt; 也救不回来，因为能力已经劣化了。&lt;/p&gt;
&lt;p&gt;我的做法：&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;code&gt;SCRATCHPAD.md&lt;/code&gt; 或 &lt;code&gt;plan.md&lt;/code&gt;，把中间结论落地到文件系统。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;复制-压缩-清空-粘贴法&lt;/strong&gt;：重要信息复制出来，&lt;code&gt;/compact&lt;/code&gt; 总结，再 &lt;code&gt;/clear&lt;/code&gt;，只粘回关键内容。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;知道何时清空&lt;/strong&gt;：会话一旦混乱，直接 &lt;code&gt;/clear&lt;/code&gt;。CLAUDE.md 还在，项目规则不会丢。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;正确的心智模型是：&lt;strong&gt;把 Claude 当成无状态的&lt;/strong&gt;。状态应该由文件系统、版本控制、外部记忆来维护，而不是由会话历史来维护。&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id=&#34;五提示词是沟通不是咒语&#34;&gt;五、提示词是沟通，不是咒语&lt;/h2&gt;
&lt;p&gt;我反复说的一句话是：提示词不是玄学，是沟通。清晰永远优于模糊。&lt;/p&gt;
&lt;p&gt;有效的提示通常包含三层：&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;：Claude 喜欢过度工程化，必须明确限制；&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;约束和原因&lt;/strong&gt;：是原型还是生产代码？性能敏感还是可读性优先？为什么？&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;比如我会这样写：&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;请为 &lt;code&gt;VideoRenderWorker&lt;/code&gt; 添加一个重试机制。要求：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;最多重试 3 次，使用指数退避；&lt;/li&gt;
&lt;li&gt;只对临时性错误重试，业务逻辑错误直接失败；&lt;/li&gt;
&lt;li&gt;不要引入新的依赖，使用现有的 Spring Retry 配置；&lt;/li&gt;
&lt;li&gt;这是生产代码，需要单元测试覆盖。&lt;/li&gt;
&lt;/ol&gt;
&lt;/blockquote&gt;
&lt;p&gt;这样的输入，输出基本可以直接进入 Code Review。&lt;/p&gt;
&lt;p&gt;另外记住：&lt;strong&gt;输出只来自输入&lt;/strong&gt;。如果你用好模型仍然得到坏结果，问题通常在你——你的提示写法、请求结构、上下文提供方式。&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id=&#34;六模型路由让合适的模型做合适的事&#34;&gt;六、模型路由：让合适的模型做合适的事&lt;/h2&gt;
&lt;p&gt;Claude 的不同模型有明确的分工：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Sonnet&lt;/strong&gt;：更快更便宜，适合执行明确的编码任务；&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Opus&lt;/strong&gt;：更慢更贵，适合复杂规划、架构设计、深度推理。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;我的常用模式是：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;用 &lt;strong&gt;Opus&lt;/strong&gt; 做架构规划和复杂方案设计；&lt;/li&gt;
&lt;li&gt;用 &lt;strong&gt;Sonnet&lt;/strong&gt; 执行实现、补全代码、跑测试；&lt;/li&gt;
&lt;li&gt;用 &lt;strong&gt;CLAUDE.md&lt;/strong&gt; 保证模型切换后仍然遵循相同的项目规则。&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;这和团队里让资深架构师画蓝图、让工程师写代码是一个道理。Claude Code 里切换模型成本很低，但前提是你知道什么任务该用什么模型。&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id=&#34;七mcphooksslash-命令与-skills&#34;&gt;七、MCP、Hooks、Slash 命令与 Skills&lt;/h2&gt;
&lt;p&gt;Claude Code 的工具生态值得花时间探索。除了前面提到的 MCP 和 Hooks，&lt;strong&gt;Skills（技能）&lt;/strong&gt; 是我最近用得越来越多的能力，它把常用工作流封装成可复用的指令包。&lt;/p&gt;
&lt;h3 id=&#34;1-mcphooks-和-slash-命令&#34;&gt;1. MCP、Hooks 和 Slash 命令&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;MCP&lt;/strong&gt;：连接外部服务。如果你还在手动复制粘贴信息进 Claude，很可能 MCP 能帮你自动化。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Hooks&lt;/strong&gt;：在 Claude 修改代码前后执行操作，比如自动格式化、类型检查、跑 lint。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;自定义 Slash 命令&lt;/strong&gt;：把常用的提示词模板化，避免每次重复输入。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;我在项目里配了几个常用 Slash 命令：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;/review&lt;/code&gt;：让 Claude 按项目规范做 Code Review；&lt;/li&gt;
&lt;li&gt;&lt;code&gt;/test&lt;/code&gt;：为当前修改生成单元测试；&lt;/li&gt;
&lt;li&gt;&lt;code&gt;/doc&lt;/code&gt;：为新增接口补全文档。&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;2-skills把个人经验变成团队能力&#34;&gt;2. Skills：把个人经验变成团队能力&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;Skill 是什么？&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Skill 是一个 Markdown 文件（通常是 &lt;code&gt;SKILL.md&lt;/code&gt;），带有 YAML frontmatter。它描述了一个完整的工作流、判断标准或领域知识。Claude 会在合适的时机自动加载它，或者你可以通过 &lt;code&gt;/skill &amp;lt;name&amp;gt;&lt;/code&gt; 手动调用。&lt;/p&gt;
&lt;p&gt;你可以把 Skill 理解为&amp;quot;可插拔的专长&amp;quot;：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;CLAUDE.md&lt;/code&gt; 是项目通用的&amp;quot;入职培训&amp;quot;，始终加载；&lt;/li&gt;
&lt;li&gt;&lt;code&gt;SKILL.md&lt;/code&gt; 是按需加载的&amp;quot;专项手册&amp;quot;，只在匹配的场景触发。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Skill 放在哪里？&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;有两种常见位置：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;个人级&lt;/strong&gt;：&lt;code&gt;~/.claude/skills/&amp;lt;skill-name&amp;gt;/SKILL.md&lt;/code&gt;，跨项目可用；&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;项目级&lt;/strong&gt;：&lt;code&gt;.claude/skills/&amp;lt;skill-name&amp;gt;/SKILL.md&lt;/code&gt;，跟随仓库走，团队成员共享。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;我推荐项目级 Skill，因为团队规范应该和代码放在一起，而不是依赖每个人的本地配置。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;一个最小 SKILL.md 示例：&lt;/strong&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-markdown&#34; data-lang=&#34;markdown&#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;name: spring-api-review
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;description: 当用户请求对 Spring Boot API 代码进行 Review 时调用此 skill。
&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;# Spring Boot API Review 规范
&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:#75715e&#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;1.&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;2.&lt;/span&gt; 服务层是否处理业务逻辑，而不是直接操作 HTTP 上下文？
&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;3.&lt;/span&gt; DTO 是否有清晰的入参/出参边界？
&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;4.&lt;/span&gt; 异常是否统一处理，而不是在每个方法里 try-catch？
&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;5.&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:#75715e&#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:#66d9ef&#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;-&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;-&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;p&gt;&lt;code&gt;description&lt;/code&gt; 字段非常关键。Claude 会根据它判断何时自动加载这个 Skill。描述越具体，触发越准确。&lt;/p&gt;
&lt;h3 id=&#34;3-有哪些值得尝试的-skill&#34;&gt;3. 有哪些值得尝试的 Skill？&lt;/h3&gt;
&lt;p&gt;Claude Code 本身不内置大量固定 Skill，但社区已经沉淀了不少高质量 Skill 包。以下是我觉得对工程团队最有价值的几个方向：&lt;/p&gt;
&lt;table&gt;
	&lt;thead&gt;
			&lt;tr&gt;
					&lt;th&gt;Skill / Skill 包&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;strong&gt;gstack&lt;/strong&gt;&lt;/td&gt;
					&lt;td&gt;比较完整的一套工程 Skill 集合，覆盖 review、qa、investigate、ship、canary、retro 等&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;/review&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;预着陆 PR 审查，检查 SQL 注入、LLM 信任边界、副作用等结构性问题&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;/qa&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;系统化 QA 测试，发现 bug 后自动修复并验证&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;/investigate&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;系统性根因排查，要求&amp;quot;无根因不修复&amp;quot;&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;/ship&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;合并主分支、跑测试、生成 PR 的发布工作流&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;/canary&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;部署后监控异常、性能回归、页面失败&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;/retro&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;基于提交历史做工程复盘&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;strong&gt;heliohq/ship&lt;/strong&gt;&lt;/td&gt;
					&lt;td&gt;更严格的分阶段流水线：spec → dev → E2E → review → QA → refactor → handoff&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;strong&gt;Cavestack&lt;/strong&gt;&lt;/td&gt;
					&lt;td&gt;强调&amp;quot;Hero Six&amp;quot;核心 Skill，包括 office-hours、investigate、plan-eng-review 等&lt;/td&gt;
			&lt;/tr&gt;
	&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;我个人用得比较多的是 &lt;code&gt;/review&lt;/code&gt;、&lt;code&gt;/investigate&lt;/code&gt; 和 &lt;code&gt;/ship&lt;/code&gt;。它们不是替代人的判断，而是把重复性的检查清单和流程自动化，让我把精力放在真正需要决策的地方。&lt;/p&gt;
&lt;h3 id=&#34;4-怎么创建自己的-skill&#34;&gt;4. 怎么创建自己的 Skill？&lt;/h3&gt;
&lt;p&gt;创建 Skill 的步骤很简单：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;新建目录&lt;/strong&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-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;mkdir -p .claude/skills/my-skill&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;写 SKILL.md&lt;/strong&gt;：包含 name、description、用途、步骤、输出格式、示例和约束。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;测试触发&lt;/strong&gt;：开一个新会话，描述一个匹配的场景，看 Claude 是否自动加载。如果没加载，调整 description 让它更具体。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;迭代优化&lt;/strong&gt;：使用一段时间后，把新发现的问题和约束补充进去。和 CLAUDE.md 一样，Skill 也是需要持续维护的。&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;我的建议是：不要一开始就写很多 Skill。先观察团队里哪些工作流是重复的、哪些判断标准是大家口头传颂的，把最常见的两三个固化成 Skill。质量比数量重要。&lt;/p&gt;
&lt;h3 id=&#34;5-skillclaudemdhooks-的分工&#34;&gt;5. Skill、CLAUDE.md、Hooks 的分工&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;CLAUDE.md&lt;/td&gt;
					&lt;td&gt;项目通用规则，始终加载&lt;/td&gt;
					&lt;td&gt;每次会话启动&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;SKILL.md&lt;/td&gt;
					&lt;td&gt;专项工作流，按需加载&lt;/td&gt;
					&lt;td&gt;匹配描述时自动加载，或 &lt;code&gt;/skill&lt;/code&gt; 手动调用&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;Hooks&lt;/td&gt;
					&lt;td&gt;代码修改前后的强制检查&lt;/td&gt;
					&lt;td&gt;触发编辑操作时&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;MCP&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;这几层叠加起来，才能把 Claude Code 从一个&amp;quot;聊天工具&amp;quot;变成符合团队工程规范的&amp;quot;协作系统&amp;quot;。&lt;/p&gt;
&lt;p&gt;这些小投入会不断复利。模型每周都在变好，但你的工具链、Skill 库和流程才是属于自己的护城河。&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id=&#34;八当-claude-卡住时换策略&#34;&gt;八、当 Claude 卡住时，换策略&lt;/h2&gt;
&lt;p&gt;Claude 有时会陷入循环：改了 A 导致 B 错，改了 B 又导致 A 错。这时候继续补充说明往往没用。&lt;/p&gt;
&lt;p&gt;我常用的策略：&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;ldquo;参考 &lt;code&gt;UserService.java&lt;/code&gt; 里的错误处理模式&amp;rdquo; 比 &amp;ldquo;请优雅地处理异常&amp;rdquo; 有效得多；&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;换种表述方式&lt;/strong&gt;：同一个需求用不同结构说一遍，有时能绕过模型的固化模式。&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;关键技能不是让 Claude 永远不出错，而是&lt;strong&gt;尽早识别循环，并及时切换策略&lt;/strong&gt;。&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id=&#34;九构建系统而不是一次性工具&#34;&gt;九、构建系统，而不是一次性工具&lt;/h2&gt;
&lt;p&gt;Claude Code 最大的价值，不在于帮你完成单次任务，而在于把它嵌入工程系统。&lt;/p&gt;
&lt;p&gt;它支持 headless 模式（&lt;code&gt;-p&lt;/code&gt;），可以脚本化、自动化、串联命令。企业已经在用它做：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;自动审 PR；&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;/ul&gt;
&lt;p&gt;我们的飞轮是：&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Claude 出错 → 改进 CLAUDE.md 或工具链 → 下次更好。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;几个月后，即使模型没变，整个系统也会显著提升。这就是复利。&lt;/p&gt;
&lt;p&gt;如果你只把 Claude Code 当成一个交互式聊天工具，你正在浪费它的大部分价值。&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id=&#34;十写给老工程师的话&#34;&gt;十、写给老工程师的话&lt;/h2&gt;
&lt;p&gt;用了 Claude Code 一段时间后，我发现一个有意思的现象：&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;经验丰富的工程师反而更容易用好它。&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;因为你知道什么是好的架构，什么是坏的妥协，什么是可以自动化的重复劳动，什么是必须人工把关的关键决策。Claude Code 不会替你承担责任，但它能把你的判断力和工程经验放大很多倍。&lt;/p&gt;
&lt;p&gt;对我来说，它最大的帮助不是写代码更快，而是：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;把重复性工作交给它，我腾出时间思考架构；&lt;/li&gt;
&lt;li&gt;用它快速验证想法，减少原型阶段的沉没成本；&lt;/li&gt;
&lt;li&gt;通过 CLAUDE.md 和工具链，把个人经验沉淀为团队能力。&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h2 id=&#34;总结&#34;&gt;总结&lt;/h2&gt;
&lt;p&gt;把 Claude Code 用好，核心就几句话：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;先思考，再输入；&lt;/li&gt;
&lt;li&gt;架构描述决定代码质量；&lt;/li&gt;
&lt;li&gt;CLAUDE.md 是杠杆点；&lt;/li&gt;
&lt;li&gt;上下文在用到 30% 时就开始劣化；&lt;/li&gt;
&lt;li&gt;提示词是沟通，输出来自输入；&lt;/li&gt;
&lt;li&gt;让 Opus 规划，让 Sonnet 执行；&lt;/li&gt;
&lt;li&gt;善用 MCP、Hooks、Slash 命令，更要善用 Skills；&lt;/li&gt;
&lt;li&gt;卡住时换策略；&lt;/li&gt;
&lt;li&gt;构建系统，而不是只做一次性任务。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;现代 AI 工具已经强得离谱。你是在和工具对抗，还是顺势而行，往往取决于这些细节。&lt;/p&gt;
&lt;hr&gt;
&lt;blockquote&gt;
&lt;p&gt;我在 ftmao.com/blog 持续记录 AI 工程、Agent 设计与 Claude Code 等工具的落地实践，欢迎关注和交流。&lt;/p&gt;
&lt;/blockquote&gt;
</description>
    </item>
    
  </channel>
</rss>
