<?xml version="1.0" encoding="UTF-8"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="zh-CN">
  <id>https://huangboming.com/</id>
  <title>数字漫游</title>
  <subtitle>数字漫游者的探索手记，记录在广袤的数字世界中漫无目的的发现、思考和技术实践</subtitle>
  <updated>2026-10-16T18:03:20+08:00</updated>
  <author>
    <name>Boming Huang</name>
    <uri>https://huangboming.com/about/</uri>
  </author>
  <link rel="self" type="application/atom+xml" href="https://huangboming.com/feed.xml" />
  <link rel="alternate" type="text/html" href="https://huangboming.com/" />
  <generator uri="https://jekyllrb.com/" version="4.4.1">Jekyll</generator>
  <rights>© 2026 Boming Huang</rights>
  <icon>https://huangboming.com/assets/img/favicons/favicon.ico</icon>
  <logo>https://huangboming.com/assets/img/favicons/favicon-96x96.png</logo>
  
    
    
    
    
  <entry>
    <title>很多日常对话，其实是在互相梳毛</title>
    <id>https://huangboming.com/posts/most-everyday-conversations-are-mutual-grooming/</id>
    <link rel="alternate" type="text/html" href="https://huangboming.com/posts/most-everyday-conversations-are-mutual-grooming/" />
    <published>2026-10-08T00:00:00+08:00</published>
    <updated>2026-10-08T00:00:00+08:00</updated>
    <author>
      <name>Boming Huang</name>
      <uri>https://huangboming.com/about/</uri>
    </author>
    <category term="随笔" />
    <summary type="text">寒暄看似没有传递实质信息，却承担着建立、维持社会纽带的作用。理解寒暄与严肃讨论的区别，可以避免用错交流方式。</summary>
    <content type="html" xml:base="https://huangboming.com/posts/most-everyday-conversations-are-mutual-grooming/">&lt;p&gt;最近学到一个好玩的概念：寒暄性交流（&lt;a href=&quot;https://en.wikipedia.org/wiki/Phatic_expression&quot;&gt;phatic communion&lt;/a&gt;）。&lt;/p&gt;

&lt;p&gt;人类学家马林诺夫斯基（Bronisław Malinowski）用它描述一类交流：说话的主要功能是建立、维持社会关系。&lt;sup id=&quot;fnref:1&quot;&gt;&lt;a href=&quot;https://huangboming.com/posts/most-everyday-conversations-are-mutual-grooming/#fn:1&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot; role=&quot;doc-noteref&quot;&gt;1&lt;/a&gt;&lt;/sup&gt;&lt;/p&gt;

&lt;p&gt;在特罗布里恩群岛开展田野调查时，他注意到，岛民们结束一天的工作后，常围坐篝火旁闲聊。虽然大家滔滔不绝，但这些对话大多没什么信息量。那这些对话有什么意义呢？&lt;/p&gt;

&lt;p&gt;不妨反过来想：如果两个人在丛林里相遇，或者一群人坐在黑夜的火堆旁，大家一言不发，会发生什么？在熟人之间，沉默可能只是尴尬。但面对不知底细的陌生人，沉默很容易滋生猜疑：我不知道你在想什么，你不知道我在想什么，你对我抱有敌意吗？你会攻击我吗？&lt;/p&gt;

&lt;p&gt;在这种环境下，有人开口说话，哪怕只是一句问候，也能缓和气氛。可以把它理解为一个安全信号：“我看到你了，我没有敌意。”&lt;/p&gt;

&lt;hr&gt;

&lt;p&gt;灵长类动物会通过互相梳毛清洁身体，也借此安抚彼此、维持关系。这种行为被称为社会性梳理（&lt;a href=&quot;https://en.wikipedia.org/wiki/Social_grooming&quot;&gt;social grooming&lt;/a&gt;）。从功能上看，我们许多日常闲聊也有些相似：话语本身未必重要，重要的是借此表达友好、确认关系。&lt;/p&gt;

&lt;p&gt;走在路上，碰到熟人，打个招呼，随便聊聊。你说一句“这鬼天气真热”，我回一句“可不是嘛，热得要命”。我们其实并不真在乎实际气温，我们只是借天气打个招呼。反过来，碰到熟人，却没有任何反应，视而不见，对方可能会怀疑“我们的关系是不是出了什么问题”。&lt;/p&gt;

&lt;p&gt;从这个角度看，语言也是一种建立社会联系的行动，而不仅仅是思考的载体。&lt;/p&gt;

&lt;p&gt;朋友之间聊聊最近碰到的破烂事儿，同事之间吐槽公司和老板……有时，对方也只是想找人说说话。听对方抱怨几句、表示理解，不急着分析谁对谁错。很多时候，这就够了。&lt;/p&gt;

&lt;hr&gt;

&lt;p&gt;对我而言，这个概念很有启发。看上去都是谈话，但寒暄和严肃讨论其实是两种不同的游戏：目标不同，规则不同，参与方式也不同。&lt;/p&gt;

&lt;p&gt;用严肃讨论去丈量寒暄，人会觉得寒暄浮于表面、没有深度，甚至浪费生命。又或者，把寒暄当成交换信息、探讨真理的场域，非得在寒暄中列事实、摆道理、给解决方案，最后很容易落得一个“不解风情”的名头。&lt;/p&gt;

&lt;hr&gt;

&lt;h2 id=&quot;脚注&quot;&gt;脚注&lt;/h2&gt;

&lt;div class=&quot;footnotes&quot; role=&quot;doc-endnotes&quot;&gt;
  &lt;ol&gt;
    &lt;li id=&quot;fn:1&quot;&gt;
      &lt;p&gt;Bronisław Malinowski，&lt;a href=&quot;https://mnytud.arts.unideb.hu/tananyag/szoclingv_alap/malinowski-the_problem_of_meaning_in_primitive_languages.pdf&quot;&gt;“The Problem of Meaning in Primitive Languages”&lt;/a&gt;，载于 &lt;em&gt;The Meaning of Meaning&lt;/em&gt;（1923），第 315 页。 &lt;a href=&quot;https://huangboming.com/posts/most-everyday-conversations-are-mutual-grooming/#fnref:1&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;↩︎&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
  &lt;/ol&gt;
&lt;/div&gt;
</content>
  </entry>
  
    
    
    
    
  <entry>
    <title>面向 token 工作</title>
    <id>https://huangboming.com/posts/token-oriented-work/</id>
    <link rel="alternate" type="text/html" href="https://huangboming.com/posts/token-oriented-work/" />
    <published>2026-09-28T00:00:00+08:00</published>
    <updated>2026-09-28T00:00:00+08:00</updated>
    <author>
      <name>Boming Huang</name>
      <uri>https://huangboming.com/about/</uri>
    </author>
    <category term="心得" />
    <summary type="text">AI agent 的用量限制带来额度焦虑，也在悄悄塑造我们的工作节奏。</summary>
    <content type="html" xml:base="https://huangboming.com/posts/token-oriented-work/">&lt;p&gt;年初时我开通了 Claude Max 5x。&lt;/p&gt;

&lt;p&gt;那段时间，我每天上班第一件事是打开 Claude Code，找找今天有什么能交给它做的。&lt;/p&gt;

&lt;p&gt;做完份内的事，我看到额度还有剩余，就让 agent 排查代码隐患，看看有哪些地方可以优化；同时自己也看看代码，有哪些不符合要求或者设计有问题。&lt;/p&gt;

&lt;p&gt;哪怕无事可干，我也会想“我这套开发工作流能不能优化”、“能不能写个新的 skill”、“&lt;code class=&quot;language-plaintext filepath highlighter-rouge&quot;&gt;CLAUDE.md&lt;/code&gt; 中有哪些可以优化的地方”……&lt;/p&gt;

&lt;p&gt;起初，我想用 agent 提高效率。但这个念头不知不觉变成了“还有那么多 token，不用完就亏了”。而当 token 真的用完之后，看着列表中自己生造出来的需求和任务，心里又开始发慌：额度用完了，还有这么多工作要做，这可怎么办呀……&lt;/p&gt;

&lt;p&gt;这样一天下来，工作确实推进了不少，但下班之后脑子嗡嗡作响，工作上的念头一直萦绕在脑海中，比自己写代码还疲惫。&lt;/p&gt;

&lt;p&gt;一段时间之后，我意识到我其实在面向 token 工作。消耗 token 从完成任务的手段变成安排工作的目标。&lt;/p&gt;

&lt;h2 id=&quot;额度焦虑&quot;&gt;额度焦虑&lt;/h2&gt;

&lt;p&gt;我最初在工作中引入 AI agent，本意是提高效率，节省时间，好让我享受片刻闲暇，或者把精力投入更重要的事情上。但在工作上大量使用 AI agent 之后，我发现模型厂商设置的用量限制给我带来了额度焦虑。&lt;/p&gt;

&lt;p&gt;开通会员订阅之后，我陷入一种稀缺心态，觉得自己既然花了钱，就该最大化利用订阅，榨干所有可用额度。如果没用完，我会觉得自己亏了。&lt;/p&gt;

&lt;p&gt;和 AI 协作时，我要确定目标，用文字清晰地向 agent 传达意图，偶尔在 agent 执行的过程中介入，最终还要花时间理解、评判它的输出，提供反馈……&lt;/p&gt;

&lt;p&gt;而且为了不浪费算力，再加上害怕错过（&lt;a href=&quot;https://en.wikipedia.org/wiki/Fear_of_missing_out&quot;&gt;fear of missing out&lt;/a&gt;），我生造了许多任务，堆满自己的时间表，让自己显得十分忙碌。&lt;/p&gt;

&lt;p&gt;最后我发现，榨干算力，其实也是在榨干自己的脑力和精力。&lt;/p&gt;

&lt;h2 id=&quot;被额度塑造的工作节奏&quot;&gt;被额度塑造的工作节奏&lt;/h2&gt;

&lt;p&gt;在工业时代，机器的运转时间决定工人的作息；而在 AI 时代，AI 的用量限制也在默默塑造我们的工作节奏。&lt;/p&gt;

&lt;p&gt;大部分厂商都有五小时限额和周限额。看上去是用量限制，但换个角度想，五小时限额决定了我这五小时只能借助模型推进这么多工作，周限额也是如此。用完额度之后，我会觉得“都用完额度了，我该好好休息了”。&lt;/p&gt;

&lt;p&gt;看似我们在役使 AI 替我们打工，但其实我们是在配合 AI 的节律活动。&lt;/p&gt;

&lt;h2 id=&quot;重新找回工作节奏&quot;&gt;重新找回工作节奏&lt;/h2&gt;

&lt;p&gt;在经历过年初的疯狂之后，我退订了 Claude Max 5x。最主要的原因是，我意识到我其实并不需要那么多额度，而且我也不想再让用量限制支配我的工作节奏甚至生活。&lt;/p&gt;

&lt;p&gt;盲目忙碌之后，我才意识到闲暇的可贵。&lt;/p&gt;

&lt;p&gt;我现在订阅两份 ChatGPT Plus，接入 &lt;a href=&quot;https://pi.dev&quot;&gt;Pi&lt;/a&gt; 使用。一份订阅不够，两份订阅刚好覆盖日常开发所需。我也不再盯着用量限制，根据额度来寻找任务。额度只是额度，用完就用完了，没用完也没关系。&lt;/p&gt;

&lt;p&gt;我的任务是产出有价值的工作，而不是耗尽手上的 token。&lt;/p&gt;
</content>
  </entry>
  
    
    
    
    
  <entry>
    <title>不再追求早睡</title>
    <id>https://huangboming.com/posts/sleep-on-time/</id>
    <link rel="alternate" type="text/html" href="https://huangboming.com/posts/sleep-on-time/" />
    <published>2026-09-24T00:00:00+08:00</published>
    <updated>2026-09-24T00:00:00+08:00</updated>
    <author>
      <name>Boming Huang</name>
      <uri>https://huangboming.com/about/</uri>
    </author>
    <category term="心得" />
    <summary type="text">“早睡”是一个容易引发内耗的模糊概念。放弃对“早睡”的执念后，我反而能做到“早睡早起”。</summary>
    <content type="html" xml:base="https://huangboming.com/posts/sleep-on-time/">&lt;p&gt;我们总说“早睡早起身体好”，心里也想早睡早起，但很多时候就是做不到，就是想多玩会电脑、看会手机。&lt;/p&gt;

&lt;p&gt;我尝试过很多次早睡，但都没有坚持下来。&lt;/p&gt;

&lt;p&gt;有一次我很困，十点半就睡了。第二天我会觉得“昨晚睡得真早，精神不错”。到当天晚上十点时，我会觉得“还早呢，要不再玩会”。结果就是玩过时间，变成十一点甚至十二点洗澡，睡得很晚。第三天早上又怪自己“昨晚怎么睡得那么晚”，又决定要早睡。到了周末，我又觉得“难得休息，多玩一会也没关系”，最后可能一两点才睡，有时甚至会熬通宵。&lt;/p&gt;

&lt;p&gt;后来我意识到，“早睡”不是好概念，因为早睡和晚睡都是相对判断，没有明确的边界。如果我对自己说“我今晚要早点睡”，实际上大脑并不知道今晚具体要几点睡。到了晚上，它就会根据情境临场判断。而临场判断并不稳定，会受当天状态、环境因素的影响。&lt;/p&gt;

&lt;p&gt;除此之外，早睡、晚睡隐含着一些道德因素：早睡意味着自律，值得赞扬；晚睡则意味着放纵，带有罪恶感。看上去很有道理，但它会引发内心的拉扯。&lt;/p&gt;

&lt;p&gt;心理学上有一个概念叫道德许可（&lt;a href=&quot;https://en.wikipedia.org/wiki/Self-licensing&quot;&gt;moral licensing&lt;/a&gt;），指一个人做了一件好事之后，会在潜意识里觉得自己积累了“道德资本”，之后会心安理得地纵容自己做一件坏事，而且不会感到内疚。&lt;/p&gt;

&lt;p&gt;“早睡”这个词会激发道德许可：因为我昨晚早睡了，所以我今晚晚点睡也合理吧。反过来，“晚睡”很容易引发自我的道德批评：我昨天没控制住自己，今晚一定要早睡。&lt;/p&gt;

&lt;p&gt;含糊的标准带来不稳定的临场判断，再加上道德评价，用“早睡”来描述作息会让人陷入一个怪圈：早睡 -&amp;gt; 感觉有余裕，可以多玩会 -&amp;gt; 晚睡 -&amp;gt; 自责，决定早睡。最后的结果是作息混
乱，内心在自我感觉良好和内疚之间打转。&lt;/p&gt;

&lt;hr&gt;

&lt;p&gt;相较之下，“按时睡觉”则是一个更好的概念。&lt;/p&gt;

&lt;p&gt;“按时睡觉”指的是固定熄灯和起床时间——晚上到点就熄灯，熄灯后不再看手机；早上到点起床，拉开窗帘，看看窗外，喝杯水。&lt;/p&gt;

&lt;p&gt;这并不意味着你要把睡眠塞到僵化的时间表中。每个人的身体状况不一样，身处的环境也不一样，作息自然不同。&lt;/p&gt;

&lt;p&gt;有的人是早鸟型，喜欢清晨的阳光，习惯十点睡，六点起；有的人是晚睡型，喜欢晚上的安静，习惯一点睡，十点起。&lt;/p&gt;

&lt;p&gt;除此之外，睡眠时间也受工作时间的影响。一个 996 的码农很难做到晚上十点睡，一个三班倒、频繁调换班次的工人也很难做到固定作息。&lt;/p&gt;

&lt;p&gt;可以试试通过实验找到身体觉得舒服的作息。我的做法是先确定一个相对稳定的起床时间，再根据自己的睡眠需求向前推算熄灯时间。执行一段时间，再根据身体状态调整。&lt;/p&gt;

&lt;p&gt;除此之外，“按时睡觉”也不意味着要求自己按时睡着。因为本质上，我可以决定什么时候去洗澡、上床、熄灯，也可以决定睡前不再看手机和电脑，但我无法决定自己闭上眼睛以后，究竟要过多久才能入睡。&lt;/p&gt;

&lt;p&gt;规则只能约束那些我们能够控制的事情。所以，我只用“是否按时熄灯”判断自己有没有执行规则。按时躺上床、熄灯，剩下的就交给身体。&lt;/p&gt;

&lt;p&gt;从生理角度看，按时睡觉是一种顺应生物钟的策略。身体真正需要的是足够和规律——足够的睡眠，加上尽量规律的睡眠和起床节奏，最好在周末也是如此。&lt;/p&gt;

&lt;p&gt;从心理角度看，这条规则是中性的，没有太多道德色彩。它只是一件到点就该去做的事情。按时睡觉很好，做到了也不需要奖励自己；偶尔没做到也没关系，不用太苛责自己，也不需要用第二天提前睡觉来补偿。第二天继续照原来的时间执行就好。&lt;/p&gt;

&lt;p&gt;例外总会出现，但它不应该成为常态，我只要保证大部分时间都能按时睡觉就好。&lt;/p&gt;

&lt;p&gt;我现在已经不太关心自己算不算“早睡”了。时间到了就上床、熄灯，仅此而已。&lt;/p&gt;
</content>
  </entry>
  
    
    
    
    
  <entry>
    <title>验证螺旋</title>
    <id>https://huangboming.com/posts/verification-spiral/</id>
    <link rel="alternate" type="text/html" href="https://huangboming.com/posts/verification-spiral/" />
    <published>2026-07-22T00:00:00+08:00</published>
    <updated>2026-07-22T17:58:22+08:00</updated>
    <author>
      <name>Boming Huang</name>
      <uri>https://huangboming.com/about/</uri>
    </author>
    <category term="心得" />
    <summary type="text">当 AI 几分钟就能生成上千行代码时，人类审查的精力却并未随之缩减。本文从“胡扯不对称原则”出发，探讨我们在面对海量 AI 产出时陷入的审查困境与失控感。</summary>
    <content type="html" xml:base="https://huangboming.com/posts/verification-spiral/">&lt;p&gt;互联网上存在一个布兰多里尼定律（&lt;a href=&quot;https://en.wikipedia.org/wiki/Brandolini%27s_law&quot;&gt;Brandolini’s law&lt;/a&gt;），或者叫胡扯不对称原则（the bullshit asymmetry principle），大意是，反驳胡说八道所需的精力，远大于制造胡说八道所需的精力。&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;The amount of energy needed to refute bullshit is an order of magnitude bigger than that needed to produce it.（反驳废话所需的能量，比产生废话所需的能量大一个数量级。）&lt;/p&gt;

  &lt;p&gt;– Alberto Brandolini&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;针对这个现象，中文圈有一个很精确的描述：“造谣一张嘴，辟谣跑断腿”。&lt;/p&gt;

&lt;p&gt;这个原则让我意识到，内容验证与内容生成所需要的精力是不一样的。而且我发现，AI 降低了内容生成的门槛以及时间成本。&lt;/p&gt;

&lt;h2 id=&quot;生成式-ai-的冲击&quot;&gt;生成式 AI 的冲击&lt;/h2&gt;

&lt;p&gt;生成式 AI（&lt;a href=&quot;https://en.wikipedia.org/wiki/Generative_artificial_intelligence&quot;&gt;generative AI&lt;/a&gt;）把内容生成变成了一种工具。人们只需要输入一段提示词，就可以生成文章、图片、播客、音乐、视频。&lt;/p&gt;

&lt;p&gt;在 AI Agent 出现之后，AI 可以理解目标、感知上下文、调用工具、在真实的环境中执行任务。这大大拓宽了内容的内涵：代码、UI 设计稿、报告讲稿、Flashcard、PPT……&lt;/p&gt;

&lt;p&gt;制造内容的门槛大幅下降，所需要的时间也显著缩短。在 AI Agent 帮助下，写作新手能在几分钟内写出一篇不错的文章，刚入职的程序员也能在几小时内完成包含大量变更的 PR。&lt;/p&gt;

&lt;p&gt;AI 能让人快速产出大量内容，但人依旧需要花大量时间与精力去理解和验证。&lt;/p&gt;

&lt;p&gt;以我所在的软件工程行业为例。&lt;/p&gt;

&lt;p&gt;在 Agent 的帮助下，对方可能花半天提交了一个 PR。这个 PR 包含上千行代码，变更涉及多个子系统，并且附上大量的测试，宣称自己已经完成某个功能。&lt;/p&gt;

&lt;p&gt;而你需要花几天才能理解这些变更，检查它们有没有漏洞、设计是否符合历史原则、代码是否遵守项目规范。&lt;/p&gt;

&lt;p&gt;当你给出建议后，对方只需把建议丢给 Agent，可能一小时就能改完。但这些修改可能把原有代码改得面目全非，你又要花好几天才能理解新变更……&lt;/p&gt;

&lt;h2 id=&quot;验证螺旋&quot;&gt;验证螺旋&lt;/h2&gt;

&lt;p&gt;有人可能会说，我用 AI 来帮我理解内容、验证内容不就行了？别人用 AI 生成了大量代码，提交了一个 PR，我直接用 AI 来帮我理解这些代码、或者直接让 AI review。这样做不是不行，但问题是：AI 的理解、AI 的 review 本身也是一种需要被验证的内容。&lt;/p&gt;

&lt;p&gt;为了验证上一个 AI 的输出，我们可能需要引入新的 AI，这就变成了一个无限套娃的游戏：AI 产出内容 -&amp;gt; 人无法确定这些内容对不对，用 AI 来验证 -&amp;gt; 人无法确定 AI 的验证对不对，用另一个 AI 来验证 -&amp;gt; ……&lt;/p&gt;

&lt;p&gt;到了最后，会出现两种情况：要么你亲自阅读内容，因为只有这样，你才能判断 AI 说的对不对；要么你把理解内容、验证内容托付给 AI，相信 AI 给出的结果。&lt;/p&gt;

&lt;p&gt;或许，这是一个信仰问题&lt;sup id=&quot;fnref:1&quot;&gt;&lt;a href=&quot;https://huangboming.com/posts/verification-spiral/#fn:1&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot; role=&quot;doc-noteref&quot;&gt;1&lt;/a&gt;&lt;/sup&gt;。&lt;/p&gt;

&lt;h2 id=&quot;两种选择&quot;&gt;两种选择&lt;/h2&gt;

&lt;p&gt;如果你选择亲自阅读内容，由于你的理解速度远远跟不上生成速度，你的大脑会被 AI 生产的内容淹没。如果完全相信 AI，你会失去对内容的真正理解和掌控感。&lt;/p&gt;

&lt;p&gt;还是以软件工程行业为例。&lt;/p&gt;

&lt;p&gt;如果你选择读代码、理解每个 PR 的变更，就会出现上面描述过的场景：别人只需要几小时就能提交包含大量变更的 PR，而你需要好几天才能理解这些变更为什么存在，是不是正确的。一个 PR 可能还好，经过几个 PR 之后，人的精力和耐心会被耗尽。&lt;/p&gt;

&lt;p&gt;行业内已经出现了一些案例。&lt;/p&gt;

&lt;p&gt;Turso 是一个开源的数据库。它有一个赏金计划，给每一个发现会导致数据损坏的漏洞的人支付 1000 美元。&lt;/p&gt;

&lt;p&gt;项目管理者在今年 5 月 12 日宣布关闭赏金计划，因为在 AI Agent 出现之后，出现了大量由 AI 生成的漏洞提交，每一个提交都声称自己找到了漏洞。这些提交让项目维护者感到精疲力尽，他们需要花大量时间来阅读、理解、审查这些提交，反复确认这是否是一个真正的漏洞。最终他们不得不放弃这个赏金计划。&lt;/p&gt;

&lt;p&gt;他们在&lt;a href=&quot;https://turso.tech/blog/the-wonders-of-ai&quot;&gt;博客&lt;/a&gt;中写道：&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;The main problem of course is that it costs the slopmaker perhaps a minute to generate their submission. But it costs us hours to read, understand, and engage with them. And they can be generated at a semi-infinite pace. It is possible to set up automated systems to gatekeep this, but with a non-negligible dollar value attached to it, the incentive is just too great for the AIs to just keep arguing, reopening the same PR, etc.（核心问题在于，垃圾内容制造者可能仅需要一分钟就能生成他们的提交，而我们却需要耗费数小时去阅读、理解并且处理它们。而且，他们生成这种垃圾内容的速度几乎是无穷无尽的。尽管我们可以建立自动化系统来拦截把关，但由于这牵涉到不可忽视的金钱利益（赏金），在巨大的诱惑下，AI 会无休止地进行争辩、反复重开同一个 PR 等操作。）&lt;/p&gt;

  &lt;p&gt;– Glauber Costa&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;如果把代码审查完全交给 AI，你就不知道这部分代码为什么要这么写，系统为什么要这么设计。即使测试跑通了，如果不去逐行阅读测试代码，你就无从得知这些测试测了什么、有没有覆盖到核心逻辑。甚至在很多时候，这些测试本身也是 AI 的产物。&lt;/p&gt;

&lt;p&gt;经过几个 PR 之后，项目会慢慢变成一个黑盒：没人知道系统内部代码如何运作，某个功能如何实现，会不会有 bug。最终，团队会失去对系统的掌控。&lt;/p&gt;

&lt;p&gt;系统正常运转时，一切安好；当出现 bug 时，没人知道该如何排查，只能寄希望于 AI；当需要新功能时，也没人知道该如何下手，只能寄希望于 AI。&lt;/p&gt;

&lt;p&gt;有一个词叫认知债（&lt;a href=&quot;https://simonwillison.net/2026/Feb/15/cognitive-debt/&quot;&gt;cognitive debt&lt;/a&gt;），还挺贴切的。&lt;/p&gt;

&lt;h2 id=&quot;一些个人感受&quot;&gt;一些个人感受&lt;/h2&gt;

&lt;p&gt;我个人更倾向于前者：我会仔细检查 AI 的输出，确保它的输出符合我的要求。如果不符合，我会亲自下场修改。&lt;/p&gt;

&lt;p&gt;我知道 AI 会产生幻觉，没有全局视野，会有上下文污染；我知道 AI 常常写出局部能工作但会影响全局架构的代码；我知道 AI 喜欢过度抽象，喜欢写没有必要的辅助函数，让代码变得难以理解。或许，还有身而为人的主体性吧。&lt;/p&gt;

&lt;p&gt;但这个选择让我感到深深的倦怠。&lt;/p&gt;

&lt;p&gt;我确实用 AI 完成比过去多得多的任务，但我感觉自己变成了 AI 的调度器，像 CPU 那样，不断地下达指令、分配任务、在不同的任务之间切换，开几个窗口同时跑不同的任务。AI 完成任务之后，我还要审查输出结果、纠错。&lt;/p&gt;

&lt;p&gt;在审查的过程中，自己指挥下的 Agent 还好，至少我知道为什么要这么改，有哪些改动是不必要的，而且我能控制变更的大小。&lt;/p&gt;

&lt;p&gt;但如果是审查别人提交的 PR，即使有 PR message，我也很难立刻理解为什么要这么改。而且，有一些 AI 喜欢在做新功能时“优化”旧代码，带来很多不必要的变更（点名批评 GPT）。只读 diff，我看到的是大量的测试（不知道在测什么）、没必要的辅助函数（明明库里有，但就是不复用）、以及意义不明的变更（不知道为什么要动这段旧代码）。&lt;/p&gt;

&lt;hr&gt;

&lt;h2 id=&quot;脚注&quot;&gt;脚注&lt;/h2&gt;

&lt;div class=&quot;footnotes&quot; role=&quot;doc-endnotes&quot;&gt;
  &lt;ol&gt;
    &lt;li id=&quot;fn:1&quot;&gt;
      &lt;p&gt;当你把“内容生成”替换成“执行任务”，这个问题就更有趣了：你多大程度上愿意相信 AI 的选择、判断，多大程度上愿意把任务全权交给 AI？万一，AI 做出你无法理解但其实是正确的选择呢？（比如，AlphaGo 在与李世石的对弈中下出的第 37 手，令许多职业棋手以及解说感到不可思议。而事后证明，这是神之一手。） &lt;a href=&quot;https://huangboming.com/posts/verification-spiral/#fnref:1&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;↩︎&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
  &lt;/ol&gt;
&lt;/div&gt;
</content>
  </entry>
  
    
    
    
    
  <entry>
    <title>厨房刀工入门</title>
    <id>https://huangboming.com/posts/basic-kitchen-knife-skills/</id>
    <link rel="alternate" type="text/html" href="https://huangboming.com/posts/basic-kitchen-knife-skills/" />
    <published>2026-07-20T00:00:00+08:00</published>
    <updated>2026-07-20T00:00:00+08:00</updated>
    <author>
      <name>Boming Huang</name>
      <uri>https://huangboming.com/about/</uri>
    </author>
    <category term="教程" />
    <summary type="text">从“扣”和“划”两个基本动作入门厨房刀工，并介绍安全握刀、常用切法与刀具保养方法。</summary>
    <content type="html" xml:base="https://huangboming.com/posts/basic-kitchen-knife-skills/">&lt;p&gt;对于刀工零基础的厨房新手来说，学会两个字就能算入门了：“扣”、“划”。&lt;/p&gt;

&lt;p&gt;这两个字属于“道”，学会了就能安全上路；具体的切法（切丝、切块、滚刀切等）都属于“术”，理解了“道”之后可以慢慢练习。&lt;/p&gt;

&lt;h2 id=&quot;扣&quot;&gt;扣&lt;/h2&gt;

&lt;p&gt;切菜的过程中，肯定要用左手固定住食材，右手才能下刀切。但新手拿菜，往往喜欢在食材上平摊手指去按。这样虽然能把菜按得很稳，但其实是很危险的：左手在食材上稍微移动得慢一点，或者右手下刀得快一些，就容易切到手指。&lt;/p&gt;

&lt;p&gt;那么，有没有什么方法，既能让我们固定住食材，又不容易伤到手呢？当然是有的，这个方法就是“扣”。专业术语叫“猫爪手”（claw grip）。&lt;/p&gt;

&lt;p&gt;顾名思义，“猫爪手”的意思是，左手五指自然弯曲，指尖向掌心方向收拢（往里“扣”），让手指的第二指节略微向前，抵住刀面。大拇指收到拳头内侧，不要从侧面探出来。这样做之后，只要刀刃不高于第二指节，你几乎不可能切到手。&lt;/p&gt;

&lt;p&gt;新手可能会觉得这个姿势有点别扭，觉得按不住食材，慢慢练习就好，切多了你就能找到感觉了。&lt;/p&gt;

&lt;p&gt;对于那些会滚动的食材，比如土豆、番茄、青椒、各种瓜类，可以先切出一个平面作为底部，这样食材就能稳稳地立在砧板上。&lt;/p&gt;

&lt;blockquote class=&quot;prompt-warning&quot;&gt;
  &lt;p&gt;不要试图用手劲去制服一个本来就不稳定的食材，这很危险。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2 id=&quot;划&quot;&gt;划&lt;/h2&gt;

&lt;p&gt;我们平常说到“切菜”、“切肉”、“切水果”，脑海中浮现的画面大多是“压”或者“剁”：刀从上用力往下压，把食物劈开。&lt;/p&gt;

&lt;p&gt;其实，这是一种费力而不讨好的方式：你需要用力往下压才能把食材切开，而且刀刃会重重撞在砧板上，不仅累手，也伤刀。&lt;/p&gt;

&lt;p&gt;更省力、安全的切法是“划”：让刀刃前后滑动，用锋利的刃口切割食材。&lt;/p&gt;

&lt;p&gt;要理解这两种发力，一个很好的类比是斧头和锯子：用“压”的方式切菜，就好像用斧头来砍树；用“划”的方式切菜，就好像用锯子把树锯断。&lt;/p&gt;

&lt;p&gt;厨房里的刀更像是锯子，而不是斧头。当你用“压”的方式切菜时，实际上你是在用刀身厚度作为一个楔子，把食材撑破。当你用“划”的方式切菜时，你是在用刀刃上的微小锯齿切断食材的纤维。这个时候，你只需要轻轻引导刀的方向，让刀自己去工作。&lt;/p&gt;

&lt;p&gt;你可以拿两个番茄来做个实验，试着把它们切成汉堡中的番茄切片，一个用“压”的方式切，一个用“划”的方式切。你会发现，用“压”的方式切，番茄会被压扁，汁水会流得满砧板都是；而用“划”的方式切，就可以切出齐整的番茄切片，而且不会流汁。&lt;/p&gt;

&lt;p&gt;理解了“划”，你就可以开始尝试各种基于“划”的刀法，比如推切（从后向前推）、拉切（从前向后拉）、推拉切（像锯子一下前后划动）。这些刀法都很基本，而且省心、省力、省刀。&lt;/p&gt;

&lt;h2 id=&quot;握刀&quot;&gt;握刀&lt;/h2&gt;

