<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/"><channel><title>Knowledge-Cards on Tarragon</title><link>https://tarrragon.github.io/blog/tags/knowledge-cards/</link><description>Recent content in Knowledge-Cards on Tarragon</description><generator>Hugo -- gohugo.io</generator><language>zh-TW</language><copyright>Tarragon (CC BY 4.0)</copyright><lastBuildDate>Wed, 01 Jul 2026 00:00:00 +0000</lastBuildDate><atom:link href="https://tarrragon.github.io/blog/tags/knowledge-cards/index.xml" rel="self" type="application/rss+xml"/><item><title>商業概念知識卡片</title><link>https://tarrragon.github.io/blog/business/knowledge-cards/</link><pubDate>Tue, 19 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/business/knowledge-cards/</guid><description>&lt;p>商業知識卡片的核心目標是把商業分析文章中的高密度術語拆成可獨立閱讀的概念。VC、創辦人、策略分析師寫的文章常一句話塞進三到五個縮寫；工程背景的讀者若沒有共同術語表，就會卡在名詞而錯過真正的判斷邏輯。&lt;/p>
&lt;p>每張卡片只處理一個術語的核心概念、概念位置、可觀察訊號與判讀方式。卡片之間用相對連結互引，建立可導航的概念網路。&lt;/p>
&lt;h2 id="建卡判準">建卡判準&lt;/h2>
&lt;p>商業術語建卡的判準是該術語是否承擔判斷成本，而不是只看是否常見。讀者如果不知道這個名詞，會誤判某段分析的結論或無法解碼一張財務表，就值得建卡。&lt;/p>
&lt;p>適合建卡的術語通常有三個特徵。第一，它包含結構性意涵，超出字面翻譯—例如 lock-in 背後是切換成本與生態系設計，遠不只「鎖定」二字。第二，它會影響讀者對商業策略的判讀—例如 FDE 不只是「派工程師」，而是揭露 SaaS 模式不可行的訊號。第三，它可以被獨立說明成「核心概念、位置、訊號、判讀」的四段結構。&lt;/p>
&lt;p>不適合建卡的是過度寬泛的詞（「策略」「成長」「轉型」）或僅在特定文章中成立的臨時詞。這類詞應在分析文章中直接補清楚。&lt;/p>
&lt;h2 id="卡片格式">卡片格式&lt;/h2>
&lt;p>每張卡片用四段結構：&lt;/p>





&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-markdown" data-lang="markdown">&lt;span class="line">&lt;span class="ln"> 1&lt;/span>&lt;span class="cl">---
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 2&lt;/span>&lt;span class="cl">title: 術語中英文名
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 3&lt;/span>&lt;span class="cl">date: YYYY-MM-DD
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 4&lt;/span>&lt;span class="cl">description: 一行說明卡片責任
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 5&lt;/span>&lt;span class="cl">weight: 編號
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 6&lt;/span>&lt;span class="cl">---
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 7&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 8&lt;/span>&lt;span class="cl">開頭段：定義核心概念，回答「這個術語是什麼」。首段須包含至少一條鄰卡連結建立網路。
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 9&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">10&lt;/span>&lt;span class="cl">&lt;span class="gu">## 概念位置
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">11&lt;/span>&lt;span class="cl">&lt;span class="gu">&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">12&lt;/span>&lt;span class="cl">說明這個概念在商業推理中的位置，跟其他概念的關係。應包含至少一條鄰卡連結。
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">13&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">14&lt;/span>&lt;span class="cl">&lt;span class="gu">## 可觀察訊號與例子
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">15&lt;/span>&lt;span class="cl">&lt;span class="gu">&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">16&lt;/span>&lt;span class="cl">說明什麼時候這個概念變成判讀的重點，舉一到兩個具體情境。
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">17&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">18&lt;/span>&lt;span class="cl">&lt;span class="gu">## 判讀方式
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">19&lt;/span>&lt;span class="cl">&lt;span class="gu">&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">20&lt;/span>&lt;span class="cl">說明遇到這個概念時要做什麼判斷，常見陷阱是什麼。&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>開頭段必須先給定義，不要先丟例子。可觀察訊號段必須是具體情境，不可只給名詞解釋。判讀方式段必須給可操作的判斷指引。&lt;/p>
&lt;h2 id="商業模式">商業模式&lt;/h2>
&lt;p>公司賣什麼、賣給誰、怎麼收費。這是讀懂任何分析文章的第一層語言。&lt;/p>
&lt;table>
 &lt;thead>
 &lt;tr>
 &lt;th>卡片&lt;/th>
 &lt;th>核心問題&lt;/th>
 &lt;th>常見出現位置&lt;/th>
 &lt;/tr>
 &lt;/thead>
 &lt;tbody>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/business/knowledge-cards/saas/" data-link-title="SaaS" data-link-desc="說明雲端訂閱軟體的商業模式與經濟特徵">SaaS&lt;/a>&lt;/td>
 &lt;td>雲端訂閱軟體的商業模式&lt;/td>
 &lt;td>gross margin、PLG、retention&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/business/knowledge-cards/vertical-saas/" data-link-title="Vertical SaaS" data-link-desc="說明專做單一行業的 SaaS 與其競爭策略">Vertical SaaS&lt;/a>&lt;/td>
 &lt;td>專做單一行業的 SaaS&lt;/td>
 &lt;td>niche、tacit knowledge&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/business/knowledge-cards/horizontal-saas/" data-link-title="Horizontal SaaS" data-link-desc="說明跨行業通用的 SaaS 模式">Horizontal SaaS&lt;/a>&lt;/td>
 &lt;td>跨行業通用的 SaaS&lt;/td>
 &lt;td>distribution、PLG&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/business/knowledge-cards/cdp/" data-link-title="CDP" data-link-desc="說明客戶資料平台的角色與商業定位">CDP&lt;/a>&lt;/td>
 &lt;td>客戶資料平台&lt;/td>
 &lt;td>數據整合、應用層 SaaS&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/business/knowledge-cards/enterprise-license/" data-link-title="Enterprise License" data-link-desc="說明企業級授權的商業模式與鎖定效應">Enterprise License&lt;/a>&lt;/td>
 &lt;td>企業級授權模式&lt;/td>
 &lt;td>lock-in、長期合約&lt;/td>
 &lt;/tr>
 &lt;/tbody>
&lt;/table>
&lt;h2 id="單位經濟">單位經濟&lt;/h2>
&lt;p>每個客戶或每筆交易的成本與利潤結構。判讀一家公司是否真的賺錢的核心語言。&lt;/p>
&lt;table>
 &lt;thead>
 &lt;tr>
 &lt;th>卡片&lt;/th>
 &lt;th>核心問題&lt;/th>
 &lt;th>常見出現位置&lt;/th>
 &lt;/tr>
 &lt;/thead>
 &lt;tbody>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/business/knowledge-cards/cogs/" data-link-title="COGS" data-link-desc="說明銷售成本與其對毛利的影響">COGS&lt;/a>&lt;/td>
 &lt;td>賣出產品的直接成本&lt;/td>
 &lt;td>gross margin、毛利壓縮&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/business/knowledge-cards/gross-margin/" data-link-title="Gross Margin" data-link-desc="說明毛利率與其對商業模式可行性的決定作用">Gross Margin&lt;/a>&lt;/td>
 &lt;td>毛利率&lt;/td>
 &lt;td>SaaS、AI 公司毛利、估值&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/business/knowledge-cards/marginal-cost/" data-link-title="Marginal Cost" data-link-desc="說明邊際成本及其對商業模式擴張性的決定作用">Marginal Cost&lt;/a>&lt;/td>
 &lt;td>多服務一個客戶的邊際成本&lt;/td>
 &lt;td>PLG、零邊際複製&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/business/knowledge-cards/pnl/" data-link-title="P&amp;amp;L" data-link-desc="說明損益表的結構與商業判讀作用">P&amp;amp;L&lt;/a>&lt;/td>
 &lt;td>損益表&lt;/td>
 &lt;td>burn rate、估值&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/business/knowledge-cards/burn-rate/" data-link-title="Burn Rate" data-link-desc="說明燒錢速度及其對新創存活的決定作用">Burn Rate&lt;/a>&lt;/td>
 &lt;td>燒錢速度&lt;/td>
 &lt;td>runway、新創存活&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/business/knowledge-cards/runway/" data-link-title="Runway" data-link-desc="說明新創的現金跑道與融資時點">Runway&lt;/a>&lt;/td>
 &lt;td>現金能撐多久&lt;/td>
 &lt;td>burn rate、融資時點&lt;/td>
 &lt;/tr>
 &lt;/tbody>
&lt;/table>
&lt;h2 id="進入市場">進入市場&lt;/h2>
&lt;p>用什麼通路、銷售模式、組織安排把產品賣出去。&lt;/p>
&lt;table>
 &lt;thead>
 &lt;tr>
 &lt;th>卡片&lt;/th>
 &lt;th>核心問題&lt;/th>
 &lt;th>常見出現位置&lt;/th>
 &lt;/tr>
 &lt;/thead>
 &lt;tbody>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/business/knowledge-cards/gtm/" data-link-title="GTM" data-link-desc="說明進入市場策略的完整含義">GTM&lt;/a>&lt;/td>
 &lt;td>進入市場策略&lt;/td>
 &lt;td>PLG、FDE、銷售模式&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/business/knowledge-cards/plg/" data-link-title="PLG" data-link-desc="說明產品自助成長模式與其經濟前提">PLG&lt;/a>&lt;/td>
 &lt;td>產品自助成長&lt;/td>
 &lt;td>低 CAC、SaaS 經典模式&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/business/knowledge-cards/fde/" data-link-title="FDE" data-link-desc="說明前線部署工程師模式的成立條件">FDE&lt;/a>&lt;/td>
 &lt;td>前線部署工程師&lt;/td>
 &lt;td>tacit knowledge、企業客戶&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/business/knowledge-cards/jv/" data-link-title="JV" data-link-desc="說明合資企業的戰略用途">JV&lt;/a>&lt;/td>
 &lt;td>合資企業&lt;/td>
 &lt;td>進入企業市場、Palantir 模式&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/business/knowledge-cards/cac/" data-link-title="CAC" data-link-desc="說明獲客成本及其對商業模式可行性的決定作用">CAC&lt;/a>&lt;/td>
 &lt;td>獲客成本&lt;/td>
 &lt;td>unit economics、PLG&lt;/td>
 &lt;/tr>
 &lt;/tbody>
&lt;/table>
&lt;h2 id="競爭護城河">競爭護城河&lt;/h2>
&lt;p>為什麼客戶留下來、為什麼別人打不進來。決定一家公司能否長期擊敗對手。&lt;/p>
&lt;table>
 &lt;thead>
 &lt;tr>
 &lt;th>卡片&lt;/th>
 &lt;th>核心問題&lt;/th>
 &lt;th>常見出現位置&lt;/th>
 &lt;/tr>
 &lt;/thead>
 &lt;tbody>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/business/knowledge-cards/lock-in/" data-link-title="Lock-in" data-link-desc="說明鎖定效應如何形成護城河">Lock-in&lt;/a>&lt;/td>
 &lt;td>客戶離不開的結構&lt;/td>
 &lt;td>enterprise license、生態系&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/business/knowledge-cards/switching-cost/" data-link-title="Switching Cost" data-link-desc="說明切換成本如何鞏固客戶留存">Switching Cost&lt;/a>&lt;/td>
 &lt;td>切換到競爭對手的成本&lt;/td>
 &lt;td>lock-in、retention&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/business/knowledge-cards/retention/" data-link-title="Retention" data-link-desc="說明客戶留存率與其對單位經濟的決定作用">Retention&lt;/a>&lt;/td>
 &lt;td>客戶留存率&lt;/td>
 &lt;td>unit economics、SaaS&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/business/knowledge-cards/thin-wrapper/" data-link-title="Thin Wrapper" data-link-desc="說明薄包裝產品的脆弱性">Thin Wrapper&lt;/a>&lt;/td>
 &lt;td>只在底層服務外包一層薄殼&lt;/td>
 &lt;td>AI 新創、被輾平&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/business/knowledge-cards/fat-data-fat-skill/" data-link-title="Fat Data / Fat Skill" data-link-desc="說明獨家資料與行業隱性能力作為 AI 時代的護城河">Fat Data / Fat Skill&lt;/a>&lt;/td>
 &lt;td>有獨家資料或行業隱性能力&lt;/td>
 &lt;td>護城河、生存空間&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/business/knowledge-cards/connector/" data-link-title="Connector" data-link-desc="說明被收編進生態系變成整合工具的命運">Connector&lt;/a>&lt;/td>
 &lt;td>被收編進生態系變成整合工具&lt;/td>
 &lt;td>整併週期、AI Labs&lt;/td>
 &lt;/tr>
 &lt;/tbody>
&lt;/table>
&lt;h2 id="市場動態">市場動態&lt;/h2>
&lt;p>賽道處在什麼階段、競爭強度、需求類型。判讀一個產業現在能不能進、何時進。&lt;/p></description><content:encoded><![CDATA[<p>商業知識卡片的核心目標是把商業分析文章中的高密度術語拆成可獨立閱讀的概念。VC、創辦人、策略分析師寫的文章常一句話塞進三到五個縮寫；工程背景的讀者若沒有共同術語表，就會卡在名詞而錯過真正的判斷邏輯。</p>
<p>每張卡片只處理一個術語的核心概念、概念位置、可觀察訊號與判讀方式。卡片之間用相對連結互引，建立可導航的概念網路。</p>
<h2 id="建卡判準">建卡判準</h2>
<p>商業術語建卡的判準是該術語是否承擔判斷成本，而不是只看是否常見。讀者如果不知道這個名詞，會誤判某段分析的結論或無法解碼一張財務表，就值得建卡。</p>
<p>適合建卡的術語通常有三個特徵。第一，它包含結構性意涵，超出字面翻譯—例如 lock-in 背後是切換成本與生態系設計，遠不只「鎖定」二字。第二，它會影響讀者對商業策略的判讀—例如 FDE 不只是「派工程師」，而是揭露 SaaS 模式不可行的訊號。第三，它可以被獨立說明成「核心概念、位置、訊號、判讀」的四段結構。</p>
<p>不適合建卡的是過度寬泛的詞（「策略」「成長」「轉型」）或僅在特定文章中成立的臨時詞。這類詞應在分析文章中直接補清楚。</p>
<h2 id="卡片格式">卡片格式</h2>
<p>每張卡片用四段結構：</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-markdown" data-lang="markdown"><span class="line"><span class="ln"> 1</span><span class="cl">---
</span></span><span class="line"><span class="ln"> 2</span><span class="cl">title: 術語中英文名
</span></span><span class="line"><span class="ln"> 3</span><span class="cl">date: YYYY-MM-DD
</span></span><span class="line"><span class="ln"> 4</span><span class="cl">description: 一行說明卡片責任
</span></span><span class="line"><span class="ln"> 5</span><span class="cl">weight: 編號
</span></span><span class="line"><span class="ln"> 6</span><span class="cl">---
</span></span><span class="line"><span class="ln"> 7</span><span class="cl">
</span></span><span class="line"><span class="ln"> 8</span><span class="cl">開頭段：定義核心概念，回答「這個術語是什麼」。首段須包含至少一條鄰卡連結建立網路。
</span></span><span class="line"><span class="ln"> 9</span><span class="cl">
</span></span><span class="line"><span class="ln">10</span><span class="cl"><span class="gu">## 概念位置
</span></span></span><span class="line"><span class="ln">11</span><span class="cl"><span class="gu"></span>
</span></span><span class="line"><span class="ln">12</span><span class="cl">說明這個概念在商業推理中的位置，跟其他概念的關係。應包含至少一條鄰卡連結。
</span></span><span class="line"><span class="ln">13</span><span class="cl">
</span></span><span class="line"><span class="ln">14</span><span class="cl"><span class="gu">## 可觀察訊號與例子
</span></span></span><span class="line"><span class="ln">15</span><span class="cl"><span class="gu"></span>
</span></span><span class="line"><span class="ln">16</span><span class="cl">說明什麼時候這個概念變成判讀的重點，舉一到兩個具體情境。
</span></span><span class="line"><span class="ln">17</span><span class="cl">
</span></span><span class="line"><span class="ln">18</span><span class="cl"><span class="gu">## 判讀方式
</span></span></span><span class="line"><span class="ln">19</span><span class="cl"><span class="gu"></span>
</span></span><span class="line"><span class="ln">20</span><span class="cl">說明遇到這個概念時要做什麼判斷，常見陷阱是什麼。</span></span></code></pre></div><p>開頭段必須先給定義，不要先丟例子。可觀察訊號段必須是具體情境，不可只給名詞解釋。判讀方式段必須給可操作的判斷指引。</p>
<h2 id="商業模式">商業模式</h2>
<p>公司賣什麼、賣給誰、怎麼收費。這是讀懂任何分析文章的第一層語言。</p>
<table>
  <thead>
      <tr>
          <th>卡片</th>
          <th>核心問題</th>
          <th>常見出現位置</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td><a href="/blog/business/knowledge-cards/saas/" data-link-title="SaaS" data-link-desc="說明雲端訂閱軟體的商業模式與經濟特徵">SaaS</a></td>
          <td>雲端訂閱軟體的商業模式</td>
          <td>gross margin、PLG、retention</td>
      </tr>
      <tr>
          <td><a href="/blog/business/knowledge-cards/vertical-saas/" data-link-title="Vertical SaaS" data-link-desc="說明專做單一行業的 SaaS 與其競爭策略">Vertical SaaS</a></td>
          <td>專做單一行業的 SaaS</td>
          <td>niche、tacit knowledge</td>
      </tr>
      <tr>
          <td><a href="/blog/business/knowledge-cards/horizontal-saas/" data-link-title="Horizontal SaaS" data-link-desc="說明跨行業通用的 SaaS 模式">Horizontal SaaS</a></td>
          <td>跨行業通用的 SaaS</td>
          <td>distribution、PLG</td>
      </tr>
      <tr>
          <td><a href="/blog/business/knowledge-cards/cdp/" data-link-title="CDP" data-link-desc="說明客戶資料平台的角色與商業定位">CDP</a></td>
          <td>客戶資料平台</td>
          <td>數據整合、應用層 SaaS</td>
      </tr>
      <tr>
          <td><a href="/blog/business/knowledge-cards/enterprise-license/" data-link-title="Enterprise License" data-link-desc="說明企業級授權的商業模式與鎖定效應">Enterprise License</a></td>
          <td>企業級授權模式</td>
          <td>lock-in、長期合約</td>
      </tr>
  </tbody>
</table>
<h2 id="單位經濟">單位經濟</h2>
<p>每個客戶或每筆交易的成本與利潤結構。判讀一家公司是否真的賺錢的核心語言。</p>
<table>
  <thead>
      <tr>
          <th>卡片</th>
          <th>核心問題</th>
          <th>常見出現位置</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td><a href="/blog/business/knowledge-cards/cogs/" data-link-title="COGS" data-link-desc="說明銷售成本與其對毛利的影響">COGS</a></td>
          <td>賣出產品的直接成本</td>
          <td>gross margin、毛利壓縮</td>
      </tr>
      <tr>
          <td><a href="/blog/business/knowledge-cards/gross-margin/" data-link-title="Gross Margin" data-link-desc="說明毛利率與其對商業模式可行性的決定作用">Gross Margin</a></td>
          <td>毛利率</td>
          <td>SaaS、AI 公司毛利、估值</td>
      </tr>
      <tr>
          <td><a href="/blog/business/knowledge-cards/marginal-cost/" data-link-title="Marginal Cost" data-link-desc="說明邊際成本及其對商業模式擴張性的決定作用">Marginal Cost</a></td>
          <td>多服務一個客戶的邊際成本</td>
          <td>PLG、零邊際複製</td>
      </tr>
      <tr>
          <td><a href="/blog/business/knowledge-cards/pnl/" data-link-title="P&amp;L" data-link-desc="說明損益表的結構與商業判讀作用">P&amp;L</a></td>
          <td>損益表</td>
          <td>burn rate、估值</td>
      </tr>
      <tr>
          <td><a href="/blog/business/knowledge-cards/burn-rate/" data-link-title="Burn Rate" data-link-desc="說明燒錢速度及其對新創存活的決定作用">Burn Rate</a></td>
          <td>燒錢速度</td>
          <td>runway、新創存活</td>
      </tr>
      <tr>
          <td><a href="/blog/business/knowledge-cards/runway/" data-link-title="Runway" data-link-desc="說明新創的現金跑道與融資時點">Runway</a></td>
          <td>現金能撐多久</td>
          <td>burn rate、融資時點</td>
      </tr>
  </tbody>
</table>
<h2 id="進入市場">進入市場</h2>
<p>用什麼通路、銷售模式、組織安排把產品賣出去。</p>
<table>
  <thead>
      <tr>
          <th>卡片</th>
          <th>核心問題</th>
          <th>常見出現位置</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td><a href="/blog/business/knowledge-cards/gtm/" data-link-title="GTM" data-link-desc="說明進入市場策略的完整含義">GTM</a></td>
          <td>進入市場策略</td>
          <td>PLG、FDE、銷售模式</td>
      </tr>
      <tr>
          <td><a href="/blog/business/knowledge-cards/plg/" data-link-title="PLG" data-link-desc="說明產品自助成長模式與其經濟前提">PLG</a></td>
          <td>產品自助成長</td>
          <td>低 CAC、SaaS 經典模式</td>
      </tr>
      <tr>
          <td><a href="/blog/business/knowledge-cards/fde/" data-link-title="FDE" data-link-desc="說明前線部署工程師模式的成立條件">FDE</a></td>
          <td>前線部署工程師</td>
          <td>tacit knowledge、企業客戶</td>
      </tr>
      <tr>
          <td><a href="/blog/business/knowledge-cards/jv/" data-link-title="JV" data-link-desc="說明合資企業的戰略用途">JV</a></td>
          <td>合資企業</td>
          <td>進入企業市場、Palantir 模式</td>
      </tr>
      <tr>
          <td><a href="/blog/business/knowledge-cards/cac/" data-link-title="CAC" data-link-desc="說明獲客成本及其對商業模式可行性的決定作用">CAC</a></td>
          <td>獲客成本</td>
          <td>unit economics、PLG</td>
      </tr>
  </tbody>
</table>
<h2 id="競爭護城河">競爭護城河</h2>
<p>為什麼客戶留下來、為什麼別人打不進來。決定一家公司能否長期擊敗對手。</p>
<table>
  <thead>
      <tr>
          <th>卡片</th>
          <th>核心問題</th>
          <th>常見出現位置</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td><a href="/blog/business/knowledge-cards/lock-in/" data-link-title="Lock-in" data-link-desc="說明鎖定效應如何形成護城河">Lock-in</a></td>
          <td>客戶離不開的結構</td>
          <td>enterprise license、生態系</td>
      </tr>
      <tr>
          <td><a href="/blog/business/knowledge-cards/switching-cost/" data-link-title="Switching Cost" data-link-desc="說明切換成本如何鞏固客戶留存">Switching Cost</a></td>
          <td>切換到競爭對手的成本</td>
          <td>lock-in、retention</td>
      </tr>
      <tr>
          <td><a href="/blog/business/knowledge-cards/retention/" data-link-title="Retention" data-link-desc="說明客戶留存率與其對單位經濟的決定作用">Retention</a></td>
          <td>客戶留存率</td>
          <td>unit economics、SaaS</td>
      </tr>
      <tr>
          <td><a href="/blog/business/knowledge-cards/thin-wrapper/" data-link-title="Thin Wrapper" data-link-desc="說明薄包裝產品的脆弱性">Thin Wrapper</a></td>
          <td>只在底層服務外包一層薄殼</td>
          <td>AI 新創、被輾平</td>
      </tr>
      <tr>
          <td><a href="/blog/business/knowledge-cards/fat-data-fat-skill/" data-link-title="Fat Data / Fat Skill" data-link-desc="說明獨家資料與行業隱性能力作為 AI 時代的護城河">Fat Data / Fat Skill</a></td>
          <td>有獨家資料或行業隱性能力</td>
          <td>護城河、生存空間</td>
      </tr>
      <tr>
          <td><a href="/blog/business/knowledge-cards/connector/" data-link-title="Connector" data-link-desc="說明被收編進生態系變成整合工具的命運">Connector</a></td>
          <td>被收編進生態系變成整合工具</td>
          <td>整併週期、AI Labs</td>
      </tr>
  </tbody>
</table>
<h2 id="市場動態">市場動態</h2>
<p>賽道處在什麼階段、競爭強度、需求類型。判讀一個產業現在能不能進、何時進。</p>
<table>
  <thead>
      <tr>
          <th>卡片</th>
          <th>核心問題</th>
          <th>常見出現位置</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td><a href="/blog/business/knowledge-cards/red-ocean-blue-ocean/" data-link-title="Red Ocean / Blue Ocean" data-link-desc="說明紅海競爭與藍海空白的賽道狀態">Red Ocean / Blue Ocean</a></td>
          <td>紅海競爭與藍海空白</td>
          <td>整併週期、賽道判讀</td>
      </tr>
      <tr>
          <td><a href="/blog/business/knowledge-cards/consolidation-cycle/" data-link-title="Consolidation Cycle" data-link-desc="說明整併週期的階段特徵">Consolidation Cycle</a></td>
          <td>整併週期</td>
          <td>M&amp;A、紅海後段</td>
      </tr>
      <tr>
          <td><a href="/blog/business/knowledge-cards/niche-market/" data-link-title="Niche Market" data-link-desc="說明利基市場的特性與 SaaS 經濟學">Niche Market</a></td>
          <td>利基市場</td>
          <td>Vertical SaaS、護城河</td>
      </tr>
      <tr>
          <td><a href="/blog/business/knowledge-cards/high-stickiness/" data-link-title="High Stickiness" data-link-desc="說明高黏著度的形成條件">High Stickiness</a></td>
          <td>高黏著度</td>
          <td>lock-in、SaaS retention</td>
      </tr>
      <tr>
          <td><a href="/blog/business/knowledge-cards/rigid-demand/" data-link-title="Rigid Demand" data-link-desc="說明剛性需求的判讀訊號">Rigid Demand</a></td>
          <td>剛性需求</td>
          <td>客戶非要不可的訊號</td>
      </tr>
      <tr>
          <td><a href="/blog/business/knowledge-cards/frontier-capability/" data-link-title="Frontier Capability" data-link-desc="說明前沿能力差距如何影響商業策略">Frontier Capability</a></td>
          <td>前沿能力</td>
          <td>AI Labs、領先差距</td>
      </tr>
      <tr>
          <td><a href="/blog/business/knowledge-cards/distribution/" data-link-title="Distribution" data-link-desc="說明分發優勢作為現有玩家的核心護城河">Distribution</a></td>
          <td>分發優勢</td>
          <td>Big Tech、現有客戶基礎</td>
      </tr>
  </tbody>
</table>
<h2 id="資本估值">資本估值</h2>
<p>公司價值怎麼被定價、被誰定價、何時崩塌。</p>
<table>
  <thead>
      <tr>
          <th>卡片</th>
          <th>核心問題</th>
          <th>常見出現位置</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td><a href="/blog/business/knowledge-cards/venture-capital/" data-link-title="Venture Capital (VC)" data-link-desc="說明創投的投資邏輯與對新創估值的影響">VC</a></td>
          <td>創投</td>
          <td>種子輪、A 輪、估值</td>
      </tr>
      <tr>
          <td><a href="/blog/business/knowledge-cards/private-equity/" data-link-title="Private Equity (PE)" data-link-desc="說明私募基金與其對中型企業市場的策略意涵">PE</a></td>
          <td>私募基金</td>
          <td>中型企業、被併購</td>
      </tr>
      <tr>
          <td><a href="/blog/business/knowledge-cards/valuation/" data-link-title="Valuation" data-link-desc="說明估值的構成與商業判讀作用">Valuation</a></td>
          <td>估值</td>
          <td>融資、退場、毛利</td>
      </tr>
      <tr>
          <td><a href="/blog/business/knowledge-cards/valuation-compression/" data-link-title="Valuation Compression" data-link-desc="說明估值壓縮如何影響新創生存">Valuation Compression</a></td>
          <td>估值壓縮</td>
          <td>毛利下降、新創生存</td>
      </tr>
      <tr>
          <td><a href="/blog/business/knowledge-cards/unit-economics/" data-link-title="Unit Economics" data-link-desc="說明單位經濟模型與其判斷一家公司是否賺錢的責任">Unit Economics</a></td>
          <td>單位經濟</td>
          <td>LTV/CAC、是否賺錢</td>
      </tr>
      <tr>
          <td><a href="/blog/business/knowledge-cards/ltv/" data-link-title="LTV" data-link-desc="說明客戶終身價值與其在估值中的作用">LTV</a></td>
          <td>客戶終身價值</td>
          <td>retention、CAC、毛利</td>
      </tr>
  </tbody>
</table>
<h2 id="執行知識">執行知識</h2>
<p>把產品做出來、把客戶服務好的隱性能力。常被低估、卻是 AI 時代差異化的核心。</p>
<table>
  <thead>
      <tr>
          <th>卡片</th>
          <th>核心問題</th>
          <th>常見出現位置</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td><a href="/blog/business/knowledge-cards/tacit-knowledge/" data-link-title="Tacit Knowledge" data-link-desc="說明隱性知識與其作為護城河的價值">Tacit Knowledge</a></td>
          <td>隱性知識</td>
          <td>FDE、SOP 寫不出來的部分</td>
      </tr>
      <tr>
          <td><a href="/blog/business/knowledge-cards/evaluation-set/" data-link-title="Evaluation Set" data-link-desc="說明評估集如何把隱性知識編碼進 AI 產品">Evaluation Set</a></td>
          <td>評估集</td>
          <td>AI 產品、tacit knowledge 編碼</td>
      </tr>
      <tr>
          <td><a href="/blog/business/knowledge-cards/prd/" data-link-title="PRD" data-link-desc="說明產品需求文件與其在傳統 SaaS 開發中的角色">PRD</a></td>
          <td>產品需求文件</td>
          <td>傳統 SaaS、wireframe</td>
      </tr>
      <tr>
          <td><a href="/blog/business/knowledge-cards/wireframe/" data-link-title="Wireframe" data-link-desc="說明線框圖在傳統產品設計流程中的角色">Wireframe</a></td>
          <td>線框圖</td>
          <td>PRD、UI 規劃</td>
      </tr>
      <tr>
          <td><a href="/blog/business/knowledge-cards/vibe-code/" data-link-title="Vibe Code" data-link-desc="說明用 AI 即時生成程式的開發模式">Vibe Code</a></td>
          <td>用 AI 即時生成程式</td>
          <td>FDE、需求迭代</td>
      </tr>
      <tr>
          <td><a href="/blog/business/knowledge-cards/judgment-stake/" data-link-title="Judgment Stake" data-link-desc="說明判斷的賭注被 AI 放大的結構">Judgment Stake</a></td>
          <td>判斷的賭注被放大</td>
          <td>AI 取代論、資深角色</td>
      </tr>
      <tr>
          <td><a href="/blog/business/knowledge-cards/junior-buffer/" data-link-title="Junior Buffer" data-link-desc="說明初階員工作為組織判斷緩衝的傳統結構">Junior Buffer</a></td>
          <td>初階員工作為判斷緩衝層</td>
          <td>judgment stake、組織結構</td>
      </tr>
  </tbody>
</table>
]]></content:encoded></item><item><title>Knowledge Cards</title><link>https://tarrragon.github.io/blog/llm/knowledge-cards/</link><pubDate>Mon, 11 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/llm/knowledge-cards/</guid><description>&lt;p>前置知識卡片的目標是把本地 LLM 章節會用到的高密度術語拆成可獨立閱讀的概念。模組零的心智模型文章會引用 token、自回歸、KV cache、量化、speculative decoding、MTP、MLX、推論伺服器、OpenAI 相容 API 等詞彙；這些詞彙背後都有明確的角色、訊號與設計責任。&lt;/p>
&lt;p>這個模組先建立共同語言。每張卡片只處理一個概念，並用「概念位置、可觀察訊號、接近真實的例子、設計責任」說明它在本地 LLM 生態中的角色。讀者可以從章節中遇到陌生詞時點進來補完，回到原章節仍能接續閱讀。&lt;/p>
&lt;h2 id="卡片分類">卡片分類&lt;/h2>
&lt;h3 id="模型輸出機制">模型輸出機制&lt;/h3>
&lt;table>
 &lt;thead>
 &lt;tr>
 &lt;th>卡片&lt;/th>
 &lt;th>核心問題&lt;/th>
 &lt;/tr>
 &lt;/thead>
 &lt;tbody>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/token/" data-link-title="Token" data-link-desc="LLM 處理文字時的最小單位：介於字元與單字之間">Token&lt;/a>&lt;/td>
 &lt;td>模型如何把文字切成可運算單位&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/autoregressive/" data-link-title="Autoregressive" data-link-desc="LLM 一次生成一個 token、把已生成內容作為下一次輸入的架構">Autoregressive&lt;/a>&lt;/td>
 &lt;td>模型如何一次生一個 token&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/tokens-per-second/" data-link-title="Tokens Per Second" data-link-desc="LLM 每秒能生成幾個 token：生字速度的標準量化指標">Tokens Per Second&lt;/a>&lt;/td>
 &lt;td>生字速度如何被量化&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/ttft/" data-link-title="TTFT" data-link-desc="Time To First Token：送出 prompt 到第一個 token 出現的等待時間">TTFT&lt;/a>&lt;/td>
 &lt;td>從送出 prompt 到第一個 token 的等待時間&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/context-window/" data-link-title="Context Window" data-link-desc="模型一次能處理的最大 token 數量：prompt 加生成的總和上限">Context Window&lt;/a>&lt;/td>
 &lt;td>模型一次能處理多少 token&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/prefill/" data-link-title="Prefill" data-link-desc="Prompt 首次處理時的計算階段：把整段輸入跑過模型、產生 KV cache">Prefill&lt;/a>&lt;/td>
 &lt;td>prompt 首次處理時的計算階段&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/kv-cache/" data-link-title="KV Cache" data-link-desc="已處理 token 的 attention 中間結果暫存：避免重算、加速後續生成">KV Cache&lt;/a>&lt;/td>
 &lt;td>已處理過的 token 如何避免重算&lt;/td>
 &lt;/tr>
 &lt;/tbody>
&lt;/table>
&lt;h3 id="模型權重與量化">模型權重與量化&lt;/h3>
&lt;table>
 &lt;thead>
 &lt;tr>
 &lt;th>卡片&lt;/th>
 &lt;th>核心問題&lt;/th>
 &lt;/tr>
 &lt;/thead>
 &lt;tbody>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/quantization/" data-link-title="Quantization" data-link-desc="用較少 bits 表示模型權重：壓縮記憶體佔用、加快生字速度，代價是少量品質衰減">Quantization&lt;/a>&lt;/td>
 &lt;td>模型權重如何用較少 bits 表示&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/gguf/" data-link-title="GGUF" data-link-desc="llama.cpp 生態定義的模型權重格式：把權重、tokenizer、metadata 打包成單一檔案">GGUF&lt;/a>&lt;/td>
 &lt;td>llama.cpp 系統如何打包模型權重&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/instruction-tuned/" data-link-title="Instruction-Tuned Model" data-link-desc="經過指令微調的模型：會跟著 prompt 走、回答使用者問題">Instruction-Tuned Model&lt;/a>&lt;/td>
 &lt;td>模型如何跟著 prompt 走&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/base-model/" data-link-title="Base Model" data-link-desc="未經指令微調的原始模型：擅長文字接龍、適合下游微調用途">Base Model&lt;/a>&lt;/td>
 &lt;td>未微調的原始模型適合什麼用途&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/embedding-model/" data-link-title="Embedding Model" data-link-desc="把文字轉成向量的模型：用於 codebase 索引與語意搜尋">Embedding Model&lt;/a>&lt;/td>
 &lt;td>文字如何轉成可比對的向量&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/model-card/" data-link-title="Model Card" data-link-desc="Hugging Face 等平台上模型的 metadata 文件、列出模型來源、訓練資料、能力、限制、授權">Model Card&lt;/a>&lt;/td>
 &lt;td>判讀模型來源、訓練資料、授權的 metadata&lt;/td>
 &lt;/tr>
 &lt;/tbody>
&lt;/table>
&lt;h3 id="推論加速技巧">推論加速技巧&lt;/h3>
&lt;table>
 &lt;thead>
 &lt;tr>
 &lt;th>卡片&lt;/th>
 &lt;th>核心問題&lt;/th>
 &lt;/tr>
 &lt;/thead>
 &lt;tbody>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/speculative-decoding/" data-link-title="Speculative Decoding" data-link-desc="用小模型猜未來 token、大模型並行驗證的加速技巧">Speculative Decoding&lt;/a>&lt;/td>
 &lt;td>怎麼一次生多個 token&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/mtp/" data-link-title="Multi-Token Prediction (MTP)" data-link-desc="Google 為 Gemma 系列釋出的 speculative decoding 工程化實作">Multi-Token Prediction&lt;/a>&lt;/td>
 &lt;td>speculative decoding 的工程化實作&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/drafter-model/" data-link-title="Drafter Model" data-link-desc="speculative decoding 中用來快速猜未來 token 的小模型">Drafter Model&lt;/a>&lt;/td>
 &lt;td>預測未來 token 的小模型&lt;/td>
 &lt;/tr>
 &lt;/tbody>
&lt;/table>
&lt;h3 id="推論基礎建設">推論基礎建設&lt;/h3>
&lt;table>
 &lt;thead>
 &lt;tr>
 &lt;th>卡片&lt;/th>
 &lt;th>核心問題&lt;/th>
 &lt;/tr>
 &lt;/thead>
 &lt;tbody>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/three-layer-architecture/" data-link-title="Three-Layer Architecture" data-link-desc="把本地 LLM 工具拆成介面層、推論伺服器層、模型權重層的基礎心智模型">Three-Layer Architecture&lt;/a>&lt;/td>
 &lt;td>介面 / 伺服器 / 模型三層分工心智模型&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/inference-server/" data-link-title="Inference Server" data-link-desc="載入模型權重、處理 prompt、產生 token 的常駐 process">Inference Server&lt;/a>&lt;/td>
 &lt;td>載入模型、提供 API 的常駐 process&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/openai-compatible-api/" data-link-title="OpenAI 相容 API" data-link-desc="本地推論伺服器跟雲端 OpenAI 共用的 API 形狀標準">OpenAI 相容 API&lt;/a>&lt;/td>
 &lt;td>介面層跟伺服器層之間的標準介面&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/model-tag/" data-link-title="Model Tag" data-link-desc="Ollama 等推論伺服器用來定位特定模型版本的命名規則">Model Tag&lt;/a>&lt;/td>
 &lt;td>推論伺服器如何指名某個模型版本&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/mlx/" data-link-title="MLX" data-link-desc="Apple 釋出的 Apple Silicon 數值運算 framework：類似 PyTorch / JAX 的 Mac 對應物">MLX&lt;/a>&lt;/td>
 &lt;td>Apple Silicon 的數值運算 framework&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/omlx/" data-link-title="oMLX" data-link-desc="以 MLX 為基礎、針對 Apple Silicon 長 context 與 SSD KV cache 優化的本地推論伺服器路線">oMLX&lt;/a>&lt;/td>
 &lt;td>MLX-backed 長 context 推論伺服器路線&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/local-vs-cloud/" data-link-title="Local vs Cloud LLM" data-link-desc="用隱私、成本、延遲、能力與維運責任判斷任務該跑本地模型還是雲端模型">Local vs Cloud LLM&lt;/a>&lt;/td>
 &lt;td>本地與雲端模型的任務分工取捨&lt;/td>
 &lt;/tr>
 &lt;/tbody>
&lt;/table>
&lt;h3 id="macos-與-shell-基礎">macOS 與 shell 基礎&lt;/h3>
&lt;p>讓對 Mac 操作不熟的讀者也能跟上本地 LLM 章節。這組卡片不算 LLM 領域知識、但本地 LLM 章節必然會碰到。&lt;/p></description><content:encoded><![CDATA[<p>前置知識卡片的目標是把本地 LLM 章節會用到的高密度術語拆成可獨立閱讀的概念。模組零的心智模型文章會引用 token、自回歸、KV cache、量化、speculative decoding、MTP、MLX、推論伺服器、OpenAI 相容 API 等詞彙；這些詞彙背後都有明確的角色、訊號與設計責任。</p>
<p>這個模組先建立共同語言。每張卡片只處理一個概念，並用「概念位置、可觀察訊號、接近真實的例子、設計責任」說明它在本地 LLM 生態中的角色。讀者可以從章節中遇到陌生詞時點進來補完，回到原章節仍能接續閱讀。</p>
<h2 id="卡片分類">卡片分類</h2>
<h3 id="模型輸出機制">模型輸出機制</h3>
<table>
  <thead>
      <tr>
          <th>卡片</th>
          <th>核心問題</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td><a href="/blog/llm/knowledge-cards/token/" data-link-title="Token" data-link-desc="LLM 處理文字時的最小單位：介於字元與單字之間">Token</a></td>
          <td>模型如何把文字切成可運算單位</td>
      </tr>
      <tr>
          <td><a href="/blog/llm/knowledge-cards/autoregressive/" data-link-title="Autoregressive" data-link-desc="LLM 一次生成一個 token、把已生成內容作為下一次輸入的架構">Autoregressive</a></td>
          <td>模型如何一次生一個 token</td>
      </tr>
      <tr>
          <td><a href="/blog/llm/knowledge-cards/tokens-per-second/" data-link-title="Tokens Per Second" data-link-desc="LLM 每秒能生成幾個 token：生字速度的標準量化指標">Tokens Per Second</a></td>
          <td>生字速度如何被量化</td>
      </tr>
      <tr>
          <td><a href="/blog/llm/knowledge-cards/ttft/" data-link-title="TTFT" data-link-desc="Time To First Token：送出 prompt 到第一個 token 出現的等待時間">TTFT</a></td>
          <td>從送出 prompt 到第一個 token 的等待時間</td>
      </tr>
      <tr>
          <td><a href="/blog/llm/knowledge-cards/context-window/" data-link-title="Context Window" data-link-desc="模型一次能處理的最大 token 數量：prompt 加生成的總和上限">Context Window</a></td>
          <td>模型一次能處理多少 token</td>
      </tr>
      <tr>
          <td><a href="/blog/llm/knowledge-cards/prefill/" data-link-title="Prefill" data-link-desc="Prompt 首次處理時的計算階段：把整段輸入跑過模型、產生 KV cache">Prefill</a></td>
          <td>prompt 首次處理時的計算階段</td>
      </tr>
      <tr>
          <td><a href="/blog/llm/knowledge-cards/kv-cache/" data-link-title="KV Cache" data-link-desc="已處理 token 的 attention 中間結果暫存：避免重算、加速後續生成">KV Cache</a></td>
          <td>已處理過的 token 如何避免重算</td>
      </tr>
  </tbody>
</table>
<h3 id="模型權重與量化">模型權重與量化</h3>
<table>
  <thead>
      <tr>
          <th>卡片</th>
          <th>核心問題</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td><a href="/blog/llm/knowledge-cards/quantization/" data-link-title="Quantization" data-link-desc="用較少 bits 表示模型權重：壓縮記憶體佔用、加快生字速度，代價是少量品質衰減">Quantization</a></td>
          <td>模型權重如何用較少 bits 表示</td>
      </tr>
      <tr>
          <td><a href="/blog/llm/knowledge-cards/gguf/" data-link-title="GGUF" data-link-desc="llama.cpp 生態定義的模型權重格式：把權重、tokenizer、metadata 打包成單一檔案">GGUF</a></td>
          <td>llama.cpp 系統如何打包模型權重</td>
      </tr>
      <tr>
          <td><a href="/blog/llm/knowledge-cards/instruction-tuned/" data-link-title="Instruction-Tuned Model" data-link-desc="經過指令微調的模型：會跟著 prompt 走、回答使用者問題">Instruction-Tuned Model</a></td>
          <td>模型如何跟著 prompt 走</td>
      </tr>
      <tr>
          <td><a href="/blog/llm/knowledge-cards/base-model/" data-link-title="Base Model" data-link-desc="未經指令微調的原始模型：擅長文字接龍、適合下游微調用途">Base Model</a></td>
          <td>未微調的原始模型適合什麼用途</td>
      </tr>
      <tr>
          <td><a href="/blog/llm/knowledge-cards/embedding-model/" data-link-title="Embedding Model" data-link-desc="把文字轉成向量的模型：用於 codebase 索引與語意搜尋">Embedding Model</a></td>
          <td>文字如何轉成可比對的向量</td>
      </tr>
      <tr>
          <td><a href="/blog/llm/knowledge-cards/model-card/" data-link-title="Model Card" data-link-desc="Hugging Face 等平台上模型的 metadata 文件、列出模型來源、訓練資料、能力、限制、授權">Model Card</a></td>
          <td>判讀模型來源、訓練資料、授權的 metadata</td>
      </tr>
  </tbody>
</table>
<h3 id="推論加速技巧">推論加速技巧</h3>
<table>
  <thead>
      <tr>
          <th>卡片</th>
          <th>核心問題</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td><a href="/blog/llm/knowledge-cards/speculative-decoding/" data-link-title="Speculative Decoding" data-link-desc="用小模型猜未來 token、大模型並行驗證的加速技巧">Speculative Decoding</a></td>
          <td>怎麼一次生多個 token</td>
      </tr>
      <tr>
          <td><a href="/blog/llm/knowledge-cards/mtp/" data-link-title="Multi-Token Prediction (MTP)" data-link-desc="Google 為 Gemma 系列釋出的 speculative decoding 工程化實作">Multi-Token Prediction</a></td>
          <td>speculative decoding 的工程化實作</td>
      </tr>
      <tr>
          <td><a href="/blog/llm/knowledge-cards/drafter-model/" data-link-title="Drafter Model" data-link-desc="speculative decoding 中用來快速猜未來 token 的小模型">Drafter Model</a></td>
          <td>預測未來 token 的小模型</td>
      </tr>
  </tbody>
</table>
<h3 id="推論基礎建設">推論基礎建設</h3>
<table>
  <thead>
      <tr>
          <th>卡片</th>
          <th>核心問題</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td><a href="/blog/llm/knowledge-cards/three-layer-architecture/" data-link-title="Three-Layer Architecture" data-link-desc="把本地 LLM 工具拆成介面層、推論伺服器層、模型權重層的基礎心智模型">Three-Layer Architecture</a></td>
          <td>介面 / 伺服器 / 模型三層分工心智模型</td>
      </tr>
      <tr>
          <td><a href="/blog/llm/knowledge-cards/inference-server/" data-link-title="Inference Server" data-link-desc="載入模型權重、處理 prompt、產生 token 的常駐 process">Inference Server</a></td>
          <td>載入模型、提供 API 的常駐 process</td>
      </tr>
      <tr>
          <td><a href="/blog/llm/knowledge-cards/openai-compatible-api/" data-link-title="OpenAI 相容 API" data-link-desc="本地推論伺服器跟雲端 OpenAI 共用的 API 形狀標準">OpenAI 相容 API</a></td>
          <td>介面層跟伺服器層之間的標準介面</td>
      </tr>
      <tr>
          <td><a href="/blog/llm/knowledge-cards/model-tag/" data-link-title="Model Tag" data-link-desc="Ollama 等推論伺服器用來定位特定模型版本的命名規則">Model Tag</a></td>
          <td>推論伺服器如何指名某個模型版本</td>
      </tr>
      <tr>
          <td><a href="/blog/llm/knowledge-cards/mlx/" data-link-title="MLX" data-link-desc="Apple 釋出的 Apple Silicon 數值運算 framework：類似 PyTorch / JAX 的 Mac 對應物">MLX</a></td>
          <td>Apple Silicon 的數值運算 framework</td>
      </tr>
      <tr>
          <td><a href="/blog/llm/knowledge-cards/omlx/" data-link-title="oMLX" data-link-desc="以 MLX 為基礎、針對 Apple Silicon 長 context 與 SSD KV cache 優化的本地推論伺服器路線">oMLX</a></td>
          <td>MLX-backed 長 context 推論伺服器路線</td>
      </tr>
      <tr>
          <td><a href="/blog/llm/knowledge-cards/local-vs-cloud/" data-link-title="Local vs Cloud LLM" data-link-desc="用隱私、成本、延遲、能力與維運責任判斷任務該跑本地模型還是雲端模型">Local vs Cloud LLM</a></td>
          <td>本地與雲端模型的任務分工取捨</td>
      </tr>
  </tbody>
</table>
<h3 id="macos-與-shell-基礎">macOS 與 shell 基礎</h3>
<p>讓對 Mac 操作不熟的讀者也能跟上本地 LLM 章節。這組卡片不算 LLM 領域知識、但本地 LLM 章節必然會碰到。</p>
<table>
  <thead>
      <tr>
          <th>卡片</th>
          <th>核心問題</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td><a href="/blog/llm/knowledge-cards/homebrew/" data-link-title="Homebrew" data-link-desc="macOS 上社群維護的套件管理器、用一行指令安裝 CLI 工具與背景服務">Homebrew</a></td>
          <td>macOS 上 CLI 工具的標準安裝入口</td>
      </tr>
      <tr>
          <td><a href="/blog/llm/knowledge-cards/launchd-service/" data-link-title="launchd Service" data-link-desc="macOS 原生的服務管理機制、把 process 註冊成自動啟動的 daemon 或 agent">launchd Service</a></td>
          <td>讓 Ollama 等服務開機自動啟動的 macOS 機制</td>
      </tr>
      <tr>
          <td><a href="/blog/llm/knowledge-cards/shell-background-process/" data-link-title="Shell 背景 Process" data-link-desc="終端機 process 的前景 / 背景生命週期、訊號控制、找出佔用 port 的 process">Shell 背景 Process</a></td>
          <td>前景 vs 背景、<code>&amp;</code>、<code>Ctrl+C</code>、找 process 的方法</td>
      </tr>
      <tr>
          <td><a href="/blog/llm/knowledge-cards/port-and-localhost/" data-link-title="Port 與 Localhost" data-link-desc="TCP port 與 listen address 如何決定 API server 的對外暴露範圍">Port 與 Localhost</a></td>
          <td>server 暴露在哪個地址、誰能連進來</td>
      </tr>
  </tbody>
</table>
<h3 id="硬體與架構">硬體與架構</h3>
<table>
  <thead>
      <tr>
          <th>卡片</th>
          <th>核心問題</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td><a href="/blog/llm/knowledge-cards/memory-bandwidth/" data-link-title="Memory Bandwidth" data-link-desc="記憶體每秒能讀寫多少 bytes：決定本地 LLM 生字速度的真正瓶頸">Memory Bandwidth</a></td>
          <td>為什麼記憶體頻寬決定生字速度</td>
      </tr>
      <tr>
          <td><a href="/blog/llm/knowledge-cards/unified-memory/" data-link-title="Unified Memory Architecture" data-link-desc="Apple Silicon 讓 CPU / GPU / NE 共用同一塊記憶體：跑大模型的優勢來源">Unified Memory Architecture</a></td>
          <td>Apple Silicon 怎麼讓模型用滿大記憶體</td>
      </tr>
      <tr>
          <td><a href="/blog/llm/knowledge-cards/vram/" data-link-title="VRAM" data-link-desc="顯卡上的記憶體、跟系統 RAM 是兩塊獨立預算、決定能載入多大模型權重跟 KV cache">VRAM</a></td>
          <td>獨立 GPU 場景的顯卡記憶體、跟系統 RAM 分層</td>
      </tr>
      <tr>
          <td><a href="/blog/llm/knowledge-cards/pcie/" data-link-title="PCIe" data-link-desc="PC 上連接 GPU 跟主機板的高速序列匯流排、影響模型載入速度跟 MoE 卸載時的推論吞吐">PCIe</a></td>
          <td>GPU 跟主機板之間的高速序列匯流排</td>
      </tr>
      <tr>
          <td><a href="/blog/llm/knowledge-cards/nvlink/" data-link-title="NVLink" data-link-desc="NVIDIA 多 GPU 之間的高速互連介面、提供比 PCIe 更高的卡間頻寬、消費級 RTX 系列普遍不支援">NVLink</a></td>
          <td>NVIDIA 多卡互連、跟 PCIe 比的卡間頻寬優勢</td>
      </tr>
      <tr>
          <td><a href="/blog/llm/knowledge-cards/gpu-compute-backend/" data-link-title="GPU Compute Backend" data-link-desc="GPU 加速計算的底層 API 介面（CUDA / ROCm / Vulkan / Metal / SYCL）、決定推論軟體能否用 GPU 跑得快">GPU Compute Backend</a></td>
          <td>CUDA / ROCm / Vulkan / Metal / SYCL 對照</td>
      </tr>
      <tr>
          <td><a href="/blog/llm/knowledge-cards/transformer/" data-link-title="Transformer" data-link-desc="寫 code 用的 LLM 神經網路架構：基於 attention 機制、自回歸生成 token">Transformer</a></td>
          <td>寫 code 用的 LLM 是哪種神經網路</td>
      </tr>
      <tr>
          <td><a href="/blog/llm/knowledge-cards/attention/" data-link-title="Attention" data-link-desc="Transformer 內部讓每個 token 對其他 token 加權平均的核心機制、形成 KV cache 跟 context window 的計算基礎">Attention</a></td>
          <td>Transformer 內部讓 token 互相加權平均的機制</td>
      </tr>
      <tr>
          <td><a href="/blog/llm/knowledge-cards/self-attention/" data-link-title="Self-Attention" data-link-desc="Q / K / V 都從同一個 sequence 投影出來的 attention、Transformer 的標誌性設計">Self-Attention</a></td>
          <td>Q/K/V 都來自同一序列的 attention、LLM 標誌</td>
      </tr>
      <tr>
          <td><a href="/blog/llm/knowledge-cards/multi-head-attention/" data-link-title="Multi-Head Attention" data-link-desc="把 attention 切成多個 head 並行計算、讓模型能同時注意多種模式">Multi-Head Attention</a></td>
          <td>把 attention 切成多個 head 並行、MHA/GQA/MLA</td>
      </tr>
      <tr>
          <td><a href="/blog/llm/knowledge-cards/causal-mask/" data-link-title="Causal Mask" data-link-desc="在 self-attention 裡擋掉「未來位置」的遮罩、讓 LLM 自回歸生成在訓練時也成立">Causal Mask</a></td>
          <td>擋掉「未來位置」的遮罩、decoder-only 的標誌</td>
      </tr>
      <tr>
          <td><a href="/blog/llm/knowledge-cards/rope/" data-link-title="RoPE（Rotary Position Embedding）" data-link-desc="用旋轉矩陣把位置資訊直接旋轉進 Q/K 向量、現代 LLM 主流的位置編碼方式">RoPE</a></td>
          <td>用旋轉矩陣編碼位置、Llama / Gemma / Qwen 主流</td>
      </tr>
      <tr>
          <td><a href="/blog/llm/knowledge-cards/positional-encoding/" data-link-title="Positional Encoding" data-link-desc="把 token 位置資訊注入 Transformer 的機制，讓 attention 能分辨順序與距離">Positional Encoding</a></td>
          <td>把 token 位置資訊注入 Transformer</td>
      </tr>
      <tr>
          <td><a href="/blog/llm/knowledge-cards/flash-attention/" data-link-title="Flash Attention" data-link-desc="Attention 計算的記憶體友善實作、減少 GPU memory 讀寫、提升長 context 推論吞吐">Flash Attention</a></td>
          <td>Attention 計算的記憶體友善實作</td>
      </tr>
      <tr>
          <td><a href="/blog/llm/knowledge-cards/grouped-query-attention/" data-link-title="Grouped-Query Attention" data-link-desc="讓多個 query head 共用較少的 key/value head，以降低 KV cache 體積與推論記憶體壓力">Grouped-Query Attention</a></td>
          <td>多個 query head 共用較少 K/V head</td>
      </tr>
      <tr>
          <td><a href="/blog/llm/knowledge-cards/ffn/" data-link-title="FFN（Feed-Forward Network）" data-link-desc="Transformer block 內部的兩層 linear &#43; activation、佔模型參數量的多數">FFN</a></td>
          <td>Transformer block 內部的兩層 linear、參數大頭</td>
      </tr>
      <tr>
          <td><a href="/blog/llm/knowledge-cards/activation-function/" data-link-title="Activation Function" data-link-desc="在 linear layer 之間插入的非線性函數、讓神經網路能表達非線性關係">Activation Function</a></td>
          <td>FFN 內的非線性、讓深度網路真的「深」起來</td>
      </tr>
      <tr>
          <td><a href="/blog/llm/knowledge-cards/layer-normalization/" data-link-title="Layer Normalization" data-link-desc="在每個 token 的 hidden state 上做正規化（減 mean、除 std）、穩定深層網路訓練">Layer Normalization</a></td>
          <td>對 hidden state 正規化、穩定深層訓練</td>
      </tr>
      <tr>
          <td><a href="/blog/llm/knowledge-cards/residual-connection/" data-link-title="Residual Connection" data-link-desc="把 layer 的輸入直接加到輸出上的「跳接」、讓深層網路的梯度能穩定回流">Residual Connection</a></td>
          <td>layer 輸入直接加到輸出、讓 gradient 能回流深層</td>
      </tr>
      <tr>
          <td><a href="/blog/llm/knowledge-cards/residual-stream/" data-link-title="Residual Stream" data-link-desc="Transformer block 之間持續傳遞與累積資訊的 hidden state 通道，常用於架構與 mechanistic interpretability 討論">Residual Stream</a></td>
          <td>Transformer block 間累積資訊的 hidden state 通道</td>
      </tr>
      <tr>
          <td><a href="/blog/llm/knowledge-cards/embedding-layer/" data-link-title="Embedding Layer" data-link-desc="Transformer 第一層的查表結構、把整數 token ID 轉成可運算的向量">Embedding Layer</a></td>
          <td>Transformer 第一層、把 token ID 轉成向量</td>
      </tr>
      <tr>
          <td><a href="/blog/llm/knowledge-cards/forward-pass/" data-link-title="Forward Pass" data-link-desc="input 經過所有 layer 的計算、得到 output 的單向流程；推論跟訓練都會跑、訓練多一個反向階段">Forward Pass</a></td>
          <td>input 流經所有 layer 的單向計算流程</td>
      </tr>
      <tr>
          <td><a href="/blog/llm/knowledge-cards/diffusion/" data-link-title="Diffusion" data-link-desc="產圖用的生成式 AI 架構：跟寫 code 用的 Transformer 是不同路線">Diffusion</a></td>
          <td>產圖用的是哪種神經網路</td>
      </tr>
  </tbody>
</table>
<h3 id="線性代數基礎">線性代數基礎</h3>
<table>
  <thead>
      <tr>
          <th>卡片</th>
          <th>核心問題</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td><a href="/blog/llm/knowledge-cards/tensor/" data-link-title="Tensor" data-link-desc="多維陣列、矩陣是 2D 特例、PyTorch / MLX / JAX 等 framework 的核心型別">Tensor</a></td>
          <td>多維陣列、framework 核心型別</td>
      </tr>
      <tr>
          <td><a href="/blog/llm/knowledge-cards/vector-norm/" data-link-title="Vector Norm" data-link-desc="衡量向量大小的純量值、L1 / L2 / L∞ 各有用途、cosine similarity 的基礎">Vector Norm</a></td>
          <td>衡量向量大小、L1 / L2 / L∞ 的不同用途</td>
      </tr>
      <tr>
          <td><a href="/blog/llm/knowledge-cards/dot-product/" data-link-title="Dot Product" data-link-desc="兩個向量對應位置相乘再加總、attention score 跟相似度判讀的基礎">Dot Product</a></td>
          <td>兩向量相乘加總、attention / similarity 基礎</td>
      </tr>
      <tr>
          <td><a href="/blog/llm/knowledge-cards/matrix-multiplication/" data-link-title="Matrix Multiplication" data-link-desc="LLM 推論最頻繁的單一運算、forward pass 每層的核心、memory bandwidth 瓶頸的根源">Matrix Multiplication</a></td>
          <td>LLM 推論最頻繁的單一運算、memory bandwidth bound</td>
      </tr>
      <tr>
          <td><a href="/blog/llm/knowledge-cards/floating-point/" data-link-title="Floating Point（FP32 / FP16 / BF16）" data-link-desc="fp32 / fp16 / bf16 浮點格式的位元結構與 LLM 訓練 / 推論的精度取捨">Floating Point</a></td>
          <td>FP32 / FP16 / BF16 的位元結構與精度取捨</td>
      </tr>
  </tbody>
</table>
<h3 id="llm-機率與資訊論">LLM 機率與資訊論</h3>
<table>
  <thead>
      <tr>
          <th>卡片</th>
          <th>核心問題</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td><a href="/blog/llm/knowledge-cards/softmax/" data-link-title="Softmax" data-link-desc="把任意實數向量正規化成「總和為 1、每個分量 ∈ [0,1]」的機率分佈">Softmax</a></td>
          <td>把實數向量轉成機率分佈、attention / sampling 共用</td>
      </tr>
      <tr>
          <td><a href="/blog/llm/knowledge-cards/logit/" data-link-title="Logit" data-link-desc="softmax 之前的原始實數分數、每個 vocab token 一個值、可正可負">Logit</a></td>
          <td>softmax 之前的原始分數、可正可負</td>
      </tr>
      <tr>
          <td><a href="/blog/llm/knowledge-cards/entropy/" data-link-title="Entropy" data-link-desc="資訊論衡量「分佈的不確定性」的指標、cross-entropy / KL divergence 的基底">Entropy</a></td>
          <td>分佈的不確定性、cross-entropy / KL 的基底</td>
      </tr>
      <tr>
          <td><a href="/blog/llm/knowledge-cards/cross-entropy/" data-link-title="Cross-Entropy" data-link-desc="衡量「預測機率分佈」跟「真實分佈」距離的指標、LLM 預訓練的主要 loss">Cross-Entropy</a></td>
          <td>預測分佈跟真實分佈的距離、預訓練主要 loss</td>
      </tr>
      <tr>
          <td><a href="/blog/llm/knowledge-cards/perplexity/" data-link-title="Perplexity" data-link-desc="cross-entropy 的指數形式、直覺意義為「模型平均覺得下個 token 有多少種可能」">Perplexity</a></td>
          <td>cross-entropy 的指數形式、人類直覺較好讀</td>
      </tr>
      <tr>
          <td><a href="/blog/llm/knowledge-cards/kl-divergence/" data-link-title="KL Divergence" data-link-desc="衡量「兩個機率分佈差距」的非對稱指標、RLHF / DPO 等 alignment 訓練的關鍵約束">KL Divergence</a></td>
          <td>兩個分佈的不對稱差距、RLHF / DPO 的 alignment 約束</td>
      </tr>
  </tbody>
</table>
<h3 id="llm-訓練流程">LLM 訓練流程</h3>
<table>
  <thead>
      <tr>
          <th>卡片</th>
          <th>核心問題</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td><a href="/blog/llm/knowledge-cards/loss-function/" data-link-title="Loss Function" data-link-desc="把「模型預測」跟「正確答案」的差距量化成一個純量、訓練的最佳化目標">Loss Function</a></td>
          <td>訓練最佳化的目標、量化「預測 vs 真實」的差距</td>
      </tr>
      <tr>
          <td><a href="/blog/llm/knowledge-cards/gradient/" data-link-title="Gradient" data-link-desc="loss function 對權重的偏微分向量、指出「該往哪個方向調權重才能讓 loss 下降最快」">Gradient</a></td>
          <td>該往哪個方向調權重才能降 loss</td>
      </tr>
      <tr>
          <td><a href="/blog/llm/knowledge-cards/backpropagation/" data-link-title="Backpropagation" data-link-desc="從 output loss 反向遞推、用 chain rule 算出每個權重的 gradient 的演算法">Backpropagation</a></td>
          <td>從 output loss 反向算出每個權重 gradient 的演算法</td>
      </tr>
      <tr>
          <td><a href="/blog/llm/knowledge-cards/gradient-explosion-vanishing/" data-link-title="Gradient Explosion / Vanishing" data-link-desc="深層網路訓練中 gradient 透過 chain rule 累乘、容易爆炸或衰減到 0 的兩種失敗模式">Gradient Explosion / Vanishing</a></td>
          <td>深層網路 chain rule 累乘的兩種失敗模式</td>
      </tr>
      <tr>
          <td><a href="/blog/llm/knowledge-cards/learning-rate/" data-link-title="Learning Rate" data-link-desc="gradient descent 每步更新權重的幅度、訓練中最敏感的 hyperparameter">Learning Rate</a></td>
          <td>gradient descent 每步幅度、最敏感的 hyperparameter</td>
      </tr>
      <tr>
          <td><a href="/blog/llm/knowledge-cards/sgd/" data-link-title="SGD" data-link-desc="Stochastic Gradient Descent：每次用 mini-batch 算 gradient 更新權重的基礎 optimizer">SGD</a></td>
          <td>用 mini-batch 算 gradient 更新的基礎 optimizer</td>
      </tr>
      <tr>
          <td><a href="/blog/llm/knowledge-cards/adam-adamw/" data-link-title="Adam / AdamW" data-link-desc="對每個參數自適應 learning rate 的 optimizer、LLM 訓練主流選擇">Adam / AdamW</a></td>
          <td>對每個參數自適應 lr、LLM 訓練主流 optimizer</td>
      </tr>
      <tr>
          <td><a href="/blog/llm/knowledge-cards/pre-training/" data-link-title="Pre-training" data-link-desc="LLM 訓練的第一階段：用 trillion-token 級網路文字做 next-token prediction、得到 base model">Pre-training</a></td>
          <td>第一階段、用 trillion-token 做 next-token prediction</td>
      </tr>
      <tr>
          <td><a href="/blog/llm/knowledge-cards/sft/" data-link-title="SFT（Supervised Fine-Tuning）" data-link-desc="在 base model 上用「指令-回答」對資料微調、讓模型會跟著指令走">SFT</a></td>
          <td>第二階段、用「指令-回答」對 fine-tune</td>
      </tr>
      <tr>
          <td><a href="/blog/llm/knowledge-cards/rlhf/" data-link-title="RLHF" data-link-desc="Reinforcement Learning from Human Feedback：用人類偏好訓練的 reward model 透過 RL 對齊 LLM">RLHF</a></td>
          <td>用人類偏好 + reward model + RL 對齊</td>
      </tr>
      <tr>
          <td><a href="/blog/llm/knowledge-cards/dpo/" data-link-title="DPO（Direct Preference Optimization）" data-link-desc="RLHF 的簡化替代：跳過 reward model、直接從人類偏好資料 fine-tune LLM">DPO</a></td>
          <td>RLHF 的簡化替代、直接從偏好資料 fine-tune</td>
      </tr>
      <tr>
          <td><a href="/blog/llm/knowledge-cards/lora/" data-link-title="LoRA" data-link-desc="Low-Rank Adaptation：凍住原模型權重、只訓兩個小矩陣的 parameter-efficient fine-tuning">LoRA</a></td>
          <td>凍住原權重、只訓兩個小矩陣的 PEFT</td>
      </tr>
      <tr>
          <td><a href="/blog/llm/knowledge-cards/qlora/" data-link-title="QLoRA" data-link-desc="把 base model 量化到 4-bit &#43; LoRA fine-tune 的組合、消費級 GPU 也能 fine-tune 大模型">QLoRA</a></td>
          <td>LoRA + 4-bit 量化、消費級 GPU 也能 fine-tune 大模型</td>
      </tr>
      <tr>
          <td><a href="/blog/llm/knowledge-cards/catastrophic-forgetting/" data-link-title="Catastrophic Forgetting" data-link-desc="Fine-tune 模型時、新訓練資料覆蓋掉原本學到的能力的現象、LoRA / 資料 mixing 是主要緩解">Catastrophic Forgetting</a></td>
          <td>Fine-tune 覆蓋掉原有能力的現象、LoRA + 資料 mixing 緩解</td>
      </tr>
      <tr>
          <td><a href="/blog/llm/knowledge-cards/contrastive-learning/" data-link-title="Contrastive Learning" data-link-desc="用「相關 vs 不相關」成對 / 三元組樣本訓練 embedding 的方法、現代 embedding model 的核心訓練 paradigm">Contrastive Learning</a></td>
          <td>Embedding model 的訓練 paradigm、相關靠近 / 無關遠離</td>
      </tr>
      <tr>
          <td><a href="/blog/llm/knowledge-cards/in-context-learning/" data-link-title="In-Context Learning" data-link-desc="模型在不更新權重的情況下，從 prompt 內範例、規則與上下文臨時對齊任務的能力">In-Context Learning</a></td>
          <td>不更新權重、從 prompt 內範例與規則臨時對齊任務</td>
      </tr>
  </tbody>
</table>
<h3 id="reasoning-models">Reasoning Models</h3>
<table>
  <thead>
      <tr>
          <th>卡片</th>
          <th>核心問題</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td><a href="/blog/llm/knowledge-cards/chain-of-thought/" data-link-title="Chain-of-Thought（CoT）" data-link-desc="讓 LLM 先輸出推理步驟再給最終答案的 prompting / 訓練方式、reasoning model 的基礎機制">Chain-of-Thought</a></td>
          <td>讓 LLM 先推理再答的 prompting / 訓練機制</td>
      </tr>
      <tr>
          <td><a href="/blog/llm/knowledge-cards/test-time-compute/" data-link-title="Test-Time Compute" data-link-desc="推論時動態增加計算量換取答案品質的 paradigm、reasoning model 跟 best-of-N 的共同基底">Test-Time Compute</a></td>
          <td>推論時動態增加算力換答案品質的 paradigm</td>
      </tr>
      <tr>
          <td><a href="/blog/llm/knowledge-cards/reasoning-model/" data-link-title="Reasoning Model" data-link-desc="訓練成自然輸出長 reasoning trace 的 LLM 變體、o1 / DeepSeek-R1 / Claude thinking 為代表">Reasoning Model</a></td>
          <td>o1 / R1 / QwQ 等內建長 reasoning trace 的 LLM family</td>
      </tr>
  </tbody>
</table>
<h3 id="vision--多模態">Vision / 多模態</h3>
<table>
  <thead>
      <tr>
          <th>卡片</th>
          <th>核心問題</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td><a href="/blog/llm/knowledge-cards/vlm/" data-link-title="VLM（Vision-Language Model）" data-link-desc="同時吃圖片 &#43; 文字輸入、產生文字輸出的 LLM 變體、coding 工作流中處理截圖 / 設計稿 / UI debug 的基底">VLM</a></td>
          <td>同時吃圖 + 文字輸入的 LLM 變體、coding 場景的 vision 基底</td>
      </tr>
      <tr>
          <td><a href="/blog/llm/knowledge-cards/vision-encoder/" data-link-title="Vision Encoder" data-link-desc="VLM 內部負責把圖片轉成可進 Transformer 的向量序列的模組、ViT / CLIP encoder 為主流">Vision Encoder</a></td>
          <td>VLM 內部把圖轉成向量序列的模組、ViT / CLIP 為主流</td>
      </tr>
      <tr>
          <td><a href="/blog/llm/knowledge-cards/image-token/" data-link-title="Image Token" data-link-desc="VLM 把圖片轉成「對 Transformer 而言跟 text token 同質」的向量、計入 context window 預算">Image Token</a></td>
          <td>VLM 把圖變成跟 text token 同質的向量、計入 context</td>
      </tr>
      <tr>
          <td><a href="/blog/llm/knowledge-cards/clip/" data-link-title="CLIP" data-link-desc="OpenAI 2021 提出的 contrastive image-text pretraining、現代 VLM 的 vision encoder 大多衍生自它">CLIP</a></td>
          <td>OpenAI contrastive 預訓練、現代 vision encoder 起點</td>
      </tr>
      <tr>
          <td><a href="/blog/llm/knowledge-cards/multimodal-fusion/" data-link-title="Multimodal Fusion" data-link-desc="VLM 把 vision encoder 跟 LLM 結合的方式：early fusion / cross-attention / native multimodal 三條路線">Multimodal Fusion</a></td>
          <td>Vision + LLM 結合方式：early / cross-attention / native</td>
      </tr>
  </tbody>
</table>
<h3 id="deployment--靜態場景">Deployment / 靜態場景</h3>
<table>
  <thead>
      <tr>
          <th>卡片</th>
          <th>核心問題</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td><a href="/blog/llm/knowledge-cards/client-side-llm/" data-link-title="Client-Side LLM / Embedding" data-link-desc="在 browser 內直接跑 LLM 或 embedding model 的 paradigm、靜態網站做 RAG 的關鍵基底">Client-Side LLM</a></td>
          <td>在 browser 跑 LLM / embedding、WebLLM / transformers.js</td>
      </tr>
  </tbody>
</table>
<h3 id="coding-agent-工程">Coding Agent 工程</h3>
<table>
  <thead>
      <tr>
          <th>卡片</th>
          <th>核心問題</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td><a href="/blog/llm/knowledge-cards/scaffold-vs-harness/" data-link-title="Scaffold vs Harness" data-link-desc="Coding agent 的兩個工程層次：scaffold 是建構時靜態結構、harness 是 runtime 的 tool dispatch &#43; context management &#43; safety">Scaffold vs Harness</a></td>
          <td>Coding agent 的兩個工程層次：建構時靜態 vs runtime 動態</td>
      </tr>
      <tr>
          <td><a href="/blog/llm/knowledge-cards/context-budget/" data-link-title="Context Budget" data-link-desc="Coding agent 的 context window 拆分配額：system prompt &#43; tool schema &#43; history &#43; file content &#43; reasoning &#43; tool result 各佔多少、留多少 margin">Context Budget</a></td>
          <td>Coding agent context window 拆分配額、25% 規則</td>
      </tr>
      <tr>
          <td><a href="/blog/llm/knowledge-cards/subagent/" data-link-title="Subagent" data-link-desc="Coding agent 中把特定責任拆給專門子 agent 的設計模式、各 subagent 有獨立 context、由 main agent 透過 handoff 調度">Subagent</a></td>
          <td>把特定責任拆給專門子 agent、各自獨立 context、用 handoff 調度</td>
      </tr>
      <tr>
          <td><a href="/blog/llm/knowledge-cards/prompt-cache/" data-link-title="Prompt Cache" data-link-desc="重複出現的 prompt prefix 在推論伺服器或 LLM 服務端被 cache、後續 query 跳過 prefill、大幅降 cost 跟 TTFT">Prompt Cache</a></td>
          <td>重複 prefix 的 KV cache 服務端持久化、90% cost 折扣</td>
      </tr>
      <tr>
          <td><a href="/blog/llm/knowledge-cards/agent-memory/" data-link-title="Agent Memory" data-link-desc="Agent 在 context window 之外管理長期狀態的設計、五個層次：working / short-term / long-term episodic / semantic / procedural">Agent Memory</a></td>
          <td>Working / session / episodic / semantic / procedural 四層</td>
      </tr>
  </tbody>
</table>
<h3 id="production--observability">Production / Observability</h3>
<table>
  <thead>
      <tr>
          <th>卡片</th>
          <th>核心問題</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td><a href="/blog/llm/knowledge-cards/llm-tracing/" data-link-title="LLM Tracing" data-link-desc="把 LLM 應用的每次 LLM call / tool call / memory op 編成結構化 span、用 OpenTelemetry GenAI semantic conventions 標準化">LLM Tracing</a></td>
          <td>OpenTelemetry GenAI semconv、結構化 span 編碼 LLM 應用</td>
      </tr>
      <tr>
          <td><a href="/blog/llm/knowledge-cards/llm-as-judge/" data-link-title="LLM-as-Judge" data-link-desc="用 LLM 評估另一個 LLM 的輸出品質、production eval 的主流方法、500-5000× 成本降但有 bias 要處理">LLM-as-Judge</a></td>
          <td>用 LLM 評另一個 LLM、production eval 主流方法</td>
      </tr>
  </tbody>
</table>
<h3 id="retrieval-進階">Retrieval 進階</h3>
<table>
  <thead>
      <tr>
          <th>卡片</th>
          <th>核心問題</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td><a href="/blog/llm/knowledge-cards/retrieval-source/" data-link-title="Retrieval Source" data-link-desc="RAG 從哪個 corpus、index、tool 或外部系統取回內容，決定來源可信度、freshness、權限與引用責任">Retrieval Source</a></td>
          <td>RAG 從哪個 corpus / index / tool 取回內容、如何追溯來源</td>
      </tr>
      <tr>
          <td><a href="/blog/llm/knowledge-cards/retrieval-cost/" data-link-title="Retrieval Cost" data-link-desc="RAG 檢索帶來的 latency、token、embedding、reranker、LLM call 與維護成本，用來判斷增強是否划算">Retrieval Cost</a></td>
          <td>每次 retrieve 與增強帶來的 latency / token / 維護成本</td>
      </tr>
      <tr>
          <td><a href="/blog/llm/knowledge-cards/query-document-gap/" data-link-title="Query-Document Gap" data-link-desc="使用者 query 與文件語言在詞彙、形態、抽象層級或領域分佈上的落差，是 RAG retrieval miss 的常見原因">Query-Document Gap</a></td>
          <td>query 與 document 語言形狀落差造成 retrieval miss</td>
      </tr>
      <tr>
          <td><a href="/blog/llm/knowledge-cards/retrieval-recall/" data-link-title="Retrieval Recall" data-link-desc="衡量 RAG 檢索是否把應該命中的文件或 chunk 放進 top-k 結果，是 component-level eval 的核心指標">Retrieval Recall</a></td>
          <td>expected chunk 是否出現在 retrieval top-k 結果中</td>
      </tr>
      <tr>
          <td><a href="/blog/llm/knowledge-cards/reranker/" data-link-title="Reranker" data-link-desc="對 retrieval top-K 結果用 cross-encoder 重新排序的 RAG 第二階段、品質提升顯著但 latency / cost 增加">Reranker</a></td>
          <td>Cross-encoder 對 retrieval top-K 重新排序、RAG 第二階段</td>
      </tr>
      <tr>
          <td><a href="/blog/llm/knowledge-cards/hybrid-search/" data-link-title="Hybrid Search" data-link-desc="把字面 retrieval（BM25）跟語意 retrieval（embedding）的結果用 RRF 等方法合併、補單一路線的盲點">Hybrid Search</a></td>
          <td>BM25（字面）+ embedding（語意）合併、補單一路線盲點</td>
      </tr>
  </tbody>
</table>
<h3 id="constrained--structured-output">Constrained / Structured Output</h3>
<table>
  <thead>
      <tr>
          <th>卡片</th>
          <th>核心問題</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td><a href="/blog/llm/knowledge-cards/structured-output/" data-link-title="Structured Output" data-link-desc="讓 LLM 輸出可被 parser 穩定消費的推論階段設計：JSON mode、schema-guided decoding、grammar 約束都屬於這一層">Structured Output</a></td>
          <td>讓模型輸出固定格式、可被 parser 穩定消費</td>
      </tr>
      <tr>
          <td><a href="/blog/llm/knowledge-cards/sampling-constraint/" data-link-title="Sampling Constraint" data-link-desc="推論時限制下一個 token 候選集合的控制手段，用來把模型生成導向合法格式或特定選項">Sampling Constraint</a></td>
          <td>推論時限制下一個 token 候選集合</td>
      </tr>
      <tr>
          <td><a href="/blog/llm/knowledge-cards/constrained-decoding/" data-link-title="Constrained Decoding" data-link-desc="推論時用 grammar 強制 LLM 輸出符合特定格式（JSON / regex / CFG）的 sampling 機制、把不合法 token 的機率歸零">Constrained Decoding</a></td>
          <td>推論時 grammar mask 強制合法 JSON / regex / CFG、反而加速</td>
      </tr>
      <tr>
          <td><a href="/blog/llm/knowledge-cards/grammar/" data-link-title="Grammar" data-link-desc="描述合法字串形狀的形式規則，在 structured output 中用來限制 LLM 每一步可輸出的 token">Grammar</a></td>
          <td>用形式規則描述合法輸出字串</td>
      </tr>
      <tr>
          <td><a href="/blog/llm/knowledge-cards/bnf/" data-link-title="BNF（Backus-Naur Form）" data-link-desc="用遞迴產生式描述語法的經典記法，是 CFG、parser 與 grammar-constrained sampling 常見的基礎表示">BNF</a></td>
          <td>用產生式描述 context-free grammar 的經典記法</td>
      </tr>
      <tr>
          <td><a href="/blog/llm/knowledge-cards/lark-grammar/" data-link-title="Lark Grammar" data-link-desc="Lark parser 使用的 EBNF-like grammar 格式，常被 structured output 工具拿來描述自訂輸出語法">Lark Grammar</a></td>
          <td>Python Lark parser 使用的 EBNF-like grammar 格式</td>
      </tr>
      <tr>
          <td><a href="/blog/llm/knowledge-cards/dsl/" data-link-title="DSL（Domain-Specific Language）" data-link-desc="為特定業務或技術領域設計的小語言，在 LLM 應用中常作為可解析、可驗證、可執行的中介輸出">DSL</a></td>
          <td>為特定領域設計的小語言、作為 LLM 可解析的中介輸出</td>
      </tr>
      <tr>
          <td><a href="/blog/llm/knowledge-cards/training-example-coverage/" data-link-title="Training Example Coverage" data-link-desc="訓練資料中的任務範例是否覆蓋足夠情境，決定模型在 function calling、格式輸出與邊界案例上的穩定性">Training Example Coverage</a></td>
          <td>訓練範例是否覆蓋足夠情境、決定能力穩定性</td>
      </tr>
      <tr>
          <td><a href="/blog/llm/knowledge-cards/capability-spectrum/" data-link-title="Capability Spectrum" data-link-desc="把模型能力視為連續光譜而非支援 / 不支援二分，用覆蓋度、穩定性與失敗模式判讀真實可用性">Capability Spectrum</a></td>
          <td>把模型能力視為光譜、用覆蓋度與失敗模式判讀可用性</td>
      </tr>
  </tbody>
</table>
<h3 id="安全--合規">安全 / 合規</h3>
<table>
  <thead>
      <tr>
          <th>卡片</th>
          <th>核心問題</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td><a href="/blog/llm/knowledge-cards/owasp-llm-top10/" data-link-title="OWASP LLM Top 10" data-link-desc="LLM 應用最常見 10 大資安風險的業界共同詞彙、跟模組六本地 dev 視角的 mapping 表">OWASP LLM Top 10</a></td>
          <td>LLM 應用最常見 10 大資安風險、跟企業合規溝通的共同詞彙</td>
      </tr>
  </tbody>
</table>
<h3 id="tokenization">Tokenization</h3>
<table>
  <thead>
      <tr>
          <th>卡片</th>
          <th>核心問題</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td><a href="/blog/llm/knowledge-cards/bpe/" data-link-title="BPE（Byte-Pair Encoding）" data-link-desc="用「最常一起出現的字元對」合併建詞彙表的 tokenization 演算法、GPT / Llama 等主流">BPE</a></td>
          <td>用「最常字元對」合併建詞彙、GPT / Llama 主流</td>
      </tr>
      <tr>
          <td><a href="/blog/llm/knowledge-cards/wordpiece/" data-link-title="WordPiece" data-link-desc="以 likelihood improvement 選擇子詞合併的 tokenizer 演算法，BERT 系列代表性使用">WordPiece</a></td>
          <td>以 likelihood improvement 選擇子詞合併</td>
      </tr>
      <tr>
          <td><a href="/blog/llm/knowledge-cards/unigram-tokenizer/" data-link-title="Unigram Tokenizer" data-link-desc="以機率模型選擇子詞切分的 tokenizer 演算法，常見於 SentencePiece 的 unigram 模式">Unigram Tokenizer</a></td>
          <td>用機率模型選擇最可能的子詞切分</td>
      </tr>
      <tr>
          <td><a href="/blog/llm/knowledge-cards/sentencepiece/" data-link-title="SentencePiece" data-link-desc="Google 開源的多語言 tokenization 框架、支援 BPE 跟 unigram 演算法、處理空白統一">SentencePiece</a></td>
          <td>Google 開源多語言 tokenization 框架</td>
      </tr>
      <tr>
          <td><a href="/blog/llm/knowledge-cards/vocabulary-size/" data-link-title="Vocabulary Size" data-link-desc="tokenizer 詞彙表的 token 總數、影響 embedding 大小、tokenization 粒度、多語言友善度">Vocabulary Size</a></td>
          <td>詞彙表大小、影響 embedding / 多語言友善度</td>
      </tr>
      <tr>
          <td><a href="/blog/llm/knowledge-cards/special-tokens/" data-link-title="Special Tokens" data-link-desc="在 vocab 中保留給特殊用途的 token：sequence 邊界、角色標記、padding、tool call 等">Special Tokens</a></td>
          <td>邊界 / 角色 / tool call 等特殊用途 token</td>
      </tr>
  </tbody>
</table>
<h3 id="sampling-策略">Sampling 策略</h3>
<table>
  <thead>
      <tr>
          <th>卡片</th>
          <th>核心問題</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td><a href="/blog/llm/knowledge-cards/beam-search/" data-link-title="Beam Search" data-link-desc="同時保留 K 條候選 sequence 的 decoding 策略、機器翻譯主流、chat / coding 場景慎用">Beam Search</a></td>
          <td>保留 K 條候選的 decoding、translation 主流</td>
      </tr>
      <tr>
          <td><a href="/blog/llm/knowledge-cards/top-p-sampling/" data-link-title="Top-K / Top-P / Min-P Sampling" data-link-desc="從機率分佈取樣前先過濾低機率 token 的三種策略、現代 LLM 推論主流">Top-K / Top-P / Min-P</a></td>
          <td>過濾低機率 token 後取樣、現代 LLM 主流</td>
      </tr>
  </tbody>
</table>
<h3 id="推論加速進階">推論加速進階</h3>
<table>
  <thead>
      <tr>
          <th>卡片</th>
          <th>核心問題</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td><a href="/blog/llm/knowledge-cards/acceptance-rate/" data-link-title="Acceptance Rate" data-link-desc="speculative decoding 中 drafter 提出的 token 被 target model 接受的比例、決定實際加速倍率">Acceptance Rate</a></td>
          <td>speculative decoding 中 drafter 提案被接受的比例</td>
      </tr>
  </tbody>
</table>
<h3 id="評估指標--benchmark">評估指標 / Benchmark</h3>
<table>
  <thead>
      <tr>
          <th>卡片</th>
          <th>核心問題</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td><a href="/blog/llm/knowledge-cards/swe-bench/" data-link-title="SWE-bench" data-link-desc="用真實 GitHub issue 量化 LLM coding 能力的 benchmark">SWE-bench</a></td>
          <td>coding 能力如何被量化比較</td>
      </tr>
      <tr>
          <td><a href="/blog/llm/knowledge-cards/llm-benchmarks/" data-link-title="LLM Benchmarks（MMLU / HumanEval / SWE-bench 等）" data-link-desc="LLM 能力評估的標準 benchmark 集合：MMLU / HumanEval / MBPP / SWE-bench / MT-Bench 等的覆蓋範圍與失效情境">LLM Benchmarks</a></td>
          <td>MMLU / HumanEval / SWE-bench 等覆蓋範圍與失效情境</td>
      </tr>
      <tr>
          <td><a href="/blog/llm/knowledge-cards/mteb-benchmark/" data-link-title="MTEB" data-link-desc="Massive Text Embedding Benchmark：8 大類 56 任務、評估 embedding model 跨任務通用能力的標準">MTEB</a></td>
          <td>Embedding model 跨任務通用能力的標準 benchmark</td>
      </tr>
      <tr>
          <td><a href="/blog/llm/knowledge-cards/needle-in-haystack/" data-link-title="Needle in a Haystack" data-link-desc="把一個事實藏在 long context 不同位置、測試 LLM 能否抓出來的 benchmark 方法">Needle in Haystack</a></td>
          <td>把事實藏在 long context 不同位置的 retrieval 測試</td>
      </tr>
      <tr>
          <td><a href="/blog/llm/knowledge-cards/lost-in-the-middle/" data-link-title="Lost in the Middle" data-link-desc="LLM 對 long context 中段內容的 attention / recall 顯著低於開頭與結尾的現象">Lost in the Middle</a></td>
          <td>Long context 中段內容 recall 顯著降的現象</td>
      </tr>
  </tbody>
</table>
<h3 id="應用層模式">應用層模式</h3>
<table>
  <thead>
      <tr>
          <th>卡片</th>
          <th>核心問題</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td><a href="/blog/llm/knowledge-cards/rag/" data-link-title="RAG" data-link-desc="Retrieval-Augmented Generation：動態外掛知識給 LLM、繞開模型參數記憶的靜態限制">RAG</a></td>
          <td>怎麼給 LLM 動態外掛知識</td>
      </tr>
      <tr>
          <td><a href="/blog/llm/knowledge-cards/query-rewriting/" data-link-title="Query Rewriting" data-link-desc="在 RAG 檢索前改寫使用者查詢，讓 query 更接近文件語言與索引分佈">Query Rewriting</a></td>
          <td>檢索前把 query 改寫成更接近文件語言</td>
      </tr>
      <tr>
          <td><a href="/blog/llm/knowledge-cards/query-expansion/" data-link-title="Query Expansion" data-link-desc="RAG 檢索前把一個 query 擴成多個語意變體，增加 coverage，再合併 retrieval 結果">Query Expansion</a></td>
          <td>把一個 query 擴成多個語意變體再合併結果</td>
      </tr>
      <tr>
          <td><a href="/blog/llm/knowledge-cards/query-decomposition/" data-link-title="Query Decomposition" data-link-desc="把複合 query 拆成可獨立檢索的子 query，平行取得證據後再合成答案">Query Decomposition</a></td>
          <td>把複合 query 拆成可獨立檢索的子 query</td>
      </tr>
      <tr>
          <td><a href="/blog/llm/knowledge-cards/multi-step-retrieval/" data-link-title="Multi-Step Retrieval" data-link-desc="RAG 中多輪 retrieve → 判斷 → 再 retrieve 的控制流，用來處理 multi-hop 問題">Multi-Step Retrieval</a></td>
          <td>多輪 retrieve → 判斷 → 再 retrieve 的控制流</td>
      </tr>
      <tr>
          <td><a href="/blog/llm/knowledge-cards/adaptive-retrieval/" data-link-title="Adaptive Retrieval" data-link-desc="RAG 控制流中先判斷是否需要檢索，只在外部知識有價值時才 retrieve">Adaptive Retrieval</a></td>
          <td>先判斷是否需要檢索、再決定 retrieve</td>
      </tr>
      <tr>
          <td><a href="/blog/llm/knowledge-cards/context-packing/" data-link-title="Context Packing" data-link-desc="RAG retrieve 後把 chunks 去重、排序、壓縮、標來源，再塞進 prompt 的組裝決策">Context Packing</a></td>
          <td>retrieve 後把 chunks 去重、排序、壓縮、標來源再塞進 prompt</td>
      </tr>
      <tr>
          <td><a href="/blog/llm/knowledge-cards/agent/" data-link-title="LLM Agent" data-link-desc="把控制流交給 LLM 的應用模式：自主決策、跨多步呼叫工具、人類角色從主導變監督">LLM Agent</a></td>
          <td>把控制流交給 LLM 的應用模式</td>
      </tr>
      <tr>
          <td><a href="/blog/llm/knowledge-cards/agent-loop/" data-link-title="Agent Loop" data-link-desc="LLM agent 自我循環的工作流：LLM 規劃下一步、執行 tool、看結果、再規劃下一步、直到任務完成或停止條件觸發">Agent Loop</a></td>
          <td>plan → act → observe 的自我循環、injection 放大器</td>
      </tr>
      <tr>
          <td><a href="/blog/llm/knowledge-cards/context-drift/" data-link-title="Context Drift" data-link-desc="Agent 長任務中累積上下文逐步偏離原始目標，導致後續行動看似合理但整體跑偏">Context Drift</a></td>
          <td>Agent 長任務中累積 context 偏離原始目標</td>
      </tr>
      <tr>
          <td><a href="/blog/llm/knowledge-cards/goal-drift/" data-link-title="Goal Drift" data-link-desc="Agent 把子目標誤當成整體目標，提早停止或朝錯誤完成條件前進的失敗模式">Goal Drift</a></td>
          <td>Agent 把子目標誤當整體完成條件</td>
      </tr>
      <tr>
          <td><a href="/blog/llm/knowledge-cards/tool-result-misread/" data-link-title="Tool Result Misread" data-link-desc="Agent 誤讀工具輸出，把錯誤、空結果或部分成功當成成功，導致後續步驟建立在錯誤狀態上">Tool Result Misread</a></td>
          <td>Agent 誤讀工具輸出、把錯誤當成功</td>
      </tr>
      <tr>
          <td><a href="/blog/llm/knowledge-cards/tool-use/" data-link-title="Tool Use" data-link-desc="LLM 透過結構化呼叫外部工具（讀檔、查資料庫、發 API request）來擴展能力的設計、function calling 跟 MCP 是常見實作">Tool Use</a></td>
          <td>LLM 透過結構化呼叫外部工具擴展能力的設計</td>
      </tr>
      <tr>
          <td><a href="/blog/llm/knowledge-cards/function-calling/" data-link-title="Function Calling" data-link-desc="模型訓練階段建立的「呼叫工具」能力：知道何時該呼叫、傳什麼參數">Function Calling</a></td>
          <td>模型訓練建立的呼叫工具能力</td>
      </tr>
      <tr>
          <td><a href="/blog/llm/knowledge-cards/mcp/" data-link-title="MCP（Model Context Protocol）" data-link-desc="LLM application ↔ 外部 tool server 之間的標準化協議、複用 OpenAI 相容 API 的成功模式">MCP</a></td>
          <td>LLM application ↔ tool server 的標準化協議</td>
      </tr>
      <tr>
          <td><a href="/blog/llm/knowledge-cards/agent-as-tool/" data-link-title="Agent-as-Tool" data-link-desc="把一個專責 agent 包成可被另一個 agent 呼叫的 tool，形成跨 agent 的責任邊界">Agent-as-Tool</a></td>
          <td>把專責 agent 封裝成另一個 agent 可呼叫的 tool</td>
      </tr>
      <tr>
          <td><a href="/blog/llm/knowledge-cards/system-prompt/" data-link-title="System Prompt" data-link-desc="LLM application 中由開發者預設、不直接顯示給使用者的指令層、定義模型的角色、行為規範、輸出格式">System Prompt</a></td>
          <td>開發者預設、不直接顯示給使用者的指令層</td>
      </tr>
      <tr>
          <td><a href="/blog/llm/knowledge-cards/chunking/" data-link-title="Chunking" data-link-desc="把長文件切成可檢索片段的設計決策：resolution vs context loss 的本質取捨">Chunking</a></td>
          <td>把長文件切成 retrieval 片段的 resolution vs context loss 取捨</td>
      </tr>
      <tr>
          <td><a href="/blog/llm/knowledge-cards/vector-database/" data-link-title="Vector Database" data-link-desc="為高維向量 (embedding) 設計的儲存 &#43; 近似最近鄰 (ANN) 檢索系統：RAG 從 prototype 跨到 production 的關鍵元件">Vector Database</a></td>
          <td>高維向量儲存 + ANN 檢索、RAG production 的關鍵元件</td>
      </tr>
      <tr>
          <td><a href="/blog/llm/knowledge-cards/multi-agent-system/" data-link-title="Multi-agent system" data-link-desc="多個 LLM agent 協作的系統、跟 multi-call workflow 的差異在控制流跟責任邊界、三種拓樸 flat / hierarchical / agent-as-tool">Multi-agent system</a></td>
          <td>多 agent 協作系統、跟 multi-call 差在控制流跟責任邊界</td>
      </tr>
      <tr>
          <td><a href="/blog/llm/knowledge-cards/hyde/" data-link-title="HyDE（Hypothetical Document Embeddings）" data-link-desc="用 LLM 生成假設文件、對假文件做 embedding 去 retrieve、繞過 query-document gap 的 RAG 增強技術">HyDE</a></td>
          <td>用假設文件 embedding 繞過 query-document gap</td>
      </tr>
  </tbody>
</table>
<h3 id="prompt-技術">Prompt 技術</h3>
<table>
  <thead>
      <tr>
          <th>卡片</th>
          <th>核心問題</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td><a href="/blog/llm/knowledge-cards/chain-of-thought/" data-link-title="Chain-of-Thought（CoT）" data-link-desc="讓 LLM 先輸出推理步驟再給最終答案的 prompting / 訓練方式、reasoning model 的基礎機制">Chain-of-Thought</a></td>
          <td>讓 LLM 先輸出推理步驟再給最終答案</td>
      </tr>
      <tr>
          <td><a href="/blog/llm/knowledge-cards/few-shot-prompting/" data-link-title="Few-shot prompting" data-link-desc="在 prompt 內塞 input-output 範例對齊任務、不動模型權重的 in-context learning 技術">Few-shot prompting</a></td>
          <td>在 prompt 內塞範例對齊任務、跟 fine-tune 是兩個 endpoint</td>
      </tr>
      <tr>
          <td><a href="/blog/llm/knowledge-cards/instruction-following/" data-link-title="Instruction Following" data-link-desc="模型遵守任務範圍、格式、限制與停止條件的能力，是評估 instruction-tuned 模型能否落地的核心訊號">Instruction Following</a></td>
          <td>模型遵守任務範圍、格式與限制的能力</td>
      </tr>
      <tr>
          <td><a href="/blog/llm/knowledge-cards/reflection/" data-link-title="Reflection / Self-critique" data-link-desc="要求模型先輸出一版、再 critique 自己、再修改的 prompting / workflow 模式、有自身失敗模式">Reflection</a></td>
          <td>模型先生成再 critique 再修改、有 systematic error 失敗模式</td>
      </tr>
  </tbody>
</table>
<h3 id="設計典範--人機協作">設計典範 / 人機協作</h3>
<table>
  <thead>
      <tr>
          <th>卡片</th>
          <th>核心問題</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td><a href="/blog/llm/knowledge-cards/deterministic-vs-fuzzy/" data-link-title="Deterministic vs Fuzzy engineering" data-link-desc="LLM 軟體 vs 傳統軟體在資料 / 邏輯 / 行為一致性 / 實驗成本四維度的典範差異、決定哪段該包 guardrail">Deterministic vs Fuzzy engineering</a></td>
          <td>LLM 軟體 vs 傳統軟體的典範差異、決定 guardrail 設計</td>
      </tr>
      <tr>
          <td><a href="/blog/llm/knowledge-cards/guardrail/" data-link-title="Guardrail" data-link-desc="在 LLM fuzzy 行為外層加上 schema、validator、policy、human review 與 monitoring 的控制設計">Guardrail</a></td>
          <td>在 LLM fuzzy 行為外層加上可驗證控制邊界</td>
      </tr>
      <tr>
          <td><a href="/blog/llm/knowledge-cards/human-in-the-loop/" data-link-title="Human-in-the-loop（HITL）" data-link-desc="人類介入 LLM 工作流的設計：三種觸發時機（pre-act / mid-stream / post-hoc）、避免橡皮圖章化的四條件">Human-in-the-loop（HITL）</a></td>
          <td>人類介入 LLM 工作流的三時機 + 四條件</td>
      </tr>
      <tr>
          <td><a href="/blog/llm/knowledge-cards/jagged-frontier/" data-link-title="Jagged frontier" data-link-desc="AI 能力分佈不規則的 framing：某些看似簡單的任務 AI 容易壞、某些看似複雜的任務 AI 反而做得好">Jagged frontier</a></td>
          <td>AI 能力分佈不規則的 framing、「全自動」是 over-trust</td>
      </tr>
      <tr>
          <td><a href="/blog/llm/knowledge-cards/frozen-baseline/" data-link-title="Frozen baseline" data-link-desc="Eval 系統中固定特定 prompt &#43; model 當長期對照、讓行為漂移可見的標準作法">Frozen baseline</a></td>
          <td>Eval 的長期對照基準、讓行為漂移可見</td>
      </tr>
  </tbody>
</table>
<h3 id="模型行為與安全">模型行為與安全</h3>
<table>
  <thead>
      <tr>
          <th>卡片</th>
          <th>核心問題</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td><a href="/blog/llm/knowledge-cards/hallucination/" data-link-title="Hallucination" data-link-desc="LLM 生成內容看起來合理但事實錯誤、引用不存在的來源、虛構不存在的 entity 的現象">Hallucination</a></td>
          <td>LLM 生成看似合理但事實錯誤的內容</td>
      </tr>
      <tr>
          <td><a href="/blog/llm/knowledge-cards/prompt-injection/" data-link-title="Prompt Injection" data-link-desc="把惡意指令藏進 LLM 會讀到的內容、誘導 LLM 跑出非開發者預期行為的攻擊類別、OWASP LLM01 列入頭號威脅">Prompt Injection</a></td>
          <td>把惡意指令藏進 LLM 會讀到的內容、OWASP LLM01</td>
      </tr>
      <tr>
          <td><a href="/blog/llm/knowledge-cards/refusal-rate/" data-link-title="Refusal Rate" data-link-desc="LLM 拒絕回答 prompt 的比例、是 production LLM 服務偵測對齊強度跟異常行為的常用訊號">Refusal Rate</a></td>
          <td>LLM 拒絕回答的比例、production 偵測訊號</td>
      </tr>
      <tr>
          <td><a href="/blog/llm/knowledge-cards/bind-address/" data-link-title="Bind Address" data-link-desc="伺服器決定接受哪些網路介面的請求、127.0.0.1 / 0.0.0.0 / 具體 LAN IP 對應三層不同的暴露範圍">Bind Address</a></td>
          <td>推論伺服器決定接受哪些網路介面的請求</td>
      </tr>
      <tr>
          <td><a href="/blog/llm/knowledge-cards/sandbox/" data-link-title="Sandbox" data-link-desc="把程式跑在受限制環境的隔離技術、限制檔案 / 網路 / 系統呼叫權限、是 tool use 跟 MCP server 副作用控制的基礎">Sandbox</a></td>
          <td>把 tool 跟 MCP server 跑在權限受限環境的隔離技術</td>
      </tr>
      <tr>
          <td><a href="/blog/llm/knowledge-cards/model-supply-chain-trust/" data-link-title="Model Supply-Chain Trust" data-link-desc="判斷模型權重、量化版本、registry 與本機檔案是否可信的供應鏈信任框架">Model Supply-Chain Trust</a></td>
          <td>模型權重、量化版本與 registry 的信任判讀</td>
      </tr>
      <tr>
          <td><a href="/blog/llm/knowledge-cards/tool-use-permission-model/" data-link-title="Tool-Use Permission Model" data-link-desc="把 LLM tool use 的讀取、寫入、外部副作用與審查節點分級管理的權限模型">Tool-Use Permission Model</a></td>
          <td>按工具副作用範圍設計權限與審查節點</td>
      </tr>
  </tbody>
</table>
<h3 id="production-推論">Production 推論</h3>
<table>
  <thead>
      <tr>
          <th>卡片</th>
          <th>核心問題</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td><a href="/blog/llm/knowledge-cards/batching/" data-link-title="Batching" data-link-desc="多 request 一起跑、攤平 model load 成本：production LLM inference 的核心優化、決定 throughput vs latency 取捨">Batching</a></td>
          <td>多 request 一起跑、攤平 memory bandwidth 成本、throughput vs latency 取捨</td>
      </tr>
      <tr>
          <td><a href="/blog/llm/knowledge-cards/prefix-cache/" data-link-title="Prefix Cache" data-link-desc="把多個請求共用的前綴 prompt 的 KV cache 重用、省下重複 prefill 算力的優化、production 多用戶服務的常見設計">Prefix Cache</a></td>
          <td>多個請求共用前綴的 KV cache 重用優化</td>
      </tr>
      <tr>
          <td><a href="/blog/llm/knowledge-cards/moe/" data-link-title="Mixture of Experts (MoE)" data-link-desc="把 transformer 的 FFN 層拆成多個專家、每 token 只啟用少數、總參數大但每 token 計算量小的架構">MoE</a></td>
          <td>Mixture of Experts 架構、總參數大但每 token 計算量小</td>
      </tr>
      <tr>
          <td><a href="/blog/llm/knowledge-cards/active-parameter/" data-link-title="Active Parameter" data-link-desc="MoE 模型每生成一個 token 實際參與計算的參數量、跟模型總參數量不同、影響推論速度上限">Active Parameter</a></td>
          <td>MoE 每 token 實際參與計算的參數量</td>
      </tr>
      <tr>
          <td><a href="/blog/llm/knowledge-cards/moe-cpu-offload/" data-link-title="MoE CPU 卸載" data-link-desc="把 Mixture-of-Experts 模型不活躍的專家層權重放在系統 RAM、用到再走 PCIe 拉回 GPU、讓有限 VRAM 跑得了更大模型">MoE CPU 卸載</a></td>
          <td>把 MoE 不活躍專家放系統 RAM、讓有限 VRAM 跑大模型</td>
      </tr>
      <tr>
          <td><a href="/blog/llm/knowledge-cards/llama-cpp-tensor-split/" data-link-title="llama.cpp Tensor Split" data-link-desc="llama.cpp 多 GPU 場景中把模型張量按比例切到多張卡上的權重分配機制">llama.cpp Tensor Split</a></td>
          <td>多 GPU 場景把模型張量按比例切到多張卡上</td>
      </tr>
  </tbody>
</table>
<h2 id="卡片寫法">卡片寫法</h2>
<p>每張卡片維持四段：</p>
<ol>
<li><strong>核心概念</strong>：用一句話說明這個術語承擔什麼責任。</li>
<li><strong>概念位置</strong>：說明它在本地 LLM 三層架構（介面 / 伺服器 / 模型）的哪一層、跟其他概念的關係。</li>
<li><strong>可觀察訊號與例子</strong>：用真實使用情境說明這個概念何時會出現、會以什麼形式被讀者察覺。</li>
<li><strong>設計責任</strong>：使用者或工程師遇到這個概念時要做哪些判斷或設定。</li>
</ol>
<p>卡片之間互相連結，章節文章使用術語時優先連到卡片。卡片是概念索引，章節文章負責情境推導；兩者分工讓讀者可以快速查詢術語，也能完整跟著章節思考。</p>
<h2 id="卡片與章節的關係">卡片與章節的關係</h2>
<p>模組零的概念文章（<a href="/blog/llm/00-foundations/local-vs-cloud/" data-link-title="0.0 本地 vs 雲端 LLM" data-link-desc="從隱私、成本、速度、能力四個維度建立本地與雲端 LLM 的基本對照">本地 vs 雲端</a>、<a href="/blog/llm/00-foundations/why-llm-feels-slow/" data-link-title="0.1 為什麼 LLM 生字慢" data-link-desc="自回歸架構與記憶體頻寬瓶頸：為何即使 Mac 算力很強，本地 LLM 仍一個字一個字吐">為什麼 LLM 生字慢</a>、<a href="/blog/llm/00-foundations/three-layer-architecture/" data-link-title="0.2 介面 / 伺服器 / 模型三層架構" data-link-desc="把任何本地 LLM 工具放回正確的層級，用三層心智模型看懂工具關係">三層架構</a> 等）會引用大量卡片術語；模組一的實作文章（<a href="/blog/llm/01-local-llm-services/ollama/" data-link-title="1.0 Ollama：主流推論伺服器" data-link-desc="一行 brew 裝完、ollama run 一鍵跑 Gemma 4 MTP、OpenAI 相容 API on localhost:11434">Ollama 安裝</a>、<a href="/blog/llm/01-local-llm-services/model-selection-priority/" data-link-title="1.4 寫 code 場景的模型選型優先順序" data-link-desc="Gemma 4 31B MTP → Qwen3-Coder 30B → Qwen3 14B → gpt-oss 20B 的取捨與適用情境">模型選型</a> 等）也會用到同一批詞彙。卡片讓兩個模組共用詞彙、避免各自重新定義。</p>
]]></content:encoded></item><item><title>Knowledge Cards</title><link>https://tarrragon.github.io/blog/backend/knowledge-cards/</link><pubDate>Thu, 23 Apr 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/knowledge-cards/</guid><description>&lt;p>前置知識卡片的核心目標是把後端服務中的高密度術語拆成可獨立閱讀的 domain knowhow。服務選型文章會使用 broker、consumer lag、dead-letter、replay、降級、停機、readiness 等詞彙；這些詞彙背後都包含產品後果、操作責任與排障方式。&lt;/p>
&lt;p>這個模組先建立共同語言。每張卡片只處理一個知識節點，並用「概念位置、可觀察訊號、接近真實網路服務的例子、設計責任」說明它在後端系統中的角色。&lt;/p>
&lt;h2 id="術語建卡判準">術語建卡判準&lt;/h2>
&lt;p>知識卡片的建卡判準是術語是否承擔理解成本與判斷成本，核心重點在它如何影響服務理解，而非只看它是否已經在多篇文章重複出現。讀者如果缺少某個名詞的服務語意，就會難以理解服務路徑、風險邊界、artifact 欄位或下一步決策，這個名詞就值得建卡。&lt;/p>
&lt;p>適合建卡的術語通常有三個特徵：第一，它超過單純字面翻譯，並包含服務責任、操作條件或失敗代價；第二，讀者若缺少它就難以理解服務路徑、風險邊界或下一步決策，例如 validation query、rollback window、fallback read；第三，它可以被獨立說明成「概念位置、可觀察訊號、例子、設計責任」。出現頻率與是否影響實作判斷都可以當補充訊號，但不參與「是否要建卡」的必要判準。&lt;/p>
&lt;p>不適合建卡的是過度寬泛、沒有明確服務責任的詞。若名詞只是文章中的普通形容詞、單一欄位值、或只能在該句子內成立，優先在正文補清楚，不硬拆成卡片。&lt;/p>
&lt;h2 id="資料與一致性">資料與一致性&lt;/h2>
&lt;table>
 &lt;thead>
 &lt;tr>
 &lt;th>卡片&lt;/th>
 &lt;th>核心問題&lt;/th>
 &lt;th>常見出現位置&lt;/th>
 &lt;/tr>
 &lt;/thead>
 &lt;tbody>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/database/" data-link-title="Database" data-link-desc="說明 database 在後端系統中如何承擔正式狀態、查詢與一致性責任">Database&lt;/a>&lt;/td>
 &lt;td>正式狀態如何保存、查詢與保護&lt;/td>
 &lt;td>source of truth、transaction、backup&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/source-of-truth/" data-link-title="Source of Truth" data-link-desc="說明正式資料來源如何決定資料判斷、修復與一致性責任">Source of Truth&lt;/a>&lt;/td>
 &lt;td>哪個位置承擔正式資料判斷&lt;/td>
 &lt;td>database、cache、search index&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/search-index/" data-link-title="Search Index" data-link-desc="說明搜尋索引如何承擔全文檢索、排序與查詢體驗">Search Index&lt;/a>&lt;/td>
 &lt;td>搜尋體驗如何有獨立讀取模型&lt;/td>
 &lt;td>full-text、filter、ranking&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/full-text-search/" data-link-title="Full-Text Search" data-link-desc="說明全文檢索如何處理關鍵字匹配、語言分析與排序">Full-Text Search&lt;/a>&lt;/td>
 &lt;td>文本檢索如何支援關鍵字與相關性排序&lt;/td>
 &lt;td>search、documents、catalog&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/facet-query/" data-link-title="Facet Query" data-link-desc="說明分面查詢如何提供分類統計與篩選體驗">Facet Query&lt;/a>&lt;/td>
 &lt;td>搜尋結果如何提供可篩選聚合維度&lt;/td>
 &lt;td>filter、aggregation、UX&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/object-storage/" data-link-title="Object Storage" data-link-desc="說明大型非結構化檔案的保存、存取與生命週期管理">Object Storage&lt;/a>&lt;/td>
 &lt;td>大型檔案如何保存與控管生命週期&lt;/td>
 &lt;td>upload、export、backup&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/event-log/" data-link-title="Event Log" data-link-desc="說明事件歷史如何保存、重播與支援跨服務資料重建">Event Log&lt;/a>&lt;/td>
 &lt;td>歷史事件如何保存與重播&lt;/td>
 &lt;td>replay、audit、projection&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/read-model/" data-link-title="Read Model" data-link-desc="說明為查詢場景建立的讀取模型，與正式狀態的責任分離">Read Model&lt;/a>&lt;/td>
 &lt;td>查詢需求如何有獨立讀取資料形狀&lt;/td>
 &lt;td>projection、query model&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/projection/" data-link-title="Projection" data-link-desc="說明從事件流或資料變更推算出查詢用讀取視圖的轉換機制">Projection&lt;/a>&lt;/td>
 &lt;td>來源資料如何轉換成查詢視圖&lt;/td>
 &lt;td>events、materialized view&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/data-lifecycle/" data-link-title="Data Lifecycle" data-link-desc="說明資料從建立、使用、保留到刪除的責任邊界">資料生命週期&lt;/a>&lt;/td>
 &lt;td>資料如何建立、保留、封存與刪除&lt;/td>
 &lt;td>retention、audit、export&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/data-inconsistency/" data-link-title="Data Inconsistency" data-link-desc="說明多份資料暫時不同步時如何判斷產品後果與修復責任">資料不一致&lt;/a>&lt;/td>
 &lt;td>多份資料暫時不同步時如何辨識與修復&lt;/td>
 &lt;td>cache、replica、eventual consistency&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/transaction/" data-link-title="Transaction" data-link-desc="說明 transaction 如何讓一組資料變更一起成功或一起回復">Transaction&lt;/a>&lt;/td>
 &lt;td>一組資料變更如何一起成功或一起回復&lt;/td>
 &lt;td>database、commit、rollback&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/transaction-boundary/" data-link-title="Transaction Boundary" data-link-desc="說明哪些資料變更應在同一個交易中一起成功或一起回復">Transaction Boundary&lt;/a>&lt;/td>
 &lt;td>哪些變更要一起成功或回復&lt;/td>
 &lt;td>database、unit of work&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/migration/" data-link-title="Migration" data-link-desc="說明系統如何把資料、流量或結構從舊狀態移到新狀態">Migration&lt;/a>&lt;/td>
 &lt;td>系統如何從舊狀態受控移到新狀態&lt;/td>
 &lt;td>release、cutover、backfill&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/schema-migration/" data-link-title="Schema Migration" data-link-desc="說明資料庫結構如何隨應用程式版本安全演進">Schema Migration&lt;/a>&lt;/td>
 &lt;td>資料庫結構如何隨版本安全演進&lt;/td>
 &lt;td>release、rollback、migration&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/expand-contract/" data-link-title="Expand / Contract" data-link-desc="說明先擴充相容面、再收斂舊路徑的遷移做法">Expand / Contract&lt;/a>&lt;/td>
 &lt;td>先擴充相容面再收斂舊路徑的遷移做法&lt;/td>
 &lt;td>schema migration、online migration&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/migration-gate/" data-link-title="Migration Gate" data-link-desc="說明遷移流程何時可以進入下一階段或正式切換">Migration Gate&lt;/a>&lt;/td>
 &lt;td>遷移流程如何決定能否進入下一階段&lt;/td>
 &lt;td>backfill、correctness check&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/mapping-table/" data-link-title="Mapping Table" data-link-desc="說明遷移或轉換期間如何把舊語意明確對應到新語意">Mapping Table&lt;/a>&lt;/td>
 &lt;td>舊資料語意如何明確對應到新語意&lt;/td>
 &lt;td>migration、backfill、validation&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/validation-query/" data-link-title="Validation Query" data-link-desc="說明遷移、回填與修復期間如何用查詢證明資料語意是否一致">Validation Query&lt;/a>&lt;/td>
 &lt;td>查詢如何證明資料語意是否一致&lt;/td>
 &lt;td>migration、evidence package&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/read-compatibility/" data-link-title="Read Compatibility" data-link-desc="說明資料或服務演進期間讀取路徑如何同時支援新舊語意">Read Compatibility&lt;/a>&lt;/td>
 &lt;td>讀取路徑如何同時支援新舊語意&lt;/td>
 &lt;td>expand、cutover、fallback read&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/fallback-read/" data-link-title="Fallback Read" data-link-desc="說明讀取路徑切換失敗時如何暫時回到舊資料語意或舊讀取來源">Fallback Read&lt;/a>&lt;/td>
 &lt;td>切換失敗時如何暫時回到舊讀取語意&lt;/td>
 &lt;td>cutover、rollback window&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/cutover-window/" data-link-title="Cutover Window" data-link-desc="說明正式切換發生的觀察窗口、停止條件與回退判讀範圍">Cutover Window&lt;/a>&lt;/td>
 &lt;td>正式切換如何被時間窗與訊號框住&lt;/td>
 &lt;td>cutover、release gate&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/release-gate/" data-link-title="Release Gate" data-link-desc="說明變更在正式釋出前如何通過或阻擋">Release Gate&lt;/a>&lt;/td>
 &lt;td>變更如何在正式釋出前通過或阻擋&lt;/td>
 &lt;td>error budget、migration、review&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/gate-decision/" data-link-title="Gate Decision" data-link-desc="說明 release gate 如何把證據轉成放行、暫停、回退或補證據的決策">Gate Decision&lt;/a>&lt;/td>
 &lt;td>gate 如何把證據轉成下一步決策&lt;/td>
 &lt;td>release gate、rollout&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/rollback-rehearsal/" data-link-title="Rollback Rehearsal" data-link-desc="說明如何在正式事故前演練回滾流程">Rollback Rehearsal&lt;/a>&lt;/td>
 &lt;td>回滾流程如何在正式事故前演練&lt;/td>
 &lt;td>rollback strategy、migration&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/rollback-window/" data-link-title="Rollback Window" data-link-desc="說明變更進入 production 後還能用哪種方式回退或改路線的時間與條件">Rollback Window&lt;/a>&lt;/td>
 &lt;td>變更後還能用哪種方式回退或改路線&lt;/td>
 &lt;td>cutover、rollback strategy&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/rollback-condition/" data-link-title="Rollback Condition" data-link-desc="說明決策執行後出現哪些訊號時要撤回、回退或改路線">Rollback Condition&lt;/a>&lt;/td>
 &lt;td>決策後何時要撤回、回退或改路線&lt;/td>
 &lt;td>incident decision、rollback&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/fail-forward/" data-link-title="Fail-forward" data-link-desc="說明無法回到舊狀態時如何用受控前進完成修復">Fail-forward&lt;/a>&lt;/td>
 &lt;td>舊狀態已失效時如何受控前進修復&lt;/td>
 &lt;td>rollback window、incident decision&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/stop-condition/" data-link-title="Stop Condition" data-link-desc="說明變更、實驗或事故處理何時必須暫停、回退或改路線">Stop Condition&lt;/a>&lt;/td>
 &lt;td>何時必須暫停、回退或改路線&lt;/td>
 &lt;td>release gate、incident decision&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/isolation-level/" data-link-title="Isolation Level" data-link-desc="說明資料庫交易隔離級別如何影響並發讀寫結果">Isolation Level&lt;/a>&lt;/td>
 &lt;td>並發交易彼此看見哪些資料&lt;/td>
 &lt;td>transaction、lock、retry&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/connection-pool/" data-link-title="Connection Pool" data-link-desc="說明連線池如何限制下游資源並影響服務容量">Connection Pool&lt;/a>&lt;/td>
 &lt;td>application 如何限制下游連線壓力&lt;/td>
 &lt;td>database、Redis、broker&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/database-sharding/" data-link-title="Database Sharding" data-link-desc="說明資料庫如何依 shard key 分散資料、路由請求與承擔跨 shard 查詢成本">Database Sharding&lt;/a>&lt;/td>
 &lt;td>資料庫如何依 shard key 分散與路由&lt;/td>
 &lt;td>Vitess、Citus、tenant key&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/write-ahead-log/" data-link-title="Write-Ahead Log" data-link-desc="說明資料庫如何先寫入 log 再合併回主資料，以提供持久性與崩潰復原">Write-Ahead Log&lt;/a>&lt;/td>
 &lt;td>寫入如何先記 log 再合併以支援復原&lt;/td>
 &lt;td>WAL、checkpoint、recovery&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/single-writer-model/" data-link-title="Single Writer Model" data-link-desc="說明單寫者模型如何序列化寫入，並成為系統的容量邊界">Single Writer Model&lt;/a>&lt;/td>
 &lt;td>寫入如何被序列化成單一路徑&lt;/td>
 &lt;td>SQLite、primary lease、容量上限&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/embedded-database/" data-link-title="Embedded Database" data-link-desc="說明嵌入式資料庫如何隨 application process 運作，並把檔案生命週期責任交回應用">Embedded Database&lt;/a>&lt;/td>
 &lt;td>資料庫如何隨 application process 運作&lt;/td>
 &lt;td>SQLite、檔案生命週期、本地儲存&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/metadata-lock/" data-link-title="Metadata Lock" data-link-desc="說明 DDL 與既有交易如何在 table metadata 層互相排隊與阻塞">Metadata Lock&lt;/a>&lt;/td>
 &lt;td>DDL 與既有交易如何在 schema 層互相阻塞&lt;/td>
 &lt;td>ALTER、長交易、DDL window&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/table-partitioning/" data-link-title="Table Partitioning" data-link-desc="說明單一資料庫內如何把大表拆成多個分區，並由查詢規劃器只掃相關片段">Table Partitioning&lt;/a>&lt;/td>
 &lt;td>大表如何在單庫內拆成多個分區&lt;/td>
 &lt;td>range/list/hash、pruning、retention&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/read-write-split/" data-link-title="Read-Write Split" data-link-desc="說明讀寫流量如何分流到 primary 與 replica，以及它引入的一致性責任">Read-Write Split&lt;/a>&lt;/td>
 &lt;td>讀寫流量如何分流到 primary 與 replica&lt;/td>
 &lt;td>proxy、replica lag、read-after-write&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/transaction-pooling/" data-link-title="Transaction Pooling" data-link-desc="說明 connection pooler 的 transaction 綁定模式如何壓縮連線並改變 session 語意">Transaction Pooling&lt;/a>&lt;/td>
 &lt;td>連線如何只綁定單一 transaction&lt;/td>
 &lt;td>pooler、session state、SET LOCAL&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/document-store/" data-link-title="Document Store" data-link-desc="說明以 JSON 文件與彈性 schema 提供資料存取的模式，以及它仍需的治理邊界">Document Store&lt;/a>&lt;/td>
 &lt;td>資料如何以 JSON 文件與彈性 schema 存取&lt;/td>
 &lt;td>JSON、巢狀結構、index&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/local-first/" data-link-title="Local-First" data-link-desc="說明本機優先的資料架構如何讓離線可用，並把同步當成獨立問題">Local-First&lt;/a>&lt;/td>
 &lt;td>資料如何本機優先並離線可用&lt;/td>
 &lt;td>離線、多端同步、行動 app&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/read-after-write/" data-link-title="Read-After-Write Consistency" data-link-desc="說明寫入後能否立即讀到該筆寫入的一致性保證">Read-After-Write Consistency&lt;/a>&lt;/td>
 &lt;td>寫入後能否立即讀到該筆寫入&lt;/td>
 &lt;td>primary、lag guard、session&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/type-affinity/" data-link-title="Type Affinity" data-link-desc="說明 SQLite 如何用 type affinity 決定欄位的型別傾向與值的儲存方式">Type Affinity&lt;/a>&lt;/td>
 &lt;td>SQLite 欄位型別如何是傾向而非硬約束&lt;/td>
 &lt;td>SQLite、storage class、STRICT&lt;/td>
 &lt;/tr>
 &lt;/tbody>
&lt;/table>
&lt;h2 id="快取與流量">快取與流量&lt;/h2>
&lt;table>
 &lt;thead>
 &lt;tr>
 &lt;th>卡片&lt;/th>
 &lt;th>核心問題&lt;/th>
 &lt;th>常見出現位置&lt;/th>
 &lt;/tr>
 &lt;/thead>
 &lt;tbody>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/timeout/" data-link-title="Timeout" data-link-desc="說明等待外部操作的時間上限如何保護資源與使用者體驗">Timeout&lt;/a>&lt;/td>
 &lt;td>單一步驟最久可以等待多久&lt;/td>
 &lt;td>API、database、broker&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/deadline/" data-link-title="Deadline" data-link-desc="說明整體操作的截止時間如何沿著服務邊界傳遞">Deadline&lt;/a>&lt;/td>
 &lt;td>整體操作何時必須完成&lt;/td>
 &lt;td>request、job、workflow&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/exponential-backoff/" data-link-title="Exponential Backoff" data-link-desc="說明重試間隔如何逐步拉長以降低下游壓力">Exponential Backoff&lt;/a>&lt;/td>
 &lt;td>重試間隔如何逐步拉長&lt;/td>
 &lt;td>retry、API、worker&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/jitter/" data-link-title="Jitter" data-link-desc="說明重試或排程加入隨機偏移如何降低同步尖峰">Jitter&lt;/a>&lt;/td>
 &lt;td>如何分散同步重試與排程尖峰&lt;/td>
 &lt;td>retry、TTL、reconnect&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/retry-storm/" data-link-title="Retry Storm" data-link-desc="說明大量重試如何把局部故障放大成系統壓力">Retry Storm&lt;/a>&lt;/td>
 &lt;td>大量重試如何放大下游壓力&lt;/td>
 &lt;td>timeout、dependency failure&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/thundering-herd/" data-link-title="Thundering Herd" data-link-desc="說明大量工作同時被喚醒或同時競爭資源時的尖峰風險">Thundering Herd&lt;/a>&lt;/td>
 &lt;td>大量工作同時醒來如何形成尖峰&lt;/td>
 &lt;td>reconnect、cache、lock&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/transient-failure/" data-link-title="Transient Failure" data-link-desc="說明暫時性故障如何影響重試、告警與使用者回應">Transient Failure&lt;/a>&lt;/td>
 &lt;td>暫時性故障如何影響重試與告警&lt;/td>
 &lt;td>network、failover、timeout&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/partial-failure/" data-link-title="Partial Failure" data-link-desc="說明分散式系統中部分依賴失效時如何保留整體可用性">Partial Failure&lt;/a>&lt;/td>
 &lt;td>局部失效時如何保留整體可用性&lt;/td>
 &lt;td>distributed system、fallback&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/cascading-failure/" data-link-title="Cascading Failure" data-link-desc="說明局部故障如何透過等待、重試與資源耗盡擴散到整個系統">Cascading Failure&lt;/a>&lt;/td>
 &lt;td>局部故障如何擴散成整體故障&lt;/td>
 &lt;td>dependency、retry、pool&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/load-shedding/" data-link-title="Load Shedding" data-link-desc="說明服務過載時如何主動拒絕低優先工作以保護核心能力">Load Shedding&lt;/a>&lt;/td>
 &lt;td>過載時如何主動拒絕低優先工作&lt;/td>
 &lt;td>overload、priority&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/token-bucket/" data-link-title="Token Bucket" data-link-desc="說明 token bucket 如何用配額與補充速率控制流量">Token Bucket&lt;/a>&lt;/td>
 &lt;td>如何用配額與補充速率控制流量&lt;/td>
 &lt;td>rate limit、retry budget&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/dependency-isolation/" data-link-title="Dependency Isolation" data-link-desc="說明如何隔離下游依賴，避免單一依賴耗盡共享資源">Dependency Isolation&lt;/a>&lt;/td>
 &lt;td>如何避免單一下游耗盡共享資源&lt;/td>
 &lt;td>pool、queue、dependency&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/bulkhead/" data-link-title="Bulkhead" data-link-desc="說明 bulkhead 如何用資源分艙限制故障擴散">Bulkhead&lt;/a>&lt;/td>
 &lt;td>如何用資源分艙限制故障擴散&lt;/td>
 &lt;td>worker、tenant、pool&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/in-process-channel/" data-link-title="In-Process Channel" data-link-desc="說明單一 process 內用來傳遞工作的 channel 或 queue abstraction">In-Process Channel&lt;/a>&lt;/td>
 &lt;td>單一 process 內如何傳遞工作或訊號&lt;/td>
 &lt;td>channel、local queue&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/local-worker/" data-link-title="Local Worker" data-link-desc="說明同一個 process 內的背景工作模型與其生命週期邊界">Local Worker&lt;/a>&lt;/td>
 &lt;td>同 process 背景工作的責任與邊界&lt;/td>
 &lt;td>background task、shutdown&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/worker-pool/" data-link-title="Worker Pool" data-link-desc="說明一組 worker 如何限制同時處理量並保護下游資源">Worker Pool&lt;/a>&lt;/td>
 &lt;td>如何限制同時處理量&lt;/td>
 &lt;td>worker、background job&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/http-client/" data-link-title="HTTP Client" data-link-desc="說明服務呼叫外部 HTTP 依賴時需要管理 timeout、連線與重試">HTTP Client&lt;/a>&lt;/td>
 &lt;td>呼叫外部 HTTP 依賴時如何管理資源&lt;/td>
 &lt;td>API、dependency&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/webhook/" data-link-title="Webhook" data-link-desc="說明外部系統回呼事件的接收、驗證與處理邊界">Webhook&lt;/a>&lt;/td>
 &lt;td>外部系統回呼事件如何驗證與處理&lt;/td>
 &lt;td>callback、signature、retry&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/websocket/" data-link-title="WebSocket" data-link-desc="說明 WebSocket 如何提供長連線雙向即時通訊">WebSocket&lt;/a>&lt;/td>
 &lt;td>長連線雙向即時通訊如何運作&lt;/td>
 &lt;td>chat、presence、push&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/sse/" data-link-title="Server-Sent Events (SSE)" data-link-desc="說明 SSE 如何透過 HTTP 長連線向 client 單向推送事件">Server-Sent Events (SSE)&lt;/a>&lt;/td>
 &lt;td>HTTP 單向事件串流如何推送更新&lt;/td>
 &lt;td>notification、progress&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/stream-pipeline/" data-link-title="Stream Pipeline" data-link-desc="說明連續資料流經多個處理階段時如何管理吞吐、順序與 backpressure ">Stream Pipeline&lt;/a>&lt;/td>
 &lt;td>連續資料流如何管理吞吐與 backpressure&lt;/td>
 &lt;td>stream、CDC、ETL&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/throughput/" data-link-title="Throughput" data-link-desc="整理系統單位時間內可處理的工作量">Throughput&lt;/a>&lt;/td>
 &lt;td>單位時間內可處理多少工作&lt;/td>
 &lt;td>load test、queue、broker&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/buffer/" data-link-title="Buffer" data-link-desc="說明系統如何用暫存空間吸收短暫速度差與尖峰流量">Buffer&lt;/a>&lt;/td>
 &lt;td>暫存空間如何吸收短暫速度差&lt;/td>
 &lt;td>queue、socket、cache&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/queue/" data-link-title="Queue" data-link-desc="說明 queue 如何保存等待處理的工作並形成容量邊界">Queue&lt;/a>&lt;/td>
 &lt;td>等待處理的工作如何形成容量邊界&lt;/td>
 &lt;td>producer、consumer、backlog&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/socket/" data-link-title="Socket" data-link-desc="說明 network socket 如何成為 application 與網路之間的資料傳輸邊界">Socket&lt;/a>&lt;/td>
 &lt;td>網路連線如何成為資料讀寫與資源邊界&lt;/td>
 &lt;td>network、connection、timeout&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/fallback/" data-link-title="Fallback" data-link-desc="說明主要路徑失敗時使用替代結果或替代流程的設計責任">Fallback&lt;/a>&lt;/td>
 &lt;td>主要路徑失敗時使用什麼替代結果&lt;/td>
 &lt;td>degradation、circuit breaker&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/fail-fast/" data-link-title="Fail Fast" data-link-desc="說明已知無法完成時快速回應如何保護資源與上游判斷">Fail Fast&lt;/a>&lt;/td>
 &lt;td>已知會失敗時如何快速回應&lt;/td>
 &lt;td>circuit breaker、validation&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/retry-budget/" data-link-title="Retry Budget" data-link-desc="說明重試次數如何受整體容量與錯誤預算限制">Retry Budget&lt;/a>&lt;/td>
 &lt;td>重試量如何受整體容量限制&lt;/td>
 &lt;td>retry、SLO、token bucket&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/cache-aside/" data-link-title="Cache Aside" data-link-desc="說明 application 如何在讀取時自行管理快取與正式資料來源">Cache Aside&lt;/a>&lt;/td>
 &lt;td>application 如何讀快取與正式來源&lt;/td>
 &lt;td>Redis、read path&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/cache-hit-miss/" data-link-title="Cache Hit / Miss" data-link-desc="說明快取命中與未命中如何影響讀取成本與下游壓力">Cache Hit / Miss&lt;/a>&lt;/td>
 &lt;td>讀取是否命中快取&lt;/td>
 &lt;td>cache、database pressure&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/cache-hit-rate/" data-link-title="Cache Hit Rate" data-link-desc="說明快取命中比例如何衡量加速效果與下游保護">Cache Hit Rate&lt;/a>&lt;/td>
 &lt;td>命中比例如何衡量快取效益&lt;/td>
 &lt;td>dashboard、capacity&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/cache-warmup/" data-link-title="Cache Warmup" data-link-desc="說明服務啟動或活動前如何預先建立快取資料">Cache Warmup&lt;/a>&lt;/td>
 &lt;td>正式流量前如何預先載入快取&lt;/td>
 &lt;td>deployment、event&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/cache-prefetching/" data-link-title="Cache Prefetching" data-link-desc="說明系統如何在資料被需要前預先載入快取">Cache Prefetching&lt;/a>&lt;/td>
 &lt;td>如何在資料被需要前預先載入&lt;/td>
 &lt;td>user flow、hot data&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/cold-start/" data-link-title="Cold Start" data-link-desc="說明服務或快取剛啟動時尚未累積狀態造成的延遲與壓力">Cold Start&lt;/a>&lt;/td>
 &lt;td>新 instance 或空快取如何造成延遲&lt;/td>
 &lt;td>autoscaling、readiness&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/write-through-cache/" data-link-title="Write-Through Cache" data-link-desc="說明寫入時同步更新快取與正式來源的策略">Write-Through Cache&lt;/a>&lt;/td>
 &lt;td>寫入時如何同步更新快取&lt;/td>
 &lt;td>write path、freshness&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/write-behind-cache/" data-link-title="Write-Behind Cache" data-link-desc="說明先寫快取再非同步寫入正式來源的風險與用途">Write-Behind Cache&lt;/a>&lt;/td>
 &lt;td>先寫緩衝層再非同步持久化的風險&lt;/td>
 &lt;td>analytics、buffer&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/stale-data/" data-link-title="Stale Data" data-link-desc="說明過期資料在快取、replica 與衍生資料中的產品影響">Stale Data&lt;/a>&lt;/td>
 &lt;td>過期資料如何影響產品結果&lt;/td>
 &lt;td>cache、replica&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/soft-ttl/" data-link-title="Soft TTL" data-link-desc="說明資料進入刷新期後仍可短暫使用以降低 stampede">Soft TTL&lt;/a>&lt;/td>
 &lt;td>進入刷新期後如何短暫使用舊資料&lt;/td>
 &lt;td>stampede、refresh&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/singleflight/" data-link-title="Singleflight" data-link-desc="說明相同工作同時發生時如何合併成一次下游請求">Singleflight&lt;/a>&lt;/td>
 &lt;td>相同工作如何合併成一次下游請求&lt;/td>
 &lt;td>cache miss、hot key&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/ttl/" data-link-title="TTL" data-link-desc="說明資料過期時間如何影響快取新鮮度、成本與一致性">TTL&lt;/a>&lt;/td>
 &lt;td>資料何時自動過期&lt;/td>
 &lt;td>cache、session、presence&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/eviction/" data-link-title="Eviction" data-link-desc="說明快取容量不足時哪些資料會被淘汰，以及淘汰如何影響服務">Eviction&lt;/a>&lt;/td>
 &lt;td>容量不足時哪些資料會被淘汰&lt;/td>
 &lt;td>Redis、local cache、CDN&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/cache-invalidation/" data-link-title="Cache Invalidation" data-link-desc="說明快取資料何時更新、刪除或重建，以及失效策略如何影響一致性">快取失效策略&lt;/a>&lt;/td>
 &lt;td>快取資料何時更新、刪除或重建&lt;/td>
 &lt;td>Redis、CDN、多層快取&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/hot-key/" data-link-title="Hot Key" data-link-desc="說明單一 key 承受大量讀寫時如何形成容量瓶頸">Hot Key&lt;/a>&lt;/td>
 &lt;td>少數 key 如何形成容量瓶頸&lt;/td>
 &lt;td>Redis、partition、counter&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/cache-stampede/" data-link-title="Cache Stampede" data-link-desc="說明快取同時失效時大量 request 如何壓垮正式來源">Cache Stampede&lt;/a>&lt;/td>
 &lt;td>快取同時 miss 如何壓垮正式來源&lt;/td>
 &lt;td>hot key、TTL、database&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/rate-limit/" data-link-title="Rate Limit" data-link-desc="說明限流如何保護服務入口、下游依賴與租戶公平性">Rate Limit&lt;/a>&lt;/td>
 &lt;td>如何限制主體在一段時間內的資源使用量&lt;/td>
 &lt;td>API、tenant、worker&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/backpressure/" data-link-title="Backpressure" data-link-desc="說明下游處理速度不足時系統如何讓上游依下游能力送出工作">Backpressure&lt;/a>&lt;/td>
 &lt;td>下游變慢時如何讓上游放慢&lt;/td>
 &lt;td>queue、worker、stream&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/buffer-pool/" data-link-title="Buffer Pool" data-link-desc="說明資料庫如何用記憶體快取磁碟頁，以降低 I/O 並影響查詢效能">Buffer Pool&lt;/a>&lt;/td>
 &lt;td>資料庫如何用記憶體快取磁碟頁&lt;/td>
 &lt;td>InnoDB、shared buffers、命中率&lt;/td>
 &lt;/tr>
 &lt;/tbody>
&lt;/table>
&lt;h2 id="入口與部署">入口與部署&lt;/h2>
&lt;table>
 &lt;thead>
 &lt;tr>
 &lt;th>卡片&lt;/th>
 &lt;th>核心問題&lt;/th>
 &lt;th>常見出現位置&lt;/th>
 &lt;/tr>
 &lt;/thead>
 &lt;tbody>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/endpoint/" data-link-title="Service Endpoint" data-link-desc="說明服務如何對外暴露可被路由與存取的入口">Service Endpoint&lt;/a>&lt;/td>
 &lt;td>服務入口如何被路由與存取&lt;/td>
 &lt;td>API、service discovery、internal&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/public-api-endpoint/" data-link-title="Public API Endpoint" data-link-desc="說明面向外部 client 的穩定 API 入口如何被管理">Public API Endpoint&lt;/a>&lt;/td>
 &lt;td>面向 client 的穩定對外入口&lt;/td>
 &lt;td>product API、SDK、client&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/api-gateway/" data-link-title="API Gateway" data-link-desc="說明外部流量如何先收斂到一層可集中控制的入口">API Gateway&lt;/a>&lt;/td>
 &lt;td>外部流量如何集中路由、驗證與轉發&lt;/td>
 &lt;td>auth、rate limit、routing、request id&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/request-routing/" data-link-title="Request Routing" data-link-desc="說明入口流量如何依規則被導向不同服務或處理路徑">Request Routing&lt;/a>&lt;/td>
 &lt;td>入口流量如何分派到不同服務或版本&lt;/td>
 &lt;td>host、path、tenant、version&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/admin-endpoint/" data-link-title="Admin Endpoint" data-link-desc="說明管理入口如何承擔高權限操作與稽核責任">Admin Endpoint&lt;/a>&lt;/td>
 &lt;td>高權限管理入口如何被隔離與稽核&lt;/td>
 &lt;td>admin、backoffice、control plane&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/diagnostic-endpoint/" data-link-title="Diagnostic Endpoint" data-link-desc="說明健康檢查、診斷與調試入口如何控制暴露面">Diagnostic Endpoint&lt;/a>&lt;/td>
 &lt;td>health、readiness 與 debug 入口&lt;/td>
 &lt;td>liveness、probe、metrics snapshot&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/internal-endpoint/" data-link-title="Internal Endpoint" data-link-desc="說明服務內部通訊入口如何配合網路邊界與服務發現">Internal Endpoint&lt;/a>&lt;/td>
 &lt;td>服務內部通訊入口如何受控&lt;/td>
 &lt;td>service-to-service、control plane&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/container/" data-link-title="Container" data-link-desc="說明容器如何包裝服務、隔離依賴與影響部署方式">Container&lt;/a>&lt;/td>
 &lt;td>服務如何被包裝成可交付單位&lt;/td>
 &lt;td>image、runtime、CI、Kubernetes&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/load-balancer/" data-link-title="Load Balancer" data-link-desc="說明流量如何分散、排空與導向健康節點">Load Balancer&lt;/a>&lt;/td>
 &lt;td>流量如何分散、排空與導向健康節點&lt;/td>
 &lt;td>ingress、draining、rolling update&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/draining/" data-link-title="Draining" data-link-desc="說明服務如何先停止接收新流量，再讓既有工作完成">Draining&lt;/a>&lt;/td>
 &lt;td>服務如何先停新流量再完成既有工作&lt;/td>
 &lt;td>rolling update、shutdown、cutover&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/sticky-session/" data-link-title="Sticky Session" data-link-desc="說明同一 client 如何在一段時間內持續命中同一個後端實例">Sticky Session&lt;/a>&lt;/td>
 &lt;td>同一 client 如何維持命中同一實例&lt;/td>
 &lt;td>session affinity、load balancer&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/idle-timeout/" data-link-title="Idle Timeout" data-link-desc="說明連線或會話在多久沒有活動後應該被回收">Idle Timeout&lt;/a>&lt;/td>
 &lt;td>連線或會話多久沒活動後要回收&lt;/td>
 &lt;td>socket、load balancer、proxy&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/health-check/" data-link-title="Health Check" data-link-desc="說明服務如何對外提供可供平台判斷狀態的健康回應">Health Check&lt;/a>&lt;/td>
 &lt;td>平台如何快速判斷服務狀態&lt;/td>
 &lt;td>load balancer、probe、diagnostic&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/resource-limit/" data-link-title="Resource Limit" data-link-desc="說明服務可使用的 CPU、memory 與相關資源上限如何影響行為">Resource Limit&lt;/a>&lt;/td>
 &lt;td>服務可用的 CPU / memory 上限如何影響行為&lt;/td>
 &lt;td>container、scheduler、runtime&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/probe/" data-link-title="Probe" data-link-desc="說明平台如何透過 probe 判斷服務狀態與接流量條件">Probe&lt;/a>&lt;/td>
 &lt;td>平台如何判斷存活與接流量條件&lt;/td>
 &lt;td>readiness、liveness、startup&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/config-rollout/" data-link-title="Config Rollout" data-link-desc="說明設定如何安全下發到正在運作的服務實例">Config Rollout&lt;/a>&lt;/td>
 &lt;td>設定如何安全下發到運作中的服務實例&lt;/td>
 &lt;td>feature flag、secret、runtime config&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/runtime-config/" data-link-title="Runtime Config" data-link-desc="說明服務在啟動與執行時如何讀取與組合設定">Runtime Config&lt;/a>&lt;/td>
 &lt;td>執行時設定如何被讀取、組合與覆寫&lt;/td>
 &lt;td>env var、secret、feature flag&lt;/td>
 &lt;/tr>
 &lt;/tbody>
&lt;/table>
&lt;h2 id="通訊協定">通訊協定&lt;/h2>
&lt;table>
 &lt;thead>
 &lt;tr>
 &lt;th>卡片&lt;/th>
 &lt;th>核心問題&lt;/th>
 &lt;th>常見出現位置&lt;/th>
 &lt;/tr>
 &lt;/thead>
 &lt;tbody>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/protocol/" data-link-title="Communication Protocol" data-link-desc="說明不同系統如何對齊資料交換與錯誤語意">Communication Protocol&lt;/a>&lt;/td>
 &lt;td>不同系統如何對齊資料交換與錯誤語意&lt;/td>
 &lt;td>request/response、message、webhook&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/request-response-protocol/" data-link-title="Request/Response Protocol" data-link-desc="說明同步請求如何在 client 與 service 之間對齊互動規則">Request/Response Protocol&lt;/a>&lt;/td>
 &lt;td>同步呼叫如何對齊互動規則&lt;/td>
 &lt;td>HTTP API、gRPC、RPC&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/message-protocol/" data-link-title="Message Protocol" data-link-desc="說明 queue 或 stream message 如何對齊格式與處理語意">Message Protocol&lt;/a>&lt;/td>
 &lt;td>queue / stream 訊息如何對齊格式與語意&lt;/td>
 &lt;td>event、job、delivery&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/webhook-protocol/" data-link-title="Webhook Protocol" data-link-desc="說明外部回呼如何對齊簽章、重試與 payload 語意">Webhook Protocol&lt;/a>&lt;/td>
 &lt;td>外部回呼如何對齊簽章與 payload&lt;/td>
 &lt;td>callback、signature、retry&lt;/td>
 &lt;/tr>
 &lt;/tbody>
&lt;/table>
&lt;h2 id="邊界與治理">邊界與治理&lt;/h2>
&lt;table>
 &lt;thead>
 &lt;tr>
 &lt;th>卡片&lt;/th>
 &lt;th>核心問題&lt;/th>
 &lt;th>常見出現位置&lt;/th>
 &lt;/tr>
 &lt;/thead>
 &lt;tbody>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/contract/" data-link-title="Boundary Contract" data-link-desc="說明跨邊界約定如何維持相容與可驗證">Boundary Contract&lt;/a>&lt;/td>
 &lt;td>邊界兩端如何維持一致約定&lt;/td>
 &lt;td>API contract、deployment contract、queue contract、load balancer contract&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/api-contract/" data-link-title="API Contract" data-link-desc="說明 request / response 邊界如何維持相容與可驗證">API Contract&lt;/a>&lt;/td>
 &lt;td>request / response 如何維持相容&lt;/td>
 &lt;td>client、SDK、public API&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/deployment-contract/" data-link-title="Deployment Contract" data-link-desc="說明服務與部署平台之間的生命週期約定">Deployment Contract&lt;/a>&lt;/td>
 &lt;td>application 與 platform 如何對齊生命週期&lt;/td>
 &lt;td>readiness、shutdown、rollout&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/queue-contract/" data-link-title="Queue Contract" data-link-desc="說明佇列工作在重試、確認與重複投遞上的約定">Queue Contract&lt;/a>&lt;/td>
 &lt;td>producer / broker / consumer 如何對齊交付語意&lt;/td>
 &lt;td>ack、retry、DLQ、redelivery&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/load-balancer-contract/" data-link-title="Load Balancer Contract" data-link-desc="說明服務與負載平衡器之間的流量與健康檢查約定">Load Balancer Contract&lt;/a>&lt;/td>
 &lt;td>服務與流量入口如何對齊健康與切流&lt;/td>
 &lt;td>health check、draining、idle timeout&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/adapter/" data-link-title="Integration Adapter" data-link-desc="說明外部系統接入層如何轉換介面與隔離差異">Integration Adapter&lt;/a>&lt;/td>
 &lt;td>外部系統如何轉成內部需要的形狀&lt;/td>
 &lt;td>repository、payment、notification&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/repository-adapter/" data-link-title="Repository Adapter" data-link-desc="說明持久化層如何把資料模型轉成外部儲存介面">Repository Adapter&lt;/a>&lt;/td>
 &lt;td>持久化存取如何對齊應用模型&lt;/td>
 &lt;td>SQL、transaction、row mapping&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/provider-adapter/" data-link-title="Provider Adapter" data-link-desc="說明第三方服務如何被包裝成內部穩定介面">Provider Adapter&lt;/a>&lt;/td>
 &lt;td>第三方服務如何被包裝成穩定介面&lt;/td>
 &lt;td>payment、email、SMS、storage&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/notification-adapter/" data-link-title="Notification Adapter" data-link-desc="說明通知通道如何把 domain event 轉成外部傳遞格式">Notification Adapter&lt;/a>&lt;/td>
 &lt;td>通知通道如何轉成外部發送格式&lt;/td>
 &lt;td>email、push、webhook&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/middleware/" data-link-title="Request Middleware" data-link-desc="說明請求處理鏈中的共通攔截與前後置處理">Request Middleware&lt;/a>&lt;/td>
 &lt;td>共通請求處理如何放在邊界上&lt;/td>
 &lt;td>auth、logging、tracing、validation&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/authentication-middleware/" data-link-title="Authentication Middleware" data-link-desc="說明請求進入 handler 前如何完成身份驗證">Authentication Middleware&lt;/a>&lt;/td>
 &lt;td>請求進入前如何驗證身份&lt;/td>
 &lt;td>token、session、signature&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/authorization-middleware/" data-link-title="Authorization Middleware" data-link-desc="說明請求進入 handler 前如何完成權限判斷">Authorization Middleware&lt;/a>&lt;/td>
 &lt;td>請求進入前如何判斷權限&lt;/td>
 &lt;td>role、tenant、resource owner&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/observability-middleware/" data-link-title="Observability Middleware" data-link-desc="說明請求進入 handler 前後如何補上觀測欄位">Observability Middleware&lt;/a>&lt;/td>
 &lt;td>請求如何補上觀測欄位&lt;/td>
 &lt;td>request id、trace context&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/security-middleware/" data-link-title="Security Middleware" data-link-desc="說明請求進入 handler 前如何完成共通安全控制">Security Middleware&lt;/a>&lt;/td>
 &lt;td>請求如何套用共通安全控制&lt;/td>
 &lt;td>rate limit、redaction&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/validation-middleware/" data-link-title="Validation Middleware" data-link-desc="說明請求進入 handler 前如何完成共通驗證">Validation Middleware&lt;/a>&lt;/td>
 &lt;td>請求如何先做共通驗證&lt;/td>
 &lt;td>schema、header、payload shape&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/vendor-lock-in/" data-link-title="Vendor Lock-In" data-link-desc="說明採用供應商產品後，其 API 與格式滲入程式碼造成的退出成本">Vendor Lock-In&lt;/a>&lt;/td>
 &lt;td>供應商 API 滲入程式碼如何造成退出成本&lt;/td>
 &lt;td>adapter、exit route、選型&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/capability-outsourcing-depth/" data-link-title="Capability Outsourcing Depth（外包深度）" data-link-desc="說明外包一塊後端能力有三種深度（managed 基礎設施、feature SaaS、BaaS bundle）、深度決定保留多少控制權與遷出代價">Capability Outsourcing Depth&lt;/a>&lt;/td>
 &lt;td>外包一塊能力的三種深度如何決定控制權與遷出代價&lt;/td>
 &lt;td>managed 基礎設施、feature SaaS、BaaS bundle&lt;/td>
 &lt;/tr>
 &lt;/tbody>
&lt;/table>
&lt;h2 id="訊息與事件">訊息與事件&lt;/h2>
&lt;table>
 &lt;thead>
 &lt;tr>
 &lt;th>卡片&lt;/th>
 &lt;th>核心問題&lt;/th>
 &lt;th>常見出現位置&lt;/th>
 &lt;/tr>
 &lt;/thead>
 &lt;tbody>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/broker/" data-link-title="Broker" data-link-desc="說明 broker 在訊息傳遞系統中負責保存、路由與交付訊息">Broker&lt;/a>&lt;/td>
 &lt;td>訊息離開單一 process 後由誰保存、路由與交付&lt;/td>
 &lt;td>queue、event、worker、stream&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/topic/" data-link-title="Topic" data-link-desc="說明 topic 如何把事件依主題分流給不同訂閱者">Topic&lt;/a>&lt;/td>
 &lt;td>事件如何依主題分流給不同訂閱者&lt;/td>
 &lt;td>broker、event、stream&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/pub-sub/" data-link-title="Pub/Sub" data-link-desc="說明 publish-subscribe 如何把事件即時分發給多個訂閱者">Pub/Sub&lt;/a>&lt;/td>
 &lt;td>訊息如何即時分發給多個訂閱者&lt;/td>
 &lt;td>realtime、notification、broadcast&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/fan-out/" data-link-title="Fan-out" data-link-desc="說明單一事件同時分發給多個下游的訊息拓撲">Fan-out&lt;/a>&lt;/td>
 &lt;td>單一事件如何同時送到多個下游&lt;/td>
 &lt;td>topic、subscription、event flow&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/durable-queue/" data-link-title="Durable Queue" data-link-desc="說明可持久化的 queue 如何在重啟與失敗後保留待處理工作">Durable Queue&lt;/a>&lt;/td>
 &lt;td>工作如何在故障後仍可被處理&lt;/td>
 &lt;td>persistence、ack/nack、retry&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/reliability-boundary/" data-link-title="Reliability Boundary" data-link-desc="說明系統在哪個邊界內承諾可靠傳遞，邊界外需要哪些補償機制">Reliability Boundary&lt;/a>&lt;/td>
 &lt;td>系統在哪些邊界內承諾可恢復傳遞&lt;/td>
 &lt;td>request、process、service boundary&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/offline-catchup/" data-link-title="Offline Catch-up" data-link-desc="說明訂閱者離線後如何補回缺失事件或狀態">Offline Catch-up&lt;/a>&lt;/td>
 &lt;td>離線期間漏失事件如何補齊&lt;/td>
 &lt;td>websocket、sync、reconnect&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/strong-reliability/" data-link-title="Strong Reliability" data-link-desc="說明高可靠事件路徑需要的保存、重試、去重與回復責任">Strong Reliability&lt;/a>&lt;/td>
 &lt;td>關鍵事件如何達到高可靠路徑&lt;/td>
 &lt;td>payment、inventory、audit&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/routing-rule/" data-link-title="Routing Rule" data-link-desc="說明訊息系統如何依規則把訊息送到不同處理路徑">Routing Rule&lt;/a>&lt;/td>
 &lt;td>訊息如何依規則進入不同處理路徑&lt;/td>
 &lt;td>broker、queue、priority&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/producer/" data-link-title="Producer" data-link-desc="說明 producer 如何把工作、事件或資料送入後續處理路徑">Producer&lt;/a>&lt;/td>
 &lt;td>誰把工作、事件或資料送入處理路徑&lt;/td>
 &lt;td>queue、broker、stream&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/consumer/" data-link-title="Consumer" data-link-desc="說明 consumer 如何取得等待處理的工作並產生業務結果">Consumer&lt;/a>&lt;/td>
 &lt;td>誰取得等待處理的工作並產生結果&lt;/td>
 &lt;td>queue、worker、side effect&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/prefetch/" data-link-title="Prefetch" data-link-desc="說明 consumer 一次取得多少未完成訊息，以及它如何影響吞吐與公平性">Prefetch&lt;/a>&lt;/td>
 &lt;td>consumer 一次可持有多少未確認訊息&lt;/td>
 &lt;td>broker、consumer tuning&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/in-flight-message/" data-link-title="In-Flight Message" data-link-desc="說明已交給 consumer 但尚未完成確認的訊息狀態">In-Flight Message&lt;/a>&lt;/td>
 &lt;td>訊息已交給 consumer 但尚未完成&lt;/td>
 &lt;td>consumer、shutdown&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/unacked-message/" data-link-title="Unacked Message" data-link-desc="說明 broker 已投遞但尚未收到 consumer 確認的訊息">Unacked Message&lt;/a>&lt;/td>
 &lt;td>broker 尚未收到 consumer 確認的訊息&lt;/td>
 &lt;td>queue health、prefetch&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/ack-nack/" data-link-title="Ack / Nack" data-link-desc="說明 consumer 如何向 broker 回報訊息處理結果">Ack / Nack&lt;/a>&lt;/td>
 &lt;td>consumer 如何回報處理結果&lt;/td>
 &lt;td>broker、retry、DLQ&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/redelivery/" data-link-title="Redelivery" data-link-desc="說明 broker 重新投遞訊息時 consumer 需要承擔的重入責任">Redelivery&lt;/a>&lt;/td>
 &lt;td>broker 重新投遞訊息時如何保持安全&lt;/td>
 &lt;td>at-least-once、idempotency&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/requeue/" data-link-title="Requeue" data-link-desc="說明處理失敗的訊息重新排回 queue 時的風險與控制條件">Requeue&lt;/a>&lt;/td>
 &lt;td>處理失敗訊息如何重新排回 queue&lt;/td>
 &lt;td>retry、nack&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/redelivery-loop/" data-link-title="Redelivery Loop" data-link-desc="說明同一訊息反覆投遞失敗如何消耗 consumer 容量">Redelivery Loop&lt;/a>&lt;/td>
 &lt;td>同一訊息反覆投遞失敗如何消耗容量&lt;/td>
 &lt;td>poison message、DLQ&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/poison-message/" data-link-title="Poison Message" data-link-desc="說明特定訊息內容如何穩定造成 consumer 失敗">Poison Message&lt;/a>&lt;/td>
 &lt;td>特定訊息內容如何穩定造成失敗&lt;/td>
 &lt;td>DLQ、schema&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/queue-depth/" data-link-title="Queue Depth" data-link-desc="說明 queue 中等待處理的訊息數如何反映 backlog 與容量壓力">Queue Depth&lt;/a>&lt;/td>
 &lt;td>queue 中等待處理的訊息數&lt;/td>
 &lt;td>backlog、capacity&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/publisher-confirm/" data-link-title="Publisher Confirm" data-link-desc="說明 producer 如何確認 broker 已接收並承擔訊息">Publisher Confirm&lt;/a>&lt;/td>
 &lt;td>producer 如何確認 broker 已接收訊息&lt;/td>
 &lt;td>publish、outbox&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/message-persistence/" data-link-title="Message Persistence" data-link-desc="說明訊息是否落盤保存，以及 broker 重啟後能否恢復">Message Persistence&lt;/a>&lt;/td>
 &lt;td>訊息是否落盤保存&lt;/td>
 &lt;td>durability、cost&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/delivery-mode/" data-link-title="Delivery Mode" data-link-desc="說明訊息投遞模式如何影響可靠性、延遲與成本">Delivery Mode&lt;/a>&lt;/td>
 &lt;td>投遞模式如何影響可靠性與延遲&lt;/td>
 &lt;td>broker、event semantics&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/delivery-semantics/" data-link-title="Delivery Semantics" data-link-desc="說明事件投遞語意如何定義遺失、重複、順序與補償策略">Delivery Semantics&lt;/a>&lt;/td>
 &lt;td>事件投遞承諾如何決定補償策略&lt;/td>
 &lt;td>retry、idempotency、replay&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/consumer-capacity/" data-link-title="Consumer Capacity" data-link-desc="說明 consumer 群組每秒能穩定處理多少工作">Consumer Capacity&lt;/a>&lt;/td>
 &lt;td>consumer 群組每秒能處理多少工作&lt;/td>
 &lt;td>lag、scaling&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/competing-consumers/" data-link-title="Competing Consumers" data-link-desc="說明多個 consumer 共同處理同一個 queue 如何提高吞吐與影響順序">Competing Consumers&lt;/a>&lt;/td>
 &lt;td>多個 consumer 如何共同處理同一 queue&lt;/td>
 &lt;td>worker、throughput&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/consumer-group/" data-link-title="Consumer Group" data-link-desc="說明一組 consumer 如何共同分攤 stream 或 topic 的處理責任">Consumer Group&lt;/a>&lt;/td>
 &lt;td>多個 consumer 如何共同分攤 stream&lt;/td>
 &lt;td>Kafka、Redis Streams&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/partition/" data-link-title="Partition" data-link-desc="說明事件流如何切分成多個可並行處理的有序片段">Partition&lt;/a>&lt;/td>
 &lt;td>事件流如何切成可並行處理片段&lt;/td>
 &lt;td>ordering、hot key&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/offset/" data-link-title="Offset" data-link-desc="說明 consumer 在事件流中的讀取位置與重放基準">Offset&lt;/a>&lt;/td>
 &lt;td>consumer 在事件流中的讀取位置&lt;/td>
 &lt;td>replay、checkpoint&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/retention/" data-link-title="Retention" data-link-desc="說明資料或事件保留多久，以及保留期限如何影響重放與成本">Retention&lt;/a>&lt;/td>
 &lt;td>資料或事件保留多久&lt;/td>
 &lt;td>stream、log、audit&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/retry-policy/" data-link-title="Retry Policy" data-link-desc="說明重試策略如何區分暫時性錯誤、永久錯誤與副作用風險">Retry Policy&lt;/a>&lt;/td>
 &lt;td>失敗後何時再試、何時停止&lt;/td>
 &lt;td>timeout、broker、API&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/consumer-lag/" data-link-title="Consumer Lag" data-link-desc="說明 consumer lag 如何反映訊息堆積、處理能力與容量風險">Consumer Lag&lt;/a>&lt;/td>
 &lt;td>consumer 處理速度落後多少&lt;/td>
 &lt;td>queue health、capacity、alert&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/dead-letter-queue/" data-link-title="Dead-Letter Queue" data-link-desc="說明 dead-letter queue 如何隔離多次處理失敗的訊息">Dead-Letter Queue&lt;/a>&lt;/td>
 &lt;td>多次處理失敗的訊息如何隔離與診斷&lt;/td>
 &lt;td>retry、poison message、incident&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/replay-runbook/" data-link-title="Replay Runbook" data-link-desc="說明事件重放前需要控制的範圍、順序、驗證與副作用">Replay Runbook&lt;/a>&lt;/td>
 &lt;td>事件重放時如何控制範圍、順序與副作用&lt;/td>
 &lt;td>migration、事故復原、補資料&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/duplicate-delivery/" data-link-title="Duplicate Delivery" data-link-desc="說明同一個訊息被處理多次時如何保持結果穩定">重複投遞&lt;/a>&lt;/td>
 &lt;td>同一個工作被處理多次時如何保持結果穩定&lt;/td>
 &lt;td>at-least-once、idempotency&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/idempotency/" data-link-title="Idempotency" data-link-desc="說明同一操作執行多次時如何保持結果一致">Idempotency&lt;/a>&lt;/td>
 &lt;td>同一操作多次執行時如何保持結果穩定&lt;/td>
 &lt;td>retry、payment、worker&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/outbox-pattern/" data-link-title="Outbox Pattern" data-link-desc="說明資料庫狀態變更與事件發布如何透過 outbox 維持一致">Outbox Pattern&lt;/a>&lt;/td>
 &lt;td>資料變更與事件發布如何維持一致&lt;/td>
 &lt;td>transaction、broker&lt;/td>
 &lt;/tr>
 &lt;/tbody>
&lt;/table>
&lt;h2 id="遷移與資料同步">遷移與資料同步&lt;/h2>
&lt;table>
 &lt;thead>
 &lt;tr>
 &lt;th>卡片&lt;/th>
 &lt;th>核心問題&lt;/th>
 &lt;th>常見出現位置&lt;/th>
 &lt;/tr>
 &lt;/thead>
 &lt;tbody>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/online-migration/" data-link-title="Online Migration" data-link-desc="說明服務持續接流量時如何完成資料或 schema 遷移">Online Migration&lt;/a>&lt;/td>
 &lt;td>服務持續接流量時如何遷移資料&lt;/td>
 &lt;td>database、release&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/cutover-switchover/" data-link-title="Cutover / Switchover" data-link-desc="說明遷移期間如何把正式流量切到新路徑">Cutover / Switchover&lt;/a>&lt;/td>
 &lt;td>正式流量如何切到新路徑&lt;/td>
 &lt;td>migration、feature flag&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/fallback-plan/" data-link-title="Fallback Plan" data-link-desc="說明變更失敗時如何回到可接受狀態">Fallback Plan&lt;/a>&lt;/td>
 &lt;td>變更失敗時如何回到可接受狀態&lt;/td>
 &lt;td>release、migration&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/change-data-capture/" data-link-title="Change Data Capture" data-link-desc="說明資料變更如何被捕捉並傳送到其他系統">Change Data Capture&lt;/a>&lt;/td>
 &lt;td>資料變更如何被捕捉並傳送&lt;/td>
 &lt;td>CDC、event stream&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/replication-lag/" data-link-title="Replication Lag" data-link-desc="說明資料副本落後正式來源多久，以及它如何影響讀取正確性">Replication Lag&lt;/a>&lt;/td>
 &lt;td>副本落後正式來源多久&lt;/td>
 &lt;td>replica、read model&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/checkpoint/" data-link-title="Checkpoint" data-link-desc="說明長時間處理流程如何記錄可恢復進度">Checkpoint&lt;/a>&lt;/td>
 &lt;td>長流程如何記錄可恢復進度&lt;/td>
 &lt;td>backfill、consumer&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/backfill/" data-link-title="Backfill" data-link-desc="說明如何為既有資料補上新欄位、新索引或新衍生狀態">Backfill&lt;/a>&lt;/td>
 &lt;td>既有資料如何補上新欄位或新狀態&lt;/td>
 &lt;td>migration、repair&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/dual-write/" data-link-title="Dual Write" data-link-desc="說明同一變更同時寫入兩個系統時的一致性風險">Dual Write&lt;/a>&lt;/td>
 &lt;td>同一變更同時寫兩個系統的風險&lt;/td>
 &lt;td>migration、split service&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/shadow-read/" data-link-title="Shadow Read" data-link-desc="說明正式讀取仍走舊路徑時如何暗中讀新路徑比對結果">Shadow Read&lt;/a>&lt;/td>
 &lt;td>正式讀舊路徑時如何暗中比對新路徑&lt;/td>
 &lt;td>cutover、validation&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/correctness-check/" data-link-title="Correctness Check" data-link-desc="說明遷移或重構期間如何驗證新舊結果是否符合規則">Correctness Check&lt;/a>&lt;/td>
 &lt;td>新舊結果如何依規則比對&lt;/td>
 &lt;td>migration、refactor&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/data-completeness/" data-link-title="Data Completeness" data-link-desc="說明資料是否完整到足以支持查詢、遷移與決策">Data Completeness&lt;/a>&lt;/td>
 &lt;td>資料是否完整到足以支持目標用途&lt;/td>
 &lt;td>migration、audit&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/data-reconciliation/" data-link-title="Data Reconciliation" data-link-desc="說明多個資料來源不一致時如何比對、修復與留下證據">Data Reconciliation&lt;/a>&lt;/td>
 &lt;td>多來源差異如何比對與修復&lt;/td>
 &lt;td>payment、eventual consistency&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/replication-slot/" data-link-title="Replication Slot" data-link-desc="說明邏輯複製如何用 slot 追蹤消費進度，並對來源端造成保留壓力">Replication Slot&lt;/a>&lt;/td>
 &lt;td>邏輯複製如何追蹤進度並保留 WAL&lt;/td>
 &lt;td>CDC、slot lag、磁碟壓力&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/conflict-resolution/" data-link-title="Conflict Resolution" data-link-desc="說明並發或離線寫入產生衝突時，如何偵測、呈現與合併成可接受狀態">Conflict Resolution&lt;/a>&lt;/td>
 &lt;td>並發或離線寫入衝突如何合併&lt;/td>
 &lt;td>LWW、欄位合併、CRDT&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/logical-replication/" data-link-title="Logical Replication" data-link-desc="說明以表為粒度解碼 row-level 變更的複製方式，對照 byte-level 的實體複製">Logical Replication&lt;/a>&lt;/td>
 &lt;td>row-level 變更如何以表為粒度複製&lt;/td>
 &lt;td>physical、CDC、跨版本&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/replica-identity/" data-link-title="Replica Identity" data-link-desc="說明 row-level 變更事件如何帶穩定 key，讓下游能正確套用 update 與 delete">Replica Identity&lt;/a>&lt;/td>
 &lt;td>變更事件如何帶穩定 key 以套用 update/delete&lt;/td>
 &lt;td>CDC、primary key、row image&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/gtid/" data-link-title="GTID" data-link-desc="說明全域交易識別碼如何讓複製進度與故障切換不依賴實體 log 位置">GTID&lt;/a>&lt;/td>
 &lt;td>複製進度如何用全域交易識別碼表示&lt;/td>
 &lt;td>replication、failover、binlog&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/replication-channel/" data-link-title="Replication Channel" data-link-desc="說明多來源複製中，每個來源對應的獨立複製通道如何成為隔離單位">Replication Channel&lt;/a>&lt;/td>
 &lt;td>多來源複製如何用獨立通道隔離&lt;/td>
 &lt;td>multi-source、per-channel lag&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/tombstone/" data-link-title="Tombstone" data-link-desc="說明刪除如何用一筆標記記錄下來，讓刪除事件能跨副本與裝置傳播">Tombstone&lt;/a>&lt;/td>
 &lt;td>刪除如何用標記跨副本與裝置傳播&lt;/td>
 &lt;td>delete propagation、sync、CRDT&lt;/td>
 &lt;/tr>
 &lt;/tbody>
&lt;/table>
&lt;h2 id="可觀測性與可靠性">可觀測性與可靠性&lt;/h2>
&lt;table>
 &lt;thead>
 &lt;tr>
 &lt;th>卡片&lt;/th>
 &lt;th>核心問題&lt;/th>
 &lt;th>常見出現位置&lt;/th>
 &lt;/tr>
 &lt;/thead>
 &lt;tbody>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/log/" data-link-title="Log" data-link-desc="說明 log 如何記錄單一事件的上下文並支援事故排查">Log&lt;/a>&lt;/td>
 &lt;td>單一事件如何留下可搜尋的上下文&lt;/td>
 &lt;td>incident、debug、audit&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/log-schema/" data-link-title="Log Schema" data-link-desc="說明結構化 log 欄位如何支援搜尋、關聯與事故排查">Log Schema&lt;/a>&lt;/td>
 &lt;td>log 欄位如何支援搜尋與關聯&lt;/td>
 &lt;td>structured log、incident&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/metrics/" data-link-title="Metrics" data-link-desc="說明指標如何描述服務趨勢、容量與健康狀態">Metrics&lt;/a>&lt;/td>
 &lt;td>指標如何描述趨勢、容量與健康&lt;/td>
 &lt;td>Prometheus、dashboard&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/histogram/" data-link-title="Histogram" data-link-desc="說明 histogram 如何用分桶統計延遲、大小與分布">Histogram&lt;/a>&lt;/td>
 &lt;td>如何用分桶統計延遲與分布&lt;/td>
 &lt;td>latency、SLO&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/bucket/" data-link-title="Bucket" data-link-desc="說明 histogram 分桶如何決定觀測解析度與成本">Bucket&lt;/a>&lt;/td>
 &lt;td>histogram 分桶如何影響解析度&lt;/td>
 &lt;td>metrics、cost&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/percentile/" data-link-title="Percentile" data-link-desc="說明 p95 與 p99 如何描述長尾延遲與使用者體驗">Percentile&lt;/a>&lt;/td>
 &lt;td>p95 / p99 如何描述長尾延遲&lt;/td>
 &lt;td>latency、UX&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/metric-cardinality/" data-link-title="Metric Cardinality" data-link-desc="說明 metric label 組合數量如何影響觀測成本與查詢穩定性">Metric Cardinality&lt;/a>&lt;/td>
 &lt;td>label 組合數如何影響成本&lt;/td>
 &lt;td>metrics、storage、query&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/trace/" data-link-title="Trace" data-link-desc="說明 trace 如何重建跨服務請求的路徑、耗時與依賴關係">Trace&lt;/a>&lt;/td>
 &lt;td>跨服務流程如何重建路徑與耗時&lt;/td>
 &lt;td>tracing、dependency&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/trace-context/" data-link-title="Trace Context" data-link-desc="說明跨服務 request 如何用 trace context 串起路徑與耗時">Trace Context&lt;/a>&lt;/td>
 &lt;td>跨服務 request 如何串起路徑&lt;/td>
 &lt;td>tracing、OpenTelemetry&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/trace-id/" data-link-title="Trace ID" data-link-desc="說明分散式追蹤中同一條呼叫路徑的識別碼">Trace ID&lt;/a>&lt;/td>
 &lt;td>同一條 trace 的識別碼&lt;/td>
 &lt;td>tracing、log correlation&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/span/" data-link-title="Span" data-link-desc="說明 trace 中一段工作如何記錄耗時、狀態與關聯">Span&lt;/a>&lt;/td>
 &lt;td>trace 中一段工作如何記錄耗時&lt;/td>
 &lt;td>tracing、dependency&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/correlation-id/" data-link-title="Correlation ID" data-link-desc="說明跨事件或跨服務的關聯識別碼如何支援排障">Correlation ID&lt;/a>&lt;/td>
 &lt;td>跨事件與跨服務如何關聯業務流程&lt;/td>
 &lt;td>order、payment、queue&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/request-id/" data-link-title="Request ID" data-link-desc="說明單次 request 的識別碼如何支援 log 搜尋與問題定位">Request ID&lt;/a>&lt;/td>
 &lt;td>單次 request 如何被追蹤&lt;/td>
 &lt;td>API、support&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/dashboard/" data-link-title="Dashboard" data-link-desc="說明 dashboard 如何把關鍵訊號組成可判讀的服務狀態畫面">Dashboard&lt;/a>&lt;/td>
 &lt;td>多個觀測訊號如何組成服務狀態畫面&lt;/td>
 &lt;td>incident、capacity、SLO&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/sli-slo/" data-link-title="SLI / SLO" data-link-desc="說明服務品質指標與服務品質目標如何連接產品承諾">SLI / SLO&lt;/a>&lt;/td>
 &lt;td>服務品質如何連到產品承諾&lt;/td>
 &lt;td>alert、incident、error budget&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/error-budget/" data-link-title="Error Budget" data-link-desc="說明 SLO 允許的失敗額度如何影響發版與可靠性投入">Error Budget&lt;/a>&lt;/td>
 &lt;td>SLO 允許的失敗額度如何決策&lt;/td>
 &lt;td>release、reliability&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/burn-rate/" data-link-title="Burn Rate" data-link-desc="說明 error budget 消耗速度如何支援告警與事故分級">Burn Rate&lt;/a>&lt;/td>
 &lt;td>error budget 消耗速度如何告警&lt;/td>
 &lt;td>SLO alert&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/sampling/" data-link-title="Sampling" data-link-desc="說明觀測資料如何抽樣以控制成本並保留診斷能力">Sampling&lt;/a>&lt;/td>
 &lt;td>如何抽樣觀測資料以控制成本&lt;/td>
 &lt;td>trace、log&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/alert/" data-link-title="Alert" data-link-desc="說明 alert 如何把需要處理的服務症狀轉成可行動通知">Alert&lt;/a>&lt;/td>
 &lt;td>服務症狀如何轉成可行動通知&lt;/td>
 &lt;td>on-call、SLO、incident&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/runbook/" data-link-title="Runbook" data-link-desc="說明 runbook 如何把事故判斷與操作步驟標準化">Runbook&lt;/a>&lt;/td>
 &lt;td>事故判斷與操作步驟如何標準化&lt;/td>
 &lt;td>on-call、incident、replay&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/alert-runbook/" data-link-title="Alert Runbook" data-link-desc="說明告警如何連到可執行的排障與恢復流程">Alert Runbook&lt;/a>&lt;/td>
 &lt;td>告警如何連到可執行排障流程&lt;/td>
 &lt;td>on-call、dashboard&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/symptom-based-alert/" data-link-title="Symptom-Based Alert" data-link-desc="說明告警應優先偵測使用者可感知症狀">Symptom-Based Alert&lt;/a>&lt;/td>
 &lt;td>告警如何優先偵測產品症狀&lt;/td>
 &lt;td>SLO、on-call&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/runbook-link/" data-link-title="Runbook Link" data-link-desc="說明告警與 dashboard 如何直接連到處理流程">Runbook Link&lt;/a>&lt;/td>
 &lt;td>告警如何直接連到處理流程&lt;/td>
 &lt;td>alert、dashboard&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/alert-fatigue/" data-link-title="Alert Fatigue" data-link-desc="說明過多低品質告警如何降低 on-call 反應品質">Alert Fatigue&lt;/a>&lt;/td>
 &lt;td>低品質告警如何降低反應品質&lt;/td>
 &lt;td>on-call、alert policy&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/degradation/" data-link-title="Degradation" data-link-desc="說明服務部分能力失效時如何保留核心功能與控制風險">降級&lt;/a>&lt;/td>
 &lt;td>服務部分能力失效時如何保留核心功能&lt;/td>
 &lt;td>failover、fallback、capacity&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/circuit-breaker/" data-link-title="Circuit Breaker" data-link-desc="說明下游持續失敗時如何暫停呼叫並保護系統">Circuit Breaker&lt;/a>&lt;/td>
 &lt;td>下游持續失敗時如何暫停呼叫&lt;/td>
 &lt;td>timeout、fallback、degradation&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/failover/" data-link-title="Failover" data-link-desc="說明主要服務或節點失效時如何切換到備援能力">Failover&lt;/a>&lt;/td>
 &lt;td>主要路徑失效時如何切到備援&lt;/td>
 &lt;td>HA、region、provider&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/autoscaling/" data-link-title="Autoscaling" data-link-desc="說明系統如何依負載自動調整服務實例數量">Autoscaling&lt;/a>&lt;/td>
 &lt;td>容量如何依指標自動擴縮&lt;/td>
 &lt;td>HPA、capacity、traffic burst&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/rolling-update/" data-link-title="Rolling Update" data-link-desc="說明逐批替換服務版本的發版策略與風險控制">Rolling Update&lt;/a>&lt;/td>
 &lt;td>版本如何逐批替換並維持可用&lt;/td>
 &lt;td>deployment、release&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/service-registry/" data-link-title="Service Registry" data-link-desc="說明服務實例如何被註冊、維護與摘除">Service Registry&lt;/a>&lt;/td>
 &lt;td>服務實例如何被註冊、維護與摘除&lt;/td>
 &lt;td>heartbeat、TTL、metadata&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/service-discovery/" data-link-title="Service Discovery" data-link-desc="說明服務實例如何被查找與路由">Service Discovery&lt;/a>&lt;/td>
 &lt;td>服務實例如何被查找與路由&lt;/td>
 &lt;td>registry、DNS、load balancing&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/downtime/" data-link-title="Downtime" data-link-desc="說明服務中斷時需要評估的產品後果、資料保護與復原順序">停機&lt;/a>&lt;/td>
 &lt;td>服務中斷時要先保護哪些產品結果&lt;/td>
 &lt;td>incident、SLO、deployment&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/readiness/" data-link-title="Readiness" data-link-desc="說明 instance 何時可以安全接收流量，以及 readiness 如何和部署平台協作">Readiness&lt;/a>&lt;/td>
 &lt;td>instance 何時可以安全接收流量&lt;/td>
 &lt;td>Kubernetes、load balancer、rollout&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/health-check-liveness/" data-link-title="Liveness" data-link-desc="說明平台如何判斷 process 是否仍然存活，以及何時應重啟">Liveness&lt;/a>&lt;/td>
 &lt;td>平台如何判斷 process 是否仍然存活&lt;/td>
 &lt;td>Kubernetes、systemd&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/graceful-shutdown/" data-link-title="Graceful Shutdown" data-link-desc="說明服務停止前如何排空流量、完成工作與保存狀態">Graceful Shutdown&lt;/a>&lt;/td>
 &lt;td>instance 停止前如何排空流量與保存狀態&lt;/td>
 &lt;td>deployment、worker、long connection&lt;/td>
 &lt;/tr>
 &lt;/tbody>
&lt;/table>
&lt;h2 id="效能工程與容量規劃">效能工程與容量規劃&lt;/h2>
&lt;table>
 &lt;thead>
 &lt;tr>
 &lt;th>卡片&lt;/th>
 &lt;th>核心問題&lt;/th>
 &lt;th>常見出現位置&lt;/th>
 &lt;/tr>
 &lt;/thead>
 &lt;tbody>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/little-law/" data-link-title="Little&amp;#39;s Law" data-link-desc="說明系統內並發數、到達率與逗留時間三者的數學關係">Little&amp;rsquo;s Law&lt;/a>&lt;/td>
 &lt;td>並發、到達率、逗留時間如何相互推導&lt;/td>
 &lt;td>capacity、saturation、SLO&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/universal-scalability-law/" data-link-title="Universal Scalability Law (USL)" data-link-desc="說明系統擴容到一定規模後吞吐反而下降的數學模型">Universal Scalability Law&lt;/a>&lt;/td>
 &lt;td>擴容到某點後吞吐反而下降的數學原因&lt;/td>
 &lt;td>scalability、coordinator、consensus&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/saturation-point/" data-link-title="Saturation Point" data-link-desc="說明系統從線性穩態進入 latency 指數成長區的關鍵流量點">Saturation Point&lt;/a>&lt;/td>
 &lt;td>latency 進入指數成長的臨界流量&lt;/td>
 &lt;td>knee、capacity、headroom&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/use-method/" data-link-title="USE Method" data-link-desc="Brendan Gregg 提出的資源層 Utilization / Saturation / Errors 三維度量測法">USE Method&lt;/a>&lt;/td>
 &lt;td>資源層 Utilization / Saturation / Errors&lt;/td>
 &lt;td>bottleneck、resource、capacity&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/red-method/" data-link-title="RED Method" data-link-desc="Tom Wilkie 提出的請求層 Rate / Errors / Duration 三維度量測法">RED Method&lt;/a>&lt;/td>
 &lt;td>請求層 Rate / Errors / Duration&lt;/td>
 &lt;td>SLO、latency、request&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/workload-model/" data-link-title="Workload Model" data-link-desc="描述 production traffic 形狀的可重播模型 — 容量規劃跟壓測的共同輸入">Workload Model&lt;/a>&lt;/td>
 &lt;td>production traffic shape 如何量化重播&lt;/td>
 &lt;td>load test、capacity、forecast&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/tail-latency/" data-link-title="Tail Latency" data-link-desc="說明 p99 / p999 等長尾延遲為何比平均延遲更能反映 saturation">Tail Latency&lt;/a>&lt;/td>
 &lt;td>p99 / p999 為何比平均更能反映 saturation&lt;/td>
 &lt;td>SLO、GC、cross-zone&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/hot-partition/" data-link-title="Hot Partition" data-link-desc="說明分散式 KV / OLTP 中、單一 partition 流量遠超其他的容量問題">Hot Partition&lt;/a>&lt;/td>
 &lt;td>單一 partition 流量過熱、名義容量達不到&lt;/td>
 &lt;td>DynamoDB、partition key、saturation&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/peak-forecast/" data-link-title="Peak Forecast" data-link-desc="說明預期峰值流量的預測方法 — 容量規劃的第一個輸入">Peak Forecast&lt;/a>&lt;/td>
 &lt;td>預期峰值如何預測 — 容量公式輸入&lt;/td>
 &lt;td>capacity、event、growth&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/headroom-budget/" data-link-title="Headroom Budget" data-link-desc="說明容量規劃中為應付異常 burst &amp;#43; AZ 故障 &amp;#43; forecast 誤差的安全餘量">Headroom Budget&lt;/a>&lt;/td>
 &lt;td>容量規劃的安全餘量&lt;/td>
 &lt;td>capacity、AZ failover、forecast 誤差&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/growth-curve/" data-link-title="Growth Curve" data-link-desc="說明用戶 / 流量隨時間成長的五種典型形狀、影響容量規劃方法">Growth Curve&lt;/a>&lt;/td>
 &lt;td>用戶 / 流量成長的五種形狀&lt;/td>
 &lt;td>linear、step、exponential、cyclical&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/predictive-scaling/" data-link-title="Predictive Scaling" data-link-desc="說明用歷史模式或 ML 模型預測流量、提前擴容的 autoscaler 模式">Predictive Scaling&lt;/a>&lt;/td>
 &lt;td>根據預測提前擴容&lt;/td>
 &lt;td>autoscaler、ML、daily pattern&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/scheduled-scaling/" data-link-title="Scheduled Scaling" data-link-desc="說明按已知時間表預先擴容的 autoscaler 模式">Scheduled Scaling&lt;/a>&lt;/td>
 &lt;td>按已知時間表預先擴容&lt;/td>
 &lt;td>event、pre-scaling、Black Friday&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/shadow-traffic/" data-link-title="Shadow Traffic" data-link-desc="把 production traffic 複製到新版本驗證、但不返回結果給用戶的測試模式">Shadow Traffic&lt;/a>&lt;/td>
 &lt;td>production traffic 複製到新版本驗證&lt;/td>
 &lt;td>production validation、traffic mirror&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/dark-launch/" data-link-title="Dark Launch" data-link-desc="新功能上線但暫不開放 UI 入口、走 production traffic 但對用戶不可見的發布模式">Dark Launch&lt;/a>&lt;/td>
 &lt;td>程式碼上線但 UI 入口暫不開放&lt;/td>
 &lt;td>feature flag、production validation&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/canary-perf-check/" data-link-title="Canary Perf Check" data-link-desc="canary release 中針對 latency / throughput 而非 error rate 的退化檢查">Canary Perf Check&lt;/a>&lt;/td>
 &lt;td>canary release 中的 latency 退化檢查&lt;/td>
 &lt;td>canary、release gate、rollback&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/profile-diff/" data-link-title="Profile Diff" data-link-desc="對比兩次 profile（如 release candidate vs baseline）找出 hottest 變化">Profile Diff&lt;/a>&lt;/td>
 &lt;td>比較兩次 profile 找退化原因&lt;/td>
 &lt;td>release、CPU、memory、lock&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/continuous-profiling/" data-link-title="Continuous Profiling" data-link-desc="在 production 持續取得低 overhead profile 的觀察方法">Continuous Profiling&lt;/a>&lt;/td>
 &lt;td>production 持續取低 overhead profile&lt;/td>
 &lt;td>flame graph、observability、tracing&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/cost-per-request/" data-link-title="Cost Per Request" data-link-desc="把雲端成本拆到單一 API 請求的 unit economics 模型">Cost Per Request&lt;/a>&lt;/td>
 &lt;td>雲端成本拆到單一請求的 unit economics&lt;/td>
 &lt;td>FinOps、capacity、TCO&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/performance-budget/" data-link-title="Performance Budget" data-link-desc="跟 error budget 同類概念、但用於 latency / throughput 退化的可控額度">Performance Budget&lt;/a>&lt;/td>
 &lt;td>跟 error budget 並列的效能退化額度&lt;/td>
 &lt;td>SLO、release freeze、burn rate&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/latency-budget/" data-link-title="Latency Budget" data-link-desc="把 user-perceived latency 拆到每個 stage 的配額、反推架構選擇">Latency Budget&lt;/a>&lt;/td>
 &lt;td>end-to-end latency 拆到每 stage 的配額&lt;/td>
 &lt;td>Little&amp;rsquo;s Law、stage、reverse calculation&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/slo-baseline-drift/" data-link-title="SLO Baseline Drift" data-link-desc="SLO baseline 因業務變化 / surge / 架構改動而需要重新校準的現象">SLO Baseline Drift&lt;/a>&lt;/td>
 &lt;td>SLO baseline 因業務變化要重新校準&lt;/td>
 &lt;td>review、surge、product change&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/olap-offload/" data-link-title="OLAP Offload" data-link-desc="說明如何把分析型查詢從 OLTP 主庫卸載，以保護線上交易效能">OLAP Offload&lt;/a>&lt;/td>
 &lt;td>分析查詢如何從 OLTP 主庫卸載&lt;/td>
 &lt;td>replica、資料倉儲、CDC&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/per-connection-memory/" data-link-title="Per-Connection Memory" data-link-desc="說明每條連線或每個操作的記憶體用量如何隨並發數放大">Per-Connection Memory&lt;/a>&lt;/td>
 &lt;td>每連線記憶體如何隨並發數放大&lt;/td>
 &lt;td>sort/join buffer、OOM、連線數&lt;/td>
 &lt;/tr>
 &lt;/tbody>
&lt;/table>
&lt;h2 id="事故處理與復盤">事故處理與復盤&lt;/h2>
&lt;table>
 &lt;thead>
 &lt;tr>
 &lt;th>卡片&lt;/th>
 &lt;th>核心問題&lt;/th>
 &lt;th>常見出現位置&lt;/th>
 &lt;/tr>
 &lt;/thead>
 &lt;tbody>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/on-call/" data-link-title="On-Call" data-link-desc="說明值班制度如何承接告警、事故分級與升級流程">On-Call&lt;/a>&lt;/td>
 &lt;td>值班制度如何承接告警與事故流程&lt;/td>
 &lt;td>paging、handover、incident&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/handover-protocol/" data-link-title="Handover Protocol" data-link-desc="說明事故與值班交接時要傳遞哪些資訊、責任與完成條件">Handover Protocol&lt;/a>&lt;/td>
 &lt;td>值班或事故責任如何安全交接&lt;/td>
 &lt;td>on-call、escalation、incident&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/playbook/" data-link-title="Playbook" data-link-desc="說明場景化處置腳本如何降低事故處理不確定性">Playbook&lt;/a>&lt;/td>
 &lt;td>場景化處置如何快速啟動與執行&lt;/td>
 &lt;td>incident workflow、recovery&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/ci-pipeline/" data-link-title="CI Pipeline" data-link-desc="說明持續整合流程如何在合併前驗證品質與相容性">CI Pipeline&lt;/a>&lt;/td>
 &lt;td>合併前如何自動驗證品質與相容性&lt;/td>
 &lt;td>tests、checks、merge gate&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/load-test/" data-link-title="Load Test" data-link-desc="說明在預期流量下驗證容量、延遲與降級策略的測試">Load Test&lt;/a>&lt;/td>
 &lt;td>預期流量下如何驗證容量與延遲&lt;/td>
 &lt;td>performance、SLO、capacity&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/chaos-test/" data-link-title="Chaos Test" data-link-desc="說明透過受控故障注入驗證系統在異常條件下的恢復能力">Chaos Test&lt;/a>&lt;/td>
 &lt;td>受控故障注入如何驗證韌性&lt;/td>
 &lt;td>resilience、failover、runbook&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/game-day/" data-link-title="Game Day" data-link-desc="說明事故演練如何驗證流程、工具與團隊協作">Game Day&lt;/a>&lt;/td>
 &lt;td>事故演練如何驗證流程與協作&lt;/td>
 &lt;td>drill、readiness、training&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/incident-severity/" data-link-title="Incident Severity" data-link-desc="說明事故分級如何把產品影響轉成對應處置節奏">Incident Severity&lt;/a>&lt;/td>
 &lt;td>事故如何依產品影響分級&lt;/td>
 &lt;td>on-call、incident、SLO&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/incident-command-system/" data-link-title="Incident Command System" data-link-desc="說明事故期間的指揮角色、決策邊界與協作方式">Incident Command System&lt;/a>&lt;/td>
 &lt;td>事故期間如何分配指揮與執行角色&lt;/td>
 &lt;td>commander、scribe、owner&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/incident-communication-channel/" data-link-title="Incident Communication Channel" data-link-desc="說明事故期間內外部溝通要使用哪些固定通道與節奏">Incident Communication Channel&lt;/a>&lt;/td>
 &lt;td>事故期間如何同步對內對外資訊&lt;/td>
 &lt;td>internal chat、status update、bridge&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/escalation-policy/" data-link-title="Escalation Policy" data-link-desc="說明事故升級鏈與值班轉接規則">Escalation Policy&lt;/a>&lt;/td>
 &lt;td>事故無回應或無進展時如何升級&lt;/td>
 &lt;td>on-call、paging、handover&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/incident-timeline/" data-link-title="Incident Timeline" data-link-desc="說明事故時間線如何支援判斷、溝通與復盤">Incident Timeline&lt;/a>&lt;/td>
 &lt;td>事故事件如何形成一致時間軸&lt;/td>
 &lt;td>incident log、communication&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/evidence-package/" data-link-title="Evidence Package" data-link-desc="說明觀測、驗證與事故流程如何把證據包成可交接、可回放的 artifact">Evidence Package&lt;/a>&lt;/td>
 &lt;td>觀測與事故證據如何交接與回放&lt;/td>
 &lt;td>observability、verification、PIR&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/time-range/" data-link-title="Time Range" data-link-desc="說明證據、查詢與事故判讀如何用時間窗保留可回放上下文">Time Range&lt;/a>&lt;/td>
 &lt;td>證據如何保留明確時間窗&lt;/td>
 &lt;td>evidence、incident timeline&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/query-link/" data-link-title="Query Link" data-link-desc="說明證據包如何保存可重跑查詢入口，而不是只保留截圖或口頭結論">Query Link&lt;/a>&lt;/td>
 &lt;td>證據如何保留可重跑查詢入口&lt;/td>
 &lt;td>evidence、handoff&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/data-quality/" data-link-title="Data Quality" data-link-desc="說明證據欄位如何標示 completeness、freshness、sampling 與資料限制">Data Quality&lt;/a>&lt;/td>
 &lt;td>證據如何標示完整度與限制&lt;/td>
 &lt;td>evidence、sampling、freshness&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/confidence/" data-link-title="Confidence" data-link-desc="說明證據包如何標示 confirmed、suspected 或 needs follow-up 的判讀信心">Confidence&lt;/a>&lt;/td>
 &lt;td>證據如何標示判讀信心等級&lt;/td>
 &lt;td>evidence、gate decision&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/known-gap/" data-link-title="Known Gap" data-link-desc="說明證據包如何明確保存已知缺口，避免下游高估證據完整性">Known Gap&lt;/a>&lt;/td>
 &lt;td>證據如何保存已知缺口&lt;/td>
 &lt;td>evidence、PIR、readiness&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/incident-decision-log/" data-link-title="Incident Decision Log" data-link-desc="說明事故期間如何保留決策、證據、owner 與回退條件">Incident Decision Log&lt;/a>&lt;/td>
 &lt;td>事故決策如何保存證據與回退條件&lt;/td>
 &lt;td>IC handoff、PIR、status update&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/steady-state/" data-link-title="Steady State" data-link-desc="說明可靠性實驗與事故恢復如何定義系統應維持的可接受狀態">Steady State&lt;/a>&lt;/td>
 &lt;td>實驗與事故恢復如何定義成功狀態&lt;/td>
 &lt;td>chaos、DR、recovery&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/blast-radius/" data-link-title="Blast Radius" data-link-desc="說明事故影響面如何估算與隔離">Blast Radius&lt;/a>&lt;/td>
 &lt;td>故障影響面如何估算與隔離&lt;/td>
 &lt;td>dependency、shared resource&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/rollback-strategy/" data-link-title="Rollback Strategy" data-link-desc="說明事故期間如何判斷回滾、回切與暫停變更">Rollback Strategy&lt;/a>&lt;/td>
 &lt;td>事故期間何時回滾與回切&lt;/td>
 &lt;td>deployment、release gate&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/post-incident-review/" data-link-title="Post-Incident Review" data-link-desc="說明事故後如何完成復盤、學習與改進閉環">Post-Incident Review&lt;/a>&lt;/td>
 &lt;td>事故後如何形成改進閉環&lt;/td>
 &lt;td>retrospective、action items&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/rca/" data-link-title="RCA" data-link-desc="說明根因分析如何區分觸發事件、系統弱點與防線缺口">RCA&lt;/a>&lt;/td>
 &lt;td>根因分析如何從證據推導改進&lt;/td>
 &lt;td>timeline、control gap&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/rto/" data-link-title="RTO" data-link-desc="說明恢復時間目標如何約束事故回復策略">RTO&lt;/a>&lt;/td>
 &lt;td>服務回復時間目標如何定義&lt;/td>
 &lt;td>SLA/SLO、DR&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/rpo/" data-link-title="RPO" data-link-desc="說明恢復點目標如何定義可接受資料損失範圍">RPO&lt;/a>&lt;/td>
 &lt;td>可接受資料損失窗口如何定義&lt;/td>
 &lt;td>backup、replication&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/mttr/" data-link-title="MTTR" data-link-desc="說明平均修復時間如何作為事故處理能力指標">MTTR&lt;/a>&lt;/td>
 &lt;td>平均修復時間如何反映處置能力&lt;/td>
 &lt;td>incident metrics、review&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/point-in-time-recovery/" data-link-title="Point-in-Time Recovery" data-link-desc="說明如何用完整備份加上後續變更日誌，把資料庫還原到任意時間點">Point-in-Time Recovery&lt;/a>&lt;/td>
 &lt;td>資料如何還原到過去任意時間點&lt;/td>
 &lt;td>base backup、WAL、RPO&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/corruption-recovery/" data-link-title="Corruption Recovery" data-link-desc="說明資料損毀事故如何先辨識來源、保全證據，再決定修復或還原">Corruption Recovery&lt;/a>&lt;/td>
 &lt;td>資料損毀事故如何辨識來源並處置&lt;/td>
 &lt;td>checksum、evidence、restore&lt;/td>
 &lt;/tr>
 &lt;/tbody>
&lt;/table>
&lt;h2 id="資安與資料保護">資安與資料保護&lt;/h2>
&lt;table>
 &lt;thead>
 &lt;tr>
 &lt;th>卡片&lt;/th>
 &lt;th>核心問題&lt;/th>
 &lt;th>常見出現位置&lt;/th>
 &lt;/tr>
 &lt;/thead>
 &lt;tbody>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/authorization/" data-link-title="Authorization" data-link-desc="說明授權如何判斷誰能對哪些資源執行哪些操作">Authorization&lt;/a>&lt;/td>
 &lt;td>誰能對哪些資源執行哪些操作&lt;/td>
 &lt;td>RBAC、ABAC、tenant&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/authentication/" data-link-title="Authentication" data-link-desc="說明系統如何確認呼叫者身份">Authentication&lt;/a>&lt;/td>
 &lt;td>系統如何確認呼叫者身份&lt;/td>
 &lt;td>login、API key、mTLS&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/credential/" data-link-title="Credential" data-link-desc="整理身分驗證與系統存取用秘密資料">Credential&lt;/a>&lt;/td>
 &lt;td>身分與系統存取用秘密如何保存與輪替&lt;/td>
 &lt;td>API key、password、private key&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/iam/" data-link-title="IAM" data-link-desc="說明 identity and access management 如何集中管理身分、角色與權限">IAM&lt;/a>&lt;/td>
 &lt;td>身分與權限如何集中治理&lt;/td>
 &lt;td>SSO、roles、policy&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/bola-idor/" data-link-title="BOLA / IDOR" data-link-desc="說明物件層授權缺失如何讓使用者存取不屬於自己的資料">BOLA / IDOR&lt;/a>&lt;/td>
 &lt;td>使用者如何被限制只能存取授權物件&lt;/td>
 &lt;td>API、resource ID&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/bopla/" data-link-title="BOPLA" data-link-desc="說明屬性層授權缺失如何讓使用者讀寫不該暴露的欄位">BOPLA&lt;/a>&lt;/td>
 &lt;td>欄位層級如何授權讀寫&lt;/td>
 &lt;td>DTO、field policy&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/mass-assignment/" data-link-title="Mass Assignment" data-link-desc="說明自動綁定 request 欄位如何造成未授權欄位被修改">Mass Assignment&lt;/a>&lt;/td>
 &lt;td>自動綁定欄位如何造成未授權修改&lt;/td>
 &lt;td>API、ORM&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/excessive-data-exposure/" data-link-title="Excessive Data Exposure" data-link-desc="說明 API 回傳過多資料如何增加敏感資訊外洩風險">Excessive Data Exposure&lt;/a>&lt;/td>
 &lt;td>API 回傳過多資料如何增加外洩風險&lt;/td>
 &lt;td>response、DTO&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/unrestricted-resource-consumption/" data-link-title="Unrestricted Resource Consumption" data-link-desc="說明缺少資源限制如何讓 API 被濫用或拖垮">Unrestricted Resource Consumption&lt;/a>&lt;/td>
 &lt;td>API 如何限制昂貴資源使用&lt;/td>
 &lt;td>upload、export、query&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/function-level-authorization/" data-link-title="Function-Level Authorization" data-link-desc="說明功能操作本身也需要授權，不只資源 ID 需要授權">Function-Level Authorization&lt;/a>&lt;/td>
 &lt;td>功能操作本身如何授權&lt;/td>
 &lt;td>refund、export、admin&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/tenant-boundary/" data-link-title="Tenant Boundary" data-link-desc="說明多租戶系統如何隔離不同客戶或組織的資料與資源">Tenant Boundary&lt;/a>&lt;/td>
 &lt;td>多租戶資料與資源如何隔離&lt;/td>
 &lt;td>SaaS、RBAC&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/least-privilege/" data-link-title="Least Privilege" data-link-desc="說明身份、服務與人員只應取得完成工作所需的最小權限">Least Privilege&lt;/a>&lt;/td>
 &lt;td>身份如何只取得必要權限&lt;/td>
 &lt;td>IAM、database user&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/security-misconfiguration/" data-link-title="Security Misconfiguration" data-link-desc="說明錯誤設定如何讓安全控制失效或暴露內部能力">Security Misconfiguration&lt;/a>&lt;/td>
 &lt;td>設定錯誤如何暴露內部能力&lt;/td>
 &lt;td>CORS、debug、cloud&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/attack-surface/" data-link-title="Attack Surface" data-link-desc="說明系統哪些對外暴露面會被先行探測與枚舉">Attack Surface&lt;/a>&lt;/td>
 &lt;td>系統哪些對外暴露面最先被探測&lt;/td>
 &lt;td>public API、admin route、webhook&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/trust-boundary/" data-link-title="Trust Boundary" data-link-desc="說明系統哪些位置開始不能沿用原本的信任假設">Trust Boundary&lt;/a>&lt;/td>
 &lt;td>哪些位置要重建信任假設&lt;/td>
 &lt;td>auth boundary、tenant、network&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/abuse-case/" data-link-title="Abuse Case" data-link-desc="說明合法功能如何被惡意轉用成突破或濫用路徑">Abuse Case&lt;/a>&lt;/td>
 &lt;td>合法功能如何被惡意轉用&lt;/td>
 &lt;td>export、invite、reset&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/waf/" data-link-title="WAF" data-link-desc="說明 Web Application Firewall 如何在入口層過濾常見攻擊與濫用">WAF&lt;/a>&lt;/td>
 &lt;td>入口層如何過濾常見攻擊與濫用&lt;/td>
 &lt;td>edge、bot、attack&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/feature-flag/" data-link-title="Feature Flag" data-link-desc="說明如何用可動態開關控制功能曝光與風險">Feature Flag&lt;/a>&lt;/td>
 &lt;td>功能開關如何分離部署與啟用&lt;/td>
 &lt;td>rollout、experiment、rollback&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/security-exception/" data-link-title="Security Exception" data-link-desc="說明資安風險例外如何以期限、補償控制與關閉條件管理">Security Exception&lt;/a>&lt;/td>
 &lt;td>風險例外如何以期限與關閉條件治理&lt;/td>
 &lt;td>risk acceptance、governance&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/release-freeze/" data-link-title="Release Freeze" data-link-desc="說明高風險期間如何以凍結策略保護正式環境">Release Freeze&lt;/a>&lt;/td>
 &lt;td>高風險期間如何暫停特定變更&lt;/td>
 &lt;td>incident、vulnerability window&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/tripwire/" data-link-title="Tripwire" data-link-desc="說明風險決策在條件變化時如何自動回到評估流程">Tripwire&lt;/a>&lt;/td>
 &lt;td>風險決策何時自動回到重評估流程&lt;/td>
 &lt;td>threshold、escalation&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/allowlist/" data-link-title="Allowlist" data-link-desc="說明如何用明確允許條件控制例外放行範圍">Allowlist&lt;/a>&lt;/td>
 &lt;td>例外放行如何維持可控範圍&lt;/td>
 &lt;td>freeze exception、policy control&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/input-validation/" data-link-title="Input Validation" data-link-desc="說明進入系統的資料如何先被檢查格式、範圍與語意">Input Validation&lt;/a>&lt;/td>
 &lt;td>入口資料如何檢查格式與語意&lt;/td>
 &lt;td>API、webhook&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/ssrf/" data-link-title="SSRF" data-link-desc="說明伺服器端請求被濫用時如何存取內部網路或 metadata 服務">SSRF&lt;/a>&lt;/td>
 &lt;td>伺服器端請求如何被濫用&lt;/td>
 &lt;td>URL fetch、webhook&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/pii/" data-link-title="PII" data-link-desc="說明可識別個人的資料如何影響權限、遮罩、保留與稽核">PII&lt;/a>&lt;/td>
 &lt;td>可識別個人的資料如何保護&lt;/td>
 &lt;td>masking、retention&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/data-classification/" data-link-title="Data Classification" data-link-desc="說明資料分級如何決定保護、存取、保留與匯出規則">Data Classification&lt;/a>&lt;/td>
 &lt;td>資料分級如何決定保護規則&lt;/td>
 &lt;td>security、compliance&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/data-masking/" data-link-title="Data Masking" data-link-desc="說明敏感資料如何在顯示、匯出、log 與測試資料中降低暴露">Data Masking&lt;/a>&lt;/td>
 &lt;td>敏感資料如何降低暴露&lt;/td>
 &lt;td>export、log、support tool&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/secret-management/" data-link-title="Secret Management" data-link-desc="說明 token、key、password 與憑證如何保存、輪替與撤銷">Secret Management&lt;/a>&lt;/td>
 &lt;td>token、key、password 如何保存與輪替&lt;/td>
 &lt;td>credential、deployment&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/tls-mtls/" data-link-title="TLS / mTLS" data-link-desc="說明傳輸加密與雙向憑證驗證如何保護跨邊界資料流">TLS / mTLS&lt;/a>&lt;/td>
 &lt;td>傳輸加密與雙向身份驗證如何保護資料流&lt;/td>
 &lt;td>service-to-service、API&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/website-certificate-lifecycle/" data-link-title="Website Certificate Lifecycle" data-link-desc="說明網站 TLS 憑證從簽發到續期與撤銷的全流程責任">Website Certificate Lifecycle&lt;/a>&lt;/td>
 &lt;td>網站憑證從簽發到續期與撤銷如何治理&lt;/td>
 &lt;td>HTTPS、edge、ingress&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/acme-automation/" data-link-title="ACME Automation" data-link-desc="說明網站憑證如何透過 ACME 自動簽發與續期">ACME Automation&lt;/a>&lt;/td>
 &lt;td>網站憑證如何自動簽發與續期&lt;/td>
 &lt;td>Let&amp;rsquo;s Encrypt、DNS-01、HTTP-01&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/certificate-chain-trust/" data-link-title="Certificate Chain and Trust Root" data-link-desc="說明網站憑證鏈與信任根如何影響連線可用性與驗證結果">Certificate Chain and Trust Root&lt;/a>&lt;/td>
 &lt;td>憑證鏈與信任根如何影響握手&lt;/td>
 &lt;td>intermediate CA、trust store&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/certificate-rotation-renewal/" data-link-title="Certificate Rotation and Renewal" data-link-desc="說明網站憑證如何安全續期與輪替以避免停機">Certificate Rotation and Renewal&lt;/a>&lt;/td>
 &lt;td>憑證與私鑰如何不中斷更新&lt;/td>
 &lt;td>expiry、zero-downtime&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/certificate-revocation/" data-link-title="Certificate Revocation" data-link-desc="說明憑證洩漏或誤發時如何撤銷並控制影響範圍">Certificate Revocation&lt;/a>&lt;/td>
 &lt;td>憑證失效時如何撤銷與替換&lt;/td>
 &lt;td>key compromise、incident&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/artifact-provenance/" data-link-title="Artifact Provenance" data-link-desc="說明交付物的來源、完整性與簽章關聯如何建立信任">Artifact Provenance&lt;/a>&lt;/td>
 &lt;td>交付物來源與完整性如何建立可驗證信任&lt;/td>
 &lt;td>CI、supply chain、release gate&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/audit-log/" data-link-title="Audit Log" data-link-desc="說明高風險操作如何留下可追溯、可稽核的紀錄">Audit Log&lt;/a>&lt;/td>
 &lt;td>高風險操作如何留下責任證據&lt;/td>
 &lt;td>admin、export、permission&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/row-level-security/" data-link-title="Row-Level Security" data-link-desc="說明資料庫如何用 policy 限制同一張表中哪些 row 對某個角色可見或可寫">Row-Level Security&lt;/a>&lt;/td>
 &lt;td>資料庫如何用 policy 過濾可見的 row&lt;/td>
 &lt;td>RLS、多租戶、policy&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/at-rest-encryption/" data-link-title="At-Rest Encryption" data-link-desc="說明資料落到儲存媒介前的加密層，以及它對應的威脅模型">At-Rest Encryption&lt;/a>&lt;/td>
 &lt;td>落地資料如何在儲存層加密&lt;/td>
 &lt;td>tablespace、backup、金鑰&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/key-management/" data-link-title="Key Management" data-link-desc="說明加密金鑰如何產生、保存、輪替，以及還原時如何依賴金鑰">Key Management&lt;/a>&lt;/td>
 &lt;td>加密金鑰如何產生、保存與輪替&lt;/td>
 &lt;td>KMS、keyring、rotation&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/break-glass-access/" data-link-title="Break-Glass Access" data-link-desc="說明緊急情況下臨時授予的高權限存取，如何用工單、時限與事後審查治理">Break-Glass Access&lt;/a>&lt;/td>
 &lt;td>緊急高權限存取如何用工單與時限治理&lt;/td>
 &lt;td>emergency、ticket、audit&lt;/td>
 &lt;/tr>
 &lt;/tbody>
&lt;/table>
&lt;h2 id="使用方式">使用方式&lt;/h2>
&lt;p>知識卡片是章節引用單位。選型文章遇到術語時，應連到對應卡片；服務實體章節需要更深入時，再從卡片延伸到具體工具操作。&lt;/p></description><content:encoded><![CDATA[<p>前置知識卡片的核心目標是把後端服務中的高密度術語拆成可獨立閱讀的 domain knowhow。服務選型文章會使用 broker、consumer lag、dead-letter、replay、降級、停機、readiness 等詞彙；這些詞彙背後都包含產品後果、操作責任與排障方式。</p>
<p>這個模組先建立共同語言。每張卡片只處理一個知識節點，並用「概念位置、可觀察訊號、接近真實網路服務的例子、設計責任」說明它在後端系統中的角色。</p>
<h2 id="術語建卡判準">術語建卡判準</h2>
<p>知識卡片的建卡判準是術語是否承擔理解成本與判斷成本，核心重點在它如何影響服務理解，而非只看它是否已經在多篇文章重複出現。讀者如果缺少某個名詞的服務語意，就會難以理解服務路徑、風險邊界、artifact 欄位或下一步決策，這個名詞就值得建卡。</p>
<p>適合建卡的術語通常有三個特徵：第一，它超過單純字面翻譯，並包含服務責任、操作條件或失敗代價；第二，讀者若缺少它就難以理解服務路徑、風險邊界或下一步決策，例如 validation query、rollback window、fallback read；第三，它可以被獨立說明成「概念位置、可觀察訊號、例子、設計責任」。出現頻率與是否影響實作判斷都可以當補充訊號，但不參與「是否要建卡」的必要判準。</p>
<p>不適合建卡的是過度寬泛、沒有明確服務責任的詞。若名詞只是文章中的普通形容詞、單一欄位值、或只能在該句子內成立，優先在正文補清楚，不硬拆成卡片。</p>
<h2 id="資料與一致性">資料與一致性</h2>
<table>
  <thead>
      <tr>
          <th>卡片</th>
          <th>核心問題</th>
          <th>常見出現位置</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td><a href="/blog/backend/knowledge-cards/database/" data-link-title="Database" data-link-desc="說明 database 在後端系統中如何承擔正式狀態、查詢與一致性責任">Database</a></td>
          <td>正式狀態如何保存、查詢與保護</td>
          <td>source of truth、transaction、backup</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/knowledge-cards/source-of-truth/" data-link-title="Source of Truth" data-link-desc="說明正式資料來源如何決定資料判斷、修復與一致性責任">Source of Truth</a></td>
          <td>哪個位置承擔正式資料判斷</td>
          <td>database、cache、search index</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/knowledge-cards/search-index/" data-link-title="Search Index" data-link-desc="說明搜尋索引如何承擔全文檢索、排序與查詢體驗">Search Index</a></td>
          <td>搜尋體驗如何有獨立讀取模型</td>
          <td>full-text、filter、ranking</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/knowledge-cards/full-text-search/" data-link-title="Full-Text Search" data-link-desc="說明全文檢索如何處理關鍵字匹配、語言分析與排序">Full-Text Search</a></td>
          <td>文本檢索如何支援關鍵字與相關性排序</td>
          <td>search、documents、catalog</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/knowledge-cards/facet-query/" data-link-title="Facet Query" data-link-desc="說明分面查詢如何提供分類統計與篩選體驗">Facet Query</a></td>
          <td>搜尋結果如何提供可篩選聚合維度</td>
          <td>filter、aggregation、UX</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/knowledge-cards/object-storage/" data-link-title="Object Storage" data-link-desc="說明大型非結構化檔案的保存、存取與生命週期管理">Object Storage</a></td>
          <td>大型檔案如何保存與控管生命週期</td>
          <td>upload、export、backup</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/knowledge-cards/event-log/" data-link-title="Event Log" data-link-desc="說明事件歷史如何保存、重播與支援跨服務資料重建">Event Log</a></td>
          <td>歷史事件如何保存與重播</td>
          <td>replay、audit、projection</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/knowledge-cards/read-model/" data-link-title="Read Model" data-link-desc="說明為查詢場景建立的讀取模型，與正式狀態的責任分離">Read Model</a></td>
          <td>查詢需求如何有獨立讀取資料形狀</td>
          <td>projection、query model</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/knowledge-cards/projection/" data-link-title="Projection" data-link-desc="說明從事件流或資料變更推算出查詢用讀取視圖的轉換機制">Projection</a></td>
          <td>來源資料如何轉換成查詢視圖</td>
          <td>events、materialized view</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/knowledge-cards/data-lifecycle/" data-link-title="Data Lifecycle" data-link-desc="說明資料從建立、使用、保留到刪除的責任邊界">資料生命週期</a></td>
          <td>資料如何建立、保留、封存與刪除</td>
          <td>retention、audit、export</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/knowledge-cards/data-inconsistency/" data-link-title="Data Inconsistency" data-link-desc="說明多份資料暫時不同步時如何判斷產品後果與修復責任">資料不一致</a></td>
          <td>多份資料暫時不同步時如何辨識與修復</td>
          <td>cache、replica、eventual consistency</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/knowledge-cards/transaction/" data-link-title="Transaction" data-link-desc="說明 transaction 如何讓一組資料變更一起成功或一起回復">Transaction</a></td>
          <td>一組資料變更如何一起成功或一起回復</td>
          <td>database、commit、rollback</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/knowledge-cards/transaction-boundary/" data-link-title="Transaction Boundary" data-link-desc="說明哪些資料變更應在同一個交易中一起成功或一起回復">Transaction Boundary</a></td>
          <td>哪些變更要一起成功或回復</td>
          <td>database、unit of work</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/knowledge-cards/migration/" data-link-title="Migration" data-link-desc="說明系統如何把資料、流量或結構從舊狀態移到新狀態">Migration</a></td>
          <td>系統如何從舊狀態受控移到新狀態</td>
          <td>release、cutover、backfill</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/knowledge-cards/schema-migration/" data-link-title="Schema Migration" data-link-desc="說明資料庫結構如何隨應用程式版本安全演進">Schema Migration</a></td>
          <td>資料庫結構如何隨版本安全演進</td>
          <td>release、rollback、migration</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/knowledge-cards/expand-contract/" data-link-title="Expand / Contract" data-link-desc="說明先擴充相容面、再收斂舊路徑的遷移做法">Expand / Contract</a></td>
          <td>先擴充相容面再收斂舊路徑的遷移做法</td>
          <td>schema migration、online migration</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/knowledge-cards/migration-gate/" data-link-title="Migration Gate" data-link-desc="說明遷移流程何時可以進入下一階段或正式切換">Migration Gate</a></td>
          <td>遷移流程如何決定能否進入下一階段</td>
          <td>backfill、correctness check</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/knowledge-cards/mapping-table/" data-link-title="Mapping Table" data-link-desc="說明遷移或轉換期間如何把舊語意明確對應到新語意">Mapping Table</a></td>
          <td>舊資料語意如何明確對應到新語意</td>
          <td>migration、backfill、validation</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/knowledge-cards/validation-query/" data-link-title="Validation Query" data-link-desc="說明遷移、回填與修復期間如何用查詢證明資料語意是否一致">Validation Query</a></td>
          <td>查詢如何證明資料語意是否一致</td>
          <td>migration、evidence package</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/knowledge-cards/read-compatibility/" data-link-title="Read Compatibility" data-link-desc="說明資料或服務演進期間讀取路徑如何同時支援新舊語意">Read Compatibility</a></td>
          <td>讀取路徑如何同時支援新舊語意</td>
          <td>expand、cutover、fallback read</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/knowledge-cards/fallback-read/" data-link-title="Fallback Read" data-link-desc="說明讀取路徑切換失敗時如何暫時回到舊資料語意或舊讀取來源">Fallback Read</a></td>
          <td>切換失敗時如何暫時回到舊讀取語意</td>
          <td>cutover、rollback window</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/knowledge-cards/cutover-window/" data-link-title="Cutover Window" data-link-desc="說明正式切換發生的觀察窗口、停止條件與回退判讀範圍">Cutover Window</a></td>
          <td>正式切換如何被時間窗與訊號框住</td>
          <td>cutover、release gate</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/knowledge-cards/release-gate/" data-link-title="Release Gate" data-link-desc="說明變更在正式釋出前如何通過或阻擋">Release Gate</a></td>
          <td>變更如何在正式釋出前通過或阻擋</td>
          <td>error budget、migration、review</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/knowledge-cards/gate-decision/" data-link-title="Gate Decision" data-link-desc="說明 release gate 如何把證據轉成放行、暫停、回退或補證據的決策">Gate Decision</a></td>
          <td>gate 如何把證據轉成下一步決策</td>
          <td>release gate、rollout</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/knowledge-cards/rollback-rehearsal/" data-link-title="Rollback Rehearsal" data-link-desc="說明如何在正式事故前演練回滾流程">Rollback Rehearsal</a></td>
          <td>回滾流程如何在正式事故前演練</td>
          <td>rollback strategy、migration</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/knowledge-cards/rollback-window/" data-link-title="Rollback Window" data-link-desc="說明變更進入 production 後還能用哪種方式回退或改路線的時間與條件">Rollback Window</a></td>
          <td>變更後還能用哪種方式回退或改路線</td>
          <td>cutover、rollback strategy</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/knowledge-cards/rollback-condition/" data-link-title="Rollback Condition" data-link-desc="說明決策執行後出現哪些訊號時要撤回、回退或改路線">Rollback Condition</a></td>
          <td>決策後何時要撤回、回退或改路線</td>
          <td>incident decision、rollback</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/knowledge-cards/fail-forward/" data-link-title="Fail-forward" data-link-desc="說明無法回到舊狀態時如何用受控前進完成修復">Fail-forward</a></td>
          <td>舊狀態已失效時如何受控前進修復</td>
          <td>rollback window、incident decision</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/knowledge-cards/stop-condition/" data-link-title="Stop Condition" data-link-desc="說明變更、實驗或事故處理何時必須暫停、回退或改路線">Stop Condition</a></td>
          <td>何時必須暫停、回退或改路線</td>
          <td>release gate、incident decision</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/knowledge-cards/isolation-level/" data-link-title="Isolation Level" data-link-desc="說明資料庫交易隔離級別如何影響並發讀寫結果">Isolation Level</a></td>
          <td>並發交易彼此看見哪些資料</td>
          <td>transaction、lock、retry</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/knowledge-cards/connection-pool/" data-link-title="Connection Pool" data-link-desc="說明連線池如何限制下游資源並影響服務容量">Connection Pool</a></td>
          <td>application 如何限制下游連線壓力</td>
          <td>database、Redis、broker</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/knowledge-cards/database-sharding/" data-link-title="Database Sharding" data-link-desc="說明資料庫如何依 shard key 分散資料、路由請求與承擔跨 shard 查詢成本">Database Sharding</a></td>
          <td>資料庫如何依 shard key 分散與路由</td>
          <td>Vitess、Citus、tenant key</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/knowledge-cards/write-ahead-log/" data-link-title="Write-Ahead Log" data-link-desc="說明資料庫如何先寫入 log 再合併回主資料，以提供持久性與崩潰復原">Write-Ahead Log</a></td>
          <td>寫入如何先記 log 再合併以支援復原</td>
          <td>WAL、checkpoint、recovery</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/knowledge-cards/single-writer-model/" data-link-title="Single Writer Model" data-link-desc="說明單寫者模型如何序列化寫入，並成為系統的容量邊界">Single Writer Model</a></td>
          <td>寫入如何被序列化成單一路徑</td>
          <td>SQLite、primary lease、容量上限</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/knowledge-cards/embedded-database/" data-link-title="Embedded Database" data-link-desc="說明嵌入式資料庫如何隨 application process 運作，並把檔案生命週期責任交回應用">Embedded Database</a></td>
          <td>資料庫如何隨 application process 運作</td>
          <td>SQLite、檔案生命週期、本地儲存</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/knowledge-cards/metadata-lock/" data-link-title="Metadata Lock" data-link-desc="說明 DDL 與既有交易如何在 table metadata 層互相排隊與阻塞">Metadata Lock</a></td>
          <td>DDL 與既有交易如何在 schema 層互相阻塞</td>
          <td>ALTER、長交易、DDL window</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/knowledge-cards/table-partitioning/" data-link-title="Table Partitioning" data-link-desc="說明單一資料庫內如何把大表拆成多個分區，並由查詢規劃器只掃相關片段">Table Partitioning</a></td>
          <td>大表如何在單庫內拆成多個分區</td>
          <td>range/list/hash、pruning、retention</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/knowledge-cards/read-write-split/" data-link-title="Read-Write Split" data-link-desc="說明讀寫流量如何分流到 primary 與 replica，以及它引入的一致性責任">Read-Write Split</a></td>
          <td>讀寫流量如何分流到 primary 與 replica</td>
          <td>proxy、replica lag、read-after-write</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/knowledge-cards/transaction-pooling/" data-link-title="Transaction Pooling" data-link-desc="說明 connection pooler 的 transaction 綁定模式如何壓縮連線並改變 session 語意">Transaction Pooling</a></td>
          <td>連線如何只綁定單一 transaction</td>
          <td>pooler、session state、SET LOCAL</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/knowledge-cards/document-store/" data-link-title="Document Store" data-link-desc="說明以 JSON 文件與彈性 schema 提供資料存取的模式，以及它仍需的治理邊界">Document Store</a></td>
          <td>資料如何以 JSON 文件與彈性 schema 存取</td>
          <td>JSON、巢狀結構、index</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/knowledge-cards/local-first/" data-link-title="Local-First" data-link-desc="說明本機優先的資料架構如何讓離線可用，並把同步當成獨立問題">Local-First</a></td>
          <td>資料如何本機優先並離線可用</td>
          <td>離線、多端同步、行動 app</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/knowledge-cards/read-after-write/" data-link-title="Read-After-Write Consistency" data-link-desc="說明寫入後能否立即讀到該筆寫入的一致性保證">Read-After-Write Consistency</a></td>
          <td>寫入後能否立即讀到該筆寫入</td>
          <td>primary、lag guard、session</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/knowledge-cards/type-affinity/" data-link-title="Type Affinity" data-link-desc="說明 SQLite 如何用 type affinity 決定欄位的型別傾向與值的儲存方式">Type Affinity</a></td>
          <td>SQLite 欄位型別如何是傾向而非硬約束</td>
          <td>SQLite、storage class、STRICT</td>
      </tr>
  </tbody>
</table>
<h2 id="快取與流量">快取與流量</h2>
<table>
  <thead>
      <tr>
          <th>卡片</th>
          <th>核心問題</th>
          <th>常見出現位置</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td><a href="/blog/backend/knowledge-cards/timeout/" data-link-title="Timeout" data-link-desc="說明等待外部操作的時間上限如何保護資源與使用者體驗">Timeout</a></td>
          <td>單一步驟最久可以等待多久</td>
          <td>API、database、broker</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/knowledge-cards/deadline/" data-link-title="Deadline" data-link-desc="說明整體操作的截止時間如何沿著服務邊界傳遞">Deadline</a></td>
          <td>整體操作何時必須完成</td>
          <td>request、job、workflow</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/knowledge-cards/exponential-backoff/" data-link-title="Exponential Backoff" data-link-desc="說明重試間隔如何逐步拉長以降低下游壓力">Exponential Backoff</a></td>
          <td>重試間隔如何逐步拉長</td>
          <td>retry、API、worker</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/knowledge-cards/jitter/" data-link-title="Jitter" data-link-desc="說明重試或排程加入隨機偏移如何降低同步尖峰">Jitter</a></td>
          <td>如何分散同步重試與排程尖峰</td>
          <td>retry、TTL、reconnect</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/knowledge-cards/retry-storm/" data-link-title="Retry Storm" data-link-desc="說明大量重試如何把局部故障放大成系統壓力">Retry Storm</a></td>
          <td>大量重試如何放大下游壓力</td>
          <td>timeout、dependency failure</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/knowledge-cards/thundering-herd/" data-link-title="Thundering Herd" data-link-desc="說明大量工作同時被喚醒或同時競爭資源時的尖峰風險">Thundering Herd</a></td>
          <td>大量工作同時醒來如何形成尖峰</td>
          <td>reconnect、cache、lock</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/knowledge-cards/transient-failure/" data-link-title="Transient Failure" data-link-desc="說明暫時性故障如何影響重試、告警與使用者回應">Transient Failure</a></td>
          <td>暫時性故障如何影響重試與告警</td>
          <td>network、failover、timeout</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/knowledge-cards/partial-failure/" data-link-title="Partial Failure" data-link-desc="說明分散式系統中部分依賴失效時如何保留整體可用性">Partial Failure</a></td>
          <td>局部失效時如何保留整體可用性</td>
          <td>distributed system、fallback</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/knowledge-cards/cascading-failure/" data-link-title="Cascading Failure" data-link-desc="說明局部故障如何透過等待、重試與資源耗盡擴散到整個系統">Cascading Failure</a></td>
          <td>局部故障如何擴散成整體故障</td>
          <td>dependency、retry、pool</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/knowledge-cards/load-shedding/" data-link-title="Load Shedding" data-link-desc="說明服務過載時如何主動拒絕低優先工作以保護核心能力">Load Shedding</a></td>
          <td>過載時如何主動拒絕低優先工作</td>
          <td>overload、priority</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/knowledge-cards/token-bucket/" data-link-title="Token Bucket" data-link-desc="說明 token bucket 如何用配額與補充速率控制流量">Token Bucket</a></td>
          <td>如何用配額與補充速率控制流量</td>
          <td>rate limit、retry budget</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/knowledge-cards/dependency-isolation/" data-link-title="Dependency Isolation" data-link-desc="說明如何隔離下游依賴，避免單一依賴耗盡共享資源">Dependency Isolation</a></td>
          <td>如何避免單一下游耗盡共享資源</td>
          <td>pool、queue、dependency</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/knowledge-cards/bulkhead/" data-link-title="Bulkhead" data-link-desc="說明 bulkhead 如何用資源分艙限制故障擴散">Bulkhead</a></td>
          <td>如何用資源分艙限制故障擴散</td>
          <td>worker、tenant、pool</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/knowledge-cards/in-process-channel/" data-link-title="In-Process Channel" data-link-desc="說明單一 process 內用來傳遞工作的 channel 或 queue abstraction">In-Process Channel</a></td>
          <td>單一 process 內如何傳遞工作或訊號</td>
          <td>channel、local queue</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/knowledge-cards/local-worker/" data-link-title="Local Worker" data-link-desc="說明同一個 process 內的背景工作模型與其生命週期邊界">Local Worker</a></td>
          <td>同 process 背景工作的責任與邊界</td>
          <td>background task、shutdown</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/knowledge-cards/worker-pool/" data-link-title="Worker Pool" data-link-desc="說明一組 worker 如何限制同時處理量並保護下游資源">Worker Pool</a></td>
          <td>如何限制同時處理量</td>
          <td>worker、background job</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/knowledge-cards/http-client/" data-link-title="HTTP Client" data-link-desc="說明服務呼叫外部 HTTP 依賴時需要管理 timeout、連線與重試">HTTP Client</a></td>
          <td>呼叫外部 HTTP 依賴時如何管理資源</td>
          <td>API、dependency</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/knowledge-cards/webhook/" data-link-title="Webhook" data-link-desc="說明外部系統回呼事件的接收、驗證與處理邊界">Webhook</a></td>
          <td>外部系統回呼事件如何驗證與處理</td>
          <td>callback、signature、retry</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/knowledge-cards/websocket/" data-link-title="WebSocket" data-link-desc="說明 WebSocket 如何提供長連線雙向即時通訊">WebSocket</a></td>
          <td>長連線雙向即時通訊如何運作</td>
          <td>chat、presence、push</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/knowledge-cards/sse/" data-link-title="Server-Sent Events (SSE)" data-link-desc="說明 SSE 如何透過 HTTP 長連線向 client 單向推送事件">Server-Sent Events (SSE)</a></td>
          <td>HTTP 單向事件串流如何推送更新</td>
          <td>notification、progress</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/knowledge-cards/stream-pipeline/" data-link-title="Stream Pipeline" data-link-desc="說明連續資料流經多個處理階段時如何管理吞吐、順序與 backpressure ">Stream Pipeline</a></td>
          <td>連續資料流如何管理吞吐與 backpressure</td>
          <td>stream、CDC、ETL</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/knowledge-cards/throughput/" data-link-title="Throughput" data-link-desc="整理系統單位時間內可處理的工作量">Throughput</a></td>
          <td>單位時間內可處理多少工作</td>
          <td>load test、queue、broker</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/knowledge-cards/buffer/" data-link-title="Buffer" data-link-desc="說明系統如何用暫存空間吸收短暫速度差與尖峰流量">Buffer</a></td>
          <td>暫存空間如何吸收短暫速度差</td>
          <td>queue、socket、cache</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/knowledge-cards/queue/" data-link-title="Queue" data-link-desc="說明 queue 如何保存等待處理的工作並形成容量邊界">Queue</a></td>
          <td>等待處理的工作如何形成容量邊界</td>
          <td>producer、consumer、backlog</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/knowledge-cards/socket/" data-link-title="Socket" data-link-desc="說明 network socket 如何成為 application 與網路之間的資料傳輸邊界">Socket</a></td>
          <td>網路連線如何成為資料讀寫與資源邊界</td>
          <td>network、connection、timeout</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/knowledge-cards/fallback/" data-link-title="Fallback" data-link-desc="說明主要路徑失敗時使用替代結果或替代流程的設計責任">Fallback</a></td>
          <td>主要路徑失敗時使用什麼替代結果</td>
          <td>degradation、circuit breaker</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/knowledge-cards/fail-fast/" data-link-title="Fail Fast" data-link-desc="說明已知無法完成時快速回應如何保護資源與上游判斷">Fail Fast</a></td>
          <td>已知會失敗時如何快速回應</td>
          <td>circuit breaker、validation</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/knowledge-cards/retry-budget/" data-link-title="Retry Budget" data-link-desc="說明重試次數如何受整體容量與錯誤預算限制">Retry Budget</a></td>
          <td>重試量如何受整體容量限制</td>
          <td>retry、SLO、token bucket</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/knowledge-cards/cache-aside/" data-link-title="Cache Aside" data-link-desc="說明 application 如何在讀取時自行管理快取與正式資料來源">Cache Aside</a></td>
          <td>application 如何讀快取與正式來源</td>
          <td>Redis、read path</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/knowledge-cards/cache-hit-miss/" data-link-title="Cache Hit / Miss" data-link-desc="說明快取命中與未命中如何影響讀取成本與下游壓力">Cache Hit / Miss</a></td>
          <td>讀取是否命中快取</td>
          <td>cache、database pressure</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/knowledge-cards/cache-hit-rate/" data-link-title="Cache Hit Rate" data-link-desc="說明快取命中比例如何衡量加速效果與下游保護">Cache Hit Rate</a></td>
          <td>命中比例如何衡量快取效益</td>
          <td>dashboard、capacity</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/knowledge-cards/cache-warmup/" data-link-title="Cache Warmup" data-link-desc="說明服務啟動或活動前如何預先建立快取資料">Cache Warmup</a></td>
          <td>正式流量前如何預先載入快取</td>
          <td>deployment、event</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/knowledge-cards/cache-prefetching/" data-link-title="Cache Prefetching" data-link-desc="說明系統如何在資料被需要前預先載入快取">Cache Prefetching</a></td>
          <td>如何在資料被需要前預先載入</td>
          <td>user flow、hot data</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/knowledge-cards/cold-start/" data-link-title="Cold Start" data-link-desc="說明服務或快取剛啟動時尚未累積狀態造成的延遲與壓力">Cold Start</a></td>
          <td>新 instance 或空快取如何造成延遲</td>
          <td>autoscaling、readiness</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/knowledge-cards/write-through-cache/" data-link-title="Write-Through Cache" data-link-desc="說明寫入時同步更新快取與正式來源的策略">Write-Through Cache</a></td>
          <td>寫入時如何同步更新快取</td>
          <td>write path、freshness</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/knowledge-cards/write-behind-cache/" data-link-title="Write-Behind Cache" data-link-desc="說明先寫快取再非同步寫入正式來源的風險與用途">Write-Behind Cache</a></td>
          <td>先寫緩衝層再非同步持久化的風險</td>
          <td>analytics、buffer</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/knowledge-cards/stale-data/" data-link-title="Stale Data" data-link-desc="說明過期資料在快取、replica 與衍生資料中的產品影響">Stale Data</a></td>
          <td>過期資料如何影響產品結果</td>
          <td>cache、replica</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/knowledge-cards/soft-ttl/" data-link-title="Soft TTL" data-link-desc="說明資料進入刷新期後仍可短暫使用以降低 stampede">Soft TTL</a></td>
          <td>進入刷新期後如何短暫使用舊資料</td>
          <td>stampede、refresh</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/knowledge-cards/singleflight/" data-link-title="Singleflight" data-link-desc="說明相同工作同時發生時如何合併成一次下游請求">Singleflight</a></td>
          <td>相同工作如何合併成一次下游請求</td>
          <td>cache miss、hot key</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/knowledge-cards/ttl/" data-link-title="TTL" data-link-desc="說明資料過期時間如何影響快取新鮮度、成本與一致性">TTL</a></td>
          <td>資料何時自動過期</td>
          <td>cache、session、presence</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/knowledge-cards/eviction/" data-link-title="Eviction" data-link-desc="說明快取容量不足時哪些資料會被淘汰，以及淘汰如何影響服務">Eviction</a></td>
          <td>容量不足時哪些資料會被淘汰</td>
          <td>Redis、local cache、CDN</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/knowledge-cards/cache-invalidation/" data-link-title="Cache Invalidation" data-link-desc="說明快取資料何時更新、刪除或重建，以及失效策略如何影響一致性">快取失效策略</a></td>
          <td>快取資料何時更新、刪除或重建</td>
          <td>Redis、CDN、多層快取</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/knowledge-cards/hot-key/" data-link-title="Hot Key" data-link-desc="說明單一 key 承受大量讀寫時如何形成容量瓶頸">Hot Key</a></td>
          <td>少數 key 如何形成容量瓶頸</td>
          <td>Redis、partition、counter</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/knowledge-cards/cache-stampede/" data-link-title="Cache Stampede" data-link-desc="說明快取同時失效時大量 request 如何壓垮正式來源">Cache Stampede</a></td>
          <td>快取同時 miss 如何壓垮正式來源</td>
          <td>hot key、TTL、database</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/knowledge-cards/rate-limit/" data-link-title="Rate Limit" data-link-desc="說明限流如何保護服務入口、下游依賴與租戶公平性">Rate Limit</a></td>
          <td>如何限制主體在一段時間內的資源使用量</td>
          <td>API、tenant、worker</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/knowledge-cards/backpressure/" data-link-title="Backpressure" data-link-desc="說明下游處理速度不足時系統如何讓上游依下游能力送出工作">Backpressure</a></td>
          <td>下游變慢時如何讓上游放慢</td>
          <td>queue、worker、stream</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/knowledge-cards/buffer-pool/" data-link-title="Buffer Pool" data-link-desc="說明資料庫如何用記憶體快取磁碟頁，以降低 I/O 並影響查詢效能">Buffer Pool</a></td>
          <td>資料庫如何用記憶體快取磁碟頁</td>
          <td>InnoDB、shared buffers、命中率</td>
      </tr>
  </tbody>
</table>
<h2 id="入口與部署">入口與部署</h2>
<table>
  <thead>
      <tr>
          <th>卡片</th>
          <th>核心問題</th>
          <th>常見出現位置</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td><a href="/blog/backend/knowledge-cards/endpoint/" data-link-title="Service Endpoint" data-link-desc="說明服務如何對外暴露可被路由與存取的入口">Service Endpoint</a></td>
          <td>服務入口如何被路由與存取</td>
          <td>API、service discovery、internal</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/knowledge-cards/public-api-endpoint/" data-link-title="Public API Endpoint" data-link-desc="說明面向外部 client 的穩定 API 入口如何被管理">Public API Endpoint</a></td>
          <td>面向 client 的穩定對外入口</td>
          <td>product API、SDK、client</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/knowledge-cards/api-gateway/" data-link-title="API Gateway" data-link-desc="說明外部流量如何先收斂到一層可集中控制的入口">API Gateway</a></td>
          <td>外部流量如何集中路由、驗證與轉發</td>
          <td>auth、rate limit、routing、request id</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/knowledge-cards/request-routing/" data-link-title="Request Routing" data-link-desc="說明入口流量如何依規則被導向不同服務或處理路徑">Request Routing</a></td>
          <td>入口流量如何分派到不同服務或版本</td>
          <td>host、path、tenant、version</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/knowledge-cards/admin-endpoint/" data-link-title="Admin Endpoint" data-link-desc="說明管理入口如何承擔高權限操作與稽核責任">Admin Endpoint</a></td>
          <td>高權限管理入口如何被隔離與稽核</td>
          <td>admin、backoffice、control plane</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/knowledge-cards/diagnostic-endpoint/" data-link-title="Diagnostic Endpoint" data-link-desc="說明健康檢查、診斷與調試入口如何控制暴露面">Diagnostic Endpoint</a></td>
          <td>health、readiness 與 debug 入口</td>
          <td>liveness、probe、metrics snapshot</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/knowledge-cards/internal-endpoint/" data-link-title="Internal Endpoint" data-link-desc="說明服務內部通訊入口如何配合網路邊界與服務發現">Internal Endpoint</a></td>
          <td>服務內部通訊入口如何受控</td>
          <td>service-to-service、control plane</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/knowledge-cards/container/" data-link-title="Container" data-link-desc="說明容器如何包裝服務、隔離依賴與影響部署方式">Container</a></td>
          <td>服務如何被包裝成可交付單位</td>
          <td>image、runtime、CI、Kubernetes</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/knowledge-cards/load-balancer/" data-link-title="Load Balancer" data-link-desc="說明流量如何分散、排空與導向健康節點">Load Balancer</a></td>
          <td>流量如何分散、排空與導向健康節點</td>
          <td>ingress、draining、rolling update</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/knowledge-cards/draining/" data-link-title="Draining" data-link-desc="說明服務如何先停止接收新流量，再讓既有工作完成">Draining</a></td>
          <td>服務如何先停新流量再完成既有工作</td>
          <td>rolling update、shutdown、cutover</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/knowledge-cards/sticky-session/" data-link-title="Sticky Session" data-link-desc="說明同一 client 如何在一段時間內持續命中同一個後端實例">Sticky Session</a></td>
          <td>同一 client 如何維持命中同一實例</td>
          <td>session affinity、load balancer</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/knowledge-cards/idle-timeout/" data-link-title="Idle Timeout" data-link-desc="說明連線或會話在多久沒有活動後應該被回收">Idle Timeout</a></td>
          <td>連線或會話多久沒活動後要回收</td>
          <td>socket、load balancer、proxy</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/knowledge-cards/health-check/" data-link-title="Health Check" data-link-desc="說明服務如何對外提供可供平台判斷狀態的健康回應">Health Check</a></td>
          <td>平台如何快速判斷服務狀態</td>
          <td>load balancer、probe、diagnostic</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/knowledge-cards/resource-limit/" data-link-title="Resource Limit" data-link-desc="說明服務可使用的 CPU、memory 與相關資源上限如何影響行為">Resource Limit</a></td>
          <td>服務可用的 CPU / memory 上限如何影響行為</td>
          <td>container、scheduler、runtime</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/knowledge-cards/probe/" data-link-title="Probe" data-link-desc="說明平台如何透過 probe 判斷服務狀態與接流量條件">Probe</a></td>
          <td>平台如何判斷存活與接流量條件</td>
          <td>readiness、liveness、startup</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/knowledge-cards/config-rollout/" data-link-title="Config Rollout" data-link-desc="說明設定如何安全下發到正在運作的服務實例">Config Rollout</a></td>
          <td>設定如何安全下發到運作中的服務實例</td>
          <td>feature flag、secret、runtime config</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/knowledge-cards/runtime-config/" data-link-title="Runtime Config" data-link-desc="說明服務在啟動與執行時如何讀取與組合設定">Runtime Config</a></td>
          <td>執行時設定如何被讀取、組合與覆寫</td>
          <td>env var、secret、feature flag</td>
      </tr>
  </tbody>
</table>
<h2 id="通訊協定">通訊協定</h2>
<table>
  <thead>
      <tr>
          <th>卡片</th>
          <th>核心問題</th>
          <th>常見出現位置</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td><a href="/blog/backend/knowledge-cards/protocol/" data-link-title="Communication Protocol" data-link-desc="說明不同系統如何對齊資料交換與錯誤語意">Communication Protocol</a></td>
          <td>不同系統如何對齊資料交換與錯誤語意</td>
          <td>request/response、message、webhook</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/knowledge-cards/request-response-protocol/" data-link-title="Request/Response Protocol" data-link-desc="說明同步請求如何在 client 與 service 之間對齊互動規則">Request/Response Protocol</a></td>
          <td>同步呼叫如何對齊互動規則</td>
          <td>HTTP API、gRPC、RPC</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/knowledge-cards/message-protocol/" data-link-title="Message Protocol" data-link-desc="說明 queue 或 stream message 如何對齊格式與處理語意">Message Protocol</a></td>
          <td>queue / stream 訊息如何對齊格式與語意</td>
          <td>event、job、delivery</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/knowledge-cards/webhook-protocol/" data-link-title="Webhook Protocol" data-link-desc="說明外部回呼如何對齊簽章、重試與 payload 語意">Webhook Protocol</a></td>
          <td>外部回呼如何對齊簽章與 payload</td>
          <td>callback、signature、retry</td>
      </tr>
  </tbody>
</table>
<h2 id="邊界與治理">邊界與治理</h2>
<table>
  <thead>
      <tr>
          <th>卡片</th>
          <th>核心問題</th>
          <th>常見出現位置</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td><a href="/blog/backend/knowledge-cards/contract/" data-link-title="Boundary Contract" data-link-desc="說明跨邊界約定如何維持相容與可驗證">Boundary Contract</a></td>
          <td>邊界兩端如何維持一致約定</td>
          <td>API contract、deployment contract、queue contract、load balancer contract</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/knowledge-cards/api-contract/" data-link-title="API Contract" data-link-desc="說明 request / response 邊界如何維持相容與可驗證">API Contract</a></td>
          <td>request / response 如何維持相容</td>
          <td>client、SDK、public API</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/knowledge-cards/deployment-contract/" data-link-title="Deployment Contract" data-link-desc="說明服務與部署平台之間的生命週期約定">Deployment Contract</a></td>
          <td>application 與 platform 如何對齊生命週期</td>
          <td>readiness、shutdown、rollout</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/knowledge-cards/queue-contract/" data-link-title="Queue Contract" data-link-desc="說明佇列工作在重試、確認與重複投遞上的約定">Queue Contract</a></td>
          <td>producer / broker / consumer 如何對齊交付語意</td>
          <td>ack、retry、DLQ、redelivery</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/knowledge-cards/load-balancer-contract/" data-link-title="Load Balancer Contract" data-link-desc="說明服務與負載平衡器之間的流量與健康檢查約定">Load Balancer Contract</a></td>
          <td>服務與流量入口如何對齊健康與切流</td>
          <td>health check、draining、idle timeout</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/knowledge-cards/adapter/" data-link-title="Integration Adapter" data-link-desc="說明外部系統接入層如何轉換介面與隔離差異">Integration Adapter</a></td>
          <td>外部系統如何轉成內部需要的形狀</td>
          <td>repository、payment、notification</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/knowledge-cards/repository-adapter/" data-link-title="Repository Adapter" data-link-desc="說明持久化層如何把資料模型轉成外部儲存介面">Repository Adapter</a></td>
          <td>持久化存取如何對齊應用模型</td>
          <td>SQL、transaction、row mapping</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/knowledge-cards/provider-adapter/" data-link-title="Provider Adapter" data-link-desc="說明第三方服務如何被包裝成內部穩定介面">Provider Adapter</a></td>
          <td>第三方服務如何被包裝成穩定介面</td>
          <td>payment、email、SMS、storage</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/knowledge-cards/notification-adapter/" data-link-title="Notification Adapter" data-link-desc="說明通知通道如何把 domain event 轉成外部傳遞格式">Notification Adapter</a></td>
          <td>通知通道如何轉成外部發送格式</td>
          <td>email、push、webhook</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/knowledge-cards/middleware/" data-link-title="Request Middleware" data-link-desc="說明請求處理鏈中的共通攔截與前後置處理">Request Middleware</a></td>
          <td>共通請求處理如何放在邊界上</td>
          <td>auth、logging、tracing、validation</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/knowledge-cards/authentication-middleware/" data-link-title="Authentication Middleware" data-link-desc="說明請求進入 handler 前如何完成身份驗證">Authentication Middleware</a></td>
          <td>請求進入前如何驗證身份</td>
          <td>token、session、signature</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/knowledge-cards/authorization-middleware/" data-link-title="Authorization Middleware" data-link-desc="說明請求進入 handler 前如何完成權限判斷">Authorization Middleware</a></td>
          <td>請求進入前如何判斷權限</td>
          <td>role、tenant、resource owner</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/knowledge-cards/observability-middleware/" data-link-title="Observability Middleware" data-link-desc="說明請求進入 handler 前後如何補上觀測欄位">Observability Middleware</a></td>
          <td>請求如何補上觀測欄位</td>
          <td>request id、trace context</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/knowledge-cards/security-middleware/" data-link-title="Security Middleware" data-link-desc="說明請求進入 handler 前如何完成共通安全控制">Security Middleware</a></td>
          <td>請求如何套用共通安全控制</td>
          <td>rate limit、redaction</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/knowledge-cards/validation-middleware/" data-link-title="Validation Middleware" data-link-desc="說明請求進入 handler 前如何完成共通驗證">Validation Middleware</a></td>
          <td>請求如何先做共通驗證</td>
          <td>schema、header、payload shape</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/knowledge-cards/vendor-lock-in/" data-link-title="Vendor Lock-In" data-link-desc="說明採用供應商產品後，其 API 與格式滲入程式碼造成的退出成本">Vendor Lock-In</a></td>
          <td>供應商 API 滲入程式碼如何造成退出成本</td>
          <td>adapter、exit route、選型</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/knowledge-cards/capability-outsourcing-depth/" data-link-title="Capability Outsourcing Depth（外包深度）" data-link-desc="說明外包一塊後端能力有三種深度（managed 基礎設施、feature SaaS、BaaS bundle）、深度決定保留多少控制權與遷出代價">Capability Outsourcing Depth</a></td>
          <td>外包一塊能力的三種深度如何決定控制權與遷出代價</td>
          <td>managed 基礎設施、feature SaaS、BaaS bundle</td>
      </tr>
  </tbody>
</table>
<h2 id="訊息與事件">訊息與事件</h2>
<table>
  <thead>
      <tr>
          <th>卡片</th>
          <th>核心問題</th>
          <th>常見出現位置</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td><a href="/blog/backend/knowledge-cards/broker/" data-link-title="Broker" data-link-desc="說明 broker 在訊息傳遞系統中負責保存、路由與交付訊息">Broker</a></td>
          <td>訊息離開單一 process 後由誰保存、路由與交付</td>
          <td>queue、event、worker、stream</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/knowledge-cards/topic/" data-link-title="Topic" data-link-desc="說明 topic 如何把事件依主題分流給不同訂閱者">Topic</a></td>
          <td>事件如何依主題分流給不同訂閱者</td>
          <td>broker、event、stream</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/knowledge-cards/pub-sub/" data-link-title="Pub/Sub" data-link-desc="說明 publish-subscribe 如何把事件即時分發給多個訂閱者">Pub/Sub</a></td>
          <td>訊息如何即時分發給多個訂閱者</td>
          <td>realtime、notification、broadcast</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/knowledge-cards/fan-out/" data-link-title="Fan-out" data-link-desc="說明單一事件同時分發給多個下游的訊息拓撲">Fan-out</a></td>
          <td>單一事件如何同時送到多個下游</td>
          <td>topic、subscription、event flow</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/knowledge-cards/durable-queue/" data-link-title="Durable Queue" data-link-desc="說明可持久化的 queue 如何在重啟與失敗後保留待處理工作">Durable Queue</a></td>
          <td>工作如何在故障後仍可被處理</td>
          <td>persistence、ack/nack、retry</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/knowledge-cards/reliability-boundary/" data-link-title="Reliability Boundary" data-link-desc="說明系統在哪個邊界內承諾可靠傳遞，邊界外需要哪些補償機制">Reliability Boundary</a></td>
          <td>系統在哪些邊界內承諾可恢復傳遞</td>
          <td>request、process、service boundary</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/knowledge-cards/offline-catchup/" data-link-title="Offline Catch-up" data-link-desc="說明訂閱者離線後如何補回缺失事件或狀態">Offline Catch-up</a></td>
          <td>離線期間漏失事件如何補齊</td>
          <td>websocket、sync、reconnect</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/knowledge-cards/strong-reliability/" data-link-title="Strong Reliability" data-link-desc="說明高可靠事件路徑需要的保存、重試、去重與回復責任">Strong Reliability</a></td>
          <td>關鍵事件如何達到高可靠路徑</td>
          <td>payment、inventory、audit</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/knowledge-cards/routing-rule/" data-link-title="Routing Rule" data-link-desc="說明訊息系統如何依規則把訊息送到不同處理路徑">Routing Rule</a></td>
          <td>訊息如何依規則進入不同處理路徑</td>
          <td>broker、queue、priority</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/knowledge-cards/producer/" data-link-title="Producer" data-link-desc="說明 producer 如何把工作、事件或資料送入後續處理路徑">Producer</a></td>
          <td>誰把工作、事件或資料送入處理路徑</td>
          <td>queue、broker、stream</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/knowledge-cards/consumer/" data-link-title="Consumer" data-link-desc="說明 consumer 如何取得等待處理的工作並產生業務結果">Consumer</a></td>
          <td>誰取得等待處理的工作並產生結果</td>
          <td>queue、worker、side effect</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/knowledge-cards/prefetch/" data-link-title="Prefetch" data-link-desc="說明 consumer 一次取得多少未完成訊息，以及它如何影響吞吐與公平性">Prefetch</a></td>
          <td>consumer 一次可持有多少未確認訊息</td>
          <td>broker、consumer tuning</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/knowledge-cards/in-flight-message/" data-link-title="In-Flight Message" data-link-desc="說明已交給 consumer 但尚未完成確認的訊息狀態">In-Flight Message</a></td>
          <td>訊息已交給 consumer 但尚未完成</td>
          <td>consumer、shutdown</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/knowledge-cards/unacked-message/" data-link-title="Unacked Message" data-link-desc="說明 broker 已投遞但尚未收到 consumer 確認的訊息">Unacked Message</a></td>
          <td>broker 尚未收到 consumer 確認的訊息</td>
          <td>queue health、prefetch</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/knowledge-cards/ack-nack/" data-link-title="Ack / Nack" data-link-desc="說明 consumer 如何向 broker 回報訊息處理結果">Ack / Nack</a></td>
          <td>consumer 如何回報處理結果</td>
          <td>broker、retry、DLQ</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/knowledge-cards/redelivery/" data-link-title="Redelivery" data-link-desc="說明 broker 重新投遞訊息時 consumer 需要承擔的重入責任">Redelivery</a></td>
          <td>broker 重新投遞訊息時如何保持安全</td>
          <td>at-least-once、idempotency</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/knowledge-cards/requeue/" data-link-title="Requeue" data-link-desc="說明處理失敗的訊息重新排回 queue 時的風險與控制條件">Requeue</a></td>
          <td>處理失敗訊息如何重新排回 queue</td>
          <td>retry、nack</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/knowledge-cards/redelivery-loop/" data-link-title="Redelivery Loop" data-link-desc="說明同一訊息反覆投遞失敗如何消耗 consumer 容量">Redelivery Loop</a></td>
          <td>同一訊息反覆投遞失敗如何消耗容量</td>
          <td>poison message、DLQ</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/knowledge-cards/poison-message/" data-link-title="Poison Message" data-link-desc="說明特定訊息內容如何穩定造成 consumer 失敗">Poison Message</a></td>
          <td>特定訊息內容如何穩定造成失敗</td>
          <td>DLQ、schema</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/knowledge-cards/queue-depth/" data-link-title="Queue Depth" data-link-desc="說明 queue 中等待處理的訊息數如何反映 backlog 與容量壓力">Queue Depth</a></td>
          <td>queue 中等待處理的訊息數</td>
          <td>backlog、capacity</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/knowledge-cards/publisher-confirm/" data-link-title="Publisher Confirm" data-link-desc="說明 producer 如何確認 broker 已接收並承擔訊息">Publisher Confirm</a></td>
          <td>producer 如何確認 broker 已接收訊息</td>
          <td>publish、outbox</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/knowledge-cards/message-persistence/" data-link-title="Message Persistence" data-link-desc="說明訊息是否落盤保存，以及 broker 重啟後能否恢復">Message Persistence</a></td>
          <td>訊息是否落盤保存</td>
          <td>durability、cost</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/knowledge-cards/delivery-mode/" data-link-title="Delivery Mode" data-link-desc="說明訊息投遞模式如何影響可靠性、延遲與成本">Delivery Mode</a></td>
          <td>投遞模式如何影響可靠性與延遲</td>
          <td>broker、event semantics</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/knowledge-cards/delivery-semantics/" data-link-title="Delivery Semantics" data-link-desc="說明事件投遞語意如何定義遺失、重複、順序與補償策略">Delivery Semantics</a></td>
          <td>事件投遞承諾如何決定補償策略</td>
          <td>retry、idempotency、replay</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/knowledge-cards/consumer-capacity/" data-link-title="Consumer Capacity" data-link-desc="說明 consumer 群組每秒能穩定處理多少工作">Consumer Capacity</a></td>
          <td>consumer 群組每秒能處理多少工作</td>
          <td>lag、scaling</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/knowledge-cards/competing-consumers/" data-link-title="Competing Consumers" data-link-desc="說明多個 consumer 共同處理同一個 queue 如何提高吞吐與影響順序">Competing Consumers</a></td>
          <td>多個 consumer 如何共同處理同一 queue</td>
          <td>worker、throughput</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/knowledge-cards/consumer-group/" data-link-title="Consumer Group" data-link-desc="說明一組 consumer 如何共同分攤 stream 或 topic 的處理責任">Consumer Group</a></td>
          <td>多個 consumer 如何共同分攤 stream</td>
          <td>Kafka、Redis Streams</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/knowledge-cards/partition/" data-link-title="Partition" data-link-desc="說明事件流如何切分成多個可並行處理的有序片段">Partition</a></td>
          <td>事件流如何切成可並行處理片段</td>
          <td>ordering、hot key</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/knowledge-cards/offset/" data-link-title="Offset" data-link-desc="說明 consumer 在事件流中的讀取位置與重放基準">Offset</a></td>
          <td>consumer 在事件流中的讀取位置</td>
          <td>replay、checkpoint</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/knowledge-cards/retention/" data-link-title="Retention" data-link-desc="說明資料或事件保留多久，以及保留期限如何影響重放與成本">Retention</a></td>
          <td>資料或事件保留多久</td>
          <td>stream、log、audit</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/knowledge-cards/retry-policy/" data-link-title="Retry Policy" data-link-desc="說明重試策略如何區分暫時性錯誤、永久錯誤與副作用風險">Retry Policy</a></td>
          <td>失敗後何時再試、何時停止</td>
          <td>timeout、broker、API</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/knowledge-cards/consumer-lag/" data-link-title="Consumer Lag" data-link-desc="說明 consumer lag 如何反映訊息堆積、處理能力與容量風險">Consumer Lag</a></td>
          <td>consumer 處理速度落後多少</td>
          <td>queue health、capacity、alert</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/knowledge-cards/dead-letter-queue/" data-link-title="Dead-Letter Queue" data-link-desc="說明 dead-letter queue 如何隔離多次處理失敗的訊息">Dead-Letter Queue</a></td>
          <td>多次處理失敗的訊息如何隔離與診斷</td>
          <td>retry、poison message、incident</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/knowledge-cards/replay-runbook/" data-link-title="Replay Runbook" data-link-desc="說明事件重放前需要控制的範圍、順序、驗證與副作用">Replay Runbook</a></td>
          <td>事件重放時如何控制範圍、順序與副作用</td>
          <td>migration、事故復原、補資料</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/knowledge-cards/duplicate-delivery/" data-link-title="Duplicate Delivery" data-link-desc="說明同一個訊息被處理多次時如何保持結果穩定">重複投遞</a></td>
          <td>同一個工作被處理多次時如何保持結果穩定</td>
          <td>at-least-once、idempotency</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/knowledge-cards/idempotency/" data-link-title="Idempotency" data-link-desc="說明同一操作執行多次時如何保持結果一致">Idempotency</a></td>
          <td>同一操作多次執行時如何保持結果穩定</td>
          <td>retry、payment、worker</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/knowledge-cards/outbox-pattern/" data-link-title="Outbox Pattern" data-link-desc="說明資料庫狀態變更與事件發布如何透過 outbox 維持一致">Outbox Pattern</a></td>
          <td>資料變更與事件發布如何維持一致</td>
          <td>transaction、broker</td>
      </tr>
  </tbody>
</table>
<h2 id="遷移與資料同步">遷移與資料同步</h2>
<table>
  <thead>
      <tr>
          <th>卡片</th>
          <th>核心問題</th>
          <th>常見出現位置</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td><a href="/blog/backend/knowledge-cards/online-migration/" data-link-title="Online Migration" data-link-desc="說明服務持續接流量時如何完成資料或 schema 遷移">Online Migration</a></td>
          <td>服務持續接流量時如何遷移資料</td>
          <td>database、release</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/knowledge-cards/cutover-switchover/" data-link-title="Cutover / Switchover" data-link-desc="說明遷移期間如何把正式流量切到新路徑">Cutover / Switchover</a></td>
          <td>正式流量如何切到新路徑</td>
          <td>migration、feature flag</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/knowledge-cards/fallback-plan/" data-link-title="Fallback Plan" data-link-desc="說明變更失敗時如何回到可接受狀態">Fallback Plan</a></td>
          <td>變更失敗時如何回到可接受狀態</td>
          <td>release、migration</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/knowledge-cards/change-data-capture/" data-link-title="Change Data Capture" data-link-desc="說明資料變更如何被捕捉並傳送到其他系統">Change Data Capture</a></td>
          <td>資料變更如何被捕捉並傳送</td>
          <td>CDC、event stream</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/knowledge-cards/replication-lag/" data-link-title="Replication Lag" data-link-desc="說明資料副本落後正式來源多久，以及它如何影響讀取正確性">Replication Lag</a></td>
          <td>副本落後正式來源多久</td>
          <td>replica、read model</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/knowledge-cards/checkpoint/" data-link-title="Checkpoint" data-link-desc="說明長時間處理流程如何記錄可恢復進度">Checkpoint</a></td>
          <td>長流程如何記錄可恢復進度</td>
          <td>backfill、consumer</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/knowledge-cards/backfill/" data-link-title="Backfill" data-link-desc="說明如何為既有資料補上新欄位、新索引或新衍生狀態">Backfill</a></td>
          <td>既有資料如何補上新欄位或新狀態</td>
          <td>migration、repair</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/knowledge-cards/dual-write/" data-link-title="Dual Write" data-link-desc="說明同一變更同時寫入兩個系統時的一致性風險">Dual Write</a></td>
          <td>同一變更同時寫兩個系統的風險</td>
          <td>migration、split service</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/knowledge-cards/shadow-read/" data-link-title="Shadow Read" data-link-desc="說明正式讀取仍走舊路徑時如何暗中讀新路徑比對結果">Shadow Read</a></td>
          <td>正式讀舊路徑時如何暗中比對新路徑</td>
          <td>cutover、validation</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/knowledge-cards/correctness-check/" data-link-title="Correctness Check" data-link-desc="說明遷移或重構期間如何驗證新舊結果是否符合規則">Correctness Check</a></td>
          <td>新舊結果如何依規則比對</td>
          <td>migration、refactor</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/knowledge-cards/data-completeness/" data-link-title="Data Completeness" data-link-desc="說明資料是否完整到足以支持查詢、遷移與決策">Data Completeness</a></td>
          <td>資料是否完整到足以支持目標用途</td>
          <td>migration、audit</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/knowledge-cards/data-reconciliation/" data-link-title="Data Reconciliation" data-link-desc="說明多個資料來源不一致時如何比對、修復與留下證據">Data Reconciliation</a></td>
          <td>多來源差異如何比對與修復</td>
          <td>payment、eventual consistency</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/knowledge-cards/replication-slot/" data-link-title="Replication Slot" data-link-desc="說明邏輯複製如何用 slot 追蹤消費進度，並對來源端造成保留壓力">Replication Slot</a></td>
          <td>邏輯複製如何追蹤進度並保留 WAL</td>
          <td>CDC、slot lag、磁碟壓力</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/knowledge-cards/conflict-resolution/" data-link-title="Conflict Resolution" data-link-desc="說明並發或離線寫入產生衝突時，如何偵測、呈現與合併成可接受狀態">Conflict Resolution</a></td>
          <td>並發或離線寫入衝突如何合併</td>
          <td>LWW、欄位合併、CRDT</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/knowledge-cards/logical-replication/" data-link-title="Logical Replication" data-link-desc="說明以表為粒度解碼 row-level 變更的複製方式，對照 byte-level 的實體複製">Logical Replication</a></td>
          <td>row-level 變更如何以表為粒度複製</td>
          <td>physical、CDC、跨版本</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/knowledge-cards/replica-identity/" data-link-title="Replica Identity" data-link-desc="說明 row-level 變更事件如何帶穩定 key，讓下游能正確套用 update 與 delete">Replica Identity</a></td>
          <td>變更事件如何帶穩定 key 以套用 update/delete</td>
          <td>CDC、primary key、row image</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/knowledge-cards/gtid/" data-link-title="GTID" data-link-desc="說明全域交易識別碼如何讓複製進度與故障切換不依賴實體 log 位置">GTID</a></td>
          <td>複製進度如何用全域交易識別碼表示</td>
          <td>replication、failover、binlog</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/knowledge-cards/replication-channel/" data-link-title="Replication Channel" data-link-desc="說明多來源複製中，每個來源對應的獨立複製通道如何成為隔離單位">Replication Channel</a></td>
          <td>多來源複製如何用獨立通道隔離</td>
          <td>multi-source、per-channel lag</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/knowledge-cards/tombstone/" data-link-title="Tombstone" data-link-desc="說明刪除如何用一筆標記記錄下來，讓刪除事件能跨副本與裝置傳播">Tombstone</a></td>
          <td>刪除如何用標記跨副本與裝置傳播</td>
          <td>delete propagation、sync、CRDT</td>
      </tr>
  </tbody>
</table>
<h2 id="可觀測性與可靠性">可觀測性與可靠性</h2>
<table>
  <thead>
      <tr>
          <th>卡片</th>
          <th>核心問題</th>
          <th>常見出現位置</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td><a href="/blog/backend/knowledge-cards/log/" data-link-title="Log" data-link-desc="說明 log 如何記錄單一事件的上下文並支援事故排查">Log</a></td>
          <td>單一事件如何留下可搜尋的上下文</td>
          <td>incident、debug、audit</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/knowledge-cards/log-schema/" data-link-title="Log Schema" data-link-desc="說明結構化 log 欄位如何支援搜尋、關聯與事故排查">Log Schema</a></td>
          <td>log 欄位如何支援搜尋與關聯</td>
          <td>structured log、incident</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/knowledge-cards/metrics/" data-link-title="Metrics" data-link-desc="說明指標如何描述服務趨勢、容量與健康狀態">Metrics</a></td>
          <td>指標如何描述趨勢、容量與健康</td>
          <td>Prometheus、dashboard</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/knowledge-cards/histogram/" data-link-title="Histogram" data-link-desc="說明 histogram 如何用分桶統計延遲、大小與分布">Histogram</a></td>
          <td>如何用分桶統計延遲與分布</td>
          <td>latency、SLO</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/knowledge-cards/bucket/" data-link-title="Bucket" data-link-desc="說明 histogram 分桶如何決定觀測解析度與成本">Bucket</a></td>
          <td>histogram 分桶如何影響解析度</td>
          <td>metrics、cost</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/knowledge-cards/percentile/" data-link-title="Percentile" data-link-desc="說明 p95 與 p99 如何描述長尾延遲與使用者體驗">Percentile</a></td>
          <td>p95 / p99 如何描述長尾延遲</td>
          <td>latency、UX</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/knowledge-cards/metric-cardinality/" data-link-title="Metric Cardinality" data-link-desc="說明 metric label 組合數量如何影響觀測成本與查詢穩定性">Metric Cardinality</a></td>
          <td>label 組合數如何影響成本</td>
          <td>metrics、storage、query</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/knowledge-cards/trace/" data-link-title="Trace" data-link-desc="說明 trace 如何重建跨服務請求的路徑、耗時與依賴關係">Trace</a></td>
          <td>跨服務流程如何重建路徑與耗時</td>
          <td>tracing、dependency</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/knowledge-cards/trace-context/" data-link-title="Trace Context" data-link-desc="說明跨服務 request 如何用 trace context 串起路徑與耗時">Trace Context</a></td>
          <td>跨服務 request 如何串起路徑</td>
          <td>tracing、OpenTelemetry</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/knowledge-cards/trace-id/" data-link-title="Trace ID" data-link-desc="說明分散式追蹤中同一條呼叫路徑的識別碼">Trace ID</a></td>
          <td>同一條 trace 的識別碼</td>
          <td>tracing、log correlation</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/knowledge-cards/span/" data-link-title="Span" data-link-desc="說明 trace 中一段工作如何記錄耗時、狀態與關聯">Span</a></td>
          <td>trace 中一段工作如何記錄耗時</td>
          <td>tracing、dependency</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/knowledge-cards/correlation-id/" data-link-title="Correlation ID" data-link-desc="說明跨事件或跨服務的關聯識別碼如何支援排障">Correlation ID</a></td>
          <td>跨事件與跨服務如何關聯業務流程</td>
          <td>order、payment、queue</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/knowledge-cards/request-id/" data-link-title="Request ID" data-link-desc="說明單次 request 的識別碼如何支援 log 搜尋與問題定位">Request ID</a></td>
          <td>單次 request 如何被追蹤</td>
          <td>API、support</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/knowledge-cards/dashboard/" data-link-title="Dashboard" data-link-desc="說明 dashboard 如何把關鍵訊號組成可判讀的服務狀態畫面">Dashboard</a></td>
          <td>多個觀測訊號如何組成服務狀態畫面</td>
          <td>incident、capacity、SLO</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/knowledge-cards/sli-slo/" data-link-title="SLI / SLO" data-link-desc="說明服務品質指標與服務品質目標如何連接產品承諾">SLI / SLO</a></td>
          <td>服務品質如何連到產品承諾</td>
          <td>alert、incident、error budget</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/knowledge-cards/error-budget/" data-link-title="Error Budget" data-link-desc="說明 SLO 允許的失敗額度如何影響發版與可靠性投入">Error Budget</a></td>
          <td>SLO 允許的失敗額度如何決策</td>
          <td>release、reliability</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/knowledge-cards/burn-rate/" data-link-title="Burn Rate" data-link-desc="說明 error budget 消耗速度如何支援告警與事故分級">Burn Rate</a></td>
          <td>error budget 消耗速度如何告警</td>
          <td>SLO alert</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/knowledge-cards/sampling/" data-link-title="Sampling" data-link-desc="說明觀測資料如何抽樣以控制成本並保留診斷能力">Sampling</a></td>
          <td>如何抽樣觀測資料以控制成本</td>
          <td>trace、log</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/knowledge-cards/alert/" data-link-title="Alert" data-link-desc="說明 alert 如何把需要處理的服務症狀轉成可行動通知">Alert</a></td>
          <td>服務症狀如何轉成可行動通知</td>
          <td>on-call、SLO、incident</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/knowledge-cards/runbook/" data-link-title="Runbook" data-link-desc="說明 runbook 如何把事故判斷與操作步驟標準化">Runbook</a></td>
          <td>事故判斷與操作步驟如何標準化</td>
          <td>on-call、incident、replay</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/knowledge-cards/alert-runbook/" data-link-title="Alert Runbook" data-link-desc="說明告警如何連到可執行的排障與恢復流程">Alert Runbook</a></td>
          <td>告警如何連到可執行排障流程</td>
          <td>on-call、dashboard</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/knowledge-cards/symptom-based-alert/" data-link-title="Symptom-Based Alert" data-link-desc="說明告警應優先偵測使用者可感知症狀">Symptom-Based Alert</a></td>
          <td>告警如何優先偵測產品症狀</td>
          <td>SLO、on-call</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/knowledge-cards/runbook-link/" data-link-title="Runbook Link" data-link-desc="說明告警與 dashboard 如何直接連到處理流程">Runbook Link</a></td>
          <td>告警如何直接連到處理流程</td>
          <td>alert、dashboard</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/knowledge-cards/alert-fatigue/" data-link-title="Alert Fatigue" data-link-desc="說明過多低品質告警如何降低 on-call 反應品質">Alert Fatigue</a></td>
          <td>低品質告警如何降低反應品質</td>
          <td>on-call、alert policy</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/knowledge-cards/degradation/" data-link-title="Degradation" data-link-desc="說明服務部分能力失效時如何保留核心功能與控制風險">降級</a></td>
          <td>服務部分能力失效時如何保留核心功能</td>
          <td>failover、fallback、capacity</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/knowledge-cards/circuit-breaker/" data-link-title="Circuit Breaker" data-link-desc="說明下游持續失敗時如何暫停呼叫並保護系統">Circuit Breaker</a></td>
          <td>下游持續失敗時如何暫停呼叫</td>
          <td>timeout、fallback、degradation</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/knowledge-cards/failover/" data-link-title="Failover" data-link-desc="說明主要服務或節點失效時如何切換到備援能力">Failover</a></td>
          <td>主要路徑失效時如何切到備援</td>
          <td>HA、region、provider</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/knowledge-cards/autoscaling/" data-link-title="Autoscaling" data-link-desc="說明系統如何依負載自動調整服務實例數量">Autoscaling</a></td>
          <td>容量如何依指標自動擴縮</td>
          <td>HPA、capacity、traffic burst</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/knowledge-cards/rolling-update/" data-link-title="Rolling Update" data-link-desc="說明逐批替換服務版本的發版策略與風險控制">Rolling Update</a></td>
          <td>版本如何逐批替換並維持可用</td>
          <td>deployment、release</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/knowledge-cards/service-registry/" data-link-title="Service Registry" data-link-desc="說明服務實例如何被註冊、維護與摘除">Service Registry</a></td>
          <td>服務實例如何被註冊、維護與摘除</td>
          <td>heartbeat、TTL、metadata</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/knowledge-cards/service-discovery/" data-link-title="Service Discovery" data-link-desc="說明服務實例如何被查找與路由">Service Discovery</a></td>
          <td>服務實例如何被查找與路由</td>
          <td>registry、DNS、load balancing</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/knowledge-cards/downtime/" data-link-title="Downtime" data-link-desc="說明服務中斷時需要評估的產品後果、資料保護與復原順序">停機</a></td>
          <td>服務中斷時要先保護哪些產品結果</td>
          <td>incident、SLO、deployment</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/knowledge-cards/readiness/" data-link-title="Readiness" data-link-desc="說明 instance 何時可以安全接收流量，以及 readiness 如何和部署平台協作">Readiness</a></td>
          <td>instance 何時可以安全接收流量</td>
          <td>Kubernetes、load balancer、rollout</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/knowledge-cards/health-check-liveness/" data-link-title="Liveness" data-link-desc="說明平台如何判斷 process 是否仍然存活，以及何時應重啟">Liveness</a></td>
          <td>平台如何判斷 process 是否仍然存活</td>
          <td>Kubernetes、systemd</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/knowledge-cards/graceful-shutdown/" data-link-title="Graceful Shutdown" data-link-desc="說明服務停止前如何排空流量、完成工作與保存狀態">Graceful Shutdown</a></td>
          <td>instance 停止前如何排空流量與保存狀態</td>
          <td>deployment、worker、long connection</td>
      </tr>
  </tbody>
</table>
<h2 id="效能工程與容量規劃">效能工程與容量規劃</h2>
<table>
  <thead>
      <tr>
          <th>卡片</th>
          <th>核心問題</th>
          <th>常見出現位置</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td><a href="/blog/backend/knowledge-cards/little-law/" data-link-title="Little&#39;s Law" data-link-desc="說明系統內並發數、到達率與逗留時間三者的數學關係">Little&rsquo;s Law</a></td>
          <td>並發、到達率、逗留時間如何相互推導</td>
          <td>capacity、saturation、SLO</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/knowledge-cards/universal-scalability-law/" data-link-title="Universal Scalability Law (USL)" data-link-desc="說明系統擴容到一定規模後吞吐反而下降的數學模型">Universal Scalability Law</a></td>
          <td>擴容到某點後吞吐反而下降的數學原因</td>
          <td>scalability、coordinator、consensus</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/knowledge-cards/saturation-point/" data-link-title="Saturation Point" data-link-desc="說明系統從線性穩態進入 latency 指數成長區的關鍵流量點">Saturation Point</a></td>
          <td>latency 進入指數成長的臨界流量</td>
          <td>knee、capacity、headroom</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/knowledge-cards/use-method/" data-link-title="USE Method" data-link-desc="Brendan Gregg 提出的資源層 Utilization / Saturation / Errors 三維度量測法">USE Method</a></td>
          <td>資源層 Utilization / Saturation / Errors</td>
          <td>bottleneck、resource、capacity</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/knowledge-cards/red-method/" data-link-title="RED Method" data-link-desc="Tom Wilkie 提出的請求層 Rate / Errors / Duration 三維度量測法">RED Method</a></td>
          <td>請求層 Rate / Errors / Duration</td>
          <td>SLO、latency、request</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/knowledge-cards/workload-model/" data-link-title="Workload Model" data-link-desc="描述 production traffic 形狀的可重播模型 — 容量規劃跟壓測的共同輸入">Workload Model</a></td>
          <td>production traffic shape 如何量化重播</td>
          <td>load test、capacity、forecast</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/knowledge-cards/tail-latency/" data-link-title="Tail Latency" data-link-desc="說明 p99 / p999 等長尾延遲為何比平均延遲更能反映 saturation">Tail Latency</a></td>
          <td>p99 / p999 為何比平均更能反映 saturation</td>
          <td>SLO、GC、cross-zone</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/knowledge-cards/hot-partition/" data-link-title="Hot Partition" data-link-desc="說明分散式 KV / OLTP 中、單一 partition 流量遠超其他的容量問題">Hot Partition</a></td>
          <td>單一 partition 流量過熱、名義容量達不到</td>
          <td>DynamoDB、partition key、saturation</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/knowledge-cards/peak-forecast/" data-link-title="Peak Forecast" data-link-desc="說明預期峰值流量的預測方法 — 容量規劃的第一個輸入">Peak Forecast</a></td>
          <td>預期峰值如何預測 — 容量公式輸入</td>
          <td>capacity、event、growth</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/knowledge-cards/headroom-budget/" data-link-title="Headroom Budget" data-link-desc="說明容量規劃中為應付異常 burst &#43; AZ 故障 &#43; forecast 誤差的安全餘量">Headroom Budget</a></td>
          <td>容量規劃的安全餘量</td>
          <td>capacity、AZ failover、forecast 誤差</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/knowledge-cards/growth-curve/" data-link-title="Growth Curve" data-link-desc="說明用戶 / 流量隨時間成長的五種典型形狀、影響容量規劃方法">Growth Curve</a></td>
          <td>用戶 / 流量成長的五種形狀</td>
          <td>linear、step、exponential、cyclical</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/knowledge-cards/predictive-scaling/" data-link-title="Predictive Scaling" data-link-desc="說明用歷史模式或 ML 模型預測流量、提前擴容的 autoscaler 模式">Predictive Scaling</a></td>
          <td>根據預測提前擴容</td>
          <td>autoscaler、ML、daily pattern</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/knowledge-cards/scheduled-scaling/" data-link-title="Scheduled Scaling" data-link-desc="說明按已知時間表預先擴容的 autoscaler 模式">Scheduled Scaling</a></td>
          <td>按已知時間表預先擴容</td>
          <td>event、pre-scaling、Black Friday</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/knowledge-cards/shadow-traffic/" data-link-title="Shadow Traffic" data-link-desc="把 production traffic 複製到新版本驗證、但不返回結果給用戶的測試模式">Shadow Traffic</a></td>
          <td>production traffic 複製到新版本驗證</td>
          <td>production validation、traffic mirror</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/knowledge-cards/dark-launch/" data-link-title="Dark Launch" data-link-desc="新功能上線但暫不開放 UI 入口、走 production traffic 但對用戶不可見的發布模式">Dark Launch</a></td>
          <td>程式碼上線但 UI 入口暫不開放</td>
          <td>feature flag、production validation</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/knowledge-cards/canary-perf-check/" data-link-title="Canary Perf Check" data-link-desc="canary release 中針對 latency / throughput 而非 error rate 的退化檢查">Canary Perf Check</a></td>
          <td>canary release 中的 latency 退化檢查</td>
          <td>canary、release gate、rollback</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/knowledge-cards/profile-diff/" data-link-title="Profile Diff" data-link-desc="對比兩次 profile（如 release candidate vs baseline）找出 hottest 變化">Profile Diff</a></td>
          <td>比較兩次 profile 找退化原因</td>
          <td>release、CPU、memory、lock</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/knowledge-cards/continuous-profiling/" data-link-title="Continuous Profiling" data-link-desc="在 production 持續取得低 overhead profile 的觀察方法">Continuous Profiling</a></td>
          <td>production 持續取低 overhead profile</td>
          <td>flame graph、observability、tracing</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/knowledge-cards/cost-per-request/" data-link-title="Cost Per Request" data-link-desc="把雲端成本拆到單一 API 請求的 unit economics 模型">Cost Per Request</a></td>
          <td>雲端成本拆到單一請求的 unit economics</td>
          <td>FinOps、capacity、TCO</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/knowledge-cards/performance-budget/" data-link-title="Performance Budget" data-link-desc="跟 error budget 同類概念、但用於 latency / throughput 退化的可控額度">Performance Budget</a></td>
          <td>跟 error budget 並列的效能退化額度</td>
          <td>SLO、release freeze、burn rate</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/knowledge-cards/latency-budget/" data-link-title="Latency Budget" data-link-desc="把 user-perceived latency 拆到每個 stage 的配額、反推架構選擇">Latency Budget</a></td>
          <td>end-to-end latency 拆到每 stage 的配額</td>
          <td>Little&rsquo;s Law、stage、reverse calculation</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/knowledge-cards/slo-baseline-drift/" data-link-title="SLO Baseline Drift" data-link-desc="SLO baseline 因業務變化 / surge / 架構改動而需要重新校準的現象">SLO Baseline Drift</a></td>
          <td>SLO baseline 因業務變化要重新校準</td>
          <td>review、surge、product change</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/knowledge-cards/olap-offload/" data-link-title="OLAP Offload" data-link-desc="說明如何把分析型查詢從 OLTP 主庫卸載，以保護線上交易效能">OLAP Offload</a></td>
          <td>分析查詢如何從 OLTP 主庫卸載</td>
          <td>replica、資料倉儲、CDC</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/knowledge-cards/per-connection-memory/" data-link-title="Per-Connection Memory" data-link-desc="說明每條連線或每個操作的記憶體用量如何隨並發數放大">Per-Connection Memory</a></td>
          <td>每連線記憶體如何隨並發數放大</td>
          <td>sort/join buffer、OOM、連線數</td>
      </tr>
  </tbody>
</table>
<h2 id="事故處理與復盤">事故處理與復盤</h2>
<table>
  <thead>
      <tr>
          <th>卡片</th>
          <th>核心問題</th>
          <th>常見出現位置</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td><a href="/blog/backend/knowledge-cards/on-call/" data-link-title="On-Call" data-link-desc="說明值班制度如何承接告警、事故分級與升級流程">On-Call</a></td>
          <td>值班制度如何承接告警與事故流程</td>
          <td>paging、handover、incident</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/knowledge-cards/handover-protocol/" data-link-title="Handover Protocol" data-link-desc="說明事故與值班交接時要傳遞哪些資訊、責任與完成條件">Handover Protocol</a></td>
          <td>值班或事故責任如何安全交接</td>
          <td>on-call、escalation、incident</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/knowledge-cards/playbook/" data-link-title="Playbook" data-link-desc="說明場景化處置腳本如何降低事故處理不確定性">Playbook</a></td>
          <td>場景化處置如何快速啟動與執行</td>
          <td>incident workflow、recovery</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/knowledge-cards/ci-pipeline/" data-link-title="CI Pipeline" data-link-desc="說明持續整合流程如何在合併前驗證品質與相容性">CI Pipeline</a></td>
          <td>合併前如何自動驗證品質與相容性</td>
          <td>tests、checks、merge gate</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/knowledge-cards/load-test/" data-link-title="Load Test" data-link-desc="說明在預期流量下驗證容量、延遲與降級策略的測試">Load Test</a></td>
          <td>預期流量下如何驗證容量與延遲</td>
          <td>performance、SLO、capacity</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/knowledge-cards/chaos-test/" data-link-title="Chaos Test" data-link-desc="說明透過受控故障注入驗證系統在異常條件下的恢復能力">Chaos Test</a></td>
          <td>受控故障注入如何驗證韌性</td>
          <td>resilience、failover、runbook</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/knowledge-cards/game-day/" data-link-title="Game Day" data-link-desc="說明事故演練如何驗證流程、工具與團隊協作">Game Day</a></td>
          <td>事故演練如何驗證流程與協作</td>
          <td>drill、readiness、training</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/knowledge-cards/incident-severity/" data-link-title="Incident Severity" data-link-desc="說明事故分級如何把產品影響轉成對應處置節奏">Incident Severity</a></td>
          <td>事故如何依產品影響分級</td>
          <td>on-call、incident、SLO</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/knowledge-cards/incident-command-system/" data-link-title="Incident Command System" data-link-desc="說明事故期間的指揮角色、決策邊界與協作方式">Incident Command System</a></td>
          <td>事故期間如何分配指揮與執行角色</td>
          <td>commander、scribe、owner</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/knowledge-cards/incident-communication-channel/" data-link-title="Incident Communication Channel" data-link-desc="說明事故期間內外部溝通要使用哪些固定通道與節奏">Incident Communication Channel</a></td>
          <td>事故期間如何同步對內對外資訊</td>
          <td>internal chat、status update、bridge</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/knowledge-cards/escalation-policy/" data-link-title="Escalation Policy" data-link-desc="說明事故升級鏈與值班轉接規則">Escalation Policy</a></td>
          <td>事故無回應或無進展時如何升級</td>
          <td>on-call、paging、handover</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/knowledge-cards/incident-timeline/" data-link-title="Incident Timeline" data-link-desc="說明事故時間線如何支援判斷、溝通與復盤">Incident Timeline</a></td>
          <td>事故事件如何形成一致時間軸</td>
          <td>incident log、communication</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/knowledge-cards/evidence-package/" data-link-title="Evidence Package" data-link-desc="說明觀測、驗證與事故流程如何把證據包成可交接、可回放的 artifact">Evidence Package</a></td>
          <td>觀測與事故證據如何交接與回放</td>
          <td>observability、verification、PIR</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/knowledge-cards/time-range/" data-link-title="Time Range" data-link-desc="說明證據、查詢與事故判讀如何用時間窗保留可回放上下文">Time Range</a></td>
          <td>證據如何保留明確時間窗</td>
          <td>evidence、incident timeline</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/knowledge-cards/query-link/" data-link-title="Query Link" data-link-desc="說明證據包如何保存可重跑查詢入口，而不是只保留截圖或口頭結論">Query Link</a></td>
          <td>證據如何保留可重跑查詢入口</td>
          <td>evidence、handoff</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/knowledge-cards/data-quality/" data-link-title="Data Quality" data-link-desc="說明證據欄位如何標示 completeness、freshness、sampling 與資料限制">Data Quality</a></td>
          <td>證據如何標示完整度與限制</td>
          <td>evidence、sampling、freshness</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/knowledge-cards/confidence/" data-link-title="Confidence" data-link-desc="說明證據包如何標示 confirmed、suspected 或 needs follow-up 的判讀信心">Confidence</a></td>
          <td>證據如何標示判讀信心等級</td>
          <td>evidence、gate decision</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/knowledge-cards/known-gap/" data-link-title="Known Gap" data-link-desc="說明證據包如何明確保存已知缺口，避免下游高估證據完整性">Known Gap</a></td>
          <td>證據如何保存已知缺口</td>
          <td>evidence、PIR、readiness</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/knowledge-cards/incident-decision-log/" data-link-title="Incident Decision Log" data-link-desc="說明事故期間如何保留決策、證據、owner 與回退條件">Incident Decision Log</a></td>
          <td>事故決策如何保存證據與回退條件</td>
          <td>IC handoff、PIR、status update</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/knowledge-cards/steady-state/" data-link-title="Steady State" data-link-desc="說明可靠性實驗與事故恢復如何定義系統應維持的可接受狀態">Steady State</a></td>
          <td>實驗與事故恢復如何定義成功狀態</td>
          <td>chaos、DR、recovery</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/knowledge-cards/blast-radius/" data-link-title="Blast Radius" data-link-desc="說明事故影響面如何估算與隔離">Blast Radius</a></td>
          <td>故障影響面如何估算與隔離</td>
          <td>dependency、shared resource</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/knowledge-cards/rollback-strategy/" data-link-title="Rollback Strategy" data-link-desc="說明事故期間如何判斷回滾、回切與暫停變更">Rollback Strategy</a></td>
          <td>事故期間何時回滾與回切</td>
          <td>deployment、release gate</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/knowledge-cards/post-incident-review/" data-link-title="Post-Incident Review" data-link-desc="說明事故後如何完成復盤、學習與改進閉環">Post-Incident Review</a></td>
          <td>事故後如何形成改進閉環</td>
          <td>retrospective、action items</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/knowledge-cards/rca/" data-link-title="RCA" data-link-desc="說明根因分析如何區分觸發事件、系統弱點與防線缺口">RCA</a></td>
          <td>根因分析如何從證據推導改進</td>
          <td>timeline、control gap</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/knowledge-cards/rto/" data-link-title="RTO" data-link-desc="說明恢復時間目標如何約束事故回復策略">RTO</a></td>
          <td>服務回復時間目標如何定義</td>
          <td>SLA/SLO、DR</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/knowledge-cards/rpo/" data-link-title="RPO" data-link-desc="說明恢復點目標如何定義可接受資料損失範圍">RPO</a></td>
          <td>可接受資料損失窗口如何定義</td>
          <td>backup、replication</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/knowledge-cards/mttr/" data-link-title="MTTR" data-link-desc="說明平均修復時間如何作為事故處理能力指標">MTTR</a></td>
          <td>平均修復時間如何反映處置能力</td>
          <td>incident metrics、review</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/knowledge-cards/point-in-time-recovery/" data-link-title="Point-in-Time Recovery" data-link-desc="說明如何用完整備份加上後續變更日誌，把資料庫還原到任意時間點">Point-in-Time Recovery</a></td>
          <td>資料如何還原到過去任意時間點</td>
          <td>base backup、WAL、RPO</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/knowledge-cards/corruption-recovery/" data-link-title="Corruption Recovery" data-link-desc="說明資料損毀事故如何先辨識來源、保全證據，再決定修復或還原">Corruption Recovery</a></td>
          <td>資料損毀事故如何辨識來源並處置</td>
          <td>checksum、evidence、restore</td>
      </tr>
  </tbody>
</table>
<h2 id="資安與資料保護">資安與資料保護</h2>
<table>
  <thead>
      <tr>
          <th>卡片</th>
          <th>核心問題</th>
          <th>常見出現位置</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td><a href="/blog/backend/knowledge-cards/authorization/" data-link-title="Authorization" data-link-desc="說明授權如何判斷誰能對哪些資源執行哪些操作">Authorization</a></td>
          <td>誰能對哪些資源執行哪些操作</td>
          <td>RBAC、ABAC、tenant</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/knowledge-cards/authentication/" data-link-title="Authentication" data-link-desc="說明系統如何確認呼叫者身份">Authentication</a></td>
          <td>系統如何確認呼叫者身份</td>
          <td>login、API key、mTLS</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/knowledge-cards/credential/" data-link-title="Credential" data-link-desc="整理身分驗證與系統存取用秘密資料">Credential</a></td>
          <td>身分與系統存取用秘密如何保存與輪替</td>
          <td>API key、password、private key</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/knowledge-cards/iam/" data-link-title="IAM" data-link-desc="說明 identity and access management 如何集中管理身分、角色與權限">IAM</a></td>
          <td>身分與權限如何集中治理</td>
          <td>SSO、roles、policy</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/knowledge-cards/bola-idor/" data-link-title="BOLA / IDOR" data-link-desc="說明物件層授權缺失如何讓使用者存取不屬於自己的資料">BOLA / IDOR</a></td>
          <td>使用者如何被限制只能存取授權物件</td>
          <td>API、resource ID</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/knowledge-cards/bopla/" data-link-title="BOPLA" data-link-desc="說明屬性層授權缺失如何讓使用者讀寫不該暴露的欄位">BOPLA</a></td>
          <td>欄位層級如何授權讀寫</td>
          <td>DTO、field policy</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/knowledge-cards/mass-assignment/" data-link-title="Mass Assignment" data-link-desc="說明自動綁定 request 欄位如何造成未授權欄位被修改">Mass Assignment</a></td>
          <td>自動綁定欄位如何造成未授權修改</td>
          <td>API、ORM</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/knowledge-cards/excessive-data-exposure/" data-link-title="Excessive Data Exposure" data-link-desc="說明 API 回傳過多資料如何增加敏感資訊外洩風險">Excessive Data Exposure</a></td>
          <td>API 回傳過多資料如何增加外洩風險</td>
          <td>response、DTO</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/knowledge-cards/unrestricted-resource-consumption/" data-link-title="Unrestricted Resource Consumption" data-link-desc="說明缺少資源限制如何讓 API 被濫用或拖垮">Unrestricted Resource Consumption</a></td>
          <td>API 如何限制昂貴資源使用</td>
          <td>upload、export、query</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/knowledge-cards/function-level-authorization/" data-link-title="Function-Level Authorization" data-link-desc="說明功能操作本身也需要授權，不只資源 ID 需要授權">Function-Level Authorization</a></td>
          <td>功能操作本身如何授權</td>
          <td>refund、export、admin</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/knowledge-cards/tenant-boundary/" data-link-title="Tenant Boundary" data-link-desc="說明多租戶系統如何隔離不同客戶或組織的資料與資源">Tenant Boundary</a></td>
          <td>多租戶資料與資源如何隔離</td>
          <td>SaaS、RBAC</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/knowledge-cards/least-privilege/" data-link-title="Least Privilege" data-link-desc="說明身份、服務與人員只應取得完成工作所需的最小權限">Least Privilege</a></td>
          <td>身份如何只取得必要權限</td>
          <td>IAM、database user</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/knowledge-cards/security-misconfiguration/" data-link-title="Security Misconfiguration" data-link-desc="說明錯誤設定如何讓安全控制失效或暴露內部能力">Security Misconfiguration</a></td>
          <td>設定錯誤如何暴露內部能力</td>
          <td>CORS、debug、cloud</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/knowledge-cards/attack-surface/" data-link-title="Attack Surface" data-link-desc="說明系統哪些對外暴露面會被先行探測與枚舉">Attack Surface</a></td>
          <td>系統哪些對外暴露面最先被探測</td>
          <td>public API、admin route、webhook</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/knowledge-cards/trust-boundary/" data-link-title="Trust Boundary" data-link-desc="說明系統哪些位置開始不能沿用原本的信任假設">Trust Boundary</a></td>
          <td>哪些位置要重建信任假設</td>
          <td>auth boundary、tenant、network</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/knowledge-cards/abuse-case/" data-link-title="Abuse Case" data-link-desc="說明合法功能如何被惡意轉用成突破或濫用路徑">Abuse Case</a></td>
          <td>合法功能如何被惡意轉用</td>
          <td>export、invite、reset</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/knowledge-cards/waf/" data-link-title="WAF" data-link-desc="說明 Web Application Firewall 如何在入口層過濾常見攻擊與濫用">WAF</a></td>
          <td>入口層如何過濾常見攻擊與濫用</td>
          <td>edge、bot、attack</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/knowledge-cards/feature-flag/" data-link-title="Feature Flag" data-link-desc="說明如何用可動態開關控制功能曝光與風險">Feature Flag</a></td>
          <td>功能開關如何分離部署與啟用</td>
          <td>rollout、experiment、rollback</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/knowledge-cards/security-exception/" data-link-title="Security Exception" data-link-desc="說明資安風險例外如何以期限、補償控制與關閉條件管理">Security Exception</a></td>
          <td>風險例外如何以期限與關閉條件治理</td>
          <td>risk acceptance、governance</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/knowledge-cards/release-freeze/" data-link-title="Release Freeze" data-link-desc="說明高風險期間如何以凍結策略保護正式環境">Release Freeze</a></td>
          <td>高風險期間如何暫停特定變更</td>
          <td>incident、vulnerability window</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/knowledge-cards/tripwire/" data-link-title="Tripwire" data-link-desc="說明風險決策在條件變化時如何自動回到評估流程">Tripwire</a></td>
          <td>風險決策何時自動回到重評估流程</td>
          <td>threshold、escalation</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/knowledge-cards/allowlist/" data-link-title="Allowlist" data-link-desc="說明如何用明確允許條件控制例外放行範圍">Allowlist</a></td>
          <td>例外放行如何維持可控範圍</td>
          <td>freeze exception、policy control</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/knowledge-cards/input-validation/" data-link-title="Input Validation" data-link-desc="說明進入系統的資料如何先被檢查格式、範圍與語意">Input Validation</a></td>
          <td>入口資料如何檢查格式與語意</td>
          <td>API、webhook</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/knowledge-cards/ssrf/" data-link-title="SSRF" data-link-desc="說明伺服器端請求被濫用時如何存取內部網路或 metadata 服務">SSRF</a></td>
          <td>伺服器端請求如何被濫用</td>
          <td>URL fetch、webhook</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/knowledge-cards/pii/" data-link-title="PII" data-link-desc="說明可識別個人的資料如何影響權限、遮罩、保留與稽核">PII</a></td>
          <td>可識別個人的資料如何保護</td>
          <td>masking、retention</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/knowledge-cards/data-classification/" data-link-title="Data Classification" data-link-desc="說明資料分級如何決定保護、存取、保留與匯出規則">Data Classification</a></td>
          <td>資料分級如何決定保護規則</td>
          <td>security、compliance</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/knowledge-cards/data-masking/" data-link-title="Data Masking" data-link-desc="說明敏感資料如何在顯示、匯出、log 與測試資料中降低暴露">Data Masking</a></td>
          <td>敏感資料如何降低暴露</td>
          <td>export、log、support tool</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/knowledge-cards/secret-management/" data-link-title="Secret Management" data-link-desc="說明 token、key、password 與憑證如何保存、輪替與撤銷">Secret Management</a></td>
          <td>token、key、password 如何保存與輪替</td>
          <td>credential、deployment</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/knowledge-cards/tls-mtls/" data-link-title="TLS / mTLS" data-link-desc="說明傳輸加密與雙向憑證驗證如何保護跨邊界資料流">TLS / mTLS</a></td>
          <td>傳輸加密與雙向身份驗證如何保護資料流</td>
          <td>service-to-service、API</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/knowledge-cards/website-certificate-lifecycle/" data-link-title="Website Certificate Lifecycle" data-link-desc="說明網站 TLS 憑證從簽發到續期與撤銷的全流程責任">Website Certificate Lifecycle</a></td>
          <td>網站憑證從簽發到續期與撤銷如何治理</td>
          <td>HTTPS、edge、ingress</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/knowledge-cards/acme-automation/" data-link-title="ACME Automation" data-link-desc="說明網站憑證如何透過 ACME 自動簽發與續期">ACME Automation</a></td>
          <td>網站憑證如何自動簽發與續期</td>
          <td>Let&rsquo;s Encrypt、DNS-01、HTTP-01</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/knowledge-cards/certificate-chain-trust/" data-link-title="Certificate Chain and Trust Root" data-link-desc="說明網站憑證鏈與信任根如何影響連線可用性與驗證結果">Certificate Chain and Trust Root</a></td>
          <td>憑證鏈與信任根如何影響握手</td>
          <td>intermediate CA、trust store</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/knowledge-cards/certificate-rotation-renewal/" data-link-title="Certificate Rotation and Renewal" data-link-desc="說明網站憑證如何安全續期與輪替以避免停機">Certificate Rotation and Renewal</a></td>
          <td>憑證與私鑰如何不中斷更新</td>
          <td>expiry、zero-downtime</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/knowledge-cards/certificate-revocation/" data-link-title="Certificate Revocation" data-link-desc="說明憑證洩漏或誤發時如何撤銷並控制影響範圍">Certificate Revocation</a></td>
          <td>憑證失效時如何撤銷與替換</td>
          <td>key compromise、incident</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/knowledge-cards/artifact-provenance/" data-link-title="Artifact Provenance" data-link-desc="說明交付物的來源、完整性與簽章關聯如何建立信任">Artifact Provenance</a></td>
          <td>交付物來源與完整性如何建立可驗證信任</td>
          <td>CI、supply chain、release gate</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/knowledge-cards/audit-log/" data-link-title="Audit Log" data-link-desc="說明高風險操作如何留下可追溯、可稽核的紀錄">Audit Log</a></td>
          <td>高風險操作如何留下責任證據</td>
          <td>admin、export、permission</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/knowledge-cards/row-level-security/" data-link-title="Row-Level Security" data-link-desc="說明資料庫如何用 policy 限制同一張表中哪些 row 對某個角色可見或可寫">Row-Level Security</a></td>
          <td>資料庫如何用 policy 過濾可見的 row</td>
          <td>RLS、多租戶、policy</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/knowledge-cards/at-rest-encryption/" data-link-title="At-Rest Encryption" data-link-desc="說明資料落到儲存媒介前的加密層，以及它對應的威脅模型">At-Rest Encryption</a></td>
          <td>落地資料如何在儲存層加密</td>
          <td>tablespace、backup、金鑰</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/knowledge-cards/key-management/" data-link-title="Key Management" data-link-desc="說明加密金鑰如何產生、保存、輪替，以及還原時如何依賴金鑰">Key Management</a></td>
          <td>加密金鑰如何產生、保存與輪替</td>
          <td>KMS、keyring、rotation</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/knowledge-cards/break-glass-access/" data-link-title="Break-Glass Access" data-link-desc="說明緊急情況下臨時授予的高權限存取，如何用工單、時限與事後審查治理">Break-Glass Access</a></td>
          <td>緊急高權限存取如何用工單與時限治理</td>
          <td>emergency、ticket、audit</td>
      </tr>
  </tbody>
</table>
<h2 id="使用方式">使用方式</h2>
<p>知識卡片是章節引用單位。選型文章遇到術語時，應連到對應卡片；服務實體章節需要更深入時，再從卡片延伸到具體工具操作。</p>
<p>卡片先回答概念本質，再放例子與提醒。這個順序讓讀者先知道該概念在系統裡承擔什麼責任，再理解 RabbitMQ、Redis、Kubernetes 或 observability 平台中的具體名稱。</p>
]]></content:encoded></item><item><title>Lua 腳本語言</title><link>https://tarrragon.github.io/blog/linux/dotfile/knowledge-cards/lua-scripting-language/</link><pubDate>Mon, 29 Jun 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/linux/dotfile/knowledge-cards/lua-scripting-language/</guid><description>&lt;p>Lua 是一個輕量級腳本語言，1993 年在巴西開發，名字是葡萄牙語的「月亮」。整個直譯器約 300KB，設計目標是&lt;strong>嵌入到其他程式當配置和擴展語言&lt;/strong>，不是當獨立的通用語言。&lt;/p>
&lt;p>Hyprland（v0.55+ 的配置格式）、Neovim（整個 plugin 和配置生態）、WezTerm（terminal emulator 配置）都用 Lua 作為配置語言。在 dotfile 管理的脈絡裡，Lua 是讀懂和寫好這些工具配置的前提知識。&lt;/p>
&lt;h2 id="配置檔用到的核心語法">配置檔用到的核心語法&lt;/h2>
&lt;h3 id="變數和型別">變數和型別&lt;/h3>





&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-lua" data-lang="lua">&lt;span class="line">&lt;span class="ln">1&lt;/span>&lt;span class="cl">&lt;span class="kd">local&lt;/span> &lt;span class="n">name&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="s2">&amp;#34;hello&amp;#34;&lt;/span> &lt;span class="c1">-- 字串&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">2&lt;/span>&lt;span class="cl">&lt;span class="kd">local&lt;/span> &lt;span class="n">count&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="mi">42&lt;/span> &lt;span class="c1">-- 數字&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">3&lt;/span>&lt;span class="cl">&lt;span class="kd">local&lt;/span> &lt;span class="n">enabled&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="kc">true&lt;/span> &lt;span class="c1">-- 布林&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">4&lt;/span>&lt;span class="cl">&lt;span class="kd">local&lt;/span> &lt;span class="n">nothing&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="kc">nil&lt;/span> &lt;span class="c1">-- 空值（類似其他語言的 null）&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>&lt;code>local&lt;/code> 宣告區域變數。沒有 &lt;code>local&lt;/code> 的變數是全域的，配置檔裡幾乎都該用 &lt;code>local&lt;/code>。&lt;/p>
&lt;h3 id="table唯一的複合資料結構">Table：唯一的複合資料結構&lt;/h3>
&lt;p>Lua 只有一種複合型別——table，同時當 array 和 dictionary 用：&lt;/p>





&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-lua" data-lang="lua">&lt;span class="line">&lt;span class="ln"> 1&lt;/span>&lt;span class="cl">&lt;span class="c1">-- 當 array（index 從 1 開始，不是 0）&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 2&lt;/span>&lt;span class="cl">&lt;span class="kd">local&lt;/span> &lt;span class="n">fruits&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="p">{&lt;/span> &lt;span class="s2">&amp;#34;apple&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="s2">&amp;#34;banana&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="s2">&amp;#34;cherry&amp;#34;&lt;/span> &lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 3&lt;/span>&lt;span class="cl">&lt;span class="n">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">fruits&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="mi">1&lt;/span>&lt;span class="p">])&lt;/span> &lt;span class="c1">-- &amp;#34;apple&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 4&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 5&lt;/span>&lt;span class="cl">&lt;span class="c1">-- 當 dictionary&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 6&lt;/span>&lt;span class="cl">&lt;span class="kd">local&lt;/span> &lt;span class="n">config&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 7&lt;/span>&lt;span class="cl"> &lt;span class="n">gaps_in&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="mi">5&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 8&lt;/span>&lt;span class="cl"> &lt;span class="n">border_size&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="mi">2&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 9&lt;/span>&lt;span class="cl"> &lt;span class="n">layout&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="s2">&amp;#34;dwindle&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">10&lt;/span>&lt;span class="cl">&lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">11&lt;/span>&lt;span class="cl">&lt;span class="n">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">config.gaps_in&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="c1">-- 5&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">12&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">13&lt;/span>&lt;span class="cl">&lt;span class="c1">-- 巢狀 table（配置檔最常見的形式）&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">14&lt;/span>&lt;span class="cl">&lt;span class="kd">local&lt;/span> &lt;span class="n">decoration&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">15&lt;/span>&lt;span class="cl"> &lt;span class="n">rounding&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="mi">8&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">16&lt;/span>&lt;span class="cl"> &lt;span class="n">blur&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">17&lt;/span>&lt;span class="cl"> &lt;span class="n">enabled&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="kc">true&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">18&lt;/span>&lt;span class="cl"> &lt;span class="n">size&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="mi">5&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">19&lt;/span>&lt;span class="cl"> &lt;span class="n">passes&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="mi">2&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">20&lt;/span>&lt;span class="cl"> &lt;span class="p">},&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">21&lt;/span>&lt;span class="cl">&lt;span class="p">}&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>Hyprland 的 &lt;code>hl.config()&lt;/code> 接收的就是一個巢狀 table：&lt;/p>





&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-lua" data-lang="lua">&lt;span class="line">&lt;span class="ln">1&lt;/span>&lt;span class="cl">&lt;span class="n">hl.config&lt;/span>&lt;span class="p">({&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">2&lt;/span>&lt;span class="cl"> &lt;span class="n">general&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">3&lt;/span>&lt;span class="cl"> &lt;span class="n">gaps_in&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="mi">5&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">4&lt;/span>&lt;span class="cl"> &lt;span class="n">gaps_out&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="mi">10&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">5&lt;/span>&lt;span class="cl"> &lt;span class="p">},&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">6&lt;/span>&lt;span class="cl"> &lt;span class="n">decoration&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">7&lt;/span>&lt;span class="cl"> &lt;span class="n">rounding&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="mi">8&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">8&lt;/span>&lt;span class="cl"> &lt;span class="p">},&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">9&lt;/span>&lt;span class="cl">&lt;span class="p">})&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h3 id="function">Function&lt;/h3>





&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-lua" data-lang="lua">&lt;span class="line">&lt;span class="ln">1&lt;/span>&lt;span class="cl">&lt;span class="kd">local&lt;/span> &lt;span class="kr">function&lt;/span> &lt;span class="nf">greet&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">who&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">2&lt;/span>&lt;span class="cl"> &lt;span class="kr">return&lt;/span> &lt;span class="s2">&amp;#34;hello &amp;#34;&lt;/span> &lt;span class="o">..&lt;/span> &lt;span class="n">who&lt;/span> &lt;span class="c1">-- .. 是字串串接&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">3&lt;/span>&lt;span class="cl">&lt;span class="kr">end&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">4&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">5&lt;/span>&lt;span class="cl">&lt;span class="c1">-- 匿名 function（Neovim 配置常見）&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">6&lt;/span>&lt;span class="cl">&lt;span class="n">vim.keymap&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">set&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s2">&amp;#34;n&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="s2">&amp;#34;&amp;lt;leader&amp;gt;f&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="kr">function&lt;/span>&lt;span class="p">()&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">7&lt;/span>&lt;span class="cl"> &lt;span class="n">require&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s2">&amp;#34;telescope.builtin&amp;#34;&lt;/span>&lt;span class="p">).&lt;/span>&lt;span class="n">find_files&lt;/span>&lt;span class="p">()&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">8&lt;/span>&lt;span class="cl">&lt;span class="kr">end&lt;/span>&lt;span class="p">)&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h3 id="條件判斷">條件判斷&lt;/h3>





&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-lua" data-lang="lua">&lt;span class="line">&lt;span class="ln">1&lt;/span>&lt;span class="cl">&lt;span class="kr">if&lt;/span> &lt;span class="n">hostname&lt;/span> &lt;span class="o">==&lt;/span> &lt;span class="s2">&amp;#34;work-laptop&amp;#34;&lt;/span> &lt;span class="kr">then&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">2&lt;/span>&lt;span class="cl"> &lt;span class="c1">-- 工作機設定&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">3&lt;/span>&lt;span class="cl">&lt;span class="kr">elseif&lt;/span> &lt;span class="n">hostname&lt;/span> &lt;span class="o">==&lt;/span> &lt;span class="s2">&amp;#34;home-desktop&amp;#34;&lt;/span> &lt;span class="kr">then&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">4&lt;/span>&lt;span class="cl"> &lt;span class="c1">-- 家裡桌機設定&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">5&lt;/span>&lt;span class="cl">&lt;span class="kr">else&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">6&lt;/span>&lt;span class="cl"> &lt;span class="c1">-- 預設&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">7&lt;/span>&lt;span class="cl">&lt;span class="kr">end&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>只有 &lt;code>nil&lt;/code> 和 &lt;code>false&lt;/code> 是 falsy。&lt;code>0&lt;/code> 和 &lt;code>&amp;quot;&amp;quot;&lt;/code> 是 truthy（跟 Python 不同）。&lt;/p>
&lt;h3 id="迴圈">迴圈&lt;/h3>





&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-lua" data-lang="lua">&lt;span class="line">&lt;span class="ln"> 1&lt;/span>&lt;span class="cl">&lt;span class="c1">-- 數字 for（Hyprland 批次產生 workspace keybind）&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 2&lt;/span>&lt;span class="cl">&lt;span class="kr">for&lt;/span> &lt;span class="n">i&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="mi">1&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="mi">9&lt;/span> &lt;span class="kr">do&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 3&lt;/span>&lt;span class="cl"> &lt;span class="n">hl.bind&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s2">&amp;#34;SUPER&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">tostring&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">i&lt;/span>&lt;span class="p">),&lt;/span> &lt;span class="s2">&amp;#34;workspace&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">tostring&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">i&lt;/span>&lt;span class="p">))&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 4&lt;/span>&lt;span class="cl">&lt;span class="kr">end&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 5&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 6&lt;/span>&lt;span class="cl">&lt;span class="c1">-- 遍歷 table&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 7&lt;/span>&lt;span class="cl">&lt;span class="kd">local&lt;/span> &lt;span class="n">tools&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="p">{&lt;/span> &lt;span class="s2">&amp;#34;zsh&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="s2">&amp;#34;git&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="s2">&amp;#34;nvim&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="s2">&amp;#34;tmux&amp;#34;&lt;/span> &lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 8&lt;/span>&lt;span class="cl">&lt;span class="kr">for&lt;/span> &lt;span class="n">_&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">tool&lt;/span> &lt;span class="kr">in&lt;/span> &lt;span class="n">ipairs&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">tools&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="kr">do&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 9&lt;/span>&lt;span class="cl"> &lt;span class="n">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">tool&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">10&lt;/span>&lt;span class="cl">&lt;span class="kr">end&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h3 id="模組化require">模組化（require）&lt;/h3>





&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-lua" data-lang="lua">&lt;span class="line">&lt;span class="ln">1&lt;/span>&lt;span class="cl">&lt;span class="c1">-- hyprland.lua 裡載入同目錄的其他 .lua 檔&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">2&lt;/span>&lt;span class="cl">&lt;span class="n">require&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s2">&amp;#34;keybinds&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="c1">-- 載入 keybinds.lua&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">3&lt;/span>&lt;span class="cl">&lt;span class="n">require&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s2">&amp;#34;rules&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="c1">-- 載入 rules.lua&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">4&lt;/span>&lt;span class="cl">&lt;span class="n">require&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s2">&amp;#34;appearance&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="c1">-- 載入 appearance.lua&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>&lt;code>require()&lt;/code> 是 Lua 原生的模組載入，取代了舊 Hyprland &lt;code>.conf&lt;/code> 格式的 &lt;code>source = ...&lt;/code> 指令。&lt;/p>
&lt;h2 id="為什麼配置工具選-lua">為什麼配置工具選 Lua&lt;/h2>
&lt;p>Lua 被嵌入到配置層的原因是一組特定的 trade-off：&lt;/p>
&lt;ul>
&lt;li>&lt;strong>比 JSON/TOML/YAML 強&lt;/strong>：有變數、迴圈、條件判斷。配置檔可以用 &lt;code>for&lt;/code> 產生重複項目、用 &lt;code>if&lt;/code> 處理機器差異，不需要外部 template engine&lt;/li>
&lt;li>&lt;strong>比 Python/JavaScript 輕&lt;/strong>：300KB 的直譯器可以嵌入 C/C++ 程式，不需要拖一個完整的 runtime&lt;/li>
&lt;li>&lt;strong>沙盒化容易&lt;/strong>：宿主程式可以控制 Lua 能存取哪些 API，限制配置檔的能力範圍&lt;/li>
&lt;/ul>
&lt;p>這也是 Neovim 從 VimScript 遷移到 Lua 的理由——plugin 生態需要一個真正的程式語言（有資料結構、有錯誤處理），但又不能讓配置檔變成一個安全隱患。&lt;/p></description><content:encoded><![CDATA[<p>Lua 是一個輕量級腳本語言，1993 年在巴西開發，名字是葡萄牙語的「月亮」。整個直譯器約 300KB，設計目標是<strong>嵌入到其他程式當配置和擴展語言</strong>，不是當獨立的通用語言。</p>
<p>Hyprland（v0.55+ 的配置格式）、Neovim（整個 plugin 和配置生態）、WezTerm（terminal emulator 配置）都用 Lua 作為配置語言。在 dotfile 管理的脈絡裡，Lua 是讀懂和寫好這些工具配置的前提知識。</p>
<h2 id="配置檔用到的核心語法">配置檔用到的核心語法</h2>
<h3 id="變數和型別">變數和型別</h3>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-lua" data-lang="lua"><span class="line"><span class="ln">1</span><span class="cl"><span class="kd">local</span> <span class="n">name</span> <span class="o">=</span> <span class="s2">&#34;hello&#34;</span>       <span class="c1">-- 字串</span>
</span></span><span class="line"><span class="ln">2</span><span class="cl"><span class="kd">local</span> <span class="n">count</span> <span class="o">=</span> <span class="mi">42</span>            <span class="c1">-- 數字</span>
</span></span><span class="line"><span class="ln">3</span><span class="cl"><span class="kd">local</span> <span class="n">enabled</span> <span class="o">=</span> <span class="kc">true</span>        <span class="c1">-- 布林</span>
</span></span><span class="line"><span class="ln">4</span><span class="cl"><span class="kd">local</span> <span class="n">nothing</span> <span class="o">=</span> <span class="kc">nil</span>         <span class="c1">-- 空值（類似其他語言的 null）</span></span></span></code></pre></div><p><code>local</code> 宣告區域變數。沒有 <code>local</code> 的變數是全域的，配置檔裡幾乎都該用 <code>local</code>。</p>
<h3 id="table唯一的複合資料結構">Table：唯一的複合資料結構</h3>
<p>Lua 只有一種複合型別——table，同時當 array 和 dictionary 用：</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-lua" data-lang="lua"><span class="line"><span class="ln"> 1</span><span class="cl"><span class="c1">-- 當 array（index 從 1 開始，不是 0）</span>
</span></span><span class="line"><span class="ln"> 2</span><span class="cl"><span class="kd">local</span> <span class="n">fruits</span> <span class="o">=</span> <span class="p">{</span> <span class="s2">&#34;apple&#34;</span><span class="p">,</span> <span class="s2">&#34;banana&#34;</span><span class="p">,</span> <span class="s2">&#34;cherry&#34;</span> <span class="p">}</span>
</span></span><span class="line"><span class="ln"> 3</span><span class="cl"><span class="n">print</span><span class="p">(</span><span class="n">fruits</span><span class="p">[</span><span class="mi">1</span><span class="p">])</span>  <span class="c1">-- &#34;apple&#34;</span>
</span></span><span class="line"><span class="ln"> 4</span><span class="cl">
</span></span><span class="line"><span class="ln"> 5</span><span class="cl"><span class="c1">-- 當 dictionary</span>
</span></span><span class="line"><span class="ln"> 6</span><span class="cl"><span class="kd">local</span> <span class="n">config</span> <span class="o">=</span> <span class="p">{</span>
</span></span><span class="line"><span class="ln"> 7</span><span class="cl">    <span class="n">gaps_in</span> <span class="o">=</span> <span class="mi">5</span><span class="p">,</span>
</span></span><span class="line"><span class="ln"> 8</span><span class="cl">    <span class="n">border_size</span> <span class="o">=</span> <span class="mi">2</span><span class="p">,</span>
</span></span><span class="line"><span class="ln"> 9</span><span class="cl">    <span class="n">layout</span> <span class="o">=</span> <span class="s2">&#34;dwindle&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="ln">10</span><span class="cl"><span class="p">}</span>
</span></span><span class="line"><span class="ln">11</span><span class="cl"><span class="n">print</span><span class="p">(</span><span class="n">config.gaps_in</span><span class="p">)</span>  <span class="c1">-- 5</span>
</span></span><span class="line"><span class="ln">12</span><span class="cl">
</span></span><span class="line"><span class="ln">13</span><span class="cl"><span class="c1">-- 巢狀 table（配置檔最常見的形式）</span>
</span></span><span class="line"><span class="ln">14</span><span class="cl"><span class="kd">local</span> <span class="n">decoration</span> <span class="o">=</span> <span class="p">{</span>
</span></span><span class="line"><span class="ln">15</span><span class="cl">    <span class="n">rounding</span> <span class="o">=</span> <span class="mi">8</span><span class="p">,</span>
</span></span><span class="line"><span class="ln">16</span><span class="cl">    <span class="n">blur</span> <span class="o">=</span> <span class="p">{</span>
</span></span><span class="line"><span class="ln">17</span><span class="cl">        <span class="n">enabled</span> <span class="o">=</span> <span class="kc">true</span><span class="p">,</span>
</span></span><span class="line"><span class="ln">18</span><span class="cl">        <span class="n">size</span> <span class="o">=</span> <span class="mi">5</span><span class="p">,</span>
</span></span><span class="line"><span class="ln">19</span><span class="cl">        <span class="n">passes</span> <span class="o">=</span> <span class="mi">2</span><span class="p">,</span>
</span></span><span class="line"><span class="ln">20</span><span class="cl">    <span class="p">},</span>
</span></span><span class="line"><span class="ln">21</span><span class="cl"><span class="p">}</span></span></span></code></pre></div><p>Hyprland 的 <code>hl.config()</code> 接收的就是一個巢狀 table：</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-lua" data-lang="lua"><span class="line"><span class="ln">1</span><span class="cl"><span class="n">hl.config</span><span class="p">({</span>
</span></span><span class="line"><span class="ln">2</span><span class="cl">    <span class="n">general</span> <span class="o">=</span> <span class="p">{</span>
</span></span><span class="line"><span class="ln">3</span><span class="cl">        <span class="n">gaps_in</span> <span class="o">=</span> <span class="mi">5</span><span class="p">,</span>
</span></span><span class="line"><span class="ln">4</span><span class="cl">        <span class="n">gaps_out</span> <span class="o">=</span> <span class="mi">10</span><span class="p">,</span>
</span></span><span class="line"><span class="ln">5</span><span class="cl">    <span class="p">},</span>
</span></span><span class="line"><span class="ln">6</span><span class="cl">    <span class="n">decoration</span> <span class="o">=</span> <span class="p">{</span>
</span></span><span class="line"><span class="ln">7</span><span class="cl">        <span class="n">rounding</span> <span class="o">=</span> <span class="mi">8</span><span class="p">,</span>
</span></span><span class="line"><span class="ln">8</span><span class="cl">    <span class="p">},</span>
</span></span><span class="line"><span class="ln">9</span><span class="cl"><span class="p">})</span></span></span></code></pre></div><h3 id="function">Function</h3>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-lua" data-lang="lua"><span class="line"><span class="ln">1</span><span class="cl"><span class="kd">local</span> <span class="kr">function</span> <span class="nf">greet</span><span class="p">(</span><span class="n">who</span><span class="p">)</span>
</span></span><span class="line"><span class="ln">2</span><span class="cl">    <span class="kr">return</span> <span class="s2">&#34;hello &#34;</span> <span class="o">..</span> <span class="n">who</span>   <span class="c1">-- .. 是字串串接</span>
</span></span><span class="line"><span class="ln">3</span><span class="cl"><span class="kr">end</span>
</span></span><span class="line"><span class="ln">4</span><span class="cl">
</span></span><span class="line"><span class="ln">5</span><span class="cl"><span class="c1">-- 匿名 function（Neovim 配置常見）</span>
</span></span><span class="line"><span class="ln">6</span><span class="cl"><span class="n">vim.keymap</span><span class="p">.</span><span class="n">set</span><span class="p">(</span><span class="s2">&#34;n&#34;</span><span class="p">,</span> <span class="s2">&#34;&lt;leader&gt;f&#34;</span><span class="p">,</span> <span class="kr">function</span><span class="p">()</span>
</span></span><span class="line"><span class="ln">7</span><span class="cl">    <span class="n">require</span><span class="p">(</span><span class="s2">&#34;telescope.builtin&#34;</span><span class="p">).</span><span class="n">find_files</span><span class="p">()</span>
</span></span><span class="line"><span class="ln">8</span><span class="cl"><span class="kr">end</span><span class="p">)</span></span></span></code></pre></div><h3 id="條件判斷">條件判斷</h3>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-lua" data-lang="lua"><span class="line"><span class="ln">1</span><span class="cl"><span class="kr">if</span> <span class="n">hostname</span> <span class="o">==</span> <span class="s2">&#34;work-laptop&#34;</span> <span class="kr">then</span>
</span></span><span class="line"><span class="ln">2</span><span class="cl">    <span class="c1">-- 工作機設定</span>
</span></span><span class="line"><span class="ln">3</span><span class="cl"><span class="kr">elseif</span> <span class="n">hostname</span> <span class="o">==</span> <span class="s2">&#34;home-desktop&#34;</span> <span class="kr">then</span>
</span></span><span class="line"><span class="ln">4</span><span class="cl">    <span class="c1">-- 家裡桌機設定</span>
</span></span><span class="line"><span class="ln">5</span><span class="cl"><span class="kr">else</span>
</span></span><span class="line"><span class="ln">6</span><span class="cl">    <span class="c1">-- 預設</span>
</span></span><span class="line"><span class="ln">7</span><span class="cl"><span class="kr">end</span></span></span></code></pre></div><p>只有 <code>nil</code> 和 <code>false</code> 是 falsy。<code>0</code> 和 <code>&quot;&quot;</code> 是 truthy（跟 Python 不同）。</p>
<h3 id="迴圈">迴圈</h3>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-lua" data-lang="lua"><span class="line"><span class="ln"> 1</span><span class="cl"><span class="c1">-- 數字 for（Hyprland 批次產生 workspace keybind）</span>
</span></span><span class="line"><span class="ln"> 2</span><span class="cl"><span class="kr">for</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">1</span><span class="p">,</span> <span class="mi">9</span> <span class="kr">do</span>
</span></span><span class="line"><span class="ln"> 3</span><span class="cl">    <span class="n">hl.bind</span><span class="p">(</span><span class="s2">&#34;SUPER&#34;</span><span class="p">,</span> <span class="n">tostring</span><span class="p">(</span><span class="n">i</span><span class="p">),</span> <span class="s2">&#34;workspace&#34;</span><span class="p">,</span> <span class="n">tostring</span><span class="p">(</span><span class="n">i</span><span class="p">))</span>
</span></span><span class="line"><span class="ln"> 4</span><span class="cl"><span class="kr">end</span>
</span></span><span class="line"><span class="ln"> 5</span><span class="cl">
</span></span><span class="line"><span class="ln"> 6</span><span class="cl"><span class="c1">-- 遍歷 table</span>
</span></span><span class="line"><span class="ln"> 7</span><span class="cl"><span class="kd">local</span> <span class="n">tools</span> <span class="o">=</span> <span class="p">{</span> <span class="s2">&#34;zsh&#34;</span><span class="p">,</span> <span class="s2">&#34;git&#34;</span><span class="p">,</span> <span class="s2">&#34;nvim&#34;</span><span class="p">,</span> <span class="s2">&#34;tmux&#34;</span> <span class="p">}</span>
</span></span><span class="line"><span class="ln"> 8</span><span class="cl"><span class="kr">for</span> <span class="n">_</span><span class="p">,</span> <span class="n">tool</span> <span class="kr">in</span> <span class="n">ipairs</span><span class="p">(</span><span class="n">tools</span><span class="p">)</span> <span class="kr">do</span>
</span></span><span class="line"><span class="ln"> 9</span><span class="cl">    <span class="n">print</span><span class="p">(</span><span class="n">tool</span><span class="p">)</span>
</span></span><span class="line"><span class="ln">10</span><span class="cl"><span class="kr">end</span></span></span></code></pre></div><h3 id="模組化require">模組化（require）</h3>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-lua" data-lang="lua"><span class="line"><span class="ln">1</span><span class="cl"><span class="c1">-- hyprland.lua 裡載入同目錄的其他 .lua 檔</span>
</span></span><span class="line"><span class="ln">2</span><span class="cl"><span class="n">require</span><span class="p">(</span><span class="s2">&#34;keybinds&#34;</span><span class="p">)</span>     <span class="c1">-- 載入 keybinds.lua</span>
</span></span><span class="line"><span class="ln">3</span><span class="cl"><span class="n">require</span><span class="p">(</span><span class="s2">&#34;rules&#34;</span><span class="p">)</span>        <span class="c1">-- 載入 rules.lua</span>
</span></span><span class="line"><span class="ln">4</span><span class="cl"><span class="n">require</span><span class="p">(</span><span class="s2">&#34;appearance&#34;</span><span class="p">)</span>   <span class="c1">-- 載入 appearance.lua</span></span></span></code></pre></div><p><code>require()</code> 是 Lua 原生的模組載入，取代了舊 Hyprland <code>.conf</code> 格式的 <code>source = ...</code> 指令。</p>
<h2 id="為什麼配置工具選-lua">為什麼配置工具選 Lua</h2>
<p>Lua 被嵌入到配置層的原因是一組特定的 trade-off：</p>
<ul>
<li><strong>比 JSON/TOML/YAML 強</strong>：有變數、迴圈、條件判斷。配置檔可以用 <code>for</code> 產生重複項目、用 <code>if</code> 處理機器差異，不需要外部 template engine</li>
<li><strong>比 Python/JavaScript 輕</strong>：300KB 的直譯器可以嵌入 C/C++ 程式，不需要拖一個完整的 runtime</li>
<li><strong>沙盒化容易</strong>：宿主程式可以控制 Lua 能存取哪些 API，限制配置檔的能力範圍</li>
</ul>
<p>這也是 Neovim 從 VimScript 遷移到 Lua 的理由——plugin 生態需要一個真正的程式語言（有資料結構、有錯誤處理），但又不能讓配置檔變成一個安全隱患。</p>
<h2 id="其他使用-lua-的場景">其他使用 Lua 的場景</h2>
<table>
  <thead>
      <tr>
          <th>場景</th>
          <th>用法</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>Neovim</td>
          <td>整個配置和 plugin 生態基於 Lua</td>
      </tr>
      <tr>
          <td>WezTerm</td>
          <td>terminal emulator 配置（<code>wezterm.lua</code>）</td>
      </tr>
      <tr>
          <td>Awesome WM</td>
          <td>X11 tiling WM 的配置和擴展</td>
      </tr>
      <tr>
          <td>Redis</td>
          <td><code>EVAL</code> 指令在 server 端執行 Lua script</td>
      </tr>
      <tr>
          <td>Nginx/OpenResty</td>
          <td>用 Lua 寫高效能的 request 處理邏輯</td>
      </tr>
      <tr>
          <td>遊戲</td>
          <td>World of Warcraft UI mod、Roblox、很多遊戲引擎的腳本層</td>
      </tr>
  </tbody>
</table>
<p>共同模式：一個用 C/C++ 寫的高效能核心，把 Lua 嵌入進去當配置和擴展語言。</p>
<h2 id="跟-pythonjavascript-的差異速查">跟 Python/JavaScript 的差異速查</h2>
<table>
  <thead>
      <tr>
          <th>項目</th>
          <th>Lua</th>
          <th>Python</th>
          <th>JavaScript</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>Array index 起始</td>
          <td><strong>1</strong></td>
          <td>0</td>
          <td>0</td>
      </tr>
      <tr>
          <td>字串串接</td>
          <td><code>..</code></td>
          <td><code>+</code></td>
          <td><code>+</code></td>
      </tr>
      <tr>
          <td>不等於</td>
          <td><code>~=</code></td>
          <td><code>!=</code></td>
          <td><code>!==</code></td>
      </tr>
      <tr>
          <td>邏輯運算</td>
          <td><code>and</code> <code>or</code> <code>not</code></td>
          <td><code>and</code> <code>or</code> <code>not</code></td>
          <td><code>&amp;&amp;</code> <code>||</code> <code>!</code></td>
      </tr>
      <tr>
          <td>空值</td>
          <td><code>nil</code></td>
          <td><code>None</code></td>
          <td><code>null</code>/<code>undefined</code></td>
      </tr>
      <tr>
          <td>Falsy 值</td>
          <td><code>nil</code>, <code>false</code></td>
          <td><code>None</code>, <code>False</code>, <code>0</code>, <code>&quot;&quot;</code>, <code>[]</code></td>
          <td><code>null</code>, <code>undefined</code>, <code>false</code>, <code>0</code>, <code>&quot;&quot;</code></td>
      </tr>
      <tr>
          <td>沒有 <code>+=</code></td>
          <td><code>x = x + 1</code></td>
          <td><code>x += 1</code></td>
          <td><code>x += 1</code></td>
      </tr>
      <tr>
          <td>註解</td>
          <td><code>--</code></td>
          <td><code>#</code></td>
          <td><code>//</code></td>
      </tr>
      <tr>
          <td>多行註解</td>
          <td><code>--[[ ... ]]</code></td>
          <td><code>&quot;&quot;&quot; ... &quot;&quot;&quot;</code></td>
          <td><code>/* ... */</code></td>
      </tr>
  </tbody>
</table>
<p>寫 Hyprland 或 Neovim 配置用到的 Lua 知識量很小——主要是 table（配置結構）、for loop（批次 keybind）、if-else（機器差異）、require（模組拆分）。不需要學 metatable、coroutine、metatmethod 這些進階功能。</p>
]]></content:encoded></item><item><title>Infrastructure as Code (IaC)</title><link>https://tarrragon.github.io/blog/infra/knowledge-cards/iac/</link><pubDate>Fri, 26 Jun 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/infra/knowledge-cards/iac/</guid><description>&lt;p>Infrastructure as Code（IaC）的核心概念是用版本控制的程式碼描述基礎設施應該長什麼樣，再由工具負責比對「程式碼描述的目標狀態」與「雲端上的實際狀態」，算出差異並收斂。這個機制把基礎設施從「某個人在 Console 手動點出來的東西」變成「可版本控制、可 review、可重建的描述」。&lt;/p>
&lt;p>IaC 工具分兩條路線：宣告式 DSL（Terraform / OpenTofu，用 HCL 描述資源）與程式語言（AWS CDK / Pulumi，用 TypeScript / Python / Go 生成資源）。兩者都能達成「用程式碼描述、由工具收斂」的目標，差別在閱讀門檻與抽象能力。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>IaC 是 infra 系列的根概念，貫穿所有模組。&lt;a href="https://tarrragon.github.io/blog/infra/00-infra-mindset/infra-responsibility-maturity/" data-link-title="infra 的責任邊界、成熟度階梯與 day 1 鐵律" data-link-desc="基礎設施承擔五個面向的責任，每一面都有獨立的失效模式；成熟度階梯用來對齊現況而非追求滿分，day 1 鐵律則劃出早期團隊該優先鋪的地基">成熟度階梯&lt;/a>的第二階（宣告式 IaC）是 IaC 正式生效的起點，第三階（環境分離）和第四階（PR 流程治理）都建立在 IaC 之上。沒有 IaC，後續所有模組的能力都無法落地。&lt;/p>
&lt;h2 id="可觀察訊號">可觀察訊號&lt;/h2>
&lt;p>需要 IaC 的訊號是規模與協作的函數：環境數量超過一套、多人同時改資源、環境事故頻率上升、外部稽核要求變更紀錄。詳見&lt;a href="https://tarrragon.github.io/blog/infra/before-infra/manual-environment-baseline/" data-link-title="手動環境的可控底線與納管準備" data-link-desc="還沒有 IaC 的環境怎麼守住底線、讓變更可追溯、降低未來納管成本，以及辨識何時該開始導入 IaC">模組負一：該開始導入 IaC 的訊號&lt;/a>。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>採用 IaC 時要決定的核心問題：&lt;/p>
&lt;ul>
&lt;li>工具選型：宣告式 DSL vs 程式語言，取捨在審查透明度 vs 抽象複用能力&lt;/li>
&lt;li>&lt;a href="https://tarrragon.github.io/blog/infra/knowledge-cards/state/" data-link-title="State（IaC 狀態檔）" data-link-desc="IaC 工具用來記錄每個納管資源在雲端真實樣貌的快照，是比對差異與排定操作順序的依據">State&lt;/a> 的存放：remote backend 的選擇與保護&lt;/li>
&lt;li>Console 唯讀紀律：所有寫入操作回到程式碼，Console 只作觀察&lt;/li>
&lt;li>納管範圍：哪些資源先進 IaC、哪些暫時留在手動&lt;/li>
&lt;/ul>
&lt;h2 id="鄰卡">鄰卡&lt;/h2>
&lt;ul>
&lt;li>&lt;a href="https://tarrragon.github.io/blog/infra/knowledge-cards/state/" data-link-title="State（IaC 狀態檔）" data-link-desc="IaC 工具用來記錄每個納管資源在雲端真實樣貌的快照，是比對差異與排定操作順序的依據">State&lt;/a> — IaC 工具追蹤現實的記憶機制&lt;/li>
&lt;li>&lt;a href="https://tarrragon.github.io/blog/infra/knowledge-cards/drift/" data-link-title="Drift（設定漂移）" data-link-desc="IaC 的 state 與雲端實際狀態之間的不一致，通常因為有人繞過 IaC 直接在 Console 改設定">Drift&lt;/a> — state 與現實不一致時的狀態&lt;/li>
&lt;li>&lt;a href="https://tarrragon.github.io/blog/infra/knowledge-cards/environment-separation/" data-link-title="環境分離" data-link-desc="把同一套基礎設施定義複製成多份隔離的執行實例，各有獨立 state 與故障半徑">環境分離&lt;/a> — 同一份 IaC 描述套用到多環境&lt;/li>
&lt;/ul></description><content:encoded><![CDATA[<p>Infrastructure as Code（IaC）的核心概念是用版本控制的程式碼描述基礎設施應該長什麼樣，再由工具負責比對「程式碼描述的目標狀態」與「雲端上的實際狀態」，算出差異並收斂。這個機制把基礎設施從「某個人在 Console 手動點出來的東西」變成「可版本控制、可 review、可重建的描述」。</p>
<p>IaC 工具分兩條路線：宣告式 DSL（Terraform / OpenTofu，用 HCL 描述資源）與程式語言（AWS CDK / Pulumi，用 TypeScript / Python / Go 生成資源）。兩者都能達成「用程式碼描述、由工具收斂」的目標，差別在閱讀門檻與抽象能力。</p>
<h2 id="概念位置">概念位置</h2>
<p>IaC 是 infra 系列的根概念，貫穿所有模組。<a href="/blog/infra/00-infra-mindset/infra-responsibility-maturity/" data-link-title="infra 的責任邊界、成熟度階梯與 day 1 鐵律" data-link-desc="基礎設施承擔五個面向的責任，每一面都有獨立的失效模式；成熟度階梯用來對齊現況而非追求滿分，day 1 鐵律則劃出早期團隊該優先鋪的地基">成熟度階梯</a>的第二階（宣告式 IaC）是 IaC 正式生效的起點，第三階（環境分離）和第四階（PR 流程治理）都建立在 IaC 之上。沒有 IaC，後續所有模組的能力都無法落地。</p>
<h2 id="可觀察訊號">可觀察訊號</h2>
<p>需要 IaC 的訊號是規模與協作的函數：環境數量超過一套、多人同時改資源、環境事故頻率上升、外部稽核要求變更紀錄。詳見<a href="/blog/infra/before-infra/manual-environment-baseline/" data-link-title="手動環境的可控底線與納管準備" data-link-desc="還沒有 IaC 的環境怎麼守住底線、讓變更可追溯、降低未來納管成本，以及辨識何時該開始導入 IaC">模組負一：該開始導入 IaC 的訊號</a>。</p>
<h2 id="設計責任">設計責任</h2>
<p>採用 IaC 時要決定的核心問題：</p>
<ul>
<li>工具選型：宣告式 DSL vs 程式語言，取捨在審查透明度 vs 抽象複用能力</li>
<li><a href="/blog/infra/knowledge-cards/state/" data-link-title="State（IaC 狀態檔）" data-link-desc="IaC 工具用來記錄每個納管資源在雲端真實樣貌的快照，是比對差異與排定操作順序的依據">State</a> 的存放：remote backend 的選擇與保護</li>
<li>Console 唯讀紀律：所有寫入操作回到程式碼，Console 只作觀察</li>
<li>納管範圍：哪些資源先進 IaC、哪些暫時留在手動</li>
</ul>
<h2 id="鄰卡">鄰卡</h2>
<ul>
<li><a href="/blog/infra/knowledge-cards/state/" data-link-title="State（IaC 狀態檔）" data-link-desc="IaC 工具用來記錄每個納管資源在雲端真實樣貌的快照，是比對差異與排定操作順序的依據">State</a> — IaC 工具追蹤現實的記憶機制</li>
<li><a href="/blog/infra/knowledge-cards/drift/" data-link-title="Drift（設定漂移）" data-link-desc="IaC 的 state 與雲端實際狀態之間的不一致，通常因為有人繞過 IaC 直接在 Console 改設定">Drift</a> — state 與現實不一致時的狀態</li>
<li><a href="/blog/infra/knowledge-cards/environment-separation/" data-link-title="環境分離" data-link-desc="把同一套基礎設施定義複製成多份隔離的執行實例，各有獨立 state 與故障半徑">環境分離</a> — 同一份 IaC 描述套用到多環境</li>
</ul>
]]></content:encoded></item><item><title>SaaS</title><link>https://tarrragon.github.io/blog/business/knowledge-cards/saas/</link><pubDate>Tue, 19 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/business/knowledge-cards/saas/</guid><description>&lt;p>SaaS 的核心概念是「Software as a Service」—軟體用訂閱方式銷售，部署在雲端，客戶按月或按年付費，不需要買斷或自行架設伺服器。Notion、Salesforce、Slack 都是典型 SaaS。SaaS 的賣點是高 &lt;a href="https://tarrragon.github.io/blog/business/knowledge-cards/gross-margin/" data-link-title="Gross Margin" data-link-desc="說明毛利率與其對商業模式可行性的決定作用">毛利&lt;/a>、可預測訂閱收入與低 &lt;a href="https://tarrragon.github.io/blog/business/knowledge-cards/marginal-cost/" data-link-title="Marginal Cost" data-link-desc="說明邊際成本及其對商業模式擴張性的決定作用">邊際成本&lt;/a>。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>SaaS 是商業模式的一種分類，相對於買斷型軟體（perpetual license）與託管型服務（managed service）。SaaS 之所以能擴張，是因為傳統 SaaS 的 &lt;a href="https://tarrragon.github.io/blog/business/knowledge-cards/marginal-cost/" data-link-title="Marginal Cost" data-link-desc="說明邊際成本及其對商業模式擴張性的決定作用">邊際成本&lt;/a> 接近零、客戶 &lt;a href="https://tarrragon.github.io/blog/business/knowledge-cards/retention/" data-link-title="Retention" data-link-desc="說明客戶留存率與其對單位經濟的決定作用">留存&lt;/a> 高、可走 &lt;a href="https://tarrragon.github.io/blog/business/knowledge-cards/plg/" data-link-title="PLG" data-link-desc="說明產品自助成長模式與其經濟前提">PLG&lt;/a> 自助上手。&lt;/p>
&lt;h2 id="可觀察訊號與例子">可觀察訊號與例子&lt;/h2>
&lt;p>判斷一家軟體公司是不是 SaaS，看三個訊號：客戶按時間訂閱付費、產品部署在雲端讓客戶用瀏覽器或 API 連線、新客戶上線的邊際成本接近零。三者全成立就是經典 SaaS。Adobe 從買斷型 Photoshop 改成 Creative Cloud 訂閱，是傳統軟體業者轉 SaaS 的代表案例。&lt;/p>
&lt;h2 id="判讀方式">判讀方式&lt;/h2>
&lt;p>讀到一家公司號稱是 SaaS 但 &lt;a href="https://tarrragon.github.io/blog/business/knowledge-cards/gross-margin/" data-link-title="Gross Margin" data-link-desc="說明毛利率與其對商業模式可行性的決定作用">毛利&lt;/a> 只有 40%、需要派業務逐單推銷時，要懷疑它是不是真 SaaS，可能更接近顧問服務或重整合的客製軟體。AI 時代許多新創號稱 SaaS 但因為要燒 GPU 算力，&lt;a href="https://tarrragon.github.io/blog/business/knowledge-cards/cogs/" data-link-title="COGS" data-link-desc="說明銷售成本與其對毛利的影響">COGS&lt;/a> 被推高，毛利反而接近傳統軟體業—這是這波 AI 商業化的結構性議題，直接影響 &lt;a href="https://tarrragon.github.io/blog/business/knowledge-cards/valuation/" data-link-title="Valuation" data-link-desc="說明估值的構成與商業判讀作用">估值&lt;/a>。&lt;/p></description><content:encoded><![CDATA[<p>SaaS 的核心概念是「Software as a Service」—軟體用訂閱方式銷售，部署在雲端，客戶按月或按年付費，不需要買斷或自行架設伺服器。Notion、Salesforce、Slack 都是典型 SaaS。SaaS 的賣點是高 <a href="/blog/business/knowledge-cards/gross-margin/" data-link-title="Gross Margin" data-link-desc="說明毛利率與其對商業模式可行性的決定作用">毛利</a>、可預測訂閱收入與低 <a href="/blog/business/knowledge-cards/marginal-cost/" data-link-title="Marginal Cost" data-link-desc="說明邊際成本及其對商業模式擴張性的決定作用">邊際成本</a>。</p>
<h2 id="概念位置">概念位置</h2>
<p>SaaS 是商業模式的一種分類，相對於買斷型軟體（perpetual license）與託管型服務（managed service）。SaaS 之所以能擴張，是因為傳統 SaaS 的 <a href="/blog/business/knowledge-cards/marginal-cost/" data-link-title="Marginal Cost" data-link-desc="說明邊際成本及其對商業模式擴張性的決定作用">邊際成本</a> 接近零、客戶 <a href="/blog/business/knowledge-cards/retention/" data-link-title="Retention" data-link-desc="說明客戶留存率與其對單位經濟的決定作用">留存</a> 高、可走 <a href="/blog/business/knowledge-cards/plg/" data-link-title="PLG" data-link-desc="說明產品自助成長模式與其經濟前提">PLG</a> 自助上手。</p>
<h2 id="可觀察訊號與例子">可觀察訊號與例子</h2>
<p>判斷一家軟體公司是不是 SaaS，看三個訊號：客戶按時間訂閱付費、產品部署在雲端讓客戶用瀏覽器或 API 連線、新客戶上線的邊際成本接近零。三者全成立就是經典 SaaS。Adobe 從買斷型 Photoshop 改成 Creative Cloud 訂閱，是傳統軟體業者轉 SaaS 的代表案例。</p>
<h2 id="判讀方式">判讀方式</h2>
<p>讀到一家公司號稱是 SaaS 但 <a href="/blog/business/knowledge-cards/gross-margin/" data-link-title="Gross Margin" data-link-desc="說明毛利率與其對商業模式可行性的決定作用">毛利</a> 只有 40%、需要派業務逐單推銷時，要懷疑它是不是真 SaaS，可能更接近顧問服務或重整合的客製軟體。AI 時代許多新創號稱 SaaS 但因為要燒 GPU 算力，<a href="/blog/business/knowledge-cards/cogs/" data-link-title="COGS" data-link-desc="說明銷售成本與其對毛利的影響">COGS</a> 被推高，毛利反而接近傳統軟體業—這是這波 AI 商業化的結構性議題，直接影響 <a href="/blog/business/knowledge-cards/valuation/" data-link-title="Valuation" data-link-desc="說明估值的構成與商業判讀作用">估值</a>。</p>
]]></content:encoded></item><item><title>Adaptive Retrieval</title><link>https://tarrragon.github.io/blog/llm/knowledge-cards/adaptive-retrieval/</link><pubDate>Thu, 14 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/llm/knowledge-cards/adaptive-retrieval/</guid><description>&lt;p>Adaptive retrieval 的核心概念是「&lt;strong>先判斷問題是否需要 &lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/rag/" data-link-title="RAG" data-link-desc="Retrieval-Augmented Generation：動態外掛知識給 LLM、繞開模型參數記憶的靜態限制">RAG&lt;/a> 外部檢索，再決定要不要 retrieve&lt;/strong>」。它避免每個 query 都塞入外部 chunk，降低 &lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/retrieval-cost/" data-link-title="Retrieval Cost" data-link-desc="RAG 檢索帶來的 latency、token、embedding、reranker、LLM call 與維護成本，用來判斷增強是否划算">retrieval cost&lt;/a>，也減少無關內容干擾模型。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>Adaptive retrieval 位在 &lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/rag/" data-link-title="RAG" data-link-desc="Retrieval-Augmented Generation：動態外掛知識給 LLM、繞開模型參數記憶的靜態限制">RAG&lt;/a> 的控制流端。它跟 &lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/query-rewriting/" data-link-title="Query Rewriting" data-link-desc="在 RAG 檢索前改寫使用者查詢，讓 query 更接近文件語言與索引分佈">query rewriting&lt;/a> 不同：rewriting 假設要 retrieve，只改查詢形狀；adaptive retrieval 先決定 retrieve 是否必要。&lt;/p>
&lt;h2 id="可觀察訊號與例子">可觀察訊號與例子&lt;/h2>
&lt;p>「2+2 等於多少」不需要 retrieve；「公司退款政策第 4 條怎麼說」需要 retrieve。若使用者 query 一半是聊天、一半是 factual lookup，adaptive retrieval 可以明顯降低 retrieval cost。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>判斷器可以是規則、小模型、主模型 self-report 或 confidence signal。風險是模型過度自信而跳過檢索；高風險事實問答應偏向 retrieve 或提供 fallback。&lt;/p></description><content:encoded><![CDATA[<p>Adaptive retrieval 的核心概念是「<strong>先判斷問題是否需要 <a href="/blog/llm/knowledge-cards/rag/" data-link-title="RAG" data-link-desc="Retrieval-Augmented Generation：動態外掛知識給 LLM、繞開模型參數記憶的靜態限制">RAG</a> 外部檢索，再決定要不要 retrieve</strong>」。它避免每個 query 都塞入外部 chunk，降低 <a href="/blog/llm/knowledge-cards/retrieval-cost/" data-link-title="Retrieval Cost" data-link-desc="RAG 檢索帶來的 latency、token、embedding、reranker、LLM call 與維護成本，用來判斷增強是否划算">retrieval cost</a>，也減少無關內容干擾模型。</p>
<h2 id="概念位置">概念位置</h2>
<p>Adaptive retrieval 位在 <a href="/blog/llm/knowledge-cards/rag/" data-link-title="RAG" data-link-desc="Retrieval-Augmented Generation：動態外掛知識給 LLM、繞開模型參數記憶的靜態限制">RAG</a> 的控制流端。它跟 <a href="/blog/llm/knowledge-cards/query-rewriting/" data-link-title="Query Rewriting" data-link-desc="在 RAG 檢索前改寫使用者查詢，讓 query 更接近文件語言與索引分佈">query rewriting</a> 不同：rewriting 假設要 retrieve，只改查詢形狀；adaptive retrieval 先決定 retrieve 是否必要。</p>
<h2 id="可觀察訊號與例子">可觀察訊號與例子</h2>
<p>「2+2 等於多少」不需要 retrieve；「公司退款政策第 4 條怎麼說」需要 retrieve。若使用者 query 一半是聊天、一半是 factual lookup，adaptive retrieval 可以明顯降低 retrieval cost。</p>
<h2 id="設計責任">設計責任</h2>
<p>判斷器可以是規則、小模型、主模型 self-report 或 confidence signal。風險是模型過度自信而跳過檢索；高風險事實問答應偏向 retrieve 或提供 fallback。</p>
]]></content:encoded></item><item><title>Agent-as-Tool</title><link>https://tarrragon.github.io/blog/llm/knowledge-cards/agent-as-tool/</link><pubDate>Thu, 14 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/llm/knowledge-cards/agent-as-tool/</guid><description>&lt;p>Agent-as-tool 的核心概念是「&lt;strong>把一個 &lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/agent/" data-link-title="LLM Agent" data-link-desc="把控制流交給 LLM 的應用模式：自主決策、跨多步呼叫工具、人類角色從主導變監督">agent&lt;/a> 封裝成另一個 agent 可呼叫的工具&lt;/strong>」。被封裝的 agent 有自己的 prompt、工具、上下文與完成條件；呼叫方只看到一個較高階的 tool interface。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>它是 &lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/multi-agent-system/" data-link-title="Multi-agent system" data-link-desc="多個 LLM agent 協作的系統、跟 multi-call workflow 的差異在控制流跟責任邊界、三種拓樸 flat / hierarchical / agent-as-tool">multi-agent system&lt;/a> 的一種拓樸，也可透過 &lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/mcp/" data-link-title="MCP（Model Context Protocol）" data-link-desc="LLM application ↔ 外部 tool server 之間的標準化協議、複用 OpenAI 相容 API 的成功模式">MCP&lt;/a> 暴露成 tool server。它跟 &lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/subagent/" data-link-title="Subagent" data-link-desc="Coding agent 中把特定責任拆給專門子 agent 的設計模式、各 subagent 有獨立 context、由 main agent 透過 handoff 調度">subagent&lt;/a> 的差異是：subagent 常是同一 runtime 內的任務分派，agent-as-tool 強調對外介面與重用邊界。&lt;/p>
&lt;h2 id="可觀察訊號與例子">可觀察訊號與例子&lt;/h2>
&lt;p>主 agent 呼叫 &lt;code>run_security_review()&lt;/code>，背後其實是一個安全 reviewer agent 讀檔、查規則、輸出 findings。主 agent 不需要知道內部步驟，只需要 consume 結果。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>Agent-as-tool 要把輸入、輸出、權限、副作用與 timeout 定清楚。否則呼叫方會把它當 deterministic tool，但內部其實是 fuzzy agent，失敗模式會被隱藏。&lt;/p></description><content:encoded><![CDATA[<p>Agent-as-tool 的核心概念是「<strong>把一個 <a href="/blog/llm/knowledge-cards/agent/" data-link-title="LLM Agent" data-link-desc="把控制流交給 LLM 的應用模式：自主決策、跨多步呼叫工具、人類角色從主導變監督">agent</a> 封裝成另一個 agent 可呼叫的工具</strong>」。被封裝的 agent 有自己的 prompt、工具、上下文與完成條件；呼叫方只看到一個較高階的 tool interface。</p>
<h2 id="概念位置">概念位置</h2>
<p>它是 <a href="/blog/llm/knowledge-cards/multi-agent-system/" data-link-title="Multi-agent system" data-link-desc="多個 LLM agent 協作的系統、跟 multi-call workflow 的差異在控制流跟責任邊界、三種拓樸 flat / hierarchical / agent-as-tool">multi-agent system</a> 的一種拓樸，也可透過 <a href="/blog/llm/knowledge-cards/mcp/" data-link-title="MCP（Model Context Protocol）" data-link-desc="LLM application ↔ 外部 tool server 之間的標準化協議、複用 OpenAI 相容 API 的成功模式">MCP</a> 暴露成 tool server。它跟 <a href="/blog/llm/knowledge-cards/subagent/" data-link-title="Subagent" data-link-desc="Coding agent 中把特定責任拆給專門子 agent 的設計模式、各 subagent 有獨立 context、由 main agent 透過 handoff 調度">subagent</a> 的差異是：subagent 常是同一 runtime 內的任務分派，agent-as-tool 強調對外介面與重用邊界。</p>
<h2 id="可觀察訊號與例子">可觀察訊號與例子</h2>
<p>主 agent 呼叫 <code>run_security_review()</code>，背後其實是一個安全 reviewer agent 讀檔、查規則、輸出 findings。主 agent 不需要知道內部步驟，只需要 consume 結果。</p>
<h2 id="設計責任">設計責任</h2>
<p>Agent-as-tool 要把輸入、輸出、權限、副作用與 timeout 定清楚。否則呼叫方會把它當 deterministic tool，但內部其實是 fuzzy agent，失敗模式會被隱藏。</p>
]]></content:encoded></item><item><title>BNF（Backus-Naur Form）</title><link>https://tarrragon.github.io/blog/llm/knowledge-cards/bnf/</link><pubDate>Thu, 14 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/llm/knowledge-cards/bnf/</guid><description>&lt;p>BNF（Backus-Naur Form）的核心概念是「&lt;strong>用產生式規則描述一個語言裡哪些字串合法&lt;/strong>」。它常用在程式語言、資料格式、parser 與 structured output grammar，讓人跟工具都能用同一份規則理解合法語法。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>BNF 是 &lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/grammar/" data-link-title="Grammar" data-link-desc="描述合法字串形狀的形式規則，在 structured output 中用來限制 LLM 每一步可輸出的 token">grammar&lt;/a> 的一種表示法，特別適合描述 context-free grammar。規則左邊是非終結符，右邊是它可以展開成的符號組合；終結符是實際會出現在字串中的 token，非終結符是中間抽象節點。&lt;/p>





&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-text" data-lang="text">&lt;span class="line">&lt;span class="ln">1&lt;/span>&lt;span class="cl">&amp;lt;expr&amp;gt; ::= &amp;lt;term&amp;gt; | &amp;lt;expr&amp;gt; &amp;#34;+&amp;#34; &amp;lt;term&amp;gt;
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">2&lt;/span>&lt;span class="cl">&amp;lt;term&amp;gt; ::= &amp;lt;number&amp;gt; | &amp;#34;(&amp;#34; &amp;lt;expr&amp;gt; &amp;#34;)&amp;#34;&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>這段規則表示 expression 可以是 term，也可以是 expression 加 term；term 可以是 number，也可以是括號包住的 expression。&lt;/p>
&lt;h2 id="可觀察訊號與例子">可觀察訊號與例子&lt;/h2>
&lt;p>看到 &lt;code>::=&lt;/code>、&lt;code>&amp;lt;name&amp;gt;&lt;/code>、多個展開選項，就是 BNF 或 BNF-like grammar。LLM structured output 文章裡提到 BNF，通常是在說「把合法輸出格式寫成形式語法，推論時用它限制生成」。llama.cpp 的 GBNF、部分 grammar engine 與 parser 文件都會使用類似記法。&lt;/p>
&lt;p>BNF 的限制是它描述語法，不描述語意。它能表示「括號必須成對」「欄位順序合法」，但不能直接表示「日期必須晚於今天」「使用者必須有權限讀這筆資料」這類外部約束。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>BNF 適合拿來讀懂 grammar-constrained sampling 的規則形狀。實作時要確認你使用的引擎支援的是標準 BNF、EBNF、GBNF，還是自家 dialect；不同 dialect 的 optional、repeat、token escaping 寫法會不同。下一步路由是 &lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/grammar/" data-link-title="Grammar" data-link-desc="描述合法字串形狀的形式規則，在 structured output 中用來限制 LLM 每一步可輸出的 token">Grammar&lt;/a> 與 &lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/lark-grammar/" data-link-title="Lark Grammar" data-link-desc="Lark parser 使用的 EBNF-like grammar 格式，常被 structured output 工具拿來描述自訂輸出語法">Lark Grammar&lt;/a>。&lt;/p></description><content:encoded><![CDATA[<p>BNF（Backus-Naur Form）的核心概念是「<strong>用產生式規則描述一個語言裡哪些字串合法</strong>」。它常用在程式語言、資料格式、parser 與 structured output grammar，讓人跟工具都能用同一份規則理解合法語法。</p>
<h2 id="概念位置">概念位置</h2>
<p>BNF 是 <a href="/blog/llm/knowledge-cards/grammar/" data-link-title="Grammar" data-link-desc="描述合法字串形狀的形式規則，在 structured output 中用來限制 LLM 每一步可輸出的 token">grammar</a> 的一種表示法，特別適合描述 context-free grammar。規則左邊是非終結符，右邊是它可以展開成的符號組合；終結符是實際會出現在字串中的 token，非終結符是中間抽象節點。</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="ln">1</span><span class="cl">&lt;expr&gt; ::= &lt;term&gt; | &lt;expr&gt; &#34;+&#34; &lt;term&gt;
</span></span><span class="line"><span class="ln">2</span><span class="cl">&lt;term&gt; ::= &lt;number&gt; | &#34;(&#34; &lt;expr&gt; &#34;)&#34;</span></span></code></pre></div><p>這段規則表示 expression 可以是 term，也可以是 expression 加 term；term 可以是 number，也可以是括號包住的 expression。</p>
<h2 id="可觀察訊號與例子">可觀察訊號與例子</h2>
<p>看到 <code>::=</code>、<code>&lt;name&gt;</code>、多個展開選項，就是 BNF 或 BNF-like grammar。LLM structured output 文章裡提到 BNF，通常是在說「把合法輸出格式寫成形式語法，推論時用它限制生成」。llama.cpp 的 GBNF、部分 grammar engine 與 parser 文件都會使用類似記法。</p>
<p>BNF 的限制是它描述語法，不描述語意。它能表示「括號必須成對」「欄位順序合法」，但不能直接表示「日期必須晚於今天」「使用者必須有權限讀這筆資料」這類外部約束。</p>
<h2 id="設計責任">設計責任</h2>
<p>BNF 適合拿來讀懂 grammar-constrained sampling 的規則形狀。實作時要確認你使用的引擎支援的是標準 BNF、EBNF、GBNF，還是自家 dialect；不同 dialect 的 optional、repeat、token escaping 寫法會不同。下一步路由是 <a href="/blog/llm/knowledge-cards/grammar/" data-link-title="Grammar" data-link-desc="描述合法字串形狀的形式規則，在 structured output 中用來限制 LLM 每一步可輸出的 token">Grammar</a> 與 <a href="/blog/llm/knowledge-cards/lark-grammar/" data-link-title="Lark Grammar" data-link-desc="Lark parser 使用的 EBNF-like grammar 格式，常被 structured output 工具拿來描述自訂輸出語法">Lark Grammar</a>。</p>
]]></content:encoded></item><item><title>Capability Spectrum</title><link>https://tarrragon.github.io/blog/llm/knowledge-cards/capability-spectrum/</link><pubDate>Thu, 14 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/llm/knowledge-cards/capability-spectrum/</guid><description>&lt;p>Capability spectrum（能力光譜）的核心概念是「&lt;strong>LLM 能力通常是連續程度，不是支援 / 不支援的二元開關&lt;/strong>」。同樣宣稱支援 function calling、reasoning、coding、structured output 的模型，可能在簡單案例都成功，但在長 context、多工具、巢狀 schema、模糊需求或反例情境下出現巨大差距。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>能力光譜是評估與選型用語，用來替代 binary checklist。它把能力拆成範圍、穩定性、成本與失敗模式：模型能做什麼、在多寬的分佈上穩定、錯的時候怎麼錯、需要多少 prompt / validator / retry 才可用。&lt;/p>





&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-text" data-lang="text">&lt;span class="line">&lt;span class="ln">1&lt;/span>&lt;span class="cl">宣稱支援 → happy path 可用
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">2&lt;/span>&lt;span class="cl">基礎可用 → 常見變體可用
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">3&lt;/span>&lt;span class="cl">生產可用 → edge cases、錯誤路徑、壓力情境仍可控&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h2 id="可觀察訊號與例子">可觀察訊號與例子&lt;/h2>
&lt;p>Function calling 的能力光譜可以用幾個訊號量化：單工具成功率、多工具選擇成功率、schema 合法率、參數語意正確率、錯誤時是否追問。某模型能輸出合法 JSON，不代表它能選對工具；能選對工具，也不代表它能填對 nested argument。&lt;/p>
&lt;p>能力光譜的常見陷阱是把 demo 成功當成生產穩定。Demo 通常測 happy path，生產會遇到拼字錯、缺欄位、權限不足、工具 timeout、prompt injection、schema 演化與多語言輸入；這些才決定能力落在哪個位置。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>做模型選型或應用設計時，把「有沒有」改成「到什麼程度可用」。判準要包含成功率、覆蓋範圍、錯誤成本、監控訊號與回退路徑。下一步路由是：能力來自訓練資料時讀 &lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/training-example-coverage/" data-link-title="Training Example Coverage" data-link-desc="訓練資料中的任務範例是否覆蓋足夠情境，決定模型在 function calling、格式輸出與邊界案例上的穩定性">Training Example Coverage&lt;/a>；能力需要推論階段兜底時讀 &lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/sampling-constraint/" data-link-title="Sampling Constraint" data-link-desc="推論時限制下一個 token 候選集合的控制手段，用來把模型生成導向合法格式或特定選項">Sampling Constraint&lt;/a>。&lt;/p></description><content:encoded><![CDATA[<p>Capability spectrum（能力光譜）的核心概念是「<strong>LLM 能力通常是連續程度，不是支援 / 不支援的二元開關</strong>」。同樣宣稱支援 function calling、reasoning、coding、structured output 的模型，可能在簡單案例都成功，但在長 context、多工具、巢狀 schema、模糊需求或反例情境下出現巨大差距。</p>
<h2 id="概念位置">概念位置</h2>
<p>能力光譜是評估與選型用語，用來替代 binary checklist。它把能力拆成範圍、穩定性、成本與失敗模式：模型能做什麼、在多寬的分佈上穩定、錯的時候怎麼錯、需要多少 prompt / validator / retry 才可用。</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="ln">1</span><span class="cl">宣稱支援 → happy path 可用
</span></span><span class="line"><span class="ln">2</span><span class="cl">基礎可用 → 常見變體可用
</span></span><span class="line"><span class="ln">3</span><span class="cl">生產可用 → edge cases、錯誤路徑、壓力情境仍可控</span></span></code></pre></div><h2 id="可觀察訊號與例子">可觀察訊號與例子</h2>
<p>Function calling 的能力光譜可以用幾個訊號量化：單工具成功率、多工具選擇成功率、schema 合法率、參數語意正確率、錯誤時是否追問。某模型能輸出合法 JSON，不代表它能選對工具；能選對工具，也不代表它能填對 nested argument。</p>
<p>能力光譜的常見陷阱是把 demo 成功當成生產穩定。Demo 通常測 happy path，生產會遇到拼字錯、缺欄位、權限不足、工具 timeout、prompt injection、schema 演化與多語言輸入；這些才決定能力落在哪個位置。</p>
<h2 id="設計責任">設計責任</h2>
<p>做模型選型或應用設計時，把「有沒有」改成「到什麼程度可用」。判準要包含成功率、覆蓋範圍、錯誤成本、監控訊號與回退路徑。下一步路由是：能力來自訓練資料時讀 <a href="/blog/llm/knowledge-cards/training-example-coverage/" data-link-title="Training Example Coverage" data-link-desc="訓練資料中的任務範例是否覆蓋足夠情境，決定模型在 function calling、格式輸出與邊界案例上的穩定性">Training Example Coverage</a>；能力需要推論階段兜底時讀 <a href="/blog/llm/knowledge-cards/sampling-constraint/" data-link-title="Sampling Constraint" data-link-desc="推論時限制下一個 token 候選集合的控制手段，用來把模型生成導向合法格式或特定選項">Sampling Constraint</a>。</p>
]]></content:encoded></item><item><title>Context Drift</title><link>https://tarrragon.github.io/blog/llm/knowledge-cards/context-drift/</link><pubDate>Thu, 14 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/llm/knowledge-cards/context-drift/</guid><description>&lt;p>Context drift（上下文漂移）的核心概念是「&lt;strong>&lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/agent-loop/" data-link-title="Agent Loop" data-link-desc="LLM agent 自我循環的工作流：LLM 規劃下一步、執行 tool、看結果、再規劃下一步、直到任務完成或停止條件觸發">agent loop&lt;/a> 長任務中累積 context 逐步偏離原始目標&lt;/strong>」。每一步局部看起來合理，但中間結果、工具輸出與模型自我敘述會逐漸取代原始任務，讓整體方向跑偏。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>Context drift 是 &lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/agent-loop/" data-link-title="Agent Loop" data-link-desc="LLM agent 自我循環的工作流：LLM 規劃下一步、執行 tool、看結果、再規劃下一步、直到任務完成或停止條件觸發">agent loop&lt;/a> 的長程失敗模式，跟 &lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/goal-drift/" data-link-title="Goal Drift" data-link-desc="Agent 把子目標誤當成整體目標，提早停止或朝錯誤完成條件前進的失敗模式">goal drift&lt;/a> 不同：goal drift 是把子目標當終點，context drift 是上下文重心逐步偏移。&lt;/p>
&lt;h2 id="可觀察訊號與例子">可觀察訊號與例子&lt;/h2>
&lt;p>任務原本是修 bug，十步後變成重構模組，再十步後變成重寫整個檔案，就是 context drift。常見訊號是 agent 開始引用近期工具輸出當主目標，卻不再回看最初 acceptance criteria。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>緩解方式是定期重錨原始目標、保留 checklist、設 checkpoint、讓外部 evaluator 比對目前行動與原始任務距離。漂移持續發生時，縮短 loop、改用 single-call pipeline，或提高 human review 頻率。&lt;/p></description><content:encoded><![CDATA[<p>Context drift（上下文漂移）的核心概念是「<strong><a href="/blog/llm/knowledge-cards/agent-loop/" data-link-title="Agent Loop" data-link-desc="LLM agent 自我循環的工作流：LLM 規劃下一步、執行 tool、看結果、再規劃下一步、直到任務完成或停止條件觸發">agent loop</a> 長任務中累積 context 逐步偏離原始目標</strong>」。每一步局部看起來合理，但中間結果、工具輸出與模型自我敘述會逐漸取代原始任務，讓整體方向跑偏。</p>
<h2 id="概念位置">概念位置</h2>
<p>Context drift 是 <a href="/blog/llm/knowledge-cards/agent-loop/" data-link-title="Agent Loop" data-link-desc="LLM agent 自我循環的工作流：LLM 規劃下一步、執行 tool、看結果、再規劃下一步、直到任務完成或停止條件觸發">agent loop</a> 的長程失敗模式，跟 <a href="/blog/llm/knowledge-cards/goal-drift/" data-link-title="Goal Drift" data-link-desc="Agent 把子目標誤當成整體目標，提早停止或朝錯誤完成條件前進的失敗模式">goal drift</a> 不同：goal drift 是把子目標當終點，context drift 是上下文重心逐步偏移。</p>
<h2 id="可觀察訊號與例子">可觀察訊號與例子</h2>
<p>任務原本是修 bug，十步後變成重構模組，再十步後變成重寫整個檔案，就是 context drift。常見訊號是 agent 開始引用近期工具輸出當主目標，卻不再回看最初 acceptance criteria。</p>
<h2 id="設計責任">設計責任</h2>
<p>緩解方式是定期重錨原始目標、保留 checklist、設 checkpoint、讓外部 evaluator 比對目前行動與原始任務距離。漂移持續發生時，縮短 loop、改用 single-call pipeline，或提高 human review 頻率。</p>
]]></content:encoded></item><item><title>Context Packing</title><link>https://tarrragon.github.io/blog/llm/knowledge-cards/context-packing/</link><pubDate>Thu, 14 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/llm/knowledge-cards/context-packing/</guid><description>&lt;p>Context packing 的核心概念是「&lt;strong>retrieve 拿到候選 chunks 後，決定哪些內容、以什麼順序、帶哪些 metadata 塞進 prompt&lt;/strong>」。它是 &lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/rag/" data-link-title="RAG" data-link-desc="Retrieval-Augmented Generation：動態外掛知識給 LLM、繞開模型參數記憶的靜態限制">RAG&lt;/a> 在 retrieval 與 generation 之間的 context 組裝層，有別於 retrieval 本身。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>Context packing 位在 top-k retrieval 結果與 LLM prompt 之間。它跟 &lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/retrieval-source/" data-link-title="Retrieval Source" data-link-desc="RAG 從哪個 corpus、index、tool 或外部系統取回內容，決定來源可信度、freshness、權限與引用責任">retrieval source&lt;/a> 相鄰，因為來源 metadata 會影響引用；也跟 &lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/lost-in-the-middle/" data-link-title="Lost in the Middle" data-link-desc="LLM 對 long context 中段內容的 attention / recall 顯著低於開頭與結尾的現象">lost-in-the-middle&lt;/a> 相鄰，因為 chunk 順序會影響模型注意力。&lt;/p>
&lt;h2 id="可觀察訊號與例子">可觀察訊號與例子&lt;/h2>
&lt;p>常見 packing 決策包含 dedup 重複 chunk、把最相關內容放前後、按 document order 保留段落流、摘要或壓縮過長 chunks、在每段前加 source path 與 score。這些決策會改變答案品質、token cost 與可追溯性。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>設計 context packing 時要回答：哪些 chunk 真的要進 prompt、順序如何安排、是否保留來源、是否需要 summarization / compression。高追溯場景優先保留 source metadata；長 context 場景要避免把重要 chunk 放在中間；latency 敏感場景要限制 top-k 與 compression call。&lt;/p></description><content:encoded><![CDATA[<p>Context packing 的核心概念是「<strong>retrieve 拿到候選 chunks 後，決定哪些內容、以什麼順序、帶哪些 metadata 塞進 prompt</strong>」。它是 <a href="/blog/llm/knowledge-cards/rag/" data-link-title="RAG" data-link-desc="Retrieval-Augmented Generation：動態外掛知識給 LLM、繞開模型參數記憶的靜態限制">RAG</a> 在 retrieval 與 generation 之間的 context 組裝層，有別於 retrieval 本身。</p>
<h2 id="概念位置">概念位置</h2>
<p>Context packing 位在 top-k retrieval 結果與 LLM prompt 之間。它跟 <a href="/blog/llm/knowledge-cards/retrieval-source/" data-link-title="Retrieval Source" data-link-desc="RAG 從哪個 corpus、index、tool 或外部系統取回內容，決定來源可信度、freshness、權限與引用責任">retrieval source</a> 相鄰，因為來源 metadata 會影響引用；也跟 <a href="/blog/llm/knowledge-cards/lost-in-the-middle/" data-link-title="Lost in the Middle" data-link-desc="LLM 對 long context 中段內容的 attention / recall 顯著低於開頭與結尾的現象">lost-in-the-middle</a> 相鄰，因為 chunk 順序會影響模型注意力。</p>
<h2 id="可觀察訊號與例子">可觀察訊號與例子</h2>
<p>常見 packing 決策包含 dedup 重複 chunk、把最相關內容放前後、按 document order 保留段落流、摘要或壓縮過長 chunks、在每段前加 source path 與 score。這些決策會改變答案品質、token cost 與可追溯性。</p>
<h2 id="設計責任">設計責任</h2>
<p>設計 context packing 時要回答：哪些 chunk 真的要進 prompt、順序如何安排、是否保留來源、是否需要 summarization / compression。高追溯場景優先保留 source metadata；長 context 場景要避免把重要 chunk 放在中間；latency 敏感場景要限制 top-k 與 compression call。</p>
]]></content:encoded></item><item><title>Deterministic vs Fuzzy engineering</title><link>https://tarrragon.github.io/blog/llm/knowledge-cards/deterministic-vs-fuzzy/</link><pubDate>Thu, 14 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/llm/knowledge-cards/deterministic-vs-fuzzy/</guid><description>&lt;p>Deterministic vs Fuzzy engineering 的核心概念是「&lt;strong>LLM 軟體跟傳統軟體在設計典範上的根本差異&lt;/strong>」。Deterministic 軟體建立在「同 input → 同 output」假設、fuzzy 軟體建立在「同 input → 分佈」假設。兩者在資料、邏輯、行為一致性、實驗成本四維度都不同、設計直覺要分開。實務上一個 LLM 應用是兩者混合、guardrail 設計是把 fuzzy 邊界包進 deterministic 約束。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>四維對照：&lt;/p>
&lt;table>
 &lt;thead>
 &lt;tr>
 &lt;th>維度&lt;/th>
 &lt;th>Deterministic 軟體&lt;/th>
 &lt;th>Fuzzy 軟體&lt;/th>
 &lt;/tr>
 &lt;/thead>
 &lt;tbody>
 &lt;tr>
 &lt;td>資料形狀&lt;/td>
 &lt;td>結構化（JSON、DB row）&lt;/td>
 &lt;td>半結構化 / 非結構化&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>邏輯來源&lt;/td>
 &lt;td>人類寫死規則&lt;/td>
 &lt;td>模型推論、依 prompt + context 浮動&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>行為一致性&lt;/td>
 &lt;td>同 input → 同 output&lt;/td>
 &lt;td>同 input → 分佈&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>分解原則&lt;/td>
 &lt;td>按職責 / 模組&lt;/td>
 &lt;td>按角色 / agent&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>測試方式&lt;/td>
 &lt;td>unit test、覆蓋率&lt;/td>
 &lt;td>eval、judge、distribution metric&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>實驗成本&lt;/td>
 &lt;td>高&lt;/td>
 &lt;td>低（改 prompt 即可）&lt;/td>
 &lt;/tr>
 &lt;/tbody>
&lt;/table>
&lt;p>典型 LLM 應用的混合：&lt;/p>





&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-text" data-lang="text">&lt;span class="line">&lt;span class="ln">1&lt;/span>&lt;span class="cl">User input
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">2&lt;/span>&lt;span class="cl"> ↓ Fuzzy（LLM 理解意圖）
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">3&lt;/span>&lt;span class="cl"> ↓ Deterministic（DB / API / policy）
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">4&lt;/span>&lt;span class="cl"> ↓ Fuzzy（LLM 寫回應）
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">5&lt;/span>&lt;span class="cl"> ↓ Deterministic（發送 / 寫入）&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>讀 LLM 應用設計文章或開始設計 production AI 系統時、這個 framing 決定每個 step 的工具選擇。實作判讀：&lt;/p>
&lt;ol>
&lt;li>&lt;strong>哪段該 deterministic / 哪段該 fuzzy&lt;/strong>：規則可窮舉、失敗代價高、需要解釋、需要 byte-exact 重現的 → deterministic；自由文字輸入、生成有風格的輸出、邊界模糊的 → fuzzy。&lt;/li>
&lt;li>&lt;strong>典範用錯的反模式&lt;/strong>：deterministic 需求硬用 fuzzy（用 LLM 算稅金）、fuzzy 需求硬用 deterministic（regex 解析自由文字）、邊界混（prompt 內塞算術 / code 內塞意圖分類）。&lt;/li>
&lt;li>&lt;strong>Fuzzy 邊界的四種 guardrail&lt;/strong>：schema validation、output validator、action gating、distribution monitoring。混用、不同 risk class 分擔不同層。&lt;/li>
&lt;li>&lt;strong>跟 &lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/human-in-the-loop/" data-link-title="Human-in-the-loop（HITL）" data-link-desc="人類介入 LLM 工作流的設計：三種觸發時機（pre-act / mid-stream / post-hoc）、避免橡皮圖章化的四條件">HITL&lt;/a> 的關係&lt;/strong>：HITL 是 deterministic guardrail 的一種——把人類判斷當 deterministic check 包 fuzzy LLM 行為。&lt;/li>
&lt;li>&lt;strong>失敗的歸因分層&lt;/strong>：壞掉時要問「是 prompt / model / context / tool / 還是 deterministic glue 的 bug」。deterministic 軟體歸因單一、fuzzy 軟體要分這幾層查。&lt;/li>
&lt;/ol>
&lt;p>完整典範討論見 &lt;a href="https://tarrragon.github.io/blog/llm/00-foundations/deterministic-vs-fuzzy-engineering/" data-link-title="0.8 Deterministic vs Fuzzy Engineering：軟體設計典範的位移" data-link-desc="傳統 deterministic 軟體跟 fuzzy LLM 軟體在資料、邏輯、分解、實驗成本四個維度的根本差異、以及哪段該 deterministic、哪段該 fuzzy 的決策框架">0.8 Deterministic vs Fuzzy Engineering&lt;/a>。&lt;/p></description><content:encoded><![CDATA[<p>Deterministic vs Fuzzy engineering 的核心概念是「<strong>LLM 軟體跟傳統軟體在設計典範上的根本差異</strong>」。Deterministic 軟體建立在「同 input → 同 output」假設、fuzzy 軟體建立在「同 input → 分佈」假設。兩者在資料、邏輯、行為一致性、實驗成本四維度都不同、設計直覺要分開。實務上一個 LLM 應用是兩者混合、guardrail 設計是把 fuzzy 邊界包進 deterministic 約束。</p>
<h2 id="概念位置">概念位置</h2>
<p>四維對照：</p>
<table>
  <thead>
      <tr>
          <th>維度</th>
          <th>Deterministic 軟體</th>
          <th>Fuzzy 軟體</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>資料形狀</td>
          <td>結構化（JSON、DB row）</td>
          <td>半結構化 / 非結構化</td>
      </tr>
      <tr>
          <td>邏輯來源</td>
          <td>人類寫死規則</td>
          <td>模型推論、依 prompt + context 浮動</td>
      </tr>
      <tr>
          <td>行為一致性</td>
          <td>同 input → 同 output</td>
          <td>同 input → 分佈</td>
      </tr>
      <tr>
          <td>分解原則</td>
          <td>按職責 / 模組</td>
          <td>按角色 / agent</td>
      </tr>
      <tr>
          <td>測試方式</td>
          <td>unit test、覆蓋率</td>
          <td>eval、judge、distribution metric</td>
      </tr>
      <tr>
          <td>實驗成本</td>
          <td>高</td>
          <td>低（改 prompt 即可）</td>
      </tr>
  </tbody>
</table>
<p>典型 LLM 應用的混合：</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="ln">1</span><span class="cl">User input
</span></span><span class="line"><span class="ln">2</span><span class="cl">   ↓ Fuzzy（LLM 理解意圖）
</span></span><span class="line"><span class="ln">3</span><span class="cl">   ↓ Deterministic（DB / API / policy）
</span></span><span class="line"><span class="ln">4</span><span class="cl">   ↓ Fuzzy（LLM 寫回應）
</span></span><span class="line"><span class="ln">5</span><span class="cl">   ↓ Deterministic（發送 / 寫入）</span></span></code></pre></div><h2 id="設計責任">設計責任</h2>
<p>讀 LLM 應用設計文章或開始設計 production AI 系統時、這個 framing 決定每個 step 的工具選擇。實作判讀：</p>
<ol>
<li><strong>哪段該 deterministic / 哪段該 fuzzy</strong>：規則可窮舉、失敗代價高、需要解釋、需要 byte-exact 重現的 → deterministic；自由文字輸入、生成有風格的輸出、邊界模糊的 → fuzzy。</li>
<li><strong>典範用錯的反模式</strong>：deterministic 需求硬用 fuzzy（用 LLM 算稅金）、fuzzy 需求硬用 deterministic（regex 解析自由文字）、邊界混（prompt 內塞算術 / code 內塞意圖分類）。</li>
<li><strong>Fuzzy 邊界的四種 guardrail</strong>：schema validation、output validator、action gating、distribution monitoring。混用、不同 risk class 分擔不同層。</li>
<li><strong>跟 <a href="/blog/llm/knowledge-cards/human-in-the-loop/" data-link-title="Human-in-the-loop（HITL）" data-link-desc="人類介入 LLM 工作流的設計：三種觸發時機（pre-act / mid-stream / post-hoc）、避免橡皮圖章化的四條件">HITL</a> 的關係</strong>：HITL 是 deterministic guardrail 的一種——把人類判斷當 deterministic check 包 fuzzy LLM 行為。</li>
<li><strong>失敗的歸因分層</strong>：壞掉時要問「是 prompt / model / context / tool / 還是 deterministic glue 的 bug」。deterministic 軟體歸因單一、fuzzy 軟體要分這幾層查。</li>
</ol>
<p>完整典範討論見 <a href="/blog/llm/00-foundations/deterministic-vs-fuzzy-engineering/" data-link-title="0.8 Deterministic vs Fuzzy Engineering：軟體設計典範的位移" data-link-desc="傳統 deterministic 軟體跟 fuzzy LLM 軟體在資料、邏輯、分解、實驗成本四個維度的根本差異、以及哪段該 deterministic、哪段該 fuzzy 的決策框架">0.8 Deterministic vs Fuzzy Engineering</a>。</p>
]]></content:encoded></item><item><title>DSL（Domain-Specific Language）</title><link>https://tarrragon.github.io/blog/llm/knowledge-cards/dsl/</link><pubDate>Thu, 14 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/llm/knowledge-cards/dsl/</guid><description>&lt;p>DSL（Domain-Specific Language）的核心概念是「&lt;strong>為特定領域設計的小語言&lt;/strong>」。它不像通用程式語言要解所有問題，而是把某個領域的可用操作、資料形狀與限制收斂成小而可解析的語法，讓人類、LLM 與程式都能用同一種中介表示溝通。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>在 LLM 應用裡，DSL 常出現在自然語言與程式執行之間。模型把使用者意圖轉成 DSL，應用再 parse、validate、authorize、execute；這比直接讓模型輸出任意程式碼更容易控管，也比純自然語言更容易自動化。&lt;/p>





&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-text" data-lang="text">&lt;span class="line">&lt;span class="ln">1&lt;/span>&lt;span class="cl">使用者：「找出高優先、尚未處理的 billing ticket」
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">2&lt;/span>&lt;span class="cl"> ↓
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">3&lt;/span>&lt;span class="cl">LLM 輸出 DSL：ticket.where(category=&amp;#34;billing&amp;#34;, priority=&amp;#34;high&amp;#34;, status!=&amp;#34;done&amp;#34;)
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">4&lt;/span>&lt;span class="cl"> ↓
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">5&lt;/span>&lt;span class="cl">parser / validator / executor&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h2 id="可觀察訊號與例子">可觀察訊號與例子&lt;/h2>
&lt;p>看到「特定 query language」「workflow mini-language」「policy expression」「filter expression」「tool command language」就是 DSL 候選。例子包括搜尋篩選語法、監控告警規則、資料轉換 pipeline、客服工單查詢、CI workflow 條件式。&lt;/p>
&lt;p>DSL 的風險是語法看起來可控，但語意與權限仍然危險。模型生成的 DSL 要經過 parser 確認語法、validator 確認欄位與型別、authorization 確認可操作範圍、dry run 或 preview 確認副作用；不能因為輸出不是通用程式碼就直接執行。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>DSL 適合操作集合固定、需要高可控性、且自然語言到執行之間需要審計紀錄的場景。設計時先定義最小語法、失敗路由與不可表示狀態；需要讓 LLM 穩定產生 DSL 時，用 &lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/grammar/" data-link-title="Grammar" data-link-desc="描述合法字串形狀的形式規則，在 structured output 中用來限制 LLM 每一步可輸出的 token">grammar&lt;/a> 或 JSON Schema 約束輸出。下一步路由是 &lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/structured-output/" data-link-title="Structured Output" data-link-desc="讓 LLM 輸出可被 parser 穩定消費的推論階段設計：JSON mode、schema-guided decoding、grammar 約束都屬於這一層">Structured Output&lt;/a> 與 &lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/sampling-constraint/" data-link-title="Sampling Constraint" data-link-desc="推論時限制下一個 token 候選集合的控制手段，用來把模型生成導向合法格式或特定選項">Sampling Constraint&lt;/a>。&lt;/p></description><content:encoded><![CDATA[<p>DSL（Domain-Specific Language）的核心概念是「<strong>為特定領域設計的小語言</strong>」。它不像通用程式語言要解所有問題，而是把某個領域的可用操作、資料形狀與限制收斂成小而可解析的語法，讓人類、LLM 與程式都能用同一種中介表示溝通。</p>
<h2 id="概念位置">概念位置</h2>
<p>在 LLM 應用裡，DSL 常出現在自然語言與程式執行之間。模型把使用者意圖轉成 DSL，應用再 parse、validate、authorize、execute；這比直接讓模型輸出任意程式碼更容易控管，也比純自然語言更容易自動化。</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="ln">1</span><span class="cl">使用者：「找出高優先、尚未處理的 billing ticket」
</span></span><span class="line"><span class="ln">2</span><span class="cl">  ↓
</span></span><span class="line"><span class="ln">3</span><span class="cl">LLM 輸出 DSL：ticket.where(category=&#34;billing&#34;, priority=&#34;high&#34;, status!=&#34;done&#34;)
</span></span><span class="line"><span class="ln">4</span><span class="cl">  ↓
</span></span><span class="line"><span class="ln">5</span><span class="cl">parser / validator / executor</span></span></code></pre></div><h2 id="可觀察訊號與例子">可觀察訊號與例子</h2>
<p>看到「特定 query language」「workflow mini-language」「policy expression」「filter expression」「tool command language」就是 DSL 候選。例子包括搜尋篩選語法、監控告警規則、資料轉換 pipeline、客服工單查詢、CI workflow 條件式。</p>
<p>DSL 的風險是語法看起來可控，但語意與權限仍然危險。模型生成的 DSL 要經過 parser 確認語法、validator 確認欄位與型別、authorization 確認可操作範圍、dry run 或 preview 確認副作用；不能因為輸出不是通用程式碼就直接執行。</p>
<h2 id="設計責任">設計責任</h2>
<p>DSL 適合操作集合固定、需要高可控性、且自然語言到執行之間需要審計紀錄的場景。設計時先定義最小語法、失敗路由與不可表示狀態；需要讓 LLM 穩定產生 DSL 時，用 <a href="/blog/llm/knowledge-cards/grammar/" data-link-title="Grammar" data-link-desc="描述合法字串形狀的形式規則，在 structured output 中用來限制 LLM 每一步可輸出的 token">grammar</a> 或 JSON Schema 約束輸出。下一步路由是 <a href="/blog/llm/knowledge-cards/structured-output/" data-link-title="Structured Output" data-link-desc="讓 LLM 輸出可被 parser 穩定消費的推論階段設計：JSON mode、schema-guided decoding、grammar 約束都屬於這一層">Structured Output</a> 與 <a href="/blog/llm/knowledge-cards/sampling-constraint/" data-link-title="Sampling Constraint" data-link-desc="推論時限制下一個 token 候選集合的控制手段，用來把模型生成導向合法格式或特定選項">Sampling Constraint</a>。</p>
]]></content:encoded></item><item><title>Few-shot prompting</title><link>https://tarrragon.github.io/blog/llm/knowledge-cards/few-shot-prompting/</link><pubDate>Thu, 14 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/llm/knowledge-cards/few-shot-prompting/</guid><description>&lt;p>Few-shot prompting 的核心概念是「&lt;strong>在 prompt 內塞幾個 input-output 範例、讓模型透過範例對齊任務&lt;/strong>」。Zero-shot 是不給範例直接給任務、few-shot 是給 1-N 個範例、模型從範例推任務分佈。屬於 in-context learning 的最常見形態、是「對齊任務」這件事的 prompt 層解法、跟 fine-tune 是兩個 endpoint。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>Zero-shot vs few-shot 對照：&lt;/p>





&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-text" data-lang="text">&lt;span class="line">&lt;span class="ln"> 1&lt;/span>&lt;span class="cl">Zero-shot：
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 2&lt;/span>&lt;span class="cl"> Classify the tone as positive/negative/neutral.
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 3&lt;/span>&lt;span class="cl"> Review: &amp;#34;Fine, but I expected more.&amp;#34;
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 4&lt;/span>&lt;span class="cl"> → 模型自己判斷「中性」邊界
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 5&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 6&lt;/span>&lt;span class="cl">Few-shot：
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 7&lt;/span>&lt;span class="cl"> Classify the tone as positive/negative/neutral.
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 8&lt;/span>&lt;span class="cl"> Examples:
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 9&lt;/span>&lt;span class="cl"> &amp;#34;Exceeded my expectations&amp;#34; → positive
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">10&lt;/span>&lt;span class="cl"> &amp;#34;OK, but I wish more features&amp;#34; → negative
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">11&lt;/span>&lt;span class="cl"> &amp;#34;Service was adequate&amp;#34; → neutral
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">12&lt;/span>&lt;span class="cl"> Review: &amp;#34;Fine, but I expected more.&amp;#34;
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">13&lt;/span>&lt;span class="cl"> → 模型按範例對齊、更傾向 negative&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>Few-shot 跟 fine-tune 對照：&lt;/p>
&lt;table>
 &lt;thead>
 &lt;tr>
 &lt;th>維度&lt;/th>
 &lt;th>Few-shot in prompt&lt;/th>
 &lt;th>Fine-tune&lt;/th>
 &lt;/tr>
 &lt;/thead>
 &lt;tbody>
 &lt;tr>
 &lt;td>Iteration&lt;/td>
 &lt;td>分鐘級、改 prompt 即可&lt;/td>
 &lt;td>天級、要 retrain&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>範例容量&lt;/td>
 &lt;td>受 context window 限制（10–50）&lt;/td>
 &lt;td>可以幾千幾萬、整個 dataset 都行&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>Cost&lt;/td>
 &lt;td>每次 inference 多付 token&lt;/td>
 &lt;td>一次性訓練 cost、之後 inference 不變&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>模型遷移&lt;/td>
 &lt;td>跨模型即時換、prompt 直接搬&lt;/td>
 &lt;td>綁特定 base model、換模型要 retrain&lt;/td>
 &lt;/tr>
 &lt;/tbody>
&lt;/table>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>讀 prompt engineering 文章或寫 production prompt 看到「few-shot」「in-context examples」就是這個機制。實作判讀：&lt;/p>
&lt;ol>
&lt;li>&lt;strong>適用任務有「我的標準跟模型預設不同」&lt;/strong>：分類邊界、抽取格式、tone alignment、structured output 形狀。&lt;/li>
&lt;li>&lt;strong>失效在範例選不好&lt;/strong>：cherry-picked 不代表 distribution、cover 不到 edge case、範例彼此衝突。&lt;/li>
&lt;li>&lt;strong>跟 &lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/chain-of-thought/" data-link-title="Chain-of-Thought（CoT）" data-link-desc="讓 LLM 先輸出推理步驟再給最終答案的 prompting / 訓練方式、reasoning model 的基礎機制">chain-of-thought&lt;/a> 可疊&lt;/strong>（few-shot CoT 是經典組合）、跟 fine-tune 是 endpoint 取捨。&lt;/li>
&lt;li>&lt;strong>何時轉 fine-tune&lt;/strong>：範例多到撐爆 &lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/context-window/" data-link-title="Context Window" data-link-desc="模型一次能處理的最大 token 數量：prompt 加生成的總和上限">context window&lt;/a> 又每天都用、才考慮。預設先 few-shot iterate。&lt;/li>
&lt;li>&lt;strong>Retrieval-augmented prompting&lt;/strong>：把寫死的 few-shot 換成從範例庫即時 retrieve、屬於 &lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/rag/" data-link-title="RAG" data-link-desc="Retrieval-Augmented Generation：動態外掛知識給 LLM、繞開模型參數記憶的靜態限制">RAG&lt;/a> 概念延伸。&lt;/li>
&lt;/ol>
&lt;p>完整 prompt 技術 landscape 見 &lt;a href="https://tarrragon.github.io/blog/llm/04-applications/prompt-techniques-landscape/" data-link-title="4.0 Prompt 技術光譜：手法分類、取捨、組合模式" data-link-desc="Zero-shot / few-shot、chain-of-thought、role / template、reflection 等 prompt 技術的分類與取捨、何時 stack 何時不要 stack、跟 fine-tune / RAG / chaining 的邊界">4.0 Prompt 技術光譜&lt;/a>。&lt;/p></description><content:encoded><![CDATA[<p>Few-shot prompting 的核心概念是「<strong>在 prompt 內塞幾個 input-output 範例、讓模型透過範例對齊任務</strong>」。Zero-shot 是不給範例直接給任務、few-shot 是給 1-N 個範例、模型從範例推任務分佈。屬於 in-context learning 的最常見形態、是「對齊任務」這件事的 prompt 層解法、跟 fine-tune 是兩個 endpoint。</p>
<h2 id="概念位置">概念位置</h2>
<p>Zero-shot vs few-shot 對照：</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="ln"> 1</span><span class="cl">Zero-shot：
</span></span><span class="line"><span class="ln"> 2</span><span class="cl">  Classify the tone as positive/negative/neutral.
</span></span><span class="line"><span class="ln"> 3</span><span class="cl">  Review: &#34;Fine, but I expected more.&#34;
</span></span><span class="line"><span class="ln"> 4</span><span class="cl">  → 模型自己判斷「中性」邊界
</span></span><span class="line"><span class="ln"> 5</span><span class="cl">
</span></span><span class="line"><span class="ln"> 6</span><span class="cl">Few-shot：
</span></span><span class="line"><span class="ln"> 7</span><span class="cl">  Classify the tone as positive/negative/neutral.
</span></span><span class="line"><span class="ln"> 8</span><span class="cl">  Examples:
</span></span><span class="line"><span class="ln"> 9</span><span class="cl">    &#34;Exceeded my expectations&#34; → positive
</span></span><span class="line"><span class="ln">10</span><span class="cl">    &#34;OK, but I wish more features&#34; → negative
</span></span><span class="line"><span class="ln">11</span><span class="cl">    &#34;Service was adequate&#34; → neutral
</span></span><span class="line"><span class="ln">12</span><span class="cl">  Review: &#34;Fine, but I expected more.&#34;
</span></span><span class="line"><span class="ln">13</span><span class="cl">  → 模型按範例對齊、更傾向 negative</span></span></code></pre></div><p>Few-shot 跟 fine-tune 對照：</p>
<table>
  <thead>
      <tr>
          <th>維度</th>
          <th>Few-shot in prompt</th>
          <th>Fine-tune</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>Iteration</td>
          <td>分鐘級、改 prompt 即可</td>
          <td>天級、要 retrain</td>
      </tr>
      <tr>
          <td>範例容量</td>
          <td>受 context window 限制（10–50）</td>
          <td>可以幾千幾萬、整個 dataset 都行</td>
      </tr>
      <tr>
          <td>Cost</td>
          <td>每次 inference 多付 token</td>
          <td>一次性訓練 cost、之後 inference 不變</td>
      </tr>
      <tr>
          <td>模型遷移</td>
          <td>跨模型即時換、prompt 直接搬</td>
          <td>綁特定 base model、換模型要 retrain</td>
      </tr>
  </tbody>
</table>
<h2 id="設計責任">設計責任</h2>
<p>讀 prompt engineering 文章或寫 production prompt 看到「few-shot」「in-context examples」就是這個機制。實作判讀：</p>
<ol>
<li><strong>適用任務有「我的標準跟模型預設不同」</strong>：分類邊界、抽取格式、tone alignment、structured output 形狀。</li>
<li><strong>失效在範例選不好</strong>：cherry-picked 不代表 distribution、cover 不到 edge case、範例彼此衝突。</li>
<li><strong>跟 <a href="/blog/llm/knowledge-cards/chain-of-thought/" data-link-title="Chain-of-Thought（CoT）" data-link-desc="讓 LLM 先輸出推理步驟再給最終答案的 prompting / 訓練方式、reasoning model 的基礎機制">chain-of-thought</a> 可疊</strong>（few-shot CoT 是經典組合）、跟 fine-tune 是 endpoint 取捨。</li>
<li><strong>何時轉 fine-tune</strong>：範例多到撐爆 <a href="/blog/llm/knowledge-cards/context-window/" data-link-title="Context Window" data-link-desc="模型一次能處理的最大 token 數量：prompt 加生成的總和上限">context window</a> 又每天都用、才考慮。預設先 few-shot iterate。</li>
<li><strong>Retrieval-augmented prompting</strong>：把寫死的 few-shot 換成從範例庫即時 retrieve、屬於 <a href="/blog/llm/knowledge-cards/rag/" data-link-title="RAG" data-link-desc="Retrieval-Augmented Generation：動態外掛知識給 LLM、繞開模型參數記憶的靜態限制">RAG</a> 概念延伸。</li>
</ol>
<p>完整 prompt 技術 landscape 見 <a href="/blog/llm/04-applications/prompt-techniques-landscape/" data-link-title="4.0 Prompt 技術光譜：手法分類、取捨、組合模式" data-link-desc="Zero-shot / few-shot、chain-of-thought、role / template、reflection 等 prompt 技術的分類與取捨、何時 stack 何時不要 stack、跟 fine-tune / RAG / chaining 的邊界">4.0 Prompt 技術光譜</a>。</p>
]]></content:encoded></item><item><title>Frozen baseline</title><link>https://tarrragon.github.io/blog/llm/knowledge-cards/frozen-baseline/</link><pubDate>Thu, 14 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/llm/knowledge-cards/frozen-baseline/</guid><description>&lt;p>Frozen baseline 的核心概念是「&lt;strong>把某個特定 prompt + 特定 model 跑 production 一段時間後 freeze、每次新版本都跟它比、定期 refresh 並標明時點&lt;/strong>」。Eval 系統的標準作法、讓行為漂移可見、避免「永遠跟上一版比、長期累積漂移看不見」的常見失敗。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>跟其他 eval 概念對照：&lt;/p>
&lt;table>
 &lt;thead>
 &lt;tr>
 &lt;th>概念&lt;/th>
 &lt;th>角色&lt;/th>
 &lt;/tr>
 &lt;/thead>
 &lt;tbody>
 &lt;tr>
 &lt;td>Eval set&lt;/td>
 &lt;td>測試 input 的集合&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>Frozen baseline&lt;/td>
 &lt;td>固定的「對照組」prompt + model 版本&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>Regression set&lt;/td>
 &lt;td>Failed case 進來、防止改 prompt 又壞同樣 case&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>Production trace&lt;/td>
 &lt;td>實際 traffic、抽樣補進 eval set / baseline&lt;/td>
 &lt;/tr>
 &lt;/tbody>
&lt;/table>
&lt;p>工作流：&lt;/p>





&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-text" data-lang="text">&lt;span class="line">&lt;span class="ln">1&lt;/span>&lt;span class="cl">Day 1：定義 eval set + 初始 prompt + model
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">2&lt;/span>&lt;span class="cl"> ↓ 跑 production 一段時間（如 2 週）
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">3&lt;/span>&lt;span class="cl">Day 14：把當下 prompt + model freeze 成 baseline-v1
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">4&lt;/span>&lt;span class="cl"> ↓
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">5&lt;/span>&lt;span class="cl">新版本 prompt / model 都跟 baseline-v1 比
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">6&lt;/span>&lt;span class="cl"> ↓ 定期（如每季）refresh
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">7&lt;/span>&lt;span class="cl">Day 90：baseline-v2、標明 refresh 時點&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>讀 eval / production AI 文章看到「frozen baseline」「baseline drift」「regression set」就是這個機制。實作判讀：&lt;/p>
&lt;ol>
&lt;li>&lt;strong>為什麼必要&lt;/strong>：每次 A/B 都跟「最新版本」比、長期累積漂移完全不可見、「整體變好了沒」無從回答。Frozen baseline 是漂移的錨點。&lt;/li>
&lt;li>&lt;strong>何時 freeze&lt;/strong>：production 跑穩、user 滿意度可接受時 freeze。太早 freeze 鎖到不夠好的版本、太晚 freeze 鎖不到。&lt;/li>
&lt;li>&lt;strong>何時 refresh&lt;/strong>：定期（每季 / 每半年）、或當 baseline 明顯 obsolete（如 model 升級、產品大改版）。Refresh 後標明時點、舊版本仍可保留當歷史對照。&lt;/li>
&lt;li>&lt;strong>跟 frozen baseline 一起的還有&lt;/strong>：regression set（failed case 永遠進、防 fix 一個壞一個）、production trace 抽樣補進 eval set（讓 eval set 不脫節）。&lt;/li>
&lt;li>&lt;strong>失敗模式&lt;/strong>：baseline 跟 production 分佈差太遠（baseline 用 lab case、production 是 wild input）、跑出來分數沒參考價值。緩解：baseline 的 eval set 用 production trace 抽樣建。&lt;/li>
&lt;/ol>
&lt;p>完整 eval 系統設計見 &lt;a href="https://tarrragon.github.io/blog/llm/04-applications/eval-design-framework/" data-link-title="4.13 Eval 設計座標系：三軸、八象限、何時測什麼" data-link-desc="Eval 設計三軸（objective↔subjective / component↔end-to-end / quantitative↔qualitative）、八象限的對應 eval 工具、軸選錯的訊號、跟 benchmarking / LLM-as-judge / tracing 的關係">4.13 Eval 設計座標系&lt;/a>。&lt;/p></description><content:encoded><![CDATA[<p>Frozen baseline 的核心概念是「<strong>把某個特定 prompt + 特定 model 跑 production 一段時間後 freeze、每次新版本都跟它比、定期 refresh 並標明時點</strong>」。Eval 系統的標準作法、讓行為漂移可見、避免「永遠跟上一版比、長期累積漂移看不見」的常見失敗。</p>
<h2 id="概念位置">概念位置</h2>
<p>跟其他 eval 概念對照：</p>
<table>
  <thead>
      <tr>
          <th>概念</th>
          <th>角色</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>Eval set</td>
          <td>測試 input 的集合</td>
      </tr>
      <tr>
          <td>Frozen baseline</td>
          <td>固定的「對照組」prompt + model 版本</td>
      </tr>
      <tr>
          <td>Regression set</td>
          <td>Failed case 進來、防止改 prompt 又壞同樣 case</td>
      </tr>
      <tr>
          <td>Production trace</td>
          <td>實際 traffic、抽樣補進 eval set / baseline</td>
      </tr>
  </tbody>
</table>
<p>工作流：</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="ln">1</span><span class="cl">Day 1：定義 eval set + 初始 prompt + model
</span></span><span class="line"><span class="ln">2</span><span class="cl">   ↓ 跑 production 一段時間（如 2 週）
</span></span><span class="line"><span class="ln">3</span><span class="cl">Day 14：把當下 prompt + model freeze 成 baseline-v1
</span></span><span class="line"><span class="ln">4</span><span class="cl">   ↓
</span></span><span class="line"><span class="ln">5</span><span class="cl">新版本 prompt / model 都跟 baseline-v1 比
</span></span><span class="line"><span class="ln">6</span><span class="cl">   ↓ 定期（如每季）refresh
</span></span><span class="line"><span class="ln">7</span><span class="cl">Day 90：baseline-v2、標明 refresh 時點</span></span></code></pre></div><h2 id="設計責任">設計責任</h2>
<p>讀 eval / production AI 文章看到「frozen baseline」「baseline drift」「regression set」就是這個機制。實作判讀：</p>
<ol>
<li><strong>為什麼必要</strong>：每次 A/B 都跟「最新版本」比、長期累積漂移完全不可見、「整體變好了沒」無從回答。Frozen baseline 是漂移的錨點。</li>
<li><strong>何時 freeze</strong>：production 跑穩、user 滿意度可接受時 freeze。太早 freeze 鎖到不夠好的版本、太晚 freeze 鎖不到。</li>
<li><strong>何時 refresh</strong>：定期（每季 / 每半年）、或當 baseline 明顯 obsolete（如 model 升級、產品大改版）。Refresh 後標明時點、舊版本仍可保留當歷史對照。</li>
<li><strong>跟 frozen baseline 一起的還有</strong>：regression set（failed case 永遠進、防 fix 一個壞一個）、production trace 抽樣補進 eval set（讓 eval set 不脫節）。</li>
<li><strong>失敗模式</strong>：baseline 跟 production 分佈差太遠（baseline 用 lab case、production 是 wild input）、跑出來分數沒參考價值。緩解：baseline 的 eval set 用 production trace 抽樣建。</li>
</ol>
<p>完整 eval 系統設計見 <a href="/blog/llm/04-applications/eval-design-framework/" data-link-title="4.13 Eval 設計座標系：三軸、八象限、何時測什麼" data-link-desc="Eval 設計三軸（objective↔subjective / component↔end-to-end / quantitative↔qualitative）、八象限的對應 eval 工具、軸選錯的訊號、跟 benchmarking / LLM-as-judge / tracing 的關係">4.13 Eval 設計座標系</a>。</p>
]]></content:encoded></item><item><title>Goal Drift</title><link>https://tarrragon.github.io/blog/llm/knowledge-cards/goal-drift/</link><pubDate>Thu, 14 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/llm/knowledge-cards/goal-drift/</guid><description>&lt;p>Goal drift（目標漂移）的核心概念是「&lt;strong>&lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/agent-loop/" data-link-title="Agent Loop" data-link-desc="LLM agent 自我循環的工作流：LLM 規劃下一步、執行 tool、看結果、再規劃下一步、直到任務完成或停止條件觸發">agent loop&lt;/a> 把子目標誤當成整體目標&lt;/strong>」。它常讓模型完成局部步驟後宣告任務完成，實際上還漏掉測試、驗證、提交、回報或其他原始要求。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>Goal drift 是 &lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/agent-loop/" data-link-title="Agent Loop" data-link-desc="LLM agent 自我循環的工作流：LLM 規劃下一步、執行 tool、看結果、再規劃下一步、直到任務完成或停止條件觸發">agent loop&lt;/a> 的 termination 失敗。它跟 &lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/context-drift/" data-link-title="Context Drift" data-link-desc="Agent 長任務中累積上下文逐步偏離原始目標，導致後續行動看似合理但整體跑偏">context drift&lt;/a> 的差異是：context drift 是上下文逐步偏移，goal drift 是完成條件被錯誤替換。&lt;/p>
&lt;h2 id="可觀察訊號與例子">可觀察訊號與例子&lt;/h2>
&lt;p>原任務是「實作、測試、commit」，agent 實作完就回答「已完成」，這是 goal drift。另一個訊號是 agent 每步都在完成一個合理子任務，但沒有維護整體 checklist。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>緩解方式是把完成條件外部化：test pass、檔案存在、PR 開啟、commit hash 產生、人工批准。不要只靠模型自評完成；高風險任務要用 checklist 與 deterministic gate。&lt;/p></description><content:encoded><![CDATA[<p>Goal drift（目標漂移）的核心概念是「<strong><a href="/blog/llm/knowledge-cards/agent-loop/" data-link-title="Agent Loop" data-link-desc="LLM agent 自我循環的工作流：LLM 規劃下一步、執行 tool、看結果、再規劃下一步、直到任務完成或停止條件觸發">agent loop</a> 把子目標誤當成整體目標</strong>」。它常讓模型完成局部步驟後宣告任務完成，實際上還漏掉測試、驗證、提交、回報或其他原始要求。</p>
<h2 id="概念位置">概念位置</h2>
<p>Goal drift 是 <a href="/blog/llm/knowledge-cards/agent-loop/" data-link-title="Agent Loop" data-link-desc="LLM agent 自我循環的工作流：LLM 規劃下一步、執行 tool、看結果、再規劃下一步、直到任務完成或停止條件觸發">agent loop</a> 的 termination 失敗。它跟 <a href="/blog/llm/knowledge-cards/context-drift/" data-link-title="Context Drift" data-link-desc="Agent 長任務中累積上下文逐步偏離原始目標，導致後續行動看似合理但整體跑偏">context drift</a> 的差異是：context drift 是上下文逐步偏移，goal drift 是完成條件被錯誤替換。</p>
<h2 id="可觀察訊號與例子">可觀察訊號與例子</h2>
<p>原任務是「實作、測試、commit」，agent 實作完就回答「已完成」，這是 goal drift。另一個訊號是 agent 每步都在完成一個合理子任務，但沒有維護整體 checklist。</p>
<h2 id="設計責任">設計責任</h2>
<p>緩解方式是把完成條件外部化：test pass、檔案存在、PR 開啟、commit hash 產生、人工批准。不要只靠模型自評完成；高風險任務要用 checklist 與 deterministic gate。</p>
]]></content:encoded></item><item><title>Grammar</title><link>https://tarrragon.github.io/blog/llm/knowledge-cards/grammar/</link><pubDate>Thu, 14 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/llm/knowledge-cards/grammar/</guid><description>&lt;p>Grammar（語法規則）的核心概念是「&lt;strong>用形式化規則描述哪些字串是合法輸出&lt;/strong>」。在 LLM structured output 裡，grammar 是 parser / decoder 可以執行的規則集合，用來判斷 JSON、SQL、DSL、表達式或自訂格式是否符合預期形狀——此處的 grammar 指形式語法，而非英文文法。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>Grammar 位在格式定義層，常被 &lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/constrained-decoding/" data-link-title="Constrained Decoding" data-link-desc="推論時用 grammar 強制 LLM 輸出符合特定格式（JSON / regex / CFG）的 sampling 機制、把不合法 token 的機率歸零">constrained decoding&lt;/a> 編譯成 token mask。它跟 schema 的差異在表達方式：schema 常描述資料結構與欄位限制，grammar 描述字串如何從符號規則生成；JSON Schema 適合物件欄位，grammar 適合自訂語言、查詢語法、括號結構與特定文字格式。&lt;/p>





&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-text" data-lang="text">&lt;span class="line">&lt;span class="ln">1&lt;/span>&lt;span class="cl">grammar 規則 → parser / decoder 編譯
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">2&lt;/span>&lt;span class="cl"> ↓
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">3&lt;/span>&lt;span class="cl">每個生成位置算出合法 token
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">4&lt;/span>&lt;span class="cl"> ↓
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">5&lt;/span>&lt;span class="cl">不合法 token 被 mask 掉&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h2 id="可觀察訊號與例子">可觀察訊號與例子&lt;/h2>
&lt;p>看到 &lt;code>expr: term (&amp;quot;+&amp;quot; term)*&lt;/code>、&lt;code>start: object&lt;/code>、&lt;code>&amp;lt;json&amp;gt; ::= ...&lt;/code> 這類規則就是 grammar。例子是讓模型只輸出簡化查詢語言：欄位只能是 &lt;code>status&lt;/code> / &lt;code>owner&lt;/code>，運算子只能是 &lt;code>=&lt;/code> / &lt;code>in&lt;/code>，字串必須加引號；grammar 可以把非法查詢擋在生成階段。&lt;/p>
&lt;p>Grammar 的邊界是語意與外部狀態。它可以限制語法合法，卻不能知道 &lt;code>owner = &amp;quot;alice&amp;quot;&lt;/code> 是否真有這個使用者，也不能判斷查詢是否符合權限；這些仍要交給 validator、authorization 與業務規則。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>需要自訂輸出格式時，先判斷格式是資料結構還是小語言：物件欄位優先用 JSON Schema，小語言或查詢語法才用 grammar。下一步路由是：需要語法表示法讀 &lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/bnf/" data-link-title="BNF（Backus-Naur Form）" data-link-desc="用遞迴產生式描述語法的經典記法，是 CFG、parser 與 grammar-constrained sampling 常見的基礎表示">BNF&lt;/a> 或 &lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/lark-grammar/" data-link-title="Lark Grammar" data-link-desc="Lark parser 使用的 EBNF-like grammar 格式，常被 structured output 工具拿來描述自訂輸出語法">Lark Grammar&lt;/a>；需要應用層自訂語言讀 &lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/dsl/" data-link-title="DSL（Domain-Specific Language）" data-link-desc="為特定業務或技術領域設計的小語言，在 LLM 應用中常作為可解析、可驗證、可執行的中介輸出">DSL&lt;/a>。&lt;/p></description><content:encoded><![CDATA[<p>Grammar（語法規則）的核心概念是「<strong>用形式化規則描述哪些字串是合法輸出</strong>」。在 LLM structured output 裡，grammar 是 parser / decoder 可以執行的規則集合，用來判斷 JSON、SQL、DSL、表達式或自訂格式是否符合預期形狀——此處的 grammar 指形式語法，而非英文文法。</p>
<h2 id="概念位置">概念位置</h2>
<p>Grammar 位在格式定義層，常被 <a href="/blog/llm/knowledge-cards/constrained-decoding/" data-link-title="Constrained Decoding" data-link-desc="推論時用 grammar 強制 LLM 輸出符合特定格式（JSON / regex / CFG）的 sampling 機制、把不合法 token 的機率歸零">constrained decoding</a> 編譯成 token mask。它跟 schema 的差異在表達方式：schema 常描述資料結構與欄位限制，grammar 描述字串如何從符號規則生成；JSON Schema 適合物件欄位，grammar 適合自訂語言、查詢語法、括號結構與特定文字格式。</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="ln">1</span><span class="cl">grammar 規則 → parser / decoder 編譯
</span></span><span class="line"><span class="ln">2</span><span class="cl">  ↓
</span></span><span class="line"><span class="ln">3</span><span class="cl">每個生成位置算出合法 token
</span></span><span class="line"><span class="ln">4</span><span class="cl">  ↓
</span></span><span class="line"><span class="ln">5</span><span class="cl">不合法 token 被 mask 掉</span></span></code></pre></div><h2 id="可觀察訊號與例子">可觀察訊號與例子</h2>
<p>看到 <code>expr: term (&quot;+&quot; term)*</code>、<code>start: object</code>、<code>&lt;json&gt; ::= ...</code> 這類規則就是 grammar。例子是讓模型只輸出簡化查詢語言：欄位只能是 <code>status</code> / <code>owner</code>，運算子只能是 <code>=</code> / <code>in</code>，字串必須加引號；grammar 可以把非法查詢擋在生成階段。</p>
<p>Grammar 的邊界是語意與外部狀態。它可以限制語法合法，卻不能知道 <code>owner = &quot;alice&quot;</code> 是否真有這個使用者，也不能判斷查詢是否符合權限；這些仍要交給 validator、authorization 與業務規則。</p>
<h2 id="設計責任">設計責任</h2>
<p>需要自訂輸出格式時，先判斷格式是資料結構還是小語言：物件欄位優先用 JSON Schema，小語言或查詢語法才用 grammar。下一步路由是：需要語法表示法讀 <a href="/blog/llm/knowledge-cards/bnf/" data-link-title="BNF（Backus-Naur Form）" data-link-desc="用遞迴產生式描述語法的經典記法，是 CFG、parser 與 grammar-constrained sampling 常見的基礎表示">BNF</a> 或 <a href="/blog/llm/knowledge-cards/lark-grammar/" data-link-title="Lark Grammar" data-link-desc="Lark parser 使用的 EBNF-like grammar 格式，常被 structured output 工具拿來描述自訂輸出語法">Lark Grammar</a>；需要應用層自訂語言讀 <a href="/blog/llm/knowledge-cards/dsl/" data-link-title="DSL（Domain-Specific Language）" data-link-desc="為特定業務或技術領域設計的小語言，在 LLM 應用中常作為可解析、可驗證、可執行的中介輸出">DSL</a>。</p>
]]></content:encoded></item><item><title>Grouped-Query Attention</title><link>https://tarrragon.github.io/blog/llm/knowledge-cards/grouped-query-attention/</link><pubDate>Thu, 14 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/llm/knowledge-cards/grouped-query-attention/</guid><description>&lt;p>Grouped-query attention（GQA）的核心概念是「&lt;strong>多個 query head 共用較少的 key/value head&lt;/strong>」。它介於 Multi-Head Attention 與 Multi-Query Attention 之間，用較小的品質代價換取更小的 &lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/kv-cache/" data-link-title="KV Cache" data-link-desc="已處理 token 的 attention 中間結果暫存：避免重算、加速後續生成">KV cache&lt;/a> 與更好的長 context serving 效率。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>GQA 是 &lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/multi-head-attention/" data-link-title="Multi-Head Attention" data-link-desc="把 attention 切成多個 head 並行計算、讓模型能同時注意多種模式">multi-head attention&lt;/a> 的推論友善變體。MHA 是每個 query head 都有自己的 K/V；MQA 是所有 query head 共用一組 K/V；GQA 則把 query head 分組，每組共用 K/V。&lt;/p>
&lt;h2 id="可觀察訊號與例子">可觀察訊號與例子&lt;/h2>
&lt;p>在 model config 裡看到 &lt;code>num_attention_heads: 32&lt;/code>、&lt;code>num_key_value_heads: 8&lt;/code>，代表 32 個 Q head 共用 8 組 K/V head，group size 是 4。這會讓 KV cache 約縮到 MHA 的四分之一，長 context 與高併發更友善。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>選模型或估算 serving 成本時，要看 &lt;code>num_key_value_heads&lt;/code>，而不是只看總參數。GQA 對本地推論特別重要，因為 &lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/context-window/" data-link-title="Context Window" data-link-desc="模型一次能處理的最大 token 數量：prompt 加生成的總和上限">context window&lt;/a> 與併發數常被 KV cache 卡住。&lt;/p></description><content:encoded><![CDATA[<p>Grouped-query attention（GQA）的核心概念是「<strong>多個 query head 共用較少的 key/value head</strong>」。它介於 Multi-Head Attention 與 Multi-Query Attention 之間，用較小的品質代價換取更小的 <a href="/blog/llm/knowledge-cards/kv-cache/" data-link-title="KV Cache" data-link-desc="已處理 token 的 attention 中間結果暫存：避免重算、加速後續生成">KV cache</a> 與更好的長 context serving 效率。</p>
<h2 id="概念位置">概念位置</h2>
<p>GQA 是 <a href="/blog/llm/knowledge-cards/multi-head-attention/" data-link-title="Multi-Head Attention" data-link-desc="把 attention 切成多個 head 並行計算、讓模型能同時注意多種模式">multi-head attention</a> 的推論友善變體。MHA 是每個 query head 都有自己的 K/V；MQA 是所有 query head 共用一組 K/V；GQA 則把 query head 分組，每組共用 K/V。</p>
<h2 id="可觀察訊號與例子">可觀察訊號與例子</h2>
<p>在 model config 裡看到 <code>num_attention_heads: 32</code>、<code>num_key_value_heads: 8</code>，代表 32 個 Q head 共用 8 組 K/V head，group size 是 4。這會讓 KV cache 約縮到 MHA 的四分之一，長 context 與高併發更友善。</p>
<h2 id="設計責任">設計責任</h2>
<p>選模型或估算 serving 成本時，要看 <code>num_key_value_heads</code>，而不是只看總參數。GQA 對本地推論特別重要，因為 <a href="/blog/llm/knowledge-cards/context-window/" data-link-title="Context Window" data-link-desc="模型一次能處理的最大 token 數量：prompt 加生成的總和上限">context window</a> 與併發數常被 KV cache 卡住。</p>
]]></content:encoded></item><item><title>Guardrail</title><link>https://tarrragon.github.io/blog/llm/knowledge-cards/guardrail/</link><pubDate>Thu, 14 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/llm/knowledge-cards/guardrail/</guid><description>&lt;p>Guardrail 的核心概念是「&lt;strong>在 LLM 的 fuzzy 行為外層加上可驗證的控制邊界&lt;/strong>」。LLM 本身會生成機率性輸出，guardrail 用 deterministic 檢查、policy、&lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/structured-output/" data-link-title="Structured Output" data-link-desc="讓 LLM 輸出可被 parser 穩定消費的推論階段設計：JSON mode、schema-guided decoding、grammar 約束都屬於這一層">structured output&lt;/a>、權限與人工審查，把錯誤後果限制在可承擔範圍內。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>Guardrail 是一組控制層。常見形式包含 &lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/structured-output/" data-link-title="Structured Output" data-link-desc="讓 LLM 輸出可被 parser 穩定消費的推論階段設計：JSON mode、schema-guided decoding、grammar 約束都屬於這一層">structured output&lt;/a>、validator、allowlist、rate limit、sandbox、human approval、eval、monitoring 與 rollback。它通常包在模型輸出與下游副作用之間。&lt;/p>
&lt;h2 id="可觀察訊號與例子">可觀察訊號與例子&lt;/h2>
&lt;p>客服分類可以用 enum schema 限制類別；tool use 可以用 allowlist 限制可呼叫工具；production 操作可以要求 &lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/human-in-the-loop/" data-link-title="Human-in-the-loop（HITL）" data-link-desc="人類介入 LLM 工作流的設計：三種觸發時機（pre-act / mid-stream / post-hoc）、避免橡皮圖章化的四條件">human-in-the-loop&lt;/a> approval；外部內容進 context 前可以標記為 untrusted，降低 prompt injection 後果。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>設計 guardrail 時先判斷失敗代價，再選控制強度。低風險任務用 schema 與 retry 即可；高副作用任務要加 permission boundary、sandbox、審查與 audit log。相關基礎見 &lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/deterministic-vs-fuzzy/" data-link-title="Deterministic vs Fuzzy engineering" data-link-desc="LLM 軟體 vs 傳統軟體在資料 / 邏輯 / 行為一致性 / 實驗成本四維度的典範差異、決定哪段該包 guardrail">Deterministic vs Fuzzy engineering&lt;/a>。&lt;/p></description><content:encoded><![CDATA[<p>Guardrail 的核心概念是「<strong>在 LLM 的 fuzzy 行為外層加上可驗證的控制邊界</strong>」。LLM 本身會生成機率性輸出，guardrail 用 deterministic 檢查、policy、<a href="/blog/llm/knowledge-cards/structured-output/" data-link-title="Structured Output" data-link-desc="讓 LLM 輸出可被 parser 穩定消費的推論階段設計：JSON mode、schema-guided decoding、grammar 約束都屬於這一層">structured output</a>、權限與人工審查，把錯誤後果限制在可承擔範圍內。</p>
<h2 id="概念位置">概念位置</h2>
<p>Guardrail 是一組控制層。常見形式包含 <a href="/blog/llm/knowledge-cards/structured-output/" data-link-title="Structured Output" data-link-desc="讓 LLM 輸出可被 parser 穩定消費的推論階段設計：JSON mode、schema-guided decoding、grammar 約束都屬於這一層">structured output</a>、validator、allowlist、rate limit、sandbox、human approval、eval、monitoring 與 rollback。它通常包在模型輸出與下游副作用之間。</p>
<h2 id="可觀察訊號與例子">可觀察訊號與例子</h2>
<p>客服分類可以用 enum schema 限制類別；tool use 可以用 allowlist 限制可呼叫工具；production 操作可以要求 <a href="/blog/llm/knowledge-cards/human-in-the-loop/" data-link-title="Human-in-the-loop（HITL）" data-link-desc="人類介入 LLM 工作流的設計：三種觸發時機（pre-act / mid-stream / post-hoc）、避免橡皮圖章化的四條件">human-in-the-loop</a> approval；外部內容進 context 前可以標記為 untrusted，降低 prompt injection 後果。</p>
<h2 id="設計責任">設計責任</h2>
<p>設計 guardrail 時先判斷失敗代價，再選控制強度。低風險任務用 schema 與 retry 即可；高副作用任務要加 permission boundary、sandbox、審查與 audit log。相關基礎見 <a href="/blog/llm/knowledge-cards/deterministic-vs-fuzzy/" data-link-title="Deterministic vs Fuzzy engineering" data-link-desc="LLM 軟體 vs 傳統軟體在資料 / 邏輯 / 行為一致性 / 實驗成本四維度的典範差異、決定哪段該包 guardrail">Deterministic vs Fuzzy engineering</a>。</p>
]]></content:encoded></item><item><title>Human-in-the-loop（HITL）</title><link>https://tarrragon.github.io/blog/llm/knowledge-cards/human-in-the-loop/</link><pubDate>Thu, 14 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/llm/knowledge-cards/human-in-the-loop/</guid><description>&lt;p>Human-in-the-loop（HITL）的核心概念是「&lt;strong>人類在 LLM 工作流中介入的設計&lt;/strong>」、用來在 fuzzy AI 行為的關鍵節點插入 deterministic 人類判斷。HITL 不是「有 vs 沒有」的二元、是 spectrum：位置由 risk（副作用範圍 + 失敗代價）跟自動 validator 能力決定。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>HITL 三種觸發時機：&lt;/p>
&lt;table>
 &lt;thead>
 &lt;tr>
 &lt;th>時機&lt;/th>
 &lt;th>介入點&lt;/th>
 &lt;th>適合任務&lt;/th>
 &lt;/tr>
 &lt;/thead>
 &lt;tbody>
 &lt;tr>
 &lt;td>Pre-act&lt;/td>
 &lt;td>Action 執行前確認&lt;/td>
 &lt;td>不可逆 / 高代價（DB write、deploy）&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>Mid-stream&lt;/td>
 &lt;td>Agent 過程中遇不確定主動問&lt;/td>
 &lt;td>路徑分歧、需要 domain judgment&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>Post-hoc&lt;/td>
 &lt;td>結果交付後 user 申訴 / 校正&lt;/td>
 &lt;td>評分類、低代價、user 數量大&lt;/td>
 &lt;/tr>
 &lt;/tbody>
&lt;/table>
&lt;p>跟其他相關概念對照：&lt;/p>
&lt;table>
 &lt;thead>
 &lt;tr>
 &lt;th>概念&lt;/th>
 &lt;th>跟 HITL 的關係&lt;/th>
 &lt;/tr>
 &lt;/thead>
 &lt;tbody>
 &lt;tr>
 &lt;td>Agent 自主度分層&lt;/td>
 &lt;td>Full auto / checkpoint / step-by-step / plan-first → 對應 HITL 時機&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>Tool 副作用範圍&lt;/td>
 &lt;td>等級 1-2 不需 HITL、等級 4-5 強制 HITL&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>Guardrail&lt;/td>
 &lt;td>Schema / validator / monitoring 是自動 guardrail、HITL 是人類 guardrail&lt;/td>
 &lt;/tr>
 &lt;/tbody>
&lt;/table>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>讀 AI 應用設計或 agent paper 看到「HITL」「human-in-the-loop」「approval flow」「appeal」就是這個機制。實作判讀：&lt;/p>
&lt;ol>
&lt;li>&lt;strong>位置由 risk 跟 validator 能力決定&lt;/strong>：risk 高 + validator 弱、HITL 頻率高；risk 低 + validator 強、HITL 頻率低。&lt;/li>
&lt;li>&lt;strong>三時機可組合&lt;/strong>：pre-act 擋高代價、mid-stream 處理 agent 不確定性、post-hoc 收回饋。三者各擋不同 risk class、不互斥。&lt;/li>
&lt;li>&lt;strong>避免橡皮圖章化的四條件&lt;/strong>：分級不同 risk 走不同 gate、approval UI 強制 show diff、reject 有明確 fallback、approval 訊號回饋進系統。任一不滿足、HITL 退化成形式。&lt;/li>
&lt;li>&lt;strong>跟 &lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/jagged-frontier/" data-link-title="Jagged frontier" data-link-desc="AI 能力分佈不規則的 framing：某些看似簡單的任務 AI 容易壞、某些看似複雜的任務 AI 反而做得好">jagged frontier&lt;/a> 的關係&lt;/strong>：frontier 外的任務該強制 HITL、不交給 user 自由心證。&lt;/li>
&lt;li>&lt;strong>跟 fuzzy engineering 典範的關係&lt;/strong>：HITL 是 fuzzy 行為的 deterministic guardrail 一種、不是預設要有、看 risk 跟自動 validator 能力決定。&lt;/li>
&lt;/ol>
&lt;p>完整 HITL 拓樸設計見 &lt;a href="https://tarrragon.github.io/blog/llm/04-applications/human-ai-collaboration/" data-link-title="4.5 人機協作拓樸：何時人介入、怎麼介入" data-link-desc="Centaur vs Cyborg 工作模式、jagged frontier、HITL 三種觸發時機（pre-act / mid-stream / post-hoc）、確認流程的設計避免橡皮圖章化">4.5 人機協作拓樸&lt;/a>。&lt;/p></description><content:encoded><![CDATA[<p>Human-in-the-loop（HITL）的核心概念是「<strong>人類在 LLM 工作流中介入的設計</strong>」、用來在 fuzzy AI 行為的關鍵節點插入 deterministic 人類判斷。HITL 不是「有 vs 沒有」的二元、是 spectrum：位置由 risk（副作用範圍 + 失敗代價）跟自動 validator 能力決定。</p>
<h2 id="概念位置">概念位置</h2>
<p>HITL 三種觸發時機：</p>
<table>
  <thead>
      <tr>
          <th>時機</th>
          <th>介入點</th>
          <th>適合任務</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>Pre-act</td>
          <td>Action 執行前確認</td>
          <td>不可逆 / 高代價（DB write、deploy）</td>
      </tr>
      <tr>
          <td>Mid-stream</td>
          <td>Agent 過程中遇不確定主動問</td>
          <td>路徑分歧、需要 domain judgment</td>
      </tr>
      <tr>
          <td>Post-hoc</td>
          <td>結果交付後 user 申訴 / 校正</td>
          <td>評分類、低代價、user 數量大</td>
      </tr>
  </tbody>
</table>
<p>跟其他相關概念對照：</p>
<table>
  <thead>
      <tr>
          <th>概念</th>
          <th>跟 HITL 的關係</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>Agent 自主度分層</td>
          <td>Full auto / checkpoint / step-by-step / plan-first → 對應 HITL 時機</td>
      </tr>
      <tr>
          <td>Tool 副作用範圍</td>
          <td>等級 1-2 不需 HITL、等級 4-5 強制 HITL</td>
      </tr>
      <tr>
          <td>Guardrail</td>
          <td>Schema / validator / monitoring 是自動 guardrail、HITL 是人類 guardrail</td>
      </tr>
  </tbody>
</table>
<h2 id="設計責任">設計責任</h2>
<p>讀 AI 應用設計或 agent paper 看到「HITL」「human-in-the-loop」「approval flow」「appeal」就是這個機制。實作判讀：</p>
<ol>
<li><strong>位置由 risk 跟 validator 能力決定</strong>：risk 高 + validator 弱、HITL 頻率高；risk 低 + validator 強、HITL 頻率低。</li>
<li><strong>三時機可組合</strong>：pre-act 擋高代價、mid-stream 處理 agent 不確定性、post-hoc 收回饋。三者各擋不同 risk class、不互斥。</li>
<li><strong>避免橡皮圖章化的四條件</strong>：分級不同 risk 走不同 gate、approval UI 強制 show diff、reject 有明確 fallback、approval 訊號回饋進系統。任一不滿足、HITL 退化成形式。</li>
<li><strong>跟 <a href="/blog/llm/knowledge-cards/jagged-frontier/" data-link-title="Jagged frontier" data-link-desc="AI 能力分佈不規則的 framing：某些看似簡單的任務 AI 容易壞、某些看似複雜的任務 AI 反而做得好">jagged frontier</a> 的關係</strong>：frontier 外的任務該強制 HITL、不交給 user 自由心證。</li>
<li><strong>跟 fuzzy engineering 典範的關係</strong>：HITL 是 fuzzy 行為的 deterministic guardrail 一種、不是預設要有、看 risk 跟自動 validator 能力決定。</li>
</ol>
<p>完整 HITL 拓樸設計見 <a href="/blog/llm/04-applications/human-ai-collaboration/" data-link-title="4.5 人機協作拓樸：何時人介入、怎麼介入" data-link-desc="Centaur vs Cyborg 工作模式、jagged frontier、HITL 三種觸發時機（pre-act / mid-stream / post-hoc）、確認流程的設計避免橡皮圖章化">4.5 人機協作拓樸</a>。</p>
]]></content:encoded></item><item><title>HyDE（Hypothetical Document Embeddings）</title><link>https://tarrragon.github.io/blog/llm/knowledge-cards/hyde/</link><pubDate>Thu, 14 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/llm/knowledge-cards/hyde/</guid><description>&lt;p>HyDE（Hypothetical Document Embeddings、Gao et al. 2022）是 &lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/rag/" data-link-title="RAG" data-link-desc="Retrieval-Augmented Generation：動態外掛知識給 LLM、繞開模型參數記憶的靜態限制">RAG&lt;/a> retrieval 階段的 query 端增強技術。核心觀察：&lt;strong>query 跟 document 在 embedding 空間的距離往往比 document 跟 document 之間更遠&lt;/strong>——這是典型 &lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/query-document-gap/" data-link-title="Query-Document Gap" data-link-desc="使用者 query 與文件語言在詞彙、形態、抽象層級或領域分佈上的落差，是 RAG retrieval miss 的常見原因">query-document gap&lt;/a>。HyDE 的做法是先用 LLM 對 query 生成「假設的答案文件」、對假文件做 embedding 拿去 retrieve、而不是直接 embed 原 query。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>HyDE 三步：&lt;/p>





&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-text" data-lang="text">&lt;span class="line">&lt;span class="ln"> 1&lt;/span>&lt;span class="cl">User query
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 2&lt;/span>&lt;span class="cl"> ↓
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 3&lt;/span>&lt;span class="cl">[Step 1] LLM 生成 hypothetical document
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 4&lt;/span>&lt;span class="cl"> (可能 hallucinate、事實正確性不重要)
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 5&lt;/span>&lt;span class="cl"> ↓
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 6&lt;/span>&lt;span class="cl">[Step 2] Embed 假文件
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 7&lt;/span>&lt;span class="cl"> ↓
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 8&lt;/span>&lt;span class="cl">[Step 3] 用假文件 embedding 去 vector DB retrieve 真文件
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 9&lt;/span>&lt;span class="cl"> ↓
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">10&lt;/span>&lt;span class="cl">真實 top-k chunks → 主 LLM 回答&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>為什麼比直接 embed query 好：假文件的 phrasing、長度、結構都更接近真文件的分佈、embedding 距離更可靠。重點是&lt;strong>假文件當 embedding 的代理&lt;/strong>、不是當答案——hallucinate 出錯誤事實 OK、但語意 / 領域要落對。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>讀 RAG paper 或工具看到「HyDE」「hypothetical document」「query-side augmentation」就是這個機制。實作判讀：&lt;/p>
&lt;ol>
&lt;li>&lt;strong>適用 phrasing 落差顯著的場景&lt;/strong>：問句 vs 陳述、口語 vs 正式、抽象 vs 技術詞彙。HyDE 原論文跨多領域都有提升、不限技術 / 學術。&lt;/li>
&lt;li>&lt;strong>失效在假文件偏離主題&lt;/strong>：LLM hallucinate 到別領域、retrieve 拿到完全不相關的東西。緩解：生成多個假文件取平均 embedding、或用 query + 假文件兩個 embedding 合併 retrieve。&lt;/li>
&lt;li>&lt;strong>Cost&lt;/strong>：每 query 多一個 LLM call（生假文件）、latency 加 500ms-1s，屬於明顯的 &lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/retrieval-cost/" data-link-title="Retrieval Cost" data-link-desc="RAG 檢索帶來的 latency、token、embedding、reranker、LLM call 與維護成本，用來判斷增強是否划算">retrieval cost&lt;/a>。對 latency 敏感場景考慮 &lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/query-rewriting/" data-link-title="Query Rewriting" data-link-desc="在 RAG 檢索前改寫使用者查詢，讓 query 更接近文件語言與索引分佈">query rewriting&lt;/a> 等較輕量的替代。&lt;/li>
&lt;li>&lt;strong>跟 &lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/hybrid-search/" data-link-title="Hybrid Search" data-link-desc="把字面 retrieval（BM25）跟語意 retrieval（embedding）的結果用 RRF 等方法合併、補單一路線的盲點">hybrid search&lt;/a> 互補&lt;/strong>：HyDE 解語意 phrasing 落差、hybrid 解語意 / 字面互補、可以同時用。&lt;/li>
&lt;/ol>
&lt;p>完整 RAG 檢索增強技術 landscape 見 &lt;a href="https://tarrragon.github.io/blog/llm/04-applications/rag-retrieval-enhancements/" data-link-title="4.2 RAG 檢索增強：query rewriting / HyDE / multi-step / context packing" data-link-desc="Query 端增強（rewriting / expansion / HyDE）、multi-step iterative retrieval、retrieve 後的 context packing（dedup / ordering / summarization）、adaptive retrieval：vanilla RAG 不夠時的下一層工具箱">4.2 RAG 檢索增強&lt;/a>。&lt;/p></description><content:encoded><![CDATA[<p>HyDE（Hypothetical Document Embeddings、Gao et al. 2022）是 <a href="/blog/llm/knowledge-cards/rag/" data-link-title="RAG" data-link-desc="Retrieval-Augmented Generation：動態外掛知識給 LLM、繞開模型參數記憶的靜態限制">RAG</a> retrieval 階段的 query 端增強技術。核心觀察：<strong>query 跟 document 在 embedding 空間的距離往往比 document 跟 document 之間更遠</strong>——這是典型 <a href="/blog/llm/knowledge-cards/query-document-gap/" data-link-title="Query-Document Gap" data-link-desc="使用者 query 與文件語言在詞彙、形態、抽象層級或領域分佈上的落差，是 RAG retrieval miss 的常見原因">query-document gap</a>。HyDE 的做法是先用 LLM 對 query 生成「假設的答案文件」、對假文件做 embedding 拿去 retrieve、而不是直接 embed 原 query。</p>
<h2 id="概念位置">概念位置</h2>
<p>HyDE 三步：</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="ln"> 1</span><span class="cl">User query
</span></span><span class="line"><span class="ln"> 2</span><span class="cl">   ↓
</span></span><span class="line"><span class="ln"> 3</span><span class="cl">[Step 1] LLM 生成 hypothetical document
</span></span><span class="line"><span class="ln"> 4</span><span class="cl">         (可能 hallucinate、事實正確性不重要)
</span></span><span class="line"><span class="ln"> 5</span><span class="cl">   ↓
</span></span><span class="line"><span class="ln"> 6</span><span class="cl">[Step 2] Embed 假文件
</span></span><span class="line"><span class="ln"> 7</span><span class="cl">   ↓
</span></span><span class="line"><span class="ln"> 8</span><span class="cl">[Step 3] 用假文件 embedding 去 vector DB retrieve 真文件
</span></span><span class="line"><span class="ln"> 9</span><span class="cl">   ↓
</span></span><span class="line"><span class="ln">10</span><span class="cl">真實 top-k chunks → 主 LLM 回答</span></span></code></pre></div><p>為什麼比直接 embed query 好：假文件的 phrasing、長度、結構都更接近真文件的分佈、embedding 距離更可靠。重點是<strong>假文件當 embedding 的代理</strong>、不是當答案——hallucinate 出錯誤事實 OK、但語意 / 領域要落對。</p>
<h2 id="設計責任">設計責任</h2>
<p>讀 RAG paper 或工具看到「HyDE」「hypothetical document」「query-side augmentation」就是這個機制。實作判讀：</p>
<ol>
<li><strong>適用 phrasing 落差顯著的場景</strong>：問句 vs 陳述、口語 vs 正式、抽象 vs 技術詞彙。HyDE 原論文跨多領域都有提升、不限技術 / 學術。</li>
<li><strong>失效在假文件偏離主題</strong>：LLM hallucinate 到別領域、retrieve 拿到完全不相關的東西。緩解：生成多個假文件取平均 embedding、或用 query + 假文件兩個 embedding 合併 retrieve。</li>
<li><strong>Cost</strong>：每 query 多一個 LLM call（生假文件）、latency 加 500ms-1s，屬於明顯的 <a href="/blog/llm/knowledge-cards/retrieval-cost/" data-link-title="Retrieval Cost" data-link-desc="RAG 檢索帶來的 latency、token、embedding、reranker、LLM call 與維護成本，用來判斷增強是否划算">retrieval cost</a>。對 latency 敏感場景考慮 <a href="/blog/llm/knowledge-cards/query-rewriting/" data-link-title="Query Rewriting" data-link-desc="在 RAG 檢索前改寫使用者查詢，讓 query 更接近文件語言與索引分佈">query rewriting</a> 等較輕量的替代。</li>
<li><strong>跟 <a href="/blog/llm/knowledge-cards/hybrid-search/" data-link-title="Hybrid Search" data-link-desc="把字面 retrieval（BM25）跟語意 retrieval（embedding）的結果用 RRF 等方法合併、補單一路線的盲點">hybrid search</a> 互補</strong>：HyDE 解語意 phrasing 落差、hybrid 解語意 / 字面互補、可以同時用。</li>
</ol>
<p>完整 RAG 檢索增強技術 landscape 見 <a href="/blog/llm/04-applications/rag-retrieval-enhancements/" data-link-title="4.2 RAG 檢索增強：query rewriting / HyDE / multi-step / context packing" data-link-desc="Query 端增強（rewriting / expansion / HyDE）、multi-step iterative retrieval、retrieve 後的 context packing（dedup / ordering / summarization）、adaptive retrieval：vanilla RAG 不夠時的下一層工具箱">4.2 RAG 檢索增強</a>。</p>
]]></content:encoded></item><item><title>In-Context Learning</title><link>https://tarrragon.github.io/blog/llm/knowledge-cards/in-context-learning/</link><pubDate>Thu, 14 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/llm/knowledge-cards/in-context-learning/</guid><description>&lt;p>In-context learning（ICL）的核心概念是「&lt;strong>模型在不更新權重的情況下，從 &lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/context-window/" data-link-title="Context Window" data-link-desc="模型一次能處理的最大 token 數量：prompt 加生成的總和上限">context window&lt;/a> 內資訊臨時學會任務格式與判準&lt;/strong>」。它是 LLM 跟傳統模型最不同的能力之一：任務規則可以放在 context 裡，而不是一定要 fine-tune 進權重。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>ICL 是推論時行為，不是訓練流程。&lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/few-shot-prompting/" data-link-title="Few-shot prompting" data-link-desc="在 prompt 內塞 input-output 範例對齊任務、不動模型權重的 in-context learning 技術">Few-shot prompting&lt;/a> 是 ICL 最常見的操作方式；SFT、LoRA、QLoRA 則是修改權重的訓練或微調方式。&lt;/p>
&lt;h2 id="可觀察訊號與例子">可觀察訊號與例子&lt;/h2>
&lt;p>給模型三個分類範例後，第四個樣本就按同一標準分類，這是 ICL。把專案命名規則、輸出格式、review rubric 放進 prompt，模型在當次回合遵守，也屬於 ICL。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>ICL 適合快速迭代與少量範例；當範例多到吃滿 &lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/context-window/" data-link-title="Context Window" data-link-desc="模型一次能處理的最大 token 數量：prompt 加生成的總和上限">context window&lt;/a>、每天重複使用且標準穩定時，再考慮 fine-tune。需要穩定輸出格式時，ICL 應搭配 &lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/structured-output/" data-link-title="Structured Output" data-link-desc="讓 LLM 輸出可被 parser 穩定消費的推論階段設計：JSON mode、schema-guided decoding、grammar 約束都屬於這一層">structured output&lt;/a> 或 validator。&lt;/p></description><content:encoded><![CDATA[<p>In-context learning（ICL）的核心概念是「<strong>模型在不更新權重的情況下，從 <a href="/blog/llm/knowledge-cards/context-window/" data-link-title="Context Window" data-link-desc="模型一次能處理的最大 token 數量：prompt 加生成的總和上限">context window</a> 內資訊臨時學會任務格式與判準</strong>」。它是 LLM 跟傳統模型最不同的能力之一：任務規則可以放在 context 裡，而不是一定要 fine-tune 進權重。</p>
<h2 id="概念位置">概念位置</h2>
<p>ICL 是推論時行為，不是訓練流程。<a href="/blog/llm/knowledge-cards/few-shot-prompting/" data-link-title="Few-shot prompting" data-link-desc="在 prompt 內塞 input-output 範例對齊任務、不動模型權重的 in-context learning 技術">Few-shot prompting</a> 是 ICL 最常見的操作方式；SFT、LoRA、QLoRA 則是修改權重的訓練或微調方式。</p>
<h2 id="可觀察訊號與例子">可觀察訊號與例子</h2>
<p>給模型三個分類範例後，第四個樣本就按同一標準分類，這是 ICL。把專案命名規則、輸出格式、review rubric 放進 prompt，模型在當次回合遵守，也屬於 ICL。</p>
<h2 id="設計責任">設計責任</h2>
<p>ICL 適合快速迭代與少量範例；當範例多到吃滿 <a href="/blog/llm/knowledge-cards/context-window/" data-link-title="Context Window" data-link-desc="模型一次能處理的最大 token 數量：prompt 加生成的總和上限">context window</a>、每天重複使用且標準穩定時，再考慮 fine-tune。需要穩定輸出格式時，ICL 應搭配 <a href="/blog/llm/knowledge-cards/structured-output/" data-link-title="Structured Output" data-link-desc="讓 LLM 輸出可被 parser 穩定消費的推論階段設計：JSON mode、schema-guided decoding、grammar 約束都屬於這一層">structured output</a> 或 validator。</p>
]]></content:encoded></item><item><title>Instruction Following</title><link>https://tarrragon.github.io/blog/llm/knowledge-cards/instruction-following/</link><pubDate>Thu, 14 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/llm/knowledge-cards/instruction-following/</guid><description>&lt;p>Instruction following 的核心概念是「&lt;strong>模型能否遵守使用者或系統給定的任務約束&lt;/strong>」。它關注模型是否照格式輸出、是否留在任務範圍、是否遵守長度與禁止事項，跟 &lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/instruction-tuned/" data-link-title="Instruction-Tuned Model" data-link-desc="經過指令微調的模型：會跟著 prompt 走、回答使用者問題">instruction-tuned model&lt;/a> 這種訓練後模型類型相關，但不是同一件事。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>&lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/instruction-tuned/" data-link-title="Instruction-Tuned Model" data-link-desc="經過指令微調的模型：會跟著 prompt 走、回答使用者問題">Instruction-tuned model&lt;/a> 是訓練狀態，instruction following 是行為表現。模型可能經過 SFT，仍在細格式、邊界條件或多約束任務上失敗；也可能在簡單指令上表現穩定，但遇到衝突指令或長 prompt 漏掉限制。&lt;/p>
&lt;h2 id="可觀察訊號與例子">可觀察訊號與例子&lt;/h2>
&lt;p>測試訊號包含：是否輸出指定 JSON、是否只回答要求的欄位、是否避免多餘解釋、是否在資料不足時說不知道、是否遵守「不要呼叫工具」或「只讀不寫」。本地小模型常在簡單問答可用，但在多條格式限制同時存在時掉分。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>評估 instruction following 時要做 coverage 測試：格式、長度、拒答、資料不足、衝突指令、跨語言指令都要看。失敗時優先用更清楚的 prompt、few-shot、structured output 或 validator 兜底；長期穩定需求才考慮 fine-tune。&lt;/p></description><content:encoded><![CDATA[<p>Instruction following 的核心概念是「<strong>模型能否遵守使用者或系統給定的任務約束</strong>」。它關注模型是否照格式輸出、是否留在任務範圍、是否遵守長度與禁止事項，跟 <a href="/blog/llm/knowledge-cards/instruction-tuned/" data-link-title="Instruction-Tuned Model" data-link-desc="經過指令微調的模型：會跟著 prompt 走、回答使用者問題">instruction-tuned model</a> 這種訓練後模型類型相關，但不是同一件事。</p>
<h2 id="概念位置">概念位置</h2>
<p><a href="/blog/llm/knowledge-cards/instruction-tuned/" data-link-title="Instruction-Tuned Model" data-link-desc="經過指令微調的模型：會跟著 prompt 走、回答使用者問題">Instruction-tuned model</a> 是訓練狀態，instruction following 是行為表現。模型可能經過 SFT，仍在細格式、邊界條件或多約束任務上失敗；也可能在簡單指令上表現穩定，但遇到衝突指令或長 prompt 漏掉限制。</p>
<h2 id="可觀察訊號與例子">可觀察訊號與例子</h2>
<p>測試訊號包含：是否輸出指定 JSON、是否只回答要求的欄位、是否避免多餘解釋、是否在資料不足時說不知道、是否遵守「不要呼叫工具」或「只讀不寫」。本地小模型常在簡單問答可用，但在多條格式限制同時存在時掉分。</p>
<h2 id="設計責任">設計責任</h2>
<p>評估 instruction following 時要做 coverage 測試：格式、長度、拒答、資料不足、衝突指令、跨語言指令都要看。失敗時優先用更清楚的 prompt、few-shot、structured output 或 validator 兜底；長期穩定需求才考慮 fine-tune。</p>
]]></content:encoded></item><item><title>Jagged frontier</title><link>https://tarrragon.github.io/blog/llm/knowledge-cards/jagged-frontier/</link><pubDate>Thu, 14 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/llm/knowledge-cards/jagged-frontier/</guid><description>&lt;p>Jagged frontier（鋸齒狀邊界、HBS / UPenn / Wharton BCG 顧問研究、2023）是 AI 能力分佈的 framing：&lt;strong>「AI 能做的任務」呈鋸齒狀分佈，而非按人類直覺的難易連續排列&lt;/strong>——某些看起來簡單的任務 AI 容易壞、某些看起來複雜的任務 AI 反而做得好。原因是能力分佈跟訓練資料 / tokenizer / 推論機制相關、不跟人類直覺的「難易」對齊。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>典型對照（2024-2025 觀察、會隨模型升級漂移）：&lt;/p>
&lt;table>
 &lt;thead>
 &lt;tr>
 &lt;th>看起來簡單但 AI 容易壞&lt;/th>
 &lt;th>看起來複雜但 AI 做得好&lt;/th>
 &lt;/tr>
 &lt;/thead>
 &lt;tbody>
 &lt;tr>
 &lt;td>精確算術&lt;/td>
 &lt;td>寫風格指定的程式碼&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>計數&lt;/td>
 &lt;td>翻譯複雜技術文章&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>嚴格遵守冷僻格式&lt;/td>
 &lt;td>從文字抽取關鍵 entity&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>引用真實 URL&lt;/td>
 &lt;td>解釋複雜概念&lt;/td>
 &lt;/tr>
 &lt;/tbody>
&lt;/table>
&lt;p>各失敗的機制各不相同：算術靠符號操作 + tokenizer 把數字切碎、計數跟 attention 機制不對盤、冷僻格式不在訓練分佈中、URL &lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/hallucination/" data-link-title="Hallucination" data-link-desc="LLM 生成內容看起來合理但事實錯誤、引用不存在的來源、虛構不存在的 entity 的現象">hallucination&lt;/a> 是模型分辨不了「真實 vs 看起來合理」。Reasoning model + tool use 普及後 frontier 會移動、表的價值在 framing「不規則」、不是具體 4 個 case 當定論。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>讀 AI 應用設計文章看到「jagged frontier」「AI capability boundary」「falling asleep at the wheel」就是這個 framing。設計判讀：&lt;/p>
&lt;ol>
&lt;li>&lt;strong>不要用人類直覺難易推測 AI 能力&lt;/strong>：試跑、看結果、不要預判。&lt;/li>
&lt;li>&lt;strong>「全自動」是 over-trust 假設&lt;/strong>：frontier 鋸齒、總有些子任務落 frontier 外、需要人介入或 tool 補。設計時假設「有部分子任務 AI 會失敗」、不是「都會成功」。&lt;/li>
&lt;li>&lt;strong>失敗在 frontier 外加 prompt iteration 通常無效&lt;/strong>：那是模型能力邊界問題、不是 prompt 問題。對應 &lt;a href="https://tarrragon.github.io/blog/llm/04-applications/prompt-techniques-landscape/" data-link-title="4.0 Prompt 技術光譜：手法分類、取捨、組合模式" data-link-desc="Zero-shot / few-shot、chain-of-thought、role / template、reflection 等 prompt 技術的分類與取捨、何時 stack 何時不要 stack、跟 fine-tune / RAG / chaining 的邊界">prompt 技術光譜&lt;/a> 的 systematic vs random error 診斷。&lt;/li>
&lt;li>&lt;strong>Falling asleep at the wheel&lt;/strong>：BCG 研究觀察到的人類行為——傾向不分辨任務是否在 frontier 內、對 AI 結果一律低度審查。緩解：對團隊 / user 明確標 frontier、frontier 外任務強制人類審查（HITL）、抽樣審查偵測 frontier 漂移。&lt;/li>
&lt;/ol>
&lt;p>完整人機協作 framing 見 &lt;a href="https://tarrragon.github.io/blog/llm/04-applications/human-ai-collaboration/" data-link-title="4.5 人機協作拓樸：何時人介入、怎麼介入" data-link-desc="Centaur vs Cyborg 工作模式、jagged frontier、HITL 三種觸發時機（pre-act / mid-stream / post-hoc）、確認流程的設計避免橡皮圖章化">4.5 人機協作拓樸&lt;/a>。&lt;/p></description><content:encoded><![CDATA[<p>Jagged frontier（鋸齒狀邊界、HBS / UPenn / Wharton BCG 顧問研究、2023）是 AI 能力分佈的 framing：<strong>「AI 能做的任務」呈鋸齒狀分佈，而非按人類直覺的難易連續排列</strong>——某些看起來簡單的任務 AI 容易壞、某些看起來複雜的任務 AI 反而做得好。原因是能力分佈跟訓練資料 / tokenizer / 推論機制相關、不跟人類直覺的「難易」對齊。</p>
<h2 id="概念位置">概念位置</h2>
<p>典型對照（2024-2025 觀察、會隨模型升級漂移）：</p>
<table>
  <thead>
      <tr>
          <th>看起來簡單但 AI 容易壞</th>
          <th>看起來複雜但 AI 做得好</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>精確算術</td>
          <td>寫風格指定的程式碼</td>
      </tr>
      <tr>
          <td>計數</td>
          <td>翻譯複雜技術文章</td>
      </tr>
      <tr>
          <td>嚴格遵守冷僻格式</td>
          <td>從文字抽取關鍵 entity</td>
      </tr>
      <tr>
          <td>引用真實 URL</td>
          <td>解釋複雜概念</td>
      </tr>
  </tbody>
</table>
<p>各失敗的機制各不相同：算術靠符號操作 + tokenizer 把數字切碎、計數跟 attention 機制不對盤、冷僻格式不在訓練分佈中、URL <a href="/blog/llm/knowledge-cards/hallucination/" data-link-title="Hallucination" data-link-desc="LLM 生成內容看起來合理但事實錯誤、引用不存在的來源、虛構不存在的 entity 的現象">hallucination</a> 是模型分辨不了「真實 vs 看起來合理」。Reasoning model + tool use 普及後 frontier 會移動、表的價值在 framing「不規則」、不是具體 4 個 case 當定論。</p>
<h2 id="設計責任">設計責任</h2>
<p>讀 AI 應用設計文章看到「jagged frontier」「AI capability boundary」「falling asleep at the wheel」就是這個 framing。設計判讀：</p>
<ol>
<li><strong>不要用人類直覺難易推測 AI 能力</strong>：試跑、看結果、不要預判。</li>
<li><strong>「全自動」是 over-trust 假設</strong>：frontier 鋸齒、總有些子任務落 frontier 外、需要人介入或 tool 補。設計時假設「有部分子任務 AI 會失敗」、不是「都會成功」。</li>
<li><strong>失敗在 frontier 外加 prompt iteration 通常無效</strong>：那是模型能力邊界問題、不是 prompt 問題。對應 <a href="/blog/llm/04-applications/prompt-techniques-landscape/" data-link-title="4.0 Prompt 技術光譜：手法分類、取捨、組合模式" data-link-desc="Zero-shot / few-shot、chain-of-thought、role / template、reflection 等 prompt 技術的分類與取捨、何時 stack 何時不要 stack、跟 fine-tune / RAG / chaining 的邊界">prompt 技術光譜</a> 的 systematic vs random error 診斷。</li>
<li><strong>Falling asleep at the wheel</strong>：BCG 研究觀察到的人類行為——傾向不分辨任務是否在 frontier 內、對 AI 結果一律低度審查。緩解：對團隊 / user 明確標 frontier、frontier 外任務強制人類審查（HITL）、抽樣審查偵測 frontier 漂移。</li>
</ol>
<p>完整人機協作 framing 見 <a href="/blog/llm/04-applications/human-ai-collaboration/" data-link-title="4.5 人機協作拓樸：何時人介入、怎麼介入" data-link-desc="Centaur vs Cyborg 工作模式、jagged frontier、HITL 三種觸發時機（pre-act / mid-stream / post-hoc）、確認流程的設計避免橡皮圖章化">4.5 人機協作拓樸</a>。</p>
]]></content:encoded></item><item><title>Lark Grammar</title><link>https://tarrragon.github.io/blog/llm/knowledge-cards/lark-grammar/</link><pubDate>Thu, 14 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/llm/knowledge-cards/lark-grammar/</guid><description>&lt;p>Lark grammar 的核心概念是「&lt;strong>Lark parser 使用的一種 EBNF-like 語法描述格式&lt;/strong>」。在 LLM structured output 文件中看到 lark grammar，通常是在說某個工具用 Lark 風格規則描述合法輸出，再把規則交給 parser 或 constrained decoding engine。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>Lark 是 Python 生態的 parsing toolkit，Lark grammar 是它的規則語言。它比傳統 &lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/bnf/" data-link-title="BNF（Backus-Naur Form）" data-link-desc="用遞迴產生式描述語法的經典記法，是 CFG、parser 與 grammar-constrained sampling 常見的基礎表示">BNF&lt;/a> 更接近實作格式，常見元素包含 rule、terminal、literal、repeat、optional、ignore whitespace 與 start rule。&lt;/p>





&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-text" data-lang="text">&lt;span class="line">&lt;span class="ln">1&lt;/span>&lt;span class="cl">start: query
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">2&lt;/span>&lt;span class="cl">query: FIELD OP VALUE
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">3&lt;/span>&lt;span class="cl">FIELD: &amp;#34;status&amp;#34; | &amp;#34;owner&amp;#34;
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">4&lt;/span>&lt;span class="cl">OP: &amp;#34;=&amp;#34; | &amp;#34;!=&amp;#34;
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">5&lt;/span>&lt;span class="cl">VALUE: ESCAPED_STRING
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">6&lt;/span>&lt;span class="cl">%import common.ESCAPED_STRING
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">7&lt;/span>&lt;span class="cl">%ignore &amp;#34; &amp;#34;&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>這段規則描述一個很小的查詢語言，只允許固定欄位、固定運算子與 quoted string。&lt;/p>
&lt;h2 id="可觀察訊號與例子">可觀察訊號與例子&lt;/h2>
&lt;p>看到 &lt;code>start:&lt;/code>、大寫 terminal、&lt;code>%import common.*&lt;/code>、&lt;code>%ignore&lt;/code>，通常就是 Lark grammar 或受它影響的格式。LLM 場景常用它描述 JSON 子集、SQL-like query、指令 DSL、分類輸出或固定格式報告。&lt;/p>
&lt;p>Lark grammar 的風險是把 parser 格式誤當跨引擎標準。某些 constrained decoding 工具支援 Lark-like 語法，某些只支援 JSON Schema、regex、GBNF 或自家格式；搬規則前要確認目標 server 能不能解析同一套語法。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>Lark grammar 適合需要清楚描述自訂格式、且工具鏈支援 Lark dialect 的場景。設計時先把合法範圍縮到應用真的需要的語法，再補 validator 處理外部狀態與權限。下一步路由是 &lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/grammar/" data-link-title="Grammar" data-link-desc="描述合法字串形狀的形式規則，在 structured output 中用來限制 LLM 每一步可輸出的 token">Grammar&lt;/a> 與 &lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/dsl/" data-link-title="DSL（Domain-Specific Language）" data-link-desc="為特定業務或技術領域設計的小語言，在 LLM 應用中常作為可解析、可驗證、可執行的中介輸出">DSL&lt;/a>。&lt;/p></description><content:encoded><![CDATA[<p>Lark grammar 的核心概念是「<strong>Lark parser 使用的一種 EBNF-like 語法描述格式</strong>」。在 LLM structured output 文件中看到 lark grammar，通常是在說某個工具用 Lark 風格規則描述合法輸出，再把規則交給 parser 或 constrained decoding engine。</p>
<h2 id="概念位置">概念位置</h2>
<p>Lark 是 Python 生態的 parsing toolkit，Lark grammar 是它的規則語言。它比傳統 <a href="/blog/llm/knowledge-cards/bnf/" data-link-title="BNF（Backus-Naur Form）" data-link-desc="用遞迴產生式描述語法的經典記法，是 CFG、parser 與 grammar-constrained sampling 常見的基礎表示">BNF</a> 更接近實作格式，常見元素包含 rule、terminal、literal、repeat、optional、ignore whitespace 與 start rule。</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="ln">1</span><span class="cl">start: query
</span></span><span class="line"><span class="ln">2</span><span class="cl">query: FIELD OP VALUE
</span></span><span class="line"><span class="ln">3</span><span class="cl">FIELD: &#34;status&#34; | &#34;owner&#34;
</span></span><span class="line"><span class="ln">4</span><span class="cl">OP: &#34;=&#34; | &#34;!=&#34;
</span></span><span class="line"><span class="ln">5</span><span class="cl">VALUE: ESCAPED_STRING
</span></span><span class="line"><span class="ln">6</span><span class="cl">%import common.ESCAPED_STRING
</span></span><span class="line"><span class="ln">7</span><span class="cl">%ignore &#34; &#34;</span></span></code></pre></div><p>這段規則描述一個很小的查詢語言，只允許固定欄位、固定運算子與 quoted string。</p>
<h2 id="可觀察訊號與例子">可觀察訊號與例子</h2>
<p>看到 <code>start:</code>、大寫 terminal、<code>%import common.*</code>、<code>%ignore</code>，通常就是 Lark grammar 或受它影響的格式。LLM 場景常用它描述 JSON 子集、SQL-like query、指令 DSL、分類輸出或固定格式報告。</p>
<p>Lark grammar 的風險是把 parser 格式誤當跨引擎標準。某些 constrained decoding 工具支援 Lark-like 語法，某些只支援 JSON Schema、regex、GBNF 或自家格式；搬規則前要確認目標 server 能不能解析同一套語法。</p>
<h2 id="設計責任">設計責任</h2>
<p>Lark grammar 適合需要清楚描述自訂格式、且工具鏈支援 Lark dialect 的場景。設計時先把合法範圍縮到應用真的需要的語法，再補 validator 處理外部狀態與權限。下一步路由是 <a href="/blog/llm/knowledge-cards/grammar/" data-link-title="Grammar" data-link-desc="描述合法字串形狀的形式規則，在 structured output 中用來限制 LLM 每一步可輸出的 token">Grammar</a> 與 <a href="/blog/llm/knowledge-cards/dsl/" data-link-title="DSL（Domain-Specific Language）" data-link-desc="為特定業務或技術領域設計的小語言，在 LLM 應用中常作為可解析、可驗證、可執行的中介輸出">DSL</a>。</p>
]]></content:encoded></item><item><title>llama.cpp Tensor Split</title><link>https://tarrragon.github.io/blog/llm/knowledge-cards/llama-cpp-tensor-split/</link><pubDate>Thu, 14 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/llm/knowledge-cards/llama-cpp-tensor-split/</guid><description>&lt;p>llama.cpp tensor split 的核心概念是「&lt;strong>在多 GPU 推論時，把模型張量按比例分配到不同 GPU&lt;/strong>」。它解的是單張卡 &lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/vram/" data-link-title="VRAM" data-link-desc="顯卡上的記憶體、跟系統 RAM 是兩塊獨立預算、決定能載入多大模型權重跟 KV cache">VRAM&lt;/a> 不足或多卡容量不均時的模型權重擺放問題。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>Tensor split 位在 inference server / GPU serving 層，跟 &lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/nvlink/" data-link-title="NVLink" data-link-desc="NVIDIA 多 GPU 之間的高速互連介面、提供比 PCIe 更高的卡間頻寬、消費級 RTX 系列普遍不支援">NVLink&lt;/a> 或 &lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/pcie/" data-link-title="PCIe" data-link-desc="PC 上連接 GPU 跟主機板的高速序列匯流排、影響模型載入速度跟 MoE 卸載時的推論吞吐">PCIe&lt;/a> 是不同責任：互連決定卡間傳輸成本，tensor split 決定權重怎麼分布。&lt;/p>
&lt;h2 id="可觀察訊號與例子">可觀察訊號與例子&lt;/h2>
&lt;p>在 llama.cpp 看到 &lt;code>--tensor-split&lt;/code> 或 &lt;code>-ts&lt;/code>，通常是在手動指定多卡分配比例。兩張 VRAM 不同的卡可以用不同比例，避免小卡先 OOM。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>只有多 GPU 且需要手動控制分配時才需要它。單卡消費級 PC 通常不用；多卡沒有高速互連時，分割模型可能降低速度，需用實際 benchmark 校準。&lt;/p></description><content:encoded><![CDATA[<p>llama.cpp tensor split 的核心概念是「<strong>在多 GPU 推論時，把模型張量按比例分配到不同 GPU</strong>」。它解的是單張卡 <a href="/blog/llm/knowledge-cards/vram/" data-link-title="VRAM" data-link-desc="顯卡上的記憶體、跟系統 RAM 是兩塊獨立預算、決定能載入多大模型權重跟 KV cache">VRAM</a> 不足或多卡容量不均時的模型權重擺放問題。</p>
<h2 id="概念位置">概念位置</h2>
<p>Tensor split 位在 inference server / GPU serving 層，跟 <a href="/blog/llm/knowledge-cards/nvlink/" data-link-title="NVLink" data-link-desc="NVIDIA 多 GPU 之間的高速互連介面、提供比 PCIe 更高的卡間頻寬、消費級 RTX 系列普遍不支援">NVLink</a> 或 <a href="/blog/llm/knowledge-cards/pcie/" data-link-title="PCIe" data-link-desc="PC 上連接 GPU 跟主機板的高速序列匯流排、影響模型載入速度跟 MoE 卸載時的推論吞吐">PCIe</a> 是不同責任：互連決定卡間傳輸成本，tensor split 決定權重怎麼分布。</p>
<h2 id="可觀察訊號與例子">可觀察訊號與例子</h2>
<p>在 llama.cpp 看到 <code>--tensor-split</code> 或 <code>-ts</code>，通常是在手動指定多卡分配比例。兩張 VRAM 不同的卡可以用不同比例，避免小卡先 OOM。</p>
<h2 id="設計責任">設計責任</h2>
<p>只有多 GPU 且需要手動控制分配時才需要它。單卡消費級 PC 通常不用；多卡沒有高速互連時，分割模型可能降低速度，需用實際 benchmark 校準。</p>
]]></content:encoded></item><item><title>Local vs Cloud LLM</title><link>https://tarrragon.github.io/blog/llm/knowledge-cards/local-vs-cloud/</link><pubDate>Thu, 14 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/llm/knowledge-cards/local-vs-cloud/</guid><description>&lt;p>Local vs cloud LLM 的核心概念是「&lt;strong>把模型執行位置視為工程取捨，而不是信仰選擇&lt;/strong>」。本地 LLM 把資料、權重與 &lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/inference-server/" data-link-title="Inference Server" data-link-desc="載入模型權重、處理 prompt、產生 token 的常駐 process">推論伺服器&lt;/a> 放在自己的機器上；雲端 LLM 把 serving 與模型能力交給 provider，換取更強模型與更低維運負擔。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>這個決策跨越 &lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/three-layer-architecture/" data-link-title="Three-Layer Architecture" data-link-desc="把本地 LLM 工具拆成介面層、推論伺服器層、模型權重層的基礎心智模型">three-layer architecture&lt;/a> 的所有層：介面可以相同，伺服器與模型位置不同。常見組合是同一個 IDE 介面同時接本地 &lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/openai-compatible-api/" data-link-title="OpenAI 相容 API" data-link-desc="本地推論伺服器跟雲端 OpenAI 共用的 API 形狀標準">OpenAI 相容 API&lt;/a> 與雲端 API，依任務切換。&lt;/p>
&lt;h2 id="可觀察訊號與例子">可觀察訊號與例子&lt;/h2>
&lt;p>本地適合私有資料、離線、可控成本、低資料外流風險；雲端適合高難度 reasoning、大型 agent、多模態、需要最新旗艦能力的任務。混合策略常見於 coding：本地做補完、摘要、低風險查詢，雲端處理複雜修復與大型 agent loop。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>判斷時看五個訊號：資料敏感度、模型能力需求、延遲體感、每月成本、維運能力。當任務失敗代價高且能力要求高，雲端未必可替代人工審查；當資料敏感且任務簡單，本地模型通常更划算。完整框架見 &lt;a href="https://tarrragon.github.io/blog/llm/00-foundations/local-vs-cloud/" data-link-title="0.0 本地 vs 雲端 LLM" data-link-desc="從隱私、成本、速度、能力四個維度建立本地與雲端 LLM 的基本對照">0.6 本地 vs 雲端&lt;/a>。&lt;/p></description><content:encoded><![CDATA[<p>Local vs cloud LLM 的核心概念是「<strong>把模型執行位置視為工程取捨，而不是信仰選擇</strong>」。本地 LLM 把資料、權重與 <a href="/blog/llm/knowledge-cards/inference-server/" data-link-title="Inference Server" data-link-desc="載入模型權重、處理 prompt、產生 token 的常駐 process">推論伺服器</a> 放在自己的機器上；雲端 LLM 把 serving 與模型能力交給 provider，換取更強模型與更低維運負擔。</p>
<h2 id="概念位置">概念位置</h2>
<p>這個決策跨越 <a href="/blog/llm/knowledge-cards/three-layer-architecture/" data-link-title="Three-Layer Architecture" data-link-desc="把本地 LLM 工具拆成介面層、推論伺服器層、模型權重層的基礎心智模型">three-layer architecture</a> 的所有層：介面可以相同，伺服器與模型位置不同。常見組合是同一個 IDE 介面同時接本地 <a href="/blog/llm/knowledge-cards/openai-compatible-api/" data-link-title="OpenAI 相容 API" data-link-desc="本地推論伺服器跟雲端 OpenAI 共用的 API 形狀標準">OpenAI 相容 API</a> 與雲端 API，依任務切換。</p>
<h2 id="可觀察訊號與例子">可觀察訊號與例子</h2>
<p>本地適合私有資料、離線、可控成本、低資料外流風險；雲端適合高難度 reasoning、大型 agent、多模態、需要最新旗艦能力的任務。混合策略常見於 coding：本地做補完、摘要、低風險查詢，雲端處理複雜修復與大型 agent loop。</p>
<h2 id="設計責任">設計責任</h2>
<p>判斷時看五個訊號：資料敏感度、模型能力需求、延遲體感、每月成本、維運能力。當任務失敗代價高且能力要求高，雲端未必可替代人工審查；當資料敏感且任務簡單，本地模型通常更划算。完整框架見 <a href="/blog/llm/00-foundations/local-vs-cloud/" data-link-title="0.0 本地 vs 雲端 LLM" data-link-desc="從隱私、成本、速度、能力四個維度建立本地與雲端 LLM 的基本對照">0.6 本地 vs 雲端</a>。</p>
]]></content:encoded></item><item><title>Model Supply-Chain Trust</title><link>https://tarrragon.github.io/blog/llm/knowledge-cards/model-supply-chain-trust/</link><pubDate>Thu, 14 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/llm/knowledge-cards/model-supply-chain-trust/</guid><description>&lt;p>Model supply-chain trust 的核心概念是「&lt;strong>把模型權重來源、量化者、registry 與本機檔案都視為信任邊界&lt;/strong>」。本地 LLM 下載的是可影響模型行為的 &lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/gguf/" data-link-title="GGUF" data-link-desc="llama.cpp 生態定義的模型權重格式：把權重、tokenizer、metadata 打包成單一檔案">GGUF&lt;/a> 或其他權重檔，來源與完整性會直接影響安全與可靠性。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>它位在模型層與安全治理交界，跟 &lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/model-card/" data-link-title="Model Card" data-link-desc="Hugging Face 等平台上模型的 metadata 文件、列出模型來源、訓練資料、能力、限制、授權">model card&lt;/a> 不同：model card 提供 metadata，supply-chain trust 判斷來源、hash、量化流程、namespace 與散發路徑是否可信。&lt;/p>
&lt;h2 id="可觀察訊號與例子">可觀察訊號與例子&lt;/h2>
&lt;p>官方 organization、知名量化者、verified registry、可比對 hash、清楚 license 與 model card 都提升信任；個人上傳、來源不明、檔案被替換、缺 metadata 都降低信任。GGUF、Safetensors、Ollama registry、Hugging Face Hub 都在這條鏈上。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>下載模型前確認來源；下載後記錄 SHA-256、檔案大小與版本；第三方量化要看量化者信譽與社群採用。MCP server 與 plugin 是另一條可執行程式碼供應鏈，要用更高權限標準判讀。&lt;/p></description><content:encoded><![CDATA[<p>Model supply-chain trust 的核心概念是「<strong>把模型權重來源、量化者、registry 與本機檔案都視為信任邊界</strong>」。本地 LLM 下載的是可影響模型行為的 <a href="/blog/llm/knowledge-cards/gguf/" data-link-title="GGUF" data-link-desc="llama.cpp 生態定義的模型權重格式：把權重、tokenizer、metadata 打包成單一檔案">GGUF</a> 或其他權重檔，來源與完整性會直接影響安全與可靠性。</p>
<h2 id="概念位置">概念位置</h2>
<p>它位在模型層與安全治理交界，跟 <a href="/blog/llm/knowledge-cards/model-card/" data-link-title="Model Card" data-link-desc="Hugging Face 等平台上模型的 metadata 文件、列出模型來源、訓練資料、能力、限制、授權">model card</a> 不同：model card 提供 metadata，supply-chain trust 判斷來源、hash、量化流程、namespace 與散發路徑是否可信。</p>
<h2 id="可觀察訊號與例子">可觀察訊號與例子</h2>
<p>官方 organization、知名量化者、verified registry、可比對 hash、清楚 license 與 model card 都提升信任；個人上傳、來源不明、檔案被替換、缺 metadata 都降低信任。GGUF、Safetensors、Ollama registry、Hugging Face Hub 都在這條鏈上。</p>
<h2 id="設計責任">設計責任</h2>
<p>下載模型前確認來源；下載後記錄 SHA-256、檔案大小與版本；第三方量化要看量化者信譽與社群採用。MCP server 與 plugin 是另一條可執行程式碼供應鏈，要用更高權限標準判讀。</p>
]]></content:encoded></item><item><title>Multi-agent system</title><link>https://tarrragon.github.io/blog/llm/knowledge-cards/multi-agent-system/</link><pubDate>Thu, 14 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/llm/knowledge-cards/multi-agent-system/</guid><description>&lt;p>Multi-agent system 的核心概念是「&lt;strong>多個 LLM &lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/agent/" data-link-title="LLM Agent" data-link-desc="把控制流交給 LLM 的應用模式：自主決策、跨多步呼叫工具、人類角色從主導變監督">agent&lt;/a> 協作完成任務&lt;/strong>」。跟 multi-call workflow 的差異&lt;strong>不在 agent 數量多寡、在控制流跟責任邊界&lt;/strong>——multi-call 是主程式編排每 step、multi-agent 是 agent 自決下一步並可呼叫其他 agent。屬於 &lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/agent/" data-link-title="LLM Agent" data-link-desc="把控制流交給 LLM 的應用模式：自主決策、跨多步呼叫工具、人類角色從主導變監督">agent&lt;/a> 概念的進一步擴展。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>跟 multi-call 對照：&lt;/p>
&lt;table>
 &lt;thead>
 &lt;tr>
 &lt;th>維度&lt;/th>
 &lt;th>Multi-call workflow&lt;/th>
 &lt;th>Multi-agent system&lt;/th>
 &lt;/tr>
 &lt;/thead>
 &lt;tbody>
 &lt;tr>
 &lt;td>控制流&lt;/td>
 &lt;td>主程式編排&lt;/td>
 &lt;td>Agent 自決&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>角色&lt;/td>
 &lt;td>Step 是函數、無「身份」&lt;/td>
 &lt;td>每個 agent 有 role / 工具集&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>Context&lt;/td>
 &lt;td>主程式傳 context&lt;/td>
 &lt;td>Agent 自帶 memory&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>重用&lt;/td>
 &lt;td>Step 是函數、容易 import&lt;/td>
 &lt;td>Agent 跨系統重用透過協議&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>失敗歸屬&lt;/td>
 &lt;td>Step 失敗、主程式接&lt;/td>
 &lt;td>Agent 失敗可能 cascading&lt;/td>
 &lt;/tr>
 &lt;/tbody>
&lt;/table>
&lt;p>三種主流拓樸：&lt;/p>
&lt;table>
 &lt;thead>
 &lt;tr>
 &lt;th>拓樸&lt;/th>
 &lt;th>結構&lt;/th>
 &lt;th>適用&lt;/th>
 &lt;/tr>
 &lt;/thead>
 &lt;tbody>
 &lt;tr>
 &lt;td>Flat&lt;/td>
 &lt;td>All-to-all、無 orchestrator&lt;/td>
 &lt;td>2-4 個 agent、動態協商&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>Hierarchical&lt;/td>
 &lt;td>Orchestrator + specialists&lt;/td>
 &lt;td>多專業 agent、單一對外介面&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>Agent-as-tool&lt;/td>
 &lt;td>Agent 互通像 tool call（如 MCP）&lt;/td>
 &lt;td>跨組織重用、標準協議&lt;/td>
 &lt;/tr>
 &lt;/tbody>
&lt;/table>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>讀 agent framework / paper 看到「multi-agent」「orchestrator」「agent-as-tool」就是這層設計。實作判讀：&lt;/p>
&lt;ol>
&lt;li>&lt;strong>「先 multi-call、不夠再 multi-agent」&lt;/strong>：multi-agent 是「特定問題的解法」、不是「更高級的設計」。判讀訊號：role 顯著差異 / 跨產品重用 / 真正平行 / 動態協作 / 團隊熟悉度——四條件全滿足才走 multi-agent。&lt;/li>
&lt;li>&lt;strong>Specialization gain vs orchestration overhead&lt;/strong>：拆細帶來單一責任、獨立優化、重用、平行；代價是 context 重複傳遞、latency 累積、debug 困難、責任歸屬模糊。&lt;/li>
&lt;li>&lt;strong>特有失敗模式&lt;/strong>：循環依賴、責任歸屬模糊、context 重複傳遞、orchestrator 單點瓶頸、agent 互相 hallucinate。每類有對應 guardrail（call stack 監測、trace 全紀錄、shared context、deterministic dispatch rule、schema validation）。&lt;/li>
&lt;li>&lt;strong>跟 &lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/mcp/" data-link-title="MCP（Model Context Protocol）" data-link-desc="LLM application ↔ 外部 tool server 之間的標準化協議、複用 OpenAI 相容 API 的成功模式">MCP&lt;/a> 的關係&lt;/strong>：MCP 的 tool primitive 視角下、agent-as-tool 可包成 MCP server 暴露、跨組織重用走這條路。&lt;/li>
&lt;/ol>
&lt;p>完整 multi-agent 拓樸設計見 &lt;a href="https://tarrragon.github.io/blog/llm/04-applications/multi-agent-topology/" data-link-title="4.8 Multi-Agent 拓樸：flat / hierarchical / agent-as-tool" data-link-desc="從 multi-call workflow 走到 multi-agent system 的判讀、flat vs hierarchical 拓樸、agent-as-tool 的 MCP 視角、specialization 跟 orchestration overhead 的取捨">4.8 Multi-Agent 拓樸&lt;/a>。&lt;/p></description><content:encoded><![CDATA[<p>Multi-agent system 的核心概念是「<strong>多個 LLM <a href="/blog/llm/knowledge-cards/agent/" data-link-title="LLM Agent" data-link-desc="把控制流交給 LLM 的應用模式：自主決策、跨多步呼叫工具、人類角色從主導變監督">agent</a> 協作完成任務</strong>」。跟 multi-call workflow 的差異<strong>不在 agent 數量多寡、在控制流跟責任邊界</strong>——multi-call 是主程式編排每 step、multi-agent 是 agent 自決下一步並可呼叫其他 agent。屬於 <a href="/blog/llm/knowledge-cards/agent/" data-link-title="LLM Agent" data-link-desc="把控制流交給 LLM 的應用模式：自主決策、跨多步呼叫工具、人類角色從主導變監督">agent</a> 概念的進一步擴展。</p>
<h2 id="概念位置">概念位置</h2>
<p>跟 multi-call 對照：</p>
<table>
  <thead>
      <tr>
          <th>維度</th>
          <th>Multi-call workflow</th>
          <th>Multi-agent system</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>控制流</td>
          <td>主程式編排</td>
          <td>Agent 自決</td>
      </tr>
      <tr>
          <td>角色</td>
          <td>Step 是函數、無「身份」</td>
          <td>每個 agent 有 role / 工具集</td>
      </tr>
      <tr>
          <td>Context</td>
          <td>主程式傳 context</td>
          <td>Agent 自帶 memory</td>
      </tr>
      <tr>
          <td>重用</td>
          <td>Step 是函數、容易 import</td>
          <td>Agent 跨系統重用透過協議</td>
      </tr>
      <tr>
          <td>失敗歸屬</td>
          <td>Step 失敗、主程式接</td>
          <td>Agent 失敗可能 cascading</td>
      </tr>
  </tbody>
</table>
<p>三種主流拓樸：</p>
<table>
  <thead>
      <tr>
          <th>拓樸</th>
          <th>結構</th>
          <th>適用</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>Flat</td>
          <td>All-to-all、無 orchestrator</td>
          <td>2-4 個 agent、動態協商</td>
      </tr>
      <tr>
          <td>Hierarchical</td>
          <td>Orchestrator + specialists</td>
          <td>多專業 agent、單一對外介面</td>
      </tr>
      <tr>
          <td>Agent-as-tool</td>
          <td>Agent 互通像 tool call（如 MCP）</td>
          <td>跨組織重用、標準協議</td>
      </tr>
  </tbody>
</table>
<h2 id="設計責任">設計責任</h2>
<p>讀 agent framework / paper 看到「multi-agent」「orchestrator」「agent-as-tool」就是這層設計。實作判讀：</p>
<ol>
<li><strong>「先 multi-call、不夠再 multi-agent」</strong>：multi-agent 是「特定問題的解法」、不是「更高級的設計」。判讀訊號：role 顯著差異 / 跨產品重用 / 真正平行 / 動態協作 / 團隊熟悉度——四條件全滿足才走 multi-agent。</li>
<li><strong>Specialization gain vs orchestration overhead</strong>：拆細帶來單一責任、獨立優化、重用、平行；代價是 context 重複傳遞、latency 累積、debug 困難、責任歸屬模糊。</li>
<li><strong>特有失敗模式</strong>：循環依賴、責任歸屬模糊、context 重複傳遞、orchestrator 單點瓶頸、agent 互相 hallucinate。每類有對應 guardrail（call stack 監測、trace 全紀錄、shared context、deterministic dispatch rule、schema validation）。</li>
<li><strong>跟 <a href="/blog/llm/knowledge-cards/mcp/" data-link-title="MCP（Model Context Protocol）" data-link-desc="LLM application ↔ 外部 tool server 之間的標準化協議、複用 OpenAI 相容 API 的成功模式">MCP</a> 的關係</strong>：MCP 的 tool primitive 視角下、agent-as-tool 可包成 MCP server 暴露、跨組織重用走這條路。</li>
</ol>
<p>完整 multi-agent 拓樸設計見 <a href="/blog/llm/04-applications/multi-agent-topology/" data-link-title="4.8 Multi-Agent 拓樸：flat / hierarchical / agent-as-tool" data-link-desc="從 multi-call workflow 走到 multi-agent system 的判讀、flat vs hierarchical 拓樸、agent-as-tool 的 MCP 視角、specialization 跟 orchestration overhead 的取捨">4.8 Multi-Agent 拓樸</a>。</p>
]]></content:encoded></item><item><title>Multi-Step Retrieval</title><link>https://tarrragon.github.io/blog/llm/knowledge-cards/multi-step-retrieval/</link><pubDate>Thu, 14 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/llm/knowledge-cards/multi-step-retrieval/</guid><description>&lt;p>Multi-step retrieval 的核心概念是「&lt;strong>讓 &lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/rag/" data-link-title="RAG" data-link-desc="Retrieval-Augmented Generation：動態外掛知識給 LLM、繞開模型參數記憶的靜態限制">RAG&lt;/a> retrieval 變成多輪控制流，而不是一次性取 top-k&lt;/strong>」。模型先讀第一輪檢索結果，判斷資訊是否足夠，再決定下一個 sub-query。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>它是 &lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/rag/" data-link-title="RAG" data-link-desc="Retrieval-Augmented Generation：動態外掛知識給 LLM、繞開模型參數記憶的靜態限制">RAG&lt;/a> 與 &lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/agent-loop/" data-link-title="Agent Loop" data-link-desc="LLM agent 自我循環的工作流：LLM 規劃下一步、執行 tool、看結果、再規劃下一步、直到任務完成或停止條件觸發">agent loop&lt;/a> 的交界：控制流比 vanilla RAG 複雜，但目標仍是補齊回答所需 context，而不是任意行動。&lt;/p>
&lt;h2 id="可觀察訊號與例子">可觀察訊號與例子&lt;/h2>
&lt;p>多 hop 問題常需要 multi-step retrieval：先查 A 的屬性，再用該屬性查 B，最後比較。單次 retrieve 可能只抓到其中一邊，導致回答缺關鍵證據。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>Multi-step retrieval 只有在問題確實需要多 hop、latency budget 允許、且有停止條件時才划算。沒有 stop condition 時容易無限 retrieve；沒有資訊足夠性判斷時容易提高 &lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/retrieval-cost/" data-link-title="Retrieval Cost" data-link-desc="RAG 檢索帶來的 latency、token、embedding、reranker、LLM call 與維護成本，用來判斷增強是否划算">retrieval cost&lt;/a> 卻沒提升。&lt;/p></description><content:encoded><![CDATA[<p>Multi-step retrieval 的核心概念是「<strong>讓 <a href="/blog/llm/knowledge-cards/rag/" data-link-title="RAG" data-link-desc="Retrieval-Augmented Generation：動態外掛知識給 LLM、繞開模型參數記憶的靜態限制">RAG</a> retrieval 變成多輪控制流，而不是一次性取 top-k</strong>」。模型先讀第一輪檢索結果，判斷資訊是否足夠，再決定下一個 sub-query。</p>
<h2 id="概念位置">概念位置</h2>
<p>它是 <a href="/blog/llm/knowledge-cards/rag/" data-link-title="RAG" data-link-desc="Retrieval-Augmented Generation：動態外掛知識給 LLM、繞開模型參數記憶的靜態限制">RAG</a> 與 <a href="/blog/llm/knowledge-cards/agent-loop/" data-link-title="Agent Loop" data-link-desc="LLM agent 自我循環的工作流：LLM 規劃下一步、執行 tool、看結果、再規劃下一步、直到任務完成或停止條件觸發">agent loop</a> 的交界：控制流比 vanilla RAG 複雜，但目標仍是補齊回答所需 context，而不是任意行動。</p>
<h2 id="可觀察訊號與例子">可觀察訊號與例子</h2>
<p>多 hop 問題常需要 multi-step retrieval：先查 A 的屬性，再用該屬性查 B，最後比較。單次 retrieve 可能只抓到其中一邊，導致回答缺關鍵證據。</p>
<h2 id="設計責任">設計責任</h2>
<p>Multi-step retrieval 只有在問題確實需要多 hop、latency budget 允許、且有停止條件時才划算。沒有 stop condition 時容易無限 retrieve；沒有資訊足夠性判斷時容易提高 <a href="/blog/llm/knowledge-cards/retrieval-cost/" data-link-title="Retrieval Cost" data-link-desc="RAG 檢索帶來的 latency、token、embedding、reranker、LLM call 與維護成本，用來判斷增強是否划算">retrieval cost</a> 卻沒提升。</p>
]]></content:encoded></item><item><title>oMLX</title><link>https://tarrragon.github.io/blog/llm/knowledge-cards/omlx/</link><pubDate>Thu, 14 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/llm/knowledge-cards/omlx/</guid><description>&lt;p>oMLX 的核心概念是「&lt;strong>以 MLX 為基礎、針對 Apple Silicon 長 context 場景優化的推論伺服器路線&lt;/strong>」。它不是 &lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/mlx/" data-link-title="MLX" data-link-desc="Apple 釋出的 Apple Silicon 數值運算 framework：類似 PyTorch / JAX 的 Mac 對應物">MLX&lt;/a> 這個運算框架本身，也不是 &lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/mtp/" data-link-title="Multi-Token Prediction (MTP)" data-link-desc="Google 為 Gemma 系列釋出的 speculative decoding 工程化實作">MTP&lt;/a> 這類解碼技巧，而是把 MLX serving、長 context 與 KV cache 管理組合成服務層能力。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>oMLX 位在 &lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/three-layer-architecture/" data-link-title="Three-Layer Architecture" data-link-desc="把本地 LLM 工具拆成介面層、推論伺服器層、模型權重層的基礎心智模型">three-layer architecture&lt;/a> 的伺服器層。它的差異化重點通常是 Apple Silicon 最佳化、長 context prefill 成本、SSD-backed KV cache 或相關 cache 策略；它對上仍可提供 API，對下仍載入模型權重。&lt;/p>
&lt;h2 id="可觀察訊號與例子">可觀察訊號與例子&lt;/h2>
&lt;p>看到文章把 oMLX 跟 Ollama、LM Studio、llama.cpp server 放在同一組比較時，討論的是 serving 路線。看到它跟 MLX / MTP 並列時，判讀重點是「框架、解碼技巧、伺服器」三者層級不同。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>評估 oMLX 時，重點是工作流是否真的受長 context 與 &lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/ttft/" data-link-title="TTFT" data-link-desc="Time To First Token：送出 prompt 到第一個 token 出現的等待時間">TTFT&lt;/a> 影響；短 prompt 對話通常未必需要特化 serving。下一步路由是 &lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/mlx/" data-link-title="MLX" data-link-desc="Apple 釋出的 Apple Silicon 數值運算 framework：類似 PyTorch / JAX 的 Mac 對應物">MLX&lt;/a>、&lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/kv-cache/" data-link-title="KV Cache" data-link-desc="已處理 token 的 attention 中間結果暫存：避免重算、加速後續生成">KV Cache&lt;/a> 與 &lt;a href="https://tarrragon.github.io/blog/llm/00-foundations/mlx-mtp-omlx/" data-link-title="0.4 MLX / MTP / oMLX 的區別" data-link-desc="三個常被混為一談的術語：framework、加速技巧、特化 server，疊加而非互斥">0.4 MLX / MTP / oMLX&lt;/a>。&lt;/p></description><content:encoded><![CDATA[<p>oMLX 的核心概念是「<strong>以 MLX 為基礎、針對 Apple Silicon 長 context 場景優化的推論伺服器路線</strong>」。它不是 <a href="/blog/llm/knowledge-cards/mlx/" data-link-title="MLX" data-link-desc="Apple 釋出的 Apple Silicon 數值運算 framework：類似 PyTorch / JAX 的 Mac 對應物">MLX</a> 這個運算框架本身，也不是 <a href="/blog/llm/knowledge-cards/mtp/" data-link-title="Multi-Token Prediction (MTP)" data-link-desc="Google 為 Gemma 系列釋出的 speculative decoding 工程化實作">MTP</a> 這類解碼技巧，而是把 MLX serving、長 context 與 KV cache 管理組合成服務層能力。</p>
<h2 id="概念位置">概念位置</h2>
<p>oMLX 位在 <a href="/blog/llm/knowledge-cards/three-layer-architecture/" data-link-title="Three-Layer Architecture" data-link-desc="把本地 LLM 工具拆成介面層、推論伺服器層、模型權重層的基礎心智模型">three-layer architecture</a> 的伺服器層。它的差異化重點通常是 Apple Silicon 最佳化、長 context prefill 成本、SSD-backed KV cache 或相關 cache 策略；它對上仍可提供 API，對下仍載入模型權重。</p>
<h2 id="可觀察訊號與例子">可觀察訊號與例子</h2>
<p>看到文章把 oMLX 跟 Ollama、LM Studio、llama.cpp server 放在同一組比較時，討論的是 serving 路線。看到它跟 MLX / MTP 並列時，判讀重點是「框架、解碼技巧、伺服器」三者層級不同。</p>
<h2 id="設計責任">設計責任</h2>
<p>評估 oMLX 時，重點是工作流是否真的受長 context 與 <a href="/blog/llm/knowledge-cards/ttft/" data-link-title="TTFT" data-link-desc="Time To First Token：送出 prompt 到第一個 token 出現的等待時間">TTFT</a> 影響；短 prompt 對話通常未必需要特化 serving。下一步路由是 <a href="/blog/llm/knowledge-cards/mlx/" data-link-title="MLX" data-link-desc="Apple 釋出的 Apple Silicon 數值運算 framework：類似 PyTorch / JAX 的 Mac 對應物">MLX</a>、<a href="/blog/llm/knowledge-cards/kv-cache/" data-link-title="KV Cache" data-link-desc="已處理 token 的 attention 中間結果暫存：避免重算、加速後續生成">KV Cache</a> 與 <a href="/blog/llm/00-foundations/mlx-mtp-omlx/" data-link-title="0.4 MLX / MTP / oMLX 的區別" data-link-desc="三個常被混為一談的術語：framework、加速技巧、特化 server，疊加而非互斥">0.4 MLX / MTP / oMLX</a>。</p>
]]></content:encoded></item><item><title>Positional Encoding</title><link>https://tarrragon.github.io/blog/llm/knowledge-cards/positional-encoding/</link><pubDate>Thu, 14 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/llm/knowledge-cards/positional-encoding/</guid><description>&lt;p>Positional encoding（位置編碼）的核心概念是「&lt;strong>把序列中的位置資訊提供給 Transformer&lt;/strong>」。純 &lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/attention/" data-link-title="Attention" data-link-desc="Transformer 內部讓每個 token 對其他 token 加權平均的核心機制、形成 KV cache 跟 context window 的計算基礎">attention&lt;/a> 對 token 集合本身近似不帶順序感，位置編碼讓模型能分辨 &lt;code>cat bites dog&lt;/code> 與 &lt;code>dog bites cat&lt;/code>。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>位置資訊通常在 embedding 進入 Transformer block 前或 attention 計算中注入。常見路線包含 sinusoidal positional encoding、learned positional embedding、&lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/rope/" data-link-title="RoPE（Rotary Position Embedding）" data-link-desc="用旋轉矩陣把位置資訊直接旋轉進 Q/K 向量、現代 LLM 主流的位置編碼方式">RoPE&lt;/a> 與 ALiBi；現代 decoder-only LLM 多使用 RoPE 或其長 context scaling 變體。&lt;/p>
&lt;h2 id="可觀察訊號與例子">可觀察訊號與例子&lt;/h2>
&lt;p>讀 model architecture 看到 &lt;code>max_position_embeddings&lt;/code>、RoPE base、RoPE scaling、ALiBi、YaRN、NTK-aware scaling，就是位置編碼相關設定。長 context 擴展常卡在位置編碼外推能力，而不是只把 context window 數字調大。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>評估長 context 模型時，要分清楚「宣稱 context 長度」與「位置編碼在該長度仍可靠」。超過訓練長度太多時，即使能載入，模型對遠距關係也可能退化。完整章節見 &lt;a href="https://tarrragon.github.io/blog/llm/03-theoretical-foundations/transformer-architecture/" data-link-title="3.3 Transformer 架構細節" data-link-desc="Decoder-only 結構、Transformer block、positional encoding、layer norm、residual stream">Transformer architecture&lt;/a>。&lt;/p></description><content:encoded><![CDATA[<p>Positional encoding（位置編碼）的核心概念是「<strong>把序列中的位置資訊提供給 Transformer</strong>」。純 <a href="/blog/llm/knowledge-cards/attention/" data-link-title="Attention" data-link-desc="Transformer 內部讓每個 token 對其他 token 加權平均的核心機制、形成 KV cache 跟 context window 的計算基礎">attention</a> 對 token 集合本身近似不帶順序感，位置編碼讓模型能分辨 <code>cat bites dog</code> 與 <code>dog bites cat</code>。</p>
<h2 id="概念位置">概念位置</h2>
<p>位置資訊通常在 embedding 進入 Transformer block 前或 attention 計算中注入。常見路線包含 sinusoidal positional encoding、learned positional embedding、<a href="/blog/llm/knowledge-cards/rope/" data-link-title="RoPE（Rotary Position Embedding）" data-link-desc="用旋轉矩陣把位置資訊直接旋轉進 Q/K 向量、現代 LLM 主流的位置編碼方式">RoPE</a> 與 ALiBi；現代 decoder-only LLM 多使用 RoPE 或其長 context scaling 變體。</p>
<h2 id="可觀察訊號與例子">可觀察訊號與例子</h2>
<p>讀 model architecture 看到 <code>max_position_embeddings</code>、RoPE base、RoPE scaling、ALiBi、YaRN、NTK-aware scaling，就是位置編碼相關設定。長 context 擴展常卡在位置編碼外推能力，而不是只把 context window 數字調大。</p>
<h2 id="設計責任">設計責任</h2>
<p>評估長 context 模型時，要分清楚「宣稱 context 長度」與「位置編碼在該長度仍可靠」。超過訓練長度太多時，即使能載入，模型對遠距關係也可能退化。完整章節見 <a href="/blog/llm/03-theoretical-foundations/transformer-architecture/" data-link-title="3.3 Transformer 架構細節" data-link-desc="Decoder-only 結構、Transformer block、positional encoding、layer norm、residual stream">Transformer architecture</a>。</p>
]]></content:encoded></item><item><title>Query Decomposition</title><link>https://tarrragon.github.io/blog/llm/knowledge-cards/query-decomposition/</link><pubDate>Thu, 14 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/llm/knowledge-cards/query-decomposition/</guid><description>&lt;p>Query decomposition 的核心概念是「&lt;strong>把一個複合問題拆成多個可獨立 retrieve 的子問題&lt;/strong>」。它處理的是單一 query 同時要求比較、列舉、跨 entity 查證或多維度分析時，單次 retrieval 容易只命中其中一部分的問題。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>Query decomposition 位在 &lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/rag/" data-link-title="RAG" data-link-desc="Retrieval-Augmented Generation：動態外掛知識給 LLM、繞開模型參數記憶的靜態限制">RAG&lt;/a> 的 query 端，跟 &lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/multi-step-retrieval/" data-link-title="Multi-Step Retrieval" data-link-desc="RAG 中多輪 retrieve → 判斷 → 再 retrieve 的控制流，用來處理 multi-hop 問題">multi-step retrieval&lt;/a> 相鄰但不相同。Decomposition 是先拆好 N 個子 query 平行 retrieve；multi-step retrieval 是 retrieve 後讀結果，再決定下一步要查什麼。&lt;/p>
&lt;h2 id="可觀察訊號與例子">可觀察訊號與例子&lt;/h2>
&lt;p>「比較 A 與 B 在安全性和成本上的差異」可以拆成「A 的安全性」「B 的安全性」「A 的成本」「B 的成本」。每個子 query 都能獨立命中文件，最後再合成比較表。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>Query decomposition 適合子問題彼此獨立的複合問題。若後一個子 query 需要前一輪結果才能產生，改用 multi-step retrieval；若拆解後子 query 過多，要回到 &lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/retrieval-cost/" data-link-title="Retrieval Cost" data-link-desc="RAG 檢索帶來的 latency、token、embedding、reranker、LLM call 與維護成本，用來判斷增強是否划算">retrieval cost&lt;/a> 與 latency budget 評估。&lt;/p></description><content:encoded><![CDATA[<p>Query decomposition 的核心概念是「<strong>把一個複合問題拆成多個可獨立 retrieve 的子問題</strong>」。它處理的是單一 query 同時要求比較、列舉、跨 entity 查證或多維度分析時，單次 retrieval 容易只命中其中一部分的問題。</p>
<h2 id="概念位置">概念位置</h2>
<p>Query decomposition 位在 <a href="/blog/llm/knowledge-cards/rag/" data-link-title="RAG" data-link-desc="Retrieval-Augmented Generation：動態外掛知識給 LLM、繞開模型參數記憶的靜態限制">RAG</a> 的 query 端，跟 <a href="/blog/llm/knowledge-cards/multi-step-retrieval/" data-link-title="Multi-Step Retrieval" data-link-desc="RAG 中多輪 retrieve → 判斷 → 再 retrieve 的控制流，用來處理 multi-hop 問題">multi-step retrieval</a> 相鄰但不相同。Decomposition 是先拆好 N 個子 query 平行 retrieve；multi-step retrieval 是 retrieve 後讀結果，再決定下一步要查什麼。</p>
<h2 id="可觀察訊號與例子">可觀察訊號與例子</h2>
<p>「比較 A 與 B 在安全性和成本上的差異」可以拆成「A 的安全性」「B 的安全性」「A 的成本」「B 的成本」。每個子 query 都能獨立命中文件，最後再合成比較表。</p>
<h2 id="設計責任">設計責任</h2>
<p>Query decomposition 適合子問題彼此獨立的複合問題。若後一個子 query 需要前一輪結果才能產生，改用 multi-step retrieval；若拆解後子 query 過多，要回到 <a href="/blog/llm/knowledge-cards/retrieval-cost/" data-link-title="Retrieval Cost" data-link-desc="RAG 檢索帶來的 latency、token、embedding、reranker、LLM call 與維護成本，用來判斷增強是否划算">retrieval cost</a> 與 latency budget 評估。</p>
]]></content:encoded></item><item><title>Query Expansion</title><link>https://tarrragon.github.io/blog/llm/knowledge-cards/query-expansion/</link><pubDate>Thu, 14 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/llm/knowledge-cards/query-expansion/</guid><description>&lt;p>Query expansion 的核心概念是「&lt;strong>把一個使用者 query 擴成多個檢索變體，再把多路 retrieval 結果合併&lt;/strong>」。它處理的是 query 太短、有歧義、或只覆蓋單一表述角度時的 recall 問題，跟 &lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/query-rewriting/" data-link-title="Query Rewriting" data-link-desc="在 RAG 檢索前改寫使用者查詢，讓 query 更接近文件語言與索引分佈">query rewriting&lt;/a> 的單一路徑改寫不同。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>Query expansion 位在 &lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/rag/" data-link-title="RAG" data-link-desc="Retrieval-Augmented Generation：動態外掛知識給 LLM、繞開模型參數記憶的靜態限制">RAG&lt;/a> 的 query 端增強層。它會提高 &lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/retrieval-cost/" data-link-title="Retrieval Cost" data-link-desc="RAG 檢索帶來的 latency、token、embedding、reranker、LLM call 與維護成本，用來判斷增強是否划算">retrieval cost&lt;/a>，因為每個變體都要 retrieve；它也常跟 &lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/hybrid-search/" data-link-title="Hybrid Search" data-link-desc="把字面 retrieval（BM25）跟語意 retrieval（embedding）的結果用 RRF 等方法合併、補單一路線的盲點">hybrid search&lt;/a> 的 RRF 合併思路相鄰，用排名融合降低單一 query 變體失誤。&lt;/p>
&lt;h2 id="可觀察訊號與例子">可觀察訊號與例子&lt;/h2>
&lt;p>使用者問「python deploy」時，系統可能擴成「Python application deployment」「Docker deploy Python service」「CI/CD for Python backend」。這能增加 coverage，但也可能把不同意圖混在一起。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>Query expansion 適合短 query、歧義 query、或同一問題有多種常見說法的場景。設計時要限制變體數量，保留 original query，並用 &lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/retrieval-recall/" data-link-title="Retrieval Recall" data-link-desc="衡量 RAG 檢索是否把應該命中的文件或 chunk 放進 top-k 結果，是 component-level eval 的核心指標">retrieval recall&lt;/a> 驗證是否真的提高命中率；變體太發散時應改用澄清問題或 query rewriting。&lt;/p></description><content:encoded><![CDATA[<p>Query expansion 的核心概念是「<strong>把一個使用者 query 擴成多個檢索變體，再把多路 retrieval 結果合併</strong>」。它處理的是 query 太短、有歧義、或只覆蓋單一表述角度時的 recall 問題，跟 <a href="/blog/llm/knowledge-cards/query-rewriting/" data-link-title="Query Rewriting" data-link-desc="在 RAG 檢索前改寫使用者查詢，讓 query 更接近文件語言與索引分佈">query rewriting</a> 的單一路徑改寫不同。</p>
<h2 id="概念位置">概念位置</h2>
<p>Query expansion 位在 <a href="/blog/llm/knowledge-cards/rag/" data-link-title="RAG" data-link-desc="Retrieval-Augmented Generation：動態外掛知識給 LLM、繞開模型參數記憶的靜態限制">RAG</a> 的 query 端增強層。它會提高 <a href="/blog/llm/knowledge-cards/retrieval-cost/" data-link-title="Retrieval Cost" data-link-desc="RAG 檢索帶來的 latency、token、embedding、reranker、LLM call 與維護成本，用來判斷增強是否划算">retrieval cost</a>，因為每個變體都要 retrieve；它也常跟 <a href="/blog/llm/knowledge-cards/hybrid-search/" data-link-title="Hybrid Search" data-link-desc="把字面 retrieval（BM25）跟語意 retrieval（embedding）的結果用 RRF 等方法合併、補單一路線的盲點">hybrid search</a> 的 RRF 合併思路相鄰，用排名融合降低單一 query 變體失誤。</p>
<h2 id="可觀察訊號與例子">可觀察訊號與例子</h2>
<p>使用者問「python deploy」時，系統可能擴成「Python application deployment」「Docker deploy Python service」「CI/CD for Python backend」。這能增加 coverage，但也可能把不同意圖混在一起。</p>
<h2 id="設計責任">設計責任</h2>
<p>Query expansion 適合短 query、歧義 query、或同一問題有多種常見說法的場景。設計時要限制變體數量，保留 original query，並用 <a href="/blog/llm/knowledge-cards/retrieval-recall/" data-link-title="Retrieval Recall" data-link-desc="衡量 RAG 檢索是否把應該命中的文件或 chunk 放進 top-k 結果，是 component-level eval 的核心指標">retrieval recall</a> 驗證是否真的提高命中率；變體太發散時應改用澄清問題或 query rewriting。</p>
]]></content:encoded></item><item><title>Query Rewriting</title><link>https://tarrragon.github.io/blog/llm/knowledge-cards/query-rewriting/</link><pubDate>Thu, 14 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/llm/knowledge-cards/query-rewriting/</guid><description>&lt;p>Query rewriting 的核心概念是「&lt;strong>在 &lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/rag/" data-link-title="RAG" data-link-desc="Retrieval-Augmented Generation：動態外掛知識給 LLM、繞開模型參數記憶的靜態限制">RAG&lt;/a> retrieval 前把使用者 query 改寫成更適合搜尋的形狀&lt;/strong>」。使用者常用口語、模糊或情境化說法，文件則使用正式術語；改寫能縮小 &lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/query-document-gap/" data-link-title="Query-Document Gap" data-link-desc="使用者 query 與文件語言在詞彙、形態、抽象層級或領域分佈上的落差，是 RAG retrieval miss 的常見原因">query-document gap&lt;/a>。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>Query rewriting 位在 &lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/rag/" data-link-title="RAG" data-link-desc="Retrieval-Augmented Generation：動態外掛知識給 LLM、繞開模型參數記憶的靜態限制">RAG&lt;/a> pipeline 的 query 端，早於 embedding、hybrid search、reranker 與 &lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/context-packing/" data-link-title="Context Packing" data-link-desc="RAG retrieve 後把 chunks 去重、排序、壓縮、標來源，再塞進 prompt 的組裝決策">context packing&lt;/a>。它跟 HyDE 不同：rewriting 產生更好的查詢句，HyDE 產生假設文件再拿去 embed。&lt;/p>
&lt;h2 id="可觀察訊號與例子">可觀察訊號與例子&lt;/h2>
&lt;p>使用者問「API 為什麼很慢」，rewriting 可能改成「API latency bottleneck, tail latency, database query optimization」。這能讓 retrieval 更容易命中正式文件中的用詞，但會增加 &lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/retrieval-cost/" data-link-title="Retrieval Cost" data-link-desc="RAG 檢索帶來的 latency、token、embedding、reranker、LLM call 與維護成本，用來判斷增強是否划算">retrieval cost&lt;/a>。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>改寫要保留原始意圖，避免把「診斷原因」改成「優化方案」這類偏移。實務上要保存 original query，retrieve 後再用原始 query 檢查結果是否對題。&lt;/p></description><content:encoded><![CDATA[<p>Query rewriting 的核心概念是「<strong>在 <a href="/blog/llm/knowledge-cards/rag/" data-link-title="RAG" data-link-desc="Retrieval-Augmented Generation：動態外掛知識給 LLM、繞開模型參數記憶的靜態限制">RAG</a> retrieval 前把使用者 query 改寫成更適合搜尋的形狀</strong>」。使用者常用口語、模糊或情境化說法，文件則使用正式術語；改寫能縮小 <a href="/blog/llm/knowledge-cards/query-document-gap/" data-link-title="Query-Document Gap" data-link-desc="使用者 query 與文件語言在詞彙、形態、抽象層級或領域分佈上的落差，是 RAG retrieval miss 的常見原因">query-document gap</a>。</p>
<h2 id="概念位置">概念位置</h2>
<p>Query rewriting 位在 <a href="/blog/llm/knowledge-cards/rag/" data-link-title="RAG" data-link-desc="Retrieval-Augmented Generation：動態外掛知識給 LLM、繞開模型參數記憶的靜態限制">RAG</a> pipeline 的 query 端，早於 embedding、hybrid search、reranker 與 <a href="/blog/llm/knowledge-cards/context-packing/" data-link-title="Context Packing" data-link-desc="RAG retrieve 後把 chunks 去重、排序、壓縮、標來源，再塞進 prompt 的組裝決策">context packing</a>。它跟 HyDE 不同：rewriting 產生更好的查詢句，HyDE 產生假設文件再拿去 embed。</p>
<h2 id="可觀察訊號與例子">可觀察訊號與例子</h2>
<p>使用者問「API 為什麼很慢」，rewriting 可能改成「API latency bottleneck, tail latency, database query optimization」。這能讓 retrieval 更容易命中正式文件中的用詞，但會增加 <a href="/blog/llm/knowledge-cards/retrieval-cost/" data-link-title="Retrieval Cost" data-link-desc="RAG 檢索帶來的 latency、token、embedding、reranker、LLM call 與維護成本，用來判斷增強是否划算">retrieval cost</a>。</p>
<h2 id="設計責任">設計責任</h2>
<p>改寫要保留原始意圖，避免把「診斷原因」改成「優化方案」這類偏移。實務上要保存 original query，retrieve 後再用原始 query 檢查結果是否對題。</p>
]]></content:encoded></item><item><title>Query-Document Gap</title><link>https://tarrragon.github.io/blog/llm/knowledge-cards/query-document-gap/</link><pubDate>Thu, 14 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/llm/knowledge-cards/query-document-gap/</guid><description>&lt;p>Query-document gap 的核心概念是「&lt;strong>使用者 query 的語言形狀跟被檢索文件的語言形狀不一致&lt;/strong>」。它是 &lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/rag/" data-link-title="RAG" data-link-desc="Retrieval-Augmented Generation：動態外掛知識給 LLM、繞開模型參數記憶的靜態限制">RAG&lt;/a> retrieval miss 的常見原因：query 可能是口語問句，document 可能是正式陳述、專業術語、程式碼符號或另一種抽象層級。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>Query-document gap 位在 query 端與 embedding / search 端之間。它跟 &lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/hybrid-search/" data-link-title="Hybrid Search" data-link-desc="把字面 retrieval（BM25）跟語意 retrieval（embedding）的結果用 RRF 等方法合併、補單一路線的盲點">hybrid search&lt;/a> 的字面 vs 語意互補相關，也跟 &lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/query-rewriting/" data-link-title="Query Rewriting" data-link-desc="在 RAG 檢索前改寫使用者查詢，讓 query 更接近文件語言與索引分佈">query rewriting&lt;/a> 與 &lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/hyde/" data-link-title="HyDE（Hypothetical Document Embeddings）" data-link-desc="用 LLM 生成假設文件、對假文件做 embedding 去 retrieve、繞過 query-document gap 的 RAG 增強技術">HyDE&lt;/a> 直接相鄰：前者改寫 query，後者生成假設文件來靠近 document 分佈。&lt;/p>
&lt;h2 id="可觀察訊號與例子">可觀察訊號與例子&lt;/h2>
&lt;p>使用者問「API 為什麼很慢」，文件寫的是「tail latency、database query plan、connection pool saturation」。兩者意思相關，但 phrasing、抽象層級與術語不同，embedding 可能命中弱，BM25 可能完全漏掉。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>處理 query-document gap 時先判斷落差類型：同義詞、口語 vs 正式、問句 vs 陳述、跨語言、domain jargon 或識別碼。輕量修法是 query rewriting；形態落差明顯時可用 HyDE；精確 keyword 與語意都重要時用 hybrid search；仍然 top-k 不準時再加 reranker。&lt;/p></description><content:encoded><![CDATA[<p>Query-document gap 的核心概念是「<strong>使用者 query 的語言形狀跟被檢索文件的語言形狀不一致</strong>」。它是 <a href="/blog/llm/knowledge-cards/rag/" data-link-title="RAG" data-link-desc="Retrieval-Augmented Generation：動態外掛知識給 LLM、繞開模型參數記憶的靜態限制">RAG</a> retrieval miss 的常見原因：query 可能是口語問句，document 可能是正式陳述、專業術語、程式碼符號或另一種抽象層級。</p>
<h2 id="概念位置">概念位置</h2>
<p>Query-document gap 位在 query 端與 embedding / search 端之間。它跟 <a href="/blog/llm/knowledge-cards/hybrid-search/" data-link-title="Hybrid Search" data-link-desc="把字面 retrieval（BM25）跟語意 retrieval（embedding）的結果用 RRF 等方法合併、補單一路線的盲點">hybrid search</a> 的字面 vs 語意互補相關，也跟 <a href="/blog/llm/knowledge-cards/query-rewriting/" data-link-title="Query Rewriting" data-link-desc="在 RAG 檢索前改寫使用者查詢，讓 query 更接近文件語言與索引分佈">query rewriting</a> 與 <a href="/blog/llm/knowledge-cards/hyde/" data-link-title="HyDE（Hypothetical Document Embeddings）" data-link-desc="用 LLM 生成假設文件、對假文件做 embedding 去 retrieve、繞過 query-document gap 的 RAG 增強技術">HyDE</a> 直接相鄰：前者改寫 query，後者生成假設文件來靠近 document 分佈。</p>
<h2 id="可觀察訊號與例子">可觀察訊號與例子</h2>
<p>使用者問「API 為什麼很慢」，文件寫的是「tail latency、database query plan、connection pool saturation」。兩者意思相關，但 phrasing、抽象層級與術語不同，embedding 可能命中弱，BM25 可能完全漏掉。</p>
<h2 id="設計責任">設計責任</h2>
<p>處理 query-document gap 時先判斷落差類型：同義詞、口語 vs 正式、問句 vs 陳述、跨語言、domain jargon 或識別碼。輕量修法是 query rewriting；形態落差明顯時可用 HyDE；精確 keyword 與語意都重要時用 hybrid search；仍然 top-k 不準時再加 reranker。</p>
]]></content:encoded></item><item><title>Reflection / Self-critique</title><link>https://tarrragon.github.io/blog/llm/knowledge-cards/reflection/</link><pubDate>Thu, 14 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/llm/knowledge-cards/reflection/</guid><description>&lt;p>Reflection（self-critique）的核心概念是「&lt;strong>模型先生成一個草版、再對自己的草版 critique、再修改&lt;/strong>」。屬於推理引導類的 prompting 技術、也是 &lt;a href="https://tarrragon.github.io/blog/llm/04-applications/workflow-patterns/" data-link-title="4.7 Workflow 編排模式" data-link-desc="Pipeline / router / parallel / reflection：多 LLM call 組合的四種基本模式與退化條件">workflow pattern&lt;/a> 的基本模式之一。跟 &lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/chain-of-thought/" data-link-title="Chain-of-Thought（CoT）" data-link-desc="讓 LLM 先輸出推理步驟再給最終答案的 prompting / 訓練方式、reasoning model 的基礎機制">chain-of-thought&lt;/a> 不同：CoT 是「過程要 explicit」、reflection 是「先寫一版再批評再改」、有明確的兩階段。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>Reflection 三步：&lt;/p>





&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-text" data-lang="text">&lt;span class="line">&lt;span class="ln">1&lt;/span>&lt;span class="cl">[Generate] 模型生成 v1
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">2&lt;/span>&lt;span class="cl"> ↓
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">3&lt;/span>&lt;span class="cl">[Critique] 模型（或 critic LLM）對 v1 給回饋
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">4&lt;/span>&lt;span class="cl"> ↓
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">5&lt;/span>&lt;span class="cl">[Refine] 模型按回饋生成 v2
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">6&lt;/span>&lt;span class="cl"> ↓
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">7&lt;/span>&lt;span class="cl">(可選 loop)&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>跟其他模式對照：&lt;/p>
&lt;table>
 &lt;thead>
 &lt;tr>
 &lt;th>模式&lt;/th>
 &lt;th>結構&lt;/th>
 &lt;th>主要解的問題&lt;/th>
 &lt;/tr>
 &lt;/thead>
 &lt;tbody>
 &lt;tr>
 &lt;td>CoT&lt;/td>
 &lt;td>Think step by step、單次生成&lt;/td>
 &lt;td>隱式推理變 explicit&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>Reflection&lt;/td>
 &lt;td>Generate → critique → refine&lt;/td>
 &lt;td>一次生成不夠好、需要二次審視&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>Multi-step&lt;/td>
 &lt;td>Retrieve / decide / retrieve again&lt;/td>
 &lt;td>資訊不足、要動態補資料&lt;/td>
 &lt;/tr>
 &lt;/tbody>
&lt;/table>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>讀 prompt engineering / agent paper 看到「reflection」「self-critique」「self-refine」「critic」就是這個機制。實作判讀：&lt;/p>
&lt;ol>
&lt;li>&lt;strong>適用模型有能力辨識「自己寫的不夠好」&lt;/strong>、critique 跟 generator 不會共用同樣 blind spot。&lt;/li>
&lt;li>&lt;strong>失敗在 systematic error&lt;/strong>：critique 跟 generator 是同個模型、訓練分佈中的盲點不會因為「再想一次」消失。判讀訊號：critique 每次給很像的建議、或修完還是同一類錯——換 critic 用不同 base model、或加外部驗證（test、lint、schema）取代 LLM critique。&lt;/li>
&lt;li>&lt;strong>失敗在低能力模型&lt;/strong>：critic 能力不足、產不出有用建議、徒增 cost / latency。&lt;/li>
&lt;li>&lt;strong>失敗在無限循環&lt;/strong>：沒有客觀停止訊號、reflection 一直跑、cost 爆掉。緩解：step cap + 外部 metric（test pass、schema valid）。&lt;/li>
&lt;li>&lt;strong>失敗在過度修正&lt;/strong>：每次 reflection 都改一點、累積結果變糟（過度 fitting critic 意見）。緩解：保留 baseline、reflection 結果要跟 baseline 比、不一定採用。&lt;/li>
&lt;/ol>
&lt;p>&lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/agent-loop/" data-link-title="Agent Loop" data-link-desc="LLM agent 自我循環的工作流：LLM 規劃下一步、執行 tool、看結果、再規劃下一步、直到任務完成或停止條件觸發">Agent loop&lt;/a> 是 reflection 的延伸特例、進階失敗模式見 &lt;a href="https://tarrragon.github.io/blog/llm/04-applications/agent-architecture/" data-link-title="4.4 Agent 架構原理" data-link-desc="Agent loop 結構、失敗模式、什麼任務適合 vs 不適合、跟人類審查的協作模型">4.4 Agent 架構&lt;/a>。完整 workflow pattern 比較見 &lt;a href="https://tarrragon.github.io/blog/llm/04-applications/workflow-patterns/" data-link-title="4.7 Workflow 編排模式" data-link-desc="Pipeline / router / parallel / reflection：多 LLM call 組合的四種基本模式與退化條件">4.7 Workflow patterns&lt;/a>。&lt;/p></description><content:encoded><![CDATA[<p>Reflection（self-critique）的核心概念是「<strong>模型先生成一個草版、再對自己的草版 critique、再修改</strong>」。屬於推理引導類的 prompting 技術、也是 <a href="/blog/llm/04-applications/workflow-patterns/" data-link-title="4.7 Workflow 編排模式" data-link-desc="Pipeline / router / parallel / reflection：多 LLM call 組合的四種基本模式與退化條件">workflow pattern</a> 的基本模式之一。跟 <a href="/blog/llm/knowledge-cards/chain-of-thought/" data-link-title="Chain-of-Thought（CoT）" data-link-desc="讓 LLM 先輸出推理步驟再給最終答案的 prompting / 訓練方式、reasoning model 的基礎機制">chain-of-thought</a> 不同：CoT 是「過程要 explicit」、reflection 是「先寫一版再批評再改」、有明確的兩階段。</p>
<h2 id="概念位置">概念位置</h2>
<p>Reflection 三步：</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="ln">1</span><span class="cl">[Generate]    模型生成 v1
</span></span><span class="line"><span class="ln">2</span><span class="cl">   ↓
</span></span><span class="line"><span class="ln">3</span><span class="cl">[Critique]    模型（或 critic LLM）對 v1 給回饋
</span></span><span class="line"><span class="ln">4</span><span class="cl">   ↓
</span></span><span class="line"><span class="ln">5</span><span class="cl">[Refine]      模型按回饋生成 v2
</span></span><span class="line"><span class="ln">6</span><span class="cl">   ↓
</span></span><span class="line"><span class="ln">7</span><span class="cl">(可選 loop)</span></span></code></pre></div><p>跟其他模式對照：</p>
<table>
  <thead>
      <tr>
          <th>模式</th>
          <th>結構</th>
          <th>主要解的問題</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>CoT</td>
          <td>Think step by step、單次生成</td>
          <td>隱式推理變 explicit</td>
      </tr>
      <tr>
          <td>Reflection</td>
          <td>Generate → critique → refine</td>
          <td>一次生成不夠好、需要二次審視</td>
      </tr>
      <tr>
          <td>Multi-step</td>
          <td>Retrieve / decide / retrieve again</td>
          <td>資訊不足、要動態補資料</td>
      </tr>
  </tbody>
</table>
<h2 id="設計責任">設計責任</h2>
<p>讀 prompt engineering / agent paper 看到「reflection」「self-critique」「self-refine」「critic」就是這個機制。實作判讀：</p>
<ol>
<li><strong>適用模型有能力辨識「自己寫的不夠好」</strong>、critique 跟 generator 不會共用同樣 blind spot。</li>
<li><strong>失敗在 systematic error</strong>：critique 跟 generator 是同個模型、訓練分佈中的盲點不會因為「再想一次」消失。判讀訊號：critique 每次給很像的建議、或修完還是同一類錯——換 critic 用不同 base model、或加外部驗證（test、lint、schema）取代 LLM critique。</li>
<li><strong>失敗在低能力模型</strong>：critic 能力不足、產不出有用建議、徒增 cost / latency。</li>
<li><strong>失敗在無限循環</strong>：沒有客觀停止訊號、reflection 一直跑、cost 爆掉。緩解：step cap + 外部 metric（test pass、schema valid）。</li>
<li><strong>失敗在過度修正</strong>：每次 reflection 都改一點、累積結果變糟（過度 fitting critic 意見）。緩解：保留 baseline、reflection 結果要跟 baseline 比、不一定採用。</li>
</ol>
<p><a href="/blog/llm/knowledge-cards/agent-loop/" data-link-title="Agent Loop" data-link-desc="LLM agent 自我循環的工作流：LLM 規劃下一步、執行 tool、看結果、再規劃下一步、直到任務完成或停止條件觸發">Agent loop</a> 是 reflection 的延伸特例、進階失敗模式見 <a href="/blog/llm/04-applications/agent-architecture/" data-link-title="4.4 Agent 架構原理" data-link-desc="Agent loop 結構、失敗模式、什麼任務適合 vs 不適合、跟人類審查的協作模型">4.4 Agent 架構</a>。完整 workflow pattern 比較見 <a href="/blog/llm/04-applications/workflow-patterns/" data-link-title="4.7 Workflow 編排模式" data-link-desc="Pipeline / router / parallel / reflection：多 LLM call 組合的四種基本模式與退化條件">4.7 Workflow patterns</a>。</p>
]]></content:encoded></item><item><title>Residual Stream</title><link>https://tarrragon.github.io/blog/llm/knowledge-cards/residual-stream/</link><pubDate>Thu, 14 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/llm/knowledge-cards/residual-stream/</guid><description>&lt;p>Residual stream 的核心概念是「&lt;strong>&lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/transformer/" data-link-title="Transformer" data-link-desc="寫 code 用的 LLM 神經網路架構：基於 attention 機制、自回歸生成 token">Transformer&lt;/a> block 之間持續傳遞、被各層逐步修改的 hidden state 通道&lt;/strong>」。它是整個模型中資訊流動的主幹，涵蓋範圍超過單一殘差連接。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>&lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/residual-connection/" data-link-title="Residual Connection" data-link-desc="把 layer 的輸入直接加到輸出上的「跳接」、讓深層網路的梯度能穩定回流">Residual connection&lt;/a> 是局部結構：把 layer input 加回 output。Residual stream 是整體視角：token representation 在每層 attention、FFN、normalization 作用後沿著主通道前進。&lt;/p>
&lt;h2 id="可觀察訊號與例子">可觀察訊號與例子&lt;/h2>
&lt;p>讀 Transformer 架構或 mechanistic interpretability 文章看到「write to residual stream」「read from residual stream」「logit lens」時，討論的是各層如何在同一條 hidden state 通道上累積特徵。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>一般使用者不用調 residual stream，但理解它能幫助區分 layer、block、hidden state 與 residual connection。進一步閱讀可回到 &lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/transformer/" data-link-title="Transformer" data-link-desc="寫 code 用的 LLM 神經網路架構：基於 attention 機制、自回歸生成 token">Transformer&lt;/a> 與 &lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/residual-connection/" data-link-title="Residual Connection" data-link-desc="把 layer 的輸入直接加到輸出上的「跳接」、讓深層網路的梯度能穩定回流">Residual Connection&lt;/a>。&lt;/p></description><content:encoded><![CDATA[<p>Residual stream 的核心概念是「<strong><a href="/blog/llm/knowledge-cards/transformer/" data-link-title="Transformer" data-link-desc="寫 code 用的 LLM 神經網路架構：基於 attention 機制、自回歸生成 token">Transformer</a> block 之間持續傳遞、被各層逐步修改的 hidden state 通道</strong>」。它是整個模型中資訊流動的主幹，涵蓋範圍超過單一殘差連接。</p>
<h2 id="概念位置">概念位置</h2>
<p><a href="/blog/llm/knowledge-cards/residual-connection/" data-link-title="Residual Connection" data-link-desc="把 layer 的輸入直接加到輸出上的「跳接」、讓深層網路的梯度能穩定回流">Residual connection</a> 是局部結構：把 layer input 加回 output。Residual stream 是整體視角：token representation 在每層 attention、FFN、normalization 作用後沿著主通道前進。</p>
<h2 id="可觀察訊號與例子">可觀察訊號與例子</h2>
<p>讀 Transformer 架構或 mechanistic interpretability 文章看到「write to residual stream」「read from residual stream」「logit lens」時，討論的是各層如何在同一條 hidden state 通道上累積特徵。</p>
<h2 id="設計責任">設計責任</h2>
<p>一般使用者不用調 residual stream，但理解它能幫助區分 layer、block、hidden state 與 residual connection。進一步閱讀可回到 <a href="/blog/llm/knowledge-cards/transformer/" data-link-title="Transformer" data-link-desc="寫 code 用的 LLM 神經網路架構：基於 attention 機制、自回歸生成 token">Transformer</a> 與 <a href="/blog/llm/knowledge-cards/residual-connection/" data-link-title="Residual Connection" data-link-desc="把 layer 的輸入直接加到輸出上的「跳接」、讓深層網路的梯度能穩定回流">Residual Connection</a>。</p>
]]></content:encoded></item><item><title>Retrieval Cost</title><link>https://tarrragon.github.io/blog/llm/knowledge-cards/retrieval-cost/</link><pubDate>Thu, 14 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/llm/knowledge-cards/retrieval-cost/</guid><description>&lt;p>Retrieval cost 的核心概念是「&lt;strong>每一次 retrieve 與其周邊增強會消耗多少 latency、token、compute 與維護成本&lt;/strong>」。它讓 &lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/rag/" data-link-title="RAG" data-link-desc="Retrieval-Augmented Generation：動態外掛知識給 LLM、繞開模型參數記憶的靜態限制">RAG&lt;/a> 設計從「能不能找更多資料」轉成「多找這些資料是否值得」。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>Retrieval cost 橫跨 query 端、retrieval 端、context 組裝端與控制流端。它跟 &lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/ttft/" data-link-title="TTFT" data-link-desc="Time To First Token：送出 prompt 到第一個 token 出現的等待時間">TTFT&lt;/a> 有關，但不只是一個延遲數字：query rewriting 多一次 LLM call，query expansion 多次 retrieve，reranker 多一段 cross-encoder 計算，retrieved chunks 進 prompt 會增加 token cost。&lt;/p>
&lt;h2 id="可觀察訊號與例子">可觀察訊號與例子&lt;/h2>
&lt;p>常見訊號是「accuracy 有提升，但 p95 latency 變差」「每個 query 都 retrieve，聊天問題也燒 embedding / vector DB」「multi-step retrieval 連跑三輪，答案只比 single-step 好一點」。這時問題在於收益是否大於成本，而非技術能不能做。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>判斷 retrieval cost 要把 accuracy、latency、token budget、服務費用與維運複雜度一起看。低風險聊天可用 &lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/adaptive-retrieval/" data-link-title="Adaptive Retrieval" data-link-desc="RAG 控制流中先判斷是否需要檢索，只在外部知識有價值時才 retrieve">adaptive retrieval&lt;/a> 降低不必要檢索；高價值問答可接受 &lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/reranker/" data-link-title="Reranker" data-link-desc="對 retrieval top-K 結果用 cross-encoder 重新排序的 RAG 第二階段、品質提升顯著但 latency / cost 增加">reranker&lt;/a> 或 &lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/multi-step-retrieval/" data-link-title="Multi-Step Retrieval" data-link-desc="RAG 中多輪 retrieve → 判斷 → 再 retrieve 的控制流，用來處理 multi-hop 問題">multi-step retrieval&lt;/a> 的額外成本；即時補完則通常偏向 single-step、cache 或較小 top-k。&lt;/p></description><content:encoded><![CDATA[<p>Retrieval cost 的核心概念是「<strong>每一次 retrieve 與其周邊增強會消耗多少 latency、token、compute 與維護成本</strong>」。它讓 <a href="/blog/llm/knowledge-cards/rag/" data-link-title="RAG" data-link-desc="Retrieval-Augmented Generation：動態外掛知識給 LLM、繞開模型參數記憶的靜態限制">RAG</a> 設計從「能不能找更多資料」轉成「多找這些資料是否值得」。</p>
<h2 id="概念位置">概念位置</h2>
<p>Retrieval cost 橫跨 query 端、retrieval 端、context 組裝端與控制流端。它跟 <a href="/blog/llm/knowledge-cards/ttft/" data-link-title="TTFT" data-link-desc="Time To First Token：送出 prompt 到第一個 token 出現的等待時間">TTFT</a> 有關，但不只是一個延遲數字：query rewriting 多一次 LLM call，query expansion 多次 retrieve，reranker 多一段 cross-encoder 計算，retrieved chunks 進 prompt 會增加 token cost。</p>
<h2 id="可觀察訊號與例子">可觀察訊號與例子</h2>
<p>常見訊號是「accuracy 有提升，但 p95 latency 變差」「每個 query 都 retrieve，聊天問題也燒 embedding / vector DB」「multi-step retrieval 連跑三輪，答案只比 single-step 好一點」。這時問題在於收益是否大於成本，而非技術能不能做。</p>
<h2 id="設計責任">設計責任</h2>
<p>判斷 retrieval cost 要把 accuracy、latency、token budget、服務費用與維運複雜度一起看。低風險聊天可用 <a href="/blog/llm/knowledge-cards/adaptive-retrieval/" data-link-title="Adaptive Retrieval" data-link-desc="RAG 控制流中先判斷是否需要檢索，只在外部知識有價值時才 retrieve">adaptive retrieval</a> 降低不必要檢索；高價值問答可接受 <a href="/blog/llm/knowledge-cards/reranker/" data-link-title="Reranker" data-link-desc="對 retrieval top-K 結果用 cross-encoder 重新排序的 RAG 第二階段、品質提升顯著但 latency / cost 增加">reranker</a> 或 <a href="/blog/llm/knowledge-cards/multi-step-retrieval/" data-link-title="Multi-Step Retrieval" data-link-desc="RAG 中多輪 retrieve → 判斷 → 再 retrieve 的控制流，用來處理 multi-hop 問題">multi-step retrieval</a> 的額外成本；即時補完則通常偏向 single-step、cache 或較小 top-k。</p>
]]></content:encoded></item><item><title>Retrieval Recall</title><link>https://tarrragon.github.io/blog/llm/knowledge-cards/retrieval-recall/</link><pubDate>Thu, 14 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/llm/knowledge-cards/retrieval-recall/</guid><description>&lt;p>Retrieval recall 的核心概念是「&lt;strong>正確文件或 chunk 是否出現在 retrieval top-k 結果中&lt;/strong>」。它把 &lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/rag/" data-link-title="RAG" data-link-desc="Retrieval-Augmented Generation：動態外掛知識給 LLM、繞開模型參數記憶的靜態限制">RAG&lt;/a> 的 retrieval 階段從主觀感覺改成 component-level eval，讓 generation 失敗與 retrieval miss 能分開判讀。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>Retrieval recall 位在 retrieval component eval 層。它跟 &lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/reranker/" data-link-title="Reranker" data-link-desc="對 retrieval top-K 結果用 cross-encoder 重新排序的 RAG 第二階段、品質提升顯著但 latency / cost 增加">reranker&lt;/a> 相鄰，因為 reranker 常用來提升 top-k 的排序品質；也跟 &lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/query-document-gap/" data-link-title="Query-Document Gap" data-link-desc="使用者 query 與文件語言在詞彙、形態、抽象層級或領域分佈上的落差，是 RAG retrieval miss 的常見原因">query-document gap&lt;/a> 相鄰，因為 gap 太大會讓 expected doc 不進 top-k。&lt;/p>
&lt;h2 id="可觀察訊號與例子">可觀察訊號與例子&lt;/h2>
&lt;p>一組 eval query 事先標出 expected chunk。若 expected chunk 出現在 top-5，記為 hit@5；一百題中 82 題命中，hit_rate@5 是 82%。若 retrieval recall 高但答案錯，問題多半在 generation 或 context packing；若 retrieval recall 低，先修 chunking、embedding、hybrid search 或 query 端增強。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>設計 retrieval recall eval 時要保存 query、expected source、top-k 結果、score 與失敗分類。不要只看 end-to-end answer correctness；否則 retrieval miss 會被 LLM hallucination、judge 偏差或 prompt 問題掩蓋。&lt;/p></description><content:encoded><![CDATA[<p>Retrieval recall 的核心概念是「<strong>正確文件或 chunk 是否出現在 retrieval top-k 結果中</strong>」。它把 <a href="/blog/llm/knowledge-cards/rag/" data-link-title="RAG" data-link-desc="Retrieval-Augmented Generation：動態外掛知識給 LLM、繞開模型參數記憶的靜態限制">RAG</a> 的 retrieval 階段從主觀感覺改成 component-level eval，讓 generation 失敗與 retrieval miss 能分開判讀。</p>
<h2 id="概念位置">概念位置</h2>
<p>Retrieval recall 位在 retrieval component eval 層。它跟 <a href="/blog/llm/knowledge-cards/reranker/" data-link-title="Reranker" data-link-desc="對 retrieval top-K 結果用 cross-encoder 重新排序的 RAG 第二階段、品質提升顯著但 latency / cost 增加">reranker</a> 相鄰，因為 reranker 常用來提升 top-k 的排序品質；也跟 <a href="/blog/llm/knowledge-cards/query-document-gap/" data-link-title="Query-Document Gap" data-link-desc="使用者 query 與文件語言在詞彙、形態、抽象層級或領域分佈上的落差，是 RAG retrieval miss 的常見原因">query-document gap</a> 相鄰，因為 gap 太大會讓 expected doc 不進 top-k。</p>
<h2 id="可觀察訊號與例子">可觀察訊號與例子</h2>
<p>一組 eval query 事先標出 expected chunk。若 expected chunk 出現在 top-5，記為 hit@5；一百題中 82 題命中，hit_rate@5 是 82%。若 retrieval recall 高但答案錯，問題多半在 generation 或 context packing；若 retrieval recall 低，先修 chunking、embedding、hybrid search 或 query 端增強。</p>
<h2 id="設計責任">設計責任</h2>
<p>設計 retrieval recall eval 時要保存 query、expected source、top-k 結果、score 與失敗分類。不要只看 end-to-end answer correctness；否則 retrieval miss 會被 LLM hallucination、judge 偏差或 prompt 問題掩蓋。</p>
]]></content:encoded></item><item><title>Retrieval Source</title><link>https://tarrragon.github.io/blog/llm/knowledge-cards/retrieval-source/</link><pubDate>Thu, 14 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/llm/knowledge-cards/retrieval-source/</guid><description>&lt;p>Retrieval source 的核心概念是「&lt;strong>RAG 或 agent 在 retrieve 時實際查詢的資料來源&lt;/strong>」。它是 &lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/rag/" data-link-title="RAG" data-link-desc="Retrieval-Augmented Generation：動態外掛知識給 LLM、繞開模型參數記憶的靜態限制">RAG&lt;/a> pipeline 中可被檢索、可被引用、也可能被污染或過期的 corpus、index、database、file system、tool response 或第三方服務——比泛稱的 source 更具體。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>Retrieval source 位在 ingestion、index 與 runtime retrieval 的交界。它跟 &lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/chunking/" data-link-title="Chunking" data-link-desc="把長文件切成可檢索片段的設計決策：resolution vs context loss 的本質取捨">chunking&lt;/a> 不同：chunking 決定來源如何切片，retrieval source 決定來源本身是否可信、是否新鮮、是否有權限被查、是否能被引用。&lt;/p>
&lt;h2 id="可觀察訊號與例子">可觀察訊號與例子&lt;/h2>
&lt;p>看到「從 codebase retrieve」「從歷史客服案例庫取相似案例」「從 vector DB 查 policy」「把 filesystem search 結果塞進 prompt」就是 retrieval source 問題。不同 source 的責任不同：官方 policy 文件可引用，使用者上傳文件要標記租戶與權限，網頁內容要防 prompt injection，過期 index 要能重建。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>設計 retrieval source 時要同時回答四件事：資料來源是否可信、資料是否新鮮、查詢者是否有權限、LLM 回答是否能追溯。高風險來源要保留 source metadata、ingestion timestamp、tenant boundary 與引用標籤；否則 retrieval 命中正確內容，也可能把不該看的資料送進 prompt。&lt;/p></description><content:encoded><![CDATA[<p>Retrieval source 的核心概念是「<strong>RAG 或 agent 在 retrieve 時實際查詢的資料來源</strong>」。它是 <a href="/blog/llm/knowledge-cards/rag/" data-link-title="RAG" data-link-desc="Retrieval-Augmented Generation：動態外掛知識給 LLM、繞開模型參數記憶的靜態限制">RAG</a> pipeline 中可被檢索、可被引用、也可能被污染或過期的 corpus、index、database、file system、tool response 或第三方服務——比泛稱的 source 更具體。</p>
<h2 id="概念位置">概念位置</h2>
<p>Retrieval source 位在 ingestion、index 與 runtime retrieval 的交界。它跟 <a href="/blog/llm/knowledge-cards/chunking/" data-link-title="Chunking" data-link-desc="把長文件切成可檢索片段的設計決策：resolution vs context loss 的本質取捨">chunking</a> 不同：chunking 決定來源如何切片，retrieval source 決定來源本身是否可信、是否新鮮、是否有權限被查、是否能被引用。</p>
<h2 id="可觀察訊號與例子">可觀察訊號與例子</h2>
<p>看到「從 codebase retrieve」「從歷史客服案例庫取相似案例」「從 vector DB 查 policy」「把 filesystem search 結果塞進 prompt」就是 retrieval source 問題。不同 source 的責任不同：官方 policy 文件可引用，使用者上傳文件要標記租戶與權限，網頁內容要防 prompt injection，過期 index 要能重建。</p>
<h2 id="設計責任">設計責任</h2>
<p>設計 retrieval source 時要同時回答四件事：資料來源是否可信、資料是否新鮮、查詢者是否有權限、LLM 回答是否能追溯。高風險來源要保留 source metadata、ingestion timestamp、tenant boundary 與引用標籤；否則 retrieval 命中正確內容，也可能把不該看的資料送進 prompt。</p>
]]></content:encoded></item><item><title>Sampling Constraint</title><link>https://tarrragon.github.io/blog/llm/knowledge-cards/sampling-constraint/</link><pubDate>Thu, 14 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/llm/knowledge-cards/sampling-constraint/</guid><description>&lt;p>Sampling constraint（sampling 約束）的核心概念是「&lt;strong>在模型選下一個 token 時，限制哪些 token 可以被選到&lt;/strong>」。模型 forward pass 產生每個 token 的 &lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/logit/" data-link-title="Logit" data-link-desc="softmax 之前的原始實數分數、每個 vocab token 一個值、可正可負">logit&lt;/a>，sampling 約束在取樣前調整候選集合或機率，讓輸出符合格式、選項或安全邊界。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>Sampling 約束屬於推論階段，不修改模型權重，也不等於模型真的理解規則。常見控制手段有 temperature、top-p / top-k、logit bias、grammar mask、JSON mode 與 &lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/constrained-decoding/" data-link-title="Constrained Decoding" data-link-desc="推論時用 grammar 強制 LLM 輸出符合特定格式（JSON / regex / CFG）的 sampling 機制、把不合法 token 的機率歸零">constrained decoding&lt;/a>；其中 grammar mask 是 structured output 最關鍵的一類。&lt;/p>





&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-text" data-lang="text">&lt;span class="line">&lt;span class="ln">1&lt;/span>&lt;span class="cl">prompt → model forward pass → logits
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">2&lt;/span>&lt;span class="cl"> ↓
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">3&lt;/span>&lt;span class="cl">sampling constraint：調整候選 token / logit / 機率
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">4&lt;/span>&lt;span class="cl"> ↓
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">5&lt;/span>&lt;span class="cl">sample next token → append → 下一輪&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h2 id="可觀察訊號與例子">可觀察訊號與例子&lt;/h2>
&lt;p>看到「低 temperature 讓答案更穩」「top-p 過濾長尾 token」「logit bias 禁止某個 token」「grammar mask 只允許合法 JSON token」就是 sampling 約束。例子是 enum 分類：如果合法答案只有 &lt;code>billing&lt;/code>、&lt;code>technical&lt;/code>、&lt;code>other&lt;/code>，推論伺服器可以在輸出欄位值的位置只允許這幾組 token 的路徑。&lt;/p>
&lt;p>Sampling 約束的風險是把模型逼到錯誤但合法的輸出。當 grammar 太窄、enum 缺少 &lt;code>unknown&lt;/code>、schema 沒有容納例外狀態時，模型可能輸出看似可解析但語意不可信的值；這時要加 fallback、confidence 或人工覆核路由。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>Sampling 約束適合處理格式合法性與候選空間控制，不適合單獨承擔事實正確性。設計時先問三件事：合法 token 集合能否完整表示業務狀態、約束失敗時要 retry 還是回退、下游 validator 如何分辨「格式合法但語意可疑」。下一步路由是 &lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/structured-output/" data-link-title="Structured Output" data-link-desc="讓 LLM 輸出可被 parser 穩定消費的推論階段設計：JSON mode、schema-guided decoding、grammar 約束都屬於這一層">Structured Output&lt;/a> 與 &lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/top-p-sampling/" data-link-title="Top-K / Top-P / Min-P Sampling" data-link-desc="從機率分佈取樣前先過濾低機率 token 的三種策略、現代 LLM 推論主流">Top-K / Top-P / Min-P Sampling&lt;/a>。&lt;/p></description><content:encoded><![CDATA[<p>Sampling constraint（sampling 約束）的核心概念是「<strong>在模型選下一個 token 時，限制哪些 token 可以被選到</strong>」。模型 forward pass 產生每個 token 的 <a href="/blog/llm/knowledge-cards/logit/" data-link-title="Logit" data-link-desc="softmax 之前的原始實數分數、每個 vocab token 一個值、可正可負">logit</a>，sampling 約束在取樣前調整候選集合或機率，讓輸出符合格式、選項或安全邊界。</p>
<h2 id="概念位置">概念位置</h2>
<p>Sampling 約束屬於推論階段，不修改模型權重，也不等於模型真的理解規則。常見控制手段有 temperature、top-p / top-k、logit bias、grammar mask、JSON mode 與 <a href="/blog/llm/knowledge-cards/constrained-decoding/" data-link-title="Constrained Decoding" data-link-desc="推論時用 grammar 強制 LLM 輸出符合特定格式（JSON / regex / CFG）的 sampling 機制、把不合法 token 的機率歸零">constrained decoding</a>；其中 grammar mask 是 structured output 最關鍵的一類。</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="ln">1</span><span class="cl">prompt → model forward pass → logits
</span></span><span class="line"><span class="ln">2</span><span class="cl">  ↓
</span></span><span class="line"><span class="ln">3</span><span class="cl">sampling constraint：調整候選 token / logit / 機率
</span></span><span class="line"><span class="ln">4</span><span class="cl">  ↓
</span></span><span class="line"><span class="ln">5</span><span class="cl">sample next token → append → 下一輪</span></span></code></pre></div><h2 id="可觀察訊號與例子">可觀察訊號與例子</h2>
<p>看到「低 temperature 讓答案更穩」「top-p 過濾長尾 token」「logit bias 禁止某個 token」「grammar mask 只允許合法 JSON token」就是 sampling 約束。例子是 enum 分類：如果合法答案只有 <code>billing</code>、<code>technical</code>、<code>other</code>，推論伺服器可以在輸出欄位值的位置只允許這幾組 token 的路徑。</p>
<p>Sampling 約束的風險是把模型逼到錯誤但合法的輸出。當 grammar 太窄、enum 缺少 <code>unknown</code>、schema 沒有容納例外狀態時，模型可能輸出看似可解析但語意不可信的值；這時要加 fallback、confidence 或人工覆核路由。</p>
<h2 id="設計責任">設計責任</h2>
<p>Sampling 約束適合處理格式合法性與候選空間控制，不適合單獨承擔事實正確性。設計時先問三件事：合法 token 集合能否完整表示業務狀態、約束失敗時要 retry 還是回退、下游 validator 如何分辨「格式合法但語意可疑」。下一步路由是 <a href="/blog/llm/knowledge-cards/structured-output/" data-link-title="Structured Output" data-link-desc="讓 LLM 輸出可被 parser 穩定消費的推論階段設計：JSON mode、schema-guided decoding、grammar 約束都屬於這一層">Structured Output</a> 與 <a href="/blog/llm/knowledge-cards/top-p-sampling/" data-link-title="Top-K / Top-P / Min-P Sampling" data-link-desc="從機率分佈取樣前先過濾低機率 token 的三種策略、現代 LLM 推論主流">Top-K / Top-P / Min-P Sampling</a>。</p>
]]></content:encoded></item><item><title>Structured Output</title><link>https://tarrragon.github.io/blog/llm/knowledge-cards/structured-output/</link><pubDate>Thu, 14 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/llm/knowledge-cards/structured-output/</guid><description>&lt;p>Structured output 的核心概念是「&lt;strong>讓 LLM 輸出符合可機器解析的固定形狀&lt;/strong>」。它解的是應用層 parser 能不能穩定消費模型輸出的問題：輸出要能被 JSON parser、schema validator、dispatcher、workflow engine 確定性處理，而不是靠人類讀自然語言再猜意圖。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>Structured output 位在推論與應用交界，常見實作包含 JSON mode、JSON Schema、&lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/grammar/" data-link-title="Grammar" data-link-desc="描述合法字串形狀的形式規則，在 structured output 中用來限制 LLM 每一步可輸出的 token">grammar&lt;/a> 約束、&lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/constrained-decoding/" data-link-title="Constrained Decoding" data-link-desc="推論時用 grammar 強制 LLM 輸出符合特定格式（JSON / regex / CFG）的 sampling 機制、把不合法 token 的機率歸零">constrained decoding&lt;/a> 與 logit mask。它跟 &lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/function-calling/" data-link-title="Function Calling" data-link-desc="模型訓練階段建立的「呼叫工具」能力：知道何時該呼叫、傳什麼參數">function calling&lt;/a> 的差異在責任層：function calling 是模型訓練出的工具呼叫能力，structured output 是推論時讓輸出形狀穩定的約束。&lt;/p>





&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-text" data-lang="text">&lt;span class="line">&lt;span class="ln">1&lt;/span>&lt;span class="cl">模型能力：知道是否該呼叫工具、該填什麼參數
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">2&lt;/span>&lt;span class="cl">推論約束：輸出必須符合 JSON / schema / grammar
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">3&lt;/span>&lt;span class="cl">應用消費：parser 解析、validator 檢查、dispatcher 執行&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h2 id="可觀察訊號與例子">可觀察訊號與例子&lt;/h2>
&lt;p>看到「固定輸出 JSON」「把結果分類成 enum」「回傳符合 schema 的物件」「讓 parser 不再處理自由文字」就是 structured output 場景。例子是客服工單分類：模型輸出 &lt;code>{&amp;quot;category&amp;quot;:&amp;quot;billing&amp;quot;,&amp;quot;priority&amp;quot;:&amp;quot;high&amp;quot;}&lt;/code>，後端可以直接依欄位路由，而不是從一段自然語言裡抽關鍵字。&lt;/p>
&lt;p>Structured output 的成功訊號是合法率、schema 對位率與下游解析失敗率。JSON 合法率只代表文字可被 parser 讀，schema 對位率才代表欄位、型別、enum、required 都符合應用契約；兩者分開看，才能分辨是語法錯、schema 錯，還是模型語意判斷錯。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>Structured output 適合「下游要自動執行」的輸出：tool 參數、分類、抽取、workflow 狀態、查詢條件。它的邊界是語意品質：grammar 可以保證格式合法，但不能保證模型填的值正確。下一步路由是：需要理解 token mask 機制讀 &lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/constrained-decoding/" data-link-title="Constrained Decoding" data-link-desc="推論時用 grammar 強制 LLM 輸出符合特定格式（JSON / regex / CFG）的 sampling 機制、把不合法 token 的機率歸零">Constrained Decoding&lt;/a>；需要判斷它跟工具呼叫的分工讀 &lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/function-calling/" data-link-title="Function Calling" data-link-desc="模型訓練階段建立的「呼叫工具」能力：知道何時該呼叫、傳什麼參數">Function Calling&lt;/a>；需要完整應用層組合讀 &lt;a href="https://tarrragon.github.io/blog/llm/04-applications/application-protocols/" data-link-title="4.6 應用層協議：function calling / structured output / MCP" data-link-desc="三個常被混為一談的概念：模型能力、sampling 約束、server 協議，三者的層級差異與組合方式">4.6 應用層協議&lt;/a>。&lt;/p></description><content:encoded><![CDATA[<p>Structured output 的核心概念是「<strong>讓 LLM 輸出符合可機器解析的固定形狀</strong>」。它解的是應用層 parser 能不能穩定消費模型輸出的問題：輸出要能被 JSON parser、schema validator、dispatcher、workflow engine 確定性處理，而不是靠人類讀自然語言再猜意圖。</p>
<h2 id="概念位置">概念位置</h2>
<p>Structured output 位在推論與應用交界，常見實作包含 JSON mode、JSON Schema、<a href="/blog/llm/knowledge-cards/grammar/" data-link-title="Grammar" data-link-desc="描述合法字串形狀的形式規則，在 structured output 中用來限制 LLM 每一步可輸出的 token">grammar</a> 約束、<a href="/blog/llm/knowledge-cards/constrained-decoding/" data-link-title="Constrained Decoding" data-link-desc="推論時用 grammar 強制 LLM 輸出符合特定格式（JSON / regex / CFG）的 sampling 機制、把不合法 token 的機率歸零">constrained decoding</a> 與 logit mask。它跟 <a href="/blog/llm/knowledge-cards/function-calling/" data-link-title="Function Calling" data-link-desc="模型訓練階段建立的「呼叫工具」能力：知道何時該呼叫、傳什麼參數">function calling</a> 的差異在責任層：function calling 是模型訓練出的工具呼叫能力，structured output 是推論時讓輸出形狀穩定的約束。</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="ln">1</span><span class="cl">模型能力：知道是否該呼叫工具、該填什麼參數
</span></span><span class="line"><span class="ln">2</span><span class="cl">推論約束：輸出必須符合 JSON / schema / grammar
</span></span><span class="line"><span class="ln">3</span><span class="cl">應用消費：parser 解析、validator 檢查、dispatcher 執行</span></span></code></pre></div><h2 id="可觀察訊號與例子">可觀察訊號與例子</h2>
<p>看到「固定輸出 JSON」「把結果分類成 enum」「回傳符合 schema 的物件」「讓 parser 不再處理自由文字」就是 structured output 場景。例子是客服工單分類：模型輸出 <code>{&quot;category&quot;:&quot;billing&quot;,&quot;priority&quot;:&quot;high&quot;}</code>，後端可以直接依欄位路由，而不是從一段自然語言裡抽關鍵字。</p>
<p>Structured output 的成功訊號是合法率、schema 對位率與下游解析失敗率。JSON 合法率只代表文字可被 parser 讀，schema 對位率才代表欄位、型別、enum、required 都符合應用契約；兩者分開看，才能分辨是語法錯、schema 錯，還是模型語意判斷錯。</p>
<h2 id="設計責任">設計責任</h2>
<p>Structured output 適合「下游要自動執行」的輸出：tool 參數、分類、抽取、workflow 狀態、查詢條件。它的邊界是語意品質：grammar 可以保證格式合法，但不能保證模型填的值正確。下一步路由是：需要理解 token mask 機制讀 <a href="/blog/llm/knowledge-cards/constrained-decoding/" data-link-title="Constrained Decoding" data-link-desc="推論時用 grammar 強制 LLM 輸出符合特定格式（JSON / regex / CFG）的 sampling 機制、把不合法 token 的機率歸零">Constrained Decoding</a>；需要判斷它跟工具呼叫的分工讀 <a href="/blog/llm/knowledge-cards/function-calling/" data-link-title="Function Calling" data-link-desc="模型訓練階段建立的「呼叫工具」能力：知道何時該呼叫、傳什麼參數">Function Calling</a>；需要完整應用層組合讀 <a href="/blog/llm/04-applications/application-protocols/" data-link-title="4.6 應用層協議：function calling / structured output / MCP" data-link-desc="三個常被混為一談的概念：模型能力、sampling 約束、server 協議，三者的層級差異與組合方式">4.6 應用層協議</a>。</p>
]]></content:encoded></item><item><title>Three-Layer Architecture</title><link>https://tarrragon.github.io/blog/llm/knowledge-cards/three-layer-architecture/</link><pubDate>Thu, 14 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/llm/knowledge-cards/three-layer-architecture/</guid><description>&lt;p>Three-layer architecture（三層架構）的核心概念是「&lt;strong>把本地 LLM 系統拆成介面層、&lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/inference-server/" data-link-title="Inference Server" data-link-desc="載入模型權重、處理 prompt、產生 token 的常駐 process">inference server&lt;/a> 層、模型層&lt;/strong>」。這個分層讓讀者能判斷一個工具是在處理使用者互動、模型 serving，還是權重本身。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>三層責任分工如下：&lt;/p>





&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-text" data-lang="text">&lt;span class="line">&lt;span class="ln">1&lt;/span>&lt;span class="cl">介面層：CLI / IDE plugin / Web UI，負責接收任務與顯示結果
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">2&lt;/span>&lt;span class="cl">伺服器層：inference server，負責載入模型、提供 API、跑推論
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">3&lt;/span>&lt;span class="cl">模型層：權重檔與 tokenizer，負責提供可被執行的神經網路參數&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>它跟 &lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/openai-compatible-api/" data-link-title="OpenAI 相容 API" data-link-desc="本地推論伺服器跟雲端 OpenAI 共用的 API 形狀標準">OpenAI 相容 API&lt;/a> 的關係是：API 是介面層跟伺服器層之間的標準接縫；跟 &lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/inference-server/" data-link-title="Inference Server" data-link-desc="載入模型權重、處理 prompt、產生 token 的常駐 process">inference server&lt;/a> 的關係是：伺服器層是三層中的中介。&lt;/p>
&lt;h2 id="可觀察訊號與例子">可觀察訊號與例子&lt;/h2>
&lt;p>看到 Continue.dev、Open WebUI、aider，通常是在介面層；看到 Ollama、LM Studio server、llama.cpp server、vLLM，通常是在伺服器層；看到 GGUF、Safetensors、MLX 權重，通常是在模型層。LM Studio 這類 all-in-one 工具會跨層，但仍可拆成 UI 與 server 兩種責任。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>排錯或換工具時，先問「問題出在哪一層」。連不上 &lt;code>localhost&lt;/code> 是伺服器或網路問題；回答品質差多半是模型或 prompt 問題；IDE 操作不順是介面層問題。完整推導見 &lt;a href="https://tarrragon.github.io/blog/llm/00-foundations/three-layer-architecture/" data-link-title="0.2 介面 / 伺服器 / 模型三層架構" data-link-desc="把任何本地 LLM 工具放回正確的層級，用三層心智模型看懂工具關係">0.2 三層架構&lt;/a>。&lt;/p></description><content:encoded><![CDATA[<p>Three-layer architecture（三層架構）的核心概念是「<strong>把本地 LLM 系統拆成介面層、<a href="/blog/llm/knowledge-cards/inference-server/" data-link-title="Inference Server" data-link-desc="載入模型權重、處理 prompt、產生 token 的常駐 process">inference server</a> 層、模型層</strong>」。這個分層讓讀者能判斷一個工具是在處理使用者互動、模型 serving，還是權重本身。</p>
<h2 id="概念位置">概念位置</h2>
<p>三層責任分工如下：</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="ln">1</span><span class="cl">介面層：CLI / IDE plugin / Web UI，負責接收任務與顯示結果
</span></span><span class="line"><span class="ln">2</span><span class="cl">伺服器層：inference server，負責載入模型、提供 API、跑推論
</span></span><span class="line"><span class="ln">3</span><span class="cl">模型層：權重檔與 tokenizer，負責提供可被執行的神經網路參數</span></span></code></pre></div><p>它跟 <a href="/blog/llm/knowledge-cards/openai-compatible-api/" data-link-title="OpenAI 相容 API" data-link-desc="本地推論伺服器跟雲端 OpenAI 共用的 API 形狀標準">OpenAI 相容 API</a> 的關係是：API 是介面層跟伺服器層之間的標準接縫；跟 <a href="/blog/llm/knowledge-cards/inference-server/" data-link-title="Inference Server" data-link-desc="載入模型權重、處理 prompt、產生 token 的常駐 process">inference server</a> 的關係是：伺服器層是三層中的中介。</p>
<h2 id="可觀察訊號與例子">可觀察訊號與例子</h2>
<p>看到 Continue.dev、Open WebUI、aider，通常是在介面層；看到 Ollama、LM Studio server、llama.cpp server、vLLM，通常是在伺服器層；看到 GGUF、Safetensors、MLX 權重，通常是在模型層。LM Studio 這類 all-in-one 工具會跨層，但仍可拆成 UI 與 server 兩種責任。</p>
<h2 id="設計責任">設計責任</h2>
<p>排錯或換工具時，先問「問題出在哪一層」。連不上 <code>localhost</code> 是伺服器或網路問題；回答品質差多半是模型或 prompt 問題；IDE 操作不順是介面層問題。完整推導見 <a href="/blog/llm/00-foundations/three-layer-architecture/" data-link-title="0.2 介面 / 伺服器 / 模型三層架構" data-link-desc="把任何本地 LLM 工具放回正確的層級，用三層心智模型看懂工具關係">0.2 三層架構</a>。</p>
]]></content:encoded></item><item><title>Tool Result Misread</title><link>https://tarrragon.github.io/blog/llm/knowledge-cards/tool-result-misread/</link><pubDate>Thu, 14 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/llm/knowledge-cards/tool-result-misread/</guid><description>&lt;p>Tool result misread（工具結果誤判）的核心概念是「&lt;strong>agent 把工具輸出的錯誤或不完整狀態解讀成成功&lt;/strong>」。LLM 只看文字與結構化回傳，若工具結果設計不清楚，模型容易忽略 error、warning、空集合或 partial failure。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>它是 &lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/tool-use/" data-link-title="Tool Use" data-link-desc="LLM 透過結構化呼叫外部工具（讀檔、查資料庫、發 API request）來擴展能力的設計、function calling 跟 MCP 是常見實作">tool use&lt;/a> 與 &lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/agent-loop/" data-link-title="Agent Loop" data-link-desc="LLM agent 自我循環的工作流：LLM 規劃下一步、執行 tool、看結果、再規劃下一步、直到任務完成或停止條件觸發">agent loop&lt;/a> 交界的失敗模式。模型可能選對工具、也成功呼叫工具，但在 observe 階段錯讀結果。&lt;/p>
&lt;h2 id="可觀察訊號與例子">可觀察訊號與例子&lt;/h2>
&lt;p>&lt;code>git push&lt;/code> 失敗，agent 卻開始寫 PR description；查詢回空集合，agent 卻假設資料存在；測試命令非零退出，agent 只讀到最後幾行 log 就當成功。這些都是工具結果誤判。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>工具回傳要結構化表示 status、exit code、error type、stdout/stderr 與可重試性。Agent loop 要在 error signal 出現時強制 re-read 或 retry，必要時呼叫狀態確認工具，而不是依賴模型記憶。&lt;/p></description><content:encoded><![CDATA[<p>Tool result misread（工具結果誤判）的核心概念是「<strong>agent 把工具輸出的錯誤或不完整狀態解讀成成功</strong>」。LLM 只看文字與結構化回傳，若工具結果設計不清楚，模型容易忽略 error、warning、空集合或 partial failure。</p>
<h2 id="概念位置">概念位置</h2>
<p>它是 <a href="/blog/llm/knowledge-cards/tool-use/" data-link-title="Tool Use" data-link-desc="LLM 透過結構化呼叫外部工具（讀檔、查資料庫、發 API request）來擴展能力的設計、function calling 跟 MCP 是常見實作">tool use</a> 與 <a href="/blog/llm/knowledge-cards/agent-loop/" data-link-title="Agent Loop" data-link-desc="LLM agent 自我循環的工作流：LLM 規劃下一步、執行 tool、看結果、再規劃下一步、直到任務完成或停止條件觸發">agent loop</a> 交界的失敗模式。模型可能選對工具、也成功呼叫工具，但在 observe 階段錯讀結果。</p>
<h2 id="可觀察訊號與例子">可觀察訊號與例子</h2>
<p><code>git push</code> 失敗，agent 卻開始寫 PR description；查詢回空集合，agent 卻假設資料存在；測試命令非零退出，agent 只讀到最後幾行 log 就當成功。這些都是工具結果誤判。</p>
<h2 id="設計責任">設計責任</h2>
<p>工具回傳要結構化表示 status、exit code、error type、stdout/stderr 與可重試性。Agent loop 要在 error signal 出現時強制 re-read 或 retry，必要時呼叫狀態確認工具，而不是依賴模型記憶。</p>
]]></content:encoded></item><item><title>Tool-Use Permission Model</title><link>https://tarrragon.github.io/blog/llm/knowledge-cards/tool-use-permission-model/</link><pubDate>Thu, 14 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/llm/knowledge-cards/tool-use-permission-model/</guid><description>&lt;p>Tool-use permission model 的核心概念是「&lt;strong>按工具副作用範圍設計 LLM 可以做什麼、何時需要人類批准&lt;/strong>」。模型只生成 &lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/tool-use/" data-link-title="Tool Use" data-link-desc="LLM 透過結構化呼叫外部工具（讀檔、查資料庫、發 API request）來擴展能力的設計、function calling 跟 MCP 是常見實作">tool use&lt;/a> call，真正副作用由 client、MCP server、shell 或外部 API 執行，因此權限邊界必須放在工具層與執行環境。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>它建立在 &lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/tool-use/" data-link-title="Tool Use" data-link-desc="LLM 透過結構化呼叫外部工具（讀檔、查資料庫、發 API request）來擴展能力的設計、function calling 跟 MCP 是常見實作">tool use&lt;/a>、&lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/mcp/" data-link-title="MCP（Model Context Protocol）" data-link-desc="LLM application ↔ 外部 tool server 之間的標準化協議、複用 OpenAI 相容 API 的成功模式">MCP&lt;/a> 與 &lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/sandbox/" data-link-title="Sandbox" data-link-desc="把程式跑在受限制環境的隔離技術、限制檔案 / 網路 / 系統呼叫權限、是 tool use 跟 MCP server 副作用控制的基礎">sandbox&lt;/a> 之上。核心不是模型是否「想」執行，而是執行該 tool 的 process 是否有權限、是否有 allowlist、是否需要 approval。&lt;/p>
&lt;h2 id="可觀察訊號與例子">可觀察訊號與例子&lt;/h2>
&lt;p>Read-only file search 可以自動；修改檔案要 checkpoint；刪除資料、push、部署、發送外部訊息通常要 step-by-step approval。第三方 MCP server 如果能讀整個 home directory，風險高於只讀 workspace 的 server。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>先把工具分成 read、local write、external side effect、irreversible operation，再配置 sandbox、allowlist、confirmation、audit log 與 rollback。高風險工具的預設應是人類批准，而不是 prompt 裡要求模型小心。&lt;/p></description><content:encoded><![CDATA[<p>Tool-use permission model 的核心概念是「<strong>按工具副作用範圍設計 LLM 可以做什麼、何時需要人類批准</strong>」。模型只生成 <a href="/blog/llm/knowledge-cards/tool-use/" data-link-title="Tool Use" data-link-desc="LLM 透過結構化呼叫外部工具（讀檔、查資料庫、發 API request）來擴展能力的設計、function calling 跟 MCP 是常見實作">tool use</a> call，真正副作用由 client、MCP server、shell 或外部 API 執行，因此權限邊界必須放在工具層與執行環境。</p>
<h2 id="概念位置">概念位置</h2>
<p>它建立在 <a href="/blog/llm/knowledge-cards/tool-use/" data-link-title="Tool Use" data-link-desc="LLM 透過結構化呼叫外部工具（讀檔、查資料庫、發 API request）來擴展能力的設計、function calling 跟 MCP 是常見實作">tool use</a>、<a href="/blog/llm/knowledge-cards/mcp/" data-link-title="MCP（Model Context Protocol）" data-link-desc="LLM application ↔ 外部 tool server 之間的標準化協議、複用 OpenAI 相容 API 的成功模式">MCP</a> 與 <a href="/blog/llm/knowledge-cards/sandbox/" data-link-title="Sandbox" data-link-desc="把程式跑在受限制環境的隔離技術、限制檔案 / 網路 / 系統呼叫權限、是 tool use 跟 MCP server 副作用控制的基礎">sandbox</a> 之上。核心不是模型是否「想」執行，而是執行該 tool 的 process 是否有權限、是否有 allowlist、是否需要 approval。</p>
<h2 id="可觀察訊號與例子">可觀察訊號與例子</h2>
<p>Read-only file search 可以自動；修改檔案要 checkpoint；刪除資料、push、部署、發送外部訊息通常要 step-by-step approval。第三方 MCP server 如果能讀整個 home directory，風險高於只讀 workspace 的 server。</p>
<h2 id="設計責任">設計責任</h2>
<p>先把工具分成 read、local write、external side effect、irreversible operation，再配置 sandbox、allowlist、confirmation、audit log 與 rollback。高風險工具的預設應是人類批准，而不是 prompt 裡要求模型小心。</p>
]]></content:encoded></item><item><title>Training Example Coverage</title><link>https://tarrragon.github.io/blog/llm/knowledge-cards/training-example-coverage/</link><pubDate>Thu, 14 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/llm/knowledge-cards/training-example-coverage/</guid><description>&lt;p>Training example coverage（訓練範例覆蓋度）的核心概念是「&lt;strong>模型在訓練時看過的任務情境是否足以支撐部署時遇到的變化&lt;/strong>」。LLM 的能力宣稱常寫成支援某功能，但實際穩定性取決於範例是否覆蓋工具數量、參數形狀、語言變體、錯誤情境與 edge cases。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>Coverage 是訓練資料分佈的問題，常在 &lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/sft/" data-link-title="SFT（Supervised Fine-Tuning）" data-link-desc="在 base model 上用「指令-回答」對資料微調、讓模型會跟著指令走">SFT&lt;/a>、偏好資料、tool-use data、domain fine-tune 裡出現。它跟 prompt 範例不同：few-shot 範例只存在於當次 context，training examples 會透過訓練更新模型權重，影響模型「自然」傾向怎麼回答。&lt;/p>





&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-text" data-lang="text">&lt;span class="line">&lt;span class="ln">1&lt;/span>&lt;span class="cl">訓練資料有覆蓋 → 模型自然輸出穩定
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">2&lt;/span>&lt;span class="cl">訓練資料缺口大 → 靠 prompt / structured output / validator 兜底&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h2 id="可觀察訊號與例子">可觀察訊號與例子&lt;/h2>
&lt;p>Function calling 的 coverage 可從四個面向判讀：該呼叫時是否呼叫、工具選擇是否正確、參數型別是否正確、巢狀 schema 與多工具情境是否穩定。小模型常在單一工具 + 平坦 schema 表現可用，但一進到多工具、optional field、nested object、跨語言 query 就明顯掉分，這通常是 coverage 不足而不是單純 parser 問題。&lt;/p>
&lt;p>Coverage 的陷阱是只看 happy path。訓練範例如果只有成功呼叫工具，模型會傾向每次都呼叫；如果缺少「資訊不足時先追問」「使用者要求超出權限時拒絕」「工具錯誤時重試或回退」這類範例，部署後會在安全與可靠性邊界失敗。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>評估模型能力時，把支援功能改問成覆蓋範圍：支援哪些 tool schema 複雜度、哪些語言、哪些錯誤路徑、哪些反例。下一步路由是用 eval set 補齊代表性情境；如果 coverage 無法補在模型訓練層，就用 &lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/structured-output/" data-link-title="Structured Output" data-link-desc="讓 LLM 輸出可被 parser 穩定消費的推論階段設計：JSON mode、schema-guided decoding、grammar 約束都屬於這一層">structured output&lt;/a>、validator、retry 與 fallback 降低失敗成本。&lt;/p></description><content:encoded><![CDATA[<p>Training example coverage（訓練範例覆蓋度）的核心概念是「<strong>模型在訓練時看過的任務情境是否足以支撐部署時遇到的變化</strong>」。LLM 的能力宣稱常寫成支援某功能，但實際穩定性取決於範例是否覆蓋工具數量、參數形狀、語言變體、錯誤情境與 edge cases。</p>
<h2 id="概念位置">概念位置</h2>
<p>Coverage 是訓練資料分佈的問題，常在 <a href="/blog/llm/knowledge-cards/sft/" data-link-title="SFT（Supervised Fine-Tuning）" data-link-desc="在 base model 上用「指令-回答」對資料微調、讓模型會跟著指令走">SFT</a>、偏好資料、tool-use data、domain fine-tune 裡出現。它跟 prompt 範例不同：few-shot 範例只存在於當次 context，training examples 會透過訓練更新模型權重，影響模型「自然」傾向怎麼回答。</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="ln">1</span><span class="cl">訓練資料有覆蓋 → 模型自然輸出穩定
</span></span><span class="line"><span class="ln">2</span><span class="cl">訓練資料缺口大 → 靠 prompt / structured output / validator 兜底</span></span></code></pre></div><h2 id="可觀察訊號與例子">可觀察訊號與例子</h2>
<p>Function calling 的 coverage 可從四個面向判讀：該呼叫時是否呼叫、工具選擇是否正確、參數型別是否正確、巢狀 schema 與多工具情境是否穩定。小模型常在單一工具 + 平坦 schema 表現可用，但一進到多工具、optional field、nested object、跨語言 query 就明顯掉分，這通常是 coverage 不足而不是單純 parser 問題。</p>
<p>Coverage 的陷阱是只看 happy path。訓練範例如果只有成功呼叫工具，模型會傾向每次都呼叫；如果缺少「資訊不足時先追問」「使用者要求超出權限時拒絕」「工具錯誤時重試或回退」這類範例，部署後會在安全與可靠性邊界失敗。</p>
<h2 id="設計責任">設計責任</h2>
<p>評估模型能力時，把支援功能改問成覆蓋範圍：支援哪些 tool schema 複雜度、哪些語言、哪些錯誤路徑、哪些反例。下一步路由是用 eval set 補齊代表性情境；如果 coverage 無法補在模型訓練層，就用 <a href="/blog/llm/knowledge-cards/structured-output/" data-link-title="Structured Output" data-link-desc="讓 LLM 輸出可被 parser 穩定消費的推論階段設計：JSON mode、schema-guided decoding、grammar 約束都屬於這一層">structured output</a>、validator、retry 與 fallback 降低失敗成本。</p>
]]></content:encoded></item><item><title>Unigram Tokenizer</title><link>https://tarrragon.github.io/blog/llm/knowledge-cards/unigram-tokenizer/</link><pubDate>Thu, 14 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/llm/knowledge-cards/unigram-tokenizer/</guid><description>&lt;p>Unigram tokenizer 的核心概念是「&lt;strong>把 &lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/token/" data-link-title="Token" data-link-desc="LLM 處理文字時的最小單位：介於字元與單字之間">token&lt;/a> 切分視為從候選子詞集合中選最可能切分的機率問題&lt;/strong>」。它先有一組候選 subword，再用機率模型找出最合理的切分，有別於逐步合併字元對的做法。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>Unigram 是 subword tokenizer 家族的一員，常由 &lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/sentencepiece/" data-link-title="SentencePiece" data-link-desc="Google 開源的多語言 tokenization 框架、支援 BPE 跟 unigram 演算法、處理空白統一">SentencePiece&lt;/a> 支援。它跟 &lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/bpe/" data-link-title="BPE（Byte-Pair Encoding）" data-link-desc="用「最常一起出現的字元對」合併建詞彙表的 tokenization 演算法、GPT / Llama 等主流">BPE&lt;/a> 的差異在訓練與切分策略：BPE 是貪婪合併，unigram 是機率選擇與剪枝候選。&lt;/p>
&lt;h2 id="可觀察訊號與例子">可觀察訊號與例子&lt;/h2>
&lt;p>讀 tokenizer 文件看到「unigram language model」「subword regularization」「SentencePiece unigram」就是這個概念。它可在訓練時對同一句話採不同合理切分，增加 tokenizer 層的資料多樣性。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>一般應用不會手動選 unigram tokenizer，但理解它能幫助比較模型的多語言支援與 token 效率。判讀時搭配 &lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/vocabulary-size/" data-link-title="Vocabulary Size" data-link-desc="tokenizer 詞彙表的 token 總數、影響 embedding 大小、tokenization 粒度、多語言友善度">Vocabulary Size&lt;/a> 與 &lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/token/" data-link-title="Token" data-link-desc="LLM 處理文字時的最小單位：介於字元與單字之間">Token&lt;/a>。&lt;/p></description><content:encoded><![CDATA[<p>Unigram tokenizer 的核心概念是「<strong>把 <a href="/blog/llm/knowledge-cards/token/" data-link-title="Token" data-link-desc="LLM 處理文字時的最小單位：介於字元與單字之間">token</a> 切分視為從候選子詞集合中選最可能切分的機率問題</strong>」。它先有一組候選 subword，再用機率模型找出最合理的切分，有別於逐步合併字元對的做法。</p>
<h2 id="概念位置">概念位置</h2>
<p>Unigram 是 subword tokenizer 家族的一員，常由 <a href="/blog/llm/knowledge-cards/sentencepiece/" data-link-title="SentencePiece" data-link-desc="Google 開源的多語言 tokenization 框架、支援 BPE 跟 unigram 演算法、處理空白統一">SentencePiece</a> 支援。它跟 <a href="/blog/llm/knowledge-cards/bpe/" data-link-title="BPE（Byte-Pair Encoding）" data-link-desc="用「最常一起出現的字元對」合併建詞彙表的 tokenization 演算法、GPT / Llama 等主流">BPE</a> 的差異在訓練與切分策略：BPE 是貪婪合併，unigram 是機率選擇與剪枝候選。</p>
<h2 id="可觀察訊號與例子">可觀察訊號與例子</h2>
<p>讀 tokenizer 文件看到「unigram language model」「subword regularization」「SentencePiece unigram」就是這個概念。它可在訓練時對同一句話採不同合理切分，增加 tokenizer 層的資料多樣性。</p>
<h2 id="設計責任">設計責任</h2>
<p>一般應用不會手動選 unigram tokenizer，但理解它能幫助比較模型的多語言支援與 token 效率。判讀時搭配 <a href="/blog/llm/knowledge-cards/vocabulary-size/" data-link-title="Vocabulary Size" data-link-desc="tokenizer 詞彙表的 token 總數、影響 embedding 大小、tokenization 粒度、多語言友善度">Vocabulary Size</a> 與 <a href="/blog/llm/knowledge-cards/token/" data-link-title="Token" data-link-desc="LLM 處理文字時的最小單位：介於字元與單字之間">Token</a>。</p>
]]></content:encoded></item><item><title>Word2Vec</title><link>https://tarrragon.github.io/blog/llm/knowledge-cards/word2vec/</link><pubDate>Thu, 14 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/llm/knowledge-cards/word2vec/</guid><description>&lt;p>Word2Vec 的核心概念是「&lt;strong>用上下文預測任務學出靜態詞向量&lt;/strong>」。它讓語意相近的詞在向量空間中靠近，是理解 &lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/embedding-model/" data-link-title="Embedding Model" data-link-desc="把文字轉成向量的模型：用於 codebase 索引與語意搜尋">embedding model&lt;/a> 與 embedding space 的經典起點。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>Word2Vec 屬於 LLM 前一代的 static embedding 方法，常見訓練方式是 skip-gram 與 CBOW。它跟現代 &lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/embedding-model/" data-link-title="Embedding Model" data-link-desc="把文字轉成向量的模型：用於 codebase 索引與語意搜尋">embedding model&lt;/a> 的差異是：Word2Vec 對同一個詞給固定向量，現代 Transformer 會依上下文產生 contextual representation。&lt;/p>
&lt;h2 id="可觀察訊號與例子">可觀察訊號與例子&lt;/h2>
&lt;p>經典例子是 &lt;code>king - man + woman ≈ queen&lt;/code> 這類向量類比。它展示 embedding space 可以承載語意方向，但也暴露靜態詞向量對多義詞與上下文的限制。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>讀 embedding 章節看到 Word2Vec 時，把它當成「embedding 概念的歷史基線」。實務 RAG 選型通常看現代 embedding model 與 &lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/mteb-benchmark/" data-link-title="MTEB" data-link-desc="Massive Text Embedding Benchmark：8 大類 56 任務、評估 embedding model 跨任務通用能力的標準">MTEB&lt;/a>，不是直接使用 Word2Vec。&lt;/p></description><content:encoded><![CDATA[<p>Word2Vec 的核心概念是「<strong>用上下文預測任務學出靜態詞向量</strong>」。它讓語意相近的詞在向量空間中靠近，是理解 <a href="/blog/llm/knowledge-cards/embedding-model/" data-link-title="Embedding Model" data-link-desc="把文字轉成向量的模型：用於 codebase 索引與語意搜尋">embedding model</a> 與 embedding space 的經典起點。</p>
<h2 id="概念位置">概念位置</h2>
<p>Word2Vec 屬於 LLM 前一代的 static embedding 方法，常見訓練方式是 skip-gram 與 CBOW。它跟現代 <a href="/blog/llm/knowledge-cards/embedding-model/" data-link-title="Embedding Model" data-link-desc="把文字轉成向量的模型：用於 codebase 索引與語意搜尋">embedding model</a> 的差異是：Word2Vec 對同一個詞給固定向量，現代 Transformer 會依上下文產生 contextual representation。</p>
<h2 id="可觀察訊號與例子">可觀察訊號與例子</h2>
<p>經典例子是 <code>king - man + woman ≈ queen</code> 這類向量類比。它展示 embedding space 可以承載語意方向，但也暴露靜態詞向量對多義詞與上下文的限制。</p>
<h2 id="設計責任">設計責任</h2>
<p>讀 embedding 章節看到 Word2Vec 時，把它當成「embedding 概念的歷史基線」。實務 RAG 選型通常看現代 embedding model 與 <a href="/blog/llm/knowledge-cards/mteb-benchmark/" data-link-title="MTEB" data-link-desc="Massive Text Embedding Benchmark：8 大類 56 任務、評估 embedding model 跨任務通用能力的標準">MTEB</a>，不是直接使用 Word2Vec。</p>
]]></content:encoded></item><item><title>WordPiece</title><link>https://tarrragon.github.io/blog/llm/knowledge-cards/wordpiece/</link><pubDate>Thu, 14 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/llm/knowledge-cards/wordpiece/</guid><description>&lt;p>WordPiece 的核心概念是「&lt;strong>用語料 likelihood 改善量選擇子詞合併的 tokenization 演算法&lt;/strong>」。它跟 &lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/bpe/" data-link-title="BPE（Byte-Pair Encoding）" data-link-desc="用「最常一起出現的字元對」合併建詞彙表的 tokenization 演算法、GPT / Llama 等主流">BPE&lt;/a> 一樣把文字拆成 subword，但選擇 merge 的準則不同。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>WordPiece 屬於 subword tokenizer 家族，BERT 系列是代表。BPE 偏向合併高頻相鄰片段；WordPiece 偏向選擇能最大化語言模型 likelihood 的片段；&lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/sentencepiece/" data-link-title="SentencePiece" data-link-desc="Google 開源的多語言 tokenization 框架、支援 BPE 跟 unigram 演算法、處理空白統一">SentencePiece&lt;/a> 則是 tokenizer framework，可支援 BPE 或 unigram。&lt;/p>
&lt;h2 id="可觀察訊號與例子">可觀察訊號與例子&lt;/h2>
&lt;p>看到 &lt;code>##ing&lt;/code>、&lt;code>##ed&lt;/code> 這類 continuation marker，通常是 WordPiece 風格 vocabulary。它讓模型能處理未見過的詞，因為陌生詞仍可拆成已知 subword。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>比較 tokenizer 時，WordPiece 主要作為 BERT/encoder 系統的背景知識。寫 LLM 推論與本地 serving 時更常遇到 BPE、SentencePiece、vocab size 與 special tokens。&lt;/p></description><content:encoded><![CDATA[<p>WordPiece 的核心概念是「<strong>用語料 likelihood 改善量選擇子詞合併的 tokenization 演算法</strong>」。它跟 <a href="/blog/llm/knowledge-cards/bpe/" data-link-title="BPE（Byte-Pair Encoding）" data-link-desc="用「最常一起出現的字元對」合併建詞彙表的 tokenization 演算法、GPT / Llama 等主流">BPE</a> 一樣把文字拆成 subword，但選擇 merge 的準則不同。</p>
<h2 id="概念位置">概念位置</h2>
<p>WordPiece 屬於 subword tokenizer 家族，BERT 系列是代表。BPE 偏向合併高頻相鄰片段；WordPiece 偏向選擇能最大化語言模型 likelihood 的片段；<a href="/blog/llm/knowledge-cards/sentencepiece/" data-link-title="SentencePiece" data-link-desc="Google 開源的多語言 tokenization 框架、支援 BPE 跟 unigram 演算法、處理空白統一">SentencePiece</a> 則是 tokenizer framework，可支援 BPE 或 unigram。</p>
<h2 id="可觀察訊號與例子">可觀察訊號與例子</h2>
<p>看到 <code>##ing</code>、<code>##ed</code> 這類 continuation marker，通常是 WordPiece 風格 vocabulary。它讓模型能處理未見過的詞，因為陌生詞仍可拆成已知 subword。</p>
<h2 id="設計責任">設計責任</h2>
<p>比較 tokenizer 時，WordPiece 主要作為 BERT/encoder 系統的背景知識。寫 LLM 推論與本地 serving 時更常遇到 BPE、SentencePiece、vocab size 與 special tokens。</p>
]]></content:encoded></item><item><title>Acceptance Rate</title><link>https://tarrragon.github.io/blog/llm/knowledge-cards/acceptance-rate/</link><pubDate>Tue, 12 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/llm/knowledge-cards/acceptance-rate/</guid><description>&lt;p>Acceptance rate（接受率）的核心概念是「&lt;strong>在 &lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/speculative-decoding/" data-link-title="Speculative Decoding" data-link-desc="用小模型猜未來 token、大模型並行驗證的加速技巧">speculative decoding&lt;/a> 中、&lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/drafter-model/" data-link-title="Drafter Model" data-link-desc="speculative decoding 中用來快速猜未來 token 的小模型">drafter&lt;/a> 提出的 token 序列被 target model 驗證後接受的比例&lt;/strong>」。Acceptance rate 直接決定 speculative decoding 的實際加速倍率：高 acceptance rate（如 0.8）能拉出接近理論上限的加速；低 acceptance rate（如 0.3）可能反而比純 target model 慢。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>Speculative decoding 一個 step 的流程：&lt;/p>





&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-text" data-lang="text">&lt;span class="line">&lt;span class="ln">1&lt;/span>&lt;span class="cl">1. Drafter 一次生 K 個候選 token（如 K=5）
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">2&lt;/span>&lt;span class="cl">2. Target model 對「prefix + 這 K 個 token」並行驗證
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">3&lt;/span>&lt;span class="cl">3. 從前往後：
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">4&lt;/span>&lt;span class="cl"> - drafter token i 跟 target 第 i 個位置 sampling 一致 → 接受
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">5&lt;/span>&lt;span class="cl"> - 第一個不一致 → 接受到此為止、用 target 的 token 取代第一個不一致
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">6&lt;/span>&lt;span class="cl">4. 若全 K 個都接受、target 再 sample 一個 bonus token&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>Acceptance rate 影響：&lt;/p>
&lt;table>
 &lt;thead>
 &lt;tr>
 &lt;th>場景&lt;/th>
 &lt;th>Acceptance rate&lt;/th>
 &lt;th>實際加速&lt;/th>
 &lt;/tr>
 &lt;/thead>
 &lt;tbody>
 &lt;tr>
 &lt;td>Drafter 跟 target 高度同分佈&lt;/td>
 &lt;td>0.8 ~ 0.95&lt;/td>
 &lt;td>接近 K 倍上限&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>Drafter / target 一般搭配&lt;/td>
 &lt;td>0.5 ~ 0.7&lt;/td>
 &lt;td>約 1.5 ~ 2× 加速&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>Drafter 訓練分佈差很多&lt;/td>
 &lt;td>0.2 ~ 0.4&lt;/td>
 &lt;td>接近 1×（甚至更慢）&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>Drafter / target tokenizer 不一致&lt;/td>
 &lt;td>不能用&lt;/td>
 &lt;td>概念不成立&lt;/td>
 &lt;/tr>
 &lt;/tbody>
&lt;/table>
&lt;h2 id="影響-acceptance-rate-的因素">影響 acceptance rate 的因素&lt;/h2>
&lt;ol>
&lt;li>&lt;strong>Drafter / target 同 family&lt;/strong>：同訓練分佈、acceptance rate 高（如 Gemma 4 31B + Gemma 4 E4B）&lt;/li>
&lt;li>&lt;strong>任務難度&lt;/strong>：簡單任務（boilerplate、常見 pattern）drafter 容易猜對；困難任務（reasoning、罕見領域）acceptance rate 降&lt;/li>
&lt;li>&lt;strong>Sampling temperature&lt;/strong>：高 temperature 兩邊 sample 分佈都拉平、隨機性增加、acceptance rate 降；T=0（greedy）acceptance rate 最高&lt;/li>
&lt;li>&lt;strong>K 設太大&lt;/strong>：drafter 越往後預測、累積誤差越大、後半段 token acceptance rate 急降；K 通常設 3-5 為甜蜜點&lt;/li>
&lt;/ol>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>讀 speculative decoding 設定 / model card 看到「draft acceptance」「acceptance length」就是這指標。寫 code 場景的判讀：&lt;/p>
&lt;ol>
&lt;li>&lt;strong>挑 drafter 看 family + 大小&lt;/strong>：drafter 跟 target 同 family（如 Gemma 4 31B + Gemma 4 E4B、Qwen3-30B + Qwen3-1.5B）是 acceptance rate 最高的組合&lt;/li>
&lt;li>&lt;strong>&lt;code>llama-bench&lt;/code> 量實際加速比理論 K 倍重要&lt;/strong>：理論加速 = K × acceptance rate、實測才知道 drafter 在自己工作流的真實表現&lt;/li>
&lt;li>&lt;strong>太低的 acceptance rate 是訊號&lt;/strong>：&amp;lt; 0.3 通常表示 drafter / target 不匹配、值得換 drafter；&amp;lt; 0.5 表示甜蜜點以下、可調 K 或 sampling 設定&lt;/li>
&lt;li>&lt;strong>MTP（Multi-Token Prediction）&lt;/strong>：把 drafter 改成 target 內建多預測 head、acceptance rate 通常更高（因為 head 跟 target 完全同分佈）&lt;/li>
&lt;/ol></description><content:encoded><![CDATA[<p>Acceptance rate（接受率）的核心概念是「<strong>在 <a href="/blog/llm/knowledge-cards/speculative-decoding/" data-link-title="Speculative Decoding" data-link-desc="用小模型猜未來 token、大模型並行驗證的加速技巧">speculative decoding</a> 中、<a href="/blog/llm/knowledge-cards/drafter-model/" data-link-title="Drafter Model" data-link-desc="speculative decoding 中用來快速猜未來 token 的小模型">drafter</a> 提出的 token 序列被 target model 驗證後接受的比例</strong>」。Acceptance rate 直接決定 speculative decoding 的實際加速倍率：高 acceptance rate（如 0.8）能拉出接近理論上限的加速；低 acceptance rate（如 0.3）可能反而比純 target model 慢。</p>
<h2 id="概念位置">概念位置</h2>
<p>Speculative decoding 一個 step 的流程：</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="ln">1</span><span class="cl">1. Drafter 一次生 K 個候選 token（如 K=5）
</span></span><span class="line"><span class="ln">2</span><span class="cl">2. Target model 對「prefix + 這 K 個 token」並行驗證
</span></span><span class="line"><span class="ln">3</span><span class="cl">3. 從前往後：
</span></span><span class="line"><span class="ln">4</span><span class="cl">   - drafter token i 跟 target 第 i 個位置 sampling 一致 → 接受
</span></span><span class="line"><span class="ln">5</span><span class="cl">   - 第一個不一致 → 接受到此為止、用 target 的 token 取代第一個不一致
</span></span><span class="line"><span class="ln">6</span><span class="cl">4. 若全 K 個都接受、target 再 sample 一個 bonus token</span></span></code></pre></div><p>Acceptance rate 影響：</p>
<table>
  <thead>
      <tr>
          <th>場景</th>
          <th>Acceptance rate</th>
          <th>實際加速</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>Drafter 跟 target 高度同分佈</td>
          <td>0.8 ~ 0.95</td>
          <td>接近 K 倍上限</td>
      </tr>
      <tr>
          <td>Drafter / target 一般搭配</td>
          <td>0.5 ~ 0.7</td>
          <td>約 1.5 ~ 2× 加速</td>
      </tr>
      <tr>
          <td>Drafter 訓練分佈差很多</td>
          <td>0.2 ~ 0.4</td>
          <td>接近 1×（甚至更慢）</td>
      </tr>
      <tr>
          <td>Drafter / target tokenizer 不一致</td>
          <td>不能用</td>
          <td>概念不成立</td>
      </tr>
  </tbody>
</table>
<h2 id="影響-acceptance-rate-的因素">影響 acceptance rate 的因素</h2>
<ol>
<li><strong>Drafter / target 同 family</strong>：同訓練分佈、acceptance rate 高（如 Gemma 4 31B + Gemma 4 E4B）</li>
<li><strong>任務難度</strong>：簡單任務（boilerplate、常見 pattern）drafter 容易猜對；困難任務（reasoning、罕見領域）acceptance rate 降</li>
<li><strong>Sampling temperature</strong>：高 temperature 兩邊 sample 分佈都拉平、隨機性增加、acceptance rate 降；T=0（greedy）acceptance rate 最高</li>
<li><strong>K 設太大</strong>：drafter 越往後預測、累積誤差越大、後半段 token acceptance rate 急降；K 通常設 3-5 為甜蜜點</li>
</ol>
<h2 id="設計責任">設計責任</h2>
<p>讀 speculative decoding 設定 / model card 看到「draft acceptance」「acceptance length」就是這指標。寫 code 場景的判讀：</p>
<ol>
<li><strong>挑 drafter 看 family + 大小</strong>：drafter 跟 target 同 family（如 Gemma 4 31B + Gemma 4 E4B、Qwen3-30B + Qwen3-1.5B）是 acceptance rate 最高的組合</li>
<li><strong><code>llama-bench</code> 量實際加速比理論 K 倍重要</strong>：理論加速 = K × acceptance rate、實測才知道 drafter 在自己工作流的真實表現</li>
<li><strong>太低的 acceptance rate 是訊號</strong>：&lt; 0.3 通常表示 drafter / target 不匹配、值得換 drafter；&lt; 0.5 表示甜蜜點以下、可調 K 或 sampling 設定</li>
<li><strong>MTP（Multi-Token Prediction）</strong>：把 drafter 改成 target 內建多預測 head、acceptance rate 通常更高（因為 head 跟 target 完全同分佈）</li>
</ol>
]]></content:encoded></item><item><title>Activation Function</title><link>https://tarrragon.github.io/blog/llm/knowledge-cards/activation-function/</link><pubDate>Tue, 12 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/llm/knowledge-cards/activation-function/</guid><description>&lt;p>Activation function（激活函數）的核心概念是「在 linear layer（矩陣乘法）之間插入的非線性函數」。沒有 activation function、整個多層神經網路會塌縮成單一個線性變換、表達能力跟單層 linear 一樣弱。activation function 讓深度網路真的「深」起來。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>LLM 中 activation function 主要出現在 &lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/ffn/" data-link-title="FFN（Feed-Forward Network）" data-link-desc="Transformer block 內部的兩層 linear &amp;#43; activation、佔模型參數量的多數">FFN&lt;/a> 內、夾在兩個矩陣乘法之間：&lt;/p>





&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-text" data-lang="text">&lt;span class="line">&lt;span class="ln">1&lt;/span>&lt;span class="cl">FFN: input → W_up (linear) → activation → W_down (linear) → output
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">2&lt;/span>&lt;span class="cl"> ↑
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">3&lt;/span>&lt;span class="cl"> 這裡是 activation function&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>主流 LLM 用的 activation function 演化：&lt;/p>
&lt;table>
 &lt;thead>
 &lt;tr>
 &lt;th>Activation&lt;/th>
 &lt;th>公式（簡化）&lt;/th>
 &lt;th>出現在&lt;/th>
 &lt;/tr>
 &lt;/thead>
 &lt;tbody>
 &lt;tr>
 &lt;td>ReLU&lt;/td>
 &lt;td>&lt;code>max(0, x)&lt;/code>&lt;/td>
 &lt;td>早期 Transformer（如 BERT）&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>GELU&lt;/td>
 &lt;td>&lt;code>x · Φ(x)&lt;/code>（Φ 是 Gaussian CDF）&lt;/td>
 &lt;td>GPT-2 / 3、BERT 後期&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>SwiGLU&lt;/td>
 &lt;td>&lt;code>Swish(xW) ⊙ (xV)&lt;/code>&lt;/td>
 &lt;td>Llama、Gemma、Qwen 等主流&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>GeGLU&lt;/td>
 &lt;td>&lt;code>GELU(xW) ⊙ (xV)&lt;/code>&lt;/td>
 &lt;td>部分 Google 系列模型&lt;/td>
 &lt;/tr>
 &lt;/tbody>
&lt;/table>
&lt;p>SwiGLU / GeGLU 是「gated」變體、用兩條線性投影相乘、表達能力比單一 activation 強、是現代 LLM 主流。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>讀 paper / model card 看到 SwiGLU、ReLU、GELU 等詞、知道它們是 FFN 內部的選擇、影響模型表達能力跟訓練穩定性、不影響「模型怎麼用 / 怎麼 inference」這類使用者面議題。寫 code 場景的判讀：模型用什麼 activation 由模型作者決定、使用者通常不用調；但若要 fine-tune 或自己訓模型、activation 選擇是設計決策之一。&lt;/p></description><content:encoded><![CDATA[<p>Activation function（激活函數）的核心概念是「在 linear layer（矩陣乘法）之間插入的非線性函數」。沒有 activation function、整個多層神經網路會塌縮成單一個線性變換、表達能力跟單層 linear 一樣弱。activation function 讓深度網路真的「深」起來。</p>
<h2 id="概念位置">概念位置</h2>
<p>LLM 中 activation function 主要出現在 <a href="/blog/llm/knowledge-cards/ffn/" data-link-title="FFN（Feed-Forward Network）" data-link-desc="Transformer block 內部的兩層 linear &#43; activation、佔模型參數量的多數">FFN</a> 內、夾在兩個矩陣乘法之間：</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="ln">1</span><span class="cl">FFN: input → W_up (linear) → activation → W_down (linear) → output
</span></span><span class="line"><span class="ln">2</span><span class="cl">                              ↑
</span></span><span class="line"><span class="ln">3</span><span class="cl">                       這裡是 activation function</span></span></code></pre></div><p>主流 LLM 用的 activation function 演化：</p>
<table>
  <thead>
      <tr>
          <th>Activation</th>
          <th>公式（簡化）</th>
          <th>出現在</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>ReLU</td>
          <td><code>max(0, x)</code></td>
          <td>早期 Transformer（如 BERT）</td>
      </tr>
      <tr>
          <td>GELU</td>
          <td><code>x · Φ(x)</code>（Φ 是 Gaussian CDF）</td>
          <td>GPT-2 / 3、BERT 後期</td>
      </tr>
      <tr>
          <td>SwiGLU</td>
          <td><code>Swish(xW) ⊙ (xV)</code></td>
          <td>Llama、Gemma、Qwen 等主流</td>
      </tr>
      <tr>
          <td>GeGLU</td>
          <td><code>GELU(xW) ⊙ (xV)</code></td>
          <td>部分 Google 系列模型</td>
      </tr>
  </tbody>
</table>
<p>SwiGLU / GeGLU 是「gated」變體、用兩條線性投影相乘、表達能力比單一 activation 強、是現代 LLM 主流。</p>
<h2 id="設計責任">設計責任</h2>
<p>讀 paper / model card 看到 SwiGLU、ReLU、GELU 等詞、知道它們是 FFN 內部的選擇、影響模型表達能力跟訓練穩定性、不影響「模型怎麼用 / 怎麼 inference」這類使用者面議題。寫 code 場景的判讀：模型用什麼 activation 由模型作者決定、使用者通常不用調；但若要 fine-tune 或自己訓模型、activation 選擇是設計決策之一。</p>
]]></content:encoded></item><item><title>Active Parameter</title><link>https://tarrragon.github.io/blog/llm/knowledge-cards/active-parameter/</link><pubDate>Tue, 12 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/llm/knowledge-cards/active-parameter/</guid><description>&lt;p>Active parameter 的核心概念是「&lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/moe/" data-link-title="Mixture of Experts (MoE)" data-link-desc="把 transformer 的 FFN 層拆成多個專家、每 token 只啟用少數、總參數大但每 token 計算量小的架構">MoE&lt;/a> 模型每生成一個 token 實際參與 forward pass 的參數量」。跟模型總參數量是兩個獨立指標：&lt;strong>總參數&lt;/strong>影響記憶體需求（要全部載入）、&lt;strong>active parameter&lt;/strong> 影響推論速度上限（每 token 走的計算量）。Dense 模型的 active parameter 等於總參數；MoE 模型的 active parameter 通常只有總參數的 10% ~ 20%。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>模型命名中的 active parameter 線索：&lt;/p>
&lt;table>
 &lt;thead>
 &lt;tr>
 &lt;th>命名範例&lt;/th>
 &lt;th>解讀&lt;/th>
 &lt;/tr>
 &lt;/thead>
 &lt;tbody>
 &lt;tr>
 &lt;td>&lt;code>Qwen3-30B-A3B&lt;/code>&lt;/td>
 &lt;td>30B 總參數、A3B 表示 active 約 3B&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;code>Mixtral-8x7B&lt;/code>&lt;/td>
 &lt;td>8 個 7B expert、每 token top-2 啟用 ≈ 14B active（含 shared）&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;code>Llama-3.3-70B&lt;/code>&lt;/td>
 &lt;td>Dense、active = total = 70B&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;code>DeepSeek-V3&lt;/code>&lt;/td>
 &lt;td>671B 總參數、active 約 37B（依官方文件）&lt;/td>
 &lt;/tr>
 &lt;/tbody>
&lt;/table>
&lt;p>模型在不同維度的影響：&lt;/p>
&lt;table>
 &lt;thead>
 &lt;tr>
 &lt;th>維度&lt;/th>
 &lt;th>受影響因素&lt;/th>
 &lt;/tr>
 &lt;/thead>
 &lt;tbody>
 &lt;tr>
 &lt;td>記憶體需求&lt;/td>
 &lt;td>總參數 × 每權重 bytes&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>生字速度上限&lt;/td>
 &lt;td>active parameter × 每 token 讀取量 / &lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/memory-bandwidth/" data-link-title="Memory Bandwidth" data-link-desc="記憶體每秒能讀寫多少 bytes：決定本地 LLM 生字速度的真正瓶頸">memory bandwidth&lt;/a>&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>模型能力（社群常見回報）&lt;/td>
 &lt;td>較強相關於總參數、但 active parameter 是底線&lt;/td>
 &lt;/tr>
 &lt;/tbody>
&lt;/table>
&lt;blockquote>
&lt;p>&lt;strong>事實查核註&lt;/strong>：active parameter 跟模型能力的關係是社群常見回報、不是嚴格定理；具體模型在 coding / reasoning / 對話等任務的表現依訓練資料、RLHF、prompt 風格變化、需以 &lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/swe-bench/" data-link-title="SWE-bench" data-link-desc="用真實 GitHub issue 量化 LLM coding 能力的 benchmark">SWE-bench&lt;/a> 等公開 benchmark 跟自己工作流校準。&lt;/p>&lt;/blockquote>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>理解 active parameter 後可以解釋兩個現象：為什麼 30B MoE 跟 30B Dense 在同硬體下生字速度差很多（前者每 token 只走 3B active）、為什麼 MoE 模型能力對應的「等價 Dense 大小」不是簡單線性（社群常見回報接近總參數的 60% ~ 80% 等價 Dense 能力、但 case-by-case）。&lt;/p>
&lt;p>選 MoE 模型時、active parameter 是速度判讀軸、總參數是記憶體判讀軸、能力判讀靠自己工作流的 benchmark；不要直接拿「30B」跟 Dense 30B 作能力對等。&lt;/p></description><content:encoded><![CDATA[<p>Active parameter 的核心概念是「<a href="/blog/llm/knowledge-cards/moe/" data-link-title="Mixture of Experts (MoE)" data-link-desc="把 transformer 的 FFN 層拆成多個專家、每 token 只啟用少數、總參數大但每 token 計算量小的架構">MoE</a> 模型每生成一個 token 實際參與 forward pass 的參數量」。跟模型總參數量是兩個獨立指標：<strong>總參數</strong>影響記憶體需求（要全部載入）、<strong>active parameter</strong> 影響推論速度上限（每 token 走的計算量）。Dense 模型的 active parameter 等於總參數；MoE 模型的 active parameter 通常只有總參數的 10% ~ 20%。</p>
<h2 id="概念位置">概念位置</h2>
<p>模型命名中的 active parameter 線索：</p>
<table>
  <thead>
      <tr>
          <th>命名範例</th>
          <th>解讀</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td><code>Qwen3-30B-A3B</code></td>
          <td>30B 總參數、A3B 表示 active 約 3B</td>
      </tr>
      <tr>
          <td><code>Mixtral-8x7B</code></td>
          <td>8 個 7B expert、每 token top-2 啟用 ≈ 14B active（含 shared）</td>
      </tr>
      <tr>
          <td><code>Llama-3.3-70B</code></td>
          <td>Dense、active = total = 70B</td>
      </tr>
      <tr>
          <td><code>DeepSeek-V3</code></td>
          <td>671B 總參數、active 約 37B（依官方文件）</td>
      </tr>
  </tbody>
</table>
<p>模型在不同維度的影響：</p>
<table>
  <thead>
      <tr>
          <th>維度</th>
          <th>受影響因素</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>記憶體需求</td>
          <td>總參數 × 每權重 bytes</td>
      </tr>
      <tr>
          <td>生字速度上限</td>
          <td>active parameter × 每 token 讀取量 / <a href="/blog/llm/knowledge-cards/memory-bandwidth/" data-link-title="Memory Bandwidth" data-link-desc="記憶體每秒能讀寫多少 bytes：決定本地 LLM 生字速度的真正瓶頸">memory bandwidth</a></td>
      </tr>
      <tr>
          <td>模型能力（社群常見回報）</td>
          <td>較強相關於總參數、但 active parameter 是底線</td>
      </tr>
  </tbody>
</table>
<blockquote>
<p><strong>事實查核註</strong>：active parameter 跟模型能力的關係是社群常見回報、不是嚴格定理；具體模型在 coding / reasoning / 對話等任務的表現依訓練資料、RLHF、prompt 風格變化、需以 <a href="/blog/llm/knowledge-cards/swe-bench/" data-link-title="SWE-bench" data-link-desc="用真實 GitHub issue 量化 LLM coding 能力的 benchmark">SWE-bench</a> 等公開 benchmark 跟自己工作流校準。</p></blockquote>
<h2 id="設計責任">設計責任</h2>
<p>理解 active parameter 後可以解釋兩個現象：為什麼 30B MoE 跟 30B Dense 在同硬體下生字速度差很多（前者每 token 只走 3B active）、為什麼 MoE 模型能力對應的「等價 Dense 大小」不是簡單線性（社群常見回報接近總參數的 60% ~ 80% 等價 Dense 能力、但 case-by-case）。</p>
<p>選 MoE 模型時、active parameter 是速度判讀軸、總參數是記憶體判讀軸、能力判讀靠自己工作流的 benchmark；不要直接拿「30B」跟 Dense 30B 作能力對等。</p>
]]></content:encoded></item><item><title>Adam / AdamW</title><link>https://tarrragon.github.io/blog/llm/knowledge-cards/adam-adamw/</link><pubDate>Tue, 12 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/llm/knowledge-cards/adam-adamw/</guid><description>&lt;p>Adam（Adaptive Moment Estimation、Kingma &amp;amp; Ba, 2014）的核心概念是「&lt;strong>對每個參數維護兩個 EMA&lt;/strong>（gradient 的一階矩 = 平均、二階矩 = 變異）、用這兩個值自適應地縮放每個參數的更新步長」。AdamW（Loshchilov &amp;amp; Hutter, 2017）是 Adam 加上「decoupled weight decay」的修正版、是現代 LLM 訓練的標準 optimizer。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>Adam 更新規則（簡化）：&lt;/p>





&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-text" data-lang="text">&lt;span class="line">&lt;span class="ln">1&lt;/span>&lt;span class="cl">m_t = β₁ × m_{t-1} + (1 - β₁) × g_t ← gradient 的 EMA（一階矩、方向）
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">2&lt;/span>&lt;span class="cl">v_t = β₂ × v_{t-1} + (1 - β₂) × g_t² ← gradient² 的 EMA（二階矩、變動率）
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">3&lt;/span>&lt;span class="cl">W -= lr × m_t / (sqrt(v_t) + ε)
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">4&lt;/span>&lt;span class="cl"> └──────┬──────┘
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">5&lt;/span>&lt;span class="cl"> 每個參數獨立縮放
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">6&lt;/span>&lt;span class="cl"> 經常變動的方向減小步長、穩定方向加大&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>跟其他 optimizer 對比：&lt;/p>
&lt;table>
 &lt;thead>
 &lt;tr>
 &lt;th>對比&lt;/th>
 &lt;th>&lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/sgd/" data-link-title="SGD" data-link-desc="Stochastic Gradient Descent：每次用 mini-batch 算 gradient 更新權重的基礎 optimizer">SGD&lt;/a>&lt;/th>
 &lt;th>SGD + Momentum&lt;/th>
 &lt;th>Adam&lt;/th>
 &lt;th>AdamW&lt;/th>
 &lt;/tr>
 &lt;/thead>
 &lt;tbody>
 &lt;tr>
 &lt;td>每參數自適應&lt;/td>
 &lt;td>否&lt;/td>
 &lt;td>否&lt;/td>
 &lt;td>是&lt;/td>
 &lt;td>是&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>記憶體開銷&lt;/td>
 &lt;td>1× W（就 gradient）&lt;/td>
 &lt;td>2× W&lt;/td>
 &lt;td>3× W&lt;/td>
 &lt;td>3× W&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>Hyperparameter&lt;/td>
 &lt;td>lr&lt;/td>
 &lt;td>lr + μ&lt;/td>
 &lt;td>lr + β₁、β₂&lt;/td>
 &lt;td>lr + β₁、β₂ + weight_decay&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>LLM 訓練主流&lt;/td>
 &lt;td>否&lt;/td>
 &lt;td>否&lt;/td>
 &lt;td>早期&lt;/td>
 &lt;td>現在主流&lt;/td>
 &lt;/tr>
 &lt;/tbody>
&lt;/table>
&lt;p>關鍵：AdamW 對 weight decay 跟 lr 解耦、修正了 Adam 在「lr × weight_decay」交互上的 bug、是 GPT、Llama、Gemma 等系列訓練的標配。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>讀 LLM training paper / config 看到 &lt;code>optimizer: AdamW&lt;/code>、&lt;code>betas: [0.9, 0.95]&lt;/code>、&lt;code>weight_decay: 0.1&lt;/code> 等就是這個 optimizer 的標準設定。記憶體佔用 = 模型權重 × 3（model + m + v）、加上 &lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/backpropagation/" data-link-title="Backpropagation" data-link-desc="從 output loss 反向遞推、用 chain rule 算出每個權重的 gradient 的演算法">backpropagation&lt;/a> 的 activation、是訓練 vs 推論記憶體差距的主要來源。&lt;/p></description><content:encoded><![CDATA[<p>Adam（Adaptive Moment Estimation、Kingma &amp; Ba, 2014）的核心概念是「<strong>對每個參數維護兩個 EMA</strong>（gradient 的一階矩 = 平均、二階矩 = 變異）、用這兩個值自適應地縮放每個參數的更新步長」。AdamW（Loshchilov &amp; Hutter, 2017）是 Adam 加上「decoupled weight decay」的修正版、是現代 LLM 訓練的標準 optimizer。</p>
<h2 id="概念位置">概念位置</h2>
<p>Adam 更新規則（簡化）：</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="ln">1</span><span class="cl">m_t = β₁ × m_{t-1} + (1 - β₁) × g_t      ← gradient 的 EMA（一階矩、方向）
</span></span><span class="line"><span class="ln">2</span><span class="cl">v_t = β₂ × v_{t-1} + (1 - β₂) × g_t²     ← gradient² 的 EMA（二階矩、變動率）
</span></span><span class="line"><span class="ln">3</span><span class="cl">W -= lr × m_t / (sqrt(v_t) + ε)
</span></span><span class="line"><span class="ln">4</span><span class="cl">            └──────┬──────┘
</span></span><span class="line"><span class="ln">5</span><span class="cl">        每個參數獨立縮放
</span></span><span class="line"><span class="ln">6</span><span class="cl">        經常變動的方向減小步長、穩定方向加大</span></span></code></pre></div><p>跟其他 optimizer 對比：</p>
<table>
  <thead>
      <tr>
          <th>對比</th>
          <th><a href="/blog/llm/knowledge-cards/sgd/" data-link-title="SGD" data-link-desc="Stochastic Gradient Descent：每次用 mini-batch 算 gradient 更新權重的基礎 optimizer">SGD</a></th>
          <th>SGD + Momentum</th>
          <th>Adam</th>
          <th>AdamW</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>每參數自適應</td>
          <td>否</td>
          <td>否</td>
          <td>是</td>
          <td>是</td>
      </tr>
      <tr>
          <td>記憶體開銷</td>
          <td>1× W（就 gradient）</td>
          <td>2× W</td>
          <td>3× W</td>
          <td>3× W</td>
      </tr>
      <tr>
          <td>Hyperparameter</td>
          <td>lr</td>
          <td>lr + μ</td>
          <td>lr + β₁、β₂</td>
          <td>lr + β₁、β₂ + weight_decay</td>
      </tr>
      <tr>
          <td>LLM 訓練主流</td>
          <td>否</td>
          <td>否</td>
          <td>早期</td>
          <td>現在主流</td>
      </tr>
  </tbody>
</table>
<p>關鍵：AdamW 對 weight decay 跟 lr 解耦、修正了 Adam 在「lr × weight_decay」交互上的 bug、是 GPT、Llama、Gemma 等系列訓練的標配。</p>
<h2 id="設計責任">設計責任</h2>
<p>讀 LLM training paper / config 看到 <code>optimizer: AdamW</code>、<code>betas: [0.9, 0.95]</code>、<code>weight_decay: 0.1</code> 等就是這個 optimizer 的標準設定。記憶體佔用 = 模型權重 × 3（model + m + v）、加上 <a href="/blog/llm/knowledge-cards/backpropagation/" data-link-title="Backpropagation" data-link-desc="從 output loss 反向遞推、用 chain rule 算出每個權重的 gradient 的演算法">backpropagation</a> 的 activation、是訓練 vs 推論記憶體差距的主要來源。</p>
]]></content:encoded></item><item><title>Agent Loop</title><link>https://tarrragon.github.io/blog/llm/knowledge-cards/agent-loop/</link><pubDate>Tue, 12 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/llm/knowledge-cards/agent-loop/</guid><description>&lt;p>Agent loop 的核心概念是「LLM 在 plan → act → observe → plan 的循環中推進任務、直到任務完成或停止條件觸發」，有別於一次性回答。它讓 LLM 從「單回合工具呼叫」進化成「自主執行多步驟工作」、但同時放大 &lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/prompt-injection/" data-link-title="Prompt Injection" data-link-desc="把惡意指令藏進 LLM 會讀到的內容、誘導 LLM 跑出非開發者預期行為的攻擊類別、OWASP LLM01 列入頭號威脅">prompt injection&lt;/a> 的影響面跟 &lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/tool-use/" data-link-title="Tool Use" data-link-desc="LLM 透過結構化呼叫外部工具（讀檔、查資料庫、發 API request）來擴展能力的設計、function calling 跟 MCP 是常見實作">tool use&lt;/a> 副作用範圍。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>典型的 agent loop 流程：&lt;/p>





&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-text" data-lang="text">&lt;span class="line">&lt;span class="ln">1&lt;/span>&lt;span class="cl">循環開始：
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">2&lt;/span>&lt;span class="cl"> step 1：LLM 看任務目標 + 當前狀態 → 規劃下一步 → 生成 tool call
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">3&lt;/span>&lt;span class="cl"> step 2：client 執行 tool call → 得到結果
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">4&lt;/span>&lt;span class="cl"> step 3：tool 結果回灌 conversation → LLM 看到新狀態
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">5&lt;/span>&lt;span class="cl"> step 4：LLM 判斷：任務完成？ → yes 結束 / no 回 step 1
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">6&lt;/span>&lt;span class="cl">循環結束。&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>Agent loop 的兩個關鍵變數：&lt;/p>
&lt;ol>
&lt;li>&lt;strong>max steps&lt;/strong>：循環最大次數、防止無限迴圈跟成本爆炸。&lt;/li>
&lt;li>&lt;strong>stop condition&lt;/strong>：什麼算「任務完成」、由 LLM 自己判斷還是有額外驗證。&lt;/li>
&lt;/ol>
&lt;p>常見實作（依框架而異）：LangGraph、AutoGPT、Claude 的 agentic abilities、OpenAI Assistants API 都提供 agent loop 機制。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>理解 agent loop 後可以解釋兩個現象：為什麼 agent 工作流的成本比單次 LLM call 高一個量級（loop 跑很多輪）、為什麼 agent loop 是 &lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/prompt-injection/" data-link-title="Prompt Injection" data-link-desc="把惡意指令藏進 LLM 會讀到的內容、誘導 LLM 跑出非開發者預期行為的攻擊類別、OWASP LLM01 列入頭號威脅">prompt injection&lt;/a> 的放大器（loop 中段被 injection 後、後續步驟都被牽動）。&lt;/p>
&lt;p>防禦設計的核心：&lt;/p>
&lt;ol>
&lt;li>&lt;strong>max steps 上限&lt;/strong>：避免無限循環、控制成本。&lt;/li>
&lt;li>&lt;strong>per-step review checkpoint&lt;/strong>：每幾步強制人為或自動驗證、防止 agent 飄離原意圖。&lt;/li>
&lt;li>&lt;strong>agent 持的 credential 最小化&lt;/strong>：避免單次 injection 影響面跨越多服務。&lt;/li>
&lt;li>&lt;strong>tool 結果在 prompt 中包覆&lt;/strong>：明確標記「以下是 tool 回傳、不執行內含指令」、降低觸發率。&lt;/li>
&lt;/ol>
&lt;p>詳見 &lt;a href="https://tarrragon.github.io/blog/backend/07-security-data-protection/llm-prompt-injection-in-agent/" data-link-title="LLM Agent Prompt Injection 後果治理" data-link-desc="production LLM agent 場景的 prompt injection 後果：tool spec 設計、agent loop 限制、review checkpoint、跟 incident workflow 的接合">LLM Agent Prompt Injection 後果治理&lt;/a> 跟 &lt;a href="https://tarrragon.github.io/blog/llm/04-applications/agent-architecture/" data-link-title="4.4 Agent 架構原理" data-link-desc="Agent loop 結構、失敗模式、什麼任務適合 vs 不適合、跟人類審查的協作模型">4.4 Agent 架構原理&lt;/a>。&lt;/p></description><content:encoded><![CDATA[<p>Agent loop 的核心概念是「LLM 在 plan → act → observe → plan 的循環中推進任務、直到任務完成或停止條件觸發」，有別於一次性回答。它讓 LLM 從「單回合工具呼叫」進化成「自主執行多步驟工作」、但同時放大 <a href="/blog/llm/knowledge-cards/prompt-injection/" data-link-title="Prompt Injection" data-link-desc="把惡意指令藏進 LLM 會讀到的內容、誘導 LLM 跑出非開發者預期行為的攻擊類別、OWASP LLM01 列入頭號威脅">prompt injection</a> 的影響面跟 <a href="/blog/llm/knowledge-cards/tool-use/" data-link-title="Tool Use" data-link-desc="LLM 透過結構化呼叫外部工具（讀檔、查資料庫、發 API request）來擴展能力的設計、function calling 跟 MCP 是常見實作">tool use</a> 副作用範圍。</p>
<h2 id="概念位置">概念位置</h2>
<p>典型的 agent loop 流程：</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="ln">1</span><span class="cl">循環開始：
</span></span><span class="line"><span class="ln">2</span><span class="cl">  step 1：LLM 看任務目標 + 當前狀態 → 規劃下一步 → 生成 tool call
</span></span><span class="line"><span class="ln">3</span><span class="cl">  step 2：client 執行 tool call → 得到結果
</span></span><span class="line"><span class="ln">4</span><span class="cl">  step 3：tool 結果回灌 conversation → LLM 看到新狀態
</span></span><span class="line"><span class="ln">5</span><span class="cl">  step 4：LLM 判斷：任務完成？ → yes 結束 / no 回 step 1
</span></span><span class="line"><span class="ln">6</span><span class="cl">循環結束。</span></span></code></pre></div><p>Agent loop 的兩個關鍵變數：</p>
<ol>
<li><strong>max steps</strong>：循環最大次數、防止無限迴圈跟成本爆炸。</li>
<li><strong>stop condition</strong>：什麼算「任務完成」、由 LLM 自己判斷還是有額外驗證。</li>
</ol>
<p>常見實作（依框架而異）：LangGraph、AutoGPT、Claude 的 agentic abilities、OpenAI Assistants API 都提供 agent loop 機制。</p>
<h2 id="設計責任">設計責任</h2>
<p>理解 agent loop 後可以解釋兩個現象：為什麼 agent 工作流的成本比單次 LLM call 高一個量級（loop 跑很多輪）、為什麼 agent loop 是 <a href="/blog/llm/knowledge-cards/prompt-injection/" data-link-title="Prompt Injection" data-link-desc="把惡意指令藏進 LLM 會讀到的內容、誘導 LLM 跑出非開發者預期行為的攻擊類別、OWASP LLM01 列入頭號威脅">prompt injection</a> 的放大器（loop 中段被 injection 後、後續步驟都被牽動）。</p>
<p>防禦設計的核心：</p>
<ol>
<li><strong>max steps 上限</strong>：避免無限循環、控制成本。</li>
<li><strong>per-step review checkpoint</strong>：每幾步強制人為或自動驗證、防止 agent 飄離原意圖。</li>
<li><strong>agent 持的 credential 最小化</strong>：避免單次 injection 影響面跨越多服務。</li>
<li><strong>tool 結果在 prompt 中包覆</strong>：明確標記「以下是 tool 回傳、不執行內含指令」、降低觸發率。</li>
</ol>
<p>詳見 <a href="/blog/backend/07-security-data-protection/llm-prompt-injection-in-agent/" data-link-title="LLM Agent Prompt Injection 後果治理" data-link-desc="production LLM agent 場景的 prompt injection 後果：tool spec 設計、agent loop 限制、review checkpoint、跟 incident workflow 的接合">LLM Agent Prompt Injection 後果治理</a> 跟 <a href="/blog/llm/04-applications/agent-architecture/" data-link-title="4.4 Agent 架構原理" data-link-desc="Agent loop 結構、失敗模式、什麼任務適合 vs 不適合、跟人類審查的協作模型">4.4 Agent 架構原理</a>。</p>
]]></content:encoded></item><item><title>Agent Memory</title><link>https://tarrragon.github.io/blog/llm/knowledge-cards/agent-memory/</link><pubDate>Tue, 12 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/llm/knowledge-cards/agent-memory/</guid><description>&lt;p>Agent memory 的核心概念是「&lt;strong>agent 在 &lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/context-window/" data-link-title="Context Window" data-link-desc="模型一次能處理的最大 token 數量：prompt 加生成的總和上限">context window&lt;/a> 之外管理長期狀態的設計&lt;/strong>」、把使用者偏好、過去任務、知識、操作流程等持久化、跨 session 重用。借鑒人類認知科學的五個層次：working memory（context 本身）、short-term（session scratchpad）、long-term episodic（過去事件）、long-term semantic（事實 / 知識）、long-term procedural（流程 / 技能）。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>五個層次的對比：&lt;/p>
&lt;table>
 &lt;thead>
 &lt;tr>
 &lt;th>層&lt;/th>
 &lt;th>範圍&lt;/th>
 &lt;th>存放位置&lt;/th>
 &lt;th>典型內容&lt;/th>
 &lt;/tr>
 &lt;/thead>
 &lt;tbody>
 &lt;tr>
 &lt;td>Working memory&lt;/td>
 &lt;td>當前 query / forward pass&lt;/td>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/context-window/" data-link-title="Context Window" data-link-desc="模型一次能處理的最大 token 數量：prompt 加生成的總和上限">Context window&lt;/a> 本身&lt;/td>
 &lt;td>當下對話、tool result、reasoning trace&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>Short-term / session memory&lt;/td>
 &lt;td>單一 session（小時級）&lt;/td>
 &lt;td>Scratchpad 物件 / &lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/prompt-cache/" data-link-title="Prompt Cache" data-link-desc="重複出現的 prompt prefix 在推論伺服器或 LLM 服務端被 cache、後續 query 跳過 prefill、大幅降 cost 跟 TTFT">prompt cache&lt;/a>&lt;/td>
 &lt;td>Session 內累積的中間結果、用過的策略&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>Long-term episodic memory&lt;/td>
 &lt;td>跨 session（永久）&lt;/td>
 &lt;td>DB / vector store / file system&lt;/td>
 &lt;td>「上週 alice 問過 X」「上個 sprint 解過 Y bug」&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>Long-term semantic memory&lt;/td>
 &lt;td>跨 session（永久）&lt;/td>
 &lt;td>DB / vector store / KG&lt;/td>
 &lt;td>「user 偏好 markdown 輸出」「專案用 React 18」「Python 3.11」&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>Long-term procedural memory&lt;/td>
 &lt;td>跨 session（永久）&lt;/td>
 &lt;td>Skill registry / playbook&lt;/td>
 &lt;td>「跑測試前先 npm install」「commit 前要 lint」&lt;/td>
 &lt;/tr>
 &lt;/tbody>
&lt;/table>
&lt;p>跟其他相關概念的關係：&lt;/p>
&lt;table>
 &lt;thead>
 &lt;tr>
 &lt;th>概念&lt;/th>
 &lt;th>跟 agent memory 的關係&lt;/th>
 &lt;/tr>
 &lt;/thead>
 &lt;tbody>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/rag/" data-link-title="RAG" data-link-desc="Retrieval-Augmented Generation：動態外掛知識給 LLM、繞開模型參數記憶的靜態限制">RAG&lt;/a>&lt;/td>
 &lt;td>Long-term semantic memory 的常見實作（vector store retrieval）&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/context-window/" data-link-title="Context Window" data-link-desc="模型一次能處理的最大 token 數量：prompt 加生成的總和上限">Context window&lt;/a>&lt;/td>
 &lt;td>Working memory 的物理上限&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/system-prompt/" data-link-title="System Prompt" data-link-desc="LLM application 中由開發者預設、不直接顯示給使用者的指令層、定義模型的角色、行為規範、輸出格式">System prompt&lt;/a>&lt;/td>
 &lt;td>把 semantic / procedural memory 編碼進 scaffold 的方式&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/subagent/" data-link-title="Subagent" data-link-desc="Coding agent 中把特定責任拆給專門子 agent 的設計模式、各 subagent 有獨立 context、由 main agent 透過 handoff 調度">Subagent&lt;/a>&lt;/td>
 &lt;td>用 subagent 分隔不同 specialty 的 memory&lt;/td>
 &lt;/tr>
 &lt;/tbody>
&lt;/table>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>讀 agent paper / 設計 / framework docs 看到「agent memory」「memory store」「mem0 / Letta」「episodic / semantic memory」就是這 framing。寫 code 場景的判讀：&lt;/p></description><content:encoded><![CDATA[<p>Agent memory 的核心概念是「<strong>agent 在 <a href="/blog/llm/knowledge-cards/context-window/" data-link-title="Context Window" data-link-desc="模型一次能處理的最大 token 數量：prompt 加生成的總和上限">context window</a> 之外管理長期狀態的設計</strong>」、把使用者偏好、過去任務、知識、操作流程等持久化、跨 session 重用。借鑒人類認知科學的五個層次：working memory（context 本身）、short-term（session scratchpad）、long-term episodic（過去事件）、long-term semantic（事實 / 知識）、long-term procedural（流程 / 技能）。</p>
<h2 id="概念位置">概念位置</h2>
<p>五個層次的對比：</p>
<table>
  <thead>
      <tr>
          <th>層</th>
          <th>範圍</th>
          <th>存放位置</th>
          <th>典型內容</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>Working memory</td>
          <td>當前 query / forward pass</td>
          <td><a href="/blog/llm/knowledge-cards/context-window/" data-link-title="Context Window" data-link-desc="模型一次能處理的最大 token 數量：prompt 加生成的總和上限">Context window</a> 本身</td>
          <td>當下對話、tool result、reasoning trace</td>
      </tr>
      <tr>
          <td>Short-term / session memory</td>
          <td>單一 session（小時級）</td>
          <td>Scratchpad 物件 / <a href="/blog/llm/knowledge-cards/prompt-cache/" data-link-title="Prompt Cache" data-link-desc="重複出現的 prompt prefix 在推論伺服器或 LLM 服務端被 cache、後續 query 跳過 prefill、大幅降 cost 跟 TTFT">prompt cache</a></td>
          <td>Session 內累積的中間結果、用過的策略</td>
      </tr>
      <tr>
          <td>Long-term episodic memory</td>
          <td>跨 session（永久）</td>
          <td>DB / vector store / file system</td>
          <td>「上週 alice 問過 X」「上個 sprint 解過 Y bug」</td>
      </tr>
      <tr>
          <td>Long-term semantic memory</td>
          <td>跨 session（永久）</td>
          <td>DB / vector store / KG</td>
          <td>「user 偏好 markdown 輸出」「專案用 React 18」「Python 3.11」</td>
      </tr>
      <tr>
          <td>Long-term procedural memory</td>
          <td>跨 session（永久）</td>
          <td>Skill registry / playbook</td>
          <td>「跑測試前先 npm install」「commit 前要 lint」</td>
      </tr>
  </tbody>
</table>
<p>跟其他相關概念的關係：</p>
<table>
  <thead>
      <tr>
          <th>概念</th>
          <th>跟 agent memory 的關係</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td><a href="/blog/llm/knowledge-cards/rag/" data-link-title="RAG" data-link-desc="Retrieval-Augmented Generation：動態外掛知識給 LLM、繞開模型參數記憶的靜態限制">RAG</a></td>
          <td>Long-term semantic memory 的常見實作（vector store retrieval）</td>
      </tr>
      <tr>
          <td><a href="/blog/llm/knowledge-cards/context-window/" data-link-title="Context Window" data-link-desc="模型一次能處理的最大 token 數量：prompt 加生成的總和上限">Context window</a></td>
          <td>Working memory 的物理上限</td>
      </tr>
      <tr>
          <td><a href="/blog/llm/knowledge-cards/system-prompt/" data-link-title="System Prompt" data-link-desc="LLM application 中由開發者預設、不直接顯示給使用者的指令層、定義模型的角色、行為規範、輸出格式">System prompt</a></td>
          <td>把 semantic / procedural memory 編碼進 scaffold 的方式</td>
      </tr>
      <tr>
          <td><a href="/blog/llm/knowledge-cards/subagent/" data-link-title="Subagent" data-link-desc="Coding agent 中把特定責任拆給專門子 agent 的設計模式、各 subagent 有獨立 context、由 main agent 透過 handoff 調度">Subagent</a></td>
          <td>用 subagent 分隔不同 specialty 的 memory</td>
      </tr>
  </tbody>
</table>
<h2 id="設計責任">設計責任</h2>
<p>讀 agent paper / 設計 / framework docs 看到「agent memory」「memory store」「mem0 / Letta」「episodic / semantic memory」就是這 framing。寫 code 場景的判讀：</p>
<ol>
<li><strong>不是每個 agent 都需要五個層次都用</strong>：autocomplete 只要 working memory；對話 IDE assistant 多用 working + session；長期 coding agent 才需要 long-term</li>
<li><strong>Long-term memory 的兩條實作路線</strong>：(a) retrieval-on-demand（vector store + similarity search、見 <a href="/blog/llm/knowledge-cards/rag/" data-link-title="RAG" data-link-desc="Retrieval-Augmented Generation：動態外掛知識給 LLM、繞開模型參數記憶的靜態限制">RAG</a>）、(b) injection-on-startup（把關鍵 memory 編進 system prompt、適合小量穩定的 procedural）</li>
<li><strong>失敗模式</strong>：memory drift（舊 memory 過時但仍被 retrieve）、PII 寫入（user 不知情下被存）、context 污染（不相關 memory 被 inject 進 working）、跟 <a href="/blog/llm/knowledge-cards/hallucination/" data-link-title="Hallucination" data-link-desc="LLM 生成內容看起來合理但事實錯誤、引用不存在的來源、虛構不存在的 entity 的現象">hallucination</a> 互相 boost</li>
<li><strong>跟 <a href="/blog/llm/04-applications/agent-memory-architecture/" data-link-title="4.19 Agent memory 分層架構" data-link-desc="Agent 在 context window 之外管理長期狀態的設計：working / short-term / long-term episodic / semantic / procedural 五個層次、寫入時機、retrieval 設計、失敗模式">4.19 agent memory 章節</a> 的關係</strong>：本卡是分類定義、章節是工程實務（寫入時機、retrieval 設計、失敗模式緩解）</li>
</ol>
]]></content:encoded></item><item><title>Attention</title><link>https://tarrragon.github.io/blog/llm/knowledge-cards/attention/</link><pubDate>Tue, 12 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/llm/knowledge-cards/attention/</guid><description>&lt;p>Attention 的核心概念是「Transformer 中讓每個 token 對其他 token 加權平均、產生 context-aware 表示」的計算機制。具體運作是用 Query（Q）、Key（K）、Value（V）三組向量算 attention score、再用 softmax 把 score 變成權重、最後加權平均 V。這個機制是 &lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/kv-cache/" data-link-title="KV Cache" data-link-desc="已處理 token 的 attention 中間結果暫存：避免重算、加速後續生成">KV cache&lt;/a> 概念的源頭、也是 &lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/context-window/" data-link-title="Context Window" data-link-desc="模型一次能處理的最大 token 數量：prompt 加生成的總和上限">context window&lt;/a> 上限的計算瓶頸。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>Attention 在 &lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/transformer/" data-link-title="Transformer" data-link-desc="寫 code 用的 LLM 神經網路架構：基於 attention 機制、自回歸生成 token">Transformer&lt;/a> block 中的位置：&lt;/p>





&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-text" data-lang="text">&lt;span class="line">&lt;span class="ln">1&lt;/span>&lt;span class="cl">Transformer block：
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">2&lt;/span>&lt;span class="cl"> ├── Layer Norm
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">3&lt;/span>&lt;span class="cl"> ├── Attention（本卡聚焦）
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">4&lt;/span>&lt;span class="cl"> │ ├── Q · K^T → attention score
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">5&lt;/span>&lt;span class="cl"> │ ├── softmax → weight
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">6&lt;/span>&lt;span class="cl"> │ └── weight · V → output
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">7&lt;/span>&lt;span class="cl"> ├── Layer Norm
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">8&lt;/span>&lt;span class="cl"> └── FFN 層（或 MoE）&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>簡化的計算公式：&lt;/p>





&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-text" data-lang="text">&lt;span class="line">&lt;span class="ln">1&lt;/span>&lt;span class="cl">attention(Q, K, V) = softmax(Q · K^T / √d) · V&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>Attention 的常見變體（影響 KV cache 體積跟推論性能）：&lt;/p>
&lt;table>
 &lt;thead>
 &lt;tr>
 &lt;th>變體&lt;/th>
 &lt;th>描述&lt;/th>
 &lt;/tr>
 &lt;/thead>
 &lt;tbody>
 &lt;tr>
 &lt;td>MHA（Multi-Head Attention）&lt;/td>
 &lt;td>原始 Transformer 設計、每 head 獨立 Q / K / V&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>GQA（Grouped-Query Attention）&lt;/td>
 &lt;td>head group 共用 K / V、KV cache 體積減小、推論較快&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>MLA（Multi-head Latent Attention）&lt;/td>
 &lt;td>DeepSeek 提出、KV cache 壓縮更激進&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>Flash Attention&lt;/td>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/flash-attention/" data-link-title="Flash Attention" data-link-desc="Attention 計算的記憶體友善實作、減少 GPU memory 讀寫、提升長 context 推論吞吐">演算法層的優化實作&lt;/a>、跟變體獨立&lt;/td>
 &lt;/tr>
 &lt;/tbody>
&lt;/table>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>理解 attention 後可以解釋三個現象：為什麼 LLM 推論的記憶體用量隨 &lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/context-window/" data-link-title="Context Window" data-link-desc="模型一次能處理的最大 token 數量：prompt 加生成的總和上限">context&lt;/a> 長度線性增加（KV cache 是 attention 暫存）、為什麼 &lt;a href="https://tarrragon.github.io/blog/llm/05-discrete-gpu/kv-cache-quantization-strategy/" data-link-title="5.2 KV cache 量化策略" data-link-desc="PC 場景用 K=Q8 / V=Q4 等量化把 KV cache 壓縮、騰出 VRAM 開大 context window 或加併發數的判讀">KV cache 量化&lt;/a> 對品質影響有不對稱性（K 用於 score 比較、V 用於加權平均、誤差累積方式不同）、為什麼不同 attention 變體在同等模型大小下推論速度差異明顯（KV cache 體積跟卡間頻寬需求不同）。&lt;/p>
&lt;p>工程實務上、Attention 是 LLM 推論性能跟記憶體需求的最大來源、量化策略、context 上限、併發數設計都圍繞 attention 跟 KV cache 展開。&lt;/p></description><content:encoded><![CDATA[<p>Attention 的核心概念是「Transformer 中讓每個 token 對其他 token 加權平均、產生 context-aware 表示」的計算機制。具體運作是用 Query（Q）、Key（K）、Value（V）三組向量算 attention score、再用 softmax 把 score 變成權重、最後加權平均 V。這個機制是 <a href="/blog/llm/knowledge-cards/kv-cache/" data-link-title="KV Cache" data-link-desc="已處理 token 的 attention 中間結果暫存：避免重算、加速後續生成">KV cache</a> 概念的源頭、也是 <a href="/blog/llm/knowledge-cards/context-window/" data-link-title="Context Window" data-link-desc="模型一次能處理的最大 token 數量：prompt 加生成的總和上限">context window</a> 上限的計算瓶頸。</p>
<h2 id="概念位置">概念位置</h2>
<p>Attention 在 <a href="/blog/llm/knowledge-cards/transformer/" data-link-title="Transformer" data-link-desc="寫 code 用的 LLM 神經網路架構：基於 attention 機制、自回歸生成 token">Transformer</a> block 中的位置：</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="ln">1</span><span class="cl">Transformer block：
</span></span><span class="line"><span class="ln">2</span><span class="cl">  ├── Layer Norm
</span></span><span class="line"><span class="ln">3</span><span class="cl">  ├── Attention（本卡聚焦）
</span></span><span class="line"><span class="ln">4</span><span class="cl">  │     ├── Q · K^T → attention score
</span></span><span class="line"><span class="ln">5</span><span class="cl">  │     ├── softmax → weight
</span></span><span class="line"><span class="ln">6</span><span class="cl">  │     └── weight · V → output
</span></span><span class="line"><span class="ln">7</span><span class="cl">  ├── Layer Norm
</span></span><span class="line"><span class="ln">8</span><span class="cl">  └── FFN 層（或 MoE）</span></span></code></pre></div><p>簡化的計算公式：</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="ln">1</span><span class="cl">attention(Q, K, V) = softmax(Q · K^T / √d) · V</span></span></code></pre></div><p>Attention 的常見變體（影響 KV cache 體積跟推論性能）：</p>
<table>
  <thead>
      <tr>
          <th>變體</th>
          <th>描述</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>MHA（Multi-Head Attention）</td>
          <td>原始 Transformer 設計、每 head 獨立 Q / K / V</td>
      </tr>
      <tr>
          <td>GQA（Grouped-Query Attention）</td>
          <td>head group 共用 K / V、KV cache 體積減小、推論較快</td>
      </tr>
      <tr>
          <td>MLA（Multi-head Latent Attention）</td>
          <td>DeepSeek 提出、KV cache 壓縮更激進</td>
      </tr>
      <tr>
          <td>Flash Attention</td>
          <td><a href="/blog/llm/knowledge-cards/flash-attention/" data-link-title="Flash Attention" data-link-desc="Attention 計算的記憶體友善實作、減少 GPU memory 讀寫、提升長 context 推論吞吐">演算法層的優化實作</a>、跟變體獨立</td>
      </tr>
  </tbody>
</table>
<h2 id="設計責任">設計責任</h2>
<p>理解 attention 後可以解釋三個現象：為什麼 LLM 推論的記憶體用量隨 <a href="/blog/llm/knowledge-cards/context-window/" data-link-title="Context Window" data-link-desc="模型一次能處理的最大 token 數量：prompt 加生成的總和上限">context</a> 長度線性增加（KV cache 是 attention 暫存）、為什麼 <a href="/blog/llm/05-discrete-gpu/kv-cache-quantization-strategy/" data-link-title="5.2 KV cache 量化策略" data-link-desc="PC 場景用 K=Q8 / V=Q4 等量化把 KV cache 壓縮、騰出 VRAM 開大 context window 或加併發數的判讀">KV cache 量化</a> 對品質影響有不對稱性（K 用於 score 比較、V 用於加權平均、誤差累積方式不同）、為什麼不同 attention 變體在同等模型大小下推論速度差異明顯（KV cache 體積跟卡間頻寬需求不同）。</p>
<p>工程實務上、Attention 是 LLM 推論性能跟記憶體需求的最大來源、量化策略、context 上限、併發數設計都圍繞 attention 跟 KV cache 展開。</p>
]]></content:encoded></item><item><title>Backpropagation</title><link>https://tarrragon.github.io/blog/llm/knowledge-cards/backpropagation/</link><pubDate>Tue, 12 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/llm/knowledge-cards/backpropagation/</guid><description>&lt;p>Backpropagation（反向傳播）的核心概念是「從輸出端的 loss 開始、用 chain rule 一層層往輸入端遞推、算出每個權重的 &lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/gradient/" data-link-title="Gradient" data-link-desc="loss function 對權重的偏微分向量、指出「該往哪個方向調權重才能讓 loss 下降最快」">gradient&lt;/a>」。它是訓練神經網路的核心演算法、沒有它就無法在合理時間內訓練深度模型。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>Backpropagation 是訓練 loop 的中段、夾在 forward pass 跟權重更新之間：&lt;/p>





&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-text" data-lang="text">&lt;span class="line">&lt;span class="ln">1&lt;/span>&lt;span class="cl">[forward pass]：input → layer1 → layer2 → ... → output → loss
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">2&lt;/span>&lt;span class="cl"> ↓
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">3&lt;/span>&lt;span class="cl">[backpropagation]：把 loss 對最後一層權重的偏微分算出來
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">4&lt;/span>&lt;span class="cl"> ←─ chain rule ─ 再往前傳播一層、算前一層的 gradient
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">5&lt;/span>&lt;span class="cl"> ←─ chain rule ─ ...一路傳回輸入層
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">6&lt;/span>&lt;span class="cl"> ↓
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">7&lt;/span>&lt;span class="cl">[optimizer step]：每個權重 w 用對應的 gradient 更新&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>關鍵特性：&lt;/p>
&lt;ol>
&lt;li>&lt;strong>計算成本 ≈ forward pass 的 2~3 倍&lt;/strong>：每個 layer 都要存 forward 階段的中間值（activation）、反向時拿來算 gradient。所以訓練比推論貴一個量級。&lt;/li>
&lt;li>&lt;strong>記憶體佔用 = forward 階段 activation 的累計&lt;/strong>：這是訓練比推論吃 VRAM 的主因、不是「權重變大」、是「activation 要存著」。&lt;/li>
&lt;li>&lt;strong>數值穩定性敏感&lt;/strong>：long chain 的 chain rule 容易導致 gradient 爆炸或消失、見 &lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/gradient/" data-link-title="Gradient" data-link-desc="loss function 對權重的偏微分向量、指出「該往哪個方向調權重才能讓 loss 下降最快」">gradient&lt;/a> 卡。&lt;/li>
&lt;/ol>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>推論階段完全不用 backpropagation。理解這點能解釋幾個現象：為什麼同樣模型訓練要 8 卡 H100 一週、推論單卡就跑得動（差幾十倍的計算與記憶體需求）；為什麼 LoRA / QLoRA 等 parameter-efficient fine-tuning 能大幅降低訓練成本（凍住大部分權重、只對少數 LoRA 矩陣做 backpropagation）；為什麼 inference framework（llama.cpp、vLLM）跟 training framework（PyTorch、JAX）的設計重點完全不同。&lt;/p></description><content:encoded><![CDATA[<p>Backpropagation（反向傳播）的核心概念是「從輸出端的 loss 開始、用 chain rule 一層層往輸入端遞推、算出每個權重的 <a href="/blog/llm/knowledge-cards/gradient/" data-link-title="Gradient" data-link-desc="loss function 對權重的偏微分向量、指出「該往哪個方向調權重才能讓 loss 下降最快」">gradient</a>」。它是訓練神經網路的核心演算法、沒有它就無法在合理時間內訓練深度模型。</p>
<h2 id="概念位置">概念位置</h2>
<p>Backpropagation 是訓練 loop 的中段、夾在 forward pass 跟權重更新之間：</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="ln">1</span><span class="cl">[forward pass]：input → layer1 → layer2 → ... → output → loss
</span></span><span class="line"><span class="ln">2</span><span class="cl">                                                          ↓
</span></span><span class="line"><span class="ln">3</span><span class="cl">[backpropagation]：把 loss 對最後一層權重的偏微分算出來
</span></span><span class="line"><span class="ln">4</span><span class="cl">                  ←─ chain rule ─ 再往前傳播一層、算前一層的 gradient
</span></span><span class="line"><span class="ln">5</span><span class="cl">                  ←─ chain rule ─ ...一路傳回輸入層
</span></span><span class="line"><span class="ln">6</span><span class="cl">                                                          ↓
</span></span><span class="line"><span class="ln">7</span><span class="cl">[optimizer step]：每個權重 w 用對應的 gradient 更新</span></span></code></pre></div><p>關鍵特性：</p>
<ol>
<li><strong>計算成本 ≈ forward pass 的 2~3 倍</strong>：每個 layer 都要存 forward 階段的中間值（activation）、反向時拿來算 gradient。所以訓練比推論貴一個量級。</li>
<li><strong>記憶體佔用 = forward 階段 activation 的累計</strong>：這是訓練比推論吃 VRAM 的主因、不是「權重變大」、是「activation 要存著」。</li>
<li><strong>數值穩定性敏感</strong>：long chain 的 chain rule 容易導致 gradient 爆炸或消失、見 <a href="/blog/llm/knowledge-cards/gradient/" data-link-title="Gradient" data-link-desc="loss function 對權重的偏微分向量、指出「該往哪個方向調權重才能讓 loss 下降最快」">gradient</a> 卡。</li>
</ol>
<h2 id="設計責任">設計責任</h2>
<p>推論階段完全不用 backpropagation。理解這點能解釋幾個現象：為什麼同樣模型訓練要 8 卡 H100 一週、推論單卡就跑得動（差幾十倍的計算與記憶體需求）；為什麼 LoRA / QLoRA 等 parameter-efficient fine-tuning 能大幅降低訓練成本（凍住大部分權重、只對少數 LoRA 矩陣做 backpropagation）；為什麼 inference framework（llama.cpp、vLLM）跟 training framework（PyTorch、JAX）的設計重點完全不同。</p>
]]></content:encoded></item><item><title>Batching</title><link>https://tarrragon.github.io/blog/llm/knowledge-cards/batching/</link><pubDate>Tue, 12 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/llm/knowledge-cards/batching/</guid><description>&lt;p>Batching 的核心概念是「&lt;strong>多個 request 在同一個 forward pass 內一起跑、攤平 model weights 從記憶體讀到處理器的成本&lt;/strong>」。是 production LLM inference 的核心優化——跟 &lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/memory-bandwidth/" data-link-title="Memory Bandwidth" data-link-desc="記憶體每秒能讀寫多少 bytes：決定本地 LLM 生字速度的真正瓶頸">memory bandwidth&lt;/a> 瓶頸對接：讀一次 model weights、能 process N 個 request、單 request 的 effective throughput 上升 N 倍。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>Batching 介於 inference engine 內部、跟 &lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/kv-cache/" data-link-title="KV Cache" data-link-desc="已處理 token 的 attention 中間結果暫存：避免重算、加速後續生成">KV cache&lt;/a> 一起決定一個 GPU / Apple Silicon 能服務多少並發 user。但 batching 不是 free——靜態 batching 要等湊滿才跑、延遲首字延遲；連續 batching 平衡 throughput + latency 但實作複雜。Single-user 場景常無 batching（local Mac 跑 Ollama 即此情境）、production multi-tenant 必有 batching。&lt;/p>
&lt;h2 id="可觀察訊號與例子">可觀察訊號與例子&lt;/h2>
&lt;table>
 &lt;thead>
 &lt;tr>
 &lt;th>策略&lt;/th>
 &lt;th>機制&lt;/th>
 &lt;th>適合場景&lt;/th>
 &lt;/tr>
 &lt;/thead>
 &lt;tbody>
 &lt;tr>
 &lt;td>No batching&lt;/td>
 &lt;td>每 request 獨立 forward pass&lt;/td>
 &lt;td>Single-user、極低 latency 要求&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>Static batching&lt;/td>
 &lt;td>等湊滿 N 個 request 才跑&lt;/td>
 &lt;td>高 throughput 批次處理（embedding pipeline、文件 ingest）&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>Continuous batching&lt;/td>
 &lt;td>新 request 動態加入正在跑的 batch&lt;/td>
 &lt;td>vLLM / TGI / SGLang 等 production inference 主流&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>In-flight batching&lt;/td>
 &lt;td>不同 sequence 在不同 step 同時推&lt;/td>
 &lt;td>NVIDIA Triton + TensorRT-LLM 等深度優化&lt;/td>
 &lt;/tr>
 &lt;/tbody>
&lt;/table>
&lt;p>實務觀察：production LLM 服務 throughput 在 batch size 4-32 之間有明顯提升、超過 GPU memory 上限後反而下降（KV cache 跟 model weight 競爭記憶體）。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>選 batching 策略看兩維度：&lt;/p>
&lt;ol>
&lt;li>&lt;strong>應用 latency tolerance&lt;/strong>：
&lt;ul>
&lt;li>互動式 UI（chatbot、IDE 補完）→ continuous batching、低 latency 優先&lt;/li>
&lt;li>批次處理（夜間 summarization）→ static batching、throughput 優先&lt;/li>
&lt;/ul>
&lt;/li>
&lt;li>&lt;strong>硬體 KV cache 上限&lt;/strong>：
&lt;ul>
&lt;li>GPU memory - model weights = batchable 容量&lt;/li>
&lt;li>預估 max batch size = available_memory / per_user_kv_cache&lt;/li>
&lt;/ul>
&lt;/li>
&lt;/ol>
&lt;p>Embedding 服務通常 batch 16-128 都 OK（embedding 是純 forward pass、無 KV cache 累積）；chat / generation 服務 batch size 受 KV cache 嚴格限制。&lt;/p></description><content:encoded><![CDATA[<p>Batching 的核心概念是「<strong>多個 request 在同一個 forward pass 內一起跑、攤平 model weights 從記憶體讀到處理器的成本</strong>」。是 production LLM inference 的核心優化——跟 <a href="/blog/llm/knowledge-cards/memory-bandwidth/" data-link-title="Memory Bandwidth" data-link-desc="記憶體每秒能讀寫多少 bytes：決定本地 LLM 生字速度的真正瓶頸">memory bandwidth</a> 瓶頸對接：讀一次 model weights、能 process N 個 request、單 request 的 effective throughput 上升 N 倍。</p>
<h2 id="概念位置">概念位置</h2>
<p>Batching 介於 inference engine 內部、跟 <a href="/blog/llm/knowledge-cards/kv-cache/" data-link-title="KV Cache" data-link-desc="已處理 token 的 attention 中間結果暫存：避免重算、加速後續生成">KV cache</a> 一起決定一個 GPU / Apple Silicon 能服務多少並發 user。但 batching 不是 free——靜態 batching 要等湊滿才跑、延遲首字延遲；連續 batching 平衡 throughput + latency 但實作複雜。Single-user 場景常無 batching（local Mac 跑 Ollama 即此情境）、production multi-tenant 必有 batching。</p>
<h2 id="可觀察訊號與例子">可觀察訊號與例子</h2>
<table>
  <thead>
      <tr>
          <th>策略</th>
          <th>機制</th>
          <th>適合場景</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>No batching</td>
          <td>每 request 獨立 forward pass</td>
          <td>Single-user、極低 latency 要求</td>
      </tr>
      <tr>
          <td>Static batching</td>
          <td>等湊滿 N 個 request 才跑</td>
          <td>高 throughput 批次處理（embedding pipeline、文件 ingest）</td>
      </tr>
      <tr>
          <td>Continuous batching</td>
          <td>新 request 動態加入正在跑的 batch</td>
          <td>vLLM / TGI / SGLang 等 production inference 主流</td>
      </tr>
      <tr>
          <td>In-flight batching</td>
          <td>不同 sequence 在不同 step 同時推</td>
          <td>NVIDIA Triton + TensorRT-LLM 等深度優化</td>
      </tr>
  </tbody>
</table>
<p>實務觀察：production LLM 服務 throughput 在 batch size 4-32 之間有明顯提升、超過 GPU memory 上限後反而下降（KV cache 跟 model weight 競爭記憶體）。</p>
<h2 id="設計責任">設計責任</h2>
<p>選 batching 策略看兩維度：</p>
<ol>
<li><strong>應用 latency tolerance</strong>：
<ul>
<li>互動式 UI（chatbot、IDE 補完）→ continuous batching、低 latency 優先</li>
<li>批次處理（夜間 summarization）→ static batching、throughput 優先</li>
</ul>
</li>
<li><strong>硬體 KV cache 上限</strong>：
<ul>
<li>GPU memory - model weights = batchable 容量</li>
<li>預估 max batch size = available_memory / per_user_kv_cache</li>
</ul>
</li>
</ol>
<p>Embedding 服務通常 batch 16-128 都 OK（embedding 是純 forward pass、無 KV cache 累積）；chat / generation 服務 batch size 受 KV cache 嚴格限制。</p>
<p>詳細跟 production 部署 capacity planning 的對接見 <a href="/blog/llm/04-applications/production-resource-planning/" data-link-title="4.9 Production 部署的資源評估原理" data-link-desc="從本地單 user 到 production multi-tenant：concurrent users、cost model、observability、SLA、capacity planning 的設計取捨">4.9 Production 資源評估</a>；跟 <a href="/blog/llm/knowledge-cards/autoregressive/" data-link-title="Autoregressive" data-link-desc="LLM 一次生成一個 token、把已生成內容作為下一次輸入的架構">autoregressive</a> 推論的單 token 瓶頸對應的優化討論見 <a href="/blog/llm/03-theoretical-foundations/attention-mechanism/" data-link-title="3.2 Attention 機制" data-link-desc="Query / Key / Value、scaled dot-product attention、multi-head attention：Transformer 的核心運算">3.2 attention 機制</a>。</p>
]]></content:encoded></item><item><title>Beam Search</title><link>https://tarrragon.github.io/blog/llm/knowledge-cards/beam-search/</link><pubDate>Tue, 12 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/llm/knowledge-cards/beam-search/</guid><description>&lt;p>Beam search 的核心概念是「&lt;strong>每步同時保留 K 條最有機率的候選 sequence（beam width = K）、最終挑一條總機率最高的當輸出&lt;/strong>」。相比 greedy decoding 只保一條、beam search 能探索更多可能、避免「貪心一時、累積失誤」；但對話 / coding 場景常出現副作用、是 &lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/top-p-sampling/" data-link-title="Top-K / Top-P / Min-P Sampling" data-link-desc="從機率分佈取樣前先過濾低機率 token 的三種策略、現代 LLM 推論主流">top-p sampling&lt;/a> 取代它的原因。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>Beam search 跟其他 decoding 策略的對比：&lt;/p>
&lt;table>
 &lt;thead>
 &lt;tr>
 &lt;th>策略&lt;/th>
 &lt;th>機制&lt;/th>
 &lt;th>適合場景&lt;/th>
 &lt;th>LLM 常見性&lt;/th>
 &lt;/tr>
 &lt;/thead>
 &lt;tbody>
 &lt;tr>
 &lt;td>Greedy&lt;/td>
 &lt;td>每步選機率最大的 token&lt;/td>
 &lt;td>確定性任務、debugging&lt;/td>
 &lt;td>高&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;strong>Beam search (K)&lt;/strong>&lt;/td>
 &lt;td>維護 K 條候選、最後挑總機率最高的&lt;/td>
 &lt;td>機器翻譯、summarization、有「正確答案」的任務&lt;/td>
 &lt;td>中（傳統 NLP 主流）&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>Top-k / top-p / min-p&lt;/td>
 &lt;td>從機率分佈隨機取樣（限制候選範圍）&lt;/td>
 &lt;td>對話、寫作、coding、創意輸出&lt;/td>
 &lt;td>高（LLM 主流）&lt;/td>
 &lt;/tr>
 &lt;/tbody>
&lt;/table>
&lt;p>Beam search 的算法直覺：&lt;/p>





&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-text" data-lang="text">&lt;span class="line">&lt;span class="ln">1&lt;/span>&lt;span class="cl">beam_width = 3
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">2&lt;/span>&lt;span class="cl">Step 1：從機率分佈挑前 3 個 token、得到 3 條 partial sequence
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">3&lt;/span>&lt;span class="cl">Step 2：每條 partial 各自展開所有可能下個 token、組合機率排序、保留前 3
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">4&lt;/span>&lt;span class="cl">Step 3：重複 Step 2、直到所有 beam 都遇到 EOS 或達到 max_length
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">5&lt;/span>&lt;span class="cl">Final：選總 log-probability 最高的 beam 當輸出&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>Beam search 在 LLM chat / coding 場景的副作用：&lt;/p>
&lt;ol>
&lt;li>&lt;strong>輸出偏 boilerplate&lt;/strong>：K 個 beam 容易收斂到同樣的高頻開頭（「Sure!」「That&amp;rsquo;s a great question」）、各 beam 平均化掉原本該有的多樣性。&lt;/li>
&lt;li>&lt;strong>缺乏隨機性&lt;/strong>：給同 prompt 永遠生同輸出、缺乏寫作 / 創意任務需要的變化。&lt;/li>
&lt;li>&lt;strong>計算貴&lt;/strong>：K 倍記憶體 + K 倍 forward pass。&lt;/li>
&lt;/ol>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>讀 inference framework 看到 &lt;code>num_beams: 1&lt;/code> 預設值就是用 greedy/sampling、&lt;code>num_beams: 5&lt;/code> 才會開 beam search。寫 code 場景的判讀：日常用 &lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/top-p-sampling/" data-link-title="Top-K / Top-P / Min-P Sampling" data-link-desc="從機率分佈取樣前先過濾低機率 token 的三種策略、現代 LLM 推論主流">top-p sampling&lt;/a> 為主、需要確定性測試用 greedy、需要「在多個候選中挑最好的」用 best-of-N（每個獨立 sample、再選 reward 最高）而非 beam search。Beam search 在現代 LLM chat 場景已經少用、但在 translation / structured output 等「有正確答案」場景仍見。&lt;/p></description><content:encoded><![CDATA[<p>Beam search 的核心概念是「<strong>每步同時保留 K 條最有機率的候選 sequence（beam width = K）、最終挑一條總機率最高的當輸出</strong>」。相比 greedy decoding 只保一條、beam search 能探索更多可能、避免「貪心一時、累積失誤」；但對話 / coding 場景常出現副作用、是 <a href="/blog/llm/knowledge-cards/top-p-sampling/" data-link-title="Top-K / Top-P / Min-P Sampling" data-link-desc="從機率分佈取樣前先過濾低機率 token 的三種策略、現代 LLM 推論主流">top-p sampling</a> 取代它的原因。</p>
<h2 id="概念位置">概念位置</h2>
<p>Beam search 跟其他 decoding 策略的對比：</p>
<table>
  <thead>
      <tr>
          <th>策略</th>
          <th>機制</th>
          <th>適合場景</th>
          <th>LLM 常見性</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>Greedy</td>
          <td>每步選機率最大的 token</td>
          <td>確定性任務、debugging</td>
          <td>高</td>
      </tr>
      <tr>
          <td><strong>Beam search (K)</strong></td>
          <td>維護 K 條候選、最後挑總機率最高的</td>
          <td>機器翻譯、summarization、有「正確答案」的任務</td>
          <td>中（傳統 NLP 主流）</td>
      </tr>
      <tr>
          <td>Top-k / top-p / min-p</td>
          <td>從機率分佈隨機取樣（限制候選範圍）</td>
          <td>對話、寫作、coding、創意輸出</td>
          <td>高（LLM 主流）</td>
      </tr>
  </tbody>
</table>
<p>Beam search 的算法直覺：</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="ln">1</span><span class="cl">beam_width = 3
</span></span><span class="line"><span class="ln">2</span><span class="cl">Step 1：從機率分佈挑前 3 個 token、得到 3 條 partial sequence
</span></span><span class="line"><span class="ln">3</span><span class="cl">Step 2：每條 partial 各自展開所有可能下個 token、組合機率排序、保留前 3
</span></span><span class="line"><span class="ln">4</span><span class="cl">Step 3：重複 Step 2、直到所有 beam 都遇到 EOS 或達到 max_length
</span></span><span class="line"><span class="ln">5</span><span class="cl">Final：選總 log-probability 最高的 beam 當輸出</span></span></code></pre></div><p>Beam search 在 LLM chat / coding 場景的副作用：</p>
<ol>
<li><strong>輸出偏 boilerplate</strong>：K 個 beam 容易收斂到同樣的高頻開頭（「Sure!」「That&rsquo;s a great question」）、各 beam 平均化掉原本該有的多樣性。</li>
<li><strong>缺乏隨機性</strong>：給同 prompt 永遠生同輸出、缺乏寫作 / 創意任務需要的變化。</li>
<li><strong>計算貴</strong>：K 倍記憶體 + K 倍 forward pass。</li>
</ol>
<h2 id="設計責任">設計責任</h2>
<p>讀 inference framework 看到 <code>num_beams: 1</code> 預設值就是用 greedy/sampling、<code>num_beams: 5</code> 才會開 beam search。寫 code 場景的判讀：日常用 <a href="/blog/llm/knowledge-cards/top-p-sampling/" data-link-title="Top-K / Top-P / Min-P Sampling" data-link-desc="從機率分佈取樣前先過濾低機率 token 的三種策略、現代 LLM 推論主流">top-p sampling</a> 為主、需要確定性測試用 greedy、需要「在多個候選中挑最好的」用 best-of-N（每個獨立 sample、再選 reward 最高）而非 beam search。Beam search 在現代 LLM chat 場景已經少用、但在 translation / structured output 等「有正確答案」場景仍見。</p>
]]></content:encoded></item><item><title>Bind Address</title><link>https://tarrragon.github.io/blog/llm/knowledge-cards/bind-address/</link><pubDate>Tue, 12 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/llm/knowledge-cards/bind-address/</guid><description>&lt;p>Bind address 的核心概念是「伺服器啟動時決定『監聽哪個網路介面上的請求』」。同一個 port 在不同 bind address 下、能接受的請求來源完全不同；對本地 LLM 推論伺服器（Ollama / llama-server / LM Studio）來說、bind address 是決定誰能連到模型的最直接設定。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>三層典型 bind address 的暴露範圍：&lt;/p>
&lt;table>
 &lt;thead>
 &lt;tr>
 &lt;th>bind address&lt;/th>
 &lt;th>接受來源&lt;/th>
 &lt;th>個人 dev 場景的常見用途&lt;/th>
 &lt;/tr>
 &lt;/thead>
 &lt;tbody>
 &lt;tr>
 &lt;td>&lt;code>127.0.0.1&lt;/code> / &lt;code>localhost&lt;/code>&lt;/td>
 &lt;td>只本機 process&lt;/td>
 &lt;td>VS Code 連本機 server、最安全預設&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>具體 LAN IP（如 &lt;code>192.168.x.x&lt;/code>）&lt;/td>
 &lt;td>同網段設備&lt;/td>
 &lt;td>想分享給家裡桌機 / 筆電&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;code>0.0.0.0&lt;/code>&lt;/td>
 &lt;td>所有網路介面&lt;/td>
 &lt;td>容器化 / 想接受 LAN + WAN（風險高）&lt;/td>
 &lt;/tr>
 &lt;/tbody>
&lt;/table>
&lt;p>關鍵差異：&lt;/p>
&lt;ol>
&lt;li>&lt;code>127.0.0.1&lt;/code> 只接 loopback、無論其他網路介面狀態都不接外部請求。&lt;/li>
&lt;li>&lt;code>0.0.0.0&lt;/code> 在所有介面上監聽、若機器有 public IP 或在公開 Wi-Fi、就會被網路上其他人連到。&lt;/li>
&lt;li>具體 LAN IP 是中間地帶、限定來源到該介面的網段。&lt;/li>
&lt;/ol>
&lt;p>檢查當前 bind 狀態的指令：&lt;/p>





&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-bash" data-lang="bash">&lt;span class="line">&lt;span class="ln">1&lt;/span>&lt;span class="cl">&lt;span class="c1"># macOS / Linux&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">2&lt;/span>&lt;span class="cl">lsof -i -P -n &lt;span class="p">|&lt;/span> grep LISTEN &lt;span class="p">|&lt;/span> grep &amp;lt;port&amp;gt;
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">3&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">4&lt;/span>&lt;span class="cl">&lt;span class="c1"># Linux&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">5&lt;/span>&lt;span class="cl">ss -lntp &lt;span class="p">|&lt;/span> grep &amp;lt;port&amp;gt;
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">6&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">7&lt;/span>&lt;span class="cl">&lt;span class="c1"># 或&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">8&lt;/span>&lt;span class="cl">netstat -an &lt;span class="p">|&lt;/span> grep LISTEN &lt;span class="p">|&lt;/span> grep &amp;lt;port&amp;gt;&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>看到 &lt;code>127.0.0.1:&amp;lt;port&amp;gt;&lt;/code> 是 loopback、&lt;code>*:&amp;lt;port&amp;gt;&lt;/code> 或 &lt;code>0.0.0.0:&amp;lt;port&amp;gt;&lt;/code> 是所有介面。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>理解 bind address 後可以解釋兩個現象：為什麼預設安全的伺服器都 bind 到 &lt;code>127.0.0.1&lt;/code>（避免不小心暴露）、為什麼 Docker &lt;code>-p 8080:8080&lt;/code> 預設 bind 到 &lt;code>0.0.0.0&lt;/code>（容器化的便利性、但對個人 dev 是潛在暴露點）。&lt;/p>
&lt;p>設計本地推論伺服器時、預設 loopback、想分享 LAN 時 bind 到具體 LAN IP（不要直接 &lt;code>0.0.0.0&lt;/code>）、要對外時加 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/api-gateway/" data-link-title="API Gateway" data-link-desc="說明外部流量如何先收斂到一層可集中控制的入口">reverse proxy&lt;/a> + auth + TLS。詳見 &lt;a href="https://tarrragon.github.io/blog/llm/06-security/inference-server-binding/" data-link-title="6.1 推論伺服器的綁定與暴露範圍" data-link-desc="個人 dev 場景下 llama-server / Ollama / LM Studio 的 bind address 判讀：127.0.0.1 vs LAN vs 反代、預設安全、誤開放給內網的後果">6.1 推論伺服器的綁定與暴露範圍&lt;/a> 跟 &lt;a href="https://tarrragon.github.io/blog/backend/07-security-data-protection/entrypoint-and-server-protection/" data-link-title="7.3 入口治理與伺服器防護" data-link-desc="以問題驅動方式整理對外入口、管理平面與伺服器邊界">7.3 入口治理與伺服器防護&lt;/a>。&lt;/p></description><content:encoded><![CDATA[<p>Bind address 的核心概念是「伺服器啟動時決定『監聽哪個網路介面上的請求』」。同一個 port 在不同 bind address 下、能接受的請求來源完全不同；對本地 LLM 推論伺服器（Ollama / llama-server / LM Studio）來說、bind address 是決定誰能連到模型的最直接設定。</p>
<h2 id="概念位置">概念位置</h2>
<p>三層典型 bind address 的暴露範圍：</p>
<table>
  <thead>
      <tr>
          <th>bind address</th>
          <th>接受來源</th>
          <th>個人 dev 場景的常見用途</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td><code>127.0.0.1</code> / <code>localhost</code></td>
          <td>只本機 process</td>
          <td>VS Code 連本機 server、最安全預設</td>
      </tr>
      <tr>
          <td>具體 LAN IP（如 <code>192.168.x.x</code>）</td>
          <td>同網段設備</td>
          <td>想分享給家裡桌機 / 筆電</td>
      </tr>
      <tr>
          <td><code>0.0.0.0</code></td>
          <td>所有網路介面</td>
          <td>容器化 / 想接受 LAN + WAN（風險高）</td>
      </tr>
  </tbody>
</table>
<p>關鍵差異：</p>
<ol>
<li><code>127.0.0.1</code> 只接 loopback、無論其他網路介面狀態都不接外部請求。</li>
<li><code>0.0.0.0</code> 在所有介面上監聽、若機器有 public IP 或在公開 Wi-Fi、就會被網路上其他人連到。</li>
<li>具體 LAN IP 是中間地帶、限定來源到該介面的網段。</li>
</ol>
<p>檢查當前 bind 狀態的指令：</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="ln">1</span><span class="cl"><span class="c1"># macOS / Linux</span>
</span></span><span class="line"><span class="ln">2</span><span class="cl">lsof -i -P -n <span class="p">|</span> grep LISTEN <span class="p">|</span> grep &lt;port&gt;
</span></span><span class="line"><span class="ln">3</span><span class="cl">
</span></span><span class="line"><span class="ln">4</span><span class="cl"><span class="c1"># Linux</span>
</span></span><span class="line"><span class="ln">5</span><span class="cl">ss -lntp <span class="p">|</span> grep &lt;port&gt;
</span></span><span class="line"><span class="ln">6</span><span class="cl">
</span></span><span class="line"><span class="ln">7</span><span class="cl"><span class="c1"># 或</span>
</span></span><span class="line"><span class="ln">8</span><span class="cl">netstat -an <span class="p">|</span> grep LISTEN <span class="p">|</span> grep &lt;port&gt;</span></span></code></pre></div><p>看到 <code>127.0.0.1:&lt;port&gt;</code> 是 loopback、<code>*:&lt;port&gt;</code> 或 <code>0.0.0.0:&lt;port&gt;</code> 是所有介面。</p>
<h2 id="設計責任">設計責任</h2>
<p>理解 bind address 後可以解釋兩個現象：為什麼預設安全的伺服器都 bind 到 <code>127.0.0.1</code>（避免不小心暴露）、為什麼 Docker <code>-p 8080:8080</code> 預設 bind 到 <code>0.0.0.0</code>（容器化的便利性、但對個人 dev 是潛在暴露點）。</p>
<p>設計本地推論伺服器時、預設 loopback、想分享 LAN 時 bind 到具體 LAN IP（不要直接 <code>0.0.0.0</code>）、要對外時加 <a href="/blog/backend/knowledge-cards/api-gateway/" data-link-title="API Gateway" data-link-desc="說明外部流量如何先收斂到一層可集中控制的入口">reverse proxy</a> + auth + TLS。詳見 <a href="/blog/llm/06-security/inference-server-binding/" data-link-title="6.1 推論伺服器的綁定與暴露範圍" data-link-desc="個人 dev 場景下 llama-server / Ollama / LM Studio 的 bind address 判讀：127.0.0.1 vs LAN vs 反代、預設安全、誤開放給內網的後果">6.1 推論伺服器的綁定與暴露範圍</a> 跟 <a href="/blog/backend/07-security-data-protection/entrypoint-and-server-protection/" data-link-title="7.3 入口治理與伺服器防護" data-link-desc="以問題驅動方式整理對外入口、管理平面與伺服器邊界">7.3 入口治理與伺服器防護</a>。</p>
]]></content:encoded></item><item><title>BPE（Byte-Pair Encoding）</title><link>https://tarrragon.github.io/blog/llm/knowledge-cards/bpe/</link><pubDate>Tue, 12 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/llm/knowledge-cards/bpe/</guid><description>&lt;p>BPE（Byte-Pair Encoding、Sennrich et al., 2015 引入 NLP）的核心概念是「&lt;strong>從字元開始、反覆找『出現頻率最高的字元對』把它合併成新 token、直到達到目標詞彙表大小&lt;/strong>」。是 GPT、Llama、Mistral 等主流 LLM 的 tokenization 演算法、能在「字元」跟「整詞」之間找平衡。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>BPE 訓練 tokenizer 的流程（簡化）：&lt;/p>





&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-text" data-lang="text">&lt;span class="line">&lt;span class="ln">1&lt;/span>&lt;span class="cl">Step 0：vocab = 所有單一字元（256 個 byte / Unicode 字符）
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">2&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">3&lt;/span>&lt;span class="cl">迭代：
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">4&lt;/span>&lt;span class="cl"> Step 1：掃描 corpus、統計所有相鄰 token 對的出現頻率
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">5&lt;/span>&lt;span class="cl"> Step 2：找出現最多的字元對（如 &amp;#34;l&amp;#34; + &amp;#34;o&amp;#34; 一起出現 1M 次）
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">6&lt;/span>&lt;span class="cl"> Step 3：把它當新 token 加進 vocab、把 corpus 裡所有這個對換成新 token
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">7&lt;/span>&lt;span class="cl"> Step 4：回到 Step 1、直到 vocab 達到目標大小（如 50K、128K、256K）&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>實際 &lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/token/" data-link-title="Token" data-link-desc="LLM 處理文字時的最小單位：介於字元與單字之間">token&lt;/a> 化的結果：&lt;/p>
&lt;table>
 &lt;thead>
 &lt;tr>
 &lt;th>文字&lt;/th>
 &lt;th>BPE token 化結果&lt;/th>
 &lt;th>理由&lt;/th>
 &lt;/tr>
 &lt;/thead>
 &lt;tbody>
 &lt;tr>
 &lt;td>&lt;code>Hello&lt;/code>&lt;/td>
 &lt;td>&lt;code>[&amp;quot;Hello&amp;quot;]&lt;/code>&lt;/td>
 &lt;td>高頻單字、整詞當一個 token&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;code>Hellobot&lt;/code>&lt;/td>
 &lt;td>&lt;code>[&amp;quot;Hello&amp;quot;, &amp;quot;bot&amp;quot;]&lt;/code>&lt;/td>
 &lt;td>罕見組合、拆成已知 token&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;code>Antidisestab...&lt;/code>&lt;/td>
 &lt;td>&lt;code>[&amp;quot;Anti&amp;quot;, &amp;quot;dis&amp;quot;, &amp;quot;establish&amp;quot;, ...]&lt;/code>&lt;/td>
 &lt;td>罕見長詞、拆成 sub-word&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;code>你好&lt;/code>&lt;/td>
 &lt;td>&lt;code>[&amp;quot;你&amp;quot;, &amp;quot;好&amp;quot;]&lt;/code> 或 &lt;code>[&amp;quot;你好&amp;quot;]&lt;/code>&lt;/td>
 &lt;td>視 tokenizer 訓練 corpus 的中文比例&lt;/td>
 &lt;/tr>
 &lt;/tbody>
&lt;/table>
&lt;p>BPE 的變體：&lt;/p>
&lt;ol>
&lt;li>&lt;strong>Byte-level BPE&lt;/strong>：把每個 byte 當基底（256 個）、所以任何 Unicode / 二進制都能 tokenize、不會有 unknown token。GPT-2 開始的標準。&lt;/li>
&lt;li>&lt;strong>&lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/sentencepiece/" data-link-title="SentencePiece" data-link-desc="Google 開源的多語言 tokenization 框架、支援 BPE 跟 unigram 演算法、處理空白統一">SentencePiece&lt;/a> BPE&lt;/strong>：跟 SentencePiece 框架結合、處理多語言更靈活。&lt;/li>
&lt;/ol>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>讀 model card 看到 &lt;code>tokenizer: BPE&lt;/code> 就是這個演算法。BPE 對英文友好（高頻單詞整個一 token）、中文 / 日韓較不友好（單字符常被當獨立 token）；這就是為什麼同一段中文翻譯成英文後、英文 token 數常常更少、雲端 LLM 用中文 API 比英文貴。但越新的模型（Gemma 4、Qwen3 等）vocab 越大（256K+）、對中文友善度提升中。&lt;/p></description><content:encoded><![CDATA[<p>BPE（Byte-Pair Encoding、Sennrich et al., 2015 引入 NLP）的核心概念是「<strong>從字元開始、反覆找『出現頻率最高的字元對』把它合併成新 token、直到達到目標詞彙表大小</strong>」。是 GPT、Llama、Mistral 等主流 LLM 的 tokenization 演算法、能在「字元」跟「整詞」之間找平衡。</p>
<h2 id="概念位置">概念位置</h2>
<p>BPE 訓練 tokenizer 的流程（簡化）：</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="ln">1</span><span class="cl">Step 0：vocab = 所有單一字元（256 個 byte / Unicode 字符）
</span></span><span class="line"><span class="ln">2</span><span class="cl">
</span></span><span class="line"><span class="ln">3</span><span class="cl">迭代：
</span></span><span class="line"><span class="ln">4</span><span class="cl">  Step 1：掃描 corpus、統計所有相鄰 token 對的出現頻率
</span></span><span class="line"><span class="ln">5</span><span class="cl">  Step 2：找出現最多的字元對（如 &#34;l&#34; + &#34;o&#34; 一起出現 1M 次）
</span></span><span class="line"><span class="ln">6</span><span class="cl">  Step 3：把它當新 token 加進 vocab、把 corpus 裡所有這個對換成新 token
</span></span><span class="line"><span class="ln">7</span><span class="cl">  Step 4：回到 Step 1、直到 vocab 達到目標大小（如 50K、128K、256K）</span></span></code></pre></div><p>實際 <a href="/blog/llm/knowledge-cards/token/" data-link-title="Token" data-link-desc="LLM 處理文字時的最小單位：介於字元與單字之間">token</a> 化的結果：</p>
<table>
  <thead>
      <tr>
          <th>文字</th>
          <th>BPE token 化結果</th>
          <th>理由</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td><code>Hello</code></td>
          <td><code>[&quot;Hello&quot;]</code></td>
          <td>高頻單字、整詞當一個 token</td>
      </tr>
      <tr>
          <td><code>Hellobot</code></td>
          <td><code>[&quot;Hello&quot;, &quot;bot&quot;]</code></td>
          <td>罕見組合、拆成已知 token</td>
      </tr>
      <tr>
          <td><code>Antidisestab...</code></td>
          <td><code>[&quot;Anti&quot;, &quot;dis&quot;, &quot;establish&quot;, ...]</code></td>
          <td>罕見長詞、拆成 sub-word</td>
      </tr>
      <tr>
          <td><code>你好</code></td>
          <td><code>[&quot;你&quot;, &quot;好&quot;]</code> 或 <code>[&quot;你好&quot;]</code></td>
          <td>視 tokenizer 訓練 corpus 的中文比例</td>
      </tr>
  </tbody>
</table>
<p>BPE 的變體：</p>
<ol>
<li><strong>Byte-level BPE</strong>：把每個 byte 當基底（256 個）、所以任何 Unicode / 二進制都能 tokenize、不會有 unknown token。GPT-2 開始的標準。</li>
<li><strong><a href="/blog/llm/knowledge-cards/sentencepiece/" data-link-title="SentencePiece" data-link-desc="Google 開源的多語言 tokenization 框架、支援 BPE 跟 unigram 演算法、處理空白統一">SentencePiece</a> BPE</strong>：跟 SentencePiece 框架結合、處理多語言更靈活。</li>
</ol>
<h2 id="設計責任">設計責任</h2>
<p>讀 model card 看到 <code>tokenizer: BPE</code> 就是這個演算法。BPE 對英文友好（高頻單詞整個一 token）、中文 / 日韓較不友好（單字符常被當獨立 token）；這就是為什麼同一段中文翻譯成英文後、英文 token 數常常更少、雲端 LLM 用中文 API 比英文貴。但越新的模型（Gemma 4、Qwen3 等）vocab 越大（256K+）、對中文友善度提升中。</p>
]]></content:encoded></item><item><title>Catastrophic Forgetting</title><link>https://tarrragon.github.io/blog/llm/knowledge-cards/catastrophic-forgetting/</link><pubDate>Tue, 12 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/llm/knowledge-cards/catastrophic-forgetting/</guid><description>&lt;p>Catastrophic forgetting（災難遺忘）的核心概念是「&lt;strong>Fine-tune 模型時、新訓練資料的 gradient 更新破壞了模型原本學到的能力&lt;/strong>」。在 LLM fine-tuning 場景特別常見：在自己 domain 資料上 fine-tune、結果模型在原 benchmark / 通用任務上分數大幅下降。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>Catastrophic forgetting 在 LLM fine-tuning 的典型表現：&lt;/p>





&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-text" data-lang="text">&lt;span class="line">&lt;span class="ln"> 1&lt;/span>&lt;span class="cl">Before fine-tune（base instruct model）：
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 2&lt;/span>&lt;span class="cl"> HumanEval: 75
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 3&lt;/span>&lt;span class="cl"> MMLU: 70
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 4&lt;/span>&lt;span class="cl"> 自己 domain 任務 hit rate: 40%
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 5&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 6&lt;/span>&lt;span class="cl">After fine-tune（在自己 domain 資料上跑 SFT、3 epochs）：
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 7&lt;/span>&lt;span class="cl"> HumanEval: 55 ← 下降 20 點
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 8&lt;/span>&lt;span class="cl"> MMLU: 50 ← 下降 20 點
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 9&lt;/span>&lt;span class="cl"> 自己 domain 任務 hit rate: 70% ← 提升 30 點
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">10&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">11&lt;/span>&lt;span class="cl">→ 自己 domain 強了、但通用能力崩了&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>成因：&lt;/p>
&lt;ol>
&lt;li>&lt;strong>Gradient 在新資料上對 base 權重做大更新&lt;/strong>：原本 base 的權重對通用任務有用、被覆蓋掉&lt;/li>
&lt;li>&lt;strong>資料分佈差距大&lt;/strong>：自己 domain 跟 pretrain corpus 分佈差距大、學新的 = 忘舊的&lt;/li>
&lt;li>&lt;strong>訓練 epoch 太多&lt;/strong>：模型 over-fit 到新資料、舊能力衰退更嚴重&lt;/li>
&lt;li>&lt;strong>Learning rate 太高&lt;/strong>：每步更新幅度大、舊權重變化快&lt;/li>
&lt;/ol>
&lt;h2 id="緩解策略">緩解策略&lt;/h2>
&lt;table>
 &lt;thead>
 &lt;tr>
 &lt;th>策略&lt;/th>
 &lt;th>機制&lt;/th>
 &lt;th>適用情境&lt;/th>
 &lt;/tr>
 &lt;/thead>
 &lt;tbody>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/lora/" data-link-title="LoRA" data-link-desc="Low-Rank Adaptation：凍住原模型權重、只訓兩個小矩陣的 parameter-efficient fine-tuning">LoRA&lt;/a> / &lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/qlora/" data-link-title="QLoRA" data-link-desc="把 base model 量化到 4-bit &amp;#43; LoRA fine-tune 的組合、消費級 GPU 也能 fine-tune 大模型">QLoRA&lt;/a>&lt;/td>
 &lt;td>凍住 base 權重、只訓 adapter、舊能力完全保留&lt;/td>
 &lt;td>多數 fine-tune 場景的 default&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>資料 mixing&lt;/td>
 &lt;td>訓練 batch 內 mix 通用資料 + domain 資料、避免分佈完全偏移&lt;/td>
 &lt;td>跟 LoRA 結合使用&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>Lower learning rate&lt;/td>
 &lt;td>用較小 lr（如 5e-6 vs 1e-5）、減慢更新&lt;/td>
 &lt;td>全參數 fine-tune 必選&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>Fewer epochs&lt;/td>
 &lt;td>訓 1-2 epoch 就停、不過度擬合&lt;/td>
 &lt;td>同上&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>Regularization（KL constraint）&lt;/td>
 &lt;td>Loss 加「不能偏離 base 太遠」的約束&lt;/td>
 &lt;td>RLHF / DPO 已內建&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>EWC（Elastic Weight Consolidation）&lt;/td>
 &lt;td>對重要權重加更強懲罰、防止它們被改&lt;/td>
 &lt;td>研究用、實務罕見&lt;/td>
 &lt;/tr>
 &lt;/tbody>
&lt;/table>
&lt;p>主流 fine-tuning 配置（避免 catastrophic forgetting）：&lt;/p>





&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-text" data-lang="text">&lt;span class="line">&lt;span class="ln">1&lt;/span>&lt;span class="cl">方法：QLoRA fine-tune
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">2&lt;/span>&lt;span class="cl">參數：
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">3&lt;/span>&lt;span class="cl"> - rank: 16-64（看資料量）
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">4&lt;/span>&lt;span class="cl"> - alpha: 32（typical）
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">5&lt;/span>&lt;span class="cl"> - lr: 1e-4 ~ 5e-4（LoRA 適合較大 lr）
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">6&lt;/span>&lt;span class="cl"> - epochs: 1-3（不過度訓）
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">7&lt;/span>&lt;span class="cl"> - 資料：80% in-domain + 20% 通用 instruction data（保留通用能力）&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>讀 fine-tune paper / 報告看到「forgetting」「retention」「regression」就是這現象。寫 code 場景的判讀：&lt;/p></description><content:encoded><![CDATA[<p>Catastrophic forgetting（災難遺忘）的核心概念是「<strong>Fine-tune 模型時、新訓練資料的 gradient 更新破壞了模型原本學到的能力</strong>」。在 LLM fine-tuning 場景特別常見：在自己 domain 資料上 fine-tune、結果模型在原 benchmark / 通用任務上分數大幅下降。</p>
<h2 id="概念位置">概念位置</h2>
<p>Catastrophic forgetting 在 LLM fine-tuning 的典型表現：</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="ln"> 1</span><span class="cl">Before fine-tune（base instruct model）：
</span></span><span class="line"><span class="ln"> 2</span><span class="cl">  HumanEval: 75
</span></span><span class="line"><span class="ln"> 3</span><span class="cl">  MMLU: 70
</span></span><span class="line"><span class="ln"> 4</span><span class="cl">  自己 domain 任務 hit rate: 40%
</span></span><span class="line"><span class="ln"> 5</span><span class="cl">
</span></span><span class="line"><span class="ln"> 6</span><span class="cl">After fine-tune（在自己 domain 資料上跑 SFT、3 epochs）：
</span></span><span class="line"><span class="ln"> 7</span><span class="cl">  HumanEval: 55  ← 下降 20 點
</span></span><span class="line"><span class="ln"> 8</span><span class="cl">  MMLU: 50       ← 下降 20 點
</span></span><span class="line"><span class="ln"> 9</span><span class="cl">  自己 domain 任務 hit rate: 70%  ← 提升 30 點
</span></span><span class="line"><span class="ln">10</span><span class="cl">
</span></span><span class="line"><span class="ln">11</span><span class="cl">→ 自己 domain 強了、但通用能力崩了</span></span></code></pre></div><p>成因：</p>
<ol>
<li><strong>Gradient 在新資料上對 base 權重做大更新</strong>：原本 base 的權重對通用任務有用、被覆蓋掉</li>
<li><strong>資料分佈差距大</strong>：自己 domain 跟 pretrain corpus 分佈差距大、學新的 = 忘舊的</li>
<li><strong>訓練 epoch 太多</strong>：模型 over-fit 到新資料、舊能力衰退更嚴重</li>
<li><strong>Learning rate 太高</strong>：每步更新幅度大、舊權重變化快</li>
</ol>
<h2 id="緩解策略">緩解策略</h2>
<table>
  <thead>
      <tr>
          <th>策略</th>
          <th>機制</th>
          <th>適用情境</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td><a href="/blog/llm/knowledge-cards/lora/" data-link-title="LoRA" data-link-desc="Low-Rank Adaptation：凍住原模型權重、只訓兩個小矩陣的 parameter-efficient fine-tuning">LoRA</a> / <a href="/blog/llm/knowledge-cards/qlora/" data-link-title="QLoRA" data-link-desc="把 base model 量化到 4-bit &#43; LoRA fine-tune 的組合、消費級 GPU 也能 fine-tune 大模型">QLoRA</a></td>
          <td>凍住 base 權重、只訓 adapter、舊能力完全保留</td>
          <td>多數 fine-tune 場景的 default</td>
      </tr>
      <tr>
          <td>資料 mixing</td>
          <td>訓練 batch 內 mix 通用資料 + domain 資料、避免分佈完全偏移</td>
          <td>跟 LoRA 結合使用</td>
      </tr>
      <tr>
          <td>Lower learning rate</td>
          <td>用較小 lr（如 5e-6 vs 1e-5）、減慢更新</td>
          <td>全參數 fine-tune 必選</td>
      </tr>
      <tr>
          <td>Fewer epochs</td>
          <td>訓 1-2 epoch 就停、不過度擬合</td>
          <td>同上</td>
      </tr>
      <tr>
          <td>Regularization（KL constraint）</td>
          <td>Loss 加「不能偏離 base 太遠」的約束</td>
          <td>RLHF / DPO 已內建</td>
      </tr>
      <tr>
          <td>EWC（Elastic Weight Consolidation）</td>
          <td>對重要權重加更強懲罰、防止它們被改</td>
          <td>研究用、實務罕見</td>
      </tr>
  </tbody>
</table>
<p>主流 fine-tuning 配置（避免 catastrophic forgetting）：</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="ln">1</span><span class="cl">方法：QLoRA fine-tune
</span></span><span class="line"><span class="ln">2</span><span class="cl">參數：
</span></span><span class="line"><span class="ln">3</span><span class="cl">  - rank: 16-64（看資料量）
</span></span><span class="line"><span class="ln">4</span><span class="cl">  - alpha: 32（typical）
</span></span><span class="line"><span class="ln">5</span><span class="cl">  - lr: 1e-4 ~ 5e-4（LoRA 適合較大 lr）
</span></span><span class="line"><span class="ln">6</span><span class="cl">  - epochs: 1-3（不過度訓）
</span></span><span class="line"><span class="ln">7</span><span class="cl">  - 資料：80% in-domain + 20% 通用 instruction data（保留通用能力）</span></span></code></pre></div><h2 id="設計責任">設計責任</h2>
<p>讀 fine-tune paper / 報告看到「forgetting」「retention」「regression」就是這現象。寫 code 場景的判讀：</p>
<ol>
<li><strong>Fine-tune 前先建 baseline benchmark</strong>：把 base model 在通用 benchmark + 自己 domain 都跑一遍、fine-tune 後對比看 regression</li>
<li><strong>用 LoRA / QLoRA 是 default</strong>：除非有特殊理由要 full fine-tune、不然優先 LoRA</li>
<li><strong>不要把通用 chat 能力 fine-tune 掉</strong>：如果 fine-tune 後模型不會聊天、只會答自己 domain 問題、就是 forgetting 過頭</li>
<li><strong>Iterative fine-tune 風險疊加</strong>：在 fine-tuned 模型上再 fine-tune（如 SFT → DPO）、forgetting 風險加倍、要小心評估</li>
<li><strong>Reasoning 能力特別容易 forget</strong>：reasoning 是後期訓練的、fine-tune 一輪 SFT 容易破壞、reasoning model 不建議再 fine-tune</li>
</ol>
]]></content:encoded></item><item><title>Causal Mask</title><link>https://tarrragon.github.io/blog/llm/knowledge-cards/causal-mask/</link><pubDate>Tue, 12 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/llm/knowledge-cards/causal-mask/</guid><description>&lt;p>Causal mask（因果遮罩）的核心概念是「在 &lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/self-attention/" data-link-title="Self-Attention" data-link-desc="Q / K / V 都從同一個 sequence 投影出來的 attention、Transformer 的標誌性設計">self-attention&lt;/a> 計算時、把 token i 看 token j (j &amp;gt; i) 的 attention 分數設成 -∞、&lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/softmax/" data-link-title="Softmax" data-link-desc="把任意實數向量正規化成「總和為 1、每個分量 ∈ [0,1]」的機率分佈">softmax&lt;/a> 後機率為 0」。直覺：LLM 是 &lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/autoregressive/" data-link-title="Autoregressive" data-link-desc="LLM 一次生成一個 token、把已生成內容作為下一次輸入的架構">autoregressive&lt;/a> 的、生成 token N 時不能看到 N+1 以後（後面還沒生）、causal mask 強制這個約束、是 decoder-only Transformer 的標誌。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>Causal mask 在 attention 計算中的位置：&lt;/p>





&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-text" data-lang="text">&lt;span class="line">&lt;span class="ln"> 1&lt;/span>&lt;span class="cl">score = Q @ K^T / sqrt(d) ← shape (seq_len, seq_len)、每對 token 一個分數
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 2&lt;/span>&lt;span class="cl">score = score + causal_mask ← 加上 mask
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 3&lt;/span>&lt;span class="cl">attention = softmax(score) @ V
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 4&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 5&lt;/span>&lt;span class="cl">causal_mask 長這樣（lower triangular、上三角全是 -∞）：
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 6&lt;/span>&lt;span class="cl"> K_0 K_1 K_2 K_3
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 7&lt;/span>&lt;span class="cl">Q_0 [ 0 -∞ -∞ -∞ ] ← token 0 只能看自己
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 8&lt;/span>&lt;span class="cl">Q_1 [ 0 0 -∞ -∞ ] ← token 1 能看 0~1
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 9&lt;/span>&lt;span class="cl">Q_2 [ 0 0 0 -∞ ]
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">10&lt;/span>&lt;span class="cl">Q_3 [ 0 0 0 0 ]&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>關鍵特性：&lt;/p>
&lt;ol>
&lt;li>&lt;strong>訓練時並行有效&lt;/strong>：所有 token 同時跑 forward pass、causal mask 確保每個 token 只看到該看的範圍。沒 mask 就會「偷看未來」、訓出 cheating 模型。&lt;/li>
&lt;li>&lt;strong>推論時自動成立&lt;/strong>：自回歸生成本來就是一個一個生、後面不存在、mask 是隱式的。&lt;/li>
&lt;li>&lt;strong>跟 &lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/kv-cache/" data-link-title="KV Cache" data-link-desc="已處理 token 的 attention 中間結果暫存：避免重算、加速後續生成">KV cache&lt;/a> 結合&lt;/strong>：推論時 cache 只存「過去」的 K/V、causal mask 自然滿足。&lt;/li>
&lt;/ol>
&lt;p>跟其他 attention 變體的關係：&lt;/p>
&lt;table>
 &lt;thead>
 &lt;tr>
 &lt;th>架構&lt;/th>
 &lt;th>是否用 causal mask&lt;/th>
 &lt;/tr>
 &lt;/thead>
 &lt;tbody>
 &lt;tr>
 &lt;td>Decoder-only LLM（GPT / Llama / Gemma）&lt;/td>
 &lt;td>用、是標配&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>Encoder-only（BERT）&lt;/td>
 &lt;td>不用、可以看雙向 context&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>Encoder-decoder（T5）&lt;/td>
 &lt;td>Decoder 部分用、Encoder 部分不用&lt;/td>
 &lt;/tr>
 &lt;/tbody>
&lt;/table>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>讀 paper / model card 看到「causal」「decoder-only」「auto-regressive」這幾組詞、就是這個機制。實務上、寫 code 場景的所有主流 LLM 都用 causal mask、所以這個概念是隱式 default、不會主動暴露給使用者；但理解它能解釋為什麼 LLM 是「接龍」、為什麼 &lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/context-window/" data-link-title="Context Window" data-link-desc="模型一次能處理的最大 token 數量：prompt 加生成的總和上限">bidirectional context&lt;/a> 在 LLM 裡不存在（要 bidirectional 要用 encoder 架構）。&lt;/p></description><content:encoded><![CDATA[<p>Causal mask（因果遮罩）的核心概念是「在 <a href="/blog/llm/knowledge-cards/self-attention/" data-link-title="Self-Attention" data-link-desc="Q / K / V 都從同一個 sequence 投影出來的 attention、Transformer 的標誌性設計">self-attention</a> 計算時、把 token i 看 token j (j &gt; i) 的 attention 分數設成 -∞、<a href="/blog/llm/knowledge-cards/softmax/" data-link-title="Softmax" data-link-desc="把任意實數向量正規化成「總和為 1、每個分量 ∈ [0,1]」的機率分佈">softmax</a> 後機率為 0」。直覺：LLM 是 <a href="/blog/llm/knowledge-cards/autoregressive/" data-link-title="Autoregressive" data-link-desc="LLM 一次生成一個 token、把已生成內容作為下一次輸入的架構">autoregressive</a> 的、生成 token N 時不能看到 N+1 以後（後面還沒生）、causal mask 強制這個約束、是 decoder-only Transformer 的標誌。</p>
<h2 id="概念位置">概念位置</h2>
<p>Causal mask 在 attention 計算中的位置：</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="ln"> 1</span><span class="cl">score = Q @ K^T / sqrt(d)     ← shape (seq_len, seq_len)、每對 token 一個分數
</span></span><span class="line"><span class="ln"> 2</span><span class="cl">score = score + causal_mask   ← 加上 mask
</span></span><span class="line"><span class="ln"> 3</span><span class="cl">attention = softmax(score) @ V
</span></span><span class="line"><span class="ln"> 4</span><span class="cl">
</span></span><span class="line"><span class="ln"> 5</span><span class="cl">causal_mask 長這樣（lower triangular、上三角全是 -∞）：
</span></span><span class="line"><span class="ln"> 6</span><span class="cl">        K_0    K_1    K_2    K_3
</span></span><span class="line"><span class="ln"> 7</span><span class="cl">Q_0   [  0    -∞     -∞     -∞ ]   ← token 0 只能看自己
</span></span><span class="line"><span class="ln"> 8</span><span class="cl">Q_1   [  0     0     -∞     -∞ ]   ← token 1 能看 0~1
</span></span><span class="line"><span class="ln"> 9</span><span class="cl">Q_2   [  0     0      0     -∞ ]
</span></span><span class="line"><span class="ln">10</span><span class="cl">Q_3   [  0     0      0      0 ]</span></span></code></pre></div><p>關鍵特性：</p>
<ol>
<li><strong>訓練時並行有效</strong>：所有 token 同時跑 forward pass、causal mask 確保每個 token 只看到該看的範圍。沒 mask 就會「偷看未來」、訓出 cheating 模型。</li>
<li><strong>推論時自動成立</strong>：自回歸生成本來就是一個一個生、後面不存在、mask 是隱式的。</li>
<li><strong>跟 <a href="/blog/llm/knowledge-cards/kv-cache/" data-link-title="KV Cache" data-link-desc="已處理 token 的 attention 中間結果暫存：避免重算、加速後續生成">KV cache</a> 結合</strong>：推論時 cache 只存「過去」的 K/V、causal mask 自然滿足。</li>
</ol>
<p>跟其他 attention 變體的關係：</p>
<table>
  <thead>
      <tr>
          <th>架構</th>
          <th>是否用 causal mask</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>Decoder-only LLM（GPT / Llama / Gemma）</td>
          <td>用、是標配</td>
      </tr>
      <tr>
          <td>Encoder-only（BERT）</td>
          <td>不用、可以看雙向 context</td>
      </tr>
      <tr>
          <td>Encoder-decoder（T5）</td>
          <td>Decoder 部分用、Encoder 部分不用</td>
      </tr>
  </tbody>
</table>
<h2 id="設計責任">設計責任</h2>
<p>讀 paper / model card 看到「causal」「decoder-only」「auto-regressive」這幾組詞、就是這個機制。實務上、寫 code 場景的所有主流 LLM 都用 causal mask、所以這個概念是隱式 default、不會主動暴露給使用者；但理解它能解釋為什麼 LLM 是「接龍」、為什麼 <a href="/blog/llm/knowledge-cards/context-window/" data-link-title="Context Window" data-link-desc="模型一次能處理的最大 token 數量：prompt 加生成的總和上限">bidirectional context</a> 在 LLM 裡不存在（要 bidirectional 要用 encoder 架構）。</p>
]]></content:encoded></item><item><title>Chain-of-Thought（CoT）</title><link>https://tarrragon.github.io/blog/llm/knowledge-cards/chain-of-thought/</link><pubDate>Tue, 12 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/llm/knowledge-cards/chain-of-thought/</guid><description>&lt;p>Chain-of-Thought（CoT、思維鏈、Wei et al., 2022）的核心概念是「&lt;strong>讓 LLM 先輸出一連串中間推理步驟、再給最終答案&lt;/strong>」、不是直接從問題跳到結論。CoT 是 reasoning model 的基礎機制；prompting 形式（few-shot 提示）跟訓練形式（reasoning RLHF / RL）兩條路都圍繞它演化。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>CoT 的兩種觸發方式：&lt;/p>





&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-text" data-lang="text">&lt;span class="line">&lt;span class="ln">1&lt;/span>&lt;span class="cl">直接回答：
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">2&lt;/span>&lt;span class="cl"> Q: 23 × 47 = ?
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">3&lt;/span>&lt;span class="cl"> A: 1081
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">4&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">5&lt;/span>&lt;span class="cl">Chain-of-Thought：
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">6&lt;/span>&lt;span class="cl"> Q: 23 × 47 = ?
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">7&lt;/span>&lt;span class="cl"> A: 先算 20 × 47 = 940、再算 3 × 47 = 141、加起來 940 + 141 = 1081。
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">8&lt;/span>&lt;span class="cl"> 答案：1081&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>CoT 在 LLM 演化中的兩個階段：&lt;/p>
&lt;table>
 &lt;thead>
 &lt;tr>
 &lt;th>階段&lt;/th>
 &lt;th>觸發方式&lt;/th>
 &lt;th>代表模型 / 技術&lt;/th>
 &lt;/tr>
 &lt;/thead>
 &lt;tbody>
 &lt;tr>
 &lt;td>Prompting CoT&lt;/td>
 &lt;td>Few-shot 提示「請逐步思考」或「let&amp;rsquo;s think step by step」&lt;/td>
 &lt;td>GPT-3、PaLM、早期 instruct 模型&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>Training CoT&lt;/td>
 &lt;td>訓練資料含大量 reasoning trace、模型學會「自然」用 CoT&lt;/td>
 &lt;td>GPT-4、Claude 3.5、Gemini Pro&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>Reasoning RL&lt;/td>
 &lt;td>RL 階段獎勵「正確答案的長 reasoning trace」、模型學會用更長 CoT&lt;/td>
 &lt;td>DeepSeek-R1、o1 / o3、Qwen-QwQ、Claude 3.7 Sonnet thinking&lt;/td>
 &lt;/tr>
 &lt;/tbody>
&lt;/table>
&lt;p>第三階段的特性：模型自己決定「該想多久」（&lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/test-time-compute/" data-link-title="Test-Time Compute" data-link-desc="推論時動態增加計算量換取答案品質的 paradigm、reasoning model 跟 best-of-N 的共同基底">test-time compute&lt;/a> 動態擴展）、推理 trace 可達數千 token、最終答案才是少數 token。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>讀 prompt engineering / paper 看到「CoT」「step by step」「reasoning trace」「thinking」等就是這個機制。寫 code 場景的判讀：&lt;/p>
&lt;ol>
&lt;li>&lt;strong>複雜推理任務開 CoT 通常有幫助&lt;/strong>（math、debug、algorithm design）— 即使是 instruct model 也能透過 prompting 觸發&lt;/li>
&lt;li>&lt;strong>簡單任務 CoT 浪費 token&lt;/strong>（autocomplete、單行查詢、純查表）&lt;/li>
&lt;li>&lt;strong>Reasoning model 的 CoT 是內建行為&lt;/strong>、不需要用 prompt 觸發、但 reasoning trace 會消耗大量 &lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/token/" data-link-title="Token" data-link-desc="LLM 處理文字時的最小單位：介於字元與單字之間">token&lt;/a>（推論時間、context、API 成本都翻倍）&lt;/li>
&lt;li>&lt;strong>本地跑 reasoning model&lt;/strong>：DeepSeek-R1 distill 系列、Qwen-QwQ 等可本地跑、但需要較大 &lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/context-window/" data-link-title="Context Window" data-link-desc="模型一次能處理的最大 token 數量：prompt 加生成的總和上限">context window&lt;/a> 容納 reasoning trace&lt;/li>
&lt;/ol></description><content:encoded><![CDATA[<p>Chain-of-Thought（CoT、思維鏈、Wei et al., 2022）的核心概念是「<strong>讓 LLM 先輸出一連串中間推理步驟、再給最終答案</strong>」、不是直接從問題跳到結論。CoT 是 reasoning model 的基礎機制；prompting 形式（few-shot 提示）跟訓練形式（reasoning RLHF / RL）兩條路都圍繞它演化。</p>
<h2 id="概念位置">概念位置</h2>
<p>CoT 的兩種觸發方式：</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="ln">1</span><span class="cl">直接回答：
</span></span><span class="line"><span class="ln">2</span><span class="cl">  Q: 23 × 47 = ?
</span></span><span class="line"><span class="ln">3</span><span class="cl">  A: 1081
</span></span><span class="line"><span class="ln">4</span><span class="cl">
</span></span><span class="line"><span class="ln">5</span><span class="cl">Chain-of-Thought：
</span></span><span class="line"><span class="ln">6</span><span class="cl">  Q: 23 × 47 = ?
</span></span><span class="line"><span class="ln">7</span><span class="cl">  A: 先算 20 × 47 = 940、再算 3 × 47 = 141、加起來 940 + 141 = 1081。
</span></span><span class="line"><span class="ln">8</span><span class="cl">     答案：1081</span></span></code></pre></div><p>CoT 在 LLM 演化中的兩個階段：</p>
<table>
  <thead>
      <tr>
          <th>階段</th>
          <th>觸發方式</th>
          <th>代表模型 / 技術</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>Prompting CoT</td>
          <td>Few-shot 提示「請逐步思考」或「let&rsquo;s think step by step」</td>
          <td>GPT-3、PaLM、早期 instruct 模型</td>
      </tr>
      <tr>
          <td>Training CoT</td>
          <td>訓練資料含大量 reasoning trace、模型學會「自然」用 CoT</td>
          <td>GPT-4、Claude 3.5、Gemini Pro</td>
      </tr>
      <tr>
          <td>Reasoning RL</td>
          <td>RL 階段獎勵「正確答案的長 reasoning trace」、模型學會用更長 CoT</td>
          <td>DeepSeek-R1、o1 / o3、Qwen-QwQ、Claude 3.7 Sonnet thinking</td>
      </tr>
  </tbody>
</table>
<p>第三階段的特性：模型自己決定「該想多久」（<a href="/blog/llm/knowledge-cards/test-time-compute/" data-link-title="Test-Time Compute" data-link-desc="推論時動態增加計算量換取答案品質的 paradigm、reasoning model 跟 best-of-N 的共同基底">test-time compute</a> 動態擴展）、推理 trace 可達數千 token、最終答案才是少數 token。</p>
<h2 id="設計責任">設計責任</h2>
<p>讀 prompt engineering / paper 看到「CoT」「step by step」「reasoning trace」「thinking」等就是這個機制。寫 code 場景的判讀：</p>
<ol>
<li><strong>複雜推理任務開 CoT 通常有幫助</strong>（math、debug、algorithm design）— 即使是 instruct model 也能透過 prompting 觸發</li>
<li><strong>簡單任務 CoT 浪費 token</strong>（autocomplete、單行查詢、純查表）</li>
<li><strong>Reasoning model 的 CoT 是內建行為</strong>、不需要用 prompt 觸發、但 reasoning trace 會消耗大量 <a href="/blog/llm/knowledge-cards/token/" data-link-title="Token" data-link-desc="LLM 處理文字時的最小單位：介於字元與單字之間">token</a>（推論時間、context、API 成本都翻倍）</li>
<li><strong>本地跑 reasoning model</strong>：DeepSeek-R1 distill 系列、Qwen-QwQ 等可本地跑、但需要較大 <a href="/blog/llm/knowledge-cards/context-window/" data-link-title="Context Window" data-link-desc="模型一次能處理的最大 token 數量：prompt 加生成的總和上限">context window</a> 容納 reasoning trace</li>
</ol>
]]></content:encoded></item><item><title>Chunking</title><link>https://tarrragon.github.io/blog/llm/knowledge-cards/chunking/</link><pubDate>Tue, 12 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/llm/knowledge-cards/chunking/</guid><description>&lt;p>Chunking 的核心概念是「把長文件切成可被 retrieval 系統獨立檢索的片段」。是 &lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/rag/" data-link-title="RAG" data-link-desc="Retrieval-Augmented Generation：動態外掛知識給 LLM、繞開模型參數記憶的靜態限制">RAG&lt;/a> 系統的關鍵設計決策——chunk 太小、retrieval 拿到的 fragment 缺脈絡；太大、retrieval 精確度低且浪費 &lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/context-window/" data-link-title="Context Window" data-link-desc="模型一次能處理的最大 token 數量：prompt 加生成的總和上限">context window&lt;/a>。「resolution vs context loss」是無法兩全的設計取捨。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>Chunking 介於 corpus 跟 &lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/embedding-model/" data-link-title="Embedding Model" data-link-desc="把文字轉成向量的模型：用於 codebase 索引與語意搜尋">embedding model&lt;/a> 之間、決定 embedding 的單位。同一份 corpus 不同 chunking 策略產出不同 index、retrieval 行為完全不同。Chunk 邊界也決定 retrieval 命中後給 LLM 的 context 邊界——chunk 邊界穿過語意單位、會把連貫資訊切散。&lt;/p>
&lt;h2 id="可觀察訊號與例子">可觀察訊號與例子&lt;/h2>
&lt;table>
 &lt;thead>
 &lt;tr>
 &lt;th>Chunk 大小&lt;/th>
 &lt;th>典型 token 數&lt;/th>
 &lt;th>適合場景&lt;/th>
 &lt;/tr>
 &lt;/thead>
 &lt;tbody>
 &lt;tr>
 &lt;td>細粒度&lt;/td>
 &lt;td>100-300&lt;/td>
 &lt;td>精確問答（單句答案）&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>中粒度&lt;/td>
 &lt;td>400-800&lt;/td>
 &lt;td>一般 RAG 主流&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>粗粒度&lt;/td>
 &lt;td>1500-3000&lt;/td>
 &lt;td>摘要任務、需要長段脈絡&lt;/td>
 &lt;/tr>
 &lt;/tbody>
&lt;/table>
&lt;p>切法策略：&lt;/p>
&lt;ul>
&lt;li>&lt;strong>固定 token 數&lt;/strong>：簡單但易切過句子 / 段落中間。&lt;/li>
&lt;li>&lt;strong>段落感知&lt;/strong>：用空白行切、保留段落完整。&lt;/li>
&lt;li>&lt;strong>語意 chunking&lt;/strong>：用 LLM / embedding 找語意邊界。&lt;/li>
&lt;li>&lt;strong>結構化文件&lt;/strong>：按 heading / section 切（markdown、code）。&lt;/li>
&lt;/ul>
&lt;p>跨 chunk 重複（overlap）：相鄰 chunk 留 10-20% 重疊、避免邊界訊號丟失。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>Chunking 之前要回答四個問題：&lt;/p>
&lt;ol>
&lt;li>&lt;strong>任務類型&lt;/strong>：問答 / 摘要 / 探索性搜尋？決定 chunk 大小 baseline。&lt;/li>
&lt;li>&lt;strong>文件結構&lt;/strong>：純文字 / markdown / code？決定切割 strategy。&lt;/li>
&lt;li>&lt;strong>語言混合&lt;/strong>：中文跟英文 token 比例不同、char-based heuristic 可能不準。&lt;/li>
&lt;li>&lt;strong>Embedding model 能力&lt;/strong>：太短 / 太長 chunk 都會降低 embedding 品質。&lt;/li>
&lt;/ol>
&lt;p>寫 code 場景的實作範例見 &lt;a href="https://tarrragon.github.io/blog/llm/01-local-llm-services/hands-on/rag-demo/" data-link-title="Hands-on：用 blog content 當 corpus 跑 RAG" data-link-desc="200 行 Python：embedding &amp;#43; cosine retrieval &amp;#43; Ollama chat、validating 4.0 RAG 原理">RAG demo hands-on&lt;/a> 的 &lt;code>slice_markdown&lt;/code> function、設計取捨展開見 &lt;a href="https://tarrragon.github.io/blog/llm/04-applications/rag-principles/" data-link-title="4.1 RAG 原理：retrieval &amp;#43; augmentation 模式" data-link-desc="為什麼模型需要外掛知識、語意相似 vs 字面相似、chunking 的本質取捨、retrieval 失敗的根本原因">4.1 RAG 原理&lt;/a> 的「Chunking 的本質取捨」段。&lt;/p></description><content:encoded><![CDATA[<p>Chunking 的核心概念是「把長文件切成可被 retrieval 系統獨立檢索的片段」。是 <a href="/blog/llm/knowledge-cards/rag/" data-link-title="RAG" data-link-desc="Retrieval-Augmented Generation：動態外掛知識給 LLM、繞開模型參數記憶的靜態限制">RAG</a> 系統的關鍵設計決策——chunk 太小、retrieval 拿到的 fragment 缺脈絡；太大、retrieval 精確度低且浪費 <a href="/blog/llm/knowledge-cards/context-window/" data-link-title="Context Window" data-link-desc="模型一次能處理的最大 token 數量：prompt 加生成的總和上限">context window</a>。「resolution vs context loss」是無法兩全的設計取捨。</p>
<h2 id="概念位置">概念位置</h2>
<p>Chunking 介於 corpus 跟 <a href="/blog/llm/knowledge-cards/embedding-model/" data-link-title="Embedding Model" data-link-desc="把文字轉成向量的模型：用於 codebase 索引與語意搜尋">embedding model</a> 之間、決定 embedding 的單位。同一份 corpus 不同 chunking 策略產出不同 index、retrieval 行為完全不同。Chunk 邊界也決定 retrieval 命中後給 LLM 的 context 邊界——chunk 邊界穿過語意單位、會把連貫資訊切散。</p>
<h2 id="可觀察訊號與例子">可觀察訊號與例子</h2>
<table>
  <thead>
      <tr>
          <th>Chunk 大小</th>
          <th>典型 token 數</th>
          <th>適合場景</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>細粒度</td>
          <td>100-300</td>
          <td>精確問答（單句答案）</td>
      </tr>
      <tr>
          <td>中粒度</td>
          <td>400-800</td>
          <td>一般 RAG 主流</td>
      </tr>
      <tr>
          <td>粗粒度</td>
          <td>1500-3000</td>
          <td>摘要任務、需要長段脈絡</td>
      </tr>
  </tbody>
</table>
<p>切法策略：</p>
<ul>
<li><strong>固定 token 數</strong>：簡單但易切過句子 / 段落中間。</li>
<li><strong>段落感知</strong>：用空白行切、保留段落完整。</li>
<li><strong>語意 chunking</strong>：用 LLM / embedding 找語意邊界。</li>
<li><strong>結構化文件</strong>：按 heading / section 切（markdown、code）。</li>
</ul>
<p>跨 chunk 重複（overlap）：相鄰 chunk 留 10-20% 重疊、避免邊界訊號丟失。</p>
<h2 id="設計責任">設計責任</h2>
<p>Chunking 之前要回答四個問題：</p>
<ol>
<li><strong>任務類型</strong>：問答 / 摘要 / 探索性搜尋？決定 chunk 大小 baseline。</li>
<li><strong>文件結構</strong>：純文字 / markdown / code？決定切割 strategy。</li>
<li><strong>語言混合</strong>：中文跟英文 token 比例不同、char-based heuristic 可能不準。</li>
<li><strong>Embedding model 能力</strong>：太短 / 太長 chunk 都會降低 embedding 品質。</li>
</ol>
<p>寫 code 場景的實作範例見 <a href="/blog/llm/01-local-llm-services/hands-on/rag-demo/" data-link-title="Hands-on：用 blog content 當 corpus 跑 RAG" data-link-desc="200 行 Python：embedding &#43; cosine retrieval &#43; Ollama chat、validating 4.0 RAG 原理">RAG demo hands-on</a> 的 <code>slice_markdown</code> function、設計取捨展開見 <a href="/blog/llm/04-applications/rag-principles/" data-link-title="4.1 RAG 原理：retrieval &#43; augmentation 模式" data-link-desc="為什麼模型需要外掛知識、語意相似 vs 字面相似、chunking 的本質取捨、retrieval 失敗的根本原因">4.1 RAG 原理</a> 的「Chunking 的本質取捨」段。</p>
]]></content:encoded></item><item><title>Client-Side LLM / Embedding</title><link>https://tarrragon.github.io/blog/llm/knowledge-cards/client-side-llm/</link><pubDate>Tue, 12 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/llm/knowledge-cards/client-side-llm/</guid><description>&lt;p>Client-side LLM / embedding 的核心概念是「&lt;strong>模型權重下載到使用者瀏覽器、用 WebGPU 或 WebAssembly 直接在 browser 內推論、不經過任何 server&lt;/strong>」。代表 runtime：WebLLM（MLC AI、用 WebGPU）、wllama（llama.cpp 的 WebAssembly port）、&lt;code>@xenova/transformers&lt;/code>（瀏覽器版 transformers）。是「靜態網站做 RAG」、「離線可用 LLM 應用」這類場景的關鍵基底。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>跟其他 LLM deployment 形態的對比：&lt;/p>
&lt;table>
 &lt;thead>
 &lt;tr>
 &lt;th>形態&lt;/th>
 &lt;th>模型權重位置&lt;/th>
 &lt;th>推論執行位置&lt;/th>
 &lt;th>隱私&lt;/th>
 &lt;th>適合&lt;/th>
 &lt;/tr>
 &lt;/thead>
 &lt;tbody>
 &lt;tr>
 &lt;td>雲端 LLM API&lt;/td>
 &lt;td>雲端伺服器&lt;/td>
 &lt;td>雲端&lt;/td>
 &lt;td>視 vendor 政策&lt;/td>
 &lt;td>高品質、production&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>本地 &lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/inference-server/" data-link-title="Inference Server" data-link-desc="載入模型權重、處理 prompt、產生 token 的常駐 process">推論伺服器&lt;/a>&lt;/td>
 &lt;td>本機磁碟&lt;/td>
 &lt;td>本機 process&lt;/td>
 &lt;td>完全本地&lt;/td>
 &lt;td>寫 code、個人 dev&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;strong>Client-side LLM&lt;/strong>&lt;/td>
 &lt;td>使用者 browser cache&lt;/td>
 &lt;td>使用者 browser&lt;/td>
 &lt;td>完全本地（不經 server）&lt;/td>
 &lt;td>靜態網站、demo、離線&lt;/td>
 &lt;/tr>
 &lt;/tbody>
&lt;/table>
&lt;p>主流 client-side runtime（2026/5）：&lt;/p>
&lt;table>
 &lt;thead>
 &lt;tr>
 &lt;th>Runtime&lt;/th>
 &lt;th>機制&lt;/th>
 &lt;th>模型支援&lt;/th>
 &lt;th>典型體積&lt;/th>
 &lt;/tr>
 &lt;/thead>
 &lt;tbody>
 &lt;tr>
 &lt;td>&lt;code>@xenova/transformers&lt;/code>&lt;/td>
 &lt;td>WASM、ONNX 格式&lt;/td>
 &lt;td>sentence-transformers、小型 LLM、CLIP、embedding&lt;/td>
 &lt;td>&amp;lt; 100 MB / 模型&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>WebLLM（MLC）&lt;/td>
 &lt;td>WebGPU、自家 MLC compiled&lt;/td>
 &lt;td>Llama / Qwen / Gemma / Phi 等 1-13B&lt;/td>
 &lt;td>1-8 GB / 模型&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>wllama&lt;/td>
 &lt;td>WASM、llama.cpp 編譯版&lt;/td>
 &lt;td>GGUF Q4 等量化模型、&amp;lt; 4B 為主&lt;/td>
 &lt;td>0.5-4 GB / 模型&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;code>transformers.js&lt;/code>&lt;/td>
 &lt;td>WASM、跟 &lt;code>@xenova/transformers&lt;/code> 同源&lt;/td>
 &lt;td>同上&lt;/td>
 &lt;td>同上&lt;/td>
 &lt;/tr>
 &lt;/tbody>
&lt;/table>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>讀靜態網站 / 前端 RAG / 離線 LLM 教學看到「WebGPU LLM」「browser-side embedding」「offline LLM」就是這 paradigm。寫 code 場景的判讀：&lt;/p>
&lt;ol>
&lt;li>&lt;strong>首訪載入慢&lt;/strong>：browser 第一次要下載模型權重（embedding 模型 ~50MB、LLM 1-5GB）、首訪體驗差；後續訪問 cache 起來、變快&lt;/li>
&lt;li>&lt;strong>WebGPU 支援度&lt;/strong>：2026/5 仍非所有 browser / 裝置都穩定支援、Safari iOS 較弱；fallback 到 WASM 但速度降一個量級&lt;/li>
&lt;li>&lt;strong>模型完整性沒簽章&lt;/strong>：使用者下載到的模型權重沒類似 &lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/model-card/" data-link-title="Model Card" data-link-desc="Hugging Face 等平台上模型的 metadata 文件、列出模型來源、訓練資料、能力、限制、授權">GGUF model card&lt;/a> 的官方驗證、要靠 CDN + HTTPS 信任、不像本地 Ollama 有 hash 比對&lt;/li>
&lt;li>&lt;strong>適合「embedding + 小 LLM」、不適合「30B reasoning」&lt;/strong>：browser 記憶體跟 WebGPU 算力都遠不如本地 Ollama、選 &amp;lt; 4B 模型較實際&lt;/li>
&lt;li>&lt;strong>跟資安的關係&lt;/strong>：client-side 不需要 server API key、隱私強；但模型分發鏈（CDN → browser）成為新的供應鏈面、見 &lt;a href="https://tarrragon.github.io/blog/llm/04-applications/static-and-serverless-rag-deployment/" data-link-title="4.16 靜態 / serverless RAG deployment：架構選擇與資安取捨" data-link-desc="沒 backend 的場景怎麼做 RAG：四種 deployment 方案、API key 暴露問題、CORS / abuse / 第三方信任、跟模組六的 routing">4.16 靜態 RAG deployment&lt;/a> 的資安段&lt;/li>
&lt;/ol></description><content:encoded><![CDATA[<p>Client-side LLM / embedding 的核心概念是「<strong>模型權重下載到使用者瀏覽器、用 WebGPU 或 WebAssembly 直接在 browser 內推論、不經過任何 server</strong>」。代表 runtime：WebLLM（MLC AI、用 WebGPU）、wllama（llama.cpp 的 WebAssembly port）、<code>@xenova/transformers</code>（瀏覽器版 transformers）。是「靜態網站做 RAG」、「離線可用 LLM 應用」這類場景的關鍵基底。</p>
<h2 id="概念位置">概念位置</h2>
<p>跟其他 LLM deployment 形態的對比：</p>
<table>
  <thead>
      <tr>
          <th>形態</th>
          <th>模型權重位置</th>
          <th>推論執行位置</th>
          <th>隱私</th>
          <th>適合</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>雲端 LLM API</td>
          <td>雲端伺服器</td>
          <td>雲端</td>
          <td>視 vendor 政策</td>
          <td>高品質、production</td>
      </tr>
      <tr>
          <td>本地 <a href="/blog/llm/knowledge-cards/inference-server/" data-link-title="Inference Server" data-link-desc="載入模型權重、處理 prompt、產生 token 的常駐 process">推論伺服器</a></td>
          <td>本機磁碟</td>
          <td>本機 process</td>
          <td>完全本地</td>
          <td>寫 code、個人 dev</td>
      </tr>
      <tr>
          <td><strong>Client-side LLM</strong></td>
          <td>使用者 browser cache</td>
          <td>使用者 browser</td>
          <td>完全本地（不經 server）</td>
          <td>靜態網站、demo、離線</td>
      </tr>
  </tbody>
</table>
<p>主流 client-side runtime（2026/5）：</p>
<table>
  <thead>
      <tr>
          <th>Runtime</th>
          <th>機制</th>
          <th>模型支援</th>
          <th>典型體積</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td><code>@xenova/transformers</code></td>
          <td>WASM、ONNX 格式</td>
          <td>sentence-transformers、小型 LLM、CLIP、embedding</td>
          <td>&lt; 100 MB / 模型</td>
      </tr>
      <tr>
          <td>WebLLM（MLC）</td>
          <td>WebGPU、自家 MLC compiled</td>
          <td>Llama / Qwen / Gemma / Phi 等 1-13B</td>
          <td>1-8 GB / 模型</td>
      </tr>
      <tr>
          <td>wllama</td>
          <td>WASM、llama.cpp 編譯版</td>
          <td>GGUF Q4 等量化模型、&lt; 4B 為主</td>
          <td>0.5-4 GB / 模型</td>
      </tr>
      <tr>
          <td><code>transformers.js</code></td>
          <td>WASM、跟 <code>@xenova/transformers</code> 同源</td>
          <td>同上</td>
          <td>同上</td>
      </tr>
  </tbody>
</table>
<h2 id="設計責任">設計責任</h2>
<p>讀靜態網站 / 前端 RAG / 離線 LLM 教學看到「WebGPU LLM」「browser-side embedding」「offline LLM」就是這 paradigm。寫 code 場景的判讀：</p>
<ol>
<li><strong>首訪載入慢</strong>：browser 第一次要下載模型權重（embedding 模型 ~50MB、LLM 1-5GB）、首訪體驗差；後續訪問 cache 起來、變快</li>
<li><strong>WebGPU 支援度</strong>：2026/5 仍非所有 browser / 裝置都穩定支援、Safari iOS 較弱；fallback 到 WASM 但速度降一個量級</li>
<li><strong>模型完整性沒簽章</strong>：使用者下載到的模型權重沒類似 <a href="/blog/llm/knowledge-cards/model-card/" data-link-title="Model Card" data-link-desc="Hugging Face 等平台上模型的 metadata 文件、列出模型來源、訓練資料、能力、限制、授權">GGUF model card</a> 的官方驗證、要靠 CDN + HTTPS 信任、不像本地 Ollama 有 hash 比對</li>
<li><strong>適合「embedding + 小 LLM」、不適合「30B reasoning」</strong>：browser 記憶體跟 WebGPU 算力都遠不如本地 Ollama、選 &lt; 4B 模型較實際</li>
<li><strong>跟資安的關係</strong>：client-side 不需要 server API key、隱私強；但模型分發鏈（CDN → browser）成為新的供應鏈面、見 <a href="/blog/llm/04-applications/static-and-serverless-rag-deployment/" data-link-title="4.16 靜態 / serverless RAG deployment：架構選擇與資安取捨" data-link-desc="沒 backend 的場景怎麼做 RAG：四種 deployment 方案、API key 暴露問題、CORS / abuse / 第三方信任、跟模組六的 routing">4.16 靜態 RAG deployment</a> 的資安段</li>
</ol>
]]></content:encoded></item><item><title>CLIP</title><link>https://tarrragon.github.io/blog/llm/knowledge-cards/clip/</link><pubDate>Tue, 12 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/llm/knowledge-cards/clip/</guid><description>&lt;p>CLIP（Contrastive Language-Image Pre-training、Radford et al., 2021）的核心概念是「&lt;strong>用 4 億組 (image, caption) 對、訓 image encoder 跟 text encoder、讓對應圖文的 embedding 在共享空間靠近&lt;/strong>」。CLIP 本身不是 VLM、但它的 image encoder 成為現代幾乎所有 &lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/vlm/" data-link-title="VLM（Vision-Language Model）" data-link-desc="同時吃圖片 &amp;#43; 文字輸入、產生文字輸出的 LLM 變體、coding 工作流中處理截圖 / 設計稿 / UI debug 的基底">VLM&lt;/a> 的 &lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/vision-encoder/" data-link-title="Vision Encoder" data-link-desc="VLM 內部負責把圖片轉成可進 Transformer 的向量序列的模組、ViT / CLIP encoder 為主流">vision encoder&lt;/a> 起點。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>CLIP 的訓練架構（簡化）：&lt;/p>





&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-text" data-lang="text">&lt;span class="line">&lt;span class="ln"> 1&lt;/span>&lt;span class="cl">4 億組 (image, caption) 從網路爬：
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 2&lt;/span>&lt;span class="cl"> (photo of cat, &amp;#34;a fluffy orange cat sitting&amp;#34;)
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 3&lt;/span>&lt;span class="cl"> (screenshot of code, &amp;#34;Python error: NameError x undefined&amp;#34;)
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 4&lt;/span>&lt;span class="cl"> ...
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 5&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 6&lt;/span>&lt;span class="cl">訓練：
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 7&lt;/span>&lt;span class="cl"> image → Image encoder（ViT-L/14）→ image_embedding
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 8&lt;/span>&lt;span class="cl"> caption → Text encoder（Transformer）→ text_embedding
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 9&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">10&lt;/span>&lt;span class="cl"> 正向對（matching image-caption）：embedding 應該相似
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">11&lt;/span>&lt;span class="cl"> 負向對（同 batch 內其他不匹配）：embedding 應該遠
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">12&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">13&lt;/span>&lt;span class="cl"> [Contrastive learning](/llm/knowledge-cards/contrastive-learning/) loss&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>訓完後得到：&lt;/p>
&lt;ol>
&lt;li>&lt;strong>共享 embedding 空間&lt;/strong>：圖跟文字 embedding 都在 768/1024 維空間、相似度比較有意義&lt;/li>
&lt;li>&lt;strong>Zero-shot classification 能力&lt;/strong>：給一張圖、給 100 個文字標籤、看哪個 embedding 最接近 → 不用 fine-tune 就能分類&lt;/li>
&lt;li>&lt;strong>Image search / 多模態 retrieval&lt;/strong>：text 跟 image 互查、是 multimodal RAG 基底&lt;/li>
&lt;/ol>
&lt;p>對 VLM 的影響：&lt;/p>





&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-text" data-lang="text">&lt;span class="line">&lt;span class="ln">1&lt;/span>&lt;span class="cl">CLIP 訓出來後：
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">2&lt;/span>&lt;span class="cl"> image encoder 已經學會「把圖片變成有意義的 embedding」
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">3&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">4&lt;/span>&lt;span class="cl">VLM 訓練時：
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">5&lt;/span>&lt;span class="cl"> - 直接拿 CLIP 的 image encoder 當 vision encoder（凍住或一起 fine-tune）
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">6&lt;/span>&lt;span class="cl"> - 接上 LLM、用 image-text 任務資料訓 alignment
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">7&lt;/span>&lt;span class="cl"> - 不用從頭訓 vision encoder、省下大量 compute&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>跟 SigLIP 的關係：SigLIP（Zhai et al., 2023）是 Google 提出的 CLIP 變體、用 sigmoid loss 取代原本 InfoNCE、訓練更穩、品質略佳；Gemma 3 / Idefics 等用 SigLIP 而非原 CLIP。&lt;/p></description><content:encoded><![CDATA[<p>CLIP（Contrastive Language-Image Pre-training、Radford et al., 2021）的核心概念是「<strong>用 4 億組 (image, caption) 對、訓 image encoder 跟 text encoder、讓對應圖文的 embedding 在共享空間靠近</strong>」。CLIP 本身不是 VLM、但它的 image encoder 成為現代幾乎所有 <a href="/blog/llm/knowledge-cards/vlm/" data-link-title="VLM（Vision-Language Model）" data-link-desc="同時吃圖片 &#43; 文字輸入、產生文字輸出的 LLM 變體、coding 工作流中處理截圖 / 設計稿 / UI debug 的基底">VLM</a> 的 <a href="/blog/llm/knowledge-cards/vision-encoder/" data-link-title="Vision Encoder" data-link-desc="VLM 內部負責把圖片轉成可進 Transformer 的向量序列的模組、ViT / CLIP encoder 為主流">vision encoder</a> 起點。</p>
<h2 id="概念位置">概念位置</h2>
<p>CLIP 的訓練架構（簡化）：</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="ln"> 1</span><span class="cl">4 億組 (image, caption) 從網路爬：
</span></span><span class="line"><span class="ln"> 2</span><span class="cl">  (photo of cat, &#34;a fluffy orange cat sitting&#34;)
</span></span><span class="line"><span class="ln"> 3</span><span class="cl">  (screenshot of code, &#34;Python error: NameError x undefined&#34;)
</span></span><span class="line"><span class="ln"> 4</span><span class="cl">  ...
</span></span><span class="line"><span class="ln"> 5</span><span class="cl">
</span></span><span class="line"><span class="ln"> 6</span><span class="cl">訓練：
</span></span><span class="line"><span class="ln"> 7</span><span class="cl">  image → Image encoder（ViT-L/14）→ image_embedding
</span></span><span class="line"><span class="ln"> 8</span><span class="cl">  caption → Text encoder（Transformer）→ text_embedding
</span></span><span class="line"><span class="ln"> 9</span><span class="cl">
</span></span><span class="line"><span class="ln">10</span><span class="cl">  正向對（matching image-caption）：embedding 應該相似
</span></span><span class="line"><span class="ln">11</span><span class="cl">  負向對（同 batch 內其他不匹配）：embedding 應該遠
</span></span><span class="line"><span class="ln">12</span><span class="cl">
</span></span><span class="line"><span class="ln">13</span><span class="cl">  [Contrastive learning](/llm/knowledge-cards/contrastive-learning/) loss</span></span></code></pre></div><p>訓完後得到：</p>
<ol>
<li><strong>共享 embedding 空間</strong>：圖跟文字 embedding 都在 768/1024 維空間、相似度比較有意義</li>
<li><strong>Zero-shot classification 能力</strong>：給一張圖、給 100 個文字標籤、看哪個 embedding 最接近 → 不用 fine-tune 就能分類</li>
<li><strong>Image search / 多模態 retrieval</strong>：text 跟 image 互查、是 multimodal RAG 基底</li>
</ol>
<p>對 VLM 的影響：</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="ln">1</span><span class="cl">CLIP 訓出來後：
</span></span><span class="line"><span class="ln">2</span><span class="cl">  image encoder 已經學會「把圖片變成有意義的 embedding」
</span></span><span class="line"><span class="ln">3</span><span class="cl">
</span></span><span class="line"><span class="ln">4</span><span class="cl">VLM 訓練時：
</span></span><span class="line"><span class="ln">5</span><span class="cl">  - 直接拿 CLIP 的 image encoder 當 vision encoder（凍住或一起 fine-tune）
</span></span><span class="line"><span class="ln">6</span><span class="cl">  - 接上 LLM、用 image-text 任務資料訓 alignment
</span></span><span class="line"><span class="ln">7</span><span class="cl">  - 不用從頭訓 vision encoder、省下大量 compute</span></span></code></pre></div><p>跟 SigLIP 的關係：SigLIP（Zhai et al., 2023）是 Google 提出的 CLIP 變體、用 sigmoid loss 取代原本 InfoNCE、訓練更穩、品質略佳；Gemma 3 / Idefics 等用 SigLIP 而非原 CLIP。</p>
<h2 id="設計責任">設計責任</h2>
<p>讀 VLM paper / model card 看到「CLIP backbone」「SigLIP encoder」「OpenCLIP weights」就是這 family。寫 code 場景的判讀：</p>
<ol>
<li><strong>CLIP 本身不是 VLM</strong>：CLIP 只有 image-text 相似度、不能生文字回答；VLM 是「CLIP 的 image encoder + LLM + alignment training」</li>
<li><strong>不同 CLIP 變體影響 VLM 能力</strong>：CLIP ViT-L/14 是經典、SigLIP / DFN（Apple）等變體在某些任務更強</li>
<li><strong>Multimodal RAG 直接用 CLIP</strong>：純 image-text retrieval（如「找跟這張圖相似的 doc」）不需要完整 VLM、CLIP-like 模型就夠</li>
<li><strong>CLIP 用於 zero-shot 分類仍實用</strong>：給定固定的 class label set（如「截圖 / 設計稿 / 程式碼 / 文件」）、CLIP 能直接 zero-shot 分類、不需要訓 specific classifier</li>
</ol>
]]></content:encoded></item><item><title>Constrained Decoding</title><link>https://tarrragon.github.io/blog/llm/knowledge-cards/constrained-decoding/</link><pubDate>Tue, 12 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/llm/knowledge-cards/constrained-decoding/</guid><description>&lt;p>Constrained decoding（受限解碼）的核心概念是「&lt;strong>推論時用 grammar 動態算出每個位置的合法 token mask、把不合法 token 的 &lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/logit/" data-link-title="Logit" data-link-desc="softmax 之前的原始實數分數、每個 vocab token 一個值、可正可負">logit&lt;/a> 設成 -∞、&lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/softmax/" data-link-title="Softmax" data-link-desc="把任意實數向量正規化成「總和為 1、每個分量 ∈ [0,1]」的機率分佈">softmax&lt;/a> 後機率為 0&lt;/strong>」。是 &lt;a href="https://tarrragon.github.io/blog/llm/04-applications/application-protocols/" data-link-title="4.6 應用層協議：function calling / structured output / MCP" data-link-desc="三個常被混為一談的概念：模型能力、sampling 約束、server 協議，三者的層級差異與組合方式">structured output&lt;/a>（JSON mode / function calling 的合法性保證）背後的 sampling 機制。代表實作：XGrammar、outlines、lm-format-enforcer、guidance、SGLang。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>跟既有 sampling 概念的層次：&lt;/p>





&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-text" data-lang="text">&lt;span class="line">&lt;span class="ln">1&lt;/span>&lt;span class="cl">模型 forward pass → logits（每個 vocab token 一個分數）
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">2&lt;/span>&lt;span class="cl"> ↓ apply temperature
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">3&lt;/span>&lt;span class="cl"> ↓ apply grammar mask（constrained decoding） ← 本卡聚焦
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">4&lt;/span>&lt;span class="cl"> - 算出當下位置的合法 token 集合
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">5&lt;/span>&lt;span class="cl"> - 不合法 token 的 logit 設 -∞
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">6&lt;/span>&lt;span class="cl"> ↓ softmax → 機率分佈
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">7&lt;/span>&lt;span class="cl"> ↓ sampling（greedy / top-p / top-k）
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">8&lt;/span>&lt;span class="cl"> ↓ next token&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>主要 grammar 類型：&lt;/p>
&lt;table>
 &lt;thead>
 &lt;tr>
 &lt;th>Grammar 類型&lt;/th>
 &lt;th>描述&lt;/th>
 &lt;th>用例&lt;/th>
 &lt;/tr>
 &lt;/thead>
 &lt;tbody>
 &lt;tr>
 &lt;td>JSON Schema&lt;/td>
 &lt;td>標準 JSON schema 定義合法 JSON 結構&lt;/td>
 &lt;td>Function calling、structured output&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>Regex&lt;/td>
 &lt;td>Regular expression&lt;/td>
 &lt;td>受限文字格式（如 phone number、email）&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>CFG（Context-Free Grammar）&lt;/td>
 &lt;td>BNF 等 grammar 描述合法語法&lt;/td>
 &lt;td>Code generation、DSL、SQL&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>Choice list&lt;/td>
 &lt;td>一組固定字串選項&lt;/td>
 &lt;td>Classification、enum 輸出&lt;/td>
 &lt;/tr>
 &lt;/tbody>
&lt;/table>
&lt;p>主流實作對比：&lt;/p>
&lt;table>
 &lt;thead>
 &lt;tr>
 &lt;th>實作&lt;/th>
 &lt;th>機制&lt;/th>
 &lt;th>推論伺服器整合&lt;/th>
 &lt;/tr>
 &lt;/thead>
 &lt;tbody>
 &lt;tr>
 &lt;td>&lt;strong>XGrammar&lt;/strong>&lt;/td>
 &lt;td>Pre-compile grammar → token mask cache、極快&lt;/td>
 &lt;td>vLLM / SGLang / TensorRT-LLM 預設&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>outlines&lt;/td>
 &lt;td>Python lib、JSON schema / regex / CFG&lt;/td>
 &lt;td>用 Transformers / vLLM&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>lm-format-enforcer&lt;/td>
 &lt;td>Lazy compile、適合動態 grammar&lt;/td>
 &lt;td>Hugging Face Transformers&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>guidance&lt;/td>
 &lt;td>Microsoft 系、API 較高階&lt;/td>
 &lt;td>自家 server&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>llama.cpp grammar&lt;/td>
 &lt;td>Built-in GBNF（GGML BNF）&lt;/td>
 &lt;td>llama.cpp 內建&lt;/td>
 &lt;/tr>
 &lt;/tbody>
&lt;/table>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>讀 sampling / structured output / function calling 進階文件看到「constrained decoding」「grammar mask」「JSON schema enforcement」就是這 framing。寫 code 場景的判讀：&lt;/p>
&lt;ol>
&lt;li>&lt;strong>何時值得用&lt;/strong>：需要 100% 合法 JSON / 特定格式、function calling spec 嚴格、structured output 不可有解析錯誤&lt;/li>
&lt;li>&lt;strong>不該用的情況&lt;/strong>：自由 / 創意輸出（會限制模型表達）、grammar 太嚴讓模型「該說的話說不出來」（如 enum 不含「unknown」、模型強制選錯）&lt;/li>
&lt;li>&lt;strong>跟 function calling 的關係&lt;/strong>：function calling 是「模型訓練 + structured output」、constrained decoding 是 sampling 層的工程實作、可獨立組合&lt;/li>
&lt;li>&lt;strong>加速 vs 拖慢&lt;/strong>：常見誤解是 grammar 拖慢 — 實測 XGrammar 等 pre-compiled 實作反而&lt;strong>加速&lt;/strong>生成（跳過 boilerplate token 直接生關鍵 token、節省 forward pass）&lt;/li>
&lt;li>&lt;strong>跟 &lt;a href="https://tarrragon.github.io/blog/llm/03-theoretical-foundations/constrained-decoding-internals/" data-link-title="3.10 Constrained decoding 內部：grammar mask 跟性能取捨" data-link-desc="Constrained decoding 的內部運作：token mask 計算、JSON schema / regex / CFG 三種 grammar、XGrammar pre-compile 機制、性能反而加速">3.10 constrained decoding 章節&lt;/a> 的關係&lt;/strong>：本卡是定義、章節是內部機制（token mask 計算、CFG 編譯、性能取捨）&lt;/li>
&lt;/ol></description><content:encoded><![CDATA[<p>Constrained decoding（受限解碼）的核心概念是「<strong>推論時用 grammar 動態算出每個位置的合法 token mask、把不合法 token 的 <a href="/blog/llm/knowledge-cards/logit/" data-link-title="Logit" data-link-desc="softmax 之前的原始實數分數、每個 vocab token 一個值、可正可負">logit</a> 設成 -∞、<a href="/blog/llm/knowledge-cards/softmax/" data-link-title="Softmax" data-link-desc="把任意實數向量正規化成「總和為 1、每個分量 ∈ [0,1]」的機率分佈">softmax</a> 後機率為 0</strong>」。是 <a href="/blog/llm/04-applications/application-protocols/" data-link-title="4.6 應用層協議：function calling / structured output / MCP" data-link-desc="三個常被混為一談的概念：模型能力、sampling 約束、server 協議，三者的層級差異與組合方式">structured output</a>（JSON mode / function calling 的合法性保證）背後的 sampling 機制。代表實作：XGrammar、outlines、lm-format-enforcer、guidance、SGLang。</p>
<h2 id="概念位置">概念位置</h2>
<p>跟既有 sampling 概念的層次：</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="ln">1</span><span class="cl">模型 forward pass → logits（每個 vocab token 一個分數）
</span></span><span class="line"><span class="ln">2</span><span class="cl">   ↓ apply temperature
</span></span><span class="line"><span class="ln">3</span><span class="cl">   ↓ apply grammar mask（constrained decoding）  ← 本卡聚焦
</span></span><span class="line"><span class="ln">4</span><span class="cl">       - 算出當下位置的合法 token 集合
</span></span><span class="line"><span class="ln">5</span><span class="cl">       - 不合法 token 的 logit 設 -∞
</span></span><span class="line"><span class="ln">6</span><span class="cl">   ↓ softmax → 機率分佈
</span></span><span class="line"><span class="ln">7</span><span class="cl">   ↓ sampling（greedy / top-p / top-k）
</span></span><span class="line"><span class="ln">8</span><span class="cl">   ↓ next token</span></span></code></pre></div><p>主要 grammar 類型：</p>
<table>
  <thead>
      <tr>
          <th>Grammar 類型</th>
          <th>描述</th>
          <th>用例</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>JSON Schema</td>
          <td>標準 JSON schema 定義合法 JSON 結構</td>
          <td>Function calling、structured output</td>
      </tr>
      <tr>
          <td>Regex</td>
          <td>Regular expression</td>
          <td>受限文字格式（如 phone number、email）</td>
      </tr>
      <tr>
          <td>CFG（Context-Free Grammar）</td>
          <td>BNF 等 grammar 描述合法語法</td>
          <td>Code generation、DSL、SQL</td>
      </tr>
      <tr>
          <td>Choice list</td>
          <td>一組固定字串選項</td>
          <td>Classification、enum 輸出</td>
      </tr>
  </tbody>
</table>
<p>主流實作對比：</p>
<table>
  <thead>
      <tr>
          <th>實作</th>
          <th>機制</th>
          <th>推論伺服器整合</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td><strong>XGrammar</strong></td>
          <td>Pre-compile grammar → token mask cache、極快</td>
          <td>vLLM / SGLang / TensorRT-LLM 預設</td>
      </tr>
      <tr>
          <td>outlines</td>
          <td>Python lib、JSON schema / regex / CFG</td>
          <td>用 Transformers / vLLM</td>
      </tr>
      <tr>
          <td>lm-format-enforcer</td>
          <td>Lazy compile、適合動態 grammar</td>
          <td>Hugging Face Transformers</td>
      </tr>
      <tr>
          <td>guidance</td>
          <td>Microsoft 系、API 較高階</td>
          <td>自家 server</td>
      </tr>
      <tr>
          <td>llama.cpp grammar</td>
          <td>Built-in GBNF（GGML BNF）</td>
          <td>llama.cpp 內建</td>
      </tr>
  </tbody>
</table>
<h2 id="設計責任">設計責任</h2>
<p>讀 sampling / structured output / function calling 進階文件看到「constrained decoding」「grammar mask」「JSON schema enforcement」就是這 framing。寫 code 場景的判讀：</p>
<ol>
<li><strong>何時值得用</strong>：需要 100% 合法 JSON / 特定格式、function calling spec 嚴格、structured output 不可有解析錯誤</li>
<li><strong>不該用的情況</strong>：自由 / 創意輸出（會限制模型表達）、grammar 太嚴讓模型「該說的話說不出來」（如 enum 不含「unknown」、模型強制選錯）</li>
<li><strong>跟 function calling 的關係</strong>：function calling 是「模型訓練 + structured output」、constrained decoding 是 sampling 層的工程實作、可獨立組合</li>
<li><strong>加速 vs 拖慢</strong>：常見誤解是 grammar 拖慢 — 實測 XGrammar 等 pre-compiled 實作反而<strong>加速</strong>生成（跳過 boilerplate token 直接生關鍵 token、節省 forward pass）</li>
<li><strong>跟 <a href="/blog/llm/03-theoretical-foundations/constrained-decoding-internals/" data-link-title="3.10 Constrained decoding 內部：grammar mask 跟性能取捨" data-link-desc="Constrained decoding 的內部運作：token mask 計算、JSON schema / regex / CFG 三種 grammar、XGrammar pre-compile 機制、性能反而加速">3.10 constrained decoding 章節</a> 的關係</strong>：本卡是定義、章節是內部機制（token mask 計算、CFG 編譯、性能取捨）</li>
</ol>
]]></content:encoded></item><item><title>Context Budget</title><link>https://tarrragon.github.io/blog/llm/knowledge-cards/context-budget/</link><pubDate>Tue, 12 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/llm/knowledge-cards/context-budget/</guid><description>&lt;p>Context budget 的核心概念是「&lt;strong>把 &lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/context-window/" data-link-title="Context Window" data-link-desc="模型一次能處理的最大 token 數量：prompt 加生成的總和上限">context window&lt;/a> 視為有限資源、明確規劃 system prompt / tool schema / history / file content / reasoning trace / tool result 各佔多少&lt;/strong>」。coding agent 的最大失敗模式是「context 用爆 → 模型開始遺忘關鍵指令 → 行為飄」、預算化是 harness 設計的核心責任。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>典型 coding agent 的 context 構成（以 200K 模型為例）：&lt;/p>





&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-text" data-lang="text">&lt;span class="line">&lt;span class="ln"> 1&lt;/span>&lt;span class="cl">[1. System prompt + tool schema]： 固定 ~10K-30K
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 2&lt;/span>&lt;span class="cl"> - agent 角色、輸出規則、tool 列表 + spec、subagent 路由
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 3&lt;/span>&lt;span class="cl"> - 經常用 prompt cache 加速、見 [prompt cache 卡]
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 4&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 5&lt;/span>&lt;span class="cl">[2. 工作歷史 / conversation history]： 動態 0-60K
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 6&lt;/span>&lt;span class="cl"> - 過去回合的 user query + assistant answer + tool calls
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 7&lt;/span>&lt;span class="cl"> - 越長越貴、harness 要決定何時 summarize / trim
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 8&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 9&lt;/span>&lt;span class="cl">[3. 當前任務 file context]： 動態 0-100K
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">10&lt;/span>&lt;span class="cl"> - 開啟的檔案、grep 結果、@-mention 帶入的內容
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">11&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">12&lt;/span>&lt;span class="cl">[4. Reasoning trace（若 reasoning model）]： 動態 1K-10K / step
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">13&lt;/span>&lt;span class="cl"> - &amp;lt;think&amp;gt;...&amp;lt;/think&amp;gt; 段、每次推論都會佔 context
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">14&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">15&lt;/span>&lt;span class="cl">[5. Tool result]： 動態 0-50K
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">16&lt;/span>&lt;span class="cl"> - file read 結果、bash output、test result
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">17&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">18&lt;/span>&lt;span class="cl">[6. Margin / safety buffer]： 保留 20-30K
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">19&lt;/span>&lt;span class="cl"> - 防止 generation 階段碰到 context limit&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>主流 coding agent 的 25% 規則（&lt;a href="https://tarrragon.github.io/blog/llm/04-applications/coding-agent-harness/" data-link-title="4.17 Coding agent harness：scaffold / context engineering / subagent" data-link-desc="Coding agent 的內部設計：scaffold vs harness 分層、context budget 25% 規則、subagent 拓樸、跟 Claude Code / Cursor / Aider 的 mapping">context engineering 慣例&lt;/a>）：&lt;/p>
&lt;table>
 &lt;thead>
 &lt;tr>
 &lt;th>規則&lt;/th>
 &lt;th>直覺&lt;/th>
 &lt;/tr>
 &lt;/thead>
 &lt;tbody>
 &lt;tr>
 &lt;td>Scaffold 部分（1+2） ≤ 25%&lt;/td>
 &lt;td>留 75% 給「當下任務」、避免 lost-in-the-middle 把指令吃掉&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>File content ≤ 50%&lt;/td>
 &lt;td>不全載入大檔、用 grep / chunked read 替代&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>Margin ≥ 10%&lt;/td>
 &lt;td>Generation 階段才不會被 context limit 截斷&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>Reasoning trace 配長 context&lt;/td>
 &lt;td>Reasoning model 至少配 64K context、見 &lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/reasoning-model/" data-link-title="Reasoning Model" data-link-desc="訓練成自然輸出長 reasoning trace 的 LLM 變體、o1 / DeepSeek-R1 / Claude thinking 為代表">reasoning-model 卡&lt;/a>&lt;/td>
 &lt;/tr>
 &lt;/tbody>
&lt;/table>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>讀 coding agent 設計 / harness paper 看到「context budget」「context engineering」「token budgeting」就是這 framing。寫 code 場景的判讀：&lt;/p></description><content:encoded><![CDATA[<p>Context budget 的核心概念是「<strong>把 <a href="/blog/llm/knowledge-cards/context-window/" data-link-title="Context Window" data-link-desc="模型一次能處理的最大 token 數量：prompt 加生成的總和上限">context window</a> 視為有限資源、明確規劃 system prompt / tool schema / history / file content / reasoning trace / tool result 各佔多少</strong>」。coding agent 的最大失敗模式是「context 用爆 → 模型開始遺忘關鍵指令 → 行為飄」、預算化是 harness 設計的核心責任。</p>
<h2 id="概念位置">概念位置</h2>
<p>典型 coding agent 的 context 構成（以 200K 模型為例）：</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="ln"> 1</span><span class="cl">[1. System prompt + tool schema]：     固定 ~10K-30K
</span></span><span class="line"><span class="ln"> 2</span><span class="cl">   - agent 角色、輸出規則、tool 列表 + spec、subagent 路由
</span></span><span class="line"><span class="ln"> 3</span><span class="cl">   - 經常用 prompt cache 加速、見 [prompt cache 卡]
</span></span><span class="line"><span class="ln"> 4</span><span class="cl">
</span></span><span class="line"><span class="ln"> 5</span><span class="cl">[2. 工作歷史 / conversation history]：  動態 0-60K
</span></span><span class="line"><span class="ln"> 6</span><span class="cl">   - 過去回合的 user query + assistant answer + tool calls
</span></span><span class="line"><span class="ln"> 7</span><span class="cl">   - 越長越貴、harness 要決定何時 summarize / trim
</span></span><span class="line"><span class="ln"> 8</span><span class="cl">
</span></span><span class="line"><span class="ln"> 9</span><span class="cl">[3. 當前任務 file context]：           動態 0-100K
</span></span><span class="line"><span class="ln">10</span><span class="cl">   - 開啟的檔案、grep 結果、@-mention 帶入的內容
</span></span><span class="line"><span class="ln">11</span><span class="cl">
</span></span><span class="line"><span class="ln">12</span><span class="cl">[4. Reasoning trace（若 reasoning model）]：  動態 1K-10K / step
</span></span><span class="line"><span class="ln">13</span><span class="cl">   - &lt;think&gt;...&lt;/think&gt; 段、每次推論都會佔 context
</span></span><span class="line"><span class="ln">14</span><span class="cl">
</span></span><span class="line"><span class="ln">15</span><span class="cl">[5. Tool result]：                    動態 0-50K
</span></span><span class="line"><span class="ln">16</span><span class="cl">   - file read 結果、bash output、test result
</span></span><span class="line"><span class="ln">17</span><span class="cl">
</span></span><span class="line"><span class="ln">18</span><span class="cl">[6. Margin / safety buffer]：         保留 20-30K
</span></span><span class="line"><span class="ln">19</span><span class="cl">   - 防止 generation 階段碰到 context limit</span></span></code></pre></div><p>主流 coding agent 的 25% 規則（<a href="/blog/llm/04-applications/coding-agent-harness/" data-link-title="4.17 Coding agent harness：scaffold / context engineering / subagent" data-link-desc="Coding agent 的內部設計：scaffold vs harness 分層、context budget 25% 規則、subagent 拓樸、跟 Claude Code / Cursor / Aider 的 mapping">context engineering 慣例</a>）：</p>
<table>
  <thead>
      <tr>
          <th>規則</th>
          <th>直覺</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>Scaffold 部分（1+2） ≤ 25%</td>
          <td>留 75% 給「當下任務」、避免 lost-in-the-middle 把指令吃掉</td>
      </tr>
      <tr>
          <td>File content ≤ 50%</td>
          <td>不全載入大檔、用 grep / chunked read 替代</td>
      </tr>
      <tr>
          <td>Margin ≥ 10%</td>
          <td>Generation 階段才不會被 context limit 截斷</td>
      </tr>
      <tr>
          <td>Reasoning trace 配長 context</td>
          <td>Reasoning model 至少配 64K context、見 <a href="/blog/llm/knowledge-cards/reasoning-model/" data-link-title="Reasoning Model" data-link-desc="訓練成自然輸出長 reasoning trace 的 LLM 變體、o1 / DeepSeek-R1 / Claude thinking 為代表">reasoning-model 卡</a></td>
      </tr>
  </tbody>
</table>
<h2 id="設計責任">設計責任</h2>
<p>讀 coding agent 設計 / harness paper 看到「context budget」「context engineering」「token budgeting」就是這 framing。寫 code 場景的判讀：</p>
<ol>
<li><strong>超出 budget 的訊號</strong>：模型開始忽略 system prompt、回答跟前文重複、tool call 重複過去步驟、reasoning trace 截斷</li>
<li><strong>節省 budget 的策略</strong>：用 <a href="/blog/llm/knowledge-cards/prompt-cache/" data-link-title="Prompt Cache" data-link-desc="重複出現的 prompt prefix 在推論伺服器或 LLM 服務端被 cache、後續 query 跳過 prefill、大幅降 cost 跟 TTFT">prompt cache</a> 把 system + tool schema 攤平、grep 取代全檔讀、tool result 限長度（如 head -100）、定期 summarize history</li>
<li><strong>跟 <a href="/blog/llm/knowledge-cards/lost-in-the-middle/" data-link-title="Lost in the Middle" data-link-desc="LLM 對 long context 中段內容的 attention / recall 顯著低於開頭與結尾的現象">lost-in-the-middle</a> 的關係</strong>：context 用越多、中段內容 recall 越差、所以「能用 20K 解就別用 100K」、不是「能塞 200K 就塞滿」</li>
<li><strong>不同 task 不同 budget</strong>：autocomplete 任務 budget 小（系統 prompt + 最近 50 行 code 就夠）；refactor 任務 budget 大（多檔案）；agent loop 任務 budget 動態（每步可能 grow）</li>
</ol>
]]></content:encoded></item><item><title>Contrastive Learning</title><link>https://tarrragon.github.io/blog/llm/knowledge-cards/contrastive-learning/</link><pubDate>Tue, 12 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/llm/knowledge-cards/contrastive-learning/</guid><description>&lt;p>Contrastive learning（對比學習）的核心概念是「&lt;strong>訓練模型讓相關樣本的 embedding 在向量空間中靠近、無關樣本遠離&lt;/strong>」。是現代 &lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/embedding-model/" data-link-title="Embedding Model" data-link-desc="把文字轉成向量的模型：用於 codebase 索引與語意搜尋">embedding model&lt;/a> 的標準訓練 paradigm、跟 LLM pretrain 的 next-token prediction 完全不同的訓練目標。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>Contrastive learning 的核心訓練形態：&lt;/p>





&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-text" data-lang="text">&lt;span class="line">&lt;span class="ln"> 1&lt;/span>&lt;span class="cl">正向對（positive pair）：
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 2&lt;/span>&lt;span class="cl"> (query, relevant_doc) — 應該在 embedding 空間靠近
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 3&lt;/span>&lt;span class="cl"> 例：(&amp;#34;Python how to read file&amp;#34;, &amp;#34;Python file reading tutorial...&amp;#34;)
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 4&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 5&lt;/span>&lt;span class="cl">負向對（negative pair）：
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 6&lt;/span>&lt;span class="cl"> (query, irrelevant_doc) — 應該在 embedding 空間遠離
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 7&lt;/span>&lt;span class="cl"> 例：(&amp;#34;Python how to read file&amp;#34;, &amp;#34;CSS flexbox guide...&amp;#34;)
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 8&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 9&lt;/span>&lt;span class="cl">Loss（簡化的 InfoNCE loss）：
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">10&lt;/span>&lt;span class="cl"> pull positive pair 靠近
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">11&lt;/span>&lt;span class="cl"> push negative pair 遠離（多個 negative samples 對比）&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>主流形式：&lt;/p>
&lt;table>
 &lt;thead>
 &lt;tr>
 &lt;th>形式&lt;/th>
 &lt;th>Loss 設計&lt;/th>
 &lt;th>代表模型&lt;/th>
 &lt;/tr>
 &lt;/thead>
 &lt;tbody>
 &lt;tr>
 &lt;td>Triplet loss&lt;/td>
 &lt;td>(anchor, positive, negative)、要求 anchor-positive 距離 &amp;lt; anchor-negative&lt;/td>
 &lt;td>早期 sentence-BERT&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>InfoNCE / NCE&lt;/td>
 &lt;td>Cross-entropy over batch、把 batch 內其他樣本當 hard negative&lt;/td>
 &lt;td>OpenAI ada-002、bge 系列&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>MultipleNegativesRankingLoss&lt;/td>
 &lt;td>上述變體、用 batch 內隨機其他樣本當 negative&lt;/td>
 &lt;td>Sentence-Transformers 主流&lt;/td>
 &lt;/tr>
 &lt;/tbody>
&lt;/table>
&lt;p>關鍵特性：&lt;/p>
&lt;ol>
&lt;li>&lt;strong>資料量需求大&lt;/strong>：contrastive learning 需要億級的正向對才能訓出好 embedding；資料來源是 query-doc click log、StackExchange QA pair、CC-paraphrase 等&lt;/li>
&lt;li>&lt;strong>Hard negative mining 是品質關鍵&lt;/strong>：隨機選 negative 容易（從 batch 取就行）、找「看似相關但實際無關」的 hard negative 更挑戰、是 embedding quality 提升的關鍵&lt;/li>
&lt;li>&lt;strong>不能直接拿 pretrained LLM 用&lt;/strong>：LLM 的 hidden state 不是「為 retrieval 優化」的、要再 fine-tune 一輪 contrastive learning 才能當 embedding model&lt;/li>
&lt;/ol>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>讀 embedding model paper / 訓練 code 看到「InfoNCE」「triplet」「hard negatives」「mining strategy」就是這 paradigm。寫 code 場景的判讀：&lt;/p>
&lt;ol>
&lt;li>&lt;strong>挑 embedding model 看訓練資料 domain&lt;/strong>：通用 retrieval（如 bge-large、nomic-embed）vs code-specific（如 jina-embeddings-v2-code、CodeT5+）、訓練資料分佈影響大&lt;/li>
&lt;li>&lt;strong>不能拿任意 LLM 抽 hidden state 當 embedding&lt;/strong>：如「Llama 的 last hidden state 當 embedding」這類做法在 retrieval 上通常顯著輸給專門 contrastive-trained embedding model&lt;/li>
&lt;li>&lt;strong>Fine-tune embedding model 通常用 LoRA + contrastive loss&lt;/strong>：在自己 domain 資料上 fine-tune、提升 in-domain retrieval；標準 pipeline 是 sentence-transformers + LoRA&lt;/li>
&lt;/ol></description><content:encoded><![CDATA[<p>Contrastive learning（對比學習）的核心概念是「<strong>訓練模型讓相關樣本的 embedding 在向量空間中靠近、無關樣本遠離</strong>」。是現代 <a href="/blog/llm/knowledge-cards/embedding-model/" data-link-title="Embedding Model" data-link-desc="把文字轉成向量的模型：用於 codebase 索引與語意搜尋">embedding model</a> 的標準訓練 paradigm、跟 LLM pretrain 的 next-token prediction 完全不同的訓練目標。</p>
<h2 id="概念位置">概念位置</h2>
<p>Contrastive learning 的核心訓練形態：</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="ln"> 1</span><span class="cl">正向對（positive pair）：
</span></span><span class="line"><span class="ln"> 2</span><span class="cl">  (query, relevant_doc) — 應該在 embedding 空間靠近
</span></span><span class="line"><span class="ln"> 3</span><span class="cl">  例：(&#34;Python how to read file&#34;, &#34;Python file reading tutorial...&#34;)
</span></span><span class="line"><span class="ln"> 4</span><span class="cl">
</span></span><span class="line"><span class="ln"> 5</span><span class="cl">負向對（negative pair）：
</span></span><span class="line"><span class="ln"> 6</span><span class="cl">  (query, irrelevant_doc) — 應該在 embedding 空間遠離
</span></span><span class="line"><span class="ln"> 7</span><span class="cl">  例：(&#34;Python how to read file&#34;, &#34;CSS flexbox guide...&#34;)
</span></span><span class="line"><span class="ln"> 8</span><span class="cl">
</span></span><span class="line"><span class="ln"> 9</span><span class="cl">Loss（簡化的 InfoNCE loss）：
</span></span><span class="line"><span class="ln">10</span><span class="cl">  pull positive pair 靠近
</span></span><span class="line"><span class="ln">11</span><span class="cl">  push negative pair 遠離（多個 negative samples 對比）</span></span></code></pre></div><p>主流形式：</p>
<table>
  <thead>
      <tr>
          <th>形式</th>
          <th>Loss 設計</th>
          <th>代表模型</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>Triplet loss</td>
          <td>(anchor, positive, negative)、要求 anchor-positive 距離 &lt; anchor-negative</td>
          <td>早期 sentence-BERT</td>
      </tr>
      <tr>
          <td>InfoNCE / NCE</td>
          <td>Cross-entropy over batch、把 batch 內其他樣本當 hard negative</td>
          <td>OpenAI ada-002、bge 系列</td>
      </tr>
      <tr>
          <td>MultipleNegativesRankingLoss</td>
          <td>上述變體、用 batch 內隨機其他樣本當 negative</td>
          <td>Sentence-Transformers 主流</td>
      </tr>
  </tbody>
</table>
<p>關鍵特性：</p>
<ol>
<li><strong>資料量需求大</strong>：contrastive learning 需要億級的正向對才能訓出好 embedding；資料來源是 query-doc click log、StackExchange QA pair、CC-paraphrase 等</li>
<li><strong>Hard negative mining 是品質關鍵</strong>：隨機選 negative 容易（從 batch 取就行）、找「看似相關但實際無關」的 hard negative 更挑戰、是 embedding quality 提升的關鍵</li>
<li><strong>不能直接拿 pretrained LLM 用</strong>：LLM 的 hidden state 不是「為 retrieval 優化」的、要再 fine-tune 一輪 contrastive learning 才能當 embedding model</li>
</ol>
<h2 id="設計責任">設計責任</h2>
<p>讀 embedding model paper / 訓練 code 看到「InfoNCE」「triplet」「hard negatives」「mining strategy」就是這 paradigm。寫 code 場景的判讀：</p>
<ol>
<li><strong>挑 embedding model 看訓練資料 domain</strong>：通用 retrieval（如 bge-large、nomic-embed）vs code-specific（如 jina-embeddings-v2-code、CodeT5+）、訓練資料分佈影響大</li>
<li><strong>不能拿任意 LLM 抽 hidden state 當 embedding</strong>：如「Llama 的 last hidden state 當 embedding」這類做法在 retrieval 上通常顯著輸給專門 contrastive-trained embedding model</li>
<li><strong>Fine-tune embedding model 通常用 LoRA + contrastive loss</strong>：在自己 domain 資料上 fine-tune、提升 in-domain retrieval；標準 pipeline 是 sentence-transformers + LoRA</li>
</ol>
]]></content:encoded></item><item><title>Cross-Entropy</title><link>https://tarrragon.github.io/blog/llm/knowledge-cards/cross-entropy/</link><pubDate>Tue, 12 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/llm/knowledge-cards/cross-entropy/</guid><description>&lt;p>Cross-entropy（交叉熵）的核心概念是「衡量兩個機率分佈的距離」。LLM 預訓練的標準 &lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/loss-function/" data-link-title="Loss Function" data-link-desc="把「模型預測」跟「正確答案」的差距量化成一個純量、訓練的最佳化目標">loss function&lt;/a> 是 cross-entropy：對每個 token、把模型預測的 vocab 機率分佈跟「真實答案是 one-hot 分佈」做 cross-entropy、加總。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>Cross-entropy 在 next-token prediction 訓練裡的具體計算：&lt;/p>





&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-text" data-lang="text">&lt;span class="line">&lt;span class="ln">1&lt;/span>&lt;span class="cl">模型預測：p = softmax(logits) ← shape: (vocab_size,)
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">2&lt;/span>&lt;span class="cl">真實答案：y = one-hot(true_token) ← shape: (vocab_size,)、只有真實 token 那位是 1
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">3&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">4&lt;/span>&lt;span class="cl">cross-entropy = -sum(y_i × log(p_i))
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">5&lt;/span>&lt;span class="cl"> = -log(p_true_token) ← 因為 y 是 one-hot、只剩這項&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>所以實作上 cross-entropy 就退化成「真實 token 預測機率的負對數」、機率越接近 1、loss 越接近 0；機率越接近 0、loss 越接近 ∞。&lt;/p>
&lt;p>跟相關概念的關係：&lt;/p>
&lt;table>
 &lt;thead>
 &lt;tr>
 &lt;th>概念&lt;/th>
 &lt;th>跟 cross-entropy 的關係&lt;/th>
 &lt;/tr>
 &lt;/thead>
 &lt;tbody>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/perplexity/" data-link-title="Perplexity" data-link-desc="cross-entropy 的指數形式、直覺意義為「模型平均覺得下個 token 有多少種可能」">Perplexity&lt;/a>&lt;/td>
 &lt;td>&lt;code>perplexity = exp(cross-entropy)&lt;/code>、cross-entropy 的指數形式、人類直覺較好讀&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/kl-divergence/" data-link-title="KL Divergence" data-link-desc="衡量「兩個機率分佈差距」的非對稱指標、RLHF / DPO 等 alignment 訓練的關鍵約束">KL divergence&lt;/a>&lt;/td>
 &lt;td>Cross-entropy = entropy(真實) + KL(真實 ‖ 預測)、訓練時 entropy 是常數、所以 minimize cross-entropy 等於 minimize KL&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/softmax/" data-link-title="Softmax" data-link-desc="把任意實數向量正規化成「總和為 1、每個分量 ∈ [0,1]」的機率分佈">Softmax&lt;/a>&lt;/td>
 &lt;td>Cross-entropy 通常吃 softmax 的輸出當「預測機率」&lt;/td>
 &lt;/tr>
 &lt;/tbody>
&lt;/table>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>讀 LLM 訓練 / paper 時看到「training loss」幾乎都是 cross-entropy。實務判讀：cross-entropy 直接代表「模型對真實 token 的預測機率有多差」、loss = 2 大致對應「真實 token 被預測機率 ≈ 0.135」（exp(-2)）。模型在 pretrain 階段 cross-entropy 從約 11（純隨機）降到約 2-3（成熟模型）、SFT 階段再略降。&lt;/p></description><content:encoded><![CDATA[<p>Cross-entropy（交叉熵）的核心概念是「衡量兩個機率分佈的距離」。LLM 預訓練的標準 <a href="/blog/llm/knowledge-cards/loss-function/" data-link-title="Loss Function" data-link-desc="把「模型預測」跟「正確答案」的差距量化成一個純量、訓練的最佳化目標">loss function</a> 是 cross-entropy：對每個 token、把模型預測的 vocab 機率分佈跟「真實答案是 one-hot 分佈」做 cross-entropy、加總。</p>
<h2 id="概念位置">概念位置</h2>
<p>Cross-entropy 在 next-token prediction 訓練裡的具體計算：</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="ln">1</span><span class="cl">模型預測：p = softmax(logits)  ← shape: (vocab_size,)
</span></span><span class="line"><span class="ln">2</span><span class="cl">真實答案：y = one-hot(true_token)  ← shape: (vocab_size,)、只有真實 token 那位是 1
</span></span><span class="line"><span class="ln">3</span><span class="cl">
</span></span><span class="line"><span class="ln">4</span><span class="cl">cross-entropy = -sum(y_i × log(p_i))
</span></span><span class="line"><span class="ln">5</span><span class="cl">              = -log(p_true_token)  ← 因為 y 是 one-hot、只剩這項</span></span></code></pre></div><p>所以實作上 cross-entropy 就退化成「真實 token 預測機率的負對數」、機率越接近 1、loss 越接近 0；機率越接近 0、loss 越接近 ∞。</p>
<p>跟相關概念的關係：</p>
<table>
  <thead>
      <tr>
          <th>概念</th>
          <th>跟 cross-entropy 的關係</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td><a href="/blog/llm/knowledge-cards/perplexity/" data-link-title="Perplexity" data-link-desc="cross-entropy 的指數形式、直覺意義為「模型平均覺得下個 token 有多少種可能」">Perplexity</a></td>
          <td><code>perplexity = exp(cross-entropy)</code>、cross-entropy 的指數形式、人類直覺較好讀</td>
      </tr>
      <tr>
          <td><a href="/blog/llm/knowledge-cards/kl-divergence/" data-link-title="KL Divergence" data-link-desc="衡量「兩個機率分佈差距」的非對稱指標、RLHF / DPO 等 alignment 訓練的關鍵約束">KL divergence</a></td>
          <td>Cross-entropy = entropy(真實) + KL(真實 ‖ 預測)、訓練時 entropy 是常數、所以 minimize cross-entropy 等於 minimize KL</td>
      </tr>
      <tr>
          <td><a href="/blog/llm/knowledge-cards/softmax/" data-link-title="Softmax" data-link-desc="把任意實數向量正規化成「總和為 1、每個分量 ∈ [0,1]」的機率分佈">Softmax</a></td>
          <td>Cross-entropy 通常吃 softmax 的輸出當「預測機率」</td>
      </tr>
  </tbody>
</table>
<h2 id="設計責任">設計責任</h2>
<p>讀 LLM 訓練 / paper 時看到「training loss」幾乎都是 cross-entropy。實務判讀：cross-entropy 直接代表「模型對真實 token 的預測機率有多差」、loss = 2 大致對應「真實 token 被預測機率 ≈ 0.135」（exp(-2)）。模型在 pretrain 階段 cross-entropy 從約 11（純隨機）降到約 2-3（成熟模型）、SFT 階段再略降。</p>
]]></content:encoded></item><item><title>Dot Product</title><link>https://tarrragon.github.io/blog/llm/knowledge-cards/dot-product/</link><pubDate>Tue, 12 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/llm/knowledge-cards/dot-product/</guid><description>&lt;p>Dot product（內積、inner product）的核心概念是「&lt;strong>兩個向量對應位置相乘再加總&lt;/strong>」：&lt;code>a · b = a₁b₁ + a₂b₂ + ... + aₙbₙ&lt;/code>。幾何意義是「a 在 b 方向上的投影長度 × b 的長度」。Dot product 是 LLM 中&lt;strong>最頻繁出現的運算之一&lt;/strong>：&lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/attention/" data-link-title="Attention" data-link-desc="Transformer 內部讓每個 token 對其他 token 加權平均的核心機制、形成 KV cache 跟 context window 的計算基礎">attention&lt;/a> 的核心是 dot product、cosine similarity 的本體也是 dot product。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>Dot product 在 LLM 中的核心應用：&lt;/p>
&lt;table>
 &lt;thead>
 &lt;tr>
 &lt;th>應用&lt;/th>
 &lt;th>公式 / 機制&lt;/th>
 &lt;th>角色&lt;/th>
 &lt;/tr>
 &lt;/thead>
 &lt;tbody>
 &lt;tr>
 &lt;td>Attention score&lt;/td>
 &lt;td>&lt;code>Q · K^T&lt;/code>&lt;/td>
 &lt;td>算「該 token 跟其他 token 的相關性」&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>Cosine similarity&lt;/td>
 &lt;td>&lt;code>dot(a, b) / (norm(a) × norm(b))&lt;/code>&lt;/td>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/rag/" data-link-title="RAG" data-link-desc="Retrieval-Augmented Generation：動態外掛知識給 LLM、繞開模型參數記憶的靜態限制">RAG&lt;/a> / semantic search&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>L2-normalized similarity&lt;/td>
 &lt;td>normalize 後直接用 &lt;code>a · b&lt;/code>&lt;/td>
 &lt;td>Vector database 高效檢索&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>Logits → token 機率&lt;/td>
 &lt;td>output_projection 本質是「最後 hidden state · token embedding」&lt;/td>
 &lt;td>算每個 vocab token 的「匹配度」&lt;/td>
 &lt;/tr>
 &lt;/tbody>
&lt;/table>
&lt;p>幾何直覺：&lt;/p>





&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-text" data-lang="text">&lt;span class="line">&lt;span class="ln">1&lt;/span>&lt;span class="cl">兩個向量方向接近時：dot product 大（正值大）
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">2&lt;/span>&lt;span class="cl">兩個向量垂直時： dot product = 0
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">3&lt;/span>&lt;span class="cl">兩個向量方向相反時：dot product 大負值
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">4&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">5&lt;/span>&lt;span class="cl">a · b = |a| × |b| × cos(θ)
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">6&lt;/span>&lt;span class="cl"> ↑
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">7&lt;/span>&lt;span class="cl"> θ 是兩向量夾角&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>LLM 推論性能上、dot product 是「&lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/matrix-multiplication/" data-link-title="Matrix Multiplication" data-link-desc="LLM 推論最頻繁的單一運算、forward pass 每層的核心、memory bandwidth 瓶頸的根源">matrix multiplication&lt;/a> 的基本單元」、整個 forward pass 可以看成大量 dot product 的批次運算；這是為什麼 GPU / Apple Silicon Neural Engine 都針對 dot product 做硬體優化。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>讀 attention / RAG 相關內容看到「inner product」「dot product」「QK^T」就是這個運算。寫 code 場景的判讀：用 vector database 時、選 distance metric 看：cosine 適合未 normalized 的 embedding、dot product 適合 L2-normalized 的 embedding（兩者結果同、後者較快）；attention 的 KV cache 量化（K=Q8 / V=Q4）對品質的不對稱影響、根本原因是 K 用於 dot product（誤差累積快）、V 用於加權平均（誤差被平均化）。&lt;/p></description><content:encoded><![CDATA[<p>Dot product（內積、inner product）的核心概念是「<strong>兩個向量對應位置相乘再加總</strong>」：<code>a · b = a₁b₁ + a₂b₂ + ... + aₙbₙ</code>。幾何意義是「a 在 b 方向上的投影長度 × b 的長度」。Dot product 是 LLM 中<strong>最頻繁出現的運算之一</strong>：<a href="/blog/llm/knowledge-cards/attention/" data-link-title="Attention" data-link-desc="Transformer 內部讓每個 token 對其他 token 加權平均的核心機制、形成 KV cache 跟 context window 的計算基礎">attention</a> 的核心是 dot product、cosine similarity 的本體也是 dot product。</p>
<h2 id="概念位置">概念位置</h2>
<p>Dot product 在 LLM 中的核心應用：</p>
<table>
  <thead>
      <tr>
          <th>應用</th>
          <th>公式 / 機制</th>
          <th>角色</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>Attention score</td>
          <td><code>Q · K^T</code></td>
          <td>算「該 token 跟其他 token 的相關性」</td>
      </tr>
      <tr>
          <td>Cosine similarity</td>
          <td><code>dot(a, b) / (norm(a) × norm(b))</code></td>
          <td><a href="/blog/llm/knowledge-cards/rag/" data-link-title="RAG" data-link-desc="Retrieval-Augmented Generation：動態外掛知識給 LLM、繞開模型參數記憶的靜態限制">RAG</a> / semantic search</td>
      </tr>
      <tr>
          <td>L2-normalized similarity</td>
          <td>normalize 後直接用 <code>a · b</code></td>
          <td>Vector database 高效檢索</td>
      </tr>
      <tr>
          <td>Logits → token 機率</td>
          <td>output_projection 本質是「最後 hidden state · token embedding」</td>
          <td>算每個 vocab token 的「匹配度」</td>
      </tr>
  </tbody>
</table>
<p>幾何直覺：</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="ln">1</span><span class="cl">兩個向量方向接近時：dot product 大（正值大）
</span></span><span class="line"><span class="ln">2</span><span class="cl">兩個向量垂直時：    dot product = 0
</span></span><span class="line"><span class="ln">3</span><span class="cl">兩個向量方向相反時：dot product 大負值
</span></span><span class="line"><span class="ln">4</span><span class="cl">
</span></span><span class="line"><span class="ln">5</span><span class="cl">a · b = |a| × |b| × cos(θ)
</span></span><span class="line"><span class="ln">6</span><span class="cl">                          ↑
</span></span><span class="line"><span class="ln">7</span><span class="cl">                  θ 是兩向量夾角</span></span></code></pre></div><p>LLM 推論性能上、dot product 是「<a href="/blog/llm/knowledge-cards/matrix-multiplication/" data-link-title="Matrix Multiplication" data-link-desc="LLM 推論最頻繁的單一運算、forward pass 每層的核心、memory bandwidth 瓶頸的根源">matrix multiplication</a> 的基本單元」、整個 forward pass 可以看成大量 dot product 的批次運算；這是為什麼 GPU / Apple Silicon Neural Engine 都針對 dot product 做硬體優化。</p>
<h2 id="設計責任">設計責任</h2>
<p>讀 attention / RAG 相關內容看到「inner product」「dot product」「QK^T」就是這個運算。寫 code 場景的判讀：用 vector database 時、選 distance metric 看：cosine 適合未 normalized 的 embedding、dot product 適合 L2-normalized 的 embedding（兩者結果同、後者較快）；attention 的 KV cache 量化（K=Q8 / V=Q4）對品質的不對稱影響、根本原因是 K 用於 dot product（誤差累積快）、V 用於加權平均（誤差被平均化）。</p>
]]></content:encoded></item><item><title>DPO（Direct Preference Optimization）</title><link>https://tarrragon.github.io/blog/llm/knowledge-cards/dpo/</link><pubDate>Tue, 12 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/llm/knowledge-cards/dpo/</guid><description>&lt;p>DPO（Direct Preference Optimization、直接偏好最佳化）的核心概念是「&lt;strong>用人類偏好資料直接 fine-tune LLM、不訓 reward model、不用 RL&lt;/strong>」。Rafailov et al. (2023) 提出、用數學變形把 &lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/rlhf/" data-link-title="RLHF" data-link-desc="Reinforcement Learning from Human Feedback：用人類偏好訓練的 reward model 透過 RL 對齊 LLM">RLHF&lt;/a> 的「reward model + PPO」兩階段合併成單一個 supervised loss、訓練流程大幅簡化。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>DPO vs RLHF 的對比：&lt;/p>
&lt;table>
 &lt;thead>
 &lt;tr>
 &lt;th>維度&lt;/th>
 &lt;th>RLHF&lt;/th>
 &lt;th>DPO&lt;/th>
 &lt;/tr>
 &lt;/thead>
 &lt;tbody>
 &lt;tr>
 &lt;td>需要 reward model&lt;/td>
 &lt;td>是&lt;/td>
 &lt;td>否&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>訓練步驟&lt;/td>
 &lt;td>收偏好 → 訓 RM → PPO&lt;/td>
 &lt;td>收偏好 → 直接 DPO loss fine-tune&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>訓練穩定性&lt;/td>
 &lt;td>PPO 對 hyperparameter 敏感、容易不穩&lt;/td>
 &lt;td>像 supervised learning、相對穩&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>記憶體&lt;/td>
 &lt;td>三個模型同時運作（policy / RM / reference）&lt;/td>
 &lt;td>兩個（policy / reference frozen）&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>KL 約束&lt;/td>
 &lt;td>顯式加 β × KL term&lt;/td>
 &lt;td>內嵌在 loss 公式裡、不用顯式&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>流行度（2026）&lt;/td>
 &lt;td>商業大廠（OpenAI / Anthropic）&lt;/td>
 &lt;td>開源社群（Llama / Qwen / Gemma 系列許多用 DPO）&lt;/td>
 &lt;/tr>
 &lt;/tbody>
&lt;/table>
&lt;p>DPO 的 loss 形式（簡化）：&lt;/p>





&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-text" data-lang="text">&lt;span class="line">&lt;span class="ln">1&lt;/span>&lt;span class="cl">loss = -log σ( β · (log π(y_w|x)/π_ref(y_w|x) - log π(y_l|x)/π_ref(y_l|x)) )
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">2&lt;/span>&lt;span class="cl"> └─ 偏好 response 在 policy 跟 ref 的 ratio ─┘
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">3&lt;/span>&lt;span class="cl"> └─ 拒絕 response 的同樣 ratio ─┘&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>直覺：讓 policy 對偏好 response 的機率增加（相對 ref）、對拒絕 response 的機率降低（相對 ref）。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>讀開源 LLM 的 paper / model card 看到「DPO-tuned」「preference fine-tuning」就是這個流程。實務上 DPO 訓練成本只是 RLHF 的一小部分、許多 fine-tune 平台（如 Hugging Face TRL）內建支援。後續還有 IPO、KTO、ORPO 等變體、都是「直接用偏好 fine-tune、不訓 reward」這條路線的進一步演化。&lt;/p></description><content:encoded><![CDATA[<p>DPO（Direct Preference Optimization、直接偏好最佳化）的核心概念是「<strong>用人類偏好資料直接 fine-tune LLM、不訓 reward model、不用 RL</strong>」。Rafailov et al. (2023) 提出、用數學變形把 <a href="/blog/llm/knowledge-cards/rlhf/" data-link-title="RLHF" data-link-desc="Reinforcement Learning from Human Feedback：用人類偏好訓練的 reward model 透過 RL 對齊 LLM">RLHF</a> 的「reward model + PPO」兩階段合併成單一個 supervised loss、訓練流程大幅簡化。</p>
<h2 id="概念位置">概念位置</h2>
<p>DPO vs RLHF 的對比：</p>
<table>
  <thead>
      <tr>
          <th>維度</th>
          <th>RLHF</th>
          <th>DPO</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>需要 reward model</td>
          <td>是</td>
          <td>否</td>
      </tr>
      <tr>
          <td>訓練步驟</td>
          <td>收偏好 → 訓 RM → PPO</td>
          <td>收偏好 → 直接 DPO loss fine-tune</td>
      </tr>
      <tr>
          <td>訓練穩定性</td>
          <td>PPO 對 hyperparameter 敏感、容易不穩</td>
          <td>像 supervised learning、相對穩</td>
      </tr>
      <tr>
          <td>記憶體</td>
          <td>三個模型同時運作（policy / RM / reference）</td>
          <td>兩個（policy / reference frozen）</td>
      </tr>
      <tr>
          <td>KL 約束</td>
          <td>顯式加 β × KL term</td>
          <td>內嵌在 loss 公式裡、不用顯式</td>
      </tr>
      <tr>
          <td>流行度（2026）</td>
          <td>商業大廠（OpenAI / Anthropic）</td>
          <td>開源社群（Llama / Qwen / Gemma 系列許多用 DPO）</td>
      </tr>
  </tbody>
</table>
<p>DPO 的 loss 形式（簡化）：</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="ln">1</span><span class="cl">loss = -log σ( β · (log π(y_w|x)/π_ref(y_w|x) - log π(y_l|x)/π_ref(y_l|x)) )
</span></span><span class="line"><span class="ln">2</span><span class="cl">                └─ 偏好 response 在 policy 跟 ref 的 ratio ─┘
</span></span><span class="line"><span class="ln">3</span><span class="cl">                                                            └─ 拒絕 response 的同樣 ratio ─┘</span></span></code></pre></div><p>直覺：讓 policy 對偏好 response 的機率增加（相對 ref）、對拒絕 response 的機率降低（相對 ref）。</p>
<h2 id="設計責任">設計責任</h2>
<p>讀開源 LLM 的 paper / model card 看到「DPO-tuned」「preference fine-tuning」就是這個流程。實務上 DPO 訓練成本只是 RLHF 的一小部分、許多 fine-tune 平台（如 Hugging Face TRL）內建支援。後續還有 IPO、KTO、ORPO 等變體、都是「直接用偏好 fine-tune、不訓 reward」這條路線的進一步演化。</p>
]]></content:encoded></item><item><title>Embedding Layer</title><link>https://tarrragon.github.io/blog/llm/knowledge-cards/embedding-layer/</link><pubDate>Tue, 12 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/llm/knowledge-cards/embedding-layer/</guid><description>&lt;p>Embedding layer（嵌入層）的核心概念是「Transformer 第一層的查表結構：把整數 &lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/token/" data-link-title="Token" data-link-desc="LLM 處理文字時的最小單位：介於字元與單字之間">token&lt;/a> ID 對應到一個可訓練向量（embedding）」。本質上是 &lt;code>vocab_size × hidden_dim&lt;/code> 的權重矩陣、每個 token ID 取對應 row 當該 token 的向量表示。後續所有 Transformer block 都對這些向量做運算。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>Embedding layer 在 &lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/forward-pass/" data-link-title="Forward Pass" data-link-desc="input 經過所有 layer 的計算、得到 output 的單向流程；推論跟訓練都會跑、訓練多一個反向階段">forward pass&lt;/a> 的位置：&lt;/p>





&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-text" data-lang="text">&lt;span class="line">&lt;span class="ln">1&lt;/span>&lt;span class="cl">input：&amp;#34;Hello world&amp;#34;
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">2&lt;/span>&lt;span class="cl"> ↓ tokenizer
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">3&lt;/span>&lt;span class="cl">token IDs: [9906, 1917] ← 整數序列
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">4&lt;/span>&lt;span class="cl"> ↓ embedding layer（vocab × hidden 查表）
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">5&lt;/span>&lt;span class="cl">embeddings: [[0.1, -0.3, ...], [0.5, 0.2, ...]] ← 向量序列、(seq_len, hidden_dim)
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">6&lt;/span>&lt;span class="cl"> ↓ Transformer block × N
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">7&lt;/span>&lt;span class="cl"> ↓ output projection
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">8&lt;/span>&lt;span class="cl">logits&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>跟 &lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/embedding-model/" data-link-title="Embedding Model" data-link-desc="把文字轉成向量的模型：用於 codebase 索引與語意搜尋">embedding model&lt;/a> 的差別：&lt;/p>
&lt;table>
 &lt;thead>
 &lt;tr>
 &lt;th>概念&lt;/th>
 &lt;th>用途&lt;/th>
 &lt;th>是否獨立訓練 / 部署&lt;/th>
 &lt;/tr>
 &lt;/thead>
 &lt;tbody>
 &lt;tr>
 &lt;td>Embedding layer（本卡）&lt;/td>
 &lt;td>LLM 內部第一層、把 token ID 轉向量&lt;/td>
 &lt;td>否、是 LLM 的一部分&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/embedding-model/" data-link-title="Embedding Model" data-link-desc="把文字轉成向量的模型：用於 codebase 索引與語意搜尋">Embedding model&lt;/a>&lt;/td>
 &lt;td>獨立模型、把整段文字轉向量、用於 RAG / 相似度&lt;/td>
 &lt;td>是、獨立模型&lt;/td>
 &lt;/tr>
 &lt;/tbody>
&lt;/table>
&lt;p>兩者「都產出向量」、但層級跟用途完全不同：embedding layer 是 LLM 內部結構（per-token、給模型 forward pass 用）、embedding model 是外部工具（per-text、給檢索系統用）。&lt;/p>
&lt;p>Embedding layer 的大小：&lt;/p>
&lt;ul>
&lt;li>Gemma 4 31B：vocab=256K、hidden=5120、embedding matrix ≈ 256K × 5120 = 1.3B 參數&lt;/li>
&lt;li>Llama 3 8B：vocab=128K、hidden=4096、embedding matrix ≈ 0.5B 參數&lt;/li>
&lt;/ul>
&lt;p>通常跟 output projection（hidden → vocab）相同大小、有些模型 tied（共用權重）、有些 untied。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>讀模型架構圖看到「token embedding」「embed_tokens」就是這一層。實務意涵：模型大小有非小比例來自 embedding（vocab 越大、embedding 越大）；換 tokenizer 等於整個 embedding 重訓、是 fine-tune 時通常不動的部分。&lt;/p></description><content:encoded><![CDATA[<p>Embedding layer（嵌入層）的核心概念是「Transformer 第一層的查表結構：把整數 <a href="/blog/llm/knowledge-cards/token/" data-link-title="Token" data-link-desc="LLM 處理文字時的最小單位：介於字元與單字之間">token</a> ID 對應到一個可訓練向量（embedding）」。本質上是 <code>vocab_size × hidden_dim</code> 的權重矩陣、每個 token ID 取對應 row 當該 token 的向量表示。後續所有 Transformer block 都對這些向量做運算。</p>
<h2 id="概念位置">概念位置</h2>
<p>Embedding layer 在 <a href="/blog/llm/knowledge-cards/forward-pass/" data-link-title="Forward Pass" data-link-desc="input 經過所有 layer 的計算、得到 output 的單向流程；推論跟訓練都會跑、訓練多一個反向階段">forward pass</a> 的位置：</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="ln">1</span><span class="cl">input：&#34;Hello world&#34;
</span></span><span class="line"><span class="ln">2</span><span class="cl">   ↓ tokenizer
</span></span><span class="line"><span class="ln">3</span><span class="cl">token IDs: [9906, 1917]            ← 整數序列
</span></span><span class="line"><span class="ln">4</span><span class="cl">   ↓ embedding layer（vocab × hidden 查表）
</span></span><span class="line"><span class="ln">5</span><span class="cl">embeddings: [[0.1, -0.3, ...], [0.5, 0.2, ...]]   ← 向量序列、(seq_len, hidden_dim)
</span></span><span class="line"><span class="ln">6</span><span class="cl">   ↓ Transformer block × N
</span></span><span class="line"><span class="ln">7</span><span class="cl">   ↓ output projection
</span></span><span class="line"><span class="ln">8</span><span class="cl">logits</span></span></code></pre></div><p>跟 <a href="/blog/llm/knowledge-cards/embedding-model/" data-link-title="Embedding Model" data-link-desc="把文字轉成向量的模型：用於 codebase 索引與語意搜尋">embedding model</a> 的差別：</p>
<table>
  <thead>
      <tr>
          <th>概念</th>
          <th>用途</th>
          <th>是否獨立訓練 / 部署</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>Embedding layer（本卡）</td>
          <td>LLM 內部第一層、把 token ID 轉向量</td>
          <td>否、是 LLM 的一部分</td>
      </tr>
      <tr>
          <td><a href="/blog/llm/knowledge-cards/embedding-model/" data-link-title="Embedding Model" data-link-desc="把文字轉成向量的模型：用於 codebase 索引與語意搜尋">Embedding model</a></td>
          <td>獨立模型、把整段文字轉向量、用於 RAG / 相似度</td>
          <td>是、獨立模型</td>
      </tr>
  </tbody>
</table>
<p>兩者「都產出向量」、但層級跟用途完全不同：embedding layer 是 LLM 內部結構（per-token、給模型 forward pass 用）、embedding model 是外部工具（per-text、給檢索系統用）。</p>
<p>Embedding layer 的大小：</p>
<ul>
<li>Gemma 4 31B：vocab=256K、hidden=5120、embedding matrix ≈ 256K × 5120 = 1.3B 參數</li>
<li>Llama 3 8B：vocab=128K、hidden=4096、embedding matrix ≈ 0.5B 參數</li>
</ul>
<p>通常跟 output projection（hidden → vocab）相同大小、有些模型 tied（共用權重）、有些 untied。</p>
<h2 id="設計責任">設計責任</h2>
<p>讀模型架構圖看到「token embedding」「embed_tokens」就是這一層。實務意涵：模型大小有非小比例來自 embedding（vocab 越大、embedding 越大）；換 tokenizer 等於整個 embedding 重訓、是 fine-tune 時通常不動的部分。</p>
]]></content:encoded></item><item><title>Entropy</title><link>https://tarrragon.github.io/blog/llm/knowledge-cards/entropy/</link><pubDate>Tue, 12 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/llm/knowledge-cards/entropy/</guid><description>&lt;p>Entropy（熵）的核心概念是「衡量一個機率分佈的不確定性」。Shannon entropy 公式：&lt;code>H(P) = -sum(P(x) × log P(x))&lt;/code>。直覺：分佈越「平」、entropy 越大（任何結果都可能）；分佈越「尖」、entropy 越小（結果很確定）。Entropy 是 &lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/cross-entropy/" data-link-title="Cross-Entropy" data-link-desc="衡量「預測機率分佈」跟「真實分佈」距離的指標、LLM 預訓練的主要 loss">cross-entropy&lt;/a>、&lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/kl-divergence/" data-link-title="KL Divergence" data-link-desc="衡量「兩個機率分佈差距」的非對稱指標、RLHF / DPO 等 alignment 訓練的關鍵約束">KL divergence&lt;/a>、資訊壓縮等概念的基底。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>Entropy 跟 LLM 相關概念的關係：&lt;/p>





&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-text" data-lang="text">&lt;span class="line">&lt;span class="ln">1&lt;/span>&lt;span class="cl">Entropy(P) = -sum P log P ← 一個分佈自身的不確定性
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">2&lt;/span>&lt;span class="cl">Cross-entropy(P, Q) = -sum P log Q ← 用分佈 Q 編碼 P 的成本
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">3&lt;/span>&lt;span class="cl">KL(P ‖ Q) = Cross-entropy(P, Q) - Entropy(P) ← 兩個分佈的差距&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>Entropy 在 LLM 中的具體意義：&lt;/p>
&lt;table>
 &lt;thead>
 &lt;tr>
 &lt;th>場景&lt;/th>
 &lt;th>Entropy 大&lt;/th>
 &lt;th>Entropy 小&lt;/th>
 &lt;/tr>
 &lt;/thead>
 &lt;tbody>
 &lt;tr>
 &lt;td>模型 next-token 預測分佈&lt;/td>
 &lt;td>「不確定下個字、可能 N 種選項」&lt;/td>
 &lt;td>「強烈傾向某幾個 token」&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>Sampling temperature 高&lt;/td>
 &lt;td>Entropy 高、輸出多樣&lt;/td>
 &lt;td>Entropy 低、輸出確定&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>訓練未收斂&lt;/td>
 &lt;td>分佈接近 uniform、entropy 接近 log(vocab)&lt;/td>
 &lt;td>分佈集中、entropy 降低&lt;/td>
 &lt;/tr>
 &lt;/tbody>
&lt;/table>
&lt;p>範例：vocab = 128K、uniform 分佈的 entropy = log(128K) ≈ 11.76（接近 12）；成熟模型在文本上的平均 entropy 約 2-3。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>Entropy 本身在 LLM 訓練 / 推論很少直接出現、但理解它能解釋一些現象：&lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/perplexity/" data-link-title="Perplexity" data-link-desc="cross-entropy 的指數形式、直覺意義為「模型平均覺得下個 token 有多少種可能」">perplexity&lt;/a> = exp(cross-entropy) 是模型平均不確定性的指數形式；temperature 控制 sampling entropy（高 T → 高 entropy → 多樣輸出）；某些評估方法（如 entropy-based uncertainty estimation）會看模型輸出分佈的 entropy 來判讀「模型有多確定」。&lt;/p></description><content:encoded><![CDATA[<p>Entropy（熵）的核心概念是「衡量一個機率分佈的不確定性」。Shannon entropy 公式：<code>H(P) = -sum(P(x) × log P(x))</code>。直覺：分佈越「平」、entropy 越大（任何結果都可能）；分佈越「尖」、entropy 越小（結果很確定）。Entropy 是 <a href="/blog/llm/knowledge-cards/cross-entropy/" data-link-title="Cross-Entropy" data-link-desc="衡量「預測機率分佈」跟「真實分佈」距離的指標、LLM 預訓練的主要 loss">cross-entropy</a>、<a href="/blog/llm/knowledge-cards/kl-divergence/" data-link-title="KL Divergence" data-link-desc="衡量「兩個機率分佈差距」的非對稱指標、RLHF / DPO 等 alignment 訓練的關鍵約束">KL divergence</a>、資訊壓縮等概念的基底。</p>
<h2 id="概念位置">概念位置</h2>
<p>Entropy 跟 LLM 相關概念的關係：</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="ln">1</span><span class="cl">Entropy(P) = -sum P log P                  ← 一個分佈自身的不確定性
</span></span><span class="line"><span class="ln">2</span><span class="cl">Cross-entropy(P, Q) = -sum P log Q         ← 用分佈 Q 編碼 P 的成本
</span></span><span class="line"><span class="ln">3</span><span class="cl">KL(P ‖ Q) = Cross-entropy(P, Q) - Entropy(P) ← 兩個分佈的差距</span></span></code></pre></div><p>Entropy 在 LLM 中的具體意義：</p>
<table>
  <thead>
      <tr>
          <th>場景</th>
          <th>Entropy 大</th>
          <th>Entropy 小</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>模型 next-token 預測分佈</td>
          <td>「不確定下個字、可能 N 種選項」</td>
          <td>「強烈傾向某幾個 token」</td>
      </tr>
      <tr>
          <td>Sampling temperature 高</td>
          <td>Entropy 高、輸出多樣</td>
          <td>Entropy 低、輸出確定</td>
      </tr>
      <tr>
          <td>訓練未收斂</td>
          <td>分佈接近 uniform、entropy 接近 log(vocab)</td>
          <td>分佈集中、entropy 降低</td>
      </tr>
  </tbody>
</table>
<p>範例：vocab = 128K、uniform 分佈的 entropy = log(128K) ≈ 11.76（接近 12）；成熟模型在文本上的平均 entropy 約 2-3。</p>
<h2 id="設計責任">設計責任</h2>
<p>Entropy 本身在 LLM 訓練 / 推論很少直接出現、但理解它能解釋一些現象：<a href="/blog/llm/knowledge-cards/perplexity/" data-link-title="Perplexity" data-link-desc="cross-entropy 的指數形式、直覺意義為「模型平均覺得下個 token 有多少種可能」">perplexity</a> = exp(cross-entropy) 是模型平均不確定性的指數形式；temperature 控制 sampling entropy（高 T → 高 entropy → 多樣輸出）；某些評估方法（如 entropy-based uncertainty estimation）會看模型輸出分佈的 entropy 來判讀「模型有多確定」。</p>
]]></content:encoded></item><item><title>FFN（Feed-Forward Network）</title><link>https://tarrragon.github.io/blog/llm/knowledge-cards/ffn/</link><pubDate>Tue, 12 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/llm/knowledge-cards/ffn/</guid><description>&lt;p>FFN（Feed-Forward Network、前饋網路）的核心概念是「Transformer block 中 attention 後面的兩層 linear + &lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/activation-function/" data-link-title="Activation Function" data-link-desc="在 linear layer 之間插入的非線性函數、讓神經網路能表達非線性關係">activation function&lt;/a> 結構」。FFN 是 LLM 中&lt;strong>參數量最大&lt;/strong>的元件、典型 Transformer block 裡 FFN 約佔 2/3 參數、attention 約佔 1/3。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>標準 FFN 的計算：&lt;/p>





&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-text" data-lang="text">&lt;span class="line">&lt;span class="ln">1&lt;/span>&lt;span class="cl">input（hidden_dim）
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">2&lt;/span>&lt;span class="cl"> ↓ W_up（linear、hidden_dim → intermediate_dim、通常放大 4x）
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">3&lt;/span>&lt;span class="cl">intermediate vector
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">4&lt;/span>&lt;span class="cl"> ↓ activation function（ReLU / GELU / SwiGLU）
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">5&lt;/span>&lt;span class="cl"> ↓ W_down（linear、intermediate_dim → hidden_dim）
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">6&lt;/span>&lt;span class="cl">output（hidden_dim）&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>Intermediate dim 通常是 hidden dim 的 4 倍（例如 hidden=4096、intermediate=16384）、所以 FFN 的參數量是 &lt;code>hidden × intermediate × 2 ≈ 8 × hidden²&lt;/code>、遠大於 attention 的 &lt;code>4 × hidden²&lt;/code>（Q/K/V/O 四個 hidden × hidden 矩陣）。&lt;/p>
&lt;p>FFN 變體：&lt;/p>
&lt;table>
 &lt;thead>
 &lt;tr>
 &lt;th>變體&lt;/th>
 &lt;th>結構特性&lt;/th>
 &lt;th>出現在&lt;/th>
 &lt;/tr>
 &lt;/thead>
 &lt;tbody>
 &lt;tr>
 &lt;td>標準 FFN&lt;/td>
 &lt;td>兩個 linear + 一個 activation&lt;/td>
 &lt;td>早期 Transformer、BERT、GPT-2&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>SwiGLU FFN&lt;/td>
 &lt;td>三個 linear（gate + up + down）+ Swish&lt;/td>
 &lt;td>Llama、Gemma、Qwen 主流&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>MoE FFN&lt;/td>
 &lt;td>多個「expert」FFN、每個 token 只啟用幾個&lt;/td>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/moe/" data-link-title="Mixture of Experts (MoE)" data-link-desc="把 transformer 的 FFN 層拆成多個專家、每 token 只啟用少數、總參數大但每 token 計算量小的架構">MoE&lt;/a> 模型&lt;/td>
 &lt;/tr>
 &lt;/tbody>
&lt;/table>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>理解 FFN 是參數大頭、能解釋幾件事：&lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/moe/" data-link-title="Mixture of Experts (MoE)" data-link-desc="把 transformer 的 FFN 層拆成多個專家、每 token 只啟用少數、總參數大但每 token 計算量小的架構">MoE&lt;/a> 為什麼是「把 FFN 換成多個專家、只啟用部分」（因為 FFN 是最值得稀疏化的部分）、&lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/moe-cpu-offload/" data-link-title="MoE CPU 卸載" data-link-desc="把 Mixture-of-Experts 模型不活躍的專家層權重放在系統 RAM、用到再走 PCIe 拉回 GPU、讓有限 VRAM 跑得了更大模型">MoE CPU offload&lt;/a> 為什麼是「把 expert FFN 卸到 RAM」（FFN 大、卸下來省 VRAM）、為什麼模型大小用「參數量」算（FFN 主導）。LoRA fine-tuning 時、通常選擇對 attention 的 Q/V 投影做 LoRA、不對 FFN 動、因為 FFN 太大、LoRA 收益相對小。&lt;/p></description><content:encoded><![CDATA[<p>FFN（Feed-Forward Network、前饋網路）的核心概念是「Transformer block 中 attention 後面的兩層 linear + <a href="/blog/llm/knowledge-cards/activation-function/" data-link-title="Activation Function" data-link-desc="在 linear layer 之間插入的非線性函數、讓神經網路能表達非線性關係">activation function</a> 結構」。FFN 是 LLM 中<strong>參數量最大</strong>的元件、典型 Transformer block 裡 FFN 約佔 2/3 參數、attention 約佔 1/3。</p>
<h2 id="概念位置">概念位置</h2>
<p>標準 FFN 的計算：</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="ln">1</span><span class="cl">input（hidden_dim）
</span></span><span class="line"><span class="ln">2</span><span class="cl">  ↓ W_up（linear、hidden_dim → intermediate_dim、通常放大 4x）
</span></span><span class="line"><span class="ln">3</span><span class="cl">intermediate vector
</span></span><span class="line"><span class="ln">4</span><span class="cl">  ↓ activation function（ReLU / GELU / SwiGLU）
</span></span><span class="line"><span class="ln">5</span><span class="cl">  ↓ W_down（linear、intermediate_dim → hidden_dim）
</span></span><span class="line"><span class="ln">6</span><span class="cl">output（hidden_dim）</span></span></code></pre></div><p>Intermediate dim 通常是 hidden dim 的 4 倍（例如 hidden=4096、intermediate=16384）、所以 FFN 的參數量是 <code>hidden × intermediate × 2 ≈ 8 × hidden²</code>、遠大於 attention 的 <code>4 × hidden²</code>（Q/K/V/O 四個 hidden × hidden 矩陣）。</p>
<p>FFN 變體：</p>
<table>
  <thead>
      <tr>
          <th>變體</th>
          <th>結構特性</th>
          <th>出現在</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>標準 FFN</td>
          <td>兩個 linear + 一個 activation</td>
          <td>早期 Transformer、BERT、GPT-2</td>
      </tr>
      <tr>
          <td>SwiGLU FFN</td>
          <td>三個 linear（gate + up + down）+ Swish</td>
          <td>Llama、Gemma、Qwen 主流</td>
      </tr>
      <tr>
          <td>MoE FFN</td>
          <td>多個「expert」FFN、每個 token 只啟用幾個</td>
          <td><a href="/blog/llm/knowledge-cards/moe/" data-link-title="Mixture of Experts (MoE)" data-link-desc="把 transformer 的 FFN 層拆成多個專家、每 token 只啟用少數、總參數大但每 token 計算量小的架構">MoE</a> 模型</td>
      </tr>
  </tbody>
</table>
<h2 id="設計責任">設計責任</h2>
<p>理解 FFN 是參數大頭、能解釋幾件事：<a href="/blog/llm/knowledge-cards/moe/" data-link-title="Mixture of Experts (MoE)" data-link-desc="把 transformer 的 FFN 層拆成多個專家、每 token 只啟用少數、總參數大但每 token 計算量小的架構">MoE</a> 為什麼是「把 FFN 換成多個專家、只啟用部分」（因為 FFN 是最值得稀疏化的部分）、<a href="/blog/llm/knowledge-cards/moe-cpu-offload/" data-link-title="MoE CPU 卸載" data-link-desc="把 Mixture-of-Experts 模型不活躍的專家層權重放在系統 RAM、用到再走 PCIe 拉回 GPU、讓有限 VRAM 跑得了更大模型">MoE CPU offload</a> 為什麼是「把 expert FFN 卸到 RAM」（FFN 大、卸下來省 VRAM）、為什麼模型大小用「參數量」算（FFN 主導）。LoRA fine-tuning 時、通常選擇對 attention 的 Q/V 投影做 LoRA、不對 FFN 動、因為 FFN 太大、LoRA 收益相對小。</p>
]]></content:encoded></item><item><title>Flash Attention</title><link>https://tarrragon.github.io/blog/llm/knowledge-cards/flash-attention/</link><pubDate>Tue, 12 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/llm/knowledge-cards/flash-attention/</guid><description>&lt;p>Flash Attention 的核心概念是「重新組織 &lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/attention/" data-link-title="Attention" data-link-desc="Transformer 內部讓每個 token 對其他 token 加權平均的核心機制、形成 KV cache 跟 context window 的計算基礎">Attention&lt;/a> 計算的順序、把中間結果留在 GPU 高速 cache、減少對 GPU memory 的讀寫往返」。它不改變 attention 的數學定義（輸出跟原始實作在浮點誤差範圍內一致）、但實作層面對長 context 推論吞吐有明顯提升、且是部分 &lt;a href="https://tarrragon.github.io/blog/llm/05-discrete-gpu/kv-cache-quantization-strategy/" data-link-title="5.2 KV cache 量化策略" data-link-desc="PC 場景用 K=Q8 / V=Q4 等量化把 KV cache 壓縮、騰出 VRAM 開大 context window 或加併發數的判讀">KV cache 量化&lt;/a> 組合在 llama.cpp 上的必要前置。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>Flash Attention 在推論架構中的角色：&lt;/p>





&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-text" data-lang="text">&lt;span class="line">&lt;span class="ln">1&lt;/span>&lt;span class="cl">推論時的 attention 計算：
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">2&lt;/span>&lt;span class="cl"> ├── 原始實作：Q · K^T 整個算完、寫進 memory、再讀出來做 softmax、再算 · V
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">3&lt;/span>&lt;span class="cl"> │ └── 多次 memory 讀寫、長 context 下 IO 成為瓶頸
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">4&lt;/span>&lt;span class="cl"> └── Flash Attention：用 tiling 把計算切塊、中間結果留在 SRAM / register
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">5&lt;/span>&lt;span class="cl"> └── 減少 memory 讀寫、長 context 加速明顯&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>跟 attention 變體的關係：&lt;/p>
&lt;ul>
&lt;li>Flash Attention 是&lt;strong>實作層&lt;/strong>的優化、跟 &lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/attention/" data-link-title="Attention" data-link-desc="Transformer 內部讓每個 token 對其他 token 加權平均的核心機制、形成 KV cache 跟 context window 的計算基礎">MHA / GQA / MLA&lt;/a> 等&lt;strong>架構層&lt;/strong>變體是兩個獨立維度。&lt;/li>
&lt;li>不同變體都能搭配 Flash Attention 的實作技巧。&lt;/li>
&lt;/ul>
&lt;p>在 llama.cpp 中的旗標：&lt;/p>





&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-bash" data-lang="bash">&lt;span class="line">&lt;span class="ln">1&lt;/span>&lt;span class="cl">llama-server -fa &lt;span class="c1"># 啟用 flash attention&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">2&lt;/span>&lt;span class="cl">&lt;span class="c1"># 或&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">3&lt;/span>&lt;span class="cl">llama-server --flash-attn&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;blockquote>
&lt;p>&lt;strong>事實查核註&lt;/strong>：Flash Attention 的版本演進快（Flash Attention 1 / 2 / 3）、不同推論引擎的支援度依版本變化。具體限制（如「V cache Q4 量化要 -fa 才能啟用」）依 llama.cpp 版本變動、引用前以 &lt;code>llama-server --help&lt;/code> 跟 release notes 為準。&lt;/p>&lt;/blockquote>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>理解 Flash Attention 後可以解釋兩個現象：為什麼啟用 &lt;code>-fa&lt;/code> 後長 context 推論速度提升明顯（IO bound 變 compute bound）、為什麼部分 KV cache 量化組合（如 V=Q4_0）在 llama.cpp 上需要 flash attention 才能跑（實作層面的耦合）。&lt;/p>
&lt;p>工程實務上、啟用 flash attention 通常沒副作用（數學上等價、品質不變）、是 PC 場景長 context 推論的預設啟用旗標。詳見 &lt;a href="https://tarrragon.github.io/blog/llm/05-discrete-gpu/kv-cache-quantization-strategy/" data-link-title="5.2 KV cache 量化策略" data-link-desc="PC 場景用 K=Q8 / V=Q4 等量化把 KV cache 壓縮、騰出 VRAM 開大 context window 或加併發數的判讀">5.2 KV cache 量化策略&lt;/a> 的 flash attention 段落。&lt;/p></description><content:encoded><![CDATA[<p>Flash Attention 的核心概念是「重新組織 <a href="/blog/llm/knowledge-cards/attention/" data-link-title="Attention" data-link-desc="Transformer 內部讓每個 token 對其他 token 加權平均的核心機制、形成 KV cache 跟 context window 的計算基礎">Attention</a> 計算的順序、把中間結果留在 GPU 高速 cache、減少對 GPU memory 的讀寫往返」。它不改變 attention 的數學定義（輸出跟原始實作在浮點誤差範圍內一致）、但實作層面對長 context 推論吞吐有明顯提升、且是部分 <a href="/blog/llm/05-discrete-gpu/kv-cache-quantization-strategy/" data-link-title="5.2 KV cache 量化策略" data-link-desc="PC 場景用 K=Q8 / V=Q4 等量化把 KV cache 壓縮、騰出 VRAM 開大 context window 或加併發數的判讀">KV cache 量化</a> 組合在 llama.cpp 上的必要前置。</p>
<h2 id="概念位置">概念位置</h2>
<p>Flash Attention 在推論架構中的角色：</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="ln">1</span><span class="cl">推論時的 attention 計算：
</span></span><span class="line"><span class="ln">2</span><span class="cl">  ├── 原始實作：Q · K^T 整個算完、寫進 memory、再讀出來做 softmax、再算 · V
</span></span><span class="line"><span class="ln">3</span><span class="cl">  │     └── 多次 memory 讀寫、長 context 下 IO 成為瓶頸
</span></span><span class="line"><span class="ln">4</span><span class="cl">  └── Flash Attention：用 tiling 把計算切塊、中間結果留在 SRAM / register
</span></span><span class="line"><span class="ln">5</span><span class="cl">        └── 減少 memory 讀寫、長 context 加速明顯</span></span></code></pre></div><p>跟 attention 變體的關係：</p>
<ul>
<li>Flash Attention 是<strong>實作層</strong>的優化、跟 <a href="/blog/llm/knowledge-cards/attention/" data-link-title="Attention" data-link-desc="Transformer 內部讓每個 token 對其他 token 加權平均的核心機制、形成 KV cache 跟 context window 的計算基礎">MHA / GQA / MLA</a> 等<strong>架構層</strong>變體是兩個獨立維度。</li>
<li>不同變體都能搭配 Flash Attention 的實作技巧。</li>
</ul>
<p>在 llama.cpp 中的旗標：</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="ln">1</span><span class="cl">llama-server -fa  <span class="c1"># 啟用 flash attention</span>
</span></span><span class="line"><span class="ln">2</span><span class="cl"><span class="c1"># 或</span>
</span></span><span class="line"><span class="ln">3</span><span class="cl">llama-server --flash-attn</span></span></code></pre></div><blockquote>
<p><strong>事實查核註</strong>：Flash Attention 的版本演進快（Flash Attention 1 / 2 / 3）、不同推論引擎的支援度依版本變化。具體限制（如「V cache Q4 量化要 -fa 才能啟用」）依 llama.cpp 版本變動、引用前以 <code>llama-server --help</code> 跟 release notes 為準。</p></blockquote>
<h2 id="設計責任">設計責任</h2>
<p>理解 Flash Attention 後可以解釋兩個現象：為什麼啟用 <code>-fa</code> 後長 context 推論速度提升明顯（IO bound 變 compute bound）、為什麼部分 KV cache 量化組合（如 V=Q4_0）在 llama.cpp 上需要 flash attention 才能跑（實作層面的耦合）。</p>
<p>工程實務上、啟用 flash attention 通常沒副作用（數學上等價、品質不變）、是 PC 場景長 context 推論的預設啟用旗標。詳見 <a href="/blog/llm/05-discrete-gpu/kv-cache-quantization-strategy/" data-link-title="5.2 KV cache 量化策略" data-link-desc="PC 場景用 K=Q8 / V=Q4 等量化把 KV cache 壓縮、騰出 VRAM 開大 context window 或加併發數的判讀">5.2 KV cache 量化策略</a> 的 flash attention 段落。</p>
]]></content:encoded></item><item><title>Floating Point（FP32 / FP16 / BF16）</title><link>https://tarrragon.github.io/blog/llm/knowledge-cards/floating-point/</link><pubDate>Tue, 12 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/llm/knowledge-cards/floating-point/</guid><description>&lt;p>Floating point（浮點數）的核心概念是「&lt;strong>用「符號位 + 指數位 + 尾數位」表示實數的二進制格式&lt;/strong>」。LLM 訓練跟推論用的精度（fp32 / bf16 / fp16）就是不同的位元分配方案。理解這些差異能解釋為什麼 bf16 是訓練主流、為什麼 &lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/quantization/" data-link-title="Quantization" data-link-desc="用較少 bits 表示模型權重：壓縮記憶體佔用、加快生字速度，代價是少量品質衰減">量化&lt;/a> 對品質的影響不是「越多 bit 越好」這麼簡單。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>主流浮點格式的位元分配：&lt;/p>
&lt;table>
 &lt;thead>
 &lt;tr>
 &lt;th>格式&lt;/th>
 &lt;th>總 bit&lt;/th>
 &lt;th>符號位&lt;/th>
 &lt;th>指數位&lt;/th>
 &lt;th>尾數位&lt;/th>
 &lt;th>動態範圍&lt;/th>
 &lt;th>精度（有效位數）&lt;/th>
 &lt;/tr>
 &lt;/thead>
 &lt;tbody>
 &lt;tr>
 &lt;td>FP32&lt;/td>
 &lt;td>32&lt;/td>
 &lt;td>1&lt;/td>
 &lt;td>8&lt;/td>
 &lt;td>23&lt;/td>
 &lt;td>±10^38&lt;/td>
 &lt;td>7 位&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>FP16&lt;/td>
 &lt;td>16&lt;/td>
 &lt;td>1&lt;/td>
 &lt;td>5&lt;/td>
 &lt;td>10&lt;/td>
 &lt;td>±65504（容易 overflow）&lt;/td>
 &lt;td>4 位&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>BF16&lt;/td>
 &lt;td>16&lt;/td>
 &lt;td>1&lt;/td>
 &lt;td>8&lt;/td>
 &lt;td>7&lt;/td>
 &lt;td>±10^38（同 fp32）&lt;/td>
 &lt;td>3 位&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>FP8 (E4M3 / E5M2)&lt;/td>
 &lt;td>8&lt;/td>
 &lt;td>1&lt;/td>
 &lt;td>4 / 5&lt;/td>
 &lt;td>3 / 2&lt;/td>
 &lt;td>視變體&lt;/td>
 &lt;td>1-2 位&lt;/td>
 &lt;/tr>
 &lt;/tbody>
&lt;/table>
&lt;p>關鍵 trade-off：&lt;/p>
&lt;ol>
&lt;li>&lt;strong>FP16 精度好、範圍窄&lt;/strong>：尾數多、表達小範圍內細節準；但指數少、容易 overflow（gradient 爆炸時）/ underflow（gradient 接近 0 時）。&lt;/li>
&lt;li>&lt;strong>BF16 範圍跟 fp32 一樣大、精度差&lt;/strong>：指數位跟 fp32 同（8 位）、訓練時的 dynamic range 跟 fp32 接近、不會 overflow；但尾數少、精度差。實測對訓練影響小、所以是現代 LLM 訓練主流。&lt;/li>
&lt;li>&lt;strong>FP8 是新興格式&lt;/strong>：H100 / B200 等新 GPU 原生支援、訓練 / 推論都能加速、但精度損失需要 careful loss scaling。&lt;/li>
&lt;/ol>
&lt;p>LLM 工作流的精度選擇：&lt;/p>
&lt;table>
 &lt;thead>
 &lt;tr>
 &lt;th>場景&lt;/th>
 &lt;th>主流精度&lt;/th>
 &lt;/tr>
 &lt;/thead>
 &lt;tbody>
 &lt;tr>
 &lt;td>Pre-training（大模型）&lt;/td>
 &lt;td>BF16 + 部分 FP32（如 optimizer state）&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>Fine-tuning&lt;/td>
 &lt;td>BF16 + 可選 FP8 / Q4（QLoRA）&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>推論（雲端 high-end）&lt;/td>
 &lt;td>FP16 / BF16&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>推論（消費級本機）&lt;/td>
 &lt;td>Q4_K_M 等量化、見 &lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/quantization/" data-link-title="Quantization" data-link-desc="用較少 bits 表示模型權重：壓縮記憶體佔用、加快生字速度，代價是少量品質衰減">quantization&lt;/a>&lt;/td>
 &lt;/tr>
 &lt;/tbody>
&lt;/table>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>讀 paper / config 看到 &lt;code>mixed_precision: bf16&lt;/code>、&lt;code>torch_dtype: bfloat16&lt;/code> 就是 BF16 訓練。寫 code 場景的判讀：本機跑 &lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/gguf/" data-link-title="GGUF" data-link-desc="llama.cpp 生態定義的模型權重格式：把權重、tokenizer、metadata 打包成單一檔案">GGUF&lt;/a> Q4_K_M 模型、內部運算的 activation 仍是 fp16 / bf16、只有權重儲存是 4-bit；&lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/kv-cache/" data-link-title="KV Cache" data-link-desc="已處理 token 的 attention 中間結果暫存：避免重算、加速後續生成">KV cache&lt;/a> 預設也是 fp16、量化 KV cache 是進階優化（K=Q8 / V=Q4）。&lt;/p></description><content:encoded><![CDATA[<p>Floating point（浮點數）的核心概念是「<strong>用「符號位 + 指數位 + 尾數位」表示實數的二進制格式</strong>」。LLM 訓練跟推論用的精度（fp32 / bf16 / fp16）就是不同的位元分配方案。理解這些差異能解釋為什麼 bf16 是訓練主流、為什麼 <a href="/blog/llm/knowledge-cards/quantization/" data-link-title="Quantization" data-link-desc="用較少 bits 表示模型權重：壓縮記憶體佔用、加快生字速度，代價是少量品質衰減">量化</a> 對品質的影響不是「越多 bit 越好」這麼簡單。</p>
<h2 id="概念位置">概念位置</h2>
<p>主流浮點格式的位元分配：</p>
<table>
  <thead>
      <tr>
          <th>格式</th>
          <th>總 bit</th>
          <th>符號位</th>
          <th>指數位</th>
          <th>尾數位</th>
          <th>動態範圍</th>
          <th>精度（有效位數）</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>FP32</td>
          <td>32</td>
          <td>1</td>
          <td>8</td>
          <td>23</td>
          <td>±10^38</td>
          <td>7 位</td>
      </tr>
      <tr>
          <td>FP16</td>
          <td>16</td>
          <td>1</td>
          <td>5</td>
          <td>10</td>
          <td>±65504（容易 overflow）</td>
          <td>4 位</td>
      </tr>
      <tr>
          <td>BF16</td>
          <td>16</td>
          <td>1</td>
          <td>8</td>
          <td>7</td>
          <td>±10^38（同 fp32）</td>
          <td>3 位</td>
      </tr>
      <tr>
          <td>FP8 (E4M3 / E5M2)</td>
          <td>8</td>
          <td>1</td>
          <td>4 / 5</td>
          <td>3 / 2</td>
          <td>視變體</td>
          <td>1-2 位</td>
      </tr>
  </tbody>
</table>
<p>關鍵 trade-off：</p>
<ol>
<li><strong>FP16 精度好、範圍窄</strong>：尾數多、表達小範圍內細節準；但指數少、容易 overflow（gradient 爆炸時）/ underflow（gradient 接近 0 時）。</li>
<li><strong>BF16 範圍跟 fp32 一樣大、精度差</strong>：指數位跟 fp32 同（8 位）、訓練時的 dynamic range 跟 fp32 接近、不會 overflow；但尾數少、精度差。實測對訓練影響小、所以是現代 LLM 訓練主流。</li>
<li><strong>FP8 是新興格式</strong>：H100 / B200 等新 GPU 原生支援、訓練 / 推論都能加速、但精度損失需要 careful loss scaling。</li>
</ol>
<p>LLM 工作流的精度選擇：</p>
<table>
  <thead>
      <tr>
          <th>場景</th>
          <th>主流精度</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>Pre-training（大模型）</td>
          <td>BF16 + 部分 FP32（如 optimizer state）</td>
      </tr>
      <tr>
          <td>Fine-tuning</td>
          <td>BF16 + 可選 FP8 / Q4（QLoRA）</td>
      </tr>
      <tr>
          <td>推論（雲端 high-end）</td>
          <td>FP16 / BF16</td>
      </tr>
      <tr>
          <td>推論（消費級本機）</td>
          <td>Q4_K_M 等量化、見 <a href="/blog/llm/knowledge-cards/quantization/" data-link-title="Quantization" data-link-desc="用較少 bits 表示模型權重：壓縮記憶體佔用、加快生字速度，代價是少量品質衰減">quantization</a></td>
      </tr>
  </tbody>
</table>
<h2 id="設計責任">設計責任</h2>
<p>讀 paper / config 看到 <code>mixed_precision: bf16</code>、<code>torch_dtype: bfloat16</code> 就是 BF16 訓練。寫 code 場景的判讀：本機跑 <a href="/blog/llm/knowledge-cards/gguf/" data-link-title="GGUF" data-link-desc="llama.cpp 生態定義的模型權重格式：把權重、tokenizer、metadata 打包成單一檔案">GGUF</a> Q4_K_M 模型、內部運算的 activation 仍是 fp16 / bf16、只有權重儲存是 4-bit；<a href="/blog/llm/knowledge-cards/kv-cache/" data-link-title="KV Cache" data-link-desc="已處理 token 的 attention 中間結果暫存：避免重算、加速後續生成">KV cache</a> 預設也是 fp16、量化 KV cache 是進階優化（K=Q8 / V=Q4）。</p>
]]></content:encoded></item><item><title>Forward Pass</title><link>https://tarrragon.github.io/blog/llm/knowledge-cards/forward-pass/</link><pubDate>Tue, 12 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/llm/knowledge-cards/forward-pass/</guid><description>&lt;p>Forward pass（前向傳播）的核心概念是「input 從第一層算到最後一層、得到 output 的單向計算流程」。LLM 推論時生成一個 &lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/token/" data-link-title="Token" data-link-desc="LLM 處理文字時的最小單位：介於字元與單字之間">token&lt;/a>、就是跑一次 forward pass；訓練時、每個 batch 也都先跑 forward pass 算出 &lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/loss-function/" data-link-title="Loss Function" data-link-desc="把「模型預測」跟「正確答案」的差距量化成一個純量、訓練的最佳化目標">loss&lt;/a>、再跑 &lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/backpropagation/" data-link-title="Backpropagation" data-link-desc="從 output loss 反向遞推、用 chain rule 算出每個權重的 gradient 的演算法">backpropagation&lt;/a> 算 gradient。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>LLM 一次 forward pass 的大略流程：&lt;/p>





&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-text" data-lang="text">&lt;span class="line">&lt;span class="ln"> 1&lt;/span>&lt;span class="cl">input token IDs
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 2&lt;/span>&lt;span class="cl"> ↓ embedding layer：整數 → 向量
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 3&lt;/span>&lt;span class="cl">sequence of vectors
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 4&lt;/span>&lt;span class="cl"> ↓ Transformer block 1（attention + FFN）
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 5&lt;/span>&lt;span class="cl"> ↓ Transformer block 2
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 6&lt;/span>&lt;span class="cl"> ↓ ...
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 7&lt;/span>&lt;span class="cl"> ↓ Transformer block N
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 8&lt;/span>&lt;span class="cl">final hidden state
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 9&lt;/span>&lt;span class="cl"> ↓ output projection（hidden → vocab）
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">10&lt;/span>&lt;span class="cl">logits（每個 vocab token 一個分數）
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">11&lt;/span>&lt;span class="cl"> ↓ softmax（推論時）
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">12&lt;/span>&lt;span class="cl">probability distribution → 挑下一個 token&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>跟相關概念的對比：&lt;/p>
&lt;table>
 &lt;thead>
 &lt;tr>
 &lt;th>概念&lt;/th>
 &lt;th>跟 forward pass 的關係&lt;/th>
 &lt;/tr>
 &lt;/thead>
 &lt;tbody>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/prefill/" data-link-title="Prefill" data-link-desc="Prompt 首次處理時的計算階段：把整段輸入跑過模型、產生 KV cache">Prefill&lt;/a>&lt;/td>
 &lt;td>Prompt 階段的「一次性 forward pass」、所有 prompt token 並行&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>Decode 階段&lt;/td>
 &lt;td>每生一個 token 跑一次 forward pass、序列化、慢&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/speculative-decoding/" data-link-title="Speculative Decoding" data-link-desc="用小模型猜未來 token、大模型並行驗證的加速技巧">Speculative decoding&lt;/a>&lt;/td>
 &lt;td>一次 forward pass 同時驗證多個猜測 token&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/backpropagation/" data-link-title="Backpropagation" data-link-desc="從 output loss 反向遞推、用 chain rule 算出每個權重的 gradient 的演算法">Backpropagation&lt;/a>&lt;/td>
 &lt;td>訓練時 forward pass 的反向延伸、推論不需要&lt;/td>
 &lt;/tr>
 &lt;/tbody>
&lt;/table>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>理解 forward pass 後可以判讀 LLM 的記憶體與速度：每次 forward pass 都要把整份模型權重從記憶體讀到處理器一次、所以 &lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/memory-bandwidth/" data-link-title="Memory Bandwidth" data-link-desc="記憶體每秒能讀寫多少 bytes：決定本地 LLM 生字速度的真正瓶頸">memory bandwidth&lt;/a> 是推論瓶頸；&lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/kv-cache/" data-link-title="KV Cache" data-link-desc="已處理 token 的 attention 中間結果暫存：避免重算、加速後續生成">KV cache&lt;/a> 的存在是為了避免每次 forward pass 重算前面 token 的 K/V；MTP / speculative decoding 都是「一次 forward pass 攤平多個 token 成本」的優化路徑。&lt;/p></description><content:encoded><![CDATA[<p>Forward pass（前向傳播）的核心概念是「input 從第一層算到最後一層、得到 output 的單向計算流程」。LLM 推論時生成一個 <a href="/blog/llm/knowledge-cards/token/" data-link-title="Token" data-link-desc="LLM 處理文字時的最小單位：介於字元與單字之間">token</a>、就是跑一次 forward pass；訓練時、每個 batch 也都先跑 forward pass 算出 <a href="/blog/llm/knowledge-cards/loss-function/" data-link-title="Loss Function" data-link-desc="把「模型預測」跟「正確答案」的差距量化成一個純量、訓練的最佳化目標">loss</a>、再跑 <a href="/blog/llm/knowledge-cards/backpropagation/" data-link-title="Backpropagation" data-link-desc="從 output loss 反向遞推、用 chain rule 算出每個權重的 gradient 的演算法">backpropagation</a> 算 gradient。</p>
<h2 id="概念位置">概念位置</h2>
<p>LLM 一次 forward pass 的大略流程：</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="ln"> 1</span><span class="cl">input token IDs
</span></span><span class="line"><span class="ln"> 2</span><span class="cl">  ↓ embedding layer：整數 → 向量
</span></span><span class="line"><span class="ln"> 3</span><span class="cl">sequence of vectors
</span></span><span class="line"><span class="ln"> 4</span><span class="cl">  ↓ Transformer block 1（attention + FFN）
</span></span><span class="line"><span class="ln"> 5</span><span class="cl">  ↓ Transformer block 2
</span></span><span class="line"><span class="ln"> 6</span><span class="cl">  ↓ ...
</span></span><span class="line"><span class="ln"> 7</span><span class="cl">  ↓ Transformer block N
</span></span><span class="line"><span class="ln"> 8</span><span class="cl">final hidden state
</span></span><span class="line"><span class="ln"> 9</span><span class="cl">  ↓ output projection（hidden → vocab）
</span></span><span class="line"><span class="ln">10</span><span class="cl">logits（每個 vocab token 一個分數）
</span></span><span class="line"><span class="ln">11</span><span class="cl">  ↓ softmax（推論時）
</span></span><span class="line"><span class="ln">12</span><span class="cl">probability distribution → 挑下一個 token</span></span></code></pre></div><p>跟相關概念的對比：</p>
<table>
  <thead>
      <tr>
          <th>概念</th>
          <th>跟 forward pass 的關係</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td><a href="/blog/llm/knowledge-cards/prefill/" data-link-title="Prefill" data-link-desc="Prompt 首次處理時的計算階段：把整段輸入跑過模型、產生 KV cache">Prefill</a></td>
          <td>Prompt 階段的「一次性 forward pass」、所有 prompt token 並行</td>
      </tr>
      <tr>
          <td>Decode 階段</td>
          <td>每生一個 token 跑一次 forward pass、序列化、慢</td>
      </tr>
      <tr>
          <td><a href="/blog/llm/knowledge-cards/speculative-decoding/" data-link-title="Speculative Decoding" data-link-desc="用小模型猜未來 token、大模型並行驗證的加速技巧">Speculative decoding</a></td>
          <td>一次 forward pass 同時驗證多個猜測 token</td>
      </tr>
      <tr>
          <td><a href="/blog/llm/knowledge-cards/backpropagation/" data-link-title="Backpropagation" data-link-desc="從 output loss 反向遞推、用 chain rule 算出每個權重的 gradient 的演算法">Backpropagation</a></td>
          <td>訓練時 forward pass 的反向延伸、推論不需要</td>
      </tr>
  </tbody>
</table>
<h2 id="設計責任">設計責任</h2>
<p>理解 forward pass 後可以判讀 LLM 的記憶體與速度：每次 forward pass 都要把整份模型權重從記憶體讀到處理器一次、所以 <a href="/blog/llm/knowledge-cards/memory-bandwidth/" data-link-title="Memory Bandwidth" data-link-desc="記憶體每秒能讀寫多少 bytes：決定本地 LLM 生字速度的真正瓶頸">memory bandwidth</a> 是推論瓶頸；<a href="/blog/llm/knowledge-cards/kv-cache/" data-link-title="KV Cache" data-link-desc="已處理 token 的 attention 中間結果暫存：避免重算、加速後續生成">KV cache</a> 的存在是為了避免每次 forward pass 重算前面 token 的 K/V；MTP / speculative decoding 都是「一次 forward pass 攤平多個 token 成本」的優化路徑。</p>
]]></content:encoded></item><item><title>GPU Compute Backend</title><link>https://tarrragon.github.io/blog/llm/knowledge-cards/gpu-compute-backend/</link><pubDate>Tue, 12 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/llm/knowledge-cards/gpu-compute-backend/</guid><description>&lt;p>GPU compute backend 的核心概念是「推論軟體（如 llama.cpp、PyTorch）跟 GPU 之間的計算 API 抽象層」。不同廠商 GPU 對應不同 backend、同一推論軟體通常要為每個 backend 編譯獨立 build。選對 backend 直接影響 GPU 算力能否被有效利用。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>各家 GPU 對應的常見 backend（2026 年 5 月狀態、依社群實踐變化）：&lt;/p>
&lt;table>
 &lt;thead>
 &lt;tr>
 &lt;th>Backend&lt;/th>
 &lt;th>主要 GPU 廠商&lt;/th>
 &lt;th>平台支援&lt;/th>
 &lt;th>llama.cpp 生態成熟度&lt;/th>
 &lt;/tr>
 &lt;/thead>
 &lt;tbody>
 &lt;tr>
 &lt;td>CUDA&lt;/td>
 &lt;td>NVIDIA&lt;/td>
 &lt;td>Windows / Linux&lt;/td>
 &lt;td>最成熟、社群預設&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>ROCm&lt;/td>
 &lt;td>AMD&lt;/td>
 &lt;td>Linux 主、Windows 演進中&lt;/td>
 &lt;td>中、依 GPU 型號變化&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>Vulkan&lt;/td>
 &lt;td>跨廠商通用&lt;/td>
 &lt;td>Windows / Linux&lt;/td>
 &lt;td>中、通用 fallback&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>Metal&lt;/td>
 &lt;td>Apple Silicon&lt;/td>
 &lt;td>macOS&lt;/td>
 &lt;td>成熟（屬模組一範圍）&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>SYCL&lt;/td>
 &lt;td>Intel ARC&lt;/td>
 &lt;td>Windows / Linux&lt;/td>
 &lt;td>相對年輕&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>DirectML&lt;/td>
 &lt;td>多廠商（DirectX）&lt;/td>
 &lt;td>Windows&lt;/td>
 &lt;td>較少用於 LLM&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>OpenVINO&lt;/td>
 &lt;td>Intel&lt;/td>
 &lt;td>多平台&lt;/td>
 &lt;td>偏 Intel 生態&lt;/td>
 &lt;/tr>
 &lt;/tbody>
&lt;/table>
&lt;p>選 backend 的判讀依硬體跟平台：NVIDIA GPU 用 CUDA、AMD on Linux 優先 ROCm、AMD on Windows 多用 Vulkan、Intel ARC 用 Vulkan 或 SYCL、Apple Silicon 用 Metal。&lt;/p>
&lt;blockquote>
&lt;p>&lt;strong>事實查核註&lt;/strong>：上表的「llama.cpp 生態成熟度」是社群常見回報、不是經本卡系統實測的 benchmark；各 backend 的支援度跟 throughput 依推論軟體版本快速演進、引用前以對應 backend 的官方文件跟 &lt;a href="https://github.com/ggml-org/llama.cpp/releases">llama.cpp release notes&lt;/a> 為準。&lt;/p>&lt;/blockquote>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>理解 GPU compute backend 後可以解釋三個現象：為什麼下載 llama.cpp release 要選 CUDA / ROCm / Vulkan 版本（每個 build 對應一種 backend）、為什麼同樣硬體 throughput 差很多（backend 不對或 fallback 到 CPU）、為什麼非 NVIDIA GPU 跑 LLM 經驗較少（CUDA 生態太成熟、其他 backend 仍在演進）。&lt;/p>
&lt;p>選 PC GPU 跑本地 LLM 時、backend 成熟度是「工具鏈支援度」軸、跟硬體規格軸獨立、選卡時兩軸都要考慮。詳見 &lt;a href="https://tarrragon.github.io/blog/llm/05-discrete-gpu/gpu-vendor-differences/" data-link-title="5.6 GPU 廠商差異" data-link-desc="NVIDIA CUDA、AMD ROCm、Intel ARC 在 llama.cpp 生態的相對位置、選卡時的判讀軸">5.6 GPU 廠商差異&lt;/a>。&lt;/p></description><content:encoded><![CDATA[<p>GPU compute backend 的核心概念是「推論軟體（如 llama.cpp、PyTorch）跟 GPU 之間的計算 API 抽象層」。不同廠商 GPU 對應不同 backend、同一推論軟體通常要為每個 backend 編譯獨立 build。選對 backend 直接影響 GPU 算力能否被有效利用。</p>
<h2 id="概念位置">概念位置</h2>
<p>各家 GPU 對應的常見 backend（2026 年 5 月狀態、依社群實踐變化）：</p>
<table>
  <thead>
      <tr>
          <th>Backend</th>
          <th>主要 GPU 廠商</th>
          <th>平台支援</th>
          <th>llama.cpp 生態成熟度</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>CUDA</td>
          <td>NVIDIA</td>
          <td>Windows / Linux</td>
          <td>最成熟、社群預設</td>
      </tr>
      <tr>
          <td>ROCm</td>
          <td>AMD</td>
          <td>Linux 主、Windows 演進中</td>
          <td>中、依 GPU 型號變化</td>
      </tr>
      <tr>
          <td>Vulkan</td>
          <td>跨廠商通用</td>
          <td>Windows / Linux</td>
          <td>中、通用 fallback</td>
      </tr>
      <tr>
          <td>Metal</td>
          <td>Apple Silicon</td>
          <td>macOS</td>
          <td>成熟（屬模組一範圍）</td>
      </tr>
      <tr>
          <td>SYCL</td>
          <td>Intel ARC</td>
          <td>Windows / Linux</td>
          <td>相對年輕</td>
      </tr>
      <tr>
          <td>DirectML</td>
          <td>多廠商（DirectX）</td>
          <td>Windows</td>
          <td>較少用於 LLM</td>
      </tr>
      <tr>
          <td>OpenVINO</td>
          <td>Intel</td>
          <td>多平台</td>
          <td>偏 Intel 生態</td>
      </tr>
  </tbody>
</table>
<p>選 backend 的判讀依硬體跟平台：NVIDIA GPU 用 CUDA、AMD on Linux 優先 ROCm、AMD on Windows 多用 Vulkan、Intel ARC 用 Vulkan 或 SYCL、Apple Silicon 用 Metal。</p>
<blockquote>
<p><strong>事實查核註</strong>：上表的「llama.cpp 生態成熟度」是社群常見回報、不是經本卡系統實測的 benchmark；各 backend 的支援度跟 throughput 依推論軟體版本快速演進、引用前以對應 backend 的官方文件跟 <a href="https://github.com/ggml-org/llama.cpp/releases">llama.cpp release notes</a> 為準。</p></blockquote>
<h2 id="設計責任">設計責任</h2>
<p>理解 GPU compute backend 後可以解釋三個現象：為什麼下載 llama.cpp release 要選 CUDA / ROCm / Vulkan 版本（每個 build 對應一種 backend）、為什麼同樣硬體 throughput 差很多（backend 不對或 fallback 到 CPU）、為什麼非 NVIDIA GPU 跑 LLM 經驗較少（CUDA 生態太成熟、其他 backend 仍在演進）。</p>
<p>選 PC GPU 跑本地 LLM 時、backend 成熟度是「工具鏈支援度」軸、跟硬體規格軸獨立、選卡時兩軸都要考慮。詳見 <a href="/blog/llm/05-discrete-gpu/gpu-vendor-differences/" data-link-title="5.6 GPU 廠商差異" data-link-desc="NVIDIA CUDA、AMD ROCm、Intel ARC 在 llama.cpp 生態的相對位置、選卡時的判讀軸">5.6 GPU 廠商差異</a>。</p>
]]></content:encoded></item><item><title>Gradient</title><link>https://tarrragon.github.io/blog/llm/knowledge-cards/gradient/</link><pubDate>Tue, 12 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/llm/knowledge-cards/gradient/</guid><description>&lt;p>Gradient（梯度）的核心概念是「&lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/loss-function/" data-link-title="Loss Function" data-link-desc="把「模型預測」跟「正確答案」的差距量化成一個純量、訓練的最佳化目標">loss function&lt;/a> 對每個權重的偏微分組成的向量」。每個分量回答「這個權重往正方向動一單位、loss 會變多少」、整個 gradient 向量指向「loss 上升最快的方向」、所以訓練時往&lt;strong>反方向&lt;/strong>走、就是讓 loss 下降最快的方向。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>Gradient 連接「loss」跟「該怎麼更新權重」兩件事、是 &lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/backpropagation/" data-link-title="Backpropagation" data-link-desc="從 output loss 反向遞推、用 chain rule 算出每個權重的 gradient 的演算法">backpropagation&lt;/a> 算出來的東西、也是 SGD / Adam 等 optimizer 消費的輸入：&lt;/p>





&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-text" data-lang="text">&lt;span class="line">&lt;span class="ln">1&lt;/span>&lt;span class="cl">[forward pass] → 算出 loss
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">2&lt;/span>&lt;span class="cl"> ↓
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">3&lt;/span>&lt;span class="cl">[backpropagation] → 算出 gradient（每個權重一個值）
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">4&lt;/span>&lt;span class="cl"> ↓
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">5&lt;/span>&lt;span class="cl">[optimizer] → 用 gradient 更新權重：w_new = w_old - lr × gradient&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>Gradient 在 LLM 訓練中的兩個常見問題：&lt;/p>
&lt;table>
 &lt;thead>
 &lt;tr>
 &lt;th>問題&lt;/th>
 &lt;th>訊號&lt;/th>
 &lt;th>處理&lt;/th>
 &lt;/tr>
 &lt;/thead>
 &lt;tbody>
 &lt;tr>
 &lt;td>Gradient 爆炸&lt;/td>
 &lt;td>loss 突然變 NaN、梯度 norm &amp;gt; 1000&lt;/td>
 &lt;td>Gradient clipping（截斷 norm 上限）、降 learning rate&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>Gradient 消失&lt;/td>
 &lt;td>深層權重幾乎不更新、loss 停在某 plateau&lt;/td>
 &lt;td>Residual connection、Layer normalization、改 activation function&lt;/td>
 &lt;/tr>
 &lt;/tbody>
&lt;/table>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>推論階段（拿訓練好的模型生 token）&lt;strong>不需要算 gradient&lt;/strong>、只有 forward pass；gradient 只在訓練 / fine-tuning 階段出現。所以本地跑 LLM 寫 code 的場景不會碰到 gradient、但讀懂訓練流程、理解「為什麼 SFT / RLHF 需要 GPU、推論不一定要」這類判讀就要先理解 gradient 的角色。&lt;/p></description><content:encoded><![CDATA[<p>Gradient（梯度）的核心概念是「<a href="/blog/llm/knowledge-cards/loss-function/" data-link-title="Loss Function" data-link-desc="把「模型預測」跟「正確答案」的差距量化成一個純量、訓練的最佳化目標">loss function</a> 對每個權重的偏微分組成的向量」。每個分量回答「這個權重往正方向動一單位、loss 會變多少」、整個 gradient 向量指向「loss 上升最快的方向」、所以訓練時往<strong>反方向</strong>走、就是讓 loss 下降最快的方向。</p>
<h2 id="概念位置">概念位置</h2>
<p>Gradient 連接「loss」跟「該怎麼更新權重」兩件事、是 <a href="/blog/llm/knowledge-cards/backpropagation/" data-link-title="Backpropagation" data-link-desc="從 output loss 反向遞推、用 chain rule 算出每個權重的 gradient 的演算法">backpropagation</a> 算出來的東西、也是 SGD / Adam 等 optimizer 消費的輸入：</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="ln">1</span><span class="cl">[forward pass] → 算出 loss
</span></span><span class="line"><span class="ln">2</span><span class="cl">                    ↓
</span></span><span class="line"><span class="ln">3</span><span class="cl">[backpropagation] → 算出 gradient（每個權重一個值）
</span></span><span class="line"><span class="ln">4</span><span class="cl">                    ↓
</span></span><span class="line"><span class="ln">5</span><span class="cl">[optimizer] → 用 gradient 更新權重：w_new = w_old - lr × gradient</span></span></code></pre></div><p>Gradient 在 LLM 訓練中的兩個常見問題：</p>
<table>
  <thead>
      <tr>
          <th>問題</th>
          <th>訊號</th>
          <th>處理</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>Gradient 爆炸</td>
          <td>loss 突然變 NaN、梯度 norm &gt; 1000</td>
          <td>Gradient clipping（截斷 norm 上限）、降 learning rate</td>
      </tr>
      <tr>
          <td>Gradient 消失</td>
          <td>深層權重幾乎不更新、loss 停在某 plateau</td>
          <td>Residual connection、Layer normalization、改 activation function</td>
      </tr>
  </tbody>
</table>
<h2 id="設計責任">設計責任</h2>
<p>推論階段（拿訓練好的模型生 token）<strong>不需要算 gradient</strong>、只有 forward pass；gradient 只在訓練 / fine-tuning 階段出現。所以本地跑 LLM 寫 code 的場景不會碰到 gradient、但讀懂訓練流程、理解「為什麼 SFT / RLHF 需要 GPU、推論不一定要」這類判讀就要先理解 gradient 的角色。</p>
]]></content:encoded></item><item><title>Gradient Explosion / Vanishing</title><link>https://tarrragon.github.io/blog/llm/knowledge-cards/gradient-explosion-vanishing/</link><pubDate>Tue, 12 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/llm/knowledge-cards/gradient-explosion-vanishing/</guid><description>&lt;p>Gradient explosion（爆炸）跟 gradient vanishing（消失）的核心概念是「深層網路的 &lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/backpropagation/" data-link-title="Backpropagation" data-link-desc="從 output loss 反向遞推、用 chain rule 算出每個權重的 gradient 的演算法">backpropagation&lt;/a> 透過 chain rule 一層層相乘、若每層 gradient &amp;gt; 1、累乘到輸入層會指數爆炸；若每層 gradient &amp;lt; 1、累乘到輸入層會衰減到接近 0」。兩者是深層網路訓不起來的典型病因、現代 Transformer 用 &lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/residual-connection/" data-link-title="Residual Connection" data-link-desc="把 layer 的輸入直接加到輸出上的「跳接」、讓深層網路的梯度能穩定回流">residual connection&lt;/a> + &lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/layer-normalization/" data-link-title="Layer Normalization" data-link-desc="在每個 token 的 hidden state 上做正規化（減 mean、除 std）、穩定深層網路訓練">layer normalization&lt;/a> 解決。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>兩種失敗模式的訊號跟處理：&lt;/p>
&lt;table>
 &lt;thead>
 &lt;tr>
 &lt;th>模式&lt;/th>
 &lt;th>訊號&lt;/th>
 &lt;th>主要成因&lt;/th>
 &lt;th>處理&lt;/th>
 &lt;/tr>
 &lt;/thead>
 &lt;tbody>
 &lt;tr>
 &lt;td>Gradient explosion&lt;/td>
 &lt;td>loss 突然變 NaN、gradient norm &amp;gt; 1000+&lt;/td>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/learning-rate/" data-link-title="Learning Rate" data-link-desc="gradient descent 每步更新權重的幅度、訓練中最敏感的 hyperparameter">Learning rate&lt;/a> 太大、初始化不當、loss 函數有奇點&lt;/td>
 &lt;td>Gradient clipping（截斷 norm 上限、如 1.0）、降低 lr、檢查資料 outliers&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>Gradient vanishing&lt;/td>
 &lt;td>深層權重幾乎不更新、loss 卡 plateau&lt;/td>
 &lt;td>層數深、activation 飽和區（sigmoid、tanh）、缺 skip connection&lt;/td>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/residual-connection/" data-link-title="Residual Connection" data-link-desc="把 layer 的輸入直接加到輸出上的「跳接」、讓深層網路的梯度能穩定回流">Residual connection&lt;/a> + &lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/layer-normalization/" data-link-title="Layer Normalization" data-link-desc="在每個 token 的 hidden state 上做正規化（減 mean、除 std）、穩定深層網路訓練">layer norm&lt;/a> + 換 activation（ReLU / GELU / SwiGLU）&lt;/td>
 &lt;/tr>
 &lt;/tbody>
&lt;/table>
&lt;p>數學直覺（簡化）：&lt;/p>





&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-text" data-lang="text">&lt;span class="line">&lt;span class="ln">1&lt;/span>&lt;span class="cl">深 N 層的 chain rule：
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">2&lt;/span>&lt;span class="cl">∂loss/∂W_input = ∂loss/∂out × ∂out/∂h_N × ∂h_N/∂h_{N-1} × ... × ∂h_1/∂W_input
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">3&lt;/span>&lt;span class="cl"> └──────────── N 個 factor 連乘 ──────────────┘
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">4&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">5&lt;/span>&lt;span class="cl">若每個 factor ≈ 0.5、N=100：累乘 ≈ 0.5^100 ≈ 0 → vanishing
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">6&lt;/span>&lt;span class="cl">若每個 factor ≈ 1.5、N=100：累乘 ≈ 1.5^100 ≈ 4e17 → explosion&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>&lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/residual-connection/" data-link-title="Residual Connection" data-link-desc="把 layer 的輸入直接加到輸出上的「跳接」、讓深層網路的梯度能穩定回流">Residual connection&lt;/a> 讓 gradient 有「捷徑」可走、不全靠 chain rule 一層層乘、是深層 Transformer 訓得起來的核心結構之一。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>讀訓練 log 看到 &lt;code>loss: nan&lt;/code>、&lt;code>grad_norm: inf&lt;/code> 就是 explosion；看到 loss 平穩、幾個 epoch 都不降就是可能的 vanishing。寫 code 場景幾乎不會碰到（推論不算 gradient）、但自己 fine-tune 時要會判讀。LLM 用的 SwiGLU / GELU 都是 saturation 較不嚴重的 activation、加上 &lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/residual-connection/" data-link-title="Residual Connection" data-link-desc="把 layer 的輸入直接加到輸出上的「跳接」、讓深層網路的梯度能穩定回流">residual&lt;/a> + &lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/layer-normalization/" data-link-title="Layer Normalization" data-link-desc="在每個 token 的 hidden state 上做正規化（減 mean、除 std）、穩定深層網路訓練">pre-norm&lt;/a>、現代 Transformer 訓 100+ 層相對穩定。&lt;/p></description><content:encoded><![CDATA[<p>Gradient explosion（爆炸）跟 gradient vanishing（消失）的核心概念是「深層網路的 <a href="/blog/llm/knowledge-cards/backpropagation/" data-link-title="Backpropagation" data-link-desc="從 output loss 反向遞推、用 chain rule 算出每個權重的 gradient 的演算法">backpropagation</a> 透過 chain rule 一層層相乘、若每層 gradient &gt; 1、累乘到輸入層會指數爆炸；若每層 gradient &lt; 1、累乘到輸入層會衰減到接近 0」。兩者是深層網路訓不起來的典型病因、現代 Transformer 用 <a href="/blog/llm/knowledge-cards/residual-connection/" data-link-title="Residual Connection" data-link-desc="把 layer 的輸入直接加到輸出上的「跳接」、讓深層網路的梯度能穩定回流">residual connection</a> + <a href="/blog/llm/knowledge-cards/layer-normalization/" data-link-title="Layer Normalization" data-link-desc="在每個 token 的 hidden state 上做正規化（減 mean、除 std）、穩定深層網路訓練">layer normalization</a> 解決。</p>
<h2 id="概念位置">概念位置</h2>
<p>兩種失敗模式的訊號跟處理：</p>
<table>
  <thead>
      <tr>
          <th>模式</th>
          <th>訊號</th>
          <th>主要成因</th>
          <th>處理</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>Gradient explosion</td>
          <td>loss 突然變 NaN、gradient norm &gt; 1000+</td>
          <td><a href="/blog/llm/knowledge-cards/learning-rate/" data-link-title="Learning Rate" data-link-desc="gradient descent 每步更新權重的幅度、訓練中最敏感的 hyperparameter">Learning rate</a> 太大、初始化不當、loss 函數有奇點</td>
          <td>Gradient clipping（截斷 norm 上限、如 1.0）、降低 lr、檢查資料 outliers</td>
      </tr>
      <tr>
          <td>Gradient vanishing</td>
          <td>深層權重幾乎不更新、loss 卡 plateau</td>
          <td>層數深、activation 飽和區（sigmoid、tanh）、缺 skip connection</td>
          <td><a href="/blog/llm/knowledge-cards/residual-connection/" data-link-title="Residual Connection" data-link-desc="把 layer 的輸入直接加到輸出上的「跳接」、讓深層網路的梯度能穩定回流">Residual connection</a> + <a href="/blog/llm/knowledge-cards/layer-normalization/" data-link-title="Layer Normalization" data-link-desc="在每個 token 的 hidden state 上做正規化（減 mean、除 std）、穩定深層網路訓練">layer norm</a> + 換 activation（ReLU / GELU / SwiGLU）</td>
      </tr>
  </tbody>
</table>
<p>數學直覺（簡化）：</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="ln">1</span><span class="cl">深 N 層的 chain rule：
</span></span><span class="line"><span class="ln">2</span><span class="cl">∂loss/∂W_input = ∂loss/∂out × ∂out/∂h_N × ∂h_N/∂h_{N-1} × ... × ∂h_1/∂W_input
</span></span><span class="line"><span class="ln">3</span><span class="cl">                                └──────────── N 個 factor 連乘 ──────────────┘
</span></span><span class="line"><span class="ln">4</span><span class="cl">
</span></span><span class="line"><span class="ln">5</span><span class="cl">若每個 factor ≈ 0.5、N=100：累乘 ≈ 0.5^100 ≈ 0       → vanishing
</span></span><span class="line"><span class="ln">6</span><span class="cl">若每個 factor ≈ 1.5、N=100：累乘 ≈ 1.5^100 ≈ 4e17    → explosion</span></span></code></pre></div><p><a href="/blog/llm/knowledge-cards/residual-connection/" data-link-title="Residual Connection" data-link-desc="把 layer 的輸入直接加到輸出上的「跳接」、讓深層網路的梯度能穩定回流">Residual connection</a> 讓 gradient 有「捷徑」可走、不全靠 chain rule 一層層乘、是深層 Transformer 訓得起來的核心結構之一。</p>
<h2 id="設計責任">設計責任</h2>
<p>讀訓練 log 看到 <code>loss: nan</code>、<code>grad_norm: inf</code> 就是 explosion；看到 loss 平穩、幾個 epoch 都不降就是可能的 vanishing。寫 code 場景幾乎不會碰到（推論不算 gradient）、但自己 fine-tune 時要會判讀。LLM 用的 SwiGLU / GELU 都是 saturation 較不嚴重的 activation、加上 <a href="/blog/llm/knowledge-cards/residual-connection/" data-link-title="Residual Connection" data-link-desc="把 layer 的輸入直接加到輸出上的「跳接」、讓深層網路的梯度能穩定回流">residual</a> + <a href="/blog/llm/knowledge-cards/layer-normalization/" data-link-title="Layer Normalization" data-link-desc="在每個 token 的 hidden state 上做正規化（減 mean、除 std）、穩定深層網路訓練">pre-norm</a>、現代 Transformer 訓 100+ 層相對穩定。</p>
]]></content:encoded></item><item><title>Hallucination</title><link>https://tarrragon.github.io/blog/llm/knowledge-cards/hallucination/</link><pubDate>Tue, 12 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/llm/knowledge-cards/hallucination/</guid><description>&lt;p>Hallucination 的核心概念是「LLM 生成的內容語法、語氣、結構看起來合理、但內容上是事實錯誤、引用不存在的來源、虛構不存在的 entity」。這是 LLM 基於統計分布生成的固有特性；以目前的研究跟工程實踐、靠「更大模型」或「更好對齊」很難徹底消除、可控的做法是用工程手段降低觸發率跟下游偵測。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>Hallucination 的常見形態：&lt;/p>
&lt;table>
 &lt;thead>
 &lt;tr>
 &lt;th>形態&lt;/th>
 &lt;th>例子&lt;/th>
 &lt;th>風險&lt;/th>
 &lt;/tr>
 &lt;/thead>
 &lt;tbody>
 &lt;tr>
 &lt;td>虛構引用&lt;/td>
 &lt;td>引用不存在的論文 / API / 函式名稱&lt;/td>
 &lt;td>使用者照抄、出錯&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>虛構 entity&lt;/td>
 &lt;td>虛構不存在的公司 / 人名 / 地址&lt;/td>
 &lt;td>寫入文件、產生誤導&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>數值幻覺&lt;/td>
 &lt;td>給看似精確但實際錯誤的數字&lt;/td>
 &lt;td>商業 / 工程決策被誤導&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>因果幻覺&lt;/td>
 &lt;td>編造看似合理但不存在的因果關係&lt;/td>
 &lt;td>推理鏈不可信&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>法律 / 醫療幻覺&lt;/td>
 &lt;td>虛構不存在的法條 / 治療方案&lt;/td>
 &lt;td>高風險領域、可能造成實際傷害&lt;/td>
 &lt;/tr>
 &lt;/tbody>
&lt;/table>
&lt;p>降低 / 偵測 hallucination 的常見手段（依場景變化）：&lt;/p>
&lt;ol>
&lt;li>&lt;strong>&lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/rag/" data-link-title="RAG" data-link-desc="Retrieval-Augmented Generation：動態外掛知識給 LLM、繞開模型參數記憶的靜態限制">RAG&lt;/a>&lt;/strong>：把真實內容檢索後注入 prompt、模型基於真實內容生成。&lt;/li>
&lt;li>&lt;strong>temperature 降低&lt;/strong>：採樣較保守、減少創造性但也減少幻覺。&lt;/li>
&lt;li>&lt;strong>citation 要求&lt;/strong>：prompt 要求列出引用、後續可驗證。&lt;/li>
&lt;li>&lt;strong>下游驗證&lt;/strong>：對輸出做事實檢查（如 code 跑 compiler、引用查實際資料庫）。&lt;/li>
&lt;li>&lt;strong>明確的「不知道就說不知道」instruction&lt;/strong>：降低過度自信、但不能消除。&lt;/li>
&lt;/ol>
&lt;blockquote>
&lt;p>&lt;strong>事實查核註&lt;/strong>：Hallucination 的研究跟降低技術仍在快速演進、不同模型、不同任務類型的 hallucination rate 變化大、引用前以最新研究跟具體 model card 為準。Stanford &lt;a href="https://arxiv.org/abs/2109.07958">TruthfulQA&lt;/a> 等 benchmark 是常見參考。&lt;/p>&lt;/blockquote>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>理解 hallucination 後可以解釋兩個現象：為什麼 LLM 給的「具體事實」（人名 / 數字 / 引用）特別要驗證（生成機制本身就會虛構）、為什麼 LLM 寫的 code 看似合理但 import 不存在的 package（hallucinate 出 library API）。&lt;/p>
&lt;p>production 場景下、hallucination 影響合規（生成包含真人 PII 的虛構內容仍是 PII 處理）、UX（使用者照抄誤導內容）、安全（生成假 URL 引發釣魚）；應對策略不是「擋住 hallucination」、是「降低觸發率 + 下游驗證 + 適當的 disclaimer」。詳見 &lt;a href="https://tarrragon.github.io/blog/backend/07-security-data-protection/llm-log-and-pii-governance/" data-link-title="LLM Log 與 PII 治理" data-link-desc="production LLM 服務的 prompt log 累積、PII 偵測與過濾、保留期限與合規對齊">LLM Log 與 PII 治理&lt;/a>。&lt;/p></description><content:encoded><![CDATA[<p>Hallucination 的核心概念是「LLM 生成的內容語法、語氣、結構看起來合理、但內容上是事實錯誤、引用不存在的來源、虛構不存在的 entity」。這是 LLM 基於統計分布生成的固有特性；以目前的研究跟工程實踐、靠「更大模型」或「更好對齊」很難徹底消除、可控的做法是用工程手段降低觸發率跟下游偵測。</p>
<h2 id="概念位置">概念位置</h2>
<p>Hallucination 的常見形態：</p>
<table>
  <thead>
      <tr>
          <th>形態</th>
          <th>例子</th>
          <th>風險</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>虛構引用</td>
          <td>引用不存在的論文 / API / 函式名稱</td>
          <td>使用者照抄、出錯</td>
      </tr>
      <tr>
          <td>虛構 entity</td>
          <td>虛構不存在的公司 / 人名 / 地址</td>
          <td>寫入文件、產生誤導</td>
      </tr>
      <tr>
          <td>數值幻覺</td>
          <td>給看似精確但實際錯誤的數字</td>
          <td>商業 / 工程決策被誤導</td>
      </tr>
      <tr>
          <td>因果幻覺</td>
          <td>編造看似合理但不存在的因果關係</td>
          <td>推理鏈不可信</td>
      </tr>
      <tr>
          <td>法律 / 醫療幻覺</td>
          <td>虛構不存在的法條 / 治療方案</td>
          <td>高風險領域、可能造成實際傷害</td>
      </tr>
  </tbody>
</table>
<p>降低 / 偵測 hallucination 的常見手段（依場景變化）：</p>
<ol>
<li><strong><a href="/blog/llm/knowledge-cards/rag/" data-link-title="RAG" data-link-desc="Retrieval-Augmented Generation：動態外掛知識給 LLM、繞開模型參數記憶的靜態限制">RAG</a></strong>：把真實內容檢索後注入 prompt、模型基於真實內容生成。</li>
<li><strong>temperature 降低</strong>：採樣較保守、減少創造性但也減少幻覺。</li>
<li><strong>citation 要求</strong>：prompt 要求列出引用、後續可驗證。</li>
<li><strong>下游驗證</strong>：對輸出做事實檢查（如 code 跑 compiler、引用查實際資料庫）。</li>
<li><strong>明確的「不知道就說不知道」instruction</strong>：降低過度自信、但不能消除。</li>
</ol>
<blockquote>
<p><strong>事實查核註</strong>：Hallucination 的研究跟降低技術仍在快速演進、不同模型、不同任務類型的 hallucination rate 變化大、引用前以最新研究跟具體 model card 為準。Stanford <a href="https://arxiv.org/abs/2109.07958">TruthfulQA</a> 等 benchmark 是常見參考。</p></blockquote>
<h2 id="設計責任">設計責任</h2>
<p>理解 hallucination 後可以解釋兩個現象：為什麼 LLM 給的「具體事實」（人名 / 數字 / 引用）特別要驗證（生成機制本身就會虛構）、為什麼 LLM 寫的 code 看似合理但 import 不存在的 package（hallucinate 出 library API）。</p>
<p>production 場景下、hallucination 影響合規（生成包含真人 PII 的虛構內容仍是 PII 處理）、UX（使用者照抄誤導內容）、安全（生成假 URL 引發釣魚）；應對策略不是「擋住 hallucination」、是「降低觸發率 + 下游驗證 + 適當的 disclaimer」。詳見 <a href="/blog/backend/07-security-data-protection/llm-log-and-pii-governance/" data-link-title="LLM Log 與 PII 治理" data-link-desc="production LLM 服務的 prompt log 累積、PII 偵測與過濾、保留期限與合規對齊">LLM Log 與 PII 治理</a>。</p>
]]></content:encoded></item><item><title>Homebrew</title><link>https://tarrragon.github.io/blog/llm/knowledge-cards/homebrew/</link><pubDate>Tue, 12 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/llm/knowledge-cards/homebrew/</guid><description>&lt;p>Homebrew 的核心概念是「macOS 的社群套件管理器、用 &lt;code>brew install&lt;/code> 一行裝完 CLI 工具或 GUI 程式」。對本地 LLM 場景的角色是「Ollama、llama.cpp 等命令列工具的標準安裝入口」、把編譯、依賴管理、PATH 設定、二進位放置位置都自動化。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>Homebrew 在 macOS 跟使用者要安裝的工具之間、扮演「公開 registry + 本地套件管理」的角色。它維護一份名為「formula」的 Ruby 腳本清單、每個 formula 描述某個工具怎麼下載、編譯、安裝。執行 &lt;code>brew install ollama&lt;/code> 時、Homebrew 找到 ollama formula、下載對應 bottle（預編譯二進位）、放到 &lt;code>/opt/homebrew/&lt;/code>（Apple Silicon）或 &lt;code>/usr/local/&lt;/code>（Intel Mac）、再把可執行檔 symlink 到 &lt;code>/opt/homebrew/bin/&lt;/code>。新機從零的完整安裝順序（含第一次裝 Homebrew、PATH 設定與晶片前綴差異）見 &lt;a href="https://tarrragon.github.io/blog/other/macos-%E6%96%B0%E6%A9%9F%E5%9F%BA%E7%A4%8E%E5%BB%BA%E8%A8%AD%E5%A5%97%E4%BB%B6%E7%AE%A1%E7%90%86%E8%88%87%E5%80%8B%E4%BA%BA-bin-%E7%9A%84%E8%A8%AD%E5%AE%9A%E9%A0%86%E5%BA%8F/" data-link-title="macOS 新機基礎建設：套件管理與個人 bin 的設定順序" data-link-desc="重灌或換機後底層基礎建設的依賴順序，免得後面工具裝不起來或路徑互相找不到。">macOS 新機基礎建設&lt;/a>。&lt;/p>
&lt;p>&lt;code>brew services&lt;/code> 是 Homebrew 附帶的服務管理子命令、把指令封裝成 macOS 原生的 &lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/launchd-service/" data-link-title="launchd Service" data-link-desc="macOS 原生的服務管理機制、把 process 註冊成自動啟動的 daemon 或 agent">launchd service&lt;/a>、處理「開機自動啟動 / 停止 / 重啟」需求。&lt;/p>
&lt;h2 id="可觀察訊號與例子">可觀察訊號與例子&lt;/h2>
&lt;p>日常會碰到的 brew 指令：&lt;/p>
&lt;table>
 &lt;thead>
 &lt;tr>
 &lt;th>指令&lt;/th>
 &lt;th>用途&lt;/th>
 &lt;/tr>
 &lt;/thead>
 &lt;tbody>
 &lt;tr>
 &lt;td>&lt;code>brew install &amp;lt;pkg&amp;gt;&lt;/code>&lt;/td>
 &lt;td>安裝套件&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;code>brew upgrade &amp;lt;pkg&amp;gt;&lt;/code>&lt;/td>
 &lt;td>升級單一套件&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;code>brew services start&lt;/code>&lt;/td>
 &lt;td>把套件註冊成 launchd service、立刻啟動&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;code>brew services list&lt;/code>&lt;/td>
 &lt;td>列出目前由 brew 管理的常駐服務&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;code>which &amp;lt;bin&amp;gt;&lt;/code>&lt;/td>
 &lt;td>確認可執行檔在 PATH 上的實際路徑&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;code>brew --prefix&lt;/code>&lt;/td>
 &lt;td>查 Homebrew 的安裝根目錄&lt;/td>
 &lt;/tr>
 &lt;/tbody>
&lt;/table>
&lt;p>Apple Silicon Mac 上的關鍵路徑是 &lt;code>/opt/homebrew/&lt;/code>、子資料夾各有角色：&lt;code>bin/&lt;/code>（可執行檔）、&lt;code>var/log/&lt;/code>（服務 log）、&lt;code>Cellar/&lt;/code>（套件實際內容）、&lt;code>opt/&lt;/code>（版本無關的 symlink）。看到「&lt;code>/opt/homebrew/var/log/ollama.log&lt;/code>」時、就是 brew 管理的 Ollama 服務 log 位置。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>用 brew 安裝 vs 用官方 .dmg / .pkg 的取捨：CLI 工具（ollama、llama.cpp、git 等）走 brew、好處是統一升級路徑；GUI 應用（LM Studio、Docker Desktop 等）多半改下載官方安裝包、因為 brew cask 不一定即時跟上版本。第一次裝 Homebrew 自己用官方 install script（在 &lt;a href="https://brew.sh">brew.sh&lt;/a>）、之後其他工具都從 brew 走。&lt;/p></description><content:encoded><![CDATA[<p>Homebrew 的核心概念是「macOS 的社群套件管理器、用 <code>brew install</code> 一行裝完 CLI 工具或 GUI 程式」。對本地 LLM 場景的角色是「Ollama、llama.cpp 等命令列工具的標準安裝入口」、把編譯、依賴管理、PATH 設定、二進位放置位置都自動化。</p>
<h2 id="概念位置">概念位置</h2>
<p>Homebrew 在 macOS 跟使用者要安裝的工具之間、扮演「公開 registry + 本地套件管理」的角色。它維護一份名為「formula」的 Ruby 腳本清單、每個 formula 描述某個工具怎麼下載、編譯、安裝。執行 <code>brew install ollama</code> 時、Homebrew 找到 ollama formula、下載對應 bottle（預編譯二進位）、放到 <code>/opt/homebrew/</code>（Apple Silicon）或 <code>/usr/local/</code>（Intel Mac）、再把可執行檔 symlink 到 <code>/opt/homebrew/bin/</code>。新機從零的完整安裝順序（含第一次裝 Homebrew、PATH 設定與晶片前綴差異）見 <a href="/blog/other/macos-%E6%96%B0%E6%A9%9F%E5%9F%BA%E7%A4%8E%E5%BB%BA%E8%A8%AD%E5%A5%97%E4%BB%B6%E7%AE%A1%E7%90%86%E8%88%87%E5%80%8B%E4%BA%BA-bin-%E7%9A%84%E8%A8%AD%E5%AE%9A%E9%A0%86%E5%BA%8F/" data-link-title="macOS 新機基礎建設：套件管理與個人 bin 的設定順序" data-link-desc="重灌或換機後底層基礎建設的依賴順序，免得後面工具裝不起來或路徑互相找不到。">macOS 新機基礎建設</a>。</p>
<p><code>brew services</code> 是 Homebrew 附帶的服務管理子命令、把指令封裝成 macOS 原生的 <a href="/blog/llm/knowledge-cards/launchd-service/" data-link-title="launchd Service" data-link-desc="macOS 原生的服務管理機制、把 process 註冊成自動啟動的 daemon 或 agent">launchd service</a>、處理「開機自動啟動 / 停止 / 重啟」需求。</p>
<h2 id="可觀察訊號與例子">可觀察訊號與例子</h2>
<p>日常會碰到的 brew 指令：</p>
<table>
  <thead>
      <tr>
          <th>指令</th>
          <th>用途</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td><code>brew install &lt;pkg&gt;</code></td>
          <td>安裝套件</td>
      </tr>
      <tr>
          <td><code>brew upgrade &lt;pkg&gt;</code></td>
          <td>升級單一套件</td>
      </tr>
      <tr>
          <td><code>brew services start</code></td>
          <td>把套件註冊成 launchd service、立刻啟動</td>
      </tr>
      <tr>
          <td><code>brew services list</code></td>
          <td>列出目前由 brew 管理的常駐服務</td>
      </tr>
      <tr>
          <td><code>which &lt;bin&gt;</code></td>
          <td>確認可執行檔在 PATH 上的實際路徑</td>
      </tr>
      <tr>
          <td><code>brew --prefix</code></td>
          <td>查 Homebrew 的安裝根目錄</td>
      </tr>
  </tbody>
</table>
<p>Apple Silicon Mac 上的關鍵路徑是 <code>/opt/homebrew/</code>、子資料夾各有角色：<code>bin/</code>（可執行檔）、<code>var/log/</code>（服務 log）、<code>Cellar/</code>（套件實際內容）、<code>opt/</code>（版本無關的 symlink）。看到「<code>/opt/homebrew/var/log/ollama.log</code>」時、就是 brew 管理的 Ollama 服務 log 位置。</p>
<h2 id="設計責任">設計責任</h2>
<p>用 brew 安裝 vs 用官方 .dmg / .pkg 的取捨：CLI 工具（ollama、llama.cpp、git 等）走 brew、好處是統一升級路徑；GUI 應用（LM Studio、Docker Desktop 等）多半改下載官方安裝包、因為 brew cask 不一定即時跟上版本。第一次裝 Homebrew 自己用官方 install script（在 <a href="https://brew.sh">brew.sh</a>）、之後其他工具都從 brew 走。</p>
]]></content:encoded></item><item><title>Hybrid Search</title><link>https://tarrragon.github.io/blog/llm/knowledge-cards/hybrid-search/</link><pubDate>Tue, 12 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/llm/knowledge-cards/hybrid-search/</guid><description>&lt;p>Hybrid search 的核心概念是「&lt;strong>同時跑字面 retrieval（BM25 / tf-idf）跟語意 retrieval（embedding similarity）、用 Reciprocal Rank Fusion 等方法合併結果&lt;/strong>」。補單一路線的盲點：BM25 抓不到語意相似（同義詞 / 不同表述）、embedding 抓不到精確 keyword（術語 / 識別碼 / 罕見 entity）。是 production RAG 的標配。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>兩條 retrieval 路線的盲點：&lt;/p>
&lt;table>
 &lt;thead>
 &lt;tr>
 &lt;th>場景&lt;/th>
 &lt;th>BM25（字面）&lt;/th>
 &lt;th>Embedding（語意）&lt;/th>
 &lt;/tr>
 &lt;/thead>
 &lt;tbody>
 &lt;tr>
 &lt;td>Query / doc 共用 keyword&lt;/td>
 &lt;td>強&lt;/td>
 &lt;td>強&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>Query 用同義詞、doc 用另一字&lt;/td>
 &lt;td>找不到&lt;/td>
 &lt;td>命中&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>Query 用通俗、doc 用 jargon&lt;/td>
 &lt;td>找不到&lt;/td>
 &lt;td>命中&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>精確 keyword（如 product code、UUID、API 名）&lt;/td>
 &lt;td>命中&lt;/td>
 &lt;td>可能漂掉&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>罕見 entity（人名 / 地名）&lt;/td>
 &lt;td>命中&lt;/td>
 &lt;td>弱（embedding model 不熟）&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>Embedding model 不熟的 domain&lt;/td>
 &lt;td>命中&lt;/td>
 &lt;td>表現崩&lt;/td>
 &lt;/tr>
 &lt;/tbody>
&lt;/table>
&lt;p>主流合併方法：&lt;/p>
&lt;h3 id="reciprocal-rank-fusionrrf">Reciprocal Rank Fusion（RRF）&lt;/h3>
&lt;p>最常用、簡單：&lt;/p>





&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-text" data-lang="text">&lt;span class="line">&lt;span class="ln"> 1&lt;/span>&lt;span class="cl">對每個 doc：
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 2&lt;/span>&lt;span class="cl"> score = sum_over_retrievers(1 / (k + rank_i))
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 3&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 4&lt;/span>&lt;span class="cl">k 是常數（典型 60）、rank 是該 retriever 給 doc 的排名
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 5&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 6&lt;/span>&lt;span class="cl">example：
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 7&lt;/span>&lt;span class="cl"> doc X 在 BM25 排名 3、在 embedding 排名 1
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 8&lt;/span>&lt;span class="cl"> RRF score = 1/(60+3) + 1/(60+1) = 0.0159 + 0.0164 = 0.0323
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 9&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">10&lt;/span>&lt;span class="cl">按 RRF score 排序、取 top-K&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>優點：不需要 normalize 不同 retriever 的分數、簡單可靠
缺點：不能 fine-tune 兩條路線的權重&lt;/p>
&lt;h3 id="weighted-score-fusion">Weighted score fusion&lt;/h3>
&lt;p>對每條路線的 score 加權平均：&lt;/p>





&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-text" data-lang="text">&lt;span class="line">&lt;span class="ln">1&lt;/span>&lt;span class="cl">score = α × BM25_score_normalized + (1-α) × embedding_score_normalized&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>優點：可以調 α 偏 BM25 或 embedding
缺點：要 normalize 兩個 score scale、調 α 是 hyper-parameter&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>讀 RAG production / retrieval framework 看到「hybrid search」「BM25 + dense」「RRF」就是這 framing。寫 code 場景的判讀：&lt;/p>
&lt;ol>
&lt;li>&lt;strong>何時值得加 hybrid&lt;/strong>：embedding-only retrieval 漏精確 keyword / 識別碼、BM25-only 漏語意相似、混合補完&lt;/li>
&lt;li>&lt;strong>何時不需要&lt;/strong>：純語意任務（embedding 已準）、純 keyword 任務（BM25 已準）、極小語料&lt;/li>
&lt;li>&lt;strong>跟 &lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/reranker/" data-link-title="Reranker" data-link-desc="對 retrieval top-K 結果用 cross-encoder 重新排序的 RAG 第二階段、品質提升顯著但 latency / cost 增加">reranker&lt;/a> 的組合&lt;/strong>：hybrid retrieve top-50（BM25 top-25 + embedding top-25、RRF 合併）→ reranker rerank → LLM top-5&lt;/li>
&lt;li>&lt;strong>主流實作&lt;/strong>：Elasticsearch / OpenSearch 內建、Weaviate / Qdrant / Pinecone 都支援、Postgres 用 pg_search + pgvector&lt;/li>
&lt;li>&lt;strong>跟 &lt;a href="https://tarrragon.github.io/blog/llm/04-applications/rag-principles/" data-link-title="4.1 RAG 原理：retrieval &amp;#43; augmentation 模式" data-link-desc="為什麼模型需要外掛知識、語意相似 vs 字面相似、chunking 的本質取捨、retrieval 失敗的根本原因">4.1 RAG 章節&lt;/a> 的關係&lt;/strong>：本卡是定義、章節是 retrieval pipeline 設計含 hybrid 段&lt;/li>
&lt;/ol></description><content:encoded><![CDATA[<p>Hybrid search 的核心概念是「<strong>同時跑字面 retrieval（BM25 / tf-idf）跟語意 retrieval（embedding similarity）、用 Reciprocal Rank Fusion 等方法合併結果</strong>」。補單一路線的盲點：BM25 抓不到語意相似（同義詞 / 不同表述）、embedding 抓不到精確 keyword（術語 / 識別碼 / 罕見 entity）。是 production RAG 的標配。</p>
<h2 id="概念位置">概念位置</h2>
<p>兩條 retrieval 路線的盲點：</p>
<table>
  <thead>
      <tr>
          <th>場景</th>
          <th>BM25（字面）</th>
          <th>Embedding（語意）</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>Query / doc 共用 keyword</td>
          <td>強</td>
          <td>強</td>
      </tr>
      <tr>
          <td>Query 用同義詞、doc 用另一字</td>
          <td>找不到</td>
          <td>命中</td>
      </tr>
      <tr>
          <td>Query 用通俗、doc 用 jargon</td>
          <td>找不到</td>
          <td>命中</td>
      </tr>
      <tr>
          <td>精確 keyword（如 product code、UUID、API 名）</td>
          <td>命中</td>
          <td>可能漂掉</td>
      </tr>
      <tr>
          <td>罕見 entity（人名 / 地名）</td>
          <td>命中</td>
          <td>弱（embedding model 不熟）</td>
      </tr>
      <tr>
          <td>Embedding model 不熟的 domain</td>
          <td>命中</td>
          <td>表現崩</td>
      </tr>
  </tbody>
</table>
<p>主流合併方法：</p>
<h3 id="reciprocal-rank-fusionrrf">Reciprocal Rank Fusion（RRF）</h3>
<p>最常用、簡單：</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="ln"> 1</span><span class="cl">對每個 doc：
</span></span><span class="line"><span class="ln"> 2</span><span class="cl">  score = sum_over_retrievers(1 / (k + rank_i))
</span></span><span class="line"><span class="ln"> 3</span><span class="cl">
</span></span><span class="line"><span class="ln"> 4</span><span class="cl">k 是常數（典型 60）、rank 是該 retriever 給 doc 的排名
</span></span><span class="line"><span class="ln"> 5</span><span class="cl">
</span></span><span class="line"><span class="ln"> 6</span><span class="cl">example：
</span></span><span class="line"><span class="ln"> 7</span><span class="cl">  doc X 在 BM25 排名 3、在 embedding 排名 1
</span></span><span class="line"><span class="ln"> 8</span><span class="cl">  RRF score = 1/(60+3) + 1/(60+1) = 0.0159 + 0.0164 = 0.0323
</span></span><span class="line"><span class="ln"> 9</span><span class="cl">
</span></span><span class="line"><span class="ln">10</span><span class="cl">按 RRF score 排序、取 top-K</span></span></code></pre></div><p>優點：不需要 normalize 不同 retriever 的分數、簡單可靠
缺點：不能 fine-tune 兩條路線的權重</p>
<h3 id="weighted-score-fusion">Weighted score fusion</h3>
<p>對每條路線的 score 加權平均：</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="ln">1</span><span class="cl">score = α × BM25_score_normalized + (1-α) × embedding_score_normalized</span></span></code></pre></div><p>優點：可以調 α 偏 BM25 或 embedding
缺點：要 normalize 兩個 score scale、調 α 是 hyper-parameter</p>
<h2 id="設計責任">設計責任</h2>
<p>讀 RAG production / retrieval framework 看到「hybrid search」「BM25 + dense」「RRF」就是這 framing。寫 code 場景的判讀：</p>
<ol>
<li><strong>何時值得加 hybrid</strong>：embedding-only retrieval 漏精確 keyword / 識別碼、BM25-only 漏語意相似、混合補完</li>
<li><strong>何時不需要</strong>：純語意任務（embedding 已準）、純 keyword 任務（BM25 已準）、極小語料</li>
<li><strong>跟 <a href="/blog/llm/knowledge-cards/reranker/" data-link-title="Reranker" data-link-desc="對 retrieval top-K 結果用 cross-encoder 重新排序的 RAG 第二階段、品質提升顯著但 latency / cost 增加">reranker</a> 的組合</strong>：hybrid retrieve top-50（BM25 top-25 + embedding top-25、RRF 合併）→ reranker rerank → LLM top-5</li>
<li><strong>主流實作</strong>：Elasticsearch / OpenSearch 內建、Weaviate / Qdrant / Pinecone 都支援、Postgres 用 pg_search + pgvector</li>
<li><strong>跟 <a href="/blog/llm/04-applications/rag-principles/" data-link-title="4.1 RAG 原理：retrieval &#43; augmentation 模式" data-link-desc="為什麼模型需要外掛知識、語意相似 vs 字面相似、chunking 的本質取捨、retrieval 失敗的根本原因">4.1 RAG 章節</a> 的關係</strong>：本卡是定義、章節是 retrieval pipeline 設計含 hybrid 段</li>
</ol>
]]></content:encoded></item><item><title>Image Token</title><link>https://tarrragon.github.io/blog/llm/knowledge-cards/image-token/</link><pubDate>Tue, 12 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/llm/knowledge-cards/image-token/</guid><description>&lt;p>Image token（圖片 token）的核心概念是「&lt;strong>&lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/vlm/" data-link-title="VLM（Vision-Language Model）" data-link-desc="同時吃圖片 &amp;#43; 文字輸入、產生文字輸出的 LLM 變體、coding 工作流中處理截圖 / 設計稿 / UI debug 的基底">VLM&lt;/a> 把圖片過 &lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/vision-encoder/" data-link-title="Vision Encoder" data-link-desc="VLM 內部負責把圖片轉成可進 Transformer 的向量序列的模組、ViT / CLIP encoder 為主流">vision encoder&lt;/a> 後、產出的向量序列、在 Transformer 內跟 text &lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/token/" data-link-title="Token" data-link-desc="LLM 處理文字時的最小單位：介於字元與單字之間">token&lt;/a> 同質處理&lt;/strong>」。理解這個概念能解釋為什麼「一張圖 = 幾百到幾千 token」、為什麼塞圖會吃掉 context budget、為什麼 VLM 推論比純文字 LLM 慢。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>從圖到 image token 的轉換：&lt;/p>





&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-text" data-lang="text">&lt;span class="line">&lt;span class="ln">1&lt;/span>&lt;span class="cl">Input image: 1024×1024 RGB
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">2&lt;/span>&lt;span class="cl"> ↓ Patchify（切 14×14 patch、得 ~5000 個 patch）
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">3&lt;/span>&lt;span class="cl"> ↓ Vision encoder（ViT 處理每個 patch、產 768/1024 維向量）
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">4&lt;/span>&lt;span class="cl"> ↓ Optional: 2D position embedding
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">5&lt;/span>&lt;span class="cl"> ↓ Optional: pooling / merging（減少 token 數）
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">6&lt;/span>&lt;span class="cl">Image tokens: ~500-2500 個（依模型設計）
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">7&lt;/span>&lt;span class="cl"> ↓ Projection（vision_dim → LLM hidden_dim、配合 LLM 內部維度）
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">8&lt;/span>&lt;span class="cl"> ↓ 跟 text token 串成單一 sequence
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">9&lt;/span>&lt;span class="cl"> ↓ Transformer 跟一般 token 一樣處理&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>主流 VLM 的單張圖 token 用量（粗略、依模型 / 解析度而變）：&lt;/p>
&lt;table>
 &lt;thead>
 &lt;tr>
 &lt;th>模型&lt;/th>
 &lt;th>預設輸入解析度&lt;/th>
 &lt;th>單張圖約用 token&lt;/th>
 &lt;th>Context 影響&lt;/th>
 &lt;/tr>
 &lt;/thead>
 &lt;tbody>
 &lt;tr>
 &lt;td>GPT-4o vision&lt;/td>
 &lt;td>動態（最高 2048×768）&lt;/td>
 &lt;td>~85 - 1000+&lt;/td>
 &lt;td>高解析度模式消耗大&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>Claude 3 vision&lt;/td>
 &lt;td>動態&lt;/td>
 &lt;td>~1000-1600&lt;/td>
 &lt;td>一張圖 ≈ 1.5K text token&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>Qwen2.5-VL&lt;/td>
 &lt;td>動態、可調 min/max&lt;/td>
 &lt;td>~500 - 4000&lt;/td>
 &lt;td>設定 &lt;code>min_pixels&lt;/code> 控制下限&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>Llama 3.2 Vision&lt;/td>
 &lt;td>固定（560×560）&lt;/td>
 &lt;td>~1600&lt;/td>
 &lt;td>多張圖直接乘&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>Gemma 3 Vision&lt;/td>
 &lt;td>動態&lt;/td>
 &lt;td>~256 - 2000&lt;/td>
 &lt;td>多語 / 多解析度&lt;/td>
 &lt;/tr>
 &lt;/tbody>
&lt;/table>
&lt;blockquote>
&lt;p>&lt;strong>事實查核註&lt;/strong>：上述 token 數量級依模型版本、推論配置（如「low / high detail」模式）變化、引用前以對應 model card 跟 API 文件為準。&lt;/p>&lt;/blockquote>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>讀 VLM API / 推論 log 看到「image tokens used: 1247」「visual tokens: 580」就是這指標。寫 code 場景的判讀：&lt;/p>
&lt;ol>
&lt;li>&lt;strong>多張截圖 = context 吃緊&lt;/strong>：一張 1500 token、丟 10 張就 15K、加上 prompt 跟回答、long context 模型才能 handle&lt;/li>
&lt;li>&lt;strong>同張圖、解析度模式影響成本&lt;/strong>：許多 API 提供 low / auto / high detail 模式、low detail 約 1/10 token；OCR 需要高解析、不細節辨識可選 low&lt;/li>
&lt;li>&lt;strong>本地 VLM 推論 prefill 慢&lt;/strong>：image token 多、prefill 階段（&lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/ttft/" data-link-title="TTFT" data-link-desc="Time To First Token：送出 prompt 到第一個 token 出現的等待時間">TTFT&lt;/a>）對應變長、第一個字出來要等較久&lt;/li>
&lt;li>&lt;strong>API 計費通常 image token 跟 text token 同價&lt;/strong>：算成本看實際用了多少 image token、不要假設「一張圖 = 一個 token」&lt;/li>
&lt;li>&lt;strong>Image token 是消耗品、不是參數&lt;/strong>：跟模型內部權重不同、純粹是「這次 forward pass 的 input」&lt;/li>
&lt;/ol></description><content:encoded><![CDATA[<p>Image token（圖片 token）的核心概念是「<strong><a href="/blog/llm/knowledge-cards/vlm/" data-link-title="VLM（Vision-Language Model）" data-link-desc="同時吃圖片 &#43; 文字輸入、產生文字輸出的 LLM 變體、coding 工作流中處理截圖 / 設計稿 / UI debug 的基底">VLM</a> 把圖片過 <a href="/blog/llm/knowledge-cards/vision-encoder/" data-link-title="Vision Encoder" data-link-desc="VLM 內部負責把圖片轉成可進 Transformer 的向量序列的模組、ViT / CLIP encoder 為主流">vision encoder</a> 後、產出的向量序列、在 Transformer 內跟 text <a href="/blog/llm/knowledge-cards/token/" data-link-title="Token" data-link-desc="LLM 處理文字時的最小單位：介於字元與單字之間">token</a> 同質處理</strong>」。理解這個概念能解釋為什麼「一張圖 = 幾百到幾千 token」、為什麼塞圖會吃掉 context budget、為什麼 VLM 推論比純文字 LLM 慢。</p>
<h2 id="概念位置">概念位置</h2>
<p>從圖到 image token 的轉換：</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="ln">1</span><span class="cl">Input image: 1024×1024 RGB
</span></span><span class="line"><span class="ln">2</span><span class="cl">   ↓ Patchify（切 14×14 patch、得 ~5000 個 patch）
</span></span><span class="line"><span class="ln">3</span><span class="cl">   ↓ Vision encoder（ViT 處理每個 patch、產 768/1024 維向量）
</span></span><span class="line"><span class="ln">4</span><span class="cl">   ↓ Optional: 2D position embedding
</span></span><span class="line"><span class="ln">5</span><span class="cl">   ↓ Optional: pooling / merging（減少 token 數）
</span></span><span class="line"><span class="ln">6</span><span class="cl">Image tokens: ~500-2500 個（依模型設計）
</span></span><span class="line"><span class="ln">7</span><span class="cl">   ↓ Projection（vision_dim → LLM hidden_dim、配合 LLM 內部維度）
</span></span><span class="line"><span class="ln">8</span><span class="cl">   ↓ 跟 text token 串成單一 sequence
</span></span><span class="line"><span class="ln">9</span><span class="cl">   ↓ Transformer 跟一般 token 一樣處理</span></span></code></pre></div><p>主流 VLM 的單張圖 token 用量（粗略、依模型 / 解析度而變）：</p>
<table>
  <thead>
      <tr>
          <th>模型</th>
          <th>預設輸入解析度</th>
          <th>單張圖約用 token</th>
          <th>Context 影響</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>GPT-4o vision</td>
          <td>動態（最高 2048×768）</td>
          <td>~85 - 1000+</td>
          <td>高解析度模式消耗大</td>
      </tr>
      <tr>
          <td>Claude 3 vision</td>
          <td>動態</td>
          <td>~1000-1600</td>
          <td>一張圖 ≈ 1.5K text token</td>
      </tr>
      <tr>
          <td>Qwen2.5-VL</td>
          <td>動態、可調 min/max</td>
          <td>~500 - 4000</td>
          <td>設定 <code>min_pixels</code> 控制下限</td>
      </tr>
      <tr>
          <td>Llama 3.2 Vision</td>
          <td>固定（560×560）</td>
          <td>~1600</td>
          <td>多張圖直接乘</td>
      </tr>
      <tr>
          <td>Gemma 3 Vision</td>
          <td>動態</td>
          <td>~256 - 2000</td>
          <td>多語 / 多解析度</td>
      </tr>
  </tbody>
</table>
<blockquote>
<p><strong>事實查核註</strong>：上述 token 數量級依模型版本、推論配置（如「low / high detail」模式）變化、引用前以對應 model card 跟 API 文件為準。</p></blockquote>
<h2 id="設計責任">設計責任</h2>
<p>讀 VLM API / 推論 log 看到「image tokens used: 1247」「visual tokens: 580」就是這指標。寫 code 場景的判讀：</p>
<ol>
<li><strong>多張截圖 = context 吃緊</strong>：一張 1500 token、丟 10 張就 15K、加上 prompt 跟回答、long context 模型才能 handle</li>
<li><strong>同張圖、解析度模式影響成本</strong>：許多 API 提供 low / auto / high detail 模式、low detail 約 1/10 token；OCR 需要高解析、不細節辨識可選 low</li>
<li><strong>本地 VLM 推論 prefill 慢</strong>：image token 多、prefill 階段（<a href="/blog/llm/knowledge-cards/ttft/" data-link-title="TTFT" data-link-desc="Time To First Token：送出 prompt 到第一個 token 出現的等待時間">TTFT</a>）對應變長、第一個字出來要等較久</li>
<li><strong>API 計費通常 image token 跟 text token 同價</strong>：算成本看實際用了多少 image token、不要假設「一張圖 = 一個 token」</li>
<li><strong>Image token 是消耗品、不是參數</strong>：跟模型內部權重不同、純粹是「這次 forward pass 的 input」</li>
</ol>
]]></content:encoded></item><item><title>KL Divergence</title><link>https://tarrragon.github.io/blog/llm/knowledge-cards/kl-divergence/</link><pubDate>Tue, 12 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/llm/knowledge-cards/kl-divergence/</guid><description>&lt;p>KL divergence（Kullback-Leibler divergence、KL 散度）的核心概念是「衡量兩個機率分佈 P 跟 Q 的差距」：&lt;code>KL(P ‖ Q) = sum(P(x) × log(P(x) / Q(x)))&lt;/code>。它&lt;strong>不對稱&lt;/strong>（&lt;code>KL(P ‖ Q) ≠ KL(Q ‖ P)&lt;/code>）、所以不算「距離」、是「散度」。在 LLM 訓練中是 alignment 階段防止模型「為了 reward 偏離太遠」的關鍵約束。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>KL divergence 在 LLM 中的兩個主要角色：&lt;/p>
&lt;ol>
&lt;li>
&lt;p>&lt;strong>跟 &lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/cross-entropy/" data-link-title="Cross-Entropy" data-link-desc="衡量「預測機率分佈」跟「真實分佈」距離的指標、LLM 預訓練的主要 loss">cross-entropy&lt;/a> 的關係&lt;/strong>：&lt;/p>





&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-text" data-lang="text">&lt;span class="line">&lt;span class="ln">1&lt;/span>&lt;span class="cl">cross-entropy(P, Q) = entropy(P) + KL(P ‖ Q)&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>訓練時 P（真實分佈）固定、entropy(P) 是常數、所以「minimize cross-entropy」等於「minimize KL」。&lt;/p>
&lt;/li>
&lt;li>
&lt;p>&lt;strong>RLHF / DPO 的「KL 約束」&lt;/strong>：&lt;/p>
&lt;p>alignment 階段不能只 maximize reward、否則模型會「為了 reward 把語言能力毀掉」。所以加 KL 約束：&lt;/p>





&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-text" data-lang="text">&lt;span class="line">&lt;span class="ln">1&lt;/span>&lt;span class="cl">objective = E[reward] - β × KL(π_new ‖ π_ref)
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">2&lt;/span>&lt;span class="cl"> └─ 不讓新模型偏離 ref（通常是 SFT 後的 base）太遠 ─┘&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>β 控制「reward 追求」vs「不偏離原始模型」的平衡。&lt;/p>
&lt;/li>
&lt;/ol>
&lt;p>跟相關概念的對比：&lt;/p>
&lt;table>
 &lt;thead>
 &lt;tr>
 &lt;th>指標&lt;/th>
 &lt;th>對稱？&lt;/th>
 &lt;th>主要用途&lt;/th>
 &lt;/tr>
 &lt;/thead>
 &lt;tbody>
 &lt;tr>
 &lt;td>Cross-entropy&lt;/td>
 &lt;td>否&lt;/td>
 &lt;td>訓練 loss、衡量預測機率分佈跟真實分佈&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>KL divergence&lt;/td>
 &lt;td>否&lt;/td>
 &lt;td>Alignment 訓練的偏離約束&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>JS divergence&lt;/td>
 &lt;td>是&lt;/td>
 &lt;td>兩個分佈的對稱差距、研究比較多&lt;/td>
 &lt;/tr>
 &lt;/tbody>
&lt;/table>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>讀 alignment paper 看到 β、KL penalty、KL coefficient 等詞、知道這些是控制「模型在追 reward 時偏離 base 多遠的容忍度」。β 太小、模型容易 reward hacking（找 reward 高但實質爛的輸出）；β 太大、模型動不了、reward 升不上去。DPO 把 KL 約束內嵌進 loss、不像 RLHF 需要顯式 KL term、是 DPO 比 RLHF 簡單的原因之一。&lt;/p></description><content:encoded><![CDATA[<p>KL divergence（Kullback-Leibler divergence、KL 散度）的核心概念是「衡量兩個機率分佈 P 跟 Q 的差距」：<code>KL(P ‖ Q) = sum(P(x) × log(P(x) / Q(x)))</code>。它<strong>不對稱</strong>（<code>KL(P ‖ Q) ≠ KL(Q ‖ P)</code>）、所以不算「距離」、是「散度」。在 LLM 訓練中是 alignment 階段防止模型「為了 reward 偏離太遠」的關鍵約束。</p>
<h2 id="概念位置">概念位置</h2>
<p>KL divergence 在 LLM 中的兩個主要角色：</p>
<ol>
<li>
<p><strong>跟 <a href="/blog/llm/knowledge-cards/cross-entropy/" data-link-title="Cross-Entropy" data-link-desc="衡量「預測機率分佈」跟「真實分佈」距離的指標、LLM 預訓練的主要 loss">cross-entropy</a> 的關係</strong>：</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="ln">1</span><span class="cl">cross-entropy(P, Q) = entropy(P) + KL(P ‖ Q)</span></span></code></pre></div><p>訓練時 P（真實分佈）固定、entropy(P) 是常數、所以「minimize cross-entropy」等於「minimize KL」。</p>
</li>
<li>
<p><strong>RLHF / DPO 的「KL 約束」</strong>：</p>
<p>alignment 階段不能只 maximize reward、否則模型會「為了 reward 把語言能力毀掉」。所以加 KL 約束：</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="ln">1</span><span class="cl">objective = E[reward] - β × KL(π_new ‖ π_ref)
</span></span><span class="line"><span class="ln">2</span><span class="cl">                         └─ 不讓新模型偏離 ref（通常是 SFT 後的 base）太遠 ─┘</span></span></code></pre></div><p>β 控制「reward 追求」vs「不偏離原始模型」的平衡。</p>
</li>
</ol>
<p>跟相關概念的對比：</p>
<table>
  <thead>
      <tr>
          <th>指標</th>
          <th>對稱？</th>
          <th>主要用途</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>Cross-entropy</td>
          <td>否</td>
          <td>訓練 loss、衡量預測機率分佈跟真實分佈</td>
      </tr>
      <tr>
          <td>KL divergence</td>
          <td>否</td>
          <td>Alignment 訓練的偏離約束</td>
      </tr>
      <tr>
          <td>JS divergence</td>
          <td>是</td>
          <td>兩個分佈的對稱差距、研究比較多</td>
      </tr>
  </tbody>
</table>
<h2 id="設計責任">設計責任</h2>
<p>讀 alignment paper 看到 β、KL penalty、KL coefficient 等詞、知道這些是控制「模型在追 reward 時偏離 base 多遠的容忍度」。β 太小、模型容易 reward hacking（找 reward 高但實質爛的輸出）；β 太大、模型動不了、reward 升不上去。DPO 把 KL 約束內嵌進 loss、不像 RLHF 需要顯式 KL term、是 DPO 比 RLHF 簡單的原因之一。</p>
]]></content:encoded></item><item><title>launchd Service</title><link>https://tarrragon.github.io/blog/llm/knowledge-cards/launchd-service/</link><pubDate>Tue, 12 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/llm/knowledge-cards/launchd-service/</guid><description>&lt;p>launchd Service 的核心概念是「macOS 用來管理常駐 process 生命週期的原生機制」。launchd 本身是 macOS 啟動後的第一個 process（PID 1）、由它負責拉起其他系統服務跟使用者註冊的背景任務。本地 LLM 場景中、Ollama 等推論伺服器透過 launchd 設定成「開機自動啟動、登入時自動拉起」、就不需要每次重開機都手動跑 &lt;code>ollama serve&lt;/code>。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>launchd service 用一份 plist（property list、XML 格式設定檔）描述「要跑哪個程式、何時啟動、出問題時要不要重啟、log 寫到哪裡」。plist 放在三個位置之一、決定服務的觸發範圍：&lt;/p>
&lt;table>
 &lt;thead>
 &lt;tr>
 &lt;th>路徑&lt;/th>
 &lt;th>角色&lt;/th>
 &lt;th>何時觸發&lt;/th>
 &lt;/tr>
 &lt;/thead>
 &lt;tbody>
 &lt;tr>
 &lt;td>&lt;code>~/Library/LaunchAgents/&lt;/code>&lt;/td>
 &lt;td>使用者 agent&lt;/td>
 &lt;td>該使用者登入時&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;code>/Library/LaunchAgents/&lt;/code>&lt;/td>
 &lt;td>全機所有使用者 agent&lt;/td>
 &lt;td>任何使用者登入時&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;code>/Library/LaunchDaemons/&lt;/code>&lt;/td>
 &lt;td>系統 daemon、需 root&lt;/td>
 &lt;td>macOS 開機時、不需登入&lt;/td>
 &lt;/tr>
 &lt;/tbody>
&lt;/table>
&lt;p>&lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/homebrew/" data-link-title="Homebrew" data-link-desc="macOS 上社群維護的套件管理器、用一行指令安裝 CLI 工具與背景服務">Homebrew&lt;/a> 的 &lt;code>brew services&lt;/code> 子命令是 launchd 的 wrapper、產生 plist 並放進 &lt;code>~/Library/LaunchAgents/&lt;/code>、避免使用者直接手寫 XML。Apple Silicon Mac 上產生的檔名形式是 &lt;code>homebrew.mxcl.&amp;lt;service&amp;gt;.plist&lt;/code>。&lt;/p>
&lt;h2 id="可觀察訊號與例子">可觀察訊號與例子&lt;/h2>
&lt;p>執行 &lt;code>brew services start ollama&lt;/code> 後可以驗證實際發生的事：&lt;/p>





&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-bash" data-lang="bash">&lt;span class="line">&lt;span class="ln">1&lt;/span>&lt;span class="cl">&lt;span class="c1"># 看 plist 內容&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">2&lt;/span>&lt;span class="cl">cat ~/Library/LaunchAgents/homebrew.mxcl.ollama.plist
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">3&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">4&lt;/span>&lt;span class="cl">&lt;span class="c1"># 用 launchctl 看服務狀態&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">5&lt;/span>&lt;span class="cl">launchctl list &lt;span class="p">|&lt;/span> grep ollama
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">6&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">7&lt;/span>&lt;span class="cl">&lt;span class="c1"># 看服務 log（Apple Silicon）&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">8&lt;/span>&lt;span class="cl">tail -f /opt/homebrew/var/log/ollama.log&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>plist 內常見的鍵：&lt;code>ProgramArguments&lt;/code>（要跑哪個指令）、&lt;code>RunAtLoad&lt;/code>（開機就啟動）、&lt;code>KeepAlive&lt;/code>（crash 後自動拉回）、&lt;code>StandardOutPath&lt;/code> / &lt;code>StandardErrorPath&lt;/code>（log 路徑）。出問題時先看 log 路徑指向的檔案、能直接看到 service 的 stdout / stderr。&lt;/p>
&lt;p>服務管理常用指令：&lt;/p>





&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-bash" data-lang="bash">&lt;span class="line">&lt;span class="ln">1&lt;/span>&lt;span class="cl">brew services list &lt;span class="c1"># 列出所有由 brew 管理的服務&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">2&lt;/span>&lt;span class="cl">brew services start ollama &lt;span class="c1"># 啟動 + 註冊自動啟動&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">3&lt;/span>&lt;span class="cl">brew services stop ollama &lt;span class="c1"># 停掉服務、保留 plist&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">4&lt;/span>&lt;span class="cl">brew services restart ollama &lt;span class="c1"># 升級套件後重啟&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>直接用系統的 &lt;code>launchctl&lt;/code> 也行、但語意較底層、實務上有 brew 包裝就用 brew。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>選擇「launchd service」vs「前景手動跑 &lt;code>ollama serve&lt;/code>」的判讀：日常用機建議用 launchd service、好處是重開機自動拉起、出問題的 log 有固定位置可看；只在偶爾用本地 LLM 的場景、保持手動跑反而省記憶體（沒在用就停掉）。升級套件後記得 &lt;code>brew services restart&lt;/code>、否則跑的還是舊版二進位。&lt;/p></description><content:encoded><![CDATA[<p>launchd Service 的核心概念是「macOS 用來管理常駐 process 生命週期的原生機制」。launchd 本身是 macOS 啟動後的第一個 process（PID 1）、由它負責拉起其他系統服務跟使用者註冊的背景任務。本地 LLM 場景中、Ollama 等推論伺服器透過 launchd 設定成「開機自動啟動、登入時自動拉起」、就不需要每次重開機都手動跑 <code>ollama serve</code>。</p>
<h2 id="概念位置">概念位置</h2>
<p>launchd service 用一份 plist（property list、XML 格式設定檔）描述「要跑哪個程式、何時啟動、出問題時要不要重啟、log 寫到哪裡」。plist 放在三個位置之一、決定服務的觸發範圍：</p>
<table>
  <thead>
      <tr>
          <th>路徑</th>
          <th>角色</th>
          <th>何時觸發</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td><code>~/Library/LaunchAgents/</code></td>
          <td>使用者 agent</td>
          <td>該使用者登入時</td>
      </tr>
      <tr>
          <td><code>/Library/LaunchAgents/</code></td>
          <td>全機所有使用者 agent</td>
          <td>任何使用者登入時</td>
      </tr>
      <tr>
          <td><code>/Library/LaunchDaemons/</code></td>
          <td>系統 daemon、需 root</td>
          <td>macOS 開機時、不需登入</td>
      </tr>
  </tbody>
</table>
<p><a href="/blog/llm/knowledge-cards/homebrew/" data-link-title="Homebrew" data-link-desc="macOS 上社群維護的套件管理器、用一行指令安裝 CLI 工具與背景服務">Homebrew</a> 的 <code>brew services</code> 子命令是 launchd 的 wrapper、產生 plist 並放進 <code>~/Library/LaunchAgents/</code>、避免使用者直接手寫 XML。Apple Silicon Mac 上產生的檔名形式是 <code>homebrew.mxcl.&lt;service&gt;.plist</code>。</p>
<h2 id="可觀察訊號與例子">可觀察訊號與例子</h2>
<p>執行 <code>brew services start ollama</code> 後可以驗證實際發生的事：</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="ln">1</span><span class="cl"><span class="c1"># 看 plist 內容</span>
</span></span><span class="line"><span class="ln">2</span><span class="cl">cat ~/Library/LaunchAgents/homebrew.mxcl.ollama.plist
</span></span><span class="line"><span class="ln">3</span><span class="cl">
</span></span><span class="line"><span class="ln">4</span><span class="cl"><span class="c1"># 用 launchctl 看服務狀態</span>
</span></span><span class="line"><span class="ln">5</span><span class="cl">launchctl list <span class="p">|</span> grep ollama
</span></span><span class="line"><span class="ln">6</span><span class="cl">
</span></span><span class="line"><span class="ln">7</span><span class="cl"><span class="c1"># 看服務 log（Apple Silicon）</span>
</span></span><span class="line"><span class="ln">8</span><span class="cl">tail -f /opt/homebrew/var/log/ollama.log</span></span></code></pre></div><p>plist 內常見的鍵：<code>ProgramArguments</code>（要跑哪個指令）、<code>RunAtLoad</code>（開機就啟動）、<code>KeepAlive</code>（crash 後自動拉回）、<code>StandardOutPath</code> / <code>StandardErrorPath</code>（log 路徑）。出問題時先看 log 路徑指向的檔案、能直接看到 service 的 stdout / stderr。</p>
<p>服務管理常用指令：</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="ln">1</span><span class="cl">brew services list             <span class="c1"># 列出所有由 brew 管理的服務</span>
</span></span><span class="line"><span class="ln">2</span><span class="cl">brew services start ollama     <span class="c1"># 啟動 + 註冊自動啟動</span>
</span></span><span class="line"><span class="ln">3</span><span class="cl">brew services stop ollama      <span class="c1"># 停掉服務、保留 plist</span>
</span></span><span class="line"><span class="ln">4</span><span class="cl">brew services restart ollama   <span class="c1"># 升級套件後重啟</span></span></span></code></pre></div><p>直接用系統的 <code>launchctl</code> 也行、但語意較底層、實務上有 brew 包裝就用 brew。</p>
<h2 id="設計責任">設計責任</h2>
<p>選擇「launchd service」vs「前景手動跑 <code>ollama serve</code>」的判讀：日常用機建議用 launchd service、好處是重開機自動拉起、出問題的 log 有固定位置可看；只在偶爾用本地 LLM 的場景、保持手動跑反而省記憶體（沒在用就停掉）。升級套件後記得 <code>brew services restart</code>、否則跑的還是舊版二進位。</p>
]]></content:encoded></item><item><title>Layer Normalization</title><link>https://tarrragon.github.io/blog/llm/knowledge-cards/layer-normalization/</link><pubDate>Tue, 12 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/llm/knowledge-cards/layer-normalization/</guid><description>&lt;p>Layer normalization（LayerNorm）的核心概念是「對單一 token 的 hidden state 向量做正規化」——把該向量的 mean 移到 0、std 縮到 1、再用兩個可學參數做仿射變換。它是 Transformer 穩定深層訓練的關鍵元件、跟 batch normalization 的差別是「正規化軸不同」、LayerNorm 對單個 sample 內部做、不依賴 batch 統計。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>LayerNorm 在 Transformer block 內的位置（現代主流是 pre-norm）：&lt;/p>





&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-text" data-lang="text">&lt;span class="line">&lt;span class="ln">1&lt;/span>&lt;span class="cl">Transformer block（pre-norm 配置）：
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">2&lt;/span>&lt;span class="cl"> x
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">3&lt;/span>&lt;span class="cl"> ↓ LayerNorm
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">4&lt;/span>&lt;span class="cl"> ↓ Self-Attention
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">5&lt;/span>&lt;span class="cl"> ↓ + 跟 x 做 residual connection
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">6&lt;/span>&lt;span class="cl"> ↓ LayerNorm
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">7&lt;/span>&lt;span class="cl"> ↓ FFN
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">8&lt;/span>&lt;span class="cl"> ↓ + 跟前一步輸出做 residual connection&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>主流變體比較：&lt;/p>
&lt;table>
 &lt;thead>
 &lt;tr>
 &lt;th>變體&lt;/th>
 &lt;th>計算&lt;/th>
 &lt;th>出現在&lt;/th>
 &lt;/tr>
 &lt;/thead>
 &lt;tbody>
 &lt;tr>
 &lt;td>LayerNorm&lt;/td>
 &lt;td>&lt;code>(x - mean) / std × γ + β&lt;/code>&lt;/td>
 &lt;td>早期 Transformer（GPT-2、BERT）&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>RMSNorm&lt;/td>
 &lt;td>&lt;code>x / rms(x) × γ&lt;/code>（不減 mean、不加 β）&lt;/td>
 &lt;td>Llama、Gemma、Qwen 等主流&lt;/td>
 &lt;/tr>
 &lt;/tbody>
&lt;/table>
&lt;p>RMSNorm 比 LayerNorm 簡單、實測訓練穩定性接近、推論更快（少算 mean 跟加 β）、所以現代 LLM 多用 RMSNorm。讀 paper 看到「RMSNorm」就是 LayerNorm 的這個簡化變體。&lt;/p>
&lt;p>Pre-norm vs post-norm：&lt;/p>
&lt;ul>
&lt;li>&lt;strong>Pre-norm&lt;/strong>（LayerNorm 在 attention / FFN 之前）：深度模型訓練較穩、現代主流。&lt;/li>
&lt;li>&lt;strong>Post-norm&lt;/strong>（LayerNorm 在 residual add 之後）：原始 Transformer paper 的設計、深層訓練不穩定。&lt;/li>
&lt;/ul>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>理解 LayerNorm 後可以判讀「深層 LLM 為什麼訓得起來」的部分答案：&lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/residual-connection/" data-link-title="Residual Connection" data-link-desc="把 layer 的輸入直接加到輸出上的「跳接」、讓深層網路的梯度能穩定回流">residual connection&lt;/a> + LayerNorm 是讓梯度能穩定流過幾十層 Transformer 的兩根支柱。讀 model card 看到「RMSNorm」「pre-norm」等詞、知道對應的設計選擇跟訓練穩定性意涵。&lt;/p></description><content:encoded><![CDATA[<p>Layer normalization（LayerNorm）的核心概念是「對單一 token 的 hidden state 向量做正規化」——把該向量的 mean 移到 0、std 縮到 1、再用兩個可學參數做仿射變換。它是 Transformer 穩定深層訓練的關鍵元件、跟 batch normalization 的差別是「正規化軸不同」、LayerNorm 對單個 sample 內部做、不依賴 batch 統計。</p>
<h2 id="概念位置">概念位置</h2>
<p>LayerNorm 在 Transformer block 內的位置（現代主流是 pre-norm）：</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="ln">1</span><span class="cl">Transformer block（pre-norm 配置）：
</span></span><span class="line"><span class="ln">2</span><span class="cl">  x
</span></span><span class="line"><span class="ln">3</span><span class="cl">  ↓ LayerNorm
</span></span><span class="line"><span class="ln">4</span><span class="cl">  ↓ Self-Attention
</span></span><span class="line"><span class="ln">5</span><span class="cl">  ↓ + 跟 x 做 residual connection
</span></span><span class="line"><span class="ln">6</span><span class="cl">  ↓ LayerNorm
</span></span><span class="line"><span class="ln">7</span><span class="cl">  ↓ FFN
</span></span><span class="line"><span class="ln">8</span><span class="cl">  ↓ + 跟前一步輸出做 residual connection</span></span></code></pre></div><p>主流變體比較：</p>
<table>
  <thead>
      <tr>
          <th>變體</th>
          <th>計算</th>
          <th>出現在</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>LayerNorm</td>
          <td><code>(x - mean) / std × γ + β</code></td>
          <td>早期 Transformer（GPT-2、BERT）</td>
      </tr>
      <tr>
          <td>RMSNorm</td>
          <td><code>x / rms(x) × γ</code>（不減 mean、不加 β）</td>
          <td>Llama、Gemma、Qwen 等主流</td>
      </tr>
  </tbody>
</table>
<p>RMSNorm 比 LayerNorm 簡單、實測訓練穩定性接近、推論更快（少算 mean 跟加 β）、所以現代 LLM 多用 RMSNorm。讀 paper 看到「RMSNorm」就是 LayerNorm 的這個簡化變體。</p>
<p>Pre-norm vs post-norm：</p>
<ul>
<li><strong>Pre-norm</strong>（LayerNorm 在 attention / FFN 之前）：深度模型訓練較穩、現代主流。</li>
<li><strong>Post-norm</strong>（LayerNorm 在 residual add 之後）：原始 Transformer paper 的設計、深層訓練不穩定。</li>
</ul>
<h2 id="設計責任">設計責任</h2>
<p>理解 LayerNorm 後可以判讀「深層 LLM 為什麼訓得起來」的部分答案：<a href="/blog/llm/knowledge-cards/residual-connection/" data-link-title="Residual Connection" data-link-desc="把 layer 的輸入直接加到輸出上的「跳接」、讓深層網路的梯度能穩定回流">residual connection</a> + LayerNorm 是讓梯度能穩定流過幾十層 Transformer 的兩根支柱。讀 model card 看到「RMSNorm」「pre-norm」等詞、知道對應的設計選擇跟訓練穩定性意涵。</p>
]]></content:encoded></item><item><title>Learning Rate</title><link>https://tarrragon.github.io/blog/llm/knowledge-cards/learning-rate/</link><pubDate>Tue, 12 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/llm/knowledge-cards/learning-rate/</guid><description>&lt;p>Learning rate（學習率、lr、α、η）的核心概念是「&lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/gradient/" data-link-title="Gradient" data-link-desc="loss function 對權重的偏微分向量、指出「該往哪個方向調權重才能讓 loss 下降最快」">gradient&lt;/a> 每步更新權重時、被乘上的純量縮放因子」。更新公式 &lt;code>W_new = W_old - lr × gradient&lt;/code> 裡的 lr 就是它。是訓練最敏感的單一 hyperparameter — 太大會 diverge（loss 飛走）、太小會訓得超慢或卡 local minimum。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>LLM 訓練 learning rate 的常見模式：&lt;/p>
&lt;table>
 &lt;thead>
 &lt;tr>
 &lt;th>階段&lt;/th>
 &lt;th>典型 lr&lt;/th>
 &lt;th>理由&lt;/th>
 &lt;/tr>
 &lt;/thead>
 &lt;tbody>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/pre-training/" data-link-title="Pre-training" data-link-desc="LLM 訓練的第一階段：用 trillion-token 級網路文字做 next-token prediction、得到 base model">Pre-training&lt;/a>&lt;/td>
 &lt;td>1e-4 ~ 3e-4&lt;/td>
 &lt;td>訓 trillion token、需要溫和的 lr 避免 diverge&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/sft/" data-link-title="SFT（Supervised Fine-Tuning）" data-link-desc="在 base model 上用「指令-回答」對資料微調、讓模型會跟著指令走">SFT&lt;/a>&lt;/td>
 &lt;td>1e-5 ~ 5e-5&lt;/td>
 &lt;td>base model 已收斂、用小 lr 微調避免 overshoot&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/rlhf/" data-link-title="RLHF" data-link-desc="Reinforcement Learning from Human Feedback：用人類偏好訓練的 reward model 透過 RL 對齊 LLM">RLHF&lt;/a> / &lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/dpo/" data-link-title="DPO（Direct Preference Optimization）" data-link-desc="RLHF 的簡化替代：跳過 reward model、直接從人類偏好資料 fine-tune LLM">DPO&lt;/a>&lt;/td>
 &lt;td>1e-7 ~ 1e-6&lt;/td>
 &lt;td>又比 SFT 更小、避免破壞 SFT 學到的對話能力&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/lora/" data-link-title="LoRA" data-link-desc="Low-Rank Adaptation：凍住原模型權重、只訓兩個小矩陣的 parameter-efficient fine-tuning">LoRA&lt;/a> fine-tune&lt;/td>
 &lt;td>1e-4 ~ 5e-4&lt;/td>
 &lt;td>只訓小 adapter、可用較大 lr&lt;/td>
 &lt;/tr>
 &lt;/tbody>
&lt;/table>
&lt;p>Learning rate schedule（lr 隨訓練步數調整）的主流模式：&lt;/p>
&lt;ol>
&lt;li>&lt;strong>Warmup&lt;/strong>：訓練最初幾百 ~ 幾千 step、lr 從 0 線性升到目標值。避免初期 gradient 大、模型瞬間 diverge。&lt;/li>
&lt;li>&lt;strong>Cosine decay&lt;/strong>：warmup 後、lr 用 cosine 函數從目標值降到接近 0。訓練後期細調。&lt;/li>
&lt;li>&lt;strong>WSD（Warmup-Stable-Decay）&lt;/strong>：近期變體、中間維持高 lr 更久。&lt;/li>
&lt;/ol>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>讀 training config 看到 &lt;code>learning_rate&lt;/code>、&lt;code>lr_scheduler_type: cosine&lt;/code>、&lt;code>warmup_steps: 1000&lt;/code> 等就是這組設定。Fine-tune 時 lr 設太大、模型會「忘記」pre-training 學到的能力（catastrophic forgetting）；太小則訓不進新資料、loss 不降。實務除錯：fine-tune 時 loss 第一個 epoch 就 NaN、十之八九是 lr 太大；loss 完全不降、十之八九是 lr 太小或 &lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/gradient/" data-link-title="Gradient" data-link-desc="loss function 對權重的偏微分向量、指出「該往哪個方向調權重才能讓 loss 下降最快」">gradient&lt;/a> 沒流到要訓的權重。&lt;/p></description><content:encoded><![CDATA[<p>Learning rate（學習率、lr、α、η）的核心概念是「<a href="/blog/llm/knowledge-cards/gradient/" data-link-title="Gradient" data-link-desc="loss function 對權重的偏微分向量、指出「該往哪個方向調權重才能讓 loss 下降最快」">gradient</a> 每步更新權重時、被乘上的純量縮放因子」。更新公式 <code>W_new = W_old - lr × gradient</code> 裡的 lr 就是它。是訓練最敏感的單一 hyperparameter — 太大會 diverge（loss 飛走）、太小會訓得超慢或卡 local minimum。</p>
<h2 id="概念位置">概念位置</h2>
<p>LLM 訓練 learning rate 的常見模式：</p>
<table>
  <thead>
      <tr>
          <th>階段</th>
          <th>典型 lr</th>
          <th>理由</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td><a href="/blog/llm/knowledge-cards/pre-training/" data-link-title="Pre-training" data-link-desc="LLM 訓練的第一階段：用 trillion-token 級網路文字做 next-token prediction、得到 base model">Pre-training</a></td>
          <td>1e-4 ~ 3e-4</td>
          <td>訓 trillion token、需要溫和的 lr 避免 diverge</td>
      </tr>
      <tr>
          <td><a href="/blog/llm/knowledge-cards/sft/" data-link-title="SFT（Supervised Fine-Tuning）" data-link-desc="在 base model 上用「指令-回答」對資料微調、讓模型會跟著指令走">SFT</a></td>
          <td>1e-5 ~ 5e-5</td>
          <td>base model 已收斂、用小 lr 微調避免 overshoot</td>
      </tr>
      <tr>
          <td><a href="/blog/llm/knowledge-cards/rlhf/" data-link-title="RLHF" data-link-desc="Reinforcement Learning from Human Feedback：用人類偏好訓練的 reward model 透過 RL 對齊 LLM">RLHF</a> / <a href="/blog/llm/knowledge-cards/dpo/" data-link-title="DPO（Direct Preference Optimization）" data-link-desc="RLHF 的簡化替代：跳過 reward model、直接從人類偏好資料 fine-tune LLM">DPO</a></td>
          <td>1e-7 ~ 1e-6</td>
          <td>又比 SFT 更小、避免破壞 SFT 學到的對話能力</td>
      </tr>
      <tr>
          <td><a href="/blog/llm/knowledge-cards/lora/" data-link-title="LoRA" data-link-desc="Low-Rank Adaptation：凍住原模型權重、只訓兩個小矩陣的 parameter-efficient fine-tuning">LoRA</a> fine-tune</td>
          <td>1e-4 ~ 5e-4</td>
          <td>只訓小 adapter、可用較大 lr</td>
      </tr>
  </tbody>
</table>
<p>Learning rate schedule（lr 隨訓練步數調整）的主流模式：</p>
<ol>
<li><strong>Warmup</strong>：訓練最初幾百 ~ 幾千 step、lr 從 0 線性升到目標值。避免初期 gradient 大、模型瞬間 diverge。</li>
<li><strong>Cosine decay</strong>：warmup 後、lr 用 cosine 函數從目標值降到接近 0。訓練後期細調。</li>
<li><strong>WSD（Warmup-Stable-Decay）</strong>：近期變體、中間維持高 lr 更久。</li>
</ol>
<h2 id="設計責任">設計責任</h2>
<p>讀 training config 看到 <code>learning_rate</code>、<code>lr_scheduler_type: cosine</code>、<code>warmup_steps: 1000</code> 等就是這組設定。Fine-tune 時 lr 設太大、模型會「忘記」pre-training 學到的能力（catastrophic forgetting）；太小則訓不進新資料、loss 不降。實務除錯：fine-tune 時 loss 第一個 epoch 就 NaN、十之八九是 lr 太大；loss 完全不降、十之八九是 lr 太小或 <a href="/blog/llm/knowledge-cards/gradient/" data-link-title="Gradient" data-link-desc="loss function 對權重的偏微分向量、指出「該往哪個方向調權重才能讓 loss 下降最快」">gradient</a> 沒流到要訓的權重。</p>
]]></content:encoded></item><item><title>LLM Benchmarks（MMLU / HumanEval / SWE-bench 等）</title><link>https://tarrragon.github.io/blog/llm/knowledge-cards/llm-benchmarks/</link><pubDate>Tue, 12 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/llm/knowledge-cards/llm-benchmarks/</guid><description>&lt;p>LLM benchmarks 的核心概念是「&lt;strong>用標準化任務集合衡量 LLM 各維度能力的評估工具&lt;/strong>」。不同 benchmark 衡量不同維度（知識、reasoning、code、對話、math 等）、選錯 benchmark 看模型會誤判。本卡列主流 benchmark 跟它們的覆蓋面、失效情境。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>主流 LLM benchmark 一覽：&lt;/p>
&lt;table>
 &lt;thead>
 &lt;tr>
 &lt;th>Benchmark&lt;/th>
 &lt;th>衡量維度&lt;/th>
 &lt;th>任務形式&lt;/th>
 &lt;th>失效情境&lt;/th>
 &lt;/tr>
 &lt;/thead>
 &lt;tbody>
 &lt;tr>
 &lt;td>&lt;strong>MMLU&lt;/strong>&lt;/td>
 &lt;td>通用知識（57 學科多選題）&lt;/td>
 &lt;td>4 選 1 選擇題&lt;/td>
 &lt;td>訓練資料污染（題目可能在 pretrain corpus）&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;strong>GSM8K&lt;/strong>&lt;/td>
 &lt;td>小學數學 word problem&lt;/td>
 &lt;td>文字 + 數字、需 reasoning&lt;/td>
 &lt;td>飽和（前沿模型 95%+）&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;strong>MATH&lt;/strong>&lt;/td>
 &lt;td>高中 / 競賽數學&lt;/td>
 &lt;td>自由作答&lt;/td>
 &lt;td>訓練污染、reasoning model 表現遠超 instruct&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;strong>HumanEval&lt;/strong>&lt;/td>
 &lt;td>Python function 補完&lt;/td>
 &lt;td>寫一個 function 通過 unit test&lt;/td>
 &lt;td>飽和、僅覆蓋初級 coding&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;strong>MBPP&lt;/strong>&lt;/td>
 &lt;td>Python coding 任務&lt;/td>
 &lt;td>同上、規模較大&lt;/td>
 &lt;td>同 HumanEval&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/swe-bench/" data-link-title="SWE-bench" data-link-desc="用真實 GitHub issue 量化 LLM coding 能力的 benchmark">&lt;strong>SWE-bench&lt;/strong>&lt;/a>&lt;/td>
 &lt;td>真實 GitHub issue 修復&lt;/td>
 &lt;td>給 repo + issue、生 patch、跑 test&lt;/td>
 &lt;td>仍是 LLM 主要 coding 差距、不易飽和&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;strong>MT-Bench&lt;/strong>&lt;/td>
 &lt;td>多輪對話品質&lt;/td>
 &lt;td>80 題 prompt、LLM-as-judge 評分&lt;/td>
 &lt;td>LLM-as-judge bias、judge 模型本身能力影響評分&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;strong>Chatbot Arena&lt;/strong>&lt;/td>
 &lt;td>開放對話偏好（眾人投票）&lt;/td>
 &lt;td>A/B 對戰、Elo 排名&lt;/td>
 &lt;td>文化偏好、prompt 設計影響&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;strong>HELM&lt;/strong>&lt;/td>
 &lt;td>多 dimension comprehensive&lt;/td>
 &lt;td>22 scenarios × 多 metrics&lt;/td>
 &lt;td>計算昂貴、不易追蹤每代新模型&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;strong>AlpacaEval&lt;/strong>&lt;/td>
 &lt;td>指令跟隨能力&lt;/td>
 &lt;td>LLM-as-judge 對比 GPT-4&lt;/td>
 &lt;td>Judge bias、易被「verbose」攻擊&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;strong>RULER&lt;/strong>&lt;/td>
 &lt;td>Long context 真實任務&lt;/td>
 &lt;td>Multi-needle、aggregation、reasoning&lt;/td>
 &lt;td>較新、覆蓋仍在演化&lt;/td>
 &lt;/tr>
 &lt;/tbody>
&lt;/table>
&lt;blockquote>
&lt;p>&lt;strong>事實查核註&lt;/strong>：各 benchmark 的飽和狀態、前沿模型 score 持續變動、上述為 2026/5 主流觀察。引用前以 &lt;a href="https://paperswithcode.com/">Papers with Code&lt;/a> 或 &lt;a href="https://huggingface.co/spaces/HuggingFaceH4/open_llm_leaderboard">HuggingFace Open LLM Leaderboard&lt;/a> 當前狀態為準。&lt;/p>&lt;/blockquote>
&lt;h2 id="benchmark-的常見陷阱">Benchmark 的常見陷阱&lt;/h2>
&lt;ol>
&lt;li>&lt;strong>訓練資料污染（Contamination）&lt;/strong>：benchmark 題目本身在 pretrain corpus 出現過、模型「記得」答案、看似強實際是 memorization&lt;/li>
&lt;li>&lt;strong>飽和（Saturation）&lt;/strong>：前沿模型 score 接近上限、無法區分模型品質差距（HumanEval 80%→95% 看似進步、實際 5% 多半是 lucky 而非實質提升）&lt;/li>
&lt;li>&lt;strong>LLM-as-judge bias&lt;/strong>：用 LLM（如 GPT-4）評其他 LLM、judge 的偏好（如「冗長 = 好」）會 bias 評分&lt;/li>
&lt;li>&lt;strong>Single-task overfitting&lt;/strong>：模型廠商針對 benchmark 特別 fine-tune、benchmark 高分但通用能力沒提升&lt;/li>
&lt;li>&lt;strong>Prompt sensitivity&lt;/strong>：同個 benchmark 用不同 prompt format、score 差幾個百分點&lt;/li>
&lt;/ol>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>讀 model card / paper 看到 benchmark 數字、判讀框架：&lt;/p>
&lt;ol>
&lt;li>&lt;strong>看 multiple benchmarks、不只一個&lt;/strong>：如挑 coding 模型、看 HumanEval + MBPP + SWE-bench、不只看 HumanEval&lt;/li>
&lt;li>&lt;strong>跟自己任務對齊的 benchmark 才重要&lt;/strong>：你做 RAG 應用、看 retrieval benchmark；你做 chat、看 MT-Bench / Arena&lt;/li>
&lt;li>&lt;strong>看「相對」、不只看「絕對」&lt;/strong>：「Model A 在 MMLU 比 Model B 高 2%」可能 noise；「A 比 B 高 10%」更可信&lt;/li>
&lt;li>&lt;strong>In-house benchmark 是最後檢驗&lt;/strong>：自己的真實工作流案例 &amp;gt; 任何公開 benchmark&lt;/li>
&lt;/ol></description><content:encoded><![CDATA[<p>LLM benchmarks 的核心概念是「<strong>用標準化任務集合衡量 LLM 各維度能力的評估工具</strong>」。不同 benchmark 衡量不同維度（知識、reasoning、code、對話、math 等）、選錯 benchmark 看模型會誤判。本卡列主流 benchmark 跟它們的覆蓋面、失效情境。</p>
<h2 id="概念位置">概念位置</h2>
<p>主流 LLM benchmark 一覽：</p>
<table>
  <thead>
      <tr>
          <th>Benchmark</th>
          <th>衡量維度</th>
          <th>任務形式</th>
          <th>失效情境</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td><strong>MMLU</strong></td>
          <td>通用知識（57 學科多選題）</td>
          <td>4 選 1 選擇題</td>
          <td>訓練資料污染（題目可能在 pretrain corpus）</td>
      </tr>
      <tr>
          <td><strong>GSM8K</strong></td>
          <td>小學數學 word problem</td>
          <td>文字 + 數字、需 reasoning</td>
          <td>飽和（前沿模型 95%+）</td>
      </tr>
      <tr>
          <td><strong>MATH</strong></td>
          <td>高中 / 競賽數學</td>
          <td>自由作答</td>
          <td>訓練污染、reasoning model 表現遠超 instruct</td>
      </tr>
      <tr>
          <td><strong>HumanEval</strong></td>
          <td>Python function 補完</td>
          <td>寫一個 function 通過 unit test</td>
          <td>飽和、僅覆蓋初級 coding</td>
      </tr>
      <tr>
          <td><strong>MBPP</strong></td>
          <td>Python coding 任務</td>
          <td>同上、規模較大</td>
          <td>同 HumanEval</td>
      </tr>
      <tr>
          <td><a href="/blog/llm/knowledge-cards/swe-bench/" data-link-title="SWE-bench" data-link-desc="用真實 GitHub issue 量化 LLM coding 能力的 benchmark"><strong>SWE-bench</strong></a></td>
          <td>真實 GitHub issue 修復</td>
          <td>給 repo + issue、生 patch、跑 test</td>
          <td>仍是 LLM 主要 coding 差距、不易飽和</td>
      </tr>
      <tr>
          <td><strong>MT-Bench</strong></td>
          <td>多輪對話品質</td>
          <td>80 題 prompt、LLM-as-judge 評分</td>
          <td>LLM-as-judge bias、judge 模型本身能力影響評分</td>
      </tr>
      <tr>
          <td><strong>Chatbot Arena</strong></td>
          <td>開放對話偏好（眾人投票）</td>
          <td>A/B 對戰、Elo 排名</td>
          <td>文化偏好、prompt 設計影響</td>
      </tr>
      <tr>
          <td><strong>HELM</strong></td>
          <td>多 dimension comprehensive</td>
          <td>22 scenarios × 多 metrics</td>
          <td>計算昂貴、不易追蹤每代新模型</td>
      </tr>
      <tr>
          <td><strong>AlpacaEval</strong></td>
          <td>指令跟隨能力</td>
          <td>LLM-as-judge 對比 GPT-4</td>
          <td>Judge bias、易被「verbose」攻擊</td>
      </tr>
      <tr>
          <td><strong>RULER</strong></td>
          <td>Long context 真實任務</td>
          <td>Multi-needle、aggregation、reasoning</td>
          <td>較新、覆蓋仍在演化</td>
      </tr>
  </tbody>
</table>
<blockquote>
<p><strong>事實查核註</strong>：各 benchmark 的飽和狀態、前沿模型 score 持續變動、上述為 2026/5 主流觀察。引用前以 <a href="https://paperswithcode.com/">Papers with Code</a> 或 <a href="https://huggingface.co/spaces/HuggingFaceH4/open_llm_leaderboard">HuggingFace Open LLM Leaderboard</a> 當前狀態為準。</p></blockquote>
<h2 id="benchmark-的常見陷阱">Benchmark 的常見陷阱</h2>
<ol>
<li><strong>訓練資料污染（Contamination）</strong>：benchmark 題目本身在 pretrain corpus 出現過、模型「記得」答案、看似強實際是 memorization</li>
<li><strong>飽和（Saturation）</strong>：前沿模型 score 接近上限、無法區分模型品質差距（HumanEval 80%→95% 看似進步、實際 5% 多半是 lucky 而非實質提升）</li>
<li><strong>LLM-as-judge bias</strong>：用 LLM（如 GPT-4）評其他 LLM、judge 的偏好（如「冗長 = 好」）會 bias 評分</li>
<li><strong>Single-task overfitting</strong>：模型廠商針對 benchmark 特別 fine-tune、benchmark 高分但通用能力沒提升</li>
<li><strong>Prompt sensitivity</strong>：同個 benchmark 用不同 prompt format、score 差幾個百分點</li>
</ol>
<h2 id="設計責任">設計責任</h2>
<p>讀 model card / paper 看到 benchmark 數字、判讀框架：</p>
<ol>
<li><strong>看 multiple benchmarks、不只一個</strong>：如挑 coding 模型、看 HumanEval + MBPP + SWE-bench、不只看 HumanEval</li>
<li><strong>跟自己任務對齊的 benchmark 才重要</strong>：你做 RAG 應用、看 retrieval benchmark；你做 chat、看 MT-Bench / Arena</li>
<li><strong>看「相對」、不只看「絕對」</strong>：「Model A 在 MMLU 比 Model B 高 2%」可能 noise；「A 比 B 高 10%」更可信</li>
<li><strong>In-house benchmark 是最後檢驗</strong>：自己的真實工作流案例 &gt; 任何公開 benchmark</li>
</ol>
]]></content:encoded></item><item><title>LLM Tracing</title><link>https://tarrragon.github.io/blog/llm/knowledge-cards/llm-tracing/</link><pubDate>Tue, 12 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/llm/knowledge-cards/llm-tracing/</guid><description>&lt;p>LLM tracing 的核心概念是「&lt;strong>把 LLM 應用的每次 LLM call / tool call / memory op / handoff 編成結構化 span、串成 trace、可在 observability 平台查詢&lt;/strong>」。對應的標準是 OpenTelemetry GenAI semantic conventions（2025 stabilizing 中）。代表平台：LangSmith、Phoenix、Braintrust、Langfuse、Datadog APM、Logfire。是 production LLM 應用 debug / cost / latency 監控的事實標準、補 traditional logging 抓不到的「為什麼 agent 跑這條路」。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>跟 traditional logging 的對比：&lt;/p>
&lt;table>
 &lt;thead>
 &lt;tr>
 &lt;th>維度&lt;/th>
 &lt;th>Traditional logging&lt;/th>
 &lt;th>LLM tracing&lt;/th>
 &lt;/tr>
 &lt;/thead>
 &lt;tbody>
 &lt;tr>
 &lt;td>結構&lt;/td>
 &lt;td>字串 line、靠 grep&lt;/td>
 &lt;td>結構化 span、parent-child 樹&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>關聯性&lt;/td>
 &lt;td>弱（要靠 request-id 串）&lt;/td>
 &lt;td>強（trace-id + span 父子關係內建）&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>屬性&lt;/td>
 &lt;td>自由 key-value&lt;/td>
 &lt;td>標準化（OTel GenAI semconv）：model / temperature / token usage / cost&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>查詢&lt;/td>
 &lt;td>grep / log aggregator&lt;/td>
 &lt;td>Trace explorer + filter + 視覺化&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>LLM 特有 attr&lt;/td>
 &lt;td>沒有&lt;/td>
 &lt;td>system prompt / tool calls / token / reasoning&lt;/td>
 &lt;/tr>
 &lt;/tbody>
&lt;/table>
&lt;p>主流 OTel GenAI span 類型：&lt;/p>
&lt;table>
 &lt;thead>
 &lt;tr>
 &lt;th>Span 類型&lt;/th>
 &lt;th>內容&lt;/th>
 &lt;/tr>
 &lt;/thead>
 &lt;tbody>
 &lt;tr>
 &lt;td>&lt;code>gen_ai.client.operation&lt;/code>&lt;/td>
 &lt;td>一次完整 LLM API call&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;code>gen_ai.tool.execution&lt;/code>&lt;/td>
 &lt;td>一次 tool 執行&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;code>gen_ai.agent&lt;/code>&lt;/td>
 &lt;td>Agent loop 一個 iteration&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;code>gen_ai.embeddings&lt;/code>&lt;/td>
 &lt;td>Embedding call&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;code>gen_ai.memory.read/write&lt;/code>&lt;/td>
 &lt;td>Memory 操作&lt;/td>
 &lt;/tr>
 &lt;/tbody>
&lt;/table>
&lt;p>每個 span 標準屬性：&lt;code>gen_ai.system&lt;/code>（vendor）、&lt;code>gen_ai.request.model&lt;/code>、&lt;code>gen_ai.usage.input_tokens&lt;/code> / &lt;code>output_tokens&lt;/code>、&lt;code>gen_ai.request.temperature&lt;/code> 等。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>讀 LLM observability docs / OTel spec 看到「span」「trace」「OTel GenAI semconv」就是這 framing。寫 code 場景的判讀：&lt;/p>
&lt;ol>
&lt;li>&lt;strong>何時值得加 tracing&lt;/strong>：超過個人 demo、有實際使用者 / production 流量、開始遇到「為什麼 agent 跑這條路」debug 問題&lt;/li>
&lt;li>&lt;strong>不該自己寫 logging&lt;/strong>：用 OTel GenAI semconv 標準化、未來可換 backend（LangSmith → Phoenix → 自架）&lt;/li>
&lt;li>&lt;strong>Trace 不只 debug、也是 eval 來源&lt;/strong>：production trace 餵回 &lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/llm-as-judge/" data-link-title="LLM-as-Judge" data-link-desc="用 LLM 評估另一個 LLM 的輸出品質、production eval 的主流方法、500-5000× 成本降但有 bias 要處理">LLM-as-judge&lt;/a> 做品質評估&lt;/li>
&lt;li>&lt;strong>跟 &lt;a href="https://tarrragon.github.io/blog/llm/04-applications/llm-tracing-and-observability/" data-link-title="4.20 LLM tracing 與 observability" data-link-desc="OpenTelemetry GenAI semantic conventions、結構化 span 設計、cost / latency 監控、failure debug 流程、跟 LLM-as-judge eval 的串接">4.20 LLM tracing 章節&lt;/a> 的關係&lt;/strong>：本卡是定義、章節是工程實務（attribute 設計、cost monitoring、failure debug 流程）&lt;/li>
&lt;/ol></description><content:encoded><![CDATA[<p>LLM tracing 的核心概念是「<strong>把 LLM 應用的每次 LLM call / tool call / memory op / handoff 編成結構化 span、串成 trace、可在 observability 平台查詢</strong>」。對應的標準是 OpenTelemetry GenAI semantic conventions（2025 stabilizing 中）。代表平台：LangSmith、Phoenix、Braintrust、Langfuse、Datadog APM、Logfire。是 production LLM 應用 debug / cost / latency 監控的事實標準、補 traditional logging 抓不到的「為什麼 agent 跑這條路」。</p>
<h2 id="概念位置">概念位置</h2>
<p>跟 traditional logging 的對比：</p>
<table>
  <thead>
      <tr>
          <th>維度</th>
          <th>Traditional logging</th>
          <th>LLM tracing</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>結構</td>
          <td>字串 line、靠 grep</td>
          <td>結構化 span、parent-child 樹</td>
      </tr>
      <tr>
          <td>關聯性</td>
          <td>弱（要靠 request-id 串）</td>
          <td>強（trace-id + span 父子關係內建）</td>
      </tr>
      <tr>
          <td>屬性</td>
          <td>自由 key-value</td>
          <td>標準化（OTel GenAI semconv）：model / temperature / token usage / cost</td>
      </tr>
      <tr>
          <td>查詢</td>
          <td>grep / log aggregator</td>
          <td>Trace explorer + filter + 視覺化</td>
      </tr>
      <tr>
          <td>LLM 特有 attr</td>
          <td>沒有</td>
          <td>system prompt / tool calls / token / reasoning</td>
      </tr>
  </tbody>
</table>
<p>主流 OTel GenAI span 類型：</p>
<table>
  <thead>
      <tr>
          <th>Span 類型</th>
          <th>內容</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td><code>gen_ai.client.operation</code></td>
          <td>一次完整 LLM API call</td>
      </tr>
      <tr>
          <td><code>gen_ai.tool.execution</code></td>
          <td>一次 tool 執行</td>
      </tr>
      <tr>
          <td><code>gen_ai.agent</code></td>
          <td>Agent loop 一個 iteration</td>
      </tr>
      <tr>
          <td><code>gen_ai.embeddings</code></td>
          <td>Embedding call</td>
      </tr>
      <tr>
          <td><code>gen_ai.memory.read/write</code></td>
          <td>Memory 操作</td>
      </tr>
  </tbody>
</table>
<p>每個 span 標準屬性：<code>gen_ai.system</code>（vendor）、<code>gen_ai.request.model</code>、<code>gen_ai.usage.input_tokens</code> / <code>output_tokens</code>、<code>gen_ai.request.temperature</code> 等。</p>
<h2 id="設計責任">設計責任</h2>
<p>讀 LLM observability docs / OTel spec 看到「span」「trace」「OTel GenAI semconv」就是這 framing。寫 code 場景的判讀：</p>
<ol>
<li><strong>何時值得加 tracing</strong>：超過個人 demo、有實際使用者 / production 流量、開始遇到「為什麼 agent 跑這條路」debug 問題</li>
<li><strong>不該自己寫 logging</strong>：用 OTel GenAI semconv 標準化、未來可換 backend（LangSmith → Phoenix → 自架）</li>
<li><strong>Trace 不只 debug、也是 eval 來源</strong>：production trace 餵回 <a href="/blog/llm/knowledge-cards/llm-as-judge/" data-link-title="LLM-as-Judge" data-link-desc="用 LLM 評估另一個 LLM 的輸出品質、production eval 的主流方法、500-5000× 成本降但有 bias 要處理">LLM-as-judge</a> 做品質評估</li>
<li><strong>跟 <a href="/blog/llm/04-applications/llm-tracing-and-observability/" data-link-title="4.20 LLM tracing 與 observability" data-link-desc="OpenTelemetry GenAI semantic conventions、結構化 span 設計、cost / latency 監控、failure debug 流程、跟 LLM-as-judge eval 的串接">4.20 LLM tracing 章節</a> 的關係</strong>：本卡是定義、章節是工程實務（attribute 設計、cost monitoring、failure debug 流程）</li>
</ol>
]]></content:encoded></item><item><title>LLM-as-Judge</title><link>https://tarrragon.github.io/blog/llm/knowledge-cards/llm-as-judge/</link><pubDate>Tue, 12 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/llm/knowledge-cards/llm-as-judge/</guid><description>&lt;p>LLM-as-Judge 的核心概念是「&lt;strong>用一個 LLM（judge）對另一個 LLM（test subject）的輸出做品質評估&lt;/strong>」。給 judge 一個 rubric（評分標準）跟 (input, output) pair、judge 輸出分數或 pairwise 偏好。是 production LLM eval 的主流方法（500-5000× 比 human eval 便宜、80%+ 跟人類同意度）、但有 bias 要處理（position / verbosity / self-preference）。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>跟其他 eval 路徑的對比：&lt;/p>
&lt;table>
 &lt;thead>
 &lt;tr>
 &lt;th>Eval 路徑&lt;/th>
 &lt;th>成本&lt;/th>
 &lt;th>速度&lt;/th>
 &lt;th>適合&lt;/th>
 &lt;/tr>
 &lt;/thead>
 &lt;tbody>
 &lt;tr>
 &lt;td>Standard &lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/llm-benchmarks/" data-link-title="LLM Benchmarks（MMLU / HumanEval / SWE-bench 等）" data-link-desc="LLM 能力評估的標準 benchmark 集合：MMLU / HumanEval / MBPP / SWE-bench / MT-Bench 等的覆蓋範圍與失效情境">benchmark&lt;/a>（MMLU / SWE-bench 等）&lt;/td>
 &lt;td>中&lt;/td>
 &lt;td>慢（一次 run 數小時）&lt;/td>
 &lt;td>通用能力比較&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>Human eval&lt;/td>
 &lt;td>極高（每筆 $1-10）&lt;/td>
 &lt;td>慢&lt;/td>
 &lt;td>黃金標準、final QA&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;strong>LLM-as-Judge（本卡）&lt;/strong>&lt;/td>
 &lt;td>低（每筆 $0.001-0.01）&lt;/td>
 &lt;td>快&lt;/td>
 &lt;td>Production loop eval、自己應用 in-house&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>Rule-based / regex&lt;/td>
 &lt;td>極低&lt;/td>
 &lt;td>即時&lt;/td>
 &lt;td>明確 binary（如格式對不對）&lt;/td>
 &lt;/tr>
 &lt;/tbody>
&lt;/table>
&lt;p>主要 use case：&lt;/p>
&lt;ol>
&lt;li>&lt;strong>In-house benchmark&lt;/strong>：自己工作流的真實案例、自寫 rubric、judge 評&lt;/li>
&lt;li>&lt;strong>Production trace eval&lt;/strong>：用 &lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/llm-tracing/" data-link-title="LLM Tracing" data-link-desc="把 LLM 應用的每次 LLM call / tool call / memory op 編成結構化 span、用 OpenTelemetry GenAI semantic conventions 標準化">LLM tracing&lt;/a> 蒐集的 production trace、定期 judge 跑、抓品質回歸&lt;/li>
&lt;li>&lt;strong>A/B test&lt;/strong>：兩個 prompt / model 變體、judge 做 pairwise 比較&lt;/li>
&lt;li>&lt;strong>Synthetic data quality&lt;/strong>：用大模型生 fine-tune 資料、judge 過濾低品質&lt;/li>
&lt;/ol>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>讀 eval framework / production AI app 看到「LLM as judge」「pairwise eval」「LLM evaluator」就是這 framing。寫 code 場景的判讀：&lt;/p>
&lt;ol>
&lt;li>&lt;strong>Judge 模型選擇&lt;/strong>：強模型當 judge（GPT-5 / Claude 4 / Gemini 旗艦）、reasoning model 更穩；judge 跟被測同家可能有 self-preference bias&lt;/li>
&lt;li>&lt;strong>三大 bias 緩解&lt;/strong>：
&lt;ul>
&lt;li>&lt;strong>Position bias&lt;/strong>：A/B pairwise 換位置跑 2 次取一致 vote&lt;/li>
&lt;li>&lt;strong>Verbosity bias&lt;/strong>：rubric 加「冗長不加分」明確指示、或長度 normalize&lt;/li>
&lt;li>&lt;strong>Self-preference bias&lt;/strong>：用 3 個不同 judge model 取多數&lt;/li>
&lt;/ul>
&lt;/li>
&lt;li>&lt;strong>跟 &lt;a href="https://tarrragon.github.io/blog/llm/04-applications/llm-as-judge/" data-link-title="4.21 LLM-as-Judge 評估方法" data-link-desc="LLM 評估 LLM 的 production eval 方法：rubric design、pairwise / direct scoring、三大 bias 緩解、跟 trace 串接的閉環、calibration">4.21 LLM-as-judge 章節&lt;/a> 的關係&lt;/strong>：本卡是定義、章節是工程實務（rubric design、bias 緩解、calibration、trace 串接）&lt;/li>
&lt;li>&lt;strong>不是萬靈丹&lt;/strong>：高 stake 任務（醫療、法律、安全）仍需 human eval；judge 的天花板 = judge 模型本身的能力&lt;/li>
&lt;/ol></description><content:encoded><![CDATA[<p>LLM-as-Judge 的核心概念是「<strong>用一個 LLM（judge）對另一個 LLM（test subject）的輸出做品質評估</strong>」。給 judge 一個 rubric（評分標準）跟 (input, output) pair、judge 輸出分數或 pairwise 偏好。是 production LLM eval 的主流方法（500-5000× 比 human eval 便宜、80%+ 跟人類同意度）、但有 bias 要處理（position / verbosity / self-preference）。</p>
<h2 id="概念位置">概念位置</h2>
<p>跟其他 eval 路徑的對比：</p>
<table>
  <thead>
      <tr>
          <th>Eval 路徑</th>
          <th>成本</th>
          <th>速度</th>
          <th>適合</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>Standard <a href="/blog/llm/knowledge-cards/llm-benchmarks/" data-link-title="LLM Benchmarks（MMLU / HumanEval / SWE-bench 等）" data-link-desc="LLM 能力評估的標準 benchmark 集合：MMLU / HumanEval / MBPP / SWE-bench / MT-Bench 等的覆蓋範圍與失效情境">benchmark</a>（MMLU / SWE-bench 等）</td>
          <td>中</td>
          <td>慢（一次 run 數小時）</td>
          <td>通用能力比較</td>
      </tr>
      <tr>
          <td>Human eval</td>
          <td>極高（每筆 $1-10）</td>
          <td>慢</td>
          <td>黃金標準、final QA</td>
      </tr>
      <tr>
          <td><strong>LLM-as-Judge（本卡）</strong></td>
          <td>低（每筆 $0.001-0.01）</td>
          <td>快</td>
          <td>Production loop eval、自己應用 in-house</td>
      </tr>
      <tr>
          <td>Rule-based / regex</td>
          <td>極低</td>
          <td>即時</td>
          <td>明確 binary（如格式對不對）</td>
      </tr>
  </tbody>
</table>
<p>主要 use case：</p>
<ol>
<li><strong>In-house benchmark</strong>：自己工作流的真實案例、自寫 rubric、judge 評</li>
<li><strong>Production trace eval</strong>：用 <a href="/blog/llm/knowledge-cards/llm-tracing/" data-link-title="LLM Tracing" data-link-desc="把 LLM 應用的每次 LLM call / tool call / memory op 編成結構化 span、用 OpenTelemetry GenAI semantic conventions 標準化">LLM tracing</a> 蒐集的 production trace、定期 judge 跑、抓品質回歸</li>
<li><strong>A/B test</strong>：兩個 prompt / model 變體、judge 做 pairwise 比較</li>
<li><strong>Synthetic data quality</strong>：用大模型生 fine-tune 資料、judge 過濾低品質</li>
</ol>
<h2 id="設計責任">設計責任</h2>
<p>讀 eval framework / production AI app 看到「LLM as judge」「pairwise eval」「LLM evaluator」就是這 framing。寫 code 場景的判讀：</p>
<ol>
<li><strong>Judge 模型選擇</strong>：強模型當 judge（GPT-5 / Claude 4 / Gemini 旗艦）、reasoning model 更穩；judge 跟被測同家可能有 self-preference bias</li>
<li><strong>三大 bias 緩解</strong>：
<ul>
<li><strong>Position bias</strong>：A/B pairwise 換位置跑 2 次取一致 vote</li>
<li><strong>Verbosity bias</strong>：rubric 加「冗長不加分」明確指示、或長度 normalize</li>
<li><strong>Self-preference bias</strong>：用 3 個不同 judge model 取多數</li>
</ul>
</li>
<li><strong>跟 <a href="/blog/llm/04-applications/llm-as-judge/" data-link-title="4.21 LLM-as-Judge 評估方法" data-link-desc="LLM 評估 LLM 的 production eval 方法：rubric design、pairwise / direct scoring、三大 bias 緩解、跟 trace 串接的閉環、calibration">4.21 LLM-as-judge 章節</a> 的關係</strong>：本卡是定義、章節是工程實務（rubric design、bias 緩解、calibration、trace 串接）</li>
<li><strong>不是萬靈丹</strong>：高 stake 任務（醫療、法律、安全）仍需 human eval；judge 的天花板 = judge 模型本身的能力</li>
</ol>
]]></content:encoded></item><item><title>Logit</title><link>https://tarrragon.github.io/blog/llm/knowledge-cards/logit/</link><pubDate>Tue, 12 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/llm/knowledge-cards/logit/</guid><description>&lt;p>Logit 的核心概念是「&lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/softmax/" data-link-title="Softmax" data-link-desc="把任意實數向量正規化成「總和為 1、每個分量 ∈ [0,1]」的機率分佈">softmax&lt;/a> 之前的原始分數」。LLM 每次 forward pass 的最後一步、會輸出長度為 vocab size 的實數向量（例如 vocab size = 128K、輸出就是 128K 個浮點數）、這個向量就是 logits。Logit 可正可負、無上下界、要經過 softmax 才變成機率分佈。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>Logit 在 LLM 輸出 pipeline 的位置：&lt;/p>





&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-text" data-lang="text">&lt;span class="line">&lt;span class="ln">1&lt;/span>&lt;span class="cl">最後一層 Transformer 輸出 hidden state
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">2&lt;/span>&lt;span class="cl"> ↓ output projection（linear layer）
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">3&lt;/span>&lt;span class="cl">logits（shape: vocab_size、實數、可正可負）
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">4&lt;/span>&lt;span class="cl"> ↓ logit warping / masking（可選、用於控制輸出）
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">5&lt;/span>&lt;span class="cl"> ↓ /temperature
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">6&lt;/span>&lt;span class="cl"> ↓ softmax
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">7&lt;/span>&lt;span class="cl">probability distribution
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">8&lt;/span>&lt;span class="cl"> ↓ sampling（greedy / top-k / top-p）
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">9&lt;/span>&lt;span class="cl">next token&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>操作 logit 的常見技巧：&lt;/p>
&lt;table>
 &lt;thead>
 &lt;tr>
 &lt;th>技巧&lt;/th>
 &lt;th>做法&lt;/th>
 &lt;th>用途&lt;/th>
 &lt;/tr>
 &lt;/thead>
 &lt;tbody>
 &lt;tr>
 &lt;td>Temperature&lt;/td>
 &lt;td>logit / T&lt;/td>
 &lt;td>控制輸出隨機度、T 越大越平&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>Logit bias&lt;/td>
 &lt;td>對特定 token 的 logit 加 / 減 offset&lt;/td>
 &lt;td>強制 / 抑制特定 token（如禁用特定詞）&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>Grammar masking&lt;/td>
 &lt;td>把不合法 token 的 logit 設成 -∞&lt;/td>
 &lt;td>Structured output、確保輸出符合 grammar&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>Repetition penalty&lt;/td>
 &lt;td>對最近出現過的 token logit 扣分&lt;/td>
 &lt;td>避免重複、改善生成多樣性&lt;/td>
 &lt;/tr>
 &lt;/tbody>
&lt;/table>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>理解 logit 後可以判讀 sampling 階段的控制粒度：所有「不重訓模型、影響輸出」的技巧（temperature、structured output、constrained generation、logit bias）本質上都是「在 softmax 前後動 logit」、不是動模型權重。這也是為什麼同一個模型用不同 sampling 設定能產生差很多的輸出。&lt;/p></description><content:encoded><![CDATA[<p>Logit 的核心概念是「<a href="/blog/llm/knowledge-cards/softmax/" data-link-title="Softmax" data-link-desc="把任意實數向量正規化成「總和為 1、每個分量 ∈ [0,1]」的機率分佈">softmax</a> 之前的原始分數」。LLM 每次 forward pass 的最後一步、會輸出長度為 vocab size 的實數向量（例如 vocab size = 128K、輸出就是 128K 個浮點數）、這個向量就是 logits。Logit 可正可負、無上下界、要經過 softmax 才變成機率分佈。</p>
<h2 id="概念位置">概念位置</h2>
<p>Logit 在 LLM 輸出 pipeline 的位置：</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="ln">1</span><span class="cl">最後一層 Transformer 輸出 hidden state
</span></span><span class="line"><span class="ln">2</span><span class="cl">   ↓ output projection（linear layer）
</span></span><span class="line"><span class="ln">3</span><span class="cl">logits（shape: vocab_size、實數、可正可負）
</span></span><span class="line"><span class="ln">4</span><span class="cl">   ↓ logit warping / masking（可選、用於控制輸出）
</span></span><span class="line"><span class="ln">5</span><span class="cl">   ↓ /temperature
</span></span><span class="line"><span class="ln">6</span><span class="cl">   ↓ softmax
</span></span><span class="line"><span class="ln">7</span><span class="cl">probability distribution
</span></span><span class="line"><span class="ln">8</span><span class="cl">   ↓ sampling（greedy / top-k / top-p）
</span></span><span class="line"><span class="ln">9</span><span class="cl">next token</span></span></code></pre></div><p>操作 logit 的常見技巧：</p>
<table>
  <thead>
      <tr>
          <th>技巧</th>
          <th>做法</th>
          <th>用途</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>Temperature</td>
          <td>logit / T</td>
          <td>控制輸出隨機度、T 越大越平</td>
      </tr>
      <tr>
          <td>Logit bias</td>
          <td>對特定 token 的 logit 加 / 減 offset</td>
          <td>強制 / 抑制特定 token（如禁用特定詞）</td>
      </tr>
      <tr>
          <td>Grammar masking</td>
          <td>把不合法 token 的 logit 設成 -∞</td>
          <td>Structured output、確保輸出符合 grammar</td>
      </tr>
      <tr>
          <td>Repetition penalty</td>
          <td>對最近出現過的 token logit 扣分</td>
          <td>避免重複、改善生成多樣性</td>
      </tr>
  </tbody>
</table>
<h2 id="設計責任">設計責任</h2>
<p>理解 logit 後可以判讀 sampling 階段的控制粒度：所有「不重訓模型、影響輸出」的技巧（temperature、structured output、constrained generation、logit bias）本質上都是「在 softmax 前後動 logit」、不是動模型權重。這也是為什麼同一個模型用不同 sampling 設定能產生差很多的輸出。</p>
]]></content:encoded></item><item><title>LoRA</title><link>https://tarrragon.github.io/blog/llm/knowledge-cards/lora/</link><pubDate>Tue, 12 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/llm/knowledge-cards/lora/</guid><description>&lt;p>LoRA（Low-Rank Adaptation、低秩適配）的核心概念是「&lt;strong>凍住原模型所有權重、在指定 layer 旁邊掛兩個小矩陣 A、B（rank 很低、如 r=8）、只訓 A、B&lt;/strong>」。Hu et al. (2021) 提出、是現在 fine-tuning 的主流選擇、大幅降低訓練成本與記憶體需求。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>LoRA 的數學形式：&lt;/p>





&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-text" data-lang="text">&lt;span class="line">&lt;span class="ln">1&lt;/span>&lt;span class="cl">原 layer 輸出：y = W × x （W 凍住）
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">2&lt;/span>&lt;span class="cl">加 LoRA 後： y = W × x + B × A × x
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">3&lt;/span>&lt;span class="cl"> └──┬──┘
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">4&lt;/span>&lt;span class="cl"> LoRA update（rank r）
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">5&lt;/span>&lt;span class="cl"> A shape: (r, hidden_dim)
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">6&lt;/span>&lt;span class="cl"> B shape: (hidden_dim, r)&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>關鍵特性：&lt;/p>
&lt;table>
 &lt;thead>
 &lt;tr>
 &lt;th>維度&lt;/th>
 &lt;th>完整 fine-tuning&lt;/th>
 &lt;th>LoRA fine-tuning（r=16）&lt;/th>
 &lt;/tr>
 &lt;/thead>
 &lt;tbody>
 &lt;tr>
 &lt;td>可訓練參數&lt;/td>
 &lt;td>全部（如 7B、70B）&lt;/td>
 &lt;td>~0.1% ~ 1%（只 A、B）&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>GPU 記憶體&lt;/td>
 &lt;td>高（要存所有 gradient）&lt;/td>
 &lt;td>大幅降低&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>Adapter 檔案大小&lt;/td>
 &lt;td>跟原模型同大&lt;/td>
 &lt;td>幾 MB ~ 幾百 MB&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>訓練成本&lt;/td>
 &lt;td>全模型 backprop&lt;/td>
 &lt;td>只算 A、B 的 gradient&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>部署&lt;/td>
 &lt;td>載入新模型&lt;/td>
 &lt;td>載入原模型 + adapter、推論時合併&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>多任務切換&lt;/td>
 &lt;td>載入不同模型&lt;/td>
 &lt;td>切換 adapter 即可（同個底）&lt;/td>
 &lt;/tr>
 &lt;/tbody>
&lt;/table>
&lt;p>QLoRA（Dettmers et al., 2023）進一步把原模型量化到 4-bit、LoRA 訓在量化模型上、消費級 GPU 也能 fine-tune 大模型。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>讀 fine-tuning 教學 / Hugging Face PEFT 看到 LoRA、QLoRA 是現在主流。寫 code 場景的判讀：LoRA 適合「在現有模型上加領域知識 / 風格」（如教模型用特定 codebase 慣例）、不適合「教模型新世界知識」（仍要 &lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/pre-training/" data-link-title="Pre-training" data-link-desc="LLM 訓練的第一階段：用 trillion-token 級網路文字做 next-token prediction、得到 base model">pre-training&lt;/a> 級資料）；adapter 形式讓「多客戶 / 多風格」場景可以共用 base model、只切換 adapter、節省 GPU 記憶體。&lt;/p></description><content:encoded><![CDATA[<p>LoRA（Low-Rank Adaptation、低秩適配）的核心概念是「<strong>凍住原模型所有權重、在指定 layer 旁邊掛兩個小矩陣 A、B（rank 很低、如 r=8）、只訓 A、B</strong>」。Hu et al. (2021) 提出、是現在 fine-tuning 的主流選擇、大幅降低訓練成本與記憶體需求。</p>
<h2 id="概念位置">概念位置</h2>
<p>LoRA 的數學形式：</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="ln">1</span><span class="cl">原 layer 輸出：y = W × x       （W 凍住）
</span></span><span class="line"><span class="ln">2</span><span class="cl">加 LoRA 後：  y = W × x + B × A × x
</span></span><span class="line"><span class="ln">3</span><span class="cl">                          └──┬──┘
</span></span><span class="line"><span class="ln">4</span><span class="cl">                       LoRA update（rank r）
</span></span><span class="line"><span class="ln">5</span><span class="cl">                       A shape: (r, hidden_dim)
</span></span><span class="line"><span class="ln">6</span><span class="cl">                       B shape: (hidden_dim, r)</span></span></code></pre></div><p>關鍵特性：</p>
<table>
  <thead>
      <tr>
          <th>維度</th>
          <th>完整 fine-tuning</th>
          <th>LoRA fine-tuning（r=16）</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>可訓練參數</td>
          <td>全部（如 7B、70B）</td>
          <td>~0.1% ~ 1%（只 A、B）</td>
      </tr>
      <tr>
          <td>GPU 記憶體</td>
          <td>高（要存所有 gradient）</td>
          <td>大幅降低</td>
      </tr>
      <tr>
          <td>Adapter 檔案大小</td>
          <td>跟原模型同大</td>
          <td>幾 MB ~ 幾百 MB</td>
      </tr>
      <tr>
          <td>訓練成本</td>
          <td>全模型 backprop</td>
          <td>只算 A、B 的 gradient</td>
      </tr>
      <tr>
          <td>部署</td>
          <td>載入新模型</td>
          <td>載入原模型 + adapter、推論時合併</td>
      </tr>
      <tr>
          <td>多任務切換</td>
          <td>載入不同模型</td>
          <td>切換 adapter 即可（同個底）</td>
      </tr>
  </tbody>
</table>
<p>QLoRA（Dettmers et al., 2023）進一步把原模型量化到 4-bit、LoRA 訓在量化模型上、消費級 GPU 也能 fine-tune 大模型。</p>
<h2 id="設計責任">設計責任</h2>
<p>讀 fine-tuning 教學 / Hugging Face PEFT 看到 LoRA、QLoRA 是現在主流。寫 code 場景的判讀：LoRA 適合「在現有模型上加領域知識 / 風格」（如教模型用特定 codebase 慣例）、不適合「教模型新世界知識」（仍要 <a href="/blog/llm/knowledge-cards/pre-training/" data-link-title="Pre-training" data-link-desc="LLM 訓練的第一階段：用 trillion-token 級網路文字做 next-token prediction、得到 base model">pre-training</a> 級資料）；adapter 形式讓「多客戶 / 多風格」場景可以共用 base model、只切換 adapter、節省 GPU 記憶體。</p>
]]></content:encoded></item><item><title>Loss Function</title><link>https://tarrragon.github.io/blog/llm/knowledge-cards/loss-function/</link><pubDate>Tue, 12 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/llm/knowledge-cards/loss-function/</guid><description>&lt;p>Loss function（損失函數、目的函數）的核心概念是「把模型預測跟正確答案的差距、壓成一個純量數值」。訓練的整個目標就是「最小化這個數值」、所有 &lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/gradient/" data-link-title="Gradient" data-link-desc="loss function 對權重的偏微分向量、指出「該往哪個方向調權重才能讓 loss 下降最快」">gradient&lt;/a> / &lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/backpropagation/" data-link-title="Backpropagation" data-link-desc="從 output loss 反向遞推、用 chain rule 算出每個權重的 gradient 的演算法">backpropagation&lt;/a> / optimizer step 都在做這件事。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>LLM 各訓練階段用不同的 loss function：&lt;/p>
&lt;table>
 &lt;thead>
 &lt;tr>
 &lt;th>階段&lt;/th>
 &lt;th>主要 loss&lt;/th>
 &lt;th>衡量的東西&lt;/th>
 &lt;/tr>
 &lt;/thead>
 &lt;tbody>
 &lt;tr>
 &lt;td>Pre-training&lt;/td>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/cross-entropy/" data-link-title="Cross-Entropy" data-link-desc="衡量「預測機率分佈」跟「真實分佈」距離的指標、LLM 預訓練的主要 loss">Cross-entropy&lt;/a>（next-token prediction）&lt;/td>
 &lt;td>模型預測的下個 token 機率跟真實答案的距離&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>SFT&lt;/td>
 &lt;td>Cross-entropy（同上、但 only on assistant response）&lt;/td>
 &lt;td>模型回答跟人類示範回答的距離&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>Reward model&lt;/td>
 &lt;td>Pairwise ranking loss&lt;/td>
 &lt;td>「人類偏好 A 大於 B」這個訊號的擬合度&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>RLHF / DPO&lt;/td>
 &lt;td>KL-constrained reward loss / DPO loss&lt;/td>
 &lt;td>reward 高 + 不偏離 base 模型太遠&lt;/td>
 &lt;/tr>
 &lt;/tbody>
&lt;/table>
&lt;p>評估時用的指標（&lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/perplexity/" data-link-title="Perplexity" data-link-desc="cross-entropy 的指數形式、直覺意義為「模型平均覺得下個 token 有多少種可能」">perplexity&lt;/a>、accuracy、BLEU 等）跟訓練 loss 是不同概念：loss 是「訓練要 minimize 的東西」、指標是「給人看模型好不好的數字」、兩者不一定一致（loss 降但指標不一定升、反之亦然）。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>選 loss function 等於選「訓練要把模型推往哪個方向」。Cross-entropy 推「機率分佈接近真實 token」、reward model 推「人類偏好高的回應」、DPO 推「偏好回應 vs 拒絕回應的對比」— 每種 loss 對應的模型行為不同。讀 paper 看到「我們用 X loss」、要回問「這 loss 把模型推往哪個方向」、才能判斷模型訓練出來的特性是否符合預期。&lt;/p></description><content:encoded><![CDATA[<p>Loss function（損失函數、目的函數）的核心概念是「把模型預測跟正確答案的差距、壓成一個純量數值」。訓練的整個目標就是「最小化這個數值」、所有 <a href="/blog/llm/knowledge-cards/gradient/" data-link-title="Gradient" data-link-desc="loss function 對權重的偏微分向量、指出「該往哪個方向調權重才能讓 loss 下降最快」">gradient</a> / <a href="/blog/llm/knowledge-cards/backpropagation/" data-link-title="Backpropagation" data-link-desc="從 output loss 反向遞推、用 chain rule 算出每個權重的 gradient 的演算法">backpropagation</a> / optimizer step 都在做這件事。</p>
<h2 id="概念位置">概念位置</h2>
<p>LLM 各訓練階段用不同的 loss function：</p>
<table>
  <thead>
      <tr>
          <th>階段</th>
          <th>主要 loss</th>
          <th>衡量的東西</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>Pre-training</td>
          <td><a href="/blog/llm/knowledge-cards/cross-entropy/" data-link-title="Cross-Entropy" data-link-desc="衡量「預測機率分佈」跟「真實分佈」距離的指標、LLM 預訓練的主要 loss">Cross-entropy</a>（next-token prediction）</td>
          <td>模型預測的下個 token 機率跟真實答案的距離</td>
      </tr>
      <tr>
          <td>SFT</td>
          <td>Cross-entropy（同上、但 only on assistant response）</td>
          <td>模型回答跟人類示範回答的距離</td>
      </tr>
      <tr>
          <td>Reward model</td>
          <td>Pairwise ranking loss</td>
          <td>「人類偏好 A 大於 B」這個訊號的擬合度</td>
      </tr>
      <tr>
          <td>RLHF / DPO</td>
          <td>KL-constrained reward loss / DPO loss</td>
          <td>reward 高 + 不偏離 base 模型太遠</td>
      </tr>
  </tbody>
</table>
<p>評估時用的指標（<a href="/blog/llm/knowledge-cards/perplexity/" data-link-title="Perplexity" data-link-desc="cross-entropy 的指數形式、直覺意義為「模型平均覺得下個 token 有多少種可能」">perplexity</a>、accuracy、BLEU 等）跟訓練 loss 是不同概念：loss 是「訓練要 minimize 的東西」、指標是「給人看模型好不好的數字」、兩者不一定一致（loss 降但指標不一定升、反之亦然）。</p>
<h2 id="設計責任">設計責任</h2>
<p>選 loss function 等於選「訓練要把模型推往哪個方向」。Cross-entropy 推「機率分佈接近真實 token」、reward model 推「人類偏好高的回應」、DPO 推「偏好回應 vs 拒絕回應的對比」— 每種 loss 對應的模型行為不同。讀 paper 看到「我們用 X loss」、要回問「這 loss 把模型推往哪個方向」、才能判斷模型訓練出來的特性是否符合預期。</p>
]]></content:encoded></item><item><title>Lost in the Middle</title><link>https://tarrragon.github.io/blog/llm/knowledge-cards/lost-in-the-middle/</link><pubDate>Tue, 12 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/llm/knowledge-cards/lost-in-the-middle/</guid><description>&lt;p>Lost in the middle（中段遺失、Liu et al., 2023）的核心概念是「&lt;strong>LLM 對 long context 中段內容的 attention / recall 顯著低於開頭與結尾&lt;/strong>」。實測：把答案放在 10K context 的開頭或結尾、模型 recall 準確率 80%+；放在中段 4000-6000 token 位置、recall 掉到 50% 甚至更低。是 long context 使用上最常見的失敗模式。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>Long context 的 effective context 跟 claimed context 落差來自三個現象：&lt;/p>
&lt;table>
 &lt;thead>
 &lt;tr>
 &lt;th>現象&lt;/th>
 &lt;th>描述&lt;/th>
 &lt;th>嚴重度&lt;/th>
 &lt;/tr>
 &lt;/thead>
 &lt;tbody>
 &lt;tr>
 &lt;td>Lost in the middle&lt;/td>
 &lt;td>中段內容 attention 顯著低、recall 掉&lt;/td>
 &lt;td>普遍、最頻繁&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>Context degradation&lt;/td>
 &lt;td>接近 context 上限時、整體品質緩降&lt;/td>
 &lt;td>接近上限才明顯&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>Needle in haystack&lt;/td>
 &lt;td>抓單一事實的能力（vs lost-in-the-middle 抓整段邏輯）&lt;/td>
 &lt;td>兩條軸、不完全重疊&lt;/td>
 &lt;/tr>
 &lt;/tbody>
&lt;/table>





&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-text" data-lang="text">&lt;span class="line">&lt;span class="ln"> 1&lt;/span>&lt;span class="cl">Recall accuracy vs 答案位置（典型 10K context）：
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 2&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 3&lt;/span>&lt;span class="cl">100% |█ █
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 4&lt;/span>&lt;span class="cl"> |██ ██
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 5&lt;/span>&lt;span class="cl"> 80% |███ ███
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 6&lt;/span>&lt;span class="cl"> |███ ███
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 7&lt;/span>&lt;span class="cl"> 60% |███ ____ ███
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 8&lt;/span>&lt;span class="cl"> |███ ___/ \___ ███
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 9&lt;/span>&lt;span class="cl"> 40% |███ _/ \_ ███
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">10&lt;/span>&lt;span class="cl"> |█████─/ \───── ███
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">11&lt;/span>&lt;span class="cl"> |
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">12&lt;/span>&lt;span class="cl"> 0 2K 4K 6K 8K 10K
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">13&lt;/span>&lt;span class="cl"> 開頭 結尾&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>成因：&lt;/p>
&lt;ol>
&lt;li>&lt;strong>Attention weight 分佈不均勻&lt;/strong>：訓練資料中、句首 / 段首通常含關鍵資訊、模型學會偏重句首；長 context 的中段在訓練資料中相對稀疏、attention 沒學好&lt;/li>
&lt;li>&lt;strong>Positional encoding 設計&lt;/strong>：RoPE / ALiBi 等對長距離 attention 的衰減模式、中段 token 跟 query 距離通常較大、attention 弱&lt;/li>
&lt;li>&lt;strong>訓練 context 長度的影響&lt;/strong>：模型若訓練在 8K context、推論時用 128K（用 RoPE scaling 延伸）、中段表現比訓練範圍內差更多&lt;/li>
&lt;/ol>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>讀 long-context paper / benchmark 看到「lost-in-the-middle」「U-shape recall」就是這現象。寫 code 場景的判讀：&lt;/p>
&lt;ol>
&lt;li>&lt;strong>把關鍵資訊放開頭或結尾&lt;/strong>：system prompt 在開頭、最新指示在結尾（剛好是模型 attention 最強的兩處）&lt;/li>
&lt;li>&lt;strong>長 context 不是「塞越多越好」&lt;/strong>：超過 effective context（典型 8-16K）後、邊際效用急降&lt;/li>
&lt;li>&lt;strong>RAG 比 long context 仍有價值&lt;/strong>：把相關片段 retrieve 出來放 prompt 開頭、比把整份文件塞進 100K context 效果更穩定&lt;/li>
&lt;li>&lt;strong>驗證自己模型的 effective context&lt;/strong>：用 needle-in-haystack 或自製測試、看模型在 8K / 16K / 32K 表現掉到哪&lt;/li>
&lt;li>&lt;strong>Reasoning model 的 thinking trace 不會遇到這事故嗎？&lt;/strong> — 仍會遇到、但 reasoning 過程會主動重新引用前文、部分緩解；不過 thinking trace 本身會擠壓 context budget、可能反而觸發 degradation&lt;/li>
&lt;/ol></description><content:encoded><![CDATA[<p>Lost in the middle（中段遺失、Liu et al., 2023）的核心概念是「<strong>LLM 對 long context 中段內容的 attention / recall 顯著低於開頭與結尾</strong>」。實測：把答案放在 10K context 的開頭或結尾、模型 recall 準確率 80%+；放在中段 4000-6000 token 位置、recall 掉到 50% 甚至更低。是 long context 使用上最常見的失敗模式。</p>
<h2 id="概念位置">概念位置</h2>
<p>Long context 的 effective context 跟 claimed context 落差來自三個現象：</p>
<table>
  <thead>
      <tr>
          <th>現象</th>
          <th>描述</th>
          <th>嚴重度</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>Lost in the middle</td>
          <td>中段內容 attention 顯著低、recall 掉</td>
          <td>普遍、最頻繁</td>
      </tr>
      <tr>
          <td>Context degradation</td>
          <td>接近 context 上限時、整體品質緩降</td>
          <td>接近上限才明顯</td>
      </tr>
      <tr>
          <td>Needle in haystack</td>
          <td>抓單一事實的能力（vs lost-in-the-middle 抓整段邏輯）</td>
          <td>兩條軸、不完全重疊</td>
      </tr>
  </tbody>
</table>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="ln"> 1</span><span class="cl">Recall accuracy vs 答案位置（典型 10K context）：
</span></span><span class="line"><span class="ln"> 2</span><span class="cl">
</span></span><span class="line"><span class="ln"> 3</span><span class="cl">100% |█                                       █
</span></span><span class="line"><span class="ln"> 4</span><span class="cl">     |██                                     ██
</span></span><span class="line"><span class="ln"> 5</span><span class="cl"> 80% |███                                   ███
</span></span><span class="line"><span class="ln"> 6</span><span class="cl">     |███                                   ███
</span></span><span class="line"><span class="ln"> 7</span><span class="cl"> 60% |███          ____                     ███
</span></span><span class="line"><span class="ln"> 8</span><span class="cl">     |███      ___/    \___                 ███
</span></span><span class="line"><span class="ln"> 9</span><span class="cl"> 40% |███    _/            \_               ███
</span></span><span class="line"><span class="ln">10</span><span class="cl">     |█████─/                \─────         ███
</span></span><span class="line"><span class="ln">11</span><span class="cl">     |
</span></span><span class="line"><span class="ln">12</span><span class="cl">       0      2K     4K     6K     8K    10K
</span></span><span class="line"><span class="ln">13</span><span class="cl">       開頭                              結尾</span></span></code></pre></div><p>成因：</p>
<ol>
<li><strong>Attention weight 分佈不均勻</strong>：訓練資料中、句首 / 段首通常含關鍵資訊、模型學會偏重句首；長 context 的中段在訓練資料中相對稀疏、attention 沒學好</li>
<li><strong>Positional encoding 設計</strong>：RoPE / ALiBi 等對長距離 attention 的衰減模式、中段 token 跟 query 距離通常較大、attention 弱</li>
<li><strong>訓練 context 長度的影響</strong>：模型若訓練在 8K context、推論時用 128K（用 RoPE scaling 延伸）、中段表現比訓練範圍內差更多</li>
</ol>
<h2 id="設計責任">設計責任</h2>
<p>讀 long-context paper / benchmark 看到「lost-in-the-middle」「U-shape recall」就是這現象。寫 code 場景的判讀：</p>
<ol>
<li><strong>把關鍵資訊放開頭或結尾</strong>：system prompt 在開頭、最新指示在結尾（剛好是模型 attention 最強的兩處）</li>
<li><strong>長 context 不是「塞越多越好」</strong>：超過 effective context（典型 8-16K）後、邊際效用急降</li>
<li><strong>RAG 比 long context 仍有價值</strong>：把相關片段 retrieve 出來放 prompt 開頭、比把整份文件塞進 100K context 效果更穩定</li>
<li><strong>驗證自己模型的 effective context</strong>：用 needle-in-haystack 或自製測試、看模型在 8K / 16K / 32K 表現掉到哪</li>
<li><strong>Reasoning model 的 thinking trace 不會遇到這事故嗎？</strong> — 仍會遇到、但 reasoning 過程會主動重新引用前文、部分緩解；不過 thinking trace 本身會擠壓 context budget、可能反而觸發 degradation</li>
</ol>
]]></content:encoded></item><item><title>Matrix Multiplication</title><link>https://tarrragon.github.io/blog/llm/knowledge-cards/matrix-multiplication/</link><pubDate>Tue, 12 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/llm/knowledge-cards/matrix-multiplication/</guid><description>&lt;p>Matrix multiplication（矩陣乘法、matmul、&lt;code>@&lt;/code>）的核心概念是「&lt;strong>左矩陣的每個 row 跟右矩陣的每個 column 做 &lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/dot-product/" data-link-title="Dot Product" data-link-desc="兩個向量對應位置相乘再加總、attention score 跟相似度判讀的基礎">dot product&lt;/a>、結果填進新矩陣&lt;/strong>」。對 &lt;code>A (m × k)&lt;/code> 跟 &lt;code>B (k × n)&lt;/code>、結果 &lt;code>C (m × n)&lt;/code>、其中 &lt;code>C[i][j] = A 第 i row · B 第 j column&lt;/code>。Matmul 是 LLM 推論最頻繁的運算、整個 &lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/forward-pass/" data-link-title="Forward Pass" data-link-desc="input 經過所有 layer 的計算、得到 output 的單向流程；推論跟訓練都會跑、訓練多一個反向階段">forward pass&lt;/a> 可以看成幾百次 matmul 串起來。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>LLM 中 matmul 出現的關鍵位置：&lt;/p>
&lt;table>
 &lt;thead>
 &lt;tr>
 &lt;th>位置&lt;/th>
 &lt;th>形狀（簡化）&lt;/th>
 &lt;th>角色&lt;/th>
 &lt;/tr>
 &lt;/thead>
 &lt;tbody>
 &lt;tr>
 &lt;td>Embedding lookup&lt;/td>
 &lt;td>&lt;code>(seq_len, vocab) @ (vocab, hidden)&lt;/code> ≡ 查表&lt;/td>
 &lt;td>Token ID → embedding&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>Q/K/V 投影&lt;/td>
 &lt;td>&lt;code>(seq_len, hidden) @ (hidden, hidden)&lt;/code>&lt;/td>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/self-attention/" data-link-title="Self-Attention" data-link-desc="Q / K / V 都從同一個 sequence 投影出來的 attention、Transformer 的標誌性設計">Self-attention&lt;/a> 第一步&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>Attention score&lt;/td>
 &lt;td>&lt;code>(seq_len, head_dim) @ (head_dim, seq_len)&lt;/code>&lt;/td>
 &lt;td>Q · K^T、O(n²)、long context 痛點&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>Attention output&lt;/td>
 &lt;td>&lt;code>(seq_len, seq_len) @ (seq_len, head_dim)&lt;/code>&lt;/td>
 &lt;td>attention weight · V&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/ffn/" data-link-title="FFN（Feed-Forward Network）" data-link-desc="Transformer block 內部的兩層 linear &amp;#43; activation、佔模型參數量的多數">FFN&lt;/a> up&lt;/td>
 &lt;td>&lt;code>(seq_len, hidden) @ (hidden, 4×hidden)&lt;/code>&lt;/td>
 &lt;td>FFN 升維、參數大頭&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>FFN down&lt;/td>
 &lt;td>&lt;code>(seq_len, 4×hidden) @ (4×hidden, hidden)&lt;/code>&lt;/td>
 &lt;td>FFN 降維&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>Output projection&lt;/td>
 &lt;td>&lt;code>(seq_len, hidden) @ (hidden, vocab)&lt;/code>&lt;/td>
 &lt;td>Hidden → logits&lt;/td>
 &lt;/tr>
 &lt;/tbody>
&lt;/table>
&lt;p>關鍵尺寸規則：&lt;strong>左矩陣 column 數 = 右矩陣 row 數&lt;/strong>、即 &lt;code>(m × k) @ (k × n) = (m × n)&lt;/code>。Dimension mismatch 是訓練 / 推論最常見的 PyTorch 報錯之一。&lt;/p>
&lt;h2 id="為什麼-matmul-是-memory-bandwidth-bound">為什麼 matmul 是 &lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/memory-bandwidth/" data-link-title="Memory Bandwidth" data-link-desc="記憶體每秒能讀寫多少 bytes：決定本地 LLM 生字速度的真正瓶頸">memory bandwidth&lt;/a> bound&lt;/h2>
&lt;p>LLM 推論每生一個 token、要把整份模型權重從記憶體讀到處理器一次（每個權重在當輪 forward pass 的某個 matmul 都用得到）；現代 GPU / Apple Silicon 的算力遠超頻寬、所以「讀權重要多久」變主要瓶頸。這就是為什麼：&lt;/p>
&lt;ul>
&lt;li>31B 模型 Q4_K_M 約 18GB、M4 Max 頻寬 546 GB/s、理論上限 ≈ 30 tok/s&lt;/li>
&lt;li>&lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/quantization/" data-link-title="Quantization" data-link-desc="用較少 bits 表示模型權重：壓縮記憶體佔用、加快生字速度，代價是少量品質衰減">量化&lt;/a> 加速主要是「權重變小、每秒能讀過更多次完整模型」&lt;/li>
&lt;li>&lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/batching/" data-link-title="Batching" data-link-desc="多 request 一起跑、攤平 model load 成本：production LLM inference 的核心優化、決定 throughput vs latency 取捨">Batching&lt;/a> / &lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/speculative-decoding/" data-link-title="Speculative Decoding" data-link-desc="用小模型猜未來 token、大模型並行驗證的加速技巧">speculative decoding&lt;/a> 加速主要是「一次讀權重、攤平到多個 token」&lt;/li>
&lt;/ul>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>讀 paper / model card 看到模型參數量、可以反推總 matmul 工作量；看到 inference benchmark 看到 tok/s、可以用「模型大小 / memory bandwidth」算理論上限對照。寫 code 場景無需直接寫 matmul、但理解這個運算的成本結構、能看懂量化 / batching / speculative decoding 等加速技巧為什麼有效。&lt;/p></description><content:encoded><![CDATA[<p>Matrix multiplication（矩陣乘法、matmul、<code>@</code>）的核心概念是「<strong>左矩陣的每個 row 跟右矩陣的每個 column 做 <a href="/blog/llm/knowledge-cards/dot-product/" data-link-title="Dot Product" data-link-desc="兩個向量對應位置相乘再加總、attention score 跟相似度判讀的基礎">dot product</a>、結果填進新矩陣</strong>」。對 <code>A (m × k)</code> 跟 <code>B (k × n)</code>、結果 <code>C (m × n)</code>、其中 <code>C[i][j] = A 第 i row · B 第 j column</code>。Matmul 是 LLM 推論最頻繁的運算、整個 <a href="/blog/llm/knowledge-cards/forward-pass/" data-link-title="Forward Pass" data-link-desc="input 經過所有 layer 的計算、得到 output 的單向流程；推論跟訓練都會跑、訓練多一個反向階段">forward pass</a> 可以看成幾百次 matmul 串起來。</p>
<h2 id="概念位置">概念位置</h2>
<p>LLM 中 matmul 出現的關鍵位置：</p>
<table>
  <thead>
      <tr>
          <th>位置</th>
          <th>形狀（簡化）</th>
          <th>角色</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>Embedding lookup</td>
          <td><code>(seq_len, vocab) @ (vocab, hidden)</code> ≡ 查表</td>
          <td>Token ID → embedding</td>
      </tr>
      <tr>
          <td>Q/K/V 投影</td>
          <td><code>(seq_len, hidden) @ (hidden, hidden)</code></td>
          <td><a href="/blog/llm/knowledge-cards/self-attention/" data-link-title="Self-Attention" data-link-desc="Q / K / V 都從同一個 sequence 投影出來的 attention、Transformer 的標誌性設計">Self-attention</a> 第一步</td>
      </tr>
      <tr>
          <td>Attention score</td>
          <td><code>(seq_len, head_dim) @ (head_dim, seq_len)</code></td>
          <td>Q · K^T、O(n²)、long context 痛點</td>
      </tr>
      <tr>
          <td>Attention output</td>
          <td><code>(seq_len, seq_len) @ (seq_len, head_dim)</code></td>
          <td>attention weight · V</td>
      </tr>
      <tr>
          <td><a href="/blog/llm/knowledge-cards/ffn/" data-link-title="FFN（Feed-Forward Network）" data-link-desc="Transformer block 內部的兩層 linear &#43; activation、佔模型參數量的多數">FFN</a> up</td>
          <td><code>(seq_len, hidden) @ (hidden, 4×hidden)</code></td>
          <td>FFN 升維、參數大頭</td>
      </tr>
      <tr>
          <td>FFN down</td>
          <td><code>(seq_len, 4×hidden) @ (4×hidden, hidden)</code></td>
          <td>FFN 降維</td>
      </tr>
      <tr>
          <td>Output projection</td>
          <td><code>(seq_len, hidden) @ (hidden, vocab)</code></td>
          <td>Hidden → logits</td>
      </tr>
  </tbody>
</table>
<p>關鍵尺寸規則：<strong>左矩陣 column 數 = 右矩陣 row 數</strong>、即 <code>(m × k) @ (k × n) = (m × n)</code>。Dimension mismatch 是訓練 / 推論最常見的 PyTorch 報錯之一。</p>
<h2 id="為什麼-matmul-是-memory-bandwidth-bound">為什麼 matmul 是 <a href="/blog/llm/knowledge-cards/memory-bandwidth/" data-link-title="Memory Bandwidth" data-link-desc="記憶體每秒能讀寫多少 bytes：決定本地 LLM 生字速度的真正瓶頸">memory bandwidth</a> bound</h2>
<p>LLM 推論每生一個 token、要把整份模型權重從記憶體讀到處理器一次（每個權重在當輪 forward pass 的某個 matmul 都用得到）；現代 GPU / Apple Silicon 的算力遠超頻寬、所以「讀權重要多久」變主要瓶頸。這就是為什麼：</p>
<ul>
<li>31B 模型 Q4_K_M 約 18GB、M4 Max 頻寬 546 GB/s、理論上限 ≈ 30 tok/s</li>
<li><a href="/blog/llm/knowledge-cards/quantization/" data-link-title="Quantization" data-link-desc="用較少 bits 表示模型權重：壓縮記憶體佔用、加快生字速度，代價是少量品質衰減">量化</a> 加速主要是「權重變小、每秒能讀過更多次完整模型」</li>
<li><a href="/blog/llm/knowledge-cards/batching/" data-link-title="Batching" data-link-desc="多 request 一起跑、攤平 model load 成本：production LLM inference 的核心優化、決定 throughput vs latency 取捨">Batching</a> / <a href="/blog/llm/knowledge-cards/speculative-decoding/" data-link-title="Speculative Decoding" data-link-desc="用小模型猜未來 token、大模型並行驗證的加速技巧">speculative decoding</a> 加速主要是「一次讀權重、攤平到多個 token」</li>
</ul>
<h2 id="設計責任">設計責任</h2>
<p>讀 paper / model card 看到模型參數量、可以反推總 matmul 工作量；看到 inference benchmark 看到 tok/s、可以用「模型大小 / memory bandwidth」算理論上限對照。寫 code 場景無需直接寫 matmul、但理解這個運算的成本結構、能看懂量化 / batching / speculative decoding 等加速技巧為什麼有效。</p>
]]></content:encoded></item><item><title>Mixture of Experts (MoE)</title><link>https://tarrragon.github.io/blog/llm/knowledge-cards/moe/</link><pubDate>Tue, 12 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/llm/knowledge-cards/moe/</guid><description>&lt;p>MoE（Mixture of Experts）的核心概念是「把 transformer block 內的 FFN 層拆成多個專家網路、router 為每個 token 動態挑選少數啟用」。結果是模型總參數可以擴張到很大、但每個 token 實際計算量保持在「&lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/active-parameter/" data-link-title="Active Parameter" data-link-desc="MoE 模型每生成一個 token 實際參與計算的參數量、跟模型總參數量不同、影響推論速度上限">active parameter&lt;/a>」這個較小的數目；同硬體下 MoE 模型常比同總參數的 Dense 模型跑得快、且能力強於同 active parameter 的 Dense 模型。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>MoE 在 transformer 架構中的位置：&lt;/p>





&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-text" data-lang="text">&lt;span class="line">&lt;span class="ln">1&lt;/span>&lt;span class="cl">transformer block：
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">2&lt;/span>&lt;span class="cl"> ├── attention 層（所有 token 共用）
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">3&lt;/span>&lt;span class="cl"> ├── layer norm
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">4&lt;/span>&lt;span class="cl"> └── FFN 層
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">5&lt;/span>&lt;span class="cl"> ├── Dense 架構：所有 token 走同一組 FFN
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">6&lt;/span>&lt;span class="cl"> └── MoE 架構：FFN 拆成多個 expert、router 挑選 top-k 個啟用&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>主流 MoE 模型的設計選擇（依模型而異）：&lt;/p>
&lt;ul>
&lt;li>&lt;strong>expert 數量&lt;/strong>：通常 8 ~ 256 個&lt;/li>
&lt;li>&lt;strong>每 token 啟用 expert 數&lt;/strong>：通常 1 ~ 2 個（top-k routing）&lt;/li>
&lt;li>&lt;strong>shared expert&lt;/strong>：部分模型保留少數所有 token 共用的 expert&lt;/li>
&lt;li>&lt;strong>total / active parameter 比&lt;/strong>：常見 5x ~ 10x（如 Qwen3-30B-A3B：30B total / 3B active）&lt;/li>
&lt;/ul>
&lt;blockquote>
&lt;p>&lt;strong>事實查核註&lt;/strong>：MoE 架構的具體實作（router 演算法、load balancing loss、expert 並行策略等）依模型快速演進、引用前以該模型的技術報告或 paper 為準。&lt;/p>&lt;/blockquote>
&lt;p>代表性 MoE 模型（依公開資訊）：Mixtral 8x7B、DeepSeek V3、Qwen3-30B-A3B、Llama 4 Scout 等。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>理解 MoE 後可以解釋三個現象：為什麼 MoE 模型的「30B 總參數」跟「3B active parameter」是兩個獨立指標（前者影響記憶體需求、後者影響速度）、為什麼 MoE 適合 &lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/moe-cpu-offload/" data-link-title="MoE CPU 卸載" data-link-desc="把 Mixture-of-Experts 模型不活躍的專家層權重放在系統 RAM、用到再走 PCIe 拉回 GPU、讓有限 VRAM 跑得了更大模型">CPU 卸載&lt;/a>（不活躍的 expert 可以留在系統 RAM）、為什麼 MoE 在多 GPU 場景的並行策略跟 Dense 模型不同（expert 可以分到不同卡）。&lt;/p>
&lt;p>選 MoE 模型 vs Dense 模型、需考慮：MoE 對 RAM 容量要求較高（要放所有 expert 權重）、對 GPU 算力要求較低（每 token 走 active parameter）；Dense 對 VRAM 容量要求較低（可全載中型模型）、對 GPU 算力要求較高。詳見 &lt;a href="https://tarrragon.github.io/blog/llm/05-discrete-gpu/moe-cpu-offload-strategy/" data-link-title="5.1 MoE 模型與 CPU 卸載策略" data-link-desc="PC 場景把 MoE 不活躍專家層留在系統 RAM 的判讀：何時值得卸載、卸幾層、對 prefill 跟生成的影響各自不同">5.1 MoE 模型與 CPU 卸載策略&lt;/a> 跟 &lt;a href="https://tarrragon.github.io/blog/llm/05-discrete-gpu/model-selection-priority-pc/" data-link-title="5.5 PC 場景的模型選型優先順序" data-link-desc="PC 獨立 GPU 場景下、MoE 卸載讓「全載小模型 vs 卸載大 MoE」變成主要的選型軸；對應不同 VRAM 容量的模型推薦">5.5 PC 場景的模型選型優先順序&lt;/a>。&lt;/p></description><content:encoded><![CDATA[<p>MoE（Mixture of Experts）的核心概念是「把 transformer block 內的 FFN 層拆成多個專家網路、router 為每個 token 動態挑選少數啟用」。結果是模型總參數可以擴張到很大、但每個 token 實際計算量保持在「<a href="/blog/llm/knowledge-cards/active-parameter/" data-link-title="Active Parameter" data-link-desc="MoE 模型每生成一個 token 實際參與計算的參數量、跟模型總參數量不同、影響推論速度上限">active parameter</a>」這個較小的數目；同硬體下 MoE 模型常比同總參數的 Dense 模型跑得快、且能力強於同 active parameter 的 Dense 模型。</p>
<h2 id="概念位置">概念位置</h2>
<p>MoE 在 transformer 架構中的位置：</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="ln">1</span><span class="cl">transformer block：
</span></span><span class="line"><span class="ln">2</span><span class="cl">  ├── attention 層（所有 token 共用）
</span></span><span class="line"><span class="ln">3</span><span class="cl">  ├── layer norm
</span></span><span class="line"><span class="ln">4</span><span class="cl">  └── FFN 層
</span></span><span class="line"><span class="ln">5</span><span class="cl">        ├── Dense 架構：所有 token 走同一組 FFN
</span></span><span class="line"><span class="ln">6</span><span class="cl">        └── MoE 架構：FFN 拆成多個 expert、router 挑選 top-k 個啟用</span></span></code></pre></div><p>主流 MoE 模型的設計選擇（依模型而異）：</p>
<ul>
<li><strong>expert 數量</strong>：通常 8 ~ 256 個</li>
<li><strong>每 token 啟用 expert 數</strong>：通常 1 ~ 2 個（top-k routing）</li>
<li><strong>shared expert</strong>：部分模型保留少數所有 token 共用的 expert</li>
<li><strong>total / active parameter 比</strong>：常見 5x ~ 10x（如 Qwen3-30B-A3B：30B total / 3B active）</li>
</ul>
<blockquote>
<p><strong>事實查核註</strong>：MoE 架構的具體實作（router 演算法、load balancing loss、expert 並行策略等）依模型快速演進、引用前以該模型的技術報告或 paper 為準。</p></blockquote>
<p>代表性 MoE 模型（依公開資訊）：Mixtral 8x7B、DeepSeek V3、Qwen3-30B-A3B、Llama 4 Scout 等。</p>
<h2 id="設計責任">設計責任</h2>
<p>理解 MoE 後可以解釋三個現象：為什麼 MoE 模型的「30B 總參數」跟「3B active parameter」是兩個獨立指標（前者影響記憶體需求、後者影響速度）、為什麼 MoE 適合 <a href="/blog/llm/knowledge-cards/moe-cpu-offload/" data-link-title="MoE CPU 卸載" data-link-desc="把 Mixture-of-Experts 模型不活躍的專家層權重放在系統 RAM、用到再走 PCIe 拉回 GPU、讓有限 VRAM 跑得了更大模型">CPU 卸載</a>（不活躍的 expert 可以留在系統 RAM）、為什麼 MoE 在多 GPU 場景的並行策略跟 Dense 模型不同（expert 可以分到不同卡）。</p>
<p>選 MoE 模型 vs Dense 模型、需考慮：MoE 對 RAM 容量要求較高（要放所有 expert 權重）、對 GPU 算力要求較低（每 token 走 active parameter）；Dense 對 VRAM 容量要求較低（可全載中型模型）、對 GPU 算力要求較高。詳見 <a href="/blog/llm/05-discrete-gpu/moe-cpu-offload-strategy/" data-link-title="5.1 MoE 模型與 CPU 卸載策略" data-link-desc="PC 場景把 MoE 不活躍專家層留在系統 RAM 的判讀：何時值得卸載、卸幾層、對 prefill 跟生成的影響各自不同">5.1 MoE 模型與 CPU 卸載策略</a> 跟 <a href="/blog/llm/05-discrete-gpu/model-selection-priority-pc/" data-link-title="5.5 PC 場景的模型選型優先順序" data-link-desc="PC 獨立 GPU 場景下、MoE 卸載讓「全載小模型 vs 卸載大 MoE」變成主要的選型軸；對應不同 VRAM 容量的模型推薦">5.5 PC 場景的模型選型優先順序</a>。</p>
]]></content:encoded></item><item><title>Model Card</title><link>https://tarrragon.github.io/blog/llm/knowledge-cards/model-card/</link><pubDate>Tue, 12 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/llm/knowledge-cards/model-card/</guid><description>&lt;p>Model card 的核心概念是「模型發布時附帶的 metadata 文件、列出模型的來源、訓練資料、預期用途、能力上限、已知限制跟授權條款」。Hugging Face 上每個 model repo 的 &lt;code>README.md&lt;/code> 就是 model card；它是個人 dev 跟 production 場景下判讀「該不該用這個模型」的最主要資訊來源。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>典型的 model card 包含哪些區段（依平台跟模型而異）：&lt;/p>
&lt;table>
 &lt;thead>
 &lt;tr>
 &lt;th>區段&lt;/th>
 &lt;th>內容&lt;/th>
 &lt;th>對應的判讀&lt;/th>
 &lt;/tr>
 &lt;/thead>
 &lt;tbody>
 &lt;tr>
 &lt;td>基本資訊&lt;/td>
 &lt;td>模型名稱、參數量、架構、發布者&lt;/td>
 &lt;td>確認是哪個 organization 發布&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>Training data&lt;/td>
 &lt;td>訓練語料的來源、規模、語言分布&lt;/td>
 &lt;td>評估模型在自己語言 / 任務的適配性&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>Intended use&lt;/td>
 &lt;td>預期用途、適合的應用場景&lt;/td>
 &lt;td>判讀模型是否符合自己工作流&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>Out-of-scope use&lt;/td>
 &lt;td>不適合的用途、已知不擅長的任務&lt;/td>
 &lt;td>避免誤用&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>Bias、ethical considerations&lt;/td>
 &lt;td>已知偏見、敏感議題的回應傾向&lt;/td>
 &lt;td>production 場景的合規評估&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>Benchmark&lt;/td>
 &lt;td>在公開 benchmark 上的分數&lt;/td>
 &lt;td>跟其他模型對比&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>License&lt;/td>
 &lt;td>模型權重的使用授權&lt;/td>
 &lt;td>商用前必看&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>Quantization 版本&lt;/td>
 &lt;td>該 repo 提供哪些量化版本&lt;/td>
 &lt;td>選對應 &lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/gguf/" data-link-title="GGUF" data-link-desc="llama.cpp 生態定義的模型權重格式：把權重、tokenizer、metadata 打包成單一檔案">GGUF&lt;/a> 版本&lt;/td>
 &lt;/tr>
 &lt;/tbody>
&lt;/table>
&lt;blockquote>
&lt;p>&lt;strong>事實查核註&lt;/strong>：Hugging Face 推動 Model Card 規範跟 &lt;a href="https://github.com/huggingface/hub-docs">Model Card Toolkit&lt;/a>、但實際填寫品質依 organization 變化、部分 repo 的 model card 內容很簡略、不能 100% 依賴。引用前以該 repo 當前內容為準。&lt;/p>&lt;/blockquote>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>理解 model card 後可以解釋兩個現象：為什麼選模型不能只看名字（同個 base model 的不同 fine-tune 版本能力差很多）、為什麼商用前要看 license（Llama Community License、Apache 2.0、MIT 等差異大）。&lt;/p>
&lt;p>實務上選模型時、model card 是第一閱讀對象、其他資訊（社群評測、benchmark leaderboard）作為交叉驗證；引用模型時應該明確記下「base model + fine-tune 變體 + 量化版本」三層。詳見 &lt;a href="https://tarrragon.github.io/blog/llm/06-security/model-supply-chain-trust/" data-link-title="6.0 模型供應鏈與信任邊界" data-link-desc="個人 dev 用本地 LLM 時的模型權重來源信任：GGUF 完整性、Hugging Face / Ollama registry 信任、量化版本污染、檔案完整性檢查">6.0 模型供應鏈與信任邊界&lt;/a> 跟 &lt;a href="https://tarrragon.github.io/blog/backend/07-security-data-protection/llm-deployment-supply-chain/" data-link-title="LLM Deployment 供應鏈完整性" data-link-desc="把 LLM 模型權重、推論伺服器、第三方 plugin 三條 production 供應鏈納入既有 artifact trust 框架的判讀">LLM Deployment 供應鏈完整性&lt;/a>。&lt;/p></description><content:encoded><![CDATA[<p>Model card 的核心概念是「模型發布時附帶的 metadata 文件、列出模型的來源、訓練資料、預期用途、能力上限、已知限制跟授權條款」。Hugging Face 上每個 model repo 的 <code>README.md</code> 就是 model card；它是個人 dev 跟 production 場景下判讀「該不該用這個模型」的最主要資訊來源。</p>
<h2 id="概念位置">概念位置</h2>
<p>典型的 model card 包含哪些區段（依平台跟模型而異）：</p>
<table>
  <thead>
      <tr>
          <th>區段</th>
          <th>內容</th>
          <th>對應的判讀</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>基本資訊</td>
          <td>模型名稱、參數量、架構、發布者</td>
          <td>確認是哪個 organization 發布</td>
      </tr>
      <tr>
          <td>Training data</td>
          <td>訓練語料的來源、規模、語言分布</td>
          <td>評估模型在自己語言 / 任務的適配性</td>
      </tr>
      <tr>
          <td>Intended use</td>
          <td>預期用途、適合的應用場景</td>
          <td>判讀模型是否符合自己工作流</td>
      </tr>
      <tr>
          <td>Out-of-scope use</td>
          <td>不適合的用途、已知不擅長的任務</td>
          <td>避免誤用</td>
      </tr>
      <tr>
          <td>Bias、ethical considerations</td>
          <td>已知偏見、敏感議題的回應傾向</td>
          <td>production 場景的合規評估</td>
      </tr>
      <tr>
          <td>Benchmark</td>
          <td>在公開 benchmark 上的分數</td>
          <td>跟其他模型對比</td>
      </tr>
      <tr>
          <td>License</td>
          <td>模型權重的使用授權</td>
          <td>商用前必看</td>
      </tr>
      <tr>
          <td>Quantization 版本</td>
          <td>該 repo 提供哪些量化版本</td>
          <td>選對應 <a href="/blog/llm/knowledge-cards/gguf/" data-link-title="GGUF" data-link-desc="llama.cpp 生態定義的模型權重格式：把權重、tokenizer、metadata 打包成單一檔案">GGUF</a> 版本</td>
      </tr>
  </tbody>
</table>
<blockquote>
<p><strong>事實查核註</strong>：Hugging Face 推動 Model Card 規範跟 <a href="https://github.com/huggingface/hub-docs">Model Card Toolkit</a>、但實際填寫品質依 organization 變化、部分 repo 的 model card 內容很簡略、不能 100% 依賴。引用前以該 repo 當前內容為準。</p></blockquote>
<h2 id="設計責任">設計責任</h2>
<p>理解 model card 後可以解釋兩個現象：為什麼選模型不能只看名字（同個 base model 的不同 fine-tune 版本能力差很多）、為什麼商用前要看 license（Llama Community License、Apache 2.0、MIT 等差異大）。</p>
<p>實務上選模型時、model card 是第一閱讀對象、其他資訊（社群評測、benchmark leaderboard）作為交叉驗證；引用模型時應該明確記下「base model + fine-tune 變體 + 量化版本」三層。詳見 <a href="/blog/llm/06-security/model-supply-chain-trust/" data-link-title="6.0 模型供應鏈與信任邊界" data-link-desc="個人 dev 用本地 LLM 時的模型權重來源信任：GGUF 完整性、Hugging Face / Ollama registry 信任、量化版本污染、檔案完整性檢查">6.0 模型供應鏈與信任邊界</a> 跟 <a href="/blog/backend/07-security-data-protection/llm-deployment-supply-chain/" data-link-title="LLM Deployment 供應鏈完整性" data-link-desc="把 LLM 模型權重、推論伺服器、第三方 plugin 三條 production 供應鏈納入既有 artifact trust 框架的判讀">LLM Deployment 供應鏈完整性</a>。</p>
]]></content:encoded></item><item><title>Model Tag</title><link>https://tarrragon.github.io/blog/llm/knowledge-cards/model-tag/</link><pubDate>Tue, 12 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/llm/knowledge-cards/model-tag/</guid><description>&lt;p>Model Tag 的核心概念是「推論伺服器用來定位特定模型版本的字串 key」。同一個模型家族（例如 Gemma 4）會被切出十幾個 tag、每個 tag 對應不同的參數量、訓練變體與&lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/quantization/" data-link-title="Quantization" data-link-desc="用較少 bits 表示模型權重：壓縮記憶體佔用、加快生字速度，代價是少量品質衰減">量化&lt;/a>等級、使用者用 tag 在 CLI 或 API 中指定要載入哪一份權重。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>Model tag 是介面層跟&lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/inference-server/" data-link-title="Inference Server" data-link-desc="載入模型權重、處理 prompt、產生 token 的常駐 process">推論伺服器&lt;/a>之間的識別碼、形式由各個伺服器各自定義。Ollama 用 &lt;code>family:size-variant-quantization&lt;/code> 的單行字串、LM Studio 用 Hugging Face 完整檔名、llama.cpp 直接用 &lt;code>.gguf&lt;/code> 檔路徑。同一份模型權重在不同伺服器有不同 tag 字串、但指向的底層&lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/gguf/" data-link-title="GGUF" data-link-desc="llama.cpp 生態定義的模型權重格式：把權重、tokenizer、metadata 打包成單一檔案">GGUF&lt;/a>權重可以是同一份。&lt;/p>
&lt;h2 id="可觀察訊號與例子">可觀察訊號與例子&lt;/h2>
&lt;p>Ollama 的 tag 結構：&lt;/p>
&lt;table>
 &lt;thead>
 &lt;tr>
 &lt;th>範例&lt;/th>
 &lt;th>拆解&lt;/th>
 &lt;/tr>
 &lt;/thead>
 &lt;tbody>
 &lt;tr>
 &lt;td>&lt;code>gemma4:e4b&lt;/code>&lt;/td>
 &lt;td>Gemma 4、E4B（edge dense）、預設量化&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;code>gemma4:31b-instruct-q5_K_M&lt;/code>&lt;/td>
 &lt;td>Gemma 4、31B、instruct-tuned、Q5_K_M 量化&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;code>gemma4:31b-coding-mtp-bf16&lt;/code>&lt;/td>
 &lt;td>Gemma 4、31B、coding 特化、含 &lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/mtp/" data-link-title="Multi-Token Prediction (MTP)" data-link-desc="Google 為 Gemma 系列釋出的 speculative decoding 工程化實作">MTP&lt;/a> drafter&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;code>qwen3-coder:30b&lt;/code>&lt;/td>
 &lt;td>Qwen3-Coder、30B 參數、預設量化&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;code>llama3.3:70b-instruct-q4_K_M&lt;/code>&lt;/td>
 &lt;td>Llama 3.3、70B、instruct、Q4_K_M&lt;/td>
 &lt;/tr>
 &lt;/tbody>
&lt;/table>
&lt;p>四個欄位裡、&lt;code>size&lt;/code> 直接決定記憶體佔用、&lt;code>variant&lt;/code>（instruct / coding / base）決定模型適合的任務型態、&lt;code>quantization&lt;/code> 影響品質跟記憶體取捨。Tag 中省略某些欄位時、伺服器用該欄位的預設值（通常是「常用組合」）。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>選 tag 時要看三件事：先看 &lt;code>size&lt;/code> 確認模型塞得進記憶體（對照&lt;a href="https://tarrragon.github.io/blog/llm/00-foundations/hardware-memory-budget/" data-link-title="0.5 Apple Silicon 記憶體預算" data-link-desc="記憶體決定能跑什麼，Q4 量化下的可運作模型對照與系統保留">硬體記憶體預算&lt;/a>）、再看 &lt;code>variant&lt;/code> 確認用途匹配（寫 code 要選 &lt;code>instruct&lt;/code> / &lt;code>coding&lt;/code> 變體、避免 base model 的隨機接龍行為）、最後看 &lt;code>quantization&lt;/code> 決定品質 / 記憶體甜蜜點。完整可用 tag 在各伺服器的 model registry（Ollama 在 &lt;a href="https://ollama.com/library">ollama.com/library&lt;/a>、LM Studio 在 Discover 分頁）。&lt;/p></description><content:encoded><![CDATA[<p>Model Tag 的核心概念是「推論伺服器用來定位特定模型版本的字串 key」。同一個模型家族（例如 Gemma 4）會被切出十幾個 tag、每個 tag 對應不同的參數量、訓練變體與<a href="/blog/llm/knowledge-cards/quantization/" data-link-title="Quantization" data-link-desc="用較少 bits 表示模型權重：壓縮記憶體佔用、加快生字速度，代價是少量品質衰減">量化</a>等級、使用者用 tag 在 CLI 或 API 中指定要載入哪一份權重。</p>
<h2 id="概念位置">概念位置</h2>
<p>Model tag 是介面層跟<a href="/blog/llm/knowledge-cards/inference-server/" data-link-title="Inference Server" data-link-desc="載入模型權重、處理 prompt、產生 token 的常駐 process">推論伺服器</a>之間的識別碼、形式由各個伺服器各自定義。Ollama 用 <code>family:size-variant-quantization</code> 的單行字串、LM Studio 用 Hugging Face 完整檔名、llama.cpp 直接用 <code>.gguf</code> 檔路徑。同一份模型權重在不同伺服器有不同 tag 字串、但指向的底層<a href="/blog/llm/knowledge-cards/gguf/" data-link-title="GGUF" data-link-desc="llama.cpp 生態定義的模型權重格式：把權重、tokenizer、metadata 打包成單一檔案">GGUF</a>權重可以是同一份。</p>
<h2 id="可觀察訊號與例子">可觀察訊號與例子</h2>
<p>Ollama 的 tag 結構：</p>
<table>
  <thead>
      <tr>
          <th>範例</th>
          <th>拆解</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td><code>gemma4:e4b</code></td>
          <td>Gemma 4、E4B（edge dense）、預設量化</td>
      </tr>
      <tr>
          <td><code>gemma4:31b-instruct-q5_K_M</code></td>
          <td>Gemma 4、31B、instruct-tuned、Q5_K_M 量化</td>
      </tr>
      <tr>
          <td><code>gemma4:31b-coding-mtp-bf16</code></td>
          <td>Gemma 4、31B、coding 特化、含 <a href="/blog/llm/knowledge-cards/mtp/" data-link-title="Multi-Token Prediction (MTP)" data-link-desc="Google 為 Gemma 系列釋出的 speculative decoding 工程化實作">MTP</a> drafter</td>
      </tr>
      <tr>
          <td><code>qwen3-coder:30b</code></td>
          <td>Qwen3-Coder、30B 參數、預設量化</td>
      </tr>
      <tr>
          <td><code>llama3.3:70b-instruct-q4_K_M</code></td>
          <td>Llama 3.3、70B、instruct、Q4_K_M</td>
      </tr>
  </tbody>
</table>
<p>四個欄位裡、<code>size</code> 直接決定記憶體佔用、<code>variant</code>（instruct / coding / base）決定模型適合的任務型態、<code>quantization</code> 影響品質跟記憶體取捨。Tag 中省略某些欄位時、伺服器用該欄位的預設值（通常是「常用組合」）。</p>
<h2 id="設計責任">設計責任</h2>
<p>選 tag 時要看三件事：先看 <code>size</code> 確認模型塞得進記憶體（對照<a href="/blog/llm/00-foundations/hardware-memory-budget/" data-link-title="0.5 Apple Silicon 記憶體預算" data-link-desc="記憶體決定能跑什麼，Q4 量化下的可運作模型對照與系統保留">硬體記憶體預算</a>）、再看 <code>variant</code> 確認用途匹配（寫 code 要選 <code>instruct</code> / <code>coding</code> 變體、避免 base model 的隨機接龍行為）、最後看 <code>quantization</code> 決定品質 / 記憶體甜蜜點。完整可用 tag 在各伺服器的 model registry（Ollama 在 <a href="https://ollama.com/library">ollama.com/library</a>、LM Studio 在 Discover 分頁）。</p>
]]></content:encoded></item><item><title>MoE CPU 卸載</title><link>https://tarrragon.github.io/blog/llm/knowledge-cards/moe-cpu-offload/</link><pubDate>Tue, 12 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/llm/knowledge-cards/moe-cpu-offload/</guid><description>&lt;p>MoE CPU 卸載的核心概念是「&lt;a href="https://en.wikipedia.org/wiki/Mixture_of_experts">Mixture-of-Experts&lt;/a> 模型每個 token 只啟用少數專家、把不活躍的專家權重留在系統 RAM、用到再走 PCIe 拉回 GPU」。它讓 16GB VRAM 卡能載入 30B / 70B 等級的 MoE 模型、是 &lt;a href="https://tarrragon.github.io/blog/llm/05-discrete-gpu/" data-link-title="模組五：Windows / Linux &amp;#43; 獨立 GPU" data-link-desc="消費級 PC（Windows / Linux &amp;#43; NVIDIA / AMD 獨立 GPU）跑本地 LLM 的硬體判讀、MoE CPU 卸載、KV cache 量化與 llama.cpp 調參">獨立 GPU 場景&lt;/a> 相對 &lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/unified-memory/" data-link-title="Unified Memory Architecture" data-link-desc="Apple Silicon 讓 CPU / GPU / NE 共用同一塊記憶體：跑大模型的優勢來源">統一記憶體&lt;/a> 場景多出的工程選項。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>MoE 卸載屬於「推論時的權重位置管理」、跟 &lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/quantization/" data-link-title="Quantization" data-link-desc="用較少 bits 表示模型權重：壓縮記憶體佔用、加快生字速度，代價是少量品質衰減">量化&lt;/a> 屬於「權重精度壓縮」是兩個獨立維度、可以疊加（如 30B MoE Q4 + 卸載部分層、模型精度跟記憶體位置同時被處理）。它跟 &lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/kv-cache/" data-link-title="KV Cache" data-link-desc="已處理 token 的 attention 中間結果暫存：避免重算、加速後續生成">KV cache&lt;/a> 量化是 PC 場景常一起使用的兩個工具：卸載騰出 VRAM、KV cache 量化讓騰出的 VRAM 拿去開大 &lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/context-window/" data-link-title="Context Window" data-link-desc="模型一次能處理的最大 token 數量：prompt 加生成的總和上限">context window&lt;/a>。&lt;/p>
&lt;p>在 llama.cpp 中、對應的旗標是 &lt;code>--n-cpu-moe &amp;lt;N&amp;gt;&lt;/code>、把 N 層的 MoE 專家權重保留在 CPU 記憶體。例如 &lt;code>--n-cpu-moe 30&lt;/code> 表示 30 層的專家層留 RAM、其餘走 GPU。&lt;/p>
&lt;h2 id="可觀察訊號與例子">可觀察訊號與例子&lt;/h2>
&lt;p>以 Qwen3-30B-A3B Q4_K_M（模型體積 10 GB 級、active parameter 約 3B 等級）為例、不同卸載策略下記憶體分布與生字速度的相對方向（具體數值依驅動、CUDA backend、模型版本、PCIe 版本變化、本表用於說明趨勢、不是嚴格 benchmark）：&lt;/p>
&lt;table>
 &lt;thead>
 &lt;tr>
 &lt;th>配置&lt;/th>
 &lt;th>卸載策略&lt;/th>
 &lt;th>VRAM 佔用方向&lt;/th>
 &lt;th>RAM 佔用方向&lt;/th>
 &lt;th>生字速度方向（同卡比較）&lt;/th>
 &lt;/tr>
 &lt;/thead>
 &lt;tbody>
 &lt;tr>
 &lt;td>全載 VRAM&lt;/td>
 &lt;td>&lt;code>--n-cpu-moe 0&lt;/code>&lt;/td>
 &lt;td>接近 VRAM 上限&lt;/td>
 &lt;td>系統正常&lt;/td>
 &lt;td>上限取決於 VRAM 頻寬&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>中度卸載&lt;/td>
 &lt;td>&lt;code>--n-cpu-moe ~20&lt;/code>&lt;/td>
 &lt;td>顯著下降&lt;/td>
 &lt;td>上升至 10 GB 級&lt;/td>
 &lt;td>較全載小幅下降&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>重度卸載&lt;/td>
 &lt;td>&lt;code>--n-cpu-moe ~30&lt;/code>&lt;/td>
 &lt;td>大幅下降&lt;/td>
 &lt;td>上升較多&lt;/td>
 &lt;td>較全載明顯下降&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>極限卸載&lt;/td>
 &lt;td>&lt;code>--n-cpu-moe ~40&lt;/code>&lt;/td>
 &lt;td>接近最低&lt;/td>
 &lt;td>上升最多&lt;/td>
 &lt;td>較全載大幅下降&lt;/td>
 &lt;/tr>
 &lt;/tbody>
&lt;/table>
&lt;blockquote>
&lt;p>&lt;strong>事實查核註&lt;/strong>：上表是趨勢示意、不是經本文系統實測的數值。實際數值依顯卡型號、PCIe 版本、CUDA backend、GGUF 量化版本、&lt;code>-ngl&lt;/code> 設定、context 長度與 batch size 變化、建議用 &lt;code>llama-bench&lt;/code> 或實際工作流校準。&lt;/p>&lt;/blockquote>
&lt;p>社群常見的觀察是：MoE 卸載對生字速度的衰減幅度、相對於「Dense 模型把同樣比例的層卸載到 CPU」較小、原因是 MoE 每 token 只啟用少數專家、PCIe 上的權重傳輸量也較少；具體幅度依模型架構（active parameter 比例、專家數）變化。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>理解 MoE 卸載後、可以解釋三個 PC 場景的現象：16GB VRAM 卡能載入 30B 級 MoE 模型（透過部分卸載而非全載 VRAM）、PC 場景 64GB RAM 相對 32GB 在 MoE 卸載空間上明顯更寬裕（可卸載更多層）、Mac 統一記憶體場景較少需要「卸載」這個概念（VRAM 跟 RAM 共用、不需要在兩個區域之間搬資料）。&lt;/p></description><content:encoded><![CDATA[<p>MoE CPU 卸載的核心概念是「<a href="https://en.wikipedia.org/wiki/Mixture_of_experts">Mixture-of-Experts</a> 模型每個 token 只啟用少數專家、把不活躍的專家權重留在系統 RAM、用到再走 PCIe 拉回 GPU」。它讓 16GB VRAM 卡能載入 30B / 70B 等級的 MoE 模型、是 <a href="/blog/llm/05-discrete-gpu/" data-link-title="模組五：Windows / Linux &#43; 獨立 GPU" data-link-desc="消費級 PC（Windows / Linux &#43; NVIDIA / AMD 獨立 GPU）跑本地 LLM 的硬體判讀、MoE CPU 卸載、KV cache 量化與 llama.cpp 調參">獨立 GPU 場景</a> 相對 <a href="/blog/llm/knowledge-cards/unified-memory/" data-link-title="Unified Memory Architecture" data-link-desc="Apple Silicon 讓 CPU / GPU / NE 共用同一塊記憶體：跑大模型的優勢來源">統一記憶體</a> 場景多出的工程選項。</p>
<h2 id="概念位置">概念位置</h2>
<p>MoE 卸載屬於「推論時的權重位置管理」、跟 <a href="/blog/llm/knowledge-cards/quantization/" data-link-title="Quantization" data-link-desc="用較少 bits 表示模型權重：壓縮記憶體佔用、加快生字速度，代價是少量品質衰減">量化</a> 屬於「權重精度壓縮」是兩個獨立維度、可以疊加（如 30B MoE Q4 + 卸載部分層、模型精度跟記憶體位置同時被處理）。它跟 <a href="/blog/llm/knowledge-cards/kv-cache/" data-link-title="KV Cache" data-link-desc="已處理 token 的 attention 中間結果暫存：避免重算、加速後續生成">KV cache</a> 量化是 PC 場景常一起使用的兩個工具：卸載騰出 VRAM、KV cache 量化讓騰出的 VRAM 拿去開大 <a href="/blog/llm/knowledge-cards/context-window/" data-link-title="Context Window" data-link-desc="模型一次能處理的最大 token 數量：prompt 加生成的總和上限">context window</a>。</p>
<p>在 llama.cpp 中、對應的旗標是 <code>--n-cpu-moe &lt;N&gt;</code>、把 N 層的 MoE 專家權重保留在 CPU 記憶體。例如 <code>--n-cpu-moe 30</code> 表示 30 層的專家層留 RAM、其餘走 GPU。</p>
<h2 id="可觀察訊號與例子">可觀察訊號與例子</h2>
<p>以 Qwen3-30B-A3B Q4_K_M（模型體積 10 GB 級、active parameter 約 3B 等級）為例、不同卸載策略下記憶體分布與生字速度的相對方向（具體數值依驅動、CUDA backend、模型版本、PCIe 版本變化、本表用於說明趨勢、不是嚴格 benchmark）：</p>
<table>
  <thead>
      <tr>
          <th>配置</th>
          <th>卸載策略</th>
          <th>VRAM 佔用方向</th>
          <th>RAM 佔用方向</th>
          <th>生字速度方向（同卡比較）</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>全載 VRAM</td>
          <td><code>--n-cpu-moe 0</code></td>
          <td>接近 VRAM 上限</td>
          <td>系統正常</td>
          <td>上限取決於 VRAM 頻寬</td>
      </tr>
      <tr>
          <td>中度卸載</td>
          <td><code>--n-cpu-moe ~20</code></td>
          <td>顯著下降</td>
          <td>上升至 10 GB 級</td>
          <td>較全載小幅下降</td>
      </tr>
      <tr>
          <td>重度卸載</td>
          <td><code>--n-cpu-moe ~30</code></td>
          <td>大幅下降</td>
          <td>上升較多</td>
          <td>較全載明顯下降</td>
      </tr>
      <tr>
          <td>極限卸載</td>
          <td><code>--n-cpu-moe ~40</code></td>
          <td>接近最低</td>
          <td>上升最多</td>
          <td>較全載大幅下降</td>
      </tr>
  </tbody>
</table>
<blockquote>
<p><strong>事實查核註</strong>：上表是趨勢示意、不是經本文系統實測的數值。實際數值依顯卡型號、PCIe 版本、CUDA backend、GGUF 量化版本、<code>-ngl</code> 設定、context 長度與 batch size 變化、建議用 <code>llama-bench</code> 或實際工作流校準。</p></blockquote>
<p>社群常見的觀察是：MoE 卸載對生字速度的衰減幅度、相對於「Dense 模型把同樣比例的層卸載到 CPU」較小、原因是 MoE 每 token 只啟用少數專家、PCIe 上的權重傳輸量也較少；具體幅度依模型架構（active parameter 比例、專家數）變化。</p>
<h2 id="設計責任">設計責任</h2>
<p>理解 MoE 卸載後、可以解釋三個 PC 場景的現象：16GB VRAM 卡能載入 30B 級 MoE 模型（透過部分卸載而非全載 VRAM）、PC 場景 64GB RAM 相對 32GB 在 MoE 卸載空間上明顯更寬裕（可卸載更多層）、Mac 統一記憶體場景較少需要「卸載」這個概念（VRAM 跟 RAM 共用、不需要在兩個區域之間搬資料）。</p>
<p>設定 PC 推論伺服器時、卸載層數通常跟 KV cache 量化、context 長度、併發數一起調：先估算想開的 context 長度、扣掉 KV cache 體積算出 VRAM 餘量、再選卸載層數讓模型剛好放得進。詳見 <a href="/blog/llm/05-discrete-gpu/vram-ram-budget/" data-link-title="5.0 VRAM &#43; RAM 分層預算" data-link-desc="PC 獨立 GPU 場景的記憶體預算判讀：VRAM 是快的世界、RAM 是大的世界、PCIe 把兩個世界連起來">5.0 VRAM + RAM 分層預算</a>。</p>
]]></content:encoded></item><item><title>MTEB</title><link>https://tarrragon.github.io/blog/llm/knowledge-cards/mteb-benchmark/</link><pubDate>Tue, 12 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/llm/knowledge-cards/mteb-benchmark/</guid><description>&lt;p>MTEB（Massive Text Embedding Benchmark、Muennighoff et al., 2022）的核心概念是「&lt;strong>評估 &lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/embedding-model/" data-link-title="Embedding Model" data-link-desc="把文字轉成向量的模型：用於 codebase 索引與語意搜尋">embedding model&lt;/a> 跨多種任務通用能力的標準 benchmark&lt;/strong>」。覆蓋 8 大類任務（classification、clustering、pair classification、reranking、retrieval、STS、summarization、bitext mining）、56 個 dataset、112 種語言。是現在挑選 embedding model 最常用的 leaderboard。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>MTEB 的 8 大任務類別：&lt;/p>
&lt;table>
 &lt;thead>
 &lt;tr>
 &lt;th>類別&lt;/th>
 &lt;th>任務本質&lt;/th>
 &lt;th>衡量&lt;/th>
 &lt;/tr>
 &lt;/thead>
 &lt;tbody>
 &lt;tr>
 &lt;td>Classification&lt;/td>
 &lt;td>用 embedding 做下游分類（如情感分析）&lt;/td>
 &lt;td>分類 accuracy&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>Clustering&lt;/td>
 &lt;td>把相似 doc 聚到一起&lt;/td>
 &lt;td>V-measure、NMI&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>Pair classification&lt;/td>
 &lt;td>判斷兩段文字「相關 / 不相關」&lt;/td>
 &lt;td>F1、AP&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;strong>Reranking&lt;/strong>&lt;/td>
 &lt;td>對 retrieval 結果用 embedding 重新排序&lt;/td>
 &lt;td>mAP、MRR&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;strong>Retrieval&lt;/strong>&lt;/td>
 &lt;td>給 query、從大量 corpus 找相關 doc&lt;/td>
 &lt;td>nDCG@10、&lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/retrieval-recall/" data-link-title="Retrieval Recall" data-link-desc="衡量 RAG 檢索是否把應該命中的文件或 chunk 放進 top-k 結果，是 component-level eval 的核心指標">Recall@k&lt;/a>&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>STS（Semantic Textual Similarity）&lt;/td>
 &lt;td>預測句對相似度（連續分數）&lt;/td>
 &lt;td>Spearman correlation&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>Summarization&lt;/td>
 &lt;td>embedding-based summary quality&lt;/td>
 &lt;td>Correlation with human rating&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>Bitext mining&lt;/td>
 &lt;td>跨語言找翻譯對&lt;/td>
 &lt;td>F1&lt;/td>
 &lt;/tr>
 &lt;/tbody>
&lt;/table>
&lt;p>&lt;strong>對寫 code / RAG 場景最相關&lt;/strong>：Retrieval、Reranking 兩類（粗體）。其他類別反映通用能力、但不直接影響 RAG 應用品質。&lt;/p>
&lt;p>主流 embedding model 在 MTEB Retrieval 的代表性能（2026/5 估計、會持續變動）：&lt;/p>
&lt;table>
 &lt;thead>
 &lt;tr>
 &lt;th>模型&lt;/th>
 &lt;th>模型大小&lt;/th>
 &lt;th>MTEB Retrieval avg&lt;/th>
 &lt;th>適合場景&lt;/th>
 &lt;/tr>
 &lt;/thead>
 &lt;tbody>
 &lt;tr>
 &lt;td>BAAI/bge-large-en-v1.5&lt;/td>
 &lt;td>~335M&lt;/td>
 &lt;td>~55&lt;/td>
 &lt;td>開源通用、英文 retrieval 主力&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>nomic-embed-text-v1.5&lt;/td>
 &lt;td>~137M&lt;/td>
 &lt;td>~52&lt;/td>
 &lt;td>開源、小巧、Ollama 內建&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>jina-embeddings-v3&lt;/td>
 &lt;td>~570M&lt;/td>
 &lt;td>~58&lt;/td>
 &lt;td>開源、多語、code 友善&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>mxbai-embed-large-v1&lt;/td>
 &lt;td>~335M&lt;/td>
 &lt;td>~55&lt;/td>
 &lt;td>開源通用&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>OpenAI text-embedding-3-large&lt;/td>
 &lt;td>API only&lt;/td>
 &lt;td>~64&lt;/td>
 &lt;td>雲端旗艦&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>voyage-3&lt;/td>
 &lt;td>API only&lt;/td>
 &lt;td>~62&lt;/td>
 &lt;td>雲端、Anthropic 推薦&lt;/td>
 &lt;/tr>
 &lt;/tbody>
&lt;/table>
&lt;blockquote>
&lt;p>&lt;strong>事實查核註&lt;/strong>：MTEB 數字依模型版本、評估配置變動、上述為 2026/5 大致排名、引用前以 &lt;a href="https://huggingface.co/spaces/mteb/leaderboard">MTEB Leaderboard&lt;/a> 當前狀態為準。&lt;/p>&lt;/blockquote>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>讀 embedding model 比較看到「MTEB score」就是這 benchmark。寫 code / RAG 場景的判讀：&lt;/p>
&lt;ol>
&lt;li>&lt;strong>看 Retrieval 子分數、不是 overall&lt;/strong>：MTEB overall 含 8 類、跟 RAG 場景關係最大的是 Retrieval 子分；通用 retrieval 分數高、reranking 分數高、就值得試&lt;/li>
&lt;li>&lt;strong>跟自己 domain 對齊&lt;/strong>：MTEB 多為通用語料、自己 domain（如 code、medical、legal）可能跟 MTEB 落差大；in-domain benchmark 比 MTEB 更重要&lt;/li>
&lt;li>&lt;strong>大小 / 速度 / 品質 trade-off&lt;/strong>：bge-large（335M）vs nomic-embed（137M）、後者跑得快、適合本地 RAG；前者品質略高、適合雲端或 latency 不敏感場景&lt;/li>
&lt;li>&lt;strong>MTEB 高分不代表「適合你」&lt;/strong>：高分模型可能是 instruction-tuned embedding（query 需要加特定前綴）、用法跟簡單模型不同、要看 model card&lt;/li>
&lt;/ol></description><content:encoded><![CDATA[<p>MTEB（Massive Text Embedding Benchmark、Muennighoff et al., 2022）的核心概念是「<strong>評估 <a href="/blog/llm/knowledge-cards/embedding-model/" data-link-title="Embedding Model" data-link-desc="把文字轉成向量的模型：用於 codebase 索引與語意搜尋">embedding model</a> 跨多種任務通用能力的標準 benchmark</strong>」。覆蓋 8 大類任務（classification、clustering、pair classification、reranking、retrieval、STS、summarization、bitext mining）、56 個 dataset、112 種語言。是現在挑選 embedding model 最常用的 leaderboard。</p>
<h2 id="概念位置">概念位置</h2>
<p>MTEB 的 8 大任務類別：</p>
<table>
  <thead>
      <tr>
          <th>類別</th>
          <th>任務本質</th>
          <th>衡量</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>Classification</td>
          <td>用 embedding 做下游分類（如情感分析）</td>
          <td>分類 accuracy</td>
      </tr>
      <tr>
          <td>Clustering</td>
          <td>把相似 doc 聚到一起</td>
          <td>V-measure、NMI</td>
      </tr>
      <tr>
          <td>Pair classification</td>
          <td>判斷兩段文字「相關 / 不相關」</td>
          <td>F1、AP</td>
      </tr>
      <tr>
          <td><strong>Reranking</strong></td>
          <td>對 retrieval 結果用 embedding 重新排序</td>
          <td>mAP、MRR</td>
      </tr>
      <tr>
          <td><strong>Retrieval</strong></td>
          <td>給 query、從大量 corpus 找相關 doc</td>
          <td>nDCG@10、<a href="/blog/llm/knowledge-cards/retrieval-recall/" data-link-title="Retrieval Recall" data-link-desc="衡量 RAG 檢索是否把應該命中的文件或 chunk 放進 top-k 結果，是 component-level eval 的核心指標">Recall@k</a></td>
      </tr>
      <tr>
          <td>STS（Semantic Textual Similarity）</td>
          <td>預測句對相似度（連續分數）</td>
          <td>Spearman correlation</td>
      </tr>
      <tr>
          <td>Summarization</td>
          <td>embedding-based summary quality</td>
          <td>Correlation with human rating</td>
      </tr>
      <tr>
          <td>Bitext mining</td>
          <td>跨語言找翻譯對</td>
          <td>F1</td>
      </tr>
  </tbody>
</table>
<p><strong>對寫 code / RAG 場景最相關</strong>：Retrieval、Reranking 兩類（粗體）。其他類別反映通用能力、但不直接影響 RAG 應用品質。</p>
<p>主流 embedding model 在 MTEB Retrieval 的代表性能（2026/5 估計、會持續變動）：</p>
<table>
  <thead>
      <tr>
          <th>模型</th>
          <th>模型大小</th>
          <th>MTEB Retrieval avg</th>
          <th>適合場景</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>BAAI/bge-large-en-v1.5</td>
          <td>~335M</td>
          <td>~55</td>
          <td>開源通用、英文 retrieval 主力</td>
      </tr>
      <tr>
          <td>nomic-embed-text-v1.5</td>
          <td>~137M</td>
          <td>~52</td>
          <td>開源、小巧、Ollama 內建</td>
      </tr>
      <tr>
          <td>jina-embeddings-v3</td>
          <td>~570M</td>
          <td>~58</td>
          <td>開源、多語、code 友善</td>
      </tr>
      <tr>
          <td>mxbai-embed-large-v1</td>
          <td>~335M</td>
          <td>~55</td>
          <td>開源通用</td>
      </tr>
      <tr>
          <td>OpenAI text-embedding-3-large</td>
          <td>API only</td>
          <td>~64</td>
          <td>雲端旗艦</td>
      </tr>
      <tr>
          <td>voyage-3</td>
          <td>API only</td>
          <td>~62</td>
          <td>雲端、Anthropic 推薦</td>
      </tr>
  </tbody>
</table>
<blockquote>
<p><strong>事實查核註</strong>：MTEB 數字依模型版本、評估配置變動、上述為 2026/5 大致排名、引用前以 <a href="https://huggingface.co/spaces/mteb/leaderboard">MTEB Leaderboard</a> 當前狀態為準。</p></blockquote>
<h2 id="設計責任">設計責任</h2>
<p>讀 embedding model 比較看到「MTEB score」就是這 benchmark。寫 code / RAG 場景的判讀：</p>
<ol>
<li><strong>看 Retrieval 子分數、不是 overall</strong>：MTEB overall 含 8 類、跟 RAG 場景關係最大的是 Retrieval 子分；通用 retrieval 分數高、reranking 分數高、就值得試</li>
<li><strong>跟自己 domain 對齊</strong>：MTEB 多為通用語料、自己 domain（如 code、medical、legal）可能跟 MTEB 落差大；in-domain benchmark 比 MTEB 更重要</li>
<li><strong>大小 / 速度 / 品質 trade-off</strong>：bge-large（335M）vs nomic-embed（137M）、後者跑得快、適合本地 RAG；前者品質略高、適合雲端或 latency 不敏感場景</li>
<li><strong>MTEB 高分不代表「適合你」</strong>：高分模型可能是 instruction-tuned embedding（query 需要加特定前綴）、用法跟簡單模型不同、要看 model card</li>
</ol>
]]></content:encoded></item><item><title>Multi-Head Attention</title><link>https://tarrragon.github.io/blog/llm/knowledge-cards/multi-head-attention/</link><pubDate>Tue, 12 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/llm/knowledge-cards/multi-head-attention/</guid><description>&lt;p>Multi-Head Attention（MHA、多頭注意力）的核心概念是「把 &lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/self-attention/" data-link-title="Self-Attention" data-link-desc="Q / K / V 都從同一個 sequence 投影出來的 attention、Transformer 的標誌性設計">self-attention&lt;/a> 的 Q/K/V 投影切成多個獨立的 &lt;strong>head&lt;/strong>、各自算 attention、最後再 concat 起來」。直覺：每個 head 可以學會關注不同類型的關係（語法 / 語意 / 位置 / 共指 etc.）、比單一 attention 表達能力強。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>MHA 的計算結構：&lt;/p>





&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-text" data-lang="text">&lt;span class="line">&lt;span class="ln">1&lt;/span>&lt;span class="cl">輸入 hidden state（dim = 4096）
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">2&lt;/span>&lt;span class="cl"> ↓ 投影成 Q/K/V、每個切成 h 個 head（如 h=32、每個 head 128 維）
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">3&lt;/span>&lt;span class="cl">Head 1：Q_1、K_1、V_1 → attention_1（128 維）
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">4&lt;/span>&lt;span class="cl">Head 2：Q_2、K_2、V_2 → attention_2
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">5&lt;/span>&lt;span class="cl">...
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">6&lt;/span>&lt;span class="cl">Head h：Q_h、K_h、V_h → attention_h
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">7&lt;/span>&lt;span class="cl"> ↓ concat 所有 head 輸出（h × 128 = 4096）
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">8&lt;/span>&lt;span class="cl"> ↓ output projection（4096 → 4096）
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">9&lt;/span>&lt;span class="cl">最終輸出&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>多頭變體：MHA → GQA → MLA 是 KV cache 體積壓縮的演化方向。&lt;/p>
&lt;table>
 &lt;thead>
 &lt;tr>
 &lt;th>變體&lt;/th>
 &lt;th>Q head 數&lt;/th>
 &lt;th>K/V head 數&lt;/th>
 &lt;th>KV cache 體積&lt;/th>
 &lt;th>出現在&lt;/th>
 &lt;/tr>
 &lt;/thead>
 &lt;tbody>
 &lt;tr>
 &lt;td>MHA（Multi-Head Attention）&lt;/td>
 &lt;td>h&lt;/td>
 &lt;td>h&lt;/td>
 &lt;td>100%（基準）&lt;/td>
 &lt;td>原始 Transformer、GPT-3、Llama 1&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>MQA（Multi-Query Attention）&lt;/td>
 &lt;td>h&lt;/td>
 &lt;td>1（所有 head 共用）&lt;/td>
 &lt;td>1/h&lt;/td>
 &lt;td>PaLM、Falcon&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>GQA（Grouped-Query Attention）&lt;/td>
 &lt;td>h&lt;/td>
 &lt;td>h/g（每 g 個 Q head 共用一組 K/V）&lt;/td>
 &lt;td>1/g&lt;/td>
 &lt;td>Llama 2 / 3、Mistral、Gemma&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>MLA（Multi-head Latent Attention）&lt;/td>
 &lt;td>h&lt;/td>
 &lt;td>用 latent 壓縮再展開&lt;/td>
 &lt;td>更激進壓縮&lt;/td>
 &lt;td>DeepSeek-V2 / V3&lt;/td>
 &lt;/tr>
 &lt;/tbody>
&lt;/table>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>讀 model card 看到 &lt;code>num_attention_heads: 32&lt;/code>、&lt;code>num_key_value_heads: 8&lt;/code> 等就是 MHA / GQA 設定（Q=32、K/V=8 表示 GQA、g=4）。寫 code 場景的意涵：GQA / MLA 的 &lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/kv-cache/" data-link-title="KV Cache" data-link-desc="已處理 token 的 attention 中間結果暫存：避免重算、加速後續生成">KV cache&lt;/a> 體積小、長 context / 高併發場景更友善、是現代 LLM 大量採用的設計。&lt;/p></description><content:encoded><![CDATA[<p>Multi-Head Attention（MHA、多頭注意力）的核心概念是「把 <a href="/blog/llm/knowledge-cards/self-attention/" data-link-title="Self-Attention" data-link-desc="Q / K / V 都從同一個 sequence 投影出來的 attention、Transformer 的標誌性設計">self-attention</a> 的 Q/K/V 投影切成多個獨立的 <strong>head</strong>、各自算 attention、最後再 concat 起來」。直覺：每個 head 可以學會關注不同類型的關係（語法 / 語意 / 位置 / 共指 etc.）、比單一 attention 表達能力強。</p>
<h2 id="概念位置">概念位置</h2>
<p>MHA 的計算結構：</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="ln">1</span><span class="cl">輸入 hidden state（dim = 4096）
</span></span><span class="line"><span class="ln">2</span><span class="cl">   ↓ 投影成 Q/K/V、每個切成 h 個 head（如 h=32、每個 head 128 維）
</span></span><span class="line"><span class="ln">3</span><span class="cl">Head 1：Q_1、K_1、V_1 → attention_1（128 維）
</span></span><span class="line"><span class="ln">4</span><span class="cl">Head 2：Q_2、K_2、V_2 → attention_2
</span></span><span class="line"><span class="ln">5</span><span class="cl">...
</span></span><span class="line"><span class="ln">6</span><span class="cl">Head h：Q_h、K_h、V_h → attention_h
</span></span><span class="line"><span class="ln">7</span><span class="cl">   ↓ concat 所有 head 輸出（h × 128 = 4096）
</span></span><span class="line"><span class="ln">8</span><span class="cl">   ↓ output projection（4096 → 4096）
</span></span><span class="line"><span class="ln">9</span><span class="cl">最終輸出</span></span></code></pre></div><p>多頭變體：MHA → GQA → MLA 是 KV cache 體積壓縮的演化方向。</p>
<table>
  <thead>
      <tr>
          <th>變體</th>
          <th>Q head 數</th>
          <th>K/V head 數</th>
          <th>KV cache 體積</th>
          <th>出現在</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>MHA（Multi-Head Attention）</td>
          <td>h</td>
          <td>h</td>
          <td>100%（基準）</td>
          <td>原始 Transformer、GPT-3、Llama 1</td>
      </tr>
      <tr>
          <td>MQA（Multi-Query Attention）</td>
          <td>h</td>
          <td>1（所有 head 共用）</td>
          <td>1/h</td>
          <td>PaLM、Falcon</td>
      </tr>
      <tr>
          <td>GQA（Grouped-Query Attention）</td>
          <td>h</td>
          <td>h/g（每 g 個 Q head 共用一組 K/V）</td>
          <td>1/g</td>
          <td>Llama 2 / 3、Mistral、Gemma</td>
      </tr>
      <tr>
          <td>MLA（Multi-head Latent Attention）</td>
          <td>h</td>
          <td>用 latent 壓縮再展開</td>
          <td>更激進壓縮</td>
          <td>DeepSeek-V2 / V3</td>
      </tr>
  </tbody>
</table>
<h2 id="設計責任">設計責任</h2>
<p>讀 model card 看到 <code>num_attention_heads: 32</code>、<code>num_key_value_heads: 8</code> 等就是 MHA / GQA 設定（Q=32、K/V=8 表示 GQA、g=4）。寫 code 場景的意涵：GQA / MLA 的 <a href="/blog/llm/knowledge-cards/kv-cache/" data-link-title="KV Cache" data-link-desc="已處理 token 的 attention 中間結果暫存：避免重算、加速後續生成">KV cache</a> 體積小、長 context / 高併發場景更友善、是現代 LLM 大量採用的設計。</p>
]]></content:encoded></item><item><title>Multimodal Fusion</title><link>https://tarrragon.github.io/blog/llm/knowledge-cards/multimodal-fusion/</link><pubDate>Tue, 12 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/llm/knowledge-cards/multimodal-fusion/</guid><description>&lt;p>Multimodal fusion（多模態融合）的核心概念是「&lt;strong>&lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/vlm/" data-link-title="VLM（Vision-Language Model）" data-link-desc="同時吃圖片 &amp;#43; 文字輸入、產生文字輸出的 LLM 變體、coding 工作流中處理截圖 / 設計稿 / UI debug 的基底">VLM&lt;/a> 把 vision encoder 產出的 &lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/image-token/" data-link-title="Image Token" data-link-desc="VLM 把圖片轉成「對 Transformer 而言跟 text token 同質」的向量、計入 context window 預算">image token&lt;/a> 跟 text token 結合進 LLM 的設計方式&lt;/strong>」。三條主流路線：early fusion（image token 跟 text token 串成同 sequence）、cross-attention（separate stream、attention 跨流）、native multimodal（單一網路統一處理）。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>三種 fusion 方式的對比：&lt;/p>
&lt;h3 id="1-early-fusion最主流">1. Early Fusion（最主流）&lt;/h3>





&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-text" data-lang="text">&lt;span class="line">&lt;span class="ln">1&lt;/span>&lt;span class="cl">image → vision encoder → image tokens ─┐
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">2&lt;/span>&lt;span class="cl"> ├→ concat 成單一 sequence → 同 LLM Transformer 處理
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">3&lt;/span>&lt;span class="cl">text → tokenizer → text tokens ────────┘&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;ul>
&lt;li>&lt;strong>特性&lt;/strong>：image token 跟 text token 在同一個 token sequence、共用 LLM 的 attention / FFN&lt;/li>
&lt;li>&lt;strong>代表&lt;/strong>：LLaVA、Qwen2-VL、Llama 3.2 Vision、Pixtral、GPT-4V 多數變體&lt;/li>
&lt;li>&lt;strong>優點&lt;/strong>：實作簡單、可重用 LLM 的 weight、訓練資料效率高&lt;/li>
&lt;li>&lt;strong>缺點&lt;/strong>：image token 佔 context、長對話 / 多圖時 context budget 吃緊&lt;/li>
&lt;/ul>
&lt;h3 id="2-cross-attentionflamingo-style">2. Cross-Attention（Flamingo-style）&lt;/h3>





&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-text" data-lang="text">&lt;span class="line">&lt;span class="ln">1&lt;/span>&lt;span class="cl">image → vision encoder → image features ─┐
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">2&lt;/span>&lt;span class="cl"> │ Cross-attention 層
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">3&lt;/span>&lt;span class="cl">text → tokenizer → tokens → LLM Transformer ──┤ 插在每幾層 Transformer 之間
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">4&lt;/span>&lt;span class="cl"> │ Image features 不進 LLM 主流
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">5&lt;/span>&lt;span class="cl">output ←─────────────────────────────────┘&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;ul>
&lt;li>&lt;strong>特性&lt;/strong>：image features 不變成 LLM 的 token、透過額外的 cross-attention 層注入&lt;/li>
&lt;li>&lt;strong>代表&lt;/strong>：Flamingo（DeepMind）、Idefics（Hugging Face）、部分 video LLM&lt;/li>
&lt;li>&lt;strong>優點&lt;/strong>：text token sequence 不會被 image 撐大、長文字 + 多圖比較友善&lt;/li>
&lt;li>&lt;strong>缺點&lt;/strong>：架構複雜、訓練難、推論伺服器支援度差&lt;/li>
&lt;/ul>
&lt;h3 id="3-native-multimodalunified-token-space">3. Native Multimodal（unified token space）&lt;/h3>





&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-text" data-lang="text">&lt;span class="line">&lt;span class="ln">1&lt;/span>&lt;span class="cl">image → patchify → discrete image tokens（如 VQ-VAE 編碼）
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">2&lt;/span>&lt;span class="cl">text → tokenizer → text tokens
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">3&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">4&lt;/span>&lt;span class="cl">兩者共用 vocab、同一個 Transformer 從頭訓
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">5&lt;/span>&lt;span class="cl">（沒有「分開的 vision encoder」、modality 在 vocab level 統一）&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;ul>
&lt;li>&lt;strong>特性&lt;/strong>：架構上「圖跟文字是同一種東西」、共用 vocab&lt;/li>
&lt;li>&lt;strong>代表&lt;/strong>：Chameleon（Meta 研究）、未來 trend&lt;/li>
&lt;li>&lt;strong>優點&lt;/strong>：理論最 clean、跨模態 generation 自然（生圖 + 生文都同個模型）&lt;/li>
&lt;li>&lt;strong>缺點&lt;/strong>：訓練極貴、目前研究階段為主、實用 VLM 仍以 early fusion 為主流&lt;/li>
&lt;/ul>
&lt;h2 id="主流選擇對比">主流選擇對比&lt;/h2>
&lt;table>
 &lt;thead>
 &lt;tr>
 &lt;th>路線&lt;/th>
 &lt;th>佔比（2026/5）&lt;/th>
 &lt;th>對 coding 場景的影響&lt;/th>
 &lt;/tr>
 &lt;/thead>
 &lt;tbody>
 &lt;tr>
 &lt;td>Early fusion&lt;/td>
 &lt;td>~85%&lt;/td>
 &lt;td>Image token 佔 context、要算清楚 context budget&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>Cross-attention&lt;/td>
 &lt;td>~10%&lt;/td>
 &lt;td>推論伺服器支援度差、本地跑選項少&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>Native multimodal&lt;/td>
 &lt;td>&amp;lt; 5%&lt;/td>
 &lt;td>研究階段、現在不適合 production / 本地工作流&lt;/td>
 &lt;/tr>
 &lt;/tbody>
&lt;/table>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>讀 VLM paper / blog 看到「early fusion」「LLaVA-style」「Flamingo-style」「cross-attention adapter」就是這分類。寫 code 場景的判讀：&lt;/p></description><content:encoded><![CDATA[<p>Multimodal fusion（多模態融合）的核心概念是「<strong><a href="/blog/llm/knowledge-cards/vlm/" data-link-title="VLM（Vision-Language Model）" data-link-desc="同時吃圖片 &#43; 文字輸入、產生文字輸出的 LLM 變體、coding 工作流中處理截圖 / 設計稿 / UI debug 的基底">VLM</a> 把 vision encoder 產出的 <a href="/blog/llm/knowledge-cards/image-token/" data-link-title="Image Token" data-link-desc="VLM 把圖片轉成「對 Transformer 而言跟 text token 同質」的向量、計入 context window 預算">image token</a> 跟 text token 結合進 LLM 的設計方式</strong>」。三條主流路線：early fusion（image token 跟 text token 串成同 sequence）、cross-attention（separate stream、attention 跨流）、native multimodal（單一網路統一處理）。</p>
<h2 id="概念位置">概念位置</h2>
<p>三種 fusion 方式的對比：</p>
<h3 id="1-early-fusion最主流">1. Early Fusion（最主流）</h3>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="ln">1</span><span class="cl">image → vision encoder → image tokens ─┐
</span></span><span class="line"><span class="ln">2</span><span class="cl">                                       ├→ concat 成單一 sequence → 同 LLM Transformer 處理
</span></span><span class="line"><span class="ln">3</span><span class="cl">text → tokenizer → text tokens ────────┘</span></span></code></pre></div><ul>
<li><strong>特性</strong>：image token 跟 text token 在同一個 token sequence、共用 LLM 的 attention / FFN</li>
<li><strong>代表</strong>：LLaVA、Qwen2-VL、Llama 3.2 Vision、Pixtral、GPT-4V 多數變體</li>
<li><strong>優點</strong>：實作簡單、可重用 LLM 的 weight、訓練資料效率高</li>
<li><strong>缺點</strong>：image token 佔 context、長對話 / 多圖時 context budget 吃緊</li>
</ul>
<h3 id="2-cross-attentionflamingo-style">2. Cross-Attention（Flamingo-style）</h3>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="ln">1</span><span class="cl">image → vision encoder → image features ─┐
</span></span><span class="line"><span class="ln">2</span><span class="cl">                                          │ Cross-attention 層
</span></span><span class="line"><span class="ln">3</span><span class="cl">text → tokenizer → tokens → LLM Transformer ──┤  插在每幾層 Transformer 之間
</span></span><span class="line"><span class="ln">4</span><span class="cl">                                          │ Image features 不進 LLM 主流
</span></span><span class="line"><span class="ln">5</span><span class="cl">output ←─────────────────────────────────┘</span></span></code></pre></div><ul>
<li><strong>特性</strong>：image features 不變成 LLM 的 token、透過額外的 cross-attention 層注入</li>
<li><strong>代表</strong>：Flamingo（DeepMind）、Idefics（Hugging Face）、部分 video LLM</li>
<li><strong>優點</strong>：text token sequence 不會被 image 撐大、長文字 + 多圖比較友善</li>
<li><strong>缺點</strong>：架構複雜、訓練難、推論伺服器支援度差</li>
</ul>
<h3 id="3-native-multimodalunified-token-space">3. Native Multimodal（unified token space）</h3>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="ln">1</span><span class="cl">image → patchify → discrete image tokens（如 VQ-VAE 編碼）
</span></span><span class="line"><span class="ln">2</span><span class="cl">text → tokenizer → text tokens
</span></span><span class="line"><span class="ln">3</span><span class="cl">
</span></span><span class="line"><span class="ln">4</span><span class="cl">兩者共用 vocab、同一個 Transformer 從頭訓
</span></span><span class="line"><span class="ln">5</span><span class="cl">（沒有「分開的 vision encoder」、modality 在 vocab level 統一）</span></span></code></pre></div><ul>
<li><strong>特性</strong>：架構上「圖跟文字是同一種東西」、共用 vocab</li>
<li><strong>代表</strong>：Chameleon（Meta 研究）、未來 trend</li>
<li><strong>優點</strong>：理論最 clean、跨模態 generation 自然（生圖 + 生文都同個模型）</li>
<li><strong>缺點</strong>：訓練極貴、目前研究階段為主、實用 VLM 仍以 early fusion 為主流</li>
</ul>
<h2 id="主流選擇對比">主流選擇對比</h2>
<table>
  <thead>
      <tr>
          <th>路線</th>
          <th>佔比（2026/5）</th>
          <th>對 coding 場景的影響</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>Early fusion</td>
          <td>~85%</td>
          <td>Image token 佔 context、要算清楚 context budget</td>
      </tr>
      <tr>
          <td>Cross-attention</td>
          <td>~10%</td>
          <td>推論伺服器支援度差、本地跑選項少</td>
      </tr>
      <tr>
          <td>Native multimodal</td>
          <td>&lt; 5%</td>
          <td>研究階段、現在不適合 production / 本地工作流</td>
      </tr>
  </tbody>
</table>
<h2 id="設計責任">設計責任</h2>
<p>讀 VLM paper / blog 看到「early fusion」「LLaVA-style」「Flamingo-style」「cross-attention adapter」就是這分類。寫 code 場景的判讀：</p>
<ol>
<li><strong>本地跑 VLM 多半是 early fusion</strong>：選 Qwen2.5-VL / Llama 3.2 Vision / Gemma 3 Vision 都是這條路線、推論伺服器（llama.cpp、Ollama、LM Studio）都支援</li>
<li><strong>Cross-attention 模型本地跑可能撞牆</strong>：推論伺服器對 Idefics 等 cross-attention 模型支援度差、不一定能跑 GGUF</li>
<li><strong>理解 fusion 影響 token 估算</strong>：early fusion 下「image token = 真的進 context」、cross-attention 下不算進 context window 主流</li>
<li><strong>未來 trend 是 unified</strong>：但現在做 production / 本地工作流不必等、用 early fusion 主流模型即可</li>
</ol>
]]></content:encoded></item><item><title>Needle in a Haystack</title><link>https://tarrragon.github.io/blog/llm/knowledge-cards/needle-in-haystack/</link><pubDate>Tue, 12 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/llm/knowledge-cards/needle-in-haystack/</guid><description>&lt;p>Needle in a Haystack（NIH、大海撈針、Greg Kamradt 2023）的核心概念是「&lt;strong>把一個明確事實（needle）插入長度可變的 context（haystack）的不同位置、測試 LLM 能否在問問題時準確 recall 該事實&lt;/strong>」。是評估 &lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/context-window/" data-link-title="Context Window" data-link-desc="模型一次能處理的最大 token 數量：prompt 加生成的總和上限">long context&lt;/a> 模型實用性的標準 benchmark 之一、跟 &lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/lost-in-the-middle/" data-link-title="Lost in the Middle" data-link-desc="LLM 對 long context 中段內容的 attention / recall 顯著低於開頭與結尾的現象">lost-in-the-middle&lt;/a> 對應但側重不同。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>NIH 測試的典型流程：&lt;/p>





&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-text" data-lang="text">&lt;span class="line">&lt;span class="ln"> 1&lt;/span>&lt;span class="cl">1. 準備 haystack：一份長文（如 Paul Graham essays、技術文件）
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 2&lt;/span>&lt;span class="cl">2. 在指定位置（如 50% 處）插入 needle：
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 3&lt;/span>&lt;span class="cl"> 「The best thing to do in San Francisco is eat a sandwich at Dolores Park.」
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 4&lt;/span>&lt;span class="cl">3. Prompt 模型：「What is the best thing to do in San Francisco?」
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 5&lt;/span>&lt;span class="cl">4. 看模型能否抓出 needle 內容
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 6&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 7&lt;/span>&lt;span class="cl">Variables：
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 8&lt;/span>&lt;span class="cl">- Context 總長度（1K、4K、16K、64K、128K、1M）
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 9&lt;/span>&lt;span class="cl">- Needle 插入位置（0%、10%、25%、50%、75%、90%、100%）
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">10&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">11&lt;/span>&lt;span class="cl">每個 (length, position) 組合測 N 次、得到 accuracy heatmap&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>跟 lost-in-the-middle 的對比：&lt;/p>
&lt;table>
 &lt;thead>
 &lt;tr>
 &lt;th>維度&lt;/th>
 &lt;th>Lost in the middle&lt;/th>
 &lt;th>Needle in haystack&lt;/th>
 &lt;/tr>
 &lt;/thead>
 &lt;tbody>
 &lt;tr>
 &lt;td>衡量的能力&lt;/td>
 &lt;td>對中段內容的整體 attention&lt;/td>
 &lt;td>抓單一事實的 recall&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>任務&lt;/td>
 &lt;td>抓整段邏輯、做推論&lt;/td>
 &lt;td>純 retrieve、不需推論&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>難度&lt;/td>
 &lt;td>高（需理解整段語意）&lt;/td>
 &lt;td>較低（明確 keyword 匹配）&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>模型表現&lt;/td>
 &lt;td>中段顯著差&lt;/td>
 &lt;td>通常各位置都接近 100%（強模型）&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>判讀意義&lt;/td>
 &lt;td>反映「實用 effective context」&lt;/td>
 &lt;td>反映「lower bound effective context」&lt;/td>
 &lt;/tr>
 &lt;/tbody>
&lt;/table>





&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-text" data-lang="text">&lt;span class="line">&lt;span class="ln"> 1&lt;/span>&lt;span class="cl">典型 NIH heatmap（GPT-4 128K 之類）：
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 2&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 3&lt;/span>&lt;span class="cl">100% |████ ████████████████████████████ ████
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 4&lt;/span>&lt;span class="cl"> 80% |████ ████████████████████████████ ████
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 5&lt;/span>&lt;span class="cl"> 60% |
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 6&lt;/span>&lt;span class="cl"> 40% |
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 7&lt;/span>&lt;span class="cl"> 20% |
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 8&lt;/span>&lt;span class="cl"> 0 +----+----+----+----+----+----+----+
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 9&lt;/span>&lt;span class="cl"> 0% 25% 50% 75% 100%（needle 位置）
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">10&lt;/span>&lt;span class="cl"> ↑ ↑
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">11&lt;/span>&lt;span class="cl"> 開頭強 結尾強
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">12&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">13&lt;/span>&lt;span class="cl">NIH heatmap 通常全綠（強模型）、但實用任務（reasoning over long context）就會出現中段塌陷&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>讀 long context 模型 release notes 看到「needle in a haystack: 100%」「pass NIH up to 128K」等聲稱、要區分：&lt;/p></description><content:encoded><![CDATA[<p>Needle in a Haystack（NIH、大海撈針、Greg Kamradt 2023）的核心概念是「<strong>把一個明確事實（needle）插入長度可變的 context（haystack）的不同位置、測試 LLM 能否在問問題時準確 recall 該事實</strong>」。是評估 <a href="/blog/llm/knowledge-cards/context-window/" data-link-title="Context Window" data-link-desc="模型一次能處理的最大 token 數量：prompt 加生成的總和上限">long context</a> 模型實用性的標準 benchmark 之一、跟 <a href="/blog/llm/knowledge-cards/lost-in-the-middle/" data-link-title="Lost in the Middle" data-link-desc="LLM 對 long context 中段內容的 attention / recall 顯著低於開頭與結尾的現象">lost-in-the-middle</a> 對應但側重不同。</p>
<h2 id="概念位置">概念位置</h2>
<p>NIH 測試的典型流程：</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="ln"> 1</span><span class="cl">1. 準備 haystack：一份長文（如 Paul Graham essays、技術文件）
</span></span><span class="line"><span class="ln"> 2</span><span class="cl">2. 在指定位置（如 50% 處）插入 needle：
</span></span><span class="line"><span class="ln"> 3</span><span class="cl">   「The best thing to do in San Francisco is eat a sandwich at Dolores Park.」
</span></span><span class="line"><span class="ln"> 4</span><span class="cl">3. Prompt 模型：「What is the best thing to do in San Francisco?」
</span></span><span class="line"><span class="ln"> 5</span><span class="cl">4. 看模型能否抓出 needle 內容
</span></span><span class="line"><span class="ln"> 6</span><span class="cl">
</span></span><span class="line"><span class="ln"> 7</span><span class="cl">Variables：
</span></span><span class="line"><span class="ln"> 8</span><span class="cl">- Context 總長度（1K、4K、16K、64K、128K、1M）
</span></span><span class="line"><span class="ln"> 9</span><span class="cl">- Needle 插入位置（0%、10%、25%、50%、75%、90%、100%）
</span></span><span class="line"><span class="ln">10</span><span class="cl">
</span></span><span class="line"><span class="ln">11</span><span class="cl">每個 (length, position) 組合測 N 次、得到 accuracy heatmap</span></span></code></pre></div><p>跟 lost-in-the-middle 的對比：</p>
<table>
  <thead>
      <tr>
          <th>維度</th>
          <th>Lost in the middle</th>
          <th>Needle in haystack</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>衡量的能力</td>
          <td>對中段內容的整體 attention</td>
          <td>抓單一事實的 recall</td>
      </tr>
      <tr>
          <td>任務</td>
          <td>抓整段邏輯、做推論</td>
          <td>純 retrieve、不需推論</td>
      </tr>
      <tr>
          <td>難度</td>
          <td>高（需理解整段語意）</td>
          <td>較低（明確 keyword 匹配）</td>
      </tr>
      <tr>
          <td>模型表現</td>
          <td>中段顯著差</td>
          <td>通常各位置都接近 100%（強模型）</td>
      </tr>
      <tr>
          <td>判讀意義</td>
          <td>反映「實用 effective context」</td>
          <td>反映「lower bound effective context」</td>
      </tr>
  </tbody>
</table>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="ln"> 1</span><span class="cl">典型 NIH heatmap（GPT-4 128K 之類）：
</span></span><span class="line"><span class="ln"> 2</span><span class="cl">
</span></span><span class="line"><span class="ln"> 3</span><span class="cl">100% |████ ████████████████████████████ ████
</span></span><span class="line"><span class="ln"> 4</span><span class="cl"> 80% |████ ████████████████████████████ ████
</span></span><span class="line"><span class="ln"> 5</span><span class="cl"> 60% |
</span></span><span class="line"><span class="ln"> 6</span><span class="cl"> 40% |
</span></span><span class="line"><span class="ln"> 7</span><span class="cl"> 20% |
</span></span><span class="line"><span class="ln"> 8</span><span class="cl">   0 +----+----+----+----+----+----+----+
</span></span><span class="line"><span class="ln"> 9</span><span class="cl">     0%   25%   50%   75%   100%（needle 位置）
</span></span><span class="line"><span class="ln">10</span><span class="cl">     ↑                                  ↑
</span></span><span class="line"><span class="ln">11</span><span class="cl">     開頭強                             結尾強
</span></span><span class="line"><span class="ln">12</span><span class="cl">
</span></span><span class="line"><span class="ln">13</span><span class="cl">NIH heatmap 通常全綠（強模型）、但實用任務（reasoning over long context）就會出現中段塌陷</span></span></code></pre></div><h2 id="設計責任">設計責任</h2>
<p>讀 long context 模型 release notes 看到「needle in a haystack: 100%」「pass NIH up to 128K」等聲稱、要區分：</p>
<ol>
<li><strong>NIH 100% 不代表「能用 128K context」</strong>：NIH 只測單一事實 retrieve、實際 reasoning over long context 仍可能崩</li>
<li><strong>真實任務 benchmark</strong>：<a href="https://github.com/THUDM/LongBench">LongBench</a>、<a href="https://github.com/hsiehjackson/RULER">RULER</a> 等是更貼近實用的 long context evaluation、會暴露 lost-in-the-middle 等問題</li>
<li><strong>本地跑 long context 模型</strong>：先用 NIH 驗證 baseline、再用 RULER / 自己工作流 case 測 effective context</li>
<li><strong>判讀「我的模型實際能用幾 K」</strong>：NIH pass 的長度是上限、實用 effective context 通常是 NIH pass 長度的 1/2 到 1/4</li>
</ol>
]]></content:encoded></item><item><title>NVLink</title><link>https://tarrragon.github.io/blog/llm/knowledge-cards/nvlink/</link><pubDate>Tue, 12 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/llm/knowledge-cards/nvlink/</guid><description>&lt;p>NVLink 的核心概念是「NVIDIA 自家的 GPU 之間高速互連介面、頻寬高於 &lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/pcie/" data-link-title="PCIe" data-link-desc="PC 上連接 GPU 跟主機板的高速序列匯流排、影響模型載入速度跟 MoE 卸載時的推論吞吐">PCIe&lt;/a>、適合多卡 tensor parallel 場景」。資料中心級 GPU（如 A100 / H100 / H200）普遍支援、消費級 RTX 30 系列部分支援（如 3090）、RTX 40 / 50 系列普遍移除 NVLink、消費級多卡通常只能走 PCIe。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>NVLink 在多卡推論場景的角色：&lt;/p>
&lt;ol>
&lt;li>&lt;strong>tensor parallel&lt;/strong>：把一個 transformer 層的 weight 切到多張卡、每 token 計算時需要卡間同步、卡間頻寬影響直接。&lt;/li>
&lt;li>&lt;strong>pipeline parallel&lt;/strong>：把不同層分到不同卡、卡間需要傳 activation、頻寬要求中等。&lt;/li>
&lt;li>&lt;strong>資料分發&lt;/strong>：把不同 request 分到不同卡（data parallel）、卡間流量低、PCIe 也夠。&lt;/li>
&lt;/ol>
&lt;p>頻寬對照（廠商標稱、依世代變化）：&lt;/p>
&lt;table>
 &lt;thead>
 &lt;tr>
 &lt;th>介面&lt;/th>
 &lt;th>卡間頻寬（標稱）&lt;/th>
 &lt;/tr>
 &lt;/thead>
 &lt;tbody>
 &lt;tr>
 &lt;td>PCIe 4.0 x16&lt;/td>
 &lt;td>約 32 GB/s 單向&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>PCIe 5.0 x16&lt;/td>
 &lt;td>約 64 GB/s 單向&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>NVLink（H100）&lt;/td>
 &lt;td>約 900 GB/s 雙向、依世代&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>NVLink（A100）&lt;/td>
 &lt;td>約 600 GB/s 雙向&lt;/td>
 &lt;/tr>
 &lt;/tbody>
&lt;/table>
&lt;p>NVLink 比 PCIe 高一個量級、是資料中心多卡推論的關鍵；消費級 RTX 場景多卡通常只能走 PCIe、縮放效益相對受限。&lt;/p>
&lt;blockquote>
&lt;p>&lt;strong>事實查核註&lt;/strong>：NVLink 各世代的頻寬數字依 NVIDIA 官方規格、不同 GPU 跟世代有差異；NVLink 在哪些消費級 / 工作站 / 資料中心 GPU 可用、依時段跟廠商策略變化、引用前以 &lt;a href="https://www.nvidia.com/">NVIDIA 官方產品頁&lt;/a> 跟對應 GPU 的 datasheet 為準。&lt;/p>&lt;/blockquote>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>理解 NVLink 後可以解釋兩個現象：為什麼資料中心多卡 LLM 推論能線性 scale（NVLink 頻寬足以做 tensor parallel）、為什麼消費級雙卡 RTX 推論縮放比通常低於線性（沒 NVLink、走 PCIe x4 / x8、卡間頻寬限制）。&lt;/p>
&lt;p>選消費級 GPU 跑本地 LLM 時、NVLink 不是常見選項；多卡升級的判讀應該基於「能否容忍縮放比低於線性」、而不是預期 NVLink 等級的卡間頻寬。詳見 &lt;a href="https://tarrragon.github.io/blog/llm/05-discrete-gpu/gpu-vendor-differences/" data-link-title="5.6 GPU 廠商差異" data-link-desc="NVIDIA CUDA、AMD ROCm、Intel ARC 在 llama.cpp 生態的相對位置、選卡時的判讀軸">5.6 GPU 廠商差異&lt;/a>。&lt;/p></description><content:encoded><![CDATA[<p>NVLink 的核心概念是「NVIDIA 自家的 GPU 之間高速互連介面、頻寬高於 <a href="/blog/llm/knowledge-cards/pcie/" data-link-title="PCIe" data-link-desc="PC 上連接 GPU 跟主機板的高速序列匯流排、影響模型載入速度跟 MoE 卸載時的推論吞吐">PCIe</a>、適合多卡 tensor parallel 場景」。資料中心級 GPU（如 A100 / H100 / H200）普遍支援、消費級 RTX 30 系列部分支援（如 3090）、RTX 40 / 50 系列普遍移除 NVLink、消費級多卡通常只能走 PCIe。</p>
<h2 id="概念位置">概念位置</h2>
<p>NVLink 在多卡推論場景的角色：</p>
<ol>
<li><strong>tensor parallel</strong>：把一個 transformer 層的 weight 切到多張卡、每 token 計算時需要卡間同步、卡間頻寬影響直接。</li>
<li><strong>pipeline parallel</strong>：把不同層分到不同卡、卡間需要傳 activation、頻寬要求中等。</li>
<li><strong>資料分發</strong>：把不同 request 分到不同卡（data parallel）、卡間流量低、PCIe 也夠。</li>
</ol>
<p>頻寬對照（廠商標稱、依世代變化）：</p>
<table>
  <thead>
      <tr>
          <th>介面</th>
          <th>卡間頻寬（標稱）</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>PCIe 4.0 x16</td>
          <td>約 32 GB/s 單向</td>
      </tr>
      <tr>
          <td>PCIe 5.0 x16</td>
          <td>約 64 GB/s 單向</td>
      </tr>
      <tr>
          <td>NVLink（H100）</td>
          <td>約 900 GB/s 雙向、依世代</td>
      </tr>
      <tr>
          <td>NVLink（A100）</td>
          <td>約 600 GB/s 雙向</td>
      </tr>
  </tbody>
</table>
<p>NVLink 比 PCIe 高一個量級、是資料中心多卡推論的關鍵；消費級 RTX 場景多卡通常只能走 PCIe、縮放效益相對受限。</p>
<blockquote>
<p><strong>事實查核註</strong>：NVLink 各世代的頻寬數字依 NVIDIA 官方規格、不同 GPU 跟世代有差異；NVLink 在哪些消費級 / 工作站 / 資料中心 GPU 可用、依時段跟廠商策略變化、引用前以 <a href="https://www.nvidia.com/">NVIDIA 官方產品頁</a> 跟對應 GPU 的 datasheet 為準。</p></blockquote>
<h2 id="設計責任">設計責任</h2>
<p>理解 NVLink 後可以解釋兩個現象：為什麼資料中心多卡 LLM 推論能線性 scale（NVLink 頻寬足以做 tensor parallel）、為什麼消費級雙卡 RTX 推論縮放比通常低於線性（沒 NVLink、走 PCIe x4 / x8、卡間頻寬限制）。</p>
<p>選消費級 GPU 跑本地 LLM 時、NVLink 不是常見選項；多卡升級的判讀應該基於「能否容忍縮放比低於線性」、而不是預期 NVLink 等級的卡間頻寬。詳見 <a href="/blog/llm/05-discrete-gpu/gpu-vendor-differences/" data-link-title="5.6 GPU 廠商差異" data-link-desc="NVIDIA CUDA、AMD ROCm、Intel ARC 在 llama.cpp 生態的相對位置、選卡時的判讀軸">5.6 GPU 廠商差異</a>。</p>
]]></content:encoded></item><item><title>OWASP LLM Top 10</title><link>https://tarrragon.github.io/blog/llm/knowledge-cards/owasp-llm-top10/</link><pubDate>Tue, 12 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/llm/knowledge-cards/owasp-llm-top10/</guid><description>&lt;p>OWASP LLM Top 10 的核心概念是「&lt;strong>Open Worldwide Application Security Project 發布的 LLM 應用最常見 10 大資安風險清單&lt;/strong>」。2023 首發、2025 更新版是業界跟企業安全溝通的共同詞彙、是 production LLM 應用做 threat modeling 跟合規溝通的標準入口。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>2025 版的 10 項（簡述）：&lt;/p>
&lt;table>
 &lt;thead>
 &lt;tr>
 &lt;th>編號&lt;/th>
 &lt;th>名稱&lt;/th>
 &lt;th>簡述&lt;/th>
 &lt;/tr>
 &lt;/thead>
 &lt;tbody>
 &lt;tr>
 &lt;td>LLM01&lt;/td>
 &lt;td>Prompt Injection&lt;/td>
 &lt;td>把惡意指令藏進 LLM 會讀到的內容、間接影響模型行為&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>LLM02&lt;/td>
 &lt;td>Sensitive Information Disclosure&lt;/td>
 &lt;td>LLM 輸出洩漏訓練資料 / system prompt / PII&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>LLM03&lt;/td>
 &lt;td>Supply Chain&lt;/td>
 &lt;td>模型 / 訓練資料 / 工具 / dependency 供應鏈攻擊&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>LLM04&lt;/td>
 &lt;td>Data and Model Poisoning&lt;/td>
 &lt;td>訓練資料污染、模型行為被植入後門&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>LLM05&lt;/td>
 &lt;td>Improper Output Handling&lt;/td>
 &lt;td>LLM 輸出未驗證直接執行（XSS / SQLi / RCE）&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>LLM06&lt;/td>
 &lt;td>Excessive Agency&lt;/td>
 &lt;td>Agent 工具權限過大、副作用不可控&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>LLM07&lt;/td>
 &lt;td>System Prompt Leakage&lt;/td>
 &lt;td>System prompt 被使用者誘導露出&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>LLM08&lt;/td>
 &lt;td>Vector and Embedding Weaknesses&lt;/td>
 &lt;td>Vector DB / embedding pipeline 的攻擊面&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>LLM09&lt;/td>
 &lt;td>Misinformation&lt;/td>
 &lt;td>Hallucination / 過度信任 LLM 輸出&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>LLM10&lt;/td>
 &lt;td>Unbounded Consumption&lt;/td>
 &lt;td>Resource exhaustion / cost runaway（DoS / 燒錢）&lt;/td>
 &lt;/tr>
 &lt;/tbody>
&lt;/table>
&lt;h2 id="跟模組六的-mapping">跟模組六的 mapping&lt;/h2>
&lt;table>
 &lt;thead>
 &lt;tr>
 &lt;th>OWASP&lt;/th>
 &lt;th>模組六章節&lt;/th>
 &lt;th>補充&lt;/th>
 &lt;/tr>
 &lt;/thead>
 &lt;tbody>
 &lt;tr>
 &lt;td>LLM01 Prompt Injection&lt;/td>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/llm/06-security/prompt-injection-in-ide/" data-link-title="6.3 IDE 場景的 prompt injection" data-link-desc="個人 dev 場景下 IDE 寫 code 工作流的 prompt injection：codebase 內容、外部文件、剪貼簿作為攻擊面、跟雲端 LLM 場景的差異">6.3 IDE 場景 prompt injection&lt;/a>&lt;/td>
 &lt;td>直接對應&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>LLM02 Sensitive Disclosure&lt;/td>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/llm/06-security/cross-cloud-local-data-boundary/" data-link-title="6.4 跨雲端 / 本地的資料邊界" data-link-desc="個人 dev 場景下混用雲端 LLM 跟本地 LLM 時的 prompt 洩漏點：Continue.dev 多 provider 設定、隱私資料流、按敏感度分流的判讀">6.4 跨雲端資料邊界&lt;/a>&lt;/td>
 &lt;td>加 &lt;a href="https://tarrragon.github.io/blog/llm/04-applications/static-and-serverless-rag-deployment/" data-link-title="4.16 靜態 / serverless RAG deployment：架構選擇與資安取捨" data-link-desc="沒 backend 的場景怎麼做 RAG：四種 deployment 方案、API key 暴露問題、CORS / abuse / 第三方信任、跟模組六的 routing">4.16 靜態 RAG 資安&lt;/a>&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>LLM03 Supply Chain&lt;/td>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/llm/06-security/model-supply-chain-trust/" data-link-title="6.0 模型供應鏈與信任邊界" data-link-desc="個人 dev 用本地 LLM 時的模型權重來源信任：GGUF 完整性、Hugging Face / Ollama registry 信任、量化版本污染、檔案完整性檢查">6.0 模型供應鏈&lt;/a>&lt;/td>
 &lt;td>直接對應&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>LLM04 Data/Model Poisoning&lt;/td>
 &lt;td>部分（限本地 dev、production 訓練屬 backend/07）&lt;/td>
 &lt;td>M6 cover 模型來源信任、不 cover 訓練毒化&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>LLM05 Improper Output&lt;/td>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/llm/06-security/tool-use-permission-model/" data-link-title="6.2 tool use 與 MCP server 的權限模型" data-link-desc="個人 dev 場景下 tool use / MCP server 的副作用權限：檔案系統 / shell / 網路存取邊界、第三方 MCP 信任、副作用的可逆性">6.2 tool use 權限&lt;/a>&lt;/td>
 &lt;td>直接對應&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>LLM06 Excessive Agency&lt;/td>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/llm/06-security/tool-use-permission-model/" data-link-title="6.2 tool use 與 MCP server 的權限模型" data-link-desc="個人 dev 場景下 tool use / MCP server 的副作用權限：檔案系統 / shell / 網路存取邊界、第三方 MCP 信任、副作用的可逆性">6.2&lt;/a> + &lt;a href="https://tarrragon.github.io/blog/llm/04-applications/agent-architecture/" data-link-title="4.4 Agent 架構原理" data-link-desc="Agent loop 結構、失敗模式、什麼任務適合 vs 不適合、跟人類審查的協作模型">4.4 agent 架構&lt;/a>&lt;/td>
 &lt;td>跨原理 + 安全&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>LLM07 System Prompt Leakage&lt;/td>
 &lt;td>部分（&lt;a href="https://tarrragon.github.io/blog/llm/04-applications/coding-agent-harness/" data-link-title="4.17 Coding agent harness：scaffold / context engineering / subagent" data-link-desc="Coding agent 的內部設計：scaffold vs harness 分層、context budget 25% 規則、subagent 拓樸、跟 Claude Code / Cursor / Aider 的 mapping">4.17 coding agent harness&lt;/a>）&lt;/td>
 &lt;td>M6 沒專章、屬 scaffold 設計&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>LLM08 Vector / Embedding&lt;/td>
 &lt;td>部分（&lt;a href="https://tarrragon.github.io/blog/llm/04-applications/rag-principles/" data-link-title="4.1 RAG 原理：retrieval &amp;#43; augmentation 模式" data-link-desc="為什麼模型需要外掛知識、語意相似 vs 字面相似、chunking 的本質取捨、retrieval 失敗的根本原因">4.1 RAG&lt;/a> + &lt;a href="https://tarrragon.github.io/blog/llm/04-applications/static-and-serverless-rag-deployment/" data-link-title="4.16 靜態 / serverless RAG deployment：架構選擇與資安取捨" data-link-desc="沒 backend 的場景怎麼做 RAG：四種 deployment 方案、API key 暴露問題、CORS / abuse / 第三方信任、跟模組六的 routing">4.16 靜態 RAG 資安&lt;/a>）&lt;/td>
 &lt;td>跨原理 + 應用&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>LLM09 Misinformation&lt;/td>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/hallucination/" data-link-title="Hallucination" data-link-desc="LLM 生成內容看起來合理但事實錯誤、引用不存在的來源、虛構不存在的 entity 的現象">hallucination&lt;/a> 卡 + &lt;a href="https://tarrragon.github.io/blog/llm/04-applications/llm-as-judge/" data-link-title="4.21 LLM-as-Judge 評估方法" data-link-desc="LLM 評估 LLM 的 production eval 方法：rubric design、pairwise / direct scoring、三大 bias 緩解、跟 trace 串接的閉環、calibration">4.21 LLM-as-judge&lt;/a>&lt;/td>
 &lt;td>跨卡 + 應用&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>LLM10 Unbounded Consumption&lt;/td>
 &lt;td>部分（&lt;a href="https://tarrragon.github.io/blog/llm/04-applications/prompt-caching-engineering/" data-link-title="4.18 Prompt caching 工程實務：cost / latency 最大槓桿" data-link-desc="Prompt cache 怎麼運作、cache_control 設計、coding agent 跟 long-context 的 cache pattern、anti-pattern 跟 cache miss 訊號">4.18 prompt caching&lt;/a> + &lt;a href="https://tarrragon.github.io/blog/llm/04-applications/static-and-serverless-rag-deployment/" data-link-title="4.16 靜態 / serverless RAG deployment：架構選擇與資安取捨" data-link-desc="沒 backend 的場景怎麼做 RAG：四種 deployment 方案、API key 暴露問題、CORS / abuse / 第三方信任、跟模組六的 routing">4.16 靜態 RAG 資安 abuse&lt;/a>）&lt;/td>
 &lt;td>M6 沒專章、屬 abuse 緩解&lt;/td>
 &lt;/tr>
 &lt;/tbody>
&lt;/table>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>讀企業 LLM 安全 / 合規文件 / vendor security audit 看到「OWASP LLM Top 10」就是這 framing。寫 code 場景的判讀：&lt;/p></description><content:encoded><![CDATA[<p>OWASP LLM Top 10 的核心概念是「<strong>Open Worldwide Application Security Project 發布的 LLM 應用最常見 10 大資安風險清單</strong>」。2023 首發、2025 更新版是業界跟企業安全溝通的共同詞彙、是 production LLM 應用做 threat modeling 跟合規溝通的標準入口。</p>
<h2 id="概念位置">概念位置</h2>
<p>2025 版的 10 項（簡述）：</p>
<table>
  <thead>
      <tr>
          <th>編號</th>
          <th>名稱</th>
          <th>簡述</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>LLM01</td>
          <td>Prompt Injection</td>
          <td>把惡意指令藏進 LLM 會讀到的內容、間接影響模型行為</td>
      </tr>
      <tr>
          <td>LLM02</td>
          <td>Sensitive Information Disclosure</td>
          <td>LLM 輸出洩漏訓練資料 / system prompt / PII</td>
      </tr>
      <tr>
          <td>LLM03</td>
          <td>Supply Chain</td>
          <td>模型 / 訓練資料 / 工具 / dependency 供應鏈攻擊</td>
      </tr>
      <tr>
          <td>LLM04</td>
          <td>Data and Model Poisoning</td>
          <td>訓練資料污染、模型行為被植入後門</td>
      </tr>
      <tr>
          <td>LLM05</td>
          <td>Improper Output Handling</td>
          <td>LLM 輸出未驗證直接執行（XSS / SQLi / RCE）</td>
      </tr>
      <tr>
          <td>LLM06</td>
          <td>Excessive Agency</td>
          <td>Agent 工具權限過大、副作用不可控</td>
      </tr>
      <tr>
          <td>LLM07</td>
          <td>System Prompt Leakage</td>
          <td>System prompt 被使用者誘導露出</td>
      </tr>
      <tr>
          <td>LLM08</td>
          <td>Vector and Embedding Weaknesses</td>
          <td>Vector DB / embedding pipeline 的攻擊面</td>
      </tr>
      <tr>
          <td>LLM09</td>
          <td>Misinformation</td>
          <td>Hallucination / 過度信任 LLM 輸出</td>
      </tr>
      <tr>
          <td>LLM10</td>
          <td>Unbounded Consumption</td>
          <td>Resource exhaustion / cost runaway（DoS / 燒錢）</td>
      </tr>
  </tbody>
</table>
<h2 id="跟模組六的-mapping">跟模組六的 mapping</h2>
<table>
  <thead>
      <tr>
          <th>OWASP</th>
          <th>模組六章節</th>
          <th>補充</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>LLM01 Prompt Injection</td>
          <td><a href="/blog/llm/06-security/prompt-injection-in-ide/" data-link-title="6.3 IDE 場景的 prompt injection" data-link-desc="個人 dev 場景下 IDE 寫 code 工作流的 prompt injection：codebase 內容、外部文件、剪貼簿作為攻擊面、跟雲端 LLM 場景的差異">6.3 IDE 場景 prompt injection</a></td>
          <td>直接對應</td>
      </tr>
      <tr>
          <td>LLM02 Sensitive Disclosure</td>
          <td><a href="/blog/llm/06-security/cross-cloud-local-data-boundary/" data-link-title="6.4 跨雲端 / 本地的資料邊界" data-link-desc="個人 dev 場景下混用雲端 LLM 跟本地 LLM 時的 prompt 洩漏點：Continue.dev 多 provider 設定、隱私資料流、按敏感度分流的判讀">6.4 跨雲端資料邊界</a></td>
          <td>加 <a href="/blog/llm/04-applications/static-and-serverless-rag-deployment/" data-link-title="4.16 靜態 / serverless RAG deployment：架構選擇與資安取捨" data-link-desc="沒 backend 的場景怎麼做 RAG：四種 deployment 方案、API key 暴露問題、CORS / abuse / 第三方信任、跟模組六的 routing">4.16 靜態 RAG 資安</a></td>
      </tr>
      <tr>
          <td>LLM03 Supply Chain</td>
          <td><a href="/blog/llm/06-security/model-supply-chain-trust/" data-link-title="6.0 模型供應鏈與信任邊界" data-link-desc="個人 dev 用本地 LLM 時的模型權重來源信任：GGUF 完整性、Hugging Face / Ollama registry 信任、量化版本污染、檔案完整性檢查">6.0 模型供應鏈</a></td>
          <td>直接對應</td>
      </tr>
      <tr>
          <td>LLM04 Data/Model Poisoning</td>
          <td>部分（限本地 dev、production 訓練屬 backend/07）</td>
          <td>M6 cover 模型來源信任、不 cover 訓練毒化</td>
      </tr>
      <tr>
          <td>LLM05 Improper Output</td>
          <td><a href="/blog/llm/06-security/tool-use-permission-model/" data-link-title="6.2 tool use 與 MCP server 的權限模型" data-link-desc="個人 dev 場景下 tool use / MCP server 的副作用權限：檔案系統 / shell / 網路存取邊界、第三方 MCP 信任、副作用的可逆性">6.2 tool use 權限</a></td>
          <td>直接對應</td>
      </tr>
      <tr>
          <td>LLM06 Excessive Agency</td>
          <td><a href="/blog/llm/06-security/tool-use-permission-model/" data-link-title="6.2 tool use 與 MCP server 的權限模型" data-link-desc="個人 dev 場景下 tool use / MCP server 的副作用權限：檔案系統 / shell / 網路存取邊界、第三方 MCP 信任、副作用的可逆性">6.2</a> + <a href="/blog/llm/04-applications/agent-architecture/" data-link-title="4.4 Agent 架構原理" data-link-desc="Agent loop 結構、失敗模式、什麼任務適合 vs 不適合、跟人類審查的協作模型">4.4 agent 架構</a></td>
          <td>跨原理 + 安全</td>
      </tr>
      <tr>
          <td>LLM07 System Prompt Leakage</td>
          <td>部分（<a href="/blog/llm/04-applications/coding-agent-harness/" data-link-title="4.17 Coding agent harness：scaffold / context engineering / subagent" data-link-desc="Coding agent 的內部設計：scaffold vs harness 分層、context budget 25% 規則、subagent 拓樸、跟 Claude Code / Cursor / Aider 的 mapping">4.17 coding agent harness</a>）</td>
          <td>M6 沒專章、屬 scaffold 設計</td>
      </tr>
      <tr>
          <td>LLM08 Vector / Embedding</td>
          <td>部分（<a href="/blog/llm/04-applications/rag-principles/" data-link-title="4.1 RAG 原理：retrieval &#43; augmentation 模式" data-link-desc="為什麼模型需要外掛知識、語意相似 vs 字面相似、chunking 的本質取捨、retrieval 失敗的根本原因">4.1 RAG</a> + <a href="/blog/llm/04-applications/static-and-serverless-rag-deployment/" data-link-title="4.16 靜態 / serverless RAG deployment：架構選擇與資安取捨" data-link-desc="沒 backend 的場景怎麼做 RAG：四種 deployment 方案、API key 暴露問題、CORS / abuse / 第三方信任、跟模組六的 routing">4.16 靜態 RAG 資安</a>）</td>
          <td>跨原理 + 應用</td>
      </tr>
      <tr>
          <td>LLM09 Misinformation</td>
          <td><a href="/blog/llm/knowledge-cards/hallucination/" data-link-title="Hallucination" data-link-desc="LLM 生成內容看起來合理但事實錯誤、引用不存在的來源、虛構不存在的 entity 的現象">hallucination</a> 卡 + <a href="/blog/llm/04-applications/llm-as-judge/" data-link-title="4.21 LLM-as-Judge 評估方法" data-link-desc="LLM 評估 LLM 的 production eval 方法：rubric design、pairwise / direct scoring、三大 bias 緩解、跟 trace 串接的閉環、calibration">4.21 LLM-as-judge</a></td>
          <td>跨卡 + 應用</td>
      </tr>
      <tr>
          <td>LLM10 Unbounded Consumption</td>
          <td>部分（<a href="/blog/llm/04-applications/prompt-caching-engineering/" data-link-title="4.18 Prompt caching 工程實務：cost / latency 最大槓桿" data-link-desc="Prompt cache 怎麼運作、cache_control 設計、coding agent 跟 long-context 的 cache pattern、anti-pattern 跟 cache miss 訊號">4.18 prompt caching</a> + <a href="/blog/llm/04-applications/static-and-serverless-rag-deployment/" data-link-title="4.16 靜態 / serverless RAG deployment：架構選擇與資安取捨" data-link-desc="沒 backend 的場景怎麼做 RAG：四種 deployment 方案、API key 暴露問題、CORS / abuse / 第三方信任、跟模組六的 routing">4.16 靜態 RAG 資安 abuse</a>）</td>
          <td>M6 沒專章、屬 abuse 緩解</td>
      </tr>
  </tbody>
</table>
<h2 id="設計責任">設計責任</h2>
<p>讀企業 LLM 安全 / 合規文件 / vendor security audit 看到「OWASP LLM Top 10」就是這 framing。寫 code 場景的判讀：</p>
<ol>
<li><strong>跟企業溝通必備</strong>：安全 team / vendor audit 都用 OWASP 編號、能 map 自己應用到 LLM01-LLM10 就能 align 對話</li>
<li><strong>不是 production 才需要看</strong>：個人 dev 也適用大部分（LLM01 prompt injection、LLM03 supply chain、LLM06 excessive agency 對個人都直接相關）</li>
<li><strong>跟 <a href="/blog/llm/06-security/owasp-llm-top10-mapping/" data-link-title="6.6 OWASP LLM Top 10 對照圖" data-link-desc="把模組六的本地 dev 視角安全章節對照到 OWASP LLM Top 10 2025、補出個人 dev 場景跟企業合規溝通的共同詞彙">6.6 OWASP 對照章節</a> 的關係</strong>：本卡是定義 + mapping、章節是詳細 mapping + 個人 dev 場景的對應 control</li>
</ol>
]]></content:encoded></item><item><title>PCIe</title><link>https://tarrragon.github.io/blog/llm/knowledge-cards/pcie/</link><pubDate>Tue, 12 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/llm/knowledge-cards/pcie/</guid><description>&lt;p>PCIe（PCI Express）的核心概念是「PC 上 GPU 跟主機板（CPU + 系統 RAM）之間的高速序列匯流排」。獨立 GPU 場景下、模型權重從 SSD / 系統 RAM 走 PCIe 進 VRAM、之後推論主要在 GPU 內部完成；但 &lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/moe-cpu-offload/" data-link-title="MoE CPU 卸載" data-link-desc="把 Mixture-of-Experts 模型不活躍的專家層權重放在系統 RAM、用到再走 PCIe 拉回 GPU、讓有限 VRAM 跑得了更大模型">MoE CPU 卸載&lt;/a> 啟用時、每 token 都需要從系統 RAM 走 PCIe 拉部分權重、PCIe 頻寬開始影響推論吞吐。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>PCIe 在本地 LLM 推論的兩個階段角色不同：&lt;/p>
&lt;ol>
&lt;li>&lt;strong>模型載入階段&lt;/strong>：模型權重從 SSD → 系統 RAM → 走 PCIe → &lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/vram/" data-link-title="VRAM" data-link-desc="顯卡上的記憶體、跟系統 RAM 是兩塊獨立預算、決定能載入多大模型權重跟 KV cache">VRAM&lt;/a>。PCIe 是常見瓶頸、影響「啟動時間」、不影響推論。&lt;/li>
&lt;li>&lt;strong>推論階段&lt;/strong>：
&lt;ul>
&lt;li>全載 VRAM 場景：權重已在 VRAM、推論時 PCIe 流量很少。&lt;/li>
&lt;li>MoE 卸載場景：每 token 從系統 RAM 拉專家權重經 PCIe、PCIe 頻寬成為次要瓶頸。&lt;/li>
&lt;/ul>
&lt;/li>
&lt;/ol>
&lt;p>PCIe 版本跟頻寬（廠商標稱、單向）：&lt;/p>
&lt;table>
 &lt;thead>
 &lt;tr>
 &lt;th>版本&lt;/th>
 &lt;th>x16 單向標稱頻寬&lt;/th>
 &lt;/tr>
 &lt;/thead>
 &lt;tbody>
 &lt;tr>
 &lt;td>PCIe 4.0 x16&lt;/td>
 &lt;td>約 32 GB/s&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>PCIe 5.0 x16&lt;/td>
 &lt;td>約 64 GB/s&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>PCIe 6.0 x16&lt;/td>
 &lt;td>約 128 GB/s&lt;/td>
 &lt;/tr>
 &lt;/tbody>
&lt;/table>
&lt;p>實際傳輸吞吐受驅動、檔案系統、量化格式影響、通常低於規格上限。&lt;/p>
&lt;blockquote>
&lt;p>&lt;strong>事實查核註&lt;/strong>：PCIe 各版本的標稱頻寬數字以 &lt;a href="https://pcisig.com/">PCI-SIG&lt;/a> 官方規格為主、實際可達吞吐依硬體配置變化、引用前以對應版本的官方規格文件為準。&lt;/p>&lt;/blockquote>
&lt;p>消費級主機板的 PCIe lane 分配常見「一條 x16 + 一條 x4」、加第二張 GPU 時、第二張的有效頻寬可能只有 x4、影響多卡縮放效益。詳見 &lt;a href="https://tarrragon.github.io/blog/llm/05-discrete-gpu/llama-cpp-on-pc/" data-link-title="5.3 llama.cpp 在 PC 上" data-link-desc="CUDA / ROCm build 取得、核心旗標地圖、llama-bench 校準、多卡 tensor split 的入門設定">5.3 llama.cpp 在 PC 上&lt;/a> 的多卡 tensor split 段落。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>理解 PCIe 後可以解釋三個現象：為什麼模型載入要等幾秒到十幾秒（PCIe 是橋）、為什麼單卡 + MoE 卸載通常不卡 PCIe（每 token 拉的權重量小於 PCIe 頻寬）、為什麼雙卡縮放比沒有直接翻倍（PCIe lane 跟主機板配置）。&lt;/p>
&lt;p>選 PC 配置時、PCIe 版本影響模型載入體感、但對單人推論的生字速度通常影響小。多卡升級前要看主機板的 PCIe lane 分配。&lt;/p></description><content:encoded><![CDATA[<p>PCIe（PCI Express）的核心概念是「PC 上 GPU 跟主機板（CPU + 系統 RAM）之間的高速序列匯流排」。獨立 GPU 場景下、模型權重從 SSD / 系統 RAM 走 PCIe 進 VRAM、之後推論主要在 GPU 內部完成；但 <a href="/blog/llm/knowledge-cards/moe-cpu-offload/" data-link-title="MoE CPU 卸載" data-link-desc="把 Mixture-of-Experts 模型不活躍的專家層權重放在系統 RAM、用到再走 PCIe 拉回 GPU、讓有限 VRAM 跑得了更大模型">MoE CPU 卸載</a> 啟用時、每 token 都需要從系統 RAM 走 PCIe 拉部分權重、PCIe 頻寬開始影響推論吞吐。</p>
<h2 id="概念位置">概念位置</h2>
<p>PCIe 在本地 LLM 推論的兩個階段角色不同：</p>
<ol>
<li><strong>模型載入階段</strong>：模型權重從 SSD → 系統 RAM → 走 PCIe → <a href="/blog/llm/knowledge-cards/vram/" data-link-title="VRAM" data-link-desc="顯卡上的記憶體、跟系統 RAM 是兩塊獨立預算、決定能載入多大模型權重跟 KV cache">VRAM</a>。PCIe 是常見瓶頸、影響「啟動時間」、不影響推論。</li>
<li><strong>推論階段</strong>：
<ul>
<li>全載 VRAM 場景：權重已在 VRAM、推論時 PCIe 流量很少。</li>
<li>MoE 卸載場景：每 token 從系統 RAM 拉專家權重經 PCIe、PCIe 頻寬成為次要瓶頸。</li>
</ul>
</li>
</ol>
<p>PCIe 版本跟頻寬（廠商標稱、單向）：</p>
<table>
  <thead>
      <tr>
          <th>版本</th>
          <th>x16 單向標稱頻寬</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>PCIe 4.0 x16</td>
          <td>約 32 GB/s</td>
      </tr>
      <tr>
          <td>PCIe 5.0 x16</td>
          <td>約 64 GB/s</td>
      </tr>
      <tr>
          <td>PCIe 6.0 x16</td>
          <td>約 128 GB/s</td>
      </tr>
  </tbody>
</table>
<p>實際傳輸吞吐受驅動、檔案系統、量化格式影響、通常低於規格上限。</p>
<blockquote>
<p><strong>事實查核註</strong>：PCIe 各版本的標稱頻寬數字以 <a href="https://pcisig.com/">PCI-SIG</a> 官方規格為主、實際可達吞吐依硬體配置變化、引用前以對應版本的官方規格文件為準。</p></blockquote>
<p>消費級主機板的 PCIe lane 分配常見「一條 x16 + 一條 x4」、加第二張 GPU 時、第二張的有效頻寬可能只有 x4、影響多卡縮放效益。詳見 <a href="/blog/llm/05-discrete-gpu/llama-cpp-on-pc/" data-link-title="5.3 llama.cpp 在 PC 上" data-link-desc="CUDA / ROCm build 取得、核心旗標地圖、llama-bench 校準、多卡 tensor split 的入門設定">5.3 llama.cpp 在 PC 上</a> 的多卡 tensor split 段落。</p>
<h2 id="設計責任">設計責任</h2>
<p>理解 PCIe 後可以解釋三個現象：為什麼模型載入要等幾秒到十幾秒（PCIe 是橋）、為什麼單卡 + MoE 卸載通常不卡 PCIe（每 token 拉的權重量小於 PCIe 頻寬）、為什麼雙卡縮放比沒有直接翻倍（PCIe lane 跟主機板配置）。</p>
<p>選 PC 配置時、PCIe 版本影響模型載入體感、但對單人推論的生字速度通常影響小。多卡升級前要看主機板的 PCIe lane 分配。</p>
]]></content:encoded></item><item><title>Perplexity</title><link>https://tarrragon.github.io/blog/llm/knowledge-cards/perplexity/</link><pubDate>Tue, 12 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/llm/knowledge-cards/perplexity/</guid><description>&lt;p>Perplexity（困惑度）的核心概念是「&lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/cross-entropy/" data-link-title="Cross-Entropy" data-link-desc="衡量「預測機率分佈」跟「真實分佈」距離的指標、LLM 預訓練的主要 loss">cross-entropy&lt;/a> 的指數形式」：&lt;code>perplexity = exp(cross-entropy)&lt;/code>。直覺意義是「模型在每個位置平均覺得下個 &lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/token/" data-link-title="Token" data-link-desc="LLM 處理文字時的最小單位：介於字元與單字之間">token&lt;/a> 有多少種候選」。perplexity = 1 表示模型完美預測；perplexity = vocab_size 表示模型純猜（vocab 上的 uniform 分佈）。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>Perplexity 跟 cross-entropy 的關係：&lt;/p>
&lt;table>
 &lt;thead>
 &lt;tr>
 &lt;th>指標&lt;/th>
 &lt;th>公式 / 定義&lt;/th>
 &lt;th>人類直覺&lt;/th>
 &lt;/tr>
 &lt;/thead>
 &lt;tbody>
 &lt;tr>
 &lt;td>Cross-entropy&lt;/td>
 &lt;td>&lt;code>-mean(log p_true)&lt;/code>、底通常是 e&lt;/td>
 &lt;td>loss 數字、訓練拿來最佳化&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>Perplexity&lt;/td>
 &lt;td>&lt;code>exp(cross-entropy)&lt;/code>&lt;/td>
 &lt;td>「平均看到幾種候選」、好讀&lt;/td>
 &lt;/tr>
 &lt;/tbody>
&lt;/table>
&lt;p>換算範例（base e）：&lt;/p>
&lt;table>
 &lt;thead>
 &lt;tr>
 &lt;th>Cross-entropy&lt;/th>
 &lt;th>Perplexity&lt;/th>
 &lt;th>意義（極粗略直覺）&lt;/th>
 &lt;/tr>
 &lt;/thead>
 &lt;tbody>
 &lt;tr>
 &lt;td>11&lt;/td>
 &lt;td>~60K&lt;/td>
 &lt;td>純隨機（vocab ≈ 128K 時）&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>5&lt;/td>
 &lt;td>~148&lt;/td>
 &lt;td>早期訓練&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>3&lt;/td>
 &lt;td>~20&lt;/td>
 &lt;td>中等訓練模型&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>2&lt;/td>
 &lt;td>~7.4&lt;/td>
 &lt;td>接近現代成熟 LLM 在文本上的表現&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>0&lt;/td>
 &lt;td>1&lt;/td>
 &lt;td>完美預測（不可能達到）&lt;/td>
 &lt;/tr>
 &lt;/tbody>
&lt;/table>
&lt;p>Perplexity 主要用於：&lt;/p>
&lt;ul>
&lt;li>&lt;strong>預訓練評估&lt;/strong>：在 held-out 語料上算 perplexity、衡量基礎建模能力。&lt;/li>
&lt;li>&lt;strong>量化品質衡量&lt;/strong>：fp16 vs Q4 vs Q3 模型的 perplexity 差異、看量化造成多少品質損失。&lt;/li>
&lt;li>&lt;strong>領域 benchmark&lt;/strong>：在特定領域語料（code、math、医學文獻）上算 perplexity、評估模型對該領域的熟悉度。&lt;/li>
&lt;/ul>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>Perplexity 是 base model 評估標準、但對 instruction-tuned / chat 模型用處有限（chat 模型輸出風格已偏離 raw text、perplexity 不一定降）。對寫 code 場景的判讀：看到 paper 報 perplexity 是評估 pretrain 品質的訊號、實際聊天 / coding 能力要看 &lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/swe-bench/" data-link-title="SWE-bench" data-link-desc="用真實 GitHub issue 量化 LLM coding 能力的 benchmark">SWE-bench&lt;/a>、MMLU、HumanEval 等任務式 benchmark。&lt;/p></description><content:encoded><![CDATA[<p>Perplexity（困惑度）的核心概念是「<a href="/blog/llm/knowledge-cards/cross-entropy/" data-link-title="Cross-Entropy" data-link-desc="衡量「預測機率分佈」跟「真實分佈」距離的指標、LLM 預訓練的主要 loss">cross-entropy</a> 的指數形式」：<code>perplexity = exp(cross-entropy)</code>。直覺意義是「模型在每個位置平均覺得下個 <a href="/blog/llm/knowledge-cards/token/" data-link-title="Token" data-link-desc="LLM 處理文字時的最小單位：介於字元與單字之間">token</a> 有多少種候選」。perplexity = 1 表示模型完美預測；perplexity = vocab_size 表示模型純猜（vocab 上的 uniform 分佈）。</p>
<h2 id="概念位置">概念位置</h2>
<p>Perplexity 跟 cross-entropy 的關係：</p>
<table>
  <thead>
      <tr>
          <th>指標</th>
          <th>公式 / 定義</th>
          <th>人類直覺</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>Cross-entropy</td>
          <td><code>-mean(log p_true)</code>、底通常是 e</td>
          <td>loss 數字、訓練拿來最佳化</td>
      </tr>
      <tr>
          <td>Perplexity</td>
          <td><code>exp(cross-entropy)</code></td>
          <td>「平均看到幾種候選」、好讀</td>
      </tr>
  </tbody>
</table>
<p>換算範例（base e）：</p>
<table>
  <thead>
      <tr>
          <th>Cross-entropy</th>
          <th>Perplexity</th>
          <th>意義（極粗略直覺）</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>11</td>
          <td>~60K</td>
          <td>純隨機（vocab ≈ 128K 時）</td>
      </tr>
      <tr>
          <td>5</td>
          <td>~148</td>
          <td>早期訓練</td>
      </tr>
      <tr>
          <td>3</td>
          <td>~20</td>
          <td>中等訓練模型</td>
      </tr>
      <tr>
          <td>2</td>
          <td>~7.4</td>
          <td>接近現代成熟 LLM 在文本上的表現</td>
      </tr>
      <tr>
          <td>0</td>
          <td>1</td>
          <td>完美預測（不可能達到）</td>
      </tr>
  </tbody>
</table>
<p>Perplexity 主要用於：</p>
<ul>
<li><strong>預訓練評估</strong>：在 held-out 語料上算 perplexity、衡量基礎建模能力。</li>
<li><strong>量化品質衡量</strong>：fp16 vs Q4 vs Q3 模型的 perplexity 差異、看量化造成多少品質損失。</li>
<li><strong>領域 benchmark</strong>：在特定領域語料（code、math、医學文獻）上算 perplexity、評估模型對該領域的熟悉度。</li>
</ul>
<h2 id="設計責任">設計責任</h2>
<p>Perplexity 是 base model 評估標準、但對 instruction-tuned / chat 模型用處有限（chat 模型輸出風格已偏離 raw text、perplexity 不一定降）。對寫 code 場景的判讀：看到 paper 報 perplexity 是評估 pretrain 品質的訊號、實際聊天 / coding 能力要看 <a href="/blog/llm/knowledge-cards/swe-bench/" data-link-title="SWE-bench" data-link-desc="用真實 GitHub issue 量化 LLM coding 能力的 benchmark">SWE-bench</a>、MMLU、HumanEval 等任務式 benchmark。</p>
]]></content:encoded></item><item><title>Port 與 Localhost</title><link>https://tarrragon.github.io/blog/llm/knowledge-cards/port-and-localhost/</link><pubDate>Tue, 12 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/llm/knowledge-cards/port-and-localhost/</guid><description>&lt;p>Port 與 Localhost 的核心概念是「網路 server 暴露在哪個地址、聽哪個 port、讓誰能連進來」。本地 LLM 場景中、Ollama 預設聽 &lt;code>127.0.0.1:11434&lt;/code>、Continue.dev 等介面層透過這個地址呼叫 &lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/openai-compatible-api/" data-link-title="OpenAI 相容 API" data-link-desc="本地推論伺服器跟雲端 OpenAI 共用的 API 形狀標準">OpenAI 相容 API&lt;/a>；理解 listen address 跟 port 的角色、才能判讀「為什麼 port 撞 / 為什麼 LAN 上另一台連不到 / 暴露到 internet 安全嗎」。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>完整的 server 入口由兩個欄位定義：&lt;/p>
&lt;table>
 &lt;thead>
 &lt;tr>
 &lt;th>欄位&lt;/th>
 &lt;th>角色&lt;/th>
 &lt;th>範例值&lt;/th>
 &lt;/tr>
 &lt;/thead>
 &lt;tbody>
 &lt;tr>
 &lt;td>Listen address&lt;/td>
 &lt;td>接受哪些網路介面送進來的封包&lt;/td>
 &lt;td>&lt;code>127.0.0.1&lt;/code> / &lt;code>0.0.0.0&lt;/code> / &lt;code>192.168.x&lt;/code>&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>Port&lt;/td>
 &lt;td>OS 用來區分「同一台機器上哪個 server」&lt;/td>
 &lt;td>&lt;code>11434&lt;/code> / &lt;code>1234&lt;/code> / &lt;code>8080&lt;/code>&lt;/td>
 &lt;/tr>
 &lt;/tbody>
&lt;/table>
&lt;p>Port 是 16 bit 數字（0 ~ 65535）、其中 0 ~ 1023 是 well-known port（HTTP 80、HTTPS 443 等、需 root 權限才能 bind）、1024 ~ 65535 是 user port、本地 LLM 工具都用這個區間（Ollama 11434、LM Studio 1234、llama.cpp 8080）。同一個 port 在同一個 listen address 上同時只能被一個 process 持有、要兩個 Ollama 並存就要其中一個換 port。&lt;/p>
&lt;p>三個常見 listen address 的語意：&lt;/p>
&lt;table>
 &lt;thead>
 &lt;tr>
 &lt;th>地址&lt;/th>
 &lt;th>等同名稱&lt;/th>
 &lt;th>接受誰的連線&lt;/th>
 &lt;/tr>
 &lt;/thead>
 &lt;tbody>
 &lt;tr>
 &lt;td>&lt;code>127.0.0.1&lt;/code>&lt;/td>
 &lt;td>&lt;code>localhost&lt;/code>&lt;/td>
 &lt;td>只接受本機 process、外部裝置連不到&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;code>0.0.0.0&lt;/code>&lt;/td>
 &lt;td>所有介面&lt;/td>
 &lt;td>接受任何網路介面送進來的封包、包含 LAN / VPN / public&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;code>192.168.x&lt;/code>&lt;/td>
 &lt;td>特定 LAN 介面&lt;/td>
 &lt;td>只接受該 LAN 介面送進來的封包&lt;/td>
 &lt;/tr>
 &lt;/tbody>
&lt;/table>
&lt;h2 id="可觀察訊號與例子">可觀察訊號與例子&lt;/h2>
&lt;p>驗證 server 真的在聽預期地址：&lt;/p>





&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-bash" data-lang="bash">&lt;span class="line">&lt;span class="ln">1&lt;/span>&lt;span class="cl">&lt;span class="c1"># macOS 下查誰佔了 11434&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">2&lt;/span>&lt;span class="cl">lsof -i :11434
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">3&lt;/span>&lt;span class="cl">&lt;span class="c1"># COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">4&lt;/span>&lt;span class="cl">&lt;span class="c1"># ollama 1234 mac 6u IPv4 0xabcd 0t0 TCP localhost:11434 (LISTEN)&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>&lt;code>TCP localhost:11434 (LISTEN)&lt;/code> 表示這個 process 只接 localhost 進來的封包。改 listen address 把 Ollama 暴露到 LAN：&lt;/p>





&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-bash" data-lang="bash">&lt;span class="line">&lt;span class="ln">1&lt;/span>&lt;span class="cl">&lt;span class="nv">OLLAMA_HOST&lt;/span>&lt;span class="o">=&lt;/span>0.0.0.0:11434 ollama serve
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">2&lt;/span>&lt;span class="cl">&lt;span class="c1"># lsof 之後會看到 TCP *:11434 (LISTEN)、星號表示所有介面&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>curl 用不同 host 名稱呼叫同一個 server：&lt;/p>





&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-bash" data-lang="bash">&lt;span class="line">&lt;span class="ln">1&lt;/span>&lt;span class="cl">curl http://localhost:11434/api/version &lt;span class="c1"># 走 loopback、最快&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">2&lt;/span>&lt;span class="cl">curl http://127.0.0.1:11434/api/version &lt;span class="c1"># 跟上面等價&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">3&lt;/span>&lt;span class="cl">curl http://&amp;lt;本機 LAN IP&amp;gt;:11434/api/version &lt;span class="c1"># 若 listen 在 0.0.0.0、會通；只 listen localhost 會 connection refused&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>「為什麼桌機跑 Ollama、筆電連不到」的最常見原因就是 Ollama 沒改 listen address、預設只接受 loopback。&lt;/p></description><content:encoded><![CDATA[<p>Port 與 Localhost 的核心概念是「網路 server 暴露在哪個地址、聽哪個 port、讓誰能連進來」。本地 LLM 場景中、Ollama 預設聽 <code>127.0.0.1:11434</code>、Continue.dev 等介面層透過這個地址呼叫 <a href="/blog/llm/knowledge-cards/openai-compatible-api/" data-link-title="OpenAI 相容 API" data-link-desc="本地推論伺服器跟雲端 OpenAI 共用的 API 形狀標準">OpenAI 相容 API</a>；理解 listen address 跟 port 的角色、才能判讀「為什麼 port 撞 / 為什麼 LAN 上另一台連不到 / 暴露到 internet 安全嗎」。</p>
<h2 id="概念位置">概念位置</h2>
<p>完整的 server 入口由兩個欄位定義：</p>
<table>
  <thead>
      <tr>
          <th>欄位</th>
          <th>角色</th>
          <th>範例值</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>Listen address</td>
          <td>接受哪些網路介面送進來的封包</td>
          <td><code>127.0.0.1</code> / <code>0.0.0.0</code> / <code>192.168.x</code></td>
      </tr>
      <tr>
          <td>Port</td>
          <td>OS 用來區分「同一台機器上哪個 server」</td>
          <td><code>11434</code> / <code>1234</code> / <code>8080</code></td>
      </tr>
  </tbody>
</table>
<p>Port 是 16 bit 數字（0 ~ 65535）、其中 0 ~ 1023 是 well-known port（HTTP 80、HTTPS 443 等、需 root 權限才能 bind）、1024 ~ 65535 是 user port、本地 LLM 工具都用這個區間（Ollama 11434、LM Studio 1234、llama.cpp 8080）。同一個 port 在同一個 listen address 上同時只能被一個 process 持有、要兩個 Ollama 並存就要其中一個換 port。</p>
<p>三個常見 listen address 的語意：</p>
<table>
  <thead>
      <tr>
          <th>地址</th>
          <th>等同名稱</th>
          <th>接受誰的連線</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td><code>127.0.0.1</code></td>
          <td><code>localhost</code></td>
          <td>只接受本機 process、外部裝置連不到</td>
      </tr>
      <tr>
          <td><code>0.0.0.0</code></td>
          <td>所有介面</td>
          <td>接受任何網路介面送進來的封包、包含 LAN / VPN / public</td>
      </tr>
      <tr>
          <td><code>192.168.x</code></td>
          <td>特定 LAN 介面</td>
          <td>只接受該 LAN 介面送進來的封包</td>
      </tr>
  </tbody>
</table>
<h2 id="可觀察訊號與例子">可觀察訊號與例子</h2>
<p>驗證 server 真的在聽預期地址：</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="ln">1</span><span class="cl"><span class="c1"># macOS 下查誰佔了 11434</span>
</span></span><span class="line"><span class="ln">2</span><span class="cl">lsof -i :11434
</span></span><span class="line"><span class="ln">3</span><span class="cl"><span class="c1"># COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME</span>
</span></span><span class="line"><span class="ln">4</span><span class="cl"><span class="c1"># ollama  1234 mac  6u IPv4 0xabcd      0t0 TCP localhost:11434 (LISTEN)</span></span></span></code></pre></div><p><code>TCP localhost:11434 (LISTEN)</code> 表示這個 process 只接 localhost 進來的封包。改 listen address 把 Ollama 暴露到 LAN：</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="ln">1</span><span class="cl"><span class="nv">OLLAMA_HOST</span><span class="o">=</span>0.0.0.0:11434 ollama serve
</span></span><span class="line"><span class="ln">2</span><span class="cl"><span class="c1"># lsof 之後會看到 TCP *:11434 (LISTEN)、星號表示所有介面</span></span></span></code></pre></div><p>curl 用不同 host 名稱呼叫同一個 server：</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="ln">1</span><span class="cl">curl http://localhost:11434/api/version    <span class="c1"># 走 loopback、最快</span>
</span></span><span class="line"><span class="ln">2</span><span class="cl">curl http://127.0.0.1:11434/api/version    <span class="c1"># 跟上面等價</span>
</span></span><span class="line"><span class="ln">3</span><span class="cl">curl http://&lt;本機 LAN IP&gt;:11434/api/version <span class="c1"># 若 listen 在 0.0.0.0、會通；只 listen localhost 會 connection refused</span></span></span></code></pre></div><p>「為什麼桌機跑 Ollama、筆電連不到」的最常見原因就是 Ollama 沒改 listen address、預設只接受 loopback。</p>
<h2 id="設計責任">設計責任</h2>
<p>選 listen address 是信任邊界決定：</p>
<ul>
<li><strong><code>127.0.0.1</code>（預設）</strong>：機器本身就是信任邊界、外部進不來、最安全</li>
<li><strong><code>0.0.0.0</code> 在家用 / 信任 LAN</strong>：把 server 暴露給同網路裝置、便於多裝置共用、風險可接受</li>
<li><strong><code>0.0.0.0</code> 在公共 Wi-Fi / 對 internet</strong>：等於對所有路過裝置開放、Ollama 沒有內建 auth、需要 SSH tunnel 或 reverse proxy + auth 才安全</li>
</ul>
<p>Port 衝突的處理順序：用 <code>lsof</code> 確認佔用方身分 → 若是舊版自己 kill、若是別的服務改自己的 port → 同步更新 IDE plugin 的 <code>apiBase</code>。完整資料流判讀見 <a href="/blog/llm/00-foundations/privacy-data-flow/" data-link-title="0.7 隱私 / 資安的資料流原理" data-link-desc="從「位置」到「資料流」的思考升級：信任邊界、合約模型、零信任原則套用到 LLM 工作流">0.7 隱私資料流</a>。</p>
]]></content:encoded></item><item><title>Pre-training</title><link>https://tarrragon.github.io/blog/llm/knowledge-cards/pre-training/</link><pubDate>Tue, 12 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/llm/knowledge-cards/pre-training/</guid><description>&lt;p>Pre-training（預訓練）的核心概念是「在大量未標註文字上、用 next-token prediction 當目標訓練一個語言模型」。產出的權重稱為 &lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/base-model/" data-link-title="Base Model" data-link-desc="未經指令微調的原始模型：擅長文字接龍、適合下游微調用途">base model&lt;/a>、是後續 &lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/sft/" data-link-title="SFT（Supervised Fine-Tuning）" data-link-desc="在 base model 上用「指令-回答」對資料微調、讓模型會跟著指令走">SFT&lt;/a> / &lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/rlhf/" data-link-title="RLHF" data-link-desc="Reinforcement Learning from Human Feedback：用人類偏好訓練的 reward model 透過 RL 對齊 LLM">RLHF&lt;/a> 的起點。Pre-training 是 LLM 三階段訓練流程中&lt;strong>最貴、最耗時、最決定模型上限&lt;/strong>的階段。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>Pre-training 在 LLM 訓練 pipeline 的位置：&lt;/p>





&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-text" data-lang="text">&lt;span class="line">&lt;span class="ln">1&lt;/span>&lt;span class="cl">[網路文字 / 書籍 / code / 論文]（trillion token 級）
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">2&lt;/span>&lt;span class="cl"> ↓ Pre-training（next-token prediction、cross-entropy loss）
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">3&lt;/span>&lt;span class="cl">[Base model]：會接龍但不會對話
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">4&lt;/span>&lt;span class="cl"> ↓ SFT（指令-回答對資料）
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">5&lt;/span>&lt;span class="cl">[Instruction-tuned model]：會跟指令走
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">6&lt;/span>&lt;span class="cl"> ↓ RLHF / DPO（人類偏好資料）
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">7&lt;/span>&lt;span class="cl">[Aligned model]：對話風格 / 安全性對齊&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>Pre-training 的特性：&lt;/p>
&lt;table>
 &lt;thead>
 &lt;tr>
 &lt;th>維度&lt;/th>
 &lt;th>典型數字（2026 年主流大模型）&lt;/th>
 &lt;/tr>
 &lt;/thead>
 &lt;tbody>
 &lt;tr>
 &lt;td>資料量&lt;/td>
 &lt;td>數兆 token（Common Crawl、RefinedWeb、The Pile、Stack 等）&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>GPU 用量&lt;/td>
 &lt;td>數百到數萬張 H100 / B200、並行訓練&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>訓練時間&lt;/td>
 &lt;td>數週到數月&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>成本級別&lt;/td>
 &lt;td>數百萬到數億美元&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>Loss&lt;/td>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/cross-entropy/" data-link-title="Cross-Entropy" data-link-desc="衡量「預測機率分佈」跟「真實分佈」距離的指標、LLM 預訓練的主要 loss">Cross-entropy&lt;/a> on next-token&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>結果&lt;/td>
 &lt;td>「會接龍」的 &lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/base-model/" data-link-title="Base Model" data-link-desc="未經指令微調的原始模型：擅長文字接龍、適合下游微調用途">base model&lt;/a>、可用 &lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/perplexity/" data-link-title="Perplexity" data-link-desc="cross-entropy 的指數形式、直覺意義為「模型平均覺得下個 token 有多少種可能」">perplexity&lt;/a> 評估&lt;/td>
 &lt;/tr>
 &lt;/tbody>
&lt;/table>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>理解 pre-training 後可以判讀幾件事：模型的「世界知識」絕大部分在 pre-training 時就決定了、&lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/sft/" data-link-title="SFT（Supervised Fine-Tuning）" data-link-desc="在 base model 上用「指令-回答」對資料微調、讓模型會跟著指令走">SFT&lt;/a> / &lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/rlhf/" data-link-title="RLHF" data-link-desc="Reinforcement Learning from Human Feedback：用人類偏好訓練的 reward model 透過 RL 對齊 LLM">RLHF&lt;/a> 只是「教模型怎麼用這些知識回答」、不會大幅增加新知識；模型 cutoff date 就是 pre-training 資料的截止；想做新領域知識引入、&lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/rag/" data-link-title="RAG" data-link-desc="Retrieval-Augmented Generation：動態外掛知識給 LLM、繞開模型參數記憶的靜態限制">RAG&lt;/a> 比繼續 fine-tune 划算（pre-training 太貴、且 fine-tune 容易讓既有能力退化）。&lt;/p></description><content:encoded><![CDATA[<p>Pre-training（預訓練）的核心概念是「在大量未標註文字上、用 next-token prediction 當目標訓練一個語言模型」。產出的權重稱為 <a href="/blog/llm/knowledge-cards/base-model/" data-link-title="Base Model" data-link-desc="未經指令微調的原始模型：擅長文字接龍、適合下游微調用途">base model</a>、是後續 <a href="/blog/llm/knowledge-cards/sft/" data-link-title="SFT（Supervised Fine-Tuning）" data-link-desc="在 base model 上用「指令-回答」對資料微調、讓模型會跟著指令走">SFT</a> / <a href="/blog/llm/knowledge-cards/rlhf/" data-link-title="RLHF" data-link-desc="Reinforcement Learning from Human Feedback：用人類偏好訓練的 reward model 透過 RL 對齊 LLM">RLHF</a> 的起點。Pre-training 是 LLM 三階段訓練流程中<strong>最貴、最耗時、最決定模型上限</strong>的階段。</p>
<h2 id="概念位置">概念位置</h2>
<p>Pre-training 在 LLM 訓練 pipeline 的位置：</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="ln">1</span><span class="cl">[網路文字 / 書籍 / code / 論文]（trillion token 級）
</span></span><span class="line"><span class="ln">2</span><span class="cl">   ↓ Pre-training（next-token prediction、cross-entropy loss）
</span></span><span class="line"><span class="ln">3</span><span class="cl">[Base model]：會接龍但不會對話
</span></span><span class="line"><span class="ln">4</span><span class="cl">   ↓ SFT（指令-回答對資料）
</span></span><span class="line"><span class="ln">5</span><span class="cl">[Instruction-tuned model]：會跟指令走
</span></span><span class="line"><span class="ln">6</span><span class="cl">   ↓ RLHF / DPO（人類偏好資料）
</span></span><span class="line"><span class="ln">7</span><span class="cl">[Aligned model]：對話風格 / 安全性對齊</span></span></code></pre></div><p>Pre-training 的特性：</p>
<table>
  <thead>
      <tr>
          <th>維度</th>
          <th>典型數字（2026 年主流大模型）</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>資料量</td>
          <td>數兆 token（Common Crawl、RefinedWeb、The Pile、Stack 等）</td>
      </tr>
      <tr>
          <td>GPU 用量</td>
          <td>數百到數萬張 H100 / B200、並行訓練</td>
      </tr>
      <tr>
          <td>訓練時間</td>
          <td>數週到數月</td>
      </tr>
      <tr>
          <td>成本級別</td>
          <td>數百萬到數億美元</td>
      </tr>
      <tr>
          <td>Loss</td>
          <td><a href="/blog/llm/knowledge-cards/cross-entropy/" data-link-title="Cross-Entropy" data-link-desc="衡量「預測機率分佈」跟「真實分佈」距離的指標、LLM 預訓練的主要 loss">Cross-entropy</a> on next-token</td>
      </tr>
      <tr>
          <td>結果</td>
          <td>「會接龍」的 <a href="/blog/llm/knowledge-cards/base-model/" data-link-title="Base Model" data-link-desc="未經指令微調的原始模型：擅長文字接龍、適合下游微調用途">base model</a>、可用 <a href="/blog/llm/knowledge-cards/perplexity/" data-link-title="Perplexity" data-link-desc="cross-entropy 的指數形式、直覺意義為「模型平均覺得下個 token 有多少種可能」">perplexity</a> 評估</td>
      </tr>
  </tbody>
</table>
<h2 id="設計責任">設計責任</h2>
<p>理解 pre-training 後可以判讀幾件事：模型的「世界知識」絕大部分在 pre-training 時就決定了、<a href="/blog/llm/knowledge-cards/sft/" data-link-title="SFT（Supervised Fine-Tuning）" data-link-desc="在 base model 上用「指令-回答」對資料微調、讓模型會跟著指令走">SFT</a> / <a href="/blog/llm/knowledge-cards/rlhf/" data-link-title="RLHF" data-link-desc="Reinforcement Learning from Human Feedback：用人類偏好訓練的 reward model 透過 RL 對齊 LLM">RLHF</a> 只是「教模型怎麼用這些知識回答」、不會大幅增加新知識；模型 cutoff date 就是 pre-training 資料的截止；想做新領域知識引入、<a href="/blog/llm/knowledge-cards/rag/" data-link-title="RAG" data-link-desc="Retrieval-Augmented Generation：動態外掛知識給 LLM、繞開模型參數記憶的靜態限制">RAG</a> 比繼續 fine-tune 划算（pre-training 太貴、且 fine-tune 容易讓既有能力退化）。</p>
]]></content:encoded></item><item><title>Prefix Cache</title><link>https://tarrragon.github.io/blog/llm/knowledge-cards/prefix-cache/</link><pubDate>Tue, 12 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/llm/knowledge-cards/prefix-cache/</guid><description>&lt;p>Prefix Cache 的核心概念是「當多個請求共用相同的前綴 prompt（如同一 system prompt、同一 few-shot 範例）、把該前綴的 &lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/kv-cache/" data-link-title="KV Cache" data-link-desc="已處理 token 的 attention 中間結果暫存：避免重算、加速後續生成">KV cache&lt;/a> 算一次、後續請求共用、省下重複 &lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/prefill/" data-link-title="Prefill" data-link-desc="Prompt 首次處理時的計算階段：把整段輸入跑過模型、產生 KV cache">prefill&lt;/a> 算力」。是 production LLM 服務的常見優化、能大幅降低 latency 跟成本；但在多租戶場景下、跨租戶共用 prefix cache 是直接的隱私洩漏面。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>Prefix Cache 在推論流程中的角色：&lt;/p>





&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-text" data-lang="text">&lt;span class="line">&lt;span class="ln">1&lt;/span>&lt;span class="cl">傳統推論：
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">2&lt;/span>&lt;span class="cl"> Request A：system prompt + user A → 完整 prefill → 生成
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">3&lt;/span>&lt;span class="cl"> Request B：system prompt + user B → 完整 prefill → 生成
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">4&lt;/span>&lt;span class="cl"> ↑ 重複算 system prompt
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">5&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">6&lt;/span>&lt;span class="cl">開啟 Prefix Cache：
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">7&lt;/span>&lt;span class="cl"> Request A：system prompt + user A → prefill 整段、cache 共用 prefix
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">8&lt;/span>&lt;span class="cl"> Request B：system prompt + user B → 重用 cache 的 system prefix + 只 prefill user B → 生成
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">9&lt;/span>&lt;span class="cl"> ↑ 省下 system prompt 的 prefill 算力&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>效益對應的場景：&lt;/p>
&lt;table>
 &lt;thead>
 &lt;tr>
 &lt;th>場景&lt;/th>
 &lt;th>效益&lt;/th>
 &lt;/tr>
 &lt;/thead>
 &lt;tbody>
 &lt;tr>
 &lt;td>同 system prompt、不同 user message&lt;/td>
 &lt;td>prefill 算力大幅省&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>同 few-shot 例子、不同 query&lt;/td>
 &lt;td>prefill 算力大幅省&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>長 RAG context 共用、不同問題&lt;/td>
 &lt;td>prefill 算力大幅省&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>完全獨立的請求（無共用前綴）&lt;/td>
 &lt;td>無效益&lt;/td>
 &lt;/tr>
 &lt;/tbody>
&lt;/table>
&lt;p>主流推論引擎的支援度（依版本變化）：vLLM、SGLang、llama.cpp 等都有 prefix cache 機制、命名各異。&lt;/p>
&lt;blockquote>
&lt;p>&lt;strong>事實查核註&lt;/strong>：prefix cache 的命名、設定方式、tenant 隔離預設行為依推論引擎跟版本差異大、引用前以對應引擎的官方文件為準（如 &lt;a href="https://docs.vllm.ai/">vLLM Automatic Prefix Caching&lt;/a>、SGLang RadixAttention 等）。&lt;/p>&lt;/blockquote>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>理解 prefix cache 後可以解釋兩個現象：為什麼 production LLM 服務的 latency 在啟用 prefix cache 後大幅下降（system prompt 不再每次重算）、為什麼 prefix cache 在多租戶場景是隱私風險（A 租戶的 prefix 可能被 B 看到、見 &lt;a href="https://tarrragon.github.io/blog/backend/07-security-data-protection/llm-multi-tenant-isolation/" data-link-title="LLM 多租戶推論隔離" data-link-desc="production LLM 服務的多租戶隔離：KV cache 不共享、log / model artifact 隔離、跨用戶 prompt 洩漏面">llm-multi-tenant-isolation&lt;/a>）。&lt;/p>
&lt;p>production 設計時、prefix cache 應該按 tenant 分桶、同 tenant 內可共用、跨 tenant 必須隔離。隔離邊界對齊 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/tenant-boundary/" data-link-title="Tenant Boundary" data-link-desc="說明多租戶系統如何隔離不同客戶或組織的資料與資源">tenant-boundary&lt;/a> 卡片的設計。&lt;/p></description><content:encoded><![CDATA[<p>Prefix Cache 的核心概念是「當多個請求共用相同的前綴 prompt（如同一 system prompt、同一 few-shot 範例）、把該前綴的 <a href="/blog/llm/knowledge-cards/kv-cache/" data-link-title="KV Cache" data-link-desc="已處理 token 的 attention 中間結果暫存：避免重算、加速後續生成">KV cache</a> 算一次、後續請求共用、省下重複 <a href="/blog/llm/knowledge-cards/prefill/" data-link-title="Prefill" data-link-desc="Prompt 首次處理時的計算階段：把整段輸入跑過模型、產生 KV cache">prefill</a> 算力」。是 production LLM 服務的常見優化、能大幅降低 latency 跟成本；但在多租戶場景下、跨租戶共用 prefix cache 是直接的隱私洩漏面。</p>
<h2 id="概念位置">概念位置</h2>
<p>Prefix Cache 在推論流程中的角色：</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="ln">1</span><span class="cl">傳統推論：
</span></span><span class="line"><span class="ln">2</span><span class="cl">  Request A：system prompt + user A → 完整 prefill → 生成
</span></span><span class="line"><span class="ln">3</span><span class="cl">  Request B：system prompt + user B → 完整 prefill → 生成
</span></span><span class="line"><span class="ln">4</span><span class="cl">                                       ↑ 重複算 system prompt
</span></span><span class="line"><span class="ln">5</span><span class="cl">
</span></span><span class="line"><span class="ln">6</span><span class="cl">開啟 Prefix Cache：
</span></span><span class="line"><span class="ln">7</span><span class="cl">  Request A：system prompt + user A → prefill 整段、cache 共用 prefix
</span></span><span class="line"><span class="ln">8</span><span class="cl">  Request B：system prompt + user B → 重用 cache 的 system prefix + 只 prefill user B → 生成
</span></span><span class="line"><span class="ln">9</span><span class="cl">                                       ↑ 省下 system prompt 的 prefill 算力</span></span></code></pre></div><p>效益對應的場景：</p>
<table>
  <thead>
      <tr>
          <th>場景</th>
          <th>效益</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>同 system prompt、不同 user message</td>
          <td>prefill 算力大幅省</td>
      </tr>
      <tr>
          <td>同 few-shot 例子、不同 query</td>
          <td>prefill 算力大幅省</td>
      </tr>
      <tr>
          <td>長 RAG context 共用、不同問題</td>
          <td>prefill 算力大幅省</td>
      </tr>
      <tr>
          <td>完全獨立的請求（無共用前綴）</td>
          <td>無效益</td>
      </tr>
  </tbody>
</table>
<p>主流推論引擎的支援度（依版本變化）：vLLM、SGLang、llama.cpp 等都有 prefix cache 機制、命名各異。</p>
<blockquote>
<p><strong>事實查核註</strong>：prefix cache 的命名、設定方式、tenant 隔離預設行為依推論引擎跟版本差異大、引用前以對應引擎的官方文件為準（如 <a href="https://docs.vllm.ai/">vLLM Automatic Prefix Caching</a>、SGLang RadixAttention 等）。</p></blockquote>
<h2 id="設計責任">設計責任</h2>
<p>理解 prefix cache 後可以解釋兩個現象：為什麼 production LLM 服務的 latency 在啟用 prefix cache 後大幅下降（system prompt 不再每次重算）、為什麼 prefix cache 在多租戶場景是隱私風險（A 租戶的 prefix 可能被 B 看到、見 <a href="/blog/backend/07-security-data-protection/llm-multi-tenant-isolation/" data-link-title="LLM 多租戶推論隔離" data-link-desc="production LLM 服務的多租戶隔離：KV cache 不共享、log / model artifact 隔離、跨用戶 prompt 洩漏面">llm-multi-tenant-isolation</a>）。</p>
<p>production 設計時、prefix cache 應該按 tenant 分桶、同 tenant 內可共用、跨 tenant 必須隔離。隔離邊界對齊 <a href="/blog/backend/knowledge-cards/tenant-boundary/" data-link-title="Tenant Boundary" data-link-desc="說明多租戶系統如何隔離不同客戶或組織的資料與資源">tenant-boundary</a> 卡片的設計。</p>
]]></content:encoded></item><item><title>Prompt Cache</title><link>https://tarrragon.github.io/blog/llm/knowledge-cards/prompt-cache/</link><pubDate>Tue, 12 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/llm/knowledge-cards/prompt-cache/</guid><description>&lt;p>Prompt cache 的核心概念是「&lt;strong>LLM 服務端 / 推論伺服器把重複出現的 prompt prefix（如 system prompt + tool schema）的 &lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/kv-cache/" data-link-title="KV Cache" data-link-desc="已處理 token 的 attention 中間結果暫存：避免重算、加速後續生成">KV cache&lt;/a> 暫存起來、後續 query 跳過該 prefix 的 &lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/prefill/" data-link-title="Prefill" data-link-desc="Prompt 首次處理時的計算階段：把整段輸入跑過模型、產生 KV cache">prefill&lt;/a> 階段&lt;/strong>」。Anthropic / OpenAI / Bedrock / Gemini 都提供、最高 90% cost 折扣 + 13-31% &lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/ttft/" data-link-title="TTFT" data-link-desc="Time To First Token：送出 prompt 到第一個 token 出現的等待時間">TTFT&lt;/a> 改善、是 coding agent / long-context 應用的核心 cost / latency 槓桿。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>跟既有 cache 概念的層次：&lt;/p>
&lt;table>
 &lt;thead>
 &lt;tr>
 &lt;th>Cache 層&lt;/th>
 &lt;th>範圍&lt;/th>
 &lt;th>機制&lt;/th>
 &lt;/tr>
 &lt;/thead>
 &lt;tbody>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/kv-cache/" data-link-title="KV Cache" data-link-desc="已處理 token 的 attention 中間結果暫存：避免重算、加速後續生成">KV cache&lt;/a>&lt;/td>
 &lt;td>單一 conversation 的同一次推論&lt;/td>
 &lt;td>過去 token 的 K/V 暫存、autoregressive 才省重算&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/prefix-cache/" data-link-title="Prefix Cache" data-link-desc="把多個請求共用的前綴 prompt 的 KV cache 重用、省下重複 prefill 算力的優化、production 多用戶服務的常見設計">Prefix cache&lt;/a>&lt;/td>
 &lt;td>多 request 共用 prefix（同 server 同 model）&lt;/td>
 &lt;td>跨 request 共用 KV cache、production 推論伺服器特性&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;strong>Prompt cache（本卡）&lt;/strong>&lt;/td>
 &lt;td>跨 request 跨時間、雲端 LLM API 服務端&lt;/td>
 &lt;td>服務端把 prefix 的 KV cache 持久化、有 TTL&lt;/td>
 &lt;/tr>
 &lt;/tbody>
&lt;/table>
&lt;p>Prompt cache 的「保留範圍」跟「定價」是商業 LLM 的 product feature：&lt;/p>
&lt;table>
 &lt;thead>
 &lt;tr>
 &lt;th>服務&lt;/th>
 &lt;th>Cache TTL&lt;/th>
 &lt;th>Write cost&lt;/th>
 &lt;th>Read cost&lt;/th>
 &lt;th>觸發方式&lt;/th>
 &lt;/tr>
 &lt;/thead>
 &lt;tbody>
 &lt;tr>
 &lt;td>Anthropic（cache_control）&lt;/td>
 &lt;td>5min 預設、1h ext&lt;/td>
 &lt;td>1.25× 原價&lt;/td>
 &lt;td>0.1× 原價（90% 折扣）&lt;/td>
 &lt;td>明確 cache_control breakpoint&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>OpenAI&lt;/td>
 &lt;td>自動（隱式）&lt;/td>
 &lt;td>同原價&lt;/td>
 &lt;td>0.5× 原價（50% 折扣）&lt;/td>
 &lt;td>自動偵測重複 prefix（&amp;gt; 1024 token）&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>Bedrock（Anthropic）&lt;/td>
 &lt;td>5min&lt;/td>
 &lt;td>同 Anthropic&lt;/td>
 &lt;td>同上&lt;/td>
 &lt;td>同 Anthropic&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>Gemini&lt;/td>
 &lt;td>自動 + explicit&lt;/td>
 &lt;td>視方案&lt;/td>
 &lt;td>視方案&lt;/td>
 &lt;td>implicit + context caching API&lt;/td>
 &lt;/tr>
 &lt;/tbody>
&lt;/table>
&lt;blockquote>
&lt;p>&lt;strong>事實查核註&lt;/strong>：定價跟 TTL 隨時間更新、引用前以對應 vendor 當前文件為準。&lt;/p>&lt;/blockquote>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>讀 LLM API docs / coding agent 設計 / cost optimization blog 看到「prompt cache」「context caching」「cache_control」就是這機制。寫 code 場景的判讀：&lt;/p></description><content:encoded><![CDATA[<p>Prompt cache 的核心概念是「<strong>LLM 服務端 / 推論伺服器把重複出現的 prompt prefix（如 system prompt + tool schema）的 <a href="/blog/llm/knowledge-cards/kv-cache/" data-link-title="KV Cache" data-link-desc="已處理 token 的 attention 中間結果暫存：避免重算、加速後續生成">KV cache</a> 暫存起來、後續 query 跳過該 prefix 的 <a href="/blog/llm/knowledge-cards/prefill/" data-link-title="Prefill" data-link-desc="Prompt 首次處理時的計算階段：把整段輸入跑過模型、產生 KV cache">prefill</a> 階段</strong>」。Anthropic / OpenAI / Bedrock / Gemini 都提供、最高 90% cost 折扣 + 13-31% <a href="/blog/llm/knowledge-cards/ttft/" data-link-title="TTFT" data-link-desc="Time To First Token：送出 prompt 到第一個 token 出現的等待時間">TTFT</a> 改善、是 coding agent / long-context 應用的核心 cost / latency 槓桿。</p>
<h2 id="概念位置">概念位置</h2>
<p>跟既有 cache 概念的層次：</p>
<table>
  <thead>
      <tr>
          <th>Cache 層</th>
          <th>範圍</th>
          <th>機制</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td><a href="/blog/llm/knowledge-cards/kv-cache/" data-link-title="KV Cache" data-link-desc="已處理 token 的 attention 中間結果暫存：避免重算、加速後續生成">KV cache</a></td>
          <td>單一 conversation 的同一次推論</td>
          <td>過去 token 的 K/V 暫存、autoregressive 才省重算</td>
      </tr>
      <tr>
          <td><a href="/blog/llm/knowledge-cards/prefix-cache/" data-link-title="Prefix Cache" data-link-desc="把多個請求共用的前綴 prompt 的 KV cache 重用、省下重複 prefill 算力的優化、production 多用戶服務的常見設計">Prefix cache</a></td>
          <td>多 request 共用 prefix（同 server 同 model）</td>
          <td>跨 request 共用 KV cache、production 推論伺服器特性</td>
      </tr>
      <tr>
          <td><strong>Prompt cache（本卡）</strong></td>
          <td>跨 request 跨時間、雲端 LLM API 服務端</td>
          <td>服務端把 prefix 的 KV cache 持久化、有 TTL</td>
      </tr>
  </tbody>
</table>
<p>Prompt cache 的「保留範圍」跟「定價」是商業 LLM 的 product feature：</p>
<table>
  <thead>
      <tr>
          <th>服務</th>
          <th>Cache TTL</th>
          <th>Write cost</th>
          <th>Read cost</th>
          <th>觸發方式</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>Anthropic（cache_control）</td>
          <td>5min 預設、1h ext</td>
          <td>1.25× 原價</td>
          <td>0.1× 原價（90% 折扣）</td>
          <td>明確 cache_control breakpoint</td>
      </tr>
      <tr>
          <td>OpenAI</td>
          <td>自動（隱式）</td>
          <td>同原價</td>
          <td>0.5× 原價（50% 折扣）</td>
          <td>自動偵測重複 prefix（&gt; 1024 token）</td>
      </tr>
      <tr>
          <td>Bedrock（Anthropic）</td>
          <td>5min</td>
          <td>同 Anthropic</td>
          <td>同上</td>
          <td>同 Anthropic</td>
      </tr>
      <tr>
          <td>Gemini</td>
          <td>自動 + explicit</td>
          <td>視方案</td>
          <td>視方案</td>
          <td>implicit + context caching API</td>
      </tr>
  </tbody>
</table>
<blockquote>
<p><strong>事實查核註</strong>：定價跟 TTL 隨時間更新、引用前以對應 vendor 當前文件為準。</p></blockquote>
<h2 id="設計責任">設計責任</h2>
<p>讀 LLM API docs / coding agent 設計 / cost optimization blog 看到「prompt cache」「context caching」「cache_control」就是這機制。寫 code 場景的判讀：</p>
<ol>
<li><strong>誰最值得開</strong>：coding agent（system prompt + tool schema 經常 &gt; 10K token、每 turn 重用）、long-context RAG（檢索 chunks 重用）、long conversation（history 累積）</li>
<li><strong>設計原則</strong>：把不變的內容（system prompt、tool schema、固定文件）放 prefix；變動的（user query、最新 file content）放後面</li>
<li><strong>常見 anti-pattern</strong>：在 prefix 插入 timestamp / user-id / request-id → 每次 prefix 不同 → cache 從不命中、付 1.25× write cost 沒得回本</li>
<li><strong>5 分鐘 TTL 的意涵</strong>：query 之間間隔 &gt; 5 分鐘、cache 已 expire、要 1h ext TTL 才能撐長對話</li>
<li><strong>跟 <a href="/blog/llm/knowledge-cards/context-budget/" data-link-title="Context Budget" data-link-desc="Coding agent 的 context window 拆分配額：system prompt &#43; tool schema &#43; history &#43; file content &#43; reasoning &#43; tool result 各佔多少、留多少 margin">context budget</a> 的關係</strong>：cache 攤平 scaffold 部分的 cost、所以可以放寬「scaffold ≤ 25%」的成本顧慮、focus 在「不超 context limit」即可</li>
</ol>
]]></content:encoded></item><item><title>Prompt Injection</title><link>https://tarrragon.github.io/blog/llm/knowledge-cards/prompt-injection/</link><pubDate>Tue, 12 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/llm/knowledge-cards/prompt-injection/</guid><description>&lt;p>Prompt injection 的核心概念是「攻擊者把惡意指令藏進 LLM 會讀到的內容（檔案、網頁、issue、tool 回傳）、誘導 LLM 忽略原本的 &lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/system-prompt/" data-link-title="System Prompt" data-link-desc="LLM application 中由開發者預設、不直接顯示給使用者的指令層、定義模型的角色、行為規範、輸出格式">system prompt&lt;/a>、改執行攻擊者意圖的動作」。OWASP &lt;a href="https://owasp.org/www-project-top-10-for-large-language-model-applications/">LLM Top 10&lt;/a> 把它列為 LLM01、是 LLM application 安全的頭號威脅。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>Prompt injection 的兩種主要形態：&lt;/p>
&lt;table>
 &lt;thead>
 &lt;tr>
 &lt;th>形態&lt;/th>
 &lt;th>描述&lt;/th>
 &lt;th>個人 dev 場景的觸發路徑&lt;/th>
 &lt;/tr>
 &lt;/thead>
 &lt;tbody>
 &lt;tr>
 &lt;td>Direct injection&lt;/td>
 &lt;td>使用者自己 prompt 內含惡意指令&lt;/td>
 &lt;td>較少發生、主要是測試場景&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>Indirect injection&lt;/td>
 &lt;td>LLM 讀到的別人內容含惡意指令&lt;/td>
 &lt;td>主要威脅形態&lt;/td>
 &lt;/tr>
 &lt;/tbody>
&lt;/table>
&lt;p>Indirect injection 的常見入口：&lt;/p>
&lt;ol>
&lt;li>&lt;strong>檔案內容&lt;/strong>：codebase 中的 README、依賴的 package README、PDF / Word 文件&lt;/li>
&lt;li>&lt;strong>Web 內容&lt;/strong>：tool 抓的網頁、社群留言、PR 描述&lt;/li>
&lt;li>&lt;strong>tool 回傳結果&lt;/strong>：DB 查詢結果、API response、其他 service 回傳&lt;/li>
&lt;li>&lt;strong>使用者貼上內容&lt;/strong>：從外部複製貼上、帶進惡意 prompt&lt;/li>
&lt;li>&lt;strong>agent 自我循環中累積&lt;/strong>：sub-agent 回傳、長 agent loop 中前段 injection 影響後段&lt;/li>
&lt;/ol>
&lt;blockquote>
&lt;p>&lt;strong>事實查核註&lt;/strong>：prompt injection 的攻擊形態跟研究進展快速演進、本卡描述參考 &lt;a href="https://owasp.org/www-project-top-10-for-large-language-model-applications/">OWASP LLM Top 10 LLM01&lt;/a> 跟 Greshake et al. 的「Indirect Prompt Injection」論文、引用前以對應的最新版本為準。&lt;/p>&lt;/blockquote>
&lt;p>實際造成影響的不是 injection 本身、是 LLM 輸出後的下游動作：&lt;/p>





&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-text" data-lang="text">&lt;span class="line">&lt;span class="ln">1&lt;/span>&lt;span class="cl">injection → LLM 輸出 → 下游動作（這裡才是真正攻擊面）
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">2&lt;/span>&lt;span class="cl"> ├── 使用者照建議貼到 shell 跑
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">3&lt;/span>&lt;span class="cl"> ├── tool use 自動執行
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">4&lt;/span>&lt;span class="cl"> ├── 寫進 commit / 文件
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">5&lt;/span>&lt;span class="cl"> └── 觸發下一個 agent&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>理解 prompt injection 後可以解釋兩個現象：為什麼「擋住 injection」對 production LLM application 是不切實際的目標（外部內容會持續引入）、為什麼防禦重點應該放在「下游動作的可逆性 + review checkpoint」（injection 不可完全擋住、但後果可以收斂）。&lt;/p>
&lt;p>防禦設計的層次：&lt;/p>
&lt;ol>
&lt;li>&lt;strong>降低觸發率&lt;/strong>：明確標記 untrusted 內容、強化模型對齊（vendor 端責任）。&lt;/li>
&lt;li>&lt;strong>限制能力上限&lt;/strong>：&lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/tool-use/" data-link-title="Tool Use" data-link-desc="LLM 透過結構化呼叫外部工具（讀檔、查資料庫、發 API request）來擴展能力的設計、function calling 跟 MCP 是常見實作">tool use&lt;/a> 白名單、副作用可逆性、agent loop 步數限制。&lt;/li>
&lt;li>&lt;strong>後果可控&lt;/strong>：人為 review checkpoint、自動偵測異常（見 &lt;a href="https://tarrragon.github.io/blog/backend/07-security-data-protection/llm-as-service-detection-coverage/" data-link-title="LLM Service 偵測訊號覆蓋" data-link-desc="production LLM 服務的 detection 訊號設計：tool call 異常模式、prompt injection 觸發徵兆、abuse 跟濫用模式、跟既有 detection-coverage 框架的接合">LLM Service 偵測訊號覆蓋&lt;/a>）。&lt;/li>
&lt;/ol>
&lt;p>詳見 &lt;a href="https://tarrragon.github.io/blog/llm/06-security/prompt-injection-in-ide/" data-link-title="6.3 IDE 場景的 prompt injection" data-link-desc="個人 dev 場景下 IDE 寫 code 工作流的 prompt injection：codebase 內容、外部文件、剪貼簿作為攻擊面、跟雲端 LLM 場景的差異">6.3 IDE 場景的 prompt injection&lt;/a> 跟 &lt;a href="https://tarrragon.github.io/blog/backend/07-security-data-protection/llm-prompt-injection-in-agent/" data-link-title="LLM Agent Prompt Injection 後果治理" data-link-desc="production LLM agent 場景的 prompt injection 後果：tool spec 設計、agent loop 限制、review checkpoint、跟 incident workflow 的接合">LLM Agent Prompt Injection 後果治理&lt;/a>。&lt;/p></description><content:encoded><![CDATA[<p>Prompt injection 的核心概念是「攻擊者把惡意指令藏進 LLM 會讀到的內容（檔案、網頁、issue、tool 回傳）、誘導 LLM 忽略原本的 <a href="/blog/llm/knowledge-cards/system-prompt/" data-link-title="System Prompt" data-link-desc="LLM application 中由開發者預設、不直接顯示給使用者的指令層、定義模型的角色、行為規範、輸出格式">system prompt</a>、改執行攻擊者意圖的動作」。OWASP <a href="https://owasp.org/www-project-top-10-for-large-language-model-applications/">LLM Top 10</a> 把它列為 LLM01、是 LLM application 安全的頭號威脅。</p>
<h2 id="概念位置">概念位置</h2>
<p>Prompt injection 的兩種主要形態：</p>
<table>
  <thead>
      <tr>
          <th>形態</th>
          <th>描述</th>
          <th>個人 dev 場景的觸發路徑</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>Direct injection</td>
          <td>使用者自己 prompt 內含惡意指令</td>
          <td>較少發生、主要是測試場景</td>
      </tr>
      <tr>
          <td>Indirect injection</td>
          <td>LLM 讀到的別人內容含惡意指令</td>
          <td>主要威脅形態</td>
      </tr>
  </tbody>
</table>
<p>Indirect injection 的常見入口：</p>
<ol>
<li><strong>檔案內容</strong>：codebase 中的 README、依賴的 package README、PDF / Word 文件</li>
<li><strong>Web 內容</strong>：tool 抓的網頁、社群留言、PR 描述</li>
<li><strong>tool 回傳結果</strong>：DB 查詢結果、API response、其他 service 回傳</li>
<li><strong>使用者貼上內容</strong>：從外部複製貼上、帶進惡意 prompt</li>
<li><strong>agent 自我循環中累積</strong>：sub-agent 回傳、長 agent loop 中前段 injection 影響後段</li>
</ol>
<blockquote>
<p><strong>事實查核註</strong>：prompt injection 的攻擊形態跟研究進展快速演進、本卡描述參考 <a href="https://owasp.org/www-project-top-10-for-large-language-model-applications/">OWASP LLM Top 10 LLM01</a> 跟 Greshake et al. 的「Indirect Prompt Injection」論文、引用前以對應的最新版本為準。</p></blockquote>
<p>實際造成影響的不是 injection 本身、是 LLM 輸出後的下游動作：</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="ln">1</span><span class="cl">injection → LLM 輸出 → 下游動作（這裡才是真正攻擊面）
</span></span><span class="line"><span class="ln">2</span><span class="cl">                       ├── 使用者照建議貼到 shell 跑
</span></span><span class="line"><span class="ln">3</span><span class="cl">                       ├── tool use 自動執行
</span></span><span class="line"><span class="ln">4</span><span class="cl">                       ├── 寫進 commit / 文件
</span></span><span class="line"><span class="ln">5</span><span class="cl">                       └── 觸發下一個 agent</span></span></code></pre></div><h2 id="設計責任">設計責任</h2>
<p>理解 prompt injection 後可以解釋兩個現象：為什麼「擋住 injection」對 production LLM application 是不切實際的目標（外部內容會持續引入）、為什麼防禦重點應該放在「下游動作的可逆性 + review checkpoint」（injection 不可完全擋住、但後果可以收斂）。</p>
<p>防禦設計的層次：</p>
<ol>
<li><strong>降低觸發率</strong>：明確標記 untrusted 內容、強化模型對齊（vendor 端責任）。</li>
<li><strong>限制能力上限</strong>：<a href="/blog/llm/knowledge-cards/tool-use/" data-link-title="Tool Use" data-link-desc="LLM 透過結構化呼叫外部工具（讀檔、查資料庫、發 API request）來擴展能力的設計、function calling 跟 MCP 是常見實作">tool use</a> 白名單、副作用可逆性、agent loop 步數限制。</li>
<li><strong>後果可控</strong>：人為 review checkpoint、自動偵測異常（見 <a href="/blog/backend/07-security-data-protection/llm-as-service-detection-coverage/" data-link-title="LLM Service 偵測訊號覆蓋" data-link-desc="production LLM 服務的 detection 訊號設計：tool call 異常模式、prompt injection 觸發徵兆、abuse 跟濫用模式、跟既有 detection-coverage 框架的接合">LLM Service 偵測訊號覆蓋</a>）。</li>
</ol>
<p>詳見 <a href="/blog/llm/06-security/prompt-injection-in-ide/" data-link-title="6.3 IDE 場景的 prompt injection" data-link-desc="個人 dev 場景下 IDE 寫 code 工作流的 prompt injection：codebase 內容、外部文件、剪貼簿作為攻擊面、跟雲端 LLM 場景的差異">6.3 IDE 場景的 prompt injection</a> 跟 <a href="/blog/backend/07-security-data-protection/llm-prompt-injection-in-agent/" data-link-title="LLM Agent Prompt Injection 後果治理" data-link-desc="production LLM agent 場景的 prompt injection 後果：tool spec 設計、agent loop 限制、review checkpoint、跟 incident workflow 的接合">LLM Agent Prompt Injection 後果治理</a>。</p>
]]></content:encoded></item><item><title>QLoRA</title><link>https://tarrragon.github.io/blog/llm/knowledge-cards/qlora/</link><pubDate>Tue, 12 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/llm/knowledge-cards/qlora/</guid><description>&lt;p>QLoRA（Quantized LoRA、Dettmers et al., 2023）的核心概念是「&lt;strong>把 base model 量化到 4-bit（凍住）+ 用 &lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/lora/" data-link-title="LoRA" data-link-desc="Low-Rank Adaptation：凍住原模型權重、只訓兩個小矩陣的 parameter-efficient fine-tuning">LoRA&lt;/a> 訓兩個小矩陣&lt;/strong>」。讓消費級 GPU（24GB VRAM）就能 fine-tune 30B-70B 模型、是現代 local fine-tuning 主流。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>QLoRA vs full fine-tuning vs LoRA 的記憶體需求對比（70B 模型）：&lt;/p>
&lt;table>
 &lt;thead>
 &lt;tr>
 &lt;th>方法&lt;/th>
 &lt;th>Base model 精度&lt;/th>
 &lt;th>訓練記憶體&lt;/th>
 &lt;th>適合硬體&lt;/th>
 &lt;/tr>
 &lt;/thead>
 &lt;tbody>
 &lt;tr>
 &lt;td>Full fine-tuning&lt;/td>
 &lt;td>BF16&lt;/td>
 &lt;td>~280 GB&lt;/td>
 &lt;td>多卡 H100&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>LoRA&lt;/td>
 &lt;td>BF16&lt;/td>
 &lt;td>~150 GB&lt;/td>
 &lt;td>多卡 A100 / H100&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;strong>QLoRA&lt;/strong>&lt;/td>
 &lt;td>4-bit (NF4)&lt;/td>
 &lt;td>&lt;strong>~40 GB&lt;/strong>&lt;/td>
 &lt;td>單張 A100 80GB / 雙 24GB GPU&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>QLoRA on 7B&lt;/td>
 &lt;td>4-bit&lt;/td>
 &lt;td>~6-8 GB&lt;/td>
 &lt;td>消費級 16GB+ GPU&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>QLoRA on 30-32B&lt;/td>
 &lt;td>4-bit&lt;/td>
 &lt;td>~20-24 GB&lt;/td>
 &lt;td>消費級 24GB+ GPU（5090）&lt;/td>
 &lt;/tr>
 &lt;/tbody>
&lt;/table>
&lt;p>QLoRA 的核心創新（簡化）：&lt;/p>
&lt;ol>
&lt;li>&lt;strong>4-bit NormalFloat（NF4）量化&lt;/strong>：base model 用 4-bit 表示、精度損失低於原 INT4&lt;/li>
&lt;li>&lt;strong>Double quantization&lt;/strong>：量化常數本身也量化、再省一點記憶體&lt;/li>
&lt;li>&lt;strong>Paged optimizer&lt;/strong>：optimizer state 跑 CPU offload、避免訓練 spike OOM&lt;/li>
&lt;li>&lt;strong>LoRA on 4-bit base&lt;/strong>：&lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/lora/" data-link-title="LoRA" data-link-desc="Low-Rank Adaptation：凍住原模型權重、只訓兩個小矩陣的 parameter-efficient fine-tuning">LoRA&lt;/a> 訓的 A、B 矩陣仍是 BF16、只有 base 是 4-bit、推論時 dequantize → 加 LoRA → forward&lt;/li>
&lt;/ol>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>讀 fine-tuning 教學 / Hugging Face PEFT 文件看到「QLoRA」「bnb-4bit」就是這方法。寫 code 場景的判讀：&lt;/p>
&lt;ol>
&lt;li>&lt;strong>想 fine-tune 大模型在消費級硬體&lt;/strong>：QLoRA 是 default 選擇（不用 QLoRA、就只能訓 &amp;lt; 7B）&lt;/li>
&lt;li>&lt;strong>記憶體預算估算&lt;/strong>：QLoRA 訓 N B 模型約需 &lt;code>0.6 × N GB&lt;/code> VRAM（30B → ~18GB、70B → ~42GB）&lt;/li>
&lt;li>&lt;strong>品質 vs full fine-tune 差距&lt;/strong>：QLoRA 後合併權重的模型、實測跟 full fine-tune 接近（差距 &amp;lt; 2-3%）、對多數場景可接受&lt;/li>
&lt;li>&lt;strong>跟 &lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/lora/" data-link-title="LoRA" data-link-desc="Low-Rank Adaptation：凍住原模型權重、只訓兩個小矩陣的 parameter-efficient fine-tuning">LoRA&lt;/a> 卡片區分&lt;/strong>：純 LoRA 是「base 不量化、訓 LoRA」、QLoRA 是「base 量化 4-bit、訓 LoRA」；QLoRA 是 LoRA 的延伸、不是替代&lt;/li>
&lt;li>&lt;strong>推論時的選擇&lt;/strong>：QLoRA fine-tuned 模型可以「base 仍 4-bit + 載入 LoRA adapter」推論、記憶體用量低；也可以 merge 後用 GGUF Q4_K_M、跟 base 原相同&lt;/li>
&lt;/ol></description><content:encoded><![CDATA[<p>QLoRA（Quantized LoRA、Dettmers et al., 2023）的核心概念是「<strong>把 base model 量化到 4-bit（凍住）+ 用 <a href="/blog/llm/knowledge-cards/lora/" data-link-title="LoRA" data-link-desc="Low-Rank Adaptation：凍住原模型權重、只訓兩個小矩陣的 parameter-efficient fine-tuning">LoRA</a> 訓兩個小矩陣</strong>」。讓消費級 GPU（24GB VRAM）就能 fine-tune 30B-70B 模型、是現代 local fine-tuning 主流。</p>
<h2 id="概念位置">概念位置</h2>
<p>QLoRA vs full fine-tuning vs LoRA 的記憶體需求對比（70B 模型）：</p>
<table>
  <thead>
      <tr>
          <th>方法</th>
          <th>Base model 精度</th>
          <th>訓練記憶體</th>
          <th>適合硬體</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>Full fine-tuning</td>
          <td>BF16</td>
          <td>~280 GB</td>
          <td>多卡 H100</td>
      </tr>
      <tr>
          <td>LoRA</td>
          <td>BF16</td>
          <td>~150 GB</td>
          <td>多卡 A100 / H100</td>
      </tr>
      <tr>
          <td><strong>QLoRA</strong></td>
          <td>4-bit (NF4)</td>
          <td><strong>~40 GB</strong></td>
          <td>單張 A100 80GB / 雙 24GB GPU</td>
      </tr>
      <tr>
          <td>QLoRA on 7B</td>
          <td>4-bit</td>
          <td>~6-8 GB</td>
          <td>消費級 16GB+ GPU</td>
      </tr>
      <tr>
          <td>QLoRA on 30-32B</td>
          <td>4-bit</td>
          <td>~20-24 GB</td>
          <td>消費級 24GB+ GPU（5090）</td>
      </tr>
  </tbody>
</table>
<p>QLoRA 的核心創新（簡化）：</p>
<ol>
<li><strong>4-bit NormalFloat（NF4）量化</strong>：base model 用 4-bit 表示、精度損失低於原 INT4</li>
<li><strong>Double quantization</strong>：量化常數本身也量化、再省一點記憶體</li>
<li><strong>Paged optimizer</strong>：optimizer state 跑 CPU offload、避免訓練 spike OOM</li>
<li><strong>LoRA on 4-bit base</strong>：<a href="/blog/llm/knowledge-cards/lora/" data-link-title="LoRA" data-link-desc="Low-Rank Adaptation：凍住原模型權重、只訓兩個小矩陣的 parameter-efficient fine-tuning">LoRA</a> 訓的 A、B 矩陣仍是 BF16、只有 base 是 4-bit、推論時 dequantize → 加 LoRA → forward</li>
</ol>
<h2 id="設計責任">設計責任</h2>
<p>讀 fine-tuning 教學 / Hugging Face PEFT 文件看到「QLoRA」「bnb-4bit」就是這方法。寫 code 場景的判讀：</p>
<ol>
<li><strong>想 fine-tune 大模型在消費級硬體</strong>：QLoRA 是 default 選擇（不用 QLoRA、就只能訓 &lt; 7B）</li>
<li><strong>記憶體預算估算</strong>：QLoRA 訓 N B 模型約需 <code>0.6 × N GB</code> VRAM（30B → ~18GB、70B → ~42GB）</li>
<li><strong>品質 vs full fine-tune 差距</strong>：QLoRA 後合併權重的模型、實測跟 full fine-tune 接近（差距 &lt; 2-3%）、對多數場景可接受</li>
<li><strong>跟 <a href="/blog/llm/knowledge-cards/lora/" data-link-title="LoRA" data-link-desc="Low-Rank Adaptation：凍住原模型權重、只訓兩個小矩陣的 parameter-efficient fine-tuning">LoRA</a> 卡片區分</strong>：純 LoRA 是「base 不量化、訓 LoRA」、QLoRA 是「base 量化 4-bit、訓 LoRA」；QLoRA 是 LoRA 的延伸、不是替代</li>
<li><strong>推論時的選擇</strong>：QLoRA fine-tuned 模型可以「base 仍 4-bit + 載入 LoRA adapter」推論、記憶體用量低；也可以 merge 後用 GGUF Q4_K_M、跟 base 原相同</li>
</ol>
]]></content:encoded></item><item><title>Reasoning Model</title><link>https://tarrragon.github.io/blog/llm/knowledge-cards/reasoning-model/</link><pubDate>Tue, 12 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/llm/knowledge-cards/reasoning-model/</guid><description>&lt;p>Reasoning model 的核心概念是「&lt;strong>透過後訓練（多半是 RL）讓模型自然在回答前產出長 &lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/chain-of-thought/" data-link-title="Chain-of-Thought（CoT）" data-link-desc="讓 LLM 先輸出推理步驟再給最終答案的 prompting / 訓練方式、reasoning model 的基礎機制">chain-of-thought&lt;/a> reasoning trace 的 LLM 變體&lt;/strong>」。代表是 OpenAI o1 / o3、DeepSeek-R1、Qwen-QwQ、Claude 3.7 Sonnet thinking 等。Reasoning model 是 2024-2026 LLM 的最大 paradigm shift、把 &lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/test-time-compute/" data-link-title="Test-Time Compute" data-link-desc="推論時動態增加計算量換取答案品質的 paradigm、reasoning model 跟 best-of-N 的共同基底">test-time compute&lt;/a> 變成可訓練、可 scale 的維度。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>Reasoning model 跟一般 instruction-tuned model 的差異：&lt;/p>
&lt;table>
 &lt;thead>
 &lt;tr>
 &lt;th>維度&lt;/th>
 &lt;th>Instruction-tuned model（如 Gemma 4 instruct）&lt;/th>
 &lt;th>Reasoning model（如 DeepSeek-R1）&lt;/th>
 &lt;/tr>
 &lt;/thead>
 &lt;tbody>
 &lt;tr>
 &lt;td>訓練後階段&lt;/td>
 &lt;td>SFT + RLHF / DPO&lt;/td>
 &lt;td>SFT + RLHF + &lt;strong>reasoning RL&lt;/strong>&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>推論行為&lt;/td>
 &lt;td>直接答（或短 CoT）&lt;/td>
 &lt;td>先生 reasoning trace（數百到數千 token）再答&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>適合任務&lt;/td>
 &lt;td>對話、寫作、簡單 coding、查詢&lt;/td>
 &lt;td>math、debug、algorithm、複雜 reasoning&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>Token 消耗&lt;/td>
 &lt;td>直接生答案 token&lt;/td>
 &lt;td>reasoning trace 通常 5-50× 於最終答案&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>推論成本&lt;/td>
 &lt;td>1×&lt;/td>
 &lt;td>5-20×（依任務難度）&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>Context 需求&lt;/td>
 &lt;td>一般&lt;/td>
 &lt;td>較大（要容納 reasoning trace）&lt;/td>
 &lt;/tr>
 &lt;/tbody>
&lt;/table>
&lt;p>主流 reasoning model 比較（2026/5）：&lt;/p>
&lt;table>
 &lt;thead>
 &lt;tr>
 &lt;th>模型&lt;/th>
 &lt;th>開源 / 商業&lt;/th>
 &lt;th>推理 trace 格式&lt;/th>
 &lt;th>本地跑可行性&lt;/th>
 &lt;/tr>
 &lt;/thead>
 &lt;tbody>
 &lt;tr>
 &lt;td>OpenAI o1 / o3&lt;/td>
 &lt;td>商業 API&lt;/td>
 &lt;td>對使用者隱藏&lt;/td>
 &lt;td>不可&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>DeepSeek-R1（full）&lt;/td>
 &lt;td>開源&lt;/td>
 &lt;td>&lt;code>&amp;lt;think&amp;gt;...&amp;lt;/think&amp;gt;&lt;/code> 標記&lt;/td>
 &lt;td>671B 太大、本地不實際&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>DeepSeek-R1 distill&lt;/td>
 &lt;td>開源&lt;/td>
 &lt;td>同上&lt;/td>
 &lt;td>7B / 14B / 32B distill 可在 24-48GB Mac 跑&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>Qwen-QwQ&lt;/td>
 &lt;td>開源&lt;/td>
 &lt;td>純文字 reasoning（無特殊 token）&lt;/td>
 &lt;td>32B 可在 64GB+ Mac 跑&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>Claude 3.7 Sonnet thinking&lt;/td>
 &lt;td>商業 API&lt;/td>
 &lt;td>extended thinking field&lt;/td>
 &lt;td>不可&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>Gemini 2.5 Flash thinking&lt;/td>
 &lt;td>商業 API&lt;/td>
 &lt;td>thinking field&lt;/td>
 &lt;td>不可&lt;/td>
 &lt;/tr>
 &lt;/tbody>
&lt;/table>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>讀 model card / paper 看到「reasoning」「thinking」「test-time compute」「R1-style」就是這個 family。寫 code 場景的判讀：&lt;/p>
&lt;ol>
&lt;li>&lt;strong>本地用 distill 版本是合理起點&lt;/strong>：DeepSeek-R1-Distill-Qwen-32B、QwQ-32B 等是「正常 32B 模型 + reasoning 後訓練」的產物、跑得起來&lt;/li>
&lt;li>&lt;strong>適合的任務&lt;/strong>：debug 複雜 bug、算 algorithm complexity、設計 multi-step refactor、解 leetcode hard&lt;/li>
&lt;li>&lt;strong>不適合的任務&lt;/strong>：autocomplete（reasoning trace 拉長 TTFT、體感變慢）、簡單 docstring 補完、純文字翻譯&lt;/li>
&lt;li>&lt;strong>混用策略&lt;/strong>：日常用 &lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/instruction-tuned/" data-link-title="Instruction-Tuned Model" data-link-desc="經過指令微調的模型：會跟著 prompt 走、回答使用者問題">instruction-tuned model&lt;/a>（如 Gemma 4 31B、Qwen3-Coder）+ 複雜任務切到本地 reasoning model（如 QwQ-32B）+ 真正困難任務切雲端 o1 / R1 full&lt;/li>
&lt;li>&lt;strong>記憶體預算&lt;/strong>：reasoning model 本身大小跟對應 instruct model 相當、但要預留更大 &lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/kv-cache/" data-link-title="KV Cache" data-link-desc="已處理 token 的 attention 中間結果暫存：避免重算、加速後續生成">KV cache&lt;/a> 給長 reasoning trace（context 通常開 32K+）&lt;/li>
&lt;/ol></description><content:encoded><![CDATA[<p>Reasoning model 的核心概念是「<strong>透過後訓練（多半是 RL）讓模型自然在回答前產出長 <a href="/blog/llm/knowledge-cards/chain-of-thought/" data-link-title="Chain-of-Thought（CoT）" data-link-desc="讓 LLM 先輸出推理步驟再給最終答案的 prompting / 訓練方式、reasoning model 的基礎機制">chain-of-thought</a> reasoning trace 的 LLM 變體</strong>」。代表是 OpenAI o1 / o3、DeepSeek-R1、Qwen-QwQ、Claude 3.7 Sonnet thinking 等。Reasoning model 是 2024-2026 LLM 的最大 paradigm shift、把 <a href="/blog/llm/knowledge-cards/test-time-compute/" data-link-title="Test-Time Compute" data-link-desc="推論時動態增加計算量換取答案品質的 paradigm、reasoning model 跟 best-of-N 的共同基底">test-time compute</a> 變成可訓練、可 scale 的維度。</p>
<h2 id="概念位置">概念位置</h2>
<p>Reasoning model 跟一般 instruction-tuned model 的差異：</p>
<table>
  <thead>
      <tr>
          <th>維度</th>
          <th>Instruction-tuned model（如 Gemma 4 instruct）</th>
          <th>Reasoning model（如 DeepSeek-R1）</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>訓練後階段</td>
          <td>SFT + RLHF / DPO</td>
          <td>SFT + RLHF + <strong>reasoning RL</strong></td>
      </tr>
      <tr>
          <td>推論行為</td>
          <td>直接答（或短 CoT）</td>
          <td>先生 reasoning trace（數百到數千 token）再答</td>
      </tr>
      <tr>
          <td>適合任務</td>
          <td>對話、寫作、簡單 coding、查詢</td>
          <td>math、debug、algorithm、複雜 reasoning</td>
      </tr>
      <tr>
          <td>Token 消耗</td>
          <td>直接生答案 token</td>
          <td>reasoning trace 通常 5-50× 於最終答案</td>
      </tr>
      <tr>
          <td>推論成本</td>
          <td>1×</td>
          <td>5-20×（依任務難度）</td>
      </tr>
      <tr>
          <td>Context 需求</td>
          <td>一般</td>
          <td>較大（要容納 reasoning trace）</td>
      </tr>
  </tbody>
</table>
<p>主流 reasoning model 比較（2026/5）：</p>
<table>
  <thead>
      <tr>
          <th>模型</th>
          <th>開源 / 商業</th>
          <th>推理 trace 格式</th>
          <th>本地跑可行性</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>OpenAI o1 / o3</td>
          <td>商業 API</td>
          <td>對使用者隱藏</td>
          <td>不可</td>
      </tr>
      <tr>
          <td>DeepSeek-R1（full）</td>
          <td>開源</td>
          <td><code>&lt;think&gt;...&lt;/think&gt;</code> 標記</td>
          <td>671B 太大、本地不實際</td>
      </tr>
      <tr>
          <td>DeepSeek-R1 distill</td>
          <td>開源</td>
          <td>同上</td>
          <td>7B / 14B / 32B distill 可在 24-48GB Mac 跑</td>
      </tr>
      <tr>
          <td>Qwen-QwQ</td>
          <td>開源</td>
          <td>純文字 reasoning（無特殊 token）</td>
          <td>32B 可在 64GB+ Mac 跑</td>
      </tr>
      <tr>
          <td>Claude 3.7 Sonnet thinking</td>
          <td>商業 API</td>
          <td>extended thinking field</td>
          <td>不可</td>
      </tr>
      <tr>
          <td>Gemini 2.5 Flash thinking</td>
          <td>商業 API</td>
          <td>thinking field</td>
          <td>不可</td>
      </tr>
  </tbody>
</table>
<h2 id="設計責任">設計責任</h2>
<p>讀 model card / paper 看到「reasoning」「thinking」「test-time compute」「R1-style」就是這個 family。寫 code 場景的判讀：</p>
<ol>
<li><strong>本地用 distill 版本是合理起點</strong>：DeepSeek-R1-Distill-Qwen-32B、QwQ-32B 等是「正常 32B 模型 + reasoning 後訓練」的產物、跑得起來</li>
<li><strong>適合的任務</strong>：debug 複雜 bug、算 algorithm complexity、設計 multi-step refactor、解 leetcode hard</li>
<li><strong>不適合的任務</strong>：autocomplete（reasoning trace 拉長 TTFT、體感變慢）、簡單 docstring 補完、純文字翻譯</li>
<li><strong>混用策略</strong>：日常用 <a href="/blog/llm/knowledge-cards/instruction-tuned/" data-link-title="Instruction-Tuned Model" data-link-desc="經過指令微調的模型：會跟著 prompt 走、回答使用者問題">instruction-tuned model</a>（如 Gemma 4 31B、Qwen3-Coder）+ 複雜任務切到本地 reasoning model（如 QwQ-32B）+ 真正困難任務切雲端 o1 / R1 full</li>
<li><strong>記憶體預算</strong>：reasoning model 本身大小跟對應 instruct model 相當、但要預留更大 <a href="/blog/llm/knowledge-cards/kv-cache/" data-link-title="KV Cache" data-link-desc="已處理 token 的 attention 中間結果暫存：避免重算、加速後續生成">KV cache</a> 給長 reasoning trace（context 通常開 32K+）</li>
</ol>
]]></content:encoded></item><item><title>Refusal Rate</title><link>https://tarrragon.github.io/blog/llm/knowledge-cards/refusal-rate/</link><pubDate>Tue, 12 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/llm/knowledge-cards/refusal-rate/</guid><description>&lt;p>Refusal rate 的核心概念是「LLM 拒絕回答 prompt 的比例」。LLM 在訓練階段（特別是 RLHF）會學到「對特定類型的請求說『我不能幫忙這個』」、production 服務通常會監控這個比例作為對齊強度跟異常行為偵測的訊號之一。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>Refusal 行為的典型形態：&lt;/p>
&lt;table>
 &lt;thead>
 &lt;tr>
 &lt;th>形態&lt;/th>
 &lt;th>例子&lt;/th>
 &lt;/tr>
 &lt;/thead>
 &lt;tbody>
 &lt;tr>
 &lt;td>安全相關拒絕&lt;/td>
 &lt;td>&amp;ldquo;Sorry, I can&amp;rsquo;t help with that request.&amp;rdquo;&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>政策相關拒絕&lt;/td>
 &lt;td>&amp;ldquo;I&amp;rsquo;m not able to discuss specific medical advice.&amp;rdquo;&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>能力相關拒絕&lt;/td>
 &lt;td>&amp;ldquo;I don&amp;rsquo;t have real-time data access.&amp;rdquo;&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>模糊拒絕（soft refusal）&lt;/td>
 &lt;td>&amp;ldquo;That&amp;rsquo;s an interesting question, but&amp;hellip;&amp;rdquo;&lt;/td>
 &lt;/tr>
 &lt;/tbody>
&lt;/table>
&lt;p>Refusal rate 作為偵測訊號的兩個方向：&lt;/p>
&lt;ol>
&lt;li>&lt;strong>率突然下降&lt;/strong>：可能是對齊被繞過、&lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/prompt-injection/" data-link-title="Prompt Injection" data-link-desc="把惡意指令藏進 LLM 會讀到的內容、誘導 LLM 跑出非開發者預期行為的攻擊類別、OWASP LLM01 列入頭號威脅">prompt injection&lt;/a> 攻擊在進行、或新版本模型對齊變弱。&lt;/li>
&lt;li>&lt;strong>率突然上升&lt;/strong>：可能是訓練資料或對齊政策變嚴、影響使用者體驗、或 vendor 端政策調整。&lt;/li>
&lt;/ol>
&lt;p>實作上、偵測 refusal 通常用簡單 pattern matching（看是否含 &amp;ldquo;I can&amp;rsquo;t&amp;rdquo; / &amp;ldquo;I&amp;rsquo;m not able&amp;rdquo; / &amp;ldquo;Sorry&amp;rdquo; 等）或更精確的 classifier；具體實作依 &lt;a href="https://tarrragon.github.io/blog/backend/07-security-data-protection/detection-coverage-and-signal-governance/" data-link-title="7.13 偵測覆蓋率與訊號治理" data-link-desc="定義偵測覆蓋、訊號品質與誤報成本的治理問題">偵測平台&lt;/a> 設計。&lt;/p>
&lt;blockquote>
&lt;p>&lt;strong>事實查核註&lt;/strong>：refusal rate 的標準化測量方式、跟「對齊強度」的對應關係仍在研究演進、不同 vendor 跟 model 的 baseline 差異大、引用前以對應模型的 model card 跟最新研究為準。&lt;/p>&lt;/blockquote>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>理解 refusal rate 後可以解釋兩個現象：為什麼 production LLM 服務監控 refusal rate（變化是異常訊號）、為什麼開源模型的 refusal rate 通常低於商業旗艦（前者 safety RLHF 投入較少）。&lt;/p>
&lt;p>production 設計時、refusal rate 是 content 層偵測訊號之一、需配合 tool call 序列、token usage、prompt pattern 等其他訊號才能形成完整偵測覆蓋。詳見 &lt;a href="https://tarrragon.github.io/blog/backend/07-security-data-protection/llm-as-service-detection-coverage/" data-link-title="LLM Service 偵測訊號覆蓋" data-link-desc="production LLM 服務的 detection 訊號設計：tool call 異常模式、prompt injection 觸發徵兆、abuse 跟濫用模式、跟既有 detection-coverage 框架的接合">LLM Service 偵測訊號覆蓋&lt;/a>。&lt;/p></description><content:encoded><![CDATA[<p>Refusal rate 的核心概念是「LLM 拒絕回答 prompt 的比例」。LLM 在訓練階段（特別是 RLHF）會學到「對特定類型的請求說『我不能幫忙這個』」、production 服務通常會監控這個比例作為對齊強度跟異常行為偵測的訊號之一。</p>
<h2 id="概念位置">概念位置</h2>
<p>Refusal 行為的典型形態：</p>
<table>
  <thead>
      <tr>
          <th>形態</th>
          <th>例子</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>安全相關拒絕</td>
          <td>&ldquo;Sorry, I can&rsquo;t help with that request.&rdquo;</td>
      </tr>
      <tr>
          <td>政策相關拒絕</td>
          <td>&ldquo;I&rsquo;m not able to discuss specific medical advice.&rdquo;</td>
      </tr>
      <tr>
          <td>能力相關拒絕</td>
          <td>&ldquo;I don&rsquo;t have real-time data access.&rdquo;</td>
      </tr>
      <tr>
          <td>模糊拒絕（soft refusal）</td>
          <td>&ldquo;That&rsquo;s an interesting question, but&hellip;&rdquo;</td>
      </tr>
  </tbody>
</table>
<p>Refusal rate 作為偵測訊號的兩個方向：</p>
<ol>
<li><strong>率突然下降</strong>：可能是對齊被繞過、<a href="/blog/llm/knowledge-cards/prompt-injection/" data-link-title="Prompt Injection" data-link-desc="把惡意指令藏進 LLM 會讀到的內容、誘導 LLM 跑出非開發者預期行為的攻擊類別、OWASP LLM01 列入頭號威脅">prompt injection</a> 攻擊在進行、或新版本模型對齊變弱。</li>
<li><strong>率突然上升</strong>：可能是訓練資料或對齊政策變嚴、影響使用者體驗、或 vendor 端政策調整。</li>
</ol>
<p>實作上、偵測 refusal 通常用簡單 pattern matching（看是否含 &ldquo;I can&rsquo;t&rdquo; / &ldquo;I&rsquo;m not able&rdquo; / &ldquo;Sorry&rdquo; 等）或更精確的 classifier；具體實作依 <a href="/blog/backend/07-security-data-protection/detection-coverage-and-signal-governance/" data-link-title="7.13 偵測覆蓋率與訊號治理" data-link-desc="定義偵測覆蓋、訊號品質與誤報成本的治理問題">偵測平台</a> 設計。</p>
<blockquote>
<p><strong>事實查核註</strong>：refusal rate 的標準化測量方式、跟「對齊強度」的對應關係仍在研究演進、不同 vendor 跟 model 的 baseline 差異大、引用前以對應模型的 model card 跟最新研究為準。</p></blockquote>
<h2 id="設計責任">設計責任</h2>
<p>理解 refusal rate 後可以解釋兩個現象：為什麼 production LLM 服務監控 refusal rate（變化是異常訊號）、為什麼開源模型的 refusal rate 通常低於商業旗艦（前者 safety RLHF 投入較少）。</p>
<p>production 設計時、refusal rate 是 content 層偵測訊號之一、需配合 tool call 序列、token usage、prompt pattern 等其他訊號才能形成完整偵測覆蓋。詳見 <a href="/blog/backend/07-security-data-protection/llm-as-service-detection-coverage/" data-link-title="LLM Service 偵測訊號覆蓋" data-link-desc="production LLM 服務的 detection 訊號設計：tool call 異常模式、prompt injection 觸發徵兆、abuse 跟濫用模式、跟既有 detection-coverage 框架的接合">LLM Service 偵測訊號覆蓋</a>。</p>
]]></content:encoded></item><item><title>Reranker</title><link>https://tarrragon.github.io/blog/llm/knowledge-cards/reranker/</link><pubDate>Tue, 12 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/llm/knowledge-cards/reranker/</guid><description>&lt;p>Reranker 的核心概念是「&lt;strong>對 &lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/rag/" data-link-title="RAG" data-link-desc="Retrieval-Augmented Generation：動態外掛知識給 LLM、繞開模型參數記憶的靜態限制">retrieval&lt;/a> 第一階段拿到的 top-K（如 50）結果、用 cross-encoder 模型重新評分、排出 top-N（如 5）給 LLM&lt;/strong>」。是 RAG 第二階段、補 bi-encoder（&lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/embedding-model/" data-link-title="Embedding Model" data-link-desc="把文字轉成向量的模型：用於 codebase 索引與語意搜尋">embedding model&lt;/a>）對 &lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/query-document-gap/" data-link-title="Query-Document Gap" data-link-desc="使用者 query 與文件語言在詞彙、形態、抽象層級或領域分佈上的落差，是 RAG retrieval miss 的常見原因">query-document gap&lt;/a> 的細粒度匹配不足、品質提升明顯（recall@5 通常 +10-30%）但成本 / latency 增加。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>Bi-encoder vs cross-encoder 的差別：&lt;/p>





&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-text" data-lang="text">&lt;span class="line">&lt;span class="ln">1&lt;/span>&lt;span class="cl">Bi-encoder（embedding model、retrieval 第一階段）：
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">2&lt;/span>&lt;span class="cl"> query → embedding A
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">3&lt;/span>&lt;span class="cl"> document → embedding B（pre-compute、存 vector DB）
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">4&lt;/span>&lt;span class="cl"> score = cosine(A, B)
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">5&lt;/span>&lt;span class="cl"> → 快、可 pre-compute、適合海量 retrieval
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">6&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">7&lt;/span>&lt;span class="cl">Cross-encoder（reranker、retrieval 第二階段）：
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">8&lt;/span>&lt;span class="cl"> (query, document) 一起進模型 → 直接輸出 relevance score
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">9&lt;/span>&lt;span class="cl"> → 慢（每對都要 forward pass）、不可 pre-compute、適合 top-K rerank&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>主流 reranker：&lt;/p>
&lt;table>
 &lt;thead>
 &lt;tr>
 &lt;th>Reranker&lt;/th>
 &lt;th>類型&lt;/th>
 &lt;th>適合場景&lt;/th>
 &lt;/tr>
 &lt;/thead>
 &lt;tbody>
 &lt;tr>
 &lt;td>Cohere Rerank 3&lt;/td>
 &lt;td>SaaS API&lt;/td>
 &lt;td>Production 高品質、多語&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>Jina Reranker v2&lt;/td>
 &lt;td>開源&lt;/td>
 &lt;td>開源、多語&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>BGE Reranker（bge-reranker-v2-m3）&lt;/td>
 &lt;td>開源&lt;/td>
 &lt;td>開源中文友善&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>Voyage rerank-2&lt;/td>
 &lt;td>SaaS API&lt;/td>
 &lt;td>跟 voyage embedding 配對&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>ColBERT v2&lt;/td>
 &lt;td>Late interaction&lt;/td>
 &lt;td>介於 bi 跟 cross encoder&lt;/td>
 &lt;/tr>
 &lt;/tbody>
&lt;/table>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>讀 RAG / production retrieval docs 看到「reranker」「cross-encoder」「rerank stage」就是這 framing。寫 code 場景的判讀：&lt;/p>
&lt;ol>
&lt;li>&lt;strong>何時值得加 reranker&lt;/strong>：retrieval 結果有「相關但不精確」問題、top-K hit rate 高但 top-5 hit rate 低、有 latency / cost budget&lt;/li>
&lt;li>&lt;strong>何時不需要&lt;/strong>：小語料（&amp;lt; 1000 docs、retrieval 已準）、明確 keyword 任務（BM25 已準）、latency 敏感（&amp;lt; 100ms TTFT）&lt;/li>
&lt;li>&lt;strong>Pipeline 設計&lt;/strong>：bi-encoder retrieve top-50 → reranker rerank → 給 LLM top-5；50/5 是常見起點、看實測調&lt;/li>
&lt;li>&lt;strong>跟 &lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/hybrid-search/" data-link-title="Hybrid Search" data-link-desc="把字面 retrieval（BM25）跟語意 retrieval（embedding）的結果用 RRF 等方法合併、補單一路線的盲點">hybrid search&lt;/a> 結合&lt;/strong>：BM25 + embedding hybrid retrieve top-50 → reranker rerank → LLM、是 production RAG 標配&lt;/li>
&lt;li>&lt;strong>跟 &lt;a href="https://tarrragon.github.io/blog/llm/04-applications/rag-principles/" data-link-title="4.1 RAG 原理：retrieval &amp;#43; augmentation 模式" data-link-desc="為什麼模型需要外掛知識、語意相似 vs 字面相似、chunking 的本質取捨、retrieval 失敗的根本原因">4.1 RAG 章節&lt;/a> 的關係&lt;/strong>：本卡是定義、章節是 retrieval pipeline 設計（含 reranker / hybrid 段）&lt;/li>
&lt;/ol></description><content:encoded><![CDATA[<p>Reranker 的核心概念是「<strong>對 <a href="/blog/llm/knowledge-cards/rag/" data-link-title="RAG" data-link-desc="Retrieval-Augmented Generation：動態外掛知識給 LLM、繞開模型參數記憶的靜態限制">retrieval</a> 第一階段拿到的 top-K（如 50）結果、用 cross-encoder 模型重新評分、排出 top-N（如 5）給 LLM</strong>」。是 RAG 第二階段、補 bi-encoder（<a href="/blog/llm/knowledge-cards/embedding-model/" data-link-title="Embedding Model" data-link-desc="把文字轉成向量的模型：用於 codebase 索引與語意搜尋">embedding model</a>）對 <a href="/blog/llm/knowledge-cards/query-document-gap/" data-link-title="Query-Document Gap" data-link-desc="使用者 query 與文件語言在詞彙、形態、抽象層級或領域分佈上的落差，是 RAG retrieval miss 的常見原因">query-document gap</a> 的細粒度匹配不足、品質提升明顯（recall@5 通常 +10-30%）但成本 / latency 增加。</p>
<h2 id="概念位置">概念位置</h2>
<p>Bi-encoder vs cross-encoder 的差別：</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="ln">1</span><span class="cl">Bi-encoder（embedding model、retrieval 第一階段）：
</span></span><span class="line"><span class="ln">2</span><span class="cl">  query → embedding A
</span></span><span class="line"><span class="ln">3</span><span class="cl">  document → embedding B（pre-compute、存 vector DB）
</span></span><span class="line"><span class="ln">4</span><span class="cl">  score = cosine(A, B)
</span></span><span class="line"><span class="ln">5</span><span class="cl">  → 快、可 pre-compute、適合海量 retrieval
</span></span><span class="line"><span class="ln">6</span><span class="cl">
</span></span><span class="line"><span class="ln">7</span><span class="cl">Cross-encoder（reranker、retrieval 第二階段）：
</span></span><span class="line"><span class="ln">8</span><span class="cl">  (query, document) 一起進模型 → 直接輸出 relevance score
</span></span><span class="line"><span class="ln">9</span><span class="cl">  → 慢（每對都要 forward pass）、不可 pre-compute、適合 top-K rerank</span></span></code></pre></div><p>主流 reranker：</p>
<table>
  <thead>
      <tr>
          <th>Reranker</th>
          <th>類型</th>
          <th>適合場景</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>Cohere Rerank 3</td>
          <td>SaaS API</td>
          <td>Production 高品質、多語</td>
      </tr>
      <tr>
          <td>Jina Reranker v2</td>
          <td>開源</td>
          <td>開源、多語</td>
      </tr>
      <tr>
          <td>BGE Reranker（bge-reranker-v2-m3）</td>
          <td>開源</td>
          <td>開源中文友善</td>
      </tr>
      <tr>
          <td>Voyage rerank-2</td>
          <td>SaaS API</td>
          <td>跟 voyage embedding 配對</td>
      </tr>
      <tr>
          <td>ColBERT v2</td>
          <td>Late interaction</td>
          <td>介於 bi 跟 cross encoder</td>
      </tr>
  </tbody>
</table>
<h2 id="設計責任">設計責任</h2>
<p>讀 RAG / production retrieval docs 看到「reranker」「cross-encoder」「rerank stage」就是這 framing。寫 code 場景的判讀：</p>
<ol>
<li><strong>何時值得加 reranker</strong>：retrieval 結果有「相關但不精確」問題、top-K hit rate 高但 top-5 hit rate 低、有 latency / cost budget</li>
<li><strong>何時不需要</strong>：小語料（&lt; 1000 docs、retrieval 已準）、明確 keyword 任務（BM25 已準）、latency 敏感（&lt; 100ms TTFT）</li>
<li><strong>Pipeline 設計</strong>：bi-encoder retrieve top-50 → reranker rerank → 給 LLM top-5；50/5 是常見起點、看實測調</li>
<li><strong>跟 <a href="/blog/llm/knowledge-cards/hybrid-search/" data-link-title="Hybrid Search" data-link-desc="把字面 retrieval（BM25）跟語意 retrieval（embedding）的結果用 RRF 等方法合併、補單一路線的盲點">hybrid search</a> 結合</strong>：BM25 + embedding hybrid retrieve top-50 → reranker rerank → LLM、是 production RAG 標配</li>
<li><strong>跟 <a href="/blog/llm/04-applications/rag-principles/" data-link-title="4.1 RAG 原理：retrieval &#43; augmentation 模式" data-link-desc="為什麼模型需要外掛知識、語意相似 vs 字面相似、chunking 的本質取捨、retrieval 失敗的根本原因">4.1 RAG 章節</a> 的關係</strong>：本卡是定義、章節是 retrieval pipeline 設計（含 reranker / hybrid 段）</li>
</ol>
]]></content:encoded></item><item><title>Residual Connection</title><link>https://tarrragon.github.io/blog/llm/knowledge-cards/residual-connection/</link><pubDate>Tue, 12 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/llm/knowledge-cards/residual-connection/</guid><description>&lt;p>Residual connection（殘差連接、skip connection）的核心概念是「把 layer 的輸入直接加到輸出上」、形式是 &lt;code>output = layer(x) + x&lt;/code>。這個簡單加法解決了深層網路的訓練退化問題：沒有 residual、模型加深會反而變差（不是過擬合、是 gradient 在反向傳播中衰減太多）；有 residual、訓練幾十甚至上百層都穩。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>Residual connection 在 Transformer block 中出現兩次：&lt;/p>





&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-text" data-lang="text">&lt;span class="line">&lt;span class="ln"> 1&lt;/span>&lt;span class="cl">Transformer block：
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 2&lt;/span>&lt;span class="cl"> x
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 3&lt;/span>&lt;span class="cl"> ├──────────────┐ ← skip connection（保留原始 x）
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 4&lt;/span>&lt;span class="cl"> ↓ │
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 5&lt;/span>&lt;span class="cl"> LayerNorm │
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 6&lt;/span>&lt;span class="cl"> ↓ │
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 7&lt;/span>&lt;span class="cl"> Self-Attention │
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 8&lt;/span>&lt;span class="cl"> ↓ │
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 9&lt;/span>&lt;span class="cl"> +←─────────────┘ ← residual add：attention output + x
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">10&lt;/span>&lt;span class="cl"> │
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">11&lt;/span>&lt;span class="cl"> ├──────────────┐ ← skip connection（保留 attention 後的值）
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">12&lt;/span>&lt;span class="cl"> ↓ │
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">13&lt;/span>&lt;span class="cl"> LayerNorm │
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">14&lt;/span>&lt;span class="cl"> ↓ │
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">15&lt;/span>&lt;span class="cl"> FFN │
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">16&lt;/span>&lt;span class="cl"> ↓ │
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">17&lt;/span>&lt;span class="cl"> +←─────────────┘ ← residual add：FFN output + previous
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">18&lt;/span>&lt;span class="cl"> ↓
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">19&lt;/span>&lt;span class="cl"> 進入下一個 block&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>關鍵性質：&lt;/p>
&lt;ol>
&lt;li>&lt;strong>Gradient 可以走捷徑&lt;/strong>：&lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/backpropagation/" data-link-title="Backpropagation" data-link-desc="從 output loss 反向遞推、用 chain rule 算出每個權重的 gradient 的演算法">Backpropagation&lt;/a> 時、gradient 能透過 skip connection 直接傳回淺層、避免 chain rule 累積衰減。&lt;/li>
&lt;li>&lt;strong>Layer 學「殘差」而不是「完整轉換」&lt;/strong>：每層學「該怎麼微調輸入」、不用學「從零生成輸出」、優化更容易。&lt;/li>
&lt;li>&lt;strong>跟 &lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/layer-normalization/" data-link-title="Layer Normalization" data-link-desc="在每個 token 的 hidden state 上做正規化（減 mean、除 std）、穩定深層網路訓練">LayerNorm&lt;/a> 配對&lt;/strong>：兩者一起是深層 Transformer 訓得起來的基礎。&lt;/li>
&lt;/ol>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>理解 residual connection 後可以判讀 Transformer 能堆幾十層的根本原因（不是因為 attention、是因為 residual + LayerNorm 讓深層仍可訓練）；也能看懂 ResNet、ViT 等其他用 residual 架構的設計。LLM 推論時 residual 不算 bottleneck、但在訓練 / fine-tune 時、residual 是 gradient flow 健康度的關鍵。&lt;/p></description><content:encoded><![CDATA[<p>Residual connection（殘差連接、skip connection）的核心概念是「把 layer 的輸入直接加到輸出上」、形式是 <code>output = layer(x) + x</code>。這個簡單加法解決了深層網路的訓練退化問題：沒有 residual、模型加深會反而變差（不是過擬合、是 gradient 在反向傳播中衰減太多）；有 residual、訓練幾十甚至上百層都穩。</p>
<h2 id="概念位置">概念位置</h2>
<p>Residual connection 在 Transformer block 中出現兩次：</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="ln"> 1</span><span class="cl">Transformer block：
</span></span><span class="line"><span class="ln"> 2</span><span class="cl">  x
</span></span><span class="line"><span class="ln"> 3</span><span class="cl">  ├──────────────┐  ← skip connection（保留原始 x）
</span></span><span class="line"><span class="ln"> 4</span><span class="cl">  ↓              │
</span></span><span class="line"><span class="ln"> 5</span><span class="cl">  LayerNorm      │
</span></span><span class="line"><span class="ln"> 6</span><span class="cl">  ↓              │
</span></span><span class="line"><span class="ln"> 7</span><span class="cl">  Self-Attention │
</span></span><span class="line"><span class="ln"> 8</span><span class="cl">  ↓              │
</span></span><span class="line"><span class="ln"> 9</span><span class="cl">  +←─────────────┘  ← residual add：attention output + x
</span></span><span class="line"><span class="ln">10</span><span class="cl">  │
</span></span><span class="line"><span class="ln">11</span><span class="cl">  ├──────────────┐  ← skip connection（保留 attention 後的值）
</span></span><span class="line"><span class="ln">12</span><span class="cl">  ↓              │
</span></span><span class="line"><span class="ln">13</span><span class="cl">  LayerNorm      │
</span></span><span class="line"><span class="ln">14</span><span class="cl">  ↓              │
</span></span><span class="line"><span class="ln">15</span><span class="cl">  FFN            │
</span></span><span class="line"><span class="ln">16</span><span class="cl">  ↓              │
</span></span><span class="line"><span class="ln">17</span><span class="cl">  +←─────────────┘  ← residual add：FFN output + previous
</span></span><span class="line"><span class="ln">18</span><span class="cl">  ↓
</span></span><span class="line"><span class="ln">19</span><span class="cl">  進入下一個 block</span></span></code></pre></div><p>關鍵性質：</p>
<ol>
<li><strong>Gradient 可以走捷徑</strong>：<a href="/blog/llm/knowledge-cards/backpropagation/" data-link-title="Backpropagation" data-link-desc="從 output loss 反向遞推、用 chain rule 算出每個權重的 gradient 的演算法">Backpropagation</a> 時、gradient 能透過 skip connection 直接傳回淺層、避免 chain rule 累積衰減。</li>
<li><strong>Layer 學「殘差」而不是「完整轉換」</strong>：每層學「該怎麼微調輸入」、不用學「從零生成輸出」、優化更容易。</li>
<li><strong>跟 <a href="/blog/llm/knowledge-cards/layer-normalization/" data-link-title="Layer Normalization" data-link-desc="在每個 token 的 hidden state 上做正規化（減 mean、除 std）、穩定深層網路訓練">LayerNorm</a> 配對</strong>：兩者一起是深層 Transformer 訓得起來的基礎。</li>
</ol>
<h2 id="設計責任">設計責任</h2>
<p>理解 residual connection 後可以判讀 Transformer 能堆幾十層的根本原因（不是因為 attention、是因為 residual + LayerNorm 讓深層仍可訓練）；也能看懂 ResNet、ViT 等其他用 residual 架構的設計。LLM 推論時 residual 不算 bottleneck、但在訓練 / fine-tune 時、residual 是 gradient flow 健康度的關鍵。</p>
]]></content:encoded></item><item><title>RLHF</title><link>https://tarrragon.github.io/blog/llm/knowledge-cards/rlhf/</link><pubDate>Tue, 12 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/llm/knowledge-cards/rlhf/</guid><description>&lt;p>RLHF（Reinforcement Learning from Human Feedback、人類反饋強化學習）的核心概念是「&lt;strong>讓人類比較兩個模型回答的好壞、訓一個 reward model 學會這個偏好、再用 RL 把 LLM 推往 reward model 給高分的方向&lt;/strong>」。RLHF 是 LLM 對話品質飛躍的關鍵（從 GPT-3 base 到 ChatGPT 的差別主要是 RLHF）。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>RLHF 在訓練流程的位置與步驟：&lt;/p>





&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-text" data-lang="text">&lt;span class="line">&lt;span class="ln"> 1&lt;/span>&lt;span class="cl">[SFT 後的模型]
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 2&lt;/span>&lt;span class="cl"> ↓
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 3&lt;/span>&lt;span class="cl">Step 1：收集人類偏好
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 4&lt;/span>&lt;span class="cl"> 對同個 prompt 讓模型生 A、B 兩個 response、人類標「我較喜歡 A」
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 5&lt;/span>&lt;span class="cl"> ↓
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 6&lt;/span>&lt;span class="cl">Step 2：訓 reward model
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 7&lt;/span>&lt;span class="cl"> 輸入 (prompt, response)、輸出一個分數
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 8&lt;/span>&lt;span class="cl"> 目標：人類偏好的 response 分數高
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 9&lt;/span>&lt;span class="cl"> ↓
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">10&lt;/span>&lt;span class="cl">Step 3：用 PPO 等 RL 演算法 fine-tune LLM
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">11&lt;/span>&lt;span class="cl"> 讓模型輸出讓 reward model 給高分的 response
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">12&lt;/span>&lt;span class="cl"> 加 [KL constraint](/llm/knowledge-cards/kl-divergence/)：不能偏離 SFT model 太遠
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">13&lt;/span>&lt;span class="cl"> ↓
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">14&lt;/span>&lt;span class="cl">[Aligned model]：回答更貼近人類偏好&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>關鍵特性與挑戰：&lt;/p>
&lt;ol>
&lt;li>&lt;strong>三個模型同時運作&lt;/strong>：policy（LLM）、reward model、reference model（SFT 後 frozen 那份）、訓練時記憶體吃緊。&lt;/li>
&lt;li>&lt;strong>Reward hacking&lt;/strong>：模型可能找到 reward model 的弱點、生成「reward 高但實質爛」的輸出（如冗長 boilerplate）。&lt;/li>
&lt;li>&lt;strong>訓練不穩&lt;/strong>：PPO 對 hyperparameter 敏感、需要小心調 β（KL 約束強度）、learning rate 等。&lt;/li>
&lt;/ol>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>RLHF 是 ChatGPT / Claude / Gemini 等商業 LLM 對話品質的核心。讀 model card 看到「RLHF-tuned」「helpfulness fine-tuning」就是這個階段。&lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/dpo/" data-link-title="DPO（Direct Preference Optimization）" data-link-desc="RLHF 的簡化替代：跳過 reward model、直接從人類偏好資料 fine-tune LLM">DPO&lt;/a> 是 2023 年後出現的簡化替代方案、跳過 reward model、直接用偏好資料 fine-tune、訓練流程簡單很多、是現代許多開源模型的主流選擇。&lt;/p></description><content:encoded><![CDATA[<p>RLHF（Reinforcement Learning from Human Feedback、人類反饋強化學習）的核心概念是「<strong>讓人類比較兩個模型回答的好壞、訓一個 reward model 學會這個偏好、再用 RL 把 LLM 推往 reward model 給高分的方向</strong>」。RLHF 是 LLM 對話品質飛躍的關鍵（從 GPT-3 base 到 ChatGPT 的差別主要是 RLHF）。</p>
<h2 id="概念位置">概念位置</h2>
<p>RLHF 在訓練流程的位置與步驟：</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="ln"> 1</span><span class="cl">[SFT 後的模型]
</span></span><span class="line"><span class="ln"> 2</span><span class="cl">   ↓
</span></span><span class="line"><span class="ln"> 3</span><span class="cl">Step 1：收集人類偏好
</span></span><span class="line"><span class="ln"> 4</span><span class="cl">  對同個 prompt 讓模型生 A、B 兩個 response、人類標「我較喜歡 A」
</span></span><span class="line"><span class="ln"> 5</span><span class="cl">   ↓
</span></span><span class="line"><span class="ln"> 6</span><span class="cl">Step 2：訓 reward model
</span></span><span class="line"><span class="ln"> 7</span><span class="cl">  輸入 (prompt, response)、輸出一個分數
</span></span><span class="line"><span class="ln"> 8</span><span class="cl">  目標：人類偏好的 response 分數高
</span></span><span class="line"><span class="ln"> 9</span><span class="cl">   ↓
</span></span><span class="line"><span class="ln">10</span><span class="cl">Step 3：用 PPO 等 RL 演算法 fine-tune LLM
</span></span><span class="line"><span class="ln">11</span><span class="cl">  讓模型輸出讓 reward model 給高分的 response
</span></span><span class="line"><span class="ln">12</span><span class="cl">  加 [KL constraint](/llm/knowledge-cards/kl-divergence/)：不能偏離 SFT model 太遠
</span></span><span class="line"><span class="ln">13</span><span class="cl">   ↓
</span></span><span class="line"><span class="ln">14</span><span class="cl">[Aligned model]：回答更貼近人類偏好</span></span></code></pre></div><p>關鍵特性與挑戰：</p>
<ol>
<li><strong>三個模型同時運作</strong>：policy（LLM）、reward model、reference model（SFT 後 frozen 那份）、訓練時記憶體吃緊。</li>
<li><strong>Reward hacking</strong>：模型可能找到 reward model 的弱點、生成「reward 高但實質爛」的輸出（如冗長 boilerplate）。</li>
<li><strong>訓練不穩</strong>：PPO 對 hyperparameter 敏感、需要小心調 β（KL 約束強度）、learning rate 等。</li>
</ol>
<h2 id="設計責任">設計責任</h2>
<p>RLHF 是 ChatGPT / Claude / Gemini 等商業 LLM 對話品質的核心。讀 model card 看到「RLHF-tuned」「helpfulness fine-tuning」就是這個階段。<a href="/blog/llm/knowledge-cards/dpo/" data-link-title="DPO（Direct Preference Optimization）" data-link-desc="RLHF 的簡化替代：跳過 reward model、直接從人類偏好資料 fine-tune LLM">DPO</a> 是 2023 年後出現的簡化替代方案、跳過 reward model、直接用偏好資料 fine-tune、訓練流程簡單很多、是現代許多開源模型的主流選擇。</p>
]]></content:encoded></item><item><title>RoPE（Rotary Position Embedding）</title><link>https://tarrragon.github.io/blog/llm/knowledge-cards/rope/</link><pubDate>Tue, 12 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/llm/knowledge-cards/rope/</guid><description>&lt;p>RoPE（Rotary Position Embedding、旋轉位置編碼、Su et al., 2021）的核心概念是「&lt;strong>把 token 在序列中的位置資訊用旋轉矩陣直接旋轉進 Q 跟 K 向量裡&lt;/strong>、不是用加法疊加另一個 embedding」。RoPE 是 Llama、Gemma、Qwen、Mistral 等現代 LLM 的標配、相對早期的 absolute / learned positional embedding 有更好的長 context 推廣性。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>位置編碼的演化路線：&lt;/p>
&lt;table>
 &lt;thead>
 &lt;tr>
 &lt;th>方法&lt;/th>
 &lt;th>機制&lt;/th>
 &lt;th>主要問題&lt;/th>
 &lt;/tr>
 &lt;/thead>
 &lt;tbody>
 &lt;tr>
 &lt;td>Absolute（原 Transformer）&lt;/td>
 &lt;td>用 sin/cos 函數產生固定 position embedding、加到 token embedding&lt;/td>
 &lt;td>訓練長度外推性差&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>Learned absolute（GPT-2）&lt;/td>
 &lt;td>每個位置學一個可訓練向量、加到 token embedding&lt;/td>
 &lt;td>超過訓練長度完全沒對應 embedding&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>Relative&lt;/td>
 &lt;td>attention 算分數時加上「相對位置」的 bias&lt;/td>
 &lt;td>實作複雜、跟 &lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/kv-cache/" data-link-title="KV Cache" data-link-desc="已處理 token 的 attention 中間結果暫存：避免重算、加速後續生成">KV cache&lt;/a> 兼容性差&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;strong>RoPE&lt;/strong>&lt;/td>
 &lt;td>用旋轉矩陣把位置旋轉進 Q/K（不動 V）&lt;/td>
 &lt;td>主流、長 context 推廣性好（配 scaling）&lt;/td>
 &lt;/tr>
 &lt;/tbody>
&lt;/table>
&lt;p>RoPE 的核心數學（簡化）：&lt;/p>





&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-text" data-lang="text">&lt;span class="line">&lt;span class="ln">1&lt;/span>&lt;span class="cl">傳統：token at position m 的 Q 是 Q_m = x_m @ W_Q
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">2&lt;/span>&lt;span class="cl">RoPE：Q_m = R(m) × (x_m @ W_Q) ← R(m) 是依位置 m 決定的旋轉矩陣
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">3&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">4&lt;/span>&lt;span class="cl">attention score = Q_m @ K_n^T
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">5&lt;/span>&lt;span class="cl"> = R(m) × q × (R(n) × k)^T
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">6&lt;/span>&lt;span class="cl"> = q × R(m - n) × k^T ← 只依賴相對位置 (m-n)！&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>關鍵性質：RoPE 算出的 attention score 只依賴&lt;strong>相對位置&lt;/strong>、所以推廣到比訓練長度更長的 context 時有自然的數學基礎、配合 RoPE scaling（YaRN、NTK-aware、Position Interpolation）就能把 8K 訓練的模型擴展到 128K / 1M context。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>讀 model card 看到 &lt;code>rope_theta: 10000&lt;/code>、&lt;code>rope_scaling: {type: yarn, factor: 8}&lt;/code> 等就是 RoPE 配置。寫 code 場景的意涵：long context 模型（如 Llama 3 128K）的推廣能力主要靠 RoPE + scaling、不是直接訓練 128K 全長；但聲稱 context 跟「實用 context」仍有差距、長 context 上模型表現會逐步衰減。&lt;/p></description><content:encoded><![CDATA[<p>RoPE（Rotary Position Embedding、旋轉位置編碼、Su et al., 2021）的核心概念是「<strong>把 token 在序列中的位置資訊用旋轉矩陣直接旋轉進 Q 跟 K 向量裡</strong>、不是用加法疊加另一個 embedding」。RoPE 是 Llama、Gemma、Qwen、Mistral 等現代 LLM 的標配、相對早期的 absolute / learned positional embedding 有更好的長 context 推廣性。</p>
<h2 id="概念位置">概念位置</h2>
<p>位置編碼的演化路線：</p>
<table>
  <thead>
      <tr>
          <th>方法</th>
          <th>機制</th>
          <th>主要問題</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>Absolute（原 Transformer）</td>
          <td>用 sin/cos 函數產生固定 position embedding、加到 token embedding</td>
          <td>訓練長度外推性差</td>
      </tr>
      <tr>
          <td>Learned absolute（GPT-2）</td>
          <td>每個位置學一個可訓練向量、加到 token embedding</td>
          <td>超過訓練長度完全沒對應 embedding</td>
      </tr>
      <tr>
          <td>Relative</td>
          <td>attention 算分數時加上「相對位置」的 bias</td>
          <td>實作複雜、跟 <a href="/blog/llm/knowledge-cards/kv-cache/" data-link-title="KV Cache" data-link-desc="已處理 token 的 attention 中間結果暫存：避免重算、加速後續生成">KV cache</a> 兼容性差</td>
      </tr>
      <tr>
          <td><strong>RoPE</strong></td>
          <td>用旋轉矩陣把位置旋轉進 Q/K（不動 V）</td>
          <td>主流、長 context 推廣性好（配 scaling）</td>
      </tr>
  </tbody>
</table>
<p>RoPE 的核心數學（簡化）：</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="ln">1</span><span class="cl">傳統：token at position m 的 Q 是 Q_m = x_m @ W_Q
</span></span><span class="line"><span class="ln">2</span><span class="cl">RoPE：Q_m = R(m) × (x_m @ W_Q)  ← R(m) 是依位置 m 決定的旋轉矩陣
</span></span><span class="line"><span class="ln">3</span><span class="cl">
</span></span><span class="line"><span class="ln">4</span><span class="cl">attention score = Q_m @ K_n^T
</span></span><span class="line"><span class="ln">5</span><span class="cl">               = R(m) × q × (R(n) × k)^T
</span></span><span class="line"><span class="ln">6</span><span class="cl">               = q × R(m - n) × k^T  ← 只依賴相對位置 (m-n)！</span></span></code></pre></div><p>關鍵性質：RoPE 算出的 attention score 只依賴<strong>相對位置</strong>、所以推廣到比訓練長度更長的 context 時有自然的數學基礎、配合 RoPE scaling（YaRN、NTK-aware、Position Interpolation）就能把 8K 訓練的模型擴展到 128K / 1M context。</p>
<h2 id="設計責任">設計責任</h2>
<p>讀 model card 看到 <code>rope_theta: 10000</code>、<code>rope_scaling: {type: yarn, factor: 8}</code> 等就是 RoPE 配置。寫 code 場景的意涵：long context 模型（如 Llama 3 128K）的推廣能力主要靠 RoPE + scaling、不是直接訓練 128K 全長；但聲稱 context 跟「實用 context」仍有差距、長 context 上模型表現會逐步衰減。</p>
]]></content:encoded></item><item><title>Sandbox</title><link>https://tarrragon.github.io/blog/llm/knowledge-cards/sandbox/</link><pubDate>Tue, 12 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/llm/knowledge-cards/sandbox/</guid><description>&lt;p>Sandbox 的核心概念是「把程式跑在權限受限的隔離環境、限制檔案存取、網路連線、系統呼叫的範圍」。在 LLM 場景下、sandbox 用來控制 &lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/tool-use/" data-link-title="Tool Use" data-link-desc="LLM 透過結構化呼叫外部工具（讀檔、查資料庫、發 API request）來擴展能力的設計、function calling 跟 MCP 是常見實作">tool use&lt;/a> 跟 MCP server 的副作用範圍：即使 LLM 被 &lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/prompt-injection/" data-link-title="Prompt Injection" data-link-desc="把惡意指令藏進 LLM 會讀到的內容、誘導 LLM 跑出非開發者預期行為的攻擊類別、OWASP LLM01 列入頭號威脅">prompt injection&lt;/a> 誘導跑惡意 tool、sandbox 能限制最壞情況的影響面。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>常見的 sandbox 技術光譜（依隔離強度跟工程成本）：&lt;/p>
&lt;table>
 &lt;thead>
 &lt;tr>
 &lt;th>技術&lt;/th>
 &lt;th>隔離強度&lt;/th>
 &lt;th>工程成本&lt;/th>
 &lt;th>LLM 場景的典型用途&lt;/th>
 &lt;/tr>
 &lt;/thead>
 &lt;tbody>
 &lt;tr>
 &lt;td>不同 OS user&lt;/td>
 &lt;td>中（檔案權限）&lt;/td>
 &lt;td>低&lt;/td>
 &lt;td>個人 dev 跑 MCP server&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>Docker container&lt;/td>
 &lt;td>中高&lt;/td>
 &lt;td>中&lt;/td>
 &lt;td>跑第三方 MCP server、隔離 LLM agent&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>VM / Firecracker / gVisor&lt;/td>
 &lt;td>高&lt;/td>
 &lt;td>中高&lt;/td>
 &lt;td>production 多租戶 LLM agent&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>chroot / namespace&lt;/td>
 &lt;td>中&lt;/td>
 &lt;td>中&lt;/td>
 &lt;td>限定 filesystem 視角&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>seccomp / AppArmor / SELinux&lt;/td>
 &lt;td>高（syscall 層）&lt;/td>
 &lt;td>高&lt;/td>
 &lt;td>細粒度限制 syscall&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>Web Worker / V8 isolate&lt;/td>
 &lt;td>中（JavaScript 層）&lt;/td>
 &lt;td>中&lt;/td>
 &lt;td>LLM 跑 user-provided JavaScript&lt;/td>
 &lt;/tr>
 &lt;/tbody>
&lt;/table>
&lt;p>Sandbox 在 LLM 場景的常見配置：&lt;/p>
&lt;ol>
&lt;li>&lt;strong>個人 dev&lt;/strong>：用獨立 OS user 跑 MCP server、限制檔案存取到 workspace；或用 Docker。&lt;/li>
&lt;li>&lt;strong>production agent&lt;/strong>：每個 user / session 一個 ephemeral container、跑完就 destroy。&lt;/li>
&lt;li>&lt;strong>code execution tool&lt;/strong>：把 LLM 生成的 code 丟進 sandbox 跑（如 OpenAI Code Interpreter、Anthropic Claude Code Tool）。&lt;/li>
&lt;/ol>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>理解 sandbox 後可以解釋兩個現象：為什麼跑第三方 MCP server 前 sandbox 是基本配置（MCP 是可執行程式碼、權限上限是「跑該 server 的 user 的權限」）、為什麼 production 場景的 code execution tool 必定在 ephemeral sandbox 內跑（避免長期 state 跟跨 user 殘留）。&lt;/p>
&lt;p>設計 LLM application 時、sandbox 跟 &lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/tool-use/" data-link-title="Tool Use" data-link-desc="LLM 透過結構化呼叫外部工具（讀檔、查資料庫、發 API request）來擴展能力的設計、function calling 跟 MCP 是常見實作">tool use&lt;/a> 的白名單是兩個獨立的防護層、建議都做：白名單擋已知範圍、sandbox 擋未預期的副作用。詳見 &lt;a href="https://tarrragon.github.io/blog/llm/06-security/tool-use-permission-model/" data-link-title="6.2 tool use 與 MCP server 的權限模型" data-link-desc="個人 dev 場景下 tool use / MCP server 的副作用權限：檔案系統 / shell / 網路存取邊界、第三方 MCP 信任、副作用的可逆性">6.2 tool use 與 MCP server 的權限模型&lt;/a>。&lt;/p></description><content:encoded><![CDATA[<p>Sandbox 的核心概念是「把程式跑在權限受限的隔離環境、限制檔案存取、網路連線、系統呼叫的範圍」。在 LLM 場景下、sandbox 用來控制 <a href="/blog/llm/knowledge-cards/tool-use/" data-link-title="Tool Use" data-link-desc="LLM 透過結構化呼叫外部工具（讀檔、查資料庫、發 API request）來擴展能力的設計、function calling 跟 MCP 是常見實作">tool use</a> 跟 MCP server 的副作用範圍：即使 LLM 被 <a href="/blog/llm/knowledge-cards/prompt-injection/" data-link-title="Prompt Injection" data-link-desc="把惡意指令藏進 LLM 會讀到的內容、誘導 LLM 跑出非開發者預期行為的攻擊類別、OWASP LLM01 列入頭號威脅">prompt injection</a> 誘導跑惡意 tool、sandbox 能限制最壞情況的影響面。</p>
<h2 id="概念位置">概念位置</h2>
<p>常見的 sandbox 技術光譜（依隔離強度跟工程成本）：</p>
<table>
  <thead>
      <tr>
          <th>技術</th>
          <th>隔離強度</th>
          <th>工程成本</th>
          <th>LLM 場景的典型用途</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>不同 OS user</td>
          <td>中（檔案權限）</td>
          <td>低</td>
          <td>個人 dev 跑 MCP server</td>
      </tr>
      <tr>
          <td>Docker container</td>
          <td>中高</td>
          <td>中</td>
          <td>跑第三方 MCP server、隔離 LLM agent</td>
      </tr>
      <tr>
          <td>VM / Firecracker / gVisor</td>
          <td>高</td>
          <td>中高</td>
          <td>production 多租戶 LLM agent</td>
      </tr>
      <tr>
          <td>chroot / namespace</td>
          <td>中</td>
          <td>中</td>
          <td>限定 filesystem 視角</td>
      </tr>
      <tr>
          <td>seccomp / AppArmor / SELinux</td>
          <td>高（syscall 層）</td>
          <td>高</td>
          <td>細粒度限制 syscall</td>
      </tr>
      <tr>
          <td>Web Worker / V8 isolate</td>
          <td>中（JavaScript 層）</td>
          <td>中</td>
          <td>LLM 跑 user-provided JavaScript</td>
      </tr>
  </tbody>
</table>
<p>Sandbox 在 LLM 場景的常見配置：</p>
<ol>
<li><strong>個人 dev</strong>：用獨立 OS user 跑 MCP server、限制檔案存取到 workspace；或用 Docker。</li>
<li><strong>production agent</strong>：每個 user / session 一個 ephemeral container、跑完就 destroy。</li>
<li><strong>code execution tool</strong>：把 LLM 生成的 code 丟進 sandbox 跑（如 OpenAI Code Interpreter、Anthropic Claude Code Tool）。</li>
</ol>
<h2 id="設計責任">設計責任</h2>
<p>理解 sandbox 後可以解釋兩個現象：為什麼跑第三方 MCP server 前 sandbox 是基本配置（MCP 是可執行程式碼、權限上限是「跑該 server 的 user 的權限」）、為什麼 production 場景的 code execution tool 必定在 ephemeral sandbox 內跑（避免長期 state 跟跨 user 殘留）。</p>
<p>設計 LLM application 時、sandbox 跟 <a href="/blog/llm/knowledge-cards/tool-use/" data-link-title="Tool Use" data-link-desc="LLM 透過結構化呼叫外部工具（讀檔、查資料庫、發 API request）來擴展能力的設計、function calling 跟 MCP 是常見實作">tool use</a> 的白名單是兩個獨立的防護層、建議都做：白名單擋已知範圍、sandbox 擋未預期的副作用。詳見 <a href="/blog/llm/06-security/tool-use-permission-model/" data-link-title="6.2 tool use 與 MCP server 的權限模型" data-link-desc="個人 dev 場景下 tool use / MCP server 的副作用權限：檔案系統 / shell / 網路存取邊界、第三方 MCP 信任、副作用的可逆性">6.2 tool use 與 MCP server 的權限模型</a>。</p>
]]></content:encoded></item><item><title>Scaffold vs Harness</title><link>https://tarrragon.github.io/blog/llm/knowledge-cards/scaffold-vs-harness/</link><pubDate>Tue, 12 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/llm/knowledge-cards/scaffold-vs-harness/</guid><description>&lt;p>Scaffold 跟 harness 的核心概念是「&lt;strong>把 coding agent 拆成『建構時靜態結構』跟『runtime 動態邏輯』兩層&lt;/strong>」。Scaffold 是建構時就決定的：system prompt 模板、tool schema 註冊、subagent 拓樸；harness 是 runtime 動態運作：tool dispatch、context budget 管理、safety / 中斷、handoff。Claude Code、Cursor、Aider、Codex 這類 coding agent 的內部設計都遵循這個分層。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>兩層的職責劃分：&lt;/p>





&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-text" data-lang="text">&lt;span class="line">&lt;span class="ln"> 1&lt;/span>&lt;span class="cl">Scaffold（建構時、static）：
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 2&lt;/span>&lt;span class="cl"> ├── System prompt 模板（角色、約束、輸出格式）
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 3&lt;/span>&lt;span class="cl"> ├── Tool schema 註冊（read_file / write_file / run_bash 等的 spec）
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 4&lt;/span>&lt;span class="cl"> ├── Subagent 拓樸（main agent + 子 agent 的調用關係）
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 5&lt;/span>&lt;span class="cl"> ├── Skill / playbook 註冊
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 6&lt;/span>&lt;span class="cl"> └── 安全 policy（什麼可寫、什麼要 confirm）
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 7&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 8&lt;/span>&lt;span class="cl"> ↓ 編譯 / 載入
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 9&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">10&lt;/span>&lt;span class="cl">Harness（runtime、dynamic）：
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">11&lt;/span>&lt;span class="cl"> ├── Tool dispatch（接 LLM tool call、執行、回 result）
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">12&lt;/span>&lt;span class="cl"> ├── Context budget 管理（剪裁歷史、塞新內容、不超 25% 規則）
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">13&lt;/span>&lt;span class="cl"> ├── Safety / 中斷（confirm UI、permission boundary、可逆性檢查）
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">14&lt;/span>&lt;span class="cl"> ├── Error recovery（tool failed → retry / fallback / escalate）
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">15&lt;/span>&lt;span class="cl"> └── Telemetry（trace / metrics / cost）&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>跟既有概念的關係：&lt;/p>
&lt;table>
 &lt;thead>
 &lt;tr>
 &lt;th>概念&lt;/th>
 &lt;th>跟 scaffold / harness 的關係&lt;/th>
 &lt;/tr>
 &lt;/thead>
 &lt;tbody>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/system-prompt/" data-link-title="System Prompt" data-link-desc="LLM application 中由開發者預設、不直接顯示給使用者的指令層、定義模型的角色、行為規範、輸出格式">System prompt&lt;/a>&lt;/td>
 &lt;td>Scaffold 的核心元件、定義 agent 角色&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/tool-use/" data-link-title="Tool Use" data-link-desc="LLM 透過結構化呼叫外部工具（讀檔、查資料庫、發 API request）來擴展能力的設計、function calling 跟 MCP 是常見實作">Tool use&lt;/a>&lt;/td>
 &lt;td>Scaffold 註冊 tool spec、Harness 在 runtime dispatch&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/agent-loop/" data-link-title="Agent Loop" data-link-desc="LLM agent 自我循環的工作流：LLM 規劃下一步、執行 tool、看結果、再規劃下一步、直到任務完成或停止條件觸發">Agent loop&lt;/a>&lt;/td>
 &lt;td>Harness 的核心 loop（perceive / reason / act / observe / terminate）&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/function-calling/" data-link-title="Function Calling" data-link-desc="模型訓練階段建立的「呼叫工具」能力：知道何時該呼叫、傳什麼參數">Function calling&lt;/a>&lt;/td>
 &lt;td>Tool spec 的具體 protocol&lt;/td>
 &lt;/tr>
 &lt;/tbody>
&lt;/table>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>讀 coding agent paper / blog 看到「scaffold」「harness」「context engineering」就是這 framing。寫 code 場景的判讀：&lt;/p></description><content:encoded><![CDATA[<p>Scaffold 跟 harness 的核心概念是「<strong>把 coding agent 拆成『建構時靜態結構』跟『runtime 動態邏輯』兩層</strong>」。Scaffold 是建構時就決定的：system prompt 模板、tool schema 註冊、subagent 拓樸；harness 是 runtime 動態運作：tool dispatch、context budget 管理、safety / 中斷、handoff。Claude Code、Cursor、Aider、Codex 這類 coding agent 的內部設計都遵循這個分層。</p>
<h2 id="概念位置">概念位置</h2>
<p>兩層的職責劃分：</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="ln"> 1</span><span class="cl">Scaffold（建構時、static）：
</span></span><span class="line"><span class="ln"> 2</span><span class="cl">  ├── System prompt 模板（角色、約束、輸出格式）
</span></span><span class="line"><span class="ln"> 3</span><span class="cl">  ├── Tool schema 註冊（read_file / write_file / run_bash 等的 spec）
</span></span><span class="line"><span class="ln"> 4</span><span class="cl">  ├── Subagent 拓樸（main agent + 子 agent 的調用關係）
</span></span><span class="line"><span class="ln"> 5</span><span class="cl">  ├── Skill / playbook 註冊
</span></span><span class="line"><span class="ln"> 6</span><span class="cl">  └── 安全 policy（什麼可寫、什麼要 confirm）
</span></span><span class="line"><span class="ln"> 7</span><span class="cl">
</span></span><span class="line"><span class="ln"> 8</span><span class="cl">   ↓ 編譯 / 載入
</span></span><span class="line"><span class="ln"> 9</span><span class="cl">
</span></span><span class="line"><span class="ln">10</span><span class="cl">Harness（runtime、dynamic）：
</span></span><span class="line"><span class="ln">11</span><span class="cl">  ├── Tool dispatch（接 LLM tool call、執行、回 result）
</span></span><span class="line"><span class="ln">12</span><span class="cl">  ├── Context budget 管理（剪裁歷史、塞新內容、不超 25% 規則）
</span></span><span class="line"><span class="ln">13</span><span class="cl">  ├── Safety / 中斷（confirm UI、permission boundary、可逆性檢查）
</span></span><span class="line"><span class="ln">14</span><span class="cl">  ├── Error recovery（tool failed → retry / fallback / escalate）
</span></span><span class="line"><span class="ln">15</span><span class="cl">  └── Telemetry（trace / metrics / cost）</span></span></code></pre></div><p>跟既有概念的關係：</p>
<table>
  <thead>
      <tr>
          <th>概念</th>
          <th>跟 scaffold / harness 的關係</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td><a href="/blog/llm/knowledge-cards/system-prompt/" data-link-title="System Prompt" data-link-desc="LLM application 中由開發者預設、不直接顯示給使用者的指令層、定義模型的角色、行為規範、輸出格式">System prompt</a></td>
          <td>Scaffold 的核心元件、定義 agent 角色</td>
      </tr>
      <tr>
          <td><a href="/blog/llm/knowledge-cards/tool-use/" data-link-title="Tool Use" data-link-desc="LLM 透過結構化呼叫外部工具（讀檔、查資料庫、發 API request）來擴展能力的設計、function calling 跟 MCP 是常見實作">Tool use</a></td>
          <td>Scaffold 註冊 tool spec、Harness 在 runtime dispatch</td>
      </tr>
      <tr>
          <td><a href="/blog/llm/knowledge-cards/agent-loop/" data-link-title="Agent Loop" data-link-desc="LLM agent 自我循環的工作流：LLM 規劃下一步、執行 tool、看結果、再規劃下一步、直到任務完成或停止條件觸發">Agent loop</a></td>
          <td>Harness 的核心 loop（perceive / reason / act / observe / terminate）</td>
      </tr>
      <tr>
          <td><a href="/blog/llm/knowledge-cards/function-calling/" data-link-title="Function Calling" data-link-desc="模型訓練階段建立的「呼叫工具」能力：知道何時該呼叫、傳什麼參數">Function calling</a></td>
          <td>Tool spec 的具體 protocol</td>
      </tr>
  </tbody>
</table>
<h2 id="設計責任">設計責任</h2>
<p>讀 coding agent paper / blog 看到「scaffold」「harness」「context engineering」就是這 framing。寫 code 場景的判讀：</p>
<ol>
<li><strong>看新 coding agent 時、分兩層拆解</strong>：scaffold（system prompt、tool list、subagent 結構）是「設計做了什麼」、harness（context 怎麼裁、tool 怎麼 dispatch、安全怎麼擋）是「runtime 怎麼跑」</li>
<li><strong>修改 / 客製 agent 時、看你動的是哪層</strong>：改 system prompt = 動 scaffold；改 tool 執行邏輯 = 動 harness</li>
<li><strong>跟 <a href="/blog/llm/04-applications/coding-agent-harness/" data-link-title="4.17 Coding agent harness：scaffold / context engineering / subagent" data-link-desc="Coding agent 的內部設計：scaffold vs harness 分層、context budget 25% 規則、subagent 拓樸、跟 Claude Code / Cursor / Aider 的 mapping">4.17 coding-agent harness</a> 的關係</strong>：本卡是定義、4.12 是 coding 場景的工程實務（context budget、scaffold 模式、harness pattern）</li>
</ol>
]]></content:encoded></item><item><title>Self-Attention</title><link>https://tarrragon.github.io/blog/llm/knowledge-cards/self-attention/</link><pubDate>Tue, 12 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/llm/knowledge-cards/self-attention/</guid><description>&lt;p>Self-attention 的核心概念是「Query / Key / Value 三組向量都從&lt;strong>同一個&lt;/strong> sequence 投影出來的 &lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/attention/" data-link-title="Attention" data-link-desc="Transformer 內部讓每個 token 對其他 token 加權平均的核心機制、形成 KV cache 跟 context window 的計算基礎">attention&lt;/a>」。對比下、cross-attention 的 Q 來自一個 sequence、K/V 來自另一個 sequence（如 encoder-decoder 的 decoder 看 encoder）。LLM（decoder-only）每層都是 self-attention、self-attention 是 Transformer 「讓每個 token 看到序列其他 token」的機制本身。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>Self-attention 的計算步驟：&lt;/p>





&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-text" data-lang="text">&lt;span class="line">&lt;span class="ln"> 1&lt;/span>&lt;span class="cl">輸入 sequence: x_1, x_2, ..., x_n（每個是向量）
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 2&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 3&lt;/span>&lt;span class="cl">對每個 token i：
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 4&lt;/span>&lt;span class="cl"> Q_i = x_i × W_Q ← Query：「我要找什麼樣的資訊」
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 5&lt;/span>&lt;span class="cl"> K_i = x_i × W_K ← Key：「我提供什麼樣的資訊」
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 6&lt;/span>&lt;span class="cl"> V_i = x_i × W_V ← Value：「我的實際內容」
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 7&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 8&lt;/span>&lt;span class="cl">attention(Q_i, K, V) = softmax(Q_i · K^T / √d) · V
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 9&lt;/span>&lt;span class="cl"> └─ Q 跟所有 K 算分數、決定權重 ─┘
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">10&lt;/span>&lt;span class="cl"> └─ 加權平均所有 V ─┘&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>關鍵特性：&lt;/p>
&lt;ol>
&lt;li>&lt;strong>Q / K / V 來源相同&lt;/strong>：跟 cross-attention 區分；都從同一個輸入 sequence 投影。&lt;/li>
&lt;li>&lt;strong>每個 token 都跟所有 token 算一次&lt;/strong>：複雜度 O(n²)、是 long context 痛點根源。&lt;/li>
&lt;li>&lt;strong>Causal mask 在 self-attention 內生效&lt;/strong>：LLM 的 &lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/transformer/" data-link-title="Transformer" data-link-desc="寫 code 用的 LLM 神經網路架構：基於 attention 機制、自回歸生成 token">decoder-only&lt;/a> self-attention 加 causal mask、token i 只能看 1~i、不能看 i+1 以後（不能偷看未來）。&lt;/li>
&lt;/ol>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>理解 self-attention 後可以判讀幾件 LLM 設計事：&lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/kv-cache/" data-link-title="KV Cache" data-link-desc="已處理 token 的 attention 中間結果暫存：避免重算、加速後續生成">KV cache&lt;/a> 為什麼有效（自回歸生成時、過去 token 的 K/V 不變、存下來下次直接用）；MHA / GQA / MLA 等變體在動什麼（共享 / 壓縮 K/V 投影、不動 Q）；為什麼長 context 推論慢（self-attention 的 O(n²) 計算）。&lt;/p></description><content:encoded><![CDATA[<p>Self-attention 的核心概念是「Query / Key / Value 三組向量都從<strong>同一個</strong> sequence 投影出來的 <a href="/blog/llm/knowledge-cards/attention/" data-link-title="Attention" data-link-desc="Transformer 內部讓每個 token 對其他 token 加權平均的核心機制、形成 KV cache 跟 context window 的計算基礎">attention</a>」。對比下、cross-attention 的 Q 來自一個 sequence、K/V 來自另一個 sequence（如 encoder-decoder 的 decoder 看 encoder）。LLM（decoder-only）每層都是 self-attention、self-attention 是 Transformer 「讓每個 token 看到序列其他 token」的機制本身。</p>
<h2 id="概念位置">概念位置</h2>
<p>Self-attention 的計算步驟：</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="ln"> 1</span><span class="cl">輸入 sequence: x_1, x_2, ..., x_n（每個是向量）
</span></span><span class="line"><span class="ln"> 2</span><span class="cl">
</span></span><span class="line"><span class="ln"> 3</span><span class="cl">對每個 token i：
</span></span><span class="line"><span class="ln"> 4</span><span class="cl">  Q_i = x_i × W_Q   ← Query：「我要找什麼樣的資訊」
</span></span><span class="line"><span class="ln"> 5</span><span class="cl">  K_i = x_i × W_K   ← Key：「我提供什麼樣的資訊」
</span></span><span class="line"><span class="ln"> 6</span><span class="cl">  V_i = x_i × W_V   ← Value：「我的實際內容」
</span></span><span class="line"><span class="ln"> 7</span><span class="cl">
</span></span><span class="line"><span class="ln"> 8</span><span class="cl">attention(Q_i, K, V) = softmax(Q_i · K^T / √d) · V
</span></span><span class="line"><span class="ln"> 9</span><span class="cl">                       └─ Q 跟所有 K 算分數、決定權重 ─┘
</span></span><span class="line"><span class="ln">10</span><span class="cl">                                                       └─ 加權平均所有 V ─┘</span></span></code></pre></div><p>關鍵特性：</p>
<ol>
<li><strong>Q / K / V 來源相同</strong>：跟 cross-attention 區分；都從同一個輸入 sequence 投影。</li>
<li><strong>每個 token 都跟所有 token 算一次</strong>：複雜度 O(n²)、是 long context 痛點根源。</li>
<li><strong>Causal mask 在 self-attention 內生效</strong>：LLM 的 <a href="/blog/llm/knowledge-cards/transformer/" data-link-title="Transformer" data-link-desc="寫 code 用的 LLM 神經網路架構：基於 attention 機制、自回歸生成 token">decoder-only</a> self-attention 加 causal mask、token i 只能看 1~i、不能看 i+1 以後（不能偷看未來）。</li>
</ol>
<h2 id="設計責任">設計責任</h2>
<p>理解 self-attention 後可以判讀幾件 LLM 設計事：<a href="/blog/llm/knowledge-cards/kv-cache/" data-link-title="KV Cache" data-link-desc="已處理 token 的 attention 中間結果暫存：避免重算、加速後續生成">KV cache</a> 為什麼有效（自回歸生成時、過去 token 的 K/V 不變、存下來下次直接用）；MHA / GQA / MLA 等變體在動什麼（共享 / 壓縮 K/V 投影、不動 Q）；為什麼長 context 推論慢（self-attention 的 O(n²) 計算）。</p>
]]></content:encoded></item><item><title>SentencePiece</title><link>https://tarrragon.github.io/blog/llm/knowledge-cards/sentencepiece/</link><pubDate>Tue, 12 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/llm/knowledge-cards/sentencepiece/</guid><description>&lt;p>SentencePiece（Kudo &amp;amp; Richardson, 2018）的核心概念是「&lt;strong>Google 開源的 tokenization 框架、把『空白也當一個字元』處理、原生支援 &lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/bpe/" data-link-title="BPE（Byte-Pair Encoding）" data-link-desc="用「最常一起出現的字元對」合併建詞彙表的 tokenization 演算法、GPT / Llama 等主流">BPE&lt;/a> 跟 unigram 兩種演算法&lt;/strong>」。Llama、Gemma、Mistral、T5 等模型用 SentencePiece 作為 tokenizer 實作；它的 multilingual 友善度跟「不依賴語言預處理」是被選擇的主因。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>SentencePiece 跟其他 tokenization 路線的對比：&lt;/p>
&lt;table>
 &lt;thead>
 &lt;tr>
 &lt;th>框架 / 路線&lt;/th>
 &lt;th>機制&lt;/th>
 &lt;th>處理多語言 / 空白&lt;/th>
 &lt;th>出現在&lt;/th>
 &lt;/tr>
 &lt;/thead>
 &lt;tbody>
 &lt;tr>
 &lt;td>WordPiece&lt;/td>
 &lt;td>類似 BPE、Google 早期方案&lt;/td>
 &lt;td>需語言預處理（如英文 lowercase）&lt;/td>
 &lt;td>BERT、DistilBERT&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;strong>SentencePiece BPE&lt;/strong>&lt;/td>
 &lt;td>BPE 演算法、空白當特殊字符 &lt;code>▁&lt;/code> 處理&lt;/td>
 &lt;td>統一處理、不需語言預設&lt;/td>
 &lt;td>Llama、Gemma、Mistral&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;strong>SentencePiece Unigram&lt;/strong>&lt;/td>
 &lt;td>機率模型、選一組讓 corpus likelihood 最大的子詞&lt;/td>
 &lt;td>同上、機率視角&lt;/td>
 &lt;td>T5、XLNet、ALBERT&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>tiktoken（OpenAI）&lt;/td>
 &lt;td>Byte-level BPE&lt;/td>
 &lt;td>統一處理&lt;/td>
 &lt;td>GPT-3.5、GPT-4、GPT-5&lt;/td>
 &lt;/tr>
 &lt;/tbody>
&lt;/table>
&lt;p>關鍵特性：&lt;/p>
&lt;ol>
&lt;li>&lt;strong>&lt;code>▁&lt;/code> 表示空白&lt;/strong>：SentencePiece 把空白編碼成 &lt;code>▁&lt;/code>（Unicode U+2581）、所以「Hello world」會被 tokenize 成 &lt;code>[&amp;quot;Hello&amp;quot;, &amp;quot;▁world&amp;quot;]&lt;/code>、保留空白資訊在 token 內。&lt;/li>
&lt;li>&lt;strong>不依賴語言預處理&lt;/strong>：傳統 NLP 要先做 lowercasing、word segmentation；SentencePiece 直接從 raw bytes 開始學、跨語言通用。&lt;/li>
&lt;li>&lt;strong>原生 multilingual&lt;/strong>：訓練 corpus 包含多語言時、tokenizer 自動學會跨語言的子詞單元、不需要為每種語言設定不同 tokenizer。&lt;/li>
&lt;/ol>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>讀 model card / repo 看到 &lt;code>tokenizer.model&lt;/code> 檔案（不是 &lt;code>tokenizer.json&lt;/code> 或 &lt;code>vocab.txt&lt;/code>）就是 SentencePiece 用的 protobuf 格式。寫 code 場景的意涵：SentencePiece tokenizer 在中文 / 多語言任務上比 WordPiece 友好；換 tokenizer 等於整個 &lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/embedding-layer/" data-link-title="Embedding Layer" data-link-desc="Transformer 第一層的查表結構、把整數 token ID 轉成可運算的向量">embedding layer&lt;/a> 失效、所以 fine-tune 時不會動 tokenizer。&lt;/p></description><content:encoded><![CDATA[<p>SentencePiece（Kudo &amp; Richardson, 2018）的核心概念是「<strong>Google 開源的 tokenization 框架、把『空白也當一個字元』處理、原生支援 <a href="/blog/llm/knowledge-cards/bpe/" data-link-title="BPE（Byte-Pair Encoding）" data-link-desc="用「最常一起出現的字元對」合併建詞彙表的 tokenization 演算法、GPT / Llama 等主流">BPE</a> 跟 unigram 兩種演算法</strong>」。Llama、Gemma、Mistral、T5 等模型用 SentencePiece 作為 tokenizer 實作；它的 multilingual 友善度跟「不依賴語言預處理」是被選擇的主因。</p>
<h2 id="概念位置">概念位置</h2>
<p>SentencePiece 跟其他 tokenization 路線的對比：</p>
<table>
  <thead>
      <tr>
          <th>框架 / 路線</th>
          <th>機制</th>
          <th>處理多語言 / 空白</th>
          <th>出現在</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>WordPiece</td>
          <td>類似 BPE、Google 早期方案</td>
          <td>需語言預處理（如英文 lowercase）</td>
          <td>BERT、DistilBERT</td>
      </tr>
      <tr>
          <td><strong>SentencePiece BPE</strong></td>
          <td>BPE 演算法、空白當特殊字符 <code>▁</code> 處理</td>
          <td>統一處理、不需語言預設</td>
          <td>Llama、Gemma、Mistral</td>
      </tr>
      <tr>
          <td><strong>SentencePiece Unigram</strong></td>
          <td>機率模型、選一組讓 corpus likelihood 最大的子詞</td>
          <td>同上、機率視角</td>
          <td>T5、XLNet、ALBERT</td>
      </tr>
      <tr>
          <td>tiktoken（OpenAI）</td>
          <td>Byte-level BPE</td>
          <td>統一處理</td>
          <td>GPT-3.5、GPT-4、GPT-5</td>
      </tr>
  </tbody>
</table>
<p>關鍵特性：</p>
<ol>
<li><strong><code>▁</code> 表示空白</strong>：SentencePiece 把空白編碼成 <code>▁</code>（Unicode U+2581）、所以「Hello world」會被 tokenize 成 <code>[&quot;Hello&quot;, &quot;▁world&quot;]</code>、保留空白資訊在 token 內。</li>
<li><strong>不依賴語言預處理</strong>：傳統 NLP 要先做 lowercasing、word segmentation；SentencePiece 直接從 raw bytes 開始學、跨語言通用。</li>
<li><strong>原生 multilingual</strong>：訓練 corpus 包含多語言時、tokenizer 自動學會跨語言的子詞單元、不需要為每種語言設定不同 tokenizer。</li>
</ol>
<h2 id="設計責任">設計責任</h2>
<p>讀 model card / repo 看到 <code>tokenizer.model</code> 檔案（不是 <code>tokenizer.json</code> 或 <code>vocab.txt</code>）就是 SentencePiece 用的 protobuf 格式。寫 code 場景的意涵：SentencePiece tokenizer 在中文 / 多語言任務上比 WordPiece 友好；換 tokenizer 等於整個 <a href="/blog/llm/knowledge-cards/embedding-layer/" data-link-title="Embedding Layer" data-link-desc="Transformer 第一層的查表結構、把整數 token ID 轉成可運算的向量">embedding layer</a> 失效、所以 fine-tune 時不會動 tokenizer。</p>
]]></content:encoded></item><item><title>SFT（Supervised Fine-Tuning）</title><link>https://tarrragon.github.io/blog/llm/knowledge-cards/sft/</link><pubDate>Tue, 12 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/llm/knowledge-cards/sft/</guid><description>&lt;p>SFT（Supervised Fine-Tuning、指令微調）的核心概念是「在 &lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/base-model/" data-link-title="Base Model" data-link-desc="未經指令微調的原始模型：擅長文字接龍、適合下游微調用途">base model&lt;/a> 上、用人類示範的『指令-回答』成對資料做監督式 fine-tune、讓模型從『接龍』變成『跟指令走』」。SFT 是 &lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/pre-training/" data-link-title="Pre-training" data-link-desc="LLM 訓練的第一階段：用 trillion-token 級網路文字做 next-token prediction、得到 base model">pre-training&lt;/a> 跟 alignment（&lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/rlhf/" data-link-title="RLHF" data-link-desc="Reinforcement Learning from Human Feedback：用人類偏好訓練的 reward model 透過 RL 對齊 LLM">RLHF&lt;/a> / &lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/dpo/" data-link-title="DPO（Direct Preference Optimization）" data-link-desc="RLHF 的簡化替代：跳過 reward model、直接從人類偏好資料 fine-tune LLM">DPO&lt;/a>）之間的橋。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>SFT 在訓練 pipeline 的位置與資料形態：&lt;/p>





&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-text" data-lang="text">&lt;span class="line">&lt;span class="ln">1&lt;/span>&lt;span class="cl">資料格式（典型）：
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">2&lt;/span>&lt;span class="cl"> {&amp;#34;instruction&amp;#34;: &amp;#34;寫一個 Python fibonacci&amp;#34;,
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">3&lt;/span>&lt;span class="cl"> &amp;#34;response&amp;#34;: &amp;#34;def fib(n): ...&amp;#34;}
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">4&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">5&lt;/span>&lt;span class="cl">訓練：
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">6&lt;/span>&lt;span class="cl"> 把 instruction + response 連起來、跑跟 pre-training 一樣的 next-token prediction
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">7&lt;/span>&lt;span class="cl"> 但 loss 只算 response token 上的 cross-entropy（instruction 部分不算）&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>SFT 後同一個模型行為大改：&lt;/p>
&lt;table>
 &lt;thead>
 &lt;tr>
 &lt;th>問同樣問題「寫一個 Python fibonacci」&lt;/th>
 &lt;th>Base model（pre-training 後）&lt;/th>
 &lt;th>Instruction-tuned model（SFT 後）&lt;/th>
 &lt;/tr>
 &lt;/thead>
 &lt;tbody>
 &lt;tr>
 &lt;td>行為&lt;/td>
 &lt;td>純文字接龍：「寫一個 Python fibonacci。寫一個 JavaScript fibonacci。寫一個 Rust&amp;hellip;」&lt;/td>
 &lt;td>直接給出 fibonacci 函式實作&lt;/td>
 &lt;/tr>
 &lt;/tbody>
&lt;/table>
&lt;p>關鍵特性：&lt;/p>
&lt;ol>
&lt;li>&lt;strong>資料量遠小於 pre-training&lt;/strong>：幾萬到幾百萬筆指令-回答對、相對 pre-training 的兆級 token 是小數字。&lt;/li>
&lt;li>&lt;strong>訓練成本相對低&lt;/strong>：通常幾百到幾千 GPU-hour、可在單機完成。&lt;/li>
&lt;li>&lt;strong>容易過擬合 / 災難遺忘&lt;/strong>：SFT 資料太少 / 太特化時、模型可能丟掉 pre-training 學到的能力、見 &lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/lora/" data-link-title="LoRA" data-link-desc="Low-Rank Adaptation：凍住原模型權重、只訓兩個小矩陣的 parameter-efficient fine-tuning">LoRA&lt;/a> 的設計動機。&lt;/li>
&lt;/ol>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>讀 model card 看到「instruct」「chat」「-it」「sft」等 suffix、就是經過 SFT 的版本。寫 code 場景用的模型幾乎都是 SFT 後的（base model 對話能力差、實用度低）。Coding-tuned 模型（如 Qwen3-Coder）是 SFT 階段大量加入 code 對話資料的特化版本、跟通用 instruct 模型在 code 任務上有可觀差距。&lt;/p></description><content:encoded><![CDATA[<p>SFT（Supervised Fine-Tuning、指令微調）的核心概念是「在 <a href="/blog/llm/knowledge-cards/base-model/" data-link-title="Base Model" data-link-desc="未經指令微調的原始模型：擅長文字接龍、適合下游微調用途">base model</a> 上、用人類示範的『指令-回答』成對資料做監督式 fine-tune、讓模型從『接龍』變成『跟指令走』」。SFT 是 <a href="/blog/llm/knowledge-cards/pre-training/" data-link-title="Pre-training" data-link-desc="LLM 訓練的第一階段：用 trillion-token 級網路文字做 next-token prediction、得到 base model">pre-training</a> 跟 alignment（<a href="/blog/llm/knowledge-cards/rlhf/" data-link-title="RLHF" data-link-desc="Reinforcement Learning from Human Feedback：用人類偏好訓練的 reward model 透過 RL 對齊 LLM">RLHF</a> / <a href="/blog/llm/knowledge-cards/dpo/" data-link-title="DPO（Direct Preference Optimization）" data-link-desc="RLHF 的簡化替代：跳過 reward model、直接從人類偏好資料 fine-tune LLM">DPO</a>）之間的橋。</p>
<h2 id="概念位置">概念位置</h2>
<p>SFT 在訓練 pipeline 的位置與資料形態：</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="ln">1</span><span class="cl">資料格式（典型）：
</span></span><span class="line"><span class="ln">2</span><span class="cl">  {&#34;instruction&#34;: &#34;寫一個 Python fibonacci&#34;,
</span></span><span class="line"><span class="ln">3</span><span class="cl">   &#34;response&#34;:    &#34;def fib(n): ...&#34;}
</span></span><span class="line"><span class="ln">4</span><span class="cl">
</span></span><span class="line"><span class="ln">5</span><span class="cl">訓練：
</span></span><span class="line"><span class="ln">6</span><span class="cl">  把 instruction + response 連起來、跑跟 pre-training 一樣的 next-token prediction
</span></span><span class="line"><span class="ln">7</span><span class="cl">  但 loss 只算 response token 上的 cross-entropy（instruction 部分不算）</span></span></code></pre></div><p>SFT 後同一個模型行為大改：</p>
<table>
  <thead>
      <tr>
          <th>問同樣問題「寫一個 Python fibonacci」</th>
          <th>Base model（pre-training 後）</th>
          <th>Instruction-tuned model（SFT 後）</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>行為</td>
          <td>純文字接龍：「寫一個 Python fibonacci。寫一個 JavaScript fibonacci。寫一個 Rust&hellip;」</td>
          <td>直接給出 fibonacci 函式實作</td>
      </tr>
  </tbody>
</table>
<p>關鍵特性：</p>
<ol>
<li><strong>資料量遠小於 pre-training</strong>：幾萬到幾百萬筆指令-回答對、相對 pre-training 的兆級 token 是小數字。</li>
<li><strong>訓練成本相對低</strong>：通常幾百到幾千 GPU-hour、可在單機完成。</li>
<li><strong>容易過擬合 / 災難遺忘</strong>：SFT 資料太少 / 太特化時、模型可能丟掉 pre-training 學到的能力、見 <a href="/blog/llm/knowledge-cards/lora/" data-link-title="LoRA" data-link-desc="Low-Rank Adaptation：凍住原模型權重、只訓兩個小矩陣的 parameter-efficient fine-tuning">LoRA</a> 的設計動機。</li>
</ol>
<h2 id="設計責任">設計責任</h2>
<p>讀 model card 看到「instruct」「chat」「-it」「sft」等 suffix、就是經過 SFT 的版本。寫 code 場景用的模型幾乎都是 SFT 後的（base model 對話能力差、實用度低）。Coding-tuned 模型（如 Qwen3-Coder）是 SFT 階段大量加入 code 對話資料的特化版本、跟通用 instruct 模型在 code 任務上有可觀差距。</p>
]]></content:encoded></item><item><title>SGD</title><link>https://tarrragon.github.io/blog/llm/knowledge-cards/sgd/</link><pubDate>Tue, 12 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/llm/knowledge-cards/sgd/</guid><description>&lt;p>SGD（Stochastic Gradient Descent、隨機梯度下降）的核心概念是「每次只用一小批資料（mini-batch）算 &lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/gradient/" data-link-title="Gradient" data-link-desc="loss function 對權重的偏微分向量、指出「該往哪個方向調權重才能讓 loss 下降最快」">gradient&lt;/a>、更新權重」。對比的是 vanilla gradient descent（用全部資料算一次 gradient）：full-batch 在 trillion-token 級資料下完全不可行、SGD 用 mini-batch 把記憶體跟計算成本拉到可行範圍。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>SGD 的更新公式：&lt;/p>





&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-text" data-lang="text">&lt;span class="line">&lt;span class="ln">1&lt;/span>&lt;span class="cl">W_new = W_old - learning_rate × gradient_of_loss_on_minibatch&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>跟其他 optimizer 的對比：&lt;/p>
&lt;table>
 &lt;thead>
 &lt;tr>
 &lt;th>Optimizer&lt;/th>
 &lt;th>更新規則&lt;/th>
 &lt;th>特性&lt;/th>
 &lt;/tr>
 &lt;/thead>
 &lt;tbody>
 &lt;tr>
 &lt;td>SGD&lt;/td>
 &lt;td>&lt;code>W -= lr × g&lt;/code>&lt;/td>
 &lt;td>簡單、慢、容易卡 local minimum&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>SGD + Momentum&lt;/td>
 &lt;td>加速度項：&lt;code>v = μv + g; W -= lr × v&lt;/code>&lt;/td>
 &lt;td>衝過 saddle point、收斂較穩&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/adam-adamw/" data-link-title="Adam / AdamW" data-link-desc="對每個參數自適應 learning rate 的 optimizer、LLM 訓練主流選擇">Adam / AdamW&lt;/a>&lt;/td>
 &lt;td>對每個參數自適應 lr、用 gradient 的 EMA 跟二階矩&lt;/td>
 &lt;td>對 lr 較不敏感、LLM 訓練主流&lt;/td>
 &lt;/tr>
 &lt;/tbody>
&lt;/table>
&lt;p>LLM 訓練幾乎都用 Adam / AdamW、不是純 SGD。但 SGD 仍出現在：&lt;/p>
&lt;ol>
&lt;li>&lt;strong>小模型 / 簡單任務&lt;/strong>：fine-tune 小 vision 模型、SGD + momentum 仍是合理選擇。&lt;/li>
&lt;li>&lt;strong>理論分析 / 教學&lt;/strong>：SGD 是最簡單的 optimizer、用來解釋 gradient descent 概念。&lt;/li>
&lt;li>&lt;strong>某些 fine-tuning 場景&lt;/strong>：&lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/lora/" data-link-title="LoRA" data-link-desc="Low-Rank Adaptation：凍住原模型權重、只訓兩個小矩陣的 parameter-efficient fine-tuning">LoRA&lt;/a> 或 SFT 偶爾用 SGD（避免 Adam 改變 base model 太多）。&lt;/li>
&lt;/ol>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>讀 paper / training script 看到 optimizer 選擇、SGD 是基線、其他 optimizer 通常是「對 SGD 的改進」。寫 code 場景的判讀：訓練自己的小模型可以從 SGD + momentum 開始；fine-tune 大 LLM 沒理由不用 AdamW。&lt;/p></description><content:encoded><![CDATA[<p>SGD（Stochastic Gradient Descent、隨機梯度下降）的核心概念是「每次只用一小批資料（mini-batch）算 <a href="/blog/llm/knowledge-cards/gradient/" data-link-title="Gradient" data-link-desc="loss function 對權重的偏微分向量、指出「該往哪個方向調權重才能讓 loss 下降最快」">gradient</a>、更新權重」。對比的是 vanilla gradient descent（用全部資料算一次 gradient）：full-batch 在 trillion-token 級資料下完全不可行、SGD 用 mini-batch 把記憶體跟計算成本拉到可行範圍。</p>
<h2 id="概念位置">概念位置</h2>
<p>SGD 的更新公式：</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="ln">1</span><span class="cl">W_new = W_old - learning_rate × gradient_of_loss_on_minibatch</span></span></code></pre></div><p>跟其他 optimizer 的對比：</p>
<table>
  <thead>
      <tr>
          <th>Optimizer</th>
          <th>更新規則</th>
          <th>特性</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>SGD</td>
          <td><code>W -= lr × g</code></td>
          <td>簡單、慢、容易卡 local minimum</td>
      </tr>
      <tr>
          <td>SGD + Momentum</td>
          <td>加速度項：<code>v = μv + g; W -= lr × v</code></td>
          <td>衝過 saddle point、收斂較穩</td>
      </tr>
      <tr>
          <td><a href="/blog/llm/knowledge-cards/adam-adamw/" data-link-title="Adam / AdamW" data-link-desc="對每個參數自適應 learning rate 的 optimizer、LLM 訓練主流選擇">Adam / AdamW</a></td>
          <td>對每個參數自適應 lr、用 gradient 的 EMA 跟二階矩</td>
          <td>對 lr 較不敏感、LLM 訓練主流</td>
      </tr>
  </tbody>
</table>
<p>LLM 訓練幾乎都用 Adam / AdamW、不是純 SGD。但 SGD 仍出現在：</p>
<ol>
<li><strong>小模型 / 簡單任務</strong>：fine-tune 小 vision 模型、SGD + momentum 仍是合理選擇。</li>
<li><strong>理論分析 / 教學</strong>：SGD 是最簡單的 optimizer、用來解釋 gradient descent 概念。</li>
<li><strong>某些 fine-tuning 場景</strong>：<a href="/blog/llm/knowledge-cards/lora/" data-link-title="LoRA" data-link-desc="Low-Rank Adaptation：凍住原模型權重、只訓兩個小矩陣的 parameter-efficient fine-tuning">LoRA</a> 或 SFT 偶爾用 SGD（避免 Adam 改變 base model 太多）。</li>
</ol>
<h2 id="設計責任">設計責任</h2>
<p>讀 paper / training script 看到 optimizer 選擇、SGD 是基線、其他 optimizer 通常是「對 SGD 的改進」。寫 code 場景的判讀：訓練自己的小模型可以從 SGD + momentum 開始；fine-tune 大 LLM 沒理由不用 AdamW。</p>
]]></content:encoded></item><item><title>Shell 背景 Process</title><link>https://tarrragon.github.io/blog/llm/knowledge-cards/shell-background-process/</link><pubDate>Tue, 12 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/llm/knowledge-cards/shell-background-process/</guid><description>&lt;p>Shell 背景 Process 的核心概念是「terminal 啟動的程式何時跟 shell 綁定、何時可以脫離、被 shell 用什麼方式管理」。本地 LLM 場景中、&lt;code>ollama serve&lt;/code> 這類常駐 server 需要持續跑、放前景會把 terminal 卡住、放背景才能繼續打其他指令、或關掉 terminal 後讓服務改交給 &lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/launchd-service/" data-link-title="launchd Service" data-link-desc="macOS 原生的服務管理機制、把 process 註冊成自動啟動的 daemon 或 agent">launchd service&lt;/a> 接手。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>Shell（zsh / bash）執行一個程式時、預設讓程式佔住 terminal、stdin / stdout / stderr 直接連到使用者眼前的視窗、稱為&lt;strong>前景 process&lt;/strong>。指令尾巴加 &lt;code>&amp;amp;&lt;/code> 改成&lt;strong>背景 process&lt;/strong>、shell 立刻拿回 prompt 控制權、程式繼續跑但不佔住 terminal。背景 process 仍綁在當前 shell session、關掉 terminal 視窗時通常會被 SIGHUP 終止；要完全脫離 shell 生命週期、得改用 &lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/launchd-service/" data-link-title="launchd Service" data-link-desc="macOS 原生的服務管理機制、把 process 註冊成自動啟動的 daemon 或 agent">launchd service&lt;/a> 或 &lt;code>nohup&lt;/code> / &lt;code>disown&lt;/code> 等機制。&lt;/p>
&lt;h2 id="可觀察訊號與例子">可觀察訊號與例子&lt;/h2>
&lt;p>shell 控制 process 的關鍵操作：&lt;/p>
&lt;table>
 &lt;thead>
 &lt;tr>
 &lt;th>動作&lt;/th>
 &lt;th>指令 / 按鍵&lt;/th>
 &lt;th>效果&lt;/th>
 &lt;/tr>
 &lt;/thead>
 &lt;tbody>
 &lt;tr>
 &lt;td>前景跑&lt;/td>
 &lt;td>&lt;code>ollama serve&lt;/code>&lt;/td>
 &lt;td>terminal 被卡住、看到 process stdout&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>背景跑&lt;/td>
 &lt;td>&lt;code>ollama serve &amp;amp;&lt;/code>&lt;/td>
 &lt;td>拿回 prompt、程式仍在跑&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>中止前景 process&lt;/td>
 &lt;td>&lt;code>Ctrl+C&lt;/code>&lt;/td>
 &lt;td>送 SIGINT、多數程式收到後優雅退出&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>暫停前景 process&lt;/td>
 &lt;td>&lt;code>Ctrl+Z&lt;/code>&lt;/td>
 &lt;td>送 SIGTSTP、process 進 stopped 狀態&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>列出當前 shell jobs&lt;/td>
 &lt;td>&lt;code>jobs&lt;/code>&lt;/td>
 &lt;td>看 shell 管理的背景 / 暫停 job&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>把 job 拉回前景&lt;/td>
 &lt;td>&lt;code>fg %1&lt;/code>&lt;/td>
 &lt;td>1 號 job 變前景&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>把暫停 job 改背景&lt;/td>
 &lt;td>&lt;code>bg %1&lt;/code>&lt;/td>
 &lt;td>1 號 job 改背景繼續跑&lt;/td>
 &lt;/tr>
 &lt;/tbody>
&lt;/table>
&lt;p>排錯常用的兩個工具（兩者跟 shell job 不直接相關、是 macOS 系統工具）：&lt;/p>
&lt;table>
 &lt;thead>
 &lt;tr>
 &lt;th>指令&lt;/th>
 &lt;th>用途&lt;/th>
 &lt;/tr>
 &lt;/thead>
 &lt;tbody>
 &lt;tr>
 &lt;td>&lt;code>lsof -i :11434&lt;/code>&lt;/td>
 &lt;td>找出哪個 process 在聽 11434 &lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/port-and-localhost/" data-link-title="Port 與 Localhost" data-link-desc="TCP port 與 listen address 如何決定 API server 的對外暴露範圍">port&lt;/a>&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;code>pkill -f &amp;quot;ollama serve&amp;quot;&lt;/code>&lt;/td>
 &lt;td>用 pattern 匹配 process 命令列、送 SIGTERM 終止&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;code>ps aux | grep ollama&lt;/code>&lt;/td>
 &lt;td>列出所有跟 ollama 有關的 process&lt;/td>
 &lt;/tr>
 &lt;/tbody>
&lt;/table>
&lt;p>對 macOS 新手最常遇到的兩個事故：一個是「前景跑 server 後不知道怎麼脫身」、解法是 &lt;code>Ctrl+Z&lt;/code> 暫停 + &lt;code>bg&lt;/code> 改背景、或下次改用 &lt;code>&amp;amp;&lt;/code> 啟動；另一個是「pkill 沒指定夠精確的 pattern、誤殺其他 process」、解法是先用 &lt;code>ps aux&lt;/code> 加 &lt;code>grep&lt;/code> 確認 PID 再 kill。&lt;/p></description><content:encoded><![CDATA[<p>Shell 背景 Process 的核心概念是「terminal 啟動的程式何時跟 shell 綁定、何時可以脫離、被 shell 用什麼方式管理」。本地 LLM 場景中、<code>ollama serve</code> 這類常駐 server 需要持續跑、放前景會把 terminal 卡住、放背景才能繼續打其他指令、或關掉 terminal 後讓服務改交給 <a href="/blog/llm/knowledge-cards/launchd-service/" data-link-title="launchd Service" data-link-desc="macOS 原生的服務管理機制、把 process 註冊成自動啟動的 daemon 或 agent">launchd service</a> 接手。</p>
<h2 id="概念位置">概念位置</h2>
<p>Shell（zsh / bash）執行一個程式時、預設讓程式佔住 terminal、stdin / stdout / stderr 直接連到使用者眼前的視窗、稱為<strong>前景 process</strong>。指令尾巴加 <code>&amp;</code> 改成<strong>背景 process</strong>、shell 立刻拿回 prompt 控制權、程式繼續跑但不佔住 terminal。背景 process 仍綁在當前 shell session、關掉 terminal 視窗時通常會被 SIGHUP 終止；要完全脫離 shell 生命週期、得改用 <a href="/blog/llm/knowledge-cards/launchd-service/" data-link-title="launchd Service" data-link-desc="macOS 原生的服務管理機制、把 process 註冊成自動啟動的 daemon 或 agent">launchd service</a> 或 <code>nohup</code> / <code>disown</code> 等機制。</p>
<h2 id="可觀察訊號與例子">可觀察訊號與例子</h2>
<p>shell 控制 process 的關鍵操作：</p>
<table>
  <thead>
      <tr>
          <th>動作</th>
          <th>指令 / 按鍵</th>
          <th>效果</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>前景跑</td>
          <td><code>ollama serve</code></td>
          <td>terminal 被卡住、看到 process stdout</td>
      </tr>
      <tr>
          <td>背景跑</td>
          <td><code>ollama serve &amp;</code></td>
          <td>拿回 prompt、程式仍在跑</td>
      </tr>
      <tr>
          <td>中止前景 process</td>
          <td><code>Ctrl+C</code></td>
          <td>送 SIGINT、多數程式收到後優雅退出</td>
      </tr>
      <tr>
          <td>暫停前景 process</td>
          <td><code>Ctrl+Z</code></td>
          <td>送 SIGTSTP、process 進 stopped 狀態</td>
      </tr>
      <tr>
          <td>列出當前 shell jobs</td>
          <td><code>jobs</code></td>
          <td>看 shell 管理的背景 / 暫停 job</td>
      </tr>
      <tr>
          <td>把 job 拉回前景</td>
          <td><code>fg %1</code></td>
          <td>1 號 job 變前景</td>
      </tr>
      <tr>
          <td>把暫停 job 改背景</td>
          <td><code>bg %1</code></td>
          <td>1 號 job 改背景繼續跑</td>
      </tr>
  </tbody>
</table>
<p>排錯常用的兩個工具（兩者跟 shell job 不直接相關、是 macOS 系統工具）：</p>
<table>
  <thead>
      <tr>
          <th>指令</th>
          <th>用途</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td><code>lsof -i :11434</code></td>
          <td>找出哪個 process 在聽 11434 <a href="/blog/llm/knowledge-cards/port-and-localhost/" data-link-title="Port 與 Localhost" data-link-desc="TCP port 與 listen address 如何決定 API server 的對外暴露範圍">port</a></td>
      </tr>
      <tr>
          <td><code>pkill -f &quot;ollama serve&quot;</code></td>
          <td>用 pattern 匹配 process 命令列、送 SIGTERM 終止</td>
      </tr>
      <tr>
          <td><code>ps aux | grep ollama</code></td>
          <td>列出所有跟 ollama 有關的 process</td>
      </tr>
  </tbody>
</table>
<p>對 macOS 新手最常遇到的兩個事故：一個是「前景跑 server 後不知道怎麼脫身」、解法是 <code>Ctrl+Z</code> 暫停 + <code>bg</code> 改背景、或下次改用 <code>&amp;</code> 啟動；另一個是「pkill 沒指定夠精確的 pattern、誤殺其他 process」、解法是先用 <code>ps aux</code> 加 <code>grep</code> 確認 PID 再 kill。</p>
<h2 id="設計責任">設計責任</h2>
<p>選前景 vs 背景的判讀：debug 場景前景跑、能直接看到 log；日常使用改 <a href="/blog/llm/knowledge-cards/launchd-service/" data-link-title="launchd Service" data-link-desc="macOS 原生的服務管理機制、把 process 註冊成自動啟動的 daemon 或 agent">launchd service</a> 跑、跟 shell session 完全脫鉤。<code>&amp;</code> 適合「terminal 開著就讓它跑、關掉也沒關係」的臨時場景、不適合需要長期穩定的服務。排錯時養成「先 <code>lsof</code> 找誰佔資源、再 <code>ps</code> 確認身分、最後才 kill」的順序、避免誤殺。</p>
]]></content:encoded></item><item><title>Softmax</title><link>https://tarrragon.github.io/blog/llm/knowledge-cards/softmax/</link><pubDate>Tue, 12 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/llm/knowledge-cards/softmax/</guid><description>&lt;p>Softmax 的核心概念是「把一串實數轉成機率分佈」。公式是 &lt;code>softmax(x_i) = exp(x_i) / sum(exp(x_j))&lt;/code>、輸出總和為 1、每個值 ∈ [0, 1]。它是 LLM 兩個關鍵環節的常駐元件：&lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/attention/" data-link-title="Attention" data-link-desc="Transformer 內部讓每個 token 對其他 token 加權平均的核心機制、形成 KV cache 跟 context window 的計算基礎">attention&lt;/a> 的權重計算、跟 sampling 階段把 &lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/logit/" data-link-title="Logit" data-link-desc="softmax 之前的原始實數分數、每個 vocab token 一個值、可正可負">logit&lt;/a> 轉成「下個 token 的機率分佈」。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>LLM 中 softmax 出現的兩個位置：&lt;/p>





&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-text" data-lang="text">&lt;span class="line">&lt;span class="ln">1&lt;/span>&lt;span class="cl">位置 1：Attention 內部
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">2&lt;/span>&lt;span class="cl"> Q · K^T → 一堆 score
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">3&lt;/span>&lt;span class="cl"> softmax(scores) → attention weight（總和 1）
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">4&lt;/span>&lt;span class="cl"> weight · V → output
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">5&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">6&lt;/span>&lt;span class="cl">位置 2：每次 token 生成的最後一步
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">7&lt;/span>&lt;span class="cl"> 最後一層 hidden → logit（每個 vocab token 一個實數分數）
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">8&lt;/span>&lt;span class="cl"> softmax(logits / temperature) → 機率分佈
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">9&lt;/span>&lt;span class="cl"> 從這個分佈 sample 出下一個 token&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>兩個位置的關鍵差異：&lt;/p>
&lt;table>
 &lt;thead>
 &lt;tr>
 &lt;th>位置&lt;/th>
 &lt;th>softmax 的作用&lt;/th>
 &lt;th>影響&lt;/th>
 &lt;/tr>
 &lt;/thead>
 &lt;tbody>
 &lt;tr>
 &lt;td>Attention&lt;/td>
 &lt;td>把 attention score 正規化成「該關注多少」&lt;/td>
 &lt;td>影響模型怎麼整合 context 資訊&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>Sampling 端&lt;/td>
 &lt;td>把 logit 變機率、配合 temperature 調分佈陡度&lt;/td>
 &lt;td>影響輸出的多樣性 / 確定性&lt;/td>
 &lt;/tr>
 &lt;/tbody>
&lt;/table>
&lt;p>Temperature 在 sampling 端跟 softmax 結合：&lt;code>softmax(logits / T)&lt;/code>、T 越小分佈越尖（接近 greedy）、T 越大分佈越平（接近隨機）。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>理解 softmax 後可以判讀幾件事：temperature 為什麼影響輸出多樣性（改的是 softmax 前的縮放）、為什麼 &lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/logit/" data-link-title="Logit" data-link-desc="softmax 之前的原始實數分數、每個 vocab token 一個值、可正可負">logit&lt;/a> bias / logit warping 等技巧能控制輸出（直接動 softmax 的輸入）、為什麼 &lt;a href="https://tarrragon.github.io/blog/llm/04-applications/tool-use-principles/" data-link-title="4.3 Tool use 原理：LLM 跟外部世界互動" data-link-desc="Structured output 是 LLM 跨入工程系統的橋、function calling 取捨、為什麼本地小模型 tool use 表現崩潰">structured output&lt;/a> 的 grammar-constrained sampling 是「把不合法 token 的機率歸零」（在 softmax 後或前做 masking）。&lt;/p></description><content:encoded><![CDATA[<p>Softmax 的核心概念是「把一串實數轉成機率分佈」。公式是 <code>softmax(x_i) = exp(x_i) / sum(exp(x_j))</code>、輸出總和為 1、每個值 ∈ [0, 1]。它是 LLM 兩個關鍵環節的常駐元件：<a href="/blog/llm/knowledge-cards/attention/" data-link-title="Attention" data-link-desc="Transformer 內部讓每個 token 對其他 token 加權平均的核心機制、形成 KV cache 跟 context window 的計算基礎">attention</a> 的權重計算、跟 sampling 階段把 <a href="/blog/llm/knowledge-cards/logit/" data-link-title="Logit" data-link-desc="softmax 之前的原始實數分數、每個 vocab token 一個值、可正可負">logit</a> 轉成「下個 token 的機率分佈」。</p>
<h2 id="概念位置">概念位置</h2>
<p>LLM 中 softmax 出現的兩個位置：</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="ln">1</span><span class="cl">位置 1：Attention 內部
</span></span><span class="line"><span class="ln">2</span><span class="cl">  Q · K^T → 一堆 score
</span></span><span class="line"><span class="ln">3</span><span class="cl">  softmax(scores) → attention weight（總和 1）
</span></span><span class="line"><span class="ln">4</span><span class="cl">  weight · V → output
</span></span><span class="line"><span class="ln">5</span><span class="cl">
</span></span><span class="line"><span class="ln">6</span><span class="cl">位置 2：每次 token 生成的最後一步
</span></span><span class="line"><span class="ln">7</span><span class="cl">  最後一層 hidden → logit（每個 vocab token 一個實數分數）
</span></span><span class="line"><span class="ln">8</span><span class="cl">  softmax(logits / temperature) → 機率分佈
</span></span><span class="line"><span class="ln">9</span><span class="cl">  從這個分佈 sample 出下一個 token</span></span></code></pre></div><p>兩個位置的關鍵差異：</p>
<table>
  <thead>
      <tr>
          <th>位置</th>
          <th>softmax 的作用</th>
          <th>影響</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>Attention</td>
          <td>把 attention score 正規化成「該關注多少」</td>
          <td>影響模型怎麼整合 context 資訊</td>
      </tr>
      <tr>
          <td>Sampling 端</td>
          <td>把 logit 變機率、配合 temperature 調分佈陡度</td>
          <td>影響輸出的多樣性 / 確定性</td>
      </tr>
  </tbody>
</table>
<p>Temperature 在 sampling 端跟 softmax 結合：<code>softmax(logits / T)</code>、T 越小分佈越尖（接近 greedy）、T 越大分佈越平（接近隨機）。</p>
<h2 id="設計責任">設計責任</h2>
<p>理解 softmax 後可以判讀幾件事：temperature 為什麼影響輸出多樣性（改的是 softmax 前的縮放）、為什麼 <a href="/blog/llm/knowledge-cards/logit/" data-link-title="Logit" data-link-desc="softmax 之前的原始實數分數、每個 vocab token 一個值、可正可負">logit</a> bias / logit warping 等技巧能控制輸出（直接動 softmax 的輸入）、為什麼 <a href="/blog/llm/04-applications/tool-use-principles/" data-link-title="4.3 Tool use 原理：LLM 跟外部世界互動" data-link-desc="Structured output 是 LLM 跨入工程系統的橋、function calling 取捨、為什麼本地小模型 tool use 表現崩潰">structured output</a> 的 grammar-constrained sampling 是「把不合法 token 的機率歸零」（在 softmax 後或前做 masking）。</p>
]]></content:encoded></item><item><title>Special Tokens</title><link>https://tarrragon.github.io/blog/llm/knowledge-cards/special-tokens/</link><pubDate>Tue, 12 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/llm/knowledge-cards/special-tokens/</guid><description>&lt;p>Special tokens（特殊 token）的核心概念是「&lt;strong>在 &lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/vocabulary-size/" data-link-title="Vocabulary Size" data-link-desc="tokenizer 詞彙表的 token 總數、影響 embedding 大小、tokenization 粒度、多語言友善度">vocab&lt;/a> 中保留給控制 / 邊界 / 結構用途的 token&lt;/strong>」、不是正常字面意義的詞。常見如 &lt;code>&amp;lt;bos&amp;gt;&lt;/code>（begin of sequence）、&lt;code>&amp;lt;eos&amp;gt;&lt;/code>（end of sequence）、&lt;code>&amp;lt;pad&amp;gt;&lt;/code>（padding）、&lt;code>&amp;lt;|user|&amp;gt;&lt;/code>、&lt;code>&amp;lt;|assistant|&amp;gt;&lt;/code>、&lt;code>&amp;lt;|tool_call|&amp;gt;&lt;/code> 等。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>LLM 中 special tokens 的常見類型：&lt;/p>
&lt;table>
 &lt;thead>
 &lt;tr>
 &lt;th>Token&lt;/th>
 &lt;th>用途&lt;/th>
 &lt;th>範例&lt;/th>
 &lt;/tr>
 &lt;/thead>
 &lt;tbody>
 &lt;tr>
 &lt;td>&lt;code>&amp;lt;bos&amp;gt;&lt;/code> / &lt;code>&amp;lt;s&amp;gt;&lt;/code>&lt;/td>
 &lt;td>序列開頭&lt;/td>
 &lt;td>Llama、Mistral&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;code>&amp;lt;eos&amp;gt;&lt;/code> / &lt;code>&amp;lt;/s&amp;gt;&lt;/code>&lt;/td>
 &lt;td>序列結尾、模型輸出這個就停&lt;/td>
 &lt;td>所有 LLM&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;code>&amp;lt;pad&amp;gt;&lt;/code>&lt;/td>
 &lt;td>把 batch 內不同長度 sequence 填齊&lt;/td>
 &lt;td>訓練 / batched 推論時用&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;code>&amp;lt;unk&amp;gt;&lt;/code>&lt;/td>
 &lt;td>遇到 vocab 外的 token（byte-level BPE 已不需要）&lt;/td>
 &lt;td>早期 tokenizer&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;code>&amp;lt;|user|&amp;gt;&lt;/code> / &lt;code>&amp;lt;|assistant|&amp;gt;&lt;/code>&lt;/td>
 &lt;td>Chat template 角色標記&lt;/td>
 &lt;td>Llama 3 chat、Qwen chat&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;code>&amp;lt;|im_start|&amp;gt;&lt;/code> / &lt;code>&amp;lt;|im_end|&amp;gt;&lt;/code>&lt;/td>
 &lt;td>ChatML 格式的對話邊界&lt;/td>
 &lt;td>OpenAI、Qwen 系列&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;code>&amp;lt;|tool_call|&amp;gt;&lt;/code> / &lt;code>&amp;lt;|tool_response|&amp;gt;&lt;/code>&lt;/td>
 &lt;td>Tool use / function calling 訊號&lt;/td>
 &lt;td>Llama 3.1+ 等支援 tool use 的模型&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;code>&amp;lt;think&amp;gt;&lt;/code> / &lt;code>&amp;lt;/think&amp;gt;&lt;/code>&lt;/td>
 &lt;td>Chain-of-thought 標記&lt;/td>
 &lt;td>DeepSeek-R1、O1 風格模型&lt;/td>
 &lt;/tr>
 &lt;/tbody>
&lt;/table>
&lt;p>關鍵特性：&lt;/p>
&lt;ol>
&lt;li>&lt;strong>訓練時用特殊 token ID 標記&lt;/strong>：模型透過大量範例學會「看到 &lt;code>&amp;lt;\|user\|&amp;gt;&lt;/code> 後面是使用者輸入、看到 &lt;code>&amp;lt;\|assistant\|&amp;gt;&lt;/code> 後面要生成回答」。&lt;/li>
&lt;li>&lt;strong>Chat template 把這些組合起來&lt;/strong>：把使用者輸入 + 系統 prompt + 對話歷史依特定格式插入這些 token、組成模型訓練時看過的格式。&lt;/li>
&lt;li>&lt;strong>&lt;code>&amp;lt;eos&amp;gt;&lt;/code> 的 sampling 行為&lt;/strong>：模型輸出 &lt;code>&amp;lt;eos&amp;gt;&lt;/code> 後、推論伺服器停止生成、所以「為什麼回答突然停了」很多時候就是模型決定發 EOS。&lt;/li>
&lt;/ol>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>讀 tokenizer config（&lt;code>tokenizer_config.json&lt;/code>）看到 &lt;code>bos_token&lt;/code>、&lt;code>eos_token&lt;/code>、&lt;code>chat_template&lt;/code> 等就是這組設定。寫 code 場景的判讀：用 Continue.dev / Ollama 時、伺服器會自動套用模型的 chat template、把使用者輸入轉成正確的 special tokens 格式；自己寫 inference code 時、要呼叫 &lt;code>tokenizer.apply_chat_template()&lt;/code> 避免格式錯亂導致模型輸出爛。&lt;/p></description><content:encoded><![CDATA[<p>Special tokens（特殊 token）的核心概念是「<strong>在 <a href="/blog/llm/knowledge-cards/vocabulary-size/" data-link-title="Vocabulary Size" data-link-desc="tokenizer 詞彙表的 token 總數、影響 embedding 大小、tokenization 粒度、多語言友善度">vocab</a> 中保留給控制 / 邊界 / 結構用途的 token</strong>」、不是正常字面意義的詞。常見如 <code>&lt;bos&gt;</code>（begin of sequence）、<code>&lt;eos&gt;</code>（end of sequence）、<code>&lt;pad&gt;</code>（padding）、<code>&lt;|user|&gt;</code>、<code>&lt;|assistant|&gt;</code>、<code>&lt;|tool_call|&gt;</code> 等。</p>
<h2 id="概念位置">概念位置</h2>
<p>LLM 中 special tokens 的常見類型：</p>
<table>
  <thead>
      <tr>
          <th>Token</th>
          <th>用途</th>
          <th>範例</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td><code>&lt;bos&gt;</code> / <code>&lt;s&gt;</code></td>
          <td>序列開頭</td>
          <td>Llama、Mistral</td>
      </tr>
      <tr>
          <td><code>&lt;eos&gt;</code> / <code>&lt;/s&gt;</code></td>
          <td>序列結尾、模型輸出這個就停</td>
          <td>所有 LLM</td>
      </tr>
      <tr>
          <td><code>&lt;pad&gt;</code></td>
          <td>把 batch 內不同長度 sequence 填齊</td>
          <td>訓練 / batched 推論時用</td>
      </tr>
      <tr>
          <td><code>&lt;unk&gt;</code></td>
          <td>遇到 vocab 外的 token（byte-level BPE 已不需要）</td>
          <td>早期 tokenizer</td>
      </tr>
      <tr>
          <td><code>&lt;|user|&gt;</code> / <code>&lt;|assistant|&gt;</code></td>
          <td>Chat template 角色標記</td>
          <td>Llama 3 chat、Qwen chat</td>
      </tr>
      <tr>
          <td><code>&lt;|im_start|&gt;</code> / <code>&lt;|im_end|&gt;</code></td>
          <td>ChatML 格式的對話邊界</td>
          <td>OpenAI、Qwen 系列</td>
      </tr>
      <tr>
          <td><code>&lt;|tool_call|&gt;</code> / <code>&lt;|tool_response|&gt;</code></td>
          <td>Tool use / function calling 訊號</td>
          <td>Llama 3.1+ 等支援 tool use 的模型</td>
      </tr>
      <tr>
          <td><code>&lt;think&gt;</code> / <code>&lt;/think&gt;</code></td>
          <td>Chain-of-thought 標記</td>
          <td>DeepSeek-R1、O1 風格模型</td>
      </tr>
  </tbody>
</table>
<p>關鍵特性：</p>
<ol>
<li><strong>訓練時用特殊 token ID 標記</strong>：模型透過大量範例學會「看到 <code>&lt;\|user\|&gt;</code> 後面是使用者輸入、看到 <code>&lt;\|assistant\|&gt;</code> 後面要生成回答」。</li>
<li><strong>Chat template 把這些組合起來</strong>：把使用者輸入 + 系統 prompt + 對話歷史依特定格式插入這些 token、組成模型訓練時看過的格式。</li>
<li><strong><code>&lt;eos&gt;</code> 的 sampling 行為</strong>：模型輸出 <code>&lt;eos&gt;</code> 後、推論伺服器停止生成、所以「為什麼回答突然停了」很多時候就是模型決定發 EOS。</li>
</ol>
<h2 id="設計責任">設計責任</h2>
<p>讀 tokenizer config（<code>tokenizer_config.json</code>）看到 <code>bos_token</code>、<code>eos_token</code>、<code>chat_template</code> 等就是這組設定。寫 code 場景的判讀：用 Continue.dev / Ollama 時、伺服器會自動套用模型的 chat template、把使用者輸入轉成正確的 special tokens 格式；自己寫 inference code 時、要呼叫 <code>tokenizer.apply_chat_template()</code> 避免格式錯亂導致模型輸出爛。</p>
]]></content:encoded></item><item><title>Subagent</title><link>https://tarrragon.github.io/blog/llm/knowledge-cards/subagent/</link><pubDate>Tue, 12 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/llm/knowledge-cards/subagent/</guid><description>&lt;p>Subagent 的核心概念是「&lt;strong>把 coding agent 切成多個專責子 agent、每個有獨立 &lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/context-window/" data-link-title="Context Window" data-link-desc="模型一次能處理的最大 token 數量：prompt 加生成的總和上限">context window&lt;/a> 跟 system prompt、由 main agent 透過 handoff 機制調度&lt;/strong>」。代表設計：Claude Code 的 Task agent、OpenAI Agents SDK 的 handoff、Anthropic multi-agent research。是「context budget 不夠 + 任務跨多個 specialty」場景的工程選擇。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>Single agent vs subagent 架構的對比：&lt;/p>





&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-text" data-lang="text">&lt;span class="line">&lt;span class="ln"> 1&lt;/span>&lt;span class="cl">Single agent（無 subagent）：
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 2&lt;/span>&lt;span class="cl"> Main agent context：
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 3&lt;/span>&lt;span class="cl"> [system prompt + tool schema + 跨所有 specialty 的 history + 所有 file content]
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 4&lt;/span>&lt;span class="cl"> ↓ 容易爆 context、specialty 互相干擾
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 5&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 6&lt;/span>&lt;span class="cl">Subagent 架構：
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 7&lt;/span>&lt;span class="cl"> Main agent context（路由 + 高階決策）：
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 8&lt;/span>&lt;span class="cl"> [main system prompt + handoff tool spec + 高階任務歷史]
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 9&lt;/span>&lt;span class="cl"> ↓ 路由到 subagent
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">10&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">11&lt;/span>&lt;span class="cl"> Subagent A context（如「跑測試」專家）：
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">12&lt;/span>&lt;span class="cl"> [test-runner system prompt + 測試 tool + 測試相關 file]
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">13&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">14&lt;/span>&lt;span class="cl"> Subagent B context（如「寫 docs」專家）：
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">15&lt;/span>&lt;span class="cl"> [docs system prompt + 寫 docs tool + 相關 docs 檔案]&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>主要好處：&lt;/p>
&lt;ol>
&lt;li>&lt;strong>Context budget 隔離&lt;/strong>：每個 subagent 只看自己 specialty 相關 context、不被別的 specialty 污染&lt;/li>
&lt;li>&lt;strong>System prompt 專門化&lt;/strong>：寫 docs 的 system prompt 跟跑測試的 system prompt 不同、各自最佳化&lt;/li>
&lt;li>&lt;strong>Specialty 路由&lt;/strong>：main agent 只決定「這個任務該交給哪個 subagent」、不直接做 specialty 工作&lt;/li>
&lt;/ol>
&lt;p>主要挑戰：&lt;/p>
&lt;ol>
&lt;li>&lt;strong>Handoff 設計&lt;/strong>：main agent 要怎麼選 subagent、怎麼傳 context、怎麼接 result&lt;/li>
&lt;li>&lt;strong>跨 subagent 共享狀態&lt;/strong>：codebase 知識、history、要避免重複 work&lt;/li>
&lt;li>&lt;strong>失敗模式&lt;/strong>：subagent 之間互相 deadlock、main agent 失去 high-level view、subagent 邊界劃錯&lt;/li>
&lt;/ol>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>讀 multi-agent / subagent paper / coding agent docs 看到「subagent」「handoff」「Task tool」「specialist agent」就是這 framing。寫 code 場景的判讀：&lt;/p>
&lt;ol>
&lt;li>&lt;strong>何時用 subagent&lt;/strong>：單一 agent context 不夠用、specialty 邊界清楚（如 search / coding / testing / documentation）、main agent 的 system prompt 已太長&lt;/li>
&lt;li>&lt;strong>何時不用&lt;/strong>：任務簡單、specialty 邊界模糊（強行拆會增加 handoff overhead）、本地小模型（handoff 機制對小模型不穩）&lt;/li>
&lt;li>&lt;strong>跟 &lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/agent-loop/" data-link-title="Agent Loop" data-link-desc="LLM agent 自我循環的工作流：LLM 規劃下一步、執行 tool、看結果、再規劃下一步、直到任務完成或停止條件觸發">agent loop&lt;/a> 的關係&lt;/strong>：每個 subagent 內部仍是 agent loop（perceive / reason / act / observe / terminate）、只是 loop 範圍縮窄&lt;/li>
&lt;li>&lt;strong>跟 &lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/scaffold-vs-harness/" data-link-title="Scaffold vs Harness" data-link-desc="Coding agent 的兩個工程層次：scaffold 是建構時靜態結構、harness 是 runtime 的 tool dispatch &amp;#43; context management &amp;#43; safety">scaffold vs harness&lt;/a> 的關係&lt;/strong>：subagent 註冊在 scaffold（建構時）、handoff 在 harness（runtime）執行&lt;/li>
&lt;/ol></description><content:encoded><![CDATA[<p>Subagent 的核心概念是「<strong>把 coding agent 切成多個專責子 agent、每個有獨立 <a href="/blog/llm/knowledge-cards/context-window/" data-link-title="Context Window" data-link-desc="模型一次能處理的最大 token 數量：prompt 加生成的總和上限">context window</a> 跟 system prompt、由 main agent 透過 handoff 機制調度</strong>」。代表設計：Claude Code 的 Task agent、OpenAI Agents SDK 的 handoff、Anthropic multi-agent research。是「context budget 不夠 + 任務跨多個 specialty」場景的工程選擇。</p>
<h2 id="概念位置">概念位置</h2>
<p>Single agent vs subagent 架構的對比：</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="ln"> 1</span><span class="cl">Single agent（無 subagent）：
</span></span><span class="line"><span class="ln"> 2</span><span class="cl">  Main agent context：
</span></span><span class="line"><span class="ln"> 3</span><span class="cl">    [system prompt + tool schema + 跨所有 specialty 的 history + 所有 file content]
</span></span><span class="line"><span class="ln"> 4</span><span class="cl">    ↓ 容易爆 context、specialty 互相干擾
</span></span><span class="line"><span class="ln"> 5</span><span class="cl">
</span></span><span class="line"><span class="ln"> 6</span><span class="cl">Subagent 架構：
</span></span><span class="line"><span class="ln"> 7</span><span class="cl">  Main agent context（路由 + 高階決策）：
</span></span><span class="line"><span class="ln"> 8</span><span class="cl">    [main system prompt + handoff tool spec + 高階任務歷史]
</span></span><span class="line"><span class="ln"> 9</span><span class="cl">       ↓ 路由到 subagent
</span></span><span class="line"><span class="ln">10</span><span class="cl">
</span></span><span class="line"><span class="ln">11</span><span class="cl">  Subagent A context（如「跑測試」專家）：
</span></span><span class="line"><span class="ln">12</span><span class="cl">    [test-runner system prompt + 測試 tool + 測試相關 file]
</span></span><span class="line"><span class="ln">13</span><span class="cl">
</span></span><span class="line"><span class="ln">14</span><span class="cl">  Subagent B context（如「寫 docs」專家）：
</span></span><span class="line"><span class="ln">15</span><span class="cl">    [docs system prompt + 寫 docs tool + 相關 docs 檔案]</span></span></code></pre></div><p>主要好處：</p>
<ol>
<li><strong>Context budget 隔離</strong>：每個 subagent 只看自己 specialty 相關 context、不被別的 specialty 污染</li>
<li><strong>System prompt 專門化</strong>：寫 docs 的 system prompt 跟跑測試的 system prompt 不同、各自最佳化</li>
<li><strong>Specialty 路由</strong>：main agent 只決定「這個任務該交給哪個 subagent」、不直接做 specialty 工作</li>
</ol>
<p>主要挑戰：</p>
<ol>
<li><strong>Handoff 設計</strong>：main agent 要怎麼選 subagent、怎麼傳 context、怎麼接 result</li>
<li><strong>跨 subagent 共享狀態</strong>：codebase 知識、history、要避免重複 work</li>
<li><strong>失敗模式</strong>：subagent 之間互相 deadlock、main agent 失去 high-level view、subagent 邊界劃錯</li>
</ol>
<h2 id="設計責任">設計責任</h2>
<p>讀 multi-agent / subagent paper / coding agent docs 看到「subagent」「handoff」「Task tool」「specialist agent」就是這 framing。寫 code 場景的判讀：</p>
<ol>
<li><strong>何時用 subagent</strong>：單一 agent context 不夠用、specialty 邊界清楚（如 search / coding / testing / documentation）、main agent 的 system prompt 已太長</li>
<li><strong>何時不用</strong>：任務簡單、specialty 邊界模糊（強行拆會增加 handoff overhead）、本地小模型（handoff 機制對小模型不穩）</li>
<li><strong>跟 <a href="/blog/llm/knowledge-cards/agent-loop/" data-link-title="Agent Loop" data-link-desc="LLM agent 自我循環的工作流：LLM 規劃下一步、執行 tool、看結果、再規劃下一步、直到任務完成或停止條件觸發">agent loop</a> 的關係</strong>：每個 subagent 內部仍是 agent loop（perceive / reason / act / observe / terminate）、只是 loop 範圍縮窄</li>
<li><strong>跟 <a href="/blog/llm/knowledge-cards/scaffold-vs-harness/" data-link-title="Scaffold vs Harness" data-link-desc="Coding agent 的兩個工程層次：scaffold 是建構時靜態結構、harness 是 runtime 的 tool dispatch &#43; context management &#43; safety">scaffold vs harness</a> 的關係</strong>：subagent 註冊在 scaffold（建構時）、handoff 在 harness（runtime）執行</li>
</ol>
]]></content:encoded></item><item><title>System Prompt</title><link>https://tarrragon.github.io/blog/llm/knowledge-cards/system-prompt/</link><pubDate>Tue, 12 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/llm/knowledge-cards/system-prompt/</guid><description>&lt;p>System prompt 的核心概念是「LLM application 中、由開發者預設、放在每次 conversation 最前面、不直接顯示給使用者的指令層」。常見用途包括設定模型角色（如「你是 senior Python engineer」）、規範輸出格式（如「always return JSON」）、加入 safety guideline。Chat-based LLM API（OpenAI、Anthropic 等）通常有專門的 &lt;code>role: &amp;quot;system&amp;quot;&lt;/code> message type。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>LLM API call 的訊息結構：&lt;/p>





&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-text" data-lang="text">&lt;span class="line">&lt;span class="ln">1&lt;/span>&lt;span class="cl">messages = [
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">2&lt;/span>&lt;span class="cl"> {role: &amp;#34;system&amp;#34;, content: &amp;#34;你是專業 code reviewer...&amp;#34;}, ← system prompt
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">3&lt;/span>&lt;span class="cl"> {role: &amp;#34;user&amp;#34;, content: &amp;#34;請 review 這段 code: ...&amp;#34;},
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">4&lt;/span>&lt;span class="cl"> {role: &amp;#34;assistant&amp;#34;, content: &amp;#34;...&amp;#34;}, ← 模型回答
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">5&lt;/span>&lt;span class="cl"> {role: &amp;#34;user&amp;#34;, content: &amp;#34;...&amp;#34;}, ← 後續對話
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">6&lt;/span>&lt;span class="cl"> ...
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">7&lt;/span>&lt;span class="cl">]&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>System prompt 在 application 設計中的角色：&lt;/p>
&lt;table>
 &lt;thead>
 &lt;tr>
 &lt;th>用途&lt;/th>
 &lt;th>例子&lt;/th>
 &lt;/tr>
 &lt;/thead>
 &lt;tbody>
 &lt;tr>
 &lt;td>角色定義&lt;/td>
 &lt;td>&amp;ldquo;你是 senior Python engineer、專長 async / typing&amp;rdquo;&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>輸出格式約束&lt;/td>
 &lt;td>&amp;ldquo;always return JSON with keys: title, body, tags&amp;rdquo;&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>行為規範&lt;/td>
 &lt;td>&amp;ldquo;若不確定、明確說『我不知道』、不要編造&amp;rdquo;&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>工具使用指引&lt;/td>
 &lt;td>&amp;ldquo;When user asks about weather, call get_weather tool&amp;rdquo;&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>安全約束&lt;/td>
 &lt;td>&amp;ldquo;Do not generate executable shell commands&amp;rdquo;&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>上下文注入&lt;/td>
 &lt;td>&amp;ldquo;Current date: 2026-05-12; User language: zh-TW&amp;rdquo;&lt;/td>
 &lt;/tr>
 &lt;/tbody>
&lt;/table>
&lt;blockquote>
&lt;p>&lt;strong>事實查核註&lt;/strong>：不同 LLM vendor 對 system prompt 的處理機制不同（如部分模型把 system 跟 user 視為相同優先級、部分模型有特殊訓練讓 system 較高優先）、具體行為以該模型的&lt;a href="https://platform.openai.com/docs/api-reference/chat">官方文件&lt;/a>為準。&lt;/p>&lt;/blockquote>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>理解 system prompt 後可以解釋兩個現象：為什麼同一個模型在不同 LLM 應用中的「個性」差很多（system prompt 不同）、為什麼 &lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/prompt-injection/" data-link-title="Prompt Injection" data-link-desc="把惡意指令藏進 LLM 會讀到的內容、誘導 LLM 跑出非開發者預期行為的攻擊類別、OWASP LLM01 列入頭號威脅">prompt injection&lt;/a> 的主要目標是繞過 system prompt 的約束（攻擊者想讓模型不照原本指令走）。&lt;/p>
&lt;p>實務上、設計 LLM application 時、system prompt 是行為約束的第一層、但不是唯一防線（容易被 injection 繞過）；critical 行為應該在 application 層（如 tool call 的權限白名單、輸出驗證）加第二層防護。詳見 &lt;a href="https://tarrragon.github.io/blog/llm/06-security/prompt-injection-in-ide/" data-link-title="6.3 IDE 場景的 prompt injection" data-link-desc="個人 dev 場景下 IDE 寫 code 工作流的 prompt injection：codebase 內容、外部文件、剪貼簿作為攻擊面、跟雲端 LLM 場景的差異">6.3 IDE 場景的 prompt injection&lt;/a>。&lt;/p></description><content:encoded><![CDATA[<p>System prompt 的核心概念是「LLM application 中、由開發者預設、放在每次 conversation 最前面、不直接顯示給使用者的指令層」。常見用途包括設定模型角色（如「你是 senior Python engineer」）、規範輸出格式（如「always return JSON」）、加入 safety guideline。Chat-based LLM API（OpenAI、Anthropic 等）通常有專門的 <code>role: &quot;system&quot;</code> message type。</p>
<h2 id="概念位置">概念位置</h2>
<p>LLM API call 的訊息結構：</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="ln">1</span><span class="cl">messages = [
</span></span><span class="line"><span class="ln">2</span><span class="cl">  {role: &#34;system&#34;, content: &#34;你是專業 code reviewer...&#34;},  ← system prompt
</span></span><span class="line"><span class="ln">3</span><span class="cl">  {role: &#34;user&#34;,   content: &#34;請 review 這段 code: ...&#34;},
</span></span><span class="line"><span class="ln">4</span><span class="cl">  {role: &#34;assistant&#34;, content: &#34;...&#34;},  ← 模型回答
</span></span><span class="line"><span class="ln">5</span><span class="cl">  {role: &#34;user&#34;,   content: &#34;...&#34;},     ← 後續對話
</span></span><span class="line"><span class="ln">6</span><span class="cl">  ...
</span></span><span class="line"><span class="ln">7</span><span class="cl">]</span></span></code></pre></div><p>System prompt 在 application 設計中的角色：</p>
<table>
  <thead>
      <tr>
          <th>用途</th>
          <th>例子</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>角色定義</td>
          <td>&ldquo;你是 senior Python engineer、專長 async / typing&rdquo;</td>
      </tr>
      <tr>
          <td>輸出格式約束</td>
          <td>&ldquo;always return JSON with keys: title, body, tags&rdquo;</td>
      </tr>
      <tr>
          <td>行為規範</td>
          <td>&ldquo;若不確定、明確說『我不知道』、不要編造&rdquo;</td>
      </tr>
      <tr>
          <td>工具使用指引</td>
          <td>&ldquo;When user asks about weather, call get_weather tool&rdquo;</td>
      </tr>
      <tr>
          <td>安全約束</td>
          <td>&ldquo;Do not generate executable shell commands&rdquo;</td>
      </tr>
      <tr>
          <td>上下文注入</td>
          <td>&ldquo;Current date: 2026-05-12; User language: zh-TW&rdquo;</td>
      </tr>
  </tbody>
</table>
<blockquote>
<p><strong>事實查核註</strong>：不同 LLM vendor 對 system prompt 的處理機制不同（如部分模型把 system 跟 user 視為相同優先級、部分模型有特殊訓練讓 system 較高優先）、具體行為以該模型的<a href="https://platform.openai.com/docs/api-reference/chat">官方文件</a>為準。</p></blockquote>
<h2 id="設計責任">設計責任</h2>
<p>理解 system prompt 後可以解釋兩個現象：為什麼同一個模型在不同 LLM 應用中的「個性」差很多（system prompt 不同）、為什麼 <a href="/blog/llm/knowledge-cards/prompt-injection/" data-link-title="Prompt Injection" data-link-desc="把惡意指令藏進 LLM 會讀到的內容、誘導 LLM 跑出非開發者預期行為的攻擊類別、OWASP LLM01 列入頭號威脅">prompt injection</a> 的主要目標是繞過 system prompt 的約束（攻擊者想讓模型不照原本指令走）。</p>
<p>實務上、設計 LLM application 時、system prompt 是行為約束的第一層、但不是唯一防線（容易被 injection 繞過）；critical 行為應該在 application 層（如 tool call 的權限白名單、輸出驗證）加第二層防護。詳見 <a href="/blog/llm/06-security/prompt-injection-in-ide/" data-link-title="6.3 IDE 場景的 prompt injection" data-link-desc="個人 dev 場景下 IDE 寫 code 工作流的 prompt injection：codebase 內容、外部文件、剪貼簿作為攻擊面、跟雲端 LLM 場景的差異">6.3 IDE 場景的 prompt injection</a>。</p>
]]></content:encoded></item><item><title>Tensor</title><link>https://tarrragon.github.io/blog/llm/knowledge-cards/tensor/</link><pubDate>Tue, 12 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/llm/knowledge-cards/tensor/</guid><description>&lt;p>Tensor（張量）的核心概念是「&lt;strong>N 維陣列&lt;/strong>」。Scalar 是 0D tensor、vector 是 1D、matrix 是 2D、再往上加維度就是 3D、4D。PyTorch、MLX、JAX、TensorFlow 等所有深度學習 framework 的核心型別都叫 Tensor、所有 LLM 內部運算（&lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/matrix-multiplication/" data-link-title="Matrix Multiplication" data-link-desc="LLM 推論最頻繁的單一運算、forward pass 每層的核心、memory bandwidth 瓶頸的根源">matrix multiplication&lt;/a>、&lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/softmax/" data-link-title="Softmax" data-link-desc="把任意實數向量正規化成「總和為 1、每個分量 ∈ [0,1]」的機率分佈">softmax&lt;/a>、&lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/layer-normalization/" data-link-title="Layer Normalization" data-link-desc="在每個 token 的 hidden state 上做正規化（減 mean、除 std）、穩定深層網路訓練">layer norm&lt;/a> 等）都對 tensor 做。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>LLM 中常見的 tensor 維度：&lt;/p>
&lt;table>
 &lt;thead>
 &lt;tr>
 &lt;th>維度&lt;/th>
 &lt;th>shape&lt;/th>
 &lt;th>意義&lt;/th>
 &lt;th>出現在&lt;/th>
 &lt;/tr>
 &lt;/thead>
 &lt;tbody>
 &lt;tr>
 &lt;td>1D&lt;/td>
 &lt;td>&lt;code>(vocab_size,)&lt;/code>&lt;/td>
 &lt;td>一個 token 位置的 &lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/logit/" data-link-title="Logit" data-link-desc="softmax 之前的原始實數分數、每個 vocab token 一個值、可正可負">logit&lt;/a> 向量&lt;/td>
 &lt;td>Output layer 輸出&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>2D&lt;/td>
 &lt;td>&lt;code>(seq_len, hidden_dim)&lt;/code>&lt;/td>
 &lt;td>一個 sequence 的 hidden state&lt;/td>
 &lt;td>每個 Transformer block 內部&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>3D&lt;/td>
 &lt;td>&lt;code>(batch_size, seq_len, hidden_dim)&lt;/code>&lt;/td>
 &lt;td>一個 batch 的多個 sequence&lt;/td>
 &lt;td>Batched 推論 / 訓練&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>4D&lt;/td>
 &lt;td>&lt;code>(batch_size, num_heads, seq_len, head_dim)&lt;/code>&lt;/td>
 &lt;td>Multi-head attention 的並行結構&lt;/td>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/self-attention/" data-link-title="Self-Attention" data-link-desc="Q / K / V 都從同一個 sequence 投影出來的 attention、Transformer 的標誌性設計">Self-attention&lt;/a> 內部&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>5D+&lt;/td>
 &lt;td>&lt;code>(batch, heads, seq, head_dim, ...)&lt;/code>&lt;/td>
 &lt;td>罕見、特殊架構&lt;/td>
 &lt;td>MoE expert dispatch、特殊 attention&lt;/td>
 &lt;/tr>
 &lt;/tbody>
&lt;/table>
&lt;p>關鍵運算：&lt;/p>
&lt;ol>
&lt;li>&lt;strong>Reshape&lt;/strong>：改 shape 但不變資料總量、如 &lt;code>(batch, seq, hidden) → (batch * seq, hidden)&lt;/code>。&lt;/li>
&lt;li>&lt;strong>Transpose / permute&lt;/strong>：交換維度順序、attention 計算前後常用。&lt;/li>
&lt;li>&lt;strong>Broadcasting&lt;/strong>：不同 shape 的 tensor 自動擴展配對、如 &lt;code>(seq, hidden) + (hidden,)&lt;/code>。&lt;/li>
&lt;li>&lt;strong>Indexing / slicing&lt;/strong>：抽出子 tensor、如 &lt;code>tensor[:, -1, :]&lt;/code> 取最後一個 token 的 hidden。&lt;/li>
&lt;/ol>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>讀 PyTorch / MLX 推論 / 訓練 code 看到 &lt;code>torch.Tensor&lt;/code>、&lt;code>mx.array&lt;/code>、&lt;code>tf.Tensor&lt;/code> 等就是這個型別、所有 LLM 運算都建在它上面。寫 code 場景的判讀：報錯訊息看到 &lt;code>shape mismatch&lt;/code> / &lt;code>size of dimension X&lt;/code> 通常是 tensor 維度配錯；&lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/kv-cache/" data-link-title="KV Cache" data-link-desc="已處理 token 的 attention 中間結果暫存：避免重算、加速後續生成">KV cache&lt;/a> 內部存的就是 4D tensor &lt;code>(num_layers, 2, batch, num_kv_heads, seq, head_dim)&lt;/code> 之類的結構、量化 KV cache 就是改這個 tensor 的 dtype。&lt;/p></description><content:encoded><![CDATA[<p>Tensor（張量）的核心概念是「<strong>N 維陣列</strong>」。Scalar 是 0D tensor、vector 是 1D、matrix 是 2D、再往上加維度就是 3D、4D。PyTorch、MLX、JAX、TensorFlow 等所有深度學習 framework 的核心型別都叫 Tensor、所有 LLM 內部運算（<a href="/blog/llm/knowledge-cards/matrix-multiplication/" data-link-title="Matrix Multiplication" data-link-desc="LLM 推論最頻繁的單一運算、forward pass 每層的核心、memory bandwidth 瓶頸的根源">matrix multiplication</a>、<a href="/blog/llm/knowledge-cards/softmax/" data-link-title="Softmax" data-link-desc="把任意實數向量正規化成「總和為 1、每個分量 ∈ [0,1]」的機率分佈">softmax</a>、<a href="/blog/llm/knowledge-cards/layer-normalization/" data-link-title="Layer Normalization" data-link-desc="在每個 token 的 hidden state 上做正規化（減 mean、除 std）、穩定深層網路訓練">layer norm</a> 等）都對 tensor 做。</p>
<h2 id="概念位置">概念位置</h2>
<p>LLM 中常見的 tensor 維度：</p>
<table>
  <thead>
      <tr>
          <th>維度</th>
          <th>shape</th>
          <th>意義</th>
          <th>出現在</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>1D</td>
          <td><code>(vocab_size,)</code></td>
          <td>一個 token 位置的 <a href="/blog/llm/knowledge-cards/logit/" data-link-title="Logit" data-link-desc="softmax 之前的原始實數分數、每個 vocab token 一個值、可正可負">logit</a> 向量</td>
          <td>Output layer 輸出</td>
      </tr>
      <tr>
          <td>2D</td>
          <td><code>(seq_len, hidden_dim)</code></td>
          <td>一個 sequence 的 hidden state</td>
          <td>每個 Transformer block 內部</td>
      </tr>
      <tr>
          <td>3D</td>
          <td><code>(batch_size, seq_len, hidden_dim)</code></td>
          <td>一個 batch 的多個 sequence</td>
          <td>Batched 推論 / 訓練</td>
      </tr>
      <tr>
          <td>4D</td>
          <td><code>(batch_size, num_heads, seq_len, head_dim)</code></td>
          <td>Multi-head attention 的並行結構</td>
          <td><a href="/blog/llm/knowledge-cards/self-attention/" data-link-title="Self-Attention" data-link-desc="Q / K / V 都從同一個 sequence 投影出來的 attention、Transformer 的標誌性設計">Self-attention</a> 內部</td>
      </tr>
      <tr>
          <td>5D+</td>
          <td><code>(batch, heads, seq, head_dim, ...)</code></td>
          <td>罕見、特殊架構</td>
          <td>MoE expert dispatch、特殊 attention</td>
      </tr>
  </tbody>
</table>
<p>關鍵運算：</p>
<ol>
<li><strong>Reshape</strong>：改 shape 但不變資料總量、如 <code>(batch, seq, hidden) → (batch * seq, hidden)</code>。</li>
<li><strong>Transpose / permute</strong>：交換維度順序、attention 計算前後常用。</li>
<li><strong>Broadcasting</strong>：不同 shape 的 tensor 自動擴展配對、如 <code>(seq, hidden) + (hidden,)</code>。</li>
<li><strong>Indexing / slicing</strong>：抽出子 tensor、如 <code>tensor[:, -1, :]</code> 取最後一個 token 的 hidden。</li>
</ol>
<h2 id="設計責任">設計責任</h2>
<p>讀 PyTorch / MLX 推論 / 訓練 code 看到 <code>torch.Tensor</code>、<code>mx.array</code>、<code>tf.Tensor</code> 等就是這個型別、所有 LLM 運算都建在它上面。寫 code 場景的判讀：報錯訊息看到 <code>shape mismatch</code> / <code>size of dimension X</code> 通常是 tensor 維度配錯；<a href="/blog/llm/knowledge-cards/kv-cache/" data-link-title="KV Cache" data-link-desc="已處理 token 的 attention 中間結果暫存：避免重算、加速後續生成">KV cache</a> 內部存的就是 4D tensor <code>(num_layers, 2, batch, num_kv_heads, seq, head_dim)</code> 之類的結構、量化 KV cache 就是改這個 tensor 的 dtype。</p>
]]></content:encoded></item><item><title>Test-Time Compute</title><link>https://tarrragon.github.io/blog/llm/knowledge-cards/test-time-compute/</link><pubDate>Tue, 12 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/llm/knowledge-cards/test-time-compute/</guid><description>&lt;p>Test-time compute（推論時計算）的核心概念是「&lt;strong>在推論階段花更多計算量、換取更高品質的答案&lt;/strong>」、不是只在訓練時投入算力。是 2024-2026 LLM 的 paradigm shift：GPT-3 → GPT-4 主要靠「更大模型 + 更多訓練資料」；o1 / DeepSeek-R1 → 主要靠「同模型、推論時想更久」。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>LLM 算力分配的兩條軸：&lt;/p>





&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-text" data-lang="text">&lt;span class="line">&lt;span class="ln"> 1&lt;/span>&lt;span class="cl">Training compute（訓練算力）：
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 2&lt;/span>&lt;span class="cl"> pre-training 大量 GPU-hour → 模型參數
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 3&lt;/span>&lt;span class="cl"> 一次性投入、後續推論不變
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 4&lt;/span>&lt;span class="cl"> → GPT-3 → 4 的主要 paradigm
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 5&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 6&lt;/span>&lt;span class="cl">Test-time compute（推論算力）：
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 7&lt;/span>&lt;span class="cl"> 每次推論時、視任務難度動態增加算力
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 8&lt;/span>&lt;span class="cl"> 難題想 30 秒（生 5000 token reasoning trace）
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 9&lt;/span>&lt;span class="cl"> 簡單問題 1 秒結束（直接答）
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">10&lt;/span>&lt;span class="cl"> → o1 / R1 / Claude thinking 的新 paradigm&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>Test-time compute 的常見實作形式：&lt;/p>
&lt;table>
 &lt;thead>
 &lt;tr>
 &lt;th>形式&lt;/th>
 &lt;th>機制&lt;/th>
 &lt;th>代表&lt;/th>
 &lt;/tr>
 &lt;/thead>
 &lt;tbody>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/chain-of-thought/" data-link-title="Chain-of-Thought（CoT）" data-link-desc="讓 LLM 先輸出推理步驟再給最終答案的 prompting / 訓練方式、reasoning model 的基礎機制">Chain-of-thought&lt;/a> 內建&lt;/td>
 &lt;td>模型訓練成「自然」用長 reasoning trace、直接生 thinking + answer&lt;/td>
 &lt;td>o1、DeepSeek-R1、Qwen-QwQ、Claude thinking&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>Best-of-N sampling&lt;/td>
 &lt;td>同 prompt 跑 N 次、reward model 選最好的&lt;/td>
 &lt;td>OpenAI early experiments、verifier-based&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>Tree search&lt;/td>
 &lt;td>結構化探索多條 reasoning path&lt;/td>
 &lt;td>AlphaCode、tree of thoughts&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>Self-consistency&lt;/td>
 &lt;td>多次 sample reasoning、投票選最常見答案&lt;/td>
 &lt;td>早期 CoT prompting 技巧&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>Tool use + verification&lt;/td>
 &lt;td>模型呼叫 calculator / interpreter 驗證自己&lt;/td>
 &lt;td>Coding agent、math 解題 agent&lt;/td>
 &lt;/tr>
 &lt;/tbody>
&lt;/table>
&lt;p>DeepSeek-R1 paper 顯示「reasoning trace 長度跟 benchmark 表現正相關、可透過 RL 拉長」— 把 test-time compute 變成可訓練、可 scale 的維度。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>讀 paper / benchmark 看到「pass@1 vs pass@10」「budget tokens」「thinking time」等就跟 test-time compute 相關。寫 code 場景的判讀：&lt;/p>
&lt;ol>
&lt;li>&lt;strong>Reasoning model 算成本翻倍&lt;/strong>：同一個 prompt、reasoning model 生 5000 token thinking + 500 token answer、傳統 model 直接生 500 token answer、推論成本差 ~10 倍&lt;/li>
&lt;li>&lt;strong>本地跑 reasoning model 的痛點&lt;/strong>：需要長 &lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/context-window/" data-link-title="Context Window" data-link-desc="模型一次能處理的最大 token 數量：prompt 加生成的總和上限">context window&lt;/a> 容納 thinking trace、生成時間長&lt;/li>
&lt;li>&lt;strong>適用任務挑選&lt;/strong>：複雜 reasoning（math、debug、long horizon planning）值得花 test-time compute；簡單任務（autocomplete、查詢）不值得&lt;/li>
&lt;li>&lt;strong>混用策略&lt;/strong>：日常用 instruct model、困難任務切到 reasoning model、是個人 dev 常見模式&lt;/li>
&lt;/ol></description><content:encoded><![CDATA[<p>Test-time compute（推論時計算）的核心概念是「<strong>在推論階段花更多計算量、換取更高品質的答案</strong>」、不是只在訓練時投入算力。是 2024-2026 LLM 的 paradigm shift：GPT-3 → GPT-4 主要靠「更大模型 + 更多訓練資料」；o1 / DeepSeek-R1 → 主要靠「同模型、推論時想更久」。</p>
<h2 id="概念位置">概念位置</h2>
<p>LLM 算力分配的兩條軸：</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="ln"> 1</span><span class="cl">Training compute（訓練算力）：
</span></span><span class="line"><span class="ln"> 2</span><span class="cl">  pre-training 大量 GPU-hour → 模型參數
</span></span><span class="line"><span class="ln"> 3</span><span class="cl">  一次性投入、後續推論不變
</span></span><span class="line"><span class="ln"> 4</span><span class="cl">  → GPT-3 → 4 的主要 paradigm
</span></span><span class="line"><span class="ln"> 5</span><span class="cl">
</span></span><span class="line"><span class="ln"> 6</span><span class="cl">Test-time compute（推論算力）：
</span></span><span class="line"><span class="ln"> 7</span><span class="cl">  每次推論時、視任務難度動態增加算力
</span></span><span class="line"><span class="ln"> 8</span><span class="cl">  難題想 30 秒（生 5000 token reasoning trace）
</span></span><span class="line"><span class="ln"> 9</span><span class="cl">  簡單問題 1 秒結束（直接答）
</span></span><span class="line"><span class="ln">10</span><span class="cl">  → o1 / R1 / Claude thinking 的新 paradigm</span></span></code></pre></div><p>Test-time compute 的常見實作形式：</p>
<table>
  <thead>
      <tr>
          <th>形式</th>
          <th>機制</th>
          <th>代表</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td><a href="/blog/llm/knowledge-cards/chain-of-thought/" data-link-title="Chain-of-Thought（CoT）" data-link-desc="讓 LLM 先輸出推理步驟再給最終答案的 prompting / 訓練方式、reasoning model 的基礎機制">Chain-of-thought</a> 內建</td>
          <td>模型訓練成「自然」用長 reasoning trace、直接生 thinking + answer</td>
          <td>o1、DeepSeek-R1、Qwen-QwQ、Claude thinking</td>
      </tr>
      <tr>
          <td>Best-of-N sampling</td>
          <td>同 prompt 跑 N 次、reward model 選最好的</td>
          <td>OpenAI early experiments、verifier-based</td>
      </tr>
      <tr>
          <td>Tree search</td>
          <td>結構化探索多條 reasoning path</td>
          <td>AlphaCode、tree of thoughts</td>
      </tr>
      <tr>
          <td>Self-consistency</td>
          <td>多次 sample reasoning、投票選最常見答案</td>
          <td>早期 CoT prompting 技巧</td>
      </tr>
      <tr>
          <td>Tool use + verification</td>
          <td>模型呼叫 calculator / interpreter 驗證自己</td>
          <td>Coding agent、math 解題 agent</td>
      </tr>
  </tbody>
</table>
<p>DeepSeek-R1 paper 顯示「reasoning trace 長度跟 benchmark 表現正相關、可透過 RL 拉長」— 把 test-time compute 變成可訓練、可 scale 的維度。</p>
<h2 id="設計責任">設計責任</h2>
<p>讀 paper / benchmark 看到「pass@1 vs pass@10」「budget tokens」「thinking time」等就跟 test-time compute 相關。寫 code 場景的判讀：</p>
<ol>
<li><strong>Reasoning model 算成本翻倍</strong>：同一個 prompt、reasoning model 生 5000 token thinking + 500 token answer、傳統 model 直接生 500 token answer、推論成本差 ~10 倍</li>
<li><strong>本地跑 reasoning model 的痛點</strong>：需要長 <a href="/blog/llm/knowledge-cards/context-window/" data-link-title="Context Window" data-link-desc="模型一次能處理的最大 token 數量：prompt 加生成的總和上限">context window</a> 容納 thinking trace、生成時間長</li>
<li><strong>適用任務挑選</strong>：複雜 reasoning（math、debug、long horizon planning）值得花 test-time compute；簡單任務（autocomplete、查詢）不值得</li>
<li><strong>混用策略</strong>：日常用 instruct model、困難任務切到 reasoning model、是個人 dev 常見模式</li>
</ol>
]]></content:encoded></item><item><title>Tool Use</title><link>https://tarrragon.github.io/blog/llm/knowledge-cards/tool-use/</link><pubDate>Tue, 12 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/llm/knowledge-cards/tool-use/</guid><description>&lt;p>Tool use 的核心概念是「LLM 不只生成文字、還能透過結構化呼叫外部工具來執行讀檔、查資料庫、發 API request、跑程式等動作」。它擴展 LLM 從「對話模型」變成「能影響真實世界的 agent」。實作上常見透過 &lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/function-calling/" data-link-title="Function Calling" data-link-desc="模型訓練階段建立的「呼叫工具」能力：知道何時該呼叫、傳什麼參數">function calling&lt;/a> 或 &lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/mcp/" data-link-title="MCP（Model Context Protocol）" data-link-desc="LLM application ↔ 外部 tool server 之間的標準化協議、複用 OpenAI 相容 API 的成功模式">MCP&lt;/a> 協定。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>Tool use 的典型流程：&lt;/p>





&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-text" data-lang="text">&lt;span class="line">&lt;span class="ln">1&lt;/span>&lt;span class="cl">1. 開發者定義 tools（每個 tool 含 name、description、parameters schema）
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">2&lt;/span>&lt;span class="cl">2. LLM 收到 user message 跟 tools 清單
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">3&lt;/span>&lt;span class="cl">3. LLM 決定要呼叫哪個 tool、生成結構化 tool call（JSON）
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">4&lt;/span>&lt;span class="cl">4. LLM client（不是模型本身）執行 tool call、得到結果
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">5&lt;/span>&lt;span class="cl">5. tool 結果回灌進 conversation、模型基於結果繼續生成或再呼叫&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>關鍵特性：&lt;/p>
&lt;ol>
&lt;li>&lt;strong>模型本身不執行 tool&lt;/strong>：模型只生成 tool call JSON、實際執行由 client 或 &lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/mcp/" data-link-title="MCP（Model Context Protocol）" data-link-desc="LLM application ↔ 外部 tool server 之間的標準化協議、複用 OpenAI 相容 API 的成功模式">MCP server&lt;/a> 完成。&lt;/li>
&lt;li>&lt;strong>權限由 OS / user / sandbox 決定&lt;/strong>：模型再「同意」執行 &lt;code>rm -rf /&lt;/code>、實際能不能跑取決於跑 tool 的 process 權限。&lt;/li>
&lt;li>&lt;strong>副作用範圍跟 tool 設計強相關&lt;/strong>：tool 寫得越通用（如 &lt;code>run_shell&lt;/code>）、攻擊面越大；tool 寫得越窄（如 &lt;code>read_workspace_file&lt;/code>）、攻擊面越小。&lt;/li>
&lt;/ol>
&lt;p>Tool use 跟 function calling、MCP 的關係：&lt;/p>
&lt;table>
 &lt;thead>
 &lt;tr>
 &lt;th>層次&lt;/th>
 &lt;th>角色&lt;/th>
 &lt;/tr>
 &lt;/thead>
 &lt;tbody>
 &lt;tr>
 &lt;td>Tool use（概念）&lt;/td>
 &lt;td>廣義概念、LLM 能呼叫工具&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>Function calling&lt;/td>
 &lt;td>OpenAI 提出的 API 規範、用 JSON schema 定義 function&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/mcp/" data-link-title="MCP（Model Context Protocol）" data-link-desc="LLM application ↔ 外部 tool server 之間的標準化協議、複用 OpenAI 相容 API 的成功模式">MCP&lt;/a>&lt;/td>
 &lt;td>Anthropic 推動的開放協議、定義 LLM client 跟 tool server 之間的通訊格式&lt;/td>
 &lt;/tr>
 &lt;/tbody>
&lt;/table>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>理解 tool use 後可以解釋三個現象：為什麼 LLM 「能跑 shell」其實是 client 跑、不是模型跑（職責切分）、為什麼 tool spec 設計直接影響攻擊面（spec 越鬆、injection 後果越大）、為什麼 &lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/agent-loop/" data-link-title="Agent Loop" data-link-desc="LLM agent 自我循環的工作流：LLM 規劃下一步、執行 tool、看結果、再規劃下一步、直到任務完成或停止條件觸發">agent loop&lt;/a> 比單次 tool call 危險（多步 tool use 中 injection 累積）。&lt;/p>
&lt;p>設計 tool 跟 MCP server 時、權限白名單 + 副作用可逆性 + confirm 機制是基本配置；production 場景見 &lt;a href="https://tarrragon.github.io/blog/backend/07-security-data-protection/llm-prompt-injection-in-agent/" data-link-title="LLM Agent Prompt Injection 後果治理" data-link-desc="production LLM agent 場景的 prompt injection 後果：tool spec 設計、agent loop 限制、review checkpoint、跟 incident workflow 的接合">LLM Agent Prompt Injection 後果治理&lt;/a> 跟 &lt;a href="https://tarrragon.github.io/blog/llm/06-security/tool-use-permission-model/" data-link-title="6.2 tool use 與 MCP server 的權限模型" data-link-desc="個人 dev 場景下 tool use / MCP server 的副作用權限：檔案系統 / shell / 網路存取邊界、第三方 MCP 信任、副作用的可逆性">6.2 tool use 與 MCP server 的權限模型&lt;/a>。&lt;/p></description><content:encoded><![CDATA[<p>Tool use 的核心概念是「LLM 不只生成文字、還能透過結構化呼叫外部工具來執行讀檔、查資料庫、發 API request、跑程式等動作」。它擴展 LLM 從「對話模型」變成「能影響真實世界的 agent」。實作上常見透過 <a href="/blog/llm/knowledge-cards/function-calling/" data-link-title="Function Calling" data-link-desc="模型訓練階段建立的「呼叫工具」能力：知道何時該呼叫、傳什麼參數">function calling</a> 或 <a href="/blog/llm/knowledge-cards/mcp/" data-link-title="MCP（Model Context Protocol）" data-link-desc="LLM application ↔ 外部 tool server 之間的標準化協議、複用 OpenAI 相容 API 的成功模式">MCP</a> 協定。</p>
<h2 id="概念位置">概念位置</h2>
<p>Tool use 的典型流程：</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="ln">1</span><span class="cl">1. 開發者定義 tools（每個 tool 含 name、description、parameters schema）
</span></span><span class="line"><span class="ln">2</span><span class="cl">2. LLM 收到 user message 跟 tools 清單
</span></span><span class="line"><span class="ln">3</span><span class="cl">3. LLM 決定要呼叫哪個 tool、生成結構化 tool call（JSON）
</span></span><span class="line"><span class="ln">4</span><span class="cl">4. LLM client（不是模型本身）執行 tool call、得到結果
</span></span><span class="line"><span class="ln">5</span><span class="cl">5. tool 結果回灌進 conversation、模型基於結果繼續生成或再呼叫</span></span></code></pre></div><p>關鍵特性：</p>
<ol>
<li><strong>模型本身不執行 tool</strong>：模型只生成 tool call JSON、實際執行由 client 或 <a href="/blog/llm/knowledge-cards/mcp/" data-link-title="MCP（Model Context Protocol）" data-link-desc="LLM application ↔ 外部 tool server 之間的標準化協議、複用 OpenAI 相容 API 的成功模式">MCP server</a> 完成。</li>
<li><strong>權限由 OS / user / sandbox 決定</strong>：模型再「同意」執行 <code>rm -rf /</code>、實際能不能跑取決於跑 tool 的 process 權限。</li>
<li><strong>副作用範圍跟 tool 設計強相關</strong>：tool 寫得越通用（如 <code>run_shell</code>）、攻擊面越大；tool 寫得越窄（如 <code>read_workspace_file</code>）、攻擊面越小。</li>
</ol>
<p>Tool use 跟 function calling、MCP 的關係：</p>
<table>
  <thead>
      <tr>
          <th>層次</th>
          <th>角色</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>Tool use（概念）</td>
          <td>廣義概念、LLM 能呼叫工具</td>
      </tr>
      <tr>
          <td>Function calling</td>
          <td>OpenAI 提出的 API 規範、用 JSON schema 定義 function</td>
      </tr>
      <tr>
          <td><a href="/blog/llm/knowledge-cards/mcp/" data-link-title="MCP（Model Context Protocol）" data-link-desc="LLM application ↔ 外部 tool server 之間的標準化協議、複用 OpenAI 相容 API 的成功模式">MCP</a></td>
          <td>Anthropic 推動的開放協議、定義 LLM client 跟 tool server 之間的通訊格式</td>
      </tr>
  </tbody>
</table>
<h2 id="設計責任">設計責任</h2>
<p>理解 tool use 後可以解釋三個現象：為什麼 LLM 「能跑 shell」其實是 client 跑、不是模型跑（職責切分）、為什麼 tool spec 設計直接影響攻擊面（spec 越鬆、injection 後果越大）、為什麼 <a href="/blog/llm/knowledge-cards/agent-loop/" data-link-title="Agent Loop" data-link-desc="LLM agent 自我循環的工作流：LLM 規劃下一步、執行 tool、看結果、再規劃下一步、直到任務完成或停止條件觸發">agent loop</a> 比單次 tool call 危險（多步 tool use 中 injection 累積）。</p>
<p>設計 tool 跟 MCP server 時、權限白名單 + 副作用可逆性 + confirm 機制是基本配置；production 場景見 <a href="/blog/backend/07-security-data-protection/llm-prompt-injection-in-agent/" data-link-title="LLM Agent Prompt Injection 後果治理" data-link-desc="production LLM agent 場景的 prompt injection 後果：tool spec 設計、agent loop 限制、review checkpoint、跟 incident workflow 的接合">LLM Agent Prompt Injection 後果治理</a> 跟 <a href="/blog/llm/06-security/tool-use-permission-model/" data-link-title="6.2 tool use 與 MCP server 的權限模型" data-link-desc="個人 dev 場景下 tool use / MCP server 的副作用權限：檔案系統 / shell / 網路存取邊界、第三方 MCP 信任、副作用的可逆性">6.2 tool use 與 MCP server 的權限模型</a>。</p>
]]></content:encoded></item><item><title>Top-K / Top-P / Min-P Sampling</title><link>https://tarrragon.github.io/blog/llm/knowledge-cards/top-p-sampling/</link><pubDate>Tue, 12 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/llm/knowledge-cards/top-p-sampling/</guid><description>&lt;p>Top-K、Top-P（nucleus sampling）、Min-P 的核心概念是「&lt;strong>從 &lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/softmax/" data-link-title="Softmax" data-link-desc="把任意實數向量正規化成「總和為 1、每個分量 ∈ [0,1]」的機率分佈">softmax&lt;/a> 出來的機率分佈中、先過濾掉低機率 token、再從剩餘候選隨機取樣&lt;/strong>」。三者是 LLM 對話 / 寫 code 場景的主流 sampling 策略、跟 greedy 對比保留隨機多樣性、跟 &lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/beam-search/" data-link-title="Beam Search" data-link-desc="同時保留 K 條候選 sequence 的 decoding 策略、機器翻譯主流、chat / coding 場景慎用">beam search&lt;/a> 對比計算成本低。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>三種策略的篩選方式：&lt;/p>
&lt;table>
 &lt;thead>
 &lt;tr>
 &lt;th>策略&lt;/th>
 &lt;th>機制&lt;/th>
 &lt;th>直覺&lt;/th>
 &lt;/tr>
 &lt;/thead>
 &lt;tbody>
 &lt;tr>
 &lt;td>&lt;strong>Top-K&lt;/strong>&lt;/td>
 &lt;td>只保留機率前 K 個 token、其餘設 0&lt;/td>
 &lt;td>固定候選數量、簡單&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;strong>Top-P&lt;/strong>&lt;/td>
 &lt;td>把 token 依機率排序、保留「累積機率達到 P」的最小集合&lt;/td>
 &lt;td>動態候選數量、適應分佈尖銳度&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;strong>Min-P&lt;/strong>&lt;/td>
 &lt;td>只保留機率 ≥ (P × max_probability) 的 token&lt;/td>
 &lt;td>相對閾值、避免低品質 token&lt;/td>
 &lt;/tr>
 &lt;/tbody>
&lt;/table>
&lt;p>範例（vocab 前 10 個 token 的機率）：&lt;/p>





&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-text" data-lang="text">&lt;span class="line">&lt;span class="ln">1&lt;/span>&lt;span class="cl">token: A B C D E F G H I J
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">2&lt;/span>&lt;span class="cl">prob: 0.45 0.30 0.12 0.05 0.03 0.02 0.01 0.01 0.005 0.005
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">3&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">4&lt;/span>&lt;span class="cl">Top-K=3：保留 A、B、C（前 3 個）
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">5&lt;/span>&lt;span class="cl">Top-P=0.9：累積機率達 0.9、保留 A、B、C、D（0.45+0.30+0.12+0.05 = 0.92）
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">6&lt;/span>&lt;span class="cl">Min-P=0.1：max=0.45、閾值=0.045、保留 A、B、C、D（≥ 0.045）&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>三者實務上常組合使用（如 &lt;code>top_k=40, top_p=0.9, temperature=0.7&lt;/code>）、各自處理不同形狀的分佈。&lt;/p>
&lt;table>
 &lt;thead>
 &lt;tr>
 &lt;th>參數情境&lt;/th>
 &lt;th>適合策略&lt;/th>
 &lt;/tr>
 &lt;/thead>
 &lt;tbody>
 &lt;tr>
 &lt;td>分佈非常尖（模型很確定）&lt;/td>
 &lt;td>Top-P / Min-P 動態縮小、Top-K 可能太大&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>分佈平（模型不確定）&lt;/td>
 &lt;td>Top-K 限制最大候選、避免取到極低品質 token&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>寫 code / 嚴謹任務&lt;/td>
 &lt;td>低 temperature (0.2 ~ 0.5) + 較緊的 Top-P (0.8 ~ 0.9)&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>創意 / 多樣寫作&lt;/td>
 &lt;td>高 temperature (0.7 ~ 1.0) + 寬鬆的 Top-P (0.95+)&lt;/td>
 &lt;/tr>
 &lt;/tbody>
&lt;/table>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>讀 inference config / Continue.dev 設定看到 &lt;code>top_k&lt;/code>、&lt;code>top_p&lt;/code>、&lt;code>min_p&lt;/code>、&lt;code>temperature&lt;/code> 就是這組參數。寫 code 場景的判讀：嚴謹任務（code generation、structured output）用低 temperature + 緊 Top-P 取「最可能對的少數 token」；創意 / 對話用高 temperature + 寬 Top-P 取多樣性。Min-P 是 2023 後流行的新策略、實務上比 Top-P 更穩、避免「分佈很尖時 Top-P 仍納入長尾低品質 token」的問題。&lt;/p></description><content:encoded><![CDATA[<p>Top-K、Top-P（nucleus sampling）、Min-P 的核心概念是「<strong>從 <a href="/blog/llm/knowledge-cards/softmax/" data-link-title="Softmax" data-link-desc="把任意實數向量正規化成「總和為 1、每個分量 ∈ [0,1]」的機率分佈">softmax</a> 出來的機率分佈中、先過濾掉低機率 token、再從剩餘候選隨機取樣</strong>」。三者是 LLM 對話 / 寫 code 場景的主流 sampling 策略、跟 greedy 對比保留隨機多樣性、跟 <a href="/blog/llm/knowledge-cards/beam-search/" data-link-title="Beam Search" data-link-desc="同時保留 K 條候選 sequence 的 decoding 策略、機器翻譯主流、chat / coding 場景慎用">beam search</a> 對比計算成本低。</p>
<h2 id="概念位置">概念位置</h2>
<p>三種策略的篩選方式：</p>
<table>
  <thead>
      <tr>
          <th>策略</th>
          <th>機制</th>
          <th>直覺</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td><strong>Top-K</strong></td>
          <td>只保留機率前 K 個 token、其餘設 0</td>
          <td>固定候選數量、簡單</td>
      </tr>
      <tr>
          <td><strong>Top-P</strong></td>
          <td>把 token 依機率排序、保留「累積機率達到 P」的最小集合</td>
          <td>動態候選數量、適應分佈尖銳度</td>
      </tr>
      <tr>
          <td><strong>Min-P</strong></td>
          <td>只保留機率 ≥ (P × max_probability) 的 token</td>
          <td>相對閾值、避免低品質 token</td>
      </tr>
  </tbody>
</table>
<p>範例（vocab 前 10 個 token 的機率）：</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="ln">1</span><span class="cl">token:     A     B     C     D     E     F     G     H     I     J
</span></span><span class="line"><span class="ln">2</span><span class="cl">prob:    0.45  0.30  0.12  0.05  0.03  0.02  0.01  0.01  0.005 0.005
</span></span><span class="line"><span class="ln">3</span><span class="cl">
</span></span><span class="line"><span class="ln">4</span><span class="cl">Top-K=3：保留 A、B、C（前 3 個）
</span></span><span class="line"><span class="ln">5</span><span class="cl">Top-P=0.9：累積機率達 0.9、保留 A、B、C、D（0.45+0.30+0.12+0.05 = 0.92）
</span></span><span class="line"><span class="ln">6</span><span class="cl">Min-P=0.1：max=0.45、閾值=0.045、保留 A、B、C、D（≥ 0.045）</span></span></code></pre></div><p>三者實務上常組合使用（如 <code>top_k=40, top_p=0.9, temperature=0.7</code>）、各自處理不同形狀的分佈。</p>
<table>
  <thead>
      <tr>
          <th>參數情境</th>
          <th>適合策略</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>分佈非常尖（模型很確定）</td>
          <td>Top-P / Min-P 動態縮小、Top-K 可能太大</td>
      </tr>
      <tr>
          <td>分佈平（模型不確定）</td>
          <td>Top-K 限制最大候選、避免取到極低品質 token</td>
      </tr>
      <tr>
          <td>寫 code / 嚴謹任務</td>
          <td>低 temperature (0.2 ~ 0.5) + 較緊的 Top-P (0.8 ~ 0.9)</td>
      </tr>
      <tr>
          <td>創意 / 多樣寫作</td>
          <td>高 temperature (0.7 ~ 1.0) + 寬鬆的 Top-P (0.95+)</td>
      </tr>
  </tbody>
</table>
<h2 id="設計責任">設計責任</h2>
<p>讀 inference config / Continue.dev 設定看到 <code>top_k</code>、<code>top_p</code>、<code>min_p</code>、<code>temperature</code> 就是這組參數。寫 code 場景的判讀：嚴謹任務（code generation、structured output）用低 temperature + 緊 Top-P 取「最可能對的少數 token」；創意 / 對話用高 temperature + 寬 Top-P 取多樣性。Min-P 是 2023 後流行的新策略、實務上比 Top-P 更穩、避免「分佈很尖時 Top-P 仍納入長尾低品質 token」的問題。</p>
]]></content:encoded></item><item><title>Vector Database</title><link>https://tarrragon.github.io/blog/llm/knowledge-cards/vector-database/</link><pubDate>Tue, 12 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/llm/knowledge-cards/vector-database/</guid><description>&lt;p>Vector Database 的核心概念是「&lt;strong>為高維向量設計的儲存系統 + 近似最近鄰 (Approximate Nearest Neighbor, ANN) 檢索引擎&lt;/strong>」。是 &lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/rag/" data-link-title="RAG" data-link-desc="Retrieval-Augmented Generation：動態外掛知識給 LLM、繞開模型參數記憶的靜態限制">RAG&lt;/a> 系統從 prototype 跨到 production 的關鍵元件——當 &lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/embedding-model/" data-link-title="Embedding Model" data-link-desc="把文字轉成向量的模型：用於 codebase 索引與語意搜尋">embedding&lt;/a> index 大到記憶體裝不下、或並發 query 量超過單機處理能力、就要從 pickle / in-memory 升級到 vector DB。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>Vector DB 跟傳統 SQL / NoSQL database 並列、但專精「向量相似度搜尋」這個操作。它不取代傳統 DB——通常 LLM 應用是兩者並用：傳統 DB 存結構化資料（user / metadata）、vector DB 存 embedding + chunk text。實作上、近期主流是「向量加進去現有 DB」（如 Postgres 的 pgvector extension）或「專用服務」（如 Pinecone、Weaviate、Qdrant）。&lt;/p>
&lt;h2 id="可觀察訊號與例子">可觀察訊號與例子&lt;/h2>
&lt;p>主流選擇分類：&lt;/p>
&lt;table>
 &lt;thead>
 &lt;tr>
 &lt;th>類別&lt;/th>
 &lt;th>例子&lt;/th>
 &lt;th>適合&lt;/th>
 &lt;/tr>
 &lt;/thead>
 &lt;tbody>
 &lt;tr>
 &lt;td>Hosted SaaS&lt;/td>
 &lt;td>Pinecone、Weaviate Cloud、Qdrant Cloud&lt;/td>
 &lt;td>不想 maintain、流量大&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>Self-host service&lt;/td>
 &lt;td>Weaviate、Qdrant、Milvus&lt;/td>
 &lt;td>內部部署、控制 cost&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>Embedded library&lt;/td>
 &lt;td>FAISS、HNSWLib、Annoy&lt;/td>
 &lt;td>嵌進應用、單機規模&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>DB extension&lt;/td>
 &lt;td>pgvector、SQLite + vec&lt;/td>
 &lt;td>已有 SQL DB、加 vector 能力&lt;/td>
 &lt;/tr>
 &lt;/tbody>
&lt;/table>
&lt;p>關鍵 ANN 演算法：&lt;/p>
&lt;ul>
&lt;li>&lt;strong>HNSW&lt;/strong>（Hierarchical Navigable Small World）：主流、sublinear 查詢、犧牲少許精度&lt;/li>
&lt;li>&lt;strong>IVF&lt;/strong>（Inverted File Index）：分組索引、適合超大規模&lt;/li>
&lt;li>&lt;strong>Flat&lt;/strong>（exhaustive search）：精確但 O(n)、小資料集 OK&lt;/li>
&lt;/ul>
&lt;p>scale 對照（基於 &lt;a href="https://tarrragon.github.io/blog/llm/04-applications/production-resource-planning/" data-link-title="4.9 Production 部署的資源評估原理" data-link-desc="從本地單 user 到 production multi-tenant：concurrent users、cost model、observability、SLA、capacity planning 的設計取捨">4.9 production&lt;/a> 跟 &lt;a href="https://tarrragon.github.io/blog/llm/01-local-llm-services/hands-on/rag-mcp-resources/" data-link-title="Hands-on：RAG / MCP 的資源 footprint" data-link-desc="RAG ingest / query / MCP server 三階段的 RAM / 磁碟 / process 實測、多模型並存的 RAM 衝突、本地 LLM 跑 RAG 跟單純 chat 的差異">RAG/MCP resources&lt;/a> 章節）：&lt;/p>
&lt;table>
 &lt;thead>
 &lt;tr>
 &lt;th>Corpus 規模&lt;/th>
 &lt;th>適合&lt;/th>
 &lt;/tr>
 &lt;/thead>
 &lt;tbody>
 &lt;tr>
 &lt;td>&amp;lt; 10K chunks&lt;/td>
 &lt;td>Python pickle / in-memory list（&lt;a href="https://tarrragon.github.io/blog/llm/01-local-llm-services/hands-on/rag-demo/" data-link-title="Hands-on：用 blog content 當 corpus 跑 RAG" data-link-desc="200 行 Python：embedding &amp;#43; cosine retrieval &amp;#43; Ollama chat、validating 4.0 RAG 原理">本 blog demo&lt;/a>）&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>10K-100K&lt;/td>
 &lt;td>FAISS / embedded library&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>100K-10M&lt;/td>
 &lt;td>Self-host vector DB&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&amp;gt; 10M&lt;/td>
 &lt;td>Hosted SaaS 或分散式 cluster&lt;/td>
 &lt;/tr>
 &lt;/tbody>
&lt;/table>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>選 vector DB 之前回答四個問題：&lt;/p></description><content:encoded><![CDATA[<p>Vector Database 的核心概念是「<strong>為高維向量設計的儲存系統 + 近似最近鄰 (Approximate Nearest Neighbor, ANN) 檢索引擎</strong>」。是 <a href="/blog/llm/knowledge-cards/rag/" data-link-title="RAG" data-link-desc="Retrieval-Augmented Generation：動態外掛知識給 LLM、繞開模型參數記憶的靜態限制">RAG</a> 系統從 prototype 跨到 production 的關鍵元件——當 <a href="/blog/llm/knowledge-cards/embedding-model/" data-link-title="Embedding Model" data-link-desc="把文字轉成向量的模型：用於 codebase 索引與語意搜尋">embedding</a> index 大到記憶體裝不下、或並發 query 量超過單機處理能力、就要從 pickle / in-memory 升級到 vector DB。</p>
<h2 id="概念位置">概念位置</h2>
<p>Vector DB 跟傳統 SQL / NoSQL database 並列、但專精「向量相似度搜尋」這個操作。它不取代傳統 DB——通常 LLM 應用是兩者並用：傳統 DB 存結構化資料（user / metadata）、vector DB 存 embedding + chunk text。實作上、近期主流是「向量加進去現有 DB」（如 Postgres 的 pgvector extension）或「專用服務」（如 Pinecone、Weaviate、Qdrant）。</p>
<h2 id="可觀察訊號與例子">可觀察訊號與例子</h2>
<p>主流選擇分類：</p>
<table>
  <thead>
      <tr>
          <th>類別</th>
          <th>例子</th>
          <th>適合</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>Hosted SaaS</td>
          <td>Pinecone、Weaviate Cloud、Qdrant Cloud</td>
          <td>不想 maintain、流量大</td>
      </tr>
      <tr>
          <td>Self-host service</td>
          <td>Weaviate、Qdrant、Milvus</td>
          <td>內部部署、控制 cost</td>
      </tr>
      <tr>
          <td>Embedded library</td>
          <td>FAISS、HNSWLib、Annoy</td>
          <td>嵌進應用、單機規模</td>
      </tr>
      <tr>
          <td>DB extension</td>
          <td>pgvector、SQLite + vec</td>
          <td>已有 SQL DB、加 vector 能力</td>
      </tr>
  </tbody>
</table>
<p>關鍵 ANN 演算法：</p>
<ul>
<li><strong>HNSW</strong>（Hierarchical Navigable Small World）：主流、sublinear 查詢、犧牲少許精度</li>
<li><strong>IVF</strong>（Inverted File Index）：分組索引、適合超大規模</li>
<li><strong>Flat</strong>（exhaustive search）：精確但 O(n)、小資料集 OK</li>
</ul>
<p>scale 對照（基於 <a href="/blog/llm/04-applications/production-resource-planning/" data-link-title="4.9 Production 部署的資源評估原理" data-link-desc="從本地單 user 到 production multi-tenant：concurrent users、cost model、observability、SLA、capacity planning 的設計取捨">4.9 production</a> 跟 <a href="/blog/llm/01-local-llm-services/hands-on/rag-mcp-resources/" data-link-title="Hands-on：RAG / MCP 的資源 footprint" data-link-desc="RAG ingest / query / MCP server 三階段的 RAM / 磁碟 / process 實測、多模型並存的 RAM 衝突、本地 LLM 跑 RAG 跟單純 chat 的差異">RAG/MCP resources</a> 章節）：</p>
<table>
  <thead>
      <tr>
          <th>Corpus 規模</th>
          <th>適合</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>&lt; 10K chunks</td>
          <td>Python pickle / in-memory list（<a href="/blog/llm/01-local-llm-services/hands-on/rag-demo/" data-link-title="Hands-on：用 blog content 當 corpus 跑 RAG" data-link-desc="200 行 Python：embedding &#43; cosine retrieval &#43; Ollama chat、validating 4.0 RAG 原理">本 blog demo</a>）</td>
      </tr>
      <tr>
          <td>10K-100K</td>
          <td>FAISS / embedded library</td>
      </tr>
      <tr>
          <td>100K-10M</td>
          <td>Self-host vector DB</td>
      </tr>
      <tr>
          <td>&gt; 10M</td>
          <td>Hosted SaaS 或分散式 cluster</td>
      </tr>
  </tbody>
</table>
<h2 id="設計責任">設計責任</h2>
<p>選 vector DB 之前回答四個問題：</p>
<ol>
<li><strong>Corpus 規模</strong>：決定 hosted vs self-host 取捨。</li>
<li><strong>Update 頻率</strong>：每天一次（適合 batch rebuild）vs 即時（要 incremental update 支援）。</li>
<li><strong>Latency 目標</strong>：&lt; 50ms 要 in-memory HNSW、可接受 200ms 用 disk-based。</li>
<li><strong>Hybrid search 需求</strong>：純向量 vs 向量 + filter（如「embedding 相似 + tag = code」），影響 schema 設計。</li>
</ol>
<p>衍生產物管理上、vector DB 屬於 <a href="/blog/llm/04-applications/artifact-management/" data-link-title="4.10 衍生產物管理原理：什麼進 git、什麼不該" data-link-desc="LLM 應用的 source / derived / external 三類產物對應 git / build cache / registry、與 production 部署的 reproducibility / cost / share 取捨">external 類別</a>——index content 不進 git、用 manifest（如 schema definition + ingest script + version tag）描述。Build pipeline 從 source corpus 自動 rebuild。</p>
<p>不適合 vector DB 的情境：knowledge 高度結構化（直接 SQL）、corpus 小（pickle 就好）、單次 retrieval（off-line 跑、不開 server）。</p>
<p>Storage 升級判讀（什麼規模該從 in-memory 升級到 vector DB）、index 生命週期、dependency 約束的工程分析見 <a href="/blog/llm/04-applications/vector-storage-engineering/" data-link-title="4.22 RAG storage 工程：從 pickle 到 vector database 的選型判讀" data-link-desc="RAG storage backend 選型：規模到哪個階段該從 in-memory 升級到 vector DB、dependency chain 如何收窄選項">4.22 RAG storage 工程</a>。</p>
]]></content:encoded></item><item><title>Vector Norm</title><link>https://tarrragon.github.io/blog/llm/knowledge-cards/vector-norm/</link><pubDate>Tue, 12 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/llm/knowledge-cards/vector-norm/</guid><description>&lt;p>Vector norm（向量範數）的核心概念是「&lt;strong>衡量向量「大小」的純量值&lt;/strong>」。最常用的 L2 norm（歐式長度）= 把每個分量平方加總再開根號；但 L1、L∞ 等其他 norm 也在不同場景出現。Norm 在 LLM 中支撐 cosine similarity、layer normalization、gradient clipping 等核心機制。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>主流 norm 的定義與用途：&lt;/p>
&lt;table>
 &lt;thead>
 &lt;tr>
 &lt;th>Norm&lt;/th>
 &lt;th>定義&lt;/th>
 &lt;th>LLM 中的用途&lt;/th>
 &lt;th>&lt;/th>
 &lt;th>&lt;/th>
 &lt;/tr>
 &lt;/thead>
 &lt;tbody>
 &lt;tr>
 &lt;td>L1（Manhattan）&lt;/td>
 &lt;td>`sum(&lt;/td>
 &lt;td>v_i&lt;/td>
 &lt;td>)`&lt;/td>
 &lt;td>L1 regularization、稀疏化&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;strong>L2（Euclidean）&lt;/strong>&lt;/td>
 &lt;td>&lt;code>sqrt(sum(v_i²))&lt;/code>&lt;/td>
 &lt;td>預設「向量長度」、cosine similarity 的分母&lt;/td>
 &lt;td>&lt;/td>
 &lt;td>&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>L∞（max）&lt;/td>
 &lt;td>`max(&lt;/td>
 &lt;td>v_i&lt;/td>
 &lt;td>)`&lt;/td>
 &lt;td>Gradient clipping by max value、某些 attention scaling&lt;/td>
 &lt;/tr>
 &lt;/tbody>
&lt;/table>
&lt;p>L2 norm 在 LLM 中的關鍵應用：&lt;/p>
&lt;ol>
&lt;li>&lt;strong>Cosine similarity&lt;/strong>：&lt;code>cos(a, b) = (a · b) / (||a||₂ × ||b||₂)&lt;/code>、衡量兩個向量的方向相似度、是 &lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/rag/" data-link-title="RAG" data-link-desc="Retrieval-Augmented Generation：動態外掛知識給 LLM、繞開模型參數記憶的靜態限制">RAG&lt;/a> / semantic search 的核心指標。&lt;/li>
&lt;li>&lt;strong>&lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/embedding-model/" data-link-title="Embedding Model" data-link-desc="把文字轉成向量的模型：用於 codebase 索引與語意搜尋">Embedding model&lt;/a> 正規化&lt;/strong>：通常把 embedding 正規化到 L2 norm = 1、之後 cosine similarity 退化成單純內積（&lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/dot-product/" data-link-title="Dot Product" data-link-desc="兩個向量對應位置相乘再加總、attention score 跟相似度判讀的基礎">dot product&lt;/a>）、計算更快。&lt;/li>
&lt;li>&lt;strong>Gradient clipping&lt;/strong>：訓練時若 &lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/gradient/" data-link-title="Gradient" data-link-desc="loss function 對權重的偏微分向量、指出「該往哪個方向調權重才能讓 loss 下降最快」">gradient&lt;/a> 的 L2 norm 超過閾值（如 1.0）、整體縮放回去、避免 &lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/gradient-explosion-vanishing/" data-link-title="Gradient Explosion / Vanishing" data-link-desc="深層網路訓練中 gradient 透過 chain rule 累乘、容易爆炸或衰減到 0 的兩種失敗模式">explosion&lt;/a>。&lt;/li>
&lt;li>&lt;strong>&lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/layer-normalization/" data-link-title="Layer Normalization" data-link-desc="在每個 token 的 hidden state 上做正規化（減 mean、除 std）、穩定深層網路訓練">Layer normalization&lt;/a>&lt;/strong>：RMSNorm 用 L2 norm（root mean square）做正規化。&lt;/li>
&lt;/ol>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>讀 RAG / embedding 教學看到「normalize embeddings」「cosine similarity」就是 L2 相關運算。寫 code 場景的判讀：用 &lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/vector-database/" data-link-title="Vector Database" data-link-desc="為高維向量 (embedding) 設計的儲存 &amp;#43; 近似最近鄰 (ANN) 檢索系統：RAG 從 prototype 跨到 production 的關鍵元件">vector database&lt;/a> 時、若 embedding 已 L2-normalized、距離指標選 dot product 比 cosine 快（結果相同）；訓練 / fine-tune 自己 model 時、&lt;code>gradient_clip: 1.0&lt;/code> 是常見預設、防止 gradient 偶發爆炸。&lt;/p></description><content:encoded><![CDATA[<p>Vector norm（向量範數）的核心概念是「<strong>衡量向量「大小」的純量值</strong>」。最常用的 L2 norm（歐式長度）= 把每個分量平方加總再開根號；但 L1、L∞ 等其他 norm 也在不同場景出現。Norm 在 LLM 中支撐 cosine similarity、layer normalization、gradient clipping 等核心機制。</p>
<h2 id="概念位置">概念位置</h2>
<p>主流 norm 的定義與用途：</p>
<table>
  <thead>
      <tr>
          <th>Norm</th>
          <th>定義</th>
          <th>LLM 中的用途</th>
          <th></th>
          <th></th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>L1（Manhattan）</td>
          <td>`sum(</td>
          <td>v_i</td>
          <td>)`</td>
          <td>L1 regularization、稀疏化</td>
      </tr>
      <tr>
          <td><strong>L2（Euclidean）</strong></td>
          <td><code>sqrt(sum(v_i²))</code></td>
          <td>預設「向量長度」、cosine similarity 的分母</td>
          <td></td>
          <td></td>
      </tr>
      <tr>
          <td>L∞（max）</td>
          <td>`max(</td>
          <td>v_i</td>
          <td>)`</td>
          <td>Gradient clipping by max value、某些 attention scaling</td>
      </tr>
  </tbody>
</table>
<p>L2 norm 在 LLM 中的關鍵應用：</p>
<ol>
<li><strong>Cosine similarity</strong>：<code>cos(a, b) = (a · b) / (||a||₂ × ||b||₂)</code>、衡量兩個向量的方向相似度、是 <a href="/blog/llm/knowledge-cards/rag/" data-link-title="RAG" data-link-desc="Retrieval-Augmented Generation：動態外掛知識給 LLM、繞開模型參數記憶的靜態限制">RAG</a> / semantic search 的核心指標。</li>
<li><strong><a href="/blog/llm/knowledge-cards/embedding-model/" data-link-title="Embedding Model" data-link-desc="把文字轉成向量的模型：用於 codebase 索引與語意搜尋">Embedding model</a> 正規化</strong>：通常把 embedding 正規化到 L2 norm = 1、之後 cosine similarity 退化成單純內積（<a href="/blog/llm/knowledge-cards/dot-product/" data-link-title="Dot Product" data-link-desc="兩個向量對應位置相乘再加總、attention score 跟相似度判讀的基礎">dot product</a>）、計算更快。</li>
<li><strong>Gradient clipping</strong>：訓練時若 <a href="/blog/llm/knowledge-cards/gradient/" data-link-title="Gradient" data-link-desc="loss function 對權重的偏微分向量、指出「該往哪個方向調權重才能讓 loss 下降最快」">gradient</a> 的 L2 norm 超過閾值（如 1.0）、整體縮放回去、避免 <a href="/blog/llm/knowledge-cards/gradient-explosion-vanishing/" data-link-title="Gradient Explosion / Vanishing" data-link-desc="深層網路訓練中 gradient 透過 chain rule 累乘、容易爆炸或衰減到 0 的兩種失敗模式">explosion</a>。</li>
<li><strong><a href="/blog/llm/knowledge-cards/layer-normalization/" data-link-title="Layer Normalization" data-link-desc="在每個 token 的 hidden state 上做正規化（減 mean、除 std）、穩定深層網路訓練">Layer normalization</a></strong>：RMSNorm 用 L2 norm（root mean square）做正規化。</li>
</ol>
<h2 id="設計責任">設計責任</h2>
<p>讀 RAG / embedding 教學看到「normalize embeddings」「cosine similarity」就是 L2 相關運算。寫 code 場景的判讀：用 <a href="/blog/llm/knowledge-cards/vector-database/" data-link-title="Vector Database" data-link-desc="為高維向量 (embedding) 設計的儲存 &#43; 近似最近鄰 (ANN) 檢索系統：RAG 從 prototype 跨到 production 的關鍵元件">vector database</a> 時、若 embedding 已 L2-normalized、距離指標選 dot product 比 cosine 快（結果相同）；訓練 / fine-tune 自己 model 時、<code>gradient_clip: 1.0</code> 是常見預設、防止 gradient 偶發爆炸。</p>
]]></content:encoded></item><item><title>Vision Encoder</title><link>https://tarrragon.github.io/blog/llm/knowledge-cards/vision-encoder/</link><pubDate>Tue, 12 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/llm/knowledge-cards/vision-encoder/</guid><description>&lt;p>Vision encoder（視覺編碼器）的核心概念是「&lt;strong>&lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/vlm/" data-link-title="VLM（Vision-Language Model）" data-link-desc="同時吃圖片 &amp;#43; 文字輸入、產生文字輸出的 LLM 變體、coding 工作流中處理截圖 / 設計稿 / UI debug 的基底">VLM&lt;/a> 內部把圖片轉成向量序列的模組&lt;/strong>」。主流做法是「把圖片切成 patch、每個 patch 過 ViT（Vision Transformer）變一個向量」、再進入 LLM 的 Transformer 層。Vision encoder 通常用 &lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/clip/" data-link-title="CLIP" data-link-desc="OpenAI 2021 提出的 contrastive image-text pretraining、現代 VLM 的 vision encoder 大多衍生自它">CLIP&lt;/a> 預訓練的權重起始、再跟 LLM 一起 fine-tune。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>Vision encoder 在 VLM 中的位置：&lt;/p>





&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-text" data-lang="text">&lt;span class="line">&lt;span class="ln">1&lt;/span>&lt;span class="cl">Input image（如 1024×1024 RGB）
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">2&lt;/span>&lt;span class="cl"> ↓ 切 patch（如 14×14 patch、每張圖 ~5000 個 patch）
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">3&lt;/span>&lt;span class="cl"> ↓ Vision encoder（ViT 或 CLIP image encoder）
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">4&lt;/span>&lt;span class="cl">Image feature vectors（每個 patch 對應一個 768/1024 維向量）
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">5&lt;/span>&lt;span class="cl"> ↓ Projection layer（vision dim → LLM hidden dim）
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">6&lt;/span>&lt;span class="cl">[Image tokens](/llm/knowledge-cards/image-token/)（變成 LLM 可吃的「視覺 token」）
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">7&lt;/span>&lt;span class="cl"> ↓
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">8&lt;/span>&lt;span class="cl">跟 text token 混合 → Transformer → output token&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>主流 vision encoder 設計：&lt;/p>
&lt;table>
 &lt;thead>
 &lt;tr>
 &lt;th>設計&lt;/th>
 &lt;th>機制&lt;/th>
 &lt;th>代表 VLM&lt;/th>
 &lt;/tr>
 &lt;/thead>
 &lt;tbody>
 &lt;tr>
 &lt;td>CLIP ViT-L/14（或變體）&lt;/td>
 &lt;td>OpenAI CLIP 的 image encoder 直接用&lt;/td>
 &lt;td>LLaVA-1.5、Qwen2-VL、Pixtral&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>SigLIP&lt;/td>
 &lt;td>Google 的 sigmoid-loss CLIP 變體、訓得更穩&lt;/td>
 &lt;td>Gemma 3 Vision、Idefics2&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>自訓 / 多解析度 ViT&lt;/td>
 &lt;td>從頭訓、支援動態解析度（不固定 224×224）&lt;/td>
 &lt;td>Qwen2.5-VL、GPT-4V&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>Native multimodal（單一網路）&lt;/td>
 &lt;td>圖跟文字共用 Transformer、不分開 encoder&lt;/td>
 &lt;td>Chameleon（Meta 研究）&lt;/td>
 &lt;/tr>
 &lt;/tbody>
&lt;/table>
&lt;p>Vision encoder 的關鍵設計取捨：&lt;/p>
&lt;ol>
&lt;li>&lt;strong>解析度&lt;/strong>：固定（224×224 / 336×336）vs 動態（依輸入圖大小）&lt;/li>
&lt;li>&lt;strong>參數量&lt;/strong>：vision encoder 0.3B-1B 是主流；太小辨識能力差、太大拖累整體推論速度&lt;/li>
&lt;li>&lt;strong>Pretrain 來源&lt;/strong>：用 CLIP / SigLIP 預訓練的權重起始、加上 multimodal fine-tune；少數從頭訓&lt;/li>
&lt;li>&lt;strong>跟 LLM 結合方式&lt;/strong>：見 &lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/multimodal-fusion/" data-link-title="Multimodal Fusion" data-link-desc="VLM 把 vision encoder 跟 LLM 結合的方式：early fusion / cross-attention / native multimodal 三條路線">multimodal fusion&lt;/a> 卡&lt;/li>
&lt;/ol>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>讀 VLM model card 看到「vision tower」「ViT backbone」「image encoder」就是這部分。寫 code 場景的判讀：&lt;/p>
&lt;ol>
&lt;li>&lt;strong>解析度影響細節辨識&lt;/strong>：低解析度（224）對「截圖中的小字 / 細邊框」可能模糊、看不清；高解析度（1024+）能看清楚但 token 用量大&lt;/li>
&lt;li>&lt;strong>Token 用量估算&lt;/strong>：一張 1024×1024 圖經過 vision encoder 後、產出 ~500-2500 image tokens（依設計）、相當於一段中等長度的文字 prompt&lt;/li>
&lt;li>&lt;strong>動態解析度模型更實用&lt;/strong>：Qwen2.5-VL / GPT-4V 等支援動態解析度、不會把高清截圖縮成 224 失去細節&lt;/li>
&lt;li>&lt;strong>Vision encoder 不能單獨 fine-tune&lt;/strong>：通常跟 LLM 一起訓、單獨換 vision encoder 會破壞 alignment&lt;/li>
&lt;/ol></description><content:encoded><![CDATA[<p>Vision encoder（視覺編碼器）的核心概念是「<strong><a href="/blog/llm/knowledge-cards/vlm/" data-link-title="VLM（Vision-Language Model）" data-link-desc="同時吃圖片 &#43; 文字輸入、產生文字輸出的 LLM 變體、coding 工作流中處理截圖 / 設計稿 / UI debug 的基底">VLM</a> 內部把圖片轉成向量序列的模組</strong>」。主流做法是「把圖片切成 patch、每個 patch 過 ViT（Vision Transformer）變一個向量」、再進入 LLM 的 Transformer 層。Vision encoder 通常用 <a href="/blog/llm/knowledge-cards/clip/" data-link-title="CLIP" data-link-desc="OpenAI 2021 提出的 contrastive image-text pretraining、現代 VLM 的 vision encoder 大多衍生自它">CLIP</a> 預訓練的權重起始、再跟 LLM 一起 fine-tune。</p>
<h2 id="概念位置">概念位置</h2>
<p>Vision encoder 在 VLM 中的位置：</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="ln">1</span><span class="cl">Input image（如 1024×1024 RGB）
</span></span><span class="line"><span class="ln">2</span><span class="cl">   ↓ 切 patch（如 14×14 patch、每張圖 ~5000 個 patch）
</span></span><span class="line"><span class="ln">3</span><span class="cl">   ↓ Vision encoder（ViT 或 CLIP image encoder）
</span></span><span class="line"><span class="ln">4</span><span class="cl">Image feature vectors（每個 patch 對應一個 768/1024 維向量）
</span></span><span class="line"><span class="ln">5</span><span class="cl">   ↓ Projection layer（vision dim → LLM hidden dim）
</span></span><span class="line"><span class="ln">6</span><span class="cl">[Image tokens](/llm/knowledge-cards/image-token/)（變成 LLM 可吃的「視覺 token」）
</span></span><span class="line"><span class="ln">7</span><span class="cl">   ↓
</span></span><span class="line"><span class="ln">8</span><span class="cl">跟 text token 混合 → Transformer → output token</span></span></code></pre></div><p>主流 vision encoder 設計：</p>
<table>
  <thead>
      <tr>
          <th>設計</th>
          <th>機制</th>
          <th>代表 VLM</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>CLIP ViT-L/14（或變體）</td>
          <td>OpenAI CLIP 的 image encoder 直接用</td>
          <td>LLaVA-1.5、Qwen2-VL、Pixtral</td>
      </tr>
      <tr>
          <td>SigLIP</td>
          <td>Google 的 sigmoid-loss CLIP 變體、訓得更穩</td>
          <td>Gemma 3 Vision、Idefics2</td>
      </tr>
      <tr>
          <td>自訓 / 多解析度 ViT</td>
          <td>從頭訓、支援動態解析度（不固定 224×224）</td>
          <td>Qwen2.5-VL、GPT-4V</td>
      </tr>
      <tr>
          <td>Native multimodal（單一網路）</td>
          <td>圖跟文字共用 Transformer、不分開 encoder</td>
          <td>Chameleon（Meta 研究）</td>
      </tr>
  </tbody>
</table>
<p>Vision encoder 的關鍵設計取捨：</p>
<ol>
<li><strong>解析度</strong>：固定（224×224 / 336×336）vs 動態（依輸入圖大小）</li>
<li><strong>參數量</strong>：vision encoder 0.3B-1B 是主流；太小辨識能力差、太大拖累整體推論速度</li>
<li><strong>Pretrain 來源</strong>：用 CLIP / SigLIP 預訓練的權重起始、加上 multimodal fine-tune；少數從頭訓</li>
<li><strong>跟 LLM 結合方式</strong>：見 <a href="/blog/llm/knowledge-cards/multimodal-fusion/" data-link-title="Multimodal Fusion" data-link-desc="VLM 把 vision encoder 跟 LLM 結合的方式：early fusion / cross-attention / native multimodal 三條路線">multimodal fusion</a> 卡</li>
</ol>
<h2 id="設計責任">設計責任</h2>
<p>讀 VLM model card 看到「vision tower」「ViT backbone」「image encoder」就是這部分。寫 code 場景的判讀：</p>
<ol>
<li><strong>解析度影響細節辨識</strong>：低解析度（224）對「截圖中的小字 / 細邊框」可能模糊、看不清；高解析度（1024+）能看清楚但 token 用量大</li>
<li><strong>Token 用量估算</strong>：一張 1024×1024 圖經過 vision encoder 後、產出 ~500-2500 image tokens（依設計）、相當於一段中等長度的文字 prompt</li>
<li><strong>動態解析度模型更實用</strong>：Qwen2.5-VL / GPT-4V 等支援動態解析度、不會把高清截圖縮成 224 失去細節</li>
<li><strong>Vision encoder 不能單獨 fine-tune</strong>：通常跟 LLM 一起訓、單獨換 vision encoder 會破壞 alignment</li>
</ol>
]]></content:encoded></item><item><title>VLM（Vision-Language Model）</title><link>https://tarrragon.github.io/blog/llm/knowledge-cards/vlm/</link><pubDate>Tue, 12 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/llm/knowledge-cards/vlm/</guid><description>&lt;p>VLM（Vision-Language Model、視覺語言模型）的核心概念是「&lt;strong>同時接受圖片 + 文字輸入、產生文字輸出的 LLM 變體&lt;/strong>」。內部結構是「&lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/vision-encoder/" data-link-title="Vision Encoder" data-link-desc="VLM 內部負責把圖片轉成可進 Transformer 的向量序列的模組、ViT / CLIP encoder 為主流">vision encoder&lt;/a> 把圖片轉成 &lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/image-token/" data-link-title="Image Token" data-link-desc="VLM 把圖片轉成「對 Transformer 而言跟 text token 同質」的向量、計入 context window 預算">image token&lt;/a>、跟文字 token 一起進 Transformer」。寫 code 場景的 VLM 用途：看截圖 debug、看 mockup 寫前端 code、看 architecture 白板照片寫文件。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>VLM 跟純文字 LLM 的差異：&lt;/p>





&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-text" data-lang="text">&lt;span class="line">&lt;span class="ln">1&lt;/span>&lt;span class="cl">純文字 LLM：
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">2&lt;/span>&lt;span class="cl"> text → tokenizer → token IDs → embedding → Transformer → output token
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">3&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">4&lt;/span>&lt;span class="cl">VLM：
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">5&lt;/span>&lt;span class="cl"> text → tokenizer → text token IDs ─┐
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">6&lt;/span>&lt;span class="cl"> ├→ 統一 token sequence → Transformer → output token
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">7&lt;/span>&lt;span class="cl"> image → vision encoder → image tokens ─┘&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>主流 VLM family（2026/5）：&lt;/p>
&lt;table>
 &lt;thead>
 &lt;tr>
 &lt;th>Family&lt;/th>
 &lt;th>商業 / 開源&lt;/th>
 &lt;th>本地可跑&lt;/th>
 &lt;th>Coding 場景強項&lt;/th>
 &lt;/tr>
 &lt;/thead>
 &lt;tbody>
 &lt;tr>
 &lt;td>GPT-4o / GPT-5 vision&lt;/td>
 &lt;td>商業 API&lt;/td>
 &lt;td>不可&lt;/td>
 &lt;td>截圖理解、OCR、UI 推理&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>Claude 3.7 / 4 Sonnet vision&lt;/td>
 &lt;td>商業 API&lt;/td>
 &lt;td>不可&lt;/td>
 &lt;td>截圖 debug、code from mockup&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>Gemini 2.5 Pro vision&lt;/td>
 &lt;td>商業 API&lt;/td>
 &lt;td>不可&lt;/td>
 &lt;td>長視訊 / 多張圖&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;strong>Qwen2.5-VL / Qwen3-VL&lt;/strong>&lt;/td>
 &lt;td>開源&lt;/td>
 &lt;td>7B / 32B / 72B 可本地&lt;/td>
 &lt;td>中英 OCR、UI 元素辨識&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;strong>Llama 3.2 Vision&lt;/strong>&lt;/td>
 &lt;td>開源&lt;/td>
 &lt;td>11B / 90B&lt;/td>
 &lt;td>通用 vision、英文場景&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;strong>Gemma 3 Vision&lt;/strong>&lt;/td>
 &lt;td>開源&lt;/td>
 &lt;td>4B / 12B / 27B&lt;/td>
 &lt;td>多語、輕量本地&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>LLaVA / InternVL / Pixtral&lt;/td>
 &lt;td>開源&lt;/td>
 &lt;td>7B-34B&lt;/td>
 &lt;td>研究 / 特定 use case&lt;/td>
 &lt;/tr>
 &lt;/tbody>
&lt;/table>
&lt;blockquote>
&lt;p>&lt;strong>事實查核註&lt;/strong>：主流 VLM family、本地可跑狀態、coding 場景強項在 2026/5 是估計、依模型更新跟推論伺服器支援度持續變化、引用前以對應 model card 跟 Hugging Face leaderboard 為準。&lt;/p>&lt;/blockquote>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>讀 model card 看到「vision」「VL」「multimodal」「-VL」「visual」就是 VLM。寫 code 場景的判讀：&lt;/p></description><content:encoded><![CDATA[<p>VLM（Vision-Language Model、視覺語言模型）的核心概念是「<strong>同時接受圖片 + 文字輸入、產生文字輸出的 LLM 變體</strong>」。內部結構是「<a href="/blog/llm/knowledge-cards/vision-encoder/" data-link-title="Vision Encoder" data-link-desc="VLM 內部負責把圖片轉成可進 Transformer 的向量序列的模組、ViT / CLIP encoder 為主流">vision encoder</a> 把圖片轉成 <a href="/blog/llm/knowledge-cards/image-token/" data-link-title="Image Token" data-link-desc="VLM 把圖片轉成「對 Transformer 而言跟 text token 同質」的向量、計入 context window 預算">image token</a>、跟文字 token 一起進 Transformer」。寫 code 場景的 VLM 用途：看截圖 debug、看 mockup 寫前端 code、看 architecture 白板照片寫文件。</p>
<h2 id="概念位置">概念位置</h2>
<p>VLM 跟純文字 LLM 的差異：</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="ln">1</span><span class="cl">純文字 LLM：
</span></span><span class="line"><span class="ln">2</span><span class="cl">  text → tokenizer → token IDs → embedding → Transformer → output token
</span></span><span class="line"><span class="ln">3</span><span class="cl">
</span></span><span class="line"><span class="ln">4</span><span class="cl">VLM：
</span></span><span class="line"><span class="ln">5</span><span class="cl">  text → tokenizer → text token IDs ─┐
</span></span><span class="line"><span class="ln">6</span><span class="cl">                                     ├→ 統一 token sequence → Transformer → output token
</span></span><span class="line"><span class="ln">7</span><span class="cl">  image → vision encoder → image tokens ─┘</span></span></code></pre></div><p>主流 VLM family（2026/5）：</p>
<table>
  <thead>
      <tr>
          <th>Family</th>
          <th>商業 / 開源</th>
          <th>本地可跑</th>
          <th>Coding 場景強項</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>GPT-4o / GPT-5 vision</td>
          <td>商業 API</td>
          <td>不可</td>
          <td>截圖理解、OCR、UI 推理</td>
      </tr>
      <tr>
          <td>Claude 3.7 / 4 Sonnet vision</td>
          <td>商業 API</td>
          <td>不可</td>
          <td>截圖 debug、code from mockup</td>
      </tr>
      <tr>
          <td>Gemini 2.5 Pro vision</td>
          <td>商業 API</td>
          <td>不可</td>
          <td>長視訊 / 多張圖</td>
      </tr>
      <tr>
          <td><strong>Qwen2.5-VL / Qwen3-VL</strong></td>
          <td>開源</td>
          <td>7B / 32B / 72B 可本地</td>
          <td>中英 OCR、UI 元素辨識</td>
      </tr>
      <tr>
          <td><strong>Llama 3.2 Vision</strong></td>
          <td>開源</td>
          <td>11B / 90B</td>
          <td>通用 vision、英文場景</td>
      </tr>
      <tr>
          <td><strong>Gemma 3 Vision</strong></td>
          <td>開源</td>
          <td>4B / 12B / 27B</td>
          <td>多語、輕量本地</td>
      </tr>
      <tr>
          <td>LLaVA / InternVL / Pixtral</td>
          <td>開源</td>
          <td>7B-34B</td>
          <td>研究 / 特定 use case</td>
      </tr>
  </tbody>
</table>
<blockquote>
<p><strong>事實查核註</strong>：主流 VLM family、本地可跑狀態、coding 場景強項在 2026/5 是估計、依模型更新跟推論伺服器支援度持續變化、引用前以對應 model card 跟 Hugging Face leaderboard 為準。</p></blockquote>
<h2 id="設計責任">設計責任</h2>
<p>讀 model card 看到「vision」「VL」「multimodal」「-VL」「visual」就是 VLM。寫 code 場景的判讀：</p>
<ol>
<li><strong>任務適合用 vision 才用</strong>：純文字描述夠清楚就別塞圖、image token 多、context 跟推論成本上升</li>
<li><strong>本地跑 VLM 比純文字 LLM 吃資源</strong>：vision encoder 通常 0.3-1B 參數、image 處理階段算力需求大、TTFT 變長</li>
<li><strong>OCR-heavy 任務不一定要 VLM</strong>：純 OCR（識別截圖中文字）用專門 OCR 工具（Tesseract / PaddleOCR）可能更穩、VLM 強項在「理解圖 + 推理」</li>
<li><strong>影片不是免費</strong>：「VLM 看影片」本質是抽 frames 變多張圖、token 用量爆炸、效益看任務</li>
</ol>
]]></content:encoded></item><item><title>Vocabulary Size</title><link>https://tarrragon.github.io/blog/llm/knowledge-cards/vocabulary-size/</link><pubDate>Tue, 12 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/llm/knowledge-cards/vocabulary-size/</guid><description>&lt;p>Vocabulary size（詞彙表大小）的核心概念是「&lt;strong>tokenizer 詞彙表中 token 的總數&lt;/strong>」。是模型訓練時就決定的 hyperparameter、後續不能改。Vocabulary size 影響 &lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/embedding-layer/" data-link-title="Embedding Layer" data-link-desc="Transformer 第一層的查表結構、把整數 token ID 轉成可運算的向量">embedding layer&lt;/a> 大小、單一文字對應的 &lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/token/" data-link-title="Token" data-link-desc="LLM 處理文字時的最小單位：介於字元與單字之間">token&lt;/a> 數、多語言處理品質。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>主流 LLM 的 vocab size 演化：&lt;/p>
&lt;table>
 &lt;thead>
 &lt;tr>
 &lt;th>模型&lt;/th>
 &lt;th>Vocab size&lt;/th>
 &lt;th>設計考量&lt;/th>
 &lt;/tr>
 &lt;/thead>
 &lt;tbody>
 &lt;tr>
 &lt;td>GPT-2&lt;/td>
 &lt;td>50,257&lt;/td>
 &lt;td>早期 byte-level BPE、英文為主&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>Llama 1 / 2&lt;/td>
 &lt;td>32,000&lt;/td>
 &lt;td>緊湊、英文 + 部分多語言&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>Llama 3&lt;/td>
 &lt;td>128,256&lt;/td>
 &lt;td>大幅擴張、改善多語言（特別是非拉丁語系）&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>Gemma 4&lt;/td>
 &lt;td>256,000&lt;/td>
 &lt;td>進一步擴大、強化多語言 + code tokenization&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>Qwen3&lt;/td>
 &lt;td>151,936&lt;/td>
 &lt;td>中文 + 多語言友善&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>DeepSeek-V3&lt;/td>
 &lt;td>129,280&lt;/td>
 &lt;td>中英 + code、跟 Llama 3 同量級&lt;/td>
 &lt;/tr>
 &lt;/tbody>
&lt;/table>
&lt;p>Vocabulary size 的取捨：&lt;/p>
&lt;table>
 &lt;thead>
 &lt;tr>
 &lt;th>Vocab 小（如 32K）&lt;/th>
 &lt;th>Vocab 大（如 256K）&lt;/th>
 &lt;/tr>
 &lt;/thead>
 &lt;tbody>
 &lt;tr>
 &lt;td>Embedding 矩陣小、模型參數少&lt;/td>
 &lt;td>Embedding 矩陣大、模型參數多&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>罕見字 / 多語言被拆很細、token 數多&lt;/td>
 &lt;td>高頻多語言整詞當一 token、token 數少&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>推論計算每步輸出 softmax 較快&lt;/td>
 &lt;td>每步 softmax 較慢（vocab × hidden 矩陣大）&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>API 計費 token 數量較多&lt;/td>
 &lt;td>API 計費 token 數量較少&lt;/td>
 &lt;/tr>
 &lt;/tbody>
&lt;/table>
&lt;p>範例：同段中文「你好、世界」、Llama 1 (vocab 32K) 約 6 token、Gemma 4 (vocab 256K) 約 2-3 token、差距不小。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>讀 model card 看到 &lt;code>vocab_size&lt;/code> 就是這個值。寫 code 場景的判讀：跑同個 prompt、不同模型實際處理的 token 數差很多、影響 &lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/context-window/" data-link-title="Context Window" data-link-desc="模型一次能處理的最大 token 數量：prompt 加生成的總和上限">context window&lt;/a> 利用率跟雲端 API 計費；換 tokenizer = 換 vocab = 整個 &lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/embedding-layer/" data-link-title="Embedding Layer" data-link-desc="Transformer 第一層的查表結構、把整數 token ID 轉成可運算的向量">embedding layer&lt;/a> 失效、所以 fine-tune 通常不動 tokenizer、想增加新語言的最簡單方式是 extend embedding（加新 row 不動既有 row、再 fine-tune）。&lt;/p></description><content:encoded><![CDATA[<p>Vocabulary size（詞彙表大小）的核心概念是「<strong>tokenizer 詞彙表中 token 的總數</strong>」。是模型訓練時就決定的 hyperparameter、後續不能改。Vocabulary size 影響 <a href="/blog/llm/knowledge-cards/embedding-layer/" data-link-title="Embedding Layer" data-link-desc="Transformer 第一層的查表結構、把整數 token ID 轉成可運算的向量">embedding layer</a> 大小、單一文字對應的 <a href="/blog/llm/knowledge-cards/token/" data-link-title="Token" data-link-desc="LLM 處理文字時的最小單位：介於字元與單字之間">token</a> 數、多語言處理品質。</p>
<h2 id="概念位置">概念位置</h2>
<p>主流 LLM 的 vocab size 演化：</p>
<table>
  <thead>
      <tr>
          <th>模型</th>
          <th>Vocab size</th>
          <th>設計考量</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>GPT-2</td>
          <td>50,257</td>
          <td>早期 byte-level BPE、英文為主</td>
      </tr>
      <tr>
          <td>Llama 1 / 2</td>
          <td>32,000</td>
          <td>緊湊、英文 + 部分多語言</td>
      </tr>
      <tr>
          <td>Llama 3</td>
          <td>128,256</td>
          <td>大幅擴張、改善多語言（特別是非拉丁語系）</td>
      </tr>
      <tr>
          <td>Gemma 4</td>
          <td>256,000</td>
          <td>進一步擴大、強化多語言 + code tokenization</td>
      </tr>
      <tr>
          <td>Qwen3</td>
          <td>151,936</td>
          <td>中文 + 多語言友善</td>
      </tr>
      <tr>
          <td>DeepSeek-V3</td>
          <td>129,280</td>
          <td>中英 + code、跟 Llama 3 同量級</td>
      </tr>
  </tbody>
</table>
<p>Vocabulary size 的取捨：</p>
<table>
  <thead>
      <tr>
          <th>Vocab 小（如 32K）</th>
          <th>Vocab 大（如 256K）</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>Embedding 矩陣小、模型參數少</td>
          <td>Embedding 矩陣大、模型參數多</td>
      </tr>
      <tr>
          <td>罕見字 / 多語言被拆很細、token 數多</td>
          <td>高頻多語言整詞當一 token、token 數少</td>
      </tr>
      <tr>
          <td>推論計算每步輸出 softmax 較快</td>
          <td>每步 softmax 較慢（vocab × hidden 矩陣大）</td>
      </tr>
      <tr>
          <td>API 計費 token 數量較多</td>
          <td>API 計費 token 數量較少</td>
      </tr>
  </tbody>
</table>
<p>範例：同段中文「你好、世界」、Llama 1 (vocab 32K) 約 6 token、Gemma 4 (vocab 256K) 約 2-3 token、差距不小。</p>
<h2 id="設計責任">設計責任</h2>
<p>讀 model card 看到 <code>vocab_size</code> 就是這個值。寫 code 場景的判讀：跑同個 prompt、不同模型實際處理的 token 數差很多、影響 <a href="/blog/llm/knowledge-cards/context-window/" data-link-title="Context Window" data-link-desc="模型一次能處理的最大 token 數量：prompt 加生成的總和上限">context window</a> 利用率跟雲端 API 計費；換 tokenizer = 換 vocab = 整個 <a href="/blog/llm/knowledge-cards/embedding-layer/" data-link-title="Embedding Layer" data-link-desc="Transformer 第一層的查表結構、把整數 token ID 轉成可運算的向量">embedding layer</a> 失效、所以 fine-tune 通常不動 tokenizer、想增加新語言的最簡單方式是 extend embedding（加新 row 不動既有 row、再 fine-tune）。</p>
]]></content:encoded></item><item><title>VRAM</title><link>https://tarrragon.github.io/blog/llm/knowledge-cards/vram/</link><pubDate>Tue, 12 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/llm/knowledge-cards/vram/</guid><description>&lt;p>VRAM（Video RAM）的核心概念是「顯卡晶片上的高速記憶體、跟系統主機板上的 RAM 是物理上獨立的兩塊預算」。獨立 GPU 場景下、模型權重要載入 VRAM 才能用 GPU 高速計算；VRAM 容量直接決定能跑多大模型。跟 Apple Silicon 的 &lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/unified-memory/" data-link-title="Unified Memory Architecture" data-link-desc="Apple Silicon 讓 CPU / GPU / NE 共用同一塊記憶體：跑大模型的優勢來源">統一記憶體&lt;/a> 不同、PC 上 VRAM 跟系統 RAM 兩塊預算要分開規劃。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>VRAM 同時影響「能載入什麼」跟「跑多快」兩個維度：&lt;/p>
&lt;ol>
&lt;li>&lt;strong>容量&lt;/strong>（GB）：決定能放多少模型權重 + &lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/kv-cache/" data-link-title="KV Cache" data-link-desc="已處理 token 的 attention 中間結果暫存：避免重算、加速後續生成">KV cache&lt;/a> + 推論中間結果。容量不夠則跑不起來、需透過 &lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/moe-cpu-offload/" data-link-title="MoE CPU 卸載" data-link-desc="把 Mixture-of-Experts 模型不活躍的專家層權重放在系統 RAM、用到再走 PCIe 拉回 GPU、讓有限 VRAM 跑得了更大模型">MoE CPU 卸載&lt;/a> 把部分權重放系統 RAM。&lt;/li>
&lt;li>&lt;strong>頻寬&lt;/strong>（GB/s）：影響每 token 生成速度上限、見 &lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/memory-bandwidth/" data-link-title="Memory Bandwidth" data-link-desc="記憶體每秒能讀寫多少 bytes：決定本地 LLM 生字速度的真正瓶頸">memory bandwidth&lt;/a> 卡片。&lt;/li>
&lt;/ol>
&lt;p>常見消費級 GPU 的 VRAM 規格（廠商標稱、依世代與型號變化）：&lt;/p>
&lt;table>
 &lt;thead>
 &lt;tr>
 &lt;th>GPU&lt;/th>
 &lt;th>VRAM 容量&lt;/th>
 &lt;th>VRAM 類型&lt;/th>
 &lt;/tr>
 &lt;/thead>
 &lt;tbody>
 &lt;tr>
 &lt;td>RTX 5060 / 4060&lt;/td>
 &lt;td>8GB&lt;/td>
 &lt;td>GDDR6/7&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>RTX 5060 Ti / 4060 Ti&lt;/td>
 &lt;td>16GB&lt;/td>
 &lt;td>GDDR6/7&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>RTX 5070 Ti / 4070 Ti&lt;/td>
 &lt;td>16GB&lt;/td>
 &lt;td>GDDR6/7&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>RTX 4090&lt;/td>
 &lt;td>24GB&lt;/td>
 &lt;td>GDDR6X&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>RTX 5090&lt;/td>
 &lt;td>32GB&lt;/td>
 &lt;td>GDDR7&lt;/td>
 &lt;/tr>
 &lt;/tbody>
&lt;/table>
&lt;p>VRAM 容量是選 GPU 跑本地 LLM 的第一決策軸、頻寬是第二決策軸。同容量下、頻寬接近 2 倍的卡（如 5070 Ti 對 5060 Ti）生字速度差異明顯。&lt;/p>
&lt;blockquote>
&lt;p>&lt;strong>事實查核註&lt;/strong>：上表是 2026 年 5 月主流消費級 NVIDIA GPU 規格的數量級對照、實際 VRAM 容量、頻寬、GDDR 版本依特定型號、廠商 / SKU、製造時間變化、引用前以 &lt;a href="https://www.nvidia.com/en-us/geforce/graphics-cards/">NVIDIA 官方規格頁&lt;/a> 為準。&lt;/p>&lt;/blockquote>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>理解 VRAM 後可以解釋三個現象：為什麼同樣 16GB 容量、不同卡的生字速度差很多（頻寬不同）；為什麼 MoE 模型在 16GB VRAM 上跑得了 30B 級模型（透過卸載）；為什麼 &lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/pcie/" data-link-title="PCIe" data-link-desc="PC 上連接 GPU 跟主機板的高速序列匯流排、影響模型載入速度跟 MoE 卸載時的推論吞吐">PCIe&lt;/a> 頻寬在 PC 場景影響 MoE 卸載的速度（系統 RAM 跟 VRAM 之間的橋）。&lt;/p>
&lt;p>選 PC 規劃本地 LLM 時、VRAM 容量決定能跑的模型上限、VRAM 頻寬決定生字速度上限、系統 RAM 容量決定 MoE 卸載空間。詳見 &lt;a href="https://tarrragon.github.io/blog/llm/05-discrete-gpu/vram-ram-budget/" data-link-title="5.0 VRAM &amp;#43; RAM 分層預算" data-link-desc="PC 獨立 GPU 場景的記憶體預算判讀：VRAM 是快的世界、RAM 是大的世界、PCIe 把兩個世界連起來">5.0 VRAM + RAM 分層預算&lt;/a>。&lt;/p></description><content:encoded><![CDATA[<p>VRAM（Video RAM）的核心概念是「顯卡晶片上的高速記憶體、跟系統主機板上的 RAM 是物理上獨立的兩塊預算」。獨立 GPU 場景下、模型權重要載入 VRAM 才能用 GPU 高速計算；VRAM 容量直接決定能跑多大模型。跟 Apple Silicon 的 <a href="/blog/llm/knowledge-cards/unified-memory/" data-link-title="Unified Memory Architecture" data-link-desc="Apple Silicon 讓 CPU / GPU / NE 共用同一塊記憶體：跑大模型的優勢來源">統一記憶體</a> 不同、PC 上 VRAM 跟系統 RAM 兩塊預算要分開規劃。</p>
<h2 id="概念位置">概念位置</h2>
<p>VRAM 同時影響「能載入什麼」跟「跑多快」兩個維度：</p>
<ol>
<li><strong>容量</strong>（GB）：決定能放多少模型權重 + <a href="/blog/llm/knowledge-cards/kv-cache/" data-link-title="KV Cache" data-link-desc="已處理 token 的 attention 中間結果暫存：避免重算、加速後續生成">KV cache</a> + 推論中間結果。容量不夠則跑不起來、需透過 <a href="/blog/llm/knowledge-cards/moe-cpu-offload/" data-link-title="MoE CPU 卸載" data-link-desc="把 Mixture-of-Experts 模型不活躍的專家層權重放在系統 RAM、用到再走 PCIe 拉回 GPU、讓有限 VRAM 跑得了更大模型">MoE CPU 卸載</a> 把部分權重放系統 RAM。</li>
<li><strong>頻寬</strong>（GB/s）：影響每 token 生成速度上限、見 <a href="/blog/llm/knowledge-cards/memory-bandwidth/" data-link-title="Memory Bandwidth" data-link-desc="記憶體每秒能讀寫多少 bytes：決定本地 LLM 生字速度的真正瓶頸">memory bandwidth</a> 卡片。</li>
</ol>
<p>常見消費級 GPU 的 VRAM 規格（廠商標稱、依世代與型號變化）：</p>
<table>
  <thead>
      <tr>
          <th>GPU</th>
          <th>VRAM 容量</th>
          <th>VRAM 類型</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>RTX 5060 / 4060</td>
          <td>8GB</td>
          <td>GDDR6/7</td>
      </tr>
      <tr>
          <td>RTX 5060 Ti / 4060 Ti</td>
          <td>16GB</td>
          <td>GDDR6/7</td>
      </tr>
      <tr>
          <td>RTX 5070 Ti / 4070 Ti</td>
          <td>16GB</td>
          <td>GDDR6/7</td>
      </tr>
      <tr>
          <td>RTX 4090</td>
          <td>24GB</td>
          <td>GDDR6X</td>
      </tr>
      <tr>
          <td>RTX 5090</td>
          <td>32GB</td>
          <td>GDDR7</td>
      </tr>
  </tbody>
</table>
<p>VRAM 容量是選 GPU 跑本地 LLM 的第一決策軸、頻寬是第二決策軸。同容量下、頻寬接近 2 倍的卡（如 5070 Ti 對 5060 Ti）生字速度差異明顯。</p>
<blockquote>
<p><strong>事實查核註</strong>：上表是 2026 年 5 月主流消費級 NVIDIA GPU 規格的數量級對照、實際 VRAM 容量、頻寬、GDDR 版本依特定型號、廠商 / SKU、製造時間變化、引用前以 <a href="https://www.nvidia.com/en-us/geforce/graphics-cards/">NVIDIA 官方規格頁</a> 為準。</p></blockquote>
<h2 id="設計責任">設計責任</h2>
<p>理解 VRAM 後可以解釋三個現象：為什麼同樣 16GB 容量、不同卡的生字速度差很多（頻寬不同）；為什麼 MoE 模型在 16GB VRAM 上跑得了 30B 級模型（透過卸載）；為什麼 <a href="/blog/llm/knowledge-cards/pcie/" data-link-title="PCIe" data-link-desc="PC 上連接 GPU 跟主機板的高速序列匯流排、影響模型載入速度跟 MoE 卸載時的推論吞吐">PCIe</a> 頻寬在 PC 場景影響 MoE 卸載的速度（系統 RAM 跟 VRAM 之間的橋）。</p>
<p>選 PC 規劃本地 LLM 時、VRAM 容量決定能跑的模型上限、VRAM 頻寬決定生字速度上限、系統 RAM 容量決定 MoE 卸載空間。詳見 <a href="/blog/llm/05-discrete-gpu/vram-ram-budget/" data-link-title="5.0 VRAM &#43; RAM 分層預算" data-link-desc="PC 獨立 GPU 場景的記憶體預算判讀：VRAM 是快的世界、RAM 是大的世界、PCIe 把兩個世界連起來">5.0 VRAM + RAM 分層預算</a>。</p>
]]></content:encoded></item><item><title>Autoregressive</title><link>https://tarrragon.github.io/blog/llm/knowledge-cards/autoregressive/</link><pubDate>Mon, 11 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/llm/knowledge-cards/autoregressive/</guid><description>&lt;p>Autoregressive（自回歸）的核心概念是「下一個 &lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/token/" data-link-title="Token" data-link-desc="LLM 處理文字時的最小單位：介於字元與單字之間">token&lt;/a> 的生成需要看到前面所有 token」。LLM 每生一個 token 都要把目前的完整序列（prompt + 已生成部分）丟進神經網路跑一次，得到下一個 token 的機率分佈，挑一個輸出，再循環。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>Autoregressive 是 &lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/transformer/" data-link-title="Transformer" data-link-desc="寫 code 用的 LLM 神經網路架構：基於 attention 機制、自回歸生成 token">Transformer&lt;/a> 模型用於文字生成的運作方式。它跟生成式架構的另一條路線 &lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/diffusion/" data-link-title="Diffusion" data-link-desc="產圖用的生成式 AI 架構：跟寫 code 用的 Transformer 是不同路線">Diffusion&lt;/a> 形成對比：Diffusion 一次處理整張圖、autoregressive 一個 token 一個 token 接龍。寫 code 用的 LLM 都是 autoregressive。&lt;/p>
&lt;h2 id="可觀察訊號與例子">可觀察訊號與例子&lt;/h2>
&lt;p>寫 code 場景的 streaming 輸出就是 autoregressive 的直接體現：你看到回答「邊想邊出現」，實際是每個 token 各跑一次 forward pass 後即時顯示。&lt;code>寫 fibonacci function&lt;/code> 的回答經過「&lt;code>def&lt;/code> → &lt;code>def fib&lt;/code> → &lt;code>def fib(&lt;/code> → &amp;hellip;」這樣逐 token 推進；模型回答越長等越久，跟雲端旗艦一樣，差別只在每次 forward pass 跑得多快。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>理解 autoregressive 後可以判讀幾件事：streaming 只是把已產出的 token 即時顯示、跟生成速度本身無關；回答長度直接影響等待時間；任何「一次生多個 token」的加速技巧（&lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/speculative-decoding/" data-link-title="Speculative Decoding" data-link-desc="用小模型猜未來 token、大模型並行驗證的加速技巧">speculative decoding&lt;/a>、&lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/mtp/" data-link-title="Multi-Token Prediction (MTP)" data-link-desc="Google 為 Gemma 系列釋出的 speculative decoding 工程化實作">MTP&lt;/a>）都是針對 autoregressive 的優化、而非取代。&lt;/p></description><content:encoded><![CDATA[<p>Autoregressive（自回歸）的核心概念是「下一個 <a href="/blog/llm/knowledge-cards/token/" data-link-title="Token" data-link-desc="LLM 處理文字時的最小單位：介於字元與單字之間">token</a> 的生成需要看到前面所有 token」。LLM 每生一個 token 都要把目前的完整序列（prompt + 已生成部分）丟進神經網路跑一次，得到下一個 token 的機率分佈，挑一個輸出，再循環。</p>
<h2 id="概念位置">概念位置</h2>
<p>Autoregressive 是 <a href="/blog/llm/knowledge-cards/transformer/" data-link-title="Transformer" data-link-desc="寫 code 用的 LLM 神經網路架構：基於 attention 機制、自回歸生成 token">Transformer</a> 模型用於文字生成的運作方式。它跟生成式架構的另一條路線 <a href="/blog/llm/knowledge-cards/diffusion/" data-link-title="Diffusion" data-link-desc="產圖用的生成式 AI 架構：跟寫 code 用的 Transformer 是不同路線">Diffusion</a> 形成對比：Diffusion 一次處理整張圖、autoregressive 一個 token 一個 token 接龍。寫 code 用的 LLM 都是 autoregressive。</p>
<h2 id="可觀察訊號與例子">可觀察訊號與例子</h2>
<p>寫 code 場景的 streaming 輸出就是 autoregressive 的直接體現：你看到回答「邊想邊出現」，實際是每個 token 各跑一次 forward pass 後即時顯示。<code>寫 fibonacci function</code> 的回答經過「<code>def</code> → <code>def fib</code> → <code>def fib(</code> → &hellip;」這樣逐 token 推進；模型回答越長等越久，跟雲端旗艦一樣，差別只在每次 forward pass 跑得多快。</p>
<h2 id="設計責任">設計責任</h2>
<p>理解 autoregressive 後可以判讀幾件事：streaming 只是把已產出的 token 即時顯示、跟生成速度本身無關；回答長度直接影響等待時間；任何「一次生多個 token」的加速技巧（<a href="/blog/llm/knowledge-cards/speculative-decoding/" data-link-title="Speculative Decoding" data-link-desc="用小模型猜未來 token、大模型並行驗證的加速技巧">speculative decoding</a>、<a href="/blog/llm/knowledge-cards/mtp/" data-link-title="Multi-Token Prediction (MTP)" data-link-desc="Google 為 Gemma 系列釋出的 speculative decoding 工程化實作">MTP</a>）都是針對 autoregressive 的優化、而非取代。</p>
]]></content:encoded></item><item><title>Base Model</title><link>https://tarrragon.github.io/blog/llm/knowledge-cards/base-model/</link><pubDate>Mon, 11 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/llm/knowledge-cards/base-model/</guid><description>&lt;p>Base Model 的核心概念是「LLM 訓練 pipeline 第一階段的產物」，只用大量文字做 next-token prediction、尚未做 &lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/instruction-tuned/" data-link-title="Instruction-Tuned Model" data-link-desc="經過指令微調的模型：會跟著 prompt 走、回答使用者問題">instruction tuning&lt;/a> 或 RLHF。Base model 擅長「順著前面的文字接下去」，但對「使用者提問、模型回答」這種交互模式比較生硬。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>Base model 跟 instruction-tuned model 共用底層權重結構、差別在後續微調階段。對寫 code 場景的多數使用者來說、預設選 instruction-tuned 版本；base model 主要服務想自己微調的研究人員與工程師。&lt;/p>
&lt;h2 id="可觀察訊號與例子">可觀察訊號與例子&lt;/h2>
&lt;p>Hugging Face / Ollama 上 base model 通常會明示：&lt;/p>
&lt;table>
 &lt;thead>
 &lt;tr>
 &lt;th>名稱範例&lt;/th>
 &lt;th>是 base model 嗎&lt;/th>
 &lt;/tr>
 &lt;/thead>
 &lt;tbody>
 &lt;tr>
 &lt;td>&lt;code>llama-3.3-70b-base&lt;/code>&lt;/td>
 &lt;td>是&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;code>llama-3.3-70b-instruct&lt;/code>&lt;/td>
 &lt;td>否（&lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/instruction-tuned/" data-link-title="Instruction-Tuned Model" data-link-desc="經過指令微調的模型：會跟著 prompt 走、回答使用者問題">已 instruction-tuned&lt;/a>）&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;code>gemma-4-31b&lt;/code>&lt;/td>
 &lt;td>視 repo 而定、要看 model card&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;code>qwen3-coder-30b&lt;/code>&lt;/td>
 &lt;td>否（coding-tuned 是 instruction-tuned 的特化）&lt;/td>
 &lt;/tr>
 &lt;/tbody>
&lt;/table>
&lt;p>對話 base model 的體感：問「寫一個 Python fibonacci」可能得到「寫一個 Python fibonacci。寫一個 JavaScript fibonacci。寫一個&amp;hellip;」這種文字接龍式回答、而非真正寫出 function。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>下載模型前確認是 instruct 還是 base 版本。Ollama registry 預設提供 instruct 版本、但 Hugging Face 上同一個模型常同時有兩種；挑錯版本會以為「這個模型很差」、其實只是用錯類型。想做 fine-tuning 的工程師才需要 base model；其他人優先選 instruct。&lt;/p></description><content:encoded><![CDATA[<p>Base Model 的核心概念是「LLM 訓練 pipeline 第一階段的產物」，只用大量文字做 next-token prediction、尚未做 <a href="/blog/llm/knowledge-cards/instruction-tuned/" data-link-title="Instruction-Tuned Model" data-link-desc="經過指令微調的模型：會跟著 prompt 走、回答使用者問題">instruction tuning</a> 或 RLHF。Base model 擅長「順著前面的文字接下去」，但對「使用者提問、模型回答」這種交互模式比較生硬。</p>
<h2 id="概念位置">概念位置</h2>
<p>Base model 跟 instruction-tuned model 共用底層權重結構、差別在後續微調階段。對寫 code 場景的多數使用者來說、預設選 instruction-tuned 版本；base model 主要服務想自己微調的研究人員與工程師。</p>
<h2 id="可觀察訊號與例子">可觀察訊號與例子</h2>
<p>Hugging Face / Ollama 上 base model 通常會明示：</p>
<table>
  <thead>
      <tr>
          <th>名稱範例</th>
          <th>是 base model 嗎</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td><code>llama-3.3-70b-base</code></td>
          <td>是</td>
      </tr>
      <tr>
          <td><code>llama-3.3-70b-instruct</code></td>
          <td>否（<a href="/blog/llm/knowledge-cards/instruction-tuned/" data-link-title="Instruction-Tuned Model" data-link-desc="經過指令微調的模型：會跟著 prompt 走、回答使用者問題">已 instruction-tuned</a>）</td>
      </tr>
      <tr>
          <td><code>gemma-4-31b</code></td>
          <td>視 repo 而定、要看 model card</td>
      </tr>
      <tr>
          <td><code>qwen3-coder-30b</code></td>
          <td>否（coding-tuned 是 instruction-tuned 的特化）</td>
      </tr>
  </tbody>
</table>
<p>對話 base model 的體感：問「寫一個 Python fibonacci」可能得到「寫一個 Python fibonacci。寫一個 JavaScript fibonacci。寫一個&hellip;」這種文字接龍式回答、而非真正寫出 function。</p>
<h2 id="設計責任">設計責任</h2>
<p>下載模型前確認是 instruct 還是 base 版本。Ollama registry 預設提供 instruct 版本、但 Hugging Face 上同一個模型常同時有兩種；挑錯版本會以為「這個模型很差」、其實只是用錯類型。想做 fine-tuning 的工程師才需要 base model；其他人優先選 instruct。</p>
]]></content:encoded></item><item><title>Context Window</title><link>https://tarrragon.github.io/blog/llm/knowledge-cards/context-window/</link><pubDate>Mon, 11 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/llm/knowledge-cards/context-window/</guid><description>&lt;p>Context Window 的核心概念是「模型一次能處理的最大 &lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/token/" data-link-title="Token" data-link-desc="LLM 處理文字時的最小單位：介於字元與單字之間">token&lt;/a> 序列長度」，包含 prompt 與生成內容的總和。超過上限時，較早的 token 會被截掉、模型「看不到」前面的對話。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>Context window 是模型訓練時決定的硬性限制，跟 &lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/kv-cache/" data-link-title="KV Cache" data-link-desc="已處理 token 的 attention 中間結果暫存：避免重算、加速後續生成">KV cache&lt;/a> 共同決定推論時的記憶體佔用。較大的 context window 讓模型能讀整個 repo 或長對話，但代價是 &lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/ttft/" data-link-title="TTFT" data-link-desc="Time To First Token：送出 prompt 到第一個 token 出現的等待時間">TTFT&lt;/a> 升高與記憶體吃緊。&lt;/p>
&lt;h2 id="可觀察訊號與例子">可觀察訊號與例子&lt;/h2>
&lt;p>2026 年 5 月各模型典型 context window：&lt;/p>
&lt;table>
 &lt;thead>
 &lt;tr>
 &lt;th>模型&lt;/th>
 &lt;th>Context Window&lt;/th>
 &lt;/tr>
 &lt;/thead>
 &lt;tbody>
 &lt;tr>
 &lt;td>Gemma 4 31B&lt;/td>
 &lt;td>256K tokens&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>Qwen3-Coder 30B&lt;/td>
 &lt;td>256K tokens&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>Llama 3.3 70B&lt;/td>
 &lt;td>128K tokens&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>Claude Sonnet 4.6（雲端）&lt;/td>
 &lt;td>1M tokens&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>GPT-5（雲端）&lt;/td>
 &lt;td>400K tokens&lt;/td>
 &lt;/tr>
 &lt;/tbody>
&lt;/table>
&lt;p>「支援 128K」跟「實用 128K」是兩件事。本地跑長 context 時 KV cache 會吃掉大量記憶體，例如 32GB Mac 跑 31B 模型實用 context 大約 8 ~ 16K tokens；硬塞 128K 會 swap、跑成蝸牛。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>評估「能不能塞整個 repo 進 prompt」要綜合三個指標：模型聲稱的 context window、實際記憶體預算、可接受的 TTFT。寫 prompt 時若反覆達到上限、考慮整理 prompt 結構（移除不必要 context）或改用支援更大 context 的雲端模型，而非硬塞。&lt;/p></description><content:encoded><![CDATA[<p>Context Window 的核心概念是「模型一次能處理的最大 <a href="/blog/llm/knowledge-cards/token/" data-link-title="Token" data-link-desc="LLM 處理文字時的最小單位：介於字元與單字之間">token</a> 序列長度」，包含 prompt 與生成內容的總和。超過上限時，較早的 token 會被截掉、模型「看不到」前面的對話。</p>
<h2 id="概念位置">概念位置</h2>
<p>Context window 是模型訓練時決定的硬性限制，跟 <a href="/blog/llm/knowledge-cards/kv-cache/" data-link-title="KV Cache" data-link-desc="已處理 token 的 attention 中間結果暫存：避免重算、加速後續生成">KV cache</a> 共同決定推論時的記憶體佔用。較大的 context window 讓模型能讀整個 repo 或長對話，但代價是 <a href="/blog/llm/knowledge-cards/ttft/" data-link-title="TTFT" data-link-desc="Time To First Token：送出 prompt 到第一個 token 出現的等待時間">TTFT</a> 升高與記憶體吃緊。</p>
<h2 id="可觀察訊號與例子">可觀察訊號與例子</h2>
<p>2026 年 5 月各模型典型 context window：</p>
<table>
  <thead>
      <tr>
          <th>模型</th>
          <th>Context Window</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>Gemma 4 31B</td>
          <td>256K tokens</td>
      </tr>
      <tr>
          <td>Qwen3-Coder 30B</td>
          <td>256K tokens</td>
      </tr>
      <tr>
          <td>Llama 3.3 70B</td>
          <td>128K tokens</td>
      </tr>
      <tr>
          <td>Claude Sonnet 4.6（雲端）</td>
          <td>1M tokens</td>
      </tr>
      <tr>
          <td>GPT-5（雲端）</td>
          <td>400K tokens</td>
      </tr>
  </tbody>
</table>
<p>「支援 128K」跟「實用 128K」是兩件事。本地跑長 context 時 KV cache 會吃掉大量記憶體，例如 32GB Mac 跑 31B 模型實用 context 大約 8 ~ 16K tokens；硬塞 128K 會 swap、跑成蝸牛。</p>
<h2 id="設計責任">設計責任</h2>
<p>評估「能不能塞整個 repo 進 prompt」要綜合三個指標：模型聲稱的 context window、實際記憶體預算、可接受的 TTFT。寫 prompt 時若反覆達到上限、考慮整理 prompt 結構（移除不必要 context）或改用支援更大 context 的雲端模型，而非硬塞。</p>
]]></content:encoded></item><item><title>Diffusion</title><link>https://tarrragon.github.io/blog/llm/knowledge-cards/diffusion/</link><pubDate>Mon, 11 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/llm/knowledge-cards/diffusion/</guid><description>&lt;p>Diffusion 的核心概念是「從純雜訊開始、逐步去噪生成完整資料的神經網路架構」。產圖（Stable Diffusion、Flux、SDXL）、產影片、產音樂多半用 Diffusion。它跟寫 code 用的 &lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/transformer/" data-link-title="Transformer" data-link-desc="寫 code 用的 LLM 神經網路架構：基於 attention 機制、自回歸生成 token">Transformer&lt;/a> 是兩個獨立的生成式 AI 路線、推論流程、工具鏈、適合任務都不同。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>Diffusion 模型一次處理整張圖、用「去噪 N 步」的方式生成；跟 Transformer 的「一個 &lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/token/" data-link-title="Token" data-link-desc="LLM 處理文字時的最小單位：介於字元與單字之間">token&lt;/a> 接一個 token」生成方式根本不同。記憶體需求、硬體最適規格、生態系都是平行宇宙。&lt;/p>
&lt;h2 id="可觀察訊號與例子">可觀察訊號與例子&lt;/h2>
&lt;p>Diffusion 跟 Transformer 工具鏈完全不通用：&lt;/p>
&lt;table>
 &lt;thead>
 &lt;tr>
 &lt;th>維度&lt;/th>
 &lt;th>Transformer LLM&lt;/th>
 &lt;th>Diffusion&lt;/th>
 &lt;/tr>
 &lt;/thead>
 &lt;tbody>
 &lt;tr>
 &lt;td>主流模型&lt;/td>
 &lt;td>Gemma 4、Qwen3、Llama 3.3、GPT-5&lt;/td>
 &lt;td>Stable Diffusion、Flux、SDXL&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>推論伺服器&lt;/td>
 &lt;td>Ollama、LM Studio、llama.cpp、oMLX&lt;/td>
 &lt;td>ComfyUI、Draw Things、AUTOMATIC1111、Diffusers&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>推論時間&lt;/td>
 &lt;td>每秒幾十 tok（autoregressive）&lt;/td>
 &lt;td>整張圖 15 ~ 60 秒（一次到位）&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>硬體最適&lt;/td>
 &lt;td>記憶體大、頻寬高&lt;/td>
 &lt;td>GPU 算力高、VRAM 頻寬高&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>Prompt 風格&lt;/td>
 &lt;td>instruction 形式&lt;/td>
 &lt;td>descriptive + negative prompt&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>量化技術&lt;/td>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/gguf/" data-link-title="GGUF" data-link-desc="llama.cpp 生態定義的模型權重格式：把權重、tokenizer、metadata 打包成單一檔案">GGUF&lt;/a>、MLX&lt;/td>
 &lt;td>各家不同、Diffusers 為主&lt;/td>
 &lt;/tr>
 &lt;/tbody>
&lt;/table>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>聽到「換 model 就能產圖」的說法時、回到本卡確認：產圖是另一個領域、要切換到 Diffusion 工具鏈、而非在 Ollama 上下載產圖模型。寫 code 工作流跟產圖工作流分開學、避免兩邊半生不熟。對 Mac 使用者來說、Draw Things（macOS 原生 app）是產圖入門的最低門檻路徑。&lt;/p></description><content:encoded><![CDATA[<p>Diffusion 的核心概念是「從純雜訊開始、逐步去噪生成完整資料的神經網路架構」。產圖（Stable Diffusion、Flux、SDXL）、產影片、產音樂多半用 Diffusion。它跟寫 code 用的 <a href="/blog/llm/knowledge-cards/transformer/" data-link-title="Transformer" data-link-desc="寫 code 用的 LLM 神經網路架構：基於 attention 機制、自回歸生成 token">Transformer</a> 是兩個獨立的生成式 AI 路線、推論流程、工具鏈、適合任務都不同。</p>
<h2 id="概念位置">概念位置</h2>
<p>Diffusion 模型一次處理整張圖、用「去噪 N 步」的方式生成；跟 Transformer 的「一個 <a href="/blog/llm/knowledge-cards/token/" data-link-title="Token" data-link-desc="LLM 處理文字時的最小單位：介於字元與單字之間">token</a> 接一個 token」生成方式根本不同。記憶體需求、硬體最適規格、生態系都是平行宇宙。</p>
<h2 id="可觀察訊號與例子">可觀察訊號與例子</h2>
<p>Diffusion 跟 Transformer 工具鏈完全不通用：</p>
<table>
  <thead>
      <tr>
          <th>維度</th>
          <th>Transformer LLM</th>
          <th>Diffusion</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>主流模型</td>
          <td>Gemma 4、Qwen3、Llama 3.3、GPT-5</td>
          <td>Stable Diffusion、Flux、SDXL</td>
      </tr>
      <tr>
          <td>推論伺服器</td>
          <td>Ollama、LM Studio、llama.cpp、oMLX</td>
          <td>ComfyUI、Draw Things、AUTOMATIC1111、Diffusers</td>
      </tr>
      <tr>
          <td>推論時間</td>
          <td>每秒幾十 tok（autoregressive）</td>
          <td>整張圖 15 ~ 60 秒（一次到位）</td>
      </tr>
      <tr>
          <td>硬體最適</td>
          <td>記憶體大、頻寬高</td>
          <td>GPU 算力高、VRAM 頻寬高</td>
      </tr>
      <tr>
          <td>Prompt 風格</td>
          <td>instruction 形式</td>
          <td>descriptive + negative prompt</td>
      </tr>
      <tr>
          <td>量化技術</td>
          <td><a href="/blog/llm/knowledge-cards/gguf/" data-link-title="GGUF" data-link-desc="llama.cpp 生態定義的模型權重格式：把權重、tokenizer、metadata 打包成單一檔案">GGUF</a>、MLX</td>
          <td>各家不同、Diffusers 為主</td>
      </tr>
  </tbody>
</table>
<h2 id="設計責任">設計責任</h2>
<p>聽到「換 model 就能產圖」的說法時、回到本卡確認：產圖是另一個領域、要切換到 Diffusion 工具鏈、而非在 Ollama 上下載產圖模型。寫 code 工作流跟產圖工作流分開學、避免兩邊半生不熟。對 Mac 使用者來說、Draw Things（macOS 原生 app）是產圖入門的最低門檻路徑。</p>
]]></content:encoded></item><item><title>Drafter Model</title><link>https://tarrragon.github.io/blog/llm/knowledge-cards/drafter-model/</link><pubDate>Mon, 11 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/llm/knowledge-cards/drafter-model/</guid><description>&lt;p>Drafter Model 的核心概念是「&lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/speculative-decoding/" data-link-title="Speculative Decoding" data-link-desc="用小模型猜未來 token、大模型並行驗證的加速技巧">speculative decoding&lt;/a> 中用來快速預測未來幾個 &lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/token/" data-link-title="Token" data-link-desc="LLM 處理文字時的最小單位：介於字元與單字之間">token&lt;/a> 的小模型」。它跑得比 target model 快很多倍、每次跑一個 forward pass 猜 N 個 token、再交給 target model 並行驗證。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>Drafter 與 target 形成一對：drafter 快但較不準、target 慢但準確、兩者組合得到「跑得快的近似 target」。drafter 在記憶體中跟 target 一起載入、佔額外記憶體。Gemma 4 31B + 官方 drafter 的記憶體佔用約「target 18GB + drafter 1GB」、需要 32GB+ Mac 才順暢。&lt;/p>
&lt;h2 id="可觀察訊號與例子">可觀察訊號與例子&lt;/h2>
&lt;p>匹配的 drafter / target 對：&lt;/p>
&lt;table>
 &lt;thead>
 &lt;tr>
 &lt;th>Target&lt;/th>
 &lt;th>Drafter&lt;/th>
 &lt;th>來源&lt;/th>
 &lt;/tr>
 &lt;/thead>
 &lt;tbody>
 &lt;tr>
 &lt;td>Gemma 4 31B&lt;/td>
 &lt;td>Gemma 4 E4B&lt;/td>
 &lt;td>Google 官方釋出&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>Llama 3.3 70B&lt;/td>
 &lt;td>Llama 3.2 1B&lt;/td>
 &lt;td>社群配對&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>Qwen3-Coder 30B&lt;/td>
 &lt;td>（尚未有官方）&lt;/td>
 &lt;td>Alibaba 還未釋出 drafter&lt;/td>
 &lt;/tr>
 &lt;/tbody>
&lt;/table>
&lt;p>關鍵限制：drafter 與 target 必須用相同 tokenizer。Gemma 系列只能配 Gemma 系列、Llama 系列只能配 Llama 系列、跨家族沒有相容性。LM Studio 的 UI 在挑 drafter 時會自動過濾相容候選。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>寫 code 場景的多數使用者透過預先打包的 model tag（如 Ollama 的 &lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/mtp/" data-link-title="Multi-Token Prediction (MTP)" data-link-desc="Google 為 Gemma 系列釋出的 speculative decoding 工程化實作">MTP&lt;/a> 版本）取得 drafter、不用自己配對。想用其他模型的 speculative decoding 時、要確認社群是否有匹配的 drafter；找不到的情況下、預設用沒 speculative decoding 的版本是合理選擇、加速收益跟「找 drafter、自己配置」的成本比起來通常不划算。&lt;/p></description><content:encoded><![CDATA[<p>Drafter Model 的核心概念是「<a href="/blog/llm/knowledge-cards/speculative-decoding/" data-link-title="Speculative Decoding" data-link-desc="用小模型猜未來 token、大模型並行驗證的加速技巧">speculative decoding</a> 中用來快速預測未來幾個 <a href="/blog/llm/knowledge-cards/token/" data-link-title="Token" data-link-desc="LLM 處理文字時的最小單位：介於字元與單字之間">token</a> 的小模型」。它跑得比 target model 快很多倍、每次跑一個 forward pass 猜 N 個 token、再交給 target model 並行驗證。</p>
<h2 id="概念位置">概念位置</h2>
<p>Drafter 與 target 形成一對：drafter 快但較不準、target 慢但準確、兩者組合得到「跑得快的近似 target」。drafter 在記憶體中跟 target 一起載入、佔額外記憶體。Gemma 4 31B + 官方 drafter 的記憶體佔用約「target 18GB + drafter 1GB」、需要 32GB+ Mac 才順暢。</p>
<h2 id="可觀察訊號與例子">可觀察訊號與例子</h2>
<p>匹配的 drafter / target 對：</p>
<table>
  <thead>
      <tr>
          <th>Target</th>
          <th>Drafter</th>
          <th>來源</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>Gemma 4 31B</td>
          <td>Gemma 4 E4B</td>
          <td>Google 官方釋出</td>
      </tr>
      <tr>
          <td>Llama 3.3 70B</td>
          <td>Llama 3.2 1B</td>
          <td>社群配對</td>
      </tr>
      <tr>
          <td>Qwen3-Coder 30B</td>
          <td>（尚未有官方）</td>
          <td>Alibaba 還未釋出 drafter</td>
      </tr>
  </tbody>
</table>
<p>關鍵限制：drafter 與 target 必須用相同 tokenizer。Gemma 系列只能配 Gemma 系列、Llama 系列只能配 Llama 系列、跨家族沒有相容性。LM Studio 的 UI 在挑 drafter 時會自動過濾相容候選。</p>
<h2 id="設計責任">設計責任</h2>
<p>寫 code 場景的多數使用者透過預先打包的 model tag（如 Ollama 的 <a href="/blog/llm/knowledge-cards/mtp/" data-link-title="Multi-Token Prediction (MTP)" data-link-desc="Google 為 Gemma 系列釋出的 speculative decoding 工程化實作">MTP</a> 版本）取得 drafter、不用自己配對。想用其他模型的 speculative decoding 時、要確認社群是否有匹配的 drafter；找不到的情況下、預設用沒 speculative decoding 的版本是合理選擇、加速收益跟「找 drafter、自己配置」的成本比起來通常不划算。</p>
]]></content:encoded></item><item><title>Embedding Model</title><link>https://tarrragon.github.io/blog/llm/knowledge-cards/embedding-model/</link><pubDate>Mon, 11 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/llm/knowledge-cards/embedding-model/</guid><description>&lt;p>Embedding Model 的核心概念是「把文字轉成固定維度向量、讓相似內容在向量空間中靠近」。Continue.dev 等工具用 embedding model 把 codebase 索引成向量資料庫、再用語意相似度搜尋相關片段。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>Embedding model 跟 chat model 是兩種不同的模型、有各自的權重檔。Chat model 用於對話與生成、embedding model 用於 retrieval。同一個推論伺服器（如 Ollama）可以同時載入兩種模型、為不同用途服務。&lt;/p>
&lt;h2 id="可觀察訊號與例子">可觀察訊號與例子&lt;/h2>
&lt;p>寫 code 場景常用的 embedding 模型：&lt;/p>
&lt;table>
 &lt;thead>
 &lt;tr>
 &lt;th>模型&lt;/th>
 &lt;th>大小&lt;/th>
 &lt;th>用途&lt;/th>
 &lt;/tr>
 &lt;/thead>
 &lt;tbody>
 &lt;tr>
 &lt;td>&lt;code>nomic-embed-text&lt;/code>&lt;/td>
 &lt;td>274MB&lt;/td>
 &lt;td>英文為主、Continue.dev 預設&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;code>mxbai-embed-large&lt;/code>&lt;/td>
 &lt;td>670MB&lt;/td>
 &lt;td>較強的英文 embedding&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;code>bge-m3&lt;/code>&lt;/td>
 &lt;td>1.2GB&lt;/td>
 &lt;td>多語言（含中文）embedding&lt;/td>
 &lt;/tr>
 &lt;/tbody>
&lt;/table>
&lt;p>向量維度通常 384 ~ 1024、不同模型不同；切換 embedding 模型要重建索引、向量空間互不相容。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>Continue.dev 的 &lt;code>@codebase&lt;/code> 命令依賴 embedding 模型；要先 &lt;code>ollama pull nomic-embed-text&lt;/code> 並在 config.json 設 &lt;code>embeddingsProvider&lt;/code>。Embedding 模型對 codebase 搜尋品質有影響、但邊際效益遠小於 chat model；先用預設 &lt;code>nomic-embed-text&lt;/code>、需求出現再換更大模型。&lt;/p></description><content:encoded><![CDATA[<p>Embedding Model 的核心概念是「把文字轉成固定維度向量、讓相似內容在向量空間中靠近」。Continue.dev 等工具用 embedding model 把 codebase 索引成向量資料庫、再用語意相似度搜尋相關片段。</p>
<h2 id="概念位置">概念位置</h2>
<p>Embedding model 跟 chat model 是兩種不同的模型、有各自的權重檔。Chat model 用於對話與生成、embedding model 用於 retrieval。同一個推論伺服器（如 Ollama）可以同時載入兩種模型、為不同用途服務。</p>
<h2 id="可觀察訊號與例子">可觀察訊號與例子</h2>
<p>寫 code 場景常用的 embedding 模型：</p>
<table>
  <thead>
      <tr>
          <th>模型</th>
          <th>大小</th>
          <th>用途</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td><code>nomic-embed-text</code></td>
          <td>274MB</td>
          <td>英文為主、Continue.dev 預設</td>
      </tr>
      <tr>
          <td><code>mxbai-embed-large</code></td>
          <td>670MB</td>
          <td>較強的英文 embedding</td>
      </tr>
      <tr>
          <td><code>bge-m3</code></td>
          <td>1.2GB</td>
          <td>多語言（含中文）embedding</td>
      </tr>
  </tbody>
</table>
<p>向量維度通常 384 ~ 1024、不同模型不同；切換 embedding 模型要重建索引、向量空間互不相容。</p>
<h2 id="設計責任">設計責任</h2>
<p>Continue.dev 的 <code>@codebase</code> 命令依賴 embedding 模型；要先 <code>ollama pull nomic-embed-text</code> 並在 config.json 設 <code>embeddingsProvider</code>。Embedding 模型對 codebase 搜尋品質有影響、但邊際效益遠小於 chat model；先用預設 <code>nomic-embed-text</code>、需求出現再換更大模型。</p>
]]></content:encoded></item><item><title>Function Calling</title><link>https://tarrragon.github.io/blog/llm/knowledge-cards/function-calling/</link><pubDate>Mon, 11 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/llm/knowledge-cards/function-calling/</guid><description>&lt;p>Function Calling 的核心概念是「模型在訓練階段學到的呼叫工具能力」。SFT 階段大量「使用者 query + 該呼叫什麼工具 + 傳什麼參數」的範例、讓模型學會看到 query 知道何時呼叫、怎麼呼叫、傳什麼參數。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>Function calling 是&lt;strong>模型能力&lt;/strong>層、跟 &lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/structured-output/" data-link-title="Structured Output" data-link-desc="讓 LLM 輸出可被 parser 穩定消費的推論階段設計：JSON mode、schema-guided decoding、grammar 約束都屬於這一層">structured output&lt;/a>（**&lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/sampling-constraint/" data-link-title="Sampling Constraint" data-link-desc="推論時限制下一個 token 候選集合的控制手段，用來把模型生成導向合法格式或特定選項">sampling 約束&lt;/a>**層）、&lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/mcp/" data-link-title="MCP（Model Context Protocol）" data-link-desc="LLM application ↔ 外部 tool server 之間的標準化協議、複用 OpenAI 相容 API 的成功模式">MCP&lt;/a>（&lt;strong>server 協議&lt;/strong>層）正交。三者解的問題層級不同、可獨立或組合使用。模型訓練支撐 vs sampling 強制的差別決定行為穩定性：function calling 訓練好的模型「自然」輸出合法呼叫、不需要強約束；訓練不足靠 structured output 兜底。&lt;/p>
&lt;h2 id="可觀察訊號與例子">可觀察訊號與例子&lt;/h2>
&lt;p>模型 function calling 強弱看四個指標：(1) 該呼叫時呼叫的準確度、(2) 呼叫格式合法率、(3) 參數準確度、(4) 多工具選對工具的準確度。寫 code 場景的本地小模型（&amp;lt; 14B）這四個都明顯弱於雲端旗艦——根因是 SFT 階段 function calling 範例量不夠、小模型容量學不全。判讀訊號：呼叫格式錯、參數胡亂填、不該呼叫時呼叫、該呼叫時不呼叫。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>選擇 function calling 還是 free-form + structured output、依模型規模跟跨 model 可移植需求決定：主流大模型走 function calling 開箱即用、跨 model / 較弱模型走 free-form + &lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/grammar/" data-link-title="Grammar" data-link-desc="描述合法字串形狀的形式規則，在 structured output 中用來限制 LLM 每一步可輸出的 token">grammar&lt;/a> 約束較穩。實務常組合：function calling 「正常情況」、structured output 兜底保證合法、retry + fallback 處理失敗。詳細展開見 &lt;a href="https://tarrragon.github.io/blog/llm/04-applications/tool-use-principles/" data-link-title="4.3 Tool use 原理：LLM 跟外部世界互動" data-link-desc="Structured output 是 LLM 跨入工程系統的橋、function calling 取捨、為什麼本地小模型 tool use 表現崩潰">4.3 Tool use 原理&lt;/a> 與 &lt;a href="https://tarrragon.github.io/blog/llm/04-applications/application-protocols/" data-link-title="4.6 應用層協議：function calling / structured output / MCP" data-link-desc="三個常被混為一談的概念：模型能力、sampling 約束、server 協議，三者的層級差異與組合方式">4.6 應用層協議&lt;/a>。&lt;/p></description><content:encoded><![CDATA[<p>Function Calling 的核心概念是「模型在訓練階段學到的呼叫工具能力」。SFT 階段大量「使用者 query + 該呼叫什麼工具 + 傳什麼參數」的範例、讓模型學會看到 query 知道何時呼叫、怎麼呼叫、傳什麼參數。</p>
<h2 id="概念位置">概念位置</h2>
<p>Function calling 是<strong>模型能力</strong>層、跟 <a href="/blog/llm/knowledge-cards/structured-output/" data-link-title="Structured Output" data-link-desc="讓 LLM 輸出可被 parser 穩定消費的推論階段設計：JSON mode、schema-guided decoding、grammar 約束都屬於這一層">structured output</a>（**<a href="/blog/llm/knowledge-cards/sampling-constraint/" data-link-title="Sampling Constraint" data-link-desc="推論時限制下一個 token 候選集合的控制手段，用來把模型生成導向合法格式或特定選項">sampling 約束</a>**層）、<a href="/blog/llm/knowledge-cards/mcp/" data-link-title="MCP（Model Context Protocol）" data-link-desc="LLM application ↔ 外部 tool server 之間的標準化協議、複用 OpenAI 相容 API 的成功模式">MCP</a>（<strong>server 協議</strong>層）正交。三者解的問題層級不同、可獨立或組合使用。模型訓練支撐 vs sampling 強制的差別決定行為穩定性：function calling 訓練好的模型「自然」輸出合法呼叫、不需要強約束；訓練不足靠 structured output 兜底。</p>
<h2 id="可觀察訊號與例子">可觀察訊號與例子</h2>
<p>模型 function calling 強弱看四個指標：(1) 該呼叫時呼叫的準確度、(2) 呼叫格式合法率、(3) 參數準確度、(4) 多工具選對工具的準確度。寫 code 場景的本地小模型（&lt; 14B）這四個都明顯弱於雲端旗艦——根因是 SFT 階段 function calling 範例量不夠、小模型容量學不全。判讀訊號：呼叫格式錯、參數胡亂填、不該呼叫時呼叫、該呼叫時不呼叫。</p>
<h2 id="設計責任">設計責任</h2>
<p>選擇 function calling 還是 free-form + structured output、依模型規模跟跨 model 可移植需求決定：主流大模型走 function calling 開箱即用、跨 model / 較弱模型走 free-form + <a href="/blog/llm/knowledge-cards/grammar/" data-link-title="Grammar" data-link-desc="描述合法字串形狀的形式規則，在 structured output 中用來限制 LLM 每一步可輸出的 token">grammar</a> 約束較穩。實務常組合：function calling 「正常情況」、structured output 兜底保證合法、retry + fallback 處理失敗。詳細展開見 <a href="/blog/llm/04-applications/tool-use-principles/" data-link-title="4.3 Tool use 原理：LLM 跟外部世界互動" data-link-desc="Structured output 是 LLM 跨入工程系統的橋、function calling 取捨、為什麼本地小模型 tool use 表現崩潰">4.3 Tool use 原理</a> 與 <a href="/blog/llm/04-applications/application-protocols/" data-link-title="4.6 應用層協議：function calling / structured output / MCP" data-link-desc="三個常被混為一談的概念：模型能力、sampling 約束、server 協議，三者的層級差異與組合方式">4.6 應用層協議</a>。</p>
]]></content:encoded></item><item><title>GGUF</title><link>https://tarrragon.github.io/blog/llm/knowledge-cards/gguf/</link><pubDate>Mon, 11 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/llm/knowledge-cards/gguf/</guid><description>&lt;p>GGUF（GGML Unified Format）的核心概念是「llama.cpp 系統定義的模型權重格式」，把模型權重、tokenizer 設定、模型 metadata 全部打包進單一檔案。Ollama 內部存的就是 GGUF，多數本地推論伺服器（除了走 &lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/mlx/" data-link-title="MLX" data-link-desc="Apple 釋出的 Apple Silicon 數值運算 framework：類似 PyTorch / JAX 的 Mac 對應物">MLX&lt;/a> 路線的）也支援。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>GGUF 屬於模型層的封裝格式，跟 Safetensors（Hugging Face 通用）、MLX format（Apple 生態）是平行的選擇。它的設計目標是「單一檔案、跨平台、支援多種&lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/quantization/" data-link-title="Quantization" data-link-desc="用較少 bits 表示模型權重：壓縮記憶體佔用、加快生字速度，代價是少量品質衰減">量化&lt;/a>等級」。Ollama、LM Studio、llama.cpp 都用 GGUF；想跑 MLX 系統的 oMLX 則要 MLX format 權重。&lt;/p>
&lt;h2 id="可觀察訊號與例子">可觀察訊號與例子&lt;/h2>
&lt;p>Hugging Face 上 GGUF 檔案命名通常含量化標籤：&lt;/p>
&lt;table>
 &lt;thead>
 &lt;tr>
 &lt;th>檔名範例&lt;/th>
 &lt;th>解讀&lt;/th>
 &lt;/tr>
 &lt;/thead>
 &lt;tbody>
 &lt;tr>
 &lt;td>&lt;code>gemma-4-31b-it-Q4_K_M.gguf&lt;/code>&lt;/td>
 &lt;td>Gemma 4、31B、instruct-tuned、Q4_K_M 量化&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;code>Llama-3.3-70B-Instruct-Q5_K_M.gguf&lt;/code>&lt;/td>
 &lt;td>Llama 3.3、70B、instruct、Q5_K_M&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;code>qwen3-coder-30b-Q8_0.gguf&lt;/code>&lt;/td>
 &lt;td>Qwen3-Coder、30B、Q8 量化&lt;/td>
 &lt;/tr>
 &lt;/tbody>
&lt;/table>
&lt;p>社群常見的高品質 GGUF 提供者有 &lt;code>bartowski&lt;/code>、&lt;code>unsloth&lt;/code>、&lt;code>TheBloke&lt;/code>（已退坑）等；挑下載量高、最近更新的 repo 較安全。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>直接下載 GGUF 多半用於 LM Studio 與 llama.cpp 場景。Ollama 使用者通常透過 &lt;code>ollama pull&lt;/code> 拉模型，背後格式也是 GGUF、但細節對使用者透明。想自己量化模型（從 Safetensors 轉 GGUF）要用 llama.cpp 的 &lt;code>quantize&lt;/code> 工具，這是少數需要直接面對 GGUF 內部的場景。&lt;/p></description><content:encoded><![CDATA[<p>GGUF（GGML Unified Format）的核心概念是「llama.cpp 系統定義的模型權重格式」，把模型權重、tokenizer 設定、模型 metadata 全部打包進單一檔案。Ollama 內部存的就是 GGUF，多數本地推論伺服器（除了走 <a href="/blog/llm/knowledge-cards/mlx/" data-link-title="MLX" data-link-desc="Apple 釋出的 Apple Silicon 數值運算 framework：類似 PyTorch / JAX 的 Mac 對應物">MLX</a> 路線的）也支援。</p>
<h2 id="概念位置">概念位置</h2>
<p>GGUF 屬於模型層的封裝格式，跟 Safetensors（Hugging Face 通用）、MLX format（Apple 生態）是平行的選擇。它的設計目標是「單一檔案、跨平台、支援多種<a href="/blog/llm/knowledge-cards/quantization/" data-link-title="Quantization" data-link-desc="用較少 bits 表示模型權重：壓縮記憶體佔用、加快生字速度，代價是少量品質衰減">量化</a>等級」。Ollama、LM Studio、llama.cpp 都用 GGUF；想跑 MLX 系統的 oMLX 則要 MLX format 權重。</p>
<h2 id="可觀察訊號與例子">可觀察訊號與例子</h2>
<p>Hugging Face 上 GGUF 檔案命名通常含量化標籤：</p>
<table>
  <thead>
      <tr>
          <th>檔名範例</th>
          <th>解讀</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td><code>gemma-4-31b-it-Q4_K_M.gguf</code></td>
          <td>Gemma 4、31B、instruct-tuned、Q4_K_M 量化</td>
      </tr>
      <tr>
          <td><code>Llama-3.3-70B-Instruct-Q5_K_M.gguf</code></td>
          <td>Llama 3.3、70B、instruct、Q5_K_M</td>
      </tr>
      <tr>
          <td><code>qwen3-coder-30b-Q8_0.gguf</code></td>
          <td>Qwen3-Coder、30B、Q8 量化</td>
      </tr>
  </tbody>
</table>
<p>社群常見的高品質 GGUF 提供者有 <code>bartowski</code>、<code>unsloth</code>、<code>TheBloke</code>（已退坑）等；挑下載量高、最近更新的 repo 較安全。</p>
<h2 id="設計責任">設計責任</h2>
<p>直接下載 GGUF 多半用於 LM Studio 與 llama.cpp 場景。Ollama 使用者通常透過 <code>ollama pull</code> 拉模型，背後格式也是 GGUF、但細節對使用者透明。想自己量化模型（從 Safetensors 轉 GGUF）要用 llama.cpp 的 <code>quantize</code> 工具，這是少數需要直接面對 GGUF 內部的場景。</p>
]]></content:encoded></item><item><title>Inference Server</title><link>https://tarrragon.github.io/blog/llm/knowledge-cards/inference-server/</link><pubDate>Mon, 11 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/llm/knowledge-cards/inference-server/</guid><description>&lt;p>Inference Server（推論伺服器）的核心概念是「常駐在機器上、載入模型權重、接收 API 請求、跑推論、回傳生成內容的 process」。本地 LLM 三層架構中、推論伺服器位於介面層（CLI / IDE / Web UI）與模型層（權重檔）之間。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>推論伺服器封裝模型載入、&lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/quantization/" data-link-title="Quantization" data-link-desc="用較少 bits 表示模型權重：壓縮記憶體佔用、加快生字速度，代價是少量品質衰減">量化&lt;/a>、&lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/kv-cache/" data-link-title="KV Cache" data-link-desc="已處理 token 的 attention 中間結果暫存：避免重算、加速後續生成">KV cache&lt;/a> 管理、&lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/speculative-decoding/" data-link-title="Speculative Decoding" data-link-desc="用小模型猜未來 token、大模型並行驗證的加速技巧">speculative decoding&lt;/a> 等推論細節、對外提供 HTTP API。多數本地推論伺服器同時提供 &lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/openai-compatible-api/" data-link-title="OpenAI 相容 API" data-link-desc="本地推論伺服器跟雲端 OpenAI 共用的 API 形狀標準">OpenAI 相容 API&lt;/a> 與自家原生 API。&lt;/p>
&lt;h2 id="可觀察訊號與例子">可觀察訊號與例子&lt;/h2>
&lt;p>2026 年 5 月主流本地推論伺服器：&lt;/p>
&lt;table>
 &lt;thead>
 &lt;tr>
 &lt;th>伺服器&lt;/th>
 &lt;th>預設 port&lt;/th>
 &lt;th>內部引擎&lt;/th>
 &lt;th>適合誰&lt;/th>
 &lt;/tr>
 &lt;/thead>
 &lt;tbody>
 &lt;tr>
 &lt;td>Ollama&lt;/td>
 &lt;td>11434&lt;/td>
 &lt;td>llama.cpp&lt;/td>
 &lt;td>多數使用者的預設&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>LM Studio&lt;/td>
 &lt;td>1234&lt;/td>
 &lt;td>llama.cpp + GUI&lt;/td>
 &lt;td>GUI 派、探索新模型&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>llama.cpp&lt;/td>
 &lt;td>8080&lt;/td>
 &lt;td>自己&lt;/td>
 &lt;td>進階使用者、特殊量化&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>oMLX&lt;/td>
 &lt;td>8000&lt;/td>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/mlx/" data-link-title="MLX" data-link-desc="Apple 釋出的 Apple Silicon 數值運算 framework：類似 PyTorch / JAX 的 Mac 對應物">MLX&lt;/a>&lt;/td>
 &lt;td>長 context coding agent&lt;/td>
 &lt;/tr>
 &lt;/tbody>
&lt;/table>
&lt;p>並存可行：port 不同就不衝突、Continue.dev 等介面層可以同時設多個 model、各指向不同伺服器。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>選擇推論伺服器看三件事：是否提供 OpenAI 相容 API（影響能接哪些介面層）、模型格式支援（&lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/gguf/" data-link-title="GGUF" data-link-desc="llama.cpp 生態定義的模型權重格式：把權重、tokenizer、metadata 打包成單一檔案">GGUF&lt;/a>、MLX format）、加速技巧支援（&lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/mtp/" data-link-title="Multi-Token Prediction (MTP)" data-link-desc="Google 為 Gemma 系列釋出的 speculative decoding 工程化實作">MTP&lt;/a> 等）。寫 code 場景的多數使用者用 Ollama 已足夠；其他選擇是針對特定需求的特化路徑。&lt;/p></description><content:encoded><![CDATA[<p>Inference Server（推論伺服器）的核心概念是「常駐在機器上、載入模型權重、接收 API 請求、跑推論、回傳生成內容的 process」。本地 LLM 三層架構中、推論伺服器位於介面層（CLI / IDE / Web UI）與模型層（權重檔）之間。</p>
<h2 id="概念位置">概念位置</h2>
<p>推論伺服器封裝模型載入、<a href="/blog/llm/knowledge-cards/quantization/" data-link-title="Quantization" data-link-desc="用較少 bits 表示模型權重：壓縮記憶體佔用、加快生字速度，代價是少量品質衰減">量化</a>、<a href="/blog/llm/knowledge-cards/kv-cache/" data-link-title="KV Cache" data-link-desc="已處理 token 的 attention 中間結果暫存：避免重算、加速後續生成">KV cache</a> 管理、<a href="/blog/llm/knowledge-cards/speculative-decoding/" data-link-title="Speculative Decoding" data-link-desc="用小模型猜未來 token、大模型並行驗證的加速技巧">speculative decoding</a> 等推論細節、對外提供 HTTP API。多數本地推論伺服器同時提供 <a href="/blog/llm/knowledge-cards/openai-compatible-api/" data-link-title="OpenAI 相容 API" data-link-desc="本地推論伺服器跟雲端 OpenAI 共用的 API 形狀標準">OpenAI 相容 API</a> 與自家原生 API。</p>
<h2 id="可觀察訊號與例子">可觀察訊號與例子</h2>
<p>2026 年 5 月主流本地推論伺服器：</p>
<table>
  <thead>
      <tr>
          <th>伺服器</th>
          <th>預設 port</th>
          <th>內部引擎</th>
          <th>適合誰</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>Ollama</td>
          <td>11434</td>
          <td>llama.cpp</td>
          <td>多數使用者的預設</td>
      </tr>
      <tr>
          <td>LM Studio</td>
          <td>1234</td>
          <td>llama.cpp + GUI</td>
          <td>GUI 派、探索新模型</td>
      </tr>
      <tr>
          <td>llama.cpp</td>
          <td>8080</td>
          <td>自己</td>
          <td>進階使用者、特殊量化</td>
      </tr>
      <tr>
          <td>oMLX</td>
          <td>8000</td>
          <td><a href="/blog/llm/knowledge-cards/mlx/" data-link-title="MLX" data-link-desc="Apple 釋出的 Apple Silicon 數值運算 framework：類似 PyTorch / JAX 的 Mac 對應物">MLX</a></td>
          <td>長 context coding agent</td>
      </tr>
  </tbody>
</table>
<p>並存可行：port 不同就不衝突、Continue.dev 等介面層可以同時設多個 model、各指向不同伺服器。</p>
<h2 id="設計責任">設計責任</h2>
<p>選擇推論伺服器看三件事：是否提供 OpenAI 相容 API（影響能接哪些介面層）、模型格式支援（<a href="/blog/llm/knowledge-cards/gguf/" data-link-title="GGUF" data-link-desc="llama.cpp 生態定義的模型權重格式：把權重、tokenizer、metadata 打包成單一檔案">GGUF</a>、MLX format）、加速技巧支援（<a href="/blog/llm/knowledge-cards/mtp/" data-link-title="Multi-Token Prediction (MTP)" data-link-desc="Google 為 Gemma 系列釋出的 speculative decoding 工程化實作">MTP</a> 等）。寫 code 場景的多數使用者用 Ollama 已足夠；其他選擇是針對特定需求的特化路徑。</p>
]]></content:encoded></item><item><title>Instruction-Tuned Model</title><link>https://tarrragon.github.io/blog/llm/knowledge-cards/instruction-tuned/</link><pubDate>Mon, 11 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/llm/knowledge-cards/instruction-tuned/</guid><description>&lt;p>Instruction-Tuned Model 的核心概念是「在 &lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/base-model/" data-link-title="Base Model" data-link-desc="未經指令微調的原始模型：擅長文字接龍、適合下游微調用途">base model&lt;/a> 之上、用指令-回答對資料進一步微調」。微調目的是讓模型理解「使用者問 X、應該回答 Y」這種交互模式。寫 code 場景該用的就是 instruction-tuned 模型（多半標 &lt;code>-instruct&lt;/code> 或 &lt;code>-it&lt;/code>）。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>Instruction tuning 是 LLM 訓練 pipeline 的中間階段：base model（純文字接龍）→ instruction-tuned（會跟指令走）→ RLHF（進一步對齊人類偏好）。寫 code 用的 Gemma 4 31B、Qwen3-Coder 30B、Llama 3.3 70B 等都是 instruction-tuned 版本。&lt;/p>
&lt;h2 id="可觀察訊號與例子">可觀察訊號與例子&lt;/h2>
&lt;p>Ollama tag 中的 &lt;code>instruct&lt;/code>、&lt;code>it&lt;/code> 是 instruction-tuned 標記：&lt;/p>
&lt;table>
 &lt;thead>
 &lt;tr>
 &lt;th>模型 tag&lt;/th>
 &lt;th>解讀&lt;/th>
 &lt;/tr>
 &lt;/thead>
 &lt;tbody>
 &lt;tr>
 &lt;td>&lt;code>gemma4:31b-instruct-q5_K_M&lt;/code>&lt;/td>
 &lt;td>Gemma 4、instruct-tuned&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;code>llama3.3:70b-instruct-q4_K_M&lt;/code>&lt;/td>
 &lt;td>Llama 3.3、instruct-tuned&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;code>qwen3-coder:30b&lt;/code>&lt;/td>
 &lt;td>Qwen3-Coder（預設就是 instruct，未必額外標）&lt;/td>
 &lt;/tr>
 &lt;/tbody>
&lt;/table>
&lt;p>Coding-tuned 是 instruction-tuned 的特化版本，再加上大量 code 訓練資料；Qwen3-Coder、Gemma 4 coding 版本都屬於這類。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>寫 code 場景的預設選擇是 instruction-tuned + coding-specialized 模型。看到 Ollama tag 沒有 &lt;code>instruct&lt;/code> 字樣（如 &lt;code>llama3.3:70b-base&lt;/code>）的版本、那是 &lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/base-model/" data-link-title="Base Model" data-link-desc="未經指令微調的原始模型：擅長文字接龍、適合下游微調用途">base model&lt;/a>、跟指令走的能力較差、適合下游微調而非直接對話。&lt;/p></description><content:encoded><![CDATA[<p>Instruction-Tuned Model 的核心概念是「在 <a href="/blog/llm/knowledge-cards/base-model/" data-link-title="Base Model" data-link-desc="未經指令微調的原始模型：擅長文字接龍、適合下游微調用途">base model</a> 之上、用指令-回答對資料進一步微調」。微調目的是讓模型理解「使用者問 X、應該回答 Y」這種交互模式。寫 code 場景該用的就是 instruction-tuned 模型（多半標 <code>-instruct</code> 或 <code>-it</code>）。</p>
<h2 id="概念位置">概念位置</h2>
<p>Instruction tuning 是 LLM 訓練 pipeline 的中間階段：base model（純文字接龍）→ instruction-tuned（會跟指令走）→ RLHF（進一步對齊人類偏好）。寫 code 用的 Gemma 4 31B、Qwen3-Coder 30B、Llama 3.3 70B 等都是 instruction-tuned 版本。</p>
<h2 id="可觀察訊號與例子">可觀察訊號與例子</h2>
<p>Ollama tag 中的 <code>instruct</code>、<code>it</code> 是 instruction-tuned 標記：</p>
<table>
  <thead>
      <tr>
          <th>模型 tag</th>
          <th>解讀</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td><code>gemma4:31b-instruct-q5_K_M</code></td>
          <td>Gemma 4、instruct-tuned</td>
      </tr>
      <tr>
          <td><code>llama3.3:70b-instruct-q4_K_M</code></td>
          <td>Llama 3.3、instruct-tuned</td>
      </tr>
      <tr>
          <td><code>qwen3-coder:30b</code></td>
          <td>Qwen3-Coder（預設就是 instruct，未必額外標）</td>
      </tr>
  </tbody>
</table>
<p>Coding-tuned 是 instruction-tuned 的特化版本，再加上大量 code 訓練資料；Qwen3-Coder、Gemma 4 coding 版本都屬於這類。</p>
<h2 id="設計責任">設計責任</h2>
<p>寫 code 場景的預設選擇是 instruction-tuned + coding-specialized 模型。看到 Ollama tag 沒有 <code>instruct</code> 字樣（如 <code>llama3.3:70b-base</code>）的版本、那是 <a href="/blog/llm/knowledge-cards/base-model/" data-link-title="Base Model" data-link-desc="未經指令微調的原始模型：擅長文字接龍、適合下游微調用途">base model</a>、跟指令走的能力較差、適合下游微調而非直接對話。</p>
]]></content:encoded></item><item><title>KV Cache</title><link>https://tarrragon.github.io/blog/llm/knowledge-cards/kv-cache/</link><pubDate>Mon, 11 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/llm/knowledge-cards/kv-cache/</guid><description>&lt;p>KV Cache 的核心概念是「LLM 推論過程中、把已處理過的 &lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/token/" data-link-title="Token" data-link-desc="LLM 處理文字時的最小單位：介於字元與單字之間">token&lt;/a> 的 attention key / value 暫存起來、後續 token 生成時直接讀」。它讓「已 &lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/prefill/" data-link-title="Prefill" data-link-desc="Prompt 首次處理時的計算階段：把整段輸入跑過模型、產生 KV cache">prefill&lt;/a> 過的 prompt」省下重複計算，是 &lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/autoregressive/" data-link-title="Autoregressive" data-link-desc="LLM 一次生成一個 token、把已生成內容作為下一次輸入的架構">autoregressive&lt;/a> 模型能跑得起來的關鍵優化。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>KV cache 存在於記憶體中，大小跟 prompt 長度線性增加。它跟模型權重一起佔用記憶體預算；長 &lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/context-window/" data-link-title="Context Window" data-link-desc="模型一次能處理的最大 token 數量：prompt 加生成的總和上限">context window&lt;/a> 場景的 KV cache 可能比模型權重本身還大。&lt;/p>
&lt;h2 id="可觀察訊號與例子">可觀察訊號與例子&lt;/h2>
&lt;p>Gemma 4 31B（Q4 量化）的 KV cache 估算：&lt;/p>
&lt;table>
 &lt;thead>
 &lt;tr>
 &lt;th>Context 長度&lt;/th>
 &lt;th>KV Cache 估算&lt;/th>
 &lt;th>加上模型權重總和&lt;/th>
 &lt;/tr>
 &lt;/thead>
 &lt;tbody>
 &lt;tr>
 &lt;td>1K tokens&lt;/td>
 &lt;td>~0.5 GB&lt;/td>
 &lt;td>18.5 GB&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>4K tokens&lt;/td>
 &lt;td>~2 GB&lt;/td>
 &lt;td>20 GB&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>16K tokens&lt;/td>
 &lt;td>~8 GB&lt;/td>
 &lt;td>26 GB&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>32K tokens&lt;/td>
 &lt;td>~16 GB&lt;/td>
 &lt;td>34 GB（32GB Mac 開始 swap）&lt;/td>
 &lt;/tr>
 &lt;/tbody>
&lt;/table>
&lt;p>32GB Mac 跑 31B 模型實際可用 context 大約 8 ~ 16K tokens；超過就需要 swap、速度崩潰。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>理解 KV cache 後可以解釋兩個現象：為何長 context 不只 TTFT 高、還會吃爆記憶體；為何 oMLX 的「paged SSD KV cache」對 coding agent 場景很有用（把 cache 推到 SSD，跨 session 復用同前綴的 prefill 結果）。設定本地伺服器時，留意 context 長度與記憶體預算的乘積、避免無意間踩到 swap。&lt;/p></description><content:encoded><![CDATA[<p>KV Cache 的核心概念是「LLM 推論過程中、把已處理過的 <a href="/blog/llm/knowledge-cards/token/" data-link-title="Token" data-link-desc="LLM 處理文字時的最小單位：介於字元與單字之間">token</a> 的 attention key / value 暫存起來、後續 token 生成時直接讀」。它讓「已 <a href="/blog/llm/knowledge-cards/prefill/" data-link-title="Prefill" data-link-desc="Prompt 首次處理時的計算階段：把整段輸入跑過模型、產生 KV cache">prefill</a> 過的 prompt」省下重複計算，是 <a href="/blog/llm/knowledge-cards/autoregressive/" data-link-title="Autoregressive" data-link-desc="LLM 一次生成一個 token、把已生成內容作為下一次輸入的架構">autoregressive</a> 模型能跑得起來的關鍵優化。</p>
<h2 id="概念位置">概念位置</h2>
<p>KV cache 存在於記憶體中，大小跟 prompt 長度線性增加。它跟模型權重一起佔用記憶體預算；長 <a href="/blog/llm/knowledge-cards/context-window/" data-link-title="Context Window" data-link-desc="模型一次能處理的最大 token 數量：prompt 加生成的總和上限">context window</a> 場景的 KV cache 可能比模型權重本身還大。</p>
<h2 id="可觀察訊號與例子">可觀察訊號與例子</h2>
<p>Gemma 4 31B（Q4 量化）的 KV cache 估算：</p>
<table>
  <thead>
      <tr>
          <th>Context 長度</th>
          <th>KV Cache 估算</th>
          <th>加上模型權重總和</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>1K tokens</td>
          <td>~0.5 GB</td>
          <td>18.5 GB</td>
      </tr>
      <tr>
          <td>4K tokens</td>
          <td>~2 GB</td>
          <td>20 GB</td>
      </tr>
      <tr>
          <td>16K tokens</td>
          <td>~8 GB</td>
          <td>26 GB</td>
      </tr>
      <tr>
          <td>32K tokens</td>
          <td>~16 GB</td>
          <td>34 GB（32GB Mac 開始 swap）</td>
      </tr>
  </tbody>
</table>
<p>32GB Mac 跑 31B 模型實際可用 context 大約 8 ~ 16K tokens；超過就需要 swap、速度崩潰。</p>
<h2 id="設計責任">設計責任</h2>
<p>理解 KV cache 後可以解釋兩個現象：為何長 context 不只 TTFT 高、還會吃爆記憶體；為何 oMLX 的「paged SSD KV cache」對 coding agent 場景很有用（把 cache 推到 SSD，跨 session 復用同前綴的 prefill 結果）。設定本地伺服器時，留意 context 長度與記憶體預算的乘積、避免無意間踩到 swap。</p>
]]></content:encoded></item><item><title>LLM Agent</title><link>https://tarrragon.github.io/blog/llm/knowledge-cards/agent/</link><pubDate>Mon, 11 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/llm/knowledge-cards/agent/</guid><description>&lt;p>LLM Agent 的核心概念是「把控制流的所有權從人類交給 LLM」。傳統對話 LLM 是「人類問、模型答」、每輪 turn 獨立；agent 是「LLM 自己決定下一步、自己呼叫工具、自己評估結果」、跨多步累積 context。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>Agent 是應用層的工作流模式、建立在 &lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/tool-use/" data-link-title="Tool Use" data-link-desc="LLM 透過結構化呼叫外部工具（讀檔、查資料庫、發 API request）來擴展能力的設計、function calling 跟 MCP 是常見實作">tool use&lt;/a>、&lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/function-calling/" data-link-title="Function Calling" data-link-desc="模型訓練階段建立的「呼叫工具」能力：知道何時該呼叫、傳什麼參數">function calling&lt;/a>、&lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/structured-output/" data-link-title="Structured Output" data-link-desc="讓 LLM 輸出可被 parser 穩定消費的推論階段設計：JSON mode、schema-guided decoding、grammar 約束都屬於這一層">structured output&lt;/a>、&lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/autoregressive/" data-link-title="Autoregressive" data-link-desc="LLM 一次生成一個 token、把已生成內容作為下一次輸入的架構">autoregressive&lt;/a> 生成之上。Agent loop 五步骨架（感知 → 推理 → 行動 → 觀察 → 判斷終止）是所有 agent framework 的共通結構、不論具體實作。本地 LLM 受 tool use 訓練不足、長 context prefill 痛點（見 &lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/ttft/" data-link-title="TTFT" data-link-desc="Time To First Token：送出 prompt 到第一個 token 出現的等待時間">TTFT&lt;/a>、&lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/prefill/" data-link-title="Prefill" data-link-desc="Prompt 首次處理時的計算階段：把整段輸入跑過模型、產生 KV cache">prefill&lt;/a>）、規劃能力弱等限制、跑 agent 現階段失敗率高於雲端旗艦。&lt;/p>
&lt;h2 id="可觀察訊號與例子">可觀察訊號與例子&lt;/h2>
&lt;p>寫 code 場景的代表 agent：aider、Cline、Cursor Agent。判讀 agent 失敗訊號分三類：&lt;strong>context drift&lt;/strong>（累積偏離原目標）、&lt;strong>目標漂移&lt;/strong>（子目標完成就停、原任務沒完成）、&lt;strong>tool 結果誤判&lt;/strong>（tool 回 error 模型 hallucinate「成功」繼續推）。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>決定該用 agent 還是 single-call、看任務是否有明確子步驟 + 客觀驗證訊號（test 通過、file 寫入）。模糊探索性任務不適合 agent。Agent 跑高風險任務時、人類審查粒度應該配合工具的副作用範圍——可逆任務全自動、不可逆任務 step-by-step approval。詳細展開見 &lt;a href="https://tarrragon.github.io/blog/llm/04-applications/agent-architecture/" data-link-title="4.4 Agent 架構原理" data-link-desc="Agent loop 結構、失敗模式、什麼任務適合 vs 不適合、跟人類審查的協作模型">4.4 Agent 架構原理&lt;/a>。&lt;/p></description><content:encoded><![CDATA[<p>LLM Agent 的核心概念是「把控制流的所有權從人類交給 LLM」。傳統對話 LLM 是「人類問、模型答」、每輪 turn 獨立；agent 是「LLM 自己決定下一步、自己呼叫工具、自己評估結果」、跨多步累積 context。</p>
<h2 id="概念位置">概念位置</h2>
<p>Agent 是應用層的工作流模式、建立在 <a href="/blog/llm/knowledge-cards/tool-use/" data-link-title="Tool Use" data-link-desc="LLM 透過結構化呼叫外部工具（讀檔、查資料庫、發 API request）來擴展能力的設計、function calling 跟 MCP 是常見實作">tool use</a>、<a href="/blog/llm/knowledge-cards/function-calling/" data-link-title="Function Calling" data-link-desc="模型訓練階段建立的「呼叫工具」能力：知道何時該呼叫、傳什麼參數">function calling</a>、<a href="/blog/llm/knowledge-cards/structured-output/" data-link-title="Structured Output" data-link-desc="讓 LLM 輸出可被 parser 穩定消費的推論階段設計：JSON mode、schema-guided decoding、grammar 約束都屬於這一層">structured output</a>、<a href="/blog/llm/knowledge-cards/autoregressive/" data-link-title="Autoregressive" data-link-desc="LLM 一次生成一個 token、把已生成內容作為下一次輸入的架構">autoregressive</a> 生成之上。Agent loop 五步骨架（感知 → 推理 → 行動 → 觀察 → 判斷終止）是所有 agent framework 的共通結構、不論具體實作。本地 LLM 受 tool use 訓練不足、長 context prefill 痛點（見 <a href="/blog/llm/knowledge-cards/ttft/" data-link-title="TTFT" data-link-desc="Time To First Token：送出 prompt 到第一個 token 出現的等待時間">TTFT</a>、<a href="/blog/llm/knowledge-cards/prefill/" data-link-title="Prefill" data-link-desc="Prompt 首次處理時的計算階段：把整段輸入跑過模型、產生 KV cache">prefill</a>）、規劃能力弱等限制、跑 agent 現階段失敗率高於雲端旗艦。</p>
<h2 id="可觀察訊號與例子">可觀察訊號與例子</h2>
<p>寫 code 場景的代表 agent：aider、Cline、Cursor Agent。判讀 agent 失敗訊號分三類：<strong>context drift</strong>（累積偏離原目標）、<strong>目標漂移</strong>（子目標完成就停、原任務沒完成）、<strong>tool 結果誤判</strong>（tool 回 error 模型 hallucinate「成功」繼續推）。</p>
<h2 id="設計責任">設計責任</h2>
<p>決定該用 agent 還是 single-call、看任務是否有明確子步驟 + 客觀驗證訊號（test 通過、file 寫入）。模糊探索性任務不適合 agent。Agent 跑高風險任務時、人類審查粒度應該配合工具的副作用範圍——可逆任務全自動、不可逆任務 step-by-step approval。詳細展開見 <a href="/blog/llm/04-applications/agent-architecture/" data-link-title="4.4 Agent 架構原理" data-link-desc="Agent loop 結構、失敗模式、什麼任務適合 vs 不適合、跟人類審查的協作模型">4.4 Agent 架構原理</a>。</p>
]]></content:encoded></item><item><title>MCP（Model Context Protocol）</title><link>https://tarrragon.github.io/blog/llm/knowledge-cards/mcp/</link><pubDate>Mon, 11 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/llm/knowledge-cards/mcp/</guid><description>&lt;p>MCP（Model Context Protocol、2024 年由 Anthropic 提出）的核心概念是「LLM application 跟外部 tool server 之間的標準化協議」。它解的是 LLM application 生態的 N×M 整合問題：N 個 application 接 M 個 tool、不標準化要寫 N×M 個 adapter；MCP 把這個成本拆成 N+M（application 端跟 server 端各實作協議一次）。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>MCP 在&lt;strong>架構協議&lt;/strong>層、跟 &lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/function-calling/" data-link-title="Function Calling" data-link-desc="模型訓練階段建立的「呼叫工具」能力：知道何時該呼叫、傳什麼參數">function calling&lt;/a>（模型能力層）、&lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/structured-output/" data-link-title="Structured Output" data-link-desc="讓 LLM 輸出可被 parser 穩定消費的推論階段設計：JSON mode、schema-guided decoding、grammar 約束都屬於這一層">structured output&lt;/a>（&lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/sampling-constraint/" data-link-title="Sampling Constraint" data-link-desc="推論時限制下一個 token 候選集合的控制手段，用來把模型生成導向合法格式或特定選項">sampling 約束&lt;/a>層）正交。它跟模型怎麼呼叫工具無關、只管「工具怎麼被暴露給 application」。複用 &lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/openai-compatible-api/" data-link-title="OpenAI 相容 API" data-link-desc="本地推論伺服器跟雲端 OpenAI 共用的 API 形狀標準">OpenAI 相容 API&lt;/a> 的標準化模式：定義最小可用標準、讓生態繞著標準長、所有 player 受益。&lt;/p>
&lt;h2 id="可觀察訊號與例子">可觀察訊號與例子&lt;/h2>
&lt;p>MCP 涵蓋 server 該提供什麼：tool 註冊、tool schema、tool 呼叫協議、resource 暴露、prompt template 共享。2026/5 主要 LLM application（Claude Desktop、Cursor 等）支援 MCP；社群維護的 MCP server 數量快速增長（檔案系統、Git、Slack、各種 API 等）；本地推論伺服器（Ollama、LM Studio）仍以 &lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/openai-compatible-api/" data-link-title="OpenAI 相容 API" data-link-desc="本地推論伺服器跟雲端 OpenAI 共用的 API 形狀標準">OpenAI 相容 API&lt;/a> 為主、MCP 接入較慢。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>需不需要用 MCP 看應用規模：小型 in-process 應用（直接 Python function）用 function calling + 簡單 dispatcher 就夠、不需 MCP。要跨 application 共用 tool、或想接入既有 MCP server 生態（如標準化的 git / filesystem tools）才需要 MCP。詳細展開見 &lt;a href="https://tarrragon.github.io/blog/llm/04-applications/application-protocols/" data-link-title="4.6 應用層協議：function calling / structured output / MCP" data-link-desc="三個常被混為一談的概念：模型能力、sampling 約束、server 協議，三者的層級差異與組合方式">4.6 應用層協議&lt;/a>。&lt;/p></description><content:encoded><![CDATA[<p>MCP（Model Context Protocol、2024 年由 Anthropic 提出）的核心概念是「LLM application 跟外部 tool server 之間的標準化協議」。它解的是 LLM application 生態的 N×M 整合問題：N 個 application 接 M 個 tool、不標準化要寫 N×M 個 adapter；MCP 把這個成本拆成 N+M（application 端跟 server 端各實作協議一次）。</p>
<h2 id="概念位置">概念位置</h2>
<p>MCP 在<strong>架構協議</strong>層、跟 <a href="/blog/llm/knowledge-cards/function-calling/" data-link-title="Function Calling" data-link-desc="模型訓練階段建立的「呼叫工具」能力：知道何時該呼叫、傳什麼參數">function calling</a>（模型能力層）、<a href="/blog/llm/knowledge-cards/structured-output/" data-link-title="Structured Output" data-link-desc="讓 LLM 輸出可被 parser 穩定消費的推論階段設計：JSON mode、schema-guided decoding、grammar 約束都屬於這一層">structured output</a>（<a href="/blog/llm/knowledge-cards/sampling-constraint/" data-link-title="Sampling Constraint" data-link-desc="推論時限制下一個 token 候選集合的控制手段，用來把模型生成導向合法格式或特定選項">sampling 約束</a>層）正交。它跟模型怎麼呼叫工具無關、只管「工具怎麼被暴露給 application」。複用 <a href="/blog/llm/knowledge-cards/openai-compatible-api/" data-link-title="OpenAI 相容 API" data-link-desc="本地推論伺服器跟雲端 OpenAI 共用的 API 形狀標準">OpenAI 相容 API</a> 的標準化模式：定義最小可用標準、讓生態繞著標準長、所有 player 受益。</p>
<h2 id="可觀察訊號與例子">可觀察訊號與例子</h2>
<p>MCP 涵蓋 server 該提供什麼：tool 註冊、tool schema、tool 呼叫協議、resource 暴露、prompt template 共享。2026/5 主要 LLM application（Claude Desktop、Cursor 等）支援 MCP；社群維護的 MCP server 數量快速增長（檔案系統、Git、Slack、各種 API 等）；本地推論伺服器（Ollama、LM Studio）仍以 <a href="/blog/llm/knowledge-cards/openai-compatible-api/" data-link-title="OpenAI 相容 API" data-link-desc="本地推論伺服器跟雲端 OpenAI 共用的 API 形狀標準">OpenAI 相容 API</a> 為主、MCP 接入較慢。</p>
<h2 id="設計責任">設計責任</h2>
<p>需不需要用 MCP 看應用規模：小型 in-process 應用（直接 Python function）用 function calling + 簡單 dispatcher 就夠、不需 MCP。要跨 application 共用 tool、或想接入既有 MCP server 生態（如標準化的 git / filesystem tools）才需要 MCP。詳細展開見 <a href="/blog/llm/04-applications/application-protocols/" data-link-title="4.6 應用層協議：function calling / structured output / MCP" data-link-desc="三個常被混為一談的概念：模型能力、sampling 約束、server 協議，三者的層級差異與組合方式">4.6 應用層協議</a>。</p>
]]></content:encoded></item><item><title>Memory Bandwidth</title><link>https://tarrragon.github.io/blog/llm/knowledge-cards/memory-bandwidth/</link><pubDate>Mon, 11 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/llm/knowledge-cards/memory-bandwidth/</guid><description>&lt;p>Memory Bandwidth（記憶體頻寬）的核心概念是「每秒能從記憶體讀寫多少 bytes」。對 LLM 推論而言、它是「真正的瓶頸」、決定 &lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/tokens-per-second/" data-link-title="Tokens Per Second" data-link-desc="LLM 每秒能生成幾個 token：生字速度的標準量化指標">tokens per second&lt;/a> 的理論上限；CPU / GPU 算力反而很少成為瓶頸。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>&lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/autoregressive/" data-link-title="Autoregressive" data-link-desc="LLM 一次生成一個 token、把已生成內容作為下一次輸入的架構">Autoregressive&lt;/a> 模型每生一個 token 都要把整個模型權重從記憶體讀到處理器一次。模型多大、頻寬多快、決定每秒能讀過幾次完整權重、也就決定每秒生幾個 token。&lt;/p>
&lt;h2 id="可觀察訊號與例子">可觀察訊號與例子&lt;/h2>
&lt;p>各代 Apple Silicon 的記憶體頻寬：&lt;/p>
&lt;table>
 &lt;thead>
 &lt;tr>
 &lt;th>晶片&lt;/th>
 &lt;th>頻寬&lt;/th>
 &lt;/tr>
 &lt;/thead>
 &lt;tbody>
 &lt;tr>
 &lt;td>M2 / M3&lt;/td>
 &lt;td>100 GB/s&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>M2 Pro&lt;/td>
 &lt;td>200 GB/s&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>M4 Max&lt;/td>
 &lt;td>546 GB/s&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>M2 / M3 Ultra&lt;/td>
 &lt;td>800+ GB/s&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>H100（雲端）&lt;/td>
 &lt;td>3,300 GB/s&lt;/td>
 &lt;/tr>
 &lt;/tbody>
&lt;/table>
&lt;p>理論上限算式：&lt;code>頻寬 / 模型大小 = 最大 tok/s&lt;/code>。M4 Max 跑 Q4 量化的 31B 模型（約 18GB）、理論上限約 546 / 18 ≈ 30 tok/s。實際值會比理論低 30 ~ 50%（&lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/kv-cache/" data-link-title="KV Cache" data-link-desc="已處理 token 的 attention 中間結果暫存：避免重算、加速後續生成">KV cache&lt;/a> 讀寫、attention 中間結果等開銷）。&lt;/p>
&lt;p>H100 頻寬是 M4 Max 的 6 倍、這就是雲端旗艦速度比本地快這麼多的根本原因。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>評估「換更快 Mac 能加速多少」要看頻寬而不是 CPU 核心數。M2 升 M4 Max 對 LLM 推論的速度收益主要來自頻寬升級（200 → 546 GB/s）、約 2.7 倍。看到「N 倍加速」報導時、把頻寬與模型大小代進公式對一下、能識破不合理的數字。&lt;/p></description><content:encoded><![CDATA[<p>Memory Bandwidth（記憶體頻寬）的核心概念是「每秒能從記憶體讀寫多少 bytes」。對 LLM 推論而言、它是「真正的瓶頸」、決定 <a href="/blog/llm/knowledge-cards/tokens-per-second/" data-link-title="Tokens Per Second" data-link-desc="LLM 每秒能生成幾個 token：生字速度的標準量化指標">tokens per second</a> 的理論上限；CPU / GPU 算力反而很少成為瓶頸。</p>
<h2 id="概念位置">概念位置</h2>
<p><a href="/blog/llm/knowledge-cards/autoregressive/" data-link-title="Autoregressive" data-link-desc="LLM 一次生成一個 token、把已生成內容作為下一次輸入的架構">Autoregressive</a> 模型每生一個 token 都要把整個模型權重從記憶體讀到處理器一次。模型多大、頻寬多快、決定每秒能讀過幾次完整權重、也就決定每秒生幾個 token。</p>
<h2 id="可觀察訊號與例子">可觀察訊號與例子</h2>
<p>各代 Apple Silicon 的記憶體頻寬：</p>
<table>
  <thead>
      <tr>
          <th>晶片</th>
          <th>頻寬</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>M2 / M3</td>
          <td>100 GB/s</td>
      </tr>
      <tr>
          <td>M2 Pro</td>
          <td>200 GB/s</td>
      </tr>
      <tr>
          <td>M4 Max</td>
          <td>546 GB/s</td>
      </tr>
      <tr>
          <td>M2 / M3 Ultra</td>
          <td>800+ GB/s</td>
      </tr>
      <tr>
          <td>H100（雲端）</td>
          <td>3,300 GB/s</td>
      </tr>
  </tbody>
</table>
<p>理論上限算式：<code>頻寬 / 模型大小 = 最大 tok/s</code>。M4 Max 跑 Q4 量化的 31B 模型（約 18GB）、理論上限約 546 / 18 ≈ 30 tok/s。實際值會比理論低 30 ~ 50%（<a href="/blog/llm/knowledge-cards/kv-cache/" data-link-title="KV Cache" data-link-desc="已處理 token 的 attention 中間結果暫存：避免重算、加速後續生成">KV cache</a> 讀寫、attention 中間結果等開銷）。</p>
<p>H100 頻寬是 M4 Max 的 6 倍、這就是雲端旗艦速度比本地快這麼多的根本原因。</p>
<h2 id="設計責任">設計責任</h2>
<p>評估「換更快 Mac 能加速多少」要看頻寬而不是 CPU 核心數。M2 升 M4 Max 對 LLM 推論的速度收益主要來自頻寬升級（200 → 546 GB/s）、約 2.7 倍。看到「N 倍加速」報導時、把頻寬與模型大小代進公式對一下、能識破不合理的數字。</p>
]]></content:encoded></item><item><title>MLX</title><link>https://tarrragon.github.io/blog/llm/knowledge-cards/mlx/</link><pubDate>Mon, 11 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/llm/knowledge-cards/mlx/</guid><description>&lt;p>MLX（Machine Learning eXchange）的核心概念是「Apple 為 Apple Silicon 設計的數值運算 framework」，2023 年由 Apple 釋出。它提供 Python API、自動排程 CPU / GPU / Neural Engine、利用&lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/unified-memory/" data-link-title="Unified Memory Architecture" data-link-desc="Apple Silicon 讓 CPU / GPU / NE 共用同一塊記憶體：跑大模型的優勢來源">統一記憶體架構&lt;/a>避免在不同記憶體層之間搬資料。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>MLX 屬於基底設施層、跟 PyTorch、JAX、NumPy 並列、是「跑神經網路用的底層數值庫」。它本身不是&lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/inference-server/" data-link-title="Inference Server" data-link-desc="載入模型權重、處理 prompt、產生 token 的常駐 process">推論伺服器&lt;/a>、不是模型、也不是加速技巧；上層工具站在 MLX 這塊地基上做封裝。&lt;/p>
&lt;table>
 &lt;thead>
 &lt;tr>
 &lt;th>通用世界&lt;/th>
 &lt;th>Apple 世界&lt;/th>
 &lt;/tr>
 &lt;/thead>
 &lt;tbody>
 &lt;tr>
 &lt;td>PyTorch / JAX&lt;/td>
 &lt;td>MLX&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>CUDA&lt;/td>
 &lt;td>Metal（MLX 在 GPU 上經 Metal）&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>NumPy&lt;/td>
 &lt;td>&lt;code>mlx.core&lt;/code>&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>Transformers&lt;/td>
 &lt;td>&lt;code>mlx-lm&lt;/code>、&lt;code>mlx-community&lt;/code>&lt;/td>
 &lt;/tr>
 &lt;/tbody>
&lt;/table>
&lt;h2 id="可觀察訊號與例子">可觀察訊號與例子&lt;/h2>
&lt;p>直接用 MLX 跑模型：&lt;/p>





&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-bash" data-lang="bash">&lt;span class="line">&lt;span class="ln">1&lt;/span>&lt;span class="cl">pip install mlx-lm
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">2&lt;/span>&lt;span class="cl">mlx_lm.generate --model mlx-community/Llama-3.2-3B-Instruct-4bit --prompt &lt;span class="s2">&amp;#34;hi&amp;#34;&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>這段命令會載入 MLX format 權重、用 MLX framework 在 Apple Silicon 上跑推論。需要再 wrap 成 HTTP server 才能讓 IDE 連、&lt;code>mlx_lm.server&lt;/code> 是輕量選擇、oMLX 是建在 MLX 之上的完整推論伺服器。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>寫 code 場景的多數使用者透過 Ollama（用 llama.cpp 當引擎、跟 MLX 無關）、體驗已足夠。直接用 MLX 適合三種情境：想跑 Apple 釋出的 MLX format 模型、想用 MLX 寫研究 code、想試 MLX backend 的推論伺服器（oMLX）。看到「Ollama 用 MLX 加速」這類說法時、回到本卡確認 Ollama 內部 backend 是 llama.cpp 而非 MLX。&lt;/p></description><content:encoded><![CDATA[<p>MLX（Machine Learning eXchange）的核心概念是「Apple 為 Apple Silicon 設計的數值運算 framework」，2023 年由 Apple 釋出。它提供 Python API、自動排程 CPU / GPU / Neural Engine、利用<a href="/blog/llm/knowledge-cards/unified-memory/" data-link-title="Unified Memory Architecture" data-link-desc="Apple Silicon 讓 CPU / GPU / NE 共用同一塊記憶體：跑大模型的優勢來源">統一記憶體架構</a>避免在不同記憶體層之間搬資料。</p>
<h2 id="概念位置">概念位置</h2>
<p>MLX 屬於基底設施層、跟 PyTorch、JAX、NumPy 並列、是「跑神經網路用的底層數值庫」。它本身不是<a href="/blog/llm/knowledge-cards/inference-server/" data-link-title="Inference Server" data-link-desc="載入模型權重、處理 prompt、產生 token 的常駐 process">推論伺服器</a>、不是模型、也不是加速技巧；上層工具站在 MLX 這塊地基上做封裝。</p>
<table>
  <thead>
      <tr>
          <th>通用世界</th>
          <th>Apple 世界</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>PyTorch / JAX</td>
          <td>MLX</td>
      </tr>
      <tr>
          <td>CUDA</td>
          <td>Metal（MLX 在 GPU 上經 Metal）</td>
      </tr>
      <tr>
          <td>NumPy</td>
          <td><code>mlx.core</code></td>
      </tr>
      <tr>
          <td>Transformers</td>
          <td><code>mlx-lm</code>、<code>mlx-community</code></td>
      </tr>
  </tbody>
</table>
<h2 id="可觀察訊號與例子">可觀察訊號與例子</h2>
<p>直接用 MLX 跑模型：</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="ln">1</span><span class="cl">pip install mlx-lm
</span></span><span class="line"><span class="ln">2</span><span class="cl">mlx_lm.generate --model mlx-community/Llama-3.2-3B-Instruct-4bit --prompt <span class="s2">&#34;hi&#34;</span></span></span></code></pre></div><p>這段命令會載入 MLX format 權重、用 MLX framework 在 Apple Silicon 上跑推論。需要再 wrap 成 HTTP server 才能讓 IDE 連、<code>mlx_lm.server</code> 是輕量選擇、oMLX 是建在 MLX 之上的完整推論伺服器。</p>
<h2 id="設計責任">設計責任</h2>
<p>寫 code 場景的多數使用者透過 Ollama（用 llama.cpp 當引擎、跟 MLX 無關）、體驗已足夠。直接用 MLX 適合三種情境：想跑 Apple 釋出的 MLX format 模型、想用 MLX 寫研究 code、想試 MLX backend 的推論伺服器（oMLX）。看到「Ollama 用 MLX 加速」這類說法時、回到本卡確認 Ollama 內部 backend 是 llama.cpp 而非 MLX。</p>
]]></content:encoded></item><item><title>Multi-Token Prediction (MTP)</title><link>https://tarrragon.github.io/blog/llm/knowledge-cards/mtp/</link><pubDate>Mon, 11 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/llm/knowledge-cards/mtp/</guid><description>&lt;p>Multi-Token Prediction（MTP）的核心概念是「&lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/speculative-decoding/" data-link-title="Speculative Decoding" data-link-desc="用小模型猜未來 token、大模型並行驗證的加速技巧">speculative decoding&lt;/a> 的工程化實作」，特指 Google 為 Gemma 4 釋出的官方版本。它包含預訓練好的 &lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/drafter-model/" data-link-title="Drafter Model" data-link-desc="speculative decoding 中用來快速猜未來 token 的小模型">drafter&lt;/a>、target 模型整合、以及優化過的推論流程。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>MTP 屬於模型推論優化層、跟 &lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/autoregressive/" data-link-title="Autoregressive" data-link-desc="LLM 一次生成一個 token、把已生成內容作為下一次輸入的架構">autoregressive&lt;/a> 基底並列。它是技巧、不是模型架構、也不是 framework；任何推論伺服器都可以選擇實作或忽略 MTP、模型可以選擇有沒有官方 drafter。三件事彼此獨立。&lt;/p>
&lt;h2 id="可觀察訊號與例子">可觀察訊號與例子&lt;/h2>
&lt;p>2026 年 5 月 MTP 在各推論伺服器的支援狀態：&lt;/p>
&lt;table>
 &lt;thead>
 &lt;tr>
 &lt;th>伺服器&lt;/th>
 &lt;th>Gemma 4 MTP 支援&lt;/th>
 &lt;/tr>
 &lt;/thead>
 &lt;tbody>
 &lt;tr>
 &lt;td>Ollama&lt;/td>
 &lt;td>v0.23.1（2026/5/7）一鍵支援&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>LM Studio&lt;/td>
 &lt;td>支援、需手動配置 draft model&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>llama.cpp&lt;/td>
 &lt;td>speculative decoding 框架在 beta、Gemma 4 官方 drafter 整合仍是 feature request&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>oMLX&lt;/td>
 &lt;td>支援&lt;/td>
 &lt;/tr>
 &lt;/tbody>
&lt;/table>
&lt;p>啟用 MTP 的速度收益主要在寫 code 場景。Google 官方數據 coding 任務 2 ~ 3 倍加速；純文字寫作、創意任務的加速幅度約 1.5 ~ 2 倍、因為 pattern 預測度較低。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>寫 code 場景的多數使用者透過 Ollama 一行啟用 MTP：&lt;code>ollama run gemma4:31b-coding-mtp-bf16&lt;/code>。看到「N 倍加速」報導時要追問來源與任務：官方 Google 數據是 2 ~ 3 倍；「40%」這類數字常常來源不明、可能是社群文章作者的估算。判讀加速幅度時、回到&lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/mtp/" data-link-title="Multi-Token Prediction (MTP)" data-link-desc="Google 為 Gemma 系列釋出的 speculative decoding 工程化實作">本卡&lt;/a> 與 &lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/speculative-decoding/" data-link-title="Speculative Decoding" data-link-desc="用小模型猜未來 token、大模型並行驗證的加速技巧">speculative decoding&lt;/a> 的官方來源比對。&lt;/p></description><content:encoded><![CDATA[<p>Multi-Token Prediction（MTP）的核心概念是「<a href="/blog/llm/knowledge-cards/speculative-decoding/" data-link-title="Speculative Decoding" data-link-desc="用小模型猜未來 token、大模型並行驗證的加速技巧">speculative decoding</a> 的工程化實作」，特指 Google 為 Gemma 4 釋出的官方版本。它包含預訓練好的 <a href="/blog/llm/knowledge-cards/drafter-model/" data-link-title="Drafter Model" data-link-desc="speculative decoding 中用來快速猜未來 token 的小模型">drafter</a>、target 模型整合、以及優化過的推論流程。</p>
<h2 id="概念位置">概念位置</h2>
<p>MTP 屬於模型推論優化層、跟 <a href="/blog/llm/knowledge-cards/autoregressive/" data-link-title="Autoregressive" data-link-desc="LLM 一次生成一個 token、把已生成內容作為下一次輸入的架構">autoregressive</a> 基底並列。它是技巧、不是模型架構、也不是 framework；任何推論伺服器都可以選擇實作或忽略 MTP、模型可以選擇有沒有官方 drafter。三件事彼此獨立。</p>
<h2 id="可觀察訊號與例子">可觀察訊號與例子</h2>
<p>2026 年 5 月 MTP 在各推論伺服器的支援狀態：</p>
<table>
  <thead>
      <tr>
          <th>伺服器</th>
          <th>Gemma 4 MTP 支援</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>Ollama</td>
          <td>v0.23.1（2026/5/7）一鍵支援</td>
      </tr>
      <tr>
          <td>LM Studio</td>
          <td>支援、需手動配置 draft model</td>
      </tr>
      <tr>
          <td>llama.cpp</td>
          <td>speculative decoding 框架在 beta、Gemma 4 官方 drafter 整合仍是 feature request</td>
      </tr>
      <tr>
          <td>oMLX</td>
          <td>支援</td>
      </tr>
  </tbody>
</table>
<p>啟用 MTP 的速度收益主要在寫 code 場景。Google 官方數據 coding 任務 2 ~ 3 倍加速；純文字寫作、創意任務的加速幅度約 1.5 ~ 2 倍、因為 pattern 預測度較低。</p>
<h2 id="設計責任">設計責任</h2>
<p>寫 code 場景的多數使用者透過 Ollama 一行啟用 MTP：<code>ollama run gemma4:31b-coding-mtp-bf16</code>。看到「N 倍加速」報導時要追問來源與任務：官方 Google 數據是 2 ~ 3 倍；「40%」這類數字常常來源不明、可能是社群文章作者的估算。判讀加速幅度時、回到<a href="/blog/llm/knowledge-cards/mtp/" data-link-title="Multi-Token Prediction (MTP)" data-link-desc="Google 為 Gemma 系列釋出的 speculative decoding 工程化實作">本卡</a> 與 <a href="/blog/llm/knowledge-cards/speculative-decoding/" data-link-title="Speculative Decoding" data-link-desc="用小模型猜未來 token、大模型並行驗證的加速技巧">speculative decoding</a> 的官方來源比對。</p>
]]></content:encoded></item><item><title>OpenAI 相容 API</title><link>https://tarrragon.github.io/blog/llm/knowledge-cards/openai-compatible-api/</link><pubDate>Mon, 11 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/llm/knowledge-cards/openai-compatible-api/</guid><description>&lt;p>OpenAI 相容 API 的核心概念是「實作 OpenAI 在 2023 年定義的 &lt;code>POST /v1/chat/completions&lt;/code> 介面、讓介面層工具不改一行 code 就能切換本地與雲端」。它是事實標準、後來幾乎所有本地&lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/inference-server/" data-link-title="Inference Server" data-link-desc="載入模型權重、處理 prompt、產生 token 的常駐 process">推論伺服器&lt;/a>都實作這份規格。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>OpenAI 相容 API 是介面層與伺服器層之間的標準介面。它承諾 API 形狀（request / response schema、streaming 格式、錯誤碼）一致；對「模型能力」「效能特性」「進階參數」等不承諾等價。本地 Gemma 4 跟雲端 GPT-5 都能用同一套 API 呼叫、但回答品質天差地遠。&lt;/p>
&lt;h2 id="可觀察訊號與例子">可觀察訊號與例子&lt;/h2>
&lt;p>最小可用請求：&lt;/p>





&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-bash" data-lang="bash">&lt;span class="line">&lt;span class="ln">1&lt;/span>&lt;span class="cl">curl http://localhost:11434/v1/chat/completions &lt;span class="se">\
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">2&lt;/span>&lt;span class="cl">&lt;span class="se">&lt;/span> -H &lt;span class="s2">&amp;#34;Content-Type: application/json&amp;#34;&lt;/span> &lt;span class="se">\
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">3&lt;/span>&lt;span class="cl">&lt;span class="se">&lt;/span> -d &lt;span class="s1">&amp;#39;{
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">4&lt;/span>&lt;span class="cl">&lt;span class="s1"> &amp;#34;model&amp;#34;: &amp;#34;gemma4:31b-coding-mtp-bf16&amp;#34;,
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">5&lt;/span>&lt;span class="cl">&lt;span class="s1"> &amp;#34;messages&amp;#34;: [{&amp;#34;role&amp;#34;: &amp;#34;user&amp;#34;, &amp;#34;content&amp;#34;: &amp;#34;Hello&amp;#34;}],
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">6&lt;/span>&lt;span class="cl">&lt;span class="s1"> &amp;#34;stream&amp;#34;: false
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">7&lt;/span>&lt;span class="cl">&lt;span class="s1"> }&amp;#39;&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>切換本地與雲端只改三個欄位：&lt;/p>
&lt;table>
 &lt;thead>
 &lt;tr>
 &lt;th>欄位&lt;/th>
 &lt;th>雲端 OpenAI&lt;/th>
 &lt;th>本地 Ollama&lt;/th>
 &lt;/tr>
 &lt;/thead>
 &lt;tbody>
 &lt;tr>
 &lt;td>API base&lt;/td>
 &lt;td>&lt;code>https://api.openai.com/v1&lt;/code>&lt;/td>
 &lt;td>&lt;code>http://localhost:11434/v1&lt;/code>&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>API key&lt;/td>
 &lt;td>&lt;code>sk-xxxxxxx&lt;/code>&lt;/td>
 &lt;td>任意字串、本地多半略過驗證&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>Model name&lt;/td>
 &lt;td>&lt;code>gpt-5&lt;/code>&lt;/td>
 &lt;td>本地 model tag&lt;/td>
 &lt;/tr>
 &lt;/tbody>
&lt;/table>
&lt;p>進階功能參差不齊：&lt;code>response_format&lt;/code>、&lt;code>tool_choice&lt;/code>、reasoning effort 等在本地伺服器的支援度視模型而定；雲端有的功能、本地未必能用。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>寫程式接 LLM 時、把 OpenAI 相容當預設選擇。多家 SDK（OpenAI Python SDK、Vercel AI SDK 等）都支援設定 &lt;code>base_url&lt;/code>、改 endpoint 就能接本地。寫 IDE plugin 或 CLI 工具時、優先支援這份 API、能同時跟雲端、Ollama、LM Studio、llama.cpp、oMLX 對接。&lt;/p></description><content:encoded><![CDATA[<p>OpenAI 相容 API 的核心概念是「實作 OpenAI 在 2023 年定義的 <code>POST /v1/chat/completions</code> 介面、讓介面層工具不改一行 code 就能切換本地與雲端」。它是事實標準、後來幾乎所有本地<a href="/blog/llm/knowledge-cards/inference-server/" data-link-title="Inference Server" data-link-desc="載入模型權重、處理 prompt、產生 token 的常駐 process">推論伺服器</a>都實作這份規格。</p>
<h2 id="概念位置">概念位置</h2>
<p>OpenAI 相容 API 是介面層與伺服器層之間的標準介面。它承諾 API 形狀（request / response schema、streaming 格式、錯誤碼）一致；對「模型能力」「效能特性」「進階參數」等不承諾等價。本地 Gemma 4 跟雲端 GPT-5 都能用同一套 API 呼叫、但回答品質天差地遠。</p>
<h2 id="可觀察訊號與例子">可觀察訊號與例子</h2>
<p>最小可用請求：</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="ln">1</span><span class="cl">curl http://localhost:11434/v1/chat/completions <span class="se">\
</span></span></span><span class="line"><span class="ln">2</span><span class="cl"><span class="se"></span>  -H <span class="s2">&#34;Content-Type: application/json&#34;</span> <span class="se">\
</span></span></span><span class="line"><span class="ln">3</span><span class="cl"><span class="se"></span>  -d <span class="s1">&#39;{
</span></span></span><span class="line"><span class="ln">4</span><span class="cl"><span class="s1">    &#34;model&#34;: &#34;gemma4:31b-coding-mtp-bf16&#34;,
</span></span></span><span class="line"><span class="ln">5</span><span class="cl"><span class="s1">    &#34;messages&#34;: [{&#34;role&#34;: &#34;user&#34;, &#34;content&#34;: &#34;Hello&#34;}],
</span></span></span><span class="line"><span class="ln">6</span><span class="cl"><span class="s1">    &#34;stream&#34;: false
</span></span></span><span class="line"><span class="ln">7</span><span class="cl"><span class="s1">  }&#39;</span></span></span></code></pre></div><p>切換本地與雲端只改三個欄位：</p>
<table>
  <thead>
      <tr>
          <th>欄位</th>
          <th>雲端 OpenAI</th>
          <th>本地 Ollama</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>API base</td>
          <td><code>https://api.openai.com/v1</code></td>
          <td><code>http://localhost:11434/v1</code></td>
      </tr>
      <tr>
          <td>API key</td>
          <td><code>sk-xxxxxxx</code></td>
          <td>任意字串、本地多半略過驗證</td>
      </tr>
      <tr>
          <td>Model name</td>
          <td><code>gpt-5</code></td>
          <td>本地 model tag</td>
      </tr>
  </tbody>
</table>
<p>進階功能參差不齊：<code>response_format</code>、<code>tool_choice</code>、reasoning effort 等在本地伺服器的支援度視模型而定；雲端有的功能、本地未必能用。</p>
<h2 id="設計責任">設計責任</h2>
<p>寫程式接 LLM 時、把 OpenAI 相容當預設選擇。多家 SDK（OpenAI Python SDK、Vercel AI SDK 等）都支援設定 <code>base_url</code>、改 endpoint 就能接本地。寫 IDE plugin 或 CLI 工具時、優先支援這份 API、能同時跟雲端、Ollama、LM Studio、llama.cpp、oMLX 對接。</p>
]]></content:encoded></item><item><title>Prefill</title><link>https://tarrragon.github.io/blog/llm/knowledge-cards/prefill/</link><pubDate>Mon, 11 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/llm/knowledge-cards/prefill/</guid><description>&lt;p>Prefill 的核心概念是「&lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/autoregressive/" data-link-title="Autoregressive" data-link-desc="LLM 一次生成一個 token、把已生成內容作為下一次輸入的架構">LLM 首次處理 prompt 時、把整段輸入跑過模型一次的計算階段&lt;/a>」。Prefill 階段會為 prompt 中每個 &lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/token/" data-link-title="Token" data-link-desc="LLM 處理文字時的最小單位：介於字元與單字之間">token&lt;/a> 算出 attention 中間結果並存進 &lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/kv-cache/" data-link-title="KV Cache" data-link-desc="已處理 token 的 attention 中間結果暫存：避免重算、加速後續生成">KV cache&lt;/a>，之後生成新 token 時可以直接讀 cache。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>Prefill 是 &lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/ttft/" data-link-title="TTFT" data-link-desc="Time To First Token：送出 prompt 到第一個 token 出現的等待時間">TTFT&lt;/a> 的主要構成部分。Prefill 結束後系統進入 decode 階段、開始一個一個生 token。兩階段的瓶頸不同：prefill 是「算力 bound」（並行處理整段 prompt）、decode 是「記憶體頻寬 bound」。&lt;/p>
&lt;h2 id="可觀察訊號與例子">可觀察訊號與例子&lt;/h2>
&lt;p>短 prompt（500 tokens）：prefill 通常 &amp;lt; 1 秒、感覺不到。&lt;/p>
&lt;p>中等 prompt（4K tokens）：M4 Max 跑 31B 模型約 3 ~ 8 秒、開始有感。&lt;/p>
&lt;p>長 prompt（10K+ tokens）：本地 prefill 拉到 30 ~ 90 秒、是 coding agent 場景最痛的點。&lt;/p>
&lt;p>雲端旗艦 prefill 速度快得多，因為 H100 / TPU 的算力遠高於 Apple Silicon，且常用大批次平行 prefill。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>判讀「為何本地 LLM 在塞長 context 時這麼慢」要追到 prefill 階段。緩解方法有三條：縮短 prompt（移除不必要 context）、用支援 prefix cache 的伺服器（如 oMLX 的 paged SSD KV cache 可重用之前 prefill 過的結果）、切到雲端旗艦（資料中心 prefill 算力遠高於 Mac）。&lt;/p></description><content:encoded><![CDATA[<p>Prefill 的核心概念是「<a href="/blog/llm/knowledge-cards/autoregressive/" data-link-title="Autoregressive" data-link-desc="LLM 一次生成一個 token、把已生成內容作為下一次輸入的架構">LLM 首次處理 prompt 時、把整段輸入跑過模型一次的計算階段</a>」。Prefill 階段會為 prompt 中每個 <a href="/blog/llm/knowledge-cards/token/" data-link-title="Token" data-link-desc="LLM 處理文字時的最小單位：介於字元與單字之間">token</a> 算出 attention 中間結果並存進 <a href="/blog/llm/knowledge-cards/kv-cache/" data-link-title="KV Cache" data-link-desc="已處理 token 的 attention 中間結果暫存：避免重算、加速後續生成">KV cache</a>，之後生成新 token 時可以直接讀 cache。</p>
<h2 id="概念位置">概念位置</h2>
<p>Prefill 是 <a href="/blog/llm/knowledge-cards/ttft/" data-link-title="TTFT" data-link-desc="Time To First Token：送出 prompt 到第一個 token 出現的等待時間">TTFT</a> 的主要構成部分。Prefill 結束後系統進入 decode 階段、開始一個一個生 token。兩階段的瓶頸不同：prefill 是「算力 bound」（並行處理整段 prompt）、decode 是「記憶體頻寬 bound」。</p>
<h2 id="可觀察訊號與例子">可觀察訊號與例子</h2>
<p>短 prompt（500 tokens）：prefill 通常 &lt; 1 秒、感覺不到。</p>
<p>中等 prompt（4K tokens）：M4 Max 跑 31B 模型約 3 ~ 8 秒、開始有感。</p>
<p>長 prompt（10K+ tokens）：本地 prefill 拉到 30 ~ 90 秒、是 coding agent 場景最痛的點。</p>
<p>雲端旗艦 prefill 速度快得多，因為 H100 / TPU 的算力遠高於 Apple Silicon，且常用大批次平行 prefill。</p>
<h2 id="設計責任">設計責任</h2>
<p>判讀「為何本地 LLM 在塞長 context 時這麼慢」要追到 prefill 階段。緩解方法有三條：縮短 prompt（移除不必要 context）、用支援 prefix cache 的伺服器（如 oMLX 的 paged SSD KV cache 可重用之前 prefill 過的結果）、切到雲端旗艦（資料中心 prefill 算力遠高於 Mac）。</p>
]]></content:encoded></item><item><title>Quantization</title><link>https://tarrragon.github.io/blog/llm/knowledge-cards/quantization/</link><pubDate>Mon, 11 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/llm/knowledge-cards/quantization/</guid><description>&lt;p>Quantization（量化）的核心概念是「把模型權重從高精度（如 16-bit float）改用較低精度（如 4-bit integer）表示」。權重數量不變，但每個權重佔的 bytes 變少；模型總大小變小、每秒能讀過的權重變多，&lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/tokens-per-second/" data-link-title="Tokens Per Second" data-link-desc="LLM 每秒能生成幾個 token：生字速度的標準量化指標">生字速度&lt;/a> 直接變快。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>量化是讓 LLM 跑在 consumer 等級硬體上的關鍵技術。沒有量化、Apple Silicon Mac 跑不動 30B+ 模型，因為原始 bf16 權重會超出記憶體預算。量化方法主要分兩類：&lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/gguf/" data-link-title="GGUF" data-link-desc="llama.cpp 生態定義的模型權重格式：把權重、tokenizer、metadata 打包成單一檔案">GGUF&lt;/a> 系統用的 K-quants（Q4_K_M、Q5_K_M 等）、以及 &lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/mlx/" data-link-title="MLX" data-link-desc="Apple 釋出的 Apple Silicon 數值運算 framework：類似 PyTorch / JAX 的 Mac 對應物">MLX&lt;/a> 等系統用的 4-bit / 8-bit 量化。&lt;/p>
&lt;h2 id="可觀察訊號與例子">可觀察訊號與例子&lt;/h2>
&lt;p>常見量化等級的取捨：&lt;/p>
&lt;table>
 &lt;thead>
 &lt;tr>
 &lt;th>量化&lt;/th>
 &lt;th>每權重 bits&lt;/th>
 &lt;th>相對 bf16 大小&lt;/th>
 &lt;th>品質衰減&lt;/th>
 &lt;th>適合場景&lt;/th>
 &lt;/tr>
 &lt;/thead>
 &lt;tbody>
 &lt;tr>
 &lt;td>bf16 / F16&lt;/td>
 &lt;td>16&lt;/td>
 &lt;td>1x&lt;/td>
 &lt;td>無（基準）&lt;/td>
 &lt;td>開發、評估、大記憶體機器&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>Q8&lt;/td>
 &lt;td>8&lt;/td>
 &lt;td>0.5x&lt;/td>
 &lt;td>幾乎察覺不到&lt;/td>
 &lt;td>32GB+ Mac、品質敏感任務&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>Q5_K_M&lt;/td>
 &lt;td>5.5&lt;/td>
 &lt;td>0.34x&lt;/td>
 &lt;td>輕微&lt;/td>
 &lt;td>24GB Mac、日常使用&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>Q4_K_M&lt;/td>
 &lt;td>4.5&lt;/td>
 &lt;td>0.28x&lt;/td>
 &lt;td>可察覺、實用&lt;/td>
 &lt;td>多數場景的甜蜜點&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>Q3&lt;/td>
 &lt;td>3&lt;/td>
 &lt;td>0.19x&lt;/td>
 &lt;td>明顯、code 任務開始崩&lt;/td>
 &lt;td>較大模型強塞較小機器時備用&lt;/td>
 &lt;/tr>
 &lt;/tbody>
&lt;/table>
&lt;p>「&lt;code>_K_M&lt;/code>」的 K 指 K-quants（較新的量化方法）、M 指 mixed-medium（不同層用不同量化）。Q3 70B 模型在 coding 任務上常輸給 Q5 14B 模型；模型大小跟模型實用品質是兩件事。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>選量化等級時看三個維度：記憶體預算（量化後是否塞得進）、體感速度（量化越激進、tok/s 越高）、品質容忍度（過低量化會明顯衰減）。寫 code 場景的甜蜜點通常是 Q4_K_M；想再換更激進量化前、先用同等記憶體預算下的較小模型 Q5 對比，常會發現後者品質更好。&lt;/p></description><content:encoded><![CDATA[<p>Quantization（量化）的核心概念是「把模型權重從高精度（如 16-bit float）改用較低精度（如 4-bit integer）表示」。權重數量不變，但每個權重佔的 bytes 變少；模型總大小變小、每秒能讀過的權重變多，<a href="/blog/llm/knowledge-cards/tokens-per-second/" data-link-title="Tokens Per Second" data-link-desc="LLM 每秒能生成幾個 token：生字速度的標準量化指標">生字速度</a> 直接變快。</p>
<h2 id="概念位置">概念位置</h2>
<p>量化是讓 LLM 跑在 consumer 等級硬體上的關鍵技術。沒有量化、Apple Silicon Mac 跑不動 30B+ 模型，因為原始 bf16 權重會超出記憶體預算。量化方法主要分兩類：<a href="/blog/llm/knowledge-cards/gguf/" data-link-title="GGUF" data-link-desc="llama.cpp 生態定義的模型權重格式：把權重、tokenizer、metadata 打包成單一檔案">GGUF</a> 系統用的 K-quants（Q4_K_M、Q5_K_M 等）、以及 <a href="/blog/llm/knowledge-cards/mlx/" data-link-title="MLX" data-link-desc="Apple 釋出的 Apple Silicon 數值運算 framework：類似 PyTorch / JAX 的 Mac 對應物">MLX</a> 等系統用的 4-bit / 8-bit 量化。</p>
<h2 id="可觀察訊號與例子">可觀察訊號與例子</h2>
<p>常見量化等級的取捨：</p>
<table>
  <thead>
      <tr>
          <th>量化</th>
          <th>每權重 bits</th>
          <th>相對 bf16 大小</th>
          <th>品質衰減</th>
          <th>適合場景</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>bf16 / F16</td>
          <td>16</td>
          <td>1x</td>
          <td>無（基準）</td>
          <td>開發、評估、大記憶體機器</td>
      </tr>
      <tr>
          <td>Q8</td>
          <td>8</td>
          <td>0.5x</td>
          <td>幾乎察覺不到</td>
          <td>32GB+ Mac、品質敏感任務</td>
      </tr>
      <tr>
          <td>Q5_K_M</td>
          <td>5.5</td>
          <td>0.34x</td>
          <td>輕微</td>
          <td>24GB Mac、日常使用</td>
      </tr>
      <tr>
          <td>Q4_K_M</td>
          <td>4.5</td>
          <td>0.28x</td>
          <td>可察覺、實用</td>
          <td>多數場景的甜蜜點</td>
      </tr>
      <tr>
          <td>Q3</td>
          <td>3</td>
          <td>0.19x</td>
          <td>明顯、code 任務開始崩</td>
          <td>較大模型強塞較小機器時備用</td>
      </tr>
  </tbody>
</table>
<p>「<code>_K_M</code>」的 K 指 K-quants（較新的量化方法）、M 指 mixed-medium（不同層用不同量化）。Q3 70B 模型在 coding 任務上常輸給 Q5 14B 模型；模型大小跟模型實用品質是兩件事。</p>
<h2 id="設計責任">設計責任</h2>
<p>選量化等級時看三個維度：記憶體預算（量化後是否塞得進）、體感速度（量化越激進、tok/s 越高）、品質容忍度（過低量化會明顯衰減）。寫 code 場景的甜蜜點通常是 Q4_K_M；想再換更激進量化前、先用同等記憶體預算下的較小模型 Q5 對比，常會發現後者品質更好。</p>
]]></content:encoded></item><item><title>RAG</title><link>https://tarrragon.github.io/blog/llm/knowledge-cards/rag/</link><pubDate>Mon, 11 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/llm/knowledge-cards/rag/</guid><description>&lt;p>RAG（Retrieval-Augmented Generation）的核心概念是「給 LLM 動態外掛一份知識、在生成時從 &lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/retrieval-source/" data-link-title="Retrieval Source" data-link-desc="RAG 從哪個 corpus、index、tool 或外部系統取回內容，決定來源可信度、freshness、權限與引用責任">retrieval source&lt;/a> 找相關片段塞進 prompt 當 context」。它解的是 LLM 參數記憶的三個天然限制：訓練 cutoff、私有資料缺席、長尾事實壓縮損失。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>RAG 跟 &lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/instruction-tuned/" data-link-title="Instruction-Tuned Model" data-link-desc="經過指令微調的模型：會跟著 prompt 走、回答使用者問題">fine-tuning&lt;/a> 跟 long context 是「讓模型知道新東西」的三條路、解的問題層次不同：RAG 動態外掛、fine-tuning 改參數、long context 直接塞 prompt。三者不互斥、常組合用。RAG 屬於應用層、依賴 &lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/embedding-model/" data-link-title="Embedding Model" data-link-desc="把文字轉成向量的模型：用於 codebase 索引與語意搜尋">embedding model&lt;/a> 把文字轉向量、用相似度檢索。&lt;/p>
&lt;h2 id="可觀察訊號與例子">可觀察訊號與例子&lt;/h2>
&lt;p>寫 code 場景的典型 RAG 是 Continue.dev 的 &lt;code>@codebase&lt;/code>：把整個 repo 切 chunk、用 &lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/embedding-model/" data-link-title="Embedding Model" data-link-desc="把文字轉成向量的模型：用於 codebase 索引與語意搜尋">embedding model&lt;/a> 索引成向量、query 時用 cosine similarity 找相關片段、塞進 prompt 給 LLM。判讀 RAG 結果好壞看：retrieval 片段相關性、塞進 prompt 後 LLM 是否真用上、答案是否能追溯到 source chunk，以及整段 &lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/retrieval-cost/" data-link-title="Retrieval Cost" data-link-desc="RAG 檢索帶來的 latency、token、embedding、reranker、LLM call 與維護成本，用來判斷增強是否划算">retrieval cost&lt;/a> 是否划算。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>設計 RAG 系統前先評估「不做 RAG 會怎樣」：知識量小可用 long context、知識結構化可用 SQL、靜態風格特化可用 fine-tune。需要動態 + 大量 + traceable 才是 RAG 的甜蜜點。詳細展開見 &lt;a href="https://tarrragon.github.io/blog/llm/04-applications/rag-principles/" data-link-title="4.1 RAG 原理：retrieval &amp;#43; augmentation 模式" data-link-desc="為什麼模型需要外掛知識、語意相似 vs 字面相似、chunking 的本質取捨、retrieval 失敗的根本原因">4.1 RAG 原理&lt;/a>。&lt;/p></description><content:encoded><![CDATA[<p>RAG（Retrieval-Augmented Generation）的核心概念是「給 LLM 動態外掛一份知識、在生成時從 <a href="/blog/llm/knowledge-cards/retrieval-source/" data-link-title="Retrieval Source" data-link-desc="RAG 從哪個 corpus、index、tool 或外部系統取回內容，決定來源可信度、freshness、權限與引用責任">retrieval source</a> 找相關片段塞進 prompt 當 context」。它解的是 LLM 參數記憶的三個天然限制：訓練 cutoff、私有資料缺席、長尾事實壓縮損失。</p>
<h2 id="概念位置">概念位置</h2>
<p>RAG 跟 <a href="/blog/llm/knowledge-cards/instruction-tuned/" data-link-title="Instruction-Tuned Model" data-link-desc="經過指令微調的模型：會跟著 prompt 走、回答使用者問題">fine-tuning</a> 跟 long context 是「讓模型知道新東西」的三條路、解的問題層次不同：RAG 動態外掛、fine-tuning 改參數、long context 直接塞 prompt。三者不互斥、常組合用。RAG 屬於應用層、依賴 <a href="/blog/llm/knowledge-cards/embedding-model/" data-link-title="Embedding Model" data-link-desc="把文字轉成向量的模型：用於 codebase 索引與語意搜尋">embedding model</a> 把文字轉向量、用相似度檢索。</p>
<h2 id="可觀察訊號與例子">可觀察訊號與例子</h2>
<p>寫 code 場景的典型 RAG 是 Continue.dev 的 <code>@codebase</code>：把整個 repo 切 chunk、用 <a href="/blog/llm/knowledge-cards/embedding-model/" data-link-title="Embedding Model" data-link-desc="把文字轉成向量的模型：用於 codebase 索引與語意搜尋">embedding model</a> 索引成向量、query 時用 cosine similarity 找相關片段、塞進 prompt 給 LLM。判讀 RAG 結果好壞看：retrieval 片段相關性、塞進 prompt 後 LLM 是否真用上、答案是否能追溯到 source chunk，以及整段 <a href="/blog/llm/knowledge-cards/retrieval-cost/" data-link-title="Retrieval Cost" data-link-desc="RAG 檢索帶來的 latency、token、embedding、reranker、LLM call 與維護成本，用來判斷增強是否划算">retrieval cost</a> 是否划算。</p>
<h2 id="設計責任">設計責任</h2>
<p>設計 RAG 系統前先評估「不做 RAG 會怎樣」：知識量小可用 long context、知識結構化可用 SQL、靜態風格特化可用 fine-tune。需要動態 + 大量 + traceable 才是 RAG 的甜蜜點。詳細展開見 <a href="/blog/llm/04-applications/rag-principles/" data-link-title="4.1 RAG 原理：retrieval &#43; augmentation 模式" data-link-desc="為什麼模型需要外掛知識、語意相似 vs 字面相似、chunking 的本質取捨、retrieval 失敗的根本原因">4.1 RAG 原理</a>。</p>
]]></content:encoded></item><item><title>Speculative Decoding</title><link>https://tarrragon.github.io/blog/llm/knowledge-cards/speculative-decoding/</link><pubDate>Mon, 11 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/llm/knowledge-cards/speculative-decoding/</guid><description>&lt;p>Speculative Decoding（推測解碼）的核心概念是「用一個快的小模型（drafter）先猜未來 N 個 &lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/token/" data-link-title="Token" data-link-desc="LLM 處理文字時的最小單位：介於字元與單字之間">token&lt;/a>、再讓大模型（target）一次並行驗證」。大模型認同的前綴保留下來、不認同的位置之後重新生成。實際效果是「一次 forward pass 產出多個 token」、攻擊的是 &lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/autoregressive/" data-link-title="Autoregressive" data-link-desc="LLM 一次生成一個 token、把已生成內容作為下一次輸入的架構">autoregressive&lt;/a> 的單 token 瓶頸。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>Speculative decoding 是純加速技巧、不改變輸出品質。大模型驗證階段的數學保證：drafter 猜對時保留、猜錯時 target 自己決定下一個 token、最終結果跟「不用 drafter 直接生成」一致。它能加速的關鍵是「驗證可以並行」—— 大模型一次跑 forward pass 驗證 N 個 token 的時間、跟驗證 1 個 token 接近、因為瓶頸是 &lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/memory-bandwidth/" data-link-title="Memory Bandwidth" data-link-desc="記憶體每秒能讀寫多少 bytes：決定本地 LLM 生字速度的真正瓶頸">memory bandwidth&lt;/a> 而非算力。&lt;/p>
&lt;h2 id="可觀察訊號與例子">可觀察訊號與例子&lt;/h2>
&lt;p>寫 code 場景的 speculative decoding 接受率特別高，因為 code 有大量可預測 pattern（縮排、括號、import 語句、常見變數名）。drafter 猜對的機率高、整體加速明顯。&lt;/p>
&lt;p>Google 為 Gemma 4 釋出官方 &lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/drafter-model/" data-link-title="Drafter Model" data-link-desc="speculative decoding 中用來快速猜未來 token 的小模型">drafter&lt;/a> 後、官方數據 coding 任務 2 ~ 3 倍加速、其他任務 1.5 ~ 2 倍。&lt;/p>
&lt;p>實作層面、Ollama v0.23.1（2026/5/7）一鍵啟用 &lt;code>gemma4:31b-coding-mtp-bf16&lt;/code>、LM Studio 提供 UI 設定面板、llama.cpp 的 &lt;code>--draft-model&lt;/code> 參數仍 beta。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>啟用 speculative decoding 需要 target 模型與 drafter 模型用相同 tokenizer。Gemma 4 31B 配 Gemma 4 E4B 可以工作、跨家族（Gemma 配 Llama 等）沒有相容性。多數使用者透過預先打包好的 model tag（如 Ollama 的 MTP 版本）一行啟用、無需自己挑 drafter。&lt;/p></description><content:encoded><![CDATA[<p>Speculative Decoding（推測解碼）的核心概念是「用一個快的小模型（drafter）先猜未來 N 個 <a href="/blog/llm/knowledge-cards/token/" data-link-title="Token" data-link-desc="LLM 處理文字時的最小單位：介於字元與單字之間">token</a>、再讓大模型（target）一次並行驗證」。大模型認同的前綴保留下來、不認同的位置之後重新生成。實際效果是「一次 forward pass 產出多個 token」、攻擊的是 <a href="/blog/llm/knowledge-cards/autoregressive/" data-link-title="Autoregressive" data-link-desc="LLM 一次生成一個 token、把已生成內容作為下一次輸入的架構">autoregressive</a> 的單 token 瓶頸。</p>
<h2 id="概念位置">概念位置</h2>
<p>Speculative decoding 是純加速技巧、不改變輸出品質。大模型驗證階段的數學保證：drafter 猜對時保留、猜錯時 target 自己決定下一個 token、最終結果跟「不用 drafter 直接生成」一致。它能加速的關鍵是「驗證可以並行」—— 大模型一次跑 forward pass 驗證 N 個 token 的時間、跟驗證 1 個 token 接近、因為瓶頸是 <a href="/blog/llm/knowledge-cards/memory-bandwidth/" data-link-title="Memory Bandwidth" data-link-desc="記憶體每秒能讀寫多少 bytes：決定本地 LLM 生字速度的真正瓶頸">memory bandwidth</a> 而非算力。</p>
<h2 id="可觀察訊號與例子">可觀察訊號與例子</h2>
<p>寫 code 場景的 speculative decoding 接受率特別高，因為 code 有大量可預測 pattern（縮排、括號、import 語句、常見變數名）。drafter 猜對的機率高、整體加速明顯。</p>
<p>Google 為 Gemma 4 釋出官方 <a href="/blog/llm/knowledge-cards/drafter-model/" data-link-title="Drafter Model" data-link-desc="speculative decoding 中用來快速猜未來 token 的小模型">drafter</a> 後、官方數據 coding 任務 2 ~ 3 倍加速、其他任務 1.5 ~ 2 倍。</p>
<p>實作層面、Ollama v0.23.1（2026/5/7）一鍵啟用 <code>gemma4:31b-coding-mtp-bf16</code>、LM Studio 提供 UI 設定面板、llama.cpp 的 <code>--draft-model</code> 參數仍 beta。</p>
<h2 id="設計責任">設計責任</h2>
<p>啟用 speculative decoding 需要 target 模型與 drafter 模型用相同 tokenizer。Gemma 4 31B 配 Gemma 4 E4B 可以工作、跨家族（Gemma 配 Llama 等）沒有相容性。多數使用者透過預先打包好的 model tag（如 Ollama 的 MTP 版本）一行啟用、無需自己挑 drafter。</p>
]]></content:encoded></item><item><title>SWE-bench</title><link>https://tarrragon.github.io/blog/llm/knowledge-cards/swe-bench/</link><pubDate>Mon, 11 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/llm/knowledge-cards/swe-bench/</guid><description>&lt;p>SWE-bench 的核心概念是「用真實開源專案的 GitHub issue 與 PR 當測試集、評量 LLM 解程式碼問題的能力」。它把 LLM 放在「給一個 issue 描述、看能否生成解決它的 patch」的任務上、跑完用 patch 是否能讓既有測試通過作為通過率。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>SWE-bench 比早期的 HumanEval（單一 function 生成）難得多、涵蓋多檔案理解、需求拆解、實際 patch 生成。它是 2026 年量化 coding LLM 能力最常被引用的指標。SWE-bench Verified 是 OpenAI 篩選過的子集、確保任務描述清楚、是現在報告主流。&lt;/p>
&lt;h2 id="可觀察訊號與例子">可觀察訊號與例子&lt;/h2>
&lt;p>2026 年 5 月各模型在 SWE-bench Verified 上的大致表現（僅供量級參考、實際數字以官方報告為準）：&lt;/p>
&lt;table>
 &lt;thead>
 &lt;tr>
 &lt;th>模型&lt;/th>
 &lt;th>SWE-bench Verified&lt;/th>
 &lt;/tr>
 &lt;/thead>
 &lt;tbody>
 &lt;tr>
 &lt;td>Claude Sonnet 4.6&lt;/td>
 &lt;td>80+ 分&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>GPT-5&lt;/td>
 &lt;td>80+ 分&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>Qwen3-Coder 30B（本地）&lt;/td>
 &lt;td>77.2 分&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>Gemma 4 31B（本地）&lt;/td>
 &lt;td>70+ 分&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>Qwen3 14B&lt;/td>
 &lt;td>50+ 分&lt;/td>
 &lt;/tr>
 &lt;/tbody>
&lt;/table>
&lt;p>「分數」是百分比、代表通過率。本地最強模型在 SWE-bench 上跟雲端旗艦仍有差距、但對寫 code 場景已堪用。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>評估模型適合不適合本地寫 code 時、SWE-bench Verified 是核心指標之一。換新模型前看分數差距：5 分以上才值得試（適應新 prompt 風格的成本不低）。看到「新模型超越 GPT-X」報導時、確認是哪個 SWE-bench 變體（Lite / Verified / Full）；變體間分數差很多、混為一談會誤判。&lt;/p></description><content:encoded><![CDATA[<p>SWE-bench 的核心概念是「用真實開源專案的 GitHub issue 與 PR 當測試集、評量 LLM 解程式碼問題的能力」。它把 LLM 放在「給一個 issue 描述、看能否生成解決它的 patch」的任務上、跑完用 patch 是否能讓既有測試通過作為通過率。</p>
<h2 id="概念位置">概念位置</h2>
<p>SWE-bench 比早期的 HumanEval（單一 function 生成）難得多、涵蓋多檔案理解、需求拆解、實際 patch 生成。它是 2026 年量化 coding LLM 能力最常被引用的指標。SWE-bench Verified 是 OpenAI 篩選過的子集、確保任務描述清楚、是現在報告主流。</p>
<h2 id="可觀察訊號與例子">可觀察訊號與例子</h2>
<p>2026 年 5 月各模型在 SWE-bench Verified 上的大致表現（僅供量級參考、實際數字以官方報告為準）：</p>
<table>
  <thead>
      <tr>
          <th>模型</th>
          <th>SWE-bench Verified</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>Claude Sonnet 4.6</td>
          <td>80+ 分</td>
      </tr>
      <tr>
          <td>GPT-5</td>
          <td>80+ 分</td>
      </tr>
      <tr>
          <td>Qwen3-Coder 30B（本地）</td>
          <td>77.2 分</td>
      </tr>
      <tr>
          <td>Gemma 4 31B（本地）</td>
          <td>70+ 分</td>
      </tr>
      <tr>
          <td>Qwen3 14B</td>
          <td>50+ 分</td>
      </tr>
  </tbody>
</table>
<p>「分數」是百分比、代表通過率。本地最強模型在 SWE-bench 上跟雲端旗艦仍有差距、但對寫 code 場景已堪用。</p>
<h2 id="設計責任">設計責任</h2>
<p>評估模型適合不適合本地寫 code 時、SWE-bench Verified 是核心指標之一。換新模型前看分數差距：5 分以上才值得試（適應新 prompt 風格的成本不低）。看到「新模型超越 GPT-X」報導時、確認是哪個 SWE-bench 變體（Lite / Verified / Full）；變體間分數差很多、混為一談會誤判。</p>
]]></content:encoded></item><item><title>Token</title><link>https://tarrragon.github.io/blog/llm/knowledge-cards/token/</link><pubDate>Mon, 11 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/llm/knowledge-cards/token/</guid><description>&lt;p>Token 的核心概念是「LLM 內部處理文字的最小單位」，介於字元（character）與單字（word）之間。模型接收 prompt 前會先用 tokenizer 把文字切成 token 序列，輸出時也以 token 為單位逐個生成。Token 是計費、速度、context 容量等所有 LLM 量化指標的共同單位。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>Token 位於介面層送出文字與模型層實際運算之間的轉換點。介面層的「字串」進入模型前會被 tokenizer 切成整數序列；模型輸出的整數序列再被 tokenizer 還原成字串給介面層顯示。不同模型用不同 tokenizer，同一段文字在 GPT、Claude、Gemma 上切出的 token 數量會有差異。&lt;/p>
&lt;h2 id="可觀察訊號與例子">可觀察訊號與例子&lt;/h2>
&lt;p>英文約「4 個字元 ≈ 1 token」，中文約「1 ~ 2 個字 ≈ 1 token」。&lt;code>Hello, world!&lt;/code> 約 4 個 token；「你好，世界」約 5 ~ 7 個 token，視 tokenizer 而定。雲端 API 的計費單據用 token 計量，本地推論的速度指標 &lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/tokens-per-second/" data-link-title="Tokens Per Second" data-link-desc="LLM 每秒能生成幾個 token：生字速度的標準量化指標">tokens per second&lt;/a> 也以 token 為單位。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>理解 token 後可以做幾件實用判斷：估算 prompt 是否會超過 &lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/context-window/" data-link-title="Context Window" data-link-desc="模型一次能處理的最大 token 數量：prompt 加生成的總和上限">context window&lt;/a>、估算雲端 API 費用、解讀 benchmark 數字。寫程式時用 OpenAI 的 &lt;code>tiktoken&lt;/code>、Hugging Face 的 &lt;code>transformers.AutoTokenizer&lt;/code> 可以精確計算特定模型的 token 數量。&lt;/p></description><content:encoded><![CDATA[<p>Token 的核心概念是「LLM 內部處理文字的最小單位」，介於字元（character）與單字（word）之間。模型接收 prompt 前會先用 tokenizer 把文字切成 token 序列，輸出時也以 token 為單位逐個生成。Token 是計費、速度、context 容量等所有 LLM 量化指標的共同單位。</p>
<h2 id="概念位置">概念位置</h2>
<p>Token 位於介面層送出文字與模型層實際運算之間的轉換點。介面層的「字串」進入模型前會被 tokenizer 切成整數序列；模型輸出的整數序列再被 tokenizer 還原成字串給介面層顯示。不同模型用不同 tokenizer，同一段文字在 GPT、Claude、Gemma 上切出的 token 數量會有差異。</p>
<h2 id="可觀察訊號與例子">可觀察訊號與例子</h2>
<p>英文約「4 個字元 ≈ 1 token」，中文約「1 ~ 2 個字 ≈ 1 token」。<code>Hello, world!</code> 約 4 個 token；「你好，世界」約 5 ~ 7 個 token，視 tokenizer 而定。雲端 API 的計費單據用 token 計量，本地推論的速度指標 <a href="/blog/llm/knowledge-cards/tokens-per-second/" data-link-title="Tokens Per Second" data-link-desc="LLM 每秒能生成幾個 token：生字速度的標準量化指標">tokens per second</a> 也以 token 為單位。</p>
<h2 id="設計責任">設計責任</h2>
<p>理解 token 後可以做幾件實用判斷：估算 prompt 是否會超過 <a href="/blog/llm/knowledge-cards/context-window/" data-link-title="Context Window" data-link-desc="模型一次能處理的最大 token 數量：prompt 加生成的總和上限">context window</a>、估算雲端 API 費用、解讀 benchmark 數字。寫程式時用 OpenAI 的 <code>tiktoken</code>、Hugging Face 的 <code>transformers.AutoTokenizer</code> 可以精確計算特定模型的 token 數量。</p>
]]></content:encoded></item><item><title>Tokens Per Second</title><link>https://tarrragon.github.io/blog/llm/knowledge-cards/tokens-per-second/</link><pubDate>Mon, 11 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/llm/knowledge-cards/tokens-per-second/</guid><description>&lt;p>Tokens Per Second（tok/s）的核心概念是「LLM 每秒能輸出多少個 &lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/token/" data-link-title="Token" data-link-desc="LLM 處理文字時的最小單位：介於字元與單字之間">token&lt;/a>」，是生字速度的標準指標。生字速度由 &lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/memory-bandwidth/" data-link-title="Memory Bandwidth" data-link-desc="記憶體每秒能讀寫多少 bytes：決定本地 LLM 生字速度的真正瓶頸">memory bandwidth&lt;/a> 跟模型大小共同決定，而非 CPU / GPU 算力。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>Tok/s 量度的是 &lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/autoregressive/" data-link-title="Autoregressive" data-link-desc="LLM 一次生成一個 token、把已生成內容作為下一次輸入的架構">autoregressive&lt;/a> 主要生成階段的吞吐量，跟 &lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/ttft/" data-link-title="TTFT" data-link-desc="Time To First Token：送出 prompt 到第一個 token 出現的等待時間">TTFT&lt;/a>（首字延遲）是兩個獨立指標。一個系統可能 TTFT 高但 tok/s 還行，也可能 TTFT 低但 tok/s 慢；兩者都要看才能完整描述體感。&lt;/p>
&lt;h2 id="可觀察訊號與例子">可觀察訊號與例子&lt;/h2>
&lt;p>實務經驗值（僅供量級參考、視硬體與量化等級而定）：&lt;/p>
&lt;table>
 &lt;thead>
 &lt;tr>
 &lt;th>場景&lt;/th>
 &lt;th>大致 tok/s&lt;/th>
 &lt;/tr>
 &lt;/thead>
 &lt;tbody>
 &lt;tr>
 &lt;td>Claude Sonnet 雲端&lt;/td>
 &lt;td>80 ~ 120&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>GPT-5 雲端&lt;/td>
 &lt;td>70 ~ 100&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>Gemma 4 31B MTP / M4 Max&lt;/td>
 &lt;td>25 ~ 40&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>Qwen3-Coder 30B / M2 Pro&lt;/td>
 &lt;td>15 ~ 25&lt;/td>
 &lt;/tr>
 &lt;/tbody>
&lt;/table>
&lt;p>體感分界：低於 10 tok/s 像 dial-up 般卡頓、20 tok/s 以上接近流暢閱讀速度、40 tok/s 以上感覺即時。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>評估本地 LLM 是否堪用時，tok/s 是核心指標之一。理論上限可用「&lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/memory-bandwidth/" data-link-title="Memory Bandwidth" data-link-desc="記憶體每秒能讀寫多少 bytes：決定本地 LLM 生字速度的真正瓶頸">memory bandwidth&lt;/a> ÷ 模型大小」估算，實際值會比理論低 30 ~ 50%。看到「N tok/s」的報告時要追問模型、&lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/quantization/" data-link-title="Quantization" data-link-desc="用較少 bits 表示模型權重：壓縮記憶體佔用、加快生字速度，代價是少量品質衰減">量化&lt;/a> 等級、硬體，三者缺一個就無法比較。&lt;/p></description><content:encoded><![CDATA[<p>Tokens Per Second（tok/s）的核心概念是「LLM 每秒能輸出多少個 <a href="/blog/llm/knowledge-cards/token/" data-link-title="Token" data-link-desc="LLM 處理文字時的最小單位：介於字元與單字之間">token</a>」，是生字速度的標準指標。生字速度由 <a href="/blog/llm/knowledge-cards/memory-bandwidth/" data-link-title="Memory Bandwidth" data-link-desc="記憶體每秒能讀寫多少 bytes：決定本地 LLM 生字速度的真正瓶頸">memory bandwidth</a> 跟模型大小共同決定，而非 CPU / GPU 算力。</p>
<h2 id="概念位置">概念位置</h2>
<p>Tok/s 量度的是 <a href="/blog/llm/knowledge-cards/autoregressive/" data-link-title="Autoregressive" data-link-desc="LLM 一次生成一個 token、把已生成內容作為下一次輸入的架構">autoregressive</a> 主要生成階段的吞吐量，跟 <a href="/blog/llm/knowledge-cards/ttft/" data-link-title="TTFT" data-link-desc="Time To First Token：送出 prompt 到第一個 token 出現的等待時間">TTFT</a>（首字延遲）是兩個獨立指標。一個系統可能 TTFT 高但 tok/s 還行，也可能 TTFT 低但 tok/s 慢；兩者都要看才能完整描述體感。</p>
<h2 id="可觀察訊號與例子">可觀察訊號與例子</h2>
<p>實務經驗值（僅供量級參考、視硬體與量化等級而定）：</p>
<table>
  <thead>
      <tr>
          <th>場景</th>
          <th>大致 tok/s</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>Claude Sonnet 雲端</td>
          <td>80 ~ 120</td>
      </tr>
      <tr>
          <td>GPT-5 雲端</td>
          <td>70 ~ 100</td>
      </tr>
      <tr>
          <td>Gemma 4 31B MTP / M4 Max</td>
          <td>25 ~ 40</td>
      </tr>
      <tr>
          <td>Qwen3-Coder 30B / M2 Pro</td>
          <td>15 ~ 25</td>
      </tr>
  </tbody>
</table>
<p>體感分界：低於 10 tok/s 像 dial-up 般卡頓、20 tok/s 以上接近流暢閱讀速度、40 tok/s 以上感覺即時。</p>
<h2 id="設計責任">設計責任</h2>
<p>評估本地 LLM 是否堪用時，tok/s 是核心指標之一。理論上限可用「<a href="/blog/llm/knowledge-cards/memory-bandwidth/" data-link-title="Memory Bandwidth" data-link-desc="記憶體每秒能讀寫多少 bytes：決定本地 LLM 生字速度的真正瓶頸">memory bandwidth</a> ÷ 模型大小」估算，實際值會比理論低 30 ~ 50%。看到「N tok/s」的報告時要追問模型、<a href="/blog/llm/knowledge-cards/quantization/" data-link-title="Quantization" data-link-desc="用較少 bits 表示模型權重：壓縮記憶體佔用、加快生字速度，代價是少量品質衰減">量化</a> 等級、硬體，三者缺一個就無法比較。</p>
]]></content:encoded></item><item><title>Transformer</title><link>https://tarrragon.github.io/blog/llm/knowledge-cards/transformer/</link><pubDate>Mon, 11 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/llm/knowledge-cards/transformer/</guid><description>&lt;p>Transformer 的核心概念是「2017 年 Google 提出、基於 self-attention 機制的神經網路架構」。寫 code 用的所有 LLM（GPT、Claude、Gemma、Llama、Qwen 系列）都是 Transformer 架構；它跟產圖用的 &lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/diffusion/" data-link-title="Diffusion" data-link-desc="產圖用的生成式 AI 架構：跟寫 code 用的 Transformer 是不同路線">Diffusion&lt;/a> 是兩個不同的生成式 AI 路線。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>Transformer 是模型架構層的選擇、決定底層運算方式與適合的任務類型。它擅長「序列建模」：文字、code、語音、時間序列等都能用 Transformer 處理。配 &lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/autoregressive/" data-link-title="Autoregressive" data-link-desc="LLM 一次生成一個 token、把已生成內容作為下一次輸入的架構">autoregressive&lt;/a> 生成方式跑文字、跑出來的就是 LLM。&lt;/p>
&lt;h2 id="可觀察訊號與例子">可觀察訊號與例子&lt;/h2>
&lt;p>Transformer LLM 的共通特徵：&lt;/p>
&lt;table>
 &lt;thead>
 &lt;tr>
 &lt;th>特徵&lt;/th>
 &lt;th>表現&lt;/th>
 &lt;/tr>
 &lt;/thead>
 &lt;tbody>
 &lt;tr>
 &lt;td>生成方式&lt;/td>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/autoregressive/" data-link-title="Autoregressive" data-link-desc="LLM 一次生成一個 token、把已生成內容作為下一次輸入的架構">一個 token 接一個 token&lt;/a>&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>量化指標&lt;/td>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/tokens-per-second/" data-link-title="Tokens Per Second" data-link-desc="LLM 每秒能生成幾個 token：生字速度的標準量化指標">tokens per second&lt;/a>、&lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/ttft/" data-link-title="TTFT" data-link-desc="Time To First Token：送出 prompt 到第一個 token 出現的等待時間">TTFT&lt;/a>&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>輸入處理&lt;/td>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/prefill/" data-link-title="Prefill" data-link-desc="Prompt 首次處理時的計算階段：把整段輸入跑過模型、產生 KV cache">prefill&lt;/a> 階段&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>中間結果&lt;/td>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/kv-cache/" data-link-title="KV Cache" data-link-desc="已處理 token 的 attention 中間結果暫存：避免重算、加速後續生成">KV cache&lt;/a>&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>容量限制&lt;/td>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/context-window/" data-link-title="Context Window" data-link-desc="模型一次能處理的最大 token 數量：prompt 加生成的總和上限">context window&lt;/a>&lt;/td>
 &lt;/tr>
 &lt;/tbody>
&lt;/table>
&lt;p>Transformer 也被用在多模態場景（vision Transformer、speech Transformer）、但寫 code 場景接觸到的都是文字 Transformer。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>理解「寫 code 的 LLM 是 Transformer」可以幫助判讀資訊。看到「最新 Transformer 模型」報導時、知道它跟 Diffusion 是兩個路線；想跑產圖時、知道要找 Diffusion 工具（ComfyUI、Draw Things）而非 Ollama；看到「LLM 架構創新」時、可以追問是 attention 機制改良、還是換到非 Transformer 路線（如 Mamba、RWKV 等少數實驗性架構）。&lt;/p></description><content:encoded><![CDATA[<p>Transformer 的核心概念是「2017 年 Google 提出、基於 self-attention 機制的神經網路架構」。寫 code 用的所有 LLM（GPT、Claude、Gemma、Llama、Qwen 系列）都是 Transformer 架構；它跟產圖用的 <a href="/blog/llm/knowledge-cards/diffusion/" data-link-title="Diffusion" data-link-desc="產圖用的生成式 AI 架構：跟寫 code 用的 Transformer 是不同路線">Diffusion</a> 是兩個不同的生成式 AI 路線。</p>
<h2 id="概念位置">概念位置</h2>
<p>Transformer 是模型架構層的選擇、決定底層運算方式與適合的任務類型。它擅長「序列建模」：文字、code、語音、時間序列等都能用 Transformer 處理。配 <a href="/blog/llm/knowledge-cards/autoregressive/" data-link-title="Autoregressive" data-link-desc="LLM 一次生成一個 token、把已生成內容作為下一次輸入的架構">autoregressive</a> 生成方式跑文字、跑出來的就是 LLM。</p>
<h2 id="可觀察訊號與例子">可觀察訊號與例子</h2>
<p>Transformer LLM 的共通特徵：</p>
<table>
  <thead>
      <tr>
          <th>特徵</th>
          <th>表現</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>生成方式</td>
          <td><a href="/blog/llm/knowledge-cards/autoregressive/" data-link-title="Autoregressive" data-link-desc="LLM 一次生成一個 token、把已生成內容作為下一次輸入的架構">一個 token 接一個 token</a></td>
      </tr>
      <tr>
          <td>量化指標</td>
          <td><a href="/blog/llm/knowledge-cards/tokens-per-second/" data-link-title="Tokens Per Second" data-link-desc="LLM 每秒能生成幾個 token：生字速度的標準量化指標">tokens per second</a>、<a href="/blog/llm/knowledge-cards/ttft/" data-link-title="TTFT" data-link-desc="Time To First Token：送出 prompt 到第一個 token 出現的等待時間">TTFT</a></td>
      </tr>
      <tr>
          <td>輸入處理</td>
          <td><a href="/blog/llm/knowledge-cards/prefill/" data-link-title="Prefill" data-link-desc="Prompt 首次處理時的計算階段：把整段輸入跑過模型、產生 KV cache">prefill</a> 階段</td>
      </tr>
      <tr>
          <td>中間結果</td>
          <td><a href="/blog/llm/knowledge-cards/kv-cache/" data-link-title="KV Cache" data-link-desc="已處理 token 的 attention 中間結果暫存：避免重算、加速後續生成">KV cache</a></td>
      </tr>
      <tr>
          <td>容量限制</td>
          <td><a href="/blog/llm/knowledge-cards/context-window/" data-link-title="Context Window" data-link-desc="模型一次能處理的最大 token 數量：prompt 加生成的總和上限">context window</a></td>
      </tr>
  </tbody>
</table>
<p>Transformer 也被用在多模態場景（vision Transformer、speech Transformer）、但寫 code 場景接觸到的都是文字 Transformer。</p>
<h2 id="設計責任">設計責任</h2>
<p>理解「寫 code 的 LLM 是 Transformer」可以幫助判讀資訊。看到「最新 Transformer 模型」報導時、知道它跟 Diffusion 是兩個路線；想跑產圖時、知道要找 Diffusion 工具（ComfyUI、Draw Things）而非 Ollama；看到「LLM 架構創新」時、可以追問是 attention 機制改良、還是換到非 Transformer 路線（如 Mamba、RWKV 等少數實驗性架構）。</p>
]]></content:encoded></item><item><title>TTFT</title><link>https://tarrragon.github.io/blog/llm/knowledge-cards/ttft/</link><pubDate>Mon, 11 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/llm/knowledge-cards/ttft/</guid><description>&lt;p>TTFT（Time To First Token）的核心概念是「使用者送出 prompt 之後，等多久才看到第一個 &lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/token/" data-link-title="Token" data-link-desc="LLM 處理文字時的最小單位：介於字元與單字之間">token&lt;/a> 出現」。它包含 prompt 的 &lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/prefill/" data-link-title="Prefill" data-link-desc="Prompt 首次處理時的計算階段：把整段輸入跑過模型、產生 KV cache">prefill&lt;/a> 時間、網路傳輸（雲端才有）、伺服器排隊與第一個 token 的生成。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>TTFT 跟 &lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/tokens-per-second/" data-link-title="Tokens Per Second" data-link-desc="LLM 每秒能生成幾個 token：生字速度的標準量化指標">tokens per second&lt;/a>（生字速度）是兩個獨立指標。前者描述「開始講話前的停頓」，後者描述「開始講話後講多快」。長 &lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/context-window/" data-link-title="Context Window" data-link-desc="模型一次能處理的最大 token 數量：prompt 加生成的總和上限">context&lt;/a> 場景的 TTFT 由 prefill 主導，與 prompt 長度成正比。&lt;/p>
&lt;h2 id="可觀察訊號與例子">可觀察訊號與例子&lt;/h2>
&lt;p>短 prompt（&amp;lt; 1K token）場景：&lt;/p>
&lt;table>
 &lt;thead>
 &lt;tr>
 &lt;th>環境&lt;/th>
 &lt;th>TTFT&lt;/th>
 &lt;/tr>
 &lt;/thead>
 &lt;tbody>
 &lt;tr>
 &lt;td>Claude Sonnet 雲端&lt;/td>
 &lt;td>0.5 ~ 1 秒&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>Gemma 4 31B MTP / M4 Max&lt;/td>
 &lt;td>1 ~ 3 秒&lt;/td>
 &lt;/tr>
 &lt;/tbody>
&lt;/table>
&lt;p>長 prompt（10K+ token）場景：本地 TTFT 可能拉到 30 ~ 90 秒（每次都重新 prefill 整段 context）。雲端 TTFT 受影響較小，因為 H100 等資料中心 GPU 的 prefill 算力遠高於 Apple Silicon。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>寫 code 場景的 TTFT 痛點主要出現在 coding agent 模式（塞整個 repo 進 prompt）。對短 prompt 場景，TTFT 1 ~ 3 秒可接受；對長 context 場景，要評估特化伺服器（如 oMLX）的 &lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/kv-cache/" data-link-title="KV Cache" data-link-desc="已處理 token 的 attention 中間結果暫存：避免重算、加速後續生成">KV cache&lt;/a> 重用方案。判讀 TTFT 報告時，務必確認 prompt 長度、否則數字無從比較。&lt;/p></description><content:encoded><![CDATA[<p>TTFT（Time To First Token）的核心概念是「使用者送出 prompt 之後，等多久才看到第一個 <a href="/blog/llm/knowledge-cards/token/" data-link-title="Token" data-link-desc="LLM 處理文字時的最小單位：介於字元與單字之間">token</a> 出現」。它包含 prompt 的 <a href="/blog/llm/knowledge-cards/prefill/" data-link-title="Prefill" data-link-desc="Prompt 首次處理時的計算階段：把整段輸入跑過模型、產生 KV cache">prefill</a> 時間、網路傳輸（雲端才有）、伺服器排隊與第一個 token 的生成。</p>
<h2 id="概念位置">概念位置</h2>
<p>TTFT 跟 <a href="/blog/llm/knowledge-cards/tokens-per-second/" data-link-title="Tokens Per Second" data-link-desc="LLM 每秒能生成幾個 token：生字速度的標準量化指標">tokens per second</a>（生字速度）是兩個獨立指標。前者描述「開始講話前的停頓」，後者描述「開始講話後講多快」。長 <a href="/blog/llm/knowledge-cards/context-window/" data-link-title="Context Window" data-link-desc="模型一次能處理的最大 token 數量：prompt 加生成的總和上限">context</a> 場景的 TTFT 由 prefill 主導，與 prompt 長度成正比。</p>
<h2 id="可觀察訊號與例子">可觀察訊號與例子</h2>
<p>短 prompt（&lt; 1K token）場景：</p>
<table>
  <thead>
      <tr>
          <th>環境</th>
          <th>TTFT</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>Claude Sonnet 雲端</td>
          <td>0.5 ~ 1 秒</td>
      </tr>
      <tr>
          <td>Gemma 4 31B MTP / M4 Max</td>
          <td>1 ~ 3 秒</td>
      </tr>
  </tbody>
</table>
<p>長 prompt（10K+ token）場景：本地 TTFT 可能拉到 30 ~ 90 秒（每次都重新 prefill 整段 context）。雲端 TTFT 受影響較小，因為 H100 等資料中心 GPU 的 prefill 算力遠高於 Apple Silicon。</p>
<h2 id="設計責任">設計責任</h2>
<p>寫 code 場景的 TTFT 痛點主要出現在 coding agent 模式（塞整個 repo 進 prompt）。對短 prompt 場景，TTFT 1 ~ 3 秒可接受；對長 context 場景，要評估特化伺服器（如 oMLX）的 <a href="/blog/llm/knowledge-cards/kv-cache/" data-link-title="KV Cache" data-link-desc="已處理 token 的 attention 中間結果暫存：避免重算、加速後續生成">KV cache</a> 重用方案。判讀 TTFT 報告時，務必確認 prompt 長度、否則數字無從比較。</p>
]]></content:encoded></item><item><title>Unified Memory Architecture</title><link>https://tarrragon.github.io/blog/llm/knowledge-cards/unified-memory/</link><pubDate>Mon, 11 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/llm/knowledge-cards/unified-memory/</guid><description>&lt;p>Unified Memory Architecture（UMA、統一記憶體架構）的核心概念是「Apple Silicon 把 CPU、GPU、Neural Engine 接在同一塊記憶體上」、共用同一份位址空間。傳統 PC 把系統記憶體跟 VRAM 分開、模型權重要塞進 VRAM 才能用 GPU 跑、跨 PCIe 搬資料很慢。Mac 的統一記憶體避開這個限制。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>UMA 是 Apple Silicon 在「能跑多大模型」上佔優勢的硬體基礎。32GB 統一記憶體可以幾乎全部給模型用（留 8GB 給系統）；同等價位的 PC + NVIDIA 配置通常只有 12 ~ 24GB VRAM。能跑得動 vs 跑得快是兩件事：UMA 解前者、&lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/memory-bandwidth/" data-link-title="Memory Bandwidth" data-link-desc="記憶體每秒能讀寫多少 bytes：決定本地 LLM 生字速度的真正瓶頸">memory bandwidth&lt;/a> 才決定後者。&lt;/p>
&lt;h2 id="可觀察訊號與例子">可觀察訊號與例子&lt;/h2>
&lt;p>32GB Mac 跑 &lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/quantization/" data-link-title="Quantization" data-link-desc="用較少 bits 表示模型權重：壓縮記憶體佔用、加快生字速度，代價是少量品質衰減">Q4 量化&lt;/a> 的 Gemma 4 31B 模型順暢（佔 18GB）、同等價位 PC（16GB VRAM 等級）跑不動同一模型、要降到 14B Q4 才行。70B 模型在 64GB Mac 上可行、PC 需要兩張 24GB VRAM GPU 配 NVLink、成本高得多。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>買 Mac 跑本地 LLM 時、把記憶體當第一順位考量、超過 CPU 規格與儲存空間。32GB 是寫 code 場景的甜蜜點（跑得起 Gemma 4 31B MTP）、48 ~ 64GB 進階配置（跑得起 70B 或同時跑兩個模型）、96GB+ 對寫 code 場景多半過度配置。MLX 等 framework 利用 UMA 的方式跟 Metal backend 略有差異、但對使用者都透明、選伺服器時無需考量 UMA 細節。&lt;/p></description><content:encoded><![CDATA[<p>Unified Memory Architecture（UMA、統一記憶體架構）的核心概念是「Apple Silicon 把 CPU、GPU、Neural Engine 接在同一塊記憶體上」、共用同一份位址空間。傳統 PC 把系統記憶體跟 VRAM 分開、模型權重要塞進 VRAM 才能用 GPU 跑、跨 PCIe 搬資料很慢。Mac 的統一記憶體避開這個限制。</p>
<h2 id="概念位置">概念位置</h2>
<p>UMA 是 Apple Silicon 在「能跑多大模型」上佔優勢的硬體基礎。32GB 統一記憶體可以幾乎全部給模型用（留 8GB 給系統）；同等價位的 PC + NVIDIA 配置通常只有 12 ~ 24GB VRAM。能跑得動 vs 跑得快是兩件事：UMA 解前者、<a href="/blog/llm/knowledge-cards/memory-bandwidth/" data-link-title="Memory Bandwidth" data-link-desc="記憶體每秒能讀寫多少 bytes：決定本地 LLM 生字速度的真正瓶頸">memory bandwidth</a> 才決定後者。</p>
<h2 id="可觀察訊號與例子">可觀察訊號與例子</h2>
<p>32GB Mac 跑 <a href="/blog/llm/knowledge-cards/quantization/" data-link-title="Quantization" data-link-desc="用較少 bits 表示模型權重：壓縮記憶體佔用、加快生字速度，代價是少量品質衰減">Q4 量化</a> 的 Gemma 4 31B 模型順暢（佔 18GB）、同等價位 PC（16GB VRAM 等級）跑不動同一模型、要降到 14B Q4 才行。70B 模型在 64GB Mac 上可行、PC 需要兩張 24GB VRAM GPU 配 NVLink、成本高得多。</p>
<h2 id="設計責任">設計責任</h2>
<p>買 Mac 跑本地 LLM 時、把記憶體當第一順位考量、超過 CPU 規格與儲存空間。32GB 是寫 code 場景的甜蜜點（跑得起 Gemma 4 31B MTP）、48 ~ 64GB 進階配置（跑得起 70B 或同時跑兩個模型）、96GB+ 對寫 code 場景多半過度配置。MLX 等 framework 利用 UMA 的方式跟 Metal backend 略有差異、但對使用者都透明、選伺服器時無需考量 UMA 細節。</p>
]]></content:encoded></item><item><title>GNU Stow</title><link>https://tarrragon.github.io/blog/linux/dotfile/knowledge-cards/gnu-stow/</link><pubDate>Mon, 29 Jun 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/linux/dotfile/knowledge-cards/gnu-stow/</guid><description>&lt;p>GNU Stow 是一個 symlink farm manager，原本設計給軟體安裝用（把 &lt;code>/usr/local/stow/program/&lt;/code> 下的檔案 symlink 到 &lt;code>/usr/local/&lt;/code>），在 dotfile 管理場景被借來做「把 repo 裡的配置檔 symlink 到家目錄」。&lt;/p>
&lt;h2 id="核心規則">核心規則&lt;/h2>
&lt;p>Stow 的核心規則只有一條：&lt;strong>package 目錄內的路徑結構，就是安裝後相對於目標目錄的路徑結構&lt;/strong>。&lt;/p>





&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-text" data-lang="text">&lt;span class="line">&lt;span class="ln">1&lt;/span>&lt;span class="cl">~/dotfiles/zsh/.zshrc → ~/.zshrc
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">2&lt;/span>&lt;span class="cl">~/dotfiles/nvim/.config/nvim/ → ~/.config/nvim/
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">3&lt;/span>&lt;span class="cl">~/dotfiles/git/.gitconfig → ~/.gitconfig&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>每個頂層目錄（&lt;code>zsh/&lt;/code>、&lt;code>nvim/&lt;/code>、&lt;code>git/&lt;/code>）是一個 stow package，可以獨立安裝或移除。&lt;/p>
&lt;h2 id="常用指令">常用指令&lt;/h2>





&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-bash" data-lang="bash">&lt;span class="line">&lt;span class="ln"> 1&lt;/span>&lt;span class="cl">&lt;span class="nb">cd&lt;/span> ~/dotfiles
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 2&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 3&lt;/span>&lt;span class="cl">&lt;span class="c1"># 安裝：在目標目錄（預設 $HOME 的上一層，通常用 --target）建立 symlink&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 4&lt;/span>&lt;span class="cl">stow zsh &lt;span class="c1"># 安裝 zsh package&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 5&lt;/span>&lt;span class="cl">stow zsh git nvim tmux &lt;span class="c1"># 批次安裝多個 package&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 6&lt;/span>&lt;span class="cl">stow */ &lt;span class="c1"># 安裝所有 package&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 7&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 8&lt;/span>&lt;span class="cl">&lt;span class="c1"># 移除：刪除該 package 建立的 symlink&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 9&lt;/span>&lt;span class="cl">stow -D nvim
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">10&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">11&lt;/span>&lt;span class="cl">&lt;span class="c1"># 重新安裝（移除 + 安裝）&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">12&lt;/span>&lt;span class="cl">stow -R zsh
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">13&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">14&lt;/span>&lt;span class="cl">&lt;span class="c1"># 收養：如果目標位置已有檔案，--adopt 把它移進 repo 再建 symlink&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">15&lt;/span>&lt;span class="cl">stow --adopt zsh&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>&lt;code>--adopt&lt;/code> 是首次把現有配置納入 dotfile 管理時的關鍵操作——它把家目錄的既有檔案「收養」進 repo（移動過去），然後建 symlink。之後 &lt;code>git diff&lt;/code> 就能看到 repo 版本跟原版的差異。&lt;/p>
&lt;h2 id="folding-與-unfolding">Folding 與 Unfolding&lt;/h2>
&lt;p>Stow 會自動判斷要 symlink 整個目錄還是逐一 symlink 檔案：&lt;/p>
&lt;ul>
&lt;li>&lt;strong>Folding&lt;/strong>：目標目錄不存在、或目錄內所有檔案都由同一個 package 管理 → symlink 整個目錄&lt;/li>
&lt;li>&lt;strong>Unfolding&lt;/strong>：目標目錄已有其他來源的檔案 → 展開成逐檔 symlink，保留既有檔案不受影響&lt;/li>
&lt;/ul>
&lt;p>這個機制讓多個 package 可以共存於同一個目標目錄（如 &lt;code>~/.config/&lt;/code>）。&lt;/p>
&lt;h2 id="限制">限制&lt;/h2>
&lt;ul>
&lt;li>只管 symlink 映射，不管套件安裝（套件由 Brewfile 或 packages.txt 處理）&lt;/li>
&lt;li>不管 file permission——需要 0600 的 secret 檔靠 symlink 繼承來源權限，無法在部署時自動 chmod&lt;/li>
&lt;li>沒有 template 機制——同一份配置在不同機器要不同內容時，需要在配置檔內用 shell 的 OS 判斷處理&lt;/li>
&lt;/ul>
&lt;p>完整選型比較見&lt;a href="https://tarrragon.github.io/blog/linux/dotfile/01-dotfile-management/management-strategies/" data-link-title="管理策略與選型" data-link-desc="要選 dotfile 管理工具時回來讀 — bare repo、stow、chezmoi 的適用場景與選型判讀">管理策略與選型&lt;/a>。&lt;/p></description><content:encoded><![CDATA[<p>GNU Stow 是一個 symlink farm manager，原本設計給軟體安裝用（把 <code>/usr/local/stow/program/</code> 下的檔案 symlink 到 <code>/usr/local/</code>），在 dotfile 管理場景被借來做「把 repo 裡的配置檔 symlink 到家目錄」。</p>
<h2 id="核心規則">核心規則</h2>
<p>Stow 的核心規則只有一條：<strong>package 目錄內的路徑結構，就是安裝後相對於目標目錄的路徑結構</strong>。</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="ln">1</span><span class="cl">~/dotfiles/zsh/.zshrc          → ~/.zshrc
</span></span><span class="line"><span class="ln">2</span><span class="cl">~/dotfiles/nvim/.config/nvim/  → ~/.config/nvim/
</span></span><span class="line"><span class="ln">3</span><span class="cl">~/dotfiles/git/.gitconfig      → ~/.gitconfig</span></span></code></pre></div><p>每個頂層目錄（<code>zsh/</code>、<code>nvim/</code>、<code>git/</code>）是一個 stow package，可以獨立安裝或移除。</p>
<h2 id="常用指令">常用指令</h2>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="ln"> 1</span><span class="cl"><span class="nb">cd</span> ~/dotfiles
</span></span><span class="line"><span class="ln"> 2</span><span class="cl">
</span></span><span class="line"><span class="ln"> 3</span><span class="cl"><span class="c1"># 安裝：在目標目錄（預設 $HOME 的上一層，通常用 --target）建立 symlink</span>
</span></span><span class="line"><span class="ln"> 4</span><span class="cl">stow zsh                <span class="c1"># 安裝 zsh package</span>
</span></span><span class="line"><span class="ln"> 5</span><span class="cl">stow zsh git nvim tmux  <span class="c1"># 批次安裝多個 package</span>
</span></span><span class="line"><span class="ln"> 6</span><span class="cl">stow */                 <span class="c1"># 安裝所有 package</span>
</span></span><span class="line"><span class="ln"> 7</span><span class="cl">
</span></span><span class="line"><span class="ln"> 8</span><span class="cl"><span class="c1"># 移除：刪除該 package 建立的 symlink</span>
</span></span><span class="line"><span class="ln"> 9</span><span class="cl">stow -D nvim
</span></span><span class="line"><span class="ln">10</span><span class="cl">
</span></span><span class="line"><span class="ln">11</span><span class="cl"><span class="c1"># 重新安裝（移除 + 安裝）</span>
</span></span><span class="line"><span class="ln">12</span><span class="cl">stow -R zsh
</span></span><span class="line"><span class="ln">13</span><span class="cl">
</span></span><span class="line"><span class="ln">14</span><span class="cl"><span class="c1"># 收養：如果目標位置已有檔案，--adopt 把它移進 repo 再建 symlink</span>
</span></span><span class="line"><span class="ln">15</span><span class="cl">stow --adopt zsh</span></span></code></pre></div><p><code>--adopt</code> 是首次把現有配置納入 dotfile 管理時的關鍵操作——它把家目錄的既有檔案「收養」進 repo（移動過去），然後建 symlink。之後 <code>git diff</code> 就能看到 repo 版本跟原版的差異。</p>
<h2 id="folding-與-unfolding">Folding 與 Unfolding</h2>
<p>Stow 會自動判斷要 symlink 整個目錄還是逐一 symlink 檔案：</p>
<ul>
<li><strong>Folding</strong>：目標目錄不存在、或目錄內所有檔案都由同一個 package 管理 → symlink 整個目錄</li>
<li><strong>Unfolding</strong>：目標目錄已有其他來源的檔案 → 展開成逐檔 symlink，保留既有檔案不受影響</li>
</ul>
<p>這個機制讓多個 package 可以共存於同一個目標目錄（如 <code>~/.config/</code>）。</p>
<h2 id="限制">限制</h2>
<ul>
<li>只管 symlink 映射，不管套件安裝（套件由 Brewfile 或 packages.txt 處理）</li>
<li>不管 file permission——需要 0600 的 secret 檔靠 symlink 繼承來源權限，無法在部署時自動 chmod</li>
<li>沒有 template 機制——同一份配置在不同機器要不同內容時，需要在配置檔內用 shell 的 OS 判斷處理</li>
</ul>
<p>完整選型比較見<a href="/blog/linux/dotfile/01-dotfile-management/management-strategies/" data-link-title="管理策略與選型" data-link-desc="要選 dotfile 管理工具時回來讀 — bare repo、stow、chezmoi 的適用場景與選型判讀">管理策略與選型</a>。</p>
]]></content:encoded></item><item><title>State（IaC 狀態檔）</title><link>https://tarrragon.github.io/blog/infra/knowledge-cards/state/</link><pubDate>Fri, 26 Jun 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/infra/knowledge-cards/state/</guid><description>&lt;p>State 是 IaC 工具用來記錄「上一次 apply 之後，每個資源在雲端長什麼樣」的快照。它的作用是讓工具能算出「程式碼描述的目標」與「雲端上的現況」之間的最小差異。沒有 state，工具每次都得把所有資源重新查一遍才知道該不該動，而且無法分辨「這個資源是我建的、該由我管」還是「別人手動建的、不歸我管」。&lt;/p>
&lt;p>State 裡通常含有資源的真實 ID、相依關係，以及部分敏感屬性（例如資料庫的初始密碼、private key 的輸出值）。這帶來兩條硬邊界：state 不能進 git（含敏感值，推進版控等於把密碼寫進每個 clone 的歷史）、state 不能只放本地（本地 state 的失敗模式是記憶綁在一台筆電上，多人並行 apply 會互相覆蓋）。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>State 是 &lt;a href="https://tarrragon.github.io/blog/infra/knowledge-cards/iac/" data-link-title="Infrastructure as Code (IaC)" data-link-desc="用程式碼描述基礎設施的最終狀態，由工具負責收斂現實與描述的差異">IaC&lt;/a> 的記憶機制。&lt;a href="https://tarrragon.github.io/blog/infra/01-minimal-iac/iac-tool-state-backend/" data-link-title="IaC 工具選型與 state 地基" data-link-desc="Terraform / OpenTofu / CDK / Pulumi 的選型判準，state 作為 IaC 工具對現實的唯一記憶，以及 remote state backend 的自管與託管路線">模組一：最小可行 IaC&lt;/a> 的核心主題就是怎麼把 state 管好——remote backend、加密、鎖機制。State 管不好，後續所有 IaC 操作都建立在不可靠的記憶上。&lt;/p>
&lt;h2 id="可觀察訊號">可觀察訊號&lt;/h2>
&lt;p>State 出問題的訊號包括：&lt;code>terraform plan&lt;/code> 顯示大量非預期的變更（state 與現實不一致）、兩個人同時 apply 後環境出現矛盾狀態、&lt;code>state list&lt;/code> 的資源數與 Console 上看到的不一致。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>管理 state 時要決定：&lt;/p>
&lt;ul>
&lt;li>存放位置：S3 + DynamoDB（自管）vs Terraform Cloud（託管），取捨在維運負擔 vs 控制權&lt;/li>
&lt;li>加密：state 含敏感值，落地加密（S3 SSE）是底線&lt;/li>
&lt;li>版本保留：bucket versioning 讓 state 損壞時能回捲到上一個正確版本&lt;/li>
&lt;li>鎖機制：防止兩個人同時 apply 互相覆蓋&lt;/li>
&lt;li>分割策略：一個大 state vs 多個小 state，取捨在引用便利性 vs 影響範圍控制&lt;/li>
&lt;/ul>
&lt;h2 id="鄰卡">鄰卡&lt;/h2>
&lt;ul>
&lt;li>&lt;a href="https://tarrragon.github.io/blog/infra/knowledge-cards/iac/" data-link-title="Infrastructure as Code (IaC)" data-link-desc="用程式碼描述基礎設施的最終狀態，由工具負責收斂現實與描述的差異">IaC&lt;/a> — state 是 IaC 工具的核心依賴&lt;/li>
&lt;li>&lt;a href="https://tarrragon.github.io/blog/infra/knowledge-cards/drift/" data-link-title="Drift（設定漂移）" data-link-desc="IaC 的 state 與雲端實際狀態之間的不一致，通常因為有人繞過 IaC 直接在 Console 改設定">Drift&lt;/a> — state 與現實的落差&lt;/li>
&lt;/ul></description><content:encoded><![CDATA[<p>State 是 IaC 工具用來記錄「上一次 apply 之後，每個資源在雲端長什麼樣」的快照。它的作用是讓工具能算出「程式碼描述的目標」與「雲端上的現況」之間的最小差異。沒有 state，工具每次都得把所有資源重新查一遍才知道該不該動，而且無法分辨「這個資源是我建的、該由我管」還是「別人手動建的、不歸我管」。</p>
<p>State 裡通常含有資源的真實 ID、相依關係，以及部分敏感屬性（例如資料庫的初始密碼、private key 的輸出值）。這帶來兩條硬邊界：state 不能進 git（含敏感值，推進版控等於把密碼寫進每個 clone 的歷史）、state 不能只放本地（本地 state 的失敗模式是記憶綁在一台筆電上，多人並行 apply 會互相覆蓋）。</p>
<h2 id="概念位置">概念位置</h2>
<p>State 是 <a href="/blog/infra/knowledge-cards/iac/" data-link-title="Infrastructure as Code (IaC)" data-link-desc="用程式碼描述基礎設施的最終狀態，由工具負責收斂現實與描述的差異">IaC</a> 的記憶機制。<a href="/blog/infra/01-minimal-iac/iac-tool-state-backend/" data-link-title="IaC 工具選型與 state 地基" data-link-desc="Terraform / OpenTofu / CDK / Pulumi 的選型判準，state 作為 IaC 工具對現實的唯一記憶，以及 remote state backend 的自管與託管路線">模組一：最小可行 IaC</a> 的核心主題就是怎麼把 state 管好——remote backend、加密、鎖機制。State 管不好，後續所有 IaC 操作都建立在不可靠的記憶上。</p>
<h2 id="可觀察訊號">可觀察訊號</h2>
<p>State 出問題的訊號包括：<code>terraform plan</code> 顯示大量非預期的變更（state 與現實不一致）、兩個人同時 apply 後環境出現矛盾狀態、<code>state list</code> 的資源數與 Console 上看到的不一致。</p>
<h2 id="設計責任">設計責任</h2>
<p>管理 state 時要決定：</p>
<ul>
<li>存放位置：S3 + DynamoDB（自管）vs Terraform Cloud（託管），取捨在維運負擔 vs 控制權</li>
<li>加密：state 含敏感值，落地加密（S3 SSE）是底線</li>
<li>版本保留：bucket versioning 讓 state 損壞時能回捲到上一個正確版本</li>
<li>鎖機制：防止兩個人同時 apply 互相覆蓋</li>
<li>分割策略：一個大 state vs 多個小 state，取捨在引用便利性 vs 影響範圍控制</li>
</ul>
<h2 id="鄰卡">鄰卡</h2>
<ul>
<li><a href="/blog/infra/knowledge-cards/iac/" data-link-title="Infrastructure as Code (IaC)" data-link-desc="用程式碼描述基礎設施的最終狀態，由工具負責收斂現實與描述的差異">IaC</a> — state 是 IaC 工具的核心依賴</li>
<li><a href="/blog/infra/knowledge-cards/drift/" data-link-title="Drift（設定漂移）" data-link-desc="IaC 的 state 與雲端實際狀態之間的不一致，通常因為有人繞過 IaC 直接在 Console 改設定">Drift</a> — state 與現實的落差</li>
</ul>
]]></content:encoded></item><item><title>Vertical SaaS</title><link>https://tarrragon.github.io/blog/business/knowledge-cards/vertical-saas/</link><pubDate>Tue, 19 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/business/knowledge-cards/vertical-saas/</guid><description>&lt;p>Vertical SaaS 的核心概念是「服務單一行業的 SaaS」—專做牙醫診所、律師事務所、餐廳 POS、保險經紀人等特定行業的軟體。相對概念是 &lt;a href="https://tarrragon.github.io/blog/business/knowledge-cards/horizontal-saas/" data-link-title="Horizontal SaaS" data-link-desc="說明跨行業通用的 SaaS 模式">Horizontal SaaS&lt;/a>（跨行業通用，例如 Slack、Notion）。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>Vertical SaaS 的設計前提是該行業的工作流程足夠特殊，通用工具解決不了。它的護城河來自對行業 &lt;a href="https://tarrragon.github.io/blog/business/knowledge-cards/tacit-knowledge/" data-link-title="Tacit Knowledge" data-link-desc="說明隱性知識與其作為護城河的價值">隱性知識&lt;/a> 的編碼，不來自技術領先。Vertical SaaS 通常待在 &lt;a href="https://tarrragon.github.io/blog/business/knowledge-cards/niche-market/" data-link-title="Niche Market" data-link-desc="說明利基市場的特性與 SaaS 經濟學">利基市場&lt;/a>—市場天花板低，但 &lt;a href="https://tarrragon.github.io/blog/business/knowledge-cards/retention/" data-link-title="Retention" data-link-desc="說明客戶留存率與其對單位經濟的決定作用">retention&lt;/a> 極高。&lt;/p>
&lt;h2 id="可觀察訊號與例子">可觀察訊號與例子&lt;/h2>
&lt;p>判斷一個產品是不是 Vertical SaaS，看它的功能列表是否包含行業特有概念—例如牙醫 SaaS 會有「治療計畫」「保險理賠申請」「X 光圖檔管理」等通用 SaaS 沒有的模組。客戶教育成本低（醫師看完就知道在做什麼）也是訊號。Procore（建築業）、Toast（餐廳）、Veeva（藥廠）都是 Vertical SaaS 代表。&lt;/p>
&lt;h2 id="判讀方式">判讀方式&lt;/h2>
&lt;p>Vertical SaaS 的優勢是高 &lt;a href="https://tarrragon.github.io/blog/business/knowledge-cards/high-stickiness/" data-link-title="High Stickiness" data-link-desc="說明高黏著度的形成條件">黏著度&lt;/a>、高 &lt;a href="https://tarrragon.github.io/blog/business/knowledge-cards/switching-cost/" data-link-title="Switching Cost" data-link-desc="說明切換成本如何鞏固客戶留存">切換成本&lt;/a>、客戶懂行業；劣勢是市場天花板低，難以擴張到其他行業。AI 時代它面臨「上游 &lt;a href="https://tarrragon.github.io/blog/business/knowledge-cards/valuation-compression/" data-link-title="Valuation Compression" data-link-desc="說明估值壓縮如何影響新創生存">毛利壓縮&lt;/a>」的壓力—因為要付 AI 模型費用給基礎模型供應商，原本接近零的 &lt;a href="https://tarrragon.github.io/blog/business/knowledge-cards/marginal-cost/" data-link-title="Marginal Cost" data-link-desc="說明邊際成本及其對商業模式擴張性的決定作用">邊際成本&lt;/a> 變高，&lt;a href="https://tarrragon.github.io/blog/business/knowledge-cards/valuation/" data-link-title="Valuation" data-link-desc="說明估值的構成與商業判讀作用">估值&lt;/a> 跟著被擠壓。&lt;/p></description><content:encoded><![CDATA[<p>Vertical SaaS 的核心概念是「服務單一行業的 SaaS」—專做牙醫診所、律師事務所、餐廳 POS、保險經紀人等特定行業的軟體。相對概念是 <a href="/blog/business/knowledge-cards/horizontal-saas/" data-link-title="Horizontal SaaS" data-link-desc="說明跨行業通用的 SaaS 模式">Horizontal SaaS</a>（跨行業通用，例如 Slack、Notion）。</p>
<h2 id="概念位置">概念位置</h2>
<p>Vertical SaaS 的設計前提是該行業的工作流程足夠特殊，通用工具解決不了。它的護城河來自對行業 <a href="/blog/business/knowledge-cards/tacit-knowledge/" data-link-title="Tacit Knowledge" data-link-desc="說明隱性知識與其作為護城河的價值">隱性知識</a> 的編碼，不來自技術領先。Vertical SaaS 通常待在 <a href="/blog/business/knowledge-cards/niche-market/" data-link-title="Niche Market" data-link-desc="說明利基市場的特性與 SaaS 經濟學">利基市場</a>—市場天花板低，但 <a href="/blog/business/knowledge-cards/retention/" data-link-title="Retention" data-link-desc="說明客戶留存率與其對單位經濟的決定作用">retention</a> 極高。</p>
<h2 id="可觀察訊號與例子">可觀察訊號與例子</h2>
<p>判斷一個產品是不是 Vertical SaaS，看它的功能列表是否包含行業特有概念—例如牙醫 SaaS 會有「治療計畫」「保險理賠申請」「X 光圖檔管理」等通用 SaaS 沒有的模組。客戶教育成本低（醫師看完就知道在做什麼）也是訊號。Procore（建築業）、Toast（餐廳）、Veeva（藥廠）都是 Vertical SaaS 代表。</p>
<h2 id="判讀方式">判讀方式</h2>
<p>Vertical SaaS 的優勢是高 <a href="/blog/business/knowledge-cards/high-stickiness/" data-link-title="High Stickiness" data-link-desc="說明高黏著度的形成條件">黏著度</a>、高 <a href="/blog/business/knowledge-cards/switching-cost/" data-link-title="Switching Cost" data-link-desc="說明切換成本如何鞏固客戶留存">切換成本</a>、客戶懂行業；劣勢是市場天花板低，難以擴張到其他行業。AI 時代它面臨「上游 <a href="/blog/business/knowledge-cards/valuation-compression/" data-link-title="Valuation Compression" data-link-desc="說明估值壓縮如何影響新創生存">毛利壓縮</a>」的壓力—因為要付 AI 模型費用給基礎模型供應商，原本接近零的 <a href="/blog/business/knowledge-cards/marginal-cost/" data-link-title="Marginal Cost" data-link-desc="說明邊際成本及其對商業模式擴張性的決定作用">邊際成本</a> 變高，<a href="/blog/business/knowledge-cards/valuation/" data-link-title="Valuation" data-link-desc="說明估值的構成與商業判讀作用">估值</a> 跟著被擠壓。</p>
]]></content:encoded></item><item><title>Rice（桌面視覺客製化）</title><link>https://tarrragon.github.io/blog/linux/dotfile/knowledge-cards/rice/</link><pubDate>Mon, 29 Jun 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/linux/dotfile/knowledge-cards/rice/</guid><description>&lt;p>Rice 在 Linux 桌面社群指的是&lt;strong>桌面視覺客製化&lt;/strong>——把系統外觀調教成個人化的美學呈現。動詞 ricing 是「正在美化桌面」，名詞 a rice 是「一套美化成果/配置」，做這件事的人叫 ricer。&lt;/p>
&lt;h2 id="詞源">詞源&lt;/h2>
&lt;p>最被廣泛接受的說法是源自汽車改裝文化的 &amp;ldquo;rice burner&amp;rdquo; / &amp;ldquo;ricer&amp;rdquo;——原本指對（通常是日系的）平價車裝上浮誇外觀套件（大尾翼、炫光、貼紙），看起來拉風但實際性能沒提升。後來 Linux 社群借用這個概念：把桌面打扮得花俏好看，本質也是「外觀的炫技」。&lt;/p>
&lt;p>也有人提出 &amp;ldquo;Race Inspired Cosmetic Enhancements&amp;rdquo; 的逆向縮寫，但普遍被認為是事後湊的解釋。&lt;/p>
&lt;p>在 Linux 圈裡，rice 的原始貶意和種族色彩已經淡化，變成中性甚至帶自豪的自稱——r/unixporn 社群就是圍繞 ricing 成果的分享運轉的。&lt;/p>
&lt;h2 id="rice-涵蓋的範圍">Rice 涵蓋的範圍&lt;/h2>
&lt;ul>
&lt;li>&lt;strong>配色方案&lt;/strong>：Catppuccin、Tokyo Night、Gruvbox、Nord 等跨工具統一的色彩定義&lt;/li>
&lt;li>&lt;strong>狀態列&lt;/strong>：Waybar、Eww 的模組設計和 CSS 外觀&lt;/li>
&lt;li>&lt;strong>啟動器&lt;/strong>：Wofi、Rofi 的搜尋框外觀&lt;/li>
&lt;li>&lt;strong>通知&lt;/strong>：Mako、Dunst 的通知氣泡樣式&lt;/li>
&lt;li>&lt;strong>鎖屏&lt;/strong>：Hyprlock 的登入畫面設計&lt;/li>
&lt;li>&lt;strong>桌布&lt;/strong>：靜態桌布或動態桌布（Swww）&lt;/li>
&lt;li>&lt;strong>終端機配色&lt;/strong>：Alacritty / Kitty / Foot 的 ANSI 色碼&lt;/li>
&lt;li>&lt;strong>字型&lt;/strong>：Nerd Font 的 icon glyph&lt;/li>
&lt;/ul>
&lt;p>Caelestia 這類「desktop shell」專案把上述元件統一設計出貨，是「打包好的 rice」。手動逐一挑選和調教各元件是「DIY rice」。兩者的目標相同——視覺上協調、好看、符合個人美學。&lt;/p>
&lt;p>完整的 rice 配置實務見&lt;a href="https://tarrragon.github.io/blog/linux/dotfile/06-rice-design/" data-link-title="模組六：桌面 Rice 設計" data-link-desc="Hyprland 桌面從能用到好看好用 — 狀態列、啟動器、通知、鎖屏、配色系統的設計與配置">桌面 Rice 設計&lt;/a>。&lt;/p></description><content:encoded><![CDATA[<p>Rice 在 Linux 桌面社群指的是<strong>桌面視覺客製化</strong>——把系統外觀調教成個人化的美學呈現。動詞 ricing 是「正在美化桌面」，名詞 a rice 是「一套美化成果/配置」，做這件事的人叫 ricer。</p>
<h2 id="詞源">詞源</h2>
<p>最被廣泛接受的說法是源自汽車改裝文化的 &ldquo;rice burner&rdquo; / &ldquo;ricer&rdquo;——原本指對（通常是日系的）平價車裝上浮誇外觀套件（大尾翼、炫光、貼紙），看起來拉風但實際性能沒提升。後來 Linux 社群借用這個概念：把桌面打扮得花俏好看，本質也是「外觀的炫技」。</p>
<p>也有人提出 &ldquo;Race Inspired Cosmetic Enhancements&rdquo; 的逆向縮寫，但普遍被認為是事後湊的解釋。</p>
<p>在 Linux 圈裡，rice 的原始貶意和種族色彩已經淡化，變成中性甚至帶自豪的自稱——r/unixporn 社群就是圍繞 ricing 成果的分享運轉的。</p>
<h2 id="rice-涵蓋的範圍">Rice 涵蓋的範圍</h2>
<ul>
<li><strong>配色方案</strong>：Catppuccin、Tokyo Night、Gruvbox、Nord 等跨工具統一的色彩定義</li>
<li><strong>狀態列</strong>：Waybar、Eww 的模組設計和 CSS 外觀</li>
<li><strong>啟動器</strong>：Wofi、Rofi 的搜尋框外觀</li>
<li><strong>通知</strong>：Mako、Dunst 的通知氣泡樣式</li>
<li><strong>鎖屏</strong>：Hyprlock 的登入畫面設計</li>
<li><strong>桌布</strong>：靜態桌布或動態桌布（Swww）</li>
<li><strong>終端機配色</strong>：Alacritty / Kitty / Foot 的 ANSI 色碼</li>
<li><strong>字型</strong>：Nerd Font 的 icon glyph</li>
</ul>
<p>Caelestia 這類「desktop shell」專案把上述元件統一設計出貨，是「打包好的 rice」。手動逐一挑選和調教各元件是「DIY rice」。兩者的目標相同——視覺上協調、好看、符合個人美學。</p>
<p>完整的 rice 配置實務見<a href="/blog/linux/dotfile/06-rice-design/" data-link-title="模組六：桌面 Rice 設計" data-link-desc="Hyprland 桌面從能用到好看好用 — 狀態列、啟動器、通知、鎖屏、配色系統的設計與配置">桌面 Rice 設計</a>。</p>
]]></content:encoded></item><item><title>Drift（設定漂移）</title><link>https://tarrragon.github.io/blog/infra/knowledge-cards/drift/</link><pubDate>Fri, 26 Jun 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/infra/knowledge-cards/drift/</guid><description>&lt;p>Drift 指的是 IaC 的 &lt;a href="https://tarrragon.github.io/blog/infra/knowledge-cards/state/" data-link-title="State（IaC 狀態檔）" data-link-desc="IaC 工具用來記錄每個納管資源在雲端真實樣貌的快照，是比對差異與排定操作順序的依據">state&lt;/a> 記錄與雲端上的實際資源狀態之間的不一致。最常見的來源是有人繞過 IaC、直接在 Console 手動修改資源設定——state 不知道這次改動發生了，下一次 &lt;code>plan&lt;/code> 時工具會把手動改的設定判定為「不在我的記憶裡、要修正回程式碼的版本」。&lt;/p>
&lt;p>Drift 的代價會延遲浮現。手動改的當下看起來沒問題——設定改了、服務正常。問題出在後續某次不相關的 &lt;code>apply&lt;/code>：工具用過時的 state 去比對，把手動改的設定覆蓋掉，服務因此斷線，而且在 PR 裡看不到這件事發生過。Drift 累積越多，每次 &lt;code>apply&lt;/code> 的不確定性越高，最終團隊會開始害怕跑 &lt;code>apply&lt;/code>，IaC 名存實亡。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>Drift 是 Console 唯讀鐵律存在的根本理由。&lt;a href="https://tarrragon.github.io/blog/infra/01-minimal-iac/console-readonly-minimal-viable/" data-link-title="Console 唯讀鐵律與最小可行資源集合" data-link-desc="Console 只用來看不用來改的操作紀律、drift 的延遲浮現與偵測，以及能跑出第一個完整 apply 迴路的最小資源集合">模組一：Console 唯讀鐵律&lt;/a>用權限機制（人類身分唯讀、寫入權限留給自動化身分）讓「在 Console 改不動」成為預設狀態，從源頭消除 drift 的產生。&lt;/p>
&lt;h2 id="可觀察訊號">可觀察訊號&lt;/h2>
&lt;p>Drift 存在的訊號：&lt;code>terraform plan&lt;/code> 在沒人改過程式碼的情況下顯示變更（代表有人在 Console 動了東西）、團隊開始說「跑 plan 前先看看有沒有奇怪的差異」、某次例行 apply 意外改掉了不該改的設定。&lt;/p>
&lt;p>偵測 drift 的主動方式是定期跑 &lt;code>terraform plan&lt;/code> 但不 apply，把 diff 輸出當成 drift 偵測的報告。Terraform Cloud 有內建的 drift detection 功能，定期比對 state 與雲端現實。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>處理 drift 時要決定：&lt;/p>
&lt;ul>
&lt;li>偵測頻率：每次 PR 觸發 plan（被動偵測）vs 定期排程 plan（主動偵測）&lt;/li>
&lt;li>修正方向：把雲端改回程式碼的版本（&lt;code>apply&lt;/code>），還是把程式碼改成雲端的版本（更新 HCL）——取捨在「程式碼是 source of truth」vs「手動改的設定有它的理由」&lt;/li>
&lt;li>預防機制：Console 唯讀權限、CI gate 攔截未經 review 的 apply&lt;/li>
&lt;/ul>
&lt;h2 id="鄰卡">鄰卡&lt;/h2>
&lt;ul>
&lt;li>&lt;a href="https://tarrragon.github.io/blog/infra/knowledge-cards/state/" data-link-title="State（IaC 狀態檔）" data-link-desc="IaC 工具用來記錄每個納管資源在雲端真實樣貌的快照，是比對差異與排定操作順序的依據">State&lt;/a> — drift 是 state 與現實的落差&lt;/li>
&lt;li>&lt;a href="https://tarrragon.github.io/blog/infra/knowledge-cards/iac/" data-link-title="Infrastructure as Code (IaC)" data-link-desc="用程式碼描述基礎設施的最終狀態，由工具負責收斂現實與描述的差異">IaC&lt;/a> — drift 破壞 IaC 的 source of truth 地位&lt;/li>
&lt;/ul></description><content:encoded><![CDATA[<p>Drift 指的是 IaC 的 <a href="/blog/infra/knowledge-cards/state/" data-link-title="State（IaC 狀態檔）" data-link-desc="IaC 工具用來記錄每個納管資源在雲端真實樣貌的快照，是比對差異與排定操作順序的依據">state</a> 記錄與雲端上的實際資源狀態之間的不一致。最常見的來源是有人繞過 IaC、直接在 Console 手動修改資源設定——state 不知道這次改動發生了，下一次 <code>plan</code> 時工具會把手動改的設定判定為「不在我的記憶裡、要修正回程式碼的版本」。</p>
<p>Drift 的代價會延遲浮現。手動改的當下看起來沒問題——設定改了、服務正常。問題出在後續某次不相關的 <code>apply</code>：工具用過時的 state 去比對，把手動改的設定覆蓋掉，服務因此斷線，而且在 PR 裡看不到這件事發生過。Drift 累積越多，每次 <code>apply</code> 的不確定性越高，最終團隊會開始害怕跑 <code>apply</code>，IaC 名存實亡。</p>
<h2 id="概念位置">概念位置</h2>
<p>Drift 是 Console 唯讀鐵律存在的根本理由。<a href="/blog/infra/01-minimal-iac/console-readonly-minimal-viable/" data-link-title="Console 唯讀鐵律與最小可行資源集合" data-link-desc="Console 只用來看不用來改的操作紀律、drift 的延遲浮現與偵測，以及能跑出第一個完整 apply 迴路的最小資源集合">模組一：Console 唯讀鐵律</a>用權限機制（人類身分唯讀、寫入權限留給自動化身分）讓「在 Console 改不動」成為預設狀態，從源頭消除 drift 的產生。</p>
<h2 id="可觀察訊號">可觀察訊號</h2>
<p>Drift 存在的訊號：<code>terraform plan</code> 在沒人改過程式碼的情況下顯示變更（代表有人在 Console 動了東西）、團隊開始說「跑 plan 前先看看有沒有奇怪的差異」、某次例行 apply 意外改掉了不該改的設定。</p>
<p>偵測 drift 的主動方式是定期跑 <code>terraform plan</code> 但不 apply，把 diff 輸出當成 drift 偵測的報告。Terraform Cloud 有內建的 drift detection 功能，定期比對 state 與雲端現實。</p>
<h2 id="設計責任">設計責任</h2>
<p>處理 drift 時要決定：</p>
<ul>
<li>偵測頻率：每次 PR 觸發 plan（被動偵測）vs 定期排程 plan（主動偵測）</li>
<li>修正方向：把雲端改回程式碼的版本（<code>apply</code>），還是把程式碼改成雲端的版本（更新 HCL）——取捨在「程式碼是 source of truth」vs「手動改的設定有它的理由」</li>
<li>預防機制：Console 唯讀權限、CI gate 攔截未經 review 的 apply</li>
</ul>
<h2 id="鄰卡">鄰卡</h2>
<ul>
<li><a href="/blog/infra/knowledge-cards/state/" data-link-title="State（IaC 狀態檔）" data-link-desc="IaC 工具用來記錄每個納管資源在雲端真實樣貌的快照，是比對差異與排定操作順序的依據">State</a> — drift 是 state 與現實的落差</li>
<li><a href="/blog/infra/knowledge-cards/iac/" data-link-title="Infrastructure as Code (IaC)" data-link-desc="用程式碼描述基礎設施的最終狀態，由工具負責收斂現實與描述的差異">IaC</a> — drift 破壞 IaC 的 source of truth 地位</li>
</ul>
]]></content:encoded></item><item><title>Horizontal SaaS</title><link>https://tarrragon.github.io/blog/business/knowledge-cards/horizontal-saas/</link><pubDate>Tue, 19 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/business/knowledge-cards/horizontal-saas/</guid><description>&lt;p>Horizontal SaaS 的核心概念是「跨行業通用的 SaaS」—不分產業都能用，例如 Slack（溝通）、Notion（文件）、Zoom（會議）、Salesforce（CRM）。相對概念是 &lt;a href="https://tarrragon.github.io/blog/business/knowledge-cards/vertical-saas/" data-link-title="Vertical SaaS" data-link-desc="說明專做單一行業的 SaaS 與其競爭策略">Vertical SaaS&lt;/a>。Horizontal SaaS 依賴 &lt;a href="https://tarrragon.github.io/blog/business/knowledge-cards/distribution/" data-link-title="Distribution" data-link-desc="說明分發優勢作為現有玩家的核心護城河">分發優勢&lt;/a> 與網絡效應做護城河。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>Horizontal SaaS 的設計前提是有一個通用工作流程（溝通、寫文件、開會、管理客戶）跨產業都有需求。它不靠行業 &lt;a href="https://tarrragon.github.io/blog/business/knowledge-cards/tacit-knowledge/" data-link-title="Tacit Knowledge" data-link-desc="說明隱性知識與其作為護城河的價值">隱性知識&lt;/a> 做護城河，而是靠普及度、整合生態系與 &lt;a href="https://tarrragon.github.io/blog/business/knowledge-cards/distribution/" data-link-title="Distribution" data-link-desc="說明分發優勢作為現有玩家的核心護城河">分發&lt;/a> 規模。&lt;/p>
&lt;h2 id="可觀察訊號與例子">可觀察訊號與例子&lt;/h2>
&lt;p>Horizontal SaaS 的客戶名單通常涵蓋從新創到財星 500 的各種行業；功能列表是「給所有人都能用的工具集」而非特定行業流程。Slack 的客戶包括醫院、銀行、廣告公司、遊戲工作室—這就是 horizontal 的訊號。它通常走 &lt;a href="https://tarrragon.github.io/blog/business/knowledge-cards/plg/" data-link-title="PLG" data-link-desc="說明產品自助成長模式與其經濟前提">PLG&lt;/a> 上手，因為產品要簡單到任何行業的人都能用。&lt;/p>
&lt;h2 id="判讀方式">判讀方式&lt;/h2>
&lt;p>Horizontal SaaS 的優勢是市場天花板高、可以走 &lt;a href="https://tarrragon.github.io/blog/business/knowledge-cards/plg/" data-link-title="PLG" data-link-desc="說明產品自助成長模式與其經濟前提">PLG&lt;/a> 快速擴張；劣勢是面對特定行業的對手（&lt;a href="https://tarrragon.github.io/blog/business/knowledge-cards/vertical-saas/" data-link-title="Vertical SaaS" data-link-desc="說明專做單一行業的 SaaS 與其競爭策略">Vertical SaaS&lt;/a>）容易被打—因為通用工具不會比專做這行的軟體更貼合該行業的工作流程。Big Tech（Microsoft、Google）做 horizontal SaaS 最有 &lt;a href="https://tarrragon.github.io/blog/business/knowledge-cards/distribution/" data-link-title="Distribution" data-link-desc="說明分發優勢作為現有玩家的核心護城河">分發優勢&lt;/a>，新創很難正面對抗。&lt;/p></description><content:encoded><![CDATA[<p>Horizontal SaaS 的核心概念是「跨行業通用的 SaaS」—不分產業都能用，例如 Slack（溝通）、Notion（文件）、Zoom（會議）、Salesforce（CRM）。相對概念是 <a href="/blog/business/knowledge-cards/vertical-saas/" data-link-title="Vertical SaaS" data-link-desc="說明專做單一行業的 SaaS 與其競爭策略">Vertical SaaS</a>。Horizontal SaaS 依賴 <a href="/blog/business/knowledge-cards/distribution/" data-link-title="Distribution" data-link-desc="說明分發優勢作為現有玩家的核心護城河">分發優勢</a> 與網絡效應做護城河。</p>
<h2 id="概念位置">概念位置</h2>
<p>Horizontal SaaS 的設計前提是有一個通用工作流程（溝通、寫文件、開會、管理客戶）跨產業都有需求。它不靠行業 <a href="/blog/business/knowledge-cards/tacit-knowledge/" data-link-title="Tacit Knowledge" data-link-desc="說明隱性知識與其作為護城河的價值">隱性知識</a> 做護城河，而是靠普及度、整合生態系與 <a href="/blog/business/knowledge-cards/distribution/" data-link-title="Distribution" data-link-desc="說明分發優勢作為現有玩家的核心護城河">分發</a> 規模。</p>
<h2 id="可觀察訊號與例子">可觀察訊號與例子</h2>
<p>Horizontal SaaS 的客戶名單通常涵蓋從新創到財星 500 的各種行業；功能列表是「給所有人都能用的工具集」而非特定行業流程。Slack 的客戶包括醫院、銀行、廣告公司、遊戲工作室—這就是 horizontal 的訊號。它通常走 <a href="/blog/business/knowledge-cards/plg/" data-link-title="PLG" data-link-desc="說明產品自助成長模式與其經濟前提">PLG</a> 上手，因為產品要簡單到任何行業的人都能用。</p>
<h2 id="判讀方式">判讀方式</h2>
<p>Horizontal SaaS 的優勢是市場天花板高、可以走 <a href="/blog/business/knowledge-cards/plg/" data-link-title="PLG" data-link-desc="說明產品自助成長模式與其經濟前提">PLG</a> 快速擴張；劣勢是面對特定行業的對手（<a href="/blog/business/knowledge-cards/vertical-saas/" data-link-title="Vertical SaaS" data-link-desc="說明專做單一行業的 SaaS 與其競爭策略">Vertical SaaS</a>）容易被打—因為通用工具不會比專做這行的軟體更貼合該行業的工作流程。Big Tech（Microsoft、Google）做 horizontal SaaS 最有 <a href="/blog/business/knowledge-cards/distribution/" data-link-title="Distribution" data-link-desc="說明分發優勢作為現有玩家的核心護城河">分發優勢</a>，新創很難正面對抗。</p>
]]></content:encoded></item><item><title>VPC（Virtual Private Cloud）</title><link>https://tarrragon.github.io/blog/infra/knowledge-cards/vpc/</link><pubDate>Fri, 26 Jun 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/infra/knowledge-cards/vpc/</guid><description>&lt;p>VPC（Virtual Private Cloud）是雲端帳號內的一塊邏輯隔離私有網段，是其餘所有網路切分的起點。在 VPC 裡開出來的所有資源預設只看得到同一個 VPC 內的成員，與其他 VPC、與其他帳號的網路天然隔離。沒有 VPC，&lt;a href="https://tarrragon.github.io/blog/infra/knowledge-cards/subnet/" data-link-title="Subnet（子網路）" data-link-desc="VPC 內按可用區與暴露程度切出的子網段，決定資源有沒有一條通往網際網路的路徑">subnet&lt;/a> 與 &lt;a href="https://tarrragon.github.io/blog/infra/knowledge-cards/security-group/" data-link-title="Security Group" data-link-desc="掛在資源網卡層級的有狀態防火牆，逐埠決定哪些來源能連進這個資源">security group&lt;/a> 無處依附。&lt;/p>
&lt;p>VPC 用 &lt;a href="https://tarrragon.github.io/blog/infra/knowledge-cards/cidr/" data-link-title="CIDR（Classless Inter-Domain Routing）" data-link-desc="用前綴長度表示 IP 地址範圍的表示法，決定 VPC 與 subnet 的地址空間大小">CIDR&lt;/a> 區塊定義地址空間。建立時的 CIDR 大小是一次性決策——事後擴張地址空間在多數雲端平台上是麻煩且容易出錯的操作（AWS 允許追加 secondary CIDR，但追加的網段在 routing 與服務相容性上有限制）。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>VPC 是&lt;a href="https://tarrragon.github.io/blog/infra/03-network-foundation/vpc-subnet-security-group/" data-link-title="網路地基 — VPC、subnet 分層與 security group 設計" data-link-desc="VPC CIDR 規劃、public / private subnet 切分、route table 與 NAT 的可用性成本取捨、security group 最小開放設計，以及 NACL 的定位">模組三：網路地基&lt;/a>的最外層邊界。Infra 系列的網路設計從 VPC 開始：先圈定地址空間，再往內切 subnet、掛 route table、設 security group。環境之間的 VPC 怎麼分（每個環境一個 VPC），屬於&lt;a href="https://tarrragon.github.io/blog/infra/04-environment-separation/directory-module-parameterization/" data-link-title="環境分離與模組化 — 目錄結構、module 參數化與 retrofit 路徑" data-link-desc="用目錄結構在第一天就隔開 dev 與 prod 的 state，用 module 讓環境共用同一套邏輯只差參數，以及已經單環境跑起來後怎麼安全拆分">模組四：環境分離&lt;/a>的設計決策。&lt;/p>
&lt;h2 id="可觀察訊號">可觀察訊號&lt;/h2>
&lt;p>VPC 設計需要關注的訊號：CIDR 空間快用完（subnet 切不出新的子網段）、需要跟其他 VPC 或地端互連時發現 CIDR 重疊（peering 無法建立）、服務被放在預設 VPC 裡（預設 VPC 是所有人共享的、CIDR 不可控的、security group 預設全通的）。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>規劃 VPC 時要決定：&lt;/p>
&lt;ul>
&lt;li>CIDR 大小：&lt;code>/16&lt;/code> 提供約六萬五千個位址，對多數單一環境足夠&lt;/li>
&lt;li>不重疊：多個 VPC（不同環境或產品線）用連續但不重疊的大段分配&lt;/li>
&lt;li>DNS 設定：&lt;code>enable_dns_support&lt;/code> 和 &lt;code>enable_dns_hostnames&lt;/code> 在多數場景都該開啟&lt;/li>
&lt;li>預設 VPC 的處理：正式服務不該放在預設 VPC，新帳號的預設 VPC 可以刪除或保留唯讀&lt;/li>
&lt;/ul>
&lt;h2 id="鄰卡">鄰卡&lt;/h2>
&lt;ul>
&lt;li>&lt;a href="https://tarrragon.github.io/blog/infra/knowledge-cards/subnet/" data-link-title="Subnet（子網路）" data-link-desc="VPC 內按可用區與暴露程度切出的子網段，決定資源有沒有一條通往網際網路的路徑">Subnet&lt;/a> — VPC 內按可用區與暴露程度切出的子網段&lt;/li>
&lt;li>&lt;a href="https://tarrragon.github.io/blog/infra/knowledge-cards/security-group/" data-link-title="Security Group" data-link-desc="掛在資源網卡層級的有狀態防火牆，逐埠決定哪些來源能連進這個資源">Security Group&lt;/a> — 掛在資源上的有狀態防火牆&lt;/li>
&lt;li>&lt;a href="https://tarrragon.github.io/blog/infra/knowledge-cards/cidr/" data-link-title="CIDR（Classless Inter-Domain Routing）" data-link-desc="用前綴長度表示 IP 地址範圍的表示法，決定 VPC 與 subnet 的地址空間大小">CIDR&lt;/a> — VPC 的地址空間定義方式&lt;/li>
&lt;li>&lt;a href="https://tarrragon.github.io/blog/infra/knowledge-cards/nat/" data-link-title="NAT Gateway" data-link-desc="讓 private subnet 的資源主動對外連線、同時不被外部入站觸及的網路地址轉換服務">NAT&lt;/a> — 讓 private subnet 出站的地址轉換機制&lt;/li>
&lt;/ul></description><content:encoded><![CDATA[<p>VPC（Virtual Private Cloud）是雲端帳號內的一塊邏輯隔離私有網段，是其餘所有網路切分的起點。在 VPC 裡開出來的所有資源預設只看得到同一個 VPC 內的成員，與其他 VPC、與其他帳號的網路天然隔離。沒有 VPC，<a href="/blog/infra/knowledge-cards/subnet/" data-link-title="Subnet（子網路）" data-link-desc="VPC 內按可用區與暴露程度切出的子網段，決定資源有沒有一條通往網際網路的路徑">subnet</a> 與 <a href="/blog/infra/knowledge-cards/security-group/" data-link-title="Security Group" data-link-desc="掛在資源網卡層級的有狀態防火牆，逐埠決定哪些來源能連進這個資源">security group</a> 無處依附。</p>
<p>VPC 用 <a href="/blog/infra/knowledge-cards/cidr/" data-link-title="CIDR（Classless Inter-Domain Routing）" data-link-desc="用前綴長度表示 IP 地址範圍的表示法，決定 VPC 與 subnet 的地址空間大小">CIDR</a> 區塊定義地址空間。建立時的 CIDR 大小是一次性決策——事後擴張地址空間在多數雲端平台上是麻煩且容易出錯的操作（AWS 允許追加 secondary CIDR，但追加的網段在 routing 與服務相容性上有限制）。</p>
<h2 id="概念位置">概念位置</h2>
<p>VPC 是<a href="/blog/infra/03-network-foundation/vpc-subnet-security-group/" data-link-title="網路地基 — VPC、subnet 分層與 security group 設計" data-link-desc="VPC CIDR 規劃、public / private subnet 切分、route table 與 NAT 的可用性成本取捨、security group 最小開放設計，以及 NACL 的定位">模組三：網路地基</a>的最外層邊界。Infra 系列的網路設計從 VPC 開始：先圈定地址空間，再往內切 subnet、掛 route table、設 security group。環境之間的 VPC 怎麼分（每個環境一個 VPC），屬於<a href="/blog/infra/04-environment-separation/directory-module-parameterization/" data-link-title="環境分離與模組化 — 目錄結構、module 參數化與 retrofit 路徑" data-link-desc="用目錄結構在第一天就隔開 dev 與 prod 的 state，用 module 讓環境共用同一套邏輯只差參數，以及已經單環境跑起來後怎麼安全拆分">模組四：環境分離</a>的設計決策。</p>
<h2 id="可觀察訊號">可觀察訊號</h2>
<p>VPC 設計需要關注的訊號：CIDR 空間快用完（subnet 切不出新的子網段）、需要跟其他 VPC 或地端互連時發現 CIDR 重疊（peering 無法建立）、服務被放在預設 VPC 裡（預設 VPC 是所有人共享的、CIDR 不可控的、security group 預設全通的）。</p>
<h2 id="設計責任">設計責任</h2>
<p>規劃 VPC 時要決定：</p>
<ul>
<li>CIDR 大小：<code>/16</code> 提供約六萬五千個位址，對多數單一環境足夠</li>
<li>不重疊：多個 VPC（不同環境或產品線）用連續但不重疊的大段分配</li>
<li>DNS 設定：<code>enable_dns_support</code> 和 <code>enable_dns_hostnames</code> 在多數場景都該開啟</li>
<li>預設 VPC 的處理：正式服務不該放在預設 VPC，新帳號的預設 VPC 可以刪除或保留唯讀</li>
</ul>
<h2 id="鄰卡">鄰卡</h2>
<ul>
<li><a href="/blog/infra/knowledge-cards/subnet/" data-link-title="Subnet（子網路）" data-link-desc="VPC 內按可用區與暴露程度切出的子網段，決定資源有沒有一條通往網際網路的路徑">Subnet</a> — VPC 內按可用區與暴露程度切出的子網段</li>
<li><a href="/blog/infra/knowledge-cards/security-group/" data-link-title="Security Group" data-link-desc="掛在資源網卡層級的有狀態防火牆，逐埠決定哪些來源能連進這個資源">Security Group</a> — 掛在資源上的有狀態防火牆</li>
<li><a href="/blog/infra/knowledge-cards/cidr/" data-link-title="CIDR（Classless Inter-Domain Routing）" data-link-desc="用前綴長度表示 IP 地址範圍的表示法，決定 VPC 與 subnet 的地址空間大小">CIDR</a> — VPC 的地址空間定義方式</li>
<li><a href="/blog/infra/knowledge-cards/nat/" data-link-title="NAT Gateway" data-link-desc="讓 private subnet 的資源主動對外連線、同時不被外部入站觸及的網路地址轉換服務">NAT</a> — 讓 private subnet 出站的地址轉換機制</li>
</ul>
]]></content:encoded></item><item><title>CDP</title><link>https://tarrragon.github.io/blog/business/knowledge-cards/cdp/</link><pubDate>Tue, 19 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/business/knowledge-cards/cdp/</guid><description>&lt;p>CDP 的核心概念是「Customer Data Platform，客戶資料平台」—把分散在各系統的客戶資料（網站、App、電商、客服、廣告）集中起來，建立統一客戶檔案，給行銷、銷售、客服使用。代表公司是 Segment（已被 Twilio 收購）、mParticle、Tealium。CDP 是「應用層 &lt;a href="https://tarrragon.github.io/blog/business/knowledge-cards/saas/" data-link-title="SaaS" data-link-desc="說明雲端訂閱軟體的商業模式與經濟特徵">SaaS&lt;/a>」的典型代表。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>CDP 位於資料庫與行銷工具之間的整合層，承擔中間的資料整合與啟用平台角色——既非底層基礎設施（如 AWS），也非終端應用（如 Mailchimp）。它常被當成「應用層 SaaS」的代表來跟基礎設施做對比—基礎設施想賺底層資源錢，應用層想賺工作流程錢，兩者邏輯不同。&lt;/p>
&lt;h2 id="可觀察訊號與例子">可觀察訊號與例子&lt;/h2>
&lt;p>CDP 客戶通常是有多個資料來源、又想做精準行銷的中大型企業。判斷某個工具是不是 CDP，看它是否同時做三件事：跨來源資料整合、統一客戶身份識別（identity resolution）、把整合後的資料推送給下游行銷工具。&lt;/p>
&lt;h2 id="判讀方式">判讀方式&lt;/h2>
&lt;p>CDP 是「&lt;a href="https://tarrragon.github.io/blog/business/knowledge-cards/vertical-saas/" data-link-title="Vertical SaaS" data-link-desc="說明專做單一行業的 SaaS 與其競爭策略">垂直 / 應用層 SaaS&lt;/a>」的代表案例—寫商業分析的人常用 CDP 跟 AWS 做對比，說明應用層 SaaS 跟基礎設施的不同。讀到「CDP」這個詞時，注意它通常被當成「特定行業之外的應用層 SaaS 例子」使用，不一定是文章主題。&lt;/p></description><content:encoded><![CDATA[<p>CDP 的核心概念是「Customer Data Platform，客戶資料平台」—把分散在各系統的客戶資料（網站、App、電商、客服、廣告）集中起來，建立統一客戶檔案，給行銷、銷售、客服使用。代表公司是 Segment（已被 Twilio 收購）、mParticle、Tealium。CDP 是「應用層 <a href="/blog/business/knowledge-cards/saas/" data-link-title="SaaS" data-link-desc="說明雲端訂閱軟體的商業模式與經濟特徵">SaaS</a>」的典型代表。</p>
<h2 id="概念位置">概念位置</h2>
<p>CDP 位於資料庫與行銷工具之間的整合層，承擔中間的資料整合與啟用平台角色——既非底層基礎設施（如 AWS），也非終端應用（如 Mailchimp）。它常被當成「應用層 SaaS」的代表來跟基礎設施做對比—基礎設施想賺底層資源錢，應用層想賺工作流程錢，兩者邏輯不同。</p>
<h2 id="可觀察訊號與例子">可觀察訊號與例子</h2>
<p>CDP 客戶通常是有多個資料來源、又想做精準行銷的中大型企業。判斷某個工具是不是 CDP，看它是否同時做三件事：跨來源資料整合、統一客戶身份識別（identity resolution）、把整合後的資料推送給下游行銷工具。</p>
<h2 id="判讀方式">判讀方式</h2>
<p>CDP 是「<a href="/blog/business/knowledge-cards/vertical-saas/" data-link-title="Vertical SaaS" data-link-desc="說明專做單一行業的 SaaS 與其競爭策略">垂直 / 應用層 SaaS</a>」的代表案例—寫商業分析的人常用 CDP 跟 AWS 做對比，說明應用層 SaaS 跟基礎設施的不同。讀到「CDP」這個詞時，注意它通常被當成「特定行業之外的應用層 SaaS 例子」使用，不一定是文章主題。</p>
]]></content:encoded></item><item><title>Subnet（子網路）</title><link>https://tarrragon.github.io/blog/infra/knowledge-cards/subnet/</link><pubDate>Fri, 26 Jun 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/infra/knowledge-cards/subnet/</guid><description>&lt;p>Subnet 是 &lt;a href="https://tarrragon.github.io/blog/infra/knowledge-cards/vpc/" data-link-title="VPC（Virtual Private Cloud）" data-link-desc="雲端帳號內的一塊邏輯隔離私有網段，是所有網路切分的起點與容器">VPC&lt;/a> 內部按可用區（Availability Zone）與暴露程度切出來的子網段。一塊資源對外暴露到什麼程度，取決於它被放進哪個 subnet——技術上的差別在於該 subnet 關聯的 route table 裡有沒有一條指向 Internet Gateway 的預設路由。&lt;/p>
&lt;p>Subnet 分兩類：&lt;/p>
&lt;ul>
&lt;li>&lt;strong>Public subnet&lt;/strong>：route table 有 &lt;code>0.0.0.0/0 → Internet Gateway&lt;/code>，讓資源能被外部 IP 直接觸及。典型住戶是對外負載平衡器、&lt;a href="https://tarrragon.github.io/blog/infra/knowledge-cards/nat/" data-link-title="NAT Gateway" data-link-desc="讓 private subnet 的資源主動對外連線、同時不被外部入站觸及的網路地址轉換服務">NAT&lt;/a> Gateway。&lt;/li>
&lt;li>&lt;strong>Private subnet&lt;/strong>：route table 把 &lt;code>0.0.0.0/0&lt;/code> 指向 NAT Gateway，外部無法主動連入。典型住戶是應用伺服器、資料庫、快取。&lt;/li>
&lt;/ul>
&lt;p>Public subnet 的真實樣貌是「薄薄一層」——它通常只住入口設施，業務邏輯跟資料儲存都在 private subnet。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>Subnet 是&lt;a href="https://tarrragon.github.io/blog/infra/03-network-foundation/vpc-subnet-security-group/" data-link-title="網路地基 — VPC、subnet 分層與 security group 設計" data-link-desc="VPC CIDR 規劃、public / private subnet 切分、route table 與 NAT 的可用性成本取捨、security group 最小開放設計，以及 NACL 的定位">模組三：網路地基&lt;/a>的中層邊界。VPC 定好地址空間後，subnet 決定「哪些資源能被外網碰到、哪些只能在內網存取」。每個 subnet 綁定單一可用區，高可用設計通常是每種角色跨至少兩個可用區各開一個 subnet。&lt;/p>
&lt;h2 id="可觀察訊號">可觀察訊號&lt;/h2>
&lt;p>Subnet 配置有問題的訊號：應用伺服器被放在 public subnet 並配了公網 IP（管理埠暴露在掃描流量下）、private subnet 的服務拉不到外部套件（route table 沒指向健康的 NAT）、新服務上線時找不到適合的 subnet（CIDR 切得太小、空間不夠）。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>規劃 subnet 時要決定：&lt;/p>
&lt;ul>
&lt;li>CIDR 切法：VPC 是 &lt;code>/16&lt;/code> 時，每個 subnet 用 &lt;code>/20&lt;/code>（約四千位址）可以在三個可用區各開 public + private 共六個 subnet&lt;/li>
&lt;li>跨可用區對稱：每種角色至少跨兩個 AZ，讓單一 AZ 故障時另一區能承接&lt;/li>
&lt;li>public 的住戶限制：只放入口設施，業務邏輯一律放 private&lt;/li>
&lt;/ul>
&lt;h2 id="鄰卡">鄰卡&lt;/h2>
&lt;ul>
&lt;li>&lt;a href="https://tarrragon.github.io/blog/infra/knowledge-cards/vpc/" data-link-title="VPC（Virtual Private Cloud）" data-link-desc="雲端帳號內的一塊邏輯隔離私有網段，是所有網路切分的起點與容器">VPC&lt;/a> — subnet 的容器&lt;/li>
&lt;li>&lt;a href="https://tarrragon.github.io/blog/infra/knowledge-cards/nat/" data-link-title="NAT Gateway" data-link-desc="讓 private subnet 的資源主動對外連線、同時不被外部入站觸及的網路地址轉換服務">NAT&lt;/a> — 讓 private subnet 出站的機制&lt;/li>
&lt;li>&lt;a href="https://tarrragon.github.io/blog/infra/knowledge-cards/security-group/" data-link-title="Security Group" data-link-desc="掛在資源網卡層級的有狀態防火牆，逐埠決定哪些來源能連進這個資源">Security Group&lt;/a> — 掛在資源上的埠級存取控制&lt;/li>
&lt;/ul></description><content:encoded><![CDATA[<p>Subnet 是 <a href="/blog/infra/knowledge-cards/vpc/" data-link-title="VPC（Virtual Private Cloud）" data-link-desc="雲端帳號內的一塊邏輯隔離私有網段，是所有網路切分的起點與容器">VPC</a> 內部按可用區（Availability Zone）與暴露程度切出來的子網段。一塊資源對外暴露到什麼程度，取決於它被放進哪個 subnet——技術上的差別在於該 subnet 關聯的 route table 裡有沒有一條指向 Internet Gateway 的預設路由。</p>
<p>Subnet 分兩類：</p>
<ul>
<li><strong>Public subnet</strong>：route table 有 <code>0.0.0.0/0 → Internet Gateway</code>，讓資源能被外部 IP 直接觸及。典型住戶是對外負載平衡器、<a href="/blog/infra/knowledge-cards/nat/" data-link-title="NAT Gateway" data-link-desc="讓 private subnet 的資源主動對外連線、同時不被外部入站觸及的網路地址轉換服務">NAT</a> Gateway。</li>
<li><strong>Private subnet</strong>：route table 把 <code>0.0.0.0/0</code> 指向 NAT Gateway，外部無法主動連入。典型住戶是應用伺服器、資料庫、快取。</li>
</ul>
<p>Public subnet 的真實樣貌是「薄薄一層」——它通常只住入口設施，業務邏輯跟資料儲存都在 private subnet。</p>
<h2 id="概念位置">概念位置</h2>
<p>Subnet 是<a href="/blog/infra/03-network-foundation/vpc-subnet-security-group/" data-link-title="網路地基 — VPC、subnet 分層與 security group 設計" data-link-desc="VPC CIDR 規劃、public / private subnet 切分、route table 與 NAT 的可用性成本取捨、security group 最小開放設計，以及 NACL 的定位">模組三：網路地基</a>的中層邊界。VPC 定好地址空間後，subnet 決定「哪些資源能被外網碰到、哪些只能在內網存取」。每個 subnet 綁定單一可用區，高可用設計通常是每種角色跨至少兩個可用區各開一個 subnet。</p>
<h2 id="可觀察訊號">可觀察訊號</h2>
<p>Subnet 配置有問題的訊號：應用伺服器被放在 public subnet 並配了公網 IP（管理埠暴露在掃描流量下）、private subnet 的服務拉不到外部套件（route table 沒指向健康的 NAT）、新服務上線時找不到適合的 subnet（CIDR 切得太小、空間不夠）。</p>
<h2 id="設計責任">設計責任</h2>
<p>規劃 subnet 時要決定：</p>
<ul>
<li>CIDR 切法：VPC 是 <code>/16</code> 時，每個 subnet 用 <code>/20</code>（約四千位址）可以在三個可用區各開 public + private 共六個 subnet</li>
<li>跨可用區對稱：每種角色至少跨兩個 AZ，讓單一 AZ 故障時另一區能承接</li>
<li>public 的住戶限制：只放入口設施，業務邏輯一律放 private</li>
</ul>
<h2 id="鄰卡">鄰卡</h2>
<ul>
<li><a href="/blog/infra/knowledge-cards/vpc/" data-link-title="VPC（Virtual Private Cloud）" data-link-desc="雲端帳號內的一塊邏輯隔離私有網段，是所有網路切分的起點與容器">VPC</a> — subnet 的容器</li>
<li><a href="/blog/infra/knowledge-cards/nat/" data-link-title="NAT Gateway" data-link-desc="讓 private subnet 的資源主動對外連線、同時不被外部入站觸及的網路地址轉換服務">NAT</a> — 讓 private subnet 出站的機制</li>
<li><a href="/blog/infra/knowledge-cards/security-group/" data-link-title="Security Group" data-link-desc="掛在資源網卡層級的有狀態防火牆，逐埠決定哪些來源能連進這個資源">Security Group</a> — 掛在資源上的埠級存取控制</li>
</ul>
]]></content:encoded></item><item><title>Enterprise License</title><link>https://tarrragon.github.io/blog/business/knowledge-cards/enterprise-license/</link><pubDate>Tue, 19 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/business/knowledge-cards/enterprise-license/</guid><description>&lt;p>Enterprise License 的核心概念是「賣給整家公司的軟體授權」—跟企業簽長期合約，按員工數、用量承諾、整合深度收費，有別於按使用者自助訂閱。ChatGPT Enterprise、Claude Enterprise、Microsoft 365 E5 都是這種模式。它的核心吸引力是極強 &lt;a href="https://tarrragon.github.io/blog/business/knowledge-cards/lock-in/" data-link-title="Lock-in" data-link-desc="說明鎖定效應如何形成護城河">Lock-in&lt;/a>。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>Enterprise License 是 &lt;a href="https://tarrragon.github.io/blog/business/knowledge-cards/saas/" data-link-title="SaaS" data-link-desc="說明雲端訂閱軟體的商業模式與經濟特徵">SaaS&lt;/a> 的高階變體，相對於 &lt;a href="https://tarrragon.github.io/blog/business/knowledge-cards/plg/" data-link-title="PLG" data-link-desc="說明產品自助成長模式與其經濟前提">PLG&lt;/a> 自助訂閱。它的訂價模式不只是「軟體本身」，還包括資料整合、權限管理、安全控管、SLA、專屬支援、長期用量承諾。這些加值內容堆出來的 &lt;a href="https://tarrragon.github.io/blog/business/knowledge-cards/switching-cost/" data-link-title="Switching Cost" data-link-desc="說明切換成本如何鞏固客戶留存">切換成本&lt;/a> 是 lock-in 的具體形式。&lt;/p>
&lt;h2 id="可觀察訊號與例子">可觀察訊號與例子&lt;/h2>
&lt;p>判斷一個產品是不是走 enterprise license 模式，看它的官網是否有「Contact Sales」按鈕但沒有透明定價；客戶是否是百人以上的公司而非個人；合約是否多年期而非月付。Salesforce、Palantir、Snowflake 都是典型例子。AI Labs 近期推出的 Enterprise 版本走的就是這條路。&lt;/p>
&lt;h2 id="判讀方式">判讀方式&lt;/h2>
&lt;p>Enterprise License 對賣方來說每個合約金額大、收入可預測、&lt;a href="https://tarrragon.github.io/blog/business/knowledge-cards/retention/" data-link-title="Retention" data-link-desc="說明客戶留存率與其對單位經濟的決定作用">retention&lt;/a> 接近 100%；對買方來說等於把核心工作流程綁定到單一供應商。AI Labs 的策略重心正是這個—不想只當「按 token 計費的模型供應商」，要直接賣 enterprise license 進企業，藉此建立 &lt;a href="https://tarrragon.github.io/blog/business/knowledge-cards/lock-in/" data-link-title="Lock-in" data-link-desc="說明鎖定效應如何形成護城河">Lock-in&lt;/a> 並穩定營收。&lt;/p></description><content:encoded><![CDATA[<p>Enterprise License 的核心概念是「賣給整家公司的軟體授權」—跟企業簽長期合約，按員工數、用量承諾、整合深度收費，有別於按使用者自助訂閱。ChatGPT Enterprise、Claude Enterprise、Microsoft 365 E5 都是這種模式。它的核心吸引力是極強 <a href="/blog/business/knowledge-cards/lock-in/" data-link-title="Lock-in" data-link-desc="說明鎖定效應如何形成護城河">Lock-in</a>。</p>
<h2 id="概念位置">概念位置</h2>
<p>Enterprise License 是 <a href="/blog/business/knowledge-cards/saas/" data-link-title="SaaS" data-link-desc="說明雲端訂閱軟體的商業模式與經濟特徵">SaaS</a> 的高階變體，相對於 <a href="/blog/business/knowledge-cards/plg/" data-link-title="PLG" data-link-desc="說明產品自助成長模式與其經濟前提">PLG</a> 自助訂閱。它的訂價模式不只是「軟體本身」，還包括資料整合、權限管理、安全控管、SLA、專屬支援、長期用量承諾。這些加值內容堆出來的 <a href="/blog/business/knowledge-cards/switching-cost/" data-link-title="Switching Cost" data-link-desc="說明切換成本如何鞏固客戶留存">切換成本</a> 是 lock-in 的具體形式。</p>
<h2 id="可觀察訊號與例子">可觀察訊號與例子</h2>
<p>判斷一個產品是不是走 enterprise license 模式，看它的官網是否有「Contact Sales」按鈕但沒有透明定價；客戶是否是百人以上的公司而非個人；合約是否多年期而非月付。Salesforce、Palantir、Snowflake 都是典型例子。AI Labs 近期推出的 Enterprise 版本走的就是這條路。</p>
<h2 id="判讀方式">判讀方式</h2>
<p>Enterprise License 對賣方來說每個合約金額大、收入可預測、<a href="/blog/business/knowledge-cards/retention/" data-link-title="Retention" data-link-desc="說明客戶留存率與其對單位經濟的決定作用">retention</a> 接近 100%；對買方來說等於把核心工作流程綁定到單一供應商。AI Labs 的策略重心正是這個—不想只當「按 token 計費的模型供應商」，要直接賣 enterprise license 進企業，藉此建立 <a href="/blog/business/knowledge-cards/lock-in/" data-link-title="Lock-in" data-link-desc="說明鎖定效應如何形成護城河">Lock-in</a> 並穩定營收。</p>
]]></content:encoded></item><item><title>Security Group</title><link>https://tarrragon.github.io/blog/infra/knowledge-cards/security-group/</link><pubDate>Fri, 26 Jun 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/infra/knowledge-cards/security-group/</guid><description>&lt;p>Security group 是掛在資源網卡（ENI）層級的有狀態防火牆，規則描述的是「哪些來源能連到這個資源的哪個埠」。「有狀態」的意思是放行一條入站連線後，對應的回應出站自動允許——規則只需描述入站方向想開放什麼。&lt;/p>
&lt;p>設計原則是最小開放：每條規則只開「這個服務確實需要被誰連的那個埠」。資料庫的 security group 入站只允許來自應用層 security group 的資料庫埠（如 5432），而不是某個 IP 範圍。用 security group 互相引用（source 指向另一個 group 而非 CIDR）讓規則跟著成員身分走、不跟著位址走——應用節點會隨擴縮而換 IP，引用 group 不會因此失效。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>Security group 是&lt;a href="https://tarrragon.github.io/blog/infra/03-network-foundation/vpc-subnet-security-group/" data-link-title="網路地基 — VPC、subnet 分層與 security group 設計" data-link-desc="VPC CIDR 規劃、public / private subnet 切分、route table 與 NAT 的可用性成本取捨、security group 最小開放設計，以及 NACL 的定位">模組三：網路地基&lt;/a>的最內層邊界——貼著服務的最後一道網路防線。即使封包順著 route table 抵達了 private &lt;a href="https://tarrragon.github.io/blog/infra/knowledge-cards/subnet/" data-link-title="Subnet（子網路）" data-link-desc="VPC 內按可用區與暴露程度切出的子網段，決定資源有沒有一條通往網際網路的路徑">subnet&lt;/a>，security group 仍能逐埠決定放不放行。&lt;a href="https://tarrragon.github.io/blog/infra/07-infra-as-pr/plan-review-apply-guardrails/" data-link-title="infra 走 PR 流程與自動化護欄" data-link-desc="infra 變更走 PR → plan → review diff → 合併 → apply，配 fmt / validate / tflint / checkov / tfsec 與 Atlantis 自動化，讓基礎設施可審查、可回溯、可交接">模組七：infra 走 PR 流程&lt;/a>用 tfsec / checkov 在 CI 攔截 &lt;code>0.0.0.0/0&lt;/code> 全開的規則。&lt;/p>
&lt;h2 id="可觀察訊號">可觀察訊號&lt;/h2>
&lt;p>Security group 需要收斂的訊號：入站來源是 &lt;code>0.0.0.0/0&lt;/code>（允許全網連入），且目標埠是資料庫（5432、3306、6379）或管理埠（22、3389）——合理出現 &lt;code>0.0.0.0/0&lt;/code> 的位置只有對外負載平衡器的 80 / 443。盤點方式是列出所有 source 為 &lt;code>0.0.0.0/0&lt;/code> 的規則，逐條問「這個埠需要全世界都連得到嗎」。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>設計 security group 時要決定：&lt;/p>
&lt;ul>
&lt;li>引用方式：用 group 互相引用（推薦）vs 用 CIDR 限定範圍&lt;/li>
&lt;li>開放範圍：只開需要的埠與來源，&lt;code>0.0.0.0/0&lt;/code> 只給對外 LB&lt;/li>
&lt;li>管理埠存取：SSH（22）改用 SSM Session Manager 取代，從公網清單上拿掉&lt;/li>
&lt;li>與 NACL 的分工：security group 是主力（有狀態、group 引用），NACL 留給少數需要 subnet 層顯式 deny 的情境&lt;/li>
&lt;/ul>
&lt;h2 id="鄰卡">鄰卡&lt;/h2>
&lt;ul>
&lt;li>&lt;a href="https://tarrragon.github.io/blog/infra/knowledge-cards/vpc/" data-link-title="VPC（Virtual Private Cloud）" data-link-desc="雲端帳號內的一塊邏輯隔離私有網段，是所有網路切分的起點與容器">VPC&lt;/a> — security group 依附的網路容器&lt;/li>
&lt;li>&lt;a href="https://tarrragon.github.io/blog/infra/knowledge-cards/subnet/" data-link-title="Subnet（子網路）" data-link-desc="VPC 內按可用區與暴露程度切出的子網段，決定資源有沒有一條通往網際網路的路徑">Subnet&lt;/a> — security group 與 subnet 各守不同層級的邊界&lt;/li>
&lt;/ul></description><content:encoded><![CDATA[<p>Security group 是掛在資源網卡（ENI）層級的有狀態防火牆，規則描述的是「哪些來源能連到這個資源的哪個埠」。「有狀態」的意思是放行一條入站連線後，對應的回應出站自動允許——規則只需描述入站方向想開放什麼。</p>
<p>設計原則是最小開放：每條規則只開「這個服務確實需要被誰連的那個埠」。資料庫的 security group 入站只允許來自應用層 security group 的資料庫埠（如 5432），而不是某個 IP 範圍。用 security group 互相引用（source 指向另一個 group 而非 CIDR）讓規則跟著成員身分走、不跟著位址走——應用節點會隨擴縮而換 IP，引用 group 不會因此失效。</p>
<h2 id="概念位置">概念位置</h2>
<p>Security group 是<a href="/blog/infra/03-network-foundation/vpc-subnet-security-group/" data-link-title="網路地基 — VPC、subnet 分層與 security group 設計" data-link-desc="VPC CIDR 規劃、public / private subnet 切分、route table 與 NAT 的可用性成本取捨、security group 最小開放設計，以及 NACL 的定位">模組三：網路地基</a>的最內層邊界——貼著服務的最後一道網路防線。即使封包順著 route table 抵達了 private <a href="/blog/infra/knowledge-cards/subnet/" data-link-title="Subnet（子網路）" data-link-desc="VPC 內按可用區與暴露程度切出的子網段，決定資源有沒有一條通往網際網路的路徑">subnet</a>，security group 仍能逐埠決定放不放行。<a href="/blog/infra/07-infra-as-pr/plan-review-apply-guardrails/" data-link-title="infra 走 PR 流程與自動化護欄" data-link-desc="infra 變更走 PR → plan → review diff → 合併 → apply，配 fmt / validate / tflint / checkov / tfsec 與 Atlantis 自動化，讓基礎設施可審查、可回溯、可交接">模組七：infra 走 PR 流程</a>用 tfsec / checkov 在 CI 攔截 <code>0.0.0.0/0</code> 全開的規則。</p>
<h2 id="可觀察訊號">可觀察訊號</h2>
<p>Security group 需要收斂的訊號：入站來源是 <code>0.0.0.0/0</code>（允許全網連入），且目標埠是資料庫（5432、3306、6379）或管理埠（22、3389）——合理出現 <code>0.0.0.0/0</code> 的位置只有對外負載平衡器的 80 / 443。盤點方式是列出所有 source 為 <code>0.0.0.0/0</code> 的規則，逐條問「這個埠需要全世界都連得到嗎」。</p>
<h2 id="設計責任">設計責任</h2>
<p>設計 security group 時要決定：</p>
<ul>
<li>引用方式：用 group 互相引用（推薦）vs 用 CIDR 限定範圍</li>
<li>開放範圍：只開需要的埠與來源，<code>0.0.0.0/0</code> 只給對外 LB</li>
<li>管理埠存取：SSH（22）改用 SSM Session Manager 取代，從公網清單上拿掉</li>
<li>與 NACL 的分工：security group 是主力（有狀態、group 引用），NACL 留給少數需要 subnet 層顯式 deny 的情境</li>
</ul>
<h2 id="鄰卡">鄰卡</h2>
<ul>
<li><a href="/blog/infra/knowledge-cards/vpc/" data-link-title="VPC（Virtual Private Cloud）" data-link-desc="雲端帳號內的一塊邏輯隔離私有網段，是所有網路切分的起點與容器">VPC</a> — security group 依附的網路容器</li>
<li><a href="/blog/infra/knowledge-cards/subnet/" data-link-title="Subnet（子網路）" data-link-desc="VPC 內按可用區與暴露程度切出的子網段，決定資源有沒有一條通往網際網路的路徑">Subnet</a> — security group 與 subnet 各守不同層級的邊界</li>
</ul>
]]></content:encoded></item><item><title>NAT Gateway</title><link>https://tarrragon.github.io/blog/infra/knowledge-cards/nat/</link><pubDate>Fri, 26 Jun 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/infra/knowledge-cards/nat/</guid><description>&lt;p>NAT Gateway（Network Address Translation Gateway）的核心職責是讓 private subnet 的資源能主動發起對外連線（拉套件、呼叫第三方 API、下載 OS 更新），同時不開放任何外部主動發起的入站連線。它借用一個公網 IP 把出站封包送出去，再把回應導回原請求者。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>NAT Gateway 在網路地基裡的角色是 private subnet 的出站閘道。它解決的問題是：private subnet 的設計意圖是「外部連不進來」，但服務仍需要主動對外。沒有 NAT，private subnet 的資源完全無法對外通訊 — 連 &lt;code>apt update&lt;/code> 或 &lt;code>pip install&lt;/code> 都做不到。&lt;/p>
&lt;p>NAT Gateway 是綁定單一可用區的資源，活在某個 public subnet 裡。這帶來一個架構取捨：共享一個 NAT（成本低、出站方向有單點）還是每個可用區各放一個（成本高、出站與 subnet 冗餘對齊）。&lt;/p>
&lt;h2 id="可觀察訊號">可觀察訊號&lt;/h2>
&lt;p>以下狀況指向 NAT 相關問題：&lt;/p>
&lt;ul>
&lt;li>Private subnet 的服務拉不到外部套件或第三方 API 全部逾時 — 先查 route table 有沒有指向健康的 NAT&lt;/li>
&lt;li>只有某一個可用區的節點受影響 — 該區的 NAT 或其所在 subnet 可能故障&lt;/li>
&lt;li>雲帳單裡 NAT Gateway 的流量費用異常高 — 大量走 NAT 的流量（S3 備份、跨區同步）可用 VPC Endpoint 繞過&lt;/li>
&lt;/ul>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>使用 NAT Gateway 時要決定：&lt;/p>
&lt;ul>
&lt;li>&lt;strong>數量&lt;/strong>：每個可用區一個（可用性優先）還是全 VPC 共享一個（成本優先）。每個 NAT 固定月費約 $32 加流量費 $0.045/GB&lt;/li>
&lt;li>&lt;strong>高流量路徑&lt;/strong>：對 AWS 自家服務的流量（S3、DynamoDB）改用 Gateway Endpoint 直連，繞過 NAT 省流量費&lt;/li>
&lt;li>&lt;strong>route table 關聯&lt;/strong>：每個 private subnet 的 route table 要明確指向哪個 NAT&lt;/li>
&lt;/ul>
&lt;h2 id="鄰卡">鄰卡&lt;/h2>
&lt;ul>
&lt;li>&lt;a href="https://tarrragon.github.io/blog/infra/knowledge-cards/subnet/" data-link-title="Subnet（子網路）" data-link-desc="VPC 內按可用區與暴露程度切出的子網段，決定資源有沒有一條通往網際網路的路徑">Subnet&lt;/a> — NAT 放在 public subnet、服務放在 private subnet&lt;/li>
&lt;li>&lt;a href="https://tarrragon.github.io/blog/infra/knowledge-cards/vpc/" data-link-title="VPC（Virtual Private Cloud）" data-link-desc="雲端帳號內的一塊邏輯隔離私有網段，是所有網路切分的起點與容器">VPC&lt;/a> — NAT 屬於 VPC 內部的出站路徑設施&lt;/li>
&lt;/ul></description><content:encoded><![CDATA[<p>NAT Gateway（Network Address Translation Gateway）的核心職責是讓 private subnet 的資源能主動發起對外連線（拉套件、呼叫第三方 API、下載 OS 更新），同時不開放任何外部主動發起的入站連線。它借用一個公網 IP 把出站封包送出去，再把回應導回原請求者。</p>
<h2 id="概念位置">概念位置</h2>
<p>NAT Gateway 在網路地基裡的角色是 private subnet 的出站閘道。它解決的問題是：private subnet 的設計意圖是「外部連不進來」，但服務仍需要主動對外。沒有 NAT，private subnet 的資源完全無法對外通訊 — 連 <code>apt update</code> 或 <code>pip install</code> 都做不到。</p>
<p>NAT Gateway 是綁定單一可用區的資源，活在某個 public subnet 裡。這帶來一個架構取捨：共享一個 NAT（成本低、出站方向有單點）還是每個可用區各放一個（成本高、出站與 subnet 冗餘對齊）。</p>
<h2 id="可觀察訊號">可觀察訊號</h2>
<p>以下狀況指向 NAT 相關問題：</p>
<ul>
<li>Private subnet 的服務拉不到外部套件或第三方 API 全部逾時 — 先查 route table 有沒有指向健康的 NAT</li>
<li>只有某一個可用區的節點受影響 — 該區的 NAT 或其所在 subnet 可能故障</li>
<li>雲帳單裡 NAT Gateway 的流量費用異常高 — 大量走 NAT 的流量（S3 備份、跨區同步）可用 VPC Endpoint 繞過</li>
</ul>
<h2 id="設計責任">設計責任</h2>
<p>使用 NAT Gateway 時要決定：</p>
<ul>
<li><strong>數量</strong>：每個可用區一個（可用性優先）還是全 VPC 共享一個（成本優先）。每個 NAT 固定月費約 $32 加流量費 $0.045/GB</li>
<li><strong>高流量路徑</strong>：對 AWS 自家服務的流量（S3、DynamoDB）改用 Gateway Endpoint 直連，繞過 NAT 省流量費</li>
<li><strong>route table 關聯</strong>：每個 private subnet 的 route table 要明確指向哪個 NAT</li>
</ul>
<h2 id="鄰卡">鄰卡</h2>
<ul>
<li><a href="/blog/infra/knowledge-cards/subnet/" data-link-title="Subnet（子網路）" data-link-desc="VPC 內按可用區與暴露程度切出的子網段，決定資源有沒有一條通往網際網路的路徑">Subnet</a> — NAT 放在 public subnet、服務放在 private subnet</li>
<li><a href="/blog/infra/knowledge-cards/vpc/" data-link-title="VPC（Virtual Private Cloud）" data-link-desc="雲端帳號內的一塊邏輯隔離私有網段，是所有網路切分的起點與容器">VPC</a> — NAT 屬於 VPC 內部的出站路徑設施</li>
</ul>
]]></content:encoded></item><item><title>OIDC 聯合</title><link>https://tarrragon.github.io/blog/infra/knowledge-cards/oidc/</link><pubDate>Fri, 26 Jun 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/infra/knowledge-cards/oidc/</guid><description>&lt;p>OIDC（OpenID Connect）聯合的核心職責是讓跑在雲外的 CI/CD 平台（GitHub Actions、GitLab CI）用每次執行才簽發、幾分鐘後就失效的短期憑證存取雲端資源，從根本上消除「在 CI 環境裡存放長期 access key」這個攻擊面。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>OIDC 聯合在身分與憑證地基裡的角色是「雲外機器身分的認證機制」。跑在雲上的 workload（EC2、ECS task）可以用平台原生的 instance profile 或 task role 取得短期憑證；跑在雲外的 CI/CD 沒有這個管道，OIDC 就是替代方案。&lt;/p>
&lt;p>運作方式是建立信任關係：雲端帳號信任某個外部 identity provider（如 GitHub Actions 的 OIDC issuer），CI 執行時平台簽發一個帶 claim 的 token（描述哪個 repo、哪個 branch、哪個 workflow），雲端用這個 token 換出一段臨時憑證。&lt;/p>
&lt;h2 id="可觀察訊號">可觀察訊號&lt;/h2>
&lt;p>以下狀況指向 OIDC 相關問題：&lt;/p>
&lt;ul>
&lt;li>CI pipeline 裡有 &lt;code>AWS_ACCESS_KEY_ID&lt;/code> 和 &lt;code>AWS_SECRET_ACCESS_KEY&lt;/code> 環境變數 — 這是長期 key，應該替換成 OIDC&lt;/li>
&lt;li>Trust policy 只驗 issuer 不驗 repo — 任何掛在同一個 CI 平台的專案都能假扮這個 role&lt;/li>
&lt;li>Pipeline 突然無法取得權限 — 可能是 trust policy 的 condition 跟 token claim 不匹配（常見於 repo 改名或 branch 改名後）&lt;/li>
&lt;/ul>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>設定 OIDC 聯合時要決定：&lt;/p>
&lt;ul>
&lt;li>&lt;strong>Trust policy 的 claim 收斂&lt;/strong>：限定 issuer + audience + 特定 repo + 特定 branch，每個條件都收到最緊&lt;/li>
&lt;li>&lt;strong>Role 的權限範圍&lt;/strong>：OIDC 換到的 role 仍然要遵循最小權限 — 只給 pipeline 需要的 action&lt;/li>
&lt;li>&lt;strong>Plan 與 apply 分開的 role&lt;/strong>：plan 只需要 read 權限、apply 需要 write 權限，用兩個 role 降低 PR 階段的風險&lt;/li>
&lt;/ul>
&lt;h2 id="鄰卡">鄰卡&lt;/h2>
&lt;ul>
&lt;li>&lt;a href="https://tarrragon.github.io/blog/infra/knowledge-cards/iam/" data-link-title="IAM（Identity and Access Management）" data-link-desc="雲端平台的授權系統，回答「某個身分能不能對某個資源做某件事」">IAM&lt;/a> — OIDC 是 IAM 身分系統的一種外部身分來源&lt;/li>
&lt;li>&lt;a href="https://tarrragon.github.io/blog/infra/knowledge-cards/security-group/" data-link-title="Security Group" data-link-desc="掛在資源網卡層級的有狀態防火牆，逐埠決定哪些來源能連進這個資源">Security Group&lt;/a> — OIDC 解的是身分層的認證問題，跟網路層的 security group 正交&lt;/li>
&lt;/ul></description><content:encoded><![CDATA[<p>OIDC（OpenID Connect）聯合的核心職責是讓跑在雲外的 CI/CD 平台（GitHub Actions、GitLab CI）用每次執行才簽發、幾分鐘後就失效的短期憑證存取雲端資源，從根本上消除「在 CI 環境裡存放長期 access key」這個攻擊面。</p>
<h2 id="概念位置">概念位置</h2>
<p>OIDC 聯合在身分與憑證地基裡的角色是「雲外機器身分的認證機制」。跑在雲上的 workload（EC2、ECS task）可以用平台原生的 instance profile 或 task role 取得短期憑證；跑在雲外的 CI/CD 沒有這個管道，OIDC 就是替代方案。</p>
<p>運作方式是建立信任關係：雲端帳號信任某個外部 identity provider（如 GitHub Actions 的 OIDC issuer），CI 執行時平台簽發一個帶 claim 的 token（描述哪個 repo、哪個 branch、哪個 workflow），雲端用這個 token 換出一段臨時憑證。</p>
<h2 id="可觀察訊號">可觀察訊號</h2>
<p>以下狀況指向 OIDC 相關問題：</p>
<ul>
<li>CI pipeline 裡有 <code>AWS_ACCESS_KEY_ID</code> 和 <code>AWS_SECRET_ACCESS_KEY</code> 環境變數 — 這是長期 key，應該替換成 OIDC</li>
<li>Trust policy 只驗 issuer 不驗 repo — 任何掛在同一個 CI 平台的專案都能假扮這個 role</li>
<li>Pipeline 突然無法取得權限 — 可能是 trust policy 的 condition 跟 token claim 不匹配（常見於 repo 改名或 branch 改名後）</li>
</ul>
<h2 id="設計責任">設計責任</h2>
<p>設定 OIDC 聯合時要決定：</p>
<ul>
<li><strong>Trust policy 的 claim 收斂</strong>：限定 issuer + audience + 特定 repo + 特定 branch，每個條件都收到最緊</li>
<li><strong>Role 的權限範圍</strong>：OIDC 換到的 role 仍然要遵循最小權限 — 只給 pipeline 需要的 action</li>
<li><strong>Plan 與 apply 分開的 role</strong>：plan 只需要 read 權限、apply 需要 write 權限，用兩個 role 降低 PR 階段的風險</li>
</ul>
<h2 id="鄰卡">鄰卡</h2>
<ul>
<li><a href="/blog/infra/knowledge-cards/iam/" data-link-title="IAM（Identity and Access Management）" data-link-desc="雲端平台的授權系統，回答「某個身分能不能對某個資源做某件事」">IAM</a> — OIDC 是 IAM 身分系統的一種外部身分來源</li>
<li><a href="/blog/infra/knowledge-cards/security-group/" data-link-title="Security Group" data-link-desc="掛在資源網卡層級的有狀態防火牆，逐埠決定哪些來源能連進這個資源">Security Group</a> — OIDC 解的是身分層的認證問題，跟網路層的 security group 正交</li>
</ul>
]]></content:encoded></item><item><title>環境分離</title><link>https://tarrragon.github.io/blog/infra/knowledge-cards/environment-separation/</link><pubDate>Fri, 26 Jun 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/infra/knowledge-cards/environment-separation/</guid><description>&lt;p>環境分離的核心職責是讓 dev 的實驗、staging 的驗證、production 的真實流量彼此不可見也不可達 — 在 dev 跑壞一個資料庫、套錯一條 security group 規則時，production 完全無感。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>環境分離在 infra 成熟度階梯上對應第三階。它建立在宣告式 IaC（第二階）的基礎上 — 有了 state 追蹤和模組化描述之後，才能用「同一份 code、不同參數」的方式複製出多個隔離環境。&lt;/p>
&lt;p>分離的實作方式有一條隔離強度光譜：從帳號級（不同雲端帳號，最強隔離）到目錄級（同一 repo 內各環境一個目錄，各自持有 state）到 workspace 級（同一份 code 用執行期切換 state，隔離最弱）。多數早期團隊在目錄級落腳，因為它在顯式邊界與維運成本之間取得平衡。&lt;/p>
&lt;h2 id="可觀察訊號">可觀察訊號&lt;/h2>
&lt;p>以下狀況指向環境分離不足：&lt;/p>
&lt;ul>
&lt;li>在 staging 測試的變更意外影響了 production 的資源 — dev 跟 prod 共用同一份 state&lt;/li>
&lt;li>某人的 &lt;code>terraform apply&lt;/code> 把另一個環境的資源改掉了 — workspace 的隱性狀態切換導致打錯環境&lt;/li>
&lt;li>dev 與 prod 的設定差異散落在 code 裡的 &lt;code>if env == &amp;quot;prod&amp;quot;&lt;/code> 判斷 — 環境差異沒有集中在參數值裡&lt;/li>
&lt;/ul>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>環境分離的設計要決定：&lt;/p>
&lt;ul>
&lt;li>&lt;strong>隔離層級&lt;/strong>：帳號級、目錄級、還是 workspace 級。判斷依據是團隊規模、合規要求、與維運餘裕&lt;/li>
&lt;li>&lt;strong>參數化邊界&lt;/strong>：dev 與 prod 之間的差異全部用參數表達（instance size、multi-AZ、backup retention），module 內部不寫環境判斷&lt;/li>
&lt;li>&lt;strong>state 位址分離&lt;/strong>：每個環境的 state backend 位址獨立，互不交叉&lt;/li>
&lt;/ul>
&lt;h2 id="鄰卡">鄰卡&lt;/h2>
&lt;ul>
&lt;li>&lt;a href="https://tarrragon.github.io/blog/infra/knowledge-cards/iac/" data-link-title="Infrastructure as Code (IaC)" data-link-desc="用程式碼描述基礎設施的最終狀態，由工具負責收斂現實與描述的差異">IaC&lt;/a> — 環境分離的前提是有可重用的 IaC 描述&lt;/li>
&lt;li>&lt;a href="https://tarrragon.github.io/blog/infra/knowledge-cards/state/" data-link-title="State（IaC 狀態檔）" data-link-desc="IaC 工具用來記錄每個納管資源在雲端真實樣貌的快照，是比對差異與排定操作順序的依據">State&lt;/a> — 每個環境持有獨立的 state 檔&lt;/li>
&lt;li>&lt;a href="https://tarrragon.github.io/blog/infra/knowledge-cards/drift/" data-link-title="Drift（設定漂移）" data-link-desc="IaC 的 state 與雲端實際狀態之間的不一致，通常因為有人繞過 IaC 直接在 Console 改設定">Drift&lt;/a> — 環境分離降低 drift 的跨環境影響範圍&lt;/li>
&lt;/ul></description><content:encoded><![CDATA[<p>環境分離的核心職責是讓 dev 的實驗、staging 的驗證、production 的真實流量彼此不可見也不可達 — 在 dev 跑壞一個資料庫、套錯一條 security group 規則時，production 完全無感。</p>
<h2 id="概念位置">概念位置</h2>
<p>環境分離在 infra 成熟度階梯上對應第三階。它建立在宣告式 IaC（第二階）的基礎上 — 有了 state 追蹤和模組化描述之後，才能用「同一份 code、不同參數」的方式複製出多個隔離環境。</p>
<p>分離的實作方式有一條隔離強度光譜：從帳號級（不同雲端帳號，最強隔離）到目錄級（同一 repo 內各環境一個目錄，各自持有 state）到 workspace 級（同一份 code 用執行期切換 state，隔離最弱）。多數早期團隊在目錄級落腳，因為它在顯式邊界與維運成本之間取得平衡。</p>
<h2 id="可觀察訊號">可觀察訊號</h2>
<p>以下狀況指向環境分離不足：</p>
<ul>
<li>在 staging 測試的變更意外影響了 production 的資源 — dev 跟 prod 共用同一份 state</li>
<li>某人的 <code>terraform apply</code> 把另一個環境的資源改掉了 — workspace 的隱性狀態切換導致打錯環境</li>
<li>dev 與 prod 的設定差異散落在 code 裡的 <code>if env == &quot;prod&quot;</code> 判斷 — 環境差異沒有集中在參數值裡</li>
</ul>
<h2 id="設計責任">設計責任</h2>
<p>環境分離的設計要決定：</p>
<ul>
<li><strong>隔離層級</strong>：帳號級、目錄級、還是 workspace 級。判斷依據是團隊規模、合規要求、與維運餘裕</li>
<li><strong>參數化邊界</strong>：dev 與 prod 之間的差異全部用參數表達（instance size、multi-AZ、backup retention），module 內部不寫環境判斷</li>
<li><strong>state 位址分離</strong>：每個環境的 state backend 位址獨立，互不交叉</li>
</ul>
<h2 id="鄰卡">鄰卡</h2>
<ul>
<li><a href="/blog/infra/knowledge-cards/iac/" data-link-title="Infrastructure as Code (IaC)" data-link-desc="用程式碼描述基礎設施的最終狀態，由工具負責收斂現實與描述的差異">IaC</a> — 環境分離的前提是有可重用的 IaC 描述</li>
<li><a href="/blog/infra/knowledge-cards/state/" data-link-title="State（IaC 狀態檔）" data-link-desc="IaC 工具用來記錄每個納管資源在雲端真實樣貌的快照，是比對差異與排定操作順序的依據">State</a> — 每個環境持有獨立的 state 檔</li>
<li><a href="/blog/infra/knowledge-cards/drift/" data-link-title="Drift（設定漂移）" data-link-desc="IaC 的 state 與雲端實際狀態之間的不一致，通常因為有人繞過 IaC 直接在 Console 改設定">Drift</a> — 環境分離降低 drift 的跨環境影響範圍</li>
</ul>
]]></content:encoded></item><item><title>CloudTrail</title><link>https://tarrragon.github.io/blog/infra/knowledge-cards/cloudtrail/</link><pubDate>Fri, 26 Jun 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/infra/knowledge-cards/cloudtrail/</guid><description>&lt;p>CloudTrail 的核心職責是把 AWS 帳號內每一個 API 呼叫記錄成可查詢的稽核日誌 — 哪個身分、在什麼時間、對哪個資源、呼叫了哪個 API、結果是成功還是拒絕。它是事故排查和合規稽核的事實來源。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>CloudTrail 在 infra 治理裡的角色是「發生了什麼」的最後防線。人工變更日誌記錄「為什麼改」，CloudTrail 記錄「改了什麼」— 兩者一起才能從事故回推到可回退的操作。&lt;/p>
&lt;p>CloudTrail 預設記錄 management event（建立、修改、刪除資源的 API 呼叫）並保留 90 天可查閱。要長期保存或記錄 data event（S3 物件存取、Lambda 呼叫等更細粒度的操作），需要建立 trail 並指定 S3 bucket 儲存。&lt;/p>
&lt;h2 id="可觀察訊號">可觀察訊號&lt;/h2>
&lt;p>以下狀況指向 CloudTrail 的使用場景：&lt;/p>
&lt;ul>
&lt;li>事故排查需要回答「誰在過去 24 小時改過這個 security group」— CloudTrail 的 &lt;code>LookupEvents&lt;/code> API 可以按事件名稱、資源類型或使用者名稱查詢&lt;/li>
&lt;li>安全稽核要求提供「過去 90 天內所有 IAM policy 變更的紀錄」— CloudTrail 是標準的證據來源&lt;/li>
&lt;li>發現不預期的資源變更（drift），需要確認是人為操作還是自動化觸發 — CloudTrail 的 &lt;code>userIdentity&lt;/code> 欄位區分人類使用者和 assume-role 的服務&lt;/li>
&lt;/ul>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>使用 CloudTrail 時要決定：&lt;/p>
&lt;ul>
&lt;li>&lt;strong>保留期限&lt;/strong>：預設 90 天免費查閱；超過需要建 trail 存到 S3，費用是 S3 儲存成本&lt;/li>
&lt;li>&lt;strong>事件範圍&lt;/strong>：management event 預設開啟；data event（S3 物件讀寫、Lambda invoke）要額外設定，且量大時儲存成本可觀&lt;/li>
&lt;li>&lt;strong>跨帳號整合&lt;/strong>：多帳號架構下，Organization trail 可以把所有帳號的事件集中到一個 S3 bucket&lt;/li>
&lt;li>&lt;strong>存取控制&lt;/strong>：CloudTrail 的 S3 bucket 本身要限制存取 — 能修改稽核日誌等於能掩蓋操作痕跡&lt;/li>
&lt;/ul>
&lt;h2 id="鄰卡">鄰卡&lt;/h2>
&lt;ul>
&lt;li>&lt;a href="https://tarrragon.github.io/blog/infra/knowledge-cards/iam/" data-link-title="IAM（Identity and Access Management）" data-link-desc="雲端平台的授權系統，回答「某個身分能不能對某個資源做某件事」">IAM&lt;/a> — CloudTrail 記錄的是 IAM 身分的 API 呼叫&lt;/li>
&lt;li>&lt;a href="https://tarrragon.github.io/blog/infra/knowledge-cards/drift/" data-link-title="Drift（設定漂移）" data-link-desc="IaC 的 state 與雲端實際狀態之間的不一致，通常因為有人繞過 IaC 直接在 Console 改設定">Drift&lt;/a> — CloudTrail 是追查 drift 來源（誰手動改了什麼）的工具&lt;/li>
&lt;/ul></description><content:encoded><![CDATA[<p>CloudTrail 的核心職責是把 AWS 帳號內每一個 API 呼叫記錄成可查詢的稽核日誌 — 哪個身分、在什麼時間、對哪個資源、呼叫了哪個 API、結果是成功還是拒絕。它是事故排查和合規稽核的事實來源。</p>
<h2 id="概念位置">概念位置</h2>
<p>CloudTrail 在 infra 治理裡的角色是「發生了什麼」的最後防線。人工變更日誌記錄「為什麼改」，CloudTrail 記錄「改了什麼」— 兩者一起才能從事故回推到可回退的操作。</p>
<p>CloudTrail 預設記錄 management event（建立、修改、刪除資源的 API 呼叫）並保留 90 天可查閱。要長期保存或記錄 data event（S3 物件存取、Lambda 呼叫等更細粒度的操作），需要建立 trail 並指定 S3 bucket 儲存。</p>
<h2 id="可觀察訊號">可觀察訊號</h2>
<p>以下狀況指向 CloudTrail 的使用場景：</p>
<ul>
<li>事故排查需要回答「誰在過去 24 小時改過這個 security group」— CloudTrail 的 <code>LookupEvents</code> API 可以按事件名稱、資源類型或使用者名稱查詢</li>
<li>安全稽核要求提供「過去 90 天內所有 IAM policy 變更的紀錄」— CloudTrail 是標準的證據來源</li>
<li>發現不預期的資源變更（drift），需要確認是人為操作還是自動化觸發 — CloudTrail 的 <code>userIdentity</code> 欄位區分人類使用者和 assume-role 的服務</li>
</ul>
<h2 id="設計責任">設計責任</h2>
<p>使用 CloudTrail 時要決定：</p>
<ul>
<li><strong>保留期限</strong>：預設 90 天免費查閱；超過需要建 trail 存到 S3，費用是 S3 儲存成本</li>
<li><strong>事件範圍</strong>：management event 預設開啟；data event（S3 物件讀寫、Lambda invoke）要額外設定，且量大時儲存成本可觀</li>
<li><strong>跨帳號整合</strong>：多帳號架構下，Organization trail 可以把所有帳號的事件集中到一個 S3 bucket</li>
<li><strong>存取控制</strong>：CloudTrail 的 S3 bucket 本身要限制存取 — 能修改稽核日誌等於能掩蓋操作痕跡</li>
</ul>
<h2 id="鄰卡">鄰卡</h2>
<ul>
<li><a href="/blog/infra/knowledge-cards/iam/" data-link-title="IAM（Identity and Access Management）" data-link-desc="雲端平台的授權系統，回答「某個身分能不能對某個資源做某件事」">IAM</a> — CloudTrail 記錄的是 IAM 身分的 API 呼叫</li>
<li><a href="/blog/infra/knowledge-cards/drift/" data-link-title="Drift（設定漂移）" data-link-desc="IaC 的 state 與雲端實際狀態之間的不一致，通常因為有人繞過 IaC 直接在 Console 改設定">Drift</a> — CloudTrail 是追查 drift 來源（誰手動改了什麼）的工具</li>
</ul>
]]></content:encoded></item><item><title>COGS</title><link>https://tarrragon.github.io/blog/business/knowledge-cards/cogs/</link><pubDate>Tue, 19 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/business/knowledge-cards/cogs/</guid><description>&lt;p>COGS 的核心概念是「Cost of Goods Sold，銷售成本」—賣出產品時直接發生的成本。製造業的 COGS 包括原料、加工、運送；&lt;a href="https://tarrragon.github.io/blog/business/knowledge-cards/saas/" data-link-title="SaaS" data-link-desc="說明雲端訂閱軟體的商業模式與經濟特徵">SaaS&lt;/a> 的 COGS 包括雲端基礎設施、第三方 API、客戶支援人力；AI 產品的 COGS 主要是模型推論的算力支出。COGS 高低決定 &lt;a href="https://tarrragon.github.io/blog/business/knowledge-cards/gross-margin/" data-link-title="Gross Margin" data-link-desc="說明毛利率與其對商業模式可行性的決定作用">毛利&lt;/a> 結構。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>COGS 是計算 &lt;a href="https://tarrragon.github.io/blog/business/knowledge-cards/gross-margin/" data-link-title="Gross Margin" data-link-desc="說明毛利率與其對商業模式可行性的決定作用">毛利&lt;/a> 的扣除項—收入扣掉 COGS 等於毛利。它不包括銷售、行銷、研發、管理費用，那些是營業費用（OpEx）。COGS 的特性決定 &lt;a href="https://tarrragon.github.io/blog/business/knowledge-cards/unit-economics/" data-link-title="Unit Economics" data-link-desc="說明單位經濟模型與其判斷一家公司是否賺錢的責任">單位經濟&lt;/a> 是否成立—COGS 接近零的商業模式才能走 &lt;a href="https://tarrragon.github.io/blog/business/knowledge-cards/plg/" data-link-title="PLG" data-link-desc="說明產品自助成長模式與其經濟前提">PLG&lt;/a>。&lt;/p>
&lt;h2 id="可觀察訊號與例子">可觀察訊號與例子&lt;/h2>
&lt;p>判斷一家公司的 COGS 結構，看它賣一筆訂單時要支付多少給上游。傳統 SaaS 賣 100 元，COGS 可能只有 20 元（伺服器費用）；AI 產品賣 100 元，COGS 可能高達 50 元（給 OpenAI / Anthropic 的 token 費用）。COGS 結構差異直接造成毛利率差三十個百分點。&lt;/p>
&lt;h2 id="判讀方式">判讀方式&lt;/h2>
&lt;p>讀到「COGS 上升」「COGS 不再接近零」這類描述時，代表該行業的毛利結構正在改變。AI 公司面對的核心議題就是 COGS 從接近零變成可觀的成本—這就是為什麼分析師說「AI 的毛利不會像傳統 SaaS 那麼高」，連帶 &lt;a href="https://tarrragon.github.io/blog/business/knowledge-cards/valuation/" data-link-title="Valuation" data-link-desc="說明估值的構成與商業判讀作用">估值&lt;/a> 跟著被壓縮。&lt;/p></description><content:encoded><![CDATA[<p>COGS 的核心概念是「Cost of Goods Sold，銷售成本」—賣出產品時直接發生的成本。製造業的 COGS 包括原料、加工、運送；<a href="/blog/business/knowledge-cards/saas/" data-link-title="SaaS" data-link-desc="說明雲端訂閱軟體的商業模式與經濟特徵">SaaS</a> 的 COGS 包括雲端基礎設施、第三方 API、客戶支援人力；AI 產品的 COGS 主要是模型推論的算力支出。COGS 高低決定 <a href="/blog/business/knowledge-cards/gross-margin/" data-link-title="Gross Margin" data-link-desc="說明毛利率與其對商業模式可行性的決定作用">毛利</a> 結構。</p>
<h2 id="概念位置">概念位置</h2>
<p>COGS 是計算 <a href="/blog/business/knowledge-cards/gross-margin/" data-link-title="Gross Margin" data-link-desc="說明毛利率與其對商業模式可行性的決定作用">毛利</a> 的扣除項—收入扣掉 COGS 等於毛利。它不包括銷售、行銷、研發、管理費用，那些是營業費用（OpEx）。COGS 的特性決定 <a href="/blog/business/knowledge-cards/unit-economics/" data-link-title="Unit Economics" data-link-desc="說明單位經濟模型與其判斷一家公司是否賺錢的責任">單位經濟</a> 是否成立—COGS 接近零的商業模式才能走 <a href="/blog/business/knowledge-cards/plg/" data-link-title="PLG" data-link-desc="說明產品自助成長模式與其經濟前提">PLG</a>。</p>
<h2 id="可觀察訊號與例子">可觀察訊號與例子</h2>
<p>判斷一家公司的 COGS 結構，看它賣一筆訂單時要支付多少給上游。傳統 SaaS 賣 100 元，COGS 可能只有 20 元（伺服器費用）；AI 產品賣 100 元，COGS 可能高達 50 元（給 OpenAI / Anthropic 的 token 費用）。COGS 結構差異直接造成毛利率差三十個百分點。</p>
<h2 id="判讀方式">判讀方式</h2>
<p>讀到「COGS 上升」「COGS 不再接近零」這類描述時，代表該行業的毛利結構正在改變。AI 公司面對的核心議題就是 COGS 從接近零變成可觀的成本—這就是為什麼分析師說「AI 的毛利不會像傳統 SaaS 那麼高」，連帶 <a href="/blog/business/knowledge-cards/valuation/" data-link-title="Valuation" data-link-desc="說明估值的構成與商業判讀作用">估值</a> 跟著被壓縮。</p>
]]></content:encoded></item><item><title>ECS</title><link>https://tarrragon.github.io/blog/infra/knowledge-cards/ecs/</link><pubDate>Fri, 26 Jun 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/infra/knowledge-cards/ecs/</guid><description>&lt;p>ECS（Elastic Container Service）的核心職責是把容器映像排程到運算資源上執行，並管理它們的生命週期 — 健康檢查、失敗重啟、滾動更新。它是 AWS 上容器工作負載的預設起點，心智負擔低於 Kubernetes（EKS），但編排彈性也較受限。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>ECS 在核心服務層裡的角色是「應用程式的執行載體」。它跑在 VPC 的 private subnet 裡，用 IAM task role 存取其他 AWS 資源，前面掛 ALB 接收流量。IaC 描述 ECS 時，重點在「接線」（subnet、security group、IAM role、target group）而非容器映像版本 — 映像版本由 CI/CD 在部署期注入。&lt;/p>
&lt;p>ECS 的執行模式分 EC2 launch type（自己管運算實例、要管 AMI 更新與 capacity provider）和 Fargate launch type（AWS 代管運算、不需管實例）。Fargate 進一步降低運維面，代價是單位成本較高（同規格約多 20-40%）且不支援 GPU workload。&lt;/p>
&lt;h2 id="可觀察訊號">可觀察訊號&lt;/h2>
&lt;p>以下狀況指向 ECS 相關問題：&lt;/p>
&lt;ul>
&lt;li>Task 頻繁被 kill 後重啟 — 健康檢查失敗或 OOM，先看 task 的 stopped reason 和 CloudWatch log&lt;/li>
&lt;li>部署後新版本遲遲不上線 — rolling update 的 minimum healthy percent 設太高，新 task 啟動空間不足&lt;/li>
&lt;li>Task 無法拉到 ECR image — 通常是 private subnet 沒有 NAT 或 VPC Endpoint 到 ECR&lt;/li>
&lt;/ul>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>使用 ECS 時要決定：&lt;/p>
&lt;ul>
&lt;li>&lt;strong>Launch type&lt;/strong>：Fargate（低運維、較高成本）還是 EC2（低成本、要管實例）。多數 web API 的初始選擇是 Fargate，流量穩定後再評估 EC2&lt;/li>
&lt;li>&lt;strong>Task IAM role&lt;/strong>：task execution role（拉 image 和寫 log 用）和 task role（應用程式存取其他 AWS 資源用）是兩個不同的 role，不要混用&lt;/li>
&lt;li>&lt;strong>映像版本解耦&lt;/strong>：task definition 裡的 image tag 由 CI/CD 部署期注入，infra code 不寫死版本號&lt;/li>
&lt;li>&lt;strong>Auto-scaling 指標&lt;/strong>：用 CPU / memory 還是 ALB request count，取決於服務是計算密集還是 IO 密集&lt;/li>
&lt;/ul>
&lt;h2 id="鄰卡">鄰卡&lt;/h2>
&lt;ul>
&lt;li>&lt;a href="https://tarrragon.github.io/blog/infra/knowledge-cards/subnet/" data-link-title="Subnet（子網路）" data-link-desc="VPC 內按可用區與暴露程度切出的子網段，決定資源有沒有一條通往網際網路的路徑">Subnet&lt;/a> — ECS task 跑在 private subnet 裡&lt;/li>
&lt;li>&lt;a href="https://tarrragon.github.io/blog/infra/knowledge-cards/security-group/" data-link-title="Security Group" data-link-desc="掛在資源網卡層級的有狀態防火牆，逐埠決定哪些來源能連進這個資源">Security Group&lt;/a> — ECS service 套用 security group 控制入站&lt;/li>
&lt;li>&lt;a href="https://tarrragon.github.io/blog/infra/knowledge-cards/iam/" data-link-title="IAM（Identity and Access Management）" data-link-desc="雲端平台的授權系統，回答「某個身分能不能對某個資源做某件事」">IAM&lt;/a> — task role 與 execution role 是 ECS 的兩個身分接線&lt;/li>
&lt;li>&lt;a href="https://tarrragon.github.io/blog/infra/knowledge-cards/alb/" data-link-title="ALB" data-link-desc="Application Load Balancer — 流量進入系統的第一站，負責 listener 路由、健康檢查與 TLS 終結">ALB&lt;/a> — 流量透過 ALB target group 導入 ECS task&lt;/li>
&lt;/ul></description><content:encoded><![CDATA[<p>ECS（Elastic Container Service）的核心職責是把容器映像排程到運算資源上執行，並管理它們的生命週期 — 健康檢查、失敗重啟、滾動更新。它是 AWS 上容器工作負載的預設起點，心智負擔低於 Kubernetes（EKS），但編排彈性也較受限。</p>
<h2 id="概念位置">概念位置</h2>
<p>ECS 在核心服務層裡的角色是「應用程式的執行載體」。它跑在 VPC 的 private subnet 裡，用 IAM task role 存取其他 AWS 資源，前面掛 ALB 接收流量。IaC 描述 ECS 時，重點在「接線」（subnet、security group、IAM role、target group）而非容器映像版本 — 映像版本由 CI/CD 在部署期注入。</p>
<p>ECS 的執行模式分 EC2 launch type（自己管運算實例、要管 AMI 更新與 capacity provider）和 Fargate launch type（AWS 代管運算、不需管實例）。Fargate 進一步降低運維面，代價是單位成本較高（同規格約多 20-40%）且不支援 GPU workload。</p>
<h2 id="可觀察訊號">可觀察訊號</h2>
<p>以下狀況指向 ECS 相關問題：</p>
<ul>
<li>Task 頻繁被 kill 後重啟 — 健康檢查失敗或 OOM，先看 task 的 stopped reason 和 CloudWatch log</li>
<li>部署後新版本遲遲不上線 — rolling update 的 minimum healthy percent 設太高，新 task 啟動空間不足</li>
<li>Task 無法拉到 ECR image — 通常是 private subnet 沒有 NAT 或 VPC Endpoint 到 ECR</li>
</ul>
<h2 id="設計責任">設計責任</h2>
<p>使用 ECS 時要決定：</p>
<ul>
<li><strong>Launch type</strong>：Fargate（低運維、較高成本）還是 EC2（低成本、要管實例）。多數 web API 的初始選擇是 Fargate，流量穩定後再評估 EC2</li>
<li><strong>Task IAM role</strong>：task execution role（拉 image 和寫 log 用）和 task role（應用程式存取其他 AWS 資源用）是兩個不同的 role，不要混用</li>
<li><strong>映像版本解耦</strong>：task definition 裡的 image tag 由 CI/CD 部署期注入，infra code 不寫死版本號</li>
<li><strong>Auto-scaling 指標</strong>：用 CPU / memory 還是 ALB request count，取決於服務是計算密集還是 IO 密集</li>
</ul>
<h2 id="鄰卡">鄰卡</h2>
<ul>
<li><a href="/blog/infra/knowledge-cards/subnet/" data-link-title="Subnet（子網路）" data-link-desc="VPC 內按可用區與暴露程度切出的子網段，決定資源有沒有一條通往網際網路的路徑">Subnet</a> — ECS task 跑在 private subnet 裡</li>
<li><a href="/blog/infra/knowledge-cards/security-group/" data-link-title="Security Group" data-link-desc="掛在資源網卡層級的有狀態防火牆，逐埠決定哪些來源能連進這個資源">Security Group</a> — ECS service 套用 security group 控制入站</li>
<li><a href="/blog/infra/knowledge-cards/iam/" data-link-title="IAM（Identity and Access Management）" data-link-desc="雲端平台的授權系統，回答「某個身分能不能對某個資源做某件事」">IAM</a> — task role 與 execution role 是 ECS 的兩個身分接線</li>
<li><a href="/blog/infra/knowledge-cards/alb/" data-link-title="ALB" data-link-desc="Application Load Balancer — 流量進入系統的第一站，負責 listener 路由、健康檢查與 TLS 終結">ALB</a> — 流量透過 ALB target group 導入 ECS task</li>
</ul>
]]></content:encoded></item><item><title>Gross Margin</title><link>https://tarrragon.github.io/blog/business/knowledge-cards/gross-margin/</link><pubDate>Tue, 19 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/business/knowledge-cards/gross-margin/</guid><description>&lt;p>Gross Margin 的核心概念是「毛利率」—收入扣掉 &lt;a href="https://tarrragon.github.io/blog/business/knowledge-cards/cogs/" data-link-title="COGS" data-link-desc="說明銷售成本與其對毛利的影響">COGS&lt;/a> 後的比例，公式 &lt;code>(收入 - COGS) ÷ 收入&lt;/code>。傳統 &lt;a href="https://tarrragon.github.io/blog/business/knowledge-cards/saas/" data-link-title="SaaS" data-link-desc="說明雲端訂閱軟體的商業模式與經濟特徵">SaaS&lt;/a> 毛利率通常在 70-80%，製造業在 20-40%，AI 產品商目前預估在 50% 出頭。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>Gross Margin 是判斷商業模式健康度的核心指標。它決定一家公司能撐多少行銷預算、能給投資人多高的 &lt;a href="https://tarrragon.github.io/blog/business/knowledge-cards/valuation/" data-link-title="Valuation" data-link-desc="說明估值的構成與商業判讀作用">估值&lt;/a>、能在價格戰中撐多久。毛利不夠厚的商業模式很難長期擴張，因為 &lt;a href="https://tarrragon.github.io/blog/business/knowledge-cards/unit-economics/" data-link-title="Unit Economics" data-link-desc="說明單位經濟模型與其判斷一家公司是否賺錢的責任">單位經濟&lt;/a> 算不過來。&lt;/p>
&lt;h2 id="可觀察訊號與例子">可觀察訊號與例子&lt;/h2>
&lt;p>判讀毛利率：低於 30% 通常是重資產業務（製造、物流），需要規模效應撐獲利；50-60% 是混合型（顧問、整合服務）；70% 以上是純軟體或高槓桿生意。AI 新創的 50% 毛利意味著「比 SaaS 差三十個百分點」—這個差距不是調漲價格能補的，&lt;a href="https://tarrragon.github.io/blog/business/knowledge-cards/plg/" data-link-title="PLG" data-link-desc="說明產品自助成長模式與其經濟前提">PLG&lt;/a> 的數學算不過來。&lt;/p>
&lt;h2 id="判讀方式">判讀方式&lt;/h2>
&lt;p>讀到「毛利壓縮」「毛利下滑」這類描述時，意味著該公司的商業模式正在從「軟體模式」滑向「服務模式」。毛利下滑直接傷估值（投資人給的倍數會降）、限制行銷支出、壓縮 &lt;a href="https://tarrragon.github.io/blog/business/knowledge-cards/burn-rate/" data-link-title="Burn Rate" data-link-desc="說明燒錢速度及其對新創存活的決定作用">燒錢空間&lt;/a>。AI 時代 SaaS 公司面對的就是這個結構性壓力，是 &lt;a href="https://tarrragon.github.io/blog/business/knowledge-cards/valuation-compression/" data-link-title="Valuation Compression" data-link-desc="說明估值壓縮如何影響新創生存">Valuation Compression&lt;/a> 的根因。&lt;/p></description><content:encoded><![CDATA[<p>Gross Margin 的核心概念是「毛利率」—收入扣掉 <a href="/blog/business/knowledge-cards/cogs/" data-link-title="COGS" data-link-desc="說明銷售成本與其對毛利的影響">COGS</a> 後的比例，公式 <code>(收入 - COGS) ÷ 收入</code>。傳統 <a href="/blog/business/knowledge-cards/saas/" data-link-title="SaaS" data-link-desc="說明雲端訂閱軟體的商業模式與經濟特徵">SaaS</a> 毛利率通常在 70-80%，製造業在 20-40%，AI 產品商目前預估在 50% 出頭。</p>
<h2 id="概念位置">概念位置</h2>
<p>Gross Margin 是判斷商業模式健康度的核心指標。它決定一家公司能撐多少行銷預算、能給投資人多高的 <a href="/blog/business/knowledge-cards/valuation/" data-link-title="Valuation" data-link-desc="說明估值的構成與商業判讀作用">估值</a>、能在價格戰中撐多久。毛利不夠厚的商業模式很難長期擴張，因為 <a href="/blog/business/knowledge-cards/unit-economics/" data-link-title="Unit Economics" data-link-desc="說明單位經濟模型與其判斷一家公司是否賺錢的責任">單位經濟</a> 算不過來。</p>
<h2 id="可觀察訊號與例子">可觀察訊號與例子</h2>
<p>判讀毛利率：低於 30% 通常是重資產業務（製造、物流），需要規模效應撐獲利；50-60% 是混合型（顧問、整合服務）；70% 以上是純軟體或高槓桿生意。AI 新創的 50% 毛利意味著「比 SaaS 差三十個百分點」—這個差距不是調漲價格能補的，<a href="/blog/business/knowledge-cards/plg/" data-link-title="PLG" data-link-desc="說明產品自助成長模式與其經濟前提">PLG</a> 的數學算不過來。</p>
<h2 id="判讀方式">判讀方式</h2>
<p>讀到「毛利壓縮」「毛利下滑」這類描述時，意味著該公司的商業模式正在從「軟體模式」滑向「服務模式」。毛利下滑直接傷估值（投資人給的倍數會降）、限制行銷支出、壓縮 <a href="/blog/business/knowledge-cards/burn-rate/" data-link-title="Burn Rate" data-link-desc="說明燒錢速度及其對新創存活的決定作用">燒錢空間</a>。AI 時代 SaaS 公司面對的就是這個結構性壓力，是 <a href="/blog/business/knowledge-cards/valuation-compression/" data-link-title="Valuation Compression" data-link-desc="說明估值壓縮如何影響新創生存">Valuation Compression</a> 的根因。</p>
]]></content:encoded></item><item><title>ALB</title><link>https://tarrragon.github.io/blog/infra/knowledge-cards/alb/</link><pubDate>Fri, 26 Jun 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/infra/knowledge-cards/alb/</guid><description>&lt;p>ALB（Application Load Balancer）的核心職責是接收外部流量、根據規則（path、host header）把請求路由到後端的 target group，並用健康檢查持續驗證後端是否能服務。它是系統對外的第一個接觸點，跑在 public subnet 裡。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>ALB 在核心服務層裡的角色是「入口設施」。它掛在 public subnet 的 security group 上（入站允許 80/443），把流量導向 private subnet 裡的 ECS task 或 EC2 instance。ALB 本身是 stateless 的 — 重建一個 ALB 不會遺失資料，但會換掉它的 DNS 名稱，所以對外服務通常在 ALB 前面掛一個穩定的 Route 53 alias record。&lt;/p>
&lt;p>TLS 終結是 ALB 的標準職責：HTTPS listener 引用 ACM（AWS Certificate Manager）簽發的憑證，ALB 處理加解密，後端收到的是 HTTP 明文。憑證由 ACM 自動續期，IaC 用 DNS 驗證方式描述憑證 — 讓「憑證存在、續期、掛載」整條鏈都進版本控制。&lt;/p>
&lt;h2 id="可觀察訊號">可觀察訊號&lt;/h2>
&lt;p>以下狀況指向 ALB 相關問題：&lt;/p>
&lt;ul>
&lt;li>使用者看到 502 — ALB 轉發請求但後端回應異常（健康檢查可能通過但實際請求處理失敗），查 target group 的健康狀態和後端 log&lt;/li>
&lt;li>使用者看到 503 — target group 裡沒有健康的後端，通常是部署期間所有舊 task 停了但新 task 還沒通過健康檢查&lt;/li>
&lt;li>HTTPS 憑證過期警告 — 如果用 ACM 搭配 DNS 驗證，憑證自動續期；看到過期警告代表 DNS 驗證記錄被刪了或 ACM 服務異常&lt;/li>
&lt;/ul>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>使用 ALB 時要決定：&lt;/p>
&lt;ul>
&lt;li>&lt;strong>健康檢查參數&lt;/strong>：檢查路徑（用應用層的 health endpoint、不用根路徑）、間隔、閾值。閾值太寬鬆會把壞掉的後端留在輪替裡，太嚴格會在部署瞬間誤判&lt;/li>
&lt;li>&lt;strong>HTTP → HTTPS redirect&lt;/strong>：port 80 的 listener 設定固定回應 301 redirect 到 443，確保所有流量走加密&lt;/li>
&lt;li>&lt;strong>TLS 憑證&lt;/strong>：用 ACM 搭配 DNS 驗證，讓憑證的簽發和續期自動化&lt;/li>
&lt;li>&lt;strong>穩定 DNS&lt;/strong>：ALB 前面掛 Route 53 alias record，對外暴露的是自己的 domain name 而非 ALB 的隨機 hostname&lt;/li>
&lt;/ul>
&lt;h2 id="鄰卡">鄰卡&lt;/h2>
&lt;ul>
&lt;li>&lt;a href="https://tarrragon.github.io/blog/infra/knowledge-cards/subnet/" data-link-title="Subnet（子網路）" data-link-desc="VPC 內按可用區與暴露程度切出的子網段，決定資源有沒有一條通往網際網路的路徑">Subnet&lt;/a> — ALB 跑在 public subnet，後端跑在 private subnet&lt;/li>
&lt;li>&lt;a href="https://tarrragon.github.io/blog/infra/knowledge-cards/security-group/" data-link-title="Security Group" data-link-desc="掛在資源網卡層級的有狀態防火牆，逐埠決定哪些來源能連進這個資源">Security Group&lt;/a> — ALB 的 security group 是系統對外唯一合理開放 0.0.0.0/0 的位置（僅限 80/443）&lt;/li>
&lt;li>&lt;a href="https://tarrragon.github.io/blog/infra/knowledge-cards/ecs/" data-link-title="ECS" data-link-desc="AWS Elastic Container Service — 受管的容器編排服務，用 task definition 描述容器配置、由平台負責排程與健康管理">ECS&lt;/a> — ALB 透過 target group 把流量導向 ECS task&lt;/li>
&lt;/ul></description><content:encoded><![CDATA[<p>ALB（Application Load Balancer）的核心職責是接收外部流量、根據規則（path、host header）把請求路由到後端的 target group，並用健康檢查持續驗證後端是否能服務。它是系統對外的第一個接觸點，跑在 public subnet 裡。</p>
<h2 id="概念位置">概念位置</h2>
<p>ALB 在核心服務層裡的角色是「入口設施」。它掛在 public subnet 的 security group 上（入站允許 80/443），把流量導向 private subnet 裡的 ECS task 或 EC2 instance。ALB 本身是 stateless 的 — 重建一個 ALB 不會遺失資料，但會換掉它的 DNS 名稱，所以對外服務通常在 ALB 前面掛一個穩定的 Route 53 alias record。</p>
<p>TLS 終結是 ALB 的標準職責：HTTPS listener 引用 ACM（AWS Certificate Manager）簽發的憑證，ALB 處理加解密，後端收到的是 HTTP 明文。憑證由 ACM 自動續期，IaC 用 DNS 驗證方式描述憑證 — 讓「憑證存在、續期、掛載」整條鏈都進版本控制。</p>
<h2 id="可觀察訊號">可觀察訊號</h2>
<p>以下狀況指向 ALB 相關問題：</p>
<ul>
<li>使用者看到 502 — ALB 轉發請求但後端回應異常（健康檢查可能通過但實際請求處理失敗），查 target group 的健康狀態和後端 log</li>
<li>使用者看到 503 — target group 裡沒有健康的後端，通常是部署期間所有舊 task 停了但新 task 還沒通過健康檢查</li>
<li>HTTPS 憑證過期警告 — 如果用 ACM 搭配 DNS 驗證，憑證自動續期；看到過期警告代表 DNS 驗證記錄被刪了或 ACM 服務異常</li>
</ul>
<h2 id="設計責任">設計責任</h2>
<p>使用 ALB 時要決定：</p>
<ul>
<li><strong>健康檢查參數</strong>：檢查路徑（用應用層的 health endpoint、不用根路徑）、間隔、閾值。閾值太寬鬆會把壞掉的後端留在輪替裡，太嚴格會在部署瞬間誤判</li>
<li><strong>HTTP → HTTPS redirect</strong>：port 80 的 listener 設定固定回應 301 redirect 到 443，確保所有流量走加密</li>
<li><strong>TLS 憑證</strong>：用 ACM 搭配 DNS 驗證，讓憑證的簽發和續期自動化</li>
<li><strong>穩定 DNS</strong>：ALB 前面掛 Route 53 alias record，對外暴露的是自己的 domain name 而非 ALB 的隨機 hostname</li>
</ul>
<h2 id="鄰卡">鄰卡</h2>
<ul>
<li><a href="/blog/infra/knowledge-cards/subnet/" data-link-title="Subnet（子網路）" data-link-desc="VPC 內按可用區與暴露程度切出的子網段，決定資源有沒有一條通往網際網路的路徑">Subnet</a> — ALB 跑在 public subnet，後端跑在 private subnet</li>
<li><a href="/blog/infra/knowledge-cards/security-group/" data-link-title="Security Group" data-link-desc="掛在資源網卡層級的有狀態防火牆，逐埠決定哪些來源能連進這個資源">Security Group</a> — ALB 的 security group 是系統對外唯一合理開放 0.0.0.0/0 的位置（僅限 80/443）</li>
<li><a href="/blog/infra/knowledge-cards/ecs/" data-link-title="ECS" data-link-desc="AWS Elastic Container Service — 受管的容器編排服務，用 task definition 描述容器配置、由平台負責排程與健康管理">ECS</a> — ALB 透過 target group 把流量導向 ECS task</li>
</ul>
]]></content:encoded></item><item><title>Marginal Cost</title><link>https://tarrragon.github.io/blog/business/knowledge-cards/marginal-cost/</link><pubDate>Tue, 19 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/business/knowledge-cards/marginal-cost/</guid><description>&lt;p>Marginal Cost 的核心概念是「多服務一個客戶要多花多少錢」。傳統軟體寫一次賣無數次，每多一個客戶幾乎沒成本（邊際成本接近零）。AI 推論每跑一次都燒實際算力，邊際成本是真實的線性支出。邊際成本特性決定 &lt;a href="https://tarrragon.github.io/blog/business/knowledge-cards/plg/" data-link-title="PLG" data-link-desc="說明產品自助成長模式與其經濟前提">PLG&lt;/a> 是否可行。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>Marginal Cost 是 &lt;a href="https://tarrragon.github.io/blog/business/knowledge-cards/saas/" data-link-title="SaaS" data-link-desc="說明雲端訂閱軟體的商業模式與經濟特徵">SaaS&lt;/a> 模式之所以能擴張的根基。零邊際成本讓 &lt;a href="https://tarrragon.github.io/blog/business/knowledge-cards/plg/" data-link-title="PLG" data-link-desc="說明產品自助成長模式與其經濟前提">PLG&lt;/a> 數學算得過去—免費試用、口碑擴散、自助上手都不會傷成本。一旦邊際成本不再是零，PLG 模式就會撐不住，要回到傳統的高接觸銷售。&lt;/p>
&lt;h2 id="可觀察訊號與例子">可觀察訊號與例子&lt;/h2>
&lt;p>判讀邊際成本：軟體下載一份檔案，邊際成本近零；雲端 API 每次呼叫，邊際成本等於底層運算成本；AI 模型每次推論，邊際成本是 GPU 時間。Netflix 多一個觀眾的邊際成本接近零（CDN 已經攤平）；Uber 多一筆訂單的邊際成本可觀（要付司機）。前者能擴張到全球同樣便宜，後者規模再大邊際還是要花錢。&lt;/p>
&lt;h2 id="判讀方式">判讀方式&lt;/h2>
&lt;p>當分析師說「邊際成本不再是零」時，通常在指出某個原本被視為 SaaS 的賽道其實更接近服務業。AI 產品就是典型例子—它看起來像軟體，但每次回答都是真實算力支出。這個訊號直接影響 &lt;a href="https://tarrragon.github.io/blog/business/knowledge-cards/plg/" data-link-title="PLG" data-link-desc="說明產品自助成長模式與其經濟前提">商業模式選擇&lt;/a>、&lt;a href="https://tarrragon.github.io/blog/business/knowledge-cards/gross-margin/" data-link-title="Gross Margin" data-link-desc="說明毛利率與其對商業模式可行性的決定作用">毛利&lt;/a> 結構與 &lt;a href="https://tarrragon.github.io/blog/business/knowledge-cards/valuation/" data-link-title="Valuation" data-link-desc="說明估值的構成與商業判讀作用">估值&lt;/a> 邏輯。&lt;/p></description><content:encoded><![CDATA[<p>Marginal Cost 的核心概念是「多服務一個客戶要多花多少錢」。傳統軟體寫一次賣無數次，每多一個客戶幾乎沒成本（邊際成本接近零）。AI 推論每跑一次都燒實際算力，邊際成本是真實的線性支出。邊際成本特性決定 <a href="/blog/business/knowledge-cards/plg/" data-link-title="PLG" data-link-desc="說明產品自助成長模式與其經濟前提">PLG</a> 是否可行。</p>
<h2 id="概念位置">概念位置</h2>
<p>Marginal Cost 是 <a href="/blog/business/knowledge-cards/saas/" data-link-title="SaaS" data-link-desc="說明雲端訂閱軟體的商業模式與經濟特徵">SaaS</a> 模式之所以能擴張的根基。零邊際成本讓 <a href="/blog/business/knowledge-cards/plg/" data-link-title="PLG" data-link-desc="說明產品自助成長模式與其經濟前提">PLG</a> 數學算得過去—免費試用、口碑擴散、自助上手都不會傷成本。一旦邊際成本不再是零，PLG 模式就會撐不住，要回到傳統的高接觸銷售。</p>
<h2 id="可觀察訊號與例子">可觀察訊號與例子</h2>
<p>判讀邊際成本：軟體下載一份檔案，邊際成本近零；雲端 API 每次呼叫，邊際成本等於底層運算成本；AI 模型每次推論，邊際成本是 GPU 時間。Netflix 多一個觀眾的邊際成本接近零（CDN 已經攤平）；Uber 多一筆訂單的邊際成本可觀（要付司機）。前者能擴張到全球同樣便宜，後者規模再大邊際還是要花錢。</p>
<h2 id="判讀方式">判讀方式</h2>
<p>當分析師說「邊際成本不再是零」時，通常在指出某個原本被視為 SaaS 的賽道其實更接近服務業。AI 產品就是典型例子—它看起來像軟體，但每次回答都是真實算力支出。這個訊號直接影響 <a href="/blog/business/knowledge-cards/plg/" data-link-title="PLG" data-link-desc="說明產品自助成長模式與其經濟前提">商業模式選擇</a>、<a href="/blog/business/knowledge-cards/gross-margin/" data-link-title="Gross Margin" data-link-desc="說明毛利率與其對商業模式可行性的決定作用">毛利</a> 結構與 <a href="/blog/business/knowledge-cards/valuation/" data-link-title="Valuation" data-link-desc="說明估值的構成與商業判讀作用">估值</a> 邏輯。</p>
]]></content:encoded></item><item><title>CIDR（Classless Inter-Domain Routing）</title><link>https://tarrragon.github.io/blog/infra/knowledge-cards/cidr/</link><pubDate>Fri, 26 Jun 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/infra/knowledge-cards/cidr/</guid><description>&lt;p>CIDR（Classless Inter-Domain Routing）用前綴長度表示一段 IP 地址範圍。&lt;code>10.0.0.0/16&lt;/code> 表示前 16 bit 是網路位址、後 16 bit 是主機位址，提供約六萬五千個可用位址。前綴越短、範圍越大：&lt;code>/16&lt;/code> 比 &lt;code>/24&lt;/code>（約 256 個位址）大 256 倍。&lt;a href="https://tarrragon.github.io/blog/infra/knowledge-cards/vpc/" data-link-title="VPC（Virtual Private Cloud）" data-link-desc="雲端帳號內的一塊邏輯隔離私有網段，是所有網路切分的起點與容器">VPC&lt;/a> 和 &lt;a href="https://tarrragon.github.io/blog/infra/knowledge-cards/subnet/" data-link-title="Subnet（子網路）" data-link-desc="VPC 內按可用區與暴露程度切出的子網段，決定資源有沒有一條通往網際網路的路徑">subnet&lt;/a> 的地址空間都用 CIDR 表示。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>CIDR 是 VPC 規劃的起點決策。建立 VPC 時指定的 CIDR 區塊決定了這個 VPC 能容納多少 subnet 和多少資源。這個決策在建立後難以修改——事後擴張意味著追加 secondary CIDR，而追加的網段在 routing 與服務相容性上有限制。&lt;/p>
&lt;p>在 infra 系列中，CIDR 規劃出現在&lt;a href="https://tarrragon.github.io/blog/infra/03-network-foundation/vpc-subnet-security-group/" data-link-title="網路地基 — VPC、subnet 分層與 security group 設計" data-link-desc="VPC CIDR 規劃、public / private subnet 切分、route table 與 NAT 的可用性成本取捨、security group 最小開放設計，以及 NACL 的定位">模組三：網路地基&lt;/a>的 VPC 段落。Terraform 的 &lt;code>cidrsubnet&lt;/code> 函式可以從 VPC 的 CIDR 自動切出 subnet 的子網段，避免手動計算。&lt;/p>
&lt;h2 id="可觀察訊號">可觀察訊號&lt;/h2>
&lt;p>CIDR 規劃出問題的訊號有兩類。第一類是地址耗盡：subnet 切不出新的子網段、或 subnet 內的 IP 分配用完，新資源無法取得位址。第二類是網段衝突：需要透過 VPC peering、Transit Gateway 或 VPN 互連兩個 VPC 時，發現兩端的 CIDR 重疊，路由無法解析，peering 建立失敗。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>規劃 CIDR 時要決定：&lt;/p>
&lt;ul>
&lt;li>大小：單一環境用 &lt;code>/16&lt;/code> 通常足夠寬裕，切成 &lt;code>/20&lt;/code> 的 subnet 可分配 16 個子網段&lt;/li>
&lt;li>不重疊：多個環境（dev &lt;code>10.0.0.0/16&lt;/code>、staging &lt;code>10.1.0.0/16&lt;/code>、prod &lt;code>10.2.0.0/16&lt;/code>）用連續但不重疊的區段，為日後互連預留空間&lt;/li>
&lt;li>與地端的協調：如果未來可能接 VPN 回地端機房，CIDR 要避開地端已使用的私有網段&lt;/li>
&lt;/ul>
&lt;h2 id="鄰卡">鄰卡&lt;/h2>
&lt;ul>
&lt;li>&lt;a href="https://tarrragon.github.io/blog/infra/knowledge-cards/vpc/" data-link-title="VPC（Virtual Private Cloud）" data-link-desc="雲端帳號內的一塊邏輯隔離私有網段，是所有網路切分的起點與容器">VPC&lt;/a> — 用 CIDR 區塊定義的邏輯隔離網段&lt;/li>
&lt;li>&lt;a href="https://tarrragon.github.io/blog/infra/knowledge-cards/subnet/" data-link-title="Subnet（子網路）" data-link-desc="VPC 內按可用區與暴露程度切出的子網段，決定資源有沒有一條通往網際網路的路徑">Subnet&lt;/a> — 從 VPC CIDR 切出的子網段&lt;/li>
&lt;/ul></description><content:encoded><![CDATA[<p>CIDR（Classless Inter-Domain Routing）用前綴長度表示一段 IP 地址範圍。<code>10.0.0.0/16</code> 表示前 16 bit 是網路位址、後 16 bit 是主機位址，提供約六萬五千個可用位址。前綴越短、範圍越大：<code>/16</code> 比 <code>/24</code>（約 256 個位址）大 256 倍。<a href="/blog/infra/knowledge-cards/vpc/" data-link-title="VPC（Virtual Private Cloud）" data-link-desc="雲端帳號內的一塊邏輯隔離私有網段，是所有網路切分的起點與容器">VPC</a> 和 <a href="/blog/infra/knowledge-cards/subnet/" data-link-title="Subnet（子網路）" data-link-desc="VPC 內按可用區與暴露程度切出的子網段，決定資源有沒有一條通往網際網路的路徑">subnet</a> 的地址空間都用 CIDR 表示。</p>
<h2 id="概念位置">概念位置</h2>
<p>CIDR 是 VPC 規劃的起點決策。建立 VPC 時指定的 CIDR 區塊決定了這個 VPC 能容納多少 subnet 和多少資源。這個決策在建立後難以修改——事後擴張意味著追加 secondary CIDR，而追加的網段在 routing 與服務相容性上有限制。</p>
<p>在 infra 系列中，CIDR 規劃出現在<a href="/blog/infra/03-network-foundation/vpc-subnet-security-group/" data-link-title="網路地基 — VPC、subnet 分層與 security group 設計" data-link-desc="VPC CIDR 規劃、public / private subnet 切分、route table 與 NAT 的可用性成本取捨、security group 最小開放設計，以及 NACL 的定位">模組三：網路地基</a>的 VPC 段落。Terraform 的 <code>cidrsubnet</code> 函式可以從 VPC 的 CIDR 自動切出 subnet 的子網段，避免手動計算。</p>
<h2 id="可觀察訊號">可觀察訊號</h2>
<p>CIDR 規劃出問題的訊號有兩類。第一類是地址耗盡：subnet 切不出新的子網段、或 subnet 內的 IP 分配用完，新資源無法取得位址。第二類是網段衝突：需要透過 VPC peering、Transit Gateway 或 VPN 互連兩個 VPC 時，發現兩端的 CIDR 重疊，路由無法解析，peering 建立失敗。</p>
<h2 id="設計責任">設計責任</h2>
<p>規劃 CIDR 時要決定：</p>
<ul>
<li>大小：單一環境用 <code>/16</code> 通常足夠寬裕，切成 <code>/20</code> 的 subnet 可分配 16 個子網段</li>
<li>不重疊：多個環境（dev <code>10.0.0.0/16</code>、staging <code>10.1.0.0/16</code>、prod <code>10.2.0.0/16</code>）用連續但不重疊的區段，為日後互連預留空間</li>
<li>與地端的協調：如果未來可能接 VPN 回地端機房，CIDR 要避開地端已使用的私有網段</li>
</ul>
<h2 id="鄰卡">鄰卡</h2>
<ul>
<li><a href="/blog/infra/knowledge-cards/vpc/" data-link-title="VPC（Virtual Private Cloud）" data-link-desc="雲端帳號內的一塊邏輯隔離私有網段，是所有網路切分的起點與容器">VPC</a> — 用 CIDR 區塊定義的邏輯隔離網段</li>
<li><a href="/blog/infra/knowledge-cards/subnet/" data-link-title="Subnet（子網路）" data-link-desc="VPC 內按可用區與暴露程度切出的子網段，決定資源有沒有一條通往網際網路的路徑">Subnet</a> — 從 VPC CIDR 切出的子網段</li>
</ul>
]]></content:encoded></item><item><title>P&amp;L</title><link>https://tarrragon.github.io/blog/business/knowledge-cards/pnl/</link><pubDate>Tue, 19 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/business/knowledge-cards/pnl/</guid><description>&lt;p>P&amp;amp;L 的核心概念是「Profit and Loss，損益表」—一段期間內的收入、成本、費用與利潤的財務報表。標準結構：收入 → 扣 &lt;a href="https://tarrragon.github.io/blog/business/knowledge-cards/cogs/" data-link-title="COGS" data-link-desc="說明銷售成本與其對毛利的影響">COGS&lt;/a> → &lt;a href="https://tarrragon.github.io/blog/business/knowledge-cards/gross-margin/" data-link-title="Gross Margin" data-link-desc="說明毛利率與其對商業模式可行性的決定作用">毛利&lt;/a> → 扣營業費用 → 營業利益 → 扣稅 → 淨利。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>P&amp;amp;L 是判讀一家公司是否賺錢的核心報表。投資人看 P&amp;amp;L 判斷 &lt;a href="https://tarrragon.github.io/blog/business/knowledge-cards/gross-margin/" data-link-title="Gross Margin" data-link-desc="說明毛利率與其對商業模式可行性的決定作用">毛利&lt;/a> 是否健康、&lt;a href="https://tarrragon.github.io/blog/business/knowledge-cards/burn-rate/" data-link-title="Burn Rate" data-link-desc="說明燒錢速度及其對新創存活的決定作用">燒錢速度&lt;/a> 是否合理、&lt;a href="https://tarrragon.github.io/blog/business/knowledge-cards/unit-economics/" data-link-title="Unit Economics" data-link-desc="說明單位經濟模型與其判斷一家公司是否賺錢的責任">單位經濟&lt;/a> 是否成立。新創討論「P&amp;amp;L 跑不過去」通常指收入扣完成本費用後仍是大幅虧損。&lt;/p>
&lt;h2 id="可觀察訊號與例子">可觀察訊號與例子&lt;/h2>
&lt;p>判讀 P&amp;amp;L 的關鍵欄位：毛利率（看商業模式效率）、營業費用比（看銷售行銷研發是否過大）、淨利率（看最終盈利能力）。SaaS 新創早期通常毛利高但因為 &lt;a href="https://tarrragon.github.io/blog/business/knowledge-cards/cac/" data-link-title="CAC" data-link-desc="說明獲客成本及其對商業模式可行性的決定作用">獲客成本&lt;/a> 大導致淨利為負，這是正常的；如果毛利就低、淨利又負，那是商業模式有問題。&lt;/p>
&lt;h2 id="判讀方式">判讀方式&lt;/h2>
&lt;p>分析師說「P&amp;amp;L 更難跑」時，通常指該行業的毛利、CAC、retention 三個面向結構性惡化，連業績好的公司都難擠出淨利。AI 新創就是這個訊號—就算產品做得比大廠好，因為要付 token 費給上游 Labs，P&amp;amp;L 表現會比傳統 SaaS 弱很多，連帶 &lt;a href="https://tarrragon.github.io/blog/business/knowledge-cards/valuation/" data-link-title="Valuation" data-link-desc="說明估值的構成與商業判讀作用">估值&lt;/a> 被壓縮。&lt;/p></description><content:encoded><![CDATA[<p>P&amp;L 的核心概念是「Profit and Loss，損益表」—一段期間內的收入、成本、費用與利潤的財務報表。標準結構：收入 → 扣 <a href="/blog/business/knowledge-cards/cogs/" data-link-title="COGS" data-link-desc="說明銷售成本與其對毛利的影響">COGS</a> → <a href="/blog/business/knowledge-cards/gross-margin/" data-link-title="Gross Margin" data-link-desc="說明毛利率與其對商業模式可行性的決定作用">毛利</a> → 扣營業費用 → 營業利益 → 扣稅 → 淨利。</p>
<h2 id="概念位置">概念位置</h2>
<p>P&amp;L 是判讀一家公司是否賺錢的核心報表。投資人看 P&amp;L 判斷 <a href="/blog/business/knowledge-cards/gross-margin/" data-link-title="Gross Margin" data-link-desc="說明毛利率與其對商業模式可行性的決定作用">毛利</a> 是否健康、<a href="/blog/business/knowledge-cards/burn-rate/" data-link-title="Burn Rate" data-link-desc="說明燒錢速度及其對新創存活的決定作用">燒錢速度</a> 是否合理、<a href="/blog/business/knowledge-cards/unit-economics/" data-link-title="Unit Economics" data-link-desc="說明單位經濟模型與其判斷一家公司是否賺錢的責任">單位經濟</a> 是否成立。新創討論「P&amp;L 跑不過去」通常指收入扣完成本費用後仍是大幅虧損。</p>
<h2 id="可觀察訊號與例子">可觀察訊號與例子</h2>
<p>判讀 P&amp;L 的關鍵欄位：毛利率（看商業模式效率）、營業費用比（看銷售行銷研發是否過大）、淨利率（看最終盈利能力）。SaaS 新創早期通常毛利高但因為 <a href="/blog/business/knowledge-cards/cac/" data-link-title="CAC" data-link-desc="說明獲客成本及其對商業模式可行性的決定作用">獲客成本</a> 大導致淨利為負，這是正常的；如果毛利就低、淨利又負，那是商業模式有問題。</p>
<h2 id="判讀方式">判讀方式</h2>
<p>分析師說「P&amp;L 更難跑」時，通常指該行業的毛利、CAC、retention 三個面向結構性惡化，連業績好的公司都難擠出淨利。AI 新創就是這個訊號—就算產品做得比大廠好，因為要付 token 費給上游 Labs，P&amp;L 表現會比傳統 SaaS 弱很多，連帶 <a href="/blog/business/knowledge-cards/valuation/" data-link-title="Valuation" data-link-desc="說明估值的構成與商業判讀作用">估值</a> 被壓縮。</p>
]]></content:encoded></item><item><title>字型的可用集合在 process 啟動時決定</title><link>https://tarrragon.github.io/blog/linux/dotfile/knowledge-cards/font-availability-at-startup/</link><pubDate>Wed, 01 Jul 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/linux/dotfile/knowledge-cards/font-availability-at-startup/</guid><description>&lt;p>一個 process 能用哪些字型，是在它&lt;strong>啟動的當下&lt;/strong>由 fontconfig（Linux 上統一管理字型搜尋與匹配的底層服務）決定並載入記憶體的。之後往系統裝新字型，不會回頭改變已經在跑的 process——它手上那份字型清單是啟動時的快照。「裝了字型卻還是豆腐」多數時候指向的是這個時序問題，而非安裝本身失敗。&lt;/p>
&lt;p>這個機制發生在 fontconfig + process 記憶體層，跟顯示協議無關——Wayland 和 X11 下的行為相同。&lt;/p>
&lt;h2 id="同一時刻兩種查詢結果">同一時刻、兩種查詢結果&lt;/h2>
&lt;p>裝完新字型後，在終端機用 fontconfig 的查詢工具 &lt;code>fc-match&lt;/code>（每次執行都是新 process）去查：&lt;/p>





&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-bash" data-lang="bash">&lt;span class="line">&lt;span class="ln">1&lt;/span>&lt;span class="cl">fc-match &lt;span class="s2">&amp;#34;:lang=zh-tw&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">2&lt;/span>&lt;span class="cl">&lt;span class="c1"># Noto Sans CJK → 系統快取已有這支字&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>查得到。但同時間，一直開著的狀態列或通知 daemon 仍顯示豆腐。矛盾的根源是兩者的啟動時間不同：&lt;code>fc-match&lt;/code> 剛啟動、讀到的是最新系統快取；那個豆腐的 daemon 是在裝字型&lt;strong>之前&lt;/strong>啟動的，記憶體裡的字型清單沒有這支字。&lt;/p>
&lt;p>套件管理器安裝字型時，post-install hook 通常已更新 fontconfig 的系統快取（pacman 會印 &lt;code>Updating fontconfig cache&lt;/code>）。手動把字型檔放進 &lt;code>~/.local/share/fonts/&lt;/code> 的情況下，需要自己跑 fontconfig 的快取重建工具 &lt;code>fc-cache&lt;/code>：&lt;/p>





&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-bash" data-lang="bash">&lt;span class="line">&lt;span class="ln">1&lt;/span>&lt;span class="cl">fc-cache -fv
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">2&lt;/span>&lt;span class="cl">&lt;span class="c1"># -f 忽略時間戳、強制全部重建&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">3&lt;/span>&lt;span class="cl">&lt;span class="c1"># -v 印出處理了哪些目錄&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>&lt;code>fc-cache&lt;/code> 只更新系統快取層——磁碟上的索引檔。它不會觸及任何已啟動 process 的記憶體，跑再多次也改變不了舊 process 的字型清單。&lt;/p>
&lt;h2 id="判讀與操作">判讀與操作&lt;/h2>
&lt;p>&lt;strong>判讀訊號&lt;/strong>：&lt;code>fc-match&lt;/code> 在命令列回得出正確字型，但某個一直開著的程式仍顯示豆腐，幾乎可確定是「那個程式啟動早於裝字型」。&lt;/p>
&lt;p>&lt;strong>修法是重啟該程式，不是 reload&lt;/strong>。&lt;code>reload&lt;/code> 類指令（如 &lt;code>makoctl reload&lt;/code>、送 SIGHUP）重讀的是&lt;strong>設定檔&lt;/strong>——能換到 daemon 啟動時已可見的字型（例如從 A 字族改成 B 字族），但看不到啟動後才新裝的字型檔。根源是 reload 不重建記憶體裡的字型清單，只有重啟 process 才會從系統快取重新載入。&lt;/p>
&lt;p>&lt;strong>重啟的範圍&lt;/strong>取決於受影響的程式數量。單一 daemon（通知、狀態列）重啟那一個即可；由 compositor &lt;code>exec-once&lt;/code> 拉起的一批元件要同時吃到新字型，最乾淨的做法是重新登入，讓它們全部重新啟動。&lt;/p>
&lt;p>&lt;strong>正常開機不會踩到這個坑&lt;/strong>——字型在開機早期就裝好，&lt;code>exec-once&lt;/code> 啟動的元件從一開始就看得到完整字型集合。這個時序問題集中在「系統已經在跑、中途才補裝字型」的除錯情境。&lt;/p>
&lt;p>&lt;strong>延伸閱讀&lt;/strong>：Nerd Font 不含 CJK、需另裝 fallback 字型的具體案例見&lt;a href="https://tarrragon.github.io/blog/linux/dotfile/06-rice-design/desktop-shell-components/" data-link-title="桌面 Shell 元件：狀態列、啟動器與通知" data-link-desc="Hyprland 桌面要拼哪些元件、各元件的配置檔怎麼寫時回來讀">桌面 Shell 元件：狀態列、啟動器與通知&lt;/a>；字型安裝方式見&lt;a href="https://tarrragon.github.io/blog/linux/dotfile/03-terminal-ecosystem/terminal-emulator-config/" data-link-title="Terminal Emulator 配置" data-link-desc="選 terminal emulator 時需要比對配置格式和跨平台能力、或想把配色和字型統一管理時回來讀">終端機與編輯器配置&lt;/a>的字型管理段。&lt;/p>
&lt;h2 id="邊界與例外">邊界與例外&lt;/h2>
&lt;p>&lt;strong>fc-match 也查不到&lt;/strong>：連新 process 都找不到剛裝的字型，問題在系統快取層（fontconfig 索引未更新），跑 &lt;code>fc-cache -fv&lt;/code> 解決。兩層的修法不同，&lt;code>fc-match&lt;/code> 是分辨在哪一層的第一步。&lt;/p>
&lt;p>&lt;strong>部分應用程式支援熱載入&lt;/strong>：瀏覽器等有獨立字型服務的程式可能在開新分頁時重新掃描字型，不需要重啟整個 process。長駐 daemon（mako、waybar）與狀態列預設是啟動時載入一次。&lt;/p>
&lt;p>&lt;strong>Flatpak / Snap 的字型隔離是不同問題&lt;/strong>：沙箱化應用程式看不到 host 的字型目錄，重啟 process 也無法解決——原因不是時序，而是沙箱的檔案系統隔離。需要透過 Flatpak 的 filesystem override 或把字型放進沙箱可存取的路徑。&lt;/p></description><content:encoded><![CDATA[<p>一個 process 能用哪些字型，是在它<strong>啟動的當下</strong>由 fontconfig（Linux 上統一管理字型搜尋與匹配的底層服務）決定並載入記憶體的。之後往系統裝新字型，不會回頭改變已經在跑的 process——它手上那份字型清單是啟動時的快照。「裝了字型卻還是豆腐」多數時候指向的是這個時序問題，而非安裝本身失敗。</p>
<p>這個機制發生在 fontconfig + process 記憶體層，跟顯示協議無關——Wayland 和 X11 下的行為相同。</p>
<h2 id="同一時刻兩種查詢結果">同一時刻、兩種查詢結果</h2>
<p>裝完新字型後，在終端機用 fontconfig 的查詢工具 <code>fc-match</code>（每次執行都是新 process）去查：</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="ln">1</span><span class="cl">fc-match <span class="s2">&#34;:lang=zh-tw&#34;</span>
</span></span><span class="line"><span class="ln">2</span><span class="cl"><span class="c1"># Noto Sans CJK → 系統快取已有這支字</span></span></span></code></pre></div><p>查得到。但同時間，一直開著的狀態列或通知 daemon 仍顯示豆腐。矛盾的根源是兩者的啟動時間不同：<code>fc-match</code> 剛啟動、讀到的是最新系統快取；那個豆腐的 daemon 是在裝字型<strong>之前</strong>啟動的，記憶體裡的字型清單沒有這支字。</p>
<p>套件管理器安裝字型時，post-install hook 通常已更新 fontconfig 的系統快取（pacman 會印 <code>Updating fontconfig cache</code>）。手動把字型檔放進 <code>~/.local/share/fonts/</code> 的情況下，需要自己跑 fontconfig 的快取重建工具 <code>fc-cache</code>：</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="ln">1</span><span class="cl">fc-cache -fv
</span></span><span class="line"><span class="ln">2</span><span class="cl"><span class="c1"># -f 忽略時間戳、強制全部重建</span>
</span></span><span class="line"><span class="ln">3</span><span class="cl"><span class="c1"># -v 印出處理了哪些目錄</span></span></span></code></pre></div><p><code>fc-cache</code> 只更新系統快取層——磁碟上的索引檔。它不會觸及任何已啟動 process 的記憶體，跑再多次也改變不了舊 process 的字型清單。</p>
<h2 id="判讀與操作">判讀與操作</h2>
<p><strong>判讀訊號</strong>：<code>fc-match</code> 在命令列回得出正確字型，但某個一直開著的程式仍顯示豆腐，幾乎可確定是「那個程式啟動早於裝字型」。</p>
<p><strong>修法是重啟該程式，不是 reload</strong>。<code>reload</code> 類指令（如 <code>makoctl reload</code>、送 SIGHUP）重讀的是<strong>設定檔</strong>——能換到 daemon 啟動時已可見的字型（例如從 A 字族改成 B 字族），但看不到啟動後才新裝的字型檔。根源是 reload 不重建記憶體裡的字型清單，只有重啟 process 才會從系統快取重新載入。</p>
<p><strong>重啟的範圍</strong>取決於受影響的程式數量。單一 daemon（通知、狀態列）重啟那一個即可；由 compositor <code>exec-once</code> 拉起的一批元件要同時吃到新字型，最乾淨的做法是重新登入，讓它們全部重新啟動。</p>
<p><strong>正常開機不會踩到這個坑</strong>——字型在開機早期就裝好，<code>exec-once</code> 啟動的元件從一開始就看得到完整字型集合。這個時序問題集中在「系統已經在跑、中途才補裝字型」的除錯情境。</p>
<p><strong>延伸閱讀</strong>：Nerd Font 不含 CJK、需另裝 fallback 字型的具體案例見<a href="/blog/linux/dotfile/06-rice-design/desktop-shell-components/" data-link-title="桌面 Shell 元件：狀態列、啟動器與通知" data-link-desc="Hyprland 桌面要拼哪些元件、各元件的配置檔怎麼寫時回來讀">桌面 Shell 元件：狀態列、啟動器與通知</a>；字型安裝方式見<a href="/blog/linux/dotfile/03-terminal-ecosystem/terminal-emulator-config/" data-link-title="Terminal Emulator 配置" data-link-desc="選 terminal emulator 時需要比對配置格式和跨平台能力、或想把配色和字型統一管理時回來讀">終端機與編輯器配置</a>的字型管理段。</p>
<h2 id="邊界與例外">邊界與例外</h2>
<p><strong>fc-match 也查不到</strong>：連新 process 都找不到剛裝的字型，問題在系統快取層（fontconfig 索引未更新），跑 <code>fc-cache -fv</code> 解決。兩層的修法不同，<code>fc-match</code> 是分辨在哪一層的第一步。</p>
<p><strong>部分應用程式支援熱載入</strong>：瀏覽器等有獨立字型服務的程式可能在開新分頁時重新掃描字型，不需要重啟整個 process。長駐 daemon（mako、waybar）與狀態列預設是啟動時載入一次。</p>
<p><strong>Flatpak / Snap 的字型隔離是不同問題</strong>：沙箱化應用程式看不到 host 的字型目錄，重啟 process 也無法解決——原因不是時序，而是沙箱的檔案系統隔離。需要透過 Flatpak 的 filesystem override 或把字型放進沙箱可存取的路徑。</p>
]]></content:encoded></item><item><title>IAM（Identity and Access Management）</title><link>https://tarrragon.github.io/blog/infra/knowledge-cards/iam/</link><pubDate>Fri, 26 Jun 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/infra/knowledge-cards/iam/</guid><description>&lt;p>IAM（Identity and Access Management）是雲端平台用來回答「某個身分能不能對某個資源做某件事」的授權系統。它把授權拆成三個獨立的元件：identity（身分，發起動作的主體）、policy（政策，描述「允許或拒絕對哪些資源做哪些動作」的規則）、role（角色，一組可以被臨時取得的權限集合）。這三者的分工是後面所有憑證決策的前提。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>IAM 是&lt;a href="https://tarrragon.github.io/blog/infra/02-identity-credentials/iam-oidc-privilege-boundary/" data-link-title="身分與憑證地基 — IAM 模型、OIDC 短期憑證與權限邊界設計" data-link-desc="IAM 的 identity / policy / role 三元件、最小權限的持續收斂、用 OIDC 取代長期 access key，以及 SCP 與 Permissions Boundary 的環境隔離">模組二：身分與憑證地基&lt;/a>的核心機制。它決定了誰能動什麼——人、服務、CI pipeline 各拿剛好夠用的權限（最小權限），憑證有明確的生命週期。身分層失守的代價在五個 infra 責任面向中最高，因為它是其他所有資源的閘門。&lt;/p>
&lt;p>在 infra 系列中，IAM 的設計從三個維度展開：最小權限的持續收斂（不是一次設定就結束）、用 &lt;a href="https://tarrragon.github.io/blog/infra/knowledge-cards/oidc/" data-link-title="OIDC 聯合" data-link-desc="讓 CI/CD 平台用短期 token 取代長期 access key 存取雲端資源的身分聯合機制">OIDC&lt;/a> 短期憑證取代長期 access key、以及跨帳號的權限邊界（SCP + Permissions Boundary）。&lt;/p>
&lt;h2 id="可觀察訊號">可觀察訊號&lt;/h2>
&lt;p>IAM 需要關注的訊號：某個 role 的 policy 有 &lt;code>*:*&lt;/code> 或 &lt;code>AdministratorAccess&lt;/code>（權限過大）；credential report 顯示有長期 access key 超過 90 天未輪替（憑證散落風險）；Access Analyzer 顯示某個 role 的實際使用 action 遠少於授予的 action（權限擴散）；dev 環境的 CI role 能列出 production 的資源（環境隔離失效）。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>IAM 設計時要決定：&lt;/p>
&lt;ul>
&lt;li>身分類型區分：人用 SSO 登入（強制 MFA）、雲上服務用 instance profile / task role、雲外 CI 用 OIDC 聯合&lt;/li>
&lt;li>權限分級：admin / operator / viewer 三級，見&lt;a href="https://tarrragon.github.io/blog/infra/02-identity-credentials/team-access-management/" data-link-title="團隊權限分級與存取管理" data-link-desc="用 admin / operator / viewer 三級劃分團隊成員的雲端操作權限，設計臨時提權流程、定期 access review 節奏，以及 contractor 與外部 vendor 的存取邊界">團隊權限分級&lt;/a>&lt;/li>
&lt;li>環境隔離：每個環境的 role 不能存取其他環境的資源&lt;/li>
&lt;li>收斂節奏：定期用 Access Analyzer 觀察實際使用的 action，收掉沒用到的權限&lt;/li>
&lt;/ul>
&lt;h2 id="鄰卡">鄰卡&lt;/h2>
&lt;ul>
&lt;li>&lt;a href="https://tarrragon.github.io/blog/infra/knowledge-cards/oidc/" data-link-title="OIDC 聯合" data-link-desc="讓 CI/CD 平台用短期 token 取代長期 access key 存取雲端資源的身分聯合機制">OIDC&lt;/a> — 用短期 token 取代長期 access key 的聯合機制&lt;/li>
&lt;li>&lt;a href="https://tarrragon.github.io/blog/infra/knowledge-cards/security-group/" data-link-title="Security Group" data-link-desc="掛在資源網卡層級的有狀態防火牆，逐埠決定哪些來源能連進這個資源">Security Group&lt;/a> — 網路層的存取控制（IAM 是 API 層的存取控制）&lt;/li>
&lt;li>&lt;a href="https://tarrragon.github.io/blog/infra/knowledge-cards/cloudtrail/" data-link-title="CloudTrail" data-link-desc="AWS 的 API 層稽核日誌服務，記錄誰在什麼時候對什麼資源做了什麼操作">CloudTrail&lt;/a> — 記錄 IAM 身分的 API 呼叫歷史&lt;/li>
&lt;/ul></description><content:encoded><![CDATA[<p>IAM（Identity and Access Management）是雲端平台用來回答「某個身分能不能對某個資源做某件事」的授權系統。它把授權拆成三個獨立的元件：identity（身分，發起動作的主體）、policy（政策，描述「允許或拒絕對哪些資源做哪些動作」的規則）、role（角色，一組可以被臨時取得的權限集合）。這三者的分工是後面所有憑證決策的前提。</p>
<h2 id="概念位置">概念位置</h2>
<p>IAM 是<a href="/blog/infra/02-identity-credentials/iam-oidc-privilege-boundary/" data-link-title="身分與憑證地基 — IAM 模型、OIDC 短期憑證與權限邊界設計" data-link-desc="IAM 的 identity / policy / role 三元件、最小權限的持續收斂、用 OIDC 取代長期 access key，以及 SCP 與 Permissions Boundary 的環境隔離">模組二：身分與憑證地基</a>的核心機制。它決定了誰能動什麼——人、服務、CI pipeline 各拿剛好夠用的權限（最小權限），憑證有明確的生命週期。身分層失守的代價在五個 infra 責任面向中最高，因為它是其他所有資源的閘門。</p>
<p>在 infra 系列中，IAM 的設計從三個維度展開：最小權限的持續收斂（不是一次設定就結束）、用 <a href="/blog/infra/knowledge-cards/oidc/" data-link-title="OIDC 聯合" data-link-desc="讓 CI/CD 平台用短期 token 取代長期 access key 存取雲端資源的身分聯合機制">OIDC</a> 短期憑證取代長期 access key、以及跨帳號的權限邊界（SCP + Permissions Boundary）。</p>
<h2 id="可觀察訊號">可觀察訊號</h2>
<p>IAM 需要關注的訊號：某個 role 的 policy 有 <code>*:*</code> 或 <code>AdministratorAccess</code>（權限過大）；credential report 顯示有長期 access key 超過 90 天未輪替（憑證散落風險）；Access Analyzer 顯示某個 role 的實際使用 action 遠少於授予的 action（權限擴散）；dev 環境的 CI role 能列出 production 的資源（環境隔離失效）。</p>
<h2 id="設計責任">設計責任</h2>
<p>IAM 設計時要決定：</p>
<ul>
<li>身分類型區分：人用 SSO 登入（強制 MFA）、雲上服務用 instance profile / task role、雲外 CI 用 OIDC 聯合</li>
<li>權限分級：admin / operator / viewer 三級，見<a href="/blog/infra/02-identity-credentials/team-access-management/" data-link-title="團隊權限分級與存取管理" data-link-desc="用 admin / operator / viewer 三級劃分團隊成員的雲端操作權限，設計臨時提權流程、定期 access review 節奏，以及 contractor 與外部 vendor 的存取邊界">團隊權限分級</a></li>
<li>環境隔離：每個環境的 role 不能存取其他環境的資源</li>
<li>收斂節奏：定期用 Access Analyzer 觀察實際使用的 action，收掉沒用到的權限</li>
</ul>
<h2 id="鄰卡">鄰卡</h2>
<ul>
<li><a href="/blog/infra/knowledge-cards/oidc/" data-link-title="OIDC 聯合" data-link-desc="讓 CI/CD 平台用短期 token 取代長期 access key 存取雲端資源的身分聯合機制">OIDC</a> — 用短期 token 取代長期 access key 的聯合機制</li>
<li><a href="/blog/infra/knowledge-cards/security-group/" data-link-title="Security Group" data-link-desc="掛在資源網卡層級的有狀態防火牆，逐埠決定哪些來源能連進這個資源">Security Group</a> — 網路層的存取控制（IAM 是 API 層的存取控制）</li>
<li><a href="/blog/infra/knowledge-cards/cloudtrail/" data-link-title="CloudTrail" data-link-desc="AWS 的 API 層稽核日誌服務，記錄誰在什麼時候對什麼資源做了什麼操作">CloudTrail</a> — 記錄 IAM 身分的 API 呼叫歷史</li>
</ul>
]]></content:encoded></item><item><title>Burn Rate</title><link>https://tarrragon.github.io/blog/business/knowledge-cards/burn-rate/</link><pubDate>Tue, 19 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/business/knowledge-cards/burn-rate/</guid><description>&lt;p>Burn Rate 的核心概念是「燒錢速度」—公司每月淨支出（支出減收入）。新創靠融資活著，融到的錢除以 burn rate 等於 &lt;a href="https://tarrragon.github.io/blog/business/knowledge-cards/runway/" data-link-title="Runway" data-link-desc="說明新創的現金跑道與融資時點">runway&lt;/a>（還能撐多久）。月燒 100 萬、帳上 1200 萬，runway 是 12 個月。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>Burn Rate 是新創生存判斷的核心數字。它決定何時要再融資、能不能挺過下一輪、有沒有空間做長線投資。連 burn rate 都壓不住的新創，做技術領先也沒意義—錢燒完就死。判讀時要跟 &lt;a href="https://tarrragon.github.io/blog/business/knowledge-cards/gross-margin/" data-link-title="Gross Margin" data-link-desc="說明毛利率與其對商業模式可行性的決定作用">毛利&lt;/a> 與營收成長率一起看。&lt;/p>
&lt;h2 id="可觀察訊號與例子">可觀察訊號與例子&lt;/h2>
&lt;p>判讀 burn rate 的健康度：要看跟「收入成長率」「毛利」搭配。月燒 100 萬但月營收成長 30%，是正向訊號；月燒 100 萬但營收不動，是危險訊號。早期新創燒錢搶市佔合理；C 輪後還在重燒就要懷疑商業模式。&lt;/p>
&lt;h2 id="判讀方式">判讀方式&lt;/h2>
&lt;p>分析師說「burn rate 撐不住」時，通常指該公司的 &lt;a href="https://tarrragon.github.io/blog/business/knowledge-cards/unit-economics/" data-link-title="Unit Economics" data-link-desc="說明單位經濟模型與其判斷一家公司是否賺錢的責任">單位經濟&lt;/a> 算不過來，融資環境也轉冷。AI 新創面對的是「&lt;a href="https://tarrragon.github.io/blog/business/knowledge-cards/gross-margin/" data-link-title="Gross Margin" data-link-desc="說明毛利率與其對商業模式可行性的決定作用">毛利&lt;/a> 被壓縮 + &lt;a href="https://tarrragon.github.io/blog/business/knowledge-cards/valuation-compression/" data-link-title="Valuation Compression" data-link-desc="說明估值壓縮如何影響新創生存">估值&lt;/a> 被壓縮 + 融資變難」三重夾擊，burn rate 就算不變，&lt;a href="https://tarrragon.github.io/blog/business/knowledge-cards/runway/" data-link-title="Runway" data-link-desc="說明新創的現金跑道與融資時點">runway&lt;/a> 也會縮短—因為下輪融資金額會比預期低。&lt;/p></description><content:encoded><![CDATA[<p>Burn Rate 的核心概念是「燒錢速度」—公司每月淨支出（支出減收入）。新創靠融資活著，融到的錢除以 burn rate 等於 <a href="/blog/business/knowledge-cards/runway/" data-link-title="Runway" data-link-desc="說明新創的現金跑道與融資時點">runway</a>（還能撐多久）。月燒 100 萬、帳上 1200 萬，runway 是 12 個月。</p>
<h2 id="概念位置">概念位置</h2>
<p>Burn Rate 是新創生存判斷的核心數字。它決定何時要再融資、能不能挺過下一輪、有沒有空間做長線投資。連 burn rate 都壓不住的新創，做技術領先也沒意義—錢燒完就死。判讀時要跟 <a href="/blog/business/knowledge-cards/gross-margin/" data-link-title="Gross Margin" data-link-desc="說明毛利率與其對商業模式可行性的決定作用">毛利</a> 與營收成長率一起看。</p>
<h2 id="可觀察訊號與例子">可觀察訊號與例子</h2>
<p>判讀 burn rate 的健康度：要看跟「收入成長率」「毛利」搭配。月燒 100 萬但月營收成長 30%，是正向訊號；月燒 100 萬但營收不動，是危險訊號。早期新創燒錢搶市佔合理；C 輪後還在重燒就要懷疑商業模式。</p>
<h2 id="判讀方式">判讀方式</h2>
<p>分析師說「burn rate 撐不住」時，通常指該公司的 <a href="/blog/business/knowledge-cards/unit-economics/" data-link-title="Unit Economics" data-link-desc="說明單位經濟模型與其判斷一家公司是否賺錢的責任">單位經濟</a> 算不過來，融資環境也轉冷。AI 新創面對的是「<a href="/blog/business/knowledge-cards/gross-margin/" data-link-title="Gross Margin" data-link-desc="說明毛利率與其對商業模式可行性的決定作用">毛利</a> 被壓縮 + <a href="/blog/business/knowledge-cards/valuation-compression/" data-link-title="Valuation Compression" data-link-desc="說明估值壓縮如何影響新創生存">估值</a> 被壓縮 + 融資變難」三重夾擊，burn rate 就算不變，<a href="/blog/business/knowledge-cards/runway/" data-link-title="Runway" data-link-desc="說明新創的現金跑道與融資時點">runway</a> 也會縮短—因為下輪融資金額會比預期低。</p>
]]></content:encoded></item><item><title>Wayland Session Lock（鎖屏安全狀態）</title><link>https://tarrragon.github.io/blog/linux/dotfile/knowledge-cards/session-lock/</link><pubDate>Wed, 01 Jul 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/linux/dotfile/knowledge-cards/session-lock/</guid><description>&lt;h2 id="鎖屏是-compositor-持有的安全狀態">鎖屏是 compositor 持有的安全狀態&lt;/h2>
&lt;p>Wayland 下的 compositor（如 Hyprland、Sway）同時管理視窗排列與畫面輸出。鎖屏工具（Hyprlock、Swaylock）一旦啟動，桌面的「鎖定」狀態就由 compositor 透過 ext-session-lock-v1（Wayland 生態系的跨 compositor 鎖屏協議）持有。解鎖的正常動作是鎖屏 client 通過認證後呼叫 &lt;code>unlock_and_destroy&lt;/code>（協議定義的 request），compositor 收到這個信號才釋放鎖定。&lt;/p>
&lt;p>這個責任邊界在自動化測試、VM 演練、遠端操作時最容易出事，因為這些情境常用「殺 process」當「關掉一個東西」的通用手段。殺掉鎖屏 client 跳過了認證，compositor 不會釋放鎖——畫面會卡在失效保護狀態而非回到桌面。&lt;/p>
&lt;h2 id="logind-提示與-compositor-鎖的值可以不一致">logind 提示與 compositor 鎖的值可以不一致&lt;/h2>
&lt;p>鎖屏狀態牽涉兩個獨立的層，觸發方向和持有者不同：&lt;/p>
&lt;table>
 &lt;thead>
 &lt;tr>
 &lt;th>層&lt;/th>
 &lt;th>持有者&lt;/th>
 &lt;th>查看方式&lt;/th>
 &lt;th>語意&lt;/th>
 &lt;/tr>
 &lt;/thead>
 &lt;tbody>
 &lt;tr>
 &lt;td>logind 會話鎖&lt;/td>
 &lt;td>systemd-logind&lt;/td>
 &lt;td>&lt;code>loginctl show-session &amp;lt;id&amp;gt; -p LockedHint&lt;/code>&lt;/td>
 &lt;td>會話的鎖定提示，給登入管理器 / 螢幕保護程式&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>compositor 鎖&lt;/td>
 &lt;td>Wayland compositor&lt;/td>
 &lt;td>畫面是否進得去、鎖屏 surface 是否在最上層&lt;/td>
 &lt;td>實際擋住畫面的那層&lt;/td>
 &lt;/tr>
 &lt;/tbody>
&lt;/table>
&lt;p>&lt;code>loginctl lock-session&lt;/code> 走 logind 層觸發鎖屏，鎖屏 client 收到信號後啟動、再向 compositor 取得 session lock。觸發方向是 logind → client → compositor；持有與強制執行方向是 compositor → 畫面。兩者方向相反，正好印證兩層是獨立的。&lt;/p>
&lt;p>實測會遇到 &lt;code>LockedHint=no&lt;/code>（logind 層說沒鎖）但畫面仍進不去——因為擋住畫面的是 compositor 的 ext-session-lock，跟 logind 提示是兩回事。判斷畫面進不進得去，看 compositor 層，不看 logind 層。&lt;/p>
&lt;h2 id="鎖屏-client-非正常結束時的失效保護">鎖屏 client 非正常結束時的失效保護&lt;/h2>
&lt;p>鎖屏 client 在持有鎖的狀態下死掉（被 &lt;code>kill&lt;/code>、crash），compositor 沒有收到認證通過的信號，只能維持鎖定並顯示失效保護畫面。Hyprland 的失效保護畫面會直接給恢復指令：&lt;/p>





&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-text" data-lang="text">&lt;span class="line">&lt;span class="ln">1&lt;/span>&lt;span class="cl">hyprctl --instance 0 &amp;#39;keyword misc:allow_session_lock_restore 1&amp;#39;
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">2&lt;/span>&lt;span class="cl">hyprctl --instance 0 &amp;#39;dispatch exec hyprlock&amp;#39;&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>&lt;code>allow_session_lock_restore&lt;/code> 允許新的鎖屏 client 接管既有的鎖（否則新 client 會因「已經鎖了」被拒）。接管後是乾淨的鎖屏 prompt，用密碼正常解鎖。&lt;/p>
&lt;p>備好 restore 路徑時，殺掉無回應的鎖屏 client 是合理操作——問題不在「殺」、在「以為殺完就回桌面」。restore 的前提是有另一個可操作的 session：另一個 TTY 或 SSH 連線。ext-session-lock 的安全語意允許 compositor 攔截 VT 切換快捷鍵（&lt;code>Ctrl+Alt+Fn&lt;/code>），遇到 TTY 切不過去的情況，SSH 是替代救援通道（事先配好 SSH server，見&lt;a href="https://tarrragon.github.io/blog/linux/dotfile/07-desktop-maintenance/common-failures-recovery/" data-link-title="常見故障場景與恢復操作" data-link-desc="Hyprland 黑屏、waybar 消失、畫面凍結、記憶體爆掉或 config 寫錯導致進不了桌面時，按症狀查恢復操作">常見故障場景與恢復操作&lt;/a>的 GPU hang 段）。&lt;/p>
&lt;h2 id="判讀與操作">判讀與操作&lt;/h2>
&lt;ul>
&lt;li>&lt;strong>判讀鎖定狀態&lt;/strong>：&lt;code>loginctl show-session $(loginctl show-user $USER -p Display --value) -p LockedHint&lt;/code> 查 logind 層；compositor 層看畫面能否操作。兩層不一致時以 compositor 層為準。&lt;/li>
&lt;li>&lt;strong>正常解鎖&lt;/strong>：通過鎖屏 client 的認證（密碼 / 指紋），client 呼叫 &lt;code>unlock_and_destroy&lt;/code>，compositor 釋放鎖。&lt;/li>
&lt;li>&lt;strong>失效保護恢復&lt;/strong>：從另一個 TTY 或 SSH 執行 &lt;code>hyprctl --instance 0 'keyword misc:allow_session_lock_restore 1'&lt;/code> + &lt;code>hyprctl --instance 0 'dispatch exec hyprlock'&lt;/code>，重新拉起鎖屏 prompt 後認證解鎖。&lt;/li>
&lt;li>&lt;strong>自動化流程的代價&lt;/strong>：啟動鎖屏後，畫面會留在鎖定狀態直到有人通過認證。自動化測試若會觸發鎖屏，要把「需人工解鎖」算進代價。&lt;/li>
&lt;li>&lt;strong>診斷路由&lt;/strong>：「畫面卡住 / 螢幕鎖了沒」當成一般 Linux 狀態判讀問題（跟判程式活著、判服務歸屬同類）時，見&lt;a href="https://tarrragon.github.io/blog/linux/debug/process-service-state-diagnosis/" data-link-title="程序、服務與狀態怎麼判" data-link-desc="要判斷一個程式活著沒、某個系統服務現在由誰提供、桌面 session 有沒有被鎖、或終端機多工器的 session 還在不在時，用對的權威來源而不是靠畫面或猜的名字">程序、服務與狀態怎麼判&lt;/a>——它把「判 session 有沒有被鎖」放進「讀權威狀態、別看畫面猜」的通用診斷紀律裡。&lt;/li>
&lt;li>&lt;strong>延伸閱讀&lt;/strong>：鎖屏的視覺配置（背景、輸入框、時鐘 label）見&lt;a href="https://tarrragon.github.io/blog/linux/dotfile/06-rice-design/color-system-theming/" data-link-title="配色系統、鎖屏與 GTK 主題" data-link-desc="桌面配色散亂看起來雜、或要換主題不知道該改哪些檔案時回來讀">配色系統、鎖屏與 GTK 主題&lt;/a>的 Hyprlock 段；桌面故障恢復流程見&lt;a href="https://tarrragon.github.io/blog/linux/dotfile/07-desktop-maintenance/common-failures-recovery/" data-link-title="常見故障場景與恢復操作" data-link-desc="Hyprland 黑屏、waybar 消失、畫面凍結、記憶體爆掉或 config 寫錯導致進不了桌面時，按症狀查恢復操作">常見故障場景與恢復操作&lt;/a>。持鎖的那個 compositor 到底是什麼、還握著哪些系統狀態，見 &lt;a href="https://tarrragon.github.io/blog/linux/dotfile/knowledge-cards/compositor/" data-link-title="Compositor（合成器）" data-link-desc="教材反覆出現 compositor / 合成器、想確認它到底負責什麼、跟 window manager 和桌面環境差在哪時讀 — Wayland 下把畫面合成與視窗管理合一的核心程式">Compositor 術語卡&lt;/a>。&lt;/li>
&lt;/ul>
&lt;h2 id="邊界條件">邊界條件&lt;/h2>
&lt;p>正常認證解鎖（走 &lt;code>unlock_and_destroy&lt;/code>）後鎖屏 client 結束，compositor 已回到非鎖定狀態，不觸發失效保護。失效保護只在「持鎖中非正常結束」時出現。&lt;/p></description><content:encoded><![CDATA[<h2 id="鎖屏是-compositor-持有的安全狀態">鎖屏是 compositor 持有的安全狀態</h2>
<p>Wayland 下的 compositor（如 Hyprland、Sway）同時管理視窗排列與畫面輸出。鎖屏工具（Hyprlock、Swaylock）一旦啟動，桌面的「鎖定」狀態就由 compositor 透過 ext-session-lock-v1（Wayland 生態系的跨 compositor 鎖屏協議）持有。解鎖的正常動作是鎖屏 client 通過認證後呼叫 <code>unlock_and_destroy</code>（協議定義的 request），compositor 收到這個信號才釋放鎖定。</p>
<p>這個責任邊界在自動化測試、VM 演練、遠端操作時最容易出事，因為這些情境常用「殺 process」當「關掉一個東西」的通用手段。殺掉鎖屏 client 跳過了認證，compositor 不會釋放鎖——畫面會卡在失效保護狀態而非回到桌面。</p>
<h2 id="logind-提示與-compositor-鎖的值可以不一致">logind 提示與 compositor 鎖的值可以不一致</h2>
<p>鎖屏狀態牽涉兩個獨立的層，觸發方向和持有者不同：</p>
<table>
  <thead>
      <tr>
          <th>層</th>
          <th>持有者</th>
          <th>查看方式</th>
          <th>語意</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>logind 會話鎖</td>
          <td>systemd-logind</td>
          <td><code>loginctl show-session &lt;id&gt; -p LockedHint</code></td>
          <td>會話的鎖定提示，給登入管理器 / 螢幕保護程式</td>
      </tr>
      <tr>
          <td>compositor 鎖</td>
          <td>Wayland compositor</td>
          <td>畫面是否進得去、鎖屏 surface 是否在最上層</td>
          <td>實際擋住畫面的那層</td>
      </tr>
  </tbody>
</table>
<p><code>loginctl lock-session</code> 走 logind 層觸發鎖屏，鎖屏 client 收到信號後啟動、再向 compositor 取得 session lock。觸發方向是 logind → client → compositor；持有與強制執行方向是 compositor → 畫面。兩者方向相反，正好印證兩層是獨立的。</p>
<p>實測會遇到 <code>LockedHint=no</code>（logind 層說沒鎖）但畫面仍進不去——因為擋住畫面的是 compositor 的 ext-session-lock，跟 logind 提示是兩回事。判斷畫面進不進得去，看 compositor 層，不看 logind 層。</p>
<h2 id="鎖屏-client-非正常結束時的失效保護">鎖屏 client 非正常結束時的失效保護</h2>
<p>鎖屏 client 在持有鎖的狀態下死掉（被 <code>kill</code>、crash），compositor 沒有收到認證通過的信號，只能維持鎖定並顯示失效保護畫面。Hyprland 的失效保護畫面會直接給恢復指令：</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="ln">1</span><span class="cl">hyprctl --instance 0 &#39;keyword misc:allow_session_lock_restore 1&#39;
</span></span><span class="line"><span class="ln">2</span><span class="cl">hyprctl --instance 0 &#39;dispatch exec hyprlock&#39;</span></span></code></pre></div><p><code>allow_session_lock_restore</code> 允許新的鎖屏 client 接管既有的鎖（否則新 client 會因「已經鎖了」被拒）。接管後是乾淨的鎖屏 prompt，用密碼正常解鎖。</p>
<p>備好 restore 路徑時，殺掉無回應的鎖屏 client 是合理操作——問題不在「殺」、在「以為殺完就回桌面」。restore 的前提是有另一個可操作的 session：另一個 TTY 或 SSH 連線。ext-session-lock 的安全語意允許 compositor 攔截 VT 切換快捷鍵（<code>Ctrl+Alt+Fn</code>），遇到 TTY 切不過去的情況，SSH 是替代救援通道（事先配好 SSH server，見<a href="/blog/linux/dotfile/07-desktop-maintenance/common-failures-recovery/" data-link-title="常見故障場景與恢復操作" data-link-desc="Hyprland 黑屏、waybar 消失、畫面凍結、記憶體爆掉或 config 寫錯導致進不了桌面時，按症狀查恢復操作">常見故障場景與恢復操作</a>的 GPU hang 段）。</p>
<h2 id="判讀與操作">判讀與操作</h2>
<ul>
<li><strong>判讀鎖定狀態</strong>：<code>loginctl show-session $(loginctl show-user $USER -p Display --value) -p LockedHint</code> 查 logind 層；compositor 層看畫面能否操作。兩層不一致時以 compositor 層為準。</li>
<li><strong>正常解鎖</strong>：通過鎖屏 client 的認證（密碼 / 指紋），client 呼叫 <code>unlock_and_destroy</code>，compositor 釋放鎖。</li>
<li><strong>失效保護恢復</strong>：從另一個 TTY 或 SSH 執行 <code>hyprctl --instance 0 'keyword misc:allow_session_lock_restore 1'</code> + <code>hyprctl --instance 0 'dispatch exec hyprlock'</code>，重新拉起鎖屏 prompt 後認證解鎖。</li>
<li><strong>自動化流程的代價</strong>：啟動鎖屏後，畫面會留在鎖定狀態直到有人通過認證。自動化測試若會觸發鎖屏，要把「需人工解鎖」算進代價。</li>
<li><strong>診斷路由</strong>：「畫面卡住 / 螢幕鎖了沒」當成一般 Linux 狀態判讀問題（跟判程式活著、判服務歸屬同類）時，見<a href="/blog/linux/debug/process-service-state-diagnosis/" data-link-title="程序、服務與狀態怎麼判" data-link-desc="要判斷一個程式活著沒、某個系統服務現在由誰提供、桌面 session 有沒有被鎖、或終端機多工器的 session 還在不在時，用對的權威來源而不是靠畫面或猜的名字">程序、服務與狀態怎麼判</a>——它把「判 session 有沒有被鎖」放進「讀權威狀態、別看畫面猜」的通用診斷紀律裡。</li>
<li><strong>延伸閱讀</strong>：鎖屏的視覺配置（背景、輸入框、時鐘 label）見<a href="/blog/linux/dotfile/06-rice-design/color-system-theming/" data-link-title="配色系統、鎖屏與 GTK 主題" data-link-desc="桌面配色散亂看起來雜、或要換主題不知道該改哪些檔案時回來讀">配色系統、鎖屏與 GTK 主題</a>的 Hyprlock 段；桌面故障恢復流程見<a href="/blog/linux/dotfile/07-desktop-maintenance/common-failures-recovery/" data-link-title="常見故障場景與恢復操作" data-link-desc="Hyprland 黑屏、waybar 消失、畫面凍結、記憶體爆掉或 config 寫錯導致進不了桌面時，按症狀查恢復操作">常見故障場景與恢復操作</a>。持鎖的那個 compositor 到底是什麼、還握著哪些系統狀態，見 <a href="/blog/linux/dotfile/knowledge-cards/compositor/" data-link-title="Compositor（合成器）" data-link-desc="教材反覆出現 compositor / 合成器、想確認它到底負責什麼、跟 window manager 和桌面環境差在哪時讀 — Wayland 下把畫面合成與視窗管理合一的核心程式">Compositor 術語卡</a>。</li>
</ul>
<h2 id="邊界條件">邊界條件</h2>
<p>正常認證解鎖（走 <code>unlock_and_destroy</code>）後鎖屏 client 結束，compositor 已回到非鎖定狀態，不觸發失效保護。失效保護只在「持鎖中非正常結束」時出現。</p>
<p>Sway/swaylock 在 client 死掉時沒有畫面上的恢復提示（不像 Hyprland 會印指令），得預先知道走 TTY 或 SSH 執行 restore。「鎖是 compositor 持有、解鎖要認證」是 ext-session-lock 協議層的共通約束；失效保護的具體呈現方式因 compositor 而異。</p>
]]></content:encoded></item><item><title>Route Table</title><link>https://tarrragon.github.io/blog/infra/knowledge-cards/route-table/</link><pubDate>Fri, 26 Jun 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/infra/knowledge-cards/route-table/</guid><description>&lt;p>Route table 是一組轉送規則，掛在 subnet 上，定義「目的地是某個網段的封包該往哪送」。每個 subnet 關聯一張 route table，封包離開 subnet 時逐條比對規則、走最長前綴匹配的那一條。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>Route table 決定了一個 subnet 是 public 還是 private。技術上的差別只有一行：route table 裡有沒有一條 &lt;code>0.0.0.0/0 → Internet Gateway&lt;/code> 的預設路由。有這條路由的 subnet 是 public（封包可以直接出網、外部也可以連入）；把預設路由指向 &lt;a href="https://tarrragon.github.io/blog/infra/knowledge-cards/nat/" data-link-title="NAT Gateway" data-link-desc="讓 private subnet 的資源主動對外連線、同時不被外部入站觸及的網路地址轉換服務">NAT Gateway&lt;/a> 的 subnet 是 private（只能主動出站、外部無法入站）。subnet 本身的屬性不含 public/private 標記，性質完全由關聯的 route table 賦予。&lt;/p>
&lt;h2 id="可觀察訊號">可觀察訊號&lt;/h2>
&lt;p>private subnet 的服務突然拉不到外部套件或第三方 API 全部逾時時，排查路徑的第一步是檢查該 subnet 關聯的 route table：預設路由是否指向健康的 NAT Gateway。如果只有某一個可用區的節點受影響，通常是那一區的 NAT Gateway 或其所在 subnet 出狀況。&lt;/p>
&lt;p>另一個常見訊號是新建的 subnet 沒有手動關聯 route table，被 VPC 的 main route table 自動關聯——main route table 的預設設定可能跟預期不符。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>使用 route table 時要決定：每個 subnet 的預設路由指向什麼（Internet Gateway / NAT Gateway / Transit Gateway / 無）、VPC 內部流量是否需要自訂路由（peering、endpoint）、以及 main route table 是否該保持空白以避免新 subnet 意外取得對外路由。每一條路由的目的地網段和目標要在 IaC 裡明確描述，讓 route table 的語意可被 review。&lt;/p>
&lt;h2 id="鄰卡">鄰卡&lt;/h2>
&lt;ul>
&lt;li>&lt;a href="https://tarrragon.github.io/blog/infra/knowledge-cards/subnet/" data-link-title="Subnet（子網路）" data-link-desc="VPC 內按可用區與暴露程度切出的子網段，決定資源有沒有一條通往網際網路的路徑">Subnet&lt;/a> — route table 掛在 subnet 上&lt;/li>
&lt;li>&lt;a href="https://tarrragon.github.io/blog/infra/knowledge-cards/nat/" data-link-title="NAT Gateway" data-link-desc="讓 private subnet 的資源主動對外連線、同時不被外部入站觸及的網路地址轉換服務">NAT&lt;/a> — private subnet 的預設路由目標&lt;/li>
&lt;li>&lt;a href="https://tarrragon.github.io/blog/infra/knowledge-cards/vpc/" data-link-title="VPC（Virtual Private Cloud）" data-link-desc="雲端帳號內的一塊邏輯隔離私有網段，是所有網路切分的起點與容器">VPC&lt;/a> — route table 存在於 VPC 內&lt;/li>
&lt;/ul></description><content:encoded><![CDATA[<p>Route table 是一組轉送規則，掛在 subnet 上，定義「目的地是某個網段的封包該往哪送」。每個 subnet 關聯一張 route table，封包離開 subnet 時逐條比對規則、走最長前綴匹配的那一條。</p>
<h2 id="概念位置">概念位置</h2>
<p>Route table 決定了一個 subnet 是 public 還是 private。技術上的差別只有一行：route table 裡有沒有一條 <code>0.0.0.0/0 → Internet Gateway</code> 的預設路由。有這條路由的 subnet 是 public（封包可以直接出網、外部也可以連入）；把預設路由指向 <a href="/blog/infra/knowledge-cards/nat/" data-link-title="NAT Gateway" data-link-desc="讓 private subnet 的資源主動對外連線、同時不被外部入站觸及的網路地址轉換服務">NAT Gateway</a> 的 subnet 是 private（只能主動出站、外部無法入站）。subnet 本身的屬性不含 public/private 標記，性質完全由關聯的 route table 賦予。</p>
<h2 id="可觀察訊號">可觀察訊號</h2>
<p>private subnet 的服務突然拉不到外部套件或第三方 API 全部逾時時，排查路徑的第一步是檢查該 subnet 關聯的 route table：預設路由是否指向健康的 NAT Gateway。如果只有某一個可用區的節點受影響，通常是那一區的 NAT Gateway 或其所在 subnet 出狀況。</p>
<p>另一個常見訊號是新建的 subnet 沒有手動關聯 route table，被 VPC 的 main route table 自動關聯——main route table 的預設設定可能跟預期不符。</p>
<h2 id="設計責任">設計責任</h2>
<p>使用 route table 時要決定：每個 subnet 的預設路由指向什麼（Internet Gateway / NAT Gateway / Transit Gateway / 無）、VPC 內部流量是否需要自訂路由（peering、endpoint）、以及 main route table 是否該保持空白以避免新 subnet 意外取得對外路由。每一條路由的目的地網段和目標要在 IaC 裡明確描述，讓 route table 的語意可被 review。</p>
<h2 id="鄰卡">鄰卡</h2>
<ul>
<li><a href="/blog/infra/knowledge-cards/subnet/" data-link-title="Subnet（子網路）" data-link-desc="VPC 內按可用區與暴露程度切出的子網段，決定資源有沒有一條通往網際網路的路徑">Subnet</a> — route table 掛在 subnet 上</li>
<li><a href="/blog/infra/knowledge-cards/nat/" data-link-title="NAT Gateway" data-link-desc="讓 private subnet 的資源主動對外連線、同時不被外部入站觸及的網路地址轉換服務">NAT</a> — private subnet 的預設路由目標</li>
<li><a href="/blog/infra/knowledge-cards/vpc/" data-link-title="VPC（Virtual Private Cloud）" data-link-desc="雲端帳號內的一塊邏輯隔離私有網段，是所有網路切分的起點與容器">VPC</a> — route table 存在於 VPC 內</li>
</ul>
]]></content:encoded></item><item><title>Runway</title><link>https://tarrragon.github.io/blog/business/knowledge-cards/runway/</link><pubDate>Tue, 19 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/business/knowledge-cards/runway/</guid><description>&lt;p>Runway 的核心概念是「現金能撐多久」—公司現有現金除以 &lt;a href="https://tarrragon.github.io/blog/business/knowledge-cards/burn-rate/" data-link-title="Burn Rate" data-link-desc="說明燒錢速度及其對新創存活的決定作用">每月燒錢速度&lt;/a>，得到剩餘月數。Runway 6 個月代表半年內必須融資或開始賺錢，不然倒閉。Runway 是新創融資節奏的計時器。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>Runway 是新創生存的時間軸。多數新創會在 runway 還剩 9-12 個月時開始準備下輪融資—因為融資本身要 3-6 個月，留 &lt;a href="https://tarrragon.github.io/blog/business/knowledge-cards/judgment-stake/" data-link-title="Judgment Stake" data-link-desc="說明判斷的賭注被 AI 放大的結構">安全邊際&lt;/a> 避免燒到斷糧。Runway 跟 &lt;a href="https://tarrragon.github.io/blog/business/knowledge-cards/burn-rate/" data-link-title="Burn Rate" data-link-desc="說明燒錢速度及其對新創存活的決定作用">burn rate&lt;/a> 是一體兩面，控制其中一個就控制另一個。&lt;/p>
&lt;h2 id="可觀察訊號與例子">可觀察訊號與例子&lt;/h2>
&lt;p>判讀 runway：12 個月以上是健康，6-12 個月是要開始準備融資，6 個月以下進入緊張期—投資人聞到味道會壓估值。創辦人說「我們有 24 個月 runway」通常是想展示「不急著融資、不會被壓估值」，是談判姿態。&lt;/p>
&lt;h2 id="判讀方式">判讀方式&lt;/h2>
&lt;p>讀到「runway 縮短」「runway 燒完」這類描述時，往往隱含商業環境惡化或公司本身的 &lt;a href="https://tarrragon.github.io/blog/business/knowledge-cards/unit-economics/" data-link-title="Unit Economics" data-link-desc="說明單位經濟模型與其判斷一家公司是否賺錢的責任">單位經濟&lt;/a> 出問題。AI 新創面臨 &lt;a href="https://tarrragon.github.io/blog/business/knowledge-cards/valuation-compression/" data-link-title="Valuation Compression" data-link-desc="說明估值壓縮如何影響新創生存">估值壓縮&lt;/a> 時，runway 會雙重壓縮—現金照樣燒，但下輪融資金額變少。創辦人此時的選擇是提早融資、裁員壓 burn rate、或快速找買家。&lt;/p></description><content:encoded><![CDATA[<p>Runway 的核心概念是「現金能撐多久」—公司現有現金除以 <a href="/blog/business/knowledge-cards/burn-rate/" data-link-title="Burn Rate" data-link-desc="說明燒錢速度及其對新創存活的決定作用">每月燒錢速度</a>，得到剩餘月數。Runway 6 個月代表半年內必須融資或開始賺錢，不然倒閉。Runway 是新創融資節奏的計時器。</p>
<h2 id="概念位置">概念位置</h2>
<p>Runway 是新創生存的時間軸。多數新創會在 runway 還剩 9-12 個月時開始準備下輪融資—因為融資本身要 3-6 個月，留 <a href="/blog/business/knowledge-cards/judgment-stake/" data-link-title="Judgment Stake" data-link-desc="說明判斷的賭注被 AI 放大的結構">安全邊際</a> 避免燒到斷糧。Runway 跟 <a href="/blog/business/knowledge-cards/burn-rate/" data-link-title="Burn Rate" data-link-desc="說明燒錢速度及其對新創存活的決定作用">burn rate</a> 是一體兩面，控制其中一個就控制另一個。</p>
<h2 id="可觀察訊號與例子">可觀察訊號與例子</h2>
<p>判讀 runway：12 個月以上是健康，6-12 個月是要開始準備融資，6 個月以下進入緊張期—投資人聞到味道會壓估值。創辦人說「我們有 24 個月 runway」通常是想展示「不急著融資、不會被壓估值」，是談判姿態。</p>
<h2 id="判讀方式">判讀方式</h2>
<p>讀到「runway 縮短」「runway 燒完」這類描述時，往往隱含商業環境惡化或公司本身的 <a href="/blog/business/knowledge-cards/unit-economics/" data-link-title="Unit Economics" data-link-desc="說明單位經濟模型與其判斷一家公司是否賺錢的責任">單位經濟</a> 出問題。AI 新創面臨 <a href="/blog/business/knowledge-cards/valuation-compression/" data-link-title="Valuation Compression" data-link-desc="說明估值壓縮如何影響新創生存">估值壓縮</a> 時，runway 會雙重壓縮—現金照樣燒，但下輪融資金額變少。創辦人此時的選擇是提早融資、裁員壓 burn rate、或快速找買家。</p>
]]></content:encoded></item><item><title>fontconfig — 字型搜尋、匹配與 fallback 服務</title><link>https://tarrragon.github.io/blog/linux/dotfile/knowledge-cards/fontconfig/</link><pubDate>Wed, 01 Jul 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/linux/dotfile/knowledge-cards/fontconfig/</guid><description>&lt;p>fontconfig 是 Linux 上統一管理字型搜尋、匹配與 fallback 的底層服務。應用程式透過 fontconfig 的 API 查詢可用字型，而非自行掃描字型目錄——無論是終端機、狀態列、通知 daemon 還是瀏覽器，底層都走同一套查詢介面。&lt;/p>
&lt;h2 id="fc--工具分工">fc-* 工具分工&lt;/h2>
&lt;p>fontconfig 附帶一組命令列工具，各自負責一件事：&lt;/p>
&lt;table>
 &lt;thead>
 &lt;tr>
 &lt;th>工具&lt;/th>
 &lt;th>用途&lt;/th>
 &lt;th>常用情境&lt;/th>
 &lt;/tr>
 &lt;/thead>
 &lt;tbody>
 &lt;tr>
 &lt;td>&lt;code>fc-list&lt;/code>&lt;/td>
 &lt;td>列出系統已知的所有字型（字族名、檔案路徑）&lt;/td>
 &lt;td>確認某支字型有沒有裝、查實際字族名&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;code>fc-match&lt;/code>&lt;/td>
 &lt;td>查詢指定條件的最佳匹配結果&lt;/td>
 &lt;td>確認 config 裡寫的字族名會匹配到哪支字&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;code>fc-cache&lt;/code>&lt;/td>
 &lt;td>重建 fontconfig 的系統快取&lt;/td>
 &lt;td>手動放字型檔後更新快取（套件安裝通常自動跑）&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;code>fc-pattern&lt;/code>&lt;/td>
 &lt;td>印出字型的完整屬性（除錯用）&lt;/td>
 &lt;td>查字型支援的語言、字重、字形變體&lt;/td>
 &lt;/tr>
 &lt;/tbody>
&lt;/table>
&lt;p>&lt;code>fc-list&lt;/code> 和 &lt;code>fc-match&lt;/code> 每次執行都是新 process，讀到的是當下最新的系統快取。這跟已啟動的長駐程式不同——長駐程式的字型清單是啟動時的快照，詳見 &lt;a href="https://tarrragon.github.io/blog/linux/dotfile/knowledge-cards/font-availability-at-startup/" data-link-title="字型的可用集合在 process 啟動時決定" data-link-desc="裝了字型但應用程式 / 狀態列 / 通知還是看不到、還是豆腐時回來讀">font-availability-at-startup&lt;/a>。&lt;/p>





&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-bash" data-lang="bash">&lt;span class="line">&lt;span class="ln">1&lt;/span>&lt;span class="cl">fc-list &lt;span class="p">|&lt;/span> grep -i meslo
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">2&lt;/span>&lt;span class="cl">&lt;span class="c1"># 確認 MesloLGS Nerd Font 有沒有裝、實際字族名是什麼&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">3&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">4&lt;/span>&lt;span class="cl">fc-match &lt;span class="s2">&amp;#34;MesloLGS Nerd Font&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">5&lt;/span>&lt;span class="cl">&lt;span class="c1"># 查 config 裡寫的名字會匹配到哪支字型檔&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">6&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">7&lt;/span>&lt;span class="cl">fc-match &lt;span class="s2">&amp;#34;:lang=zh-tw&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">8&lt;/span>&lt;span class="cl">&lt;span class="c1"># 查系統有沒有可用的繁體中文字型&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h2 id="fallback-chain">Fallback chain&lt;/h2>
&lt;p>應用程式在 config 裡指定字族名（如 &lt;code>MesloLGS Nerd Font&lt;/code>），fontconfig 依以下順序處理：&lt;/p>
&lt;ol>
&lt;li>在已知字型中找&lt;strong>完全匹配&lt;/strong>的字族&lt;/li>
&lt;li>找不到就沿 fallback chain 往下找候選——fontconfig 的預設 fallback 規則定義在 &lt;code>/etc/fonts/conf.d/&lt;/code> 的 XML 設定檔中&lt;/li>
&lt;li>CJK fallback 依語言優先序決定——&lt;code>fc-match &amp;quot;:lang=zh-tw&amp;quot;&lt;/code> 回的是 fontconfig 認為最適合該語言的字型&lt;/li>
&lt;/ol>
&lt;p>Nerd Font（MesloLGS、JetBrainsMono 等）只含 Latin 字元與圖示 glyph，CJK 字元靠 fallback 到另一支字型（如 &lt;code>noto-fonts-cjk&lt;/code>）補齊。fontconfig 的 fallback 對應用程式透明——應用程式只指定主字型，缺字時 fontconfig 自動補。&lt;/p>
&lt;h2 id="系統快取">系統快取&lt;/h2>
&lt;p>fontconfig 把字型目錄的掃描結果存成快取檔，避免每次查詢都重新掃描整個檔案系統：&lt;/p>
&lt;ul>
&lt;li>系統層快取：&lt;code>/var/cache/fontconfig/&lt;/code>&lt;/li>
&lt;li>使用者層快取：&lt;code>~/.cache/fontconfig/&lt;/code>&lt;/li>
&lt;/ul>
&lt;p>套件管理器安裝字型時，post-install hook 會自動執行 &lt;code>fc-cache&lt;/code> 更新系統快取（pacman 安裝完會印 &lt;code>Updating fontconfig cache&lt;/code>）。手動把字型檔放進 &lt;code>~/.local/share/fonts/&lt;/code> 時需要自己跑 &lt;code>fc-cache&lt;/code>——不跑的話 fontconfig 看不到新字型。&lt;/p>
&lt;p>&lt;code>fc-cache -f&lt;/code> 的 &lt;code>-f&lt;/code> 是 force，忽略時間戳全部重建；不加 &lt;code>-f&lt;/code> 只更新有變動的目錄。兩者都只動系統快取層——已啟動的 process 記憶體中的字型清單不受影響，那是另一個層級的問題（見 &lt;a href="https://tarrragon.github.io/blog/linux/dotfile/knowledge-cards/font-availability-at-startup/" data-link-title="字型的可用集合在 process 啟動時決定" data-link-desc="裝了字型但應用程式 / 狀態列 / 通知還是看不到、還是豆腐時回來讀">font-availability-at-startup&lt;/a>）。&lt;/p>
&lt;h2 id="下一步路由">下一步路由&lt;/h2>
&lt;ul>
&lt;li>字型安裝方式：&lt;a href="https://tarrragon.github.io/blog/linux/dotfile/03-terminal-ecosystem/" data-link-title="模組三：終端機與編輯器" data-link-desc="終端機相關工具的配置檔散落在不同位置、不確定哪些該進 dotfile repo 時回來讀">終端機與編輯器&lt;/a>的字型管理段&lt;/li>
&lt;li>裝了字型但應用程式還是看不到：&lt;a href="https://tarrragon.github.io/blog/linux/dotfile/knowledge-cards/font-availability-at-startup/" data-link-title="字型的可用集合在 process 啟動時決定" data-link-desc="裝了字型但應用程式 / 狀態列 / 通知還是看不到、還是豆腐時回來讀">font-availability-at-startup&lt;/a>（process 啟動時快照的時序問題）&lt;/li>
&lt;/ul></description><content:encoded><![CDATA[<p>fontconfig 是 Linux 上統一管理字型搜尋、匹配與 fallback 的底層服務。應用程式透過 fontconfig 的 API 查詢可用字型，而非自行掃描字型目錄——無論是終端機、狀態列、通知 daemon 還是瀏覽器，底層都走同一套查詢介面。</p>
<h2 id="fc--工具分工">fc-* 工具分工</h2>
<p>fontconfig 附帶一組命令列工具，各自負責一件事：</p>
<table>
  <thead>
      <tr>
          <th>工具</th>
          <th>用途</th>
          <th>常用情境</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td><code>fc-list</code></td>
          <td>列出系統已知的所有字型（字族名、檔案路徑）</td>
          <td>確認某支字型有沒有裝、查實際字族名</td>
      </tr>
      <tr>
          <td><code>fc-match</code></td>
          <td>查詢指定條件的最佳匹配結果</td>
          <td>確認 config 裡寫的字族名會匹配到哪支字</td>
      </tr>
      <tr>
          <td><code>fc-cache</code></td>
          <td>重建 fontconfig 的系統快取</td>
          <td>手動放字型檔後更新快取（套件安裝通常自動跑）</td>
      </tr>
      <tr>
          <td><code>fc-pattern</code></td>
          <td>印出字型的完整屬性（除錯用）</td>
          <td>查字型支援的語言、字重、字形變體</td>
      </tr>
  </tbody>
</table>
<p><code>fc-list</code> 和 <code>fc-match</code> 每次執行都是新 process，讀到的是當下最新的系統快取。這跟已啟動的長駐程式不同——長駐程式的字型清單是啟動時的快照，詳見 <a href="/blog/linux/dotfile/knowledge-cards/font-availability-at-startup/" data-link-title="字型的可用集合在 process 啟動時決定" data-link-desc="裝了字型但應用程式 / 狀態列 / 通知還是看不到、還是豆腐時回來讀">font-availability-at-startup</a>。</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="ln">1</span><span class="cl">fc-list <span class="p">|</span> grep -i meslo
</span></span><span class="line"><span class="ln">2</span><span class="cl"><span class="c1"># 確認 MesloLGS Nerd Font 有沒有裝、實際字族名是什麼</span>
</span></span><span class="line"><span class="ln">3</span><span class="cl">
</span></span><span class="line"><span class="ln">4</span><span class="cl">fc-match <span class="s2">&#34;MesloLGS Nerd Font&#34;</span>
</span></span><span class="line"><span class="ln">5</span><span class="cl"><span class="c1"># 查 config 裡寫的名字會匹配到哪支字型檔</span>
</span></span><span class="line"><span class="ln">6</span><span class="cl">
</span></span><span class="line"><span class="ln">7</span><span class="cl">fc-match <span class="s2">&#34;:lang=zh-tw&#34;</span>
</span></span><span class="line"><span class="ln">8</span><span class="cl"><span class="c1"># 查系統有沒有可用的繁體中文字型</span></span></span></code></pre></div><h2 id="fallback-chain">Fallback chain</h2>
<p>應用程式在 config 裡指定字族名（如 <code>MesloLGS Nerd Font</code>），fontconfig 依以下順序處理：</p>
<ol>
<li>在已知字型中找<strong>完全匹配</strong>的字族</li>
<li>找不到就沿 fallback chain 往下找候選——fontconfig 的預設 fallback 規則定義在 <code>/etc/fonts/conf.d/</code> 的 XML 設定檔中</li>
<li>CJK fallback 依語言優先序決定——<code>fc-match &quot;:lang=zh-tw&quot;</code> 回的是 fontconfig 認為最適合該語言的字型</li>
</ol>
<p>Nerd Font（MesloLGS、JetBrainsMono 等）只含 Latin 字元與圖示 glyph，CJK 字元靠 fallback 到另一支字型（如 <code>noto-fonts-cjk</code>）補齊。fontconfig 的 fallback 對應用程式透明——應用程式只指定主字型，缺字時 fontconfig 自動補。</p>
<h2 id="系統快取">系統快取</h2>
<p>fontconfig 把字型目錄的掃描結果存成快取檔，避免每次查詢都重新掃描整個檔案系統：</p>
<ul>
<li>系統層快取：<code>/var/cache/fontconfig/</code></li>
<li>使用者層快取：<code>~/.cache/fontconfig/</code></li>
</ul>
<p>套件管理器安裝字型時，post-install hook 會自動執行 <code>fc-cache</code> 更新系統快取（pacman 安裝完會印 <code>Updating fontconfig cache</code>）。手動把字型檔放進 <code>~/.local/share/fonts/</code> 時需要自己跑 <code>fc-cache</code>——不跑的話 fontconfig 看不到新字型。</p>
<p><code>fc-cache -f</code> 的 <code>-f</code> 是 force，忽略時間戳全部重建；不加 <code>-f</code> 只更新有變動的目錄。兩者都只動系統快取層——已啟動的 process 記憶體中的字型清單不受影響，那是另一個層級的問題（見 <a href="/blog/linux/dotfile/knowledge-cards/font-availability-at-startup/" data-link-title="字型的可用集合在 process 啟動時決定" data-link-desc="裝了字型但應用程式 / 狀態列 / 通知還是看不到、還是豆腐時回來讀">font-availability-at-startup</a>）。</p>
<h2 id="下一步路由">下一步路由</h2>
<ul>
<li>字型安裝方式：<a href="/blog/linux/dotfile/03-terminal-ecosystem/" data-link-title="模組三：終端機與編輯器" data-link-desc="終端機相關工具的配置檔散落在不同位置、不確定哪些該進 dotfile repo 時回來讀">終端機與編輯器</a>的字型管理段</li>
<li>裝了字型但應用程式還是看不到：<a href="/blog/linux/dotfile/knowledge-cards/font-availability-at-startup/" data-link-title="字型的可用集合在 process 啟動時決定" data-link-desc="裝了字型但應用程式 / 狀態列 / 通知還是看不到、還是豆腐時回來讀">font-availability-at-startup</a>（process 啟動時快照的時序問題）</li>
</ul>
]]></content:encoded></item><item><title>SCP (Service Control Policy)</title><link>https://tarrragon.github.io/blog/infra/knowledge-cards/scp/</link><pubDate>Fri, 26 Jun 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/infra/knowledge-cards/scp/</guid><description>&lt;p>Service Control Policy（SCP）是 AWS Organizations 裡套用在 OU 或帳號上的權限上限。SCP 不授予權限——它設定一個天花板，限制該範圍內的 IAM 能做什麼。即使帳號內有 &lt;code>AdministratorAccess&lt;/code> 的 IAM role，SCP deny 的操作仍然被擋下。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>SCP 跟 &lt;a href="https://tarrragon.github.io/blog/infra/knowledge-cards/iam/" data-link-title="IAM（Identity and Access Management）" data-link-desc="雲端平台的授權系統，回答「某個身分能不能對某個資源做某件事」">IAM&lt;/a> policy 的關係是交集而非覆蓋：一個操作要同時被 SCP 允許且被 IAM policy 允許才會生效。SCP 的設計目的是讓組織管理者設定「即使帳號管理員也做不了」的護欄，常見的 day-1 SCP 包括：禁止關閉 CloudTrail、禁止離開指定 region、禁止刪除 VPC Flow Logs。&lt;/p>
&lt;p>SCP 套用在 OU 上時會繼承給 OU 下所有帳號和子 OU。Management account（Organizations 的根帳號）不受 SCP 約束——這是設計上的逃生門，也是 management account 應該盡量不跑 workload 的原因。&lt;/p>
&lt;h2 id="可觀察訊號">可觀察訊號&lt;/h2>
&lt;p>當帳號內的 IAM role 執行某個操作時收到 &lt;code>AccessDeniedException&lt;/code>、但該 role 的 IAM policy 確實允許該操作，SCP 是第一個要檢查的位置。另一個訊號是新帳號加入 OU 後某些原本能用的服務突然不可用——通常是繼承了 OU 的 SCP deny list。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>SCP 的設計要決定：用 deny-list 策略（預設全開、明確列出禁止項）還是 allow-list 策略（預設全關、明確列出允許項）。Deny-list 較常見也較易維護——只需要管「哪些該禁」。Allow-list 更嚴格但維護成本高——每次有新服務需求都要更新 SCP。&lt;/p>
&lt;p>套用 SCP 前要確認不會擋到正在運作的服務——先在 sandbox OU 測試，確認既有 workload 不受影響再推到 workload OU。SCP 的變更跟 &lt;a href="https://tarrragon.github.io/blog/infra/knowledge-cards/iam/" data-link-title="IAM（Identity and Access Management）" data-link-desc="雲端平台的授權系統，回答「某個身分能不能對某個資源做某件事」">IAM&lt;/a> 一樣要走 PR review。跨帳號策略的完整設計見&lt;a href="https://tarrragon.github.io/blog/infra/02-identity-credentials/multi-account-strategy/" data-link-title="跨帳號策略 — Organizations、SCP 與帳號工廠" data-link-desc="用 AWS Organizations 把環境拆成獨立帳號、用 SCP 設定連管理員都越不過的護欄、用帳號工廠讓每個新帳號自帶安全基線">跨帳號策略文章&lt;/a>。&lt;/p>
&lt;h2 id="鄰卡">鄰卡&lt;/h2>
&lt;ul>
&lt;li>&lt;a href="https://tarrragon.github.io/blog/infra/knowledge-cards/iam/" data-link-title="IAM（Identity and Access Management）" data-link-desc="雲端平台的授權系統，回答「某個身分能不能對某個資源做某件事」">IAM&lt;/a> — SCP 是 IAM policy 的上層天花板&lt;/li>
&lt;li>&lt;a href="https://tarrragon.github.io/blog/infra/knowledge-cards/environment-separation/" data-link-title="環境分離" data-link-desc="把同一套基礎設施定義複製成多份隔離的執行實例，各有獨立 state 與故障半徑">環境分離&lt;/a> — SCP 靠 OU 結構實現環境之間的權限隔離&lt;/li>
&lt;/ul></description><content:encoded><![CDATA[<p>Service Control Policy（SCP）是 AWS Organizations 裡套用在 OU 或帳號上的權限上限。SCP 不授予權限——它設定一個天花板，限制該範圍內的 IAM 能做什麼。即使帳號內有 <code>AdministratorAccess</code> 的 IAM role，SCP deny 的操作仍然被擋下。</p>
<h2 id="概念位置">概念位置</h2>
<p>SCP 跟 <a href="/blog/infra/knowledge-cards/iam/" data-link-title="IAM（Identity and Access Management）" data-link-desc="雲端平台的授權系統，回答「某個身分能不能對某個資源做某件事」">IAM</a> policy 的關係是交集而非覆蓋：一個操作要同時被 SCP 允許且被 IAM policy 允許才會生效。SCP 的設計目的是讓組織管理者設定「即使帳號管理員也做不了」的護欄，常見的 day-1 SCP 包括：禁止關閉 CloudTrail、禁止離開指定 region、禁止刪除 VPC Flow Logs。</p>
<p>SCP 套用在 OU 上時會繼承給 OU 下所有帳號和子 OU。Management account（Organizations 的根帳號）不受 SCP 約束——這是設計上的逃生門，也是 management account 應該盡量不跑 workload 的原因。</p>
<h2 id="可觀察訊號">可觀察訊號</h2>
<p>當帳號內的 IAM role 執行某個操作時收到 <code>AccessDeniedException</code>、但該 role 的 IAM policy 確實允許該操作，SCP 是第一個要檢查的位置。另一個訊號是新帳號加入 OU 後某些原本能用的服務突然不可用——通常是繼承了 OU 的 SCP deny list。</p>
<h2 id="設計責任">設計責任</h2>
<p>SCP 的設計要決定：用 deny-list 策略（預設全開、明確列出禁止項）還是 allow-list 策略（預設全關、明確列出允許項）。Deny-list 較常見也較易維護——只需要管「哪些該禁」。Allow-list 更嚴格但維護成本高——每次有新服務需求都要更新 SCP。</p>
<p>套用 SCP 前要確認不會擋到正在運作的服務——先在 sandbox OU 測試，確認既有 workload 不受影響再推到 workload OU。SCP 的變更跟 <a href="/blog/infra/knowledge-cards/iam/" data-link-title="IAM（Identity and Access Management）" data-link-desc="雲端平台的授權系統，回答「某個身分能不能對某個資源做某件事」">IAM</a> 一樣要走 PR review。跨帳號策略的完整設計見<a href="/blog/infra/02-identity-credentials/multi-account-strategy/" data-link-title="跨帳號策略 — Organizations、SCP 與帳號工廠" data-link-desc="用 AWS Organizations 把環境拆成獨立帳號、用 SCP 設定連管理員都越不過的護欄、用帳號工廠讓每個新帳號自帶安全基線">跨帳號策略文章</a>。</p>
<h2 id="鄰卡">鄰卡</h2>
<ul>
<li><a href="/blog/infra/knowledge-cards/iam/" data-link-title="IAM（Identity and Access Management）" data-link-desc="雲端平台的授權系統，回答「某個身分能不能對某個資源做某件事」">IAM</a> — SCP 是 IAM policy 的上層天花板</li>
<li><a href="/blog/infra/knowledge-cards/environment-separation/" data-link-title="環境分離" data-link-desc="把同一套基礎設施定義複製成多份隔離的執行實例，各有獨立 state 與故障半徑">環境分離</a> — SCP 靠 OU 結構實現環境之間的權限隔離</li>
</ul>
]]></content:encoded></item><item><title>Remote State Backend</title><link>https://tarrragon.github.io/blog/infra/knowledge-cards/remote-state-backend/</link><pubDate>Fri, 26 Jun 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/infra/knowledge-cards/remote-state-backend/</guid><description>&lt;p>Remote state backend 是 IaC 工具用來存放 &lt;a href="https://tarrragon.github.io/blog/infra/knowledge-cards/state/" data-link-title="State（IaC 狀態檔）" data-link-desc="IaC 工具用來記錄每個納管資源在雲端真實樣貌的快照，是比對差異與排定操作順序的依據">state&lt;/a> 的共享儲存機制。它要同時滿足三件事：持久保存（不會因為某台筆電故障而遺失）、防止並行寫入衝突（兩個人不能同時 apply）、以及保護敏感內容（state 內含資源的真實屬性，可能包含密碼或 key）。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>State 是 &lt;a href="https://tarrragon.github.io/blog/infra/knowledge-cards/iac/" data-link-title="Infrastructure as Code (IaC)" data-link-desc="用程式碼描述基礎設施的最終狀態，由工具負責收斂現實與描述的差異">IaC&lt;/a> 工具對現實的唯一記憶。把它放在本地檔案系統等於把整個基礎設施的記憶綁在一台機器上——換人接手、換台電腦、或兩人同時 apply，記憶就分裂了。Remote state backend 解決的是「讓 state 變成團隊共用的、有保護的事實來源」。&lt;/p>
&lt;p>典型的自管組合是 S3（存放 state 檔、開 versioning 和加密）加上 DynamoDB（提供 apply 時的並行鎖）。託管服務（Terraform Cloud、Spacelift）把存放、鎖和加密包在一起，用月費換掉配置和維運負擔。&lt;/p>
&lt;h2 id="可觀察訊號">可觀察訊號&lt;/h2>
&lt;p>本地 state 的失敗訊號是：跑 &lt;code>terraform plan&lt;/code> 時出現「想刪掉」明知存在的資源——通常代表本地 state 跟雲端實際狀態已經脫節。另一個訊號是兩個人同時跑 apply 但沒有任何鎖機制阻擋——結果是互相覆蓋對方的變更，state 進入不一致狀態。&lt;/p>
&lt;p>Remote backend 設定後，如果 &lt;code>terraform init&lt;/code> 提示 state 遷移確認，代表正在從本地搬到遠端——這是正確的一次性操作，但搬遷過程中不能有其他人在 apply。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>選擇 remote state backend 時要決定：自管還是託管（取決於團隊規模和維運餘裕）、state bucket 的加密與存取控制（誰能讀 state 等於誰能看到所有資源的敏感屬性）、versioning 是否開啟（是 state 回捲的唯一退路）、以及鎖表的設定（DynamoDB 的表名和 partition key）。&lt;/p>
&lt;p>State 絕不能進 git——它含明文敏感值，推進版控等於把密碼寫進每個 clone 的歷史裡。Backend 設定本身（bucket name、region、鎖表名稱）寫在 HCL 裡進 git，state 檔本身只存在 backend 裡。&lt;/p>
&lt;h2 id="鄰卡">鄰卡&lt;/h2>
&lt;ul>
&lt;li>&lt;a href="https://tarrragon.github.io/blog/infra/knowledge-cards/state/" data-link-title="State（IaC 狀態檔）" data-link-desc="IaC 工具用來記錄每個納管資源在雲端真實樣貌的快照，是比對差異與排定操作順序的依據">State&lt;/a> — remote backend 存放的對象&lt;/li>
&lt;li>&lt;a href="https://tarrragon.github.io/blog/infra/knowledge-cards/drift/" data-link-title="Drift（設定漂移）" data-link-desc="IaC 的 state 與雲端實際狀態之間的不一致，通常因為有人繞過 IaC 直接在 Console 改設定">Drift&lt;/a> — state 與現實不一致時的現象&lt;/li>
&lt;li>&lt;a href="https://tarrragon.github.io/blog/infra/knowledge-cards/iac/" data-link-title="Infrastructure as Code (IaC)" data-link-desc="用程式碼描述基礎設施的最終狀態，由工具負責收斂現實與描述的差異">IaC&lt;/a> — remote state backend 是 IaC 工具的基礎設施&lt;/li>
&lt;/ul></description><content:encoded><![CDATA[<p>Remote state backend 是 IaC 工具用來存放 <a href="/blog/infra/knowledge-cards/state/" data-link-title="State（IaC 狀態檔）" data-link-desc="IaC 工具用來記錄每個納管資源在雲端真實樣貌的快照，是比對差異與排定操作順序的依據">state</a> 的共享儲存機制。它要同時滿足三件事：持久保存（不會因為某台筆電故障而遺失）、防止並行寫入衝突（兩個人不能同時 apply）、以及保護敏感內容（state 內含資源的真實屬性，可能包含密碼或 key）。</p>
<h2 id="概念位置">概念位置</h2>
<p>State 是 <a href="/blog/infra/knowledge-cards/iac/" data-link-title="Infrastructure as Code (IaC)" data-link-desc="用程式碼描述基礎設施的最終狀態，由工具負責收斂現實與描述的差異">IaC</a> 工具對現實的唯一記憶。把它放在本地檔案系統等於把整個基礎設施的記憶綁在一台機器上——換人接手、換台電腦、或兩人同時 apply，記憶就分裂了。Remote state backend 解決的是「讓 state 變成團隊共用的、有保護的事實來源」。</p>
<p>典型的自管組合是 S3（存放 state 檔、開 versioning 和加密）加上 DynamoDB（提供 apply 時的並行鎖）。託管服務（Terraform Cloud、Spacelift）把存放、鎖和加密包在一起，用月費換掉配置和維運負擔。</p>
<h2 id="可觀察訊號">可觀察訊號</h2>
<p>本地 state 的失敗訊號是：跑 <code>terraform plan</code> 時出現「想刪掉」明知存在的資源——通常代表本地 state 跟雲端實際狀態已經脫節。另一個訊號是兩個人同時跑 apply 但沒有任何鎖機制阻擋——結果是互相覆蓋對方的變更，state 進入不一致狀態。</p>
<p>Remote backend 設定後，如果 <code>terraform init</code> 提示 state 遷移確認，代表正在從本地搬到遠端——這是正確的一次性操作，但搬遷過程中不能有其他人在 apply。</p>
<h2 id="設計責任">設計責任</h2>
<p>選擇 remote state backend 時要決定：自管還是託管（取決於團隊規模和維運餘裕）、state bucket 的加密與存取控制（誰能讀 state 等於誰能看到所有資源的敏感屬性）、versioning 是否開啟（是 state 回捲的唯一退路）、以及鎖表的設定（DynamoDB 的表名和 partition key）。</p>
<p>State 絕不能進 git——它含明文敏感值，推進版控等於把密碼寫進每個 clone 的歷史裡。Backend 設定本身（bucket name、region、鎖表名稱）寫在 HCL 裡進 git，state 檔本身只存在 backend 裡。</p>
<h2 id="鄰卡">鄰卡</h2>
<ul>
<li><a href="/blog/infra/knowledge-cards/state/" data-link-title="State（IaC 狀態檔）" data-link-desc="IaC 工具用來記錄每個納管資源在雲端真實樣貌的快照，是比對差異與排定操作順序的依據">State</a> — remote backend 存放的對象</li>
<li><a href="/blog/infra/knowledge-cards/drift/" data-link-title="Drift（設定漂移）" data-link-desc="IaC 的 state 與雲端實際狀態之間的不一致，通常因為有人繞過 IaC 直接在 Console 改設定">Drift</a> — state 與現實不一致時的現象</li>
<li><a href="/blog/infra/knowledge-cards/iac/" data-link-title="Infrastructure as Code (IaC)" data-link-desc="用程式碼描述基礎設施的最終狀態，由工具負責收斂現實與描述的差異">IaC</a> — remote state backend 是 IaC 工具的基礎設施</li>
</ul>
]]></content:encoded></item><item><title>Trust Policy</title><link>https://tarrragon.github.io/blog/infra/knowledge-cards/trust-policy/</link><pubDate>Fri, 26 Jun 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/infra/knowledge-cards/trust-policy/</guid><description>&lt;p>Trust policy 是附加在 &lt;a href="https://tarrragon.github.io/blog/infra/knowledge-cards/iam/" data-link-title="IAM（Identity and Access Management）" data-link-desc="雲端平台的授權系統，回答「某個身分能不能對某個資源做某件事」">IAM&lt;/a> role 上的一份 JSON 文件，定義「誰被允許臨時取得（assume）這個 role 的權限」。跟 IAM policy 的差別是：IAM policy 描述「這個 role 能做什麼」，trust policy 描述「誰能變成這個 role」。兩者合在一起才構成完整的授權——先過 trust policy 的門、再受 IAM policy 的限。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>Trust policy 是 &lt;a href="https://tarrragon.github.io/blog/infra/knowledge-cards/oidc/" data-link-title="OIDC 聯合" data-link-desc="讓 CI/CD 平台用短期 token 取代長期 access key 存取雲端資源的身分聯合機制">OIDC&lt;/a> 聯合的核心配件。當 CI/CD 平台（GitHub Actions、GitLab CI）要用短期憑證存取雲端資源時，trust policy 用 OIDC token 裡的 claim（issuer、audience、subject）決定「這個 token 代表的身分能不能 assume 這個 role」。&lt;/p>
&lt;p>Trust policy 的設計要點是 claim 的收斂程度。只驗 issuer 而不驗 repo 和 branch，等於同一個 CI 平台上所有專案都能 assume 這個 role——這是常見的設定陷阱。收到最緊意味著限定到「某個 org 的某個 repo 的某個 branch 或 environment」。&lt;/p>
&lt;h2 id="可觀察訊號">可觀察訊號&lt;/h2>
&lt;p>&lt;code>sts:AssumeRoleWithWebIdentity&lt;/code> 呼叫失敗、回傳 &lt;code>AccessDenied&lt;/code> 時，問題通常在 trust policy 的 condition 比對不上。排查路徑是把 CI 平台簽發的 OIDC token decode（JWT 的 payload 部分），逐一比對 token 裡的 &lt;code>iss&lt;/code>、&lt;code>aud&lt;/code>、&lt;code>sub&lt;/code> 跟 trust policy 的 condition 值。&lt;/p>
&lt;p>另一個訊號是 trust policy 的 condition 用了 &lt;code>StringLike&lt;/code> 但 pattern 太寬（如 &lt;code>repo:my-org/*&lt;/code>），讓非預期的 repo 也能 assume——這類過寬的 trust policy 在安全稽核時會被標記。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>設計 trust policy 時要決定：允許哪些外部身分 assume（issuer + subject 的精確匹配）、audience 是否需要額外驗證（AWS 預設 &lt;code>sts.amazonaws.com&lt;/code>）、以及是否把 plan role 和 apply role 分開（plan 只需 read-only、apply 需要 write，用兩個 role 各自設不同 trust condition 來區分 branch 或 environment）。&lt;/p>
&lt;p>Trust policy 的變更跟 &lt;a href="https://tarrragon.github.io/blog/infra/knowledge-cards/iam/" data-link-title="IAM（Identity and Access Management）" data-link-desc="雲端平台的授權系統，回答「某個身分能不能對某個資源做某件事」">IAM&lt;/a> policy 一樣要走 PR review——因為改寬一個 condition 就等於給更多外部身分開門。設定指南見 &lt;a href="https://tarrragon.github.io/blog/infra/02-identity-credentials/oidc-trust-policy-setup/" data-link-title="OIDC Trust Policy 設定指南" data-link-desc="GitHub Actions 與 AWS 之間的 OIDC 聯合設定：建立 provider、設計 trust policy 的 claim 收斂、plan 與 apply role 分離、常見錯誤排查">OIDC Trust Policy 設定指南&lt;/a>。&lt;/p>
&lt;h2 id="鄰卡">鄰卡&lt;/h2>
&lt;ul>
&lt;li>&lt;a href="https://tarrragon.github.io/blog/infra/knowledge-cards/iam/" data-link-title="IAM（Identity and Access Management）" data-link-desc="雲端平台的授權系統，回答「某個身分能不能對某個資源做某件事」">IAM&lt;/a> — trust policy 是 IAM role 的一部分&lt;/li>
&lt;li>&lt;a href="https://tarrragon.github.io/blog/infra/knowledge-cards/oidc/" data-link-title="OIDC 聯合" data-link-desc="讓 CI/CD 平台用短期 token 取代長期 access key 存取雲端資源的身分聯合機制">OIDC&lt;/a> — trust policy 用 OIDC token 的 claim 做 assume 判斷&lt;/li>
&lt;/ul></description><content:encoded><![CDATA[<p>Trust policy 是附加在 <a href="/blog/infra/knowledge-cards/iam/" data-link-title="IAM（Identity and Access Management）" data-link-desc="雲端平台的授權系統，回答「某個身分能不能對某個資源做某件事」">IAM</a> role 上的一份 JSON 文件，定義「誰被允許臨時取得（assume）這個 role 的權限」。跟 IAM policy 的差別是：IAM policy 描述「這個 role 能做什麼」，trust policy 描述「誰能變成這個 role」。兩者合在一起才構成完整的授權——先過 trust policy 的門、再受 IAM policy 的限。</p>
<h2 id="概念位置">概念位置</h2>
<p>Trust policy 是 <a href="/blog/infra/knowledge-cards/oidc/" data-link-title="OIDC 聯合" data-link-desc="讓 CI/CD 平台用短期 token 取代長期 access key 存取雲端資源的身分聯合機制">OIDC</a> 聯合的核心配件。當 CI/CD 平台（GitHub Actions、GitLab CI）要用短期憑證存取雲端資源時，trust policy 用 OIDC token 裡的 claim（issuer、audience、subject）決定「這個 token 代表的身分能不能 assume 這個 role」。</p>
<p>Trust policy 的設計要點是 claim 的收斂程度。只驗 issuer 而不驗 repo 和 branch，等於同一個 CI 平台上所有專案都能 assume 這個 role——這是常見的設定陷阱。收到最緊意味著限定到「某個 org 的某個 repo 的某個 branch 或 environment」。</p>
<h2 id="可觀察訊號">可觀察訊號</h2>
<p><code>sts:AssumeRoleWithWebIdentity</code> 呼叫失敗、回傳 <code>AccessDenied</code> 時，問題通常在 trust policy 的 condition 比對不上。排查路徑是把 CI 平台簽發的 OIDC token decode（JWT 的 payload 部分），逐一比對 token 裡的 <code>iss</code>、<code>aud</code>、<code>sub</code> 跟 trust policy 的 condition 值。</p>
<p>另一個訊號是 trust policy 的 condition 用了 <code>StringLike</code> 但 pattern 太寬（如 <code>repo:my-org/*</code>），讓非預期的 repo 也能 assume——這類過寬的 trust policy 在安全稽核時會被標記。</p>
<h2 id="設計責任">設計責任</h2>
<p>設計 trust policy 時要決定：允許哪些外部身分 assume（issuer + subject 的精確匹配）、audience 是否需要額外驗證（AWS 預設 <code>sts.amazonaws.com</code>）、以及是否把 plan role 和 apply role 分開（plan 只需 read-only、apply 需要 write，用兩個 role 各自設不同 trust condition 來區分 branch 或 environment）。</p>
<p>Trust policy 的變更跟 <a href="/blog/infra/knowledge-cards/iam/" data-link-title="IAM（Identity and Access Management）" data-link-desc="雲端平台的授權系統，回答「某個身分能不能對某個資源做某件事」">IAM</a> policy 一樣要走 PR review——因為改寬一個 condition 就等於給更多外部身分開門。設定指南見 <a href="/blog/infra/02-identity-credentials/oidc-trust-policy-setup/" data-link-title="OIDC Trust Policy 設定指南" data-link-desc="GitHub Actions 與 AWS 之間的 OIDC 聯合設定：建立 provider、設計 trust policy 的 claim 收斂、plan 與 apply role 分離、常見錯誤排查">OIDC Trust Policy 設定指南</a>。</p>
<h2 id="鄰卡">鄰卡</h2>
<ul>
<li><a href="/blog/infra/knowledge-cards/iam/" data-link-title="IAM（Identity and Access Management）" data-link-desc="雲端平台的授權系統，回答「某個身分能不能對某個資源做某件事」">IAM</a> — trust policy 是 IAM role 的一部分</li>
<li><a href="/blog/infra/knowledge-cards/oidc/" data-link-title="OIDC 聯合" data-link-desc="讓 CI/CD 平台用短期 token 取代長期 access key 存取雲端資源的身分聯合機制">OIDC</a> — trust policy 用 OIDC token 的 claim 做 assume 判斷</li>
</ul>
]]></content:encoded></item><item><title>Deletion Protection</title><link>https://tarrragon.github.io/blog/infra/knowledge-cards/deletion-protection/</link><pubDate>Fri, 26 Jun 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/infra/knowledge-cards/deletion-protection/</guid><description>&lt;p>Deletion protection 是雲端平台在資源層級提供的防護機制：開啟後，任何刪除該資源的操作（Console 點按、CLI 指令、IaC 的 destroy）都會被擋下，必須先顯式關閉保護才能執行刪除。這個額外步驟的目的是防止手滑、批次操作誤傷、以及 Terraform plan 裡意外出現的 destroy。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>Deletion protection 是 &lt;a href="https://tarrragon.github.io/blog/infra/05-core-services/stateful-protection-dependency/" data-link-title="Stateful 資源保護與跨服務依賴表達" data-link-desc="stateful 資源的保護策略（multi-AZ、備份、刪除保護）、stateful 與 stateless 的操作差異，以及用 output 與 data source 表達服務間依賴">stateful 資源保護&lt;/a>的第一道防線。運算節點可以隨時重建，資料一旦遺失通常無法重來——這條分界線決定了哪些資源該開保護。對 stateful 資源（資料庫、持久化儲存）來說，這是 day-1 該開的設定，不是「等穩定再開」的選項。&lt;/p>
&lt;p>不同 AWS 服務的保護機制名稱不同但行為一致：&lt;/p>
&lt;table>
 &lt;thead>
 &lt;tr>
 &lt;th>服務&lt;/th>
 &lt;th>屬性名稱&lt;/th>
 &lt;th>保護對象&lt;/th>
 &lt;/tr>
 &lt;/thead>
 &lt;tbody>
 &lt;tr>
 &lt;td>RDS&lt;/td>
 &lt;td>&lt;code>deletion_protection&lt;/code>&lt;/td>
 &lt;td>資料庫 instance&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>EC2&lt;/td>
 &lt;td>&lt;code>disable_api_termination&lt;/code>&lt;/td>
 &lt;td>運算 instance&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>S3&lt;/td>
 &lt;td>MFA delete&lt;/td>
 &lt;td>bucket 版本控制&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>DynamoDB&lt;/td>
 &lt;td>&lt;code>deletion_protection_enabled&lt;/code>&lt;/td>
 &lt;td>表格&lt;/td>
 &lt;/tr>
 &lt;/tbody>
&lt;/table>
&lt;h2 id="可觀察訊號">可觀察訊號&lt;/h2>
&lt;p>需要開啟 deletion protection 的訊號是資源承載了不可重建的狀態。判斷方式是問一個問題：「這個資源被刪除後，能不能在 10 分鐘內從程式碼或備份完整恢復？」不能的就該開。&lt;/p>
&lt;p>&lt;code>terraform plan&lt;/code> 輸出裡出現 &lt;code>destroy&lt;/code> 或 &lt;code>forces replacement&lt;/code>（&lt;code>-/+&lt;/code>）時，deletion protection 是阻擋意外資料遺失的最後一道閘門。有保護的資源在 apply 時會報錯而非直接刪除，讓操作者有機會停下來確認。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>用 &lt;a href="https://tarrragon.github.io/blog/infra/knowledge-cards/iac/" data-link-title="Infrastructure as Code (IaC)" data-link-desc="用程式碼描述基礎設施的最終狀態，由工具負責收斂現實與描述的差異">IaC&lt;/a> 描述 stateful 資源時，把 deletion protection 寫進程式碼而非手動在 Console 開啟——這讓保護策略本身成為可審查、可追蹤的設定。同時搭配 &lt;code>skip_final_snapshot = false&lt;/code>（RDS）確保刪除前自動做最後一份快照。&lt;/p>
&lt;p>Deletion protection 擋的是刪除操作，不擋資料覆寫或邏輯損壞——一段錯誤的 UPDATE 不會被 deletion protection 攔截。資料層的完整防線還需要備份保留與時間點還原（PITR），跟 deletion protection 正交。&lt;/p>
&lt;h2 id="鄰卡">鄰卡&lt;/h2>
&lt;ul>
&lt;li>&lt;a href="https://tarrragon.github.io/blog/infra/knowledge-cards/state/" data-link-title="State（IaC 狀態檔）" data-link-desc="IaC 工具用來記錄每個納管資源在雲端真實樣貌的快照，是比對差異與排定操作順序的依據">State&lt;/a> — deletion protection 在 &lt;a href="https://tarrragon.github.io/blog/infra/knowledge-cards/state/" data-link-title="State（IaC 狀態檔）" data-link-desc="IaC 工具用來記錄每個納管資源在雲端真實樣貌的快照，是比對差異與排定操作順序的依據">state&lt;/a> 裡記錄為資源屬性，plan 會顯示保護狀態&lt;/li>
&lt;li>&lt;a href="https://tarrragon.github.io/blog/infra/knowledge-cards/iac/" data-link-title="Infrastructure as Code (IaC)" data-link-desc="用程式碼描述基礎設施的最終狀態，由工具負責收斂現實與描述的差異">IaC&lt;/a> — 保護策略寫進 IaC 讓它可審查&lt;/li>
&lt;/ul></description><content:encoded><![CDATA[<p>Deletion protection 是雲端平台在資源層級提供的防護機制：開啟後，任何刪除該資源的操作（Console 點按、CLI 指令、IaC 的 destroy）都會被擋下，必須先顯式關閉保護才能執行刪除。這個額外步驟的目的是防止手滑、批次操作誤傷、以及 Terraform plan 裡意外出現的 destroy。</p>
<h2 id="概念位置">概念位置</h2>
<p>Deletion protection 是 <a href="/blog/infra/05-core-services/stateful-protection-dependency/" data-link-title="Stateful 資源保護與跨服務依賴表達" data-link-desc="stateful 資源的保護策略（multi-AZ、備份、刪除保護）、stateful 與 stateless 的操作差異，以及用 output 與 data source 表達服務間依賴">stateful 資源保護</a>的第一道防線。運算節點可以隨時重建，資料一旦遺失通常無法重來——這條分界線決定了哪些資源該開保護。對 stateful 資源（資料庫、持久化儲存）來說，這是 day-1 該開的設定，不是「等穩定再開」的選項。</p>
<p>不同 AWS 服務的保護機制名稱不同但行為一致：</p>
<table>
  <thead>
      <tr>
          <th>服務</th>
          <th>屬性名稱</th>
          <th>保護對象</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>RDS</td>
          <td><code>deletion_protection</code></td>
          <td>資料庫 instance</td>
      </tr>
      <tr>
          <td>EC2</td>
          <td><code>disable_api_termination</code></td>
          <td>運算 instance</td>
      </tr>
      <tr>
          <td>S3</td>
          <td>MFA delete</td>
          <td>bucket 版本控制</td>
      </tr>
      <tr>
          <td>DynamoDB</td>
          <td><code>deletion_protection_enabled</code></td>
          <td>表格</td>
      </tr>
  </tbody>
</table>
<h2 id="可觀察訊號">可觀察訊號</h2>
<p>需要開啟 deletion protection 的訊號是資源承載了不可重建的狀態。判斷方式是問一個問題：「這個資源被刪除後，能不能在 10 分鐘內從程式碼或備份完整恢復？」不能的就該開。</p>
<p><code>terraform plan</code> 輸出裡出現 <code>destroy</code> 或 <code>forces replacement</code>（<code>-/+</code>）時，deletion protection 是阻擋意外資料遺失的最後一道閘門。有保護的資源在 apply 時會報錯而非直接刪除，讓操作者有機會停下來確認。</p>
<h2 id="設計責任">設計責任</h2>
<p>用 <a href="/blog/infra/knowledge-cards/iac/" data-link-title="Infrastructure as Code (IaC)" data-link-desc="用程式碼描述基礎設施的最終狀態，由工具負責收斂現實與描述的差異">IaC</a> 描述 stateful 資源時，把 deletion protection 寫進程式碼而非手動在 Console 開啟——這讓保護策略本身成為可審查、可追蹤的設定。同時搭配 <code>skip_final_snapshot = false</code>（RDS）確保刪除前自動做最後一份快照。</p>
<p>Deletion protection 擋的是刪除操作，不擋資料覆寫或邏輯損壞——一段錯誤的 UPDATE 不會被 deletion protection 攔截。資料層的完整防線還需要備份保留與時間點還原（PITR），跟 deletion protection 正交。</p>
<h2 id="鄰卡">鄰卡</h2>
<ul>
<li><a href="/blog/infra/knowledge-cards/state/" data-link-title="State（IaC 狀態檔）" data-link-desc="IaC 工具用來記錄每個納管資源在雲端真實樣貌的快照，是比對差異與排定操作順序的依據">State</a> — deletion protection 在 <a href="/blog/infra/knowledge-cards/state/" data-link-title="State（IaC 狀態檔）" data-link-desc="IaC 工具用來記錄每個納管資源在雲端真實樣貌的快照，是比對差異與排定操作順序的依據">state</a> 裡記錄為資源屬性，plan 會顯示保護狀態</li>
<li><a href="/blog/infra/knowledge-cards/iac/" data-link-title="Infrastructure as Code (IaC)" data-link-desc="用程式碼描述基礎設施的最終狀態，由工具負責收斂現實與描述的差異">IaC</a> — 保護策略寫進 IaC 讓它可審查</li>
</ul>
]]></content:encoded></item><item><title>checkov</title><link>https://tarrragon.github.io/blog/infra/knowledge-cards/checkov/</link><pubDate>Fri, 26 Jun 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/infra/knowledge-cards/checkov/</guid><description>&lt;p>checkov 是一個開源的靜態分析工具，掃描 Terraform / CloudFormation / Kubernetes 等 IaC 程式碼，比對內建的規則庫找出安全漏洞與合規違規。它在 &lt;code>plan&lt;/code> 之前或之後執行、不建立任何雲端資源，所以是 CI pipeline 裡最便宜的安全檢查之一。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>checkov 在 &lt;a href="https://tarrragon.github.io/blog/infra/07-infra-as-pr/plan-review-apply-guardrails/" data-link-title="infra 走 PR 流程與自動化護欄" data-link-desc="infra 變更走 PR → plan → review diff → 合併 → apply，配 fmt / validate / tflint / checkov / tfsec 與 Atlantis 自動化，讓基礎設施可審查、可回溯、可交接">infra PR 流程&lt;/a>裡的位置是 &lt;code>fmt&lt;/code> → &lt;code>validate&lt;/code> → &lt;strong>checkov / tfsec&lt;/strong> → &lt;code>plan&lt;/code>。前兩步檢查語法正確，checkov 檢查語意安全，plan 檢查實際差異。checkov 補的是 reviewer 肉眼容易漏的盲區——一條 &lt;a href="https://tarrragon.github.io/blog/infra/knowledge-cards/security-group/" data-link-title="Security Group" data-link-desc="掛在資源網卡層級的有狀態防火牆，逐埠決定哪些來源能連進這個資源">security group&lt;/a> 規則寫成 &lt;code>0.0.0.0/0&lt;/code> 在 HCL 裡只是一行字串，人會看漏，規則不會。&lt;/p>
&lt;p>三個常見的 IaC 掃描工具各有側重：&lt;/p>
&lt;table>
 &lt;thead>
 &lt;tr>
 &lt;th>工具&lt;/th>
 &lt;th>側重&lt;/th>
 &lt;th>維護方&lt;/th>
 &lt;/tr>
 &lt;/thead>
 &lt;tbody>
 &lt;tr>
 &lt;td>checkov&lt;/td>
 &lt;td>安全 + 合規&lt;/td>
 &lt;td>Prisma Cloud (Palo Alto)&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>tfsec&lt;/td>
 &lt;td>安全&lt;/td>
 &lt;td>Aqua Security&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>tflint&lt;/td>
 &lt;td>provider 正確性&lt;/td>
 &lt;td>社群&lt;/td>
 &lt;/tr>
 &lt;/tbody>
&lt;/table>
&lt;p>checkov 的規則庫最廣（涵蓋 CIS Benchmark、SOC 2、PCI DSS 等合規框架），tfsec 的規則更聚焦安全面，tflint 偏向「這個 instance type 在這個 region 存不存在」的 provider 正確性。三者可疊加使用。&lt;/p>
&lt;h2 id="可觀察訊號">可觀察訊號&lt;/h2>
&lt;p>需要引入 checkov 的訊號是 PR review 開始漏掉安全問題——S3 bucket 缺 public access block、RDS 沒開加密、IAM policy 過寬。這些問題的 pattern 是固定的、可以用規則比對，不應該靠人記憶來擋。&lt;/p>
&lt;p>checkov 命中後要區分「真漏洞」和「情境合理的例外」。ALB 的 HTTPS listener 在 port 443 開 &lt;code>0.0.0.0/0&lt;/code> 是設計本意，不是漏洞。豁免用行內註解標記並寫理由：&lt;code>#checkov:skip=CKV_AWS_260:ALB public HTTPS listener&lt;/code>。詳細的規則配置與豁免管理見 &lt;a href="https://tarrragon.github.io/blog/infra/07-infra-as-pr/checkov-tfsec-rule-customization/" data-link-title="checkov 與 tfsec 規則配置" data-link-desc="靜態掃描工具的規則選擇策略、自訂規則、豁免管理、false positive 處理與 CI 整合，讓掃描從噪音來源變成可信的品質關卡">checkov 與 tfsec 規則配置&lt;/a>。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>引入 checkov 時要決定兩件事：啟用哪些規則（全部 vs 漸進啟用），以及命中時 CI 要不要擋（hard fail vs warning）。常見的漸進策略是先從高嚴重度規則開始、設為 hard fail，中低嚴重度設為 warning，隨團隊習慣逐步收緊。&lt;/p>
&lt;h2 id="鄰卡">鄰卡&lt;/h2>
&lt;ul>
&lt;li>&lt;a href="https://tarrragon.github.io/blog/infra/knowledge-cards/iac/" data-link-title="Infrastructure as Code (IaC)" data-link-desc="用程式碼描述基礎設施的最終狀態，由工具負責收斂現實與描述的差異">IaC&lt;/a> — checkov 掃描的對象&lt;/li>
&lt;li>&lt;a href="https://tarrragon.github.io/blog/infra/knowledge-cards/security-group/" data-link-title="Security Group" data-link-desc="掛在資源網卡層級的有狀態防火牆，逐埠決定哪些來源能連進這個資源">Security Group&lt;/a> — checkov 最常攔截的 &lt;code>0.0.0.0/0&lt;/code> 全開規則&lt;/li>
&lt;/ul></description><content:encoded><![CDATA[<p>checkov 是一個開源的靜態分析工具，掃描 Terraform / CloudFormation / Kubernetes 等 IaC 程式碼，比對內建的規則庫找出安全漏洞與合規違規。它在 <code>plan</code> 之前或之後執行、不建立任何雲端資源，所以是 CI pipeline 裡最便宜的安全檢查之一。</p>
<h2 id="概念位置">概念位置</h2>
<p>checkov 在 <a href="/blog/infra/07-infra-as-pr/plan-review-apply-guardrails/" data-link-title="infra 走 PR 流程與自動化護欄" data-link-desc="infra 變更走 PR → plan → review diff → 合併 → apply，配 fmt / validate / tflint / checkov / tfsec 與 Atlantis 自動化，讓基礎設施可審查、可回溯、可交接">infra PR 流程</a>裡的位置是 <code>fmt</code> → <code>validate</code> → <strong>checkov / tfsec</strong> → <code>plan</code>。前兩步檢查語法正確，checkov 檢查語意安全，plan 檢查實際差異。checkov 補的是 reviewer 肉眼容易漏的盲區——一條 <a href="/blog/infra/knowledge-cards/security-group/" data-link-title="Security Group" data-link-desc="掛在資源網卡層級的有狀態防火牆，逐埠決定哪些來源能連進這個資源">security group</a> 規則寫成 <code>0.0.0.0/0</code> 在 HCL 裡只是一行字串，人會看漏，規則不會。</p>
<p>三個常見的 IaC 掃描工具各有側重：</p>
<table>
  <thead>
      <tr>
          <th>工具</th>
          <th>側重</th>
          <th>維護方</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>checkov</td>
          <td>安全 + 合規</td>
          <td>Prisma Cloud (Palo Alto)</td>
      </tr>
      <tr>
          <td>tfsec</td>
          <td>安全</td>
          <td>Aqua Security</td>
      </tr>
      <tr>
          <td>tflint</td>
          <td>provider 正確性</td>
          <td>社群</td>
      </tr>
  </tbody>
</table>
<p>checkov 的規則庫最廣（涵蓋 CIS Benchmark、SOC 2、PCI DSS 等合規框架），tfsec 的規則更聚焦安全面，tflint 偏向「這個 instance type 在這個 region 存不存在」的 provider 正確性。三者可疊加使用。</p>
<h2 id="可觀察訊號">可觀察訊號</h2>
<p>需要引入 checkov 的訊號是 PR review 開始漏掉安全問題——S3 bucket 缺 public access block、RDS 沒開加密、IAM policy 過寬。這些問題的 pattern 是固定的、可以用規則比對，不應該靠人記憶來擋。</p>
<p>checkov 命中後要區分「真漏洞」和「情境合理的例外」。ALB 的 HTTPS listener 在 port 443 開 <code>0.0.0.0/0</code> 是設計本意，不是漏洞。豁免用行內註解標記並寫理由：<code>#checkov:skip=CKV_AWS_260:ALB public HTTPS listener</code>。詳細的規則配置與豁免管理見 <a href="/blog/infra/07-infra-as-pr/checkov-tfsec-rule-customization/" data-link-title="checkov 與 tfsec 規則配置" data-link-desc="靜態掃描工具的規則選擇策略、自訂規則、豁免管理、false positive 處理與 CI 整合，讓掃描從噪音來源變成可信的品質關卡">checkov 與 tfsec 規則配置</a>。</p>
<h2 id="設計責任">設計責任</h2>
<p>引入 checkov 時要決定兩件事：啟用哪些規則（全部 vs 漸進啟用），以及命中時 CI 要不要擋（hard fail vs warning）。常見的漸進策略是先從高嚴重度規則開始、設為 hard fail，中低嚴重度設為 warning，隨團隊習慣逐步收緊。</p>
<h2 id="鄰卡">鄰卡</h2>
<ul>
<li><a href="/blog/infra/knowledge-cards/iac/" data-link-title="Infrastructure as Code (IaC)" data-link-desc="用程式碼描述基礎設施的最終狀態，由工具負責收斂現實與描述的差異">IaC</a> — checkov 掃描的對象</li>
<li><a href="/blog/infra/knowledge-cards/security-group/" data-link-title="Security Group" data-link-desc="掛在資源網卡層級的有狀態防火牆，逐埠決定哪些來源能連進這個資源">Security Group</a> — checkov 最常攔截的 <code>0.0.0.0/0</code> 全開規則</li>
</ul>
]]></content:encoded></item><item><title>GTM</title><link>https://tarrragon.github.io/blog/business/knowledge-cards/gtm/</link><pubDate>Tue, 19 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/business/knowledge-cards/gtm/</guid><description>&lt;p>GTM 的核心概念是「Go-To-Market，進入市場策略」—公司怎麼把產品賣到市場上的整套打法，包括定位、定價、銷售管道、目標客戶、行銷訊息、組織安排。GTM 不只是行銷或銷售，是從產品到收入的完整路徑設計。GTM 選擇決定 &lt;a href="https://tarrragon.github.io/blog/business/knowledge-cards/cac/" data-link-title="CAC" data-link-desc="說明獲客成本及其對商業模式可行性的決定作用">CAC&lt;/a> 結構。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>GTM 是商業模式的執行層。同一個產品可以走不同 GTM—例如 &lt;a href="https://tarrragon.github.io/blog/business/knowledge-cards/plg/" data-link-title="PLG" data-link-desc="說明產品自助成長模式與其經濟前提">PLG&lt;/a>（產品自助）、Sales-led（業務驅動）、Channel（通路夥伴）、&lt;a href="https://tarrragon.github.io/blog/business/knowledge-cards/fde/" data-link-title="FDE" data-link-desc="說明前線部署工程師模式的成立條件">FDE&lt;/a>（前線駐點）、&lt;a href="https://tarrragon.github.io/blog/business/knowledge-cards/enterprise-license/" data-link-title="Enterprise License" data-link-desc="說明企業級授權的商業模式與鎖定效應">Enterprise License&lt;/a>（企業合約）。GTM 選擇直接影響 &lt;a href="https://tarrragon.github.io/blog/business/knowledge-cards/cac/" data-link-title="CAC" data-link-desc="說明獲客成本及其對商業模式可行性的決定作用">CAC&lt;/a>、銷售週期、客戶輪廓。&lt;/p>
&lt;h2 id="可觀察訊號與例子">可觀察訊號與例子&lt;/h2>
&lt;p>判讀一家公司的 GTM：看它的銷售團隊比例（PLG 銷售很少，Enterprise 銷售人數比工程師多）、客戶簽約週期（PLG 幾分鐘，Enterprise 幾個月）、定價公開程度（PLG 全公開，Enterprise 需要 contact sales）。同一家公司在不同產品線可能走不同 GTM。&lt;/p>
&lt;h2 id="判讀方式">判讀方式&lt;/h2>
&lt;p>讀「重新設計 GTM」「FDE 是新的 GTM」這類論述時，意味著該公司認為原本的進市場路徑不可行，需要結構性換打法。AI Labs 共同的 GTM 轉向就是從「賣 API 給開發者」變成「派工程師進企業」—這是 GTM 層的重大判斷，不只是業務團隊增員，而是商業模式的重新定位。&lt;/p></description><content:encoded><![CDATA[<p>GTM 的核心概念是「Go-To-Market，進入市場策略」—公司怎麼把產品賣到市場上的整套打法，包括定位、定價、銷售管道、目標客戶、行銷訊息、組織安排。GTM 不只是行銷或銷售，是從產品到收入的完整路徑設計。GTM 選擇決定 <a href="/blog/business/knowledge-cards/cac/" data-link-title="CAC" data-link-desc="說明獲客成本及其對商業模式可行性的決定作用">CAC</a> 結構。</p>
<h2 id="概念位置">概念位置</h2>
<p>GTM 是商業模式的執行層。同一個產品可以走不同 GTM—例如 <a href="/blog/business/knowledge-cards/plg/" data-link-title="PLG" data-link-desc="說明產品自助成長模式與其經濟前提">PLG</a>（產品自助）、Sales-led（業務驅動）、Channel（通路夥伴）、<a href="/blog/business/knowledge-cards/fde/" data-link-title="FDE" data-link-desc="說明前線部署工程師模式的成立條件">FDE</a>（前線駐點）、<a href="/blog/business/knowledge-cards/enterprise-license/" data-link-title="Enterprise License" data-link-desc="說明企業級授權的商業模式與鎖定效應">Enterprise License</a>（企業合約）。GTM 選擇直接影響 <a href="/blog/business/knowledge-cards/cac/" data-link-title="CAC" data-link-desc="說明獲客成本及其對商業模式可行性的決定作用">CAC</a>、銷售週期、客戶輪廓。</p>
<h2 id="可觀察訊號與例子">可觀察訊號與例子</h2>
<p>判讀一家公司的 GTM：看它的銷售團隊比例（PLG 銷售很少，Enterprise 銷售人數比工程師多）、客戶簽約週期（PLG 幾分鐘，Enterprise 幾個月）、定價公開程度（PLG 全公開，Enterprise 需要 contact sales）。同一家公司在不同產品線可能走不同 GTM。</p>
<h2 id="判讀方式">判讀方式</h2>
<p>讀「重新設計 GTM」「FDE 是新的 GTM」這類論述時，意味著該公司認為原本的進市場路徑不可行，需要結構性換打法。AI Labs 共同的 GTM 轉向就是從「賣 API 給開發者」變成「派工程師進企業」—這是 GTM 層的重大判斷，不只是業務團隊增員，而是商業模式的重新定位。</p>
]]></content:encoded></item><item><title>Fargate</title><link>https://tarrragon.github.io/blog/infra/knowledge-cards/fargate/</link><pubDate>Fri, 26 Jun 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/infra/knowledge-cards/fargate/</guid><description>&lt;p>Fargate 是 AWS &lt;a href="https://tarrragon.github.io/blog/infra/knowledge-cards/ecs/" data-link-title="ECS" data-link-desc="AWS Elastic Container Service — 受管的容器編排服務，用 task definition 描述容器配置、由平台負責排程與健康管理">ECS&lt;/a> 的一種 launch type，把容器的運算實例交給 AWS 代管。使用 Fargate 時不需要配 EC2 instance、不需要管 capacity provider 的 scaling、不需要更新 AMI——只描述 task 需要多少 vCPU 和記憶體，AWS 負責分配運算資源。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>ECS 有兩種 launch type，差別在運算層的管理責任：&lt;/p>
&lt;table>
 &lt;thead>
 &lt;tr>
 &lt;th>Launch type&lt;/th>
 &lt;th>運算層管理&lt;/th>
 &lt;th>適用情境&lt;/th>
 &lt;/tr>
 &lt;/thead>
 &lt;tbody>
 &lt;tr>
 &lt;td>Fargate&lt;/td>
 &lt;td>AWS 代管&lt;/td>
 &lt;td>web API、微服務、批次任務&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>EC2&lt;/td>
 &lt;td>自管 instance&lt;/td>
 &lt;td>GPU workload、高密度排程、成本敏感&lt;/td>
 &lt;/tr>
 &lt;/tbody>
&lt;/table>
&lt;p>Fargate 降低的是運維面（不用管 OS patch、不用管 instance 容量），代價是單位成本較高（同規格約比 EC2 高 20-40%）和啟動延遲（cold start 通常在 30-60 秒，EC2 上的 task 因為 instance 已在所以秒級啟動）。多數 web API 的初始選擇是 Fargate，流量穩定且成本壓力大時再切回 EC2 launch type。&lt;/p>
&lt;h2 id="可觀察訊號">可觀察訊號&lt;/h2>
&lt;p>評估是否從 Fargate 切到 EC2 的訊號是月費曲線。Fargate 按 vCPU-hour 和 memory-hour 計費，task 數量少時費用低、管理簡單。當 task 數量穩定在 10-20 個以上且流量模式可預測時，EC2 launch type 搭配 reserved instance 或 Savings Plans 的成本優勢開始顯著——但要承擔 instance 管理的運維負擔。詳細的成本分析見 &lt;a href="https://tarrragon.github.io/blog/infra/05-core-services/ecs-fargate-cost-optimization/" data-link-title="ECS Fargate 成本分析與優化" data-link-desc="Fargate 的計價模型、與 EC2 launch type 的成本交叉點、Spot 與 Savings Plans 的折扣機制、task 規格的 rightsizing 方法，以及何時該切回 EC2">ECS Fargate 成本分析與優化&lt;/a>。&lt;/p>
&lt;p>Fargate Spot 是介於兩者之間的選項：費用約為 on-demand Fargate 的 30%，但 AWS 可以隨時中斷 task（提前 2 分鐘通知）。適合可容忍中斷的 workload（批次處理、非即時的資料轉換），不適合面對使用者的即時 API。常見的混合策略是用 on-demand Fargate 跑基線流量、Fargate Spot 跑彈性擴張的部分。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>選 Fargate 時要決定三件事：task 的 vCPU / memory 規格（Fargate 的可選組合是固定的，不是任意搭配）、是否混用 Spot、以及 health check 的 grace period（Fargate 的 cold start 比 EC2 長，health check 太早判定失敗會讓 task 反覆重啟）。&lt;/p>
&lt;p>task 規格的 rightsizing 靠 CloudWatch Container Insights 的 CPU / memory utilization 決定——p95 使用率低於 30% 代表規格過大、持續高於 80% 代表該升級。&lt;/p>
&lt;h2 id="鄰卡">鄰卡&lt;/h2>
&lt;ul>
&lt;li>&lt;a href="https://tarrragon.github.io/blog/infra/knowledge-cards/ecs/" data-link-title="ECS" data-link-desc="AWS Elastic Container Service — 受管的容器編排服務，用 task definition 描述容器配置、由平台負責排程與健康管理">ECS&lt;/a> — Fargate 是 ECS 的 launch type 之一&lt;/li>
&lt;li>&lt;a href="https://tarrragon.github.io/blog/infra/knowledge-cards/alb/" data-link-title="ALB" data-link-desc="Application Load Balancer — 流量進入系統的第一站，負責 listener 路由、健康檢查與 TLS 終結">ALB&lt;/a> — Fargate task 通常掛在 ALB 的 target group 後面&lt;/li>
&lt;/ul></description><content:encoded><![CDATA[<p>Fargate 是 AWS <a href="/blog/infra/knowledge-cards/ecs/" data-link-title="ECS" data-link-desc="AWS Elastic Container Service — 受管的容器編排服務，用 task definition 描述容器配置、由平台負責排程與健康管理">ECS</a> 的一種 launch type，把容器的運算實例交給 AWS 代管。使用 Fargate 時不需要配 EC2 instance、不需要管 capacity provider 的 scaling、不需要更新 AMI——只描述 task 需要多少 vCPU 和記憶體，AWS 負責分配運算資源。</p>
<h2 id="概念位置">概念位置</h2>
<p>ECS 有兩種 launch type，差別在運算層的管理責任：</p>
<table>
  <thead>
      <tr>
          <th>Launch type</th>
          <th>運算層管理</th>
          <th>適用情境</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>Fargate</td>
          <td>AWS 代管</td>
          <td>web API、微服務、批次任務</td>
      </tr>
      <tr>
          <td>EC2</td>
          <td>自管 instance</td>
          <td>GPU workload、高密度排程、成本敏感</td>
      </tr>
  </tbody>
</table>
<p>Fargate 降低的是運維面（不用管 OS patch、不用管 instance 容量），代價是單位成本較高（同規格約比 EC2 高 20-40%）和啟動延遲（cold start 通常在 30-60 秒，EC2 上的 task 因為 instance 已在所以秒級啟動）。多數 web API 的初始選擇是 Fargate，流量穩定且成本壓力大時再切回 EC2 launch type。</p>
<h2 id="可觀察訊號">可觀察訊號</h2>
<p>評估是否從 Fargate 切到 EC2 的訊號是月費曲線。Fargate 按 vCPU-hour 和 memory-hour 計費，task 數量少時費用低、管理簡單。當 task 數量穩定在 10-20 個以上且流量模式可預測時，EC2 launch type 搭配 reserved instance 或 Savings Plans 的成本優勢開始顯著——但要承擔 instance 管理的運維負擔。詳細的成本分析見 <a href="/blog/infra/05-core-services/ecs-fargate-cost-optimization/" data-link-title="ECS Fargate 成本分析與優化" data-link-desc="Fargate 的計價模型、與 EC2 launch type 的成本交叉點、Spot 與 Savings Plans 的折扣機制、task 規格的 rightsizing 方法，以及何時該切回 EC2">ECS Fargate 成本分析與優化</a>。</p>
<p>Fargate Spot 是介於兩者之間的選項：費用約為 on-demand Fargate 的 30%，但 AWS 可以隨時中斷 task（提前 2 分鐘通知）。適合可容忍中斷的 workload（批次處理、非即時的資料轉換），不適合面對使用者的即時 API。常見的混合策略是用 on-demand Fargate 跑基線流量、Fargate Spot 跑彈性擴張的部分。</p>
<h2 id="設計責任">設計責任</h2>
<p>選 Fargate 時要決定三件事：task 的 vCPU / memory 規格（Fargate 的可選組合是固定的，不是任意搭配）、是否混用 Spot、以及 health check 的 grace period（Fargate 的 cold start 比 EC2 長，health check 太早判定失敗會讓 task 反覆重啟）。</p>
<p>task 規格的 rightsizing 靠 CloudWatch Container Insights 的 CPU / memory utilization 決定——p95 使用率低於 30% 代表規格過大、持續高於 80% 代表該升級。</p>
<h2 id="鄰卡">鄰卡</h2>
<ul>
<li><a href="/blog/infra/knowledge-cards/ecs/" data-link-title="ECS" data-link-desc="AWS Elastic Container Service — 受管的容器編排服務，用 task definition 描述容器配置、由平台負責排程與健康管理">ECS</a> — Fargate 是 ECS 的 launch type 之一</li>
<li><a href="/blog/infra/knowledge-cards/alb/" data-link-title="ALB" data-link-desc="Application Load Balancer — 流量進入系統的第一站，負責 listener 路由、健康檢查與 TLS 終結">ALB</a> — Fargate task 通常掛在 ALB 的 target group 後面</li>
</ul>
]]></content:encoded></item><item><title>PLG</title><link>https://tarrragon.github.io/blog/business/knowledge-cards/plg/</link><pubDate>Tue, 19 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/business/knowledge-cards/plg/</guid><description>&lt;p>PLG 的核心概念是「Product-Led Growth，產品自助成長」—讓使用者自己註冊、自己上手、自己付費，不靠業務團隊推銷。Slack、Notion、Figma、Zoom 都是經典 PLG。PLG 是 &lt;a href="https://tarrragon.github.io/blog/business/knowledge-cards/gtm/" data-link-title="GTM" data-link-desc="說明進入市場策略的完整含義">GTM&lt;/a> 策略的一種，前提是極低 &lt;a href="https://tarrragon.github.io/blog/business/knowledge-cards/cac/" data-link-title="CAC" data-link-desc="說明獲客成本及其對商業模式可行性的決定作用">CAC&lt;/a> 與接近零 &lt;a href="https://tarrragon.github.io/blog/business/knowledge-cards/marginal-cost/" data-link-title="Marginal Cost" data-link-desc="說明邊際成本及其對商業模式擴張性的決定作用">邊際成本&lt;/a>。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>PLG 跟 Sales-led（業務驅動）相對。PLG 依賴極低的 &lt;a href="https://tarrragon.github.io/blog/business/knowledge-cards/cac/" data-link-title="CAC" data-link-desc="說明獲客成本及其對商業模式可行性的決定作用">CAC&lt;/a>、接近零的 &lt;a href="https://tarrragon.github.io/blog/business/knowledge-cards/marginal-cost/" data-link-title="Marginal Cost" data-link-desc="說明邊際成本及其對商業模式擴張性的決定作用">邊際成本&lt;/a>、產品本身有自帶傳播力（同事看到就會用）。三者中任何一個鬆動，PLG 數學就難跑—這是 AI 時代 PLG 不再萬靈丹的結構原因。&lt;/p>
&lt;h2 id="可觀察訊號與例子">可觀察訊號與例子&lt;/h2>
&lt;p>判斷一個產品走 PLG：免費試用無需信用卡、註冊到啟用只要幾分鐘、定價公開且自助購買、產品內建分享機制（邀請同事、共用文件）。Calendly 的 PLG 經典—被約會的人看到別人用就會自己去註冊，產品本身就是行銷管道。&lt;/p>
&lt;h2 id="判讀方式">判讀方式&lt;/h2>
&lt;p>PLG 的數學前提是「&lt;a href="https://tarrragon.github.io/blog/business/knowledge-cards/gross-margin/" data-link-title="Gross Margin" data-link-desc="說明毛利率與其對商業模式可行性的決定作用">毛利&lt;/a> 夠高 + 邊際成本夠低」—這樣免費使用者也不傷成本，付費轉化能彌補。AI 產品因為推論成本真實存在，免費試用會直接燒錢，PLG 就難跑—這就是為什麼 AI Labs 都在從 PLG 轉向 &lt;a href="https://tarrragon.github.io/blog/business/knowledge-cards/enterprise-license/" data-link-title="Enterprise License" data-link-desc="說明企業級授權的商業模式與鎖定效應">Enterprise License&lt;/a> 與 &lt;a href="https://tarrragon.github.io/blog/business/knowledge-cards/fde/" data-link-title="FDE" data-link-desc="說明前線部署工程師模式的成立條件">FDE&lt;/a>。&lt;/p></description><content:encoded><![CDATA[<p>PLG 的核心概念是「Product-Led Growth，產品自助成長」—讓使用者自己註冊、自己上手、自己付費，不靠業務團隊推銷。Slack、Notion、Figma、Zoom 都是經典 PLG。PLG 是 <a href="/blog/business/knowledge-cards/gtm/" data-link-title="GTM" data-link-desc="說明進入市場策略的完整含義">GTM</a> 策略的一種，前提是極低 <a href="/blog/business/knowledge-cards/cac/" data-link-title="CAC" data-link-desc="說明獲客成本及其對商業模式可行性的決定作用">CAC</a> 與接近零 <a href="/blog/business/knowledge-cards/marginal-cost/" data-link-title="Marginal Cost" data-link-desc="說明邊際成本及其對商業模式擴張性的決定作用">邊際成本</a>。</p>
<h2 id="概念位置">概念位置</h2>
<p>PLG 跟 Sales-led（業務驅動）相對。PLG 依賴極低的 <a href="/blog/business/knowledge-cards/cac/" data-link-title="CAC" data-link-desc="說明獲客成本及其對商業模式可行性的決定作用">CAC</a>、接近零的 <a href="/blog/business/knowledge-cards/marginal-cost/" data-link-title="Marginal Cost" data-link-desc="說明邊際成本及其對商業模式擴張性的決定作用">邊際成本</a>、產品本身有自帶傳播力（同事看到就會用）。三者中任何一個鬆動，PLG 數學就難跑—這是 AI 時代 PLG 不再萬靈丹的結構原因。</p>
<h2 id="可觀察訊號與例子">可觀察訊號與例子</h2>
<p>判斷一個產品走 PLG：免費試用無需信用卡、註冊到啟用只要幾分鐘、定價公開且自助購買、產品內建分享機制（邀請同事、共用文件）。Calendly 的 PLG 經典—被約會的人看到別人用就會自己去註冊，產品本身就是行銷管道。</p>
<h2 id="判讀方式">判讀方式</h2>
<p>PLG 的數學前提是「<a href="/blog/business/knowledge-cards/gross-margin/" data-link-title="Gross Margin" data-link-desc="說明毛利率與其對商業模式可行性的決定作用">毛利</a> 夠高 + 邊際成本夠低」—這樣免費使用者也不傷成本，付費轉化能彌補。AI 產品因為推論成本真實存在，免費試用會直接燒錢，PLG 就難跑—這就是為什麼 AI Labs 都在從 PLG 轉向 <a href="/blog/business/knowledge-cards/enterprise-license/" data-link-title="Enterprise License" data-link-desc="說明企業級授權的商業模式與鎖定效應">Enterprise License</a> 與 <a href="/blog/business/knowledge-cards/fde/" data-link-title="FDE" data-link-desc="說明前線部署工程師模式的成立條件">FDE</a>。</p>
]]></content:encoded></item><item><title>phpMyAdmin</title><link>https://tarrragon.github.io/blog/infra/knowledge-cards/phpmyadmin/</link><pubDate>Fri, 26 Jun 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/infra/knowledge-cards/phpmyadmin/</guid><description>&lt;p>phpMyAdmin 是一套透過瀏覽器操作 MySQL 和 MariaDB 的 Web 應用程式。它提供圖形介面執行 SQL 查詢、瀏覽資料表、匯出與匯入資料庫、修改 schema（新增欄位、改索引、刪表）、以及管理使用者權限。多數主機商在安裝 cPanel 或 Plesk 時會一併預裝，讓租用主機的使用者不需要 SSH 就能管理資料庫。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>在無 SSH 的主機環境裡，phpMyAdmin 通常是唯一可用的資料庫管理入口。它取代了 &lt;code>mysql&lt;/code> CLI client 和 &lt;code>mysqldump&lt;/code> 指令的角色——查詢用 SQL 編輯器、匯出用匯出頁面、匯入用上傳 SQL 檔。接手維運時，phpMyAdmin 是拍下資料庫現況（SQL dump）的主要工具。&lt;/p>
&lt;h2 id="可觀察訊號">可觀察訊號&lt;/h2>
&lt;p>以下情境會遇到 phpMyAdmin：主機面板（cPanel / Plesk）裡有「phpMyAdmin」按鈕可以進入；接手的專案的資料庫操作文件提到「在 phpMyAdmin 裡執行」；或者專案的部署流程包含「登入 phpMyAdmin 匯入 SQL」。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>使用 phpMyAdmin 時要處理三個限制。第一是匯出 timeout：大資料庫（50MB 以上）的匯出可能因為 PHP 的 &lt;code>max_execution_time&lt;/code> 限制而中斷，需要分表匯出或調整 phpMyAdmin 設定。第二是沒有 CLI 可腳本化：所有操作都要手動點擊，無法排程自動備份。第三是安全暴露：phpMyAdmin 掛在 web 上、可被外部存取，如果沒有設密碼保護或 IP 白名單，等於把資料庫管理介面開給全世界。&lt;/p>
&lt;p>如果主機允許遠端 MySQL 連線（port 3306 開放），可以改用桌面工具（DBeaver、TablePlus、HeidiSQL）直連資料庫，繞過 phpMyAdmin 的 timeout 限制。&lt;/p>
&lt;h2 id="鄰卡">鄰卡&lt;/h2>
&lt;ul>
&lt;li>&lt;a href="https://tarrragon.github.io/blog/infra/knowledge-cards/cpanel/" data-link-title="cPanel" data-link-desc="Web 主機管理面板，提供 PHP 版本切換、cron、email、SSL、備份等功能的圖形介面">cPanel&lt;/a>：phpMyAdmin 通常內嵌在 cPanel 裡&lt;/li>
&lt;/ul></description><content:encoded><![CDATA[<p>phpMyAdmin 是一套透過瀏覽器操作 MySQL 和 MariaDB 的 Web 應用程式。它提供圖形介面執行 SQL 查詢、瀏覽資料表、匯出與匯入資料庫、修改 schema（新增欄位、改索引、刪表）、以及管理使用者權限。多數主機商在安裝 cPanel 或 Plesk 時會一併預裝，讓租用主機的使用者不需要 SSH 就能管理資料庫。</p>
<h2 id="概念位置">概念位置</h2>
<p>在無 SSH 的主機環境裡，phpMyAdmin 通常是唯一可用的資料庫管理入口。它取代了 <code>mysql</code> CLI client 和 <code>mysqldump</code> 指令的角色——查詢用 SQL 編輯器、匯出用匯出頁面、匯入用上傳 SQL 檔。接手維運時，phpMyAdmin 是拍下資料庫現況（SQL dump）的主要工具。</p>
<h2 id="可觀察訊號">可觀察訊號</h2>
<p>以下情境會遇到 phpMyAdmin：主機面板（cPanel / Plesk）裡有「phpMyAdmin」按鈕可以進入；接手的專案的資料庫操作文件提到「在 phpMyAdmin 裡執行」；或者專案的部署流程包含「登入 phpMyAdmin 匯入 SQL」。</p>
<h2 id="設計責任">設計責任</h2>
<p>使用 phpMyAdmin 時要處理三個限制。第一是匯出 timeout：大資料庫（50MB 以上）的匯出可能因為 PHP 的 <code>max_execution_time</code> 限制而中斷，需要分表匯出或調整 phpMyAdmin 設定。第二是沒有 CLI 可腳本化：所有操作都要手動點擊，無法排程自動備份。第三是安全暴露：phpMyAdmin 掛在 web 上、可被外部存取，如果沒有設密碼保護或 IP 白名單，等於把資料庫管理介面開給全世界。</p>
<p>如果主機允許遠端 MySQL 連線（port 3306 開放），可以改用桌面工具（DBeaver、TablePlus、HeidiSQL）直連資料庫，繞過 phpMyAdmin 的 timeout 限制。</p>
<h2 id="鄰卡">鄰卡</h2>
<ul>
<li><a href="/blog/infra/knowledge-cards/cpanel/" data-link-title="cPanel" data-link-desc="Web 主機管理面板，提供 PHP 版本切換、cron、email、SSL、備份等功能的圖形介面">cPanel</a>：phpMyAdmin 通常內嵌在 cPanel 裡</li>
</ul>
]]></content:encoded></item><item><title>FDE</title><link>https://tarrragon.github.io/blog/business/knowledge-cards/fde/</link><pubDate>Tue, 19 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/business/knowledge-cards/fde/</guid><description>&lt;p>FDE 的核心概念是「Forward Deployed Engineer，前線部署工程師」—工程師直接派駐到客戶公司，跟客戶一起把產品塞進工作流程，不是賣完軟體就走。Palantir 是 FDE 模式的鼻祖，OpenAI、Anthropic、Google 近年都在大規模採用。FDE 是 &lt;a href="https://tarrragon.github.io/blog/business/knowledge-cards/gtm/" data-link-title="GTM" data-link-desc="說明進入市場策略的完整含義">GTM&lt;/a> 策略的一種，與 &lt;a href="https://tarrragon.github.io/blog/business/knowledge-cards/plg/" data-link-title="PLG" data-link-desc="說明產品自助成長模式與其經濟前提">PLG&lt;/a> 相對。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>FDE 的成立條件是客戶有大量 &lt;a href="https://tarrragon.github.io/blog/business/knowledge-cards/tacit-knowledge/" data-link-title="Tacit Knowledge" data-link-desc="說明隱性知識與其作為護城河的價值">隱性知識&lt;/a> 寫不進 SOP，產品需要現場萃取這些知識才能落地。Palantir 過去獨佔 FDE 模式是因為 &lt;a href="https://tarrragon.github.io/blog/business/knowledge-cards/unit-economics/" data-link-title="Unit Economics" data-link-desc="說明單位經濟模型與其判斷一家公司是否賺錢的責任">unit economics&lt;/a> 算不過來—現在 AI 編程工具改變了這個前提，FDE 可以下沉到中型企業市場。&lt;/p>
&lt;h2 id="可觀察訊號與例子">可觀察訊號與例子&lt;/h2>
&lt;p>FDE 模式的訊號：客戶簽約後工程師長駐客戶辦公室幾週到幾個月、產品高度客製化、合約金額大、續約率極高。Palantir 一個 FDE 一年原本只能服務一兩個大客戶；&lt;a href="https://tarrragon.github.io/blog/business/knowledge-cards/vibe-code/" data-link-title="Vibe Code" data-link-desc="說明用 AI 即時生成程式的開發模式">Vibe Code&lt;/a> 工具把原型開發時間從幾週壓到幾小時後，FDE 產能變成過去三到五倍。&lt;/p>
&lt;h2 id="判讀方式">判讀方式&lt;/h2>
&lt;p>讀到「某家公司轉向 FDE」時，意味著該行業的需求不能靠語言描述清楚—客戶說「我要一個 agent」這句資訊量太低，必須現場跟業務人員一起跑真實案例。FDE 是這波 AI 商業化的 enabler，因為它能把客戶的 &lt;a href="https://tarrragon.github.io/blog/business/knowledge-cards/tacit-knowledge/" data-link-title="Tacit Knowledge" data-link-desc="說明隱性知識與其作為護城河的價值">隱性知識&lt;/a> 編碼進 &lt;a href="https://tarrragon.github.io/blog/business/knowledge-cards/evaluation-set/" data-link-title="Evaluation Set" data-link-desc="說明評估集如何把隱性知識編碼進 AI 產品">evaluation set&lt;/a>。是長期結構還是過渡狀態目前無解。&lt;/p></description><content:encoded><![CDATA[<p>FDE 的核心概念是「Forward Deployed Engineer，前線部署工程師」—工程師直接派駐到客戶公司，跟客戶一起把產品塞進工作流程，不是賣完軟體就走。Palantir 是 FDE 模式的鼻祖，OpenAI、Anthropic、Google 近年都在大規模採用。FDE 是 <a href="/blog/business/knowledge-cards/gtm/" data-link-title="GTM" data-link-desc="說明進入市場策略的完整含義">GTM</a> 策略的一種，與 <a href="/blog/business/knowledge-cards/plg/" data-link-title="PLG" data-link-desc="說明產品自助成長模式與其經濟前提">PLG</a> 相對。</p>
<h2 id="概念位置">概念位置</h2>
<p>FDE 的成立條件是客戶有大量 <a href="/blog/business/knowledge-cards/tacit-knowledge/" data-link-title="Tacit Knowledge" data-link-desc="說明隱性知識與其作為護城河的價值">隱性知識</a> 寫不進 SOP，產品需要現場萃取這些知識才能落地。Palantir 過去獨佔 FDE 模式是因為 <a href="/blog/business/knowledge-cards/unit-economics/" data-link-title="Unit Economics" data-link-desc="說明單位經濟模型與其判斷一家公司是否賺錢的責任">unit economics</a> 算不過來—現在 AI 編程工具改變了這個前提，FDE 可以下沉到中型企業市場。</p>
<h2 id="可觀察訊號與例子">可觀察訊號與例子</h2>
<p>FDE 模式的訊號：客戶簽約後工程師長駐客戶辦公室幾週到幾個月、產品高度客製化、合約金額大、續約率極高。Palantir 一個 FDE 一年原本只能服務一兩個大客戶；<a href="/blog/business/knowledge-cards/vibe-code/" data-link-title="Vibe Code" data-link-desc="說明用 AI 即時生成程式的開發模式">Vibe Code</a> 工具把原型開發時間從幾週壓到幾小時後，FDE 產能變成過去三到五倍。</p>
<h2 id="判讀方式">判讀方式</h2>
<p>讀到「某家公司轉向 FDE」時，意味著該行業的需求不能靠語言描述清楚—客戶說「我要一個 agent」這句資訊量太低，必須現場跟業務人員一起跑真實案例。FDE 是這波 AI 商業化的 enabler，因為它能把客戶的 <a href="/blog/business/knowledge-cards/tacit-knowledge/" data-link-title="Tacit Knowledge" data-link-desc="說明隱性知識與其作為護城河的價值">隱性知識</a> 編碼進 <a href="/blog/business/knowledge-cards/evaluation-set/" data-link-title="Evaluation Set" data-link-desc="說明評估集如何把隱性知識編碼進 AI 產品">evaluation set</a>。是長期結構還是過渡狀態目前無解。</p>
]]></content:encoded></item><item><title>FileZilla</title><link>https://tarrragon.github.io/blog/infra/knowledge-cards/filezilla/</link><pubDate>Fri, 26 Jun 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/infra/knowledge-cards/filezilla/</guid><description>&lt;p>FileZilla 是一套開源的 FTP / SFTP / FTPS client，支援 Windows、macOS 和 Linux。它的介面分成本地和遠端兩側的檔案瀏覽器，讓使用者透過拖放或右鍵選單在本機與伺服器之間傳輸檔案。在無 SSH 的主機環境裡，FileZilla 是上傳程式碼和下載備份的主要工具。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>FTP 是無 SSH 環境裡傳輸檔案的主要協定。FileZilla 把 FTP 操作從 CLI（如 &lt;code>ftp&lt;/code> 或 &lt;code>lftp&lt;/code> 指令）包裝成圖形介面，降低操作門檻。接手維運時，FileZilla 的角色是「把整個站台拉回本地」和「把改好的檔案推上 prod」。&lt;/p>
&lt;h2 id="可觀察訊號">可觀察訊號&lt;/h2>
&lt;p>以下情境會用到 FileZilla：接手的專案只有 FTP 帳密沒有 SSH key；部署方式是「FTP 上傳改過的檔案」；或者需要對比本地版本和伺服器版本的差異。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>使用 FileZilla 時有三個關鍵功能和注意事項。&lt;/p>
&lt;p>&lt;strong>站台管理員&lt;/strong>：儲存多組 FTP 連線設定（主機、帳號、密碼、port），避免每次手動輸入。接手時第一步是在站台管理員建好 prod 的連線，並確認協定選擇正確（FTP 明文、FTPS 加密、SFTP 走 SSH）。&lt;/p>
&lt;p>&lt;strong>目錄比較&lt;/strong>：「檢視 → 目錄比較 → 啟用」功能會標示本地與遠端的檔案差異——哪些本地較新、哪些遠端較新、哪些只存在於一邊。上傳前先跑目錄比較可以看到即將改動的範圍。&lt;/p>
&lt;p>&lt;strong>隱藏檔&lt;/strong>：預設不顯示以 &lt;code>.&lt;/code> 開頭的檔案（如 &lt;code>.htaccess&lt;/code>、&lt;code>.env&lt;/code>、&lt;code>.user.ini&lt;/code>）。要在「伺服器 → 強制顯示隱藏檔案」啟用，否則接手時會漏拉這些關鍵設定檔。&lt;/p>
&lt;p>FTP 傳輸是逐檔覆寫、沒有原子性——上傳到一半斷線會讓伺服器上同時存在新舊版本的混合狀態。對關鍵檔案（&lt;code>index.php&lt;/code>、&lt;code>.htaccess&lt;/code>）的上傳需要額外小心。&lt;/p>
&lt;h2 id="鄰卡">鄰卡&lt;/h2>
&lt;p>無。FileZilla 是獨立工具。替代工具包括 WinSCP（Windows）、Cyberduck（macOS）、Transmit（macOS）。&lt;/p></description><content:encoded><![CDATA[<p>FileZilla 是一套開源的 FTP / SFTP / FTPS client，支援 Windows、macOS 和 Linux。它的介面分成本地和遠端兩側的檔案瀏覽器，讓使用者透過拖放或右鍵選單在本機與伺服器之間傳輸檔案。在無 SSH 的主機環境裡，FileZilla 是上傳程式碼和下載備份的主要工具。</p>
<h2 id="概念位置">概念位置</h2>
<p>FTP 是無 SSH 環境裡傳輸檔案的主要協定。FileZilla 把 FTP 操作從 CLI（如 <code>ftp</code> 或 <code>lftp</code> 指令）包裝成圖形介面，降低操作門檻。接手維運時，FileZilla 的角色是「把整個站台拉回本地」和「把改好的檔案推上 prod」。</p>
<h2 id="可觀察訊號">可觀察訊號</h2>
<p>以下情境會用到 FileZilla：接手的專案只有 FTP 帳密沒有 SSH key；部署方式是「FTP 上傳改過的檔案」；或者需要對比本地版本和伺服器版本的差異。</p>
<h2 id="設計責任">設計責任</h2>
<p>使用 FileZilla 時有三個關鍵功能和注意事項。</p>
<p><strong>站台管理員</strong>：儲存多組 FTP 連線設定（主機、帳號、密碼、port），避免每次手動輸入。接手時第一步是在站台管理員建好 prod 的連線，並確認協定選擇正確（FTP 明文、FTPS 加密、SFTP 走 SSH）。</p>
<p><strong>目錄比較</strong>：「檢視 → 目錄比較 → 啟用」功能會標示本地與遠端的檔案差異——哪些本地較新、哪些遠端較新、哪些只存在於一邊。上傳前先跑目錄比較可以看到即將改動的範圍。</p>
<p><strong>隱藏檔</strong>：預設不顯示以 <code>.</code> 開頭的檔案（如 <code>.htaccess</code>、<code>.env</code>、<code>.user.ini</code>）。要在「伺服器 → 強制顯示隱藏檔案」啟用，否則接手時會漏拉這些關鍵設定檔。</p>
<p>FTP 傳輸是逐檔覆寫、沒有原子性——上傳到一半斷線會讓伺服器上同時存在新舊版本的混合狀態。對關鍵檔案（<code>index.php</code>、<code>.htaccess</code>）的上傳需要額外小心。</p>
<h2 id="鄰卡">鄰卡</h2>
<p>無。FileZilla 是獨立工具。替代工具包括 WinSCP（Windows）、Cyberduck（macOS）、Transmit（macOS）。</p>
]]></content:encoded></item><item><title>JV</title><link>https://tarrragon.github.io/blog/business/knowledge-cards/jv/</link><pubDate>Tue, 19 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/business/knowledge-cards/jv/</guid><description>&lt;p>JV 的核心概念是「Joint Venture，合資企業」—兩家或多家公司一起出資成立新公司或合作專案，共享風險與收益。Anthropic 跟 Blackstone、高盛合資進企業市場，就是 JV 模式。JV 是進入新市場的一種 &lt;a href="https://tarrragon.github.io/blog/business/knowledge-cards/gtm/" data-link-title="GTM" data-link-desc="說明進入市場策略的完整含義">GTM&lt;/a> 結構。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>JV 適用於需要對方的客戶基礎、行業知識或法律授權，但又不想被完全併購的場景。相對於自建（greenfield）或併購（acquisition），JV 共擔風險、共享資源，但決策複雜度高。常跟 &lt;a href="https://tarrragon.github.io/blog/business/knowledge-cards/fde/" data-link-title="FDE" data-link-desc="說明前線部署工程師模式的成立條件">FDE&lt;/a> 一起出現—JV 提供客戶基礎、FDE 提供現場落地能力。&lt;/p>
&lt;h2 id="可觀察訊號與例子">可觀察訊號與例子&lt;/h2>
&lt;p>JV 常見訊號：合作雙方有互補資源（A 有技術、B 有客戶）、新公司有獨立董事會與管理層、股權比例與決策權設計複雜。Anthropic + Blackstone 的 JV—Anthropic 出 AI 技術，Blackstone 出 &lt;a href="https://tarrragon.github.io/blog/business/knowledge-cards/private-equity/" data-link-title="Private Equity (PE)" data-link-desc="說明私募基金與其對中型企業市場的策略意涵">PE&lt;/a> 投資組合公司當客戶基礎。&lt;/p>
&lt;h2 id="判讀方式">判讀方式&lt;/h2>
&lt;p>看到 AI Labs 大規模做 JV，意味著它們判斷單靠自己進企業市場效率太低，需要借力行業既有玩家。這跟 &lt;a href="https://tarrragon.github.io/blog/business/knowledge-cards/fde/" data-link-title="FDE" data-link-desc="說明前線部署工程師模式的成立條件">FDE&lt;/a> 一起出現的訊號是「&lt;a href="https://tarrragon.github.io/blog/business/knowledge-cards/plg/" data-link-title="PLG" data-link-desc="說明產品自助成長模式與其經濟前提">PLG&lt;/a> 模式不適合 AI 進企業」—得用更重、更貼客戶的方式做 &lt;a href="https://tarrragon.github.io/blog/business/knowledge-cards/gtm/" data-link-title="GTM" data-link-desc="說明進入市場策略的完整含義">GTM&lt;/a>。JV 的潛在風險是文化衝突、決策慢、利益分配難算清楚。&lt;/p></description><content:encoded><![CDATA[<p>JV 的核心概念是「Joint Venture，合資企業」—兩家或多家公司一起出資成立新公司或合作專案，共享風險與收益。Anthropic 跟 Blackstone、高盛合資進企業市場，就是 JV 模式。JV 是進入新市場的一種 <a href="/blog/business/knowledge-cards/gtm/" data-link-title="GTM" data-link-desc="說明進入市場策略的完整含義">GTM</a> 結構。</p>
<h2 id="概念位置">概念位置</h2>
<p>JV 適用於需要對方的客戶基礎、行業知識或法律授權，但又不想被完全併購的場景。相對於自建（greenfield）或併購（acquisition），JV 共擔風險、共享資源，但決策複雜度高。常跟 <a href="/blog/business/knowledge-cards/fde/" data-link-title="FDE" data-link-desc="說明前線部署工程師模式的成立條件">FDE</a> 一起出現—JV 提供客戶基礎、FDE 提供現場落地能力。</p>
<h2 id="可觀察訊號與例子">可觀察訊號與例子</h2>
<p>JV 常見訊號：合作雙方有互補資源（A 有技術、B 有客戶）、新公司有獨立董事會與管理層、股權比例與決策權設計複雜。Anthropic + Blackstone 的 JV—Anthropic 出 AI 技術，Blackstone 出 <a href="/blog/business/knowledge-cards/private-equity/" data-link-title="Private Equity (PE)" data-link-desc="說明私募基金與其對中型企業市場的策略意涵">PE</a> 投資組合公司當客戶基礎。</p>
<h2 id="判讀方式">判讀方式</h2>
<p>看到 AI Labs 大規模做 JV，意味著它們判斷單靠自己進企業市場效率太低，需要借力行業既有玩家。這跟 <a href="/blog/business/knowledge-cards/fde/" data-link-title="FDE" data-link-desc="說明前線部署工程師模式的成立條件">FDE</a> 一起出現的訊號是「<a href="/blog/business/knowledge-cards/plg/" data-link-title="PLG" data-link-desc="說明產品自助成長模式與其經濟前提">PLG</a> 模式不適合 AI 進企業」—得用更重、更貼客戶的方式做 <a href="/blog/business/knowledge-cards/gtm/" data-link-title="GTM" data-link-desc="說明進入市場策略的完整含義">GTM</a>。JV 的潛在風險是文化衝突、決策慢、利益分配難算清楚。</p>
]]></content:encoded></item><item><title>cPanel</title><link>https://tarrragon.github.io/blog/infra/knowledge-cards/cpanel/</link><pubDate>Fri, 26 Jun 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/infra/knowledge-cards/cpanel/</guid><description>&lt;p>cPanel 是最常見的 Web 主機管理面板，讓租用主機的使用者透過瀏覽器管理伺服器的常用功能——PHP 版本切換、cron job 排程、email 帳號管理、SSL 憑證安裝、檔案管理、資料庫管理、以及完整備份。Plesk 是同類產品，功能範圍相似但介面和設定路徑不同。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>cPanel 是無 SSH 環境裡的「控制中心」。它整合了多種工具的圖形入口：phpMyAdmin（資料庫）、檔案管理員（web 版 FTP）、PHP 設定、cron 編輯器、SSL/TLS 管理。接手維運時，第一步是確認有沒有 cPanel 存取權——有的話很多操作（備份、PHP 版本、cron）可以在面板裡完成，不需要 SSH。&lt;/p>
&lt;h2 id="可觀察訊號">可觀察訊號&lt;/h2>
&lt;p>以下情境代表環境有 cPanel：主機商提供了 cPanel 登入 URL（通常是 &lt;code>domain:2083&lt;/code>）；接手時收到的帳密包含「cPanel 帳號」；或者主機商的服務說明提到 cPanel / WHM。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>接手維運時，cPanel 有幾個關鍵功能要確認：&lt;/p>
&lt;p>&lt;strong>完整備份&lt;/strong>：「備份精靈」可以一次打包整個帳號（檔案 + 資料庫 + email + cron + DNS 設定）。這是最快的「拍下現況」方式——比 FTP 逐檔拉 + phpMyAdmin 匯出快得多。但完整備份通常只能下載、不能自動排程到外部儲存（部分主機商限制）。&lt;/p>
&lt;p>&lt;strong>PHP 版本選擇器&lt;/strong>：可以切換整個帳號或單一域名的 PHP 版本。升級 PHP 時，可以先在 staging 子域名切到新版本測試、確認沒問題再切主域名。這是無 SSH 環境裡最安全的 PHP 升級方式。&lt;/p>
&lt;p>&lt;strong>cron job 管理&lt;/strong>：圖形介面設定排程任務，語法是 cron 標準格式。接手時要截圖或匯出所有 cron——它們可能是系統運作的隱性依賴（定期清快取、寄報表、同步資料）。&lt;/p>
&lt;p>&lt;strong>SSL/TLS&lt;/strong>：管理 HTTPS 憑證。部分主機商整合了 Let&amp;rsquo;s Encrypt 自動簽發，部分需要手動上傳憑證。&lt;/p>
&lt;h2 id="鄰卡">鄰卡&lt;/h2>
&lt;ul>
&lt;li>&lt;a href="https://tarrragon.github.io/blog/infra/knowledge-cards/phpmyadmin/" data-link-title="phpMyAdmin" data-link-desc="Web 介面的 MySQL / MariaDB 管理工具，透過瀏覽器操作資料庫">phpMyAdmin&lt;/a>：通常內嵌在 cPanel 的「資料庫」區塊裡&lt;/li>
&lt;/ul></description><content:encoded><![CDATA[<p>cPanel 是最常見的 Web 主機管理面板，讓租用主機的使用者透過瀏覽器管理伺服器的常用功能——PHP 版本切換、cron job 排程、email 帳號管理、SSL 憑證安裝、檔案管理、資料庫管理、以及完整備份。Plesk 是同類產品，功能範圍相似但介面和設定路徑不同。</p>
<h2 id="概念位置">概念位置</h2>
<p>cPanel 是無 SSH 環境裡的「控制中心」。它整合了多種工具的圖形入口：phpMyAdmin（資料庫）、檔案管理員（web 版 FTP）、PHP 設定、cron 編輯器、SSL/TLS 管理。接手維運時，第一步是確認有沒有 cPanel 存取權——有的話很多操作（備份、PHP 版本、cron）可以在面板裡完成，不需要 SSH。</p>
<h2 id="可觀察訊號">可觀察訊號</h2>
<p>以下情境代表環境有 cPanel：主機商提供了 cPanel 登入 URL（通常是 <code>domain:2083</code>）；接手時收到的帳密包含「cPanel 帳號」；或者主機商的服務說明提到 cPanel / WHM。</p>
<h2 id="設計責任">設計責任</h2>
<p>接手維運時，cPanel 有幾個關鍵功能要確認：</p>
<p><strong>完整備份</strong>：「備份精靈」可以一次打包整個帳號（檔案 + 資料庫 + email + cron + DNS 設定）。這是最快的「拍下現況」方式——比 FTP 逐檔拉 + phpMyAdmin 匯出快得多。但完整備份通常只能下載、不能自動排程到外部儲存（部分主機商限制）。</p>
<p><strong>PHP 版本選擇器</strong>：可以切換整個帳號或單一域名的 PHP 版本。升級 PHP 時，可以先在 staging 子域名切到新版本測試、確認沒問題再切主域名。這是無 SSH 環境裡最安全的 PHP 升級方式。</p>
<p><strong>cron job 管理</strong>：圖形介面設定排程任務，語法是 cron 標準格式。接手時要截圖或匯出所有 cron——它們可能是系統運作的隱性依賴（定期清快取、寄報表、同步資料）。</p>
<p><strong>SSL/TLS</strong>：管理 HTTPS 憑證。部分主機商整合了 Let&rsquo;s Encrypt 自動簽發，部分需要手動上傳憑證。</p>
<h2 id="鄰卡">鄰卡</h2>
<ul>
<li><a href="/blog/infra/knowledge-cards/phpmyadmin/" data-link-title="phpMyAdmin" data-link-desc="Web 介面的 MySQL / MariaDB 管理工具，透過瀏覽器操作資料庫">phpMyAdmin</a>：通常內嵌在 cPanel 的「資料庫」區塊裡</li>
</ul>
]]></content:encoded></item><item><title>CAC</title><link>https://tarrragon.github.io/blog/business/knowledge-cards/cac/</link><pubDate>Tue, 19 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/business/knowledge-cards/cac/</guid><description>&lt;p>CAC 的核心概念是「Customer Acquisition Cost，獲客成本」—拉一個新客戶進來總共要花多少錢，包括行銷費、業務人力、廣告投放、銷售獎金等所有成本除以新客數。CAC 是 &lt;a href="https://tarrragon.github.io/blog/business/knowledge-cards/unit-economics/" data-link-title="Unit Economics" data-link-desc="說明單位經濟模型與其判斷一家公司是否賺錢的責任">單位經濟&lt;/a> 的核心參數。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>CAC 跟 &lt;a href="https://tarrragon.github.io/blog/business/knowledge-cards/ltv/" data-link-title="LTV" data-link-desc="說明客戶終身價值與其在估值中的作用">LTV&lt;/a> 一起構成 &lt;a href="https://tarrragon.github.io/blog/business/knowledge-cards/unit-economics/" data-link-title="Unit Economics" data-link-desc="說明單位經濟模型與其判斷一家公司是否賺錢的責任">單位經濟&lt;/a> 的兩端。LTV/CAC &amp;gt; 3 通常被視為健康，意思是一個客戶帶來的總收入要至少是獲取成本的三倍。CAC 由 &lt;a href="https://tarrragon.github.io/blog/business/knowledge-cards/gtm/" data-link-title="GTM" data-link-desc="說明進入市場策略的完整含義">GTM&lt;/a> 選擇決定—不同 GTM 對應不同 CAC 量級。&lt;/p>
&lt;h2 id="可觀察訊號與例子">可觀察訊號與例子&lt;/h2>
&lt;p>不同 GTM 的 CAC 差異極大：&lt;a href="https://tarrragon.github.io/blog/business/knowledge-cards/plg/" data-link-title="PLG" data-link-desc="說明產品自助成長模式與其經濟前提">PLG&lt;/a> 的 CAC 可以很低（幾十美金，靠口碑），Sales-led 的 CAC 從幾百到幾千美金，&lt;a href="https://tarrragon.github.io/blog/business/knowledge-cards/enterprise-license/" data-link-title="Enterprise License" data-link-desc="說明企業級授權的商業模式與鎖定效應">Enterprise&lt;/a> / &lt;a href="https://tarrragon.github.io/blog/business/knowledge-cards/fde/" data-link-title="FDE" data-link-desc="說明前線部署工程師模式的成立條件">FDE&lt;/a> 的 CAC 可達幾萬到幾十萬美金（要派工程師駐點）。&lt;/p>
&lt;h2 id="判讀方式">判讀方式&lt;/h2>
&lt;p>讀到「CAC 上升」「PLG 數學算不過來」時，通常指該行業面臨 &lt;a href="https://tarrragon.github.io/blog/business/knowledge-cards/gross-margin/" data-link-title="Gross Margin" data-link-desc="說明毛利率與其對商業模式可行性的決定作用">毛利&lt;/a> 下滑或 LTV 下降，導致原本能撐的 CAC 變成負擔。AI 時代許多新創要把 GTM 從 PLG 改成 Sales-led 或 FDE，意味著 CAC 會大幅上升—這直接擠壓 &lt;a href="https://tarrragon.github.io/blog/business/knowledge-cards/pnl/" data-link-title="P&amp;amp;L" data-link-desc="說明損益表的結構與商業判讀作用">P&amp;amp;L&lt;/a> 與 &lt;a href="https://tarrragon.github.io/blog/business/knowledge-cards/valuation/" data-link-title="Valuation" data-link-desc="說明估值的構成與商業判讀作用">估值&lt;/a>。&lt;/p></description><content:encoded><![CDATA[<p>CAC 的核心概念是「Customer Acquisition Cost，獲客成本」—拉一個新客戶進來總共要花多少錢，包括行銷費、業務人力、廣告投放、銷售獎金等所有成本除以新客數。CAC 是 <a href="/blog/business/knowledge-cards/unit-economics/" data-link-title="Unit Economics" data-link-desc="說明單位經濟模型與其判斷一家公司是否賺錢的責任">單位經濟</a> 的核心參數。</p>
<h2 id="概念位置">概念位置</h2>
<p>CAC 跟 <a href="/blog/business/knowledge-cards/ltv/" data-link-title="LTV" data-link-desc="說明客戶終身價值與其在估值中的作用">LTV</a> 一起構成 <a href="/blog/business/knowledge-cards/unit-economics/" data-link-title="Unit Economics" data-link-desc="說明單位經濟模型與其判斷一家公司是否賺錢的責任">單位經濟</a> 的兩端。LTV/CAC &gt; 3 通常被視為健康，意思是一個客戶帶來的總收入要至少是獲取成本的三倍。CAC 由 <a href="/blog/business/knowledge-cards/gtm/" data-link-title="GTM" data-link-desc="說明進入市場策略的完整含義">GTM</a> 選擇決定—不同 GTM 對應不同 CAC 量級。</p>
<h2 id="可觀察訊號與例子">可觀察訊號與例子</h2>
<p>不同 GTM 的 CAC 差異極大：<a href="/blog/business/knowledge-cards/plg/" data-link-title="PLG" data-link-desc="說明產品自助成長模式與其經濟前提">PLG</a> 的 CAC 可以很低（幾十美金，靠口碑），Sales-led 的 CAC 從幾百到幾千美金，<a href="/blog/business/knowledge-cards/enterprise-license/" data-link-title="Enterprise License" data-link-desc="說明企業級授權的商業模式與鎖定效應">Enterprise</a> / <a href="/blog/business/knowledge-cards/fde/" data-link-title="FDE" data-link-desc="說明前線部署工程師模式的成立條件">FDE</a> 的 CAC 可達幾萬到幾十萬美金（要派工程師駐點）。</p>
<h2 id="判讀方式">判讀方式</h2>
<p>讀到「CAC 上升」「PLG 數學算不過來」時，通常指該行業面臨 <a href="/blog/business/knowledge-cards/gross-margin/" data-link-title="Gross Margin" data-link-desc="說明毛利率與其對商業模式可行性的決定作用">毛利</a> 下滑或 LTV 下降，導致原本能撐的 CAC 變成負擔。AI 時代許多新創要把 GTM 從 PLG 改成 Sales-led 或 FDE，意味著 CAC 會大幅上升—這直接擠壓 <a href="/blog/business/knowledge-cards/pnl/" data-link-title="P&amp;L" data-link-desc="說明損益表的結構與商業判讀作用">P&amp;L</a> 與 <a href="/blog/business/knowledge-cards/valuation/" data-link-title="Valuation" data-link-desc="說明估值的構成與商業判讀作用">估值</a>。</p>
]]></content:encoded></item><item><title>.htaccess</title><link>https://tarrragon.github.io/blog/infra/knowledge-cards/htaccess/</link><pubDate>Fri, 26 Jun 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/infra/knowledge-cards/htaccess/</guid><description>&lt;p>&lt;code>.htaccess&lt;/code>（Hypertext Access）是 Apache Web Server 的目錄層級設定檔。它讓使用者在沒有伺服器管理員權限的情況下，覆寫 Apache 的部分全域設定——包括 URL 重寫規則、目錄存取控制、PHP 設定覆寫、HTTPS 強制跳轉、以及 HTTP 安全標頭。每個目錄可以有自己的 &lt;code>.htaccess&lt;/code>，Apache 處理請求時會從根目錄到目標目錄逐層讀取並套用。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>在 Apache 為主的主機環境（多數共享主機和部分 VPS），&lt;code>.htaccess&lt;/code> 是不需要重啟伺服器就能調整行為的設定機制。WordPress、Laravel、Drupal 等 PHP 框架都依賴 &lt;code>.htaccess&lt;/code> 的 URL rewrite 規則來實現 pretty URL（把 &lt;code>/blog/post-title&lt;/code> 轉成 &lt;code>index.php?page=post-title&lt;/code>）。&lt;/p>
&lt;h2 id="可觀察訊號">可觀察訊號&lt;/h2>
&lt;p>站台根目錄有 &lt;code>.htaccess&lt;/code> 檔案（注意它是隱藏檔，FTP client 要啟用「顯示隱藏檔案」才看得到）。上傳目錄（&lt;code>uploads/&lt;/code>）、後台目錄（&lt;code>admin/&lt;/code>、&lt;code>wp-admin/&lt;/code>）可能各有一份獨立的 &lt;code>.htaccess&lt;/code> 做額外的存取控制。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>接手維運時，&lt;code>.htaccess&lt;/code> 要注意四件事：&lt;/p>
&lt;p>&lt;strong>URL rewrite 規則&lt;/strong>：這些規則決定了站台的 URL 結構。亂改或刪除會讓所有內頁都回 404。修改前先備份原始版本。&lt;/p>
&lt;p>&lt;strong>安全設定&lt;/strong>：&lt;code>Options -Indexes&lt;/code> 禁止目錄列表、&lt;code>php_flag engine off&lt;/code> 禁止上傳目錄執行 PHP、&lt;code>Require all denied&lt;/code> 禁止存取 &lt;code>.env&lt;/code> 等機密檔案。這些設定分散在多個目錄的 &lt;code>.htaccess&lt;/code> 裡，接手時要全部找出來。&lt;/p>
&lt;p>&lt;strong>PHP 設定覆寫&lt;/strong>：部分 PHP 設定（如 &lt;code>upload_max_filesize&lt;/code>、&lt;code>max_execution_time&lt;/code>）可以在 &lt;code>.htaccess&lt;/code> 裡用 &lt;code>php_value&lt;/code> 或 &lt;code>php_flag&lt;/code> 指令覆寫。這些覆寫可能不在 &lt;code>php.ini&lt;/code> 裡，只存在於 &lt;code>.htaccess&lt;/code>。&lt;/p>
&lt;p>&lt;strong>遷移到 nginx 的影響&lt;/strong>：nginx 沒有 &lt;code>.htaccess&lt;/code> 的對等機制——所有設定都在集中的 nginx 設定檔裡。從 Apache 遷移到 nginx 時，&lt;code>.htaccess&lt;/code> 裡的每一條規則都要手動轉換成 nginx 語法。&lt;/p>
&lt;h2 id="鄰卡">鄰卡&lt;/h2>
&lt;ul>
&lt;li>&lt;a href="https://tarrragon.github.io/blog/infra/knowledge-cards/php-ini/" data-link-title="php.ini / .user.ini" data-link-desc="PHP 的執行期設定檔，控制記憶體上限、上傳大小、錯誤報告等 runtime 行為">php.ini / .user.ini&lt;/a>：&lt;code>.htaccess&lt;/code> 管 Apache 行為，&lt;code>.user.ini&lt;/code> 管 PHP 行為，兩者互補&lt;/li>
&lt;/ul></description><content:encoded><![CDATA[<p><code>.htaccess</code>（Hypertext Access）是 Apache Web Server 的目錄層級設定檔。它讓使用者在沒有伺服器管理員權限的情況下，覆寫 Apache 的部分全域設定——包括 URL 重寫規則、目錄存取控制、PHP 設定覆寫、HTTPS 強制跳轉、以及 HTTP 安全標頭。每個目錄可以有自己的 <code>.htaccess</code>，Apache 處理請求時會從根目錄到目標目錄逐層讀取並套用。</p>
<h2 id="概念位置">概念位置</h2>
<p>在 Apache 為主的主機環境（多數共享主機和部分 VPS），<code>.htaccess</code> 是不需要重啟伺服器就能調整行為的設定機制。WordPress、Laravel、Drupal 等 PHP 框架都依賴 <code>.htaccess</code> 的 URL rewrite 規則來實現 pretty URL（把 <code>/blog/post-title</code> 轉成 <code>index.php?page=post-title</code>）。</p>
<h2 id="可觀察訊號">可觀察訊號</h2>
<p>站台根目錄有 <code>.htaccess</code> 檔案（注意它是隱藏檔，FTP client 要啟用「顯示隱藏檔案」才看得到）。上傳目錄（<code>uploads/</code>）、後台目錄（<code>admin/</code>、<code>wp-admin/</code>）可能各有一份獨立的 <code>.htaccess</code> 做額外的存取控制。</p>
<h2 id="設計責任">設計責任</h2>
<p>接手維運時，<code>.htaccess</code> 要注意四件事：</p>
<p><strong>URL rewrite 規則</strong>：這些規則決定了站台的 URL 結構。亂改或刪除會讓所有內頁都回 404。修改前先備份原始版本。</p>
<p><strong>安全設定</strong>：<code>Options -Indexes</code> 禁止目錄列表、<code>php_flag engine off</code> 禁止上傳目錄執行 PHP、<code>Require all denied</code> 禁止存取 <code>.env</code> 等機密檔案。這些設定分散在多個目錄的 <code>.htaccess</code> 裡，接手時要全部找出來。</p>
<p><strong>PHP 設定覆寫</strong>：部分 PHP 設定（如 <code>upload_max_filesize</code>、<code>max_execution_time</code>）可以在 <code>.htaccess</code> 裡用 <code>php_value</code> 或 <code>php_flag</code> 指令覆寫。這些覆寫可能不在 <code>php.ini</code> 裡，只存在於 <code>.htaccess</code>。</p>
<p><strong>遷移到 nginx 的影響</strong>：nginx 沒有 <code>.htaccess</code> 的對等機制——所有設定都在集中的 nginx 設定檔裡。從 Apache 遷移到 nginx 時，<code>.htaccess</code> 裡的每一條規則都要手動轉換成 nginx 語法。</p>
<h2 id="鄰卡">鄰卡</h2>
<ul>
<li><a href="/blog/infra/knowledge-cards/php-ini/" data-link-title="php.ini / .user.ini" data-link-desc="PHP 的執行期設定檔，控制記憶體上限、上傳大小、錯誤報告等 runtime 行為">php.ini / .user.ini</a>：<code>.htaccess</code> 管 Apache 行為，<code>.user.ini</code> 管 PHP 行為，兩者互補</li>
</ul>
]]></content:encoded></item><item><title>.env</title><link>https://tarrragon.github.io/blog/infra/knowledge-cards/dotenv/</link><pubDate>Fri, 26 Jun 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/infra/knowledge-cards/dotenv/</guid><description>&lt;p>&lt;code>.env&lt;/code> 是一個純文字檔案，每行一組 &lt;code>KEY=VALUE&lt;/code> 的環境變數定義。它的用途是把機密值（資料庫密碼、API key、SMTP 憑證）和環境專屬設定（資料庫 host、debug 模式開關）從程式碼分離出來，讓同一份程式碼在不同環境（開發、staging、production）用不同的設定值，而且機密值不進版本控制。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>&lt;code>.env&lt;/code> 是跨語言的設定分離慣例。PHP 用 &lt;code>vlucas/phpdotenv&lt;/code> 套件讀取、Node.js 用 &lt;code>dotenv&lt;/code> 套件、Python 用 &lt;code>python-dotenv&lt;/code>、Go 用 &lt;code>godotenv&lt;/code>。這些套件的行為相同：程式啟動時讀 &lt;code>.env&lt;/code> 檔案，把裡面的變數載入到執行環境的環境變數裡，讓程式碼用 &lt;code>$_ENV['KEY']&lt;/code>（PHP）或 &lt;code>process.env.KEY&lt;/code>（Node）存取。&lt;/p>
&lt;h2 id="可觀察訊號">可觀察訊號&lt;/h2>
&lt;p>站台根目錄有 &lt;code>.env&lt;/code> 或 &lt;code>.env.production&lt;/code> 檔案；&lt;code>.gitignore&lt;/code> 裡有 &lt;code>.env&lt;/code> 這一行；repo 裡有 &lt;code>.env.example&lt;/code> 或 &lt;code>.env.sample&lt;/code> 列出所有需要的變數但不填實際值。如果接手的專案沒有 &lt;code>.env&lt;/code> 但 &lt;code>config.php&lt;/code> 裡直接寫了資料庫密碼，代表設定分離還沒做——這是接手後應該處理的事。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>使用 &lt;code>.env&lt;/code> 時有三個紀律：&lt;/p>
&lt;p>&lt;strong>不進 Git&lt;/strong>：&lt;code>.env&lt;/code> 包含明文密碼，進了 Git 就跟著每一次 clone、fork、CI 快取擴散。&lt;code>.gitignore&lt;/code> 必須排除 &lt;code>.env&lt;/code>。如果 &lt;code>.env&lt;/code> 已經在 Git 歷史裡，刪掉那一行不夠——密碼留在 history 裡，要輪替所有外洩的密碼。&lt;/p>
&lt;p>&lt;strong>範本檔進 Git&lt;/strong>：repo 裡放一份 &lt;code>.env.example&lt;/code>，列出所有必要的環境變數但不填實際值。新接手的人複製 &lt;code>.env.example&lt;/code> 成 &lt;code>.env&lt;/code>，再填入自己環境的值。&lt;/p>
&lt;p>&lt;strong>不用 &lt;code>.env&lt;/code> 管非機密設定&lt;/strong>：應用程式的功能開關、UI 設定、feature flag 不屬於 &lt;code>.env&lt;/code>——這些設定沒有機密性、應該進版本控制。&lt;code>.env&lt;/code> 只放「換一個環境就要改的值」和「不能被看到的值」。&lt;/p>
&lt;h2 id="鄰卡">鄰卡&lt;/h2>
&lt;ul>
&lt;li>&lt;a href="https://tarrragon.github.io/blog/infra/knowledge-cards/php-ini/" data-link-title="php.ini / .user.ini" data-link-desc="PHP 的執行期設定檔，控制記憶體上限、上傳大小、錯誤報告等 runtime 行為">php.ini / .user.ini&lt;/a>：&lt;code>.env&lt;/code> 管應用程式設定、php.ini 管 PHP runtime 設定&lt;/li>
&lt;/ul></description><content:encoded><![CDATA[<p><code>.env</code> 是一個純文字檔案，每行一組 <code>KEY=VALUE</code> 的環境變數定義。它的用途是把機密值（資料庫密碼、API key、SMTP 憑證）和環境專屬設定（資料庫 host、debug 模式開關）從程式碼分離出來，讓同一份程式碼在不同環境（開發、staging、production）用不同的設定值，而且機密值不進版本控制。</p>
<h2 id="概念位置">概念位置</h2>
<p><code>.env</code> 是跨語言的設定分離慣例。PHP 用 <code>vlucas/phpdotenv</code> 套件讀取、Node.js 用 <code>dotenv</code> 套件、Python 用 <code>python-dotenv</code>、Go 用 <code>godotenv</code>。這些套件的行為相同：程式啟動時讀 <code>.env</code> 檔案，把裡面的變數載入到執行環境的環境變數裡，讓程式碼用 <code>$_ENV['KEY']</code>（PHP）或 <code>process.env.KEY</code>（Node）存取。</p>
<h2 id="可觀察訊號">可觀察訊號</h2>
<p>站台根目錄有 <code>.env</code> 或 <code>.env.production</code> 檔案；<code>.gitignore</code> 裡有 <code>.env</code> 這一行；repo 裡有 <code>.env.example</code> 或 <code>.env.sample</code> 列出所有需要的變數但不填實際值。如果接手的專案沒有 <code>.env</code> 但 <code>config.php</code> 裡直接寫了資料庫密碼，代表設定分離還沒做——這是接手後應該處理的事。</p>
<h2 id="設計責任">設計責任</h2>
<p>使用 <code>.env</code> 時有三個紀律：</p>
<p><strong>不進 Git</strong>：<code>.env</code> 包含明文密碼，進了 Git 就跟著每一次 clone、fork、CI 快取擴散。<code>.gitignore</code> 必須排除 <code>.env</code>。如果 <code>.env</code> 已經在 Git 歷史裡，刪掉那一行不夠——密碼留在 history 裡，要輪替所有外洩的密碼。</p>
<p><strong>範本檔進 Git</strong>：repo 裡放一份 <code>.env.example</code>，列出所有必要的環境變數但不填實際值。新接手的人複製 <code>.env.example</code> 成 <code>.env</code>，再填入自己環境的值。</p>
<p><strong>不用 <code>.env</code> 管非機密設定</strong>：應用程式的功能開關、UI 設定、feature flag 不屬於 <code>.env</code>——這些設定沒有機密性、應該進版本控制。<code>.env</code> 只放「換一個環境就要改的值」和「不能被看到的值」。</p>
<h2 id="鄰卡">鄰卡</h2>
<ul>
<li><a href="/blog/infra/knowledge-cards/php-ini/" data-link-title="php.ini / .user.ini" data-link-desc="PHP 的執行期設定檔，控制記憶體上限、上傳大小、錯誤報告等 runtime 行為">php.ini / .user.ini</a>：<code>.env</code> 管應用程式設定、php.ini 管 PHP runtime 設定</li>
</ul>
]]></content:encoded></item><item><title>php.ini / .user.ini</title><link>https://tarrragon.github.io/blog/infra/knowledge-cards/php-ini/</link><pubDate>Fri, 26 Jun 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/infra/knowledge-cards/php-ini/</guid><description>&lt;p>&lt;code>php.ini&lt;/code> 是 PHP 的全域設定檔，控制 PHP 的 runtime 行為——記憶體上限、檔案上傳大小、最大執行時間、錯誤報告層級、時區、session 處理方式。&lt;code>.user.ini&lt;/code> 是 PHP 5.3 之後支援的目錄層級覆寫機制，放在站台目錄裡可以覆寫部分 &lt;code>php.ini&lt;/code> 的設定，不需要伺服器管理員權限。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>&lt;code>php.ini&lt;/code> 由伺服器管理員管理，租用主機的使用者通常不能直接修改。&lt;code>.user.ini&lt;/code> 是使用者層級的設定覆寫——功能上類似 &lt;code>.htaccess&lt;/code> 對 Apache 的角色，但只管 PHP 設定。在 cPanel 環境裡，部分設定也可以透過「PHP 選擇器」的圖形介面調整。&lt;/p>
&lt;h2 id="可觀察訊號">可觀察訊號&lt;/h2>
&lt;p>PHP 行為異常時要檢查的第一個地方。常見的情境：上傳檔案失敗（&lt;code>upload_max_filesize&lt;/code> 太小）、長時間運算被中斷（&lt;code>max_execution_time&lt;/code> 太短）、記憶體不足錯誤（&lt;code>memory_limit&lt;/code> 太低）、看不到錯誤訊息（&lt;code>display_errors&lt;/code> 關閉）。用 &lt;code>phpinfo()&lt;/code> 可以看到每一項設定的目前值和來源（&lt;code>php.ini&lt;/code> / &lt;code>.user.ini&lt;/code> / &lt;code>.htaccess&lt;/code>）。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>接手維運時要知道的關鍵設定：&lt;/p>
&lt;table>
 &lt;thead>
 &lt;tr>
 &lt;th>設定&lt;/th>
 &lt;th>作用&lt;/th>
 &lt;th>常見預設值&lt;/th>
 &lt;th>接手時要確認的事&lt;/th>
 &lt;/tr>
 &lt;/thead>
 &lt;tbody>
 &lt;tr>
 &lt;td>&lt;code>memory_limit&lt;/code>&lt;/td>
 &lt;td>PHP 程式的記憶體上限&lt;/td>
 &lt;td>128M&lt;/td>
 &lt;td>大型操作（匯出、圖片處理）是否夠用&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;code>upload_max_filesize&lt;/code>&lt;/td>
 &lt;td>單檔上傳大小上限&lt;/td>
 &lt;td>2M&lt;/td>
 &lt;td>是否符合業務需求&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;code>post_max_size&lt;/code>&lt;/td>
 &lt;td>POST 請求的總大小上限&lt;/td>
 &lt;td>8M&lt;/td>
 &lt;td>要大於 upload_max_filesize&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;code>max_execution_time&lt;/code>&lt;/td>
 &lt;td>PHP 腳本最大執行秒數&lt;/td>
 &lt;td>30&lt;/td>
 &lt;td>長時間操作（備份、匯入）是否需要加長&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;code>error_reporting&lt;/code>&lt;/td>
 &lt;td>顯示哪些層級的錯誤&lt;/td>
 &lt;td>E_ALL&lt;/td>
 &lt;td>開發時開到 E_ALL、production 時關 display_errors&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;code>display_errors&lt;/code>&lt;/td>
 &lt;td>是否在頁面上顯示錯誤&lt;/td>
 &lt;td>Off&lt;/td>
 &lt;td>production 應該關閉（錯誤寫 log 不顯示給使用者）&lt;/td>
 &lt;/tr>
 &lt;/tbody>
&lt;/table>
&lt;p>&lt;code>.user.ini&lt;/code> 的修改不需要重啟 Apache/nginx，但有快取時間（預設 300 秒）——改完後要等最多 5 分鐘才生效。&lt;code>php.ini&lt;/code> 的修改在多數環境需要重啟 web server。&lt;/p>
&lt;h2 id="鄰卡">鄰卡&lt;/h2>
&lt;ul>
&lt;li>&lt;a href="https://tarrragon.github.io/blog/infra/knowledge-cards/htaccess/" data-link-title=".htaccess" data-link-desc="Apache Web Server 的目錄層級設定檔，控制 URL rewrite、存取權限、PHP 設定覆寫與安全標頭">.htaccess&lt;/a>：&lt;code>.htaccess&lt;/code> 管 Apache 行為（URL rewrite、存取控制），&lt;code>.user.ini&lt;/code> 管 PHP 行為（記憶體、執行時間），兩者互補&lt;/li>
&lt;li>&lt;a href="https://tarrragon.github.io/blog/infra/knowledge-cards/dotenv/" data-link-title=".env" data-link-desc="存放環境變數的純文字檔案，把機密值從程式碼分離出來">.env&lt;/a>：&lt;code>.env&lt;/code> 管應用程式設定（DB 密碼、API key），&lt;code>php.ini&lt;/code> 管 PHP runtime 設定（記憶體、上傳大小）&lt;/li>
&lt;/ul></description><content:encoded><![CDATA[<p><code>php.ini</code> 是 PHP 的全域設定檔，控制 PHP 的 runtime 行為——記憶體上限、檔案上傳大小、最大執行時間、錯誤報告層級、時區、session 處理方式。<code>.user.ini</code> 是 PHP 5.3 之後支援的目錄層級覆寫機制，放在站台目錄裡可以覆寫部分 <code>php.ini</code> 的設定，不需要伺服器管理員權限。</p>
<h2 id="概念位置">概念位置</h2>
<p><code>php.ini</code> 由伺服器管理員管理，租用主機的使用者通常不能直接修改。<code>.user.ini</code> 是使用者層級的設定覆寫——功能上類似 <code>.htaccess</code> 對 Apache 的角色，但只管 PHP 設定。在 cPanel 環境裡，部分設定也可以透過「PHP 選擇器」的圖形介面調整。</p>
<h2 id="可觀察訊號">可觀察訊號</h2>
<p>PHP 行為異常時要檢查的第一個地方。常見的情境：上傳檔案失敗（<code>upload_max_filesize</code> 太小）、長時間運算被中斷（<code>max_execution_time</code> 太短）、記憶體不足錯誤（<code>memory_limit</code> 太低）、看不到錯誤訊息（<code>display_errors</code> 關閉）。用 <code>phpinfo()</code> 可以看到每一項設定的目前值和來源（<code>php.ini</code> / <code>.user.ini</code> / <code>.htaccess</code>）。</p>
<h2 id="設計責任">設計責任</h2>
<p>接手維運時要知道的關鍵設定：</p>
<table>
  <thead>
      <tr>
          <th>設定</th>
          <th>作用</th>
          <th>常見預設值</th>
          <th>接手時要確認的事</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td><code>memory_limit</code></td>
          <td>PHP 程式的記憶體上限</td>
          <td>128M</td>
          <td>大型操作（匯出、圖片處理）是否夠用</td>
      </tr>
      <tr>
          <td><code>upload_max_filesize</code></td>
          <td>單檔上傳大小上限</td>
          <td>2M</td>
          <td>是否符合業務需求</td>
      </tr>
      <tr>
          <td><code>post_max_size</code></td>
          <td>POST 請求的總大小上限</td>
          <td>8M</td>
          <td>要大於 upload_max_filesize</td>
      </tr>
      <tr>
          <td><code>max_execution_time</code></td>
          <td>PHP 腳本最大執行秒數</td>
          <td>30</td>
          <td>長時間操作（備份、匯入）是否需要加長</td>
      </tr>
      <tr>
          <td><code>error_reporting</code></td>
          <td>顯示哪些層級的錯誤</td>
          <td>E_ALL</td>
          <td>開發時開到 E_ALL、production 時關 display_errors</td>
      </tr>
      <tr>
          <td><code>display_errors</code></td>
          <td>是否在頁面上顯示錯誤</td>
          <td>Off</td>
          <td>production 應該關閉（錯誤寫 log 不顯示給使用者）</td>
      </tr>
  </tbody>
</table>
<p><code>.user.ini</code> 的修改不需要重啟 Apache/nginx，但有快取時間（預設 300 秒）——改完後要等最多 5 分鐘才生效。<code>php.ini</code> 的修改在多數環境需要重啟 web server。</p>
<h2 id="鄰卡">鄰卡</h2>
<ul>
<li><a href="/blog/infra/knowledge-cards/htaccess/" data-link-title=".htaccess" data-link-desc="Apache Web Server 的目錄層級設定檔，控制 URL rewrite、存取權限、PHP 設定覆寫與安全標頭">.htaccess</a>：<code>.htaccess</code> 管 Apache 行為（URL rewrite、存取控制），<code>.user.ini</code> 管 PHP 行為（記憶體、執行時間），兩者互補</li>
<li><a href="/blog/infra/knowledge-cards/dotenv/" data-link-title=".env" data-link-desc="存放環境變數的純文字檔案，把機密值從程式碼分離出來">.env</a>：<code>.env</code> 管應用程式設定（DB 密碼、API key），<code>php.ini</code> 管 PHP runtime 設定（記憶體、上傳大小）</li>
</ul>
]]></content:encoded></item><item><title>DNS</title><link>https://tarrragon.github.io/blog/infra/knowledge-cards/dns/</link><pubDate>Fri, 26 Jun 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/infra/knowledge-cards/dns/</guid><description>&lt;p>DNS（Domain Name System）是把人類可讀的域名（&lt;code>example.com&lt;/code>）轉成機器可達的 IP 位址（&lt;code>93.184.216.34&lt;/code>）的分散式查詢系統。瀏覽器輸入網址後，作業系統先查本地快取、再逐層查詢 DNS server，最終拿到 IP 才能建立連線。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>DNS 在 infra 裡扮演「服務的門牌」角色。平台遷移、環境切換、TLS 憑證驗證都經過 DNS。ALB 或 CDN 前面通常掛一層 DNS record 作為穩定入口——IP 會隨資源重建而變，DNS 名稱不變。&lt;/p>
&lt;h2 id="常見的記錄類型">常見的記錄類型&lt;/h2>
&lt;table>
 &lt;thead>
 &lt;tr>
 &lt;th>類型&lt;/th>
 &lt;th>指向什麼&lt;/th>
 &lt;th>典型用途&lt;/th>
 &lt;/tr>
 &lt;/thead>
 &lt;tbody>
 &lt;tr>
 &lt;td>A&lt;/td>
 &lt;td>IPv4 位址&lt;/td>
 &lt;td>主要的域名 → IP 對應&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>AAAA&lt;/td>
 &lt;td>IPv6 位址&lt;/td>
 &lt;td>IPv6 環境&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>CNAME&lt;/td>
 &lt;td>另一個域名&lt;/td>
 &lt;td>別名（&lt;code>www&lt;/code> → &lt;code>example.com&lt;/code>）&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>NS&lt;/td>
 &lt;td>負責管理的 DNS server&lt;/td>
 &lt;td>子域委派（dev.example.com）&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>MX&lt;/td>
 &lt;td>郵件伺服器&lt;/td>
 &lt;td>email routing&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>TXT&lt;/td>
 &lt;td>任意文字&lt;/td>
 &lt;td>SPF / DKIM / 域名驗證（ACM）&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>Alias&lt;/td>
 &lt;td>AWS 特有，指向 ALB 等&lt;/td>
 &lt;td>跟 A record 等效但支援 zone apex&lt;/td>
 &lt;/tr>
 &lt;/tbody>
&lt;/table>
&lt;h2 id="可觀察訊號">可觀察訊號&lt;/h2>
&lt;p>平台遷移時 DNS 切換是最後一步也是最不可控的一步——TTL（Time To Live）決定舊記錄被各地 DNS resolver 快取多久。TTL 300 秒代表切換後最多 5 分鐘全部 client 會指向新 IP；TTL 86400（1 天）代表最慢要等一天。遷移前 48 小時先降 TTL 到 300 秒，讓快取過期後所有 resolver 都拿到短 TTL 版本，切換時才能快速生效。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>DNS 設定要決定：誰管這個域名的 zone（Route 53 / Cloudflare / 域名商）、子域怎麼委派（dev / staging 用 NS delegation 交給不同 zone）、TTL 設多少（平常 3600 秒夠用、遷移前降到 300）。ACM 的 DNS 驗證也依賴 DNS——建立 TXT 或 CNAME 記錄證明域名歸屬。&lt;/p>
&lt;h2 id="鄰卡">鄰卡&lt;/h2>
&lt;ul>
&lt;li>&lt;a href="https://tarrragon.github.io/blog/infra/knowledge-cards/alb/" data-link-title="ALB" data-link-desc="Application Load Balancer — 流量進入系統的第一站，負責 listener 路由、健康檢查與 TLS 終結">ALB&lt;/a> — DNS 記錄通常指向 ALB 作為流量入口&lt;/li>
&lt;li>&lt;a href="https://tarrragon.github.io/blog/infra/knowledge-cards/ssl-tls/" data-link-title="SSL / TLS" data-link-desc="加密 client 與 server 之間通訊的協定，讓 HTTPS 成為可能。TLS 是 SSL 的後繼者，但 SSL 憑證的稱呼仍廣泛使用">SSL/TLS&lt;/a> — TLS 憑證的 DNS 驗證依賴 DNS record&lt;/li>
&lt;/ul></description><content:encoded><![CDATA[<p>DNS（Domain Name System）是把人類可讀的域名（<code>example.com</code>）轉成機器可達的 IP 位址（<code>93.184.216.34</code>）的分散式查詢系統。瀏覽器輸入網址後，作業系統先查本地快取、再逐層查詢 DNS server，最終拿到 IP 才能建立連線。</p>
<h2 id="概念位置">概念位置</h2>
<p>DNS 在 infra 裡扮演「服務的門牌」角色。平台遷移、環境切換、TLS 憑證驗證都經過 DNS。ALB 或 CDN 前面通常掛一層 DNS record 作為穩定入口——IP 會隨資源重建而變，DNS 名稱不變。</p>
<h2 id="常見的記錄類型">常見的記錄類型</h2>
<table>
  <thead>
      <tr>
          <th>類型</th>
          <th>指向什麼</th>
          <th>典型用途</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>A</td>
          <td>IPv4 位址</td>
          <td>主要的域名 → IP 對應</td>
      </tr>
      <tr>
          <td>AAAA</td>
          <td>IPv6 位址</td>
          <td>IPv6 環境</td>
      </tr>
      <tr>
          <td>CNAME</td>
          <td>另一個域名</td>
          <td>別名（<code>www</code> → <code>example.com</code>）</td>
      </tr>
      <tr>
          <td>NS</td>
          <td>負責管理的 DNS server</td>
          <td>子域委派（dev.example.com）</td>
      </tr>
      <tr>
          <td>MX</td>
          <td>郵件伺服器</td>
          <td>email routing</td>
      </tr>
      <tr>
          <td>TXT</td>
          <td>任意文字</td>
          <td>SPF / DKIM / 域名驗證（ACM）</td>
      </tr>
      <tr>
          <td>Alias</td>
          <td>AWS 特有，指向 ALB 等</td>
          <td>跟 A record 等效但支援 zone apex</td>
      </tr>
  </tbody>
</table>
<h2 id="可觀察訊號">可觀察訊號</h2>
<p>平台遷移時 DNS 切換是最後一步也是最不可控的一步——TTL（Time To Live）決定舊記錄被各地 DNS resolver 快取多久。TTL 300 秒代表切換後最多 5 分鐘全部 client 會指向新 IP；TTL 86400（1 天）代表最慢要等一天。遷移前 48 小時先降 TTL 到 300 秒，讓快取過期後所有 resolver 都拿到短 TTL 版本，切換時才能快速生效。</p>
<h2 id="設計責任">設計責任</h2>
<p>DNS 設定要決定：誰管這個域名的 zone（Route 53 / Cloudflare / 域名商）、子域怎麼委派（dev / staging 用 NS delegation 交給不同 zone）、TTL 設多少（平常 3600 秒夠用、遷移前降到 300）。ACM 的 DNS 驗證也依賴 DNS——建立 TXT 或 CNAME 記錄證明域名歸屬。</p>
<h2 id="鄰卡">鄰卡</h2>
<ul>
<li><a href="/blog/infra/knowledge-cards/alb/" data-link-title="ALB" data-link-desc="Application Load Balancer — 流量進入系統的第一站，負責 listener 路由、健康檢查與 TLS 終結">ALB</a> — DNS 記錄通常指向 ALB 作為流量入口</li>
<li><a href="/blog/infra/knowledge-cards/ssl-tls/" data-link-title="SSL / TLS" data-link-desc="加密 client 與 server 之間通訊的協定，讓 HTTPS 成為可能。TLS 是 SSL 的後繼者，但 SSL 憑證的稱呼仍廣泛使用">SSL/TLS</a> — TLS 憑證的 DNS 驗證依賴 DNS record</li>
</ul>
]]></content:encoded></item><item><title>SSL / TLS</title><link>https://tarrragon.github.io/blog/infra/knowledge-cards/ssl-tls/</link><pubDate>Fri, 26 Jun 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/infra/knowledge-cards/ssl-tls/</guid><description>&lt;p>TLS（Transport Layer Security）加密 client 與 server 之間的通訊，防止中間人竊聽或竄改。HTTPS 就是 HTTP 加上 TLS 加密層。SSL 是 TLS 的前身、所有版本都已被棄用，但「SSL 憑證」這個稱呼仍然廣泛使用——實際上指的是 TLS 憑證。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>TLS 在 infra 裡負責「傳輸安全」。ALB 的 HTTPS listener 需要掛一張 TLS 憑證；ACM（AWS Certificate Manager）提供免費的憑證申請與自動續期；Let&amp;rsquo;s Encrypt 是跨平台的免費 CA（Certificate Authority，憑證簽發機構）。&lt;/p>
&lt;h2 id="可觀察訊號">可觀察訊號&lt;/h2>
&lt;p>TLS 憑證有到期日。過期的憑證會讓瀏覽器顯示安全警告、部分 client 直接拒絕連線。ACM 管理的憑證會自動續期（前提是 DNS 驗證記錄仍然存在）；手動上傳的憑證需要人工追蹤到期日。接手維運時要確認：憑證的簽發者是誰、到期日是什麼時候、續期是自動還是手動。&lt;/p>
&lt;p>用 CLI 查看遠端憑證資訊：&lt;/p>





&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-bash" data-lang="bash">&lt;span class="line">&lt;span class="ln">1&lt;/span>&lt;span class="cl">&lt;span class="nb">echo&lt;/span> &lt;span class="p">|&lt;/span> openssl s_client -connect example.com:443 2&amp;gt;/dev/null &lt;span class="p">|&lt;/span> openssl x509 -noout -dates -issuer&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>TLS 設定要決定：憑證從哪裡來（ACM 免費但只能用在 AWS 服務上、Let&amp;rsquo;s Encrypt 免費且跨平台）、驗證方式（DNS 驗證適合自動化、email 驗證較手動）、是否需要多域名的 SAN 憑證（一張憑證涵蓋 &lt;code>example.com&lt;/code> + &lt;code>*.example.com&lt;/code>）、HTTP → HTTPS 的強制跳轉怎麼設。&lt;/p>
&lt;h2 id="鄰卡">鄰卡&lt;/h2>
&lt;ul>
&lt;li>&lt;a href="https://tarrragon.github.io/blog/infra/knowledge-cards/dns/" data-link-title="DNS" data-link-desc="Domain Name System — 把域名轉成 IP 位址的系統，以及 A record、CNAME、NS、TTL 的角色">DNS&lt;/a> — TLS 憑證的 DNS 驗證依賴 DNS record&lt;/li>
&lt;li>&lt;a href="https://tarrragon.github.io/blog/infra/knowledge-cards/alb/" data-link-title="ALB" data-link-desc="Application Load Balancer — 流量進入系統的第一站，負責 listener 路由、健康檢查與 TLS 終結">ALB&lt;/a> — HTTPS listener 需要掛 TLS 憑證&lt;/li>
&lt;/ul></description><content:encoded><![CDATA[<p>TLS（Transport Layer Security）加密 client 與 server 之間的通訊，防止中間人竊聽或竄改。HTTPS 就是 HTTP 加上 TLS 加密層。SSL 是 TLS 的前身、所有版本都已被棄用，但「SSL 憑證」這個稱呼仍然廣泛使用——實際上指的是 TLS 憑證。</p>
<h2 id="概念位置">概念位置</h2>
<p>TLS 在 infra 裡負責「傳輸安全」。ALB 的 HTTPS listener 需要掛一張 TLS 憑證；ACM（AWS Certificate Manager）提供免費的憑證申請與自動續期；Let&rsquo;s Encrypt 是跨平台的免費 CA（Certificate Authority，憑證簽發機構）。</p>
<h2 id="可觀察訊號">可觀察訊號</h2>
<p>TLS 憑證有到期日。過期的憑證會讓瀏覽器顯示安全警告、部分 client 直接拒絕連線。ACM 管理的憑證會自動續期（前提是 DNS 驗證記錄仍然存在）；手動上傳的憑證需要人工追蹤到期日。接手維運時要確認：憑證的簽發者是誰、到期日是什麼時候、續期是自動還是手動。</p>
<p>用 CLI 查看遠端憑證資訊：</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="ln">1</span><span class="cl"><span class="nb">echo</span> <span class="p">|</span> openssl s_client -connect example.com:443 2&gt;/dev/null <span class="p">|</span> openssl x509 -noout -dates -issuer</span></span></code></pre></div><h2 id="設計責任">設計責任</h2>
<p>TLS 設定要決定：憑證從哪裡來（ACM 免費但只能用在 AWS 服務上、Let&rsquo;s Encrypt 免費且跨平台）、驗證方式（DNS 驗證適合自動化、email 驗證較手動）、是否需要多域名的 SAN 憑證（一張憑證涵蓋 <code>example.com</code> + <code>*.example.com</code>）、HTTP → HTTPS 的強制跳轉怎麼設。</p>
<h2 id="鄰卡">鄰卡</h2>
<ul>
<li><a href="/blog/infra/knowledge-cards/dns/" data-link-title="DNS" data-link-desc="Domain Name System — 把域名轉成 IP 位址的系統，以及 A record、CNAME、NS、TTL 的角色">DNS</a> — TLS 憑證的 DNS 驗證依賴 DNS record</li>
<li><a href="/blog/infra/knowledge-cards/alb/" data-link-title="ALB" data-link-desc="Application Load Balancer — 流量進入系統的第一站，負責 listener 路由、健康檢查與 TLS 終結">ALB</a> — HTTPS listener 需要掛 TLS 憑證</li>
</ul>
]]></content:encoded></item><item><title>SSH</title><link>https://tarrragon.github.io/blog/infra/knowledge-cards/ssh/</link><pubDate>Fri, 26 Jun 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/infra/knowledge-cards/ssh/</guid><description>&lt;p>SSH（Secure Shell）是加密的遠端 shell 連線協定，讓操作者在本地終端機執行遠端伺服器上的指令。連線建立後，操作者看到的是遠端伺服器的命令列——可以跑任何該伺服器上安裝的 CLI 工具。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>SSH 在接手維運的情境裡是一條關鍵分界線：有 SSH 存取就能用 &lt;code>mysqldump&lt;/code>、&lt;code>git&lt;/code>、&lt;code>systemctl&lt;/code> 等 CLI 工具操作伺服器；沒有 SSH 就只能用 FTP 傳檔案、用 phpMyAdmin 管資料庫、用 cPanel 改設定。兩種情境的操作流程和可用工具完全不同。&lt;/p>
&lt;h2 id="可觀察訊號">可觀察訊號&lt;/h2>
&lt;p>判斷有沒有 SSH 存取：嘗試 &lt;code>ssh user@host&lt;/code>。如果連線成功進入命令列就有；如果 timeout 或被拒，可能是主機不開放 SSH（共享主機常見）、或 port 不是預設的 22、或需要 IP 白名單。cPanel 的「終端機」功能有時提供 web-based SSH，但功能受限。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>SSH 的認證方式有兩種：密碼（簡單但不安全，容易被暴力嘗試）和 SSH key pair（公鑰放在 server 的 &lt;code>~/.ssh/authorized_keys&lt;/code>，私鑰留在 client）。生產環境應該用 key 認證並關閉密碼登入。&lt;/p>
&lt;p>接手維運時要確認：SSH 的登入帳號是什麼、用密碼還是 key、key 在哪裡、有沒有其他人也有存取權限。前任維護者的 SSH key 如果還在 &lt;code>authorized_keys&lt;/code> 裡，離職後應該移除。&lt;/p>





&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-bash" data-lang="bash">&lt;span class="line">&lt;span class="ln">1&lt;/span>&lt;span class="cl">&lt;span class="c1"># 產生 SSH key pair&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">2&lt;/span>&lt;span class="cl">ssh-keygen -t ed25519 -C &lt;span class="s2">&amp;#34;your-email@example.com&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">3&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">4&lt;/span>&lt;span class="cl">&lt;span class="c1"># 把公鑰加到遠端 server&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">5&lt;/span>&lt;span class="cl">ssh-copy-id -i ~/.ssh/id_ed25519.pub user@host&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h2 id="鄰卡">鄰卡&lt;/h2>
&lt;ul>
&lt;li>&lt;a href="https://tarrragon.github.io/blog/infra/knowledge-cards/ftp/" data-link-title="FTP" data-link-desc="File Transfer Protocol — 檔案傳輸協定，無 SSH 環境的主要檔案管理方式。SFTP 和 FTPS 是其加密變體">FTP&lt;/a> — 沒有 SSH 時的檔案傳輸替代方案&lt;/li>
&lt;/ul></description><content:encoded><![CDATA[<p>SSH（Secure Shell）是加密的遠端 shell 連線協定，讓操作者在本地終端機執行遠端伺服器上的指令。連線建立後，操作者看到的是遠端伺服器的命令列——可以跑任何該伺服器上安裝的 CLI 工具。</p>
<h2 id="概念位置">概念位置</h2>
<p>SSH 在接手維運的情境裡是一條關鍵分界線：有 SSH 存取就能用 <code>mysqldump</code>、<code>git</code>、<code>systemctl</code> 等 CLI 工具操作伺服器；沒有 SSH 就只能用 FTP 傳檔案、用 phpMyAdmin 管資料庫、用 cPanel 改設定。兩種情境的操作流程和可用工具完全不同。</p>
<h2 id="可觀察訊號">可觀察訊號</h2>
<p>判斷有沒有 SSH 存取：嘗試 <code>ssh user@host</code>。如果連線成功進入命令列就有；如果 timeout 或被拒，可能是主機不開放 SSH（共享主機常見）、或 port 不是預設的 22、或需要 IP 白名單。cPanel 的「終端機」功能有時提供 web-based SSH，但功能受限。</p>
<h2 id="設計責任">設計責任</h2>
<p>SSH 的認證方式有兩種：密碼（簡單但不安全，容易被暴力嘗試）和 SSH key pair（公鑰放在 server 的 <code>~/.ssh/authorized_keys</code>，私鑰留在 client）。生產環境應該用 key 認證並關閉密碼登入。</p>
<p>接手維運時要確認：SSH 的登入帳號是什麼、用密碼還是 key、key 在哪裡、有沒有其他人也有存取權限。前任維護者的 SSH key 如果還在 <code>authorized_keys</code> 裡，離職後應該移除。</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="ln">1</span><span class="cl"><span class="c1"># 產生 SSH key pair</span>
</span></span><span class="line"><span class="ln">2</span><span class="cl">ssh-keygen -t ed25519 -C <span class="s2">&#34;your-email@example.com&#34;</span>
</span></span><span class="line"><span class="ln">3</span><span class="cl">
</span></span><span class="line"><span class="ln">4</span><span class="cl"><span class="c1"># 把公鑰加到遠端 server</span>
</span></span><span class="line"><span class="ln">5</span><span class="cl">ssh-copy-id -i ~/.ssh/id_ed25519.pub user@host</span></span></code></pre></div><h2 id="鄰卡">鄰卡</h2>
<ul>
<li><a href="/blog/infra/knowledge-cards/ftp/" data-link-title="FTP" data-link-desc="File Transfer Protocol — 檔案傳輸協定，無 SSH 環境的主要檔案管理方式。SFTP 和 FTPS 是其加密變體">FTP</a> — 沒有 SSH 時的檔案傳輸替代方案</li>
</ul>
]]></content:encoded></item><item><title>Lock-in</title><link>https://tarrragon.github.io/blog/business/knowledge-cards/lock-in/</link><pubDate>Tue, 19 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/business/knowledge-cards/lock-in/</guid><description>&lt;p>Lock-in 的核心概念是「客戶離不開的結構」—使用某個產品越久越難換掉，因為資料、流程、權限、整合、習慣都綁定在上面。Salesforce、SAP、Oracle 都是 lock-in 大師。Lock-in 是 &lt;a href="https://tarrragon.github.io/blog/business/knowledge-cards/switching-cost/" data-link-title="Switching Cost" data-link-desc="說明切換成本如何鞏固客戶留存">護城河&lt;/a> 的核心機制。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>Lock-in 跟 &lt;a href="https://tarrragon.github.io/blog/business/knowledge-cards/switching-cost/" data-link-title="Switching Cost" data-link-desc="說明切換成本如何鞏固客戶留存">Switching Cost&lt;/a> 是一體兩面—lock-in 是結構，switching cost 是讓客戶面臨換掉時的痛點。強 lock-in 帶來高 &lt;a href="https://tarrragon.github.io/blog/business/knowledge-cards/retention/" data-link-title="Retention" data-link-desc="說明客戶留存率與其對單位經濟的決定作用">retention&lt;/a> 與高 &lt;a href="https://tarrragon.github.io/blog/business/knowledge-cards/valuation/" data-link-title="Valuation" data-link-desc="說明估值的構成與商業判讀作用">估值&lt;/a>。&lt;a href="https://tarrragon.github.io/blog/business/knowledge-cards/enterprise-license/" data-link-title="Enterprise License" data-link-desc="說明企業級授權的商業模式與鎖定效應">Enterprise License&lt;/a> 是 lock-in 的高階形式。&lt;/p>
&lt;h2 id="可觀察訊號與例子">可觀察訊號與例子&lt;/h2>
&lt;p>判讀 lock-in 強度，看四個維度：客戶的核心資料是否儲存在你這（資料 lock-in）、客戶的多個系統是否依賴你做整合中樞（整合 lock-in）、客戶的員工訓練是否花費巨大（操作 lock-in）、客戶的客製化邏輯是否難以遷移（流程 lock-in）。四個維度的綜合決定強度。&lt;/p>
&lt;h2 id="判讀方式">判讀方式&lt;/h2>
&lt;p>讀到「lock-in 是 AI Labs 真正想要的」時，意味著它們不滿足於 API 計費，而要把 AI 接進企業的文件、系統、流程，讓企業無法輕易換掉。這也是為什麼從賣 token 轉向賣 &lt;a href="https://tarrragon.github.io/blog/business/knowledge-cards/enterprise-license/" data-link-title="Enterprise License" data-link-desc="說明企業級授權的商業模式與鎖定效應">Enterprise License&lt;/a>—後者的 lock-in 強度高得多，能撐起更穩定的營收與更高的估值。&lt;/p></description><content:encoded><![CDATA[<p>Lock-in 的核心概念是「客戶離不開的結構」—使用某個產品越久越難換掉，因為資料、流程、權限、整合、習慣都綁定在上面。Salesforce、SAP、Oracle 都是 lock-in 大師。Lock-in 是 <a href="/blog/business/knowledge-cards/switching-cost/" data-link-title="Switching Cost" data-link-desc="說明切換成本如何鞏固客戶留存">護城河</a> 的核心機制。</p>
<h2 id="概念位置">概念位置</h2>
<p>Lock-in 跟 <a href="/blog/business/knowledge-cards/switching-cost/" data-link-title="Switching Cost" data-link-desc="說明切換成本如何鞏固客戶留存">Switching Cost</a> 是一體兩面—lock-in 是結構，switching cost 是讓客戶面臨換掉時的痛點。強 lock-in 帶來高 <a href="/blog/business/knowledge-cards/retention/" data-link-title="Retention" data-link-desc="說明客戶留存率與其對單位經濟的決定作用">retention</a> 與高 <a href="/blog/business/knowledge-cards/valuation/" data-link-title="Valuation" data-link-desc="說明估值的構成與商業判讀作用">估值</a>。<a href="/blog/business/knowledge-cards/enterprise-license/" data-link-title="Enterprise License" data-link-desc="說明企業級授權的商業模式與鎖定效應">Enterprise License</a> 是 lock-in 的高階形式。</p>
<h2 id="可觀察訊號與例子">可觀察訊號與例子</h2>
<p>判讀 lock-in 強度，看四個維度：客戶的核心資料是否儲存在你這（資料 lock-in）、客戶的多個系統是否依賴你做整合中樞（整合 lock-in）、客戶的員工訓練是否花費巨大（操作 lock-in）、客戶的客製化邏輯是否難以遷移（流程 lock-in）。四個維度的綜合決定強度。</p>
<h2 id="判讀方式">判讀方式</h2>
<p>讀到「lock-in 是 AI Labs 真正想要的」時，意味著它們不滿足於 API 計費，而要把 AI 接進企業的文件、系統、流程，讓企業無法輕易換掉。這也是為什麼從賣 token 轉向賣 <a href="/blog/business/knowledge-cards/enterprise-license/" data-link-title="Enterprise License" data-link-desc="說明企業級授權的商業模式與鎖定效應">Enterprise License</a>—後者的 lock-in 強度高得多，能撐起更穩定的營收與更高的估值。</p>
]]></content:encoded></item><item><title>FTP</title><link>https://tarrragon.github.io/blog/infra/knowledge-cards/ftp/</link><pubDate>Fri, 26 Jun 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/infra/knowledge-cards/ftp/</guid><description>&lt;p>FTP（File Transfer Protocol）是把檔案在本地電腦與遠端伺服器之間上傳/下載的協定。操作者透過 FTP client（如 FileZilla）連線到伺服器，看到遠端的目錄結構，用拖放或指令傳輸檔案。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>FTP 在無 SSH 的環境裡是唯一的檔案管理途徑——程式碼部署靠 FTP 上傳、備份靠 FTP 下載、檔案比對靠 FTP client 的目錄比較功能。它是接手維運模組「無 SSH 環境」路線的核心工具。&lt;/p>
&lt;h2 id="ftp-的變體">FTP 的變體&lt;/h2>
&lt;table>
 &lt;thead>
 &lt;tr>
 &lt;th>協定&lt;/th>
 &lt;th>加密方式&lt;/th>
 &lt;th>常見情境&lt;/th>
 &lt;/tr>
 &lt;/thead>
 &lt;tbody>
 &lt;tr>
 &lt;td>FTP&lt;/td>
 &lt;td>無加密（明文傳輸）&lt;/td>
 &lt;td>老舊主機、內部網路&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>FTPS&lt;/td>
 &lt;td>FTP + TLS 加密&lt;/td>
 &lt;td>支援 SSL 的主機&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>SFTP&lt;/td>
 &lt;td>走 SSH 通道（完全不同協定）&lt;/td>
 &lt;td>有 SSH 存取的伺服器&lt;/td>
 &lt;/tr>
 &lt;/tbody>
&lt;/table>
&lt;p>多數 FTP client（FileZilla、WinSCP）同時支援三種協定。如果伺服器有 SSH，用 SFTP 比 FTP 安全且功能更多。&lt;/p>
&lt;h2 id="可觀察訊號">可觀察訊號&lt;/h2>
&lt;p>FTP 操作的三個限制在接手維運時要意識到：第一，非原子操作——檔案逐一上傳，上傳過程中伺服器上同時存在新舊版本的混合狀態。第二，不支援指令執行——只能傳檔案、不能跑腳本或重啟服務。第三，沒有版本控制——上傳覆蓋就是覆蓋，沒有 diff、沒有 rollback。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>用 FTP 部署時要建立的紀律：本地先 Git commit 再上傳（Git 提供版本控制、FTP 只負責傳輸）；上傳前用目錄比較確認差異；關鍵檔案（&lt;code>index.php&lt;/code>、&lt;code>.htaccess&lt;/code>）上傳前先從 server 下載一份備份。&lt;/p>
&lt;h2 id="鄰卡">鄰卡&lt;/h2>
&lt;ul>
&lt;li>&lt;a href="https://tarrragon.github.io/blog/infra/knowledge-cards/ssh/" data-link-title="SSH" data-link-desc="Secure Shell — 加密的遠端 shell 連線，有 SSH 等於有 CLI 工具鏈，沒有就只能靠 FTP 和 web 面板">SSH&lt;/a> — 有 SSH 時用 SFTP 或 SCP 替代 FTP&lt;/li>
&lt;li>&lt;a href="https://tarrragon.github.io/blog/infra/knowledge-cards/filezilla/" data-link-title="FileZilla" data-link-desc="跨平台的 FTP/SFTP client，提供目錄同步瀏覽和檔案比較功能">FileZilla&lt;/a> — 最常用的 FTP client&lt;/li>
&lt;/ul></description><content:encoded><![CDATA[<p>FTP（File Transfer Protocol）是把檔案在本地電腦與遠端伺服器之間上傳/下載的協定。操作者透過 FTP client（如 FileZilla）連線到伺服器，看到遠端的目錄結構，用拖放或指令傳輸檔案。</p>
<h2 id="概念位置">概念位置</h2>
<p>FTP 在無 SSH 的環境裡是唯一的檔案管理途徑——程式碼部署靠 FTP 上傳、備份靠 FTP 下載、檔案比對靠 FTP client 的目錄比較功能。它是接手維運模組「無 SSH 環境」路線的核心工具。</p>
<h2 id="ftp-的變體">FTP 的變體</h2>
<table>
  <thead>
      <tr>
          <th>協定</th>
          <th>加密方式</th>
          <th>常見情境</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>FTP</td>
          <td>無加密（明文傳輸）</td>
          <td>老舊主機、內部網路</td>
      </tr>
      <tr>
          <td>FTPS</td>
          <td>FTP + TLS 加密</td>
          <td>支援 SSL 的主機</td>
      </tr>
      <tr>
          <td>SFTP</td>
          <td>走 SSH 通道（完全不同協定）</td>
          <td>有 SSH 存取的伺服器</td>
      </tr>
  </tbody>
</table>
<p>多數 FTP client（FileZilla、WinSCP）同時支援三種協定。如果伺服器有 SSH，用 SFTP 比 FTP 安全且功能更多。</p>
<h2 id="可觀察訊號">可觀察訊號</h2>
<p>FTP 操作的三個限制在接手維運時要意識到：第一，非原子操作——檔案逐一上傳，上傳過程中伺服器上同時存在新舊版本的混合狀態。第二，不支援指令執行——只能傳檔案、不能跑腳本或重啟服務。第三，沒有版本控制——上傳覆蓋就是覆蓋，沒有 diff、沒有 rollback。</p>
<h2 id="設計責任">設計責任</h2>
<p>用 FTP 部署時要建立的紀律：本地先 Git commit 再上傳（Git 提供版本控制、FTP 只負責傳輸）；上傳前用目錄比較確認差異；關鍵檔案（<code>index.php</code>、<code>.htaccess</code>）上傳前先從 server 下載一份備份。</p>
<h2 id="鄰卡">鄰卡</h2>
<ul>
<li><a href="/blog/infra/knowledge-cards/ssh/" data-link-title="SSH" data-link-desc="Secure Shell — 加密的遠端 shell 連線，有 SSH 等於有 CLI 工具鏈，沒有就只能靠 FTP 和 web 面板">SSH</a> — 有 SSH 時用 SFTP 或 SCP 替代 FTP</li>
<li><a href="/blog/infra/knowledge-cards/filezilla/" data-link-title="FileZilla" data-link-desc="跨平台的 FTP/SFTP client，提供目錄同步瀏覽和檔案比較功能">FileZilla</a> — 最常用的 FTP client</li>
</ul>
]]></content:encoded></item><item><title>Switching Cost</title><link>https://tarrragon.github.io/blog/business/knowledge-cards/switching-cost/</link><pubDate>Tue, 19 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/business/knowledge-cards/switching-cost/</guid><description>&lt;p>Switching Cost 的核心概念是「換到競爭對手的總成本」—包括資料搬遷、系統整合、員工再訓練、流程重設計、舊系統停用的風險。Switching cost 越高，客戶越不會走。它是 &lt;a href="https://tarrragon.github.io/blog/business/knowledge-cards/lock-in/" data-link-title="Lock-in" data-link-desc="說明鎖定效應如何形成護城河">Lock-in&lt;/a> 的可量化面向。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>Switching Cost 跟 &lt;a href="https://tarrragon.github.io/blog/business/knowledge-cards/lock-in/" data-link-title="Lock-in" data-link-desc="說明鎖定效應如何形成護城河">Lock-in&lt;/a> 互為表裡，也是 &lt;a href="https://tarrragon.github.io/blog/business/knowledge-cards/retention/" data-link-title="Retention" data-link-desc="說明客戶留存率與其對單位經濟的決定作用">Retention&lt;/a> 的結構性原因。它不只是金錢成本，還包括時間成本、風險成本與機會成本—換錯了可能整個業務癱瘓。對賣方來說，主動設計切換成本是長期策略；對買方來說，避免被高切換成本綁定是採購紀律。&lt;/p>
&lt;h2 id="可觀察訊號與例子">可觀察訊號與例子&lt;/h2>
&lt;p>判讀 switching cost 高低：搬資料要幾週還是幾分鐘？員工再訓練要幾天還是幾個月？舊系統能保留多久當保險？這些都是訊號。SAP 的 switching cost 是業界傳奇—多數公司換 ERP 要花兩三年，多數老闆寧願忍下去也不敢換。&lt;/p>
&lt;h2 id="判讀方式">判讀方式&lt;/h2>
&lt;p>當分析師說「AI 模型之間的 switching cost 下降」時，意味著模型 API 規格越來越標準化、prompt 也可以稍微改一改就跨模型用，客戶換成本變低。這對 AI Labs 是壞消息—它們必須靠 &lt;a href="https://tarrragon.github.io/blog/business/knowledge-cards/lock-in/" data-link-title="Lock-in" data-link-desc="說明鎖定效應如何形成護城河">Lock-in&lt;/a> 的其他維度（資料整合、企業合約、權限管理）來補回 switching cost，這就是為什麼要做 &lt;a href="https://tarrragon.github.io/blog/business/knowledge-cards/enterprise-license/" data-link-title="Enterprise License" data-link-desc="說明企業級授權的商業模式與鎖定效應">Enterprise License&lt;/a>。&lt;/p></description><content:encoded><![CDATA[<p>Switching Cost 的核心概念是「換到競爭對手的總成本」—包括資料搬遷、系統整合、員工再訓練、流程重設計、舊系統停用的風險。Switching cost 越高，客戶越不會走。它是 <a href="/blog/business/knowledge-cards/lock-in/" data-link-title="Lock-in" data-link-desc="說明鎖定效應如何形成護城河">Lock-in</a> 的可量化面向。</p>
<h2 id="概念位置">概念位置</h2>
<p>Switching Cost 跟 <a href="/blog/business/knowledge-cards/lock-in/" data-link-title="Lock-in" data-link-desc="說明鎖定效應如何形成護城河">Lock-in</a> 互為表裡，也是 <a href="/blog/business/knowledge-cards/retention/" data-link-title="Retention" data-link-desc="說明客戶留存率與其對單位經濟的決定作用">Retention</a> 的結構性原因。它不只是金錢成本，還包括時間成本、風險成本與機會成本—換錯了可能整個業務癱瘓。對賣方來說，主動設計切換成本是長期策略；對買方來說，避免被高切換成本綁定是採購紀律。</p>
<h2 id="可觀察訊號與例子">可觀察訊號與例子</h2>
<p>判讀 switching cost 高低：搬資料要幾週還是幾分鐘？員工再訓練要幾天還是幾個月？舊系統能保留多久當保險？這些都是訊號。SAP 的 switching cost 是業界傳奇—多數公司換 ERP 要花兩三年，多數老闆寧願忍下去也不敢換。</p>
<h2 id="判讀方式">判讀方式</h2>
<p>當分析師說「AI 模型之間的 switching cost 下降」時，意味著模型 API 規格越來越標準化、prompt 也可以稍微改一改就跨模型用，客戶換成本變低。這對 AI Labs 是壞消息—它們必須靠 <a href="/blog/business/knowledge-cards/lock-in/" data-link-title="Lock-in" data-link-desc="說明鎖定效應如何形成護城河">Lock-in</a> 的其他維度（資料整合、企業合約、權限管理）來補回 switching cost，這就是為什麼要做 <a href="/blog/business/knowledge-cards/enterprise-license/" data-link-title="Enterprise License" data-link-desc="說明企業級授權的商業模式與鎖定效應">Enterprise License</a>。</p>
]]></content:encoded></item><item><title>cron</title><link>https://tarrragon.github.io/blog/infra/knowledge-cards/cron/</link><pubDate>Fri, 26 Jun 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/infra/knowledge-cards/cron/</guid><description>&lt;p>cron 是 Unix/Linux 系統內建的排程工作管理器，按預定的時間表自動執行指令。一個 cron job 定義「什麼時間跑什麼指令」，系統背景的 cron daemon 負責到時間就執行。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>cron 在接手維運時是容易被忽略的隱藏工作——它不像 web 服務有明顯的入口，但可能負責資料庫備份、快取清除、報表產出、日誌清理等關鍵任務。漏掉一個 cron job 可能讓備份停止、快取永不過期、報表不再更新，而且不會立刻有人發現。&lt;/p>
&lt;h2 id="crontab-格式">crontab 格式&lt;/h2>





&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-text" data-lang="text">&lt;span class="line">&lt;span class="ln">1&lt;/span>&lt;span class="cl"># 分 時 日 月 週 指令
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">2&lt;/span>&lt;span class="cl">0 3 * * * /usr/bin/php /var/www/backup.php
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">3&lt;/span>&lt;span class="cl">*/5 * * * * /usr/bin/curl -s https://example.com/cron/heartbeat
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">4&lt;/span>&lt;span class="cl">0 0 1 * * /usr/bin/find /tmp -mtime +7 -delete&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>五個時間欄位依序是分鐘（0-59）、小時（0-23）、日（1-31）、月（1-12）、星期幾（0-7，0 和 7 都是星期日）。&lt;code>*&lt;/code> 代表「每一個」，&lt;code>*/5&lt;/code> 代表「每 5 個」。&lt;/p>
&lt;h2 id="可觀察訊號">可觀察訊號&lt;/h2>
&lt;p>接手維運時盤點 cron job：&lt;/p>





&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-bash" data-lang="bash">&lt;span class="line">&lt;span class="ln"> 1&lt;/span>&lt;span class="cl">&lt;span class="c1"># 當前使用者的 crontab&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 2&lt;/span>&lt;span class="cl">crontab -l
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 3&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 4&lt;/span>&lt;span class="cl">&lt;span class="c1"># 所有使用者的 crontab（需要 root）&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 5&lt;/span>&lt;span class="cl">&lt;span class="k">for&lt;/span> user in &lt;span class="k">$(&lt;/span>cut -f1 -d: /etc/passwd&lt;span class="k">)&lt;/span>&lt;span class="p">;&lt;/span> &lt;span class="k">do&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 6&lt;/span>&lt;span class="cl"> crontab -u &lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="nv">$user&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span> -l 2&amp;gt;/dev/null &lt;span class="o">&amp;amp;&amp;amp;&lt;/span> &lt;span class="nb">echo&lt;/span> &lt;span class="s2">&amp;#34;=== &lt;/span>&lt;span class="nv">$user&lt;/span>&lt;span class="s2"> ===&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 7&lt;/span>&lt;span class="cl">&lt;span class="k">done&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 8&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 9&lt;/span>&lt;span class="cl">&lt;span class="c1"># 系統級 cron&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">10&lt;/span>&lt;span class="cl">cat /etc/crontab
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">11&lt;/span>&lt;span class="cl">ls /etc/cron.d/&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>沒有 SSH 時（cPanel 環境），在 cPanel 的「Cron 工作」頁面查看和匯出。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>cron job 要決定：排程頻率、執行失敗時的通知方式（cron 預設把輸出寄 email，但 email 常沒配好）、日誌記錄（指令的 stdout/stderr 導到 log 檔）。遷移或升級時，cron job 要隨著遷移——忘了搬等於停掉排程但沒人知道。&lt;/p>
&lt;p>雲端替代品：AWS CloudWatch Events / EventBridge、GCP Cloud Scheduler、Azure Logic Apps。這些服務提供 web UI 管理、失敗通知、執行歷史，但需要額外設定。&lt;/p>
&lt;h2 id="鄰卡">鄰卡&lt;/h2>
&lt;ul>
&lt;li>&lt;a href="https://tarrragon.github.io/blog/infra/knowledge-cards/ssh/" data-link-title="SSH" data-link-desc="Secure Shell — 加密的遠端 shell 連線，有 SSH 等於有 CLI 工具鏈，沒有就只能靠 FTP 和 web 面板">SSH&lt;/a> — 盤點和管理 cron 需要 SSH 存取&lt;/li>
&lt;/ul></description><content:encoded><![CDATA[<p>cron 是 Unix/Linux 系統內建的排程工作管理器，按預定的時間表自動執行指令。一個 cron job 定義「什麼時間跑什麼指令」，系統背景的 cron daemon 負責到時間就執行。</p>
<h2 id="概念位置">概念位置</h2>
<p>cron 在接手維運時是容易被忽略的隱藏工作——它不像 web 服務有明顯的入口，但可能負責資料庫備份、快取清除、報表產出、日誌清理等關鍵任務。漏掉一個 cron job 可能讓備份停止、快取永不過期、報表不再更新，而且不會立刻有人發現。</p>
<h2 id="crontab-格式">crontab 格式</h2>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="ln">1</span><span class="cl"># 分 時 日 月 週  指令
</span></span><span class="line"><span class="ln">2</span><span class="cl">0  3  *  *  *    /usr/bin/php /var/www/backup.php
</span></span><span class="line"><span class="ln">3</span><span class="cl">*/5 * *  *  *    /usr/bin/curl -s https://example.com/cron/heartbeat
</span></span><span class="line"><span class="ln">4</span><span class="cl">0  0  1  *  *    /usr/bin/find /tmp -mtime +7 -delete</span></span></code></pre></div><p>五個時間欄位依序是分鐘（0-59）、小時（0-23）、日（1-31）、月（1-12）、星期幾（0-7，0 和 7 都是星期日）。<code>*</code> 代表「每一個」，<code>*/5</code> 代表「每 5 個」。</p>
<h2 id="可觀察訊號">可觀察訊號</h2>
<p>接手維運時盤點 cron job：</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="ln"> 1</span><span class="cl"><span class="c1"># 當前使用者的 crontab</span>
</span></span><span class="line"><span class="ln"> 2</span><span class="cl">crontab -l
</span></span><span class="line"><span class="ln"> 3</span><span class="cl">
</span></span><span class="line"><span class="ln"> 4</span><span class="cl"><span class="c1"># 所有使用者的 crontab（需要 root）</span>
</span></span><span class="line"><span class="ln"> 5</span><span class="cl"><span class="k">for</span> user in <span class="k">$(</span>cut -f1 -d: /etc/passwd<span class="k">)</span><span class="p">;</span> <span class="k">do</span>
</span></span><span class="line"><span class="ln"> 6</span><span class="cl">  crontab -u <span class="s2">&#34;</span><span class="nv">$user</span><span class="s2">&#34;</span> -l 2&gt;/dev/null <span class="o">&amp;&amp;</span> <span class="nb">echo</span> <span class="s2">&#34;=== </span><span class="nv">$user</span><span class="s2"> ===&#34;</span>
</span></span><span class="line"><span class="ln"> 7</span><span class="cl"><span class="k">done</span>
</span></span><span class="line"><span class="ln"> 8</span><span class="cl">
</span></span><span class="line"><span class="ln"> 9</span><span class="cl"><span class="c1"># 系統級 cron</span>
</span></span><span class="line"><span class="ln">10</span><span class="cl">cat /etc/crontab
</span></span><span class="line"><span class="ln">11</span><span class="cl">ls /etc/cron.d/</span></span></code></pre></div><p>沒有 SSH 時（cPanel 環境），在 cPanel 的「Cron 工作」頁面查看和匯出。</p>
<h2 id="設計責任">設計責任</h2>
<p>cron job 要決定：排程頻率、執行失敗時的通知方式（cron 預設把輸出寄 email，但 email 常沒配好）、日誌記錄（指令的 stdout/stderr 導到 log 檔）。遷移或升級時，cron job 要隨著遷移——忘了搬等於停掉排程但沒人知道。</p>
<p>雲端替代品：AWS CloudWatch Events / EventBridge、GCP Cloud Scheduler、Azure Logic Apps。這些服務提供 web UI 管理、失敗通知、執行歷史，但需要額外設定。</p>
<h2 id="鄰卡">鄰卡</h2>
<ul>
<li><a href="/blog/infra/knowledge-cards/ssh/" data-link-title="SSH" data-link-desc="Secure Shell — 加密的遠端 shell 連線，有 SSH 等於有 CLI 工具鏈，沒有就只能靠 FTP 和 web 面板">SSH</a> — 盤點和管理 cron 需要 SSH 存取</li>
</ul>
]]></content:encoded></item><item><title>Retention</title><link>https://tarrragon.github.io/blog/business/knowledge-cards/retention/</link><pubDate>Tue, 19 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/business/knowledge-cards/retention/</guid><description>&lt;p>Retention 的核心概念是「客戶留存率」—簽下來的客戶在 N 期後還繼續付費的比例。&lt;a href="https://tarrragon.github.io/blog/business/knowledge-cards/saas/" data-link-title="SaaS" data-link-desc="說明雲端訂閱軟體的商業模式與經濟特徵">SaaS&lt;/a> 業界常用 net revenue retention（NRR）—不只算續約，還算現有客戶是否升級加購。NRR 120% 代表現有客戶不流失還反向擴張。Retention 是 &lt;a href="https://tarrragon.github.io/blog/business/knowledge-cards/unit-economics/" data-link-title="Unit Economics" data-link-desc="說明單位經濟模型與其判斷一家公司是否賺錢的責任">單位經濟&lt;/a> 的核心放大器。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>Retention 是 &lt;a href="https://tarrragon.github.io/blog/business/knowledge-cards/lock-in/" data-link-title="Lock-in" data-link-desc="說明鎖定效應如何形成護城河">Lock-in&lt;/a> 與 &lt;a href="https://tarrragon.github.io/blog/business/knowledge-cards/switching-cost/" data-link-title="Switching Cost" data-link-desc="說明切換成本如何鞏固客戶留存">Switching Cost&lt;/a> 的結果指標。同樣的 &lt;a href="https://tarrragon.github.io/blog/business/knowledge-cards/cac/" data-link-title="CAC" data-link-desc="說明獲客成本及其對商業模式可行性的決定作用">CAC&lt;/a>，retention 100% 跟 retention 80% 對應的 &lt;a href="https://tarrragon.github.io/blog/business/knowledge-cards/ltv/" data-link-title="LTV" data-link-desc="說明客戶終身價值與其在估值中的作用">LTV&lt;/a> 差距巨大。Retention 也是 &lt;a href="https://tarrragon.github.io/blog/business/knowledge-cards/valuation/" data-link-title="Valuation" data-link-desc="說明估值的構成與商業判讀作用">估值&lt;/a> 計算的核心參數—NRR 越高，估值倍數越高。&lt;/p>
&lt;h2 id="可觀察訊號與例子">可觀察訊號與例子&lt;/h2>
&lt;p>判讀 retention 的健康度：SaaS 業界 90%+ 是優秀，80-90% 是健康，低於 80% 要懷疑產品價值或競爭力。Palantir 的 retention 高到誇張，就是 &lt;a href="https://tarrragon.github.io/blog/business/knowledge-cards/fde/" data-link-title="FDE" data-link-desc="說明前線部署工程師模式的成立條件">FDE&lt;/a> 模式深度嵌入客戶流程的結果—一旦工程師把整套東西嵌進客戶流程，客戶根本拔不掉。&lt;/p>
&lt;h2 id="判讀方式">判讀方式&lt;/h2>
&lt;p>讀到「retention 下降」時，往往是商業模式或競爭環境惡化的早期訊號—客戶不續約不一定是因為產品變差，可能是因為 &lt;a href="https://tarrragon.github.io/blog/business/knowledge-cards/switching-cost/" data-link-title="Switching Cost" data-link-desc="說明切換成本如何鞏固客戶留存">切換成本&lt;/a> 變低或競爭對手出現。Retention 下降會放大 &lt;a href="https://tarrragon.github.io/blog/business/knowledge-cards/valuation-compression/" data-link-title="Valuation Compression" data-link-desc="說明估值壓縮如何影響新創生存">估值壓縮&lt;/a>，因為投資人計算 &lt;a href="https://tarrragon.github.io/blog/business/knowledge-cards/ltv/" data-link-title="LTV" data-link-desc="說明客戶終身價值與其在估值中的作用">LTV&lt;/a> 時會用更保守的留存假設。&lt;/p></description><content:encoded><![CDATA[<p>Retention 的核心概念是「客戶留存率」—簽下來的客戶在 N 期後還繼續付費的比例。<a href="/blog/business/knowledge-cards/saas/" data-link-title="SaaS" data-link-desc="說明雲端訂閱軟體的商業模式與經濟特徵">SaaS</a> 業界常用 net revenue retention（NRR）—不只算續約，還算現有客戶是否升級加購。NRR 120% 代表現有客戶不流失還反向擴張。Retention 是 <a href="/blog/business/knowledge-cards/unit-economics/" data-link-title="Unit Economics" data-link-desc="說明單位經濟模型與其判斷一家公司是否賺錢的責任">單位經濟</a> 的核心放大器。</p>
<h2 id="概念位置">概念位置</h2>
<p>Retention 是 <a href="/blog/business/knowledge-cards/lock-in/" data-link-title="Lock-in" data-link-desc="說明鎖定效應如何形成護城河">Lock-in</a> 與 <a href="/blog/business/knowledge-cards/switching-cost/" data-link-title="Switching Cost" data-link-desc="說明切換成本如何鞏固客戶留存">Switching Cost</a> 的結果指標。同樣的 <a href="/blog/business/knowledge-cards/cac/" data-link-title="CAC" data-link-desc="說明獲客成本及其對商業模式可行性的決定作用">CAC</a>，retention 100% 跟 retention 80% 對應的 <a href="/blog/business/knowledge-cards/ltv/" data-link-title="LTV" data-link-desc="說明客戶終身價值與其在估值中的作用">LTV</a> 差距巨大。Retention 也是 <a href="/blog/business/knowledge-cards/valuation/" data-link-title="Valuation" data-link-desc="說明估值的構成與商業判讀作用">估值</a> 計算的核心參數—NRR 越高，估值倍數越高。</p>
<h2 id="可觀察訊號與例子">可觀察訊號與例子</h2>
<p>判讀 retention 的健康度：SaaS 業界 90%+ 是優秀，80-90% 是健康，低於 80% 要懷疑產品價值或競爭力。Palantir 的 retention 高到誇張，就是 <a href="/blog/business/knowledge-cards/fde/" data-link-title="FDE" data-link-desc="說明前線部署工程師模式的成立條件">FDE</a> 模式深度嵌入客戶流程的結果—一旦工程師把整套東西嵌進客戶流程，客戶根本拔不掉。</p>
<h2 id="判讀方式">判讀方式</h2>
<p>讀到「retention 下降」時，往往是商業模式或競爭環境惡化的早期訊號—客戶不續約不一定是因為產品變差，可能是因為 <a href="/blog/business/knowledge-cards/switching-cost/" data-link-title="Switching Cost" data-link-desc="說明切換成本如何鞏固客戶留存">切換成本</a> 變低或競爭對手出現。Retention 下降會放大 <a href="/blog/business/knowledge-cards/valuation-compression/" data-link-title="Valuation Compression" data-link-desc="說明估值壓縮如何影響新創生存">估值壓縮</a>，因為投資人計算 <a href="/blog/business/knowledge-cards/ltv/" data-link-title="LTV" data-link-desc="說明客戶終身價值與其在估值中的作用">LTV</a> 時會用更保守的留存假設。</p>
]]></content:encoded></item><item><title>nginx</title><link>https://tarrragon.github.io/blog/infra/knowledge-cards/nginx/</link><pubDate>Fri, 26 Jun 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/infra/knowledge-cards/nginx/</guid><description>&lt;p>nginx 是高效能的 Web Server 和 Reverse Proxy，以非同步事件驅動架構處理大量並發連線。它在全球 web server 市場佔有率與 Apache 並列前二，新部署的伺服器多數選 nginx。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>nginx 在 infra 裡常見的角色有三種：作為 reverse proxy 把請求轉給後端應用（Node.js、PHP-FPM、Python WSGI）、作為靜態檔案伺服器、作為 TLS 終結點處理 HTTPS。ALB 在雲端環境承擔了部分 nginx 的職責（負載平衡、TLS 終結），但 VPS 環境裡 nginx 仍然是標準選擇。&lt;/p>
&lt;h2 id="跟-apache-的關鍵差別">跟 Apache 的關鍵差別&lt;/h2>
&lt;table>
 &lt;thead>
 &lt;tr>
 &lt;th>面向&lt;/th>
 &lt;th>nginx&lt;/th>
 &lt;th>Apache&lt;/th>
 &lt;/tr>
 &lt;/thead>
 &lt;tbody>
 &lt;tr>
 &lt;td>設定模式&lt;/td>
 &lt;td>集中式（&lt;code>/etc/nginx/&lt;/code> 下的設定檔）&lt;/td>
 &lt;td>支援 .htaccess 分散式設定&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>並發模型&lt;/td>
 &lt;td>事件驅動、非阻塞&lt;/td>
 &lt;td>預設 prefork（每個請求一個 process）&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>PHP 整合&lt;/td>
 &lt;td>透過 FastCGI（PHP-FPM）&lt;/td>
 &lt;td>mod_php（直接嵌入）或 FastCGI&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>URL rewrite&lt;/td>
 &lt;td>&lt;code>location&lt;/code> + &lt;code>rewrite&lt;/code> 區塊&lt;/td>
 &lt;td>&lt;code>.htaccess&lt;/code> 的 &lt;code>RewriteRule&lt;/code>&lt;/td>
 &lt;/tr>
 &lt;/tbody>
&lt;/table>
&lt;h2 id="可觀察訊號">可觀察訊號&lt;/h2>
&lt;p>OS 升級或平台遷移時，如果從 Apache 換成 nginx，所有 &lt;code>.htaccess&lt;/code> 規則要手動轉成 nginx 設定：URL rewrite、目錄保護、PHP 設定覆寫、安全標頭。nginx 沒有 &lt;code>.htaccess&lt;/code> 的等價物——所有設定都在集中的設定檔裡，需要 reload nginx 才能生效（Apache 的 &lt;code>.htaccess&lt;/code> 每次請求都重新讀取）。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>nginx 設定要決定：server block（類似 Apache 的 VirtualHost）怎麼組織、upstream 指向哪個 app server、靜態檔案的 root 路徑、TLS 憑證掛在哪裡、access log 和 error log 的路徑。設定改完跑 &lt;code>nginx -t&lt;/code> 驗證語法後再 &lt;code>nginx -s reload&lt;/code>。&lt;/p>
&lt;h2 id="鄰卡">鄰卡&lt;/h2>
&lt;ul>
&lt;li>&lt;a href="https://tarrragon.github.io/blog/infra/knowledge-cards/htaccess/" data-link-title=".htaccess" data-link-desc="Apache Web Server 的目錄層級設定檔，控制 URL rewrite、存取權限、PHP 設定覆寫與安全標頭">.htaccess&lt;/a> — Apache 的分散設定，遷移到 nginx 時需要轉換&lt;/li>
&lt;li>&lt;a href="https://tarrragon.github.io/blog/infra/knowledge-cards/alb/" data-link-title="ALB" data-link-desc="Application Load Balancer — 流量進入系統的第一站，負責 listener 路由、健康檢查與 TLS 終結">ALB&lt;/a> — 雲端環境裡承擔部分 nginx 職責&lt;/li>
&lt;/ul></description><content:encoded><![CDATA[<p>nginx 是高效能的 Web Server 和 Reverse Proxy，以非同步事件驅動架構處理大量並發連線。它在全球 web server 市場佔有率與 Apache 並列前二，新部署的伺服器多數選 nginx。</p>
<h2 id="概念位置">概念位置</h2>
<p>nginx 在 infra 裡常見的角色有三種：作為 reverse proxy 把請求轉給後端應用（Node.js、PHP-FPM、Python WSGI）、作為靜態檔案伺服器、作為 TLS 終結點處理 HTTPS。ALB 在雲端環境承擔了部分 nginx 的職責（負載平衡、TLS 終結），但 VPS 環境裡 nginx 仍然是標準選擇。</p>
<h2 id="跟-apache-的關鍵差別">跟 Apache 的關鍵差別</h2>
<table>
  <thead>
      <tr>
          <th>面向</th>
          <th>nginx</th>
          <th>Apache</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>設定模式</td>
          <td>集中式（<code>/etc/nginx/</code> 下的設定檔）</td>
          <td>支援 .htaccess 分散式設定</td>
      </tr>
      <tr>
          <td>並發模型</td>
          <td>事件驅動、非阻塞</td>
          <td>預設 prefork（每個請求一個 process）</td>
      </tr>
      <tr>
          <td>PHP 整合</td>
          <td>透過 FastCGI（PHP-FPM）</td>
          <td>mod_php（直接嵌入）或 FastCGI</td>
      </tr>
      <tr>
          <td>URL rewrite</td>
          <td><code>location</code> + <code>rewrite</code> 區塊</td>
          <td><code>.htaccess</code> 的 <code>RewriteRule</code></td>
      </tr>
  </tbody>
</table>
<h2 id="可觀察訊號">可觀察訊號</h2>
<p>OS 升級或平台遷移時，如果從 Apache 換成 nginx，所有 <code>.htaccess</code> 規則要手動轉成 nginx 設定：URL rewrite、目錄保護、PHP 設定覆寫、安全標頭。nginx 沒有 <code>.htaccess</code> 的等價物——所有設定都在集中的設定檔裡，需要 reload nginx 才能生效（Apache 的 <code>.htaccess</code> 每次請求都重新讀取）。</p>
<h2 id="設計責任">設計責任</h2>
<p>nginx 設定要決定：server block（類似 Apache 的 VirtualHost）怎麼組織、upstream 指向哪個 app server、靜態檔案的 root 路徑、TLS 憑證掛在哪裡、access log 和 error log 的路徑。設定改完跑 <code>nginx -t</code> 驗證語法後再 <code>nginx -s reload</code>。</p>
<h2 id="鄰卡">鄰卡</h2>
<ul>
<li><a href="/blog/infra/knowledge-cards/htaccess/" data-link-title=".htaccess" data-link-desc="Apache Web Server 的目錄層級設定檔，控制 URL rewrite、存取權限、PHP 設定覆寫與安全標頭">.htaccess</a> — Apache 的分散設定，遷移到 nginx 時需要轉換</li>
<li><a href="/blog/infra/knowledge-cards/alb/" data-link-title="ALB" data-link-desc="Application Load Balancer — 流量進入系統的第一站，負責 listener 路由、健康檢查與 TLS 終結">ALB</a> — 雲端環境裡承擔部分 nginx 職責</li>
</ul>
]]></content:encoded></item><item><title>Thin Wrapper</title><link>https://tarrragon.github.io/blog/business/knowledge-cards/thin-wrapper/</link><pubDate>Tue, 19 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/business/knowledge-cards/thin-wrapper/</guid><description>&lt;p>Thin Wrapper 的核心概念是「在底層服務外只包一層薄殼就拿出來賣」—沒有自己的資料、沒有自己的工作流、沒有 &lt;a href="https://tarrragon.github.io/blog/business/knowledge-cards/tacit-knowledge/" data-link-title="Tacit Knowledge" data-link-desc="說明隱性知識與其作為護城河的價值">隱性知識&lt;/a>。GPT 出來後一年，大量「ChatGPT 套殼」產品都是 thin wrapper，相對概念是有 &lt;a href="https://tarrragon.github.io/blog/business/knowledge-cards/fat-data-fat-skill/" data-link-title="Fat Data / Fat Skill" data-link-desc="說明獨家資料與行業隱性能力作為 AI 時代的護城河">Fat Data / Fat Skill&lt;/a> 的產品。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>Thin Wrapper 是 &lt;a href="https://tarrragon.github.io/blog/business/knowledge-cards/fat-data-fat-skill/" data-link-title="Fat Data / Fat Skill" data-link-desc="說明獨家資料與行業隱性能力作為 AI 時代的護城河">護城河&lt;/a> 缺席的具體表現。它沒有 &lt;a href="https://tarrragon.github.io/blog/business/knowledge-cards/fat-data-fat-skill/" data-link-title="Fat Data / Fat Skill" data-link-desc="說明獨家資料與行業隱性能力作為 AI 時代的護城河">Fat Data&lt;/a>（獨家資料）也沒有 &lt;a href="https://tarrragon.github.io/blog/business/knowledge-cards/fat-data-fat-skill/" data-link-title="Fat Data / Fat Skill" data-link-desc="說明獨家資料與行業隱性能力作為 AI 時代的護城河">Fat Skill&lt;/a>（行業隱性能力），所以底層服務一旦出官方版就被輾平。它的另一個命運是被收編成 &lt;a href="https://tarrragon.github.io/blog/business/knowledge-cards/connector/" data-link-title="Connector" data-link-desc="說明被收編進生態系變成整合工具的命運">Connector&lt;/a>。&lt;/p>
&lt;h2 id="可觀察訊號與例子">可觀察訊號與例子&lt;/h2>
&lt;p>判斷一個產品是不是 thin wrapper：拿掉底層 AI 模型後還剩下什麼？如果只剩 UI 跟 prompt，那就是 thin wrapper。如果還有獨家資料、行業特定工作流、客戶累積的歷史脈絡—那不是 thin wrapper。同樣是 Chat UI，問答機器人是 thin wrapper，但保險核保副駕駛因為內建公司歷史核保資料就不是。&lt;/p>
&lt;h2 id="判讀方式">判讀方式&lt;/h2>
&lt;p>讀到「thin wrapper 會被殺死」時，意味著該類產品在 AI Labs 推出官方版功能後沒有抵抗力。AI 新創想活下去得在 &lt;a href="https://tarrragon.github.io/blog/business/knowledge-cards/fat-data-fat-skill/" data-link-title="Fat Data / Fat Skill" data-link-desc="說明獨家資料與行業隱性能力作為 AI 時代的護城河">Fat Data&lt;/a> 或 &lt;a href="https://tarrragon.github.io/blog/business/knowledge-cards/fat-data-fat-skill/" data-link-title="Fat Data / Fat Skill" data-link-desc="說明獨家資料與行業隱性能力作為 AI 時代的護城河">Fat Skill&lt;/a> 上累積—只靠 prompt 工程或 UI 設計不夠。投資人判讀 AI 新創第一個過濾條件就是「拿掉底層模型還剩什麼」。&lt;/p></description><content:encoded><![CDATA[<p>Thin Wrapper 的核心概念是「在底層服務外只包一層薄殼就拿出來賣」—沒有自己的資料、沒有自己的工作流、沒有 <a href="/blog/business/knowledge-cards/tacit-knowledge/" data-link-title="Tacit Knowledge" data-link-desc="說明隱性知識與其作為護城河的價值">隱性知識</a>。GPT 出來後一年，大量「ChatGPT 套殼」產品都是 thin wrapper，相對概念是有 <a href="/blog/business/knowledge-cards/fat-data-fat-skill/" data-link-title="Fat Data / Fat Skill" data-link-desc="說明獨家資料與行業隱性能力作為 AI 時代的護城河">Fat Data / Fat Skill</a> 的產品。</p>
<h2 id="概念位置">概念位置</h2>
<p>Thin Wrapper 是 <a href="/blog/business/knowledge-cards/fat-data-fat-skill/" data-link-title="Fat Data / Fat Skill" data-link-desc="說明獨家資料與行業隱性能力作為 AI 時代的護城河">護城河</a> 缺席的具體表現。它沒有 <a href="/blog/business/knowledge-cards/fat-data-fat-skill/" data-link-title="Fat Data / Fat Skill" data-link-desc="說明獨家資料與行業隱性能力作為 AI 時代的護城河">Fat Data</a>（獨家資料）也沒有 <a href="/blog/business/knowledge-cards/fat-data-fat-skill/" data-link-title="Fat Data / Fat Skill" data-link-desc="說明獨家資料與行業隱性能力作為 AI 時代的護城河">Fat Skill</a>（行業隱性能力），所以底層服務一旦出官方版就被輾平。它的另一個命運是被收編成 <a href="/blog/business/knowledge-cards/connector/" data-link-title="Connector" data-link-desc="說明被收編進生態系變成整合工具的命運">Connector</a>。</p>
<h2 id="可觀察訊號與例子">可觀察訊號與例子</h2>
<p>判斷一個產品是不是 thin wrapper：拿掉底層 AI 模型後還剩下什麼？如果只剩 UI 跟 prompt，那就是 thin wrapper。如果還有獨家資料、行業特定工作流、客戶累積的歷史脈絡—那不是 thin wrapper。同樣是 Chat UI，問答機器人是 thin wrapper，但保險核保副駕駛因為內建公司歷史核保資料就不是。</p>
<h2 id="判讀方式">判讀方式</h2>
<p>讀到「thin wrapper 會被殺死」時，意味著該類產品在 AI Labs 推出官方版功能後沒有抵抗力。AI 新創想活下去得在 <a href="/blog/business/knowledge-cards/fat-data-fat-skill/" data-link-title="Fat Data / Fat Skill" data-link-desc="說明獨家資料與行業隱性能力作為 AI 時代的護城河">Fat Data</a> 或 <a href="/blog/business/knowledge-cards/fat-data-fat-skill/" data-link-title="Fat Data / Fat Skill" data-link-desc="說明獨家資料與行業隱性能力作為 AI 時代的護城河">Fat Skill</a> 上累積—只靠 prompt 工程或 UI 設計不夠。投資人判讀 AI 新創第一個過濾條件就是「拿掉底層模型還剩什麼」。</p>
]]></content:encoded></item><item><title>MySQL</title><link>https://tarrragon.github.io/blog/infra/knowledge-cards/mysql/</link><pubDate>Fri, 26 Jun 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/infra/knowledge-cards/mysql/</guid><description>&lt;p>MySQL 是最廣泛使用的開源關聯式資料庫，多數 PHP 應用、WordPress、以及大量 web 服務的資料層都跑在 MySQL 上。MariaDB 是 MySQL 被 Oracle 收購後社群分支出來的相容實作，多數 Linux 發行版已經把預設的 mysql 套件指向 MariaDB。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>MySQL 在 infra 裡是典型的 stateful 資源——資料不可重建、備份和刪除保護是 day-1 需求。接手維運時，MySQL 的版本、備份設定、認證方式是第一批要確認的項目。雲端環境裡 MySQL 常以 RDS 形式運行（受管服務、代管備份與 failover）。&lt;/p>
&lt;h2 id="大版本升級的關鍵差異">大版本升級的關鍵差異&lt;/h2>
&lt;p>MySQL 5.7 → 8.0 的 breaking change 在接手和升級情境裡經常遇到：&lt;/p>
&lt;table>
 &lt;thead>
 &lt;tr>
 &lt;th>變更項&lt;/th>
 &lt;th>5.7 行為&lt;/th>
 &lt;th>8.0 行為&lt;/th>
 &lt;/tr>
 &lt;/thead>
 &lt;tbody>
 &lt;tr>
 &lt;td>預設認證方式&lt;/td>
 &lt;td>&lt;code>mysql_native_password&lt;/code>&lt;/td>
 &lt;td>&lt;code>caching_sha2_password&lt;/code>&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;code>GROUP BY&lt;/code> 隱式排序&lt;/td>
 &lt;td>有（按 group 欄位排）&lt;/td>
 &lt;td>無（需要明確 &lt;code>ORDER BY&lt;/code>）&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>預設字元集&lt;/td>
 &lt;td>&lt;code>utf8&lt;/code>（3 byte）&lt;/td>
 &lt;td>&lt;code>utf8mb4&lt;/code>（4 byte、支援 emoji）&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;code>GRANT&lt;/code> 同時建使用者&lt;/td>
 &lt;td>允許&lt;/td>
 &lt;td>必須先 &lt;code>CREATE USER&lt;/code>&lt;/td>
 &lt;/tr>
 &lt;/tbody>
&lt;/table>
&lt;h2 id="可觀察訊號">可觀察訊號&lt;/h2>
&lt;p>接手維運時的確認清單：&lt;code>SELECT VERSION();&lt;/code> 查版本、&lt;code>SHOW DATABASES;&lt;/code> 看有哪些資料庫、&lt;code>SHOW VARIABLES LIKE 'character_set%';&lt;/code> 確認字元集、&lt;code>SHOW VARIABLES LIKE 'max_connections';&lt;/code> 看連線上限。&lt;/p>
&lt;h2 id="cli-工具">CLI 工具&lt;/h2>
&lt;table>
 &lt;thead>
 &lt;tr>
 &lt;th>工具&lt;/th>
 &lt;th>功能&lt;/th>
 &lt;/tr>
 &lt;/thead>
 &lt;tbody>
 &lt;tr>
 &lt;td>&lt;code>mysql&lt;/code>&lt;/td>
 &lt;td>互動式 SQL 查詢&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;code>mysqldump&lt;/code>&lt;/td>
 &lt;td>匯出資料庫為 SQL 文字檔&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;code>mysqlcheck&lt;/code>&lt;/td>
 &lt;td>檢查、修復、優化資料表&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;code>mysqlimport&lt;/code>&lt;/td>
 &lt;td>匯入 CSV / TSV 資料&lt;/td>
 &lt;/tr>
 &lt;/tbody>
&lt;/table>
&lt;p>&lt;code>mysqldump&lt;/code> 是備份的核心工具——一行指令把整個資料庫匯出成可還原的 SQL。phpMyAdmin 的匯出功能底層也是類似的邏輯，但受 web server timeout 限制，大資料庫更適合用 CLI。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>MySQL 的 infra 設計要決定：備份頻率和保留天數（RDS 預設 7 天自動備份）、是否開 multi-AZ（failover 保護）、連線池設定（RDS Proxy 或應用層 pool）、慢查詢日誌是否開啟。&lt;/p>
&lt;h2 id="鄰卡">鄰卡&lt;/h2>
&lt;ul>
&lt;li>&lt;a href="https://tarrragon.github.io/blog/infra/knowledge-cards/rds/" data-link-title="RDS" data-link-desc="AWS 的受管關聯式資料庫服務，代管備份、更新與 failover，讓使用者專注在 schema 和查詢">RDS&lt;/a> — AWS 的受管 MySQL 服務&lt;/li>
&lt;li>&lt;a href="https://tarrragon.github.io/blog/infra/knowledge-cards/phpmyadmin/" data-link-title="phpMyAdmin" data-link-desc="Web 介面的 MySQL / MariaDB 管理工具，透過瀏覽器操作資料庫">phpMyAdmin&lt;/a> — Web 介面的 MySQL 管理工具&lt;/li>
&lt;/ul></description><content:encoded><![CDATA[<p>MySQL 是最廣泛使用的開源關聯式資料庫，多數 PHP 應用、WordPress、以及大量 web 服務的資料層都跑在 MySQL 上。MariaDB 是 MySQL 被 Oracle 收購後社群分支出來的相容實作，多數 Linux 發行版已經把預設的 mysql 套件指向 MariaDB。</p>
<h2 id="概念位置">概念位置</h2>
<p>MySQL 在 infra 裡是典型的 stateful 資源——資料不可重建、備份和刪除保護是 day-1 需求。接手維運時，MySQL 的版本、備份設定、認證方式是第一批要確認的項目。雲端環境裡 MySQL 常以 RDS 形式運行（受管服務、代管備份與 failover）。</p>
<h2 id="大版本升級的關鍵差異">大版本升級的關鍵差異</h2>
<p>MySQL 5.7 → 8.0 的 breaking change 在接手和升級情境裡經常遇到：</p>
<table>
  <thead>
      <tr>
          <th>變更項</th>
          <th>5.7 行為</th>
          <th>8.0 行為</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>預設認證方式</td>
          <td><code>mysql_native_password</code></td>
          <td><code>caching_sha2_password</code></td>
      </tr>
      <tr>
          <td><code>GROUP BY</code> 隱式排序</td>
          <td>有（按 group 欄位排）</td>
          <td>無（需要明確 <code>ORDER BY</code>）</td>
      </tr>
      <tr>
          <td>預設字元集</td>
          <td><code>utf8</code>（3 byte）</td>
          <td><code>utf8mb4</code>（4 byte、支援 emoji）</td>
      </tr>
      <tr>
          <td><code>GRANT</code> 同時建使用者</td>
          <td>允許</td>
          <td>必須先 <code>CREATE USER</code></td>
      </tr>
  </tbody>
</table>
<h2 id="可觀察訊號">可觀察訊號</h2>
<p>接手維運時的確認清單：<code>SELECT VERSION();</code> 查版本、<code>SHOW DATABASES;</code> 看有哪些資料庫、<code>SHOW VARIABLES LIKE 'character_set%';</code> 確認字元集、<code>SHOW VARIABLES LIKE 'max_connections';</code> 看連線上限。</p>
<h2 id="cli-工具">CLI 工具</h2>
<table>
  <thead>
      <tr>
          <th>工具</th>
          <th>功能</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td><code>mysql</code></td>
          <td>互動式 SQL 查詢</td>
      </tr>
      <tr>
          <td><code>mysqldump</code></td>
          <td>匯出資料庫為 SQL 文字檔</td>
      </tr>
      <tr>
          <td><code>mysqlcheck</code></td>
          <td>檢查、修復、優化資料表</td>
      </tr>
      <tr>
          <td><code>mysqlimport</code></td>
          <td>匯入 CSV / TSV 資料</td>
      </tr>
  </tbody>
</table>
<p><code>mysqldump</code> 是備份的核心工具——一行指令把整個資料庫匯出成可還原的 SQL。phpMyAdmin 的匯出功能底層也是類似的邏輯，但受 web server timeout 限制，大資料庫更適合用 CLI。</p>
<h2 id="設計責任">設計責任</h2>
<p>MySQL 的 infra 設計要決定：備份頻率和保留天數（RDS 預設 7 天自動備份）、是否開 multi-AZ（failover 保護）、連線池設定（RDS Proxy 或應用層 pool）、慢查詢日誌是否開啟。</p>
<h2 id="鄰卡">鄰卡</h2>
<ul>
<li><a href="/blog/infra/knowledge-cards/rds/" data-link-title="RDS" data-link-desc="AWS 的受管關聯式資料庫服務，代管備份、更新與 failover，讓使用者專注在 schema 和查詢">RDS</a> — AWS 的受管 MySQL 服務</li>
<li><a href="/blog/infra/knowledge-cards/phpmyadmin/" data-link-title="phpMyAdmin" data-link-desc="Web 介面的 MySQL / MariaDB 管理工具，透過瀏覽器操作資料庫">phpMyAdmin</a> — Web 介面的 MySQL 管理工具</li>
</ul>
]]></content:encoded></item><item><title>Fat Data / Fat Skill</title><link>https://tarrragon.github.io/blog/business/knowledge-cards/fat-data-fat-skill/</link><pubDate>Tue, 19 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/business/knowledge-cards/fat-data-fat-skill/</guid><description>&lt;p>Fat Data / Fat Skill 的核心概念是「AI 時代仍能撐住的兩種 &lt;a href="https://tarrragon.github.io/blog/business/knowledge-cards/lock-in/" data-link-title="Lock-in" data-link-desc="說明鎖定效應如何形成護城河">護城河&lt;/a>」。Fat Data 是別人沒有的獨家資料—例如十年的判決書資料庫、保險理賠歷史、醫院影像標註。Fat Skill 是深度嵌入行業的工作流知識—例如保險核保流程、銀行合規要求、醫院動線設計。相對概念是 &lt;a href="https://tarrragon.github.io/blog/business/knowledge-cards/thin-wrapper/" data-link-title="Thin Wrapper" data-link-desc="說明薄包裝產品的脆弱性">Thin Wrapper&lt;/a>。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>Fat Data / Fat Skill 承擔的責任是：當底層 AI 模型不斷進步時，這層資料 / 知識仍然只有你有，所以你的產品不會被基礎模型供應商直接輾平。Fat Skill 通常需要 &lt;a href="https://tarrragon.github.io/blog/business/knowledge-cards/fde/" data-link-title="FDE" data-link-desc="說明前線部署工程師模式的成立條件">FDE&lt;/a> 才能萃取出來，因為它是 &lt;a href="https://tarrragon.github.io/blog/business/knowledge-cards/tacit-knowledge/" data-link-title="Tacit Knowledge" data-link-desc="說明隱性知識與其作為護城河的價值">隱性知識&lt;/a> 的編碼。&lt;/p>
&lt;h2 id="可觀察訊號與例子">可觀察訊號與例子&lt;/h2>
&lt;p>Fat Data 的判讀訊號：資料是不是花了多年才累積、是不是來自獨家管道、能不能被簡單爬取或重建。Fat Skill 的判讀訊號：是否依賴 FDE 才能服務、是否需要長期在客戶端駐點才能學會、客戶離開後員工是否會被別家挖走整套搬家。Bloomberg Terminal 同時有 Fat Data（獨家金融資料）跟 Fat Skill（交易員工作流），是兩種護城河疊加的典型。&lt;/p>
&lt;h2 id="判讀方式">判讀方式&lt;/h2>
&lt;p>看到「沒有 fat data 或 fat skill 的會被殺到地板」這類論斷時，意味著該分析師認為 AI 時代差異化只剩這兩條路。判讀一家 AI 新創的存活機率，看它累積的是 fat data、fat skill、還是純粹的 &lt;a href="https://tarrragon.github.io/blog/business/knowledge-cards/thin-wrapper/" data-link-title="Thin Wrapper" data-link-desc="說明薄包裝產品的脆弱性">Thin Wrapper&lt;/a>。這也是 VC 投資 AI 新創時的核心過濾條件。&lt;/p></description><content:encoded><![CDATA[<p>Fat Data / Fat Skill 的核心概念是「AI 時代仍能撐住的兩種 <a href="/blog/business/knowledge-cards/lock-in/" data-link-title="Lock-in" data-link-desc="說明鎖定效應如何形成護城河">護城河</a>」。Fat Data 是別人沒有的獨家資料—例如十年的判決書資料庫、保險理賠歷史、醫院影像標註。Fat Skill 是深度嵌入行業的工作流知識—例如保險核保流程、銀行合規要求、醫院動線設計。相對概念是 <a href="/blog/business/knowledge-cards/thin-wrapper/" data-link-title="Thin Wrapper" data-link-desc="說明薄包裝產品的脆弱性">Thin Wrapper</a>。</p>
<h2 id="概念位置">概念位置</h2>
<p>Fat Data / Fat Skill 承擔的責任是：當底層 AI 模型不斷進步時，這層資料 / 知識仍然只有你有，所以你的產品不會被基礎模型供應商直接輾平。Fat Skill 通常需要 <a href="/blog/business/knowledge-cards/fde/" data-link-title="FDE" data-link-desc="說明前線部署工程師模式的成立條件">FDE</a> 才能萃取出來，因為它是 <a href="/blog/business/knowledge-cards/tacit-knowledge/" data-link-title="Tacit Knowledge" data-link-desc="說明隱性知識與其作為護城河的價值">隱性知識</a> 的編碼。</p>
<h2 id="可觀察訊號與例子">可觀察訊號與例子</h2>
<p>Fat Data 的判讀訊號：資料是不是花了多年才累積、是不是來自獨家管道、能不能被簡單爬取或重建。Fat Skill 的判讀訊號：是否依賴 FDE 才能服務、是否需要長期在客戶端駐點才能學會、客戶離開後員工是否會被別家挖走整套搬家。Bloomberg Terminal 同時有 Fat Data（獨家金融資料）跟 Fat Skill（交易員工作流），是兩種護城河疊加的典型。</p>
<h2 id="判讀方式">判讀方式</h2>
<p>看到「沒有 fat data 或 fat skill 的會被殺到地板」這類論斷時，意味著該分析師認為 AI 時代差異化只剩這兩條路。判讀一家 AI 新創的存活機率，看它累積的是 fat data、fat skill、還是純粹的 <a href="/blog/business/knowledge-cards/thin-wrapper/" data-link-title="Thin Wrapper" data-link-desc="說明薄包裝產品的脆弱性">Thin Wrapper</a>。這也是 VC 投資 AI 新創時的核心過濾條件。</p>
]]></content:encoded></item><item><title>RDS</title><link>https://tarrragon.github.io/blog/infra/knowledge-cards/rds/</link><pubDate>Fri, 26 Jun 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/infra/knowledge-cards/rds/</guid><description>&lt;p>RDS（Relational Database Service）是 AWS 提供的受管關聯式資料庫服務。它在 EC2 instance 上跑資料庫引擎（MySQL、PostgreSQL、MariaDB、Oracle、SQL Server），但把作業系統更新、自動備份、跨可用區 failover、磁碟擴容這些運維工作交給 AWS 代管。使用者操作的是資料庫層級的設定（schema、query、parameter group），不需要 SSH 進機器管 OS。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>RDS 是 infra 系列中 stateful 資源的代表。它持有不可重建的資料，所以它的 IaC 描述、備份策略、刪除保護、變更審查都比 stateless 資源（如 EC2 web server）嚴格。模組五（核心服務）和接手維運模組的資料庫相關段落都以 RDS 為主要範例。&lt;/p>
&lt;h2 id="可觀察訊號">可觀察訊號&lt;/h2>
&lt;p>需要理解 RDS 的情境包括：接手一個已經在跑的 production 資料庫、評估要不要從自建 MySQL 遷移到 RDS、設定資料庫的備份和高可用、或在 IaC 裡描述資料庫資源。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>使用 RDS 時要決定的關鍵設定：&lt;/p>
&lt;table>
 &lt;thead>
 &lt;tr>
 &lt;th>設定&lt;/th>
 &lt;th>決定什麼&lt;/th>
 &lt;th>影響&lt;/th>
 &lt;/tr>
 &lt;/thead>
 &lt;tbody>
 &lt;tr>
 &lt;td>instance class&lt;/td>
 &lt;td>CPU / 記憶體規格&lt;/td>
 &lt;td>效能與成本&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>multi-AZ&lt;/td>
 &lt;td>是否跨可用區部署 standby&lt;/td>
 &lt;td>可用性（failover 分鐘級）vs 成本（約 2 倍）&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>backup retention&lt;/td>
 &lt;td>自動備份保留天數（1-35）&lt;/td>
 &lt;td>可回溯的時間窗口&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>deletion protection&lt;/td>
 &lt;td>是否允許刪除&lt;/td>
 &lt;td>防誤刪（production 必開）&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>parameter group&lt;/td>
 &lt;td>資料庫引擎參數（max_connections 等）&lt;/td>
 &lt;td>效能調校&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>engine version&lt;/td>
 &lt;td>資料庫版本&lt;/td>
 &lt;td>功能與相容性&lt;/td>
 &lt;/tr>
 &lt;/tbody>
&lt;/table>
&lt;p>跟自建 MySQL on EC2 的取捨：RDS 省去 OS 層運維，但 parameter group 和 option group 的可調整範圍比直接操作 my.cnf 窄。需要完全控制 OS 層（如自訂 plugin、特殊檔案系統）時，自建較合理。&lt;/p>
&lt;h2 id="鄰卡">鄰卡&lt;/h2>
&lt;ul>
&lt;li>&lt;a href="https://tarrragon.github.io/blog/infra/knowledge-cards/mysql/" data-link-title="MySQL" data-link-desc="最廣泛使用的開源關聯式資料庫。MariaDB 是其社群分支。大版本升級（5.7→8.0）有認證方式和查詢行為的 breaking change">MySQL&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://tarrragon.github.io/blog/infra/knowledge-cards/deletion-protection/" data-link-title="Deletion Protection" data-link-desc="雲端平台提供的防誤刪機制，開啟後刪除操作需要先顯式關閉保護才能執行">Deletion Protection&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://tarrragon.github.io/blog/infra/knowledge-cards/subnet/" data-link-title="Subnet（子網路）" data-link-desc="VPC 內按可用區與暴露程度切出的子網段，決定資源有沒有一條通往網際網路的路徑">Subnet&lt;/a>&lt;/li>
&lt;/ul></description><content:encoded><![CDATA[<p>RDS（Relational Database Service）是 AWS 提供的受管關聯式資料庫服務。它在 EC2 instance 上跑資料庫引擎（MySQL、PostgreSQL、MariaDB、Oracle、SQL Server），但把作業系統更新、自動備份、跨可用區 failover、磁碟擴容這些運維工作交給 AWS 代管。使用者操作的是資料庫層級的設定（schema、query、parameter group），不需要 SSH 進機器管 OS。</p>
<h2 id="概念位置">概念位置</h2>
<p>RDS 是 infra 系列中 stateful 資源的代表。它持有不可重建的資料，所以它的 IaC 描述、備份策略、刪除保護、變更審查都比 stateless 資源（如 EC2 web server）嚴格。模組五（核心服務）和接手維運模組的資料庫相關段落都以 RDS 為主要範例。</p>
<h2 id="可觀察訊號">可觀察訊號</h2>
<p>需要理解 RDS 的情境包括：接手一個已經在跑的 production 資料庫、評估要不要從自建 MySQL 遷移到 RDS、設定資料庫的備份和高可用、或在 IaC 裡描述資料庫資源。</p>
<h2 id="設計責任">設計責任</h2>
<p>使用 RDS 時要決定的關鍵設定：</p>
<table>
  <thead>
      <tr>
          <th>設定</th>
          <th>決定什麼</th>
          <th>影響</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>instance class</td>
          <td>CPU / 記憶體規格</td>
          <td>效能與成本</td>
      </tr>
      <tr>
          <td>multi-AZ</td>
          <td>是否跨可用區部署 standby</td>
          <td>可用性（failover 分鐘級）vs 成本（約 2 倍）</td>
      </tr>
      <tr>
          <td>backup retention</td>
          <td>自動備份保留天數（1-35）</td>
          <td>可回溯的時間窗口</td>
      </tr>
      <tr>
          <td>deletion protection</td>
          <td>是否允許刪除</td>
          <td>防誤刪（production 必開）</td>
      </tr>
      <tr>
          <td>parameter group</td>
          <td>資料庫引擎參數（max_connections 等）</td>
          <td>效能調校</td>
      </tr>
      <tr>
          <td>engine version</td>
          <td>資料庫版本</td>
          <td>功能與相容性</td>
      </tr>
  </tbody>
</table>
<p>跟自建 MySQL on EC2 的取捨：RDS 省去 OS 層運維，但 parameter group 和 option group 的可調整範圍比直接操作 my.cnf 窄。需要完全控制 OS 層（如自訂 plugin、特殊檔案系統）時，自建較合理。</p>
<h2 id="鄰卡">鄰卡</h2>
<ul>
<li><a href="/blog/infra/knowledge-cards/mysql/" data-link-title="MySQL" data-link-desc="最廣泛使用的開源關聯式資料庫。MariaDB 是其社群分支。大版本升級（5.7→8.0）有認證方式和查詢行為的 breaking change">MySQL</a></li>
<li><a href="/blog/infra/knowledge-cards/deletion-protection/" data-link-title="Deletion Protection" data-link-desc="雲端平台提供的防誤刪機制，開啟後刪除操作需要先顯式關閉保護才能執行">Deletion Protection</a></li>
<li><a href="/blog/infra/knowledge-cards/subnet/" data-link-title="Subnet（子網路）" data-link-desc="VPC 內按可用區與暴露程度切出的子網段，決定資源有沒有一條通往網際網路的路徑">Subnet</a></li>
</ul>
]]></content:encoded></item><item><title>Connector</title><link>https://tarrragon.github.io/blog/business/knowledge-cards/connector/</link><pubDate>Tue, 19 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/business/knowledge-cards/connector/</guid><description>&lt;p>Connector 的核心概念是「被收編進大平台的生態系變成上面的整合工具」。原本是獨立產品的公司，被併購或主動加入後變成大平台的 plug-in 或 integration。Zapier 的數千個 connector、Salesforce AppExchange 的 app 都屬此類。Connector 是 &lt;a href="https://tarrragon.github.io/blog/business/knowledge-cards/thin-wrapper/" data-link-title="Thin Wrapper" data-link-desc="說明薄包裝產品的脆弱性">Thin Wrapper&lt;/a> 不被殺死的另一條路。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>Connector 化是新創生命週期的一種終局狀態—雖然失去獨立生意，但保住一部分用戶與營收。它的反面是真正獨立的產品（有自己的 &lt;a href="https://tarrragon.github.io/blog/business/knowledge-cards/fat-data-fat-skill/" data-link-title="Fat Data / Fat Skill" data-link-desc="說明獨家資料與行業隱性能力作為 AI 時代的護城河">Fat Data / Fat Skill&lt;/a> 護城河）。&lt;a href="https://tarrragon.github.io/blog/business/knowledge-cards/consolidation-cycle/" data-link-title="Consolidation Cycle" data-link-desc="說明整併週期的階段特徵">整併週期&lt;/a> 後段大量公司會走上 connector 化的路。&lt;/p>
&lt;h2 id="可觀察訊號與例子">可觀察訊號與例子&lt;/h2>
&lt;p>Connector 化的訊號：產品從 standalone app 變成「某某平台的 add-on」、定價變成按平台分潤、行銷渠道改成從平台市集導流、產品演進方向被大平台 roadmap 牽著走。許多被大平台併購的小新創走的就是這條路。&lt;/p>
&lt;h2 id="判讀方式">判讀方式&lt;/h2>
&lt;p>讀到「會被收進 ecosystem 變成 connector」時，意味著該產品還有一定價值（不至於被完全殺死），但獨立公司的空間沒了。對新創創辦人來說，這是「被併購」的另一種說法；對使用者來說，意味著該工具的長期演進會被大平台的優先順序綁定，創新速度通常會慢下來。&lt;/p></description><content:encoded><![CDATA[<p>Connector 的核心概念是「被收編進大平台的生態系變成上面的整合工具」。原本是獨立產品的公司，被併購或主動加入後變成大平台的 plug-in 或 integration。Zapier 的數千個 connector、Salesforce AppExchange 的 app 都屬此類。Connector 是 <a href="/blog/business/knowledge-cards/thin-wrapper/" data-link-title="Thin Wrapper" data-link-desc="說明薄包裝產品的脆弱性">Thin Wrapper</a> 不被殺死的另一條路。</p>
<h2 id="概念位置">概念位置</h2>
<p>Connector 化是新創生命週期的一種終局狀態—雖然失去獨立生意，但保住一部分用戶與營收。它的反面是真正獨立的產品（有自己的 <a href="/blog/business/knowledge-cards/fat-data-fat-skill/" data-link-title="Fat Data / Fat Skill" data-link-desc="說明獨家資料與行業隱性能力作為 AI 時代的護城河">Fat Data / Fat Skill</a> 護城河）。<a href="/blog/business/knowledge-cards/consolidation-cycle/" data-link-title="Consolidation Cycle" data-link-desc="說明整併週期的階段特徵">整併週期</a> 後段大量公司會走上 connector 化的路。</p>
<h2 id="可觀察訊號與例子">可觀察訊號與例子</h2>
<p>Connector 化的訊號：產品從 standalone app 變成「某某平台的 add-on」、定價變成按平台分潤、行銷渠道改成從平台市集導流、產品演進方向被大平台 roadmap 牽著走。許多被大平台併購的小新創走的就是這條路。</p>
<h2 id="判讀方式">判讀方式</h2>
<p>讀到「會被收進 ecosystem 變成 connector」時，意味著該產品還有一定價值（不至於被完全殺死），但獨立公司的空間沒了。對新創創辦人來說，這是「被併購」的另一種說法；對使用者來說，意味著該工具的長期演進會被大平台的優先順序綁定，創新速度通常會慢下來。</p>
]]></content:encoded></item><item><title>S3</title><link>https://tarrragon.github.io/blog/infra/knowledge-cards/s3/</link><pubDate>Fri, 26 Jun 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/infra/knowledge-cards/s3/</guid><description>&lt;p>S3（Simple Storage Service）是 AWS 的物件儲存服務。每個檔案（object）放在一個 bucket 裡、用 key（路徑）定址。S3 的持久性設計為 99.999999999%（11 個 9），資料自動跨多個可用區複製，不需要手動備份 S3 本身——要保護的是「物件被覆寫或刪除」的風險，而非「S3 服務掛掉」的風險。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>S3 在 infra 系列裡有三個角色：Terraform state 的存放處（remote state backend）、應用程式的靜態檔案儲存（上傳內容、備份歸檔）、以及 log 的長期保存目的地。模組一（state backend）、模組五（storage）、模組八（治理）都涉及 S3。&lt;/p>
&lt;h2 id="可觀察訊號">可觀察訊號&lt;/h2>
&lt;p>需要理解 S3 的情境包括：設定 Terraform 的 remote state backend、管理使用者上傳的檔案、設計備份歸檔策略、或評估儲存成本。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>使用 S3 時要決定的關鍵設定：&lt;/p>
&lt;table>
 &lt;thead>
 &lt;tr>
 &lt;th>設定&lt;/th>
 &lt;th>決定什麼&lt;/th>
 &lt;th>影響&lt;/th>
 &lt;/tr>
 &lt;/thead>
 &lt;tbody>
 &lt;tr>
 &lt;td>versioning&lt;/td>
 &lt;td>是否保留物件的歷史版本&lt;/td>
 &lt;td>覆寫或刪除後能回溯（state bucket 必開）&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>encryption&lt;/td>
 &lt;td>靜態加密方式（SSE-S3 / SSE-KMS）&lt;/td>
 &lt;td>合規與金鑰管理&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>public access block&lt;/td>
 &lt;td>是否封鎖公開存取&lt;/td>
 &lt;td>安全（預設全封鎖）&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>lifecycle rules&lt;/td>
 &lt;td>自動移到低成本儲存類或過期刪除&lt;/td>
 &lt;td>成本控制（如 30 天後移到 Glacier）&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>bucket policy&lt;/td>
 &lt;td>跨帳號或跨服務的存取規則&lt;/td>
 &lt;td>權限邊界&lt;/td>
 &lt;/tr>
 &lt;/tbody>
&lt;/table>
&lt;p>versioning 開啟後，刪除物件只是加一個 delete marker、實際資料還在。要真正刪除需要刪除 delete marker 和所有歷史版本。這是保護 state 檔的關鍵機制——誤寫 state 後可以回捲到上一個版本。&lt;/p>
&lt;h2 id="鄰卡">鄰卡&lt;/h2>
&lt;ul>
&lt;li>&lt;a href="https://tarrragon.github.io/blog/infra/knowledge-cards/remote-state-backend/" data-link-title="Remote State Backend" data-link-desc="把 Terraform state 從本地搬到團隊共享儲存的機制，同時滿足持久保存、並行鎖與敏感值保護">Remote State Backend&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://tarrragon.github.io/blog/infra/knowledge-cards/deletion-protection/" data-link-title="Deletion Protection" data-link-desc="雲端平台提供的防誤刪機制，開啟後刪除操作需要先顯式關閉保護才能執行">Deletion Protection&lt;/a>&lt;/li>
&lt;/ul></description><content:encoded><![CDATA[<p>S3（Simple Storage Service）是 AWS 的物件儲存服務。每個檔案（object）放在一個 bucket 裡、用 key（路徑）定址。S3 的持久性設計為 99.999999999%（11 個 9），資料自動跨多個可用區複製，不需要手動備份 S3 本身——要保護的是「物件被覆寫或刪除」的風險，而非「S3 服務掛掉」的風險。</p>
<h2 id="概念位置">概念位置</h2>
<p>S3 在 infra 系列裡有三個角色：Terraform state 的存放處（remote state backend）、應用程式的靜態檔案儲存（上傳內容、備份歸檔）、以及 log 的長期保存目的地。模組一（state backend）、模組五（storage）、模組八（治理）都涉及 S3。</p>
<h2 id="可觀察訊號">可觀察訊號</h2>
<p>需要理解 S3 的情境包括：設定 Terraform 的 remote state backend、管理使用者上傳的檔案、設計備份歸檔策略、或評估儲存成本。</p>
<h2 id="設計責任">設計責任</h2>
<p>使用 S3 時要決定的關鍵設定：</p>
<table>
  <thead>
      <tr>
          <th>設定</th>
          <th>決定什麼</th>
          <th>影響</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>versioning</td>
          <td>是否保留物件的歷史版本</td>
          <td>覆寫或刪除後能回溯（state bucket 必開）</td>
      </tr>
      <tr>
          <td>encryption</td>
          <td>靜態加密方式（SSE-S3 / SSE-KMS）</td>
          <td>合規與金鑰管理</td>
      </tr>
      <tr>
          <td>public access block</td>
          <td>是否封鎖公開存取</td>
          <td>安全（預設全封鎖）</td>
      </tr>
      <tr>
          <td>lifecycle rules</td>
          <td>自動移到低成本儲存類或過期刪除</td>
          <td>成本控制（如 30 天後移到 Glacier）</td>
      </tr>
      <tr>
          <td>bucket policy</td>
          <td>跨帳號或跨服務的存取規則</td>
          <td>權限邊界</td>
      </tr>
  </tbody>
</table>
<p>versioning 開啟後，刪除物件只是加一個 delete marker、實際資料還在。要真正刪除需要刪除 delete marker 和所有歷史版本。這是保護 state 檔的關鍵機制——誤寫 state 後可以回捲到上一個版本。</p>
<h2 id="鄰卡">鄰卡</h2>
<ul>
<li><a href="/blog/infra/knowledge-cards/remote-state-backend/" data-link-title="Remote State Backend" data-link-desc="把 Terraform state 從本地搬到團隊共享儲存的機制，同時滿足持久保存、並行鎖與敏感值保護">Remote State Backend</a></li>
<li><a href="/blog/infra/knowledge-cards/deletion-protection/" data-link-title="Deletion Protection" data-link-desc="雲端平台提供的防誤刪機制，開啟後刪除操作需要先顯式關閉保護才能執行">Deletion Protection</a></li>
</ul>
]]></content:encoded></item><item><title>EC2</title><link>https://tarrragon.github.io/blog/infra/knowledge-cards/ec2/</link><pubDate>Fri, 26 Jun 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/infra/knowledge-cards/ec2/</guid><description>&lt;p>EC2（Elastic Compute Cloud）是 AWS 提供的虛擬機器服務。每一台 EC2 instance 是一台完整的虛擬伺服器——有自己的 OS、CPU、記憶體、磁碟和網路介面。使用者可以 SSH 進去、安裝軟體、跑應用程式，跟操作一台實體伺服器的體驗相似。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>EC2 是 infra 系列中「運算」面向的基礎單位。容器服務（ECS、EKS）底層也跑在 EC2 上（除非用 Fargate）。模組五（核心服務）的運算段落、接手維運（雲端篇）的 VM 快照、升級模組的 OS 遷移都以 EC2 為操作對象。&lt;/p>
&lt;h2 id="可觀察訊號">可觀察訊號&lt;/h2>
&lt;p>需要理解 EC2 的情境包括：接手一個跑在 VM 上的應用程式、評估容器化 vs VM 部署、設定 auto-scaling、或建立 AMI 快照作為備份。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>一台 EC2 instance 由五個組件構成：&lt;/p>
&lt;table>
 &lt;thead>
 &lt;tr>
 &lt;th>組件&lt;/th>
 &lt;th>角色&lt;/th>
 &lt;th>選型判準&lt;/th>
 &lt;/tr>
 &lt;/thead>
 &lt;tbody>
 &lt;tr>
 &lt;td>AMI&lt;/td>
 &lt;td>作業系統映像（Ubuntu、Amazon Linux 等）&lt;/td>
 &lt;td>OS 偏好、軟體預裝需求&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>Instance type&lt;/td>
 &lt;td>CPU / 記憶體規格（t3.micro、m6i.large 等）&lt;/td>
 &lt;td>工作負載的 CPU 和記憶體需求&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>EBS&lt;/td>
 &lt;td>持久化磁碟&lt;/td>
 &lt;td>容量、IOPS、是否需要加密&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>Security group&lt;/td>
 &lt;td>網路防火牆規則&lt;/td>
 &lt;td>哪些 port 開放、來源限制&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>IAM role&lt;/td>
 &lt;td>instance 的雲端權限&lt;/td>
 &lt;td>需要存取哪些 AWS 服務&lt;/td>
 &lt;/tr>
 &lt;/tbody>
&lt;/table>
&lt;p>跟容器（ECS / EKS）的差別：EC2 管整台 VM（含 OS 更新、安全性修補、磁碟管理），容器只管應用程式及其依賴。EC2 的運維負擔較高、但控制粒度也較高。&lt;/p>
&lt;h2 id="鄰卡">鄰卡&lt;/h2>
&lt;ul>
&lt;li>&lt;a href="https://tarrragon.github.io/blog/infra/knowledge-cards/ami/" data-link-title="AMI" data-link-desc="EC2 instance 的作業系統映像快照，包含 OS、軟體、設定與磁碟內容，從 AMI 開出的 instance 跟原始狀態一樣">AMI&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://tarrragon.github.io/blog/infra/knowledge-cards/ecs/" data-link-title="ECS" data-link-desc="AWS Elastic Container Service — 受管的容器編排服務，用 task definition 描述容器配置、由平台負責排程與健康管理">ECS&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://tarrragon.github.io/blog/infra/knowledge-cards/subnet/" data-link-title="Subnet（子網路）" data-link-desc="VPC 內按可用區與暴露程度切出的子網段，決定資源有沒有一條通往網際網路的路徑">Subnet&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://tarrragon.github.io/blog/infra/knowledge-cards/security-group/" data-link-title="Security Group" data-link-desc="掛在資源網卡層級的有狀態防火牆，逐埠決定哪些來源能連進這個資源">Security Group&lt;/a>&lt;/li>
&lt;/ul></description><content:encoded><![CDATA[<p>EC2（Elastic Compute Cloud）是 AWS 提供的虛擬機器服務。每一台 EC2 instance 是一台完整的虛擬伺服器——有自己的 OS、CPU、記憶體、磁碟和網路介面。使用者可以 SSH 進去、安裝軟體、跑應用程式，跟操作一台實體伺服器的體驗相似。</p>
<h2 id="概念位置">概念位置</h2>
<p>EC2 是 infra 系列中「運算」面向的基礎單位。容器服務（ECS、EKS）底層也跑在 EC2 上（除非用 Fargate）。模組五（核心服務）的運算段落、接手維運（雲端篇）的 VM 快照、升級模組的 OS 遷移都以 EC2 為操作對象。</p>
<h2 id="可觀察訊號">可觀察訊號</h2>
<p>需要理解 EC2 的情境包括：接手一個跑在 VM 上的應用程式、評估容器化 vs VM 部署、設定 auto-scaling、或建立 AMI 快照作為備份。</p>
<h2 id="設計責任">設計責任</h2>
<p>一台 EC2 instance 由五個組件構成：</p>
<table>
  <thead>
      <tr>
          <th>組件</th>
          <th>角色</th>
          <th>選型判準</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>AMI</td>
          <td>作業系統映像（Ubuntu、Amazon Linux 等）</td>
          <td>OS 偏好、軟體預裝需求</td>
      </tr>
      <tr>
          <td>Instance type</td>
          <td>CPU / 記憶體規格（t3.micro、m6i.large 等）</td>
          <td>工作負載的 CPU 和記憶體需求</td>
      </tr>
      <tr>
          <td>EBS</td>
          <td>持久化磁碟</td>
          <td>容量、IOPS、是否需要加密</td>
      </tr>
      <tr>
          <td>Security group</td>
          <td>網路防火牆規則</td>
          <td>哪些 port 開放、來源限制</td>
      </tr>
      <tr>
          <td>IAM role</td>
          <td>instance 的雲端權限</td>
          <td>需要存取哪些 AWS 服務</td>
      </tr>
  </tbody>
</table>
<p>跟容器（ECS / EKS）的差別：EC2 管整台 VM（含 OS 更新、安全性修補、磁碟管理），容器只管應用程式及其依賴。EC2 的運維負擔較高、但控制粒度也較高。</p>
<h2 id="鄰卡">鄰卡</h2>
<ul>
<li><a href="/blog/infra/knowledge-cards/ami/" data-link-title="AMI" data-link-desc="EC2 instance 的作業系統映像快照，包含 OS、軟體、設定與磁碟內容，從 AMI 開出的 instance 跟原始狀態一樣">AMI</a></li>
<li><a href="/blog/infra/knowledge-cards/ecs/" data-link-title="ECS" data-link-desc="AWS Elastic Container Service — 受管的容器編排服務，用 task definition 描述容器配置、由平台負責排程與健康管理">ECS</a></li>
<li><a href="/blog/infra/knowledge-cards/subnet/" data-link-title="Subnet（子網路）" data-link-desc="VPC 內按可用區與暴露程度切出的子網段，決定資源有沒有一條通往網際網路的路徑">Subnet</a></li>
<li><a href="/blog/infra/knowledge-cards/security-group/" data-link-title="Security Group" data-link-desc="掛在資源網卡層級的有狀態防火牆，逐埠決定哪些來源能連進這個資源">Security Group</a></li>
</ul>
]]></content:encoded></item><item><title>EBS</title><link>https://tarrragon.github.io/blog/infra/knowledge-cards/ebs/</link><pubDate>Fri, 26 Jun 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/infra/knowledge-cards/ebs/</guid><description>&lt;p>EBS（Elastic Block Store）是 AWS 提供的區塊儲存服務——可以把它理解為掛在 EC2 instance 上的虛擬硬碟。EBS volume 跟 EC2 instance 的生命週期獨立：instance 停止或終止時，EBS volume 上的資料不會消失（除非明確設定 &lt;code>DeleteOnTermination&lt;/code>）。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>EBS 是 infra 系列中儲存面向的底層組件。RDS 的資料實際存在 EBS 上（由 AWS 代管）、EC2 的根磁碟和附加磁碟都是 EBS volume。接手維運時對 VM 做快照（AMI），背後就是在對 EBS volume 做 snapshot。&lt;/p>
&lt;h2 id="可觀察訊號">可觀察訊號&lt;/h2>
&lt;p>需要理解 EBS 的情境包括：EC2 instance 的磁碟快滿了需要擴容、要對 VM 做快照備份、評估磁碟效能（IOPS）是否足夠、或清理不再掛載的孤立 volume（殭屍 volume 持續計費）。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;table>
 &lt;thead>
 &lt;tr>
 &lt;th>設定&lt;/th>
 &lt;th>決定什麼&lt;/th>
 &lt;th>影響&lt;/th>
 &lt;/tr>
 &lt;/thead>
 &lt;tbody>
 &lt;tr>
 &lt;td>Volume type&lt;/td>
 &lt;td>gp3（通用）/ io2（高 IOPS）/ st1（高吞吐）&lt;/td>
 &lt;td>效能與成本&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>Size&lt;/td>
 &lt;td>磁碟容量（GB）&lt;/td>
 &lt;td>線上擴容可行、但縮小不行&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>Encryption&lt;/td>
 &lt;td>是否加密&lt;/td>
 &lt;td>合規（建立後不可更改，要加密只能建新的複製過去）&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>Snapshot&lt;/td>
 &lt;td>快照備份&lt;/td>
 &lt;td>EBS snapshot 是增量的（只存變更的區塊）&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>DeleteOnTermination&lt;/td>
 &lt;td>instance 終止時是否跟著刪除&lt;/td>
 &lt;td>根磁碟預設 true、附加磁碟預設 false&lt;/td>
 &lt;/tr>
 &lt;/tbody>
&lt;/table>
&lt;p>跟 instance store 的差別：instance store 是 EC2 實體主機上的臨時磁碟，效能高但 instance 停止資料就消失。EBS 是持久化儲存，instance 停止資料仍在。&lt;/p>
&lt;h2 id="鄰卡">鄰卡&lt;/h2>
&lt;ul>
&lt;li>&lt;a href="https://tarrragon.github.io/blog/infra/knowledge-cards/ec2/" data-link-title="EC2" data-link-desc="AWS 的虛擬機器服務，提供可隨時啟停的運算實例，組成包含 AMI、instance type、EBS、security group 與 IAM role">EC2&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://tarrragon.github.io/blog/infra/knowledge-cards/deletion-protection/" data-link-title="Deletion Protection" data-link-desc="雲端平台提供的防誤刪機制，開啟後刪除操作需要先顯式關閉保護才能執行">Deletion Protection&lt;/a>&lt;/li>
&lt;/ul></description><content:encoded><![CDATA[<p>EBS（Elastic Block Store）是 AWS 提供的區塊儲存服務——可以把它理解為掛在 EC2 instance 上的虛擬硬碟。EBS volume 跟 EC2 instance 的生命週期獨立：instance 停止或終止時，EBS volume 上的資料不會消失（除非明確設定 <code>DeleteOnTermination</code>）。</p>
<h2 id="概念位置">概念位置</h2>
<p>EBS 是 infra 系列中儲存面向的底層組件。RDS 的資料實際存在 EBS 上（由 AWS 代管）、EC2 的根磁碟和附加磁碟都是 EBS volume。接手維運時對 VM 做快照（AMI），背後就是在對 EBS volume 做 snapshot。</p>
<h2 id="可觀察訊號">可觀察訊號</h2>
<p>需要理解 EBS 的情境包括：EC2 instance 的磁碟快滿了需要擴容、要對 VM 做快照備份、評估磁碟效能（IOPS）是否足夠、或清理不再掛載的孤立 volume（殭屍 volume 持續計費）。</p>
<h2 id="設計責任">設計責任</h2>
<table>
  <thead>
      <tr>
          <th>設定</th>
          <th>決定什麼</th>
          <th>影響</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>Volume type</td>
          <td>gp3（通用）/ io2（高 IOPS）/ st1（高吞吐）</td>
          <td>效能與成本</td>
      </tr>
      <tr>
          <td>Size</td>
          <td>磁碟容量（GB）</td>
          <td>線上擴容可行、但縮小不行</td>
      </tr>
      <tr>
          <td>Encryption</td>
          <td>是否加密</td>
          <td>合規（建立後不可更改，要加密只能建新的複製過去）</td>
      </tr>
      <tr>
          <td>Snapshot</td>
          <td>快照備份</td>
          <td>EBS snapshot 是增量的（只存變更的區塊）</td>
      </tr>
      <tr>
          <td>DeleteOnTermination</td>
          <td>instance 終止時是否跟著刪除</td>
          <td>根磁碟預設 true、附加磁碟預設 false</td>
      </tr>
  </tbody>
</table>
<p>跟 instance store 的差別：instance store 是 EC2 實體主機上的臨時磁碟，效能高但 instance 停止資料就消失。EBS 是持久化儲存，instance 停止資料仍在。</p>
<h2 id="鄰卡">鄰卡</h2>
<ul>
<li><a href="/blog/infra/knowledge-cards/ec2/" data-link-title="EC2" data-link-desc="AWS 的虛擬機器服務，提供可隨時啟停的運算實例，組成包含 AMI、instance type、EBS、security group 與 IAM role">EC2</a></li>
<li><a href="/blog/infra/knowledge-cards/deletion-protection/" data-link-title="Deletion Protection" data-link-desc="雲端平台提供的防誤刪機制，開啟後刪除操作需要先顯式關閉保護才能執行">Deletion Protection</a></li>
</ul>
]]></content:encoded></item><item><title>HCL</title><link>https://tarrragon.github.io/blog/infra/knowledge-cards/hcl/</link><pubDate>Fri, 26 Jun 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/infra/knowledge-cards/hcl/</guid><description>&lt;p>HCL（HashiCorp Configuration Language）是 Terraform 和 OpenTofu 使用的設定語言。它用宣告式的 resource block 描述「環境應該長什麼樣」，由工具負責比對現況與描述、算出差異再套用。寫 HCL 的人描述目標狀態，不描述達到目標的步驟。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>HCL 是 infra 系列中 IaC 程式碼的語言層。IaC 卡講的是「用程式碼管理基礎設施」的概念，HCL 是這個概念落地時最常用的語言。模組一到八的所有 HCL 範例都用這個語言寫成。&lt;/p>
&lt;h2 id="可觀察訊號">可觀察訊號&lt;/h2>
&lt;p>需要理解 HCL 的情境包括：第一次打開一份 &lt;code>.tf&lt;/code> 檔案、要讀懂 Terraform 的 plan 輸出、要修改或新增一個 resource 定義、或要 review 別人的 infra PR。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>HCL 的基本結構：&lt;/p>





&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-hcl" data-lang="hcl">&lt;span class="line">&lt;span class="ln">1&lt;/span>&lt;span class="cl">&lt;span class="k">resource&lt;/span> &lt;span class="s2">&amp;#34;aws_s3_bucket&amp;#34; &amp;#34;example&amp;#34;&lt;/span> {
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">2&lt;/span>&lt;span class="cl">&lt;span class="n"> bucket&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="s2">&amp;#34;my-bucket&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">3&lt;/span>&lt;span class="cl">&lt;span class="n"> tags&lt;/span> &lt;span class="o">=&lt;/span>&lt;span class="n"> { env&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="s2">&amp;#34;prod&amp;#34;&lt;/span> }
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">4&lt;/span>&lt;span class="cl">}&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;ul>
&lt;li>&lt;code>resource&lt;/code>：宣告一個雲端資源&lt;/li>
&lt;li>&lt;code>&amp;quot;aws_s3_bucket&amp;quot;&lt;/code>：資源類型（由 provider 決定）&lt;/li>
&lt;li>&lt;code>&amp;quot;example&amp;quot;&lt;/code>：這個資源在程式碼裡的名稱（用來引用）&lt;/li>
&lt;li>&lt;code>{}&lt;/code>：這個資源的屬性&lt;/li>
&lt;/ul>
&lt;p>跟其他格式的差別：&lt;/p>
&lt;table>
 &lt;thead>
 &lt;tr>
 &lt;th>格式&lt;/th>
 &lt;th>特性&lt;/th>
 &lt;th>適合場景&lt;/th>
 &lt;/tr>
 &lt;/thead>
 &lt;tbody>
 &lt;tr>
 &lt;td>JSON / YAML&lt;/td>
 &lt;td>純資料格式、沒有邏輯&lt;/td>
 &lt;td>設定值、資料交換&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>HCL&lt;/td>
 &lt;td>支援變數、函式、條件、迴圈&lt;/td>
 &lt;td>基礎設施描述&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>TypeScript / Python&lt;/td>
 &lt;td>通用程式語言、完整邏輯&lt;/td>
 &lt;td>複雜的 infra 抽象（CDK / Pulumi）&lt;/td>
 &lt;/tr>
 &lt;/tbody>
&lt;/table>
&lt;p>HCL 的定位在 JSON 和通用語言之間——比 JSON 有表達力（能做迴圈和條件）、比通用語言好 review（diff 直觀、不需要在腦中「執行」程式碼才知道結果）。&lt;/p>
&lt;h2 id="鄰卡">鄰卡&lt;/h2>
&lt;ul>
&lt;li>&lt;a href="https://tarrragon.github.io/blog/infra/knowledge-cards/iac/" data-link-title="Infrastructure as Code (IaC)" data-link-desc="用程式碼描述基礎設施的最終狀態，由工具負責收斂現實與描述的差異">IaC&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://tarrragon.github.io/blog/infra/knowledge-cards/state/" data-link-title="State（IaC 狀態檔）" data-link-desc="IaC 工具用來記錄每個納管資源在雲端真實樣貌的快照，是比對差異與排定操作順序的依據">State&lt;/a>&lt;/li>
&lt;/ul></description><content:encoded><![CDATA[<p>HCL（HashiCorp Configuration Language）是 Terraform 和 OpenTofu 使用的設定語言。它用宣告式的 resource block 描述「環境應該長什麼樣」，由工具負責比對現況與描述、算出差異再套用。寫 HCL 的人描述目標狀態，不描述達到目標的步驟。</p>
<h2 id="概念位置">概念位置</h2>
<p>HCL 是 infra 系列中 IaC 程式碼的語言層。IaC 卡講的是「用程式碼管理基礎設施」的概念，HCL 是這個概念落地時最常用的語言。模組一到八的所有 HCL 範例都用這個語言寫成。</p>
<h2 id="可觀察訊號">可觀察訊號</h2>
<p>需要理解 HCL 的情境包括：第一次打開一份 <code>.tf</code> 檔案、要讀懂 Terraform 的 plan 輸出、要修改或新增一個 resource 定義、或要 review 別人的 infra PR。</p>
<h2 id="設計責任">設計責任</h2>
<p>HCL 的基本結構：</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-hcl" data-lang="hcl"><span class="line"><span class="ln">1</span><span class="cl"><span class="k">resource</span> <span class="s2">&#34;aws_s3_bucket&#34; &#34;example&#34;</span> {
</span></span><span class="line"><span class="ln">2</span><span class="cl"><span class="n">  bucket</span> <span class="o">=</span> <span class="s2">&#34;my-bucket&#34;</span>
</span></span><span class="line"><span class="ln">3</span><span class="cl"><span class="n">  tags</span>   <span class="o">=</span><span class="n"> { env</span> <span class="o">=</span> <span class="s2">&#34;prod&#34;</span> }
</span></span><span class="line"><span class="ln">4</span><span class="cl">}</span></span></code></pre></div><ul>
<li><code>resource</code>：宣告一個雲端資源</li>
<li><code>&quot;aws_s3_bucket&quot;</code>：資源類型（由 provider 決定）</li>
<li><code>&quot;example&quot;</code>：這個資源在程式碼裡的名稱（用來引用）</li>
<li><code>{}</code>：這個資源的屬性</li>
</ul>
<p>跟其他格式的差別：</p>
<table>
  <thead>
      <tr>
          <th>格式</th>
          <th>特性</th>
          <th>適合場景</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>JSON / YAML</td>
          <td>純資料格式、沒有邏輯</td>
          <td>設定值、資料交換</td>
      </tr>
      <tr>
          <td>HCL</td>
          <td>支援變數、函式、條件、迴圈</td>
          <td>基礎設施描述</td>
      </tr>
      <tr>
          <td>TypeScript / Python</td>
          <td>通用程式語言、完整邏輯</td>
          <td>複雜的 infra 抽象（CDK / Pulumi）</td>
      </tr>
  </tbody>
</table>
<p>HCL 的定位在 JSON 和通用語言之間——比 JSON 有表達力（能做迴圈和條件）、比通用語言好 review（diff 直觀、不需要在腦中「執行」程式碼才知道結果）。</p>
<h2 id="鄰卡">鄰卡</h2>
<ul>
<li><a href="/blog/infra/knowledge-cards/iac/" data-link-title="Infrastructure as Code (IaC)" data-link-desc="用程式碼描述基礎設施的最終狀態，由工具負責收斂現實與描述的差異">IaC</a></li>
<li><a href="/blog/infra/knowledge-cards/state/" data-link-title="State（IaC 狀態檔）" data-link-desc="IaC 工具用來記錄每個納管資源在雲端真實樣貌的快照，是比對差異與排定操作順序的依據">State</a></li>
</ul>
]]></content:encoded></item><item><title>terraform plan / apply</title><link>https://tarrragon.github.io/blog/infra/knowledge-cards/terraform-plan-apply/</link><pubDate>Fri, 26 Jun 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/infra/knowledge-cards/terraform-plan-apply/</guid><description>&lt;p>&lt;code>terraform plan&lt;/code> 和 &lt;code>terraform apply&lt;/code> 是 Terraform 操作基礎設施的兩個核心指令。plan 比對三方（state 檔、雲端現況、HCL 描述）產出差異報告，告訴使用者「如果 apply 會發生什麼」，但不做任何改動。apply 執行 plan 算出的差異，在雲端建立、修改或刪除資源。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>plan/apply 的分離是 IaC 可審查性的基礎。模組七（PR 流程）的核心機制就是「PR 觸發 plan → plan 結果貼回 PR → reviewer 看 plan 再決定要不要 apply」。這個「先看再動」的流程跟手動操作（直接在 Console 改）的根本差別。&lt;/p>
&lt;h2 id="可觀察訊號">可觀察訊號&lt;/h2>
&lt;p>需要理解 plan/apply 的情境包括：第一次跑 Terraform、review 別人的 infra PR（看 plan 輸出）、排查 drift（plan 在沒有 code 變更的情況下顯示差異）、或決定一次 apply 是否安全。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>plan 輸出的三種動作標記：&lt;/p>
&lt;table>
 &lt;thead>
 &lt;tr>
 &lt;th>標記&lt;/th>
 &lt;th>意義&lt;/th>
 &lt;th>風險&lt;/th>
 &lt;/tr>
 &lt;/thead>
 &lt;tbody>
 &lt;tr>
 &lt;td>&lt;code>+&lt;/code>&lt;/td>
 &lt;td>新增資源&lt;/td>
 &lt;td>低（新建不影響現有）&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;code>~&lt;/code>&lt;/td>
 &lt;td>修改資源（in-place update）&lt;/td>
 &lt;td>中（看改什麼，改 tag 低風險、改 instance type 可能重啟）&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;code>-/+&lt;/code>&lt;/td>
 &lt;td>先刪後建（forces replacement）&lt;/td>
 &lt;td>高（stateful 資源如 RDS 代表資料遺失）&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;code>-&lt;/code>&lt;/td>
 &lt;td>刪除資源&lt;/td>
 &lt;td>高（不可逆）&lt;/td>
 &lt;/tr>
 &lt;/tbody>
&lt;/table>
&lt;p>review plan 時最需要警惕的是 &lt;code>-/+&lt;/code>（forces replacement）——看起來只是改一個屬性，但某些屬性的修改會觸發資源重建（例如 RDS 的 &lt;code>identifier&lt;/code> 改名）。&lt;/p>
&lt;p>plan 與 apply 之間可能有時間差。如果 plan 之後、apply 之前有人手動改了雲端資源，apply 時的實際行為可能跟 plan 預期的不同。多數團隊在 apply 階段會重跑一次 plan 並要求結果一致。&lt;/p>
&lt;h2 id="鄰卡">鄰卡&lt;/h2>
&lt;ul>
&lt;li>&lt;a href="https://tarrragon.github.io/blog/infra/knowledge-cards/state/" data-link-title="State（IaC 狀態檔）" data-link-desc="IaC 工具用來記錄每個納管資源在雲端真實樣貌的快照，是比對差異與排定操作順序的依據">State&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://tarrragon.github.io/blog/infra/knowledge-cards/drift/" data-link-title="Drift（設定漂移）" data-link-desc="IaC 的 state 與雲端實際狀態之間的不一致，通常因為有人繞過 IaC 直接在 Console 改設定">Drift&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://tarrragon.github.io/blog/infra/knowledge-cards/iac/" data-link-title="Infrastructure as Code (IaC)" data-link-desc="用程式碼描述基礎設施的最終狀態，由工具負責收斂現實與描述的差異">IaC&lt;/a>&lt;/li>
&lt;/ul></description><content:encoded><![CDATA[<p><code>terraform plan</code> 和 <code>terraform apply</code> 是 Terraform 操作基礎設施的兩個核心指令。plan 比對三方（state 檔、雲端現況、HCL 描述）產出差異報告，告訴使用者「如果 apply 會發生什麼」，但不做任何改動。apply 執行 plan 算出的差異，在雲端建立、修改或刪除資源。</p>
<h2 id="概念位置">概念位置</h2>
<p>plan/apply 的分離是 IaC 可審查性的基礎。模組七（PR 流程）的核心機制就是「PR 觸發 plan → plan 結果貼回 PR → reviewer 看 plan 再決定要不要 apply」。這個「先看再動」的流程跟手動操作（直接在 Console 改）的根本差別。</p>
<h2 id="可觀察訊號">可觀察訊號</h2>
<p>需要理解 plan/apply 的情境包括：第一次跑 Terraform、review 別人的 infra PR（看 plan 輸出）、排查 drift（plan 在沒有 code 變更的情況下顯示差異）、或決定一次 apply 是否安全。</p>
<h2 id="設計責任">設計責任</h2>
<p>plan 輸出的三種動作標記：</p>
<table>
  <thead>
      <tr>
          <th>標記</th>
          <th>意義</th>
          <th>風險</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td><code>+</code></td>
          <td>新增資源</td>
          <td>低（新建不影響現有）</td>
      </tr>
      <tr>
          <td><code>~</code></td>
          <td>修改資源（in-place update）</td>
          <td>中（看改什麼，改 tag 低風險、改 instance type 可能重啟）</td>
      </tr>
      <tr>
          <td><code>-/+</code></td>
          <td>先刪後建（forces replacement）</td>
          <td>高（stateful 資源如 RDS 代表資料遺失）</td>
      </tr>
      <tr>
          <td><code>-</code></td>
          <td>刪除資源</td>
          <td>高（不可逆）</td>
      </tr>
  </tbody>
</table>
<p>review plan 時最需要警惕的是 <code>-/+</code>（forces replacement）——看起來只是改一個屬性，但某些屬性的修改會觸發資源重建（例如 RDS 的 <code>identifier</code> 改名）。</p>
<p>plan 與 apply 之間可能有時間差。如果 plan 之後、apply 之前有人手動改了雲端資源，apply 時的實際行為可能跟 plan 預期的不同。多數團隊在 apply 階段會重跑一次 plan 並要求結果一致。</p>
<h2 id="鄰卡">鄰卡</h2>
<ul>
<li><a href="/blog/infra/knowledge-cards/state/" data-link-title="State（IaC 狀態檔）" data-link-desc="IaC 工具用來記錄每個納管資源在雲端真實樣貌的快照，是比對差異與排定操作順序的依據">State</a></li>
<li><a href="/blog/infra/knowledge-cards/drift/" data-link-title="Drift（設定漂移）" data-link-desc="IaC 的 state 與雲端實際狀態之間的不一致，通常因為有人繞過 IaC 直接在 Console 改設定">Drift</a></li>
<li><a href="/blog/infra/knowledge-cards/iac/" data-link-title="Infrastructure as Code (IaC)" data-link-desc="用程式碼描述基礎設施的最終狀態，由工具負責收斂現實與描述的差異">IaC</a></li>
</ul>
]]></content:encoded></item><item><title>Red Ocean / Blue Ocean</title><link>https://tarrragon.github.io/blog/business/knowledge-cards/red-ocean-blue-ocean/</link><pubDate>Tue, 19 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/business/knowledge-cards/red-ocean-blue-ocean/</guid><description>&lt;p>Red Ocean / Blue Ocean 的核心概念是「賽道狀態的比喻」。Red Ocean（紅海）是已經被大家搶得頭破血流的成熟市場—價格戰、毛利低、整併進行中。Blue Ocean（藍海）是還沒人在的空白市場—需求待開發、利潤厚、競爭少。紅海後段會進入 &lt;a href="https://tarrragon.github.io/blog/business/knowledge-cards/consolidation-cycle/" data-link-title="Consolidation Cycle" data-link-desc="說明整併週期的階段特徵">整併週期&lt;/a>。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>Red / Blue Ocean 是市場動態的時間切片。藍海會隨時間變紅—第一個進入者吃到豐厚利潤後吸引競爭者，最終進入整併週期。判讀「現在進這個賽道」要先判讀它在哪個階段—紅海後段對新進者很不友善，除非有特殊 &lt;a href="https://tarrragon.github.io/blog/business/knowledge-cards/distribution/" data-link-title="Distribution" data-link-desc="說明分發優勢作為現有玩家的核心護城河">分發優勢&lt;/a> 或 &lt;a href="https://tarrragon.github.io/blog/business/knowledge-cards/fat-data-fat-skill/" data-link-title="Fat Data / Fat Skill" data-link-desc="說明獨家資料與行業隱性能力作為 AI 時代的護城河">Fat Data / Fat Skill&lt;/a>。&lt;/p>
&lt;h2 id="可觀察訊號與例子">可觀察訊號與例子&lt;/h2>
&lt;p>紅海訊號：玩家數量多、客戶選擇豐富、價格戰激烈、&lt;a href="https://tarrragon.github.io/blog/business/knowledge-cards/gross-margin/" data-link-title="Gross Margin" data-link-desc="說明毛利率與其對商業模式可行性的決定作用">毛利&lt;/a> 持續下降、開始出現整併新聞。串流訊息（Kafka 生態系）目前就是紅海—多家提供商打到開始互相收購。藍海訊號：客戶有需求但找不到產品、玩家少且不專業、毛利高得反常。&lt;/p>
&lt;h2 id="判讀方式">判讀方式&lt;/h2>
&lt;p>看到「打打發現餅其實沒那麼大」「進入殘酷的整併週期」時，是紅海後段的明確訊號。對新進者來說，紅海後段很難贏；對既有玩家來說，紅海是賣公司或被收購的時點。創業者要警覺「藍海可能比想像中更快變紅」—別把短期沒競爭者誤判成長期藍海。&lt;/p></description><content:encoded><![CDATA[<p>Red Ocean / Blue Ocean 的核心概念是「賽道狀態的比喻」。Red Ocean（紅海）是已經被大家搶得頭破血流的成熟市場—價格戰、毛利低、整併進行中。Blue Ocean（藍海）是還沒人在的空白市場—需求待開發、利潤厚、競爭少。紅海後段會進入 <a href="/blog/business/knowledge-cards/consolidation-cycle/" data-link-title="Consolidation Cycle" data-link-desc="說明整併週期的階段特徵">整併週期</a>。</p>
<h2 id="概念位置">概念位置</h2>
<p>Red / Blue Ocean 是市場動態的時間切片。藍海會隨時間變紅—第一個進入者吃到豐厚利潤後吸引競爭者，最終進入整併週期。判讀「現在進這個賽道」要先判讀它在哪個階段—紅海後段對新進者很不友善，除非有特殊 <a href="/blog/business/knowledge-cards/distribution/" data-link-title="Distribution" data-link-desc="說明分發優勢作為現有玩家的核心護城河">分發優勢</a> 或 <a href="/blog/business/knowledge-cards/fat-data-fat-skill/" data-link-title="Fat Data / Fat Skill" data-link-desc="說明獨家資料與行業隱性能力作為 AI 時代的護城河">Fat Data / Fat Skill</a>。</p>
<h2 id="可觀察訊號與例子">可觀察訊號與例子</h2>
<p>紅海訊號：玩家數量多、客戶選擇豐富、價格戰激烈、<a href="/blog/business/knowledge-cards/gross-margin/" data-link-title="Gross Margin" data-link-desc="說明毛利率與其對商業模式可行性的決定作用">毛利</a> 持續下降、開始出現整併新聞。串流訊息（Kafka 生態系）目前就是紅海—多家提供商打到開始互相收購。藍海訊號：客戶有需求但找不到產品、玩家少且不專業、毛利高得反常。</p>
<h2 id="判讀方式">判讀方式</h2>
<p>看到「打打發現餅其實沒那麼大」「進入殘酷的整併週期」時，是紅海後段的明確訊號。對新進者來說，紅海後段很難贏；對既有玩家來說，紅海是賣公司或被收購的時點。創業者要警覺「藍海可能比想像中更快變紅」—別把短期沒競爭者誤判成長期藍海。</p>
]]></content:encoded></item><item><title>AMI</title><link>https://tarrragon.github.io/blog/infra/knowledge-cards/ami/</link><pubDate>Fri, 26 Jun 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/infra/knowledge-cards/ami/</guid><description>&lt;p>AMI（Amazon Machine Image）是 EC2 instance 的完整映像快照。它包含作業系統、已安裝的軟體、設定檔、磁碟內容——從一個 AMI 啟動新的 instance，得到的是跟拍照時完全一樣的環境。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>AMI 在 infra 系列裡有兩個角色。第一個是接手維運時的保險——對 VM 建一個 AMI 等於把整台機器拍下來，做任何改動前都有一個可回退的基線。第二個是環境標準化——把裝好軟體的 instance 做成 AMI（golden image），之後開新機器都從這個 AMI 啟動，確保每台機器的基線一致。&lt;/p>
&lt;h2 id="可觀察訊號">可觀察訊號&lt;/h2>
&lt;p>需要理解 AMI 的情境包括：接手一台不確定裡面裝了什麼的 EC2（先拍 AMI 再動）、要在另一個 region 或帳號複製一台同樣的機器、OS 升級時要保留舊環境作為 rollback、或設計 auto-scaling 的 launch template（需要指定 AMI）。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;table>
 &lt;thead>
 &lt;tr>
 &lt;th>操作&lt;/th>
 &lt;th>用途&lt;/th>
 &lt;th>注意事項&lt;/th>
 &lt;/tr>
 &lt;/thead>
 &lt;tbody>
 &lt;tr>
 &lt;td>建立 AMI&lt;/td>
 &lt;td>對現有 instance 拍照&lt;/td>
 &lt;td>&lt;code>--no-reboot&lt;/code> 避免服務中斷，但檔案系統一致性略低&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>從 AMI 啟動 instance&lt;/td>
 &lt;td>複製環境&lt;/td>
 &lt;td>新 instance 有新的 IP、hostname、instance ID&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>跨 region 複製 AMI&lt;/td>
 &lt;td>災難復原或多 region 部署&lt;/td>
 &lt;td>複製是非同步的、完成後才能在目標 region 使用&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>共享 AMI&lt;/td>
 &lt;td>跨帳號使用同一個映像&lt;/td>
 &lt;td>需要設定 AMI 的 launch permission&lt;/td>
 &lt;/tr>
 &lt;/tbody>
&lt;/table>
&lt;p>AMI 包含 EBS snapshot——AMI 的儲存成本就是底層 EBS snapshot 的成本（按儲存量計費）。不再使用的 AMI 要記得 deregister 並刪除對應的 snapshot，否則持續計費。&lt;/p>
&lt;p>跟 container image 的差別：AMI 是整台 VM 的映像（含 OS、kernel、系統套件），container image 只包含應用程式和它的依賴（共用 host OS 的 kernel）。AMI 以 GB 計（通常 8-50 GB），container image 以 MB 計（通常 50-500 MB）。&lt;/p>
&lt;h2 id="鄰卡">鄰卡&lt;/h2>
&lt;ul>
&lt;li>&lt;a href="https://tarrragon.github.io/blog/infra/knowledge-cards/ec2/" data-link-title="EC2" data-link-desc="AWS 的虛擬機器服務，提供可隨時啟停的運算實例，組成包含 AMI、instance type、EBS、security group 與 IAM role">EC2&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://tarrragon.github.io/blog/infra/knowledge-cards/ebs/" data-link-title="EBS" data-link-desc="掛在 EC2 instance 上的持久化區塊儲存（虛擬磁碟），支援 snapshot 快照備份，跟 instance 獨立生命週期">EBS&lt;/a>&lt;/li>
&lt;/ul></description><content:encoded><![CDATA[<p>AMI（Amazon Machine Image）是 EC2 instance 的完整映像快照。它包含作業系統、已安裝的軟體、設定檔、磁碟內容——從一個 AMI 啟動新的 instance，得到的是跟拍照時完全一樣的環境。</p>
<h2 id="概念位置">概念位置</h2>
<p>AMI 在 infra 系列裡有兩個角色。第一個是接手維運時的保險——對 VM 建一個 AMI 等於把整台機器拍下來，做任何改動前都有一個可回退的基線。第二個是環境標準化——把裝好軟體的 instance 做成 AMI（golden image），之後開新機器都從這個 AMI 啟動，確保每台機器的基線一致。</p>
<h2 id="可觀察訊號">可觀察訊號</h2>
<p>需要理解 AMI 的情境包括：接手一台不確定裡面裝了什麼的 EC2（先拍 AMI 再動）、要在另一個 region 或帳號複製一台同樣的機器、OS 升級時要保留舊環境作為 rollback、或設計 auto-scaling 的 launch template（需要指定 AMI）。</p>
<h2 id="設計責任">設計責任</h2>
<table>
  <thead>
      <tr>
          <th>操作</th>
          <th>用途</th>
          <th>注意事項</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>建立 AMI</td>
          <td>對現有 instance 拍照</td>
          <td><code>--no-reboot</code> 避免服務中斷，但檔案系統一致性略低</td>
      </tr>
      <tr>
          <td>從 AMI 啟動 instance</td>
          <td>複製環境</td>
          <td>新 instance 有新的 IP、hostname、instance ID</td>
      </tr>
      <tr>
          <td>跨 region 複製 AMI</td>
          <td>災難復原或多 region 部署</td>
          <td>複製是非同步的、完成後才能在目標 region 使用</td>
      </tr>
      <tr>
          <td>共享 AMI</td>
          <td>跨帳號使用同一個映像</td>
          <td>需要設定 AMI 的 launch permission</td>
      </tr>
  </tbody>
</table>
<p>AMI 包含 EBS snapshot——AMI 的儲存成本就是底層 EBS snapshot 的成本（按儲存量計費）。不再使用的 AMI 要記得 deregister 並刪除對應的 snapshot，否則持續計費。</p>
<p>跟 container image 的差別：AMI 是整台 VM 的映像（含 OS、kernel、系統套件），container image 只包含應用程式和它的依賴（共用 host OS 的 kernel）。AMI 以 GB 計（通常 8-50 GB），container image 以 MB 計（通常 50-500 MB）。</p>
<h2 id="鄰卡">鄰卡</h2>
<ul>
<li><a href="/blog/infra/knowledge-cards/ec2/" data-link-title="EC2" data-link-desc="AWS 的虛擬機器服務，提供可隨時啟停的運算實例，組成包含 AMI、instance type、EBS、security group 與 IAM role">EC2</a></li>
<li><a href="/blog/infra/knowledge-cards/ebs/" data-link-title="EBS" data-link-desc="掛在 EC2 instance 上的持久化區塊儲存（虛擬磁碟），支援 snapshot 快照備份，跟 instance 獨立生命週期">EBS</a></li>
</ul>
]]></content:encoded></item><item><title>Consolidation Cycle</title><link>https://tarrragon.github.io/blog/business/knowledge-cards/consolidation-cycle/</link><pubDate>Tue, 19 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/business/knowledge-cards/consolidation-cycle/</guid><description>&lt;p>Consolidation Cycle 的核心概念是「產業整併週期」—市場成熟後玩家數量會從多到少、大公司併購小公司或小公司互相合併。早期百家爭鳴 → 成長放緩 → 小玩家活不下去 → 大公司整併 → 剩下少數幾家。整併是 &lt;a href="https://tarrragon.github.io/blog/business/knowledge-cards/red-ocean-blue-ocean/" data-link-title="Red Ocean / Blue Ocean" data-link-desc="說明紅海競爭與藍海空白的賽道狀態">Red Ocean&lt;/a> 的後段階段。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>Consolidation Cycle 通常伴隨 &lt;a href="https://tarrragon.github.io/blog/business/knowledge-cards/gross-margin/" data-link-title="Gross Margin" data-link-desc="說明毛利率與其對商業模式可行性的決定作用">毛利&lt;/a> 壓縮、&lt;a href="https://tarrragon.github.io/blog/business/knowledge-cards/cac/" data-link-title="CAC" data-link-desc="說明獲客成本及其對商業模式可行性的決定作用">CAC&lt;/a> 上升、&lt;a href="https://tarrragon.github.io/blog/business/knowledge-cards/venture-capital/" data-link-title="Venture Capital (VC)" data-link-desc="說明創投的投資邏輯與對新創估值的影響">融資&lt;/a> 環境變冷。整併本身會加速—因為被併購的小玩家會減少競爭、釋出客戶給剩下的玩家。整併後剩下的玩家通常有更強定價權。&lt;/p>
&lt;h2 id="可觀察訊號與例子">可觀察訊號與例子&lt;/h2>
&lt;p>整併週期的訊號：產業新聞密集出現 M&amp;amp;A、新公司獲得融資的金額下降、私募基金（&lt;a href="https://tarrragon.github.io/blog/business/knowledge-cards/private-equity/" data-link-title="Private Equity (PE)" data-link-desc="說明私募基金與其對中型企業市場的策略意涵">PE&lt;/a>）開始進場整合、剩下的玩家都在強調自己是「最後幾家」。Kafka 生態系的 Bufstream 被 CoreWeave 收購、WarpStream 被 Confluent 收購，就是典型整併訊號。&lt;/p>
&lt;h2 id="判讀方式">判讀方式&lt;/h2>
&lt;p>讀到「進入殘酷的整併週期」時，對新創創辦人是「該找買家還是該收掉」的訊號；對投資人是「現在進場估值會更便宜還是會被套」的判斷；對既有玩家是「該主動整合還是該被整合」的決策。整併週期過後，剩下的玩家通常能享受寡占的高毛利—但要先撐過整併本身。&lt;/p></description><content:encoded><![CDATA[<p>Consolidation Cycle 的核心概念是「產業整併週期」—市場成熟後玩家數量會從多到少、大公司併購小公司或小公司互相合併。早期百家爭鳴 → 成長放緩 → 小玩家活不下去 → 大公司整併 → 剩下少數幾家。整併是 <a href="/blog/business/knowledge-cards/red-ocean-blue-ocean/" data-link-title="Red Ocean / Blue Ocean" data-link-desc="說明紅海競爭與藍海空白的賽道狀態">Red Ocean</a> 的後段階段。</p>
<h2 id="概念位置">概念位置</h2>
<p>Consolidation Cycle 通常伴隨 <a href="/blog/business/knowledge-cards/gross-margin/" data-link-title="Gross Margin" data-link-desc="說明毛利率與其對商業模式可行性的決定作用">毛利</a> 壓縮、<a href="/blog/business/knowledge-cards/cac/" data-link-title="CAC" data-link-desc="說明獲客成本及其對商業模式可行性的決定作用">CAC</a> 上升、<a href="/blog/business/knowledge-cards/venture-capital/" data-link-title="Venture Capital (VC)" data-link-desc="說明創投的投資邏輯與對新創估值的影響">融資</a> 環境變冷。整併本身會加速—因為被併購的小玩家會減少競爭、釋出客戶給剩下的玩家。整併後剩下的玩家通常有更強定價權。</p>
<h2 id="可觀察訊號與例子">可觀察訊號與例子</h2>
<p>整併週期的訊號：產業新聞密集出現 M&amp;A、新公司獲得融資的金額下降、私募基金（<a href="/blog/business/knowledge-cards/private-equity/" data-link-title="Private Equity (PE)" data-link-desc="說明私募基金與其對中型企業市場的策略意涵">PE</a>）開始進場整合、剩下的玩家都在強調自己是「最後幾家」。Kafka 生態系的 Bufstream 被 CoreWeave 收購、WarpStream 被 Confluent 收購，就是典型整併訊號。</p>
<h2 id="判讀方式">判讀方式</h2>
<p>讀到「進入殘酷的整併週期」時，對新創創辦人是「該找買家還是該收掉」的訊號；對投資人是「現在進場估值會更便宜還是會被套」的判斷；對既有玩家是「該主動整合還是該被整合」的決策。整併週期過後，剩下的玩家通常能享受寡占的高毛利—但要先撐過整併本身。</p>
]]></content:encoded></item><item><title>Composer</title><link>https://tarrragon.github.io/blog/infra/knowledge-cards/composer/</link><pubDate>Fri, 26 Jun 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/infra/knowledge-cards/composer/</guid><description>&lt;p>Composer 是 PHP 的套件管理工具，角色等同於 Node.js 的 npm、Python 的 pip、Go 的 go mod。它負責宣告專案需要哪些第三方套件、鎖定每個套件的確切版本、以及把套件安裝到專案目錄裡。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>接手 PHP 專案時，Composer 是判斷「專案依賴了什麼、版本有沒有已知漏洞」的入口。專案根目錄通常有三個 Composer 相關的檔案：&lt;/p>
&lt;table>
 &lt;thead>
 &lt;tr>
 &lt;th>檔案&lt;/th>
 &lt;th>角色&lt;/th>
 &lt;th>進 Git？&lt;/th>
 &lt;/tr>
 &lt;/thead>
 &lt;tbody>
 &lt;tr>
 &lt;td>&lt;code>composer.json&lt;/code>&lt;/td>
 &lt;td>宣告依賴（套件名稱 + 版本範圍）&lt;/td>
 &lt;td>是&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;code>composer.lock&lt;/code>&lt;/td>
 &lt;td>鎖定確切版本（含所有 transitive 依賴）&lt;/td>
 &lt;td>是&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;code>vendor/&lt;/code>&lt;/td>
 &lt;td>安裝的套件目錄&lt;/td>
 &lt;td>否（.gitignore 排除、由 &lt;code>composer install&lt;/code> 重建）&lt;/td>
 &lt;/tr>
 &lt;/tbody>
&lt;/table>
&lt;h2 id="可觀察訊號">可觀察訊號&lt;/h2>
&lt;p>接手專案時如果根目錄有 &lt;code>composer.json&lt;/code> 但沒有 &lt;code>vendor/&lt;/code>，代表需要先跑 &lt;code>composer install&lt;/code> 才能讓專案運作。如果連 &lt;code>composer.lock&lt;/code> 都沒有，代表套件版本沒有鎖定——每次安裝可能拿到不同版本。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>兩個常用指令的差別：&lt;/p>
&lt;ul>
&lt;li>&lt;code>composer install&lt;/code>：按 &lt;code>composer.lock&lt;/code> 安裝確切版本。用於部署和接手——確保每台機器安裝的版本一致。&lt;/li>
&lt;li>&lt;code>composer update&lt;/code>：重新解析 &lt;code>composer.json&lt;/code> 的版本範圍、更新到最新的符合版本、改寫 &lt;code>composer.lock&lt;/code>。用於主動升級依賴。&lt;/li>
&lt;/ul>
&lt;p>接手時的關鍵操作：&lt;/p>
&lt;ul>
&lt;li>&lt;code>composer audit&lt;/code>：掃描已安裝套件的已知安全漏洞&lt;/li>
&lt;li>&lt;code>composer outdated&lt;/code>：列出可更新的套件及其最新版本&lt;/li>
&lt;/ul>
&lt;h2 id="鄰卡">鄰卡&lt;/h2>
&lt;ul>
&lt;li>&lt;a href="https://tarrragon.github.io/blog/infra/knowledge-cards/dotenv/" data-link-title=".env" data-link-desc="存放環境變數的純文字檔案，把機密值從程式碼分離出來">.env&lt;/a>：Composer 管套件、.env 管設定值，兩者都是 PHP 專案的基礎設施&lt;/li>
&lt;li>&lt;a href="https://tarrragon.github.io/blog/infra/knowledge-cards/php-ini/" data-link-title="php.ini / .user.ini" data-link-desc="PHP 的執行期設定檔，控制記憶體上限、上傳大小、錯誤報告等 runtime 行為">php.ini / .user.ini&lt;/a>：Composer 需要 PHP CLI 執行，php.ini 的 memory_limit 和 max_execution_time 會影響 Composer 能不能跑完&lt;/li>
&lt;/ul></description><content:encoded><![CDATA[<p>Composer 是 PHP 的套件管理工具，角色等同於 Node.js 的 npm、Python 的 pip、Go 的 go mod。它負責宣告專案需要哪些第三方套件、鎖定每個套件的確切版本、以及把套件安裝到專案目錄裡。</p>
<h2 id="概念位置">概念位置</h2>
<p>接手 PHP 專案時，Composer 是判斷「專案依賴了什麼、版本有沒有已知漏洞」的入口。專案根目錄通常有三個 Composer 相關的檔案：</p>
<table>
  <thead>
      <tr>
          <th>檔案</th>
          <th>角色</th>
          <th>進 Git？</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td><code>composer.json</code></td>
          <td>宣告依賴（套件名稱 + 版本範圍）</td>
          <td>是</td>
      </tr>
      <tr>
          <td><code>composer.lock</code></td>
          <td>鎖定確切版本（含所有 transitive 依賴）</td>
          <td>是</td>
      </tr>
      <tr>
          <td><code>vendor/</code></td>
          <td>安裝的套件目錄</td>
          <td>否（.gitignore 排除、由 <code>composer install</code> 重建）</td>
      </tr>
  </tbody>
</table>
<h2 id="可觀察訊號">可觀察訊號</h2>
<p>接手專案時如果根目錄有 <code>composer.json</code> 但沒有 <code>vendor/</code>，代表需要先跑 <code>composer install</code> 才能讓專案運作。如果連 <code>composer.lock</code> 都沒有，代表套件版本沒有鎖定——每次安裝可能拿到不同版本。</p>
<h2 id="設計責任">設計責任</h2>
<p>兩個常用指令的差別：</p>
<ul>
<li><code>composer install</code>：按 <code>composer.lock</code> 安裝確切版本。用於部署和接手——確保每台機器安裝的版本一致。</li>
<li><code>composer update</code>：重新解析 <code>composer.json</code> 的版本範圍、更新到最新的符合版本、改寫 <code>composer.lock</code>。用於主動升級依賴。</li>
</ul>
<p>接手時的關鍵操作：</p>
<ul>
<li><code>composer audit</code>：掃描已安裝套件的已知安全漏洞</li>
<li><code>composer outdated</code>：列出可更新的套件及其最新版本</li>
</ul>
<h2 id="鄰卡">鄰卡</h2>
<ul>
<li><a href="/blog/infra/knowledge-cards/dotenv/" data-link-title=".env" data-link-desc="存放環境變數的純文字檔案，把機密值從程式碼分離出來">.env</a>：Composer 管套件、.env 管設定值，兩者都是 PHP 專案的基礎設施</li>
<li><a href="/blog/infra/knowledge-cards/php-ini/" data-link-title="php.ini / .user.ini" data-link-desc="PHP 的執行期設定檔，控制記憶體上限、上傳大小、錯誤報告等 runtime 行為">php.ini / .user.ini</a>：Composer 需要 PHP CLI 執行，php.ini 的 memory_limit 和 max_execution_time 會影響 Composer 能不能跑完</li>
</ul>
]]></content:encoded></item><item><title>Niche Market</title><link>https://tarrragon.github.io/blog/business/knowledge-cards/niche-market/</link><pubDate>Tue, 19 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/business/knowledge-cards/niche-market/</guid><description>&lt;p>Niche Market 的核心概念是「利基市場」—不是大眾市場，但有特定需求、特定客戶輪廓、競爭較少的小眾領域。利基市場通常單一賽道規模小，但客戶願意付不錯的價格，且競爭者少。它是 &lt;a href="https://tarrragon.github.io/blog/business/knowledge-cards/vertical-saas/" data-link-title="Vertical SaaS" data-link-desc="說明專做單一行業的 SaaS 與其競爭策略">Vertical SaaS&lt;/a> 的天然舞台。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>Niche Market 的特徵是「高價值 + 高 &lt;a href="https://tarrragon.github.io/blog/business/knowledge-cards/high-stickiness/" data-link-title="High Stickiness" data-link-desc="說明高黏著度的形成條件">黏著度&lt;/a> + 小但夠用的市場」。它的 &lt;a href="https://tarrragon.github.io/blog/business/knowledge-cards/gross-margin/" data-link-title="Gross Margin" data-link-desc="說明毛利率與其對商業模式可行性的決定作用">毛利&lt;/a> 通常比大眾市場高，因為對手少、客戶替代品少。對投資人來說，niche market 的優點是競爭少、毛利高、&lt;a href="https://tarrragon.github.io/blog/business/knowledge-cards/retention/" data-link-title="Retention" data-link-desc="說明客戶留存率與其對單位經濟的決定作用">retention&lt;/a> 高；缺點是天花板低，難以長到 IPO 規模。&lt;/p>
&lt;h2 id="可觀察訊號與例子">可觀察訊號與例子&lt;/h2>
&lt;p>判讀利基市場的健康度：客戶數量是不是太少（總可服務市場太小）、單客單價是否能撐起一家公司、進入者是否被行業特殊性擋在外。Buf 的 Protobuf 工具就是利基市場—使用 Protobuf 的公司有限，但這些公司願意為專業工具付不錯的價格。Veeva（藥廠 SaaS）也是—藥廠數量有限，但每家年費上千萬美金。&lt;/p>
&lt;h2 id="判讀方式">判讀方式&lt;/h2>
&lt;p>看到「在高價值、高黏著度的利基市場站穩腳步」這類描述時，意味著該公司不打算搶大眾市場，而是在小但深的領域建立優勢。對 &lt;a href="https://tarrragon.github.io/blog/business/knowledge-cards/venture-capital/" data-link-title="Venture Capital (VC)" data-link-desc="說明創投的投資邏輯與對新創估值的影響">VC&lt;/a> 來說 niche market 不一定有興趣（看天花板）；對 &lt;a href="https://tarrragon.github.io/blog/business/knowledge-cards/private-equity/" data-link-title="Private Equity (PE)" data-link-desc="說明私募基金與其對中型企業市場的策略意涵">PE&lt;/a> 來說 niche market 反而很有吸引力（現金流穩定）。&lt;/p></description><content:encoded><![CDATA[<p>Niche Market 的核心概念是「利基市場」—不是大眾市場，但有特定需求、特定客戶輪廓、競爭較少的小眾領域。利基市場通常單一賽道規模小，但客戶願意付不錯的價格，且競爭者少。它是 <a href="/blog/business/knowledge-cards/vertical-saas/" data-link-title="Vertical SaaS" data-link-desc="說明專做單一行業的 SaaS 與其競爭策略">Vertical SaaS</a> 的天然舞台。</p>
<h2 id="概念位置">概念位置</h2>
<p>Niche Market 的特徵是「高價值 + 高 <a href="/blog/business/knowledge-cards/high-stickiness/" data-link-title="High Stickiness" data-link-desc="說明高黏著度的形成條件">黏著度</a> + 小但夠用的市場」。它的 <a href="/blog/business/knowledge-cards/gross-margin/" data-link-title="Gross Margin" data-link-desc="說明毛利率與其對商業模式可行性的決定作用">毛利</a> 通常比大眾市場高，因為對手少、客戶替代品少。對投資人來說，niche market 的優點是競爭少、毛利高、<a href="/blog/business/knowledge-cards/retention/" data-link-title="Retention" data-link-desc="說明客戶留存率與其對單位經濟的決定作用">retention</a> 高；缺點是天花板低，難以長到 IPO 規模。</p>
<h2 id="可觀察訊號與例子">可觀察訊號與例子</h2>
<p>判讀利基市場的健康度：客戶數量是不是太少（總可服務市場太小）、單客單價是否能撐起一家公司、進入者是否被行業特殊性擋在外。Buf 的 Protobuf 工具就是利基市場—使用 Protobuf 的公司有限，但這些公司願意為專業工具付不錯的價格。Veeva（藥廠 SaaS）也是—藥廠數量有限，但每家年費上千萬美金。</p>
<h2 id="判讀方式">判讀方式</h2>
<p>看到「在高價值、高黏著度的利基市場站穩腳步」這類描述時，意味著該公司不打算搶大眾市場，而是在小但深的領域建立優勢。對 <a href="/blog/business/knowledge-cards/venture-capital/" data-link-title="Venture Capital (VC)" data-link-desc="說明創投的投資邏輯與對新創估值的影響">VC</a> 來說 niche market 不一定有興趣（看天花板）；對 <a href="/blog/business/knowledge-cards/private-equity/" data-link-title="Private Equity (PE)" data-link-desc="說明私募基金與其對中型企業市場的策略意涵">PE</a> 來說 niche market 反而很有吸引力（現金流穩定）。</p>
]]></content:encoded></item><item><title>mysqldump</title><link>https://tarrragon.github.io/blog/infra/knowledge-cards/mysqldump/</link><pubDate>Fri, 26 Jun 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/infra/knowledge-cards/mysqldump/</guid><description>&lt;p>mysqldump 是 MySQL 和 MariaDB 內建的命令列備份工具，把整個資料庫（或指定的表）匯出成一份包含 CREATE TABLE 和 INSERT 語句的 SQL 純文字檔。還原時把這份檔案餵給 &lt;code>mysql&lt;/code> client 就能重建資料。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>mysqldump 是有 SSH 存取（或 remote MySQL 存取）時的主要備份手段。比 &lt;a href="https://tarrragon.github.io/blog/infra/knowledge-cards/phpmyadmin/" data-link-title="phpMyAdmin" data-link-desc="Web 介面的 MySQL / MariaDB 管理工具，透過瀏覽器操作資料庫">phpMyAdmin&lt;/a> 的匯出更可靠——不受 web server 的 timeout 和記憶體限制影響，可以處理數 GB 的資料庫。沒有 SSH 的環境只能退回 phpMyAdmin 匯出。&lt;/p>
&lt;h2 id="可觀察訊號">可觀察訊號&lt;/h2>
&lt;p>接手時如果 server 上有 &lt;a href="https://tarrragon.github.io/blog/infra/knowledge-cards/cron/" data-link-title="cron" data-link-desc="Unix/Linux 的排程工作系統，按時間表自動執行指令。接手維運時要盤點所有 cron job">cron&lt;/a> job 在跑 mysqldump，代表前任有做自動備份——確認輸出的 dump 檔案存在哪、保留幾天、有沒有被驗證過能還原。如果沒有任何 mysqldump cron，代表備份可能只靠 phpMyAdmin 手動匯出或完全沒做。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>常用的 flag 組合：&lt;/p>





&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-bash" data-lang="bash">&lt;span class="line">&lt;span class="ln">1&lt;/span>&lt;span class="cl">mysqldump -u user -p &lt;span class="se">\
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">2&lt;/span>&lt;span class="cl">&lt;span class="se">&lt;/span> --single-transaction &lt;span class="se">\
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">3&lt;/span>&lt;span class="cl">&lt;span class="se">&lt;/span> --routines &lt;span class="se">\
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">4&lt;/span>&lt;span class="cl">&lt;span class="se">&lt;/span> --triggers &lt;span class="se">\
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">5&lt;/span>&lt;span class="cl">&lt;span class="se">&lt;/span> dbname &amp;gt; dump-&lt;span class="k">$(&lt;/span>date +%Y%m%d&lt;span class="k">)&lt;/span>.sql&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;table>
 &lt;thead>
 &lt;tr>
 &lt;th>Flag&lt;/th>
 &lt;th>作用&lt;/th>
 &lt;/tr>
 &lt;/thead>
 &lt;tbody>
 &lt;tr>
 &lt;td>&lt;code>--single-transaction&lt;/code>&lt;/td>
 &lt;td>InnoDB 表不鎖表匯出（用一致性快照），生產備份必備&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;code>--routines&lt;/code>&lt;/td>
 &lt;td>含 stored procedure 和 function&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;code>--triggers&lt;/code>&lt;/td>
 &lt;td>含 trigger&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;code>--quick&lt;/code>&lt;/td>
 &lt;td>逐行讀取、不把整個表載入記憶體，大表必備&lt;/td>
 &lt;/tr>
 &lt;/tbody>
&lt;/table>
&lt;p>還原指令：&lt;/p>





&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-bash" data-lang="bash">&lt;span class="line">&lt;span class="ln">1&lt;/span>&lt;span class="cl">mysql -u user -p dbname &amp;lt; dump-20260626.sql&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>mysqldump 產出的是邏輯備份（SQL 語句），還原速度取決於資料量——幾百 MB 以內分鐘級，數 GB 可能要半小時以上。需要更快的備份/還原（物理備份），要用 Percona XtraBackup 或 MySQL Enterprise Backup。&lt;/p>
&lt;h2 id="鄰卡">鄰卡&lt;/h2>
&lt;ul>
&lt;li>&lt;a href="https://tarrragon.github.io/blog/infra/knowledge-cards/phpmyadmin/" data-link-title="phpMyAdmin" data-link-desc="Web 介面的 MySQL / MariaDB 管理工具，透過瀏覽器操作資料庫">phpMyAdmin&lt;/a>：無 SSH 時的替代備份手段&lt;/li>
&lt;li>&lt;a href="https://tarrragon.github.io/blog/infra/knowledge-cards/cron/" data-link-title="cron" data-link-desc="Unix/Linux 的排程工作系統，按時間表自動執行指令。接手維運時要盤點所有 cron job">cron&lt;/a>：搭配 cron 做定期自動備份&lt;/li>
&lt;/ul></description><content:encoded><![CDATA[<p>mysqldump 是 MySQL 和 MariaDB 內建的命令列備份工具，把整個資料庫（或指定的表）匯出成一份包含 CREATE TABLE 和 INSERT 語句的 SQL 純文字檔。還原時把這份檔案餵給 <code>mysql</code> client 就能重建資料。</p>
<h2 id="概念位置">概念位置</h2>
<p>mysqldump 是有 SSH 存取（或 remote MySQL 存取）時的主要備份手段。比 <a href="/blog/infra/knowledge-cards/phpmyadmin/" data-link-title="phpMyAdmin" data-link-desc="Web 介面的 MySQL / MariaDB 管理工具，透過瀏覽器操作資料庫">phpMyAdmin</a> 的匯出更可靠——不受 web server 的 timeout 和記憶體限制影響，可以處理數 GB 的資料庫。沒有 SSH 的環境只能退回 phpMyAdmin 匯出。</p>
<h2 id="可觀察訊號">可觀察訊號</h2>
<p>接手時如果 server 上有 <a href="/blog/infra/knowledge-cards/cron/" data-link-title="cron" data-link-desc="Unix/Linux 的排程工作系統，按時間表自動執行指令。接手維運時要盤點所有 cron job">cron</a> job 在跑 mysqldump，代表前任有做自動備份——確認輸出的 dump 檔案存在哪、保留幾天、有沒有被驗證過能還原。如果沒有任何 mysqldump cron，代表備份可能只靠 phpMyAdmin 手動匯出或完全沒做。</p>
<h2 id="設計責任">設計責任</h2>
<p>常用的 flag 組合：</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="ln">1</span><span class="cl">mysqldump -u user -p <span class="se">\
</span></span></span><span class="line"><span class="ln">2</span><span class="cl"><span class="se"></span>  --single-transaction <span class="se">\
</span></span></span><span class="line"><span class="ln">3</span><span class="cl"><span class="se"></span>  --routines <span class="se">\
</span></span></span><span class="line"><span class="ln">4</span><span class="cl"><span class="se"></span>  --triggers <span class="se">\
</span></span></span><span class="line"><span class="ln">5</span><span class="cl"><span class="se"></span>  dbname &gt; dump-<span class="k">$(</span>date +%Y%m%d<span class="k">)</span>.sql</span></span></code></pre></div><table>
  <thead>
      <tr>
          <th>Flag</th>
          <th>作用</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td><code>--single-transaction</code></td>
          <td>InnoDB 表不鎖表匯出（用一致性快照），生產備份必備</td>
      </tr>
      <tr>
          <td><code>--routines</code></td>
          <td>含 stored procedure 和 function</td>
      </tr>
      <tr>
          <td><code>--triggers</code></td>
          <td>含 trigger</td>
      </tr>
      <tr>
          <td><code>--quick</code></td>
          <td>逐行讀取、不把整個表載入記憶體，大表必備</td>
      </tr>
  </tbody>
</table>
<p>還原指令：</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="ln">1</span><span class="cl">mysql -u user -p dbname &lt; dump-20260626.sql</span></span></code></pre></div><p>mysqldump 產出的是邏輯備份（SQL 語句），還原速度取決於資料量——幾百 MB 以內分鐘級，數 GB 可能要半小時以上。需要更快的備份/還原（物理備份），要用 Percona XtraBackup 或 MySQL Enterprise Backup。</p>
<h2 id="鄰卡">鄰卡</h2>
<ul>
<li><a href="/blog/infra/knowledge-cards/phpmyadmin/" data-link-title="phpMyAdmin" data-link-desc="Web 介面的 MySQL / MariaDB 管理工具，透過瀏覽器操作資料庫">phpMyAdmin</a>：無 SSH 時的替代備份手段</li>
<li><a href="/blog/infra/knowledge-cards/cron/" data-link-title="cron" data-link-desc="Unix/Linux 的排程工作系統，按時間表自動執行指令。接手維運時要盤點所有 cron job">cron</a>：搭配 cron 做定期自動備份</li>
</ul>
]]></content:encoded></item><item><title>High Stickiness</title><link>https://tarrragon.github.io/blog/business/knowledge-cards/high-stickiness/</link><pubDate>Tue, 19 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/business/knowledge-cards/high-stickiness/</guid><description>&lt;p>High Stickiness 的核心概念是「高黏著度」—客戶一旦用了就很難換掉。High stickiness 通常由 &lt;a href="https://tarrragon.github.io/blog/business/knowledge-cards/lock-in/" data-link-title="Lock-in" data-link-desc="說明鎖定效應如何形成護城河">Lock-in&lt;/a>、&lt;a href="https://tarrragon.github.io/blog/business/knowledge-cards/switching-cost/" data-link-title="Switching Cost" data-link-desc="說明切換成本如何鞏固客戶留存">Switching Cost&lt;/a> 與深度整合構成；它的結果指標是高 &lt;a href="https://tarrragon.github.io/blog/business/knowledge-cards/retention/" data-link-title="Retention" data-link-desc="說明客戶留存率與其對單位經濟的決定作用">Retention&lt;/a>。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>Stickiness 跟 Retention、Lock-in、Switching Cost 是同一組概念群。Stickiness 是質性描述（客戶離不開），retention 是量化結果（續約率高），lock-in 是結構機制（為什麼離不開），switching cost 是換掉的痛點。四個概念合起來描述同一件事的不同面向。&lt;/p>
&lt;h2 id="可觀察訊號與例子">可觀察訊號與例子&lt;/h2>
&lt;p>判讀 stickiness：客戶用該產品多久？多少資料儲存在那？工作流程多深度依賴它？員工要多久訓練才會用？這些訊號加起來判讀 stickiness 強度。GitHub 的 stickiness 很高—工程師整個職涯的 commit history 都在那，要換到 GitLab 不只是搬程式碼，是搬掉個人品牌的一部分。&lt;/p>
&lt;h2 id="判讀方式">判讀方式&lt;/h2>
&lt;p>讀到「高價值、高黏著度的利基市場」時，意味著該市場進去就很難被打掉，但也意味著新進者進不去（客戶不會輕易換）。對既有玩家來說 high stickiness 是好消息；對新進者是壞消息—除非有顛覆性差異化（&lt;a href="https://tarrragon.github.io/blog/business/knowledge-cards/frontier-capability/" data-link-title="Frontier Capability" data-link-desc="說明前沿能力差距如何影響商業策略">Frontier Capability&lt;/a> 或全新工作流）。&lt;/p></description><content:encoded><![CDATA[<p>High Stickiness 的核心概念是「高黏著度」—客戶一旦用了就很難換掉。High stickiness 通常由 <a href="/blog/business/knowledge-cards/lock-in/" data-link-title="Lock-in" data-link-desc="說明鎖定效應如何形成護城河">Lock-in</a>、<a href="/blog/business/knowledge-cards/switching-cost/" data-link-title="Switching Cost" data-link-desc="說明切換成本如何鞏固客戶留存">Switching Cost</a> 與深度整合構成；它的結果指標是高 <a href="/blog/business/knowledge-cards/retention/" data-link-title="Retention" data-link-desc="說明客戶留存率與其對單位經濟的決定作用">Retention</a>。</p>
<h2 id="概念位置">概念位置</h2>
<p>Stickiness 跟 Retention、Lock-in、Switching Cost 是同一組概念群。Stickiness 是質性描述（客戶離不開），retention 是量化結果（續約率高），lock-in 是結構機制（為什麼離不開），switching cost 是換掉的痛點。四個概念合起來描述同一件事的不同面向。</p>
<h2 id="可觀察訊號與例子">可觀察訊號與例子</h2>
<p>判讀 stickiness：客戶用該產品多久？多少資料儲存在那？工作流程多深度依賴它？員工要多久訓練才會用？這些訊號加起來判讀 stickiness 強度。GitHub 的 stickiness 很高—工程師整個職涯的 commit history 都在那，要換到 GitLab 不只是搬程式碼，是搬掉個人品牌的一部分。</p>
<h2 id="判讀方式">判讀方式</h2>
<p>讀到「高價值、高黏著度的利基市場」時，意味著該市場進去就很難被打掉，但也意味著新進者進不去（客戶不會輕易換）。對既有玩家來說 high stickiness 是好消息；對新進者是壞消息—除非有顛覆性差異化（<a href="/blog/business/knowledge-cards/frontier-capability/" data-link-title="Frontier Capability" data-link-desc="說明前沿能力差距如何影響商業策略">Frontier Capability</a> 或全新工作流）。</p>
]]></content:encoded></item><item><title>Reverse Proxy</title><link>https://tarrragon.github.io/blog/infra/knowledge-cards/reverse-proxy/</link><pubDate>Fri, 26 Jun 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/infra/knowledge-cards/reverse-proxy/</guid><description>&lt;p>Reverse proxy 是一個坐在後端服務前面、代替它接收外部請求的中介層。外部 client 連的是 reverse proxy 的位址，reverse proxy 根據規則把請求轉發到實際處理的內部服務，再把回應傳回給 client。Client 不知道（也不需要知道）後面有幾台服務、跑在哪裡。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>nginx 和 &lt;a href="https://tarrragon.github.io/blog/infra/knowledge-cards/alb/" data-link-title="ALB" data-link-desc="Application Load Balancer — 流量進入系統的第一站，負責 listener 路由、健康檢查與 TLS 終結">ALB&lt;/a> 都扮演 reverse proxy 角色。差別在層級：nginx 通常部署在應用層（跟應用伺服器同一台或同一個 VPC 內），ALB 是雲端平台提供的受管服務。兩者的核心功能相同——接收外部流量、轉發到後端、回傳結果。&lt;/p>
&lt;p>跟 forward proxy 的方向相反：forward proxy 代替 client 發送請求（client 在內網、proxy 幫它出去）；reverse proxy 代替 server 接收請求（server 在內網、proxy 幫它面對外部）。&lt;/p>
&lt;h2 id="可觀察訊號">可觀察訊號&lt;/h2>
&lt;p>接手時如果 server 上跑著 nginx 但應用程式用的是 PHP-FPM 或 Node.js，nginx 多半扮演 reverse proxy——它接 HTTP/HTTPS 請求、轉發給後端的 application server。設定檔裡的 &lt;code>proxy_pass&lt;/code>（nginx）或 &lt;code>ProxyPass&lt;/code>（Apache）就是 reverse proxy 的轉發規則。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>reverse proxy 常承擔的功能：&lt;/p>
&lt;table>
 &lt;thead>
 &lt;tr>
 &lt;th>功能&lt;/th>
 &lt;th>說明&lt;/th>
 &lt;/tr>
 &lt;/thead>
 &lt;tbody>
 &lt;tr>
 &lt;td>TLS 終結&lt;/td>
 &lt;td>HTTPS 的加解密在 proxy 層處理，後端服務只收 HTTP&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>負載平衡&lt;/td>
 &lt;td>把請求分配到多台後端（round-robin、least-connection）&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>路由分流&lt;/td>
 &lt;td>依 URL path 導到不同後端服務（/api → backend、/ → frontend）&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>靜態檔案快取&lt;/td>
 &lt;td>圖片、CSS、JS 由 proxy 直接回應、不轉發到後端&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>安全過濾&lt;/td>
 &lt;td>擋掉異常請求、限制請求速率、加安全標頭&lt;/td>
 &lt;/tr>
 &lt;/tbody>
&lt;/table>
&lt;h2 id="鄰卡">鄰卡&lt;/h2>
&lt;ul>
&lt;li>&lt;a href="https://tarrragon.github.io/blog/infra/knowledge-cards/alb/" data-link-title="ALB" data-link-desc="Application Load Balancer — 流量進入系統的第一站，負責 listener 路由、健康檢查與 TLS 終結">ALB&lt;/a>：雲端的受管 reverse proxy + 負載平衡器&lt;/li>
&lt;li>&lt;a href="https://tarrragon.github.io/blog/infra/knowledge-cards/nginx/" data-link-title="nginx" data-link-desc="高效能 Web Server 與 Reverse Proxy，以集中設定檔取代 Apache 的 .htaccess 分散設定">nginx&lt;/a>：最常見的 reverse proxy 軟體&lt;/li>
&lt;/ul></description><content:encoded><![CDATA[<p>Reverse proxy 是一個坐在後端服務前面、代替它接收外部請求的中介層。外部 client 連的是 reverse proxy 的位址，reverse proxy 根據規則把請求轉發到實際處理的內部服務，再把回應傳回給 client。Client 不知道（也不需要知道）後面有幾台服務、跑在哪裡。</p>
<h2 id="概念位置">概念位置</h2>
<p>nginx 和 <a href="/blog/infra/knowledge-cards/alb/" data-link-title="ALB" data-link-desc="Application Load Balancer — 流量進入系統的第一站，負責 listener 路由、健康檢查與 TLS 終結">ALB</a> 都扮演 reverse proxy 角色。差別在層級：nginx 通常部署在應用層（跟應用伺服器同一台或同一個 VPC 內），ALB 是雲端平台提供的受管服務。兩者的核心功能相同——接收外部流量、轉發到後端、回傳結果。</p>
<p>跟 forward proxy 的方向相反：forward proxy 代替 client 發送請求（client 在內網、proxy 幫它出去）；reverse proxy 代替 server 接收請求（server 在內網、proxy 幫它面對外部）。</p>
<h2 id="可觀察訊號">可觀察訊號</h2>
<p>接手時如果 server 上跑著 nginx 但應用程式用的是 PHP-FPM 或 Node.js，nginx 多半扮演 reverse proxy——它接 HTTP/HTTPS 請求、轉發給後端的 application server。設定檔裡的 <code>proxy_pass</code>（nginx）或 <code>ProxyPass</code>（Apache）就是 reverse proxy 的轉發規則。</p>
<h2 id="設計責任">設計責任</h2>
<p>reverse proxy 常承擔的功能：</p>
<table>
  <thead>
      <tr>
          <th>功能</th>
          <th>說明</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>TLS 終結</td>
          <td>HTTPS 的加解密在 proxy 層處理，後端服務只收 HTTP</td>
      </tr>
      <tr>
          <td>負載平衡</td>
          <td>把請求分配到多台後端（round-robin、least-connection）</td>
      </tr>
      <tr>
          <td>路由分流</td>
          <td>依 URL path 導到不同後端服務（/api → backend、/ → frontend）</td>
      </tr>
      <tr>
          <td>靜態檔案快取</td>
          <td>圖片、CSS、JS 由 proxy 直接回應、不轉發到後端</td>
      </tr>
      <tr>
          <td>安全過濾</td>
          <td>擋掉異常請求、限制請求速率、加安全標頭</td>
      </tr>
  </tbody>
</table>
<h2 id="鄰卡">鄰卡</h2>
<ul>
<li><a href="/blog/infra/knowledge-cards/alb/" data-link-title="ALB" data-link-desc="Application Load Balancer — 流量進入系統的第一站，負責 listener 路由、健康檢查與 TLS 終結">ALB</a>：雲端的受管 reverse proxy + 負載平衡器</li>
<li><a href="/blog/infra/knowledge-cards/nginx/" data-link-title="nginx" data-link-desc="高效能 Web Server 與 Reverse Proxy，以集中設定檔取代 Apache 的 .htaccess 分散設定">nginx</a>：最常見的 reverse proxy 軟體</li>
</ul>
]]></content:encoded></item><item><title>Rigid Demand</title><link>https://tarrragon.github.io/blog/business/knowledge-cards/rigid-demand/</link><pubDate>Tue, 19 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/business/knowledge-cards/rigid-demand/</guid><description>&lt;p>Rigid Demand 的核心概念是「剛需」—客戶非要不可的需求，價格彈性低，砍預算時是最後砍的項目。相對概念是 nice-to-have（有更好、沒也不會死）。Rigid demand 是 &lt;a href="https://tarrragon.github.io/blog/business/knowledge-cards/saas/" data-link-title="SaaS" data-link-desc="說明雲端訂閱軟體的商業模式與經濟特徵">商業模式&lt;/a> 可持續性的根本。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>Rigid Demand 是判斷產品市場契合（PMF）的核心訊號。賣 rigid demand 的公司即使在景氣差時也活得下來，因為客戶不會省這筆錢。產品經理找方向時，「rigid demand 還是 nice-to-have」是必問問題；&lt;a href="https://tarrragon.github.io/blog/business/knowledge-cards/venture-capital/" data-link-title="Venture Capital (VC)" data-link-desc="說明創投的投資邏輯與對新創估值的影響">VC&lt;/a> 評估新創時也用這個維度做過濾。&lt;/p>
&lt;h2 id="可觀察訊號與例子">可觀察訊號與例子&lt;/h2>
&lt;p>判讀 rigid demand 的訊號：客戶在景氣差時是否仍續約、客戶是否願意接受漲價、客戶是否會主動推薦同行用。Buf 觀察到大客戶都「為了確保格式對而自己搭代理層」—這個自建行為本身就是 rigid demand 的訊號（如果不重要他們不會自己花人力做）。會計軟體、合規工具、薪資系統都是典型 rigid demand。&lt;/p>
&lt;h2 id="判讀方式">判讀方式&lt;/h2>
&lt;p>讀到「客戶有這個剛需」時，意味著該產品的需求被驗證是必要的，不是可選的。創辦人找產品方向時應該追 rigid demand，避開 nice-to-have；投資人評估新創時看「客戶用這產品多久」「砍預算時會不會砍」來判讀。Rigid demand 通常配高 &lt;a href="https://tarrragon.github.io/blog/business/knowledge-cards/retention/" data-link-title="Retention" data-link-desc="說明客戶留存率與其對單位經濟的決定作用">retention&lt;/a> 與穩定毛利。&lt;/p></description><content:encoded><![CDATA[<p>Rigid Demand 的核心概念是「剛需」—客戶非要不可的需求，價格彈性低，砍預算時是最後砍的項目。相對概念是 nice-to-have（有更好、沒也不會死）。Rigid demand 是 <a href="/blog/business/knowledge-cards/saas/" data-link-title="SaaS" data-link-desc="說明雲端訂閱軟體的商業模式與經濟特徵">商業模式</a> 可持續性的根本。</p>
<h2 id="概念位置">概念位置</h2>
<p>Rigid Demand 是判斷產品市場契合（PMF）的核心訊號。賣 rigid demand 的公司即使在景氣差時也活得下來，因為客戶不會省這筆錢。產品經理找方向時，「rigid demand 還是 nice-to-have」是必問問題；<a href="/blog/business/knowledge-cards/venture-capital/" data-link-title="Venture Capital (VC)" data-link-desc="說明創投的投資邏輯與對新創估值的影響">VC</a> 評估新創時也用這個維度做過濾。</p>
<h2 id="可觀察訊號與例子">可觀察訊號與例子</h2>
<p>判讀 rigid demand 的訊號：客戶在景氣差時是否仍續約、客戶是否願意接受漲價、客戶是否會主動推薦同行用。Buf 觀察到大客戶都「為了確保格式對而自己搭代理層」—這個自建行為本身就是 rigid demand 的訊號（如果不重要他們不會自己花人力做）。會計軟體、合規工具、薪資系統都是典型 rigid demand。</p>
<h2 id="判讀方式">判讀方式</h2>
<p>讀到「客戶有這個剛需」時，意味著該產品的需求被驗證是必要的，不是可選的。創辦人找產品方向時應該追 rigid demand，避開 nice-to-have；投資人評估新創時看「客戶用這產品多久」「砍預算時會不會砍」來判讀。Rigid demand 通常配高 <a href="/blog/business/knowledge-cards/retention/" data-link-title="Retention" data-link-desc="說明客戶留存率與其對單位經濟的決定作用">retention</a> 與穩定毛利。</p>
]]></content:encoded></item><item><title>Database Migration</title><link>https://tarrragon.github.io/blog/infra/knowledge-cards/database-migration/</link><pubDate>Fri, 26 Jun 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/infra/knowledge-cards/database-migration/</guid><description>&lt;p>Database migration 是用版本化的腳本管理資料庫 schema 變更的做法。每次 schema 變更（加欄位、改索引、拆表、改資料型別）寫成一份獨立的 migration 檔案，按順序套用。這讓 schema 的演進跟程式碼一樣有版本歷史、可追蹤、可在新環境重現。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>migration 解決的問題是「資料庫的 schema 怎麼從 A 狀態安全地變成 B 狀態」。沒有 migration 時，schema 變更靠在 &lt;a href="https://tarrragon.github.io/blog/infra/knowledge-cards/phpmyadmin/" data-link-title="phpMyAdmin" data-link-desc="Web 介面的 MySQL / MariaDB 管理工具，透過瀏覽器操作資料庫">phpMyAdmin&lt;/a> 或 CLI 手動執行 SQL，改了什麼只存在操作者的記憶裡。有 migration 時，每次變更都是 repo 裡的一份檔案，跟程式碼一起 commit、一起 review。&lt;/p>
&lt;h2 id="可觀察訊號">可觀察訊號&lt;/h2>
&lt;p>接手專案時，如果 repo 裡有 &lt;code>migrations/&lt;/code> 目錄（或框架特定的路徑如 Laravel 的 &lt;code>database/migrations/&lt;/code>、Rails 的 &lt;code>db/migrate/&lt;/code>），代表專案使用 migration。如果 repo 裡只有一份 &lt;code>schema.sql&lt;/code> 或完全沒有 schema 相關檔案，代表 schema 變更是手動的——這時候建立 migration 紀律是接手後的優先事項之一。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>每份 migration 檔案包含兩個方向：&lt;/p>
&lt;ul>
&lt;li>&lt;strong>UP&lt;/strong>（套用）：執行 schema 變更的 SQL&lt;/li>
&lt;li>&lt;strong>DOWN&lt;/strong>（回退）：撤銷這次變更的 SQL（不是所有變更都能完美回退，如刪除欄位後資料就沒了）&lt;/li>
&lt;/ul>





&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-sql" data-lang="sql">&lt;span class="line">&lt;span class="ln">1&lt;/span>&lt;span class="cl">&lt;span class="c1">-- migrations/2026-06-26-001-add-users-email-verified.sql
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">2&lt;/span>&lt;span class="cl">&lt;span class="c1">&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">3&lt;/span>&lt;span class="cl">&lt;span class="w">&lt;/span>&lt;span class="c1">-- UP
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">4&lt;/span>&lt;span class="cl">&lt;span class="c1">&lt;/span>&lt;span class="k">ALTER&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="k">TABLE&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">users&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="k">ADD&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="k">COLUMN&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">email_verified&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="nb">BOOLEAN&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="k">DEFAULT&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="k">FALSE&lt;/span>&lt;span class="p">;&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">5&lt;/span>&lt;span class="cl">&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">6&lt;/span>&lt;span class="cl">&lt;span class="w">&lt;/span>&lt;span class="c1">-- DOWN
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">7&lt;/span>&lt;span class="cl">&lt;span class="c1">&lt;/span>&lt;span class="k">ALTER&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="k">TABLE&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">users&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="k">DROP&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="k">COLUMN&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">email_verified&lt;/span>&lt;span class="p">;&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>常用的 migration 工具：&lt;/p>
&lt;table>
 &lt;thead>
 &lt;tr>
 &lt;th>工具&lt;/th>
 &lt;th>語言 / 框架&lt;/th>
 &lt;/tr>
 &lt;/thead>
 &lt;tbody>
 &lt;tr>
 &lt;td>Laravel Migration&lt;/td>
 &lt;td>PHP / Laravel&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>Rails Migration&lt;/td>
 &lt;td>Ruby / Rails&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>Flyway&lt;/td>
 &lt;td>Java / 跨語言（純 SQL）&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>Liquibase&lt;/td>
 &lt;td>Java / 跨語言（XML / YAML / SQL）&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>golang-migrate&lt;/td>
 &lt;td>Go&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>手動 SQL 檔案&lt;/td>
 &lt;td>無框架時的最低限度方案&lt;/td>
 &lt;/tr>
 &lt;/tbody>
&lt;/table>
&lt;p>沒有框架時，用日期 + 序號命名 SQL 檔案（&lt;code>2026-06-26-001-描述.sql&lt;/code>），搭配一張 &lt;code>migration_log&lt;/code> 表記錄哪些已經套用過，就是最低限度的 migration 系統。&lt;/p>
&lt;h2 id="鄰卡">鄰卡&lt;/h2>
&lt;ul>
&lt;li>&lt;a href="https://tarrragon.github.io/blog/infra/knowledge-cards/rds/" data-link-title="RDS" data-link-desc="AWS 的受管關聯式資料庫服務，代管備份、更新與 failover，讓使用者專注在 schema 和查詢">RDS&lt;/a>：migration 在 production 資料庫上執行時要格外小心——大表的 ALTER TABLE 可能鎖表&lt;/li>
&lt;li>&lt;a href="https://tarrragon.github.io/blog/infra/knowledge-cards/mysqldump/" data-link-title="mysqldump" data-link-desc="MySQL / MariaDB 的 CLI 備份工具，把資料庫匯出成 SQL 語句的純文字檔">mysqldump&lt;/a>：執行 migration 前先做一次完整備份&lt;/li>
&lt;/ul></description><content:encoded><![CDATA[<p>Database migration 是用版本化的腳本管理資料庫 schema 變更的做法。每次 schema 變更（加欄位、改索引、拆表、改資料型別）寫成一份獨立的 migration 檔案，按順序套用。這讓 schema 的演進跟程式碼一樣有版本歷史、可追蹤、可在新環境重現。</p>
<h2 id="概念位置">概念位置</h2>
<p>migration 解決的問題是「資料庫的 schema 怎麼從 A 狀態安全地變成 B 狀態」。沒有 migration 時，schema 變更靠在 <a href="/blog/infra/knowledge-cards/phpmyadmin/" data-link-title="phpMyAdmin" data-link-desc="Web 介面的 MySQL / MariaDB 管理工具，透過瀏覽器操作資料庫">phpMyAdmin</a> 或 CLI 手動執行 SQL，改了什麼只存在操作者的記憶裡。有 migration 時，每次變更都是 repo 裡的一份檔案，跟程式碼一起 commit、一起 review。</p>
<h2 id="可觀察訊號">可觀察訊號</h2>
<p>接手專案時，如果 repo 裡有 <code>migrations/</code> 目錄（或框架特定的路徑如 Laravel 的 <code>database/migrations/</code>、Rails 的 <code>db/migrate/</code>），代表專案使用 migration。如果 repo 裡只有一份 <code>schema.sql</code> 或完全沒有 schema 相關檔案，代表 schema 變更是手動的——這時候建立 migration 紀律是接手後的優先事項之一。</p>
<h2 id="設計責任">設計責任</h2>
<p>每份 migration 檔案包含兩個方向：</p>
<ul>
<li><strong>UP</strong>（套用）：執行 schema 變更的 SQL</li>
<li><strong>DOWN</strong>（回退）：撤銷這次變更的 SQL（不是所有變更都能完美回退，如刪除欄位後資料就沒了）</li>
</ul>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-sql" data-lang="sql"><span class="line"><span class="ln">1</span><span class="cl"><span class="c1">-- migrations/2026-06-26-001-add-users-email-verified.sql
</span></span></span><span class="line"><span class="ln">2</span><span class="cl"><span class="c1"></span><span class="w">
</span></span></span><span class="line"><span class="ln">3</span><span class="cl"><span class="w"></span><span class="c1">-- UP
</span></span></span><span class="line"><span class="ln">4</span><span class="cl"><span class="c1"></span><span class="k">ALTER</span><span class="w"> </span><span class="k">TABLE</span><span class="w"> </span><span class="n">users</span><span class="w"> </span><span class="k">ADD</span><span class="w"> </span><span class="k">COLUMN</span><span class="w"> </span><span class="n">email_verified</span><span class="w"> </span><span class="nb">BOOLEAN</span><span class="w"> </span><span class="k">DEFAULT</span><span class="w"> </span><span class="k">FALSE</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="ln">5</span><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="ln">6</span><span class="cl"><span class="w"></span><span class="c1">-- DOWN
</span></span></span><span class="line"><span class="ln">7</span><span class="cl"><span class="c1"></span><span class="k">ALTER</span><span class="w"> </span><span class="k">TABLE</span><span class="w"> </span><span class="n">users</span><span class="w"> </span><span class="k">DROP</span><span class="w"> </span><span class="k">COLUMN</span><span class="w"> </span><span class="n">email_verified</span><span class="p">;</span></span></span></code></pre></div><p>常用的 migration 工具：</p>
<table>
  <thead>
      <tr>
          <th>工具</th>
          <th>語言 / 框架</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>Laravel Migration</td>
          <td>PHP / Laravel</td>
      </tr>
      <tr>
          <td>Rails Migration</td>
          <td>Ruby / Rails</td>
      </tr>
      <tr>
          <td>Flyway</td>
          <td>Java / 跨語言（純 SQL）</td>
      </tr>
      <tr>
          <td>Liquibase</td>
          <td>Java / 跨語言（XML / YAML / SQL）</td>
      </tr>
      <tr>
          <td>golang-migrate</td>
          <td>Go</td>
      </tr>
      <tr>
          <td>手動 SQL 檔案</td>
          <td>無框架時的最低限度方案</td>
      </tr>
  </tbody>
</table>
<p>沒有框架時，用日期 + 序號命名 SQL 檔案（<code>2026-06-26-001-描述.sql</code>），搭配一張 <code>migration_log</code> 表記錄哪些已經套用過，就是最低限度的 migration 系統。</p>
<h2 id="鄰卡">鄰卡</h2>
<ul>
<li><a href="/blog/infra/knowledge-cards/rds/" data-link-title="RDS" data-link-desc="AWS 的受管關聯式資料庫服務，代管備份、更新與 failover，讓使用者專注在 schema 和查詢">RDS</a>：migration 在 production 資料庫上執行時要格外小心——大表的 ALTER TABLE 可能鎖表</li>
<li><a href="/blog/infra/knowledge-cards/mysqldump/" data-link-title="mysqldump" data-link-desc="MySQL / MariaDB 的 CLI 備份工具，把資料庫匯出成 SQL 語句的純文字檔">mysqldump</a>：執行 migration 前先做一次完整備份</li>
</ul>
]]></content:encoded></item><item><title>Frontier Capability</title><link>https://tarrragon.github.io/blog/business/knowledge-cards/frontier-capability/</link><pubDate>Tue, 19 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/business/knowledge-cards/frontier-capability/</guid><description>&lt;p>Frontier Capability 的核心概念是「前沿能力」—在某個領域做到最尖端、最領先的水平。AI 領域常用 frontier model 指最強大的最新模型（GPT、Claude 最新一代）。Frontier 差距決定技術領先是否足以撐起 &lt;a href="https://tarrragon.github.io/blog/business/knowledge-cards/gross-margin/" data-link-title="Gross Margin" data-link-desc="說明毛利率與其對商業模式可行性的決定作用">毛利&lt;/a> 溢價。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>Frontier Capability 是判讀技術賽道領先差距的關鍵。如果 frontier 領先很多（差距持續拉大），落後者很難追；如果 frontier 領先有限（很快被追上），技術領先就不是護城河，要靠 &lt;a href="https://tarrragon.github.io/blog/business/knowledge-cards/distribution/" data-link-title="Distribution" data-link-desc="說明分發優勢作為現有玩家的核心護城河">分發&lt;/a> 或 &lt;a href="https://tarrragon.github.io/blog/business/knowledge-cards/fat-data-fat-skill/" data-link-title="Fat Data / Fat Skill" data-link-desc="說明獨家資料與行業隱性能力作為 AI 時代的護城河">Fat Data / Fat Skill&lt;/a>。&lt;/p>
&lt;h2 id="可觀察訊號與例子">可觀察訊號與例子&lt;/h2>
&lt;p>判讀 frontier 差距：benchmark 分數差多少、實際使用體感差多少、客戶願意為差距付多少溢價。OpenAI 押的是「frontier 差距會繼續拉開」，所以投資巨額算力做下一代模型；Google 押的是「&lt;a href="https://tarrragon.github.io/blog/business/knowledge-cards/distribution/" data-link-title="Distribution" data-link-desc="說明分發優勢作為現有玩家的核心護城河">分發&lt;/a> 勝過 frontier」，所以利用 Cloud 跟 Workspace 既有客戶慢慢轉。&lt;/p>
&lt;h2 id="判讀方式">判讀方式&lt;/h2>
&lt;p>讀到「押 frontier 能力差距」時，意味著該公司賭的是技術領先足以撐起溢價。讀到「frontier 差距收斂」「模型能力差不多」時，意味著該分析師認為技術差異化不夠，要看其他維度（&lt;a href="https://tarrragon.github.io/blog/business/knowledge-cards/tacit-knowledge/" data-link-title="Tacit Knowledge" data-link-desc="說明隱性知識與其作為護城河的價值">行業 know-how&lt;/a>、&lt;a href="https://tarrragon.github.io/blog/business/knowledge-cards/distribution/" data-link-title="Distribution" data-link-desc="說明分發優勢作為現有玩家的核心護城河">分發&lt;/a>）。三家 AI Labs 的策略差異反映的就是對 frontier 走向的不同押注。&lt;/p></description><content:encoded><![CDATA[<p>Frontier Capability 的核心概念是「前沿能力」—在某個領域做到最尖端、最領先的水平。AI 領域常用 frontier model 指最強大的最新模型（GPT、Claude 最新一代）。Frontier 差距決定技術領先是否足以撐起 <a href="/blog/business/knowledge-cards/gross-margin/" data-link-title="Gross Margin" data-link-desc="說明毛利率與其對商業模式可行性的決定作用">毛利</a> 溢價。</p>
<h2 id="概念位置">概念位置</h2>
<p>Frontier Capability 是判讀技術賽道領先差距的關鍵。如果 frontier 領先很多（差距持續拉大），落後者很難追；如果 frontier 領先有限（很快被追上），技術領先就不是護城河，要靠 <a href="/blog/business/knowledge-cards/distribution/" data-link-title="Distribution" data-link-desc="說明分發優勢作為現有玩家的核心護城河">分發</a> 或 <a href="/blog/business/knowledge-cards/fat-data-fat-skill/" data-link-title="Fat Data / Fat Skill" data-link-desc="說明獨家資料與行業隱性能力作為 AI 時代的護城河">Fat Data / Fat Skill</a>。</p>
<h2 id="可觀察訊號與例子">可觀察訊號與例子</h2>
<p>判讀 frontier 差距：benchmark 分數差多少、實際使用體感差多少、客戶願意為差距付多少溢價。OpenAI 押的是「frontier 差距會繼續拉開」，所以投資巨額算力做下一代模型；Google 押的是「<a href="/blog/business/knowledge-cards/distribution/" data-link-title="Distribution" data-link-desc="說明分發優勢作為現有玩家的核心護城河">分發</a> 勝過 frontier」，所以利用 Cloud 跟 Workspace 既有客戶慢慢轉。</p>
<h2 id="判讀方式">判讀方式</h2>
<p>讀到「押 frontier 能力差距」時，意味著該公司賭的是技術領先足以撐起溢價。讀到「frontier 差距收斂」「模型能力差不多」時，意味著該分析師認為技術差異化不夠，要看其他維度（<a href="/blog/business/knowledge-cards/tacit-knowledge/" data-link-title="Tacit Knowledge" data-link-desc="說明隱性知識與其作為護城河的價值">行業 know-how</a>、<a href="/blog/business/knowledge-cards/distribution/" data-link-title="Distribution" data-link-desc="說明分發優勢作為現有玩家的核心護城河">分發</a>）。三家 AI Labs 的策略差異反映的就是對 frontier 走向的不同押注。</p>
]]></content:encoded></item><item><title>Prometheus</title><link>https://tarrragon.github.io/blog/infra/knowledge-cards/prometheus/</link><pubDate>Fri, 26 Jun 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/infra/knowledge-cards/prometheus/</guid><description>&lt;p>Prometheus 是開源的 metrics 收集與告警系統。它用 pull 模式運作——定期從被監控的 target（應用程式、伺服器、資料庫）的 HTTP endpoint 拉取指標，存進本地的時序資料庫。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>Prometheus 在 infra 監控層負責「收集與儲存指標」。它搭配 &lt;a href="https://tarrragon.github.io/blog/infra/knowledge-cards/grafana/" data-link-title="Grafana" data-link-desc="開源的監控視覺化平台，從 Prometheus / Loki / Elasticsearch 等資料源建立 dashboard">Grafana&lt;/a> 做視覺化（Prometheus 自己的 UI 只有基礎的 query 介面）、搭配 Alertmanager 做告警路由（Prometheus 偵測異常、Alertmanager 決定通知誰）。斷網環境裡它是取代 Datadog / New Relic 的預設方案——不需要連外、self-hosted、社群龐大。&lt;/p>
&lt;h2 id="可觀察訊號">可觀察訊號&lt;/h2>
&lt;p>系統需要 Prometheus 的訊號是：需要追蹤隨時間變化的數值指標（CPU 使用率、request 延遲、佇列深度、錯誤率），且這些指標要能查詢歷史趨勢和設定告警閾值。如果只需要 log（文字紀錄），Loki 或 ELK 更適合；Prometheus 處理的是結構化的數值 metrics。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>使用 Prometheus 時要決定：scrape interval（多久拉一次、預設 15 秒）、retention（資料保留多久、預設 15 天）、哪些 target 要監控（service discovery 或靜態設定）、告警規則的閾值和評估窗口。斷網環境的額外考量是 storage capacity——所有資料留在本地磁碟、沒有 cloud auto-scale。&lt;/p>
&lt;h2 id="鄰卡">鄰卡&lt;/h2>
&lt;ul>
&lt;li>&lt;a href="https://tarrragon.github.io/blog/infra/knowledge-cards/grafana/" data-link-title="Grafana" data-link-desc="開源的監控視覺化平台，從 Prometheus / Loki / Elasticsearch 等資料源建立 dashboard">Grafana&lt;/a>：視覺化 Prometheus 的指標&lt;/li>
&lt;/ul></description><content:encoded><![CDATA[<p>Prometheus 是開源的 metrics 收集與告警系統。它用 pull 模式運作——定期從被監控的 target（應用程式、伺服器、資料庫）的 HTTP endpoint 拉取指標，存進本地的時序資料庫。</p>
<h2 id="概念位置">概念位置</h2>
<p>Prometheus 在 infra 監控層負責「收集與儲存指標」。它搭配 <a href="/blog/infra/knowledge-cards/grafana/" data-link-title="Grafana" data-link-desc="開源的監控視覺化平台，從 Prometheus / Loki / Elasticsearch 等資料源建立 dashboard">Grafana</a> 做視覺化（Prometheus 自己的 UI 只有基礎的 query 介面）、搭配 Alertmanager 做告警路由（Prometheus 偵測異常、Alertmanager 決定通知誰）。斷網環境裡它是取代 Datadog / New Relic 的預設方案——不需要連外、self-hosted、社群龐大。</p>
<h2 id="可觀察訊號">可觀察訊號</h2>
<p>系統需要 Prometheus 的訊號是：需要追蹤隨時間變化的數值指標（CPU 使用率、request 延遲、佇列深度、錯誤率），且這些指標要能查詢歷史趨勢和設定告警閾值。如果只需要 log（文字紀錄），Loki 或 ELK 更適合；Prometheus 處理的是結構化的數值 metrics。</p>
<h2 id="設計責任">設計責任</h2>
<p>使用 Prometheus 時要決定：scrape interval（多久拉一次、預設 15 秒）、retention（資料保留多久、預設 15 天）、哪些 target 要監控（service discovery 或靜態設定）、告警規則的閾值和評估窗口。斷網環境的額外考量是 storage capacity——所有資料留在本地磁碟、沒有 cloud auto-scale。</p>
<h2 id="鄰卡">鄰卡</h2>
<ul>
<li><a href="/blog/infra/knowledge-cards/grafana/" data-link-title="Grafana" data-link-desc="開源的監控視覺化平台，從 Prometheus / Loki / Elasticsearch 等資料源建立 dashboard">Grafana</a>：視覺化 Prometheus 的指標</li>
</ul>
]]></content:encoded></item><item><title>Distribution</title><link>https://tarrragon.github.io/blog/business/knowledge-cards/distribution/</link><pubDate>Tue, 19 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/business/knowledge-cards/distribution/</guid><description>&lt;p>Distribution 的核心概念是「分發優勢」—公司能不能把產品送到客戶眼前的能力，依靠既有客戶基礎、銷售通路、平台優勢、品牌信任。Microsoft、Google、Apple 的 distribution 是它們的核心競爭力。Distribution 是 &lt;a href="https://tarrragon.github.io/blog/business/knowledge-cards/gtm/" data-link-title="GTM" data-link-desc="說明進入市場策略的完整含義">GTM&lt;/a> 的長期積累。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>Distribution 跟 &lt;a href="https://tarrragon.github.io/blog/business/knowledge-cards/frontier-capability/" data-link-title="Frontier Capability" data-link-desc="說明前沿能力差距如何影響商業策略">Frontier Capability&lt;/a> 是兩種對立的押注策略。新創通常 distribution 弱（沒有客戶基礎），要靠 &lt;a href="https://tarrragon.github.io/blog/business/knowledge-cards/plg/" data-link-title="PLG" data-link-desc="說明產品自助成長模式與其經濟前提">PLG&lt;/a> 或產品差異化突圍；大公司 distribution 強（有既有客戶與通路），即使產品稍弱也能慢慢轉化客戶過來。Distribution 是降低 &lt;a href="https://tarrragon.github.io/blog/business/knowledge-cards/cac/" data-link-title="CAC" data-link-desc="說明獲客成本及其對商業模式可行性的決定作用">CAC&lt;/a> 的長期資產。&lt;/p>
&lt;h2 id="可觀察訊號與例子">可觀察訊號與例子&lt;/h2>
&lt;p>判讀 distribution：公司有多少現成的客戶能交叉銷售？有多少銷售人員與通路夥伴？品牌在目標客群中是否被信任？Microsoft Copilot 的優勢就是 distribution—Office 已經在每家公司，加 Copilot 只是 upgrade。Google 把 AI 接進 Search 與 Workspace 同樣不需要說服客戶換工具。&lt;/p>
&lt;h2 id="判讀方式">判讀方式&lt;/h2>
&lt;p>讀到「分發優勢勝過一切」時，意味著該分析師認為現有大公司會贏，因為新創產品就算好也賣不過去。AI 時代 Big Tech 的 distribution 優勢被多次討論—它們不需要 &lt;a href="https://tarrragon.github.io/blog/business/knowledge-cards/plg/" data-link-title="PLG" data-link-desc="說明產品自助成長模式與其經濟前提">PLG&lt;/a> 拉新客戶，只要把 AI 功能塞進既有產品就直接觸及幾億用戶。新創若沒有差異化的 &lt;a href="https://tarrragon.github.io/blog/business/knowledge-cards/fat-data-fat-skill/" data-link-title="Fat Data / Fat Skill" data-link-desc="說明獨家資料與行業隱性能力作為 AI 時代的護城河">Fat Data / Fat Skill&lt;/a>，很難對抗 distribution 優勢。&lt;/p></description><content:encoded><![CDATA[<p>Distribution 的核心概念是「分發優勢」—公司能不能把產品送到客戶眼前的能力，依靠既有客戶基礎、銷售通路、平台優勢、品牌信任。Microsoft、Google、Apple 的 distribution 是它們的核心競爭力。Distribution 是 <a href="/blog/business/knowledge-cards/gtm/" data-link-title="GTM" data-link-desc="說明進入市場策略的完整含義">GTM</a> 的長期積累。</p>
<h2 id="概念位置">概念位置</h2>
<p>Distribution 跟 <a href="/blog/business/knowledge-cards/frontier-capability/" data-link-title="Frontier Capability" data-link-desc="說明前沿能力差距如何影響商業策略">Frontier Capability</a> 是兩種對立的押注策略。新創通常 distribution 弱（沒有客戶基礎），要靠 <a href="/blog/business/knowledge-cards/plg/" data-link-title="PLG" data-link-desc="說明產品自助成長模式與其經濟前提">PLG</a> 或產品差異化突圍；大公司 distribution 強（有既有客戶與通路），即使產品稍弱也能慢慢轉化客戶過來。Distribution 是降低 <a href="/blog/business/knowledge-cards/cac/" data-link-title="CAC" data-link-desc="說明獲客成本及其對商業模式可行性的決定作用">CAC</a> 的長期資產。</p>
<h2 id="可觀察訊號與例子">可觀察訊號與例子</h2>
<p>判讀 distribution：公司有多少現成的客戶能交叉銷售？有多少銷售人員與通路夥伴？品牌在目標客群中是否被信任？Microsoft Copilot 的優勢就是 distribution—Office 已經在每家公司，加 Copilot 只是 upgrade。Google 把 AI 接進 Search 與 Workspace 同樣不需要說服客戶換工具。</p>
<h2 id="判讀方式">判讀方式</h2>
<p>讀到「分發優勢勝過一切」時，意味著該分析師認為現有大公司會贏，因為新創產品就算好也賣不過去。AI 時代 Big Tech 的 distribution 優勢被多次討論—它們不需要 <a href="/blog/business/knowledge-cards/plg/" data-link-title="PLG" data-link-desc="說明產品自助成長模式與其經濟前提">PLG</a> 拉新客戶，只要把 AI 功能塞進既有產品就直接觸及幾億用戶。新創若沒有差異化的 <a href="/blog/business/knowledge-cards/fat-data-fat-skill/" data-link-title="Fat Data / Fat Skill" data-link-desc="說明獨家資料與行業隱性能力作為 AI 時代的護城河">Fat Data / Fat Skill</a>，很難對抗 distribution 優勢。</p>
]]></content:encoded></item><item><title>Grafana</title><link>https://tarrragon.github.io/blog/infra/knowledge-cards/grafana/</link><pubDate>Fri, 26 Jun 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/infra/knowledge-cards/grafana/</guid><description>&lt;p>Grafana 是開源的監控視覺化平台。它本身不收集或儲存資料——它連接外部資料源（&lt;a href="https://tarrragon.github.io/blog/infra/knowledge-cards/prometheus/" data-link-title="Prometheus" data-link-desc="開源的 metrics 收集與告警系統，用 pull 模式從 target 拉取指標，斷網環境的預設監控方案">Prometheus&lt;/a>、Loki、Elasticsearch、MySQL 等），提供查詢介面和可自訂的儀表板。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>Grafana 在監控體系裡負責「讓指標和 log 變成人可以讀的畫面」。Prometheus 收集指標、Loki 收集 log、Grafana 把兩者的資料用圖表、表格、熱力圖呈現。不同角色看不同 dashboard——DevOps 看資源健康、開發者看應用指標、管理層看 SLA 達成率。&lt;/p>
&lt;h2 id="可觀察訊號">可觀察訊號&lt;/h2>
&lt;p>系統需要 Grafana 的訊號是：已經有 Prometheus 或其他資料源在收集指標，但需要一個視覺化介面來建 dashboard、設告警（Grafana 也有自己的告警功能）、分享給團隊。如果只需要 CLI 查詢，PromQL 直接在 Prometheus 跑就好。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>使用 Grafana 時要決定：dashboard 的組織（按服務、按環境、按角色）、資料源的連線設定、使用者權限（viewer / editor / admin）、告警通知管道（email / Slack / webhook）。斷網環境裡 Grafana 的 plugin 需要離線安裝（&lt;code>grafana-cli --pluginUrl&lt;/code> 指向本地檔案）。&lt;/p>
&lt;h2 id="鄰卡">鄰卡&lt;/h2>
&lt;ul>
&lt;li>&lt;a href="https://tarrragon.github.io/blog/infra/knowledge-cards/prometheus/" data-link-title="Prometheus" data-link-desc="開源的 metrics 收集與告警系統，用 pull 模式從 target 拉取指標，斷網環境的預設監控方案">Prometheus&lt;/a>：Grafana 最常見的 metrics 資料源&lt;/li>
&lt;/ul></description><content:encoded><![CDATA[<p>Grafana 是開源的監控視覺化平台。它本身不收集或儲存資料——它連接外部資料源（<a href="/blog/infra/knowledge-cards/prometheus/" data-link-title="Prometheus" data-link-desc="開源的 metrics 收集與告警系統，用 pull 模式從 target 拉取指標，斷網環境的預設監控方案">Prometheus</a>、Loki、Elasticsearch、MySQL 等），提供查詢介面和可自訂的儀表板。</p>
<h2 id="概念位置">概念位置</h2>
<p>Grafana 在監控體系裡負責「讓指標和 log 變成人可以讀的畫面」。Prometheus 收集指標、Loki 收集 log、Grafana 把兩者的資料用圖表、表格、熱力圖呈現。不同角色看不同 dashboard——DevOps 看資源健康、開發者看應用指標、管理層看 SLA 達成率。</p>
<h2 id="可觀察訊號">可觀察訊號</h2>
<p>系統需要 Grafana 的訊號是：已經有 Prometheus 或其他資料源在收集指標，但需要一個視覺化介面來建 dashboard、設告警（Grafana 也有自己的告警功能）、分享給團隊。如果只需要 CLI 查詢，PromQL 直接在 Prometheus 跑就好。</p>
<h2 id="設計責任">設計責任</h2>
<p>使用 Grafana 時要決定：dashboard 的組織（按服務、按環境、按角色）、資料源的連線設定、使用者權限（viewer / editor / admin）、告警通知管道（email / Slack / webhook）。斷網環境裡 Grafana 的 plugin 需要離線安裝（<code>grafana-cli --pluginUrl</code> 指向本地檔案）。</p>
<h2 id="鄰卡">鄰卡</h2>
<ul>
<li><a href="/blog/infra/knowledge-cards/prometheus/" data-link-title="Prometheus" data-link-desc="開源的 metrics 收集與告警系統，用 pull 模式從 target 拉取指標，斷網環境的預設監控方案">Prometheus</a>：Grafana 最常見的 metrics 資料源</li>
</ul>
]]></content:encoded></item><item><title>HashiCorp Vault</title><link>https://tarrragon.github.io/blog/infra/knowledge-cards/vault/</link><pubDate>Fri, 26 Jun 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/infra/knowledge-cards/vault/</guid><description>&lt;p>HashiCorp Vault 是機密管理系統，集中存放和控制對敏感資料（密碼、API key、TLS 私鑰、資料庫憑證）的存取。每一次讀取都有稽核紀錄、每一份機密都有存取政策、憑證可以設定自動輪替。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>Vault 在 infra 裡負責「機密值的集中管理」。跟直接把密碼寫在環境變數或設定檔的差別是：Vault 提供存取控制（只有被授權的身分能讀特定 secret）、稽核軌跡（誰在什麼時候讀了什麼）、以及動態 secret（每次請求產生一組臨時憑證、用完即銷毀）。&lt;/p>
&lt;p>連網環境通常用雲端的 secret manager（AWS Secrets Manager、GCP Secret Manager）。斷網環境沒有雲端服務可用、Vault 是 self-hosted 的替代方案。&lt;/p>
&lt;h2 id="可觀察訊號">可觀察訊號&lt;/h2>
&lt;p>系統需要 Vault 的訊號是：多個服務共用同一組資料庫密碼且密碼寫在設定檔裡、沒有人知道上次輪替是什麼時候、或是稽核要求「列出誰能存取哪些機密」而答不出來。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>使用 Vault 時要決定：unseal 方式（連網用 cloud auto-unseal、斷網用 Shamir&amp;rsquo;s secret sharing——需要 N 把 key 中的 M 把才能解鎖）、storage backend（Consul、PostgreSQL、filesystem）、認證方式（人用 LDAP/OIDC、機器用 AppRole）、secret engine 的選擇（KV 存靜態值、PKI 簽發憑證、database 動態產生 DB 帳號）。&lt;/p>
&lt;h2 id="鄰卡">鄰卡&lt;/h2>
&lt;ul>
&lt;li>&lt;a href="https://tarrragon.github.io/blog/infra/knowledge-cards/iam/" data-link-title="IAM（Identity and Access Management）" data-link-desc="雲端平台的授權系統，回答「某個身分能不能對某個資源做某件事」">IAM&lt;/a>：Vault 的存取政策跟 IAM 的 policy 概念類似&lt;/li>
&lt;li>&lt;a href="https://tarrragon.github.io/blog/infra/knowledge-cards/ssl-tls/" data-link-title="SSL / TLS" data-link-desc="加密 client 與 server 之間通訊的協定，讓 HTTPS 成為可能。TLS 是 SSL 的後繼者，但 SSL 憑證的稱呼仍廣泛使用">SSL/TLS&lt;/a>：Vault 的 PKI engine 可以當內部 CA 簽發憑證&lt;/li>
&lt;/ul></description><content:encoded><![CDATA[<p>HashiCorp Vault 是機密管理系統，集中存放和控制對敏感資料（密碼、API key、TLS 私鑰、資料庫憑證）的存取。每一次讀取都有稽核紀錄、每一份機密都有存取政策、憑證可以設定自動輪替。</p>
<h2 id="概念位置">概念位置</h2>
<p>Vault 在 infra 裡負責「機密值的集中管理」。跟直接把密碼寫在環境變數或設定檔的差別是：Vault 提供存取控制（只有被授權的身分能讀特定 secret）、稽核軌跡（誰在什麼時候讀了什麼）、以及動態 secret（每次請求產生一組臨時憑證、用完即銷毀）。</p>
<p>連網環境通常用雲端的 secret manager（AWS Secrets Manager、GCP Secret Manager）。斷網環境沒有雲端服務可用、Vault 是 self-hosted 的替代方案。</p>
<h2 id="可觀察訊號">可觀察訊號</h2>
<p>系統需要 Vault 的訊號是：多個服務共用同一組資料庫密碼且密碼寫在設定檔裡、沒有人知道上次輪替是什麼時候、或是稽核要求「列出誰能存取哪些機密」而答不出來。</p>
<h2 id="設計責任">設計責任</h2>
<p>使用 Vault 時要決定：unseal 方式（連網用 cloud auto-unseal、斷網用 Shamir&rsquo;s secret sharing——需要 N 把 key 中的 M 把才能解鎖）、storage backend（Consul、PostgreSQL、filesystem）、認證方式（人用 LDAP/OIDC、機器用 AppRole）、secret engine 的選擇（KV 存靜態值、PKI 簽發憑證、database 動態產生 DB 帳號）。</p>
<h2 id="鄰卡">鄰卡</h2>
<ul>
<li><a href="/blog/infra/knowledge-cards/iam/" data-link-title="IAM（Identity and Access Management）" data-link-desc="雲端平台的授權系統，回答「某個身分能不能對某個資源做某件事」">IAM</a>：Vault 的存取政策跟 IAM 的 policy 概念類似</li>
<li><a href="/blog/infra/knowledge-cards/ssl-tls/" data-link-title="SSL / TLS" data-link-desc="加密 client 與 server 之間通訊的協定，讓 HTTPS 成為可能。TLS 是 SSL 的後繼者，但 SSL 憑證的稱呼仍廣泛使用">SSL/TLS</a>：Vault 的 PKI engine 可以當內部 CA 簽發憑證</li>
</ul>
]]></content:encoded></item><item><title>Harbor</title><link>https://tarrragon.github.io/blog/infra/knowledge-cards/harbor/</link><pubDate>Fri, 26 Jun 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/infra/knowledge-cards/harbor/</guid><description>&lt;p>Harbor 是開源的 container image registry，由 CNCF 孵化。它在 Docker Registry 的基礎上加了企業級功能：Web UI、角色型存取控制（RBAC）、映像漏洞掃描（內建 Trivy）、映像簽章驗證、以及跨 registry 的映像複製。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>Harbor 在容器生態裡負責「映像的儲存、分發和安全把關」。連網環境裡這個角色通常由 Docker Hub、AWS ECR 或 GCR 擔任。斷網環境沒有公開 registry 可用、Harbor 是 self-hosted 的替代——所有 base image 和應用 image 都推進 Harbor、所有 docker pull 都從 Harbor 拉。&lt;/p>
&lt;h2 id="可觀察訊號">可觀察訊號&lt;/h2>
&lt;p>系統需要 Harbor 的訊號是：團隊開始用容器部署服務、且環境無法連到公開 registry（斷網或受限網路）、或需要在 pull 時自動掃描漏洞。如果只是幾個人在開發機上用 Docker、Docker Registry（無 UI、無掃描）就夠了。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>使用 Harbor 時要決定：project 的組織（按團隊、按環境、按產品線）、使用者認證（本地帳號 or LDAP 整合）、漏洞掃描政策（push 時自動掃、block 有 Critical CVE 的 image）、映像保留政策（保留最近 N 個 tag、自動清理舊 image）、以及 storage backend（本地磁碟或 NFS）。&lt;/p>
&lt;h2 id="鄰卡">鄰卡&lt;/h2>
&lt;ul>
&lt;li>&lt;a href="https://tarrragon.github.io/blog/infra/knowledge-cards/ecs/" data-link-title="ECS" data-link-desc="AWS Elastic Container Service — 受管的容器編排服務，用 task definition 描述容器配置、由平台負責排程與健康管理">ECS&lt;/a>：ECS task 從 registry 拉 image&lt;/li>
&lt;li>&lt;a href="https://tarrragon.github.io/blog/infra/knowledge-cards/fargate/" data-link-title="Fargate" data-link-desc="AWS ECS 的無伺服器執行模式，由 AWS 代管運算實例，不需要管 EC2 capacity 或 AMI 更新">Fargate&lt;/a>：Fargate task 同樣需要 registry&lt;/li>
&lt;/ul></description><content:encoded><![CDATA[<p>Harbor 是開源的 container image registry，由 CNCF 孵化。它在 Docker Registry 的基礎上加了企業級功能：Web UI、角色型存取控制（RBAC）、映像漏洞掃描（內建 Trivy）、映像簽章驗證、以及跨 registry 的映像複製。</p>
<h2 id="概念位置">概念位置</h2>
<p>Harbor 在容器生態裡負責「映像的儲存、分發和安全把關」。連網環境裡這個角色通常由 Docker Hub、AWS ECR 或 GCR 擔任。斷網環境沒有公開 registry 可用、Harbor 是 self-hosted 的替代——所有 base image 和應用 image 都推進 Harbor、所有 docker pull 都從 Harbor 拉。</p>
<h2 id="可觀察訊號">可觀察訊號</h2>
<p>系統需要 Harbor 的訊號是：團隊開始用容器部署服務、且環境無法連到公開 registry（斷網或受限網路）、或需要在 pull 時自動掃描漏洞。如果只是幾個人在開發機上用 Docker、Docker Registry（無 UI、無掃描）就夠了。</p>
<h2 id="設計責任">設計責任</h2>
<p>使用 Harbor 時要決定：project 的組織（按團隊、按環境、按產品線）、使用者認證（本地帳號 or LDAP 整合）、漏洞掃描政策（push 時自動掃、block 有 Critical CVE 的 image）、映像保留政策（保留最近 N 個 tag、自動清理舊 image）、以及 storage backend（本地磁碟或 NFS）。</p>
<h2 id="鄰卡">鄰卡</h2>
<ul>
<li><a href="/blog/infra/knowledge-cards/ecs/" data-link-title="ECS" data-link-desc="AWS Elastic Container Service — 受管的容器編排服務，用 task definition 描述容器配置、由平台負責排程與健康管理">ECS</a>：ECS task 從 registry 拉 image</li>
<li><a href="/blog/infra/knowledge-cards/fargate/" data-link-title="Fargate" data-link-desc="AWS ECS 的無伺服器執行模式，由 AWS 代管運算實例，不需要管 EC2 capacity 或 AMI 更新">Fargate</a>：Fargate task 同樣需要 registry</li>
</ul>
]]></content:encoded></item><item><title>Helm</title><link>https://tarrragon.github.io/blog/infra/knowledge-cards/helm/</link><pubDate>Fri, 26 Jun 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/infra/knowledge-cards/helm/</guid><description>&lt;p>Helm 是 Kubernetes 的套件管理工具。它用 chart（一組模板檔案 + 預設值）把多個 K8s 資源（Deployment、Service、ConfigMap、Ingress 等）打包成一個可安裝、可升級、可回退的單位。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>Helm 在 K8s 生態裡的角色類似 apt 在 Linux、npm 在 Node.js——把「安裝一個應用」從「逐一 apply 多個 YAML」變成「一條 &lt;code>helm install&lt;/code> 指令」。chart 可以參數化（values.yaml），同一份 chart 在不同環境用不同參數部署。&lt;/p>
&lt;p>公開 chart 從 Artifact Hub 下載。斷網環境裡用 &lt;code>helm pull&lt;/code> 在外部下載 chart tarball、搬進內網、從本地檔案安裝，或用 Harbor 的 OCI chart 支援當內部 chart registry。&lt;/p>
&lt;h2 id="可觀察訊號">可觀察訊號&lt;/h2>
&lt;p>系統需要 Helm 的訊號是：用 K8s 部署的應用超過 3 個、每個應用由 5+ 個 K8s 資源組成、且需要在多個環境（dev/staging/prod）用不同參數部署同一套定義。如果只有 1-2 個簡單應用、直接 &lt;code>kubectl apply&lt;/code> 就好。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>使用 Helm 時要決定：chart 的粒度（一個 chart = 一個微服務 or 一整個平台）、values 的組織（per-environment values file）、chart 版本管理（chart version vs app version）、以及升級策略（&lt;code>helm upgrade --atomic&lt;/code> 失敗自動回退）。&lt;/p>
&lt;h2 id="鄰卡">鄰卡&lt;/h2>
&lt;ul>
&lt;li>&lt;a href="https://tarrragon.github.io/blog/infra/knowledge-cards/ecs/" data-link-title="ECS" data-link-desc="AWS Elastic Container Service — 受管的容器編排服務，用 task definition 描述容器配置、由平台負責排程與健康管理">ECS&lt;/a>：ECS 是非 K8s 的容器編排替代&lt;/li>
&lt;/ul></description><content:encoded><![CDATA[<p>Helm 是 Kubernetes 的套件管理工具。它用 chart（一組模板檔案 + 預設值）把多個 K8s 資源（Deployment、Service、ConfigMap、Ingress 等）打包成一個可安裝、可升級、可回退的單位。</p>
<h2 id="概念位置">概念位置</h2>
<p>Helm 在 K8s 生態裡的角色類似 apt 在 Linux、npm 在 Node.js——把「安裝一個應用」從「逐一 apply 多個 YAML」變成「一條 <code>helm install</code> 指令」。chart 可以參數化（values.yaml），同一份 chart 在不同環境用不同參數部署。</p>
<p>公開 chart 從 Artifact Hub 下載。斷網環境裡用 <code>helm pull</code> 在外部下載 chart tarball、搬進內網、從本地檔案安裝，或用 Harbor 的 OCI chart 支援當內部 chart registry。</p>
<h2 id="可觀察訊號">可觀察訊號</h2>
<p>系統需要 Helm 的訊號是：用 K8s 部署的應用超過 3 個、每個應用由 5+ 個 K8s 資源組成、且需要在多個環境（dev/staging/prod）用不同參數部署同一套定義。如果只有 1-2 個簡單應用、直接 <code>kubectl apply</code> 就好。</p>
<h2 id="設計責任">設計責任</h2>
<p>使用 Helm 時要決定：chart 的粒度（一個 chart = 一個微服務 or 一整個平台）、values 的組織（per-environment values file）、chart 版本管理（chart version vs app version）、以及升級策略（<code>helm upgrade --atomic</code> 失敗自動回退）。</p>
<h2 id="鄰卡">鄰卡</h2>
<ul>
<li><a href="/blog/infra/knowledge-cards/ecs/" data-link-title="ECS" data-link-desc="AWS Elastic Container Service — 受管的容器編排服務，用 task definition 描述容器配置、由平台負責排程與健康管理">ECS</a>：ECS 是非 K8s 的容器編排替代</li>
</ul>
]]></content:encoded></item><item><title>Venture Capital (VC)</title><link>https://tarrragon.github.io/blog/business/knowledge-cards/venture-capital/</link><pubDate>Tue, 19 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/business/knowledge-cards/venture-capital/</guid><description>&lt;p>Venture Capital 的核心概念是「創投」—投資早期、高風險、高成長潛力的新創，期待少數成功案例的回報彌補多數失敗。VC 通常依輪次投資：seed → Series A → B → C → &amp;hellip;，每輪 &lt;a href="https://tarrragon.github.io/blog/business/knowledge-cards/valuation/" data-link-title="Valuation" data-link-desc="說明估值的構成與商業判讀作用">估值&lt;/a> 升高、股權稀釋。VC 跟 &lt;a href="https://tarrragon.github.io/blog/business/knowledge-cards/private-equity/" data-link-title="Private Equity (PE)" data-link-desc="說明私募基金與其對中型企業市場的策略意涵">PE&lt;/a> 投的是不同階段的公司。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>VC 是估值制定的核心參與者。VC 不只是給錢，還影響新創的 &lt;a href="https://tarrragon.github.io/blog/business/knowledge-cards/saas/" data-link-title="SaaS" data-link-desc="說明雲端訂閱軟體的商業模式與經濟特徵">商業模式&lt;/a> 選擇、&lt;a href="https://tarrragon.github.io/blog/business/knowledge-cards/gtm/" data-link-title="GTM" data-link-desc="說明進入市場策略的完整含義">GTM&lt;/a> 策略、何時退場。VC 看的是「能不能在 5-10 年回 10 倍」，所以對 &lt;a href="https://tarrragon.github.io/blog/business/knowledge-cards/unit-economics/" data-link-title="Unit Economics" data-link-desc="說明單位經濟模型與其判斷一家公司是否賺錢的責任">單位經濟&lt;/a> 跟 &lt;a href="https://tarrragon.github.io/blog/business/knowledge-cards/gross-margin/" data-link-title="Gross Margin" data-link-desc="說明毛利率與其對商業模式可行性的決定作用">毛利&lt;/a> 特別敏感—回不到 10 倍的賽道他們不感興趣。&lt;/p>
&lt;h2 id="可觀察訊號與例子">可觀察訊號與例子&lt;/h2>
&lt;p>VC 投資的訊號：基金規模從幾億到幾十億美金、單筆投資金額從幾百萬到幾億、要求 board seat、要求 &lt;a href="https://tarrragon.github.io/blog/business/knowledge-cards/pnl/" data-link-title="P&amp;amp;L" data-link-desc="說明損益表的結構與商業判讀作用">財務指標&lt;/a> 透明、要求成長率達標才釋放下一筆資金。a16z、Sequoia、Benchmark 是典型 VC。&lt;/p>
&lt;h2 id="判讀方式">判讀方式&lt;/h2>
&lt;p>讀到「VC 開始保守」「估值被 VC 壓」時，意味著資本環境變冷或該賽道單位經濟惡化。AI 新創面對的 VC 壓力是「毛利不到 50% 我給你的估值會打折」—這個訊號通過 &lt;a href="https://tarrragon.github.io/blog/business/knowledge-cards/runway/" data-link-title="Runway" data-link-desc="說明新創的現金跑道與融資時點">融資輪&lt;/a> 直接傳到創辦人的決策。VC 的「不投了」對新創常等於死刑判決。&lt;/p></description><content:encoded><![CDATA[<p>Venture Capital 的核心概念是「創投」—投資早期、高風險、高成長潛力的新創，期待少數成功案例的回報彌補多數失敗。VC 通常依輪次投資：seed → Series A → B → C → &hellip;，每輪 <a href="/blog/business/knowledge-cards/valuation/" data-link-title="Valuation" data-link-desc="說明估值的構成與商業判讀作用">估值</a> 升高、股權稀釋。VC 跟 <a href="/blog/business/knowledge-cards/private-equity/" data-link-title="Private Equity (PE)" data-link-desc="說明私募基金與其對中型企業市場的策略意涵">PE</a> 投的是不同階段的公司。</p>
<h2 id="概念位置">概念位置</h2>
<p>VC 是估值制定的核心參與者。VC 不只是給錢，還影響新創的 <a href="/blog/business/knowledge-cards/saas/" data-link-title="SaaS" data-link-desc="說明雲端訂閱軟體的商業模式與經濟特徵">商業模式</a> 選擇、<a href="/blog/business/knowledge-cards/gtm/" data-link-title="GTM" data-link-desc="說明進入市場策略的完整含義">GTM</a> 策略、何時退場。VC 看的是「能不能在 5-10 年回 10 倍」，所以對 <a href="/blog/business/knowledge-cards/unit-economics/" data-link-title="Unit Economics" data-link-desc="說明單位經濟模型與其判斷一家公司是否賺錢的責任">單位經濟</a> 跟 <a href="/blog/business/knowledge-cards/gross-margin/" data-link-title="Gross Margin" data-link-desc="說明毛利率與其對商業模式可行性的決定作用">毛利</a> 特別敏感—回不到 10 倍的賽道他們不感興趣。</p>
<h2 id="可觀察訊號與例子">可觀察訊號與例子</h2>
<p>VC 投資的訊號：基金規模從幾億到幾十億美金、單筆投資金額從幾百萬到幾億、要求 board seat、要求 <a href="/blog/business/knowledge-cards/pnl/" data-link-title="P&amp;L" data-link-desc="說明損益表的結構與商業判讀作用">財務指標</a> 透明、要求成長率達標才釋放下一筆資金。a16z、Sequoia、Benchmark 是典型 VC。</p>
<h2 id="判讀方式">判讀方式</h2>
<p>讀到「VC 開始保守」「估值被 VC 壓」時，意味著資本環境變冷或該賽道單位經濟惡化。AI 新創面對的 VC 壓力是「毛利不到 50% 我給你的估值會打折」—這個訊號通過 <a href="/blog/business/knowledge-cards/runway/" data-link-title="Runway" data-link-desc="說明新創的現金跑道與融資時點">融資輪</a> 直接傳到創辦人的決策。VC 的「不投了」對新創常等於死刑判決。</p>
]]></content:encoded></item><item><title>Private Equity (PE)</title><link>https://tarrragon.github.io/blog/business/knowledge-cards/private-equity/</link><pubDate>Tue, 19 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/business/knowledge-cards/private-equity/</guid><description>&lt;p>Private Equity 的核心概念是「私募基金」—投資成熟、有現金流、可以靠營運改善或槓桿放大回報的公司，跟 &lt;a href="https://tarrragon.github.io/blog/business/knowledge-cards/venture-capital/" data-link-title="Venture Capital (VC)" data-link-desc="說明創投的投資邏輯與對新創估值的影響">VC&lt;/a> 投早期新創不同。PE 通常會買下整家公司、改造一兩年、再賣掉或上市。Blackstone、KKR、Carlyle 是代表玩家。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>PE 是 &lt;a href="https://tarrragon.github.io/blog/business/knowledge-cards/consolidation-cycle/" data-link-title="Consolidation Cycle" data-link-desc="說明整併週期的階段特徵">整併週期&lt;/a> 的重要推手—它買下多家同行業公司合併運營降本，或買被低估的公司重新包裝。PE 的投資組合公司常成為 SaaS 新創的客戶基礎—因為 PE 想用統一工具整合旗下公司，這也是 AI Labs 跟 PE 做 &lt;a href="https://tarrragon.github.io/blog/business/knowledge-cards/jv/" data-link-title="JV" data-link-desc="說明合資企業的戰略用途">JV&lt;/a> 的核心戰略原因。&lt;/p>
&lt;h2 id="可觀察訊號與例子">可觀察訊號與例子&lt;/h2>
&lt;p>PE 介入的訊號：成熟產業出現多筆收購、被收購公司被合併營運、財報變得保守（為了能轉手）。Anthropic 跟 Blackstone 合資—Blackstone 旗下幾百家投資組合公司直接變成 Anthropic 的潛在客戶基礎。一個 PE 巨頭背後的投資組合公司數量比 Fortune 500 還多。&lt;/p>
&lt;h2 id="判讀方式">判讀方式&lt;/h2>
&lt;p>讀到「鎖定 PE 旗下中型企業」時，意味著該 AI 公司用 PE 的投資組合當銷售捷徑—一次簽進去能拿到幾十家公司。對銷售方來說，這降低 &lt;a href="https://tarrragon.github.io/blog/business/knowledge-cards/cac/" data-link-title="CAC" data-link-desc="說明獲客成本及其對商業模式可行性的決定作用">CAC&lt;/a> 並縮短銷售週期；對 PE 來說，標準化 AI 工具能降低旗下公司營運成本。這是雙方的雙贏結構。&lt;/p></description><content:encoded><![CDATA[<p>Private Equity 的核心概念是「私募基金」—投資成熟、有現金流、可以靠營運改善或槓桿放大回報的公司，跟 <a href="/blog/business/knowledge-cards/venture-capital/" data-link-title="Venture Capital (VC)" data-link-desc="說明創投的投資邏輯與對新創估值的影響">VC</a> 投早期新創不同。PE 通常會買下整家公司、改造一兩年、再賣掉或上市。Blackstone、KKR、Carlyle 是代表玩家。</p>
<h2 id="概念位置">概念位置</h2>
<p>PE 是 <a href="/blog/business/knowledge-cards/consolidation-cycle/" data-link-title="Consolidation Cycle" data-link-desc="說明整併週期的階段特徵">整併週期</a> 的重要推手—它買下多家同行業公司合併運營降本，或買被低估的公司重新包裝。PE 的投資組合公司常成為 SaaS 新創的客戶基礎—因為 PE 想用統一工具整合旗下公司，這也是 AI Labs 跟 PE 做 <a href="/blog/business/knowledge-cards/jv/" data-link-title="JV" data-link-desc="說明合資企業的戰略用途">JV</a> 的核心戰略原因。</p>
<h2 id="可觀察訊號與例子">可觀察訊號與例子</h2>
<p>PE 介入的訊號：成熟產業出現多筆收購、被收購公司被合併營運、財報變得保守（為了能轉手）。Anthropic 跟 Blackstone 合資—Blackstone 旗下幾百家投資組合公司直接變成 Anthropic 的潛在客戶基礎。一個 PE 巨頭背後的投資組合公司數量比 Fortune 500 還多。</p>
<h2 id="判讀方式">判讀方式</h2>
<p>讀到「鎖定 PE 旗下中型企業」時，意味著該 AI 公司用 PE 的投資組合當銷售捷徑—一次簽進去能拿到幾十家公司。對銷售方來說，這降低 <a href="/blog/business/knowledge-cards/cac/" data-link-title="CAC" data-link-desc="說明獲客成本及其對商業模式可行性的決定作用">CAC</a> 並縮短銷售週期；對 PE 來說，標準化 AI 工具能降低旗下公司營運成本。這是雙方的雙贏結構。</p>
]]></content:encoded></item><item><title>Valuation</title><link>https://tarrragon.github.io/blog/business/knowledge-cards/valuation/</link><pubDate>Tue, 19 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/business/knowledge-cards/valuation/</guid><description>&lt;p>Valuation 的核心概念是「公司值多少錢」—通常用未來收入或利潤的折現、同類公司倍數（multiple）、最近融資金額等方式估算。&lt;a href="https://tarrragon.github.io/blog/business/knowledge-cards/saas/" data-link-title="SaaS" data-link-desc="說明雲端訂閱軟體的商業模式與經濟特徵">SaaS&lt;/a> 公司常用 revenue multiple（營收倍數）—如 ARR 10 倍。Valuation 受 &lt;a href="https://tarrragon.github.io/blog/business/knowledge-cards/gross-margin/" data-link-title="Gross Margin" data-link-desc="說明毛利率與其對商業模式可行性的決定作用">毛利&lt;/a>、&lt;a href="https://tarrragon.github.io/blog/business/knowledge-cards/retention/" data-link-title="Retention" data-link-desc="說明客戶留存率與其對單位經濟的決定作用">retention&lt;/a> 多重影響。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>Valuation 是 &lt;a href="https://tarrragon.github.io/blog/business/knowledge-cards/venture-capital/" data-link-title="Venture Capital (VC)" data-link-desc="說明創投的投資邏輯與對新創估值的影響">VC&lt;/a> / &lt;a href="https://tarrragon.github.io/blog/business/knowledge-cards/private-equity/" data-link-title="Private Equity (PE)" data-link-desc="說明私募基金與其對中型企業市場的策略意涵">PE&lt;/a> 決策的核心數字，也是創辦人最敏感的指標—它決定融資要釋出多少股權、退場時拿多少錢。Valuation 跟 &lt;a href="https://tarrragon.github.io/blog/business/knowledge-cards/unit-economics/" data-link-title="Unit Economics" data-link-desc="說明單位經濟模型與其判斷一家公司是否賺錢的責任">單位經濟&lt;/a> 是因果鏈：unit economics 健康才能撐高 valuation。&lt;/p>
&lt;h2 id="可觀察訊號與例子">可觀察訊號與例子&lt;/h2>
&lt;p>判讀 valuation 的健康度：跟同期同類公司比是否合理、跟自己上輪比是漲是跌、是否跟收入成長率匹配。SaaS 在 2021 年市場熱時 multiple 飆到 30 倍，2024 年回到 5-10 倍—這個 multiple 收斂直接影響新創估值。Down round（這輪估值低於上輪）是極差的訊號。&lt;/p>
&lt;h2 id="判讀方式">判讀方式&lt;/h2>
&lt;p>讀到「估值被壓縮」時，意味著市場對該行業未來營收的預期下調，或對成本結構的擔憂增加。AI 新創面臨的 &lt;a href="https://tarrragon.github.io/blog/business/knowledge-cards/valuation-compression/" data-link-title="Valuation Compression" data-link-desc="說明估值壓縮如何影響新創生存">Valuation Compression&lt;/a> 主要來自 &lt;a href="https://tarrragon.github.io/blog/business/knowledge-cards/gross-margin/" data-link-title="Gross Margin" data-link-desc="說明毛利率與其對商業模式可行性的決定作用">毛利&lt;/a> 下降—投資人用更保守的成本假設算估值，數字自然下降。這個訊號通過 &lt;a href="https://tarrragon.github.io/blog/business/knowledge-cards/runway/" data-link-title="Runway" data-link-desc="說明新創的現金跑道與融資時點">融資輪&lt;/a> 直接影響新創生存。&lt;/p></description><content:encoded><![CDATA[<p>Valuation 的核心概念是「公司值多少錢」—通常用未來收入或利潤的折現、同類公司倍數（multiple）、最近融資金額等方式估算。<a href="/blog/business/knowledge-cards/saas/" data-link-title="SaaS" data-link-desc="說明雲端訂閱軟體的商業模式與經濟特徵">SaaS</a> 公司常用 revenue multiple（營收倍數）—如 ARR 10 倍。Valuation 受 <a href="/blog/business/knowledge-cards/gross-margin/" data-link-title="Gross Margin" data-link-desc="說明毛利率與其對商業模式可行性的決定作用">毛利</a>、<a href="/blog/business/knowledge-cards/retention/" data-link-title="Retention" data-link-desc="說明客戶留存率與其對單位經濟的決定作用">retention</a> 多重影響。</p>
<h2 id="概念位置">概念位置</h2>
<p>Valuation 是 <a href="/blog/business/knowledge-cards/venture-capital/" data-link-title="Venture Capital (VC)" data-link-desc="說明創投的投資邏輯與對新創估值的影響">VC</a> / <a href="/blog/business/knowledge-cards/private-equity/" data-link-title="Private Equity (PE)" data-link-desc="說明私募基金與其對中型企業市場的策略意涵">PE</a> 決策的核心數字，也是創辦人最敏感的指標—它決定融資要釋出多少股權、退場時拿多少錢。Valuation 跟 <a href="/blog/business/knowledge-cards/unit-economics/" data-link-title="Unit Economics" data-link-desc="說明單位經濟模型與其判斷一家公司是否賺錢的責任">單位經濟</a> 是因果鏈：unit economics 健康才能撐高 valuation。</p>
<h2 id="可觀察訊號與例子">可觀察訊號與例子</h2>
<p>判讀 valuation 的健康度：跟同期同類公司比是否合理、跟自己上輪比是漲是跌、是否跟收入成長率匹配。SaaS 在 2021 年市場熱時 multiple 飆到 30 倍，2024 年回到 5-10 倍—這個 multiple 收斂直接影響新創估值。Down round（這輪估值低於上輪）是極差的訊號。</p>
<h2 id="判讀方式">判讀方式</h2>
<p>讀到「估值被壓縮」時，意味著市場對該行業未來營收的預期下調，或對成本結構的擔憂增加。AI 新創面臨的 <a href="/blog/business/knowledge-cards/valuation-compression/" data-link-title="Valuation Compression" data-link-desc="說明估值壓縮如何影響新創生存">Valuation Compression</a> 主要來自 <a href="/blog/business/knowledge-cards/gross-margin/" data-link-title="Gross Margin" data-link-desc="說明毛利率與其對商業模式可行性的決定作用">毛利</a> 下降—投資人用更保守的成本假設算估值，數字自然下降。這個訊號通過 <a href="/blog/business/knowledge-cards/runway/" data-link-title="Runway" data-link-desc="說明新創的現金跑道與融資時點">融資輪</a> 直接影響新創生存。</p>
]]></content:encoded></item><item><title>Valuation Compression</title><link>https://tarrragon.github.io/blog/business/knowledge-cards/valuation-compression/</link><pubDate>Tue, 19 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/business/knowledge-cards/valuation-compression/</guid><description>&lt;p>Valuation Compression 的核心概念是「估值壓縮」—同樣的公司過去能拿到的估值現在拿不到了，可能因為市場降溫、行業結構改變、&lt;a href="https://tarrragon.github.io/blog/business/knowledge-cards/unit-economics/" data-link-title="Unit Economics" data-link-desc="說明單位經濟模型與其判斷一家公司是否賺錢的責任">單位經濟&lt;/a> 惡化。Multiple 從 30 倍降到 5 倍是典型例子，影響直接傳到 &lt;a href="https://tarrragon.github.io/blog/business/knowledge-cards/venture-capital/" data-link-title="Venture Capital (VC)" data-link-desc="說明創投的投資邏輯與對新創估值的影響">新創融資&lt;/a>。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>Valuation Compression 對新創殺傷力最大的環節是融資。同樣 ARR 1000 萬，估值從 3 億降到 5000 萬，創辦人要釋出更多股權才能融到同樣金額，&lt;a href="https://tarrragon.github.io/blog/business/knowledge-cards/burn-rate/" data-link-title="Burn Rate" data-link-desc="說明燒錢速度及其對新創存活的決定作用">burn rate&lt;/a> 不變但 &lt;a href="https://tarrragon.github.io/blog/business/knowledge-cards/runway/" data-link-title="Runway" data-link-desc="說明新創的現金跑道與融資時點">runway&lt;/a> 實質縮短。Valuation Compression 跟 &lt;a href="https://tarrragon.github.io/blog/business/knowledge-cards/consolidation-cycle/" data-link-title="Consolidation Cycle" data-link-desc="說明整併週期的階段特徵">整併週期&lt;/a> 常一起出現。&lt;/p>
&lt;h2 id="可觀察訊號與例子">可觀察訊號與例子&lt;/h2>
&lt;p>Valuation Compression 的訊號：同類公司最新一輪 down round（估值比上輪低）、IPO 估值低於上市前融資估值、收購案估值打折。AI 新創面對的壓縮來自上游 &lt;a href="https://tarrragon.github.io/blog/business/knowledge-cards/gross-margin/" data-link-title="Gross Margin" data-link-desc="說明毛利率與其對商業模式可行性的決定作用">毛利&lt;/a> 被基礎模型供應商拿走—算下來毛利只有 50% 出頭，VC 算估值的數字就比 SaaS 經典 70-80% 毛利時期少很多。&lt;/p>
&lt;h2 id="判讀方式">判讀方式&lt;/h2>
&lt;p>讀到「估值壓縮直接影響生存」時，意味著該公司即使營運沒變差，但融資環境變化讓它面臨「拿不到當初預期金額」的壓力。對創辦人來說要考慮提早融資（趁估值還沒進一步壓縮）或裁員壓縮 &lt;a href="https://tarrragon.github.io/blog/business/knowledge-cards/burn-rate/" data-link-title="Burn Rate" data-link-desc="說明燒錢速度及其對新創存活的決定作用">burn rate&lt;/a>。Thin wrapper 類型的新創最容易死在 valuation compression 上。&lt;/p></description><content:encoded><![CDATA[<p>Valuation Compression 的核心概念是「估值壓縮」—同樣的公司過去能拿到的估值現在拿不到了，可能因為市場降溫、行業結構改變、<a href="/blog/business/knowledge-cards/unit-economics/" data-link-title="Unit Economics" data-link-desc="說明單位經濟模型與其判斷一家公司是否賺錢的責任">單位經濟</a> 惡化。Multiple 從 30 倍降到 5 倍是典型例子，影響直接傳到 <a href="/blog/business/knowledge-cards/venture-capital/" data-link-title="Venture Capital (VC)" data-link-desc="說明創投的投資邏輯與對新創估值的影響">新創融資</a>。</p>
<h2 id="概念位置">概念位置</h2>
<p>Valuation Compression 對新創殺傷力最大的環節是融資。同樣 ARR 1000 萬，估值從 3 億降到 5000 萬，創辦人要釋出更多股權才能融到同樣金額，<a href="/blog/business/knowledge-cards/burn-rate/" data-link-title="Burn Rate" data-link-desc="說明燒錢速度及其對新創存活的決定作用">burn rate</a> 不變但 <a href="/blog/business/knowledge-cards/runway/" data-link-title="Runway" data-link-desc="說明新創的現金跑道與融資時點">runway</a> 實質縮短。Valuation Compression 跟 <a href="/blog/business/knowledge-cards/consolidation-cycle/" data-link-title="Consolidation Cycle" data-link-desc="說明整併週期的階段特徵">整併週期</a> 常一起出現。</p>
<h2 id="可觀察訊號與例子">可觀察訊號與例子</h2>
<p>Valuation Compression 的訊號：同類公司最新一輪 down round（估值比上輪低）、IPO 估值低於上市前融資估值、收購案估值打折。AI 新創面對的壓縮來自上游 <a href="/blog/business/knowledge-cards/gross-margin/" data-link-title="Gross Margin" data-link-desc="說明毛利率與其對商業模式可行性的決定作用">毛利</a> 被基礎模型供應商拿走—算下來毛利只有 50% 出頭，VC 算估值的數字就比 SaaS 經典 70-80% 毛利時期少很多。</p>
<h2 id="判讀方式">判讀方式</h2>
<p>讀到「估值壓縮直接影響生存」時，意味著該公司即使營運沒變差，但融資環境變化讓它面臨「拿不到當初預期金額」的壓力。對創辦人來說要考慮提早融資（趁估值還沒進一步壓縮）或裁員壓縮 <a href="/blog/business/knowledge-cards/burn-rate/" data-link-title="Burn Rate" data-link-desc="說明燒錢速度及其對新創存活的決定作用">burn rate</a>。Thin wrapper 類型的新創最容易死在 valuation compression 上。</p>
]]></content:encoded></item><item><title>Unit Economics</title><link>https://tarrragon.github.io/blog/business/knowledge-cards/unit-economics/</link><pubDate>Tue, 19 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/business/knowledge-cards/unit-economics/</guid><description>&lt;p>Unit Economics 的核心概念是「服務一個客戶或賣一個單位產品到底賺不賺錢」。標準公式：&lt;a href="https://tarrragon.github.io/blog/business/knowledge-cards/ltv/" data-link-title="LTV" data-link-desc="說明客戶終身價值與其在估值中的作用">LTV&lt;/a> ÷ &lt;a href="https://tarrragon.github.io/blog/business/knowledge-cards/cac/" data-link-title="CAC" data-link-desc="說明獲客成本及其對商業模式可行性的決定作用">CAC&lt;/a> &amp;gt; 3 表示單位經濟健康。LTV 是客戶生命週期帶來的總利潤，CAC 是獲取該客戶的總成本。Unit economics 是判讀新創是否值得繼續投錢的根本。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>整家公司虧損沒關係—只要每個客戶都賺，規模放大就會獲利。Unit Economics 不健康代表「賣越多虧越多」，這種公司 &lt;a href="https://tarrragon.github.io/blog/business/knowledge-cards/valuation/" data-link-title="Valuation" data-link-desc="說明估值的構成與商業判讀作用">估值&lt;/a> 再高也是泡沫。Unit economics 由 &lt;a href="https://tarrragon.github.io/blog/business/knowledge-cards/gross-margin/" data-link-title="Gross Margin" data-link-desc="說明毛利率與其對商業模式可行性的決定作用">毛利&lt;/a>、&lt;a href="https://tarrragon.github.io/blog/business/knowledge-cards/retention/" data-link-title="Retention" data-link-desc="說明客戶留存率與其對單位經濟的決定作用">retention&lt;/a> 與 &lt;a href="https://tarrragon.github.io/blog/business/knowledge-cards/cac/" data-link-title="CAC" data-link-desc="說明獲客成本及其對商業模式可行性的決定作用">CAC&lt;/a> 三者組合決定。&lt;/p>
&lt;h2 id="可觀察訊號與例子">可觀察訊號與例子&lt;/h2>
&lt;p>判讀 unit economics 健康度：LTV/CAC &amp;gt; 3 是健康；CAC 回收期（payback period）小於 12 個月是健康；高毛利且高 retention 也是健康訊號。Uber 早期 unit economics 很差—每筆訂單還在補貼，但靠規模逐漸轉正。多數 &lt;a href="https://tarrragon.github.io/blog/business/knowledge-cards/thin-wrapper/" data-link-title="Thin Wrapper" data-link-desc="說明薄包裝產品的脆弱性">Thin Wrapper&lt;/a> 類型公司的 unit economics 從一開始就不會健康。&lt;/p>
&lt;h2 id="判讀方式">判讀方式&lt;/h2>
&lt;p>讀到「unit economics 算不過來」時，意味著該公司不只是規模問題，是賣越多虧越多。AI 新創面臨的 unit economics 挑戰是 &lt;a href="https://tarrragon.github.io/blog/business/knowledge-cards/gross-margin/" data-link-title="Gross Margin" data-link-desc="說明毛利率與其對商業模式可行性的決定作用">毛利&lt;/a> 下降同時 &lt;a href="https://tarrragon.github.io/blog/business/knowledge-cards/cac/" data-link-title="CAC" data-link-desc="說明獲客成本及其對商業模式可行性的決定作用">CAC&lt;/a> 上升（因為要 &lt;a href="https://tarrragon.github.io/blog/business/knowledge-cards/fde/" data-link-title="FDE" data-link-desc="說明前線部署工程師模式的成立條件">FDE&lt;/a> 而非 &lt;a href="https://tarrragon.github.io/blog/business/knowledge-cards/plg/" data-link-title="PLG" data-link-desc="說明產品自助成長模式與其經濟前提">PLG&lt;/a>）—兩頭夾擊讓數字難看。這就是「PLG 的數學算不過來」的具體含義。&lt;/p></description><content:encoded><![CDATA[<p>Unit Economics 的核心概念是「服務一個客戶或賣一個單位產品到底賺不賺錢」。標準公式：<a href="/blog/business/knowledge-cards/ltv/" data-link-title="LTV" data-link-desc="說明客戶終身價值與其在估值中的作用">LTV</a> ÷ <a href="/blog/business/knowledge-cards/cac/" data-link-title="CAC" data-link-desc="說明獲客成本及其對商業模式可行性的決定作用">CAC</a> &gt; 3 表示單位經濟健康。LTV 是客戶生命週期帶來的總利潤，CAC 是獲取該客戶的總成本。Unit economics 是判讀新創是否值得繼續投錢的根本。</p>
<h2 id="概念位置">概念位置</h2>
<p>整家公司虧損沒關係—只要每個客戶都賺，規模放大就會獲利。Unit Economics 不健康代表「賣越多虧越多」，這種公司 <a href="/blog/business/knowledge-cards/valuation/" data-link-title="Valuation" data-link-desc="說明估值的構成與商業判讀作用">估值</a> 再高也是泡沫。Unit economics 由 <a href="/blog/business/knowledge-cards/gross-margin/" data-link-title="Gross Margin" data-link-desc="說明毛利率與其對商業模式可行性的決定作用">毛利</a>、<a href="/blog/business/knowledge-cards/retention/" data-link-title="Retention" data-link-desc="說明客戶留存率與其對單位經濟的決定作用">retention</a> 與 <a href="/blog/business/knowledge-cards/cac/" data-link-title="CAC" data-link-desc="說明獲客成本及其對商業模式可行性的決定作用">CAC</a> 三者組合決定。</p>
<h2 id="可觀察訊號與例子">可觀察訊號與例子</h2>
<p>判讀 unit economics 健康度：LTV/CAC &gt; 3 是健康；CAC 回收期（payback period）小於 12 個月是健康；高毛利且高 retention 也是健康訊號。Uber 早期 unit economics 很差—每筆訂單還在補貼，但靠規模逐漸轉正。多數 <a href="/blog/business/knowledge-cards/thin-wrapper/" data-link-title="Thin Wrapper" data-link-desc="說明薄包裝產品的脆弱性">Thin Wrapper</a> 類型公司的 unit economics 從一開始就不會健康。</p>
<h2 id="判讀方式">判讀方式</h2>
<p>讀到「unit economics 算不過來」時，意味著該公司不只是規模問題，是賣越多虧越多。AI 新創面臨的 unit economics 挑戰是 <a href="/blog/business/knowledge-cards/gross-margin/" data-link-title="Gross Margin" data-link-desc="說明毛利率與其對商業模式可行性的決定作用">毛利</a> 下降同時 <a href="/blog/business/knowledge-cards/cac/" data-link-title="CAC" data-link-desc="說明獲客成本及其對商業模式可行性的決定作用">CAC</a> 上升（因為要 <a href="/blog/business/knowledge-cards/fde/" data-link-title="FDE" data-link-desc="說明前線部署工程師模式的成立條件">FDE</a> 而非 <a href="/blog/business/knowledge-cards/plg/" data-link-title="PLG" data-link-desc="說明產品自助成長模式與其經濟前提">PLG</a>）—兩頭夾擊讓數字難看。這就是「PLG 的數學算不過來」的具體含義。</p>
]]></content:encoded></item><item><title>LTV</title><link>https://tarrragon.github.io/blog/business/knowledge-cards/ltv/</link><pubDate>Tue, 19 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/business/knowledge-cards/ltv/</guid><description>&lt;p>LTV 的核心概念是「Lifetime Value，客戶終身價值」—一個客戶從簽約到離開、總共帶來的利潤。&lt;a href="https://tarrragon.github.io/blog/business/knowledge-cards/saas/" data-link-title="SaaS" data-link-desc="說明雲端訂閱軟體的商業模式與經濟特徵">SaaS&lt;/a> 計算公式常用：年訂閱金額 × &lt;a href="https://tarrragon.github.io/blog/business/knowledge-cards/gross-margin/" data-link-title="Gross Margin" data-link-desc="說明毛利率與其對商業模式可行性的決定作用">毛利率&lt;/a> × 平均留存年數。LTV 是 &lt;a href="https://tarrragon.github.io/blog/business/knowledge-cards/unit-economics/" data-link-title="Unit Economics" data-link-desc="說明單位經濟模型與其判斷一家公司是否賺錢的責任">單位經濟&lt;/a> 的核心參數。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>LTV 跟 &lt;a href="https://tarrragon.github.io/blog/business/knowledge-cards/cac/" data-link-title="CAC" data-link-desc="說明獲客成本及其對商業模式可行性的決定作用">CAC&lt;/a> 一起構成單位經濟。LTV 受 &lt;a href="https://tarrragon.github.io/blog/business/knowledge-cards/retention/" data-link-title="Retention" data-link-desc="說明客戶留存率與其對單位經濟的決定作用">retention&lt;/a>、&lt;a href="https://tarrragon.github.io/blog/business/knowledge-cards/gross-margin/" data-link-title="Gross Margin" data-link-desc="說明毛利率與其對商業模式可行性的決定作用">毛利&lt;/a> 與 expansion revenue（同一客戶加購）多重影響。LTV 越高，能負擔的 CAC 越高—這就是 &lt;a href="https://tarrragon.github.io/blog/business/knowledge-cards/enterprise-license/" data-link-title="Enterprise License" data-link-desc="說明企業級授權的商業模式與鎖定效應">Enterprise License&lt;/a> 為什麼能撐起 &lt;a href="https://tarrragon.github.io/blog/business/knowledge-cards/fde/" data-link-title="FDE" data-link-desc="說明前線部署工程師模式的成立條件">FDE&lt;/a> 的高 CAC。&lt;/p>
&lt;h2 id="可觀察訊號與例子">可觀察訊號與例子&lt;/h2>
&lt;p>判讀 LTV：高訂閱費 × 長留存 × 高毛利 = 高 LTV。Palantir 一個 enterprise 客戶 LTV 可達數千萬美金（合約大、留得久）；PLG 工具一個客戶 LTV 可能只有幾百到幾千美金。LTV 算出來看起來很大時要警覺—它依賴對未來留存的樂觀假設，假設崩了 LTV 也崩。&lt;/p>
&lt;h2 id="判讀方式">判讀方式&lt;/h2>
&lt;p>讀到「LTV 下降」時，意味著 &lt;a href="https://tarrragon.github.io/blog/business/knowledge-cards/retention/" data-link-title="Retention" data-link-desc="說明客戶留存率與其對單位經濟的決定作用">retention&lt;/a> 變差、&lt;a href="https://tarrragon.github.io/blog/business/knowledge-cards/gross-margin/" data-link-title="Gross Margin" data-link-desc="說明毛利率與其對商業模式可行性的決定作用">毛利&lt;/a> 變差或單客單價降低。AI 時代 LTV 計算變難—因為 &lt;a href="https://tarrragon.github.io/blog/business/knowledge-cards/switching-cost/" data-link-title="Switching Cost" data-link-desc="說明切換成本如何鞏固客戶留存">切換成本&lt;/a> 下降，客戶可能隨時換模型，留存假設不能用傳統 SaaS 的數字。這直接影響 &lt;a href="https://tarrragon.github.io/blog/business/knowledge-cards/valuation/" data-link-title="Valuation" data-link-desc="說明估值的構成與商業判讀作用">估值&lt;/a> 計算。&lt;/p></description><content:encoded><![CDATA[<p>LTV 的核心概念是「Lifetime Value，客戶終身價值」—一個客戶從簽約到離開、總共帶來的利潤。<a href="/blog/business/knowledge-cards/saas/" data-link-title="SaaS" data-link-desc="說明雲端訂閱軟體的商業模式與經濟特徵">SaaS</a> 計算公式常用：年訂閱金額 × <a href="/blog/business/knowledge-cards/gross-margin/" data-link-title="Gross Margin" data-link-desc="說明毛利率與其對商業模式可行性的決定作用">毛利率</a> × 平均留存年數。LTV 是 <a href="/blog/business/knowledge-cards/unit-economics/" data-link-title="Unit Economics" data-link-desc="說明單位經濟模型與其判斷一家公司是否賺錢的責任">單位經濟</a> 的核心參數。</p>
<h2 id="概念位置">概念位置</h2>
<p>LTV 跟 <a href="/blog/business/knowledge-cards/cac/" data-link-title="CAC" data-link-desc="說明獲客成本及其對商業模式可行性的決定作用">CAC</a> 一起構成單位經濟。LTV 受 <a href="/blog/business/knowledge-cards/retention/" data-link-title="Retention" data-link-desc="說明客戶留存率與其對單位經濟的決定作用">retention</a>、<a href="/blog/business/knowledge-cards/gross-margin/" data-link-title="Gross Margin" data-link-desc="說明毛利率與其對商業模式可行性的決定作用">毛利</a> 與 expansion revenue（同一客戶加購）多重影響。LTV 越高，能負擔的 CAC 越高—這就是 <a href="/blog/business/knowledge-cards/enterprise-license/" data-link-title="Enterprise License" data-link-desc="說明企業級授權的商業模式與鎖定效應">Enterprise License</a> 為什麼能撐起 <a href="/blog/business/knowledge-cards/fde/" data-link-title="FDE" data-link-desc="說明前線部署工程師模式的成立條件">FDE</a> 的高 CAC。</p>
<h2 id="可觀察訊號與例子">可觀察訊號與例子</h2>
<p>判讀 LTV：高訂閱費 × 長留存 × 高毛利 = 高 LTV。Palantir 一個 enterprise 客戶 LTV 可達數千萬美金（合約大、留得久）；PLG 工具一個客戶 LTV 可能只有幾百到幾千美金。LTV 算出來看起來很大時要警覺—它依賴對未來留存的樂觀假設，假設崩了 LTV 也崩。</p>
<h2 id="判讀方式">判讀方式</h2>
<p>讀到「LTV 下降」時，意味著 <a href="/blog/business/knowledge-cards/retention/" data-link-title="Retention" data-link-desc="說明客戶留存率與其對單位經濟的決定作用">retention</a> 變差、<a href="/blog/business/knowledge-cards/gross-margin/" data-link-title="Gross Margin" data-link-desc="說明毛利率與其對商業模式可行性的決定作用">毛利</a> 變差或單客單價降低。AI 時代 LTV 計算變難—因為 <a href="/blog/business/knowledge-cards/switching-cost/" data-link-title="Switching Cost" data-link-desc="說明切換成本如何鞏固客戶留存">切換成本</a> 下降，客戶可能隨時換模型，留存假設不能用傳統 SaaS 的數字。這直接影響 <a href="/blog/business/knowledge-cards/valuation/" data-link-title="Valuation" data-link-desc="說明估值的構成與商業判讀作用">估值</a> 計算。</p>
]]></content:encoded></item><item><title>Tacit Knowledge</title><link>https://tarrragon.github.io/blog/business/knowledge-cards/tacit-knowledge/</link><pubDate>Tue, 19 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/business/knowledge-cards/tacit-knowledge/</guid><description>&lt;p>Tacit Knowledge 的核心概念是「隱性知識」—資深員工腦袋裡知道、但寫不進 SOP 或文件的知識。判斷 case 該怎麼處理、客戶潛規則、行業慣例、灰色地帶決策—這些都是 tacit。對應概念是 explicit knowledge（顯性知識，可文件化）。Tacit knowledge 是 &lt;a href="https://tarrragon.github.io/blog/business/knowledge-cards/fat-data-fat-skill/" data-link-title="Fat Data / Fat Skill" data-link-desc="說明獨家資料與行業隱性能力作為 AI 時代的護城河">Fat Skill&lt;/a> 的核心構成。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>Tacit Knowledge 在 AI 時代變得更值錢—因為 explicit knowledge 容易被 AI 取代，tacit knowledge 不容易。AI 產品要做好行業應用，必須把 tacit knowledge 萃取出來編碼到 &lt;a href="https://tarrragon.github.io/blog/business/knowledge-cards/evaluation-set/" data-link-title="Evaluation Set" data-link-desc="說明評估集如何把隱性知識編碼進 AI 產品">evaluation set&lt;/a>。這個萃取過程就是 &lt;a href="https://tarrragon.github.io/blog/business/knowledge-cards/fde/" data-link-title="FDE" data-link-desc="說明前線部署工程師模式的成立條件">FDE&lt;/a> 的核心工作。&lt;/p>
&lt;h2 id="可觀察訊號與例子">可觀察訊號與例子&lt;/h2>
&lt;p>Tacit Knowledge 的訊號：資深員工說「這個 case 不能這樣處理因為某某理由」但說不清楚理由；公司內部訓練主要靠 shadowing（跟著資深做）而非看文件；初入該領域者錯誤常出在「不知道有這個規則」而非「不會操作」。理賠專員「這份賠但那份不賠」的判斷是典型 tacit。&lt;/p>
&lt;h2 id="判讀方式">判讀方式&lt;/h2>
&lt;p>讀到「tacit knowledge 寫不進 SOP」時，意味著該領域不能靠純軟體解決—必須有人坐在客戶端萃取。這就是 &lt;a href="https://tarrragon.github.io/blog/business/knowledge-cards/fde/" data-link-title="FDE" data-link-desc="說明前線部署工程師模式的成立條件">FDE&lt;/a> 模式的成立前提：客戶說「我要一個 agent」資訊量太低，要在現場跑真實 case 才能把 tacit 編碼。Tacit knowledge 累積成 &lt;a href="https://tarrragon.github.io/blog/business/knowledge-cards/fat-data-fat-skill/" data-link-title="Fat Data / Fat Skill" data-link-desc="說明獨家資料與行業隱性能力作為 AI 時代的護城河">Fat Skill&lt;/a> 後就形成 AI 時代仍然有效的護城河。&lt;/p></description><content:encoded><![CDATA[<p>Tacit Knowledge 的核心概念是「隱性知識」—資深員工腦袋裡知道、但寫不進 SOP 或文件的知識。判斷 case 該怎麼處理、客戶潛規則、行業慣例、灰色地帶決策—這些都是 tacit。對應概念是 explicit knowledge（顯性知識，可文件化）。Tacit knowledge 是 <a href="/blog/business/knowledge-cards/fat-data-fat-skill/" data-link-title="Fat Data / Fat Skill" data-link-desc="說明獨家資料與行業隱性能力作為 AI 時代的護城河">Fat Skill</a> 的核心構成。</p>
<h2 id="概念位置">概念位置</h2>
<p>Tacit Knowledge 在 AI 時代變得更值錢—因為 explicit knowledge 容易被 AI 取代，tacit knowledge 不容易。AI 產品要做好行業應用，必須把 tacit knowledge 萃取出來編碼到 <a href="/blog/business/knowledge-cards/evaluation-set/" data-link-title="Evaluation Set" data-link-desc="說明評估集如何把隱性知識編碼進 AI 產品">evaluation set</a>。這個萃取過程就是 <a href="/blog/business/knowledge-cards/fde/" data-link-title="FDE" data-link-desc="說明前線部署工程師模式的成立條件">FDE</a> 的核心工作。</p>
<h2 id="可觀察訊號與例子">可觀察訊號與例子</h2>
<p>Tacit Knowledge 的訊號：資深員工說「這個 case 不能這樣處理因為某某理由」但說不清楚理由；公司內部訓練主要靠 shadowing（跟著資深做）而非看文件；初入該領域者錯誤常出在「不知道有這個規則」而非「不會操作」。理賠專員「這份賠但那份不賠」的判斷是典型 tacit。</p>
<h2 id="判讀方式">判讀方式</h2>
<p>讀到「tacit knowledge 寫不進 SOP」時，意味著該領域不能靠純軟體解決—必須有人坐在客戶端萃取。這就是 <a href="/blog/business/knowledge-cards/fde/" data-link-title="FDE" data-link-desc="說明前線部署工程師模式的成立條件">FDE</a> 模式的成立前提：客戶說「我要一個 agent」資訊量太低，要在現場跑真實 case 才能把 tacit 編碼。Tacit knowledge 累積成 <a href="/blog/business/knowledge-cards/fat-data-fat-skill/" data-link-title="Fat Data / Fat Skill" data-link-desc="說明獨家資料與行業隱性能力作為 AI 時代的護城河">Fat Skill</a> 後就形成 AI 時代仍然有效的護城河。</p>
]]></content:encoded></item><item><title>Evaluation Set</title><link>https://tarrragon.github.io/blog/business/knowledge-cards/evaluation-set/</link><pubDate>Tue, 19 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/business/knowledge-cards/evaluation-set/</guid><description>&lt;p>Evaluation Set 的核心概念是「評估集」—用來測試 AI 模型表現好不好的測試資料集。一組 input + 期望 output + 通過判準，AI 跑出來的結果跟期望比對判斷是否合格。Evaluation Set 是 &lt;a href="https://tarrragon.github.io/blog/business/knowledge-cards/tacit-knowledge/" data-link-title="Tacit Knowledge" data-link-desc="說明隱性知識與其作為護城河的價值">Tacit Knowledge&lt;/a> 的編碼形式。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>Evaluation Set 是 AI 產品開發的核心 artifact。對 AI Labs 來說它是模型訓練的方向盤；對企業 AI 應用來說它是把客戶腦袋裡的「這個 case 該怎麼處理」轉成可測試的資料點。&lt;a href="https://tarrragon.github.io/blog/business/knowledge-cards/fde/" data-link-title="FDE" data-link-desc="說明前線部署工程師模式的成立條件">FDE&lt;/a> 駐點工作的最終產出，本質就是該客戶的 evaluation set。&lt;/p>
&lt;h2 id="可觀察訊號與例子">可觀察訊號與例子&lt;/h2>
&lt;p>Evaluation Set 的訊號：一組客戶實際遇到的 case + 業務專家標註的正確處理方式。例如保險理賠 evaluation set 會包含「這份理賠該批准 / 該拒絕 / 該調查」的歷史 case，AI 跑過要對得起來。Evaluation set 通常隨服務時間累積增大，新 edge case 不斷加入。&lt;/p>
&lt;h2 id="判讀方式">判讀方式&lt;/h2>
&lt;p>讀到「把 tacit knowledge encode 進 evaluation set」時，意味著該公司在做的不只是「賣 AI」而是「把客戶的判斷邏輯萃取進產品」。這就是 &lt;a href="https://tarrragon.github.io/blog/business/knowledge-cards/fde/" data-link-title="FDE" data-link-desc="說明前線部署工程師模式的成立條件">FDE&lt;/a> 在做的核心工作—現場跑案例、跟業務人員迭代、用業務人員的修正建立 evaluation set。Evaluation set 一旦累積到一定深度，就是該客戶獨有的 &lt;a href="https://tarrragon.github.io/blog/business/knowledge-cards/fat-data-fat-skill/" data-link-title="Fat Data / Fat Skill" data-link-desc="說明獨家資料與行業隱性能力作為 AI 時代的護城河">Fat Data&lt;/a>。&lt;/p></description><content:encoded><![CDATA[<p>Evaluation Set 的核心概念是「評估集」—用來測試 AI 模型表現好不好的測試資料集。一組 input + 期望 output + 通過判準，AI 跑出來的結果跟期望比對判斷是否合格。Evaluation Set 是 <a href="/blog/business/knowledge-cards/tacit-knowledge/" data-link-title="Tacit Knowledge" data-link-desc="說明隱性知識與其作為護城河的價值">Tacit Knowledge</a> 的編碼形式。</p>
<h2 id="概念位置">概念位置</h2>
<p>Evaluation Set 是 AI 產品開發的核心 artifact。對 AI Labs 來說它是模型訓練的方向盤；對企業 AI 應用來說它是把客戶腦袋裡的「這個 case 該怎麼處理」轉成可測試的資料點。<a href="/blog/business/knowledge-cards/fde/" data-link-title="FDE" data-link-desc="說明前線部署工程師模式的成立條件">FDE</a> 駐點工作的最終產出，本質就是該客戶的 evaluation set。</p>
<h2 id="可觀察訊號與例子">可觀察訊號與例子</h2>
<p>Evaluation Set 的訊號：一組客戶實際遇到的 case + 業務專家標註的正確處理方式。例如保險理賠 evaluation set 會包含「這份理賠該批准 / 該拒絕 / 該調查」的歷史 case，AI 跑過要對得起來。Evaluation set 通常隨服務時間累積增大，新 edge case 不斷加入。</p>
<h2 id="判讀方式">判讀方式</h2>
<p>讀到「把 tacit knowledge encode 進 evaluation set」時，意味著該公司在做的不只是「賣 AI」而是「把客戶的判斷邏輯萃取進產品」。這就是 <a href="/blog/business/knowledge-cards/fde/" data-link-title="FDE" data-link-desc="說明前線部署工程師模式的成立條件">FDE</a> 在做的核心工作—現場跑案例、跟業務人員迭代、用業務人員的修正建立 evaluation set。Evaluation set 一旦累積到一定深度，就是該客戶獨有的 <a href="/blog/business/knowledge-cards/fat-data-fat-skill/" data-link-title="Fat Data / Fat Skill" data-link-desc="說明獨家資料與行業隱性能力作為 AI 時代的護城河">Fat Data</a>。</p>
]]></content:encoded></item><item><title>PRD</title><link>https://tarrragon.github.io/blog/business/knowledge-cards/prd/</link><pubDate>Tue, 19 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/business/knowledge-cards/prd/</guid><description>&lt;p>PRD 的核心概念是「Product Requirements Document，產品需求文件」—描述要做什麼產品、給誰用、解決什麼問題、長什麼樣的文件。傳統 &lt;a href="https://tarrragon.github.io/blog/business/knowledge-cards/saas/" data-link-title="SaaS" data-link-desc="說明雲端訂閱軟體的商業模式與經濟特徵">SaaS&lt;/a> 開發流程：客戶訪談 → 寫 PRD → 做 &lt;a href="https://tarrragon.github.io/blog/business/knowledge-cards/wireframe/" data-link-title="Wireframe" data-link-desc="說明線框圖在傳統產品設計流程中的角色">wireframe&lt;/a> → 跑使用者測試 → 開發。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>PRD 是 SaaS 時代「先用文字描述產品再開發」的核心 artifact。它的前提是「需求可以用語言描述清楚」—多數傳統軟體需求都可以。AI 產品的需求常常無法用 PRD 寫清楚，這是 &lt;a href="https://tarrragon.github.io/blog/business/knowledge-cards/fde/" data-link-title="FDE" data-link-desc="說明前線部署工程師模式的成立條件">FDE&lt;/a> 與 &lt;a href="https://tarrragon.github.io/blog/business/knowledge-cards/vibe-code/" data-link-title="Vibe Code" data-link-desc="說明用 AI 即時生成程式的開發模式">Vibe Code&lt;/a> 出現的核心理由。&lt;/p>
&lt;h2 id="可觀察訊號與例子">可觀察訊號與例子&lt;/h2>
&lt;p>PRD 的典型欄位：背景、目標、使用者、流程、UI、非功能性需求、上線判準。產品經理常用 PRD 對齊跨團隊—工程、設計、QA 都看同一份。Notion 上常見的「Product Spec」「Feature Brief」都是 PRD 的變體。&lt;/p>
&lt;h2 id="判讀方式">判讀方式&lt;/h2>
&lt;p>讀到「AI native 應用沒辦法用 PRD 做」這類論述時，意味著該作者認為傳統 SaaS 流程不適用 AI—因為 AI 的輸出在跑之前看不到，沒辦法事先寫死期望。這就是為什麼要現場迭代跟 &lt;a href="https://tarrragon.github.io/blog/business/knowledge-cards/fde/" data-link-title="FDE" data-link-desc="說明前線部署工程師模式的成立條件">FDE&lt;/a> 駐點，不能遠端用 PRD 規劃。PRD 的「先描述後實作」邏輯在 AI 產品開發中失效是這波商業化轉向的核心訊號。&lt;/p></description><content:encoded><![CDATA[<p>PRD 的核心概念是「Product Requirements Document，產品需求文件」—描述要做什麼產品、給誰用、解決什麼問題、長什麼樣的文件。傳統 <a href="/blog/business/knowledge-cards/saas/" data-link-title="SaaS" data-link-desc="說明雲端訂閱軟體的商業模式與經濟特徵">SaaS</a> 開發流程：客戶訪談 → 寫 PRD → 做 <a href="/blog/business/knowledge-cards/wireframe/" data-link-title="Wireframe" data-link-desc="說明線框圖在傳統產品設計流程中的角色">wireframe</a> → 跑使用者測試 → 開發。</p>
<h2 id="概念位置">概念位置</h2>
<p>PRD 是 SaaS 時代「先用文字描述產品再開發」的核心 artifact。它的前提是「需求可以用語言描述清楚」—多數傳統軟體需求都可以。AI 產品的需求常常無法用 PRD 寫清楚，這是 <a href="/blog/business/knowledge-cards/fde/" data-link-title="FDE" data-link-desc="說明前線部署工程師模式的成立條件">FDE</a> 與 <a href="/blog/business/knowledge-cards/vibe-code/" data-link-title="Vibe Code" data-link-desc="說明用 AI 即時生成程式的開發模式">Vibe Code</a> 出現的核心理由。</p>
<h2 id="可觀察訊號與例子">可觀察訊號與例子</h2>
<p>PRD 的典型欄位：背景、目標、使用者、流程、UI、非功能性需求、上線判準。產品經理常用 PRD 對齊跨團隊—工程、設計、QA 都看同一份。Notion 上常見的「Product Spec」「Feature Brief」都是 PRD 的變體。</p>
<h2 id="判讀方式">判讀方式</h2>
<p>讀到「AI native 應用沒辦法用 PRD 做」這類論述時，意味著該作者認為傳統 SaaS 流程不適用 AI—因為 AI 的輸出在跑之前看不到，沒辦法事先寫死期望。這就是為什麼要現場迭代跟 <a href="/blog/business/knowledge-cards/fde/" data-link-title="FDE" data-link-desc="說明前線部署工程師模式的成立條件">FDE</a> 駐點，不能遠端用 PRD 規劃。PRD 的「先描述後實作」邏輯在 AI 產品開發中失效是這波商業化轉向的核心訊號。</p>
]]></content:encoded></item><item><title>Wireframe</title><link>https://tarrragon.github.io/blog/business/knowledge-cards/wireframe/</link><pubDate>Tue, 19 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/business/knowledge-cards/wireframe/</guid><description>&lt;p>Wireframe 的核心概念是「線框圖」—用簡單線條表示 UI 結構與資訊流的草圖，不含顏色、字型、圖像。它的目的是讓設計師、工程師、PM 對齊「畫面上有什麼、按了會去哪」，不討論視覺風格。Wireframe 是 &lt;a href="https://tarrragon.github.io/blog/business/knowledge-cards/prd/" data-link-title="PRD" data-link-desc="說明產品需求文件與其在傳統 SaaS 開發中的角色">PRD&lt;/a> 之後、設計稿之前的中間 artifact。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>Wireframe 在傳統 SaaS 開發中承擔「視覺化需求」的責任—把 PRD 的文字轉成畫面草圖，讓利害關係人能評論。它依賴的前提是「產品的核心價值可以用 UI 描述」。AI 產品的核心價值在 AI 行為而非 UI，wireframe 描述不了，就需要 &lt;a href="https://tarrragon.github.io/blog/business/knowledge-cards/vibe-code/" data-link-title="Vibe Code" data-link-desc="說明用 AI 即時生成程式的開發模式">Vibe Code&lt;/a> 現場跑。&lt;/p>
&lt;h2 id="可觀察訊號與例子">可觀察訊號與例子&lt;/h2>
&lt;p>Wireframe 的訊號：黑白線條、灰塊代表圖、虛擬文字（lorem ipsum）佔位、箭頭表示流程跳轉。Figma、Sketch、Balsamiq 都是常見工具。Wireframe 通常會跟 user flow（流程圖）一起出現，形成完整的需求視覺化。&lt;/p>
&lt;h2 id="判讀方式">判讀方式&lt;/h2>
&lt;p>讀到「AI 不能靠 wireframe 描述」時，意味著該產品的核心價值在 AI 行為而非 UI—wireframe 畫得再漂亮也描述不出 AI 跑出來會多準確。這是 AI 產品開發跟傳統 SaaS 的根本差異—描述工具失效後，&lt;a href="https://tarrragon.github.io/blog/business/knowledge-cards/fde/" data-link-title="FDE" data-link-desc="說明前線部署工程師模式的成立條件">FDE&lt;/a> 現場迭代成為唯一可行路徑。&lt;/p></description><content:encoded><![CDATA[<p>Wireframe 的核心概念是「線框圖」—用簡單線條表示 UI 結構與資訊流的草圖，不含顏色、字型、圖像。它的目的是讓設計師、工程師、PM 對齊「畫面上有什麼、按了會去哪」，不討論視覺風格。Wireframe 是 <a href="/blog/business/knowledge-cards/prd/" data-link-title="PRD" data-link-desc="說明產品需求文件與其在傳統 SaaS 開發中的角色">PRD</a> 之後、設計稿之前的中間 artifact。</p>
<h2 id="概念位置">概念位置</h2>
<p>Wireframe 在傳統 SaaS 開發中承擔「視覺化需求」的責任—把 PRD 的文字轉成畫面草圖，讓利害關係人能評論。它依賴的前提是「產品的核心價值可以用 UI 描述」。AI 產品的核心價值在 AI 行為而非 UI，wireframe 描述不了，就需要 <a href="/blog/business/knowledge-cards/vibe-code/" data-link-title="Vibe Code" data-link-desc="說明用 AI 即時生成程式的開發模式">Vibe Code</a> 現場跑。</p>
<h2 id="可觀察訊號與例子">可觀察訊號與例子</h2>
<p>Wireframe 的訊號：黑白線條、灰塊代表圖、虛擬文字（lorem ipsum）佔位、箭頭表示流程跳轉。Figma、Sketch、Balsamiq 都是常見工具。Wireframe 通常會跟 user flow（流程圖）一起出現，形成完整的需求視覺化。</p>
<h2 id="判讀方式">判讀方式</h2>
<p>讀到「AI 不能靠 wireframe 描述」時，意味著該產品的核心價值在 AI 行為而非 UI—wireframe 畫得再漂亮也描述不出 AI 跑出來會多準確。這是 AI 產品開發跟傳統 SaaS 的根本差異—描述工具失效後，<a href="/blog/business/knowledge-cards/fde/" data-link-title="FDE" data-link-desc="說明前線部署工程師模式的成立條件">FDE</a> 現場迭代成為唯一可行路徑。</p>
]]></content:encoded></item><item><title>Vibe Code</title><link>https://tarrragon.github.io/blog/business/knowledge-cards/vibe-code/</link><pubDate>Tue, 19 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/business/knowledge-cards/vibe-code/</guid><description>&lt;p>Vibe Code 的核心概念是「靠感覺寫程式」—不一行一行手敲，而是丟描述給 AI、AI 生程式碼、看結果改描述、再生一次。Cursor、Claude Code、Windsurf 把開發週期從「打字幾天」壓到「描述幾分鐘」。Vibe Code 改變了 &lt;a href="https://tarrragon.github.io/blog/business/knowledge-cards/fde/" data-link-title="FDE" data-link-desc="說明前線部署工程師模式的成立條件">FDE&lt;/a> 的 &lt;a href="https://tarrragon.github.io/blog/business/knowledge-cards/unit-economics/" data-link-title="Unit Economics" data-link-desc="說明單位經濟模型與其判斷一家公司是否賺錢的責任">單位經濟&lt;/a>。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>Vibe Code 是 AI 編程工具帶來的工作模式改變。它的存在讓 FDE 經濟學成立—一個工程師原本要幾週才能做出原型，現在會議室內幾小時搞定，產能變三到五倍。原本只有 Palantir 玩得起的 FDE 模式，靠 Vibe Code 下沉到中型企業市場成為可能。&lt;/p>
&lt;h2 id="可觀察訊號與例子">可觀察訊號與例子&lt;/h2>
&lt;p>Vibe Code 的訊號：開發者描述「我要一個處理 OAuth 的 endpoint」AI 直接生出可跑的程式；遇到 bug 描述問題 AI 直接補 patch；不寫 spec 直接迭代。Buf 的 Bufstream 開發、AI Labs 的 FDE 在客戶會議室生原型都是 vibe code 在用。&lt;/p>
&lt;h2 id="判讀方式">判讀方式&lt;/h2>
&lt;p>讀到「vibe code 改變了 FDE 經濟學」時，意味著 AI 編程工具不只是提升個別工程師效率，而是讓「派工程師駐點」這個 GTM 模式可規模化。它把 Palantir 模式從「只有它玩得起」變成「&lt;a href="https://tarrragon.github.io/blog/business/knowledge-cards/private-equity/" data-link-title="Private Equity (PE)" data-link-desc="說明私募基金與其對中型企業市場的策略意涵">PE&lt;/a> 旗下中型企業都能用 FDE」—這是 Anthropic 鎖定 PE 投資組合的結構性原因。&lt;/p></description><content:encoded><![CDATA[<p>Vibe Code 的核心概念是「靠感覺寫程式」—不一行一行手敲，而是丟描述給 AI、AI 生程式碼、看結果改描述、再生一次。Cursor、Claude Code、Windsurf 把開發週期從「打字幾天」壓到「描述幾分鐘」。Vibe Code 改變了 <a href="/blog/business/knowledge-cards/fde/" data-link-title="FDE" data-link-desc="說明前線部署工程師模式的成立條件">FDE</a> 的 <a href="/blog/business/knowledge-cards/unit-economics/" data-link-title="Unit Economics" data-link-desc="說明單位經濟模型與其判斷一家公司是否賺錢的責任">單位經濟</a>。</p>
<h2 id="概念位置">概念位置</h2>
<p>Vibe Code 是 AI 編程工具帶來的工作模式改變。它的存在讓 FDE 經濟學成立—一個工程師原本要幾週才能做出原型，現在會議室內幾小時搞定，產能變三到五倍。原本只有 Palantir 玩得起的 FDE 模式，靠 Vibe Code 下沉到中型企業市場成為可能。</p>
<h2 id="可觀察訊號與例子">可觀察訊號與例子</h2>
<p>Vibe Code 的訊號：開發者描述「我要一個處理 OAuth 的 endpoint」AI 直接生出可跑的程式；遇到 bug 描述問題 AI 直接補 patch；不寫 spec 直接迭代。Buf 的 Bufstream 開發、AI Labs 的 FDE 在客戶會議室生原型都是 vibe code 在用。</p>
<h2 id="判讀方式">判讀方式</h2>
<p>讀到「vibe code 改變了 FDE 經濟學」時，意味著 AI 編程工具不只是提升個別工程師效率，而是讓「派工程師駐點」這個 GTM 模式可規模化。它把 Palantir 模式從「只有它玩得起」變成「<a href="/blog/business/knowledge-cards/private-equity/" data-link-title="Private Equity (PE)" data-link-desc="說明私募基金與其對中型企業市場的策略意涵">PE</a> 旗下中型企業都能用 FDE」—這是 Anthropic 鎖定 PE 投資組合的結構性原因。</p>
]]></content:encoded></item><item><title>Judgment Stake</title><link>https://tarrragon.github.io/blog/business/knowledge-cards/judgment-stake/</link><pubDate>Tue, 19 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/business/knowledge-cards/judgment-stake/</guid><description>&lt;p>Judgment Stake 的核心概念是「判斷的賭注被放大」—AI 接走低價值執行工作（找資料、做表、起草文件）後，剩下的判斷工作每次出錯的代價變高。原本資深角色靠 &lt;a href="https://tarrragon.github.io/blog/business/knowledge-cards/junior-buffer/" data-link-title="Junior Buffer" data-link-desc="說明初階員工作為組織判斷緩衝的傳統結構">junior buffer&lt;/a> 吸收判斷失誤，buffer 沒了之後判斷直接面對結果。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>Judgment Stake 是 AI 取代論的核心反論。它說明的不是「AI 取代誰」，而是「AI 改變了哪層工作的風險分布」。執行層被 AI 接走，判斷層的單次重要性放大—因為錯了沒人擋。這個框架可以套到律師、財務、顧問、醫師等各類知識工作者。&lt;/p>
&lt;h2 id="可觀察訊號與例子">可觀察訊號與例子&lt;/h2>
&lt;p>Judgment Stake 放大的訊號：律師 associate、財務 junior、顧問 analyst 的工作被 AI 取代後，資深合夥人簽字的每個判斷都直接生效；醫師看 AI 報告直接做治療決定，沒有住院醫師再核對。這些情境下判斷失誤的代價提高，導致資深角色短期不敢放手給 AI。&lt;/p>
&lt;h2 id="判讀方式">判讀方式&lt;/h2>
&lt;p>讀到「AI 不會取代資深角色，只會放大其賭注」時，意味著該作者認為 AI 影響的主要對象是中段執行—頭部因為 stake 提高反而更值錢。這個觀察可以套到任何「AI 進入某職能」的情境—問「執行被取代、判斷怎麼樣」就能推導出影響輪廓。&lt;/p></description><content:encoded><![CDATA[<p>Judgment Stake 的核心概念是「判斷的賭注被放大」—AI 接走低價值執行工作（找資料、做表、起草文件）後，剩下的判斷工作每次出錯的代價變高。原本資深角色靠 <a href="/blog/business/knowledge-cards/junior-buffer/" data-link-title="Junior Buffer" data-link-desc="說明初階員工作為組織判斷緩衝的傳統結構">junior buffer</a> 吸收判斷失誤，buffer 沒了之後判斷直接面對結果。</p>
<h2 id="概念位置">概念位置</h2>
<p>Judgment Stake 是 AI 取代論的核心反論。它說明的不是「AI 取代誰」，而是「AI 改變了哪層工作的風險分布」。執行層被 AI 接走，判斷層的單次重要性放大—因為錯了沒人擋。這個框架可以套到律師、財務、顧問、醫師等各類知識工作者。</p>
<h2 id="可觀察訊號與例子">可觀察訊號與例子</h2>
<p>Judgment Stake 放大的訊號：律師 associate、財務 junior、顧問 analyst 的工作被 AI 取代後，資深合夥人簽字的每個判斷都直接生效；醫師看 AI 報告直接做治療決定，沒有住院醫師再核對。這些情境下判斷失誤的代價提高，導致資深角色短期不敢放手給 AI。</p>
<h2 id="判讀方式">判讀方式</h2>
<p>讀到「AI 不會取代資深角色，只會放大其賭注」時，意味著該作者認為 AI 影響的主要對象是中段執行—頭部因為 stake 提高反而更值錢。這個觀察可以套到任何「AI 進入某職能」的情境—問「執行被取代、判斷怎麼樣」就能推導出影響輪廓。</p>
]]></content:encoded></item><item><title>Junior Buffer</title><link>https://tarrragon.github.io/blog/business/knowledge-cards/junior-buffer/</link><pubDate>Tue, 19 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/business/knowledge-cards/junior-buffer/</guid><description>&lt;p>Junior Buffer 的核心概念是「初階員工作為判斷緩衝層」—資深員工的判斷先讓 junior 做一版、看過修改、錯了還能擋下來，不直接生效。這層緩衝吸收判斷成本，讓資深可以放手做更多決策。Junior Buffer 是傳統知識工作者組織的隱性設計，跟 &lt;a href="https://tarrragon.github.io/blog/business/knowledge-cards/judgment-stake/" data-link-title="Judgment Stake" data-link-desc="說明判斷的賭注被 AI 放大的結構">Judgment Stake&lt;/a> 是一體兩面。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>Junior Buffer 出現在多數知識工作職業的階梯結構中：律師事務所的 partner-associate、投行的 MD-VP-analyst、顧問公司的 partner-consultant、醫院的 attending-resident。AI 接走 junior 工作後，這個緩衝層消失，&lt;a href="https://tarrragon.github.io/blog/business/knowledge-cards/judgment-stake/" data-link-title="Judgment Stake" data-link-desc="說明判斷的賭注被 AI 放大的結構">判斷的賭注&lt;/a> 被放大。&lt;/p>
&lt;h2 id="可觀察訊號與例子">可觀察訊號與例子&lt;/h2>
&lt;p>Junior Buffer 的訊號：資深角色不直接做執行（查資料、起草、做表），由 junior 先做一版；junior 工作出錯資深會發現並修；junior 隨年資累積最終升上資深。律師事務所 partner 看 associate 寫的 memo、投行 MD 看 analyst 做的財務模型，都是這個 buffer 在運作。&lt;/p>
&lt;h2 id="判讀方式">判讀方式&lt;/h2>
&lt;p>讀到「junior buffer 沒了」時，意味著該作者認為 AI 不只是取代基層工作，還影響組織的判斷風險分布。對組織來說要重新設計「沒有 junior 的判斷流程」—例如多層交叉複核、AI 跑多種選項給資深選、保留小規模 junior 純粹作為訓練資深的管道。長遠看，AI 時代的職涯階梯可能從金字塔變成沙漏—中段消失、頭尾留存。&lt;/p></description><content:encoded><![CDATA[<p>Junior Buffer 的核心概念是「初階員工作為判斷緩衝層」—資深員工的判斷先讓 junior 做一版、看過修改、錯了還能擋下來，不直接生效。這層緩衝吸收判斷成本，讓資深可以放手做更多決策。Junior Buffer 是傳統知識工作者組織的隱性設計，跟 <a href="/blog/business/knowledge-cards/judgment-stake/" data-link-title="Judgment Stake" data-link-desc="說明判斷的賭注被 AI 放大的結構">Judgment Stake</a> 是一體兩面。</p>
<h2 id="概念位置">概念位置</h2>
<p>Junior Buffer 出現在多數知識工作職業的階梯結構中：律師事務所的 partner-associate、投行的 MD-VP-analyst、顧問公司的 partner-consultant、醫院的 attending-resident。AI 接走 junior 工作後，這個緩衝層消失，<a href="/blog/business/knowledge-cards/judgment-stake/" data-link-title="Judgment Stake" data-link-desc="說明判斷的賭注被 AI 放大的結構">判斷的賭注</a> 被放大。</p>
<h2 id="可觀察訊號與例子">可觀察訊號與例子</h2>
<p>Junior Buffer 的訊號：資深角色不直接做執行（查資料、起草、做表），由 junior 先做一版；junior 工作出錯資深會發現並修；junior 隨年資累積最終升上資深。律師事務所 partner 看 associate 寫的 memo、投行 MD 看 analyst 做的財務模型，都是這個 buffer 在運作。</p>
<h2 id="判讀方式">判讀方式</h2>
<p>讀到「junior buffer 沒了」時，意味著該作者認為 AI 不只是取代基層工作，還影響組織的判斷風險分布。對組織來說要重新設計「沒有 junior 的判斷流程」—例如多層交叉複核、AI 跑多種選項給資深選、保留小規模 junior 純粹作為訓練資深的管道。長遠看，AI 時代的職涯階梯可能從金字塔變成沙漏—中段消失、頭尾留存。</p>
]]></content:encoded></item><item><title>Dotfile 術語卡</title><link>https://tarrragon.github.io/blog/linux/dotfile/knowledge-cards/</link><pubDate>Mon, 29 Jun 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/linux/dotfile/knowledge-cards/</guid><description>&lt;p>本系列使用的關鍵術語。各卡片會在對應章節深入說明、這裡提供快速查閱入口。&lt;/p>
&lt;p>術語卡會隨教材擴展逐步補充。&lt;/p>
&lt;h2 id="語言與工具">語言與工具&lt;/h2>
&lt;table>
 &lt;thead>
 &lt;tr>
 &lt;th>卡片&lt;/th>
 &lt;th>主題&lt;/th>
 &lt;/tr>
 &lt;/thead>
 &lt;tbody>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/linux/dotfile/knowledge-cards/lua-scripting-language/" data-link-title="Lua 腳本語言" data-link-desc="在 Hyprland 或 Neovim 配置檔遇到 Lua 語法看不懂時回來讀 — 配置檔需要的最小 Lua 知識">Lua 腳本語言&lt;/a>&lt;/td>
 &lt;td>Hyprland / Neovim 配置檔使用的腳本語言，配置檔需要的最小知識&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/linux/dotfile/knowledge-cards/gnu-stow/" data-link-title="GNU Stow" data-link-desc="dotfile 管理文章裡提到 stow、symlink、package 看不懂時回來讀 — stow 的核心概念和常用指令">GNU Stow&lt;/a>&lt;/td>
 &lt;td>symlink farm manager，dotfile 管理的核心工具之一&lt;/td>
 &lt;/tr>
 &lt;/tbody>
&lt;/table>
&lt;h2 id="系統概念">系統概念&lt;/h2>
&lt;table>
 &lt;thead>
 &lt;tr>
 &lt;th>卡片&lt;/th>
 &lt;th>主題&lt;/th>
 &lt;/tr>
 &lt;/thead>
 &lt;tbody>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/linux/dotfile/knowledge-cards/tty/" data-link-title="TTY" data-link-desc="恢復操作提到切 TTY 但不知道 TTY 是什麼時讀 — Linux 核心直接提供的純文字終端機介面">TTY&lt;/a>&lt;/td>
 &lt;td>Linux 核心的純文字終端機介面，桌面故障時的救生通道&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/linux/dotfile/knowledge-cards/initramfs/" data-link-title="initramfs" data-link-desc="看到 ESP 大小要算進 initramfs、或開機卡在掛載 root 之前、不知道 initramfs 是什麼時讀 — 開機初期掛真 root 之前的臨時根檔系統">initramfs&lt;/a>&lt;/td>
 &lt;td>開機初期掛真 root 之前的臨時根檔系統，ESP 大小要算進它&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/linux/dotfile/knowledge-cards/uefi-boot-chain/" data-link-title="UEFI 開機鏈" data-link-desc="在 bootloader 選型（GRUB / EFISTUB / systemd-boot）卡住、或機器重開後找不到 kernel、需要理解韌體怎麼找到並載入系統時讀 — 韌體到 kernel 的交棒過程">UEFI 開機鏈&lt;/a>&lt;/td>
 &lt;td>韌體到 kernel 的交棒過程，bootloader 選型與開機故障的依據&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/linux/dotfile/knowledge-cards/partition-identification/" data-link-title="分區識別（PARTUUID / FSUUID）" data-link-desc="在 fstab 或 bootloader 設定要指定一個分區、不確定該用 PARTUUID、UUID 還是 /dev/sda1、或重格式化後系統開不了機時讀 — 分區的穩定識別方式">分區識別（PARTUUID / FSUUID）&lt;/a>&lt;/td>
 &lt;td>分區的穩定識別方式，fstab / bootloader 怎麼指涉分區&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/linux/dotfile/knowledge-cards/font-availability-at-startup/" data-link-title="字型的可用集合在 process 啟動時決定" data-link-desc="裝了字型但應用程式 / 狀態列 / 通知還是看不到、還是豆腐時回來讀">字型的可用集合在 process 啟動時決定&lt;/a>&lt;/td>
 &lt;td>裝了字型但畫面還是豆腐時的判讀依據&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/linux/dotfile/knowledge-cards/session-lock/" data-link-title="Wayland Session Lock（鎖屏安全狀態）" data-link-desc="hyprlock / swaylock 畫面卡住、pkill 後進不了桌面、或要在 VM / 自動化環境測試鎖屏時回來讀">Session Lock&lt;/a>&lt;/td>
 &lt;td>鎖屏是 compositor 持有的安全狀態，殺 process 不等於解鎖&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/linux/dotfile/knowledge-cards/compositor/" data-link-title="Compositor（合成器）" data-link-desc="教材反覆出現 compositor / 合成器、想確認它到底負責什麼、跟 window manager 和桌面環境差在哪時讀 — Wayland 下把畫面合成與視窗管理合一的核心程式">Compositor（合成器）&lt;/a>&lt;/td>
 &lt;td>Wayland 下把畫面合成與視窗管理合一的核心程式，多個系統狀態的持有者&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/linux/dotfile/knowledge-cards/fontconfig/" data-link-title="fontconfig — 字型搜尋、匹配與 fallback 服務" data-link-desc="不確定 fc-list / fc-match / fc-cache 各做什麼、或 fontconfig fallback 機制怎麼運作時回來讀">fontconfig&lt;/a>&lt;/td>
 &lt;td>字型搜尋、匹配與 fallback 的底層服務，fc-* 工具分工&lt;/td>
 &lt;/tr>
 &lt;/tbody>
&lt;/table>
&lt;h2 id="文化與術語">文化與術語&lt;/h2>
&lt;table>
 &lt;thead>
 &lt;tr>
 &lt;th>卡片&lt;/th>
 &lt;th>主題&lt;/th>
 &lt;/tr>
 &lt;/thead>
 &lt;tbody>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/linux/dotfile/knowledge-cards/rice/" data-link-title="Rice（桌面視覺客製化）" data-link-desc="Linux 桌面文章裡看到 rice / ricing / ricer 不確定意思時回來讀">Rice（桌面視覺客製化）&lt;/a>&lt;/td>
 &lt;td>Linux 桌面社群的視覺客製化文化，詞源和涵蓋範圍&lt;/td>
 &lt;/tr>
 &lt;/tbody>
&lt;/table></description><content:encoded><![CDATA[<p>本系列使用的關鍵術語。各卡片會在對應章節深入說明、這裡提供快速查閱入口。</p>
<p>術語卡會隨教材擴展逐步補充。</p>
<h2 id="語言與工具">語言與工具</h2>
<table>
  <thead>
      <tr>
          <th>卡片</th>
          <th>主題</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td><a href="/blog/linux/dotfile/knowledge-cards/lua-scripting-language/" data-link-title="Lua 腳本語言" data-link-desc="在 Hyprland 或 Neovim 配置檔遇到 Lua 語法看不懂時回來讀 — 配置檔需要的最小 Lua 知識">Lua 腳本語言</a></td>
          <td>Hyprland / Neovim 配置檔使用的腳本語言，配置檔需要的最小知識</td>
      </tr>
      <tr>
          <td><a href="/blog/linux/dotfile/knowledge-cards/gnu-stow/" data-link-title="GNU Stow" data-link-desc="dotfile 管理文章裡提到 stow、symlink、package 看不懂時回來讀 — stow 的核心概念和常用指令">GNU Stow</a></td>
          <td>symlink farm manager，dotfile 管理的核心工具之一</td>
      </tr>
  </tbody>
</table>
<h2 id="系統概念">系統概念</h2>
<table>
  <thead>
      <tr>
          <th>卡片</th>
          <th>主題</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td><a href="/blog/linux/dotfile/knowledge-cards/tty/" data-link-title="TTY" data-link-desc="恢復操作提到切 TTY 但不知道 TTY 是什麼時讀 — Linux 核心直接提供的純文字終端機介面">TTY</a></td>
          <td>Linux 核心的純文字終端機介面，桌面故障時的救生通道</td>
      </tr>
      <tr>
          <td><a href="/blog/linux/dotfile/knowledge-cards/initramfs/" data-link-title="initramfs" data-link-desc="看到 ESP 大小要算進 initramfs、或開機卡在掛載 root 之前、不知道 initramfs 是什麼時讀 — 開機初期掛真 root 之前的臨時根檔系統">initramfs</a></td>
          <td>開機初期掛真 root 之前的臨時根檔系統，ESP 大小要算進它</td>
      </tr>
      <tr>
          <td><a href="/blog/linux/dotfile/knowledge-cards/uefi-boot-chain/" data-link-title="UEFI 開機鏈" data-link-desc="在 bootloader 選型（GRUB / EFISTUB / systemd-boot）卡住、或機器重開後找不到 kernel、需要理解韌體怎麼找到並載入系統時讀 — 韌體到 kernel 的交棒過程">UEFI 開機鏈</a></td>
          <td>韌體到 kernel 的交棒過程，bootloader 選型與開機故障的依據</td>
      </tr>
      <tr>
          <td><a href="/blog/linux/dotfile/knowledge-cards/partition-identification/" data-link-title="分區識別（PARTUUID / FSUUID）" data-link-desc="在 fstab 或 bootloader 設定要指定一個分區、不確定該用 PARTUUID、UUID 還是 /dev/sda1、或重格式化後系統開不了機時讀 — 分區的穩定識別方式">分區識別（PARTUUID / FSUUID）</a></td>
          <td>分區的穩定識別方式，fstab / bootloader 怎麼指涉分區</td>
      </tr>
      <tr>
          <td><a href="/blog/linux/dotfile/knowledge-cards/font-availability-at-startup/" data-link-title="字型的可用集合在 process 啟動時決定" data-link-desc="裝了字型但應用程式 / 狀態列 / 通知還是看不到、還是豆腐時回來讀">字型的可用集合在 process 啟動時決定</a></td>
          <td>裝了字型但畫面還是豆腐時的判讀依據</td>
      </tr>
      <tr>
          <td><a href="/blog/linux/dotfile/knowledge-cards/session-lock/" data-link-title="Wayland Session Lock（鎖屏安全狀態）" data-link-desc="hyprlock / swaylock 畫面卡住、pkill 後進不了桌面、或要在 VM / 自動化環境測試鎖屏時回來讀">Session Lock</a></td>
          <td>鎖屏是 compositor 持有的安全狀態，殺 process 不等於解鎖</td>
      </tr>
      <tr>
          <td><a href="/blog/linux/dotfile/knowledge-cards/compositor/" data-link-title="Compositor（合成器）" data-link-desc="教材反覆出現 compositor / 合成器、想確認它到底負責什麼、跟 window manager 和桌面環境差在哪時讀 — Wayland 下把畫面合成與視窗管理合一的核心程式">Compositor（合成器）</a></td>
          <td>Wayland 下把畫面合成與視窗管理合一的核心程式，多個系統狀態的持有者</td>
      </tr>
      <tr>
          <td><a href="/blog/linux/dotfile/knowledge-cards/fontconfig/" data-link-title="fontconfig — 字型搜尋、匹配與 fallback 服務" data-link-desc="不確定 fc-list / fc-match / fc-cache 各做什麼、或 fontconfig fallback 機制怎麼運作時回來讀">fontconfig</a></td>
          <td>字型搜尋、匹配與 fallback 的底層服務，fc-* 工具分工</td>
      </tr>
  </tbody>
</table>
<h2 id="文化與術語">文化與術語</h2>
<table>
  <thead>
      <tr>
          <th>卡片</th>
          <th>主題</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td><a href="/blog/linux/dotfile/knowledge-cards/rice/" data-link-title="Rice（桌面視覺客製化）" data-link-desc="Linux 桌面文章裡看到 rice / ricing / ricer 不確定意思時回來讀">Rice（桌面視覺客製化）</a></td>
          <td>Linux 桌面社群的視覺客製化文化，詞源和涵蓋範圍</td>
      </tr>
  </tbody>
</table>
]]></content:encoded></item><item><title>Infra 知識卡</title><link>https://tarrragon.github.io/blog/infra/knowledge-cards/</link><pubDate>Fri, 26 Jun 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/infra/knowledge-cards/</guid><description>&lt;p>Infra 知識卡收錄基礎設施領域的核心術語。每張卡自包含、可獨立閱讀，讀者可以從任何一張卡進入、透過鄰卡連結導航到相關概念。&lt;/p>
&lt;p>知識卡的職責是建立術語的語意錨點。教學模組負責情境推導與操作判準，知識卡負責「這個詞是什麼、什麼時候會碰到、使用時要決定什麼」。兩者互相引用但各自完整。&lt;/p>
&lt;h2 id="卡片清單">卡片清單&lt;/h2>
&lt;table>
 &lt;thead>
 &lt;tr>
 &lt;th>卡片&lt;/th>
 &lt;th>說明&lt;/th>
 &lt;/tr>
 &lt;/thead>
 &lt;tbody>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/infra/knowledge-cards/alb/" data-link-title="ALB" data-link-desc="Application Load Balancer — 流量進入系統的第一站，負責 listener 路由、健康檢查與 TLS 終結">ALB&lt;/a>&lt;/td>
 &lt;td>Application Load Balancer — 流量進入系統的第一站，負責 listener 路由、健康檢查與 TLS 終結&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/infra/knowledge-cards/cidr/" data-link-title="CIDR（Classless Inter-Domain Routing）" data-link-desc="用前綴長度表示 IP 地址範圍的表示法，決定 VPC 與 subnet 的地址空間大小">CIDR&lt;/a>&lt;/td>
 &lt;td>用前綴長度表示 IP 地址範圍的表示法，決定 VPC 與 subnet 的地址空間大小&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/infra/knowledge-cards/cloudtrail/" data-link-title="CloudTrail" data-link-desc="AWS 的 API 層稽核日誌服務，記錄誰在什麼時候對什麼資源做了什麼操作">CloudTrail&lt;/a>&lt;/td>
 &lt;td>AWS 的 API 層稽核日誌服務，記錄誰在什麼時候對什麼資源做了什麼操作&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/infra/knowledge-cards/drift/" data-link-title="Drift（設定漂移）" data-link-desc="IaC 的 state 與雲端實際狀態之間的不一致，通常因為有人繞過 IaC 直接在 Console 改設定">Drift&lt;/a>&lt;/td>
 &lt;td>IaC 的 state 與雲端實際狀態之間的不一致，通常因為繞過 IaC 直接在 Console 改設定&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/infra/knowledge-cards/ecs/" data-link-title="ECS" data-link-desc="AWS Elastic Container Service — 受管的容器編排服務，用 task definition 描述容器配置、由平台負責排程與健康管理">ECS&lt;/a>&lt;/td>
 &lt;td>AWS 受管容器編排服務，用 task definition 描述容器配置、由平台負責排程與健康管理&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/infra/knowledge-cards/iam/" data-link-title="IAM（Identity and Access Management）" data-link-desc="雲端平台的授權系統，回答「某個身分能不能對某個資源做某件事」">IAM&lt;/a>&lt;/td>
 &lt;td>雲端平台的授權系統，回答「某個身分能不能對某個資源做某件事」&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/infra/knowledge-cards/iac/" data-link-title="Infrastructure as Code (IaC)" data-link-desc="用程式碼描述基礎設施的最終狀態，由工具負責收斂現實與描述的差異">IaC&lt;/a>&lt;/td>
 &lt;td>用程式碼描述基礎設施的最終狀態，由工具負責收斂現實與描述的差異&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/infra/knowledge-cards/nat/" data-link-title="NAT Gateway" data-link-desc="讓 private subnet 的資源主動對外連線、同時不被外部入站觸及的網路地址轉換服務">NAT Gateway&lt;/a>&lt;/td>
 &lt;td>讓 private subnet 的資源主動對外連線、同時不被外部入站觸及&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/infra/knowledge-cards/oidc/" data-link-title="OIDC 聯合" data-link-desc="讓 CI/CD 平台用短期 token 取代長期 access key 存取雲端資源的身分聯合機制">OIDC 聯合&lt;/a>&lt;/td>
 &lt;td>讓 CI/CD 平台用短期 token 取代長期 access key 存取雲端資源&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/infra/knowledge-cards/security-group/" data-link-title="Security Group" data-link-desc="掛在資源網卡層級的有狀態防火牆，逐埠決定哪些來源能連進這個資源">Security Group&lt;/a>&lt;/td>
 &lt;td>掛在資源網卡層級的有狀態防火牆，逐埠決定哪些來源能連進這個資源&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/infra/knowledge-cards/state/" data-link-title="State（IaC 狀態檔）" data-link-desc="IaC 工具用來記錄每個納管資源在雲端真實樣貌的快照，是比對差異與排定操作順序的依據">State&lt;/a>&lt;/td>
 &lt;td>IaC 工具用來記錄每個納管資源在雲端真實樣貌的快照&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/infra/knowledge-cards/subnet/" data-link-title="Subnet（子網路）" data-link-desc="VPC 內按可用區與暴露程度切出的子網段，決定資源有沒有一條通往網際網路的路徑">Subnet&lt;/a>&lt;/td>
 &lt;td>VPC 內按可用區與暴露程度切出的子網段，決定資源有沒有通往網際網路的路徑&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/infra/knowledge-cards/vpc/" data-link-title="VPC（Virtual Private Cloud）" data-link-desc="雲端帳號內的一塊邏輯隔離私有網段，是所有網路切分的起點與容器">VPC&lt;/a>&lt;/td>
 &lt;td>雲端帳號內的一塊邏輯隔離私有網段，是所有網路切分的起點與容器&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/infra/knowledge-cards/checkov/" data-link-title="checkov" data-link-desc="開源的 IaC 靜態安全掃描工具，在不建立資源的前提下比對已知的壞寫法與安全反模式">checkov&lt;/a>&lt;/td>
 &lt;td>IaC 靜態安全掃描工具，比對 HCL 裡的已知壞寫法與安全反模式&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/infra/knowledge-cards/deletion-protection/" data-link-title="Deletion Protection" data-link-desc="雲端平台提供的防誤刪機制，開啟後刪除操作需要先顯式關閉保護才能執行">Deletion Protection&lt;/a>&lt;/td>
 &lt;td>防止誤刪 stateful 資源的平台級保護機制，開啟後刪除需先顯式關閉保護&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/infra/knowledge-cards/fargate/" data-link-title="Fargate" data-link-desc="AWS ECS 的無伺服器執行模式，由 AWS 代管運算實例，不需要管 EC2 capacity 或 AMI 更新">Fargate&lt;/a>&lt;/td>
 &lt;td>AWS ECS 的無伺服器容器執行模式，不需管理 EC2 instance&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/infra/knowledge-cards/remote-state-backend/" data-link-title="Remote State Backend" data-link-desc="把 Terraform state 從本地搬到團隊共享儲存的機制，同時滿足持久保存、並行鎖與敏感值保護">Remote State Backend&lt;/a>&lt;/td>
 &lt;td>團隊共享、有鎖、有加密的 state 存放機制&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/infra/knowledge-cards/route-table/" data-link-title="Route Table" data-link-desc="掛在 subnet 上的流量轉送規則，決定封包離開 subnet 後往哪走">Route Table&lt;/a>&lt;/td>
 &lt;td>subnet 的流量轉送規則，決定封包離開 subnet 後往哪走&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/infra/knowledge-cards/scp/" data-link-title="SCP (Service Control Policy)" data-link-desc="AWS Organizations 層級的權限天花板，套用到 OU 後連管理員都越不過">SCP&lt;/a>&lt;/td>
 &lt;td>Organizations 層級的權限天花板，連管理員都越不過&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/infra/knowledge-cards/trust-policy/" data-link-title="Trust Policy" data-link-desc="IAM role 的信任關係設定，規定哪個身分被允許 assume 這個 role">Trust Policy&lt;/a>&lt;/td>
 &lt;td>IAM role 的信任關係設定，控制誰能 assume 這個 role&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/infra/knowledge-cards/environment-separation/" data-link-title="環境分離" data-link-desc="把同一套基礎設施定義複製成多份隔離的執行實例，各有獨立 state 與故障半徑">環境分離&lt;/a>&lt;/td>
 &lt;td>把同一套基礎設施定義複製成多份隔離的執行實例，各有獨立 state 與故障半徑&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/infra/knowledge-cards/phpmyadmin/" data-link-title="phpMyAdmin" data-link-desc="Web 介面的 MySQL / MariaDB 管理工具，透過瀏覽器操作資料庫">phpMyAdmin&lt;/a>&lt;/td>
 &lt;td>Web 介面的 MySQL / MariaDB 管理工具，無 SSH 環境的主要 DB 管理入口&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/infra/knowledge-cards/filezilla/" data-link-title="FileZilla" data-link-desc="跨平台的 FTP/SFTP client，提供目錄同步瀏覽和檔案比較功能">FileZilla&lt;/a>&lt;/td>
 &lt;td>跨平台 FTP/SFTP client，提供目錄同步瀏覽和檔案比較功能&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/infra/knowledge-cards/cpanel/" data-link-title="cPanel" data-link-desc="Web 主機管理面板，提供 PHP 版本切換、cron、email、SSL、備份等功能的圖形介面">cPanel&lt;/a>&lt;/td>
 &lt;td>Web 主機管理面板，整合 PHP 版本切換、cron、email、SSL、備份的圖形介面&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/infra/knowledge-cards/htaccess/" data-link-title=".htaccess" data-link-desc="Apache Web Server 的目錄層級設定檔，控制 URL rewrite、存取權限、PHP 設定覆寫與安全標頭">.htaccess&lt;/a>&lt;/td>
 &lt;td>Apache 的目錄層級設定檔，控制 URL rewrite、存取權限、PHP 設定覆寫&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/infra/knowledge-cards/dotenv/" data-link-title=".env" data-link-desc="存放環境變數的純文字檔案，把機密值從程式碼分離出來">.env&lt;/a>&lt;/td>
 &lt;td>存放環境變數的純文字檔案，把機密值從程式碼分離出來&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/infra/knowledge-cards/php-ini/" data-link-title="php.ini / .user.ini" data-link-desc="PHP 的執行期設定檔，控制記憶體上限、上傳大小、錯誤報告等 runtime 行為">php.ini / .user.ini&lt;/a>&lt;/td>
 &lt;td>PHP 的執行期設定檔，控制記憶體上限、上傳大小、錯誤報告等 runtime 行為&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/infra/knowledge-cards/composer/" data-link-title="Composer" data-link-desc="PHP 的套件管理工具，管理專案的第三方依賴、版本鎖定與安全掃描">Composer&lt;/a>&lt;/td>
 &lt;td>PHP 的套件管理工具，管理第三方依賴、版本鎖定與安全掃描&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/infra/knowledge-cards/mysqldump/" data-link-title="mysqldump" data-link-desc="MySQL / MariaDB 的 CLI 備份工具，把資料庫匯出成 SQL 語句的純文字檔">mysqldump&lt;/a>&lt;/td>
 &lt;td>MySQL/MariaDB 的 CLI 備份工具，把資料庫匯出成 SQL 純文字檔&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/infra/knowledge-cards/reverse-proxy/" data-link-title="Reverse Proxy" data-link-desc="代替後端服務接收外部請求、再轉發到內部服務的中介層，承擔 TLS 終結、負載平衡與路由分流">Reverse Proxy&lt;/a>&lt;/td>
 &lt;td>代替後端服務接收外部請求的中介層，承擔 TLS 終結、負載平衡與路由分流&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/infra/knowledge-cards/database-migration/" data-link-title="Database Migration" data-link-desc="用版本化的 SQL 腳本管理資料庫 schema 的變更歷程，讓 schema 變更可追蹤、可重現、可回退">Database Migration&lt;/a>&lt;/td>
 &lt;td>用版本化的 SQL 腳本管理資料庫 schema 的變更歷程&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/infra/knowledge-cards/prometheus/" data-link-title="Prometheus" data-link-desc="開源的 metrics 收集與告警系統，用 pull 模式從 target 拉取指標，斷網環境的預設監控方案">Prometheus&lt;/a>&lt;/td>
 &lt;td>開源的 metrics 收集與告警系統，用 pull 模式從 target 拉取指標&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/infra/knowledge-cards/grafana/" data-link-title="Grafana" data-link-desc="開源的監控視覺化平台，從 Prometheus / Loki / Elasticsearch 等資料源建立 dashboard">Grafana&lt;/a>&lt;/td>
 &lt;td>開源的監控視覺化平台，從 Prometheus / Loki 等資料源建立 dashboard&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/infra/knowledge-cards/vault/" data-link-title="HashiCorp Vault" data-link-desc="機密管理系統，集中存放密碼、API key、TLS 私鑰，提供存取控制、稽核和自動輪替">HashiCorp Vault&lt;/a>&lt;/td>
 &lt;td>機密管理系統，集中存放密碼與 API key，提供存取控制與稽核&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/infra/knowledge-cards/harbor/" data-link-title="Harbor" data-link-desc="開源的 container image registry，支援映像掃描、RBAC、複製，斷網環境取代 Docker Hub 的方案">Harbor&lt;/a>&lt;/td>
 &lt;td>開源的 container image registry，支援映像掃描、RBAC、複製&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/infra/knowledge-cards/helm/" data-link-title="Helm" data-link-desc="Kubernetes 的套件管理工具，用 chart 打包一組 K8s 資源的部署定義">Helm&lt;/a>&lt;/td>
 &lt;td>Kubernetes 的套件管理工具，用 chart 打包一組 K8s 資源部署定義&lt;/td>
 &lt;/tr>
 &lt;/tbody>
&lt;/table></description><content:encoded><![CDATA[<p>Infra 知識卡收錄基礎設施領域的核心術語。每張卡自包含、可獨立閱讀，讀者可以從任何一張卡進入、透過鄰卡連結導航到相關概念。</p>
<p>知識卡的職責是建立術語的語意錨點。教學模組負責情境推導與操作判準，知識卡負責「這個詞是什麼、什麼時候會碰到、使用時要決定什麼」。兩者互相引用但各自完整。</p>
<h2 id="卡片清單">卡片清單</h2>
<table>
  <thead>
      <tr>
          <th>卡片</th>
          <th>說明</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td><a href="/blog/infra/knowledge-cards/alb/" data-link-title="ALB" data-link-desc="Application Load Balancer — 流量進入系統的第一站，負責 listener 路由、健康檢查與 TLS 終結">ALB</a></td>
          <td>Application Load Balancer — 流量進入系統的第一站，負責 listener 路由、健康檢查與 TLS 終結</td>
      </tr>
      <tr>
          <td><a href="/blog/infra/knowledge-cards/cidr/" data-link-title="CIDR（Classless Inter-Domain Routing）" data-link-desc="用前綴長度表示 IP 地址範圍的表示法，決定 VPC 與 subnet 的地址空間大小">CIDR</a></td>
          <td>用前綴長度表示 IP 地址範圍的表示法，決定 VPC 與 subnet 的地址空間大小</td>
      </tr>
      <tr>
          <td><a href="/blog/infra/knowledge-cards/cloudtrail/" data-link-title="CloudTrail" data-link-desc="AWS 的 API 層稽核日誌服務，記錄誰在什麼時候對什麼資源做了什麼操作">CloudTrail</a></td>
          <td>AWS 的 API 層稽核日誌服務，記錄誰在什麼時候對什麼資源做了什麼操作</td>
      </tr>
      <tr>
          <td><a href="/blog/infra/knowledge-cards/drift/" data-link-title="Drift（設定漂移）" data-link-desc="IaC 的 state 與雲端實際狀態之間的不一致，通常因為有人繞過 IaC 直接在 Console 改設定">Drift</a></td>
          <td>IaC 的 state 與雲端實際狀態之間的不一致，通常因為繞過 IaC 直接在 Console 改設定</td>
      </tr>
      <tr>
          <td><a href="/blog/infra/knowledge-cards/ecs/" data-link-title="ECS" data-link-desc="AWS Elastic Container Service — 受管的容器編排服務，用 task definition 描述容器配置、由平台負責排程與健康管理">ECS</a></td>
          <td>AWS 受管容器編排服務，用 task definition 描述容器配置、由平台負責排程與健康管理</td>
      </tr>
      <tr>
          <td><a href="/blog/infra/knowledge-cards/iam/" data-link-title="IAM（Identity and Access Management）" data-link-desc="雲端平台的授權系統，回答「某個身分能不能對某個資源做某件事」">IAM</a></td>
          <td>雲端平台的授權系統，回答「某個身分能不能對某個資源做某件事」</td>
      </tr>
      <tr>
          <td><a href="/blog/infra/knowledge-cards/iac/" data-link-title="Infrastructure as Code (IaC)" data-link-desc="用程式碼描述基礎設施的最終狀態，由工具負責收斂現實與描述的差異">IaC</a></td>
          <td>用程式碼描述基礎設施的最終狀態，由工具負責收斂現實與描述的差異</td>
      </tr>
      <tr>
          <td><a href="/blog/infra/knowledge-cards/nat/" data-link-title="NAT Gateway" data-link-desc="讓 private subnet 的資源主動對外連線、同時不被外部入站觸及的網路地址轉換服務">NAT Gateway</a></td>
          <td>讓 private subnet 的資源主動對外連線、同時不被外部入站觸及</td>
      </tr>
      <tr>
          <td><a href="/blog/infra/knowledge-cards/oidc/" data-link-title="OIDC 聯合" data-link-desc="讓 CI/CD 平台用短期 token 取代長期 access key 存取雲端資源的身分聯合機制">OIDC 聯合</a></td>
          <td>讓 CI/CD 平台用短期 token 取代長期 access key 存取雲端資源</td>
      </tr>
      <tr>
          <td><a href="/blog/infra/knowledge-cards/security-group/" data-link-title="Security Group" data-link-desc="掛在資源網卡層級的有狀態防火牆，逐埠決定哪些來源能連進這個資源">Security Group</a></td>
          <td>掛在資源網卡層級的有狀態防火牆，逐埠決定哪些來源能連進這個資源</td>
      </tr>
      <tr>
          <td><a href="/blog/infra/knowledge-cards/state/" data-link-title="State（IaC 狀態檔）" data-link-desc="IaC 工具用來記錄每個納管資源在雲端真實樣貌的快照，是比對差異與排定操作順序的依據">State</a></td>
          <td>IaC 工具用來記錄每個納管資源在雲端真實樣貌的快照</td>
      </tr>
      <tr>
          <td><a href="/blog/infra/knowledge-cards/subnet/" data-link-title="Subnet（子網路）" data-link-desc="VPC 內按可用區與暴露程度切出的子網段，決定資源有沒有一條通往網際網路的路徑">Subnet</a></td>
          <td>VPC 內按可用區與暴露程度切出的子網段，決定資源有沒有通往網際網路的路徑</td>
      </tr>
      <tr>
          <td><a href="/blog/infra/knowledge-cards/vpc/" data-link-title="VPC（Virtual Private Cloud）" data-link-desc="雲端帳號內的一塊邏輯隔離私有網段，是所有網路切分的起點與容器">VPC</a></td>
          <td>雲端帳號內的一塊邏輯隔離私有網段，是所有網路切分的起點與容器</td>
      </tr>
      <tr>
          <td><a href="/blog/infra/knowledge-cards/checkov/" data-link-title="checkov" data-link-desc="開源的 IaC 靜態安全掃描工具，在不建立資源的前提下比對已知的壞寫法與安全反模式">checkov</a></td>
          <td>IaC 靜態安全掃描工具，比對 HCL 裡的已知壞寫法與安全反模式</td>
      </tr>
      <tr>
          <td><a href="/blog/infra/knowledge-cards/deletion-protection/" data-link-title="Deletion Protection" data-link-desc="雲端平台提供的防誤刪機制，開啟後刪除操作需要先顯式關閉保護才能執行">Deletion Protection</a></td>
          <td>防止誤刪 stateful 資源的平台級保護機制，開啟後刪除需先顯式關閉保護</td>
      </tr>
      <tr>
          <td><a href="/blog/infra/knowledge-cards/fargate/" data-link-title="Fargate" data-link-desc="AWS ECS 的無伺服器執行模式，由 AWS 代管運算實例，不需要管 EC2 capacity 或 AMI 更新">Fargate</a></td>
          <td>AWS ECS 的無伺服器容器執行模式，不需管理 EC2 instance</td>
      </tr>
      <tr>
          <td><a href="/blog/infra/knowledge-cards/remote-state-backend/" data-link-title="Remote State Backend" data-link-desc="把 Terraform state 從本地搬到團隊共享儲存的機制，同時滿足持久保存、並行鎖與敏感值保護">Remote State Backend</a></td>
          <td>團隊共享、有鎖、有加密的 state 存放機制</td>
      </tr>
      <tr>
          <td><a href="/blog/infra/knowledge-cards/route-table/" data-link-title="Route Table" data-link-desc="掛在 subnet 上的流量轉送規則，決定封包離開 subnet 後往哪走">Route Table</a></td>
          <td>subnet 的流量轉送規則，決定封包離開 subnet 後往哪走</td>
      </tr>
      <tr>
          <td><a href="/blog/infra/knowledge-cards/scp/" data-link-title="SCP (Service Control Policy)" data-link-desc="AWS Organizations 層級的權限天花板，套用到 OU 後連管理員都越不過">SCP</a></td>
          <td>Organizations 層級的權限天花板，連管理員都越不過</td>
      </tr>
      <tr>
          <td><a href="/blog/infra/knowledge-cards/trust-policy/" data-link-title="Trust Policy" data-link-desc="IAM role 的信任關係設定，規定哪個身分被允許 assume 這個 role">Trust Policy</a></td>
          <td>IAM role 的信任關係設定，控制誰能 assume 這個 role</td>
      </tr>
      <tr>
          <td><a href="/blog/infra/knowledge-cards/environment-separation/" data-link-title="環境分離" data-link-desc="把同一套基礎設施定義複製成多份隔離的執行實例，各有獨立 state 與故障半徑">環境分離</a></td>
          <td>把同一套基礎設施定義複製成多份隔離的執行實例，各有獨立 state 與故障半徑</td>
      </tr>
      <tr>
          <td><a href="/blog/infra/knowledge-cards/phpmyadmin/" data-link-title="phpMyAdmin" data-link-desc="Web 介面的 MySQL / MariaDB 管理工具，透過瀏覽器操作資料庫">phpMyAdmin</a></td>
          <td>Web 介面的 MySQL / MariaDB 管理工具，無 SSH 環境的主要 DB 管理入口</td>
      </tr>
      <tr>
          <td><a href="/blog/infra/knowledge-cards/filezilla/" data-link-title="FileZilla" data-link-desc="跨平台的 FTP/SFTP client，提供目錄同步瀏覽和檔案比較功能">FileZilla</a></td>
          <td>跨平台 FTP/SFTP client，提供目錄同步瀏覽和檔案比較功能</td>
      </tr>
      <tr>
          <td><a href="/blog/infra/knowledge-cards/cpanel/" data-link-title="cPanel" data-link-desc="Web 主機管理面板，提供 PHP 版本切換、cron、email、SSL、備份等功能的圖形介面">cPanel</a></td>
          <td>Web 主機管理面板，整合 PHP 版本切換、cron、email、SSL、備份的圖形介面</td>
      </tr>
      <tr>
          <td><a href="/blog/infra/knowledge-cards/htaccess/" data-link-title=".htaccess" data-link-desc="Apache Web Server 的目錄層級設定檔，控制 URL rewrite、存取權限、PHP 設定覆寫與安全標頭">.htaccess</a></td>
          <td>Apache 的目錄層級設定檔，控制 URL rewrite、存取權限、PHP 設定覆寫</td>
      </tr>
      <tr>
          <td><a href="/blog/infra/knowledge-cards/dotenv/" data-link-title=".env" data-link-desc="存放環境變數的純文字檔案，把機密值從程式碼分離出來">.env</a></td>
          <td>存放環境變數的純文字檔案，把機密值從程式碼分離出來</td>
      </tr>
      <tr>
          <td><a href="/blog/infra/knowledge-cards/php-ini/" data-link-title="php.ini / .user.ini" data-link-desc="PHP 的執行期設定檔，控制記憶體上限、上傳大小、錯誤報告等 runtime 行為">php.ini / .user.ini</a></td>
          <td>PHP 的執行期設定檔，控制記憶體上限、上傳大小、錯誤報告等 runtime 行為</td>
      </tr>
      <tr>
          <td><a href="/blog/infra/knowledge-cards/composer/" data-link-title="Composer" data-link-desc="PHP 的套件管理工具，管理專案的第三方依賴、版本鎖定與安全掃描">Composer</a></td>
          <td>PHP 的套件管理工具，管理第三方依賴、版本鎖定與安全掃描</td>
      </tr>
      <tr>
          <td><a href="/blog/infra/knowledge-cards/mysqldump/" data-link-title="mysqldump" data-link-desc="MySQL / MariaDB 的 CLI 備份工具，把資料庫匯出成 SQL 語句的純文字檔">mysqldump</a></td>
          <td>MySQL/MariaDB 的 CLI 備份工具，把資料庫匯出成 SQL 純文字檔</td>
      </tr>
      <tr>
          <td><a href="/blog/infra/knowledge-cards/reverse-proxy/" data-link-title="Reverse Proxy" data-link-desc="代替後端服務接收外部請求、再轉發到內部服務的中介層，承擔 TLS 終結、負載平衡與路由分流">Reverse Proxy</a></td>
          <td>代替後端服務接收外部請求的中介層，承擔 TLS 終結、負載平衡與路由分流</td>
      </tr>
      <tr>
          <td><a href="/blog/infra/knowledge-cards/database-migration/" data-link-title="Database Migration" data-link-desc="用版本化的 SQL 腳本管理資料庫 schema 的變更歷程，讓 schema 變更可追蹤、可重現、可回退">Database Migration</a></td>
          <td>用版本化的 SQL 腳本管理資料庫 schema 的變更歷程</td>
      </tr>
      <tr>
          <td><a href="/blog/infra/knowledge-cards/prometheus/" data-link-title="Prometheus" data-link-desc="開源的 metrics 收集與告警系統，用 pull 模式從 target 拉取指標，斷網環境的預設監控方案">Prometheus</a></td>
          <td>開源的 metrics 收集與告警系統，用 pull 模式從 target 拉取指標</td>
      </tr>
      <tr>
          <td><a href="/blog/infra/knowledge-cards/grafana/" data-link-title="Grafana" data-link-desc="開源的監控視覺化平台，從 Prometheus / Loki / Elasticsearch 等資料源建立 dashboard">Grafana</a></td>
          <td>開源的監控視覺化平台，從 Prometheus / Loki 等資料源建立 dashboard</td>
      </tr>
      <tr>
          <td><a href="/blog/infra/knowledge-cards/vault/" data-link-title="HashiCorp Vault" data-link-desc="機密管理系統，集中存放密碼、API key、TLS 私鑰，提供存取控制、稽核和自動輪替">HashiCorp Vault</a></td>
          <td>機密管理系統，集中存放密碼與 API key，提供存取控制與稽核</td>
      </tr>
      <tr>
          <td><a href="/blog/infra/knowledge-cards/harbor/" data-link-title="Harbor" data-link-desc="開源的 container image registry，支援映像掃描、RBAC、複製，斷網環境取代 Docker Hub 的方案">Harbor</a></td>
          <td>開源的 container image registry，支援映像掃描、RBAC、複製</td>
      </tr>
      <tr>
          <td><a href="/blog/infra/knowledge-cards/helm/" data-link-title="Helm" data-link-desc="Kubernetes 的套件管理工具，用 chart 打包一組 K8s 資源的部署定義">Helm</a></td>
          <td>Kubernetes 的套件管理工具，用 chart 打包一組 K8s 資源部署定義</td>
      </tr>
  </tbody>
</table>
]]></content:encoded></item><item><title>Monitoring 知識卡片</title><link>https://tarrragon.github.io/blog/monitoring/knowledge-cards/</link><pubDate>Fri, 19 Jun 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/monitoring/knowledge-cards/</guid><description>&lt;p>監控體系教學中出現的關鍵術語卡片。每張卡片說明一個語意責任，跨情境變義的概念拆成獨立卡片。&lt;/p></description><content:encoded>&lt;p>監控體系教學中出現的關鍵術語卡片。每張卡片說明一個語意責任，跨情境變義的概念拆成獨立卡片。&lt;/p>
</content:encoded></item><item><title>Testing 知識卡片</title><link>https://tarrragon.github.io/blog/testing/knowledge-cards/</link><pubDate>Fri, 19 Jun 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/testing/knowledge-cards/</guid><description>&lt;p>測試策略教學中出現的關鍵術語卡片。每張卡片說明一個語意責任，跨情境變義的概念拆成獨立卡片。&lt;/p></description><content:encoded>&lt;p>測試策略教學中出現的關鍵術語卡片。每張卡片說明一個語意責任，跨情境變義的概念拆成獨立卡片。&lt;/p>
</content:encoded></item><item><title>UX Design 知識卡片</title><link>https://tarrragon.github.io/blog/ux-design/knowledge-cards/</link><pubDate>Fri, 19 Jun 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/ux-design/knowledge-cards/</guid><description>&lt;p>UX 設計教學中出現的關鍵術語卡片。每張卡片說明一個語意責任，跨情境變義的概念拆成獨立卡片。&lt;/p></description><content:encoded>&lt;p>UX 設計教學中出現的關鍵術語卡片。每張卡片說明一個語意責任，跨情境變義的概念拆成獨立卡片。&lt;/p>
</content:encoded></item><item><title>Knowledge Cards</title><link>https://tarrragon.github.io/blog/ci/knowledge-cards/</link><pubDate>Wed, 06 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/ci/knowledge-cards/</guid><description>&lt;p>CI/CD 知識卡片的核心責任是建立共同語言。流程文章會使用 pipeline、gate、artifact、rollout、rollback、environment protection 等術語；卡片負責定義它們在系統中的位置、可觀察訊號與設計責任。&lt;/p>
&lt;h2 id="核心術語">核心術語&lt;/h2>
&lt;table>
 &lt;thead>
 &lt;tr>
 &lt;th>卡片&lt;/th>
 &lt;th>核心問題&lt;/th>
 &lt;th>常見出現位置&lt;/th>
 &lt;/tr>
 &lt;/thead>
 &lt;tbody>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/ci/knowledge-cards/ci-pipeline/" data-link-title="CI Pipeline" data-link-desc="說明持續整合如何在合併前自動驗證變更品質與相容性">CI Pipeline&lt;/a>&lt;/td>
 &lt;td>變更如何在合併前被自動驗證&lt;/td>
 &lt;td>lint、test、build、security check&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/ci/knowledge-cards/cd-pipeline/" data-link-title="CD Pipeline" data-link-desc="說明持續交付如何把已驗證產物推進到目標環境">CD Pipeline&lt;/a>&lt;/td>
 &lt;td>驗證後產物如何被安全推進到目標環境&lt;/td>
 &lt;td>deploy、promotion、release workflow&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/ci/knowledge-cards/required-checks/" data-link-title="Required Checks" data-link-desc="說明 pull request 的必要檢查如何作為合併 gate">Required Checks&lt;/a>&lt;/td>
 &lt;td>PR 合併條件如何由檢查結果定義&lt;/td>
 &lt;td>branch protection、status checks&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/ci/knowledge-cards/artifact/" data-link-title="Artifact" data-link-desc="說明 CI/CD 中可被驗證、保存與發布的交付產物">Artifact&lt;/a>&lt;/td>
 &lt;td>交付產物如何被追溯、保存與發布&lt;/td>
 &lt;td>build output、image、app bundle&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/ci/knowledge-cards/artifact-handoff/" data-link-title="Artifact Handoff" data-link-desc="說明測試與部署如何共用同一份可追溯產物">Artifact Handoff&lt;/a>&lt;/td>
 &lt;td>測試與發布如何共用同一份產物&lt;/td>
 &lt;td>build artifact、package、deploy&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/ci/knowledge-cards/migration/" data-link-title="Migration" data-link-desc="說明資料或結構變更如何在服務不中斷前提下受控推進">Migration&lt;/a>&lt;/td>
 &lt;td>狀態變更如何在相容窗口內受控推進&lt;/td>
 &lt;td>schema change、backfill、release&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/ci/knowledge-cards/branch-protection/" data-link-title="Branch Protection" data-link-desc="說明主線分支如何以規則保護合併與發布前置條件">Branch Protection&lt;/a>&lt;/td>
 &lt;td>主線合併條件如何由規則強制保護&lt;/td>
 &lt;td>required checks、review policy&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/ci/knowledge-cards/readiness-health-check/" data-link-title="Readiness / Health Check" data-link-desc="說明服務存活與可接流量判斷在部署中的不同責任">Readiness / Health Check&lt;/a>&lt;/td>
 &lt;td>部署放行如何區分存活與可接流量訊號&lt;/td>
 &lt;td>rollout、probe、traffic switch&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/ci/knowledge-cards/container-registry/" data-link-title="Container Registry" data-link-desc="說明容器產物儲存、權限與推進流程在 CD 中的責任">Container Registry&lt;/a>&lt;/td>
 &lt;td>image 供應鏈如何被保存與推進&lt;/td>
 &lt;td>push、retention、promotion&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/ci/knowledge-cards/app-signing/" data-link-title="App Signing" data-link-desc="說明行動與桌面應用的簽章憑證如何影響發布能力">App Signing&lt;/a>&lt;/td>
 &lt;td>行動與桌面發版能力如何由簽章維持&lt;/td>
 &lt;td>certificate、profile、keystore&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/ci/knowledge-cards/flaky-test/" data-link-title="Flaky Test" data-link-desc="說明非決定性測試如何降低 CI gate 信任度與治理方式">Flaky Test&lt;/a>&lt;/td>
 &lt;td>非決定性測試如何影響 gate 信任度&lt;/td>
 &lt;td>rerun noise、test governance&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/ci/knowledge-cards/environment-protection/" data-link-title="Environment Protection" data-link-desc="說明目標環境的審核、權限與放行條件如何保護發布">Environment Protection&lt;/a>&lt;/td>
 &lt;td>目標環境如何設置審核與發布保護&lt;/td>
 &lt;td>production、staging、review gate&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/ci/knowledge-cards/preview-environment/" data-link-title="Preview Environment" data-link-desc="說明 pull request 變更如何在隔離部署環境中被驗證">Preview Environment&lt;/a>&lt;/td>
 &lt;td>PR 變更如何在隔離環境中被提前驗證&lt;/td>
 &lt;td>frontend preview URL、review app&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/ci/knowledge-cards/rollout-strategy/" data-link-title="Rollout Strategy" data-link-desc="說明新版本如何以可控節奏推進到全部流量">Rollout Strategy&lt;/a>&lt;/td>
 &lt;td>新版本如何分批推進以控制風險&lt;/td>
 &lt;td>rolling、canary、phased rollout&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/ci/knowledge-cards/rollback-strategy/" data-link-title="Rollback Strategy" data-link-desc="說明發布異常時如何快速回到已知可用狀態">Rollback Strategy&lt;/a>&lt;/td>
 &lt;td>發布異常時如何回到已知可用狀態&lt;/td>
 &lt;td>deploy rollback、hotfix、forward fix&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/ci/knowledge-cards/deployment-dry-run/" data-link-title="Deployment Dry Run" data-link-desc="說明發布前如何用預演檢查部署條件與風險">Deployment Dry Run&lt;/a>&lt;/td>
 &lt;td>發布前如何先驗證流程條件與權限&lt;/td>
 &lt;td>preflight check、artifact check、permission&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/ci/knowledge-cards/backfill/" data-link-title="Backfill" data-link-desc="說明資料處理與 migration 中如何受控補算歷史資料">Backfill&lt;/a>&lt;/td>
 &lt;td>歷史資料如何受控補算&lt;/td>
 &lt;td>migration、data pipeline、repair&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/ci/knowledge-cards/checkpoint/" data-link-title="Checkpoint" data-link-desc="說明長時間任務如何記錄進度以支援接續、重跑與事故修復">Checkpoint&lt;/a>&lt;/td>
 &lt;td>長時間任務如何保存接續位置&lt;/td>
 &lt;td>backfill、stream processor、rerun&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/ci/knowledge-cards/rerun/" data-link-title="Rerun" data-link-desc="說明 CI/CD 與 data pipeline 中重跑任務前需要判斷的輸出語意與副作用">Rerun&lt;/a>&lt;/td>
 &lt;td>重跑流程如何避免擴大副作用&lt;/td>
 &lt;td>flaky test、data repair、pipeline recovery&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/ci/knowledge-cards/image-digest/" data-link-title="Image Digest" data-link-desc="說明 container image digest 如何作為不可變產物身分，支撐掃描、推進與 runtime 追溯">Image Digest&lt;/a>&lt;/td>
 &lt;td>container image 如何取得不可變身分&lt;/td>
 &lt;td>registry、scan、runtime handoff&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/ci/knowledge-cards/sbom/" data-link-title="SBOM" data-link-desc="說明 Software Bill of Materials 如何揭露 artifact 內含元件，支撐供應鏈掃描與例外治理">SBOM&lt;/a>&lt;/td>
 &lt;td>artifact 內含元件如何被揭露&lt;/td>
 &lt;td>image scan、release evidence、compliance&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/ci/knowledge-cards/release-channel/" data-link-title="Release Channel" data-link-desc="說明 stable、beta、internal 等發行通道如何控制 artifact 接觸到的使用者範圍">Release Channel&lt;/a>&lt;/td>
 &lt;td>版本如何依使用者範圍分流&lt;/td>
 &lt;td>app、desktop、beta、stable&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/ci/knowledge-cards/update-feed/" data-link-title="Update Feed" data-link-desc="說明桌面與客戶端應用如何透過更新來源取得已簽章版本與回復路徑">Update Feed&lt;/a>&lt;/td>
 &lt;td>已安裝客戶端如何取得新版本&lt;/td>
 &lt;td>desktop auto-update、rollback channel&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/ci/knowledge-cards/infrastructure-drift/" data-link-title="Infrastructure Drift" data-link-desc="說明真實基礎設施狀態與 IaC 宣告分叉時的偵測、判讀與修復責任">Infrastructure Drift&lt;/a>&lt;/td>
 &lt;td>真實環境與 IaC 宣告如何分叉&lt;/td>
 &lt;td>Terraform、Pulumi、manual hotfix&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/ci/knowledge-cards/state-lock/" data-link-title="State Lock" data-link-desc="說明 IaC apply 如何用狀態鎖避免併發變更覆寫基礎設施狀態">State Lock&lt;/a>&lt;/td>
 &lt;td>IaC apply 如何避免併發覆寫 state&lt;/td>
 &lt;td>Terraform backend、workspace、apply&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/ci/knowledge-cards/function-alias/" data-link-title="Function Alias" data-link-desc="說明 serverless function alias 如何把穩定入口指向特定版本並支援流量切換與回復">Function Alias&lt;/a>&lt;/td>
 &lt;td>serverless 入口如何指向特定版本&lt;/td>
 &lt;td>alias rollback、traffic shift&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/ci/knowledge-cards/event-source/" data-link-title="Event Source" data-link-desc="說明 serverless 與事件驅動流程中觸發來源如何影響 retry、dead-letter 與回復策略">Event Source&lt;/a>&lt;/td>
 &lt;td>事件來源如何影響 retry 與回復&lt;/td>
 &lt;td>queue、topic、HTTP trigger、scheduler&lt;/td>
 &lt;/tr>
 &lt;/tbody>
&lt;/table>
&lt;p>卡片與流程文章分工清楚。卡片負責名詞與邊界，流程文章負責情境判讀與操作路由。&lt;/p></description><content:encoded><![CDATA[<p>CI/CD 知識卡片的核心責任是建立共同語言。流程文章會使用 pipeline、gate、artifact、rollout、rollback、environment protection 等術語；卡片負責定義它們在系統中的位置、可觀察訊號與設計責任。</p>
<h2 id="核心術語">核心術語</h2>
<table>
  <thead>
      <tr>
          <th>卡片</th>
          <th>核心問題</th>
          <th>常見出現位置</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td><a href="/blog/ci/knowledge-cards/ci-pipeline/" data-link-title="CI Pipeline" data-link-desc="說明持續整合如何在合併前自動驗證變更品質與相容性">CI Pipeline</a></td>
          <td>變更如何在合併前被自動驗證</td>
          <td>lint、test、build、security check</td>
      </tr>
      <tr>
          <td><a href="/blog/ci/knowledge-cards/cd-pipeline/" data-link-title="CD Pipeline" data-link-desc="說明持續交付如何把已驗證產物推進到目標環境">CD Pipeline</a></td>
          <td>驗證後產物如何被安全推進到目標環境</td>
          <td>deploy、promotion、release workflow</td>
      </tr>
      <tr>
          <td><a href="/blog/ci/knowledge-cards/required-checks/" data-link-title="Required Checks" data-link-desc="說明 pull request 的必要檢查如何作為合併 gate">Required Checks</a></td>
          <td>PR 合併條件如何由檢查結果定義</td>
          <td>branch protection、status checks</td>
      </tr>
      <tr>
          <td><a href="/blog/ci/knowledge-cards/artifact/" data-link-title="Artifact" data-link-desc="說明 CI/CD 中可被驗證、保存與發布的交付產物">Artifact</a></td>
          <td>交付產物如何被追溯、保存與發布</td>
          <td>build output、image、app bundle</td>
      </tr>
      <tr>
          <td><a href="/blog/ci/knowledge-cards/artifact-handoff/" data-link-title="Artifact Handoff" data-link-desc="說明測試與部署如何共用同一份可追溯產物">Artifact Handoff</a></td>
          <td>測試與發布如何共用同一份產物</td>
          <td>build artifact、package、deploy</td>
      </tr>
      <tr>
          <td><a href="/blog/ci/knowledge-cards/migration/" data-link-title="Migration" data-link-desc="說明資料或結構變更如何在服務不中斷前提下受控推進">Migration</a></td>
          <td>狀態變更如何在相容窗口內受控推進</td>
          <td>schema change、backfill、release</td>
      </tr>
      <tr>
          <td><a href="/blog/ci/knowledge-cards/branch-protection/" data-link-title="Branch Protection" data-link-desc="說明主線分支如何以規則保護合併與發布前置條件">Branch Protection</a></td>
          <td>主線合併條件如何由規則強制保護</td>
          <td>required checks、review policy</td>
      </tr>
      <tr>
          <td><a href="/blog/ci/knowledge-cards/readiness-health-check/" data-link-title="Readiness / Health Check" data-link-desc="說明服務存活與可接流量判斷在部署中的不同責任">Readiness / Health Check</a></td>
          <td>部署放行如何區分存活與可接流量訊號</td>
          <td>rollout、probe、traffic switch</td>
      </tr>
      <tr>
          <td><a href="/blog/ci/knowledge-cards/container-registry/" data-link-title="Container Registry" data-link-desc="說明容器產物儲存、權限與推進流程在 CD 中的責任">Container Registry</a></td>
          <td>image 供應鏈如何被保存與推進</td>
          <td>push、retention、promotion</td>
      </tr>
      <tr>
          <td><a href="/blog/ci/knowledge-cards/app-signing/" data-link-title="App Signing" data-link-desc="說明行動與桌面應用的簽章憑證如何影響發布能力">App Signing</a></td>
          <td>行動與桌面發版能力如何由簽章維持</td>
          <td>certificate、profile、keystore</td>
      </tr>
      <tr>
          <td><a href="/blog/ci/knowledge-cards/flaky-test/" data-link-title="Flaky Test" data-link-desc="說明非決定性測試如何降低 CI gate 信任度與治理方式">Flaky Test</a></td>
          <td>非決定性測試如何影響 gate 信任度</td>
          <td>rerun noise、test governance</td>
      </tr>
      <tr>
          <td><a href="/blog/ci/knowledge-cards/environment-protection/" data-link-title="Environment Protection" data-link-desc="說明目標環境的審核、權限與放行條件如何保護發布">Environment Protection</a></td>
          <td>目標環境如何設置審核與發布保護</td>
          <td>production、staging、review gate</td>
      </tr>
      <tr>
          <td><a href="/blog/ci/knowledge-cards/preview-environment/" data-link-title="Preview Environment" data-link-desc="說明 pull request 變更如何在隔離部署環境中被驗證">Preview Environment</a></td>
          <td>PR 變更如何在隔離環境中被提前驗證</td>
          <td>frontend preview URL、review app</td>
      </tr>
      <tr>
          <td><a href="/blog/ci/knowledge-cards/rollout-strategy/" data-link-title="Rollout Strategy" data-link-desc="說明新版本如何以可控節奏推進到全部流量">Rollout Strategy</a></td>
          <td>新版本如何分批推進以控制風險</td>
          <td>rolling、canary、phased rollout</td>
      </tr>
      <tr>
          <td><a href="/blog/ci/knowledge-cards/rollback-strategy/" data-link-title="Rollback Strategy" data-link-desc="說明發布異常時如何快速回到已知可用狀態">Rollback Strategy</a></td>
          <td>發布異常時如何回到已知可用狀態</td>
          <td>deploy rollback、hotfix、forward fix</td>
      </tr>
      <tr>
          <td><a href="/blog/ci/knowledge-cards/deployment-dry-run/" data-link-title="Deployment Dry Run" data-link-desc="說明發布前如何用預演檢查部署條件與風險">Deployment Dry Run</a></td>
          <td>發布前如何先驗證流程條件與權限</td>
          <td>preflight check、artifact check、permission</td>
      </tr>
      <tr>
          <td><a href="/blog/ci/knowledge-cards/backfill/" data-link-title="Backfill" data-link-desc="說明資料處理與 migration 中如何受控補算歷史資料">Backfill</a></td>
          <td>歷史資料如何受控補算</td>
          <td>migration、data pipeline、repair</td>
      </tr>
      <tr>
          <td><a href="/blog/ci/knowledge-cards/checkpoint/" data-link-title="Checkpoint" data-link-desc="說明長時間任務如何記錄進度以支援接續、重跑與事故修復">Checkpoint</a></td>
          <td>長時間任務如何保存接續位置</td>
          <td>backfill、stream processor、rerun</td>
      </tr>
      <tr>
          <td><a href="/blog/ci/knowledge-cards/rerun/" data-link-title="Rerun" data-link-desc="說明 CI/CD 與 data pipeline 中重跑任務前需要判斷的輸出語意與副作用">Rerun</a></td>
          <td>重跑流程如何避免擴大副作用</td>
          <td>flaky test、data repair、pipeline recovery</td>
      </tr>
      <tr>
          <td><a href="/blog/ci/knowledge-cards/image-digest/" data-link-title="Image Digest" data-link-desc="說明 container image digest 如何作為不可變產物身分，支撐掃描、推進與 runtime 追溯">Image Digest</a></td>
          <td>container image 如何取得不可變身分</td>
          <td>registry、scan、runtime handoff</td>
      </tr>
      <tr>
          <td><a href="/blog/ci/knowledge-cards/sbom/" data-link-title="SBOM" data-link-desc="說明 Software Bill of Materials 如何揭露 artifact 內含元件，支撐供應鏈掃描與例外治理">SBOM</a></td>
          <td>artifact 內含元件如何被揭露</td>
          <td>image scan、release evidence、compliance</td>
      </tr>
      <tr>
          <td><a href="/blog/ci/knowledge-cards/release-channel/" data-link-title="Release Channel" data-link-desc="說明 stable、beta、internal 等發行通道如何控制 artifact 接觸到的使用者範圍">Release Channel</a></td>
          <td>版本如何依使用者範圍分流</td>
          <td>app、desktop、beta、stable</td>
      </tr>
      <tr>
          <td><a href="/blog/ci/knowledge-cards/update-feed/" data-link-title="Update Feed" data-link-desc="說明桌面與客戶端應用如何透過更新來源取得已簽章版本與回復路徑">Update Feed</a></td>
          <td>已安裝客戶端如何取得新版本</td>
          <td>desktop auto-update、rollback channel</td>
      </tr>
      <tr>
          <td><a href="/blog/ci/knowledge-cards/infrastructure-drift/" data-link-title="Infrastructure Drift" data-link-desc="說明真實基礎設施狀態與 IaC 宣告分叉時的偵測、判讀與修復責任">Infrastructure Drift</a></td>
          <td>真實環境與 IaC 宣告如何分叉</td>
          <td>Terraform、Pulumi、manual hotfix</td>
      </tr>
      <tr>
          <td><a href="/blog/ci/knowledge-cards/state-lock/" data-link-title="State Lock" data-link-desc="說明 IaC apply 如何用狀態鎖避免併發變更覆寫基礎設施狀態">State Lock</a></td>
          <td>IaC apply 如何避免併發覆寫 state</td>
          <td>Terraform backend、workspace、apply</td>
      </tr>
      <tr>
          <td><a href="/blog/ci/knowledge-cards/function-alias/" data-link-title="Function Alias" data-link-desc="說明 serverless function alias 如何把穩定入口指向特定版本並支援流量切換與回復">Function Alias</a></td>
          <td>serverless 入口如何指向特定版本</td>
          <td>alias rollback、traffic shift</td>
      </tr>
      <tr>
          <td><a href="/blog/ci/knowledge-cards/event-source/" data-link-title="Event Source" data-link-desc="說明 serverless 與事件驅動流程中觸發來源如何影響 retry、dead-letter 與回復策略">Event Source</a></td>
          <td>事件來源如何影響 retry 與回復</td>
          <td>queue、topic、HTTP trigger、scheduler</td>
      </tr>
  </tbody>
</table>
<p>卡片與流程文章分工清楚。卡片負責名詞與邊界，流程文章負責情境判讀與操作路由。</p>
]]></content:encoded></item></channel></rss>