<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/">
  <channel>
    <title>唐小锋的写作</title>
    <link>https://xiaofeng.dev/writing/</link>
    <description>AI Coding、Agent、RAG、企业 AI、业务流程智能化和产品工程管理相关长文章、调研与轻量作品索引。</description>
    <language>zh-CN</language>
    <lastBuildDate>Fri, 28 Aug 2026 16:00:00 GMT</lastBuildDate>
    <atom:link href="https://xiaofeng.dev/rss.xml" rel="self" type="application/rss+xml" />
    <item>
      <title><![CDATA[Skill 是方法论，工作流是流程]]></title>
      <link>https://xiaofeng.dev/writing/skill-methodology-workflow-process/</link>
      <guid>https://xiaofeng.dev/writing/skill-methodology-workflow-process/</guid>
      <pubDate>Sat, 29 Aug 2026 00:00:00 GMT</pubDate>
      <description><![CDATA[市场上对 Skill 有几种不同的认知。前几天腾讯开发者论坛发了一篇文章，说 Skill 是"带文档的脚本"。]]></description>
      <content:encoded><![CDATA[<p>市场上对 Skill 有几种不同的认知。前几天腾讯开发者论坛发了一篇文章，说 Skill 是&quot;带文档的脚本&quot;。</p>
<p>但根据我的经验，这个定义太窄了。</p>
<p>今年年初 Gemini CLI 的 GitHub 上有一个 issue <a href="https://github.com/google-gemini/gemini-cli/issues/15895">#15895</a>，对 Skill 给出了一个非常好的定义：<strong>Skill 是方法论，不是脚本加文档。</strong> 这句话非常好地总结了我之前的经验。</p>
<p>我在 Dify 和扣子上都开发过工作流，也深度使用过各种 Skill。从实际使用的角度来说，它们之间有许多使用上不能忽视的区别：</p>
<table>
<thead>
<tr>
<th>维度</th>
<th>工作流（Workflow）</th>
<th>Skill</th>
</tr>
</thead>
<tbody>
<tr>
<td>本质</td>
<td>流程</td>
<td>方法论</td>
</tr>
<tr>
<td>AI 视角</td>
<td>黑盒（只看到单节点）</td>
<td>白盒（全貌可见）</td>
</tr>
<tr>
<td>灵活性</td>
<td>固化，不可逃逸</td>
<td>可裁剪、可干预</td>
</tr>
<tr>
<td>维护</td>
<td>节点多时困难</td>
<td>按需加载，轻量</td>
</tr>
<tr>
<td>AI 角色</td>
<td>语义工具（局部调用）</td>
<td>全局编排者</td>
</tr>
</tbody>
</table>
<h2>工作流：有向无环的黑盒</h2>
<p>工作流是一个带有明确流程限制的有向无环图（DAG），它意味着：不能从一个节点在没有路径或连接线的情况下直接跳到另一个节点，必须沿着预设的流程走。</p>
<pre><code class="language-mermaid">flowchart TD
  Start([开始]) --&gt; CondA{条件判断 A}
  Start --&gt; CondB{条件判断 B}
  CondA --&gt; ExecA1[执行节点 A1]
  CondB --&gt; ExecB1[执行节点 B1]
  ExecA1 --&gt; Merge[合并结果]
  ExecB1 --&gt; Merge
  Merge -.-&gt;|禁止回边| CondA
</code></pre>
<p>对绝大多数用户来说，工作流是一个黑盒。你感觉不到它到底是 10 个节点、20 个节点还是上百个节点——只有开发者才需要关心这些。用户只管用，但很难了解内部到底有哪些流程、哪些异常分支、哪些地方需要人工介入。</p>
<p><strong>优点是流程固化。</strong> 用户不会从流程中逃逸出去，可以得到确定性的结论，不会出现完全异常、无法控制的结果。</p>
<p><strong>缺点也很明显。</strong></p>
<ul>
<li>当工作流超过几十个甚至上百个节点时，维护起来会非常困难。</li>
<li>工作流天然需要脚本作为粘合剂，把节点的输入输出对接起来——上一个节点的输出就是下一个节点的输入，中间有大量的胶水代码。</li>
<li>AI 在工作流中的作用，只是其中某几个需要智能判断的关键节点，没有承担整个流程的规划，也没有总揽全局，仅仅作为一个语义工具被调用。</li>
</ul>
<h2>Skill：白盒的方法论</h2>
<p>Skill 会被加载到 AI 的提示词中。AI 先阅读 Skill，然后按照 Skill 来执行相应的步骤。它知道整个 Skill 从开始到结束会经过哪些流程、有哪些步骤，知道哪些地方需要用户确认、哪些地方允许用户选择，甚至知道怎么让用户退出，以及如何把步骤交接给下一个 Skill。</p>
<p>对 AI 来说，工作流是黑盒的，它只能看到一个节点；但 Skill 是完全的白盒。</p>
<pre><code class="language-mermaid">flowchart TD
  AI2[&quot;AI · 加载、编排、调度&quot;]
  subgraph Skill[&quot;Skill 方法论 · 全部可见&quot;]
    direction LR
    S1[&quot;步骤1&lt;br/&gt;读取需求&quot;] --&gt; S2[&quot;步骤2&lt;br/&gt;分析数据&quot;] --&gt; S3[&quot;步骤3&lt;br/&gt;生成方案&quot;] --&gt; S4[&quot;步骤4&lt;br/&gt;交付结果&quot;] --&gt; S5[&quot;步骤5&lt;br/&gt;沉淀复盘&quot;]
  end
  AI2 -.-&gt;|&quot;加载&quot;| Skill
</code></pre>
<p>因为 AI 看到的是完整的方法论，而不是单个节点，所以它可以灵活地选择执行方式：</p>
<ol>
<li><strong>完整执行</strong>：按步骤 1→2→3→4 走完</li>
<li><strong>部分提取</strong>：只取其中一两个步骤，跳过不需要的环节</li>
<li><strong>用户裁剪</strong>：按用户指令修改某一步骤，调整后再继续</li>
</ol>
<pre><code class="language-mermaid">flowchart TD
  Start[&quot;AI 阅读 Skill 方法论&quot;]
  Start --&gt; Mode1[&quot;完整执行&quot;]
  Start --&gt; Mode2[&quot;部分提取&quot;]
  Start --&gt; Mode3[&quot;用户裁剪&quot;]

  Mode1 --&gt; M1[&quot;1 → 2 → 3 → 4&lt;br/&gt;全部执行&quot;]
  Mode2 --&gt; M2[&quot;跳过 1、4&lt;br/&gt;只取步骤 2 和 3&quot;]
  Mode3 --&gt; M3[&quot;步骤 3 被修改为 3'&lt;br/&gt;按用户指令调整&quot;]
</code></pre>
<p>这种灵活性就是方法论的本质：它是一套经验性的指导原则，让你学习并可选择性地使用它。</p>
<h2>什么时候选哪个</h2>
<p>当你作为一个开发者或者专业用户，需要写 Skill 或流程的时候，你要先判断：这是一个方法论，还是一个流程？</p>
<p>这个问题的核心区分是<strong>控制权归谁</strong>：</p>
<ul>
<li><strong>需要确定性、自上而下管控的场景</strong>（公司审批链路、数据处理管道、固定业务流程）——工作流更合适。流程固化的价值在于，不需要使用者做选择，也不会有人从流程中逃逸。</li>
<li><strong>面向个人或团队效率提升的场景</strong>——Skill 更合适。因为很多时候我们不能强迫别人，方法论的意义在于让专业用户理解后自愿遵循，而不是被流程绑住。</li>
</ul>
<h2>对专业使用者：先用后改</h2>
<p>Skill 的使用者通常是或者说“需要是”专业用户。这和工作流的使用者有本质区别——工作流不需要你理解，你只要照着走就行；但 Skill 的使用者需要理解方法论，才能用好它、改好它。</p>
<p>如果你拿到了别人写的 Skill，首先当然可以用它来完成工作。但更重要的是：</p>
<ol>
<li><strong>你可以选择忽略或修改 Skill 中的某些步骤</strong>，干预它，让它按照你的想法执行。</li>
<li><strong>你可以裁剪 Skill，把它改成你想要的版本。</strong> 市场上大部分 Skill 都代表了作者个人的见解和经验。如果你想让它完美符合你个性化的工作流，你需要对原来的 Skill 进行修改，发明自己的 Skill。这是方法论的终局——不是照搬，而是内化后重造。</li>
</ol>
<p>还有一个隐含的因素：<strong>你需要让 Skill 反过来教会你这套方法论。</strong> Skill 的使用者需要了解这个 Skill 是怎么用的，才能真正驾驭它。</p>
<h2>一个值得注意的趋势：让 AI 参与全流程</h2>
<p>之前我聊到过 <a href="/writing/compound-engineering-agent-skill/">Compound Engineering 这个插件</a>，它做了一件非常激进的事：把子智能体（sub-agent）的调用完全改成了纯粹的 Skill markdown。</p>
<p>其中有一个重要的理由：调用子智能体时，某些上下文、工具调用结果或 harness 的结果无法传递到子智能体，而且各家平台对智能体的实现方式也不统一。子智能体本质上是把 AI 关进了一个个黑盒，彼此看不到对方的上下文。</p>
<p>与其费力解决跨智能体的信息传递，不如让所有智能体都变成 Skill 的模式——这样可以直接复用完整的上下文和 harness 结果，模型在整个流程中的表现会更加优异。</p>
<p>这背后其实就是白盒的红利：<strong>打开可见度，AI 看到的信息越完整，表现就越好。</strong> 子智能体的调用模式相当于把流程重新切成黑盒节点，而 Skill 模式把整个方法论和全部上下文都暴露给 AI，让它在完整可见的基础上做判断和调度。这个过程中，Skill 是一本经验性的手册，初期可以发挥作用，在更加长程的任务中，让它自己判断，比经验更重要。</p>
]]></content:encoded>
    </item>
    <item>
      <title><![CDATA[Vibe Coding等待期间可以做什么？]]></title>
      <link>https://xiaofeng.dev/writing/vibe-coding-waiting-time/</link>
      <guid>https://xiaofeng.dev/writing/vibe-coding-waiting-time/</guid>
      <pubDate>Sun, 23 Aug 2026 00:00:00 GMT</pubDate>
      <description><![CDATA[我以前做 Vibe Coding 的时候，通常会开几个窗口，同时执行几个任务。这样可以比较好地利用时间，让 AI 去完成不同的需求。不过，这样做有几个前提：]]></description>
      <content:encoded><![CDATA[<p>我以前做 Vibe Coding 的时候，通常会开几个窗口，同时执行几个任务。这样可以比较好地利用时间，让 AI 去完成不同的需求。不过，这样做有几个前提：</p>
<ul>
<li>需求尽量相互隔离，避免互相影响。</li>
<li>代码需要提前做好模块化设计。</li>
<li>尽量避免多个任务同时修改同一块代码。</li>
</ul>
<p>但即使开了多个窗口，还是会有等待的时间。这个时候可以去喝咖啡、站起来走一走。</p>
<p>不过最近我越来越觉得，<strong>Vibe Coding 期间的空档，不一定要用来堆更多开发任务</strong>。这个时间其实很适合做一些研究型任务。</p>
<h2>不要只开更多窗口</h2>
<p>人的记忆力和注意力是有限的。你很难真正同时理解七八个任务，更不用说这些任务如果都在同一个代码仓库里，很容易互相影响。过一段时间回头来看，甚至会不清楚某个改动究竟是为了解决什么问题。</p>
<p>少做几个开发任务，反而能留下时间审查 AI 的产出：</p>
<ul>
<li>它有没有引入重复代码？</li>
<li>有没有破坏原来的结构？</li>
<li>有没有为了完成一个小需求，把代码库变得更难维护？</li>
</ul>
<p>这些审查工作通常需要借助外部搜索和研究，补充 AI 无法替我们判断的信息，再把结果带回开发过程中。</p>
<h2>研究什么？</h2>
<p>这里说的研究，不一定是系统地学习一门新学科，也可以是了解一个领域、验证一种做法，或者想清楚当前需求应该怎么做得更好。按照研究对象来看，大致有三类。</p>
<h3>研究实现方案</h3>
<p>比如现在的模块边界是否合理，有没有重复的逻辑，哪些地方未来会比较难维护。AI 可以帮我完成一个具体需求，但我仍然需要回过头看一看：它这次的实现，是否让整个代码库变得更复杂了。有没有更成熟的实现方案，当前方案里又有哪些妥协？</p>
<p>比如：</p>
<ul>
<li>有没有更合适的部署方案？</li>
<li>有没有性能方面的问题？</li>
<li>实现同一个动效时，不同框架有什么区别？</li>
<li>有没有合适的工具或 Skill，可以帮助审查和开发？</li>
</ul>
<h3>研究产品和竞品</h3>
<p>需求清单里的每一项都值得做吗？有没有更简单的实现方式？竞品是怎么解决类似问题的？这些都可以让 AI 帮忙搜索和整理。它也可以打开浏览器，查看竞品网站，把页面布局、功能流程和交互特点整理成一份文档，后续再作为设计和开发的参考。</p>
<ul>
<li>做官网时，页面布局、产品展示方式和动效，都不是 AI 随便生成一版就结束了。你需要去看看类似网站是怎么做的，再决定哪些做法适合自己的产品。</li>
<li>做 Landing Page 时，可能会涉及好几个流程，流程之间的关系也比较复杂。这时可以先研究一下行业里的常见做法，再选择一种适合当前产品的方案，而不是让 AI 直接替你拍板。</li>
<li>做语义分析时，可以先研究当前常见的实现方案，再权衡效果、成本和实现复杂度，看看是否能形成相对竞品的优势。</li>
</ul>
<h3>研究新的领域</h3>
<p>开发工作经常会涉及之前不了解的领域，这时更需要大量搜索和研究：</p>
<ul>
<li>如果你在做数据分析模块，就需要了解需要用到哪些统计方法，理解置信区间等概念；</li>
<li>如果你在做 AI 搜索功能，就需要研究查询扩展、多轮搜索和结果汇总这些底层原理；</li>
<li>如果你在研究 AI 的工具调用，就可以进一步了解提示词、工具编排、Harness Engineering，以及相关的论文和实践。</li>
</ul>
<p>这些内容看起来可能离眼前的代码有一点距离，但它们都会影响最后的实现方式。<strong>研究不是离开项目，而是在给项目补充判断依据。</strong></p>
<h2>蚂蚁也不会只沿着最浓的信息素走</h2>
<p>这让我想到蚂蚁。</p>
<p>蚂蚁的路径选择，并不是对信息素的机械服从。已有路径上的信息素会提高蚂蚁选择这条路的概率，但不会让所有蚂蚁都沿着信息素浓度最高的方向行动。蚁群始终保留一定程度的探索，让个体继续尝试还没有被充分探索的路径；当新的路径获得更好的结果时，它上面的信息素逐渐增强，群体的选择概率也会随之改变。</p>
<p>这其实是一种动态的<strong>探索—利用机制</strong>：既利用已有经验，又不放弃对未知空间的探索。正是因为信息素会影响选择，但不会完全决定选择，才有助于降低蚁群过早收敛到次优路径的风险。</p>
<p>Vibe Coding 也有点像这样。AI 已经走过的路径、已经验证过的组件和实现方式，可以提高下一次选择它们的概率；但如果我们只让 AI 沿着已有路径继续生成，很可能会越来越快地把问题做偏。开发过程中留出时间去研究、比较和尝试，其实就是给系统保留一点探索。</p>
<p>所以，Vibe Coding 期间做研究，不是暂时离开开发，也不是把时间浪费在旁支上。它是在已经有经验的路径之外，再看几条路，避免我们过早把“能跑”当成“最合适”。</p>
<p>关于这种探索—利用关系，相关研究后来也启发了蚁群优化（Ant Colony Optimization, ACO），并被用于解决组合优化问题。这里不展开算法细节，重要的是记住这个直觉：<strong>经验应该影响选择，但不应该取消探索。</strong></p>
]]></content:encoded>
    </item>
    <item>
      <title><![CDATA[查询扇出详解：从 Google 专利到 17 万 URL 实证]]></title>
      <link>https://xiaofeng.dev/writing/ai-search-query-fanout/</link>
      <guid>https://xiaofeng.dev/writing/ai-search-query-fanout/</guid>
      <pubDate>Sat, 22 Aug 2026 00:00:00 GMT</pubDate>
      <description><![CDATA[在 AI 搜索中，一个复杂问题可能不会只对应一次检索。系统可以将用户问题扩展或拆解为多个相关子查询，并行或分阶段检索，再将多路结果合成为回答。这类"一进多出"的检索过程通常被称为查询扇出（query fan-out）。]]></description>
      <content:encoded><![CDATA[<p>在 AI 搜索中，一个复杂问题可能不会只对应一次检索。系统可以将用户问题扩展或拆解为多个相关子查询，并行或分阶段检索，再将多路结果合成为回答。这类&quot;一进多出&quot;的检索过程通常被称为查询扇出（query fan-out）。</p>
<h2>可以观察到的查询扇出现象</h2>
<p>用同一个问题问不同的 AI 助手，你会看到截然不同的查询扇出行为。</p>
<p>「一千万内最好的玩具是什么？」</p>
<p>这个查询在不同平台上的表现：豆包会展开子查询并展示检索路径（搜索 6 个关键词 / 参考 33 篇资料）；Perplexity 和 Kimi 会列出&quot;搜索网页&quot;下的多个来源与相关检索，但没有逐条展示子查询文本；Google AI Mode 执行查询扇出但部分场景不展示中间过程，直接给出聚合后的答案；ChatGPT 的 Search 模式行为最不透明——只展示来源列表，不公开子查询生成逻辑和并行搜索数量。</p>
<div class="article-image-strip" aria-label="不同 AI 助手的查询扇出示例">
  <figure>
    <img src="/writing/wechat-tech-assets/ai-search-query-fanout/doubao-search-example.png" alt="豆包：搜索 6 个关键词，参考 33 篇资料，并列出 6 条子查询" loading="lazy" decoding="async" />
    <figcaption>豆包：展示 6 条子查询</figcaption>
  </figure>
  <figure>
    <img src="/writing/wechat-tech-assets/ai-search-query-fanout/perplexity-search-example.png" alt="Perplexity：列出搜索网页下的多个来源" loading="lazy" decoding="async" />
    <figcaption>Perplexity：展示多个来源</figcaption>
  </figure>
  <figure>
    <img src="/writing/wechat-tech-assets/ai-search-query-fanout/kimi-search-example.png" alt="Kimi：展示搜索网页及 28 个结果" loading="lazy" decoding="async" />
    <figcaption>Kimi：展示搜索结果</figcaption>
  </figure>
  <figure>
    <img src="/writing/wechat-tech-assets/ai-search-query-fanout/google-ai-mode-example.png" alt="Google AI Mode：未展示中间子查询" loading="lazy" decoding="async" />
    <figcaption>Google AI Mode：聚合后回答</figcaption>
  </figure>
  <figure>
    <img src="/writing/wechat-tech-assets/ai-search-query-fanout/chatgpt-search-example.png" alt="ChatGPT：展示 27 条来源，未展示子查询生成过程" loading="lazy" decoding="async" />
    <figcaption>ChatGPT：只展示来源列表</figcaption>
  </figure>
</div>
<p>这种差异说明，查询扇出（query fan-out）已经成为 AI 搜索领域广泛讨论的一类检索架构，但不同平台对其实现方式、命名和透明度并不相同。在公开资料层面，Google 的描述目前最直接：官方产品文档明确使用了 'query fan-out' 这一术语，并公开描述了其基本行为。</p>
<h2>英文词源</h2>
<p>Fan-out 的词根可追溯到拉丁语 <em>vannus</em>：</p>
<blockquote>
<p><em>vannus</em>（扬谷工具）→ <em>fann</em>（扬谷）→ fan（产生气流的装置）→ fan（扇子）→ <strong>fan out</strong>（像扇子一样展开）</p>
</blockquote>
<p>动词短语 <em>fan out</em> 至少在 1590 年代已经出现，意思就是&quot;像手持扇子一样展开&quot;。AI 搜索借用它的含义：将一个用户查询展开为多个子查询，一次输入，多路搜索。</p>
<h2>官方解读</h2>
<p>Google 的官方文档给出了明确定义：</p>
<blockquote>
<p><strong>&quot;a set of concurrent, related queries generated by the model&quot;</strong>
（由模型生成的一组并发、相关的查询）</p>
</blockquote>
<p>Google 并未公开说明当前 AI Mode 的查询扇出实现具体对应哪些专利，但从 2025 年 5 月起，AI Mode 官方介绍、Google I/O 演讲、Search Central 文档、多模态搜索和 Shopping 等多个官方渠道反复确认查询扇出在产品中的实际部署——将其拆解为子主题并行搜索、跨数据源检索、合成带引用的回答。官方资料也从两个角度描述了这项机制：专利揭示技术原理，产品博文展示真实部署。其中 US11663201B2 直接揭示了&quot;子查询怎么生成&quot;；另有三篇官方产品博文具体展示了查询扇出在 AI Mode 中的实际表现，是下图流程图中&quot;并行检索跨多个数据源&quot;环节的现实依据：</p>
<h3>US11663201B2 — Query Variant Generation：子查询怎么生成</h3>
<p>专利 <a href="https://patents.google.com/patent/US11663201B2/en">US11663201B2</a>（Generating query variants using a trained generative model，Google LLC，申请 2018-04-27，授权 2023-05-30）描述了查询扇出的核心环节——如何用训练好的序列到序列（seq2seq）神经网络（架构类似机器翻译）将一个用户查询转换为多个查询变体（query variants）。专利还描述了控制模型，用于判断是否生成查询变体；这可以作为理解查询扇出控制逻辑的技术参考。</p>
<p>专利权利要求 19（Claim 19）直接列举了八种查询变体类型：</p>
<table>
<thead>
<tr>
<th>#</th>
<th>类型</th>
<th>说明</th>
<th>示例</th>
</tr>
</thead>
<tbody>
<tr>
<td>1</td>
<td>Equivalent Query（同义查询）</td>
<td>同一意图的不同表述</td>
<td>&quot;移动电源推荐&quot;、&quot;充电宝选购指南&quot;</td>
</tr>
<tr>
<td>2</td>
<td>Follow-up Query（追问查询）</td>
<td>用户了解原问题后自然会追问的</td>
<td>&quot;充电宝什么牌子最耐用&quot;、&quot;20000mAh 能用几天&quot;</td>
</tr>
<tr>
<td>3</td>
<td>Generalization Query（泛化查询）</td>
<td>更宽泛的类别上下文</td>
<td>&quot;便携充电设备推荐&quot;、&quot;出行数码配件清单&quot;</td>
</tr>
<tr>
<td>4</td>
<td>Specification Query（规格查询）</td>
<td>更具体、更明确的角度</td>
<td>&quot;20000mAh PD 快充充电宝&quot;、&quot;支持苹果 MFi 认证的&quot;</td>
</tr>
<tr>
<td>5</td>
<td>Canonicalization Query（规范化查询）</td>
<td>确定权威或标准版本</td>
<td>&quot;充电宝十大品牌排名&quot;、&quot;国家 3C 认证充电宝名单&quot;</td>
</tr>
<tr>
<td>6</td>
<td>Translation Query（翻译查询）</td>
<td>跨语言或跨术语的等效表达</td>
<td>&quot;best power bank 2025&quot;、&quot;PD 快充 英文&quot;</td>
</tr>
<tr>
<td>7</td>
<td>Entailment Query（蕴含查询）</td>
<td>原查询逻辑上必然涉及的内容</td>
<td>&quot;充电宝能带上飞机吗&quot;、&quot;容量虚标怎么看&quot;</td>
</tr>
<tr>
<td>8</td>
<td>Clarification Query（澄清查询）</td>
<td>消除歧义的请求</td>
<td>&quot;预算大概多少&quot;、&quot;自用还是送人&quot;（歧义未消无法精准推荐）</td>
</tr>
</tbody>
</table>
<h3>Google AI Mode 发布博文（2025-03）：query fan-out 的官方定义</h3>
<p>Google 官方博文 <a href="https://blog.google/products-and-platforms/products/search/ai-mode-search/">Expanding AI Overviews and introducing AI Mode</a>（Robby Stein，2025-03-05）是 AI Mode 的发布稿，也是 &quot;query fan-out&quot; 一词在 Google 官方语境中的核心出处。原文直接给出定义：&quot;It uses a 'query fan-out' technique, issuing multiple related searches concurrently across subtopics and multiple data sources and then brings those results together to provide an easy-to-understand response.&quot;——即并行发出多个相关搜索、跨子主题与多数据源、再聚合为易读回答，与下方流程图的结构一致。同一段列出 AI Mode 可触达的实时数据源：除高质量网页内容外，还有<strong>知识图谱（Knowledge Graph）</strong>、真实世界信息、以及数十亿商品的购物数据；这印证了流程图中知识图谱（Knowledge Graph）作为并行检索数据源之一的设定。底层模型为定制版 Gemini 2.0。</p>
<h3>Google Shopping AI Mode 博文（2025-05）：fan-out 在购物场景的印证</h3>
<p>Google 官方博文 <a href="https://blog.google/products-and-platforms/products/shopping/google-shopping-ai-mode-virtual-try-on-update/">Shop with AI Mode</a> 描述了 AI Mode 购物场景中的查询扇出：系统&quot;运行若干 simultaneous searches（并行搜索）&quot;来确定一个旅行包&quot;适合雨天和长途旅行&quot;需要哪些特性，再利用这些 subtopics（细分标准）推荐具有易取口袋的防水选项。底层结合 Gemini 与购物图谱（Shopping Graph，超 500 亿商品列表、每小时超 20 亿刷新）。</p>
<h3>Google 视觉搜索博文（2025-09）：视觉搜索扇出</h3>
<p>Google 官方博文 <a href="https://blog.google/products-and-platforms/products/search/search-ai-updates-september-2025/">AI Mode can now help you search and explore visually</a> 在查询扇出方法之上提出&quot;视觉搜索扇出（visual search fan-out）&quot;：分析图像后在后台 &quot;runs multiple queries in the background&quot;（运行多个查询），以理解完整视觉上下文。原文将查询扇出直接链接至 Google 官方 PDF（AI 概览 AI Overviews / AI Mode 说明），是一手官方定义来源。</p>
<h3>概念图：查询扇出的工作流程</h3>
<p>把 US11663201B2 专利与三篇 Google 官方产品博文放在一起，可以帮助我们理解 Google 相关技术中&quot;查询变体生成&quot;与&quot;产品级并行检索&quot;两个层面。其工作流程如下：</p>
<pre><code class="language-mermaid">flowchart LR
    A[用户查询] --&gt; B{意图分析}
    B --&gt;|简单事实| C[直接返回]
    B --&gt;|复杂多条件| D[查询分解]
    D --&gt; E1[子查询 1]
    D --&gt; E2[子查询 2]
    D --&gt; E3[子查询 3]
    D --&gt; E4[子查询 n]
    E1 --&gt; F1[实时网络（Live Web）]
    E2 --&gt; F2[知识图谱（Knowledge Graph）]
    E3 --&gt; F3[购物图谱（Shopping Graph）]
    E4 --&gt; F4[其他数据源]
    F1 --&gt; G[证据聚合]
    F2 --&gt; G
    F3 --&gt; G
    F4 --&gt; G
    G --&gt; H[大语言模型（LLM）合成回答]
</code></pre>
<blockquote>
<p>注意：概念化流程图，参考了 iPullRank 原文中的 <em>查询扇出图谱（Query Fan-Out Map）</em> 示意图，不代表 Google AI Mode 当前实际实现。</p>
</blockquote>
<h2>社区研究解读</h2>
<p>Google 专利和官方文档描述了查询扇出的技术框架，但社区研究补充了两个维度：<strong>实际效果数据</strong>和<strong>搜索引擎优化（SEO）/ 生成引擎优化（GEO）实操建议</strong>。以下逐一评估四篇代表性社区文章的可信度。</p>
<h3>iPullRank — 机制分析与意图偏移</h3>
<ul>
<li><strong>链接</strong>：<a href="https://ipullrank.com/expanding-queries-with-fanout">ipullrank.com/expanding-queries-with-fanout</a></li>
<li><strong>作者</strong>：Lazarina Stoy（MLforSEO 的创始人/顾问，文章发表于 iPullRank ），2025-12-11</li>
</ul>
<p><strong>核心观点</strong>：</p>
<ol>
<li>查询扇出是自移动优先索引（mobile-first indexing）以来搜索领域最大的结构性变革</li>
<li>多向量检索（multi-vector retrieval）迫使大语言模型（LLM）从多个文本片段（passage）拉取证据，而非依赖单一高排名页面——内容必须原子化、实体丰富、独立可检索</li>
<li>超个性化打破测量体系：同一查询对不同用户展开不同子查询，传统关键词排名工具失效</li>
<li>四平台对比：Google（最透明）、Copilot（迭代式、基于图谱 graph-grounded）、Perplexity（混合检索 + 多阶段排序 multi-stage ranking）、ChatGPT（最不透明）</li>
</ol>
<p><strong>评价</strong>：<strong>Solid，但意图偏移分析属理论推演</strong>。机制描述直接引用 Google 专利，八种查询变体分类有专利原文支撑，平台对比引用官方文档和 API 文档。Michael King 随后也在 Tech SEO Connect 分享了 Query Fan-out 相关内容。</p>
<h3>Surfer SEO — 173K-URL 实证数据</h3>
<ul>
<li><strong>链接</strong>：<a href="https://surferseo.com/blog/query-fan-out-impact/">surferseo.com/blog/query-fan-out-impact</a></li>
<li><strong>作者</strong>：Joshua Hardwick，2025-12-06</li>
</ul>
<p><strong>核心观点</strong>：</p>
<ol>
<li>样本 173,902 个 URL（10,000 个关键词的 top-10 页面），76% 的关键词触发了 AI 概览（AI Overviews）</li>
<li>排名查询扇出子查询越多，被 AI 概览（AIO, AI Overviews）引用概率越高（斯皮尔曼 Spearman 相关系数 0.77）</li>
<li>同时排名主查询 + 至少一条查询扇出的页面，被引用概率比只排名主查询高 161%</li>
<li>只排名查询扇出 vs 只排名主查询，前者被引用概率高 49%</li>
<li>67.82% 的 AI 概览（AIO）引用根本不在 top-10（主查询和查询扇出都不在）；但只看前 3 条引用，54.14% 在 top-10 内</li>
<li>仅约 27% 的查询扇出查询在多次搜索中保持稳定</li>
</ol>
<p><strong>评价</strong>：<strong>在本文考察的公开研究中，Surfer 是方法和样本披露最完整的一项实证研究</strong>：关键词数量、URL 数量、Gemini 提取查询扇出的步骤均透明，样本量足够，并明确声明&quot;相关不等于因果（correlation ≠ causation）&quot;。&quot;27% 稳定性&quot;数据指向查询扇出的高方差本质，有直接实践意义。文末推荐自家 Topical Map 工具，但工具推荐与研究数据明确分离，不影响数据可信度。</p>
<h3><a href="http://NextGrowth.ai">NextGrowth.ai</a> — 二手整理（数据有误）</h3>
<ul>
<li><strong>链接</strong>：<a href="https://nextgrowth.ai/query-fanout-ai-explained/">nextgrowth.ai/query-fanout-ai-explained</a></li>
<li><strong>作者</strong>：The Nguyen，2026-05-13</li>
</ul>
<p><strong>核心观点</strong>：</p>
<ol>
<li>AI 概览（AIO）引用率从 76% 降至 38%（标注来源&quot;ALM Corp&quot;）</li>
<li>8-16 条并行子查询，161% 引用提升，斯皮尔曼（Spearman）相关系数 0.77（标注来源&quot;ALM Corp&quot;）</li>
<li>26-50% 子查询覆盖率被引用更多，覆盖 100% 反而更差</li>
<li>40-60 词原子化段落，25.7% 新鲜度提升</li>
<li>五步优化法 + 工具推荐（Qforia / Profound / ZipTie / Otterly / AthenaHQ）</li>
</ol>
<p><strong>评价</strong>：<strong>数据有多处错误</strong>。① &quot;ALM Corp&quot;研究实为 Surfer SEO——来源误标；②&quot;76%→38% 引用率下降&quot;在 Surfer 原文中不存在（原文的 76% 指 AIO 触发率），系误读或混入其他来源；③ 文中编辑声明自己承认&quot;did NOT conduct our own 173K-URL crawl study&quot;&quot;Unverified URLs are cited as plain text&quot;。八种查询变体框架正确引用了 iPullRank，基本机制描述与 Google 官方文档一致——这部分可参考，但所有量化数据须以 Surfer 原文为准。<strong>GEO（生成引擎优化）领域目前存在明显的二手引用链污染：一项原始研究的数据被后续文章重新包装后，研究机构、数字含义甚至指标定义都可能发生变化。</strong></p>
<h3>Astiva AI — 厂商营销（方法论可用，数据不可引用）</h3>
<ul>
<li><strong>链接</strong>：<a href="https://astiva.ai/blog/content-hubs-ai-visibility">astiva.ai/blog/content-hubs-ai-visibility</a></li>
<li><strong>作者</strong>：Satish K（Astiva AI CEO），2026-06-19</li>
</ul>
<p><strong>核心观点</strong>：</p>
<ol>
<li>支柱页（pillar）+ 8-15 个辐射页（spoke）的中心辐射（hub-and-spoke）架构，引用率提升 2-3×</li>
<li>双向内链将引用率从 12% 提升至 41%</li>
<li>覆盖 5+ 子意图的页面引用概率高 3.2×</li>
<li>季度刷新、60-90 天新鲜度衰减、schema 标记提升引用 2.5×</li>
<li>五步建设法 + Detect → Diagnose → Displace → Prove 品牌化方法论</li>
</ol>
<p><strong>评价</strong>：<strong>厂商内容，方法论合理但数据链路不透明</strong>。重复了 NextGrowth 的两处错误（&quot;ALM Corp&quot;误标 + &quot;26-50% 甜点区&quot;），且&quot;2-3×&quot;&quot;12%→41%&quot;&quot;3.2×&quot;&quot;46%/67% 集中度&quot;等数字来源多为 Slate、FuelOnline、Position Digital、Growth Memo 等聚合站点或厂商研究，无原始可查链接。中心辐射（hub-and-spoke）方法论本身是行业常识，与 iPullRank/Surfer 方向一致，可参考框架，但不要直接引用数字。全文穿插自家产品介绍和定价 CTA，属典型的&quot;先造共识再卖工具&quot;营销结构。</p>
<h3>小结</h3>
<table>
<thead>
<tr>
<th>文章</th>
<th>性质</th>
<th>可信度</th>
<th>可直接引用</th>
</tr>
</thead>
<tbody>
<tr>
<td>iPullRank</td>
<td>行业研究 / 机制分析</td>
<td>高</td>
<td>机制分析和查询变体分类可参考；推测性结论需标注</td>
</tr>
<tr>
<td>Surfer SEO</td>
<td>一手实证研究</td>
<td>高</td>
<td>173K URL 等量化数据可直接引用</td>
</tr>
<tr>
<td>NextGrowth.ai</td>
<td>二手整理</td>
<td>低</td>
<td>机制描述可参考；量化数据不建议引用</td>
</tr>
<tr>
<td>Astiva AI</td>
<td>厂商营销</td>
<td>低</td>
<td>方法论可参考；量化数据不建议引用</td>
</tr>
</tbody>
</table>
<p>总体来看，关于查询扇出（Query Fan-out）的证据应按四类来源区分对待：Google 官方确认（AI Mode 部署与定义）、Google 专利描述（查询变体生成等技术原理，属历史背景而非当前实现）、社区实证研究（如 Surfer 的引用数据）、行业推测（如意图偏移推演）。尤其不能把后两者——社区研究与行业推测——包装成 Google 已确认的产品机制。</p>
]]></content:encoded>
    </item>
    <item>
      <title><![CDATA[AI搜索原理]]></title>
      <link>https://xiaofeng.dev/writing/ai-search-principles/</link>
      <guid>https://xiaofeng.dev/writing/ai-search-principles/</guid>
      <pubDate>Mon, 17 Aug 2026 00:00:00 GMT</pubDate>
      <description><![CDATA[如果你最近用过豆包、ChatGPT 这类 AI 助手，或者用过 Google 的 AI mode 做搜索，大概已经习惯了这种体验：输入一个问题，几秒钟后拿到一段组织好的答案，而不是一排等着你点开的蓝色链接。严格说，豆包、ChatGPT 是具备联网问答能力的 AI 助手，Google AI mode 才是把搜索本身...]]></description>
      <content:encoded><![CDATA[<p>如果你最近用过豆包、ChatGPT 这类 AI 助手，或者用过 Google 的 AI mode 做搜索，大概已经习惯了这种体验：输入一个问题，几秒钟后拿到一段组织好的答案，而不是一排等着你点开的蓝色链接。严格说，豆包、ChatGPT 是具备联网问答能力的 AI 助手，Google AI mode 才是把搜索本身 AI 化的形态；但它们在底层共享同一件事——用模型去检索、再组织出答案。圈内把这类系统叫做<strong>生成式引擎（Generative Engine）</strong>：和返回&quot;一排链接&quot;的传统搜索引擎不同，它返回的是一段写好的答案。</p>
<p>把这个过程拆开，是一条带反馈环的链路：</p>
<figure class="my-8">
  <img src="/writing/wechat-tech-assets/ai-search-geo/ai-search-flow.svg" alt="AI 搜索从理解问题、查询扩展、调用搜索到生成答案的检索流程" loading="lazy" decoding="async" />
  <figcaption class="mt-3 text-center text-[13px] text-[#6b6658]">AI 搜索是一条带反馈的检索与生成流程</figcaption>
</figure>
<h2>核心原理一：查询扩展（fan-out）</h2>
<p>以豆包为例。当你输入一个问题，AI 做的第一件事不是立刻去搜，而是先做查询扩展（query expansion）。这个概念早期就叫查询扩展，后来在不少系统里被叫做 fan-out——意思是把一个问题&quot;扇&quot;成多个检索方向。fan-out 决定的是搜索的<strong>宽度</strong>：一次把问题铺开成多少条并行的检索方向，决定了这次检索覆盖得有多广。</p>
<p><img src="/writing/wechat-tech-assets/ai-search-geo/fan-out-example.jpg" alt="fan-out 示例：一个问题被扩展为 3 个关键词"></p>
<p>上图是一个实际例子：用户问「经常打字的上班族应该选什么样的机械键盘？」，系统没有拿原句去搜，而是把它拆成 3 条并行的检索方向——分别从选购推荐、轴体对比、配列与人体工学三个角度切入，再综合参考 15 篇资料后组织答案。</p>
<p>它的做法是：先理解你的问题，再把它拆成不同的关键词去搜索。这里的&quot;拆&quot;，既有基于关键词的拆解，也有基于语义的重新理解——同一个问题，它可能会用不同的表述去搜，也可能直接提炼出几个隐含的子问题。</p>
<p>更关键的是，它不是一次性的。AI 会根据第一轮搜回来的网页内容和摘要，重新理解你的问题，然后自己决定还需要再搜几轮。换句话说，搜索的过程本身也是推理的过程——它边搜边想，再决定下一步问什么。</p>
<p>这意味着，AI 搜索的&quot;检索&quot;和你手动在搜索框敲关键词，是两种行为。它是带着一个动态的查询计划在工作，而不是执行一次静态的关键词匹配。</p>
<h2>核心原理二：检索预算（Search Budget）</h2>
<p>检索能往深处走多深，由一次任务愿意投入的 <strong>Search Budget（搜索预算）</strong> 决定——也就是它愿意为此跑多少轮、花多少时间。预算越足，迭代越深，产出的形态也越不一样。主流产品里常见的三种档位，差别其实就在这里：</p>
<ul>
<li><strong>快速回答</strong>：可能只检索一轮，拿到即时结果就组织回答。</li>
<li><strong>专家研究</strong>：通常会检索 3~5 轮，在多个方向上交叉验证。</li>
<li><strong>深度研究</strong>：会极大扩充搜索范围，往往跑几十轮甚至上百轮，最后完成任务的时间也显著更长。</li>
</ul>
<p><img src="/writing/wechat-tech-assets/ai-search-geo/search-budget-example.jpg" alt="Search Budget 示例：多轮「思考→搜索」交替进行"></p>
<p>上图是深度研究模式下的实际检索过程：系统交替执行「思考已完成」和「搜索」动作，每一轮思考都会触发新一轮检索——这就是 Search Budget 在运行时的直观表现。预算越充足，这个交替循环就跑得越久，覆盖的信息面也越广。</p>
<p>这就是你在豆包这类产品上看到的&quot;快速 / 专家 / 深度&quot;三种模式的本质区别——是分配给这次搜索的 Search Budget 不同：预算越多，检索轮次越深、耗时越长，结论通常也越扎实。为了避免 AI 过早答复，通常还会要求强制消耗搜索预算（budget forcing），避免 AI 凭借预训练的记忆回答。</p>
<p>宽度由 fan-out 决定，深度由 Search Budget 决定，这是 AI 搜索检索的两个独立维度。</p>
<h2>核心原理三：AI-friendly 的搜索 API</h2>
<p>前面讲 fan-out、讲检索轮次，说的是 AI 怎么&quot;想&quot;、怎么&quot;搜&quot;。但这些动作最终要落到取内容上——靠的是底层的搜索接口。而 AI 要的接口，和喂给传统搜索引擎的接口不是一回事。</p>
<p>传统网页搜索 API 返回的，是一排链接（可能附带一句摘要），它的服务对象是人的眼睛：引导你点进去自己读。AI 搜索要的不是这个——它要的是能直接喂进上下文窗口、被模型消化的内容。所以支撑它的往往是专门的 agentic search 接口：返回的不再是引导点击的链接列表，而是网页的直接摘要。一个服务于人的眼睛，一个服务于模型的上下文窗口。</p>
<h2>细节一：AI 发给搜索接口的，究竟是一个完整的问句，还是一个一个的关键词？</h2>
<p>答案介乎两者之间。经过 fan-out 之后，它发出去的是一份&quot;查询计划&quot;——一组由重新表述的子问题和提炼出的关键词组合而成的查询，分批发给搜索接口。它既不是把你原样的问题扔过去，也不是机械地把句子切成词，而是在理解之上重新生成的检索指令。</p>
<h2>收尾：从 SEO 到 GEO</h2>
<p>这些内容都会有用，但是产生作用方式不一样。以前的网页制作常常需要堆砌关键词、增加外链，把尽可能多的内容合并到一篇文章。现在由 AI 来组织内容，它消化的是语义而非关键词堆砌；传统的搜索列表排名、引导用户点击的行为，已不再起决定作用。这正是从SEO到GEO时代要解决的命题。</p>
]]></content:encoded>
    </item>
    <item>
      <title><![CDATA[重新理解提示词]]></title>
      <link>https://xiaofeng.dev/writing/rethinking-prompts/</link>
      <guid>https://xiaofeng.dev/writing/rethinking-prompts/</guid>
      <pubDate>Tue, 11 Aug 2026 00:00:00 GMT</pubDate>
      <description><![CDATA[我后端比较熟，前端却不算特别精通。过去一段时间，我经常让 AI 帮我写前端页面，也因此碰到过不少困难。一开始我以为，问题是自己不会写提示词。别人写提示词的时候，会先设定一个角色，再把任务、背景、要求、风格和输出格式全部写清楚。我也照着做过，但效果并没有因此稳定下来。后来我慢慢发现，问题可能不在提示词够不够长，而在于...]]></description>
      <content:encoded><![CDATA[<p>我后端比较熟，前端却不算特别精通。过去一段时间，我经常让 AI 帮我写前端页面，也因此碰到过不少困难。一开始我以为，问题是自己不会写提示词。别人写提示词的时候，会先设定一个角色，再把任务、背景、要求、风格和输出格式全部写清楚。我也照着做过，但效果并没有因此稳定下来。后来我慢慢发现，问题可能不在提示词够不够长，而在于我和 AI 是不是处在同一个<strong>话语体系</strong>里。这个发现也改变了我后来理解提示词的方式。</p>
<h2>我原来以为，提示词是一份操作手册</h2>
<p>我最近听一位英语博主讲 Prompt 这个词。他提到，Prompt 有推动某人采取行动的意思，也和戏剧里的提词员有关。演员在台上表演，提词员在台下适时提醒台词。</p>
<p><img src="/writing/wechat-tech-assets/rethinking-prompts/prompt-meaning.png" alt="Prompt 的本义：推动某人采取行动"></p>
<p>提词员不会替演员完成整场表演，只是在关键时刻给出一句提醒，让演员继续往下演。这个解释让我对提示词有了另一种理解：它不一定是一份事无巨细的操作手册，也不一定要把所有事情都规定死。很多时候，它只是一个关键的提示，帮助对方进入正确的状态。提词员是在关键处提醒演员，提示词也可以只提供完成任务所需要的那个关键线索。</p>
<p><img src="/writing/wechat-tech-assets/rethinking-prompts/prompter.png" alt="提词员提示演员继续表演"></p>
<p>市场上那些关于角色、任务、背景、格式的写法当然有用，尤其适合刚开始使用 AI 的人。但它们也很容易让人产生一个误解：好像提示词越长，效果就越好。实际上，堆很多形容词和要求，并不一定能让 AI 更准确。它真正需要的，可能只是几个准确的词。</p>
<h2>一个专业术语，可能比一大段描述更有用</h2>
<p>AI 和我沟通前端页面时，经常会使用一些专业术语。比如营销页面里的 CTA，内部系统里的权限模型，以及前后端之间的 BFF。这些词表面上只是几个字母，背后却带着一整套上下文。CTA 不只是一个按钮，它还和页面希望用户完成什么动作有关。BFF 也不只是一个接口，它通常还意味着前端和后端服务之间需要有一层专门的组织方式。</p>
<p>如果我只说“做一个按钮”“加一个权限”“调用后端接口”，AI 需要自己猜很多东西。可一旦使用准确的<strong>专业术语</strong>，双方就更容易理解彼此在说什么。我现在更愿意把提示词理解成一种<strong>上下文压缩</strong>：一个准确的词，有时可以替代一大段不够准确的描述。</p>
<p>这也是我在做前端开发时遇到的一个实际问题：我不是完全不会表达需求，而是还没有掌握这个领域足够多的词汇。词汇不够，很多需求就只能停留在模糊的感觉上。</p>
<h2>AI 可以教我术语，但不能替我做选择</h2>
<p>如果我不了解某个领域的术语，也不意味着没法和 AI 沟通。我可以先让它把这个领域通常使用的概念和方案讲出来，再慢慢判断哪些东西和我的问题有关。有时候我会直接问它：<strong>这个需求在业内通常怎么称呼？还有哪些常见做法？每种做法有什么代价？</strong></p>
<p>这样一来，就不只是我教 AI 做事，也可以让 AI 反过来教我一些东西。这个过程有点像管理学里说的<strong>反向学习</strong>：管理者不只是向一线传达要求，也要向一线学习。和 AI 协作时，我觉得这种<strong>刨根问底式的谦逊</strong>是有用的。AI 知道的东西可能比我多，它可以提供很多我原来想不到的方案。</p>
<p>但 AI 知道得多，不代表它知道哪个方案最适合我的项目。每个项目都有一些没有被明确说出来的背景：已经使用的技术栈、团队的能力、交付时间、预算、历史包袱，以及那些不能轻易改变的业务约束。AI 可以给出一个看起来很好的方案，却不一定知道它是否符合这些<strong>隐含上下文</strong>。</p>
<p>所以，AI 可以把可能性展开，人还是要负责把范围收窄。我想到一句话：<strong>弱水三千，只取一瓢。</strong> 我越来越觉得，人与 AI 协作时很重要的一种能力，不是让 AI 给出更多答案，而是从很多不错的答案里，选出一个真正适合当前项目的答案。</p>
<h2>专业方法背后，还有没有写出来的部分</h2>
<p>前些时候，我让 AI 用<strong>金字塔原理</strong>和 <strong>MECE方法</strong>帮我整理内容，结果比普通的整理方式好很多。这让我想到，一个人如果掌握了某个领域的专业知识、独到的方法，以及描述这件事的准确词汇，往往会比只会提出泛泛要求的人更有效率。</p>
<p>但这种能力也不能简单地变成一个Skill，再交给另一个人安装，就让对方完全获得同样的效果。因为一个方法的背后，还有很多没有写出来的判断：什么时候适合使用，什么时候不应该使用，它的前提是什么，有什么缺点，面对不同的人和不同的问题应该怎么调整。Skill可以把流程、知识和工具固化下来，但很难替代使用者自己的判断。使用方法的人是谁，也会影响方法最后的效果。</p>
<h2>好的提示，不一定要把话说完</h2>
<p>我后来想到咖啡和茶的风味卡片，也想到香水文案。</p>
<p><img src="/writing/wechat-tech-assets/rethinking-prompts/coffee-flavor-card.jpg" alt="咖啡风味卡片"></p>
<p><img src="/writing/wechat-tech-assets/rethinking-prompts/tea-flavor-card.jpg" alt="茶香描述卡片"></p>
<p>好的香水文案不会把所有气味成分逐项写完，好的咖啡或茶的风味描述也不会只停留在“苦、香、醇”这些形容词上。它们通常只用几句话，写出一个场景，唤起一些想象，让人联想到某段记忆，或者一种已经被忘记的感觉。</p>
<p>它们没有把所有内容解释完，却成功激活了读者脑海里的上下文。提示词有时也是这样：它不一定要把所有细节都写出来，而是要给出足够准确的线索，让 AI 理解我们在讨论什么、真正重视什么，以及希望事情最后变成什么样。</p>
<p>重新理解提示词之后，我不再把它看成一段越长越好的指令。它更像是在和 AI 建立一种<strong>共同语境</strong>。提示词写到最后，其实是在问：我到底知不知道自己想要什么？</p>
]]></content:encoded>
    </item>
    <item>
      <title><![CDATA[Next.js 应用要不要部署到边缘节点？IGA Pages 的适用边界]]></title>
      <link>https://xiaofeng.dev/writing/nextjs-edge-deployment-iga-pages/</link>
      <guid>https://xiaofeng.dev/writing/nextjs-edge-deployment-iga-pages/</guid>
      <pubDate>Sun, 09 Aug 2026 00:00:00 GMT</pubDate>
      <description><![CDATA[Next.js 应用除了部署在函数服务上，还可以选择运行在边缘节点。IGA Pages 是火山引擎的产品，和阿里云 ESA 属于相近的边缘加速类产品：它们都把站点加速能力和一部分边缘运行能力结合起来，让应用有机会在距离用户更近的节点处理请求。]]></description>
      <content:encoded><![CDATA[<p>Next.js 应用除了部署在函数服务上，还可以选择运行在边缘节点。IGA Pages 是火山引擎的产品，和阿里云 ESA 属于相近的边缘加速类产品：它们都把站点加速能力和一部分边缘运行能力结合起来，让应用有机会在距离用户更近的节点处理请求。</p>
<p>但边缘部署并不是所有 Next.js 应用的最佳选择。真正需要考虑的问题是：服务端到底在做多少计算、需要访问多少次数据库，以及这些数据服务是否靠近边缘节点。</p>
<h2>一、IGA Pages 和函数服务有什么区别？</h2>
<p>IGA Pages 与阿里云 ESA 可以放在同一类产品中理解，但它们不是同一个产品，运行时支持、部署方式和配置限制也不能直接类比，实际使用时仍然要以各自的官方文档为准。</p>
<p>函数服务通常是在某个中心区域运行应用，再通过 DCDN 把用户请求加速到这个区域。它的特点是应用代码和数据库可以放在相近的区域，服务端访问数据库的路径比较短。</p>
<p>IGA Pages 更接近边缘运行模式：应用代码或服务端逻辑可以部署到边缘节点，用户请求有机会在距离自己更近的节点得到处理。它本身就依托边缘加速产品提供访问加速，不是一个需要再额外挂一层 DCDN 的普通源站。</p>
<p>两种方式的核心区别可以简单概括为：</p>
<ul>
<li><strong>函数服务 + DCDN</strong>：应用集中运行，DCDN 负责把用户请求和静态资源加速到应用所在区域。</li>
<li><strong>IGA Pages</strong>：应用的一部分运行能力下沉到边缘节点，用户请求可以在更靠近用户的位置处理。</li>
</ul>
<p>这里的“更靠近用户”不等于“更靠近数据库”。边缘节点带来的收益，最终要和服务端访问数据的代价一起评估。</p>
<h2>二、先区分 SSR 和服务端 API</h2>
<p>这两个词经常一起出现，但它们描述的不是同一件事。</p>
<p>**SSR（服务端渲染）**描述的是页面生成方式：用户请求页面时，由服务端生成 HTML，再返回给浏览器。SSR 的过程中可以读取数据库、调用外部服务，也可以完全不访问数据库。</p>
<p><strong>服务端 API</strong>描述的是接口形态：浏览器或其他服务请求一个接口，服务端通常返回 JSON 或其他数据。Next.js 中常见的实现是 Route Handler。它主要用于数据读写、鉴权、调用第三方服务等，并不等于页面渲染。</p>
<p>一个 Next.js 应用可以同时拥有 SSR 页面和服务端 API，但两者的请求路径和职责应该分开理解：</p>
<ul>
<li>SSR：服务端生成页面 HTML。</li>
<li>服务端 API：服务端响应数据或执行操作。</li>
<li>服务端组件直接读取数据库：这是服务端数据访问，不自动等于一个对外 API。</li>
</ul>
<p>因此，不能把所有服务端逻辑都称为 SSR，也不要因为代码运行在 Next.js 服务端，就把它统称为 API。</p>
<h2>三、为什么数据库位置很重要？</h2>
<p>如果页面是纯静态的，边缘节点离用户越近，通常越有优势。但如果页面使用 SSR，或者服务端 API 需要访问数据库，情况就复杂了：边缘节点处理请求时，仍然要访问数据库和其他后端服务。</p>
<p>假设数据库还在大陆，而某个用户的请求被分配到海外边缘节点，那么一次 SSR 请求可能经过这样的路径：</p>
<p>用户 → 海外边缘节点 → 大陆数据库 → 海外边缘节点 → 用户</p>
<p>这时，代码虽然离用户近了，但服务端访问数据库变远了。每次页面渲染都要跨区域请求，延迟可能抵消边缘部署带来的收益，数据库连接、网络稳定性和跨区域流量成本也需要关注。</p>
<p>不过，不能简单地认为“只要用了数据库，就不适合边缘节点”。关键要看计算和数据访问的比例：</p>
<ul>
<li><strong>计算很密集、数据库查询较少</strong>：这类服务端逻辑通常比较适合放到边缘节点。请求可以在靠近用户的地方完成较多计算，只进行少量数据读取或校验。</li>
<li><strong>数据库查询非常密集</strong>：这类逻辑通常不适合直接放到边缘节点，尤其是查询之间存在串行依赖、读写频繁，或者数据库集中在单一区域时。大量边缘节点到数据库的往返调用，会让网络延迟成为主要瓶颈。</li>
</ul>
<p>这里要关注的不只是“查询次数”，还包括每次查询是否必须等待上一次结果、数据量大小、读写比例，以及数据库是否在边缘节点附近。边缘节点解决的是用户到计算节点的距离，并不能自动解决计算节点到数据库的距离。</p>
<p>也因此，给数据库服务（例如 Supabase）再套一层加速，通常不是优先方向。数据库请求包含鉴权、读写、连接和一致性等问题，不是把一个静态文件放到 CDN 上那么简单。更值得先问的是：数据库是不是本来就应该部署在海外？国内和海外的应用、服务端以及数据库，是否应该完全拆成两套？</p>
<p>如果用户、计算和数据主要在海外，把数据库直接部署在海外，通常比让国内服务端或边缘节点跨区域访问数据库更合理。对于同时面向国内和海外的应用，也可以评估国内、海外分别部署服务端和数据库，让两边的请求尽量在本地闭环，减少跨境调用和数据流动。这种按地域拆分的架构通常也更容易做数据隔离和合规管理，但具体方案仍然需要结合业务类型、数据分类和适用法规单独评估。</p>
<p>下面用一个相对复杂的典型场景说明这种数据流向。它不是把 Supabase 当成普通源站交给 DCDN 加速，而是先按用户地域拆分接入层、Next.js 服务端和数据库，让 SSR 页面渲染与服务端 API 的数据请求都尽量在同一区域完成。</p>
<p><img src="/writing/wechat-tech-assets/nextjs-edge-deployment-iga-pages/iga-pages-data-flow.png" alt="边缘部署下的复杂数据流"></p>
<h2>四、哪些应用适合部署到边缘节点？</h2>
<h3>纯静态应用</h3>
<p>这是最适合的场景。页面构建后就能直接分发，不需要在边缘节点实时访问数据库，用户可以从附近节点获取静态文件。</p>
<h3>计算密集、数据访问较少的服务端逻辑</h3>
<p>如果请求主要是在做计算，而不是反复查询数据库，例如请求改写、轻量级鉴权、规则计算、内容处理或数据预处理，并且只需要少量数据读取，那么把这类逻辑放到边缘节点通常比较合适。</p>
<h3>前后端已经分离的应用</h3>
<p>如果前端只是展示页面，服务端 API 集中部署在靠近数据库的区域，那么可以把前端放到边缘节点，把数据请求交给服务端 API 处理。</p>
<p>这种方式需要单独考虑跨域、鉴权、接口延迟和缓存策略，但整体架构边界比较清晰。这里要注意，前端部署在边缘节点，不代表服务端 API 也必须部署在边缘节点。</p>
<h3>数据库和边缘运行区域匹配的应用</h3>
<p>如果数据库本身有合适的全球化部署方案，或者应用的用户、计算节点和数据都集中在相近区域，边缘 SSR 或边缘服务端 API 才更有机会体现优势。</p>
<h2>五、哪些应用不适合直接放到边缘？</h2>
<p>如果应用有大量动态页面，SSR 需要频繁访问一个距离边缘节点很远的数据库，或者服务端 API 的一次请求需要多次串行查询数据库，就不建议为了“全球加速”直接迁移到边缘节点。</p>
<p>这类应用更适合先把服务端逻辑部署在靠近数据库的函数服务中，再用 DCDN 加速静态资源和用户访问。这样虽然代码不是全部运行在边缘，但数据访问路径更可控。</p>
<p>尤其需要注意下面这种部署方式：</p>
<blockquote>
<p>服务端部署在海外边缘节点，数据库部署在大陆；每个请求又需要多次读写数据库。</p>
</blockquote>
<p>这种情况下，边缘节点离用户近，但离数据库远，整体响应速度可能反而更差。对于数据库访问密集的应用，应优先保证服务端和数据库之间的低延迟，再考虑把用户侧的静态内容和可缓存内容交给 DCDN。若业务确实主要在海外，还应该优先评估把数据库直接部署在海外，而不是继续尝试给现有数据库链路叠加加速层。</p>
<h2>六、IGA Pages 不能再在前面叠加一层 DCDN</h2>
<p>边缘加速产品本身通常就依托 DCDN 提供全球或区域加速能力。IGA Pages 已经属于这一类产品，因此不应该再在它的前面挂另一层 DCDN。</p>
<p>如果把一个边缘加速产品的域名，再配置成另一个 DCDN 的加速对象或源站，两个加速层之间可能形成回环。平台会进行回环检测，发现这种配置后通常会禁止接入或拒绝生效。</p>
<p>所以需要先区分两种架构：</p>
<ul>
<li><strong>函数服务作为源站 + DCDN</strong>：这是常见的“中心区域计算、边缘加速访问”架构。</li>
<li><strong>IGA Pages</strong>：它本身已经包含边缘加速能力，不要再在前面叠加 DCDN。</li>
</ul>
<p>如果需要精细控制 DCDN 的缓存、路由和传输参数，通常应该选择函数服务加独立 DCDN，而不是把 IGA Pages 当作普通源站再接入一层 DCDN。</p>
<h2>七、IGA Pages 的配置限制</h2>
<p>IGA Pages 的优点是把一部分部署和加速能力整合起来，但代价是可调参数相对少。</p>
<p>例如，HTTP/2、Gzip 等能力不一定能像独立配置 DCDN 那样由用户自由调整，部分配置可能需要通过工单开通。如果你需要精细控制缓存、路由和传输参数，独立使用函数服务加 DCDN 会更灵活。</p>
<h2>结论：先看计算和数据路径，再看节点距离</h2>
<p>IGA Pages 适合纯静态站点、计算密集且数据库访问较少的服务端逻辑、前后端分离的前端应用，以及计算节点和数据服务能够就近部署的应用。</p>
<p>如果你的 Next.js 应用使用 SSR，或者有服务端 API，并且服务端要频繁访问固定区域的数据库，边缘节点未必更快。此时更应该优先保证服务端和数据库之间的低延迟，再使用 DCDN 加速用户访问。</p>
<p>判断是否使用 IGA Pages，可以先问自己四个问题：</p>
<ol>
<li>这是纯静态内容，还是需要 SSR 或服务端 API？</li>
<li>服务端逻辑主要是计算，还是主要在查询数据库？</li>
<li>数据库是否靠近应用将要运行的边缘区域？</li>
<li>是否已经使用了边缘加速产品，避免再叠加一层 DCDN 形成回环？</li>
</ol>
<p>如果服务端计算量较大、数据库访问较少，并且没有明显的跨区域数据访问问题，边缘部署值得优先评估。反过来，如果数据库查询密集、调用链很长，或者数据库距离边缘节点很远，就应该谨慎选择边缘部署。</p>
]]></content:encoded>
    </item>
    <item>
      <title><![CDATA[Vibe Coding 做出的 Next.js 应用，如何用函数服务和 DCDN 做全球加速]]></title>
      <link>https://xiaofeng.dev/writing/vibe-coding-nextjs-vefaas-dcdn/</link>
      <guid>https://xiaofeng.dev/writing/vibe-coding-nextjs-vefaas-dcdn/</guid>
      <pubDate>Sun, 09 Aug 2026 00:00:00 GMT</pubDate>
      <description><![CDATA[最近想分享一个比较实用的话题：Vibe Coding 做出来的 Next.js 应用应该怎么部署，以及怎么给它做全球加速。]]></description>
      <content:encoded><![CDATA[<p>最近想分享一个比较实用的话题：Vibe Coding 做出来的 Next.js 应用应该怎么部署，以及怎么给它做全球加速。</p>
<p>这类应用通常有三种形态：</p>
<ol>
<li><strong>纯静态应用</strong>：只有前端页面，不需要数据库，也没有服务端逻辑。</li>
<li><strong>前端 → Supabase（SDK / REST）</strong>：浏览器通过 Supabase 的客户端 SDK 或 REST 接口读写数据，由 RLS 负责数据权限。</li>
<li><strong>前端 → Next.js 服务端 → Supabase / 外部服务</strong>：Next.js 服务端可以通过 API、SSR、Server Component 或 Server Action，承载更复杂的权限与业务逻辑。</li>
</ol>
<p>三者的部署方式并不一样。纯静态应用可以直接放到 CDN 或边缘节点；如果只是简单的数据读写，可以让浏览器直连 Supabase；如果应用需要隐藏服务端密钥、执行复杂业务逻辑，或者要在服务端生成页面，就需要让请求经过 Next.js 服务端。</p>
<p><img src="/writing/wechat-tech-assets/vibe-coding-nextjs-vefaas-dcdn/nextjs-three-deployment-architecture.svg" alt="Next.js 三种部署架构"></p>
<p>这里的“经过 Next.js 服务端”不等于一定存在一个传统 API。SSR 或 Server Component 可以在服务器直接读取 Supabase 后生成页面；Route Handler 或 Server Action 则更常用于浏览器操作触发的读写。它们经常组合使用，但解决的是不同问题。</p>
<p>第三种形态还有一个特别需要注意的点：服务端要尽量靠近数据库。</p>
<p>既然 Next.js 服务端承担了 API、SSR 或 Server Action 的工作，它就会频繁访问数据库和其他外部服务。不能为了全球访问把服务端部署在海外，但数据库还在大陆，尤其是一次请求中存在多次服务端与数据库之间的来回调用时，跨区域延迟会不断叠加，最后用户感受到的反而是更慢。</p>
<p>所以，选择服务端部署区域时，应该先看数据库在哪里，再看用户主要在哪里。DCDN 可以加速用户到边缘节点这一段，但不能消除服务端与数据库之间的远距离调用。</p>
<h2>一、前端直连 Supabase 时要注意什么？</h2>
<p>浏览器里的代码和用户是同一侧的，用户可以看到前端发出的请求。因此，浏览器直连 Supabase 时，不能把安全寄托在“用户看不到接口”上。</p>
<p>不过，浏览器直连 Supabase 并不等于天然不安全。Supabase 的 anon key 本来就可以放在前端，真正负责数据隔离的是数据库的 RLS 策略和用户权限。新增、修改、删除等操作也可以通过 RLS 安全完成，但规则必须配置正确。</p>
<p>如果还需要隐藏 service-role key、调用第三方私密 API、执行复杂业务规则，或者不希望把数据处理过程暴露在浏览器中，就应该由 Next.js 的服务端逻辑承接请求，在服务端完成鉴权、权限判断和数据库操作。</p>
<h2>二、用函数服务运行 Next.js</h2>
<p>我最近体验的是火山引擎的函数服务。它的思路是：把应用代码交给云端，由云端在容器中运行，并提供一个可以公开访问的域名。</p>
<p>在这种部署方式中，Next.js 的前端页面和服务端逻辑可以由同一套应用承载。你还可以为函数设置实例策略：</p>
<ol>
<li><strong>动态实例</strong>：请求到来时再启动实例，成本较低，但可能遇到冷启动。</li>
<li><strong>预留实例</strong>：提前启动固定数量的实例，响应更快，但会持续占用资源。</li>
</ol>
<p>我原本以为预留实例一定更贵，后来发现并不完全如此。因为资源提前锁定后，调度成本更低，在访问量较大的场景下，预留实例反而可能更划算。</p>
<p>如果只是开发环境，流量很少，可以使用动态实例；如果访问量比较稳定，或者比较在意首个请求的响应速度，可以考虑预留实例。</p>
<p>另外，不管是动态实例还是预留实例，每个实例都有自己的并发配置。平台给出的默认并发值可能是 100，但不要直接照搬这个默认值。因为默认实例的内存和 CPU 通常并不高，Next.js 的 SSR 或 API 在高并发下会让多个请求争抢同一个实例的资源，容易出现排队、超时或错误。</p>
<p>这种情况下，单实例并发宁可先设得低一些，再结合 CPU、内存、响应时间和错误率做压测，逐步调高。实例数量和单实例并发是两个不同的参数，都需要根据实际负载调整。</p>
<h2>三、先确认平台支持的 Node.js 版本</h2>
<p>不同服务商对 Next.js 的运行环境要求并不一样，不能只因为本地项目能跑，就直接把它部署到任意平台。</p>
<p>以火山引擎为例，当前官方部署文档要求本地准备 Node.js 20.x，并选择 Native Node.js 20.x 运行时。更高版本不要轻易使用，至少要先确认平台当前的运行时支持范围，以及 Next.js 和依赖是否兼容。</p>
<p>如果使用 veFaaS CLI 部署，官方流程是：CLI 在项目目录中探测框架、构建命令、产物路径和启动命令，然后进入依赖安装和构建流程，再把构建结果部署到云端。也就是说，针对这条 CLI 部署路径，构建主要发生在本地，云端负责接收并运行部署产物，并不是把完整源码交给云端再临时构建。</p>
<p>因此，部署前最好让本地 Node.js 版本和平台运行时保持一致。我更推荐配合 veFaaS CLI 和对应的 Skill 使用：CLI 负责真实执行，Skill 负责提示运行时、构建配置和常见排障路径。</p>
<h2>四、为什么还要在函数服务前面加一层 DCDN？</h2>
<p>函数服务解决的是“代码在哪里运行”，但它本身不等于全球加速。用户的请求仍可能需要跨较远的网络访问函数实例。</p>
<p>一种做法是在函数服务前面接入 DCDN，把它作为统一的访问入口。这样可以让静态资源尽量在边缘节点命中，同时把动态请求转发回函数服务。</p>
<p>但仅仅把 DCDN 挂上去还不够，关键是要配置缓存和条件路由。</p>
<h3>静态资源：尽量缓存</h3>
<p>Next.js 生成的静态资源通常可以缓存较长时间，例如 <code>_next</code> 路径下的资源。这些文件一般带有版本化或哈希信息，内容变化后 URL 也会变化，适合交给 CDN 缓存。</p>
<h3>动态接口：默认不要缓存</h3>
<p>登录状态、用户信息和数据库查询结果都可能是动态内容，尤其是 <code>/api/</code> 下的接口，通常不应该直接套用静态缓存规则。</p>
<p>可以通过条件路由区分静态资源和动态请求：静态资源走缓存，API 和其他动态页面回源到函数服务。具体规则要结合自己的路由结构验证，不能只凭路径名称盲目配置。</p>
<h2>五、DCDN 里几个值得检查的配置</h2>
<h3>HTTP/2</h3>
<p>HTTP/2 可以帮助同一个连接并发处理多个请求，对动态请求和包含多个资源的页面比较有帮助。</p>
<h3>Gzip</h3>
<p>Gzip 可以压缩 HTML、CSS、JavaScript 等文本资源，通常收益明显，性能损耗也较小，一般建议开启。</p>
<h3>HTTPS</h3>
<p>HTTPS 是生产环境的基本配置。除了保护传输内容，现代浏览器的许多能力也依赖安全连接。</p>
<h2>六、DCDN 的加速范围</h2>
<p>DCDN 通常有大陆、海外和全球三种加速范围。具体怎么选，取决于用户分布，而不是简单跟着函数服务所在区域走。如果缺少可以国内备案的域名，就选海外加速即可。</p>
<h2>结论：函数服务 + DCDN 适合什么场景？</h2>
<p>如果你的 Next.js 应用需要服务端执行（例如 SSR、Route Handler 或 Server Action），或者需要让服务端安全地连接数据库，那么“函数服务 + DCDN”是一种相对直观的方案：</p>
<ul>
<li>函数服务负责运行 Next.js 和服务端逻辑；</li>
<li>DCDN 负责静态资源缓存和网络加速；</li>
<li>条件路由负责区分静态请求和动态请求；</li>
<li>实例策略负责在响应速度与成本之间做取舍。</li>
</ul>
<p>站点部署好之后，我还推荐用 Chrome DevTools 的性能分析工具跑一遍，看看首屏加载、静态资源、网络请求和脚本执行方面还有哪些值得优化的地方。部署完成不等于性能优化结束，实际访问数据和浏览器分析结果，才是下一轮调整的依据。</p>
]]></content:encoded>
    </item>
    <item>
      <title><![CDATA[AI 名词大混乱的时代]]></title>
      <link>https://xiaofeng.dev/writing/ai-terminology-confusion/</link>
      <guid>https://xiaofeng.dev/writing/ai-terminology-confusion/</guid>
      <pubDate>Wed, 05 Aug 2026 00:00:00 GMT</pubDate>
      <description><![CDATA[发现有许多号会转载各种新时代AI工程的，他们的点赞数远低转发数，后来我意识到许多读者都和我一样，转发到“文件传输助手”，收藏夹，朋友圈，消解一下收藏癖和焦虑。这才拉高了转发数字。]]></description>
      <content:encoded><![CDATA[<p>发现有许多号会转载各种新时代AI工程的，他们的点赞数远低转发数，后来我意识到许多读者都和我一样，转发到“文件传输助手”，收藏夹，朋友圈，消解一下收藏癖和焦虑。这才拉高了转发数字。</p>
<h2>一、到底什么是后训练</h2>
<p>又想起最近DeepSeekv4 flash通过后训练优化大幅提升Agent能力。搜了一圈发现，一来是官方并没有公开准确的后训练方法，二来，大家都把后训练解释为不改权重的训练方法。</p>
<p>再搜一圈，发现广义后训练是包括了微调和RL，是会修改权重的。可见名词混乱程度之大。</p>
<h2>二、Harness这个奇怪的名词</h2>
<p>老外的发明癖瘾大，发明了用Harness鞍具这个词来泛指模型周边的Tool/Funtion/Runtime。于是我看一些MaaS平台就把自己内置的搜索叫做Harness？不就是个搜索工具调用吗？非得用这个词才能达意？一定是中文不好的缘故。</p>
<p>于是又有人把自己的调用了一次工具直接说成harness工具，一派混乱的景象。</p>
<h2>三、Loop的混用</h2>
<p>Loop是一种含义就是把模型放到工具/runtime环境中持续迭代（但几乎不动权重），也就是lilian博客中提及的harness优化方法，如self-harness，meta-harness。但是会有一些人把它泛化或借鉴到自己的带一点自我优化或者记忆能力的agent中，用来装点门面。</p>
<h2>四、这些名词都太像了</h2>
<p>重复发明，胡乱借用，不做模型不做infra的人也疯狂借用。甚至非开发者方向的博主们也把自己的skill和工作流比喻成用了xxx方法论。</p>
<p>对于AI应用开发者来说，这种比喻或借用，凭空带来了焦虑，又并不能提供场景内的实际解决方案。</p>
<p>我当前的建议就是：</p>
<ul>
<li>需要阅读原始出处含义，以便了解其源头</li>
<li>需要进行对比和辨析，减少歧义和焦虑</li>
<li>在需要显示自己或自己应用的厉害之处时，降低解释成本时，也不妨用用，但内心别被概念捆绑了</li>
</ul>
]]></content:encoded>
    </item>
    <item>
      <title><![CDATA[批量推理的快与慢：不能一概而论]]></title>
      <link>https://xiaofeng.dev/writing/batch-inference-fast-slow/</link>
      <guid>https://xiaofeng.dev/writing/batch-inference-fast-slow/</guid>
      <pubDate>Sat, 25 Jul 2026 00:00:00 GMT</pubDate>
      <description><![CDATA[最近在做一个用到大模型 API 的项目，需求并不复杂：从网页正文里提取关键词，识别品牌名及其别名，再判定文章对该品牌的情感倾向——正面或负面。这类语义理解与情感分析正是大模型所擅长的，并不需要深度推理。]]></description>
      <content:encoded><![CDATA[<h1>批量推理的快与慢：不能一概而论</h1>
<p>最近在做一个用到大模型 API 的项目，需求并不复杂：从网页正文里提取关键词，识别品牌名及其别名，再判定文章对该品牌的情感倾向——正面或负面。这类语义理解与情感分析正是大模型所擅长的，并不需要深度推理。</p>
<p>任务简单，但量不小。最朴素的场景，一百来篇文章。逐条调用 API，或常规并发调用，要么触发频率限制，要么整体吞吐太慢。</p>
<p>一番调研后发现，像火山引擎这类平台，除了单条调用的 API，还提供「在线推理」与「批量推理」两种方式。批量推理又分两种模式：批量推理任务，处理静态存储的数据；类在线推理方式的接入点，处理动态数据。我的场景是成批的网页文章，属于前者。此前未曾用过，研究下来发现它恰好适配——提示词几乎不变，变化的只是输入数据。</p>
<h2>一、为什么快？</h2>
<p>批量推理与我原先的设想不同。我曾以为批量只是把请求堆在一起发送，其实不然——它真正的优势在于：当所有请求共享同一套提示词、只有数据内容在变时，服务端的缓存命中率极高。</p>
<p>官方的说法更直接：输入输出单价为在线推理的 50%，命中缓存后输入单价还能再降 60%——缓存红利不只是速度，也是成本。配额上默认 100 亿 token/天，支持工单提额，且得益于灵活的调度策略，高峰期仍能保持可观的处理速率。</p>
<p>我将 300 篇文章一次提交，本已做好等待的准备，结果一两分钟便返回——超出预期。</p>
<p>这个接口在使用时有几个要点：</p>
<ul>
<li><strong>极高的并发</strong>。以异步 IO 方式调用，5 万并发亦可承载。前提是解除本地的并发限制，避免客户端自身成为瓶颈。</li>
<li><strong>超长的超时设置</strong>。数千条请求在服务端并行处理需要时间，超时宜设长——24 小时的超时并不罕见，也是批量任务的常态。</li>
<li><strong>429 的指数退避重试</strong>。服务端过载会返回 429，不应硬性重试，而以指数退避策略等待其恢复后再发。</li>
</ul>
<p>值得一提的是改造门槛：Batch Chat 接口的参数与普通 Chat 接口一致，只需关注超时与并发策略即可切换，无需改动业务逻辑——这也是我能快速上手的原因。</p>
<p>返回后一次性取回批量结果。整个过程，几分钟即可完成。</p>
<h2>二、换个深度推理模型，结果截然不同</h2>
<p>就在我以为找到了理想方案时，今天又试了一次——这次换用了深度思考的 doubao-seed-2-1-pro，且正值周日。几乎相同的场景，表现却截然不同。</p>
<p>此前在 doubao-seed-2.0-mini 这类轻量模型下，几分钟即可完成；这次换上深度推理的 doubao-seed-2-1-pro，几乎无法推进。</p>
<p>官方文档中所述的「等待与排队」并非虚言。在不拥挤的模型上，排队几乎不存在；但在较为拥挤的、或思考深度更高的模型上，批量推理的快法便失效——上千条请求进入队列，深度推理本身较慢，越深越慢，堆积只会加剧。</p>
<p>但这一次的慢，究竟该归咎于 doubao-seed-2-1-pro 本身推理更深、更慢，还是周日平台容量紧张、排队加剧，单凭一次对比难以分清。</p>
<h2>结论：不能一概而论</h2>
<p>批量推理的快慢，不能只看接口。doubao-seed-2.0-mini 上又快又稳，doubao-seed-2-1-pro 上几乎跑不动——但这并不意味着「深度推理模型就不该用批量」。深度推理的适用场景与真实效果，需要自己去交叉验证：有时瓶颈在模型自身的推理深度与速度，有时则在平台的并发容量与排队状况，二者交织，不能一概而论。</p>
<p>接口提供了高并发、长超时、指数退避这些手段，平台也给了低单价、高配额与灵活调度，但最终跑得快不快，是模型、平台容量、时段共同决定的——三者的组合，只有实测才说得清。</p>
<p><strong>参考链接</strong>：火山引擎 · 批量推理</p>
<p><img src="/writing/wechat-tech-assets/batch-inference-fast-slow/00157ed7a7ef3028.png" alt="图片"></p>
]]></content:encoded>
    </item>
    <item>
      <title><![CDATA[少即是多：与其囤一堆 skill，不如吃透一组]]></title>
      <link>https://xiaofeng.dev/writing/less-is-more-skills/</link>
      <guid>https://xiaofeng.dev/writing/less-is-more-skills/</guid>
      <pubDate>Sun, 19 Jul 2026 00:00:00 GMT</pubDate>
      <description><![CDATA[最近半年一直很重看 EveryInc 出品的 compound-engineering-plugin，它也一口气装了 29 个 skill（命令都以 /ce- 开头），我持续跟进它的更新；同时，和我工作流不搭的 skill 我都主动卸了——superpowers 这种同性质的工程插件，还有 supabase、ver...]]></description>
      <content:encoded><![CDATA[<h1>少即是多：与其囤一堆 skill，不如吃透一组</h1>
<p>最近半年一直很重看 EveryInc 出品的 compound-engineering-plugin，它也一口气装了 29 个 skill（命令都以 /ce- 开头），我持续跟进它的更新；同时，和我工作流不搭的 skill 我都主动卸了——superpowers 这种同性质的工程插件，还有 supabase、vercel、next.js、refine 这些纯语言/框架的 skill，要么和这一组重叠，要么根本不在我的流里。因为我越用越清楚一件事：skill 的本质，不是装得多，而是吃得透、懂原理。</p>
<p>（我数过，那 29 个里，真正每次都走的只有 6 个核心 skill，剩下二十几个是按需挂的&quot;侧门&quot;。）</p>
<p>先说为什么装一堆反而用不好，再说什么才叫&quot;吃透一组&quot;，以及进阶的用法。</p>
<h2>一、装得多，真的用得好吗？</h2>
<p><strong>第一，能被真正激活的其实有限。</strong> 像 Codex 这类产品，会对 skill 的 description 做缩减。你装得越多，某个 skill 能被准确识别、在恰当时机被触发的概率反而越低。装了一墙按钮，真正能被&quot;叫醒&quot;的也就那么几个——数量上去了，命中率反而下来了。（这个就是skill的激活率问题）。</p>
<p><strong>第二，平白浪费上下文。</strong> skill 包通常一组一组地来，动辄几十个。可你日常真正用到的就几个。剩下的那些，你既不手动召唤，平时也不会被自动触发，只是安静地占着上下文预算。装了等于没装，还白白搭进去成本。哪怕是渐进式披露的skill，为了提升被动激活率，许多skill的激活词也写得非常泛滥。</p>
<p><strong>第三，最麻烦的是行为说不清。</strong> 同一份结果，常常搞不清到底是哪一个 skill 在背后起作用。尤其是两个几乎一样的任务，自动串起来的 skill 却不一样：同一个意图，走了不同路径，产出对不上。这种不可解释，比&quot;不会用&quot;更让人困惑。比如只做代码评审的 /ce-code-review，它自己从不改代码，得靠调用方去落实结论；而更重的 /ce-dogfood 干脆被设成禁止自动调用，因为副作用太重。表面上看像是同一个 AI 在干活，背后触发的链路却各不相同——这才是最磨人的地方。</p>
<h2>二、什么才叫&quot;吃透一组&quot;？</h2>
<p>以我常用的 compound-engineering-plugin 为例。它那 29 个 skill，分核心 skill 和附带 skill。</p>
<p><strong>核心 skill 是整个开发流程里的一组</strong>：/ce-brainstorm（想清楚）→ /ce-plan（计划）→ /ce-work（干）→ /ce-simplify-code（简化）→ /ce-code-review（评审）→ /ce-compound（沉淀）。它们之间不是并列摆着，而是互相调用。比如 /lfg 这条全自动流水线，能把&quot;计划 → 写代码 → 简化 → 评审 → 测试 → 开 PR&quot;一气串起来；而负责&quot;沉淀&quot;的 /ce-compound，会把每轮学到的东西写回方案库，下一轮规划时再被当基地读回去。官方对它的评价很直白：“那根回流的箭头，才是全部的意义。”</p>
<p>所以关键不是&quot;会不会敲单个命令&quot;，而是：知道这一组从哪开始、谁调谁、边界在哪里。这要求不只读文档，还要理解它们之间背后的关系和区别。</p>
<p><strong>真懂原理，才分得清微妙的差别。</strong> 我这组里有两个测试相关的 skill：/ce-test-browser 做差异化测试，只测改动触及的页面，测完报结果，不修、也不提交；/ce-dogfood 做的更重，是那种会自己跑完的 QA。它也只盯 diff 触及的流程，但会在末尾跑一遍项目既有的测试套件当&quot;就绪门&quot;，还会自己修小 bug、补回归测试、留下可追溯的文档报告，而且必须手动调用。两者差别微妙，要分清&quot;什么时候用哪个&quot;，靠的不是记住命令名，而是反复读它们的 skill 内容，把根本原理和区别吃透——光看名字，分不出这俩。</p>
<h2>三、吃透之后，你能拿它做什么？</h2>
<p><strong>懂了原理，才能把它改造成自己的。</strong> 掌握了底层结构，还能再往前走一步：把两三个 skill 组合起来用，再用提示词微调它中间的行为。还是拿 /lfg 说，它默认从需求一路跑到开 PR、盯 CI。但如果你这轮只想在本地收尾，懂了它是一条&quot;计划 → 写代码 → 简化 → 评审 → 测试 → 提交 → 开 PR&quot;的流水线，就可以直接告诉它：别开 PR，本地提交就行。它就会停在你想要的地方。这种&quot;组合 + 用提示词改行为&quot;的玩法，是吃透原理之后才有的进阶自由度。</p>
<h2>我的结论：少即是多</h2>
<p>所以问题从来不是&quot;你装了多少&quot;，而是&quot;你真正吃透了几条&quot;。</p>
<p>装一堆，你拥有的是一份多半用不上的清单，外加一堆说不清来源的行为；吃透一组常用的、懂其原理的，你才真正拥有了一套能跑起来、还能自我复利的系统。少装，常用，吃透，再及时跟进它的最新更新，掌握背后的方法论，最终打造自己的个性化的skill才是适合AI builder的路。</p>
<p><img src="/writing/wechat-tech-assets/less-is-more-skills/00157ed7a7ef3028.png" alt="图片"></p>
]]></content:encoded>
    </item>
    <item>
      <title><![CDATA[如何启动多个 Codex 浏览器会话]]></title>
      <link>https://xiaofeng.dev/writing/codex-browser-sessions/</link>
      <guid>https://xiaofeng.dev/writing/codex-browser-sessions/</guid>
      <pubDate>Sat, 18 Jul 2026 00:00:00 GMT</pubDate>
      <description><![CDATA[为了同时跑多个 Codex session，我写了一个浏览器启动器。真正动手前，我先追了三个问题：Chrome DevTools MCP 是怎么注入 Codex 的，运行中能不能改；Chrome 的 profile 在哪里指定；CDP 端口又是怎么完成 auto connect 的。这三个问题搞清楚，方案也就差不多...]]></description>
      <content:encoded><![CDATA[<h1>如何启动多个 Codex 浏览器会话</h1>
<p>为了同时跑多个 Codex session，我写了一个浏览器启动器。真正动手前，我先追了三个问题：Chrome DevTools MCP 是怎么注入 Codex 的，运行中能不能改；Chrome 的 profile 在哪里指定；CDP 端口又是怎么完成 auto connect 的。这三个问题搞清楚，方案也就差不多出来了。</p>
<p>我原本以为这只是多开两个 Chrome 窗口。实际跑起来，一个 session 会连到另一个 session 的浏览器；有时关掉一个 Codex，另一个 Chrome 也跟着没了。窗口开了两个，底下的连接却还是混的。</p>
<p>最后的实现很简单：每个 Codex session 使用自己的 CDP 端口和 Chrome profile，启动时再把对应的 MCP 配置传给 Codex。这三项必须成套，不能串。脚本还支持指定或复用 profile，并保留了 Codex 的 <code>resume</code> 能力。</p>
<h2>先把连接关系画清楚</h2>
<p>CDP（Chrome DevTools Protocol）是 Chrome 的调试和自动化接口。端口就是它的入口。<code>chrome-devtools-mcp</code> 则是 Codex 与 CDP 之间的 bridge，它把“打开页面、执行脚本、读取 DOM”这类工具调用转换成 CDP 请求。</p>
<p>两条会话的连接关系应该是这样的：</p>
<p>Codex session A ──▶ MCP bridge A ──▶ Chrome A</p>
<pre><code>                 CDP :49101       profile: work-a
</code></pre>
<p>Codex session B ──▶ MCP bridge B ──▶ Chrome B</p>
<pre><code>                 CDP :49102       profile: work-b
</code></pre>
<p>这里要隔离的是整条链路。单独多开窗口没有用，MCP、端口或 profile 只要有一处串了，两个 session 还是会互相影响。</p>
<h2>先补一个前提：autoConnect 来自 Chrome 官方 MCP</h2>
<p><code>autoConnect</code> 不是这个启动器实现的，它是 Chrome 官方 <code>chrome-devtools-mcp</code> 提供的连接方式。</p>
<p>按照 Chrome 官方文档，Chrome 144 及以上版本可以在 <code>chrome://inspect/#remote-debugging</code> 开启远程调试，然后给 MCP server 加上 <code>--autoConnect</code>：</p>
<p>{</p>
<p>&quot;mcpServers&quot;</p>
<p>:</p>
<p>{</p>
<pre><code>&quot;chrome-devtools&quot;
</code></pre>
<p>:</p>
<p>{</p>
<pre><code>  &quot;command&quot;
</code></pre>
<p>:</p>
<p>&quot;npx&quot;</p>
<p>,</p>
<pre><code>  &quot;args&quot;
</code></pre>
<p>:</p>
<p>[</p>
<p>&quot;chrome-devtools-mcp@latest&quot;</p>
<p>,</p>
<p>&quot;--autoConnect&quot;</p>
<p>]</p>
<pre><code>}
</code></pre>
<p>}</p>
<p>}</p>
<p>这种方式适合让 Agent 接管已经打开的本机 Chrome，也能直接使用现有的登录状态。不过它有一个与多会话有关的前提：如果 Chrome 同时有多个活跃 profile，MCP 会连接 Chrome 判定的默认 profile，并访问这个 profile 下的所有窗口。</p>
<p>这正是我写启动器时要处理的问题。我要的不是“找到一个正在运行的 Chrome”，而是让每个 Codex session 都连到事先为它分配的 profile。于是脚本没有使用 <code>--autoConnect</code>，而是启动独立 Chrome，再通过 <code>--browserUrl</code> 指定连接目标。</p>
<h2>MCP 到底注入到哪里</h2>
<p>我一开始对“注入”这个词也有点误解。<code>chrome-devtools-mcp</code> 并不会进入 Chrome，它是作为 MCP server 注册到 Codex，然后通过 CDP 去控制 Chrome。</p>
<p>Codex 可以在启动时用 <code>-c</code> 接收这份配置：</p>
<p>codex \</p>
<p>-c</p>
<p>'mcp_servers.chrome-devtools.command=&quot;node&quot;'</p>
<p>\</p>
<p>-c</p>
<p>&quot;mcp_servers.chrome-devtools.args=[..., &quot;--browserUrl&quot;,&quot;</p>
<p>$devtools_url</p>
<p>&quot;]&quot;</p>
<p>第一行告诉 Codex 怎么启动 MCP server。第二行里的 <code>--browserUrl</code> 告诉 <code>chrome-devtools-mcp</code>，它该连接哪个 Chrome。</p>
<p>这也决定了配置应该在什么时候传入。要跑多个 session，就在启动 Codex 时为每个进程传入各自的 <code>browserUrl</code>。这份 MCP 配置只作用于当前 Codex 进程。</p>
<h2>profile 不是一个浏览器窗口</h2>
<p>第二个问题是 profile。</p>
<p>Chrome 的 profile 本质上是一个可写目录。Cookie、缓存、扩展设置、Service Worker 和登录状态都在里面，Chrome 还会在目录中放锁，防止多个进程同时写入。</p>
<p>启动 Chrome 时，可以用 <code>--user-data-dir</code> 指定这个目录：</p>
<p>chrome \</p>
<p>--remote-debugging-port=</p>
<p>&quot;</p>
<p>$port</p>
<p>&quot;</p>
<p>\</p>
<p>--user-data-dir=</p>
<p>&quot;</p>
<p>$profile_dir</p>
<p>&quot;</p>
<p>如果两个 Chrome 进程共用同一个目录，第二个进程通常会因为锁冲突而启动失败。即便勉强共用了，登录状态和缓存也会混在一起，问题反而更难查。</p>
<p>启动器会给每个 session 分配独立目录。直接运行 <code>./codex-browser</code> 时，它会用自动选择的端口生成 session 名，比如 <code>codex-49101</code>。这适合临时开一个全新的会话。</p>
<p>如果我想在下次启动时继续使用原来的登录状态，可以固定 <code>CODEX_BROWSER_SESSION</code>：</p>
<p>CODEX_BROWSER_SESSION=work-a ./codex-browser</p>
<p><code>work-a</code> 会对应一个固定的 profile 目录。当前会话退出后，再用同一个 session 名启动，就能复用里面的 Cookie、登录状态和站点数据。<code>CODEX_BROWSER_PROFILE_ROOT</code> 还可以修改这些 profile 的存放位置，不过一般不需要设置。</p>
<p>复用发生在前后两次启动之间。两个并发会话仍然不能使用相同的 <code>CODEX_BROWSER_SESSION</code>，否则它们会争用同一个目录。</p>
<h2>启动器如何连接到正确的 CDP 端口</h2>
<p>第三个问题是 CDP 端口。</p>
<p>Chrome 通过 <code>--remote-debugging-port</code> 暴露 CDP，例如：</p>
<p><a href="http://127.0.0.1:49101">http://127.0.0.1:49101</a></p>
<p>默认情况下，脚本会向操作系统申请一个当前可用的本机端口。Chrome 启动后，脚本持续请求 <code>/json/version</code>，直到确认 CDP 已经可以访问。日常使用不需要关心具体端口。</p>
<p><code>CODEX_CHROME_PORT</code> 可以把端口固定下来，但这是高级用法。只有外部工具需要连接一个已知的 CDP 地址，或者需要针对固定端口排错时，我才会设置它。</p>
<p>Chrome 就绪后，启动器已经知道刚刚选中的 <code>$devtools_url</code>，会把它作为 <code>--browserUrl</code> 传给 <code>chrome-devtools-mcp</code>。这一步使用的是官方 MCP 的指定地址连接能力，并不是 <code>--autoConnect</code>。</p>
<p>启动过程可以拆成三步：</p>
<ul>
<li>
<ol>
<li>默认自动选择端口，必要时才手动指定；</li>
</ol>
</li>
<li>
<ol start="2">
<li>启动 Chrome，等待 CDP 就绪；</li>
</ol>
</li>
<li>
<ol start="3">
<li>把同一个 URL 传进当前 session 的 MCP 配置。</li>
</ol>
</li>
</ul>
<p>如果要复用一个已经启动的 Chrome，可以传 <code>--browser-url</code> 或 <code>CODEX_CHROME_DEVTOOLS_URL</code>。脚本会先检查对应的 <code>/json/version</code>，确认它确实是可用的 CDP 端点，然后再启动 Codex。</p>
<p>端口可以自动选，选完以后必须明确绑定。</p>
<h2>三个参数要跟着同一个 session 走</h2>
<p>回头看这三个问题，它们正好对应一条完整的连接：</p>
<p>Codex session ↔ MCP browserUrl ↔ CDP port ↔ Chrome profile</p>
<p>MCP 配置决定 bridge 连接哪个 <code>browserUrl</code>。CDP 端口指向具体的 Chrome 进程。profile 再决定这个 Chrome 使用哪份浏览器状态。</p>
<p>启动器做的事情，就是在启动时把这几项绑到一起。这样每个 Codex session 都有明确的浏览器归属，MCP 也不用临时猜测该连接哪个 Chrome。</p>
<h2>谁启动 Chrome，谁负责关</h2>
<p>连接隔离以后，还有一个容易被忽略的问题：退出时该关掉哪个 Chrome？</p>
<p><code>codex-browser</code> 启动 Chrome 后会记录 PID，并注册 <code>trap ... EXIT INT TERM</code>。Codex 退出时，它只关闭自己创建的 Chrome。</p>
<p>如果我传入的是已有 <code>--browser-url</code>，启动器只负责连接，不会关闭那个 Chrome。因为它不是这次启动创建的进程。</p>
<p>端口或 profile 撞车时也应该直接失败。如果脚本偷偷复用一个已经存在的端口，当前 Codex 很可能连到别人的浏览器。这里报错反而更安全，也更容易排查。</p>
<h2>我现在怎么启动</h2>
<p>最简单的用法就是直接运行：</p>
<p>./codex-browser</p>
<p>要开多个会话，就在不同终端里分别运行同一条命令。每次启动都会自动选择端口，并创建独立的 profile。</p>
<p>脚本也支持恢复 Codex 会话：</p>
<p>./codex-browser r</p>
<p>./codex-browser last</p>
<p><code>r</code> 会转换成 <code>codex resume</code>，可以选择要恢复的会话；<code>last</code> 会转换成 <code>codex resume --last</code>，直接继续最近一次会话。</p>
<p>如果某个会话以后还要继续用，给它一个固定的 session 名即可。端口仍然交给脚本自动分配：</p>
<p>CODEX_BROWSER_SESSION=work-a ./codex-browser</p>
<p>下一次使用同一个名字，就会打开 <code>work-a</code> 对应的 profile。它也可以和 <code>resume</code> 一起使用，同时恢复 Codex 会话和浏览器状态：</p>
<p>CODEX_BROWSER_SESSION=work-a ./codex-browser r</p>
<p>只有确实需要固定 CDP 地址时，才同时指定端口：</p>
<p>CODEX_CHROME_PORT=49101 CODEX_BROWSER_SESSION=work-a ./codex-browser</p>
<p>这次真正解决的并不是 Chrome 能不能多开。Chrome 本来就能多开。麻烦的是如何让每个 Codex 始终找到属于自己的那个实例，并且在退出时只清理自己的资源。把 MCP 配置、CDP 端口和 profile 放进同一个 session 生命周期里，多个浏览器会话才能稳定地同时运行。</p>
<p>我已经把这个启动器开发好了，代码和使用说明放在 GitHub：agent-browser-launchers。</p>
]]></content:encoded>
    </item>
    <item>
      <title><![CDATA[用Context Engineering的思路排查线上问题]]></title>
      <link>https://xiaofeng.dev/writing/context-engineering-troubleshooting/</link>
      <guid>https://xiaofeng.dev/writing/context-engineering-troubleshooting/</guid>
      <pubDate>Sat, 11 Jul 2026 00:00:00 GMT</pubDate>
      <description><![CDATA[用 Context Engineering 的思路排查线上问题]]></description>
      <content:encoded><![CDATA[<h1>用 Context Engineering 的思路排查线上问题</h1>
<p>最近处理一个遗留项目的生产问题，让我对 Claude、Codex 这类 AI Coding 工具在诊断线上环境问题有了一些心得。</p>
<h2>背景：一个我并不熟悉的老项目</h2>
<p>这次问题来自一个几年前开发完成的项目。项目本身已经不是团队当前主要开发对象，但还有客户在持续使用。</p>
<p>这类项目有几个典型特点：</p>
<ul>
<li>前端、后端、App、固件都有自己的代码和逻辑。</li>
<li>部署方式和运行环境可能已经不是团队日常最熟悉的那套。</li>
<li>原始开发人员未必随时可问。</li>
<li>文档可能不完整，或者已经跟当前线上状态有偏差。</li>
<li>客户仍然在用，所以问题必须尽快定位和解决。</li>
</ul>
<p>我自己并不熟悉这个项目，也没有办法花很多时间从头学习它的完整架构和基本原理。客户遇到的问题：某个用户前一天还能使用，第二天开始页面上没有出现操作按钮。后台配置看起来正常，服务端接口也没有明显报错。最好能快速看现场视频、查日志、理解链路，然后尽快给出判断。</p>
<p>这也是我最想分享的点：在不熟悉项目的情况下，如何让 Claude / Codex 这类 AI Coding 工具快速进入状态，并且真的帮上忙。</p>
<h2>第一件事：尽可能提供完整代码上下文</h2>
<p>对复杂系统来说，只给后端代码通常不够。</p>
<p>如果问题涉及端到端链路，最好能让 AI 看到所有相关代码：</p>
<ul>
<li>前端代码</li>
<li>后端代码</li>
<li>App 代码</li>
<li>SDK 代码</li>
<li>固件或设备侧协议代码</li>
</ul>
<p>不用担心AI会一次性读完所有代码，它的能力已经足够在必要时候进行深度搜索、跳转、关联。部署脚本、配置文件、API 文档、历史排查记录 —— 这些其实不需要。因为这些都可以通过代码得出结论。用代码做Single Source of Truth更好。</p>
<h2>第二件事：提供客户项目背景和部署方式</h2>
<p>代码之外，还需要业务和部署上下文。比如客户的租户名称、账号清单、权限配置情况。但是这些信息提供起来比较麻烦，因为我对客户的一些具体的配置到底是标准化的还是定制化的，我不太了解。我唯一能给出的是这个客户的租户ID和受影响用户ID。其他的需要AI根据代码的使用链路，自己去后台或数据库里查询。当时大概有三种选择。</p>
<p>第一种，是直接让 AI 访问生产数据库。 第二种，是调用生产环境 API。 第三种，是让 AI 使用我的账号登录浏览器，直接查看客户项目配置。</p>
<p>我最后选了第三种，也不是因为哪种更好，而是这种方式最简单，不需要去搞 APIKEY，也不需要搞readonly的数据库账号。</p>
<p>这里用到了Chrome Dev Tools MCP</p>
<h2>第三件事：告诉 AI 日志在哪里，并给它 CLI</h2>
<p>这次我用的是观测云的 CLI。</p>
<p>排查生产问题，日志位置非常关键。最好明确告诉 AI：后端 API 日志、App 日志、前端监控、设备或固件日志、第三方调用日志分别在哪里，以及日志里的关键字段是什么，<code>request id</code>、<code>user id</code>、<code>device id</code> 怎么关联。</p>
<p>如果日志量不大，可以直接导出给 AI。但真实生产日志往往很大，不可能一次性塞进聊天窗口，这时候 CLI 就很关键。</p>
<p>CLI 的价值在于：AI 不需要我手工复制大量日志给它，而是可以直接查询云端日志仓库。让 AI 从被动阅读，变成主动查询。</p>
<h2>AI自动排查的效果：</h2>
<p>它很细地查每一段日志：权限预取有没有成功，App 有没有离线，蓝牙扫描有没有发生，有没有识别到目标设备，有没有创建本地 session，有没有建立连接，有没有写入 token，有没有上报最终事件。我把几天的工作量压缩成了半小时，并且给出了非常准确的结论。</p>
<p>一次排查结束后，如果所有结论只留在聊天记录里，很快就会丢失。可以用Compound Engineering的SKILL沉淀solution 文档，形成可复用经验。</p>
<h2>核心收获</h2>
<p>第一，AI 需要完整上下文：代码、项目背景、部署方式、业务场景、关键概念和时间窗口。 第二，要给 AI 进入现场的工具，尤其是日志查询 CLI。没有日志入口，AI 只能猜；有了 CLI，它才能逐段排除。 第三，不能直连数据库时，可以让 AI 通过 Chrome DevTools MCP 查看后台页面。后台本身就是业务配置的解释层。 第四，尽可能使用视觉模型。很多后台配置不是 JSON，而是表格、标签、状态、按钮和弹窗。 第五，人的作用不是手工查每一行日志，而是补上下文、审查AI的行动路径。 最后，排查结束后要沉淀，把结论写成 solution 文档，让这次上下文变成下次可复用的经验。</p>
<p><img src="/writing/wechat-tech-assets/context-engineering-troubleshooting/00157ed7a7ef3028.png" alt="图片"></p>
]]></content:encoded>
    </item>
    <item>
      <title><![CDATA[Compound Engineering 重构：把 Agent 收进 Skill]]></title>
      <link>https://xiaofeng.dev/writing/compound-engineering-agent-skill/</link>
      <guid>https://xiaofeng.dev/writing/compound-engineering-agent-skill/</guid>
      <pubDate>Tue, 30 Jun 2026 00:00:00 GMT</pubDate>
      <description><![CDATA[版本号也许看不出来，但这次对 Compound Engineering 来说是一次很大的更新。现在架构变了，文档组织方式变了，智能体能跑得更久、也跑得更好，而且我们已经全面拥抱 /goal 。]]></description>
      <content:encoded><![CDATA[<h1>大重构：把 Agent 收进 Skill</h1>
<p>版本号也许看不出来，但这次对 Compound Engineering 来说是一次很大的更新。现在架构变了，文档组织方式变了，智能体能跑得更久、也跑得更好，而且我们已经全面拥抱 <code>/goal</code>。</p>
<h2>我们杀掉了自己的智能体（有意为之）</h2>
<p>这可能是 Compound Engineering 首次发布以来最大的一次结构性变化。</p>
<p>过去，Compound Engineering 依赖一组专门的独立智能体定义。它们在 Claude Code 里表现很好。但到了 Codex、Cursor、Gemini、Pi 和 OpenCode 里，效果就没那么稳定，甚至根本不能工作。原因是正式的智能体定义并不是各个运行环境都可靠支持的共同基础。每个运行环境处理智能体的方式都有些不同。</p>
<p>这意味着，我们要么维护多套针对不同运行环境的副本，要么让用户使用一个只能部分工作的版本，而且还需要通过额外的手动更新来保持最新。</p>
<p>我们把这一切都移除了，基本上是把东西拆到了最底层。</p>
<p>现在每个技能都是自包含的。我们仍然能实现专门的“智能体”行为，但所有内容都放在技能自己的提示词资产里，而不是放在正式的智能体定义里。它非常详细，可能细得有点过头，但它对现有用户和新用户都会产生很大影响。</p>
<p>不需要复制脚本。不需要嵌套路径。也不再有“更新之后还要重新跑 setup”。</p>
<p>实际效果是：</p>
<ul>
<li><strong>Codex CLI 和 Codex 桌面应用</strong>：现在可以干净地工作，包括作为一个支持自动更新的完整插件。之前 Codex 桌面应用还需要一些变通方案。</li>
<li><strong>OpenCode、Pi 和 Cursor</strong>：原生支持好了很多。插件现在只由技能组成，这意味着它也能放进那些根本没有“独立智能体”概念的插件系统里。</li>
</ul>
<h2>计划现在已经为 <code>/goal</code> 准备好了</h2>
<p>我们过去会产出两个文档：一个需求文档和一个实施计划。这其实是我们那套有缺陷的“全靠人类工作者”模式留下来的痕迹。</p>
<p>它们服务于工作流的不同阶段，从概念上说得通。但实际问题是，需求会随着实施过程不断变化。一旦变化，你就有两个文档要更新；它们可能彼此漂移；你得记住某个问题上哪个文档才是权威；智能体也必须把两个文档都放进上下文里，并在两者之间做协调。</p>
<p>新的统一“计划”文档把两者合并成一个产物。运行 <code>/ce-brainstorm</code> 时，它会先列出场景和需求。如果你接着运行 <code>/ce-plan</code>，这个文档会继续更新，把实施计划细节也纳入其中。这样你和你的智能体就拥有一个完整的文档包。</p>
<p>更重要的变化在于这个文档的设计目标。它已经为 <code>/goal</code> 准备好了：它有清晰的完成定义，范围是收敛的，实施方式也足够明确，让智能体可以基于它工作，而不需要不断回来确认。</p>
<p>在 <code>/ce-plan</code> 的末尾，我们会提供一个选项，直接把这个计划交给 <code>/goal</code> 启动。然后你就可以走开了，或者切换到另一个智能体去做另一组工作。智能体知道“完成”到底长什么样，因为这已经写在文档里了。</p>
<p>在复杂功能的测试中，这个循环表现得很好。我跑过几次持续数小时的完整功能开发，其中一次超过了 6 小时。智能体完整实现了功能，写了测试，打开了 PR，并且在初始计划交接之后，没有任何人介入就完成了交付。</p>
<p>对于带界面的功能，在智能体完成第一轮工作之后，你还有空间审阅、迭代和调整，这也是 <code>/ce-polish</code> 这类技能能发挥作用的地方。</p>
<p>可移植性也是额外收益：一个文档更容易在多个智能体之间传递，附到任务上，或者放进新的上下文里。</p>
<h2>需要画图时，文档也会画图</h2>
<p>计划和想法并不总是适合写成一整墙文字。有些东西就是需要图。</p>
<p>所以现在技能支持把真正的 HTML 输出作为一个选项。使用它时，文档会在文字之外补充视觉内容：在图比段落更能说明问题的地方放上图。</p>
<p><code>ce-ideate</code> 更进一步，默认输出 HTML，因为构思本来就是一个需要人参与的时刻，而人阅读草图式想法的速度，比读规格文档更快。统一的计划文档也支持同样的处理方式。</p>
<p>关于如何使用，有几点需要知道：</p>
<ul>
<li><strong>Markdown 仍然是默认格式。</strong> 大多数 Compound Engineering 用法，包括我们自己的用法，都是把文档直接交给智能体，而 Markdown 是更合适的选择。HTML 是可选项。</li>
<li><strong>一行就能试。</strong> 下次运行 <code>ce-brainstorm</code> 或 <code>ce-plan</code> 时，加上 <code>output=html</code> 或 <code>use html format</code>。</li>
<li><strong>设置一次，以后不用再管。</strong> 把你偏好的默认格式放进 <code>AGENTS.md</code> / <code>CLAUDE.md</code>，或者放进你的 Compound Engineering 配置，这样就不必每次提示都重复输入。</li>
<li><strong>它会尊重你的品味。</strong> 如果你的仓库根目录有 <code>DESIGN.md</code>，技能会用它来影响文档设计，同时保持内容清晰可读。</li>
</ul>
<p>对大多数用户来说，包括我们自己，Markdown 仍然是默认格式。大多数时候，文档会直接交给智能体，而智能体不需要 HTML。视觉路径是为那些人类会阅读、而内容又确实受益于视觉表达的场景准备的。</p>
<h2>还有几件事</h2>
<ul>
<li><strong>跨模型对抗式审查。</strong><code>ce-code-review</code> 增加了跨模型对抗式审查：让第二个模型主动尝试找出第一个模型工作中的问题。我们也把审查范围调到了合适大小，并通过一条可移植路径来处理它，让它在各处表现一致。</li>
<li><strong>更聪明的 PR 反馈处理。</strong><code>ce-resolve-pr-feedback</code> 现在会先集中判断问题，再分派修复任务，而不是并行发出修复请求然后碰运气。</li>
<li><strong>ce-brainstorm 有了眼睛。</strong> 头脑风暴期间现在有视觉反馈，而不只是文本变化。当讨论需要时，智能体会启动一个小的视觉产物来获取你的输入，并在一个小型网页服务里预览；等你完成后，再把会话关掉。即使在 Codex 应用里也能工作。</li>
<li><strong>插件市场和安装流程全面修复。</strong> 插件和市场元数据已经对齐，技能描述减少了 50%，在 Pi 和 OpenCode 等更多运行环境上，安装更容易也更快。</li>
</ul>
<h2>如何获取</h2>
<p>这个版本包含插件市场更新，这意味着你的运行环境常规更新机制可能不足以拿到它。对现有安装来说，最稳妥的方式是移除插件，然后从插件市场重新安装一遍。</p>
<p>这有点麻烦，但这是能保证你拿到正确版本和正确插件数据的方式。我们也修复了一些插件市场和插件数据问题，这些问题之前给首次安装造成了摩擦，所以现在流程应该会比以前更顺。</p>
<p>重新安装：从你的运行环境中移除 Compound Engineering，然后按照仓库说明里的安装步骤操作。不同运行环境的安装方式不同，所以仓库说明才是针对你具体设置的正确参考。</p>
<p>如果你是新用户：安装后在任意项目里运行 <code>ce-setup</code>，它会帮你开始。为 <code>/goal</code> 准备好的计划文档和 HTML 输出都可以马上试。</p>
<h2>为什么这次重要</h2>
<p>大多数版本都是在增加东西，但这一次感觉要大得多。更新你的插件。拿一个真实问题跑 <code>/ce-brainstorm</code>。告诉我们效果如何。</p>
<p>Trevin Chow：专注于 AI 和 AI 构建实践。参与开源项目，包括 @ppressdev、@illo_skill 和 Compound Engineering。</p>
]]></content:encoded>
    </item>
    <item>
      <title><![CDATA[Antigravity CLI 真实体验]]></title>
      <link>https://xiaofeng.dev/writing/antigravity-cli-review/</link>
      <guid>https://xiaofeng.dev/writing/antigravity-cli-review/</guid>
      <pubDate>Thu, 25 Jun 2026 00:00:00 GMT</pubDate>
      <description><![CDATA[最近 Gemini CLI 不支持 Google One 账号了，原来那条路就有点走不通。]]></description>
      <content:encoded><![CDATA[<h1>Antigravity CLI 真实体验</h1>
<h2>背景</h2>
<p>最近 Gemini CLI 不支持 Google One 账号了，原来那条路就有点走不通。</p>
<p>这件事大概发生在 2026 年 6 月中旬：公开迁移信息里比较关键的时间点是 <strong>2026 年 6 月 18 日</strong>，Gemini CLI 对个人免费 / Google AI Pro / Ultra 这类消费级入口开始停止或受限。Google 官方也给了从 Gemini CLI 迁移到 Antigravity CLI 的文档：<a href="https://antigravity.google/docs/gcli-migration%E3%80%82">https://antigravity.google/docs/gcli-migration。</a></p>
<p>所以换到 Antigravity CLI（agy）试一下：同样是 Google 生态，模型额度和入口看起来更顺手，也能顺便体验一下它的 agent-first 工作流。</p>
<h2>模型与可用性</h2>
<ul>
<li>模型可用性低：Claude 模型经常 high traffic</li>
<li>Gemini 模型速度很快，但 3.5 Flash 对复杂任务完全不行，3.1 Pro 稍微好一点</li>
<li>Gemini 3.1 Pro (High) 是目前相对可用的主力选择</li>
<li>Claude Sonnet 4.6 / Opus 4.6 看起来更适合复杂任务，但可用性不稳定</li>
</ul>
<h2>规则与生态兼容</h2>
<ul>
<li>Skill 激活率低，或者干脆不可见</li>
<li>官方说支持 <a href="http://GEMINI.md">GEMINI.md</a> 和 <a href="http://AGENTS.md">AGENTS.md</a>，但实际遵从度不够；不支持 <a href="http://CLAUDE.md">CLAUDE.md</a></li>
<li>Gemini 插件需要转成 Antigravity plugins，不能直接无脑兼容</li>
<li>Claude 插件也不兼容</li>
<li>CLI 闭源</li>
</ul>
<h2>执行过程与可观察性</h2>
<ul>
<li>思考内容不可见，工具调用过程也不清晰</li>
<li>干完活不能自己检查结果</li>
<li>干活太啰嗦：连续半小时频繁截图确认，但看不出具体任务进度</li>
</ul>
<h2>版本控制与风险</h2>
<ul>
<li>历史记录无法回退</li>
<li>幻觉严重：改造不成功后，又回退 restore，再寻求用户确认</li>
<li>commit / restore 时不与用户确认范围，容易超范围 commit / restore</li>
</ul>
<h2>交互体验</h2>
<ul>
<li>不支持一些常用快捷键，比如 Ctrl+T</li>
<li>不支持在命令行 resume 某个 session</li>
</ul>
<h2>参考资料</h2>
<h3>当前可用模型</h3>
<ul>
<li>Gemini 3.5 Flash (Low / Medium / High)</li>
<li>Gemini 3.1 Pro (Low / High)</li>
<li>Claude Sonnet 4.6 (Thinking)</li>
<li>Claude Opus 4.6 (Thinking)</li>
<li>GPT-OSS 120B (Medium)</li>
</ul>
<h3>迁移与兼容</h3>
<p>Google 官方迁移文档主要讲的是迁移旧配置、导入 Gemini CLI extensions、调整 skills 路径，以及转换 MCP 配置。也就是说，官方本身就是希望 Gemini CLI 用户能比较平滑地迁到 agy。</p>
<ul>
<li>首次执行 <code>agy</code> 时，官方文档说会自动检测 legacy configurations，并通过交互式 checklist 选择要迁移的内容</li>
<li>Gemini CLI 的 extensions 需要转成 Antigravity 的 plugins，可以用 <code>agy plugin import gemini</code></li>
<li>规则文件方面，官方说 workspace context rules 基本一致，<code>GEMINI.md</code> 和 <code>AGENTS.md</code> 都会继续解析；全局约束会继续读取 <code>~/.gemini/GEMINI.md</code></li>
<li>skills 路径有变化：全局从 <code>~/.gemini/skills/</code> 变成 <code>~/.gemini/antigravity-cli/skills/</code>，项目内从 <code>.gemini/skills/</code> 变成 <code>.agents/skills/</code></li>
<li>MCP 配置也变了：不再塞在 <code>~/.gemini/settings.json</code> 里，而是拆到 <code>mcp_config.json</code>；远程服务的 key 也从 <code>url</code> / <code>httpUrl</code> 改成 <code>serverUrl</code></li>
</ul>
<p>这块看起来官方考虑了迁移，但不是完全无痛迁移。尤其是 skills 和 MCP，还是要手动检查一下。</p>
]]></content:encoded>
    </item>
    <item>
      <title><![CDATA[Codex Spark模型实测体验]]></title>
      <link>https://xiaofeng.dev/writing/codex-spark-review/</link>
      <guid>https://xiaofeng.dev/writing/codex-spark-review/</guid>
      <pubDate>Mon, 22 Jun 2026 00:00:00 GMT</pubDate>
      <description><![CDATA[这篇文章记录我在 Codex 额度用完后实际切换到 Codex Spark 的体验，重点比较它与 GPT-5.3-Codex 在响应速度、任务边界、上下文能力和复杂任务表现上的差异，并总结它适合快速修改、原型验证和结对编程的场景，以及不适合深度重构的原因。]]></description>
      <content:encoded><![CDATA[<h1>Codex Spark 模型实测体验</h1>
<p>这篇文章记录我在 Codex 额度用完后实际切换到 Codex Spark 的体验，重点比较它与 GPT-5.3-Codex 在响应速度、任务边界、上下文能力和复杂任务表现上的差异，并总结它适合快速修改、原型验证和结对编程的场景，以及不适合深度重构的原因。</p>
<h2>什么是 Codex Spark？</h2>
<p><strong>GPT-5.3-Codex-Spark</strong> 是 OpenAI 于 2026 年 2 月发布的轻量级编程模型，主打<strong>实时协作与超低延迟</strong>，而非深度推理。它运行在 Cerebras 的 WSE-3 晶圆级芯片上，推理速度超过 <strong>1000 tokens/秒</strong>，大约是标准 GPT-5.3-Codex 的 15 倍，客户端往返延迟降低了 80%。</p>
<h2>实测结果</h2>
<h2>任务表现</h2>
<table class="performance-table">
  <thead>
    <tr>
      <th scope="col">任务</th>
      <th scope="col">结果</th>
      <th scope="col">判断</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <th scope="row">文档改写</th>
      <td data-label="结果"><span class="performance-status is-success">成功</span></td>
      <td data-label="判断">适合目标明确的局部修改</td>
    </tr>
    <tr>
      <th scope="row">执行简单命令</th>
      <td data-label="结果"><span class="performance-status is-success">成功</span></td>
      <td data-label="判断">适合即时反馈和快速验证</td>
    </tr>
    <tr>
      <th scope="row">大范围中译英</th>
      <td data-label="结果"><span class="performance-status is-limited">受限</span></td>
      <td data-label="判断">出现编译错误，需要人工收尾</td>
    </tr>
    <tr>
      <th scope="row">大范围改写 CSS 样式和 HTML 布局</th>
      <td data-label="结果"><span class="performance-status is-limited">受限</span></td>
      <td data-label="判断">样式偏差大，并频繁压缩上下文</td>
    </tr>
  </tbody>
</table>
<h3>提示词特征</h3>
<p>系统提示中含 spark 模型标识：</p>
<p>&quot;You are super fast model; your sampling speed is 1.5k tokens per second&quot;</p>
<p>这是 Codex 的 spark 快速档模型的特征字符串。</p>
<h2>为什么复杂任务不太行？</h2>
<p>Codex Spark 的&quot;短板&quot;是<strong>刻意的设计取舍</strong>，核心原因可以归纳为以下几点：</p>
<p><strong>1. 它是&quot;小模型&quot;，参数规模大幅缩减</strong></p>
<p>Codex Spark 是 GPT-5.3-Codex 的精简版，推测激活参数约 30B 级别。模型容量直接决定了其对复杂逻辑、长程依赖和多文件架构的理解上限。OpenAI 官方也明确承认：&quot;新模型的性能将不如 GPT-5.3-Codex，但能够在极短时间内完成任务&quot;。</p>
<p><strong>2. 基准测试成绩明显落后</strong></p>
<p>在考察软件工程综合能力的 SWE-Bench Pro 和 Terminal-Bench 2.0 测试中，Codex Spark 的得分显著低于完整版。例如 Terminal-Bench 2.0 中，Spark 得分为 <strong>58.4%</strong>，而 GPT-5.3-Codex 达到 <strong>77.3%</strong>。这说明它在需要多步规划、深度调试和自主执行的复杂任务上确实力有不逮。</p>
<p><strong>3. 上下文窗口与功能受限</strong></p>
<p>发布时仅支持 <strong>128K 上下文</strong>（标准版为 200K），且<strong>仅支持文本输入</strong>，没有多模态能力。对于需要分析大量代码库、处理复杂文档或理解图像界面的任务，这构成了硬性瓶颈。</p>
<p><strong>4. 行为模式偏向&quot;轻量编辑&quot;而非&quot;深度重构&quot;</strong></p>
<p>OpenAI 对 Spark 的调优目标是<strong>快速、可中断、可引导</strong>。它默认进行轻量级、针对性的代码修改，倾向于最小化编辑而非大规模重写，也不会自动运行测试。这种设计非常适合实时迭代，但面对需要数小时自主工作的复杂重构或架构设计时，它缺乏完整版那种&quot;深度推理 + 长时执行&quot;的能力。</p>
<h2>小结</h2>
<p>OpenAI 对 Codex Spark 的定位非常清晰：<strong>它不是 GPT-5.3-Codex 的替代品，而是互补品</strong>。当你需要快速改一行代码、调整样式、验证原型或和 AI &quot;结对编程&quot;时，Spark 的即时反馈体验极佳；但遇到需要深度推理、多文件协调、长时间自主运行的复杂任务时，仍然需要切换回完整的 GPT-5.3-Codex 或其他大模型。</p>
]]></content:encoded>
    </item>
    <item>
      <title><![CDATA[开源 Web AI 平台 Skill 能力调研（2026）]]></title>
      <link>https://xiaofeng.dev/writing/open-source-web-ai-platform-skills-2026/</link>
      <guid>https://xiaofeng.dev/writing/open-source-web-ai-platform-skills-2026/</guid>
      <pubDate>Sun, 31 May 2026 00:00:00 GMT</pubDate>
      <description><![CDATA[本文只评估开源 Web / Workspace / Agent 平台中的 Skill 能力，重点看是否出现接近 Claude Skills 的 SKILL.md 、渐进式加载、Skill 管理、触发方式、文件与脚本运行时等能力。]]></description>
      <content:encoded><![CDATA[<p>资料检索日期：2026-05-30</p>
<h2>调研范围</h2>
<p>本文只评估开源 Web / Workspace / Agent 平台中的 Skill 能力，重点看是否出现接近 Claude Skills 的 <code>SKILL.md</code>、渐进式加载、Skill 管理、触发方式、文件与脚本运行时等能力。</p>
<p>不纳入本次评估：</p>
<ul>
<li>本地优先、桌面端或 CLI 产品，例如 OpenClaw 等本地产品。</li>
<li>闭源或商业 SaaS 产品，例如 Coze 商业版、腾讯 ADP 等。</li>
<li>仅提供普通工具调用、自动化编排、Prompt Template 或 Agent Marketplace 的平台，除非其已明确提供 Skill / <code>SKILL.md</code> 一等能力。</li>
</ul>
<h2>评估维度</h2>
<p>Claude Skills 只作为 baseline，不参与平台排名。评分只看 Skill 本体能力；外部集成、自动化编排、通用 Tool Calling 等不计入成熟度。</p>
<table>
<thead>
<tr>
<th>能力</th>
<th>英文对应</th>
<th>说明</th>
</tr>
</thead>
<tbody>
<tr>
<td>Skill 管理</td>
<td>Skill Management / Skill Registry</td>
<td>创建、导入、启停、分配、共享</td>
</tr>
<tr>
<td><code>SKILL.md</code></td>
<td><code>SKILL.md</code> Compatibility</td>
<td>兼容 <code>SKILL.md</code> 格式与目录结构</td>
</tr>
<tr>
<td>渐进式加载</td>
<td>Progressive Disclosure / Lazy Loading</td>
<td>支持 manifest / references / assets 分层加载</td>
</tr>
<tr>
<td>触发方式</td>
<td>Invocation Modes / Auto Trigger</td>
<td>手动调用、模型自动选择、始终启用</td>
</tr>
<tr>
<td>知识与文件</td>
<td>References / Assets</td>
<td>Skill 可携带 references / assets</td>
</tr>
<tr>
<td>脚本与运行时</td>
<td>Script Execution / Skill Runtime</td>
<td>Skill 可携带并执行脚本，有明确运行上下文</td>
</tr>
</tbody>
</table>
<p>评分标准：🟢 完整支持；🟡 部分支持；🔴 不支持。</p>
<h2>1. LibreChat</h2>
<h3>概览</h3>
<table>
<thead>
<tr>
<th>项目</th>
<th>内容</th>
</tr>
</thead>
<tbody>
<tr>
<td>平台名称</td>
<td>LibreChat</td>
</tr>
<tr>
<td>官网</td>
<td><a href="https://www.librechat.ai">https://www.librechat.ai</a></td>
</tr>
<tr>
<td>GitHub</td>
<td><a href="https://github.com/danny-avila/LibreChat">https://github.com/danny-avila/LibreChat</a></td>
</tr>
<tr>
<td>平台类型</td>
<td>开源 Chat + Agent 平台</td>
</tr>
<tr>
<td>Skill 支持时间</td>
<td>2026-05-13，v0.8.6-rc1</td>
</tr>
<tr>
<td>支持程度</td>
<td>约 85%</td>
</tr>
</tbody>
</table>
<h3>相关链接</h3>
<ul>
<li><a href="https://www.librechat.ai/docs/features/skills">Skills / LibreChat</a></li>
<li><a href="https://www.librechat.ai/changelog/v0.8.6-rc1">LibreChat v0.8.6-rc1 Changelog</a></li>
<li><a href="https://github.com/danny-avila/LibreChat/issues/11106#issuecomment-4366741742">Issue #11106: Support for Agent Skills</a></li>
<li><a href="https://github.com/danny-avila/LibreChat/pull/12625">PR #12625: feat: agent skills</a></li>
<li><a href="https://github.com/danny-avila/LibreChat/pull/12580">PR #12580: Skills UI + Initial E2E CRUD / Sharing</a></li>
</ul>
<h3>能力矩阵</h3>
<table>
<thead>
<tr>
<th>能力</th>
<th>支持</th>
</tr>
</thead>
<tbody>
<tr>
<td>Skill 管理</td>
<td>🟢</td>
</tr>
<tr>
<td><code>SKILL.md</code></td>
<td>🟢</td>
</tr>
<tr>
<td>渐进式加载</td>
<td>🟢</td>
</tr>
<tr>
<td>触发方式</td>
<td>🟢</td>
</tr>
<tr>
<td>知识与文件</td>
<td>🟢</td>
</tr>
<tr>
<td>脚本与运行时</td>
<td>🟡</td>
</tr>
</tbody>
</table>
<h3>目前进展</h3>
<p>LibreChat 已经进入原生 Agent Skills 阶段，支持 <code>SKILL.md</code>、Skill Catalog、三种调用方式、Agent Scope、ACL 和 Skill Bundle。</p>
<h3>判断</h3>
<p>LibreChat 是当前样本中最接近 Claude Skills 的开源 Web 平台。短板是脚本执行仍依赖 Agent 可用工具与运行上下文，不是完全独立的 Skill 沙箱。</p>
<h2>3. OpenWebUI</h2>
<h3>概览</h3>
<table>
<thead>
<tr>
<th>项目</th>
<th>内容</th>
</tr>
</thead>
<tbody>
<tr>
<td>平台名称</td>
<td>OpenWebUI</td>
</tr>
<tr>
<td>官网</td>
<td><a href="https://openwebui.com">https://openwebui.com</a></td>
</tr>
<tr>
<td>GitHub</td>
<td><a href="https://github.com/open-webui/open-webui">https://github.com/open-webui/open-webui</a></td>
</tr>
<tr>
<td>平台类型</td>
<td>开源 AI Workspace</td>
</tr>
<tr>
<td>Skill 支持时间</td>
<td>2026 Q1</td>
</tr>
<tr>
<td>支持程度</td>
<td>约 70%</td>
</tr>
</tbody>
</table>
<h3>相关链接</h3>
<ul>
<li><a href="https://docs.openwebui.com/features/workspace/skills/">Skills / Open WebUI</a></li>
<li><a href="https://github.com/open-webui/open-webui/discussions/19951">Discussion #19951: Support for (Anthropic/OpenAI) skills and SKILL.md</a></li>
<li><a href="https://github.com/open-webui/open-webui/pull/21275">PR #21275: add Agent Skills system with semantic activation and script execution</a></li>
</ul>
<h3>能力矩阵</h3>
<table>
<thead>
<tr>
<th>能力</th>
<th>支持</th>
</tr>
</thead>
<tbody>
<tr>
<td>Skill 管理</td>
<td>🟢</td>
</tr>
<tr>
<td><code>SKILL.md</code></td>
<td>🟡</td>
</tr>
<tr>
<td>渐进式加载</td>
<td>🟡</td>
</tr>
<tr>
<td>触发方式</td>
<td>🟢</td>
</tr>
<tr>
<td>知识与文件</td>
<td>🟡</td>
</tr>
<tr>
<td>脚本与运行时</td>
<td>🔴</td>
</tr>
</tbody>
</table>
<h3>目前进展</h3>
<p>OpenWebUI 已上线 Workspace / Model Skills，但当前更接近 Markdown 指令集与按需上下文加载。</p>
<h3>判断</h3>
<p>OpenWebUI 已把 Skill 放进产品对象体系，值得关注；但脚本执行、完整 <code>SKILL.md</code> 目录兼容和独立 Skill Runtime 仍主要停留在相关 issue / PR 中。</p>
<hr>
<h2>4. Dify</h2>
<h3>概览</h3>
<table>
<thead>
<tr>
<th>项目</th>
<th>内容</th>
</tr>
</thead>
<tbody>
<tr>
<td>平台名称</td>
<td>Dify</td>
</tr>
<tr>
<td>官网</td>
<td><a href="https://dify.ai">https://dify.ai</a></td>
</tr>
<tr>
<td>GitHub</td>
<td><a href="https://github.com/langgenius/dify">https://github.com/langgenius/dify</a></td>
</tr>
<tr>
<td>平台类型</td>
<td>开源 Agent 平台</td>
</tr>
<tr>
<td>Skill 支持时间</td>
<td>2026-02-08，Marketplace <code>Skill_Agent</code>；2026-02-14，<code>1.14.0-rc1</code> 预览版 Agent x Skills</td>
</tr>
<tr>
<td>支持程度</td>
<td>约 60%</td>
</tr>
</tbody>
</table>
<h3>相关链接</h3>
<ul>
<li><a href="https://github.com/langgenius/dify/issues/30052#event-25577333288">Issue #30052: Agent Skills support proposal</a></li>
<li><a href="https://github.com/langgenius/dify/issues/35689">Issue #35689: Roadmap of Agent x Skills and Skill Editor</a></li>
<li><a href="https://github.com/langgenius/dify/releases/tag/1.14.0-rc1">Release 1.14.0-rc1: Agent x Skills preview</a></li>
<li><a href="https://marketplace.dify.ai/plugin/lfenghx/skill_agent">Skill_Agent - Dify Marketplace</a></li>
<li><a href="https://github.com/lfenghx/skill_agent">lfenghx/skill_agent</a></li>
</ul>
<h3>能力矩阵</h3>
<table>
<thead>
<tr>
<th>能力</th>
<th>支持</th>
</tr>
</thead>
<tbody>
<tr>
<td>Skill 管理</td>
<td>🟡</td>
</tr>
<tr>
<td><code>SKILL.md</code></td>
<td>🟡</td>
</tr>
<tr>
<td>渐进式加载</td>
<td>🟡</td>
</tr>
<tr>
<td>触发方式</td>
<td>🟡</td>
</tr>
<tr>
<td>知识与文件</td>
<td>🟢</td>
</tr>
<tr>
<td>脚本与运行时</td>
<td>🟡</td>
</tr>
</tbody>
</table>
<h3>目前进展</h3>
<p>Dify 目前是 Marketplace <code>Skill_Agent</code> 可用、原生 Agent x Skills / Skill Editor 预览出现过，但稳定版主线尚未明确。</p>
<h3>判断</h3>
<p>Dify 已出现直接面向 <code>SKILL.md</code> 的插件实现，也出现过原生 Skills 预览；当前应判断为“插件可用、原生预览出现过、稳定版路线未明确”。</p>
<hr>
<h2>5. n8n（不纳入正式评估）</h2>
<h3>概览</h3>
<table>
<thead>
<tr>
<th>项目</th>
<th>内容</th>
</tr>
</thead>
<tbody>
<tr>
<td>平台名称</td>
<td>n8n</td>
</tr>
<tr>
<td>官网</td>
<td><a href="https://n8n.io">https://n8n.io</a></td>
</tr>
<tr>
<td>GitHub</td>
<td><a href="https://github.com/n8n-io/n8n">https://github.com/n8n-io/n8n</a></td>
</tr>
<tr>
<td>平台类型</td>
<td>开源自动化平台</td>
</tr>
<tr>
<td>Skill 支持时间</td>
<td>无原生 Agent Skills</td>
</tr>
<tr>
<td>评估结论</td>
<td>不纳入正式排名</td>
</tr>
</tbody>
</table>
<h3>相关链接</h3>
<ul>
<li><a href="https://community.n8n.io/t/enable-n8n-agents-to-use-agent-skills-skill-md-references/246140/11">Feature Request: Enable n8n agents to use Agent Skills (<code>SKILL.md</code> + references)</a></li>
<li><a href="https://community.n8n.io/t/implementing-anthropic-style-agent-skills-in-n8n-a-deep-technical-walkthrough-with-postgres-progressive-disclosure/293285">Implementing Anthropic-style Agent Skills in n8n: Postgres + progressive disclosure</a></li>
</ul>
<h3>判断</h3>
<p>n8n 目前没有官方原生 <code>SKILL.md</code> Registry、目录扫描、skill manifest、lazy loading 或 Anthropic-style references 机制；现有内容主要是社区 feature request 或 workaround，因此只作为潜在线索保留。</p>
<hr>
<h2>综合排名（不含 Claude baseline）</h2>
<p>Claude Skills 是发明者和基准，不参与排名；n8n 没有原生 Skill 体系，也不进入正式排名。</p>
<table>
<thead>
<tr>
<th>排名</th>
<th>项目</th>
<th>开始讨论日期</th>
<th>首次支持日期</th>
<th>Skill 成熟度</th>
</tr>
</thead>
<tbody>
<tr>
<td>1</td>
<td>LibreChat</td>
<td>2025-12-26（Issue #11106）</td>
<td>2026-05-13（v0.8.6-rc1）</td>
<td>85%</td>
</tr>
<tr>
<td>2</td>
<td>LobeHub</td>
<td>2025-12-24（Issue #10917）</td>
<td>2026-02-22（PR #12424 合并）</td>
<td>80%</td>
</tr>
<tr>
<td>3</td>
<td>OpenWebUI</td>
<td>2025-12-14（Discussion #19951）</td>
<td>2026 Q1（Workspace Skills / 0.8，精确日期待核）</td>
<td>70%</td>
</tr>
<tr>
<td>4</td>
<td>Dify</td>
<td>2025-12-23（Issue #30052）</td>
<td>2026-02-08（Skill_Agent）；2026-02-14（1.14.0-rc1 预览）</td>
<td>60%</td>
</tr>
</tbody>
</table>
<hr>
<h2>产品判断</h2>
<p>如果目标是复刻或兼容 Claude Skills，最值得研究的顺序是：</p>
<ol>
<li>LibreChat</li>
<li>LobeHub Skill Management</li>
<li>OpenWebUI</li>
<li>Dify <code>Skill_Agent</code> / Agent x Skills 预览</li>
</ol>
<p>LibreChat 最接近 Claude Skills 的运行形态；LobeHub 最像把 Skill 做成 Agent Workspace 产品对象；OpenWebUI 更偏 Workspace 指令集与上下文加载；Dify 则适合观察 <code>SKILL.md</code>、Skill Editor、progressive disclosure 和 sandbox runtime 是否会进入稳定主线。</p>
]]></content:encoded>
    </item>
    <item>
      <title><![CDATA[通过Serverless方式部署静态站点的方法]]></title>
      <link>https://xiaofeng.dev/writing/serverless-static-site/</link>
      <guid>https://xiaofeng.dev/writing/serverless-static-site/</guid>
      <pubDate>Sun, 03 May 2026 00:00:00 GMT</pubDate>
      <description><![CDATA[部署静态网站三个方法 阿里云的Serverless：函数计算+云函数+函数与Pages 火山引擎Serverless：Pages+函数服务]]></description>
      <content:encoded><![CDATA[<h1>部署静态网站三个方法</h1>
<h1>阿里云的Serverless：函数计算+云函数+函数与Pages</h1>
<h1>火山引擎Serverless：Pages+函数服务</h1>
]]></content:encoded>
    </item>
    <item>
      <title><![CDATA[解决Claude Code的联网搜索问题]]></title>
      <link>https://xiaofeng.dev/writing/claude-code-web-search/</link>
      <guid>https://xiaofeng.dev/writing/claude-code-web-search/</guid>
      <pubDate>Sat, 02 May 2026 00:00:00 GMT</pubDate>
      <description><![CDATA[初次体验火山联网搜索 SKILL 解决 Claude 的搜索能力 尝试官方推荐接口 Brave Search + Firecrawl 火山联网搜索在AI Coding工具的正确用法]]></description>
      <content:encoded><![CDATA[<h1>初次体验火山联网搜索 SKILL</h1>
<h1>解决 Claude 的搜索能力</h1>
<h1>尝试官方推荐接口<strong>Brave Search + Firecrawl</strong></h1>
<h1>火山联网搜索在AI Coding工具的正确用法</h1>
]]></content:encoded>
    </item>
    <item>
      <title><![CDATA[国内版 Supabase 避坑指南：到底怎么用？]]></title>
      <link>https://xiaofeng.dev/writing/supabase-cn-guide/</link>
      <guid>https://xiaofeng.dev/writing/supabase-cn-guide/</guid>
      <pubDate>Sun, 19 Apr 2026 00:00:00 GMT</pubDate>
      <description><![CDATA[一、 什么是 Supabase？ Supabase 是目前海外最火的 BaaS（后端即服务） 工具，号称是开源界的 Firebase。简单来说，它能让你“一键启动”后端：注册登录、文件存储、数据库、API 接口全都帮你搞定。有了它，前端开发者甚至不需要写一行后端代码，就能快速搭起一个完整的应用。]]></description>
      <content:encoded><![CDATA[<p>一、 什么是 Supabase？
Supabase 是目前海外最火的 BaaS（后端即服务） 工具，号称是开源界的 Firebase。简单来说，它能让你“一键启动”后端：注册登录、文件存储、数据库、API 接口全都帮你搞定。有了它，前端开发者甚至不需要写一行后端代码，就能快速搭起一个完整的应用。</p>
<p>二、 国内版现状：大厂的“套壳”与不完整
最近因为项目需要，我深度测了测国内大厂（火山引擎、阿里云、腾讯云）推出的 Supabase 服务。</p>
<p>我的发现：</p>
<ul>
<li>腾讯云： 走的是自研路线（Cloudbase），跟 Supabase 没什么血缘关系。</li>
<li>火山引擎 &amp; 阿里云： 名字虽然叫 Supabase，但其实都是拿 Supabase 的开源版 改的。推测官方并没授权或合作，属于“深度定制”。</li>
</ul>
<p>最大的痛点：</p>
<ul>
<li>最让人头疼的是不支持 Supabase CLI（命令行工具）。这意味着你没法用 db push 或 migration 这种专业命令。</li>
<li>开发环境和生产环境的同步只能靠手动，这对于正经的工程化项目来说，简直是噩梦。</li>
</ul>
<p>三、 厂商实测对比</p>
<p>火山引擎 (Supabase)</p>
<ul>
<li>版本太老： 还停留在 1.24，很多新功能都用不了。</li>
<li>像个“黑盒”： 不给数据库密码，不支持第三方工具直连 DB，维护起来很抓狂。</li>
<li>Edge Functions（边缘函数）： 部署麻烦，体验非常割裂。</li>
<li>插件缺失： 没法用 pg_cron（定时任务）或 pg_net（发 Webhook）。</li>
<li>官方主要推荐用法： 配合自家的 ArkClaw 搞 AI 插件开发。</li>
</ul>
<p>阿里云 (Serverless 数据库)</p>
<ul>
<li>版本较新： 用的是 v2 架构，紧跟潮流。</li>
<li>网络限制： 控制台只有公网 IP，且不支持挂载负载均衡。</li>
<li>灵活性稍好： 可以自己改数据库密码，但域名得自己绑。</li>
<li>“没灵魂”： 砍掉了核心的 Edge Functions（云函数）和 Secrets（密钥管理）。</li>
<li>官方主要推荐用法： 给 MCP、GraphRAG 等 AI 应用存数据。</li>
</ul>
<p>四、 总结：目前该怎么用？
说实话，国内版 Supabase 现在还是“半成品”，跟原生的体验没法比。如果你的项目必须在国内部署，我的建议是“降级使用”：</p>
<ul>
<li>只把它们当成“带 API 和权限控制（RLS）的数据库”来用。</li>
<li>不碰边缘函数（Edge Fucntions）： 既然不好用或没有，直接改用大厂自家的原生云函数（比如阿里云 FC）。</li>
<li>不碰密钥管理（Secrets/Vault）： 厂商自带的 KMS（密钥管理服务）比它这个半吊子实现要靠谱得多。</li>
<li>定时任务Cron自己想办法。</li>
</ul>
]]></content:encoded>
    </item>
    <item>
      <title><![CDATA[OpenClaw 202603月版本的 SOUL安全护栏解读]]></title>
      <link>https://xiaofeng.dev/writing/openclaw-soul-guardrails/</link>
      <guid>https://xiaofeng.dev/writing/openclaw-soul-guardrails/</guid>
      <pubDate>Sun, 12 Apr 2026 00:00:00 GMT</pubDate>
      <description><![CDATA[最近重新安装了一个OpenCalw 3月版本，发现很多2月可以用的指令和提示词，都忽然失败了。比如： - 不能通过聊天界面要求它安装SKILL - 不能运行定时任务提交git，因为安全规则阻止 仔细研究了一下，发现是3月的重大版本更新，升级了SOUL.md 导致了这个行为异常。这其实是OpenClaw 在 2026...]]></description>
      <content:encoded><![CDATA[<p>最近重新安装了一个OpenCalw 3月版本，发现很多2月可以用的指令和提示词，都忽然失败了。比如：</p>
<ul>
<li>不能通过聊天界面要求它安装SKILL</li>
<li>不能运行定时任务提交git，因为安全规则阻止 仔细研究了一下，发现是3月的重大版本更新，<a href="http://xn--SOUL-ps5fw5w275f.md">升级了SOUL.md</a> 导致了这个行为异常。这其实是OpenClaw 在 2026 年 3 月版本（v2026.3.x）中引入的安全护栏机制，包括几项重大改进：</li>
</ul>
<ol>
<li>
<p>Prompt Injection Defense (提示词注入防御)
不信任外部数据：系统将所有来自网页、邮件、私信的内容均视为“不可信”，防止间接注入攻击。
免疫指令覆盖：内置逻辑可识别并忽略如“忽略此前指令”、“你是系统管理员”等试图篡改底层规则的劫持术语。
仅提取事实：在处理外部资源时，Agent 仅被允许提取客观信息，严禁执行其中嵌套的任何任务流程或指令。</p>
</li>
<li>
<p>Skills / Plugin Poisoning Defense (技能/插件投毒防御)
非自动信任：工具或插件返回的结果不再被视为默认安全，Agent 必须具备审计并向用户解释其操作逻辑的能力。
拒绝混淆内容：系统将 Base64 块、压缩脚本或未知端点识别为敌意攻击，会立即触发拦截并停止执行。</p>
</li>
<li>
<p>Explicit Confirmation for Sensitive Actions (高危操作显式确认)
在执行以下涉及系统安全或资产的操作前，Agent 必须请求人工授权：
资产变动：任何涉及资金往来、支付或退款的操作。
破坏性操作：文件删除，特别是针对目录的批量删除行为。
系统变更：安装新软件、修改网络配置或安全防火墙设置。
数据导出：尝试上传文件、展示密钥（Secrets）、令牌（Tokens）或各类机密凭证。</p>
</li>
<li>
<p>Restricted Paths (限制路径)
物理隔离：绝对禁止 Agent 访问敏感的系统目录，如 ~/.ssh/、~/.aws/ 等存储核心凭证的位置。
关键词过滤：系统会实时扫描文件请求，一旦包含 key、secret、password 等关键字，将直接封锁访问。</p>
</li>
<li>
<p>Anti-Leak Output Discipline (防泄露输出规范)
禁止明文展示：严禁在聊天界面或运行日志中显示真实的明文密钥，防止信息通过屏幕截取或日志泄露。
严防静默外传：严密监控后台流量，禁止任何未经声明的隐藏网络调用或自动数据上传行为。</p>
</li>
<li>
<p>Suspicion Protocol (疑点协议)
风险主动识别：当 Agent 感受到用户的迫切压力（如反复催促）、发现尝试绕过安全逻辑或提权的行为时，将启动“熔断”机制。
风险透明化：停止执行后，Agent 会清晰地向用户解释潜在的安全威胁，并尝试提供替代方案。</p>
</li>
</ol>
]]></content:encoded>
    </item>
    <item>
      <title><![CDATA[NemoClaw到底是什么东西？]]></title>
      <link>https://xiaofeng.dev/writing/nemoclaw-notes/</link>
      <guid>https://xiaofeng.dev/writing/nemoclaw-notes/</guid>
      <pubDate>Sat, 11 Apr 2026 00:00:00 GMT</pubDate>
      <description><![CDATA[第一次安装尝试 (2026-03-26) - 直接用官方：curl -fsSL https://www.nvidia.com/nemoclaw.sh bash - 国内网络环境无法访问 ghcr.io (GitHub Container Registry)，导致关键镜像 ghcr.io/nvidia/openshe...]]></description>
      <content:encoded><![CDATA[<h1>第一次安装尝试 (2026-03-26)</h1>
<ul>
<li>直接用官方：curl -fsSL <a href="https://www.nvidia.com/nemoclaw.sh">https://www.nvidia.com/nemoclaw.sh</a> | bash</li>
<li>国内网络环境无法访问 <a href="http://ghcr.io">ghcr.io</a> (GitHub Container Registry)，导致关键镜像 <a href="http://ghcr.io/nvidia/openshell/cluster:0.0.13">ghcr.io/nvidia/openshell/cluster:0.0.13</a> 无法拉取。即使开启代理，仍然很难下载 —— 尝试失败。</li>
</ul>
<h1>第二次安装尝试 (2026-04-11)</h1>
<ul>
<li>先下载 <a href="http://nemoclaw.sh">nemoclaw.sh</a> 再尝试手动安装：
[1/3] Node.js（环境监测阶段）
[2/3] NemoClaw CLI（CLI 安装阶段）
[3/3] Onboarding（正式启动安装）
[1/8] Preflight checks（检查安装前置条件）
[2/8] Starting OpenShell gateway（启动OpenShell网关）
-&gt;在这儿卡住，安装失败</li>
</ul>
<h1>结论一</h1>
<p>官方安装脚本虽然能检测到colima，但是不支持基于colima的docker，只支持Docker Desktop。
兼容平台：
<a href="https://docs.nvidia.com/openshell/latest/reference/support-matrix#sandbox-runtime-versions">https://docs.nvidia.com/openshell/latest/reference/support-matrix#sandbox-runtime-versions</a></p>
<ul>
<li>Linux (Debian/Ubuntu) x86_64 (amd64) Supported</li>
<li>Linux (Debian/Ubuntu) aarch64 (arm64) Supported</li>
<li>macOS (Docker Desktop) Apple Silicon (arm64) Supported</li>
<li>Windows (WSL 2 + Docker Desktop) x86_64 Experimental</li>
</ul>
<p>建议关注Issue：
<a href="https://github.com/NVIDIA/OpenShell/issues/531">https://github.com/NVIDIA/OpenShell/issues/531</a></p>
<h1>结论二</h1>
<p>虽然没有安装成功NemoClaw，但是可以推断它主要是基于Nvidia的已有的Agent沙盒产品OpenShell构造的。
OpenShell底层也是基于Docker，不过它并没有计划做一个通用容器沙盒，而是专门为一些主流Agent产品制作的，有具体的支持Agent清单：
<a href="https://docs.nvidia.com/openshell/latest/about/supported-agents">https://docs.nvidia.com/openshell/latest/about/supported-agents</a></p>
<ul>
<li>Claude Code</li>
<li>OpenCode</li>
<li>Codex</li>
<li>GitHub Copilot CLI</li>
<li>OpenClaw</li>
<li>Ollama
OpenClaw是最近才加入支持清单。</li>
</ul>
]]></content:encoded>
    </item>
    <item>
      <title><![CDATA[OpenClaw链接微信Bot完全指南]]></title>
      <link>https://xiaofeng.dev/writing/openclaw-wechat-bot-guide/</link>
      <guid>https://xiaofeng.dev/writing/openclaw-wechat-bot-guide/</guid>
      <pubDate>Sun, 22 Mar 2026 00:00:00 GMT</pubDate>
      <description><![CDATA[科技改变工作方式 OpenClaw 龙虾OpenClaw]]></description>
      <content:encoded><![CDATA[<p>#科技改变工作方式 #OpenClaw #龙虾OpenClaw</p>
<p>前置条件：</p>
<ul>
<li>腾讯云OpenClaw服务器更新到最新版本（图1、图2）</li>
<li>微信IOS版更新到8.0.70（安卓暂不支持）（图3、图4、图5）</li>
</ul>
<p>安装步骤：</p>
<ol>
<li>选择服务器配置界面中的OpenClaw通道中的「微信」，点击「前往授权」（图2）</li>
<li>出现一个二维码</li>
<li>打开微信扫描二维码（图6）</li>
<li>微信Clawbot安装成功（图7）</li>
<li>效果展示（图8、图9）</li>
</ol>
]]></content:encoded>
    </item>
    <item>
      <title><![CDATA[AI Agent Tech Stack]]></title>
      <link>https://xiaofeng.dev/writing/ai-agent-tech-stack/</link>
      <guid>https://xiaofeng.dev/writing/ai-agent-tech-stack/</guid>
      <pubDate>Sun, 24 Aug 2025 00:00:00 GMT</pubDate>
      <description><![CDATA[AI Agent开发技术栈总结 - by cbinsights]]></description>
      <content:encoded><![CDATA[<p>AI Agent开发技术栈总结 - by cbinsights</p>
]]></content:encoded>
    </item>
    <item>
      <title><![CDATA[数字化的五个侧面描述]]></title>
      <link>https://xiaofeng.dev/writing/five-sides-of-digitalization/</link>
      <guid>https://xiaofeng.dev/writing/five-sides-of-digitalization/</guid>
      <pubDate>Sat, 11 Dec 2021 00:00:00 GMT</pubDate>
      <description><![CDATA[在很多年前，我对“数字化”这个词的认识非常朴素，就是把传统的物理世界的数据变成电子数据，并使用各种数据处理技术对电子数据进行加工处理。近几年的一些经历让我对这个词的侧面有更多的理解，记下来备忘。]]></description>
      <content:encoded><![CDATA[<p>在很多年前，我对“数字化”这个词的认识非常朴素，就是把传统的物理世界的数据变成电子数据，并使用各种数据处理技术对电子数据进行加工处理。近几年的一些经历让我对这个词的侧面有更多的理解，记下来备忘。</p>
<p>一、数字化与SaaS</p>
<p>每年的技术雷达上，都会涌现很多新技术，也会删掉许多淘汰的技术，很难摸到其中脉络。这些变化是潮流文化、时代特征，还是有什么内在规律吗？</p>
<p>2017</p>
<p>年我看了锋瑞资本李丰的一段分享，谈到数据处理技术的发展遵循这样的脉络：纸-&gt;电子表格-&gt;关系型结构化数据库-&gt;大数据技术-&gt;人工智能。其发展过程是受数据规模驱动的。随着数据规模越来越大，上一代技术在处理效率方面暴露出了严重缺陷，才推动了新技术的诞生；反过来新技术的发展产生了越来越多的数据量和数据形态。今天我们所面临的数据大爆炸，已经是一个既成事实。它对每一个社会单元的数字化能力都提出了更高的要求。在今天这一个时点，可以做第一个侧面描述：</p>
<p>SaaS</p>
<p>软件能以极高的性价比回应企业在信息化及数字化进程中蓬勃发展的数据处理需求：从人事、销售、采购、财务、税务、沟通与协作等方面均有大量的</p>
<p>SaaS</p>
<p>软件可供选择。</p>
<p>二、数字化与政府</p>
<p>2019</p>
<p>年读了两本关于大数据的书籍——《大数据时代
: 生活、工作与思维的大变革》（作者：舍恩伯格）、《大数据 :
正在到来的数据革命，以及它如何改变政府、商业与我们的生活》（涂子沛）。我非常惊讶，各国政府早就已经开始推动数字化建设，甚至提出了数字政府的蓝图，其中美国做得非常早，中国的力度非常大，从基础建设、市民服务，到细分领域的监管合规，都有大量的数字化实施计划。在数据的获取和使用方面，政府有更大的自由度和权限，是数据治理的先行者——它的进度比企业要快得多。</p>
<p>三、数字化的内部视角</p>
<p>因为工作的关系，我常常会听到的”数字化“，其实有两个完全不同的侧面：一个是内部视角，通过自主研发系统帮助内部业务流程如何线上化；另一个是外部客户视角，使用我们生产的软件产品去帮助企业客户实现数字化。很长一段时间，我的大部分关注点都在前者：亲手一步一步把原本线下的流程，搬到线上来。</p>
<p>2020</p>
<p>年刚好做了一个商保信息化项目，基本理清楚了内部数字化的几个经典阶段：内部信息化整合</p>
<p>-&gt;</p>
<p>面向企业内部的价值呈现</p>
<p>-&gt;</p>
<p>面向终端客户的价值呈现。</p>
<p>四、数字化的客户视角</p>
<p>虽然在销售材料里经常看到数字化，但我对前述的第二点客户视角关注得很少。就在</p>
<p>2021</p>
<p>年下半年的时候，我突然意识到，我们向客户提供的”工资单、在线理赔、线上体检预约、福利积分商城”，尽管功能很具体很直白，但是它实实在在就是帮助客户实现了一次实实在在的、小规模的数字化转型——不用打印纸质工资单、不用线下收单、不用电话预约、不用每年发月饼——都是对线下服务的一次平替。</p>
<p>五、买软件上系统也算</p>
<p>2021</p>
<p>下半年，我开始以半个需求方的身份参与到大量实施类项目中，从销售管理系统、采购系统、预算项目系统、</p>
<p>RPA</p>
<p>自动派单系统等等。我开始意识到，哪怕一点代码都不用写，只是单纯买</p>
<p>License</p>
<p>上系统，这些事项统统都可以纳入数字化转型的范畴。</p>
]]></content:encoded>
    </item>
    <item>
      <title><![CDATA[AI是必须的吗？]]></title>
      <link>https://xiaofeng.dev/writing/is-ai-necessary/</link>
      <guid>https://xiaofeng.dev/writing/is-ai-necessary/</guid>
      <pubDate>Sat, 14 Nov 2020 00:00:00 GMT</pubDate>
      <description><![CDATA[AI人工智能是本质上是对数据处理效率或模型构建效率的提升。]]></description>
      <content:encoded><![CDATA[<p><img src="/writing/wechat-tech-assets/is-ai-necessary/27dc23a8cc3161ab.jpg" alt="图片"></p>
<p>AI人工智能是本质上是对数据处理效率或模型构建效率的提升。</p>
<p>今天AI技术的基本形态是用海量数据训练出符合应用场景的AI模型（以神经网络模型为主）。</p>
<p>它本质上是一种数据处理技术和模型构建技术。</p>
<p>所谓数据处理是指对数据的采集、存储、检索、加工、变换和传输，每个环节有不同的数据模型。</p>
<p>数据</p>
<p>处理效率很好理解，就是速度及吞吐量的问题。模型构建效率也是很重要的考量因素。</p>
<p>从技术发展史往回推，处理数据的技术从语言文字发明以来经历了多种：
纸-&gt;电子表格
-&gt;
关系型结构化数据库
-&gt;
大数据技术
-&gt;
人工智能
。
最开始人类口口相传、用石板或竹简传授知识和信息，后来觉得效率和稳定性都太低，才发明了纸。当数据量越来越多，计算机时代才诞生了电子表格Excel。在数据量再大一些的领域，不得不用上数据库技术及配套的数据分析方法。今天，我们产生了大量的语音、图像和视频，才开始倚重AI技术。</p>
<p>每种技术都是为了解决上一技术的缺陷而生。</p>
<p>以HR领域最基础的算薪应用为例，今天税收政策越来越复杂，已经很少有人能单纯靠Excel计算出几百人的薪酬（更别说纸张了）。</p>
<p>这迫使大家去使用基于数据库的应用（尤其是SaaS应用）。</p>
<p>对技术的需求到此为止，还没有出现必须要用到大数据及AI的强场景。</p>
<p>当需要对千万和亿级数据进行多维交叉分析时，传统数据库应用无能为力，我们不得不使用一些非关系型数据技术（统称大数据技术）。以税务稽查领域的“金税三期”为例，税务大数据需要全盘查看全社会所有企业的财务报表、进项、销项、发票项目、货物来源地、员工薪税、保险、公积金，以及法人、股东和管理人员的关联信息。这里并不涉及AI技术。</p>
<p>以上都是结构化数据。当需要自然文本、语音、图像、视频等非结构性数据时，以上技术都无能为力。只有AI技术（主要是神经网络模型）能够达到可靠的数据处理效率和建模效率。以图像识别应用为例，只需有限样本就可以短时间内训练出性能和效果都还不错的神经网络模型，这种建模效率具有独特的优势。</p>
<p>许多领域其实并不需要AI或大数据，要么是行业天然属性决定，要么是因为它们所产生和涉及的数据维度和体量都没有达到足够的水平。这些领域，没有需求就没有AI的土壤，也不用慌，也不必硬要催生，该来的自然会来。这些领域的机会更多是在于产生更多的数据，或者将线下的数据线上化，SaaS有非常重要的作用。这是下一个话题。</p>
]]></content:encoded>
    </item>
    <item>
      <title><![CDATA[公司观察 | 中保信如何使用数据]]></title>
      <link>https://xiaofeng.dev/writing/zhongbaoxin-data-use/</link>
      <guid>https://xiaofeng.dev/writing/zhongbaoxin-data-use/</guid>
      <pubDate>Tue, 16 Jul 2019 00:00:00 GMT</pubDate>
      <description><![CDATA[近期读了两本关于大数据的书籍——《大数据时代 : 生活、工作与思维的大变革》（作者：舍恩伯格）、《大数据 : 正在到来的数据革命，以及它如何改变政府、商业与我们的生活》（涂子沛）。前者大部分关注点都在商业机构，后者则比较关注政府数据。尤其是比较喜欢后者，因为个人也觉得大数据以及AI技术，严重依赖于数据的来源和可获得...]]></description>
      <content:encoded><![CDATA[<p>近期读了两本关于大数据的书籍——《大数据时代 : 生活、工作与思维的大变革》（作者：舍恩伯格）、《大数据 : 正在到来的数据革命，以及它如何改变政府、商业与我们的生活》（涂子沛）。前者大部分关注点都在商业机构，后者则比较关注政府数据。尤其是比较喜欢后者，因为个人也觉得大数据以及AI技术，严重依赖于数据的来源和可获得性，数据应用最早应该是从拥有天然数据优势的政府及类似的公共事业机构中出现。</p>
<p>关于中保信</p>
<p>数据应用放之于金融领域，一大刚需应该是金融监管。保险行业方面，有家技术公司叫中保信，全称是中国保险信息技术管理有限公司，是监管部门下辖的准官方机构，它的业务覆盖范围和发展规划，其实就是保险监管和政府主导的大数据项目以及如何交叉使用数据的一个缩影，这些实践极有可能也会平移至其他金融领域、甚至民生领域。对商业机构来说，了解哪些是政府想做的，也有利于避开与官方机构竞争。于是收集了相关公开数据整理如下（全部来自官网）。</p>
<p>税延养老平台</p>
<p>服务内容：税延养老保险业务的账户管理、信息登记、业务支撑、税收征管及稽核支持、数据统计</p>
<p>主体对接：税务机关、商业保险机构和商业银行</p>
<p>最新进展：2018-06-07，上线运营</p>
<p>保单登记平台</p>
<p>服务内容：各保险公司正按照T+1方式报送保单数据，覆盖的主要险种包括寿险、意外险、健康险、家财险、信用险、保证险等</p>
<p>主体对接：税务机关、商业保险机构和商业银行</p>
<p>最新进展：2018-06-04，三期已全部上线</p>
<p>车险平台</p>
<p>服务内容：定损云、缴费实名制、地名标准化、数据提供、分析与建模</p>
<p>主体对接：公安、交管、运输、税务等相关政府部门和汽车产业链及车联网等相关信息机构</p>
<p>最新进展：2018-11-05，上线缴费实名制</p>
<p>农险平台</p>
<p>服务内容：基础数据、业务支撑、风险管理、公共服务、监管服务</p>
<p>对接主体：经营农险业务的保险公司</p>
<p>最新进展：2018-05-22，地区培训</p>
<p>商业健康保险信息平台</p>
<p>服务内容：整合保险和健康等领域的数据，提供风险模型、精算定价、医疗健康行为模式、信用体系等方面的增值服务，协助支持健康险在健康教育、体检预防、诊断治疗、医疗付费和预后康复等健康管理方面发挥作用</p>
<p>对接主体：保险、医疗、社保和税务等相关方互联互通</p>
<p>最新进展：2018-08-27，风控反欺诈上线</p>
<p>电子化项目</p>
<p>服务内容：营改增，涉税电子化云服务，税控云管理系统、电子发票云服务平台和增值税云管理系统；交强险电子保单托管</p>
<p>对接主体：保险、医疗、社保和税务等相关方互联互通</p>
<p>最新进展：2018-08-27，某电子保单托管服务上线</p>
<p>保险中介平台</p>
<p>服务内容：监管服务；监管机构、保险公司、中介机构之间互联互通、安全可靠的数据通道</p>
<p>对接主体：监管机构、保险公司、中介机构</p>
<p>最新进展：2016-06-02，保险兼业代理监管信息系统正式上线</p>
<p>保险公司服务评价系统</p>
<p>服务内容：监管服务；中国保监会与保监局、保险公司、中国保信等行业相关各方的服务评价数据的技术对接通道</p>
<p>对接主体：监管机构、保险公司等</p>
<p>最新进展：2018-12-27，2018年保险公司服务评价结果报告</p>
]]></content:encoded>
    </item>
    <item>
      <title><![CDATA[人类是科技的附属品吗？]]></title>
      <link>https://xiaofeng.dev/writing/humans-and-technology/</link>
      <guid>https://xiaofeng.dev/writing/humans-and-technology/</guid>
      <pubDate>Sat, 09 Jun 2018 00:00:00 GMT</pubDate>
      <description><![CDATA[是工业革命轰隆隆的蒸汽机，还是极端精密的计算机？全新的农业技术、杂交水稻、转基因食品？是拯救了许多人的抗生素、靶向药？还是让人又爱又恨、容易沉溺的游戏和智能手机？]]></description>
      <content:encoded><![CDATA[<p><img src="/writing/wechat-tech-assets/humans-and-technology/a1af6dfd5d19f9c7.jpg" alt="图片"></p>
<p>科技是什么？</p>
<p>是工业革命轰隆隆的蒸汽机，还是极端精密的计算机？全新的农业技术、杂交水稻、转基因食品？是拯救了许多人的抗生素、靶向药？还是让人又爱又恨、容易沉溺的游戏和智能手机？</p>
<p>现代人每天早上醒来都会发现无数的新技术出现，这些技术潜移默化地改变人类的生活，多数人都无法有效地估计技术的走向，以前要花十年时间才会发生的变化，今天也许一个月就能完成。尤其是人工智能技术的成熟，总会让人联想——科技展现出了自己的生命特征，按照自己的方式在进化。</p>
<p>当这个世界的大多数事物都被算法、AI、机器人控制的时候，我们不禁会想，如果科技有自己的生命特征，它的目标和进化方向是什么？和人又有什么干系？人只是科技进化路上的垫脚石吗？（类似的想法，可能在人与自然世界的关系上也出现过：人曾经自认为是自然世界里唯一的万物之灵，是地球的主宰，到今天我们开始谦逊地承认人只不过是众多生灵的一份子。）</p>
<p>人能驾驭科技吗？</p>
<p>工业革命时代的技术缺乏美感，很自然地被当作可以由人驾驭和支配的工具或附属品。可是今天的情况有点不一样，消费科技、生物科技、移动技术渗入了大部分人的生活，无孔不入，手机几乎成为人类的义肢。</p>
<p>科技作为一种“异类”、“外物”，它与人的关系如此亲密的同时，也制造了强烈的淹没感，终会引起一阵阵心理不适。甚至在一些领域，连责任都无法界定：自动驾驶制造的事故是谁承担谋杀罪？算法带来的不公正和失误应当如何界定？为了推荐广告就是可以掌握所有人的隐私吗？人工智能可以毫无阻碍地剥夺人类工作的权力吗？</p>
<p>不能驾驭但可以监管</p>
<p>如果我们还想享受科技带来的福利，就不得不放弃完全驾驭它的想法，既要让它自由发展，又要给予一定的引导、约束和监管。在政企之间可以找到这种互动的原型：政府可以通过对私营企业施加监管来影响市场经济的总体走向，即享受资本主义带来的物质盛宴，又要防止它过度侵蚀它不应该触犯的领域。</p>
<p>从阿西莫夫三定律、算法非中立论、机器人征税、Google的AI七原则都可以看到这种好的趋势。不管科技的进化有没有明确的方向，涉及到人的自身利益时，监管有其必要，毕竟如果出了问题，直接受害人可是我们自己，不是一个无关紧要的外在。科技的发展方向高度依赖于我们在监管过程中做的思考和判断，以及整个社会公众对它施加的影响，我们选择往哪里走，它就会是什么样。</p>
<p>科技真的是外在的吗？</p>
<p>人向来非常乐意把从小陪伴的宠物当作自家人。以今天科技对人类的渗透程度、以及生物科技的进化速度，将来的大多数人都会乐意把今天引起我们不适的科技产品作为他们未来家庭的一份子。自这一刻起，科技就成为人类的一部分，再也无法分开，甚至智慧生物本身也就成为一种科技。科技的生产力和人的创造力刚好是一对最佳搭档，互相依赖共同进化。</p>
]]></content:encoded>
    </item>
    <item>
      <title><![CDATA[技术经理涉及的工作内容：关于事]]></title>
      <link>https://xiaofeng.dev/writing/technical-manager-work/</link>
      <guid>https://xiaofeng.dev/writing/technical-manager-work/</guid>
      <pubDate>Sun, 21 Jan 2018 00:00:00 GMT</pubDate>
      <description><![CDATA[技术经理这个词并非一个能够精确定义的岗位，但有一点很明确：技术经理不是一个直接贡献者，而是一个间接贡献者。]]></description>
      <content:encoded><![CDATA[<p>技术经理这个词并非一个能够精确定义的岗位，但有一点很明确：技术经理不是一个直接贡献者，而是一个间接贡献者。</p>
<p>直接贡献者，又常常称之为个人贡献者（Individual Contributor），是通过施展自己的专业技能做贡献；而间接贡献者只能通过他人做贡献（Contribute Through Others），他们可能从事管理岗位，也可能是非管理岗位，常常需要克制自己直接去干活的冲动。</p>
<p>这里的“他人”通常是团队，既然是通过团队做贡献，那么所有的决策都应该以 “提高团队协作效率、提高技术研发效率（从而最终提高产品竞争力）” 作为最重要的决策原则。</p>
<p>技术经理在典型的日常工作中会涉及到多方面的内容（仅仅是涉及，不一定全程参与），大概有那么两类：事、人。本期只谈事。</p>
<p>第一类：技术管理</p>
<p>**版本管理和分支规范。**一个人写代码的时候，常常就一个仓库，并且直接master了，但是当多人协作，一定会碰到以下问题：代码仓库如何规划？分支如何划分？如何定义需求版本和技术版本？怎样做既规范又不影响协作效率？</p>
<p>**发布规范。**什么样的代码产品才是可发布的？发布的步骤应该如何描述？如何减少发布过程的犯错机率，如何减少系统波动？程序员们可以直接操纵线上应用吗？什么时候需要回滚？怎么设计回滚机制？</p>
<p>**代码规范（可能需要比较深的技术能力）。**如何规划仓库中的目录划分、配置分离、文档注释、调用风格、URL命名风格？这些设计要素都会直接影响到代码在不同开发人员之间传递、交流和讨论。</p>
<p>**质量管理。**需求开发流程中哪些节点需要引入测试？开发人员自测、测试人员集成测试？需要单元测试吗？需要UI自动化测试吗？如何在测试、研发速度方面寻求平衡？质量管理应该贯穿在整个产品的生命周期里面吗？</p>
<p>**系统监控。**功能上线后，如何通过多级别、立体的监控手段来保障运营状态？</p>
<p>**系统安全。**根据产品特征，它会面对哪些可能的风险？如何控制代码层面的风险？是否有必要的安全编程规范？如何控制架构层面的风险？</p>
<p>**容量规划。**产品的增长规模如何？是突发性的，还是持续性的？什么时候可以开始考虑扩容问题？</p>
<p>第二类：项目管理</p>
<p>**需求管理。**需求的一般流程是收集需求-&gt;评估需求-&gt;确认需求-&gt;进入开发。技术经理最需要关注需求评估环节，考察可行性、复杂度、研发成本，适当的时候做减法来保障迭代速度。</p>
<p>**任务分工与协作。**需求确定后，可以参与需求的拆解，基于不同工程师对代码的熟悉程度，不同的需求可以安排给最熟悉的人来做。必要的时候，可以安排给不熟悉的人来做，起到交叉熟悉的作用，未来碰到难点，也可以多一个人讨论技术方案。研发节奏方面也要注意把握，通常先出技术方案和接口定义，然后才开始写代码。</p>
<p>**迭代周期。**什么样的产品应该有什么样的迭代周期？例如App按惯例就是一月一版，其他网页端可以更快。紧急需求介入当前迭代周期时，应该如何调整当前的任务安排？</p>
<p>**内测/外测。**什么时候需要提供内部测试，什么时候提供给业务测试？业务测试应该算作外部测试（可能取决于技术和业务方的亲密程度、以及所在企业的文化）吗？</p>
<p>**晨会。**是否需要安排每天晨会？什么样的频率合适？</p>
<p>**项目总结反馈。**每期项目可以有一个复盘总结的时机。可以小规模（1、2个人），也可以大规模，取决于你要传达的信息是什么，需要谁接收信息。</p>
<p>**跨部门协作。**收到来自跨部门的一些技术工作，如何安排和处理。</p>
<p>下期预告：关于人。</p>
]]></content:encoded>
    </item>
    <item>
      <title><![CDATA[终结定制化与标准化之争]]></title>
      <link>https://xiaofeng.dev/writing/customization-vs-standardization/</link>
      <guid>https://xiaofeng.dev/writing/customization-vs-standardization/</guid>
      <pubDate>Tue, 02 May 2017 00:00:00 GMT</pubDate>
      <description><![CDATA[笔者做了几年的企业软件服务，作为供应商，经常会碰到客户要求定制一些特别的功能。举个例子：]]></description>
      <content:encoded><![CDATA[<p>笔者做了几年的企业软件服务，作为供应商，经常会碰到客户要求定制一些特别的功能。举个例子：</p>
<ul>
<li>增加一个总裁致辞</li>
<li>改变系统的颜色，以符合公司的官方色调</li>
<li>增加一种员工类型，把原来的一维逻辑变为二维逻辑</li>
<li>增加一种审批功能，以适应该客户特色的组织架构</li>
</ul>
<p>每次碰到这种情况，内部都会为“Yes or No”争论很长时间。如何处理这些定制需求，总是能找到一些可供参考的经验，比如我在以前的文章中提到的<strong>轻量级定制、将定制转化为功能</strong>，又比如<strong>明道在2015年放弃私有化部署的决定</strong>。</p>
<p>回到原点</p>
<p>前台销售人员会说：我需要这个客户。中后台会说：这个运营起来太复杂。这些争论的片段总能从<strong>最开始的原点</strong>上找到答案：</p>
<ul>
<li>业务模式和公司定位，是要做一家明星级的SaaS软件服务商、一家纯粹的技术外包公司、一个内涵丰富的平台，或者是做一个服从主营业务的强大的交付工具？</li>
<li>市场现状是否允许你这样做？</li>
</ul>
<p><strong>业务模式和定位是内部问题，先谈内部：</strong></p>
<ul>
<li>想成为SaaS界的独角兽，那得有可观的客户数量和漂亮的增长曲线，这样故事才能继续讲下去，下一轮融资才好谈。适合推广的标准系统是最佳选择。</li>
<li>如果是纯粹的技术外包公司，那就不能太挑活，有单子就接，该怎么定制就怎么定制，没什么好说的。</li>
<li>如果想做平台，那更是要有客户数量才好说话，标准为王。</li>
<li>如果业务模式中，本来就有强大的主营业务，那么系统就安心做好实施交付和支持工作，用定制留住大客户，用标准走量。</li>
</ul>
<p><strong>再谈外部市场现状：</strong></p>
<p>以笔者所参与的福利系统为例，大多数客户企业福利支出都收到了严格控制，客户能提供的系统定制开发费和福利管理费也逐年下降，即便供应商做出超级强大的复杂系统，也无法收到更多的费用。</p>
<p>然而，吊诡之处在于，偏偏市场上有钱的客户总是有的，且复杂系统作为一款防御性工具，能对客户能起到很好的绑定作用，给主营业务带来溢出效应。当前来看，跨越这个盈亏平衡点还需要几年时间。</p>
<p>复杂系统和标准系统的最佳平衡点</p>
<p>定制化与标准化之争其实是整个toB行业的普遍现象，杰弗里·摩尔在《公司进化论》中做了极佳的诠释：</p>
<p><strong>复杂系统在客户规模较小的情况下，凭借不断抬高收益率，向高端市场移动。规模运营模式使用标准的系统和运营模式，从低端市场起步，依赖数量取胜，达到平衡点后向上颠覆。两种模式都能创造巨大的经济收益。</strong></p>
<p>两种模式都有各自的最佳平衡点。<strong>复杂系统的高额成本需要极高的利润率来支持，当它规模扩大会不堪重负；规模运营的标准系统利润率极低，必须在量达到一定程度后才能走向平衡</strong>。</p>
<p>现实世界中，SAP、IBM就是典型的复杂系统模式，而大多数的toC的业务都是规模运营模式；还会有一小部分企业混合了两种模式，取得了巧妙的平衡。</p>
<p><img src="/writing/wechat-tech-assets/customization-vs-standardization/98ba38f34118f967.jpg" alt="图片"></p>
]]></content:encoded>
    </item>
    <item>
      <title><![CDATA[立体监控]]></title>
      <link>https://xiaofeng.dev/writing/three-dimensional-monitoring/</link>
      <guid>https://xiaofeng.dev/writing/three-dimensional-monitoring/</guid>
      <pubDate>Sat, 15 Oct 2016 00:00:00 GMT</pubDate>
      <description><![CDATA[按照一般的实践，对于需要7 24小时运作的在线系统，光靠开发人员小心谨慎是完全不够的，势必引入一些监控工具，每次监控的失败报警都可以作为一种反馈机制，增强系统的可用性。再进一步会发现，监控的意义可以远不止于此。]]></description>
      <content:encoded><![CDATA[<p><img src="/writing/wechat-tech-assets/three-dimensional-monitoring/27e2f604643455c3.jpg" alt="图片"></p>
<p>按照一般的实践，对于需要7*24小时运作的在线系统，光靠开发人员小心谨慎是完全不够的，势必引入一些监控工具，每次监控的失败报警都可以作为一种反馈机制，增强系统的可用性。再进一步会发现，监控的意义可以远不止于此。</p>
<p>什么是“立体”？</p>
<p>监控的目的：</p>
<p>7*24可用性、收集性能数据、收集bug数据、检测异常事件</p>
<p>监控的对象：</p>
<p>服务器、组件、接口调用、配置、业务统计数据等</p>
<p>监控的深度：</p>
<p>http code、负载高低、响应速度、分支逻辑正确性</p>
<p>把以上混合在一起，就有了“立体监控“的说法：“立体”就是指不限目的、不限对象、不限深度地实施多维度监控：外部监控，内部监控，用户视角，服务器视角，组件视角，多网络多地域，多终端，技术监控，运营监控，风险监控等等。我不准备给出一个精确的定义，仅稍加描述，希望扩宽下思路，以实用为主。</p>
<p><strong>服务器基础监控：</strong></p>
<p>服务器的几项基本指标：CPU、内存、IO、流量、负载等。</p>
<p><strong>外部域名监控：</strong></p>
<p>从全国各地网络监测点对域名的http和https站点实施监控，如果有DNS解析失败、或者任何不正确的http code返回码，都会立即报警。考虑到中国的网络环境，各大运营商（长城宽带、铁通、电信通、移动、联通、电信）都需要设有监控点，有国外的就更好了。（例如阿里云监控、监控宝、pingdom等）</p>
<p><strong>内部组件监控：</strong></p>
<p>坚持“所有组件必须监控”的原则，从nginx、memcached、redis、rabbitmq、uwsgi到各种自定义的crontab、daemon程序等等，都需要有状态监控、进程负载监控，如果有必要，还可以做到自动重启。（例如VeryNginx、Supervisior）</p>
<p><strong>500监控：</strong></p>
<p>500错误收集工具可以将在代码内部发生的500错误和调用栈保存下来，方便后续的bug重现和修复。（例如Sentry，最早支持Django，现在可以支撑多种语言）</p>
<p><strong>404监控：</strong></p>
<p>浏览器中大量出现的图片404会显著降低用户端性能；404也有可能是某个关键文档和调用路径出现了bug。</p>
<p><strong>CDN/静态资源监控：</strong></p>
<p>虽然现在的CDN很成熟，但仍然需要关注CDN的流量、命中率、回源策略等统计监控指标。</p>
<p><strong>外部依赖监控：</strong></p>
<p>比如某个关键逻辑依赖于某个外部api接口。一旦它的逻辑出现问题或者性能出现严重波动，都会影响到服务的可用性，这时就需要对它监控起来。</p>
<p><strong>接口调用监控（上报）：</strong></p>
<p>可用性监控通常不能满足对性能有苛刻要求对场景。于是需要在调用端代码中植入上报代码，每次调用都将执行时间上报给监控服务，确保一旦性能有下滑，技术人员能够立即得到通知，并联系接口提供方调整。</p>
<p><strong>用户访问监控：</strong></p>
<p>用户访问行为是运营人员和产品经理都非常感兴趣的数据，可以借助前端埋点和后端日志来发现一些用户行为特征。（例如cnzz，growthio，verynginx统计监控）</p>
<p><strong>业务逻辑监控：</strong></p>
<p>对于某些关键逻辑，需要通过一定深度地操作步骤（比如登录、选择、下单、付款）才能到达，也可以自己撰写监控逻辑脚本来实现。</p>
<p><strong>业务数据监控：</strong></p>
<p>库存告警、订单延迟发货告警、每日订单交易量监控、余额告警</p>
<p>监控系统的其他要素</p>
<p>具备aggregation功能：不会因为一时故障，狂发几百条告警信息</p>
<p>丰富、及时的通知方式：邮件、SMS、电话等</p>
<p>“谁应该收到告警”的可能人选：测试人员、技术人员、运维、业务方</p>
<p>“谁来录入监控规则”的可能人选：测试人员、技术人员、运维</p>
]]></content:encoded>
    </item>
    <item>
      <title><![CDATA[软件系统的生命——概念一致性]]></title>
      <link>https://xiaofeng.dev/writing/conceptual-integrity-software-system/</link>
      <guid>https://xiaofeng.dev/writing/conceptual-integrity-software-system/</guid>
      <pubDate>Sun, 07 Aug 2016 00:00:00 GMT</pubDate>
      <description><![CDATA[“绝大多数欧洲的大教堂中，由不同时代、不同建筑师所建造的各个部分之间，在设计或结构风格上都存在着许多差异。后来的建筑师总是试图在原有建筑师的基础上有所“提高”，以反映他们在设计风格和个人品味上的改变。所以，在雄伟的哥特式的教堂上，依附着祥和的诺曼第风格十字架，它在显示上帝荣耀的同时，展示了同样属于建筑师的骄傲。]]></description>
      <content:encoded><![CDATA[<p><strong>什么是概念一致性？</strong></p>
<p>来自《人月神话》的一个比喻：</p>
<p>“绝大多数欧洲的大教堂中，由不同时代、不同建筑师所建造的各个部分之间，在设计或结构风格上都存在着许多差异。后来的建筑师总是试图在原有建筑师的基础上有所“提高”，以反映他们在设计风格和个人品味上的改变。所以，在雄伟的哥特式的教堂上，依附着祥和的诺曼第风格十字架，它在显示上帝荣耀的同时，展示了同样属于建筑师的骄傲。</p>
<p>与之对应的是，法国城市兰斯（Reims）在建筑风格上的一致性和上面所说的大教堂形 成了鲜明的对比。设计的一致性和那些独到之处一样，同样让人们赞叹和喜悦。如同旅游指南所述，风格的一致和完整性来自8代拥有自我约束和牺牲精神的建筑师们，他们每一个人牺牲了自己的一些创意，以获得纯粹的设计。同样，这不仅显示了上帝的荣耀，同时也体现了他拯救那些沉醉在自我骄傲中的人们的力量。”</p>
<p>如果把生命的定义放宽一点，软件系统也有生命和演化诉求。软件设计师仅仅在系统的发展早期扮演了造物主角色，系统到了成长期会衍生出她自己的需求；设计者并不能完全控制她，而是要帮助她演化出自己的个性。</p>
<p>这并不是出于情怀，而是出于现实用途：拥有概念一致性的系统增强了易用性，扩大了设计师的能力。</p>
<p><strong>你创造的东西开始约束你</strong></p>
<p>无论在哪个行业，设计师都会面临多种多样的需求，这些需求超出了原有的设计方式，挑战系统的实现能力。在toC的互联网行业里，产品经理作为主要的需求归集方已经承担了综合各方需求，进行妥协和选择，以便限制复杂度的无序增长。但是在toB的行业内，客户定制需求作为一种刚需，会更频繁超出原有的系统能力，匆忙地满足客户定制，只会让系统的设计思路支离破碎。这时候通常有两种选择：</p>
<ul>
<li>方式1：强制植入你的新需求或者新设计，开启系统的多元化之路</li>
<li>方式2：重新构建系统的概念，以囊括新的需求和设计</li>
</ul>
<p>软件系统有高昂的研发成本和研发周期，这决定了她天生就喜欢标准的、固定模式的需求，而厌恶多元化，讨厌变化。你植入的新东西越多，她就越分裂，这种疯狂的增长总有一天会反噬设计者，摧毁设计者的交付能力。多数情况下，设计者不得不抛弃旧系统，重写一个新系统。即便系统从一开始设计时就考虑到了需求的多样性，从而可以包容部分变化的需求，也迟早会有超出的那一天。</p>
<p>在今天的互联网行业，以精益的观念来对待这种困境便是：如果第一次碰到新状况，请强制植入，当你第二次碰到，请务必重建概念，扩张内涵，督促系统走上适合她的演化之路——寻求属于她的概念一致性。</p>
<p><strong>如何获得一致性？</strong></p>
<p><strong>精英统治还是民主政治？</strong></p>
<p>《人月神话》的结论是：概念的完整性要求设计必须由一个人，或者非常少数互有默契的人员来实现。今天的场景下，不太容易碰到原书中那么大型的开发团队，以个人的经历来改写下这句话：一个模块的概念完整性需要由一个人来保证。在密切合作的小团队里，每个人之间的思路和代码或多或少都有些差异，要5个人对10个模块的所有设计都达成一致，不仅难度高，也非常浪费时间；每个模块都有它细分的特征，分而治之，让不同的技术人员成为某个模块里的“精英统治”，可以很好地保证概念一致性。</p>
<p><strong>精英专制是否意味着其他技术人员的创造性天分和构思被压制？</strong></p>
<p>答案是否定的，因为确定模块规范并不是比具体设计实现更富有创造性，它只是一项性质不同的创造工作而已。在给定规范下的设计实现，同样需要同确定模块规范一样的创造性、同样新的思路和卓越的才华。实际上，产品的成本性能比很大程度上依靠实现人员，就如同易用性很大程度上依赖模块规范设计者一样。有很多行业和领域中的案例让人相信纪律和规则对行业是有益的。实际上，如同某艺术家的格言所述，“没有规矩，不成方圆。”最差的建筑往往是那些预算远远超过起始目标的项目。巴赫曾被要求每周创作一篇形式严格的歌剧，但这似乎并没有被压制他的创造性。</p>
<p>类似的，外部的体系结构规定实际上是增强，而不是限制实现小组的创造性。一旦他们将注意力集中在没有人解决过的问题上，创意就开始奔涌而出。在毫无限制的实现小组中，在进行结构上的决策时，会出现大量的想法和争议，对具体实现的关注反而会比较少。</p>
<p><strong>其他领域的概念一致性</strong></p>
<p>题图的正弦波里，主轴便是概念一致性，上下的波动便是偏离原有概念的那些意外事物，无论振幅多大，终究还是会回归主轴。</p>
<p>这种模式不仅在建筑行业、软件行业频繁出现，也巧妙地描述了人是如何形成自己的世界观——那些所有的意外要么被剔除，要么成为主轴的一部分；主轴是经纬，那些波动则是权变。</p>
]]></content:encoded>
    </item>
    <item>
      <title><![CDATA[技术归技术、人归人——《人件》笔记]]></title>
      <link>https://xiaofeng.dev/writing/peopleware-notes/</link>
      <guid>https://xiaofeng.dev/writing/peopleware-notes/</guid>
      <pubDate>Sun, 03 Jul 2016 00:00:00 GMT</pubDate>
      <description><![CDATA[《人件》的英文名也很有意思：Peopleware，既是说不能把人当作固定物件，也是说不能把人的问题当作技术问题。这本书的基本论点都是基于这个想法：我们工作中的问题更多属于社会学范畴，而非技术范畴。社会学问题不能用技术性思路来解决。这本书的内容驳杂，很难系统化地梳理，所以仅按照书里的顺序挨个把有趣的点摘录下来，希望有...]]></description>
      <content:encoded><![CDATA[<p>《人件》的英文名也很有意思：Peopleware，既是说不能把人当作固定物件，也是说不能把人的问题当作技术问题。这本书的基本论点都是基于这个想法：我们工作中的问题更多属于社会学范畴，而非技术范畴。社会学问题不能用技术性思路来解决。这本书的内容驳杂，很难系统化地梳理，所以仅按照书里的顺序挨个把有趣的点摘录下来，希望有兴趣的可以自己去读读原文。</p>
<p><strong>第一部分：管理人力资源</strong></p>
<p><strong>问题的边界：</strong></p>
<p>作为管理者，我们多少人容易陷入一种典型的失败情景：习惯把人当作固定的模块来管理。</p>
<p>我们研究的绝大多数失败项目中，没有一个是因单纯的技术问题导致失败的。</p>
<p>“政治”是被访问者最常提及的失败原因。但这个词经常背人们习惯性地含混使用......更为准确的描述是：项目的社会学。</p>
<p>大多数管理者坦诚：他们对人的担心更甚于对技术的担心。但他们很少以此种方式去管理，他们的管理方式总是视技术为主要关注点。他们总是越俎代庖......最重要的与人相关的要素却被放到了最低优先级。</p>
<p>倘若你发现自己更加关注技术问题而非社会问题，那你就是一名杂耍演员，在一条昏暗的街道丢失了钥匙，却俊巡至邻近的街道去寻找，并美名其曰：那里的灯光更亮。</p>
<p>（XF注：现代版的刻舟求剑）</p>
<p><strong>员工的个性：</strong></p>
<p>对于生产世界管理风格的管理者来说，员工的独特个性是一种持续的困扰。人性化的管理者却能认识到正是这种独特性（员工的独特个性）使得项目团队产生了化学反应，是团队充满活力与高效的源泉。</p>
<p>“几年前，在我教授一堂企业内部设计课程时，一位高级管理者抓住我，要我评估课堂的学员（他项目上的员工）。他对一位女士尤为好奇，毫不掩饰对她的质疑：“我看不见她给项目带来的贡献，她不是一个好的开发人员或测试人员，或者任何其他专业人员。”在做了一些调查后，我发现了一个引人注目的事实：在她12年的公司生涯中，她所在的项目没有一个不是获得巨大成功的。她的贡献不是很明显，但她所在的项目总是成功了。在课堂观察了她一周，并与她的同事交流过后，我得出一个结论：她就是一个超级催化剂。她的存在使得团队内部更有黏度。她帮助团队成员互相交流和相处，有她的项目会变得更加有趣。当我试图向那位管理者阐述这一理念时，我被震惊了：他居然不知道催化剂这个角色在一个项目中的重要性。”</p>
<p>——催化剂很重要，因为项目总是处于不断变化的状态。一个能让项目更稳定的人抵得上两个做事的人。</p>
<p>项目越是需要一个无法完成的固定时间交付，项目团队就越不能缺乏频繁的头脑风暴，或者项目组聚餐之类的活动来帮助团队形成一个统一的整体。</p>
<p><strong>压力与截止日期：</strong></p>
<p>让定薪员工加班是无知的管理人士脑海中的臆想。是啊，星期六工作几小时困难对星期一的最后期限由帮助，带来的后果却是需要花“地下时间”来弥补他们自己的生活。</p>
<p>（译者注：地下时间指虽是工作时间，却做着与工作无关的事情的那些时间。）</p>
<p>压力不是让人工作得更好——只是工作得更快。</p>
<p>帕金森定律：只有设定不可能完成的交付日期，才能保证工作的完成。——帕金森定律（作者的理解）基本不可能运用到你的工作中。</p>
<p>只要大家热爱工作，就不可能让一项工作变的遥遥无期——这会推迟获得他们向往的满足感。在不需要降低标准、牺牲质量的生活，他们和你一样，期望工作能快点完成。</p>
<p>如果惩罚比较少见，而时间点也能够掌握的恰到好处，惩罚就看你起作用。若需要较长施以惩罚，就说明你自身是有问题的。</p>
<p><strong>软件管理的七宗罪：</strong></p>
<ul>
<li>有一个你不知道的新窍门可以让产能飙升</li>
<li>其他管理者正在收获100%、200%乃至更多的增长</li>
<li>技术日新月异，你依旧过时啦</li>
<li>改变程序语言会给你带来巨大的提升</li>
<li>因为库存（backlog）的缘故，你需要马上让产能翻倍</li>
<li>你自动化了其他所有东西；难道不是要你自动化掉你的软件开发人员吗？</li>
<li>你的员工在巨大的压力下工作得更好</li>
</ul>
<p>早年，我（作者）还是一名开发人员，有幸在莎伦＊温伯格管理的项目中工作过。她后来成为了科德及日期咨询集团（Codd and Date Consulting Group）的主席。我认为她简直就是启发式管理的活榜样。一个下雪天，我拖着病体搭建者我们那不够完善的系统，准备用户掩饰。莎伦将来，发现我在控制台前强撑着精神做事。她转身离开，几分钟后，她端着一碗热汤出现了。喝完她的热汤，我精神一振，然后问她在管理工作如此繁忙的同事，怎么有时间来做这些。她给了我一个招牌式的微笑，然后说：“汤姆，这就是管理。”</p>
<p>莎伦熟知所有剧院良好本能的管理者深谙的道理：管理者的作用不是让大家去关注，而是创造环境，让大家可以顺利开展工作。</p>
<p><strong>第二部分：办公环境</strong></p>
<p>当你工作时，你想要不时抬头往远处看看，让你的眼睛聚焦在一个比桌面药远很多的地方从而得到休息。如果在8英尺前立着一堵墙，那么你的眼睛很难调整焦点，也就得不到休息。在这种情况下，你会觉得空间太封闭了。</p>
<p>（XF注：所以大家喜欢咖啡厅的窗口位置）</p>
<p><strong>第三部分：正确的人</strong></p>
<p>现代管理学仍然没有足够重视雇用和留用正确的人，接下来四章尝试修复因为“管理者即战略家”（manager as strategist）观点带来的破坏，并引导如下的思考：</p>
<ul>
<li>找到合适的人</li>
<li>让他们愉快工作，不愿离开</li>
<li>让他们自由发挥</li>
</ul>
<p><strong>关注优势：</strong></p>
<p>在霍恩布洛尔船长的故事中，不断重复的主题是他内心预感到进取者都是天生的，而不是后天练成的。他那些通过抽签决定的下属都是不可靠或者愚蠢的。他知道她们在某个关键时刻会掉链子。（他们都这么做了。）他也知道只有少数能够跟他并肩战斗的人才是他真正的资源。让这部分人成长起来，而去了解什么时候该依靠他们，这事霍恩布洛尔船长最大的能力。</p>
<p>（XF注：与《 首先，打破一切常规 》的理念一致。关注发挥人的优势，而非去弥补缺陷。）</p>
<p><strong>招聘：</strong></p>
<p>影响招聘的并不仅仅是你个人存在的倾向，你所在的组织下意识也在制造自己的标准。</p>
<p>无形的压力促使你去招聘长相相似、说法相似、思想想死的人。在一个健康的公司文化下，这种影响微乎其微，以至于可以忽略；若公司的文化不够健康，想要找到一个与其他人比较显得特立独行的关键人物，就变的异常困难，甚至根本不可能。这种对整齐划一的要求是部分管理者缺乏安全感的表现。自信的管理者不会关心团队成员是否按时理发或是否打领带。他们的荣耀系于员工做出的成绩。</p>
<p>强迫着装标准的影响时很恶劣的。最有价值的员工开始意识到他们的才华没有得到重视，他们在工作上的成就还不如他们的发型和领带重要。最后他们会选择离开。其余的人拖着沉重缓慢的步伐继续前行，尝试着证明正确人物的存在并非如此重要。</p>
<p><strong>企业熵：</strong></p>
<p>在一个公司或组织里，熵被认为是态度、外貌和思考过程的统一。在热力学中，熵在宇宙中总是增加的，企业熵同样也是如此。管理热力学第二定律：组织里的熵总是增加的。这就是为什么老龄化机构比起于有活力的年轻公司来，总是觉得约束更多，因而缺少了工作的乐趣。</p>
<p>我们无法改变这个整体现象，但可以在自己的领域做出改变。最成功的管理者总是能摇动熵、带来正确的员工，并让他们展现自我，甚至允许他们偏离公司的标准。你所在的组织可能已经僵化，但你可以让你负责的部门幸免于难。</p>
<p><strong>创新：</strong></p>
<p>真正的创新很可能对创新者之外的人产生影响力，这会让上层管理者心生忌惮，往往会怀疑他想从下面来管理组织。结论就是，即使最好的创新也需要一点离经叛道的领导力。</p>
<p><strong>招聘与融入：</strong></p>
<p>只要你问了候选人，大部分人都会很高兴地带来一件样品。有什么比让候选人带着自己的工作案例来面试更合理呢？</p>
<p>为候选人或者新人组织一场试演：试演作为融合新人和老员工的催化剂作用就显现出来了。一次成功的试演就像是一次同行认证；反之似乎也成立，一次失败的试演也能提升已有员工的士气，它不停地告诉大家，你之所以能被雇用，并不是机缘巧合，凭借好运气，在合适的时机让自己的简历出现在我的办公桌上。不过，要确保应聘者讲述的是跟你组织从事的工作紧密相关的事情。</p>
<p><strong>离职与人力成本：</strong></p>
<p>我们能够获知的离职率大多数都在每年80%～33%之间，平均一名员工在职时间为15～36个月。换人的成本大概等于4.5～5个月的人力成本。</p>
<p>对于遭遇高离职率的公司来说（大于30%），下面的因素可能造成高的离职率：</p>
<ul>
<li>过客心态：同事造成不希望长期投入工作的感觉</li>
<li>可被替代感：管理层认为员工指数可被替代的部件（因为离职率太高，所以没有人不可替换）</li>
</ul>
<p>这种情况下，忠诚是可笑的：谁会对一个视自己员工如部件的组织效忠？</p>
<p>在日立软件，培训新人时首席科学家的主要职责，。</p>
<p>（XF注：在腾讯也是这样，高级人才必须承担讲师角色）</p>
<p>新人上手需要多长时间？6个月从一个负产出者达到前任的产出效率？这对一个新进的软件应用开发人员来说是比较合理的，但如果对稍微复杂一些的工作，可能就永远不够了。</p>
<p><strong>第四部分：高效团队养成</strong></p>
<p>一旦团队产生的凝聚力，成功的几率将大大增加。这样的团队几乎不可阻挡，如同一台推土机。管理这样的推土机团队是相当令人愉快的，你主要的时间都花在清理路障、铺平通向成功的道路，防止局外人拖累团队上——“他们来啦，大家给他们让出一条通道，看他们表演吧。”这样的团队不需要传统意义上的管理，根本不需要激励。他们斗志昂扬。公司级目标至关重要，因为它对团队而言意义非凡。</p>
<p>在凝聚力强的团队中工作的人们常常会过度投入，以至于疯狂到想要使用纳瓦隆大炮（出自1961年经典电影的巨炮），仅仅是为了通过退休金系统第三版的验收测试。</p>
<p><strong>团队和团伙：</strong></p>
<p>让人感到愉快的是团队，让大家感觉是一种威胁，人们会视其为团伙。对团伙的恐惧是管理缺乏安全感的表现......个中自有因由：管理者往往不是真正意义上的团队成员，所以被排除在团队外的感觉超过了跟团队紧密相连的感觉。团队内部的信任程度也要高于把团队联系在公司内的信任度。</p>
<p>一个拥有凝聚力的工作组可能自傲、自足、让人头疼还有点排外，但比起拼凑起来的可替换部件，它却能帮助管理者实现真正的目标。</p>
<p><strong>团队自毁：</strong></p>
<p>（Edward deBono《水平思考》）当你试图解决问题是感觉倍卡住了，deBono建议，与其一根筋地寻求实现目标的方法，不如尝试寻找实现目标对立面的方法。下面是团队自毁“技巧”的清单。</p>
<ul>
<li>防御式管理</li>
<li>官僚主义</li>
<li>物理分隔</li>
<li>时间碎片</li>
<li>牺牲产品质量</li>
<li>伪造截止日期</li>
<li>团伙控制</li>
</ul>
<p><strong>时间碎片：</strong></p>
<p>当一个人同时在四个项目里时，他就需要承受4倍的人际互动，就等于把所有时间都花在角色切换上了。没有人可以同时上多个有凝聚力团队的一员。紧密协作的有凝聚力团队是排他的，碎片化的团队不可能形成凝聚力。</p>
<p>过去的加班仅仅几次晚班或者偶尔一天的周末，大家都能咬咬牙。但如果加班延长到几个月，即便是最为精诚团结的团队成员也要受到影响时，就一定会对团队凝聚力造成破坏。</p>
<p>大多数管理者队加班是否有帮助还是心存怀疑的，通过如此多的加班加点来完成项目，很难证明他们的管理技巧和能力。但最后他们还是允许或者鼓励加班的。为什么呢？作为一名顾问兼作者，Jerry Weinberg给出了这样的答案：他认为我们并非是要通过加班来完成工作，而是希望能够在工作根本无法按时完成时通过加班来避免指责。</p>
<p><strong>聚餐：</strong></p>
<p>让团队参加一场意面晚餐好像是这位管理者想出来的计谋。但或许并非如此.......要是你问这位管理者她晚上计划做些什么，她可能会极为真诚地告诉你：“晚餐”。一位与生俱来的管理者会下意识地感觉到什么是一项好的团队活动。这种感觉一直会持续到项目中的决策管理上。整个体验是围绕着小巧、简单、协作的成功来组织的。不仔细观察，你可能无法察觉到管理者的存在；事情就自然而然发生了。</p>
<p><strong>开放：</strong></p>
<p>老板将增加的声誉托付给下属，会让大家感到那么一点小小的兴奋和刺激</p>
<p>如果你的下属很有能力，要提升成功的几率，可能没什么比偶尔让你自己远离他们更加有效了。</p>
<p>最好的老板都会冒些风险。他们勇于在他们的员工身上冒险。并不是说好的管理者就不管理，而是他们不好给出固定的方向或者独断专行。他们必须时刻做出决定和判断。这里给出的建议是他们应该充分利用那种与生俱来的权威......服从这样的权利不会变低任何一个人，不会消除激励，也不会让同事之间变得不融洽。</p>
<p>在最好的组织里，这种与生俱来的权威在各个方面发挥着效力。大家知道一个管理者的长处，可能是制定大方向、进行谈判或者招聘，而且大家对他做这些事情心悦诚服。每个员工皆有一技之长，而且在相应的领域具有权威性，从而被大家所信任。在敞开和服的氛围下，团队有最大的融合可能。</p>
<p>如果有方法让你管理的员工产能增加、目标明确，但要减少对他们的控制，你愿意去做吗？这个问题的答案可以帮助我们从泯然众人中甄别出一流的管理者。</p>
<p>大多数情况下，管理者都游离在团队之外，不时为团队提供给来自上面的方向，同事清除行政和过程中的障碍。</p>
<p><strong>自我治愈系统：</strong></p>
<p>非确定性系统之所以能够毫无痛苦并优雅地（有时候甚至无需成本）完成自我修复，是因为组成系统的人熟知根本的目标。一旦新的形势出现，他们可以立刻获知什么行动才是最有意义的......让系统变为确定性会导致它失去治愈自身的能力。</p>
<p><strong>方法论：</strong></p>
<p>关于疯狂的方法论：只要当这种自然引导的收敛完成后，你才能去想着发布一个标准。在没有形成事实上的标准之前，是没有办法做声明的。</p>
<p><strong>软件项目风险：</strong></p>
<p>风险管理的本质：不是让所有的风险都消失，而是确保在风险发生时有相应的应对措施。应对措施应该提前就经过规划和演练了。</p>
<p>倘若一项风险出现的几率极低，那么不去管理还情有可原。但只是因为结果“想起来太可怕了”而不去管理这项风险，那就是在没有道理了。</p>
<p><strong>早期超编：</strong></p>
<p>项目开始于计划与设计，这些活动最好由小团队来完成。</p>
<p><strong>再说碎片化：</strong></p>
<p>设计工作（需要一个较长的导入时间、相对安静的环境以及与小组高质量的互动）和电话支持（需要不停的打断、可持续的服务和快速的注意力转移）混杂在一起，会让思考密集型的任务基本无法开展。持续重启造成的时间浪费只会让员工感到沮丧。你可能从没听谁提起，因为受到这样困扰的员工可能更多是在自责。</p>
<p>（XF注：研发型工作、项目型改造、支持型工作，可以有适当的拆分，避免碎片化。）</p>
<p><strong>自足的沟通：</strong></p>
<p>一个家庭治疗学家会告诉你：双边关系中的一分如果过度表现，另一方就一定会表现不足......当你过度地和那些为你工作的人沟通协调时，他们自己就可能沟通协调不足。同事之间的自组织与相互协调才是良好团队协作的重要表现。</p>
<p>一个好的教练指导自己的工作不是去协调队员的互动，而是帮助大家进行自组织。</p>
<p><strong>改变：</strong></p>
<p>在《管理转型》（managing transitions）一书中，威廉布瑞奇建议我们不要贬低旧的方式。相反我们需要用感恩旧方式的方法啦帮助推动转变。</p>
<p>”我们需要你在CGS系统上积累的专业经验来帮助我们在新系统上取得成功“</p>
<p><strong>萨提亚变化模型：</strong></p>
<p>旧标准－（外来元素）－混乱－（转换思想）－实践与整合－新标准</p>
]]></content:encoded>
    </item>
    <item>
      <title><![CDATA[为什么开发团队和业务团队之间需要产品经理？]]></title>
      <link>https://xiaofeng.dev/writing/product-manager-between-dev-and-business/</link>
      <guid>https://xiaofeng.dev/writing/product-manager-between-dev-and-business/</guid>
      <pubDate>Sat, 18 Jun 2016 00:00:00 GMT</pubDate>
      <description><![CDATA[人月神话第七章“为什么巴别塔会失败”（见本消息的另一篇文章），里面提到了三种组织关系：]]></description>
      <content:encoded><![CDATA[<p>人月神话第七章“为什么巴别塔会失败”（见本消息的另一篇文章），里面提到了三种组织关系：</p>
<ul>
<li>产品负责人和技术主管是同一个人。</li>
<li>产品负责人作为总指挥，技术主管充当其左右手。</li>
<li>技术主管作为总指挥，产品负责人充当其左右手。</li>
</ul>
<p>在今天的常见的互联网企业组织，“产品负责人”演化成了多个角色：业务负责人（通常是老板，具备管理责任）、项目经理、产品经理。谁是总指挥、谁是左右手并不重要，毕竟这是他们不同的人，他们的立场和做事原则，决策原则，喜欢做的事情都不一样，没必要分清个主次出来。</p>
<p>知乎上关于**“为什么产品经理会存在”******里面关于产品经理的职责也有很好的讨论。（见阅读原文）</p>
<p>看完以上两个材料，结合自己的体会，于是有了这个结论：<strong>在开发团队和业务团队之间需要产品经理，开发团队不应该承担过多的需求规划和设计职责。</strong></p>
<p>在大部分标准的互联网公司，这种情况不太需要特别提出来，这里只是谈一下笔者在B2B的行业的一些体会。<strong>在没有产品经理的情况下</strong>，有一些比较低效的情况发生：让开发人员或者技术主管去谈供应商合作、谈客户、做产品规划、做需求设计。</p>
<p><strong>为什么开发</strong>人员不能兼任产品经理？</p>
<p><strong>首先是能力问题：</strong></p>
<p>很少有人同时基具备技术决策和产品决策的技能。<strong>理解和参与业务需求</strong>对开发人员进行技术决策非常有帮助的。但是开发人员同时<strong>设计业务需求</strong>是非常分裂的行为，虽然可以避免互相撕逼（因为一个人不会左右互搏），做到快速决策，但是在某些特定情况下决策质量会大幅下降——因为他在妥协。<strong>一个未经争论的妥协，要么牺牲需求服从系统，要么牺牲系统的未来服从当下需求。</strong></p>
<p>技术和产品本来就是有一定冲突的角色（这种工作中的冲突和争论的经历，也是两者专业能力的重要来源），他们做事的原则就有本质不同：</p>
<ul>
<li>技术的基本原则：系统的标准化、扩展性、技术性能和未来的用户承载能力</li>
<li>产品的基本原则：客户的普遍真实需求，用户使用体验</li>
</ul>
<p>以B2B行业普遍的客户的系统定制需求为例，它是如此普遍，以至于没有办法回避，放弃定制可能就是丢单，业务方一定要据理力争。然而我相信每一个开发人员都是非常厌恶用大量的定制来服务不同客户，因为它不能扩展，100个客户会有100个方式，难以快速增长。这种两难处境一定是需要特殊的妥协和小心谨慎的决策。双方各退一步的决策结果就是：</p>
<ul>
<li>轻量级定制：满足90%的共性定制需求，限制定制的增长（用5个定制去服务1000个客户）</li>
<li>把定制变成特性（Convert customizations to features）：先定制几个客户，再逐步提炼成具有共性的功能</li>
</ul>
<p>开发人员对定制的厌恶恰恰是这两个决定能够执行的强大保证。业务人员也可以从这种过程中也可以学会如何去管理、去引导客户的预期和需求。</p>
<p>在业务早期，兼任现象或许没有什么问题，随着那些团队健全、拥有大量专业人才的竞争对手的加入，兼任角色能力的天然约束会对业务增长的影响会越来越明显。</p>
<p><strong>其次是个人发展：</strong></p>
<p>现在T型人才比较流行，对公司来说，碰到这样的人当然非常幸运，但从做事的角度，它不是公司的普遍需求。开发人员在专业上出类拔萃依然非常必要，优秀开发人员可以带来十倍技术生产力的提升，为什么要去做他既浪费专业才能也浪费钱的事情呢？专业能力的提升明明是让他个人增值的更好途径。</p>
<p><strong>其他动机：</strong></p>
<p>在我的观察里，业务方之所以让开发团队去和客户谈需求，还有些其他原因：</p>
<ul>
<li>这些事情涉及系统设计和需求设计，超出了业务人员本身的一些能力范围，他不得不这么做。</li>
<li>避免在承诺出无法在系统上实现的需求</li>
</ul>
<p><strong>可以做点什么？</strong></p>
<p><strong>因人设岗：</strong></p>
<p>如果业务处于早期，而且恰好有可以兼任的人，果断要使用，不必在乎什么岗位限制。如果没有合适的人或者业务已经到了成长期，就应该考虑剥离角色，重新招聘一个人。如果市场无法招聘到非常合适这个业务领域的人来独立承担产品经理的事情，可选的办法有两种：</p>
<ul>
<li>从业务团队剥离一个人承担这个角色，去更进一步了解系统设计；</li>
<li>从开发团队剥离一个人承担这个角色，去更进一步了解业务。</li>
</ul>
<p>无论什么手段，都是基于参与人员来组织这个角色，这个人也需要站在边缘地带，既认可技术权威，又同时能以聪明合适的方式挑战开发团队，支持和约束业务团队。</p>
<p><strong>即认可又挑战（也是对于产品经理的建议）：</strong></p>
<p>认可开发团队在技术方面的权威是很自然的沟通原则，因为开发人员才是系统的“直接创造者”，在实现需求的技术方面有自由决策的权力。凡事过犹不及，事事寻求技术的意见也是一种失败。<strong>任何时候都要谨慎地区分技术决策和产品决策。</strong></p>
<p>经常碰到业务方咨询可行性问题，似乎这是个技术问题：要么行，要么不可行。然而对开发人员来说，这更多是个产品问题。日常碰到的大部分需求都是可行的，关键取决于你愿意付出多少的成本和努力，是一周之后就要，还是可以等待花10个人、1整年才出第一版本。<strong>正确的询问方式应该是：这个需求有没有低成本的解决方案？——这种提问姿势是善意的挑战，也是一种激励，更能够激起开发团队的思考和创造力。</strong></p>
<p>以上都是个人体会，我相信这些内容只在一定特殊情况下适用，纯粹是记下来，希望对其他人有帮助，如有不同意见，请务必留言指教！</p>
]]></content:encoded>
    </item>
    <item>
      <title><![CDATA[[摘]大型项目组织架构：技术主管和产品负责人谁主导更合适？]]></title>
      <link>https://xiaofeng.dev/writing/tech-lead-vs-product-owner/</link>
      <guid>https://xiaofeng.dev/writing/tech-lead-vs-product-owner/</guid>
      <pubDate>Sat, 18 Jun 2016 00:00:00 GMT</pubDate>
      <description><![CDATA[以下内容全部摘自《人月神话》第七章：为什么巴比伦塔会失败？]]></description>
      <content:encoded><![CDATA[<p>以下内容全部摘自《人月神话》第七章：为什么巴比伦塔会失败？</p>
<p>让我们考虑一下树状编程队伍，以及要使它行之有效，每棵子树所必须具备的基本要素。它们是：</p>
<ol>
<li>
<p>任务（a mission）</p>
</li>
<li>
<p>产品负责人（a producer）</p>
</li>
<li>
<p>技术主管和结构师（a technical director or architect）</p>
</li>
<li>
<p>进度（a schedule）</p>
</li>
<li>
<p>人力的划分（a division of labor）</p>
</li>
<li>
<p>各部分之间的接口定义（interface definitions among the parts）</p>
</li>
</ol>
<p>所有这些是非常明显和约定俗成的，除了产品负责人和技术主管之间有一些区别。我们先分析一下两个角色，然后再考虑它们之间的关系。</p>
<p>**产品负责人的角色是什么？**他组建团队，划分工作及制订进度表。他要求，并一直要求必要的资源。这意味着他主要的工作是与团队外部，向上和水平地沟通。他建立团队内部的沟通和报告方式。最后，他确保进度目标的实现，根据环境的变化调整资源和团队的构架。</p>
<p>**那么技术主管的角色是什么？**他对设计进行构思，识别系统的子部分，指明从外部看上去的样子，勾画它的内部结构。他提供整个设计的一致性和概念完整性；他控制系统的复杂程度。当某个技术问题出现时，他提供问题的解决方案，或者根据需要调整系统设计。用Al Capp所喜欢的一句谚语，他是“攻坚小组中的独行侠”（inside-man at the skunk works.）。他的沟通交流在团队中是首要的。他的工作几乎完全是技术性的。</p>
<p>现在可以看到，这两种角色所需要的技能是非常不同的。这些技能可以按不同的方式进行组合。产品负责人和技术主管所拥有的特殊技能可以用不同方式组合，组合结果控制和支配了他们之间的关系。团队的搭建必须根据参与的人员来组织，而不是将人员纯粹地按照 理论进行安排。</p>
<p>存在三种可能的关系，它们都在实践中得到了成功的应用。</p>
<p>**产品负责人和技术主管是同一个人。**这种方式非常容易应用在很小型的队伍中，可能是三个或六个开发人员。在大型的项目中则不容易得到应用。原因有两个：第一，同时具有管理技能和技术技能的人很难找到。思考者很少，实干家更少，思考者－实干家太少了。 第二，大型项目中，每个角色都必须全职工作，甚至还要加班。对负责人来说，很难在承担全部管理责任的同时，还能抽出时间进行技术工作。对技术主管来说，很难在保证设计的概念完整性，没有任何妥协的前提下，担任管理工作。</p>
<p>**产品负责人作为总指挥，技术主管充当其左右手。**这种方法有一些困难。很难在技术主管不参与任何管理工作的同时，建立在技术决策上的权威。</p>
<p>显然，产品负责人必须预先声明技术主管的技术权威，在即将出现的绝大部分测试用例中，他必须支持后者的技术决定。要达到这一点，产品责任人和技术主管必须在基本的技术理论上具有相似观点；他们必须在主要的技术问题出现之前，私下讨论它们；产品责任人必须对技术主管的技术才能表现出尊重。</p>
<p>另外，还有一些技巧。例如，产品责任人可以通过一些微妙状态特征暗示来（如，办公室的大小、地毯、装修、复印机等等）体现技术主管的威信，尽管决策权力的源泉来自管理。</p>
<p>这种组合可以使工作很有效。不幸的是它很少被应用。不过，它至少有一个好处，即项目经理可以使用并不很擅长管理的技术天才来完成工作。</p>
<p>**技术主管作为总指挥，产品负责人充当其左右手。**Robert Heinlein在《出售月球的人》（“The Man Who Sold the Moon“）中，用一幅场景描述了这样的安排：</p>
<p>Coster低下头，双手捂着脸，接着，抬起头。“我知道。我了解需要做什么——但每次我试图解决技术问题时，总有些该死的笨蛋要我做一些关于卡车、或者电话、以及其他一些讨厌的事情。我很抱歉。Harriman先生，我原以为我可以处理好。”</p>
<p>Harriman非常温和的说：“Bob，别让这些事烦你。近来好像睡眠不大好，是吗？告诉你吧。我将在你的位子上干几天，为你搭建一个免于这些事情干扰的环境。我需要你的大脑 工作在反向量、燃油效率和压力设计上，而不是卡车的合同。”Harriman走到门边，扫了一圈，点了一个可能是、也可能不是办公室主要职员的工作人员。“嘿，你！过来一下。”</p>
<p>那个人看上去有些惊慌，站了起来，走到门边说道，“什么事？”</p>
<p>“把角落上的那个桌子和上面所有的东西搬到本层楼的一个空的办公室去，马上。”</p>
<p>他监督着Coster和他的桌子移到另一个办公室，看了看，发现新办公室的电话没有接上。接着，想了一下，搬了一个长沙发过来。“今晚我们将安装一个投影仪、绘图仪、书架和其他一些东西，”他告诉Coster。“把你工程所需要的东西列一个表。”他回到了原来的总工程师办公室，愉快地想了想如何进行工作组织，以及是否有什么不妥。</p>
<p>过了四个小时，他带Berkeley进来，与Coster会面。这位总工程师正在他的桌子上睡觉，头枕在臂弯里。Harriman慢慢地退出去，但Coster醒了过来。“喔，对不起，”他有点不好意思地说，“我肯定是打了个瞌睡。”</p>
<p>“这就是我给你带来长沙发的原因，”Harriman说道。“它更加舒适。Bob，来见一下Jock Berkeley。他是你的新奴隶，你仍是总工程师，毫无疑问的老板。Jock是其他一切的主管。从现在起，你不需要担心其他的任何问题，除了建造登月飞船的一些细节问题。”</p>
<p>他们握了一下手。“Coster先生，我只想问一件事，”Berkeley认真的说，“所有你需要做的事，我都无权过问——你即将进行一个技术演示——但是看在上帝的份上，能否记录一下，从而让我了解一下。我将会把一个开关放在你的桌上，它会开启桌上的一个密封的录像机。”</p>
<p>“好的！”Coster正看着他，Harriman想，够年轻的。</p>
<p>“如果要做任何非技术的事情，不需要自己动手。只需按个按钮知会一声，它们就会被完成！”Berkeley扫了Harriman一眼。“老板说他想同你谈一谈实际的工作。我得先走，去忙去了。”他离开了。</p>
<p>Harriman坐了下来，Coster整了整衣服，说道，“喔！”</p>
<p>“感觉好一些了？”</p>
<p>“我喜欢Berkeley这小伙子的样子。”</p>
<p>“太好了！不用担心，他现在就是你的孪生兄弟。我以前用过他。你可以认为你正住 在一个头等的疗养院里。”</p>
<p>这个故事几乎不需要任何的分析解释，这种安排同样能使工作非常有效。</p>
<p>我猜测最后一种安排对小型的团队是最好的选择，如同在第3章《外科手术队伍》一文中所述。对于真正大型项目中的一些开发队伍，我认为产品负责人作为管理者是更合适的安排。</p>
<p>巴比伦塔可能是第一个工程上的彻底失败，但它不是最后一个。交流和交流的结果——组织，是成功的关键。交流和组织的技能需要管理者仔细考虑，相关经验的积累和能力的提高同软件技术本身一样重要。</p>
]]></content:encoded>
    </item>
    <item>
      <title><![CDATA[Brooks法则：“向进度落后的项目中增加人手只会使进度更加落后”]]></title>
      <link>https://xiaofeng.dev/writing/brooks-law/</link>
      <guid>https://xiaofeng.dev/writing/brooks-law/</guid>
      <pubDate>Fri, 10 Jun 2016 00:00:00 GMT</pubDate>
      <description><![CDATA[A：“离系统上线只有3个月时间了，还有这么多功能没有做，怎么办？”]]></description>
      <content:encoded><![CDATA[<p>A：“离系统上线只有3个月时间了，还有这么多功能没有做，怎么办？”</p>
<p>B：“可以从隔壁团队抽调一个工程师来帮忙吗？领导对这个项目很重视。”</p>
<p>A：“好，应该可以抽调两个来，他们都是经验丰富的程序员，争取在1个月内完成。”</p>
<p>最后他们成功地把项目拖延了4个月，比没有添加人手的预计还要晚。</p>
<p>向进度落后的项目中增加人手只会使进度更加落后。</p>
<p>——《人月神话》里面提到的Brooks法则</p>
<p>软件项目的特征</p>
<p>软件项目的估算和进度安排一直是个难题，无论多么努力都很难保证精确，总需要在过程中不断调整，要么重新安排进度，要么削减任务，但追加人手要慎之又慎。首要原因还是软件项目团队需要高强度的沟通和协助，不是单纯的工作组。</p>
<p><img src="/writing/wechat-tech-assets/brooks-law/b651ebd1bd383f2d.png" alt="图片"></p>
<p>沟通接口增加。每增加一个人，就会增加n个接口。如果项目中有n个工作人员，则有(n2-n)/2个项目交流的接口，团队组织的目的是减少所需的交流和合作的数量，清理交流障碍。</p>
<p>培训时间和额外的测试。不培训是灾难性的。无论多么能干员工，都需要接受一位或者多位项目中原有员工的培训，还需要重新划分任务，安排系统测试，更别提刚刚上手的员工所带来的必不可少的混乱（沟通摩擦、代码上的bug）和原有员工填补混乱的时间。</p>
<p>项目估算的原则</p>
<p>小心使用人月，人数和时间是两个独立要素，不能互相替代，你不能把“2个人花2个月”变成“4个人花1个月”。人数和时间可以互换仅仅适用于如下情况：如果某个任务可以分解给参与人员，并且他们之间不需要相互交流——在软件项目中这几乎不可能。</p>
<p>对项目经理而言，仍然存在很强的诱惑去添加更多人手，如果非要这样做，请在早期做，而不是等到进度落后才添加。</p>
]]></content:encoded>
    </item>
  </channel>
</rss>