&lt;p&gt;因为重心不同，不同的刀有不同的握法：常见的中式菜刀是直接手掌包住刀柄，有时需要食指搭在刀背上，更好控制方向；主厨刀的话主要是用捏刀法（pinch grip）——大拇指和食指捏住刀刃的根部，食指的第二指节搭在刀背上，剩下的中指、无名指和小指自然地卷住刀柄。&lt;/p&gt;

&lt;h2 id=&quot;刀具保养&quot;&gt;刀具保养&lt;/h2&gt;

&lt;p&gt;“钝刀比锋利的刀更危险。”&lt;/p&gt;

&lt;p&gt;第一次听说这个道理时，我觉得很反直觉，但事实确实如此：如果刀比较钝的话，就很难用“划”的方式切开食材。你会不自觉地用力，用“压”的方式切开食材，容易打滑失控切到手。&lt;/p&gt;

&lt;p&gt;这其实和用手动剃须刀有点像：刀片锋利时，在脸上轻轻一划就能刮掉胡子；当刀片变钝之后，你会不自觉地用力往脸上压，反而更容易刮破皮肤。&lt;/p&gt;

&lt;blockquote class=&quot;prompt-warning&quot;&gt;
  &lt;p&gt;如果你已经习惯了钝刀，然后再用锋利的刀切菜时，你会错估刀的锋利度，用力过猛，很容易伤到自己。在换新刀时要特别注意这一点。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;锋利的刀比钝刀更好，所以刀具保养十分重要。这里就随便讲点方法论吧，可能不是很系统：&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;用“划”的方式去切菜，不要用力向下压。&lt;/li&gt;
  &lt;li&gt;专刀专用。剁骨头用专用的斩骨刀；斩切刀可以用来切肉切菜、斩剁小骨头；厨师刀用来切丝、切片、切丁。为了你的刀好，不要用厨师刀碰骨头，不要用斩切刀来剁骨头。&lt;/li&gt;
  &lt;li&gt;不要用刀刃贴着砧板，把菜刮进锅里或盘子里。这个是很多人会犯的错误，我之前也经常干。但我发现它很伤刀刃。换个方向，用刀背来刮就好了。&lt;/li&gt;
  &lt;li&gt;切酸性食物（比如柠檬、西红柿、酸菜）之后立刻洗干净。一般来说，切好菜之后最好能早点洗刀，擦干，放回刀具架上。&lt;/li&gt;
  &lt;li&gt;选好一块好砧板也很重要。最好买一块实木砧板，或者塑料砧板。用完之后最好也早点清洗晾干。&lt;/li&gt;
  &lt;li&gt;至于磨刀，我没试过，怕把我的刀磨坏了。我最多就是切完菜之后在一根磨刀棒（&lt;a href=&quot;https://en.wikipedia.org/wiki/Honing_steel&quot;&gt;honing steel&lt;/a&gt;）划几下刀。磨刀棒算是简单、实用，可以拨正厨师刀稍微卷曲的微小刀刃。用来磨厨师刀可以，但我不太确定能不能用来磨中式菜刀。&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;资源推荐&quot;&gt;资源推荐&lt;/h2&gt;

&lt;ul&gt;
  &lt;li&gt;
&lt;a href=&quot;https://www.bilibili.com/video/BV1jL4y1K716/&quot;&gt;厨师长教你：认刀、握刀、放刀，基础刀功第 2 期&lt;/a&gt;：王刚的刀工教学，总共有 5 期。对于新手来说，可以看看 2～4 期&lt;/li&gt;
  &lt;li&gt;
&lt;a href=&quot;https://www.youtube.com/watch?v=d6LDQudJXdY&quot;&gt;用刀技巧 1｜小改變就能大大提昇刀工｜刀工小秘訣讓你練習刀工更有效率&lt;/a&gt;：这个视频讲得很详细，这篇文章涉及到的要点基本都讲到了，很推荐&lt;/li&gt;
  &lt;li&gt;
&lt;a href=&quot;https://www.youtube.com/watch?v=t-_qzsMF8RM&quot;&gt;The Best Way To Sharpen &amp;amp; Clean Knives (And The Worst)&lt;/a&gt;：这个视频主要讲磨刀和刀具保养，也很推荐&lt;/li&gt;
&lt;/ul&gt;
</content>
  </entry>
  
    
    
    
    
  <entry>
    <title>效率陷阱</title>
    <id>https://huangboming.com/posts/efficiency-traps/</id>
    <link rel="alternate" type="text/html" href="https://huangboming.com/posts/efficiency-traps/" />
    <published>2026-07-15T00:00:00+08:00</published>
    <updated>2026-07-21T17:32:08+08:00</updated>
    <author>
      <name>Boming Huang</name>
      <uri>https://huangboming.com/about/</uri>
    </author>
    <category term="心得" />
    <summary type="text">探讨生产力的真正含义，分享职场中两个常见的效率陷阱</summary>
    <content type="html" xml:base="https://huangboming.com/posts/efficiency-traps/">&lt;p&gt;在职场最经常出现的词莫过于“生产力”和“效率”：管理层喜欢强调“高效”、“高生产力”，员工们也接受这种观念，即“高效、高生产力是一件好事”，认为自己做得足够快、产出足够多，就代表着能力强、有价值。&lt;/p&gt;

&lt;p&gt;我们都在低头狂奔，追求所谓的“高效”。但，很少有人真正停下来问过一个最基本的问题：到底什么是“生产力”？所谓“高效”，究竟意味着什么？&lt;/p&gt;

&lt;h2 id=&quot;产出--生产力&quot;&gt;产出 = 生产力？&lt;/h2&gt;

&lt;p&gt;说起“生产力”，很多人的第一想法是“产出”——产出得多就意味着高生产力，产出得少就意味着低生产力。&lt;/p&gt;

&lt;p&gt;这个定义看上去很合理。但把它应用到现实中，却会碰到一个很尴尬的情况：很多产出很难被量化，甚至无法量化。&lt;/p&gt;

&lt;p&gt;在流水线上，工人的产出确实可以被量化、比较。比如，工人 A 在一个小时内缝了 10 件衣服，工人 B 在一个小时内缝了 20 件衣服。那我们可以说 B 的生产力是 A 的两倍。&lt;/p&gt;

&lt;p&gt;但是，在脑力劳动以及复杂协作中，员工的产出很难被量化。&lt;/p&gt;

&lt;p&gt;比如，如何衡量一个程序员的产出？代码量、完成的功能数量、解决的问题数量，还是别的什么？&lt;/p&gt;

&lt;p&gt;假设两个工程师都面临同样一个任务。一个工程师花一整天写了 1000 行代码，并且附上详细的文档、完整的测试，完美地解决了这个问题。而另一个工程师出门散步，在快下班时想出了解决方案，回到办公室，删除了 100 行已有代码，也完美地解决了这个问题。&lt;/p&gt;

&lt;p&gt;在这种情况下，谁的生产力更高呢？&lt;/p&gt;

&lt;p&gt;直觉告诉我们是后者：他在解决问题的同时，没有引入额外的代码，降低了整个系统的维护成本。但在单纯追求“产出”的评价体系里，他的生产力甚至是负的。&lt;/p&gt;

&lt;p&gt;或者，假设有两个工程师。一个工程师专注于业务开发，完成了很多功能；而另一个工程师一个功能都没有完成，但他每天都在和团队里其他人一起工作：他热心地帮助经验少的程序员，耐心地教导他们，让他们自己动手，在实践中学习；他也和经验丰富的程序员互相讨论，想出更好的方案。&lt;/p&gt;

&lt;p&gt;在这种情况下，谁的生产力更高呢？&lt;/p&gt;

&lt;p&gt;这很难比较。前者的产出肉眼可见，但后者的产出却沉淀在团队其他人的产出中，为团队带来价值。在单纯追求“产出”的评价体系里，后者的生产力几乎为零。&lt;/p&gt;

&lt;p&gt;当产出难以衡量，管理者会退而求其次，寻找一些可以量化的指标。但这又会掉入另一个陷阱：过度追求局部优化。这就是所谓的古德哈特定律（&lt;a href=&quot;https://en.wikipedia.org/wiki/Goodhart%27s_law&quot;&gt;Goodhart’s law&lt;/a&gt;）：&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;When a measure becomes a target, it ceases to be a good measure.（当一个指标变成目标时，它便不再是一个好的指标）&lt;/p&gt;

  &lt;p&gt;– 查尔斯·古德哈特（Charles Goodhart）&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;如果用代码量来衡量程序员的产出，那么项目中就会堆积大量无用的代码；如果用完成的功能数量来衡量程序员的产出，那么项目就会变得臃肿；如果用解决的问题数量来衡量程序员的产出，那么系统就会出现大量小问题。&lt;/p&gt;

&lt;p&gt;退一步说，就算我们能找到完美的量化指标，还有一个更根本的问题：这些产出真的有价值吗？&lt;/p&gt;

&lt;h2 id=&quot;没有目标就无法定义生产力&quot;&gt;没有目标，就无法定义生产力&lt;/h2&gt;

&lt;p&gt;在小说《目标：简单而有效的常识管理》中，厂长罗哥在机场偶遇他大学时代的物理学教授钟纳。两人闲聊的过程中，罗哥提到他工厂中某个部门引入机器人后，生产力提高了 36%。钟纳很惊讶：“那么你的工厂因为装设了几部机器人，就多赚了 36% 的钱？真是不可思议。”&lt;/p&gt;

&lt;p&gt;罗哥澄清：“只有一个部门的生产力改善了 36%。”实际上，工厂没有因为机器人而多生产了多少产品、没有裁员、存货也没有降低。钟纳由此断定：“那么，生产力并没有真的提高。”&lt;/p&gt;

&lt;p&gt;在这段谈话的最后，钟纳问罗哥一个问题：“那么，生产力究竟是什么？怎么样才能算作有生产力？”&lt;/p&gt;

&lt;p&gt;面对钟纳的追问，罗哥一时语塞，匆忙之下随口猜了一个答案：“我猜生产力代表我在工作上有所成就。”&lt;/p&gt;

&lt;p&gt;“完全正确！”钟纳紧接着反问，“但是，你根据什么来说你有所成就呢？”&lt;/p&gt;

&lt;p&gt;“根据目标。”罗哥试探性地回答。&lt;/p&gt;

&lt;p&gt;在引导罗哥找到答案之后，钟纳才给出了他对生产力的定义：&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;生产力是把一个公司带向目标的行动。每个能更接近目标的行动，都是有生产力的行动；每个不能让公司更接近目标的行动都没生产力。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;换句话说，除非你知道目标是什么，否则生产力就毫无意义可言。&lt;/p&gt;

&lt;h2 id=&quot;效率陷阱一空谈生产力而不谈目标&quot;&gt;效率陷阱一：空谈生产力而不谈目标&lt;/h2&gt;

&lt;p&gt;但在现实的职场中，情况往往是反过来的。&lt;/p&gt;

&lt;p&gt;管理层强调高效和执行力，用各种指标、绩效来考核员工。但他们很少停下来和团队同步：公司的核心目标是什么&lt;sup id=&quot;fnref:1&quot;&gt;&lt;a href=&quot;https://huangboming.com/posts/efficiency-traps/#fn:1&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot; role=&quot;doc-noteref&quot;&gt;1&lt;/a&gt;&lt;/sup&gt;，以及这些工作对达成目标有什么帮助。有时候，甚至连管理层自己都没有想明白真正的目标在哪里，只是先让大家“动起来再说”。&lt;/p&gt;

&lt;p&gt;当“为什么要做”变得模糊时，大家很容易把注意力转移到“做得多快”、“产出了多少”上。&lt;/p&gt;

&lt;p&gt;管理层看到大家都在加班加点、不断交付，就觉得团队运转良好。在这种环境下，员工为了证明自己的价值，想方设法高效地完成任务、提高自己的产出，或者让自己看起来很忙碌。&lt;/p&gt;

&lt;p&gt;整个团队就像在跑步机上狂奔，每个人都大汗淋漓、精疲力尽。复盘会上，大家都能罗列出满满当当的业绩，每一项都像模像样。但，这些产出真的能帮助团队达成目标吗？&lt;/p&gt;

&lt;p&gt;如果目标错了，或者根本就没有目标，那么你的速度越快、产出得越多，浪费的资源就越庞大。&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;There is nothing so useless as doing efficiently that which should not be done at all.（没有什么比高效率地做一件根本不该做的事情，更无用的了）&lt;/p&gt;

  &lt;p&gt;– 彼得·德鲁克（Peter Drucker）&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2 id=&quot;效率陷阱二误以为只要高效就能完成所有任务&quot;&gt;效率陷阱二：误以为只要高效就能完成所有任务&lt;/h2&gt;

&lt;p&gt;第一个陷阱发生在公司和组织层面上，让整个团队在跑步机上狂奔；第二个陷阱则发生在我们心里：我们总是幻想，只要自己跑得足够快，总有一天能跑到终点，停下来好好休息。&lt;/p&gt;

&lt;p&gt;很多人（尤其是刚工作不久的人）会有一种错觉：认为只要高效就能把手头上的所有任务做完，做完之后就能腾出时间好好休息、做自己真正想做的事。&lt;/p&gt;

&lt;p&gt;这不难理解——我们从小被教导“等考上好大学就好了”、“等找到好工作就好了”、“等买房就好了”……在这种思想的影响下，我们下意识地以为“等我把手头的工作做完就好了”。&lt;/p&gt;

&lt;p&gt;于是，我们心甘情愿地把自己留在工位上，觉得“加加班把这个任务搞完就好了”、“只要周末再熬个夜把这个项目上线，下周就能喘口气了”。&lt;/p&gt;

&lt;p&gt;但现实往往是，无论你的效率有多高，工作永远都做不完。更可能出现的情况是：你的效率越高，涌向你的任务越多。&lt;/p&gt;

&lt;p&gt;这是因为，只要你有空闲时间，就会有新的任务冒出来填满它。这被称为帕金森定律（&lt;a href=&quot;https://en.wikipedia.org/wiki/Parkinson%27s_law&quot;&gt;Parkinson’s law&lt;/a&gt;）：&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;work expands so as to fill the time available for its completion.（工作会膨胀，直至占满所有可用的时间）&lt;/p&gt;

  &lt;p&gt;– 西里尔·诺斯古德·帕金森（C. Northcote Parkinson）&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;仔细回想一下，即使你真的某天超常发挥，提前两个小时完成了所有工作，你真的“好好休息”、“做自己真正想做的事”了吗？&lt;/p&gt;

&lt;p&gt;大多数时候，我们不敢提前离开办公室，只能在工位上无目的地刷着网页熬到下班。或者，为了显得忙碌又接了一个新需求。&lt;/p&gt;

&lt;p&gt;而且，当你表现出高效之后，很少会有老板说“你辛苦了，剩下的时间去休息吧”。更常见的情况是，“看来你的工作量还不饱和”。&lt;/p&gt;

&lt;h2 id=&quot;推荐阅读&quot;&gt;推荐阅读&lt;/h2&gt;

&lt;ul&gt;
  &lt;li&gt;关于衡量程序员的产出：
    &lt;ul&gt;
      &lt;li&gt;&lt;a href=&quot;https://www.benrady.com/2012/11/theres-no-such-thing-as-software-productivity.html&quot;&gt;There’s No Such Thing As Software Productivity&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;https://dannorth.net/blog/the-worst-programmer/&quot;&gt;The Worst Programmer I Know&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;西乔的漫画《神秘的程序员们》第 51 期&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;《目标：简单而有效的常识管理》：一本很有启发性也很好玩的小说，主要讲生产力、目标，以及瓶颈理论&lt;/li&gt;
  &lt;li&gt;《四千周》：谈论人生的有限性、效率陷阱&lt;/li&gt;
&lt;/ul&gt;

&lt;hr&gt;

&lt;h2 id=&quot;脚注&quot;&gt;脚注&lt;/h2&gt;

&lt;div class=&quot;footnotes&quot; role=&quot;doc-endnotes&quot;&gt;
  &lt;ol&gt;
    &lt;li id=&quot;fn:1&quot;&gt;
      &lt;p&gt;关于公司的目标是什么，《目标》中也有一个很清晰的观点：盈利性公司存在的根本目标是为了赚钱。 &lt;a href=&quot;https://huangboming.com/posts/efficiency-traps/#fnref:1&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;↩︎&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
  &lt;/ol&gt;
&lt;/div&gt;
</content>
  </entry>
  
    
    
    
    
  <entry>
    <title>为自己写作</title>
    <id>https://huangboming.com/posts/writing-for-oneself/</id>
    <link rel="alternate" type="text/html" href="https://huangboming.com/posts/writing-for-oneself/" />
    <published>2026-06-29T00:00:00+08:00</published>
    <updated>2026-07-21T15:40:49+08:00</updated>
    <author>
      <name>Boming Huang</name>
      <uri>https://huangboming.com/about/</uri>
    </author>
    <category term="随笔" />
    <summary type="text">从小学被批改的日记到自由写作，写作的异化与回归——学会不再考虑别人的目光，纯粹地为自己而写。</summary>
    <content type="html" xml:base="https://huangboming.com/posts/writing-for-oneself/">&lt;p&gt;在上一篇博文（&lt;a href=&quot;https://huangboming.com/posts/practice-is-a-long-process/&quot;&gt;践行是一个漫长的过程&lt;/a&gt;）中我写到，“写作已经成为了我的一部分”。这篇文章就来聊聊这个过程中最重要的心态转变：学会为自己而写。&lt;/p&gt;

&lt;h2 id=&quot;写作的异化&quot;&gt;写作的异化&lt;/h2&gt;

&lt;p&gt;回想从小接受的教育，我发现自己对写作的认知被塑造成：写作主要是为了他人，而不是为了自己。&lt;/p&gt;

&lt;p&gt;在小学，老师教导我们要写日记或者周记。&lt;/p&gt;

&lt;p&gt;日记是一种很自然的写法：我们在一个很私密的领地，用文字记录观察、感受、思考，不需要考虑他人的目光。这本是一个人探索自我和世界的好方式。&lt;/p&gt;

&lt;p&gt;但是，这些日记往往会被审阅、批改，甚至在全班面前被大声朗读。不论是被当作范文表扬，还是作为反面教材批评。慢慢地，我开始觉得文字是不安全的，写下来的东西随时可能暴露、被审视，甚至被嘲笑。&lt;/p&gt;

&lt;p&gt;为了适应这套规则，我学会了表演，摸索出“如何写出老师爱看的日记”。我开始编造想法和经历（比如经典的“扶老奶奶过马路”），刻意堆砌修辞、引用所谓的名人名言。&lt;/p&gt;

&lt;p&gt;我不敢写自己讨厌某个同学，不敢写上课很无聊，不敢写自己去哪里玩了。因为我知道，这些真实的想法换来的可能是批评、低分或嘲笑。&lt;/p&gt;

&lt;p&gt;上了初中，我开始学习如何写作文。在考场上，作文是有标准的：要符合题意、要中心思想明确、要引经据典、要有好词好句。只有这样，我才能得到高分。而如果写自己真实的，但不符合主流审美的想法，往往会得低分。&lt;/p&gt;

&lt;p&gt;经过漫长的训练，我在写作的过程中，总觉得自己的文字会被他人审视、评论；觉得自己真实的观察、想法没有价值，只有高立意、“有意义”的文章才值得写。对于写作，我的第一反应已经不再是“我有什么感受”，而变成了“别人希望我写什么”。&lt;/p&gt;

&lt;h2 id=&quot;找回写作的感觉&quot;&gt;找回写作的感觉&lt;/h2&gt;

&lt;p&gt;当我后来想要重新开始写作时，面对电脑屏幕，我也常常一坐就是半小时。盯着闪烁的光标，不知道应该写点什么，总觉得自己的想法太单薄、表达太笨拙，害怕被别人评判。&lt;/p&gt;

&lt;p&gt;后来，我接触到一个方法论，&lt;strong&gt;自由写作（&lt;a href=&quot;https://en.wikipedia.org/wiki/Free_writing&quot;&gt;free writing&lt;/a&gt;）&lt;/strong&gt;。大意是，坐下来，尽可能快地写尽可能多的东西，倾倒自己脑海中出现的任何想法。不要求表达有多好，不要求格式。唯一的要求是，不要在写作的途中修改原文。&lt;/p&gt;

&lt;p&gt;关键在于，&lt;strong&gt;为自己创建一个绝对安全的心理舒适区&lt;/strong&gt;：这些文字只给自己看，不会有任何其他人能看到这些文字。&lt;/p&gt;

&lt;p&gt;我发现，只要确立了这个绝对安全的前提，我就不再期待写出来的东西必须有多好，也不用担心任何人的目光，只需专注于写作本身。写多少都可以，写得多糟糕也无所谓，反正是写给自己的。&lt;/p&gt;

&lt;blockquote class=&quot;prompt-tip&quot;&gt;
  &lt;p&gt;可以试试给自己设定一个 10 或 15 分钟的倒计时。在闹钟响起前，手不要离开键盘，脑子里冒出什么就敲什么。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;一开始，我也不知道应该写点什么，写什么类型的东西，我就直接从日记开始，写点流水账：我今天看到了什么，读了些什么，做了些什么，内心在想什么。这样写的好处是，无论如何，你总有一些东西可以写。&lt;/p&gt;

&lt;p&gt;慢慢地，当我习惯了写流水账之后，我开始有了一点思考，开始在基本的感受之上加上一点点自己的观点、想法。&lt;/p&gt;

&lt;p&gt;后来我还发现，我可以把这些文字发送给 AI，围绕着这些文字聊天、讨论。与向他人倾诉不同，AI 并不带有审视的目光，它更像一面映照内心的镜子。&lt;/p&gt;

&lt;p&gt;比如，我为工作上的某件事生气，我会先用文字记录下来发给它。它不会评判我的情绪，相反地，它会先安慰我，然后帮我理清被愤怒掩盖的内在需求，提供一些不一样的视角。&lt;/p&gt;

&lt;p&gt;或者在读书、写作时产生的新观点，我也会丢给 AI，和它聊聊。它能帮我延伸思考，拓展原有的观点，或者建立与其他领域的联系。我也会让它推荐一些书籍，帮助我进一步拓展视野和认知。&lt;/p&gt;

&lt;p&gt;在这个过程中，我的写作依然是私密的，AI 只是帮助我向内心探索得更深一点。这也是为什么我更喜欢 Gemini：它的世界知识很广，总能给我一些惊喜。&lt;/p&gt;

&lt;p&gt;这些都让我觉得写作是一件很好玩的事情。慢慢地，我开始享受这样的写作：不再需要考虑别人的目光，纯粹地为了自己而写。&lt;/p&gt;

&lt;h2 id=&quot;自由写作的价值&quot;&gt;自由写作的价值&lt;/h2&gt;

&lt;p&gt;最后来聊聊自由写作的价值吧。&lt;/p&gt;

&lt;p&gt;看着自己初期写下的大段流水账，我也曾怀疑：这些文字真的有意义吗？后来我意识到，我脑海中丈量“价值”的尺子，依然是“从别人的角度来看是否有用”。而这些文字是私密的，自然不具备向外的“阅读价值”。从这个角度来看，自由写作当然没有价值。&lt;/p&gt;

&lt;p&gt;但我发现，这些文字不需要外在的认可，用文字表达自己的观察和思考这个过程本身就是有价值的。&lt;/p&gt;

&lt;p&gt;在心理学上有一个很有意思的理论，叫“自我知觉理论”（&lt;a href=&quot;https://en.wikipedia.org/wiki/Self-perception_theory&quot;&gt;self-perception theory&lt;/a&gt;）。&lt;/p&gt;

&lt;p&gt;我们一般认为，我们要先有想法，然后再有行动。比如，我知道我喜欢苹果，所以我吃苹果。&lt;/p&gt;

&lt;p&gt;自我知觉理论则认为，在很多情况下，我们实际上并不了解我们的内在状态，比如情绪、态度、真实想法。我们通过观察自己的行为来推断出自己到底在想什么。比如说，我发现我最近总在吃苹果，所以我很喜欢吃苹果。&lt;/p&gt;

&lt;p&gt;这个道理放在写作上也是如此。也许，写作并不总是为了表达已有的想法。很多时候，直到写下的那一刻，我们才刚刚开始认识自己。&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;I write entirely to find out what I’m thinking, what I’m looking at, what I see and what it means. What I want and what I fear.（我写文章，完全是为了弄清楚我在想什么，我在看什么，我看到了什么，以及这一切意味着什么。我渴望什么，我又恐惧什么。）&lt;/p&gt;

  &lt;p&gt;– Joan Didion&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2 id=&quot;延伸阅读&quot;&gt;延伸阅读&lt;/h2&gt;

&lt;ul&gt;
  &lt;li&gt;
&lt;em&gt;The Artist’s Way: 30th Anniversary Edition&lt;/em&gt;（中译：《唤醒创作力》）, by Julia Cameron. 书中有几个很有启发性的观念：创造是人的自然本能，每个人都是天生的艺术家、晨页（morning pages）、艺术家之约（Artist Dates）。&lt;/li&gt;
&lt;/ul&gt;
</content>
  </entry>
  
    
    
    
    
  <entry>
    <title>践行是一个漫长的过程</title>
    <id>https://huangboming.com/posts/practice-is-a-long-process/</id>
    <link rel="alternate" type="text/html" href="https://huangboming.com/posts/practice-is-a-long-process/" />
    <published>2026-06-28T00:00:00+08:00</published>
    <updated>2026-07-21T15:40:49+08:00</updated>
    <author>
      <name>Boming Huang</name>
      <uri>https://huangboming.com/about/</uri>
    </author>
    <category term="随笔" />
    <summary type="text">为什么听过很多道理，依然过不好这一生？践行不是简单的“知道就去做”，从知道到内心真正改变，是一条漫长的路。</summary>
    <content type="html" xml:base="https://huangboming.com/posts/practice-is-a-long-process/">&lt;p&gt;这是一个困扰很多人的问题：为什么听过很多道理，依然过不好这一生？&lt;/p&gt;

&lt;p&gt;李笑来在他的作品《七年就是一辈子》和《通往财富自由之路》中给出了他的答案：这是因为人没有真正认同并且笃定地践行那些道理。道理很简单，&lt;strong&gt;“知道”并不等于“做到”&lt;/strong&gt;。&lt;/p&gt;

&lt;p&gt;我很认同他的观点，也按照他的观点走了很长一段路。在这段路中，我发现&lt;strong&gt;践行其实是一个很漫长的过程&lt;/strong&gt;。并不是只要你听过某个道理，然后告诉自己“我要按照这个道理做”就可以了。从“知道”到“行动”，再到人发自内心的改变还有很长一段距离。&lt;/p&gt;

&lt;p&gt;我碰到的现实是，我读到某个观念，觉得它很有道理，也根据它执行了一段时间。但可能过一段时间之后，或是自己忘记了，或是碰到了某个困难，或是意志力耗尽、无法坚持，于是就不知不觉地放弃了。&lt;/p&gt;

&lt;p&gt;比如，我知道复利效应，知道长期微小的行动可以积累出很大的成果，知道最好不要中断复利效应；我也知道写作有助于思考。那么一个合理的推论就是，我可以每天写作，梳理自己的思路，记录自己的思考。于是，我给自己定了一个目标：每天写一千字。&lt;/p&gt;

&lt;p&gt;刚开始几天，我确实每天写了一千字。但很快我就开始觉得这是一个负担：每天都要花上半小时甚至一小时来写，而且写到最后不知道应该写什么，感觉没什么想写的。这种挫败感一天天积累，到最后，我放弃了这个目标。&lt;/p&gt;

&lt;p&gt;相信很多人都有过类似的经历，不一定是写作，可能是健身、阅读、学习。&lt;/p&gt;

&lt;p&gt;对于这个现象，我是这样理解的：&lt;strong&gt;一切都关乎你的心&lt;/strong&gt;。只有当你的内心发生了真正的转变，行动才会自然而然地发生。&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;在此之前，一切都是借来的：观念只是暂时的，行动也需要意志力去维系。而人的意志力总是有限的，总会有坚持不下去的一天。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;每一个道理都像是一副眼镜。当你听到它时，你就像戴上了一副眼镜，可以从一个不同的视角来看待世界，可以看到之前没有注意到的东西。&lt;/p&gt;

&lt;p&gt;比如，听到“课题分离”，你会突然看见很多痛苦其实来自越界；听到“人生是自己的责任”，你会突然看见自己过去把太多主动权交给了环境和别人。&lt;/p&gt;

&lt;p&gt;只是，这副眼镜是暂时的。刚开始，你会觉得很兴奋，觉得自己看到了不一样的世界，要根据看到的东西去行动。但睡几觉之后，你会慢慢忘记这个道理，你通过这副眼镜看到的世界也会慢慢褪色。而且，你的行动依旧被旧习惯和旧环境所影响，在现实世界中遇到阻力。你开始萌生退意，最终放弃。&lt;/p&gt;

&lt;p&gt;不过，这颗改变的种子已经种下，等待着发芽、成长、开花、结果。只不过，这个过程是漫长的。&lt;/p&gt;

&lt;p&gt;你之前透过这副眼镜看到的东西，会不知不觉地改变你的内心。你可能会在某个时刻突然想起这个道理，重新开始践行。你可能会经历很多次“诶呀，我怎么这么傻，我明明听过这个道理”，或者“我根据这个道理思考、行动，感觉很快乐、很自然”的时刻。这些时刻，都是种子的养料。&lt;/p&gt;

&lt;p&gt;直到有一天，这颗种子长成了参天大树。&lt;strong&gt;这个道理不再是借来的文字，它已经变成了你的一部分&lt;/strong&gt;。你不需要再告诉自己“我要去践行这个道理”、“我要坚持下去”、“我要自律”，行动会自然而然发生。&lt;/p&gt;

&lt;p&gt;现在，写作已经成为了我的一部分。对于我来说，写作就是写作，是我的思考方式，是我的生活。我不再需要强迫自己，告诉自己“写作可以帮助我思考，对我来说很有帮助”，也不用再说“我坚持每天写作”、“我每天要写一千字”。&lt;/p&gt;

&lt;p&gt;这一切，都来源于我内心的转变：&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;我了解到“自由写作”的概念，发现最简单的写作不过是把自己的所见所闻、所思所想都写下来，不需要考虑字数，不需要担心写得好不好，不需要考虑别人的看法。&lt;/li&gt;
  &lt;li&gt;我学会了接纳自己的生活节奏，人的精力有高峰有低谷，不再强迫自己在状态差的时候去写作。&lt;/li&gt;
  &lt;li&gt;我在自由写作的过程中，发现写作可以让我排解情绪、梳理思路。我还可以和 AI 围绕着我写下的东西闲聊，发现新的视角，这让我觉得写作是一件很好玩的事儿。&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;了解一个道理，觉得一个道理是对的，笃定地践行那个道理，这当然没问题。只是要记住，这个践行的过程很漫长。不要太心急，一口吃成一个大胖子；也不要太强求自己，觉得“既然知道了，就必须做到”。&lt;/p&gt;

&lt;p&gt;还好，人生也挺漫长的，也不急于一时。&lt;/p&gt;

&lt;p&gt;最后贴一个 ChatGPT 的总结和补充吧，比我写得好多了：&lt;/p&gt;

&lt;blockquote class=&quot;prompt-info&quot;&gt;
  &lt;p&gt;一开始，道理是借来的。行动也是勉强的。
但只要你在某些关键时刻真的用它看过世界、做过选择、承受过后果、尝到过一点真实的好处，它就会慢慢从“别人的话”变成“我的经验”。&lt;/p&gt;

  &lt;p&gt;人不是因为听懂了道理才改变。
人是因为某个道理终于进入了自己的生命经验，才改变。&lt;/p&gt;
&lt;/blockquote&gt;
</content>
  </entry>
  
    
    
    
    
  <entry>
    <title>AI 翻译阅读</title>
    <id>https://huangboming.com/posts/ai-translation/</id>
    <link rel="alternate" type="text/html" href="https://huangboming.com/posts/ai-translation/" />
    <published>2025-08-09T00:00:00+08:00</published>
    <updated>2026-07-16T00:13:32+08:00</updated>
    <author>
      <name>Boming Huang</name>
      <uri>https://huangboming.com/about/</uri>
    </author>
    <category term="心得" />
    <summary type="text">分享使用 Gemini 2.5 Pro 进行整书级 AI 翻译的完整流程，包括模型选择、书籍格式转换与翻译提示词撰写心得。</summary>
    <content type="html" xml:base="https://huangboming.com/posts/ai-translation/">&lt;p&gt;这是读书爱好者的好时代。&lt;/p&gt;

&lt;p&gt;在互联网时代，获取电子书的门槛已经大大降低，而且成本也相对纸质书更低，特别是外文原版书。以《穷查理宝典》为例，其英文版在 &lt;a href=&quot;https://www.amazon.com/Poor-Charlies-Almanack-Essential-Charles-ebook/dp/B0C5TCGPPS/&quot;&gt;亚马逊&lt;/a&gt; 上纸质版价格为 27.90 美元，而电子版价格仅为 9.99 美元。&lt;/p&gt;

&lt;p&gt;不过，语言依然是一道门槛。当我们的外文水平或耐心不足以支撑读完一整本原版书时，我们只能等国内出版社引进，才能读到翻译版。这就带来几个问题。&lt;/p&gt;

&lt;p&gt;首先，等翻译版意味着时间差，意味着我们无法第一时间接触到那些关键的思想、知识或概念，或者满足自己的好奇心。&lt;/p&gt;

&lt;p&gt;比如，之前在 ChatGPT 刚刚兴起时，我想补补 NLP 领域相关的核心知识，找到了《Natural Language Processing with Transformers》。但当时这本书并没有中译本。幸好我英文水平还行，还能慢慢地啃完它。&lt;/p&gt;

&lt;p&gt;如果碰到一本自己想读的外文书却没有译本，而后在等翻译版的过程中失去耐心，或者忘记自己想读这本书，无疑是一件很可惜的事。&lt;/p&gt;

&lt;p&gt;而且，我们想读的书未必会被引进。特别是一些小众的、年代久远的书，可能永远等不来翻译版。比如《The Path of Least Resistance》。&lt;/p&gt;

&lt;p&gt;然后，由于译者水平良莠不齐，翻译质量很难得到保证（读过某些国内翻译的英文教材的读者应该能理解）。更别提可能存在的删减。&lt;/p&gt;

&lt;p&gt;而在 AI 时代，我们完全可以自己动手，丰衣足食。遇到想看的书，直接用 AI 翻译成中文版。快速阅读，吸收书中的思想，满足自己的好奇心。&lt;/p&gt;

&lt;p&gt;不过，有些人可能怀疑 AI 翻译的质量，认为 AI 翻译也不行。&lt;/p&gt;

&lt;p&gt;我的观点是，对于以获取知识和思想为目的的阅读，我们的首要目标应该是理解作者想要表达的内容，而不是关注译文质量。我对译文的要求只是逻辑通顺、文字流畅、不篡改作者原意、不删减。而读过几本 AI 翻译的书籍之后，我发现 AI 的翻译完全能达到以上要求。&lt;/p&gt;

&lt;p&gt;而且，我们还可以使用提示词（prompt）增强 AI 的翻译能力，也可以让它按照我们的喜好翻译。例如，我喜欢译文中在专有名词（人名、地名、专业术语等等）后面标注对应的英文，方便后续查找相关英文资料，进一步研究。那么我只要在提示词中写明要求，它会给出满足我要求的译文。&lt;/p&gt;

&lt;p&gt;AI 翻译还有一个好玩的地方是，它可以给你一种“边译边读”的体验：你可以一边让它翻译，一边读刚刚它翻译的内容；也可以读完上一次翻译的内容，让它继续翻译，同时自己起身喝杯水、伸个懒腰。这种即时互动的阅读方式，是任何传统翻译无法给我们的。&lt;/p&gt;

&lt;p&gt;下面，我将分享一套完整 AI 翻译教程与心得。&lt;/p&gt;

&lt;h2 id=&quot;免责声明&quot;&gt;免责声明&lt;/h2&gt;

&lt;ol&gt;
  &lt;li&gt;注意版权问题。AI 翻译的译文应该仅供自己学习，请勿传播或用于商业目的。&lt;/li&gt;
  &lt;li&gt;获取电子书不在本文讨论范畴之内。下文假设你已经有一本没有 &lt;a href=&quot;https://en.wikipedia.org/wiki/Digital_rights_management&quot;&gt;DRM&lt;/a&gt; 电子书，最好是常见的电子书格式，比如说 EPUB、MOBI、PDF、TXT。&lt;/li&gt;
  &lt;li&gt;AI 翻译不能保证完全准确。AI 可能会错译、漏译，需要读者在翻译过程中谨慎检查，建议在读译文的同时，偶尔看看原文。&lt;/li&gt;
&lt;/ol&gt;

&lt;h2 id=&quot;准备工作&quot;&gt;准备工作&lt;/h2&gt;

&lt;h3 id=&quot;模型选择gemini-25-pro&quot;&gt;模型选择：Gemini 2.5 Pro&lt;/h3&gt;

&lt;p&gt;一如既往，我个人还是推荐使用 Gemini 2.5 Pro。&lt;/p&gt;

&lt;p&gt;首先，它的上手门槛很低——只需要一个 Google 账号，可以免费使用。而且模型本身能力也很强。&lt;/p&gt;

&lt;p&gt;更重要的是，Gemini 2.5 Pro 具备以下对于翻译很重要的几个特点。&lt;/p&gt;

&lt;p&gt;第一，它具备广泛的世界知识。这是因为 Google 作为世界上最大的搜索引擎，能够收集到巨量、涵盖各个领域的数据集。这意味着它能够准确地理解不同领域的术语和背景，从而给出更贴切的译文。&lt;/p&gt;

&lt;p&gt;其次，它是一个多模态模型，能够准确地理解大部分 PDF。这意味着我们不需要手动提取 PDF 中的内容，这在翻译扫描版 PDF 时尤其有用。&lt;/p&gt;

&lt;p&gt;再者，它的上下文窗口长达一百万 token，而且抗上下文衰减能力强。这意味着它能轻松阅读并翻译一整本书，并在翻译时保持全局语境的连贯性。&lt;/p&gt;

&lt;p&gt;以我最近读的《Outlive》为例。它的英文版 PDF 长达 559 页，上传 PDF 消耗了 14.5 万 token。完整翻译之后，整个上下文窗口也才 32.8 万 token。&lt;/p&gt;

&lt;p&gt;最后，它输出窗口也很大，一次性可以输出 6.5 万 token。这意味着一次输出更多文字，用更少的对话就能翻译全书。这可以极大降低成本，因为每一次对话都会把之前对话中所有内容发送给 AI，多发送一次，成本就会像滚雪球一样增加。当然，我们不需要关心价格，毕竟是免费使用。&lt;/p&gt;

&lt;p&gt;不过 Gemini 2.5 Pro 在翻译中也有值得注意的问题：译文中有可能会突然蹦出一两个其他语言的词汇（我甚至见过日语、俄语的词汇）。这个现象比较罕见，不太影响实际阅读。&lt;/p&gt;

&lt;h3 id=&quot;书籍格式转换&quot;&gt;书籍格式转换&lt;/h3&gt;

&lt;p&gt;目前，Google AI Studio 只支持上传 PDF 格式的文件，或粘贴纯文本。因此，在开始之前，你需要将 EPUB、MOBI 等格式的书籍统一转换为 PDF 或 TXT。&lt;/p&gt;

&lt;p&gt;我推荐使用 Calibre 转换书籍。它是一个免费、开源且功能强大的电子书管理工具，几乎支持导入所有主流电子书格式，并可在这些格式之间相互转换。&lt;/p&gt;

&lt;p&gt;首先，访问 &lt;a href=&quot;https://calibre-ebook.com/download&quot;&gt;Calibre 官网&lt;/a&gt;，下载并安装 Calibre。如果你使用 macOS 系统而且使用 Homebrew，那么你可以直接通过 Homebrew 安装：&lt;/p&gt;

&lt;div class=&quot;language-shell highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;table class=&quot;rouge-table&quot;&gt;&lt;tbody&gt;&lt;tr&gt;
&lt;td class=&quot;rouge-gutter gl&quot;&gt;&lt;pre class=&quot;lineno&quot;&gt;1
&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&quot;rouge-code&quot;&gt;&lt;pre&gt;brew &lt;span class=&quot;nb&quot;&gt;install&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;--cask&lt;/span&gt; calibre
&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;安装好之后，运行 Calibre，你会看到一个很复古的页面。点击左上角菜单栏的“Add book”按钮，从文件系统中导入电子书。&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;https://huangboming.com/assets/images/ai-translation/1.png&quot; alt=&quot;Calibre 主页面&quot; class=&quot;shadow&quot; w=&quot;700&quot; h=&quot;447&quot;&gt;
&lt;em&gt;Calibre 主页面&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;然后，在书籍列表中选中这本书，点击菜单栏“Add book”右侧的“Convert books”（见上图）。在弹出窗口的右上角，找到“Output format”，选择你想要转换的格式（PDF 或 TXT），然后点击右下角的“OK”按钮，开始格式转换。&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;https://huangboming.com/assets/images/ai-translation/2.png&quot; alt=&quot;转换书籍页面&quot; class=&quot;shadow&quot; w=&quot;700&quot; h=&quot;443&quot;&gt;
&lt;em&gt;转换书籍页面&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;你可以在 Calibre 主页的右下角“Jobs”处看到进度。格式转换完成之后，在书籍列表中选中这本书。右键打开上下文菜单，选择“Save to disk -&amp;gt; Single format to disk”。在弹出的窗口中选择转换后的格式，把转换后的书籍保存到选定路径下。&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;https://huangboming.com/assets/images/ai-translation/3.png&quot; alt=&quot;保存转换后的书籍&quot; class=&quot;shadow&quot; w=&quot;700&quot; h=&quot;430&quot;&gt;
&lt;em&gt;保存转换后的书籍&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;对于格式选择，我有两个建议：&lt;/p&gt;
&lt;ol&gt;
  &lt;li&gt;如果书籍以文字为主，首选 TXT 格式，把书籍内容复制到对话框。毕竟 Gemini 2.5 Pro 最擅长的还是文字处理，这也能最大化利用它的长文输出能力，翻译过程最流畅。&lt;/li&gt;
  &lt;li&gt;如果书籍包含大量图片、图表，或是扫描版 PDF，建议统一转成 PDF 格式，利用 Gemini 2.5 Pro 多模态能力来翻译。Gemini 虽然不能直接翻译图表，但它能用语言描述图表中的内容。&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;虽说 Gemini 2.5 Pro 可以直接准确翻译 PDF，但是翻译过程体验不是很好，容易漏译。比如，在翻译长章节时，它往往翻译到一半就停下。我猜测是因为它看到一个小标题，误以为那是下一章的标题，于是认为这一章已经翻译结束。因此，翻译 PDF 时建议边译边看看原文，随时检查有无漏译。&lt;/p&gt;

&lt;p&gt;因为版权原因，我不能放具体的例子。大家可以自行尝试、对比这两种转换方式，找到自己认为合适的方式。&lt;/p&gt;

&lt;h2 id=&quot;翻译流程&quot;&gt;翻译流程&lt;/h2&gt;

&lt;p&gt;整个翻译过程非常简单。&lt;/p&gt;

&lt;h3 id=&quot;1-设置模型和系统提示词&quot;&gt;1. 设置模型和系统提示词&lt;/h3&gt;

&lt;p&gt;访问 &lt;a href=&quot;https://aistudio.google.com/prompts/new_chat&quot;&gt;Google AI Studio&lt;/a&gt;，在右侧 Run settings 中，设置模型为 Gemini 2.5 Pro。然后，点击上方工具栏的第一个图标，设置系统提示词（system prompt）。&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;https://huangboming.com/assets/images/ai-translation/4.png&quot; alt=&quot;AI Studio 中设置系统提示词&quot; class=&quot;shadow&quot; w=&quot;700&quot; h=&quot;412&quot;&gt;
&lt;em&gt;AI Studio 中设置系统提示词&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;使用&lt;a href=&quot;https://huangboming.com/posts/aesthetics-and-prompting/&quot;&gt;审美与提示词书写&lt;/a&gt;中的方法论，我撰写了一份翻译系统提示词。你可以直接复制使用：&lt;/p&gt;

&lt;div class=&quot;language-markdown highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;table class=&quot;rouge-table&quot;&gt;&lt;tbody&gt;&lt;tr&gt;
&lt;td class=&quot;rouge-gutter gl&quot;&gt;&lt;pre class=&quot;lineno&quot;&gt;1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&quot;rouge-code&quot;&gt;&lt;pre&gt;你是一个世界级翻译家，你的所有翻译要符合下面的翻译准则。

&lt;span class=&quot;gu&quot;&gt;## 翻译准则&lt;/span&gt;

好的译文：
&lt;span class=&quot;p&quot;&gt;-&lt;/span&gt; 信——对原作，它忠实而深刻
&lt;span class=&quot;p&quot;&gt;-&lt;/span&gt; 达——对读者，它清晰而自然
&lt;span class=&quot;p&quot;&gt;-&lt;/span&gt; 雅——在艺术上，它优雅而得体
&lt;span class=&quot;p&quot;&gt;-&lt;/span&gt; 功能对等——在功能上，它精准而有效

其他要求：
&lt;span class=&quot;p&quot;&gt;-&lt;/span&gt; 在处理专有名词（人名、地名、专业术语等）时，在其后附上括号标注英文原文。如卡尔·萨根 (Carl Sagan)。而对于那些已经普遍接受的规范译名，则无需进行标注，例如：爱因斯坦。
&lt;span class=&quot;p&quot;&gt;-&lt;/span&gt; 对于不确定翻译是否准确的句子，在其后附上括号标注英文原文。

&lt;span class=&quot;gu&quot;&gt;### 信&lt;/span&gt;

“信”意味着忠实于原文的内容、思想、情感、风格和语气。译者需要像一个侦探，深入理解作者为什么要用这个词，这句话背后隐藏的情感和立场是什么。

要点：
&lt;span class=&quot;p&quot;&gt;-&lt;/span&gt; 保证信息完整，不能随意增删、扭曲原文的信息。无论是事实、数据，还是微妙的情感色彩，都应尽可能完整地传达。
&lt;span class=&quot;p&quot;&gt;-&lt;/span&gt; 保证风格一致。原文是诙谐的，译文就不应是严肃的；原文是古朴的，译文就不应是现代的。译者需要把握原作的整体风格，并在译文中复现。

&lt;span class=&quot;gu&quot;&gt;### 达&lt;/span&gt;

“达”意味着译文通顺流畅，符合目标语言的阅读习惯。行文流畅，宛若原创，这是“达”的理想状态。

一个优秀的译者必然是一个文化使者。他需要处理原文中特有的文化元素（如典故、习俗、俚语）。一篇充满了翻译腔（欧式句法、生硬词汇）的译文，即使每个词的意思都对，也算不上“达”。译文必须读起来地道，自然、流畅，没有生涩之感。好的译文能让读者跨越文化鸿沟，与作品产生共鸣。&lt;span class=&quot;sb&quot;&gt;


&lt;/span&gt;要点：
&lt;span class=&quot;p&quot;&gt;-&lt;/span&gt; 译文必须确保逻辑通顺，让读者能够毫不费力地理解内容。
&lt;span class=&quot;p&quot;&gt;-&lt;/span&gt; 当原文中出现目标读者不熟悉的文化典故、习语时（例如，英文中的 &quot;It&apos;s raining cats and dogs.&quot;），好的译者不会直译为“下猫下狗”，而是会采取读者能理解的方式进行处理，如意译为“倾盆大雨”，或在必要时加以注释，帮助读者理解文化背景。

&lt;span class=&quot;gu&quot;&gt;### 雅&lt;/span&gt;

“雅”是在“信”和“达”的基础上，追求文字的精炼和美感。

要点：
&lt;span class=&quot;p&quot;&gt;-&lt;/span&gt; 注意文字的韵律与节奏：美的译文是有音律感的。长短句的交错、词语的搭配、声调的和谐，都会影响阅读的体验。尤其在文学、诗歌翻译中，译者需要像音乐家一样，组织语言的节奏和韵律。
&lt;span class=&quot;p&quot;&gt;-&lt;/span&gt; 对词语的精挑细选，力求用最精准、最富表现力、最有意境的词汇来还原原文的神采
&lt;span class=&quot;p&quot;&gt;-&lt;/span&gt; 营造意境：美的译文能够超越字面，将原文的画面感、氛围和弦外之音巧妙地传达给读者，引发读者的联想和共鸣。

&lt;span class=&quot;gu&quot;&gt;### 功能对等&lt;/span&gt;

功能对等意味着，一个好的译文，必须实现其预设的功能。它的“好”体现在“恰如其分”。

比如，
&lt;span class=&quot;p&quot;&gt;-&lt;/span&gt; 广告语翻译：目的不是字面对等，而是要在目标市场引起同样的购买欲。耐克的 &quot;Just do it&quot; 翻译成“想做就做”或保留原文，都是基于功能的选择。
&lt;span class=&quot;p&quot;&gt;-&lt;/span&gt; 法律合同翻译：美感和文采完全不重要，极端精准、无歧义才是唯一的美。
&lt;span class=&quot;p&quot;&gt;-&lt;/span&gt; 儿童读物翻译：语言必须符合儿童的认知水平，生动有趣，易于理解。
&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;2-上传书籍&quot;&gt;2. 上传书籍&lt;/h3&gt;

&lt;p&gt;对于 TXT 格式的书籍，你可以复制文件中所有内容。然后，在对话框中，先输入提示词“将下面的文字翻译成中文”，再换行，输入一些分隔符（——–），再换行，再粘贴书籍内容。对于 PDF 格式的书籍，你可以点击对话框右侧的加号，上传 PDF 文件。&lt;/p&gt;

&lt;h3 id=&quot;3-开始翻译&quot;&gt;3. 开始翻译&lt;/h3&gt;

&lt;p&gt;对于 TXT 格式的书籍，输入上述提示词以及书籍内容之后，点击“Run”即可。而对于 PDF，上传成功之后，在对话框输入“请把这份文档翻译成中文。”，然后点击“Run”。&lt;/p&gt;

&lt;p&gt;你可以自定义提示词。不过，一定不要在提示词中出现“翻译书籍”之类的措辞，否则 Gemini 会说有版权问题，拒绝翻译。&lt;/p&gt;

&lt;p&gt;开始翻译之后，后续就是一路输入“继续”，直到全书翻译完成。对于 PDF，别忘了边译边读，随时检查是否有中断或者遗漏。&lt;/p&gt;

&lt;h2 id=&quot;结语&quot;&gt;结语&lt;/h2&gt;

&lt;p&gt;以上是我用 Gemini 2.5 Pro 进行整书级 AI 翻译的实践路径和心得。祝你玩得愉快，阅读愉快。&lt;/p&gt;
</content>
  </entry>
  
    
    
    
    
  <entry>
    <title>Claude Code 基础教程以及使用心得分享</title>
    <id>https://huangboming.com/posts/using-cc/</id>
    <link rel="alternate" type="text/html" href="https://huangboming.com/posts/using-cc/" />
    <published>2025-07-31T00:00:00+08:00</published>
    <updated>2026-07-16T00:13:32+08:00</updated>
    <author>
      <name>Boming Huang</name>
      <uri>https://huangboming.com/about/</uri>
    </author>
    <category term="教程" />
    <summary type="text">Claude Code 基础安装配置教程，以及 CLAUDE.md 书写、上下文管理、用量监控等实战心得分享。</summary>
    <content type="html" xml:base="https://huangboming.com/posts/using-cc/">&lt;p&gt;自从 Claude Code（下文简称 cc）支持 Claude Pro 订阅用户之后，它的身影便频繁出现在各大技术论坛，常被用来与 Cursor 等 AI 编程工具作比较。作为 Cursor 的年费用户，我已经在项目中建立一套成熟的 Cursor 工作流，因此虽然很想体验，但迟迟并没有下定决心。&lt;/p&gt;

&lt;p&gt;最近 Cursor 的计费模式&lt;a href=&quot;https://cursor.com/en/blog/june-2025-pricing&quot;&gt;调整&lt;/a&gt;，从按次计费改为按 API 用量计费。在我看来是变相削减用量。于是，我一边发邮件申请切回旧方案（顺带一提，邮件申请通过了），我一边开通了 Claude Pro，打算先用 cc 过渡一阵。&lt;/p&gt;

&lt;p&gt;经过一段时间的探索，我发现 cc 确实名不虚传。它和 Cursor 各有所长，完全可以相辅相成，并不是替代关系。后续我打算双持，搭配使用。&lt;/p&gt;

&lt;h2 id=&quot;基础入门&quot;&gt;基础入门&lt;/h2&gt;

&lt;h3 id=&quot;什么是-claude-code&quot;&gt;什么是 Claude Code&lt;/h3&gt;

&lt;p&gt;Claude Code 是 Anthropic 官方基于最新的 Claude Opus/Sonnet 4 开发的 CLI AI 编程工具。&lt;/p&gt;

&lt;p&gt;和常见的 IDE 不同，cc 完全运行在终端中，没有图形界面。对于习惯使用图形界面来开发的程序员来说，刚开始使用 cc 可能会有些不适应。不过，这两者并不冲突。你完全可以在终端中使用 cc 开发，再回到 IDE 中审查代码、提交 commit、执行 rebase。&lt;/p&gt;

&lt;h3 id=&quot;安装&quot;&gt;安装&lt;/h3&gt;

&lt;p&gt;本文主要介绍在 macOS 和 Linux 系统上安装并使用原生 cc 的方法。&lt;/p&gt;

&lt;p&gt;如果你想：&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;Windows 系统上使用，需要额外配置，具体方法可以参考&lt;a href=&quot;https://linux.do/t/topic/803265&quot;&gt;《Claude Code 终极版 FAQ 指南》&lt;/a&gt;。&lt;/li&gt;
  &lt;li&gt;使用非 Anthropic API 格式的 API，如 Gemini API、OpenAI API，可以参考 &lt;a href=&quot;https://github.com/musistudio/claude-code-router&quot;&gt;Claude Code Router 项目&lt;/a&gt;
&lt;/li&gt;
  &lt;li&gt;使用支持 Anthropic API 格式的非官方 API（如第三方中转、Kimi K2），可以通过配置环境变量 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ANTHROPIC_BASE_URL&lt;/code&gt; 和 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ANTHROPIC_AUTH_TOKEN&lt;/code&gt; 实现。&lt;/li&gt;
&lt;/ul&gt;

&lt;h4 id=&quot;准备&quot;&gt;准备&lt;/h4&gt;

&lt;p&gt;要使用 cc，你需要准备：&lt;/p&gt;
&lt;ol&gt;
  &lt;li&gt;一个稳定的梯子&lt;/li&gt;
  &lt;li&gt;Claude Pro 订阅的 Claude 账号&lt;/li&gt;
&lt;/ol&gt;

&lt;h4 id=&quot;安装与代理配置&quot;&gt;安装与代理配置&lt;/h4&gt;

&lt;p&gt;你可以使用下面的命令安装 cc：&lt;/p&gt;

&lt;div class=&quot;language-shell highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;table class=&quot;rouge-table&quot;&gt;&lt;tbody&gt;&lt;tr&gt;
&lt;td class=&quot;rouge-gutter gl&quot;&gt;&lt;pre class=&quot;lineno&quot;&gt;1
&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&quot;rouge-code&quot;&gt;&lt;pre&gt;npm &lt;span class=&quot;nb&quot;&gt;install&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-g&lt;/span&gt; @anthropic-ai/claude-code
&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;由于终端不走系统代理，如果你没有开全局代理或者 TUN 模式，需要为终端配置代理。切记一定要配置好代理，否则可能因为 IP 问题被封号（A 社封号相当严格）。&lt;/p&gt;

&lt;p&gt;在终端执行以下命令，根据你的代理工具修改端口号：&lt;/p&gt;

&lt;div class=&quot;language-shell highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;table class=&quot;rouge-table&quot;&gt;&lt;tbody&gt;&lt;tr&gt;
&lt;td class=&quot;rouge-gutter gl&quot;&gt;&lt;pre class=&quot;lineno&quot;&gt;1
2
3
&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&quot;rouge-code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;nb&quot;&gt;export &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;HTTPS_PROXY&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;http://127.0.0.1:6152
&lt;span class=&quot;nb&quot;&gt;export &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;HTTP_PROXY&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;http://127.0.0.1:6152
&lt;span class=&quot;nb&quot;&gt;export &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;ALL_PROXY&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;socks5://127.0.0.1:6153
&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;如果不想每次都输入以上三条命令，也可以直接在 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;~/.claude/settings.json&lt;/code&gt; 中配置：&lt;/p&gt;

&lt;div class=&quot;language-json highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;table class=&quot;rouge-table&quot;&gt;&lt;tbody&gt;&lt;tr&gt;
&lt;td class=&quot;rouge-gutter gl&quot;&gt;&lt;pre class=&quot;lineno&quot;&gt;1
2
3
4
5
6
7
&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&quot;rouge-code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;env&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
	    &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;HTTP_PROXY&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;http://127.0.0.1:6152&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
	    &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;HTTPS_PROXY&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;http://127.0.0.1:6152&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
	    &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;ALL_PROXY&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;socks5://127.0.0.1:6153&quot;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h4 id=&quot;登录&quot;&gt;登录&lt;/h4&gt;

&lt;p&gt;整个登录流程如下：&lt;/p&gt;
&lt;ol&gt;
  &lt;li&gt;运行 cc：&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;claude&lt;/code&gt;
&lt;/li&gt;
  &lt;li&gt;首次运行，cc 会提示你选择主题，然后进入登录页面。&lt;/li&gt;
  &lt;li&gt;登录时选择“Claude account with subscription”，使用订阅账号登录。&lt;/li&gt;
  &lt;li&gt;cc 会自动打开浏览器让你登录 Claude 账号。如果在远端服务器上运行 cc，稍等一小会之后，cc 会给你一个临时链接，你可以在本地机器上用浏览器打开这个链接，登录 Claude 账号。在浏览器登录账号之后，屏幕上会显示一个授权码（code），把它粘贴到终端中并回车，即可完成远端服务器上 cc 的登录。&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;登录成功后，你可以直接在对话框中与 Claude 交互。不过，要实际在项目中高效地使用它编程，我们还需要先进行一番配置。&lt;/p&gt;

&lt;h3 id=&quot;配置&quot;&gt;配置&lt;/h3&gt;

&lt;p&gt;要在项目中使用 cc，你需要先 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;cd&lt;/code&gt; 到项目根目录，然后再运行 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;claude&lt;/code&gt;。在运行之前，我推荐先配置好项目的 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;CLAUDE.md&lt;/code&gt; 以及 MCP，这能极大增强 AI Agent 的能力。&lt;/p&gt;

&lt;h4 id=&quot;claudemd&quot;&gt;CLAUDE.md&lt;/h4&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;CLAUDE.md&lt;/code&gt; 是 Agent 的记忆文件，每次会话开始时都会自动载入上下文。你既可以在 cc 中直接使用 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/init&lt;/code&gt; 生成，也可以在项目根目录下手动创建。&lt;/p&gt;

&lt;p&gt;如果想自己动手，但又不知道从何写起，你可以参考&lt;a href=&quot;https://www.anthropic.com/engineering/claude-code-best-practices&quot;&gt;官方最佳实践教程&lt;/a&gt;中推荐的 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;CLAUDE.md&lt;/code&gt; 内容：&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;Common bash commands（常用 bash 命令）&lt;/li&gt;
  &lt;li&gt;Core files and utility functions（核心文件、函数）&lt;/li&gt;
  &lt;li&gt;Code style guidelines（编码规范）&lt;/li&gt;
  &lt;li&gt;Testing instructions（测试指令）&lt;/li&gt;
  &lt;li&gt;Repository etiquette (e.g., branch naming, merge vs. rebase, etc.)（仓库规范）&lt;/li&gt;
  &lt;li&gt;Developer environment setup (e.g., pyenv use, which compilers work)（开发者环境配置）&lt;/li&gt;
  &lt;li&gt;Any unexpected behaviors or warnings particular to the project（项目中的异常行为或者警告）&lt;/li&gt;
  &lt;li&gt;Other information you want Claude to remember（其它你想要让 cc 记住的信息）&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;你还可以参考 Gemini CLI Repo 下的 &lt;a href=&quot;https://github.com/google-gemini/gemini-cli/blob/main/GEMINI.md&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;GEMINI.md&lt;/code&gt;&lt;/a&gt;，两者的作用是一样的。下文我也会分享我写 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;CLAUDE.md&lt;/code&gt; 的方法论和心得。&lt;/p&gt;

&lt;p&gt;CLAUDE.md 支持项目级（在项目根目录）和系统级（在 ~/.claude/ 目录）两种配置。你可以把跨项目的规则写到系统级配置中。&lt;/p&gt;

&lt;h4 id=&quot;mcp&quot;&gt;MCP&lt;/h4&gt;

&lt;p&gt;MCP 的作用以及我推荐的一些 MCP 服务器我在 &lt;a href=&quot;https://huangboming.com/posts/cursor-vibe-coding/&quot;&gt;Cursor Vibe Coding 心得分享&lt;/a&gt;已经分享过，在这里就不再赘述。&lt;/p&gt;

&lt;p&gt;在 cc 中，你同样可以为项目级（在项目根目录创建 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.mcp.json&lt;/code&gt;）和系统级（配置 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;~/claude.json&lt;/code&gt;）配置 MCP。&lt;/p&gt;

&lt;p&gt;以下是一个配置示例：&lt;/p&gt;

&lt;div class=&quot;language-json highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;table class=&quot;rouge-table&quot;&gt;&lt;tbody&gt;&lt;tr&gt;
&lt;td class=&quot;rouge-gutter gl&quot;&gt;&lt;pre class=&quot;lineno&quot;&gt;1
2
3
4
5
6
7
8
9
10
11
12
&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&quot;rouge-code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
  &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;mcpServers&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;context7&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
      &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;command&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;npx&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
      &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;args&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;-y&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;@upstash/context7-mcp&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;mcp-feedback-enhanced&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
      &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;command&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;uvx&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
      &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;args&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;mcp-feedback-enhanced@latest&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
  &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;你也可以使用 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;claude mcp add&lt;/code&gt; 命令来配置 MCP 服务器，具体可以参考官方文档：&lt;a href=&quot;https://docs.anthropic.com/en/docs/claude-code/mcp&quot;&gt;Model Context Protocol (MCP)&lt;/a&gt;。&lt;/p&gt;

&lt;p&gt;配置好之后，你可以使用 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;claude mcp list&lt;/code&gt; 来检查 MCP 服务器连接状态。&lt;/p&gt;

&lt;h2 id=&quot;实战技巧与心得&quot;&gt;实战技巧与心得&lt;/h2&gt;

&lt;h3 id=&quot;书写-claudemd&quot;&gt;书写 CLAUDE.md&lt;/h3&gt;

&lt;p&gt;虽然可以直接使用 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/init&lt;/code&gt; 一键生成，但我一般喜欢自己写 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;CLAUDE.md&lt;/code&gt;，可以定制化程度和可玩性都更高。&lt;/p&gt;

&lt;p&gt;在实践中，我摸索出一套 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;CLAUDE.md&lt;/code&gt; 模板结构：&lt;/p&gt;

&lt;div class=&quot;language-markdown highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;table class=&quot;rouge-table&quot;&gt;&lt;tbody&gt;&lt;tr&gt;
&lt;td class=&quot;rouge-gutter gl&quot;&gt;&lt;pre class=&quot;lineno&quot;&gt;1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&quot;rouge-code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;gh&quot;&gt;# 项目开发指南&lt;/span&gt;

&lt;span class=&quot;gu&quot;&gt;## 工程师角色&lt;/span&gt;

你是一个【角色】，擅长【技术栈】。

&lt;span class=&quot;gu&quot;&gt;### 工作流程&lt;/span&gt;

【工作流程】

&lt;span class=&quot;gu&quot;&gt;### 要求&lt;/span&gt;

【要求】

&lt;span class=&quot;gu&quot;&gt;### 技术栈要求&lt;/span&gt;

【项目技术栈】

&lt;span class=&quot;gu&quot;&gt;## 项目架构概述&lt;/span&gt;

【项目架构】

&lt;span class=&quot;gu&quot;&gt;## 常用命令&lt;/span&gt;

【常用命令】

&lt;span class=&quot;gu&quot;&gt;## 编码规范&lt;/span&gt;

【编码规范】
&lt;span class=&quot;p&quot;&gt;
---
&lt;/span&gt;
【其它】

&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;每个参数解释如下：&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;【角色】：为 AI 定义角色，比如“世界级的全栈工程师”、“世界级的前端工程师”&lt;/li&gt;
  &lt;li&gt;【技术栈】：大方向上的技术栈，比如 React、Python、Rust&lt;/li&gt;
  &lt;li&gt;【工作流程】：定义 AI 的工作流程。我在 &lt;a href=&quot;https://huangboming.com/posts/cursor-vibe-coding/&quot;&gt;Cursor Vibe Coding 心得分享&lt;/a&gt;中分享过一些工作流程，比如 RIPER5、基于任务拆解的工作流。&lt;/li&gt;
  &lt;li&gt;【要求】：你对 AI 的要求。比如“使用简体中文回复”、“一定要多使用 interactive_feedback 工具多向我反馈、报告工作以及下一步任务。”&lt;/li&gt;
  &lt;li&gt;【项目技术栈】：具体的技术栈，比如：
    &lt;ul&gt;
      &lt;li&gt;语言：Python 3.11
        &lt;ul&gt;
          &lt;li&gt;依赖管理：&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;uv&lt;/code&gt;
&lt;/li&gt;
          &lt;li&gt;测试框架：&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;pytest&lt;/code&gt;
&lt;/li&gt;
          &lt;li&gt;代码质量：&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ruff&lt;/code&gt;
&lt;/li&gt;
        &lt;/ul&gt;
      &lt;/li&gt;
      &lt;li&gt;配置管理：python-dotenv&lt;/li&gt;
      &lt;li&gt;Web 框架：FastAPI&lt;/li&gt;
      &lt;li&gt;数据校验：Pydantic&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;【项目架构】：简单介绍项目架构，比如有哪些服务、前端是什么、后端是什么、它们怎么通信。也可以是文件夹目录说明&lt;/li&gt;
  &lt;li&gt;【常用命令】：项目中常用的命令及其含义。一定要有！一定要有！一定要有！如果没有 AI 会乱猜，执行一些奇怪的命令，很浪费时间和 token。比如：
    &lt;ul&gt;
      &lt;li&gt;在 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;frontend&lt;/code&gt; 目录下：
        &lt;ul&gt;
          &lt;li&gt;
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;npm run dev&lt;/code&gt;：启动前端项目&lt;/li&gt;
          &lt;li&gt;
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;npm run build&lt;/code&gt;：构建前端项目&lt;/li&gt;
          &lt;li&gt;
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;npm run lint&lt;/code&gt;：执行 ESLint&lt;/li&gt;
        &lt;/ul&gt;
      &lt;/li&gt;
      &lt;li&gt;在 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;backend&lt;/code&gt; 目录下：
        &lt;ul&gt;
          &lt;li&gt;
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;uv sync --all-groups&lt;/code&gt;：更新依赖（包含开发用的所有依赖）&lt;/li&gt;
          &lt;li&gt;
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;uv run pytest&lt;/code&gt;：运行测试&lt;/li&gt;
        &lt;/ul&gt;
      &lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;【编码规范】：定义编码规范。我一般会用 &lt;a href=&quot;https://huangboming.com/posts/aesthetics-and-prompting/&quot;&gt;审美与提示词书写&lt;/a&gt; 中的方法写一套编码规范。&lt;/li&gt;
  &lt;li&gt;【其它】：其它想要添加的部分。比如，如果是一个前端项目，我会写一份 UI/UX 设计规范。&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;plan-mode&quot;&gt;Plan mode&lt;/h3&gt;

&lt;p&gt;在 cc 中，连按两次 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;shift + tab&lt;/code&gt; 可以进入 Plan mode（规划模式）。在规划模式下，cc 会自动理解需求、搜集相关代码，然后做出一份行动计划，并根据行动计划执行。&lt;/p&gt;

&lt;p&gt;简而言之，如果你还没有形成自己的工作流，Plan mode 是一个很好的起点。但如果你已有一套成熟的方法论，直接按自己的节奏来，效率可能更高。&lt;/p&gt;

&lt;h3 id=&quot;上下文管理&quot;&gt;上下文管理&lt;/h3&gt;

&lt;p&gt;在 &lt;a href=&quot;https://huangboming.com/posts/cursor-vibe-coding/&quot;&gt;Cursor Vibe Coding 心得分享&lt;/a&gt;中，我提到过，上下文管理是所有 AI 编程工具的核心。cc 也不例外。&lt;/p&gt;

&lt;p&gt;除了常用的清空上下文窗口（&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/clear&lt;/code&gt;）之外，cc 提供了强大的 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/compact&lt;/code&gt; 命令。它能压缩当前上下文窗口中所有对话的内容，生成一份总结，并在一个全新的会话中载入总结，实现信息压缩、流转。&lt;/p&gt;

&lt;p&gt;这个功能对于复杂的多阶段任务尤其有用。比如，一个需求需要被拆解成五个开发阶段。传统做法是，先制定一份开发计划，然后每个阶段都开启一个新会话，将计划放入上下文，并在提示词中指明当前进度与后续任务。&lt;/p&gt;

&lt;p&gt;而有了 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/compact&lt;/code&gt;，工作流就变得更流畅：它会自动提炼当前会话的核心信息（如初始需求、任务进度等），带到下一个会话中。这个流程就简化为：&lt;/p&gt;
&lt;ol&gt;
  &lt;li&gt;提出需求，让 AI 理解需求、拆解开发任务&lt;/li&gt;
  &lt;li&gt;
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/compact&lt;/code&gt;，执行第一阶段任务&lt;/li&gt;
  &lt;li&gt;确认第一阶段任务无误之后，&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/compact&lt;/code&gt;，继续执行第二阶段任务&lt;/li&gt;
  &lt;li&gt;确认第二阶段任务无误之后，&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/compact&lt;/code&gt;，继续执行第三阶段任务&lt;/li&gt;
  &lt;li&gt;以此类推，直到任务完成&lt;/li&gt;
&lt;/ol&gt;

&lt;h3 id=&quot;用量查看&quot;&gt;用量查看&lt;/h3&gt;

&lt;p&gt;&lt;a href=&quot;https://github.com/ryoppippi/ccusage&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ccusage&lt;/code&gt;&lt;/a&gt; 是一个用于查看、监控 cc 用量的命令行工具。&lt;/p&gt;

&lt;div class=&quot;language-shell highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;table class=&quot;rouge-table&quot;&gt;&lt;tbody&gt;&lt;tr&gt;
&lt;td class=&quot;rouge-gutter gl&quot;&gt;&lt;pre class=&quot;lineno&quot;&gt;1
2
3
4
5
6
7
8
&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&quot;rouge-code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;c&quot;&gt;# 安装 ccusage&lt;/span&gt;
npm &lt;span class=&quot;nb&quot;&gt;install&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-g&lt;/span&gt; ccusage

&lt;span class=&quot;c&quot;&gt;# 比较常用的命令&lt;/span&gt;
ccusage  &lt;span class=&quot;c&quot;&gt;# 查看每日用量&lt;/span&gt;
ccusage monthly  &lt;span class=&quot;c&quot;&gt;# 查看每月用量&lt;/span&gt;
ccusage session  &lt;span class=&quot;c&quot;&gt;# 查看每个项目的用量&lt;/span&gt;
ccusage blocks &lt;span class=&quot;nt&quot;&gt;--live&lt;/span&gt;  &lt;span class=&quot;c&quot;&gt;# 实时监控用量&lt;/span&gt;
&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;更多用法可以参考&lt;a href=&quot;https://github.com/ryoppippi/ccusage#usage&quot;&gt;官方文档&lt;/a&gt;。&lt;/p&gt;

&lt;p&gt;目前 cc 的用量上限规则为：&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;一个 cc 用量窗口（session）持续 5 小时。也就是说，5 小时重置一次用量。&lt;/li&gt;
  &lt;li&gt;用量窗口以整小时为单位。假设你 8:55 发送第一条消息，那么用量窗口为 8:00 - 13:00.&lt;/li&gt;
  &lt;li&gt;Anthropic 会根据服务器负载来决定用户用量。对于 Claude Pro 用户，一般一个用量窗口可以用 $5-10&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;不过最近我收到一封来自 Anthropic 的邮件，他们将在八月底调整用量规则，在五小时重置的基础上引入每周使用限制。&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Starting August 28, we’re introducing weekly usage limits alongside our existing 5-hour limits:&lt;/p&gt;
  &lt;ul&gt;
    &lt;li&gt;
&lt;strong&gt;Current&lt;/strong&gt;: Usage limit that resets every 5 hours (no change)&lt;/li&gt;
    &lt;li&gt;
&lt;strong&gt;New&lt;/strong&gt;: Overall weekly limit that resets every 7 days&lt;/li&gt;
    &lt;li&gt;
&lt;strong&gt;New&lt;/strong&gt;: Claude Opus 4 weekly limit that resets every 7 days&lt;/li&gt;
    &lt;li&gt;As we learn more about how developers use Claude Code, we may adjust usage limits to better serve our community.&lt;/li&gt;
  &lt;/ul&gt;
&lt;/blockquote&gt;

&lt;p&gt;中文翻译：从八月二十八日开始，我们将在现有 5 小时使用限制的基础上，引入每周使用限制：&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;当前：每 5 小时重置一次的使用限制（保持不变）&lt;/li&gt;
  &lt;li&gt;新增：每 7 天重置一次的总体每周限制&lt;/li&gt;
  &lt;li&gt;新增：每 7 天重置一次的 Claude Opus 4 每周限制
随着我们对开发者如何使用 Claude Code 了解更多，我们可能会调整使用限制，以便更好地服务我们的社区。&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;现在还不知道每周限制具体限多少，Anthropic 认为“Most Pro users can expect 40-80 hours of Sonnet 4 within their weekly rate limits.”（在新的每周限制下，大部分 Pro 用户一周可以使用 40-80 小时的 Sonnet 4）。具体影响有待观察，希望不要限得太死。&lt;/p&gt;

&lt;p&gt;我强烈推荐在使用 cc 时，在另一个终端窗口运行 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ccusage blocks --live&lt;/code&gt; 实时监控用量。这能帮你根据剩余用量动态调整任务预期——额度充裕时，放心让它执行复杂任务；额度见底时，则让它做一些简单任务，避免任务执行到一半因为用尽额度而中断。&lt;/p&gt;

&lt;h3 id=&quot;其它奇怪玩法&quot;&gt;其它奇怪玩法&lt;/h3&gt;

&lt;p&gt;在实践中，我发现 CLI 类 AI 编程工具（比如 cc、Gemini CLI）的用法并不仅限于编程。核心思想是，把它看作一个可以访问、修改你电脑上的文件，并且可以运行命令行工具的 AI Agent。基于这个想法，你可以发展出很多玩法。&lt;/p&gt;

&lt;p&gt;比如，用 AI 写一份月总结：&lt;/p&gt;

&lt;div class=&quot;language-shell highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;table class=&quot;rouge-table&quot;&gt;&lt;tbody&gt;&lt;tr&gt;
&lt;td class=&quot;rouge-gutter gl&quot;&gt;&lt;pre class=&quot;lineno&quot;&gt;1
&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&quot;rouge-code&quot;&gt;&lt;pre&gt;claude &lt;span class=&quot;nt&quot;&gt;-p&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;请你使用 &lt;/span&gt;&lt;span class=&quot;sb&quot;&gt;`&lt;/span&gt;git log &lt;span class=&quot;nt&quot;&gt;--author&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;$(&lt;/span&gt;git config user.name&lt;span class=&quot;si&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;sb&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt; 查看我这个月提交的所有 commit，并做一份月总结&quot;&lt;/span&gt;
&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;或者，&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;cd&lt;/code&gt; 到 Obsidian Vault 文件夹下，让它可以访问、修改 Obsidian 笔记，或者搜索相关笔记并回答。&lt;/p&gt;

&lt;h2 id=&quot;常用命令快捷键汇总&quot;&gt;常用命令、快捷键汇总&lt;/h2&gt;

&lt;h3 id=&quot;常用命令&quot;&gt;常用命令&lt;/h3&gt;

&lt;ul&gt;
  &lt;li&gt;基础：
    &lt;ul&gt;
      &lt;li&gt;
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;claude&lt;/code&gt;：运行 cc&lt;/li&gt;
      &lt;li&gt;
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;claude -c&lt;/code&gt;：继续上一个会话&lt;/li&gt;
      &lt;li&gt;
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;claude -r&lt;/code&gt;：继续之前的某一个会话（会进入一个窗口让你选择某个之前的会话）&lt;/li&gt;
      &lt;li&gt;
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;claude --dangerously-skip-permissions&lt;/code&gt;：运行 cc，并进入 YOLO 模式（自动同意 Agent 的所有操作）&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;MCP 相关：
    &lt;ul&gt;
      &lt;li&gt;
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;claude mcp add&lt;/code&gt;：添加 MCP 服务器&lt;/li&gt;
      &lt;li&gt;
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;claude mcp list&lt;/code&gt;：检查 MCP 服务器状态&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;检查 &amp;amp; 更新：
    &lt;ul&gt;
      &lt;li&gt;
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;claude doctor&lt;/code&gt;：检查 cc 状态&lt;/li&gt;
      &lt;li&gt;
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;claude update&lt;/code&gt;：更新 cc&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;常用快捷键&quot;&gt;常用快捷键&lt;/h3&gt;

&lt;ul&gt;
  &lt;li&gt;
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ctrc + c&lt;/code&gt;：
    &lt;ul&gt;
      &lt;li&gt;按下一次 = 清空输入框&lt;/li&gt;
      &lt;li&gt;连按两次 = 退出 cc&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;esc&lt;/code&gt;：
    &lt;ul&gt;
      &lt;li&gt;在 AI 执行任务时，单击 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;esc&lt;/code&gt; 打断 AI&lt;/li&gt;
      &lt;li&gt;双击 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;esc&lt;/code&gt;：
        &lt;ul&gt;
          &lt;li&gt;如果输入框中有内容，双击 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;esc&lt;/code&gt; 效果为清空输入框&lt;/li&gt;
          &lt;li&gt;如果输入框中没有内容，双击 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;esc&lt;/code&gt; 效果为跳到当前会话中某个之前的对话，从该处开始重新对话&lt;/li&gt;
        &lt;/ul&gt;
      &lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;shift + tab&lt;/code&gt;：用于状态切换
    &lt;ol&gt;
      &lt;li&gt;默认为正常模式&lt;/li&gt;
      &lt;li&gt;使用一次切换至 auto-accept edit mode：自动同意 AI 编辑的操作&lt;/li&gt;
      &lt;li&gt;再使用一次切换至 plan mode：规划模式，用于写代码前的规划&lt;/li&gt;
      &lt;li&gt;再使用一次切回正常模式&lt;/li&gt;
    &lt;/ol&gt;
  &lt;/li&gt;
  &lt;li&gt;
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ctrl + r&lt;/code&gt;：切换到详细输出模式。可以看到 cc 具体读了哪些代码，具体的输出。不过，个人感觉也不是很详细，聊胜于无&lt;/li&gt;
  &lt;li&gt;
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;option + 回车&lt;/code&gt;：换行&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;常用-slash-命令&quot;&gt;常用 slash 命令&lt;/h3&gt;

&lt;ul&gt;
  &lt;li&gt;
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/init&lt;/code&gt;：为项目初始化一份 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;CLAUDE.md&lt;/code&gt;
&lt;/li&gt;
  &lt;li&gt;
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/clear&lt;/code&gt;：清空所有上下文，开始新会话&lt;/li&gt;
  &lt;li&gt;
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/compact&lt;/code&gt;：压缩上下文并开始新会话。cc 会生成一份当前会话的总结，并将这份总结
作为下一个会话的开始&lt;/li&gt;
  &lt;li&gt;
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/model&lt;/code&gt;：&lt;/li&gt;
  &lt;li&gt;
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/mcp&lt;/code&gt;：查看当前 MCP 服务器状态&lt;/li&gt;
  &lt;li&gt;
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/help&lt;/code&gt;：查询所有可用 slash 命令&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;结语&quot;&gt;结语&lt;/h2&gt;

&lt;p&gt;我在这篇文章中分享了近期使用 cc 的一些心得和常用操作。实际上，cc 还有许多更高级的用法，比如&lt;a href=&quot;https://docs.anthropic.com/en/docs/claude-code/slash-commands&quot;&gt;自定义 slash command&lt;/a&gt;、&lt;a href=&quot;https://docs.anthropic.com/en/docs/claude-code/hooks&quot;&gt;Hooks&lt;/a&gt;、以及最近刚出的 &lt;a href=&quot;https://docs.anthropic.com/en/docs/claude-code/sub-agents&quot;&gt;Subagents&lt;/a&gt;。这些功能可以进一步扩展 cc 的能力，实现更自动化、更智能的开发流程。&lt;/p&gt;

&lt;p&gt;目前我也在摸索这些功能的用法，后续如果我发现好玩的用法，我也会分享给大家。&lt;/p&gt;
</content>
  </entry>
  
    
    
    
    
  <entry>
    <title>审美与提示词书写</title>
    <id>https://huangboming.com/posts/aesthetics-and-prompting/</id>
    <link rel="alternate" type="text/html" href="https://huangboming.com/posts/aesthetics-and-prompting/" />
    <published>2025-07-21T00:00:00+08:00</published>
    <updated>2026-07-16T00:13:32+08:00</updated>
    <author>
      <name>Boming Huang</name>
      <uri>https://huangboming.com/about/</uri>
    </author>
    <category term="心得" />
    <summary type="text">分享将隐性的审美标准转化为显性提示词指令的方法</summary>
    <content type="html" xml:base="https://huangboming.com/posts/aesthetics-and-prompting/">&lt;p&gt;在使用 AI 时，我们常常遇到这样的情况：明明给出详细的指令，但 AI 生成的结果质量却不稳定——有时让人眼前一亮，但有时却不尽如人意。它给出的结果或许正确，但是不那么好。例如，让 AI 翻译一篇文章，它可能给出一份语法正确但生硬的译文。&lt;/p&gt;

&lt;p&gt;我认为，问题的关键在于&lt;strong&gt;我们只告诉 AI 要做什么，但是没有界定“怎么才算做得好”&lt;/strong&gt;。我们内心深处有一套关于“好”与“美”的评判标准，但我们没有将其清晰地传达给 AI。&lt;/p&gt;

&lt;p&gt;在这篇文章中，我想分享如何将我们脑中那些模糊、隐性的审美标准，转化为可执行的指令，融入到提示词中，从而提高 AI 的输出质量。&lt;/p&gt;

&lt;h2 id=&quot;何谓审美&quot;&gt;何谓审美&lt;/h2&gt;

&lt;p&gt;关于审美，我个人有一个朴素的定义：&lt;strong&gt;审美就是知道什么是好的、什么是不好的。&lt;/strong&gt;“而什么是好的、什么是不好的”便构成了一套审美标准。&lt;/p&gt;

&lt;p&gt;例如，翻译家严复曾经提出一套翻译标准&lt;a href=&quot;https://zh.wikipedia.org/zh-hans/%E4%BF%A1%E8%BE%BE%E9%9B%85&quot;&gt;“信、达、雅”&lt;/a&gt;，它清晰地界定了“好的译文”应该具备的特质：&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;信：译文要忠实于原文，内容准确，不歪曲、不遗漏原文的意思&lt;/li&gt;
  &lt;li&gt;达：译文要通顺流畅，符合目的语的表达习惯，使读者易于理解&lt;/li&gt;
  &lt;li&gt;雅：译文的文字要优美典雅，具有较高的艺术性和审美价值，追求原文的神韵&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;再如，&lt;a href=&quot;https://peps.python.org/pep-0020/&quot;&gt;The Zen of Python&lt;/a&gt; 也是一套审美标准，它定义了什么是好的代码，什么是不好的代码：&lt;/p&gt;

&lt;div class=&quot;language-shell highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;table class=&quot;rouge-table&quot;&gt;&lt;tbody&gt;&lt;tr&gt;
&lt;td class=&quot;rouge-gutter gl&quot;&gt;&lt;pre class=&quot;lineno&quot;&gt;1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&quot;rouge-code&quot;&gt;&lt;pre&gt;❯ python3 &lt;span class=&quot;nt&quot;&gt;-m&lt;/span&gt; this
The Zen of Python, by Tim Peters

Beautiful is better than ugly.
Explicit is better than implicit.
Simple is better than complex.
Complex is better than complicated.
Flat is better than nested.
Sparse is better than dense.
Readability counts.
Special cases aren&lt;span class=&quot;s1&quot;&gt;&apos;t special enough to break the rules.
Although practicality beats purity.
Errors should never pass silently.
Unless explicitly silenced.
In the face of ambiguity, refuse the temptation to guess.
There should be one-- and preferably only one --obvious way to do it.
Although that way may not be obvious at first unless you&apos;&lt;/span&gt;re Dutch.
Now is better than never.
Although never is often better than &lt;span class=&quot;k&quot;&gt;*&lt;/span&gt;right&lt;span class=&quot;k&quot;&gt;*&lt;/span&gt; now.
If the implementation is hard to explain, it&lt;span class=&quot;s1&quot;&gt;&apos;s a bad idea.
If the implementation is easy to explain, it may be a good idea.
Namespaces are one honking great idea -- let&apos;&lt;/span&gt;s &lt;span class=&quot;k&quot;&gt;do &lt;/span&gt;more of those!
&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;如何将审美标准融入提示词&quot;&gt;如何将审美标准融入提示词&lt;/h2&gt;

&lt;p&gt;要将审美标准融入提示词，核心在于将隐性审美标准转化为显性指令，最好能给出一些实践要点，方便 AI 理解与执行。以上述“信、达、雅”为例，它可以细化为：&lt;/p&gt;

&lt;div class=&quot;language-markdown highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;table class=&quot;rouge-table&quot;&gt;&lt;tbody&gt;&lt;tr&gt;
&lt;td class=&quot;rouge-gutter gl&quot;&gt;&lt;pre class=&quot;lineno&quot;&gt;1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&quot;rouge-code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;gu&quot;&gt;### 信&lt;/span&gt;

“信”意味着忠实于原文的内容、思想、情感、风格和语气。译者需要像一个侦探，深入理解作者为什么要用这个词，这句话背后隐藏的情感和立场是什么。

要点：
&lt;span class=&quot;p&quot;&gt;-&lt;/span&gt; 保证信息完整，不能随意增删、扭曲原文的信息。无论是事实、数据，还是微妙的情感色彩，都应尽可能完整地传达。
&lt;span class=&quot;p&quot;&gt;-&lt;/span&gt; 保证风格一致。原文是诙谐的，译文就不应是严肃的；原文是古朴的，译文就不应是现代的。译者需要把握原作的整体风格，并在译文中复现。

&lt;span class=&quot;gu&quot;&gt;### 达&lt;/span&gt;

“达”意味着译文通顺流畅，符合目标语言的阅读习惯。行文流畅，宛若原创，这是“达”的理想状态。

一个优秀的译者必然是一个文化使者。他需要处理原文中特有的文化元素（如典故、习俗、俚语）。一篇充满了翻译腔（欧式句法、生硬词汇）的译文，即使每个词的意思都对，也算不上“达”。译文必须读起来地道，自然、流畅，没有生涩之感。好的译文能让读者跨越文化鸿沟，与作品产生共鸣。

要点：
&lt;span class=&quot;p&quot;&gt;-&lt;/span&gt; 译文必须确保逻辑通顺，让读者能够毫不费力地理解内容。
&lt;span class=&quot;p&quot;&gt;-&lt;/span&gt; 当原文中出现目标读者不熟悉的文化典故、习语时（例如，英文中的 &quot;It&apos;s raining cats and dogs.&quot;），好的译者不会直译为“下猫下狗”，而是会采取读者能理解的方式进行处理，如意译为“倾盆大雨”，或在必要时加以注释，帮助读者理解文化背景。

&lt;span class=&quot;gu&quot;&gt;### 雅&lt;/span&gt;

“雅”是在“信”和&quot;达”的基础上，追求文字的精炼和美感。

要点：
&lt;span class=&quot;p&quot;&gt;-&lt;/span&gt; 注意文字的韵律与节奏：美的译文是有音律感的。长短句的交错、词语的搭配、声调的和谐，都会影响阅读的体验。尤其在文学、诗歌翻译中，译者需要像音乐家一样，组织语言的节奏和韵律。
&lt;span class=&quot;p&quot;&gt;-&lt;/span&gt; 对词语的精挑细选，力求用最精准、最富表现力、最有意境的词汇来还原原文的神采
&lt;span class=&quot;p&quot;&gt;-&lt;/span&gt; 营造意境：美的译文能够超越字面，将原文的画面感、氛围和弦外之音巧妙地传达给读者，引发读者的联想和共鸣。
&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;当我们把审美标准显化成具体指令之后，我们就可以把指令融入提示词中。我在实践中总结出两套方法：&lt;/p&gt;
&lt;ol&gt;
  &lt;li&gt;直接插入提示词末尾&lt;/li&gt;
  &lt;li&gt;借助 AI 融合提示词&lt;/li&gt;
&lt;/ol&gt;

&lt;h3 id=&quot;方法一直接插入提示词&quot;&gt;方法一：直接插入提示词&lt;/h3&gt;

&lt;p&gt;针对简单场景，可以直接把审美标准直接置于提示词末尾。&lt;/p&gt;

&lt;p&gt;例如，针对翻译任务的提示词为：&lt;/p&gt;

&lt;div class=&quot;language-markdown highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;table class=&quot;rouge-table&quot;&gt;&lt;tbody&gt;&lt;tr&gt;
&lt;td class=&quot;rouge-gutter gl&quot;&gt;&lt;pre class=&quot;lineno&quot;&gt;1
2
3
4
5
6
7
8
9
&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&quot;rouge-code&quot;&gt;&lt;pre&gt;请你将下面的文章翻译成中文，务必遵循最后的翻译守则。
&lt;span class=&quot;p&quot;&gt;
---&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;&amp;lt;文章内容&amp;gt;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;
---&lt;/span&gt;
&lt;span class=&quot;gh&quot;&gt;# 翻译守则&lt;/span&gt;

&lt;span class=&quot;nt&quot;&gt;&amp;lt;关于翻译的审美标准&amp;gt;&lt;/span&gt;
&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;这种方法同样适用于各类 AI 编程软件的配置文件，比如 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;CLAUDE.md&lt;/code&gt;、&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;GEMINI.md&lt;/code&gt; 或者 Cursor rules。你可以把关于“好代码库”、“好 UI/UX”等标准直接写入其中，让 AI 在每一次交互中都遵循规范。&lt;/p&gt;

&lt;h3 id=&quot;方法二借助-ai-融合提示词&quot;&gt;方法二：借助 AI 融合提示词&lt;/h3&gt;

&lt;p&gt;对于比较复杂的场景，我更推荐使用 AI 融合提示词——让 AI 基于通用审美标准以及具体任务场景，生成一份更详细、更定制化的提示词。&lt;/p&gt;

&lt;p&gt;例如，我有一套通用的代码库审美标准，我想为一个技术栈为 React + Tauri + Python 的项目编写 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;CLAUDE.md&lt;/code&gt;，我会让 AI 根据代码库审美标准以及技术栈来撰写开发指南。AI 会将通用原则（如“直观的项目结构”、“代码自文档化”）与特定技术栈的最佳实践结合起来，生成一份更详细、更定制化的提示词。&lt;/p&gt;

&lt;p&gt;以下为一个示例片段：&lt;/p&gt;

&lt;div class=&quot;language-markdown highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;table class=&quot;rouge-table&quot;&gt;&lt;tbody&gt;&lt;tr&gt;
&lt;td class=&quot;rouge-gutter gl&quot;&gt;&lt;pre class=&quot;lineno&quot;&gt;1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&quot;rouge-code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;gu&quot;&gt;### 清晰&lt;/span&gt;

代码的首要读者是人。清晰的代码能降低协作成本，加速迭代，并减少错误。

通用：
&lt;span class=&quot;p&quot;&gt;-&lt;/span&gt; 直观的项目结构：文件和目录的组织方式逻辑清晰、一目了然。无论是按功能（Feature）还是按类型（Layer）组织，都应在整个项目中保持一致。遵循“约定优于配置”的原则，让开发者能快速定位到任何代码。
&lt;span class=&quot;p&quot;&gt;-&lt;/span&gt; 代码自文档化：通过语义明确的命名和分层清晰的逻辑架构，让代码本身即是最直接的“文档”。注释只需解释“为什么”，不需重复“做什么”。
&lt;span class=&quot;p&quot;&gt;-&lt;/span&gt; 最小惊奇原则：模块应符合直觉，能合理预测。从而让使用者心里永远不产生“它居然会这样工作”的疑惑。
&lt;span class=&quot;p&quot;&gt;-&lt;/span&gt; 关注专注的单元设计：遵循单一职责原则，避免因过多功能堆叠而产生难理解的“大类”或“多功能函数”。
&lt;span class=&quot;p&quot;&gt;-&lt;/span&gt; 统一代码风格：一致的代码格式和风格规范是团队沟通的共同语言。借助自动化工具可简化执行。

前端：
&lt;span class=&quot;p&quot;&gt;-&lt;/span&gt; 采用功能驱动 (Feature-driven) 的目录结构。将与特定功能相关的所有文件（组件、Hooks、样式、测试）放在同一个文件夹下
&lt;span class=&quot;p&quot;&gt;-&lt;/span&gt; 保持组件简短，专注于渲染。将所有非渲染逻辑（数据获取、事件处理、状态管理）尽可能地抽离到自定义 Hooks 中。
&lt;span class=&quot;p&quot;&gt;-&lt;/span&gt; 导入请使用绝对路径格式（&lt;span class=&quot;sb&quot;&gt;`@/path/to/directory`&lt;/span&gt;），减少维护难度

Tauri：
&lt;span class=&quot;p&quot;&gt;-&lt;/span&gt; 每个 command 都是一个独立的、功能明确的单元。

Python：
&lt;span class=&quot;p&quot;&gt;-&lt;/span&gt; 使用 APIRouter 按业务域组织路由。利用依赖注入系统 (Depends) 将数据库会话、认证逻辑等横切关注点与业务逻辑解耦。
&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;小技巧如何总结一份审美标准&quot;&gt;小技巧：如何总结一份审美标准&lt;/h2&gt;

&lt;p&gt;在我们擅长的领域中，我们往往对“什么是好的”有直觉上的认知。即使不一定能用语言精确地表达，但至少也有一个模糊的印象。此时，可以尝试用名词和形容词描述自己心目中的“美”。哪怕最初只能写下零散的词语，也可以逐步梳理成结构化的要点。当然，也可以直接使用下文提到的 AI 辅助思考方式来归纳总结。&lt;/p&gt;

&lt;p&gt;而在我们不熟悉的领域中，我们对“什么是好的、什么是不好的”缺乏认知。此时我们可以借助 AI 来思考，快速构建出一套审美标准。&lt;/p&gt;

&lt;p&gt;比如，你想让 AI 英译中，可以先询问 AI“从专业的角度看，什么是好的译文”。&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;https://huangboming.com/assets/images/aesthetics-and-prompting/1.png&quot; alt=&quot;AI 回答：什么是好的译文&quot; class=&quot;shadow&quot; w=&quot;700&quot; h=&quot;731&quot;&gt;
&lt;em&gt;AI 回答：什么是好的译文&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;再比如，假设你想让 AI 写代码或者审查代码，可以询问 AI “从专业的角度来看，什么是好的代码库”。&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;https://huangboming.com/assets/images/aesthetics-and-prompting/2.png&quot; alt=&quot;AI 回答：什么是好的代码库&quot; class=&quot;shadow&quot; w=&quot;700&quot; h=&quot;730&quot;&gt;
&lt;em&gt;AI 回答：什么是好的代码库&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;你可以多生成几次，多问几个模型。从每个模型的回答中提取出符合你审美的部分，加以整合，便能得到一份属于你的审美标准。&lt;/strong&gt;建议把它整理成文档，方便后续使用以及迭代优化。&lt;/p&gt;

&lt;p&gt;以下是我根据 AI 回答整理的一份关于翻译的审美标准：&lt;/p&gt;

&lt;div class=&quot;language-markdown highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;table class=&quot;rouge-table&quot;&gt;&lt;tbody&gt;&lt;tr&gt;
&lt;td class=&quot;rouge-gutter gl&quot;&gt;&lt;pre class=&quot;lineno&quot;&gt;1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&quot;rouge-code&quot;&gt;&lt;pre&gt;好的译文：
&lt;span class=&quot;p&quot;&gt;-&lt;/span&gt; 信——对原作，它忠实而深刻
&lt;span class=&quot;p&quot;&gt;-&lt;/span&gt; 达——对读者，它清晰而自然
&lt;span class=&quot;p&quot;&gt;-&lt;/span&gt; 雅——在艺术上，它优雅而得体
&lt;span class=&quot;p&quot;&gt;-&lt;/span&gt; 功能对等——在功能上，它精准而有效

&lt;span class=&quot;gu&quot;&gt;### 信&lt;/span&gt;

“信”意味着忠实于原文的内容、思想、情感、风格和语气。译者需要像一个侦探，深入理解作者为什么要用这个词，这句话背后隐藏的情感和立场是什么。

要点：
&lt;span class=&quot;p&quot;&gt;-&lt;/span&gt; 保证信息完整，不能随意增删、扭曲原文的信息。无论是事实、数据，还是微妙的情感色彩，都应尽可能完整地传达。
&lt;span class=&quot;p&quot;&gt;-&lt;/span&gt; 保证风格一致。原文是诙谐的，译文就不应是严肃的；原文是古朴的，译文就不应是现代的。译者需要把握原作的整体风格，并在译文中复现。

&lt;span class=&quot;gu&quot;&gt;### 达&lt;/span&gt;

“达”意味着译文通顺流畅，符合目标语言的阅读习惯。行文流畅，宛若原创，这是“达”的理想状态。

一个优秀的译者必然是一个文化使者。他需要处理原文中特有的文化元素（如典故、习俗、俚语）。一篇充满了翻译腔（欧式句法、生硬词汇）的译文，即使每个词的意思都对，也算不上“达”。译文必须读起来地道，自然、流畅，没有生涩之感。好的译文能让读者跨越文化鸿沟，与作品产生共鸣。

要点：
&lt;span class=&quot;p&quot;&gt;-&lt;/span&gt; 译文必须确保逻辑通顺，让读者能够毫不费力地理解内容。
&lt;span class=&quot;p&quot;&gt;-&lt;/span&gt; 当原文中出现目标读者不熟悉的文化典故、习语时（例如，英文中的 &quot;It&apos;s raining cats and dogs.&quot;），好的译者不会直译为“下猫下狗”，而是会采取读者能理解的方式进行处理，如意译为“倾盆大雨”，或在必要时加以注释，帮助读者理解文化背景。

&lt;span class=&quot;gu&quot;&gt;### 雅&lt;/span&gt;

“雅”是在“信”和&quot;达”的基础上，求文字的精炼和美感。

要点：
&lt;span class=&quot;p&quot;&gt;-&lt;/span&gt; 注意文字的韵律与节奏：美的译文是有音律感的。长短句的交错、词语的搭配、声调的和谐，都会影响阅读的体验。尤其在文学、诗歌翻译中，译者需要像音乐家一样，组织语言的节奏和韵律。
&lt;span class=&quot;p&quot;&gt;-&lt;/span&gt; 对词语的精挑细选，力求用最精准、最富表现力、最有意境的词汇来还原原文的神采
&lt;span class=&quot;p&quot;&gt;-&lt;/span&gt; 营造意境：美的译文能够超越字面，将原文的画面感、氛围和弦外之音巧妙地传达给读者，引发读者的联想和共鸣。

&lt;span class=&quot;gu&quot;&gt;### 功能对等&lt;/span&gt;

功能对等意味着，一个好的译文，必须实现其预设的功能。它的“好”体现在“恰如其分”。

比如，
&lt;span class=&quot;p&quot;&gt;-&lt;/span&gt; 广告语翻译：目的不是字面对等，而是要在目标市场引起同样的购买欲。耐克的 &quot;Just do it&quot; 翻译成“想做就做”或保留原文，都是基于功能的选择。
&lt;span class=&quot;p&quot;&gt;-&lt;/span&gt; 法律合同翻译：美感和文采完全不重要，极端精准、无歧义才是唯一的美。
&lt;span class=&quot;p&quot;&gt;-&lt;/span&gt; 儿童读物翻译：语言必须符合儿童的认知水平，生动有趣，易于理解。
&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;最后一点想法&quot;&gt;最后一点想法&lt;/h2&gt;

&lt;p&gt;最近 AWS 推出了 AI IDE &lt;a href=&quot;https://kiro.dev&quot;&gt;Kiro&lt;/a&gt;。Kiro 和其它 AI IDE 最大的不同在于它提倡的 &lt;a href=&quot;https://kiro.dev/blog/kiro-and-the-future-of-software-development/&quot;&gt;spec-driven development&lt;/a&gt;（文档驱动开发）。&lt;/p&gt;

&lt;p&gt;当开发者想让 AI 去实现某个功能时，它会先创建详细的一份规格文档（specification），其中包含：&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;Requirements document：定义功能的目标和范围，由一系列关于这个功能的&lt;a href=&quot;https://zh.wikipedia.org/zh-hans/%E7%94%A8%E6%88%B7%E6%95%85%E4%BA%8B&quot;&gt;用户故事&lt;/a&gt;构成&lt;/li&gt;
  &lt;li&gt;Design document：规划技术实现方案&lt;/li&gt;
  &lt;li&gt;Task list：定义开发任务&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;在我看来，审美标准是一种自上而下的标准，而用户故事是一种自下而上的验收标准。审美标准从开发者的角度定义“什么是好，如何做得好”，而用户故事则是从用户的角度定义“开发者需要做什么，从用户的角度来看什么是好”。&lt;/p&gt;

&lt;p&gt;或许我们可以把这两套标准都融入到我们的开发流程中，打造出一个更高效的 AI 辅助编程工作流。&lt;/p&gt;
</content>
  </entry>
  
    
    
    
    
  <entry>
    <title>使用 Docker Context + SSH 访问远端 Docker Daemon</title>
    <id>https://huangboming.com/posts/remote-docker/</id>
    <link rel="alternate" type="text/html" href="https://huangboming.com/posts/remote-docker/" />
    <published>2025-07-01T00:00:00+08:00</published>
    <updated>2026-07-16T00:13:32+08:00</updated>
    <author>
      <name>Boming Huang</name>
      <uri>https://huangboming.com/about/</uri>
    </author>
    <category term="教程" />
    <summary type="text">通过 Docker Context + SSH 让本地 docker 客户端远程操控服务器 dockerd，告别 Docker Desktop 的高内存占用和跨架构编译烦恼。</summary>
    <content type="html" xml:base="https://huangboming.com/posts/remote-docker/">&lt;p&gt;在 Windows 或者 macOS 上使用 Docker Desktop 时，Docker Desktop 会创建一个轻量级虚拟机来运行 Docker 守护进程（Docker daemon， &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;dockerd&lt;/code&gt;）。这相当消耗内存和 CPU 资源。我在 Mac 上只是启动 Docker Desktop，没有运行任何 container 就消耗了 2GB 内存。&lt;/p&gt;

&lt;p&gt;而且，我在 M 系列芯片的 Mac 上使用 Docker 时，经常碰到镜像架构不兼容问题。打包出的镜像是 ARM 架构，无法直接部署到 x86 服务器上。虽然可以通过 &lt;a href=&quot;https://github.com/docker/buildx&quot;&gt;Docker Buildx&lt;/a&gt; 插件跨架构编译，但跨架构编译通常比原生编译更慢，配置也更繁琐。&lt;/p&gt;

&lt;p&gt;恰好我家里有一台 x86 的 PVE 主机，其中跑着一台 Ubuntu 虚拟机。我就想，能不能让 Mac 上的 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;docker&lt;/code&gt; 客户端直接操作 Ubuntu 虚拟机的 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;dockerd&lt;/code&gt;，在上面构建镜像、部署服务。&lt;/p&gt;

&lt;p&gt;答案是肯定的，而且相当优雅 —— Docker Context + SSH。&lt;/p&gt;

&lt;h2 id=&quot;docker-的-cs-架构&quot;&gt;Docker 的 C/S 架构&lt;/h2&gt;

&lt;p&gt;要理解这个方案，我们得先回到 Docker 的架构：它是一个客户端/服务器（client-server, c/s）架构。&lt;/p&gt;

&lt;p&gt;我们日常在终端里使用的 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;docker&lt;/code&gt; 命令，其实是 Docker 客户端。它负责将指令发送给 Docker 守护进程（&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;dockerd&lt;/code&gt;），后者则负责管理镜像、容器、网络和存储等资源。&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;https://huangboming.com/assets/images/remote-docker/1.webp&quot; alt=&quot;docker 架构图&quot; w=&quot;700&quot; h=&quot;370&quot;&gt;
&lt;em&gt;Docker C/S 架构（来源：Docker 官方文档）&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;既然它是 c/s 架构，那么客户端与守护进程就不必非得在同一台机器上。我们完全可以让本地的 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;docker&lt;/code&gt; 客户端，通过网络，与远程服务器上的 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;dockerd&lt;/code&gt; 通信。&lt;/p&gt;

&lt;p&gt;传统方式是暴露 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;dockerd&lt;/code&gt; 的 TCP 端口并用 TLS 证书加密。具体配置方式可以参考&lt;a href=&quot;https://blog.itshangxp.com/docker/docker-remote/&quot;&gt;这篇博文&lt;/a&gt;。这套配置相对繁琐，需要在服务器端修改 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;dockerd&lt;/code&gt; 配置，还要生成和管理证书文件。&lt;/p&gt;

&lt;p&gt;相比之下，SSH 方案要便捷得多。我们只需要在本机配置好 SSH 密钥，无需对远程服务器上的 Docker 做任何改动，既安全又方便。&lt;/p&gt;

&lt;h2 id=&quot;1-配置-ssh-密钥&quot;&gt;1. 配置 SSH 密钥&lt;/h2&gt;

&lt;p&gt;Docker 通过 SSH 连接远程主机时，只支持密钥认证，不支持密码认证。所以，在开始之前，你先需要配置 SSH 密钥登录远端服务器。&lt;/p&gt;

&lt;p&gt;下面以一台 IP 地址为 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;192.168.31.100&lt;/code&gt;，用户名为 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ubuntu&lt;/code&gt; 的远程 Ubuntu 虚拟机为例。&lt;/p&gt;

&lt;p&gt;首先，我们要在本地主机生成一对公私钥。公钥会被安装到远端服务器上，私钥则用于身份认证。这里推荐使用更现代、更安全的 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ed25519&lt;/code&gt; 算法：&lt;/p&gt;

&lt;div class=&quot;language-shell highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;table class=&quot;rouge-table&quot;&gt;&lt;tbody&gt;&lt;tr&gt;
&lt;td class=&quot;rouge-gutter gl&quot;&gt;&lt;pre class=&quot;lineno&quot;&gt;1
2
&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&quot;rouge-code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;c&quot;&gt;# ssh-keygen -t &amp;lt;算法&amp;gt; -f &amp;lt;公私钥路径&amp;gt;&lt;/span&gt;
ssh-keygen &lt;span class=&quot;nt&quot;&gt;-t&lt;/span&gt; ed25519 &lt;span class=&quot;nt&quot;&gt;-f&lt;/span&gt; ~/.ssh/ubuntu
&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;生成过程中，系统会提示你设置一个密码短语（pass phrase）。这是一个为私钥本身加密的密码。设置后，每次使用该私钥时，都需要先输入 pass phrase。如果嫌麻烦也可以不设置。当然，代价是牺牲了一定的安全性，一旦私钥文件泄露，攻击者就能直接访问你的服务器。&lt;/p&gt;

&lt;p&gt;完成后，你的 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;~/.ssh/&lt;/code&gt; 目录下会新增两个文件：&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ubuntu&lt;/code&gt;：私钥文件&lt;/li&gt;
  &lt;li&gt;
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ubuntu.pub&lt;/code&gt;：公钥文件&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;然后，我们要将公钥添加到远端服务器：&lt;/p&gt;

&lt;div class=&quot;language-shell highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;table class=&quot;rouge-table&quot;&gt;&lt;tbody&gt;&lt;tr&gt;
&lt;td class=&quot;rouge-gutter gl&quot;&gt;&lt;pre class=&quot;lineno&quot;&gt;1
2
&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&quot;rouge-code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;c&quot;&gt;# ssh-copy-id -i &amp;lt;公钥路径&amp;gt; &amp;lt;服务器用户名&amp;gt;@&amp;lt;服务器主机地址&amp;gt;&lt;/span&gt;
ssh-copy-id &lt;span class=&quot;nt&quot;&gt;-i&lt;/span&gt; ~/.ssh/ubuntu.pub ubuntu@192.168.31.100
&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;这条命令会自动将你的公钥内容追加到服务器的 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;~/.ssh/authorized_keys&lt;/code&gt; 文件中。期间会要求你输入一次服务器的登录密码，授权本次公钥写入操作。&lt;/p&gt;

&lt;p&gt;完成后，你可以测试一下是否能用私钥直接登录：（如果设置了 pass phrase，则需要输入它）：&lt;/p&gt;

&lt;div class=&quot;language-shell highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;table class=&quot;rouge-table&quot;&gt;&lt;tbody&gt;&lt;tr&gt;
&lt;td class=&quot;rouge-gutter gl&quot;&gt;&lt;pre class=&quot;lineno&quot;&gt;1
2
&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&quot;rouge-code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;c&quot;&gt;# ssh -i &amp;lt;私钥路径&amp;gt; &amp;lt;服务器用户名&amp;gt;@&amp;lt;服务器主机地址&amp;gt;。&lt;/span&gt;
ssh &lt;span class=&quot;nt&quot;&gt;-i&lt;/span&gt; ~/.ssh/ubuntu ubuntu@192.168.31.100
&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;如果能成功登录，说明密钥已配置成功。&lt;/p&gt;

&lt;p&gt;每次都输入长长的命令（&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ssh -i ...&lt;/code&gt;）显然不够优雅，我们可以通过配置 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;~/.ssh/config&lt;/code&gt; 文件，为服务器创建一个别名，简化登录命令。&lt;/p&gt;

&lt;p&gt;编辑（如果不存在则创建）&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;~/.ssh/config&lt;/code&gt; 文件，在文件末尾添加以下内容：&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;table class=&quot;rouge-table&quot;&gt;&lt;tbody&gt;&lt;tr&gt;
&lt;td class=&quot;rouge-gutter gl&quot;&gt;&lt;pre class=&quot;lineno&quot;&gt;1
2
3
4
5
6
7
8
9
10
&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&quot;rouge-code&quot;&gt;&lt;pre&gt;# Host &amp;lt;服务器别名&amp;gt;
#     HostName &amp;lt;服务器地址&amp;gt;
#     User &amp;lt;服务器用户名&amp;gt;
#     IdentityFile &amp;lt;私钥文件地址&amp;gt;

# 比如
Host ubuntu
    HostName 192.168.31.100
    User ubuntu
    IdentityFile ~/.ssh/ubuntu
&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;配置好之后，你只需要执行 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ssh ubuntu&lt;/code&gt; 就可以登录服务器。&lt;/p&gt;

&lt;h2 id=&quot;2-配置-docker-context&quot;&gt;2. 配置 Docker Context&lt;/h2&gt;

&lt;p&gt;Docker Contexts 是 Docker 19.03 版本引入的新特性，它封装了连接到不同 Docker 环境所需的所有配置，用于更方便地管理多个 Docker 主机（无论是本地还是远程）。&lt;/p&gt;

&lt;p&gt;如果你用过 Kubernetes，可以把它理解为 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;kubectl config&lt;/code&gt; 中的 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;context&lt;/code&gt;—— 它能让你在不同 Kubernetes 集群间无缝切换。Docker Context 也类似，只不过它切换的是 Docker 守护进程。&lt;/p&gt;

&lt;p&gt;创建一个指向远程服务器的 Context 非常简单：&lt;/p&gt;

&lt;div class=&quot;language-shell highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;table class=&quot;rouge-table&quot;&gt;&lt;tbody&gt;&lt;tr&gt;
&lt;td class=&quot;rouge-gutter gl&quot;&gt;&lt;pre class=&quot;lineno&quot;&gt;1
2
3
4
&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&quot;rouge-code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;c&quot;&gt;# docker context -create &amp;lt;context名称&amp;gt; --docker &quot;host=ssh://&amp;lt;服务器别名&amp;gt; --description &quot;&amp;lt;描述&amp;gt;&quot;&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# 或者 docker context -create &amp;lt;context名称&amp;gt; --docker &quot;host=ssh://&amp;lt;服务器用户&amp;gt;@&amp;lt;服务器IP&amp;gt;&quot; --description &quot;&amp;lt;描述&amp;gt;&quot;&lt;/span&gt;

docker context create remote-ubuntu &lt;span class=&quot;nt&quot;&gt;--docker&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;host=ssh://ubuntu&quot;&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;--description&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;Home Ubuntu server&quot;&lt;/span&gt;
&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;创建成功后，可以使用 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;docker context ls&lt;/code&gt; 查看当前 Context 列表：&lt;/p&gt;

&lt;div class=&quot;language-shell highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;table class=&quot;rouge-table&quot;&gt;&lt;tbody&gt;&lt;tr&gt;
&lt;td class=&quot;rouge-gutter gl&quot;&gt;&lt;pre class=&quot;lineno&quot;&gt;1
2
3
4
5
6
7
&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&quot;rouge-code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;docker context &lt;span class=&quot;nb&quot;&gt;ls&lt;/span&gt;                                            

NAME            DESCRIPTION                               DOCKER ENDPOINT                             ERROR
default &lt;span class=&quot;k&quot;&gt;*&lt;/span&gt;       Current DOCKER_HOST based configuration   unix:///var/run/docker.sock                 
desktop-linux   Docker Desktop                            unix:///Users/xxxx/.docker/run/docker.sock   

remote-ubuntu   Home Ubuntu server                        ssh://ubuntu
&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;可以看到，我们有一个本地 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;default&lt;/code&gt; Context 和一个刚创建的 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;remote-ubuntu&lt;/code&gt; Context。名称后的星号表示当前正在使用的 Context。&lt;/p&gt;

&lt;h2 id=&quot;3-使用远端-docker&quot;&gt;3. 使用远端 Docker&lt;/h2&gt;

&lt;p&gt;创建好 Context 之后，执行以下命令，将 Docker 环境切换到远程服务器：&lt;/p&gt;

&lt;div class=&quot;language-shell highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;table class=&quot;rouge-table&quot;&gt;&lt;tbody&gt;&lt;tr&gt;
&lt;td class=&quot;rouge-gutter gl&quot;&gt;&lt;pre class=&quot;lineno&quot;&gt;1
2
&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&quot;rouge-code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;c&quot;&gt;# docker context use &amp;lt;context名称&amp;gt;&lt;/span&gt;
docker context use remote-ubuntu
&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;切换过后，你就可以与远端的 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;dockerd&lt;/code&gt; 通信了——你执行的每个 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;docker&lt;/code&gt; 命令都会通过 SSH 隧道，以远程的服务器上执行。当你需要在远程服务器上构建 x86 镜像，或者运行 container 时，都可以直接执行 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;docker build&lt;/code&gt;、&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;docker run&lt;/code&gt;。&lt;/p&gt;

&lt;p&gt;简单验证一下：&lt;/p&gt;

&lt;div class=&quot;language-shell highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;table class=&quot;rouge-table&quot;&gt;&lt;tbody&gt;&lt;tr&gt;
&lt;td class=&quot;rouge-gutter gl&quot;&gt;&lt;pre class=&quot;lineno&quot;&gt;1
2
&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&quot;rouge-code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;docker info | &lt;span class=&quot;nb&quot;&gt;grep&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;Operating System&quot;&lt;/span&gt;
Operating System: Ubuntu 22.04.5 LTS
&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;如果想切回本地的 Docker 环境，也很简单：&lt;/p&gt;

&lt;div class=&quot;language-shell highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;table class=&quot;rouge-table&quot;&gt;&lt;tbody&gt;&lt;tr&gt;
&lt;td class=&quot;rouge-gutter gl&quot;&gt;&lt;pre class=&quot;lineno&quot;&gt;1
&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&quot;rouge-code&quot;&gt;&lt;pre&gt;docker context use default
&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;局限性&quot;&gt;局限性&lt;/h2&gt;

&lt;p&gt;虽然通过 SSH + Docker Context 可以使用远端 Docker，在某些场景下存在局限性。最主要的两点是本地文件挂载和端口映射的行为与我们的直觉不符。&lt;/p&gt;

&lt;h3 id=&quot;1-文件挂载&quot;&gt;1. 文件挂载&lt;/h3&gt;

&lt;p&gt;当你在本地执行 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;docker run -v /local/path:/container/path my-image&lt;/code&gt; 时，你可能会期望将本地的 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/local/path&lt;/code&gt; 目录挂载到 container 中。但实际上，由于 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;dockerd&lt;/code&gt; 运行在远端服务器上，它会尝试挂载远端服务器上的 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/local/path&lt;/code&gt; 目录。这意味着我们无法将本机的目录挂载到 container 中，基本告别使用远端 Docker + &lt;a href=&quot;https://code.visualstudio.com/docs/devcontainers/containers&quot;&gt;dev container&lt;/a&gt; 开发了。&lt;/p&gt;

&lt;h3 id=&quot;2-端口映射&quot;&gt;2. 端口映射&lt;/h3&gt;

&lt;p&gt;类似地，当你使用 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-p&lt;/code&gt; 参数（例如 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;docker run -p 8080:80 my-nginx&lt;/code&gt;）时，端口 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;8080&lt;/code&gt; 会被映射到远端服务器的网络接口上，而不是你的本地主机。&lt;/p&gt;

&lt;h3 id=&quot;3-构建上下文build-context&quot;&gt;3. 构建上下文（Build Context）&lt;/h3&gt;

&lt;p&gt;执行 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;docker build .&lt;/code&gt; 时，Docker 客户端会将当前目录（构建上下文）完整地打包，并通过 SSH 发送到远端服务器。如果你的项目包含大量文件，或者你的网络连接不佳，这个上传过程可能会非常缓慢。&lt;/p&gt;

&lt;h2 id=&quot;延伸阅读&quot;&gt;延伸阅读&lt;/h2&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;https://docs.docker.com/engine/daemon/remote-access/&quot;&gt;Configure remote access for Docker daemon&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://docs.docker.com/engine/security/protect-access/&quot;&gt;Protect the Docker daemon socket&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
</content>
  </entry>
  
    
    
    
    
  <entry>
    <title>Cursor Vibe Coding 心得分享</title>
    <id>https://huangboming.com/posts/cursor-vibe-coding/</id>
    <link rel="alternate" type="text/html" href="https://huangboming.com/posts/cursor-vibe-coding/" />
    <published>2025-06-27T00:00:00+08:00</published>
    <updated>2026-07-21T17:32:08+08:00</updated>
    <author>
      <name>Boming Huang</name>
      <uri>https://huangboming.com/about/</uri>
    </author>
    <category term="心得" />
    <summary type="text">分享使用 Cursor Agent 进行 vibe coding 的心得，包括任务拆解、上下文管理、MCP 工具配置以及文档驱动开发的最佳实践。</summary>
    <content type="html" xml:base="https://huangboming.com/posts/cursor-vibe-coding/">&lt;p&gt;最近在使用 Cursor pro 从零开始设计并编写一个项目（React 前端 + FastAPI 后端 + Tauri 打包），完全 vibe coding，几乎没有手写一行代码。&lt;/p&gt;

&lt;p&gt;在这个过程中我摸索出一套 AI Agent 编写项目的技巧。今天就来分享一些我使用 Cursor vibe coding 的心得。&lt;/p&gt;

&lt;h2 id=&quot;写在前面&quot;&gt;写在前面&lt;/h2&gt;

&lt;p&gt;这篇心得并不鼓吹“全自动 AI 编程”。我深知 AI 能力有限，也在实践中慢慢摸索 AI 能力的边界。我只想分享一些我摸索出的 AI 协作工作流与心法，不希望给读者“一句话就能完成一个项目”、“完全 vibe coding，一路 Accept，不需要人工干预”的印象。&lt;/p&gt;

&lt;p&gt;虽然我确实在整个编码阶段都在 vibe coding —— 只提需求，放心让 AI 全自动编码，也没怎么 review 代码，但实际上我在项目过程中做了很多工作：&lt;/p&gt;
&lt;ol&gt;
  &lt;li&gt;项目前期规划，定义项目愿景、MVP、UI/UX 设计、系统架构设计等等，并且形成 AI 可读的文档，为 AI 提供项目上下文&lt;/li&gt;
  &lt;li&gt;仔细审查 AI 生成的每一个任务规划&lt;/li&gt;
  &lt;li&gt;AI 完成阶段性任务后，由我来测试、验证并提供反馈。&lt;/li&gt;
  &lt;li&gt;定期重构，保持代码整洁&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;这些工作乍一看没太大意义，但实际上是 AI Agent 高效运转的基石。具体为什么，容我先卖个关子。&lt;/p&gt;

&lt;h2 id=&quot;准备工作&quot;&gt;准备工作&lt;/h2&gt;

&lt;p&gt;在开始一个项目之前，我们需要先配置好 Cursor。这里配置指的不仅仅是配置编程环境、安装插件，更重要的是，为 Agent 配置好工具 —— Cursor rules、项目文档以及 MCP 服务器。&lt;/p&gt;

&lt;h3 id=&quot;cursor-rules&quot;&gt;Cursor rules&lt;/h3&gt;

&lt;p&gt;在 Cursor 中，我们可以通过 Cursor rules 为 Agent 设定行动规则、提供上下文。具体的配置方式是，在项目根目录的 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.cursor/rules/&lt;/code&gt; 文件夹下创建一系列的 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;*.mdc&lt;/code&gt; 文件，在其中添加规则。&lt;/p&gt;

&lt;p&gt;对于每个项目，我会添加以下规则：&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;基于 RIPER-5 提示词的 Cursor rules： &lt;a href=&quot;https://github.com/johnpeterman72/CursorRIPER&quot;&gt;CursorRIPER&lt;/a&gt;
&lt;/li&gt;
  &lt;li&gt;MCP 工具规则，用于介绍可用的 MCP 工具，以及使用工具时的规则&lt;/li&gt;
  &lt;li&gt;项目专属规则：开发过程中随时补充的其它规则，比如语言偏好、代码风格等等&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;RIPER-5 提示词是 robotlovehuman 在 &lt;a href=&quot;https://forum.cursor.com/t/i-created-an-amazing-mode-called-riper-5-mode-fixes-claude-3-7-drastically/65516&quot;&gt;Cursor 论坛&lt;/a&gt;中提出的一个提示词，它为 Agent 设定了五个模式：&lt;/p&gt;
&lt;ol&gt;
  &lt;li&gt;Research mode（研究模式）：负责收集资料、阅读项目代码&lt;/li&gt;
  &lt;li&gt;Innovate mode（创新模式）：负责头脑风暴、探索关于项目的新想法、新功能&lt;/li&gt;
  &lt;li&gt;Plan mode（规划模式）：负责规划任务以及下一步行动&lt;/li&gt;
  &lt;li&gt;Execute mode（执行模式）：负责执行计划中的任务，编写实际代码&lt;/li&gt;
  &lt;li&gt;Review mode（评审模式）：负责审阅代码，检查代码是否实现计划中的任务&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Cursor RIPER 结合了 RIPER-5 提示词和 Memory bank（记忆银行）。Memory bank 主要用于为模型提供必要的项目上下文，比如项目概述、项目所用技术栈、项目进度等等。&lt;sup id=&quot;fnref:1&quot;&gt;&lt;a href=&quot;https://huangboming.com/posts/cursor-vibe-coding/#fn:1&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot; role=&quot;doc-noteref&quot;&gt;1&lt;/a&gt;&lt;/sup&gt;&lt;/p&gt;

&lt;h3 id=&quot;项目文档&quot;&gt;项目文档&lt;/h3&gt;

&lt;p&gt;重要的事说三遍：一定要有文档，一定要有文档，一定要有文档！哪怕是 AI 生成的文档也比没有文档强。从 AI 上下文窗口的角度来看，制作项目文档相当于压缩项目代码和之前项目进度，使得 Agent 可以在有限的上下文窗口中了解项目。&lt;/p&gt;

&lt;p&gt;项目文档对于 Agent 特别重要，因为 Agent 是无状态的（stateless）。&lt;/p&gt;

&lt;p&gt;我们在做项目时，我们会在大脑中构建一个关于整个项目的心智模型（mental model），包含代码结构、业务逻辑、代码风格，甚至团队成员间不成文的约定等等。但对于 Agent 来说，它没有这样一个心智模型。你需要在对话中为它提供必要的项目信息，帮它构建一个临时的心智模式。&lt;/p&gt;

&lt;p&gt;简单来说，你可以把 Agent 想象成一位新来的实习生：每次开启新的对话，都相当于换了一个全新的实习生。如果你没有提供足够上下文信息，这个新实习生就不了解当前项目，两眼一抹黑，表现自然就会很差。&lt;/p&gt;

&lt;p&gt;当然，你也不可能指望把所有资料全压在一个对话窗口中，从项目开发之初到项目结束只使用一个对话窗口；或者让 Agent 一次性读完项目中所有代码来理解项目。&lt;/p&gt;

&lt;p&gt;首先，模型上下文窗口有限。目前上下文窗口最大的 Gemini 模型的窗口大小也只有一百万 token，Claude Sonnet 4 也才二十万。更重要的是，就算上下文窗口足够大，模型在长上下文的表现也很有限。简单来说，它在一次任务中能够有效关注和处理的信息有限。参考资料：&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;
&lt;a href=&quot;https://fiction.live/stories/Fiction-liveBench-Mar-25-2025/oQdzQvKHw8JyXbN87&quot;&gt;Fiction.LiveBench&lt;/a&gt;：一个测试模型在长上下文表现的 benchmark&lt;/li&gt;
  &lt;li&gt;
&lt;a href=&quot;https://arxiv.org/abs/2307.03172&quot;&gt;Lost in the Middle - How Language Models Use Long Contexts&lt;/a&gt;：模型在处理长文本时，更容易关注头尾的文本，而忽略中间的文本&lt;/li&gt;
  &lt;li&gt;
&lt;a href=&quot;https://arxiv.org/abs/2502.01951&quot;&gt;On the Emergence of Position Bias in Transformers&lt;/a&gt;：模型存在位置偏误&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;沿用上面的类比，把所有内容全压在一个对话窗口中就相当于让新来的实习生一次读完所有项目代码、文档，然后立马开始干活。这当然是不可能的。&lt;/p&gt;

&lt;p&gt;我把项目文档分成几类：&lt;/p&gt;
&lt;ol&gt;
  &lt;li&gt;
&lt;strong&gt;整体项目文档&lt;/strong&gt;：包括项目愿景、项目需求文档（PRD）、MVP 定义文档、系统架构设计图、开发指南。这些文档会被保存在项目根目录的 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;docs/&lt;/code&gt; 下，后续基本不会修改。这些文档是项目的基石，用于项目 Memory bank 初始化，以及规划下一步功能&lt;/li&gt;
  &lt;li&gt;
&lt;strong&gt;模块文档&lt;/strong&gt;：在每一个文件夹下创建一个 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;README.md&lt;/code&gt;，描述该文件夹内所有文件的主要内容、职责。这可以帮助 Agent 快速了解项目，找到对应的模块，而不需要直接阅读代码 —— 极大地节省了 Token 消耗 和 Agent 的“注意力”。&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;在实际编码时，我一般会引入“架构设计”和“开发指南”两个文档，让 Agent 以这两个文档为起点。如果它在执行具体任务时需要查看某个模块的文档，它会自己去查看。&lt;/p&gt;

&lt;p&gt;举一个例子，比如说有一个前端项目，其文件结构如下：&lt;/p&gt;
&lt;div class=&quot;language-shell highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;table class=&quot;rouge-table&quot;&gt;&lt;tbody&gt;&lt;tr&gt;
&lt;td class=&quot;rouge-gutter gl&quot;&gt;&lt;pre class=&quot;lineno&quot;&gt;1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&quot;rouge-code&quot;&gt;&lt;pre&gt;frontend/src
├── App.css
├── App.tsx
├── components
│   ├── a.tsx
|   ├── b.tsx
│   └── tabs
│   │   ├── c.tsx
│   │   ├── d.tsx
├── hooks
│   ├── e.ts
│   ├── f.ts
│   ├── g.ts
│   ├── h.ts
├── main.tsx
&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;我会在 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;frontend/src&lt;/code&gt; 目录下创建一个 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;docs&lt;/code&gt; 文件夹，存放以下项目文档：&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;架构设计：包含项目概述、技术架构层次、核心组件（Mermaid 图）以及项目结构（项目文件夹结构 + 指向模块文档的链接）&lt;/li&gt;
  &lt;li&gt;设计风格：包含页面 UI 设计风格&lt;/li&gt;
  &lt;li&gt;开发指南：包含设计原则、代码风格&lt;/li&gt;
  &lt;li&gt;技术选型：包含所用的技术栈&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;然后分别在每个子目录（&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;components&lt;/code&gt;、&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;hooks&lt;/code&gt;）下，创建 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;README.md&lt;/code&gt;，概述该文件夹下所有文件的内容，主要包含&lt;strong&gt;模块概览&lt;/strong&gt;、每个文件的&lt;strong&gt;文件名&lt;/strong&gt;和&lt;strong&gt;职责描述&lt;/strong&gt;。&lt;/p&gt;

&lt;p&gt;在实际开发时，我会让 Agent 从顶层的架构设计、开发指南出发，先阅读顶层文档，再逐步阅读下层文档，规划、拆解任务。&lt;/p&gt;

&lt;p&gt;如果你像我一样想偷懒，也可以让 Agent 生成文档。创建文档提示词如下：&lt;/p&gt;
&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;table class=&quot;rouge-table&quot;&gt;&lt;tbody&gt;&lt;tr&gt;
&lt;td class=&quot;rouge-gutter gl&quot;&gt;&lt;pre class=&quot;lineno&quot;&gt;1
2
3
&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&quot;rouge-code&quot;&gt;&lt;pre&gt;我想让你逐步阅读frontend/src/hooks下的所有文件，理解该模块的主要内容、职责、代码结构，然后在这个文件夹下创建一个README.md，概述该文件夹的结构、设计原则、详细描述每个文件的主要内容、职责、功能，但不要包含具体代码。要求通俗易懂，让新来的实习生也能够快速了解项目，融入团队。

如果文件夹下有嵌套文件夹，你可以先阅读其中的README.md。如果其中没有README.md，那就先阅读该文件夹中下所有文件，先创建该文件夹的README.md。如果一直碰到文件夹，你需要重复这个过程。
&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;一定要保证文档能够反映项目的最新状态。我有时候会在任务结束的最后，让 Agent 更新相关文档；有时候也会一次性让它更新所有文档。更新文档提示词如下：&lt;/p&gt;

&lt;div class=&quot;language-text highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;table class=&quot;rouge-table&quot;&gt;&lt;tbody&gt;&lt;tr&gt;
&lt;td class=&quot;rouge-gutter gl&quot;&gt;&lt;pre class=&quot;lineno&quot;&gt;1
&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&quot;rouge-code&quot;&gt;&lt;pre&gt;我想让你逐步阅读frontend/src下的所有文件，更新相关的文档，使得文档up to date，让新来的实习生能快速了解项目，融入团队。要求不要包含具体代码。
&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;mcp-服务器&quot;&gt;MCP 服务器&lt;/h3&gt;

&lt;p&gt;MCP（Model Context Protocol，模型上下文协议）是一个协议，允许 AI 安全地访问外部的数据和工具。简单来说，MCP 服务器为 Agent 提供了可以使用的外部工具，拓展模型的能力。&lt;/p&gt;

&lt;p&gt;具体的配置方式可以参考 &lt;a href=&quot;https://docs.cursor.com/context/model-context-protocol&quot;&gt;Cursor 的官方文档&lt;/a&gt;。我的 MCP 服务器配置如下图：&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;https://huangboming.com/assets/images/cursor-vibe-coding/1.png&quot; alt=&quot;MCP 配置&quot; class=&quot;shadow&quot; w=&quot;700&quot; h=&quot;448&quot;&gt;&lt;/p&gt;

&lt;h4 id=&quot;context-7&quot;&gt;Context 7&lt;/h4&gt;

&lt;p&gt;模型可以使用 &lt;a href=&quot;https://github.com/upstash/context7&quot;&gt;Context 7 MCP&lt;/a&gt; 提供的工具查询依赖包的最新文档，可以避免知识库过时或者模型幻觉问题。基本上每次模型要处理与依赖包相关的代码时，我都会提示模型 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;请先使用context 7工具查看最新文档，再开始执行任务&lt;/code&gt;。比如说，如果不使用 context 7 MCP，模型会使用 Tauri v1.x、Tailwind CSS v3，而不是用最新的 Tauri v2.0、Tailwind CSS v4。即使你提示它用最新的库，它也不知道怎么用，会写出一堆有问题的代码。&lt;/p&gt;

&lt;h4 id=&quot;mcp-feedback-enhanced&quot;&gt;MCP feedback enhanced&lt;/h4&gt;

&lt;p&gt;模型可以使用 &lt;a href=&quot;https://github.com/Minidoracat/mcp-feedback-enhanced?tab=readme-ov-file&quot;&gt;MCP feedback enhanced&lt;/a&gt; 提供的工具与用户交互。这个 MCP 看起来平平无奇，但实际上它为 vibe coding 提供了一个很重要的反馈功能。&lt;/p&gt;

&lt;p&gt;接着刚刚的类比，把 Agent 看成一个实习生。在没有这个 MCP 之前，你提出需求，这个实习生会一口气一路干到最后，中间没有任何反馈或修正的机会。结果等你运行起来才发现，效果根本不是你想要的，或者出现各种问题。&lt;/p&gt;

&lt;p&gt;而一旦有这个 MCP，情况就大不同了。你可以让它每完成一个小任务就给你写一份工作报告，总结所做的修改，并寻求你的反馈。经过你的审阅、测试，确认没问题之后，再继续执行下一个任务。一旦发现问题，你也可以立即要求它进行修改，而不是在错误的道路上一错再错。&lt;/p&gt;

&lt;p&gt;举一个常见的例子：在写前端项目时，你可以充当人肉测试员。Agent 每完成一个小模块或功能实现后，你可以负责测试页面的功能和 UI 是否符合预期。如果哪里有问题，可以及时反馈给 Agent，让它进行修复，然后你继续测试，重复这个过程一直到满意为止。如果你想更偷懒一些，你可以提示模型 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;如果你有什么疑问，完成小任务之后、或者需要我测试前端页面，请务必使用mcp-feedback-enhanced与我沟通、反馈。如果需要我测试，请提供一份测试方案&lt;/code&gt;，让 AI 给你提供测试方案。&lt;/p&gt;

&lt;p&gt;这个 MCP 的出现，也让我彻底放弃了让 AI 使用 Playwright MCP 自行测试前端的想法——相比之下，人工测试效果更佳，也更放心。&lt;/p&gt;

&lt;p&gt;在使用这个 MCP 的过程中，我总结了几点心得和注意事项：&lt;/p&gt;
&lt;ol&gt;
  &lt;li&gt;在需要创建代码保存点（checkpoint）时，务必打断这个 MCP 的调用。在 Cursor 中，每一次对话都会存一份代码保存点，方便回滚到当时的代码状态；但调用 MCP 时并不会存保存点。我碰到过这种情况：将一个大任务拆解成若干任务阶段，每一个任务阶段都有若干子任务。Agent 完成第一阶段任务之后，通过 MCP 向我确认。我确认没问题之后，它会在&lt;strong&gt;同一个对话&lt;/strong&gt;中继续执行第二阶段任务。当第二阶段任务出错之后，我想回滚到第一阶段完成时的状态时，结果发现没有相应的保存点，只能返回到最开始的地方，白白浪费时间。因此，我的建议是：每完成一个阶段性任务，就主动打断 MCP 的调用，然后在新的对话中让 Agent 继续执行下一个阶段的任务，这样就能确保每一步都有可回溯的保存点。&lt;/li&gt;
  &lt;li&gt;如果上下文太长，要及时切换到另一个对话窗口。这个 MCP 会让你觉得“这个对话窗口也没多少对话”，但实际上可能上下文窗口已经满了。&lt;/li&gt;
&lt;/ol&gt;

&lt;h4 id=&quot;desktop-commander&quot;&gt;Desktop Commander&lt;/h4&gt;

&lt;p&gt;&lt;a href=&quot;https://github.com/wonderwhy-er/DesktopCommanderMCP&quot;&gt;Desktop Commander MCP&lt;/a&gt; 为模型提供了操作编程中常见的工具，包括读写文件、运行命令。这个 MCP 我没有深度使用，所以不做太多推荐。只说一个应用场景：Cursor 内置的文件读取功能有行数限制，如果文件比较大，模型只能读取一部分。使用 Desktop Commander 就能读取所有的文件内容。&lt;/p&gt;

&lt;p&gt;如果你想用它替代 Cursor 内置的文件读写以及运行命令功能，有几个注意事项：&lt;/p&gt;
&lt;ol&gt;
  &lt;li&gt;配置好它的配置文件（&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/.claude-server-commander/config.json&lt;/code&gt;），特别是允许它使用的命令以及访问的目录。&lt;/li&gt;
  &lt;li&gt;善用 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;git&lt;/code&gt;。使用 Desktop Commander 修改文件时，Cursor 页面不会有任何提示，你只能通过 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;git diff&lt;/code&gt; 来查看模型所做的修改。而且也没有任何保存点，你只能自己使用 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;git&lt;/code&gt; 来保存。建议完成每一个小任务 commit 一次，最后再通过 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;git rebase&lt;/code&gt; 来整理 commit 信息。如果你不太熟悉 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;git rebase&lt;/code&gt;，给你推荐一篇很好的&lt;a href=&quot;https://medium.com/starbugs/use-git-interactive-rebase-to-organize-commits-85e692b46dd&quot;&gt;教学文&lt;/a&gt;。&lt;/li&gt;
&lt;/ol&gt;

&lt;h2 id=&quot;编码过程&quot;&gt;编码过程&lt;/h2&gt;

&lt;h3 id=&quot;核心原则拆解&quot;&gt;核心原则：拆解&lt;/h3&gt;

&lt;p&gt;随着项目的推进，我意识到要用好 Agent 完成项目任务，提高 Agent 的表现，拆解必不可少。原因我在前文已经提到过——模型上下文窗口限制以及处理长文能力有限。&lt;/p&gt;

&lt;p&gt;在整个过程中我实践过几种不一样的拆解：&lt;/p&gt;
&lt;ol&gt;
  &lt;li&gt;项目拆解：厘清项目愿景、定义 MVP、拆解出若干项目文档，为模型提供必要项目上下文&lt;/li&gt;
  &lt;li&gt;任务拆解：将功能需求拆解为具体可实施的任务&lt;/li&gt;
  &lt;li&gt;代码重构：重构代码，使得代码模块化、低耦合，减少一个项目文本的代码行数&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;关于项目拆解于编码过程没啥关系，我会再写一篇文章来介绍它，如何从一个想法开始发展成一个项目、再到 MVP 文档、UI/UX 设计、系统架构等等，以及在这个过程中如何使用 AI 辅助。&lt;/p&gt;

&lt;h4 id=&quot;任务拆解plan-and-solve&quot;&gt;任务拆解：Plan and Solve&lt;/h4&gt;

&lt;p&gt;在提示词工程中，有一个经典的提示词方式叫 &lt;a href=&quot;https://arxiv.org/abs/2305.04091&quot;&gt;Plan and Solve&lt;/a&gt;（先规划后解决） —— 针对特定任务/功能需求，先让模型理解功能需求、拆解任务，制作一份详细的任务清单，然后再让模型一步一步按照计划完成任务。我们可以直接套用这个方法论。&lt;/p&gt;

&lt;p&gt;在实际使用中，我们可以使用两个不同的模型，一个负责规划任务（Planner），另一个负责实际编码（Solver）。我喜欢用 Gemini 2.5 pro 规划任务，然后使用 Claude Sonnet 4 来编码。你可以根据自己的喜好、实践经验来选择 Planner 和 Solver。&lt;/p&gt;

&lt;p&gt;这里稍稍偏个题，聊聊我对目前主流模型的理解和感觉：&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;Gemini 2.5 pro：虽然在 Cursor 中 Gemini 2.5 pro 被砍了上下文，但它的长文理解能力、逻辑推理能力以及长文输出能力都很强。所以它很适合作为 Planner。但是它调用工具的能力比较差，有时会做出破坏性改动——它觉得之前的代码有问题，它就会去修改，即使你没有叫它去改这一块代码。整体来说，作为 Solver 它的表现没有 Claude Sonnet 4 那么稳定，但还算可用。&lt;/li&gt;
  &lt;li&gt;Claude Sonnet 4：它遵从指令、调用工具还有编码能力都很强，是一个合格的 Solver。用的人很多，导致整体响应慢，有时甚至不可用。用它来做规划也可以，只是我比较偏好 Gemini 2.5 pro。&lt;/li&gt;
  &lt;li&gt;O3 &amp;amp; GPT 4.1 我都没有深度使用，不做评价。&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;具体提示词如下（Credit: &lt;a href=&quot;https://linux.do/u/kkkyyx&quot;&gt;kkkyyx&lt;/a&gt;）：&lt;/p&gt;

&lt;div class=&quot;language-markdown highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;table class=&quot;rouge-table&quot;&gt;&lt;tbody&gt;&lt;tr&gt;
&lt;td class=&quot;rouge-gutter gl&quot;&gt;&lt;pre class=&quot;lineno&quot;&gt;1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&quot;rouge-code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;nt&quot;&gt;&amp;lt;你的需求&amp;gt;&lt;/span&gt;

请你进入PLAN模式，阅读相关文档、前后端代码，然后开始分析、规划，拆解任务。

在执行任务时，请遵循以下工作流程：
&lt;span class=&quot;p&quot;&gt;
1.&lt;/span&gt; &lt;span class=&quot;gs&quot;&gt;**任务分解阶段**&lt;/span&gt;：
&lt;span class=&quot;p&quot;&gt;    -&lt;/span&gt; 将主要任务分解为具体的、可执行的子任务
&lt;span class=&quot;p&quot;&gt;    -&lt;/span&gt; 每个子任务应该是明确的、可衡量的单一操作
&lt;span class=&quot;p&quot;&gt;    -&lt;/span&gt; 确保子任务之间有逻辑顺序和依赖关系
&lt;span class=&quot;p&quot;&gt;2.&lt;/span&gt; &lt;span class=&quot;gs&quot;&gt;**任务清单制作**&lt;/span&gt;：
&lt;span class=&quot;p&quot;&gt;    -&lt;/span&gt; 使用以下格式列出所有子任务：
        &lt;span class=&quot;sb&quot;&gt;`[ ] 子任务描述（具体操作内容） [ ] 子任务描述（具体操作内容）`&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;    -&lt;/span&gt; 按执行顺序排列任务
&lt;span class=&quot;p&quot;&gt;3.&lt;/span&gt; &lt;span class=&quot;gs&quot;&gt;**任务执行阶段**&lt;/span&gt;：
&lt;span class=&quot;p&quot;&gt;    -&lt;/span&gt; 逐一完成每个子任务
&lt;span class=&quot;p&quot;&gt;    -&lt;/span&gt; 完成后将对应任务标记为：&lt;span class=&quot;sb&quot;&gt;`[√] 已完成的任务描述`&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;    -&lt;/span&gt; 如遇到问题，说明具体困难并寻求解决方案

请在开始任何任务前，先展示完整的任务分解清单，获得确认后再开始执行。

一定要多使用 mcp-feedback-enhanced 工具多向我反馈、报告工作以及下一步任务。如果有需要我测试的地方（运行命令、调试前端等），也可以直接告诉我。只要你给出一份测试流程，我乐意帮忙测试。
&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;它给出一份任务清单之后，你需要仔细阅读，思考这个方案合不合理。如果不合理，就跟进补充修改需求，或者让它再生成几次。这一步就别偷懒了，虽说是自动驾驶，但也不要完全自动:)&lt;/p&gt;

&lt;p&gt;每次需求最好新启动一个会话，清空会话框所有的 Context，引入必要的项目文档（比如代码风格、前端架构文档等等），再配合上面的提示词开始一次任务。最好不要引入具体的代码文件，特别是很长的代码文件，这会污染上下文窗口。&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;https://huangboming.com/assets/images/cursor-vibe-coding/2.png&quot; alt=&quot;上下文管理&quot; class=&quot;shadow&quot; w=&quot;700&quot; h=&quot;1358&quot;&gt;
&lt;em&gt;注意清空会话框所有的 Context&lt;/em&gt;&lt;/p&gt;

&lt;h4 id=&quot;代码重构&quot;&gt;代码重构&lt;/h4&gt;

&lt;p&gt;随着项目推进，代码会变得越来越复杂。我们需要有意识地重构旧代码，清理混乱和技术债，减轻自己和 Agent 的心智负担。&lt;/p&gt;

&lt;p&gt;代码重构有两个核心意义：&lt;/p&gt;
&lt;ol&gt;
  &lt;li&gt;组件间解耦、保持低耦合：高耦合的代码是所有开发者（包括 AI）的噩梦。修改高耦合度的组件代码就得通读所有相关联的模块，这会消耗 Agent 宝贵的上下文窗口和注意力。我们平时处理高耦合代码的过程其实也差不多：需要思考所有可能涉及到的组件，更改某段代码会造成哪些影响，然后才能小心翼翼地修改。修改过后还要再做一次完整测试，确保所有组件工作正常。&lt;/li&gt;
  &lt;li&gt;控制文件中的代码行数：我的经验法则是，单个文件尽量不要超过 500-700 行。超过之后 Agent 就会开始偷懒，只读其中的一小部分。把长代码文件拆分成若干小代码文件，再配上文档，Agent 就更容易找到并关注相关代码，修改时也不容易误伤不相关的逻辑。&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;我常常在几次小修改或者一次大修改之后重构代码。重构代码也可以让 AI 阅读代码、做方案，然后再执行。具体提示词如下：&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;table class=&quot;rouge-table&quot;&gt;&lt;tbody&gt;&lt;tr&gt;
&lt;td class=&quot;rouge-gutter gl&quot;&gt;&lt;pre class=&quot;lineno&quot;&gt;1
2
3
&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&quot;rouge-code&quot;&gt;&lt;pre&gt;我希望你能阅读并分析frontend/src/hooks中的代码，寻找其中可能的重构点、性能、安全改进点，主要目的是让它们更模块化、减少耦合性、更可维护、更高性能、更安全。

给出一份代码分析与改进建议报告，详细描述潜在的问题、重构方案以及优先级，并写入该文件夹的TODOs.md中
&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;其它注意事项&quot;&gt;其它注意事项&lt;/h3&gt;

&lt;ul&gt;
  &lt;li&gt;完成阶段性任务之后，及时更新文档&lt;/li&gt;
  &lt;li&gt;如果 Agent 表现不够好，保持耐心。可以试试再拆解、细化，或者换一个模型，或者再生成几次。如果还是不行，说明 Agent 不能胜任这个任务，只能自己上了:(&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;总结&quot;&gt;总结&lt;/h2&gt;

&lt;p&gt;回顾全文，我的所有心得其实都围绕着如何让 AI 更好地工作，核心在于理解并应对它的边界：&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;知识边界：模型的知识库老旧 -&amp;gt; 使用工具解决，比如 context 7、联网&lt;/li&gt;
  &lt;li&gt;记忆边界：模型没有记忆、上下文窗口有限、处理长上下文能力有限 -&amp;gt; 管理上下文，核心在于拆解以及文档管理&lt;/li&gt;
  &lt;li&gt;能力边界：模型操作计算机测试能力有限 -&amp;gt; 由人工测试并给模型提供反馈&lt;/li&gt;
  &lt;li&gt;可靠性边界：模型会产生幻觉 -&amp;gt; 依靠人工审查和测试来保证代码质量&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;最后一点感想&quot;&gt;最后一点感想&lt;/h2&gt;

&lt;p&gt;我慢慢觉得，在 AI 时代我们要重新审视和定义开发者的角色。&lt;/p&gt;

&lt;p&gt;在过去，技术栈是一个壁垒——如果你不熟悉某个技术栈，你需要先学习然后才能开发相关项目。但现在，AI 极大地拓宽了我们行动域，让我们可以做到过去不敢想或者做不到的事情。&lt;/p&gt;

&lt;p&gt;在这个项目开始之前，我只自学过一些 React，懂 Python 和一些 Rust，完全没有接触过 Tauri 框架。如果让我从头开始自己写这个项目，那没几个月是写不出来的。更可能的出现的情况是，耐心和精力耗尽，项目半路夭折。&lt;/p&gt;

&lt;p&gt;在这个过程中，我更像是一个产品经理、一个项目总监、一个 QA。我的精力更多地花在定义问题、设计方案、测试、以及把握项目的整体方向，而不是实际的编码工作。&lt;/p&gt;

&lt;p&gt;这不意味着传统的编码技能不重要。你可能不需要手敲每一行代码，但你需要理解 AI 给出的代码是否合理，是否符合最佳实践；你可能不需要记住某个依赖的所有接口，但你需要知道什么时候，应该让 AI 去查阅某个文档或使用某个工具。&lt;/p&gt;

&lt;p&gt;说到底，&lt;strong&gt;你的想法、审美、眼界也决定了 Agent 可以做到什么程度。&lt;/strong&gt;&lt;/p&gt;

&lt;hr&gt;

&lt;h2 id=&quot;脚注&quot;&gt;脚注&lt;/h2&gt;

&lt;div class=&quot;footnotes&quot; role=&quot;doc-endnotes&quot;&gt;
  &lt;ol&gt;
    &lt;li id=&quot;fn:1&quot;&gt;
      &lt;p&gt;RIPER 5 + Memory bank 在项目前期很好用，但在项目后期我基本上没怎么用。直接使用任务拆解提示词 + 及时更新项目文档对我而言效率更高一些 &lt;a href=&quot;https://huangboming.com/posts/cursor-vibe-coding/#fnref:1&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;↩︎&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
  &lt;/ol&gt;
&lt;/div&gt;
</content>
  </entry>
  
    
    
    
    
  <entry>
    <title>在 Open WebUI 中使用 Gemini 2.5 TTS 模型</title>
    <id>https://huangboming.com/posts/using-gemini-tts-in-open-webui/</id>
    <link rel="alternate" type="text/html" href="https://huangboming.com/posts/using-gemini-tts-in-open-webui/" />
    <published>2025-06-25T00:00:00+08:00</published>
    <updated>2026-07-16T00:13:32+08:00</updated>
    <author>
      <name>Boming Huang</name>
      <uri>https://huangboming.com/about/</uri>
    </author>
    <category term="教程" />
    <summary type="text">介绍如何将 Gemini 2.5 TTS 模型通过自建转换服务集成到 Open WebUI 中，实现自然流畅的语音朗读。</summary>
    <content type="html" xml:base="https://huangboming.com/posts/using-gemini-tts-in-open-webui/">&lt;p&gt;在今年的 I/O 大会上，Google 推出了 Gemini 2.5 系列 TTS (text-to-speech) 模型的预览版，包括 Gemini 2.5 Flash 和 Gemini 2.5 Pro。用户可以在 &lt;a href=&quot;https://aistudio.google.com/generate-speech&quot;&gt;AI Studio&lt;/a&gt; 上免费体验。免费层级的 AI Studio API 用户也有一定的试用额度，具体可参见&lt;a href=&quot;https://ai.google.dev/gemini-api/docs/rate-limits#free-tier&quot;&gt;官方文档&lt;/a&gt;。&lt;/p&gt;

&lt;p&gt;初步体验过后，我发现它生成的语音流畅、自然，几乎听不出明显的机器音。虽然官方文档上没有明确说明支持中文，但实测下来发现可用，而且效果还可以。&lt;/p&gt;

&lt;p&gt;我最近一直在使用 Open WebUI，它内置的 TTS 功能可以朗读对话内容。于是我萌生了将 Gemini 2.5 TTS 集成进 Open WebUI 的想法。经过一番研究，我发现 Open WebUI 并不支持 Gemini 的 API 格式，但兼容 OpenAI 的格式。&lt;/p&gt;

&lt;p&gt;于是，我借助 AI 快速开发了一个简单的&lt;a href=&quot;https://github.com/huangboming/gemini-to-openai-tts&quot;&gt;转换服务&lt;/a&gt;，它能将 OpenAI 格式的 TTS 请求转换为 Gemini API 所需的格式，然后调用 Gemini API 获取音频并返回。通过这个服务，我们就能在 Open WebUI 中无缝使用 Gemini 2.5 TTS 模型。如果你觉得这个项目对你有帮助，欢迎在 GitHub 上给我一个 star。&lt;/p&gt;

&lt;h2 id=&quot;部署服务&quot;&gt;部署服务&lt;/h2&gt;

&lt;h3 id=&quot;使用-docker&quot;&gt;使用 Docker&lt;/h3&gt;

&lt;p&gt;首先，你需要创建一个 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.env&lt;/code&gt; 文件来配置环境变量（可参考项目中的 &lt;a href=&quot;https://github.com/huangboming/gemini-to-openai-tts/blob/main/.env.example&quot;&gt;.env.example&lt;/a&gt; 文件）：&lt;/p&gt;
&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;table class=&quot;rouge-table&quot;&gt;&lt;tbody&gt;&lt;tr&gt;
&lt;td class=&quot;rouge-gutter gl&quot;&gt;&lt;pre class=&quot;lineno&quot;&gt;1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&quot;rouge-code&quot;&gt;&lt;pre&gt;# .env.example - 环境变量配置模板
# 复制此文件为 .env 并填入你的实际配置

# === 服务认证配置 ===
# 客户端访问此服务时需要提供的 API 密钥（可以是多个，用逗号分隔）
# 建议使用强密码生成器生成 32+ 位的随机字符串
API_KEYS=&quot;your_secret_api_key_1,your_secret_api_key_2&quot;

# === 上游 API 配置 ===
# 你的 Google Gemini API 密钥
# 获取方式：https://aistudio.google.com/apikey
GEMINI_API_KEY=&quot;your_google_gemini_api_key_here&quot;

# === 应用配置 ===
# 日志级别：DEBUG, INFO, WARNING, ERROR
# 开发环境推荐使用 DEBUG，生产环境推荐使用 INFO
LOG_LEVEL=INFO
&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;配置完成后，可以直接使用我打包好的镜像，使用以下命令即可一键运行服务：&lt;/p&gt;
&lt;div class=&quot;language-shell highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;table class=&quot;rouge-table&quot;&gt;&lt;tbody&gt;&lt;tr&gt;
&lt;td class=&quot;rouge-gutter gl&quot;&gt;&lt;pre class=&quot;lineno&quot;&gt;1
2
3
4
5
6
&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&quot;rouge-code&quot;&gt;&lt;pre&gt;docker run &lt;span class=&quot;nt&quot;&gt;-d&lt;/span&gt; &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
  &lt;span class=&quot;nt&quot;&gt;--name&lt;/span&gt; gemini-tts &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
  &lt;span class=&quot;nt&quot;&gt;-p&lt;/span&gt; 8000:8000 &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
  &lt;span class=&quot;nt&quot;&gt;--env-file&lt;/span&gt; .env &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
  &lt;span class=&quot;nt&quot;&gt;--restart&lt;/span&gt; unless-stopped &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
  boming/gemini-to-openai-tts:latest
&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;本机部署&quot;&gt;本机部署&lt;/h3&gt;

&lt;p&gt;如果你希望在本地直接运行，步骤同样很简单。项目提供了一个 Makefile 来简化流程：&lt;/p&gt;
&lt;ol&gt;
  &lt;li&gt;克隆仓库： &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;git clone https://github.com/huangboming/gemini-to-openai-tts&lt;/code&gt;
&lt;/li&gt;
  &lt;li&gt;进入项目目录： &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;cd gemini-to-openai-tts&lt;/code&gt;
&lt;/li&gt;
  &lt;li&gt;配置环境变量： &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;cp .env.example .env&lt;/code&gt;，然后修改 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.env&lt;/code&gt; 文件，具体说明同上一节。&lt;/li&gt;
  &lt;li&gt;安装依赖：&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;make install&lt;/code&gt;
&lt;/li&gt;
  &lt;li&gt;运行服务： &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;make run&lt;/code&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;服务启动后，你可以在 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;http://&amp;lt;你的IP&amp;gt;:8000&lt;/code&gt; 访问它。&lt;/p&gt;

&lt;h2 id=&quot;配置-open-webui&quot;&gt;配置 Open WebUI&lt;/h2&gt;

&lt;p&gt;Open WebUI 的配置过程与设置标准的 OpenAI TTS 类似，只需修改 API 端点和密钥即可。&lt;/p&gt;

&lt;p&gt;具体配置如下：&lt;/p&gt;
&lt;ol&gt;
  &lt;li&gt;在 Open WebUI 中打开管理员面板&lt;/li&gt;
  &lt;li&gt;导航至 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;设置 -&amp;gt; 语音&lt;/code&gt;
&lt;/li&gt;
  &lt;li&gt;配置以下设置：
    &lt;ul&gt;
      &lt;li&gt;将 TTS API 端点设置为你的服务 URL（例如：&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;http://localhost:8000/v1/audio/speech&lt;/code&gt;）&lt;/li&gt;
      &lt;li&gt;在认证字段中添加你的 API key，这里是上面环境变量中 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;API_KEYS&lt;/code&gt; 中的一个&lt;/li&gt;
      &lt;li&gt;从可用选项中选择你喜欢的语音&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;一个配置示例如下：&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;https://huangboming.com/assets/images/using-gemini-tts-in-open-webui/1.png&quot; alt=&quot;Open WebUI TTS 配置示例&quot; w=&quot;1348&quot; h=&quot;1202&quot; class=&quot;shadow&quot;&gt;
&lt;em&gt;Open WebUI TTS 配置界面&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;最后有一个小提示：如果你使用的是免费层级的 Gemini API key，建议将“拆分回复”选项设置为 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;paragraphs&lt;/code&gt; (段落) 或 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;none&lt;/code&gt; (不拆分)。因为免费版 API 每分钟的请求次数有限（3 次/分钟，15 次/天），如果按句子拆分，很容易超出额度。&lt;/p&gt;
</content>
  </entry>
  
    
    
    
    
  <entry>
    <title>深圳出发，经香港机场往返杭州</title>
    <id>https://huangboming.com/posts/shenzhen-to-hangzhou-via-hong-kong-airport/</id>
    <link rel="alternate" type="text/html" href="https://huangboming.com/posts/shenzhen-to-hangzhou-via-hong-kong-airport/" />
    <published>2025-06-13T00:00:00+08:00</published>
    <updated>2026-07-21T17:32:08+08:00</updated>
    <author>
      <name>Boming Huang</name>
      <uri>https://huangboming.com/about/</uri>
    </author>
    <category term="随笔" />
    <summary type="text">分享从深圳出发经香港机场往返杭州的详细通关记录，包括出行前准备、交通路线、避坑经验，以及全程费用与时间总结。</summary>
    <content type="html" xml:base="https://huangboming.com/posts/shenzhen-to-hangzhou-via-hong-kong-airport/">&lt;p&gt;坐标深圳，今年端午假期计划去杭州。在查询机票时发现，从香港出发的航班价格比从深圳出发的航班要低许多，而且往返的起飞时间都在下午，堪称完美。而且，对我而言去香港机场比去宝安机场更近、更方便。于是就有了这次“借道”香港的出行。&lt;/p&gt;

&lt;p&gt;整趟行程下来，除机票外的交通成本只有 68.5 港币，比在深圳本地打车去机场还便宜。&lt;/p&gt;

&lt;p&gt;这篇文章是一份简单的“通关”记录，希望能帮到有同样计划的朋友。我会在这篇文章中详细地说明我往返时的行程经历，以及碰到的问题。但这篇文章不会有很多配图，因为当时出发时没有想到在 blog 中记录行程，就没有刻意拍照，请大家见谅。&lt;/p&gt;

&lt;h2 id=&quot;出行前准备&quot;&gt;出行前准备&lt;/h2&gt;

&lt;p&gt;首先，也是最重要的是机票。我在携程上购票。在携程上直接搜索香港到杭州的往返机票，选好日期，然后选择合适的往返机票组合。这里需要特别注意的是，&lt;strong&gt;要使用港澳通行证来购票&lt;/strong&gt;。不要使用大陆的身份证，也不推荐使用护照（据说可以但不推荐），护照一般飞国外才会使用。&lt;/p&gt;

&lt;p&gt;通行证证件号码填通行证正面右上角的号码，具体可以参考维基百科：&lt;a href=&quot;https://zh.wikipedia.org/zh-hans/%E5%BE%80%E6%9D%A5%E6%B8%AF%E6%BE%B3%E9%80%9A%E8%A1%8C%E8%AF%81#%E5%BC%8F%E6%A0%B7&quot;&gt;往来港澳通行证&lt;/a&gt;。&lt;/p&gt;

&lt;p&gt;买好机票之后，你还需要查看一下机票所附赠的行李额，确保自己带的行李符合要求。&lt;/p&gt;

&lt;p&gt;其它还需要准备的东西有：&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;通行香港的一年多签签注。这条路线需要两次签注：深圳出境到香港一次，杭州飞抵香港入境一次。如果你的通行证是一年多签，一次签注可以在有效期内多次使用；如果是一次签注，你可以先办理一次签注。到目的地之后，在当地找签注机或者出入境再签一次。&lt;/li&gt;
  &lt;li&gt;去和回当天开通手机漫游流量，保证能够在香港支付和通信。&lt;/li&gt;
  &lt;li&gt;八达通。使用支付宝/微信也可以，因为全程只有乘坐巴士需要港币。&lt;/li&gt;
  &lt;li&gt;一些港币零钱。用于防止意外情况。&lt;/li&gt;
&lt;/ol&gt;

&lt;h2 id=&quot;出发&quot;&gt;出发&lt;/h2&gt;

&lt;h3 id=&quot;深圳---香港机场-t1-航站楼&quot;&gt;深圳 -&amp;gt; 香港机场 T1 航站楼&lt;/h3&gt;

&lt;p&gt;2024 年底，深圳 13 号线一期南段（深圳湾口岸至高新中段）正式开通。从深圳出发，可以乘坐 13 号线到深圳湾口岸站，从 C 口（站内也有提示）出，进入旅检大楼。&lt;/p&gt;

&lt;p&gt;一路跟着人流向前走，检行李，排队，过闸机。一共需要过两个闸机：一个是出（大陆）境，一个是入（香港）境。&lt;/p&gt;

&lt;p&gt;过闸机之后，也是一路向前走。出旅检大楼就是乘坐巴士、出租车的地方。如果你比较赶时间，可以乘坐出租车。如果不堵车的话半小时左右就能到机场。据说也有直达机场的巴士，就是价格会稍高一些，行程在四五十分钟左右。&lt;/p&gt;

&lt;p&gt;因为我的时间比较充裕，加上想体验一些新路线，我选择乘坐 B3X，坐一站到紅橋站下车（大约坐半小时，花费 16.5 港币）。按照我的计划，在紅橋站下车，等 A36 路巴士，一直可以坐到香港机场 T1 航站楼。&lt;/p&gt;

&lt;p&gt;本来我以为，最多等个二十分钟就能上车了。结果最后等了快一个小时，而且整个等车的过程非常煎熬。&lt;/p&gt;

&lt;p&gt;首先，等车的人很多，等车的队伍大概有六七米。除开之前在等车的人，我乘坐的 B3X 也有很多人在这一站下，其中大部分也是等 A36 转到香港机场。&lt;/p&gt;

&lt;p&gt;其次，A36 巴士 25 分钟才有一班车&lt;sup id=&quot;fnref:1&quot;&gt;&lt;a href=&quot;https://huangboming.com/posts/shenzhen-to-hangzhou-via-hong-kong-airport/#fn:1&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot; role=&quot;doc-noteref&quot;&gt;1&lt;/a&gt;&lt;/sup&gt;。不像内地，可能十几分钟就能等到车。&lt;/p&gt;

&lt;p&gt;更糟糕的是，好不容易等来的车上都是人，根本上不去，只能等下一趟。&lt;sup id=&quot;fnref:2&quot;&gt;&lt;a href=&quot;https://huangboming.com/posts/shenzhen-to-hangzhou-via-hong-kong-airport/#fn:2&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot; role=&quot;doc-noteref&quot;&gt;2&lt;/a&gt;&lt;/sup&gt;&lt;/p&gt;

&lt;p&gt;还有一个让人不舒服的点是，紅橋站在一个车来车往的路边，虽然有遮挡不会晒太阳，但等车的过程充满了鸣笛声和扬尘。&lt;/p&gt;

&lt;p&gt;在大约一个小时之后，我终于挤上 A36，一直坐到一號客運大樓站（也就是香港机场 T1 航站楼）。中间有一小段路堵车的情况下，从坐上车到机场大约花了二十分钟。&lt;/p&gt;

&lt;p&gt;我总结出了一些教训：&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;如果赶时间，直接选择直达巴士（推荐）或者出租车（非常贵）。考虑到堵车因素，稳一点的话从上车到预留至少四十分钟到一小时&lt;/li&gt;
  &lt;li&gt;如果不赶时间，想省钱，可以走我这条路。到紅橋站之后，可以考虑在紅橋站转乘其他路线到较前面的站点，再换乘（具体可以查询谷歌地图），不要傻傻等 A36&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;香港机场&quot;&gt;香港机场&lt;/h3&gt;

&lt;p&gt;坐巴士到达一號客運大樓站之后，下车就是 T1 航站楼。进入航站楼，第一件事就是找所乘坐航班对应的值机柜台。如果不需要托运行李，可以直接找一个自助值机机器，在机器上刷购票所用的证件（这里是港澳通行证）自助办理值机、选座、领纸质登机牌。如果需要托运行李，就要去对应值机柜台办理。&lt;/p&gt;

&lt;p&gt;领取登机牌之后，下一步是沿着标识去离（香港）境处，安检。和一般的机场安检流程差不多。这一步听不懂粤语也没关系，大概理解个意思就行。一般保安就是提醒游客不要携带液体，电子设备（iPad、电脑、手机、充电宝等）单独放到一个篮子过机&lt;sup id=&quot;fnref:3&quot;&gt;&lt;a href=&quot;https://huangboming.com/posts/shenzhen-to-hangzhou-via-hong-kong-airport/#fn:3&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot; role=&quot;doc-noteref&quot;&gt;3&lt;/a&gt;&lt;/sup&gt;。&lt;/p&gt;

&lt;p&gt;过安检之后，再向前走就是离境闸机，刷港澳通行证离境即可。&lt;/p&gt;

&lt;p&gt;过闸机之后，就正式进入香港机场内部。整个香港机场很大，有很多可以逛的地方。但是建议先看看自己登机牌或者手机上的登机口，合理安排游玩时间。机场内有免税店、给小朋友玩耍的游乐场、可以俯瞰香港机场的观景台、还价格比香港市中心稍贵一些的食阁（food court）。因为时间关系，我稍微逛了一会就去登机口等待登机，有很多地方没能逛。&lt;/p&gt;

&lt;p&gt;小贴士：&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;机场内有免费 WiFi 且网速不错&lt;/li&gt;
  &lt;li&gt;登机口前的座椅都有充电口，手机没电了可以稍微充一会。&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;后续的过程就比较简单，因为一般飞往内地的航空都是内地的航空，直接普通话就好，不用担心语言隔阂。登机，等待起飞。&lt;/p&gt;

&lt;p&gt;我乘坐的这一班飞机非常奇怪：准点登机，但是在飞机上等了四十分钟才起飞。起飞时机长说香港到杭州只需要飞两个小时，但机票上写的两个半小时。最后真的准时到达杭州萧山机场。&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;https://huangboming.com/assets/images/shenzhen-to-hangzhou-via-hong-kong-airport/1.webp&quot; alt=&quot;在飞机上拍的环形彩虹&quot; w=&quot;700&quot; h=&quot;525&quot;&gt;
&lt;em&gt;在飞机上拍的环形彩虹&lt;/em&gt;&lt;/p&gt;

&lt;h3 id=&quot;萧山国际机场&quot;&gt;萧山国际机场&lt;/h3&gt;

&lt;p&gt;大约飞了两个小时，飞机成功在萧山国际机场降落。下飞机之后，坐摆渡车到 T4 航站楼。一路沿着“国际游客入境”（大意如此，具体我也记不太清了）标识向前走，来到行李转盘。领取行李之后，到入境处刷港澳通行证入境。&lt;/p&gt;

&lt;p&gt;入境之后，就比较随意。可以打车，也可以坐 19 号线地铁（T4 航站楼离地铁有点距离，大概有个六七百米）。机场离市区比较远，坐地铁到西湖附近要四五十分钟。&lt;/p&gt;

&lt;h2 id=&quot;返程&quot;&gt;返程&lt;/h2&gt;

&lt;h3 id=&quot;萧山国际机场-1&quot;&gt;萧山国际机场&lt;/h3&gt;

&lt;p&gt;我在返程当天搭乘 19 号线到萧山国际机场，步行到 T4 航站楼。&lt;/p&gt;

&lt;p&gt;机场内没有自助值机机器，所以只能到航班对应柜台处办理值机，领取登机牌。办理时工作人员会查验港澳通行证，看看背面的签注信息，询问一些问题。&lt;/p&gt;

&lt;p&gt;领到登机牌之后，前往出境处。首先刷登机牌入闸。继续向前走是出境和机场安检。工作人员会要求查看登机牌以及港澳通行证，以及刷人脸；安检就是正常的机场安检，没有特别值得提的地方。&lt;/p&gt;

&lt;p&gt;过安检之后，还需要刷一次港澳通行证过闸机，就像我们在旅检大楼出境一样（具体步骤记忆有些模糊，建议出行时留意现场指引）。过闸机之后就是机场内部。&lt;/p&gt;

&lt;p&gt;我当前比较赶时间，就没有逛机场，直奔登机口，登机，飞回香港。&lt;/p&gt;

&lt;h3 id=&quot;香港机场---深圳&quot;&gt;香港机场 -&amp;gt; 深圳&lt;/h3&gt;

&lt;p&gt;到达香港机场 T1 航站楼之后，下飞机，跟着人流一路向前走很长一段距离，来到入境处。直接刷港澳通行证入境即可，不需要再安检。&lt;/p&gt;

&lt;p&gt;入境之后，沿着路标，找前往市区的巴士。注意不要找不要找往内地或者澳门的巴士，这些巴士是我之前说过的直达巴士，会比较贵。&lt;/p&gt;

&lt;p&gt;一路沿着路标，走出机场，来到機場 (地面運輸中心) 總站。到这里之后，你可以自行使用谷歌地图规划路线。我选择的路线是，A34 坐 3 站到蝴蝶站下车（大约二十分钟，花费 15.7 港币），然后在蝴蝶站等 B3，坐 B3 一路到深圳湾口岸下车（大约三四十分钟，花费 16.5 港币）。&lt;/p&gt;

&lt;p&gt;到达深圳湾口岸之后，下车，进入旅检中心，刷通行证入境，安检，进入深圳。&lt;/p&gt;

&lt;h2 id=&quot;费用时间总结&quot;&gt;费用、时间总结&lt;/h2&gt;

&lt;ul&gt;
  &lt;li&gt;去程：B3X (16.5 港币、半小时) + 等车一小时 + A36 (19.8 港币、半小时) = 36.3 港币、两小时&lt;/li&gt;
  &lt;li&gt;回程：A34 (15.7 港币、半小时) + 等车半小时 + B3 (16.5 港币、四十分钟) = 32.2 港币、一小时四十分钟&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;尾记&quot;&gt;尾记&lt;/h2&gt;

&lt;p&gt;香港机场有&lt;a href=&quot;https://www.hongkongairport.com/sc/passenger-guide/departures/air-passenger-departure-tax.page&quot;&gt;离境税&lt;/a&gt;——搭乘飞机离开香港，一般需要缴 120 港币的离境税。一般来说，这笔税会包含在机票价格中。&lt;/p&gt;

&lt;p&gt;最近有&lt;a href=&quot;https://finance.sina.com.cn/stock/hkstock/hkstocknews/2025-06-11/doc-inezsutk8032190.shtml&quot;&gt;新闻&lt;/a&gt;称，港府草拟&lt;a href=&quot;https://www.info.gov.hk/gia/general/202506/11/P2025061100326.htm?fontSize=3&quot;&gt;《2025 年飞机乘客离境税条例(修订附表 2)令》&lt;/a&gt;，打算扩大离境税豁免范围。其中有一条是：&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;以乘搭飞机以外的方式经过出入境检查抵达香港，然后于抵达当日或下一日于机场乘搭飞机离境的乘客(即最多四十八小时)。条例将加入豁除条文，以防止个别人士刻意在短时间内往返香港和内地或澳门以符合豁免离境税资格。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;如果我没有理解错，这一条包括我们这些从深圳到香港机场搭乘飞机飞内地的乘客。这样一看，好像从香港飞内地的性价比又更高了。希望这项修订令能够通过立法会并在今年 10 月 1 日生效。&lt;/p&gt;

&lt;hr&gt;

&lt;h2 id=&quot;脚注&quot;&gt;脚注&lt;/h2&gt;

&lt;div class=&quot;footnotes&quot; role=&quot;doc-endnotes&quot;&gt;
  &lt;ol&gt;
    &lt;li id=&quot;fn:1&quot;&gt;
      &lt;p&gt;参见&lt;a href=&quot;https://hkbus.fandom.com/wiki/%E9%BE%8D%E9%81%8B%E5%B7%B4%E5%A3%ABA36%E7%B7%9A&quot;&gt;龍運巴士 A36 線&lt;/a&gt; &lt;a href=&quot;https://huangboming.com/posts/shenzhen-to-hangzhou-via-hong-kong-airport/#fnref:1&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;↩︎&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
    &lt;li id=&quot;fn:2&quot;&gt;
      &lt;p&gt;因为紅橋站临近终点站，而且途经&lt;a href=&quot;https://hkbus.fandom.com/wiki/%E6%B8%AF%E7%8F%A0%E6%BE%B3%E5%A4%A7%E6%A9%8B%E9%A6%99%E6%B8%AF%E5%8F%A3%E5%B2%B8%E6%97%85%E6%AA%A2%E5%A4%A7%E6%A8%93&quot;&gt;港珠澳大橋香港口岸旅檢大樓&lt;/a&gt;。很多人在港珠澳大橋香港口岸旅檢大樓站下车。当天是周五，我猜测是香港人从这里出境，乘坐巴士去珠海或者澳门旅游。 &lt;a href=&quot;https://huangboming.com/posts/shenzhen-to-hangzhou-via-hong-kong-airport/#fnref:2&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;↩︎&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
    &lt;li id=&quot;fn:3&quot;&gt;
      &lt;p&gt;具体要求可以看&lt;a href=&quot;https://www.hongkongairport.com/tc/passenger-guide/airport-security/&quot;&gt;香港机场的旅客指南&lt;/a&gt; &lt;a href=&quot;https://huangboming.com/posts/shenzhen-to-hangzhou-via-hong-kong-airport/#fnref:3&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;↩︎&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
  &lt;/ol&gt;
&lt;/div&gt;
</content>
  </entry>
  
    
    
    
    
  <entry>
    <title>分享一套 AI 略读方法论</title>
    <id>https://huangboming.com/posts/using-ai-for-pre-reading/</id>
    <link rel="alternate" type="text/html" href="https://huangboming.com/posts/using-ai-for-pre-reading/" />
    <published>2025-05-12T00:00:00+08:00</published>
    <updated>2026-07-21T17:32:08+08:00</updated>
    <author>
      <name>Boming Huang</name>
      <uri>https://huangboming.com/about/</uri>
    </author>
    <category term="心得" />
    <summary type="text">分享一套用 AI 略读文章的方法论：用结构化提示词引导 AI 深度理解原文，再用“用大白话解释”获取通俗易懂的核心内容。</summary>
    <content type="html" xml:base="https://huangboming.com/posts/using-ai-for-pre-reading/">&lt;p&gt;我习惯用 RSS 订阅各种信息源，并且每天花一些时间筛选我感兴趣的内容来阅读。为此，我还为自己制作了一份 &lt;a href=&quot;https://github.com/huangboming/huggingface-daily-paper-feed&quot;&gt;Hugging face daily paper 的 RSS feed&lt;/a&gt;。&lt;/p&gt;

&lt;p&gt;RSS 的主要问题是信息过载——每天动辄几十上百条新内容推送。我的对策是：&lt;/p&gt;
&lt;ol&gt;
  &lt;li&gt;不为推送信息过多而感到焦虑。一次读不完所有推送也无妨，可以之后再读。&lt;/li&gt;
  &lt;li&gt;每天花一段固定的时间，从中挑选出我感兴趣的内容。&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;这样筛选一轮下来，每天仍有 5 到 20 篇新闻、博客或论文等着我。这个数量其实也不少，要把它们通读一遍相当花时间。于是，我想了一个办法：让 AI 帮助我略读——总结文章的核心内容、思想。略读之后，我再决定要不要精读或者记录文献笔记。在精读时，碰到什么不理解的地方还可以随时请教 AI。&lt;/p&gt;

&lt;h2 id=&quot;略读提示词&quot;&gt;略读提示词&lt;/h2&gt;

&lt;p&gt;下面是我设计的 AI 略读提示词：&lt;/p&gt;

&lt;div class=&quot;language-markdown highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;table class=&quot;rouge-table&quot;&gt;&lt;tbody&gt;&lt;tr&gt;
&lt;td class=&quot;rouge-gutter gl&quot;&gt;&lt;pre class=&quot;lineno&quot;&gt;1
2
3
4
5
6
7
8
9
10
11
12
13
14
&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&quot;rouge-code&quot;&gt;&lt;pre&gt;Write a comprehensive and structured summary (1,000-2,000 words) of the provided text, ensuring clarity, depth, and coherence. The summary should be structured around the following four analytical dimensions:
&lt;span class=&quot;p&quot;&gt;
1.&lt;/span&gt; Structural Overview: Clearly outline the main theme, central argument, and overall structure of the text.
&lt;span class=&quot;p&quot;&gt;2.&lt;/span&gt; Analytical Breakdown: Explain how the author supports their arguments, including key concepts, evidence, reasoning, and examples.
&lt;span class=&quot;p&quot;&gt;3.&lt;/span&gt; Critical Evaluation: Assess the text’s persuasiveness, strengths, weaknesses, biases, and alternative perspectives. Maintain an objective tone unless otherwise specified.
&lt;span class=&quot;p&quot;&gt;4.&lt;/span&gt; Practical Application: Discuss how the text’s ideas can be applied in real life, considering relevance, impact, and actionable insights.

Adapt the summary style to the nature of the text (e.g., academic tone for research papers, engaging style for blogs). For academic works, cite key arguments with paraphrased points or direct quotes where appropriate. If summarizing a narrative or literary work, maintain fidelity to its themes and tone.

&lt;span class=&quot;gu&quot;&gt;## Constraints:&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;
-&lt;/span&gt; Maintain an objective, third-person tone unless explicitly instructed otherwise.
&lt;span class=&quot;p&quot;&gt;-&lt;/span&gt; Avoid excessive subjective interpretation unless required.
&lt;span class=&quot;p&quot;&gt;-&lt;/span&gt; Ensure coherence between sections to create a seamless, logically flowing summary.
&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;这个提示词的设计借鉴了《如何阅读一本书》中的思想——要了解一本书，你需要回答四个主要问题&lt;sup id=&quot;fnref:1&quot;&gt;&lt;a href=&quot;https://huangboming.com/posts/using-ai-for-pre-reading/#fn:1&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot; role=&quot;doc-noteref&quot;&gt;1&lt;/a&gt;&lt;/sup&gt;：&lt;/p&gt;
&lt;ol&gt;
  &lt;li&gt;整体来看，这本书到底在谈些什么？找到这本书的主题、核心论点、以及整本书的论述架构&lt;/li&gt;
  &lt;li&gt;具体来看，作者怎么论述书中的论点？&lt;/li&gt;
  &lt;li&gt;从批判性的角度来看，这本书说得有道理吗？&lt;/li&gt;
  &lt;li&gt;从应用的角度来看，这本书对我有什么用？怎么应用到现实中？&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;我更推荐使用英文提示词，主要有两个原因：一是 AI 模型通常接受了更多的英文训练，因此能更准确地理解英文指令中的细节。二是英文提示词所消耗的 token 数量更少，成本更低。&lt;/p&gt;

&lt;p&gt;把这份提示词以及你要阅读的文本一并发送给 AI，它会生成一份 1000 到 2000 词的英文总结。我们并不需要阅读这份总结&lt;sup id=&quot;fnref:2&quot;&gt;&lt;a href=&quot;https://huangboming.com/posts/using-ai-for-pre-reading/#fn:2&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot; role=&quot;doc-noteref&quot;&gt;2&lt;/a&gt;&lt;/sup&gt;——它的真正目的是引导 AI 深度理解原文，并提炼核心内容。&lt;/p&gt;

&lt;p&gt;最关键的一步是，AI 生成总结后，追加一句“用大白话解释”&lt;sup id=&quot;fnref:3&quot;&gt;&lt;a href=&quot;https://huangboming.com/posts/using-ai-for-pre-reading/#fn:3&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot; role=&quot;doc-noteref&quot;&gt;3&lt;/a&gt;&lt;/sup&gt;，AI 就会用通俗易懂的大白话为你解释文章的主要内容。&lt;/p&gt;

&lt;p&gt;“用大白话解释”是一个颇具魔力的提示词。它能让 AI 使用简单明了的语言解释复杂概念，就像一位朋友在和你聊天一样，从而极大地降低阅读理解的难度。它可以用在很多地方，比如你让 AI 给你解释一个复杂概念时，如果你觉得它还没解释清楚，不妨试试“用大白话解释”。&lt;/p&gt;

&lt;h2 id=&quot;示例一在-open-webui-中阅读网页&quot;&gt;示例一：在 Open WebUI 中阅读网页&lt;/h2&gt;

&lt;p&gt;阅读博客、新闻这类网页时，推荐使用 Open WebUI 自带的网页抓取功能，先抓取网页中的文本&lt;sup id=&quot;fnref:4&quot;&gt;&lt;a href=&quot;https://huangboming.com/posts/using-ai-for-pre-reading/#fn:4&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot; role=&quot;doc-noteref&quot;&gt;4&lt;/a&gt;&lt;/sup&gt;，再交 AI 总结。&lt;/p&gt;

&lt;p&gt;操作很简单：在 Open WebUI 对话框中输入 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;#&lt;/code&gt;，紧接着粘贴或输入目标网址，回车即可。Open WebUI 便会自动抓取页面文本。比如说，要阅读&lt;a href=&quot;https://notashelf.dev/posts/curse-of-knowing&quot;&gt;这篇博客&lt;/a&gt;，可以在对话框中输入 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;#https://notashelf.dev/posts/curse-of-knowing&lt;/code&gt;，然后回车。&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;https://huangboming.com/assets/images/using-ai-for-pre-reading/1.png&quot; alt=&quot;输入# + 文章 URL&quot; class=&quot;shadow&quot; w=&quot;700&quot; h=&quot;573&quot;&gt;
&lt;em&gt;输入“#”和目标网址&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;https://huangboming.com/assets/images/using-ai-for-pre-reading/2.png&quot; alt=&quot;输入# + 文章 URL 后回车&quot; class=&quot;shadow&quot; w=&quot;700&quot; h=&quot;660&quot;&gt;
&lt;em&gt;回车后，Open WebUI 自动抓取网页内容&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;接着，将前述的 AI 略读提示词输入对话框并发送，让 AI 先理解、总结文章：&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;https://huangboming.com/assets/images/using-ai-for-pre-reading/3.png&quot; alt=&quot;输入 AI 略读提示词&quot; class=&quot;shadow&quot; w=&quot;700&quot; h=&quot;659&quot;&gt;
&lt;em&gt;发送 AI 略读提示词&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;最后，再补上一句“用大白话解释”：&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;https://huangboming.com/assets/images/using-ai-for-pre-reading/4.png&quot; alt=&quot;输入“用大白话解释”&quot; class=&quot;shadow&quot; w=&quot;700&quot; h=&quot;657&quot;&gt;
&lt;em&gt;发送“用大白话解释”指令后，AI 输出通俗易懂的解释&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;可以看到 AI 生成的解释通俗易懂，核心内容一目了然。&lt;/p&gt;

&lt;h2 id=&quot;示例二在-google-ai-studio-中阅读-pdf&quot;&gt;示例二：在 Google AI studio 中阅读 PDF&lt;/h2&gt;

&lt;p&gt;对于 PDF 格式的内容（比如学术论文），如果你没有配置好 Open WebUI 的 Content Extraction Engine 以及 RAG 功能，我更推荐直接在 &lt;a href=&quot;https://aistudio.google.com&quot;&gt;Google AI studio&lt;/a&gt; 上阅读。它会通过 OCR 技术自动提取 PDF 文本&lt;sup id=&quot;fnref:5&quot;&gt;&lt;a href=&quot;https://huangboming.com/posts/using-ai-for-pre-reading/#fn:5&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot; role=&quot;doc-noteref&quot;&gt;5&lt;/a&gt;&lt;/sup&gt;，不需要你自己提取，非常方便。&lt;/p&gt;

&lt;p&gt;步骤也同样简单：访问 AI Studio，上传 PDF，然后依次使用 AI 略读提示词和“用大白话解释”。&lt;/p&gt;

&lt;p&gt;下面以 &lt;a href=&quot;https://arxiv.org/abs/2504.20879&quot;&gt;The Leaderboard Illusion&lt;/a&gt; 这篇论文为例。&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;https://huangboming.com/assets/images/using-ai-for-pre-reading/5.png&quot; alt=&quot;上传 PDF 文件&quot; class=&quot;shadow&quot; w=&quot;700&quot; h=&quot;402&quot;&gt;
&lt;em&gt;在 Google AI Studio 上传 PDF 文件&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;https://huangboming.com/assets/images/using-ai-for-pre-reading/6.png&quot; alt=&quot;AI 略读提示词 + “用大白话解释”之后的效果&quot; class=&quot;shadow&quot; w=&quot;700&quot; h=&quot;598&quot;&gt;
&lt;em&gt;使用 AI 略读提示词及“用大白话解释”指令后的输出效果&lt;/em&gt;&lt;/p&gt;

&lt;hr&gt;

&lt;h2 id=&quot;脚注&quot;&gt;脚注&lt;/h2&gt;

&lt;div class=&quot;footnotes&quot; role=&quot;doc-endnotes&quot;&gt;
  &lt;ol&gt;
    &lt;li id=&quot;fn:1&quot;&gt;
      &lt;p&gt;莫提默 J. 艾得勒, 查尔斯 范多伦著 ; 郝明义, 朱衣译. 如何阅读一本书. 第一版. 北京: 商务印书馆, 2004. 这四个主要问题可以在第五章找到 &lt;a href=&quot;https://huangboming.com/posts/using-ai-for-pre-reading/#fnref:1&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;↩︎&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
    &lt;li id=&quot;fn:2&quot;&gt;
      &lt;p&gt;这份总结很可能比原文长，读它不如直接去读原文 &lt;a href=&quot;https://huangboming.com/posts/using-ai-for-pre-reading/#fnref:2&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;↩︎&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
    &lt;li id=&quot;fn:3&quot;&gt;
      &lt;p&gt;我从和菜头的一篇文章中发现了这个神奇的提示词，详见：&lt;a href=&quot;https://www.hecaitou.com/2025/01/Deepseek-Advanced-Usage-Guide.html&quot;&gt;deepseek 进阶使用指南&lt;/a&gt; &lt;a href=&quot;https://huangboming.com/posts/using-ai-for-pre-reading/#fnref:3&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;↩︎&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
    &lt;li id=&quot;fn:4&quot;&gt;
      &lt;p&gt;只抓取文本内容，并不会抓取图片。对于多图且图片对于内容很重要的网页，建议导出成 PDF，在 AI studio 中阅读 &lt;a href=&quot;https://huangboming.com/posts/using-ai-for-pre-reading/#fnref:4&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;↩︎&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
    &lt;li id=&quot;fn:5&quot;&gt;
      &lt;p&gt;AI studio 文档中没有明确说明它用 OCR 提取 PDF 中的文本内容。我在一次实验中发现这一点：上传一个 PDF 文档，然后输入“output the first page of the PDF, do not change anything I provided to you”。Gemini 输出的开头结尾会带有“Start of OCR for page 1”和“End of OCR for page 1” &lt;a href=&quot;https://huangboming.com/posts/using-ai-for-pre-reading/#fnref:5&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;↩︎&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
  &lt;/ol&gt;
&lt;/div&gt;
</content>
  </entry>
  
    
    
    
    
  <entry>
    <title>申请 Gemini API key 并在 Open WebUI 中配置使用</title>
    <id>https://huangboming.com/posts/get-gemini-api-key/</id>
    <link rel="alternate" type="text/html" href="https://huangboming.com/posts/get-gemini-api-key/" />
    <published>2025-05-06T00:00:00+08:00</published>
    <updated>2026-07-21T17:32:08+08:00</updated>
    <author>
      <name>Boming Huang</name>
      <uri>https://huangboming.com/about/</uri>
    </author>
    <category term="教程" />
    <summary type="text">手把手教你免费申请 Gemini API key，并通过 OpenAI API connections 和 Open WebUI 函数两种方式在 Open WebUI 中配置使用，同时介绍如何开启 Gemini 原生的联网搜索功能。</summary>
    <content type="html" xml:base="https://huangboming.com/posts/get-gemini-api-key/">&lt;p&gt;部署好 Open WebUI 之后，下一步就是为它接入语言模型。对于初学者，我最推荐的是 Gemini。&lt;/p&gt;

&lt;p&gt;首先，可能也是最重要的一点是，Gemini API 免费，而且只需要一个 Google 账号就能申请，不需要绑卡，也不需要充值，对新手非常友好。&lt;/p&gt;

&lt;p&gt;其次，近期发布的 Gemini 2.5 系列模型能力很强——1M token 的上下文窗口（context window），64k token 的输出，内置思考（thinking）能力，还支持&lt;a href=&quot;https://ai.google.dev/gemini-api/docs/grounding&quot;&gt;网络搜索&lt;/a&gt;（grouding with Google search）。截止 2025 年 4 月 30 日，Gemini 2.5 Pro Preview 在 &lt;a href=&quot;https://livebench.ai/&quot;&gt;Livebench&lt;/a&gt; 上排名第四，Gemini 2.5 Flash Preview 排名第十。我个人把 Gemini 2.5 Flash Preview 设成 Open WebUI 的默认模型。这是我现在最常用的模型。&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;https://huangboming.com/assets/images/get-gemini-api-key/1.png&quot; alt=&quot;2025 年 4 月 30 日 Livebench 排行榜&quot; class=&quot;shadow&quot; w=&quot;700&quot; h=&quot;381&quot;&gt;
&lt;em&gt;2025 年 4 月 30 日 Livebench 排行榜&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;不过免费也有免费的代价。&lt;/p&gt;

&lt;p&gt;首先是&lt;a href=&quot;https://ai.google.dev/gemini-api/docs/rate-limits#free-tier&quot;&gt;速率限制&lt;/a&gt;（rate limit）。免费用户会受到每分钟请求数（RPM）、每分钟处理 Token 数（TPM）以及每日请求数（RPD）的限制，具体如下图所示：&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;https://huangboming.com/assets/images/get-gemini-api-key/2.png&quot; alt=&quot;免费用户的 Gemini 使用速率限制&quot; class=&quot;shadow&quot; w=&quot;700&quot; h=&quot;523&quot;&gt;
&lt;em&gt;免费用户的 Gemini 使用速率限制&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;对于个人用户来说，这些限制并不算太大的问题，因为一般也用不到这么多。如果你是重度用户，又不想花钱，也可以考虑创建多个 Google 账号并分别申请 API key 轮流使用。反正创建 Google 账号本身不需要花钱。&lt;/p&gt;

&lt;p&gt;第二，如果你使用免费版的 Gemini API key，Google 会收集你对话数据用于训练 Gemini 模型。这一点见仁见智，如果对此有所顾虑，可能需要考虑其他选项，比如付费 Gemini API key 或者其它模型提供商的 API。&lt;/p&gt;

&lt;h2 id=&quot;准备工作&quot;&gt;准备工作&lt;/h2&gt;

&lt;p&gt;在开始之前，你需要先准备：&lt;/p&gt;
&lt;ol&gt;
  &lt;li&gt;一个正在运行的 Open WebUI 服务（关于如何部署 Open WebUI，参见&lt;a href=&quot;https://huangboming.com/posts/deploy-openwebui/&quot;&gt;这一篇文章&lt;/a&gt;）&lt;/li&gt;
  &lt;li&gt;Open WebUI 服务所在的主机需要配置好代理服务，能够访问到 Gemini&lt;/li&gt;
  &lt;li&gt;一个 Google 账号。需要注意你的账号是否处于&lt;a href=&quot;https://ai.google.dev/gemini-api/docs/available-regions&quot;&gt;支持地区&lt;/a&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;h2 id=&quot;创建-api-key&quot;&gt;创建 API key&lt;/h2&gt;

&lt;p&gt;首先，用浏览器访问 &lt;a href=&quot;https://aistudio.google.com/&quot;&gt;Google AI Studio&lt;/a&gt;。进入页面之后，点击上方的“Get API key”。&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;https://huangboming.com/assets/images/get-gemini-api-key/3.png&quot; alt=&quot;Google AI Studio 主页&quot; class=&quot;shadow&quot; w=&quot;700&quot; h=&quot;456&quot;&gt;
&lt;em&gt;Google AI Studio 主页&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;进入 API keys 页面后，点击“Create API key”，API key 就创建好了。就这么简单，不需要什么复杂操作。&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;https://huangboming.com/assets/images/get-gemini-api-key/4.png&quot; alt=&quot;Google AI Studio 创建 API 页面&quot; class=&quot;shadow&quot; w=&quot;700&quot; h=&quot;456&quot;&gt;
&lt;em&gt;Google AI Studio 创建 API 页面&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;你可以复制 API key，保存到一个地方。当然不复制也行，之后可以在这个页面再次查看你的 API key。&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;https://huangboming.com/assets/images/get-gemini-api-key/5.png&quot; alt=&quot;在 Google AI Studio 创建 API 页面查看 API key&quot; class=&quot;shadow&quot; w=&quot;700&quot; h=&quot;456&quot;&gt;
&lt;em&gt;在 Google AI Studio 创建 API 页面查看 API key&lt;/em&gt;&lt;/p&gt;

&lt;blockquote class=&quot;prompt-danger&quot;&gt;
  &lt;p&gt;一定要保管好自己的 API key，不要泄露给任何人。一旦泄露，他人可能滥用你的 API 密钥，导致不必要的麻烦。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2 id=&quot;在-open-webui-中配置使用-gemini-api-key&quot;&gt;在 Open WebUI 中配置使用 Gemini API key&lt;/h2&gt;

&lt;p&gt;要在 Open WebUI 中配置使用 Gemini API key，一共有两种方法：&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;第一种是使用 OpenAI API connections&lt;/li&gt;
  &lt;li&gt;第二种是使用 Open WebUI 函数（Function）&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;如果你只是想快速开始使用 Gemini 模型，我推荐使用第一种方式配置。如果你需要使用 Gemini 原生支持的联网搜索功能，我推荐通过第二种方式配置。&lt;/p&gt;

&lt;h3 id=&quot;第一种方式使用-openai-api-connections&quot;&gt;第一种方式：使用 OpenAI API connections&lt;/h3&gt;

&lt;p&gt;由于开发者的设计考量&lt;sup id=&quot;fnref:1&quot;&gt;&lt;a href=&quot;https://huangboming.com/posts/get-gemini-api-key/#fn:1&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot; role=&quot;doc-noteref&quot;&gt;1&lt;/a&gt;&lt;/sup&gt;，Open WebUI 原生只支持 OpenAI 格式的 API 调用，不支持也不打算支持其它提供商的 API key 调用格式（比如 Gemini API key）。但好在 &lt;a href=&quot;https://ai.google.dev/gemini-api/docs/openai&quot;&gt;Gemini API key 原生兼容 OpenAI 格式的 API 调用方式&lt;/a&gt;，所以我们可以直接通过 OpenAI API Connection 的方式使用它。&lt;/p&gt;

&lt;p&gt;在 Open WebUI 的外部连接页面，可以配置 OpenAI API connection。具体配置方法可以参见&lt;a href=&quot;https://huangboming.com/posts/deploy-openwebui/#%E9%85%8D%E7%BD%AE-api-key&quot;&gt;这一篇文章的配置 API key 部分&lt;/a&gt;。&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;https://huangboming.com/assets/images/get-gemini-api-key/6.png&quot; alt=&quot;Open WebUI 外部连接配置页面&quot; class=&quot;shadow&quot; w=&quot;700&quot; h=&quot;473&quot;&gt;
&lt;em&gt;Open WebUI 外部连接配置页面&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;URL 填 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;https://generativelanguage.googleapis.com/v1beta/openai&lt;/code&gt;，Key 填你的 API key。Model IDs 部分可以不填，如果不填意味着 Open WebUI 会自动获取所有可用的模型；也可以自己到 &lt;a href=&quot;https://ai.google.dev/gemini-api/docs/models&quot;&gt;Gemini 模型页面&lt;/a&gt;上去找到自己想用的模型 ID。比如 Gemini 2.5 Flash Preview 04-17 的模型 ID 是 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;models/gemini-2.5-flash-preview-04-17&lt;/code&gt;。&lt;/p&gt;

&lt;p&gt;配置好之后，点击保存。回到主界面，刷新页面，你就可以看到所有可用的 Gemini 模型了。&lt;/p&gt;

&lt;h3 id=&quot;第二种方式使用-open-webui-函数&quot;&gt;第二种方式：使用 Open WebUI 函数&lt;/h3&gt;

&lt;p&gt;通过 OpenAI API connections 配置 Gemini API key 虽然比较简单，容易上手，但这种方式的一个核心缺点是无法调用 Gemini 原生支持的网络搜索功能。根据我的使用体验，Gemini 原生支持的网络搜索功能效果比 Open WebUI 自带的搜索功能（配置 Google PSE）更为出色。所以我更推荐使用 Open WebUI 函数（Function）的方式来配置 Gemini API key。&lt;/p&gt;

&lt;p&gt;根据 Open WebUI 官网的介绍，Open WebUI 函数可以理解为 Open WebUI 的内置插件，用以拓展其核心能力&lt;sup id=&quot;fnref:2&quot;&gt;&lt;a href=&quot;https://huangboming.com/posts/get-gemini-api-key/#fn:2&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot; role=&quot;doc-noteref&quot;&gt;2&lt;/a&gt;&lt;/sup&gt;。&lt;/p&gt;

&lt;p&gt;你不需要自己写函数，直接使用别人写好的就行。我使用的是 &lt;a href=&quot;https://openwebui.com/f/suurt8ll/gemini_manifold_google_genai&quot;&gt;Gemini Manifold Google_genai&lt;/a&gt; 函数，它原生支持文生图和网络搜索功能。&lt;/p&gt;

&lt;h4 id=&quot;0-检查环境&quot;&gt;0. 检查环境&lt;/h4&gt;

&lt;p&gt;在创建函数时，Open WebUI 会调用 Open WebUI 所在虚拟环境中的 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;pip&lt;/code&gt; 安装函数所需要的依赖。于是，在安装函数之前，你需要保证虚拟环境中有 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;pip&lt;/code&gt;。&lt;/p&gt;

&lt;p&gt;一般来说虚拟环境中都会有 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;pip&lt;/code&gt;，但是使用 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;uv&lt;/code&gt; 创建的虚拟环境中没有 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;pip&lt;/code&gt;&lt;sup id=&quot;fnref:3&quot;&gt;&lt;a href=&quot;https://huangboming.com/posts/get-gemini-api-key/#fn:3&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot; role=&quot;doc-noteref&quot;&gt;3&lt;/a&gt;&lt;/sup&gt;，你需要手动安装：&lt;/p&gt;

&lt;div class=&quot;language-shell highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;table class=&quot;rouge-table&quot;&gt;&lt;tbody&gt;&lt;tr&gt;
&lt;td class=&quot;rouge-gutter gl&quot;&gt;&lt;pre class=&quot;lineno&quot;&gt;1
2
&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&quot;rouge-code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;c&quot;&gt;# 在uv创建的虚拟环境下安装pip&lt;/span&gt;
uv pip &lt;span class=&quot;nb&quot;&gt;install &lt;/span&gt;pip
&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h4 id=&quot;1-在-open-webui-中安装函数&quot;&gt;1. 在 Open WebUI 中安装函数&lt;/h4&gt;

&lt;p&gt;首先来到管理员面板，选择上方的函数，来到函数页面。然后点击右边的加号，添加新函数。&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;https://huangboming.com/assets/images/get-gemini-api-key/7.png&quot; alt=&quot;Open WebUI 函数页面&quot; class=&quot;shadow&quot; w=&quot;700&quot; h=&quot;446&quot;&gt;
&lt;em&gt;Open WebUI 函数页面&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;在创建函数页面，函数名称填 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Gemini Manifold google genai&lt;/code&gt;，函数描述填 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Manifold function for Gemini Developer API. Supports native image generation, grounding with Google Search and streaming. Uses google-genai.&lt;/code&gt;。然后访问 Gemini Manifold Google_genai 函数的&lt;a href=&quot;https://raw.githubusercontent.com/suurt8ll/open_webui_functions/refs/heads/master/plugins/pipes/gemini_manifold.py&quot;&gt;源代码&lt;/a&gt;，复制所有代码，粘贴到 Open WebUI 页面的函数代码处。&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;https://huangboming.com/assets/images/get-gemini-api-key/8.png&quot; alt=&quot;配置 Gemini Manifold google genai 函数&quot; class=&quot;shadow&quot; w=&quot;700&quot; h=&quot;443&quot;&gt;
&lt;em&gt;配置 Gemini Manifold google genai 函数，需要填写函数名称、描述和代码&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;根据 Gemini Manifold Google_genai 项目的&lt;a href=&quot;https://github.com/suurt8ll/open_webui_functions/blob/master/docs/plugins/pipes/gemini_manifold.md&quot;&gt;文档&lt;/a&gt;，如果你想使用 Gemini API 自带的网页搜索功能，除了安装 Gemini Manifold Google_genai 函数之外，你还需要安装一个辅助函数 Gemini Manifold Companion。&lt;/p&gt;

&lt;p&gt;和刚刚一样，在函数页面创建一个新的函数。函数名填 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Gemini Manifold Companion&lt;/code&gt;，函数描述填 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;A companion filter for &quot;Gemini Manifold google_genai&quot; pipe providing enhanced functionality.&lt;/code&gt;。然后访问 Gemini Manifold Companion 的&lt;a href=&quot;https://github.com/suurt8ll/open_webui_functions/raw/refs/heads/master/plugins/filters/gemini_manifold_companion.py&quot;&gt;源代码&lt;/a&gt;，复制所有代码，粘贴到 Open WebUI 页面的函数代码处。&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;https://huangboming.com/assets/images/get-gemini-api-key/9.png&quot; alt=&quot;配置 Gemini Manifold Companion 辅助函数&quot; class=&quot;shadow&quot; w=&quot;700&quot; h=&quot;586&quot;&gt;
&lt;em&gt;配置 Gemini Manifold Companion 辅助函数&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;（2025-07-28 补充）
配置好之后，你还需要全局应用 Gemini Manifold Companion 辅助函数，让它在全局生效，而不需要在每一个 Gemini 模型页面下手动开启。配置按钮如下图：&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;https://huangboming.com/assets/images/get-gemini-api-key/12.png&quot; alt=&quot;全局应用 Gemini Manifold Companion 辅助函数&quot; class=&quot;shadow&quot; w=&quot;700&quot; h=&quot;228&quot;&gt;
&lt;em&gt;全局应用 Gemini Manifold Companion 辅助函数&lt;/em&gt;&lt;/p&gt;

&lt;h4 id=&quot;2-配置函数的值&quot;&gt;2. 配置函数的值&lt;/h4&gt;

&lt;p&gt;创建好一个主函数和一个辅助函数之后，我们还需要配置函数的值（Valves）&lt;sup id=&quot;fnref:4&quot;&gt;&lt;a href=&quot;https://huangboming.com/posts/get-gemini-api-key/#fn:4&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot; role=&quot;doc-noteref&quot;&gt;4&lt;/a&gt;&lt;/sup&gt;，把我们刚刚申请的 Gemini API key 放进去。&lt;/p&gt;

&lt;p&gt;配置方式也很简单，来到函数页面，点击 Gemini Manifold google genai 函数右边的齿轮，打开值配置页面。刚打开值配置页面时，所有的值都是“默认”值。点击“默认”就会切换到输入框，可以添加值内容。你只需要关注下面几个值：&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Gemini Api Key&lt;/code&gt;：填你的 Gemini API key&lt;/li&gt;
  &lt;li&gt;
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Model Blacklist&lt;/code&gt;：模型黑名单，用于过滤掉你不想看到的模型。我填的是 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;gemini-1.0*,gemini-1.5*&lt;/code&gt;，过滤掉 1.0 和 1.5 系列的模型。这两个系列的模型太老了，现在直接用 2.0、2.5 系统的模型就好。&lt;/li&gt;
  &lt;li&gt;
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Thinking Budget&lt;/code&gt;：用于控制 Gemini 2.5 Flash 的思考长度。这个值越大，模型就思考得越多，但相应的，响应时间也会变得更长。默认值是 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;8196&lt;/code&gt;，如果填 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;0&lt;/code&gt; 意味着不思考。最高可以填 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;24576&lt;/code&gt;
&lt;/li&gt;
  &lt;li&gt;
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Emit Status Updates&lt;/code&gt;：可以看到模型当前的状态（思考中或者是联网搜索中），建议开启&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;img src=&quot;https://huangboming.com/assets/images/get-gemini-api-key/10.png&quot; alt=&quot;Gemini Manifold google genai 值配置&quot; class=&quot;shadow&quot; w=&quot;700&quot; h=&quot;690&quot;&gt;
&lt;em&gt;Gemini Manifold google genai 值配置&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;配置好之后，点击保存就大功告成了。&lt;/p&gt;

&lt;h4 id=&quot;3-测试&quot;&gt;3. 测试&lt;/h4&gt;

&lt;p&gt;通过这种方式配置 Gemini API key，你可以直接使用 API 自带的联网搜索功能，而不需要额外在 Open WebUI 中配置搜索引擎。你可以返回主页面，试试与模型对话，以及搜索功能。&lt;/p&gt;

&lt;p&gt;（2025-07-28 补充）
要使用 Open WebUI 的网络搜索功能，你需要先打开网络搜索功能开关，具体的位置见下图：
&lt;img src=&quot;https://huangboming.com/assets/images/get-gemini-api-key/13.png&quot; alt=&quot;打开 Open WebUI 网络搜索功能&quot; class=&quot;shadow&quot; w=&quot;700&quot; h=&quot;317&quot;&gt;
&lt;em&gt;打开 Open WebUI 网络搜索功能&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;https://huangboming.com/assets/images/get-gemini-api-key/11.png&quot; alt=&quot;测试 Gemini 网络搜索功能&quot; class=&quot;shadow&quot; w=&quot;700&quot; h=&quot;447&quot;&gt;
&lt;em&gt;测试 Gemini 网络搜索功能&lt;/em&gt;&lt;/p&gt;

&lt;h2 id=&quot;总结&quot;&gt;总结&lt;/h2&gt;

&lt;p&gt;总的来说，获取 Gemini API key 非常简单，只需要一个 Google 账号即可。&lt;/p&gt;

&lt;p&gt;在 Open WebUI 中配置 Gemini API key 主要有两种方式：&lt;/p&gt;
&lt;ol&gt;
  &lt;li&gt;使用 OpenAI API connections：这种方式配置简单快捷，适合想快速上手体验 Gemini 模型的用户。但缺点是无法使用 Gemini 原生的网络搜索等高级功能。&lt;/li&gt;
  &lt;li&gt;使用 Open WebUI 函数：这种方式配置稍复杂，需要安装 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Gemini Manifold google_genai&lt;/code&gt; 主函数和 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Gemini Manifold Companion&lt;/code&gt; 辅助函数，并进行相应的参数配置。优点是可以充分利用 Gemini API 的原生功能，如网络搜索和文生图，获得更好的使用体验。&lt;/li&gt;
&lt;/ol&gt;

&lt;h2 id=&quot;相关文档&quot;&gt;相关文档&lt;/h2&gt;

&lt;ul&gt;
  &lt;li&gt;
&lt;a href=&quot;https://ai.google.dev/gemini-api/docs/models&quot;&gt;Gemini models&lt;/a&gt;：可以查看每个模型的详细信息，包括有哪些模型可以调用，每个模型的上下文窗口大小，输出 token 数量，支持哪些功能，知识截止日期（knowledge cutoff）等等&lt;/li&gt;
&lt;/ul&gt;

&lt;hr&gt;

&lt;h2 id=&quot;脚注&quot;&gt;脚注&lt;/h2&gt;

&lt;div class=&quot;footnotes&quot; role=&quot;doc-endnotes&quot;&gt;
  &lt;ol&gt;
    &lt;li id=&quot;fn:1&quot;&gt;
      &lt;p&gt;详情请见开发者在 PR 下的评论：&lt;a href=&quot;https://github.com/open-webui/open-webui/pull/9241#issuecomment-2629707340&quot;&gt;https://github.com/open-webui/open-webui/pull/9241#issuecomment-2629707340&lt;/a&gt; &lt;a href=&quot;https://huangboming.com/posts/get-gemini-api-key/#fnref:1&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;↩︎&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
    &lt;li id=&quot;fn:2&quot;&gt;
      &lt;p&gt;参见 &lt;a href=&quot;https://docs.openwebui.com/features/plugin/functions/&quot;&gt;https://docs.openwebui.com/features/plugin/functions/&lt;/a&gt; &lt;a href=&quot;https://huangboming.com/posts/get-gemini-api-key/#fnref:2&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;↩︎&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
    &lt;li id=&quot;fn:3&quot;&gt;
      &lt;p&gt;可能是因为 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;uv&lt;/code&gt; 本身就旨在替代 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;pip&lt;/code&gt; 的功能 &lt;a href=&quot;https://huangboming.com/posts/get-gemini-api-key/#fnref:3&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;↩︎&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
    &lt;li id=&quot;fn:4&quot;&gt;
      &lt;p&gt;在 Open WebUI 中，函数的值（Valves）是函数的输入参数。Valves 直译是“阀门”，但不知道为什么官方把它翻译成“值”（Values）。 &lt;a href=&quot;https://huangboming.com/posts/get-gemini-api-key/#fnref:4&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;↩︎&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
  &lt;/ol&gt;
&lt;/div&gt;
</content>
  </entry>
  
    
    
    
    
  <entry>
    <title>在 PVE 上使用 CT 部署 Open WebUI 服务</title>
    <id>https://huangboming.com/posts/deploy-openwebui/</id>
    <link rel="alternate" type="text/html" href="https://huangboming.com/posts/deploy-openwebui/" />
    <published>2025-04-29T00:00:00+08:00</published>
    <updated>2026-07-16T00:13:32+08:00</updated>
    <author>
      <name>Boming Huang</name>
      <uri>https://huangboming.com/about/</uri>
    </author>
    <category term="教程" />
    <summary type="text">在 Proxmox VE 的 CT 容器中部署 Open WebUI，并配置为 systemd 服务实现开机自启与故障自动重启。</summary>
    <content type="html" xml:base="https://huangboming.com/posts/deploy-openwebui/">&lt;h2 id=&quot;什么是-open-webui&quot;&gt;什么是 Open WebUI&lt;/h2&gt;

&lt;p&gt;Open WebUI 是一个开源、自托管的 Web 界面，主要用于与各类大型语言模型（LLM）交互。简单来说，它提供一个类似 ChatGPT、Deepseek 那样的对话页面，你可以在上面与模型对话。与 ChatGPT 对话页面不同的是，Open WebUI 支持与不同的大模型对话。&lt;/p&gt;

&lt;p&gt;一般来说，我们使用某个模型，要去对应提供商的网页去与模型对话。比如说，使用 ChatGPT 需要访问 &lt;a href=&quot;https://chatgpt.com&quot;&gt;chatgpt.com&lt;/a&gt;；使用 Claude，需要访问 &lt;a href=&quot;https://claude.ai&quot;&gt;claude.ai&lt;/a&gt;；使用 Deepseek，则要去 &lt;a href=&quot;https://chat.deepseek.com&quot;&gt;chat.deepseek.com&lt;/a&gt;。这种方式不仅需要在不同平台间切换，而且聊天记录分散在各个提供商处，不太方便整理和检索。&lt;/p&gt;

&lt;p&gt;Open WebUI 的优势在于，只要有对应模型的 API，我们就可以直接在 Open WebUI 上与多个模型对话——不仅仅可以选择某次回答使用哪个模型，我们还可以让多个模型同时回答。而且聊天数据也保存在一个地方，可以随时导入导出。&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;https://huangboming.com/assets/images/deploy-openwebui/1.png&quot; alt=&quot;Open WebUI 界面展示&quot; class=&quot;shadow&quot; w=&quot;700&quot; h=&quot;434&quot;&gt;
&lt;em&gt;Open WebUI 主界面&lt;/em&gt;&lt;/p&gt;

&lt;h2 id=&quot;部署&quot;&gt;部署&lt;/h2&gt;

&lt;p&gt;Open WebUI 的&lt;a href=&quot;https://docs.openwebui.com/getting-started/quick-start/&quot;&gt;官方文档&lt;/a&gt;上提供几种部署方式：Python、Docker、k8s。&lt;/p&gt;

&lt;p&gt;我个人比较倾向本机上使用 Python 安装和部署，而不太喜欢 Docker。第一是使用 Docker 的方式部署，调试不是很方便。其次，使用 Docker 部署网络配置容易出各种问题，持久存储也需要额外配置。&lt;/p&gt;

&lt;p&gt;我现在的部署方案是在 PVE 中启动一个单独的 CT（Container）部署 Open WebUI，并通过 Cloudflare Tunnel 将服务暴露在公网上，再加上 Cloudflare Zero Trust 进行身份验证。这里先谈谈如何在 CT 上部署 Open WebUI，Cloudflare 相关的在后续的 blog 中再讲。如果你用的不是 PVE 系统可以跳过 PVE 相关部分，直接看后面部署的部分。&lt;/p&gt;

&lt;h3 id=&quot;创建-ct&quot;&gt;创建 CT&lt;/h3&gt;

&lt;p&gt;要创建一个 CT，我们需要先下载一个 CT 模板（CT template）。在 PVE 页面上，点进 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;CT Template&lt;/code&gt; 管理页面，具体的路径是：&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Datacenter -&amp;gt; &amp;lt;你的节点名&amp;gt; -&amp;gt; local -&amp;gt; CT Templates&lt;/code&gt;，然后点击 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Templates&lt;/code&gt;。在 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Templates&lt;/code&gt; 页面中可以找到官方预设的 CT 模版。选择一个自己喜欢的模板（我自己选择的是 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ubuntu-22.04-standard&lt;/code&gt;），点击右下角的 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Download&lt;/code&gt; 模板就会开始下载。&lt;/p&gt;

&lt;p&gt;下载好 CT 模板之后，在 PVE 主页上点击右上角的 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Create CT&lt;/code&gt; 来创建一个 CT。创建之前需要填一些 CT 相关的参数，我这里记录一些比较重要的参数：&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;General 页面：
    &lt;ul&gt;
      &lt;li&gt;Password: 访问 CT shell 所需要的密码&lt;/li&gt;
      &lt;li&gt;SSH public key（非必需）：如果你想使用 ssh，可以把 SSH 公钥填上去&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;Template 页面：
    &lt;ul&gt;
      &lt;li&gt;Template：选择你刚刚下载的 CT template&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;Disk 页面：
    &lt;ul&gt;
      &lt;li&gt;Disk size（存储）：10GB 以上，最好 20-30GB&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;CPU 页面：
    &lt;ul&gt;
      &lt;li&gt;Cores（CPU 核心数）：一般 1-2 核就足够&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;Memory 页面：
    &lt;ul&gt;
      &lt;li&gt;Memory（内存）&amp;amp; Swap：建议 2-4GB&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;Network 页面 &amp;amp; DNS 页面：自行配置。如果想使用国外的大模型，需要配置好代理&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;最后在 Comfirm 页面确认一遍就可以部署了。&lt;/p&gt;

&lt;h3 id=&quot;下载和运行-open-webui&quot;&gt;下载和运行 Open WebUI&lt;/h3&gt;

&lt;p&gt;创建 CT 之后，需要先手动启动 CT。启动好之后，来到 CT 页面，通过 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Console&lt;/code&gt; 登陆 CT 的 shell。这里需要注意用户名填 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;root&lt;/code&gt;，密码填刚刚你设置的密码。&lt;/p&gt;

&lt;p&gt;进到 shell，第一件事是更新依赖项：&lt;/p&gt;
&lt;div class=&quot;language-shell highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;table class=&quot;rouge-table&quot;&gt;&lt;tbody&gt;&lt;tr&gt;
&lt;td class=&quot;rouge-gutter gl&quot;&gt;&lt;pre class=&quot;lineno&quot;&gt;1
&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&quot;rouge-code&quot;&gt;&lt;pre&gt;apt update &lt;span class=&quot;o&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; apt upgrade &lt;span class=&quot;nt&quot;&gt;-y&lt;/span&gt;
&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;然后安装必要的依赖：&lt;/p&gt;
&lt;div class=&quot;language-shell highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;table class=&quot;rouge-table&quot;&gt;&lt;tbody&gt;&lt;tr&gt;
&lt;td class=&quot;rouge-gutter gl&quot;&gt;&lt;pre class=&quot;lineno&quot;&gt;1
&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&quot;rouge-code&quot;&gt;&lt;pre&gt;apt &lt;span class=&quot;nb&quot;&gt;install&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-y&lt;/span&gt; curl ffmpeg
&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;接下来，我们将使用 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;uv&lt;/code&gt; 来安装 Python 和 Open WebUI。通过 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;uv&lt;/code&gt; 安装 Python 3.11，然后创建虚拟环境，下载 Open WebUI:&lt;/p&gt;
&lt;div class=&quot;language-shell highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;table class=&quot;rouge-table&quot;&gt;&lt;tbody&gt;&lt;tr&gt;
&lt;td class=&quot;rouge-gutter gl&quot;&gt;&lt;pre class=&quot;lineno&quot;&gt;1
2
3
4
5
6
7
8
9
10
&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&quot;rouge-code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;c&quot;&gt;# 安装uv&lt;/span&gt;
curl &lt;span class=&quot;nt&quot;&gt;-LsSf&lt;/span&gt; https://astral.sh/uv/install.sh | sh

&lt;span class=&quot;c&quot;&gt;# 安装Python 3.11&lt;/span&gt;
uv python &lt;span class=&quot;nb&quot;&gt;install &lt;/span&gt;3.11
&lt;span class=&quot;c&quot;&gt;# 创建虚拟环境&lt;/span&gt;
uv venv .venv &lt;span class=&quot;nt&quot;&gt;--python&lt;/span&gt; 3.11
&lt;span class=&quot;nb&quot;&gt;source&lt;/span&gt; .venv/bin/activate
&lt;span class=&quot;c&quot;&gt;# 安装open webui&lt;/span&gt;
uv pip &lt;span class=&quot;nb&quot;&gt;install &lt;/span&gt;open-webui
&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;如果你不想装 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;uv&lt;/code&gt;，也可以通过 Python 创建虚拟环境，在虚拟环境上安装 Open WebUI，效果是一样的。&lt;/p&gt;
&lt;div class=&quot;language-shell highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;table class=&quot;rouge-table&quot;&gt;&lt;tbody&gt;&lt;tr&gt;
&lt;td class=&quot;rouge-gutter gl&quot;&gt;&lt;pre class=&quot;lineno&quot;&gt;1
2
3
&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&quot;rouge-code&quot;&gt;&lt;pre&gt;python3 &lt;span class=&quot;nt&quot;&gt;-m&lt;/span&gt; venv venv
&lt;span class=&quot;nb&quot;&gt;source &lt;/span&gt;venv/bin/activate
pip &lt;span class=&quot;nb&quot;&gt;install &lt;/span&gt;open-webui
&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;最后，通过设置 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;DATA_DIR&lt;/code&gt; 环境变量指定数据存储目录（用于存放数据库），然后启动 Open WebUI 服务：运行 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;DATA_DIR=~/.open-webui open-webui serve&lt;/code&gt;。服务启动之后，我们可以在浏览器上通过 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;http://&amp;lt;主机或者CT的IP地址&amp;gt;:8080&lt;/code&gt; 访问它。&lt;/p&gt;

&lt;h3 id=&quot;可选将-open-webui-部署成一个-system-service&quot;&gt;（可选）将 Open WebUI 部署成一个 System Service&lt;/h3&gt;

&lt;p&gt;为了让 Open WebUI 能够在系统启动时自动运行，并在意外退出时自动重启，我们可以将其配置为一个 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;systemd&lt;/code&gt; 服务。&lt;/p&gt;

&lt;p&gt;以下是在基于 Ubuntu/Debian 的系统上配置 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;systemd&lt;/code&gt; 服务的步骤。对于其他 Linux 发行版，命令可能略有不同。&lt;/p&gt;

&lt;p&gt;在 Ubuntu 上将服务部署成一个系统服务，我们需要在 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/etc/systemd/system&lt;/code&gt; 目录下创建一个 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.service&lt;/code&gt; 文件，告诉 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;systemd&lt;/code&gt; 如何启动、停止和管理这个服务。&lt;/p&gt;

&lt;p&gt;运行下面的命令，在 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/etc/systemd/system&lt;/code&gt; 中创建一个 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;open-webui.service&lt;/code&gt; 文件，并在文件中声明运行所需要的命令、环境变量、重启策略。&lt;/p&gt;
&lt;div class=&quot;language-shell highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;table class=&quot;rouge-table&quot;&gt;&lt;tbody&gt;&lt;tr&gt;
&lt;td class=&quot;rouge-gutter gl&quot;&gt;&lt;pre class=&quot;lineno&quot;&gt;1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&quot;rouge-code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;nb&quot;&gt;cat&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;EOF&lt;/span&gt;&lt;span class=&quot;sh&quot;&gt; &amp;gt; /etc/systemd/system/open-webui.service
[Unit]
Description=Open WebUI Service
After=network.target

[Service]
Type=simple
User=root
WorkingDirectory=/root
Environment=&quot;DATA_DIR=/root/.open-webui&quot;
ExecStart=/bin/bash -l -c &quot;source /root/.venv/bin/activate &amp;amp;&amp;amp; open-webui serve&quot;
Restart=on-failure
RestartSec=5

[Install]
WantedBy=multi-user.target
&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;EOF
&lt;/span&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;重载 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;systemd&lt;/code&gt; 的配置、启动 Open WebUI 服务并且配置开机启动：&lt;/p&gt;
&lt;div class=&quot;language-shell highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;table class=&quot;rouge-table&quot;&gt;&lt;tbody&gt;&lt;tr&gt;
&lt;td class=&quot;rouge-gutter gl&quot;&gt;&lt;pre class=&quot;lineno&quot;&gt;1
2
3
4
5
6
&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&quot;rouge-code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;c&quot;&gt;# 重新载配置&lt;/span&gt;
systemctl daemon-reload
&lt;span class=&quot;c&quot;&gt;# 启动服务&lt;/span&gt;
systemctl start open-webui.service
&lt;span class=&quot;c&quot;&gt;# 设置开机启动&lt;/span&gt;
systemctl &lt;span class=&quot;nb&quot;&gt;enable &lt;/span&gt;open-webui.service
&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;启动之后可以查看 Open WebUI 服务的状态：&lt;/p&gt;
&lt;div class=&quot;language-shell highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;table class=&quot;rouge-table&quot;&gt;&lt;tbody&gt;&lt;tr&gt;
&lt;td class=&quot;rouge-gutter gl&quot;&gt;&lt;pre class=&quot;lineno&quot;&gt;1
&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&quot;rouge-code&quot;&gt;&lt;pre&gt;systemctl status open-webui.service
&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;正常情况下，你应该会看到服务状态显示为 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;active (running)&lt;/code&gt;。这说明 Open WebUI 服务已经正常运行。&lt;/p&gt;

&lt;h2 id=&quot;初步配置&quot;&gt;初步配置&lt;/h2&gt;

&lt;p&gt;部署好 Open WebUI 之后，使用浏览器访问 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;http://&amp;lt;主机或者CT的IP地址&amp;gt;:8080&lt;/code&gt;，来到 Open WebUI 的主页。首次访问时，系统会要求你创建一个管理员账户。输入用户名、邮箱（格式正确即可，无需真实验证）和密码。&lt;/p&gt;

&lt;p&gt;设置好管理员账号，登录，就来到 Open WebUI 的主页面。&lt;/p&gt;

&lt;h3 id=&quot;中文页面&quot;&gt;中文页面&lt;/h3&gt;

&lt;p&gt;如果不习惯英文，可以先点右上角的头像，选择“Settings”，点进去。然后在“General”页面把 Language 改成“简体中文”。&lt;/p&gt;

&lt;h3 id=&quot;配置-api-key&quot;&gt;配置 API key&lt;/h3&gt;

&lt;p&gt;假设你已经有 API Key，你可以来到“管理员面板/Admin panel”（右上角头像 -&amp;gt; 管理员面板/Admin panel），然后点击“设置/Settings”，找到“外部连接/Connection”。&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;https://huangboming.com/assets/images/deploy-openwebui/2.png&quot; alt=&quot;外部连接页面&quot; class=&quot;shadow&quot; w=&quot;700&quot; h=&quot;423&quot;&gt;
&lt;em&gt;进入 Open WebUI 外部连接页面&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;然后在“管理 OpenAI API/Manage OpenAI API Connections”连接部分，点击右边的加号，输入相应的 API base URL 以及 API Key，再点击“保存/save”。配置好之后返回主页面，就能看到相应的模型了。&lt;/p&gt;

&lt;h2 id=&quot;运维&quot;&gt;运维&lt;/h2&gt;

&lt;p&gt;部署好服务之后，后续还需要运维。这里记录一下常见的运维命令：&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;查看服务状态：&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;systemctl status open-webui.service&lt;/code&gt;
&lt;/li&gt;
  &lt;li&gt;重启服务：&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;systemctl restart open-webui.service&lt;/code&gt;
&lt;/li&gt;
  &lt;li&gt;停止服务：&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;systemctl stop open-webui.service&lt;/code&gt;
&lt;/li&gt;
  &lt;li&gt;查看 Open WebUI 的日志：&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;journalctl -u open-webui.service -f&lt;/code&gt;
&lt;/li&gt;
  &lt;li&gt;升级 Open WebUI 到最新版本并重启服务：&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;uv pip install open-webui --upgrade &amp;amp;&amp;amp; systemctl restart open-webui.service&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;
</content>
  </entry>
  
</feed>
