<?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>Foundations on Tarragon</title><link>https://tarrragon.github.io/blog/tags/foundations/</link><description>Recent content in Foundations on Tarragon</description><generator>Hugo -- gohugo.io</generator><language>zh-TW</language><copyright>Tarragon (CC BY 4.0)</copyright><lastBuildDate>Thu, 14 May 2026 00:00:00 +0000</lastBuildDate><atom:link href="https://tarrragon.github.io/blog/tags/foundations/index.xml" rel="self" type="application/rss+xml"/><item><title>0.1 為什麼 LLM 生字慢</title><link>https://tarrragon.github.io/blog/llm/00-foundations/why-llm-feels-slow/</link><pubDate>Mon, 11 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/llm/00-foundations/why-llm-feels-slow/</guid><description>&lt;p>LLM 生字慢的核心原因有兩個：&lt;strong>&lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/autoregressive/" data-link-title="Autoregressive" data-link-desc="LLM 一次生成一個 token、把已生成內容作為下一次輸入的架構">自回歸架構&lt;/a>&lt;/strong>（autoregressive）讓模型一次生一個 &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>&lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/memory-bandwidth/" data-link-title="Memory Bandwidth" data-link-desc="記憶體每秒能讀寫多少 bytes：決定本地 LLM 生字速度的真正瓶頸">記憶體頻寬&lt;/a>瓶頸&lt;/strong>讓 Apple Silicon 在算力之外有一個獨立的速度上限。這兩個瓶頸結合起來、才能解釋為什麼 32GB Mac 跑 31B 模型約 30 &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：生字速度的標準量化指標">tok/s&lt;/a>、而資料中心的 H100 跑同樣模型能到 200 tok/s。&lt;/p>
&lt;p>理解這個機制不只是為了知識本身。後續所有加速技巧（&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>、&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/quantization/" data-link-title="Quantization" data-link-desc="用較少 bits 表示模型權重：壓縮記憶體佔用、加快生字速度，代價是少量品質衰減">量化&lt;/a>）都是在攻擊這兩個瓶頸的不同部分；不懂瓶頸在哪，看到「2x 加速」「3x 加速」這種廣告詞就無從判讀。&lt;/p>
&lt;h2 id="本章目標">本章目標&lt;/h2>
&lt;p>讀完本章後，你應該能回答：&lt;/p>
&lt;ol>
&lt;li>為什麼 LLM 採用「一個 token 接一個 token」的生成方式、而非整段一次生出？&lt;/li>
&lt;li>為什麼 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>」對 LLM 推論是優勢？&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>為什麼長 prompt 的&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 出現的等待時間">首字延遲&lt;/a>特別有感？&lt;/li>
&lt;/ol>
&lt;h2 id="自回歸架構一次只能吐一個-token">自回歸架構：一次只能吐一個 token&lt;/h2>
&lt;p>自回歸的核心概念是「下一個 token 的生成需要前面所有 token 的結果」。模型每生成一個 token，都要把目前已有的 token 序列（你的 prompt + 它已經生成的部分）重新丟進神經網路算一次，得到下一個 token 的機率分佈，挑一個輸出，然後重複。&lt;/p>
&lt;p>舉個具體例子。當你輸入 &lt;code>寫一個 Python function 計算費氏數列&lt;/code>，模型生成回答的過程大致是：&lt;/p>
&lt;ol>
&lt;li>把 prompt 丟進模型，產出第一個 token，例如 &lt;code>def&lt;/code>。&lt;/li>
&lt;li>把 prompt + &lt;code>def&lt;/code> 丟進模型，產出 &lt;code>fib&lt;/code>。&lt;/li>
&lt;li>把 prompt + &lt;code>def fib&lt;/code> 丟進模型，產出 &lt;code>(&lt;/code>。&lt;/li>
&lt;li>一直重複到模型決定產出結束 token。&lt;/li>
&lt;/ol>
&lt;p>每一步都要跑一次完整的神經網路 forward pass（神經網路把輸入資料從第一層算到最後一層、產出輸出的單次計算）。這就是為什麼回答長度直接影響等待時間、跟雲端旗艦模型一樣；差別只是雲端每個 forward pass 跑得更快。&lt;/p>
&lt;p>陷阱是把自回歸跟 streaming 混淆。Streaming 只是把已產出的 token 即時顯示在畫面上，看起來「邊想邊說」；模型內部該跑幾次 forward pass 就是幾次，streaming 不會加速生成本身。&lt;/p>
&lt;h2 id="記憶體頻寬apple-silicon-真正的瓶頸">記憶體頻寬：Apple Silicon 真正的瓶頸&lt;/h2>
&lt;p>LLM 推論的瓶頸幾乎一定落在記憶體頻寬、而不是算力。原因是每生成一個 token 都要把整個模型的權重從記憶體讀到處理器一次；模型有多大、每秒能讀多少 GB、就決定了每秒能吐幾個 token。每生一個 token 都要把整份權重讀過一次、所以「每秒能讀完幾份權重」就是「每秒能吐幾個 token」。&lt;/p>
&lt;p>模型大小的換算規則很簡單：bf16 每個權重佔 2 bytes、Q4 量化後每個權重約 0.5 byte。所以：&lt;/p>
&lt;ul>
&lt;li>Gemma 4 31B 的 bf16 權重約 62GB（31B × 2 bytes）、Q4 量化後約 18GB。&lt;/li>
&lt;li>M4 Max 的記憶體頻寬約 546 GB/s、M2 Pro 約 200 GB/s。&lt;/li>
&lt;li>理論上限 = 頻寬 / 模型大小。M4 Max 跑 Q4 量化 31B 模型、理論上限約 546 / 18 ≈ 30 tok/s。&lt;/li>
&lt;/ul>
&lt;p>實際數字會比理論上限低 30 ~ 50%（attention 機制的 KV cache 也要讀寫、有些運算需要中間結果），所以 M4 Max 跑 Q4 31B 大約落在 20 ~ 25 tok/s。這個推導讓你看到任何「在 Mac 上跑 70B 模型很快」的說法時，可以直接用頻寬算一下合不合理。&lt;/p></description><content:encoded><![CDATA[<p>LLM 生字慢的核心原因有兩個：<strong><a href="/blog/llm/knowledge-cards/autoregressive/" data-link-title="Autoregressive" data-link-desc="LLM 一次生成一個 token、把已生成內容作為下一次輸入的架構">自回歸架構</a></strong>（autoregressive）讓模型一次生一個 <a href="/blog/llm/knowledge-cards/token/" data-link-title="Token" data-link-desc="LLM 處理文字時的最小單位：介於字元與單字之間">token</a>、<strong><a href="/blog/llm/knowledge-cards/memory-bandwidth/" data-link-title="Memory Bandwidth" data-link-desc="記憶體每秒能讀寫多少 bytes：決定本地 LLM 生字速度的真正瓶頸">記憶體頻寬</a>瓶頸</strong>讓 Apple Silicon 在算力之外有一個獨立的速度上限。這兩個瓶頸結合起來、才能解釋為什麼 32GB Mac 跑 31B 模型約 30 <a href="/blog/llm/knowledge-cards/tokens-per-second/" data-link-title="Tokens Per Second" data-link-desc="LLM 每秒能生成幾個 token：生字速度的標準量化指標">tok/s</a>、而資料中心的 H100 跑同樣模型能到 200 tok/s。</p>
<p>理解這個機制不只是為了知識本身。後續所有加速技巧（<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>、<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/quantization/" data-link-title="Quantization" data-link-desc="用較少 bits 表示模型權重：壓縮記憶體佔用、加快生字速度，代價是少量品質衰減">量化</a>）都是在攻擊這兩個瓶頸的不同部分；不懂瓶頸在哪，看到「2x 加速」「3x 加速」這種廣告詞就無從判讀。</p>
<h2 id="本章目標">本章目標</h2>
<p>讀完本章後，你應該能回答：</p>
<ol>
<li>為什麼 LLM 採用「一個 token 接一個 token」的生成方式、而非整段一次生出？</li>
<li>為什麼 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>」對 LLM 推論是優勢？</li>
<li>為什麼<a href="/blog/llm/knowledge-cards/quantization/" data-link-title="Quantization" data-link-desc="用較少 bits 表示模型權重：壓縮記憶體佔用、加快生字速度，代價是少量品質衰減">模型量化</a>能加速、而非只是省記憶體？</li>
<li>為什麼長 prompt 的<a href="/blog/llm/knowledge-cards/ttft/" data-link-title="TTFT" data-link-desc="Time To First Token：送出 prompt 到第一個 token 出現的等待時間">首字延遲</a>特別有感？</li>
</ol>
<h2 id="自回歸架構一次只能吐一個-token">自回歸架構：一次只能吐一個 token</h2>
<p>自回歸的核心概念是「下一個 token 的生成需要前面所有 token 的結果」。模型每生成一個 token，都要把目前已有的 token 序列（你的 prompt + 它已經生成的部分）重新丟進神經網路算一次，得到下一個 token 的機率分佈，挑一個輸出，然後重複。</p>
<p>舉個具體例子。當你輸入 <code>寫一個 Python function 計算費氏數列</code>，模型生成回答的過程大致是：</p>
<ol>
<li>把 prompt 丟進模型，產出第一個 token，例如 <code>def</code>。</li>
<li>把 prompt + <code>def</code> 丟進模型，產出 <code>fib</code>。</li>
<li>把 prompt + <code>def fib</code> 丟進模型，產出 <code>(</code>。</li>
<li>一直重複到模型決定產出結束 token。</li>
</ol>
<p>每一步都要跑一次完整的神經網路 forward pass（神經網路把輸入資料從第一層算到最後一層、產出輸出的單次計算）。這就是為什麼回答長度直接影響等待時間、跟雲端旗艦模型一樣；差別只是雲端每個 forward pass 跑得更快。</p>
<p>陷阱是把自回歸跟 streaming 混淆。Streaming 只是把已產出的 token 即時顯示在畫面上，看起來「邊想邊說」；模型內部該跑幾次 forward pass 就是幾次，streaming 不會加速生成本身。</p>
<h2 id="記憶體頻寬apple-silicon-真正的瓶頸">記憶體頻寬：Apple Silicon 真正的瓶頸</h2>
<p>LLM 推論的瓶頸幾乎一定落在記憶體頻寬、而不是算力。原因是每生成一個 token 都要把整個模型的權重從記憶體讀到處理器一次；模型有多大、每秒能讀多少 GB、就決定了每秒能吐幾個 token。每生一個 token 都要把整份權重讀過一次、所以「每秒能讀完幾份權重」就是「每秒能吐幾個 token」。</p>
<p>模型大小的換算規則很簡單：bf16 每個權重佔 2 bytes、Q4 量化後每個權重約 0.5 byte。所以：</p>
<ul>
<li>Gemma 4 31B 的 bf16 權重約 62GB（31B × 2 bytes）、Q4 量化後約 18GB。</li>
<li>M4 Max 的記憶體頻寬約 546 GB/s、M2 Pro 約 200 GB/s。</li>
<li>理論上限 = 頻寬 / 模型大小。M4 Max 跑 Q4 量化 31B 模型、理論上限約 546 / 18 ≈ 30 tok/s。</li>
</ul>
<p>實際數字會比理論上限低 30 ~ 50%（attention 機制的 KV cache 也要讀寫、有些運算需要中間結果），所以 M4 Max 跑 Q4 31B 大約落在 20 ~ 25 tok/s。這個推導讓你看到任何「在 Mac 上跑 70B 模型很快」的說法時，可以直接用頻寬算一下合不合理。</p>
<p>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>**（Unified Memory Architecture, UMA）讓 CPU、GPU、Neural Engine 共用同一塊記憶體、省下跨 PCIe 搬資料的成本。傳統 PC + NVIDIA GPU 的記憶體分成系統記憶體跟 VRAM；模型權重要放進 VRAM 才能用 GPU 跑、跨 PCIe 搬資料的速度成本很高。Mac 的 64GB 統一記憶體可以幾乎全部給模型用（扣掉系統保留部分）、同等價位的 PC 通常只有 12GB ~ 24GB VRAM。</p>
<p>這就是為什麼 Mac 在「跑得動多大的模型」上佔優勢，但在「跑多快」上輸給 H100。H100 的 HBM 頻寬約 3,300 GB/s，是 M4 Max 的 6 倍。能跑得動 vs 跑得快，是兩件事。</p>
<h2 id="量化用精度換頻寬">量化：用精度換頻寬</h2>
<p>量化的核心是把模型權重從 16-bit float 壓成 4-bit、5-bit、8-bit integer。權重數量不變，但每個權重佔的 bytes 變少；模型總大小變小，每秒能讀過的權重變多，生字速度直接變快。</p>
<p>常見量化等級：</p>
<table>
  <thead>
      <tr>
          <th>量化</th>
          <th>每權重 bits</th>
          <th>相對 bf16 大小</th>
          <th>品質衰減</th>
          <th>適合場景</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>bf16</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</td>
          <td>5</td>
          <td>0.31x</td>
          <td>輕微</td>
          <td>24GB Mac、日常使用</td>
      </tr>
      <tr>
          <td>Q4_K</td>
          <td>4</td>
          <td>0.25x</td>
          <td>可察覺但實用</td>
          <td>16 ~ 24GB Mac、最常用甜蜜點</td>
      </tr>
      <tr>
          <td>Q3</td>
          <td>3</td>
          <td>0.19x</td>
          <td>明顯、coding 任務 hallucination 上升</td>
          <td>記憶體緊張時的權宜選擇、coding 慎用</td>
      </tr>
  </tbody>
</table>
<p>接近真實的選擇：</p>
<ul>
<li>32GB Mac 跑 31B 模型：選 Q4_K，記憶體佔用 ~ 18GB，留 14GB 給系統與 IDE。</li>
<li>24GB Mac 跑 14B 模型：選 Q5_K 或 Q4_K，看任務品質要求。</li>
<li>16GB Mac 跑 7B 模型：選 Q4_K，是現實上界。</li>
</ul>
<p>陷阱是把量化等級拉到極限以塞下更大模型。Coding 任務上 Q3 的 31B 模型常輸給 Q5 的 14B 模型；模型「夠大」跟「夠好」是兩件事、選 model size 時先看任務通過率、再用量化等級調記憶體。後續 <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>
<h2 id="kv-cache-與長-prompt-痛點">KV cache 與長 prompt 痛點</h2>
<p><a href="/blog/llm/knowledge-cards/kv-cache/" data-link-title="KV Cache" data-link-desc="已處理 token 的 attention 中間結果暫存：避免重算、加速後續生成">KV cache</a>（key-value cache）把 attention 機制每個 token 產生的中間結果暫存、後續 token 生成時直接讀 cache 跳過重算、讓「已經算過的 prompt」省下重複跑 forward pass。</p>
<p>但 KV cache 有兩個性質會放大長 prompt 的痛點：</p>
<ol>
<li><strong>首次處理 prompt 時要完整算過一次</strong>、這個階段稱為 <strong><a href="/blog/llm/knowledge-cards/prefill/" data-link-title="Prefill" data-link-desc="Prompt 首次處理時的計算階段：把整段輸入跑過模型、產生 KV cache">prefill</a></strong>。10K token 的 prompt 在本地可能需要 30 ~ 90 秒才 prefill 完、這 30 ~ 90 秒就是 <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>KV cache 本身佔記憶體</strong>：長 <a href="/blog/llm/knowledge-cards/context-window/" data-link-title="Context Window" data-link-desc="模型一次能處理的最大 token 數量：prompt 加生成的總和上限">context</a> 跑下來、KV cache 可能比模型權重還大、會擠壓可用記憶體。</li>
</ol>
<p>這就是為什麼 coding agent 場景（塞整個 repo 進 prompt）在本地特別痛：每次都要重新 prefill，每次都等 30 ~ 90 秒。oMLX 這類特化伺服器就是針對這個痛點，用 paged SSD KV cache 把已 prefill 過的 context 存到 SSD，下次同樣的 prompt 前綴可以直接讀 cache，把 TTFT 從 30 ~ 90 秒降到 1 ~ 3 秒。詳見 <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>
<h2 id="speculative-decoding-與-mtp">Speculative decoding 與 MTP</h2>
<p>既然瓶頸是「每生一個 token 都要讀一次完整模型權重」、那能否一次生多個 token？<a href="/blog/llm/knowledge-cards/speculative-decoding/" data-link-title="Speculative Decoding" data-link-desc="用小模型猜未來 token、大模型並行驗證的加速技巧">speculative decoding</a>（推測解碼）就是這個想法的具體實作。</p>
<p>機制大致是：</p>
<ol>
<li>用一個小模型（<a href="/blog/llm/knowledge-cards/drafter-model/" data-link-title="Drafter Model" data-link-desc="speculative decoding 中用來快速猜未來 token 的小模型">drafter</a>、例如 1B 參數）快速猜未來 N 個 token。</li>
<li>把這 N 個 token 一次餵給大模型（target、例如 31B 參數）、讓大模型並行驗證每個位置的機率分佈。</li>
<li>大模型保留認同的前綴、從第一個拒絕點之後重新生成。</li>
</ol>
<p>這個機制能加速的關鍵是「大模型的驗證可以並行」。一次 forward pass 驗證 N 個 token 的時間，跟驗證 1 個 token 的時間差不多（因為瓶頸是讀權重，不是算力）。如果接受率高，等於一次 forward pass 產出多個 token。</p>
<p>寫 code 場景特別適合 speculative decoding、因為 code 有大量可預測 pattern（縮排、括號、常見變數名、import 語句）、小模型猜對的接受率高。Google 為 Gemma 4 釋出官方 drafter、官方數據在 coding 任務有 2 ~ 3 倍加速；接受率低的任務（純創意寫作、隨機字串生成）加速幅度可能降到 1.5 倍左右、加速倍數跟任務 pattern 強相關。</p>
<p><strong><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></strong>（MTP）是這個概念的具體實作、本質是 speculative decoding 的工程化版本。下一章 <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> 會把 MTP 跟其他容易混淆的術語放在一起對照。</p>
<h2 id="何時這套推導失準">何時這套推導失準</h2>
<p>「頻寬決定生字速度」是 dense 模型 + 單請求情境下的乾淨推導。實務上有三類情境會讓這個公式失準、解讀效能數字時要對應調整：</p>
<ol>
<li><strong>MoE 模型（Mixture of Experts）</strong>：每個 token 只啟用部分專家層、實際讀的權重遠小於總權重。例如 Mixtral 8x7B 名義 46B 參數、但每個 token 只啟用約 12B、速度上限要用「啟用權重」算、不是總權重。判讀 MoE 模型在 PC 獨立 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>。</li>
<li><strong>多請求 batching</strong>：資料中心級推論伺服器把多請求 batch 一起跑、權重讀一次處理 N 個 token、攤平頻寬成本。本章開頭舉的「H100 跑 200 tok/s」是 batch=1 的單 user 數字、production 場景 batch=32 時單 user 看到的速度更接近 50 tok/s、但 total throughput 翻 N 倍。詳見 <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>。</li>
<li><strong>Speculative decoding 接受率變動</strong>：MTP / drafter 的加速幅度跟任務 pattern 強相關、coding 任務的 2 ~ 3 倍無法直接 carryover 到創意寫作、看 benchmark 數字時要追問「跑的是哪類任務」。</li>
</ol>
<p>判讀效能數字時的反射動作：先問「dense 還是 MoE」「batch 多少」「任務 pattern 強弱」、再決定能不能套頻寬公式。</p>
<h2 id="下一章">下一章</h2>
<p>下一章：<a href="/blog/llm/00-foundations/three-layer-architecture/" data-link-title="0.2 介面 / 伺服器 / 模型三層架構" data-link-desc="把任何本地 LLM 工具放回正確的層級，用三層心智模型看懂工具關係">0.2 三層架構</a>，把任何本地 LLM 工具放回正確的層級。</p>
]]></content:encoded></item><item><title>0.2 介面 / 伺服器 / 模型三層架構</title><link>https://tarrragon.github.io/blog/llm/00-foundations/three-layer-architecture/</link><pubDate>Mon, 11 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/llm/00-foundations/three-layer-architecture/</guid><description>&lt;p>本地 LLM 生態的核心心智模型是**&lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/three-layer-architecture/" data-link-title="Three-Layer Architecture" data-link-desc="把本地 LLM 工具拆成介面層、推論伺服器層、模型權重層的基礎心智模型">三層架構&lt;/a>**：介面層（CLI / UI / Plugin）→ 伺服器層（推論引擎與 API）→ 模型本身（權重檔）。三層之間有明確邊界，每層可以獨立替換；理解這個分層後，看到任何新工具都能立刻判斷它在解哪一層的問題。&lt;/p>
&lt;p>對應到你已經熟悉的雲端世界：ChatGPT 網頁是介面層，OpenAI 的後端服務是伺服器層，GPT-5 模型是模型層。Cursor 是另一個介面層，連到的也是同一批雲端伺服器。介面跟伺服器各自獨立演化，這就是為什麼換介面不用換模型、換模型不用換介面。&lt;/p>
&lt;p>本地 LLM 把這三層全部搬到你的 Mac 上，但分層關係不變。看懂這點，後面所有工具關係就清楚。&lt;/p>
&lt;h2 id="本章目標">本章目標&lt;/h2>
&lt;p>讀完本章後，你應該能：&lt;/p>
&lt;ol>
&lt;li>看到任一個本地 LLM 工具，立刻判斷它屬於哪一層。&lt;/li>
&lt;li>理解為什麼可以「介面換、伺服器留」或「伺服器換、介面留」。&lt;/li>
&lt;li>看懂 &lt;code>localhost:11434&lt;/code> 這類本地 API endpoint 的意義。&lt;/li>
&lt;li>對應雲端世界的工具，建立熟悉感橋接。&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;th>雲端對應&lt;/th>
 &lt;/tr>
 &lt;/thead>
 &lt;tbody>
 &lt;tr>
 &lt;td>介面層&lt;/td>
 &lt;td>接收使用者輸入、顯示輸出、整合 IDE / 終端機&lt;/td>
 &lt;td>Continue.dev、Open WebUI、aider、CLI&lt;/td>
 &lt;td>ChatGPT 網頁、Cursor、Claude Desktop&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>伺服器層&lt;/td>
 &lt;td>載入模型權重、處理 prompt、產生 token、提供 HTTP API&lt;/td>
 &lt;td>Ollama、LM Studio、llama.cpp &lt;code>server&lt;/code>、oMLX、vLLM&lt;/td>
 &lt;td>OpenAI 後端服務、Anthropic 後端服務&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>模型層&lt;/td>
 &lt;td>神經網路權重檔本身&lt;/td>
 &lt;td>Gemma 4、Qwen3、Llama 3.x、gpt-oss&lt;/td>
 &lt;td>GPT-5、Claude Sonnet、Gemini&lt;/td>
 &lt;/tr>
 &lt;/tbody>
&lt;/table>
&lt;p>這張表是後續判讀新工具的基底。任何工具都可以放到這三層的某一格；少數工具同時跨多層（例如 LM Studio 內建介面跟伺服器），但它的功能仍可拆成三層去理解。&lt;/p>
&lt;h2 id="介面層你實際在用的東西">介面層：你實際在用的東西&lt;/h2>
&lt;p>介面層的責任是「人類能舒服地把任務送進去、把結果拿出來」。它本身不跑模型，只是把使用者輸入打包成 API 請求、把 API 回應顯示出來。&lt;/p>
&lt;p>接近真實的例子：&lt;/p>
&lt;ul>
&lt;li>&lt;strong>Continue.dev&lt;/strong>：VS Code 擴充套件，把 Cmd+L 開啟側邊對話框、Cmd+I 觸發 inline 編輯。背後送的是 OpenAI 相容 API 請求，target 可以是本地 Ollama 也可以是雲端 OpenAI。&lt;/li>
&lt;li>&lt;strong>aider&lt;/strong>：CLI 工具，把 git 倉庫狀態跟 prompt 一起打包送進 LLM，再把回應的 diff apply 到本機檔案。背後也是送 API 請求。&lt;/li>
&lt;li>&lt;strong>Open WebUI&lt;/strong>：類 ChatGPT 風格的網頁介面，跑在本機 Docker 裡，連到本地或遠端的 LLM API。&lt;/li>
&lt;li>&lt;strong>CLI 直接呼叫&lt;/strong>：&lt;code>ollama run gemma4:31b&lt;/code> 在終端機開一個對話 session，本身也是一個介面層。&lt;/li>
&lt;/ul>
&lt;p>介面層的選擇影響日常使用體驗，但完全不影響推論速度或品質。換介面不用換模型，這就是分層的好處。&lt;/p>
&lt;h2 id="伺服器層載入權重與跑推論">伺服器層：載入權重與跑推論&lt;/h2>
&lt;p>&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>負責把模型權重從磁碟載入記憶體、接收 HTTP API 請求、處理 prompt、跑推論、把生成的 token 流回客戶端。&lt;/p>
&lt;p>接近真實的例子：&lt;/p>
&lt;ul>
&lt;li>&lt;strong>&lt;a href="https://tarrragon.github.io/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&lt;/a>&lt;/strong>：最主流的本地推論伺服器、預設聽 &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 的對外暴露範圍">&lt;code>localhost:11434&lt;/code>&lt;/a>、提供 OpenAI 相容 API 與自己的原生 API。內建 model registry、&lt;code>ollama pull gemma4:31b&lt;/code> 會自動下載權重檔。&lt;/li>
&lt;li>&lt;strong>&lt;a href="https://tarrragon.github.io/blog/llm/01-local-llm-services/lm-studio/" data-link-title="1.1 LM Studio：GUI 探索模型" data-link-desc="GUI 取向的本地推論伺服器：內建模型瀏覽器、speculative decoding 設定面板、適合探索新模型">LM Studio&lt;/a>&lt;/strong>：GUI 工具、內建模型瀏覽器與本地伺服器。可以在 UI 上開啟 server、預設聽 &lt;code>localhost:1234&lt;/code>。適合喜歡可視化操作、不熟悉終端機的使用者。&lt;/li>
&lt;li>&lt;strong>&lt;a href="https://tarrragon.github.io/blog/llm/01-local-llm-services/llama-cpp/" data-link-title="1.2 llama.cpp：底層推論引擎" data-link-desc="GGUF 格式、量化、MTP 仍 beta；多數讀者不需要直接接觸，Ollama 已經包好">llama.cpp &lt;code>server&lt;/code>&lt;/a>&lt;/strong>：底層推論引擎附帶的 HTTP server、需要手動編譯與配置。Ollama 內部其實是用 llama.cpp 當推論引擎。&lt;/li>
&lt;li>&lt;strong>&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;/strong>：建在 MLX 之上的特化伺服器、主打 paged SSD KV cache、針對 coding agent 長 context 場景的首字延遲優化。詳見 &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;/li>
&lt;/ul>
&lt;p>伺服器層的選擇影響：&lt;/p></description><content:encoded><![CDATA[<p>本地 LLM 生態的核心心智模型是**<a href="/blog/llm/knowledge-cards/three-layer-architecture/" data-link-title="Three-Layer Architecture" data-link-desc="把本地 LLM 工具拆成介面層、推論伺服器層、模型權重層的基礎心智模型">三層架構</a>**：介面層（CLI / UI / Plugin）→ 伺服器層（推論引擎與 API）→ 模型本身（權重檔）。三層之間有明確邊界，每層可以獨立替換；理解這個分層後，看到任何新工具都能立刻判斷它在解哪一層的問題。</p>
<p>對應到你已經熟悉的雲端世界：ChatGPT 網頁是介面層，OpenAI 的後端服務是伺服器層，GPT-5 模型是模型層。Cursor 是另一個介面層，連到的也是同一批雲端伺服器。介面跟伺服器各自獨立演化，這就是為什麼換介面不用換模型、換模型不用換介面。</p>
<p>本地 LLM 把這三層全部搬到你的 Mac 上，但分層關係不變。看懂這點，後面所有工具關係就清楚。</p>
<h2 id="本章目標">本章目標</h2>
<p>讀完本章後，你應該能：</p>
<ol>
<li>看到任一個本地 LLM 工具，立刻判斷它屬於哪一層。</li>
<li>理解為什麼可以「介面換、伺服器留」或「伺服器換、介面留」。</li>
<li>看懂 <code>localhost:11434</code> 這類本地 API endpoint 的意義。</li>
<li>對應雲端世界的工具，建立熟悉感橋接。</li>
</ol>
<h2 id="三層的責任邊界">三層的責任邊界</h2>
<table>
  <thead>
      <tr>
          <th>層級</th>
          <th>責任</th>
          <th>本地代表</th>
          <th>雲端對應</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>介面層</td>
          <td>接收使用者輸入、顯示輸出、整合 IDE / 終端機</td>
          <td>Continue.dev、Open WebUI、aider、CLI</td>
          <td>ChatGPT 網頁、Cursor、Claude Desktop</td>
      </tr>
      <tr>
          <td>伺服器層</td>
          <td>載入模型權重、處理 prompt、產生 token、提供 HTTP API</td>
          <td>Ollama、LM Studio、llama.cpp <code>server</code>、oMLX、vLLM</td>
          <td>OpenAI 後端服務、Anthropic 後端服務</td>
      </tr>
      <tr>
          <td>模型層</td>
          <td>神經網路權重檔本身</td>
          <td>Gemma 4、Qwen3、Llama 3.x、gpt-oss</td>
          <td>GPT-5、Claude Sonnet、Gemini</td>
      </tr>
  </tbody>
</table>
<p>這張表是後續判讀新工具的基底。任何工具都可以放到這三層的某一格；少數工具同時跨多層（例如 LM Studio 內建介面跟伺服器），但它的功能仍可拆成三層去理解。</p>
<h2 id="介面層你實際在用的東西">介面層：你實際在用的東西</h2>
<p>介面層的責任是「人類能舒服地把任務送進去、把結果拿出來」。它本身不跑模型，只是把使用者輸入打包成 API 請求、把 API 回應顯示出來。</p>
<p>接近真實的例子：</p>
<ul>
<li><strong>Continue.dev</strong>：VS Code 擴充套件，把 Cmd+L 開啟側邊對話框、Cmd+I 觸發 inline 編輯。背後送的是 OpenAI 相容 API 請求，target 可以是本地 Ollama 也可以是雲端 OpenAI。</li>
<li><strong>aider</strong>：CLI 工具，把 git 倉庫狀態跟 prompt 一起打包送進 LLM，再把回應的 diff apply 到本機檔案。背後也是送 API 請求。</li>
<li><strong>Open WebUI</strong>：類 ChatGPT 風格的網頁介面，跑在本機 Docker 裡，連到本地或遠端的 LLM API。</li>
<li><strong>CLI 直接呼叫</strong>：<code>ollama run gemma4:31b</code> 在終端機開一個對話 session，本身也是一個介面層。</li>
</ul>
<p>介面層的選擇影響日常使用體驗，但完全不影響推論速度或品質。換介面不用換模型，這就是分層的好處。</p>
<h2 id="伺服器層載入權重與跑推論">伺服器層：載入權重與跑推論</h2>
<p><a href="/blog/llm/knowledge-cards/inference-server/" data-link-title="Inference Server" data-link-desc="載入模型權重、處理 prompt、產生 token 的常駐 process">伺服器層</a>負責把模型權重從磁碟載入記憶體、接收 HTTP API 請求、處理 prompt、跑推論、把生成的 token 流回客戶端。</p>
<p>接近真實的例子：</p>
<ul>
<li><strong><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></strong>：最主流的本地推論伺服器、預設聽 <a href="/blog/llm/knowledge-cards/port-and-localhost/" data-link-title="Port 與 Localhost" data-link-desc="TCP port 與 listen address 如何決定 API server 的對外暴露範圍"><code>localhost:11434</code></a>、提供 OpenAI 相容 API 與自己的原生 API。內建 model registry、<code>ollama pull gemma4:31b</code> 會自動下載權重檔。</li>
<li><strong><a href="/blog/llm/01-local-llm-services/lm-studio/" data-link-title="1.1 LM Studio：GUI 探索模型" data-link-desc="GUI 取向的本地推論伺服器：內建模型瀏覽器、speculative decoding 設定面板、適合探索新模型">LM Studio</a></strong>：GUI 工具、內建模型瀏覽器與本地伺服器。可以在 UI 上開啟 server、預設聽 <code>localhost:1234</code>。適合喜歡可視化操作、不熟悉終端機的使用者。</li>
<li><strong><a href="/blog/llm/01-local-llm-services/llama-cpp/" data-link-title="1.2 llama.cpp：底層推論引擎" data-link-desc="GGUF 格式、量化、MTP 仍 beta；多數讀者不需要直接接觸，Ollama 已經包好">llama.cpp <code>server</code></a></strong>：底層推論引擎附帶的 HTTP server、需要手動編譯與配置。Ollama 內部其實是用 llama.cpp 當推論引擎。</li>
<li><strong><a href="/blog/llm/knowledge-cards/omlx/" data-link-title="oMLX" data-link-desc="以 MLX 為基礎、針對 Apple Silicon 長 context 與 SSD KV cache 優化的本地推論伺服器路線">oMLX</a></strong>：建在 MLX 之上的特化伺服器、主打 paged SSD KV cache、針對 coding agent 長 context 場景的首字延遲優化。詳見 <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>。</li>
</ul>
<p>伺服器層的選擇影響：</p>
<ol>
<li><strong>速度</strong>：不同伺服器對量化、KV cache、speculative decoding 的支援度不同。</li>
<li><strong>能跑哪些模型</strong>：每個伺服器支援的模型格式不同（GGUF、MLX、Safetensors 等）。</li>
<li><strong>API 形狀</strong>：多數本地伺服器同時提供「OpenAI 相容」跟「自家原生」兩套 API。詳見 <a href="/blog/llm/00-foundations/openai-compatible-api/" data-link-title="0.3 OpenAI 相容 API" data-link-desc="為什麼幾乎所有本地 LLM 工具不用改就能切到本地：背後是同一套 API 形狀">0.3 OpenAI 相容 API</a>。</li>
</ol>
<p>陷阱是把伺服器跟模型混為一談。「Ollama 跑得快不快」這句話離開模型與機器脈絡就難以判讀、要追問「Ollama 跑哪個模型、在哪台 Mac 上、tok/s 多少」才有意義。伺服器是執行引擎、模型是被執行的對象。</p>
<h2 id="模型層權重檔本身">模型層：權重檔本身</h2>
<p>模型層就是神經網路的權重檔。本身只是一堆數字，沒有伺服器就無法執行；但同一個模型可以被不同伺服器載入，前提是格式相容。</p>
<p>接近真實的例子：</p>
<ul>
<li><strong>Gemma 4 31B</strong>：Google 釋出的開源模型，31 billion 參數。權重檔可以是 <code>gemma-4-31b-it-Q4_K_M.gguf</code>（GGUF 格式、Q4 量化）或 <code>mlx-community/gemma-4-31b-it-4bit</code>（MLX 格式）。</li>
<li><strong>Qwen3-Coder 30B</strong>：Alibaba 釋出的 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> 等 coding benchmark 上表現強。</li>
<li><strong>Llama 3.x 系列</strong>：Meta 釋出的開源模型，是早期本地 LLM 生態的主力。</li>
<li><strong>gpt-oss 20B</strong>：OpenAI 釋出的開源版本，2025 年發布。</li>
</ul>
<p>模型層的關鍵屬性：</p>
<ol>
<li><strong>參數規模</strong>（B = billion）：7B、14B、31B、70B 等。規模越大能力越強，但記憶體佔用、推論速度成本也越高。</li>
<li><strong>量化等級</strong>：bf16、Q8、Q5_K、Q4_K 等。同模型不同量化，記憶體與品質的取捨不同。</li>
<li><strong>格式</strong>：GGUF（llama.cpp 與 Ollama 主流）、MLX（Apple 框架）、Safetensors（Hugging Face 通用）等。不同伺服器支援的格式不同。</li>
<li><strong>訓練目的</strong>：<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/instruction-tuned/" data-link-title="Instruction-Tuned Model" data-link-desc="經過指令微調的模型：會跟著 prompt 走、回答使用者問題">instruction-tuned</a>、coding-tuned 等。寫 code 場景下 instruction-tuned + coding 版本通常勝過 base model；base model 適合下游微調研究、直接拿來對話的場景較少。</li>
</ol>
<p>模型選擇影響能力與速度。同樣 32GB Mac 跑 Gemma 4 31B 跟 Qwen3-Coder 30B，兩個模型擅長的任務不同，速度也不同。詳見 <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>
<h2 id="拼裝組合三層的搭配範例">拼裝組合：三層的搭配範例</h2>
<p>理解三層後，本地 LLM 的所有「組合」都變得簡單。下表是幾個常見組合：</p>
<table>
  <thead>
      <tr>
          <th>介面層</th>
          <th>伺服器層</th>
          <th>模型層</th>
          <th>用途</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>Continue.dev</td>
          <td>Ollama</td>
          <td>Gemma 4 31B MTP</td>
          <td>VS Code 寫 code 主力</td>
      </tr>
      <tr>
          <td>Continue.dev</td>
          <td>LM Studio</td>
          <td>Qwen3-Coder 30B</td>
          <td>LM Studio 派的 VS Code 整合</td>
      </tr>
      <tr>
          <td>aider</td>
          <td>Ollama</td>
          <td>Qwen3-Coder 30B</td>
          <td>CLI 寫 code、git-aware</td>
      </tr>
      <tr>
          <td>Open WebUI</td>
          <td>Ollama</td>
          <td>Gemma 4 31B</td>
          <td>類 ChatGPT 網頁、團隊共用</td>
      </tr>
      <tr>
          <td>Ollama CLI</td>
          <td>Ollama</td>
          <td>Llama 3.3 70B Q3</td>
          <td>終端機直接對話、極限模型壓榨</td>
      </tr>
      <tr>
          <td>LM Studio UI</td>
          <td>LM Studio</td>
          <td>任意</td>
          <td>純探索新模型、GUI 派</td>
      </tr>
  </tbody>
</table>
<p>表格中的規格欄位（量化等級、<code>gemma4:31b-coding-mtp-bf16</code> 這類 model tag、Q3 等）含義見 <a href="/blog/llm/00-foundations/hardware-memory-budget/" data-link-title="0.5 Apple Silicon 記憶體預算" data-link-desc="記憶體決定能跑什麼，Q4 量化下的可運作模型對照與系統保留">0.5 記憶體預算</a> 與 <a href="/blog/llm/01-local-llm-services/ollama/#model-tag-%e5%91%bd%e5%90%8d%e8%a6%8f%e5%89%87" data-link-title="1.0 Ollama：主流推論伺服器" data-link-desc="一行 brew 裝完、ollama run 一鍵跑 Gemma 4 MTP、OpenAI 相容 API on localhost:11434">Ollama model tag 命名規則</a>。</p>
<p>注意三件事：</p>
<ol>
<li>介面跟伺服器之間用 HTTP API 通訊，所以介面層可以同時連多個伺服器，或一個伺服器服務多個介面層。</li>
<li>同一個介面（如 Continue.dev）可以同時設定本地 Ollama 跟雲端 OpenAI，根據任務切換。</li>
<li>LM Studio 自己同時是介面 + 伺服器，所以表上有兩列；但它的伺服器部分也可以對外 expose，讓其他介面（如 Continue.dev）連進來。</li>
</ol>
<h2 id="雲端對應關係建立熟悉感橋接">雲端對應關係：建立熟悉感橋接</h2>
<p>下表把本地三層對應到雲端世界，幫助建立直覺：</p>
<table>
  <thead>
      <tr>
          <th>本地</th>
          <th>雲端對應</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>Continue.dev</td>
          <td>Cursor</td>
      </tr>
      <tr>
          <td>Open WebUI</td>
          <td>ChatGPT 網頁</td>
      </tr>
      <tr>
          <td>Ollama / LM Studio (server 部分)</td>
          <td>OpenAI / Anthropic 後端服務</td>
      </tr>
      <tr>
          <td>Ollama API on localhost:11434</td>
          <td>api.openai.com</td>
      </tr>
      <tr>
          <td>Gemma 4 31B</td>
          <td>GPT-5、Claude Sonnet 4.6</td>
      </tr>
      <tr>
          <td><code>gemma4:31b-coding-mtp-bf16</code>（模型 tag）</td>
          <td><code>gpt-5</code>、<code>claude-sonnet-4-6</code>（API model name）</td>
      </tr>
  </tbody>
</table>
<p>這個對應的關鍵啟示是：<strong>Cursor 跟 Continue.dev 都是介面層</strong>、差別在於 Cursor 預設綁雲端、Continue.dev 預設綁本地、但兩者的責任邊界一樣。換句話說、要在 VS Code 裡接本地 LLM、不需要尋找專屬「本地版的 Cursor」、找一個能設定 OpenAI 相容 endpoint 的介面層就好。</p>
<h2 id="分層失效徵兆什麼時候三層心智模型會失準">分層失效徵兆：什麼時候三層心智模型會失準</h2>
<p>三層架構是教學用的乾淨模型、實務上有幾類工具會跨層或讓邊界模糊、判讀時要對應調整：</p>
<ol>
<li><strong>同層耦合（介面 + 伺服器綁死）</strong>：LM Studio 的 GUI 跟內建 server 同屬一個 app、關掉 LM Studio 視窗 server 就停。這類工具用起來方便、但失去「介面換、伺服器留」的彈性、想常駐 server 時建議改用 <a href="/blog/llm/01-local-llm-services/ollama/#%e8%83%8c%e6%99%af%e5%b8%b8%e9%a7%90launchd-service" data-link-title="1.0 Ollama：主流推論伺服器" data-link-desc="一行 brew 裝完、ollama run 一鍵跑 Gemma 4 MTP、OpenAI 相容 API on localhost:11434">Ollama 的 launchd service 模式</a>。</li>
<li><strong>伺服器內嵌引擎（責任邊界模糊）</strong>：Ollama 內部用 llama.cpp 當推論引擎、但對使用者展現的是 Ollama API 跟 model tag。看到「Ollama 不支援某個 llama.cpp 新功能」時、要回到 Ollama 的 release notes 看版本 cherry-pick 狀態、不是看 llama.cpp 上游。</li>
<li><strong>All-in-one 工具淡化分層</strong>：Open WebUI 把介面、user 管理、RAG pipeline 都包進一個 Docker container、看起來像「裝完就能用」、但底層仍要連到一個伺服器層（Ollama / OpenAI）。判讀此類工具時、先問「它的 server 是內建還是外接」、就能放回正確的分層。</li>
<li><strong>「Cursor 是本地工具嗎」常見誤判</strong>：Cursor 是介面層、它連的是雲端伺服器層、跑的是雲端模型 — 不是本地工具。對應到本地的是 Continue.dev + Ollama + 本地模型的組合。</li>
</ol>
<p>判讀新工具的反射動作：先把它拆成三層（這工具負責介面 / 伺服器 / 模型 的哪一段？）、再問「它做了多少跨層耦合、影響什麼彈性」。</p>
<h2 id="下一章">下一章</h2>
<p>下一章：<a href="/blog/llm/00-foundations/openai-compatible-api/" data-link-title="0.3 OpenAI 相容 API" data-link-desc="為什麼幾乎所有本地 LLM 工具不用改就能切到本地：背後是同一套 API 形狀">0.3 OpenAI 相容 API</a>，解釋為什麼三層之間能自由組合，背後是同一套 API 形狀。</p>
]]></content:encoded></item><item><title>0.3 OpenAI 相容 API</title><link>https://tarrragon.github.io/blog/llm/00-foundations/openai-compatible-api/</link><pubDate>Mon, 11 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/llm/00-foundations/openai-compatible-api/</guid><description>&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> 是本地 LLM 生態能夠快速繁榮的關鍵基礎建設。OpenAI 在 2023 年定義的 &lt;code>POST /v1/chat/completions&lt;/code> 介面成為事實標準後，後來幾乎所有本地推論伺服器（Ollama、LM Studio、llama.cpp、vLLM、oMLX）都實作同一份 API 規格；介面層工具只要支援這個規格，就能「不改一行程式」切換本地與雲端。&lt;/p>
&lt;p>這個相容性決定了你的選擇空間。理解它的意義後，看到任何工具寫「支援 OpenAI 相容 API」時，你會知道這句話真正承諾的是什麼、不承諾的是什麼。&lt;/p>
&lt;h2 id="本章目標">本章目標&lt;/h2>
&lt;p>讀完本章後，你應該能：&lt;/p>
&lt;ol>
&lt;li>看懂 &lt;code>apiBase: http://localhost:11434/v1&lt;/code> 這類設定背後在做什麼。&lt;/li>
&lt;li>判斷一個介面層工具是否支援本地 LLM。&lt;/li>
&lt;li>知道「&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 相容&lt;/a>」承諾的範圍與邊界。&lt;/li>
&lt;li>用 curl 直接打本地 LLM 的 API 驗證它在跑。&lt;/li>
&lt;/ol>
&lt;h2 id="api-形狀的核心chat-completions">API 形狀的核心：chat completions&lt;/h2>
&lt;p>OpenAI 在 2023 年定義的 chat completions API 核心是這個請求格式：&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://api.openai.com/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;Authorization: Bearer &lt;/span>&lt;span class="nv">$OPENAI_API_KEY&lt;/span>&lt;span class="s2">&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> -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"> 4&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"> 5&lt;/span>&lt;span class="cl">&lt;span class="s1"> &amp;#34;model&amp;#34;: &amp;#34;gpt-5&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;messages&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="s1"> {&amp;#34;role&amp;#34;: &amp;#34;system&amp;#34;, &amp;#34;content&amp;#34;: &amp;#34;You are a helpful assistant.&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="s1"> {&amp;#34;role&amp;#34;: &amp;#34;user&amp;#34;, &amp;#34;content&amp;#34;: &amp;#34;寫一個 Python function 計算費氏數列&amp;#34;}
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 9&lt;/span>&lt;span class="cl">&lt;span class="s1"> ],
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">10&lt;/span>&lt;span class="cl">&lt;span class="s1"> &amp;#34;stream&amp;#34;: true
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">11&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>回應是一連串 server-sent events（SSE、伺服器把回應切成小封包陸續推給 client、而不是等整段算完才一次回）、每個 event 包含一個 token chunk。&lt;/p>
&lt;p>本地推論伺服器實作同樣的 endpoint 形狀，只是 host 換成 localhost、API key 不檢查或檢查 dummy 值：&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;: [
&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;role&amp;#34;: &amp;#34;system&amp;#34;, &amp;#34;content&amp;#34;: &amp;#34;You are a helpful assistant.&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="s1"> {&amp;#34;role&amp;#34;: &amp;#34;user&amp;#34;, &amp;#34;content&amp;#34;: &amp;#34;寫一個 Python function 計算費氏數列&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="s1"> ],
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 9&lt;/span>&lt;span class="cl">&lt;span class="s1"> &amp;#34;stream&amp;#34;: true
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">10&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;ol>
&lt;li>&lt;strong>host&lt;/strong>：從 &lt;code>api.openai.com&lt;/code> 換成 &lt;code>localhost:11434&lt;/code>。&lt;/li>
&lt;li>&lt;strong>model&lt;/strong>：從 &lt;code>gpt-5&lt;/code> 換成 &lt;code>gemma4:31b-coding-mtp-bf16&lt;/code>。&lt;/li>
&lt;li>&lt;strong>Authorization&lt;/strong>：本地通常不檢查 API key，或接受任意值。&lt;/li>
&lt;/ol>
&lt;p>請求與回應的 JSON schema 完全一樣。這就是「OpenAI 相容」的字面意義。&lt;/p>
&lt;h2 id="為什麼這個相容性這麼重要">為什麼這個相容性這麼重要&lt;/h2>
&lt;p>如果沒有 OpenAI 相容 API，每個介面層工具要支援新的伺服器就得寫專屬整合：Continue.dev 要為 Ollama 寫一份、為 LM Studio 寫一份、為 llama.cpp 寫一份、為雲端 OpenAI 寫一份、為 Anthropic 寫一份。每多一個工具就 N×M 的整合成本。&lt;/p></description><content:encoded><![CDATA[<p><a href="/blog/llm/knowledge-cards/openai-compatible-api/" data-link-title="OpenAI 相容 API" data-link-desc="本地推論伺服器跟雲端 OpenAI 共用的 API 形狀標準">OpenAI 相容 API</a> 是本地 LLM 生態能夠快速繁榮的關鍵基礎建設。OpenAI 在 2023 年定義的 <code>POST /v1/chat/completions</code> 介面成為事實標準後，後來幾乎所有本地推論伺服器（Ollama、LM Studio、llama.cpp、vLLM、oMLX）都實作同一份 API 規格；介面層工具只要支援這個規格，就能「不改一行程式」切換本地與雲端。</p>
<p>這個相容性決定了你的選擇空間。理解它的意義後，看到任何工具寫「支援 OpenAI 相容 API」時，你會知道這句話真正承諾的是什麼、不承諾的是什麼。</p>
<h2 id="本章目標">本章目標</h2>
<p>讀完本章後，你應該能：</p>
<ol>
<li>看懂 <code>apiBase: http://localhost:11434/v1</code> 這類設定背後在做什麼。</li>
<li>判斷一個介面層工具是否支援本地 LLM。</li>
<li>知道「<a href="/blog/llm/knowledge-cards/openai-compatible-api/" data-link-title="OpenAI 相容 API" data-link-desc="本地推論伺服器跟雲端 OpenAI 共用的 API 形狀標準">OpenAI 相容</a>」承諾的範圍與邊界。</li>
<li>用 curl 直接打本地 LLM 的 API 驗證它在跑。</li>
</ol>
<h2 id="api-形狀的核心chat-completions">API 形狀的核心：chat completions</h2>
<p>OpenAI 在 2023 年定義的 chat completions API 核心是這個請求格式：</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://api.openai.com/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;Authorization: Bearer </span><span class="nv">$OPENAI_API_KEY</span><span class="s2">&#34;</span> <span class="se">\
</span></span></span><span class="line"><span class="ln"> 3</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"> 4</span><span class="cl"><span class="se"></span>  -d <span class="s1">&#39;{
</span></span></span><span class="line"><span class="ln"> 5</span><span class="cl"><span class="s1">    &#34;model&#34;: &#34;gpt-5&#34;,
</span></span></span><span class="line"><span class="ln"> 6</span><span class="cl"><span class="s1">    &#34;messages&#34;: [
</span></span></span><span class="line"><span class="ln"> 7</span><span class="cl"><span class="s1">      {&#34;role&#34;: &#34;system&#34;, &#34;content&#34;: &#34;You are a helpful assistant.&#34;},
</span></span></span><span class="line"><span class="ln"> 8</span><span class="cl"><span class="s1">      {&#34;role&#34;: &#34;user&#34;, &#34;content&#34;: &#34;寫一個 Python function 計算費氏數列&#34;}
</span></span></span><span class="line"><span class="ln"> 9</span><span class="cl"><span class="s1">    ],
</span></span></span><span class="line"><span class="ln">10</span><span class="cl"><span class="s1">    &#34;stream&#34;: true
</span></span></span><span class="line"><span class="ln">11</span><span class="cl"><span class="s1">  }&#39;</span></span></span></code></pre></div><p>回應是一連串 server-sent events（SSE、伺服器把回應切成小封包陸續推給 client、而不是等整段算完才一次回）、每個 event 包含一個 token chunk。</p>
<p>本地推論伺服器實作同樣的 endpoint 形狀，只是 host 換成 localhost、API key 不檢查或檢查 dummy 值：</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;: [
</span></span></span><span class="line"><span class="ln"> 6</span><span class="cl"><span class="s1">      {&#34;role&#34;: &#34;system&#34;, &#34;content&#34;: &#34;You are a helpful assistant.&#34;},
</span></span></span><span class="line"><span class="ln"> 7</span><span class="cl"><span class="s1">      {&#34;role&#34;: &#34;user&#34;, &#34;content&#34;: &#34;寫一個 Python function 計算費氏數列&#34;}
</span></span></span><span class="line"><span class="ln"> 8</span><span class="cl"><span class="s1">    ],
</span></span></span><span class="line"><span class="ln"> 9</span><span class="cl"><span class="s1">    &#34;stream&#34;: true
</span></span></span><span class="line"><span class="ln">10</span><span class="cl"><span class="s1">  }&#39;</span></span></span></code></pre></div><p>差別只有三點：</p>
<ol>
<li><strong>host</strong>：從 <code>api.openai.com</code> 換成 <code>localhost:11434</code>。</li>
<li><strong>model</strong>：從 <code>gpt-5</code> 換成 <code>gemma4:31b-coding-mtp-bf16</code>。</li>
<li><strong>Authorization</strong>：本地通常不檢查 API key，或接受任意值。</li>
</ol>
<p>請求與回應的 JSON schema 完全一樣。這就是「OpenAI 相容」的字面意義。</p>
<h2 id="為什麼這個相容性這麼重要">為什麼這個相容性這麼重要</h2>
<p>如果沒有 OpenAI 相容 API，每個介面層工具要支援新的伺服器就得寫專屬整合：Continue.dev 要為 Ollama 寫一份、為 LM Studio 寫一份、為 llama.cpp 寫一份、為雲端 OpenAI 寫一份、為 Anthropic 寫一份。每多一個工具就 N×M 的整合成本。</p>
<p>OpenAI 相容把這個成本拆成「<a href="/blog/llm/00-foundations/three-layer-architecture/" data-link-title="0.2 介面 / 伺服器 / 模型三層架構" data-link-desc="把任何本地 LLM 工具放回正確的層級，用三層心智模型看懂工具關係">介面層</a>支援標準 API 一次 + <a href="/blog/llm/knowledge-cards/inference-server/" data-link-title="Inference Server" data-link-desc="載入模型權重、處理 prompt、產生 token 的常駐 process">伺服器層</a>實作標準 API 一次」、整合工作從 N×M 降到 N+M。後果是新伺服器（如 2024 年才出現的 oMLX）只要實作這份 API、馬上能被既有的所有介面層用上。</p>
<p>這也是為什麼幾乎所有 IDE plugin、CLI 工具、Web UI 都選擇 OpenAI 相容做 first-class citizen。Anthropic 自己的 API 形狀（messages、不同 streaming 格式）反而成為次要選項，介面層工具通常要為 Anthropic 寫額外的 adapter。</p>
<h2 id="接本地-llm-的最小設定">接本地 LLM 的最小設定</h2>
<p>實際使用上，把任一個介面層工具切到本地 LLM 通常只要改三個欄位：</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>任意字串，常用 <code>ollama</code> 或 <code>not-needed</code></td>
      </tr>
      <tr>
          <td>Model name</td>
          <td><code>gpt-5</code>、<code>gpt-4o</code></td>
          <td>Ollama 本地的 model tag，如 <code>gemma4:31b</code></td>
      </tr>
  </tbody>
</table>
<p>三個欄位的延伸判讀：API base 改成 <a href="/blog/llm/knowledge-cards/port-and-localhost/" data-link-title="Port 與 Localhost" data-link-desc="TCP port 與 listen address 如何決定 API server 的對外暴露範圍"><code>localhost:11434</code></a> 表示請求送到本機 11434 port、不走網路；API key 本地通常不檢查、但介面層工具可能仍要求填一個值才能初始化；Model name 要去伺服器看當前已下載的 <a href="/blog/llm/knowledge-cards/model-tag/" data-link-title="Model Tag" data-link-desc="Ollama 等推論伺服器用來定位特定模型版本的命名規則">model tag</a>、Ollama 用 <code>ollama list</code> 查、LM Studio 在 Discover 分頁查。</p>
<p>接近真實的例子是 Continue.dev 的 <code>config.json</code>：</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-json" data-lang="json"><span class="line"><span class="ln"> 1</span><span class="cl"><span class="p">{</span>
</span></span><span class="line"><span class="ln"> 2</span><span class="cl">  <span class="nt">&#34;models&#34;</span><span class="p">:</span> <span class="p">[</span>
</span></span><span class="line"><span class="ln"> 3</span><span class="cl">    <span class="p">{</span>
</span></span><span class="line"><span class="ln"> 4</span><span class="cl">      <span class="nt">&#34;title&#34;</span><span class="p">:</span> <span class="s2">&#34;Gemma 4 31B (local)&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="ln"> 5</span><span class="cl">      <span class="nt">&#34;provider&#34;</span><span class="p">:</span> <span class="s2">&#34;ollama&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="ln"> 6</span><span class="cl">      <span class="nt">&#34;model&#34;</span><span class="p">:</span> <span class="s2">&#34;gemma4:31b-coding-mtp-bf16&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="ln"> 7</span><span class="cl">      <span class="nt">&#34;apiBase&#34;</span><span class="p">:</span> <span class="s2">&#34;http://localhost:11434&#34;</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><span class="line"><span class="ln">10</span><span class="cl"><span class="p">}</span></span></span></code></pre></div><p>Continue.dev 內部會把 <code>provider: ollama</code> 翻成 OpenAI 相容請求送到 <code>apiBase</code>。如果你想用通用 OpenAI provider：</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-json" data-lang="json"><span class="line"><span class="ln"> 1</span><span class="cl"><span class="p">{</span>
</span></span><span class="line"><span class="ln"> 2</span><span class="cl">  <span class="nt">&#34;models&#34;</span><span class="p">:</span> <span class="p">[</span>
</span></span><span class="line"><span class="ln"> 3</span><span class="cl">    <span class="p">{</span>
</span></span><span class="line"><span class="ln"> 4</span><span class="cl">      <span class="nt">&#34;title&#34;</span><span class="p">:</span> <span class="s2">&#34;Local LLM (via OpenAI-compatible)&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="ln"> 5</span><span class="cl">      <span class="nt">&#34;provider&#34;</span><span class="p">:</span> <span class="s2">&#34;openai&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="ln"> 6</span><span class="cl">      <span class="nt">&#34;model&#34;</span><span class="p">:</span> <span class="s2">&#34;gemma4:31b-coding-mtp-bf16&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="ln"> 7</span><span class="cl">      <span class="nt">&#34;apiBase&#34;</span><span class="p">:</span> <span class="s2">&#34;http://localhost:11434/v1&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="ln"> 8</span><span class="cl">      <span class="nt">&#34;apiKey&#34;</span><span class="p">:</span> <span class="s2">&#34;not-needed&#34;</span>
</span></span><span class="line"><span class="ln"> 9</span><span class="cl">    <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="p">}</span></span></span></code></pre></div><p>兩種寫法都會工作。<code>provider: ollama</code> 多一些 Ollama 特有功能（如 model auto-pull），<code>provider: openai</code> 比較通用、可以接任何 OpenAI 相容伺服器。</p>
<h2 id="openai-相容承諾什麼不承諾什麼">「OpenAI 相容」承諾什麼、不承諾什麼</h2>
<p>相容承諾的是 <strong>API 形狀</strong> —— request schema、response schema、streaming 格式、錯誤碼大致一致。不承諾的是：</p>
<ol>
<li><strong>模型能力</strong>：本地 Gemma 4 31B 跟雲端 GPT-5 都能用同一套 API 呼叫，但回答品質天差地遠。</li>
<li><strong>效能特性</strong>：本地的 TTFT、生字速度跟雲端完全不同，介面層感覺不到差別不代表速度一樣。</li>
<li><strong>進階參數</strong>：OpenAI 自己的新功能（function calling 進階模式、structured output 強制 JSON 輸出、reasoning effort 控制推理深度等）不一定被本地伺服器完整支援。寫 code 場景常見問題是設定了 <code>tools</code> 參數但本地模型不會主動呼叫。模組四會展開這些進階特性、見 <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>。</li>
<li><strong>模型清單</strong>：呼叫 <code>GET /v1/models</code> 回的清單、本地是你已下載的模型、雲端是 OpenAI 提供的模型；介面層要把兩邊清單視為各自獨立的資料。</li>
</ol>
<p>接近真實的意外事件：</p>
<ul>
<li>設定 <code>response_format: { type: &quot;json_object&quot; }</code> 強制 JSON 輸出，本地某些舊模型不認，會直接回普通文字。</li>
<li>設定 <code>tool_choice: &quot;required&quot;</code> 強制使用工具，本地許多模型不支援，行為退化成普通對話。</li>
<li>設定 <code>seed</code> 想拿確定性輸出，本地伺服器多半實作了，但雲端 OpenAI 並不保證每個 model 都尊重。</li>
</ul>
<p>陷阱是把「相容」當成「等價」。在依賴進階參數的場景下、寫程式時值得先假設本地伺服器可能不支援最新功能、預先準備降級處理（例如先試 <code>tool_choice: &quot;required&quot;</code>、伺服器忽略時 fallback 到 prompt-based 工具呼叫）。</p>
<h2 id="用-curl-驗證本地-llm-在跑">用 curl 驗證本地 LLM 在跑</h2>
<p>啟動 Ollama 並 pull 一個模型後，最快確認它在跑的方式是直接 curl：</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:e4b&#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;Say hi in three languages.&#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>如果回的是 JSON 包含 <code>choices[0].message.content</code>，伺服器層正常。介面層連不上的時候，先用這個 curl 確認問題是介面層、伺服器層，還是模型本身。</p>
<p>需要驗證 streaming：</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:e4b&#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;Count from 1 to 5.&#34;}],
</span></span></span><span class="line"><span class="ln">6</span><span class="cl"><span class="s1">    &#34;stream&#34;: true
</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>正常應該看到一連串 <code>data: {...}</code> 行，每行是一個 token chunk。</p>
<h2 id="多伺服器並存同時跑-ollama-與-lm-studio">多伺服器並存：同時跑 Ollama 與 LM Studio</h2>
<p>OpenAI 相容讓你可以同時在同一台 Mac 上跑多個伺服器，只要 port 不撞。常見配置：</p>
<table>
  <thead>
      <tr>
          <th>伺服器</th>
          <th>預設 port</th>
          <th>用途</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>Ollama</td>
          <td>11434</td>
          <td>日常寫 code 主力</td>
      </tr>
      <tr>
          <td>LM Studio</td>
          <td>1234</td>
          <td>探索新模型、不影響主 server</td>
      </tr>
      <tr>
          <td>llama.cpp</td>
          <td>8080</td>
          <td>進階測試、特殊量化</td>
      </tr>
      <tr>
          <td>oMLX</td>
          <td>8000</td>
          <td>長 context coding agent 場景</td>
      </tr>
  </tbody>
</table>
<p>Port 衝突的徵兆是啟動伺服器時報 <code>address already in use</code>。用 <code>lsof -i :&lt;port&gt;</code> 找佔用方、確認是舊版伺服器就 <code>pkill -f</code> 終止、或改用其他 port 啟動。詳細的 port 與 listen address 判讀見 <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> 卡片。</p>
<p>Continue.dev 的 <code>config.json</code> 可以同時列多個 model、每個 model 指向不同伺服器、UI 上下拉切換。這個能力讓「主力模型穩定跑、實驗模型隔離測試」變得直接。</p>
<h2 id="不是-openai-相容的本地工具">不是 OpenAI 相容的本地工具</h2>
<p>少數本地工具不走 OpenAI 相容，要特別注意：</p>
<ol>
<li><strong><a href="/blog/llm/knowledge-cards/mlx/" data-link-title="MLX" data-link-desc="Apple 釋出的 Apple Silicon 數值運算 framework：類似 PyTorch / JAX 的 Mac 對應物">MLX</a> 原生 Python API</strong>：Apple 的 MLX framework 本身是 Python library、不是 HTTP server。需要自己 wrap 或用 <code>mlx_lm.server</code>（次要產品、功能不全）。完整的 MLX / MTP / oMLX 區別見 <a href="/blog/llm/00-foundations/mlx-mtp-omlx/" data-link-title="0.4 MLX / MTP / oMLX 的區別" data-link-desc="三個常被混為一談的術語：framework、加速技巧、特化 server，疊加而非互斥">0.4 章節</a>。</li>
<li><strong>早期 llama.cpp</strong>：在 OpenAI 相容前就存在，原生 API 形狀不同；新版加上 <code>/v1/chat/completions</code> 後跟主流相容。</li>
<li><strong>某些研究專案</strong>：直接 wrap PyTorch / Transformers，沒有 HTTP 層，要當 library 用。</li>
</ol>
<p>遇到這類工具時、值得先評估「該不該為它寫 adapter」。判讀訊號：模型唯一性（這個工具是否提供其他伺服器拿不到的模型？）vs 整合成本（寫 adapter 與長期維護的時間投入）。模型唯一性高時值得投資、模型可在主流伺服器找到替代時、選 OpenAI 相容的主流伺服器（Ollama、LM Studio）能省下大量整合成本。</p>
<h2 id="下一章">下一章</h2>
<p>下一章：<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>，澄清三個常被混為一談的術語，避開網路上最常見的本地 LLM 認知陷阱。</p>
]]></content:encoded></item><item><title>0.4 MLX / MTP / oMLX 的區別</title><link>https://tarrragon.github.io/blog/llm/00-foundations/mlx-mtp-omlx/</link><pubDate>Mon, 11 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/llm/00-foundations/mlx-mtp-omlx/</guid><description>&lt;p>MLX、MTP、oMLX 是本地 LLM 生態中最容易被網路文章混為一談的三個術語。它們分別屬於不同的技術層級：MLX 是 Apple 自家的數值運算 framework，MTP 是一種加速技巧，oMLX 是一個建在 MLX 上的特化推論伺服器。三者&lt;strong>疊加而非互斥&lt;/strong>，可以同時存在於一套堆疊裡。&lt;/p>
&lt;p>把這三個分清楚後，看到「MLX 加速 50%」「MTP 整合到 llama.cpp」「oMLX 用上 MTP」這類句子就能精準判讀。本章的責任是把每個術語放回正確的位置，再說明它們如何疊加。&lt;/p>
&lt;h2 id="本章目標">本章目標&lt;/h2>
&lt;p>讀完本章後，你應該能：&lt;/p>
&lt;ol>
&lt;li>用一句話分別說清楚 MLX、MTP、oMLX 是什麼。&lt;/li>
&lt;li>看懂「MLX backend」「啟用 MTP」「用 oMLX 跑」這些句子。&lt;/li>
&lt;li>判斷三者組合的可行性與效果。&lt;/li>
&lt;li>避開把它們當成競爭關係的常見誤解。&lt;/li>
&lt;/ol>
&lt;h2 id="mlxapple-的數值運算-framework">MLX：Apple 的數值運算 framework&lt;/h2>
&lt;p>&lt;strong>MLX&lt;/strong> 是 Apple 為 Apple Silicon 設計的數值運算 framework、類似 PyTorch 或 JAX 在 Mac 上的對應物（全名 Machine Learning eXchange、2023 年釋出）。它的責任是：&lt;/p>
&lt;ol>
&lt;li>在 CPU、GPU、Neural Engine 之間自動排程運算。&lt;/li>
&lt;li>利用統一記憶體（UMA）避免在記憶體層級之間搬資料。&lt;/li>
&lt;li>提供 lazy evaluation（延遲計算、把運算累積成圖再一次優化執行）與 graph optimization（自動合併多個運算、減少記憶體 round-trip）、讓相同的 Python 程式碼在 M1 ~ M4 上都能用上各代硬體優勢。&lt;/li>
&lt;li>提供 &lt;code>mlx.core&lt;/code>、&lt;code>mlx.nn&lt;/code> 等 Python API、可以寫訓練 / 推論程式。&lt;/li>
&lt;/ol>
&lt;p>MLX 的角色就是「跑神經網路用的底層數值庫」、把 server / 模型 / 加速技巧三個責任都留給上層工具去做。可以類比：&lt;/p>
&lt;table>
 &lt;thead>
 &lt;tr>
 &lt;th>主流生態&lt;/th>
 &lt;th>Apple Silicon 對應&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>Hugging Face 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;p>MLX 的角色定位是「basic infrastructure」。要拿 MLX 跑 LLM，你需要：MLX framework + 一份用 MLX 寫的模型實作（如 &lt;code>mlx-lm&lt;/code> package）+ 模型權重（MLX format）+ 一個介面（CLI 或 server wrapper）。所有上層工具都站在 MLX 這塊地基上。&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">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 格式的模型權重、用 MLX framework 在 Apple Silicon 上跑推論。但這只是 library 等級的呼叫、不是常駐伺服器；要做成 server 還需要再 wrap 一層（例如 &lt;code>mlx_lm.server&lt;/code> 或 oMLX）。&lt;/p>
&lt;h3 id="常見-mlx-誤用">常見 MLX 誤用&lt;/h3>
&lt;ol>
&lt;li>&lt;strong>以為裝 MLX 就有 server&lt;/strong>：MLX 只是 library、要 expose HTTP API 需要再 wrap 一層（&lt;code>mlx_lm.server&lt;/code>、oMLX、或自己用 FastAPI 包）。&lt;/li>
&lt;li>&lt;strong>以為 MLX 跟 Metal 互斥&lt;/strong>：MLX 跑在 GPU 上會自動用 Metal、兩者是上下層關係、不是擇一。Metal 是 Apple 的 GPU 加速 API、MLX 是利用 Metal 的高階 framework。&lt;/li>
&lt;li>&lt;strong>以為 Ollama 用 MLX backend&lt;/strong>：Ollama 內部用 &lt;a href="https://tarrragon.github.io/blog/llm/01-local-llm-services/llama-cpp/" data-link-title="1.2 llama.cpp：底層推論引擎" data-link-desc="GGUF 格式、量化、MTP 仍 beta；多數讀者不需要直接接觸，Ollama 已經包好">llama.cpp&lt;/a> 配 Metal、跟 MLX 沒關係。看到「Ollama 用 MLX 加速」要追問來源、多半是混淆。&lt;/li>
&lt;/ol>
&lt;h2 id="mtp一種加速技巧">MTP：一種加速技巧&lt;/h2>
&lt;p>&lt;strong>Multi-Token Prediction&lt;/strong>（MTP）的核心是「一次預測多個 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;/p></description><content:encoded><![CDATA[<p>MLX、MTP、oMLX 是本地 LLM 生態中最容易被網路文章混為一談的三個術語。它們分別屬於不同的技術層級：MLX 是 Apple 自家的數值運算 framework，MTP 是一種加速技巧，oMLX 是一個建在 MLX 上的特化推論伺服器。三者<strong>疊加而非互斥</strong>，可以同時存在於一套堆疊裡。</p>
<p>把這三個分清楚後，看到「MLX 加速 50%」「MTP 整合到 llama.cpp」「oMLX 用上 MTP」這類句子就能精準判讀。本章的責任是把每個術語放回正確的位置，再說明它們如何疊加。</p>
<h2 id="本章目標">本章目標</h2>
<p>讀完本章後，你應該能：</p>
<ol>
<li>用一句話分別說清楚 MLX、MTP、oMLX 是什麼。</li>
<li>看懂「MLX backend」「啟用 MTP」「用 oMLX 跑」這些句子。</li>
<li>判斷三者組合的可行性與效果。</li>
<li>避開把它們當成競爭關係的常見誤解。</li>
</ol>
<h2 id="mlxapple-的數值運算-framework">MLX：Apple 的數值運算 framework</h2>
<p><strong>MLX</strong> 是 Apple 為 Apple Silicon 設計的數值運算 framework、類似 PyTorch 或 JAX 在 Mac 上的對應物（全名 Machine Learning eXchange、2023 年釋出）。它的責任是：</p>
<ol>
<li>在 CPU、GPU、Neural Engine 之間自動排程運算。</li>
<li>利用統一記憶體（UMA）避免在記憶體層級之間搬資料。</li>
<li>提供 lazy evaluation（延遲計算、把運算累積成圖再一次優化執行）與 graph optimization（自動合併多個運算、減少記憶體 round-trip）、讓相同的 Python 程式碼在 M1 ~ M4 上都能用上各代硬體優勢。</li>
<li>提供 <code>mlx.core</code>、<code>mlx.nn</code> 等 Python API、可以寫訓練 / 推論程式。</li>
</ol>
<p>MLX 的角色就是「跑神經網路用的底層數值庫」、把 server / 模型 / 加速技巧三個責任都留給上層工具去做。可以類比：</p>
<table>
  <thead>
      <tr>
          <th>主流生態</th>
          <th>Apple Silicon 對應</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>Hugging Face Transformers</td>
          <td><code>mlx-lm</code>、<code>mlx-community</code> 上的模型</td>
      </tr>
  </tbody>
</table>
<p>MLX 的角色定位是「basic infrastructure」。要拿 MLX 跑 LLM，你需要：MLX framework + 一份用 MLX 寫的模型實作（如 <code>mlx-lm</code> package）+ 模型權重（MLX format）+ 一個介面（CLI 或 server wrapper）。所有上層工具都站在 MLX 這塊地基上。</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">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 格式的模型權重、用 MLX framework 在 Apple Silicon 上跑推論。但這只是 library 等級的呼叫、不是常駐伺服器；要做成 server 還需要再 wrap 一層（例如 <code>mlx_lm.server</code> 或 oMLX）。</p>
<h3 id="常見-mlx-誤用">常見 MLX 誤用</h3>
<ol>
<li><strong>以為裝 MLX 就有 server</strong>：MLX 只是 library、要 expose HTTP API 需要再 wrap 一層（<code>mlx_lm.server</code>、oMLX、或自己用 FastAPI 包）。</li>
<li><strong>以為 MLX 跟 Metal 互斥</strong>：MLX 跑在 GPU 上會自動用 Metal、兩者是上下層關係、不是擇一。Metal 是 Apple 的 GPU 加速 API、MLX 是利用 Metal 的高階 framework。</li>
<li><strong>以為 Ollama 用 MLX backend</strong>：Ollama 內部用 <a href="/blog/llm/01-local-llm-services/llama-cpp/" data-link-title="1.2 llama.cpp：底層推論引擎" data-link-desc="GGUF 格式、量化、MTP 仍 beta；多數讀者不需要直接接觸，Ollama 已經包好">llama.cpp</a> 配 Metal、跟 MLX 沒關係。看到「Ollama 用 MLX 加速」要追問來源、多半是混淆。</li>
</ol>
<h2 id="mtp一種加速技巧">MTP：一種加速技巧</h2>
<p><strong>Multi-Token Prediction</strong>（MTP）的核心是「一次預測多個 token 的加速技巧」，本質上是 <a href="/blog/llm/knowledge-cards/speculative-decoding/" data-link-title="Speculative Decoding" data-link-desc="用小模型猜未來 token、大模型並行驗證的加速技巧">speculative decoding</a> 的工程化實作。它的責任是：</p>
<ol>
<li>用一個小模型（drafter）快速猜未來 N 個 token。</li>
<li>把這 N 個 token 一次餵給大模型（target），讓大模型並行驗證。</li>
<li>大模型保留它認同的 token 前綴，從第一個拒絕點繼續。</li>
</ol>
<p>MTP 是跑模型時的演算法層、跟伺服器與模型實作互相正交：任何推論伺服器都可以選擇實作或不實作 MTP、模型可以選擇有沒有官方 drafter、兩件事分離。</p>
<p>Google 為 Gemma 4 釋出官方 drafter 後，MTP 變成 Gemma 4 生態的標準配備。官方數據宣稱 coding 任務 2 ~ 3 倍加速；寫 code 的加速尤其明顯，因為 code 有大量可預測 pattern（縮排、括號、常見變數名），drafter 接受率高。</p>
<p>陷阱有三個：</p>
<ol>
<li><strong>MTP ≠ Gemma 4 限定</strong>。任何模型理論上都能用 speculative decoding；只是 Gemma 4 有官方 drafter、現成可用。其他模型要嘛社群自己訓 drafter，要嘛沒有。</li>
<li><strong>MTP 不一定加速所有任務</strong>。對沒有預測 pattern 的任務（如生成隨機 ID、加密文字），接受率低，反而會拖慢。寫 code 是甜蜜點。</li>
<li><strong>加速倍數受實作品質影響</strong>。網路上「MTP 加速 40%」這類來源不明數字常見；Google 官方數據是 2 ~ 3 倍，視任務而定。引用時要追到官方來源。</li>
</ol>
<p>實作層面、要用 MTP 需要：</p>
<ul>
<li>一個支援 speculative decoding 的伺服器（2026 年 5 月時 Ollama v0.23+ 已支援、LM Studio 跟 oMLX 也支援、llama.cpp 上游 speculative decoding 框架仍 beta）。</li>
<li>一個有 drafter 的模型、或自己組合 target + drafter pair。</li>
</ul>
<p>Ollama 在 2026/5/7 釋出的 v0.23.1 加入 Gemma 4 MTP 一鍵支援：</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">ollama run gemma4:31b-coding-mtp-bf16</span></span></code></pre></div><p>這個 model tag 內含 drafter，伺服器自動啟用 speculative decoding。</p>
<h2 id="omlx建在-mlx-上的特化伺服器">oMLX：建在 MLX 上的特化伺服器</h2>
<p><strong>oMLX</strong>（&ldquo;optimized MLX server&rdquo; 的縮寫，2024 年由社群釋出）的核心是「建在 MLX 之上、針對 coding agent 長 context 場景優化的推論伺服器」。它的責任是：</p>
<ol>
<li>用 MLX 當推論 backend，吃 Apple Silicon 統一記憶體優勢。</li>
<li>提供 OpenAI 相容 HTTP API。</li>
<li><strong>paged SSD KV cache</strong>：把已 prefill 過的 prompt context 存到 SSD，下次同前綴 prompt 可以直接讀 cache。</li>
<li>支援 speculative decoding 與<a href="/blog/llm/knowledge-cards/quantization/" data-link-title="Quantization" data-link-desc="用較少 bits 表示模型權重：壓縮記憶體佔用、加快生字速度，代價是少量品質衰減">量化</a>。</li>
</ol>
<p>oMLX 跟 Ollama 並列同一層（都是推論伺服器），但定位不同：</p>
<table>
  <thead>
      <tr>
          <th>維度</th>
          <th>Ollama</th>
          <th>oMLX</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>推論 backend</td>
          <td>llama.cpp</td>
          <td>MLX</td>
      </tr>
      <tr>
          <td>目標場景</td>
          <td>通用本地 LLM</td>
          <td>coding agent 長 context</td>
      </tr>
      <tr>
          <td>KV cache 策略</td>
          <td>記憶體內，session 結束就丟</td>
          <td>paged SSD，跨 session 復用</td>
      </tr>
      <tr>
          <td>安裝難度</td>
          <td>一行 brew</td>
          <td>較高，要設 Python 環境</td>
      </tr>
      <tr>
          <td>對 TTFT 的優化</td>
          <td>一般</td>
          <td>主打：30 ~ 90 秒降到 1 ~ 3 秒</td>
      </tr>
      <tr>
          <td>生態成熟度</td>
          <td>高，大量 model tag</td>
          <td>較新，模型支援要自己轉</td>
      </tr>
  </tbody>
</table>
<p>oMLX 解的是 <a href="/blog/llm/00-foundations/why-llm-feels-slow/" data-link-title="0.1 為什麼 LLM 生字慢" data-link-desc="自回歸架構與記憶體頻寬瓶頸：為何即使 Mac 算力很強，本地 LLM 仍一個字一個字吐">0.1 為什麼 LLM 生字慢</a> 提到的痛點：當你用 aider 或 Cline 這類 <a href="/blog/llm/04-applications/agent-architecture/" data-link-title="4.4 Agent 架構原理" data-link-desc="Agent loop 結構、失敗模式、什麼任務適合 vs 不適合、跟人類審查的協作模型">coding agent</a>（用 LLM 自動操作 git / 檔案的 CLI 工具、模組四會展開）、把整個 repo 塞進 prompt 時、本地 LLM 每次都要重新 <a href="/blog/llm/knowledge-cards/prefill/" data-link-title="Prefill" data-link-desc="Prompt 首次處理時的計算階段：把整段輸入跑過模型、產生 KV cache">prefill</a> 10K+ tokens、等 30 ~ 90 秒。oMLX 的 SSD cache 把同前綴 prompt 的 prefill 結果保存下來、下次只 prefill「新增的部分」、TTFT 從幾十秒降到幾秒。</p>
<p>陷阱是把 oMLX 當成「比 Ollama 強的替代品」。它解的是非常特定的痛點；短 prompt code completion 或一般對話場景下、Ollama 的 TTFT 痛點不浮現、oMLX 的 SSD cache 賣點換不到體感、卻要先承擔較高的安裝與維護成本。長 context coding agent 才是 oMLX 的甜蜜點。</p>
<h2 id="三者疊加實際堆疊長什麼樣">三者疊加：實際堆疊長什麼樣</h2>
<p>三者不是競爭關係，是堆疊關係。下表是幾種常見組合：</p>
<table>
  <thead>
      <tr>
          <th>組合</th>
          <th>適用情境</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>MLX framework + <code>mlx-lm</code> library</td>
          <td>研究用、直接寫 Python 跑推論</td>
      </tr>
      <tr>
          <td>Ollama（用 llama.cpp 當 backend）</td>
          <td>主流選擇、跟 MLX 無關</td>
      </tr>
      <tr>
          <td>Ollama + Gemma 4 with MTP drafter</td>
          <td>主流選擇 + 加速、coding 場景 2x</td>
      </tr>
      <tr>
          <td>oMLX（用 MLX 當 backend）+ Gemma 4 MTP</td>
          <td>長 context agent 場景的完整堆疊</td>
      </tr>
      <tr>
          <td>LM Studio + Qwen3-Coder + speculative decoding</td>
          <td>GUI 派 + 加速</td>
      </tr>
  </tbody>
</table>
<p>兩個主流堆疊的延伸判讀：</p>
<ul>
<li><strong>Ollama + Gemma 4 MTP</strong>：成立條件是 Ollama 版本 ≥ v0.23.1（內建 MTP 一鍵支援）、target / drafter 同 family（都是 Gemma 4）。換成 Llama 或 Qwen 系列就要找對應的 drafter 配對、或退回沒 MTP 的版本；2026 年 5 月時 Qwen3-Coder 還沒有官方 drafter。</li>
<li><strong>oMLX + Gemma 4 MTP</strong>：成立條件是有長 context coding agent 工作流（10K+ tokens）、且 Mac 記憶體足夠同時載入 target + drafter（32GB+）。短 context 或一般對話場景、oMLX 的 SSD cache 帶不來體感優勢、改用 Ollama 配同樣 model tag 更省事。</li>
</ul>
<p>注意三件事：</p>
<ol>
<li>Ollama 預設用 llama.cpp 當 backend，跟 MLX 沒關係。看到「Ollama 用 MLX 加速」這種句子要追問來源，多半是混淆。</li>
<li>oMLX 是少數真正把 MLX 用在 server 層的工具；它的賣點不是「MLX」本身，是 SSD KV cache。</li>
<li>MTP 是技巧層，可以疊在 Ollama 或 oMLX 上面，跟伺服器選擇正交。</li>
</ol>
<h2 id="用三層定位判讀新資訊">用三層定位判讀新資訊</h2>
<p>三層定位的用法是「把每則資訊放回 framework / server / 技巧層、再追問該層的證據」。社群文章在描述這三者時常會混用層級、用這個流程可以快速還原它真正在說什麼。下面是幾個常見句子、加上三層定位重新解析的版本：</p>
<p><strong>「llama.cpp 已整合 Gemma 4 MTP」</strong>：要追問版本與時間點。2026 年 5 月時 llama.cpp 上游的 speculative decoding 框架仍 beta、Gemma 4 官方 drafter 整合是 feature request；Ollama 反而在 v0.23.1（2026/5/7）一鍵支援、是少見的「Ollama 領先底層 llama.cpp」情境。Ollama 維護自己的 fork、有時搶先加 patch。</p>
<p><strong>「MTP 加速 40%」</strong>：要追問任務與基準。Google 官方數據是 coding 任務 2 ~ 3 倍、其他任務 1.5 ~ 2 倍。「40%」這類數字若沒附上任務、硬體、比較基準、判讀價值有限。回到 Google Gemma 4 技術報告比對原始三變數。</p>
<p><strong>「Ollama 用 MLX 比 llama.cpp 快」</strong>：混淆了 framework 層與 server 層。Ollama 內部用 llama.cpp（library 層）當推論引擎、配 Metal backend 接 Apple Silicon GPU。它跟 MLX 是平行的選擇、不是包含關係。想用 MLX 當 backend 要選 oMLX 或自己 wrap mlx-lm。</p>
<p><strong>「oMLX 是 Ollama 的 MLX 版本」</strong>：兩者沒有 fork 關係。oMLX 的主要創新是 paged SSD KV cache、解的是長 <a href="/blog/llm/knowledge-cards/context-window/" data-link-title="Context Window" data-link-desc="模型一次能處理的最大 token 數量：prompt 加生成的總和上限">context window</a> coding agent 的 <a href="/blog/llm/knowledge-cards/ttft/" data-link-title="TTFT" data-link-desc="Time To First Token：送出 prompt 到第一個 token 出現的等待時間">TTFT</a> 痛點。「換 backend 到 MLX」是另一回事、不是 oMLX 的賣點。</p>
<p><strong>「裝 MLX 就能跑 LLM」</strong>：<a href="/blog/llm/knowledge-cards/mlx/" data-link-title="MLX" data-link-desc="Apple 釋出的 Apple Silicon 數值運算 framework：類似 PyTorch / JAX 的 Mac 對應物">MLX</a> 只是 framework。實際要跑 LLM 還需要模型實作（<code>mlx-lm</code>）+ 模型權重（MLX format）+ 介面（CLI 或 server wrapper）。對寫 code 場景的多數使用者、直接用 Ollama 反而更直接、不用接觸 MLX 細節。</p>
<p>詳細的判讀框架見 <a href="/blog/llm/00-foundations/info-judgment-frames/" data-link-title="0.6 判讀本地 LLM 資訊的五個框架" data-link-desc="本地 LLM 資訊更新快，學會用版本、層級、變數、能力、資料流五個框架評估文章與宣稱">0.6 判讀本地 LLM 資訊的五個框架</a>；其中框架一（追溯版本與時間點）、框架二（量化宣稱三變數）、框架三（工具放回三層架構）對本章三個術語的混淆特別有用。</p>
<h2 id="給讀者的選擇順序">給讀者的選擇順序</h2>
<p>寫 code 場景的優先順序：</p>
<ol>
<li><strong>先裝 Ollama</strong>、跑 Gemma 4 31B MTP 或 Qwen3-Coder 30B。MTP 加速包含在 Ollama v0.23.1 內、開箱即用。</li>
<li><strong>用一週後</strong>若發現 TTFT 在塞長 context 時體感痛、再評估 oMLX。</li>
<li><strong>MLX 本身</strong>對寫 code 使用者是抽象層下面的事、多數場景由 Ollama 把 MLX 細節包起來；直接接觸 MLX 的時機是想自己 wrap library 或調試底層 framework。</li>
</ol>
<p>順序設計的核心是「先解決日常路徑、再針對痛點做特化」。先鑽 MLX 細節或安裝 oMLX、會在還沒驗證痛點存在時就承擔額外的學習與維護成本。</p>
<h2 id="下一章">下一章</h2>
<p>下一章：<a href="/blog/llm/00-foundations/hardware-memory-budget/" data-link-title="0.5 Apple Silicon 記憶體預算" data-link-desc="記憶體決定能跑什麼，Q4 量化下的可運作模型對照與系統保留">0.5 Apple Silicon 記憶體預算</a>、把心智模型對到自己 Mac 的真實規格。</p>
]]></content:encoded></item><item><title>0.5 Apple Silicon 記憶體預算</title><link>https://tarrragon.github.io/blog/llm/00-foundations/hardware-memory-budget/</link><pubDate>Mon, 11 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/llm/00-foundations/hardware-memory-budget/</guid><description>&lt;p>本章只處理 Apple Silicon Mac 的場景。Mac 是「&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>」架構、CPU 跟 GPU 共用同一塊 RAM、所以判讀模型是「一塊預算切系統 / 模型 / KV cache」。Windows / Linux + 獨立 GPU 是「VRAM + 系統 RAM」兩塊分層預算、判讀模型本質不同、見 &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>
&lt;p>Apple Silicon Mac 跑本地 LLM 的核心限制是&lt;strong>記憶體大小&lt;/strong>、而非 CPU 或 GPU 算力。記憶體決定能載入多大的模型；模型載得進、推論才有得跑（生字速度則由 &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/00-foundations/why-llm-feels-slow/" data-link-title="0.1 為什麼 LLM 生字慢" data-link-desc="自回歸架構與記憶體頻寬瓶頸：為何即使 Mac 算力很強，本地 LLM 仍一個字一個字吐">0.1&lt;/a>）。本章把「24GB 能跑 70B」這類含糊說法、換成可操作的記憶體預算判讀。&lt;/p>
&lt;p>讀完本章後，你可以對自己這台 Mac 直接回答：能跑哪些模型、要用什麼量化、要留多少給系統、風扇會不會狂轉、什麼時候該升級。&lt;/p>
&lt;h2 id="本章目標">本章目標&lt;/h2>
&lt;p>讀完本章後，你應該能：&lt;/p>
&lt;ol>
&lt;li>看 Mac 規格立刻知道能跑哪一級的模型。&lt;/li>
&lt;li>理解量化等級跟模型大小的乘積為何決定可行性。&lt;/li>
&lt;li>為「給系統留多少記憶體」這件事設一個合理上界。&lt;/li>
&lt;li>判斷自己這台 Mac 適不適合跑本地 LLM。&lt;/li>
&lt;/ol>
&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">總記憶體 = 系統與其他 app（保留）+ 模型權重 + KV cache + 推論中間結果&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>各塊的估算原則：&lt;/p>
&lt;ol>
&lt;li>&lt;strong>系統與其他 app&lt;/strong>：至少留 8GB 給 macOS、VS Code、瀏覽器與其他工作流程。重度多工建議留 10 ~ 12GB。&lt;/li>
&lt;li>&lt;strong>模型權重&lt;/strong>：用「參數規模 × 每權重 bits / 8」算出 bytes。其中「Q4」代表&lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/quantization/" data-link-title="Quantization" data-link-desc="用較少 bits 表示模型權重：壓縮記憶體佔用、加快生字速度，代價是少量品質衰減">每個權重佔 4 bits&lt;/a>。例如 31B 模型 Q4 量化 = 31 × 4 / 8 = 15.5 GB、加上 metadata 與 overhead 約 16 ~ 18GB。&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>：跟 &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> 長度成正比。短 context（&amp;lt; 2K tokens）約 0.5 ~ 1GB、長 context（10K+ tokens）可能超過 5GB。&lt;/li>
&lt;li>&lt;strong>推論中間結果&lt;/strong>：通常 1 ~ 2GB。&lt;/li>
&lt;/ol>
&lt;p>實際留給模型的可用記憶體 = 總記憶體 − 系統保留（8GB）− KV cache（2 ~ 5GB）− 推論 overhead（2GB）。&lt;/p>
&lt;h2 id="mac-記憶體與可運作模型對照">Mac 記憶體與可運作模型對照&lt;/h2>
&lt;p>下表是 2026 年 5 月、Apple Silicon Mac 在 Q4 量化下的可運作模型對照。預設 Q4 是因為它是 31B 等級寫 code 場景的甜蜜點、下節「為什麼 32GB 是寫 code 場景的甜蜜點」會展開原因。所有體感標籤都假設「主要用途是寫 code」、純文字對話的甜蜜點會往較小模型偏。&lt;/p></description><content:encoded><![CDATA[<p>本章只處理 Apple Silicon Mac 的場景。Mac 是「<a href="/blog/llm/knowledge-cards/unified-memory/" data-link-title="Unified Memory Architecture" data-link-desc="Apple Silicon 讓 CPU / GPU / NE 共用同一塊記憶體：跑大模型的優勢來源">統一記憶體</a>」架構、CPU 跟 GPU 共用同一塊 RAM、所以判讀模型是「一塊預算切系統 / 模型 / KV cache」。Windows / Linux + 獨立 GPU 是「VRAM + 系統 RAM」兩塊分層預算、判讀模型本質不同、見 <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>
<p>Apple Silicon Mac 跑本地 LLM 的核心限制是<strong>記憶體大小</strong>、而非 CPU 或 GPU 算力。記憶體決定能載入多大的模型；模型載得進、推論才有得跑（生字速度則由 <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/00-foundations/why-llm-feels-slow/" data-link-title="0.1 為什麼 LLM 生字慢" data-link-desc="自回歸架構與記憶體頻寬瓶頸：為何即使 Mac 算力很強，本地 LLM 仍一個字一個字吐">0.1</a>）。本章把「24GB 能跑 70B」這類含糊說法、換成可操作的記憶體預算判讀。</p>
<p>讀完本章後，你可以對自己這台 Mac 直接回答：能跑哪些模型、要用什麼量化、要留多少給系統、風扇會不會狂轉、什麼時候該升級。</p>
<h2 id="本章目標">本章目標</h2>
<p>讀完本章後，你應該能：</p>
<ol>
<li>看 Mac 規格立刻知道能跑哪一級的模型。</li>
<li>理解量化等級跟模型大小的乘積為何決定可行性。</li>
<li>為「給系統留多少記憶體」這件事設一個合理上界。</li>
<li>判斷自己這台 Mac 適不適合跑本地 LLM。</li>
</ol>
<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">總記憶體 = 系統與其他 app（保留）+ 模型權重 + KV cache + 推論中間結果</span></span></code></pre></div><p>各塊的估算原則：</p>
<ol>
<li><strong>系統與其他 app</strong>：至少留 8GB 給 macOS、VS Code、瀏覽器與其他工作流程。重度多工建議留 10 ~ 12GB。</li>
<li><strong>模型權重</strong>：用「參數規模 × 每權重 bits / 8」算出 bytes。其中「Q4」代表<a href="/blog/llm/knowledge-cards/quantization/" data-link-title="Quantization" data-link-desc="用較少 bits 表示模型權重：壓縮記憶體佔用、加快生字速度，代價是少量品質衰減">每個權重佔 4 bits</a>。例如 31B 模型 Q4 量化 = 31 × 4 / 8 = 15.5 GB、加上 metadata 與 overhead 約 16 ~ 18GB。</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>：跟 <a href="/blog/llm/knowledge-cards/context-window/" data-link-title="Context Window" data-link-desc="模型一次能處理的最大 token 數量：prompt 加生成的總和上限">context</a> 長度成正比。短 context（&lt; 2K tokens）約 0.5 ~ 1GB、長 context（10K+ tokens）可能超過 5GB。</li>
<li><strong>推論中間結果</strong>：通常 1 ~ 2GB。</li>
</ol>
<p>實際留給模型的可用記憶體 = 總記憶體 − 系統保留（8GB）− KV cache（2 ~ 5GB）− 推論 overhead（2GB）。</p>
<h2 id="mac-記憶體與可運作模型對照">Mac 記憶體與可運作模型對照</h2>
<p>下表是 2026 年 5 月、Apple Silicon Mac 在 Q4 量化下的可運作模型對照。預設 Q4 是因為它是 31B 等級寫 code 場景的甜蜜點、下節「為什麼 32GB 是寫 code 場景的甜蜜點」會展開原因。所有體感標籤都假設「主要用途是寫 code」、純文字對話的甜蜜點會往較小模型偏。</p>
<table>
  <thead>
      <tr>
          <th>Mac 記憶體</th>
          <th>留給模型</th>
          <th>能跑的最大模型</th>
          <th>體感</th>
          <th>備註</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>8GB</td>
          <td>0GB</td>
          <td>4B 以上模型互動體感失效</td>
          <td>不在本指南範圍</td>
          <td>連 4B 模型 Q4 都很勉強</td>
      </tr>
      <tr>
          <td>16GB</td>
          <td>6 ~ 8GB</td>
          <td>Gemma 4 E4B、Qwen3 7B、Llama 3.2 8B</td>
          <td>勉強</td>
          <td>同時開 VS Code 就會吃緊、常 swap</td>
      </tr>
      <tr>
          <td>24GB</td>
          <td>12 ~ 14GB</td>
          <td>Gemma 4 26B A4B（MoE、見下段）、Qwen3-Coder 14B、Llama 3.3 13B</td>
          <td>堪用</td>
          <td>多數工程師的起點</td>
      </tr>
      <tr>
          <td>32GB</td>
          <td>18 ~ 22GB</td>
          <td><strong>Gemma 4 31B（含 <a href="/blog/llm/knowledge-cards/mtp/" data-link-title="Multi-Token Prediction (MTP)" data-link-desc="Google 為 Gemma 系列釋出的 speculative decoding 工程化實作">MTP</a> drafter）甜蜜點</strong>、Qwen3-Coder 30B Q4</td>
          <td>順暢</td>
          <td>寫 code 場景最佳價格效能比</td>
      </tr>
      <tr>
          <td>48GB</td>
          <td>32 ~ 36GB</td>
          <td>Qwen3-Coder 32B Q5、Llama 3.3 70B Q3</td>
          <td>順暢</td>
          <td>開始接近 GPT-4 mini 等級</td>
      </tr>
      <tr>
          <td>64GB</td>
          <td>48 ~ 52GB</td>
          <td>Qwen3-Coder 32B bf16、Llama 3.3 70B Q4</td>
          <td>順暢</td>
          <td>大模型用較高量化、品質更好</td>
      </tr>
      <tr>
          <td>96GB+</td>
          <td>80GB+</td>
          <td>Llama 3.3 70B Q8、實驗 100B+ 模型</td>
          <td>順暢</td>
          <td>過度配置、除非有特殊需求</td>
      </tr>
  </tbody>
</table>
<p>讀這張表要注意四件事：</p>
<ol>
<li><strong>體感是 coding 場景</strong>。純對話、寫文章、解釋程式的記憶體門檻較低。</li>
<li><strong>量化等級可以調整</strong>。32GB 跑 31B Q4 順暢、跑 31B Q5 也行（吃 21GB 左右）；跑 70B Q3 會崩潰，因為 70B Q3 約 26GB，加上 KV cache 跟系統，超過 32GB。</li>
<li><strong>fanless 機種要打折</strong>。MacBook Air 系列因為散熱被動，跑大型模型 5 分鐘後會降頻，實際生字速度比有風扇的同代機器低 30 ~ 50%。</li>
<li><strong>記憶體不是 SSD</strong>。Apple Silicon 的「統一記憶體」是 RAM、不是 SSD swap。雖然 macOS 會 swap、但 swap 後生字速度會慢一個量級以上、實質喪失互動可用性。</li>
</ol>
<h2 id="moe-與-dense-模型在記憶體預算上的差異">MoE 與 dense 模型在記憶體預算上的差異</h2>
<p><a href="/blog/llm/knowledge-cards/moe-cpu-offload/" data-link-title="MoE CPU 卸載" data-link-desc="把 Mixture-of-Experts 模型不活躍的專家層權重放在系統 RAM、用到再走 PCIe 拉回 GPU、讓有限 VRAM 跑得了更大模型">Mixture of Experts（MoE）</a> 模型跟 dense 模型的記憶體 / 速度判讀方式不同、Gemma 4 26B A4B 這類 MoE 模型在上表「24GB Mac」一格出現時、容易讓人誤以為跟 14B dense 同等的記憶體需求。實際差異：</p>
<table>
  <thead>
      <tr>
          <th>維度</th>
          <th>Dense 模型（如 Gemma 4 31B）</th>
          <th>MoE 模型（如 Gemma 4 26B A4B）</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>名義參數</td>
          <td>31B 全部參與每個 token</td>
          <td>26B 總參數、每個 token 啟用約 4B（A4B 表示 active 4B）</td>
      </tr>
      <tr>
          <td>記憶體佔用</td>
          <td>整份權重必須塞進記憶體（18GB Q4）</td>
          <td>整份權重也要塞（13GB Q4）、但活躍部分小</td>
      </tr>
      <tr>
          <td>速度上限</td>
          <td>頻寬 / 整份權重 ≈ 30 tok/s</td>
          <td>頻寬 / 活躍權重 ≈ 80 tok/s（同硬體下）</td>
      </tr>
      <tr>
          <td>量化容忍度</td>
          <td>Q4 31B 仍可用</td>
          <td>Q4 在 MoE 上的影響跟 dense 不同、需 case-by-case 驗證</td>
      </tr>
  </tbody>
</table>
<p>判讀重點：MoE 的記憶體需求看「總參數」、但速度看「啟用參數」。同記憶體預算下 MoE 通常跑得比 dense 快、但能力強度比較需配合具體 benchmark 判讀、名義參數僅作初步篩選。PC 獨立 GPU 上的 MoE 部署策略（CPU 卸載專家層）見 <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>。</p>
<h2 id="為什麼-32gb-是寫-code-場景的甜蜜點">為什麼 32GB 是寫 code 場景的甜蜜點</h2>
<p>32GB Mac 跑 Gemma 4 31B（Q4 + MTP）是 2026 年 5 月寫 code 場景最佳的價格效能比，原因是三個趨勢的交會：</p>
<ol>
<li><strong>31B 模型剛好能力夠用</strong>。Gemma 4 31B / Qwen3-Coder 30B 在 SWE-bench 等 coding benchmark 上的表現大幅超越 14B 模型，接近 GPT-4 mini 等級。14B 等級的模型在跨檔案任務上仍經常失誤。</li>
<li><strong>Q4 量化在 31B 上的品質衰減仍可接受</strong>。Q4 在 7B 模型上品質衰減明顯，但 31B 模型有「參數冗餘」，Q4 反而是甜蜜點。</li>
<li><strong>32GB 剛好夠 18GB 模型 + 8GB 系統 + 6GB 其他</strong>。再小（24GB）跑 31B Q4 會吃緊；再大（48GB）邊際效益降低，除非要跑 70B。</li>
</ol>
<p>對應的 Mac 機型（2026 年 5 月可購）：</p>
<ul>
<li>MacBook Pro 14 / 16 with M4 Pro / Max，32GB 配置。</li>
<li>Mac mini M4 Pro，32GB 配置（最便宜的進入點）。</li>
<li>Mac Studio M4 Max，32GB 起跳。</li>
</ul>
<p>如果你正準備買新 Mac 主要為了跑本地 LLM 寫 code、32GB 在 [預算敏感、單機、Gemma 4 31B 為主] 通常是最划算的起點。16GB 在 [&gt;14B 模型 / 多工] 會被擠到 swap、48GB+ 在純寫 code 場景超過甜蜜點、但對 [長 context coding agent / 70B 模型] 仍有實際價值。</p>
<h2 id="16gb-mac-的可行策略">16GB Mac 的可行策略</h2>
<p>16GB Mac 是現實上的最小可用配置。能跑的最大實用模型是 Gemma 4 E4B（Google 的 8B 級實驗版本）或 Qwen3 7B。體感上：</p>
<ol>
<li>同時開 VS Code + Chrome + Slack 跟跑模型會擠到 swap、整台 Mac 變慢；建議跑模型時關掉其他重度 app。</li>
<li>模型品質明顯弱於 31B 等級。簡單 function 補完還行、跨檔案重構交給雲端旗艦更划算。</li>
<li>適合「偶爾用本地、主要還是雲端」的混用策略。</li>
</ol>
<p>如果你的 Mac 是 16GB，先用 Gemma 4 E4B 試試看，評估自己工作流是否真的需要本地 LLM。多數情況下答案是「雲端 API 月費比換 Mac 便宜」。</p>
<h2 id="kv-cache-與長-context-的記憶體陷阱">KV cache 與長 context 的記憶體陷阱</h2>
<p>模型權重佔的記憶體是固定的，但 KV cache 隨 context 長度線性增加。長 context 場景的記憶體陷阱常被忽略。</p>
<p>接近真實的估算（Gemma 4 31B、Q4 量化）：</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>模型 18GB + 0.5GB</td>
      </tr>
      <tr>
          <td>4K tokens</td>
          <td>~2 GB</td>
          <td>模型 18GB + 2GB</td>
      </tr>
      <tr>
          <td>16K tokens</td>
          <td>~8 GB</td>
          <td>模型 18GB + 8GB</td>
      </tr>
      <tr>
          <td>32K tokens</td>
          <td>~16 GB</td>
          <td>模型 18GB + 16GB → 32GB Mac 開始 swap</td>
      </tr>
  </tbody>
</table>
<p>陷阱是把 context 長度設到模型支援的上限（如 32K、128K）卻沒算 KV cache 成本。32GB Mac 跑 31B 模型，實際可用 context 大約只有 8 ~ 16K tokens；超過就會 swap，速度崩潰。</p>
<p>解法：</p>
<ol>
<li>短 prompt 場景（compact code completion）：完全沒問題，多數設定都在 2K 以下。</li>
<li>中等 context（4 ~ 16K）：32GB Mac 仍可運作，但要留意 KV cache 吃多少。</li>
<li>長 context（16K+）：考慮 oMLX 的 paged SSD KV cache（把 KV cache 部分頁面換出到 SSD、換取較長 context、代價是 TTFT 與生字速度略增）。詳見 <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>。</li>
</ol>
<h2 id="風扇發熱與降頻">風扇、發熱與降頻</h2>
<p>Apple Silicon Mac 跑本地 LLM 會持續滿載 CPU / GPU。實際體感：</p>
<table>
  <thead>
      <tr>
          <th>機型</th>
          <th>散熱</th>
          <th>持續推論體感</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>MacBook Air（fanless）</td>
          <td>被動</td>
          <td>5 ~ 10 分鐘後降頻，生字速度掉 30 ~ 50%</td>
      </tr>
      <tr>
          <td>MacBook Pro 14 / 16</td>
          <td>主動</td>
          <td>風扇明顯轉，但能維持效能</td>
      </tr>
      <tr>
          <td>Mac mini</td>
          <td>主動</td>
          <td>風扇轉但較安靜</td>
      </tr>
      <tr>
          <td>Mac Studio</td>
          <td>主動</td>
          <td>體感安靜，效能維持最好</td>
      </tr>
  </tbody>
</table>
<p>對「全天候用本地 LLM」的工作流，桌機型（Mac mini、Studio）比筆電好。筆電上跑長時間推論還要考慮電池與發熱對手部舒適度的影響。</p>
<h2 id="按情境選機型決策表">按情境選機型決策表</h2>
<p>決策表把前面三個變數（手上預算 / 想跑的 model size / 主要用途）摺成一張快查、依情境定位、不需要重新讀整章。詳細的模型選型考慮見 <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 的取捨與適用情境">1.4 模型選型優先順序</a>。</p>
<table>
  <thead>
      <tr>
          <th>情境</th>
          <th>建議</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>已有 16GB Mac，想試本地</td>
          <td>用 Gemma 4 E4B 試一週，主力仍用雲端，評估是否值得升級</td>
      </tr>
      <tr>
          <td>已有 24GB Mac，想試本地</td>
          <td>Gemma 4 12B 或 Qwen3-Coder 14B，是合理起點</td>
      </tr>
      <tr>
          <td>已有 32GB Mac</td>
          <td>Gemma 4 31B MTP 是預設選擇，能力 / 速度甜蜜點</td>
      </tr>
      <tr>
          <td>已有 48GB+ Mac</td>
          <td>Qwen3-Coder 32B 或 Llama 3.3 70B Q4，能力接近 GPT-4 mini</td>
      </tr>
      <tr>
          <td>正準備買新 Mac，預算敏感</td>
          <td>Mac mini M4 Pro 32GB 是最划算的進入點</td>
      </tr>
      <tr>
          <td>正準備買新 Mac，要兼顧攜帶</td>
          <td>MacBook Pro 14 with M4 Pro 32GB</td>
      </tr>
      <tr>
          <td>正準備買新 Mac，要追求最大本地能力</td>
          <td>Mac Studio M4 Max 64GB+</td>
      </tr>
  </tbody>
</table>
<p>陷阱是把 96GB+ 配置當成「未來證明」。模型架構演進可能讓現在的記憶體預算明年就不重要（例如 1-bit 量化、新的稀疏架構）。買超大記憶體前先確認有具體現有需求支撐；「以後可能跑得到 100B+ 模型」這類期待風險很高。</p>
<h2 id="下一章">下一章</h2>
<p>下一章：<a href="/blog/llm/00-foundations/info-judgment-frames/" data-link-title="0.6 判讀本地 LLM 資訊的五個框架" data-link-desc="本地 LLM 資訊更新快，學會用版本、層級、變數、能力、資料流五個框架評估文章與宣稱">0.6 判讀本地 LLM 資訊的五個框架</a>、把心智模型轉成判讀資訊的反射。</p>
]]></content:encoded></item><item><title>0.6 判讀本地 LLM 資訊的五個框架</title><link>https://tarrragon.github.io/blog/llm/00-foundations/info-judgment-frames/</link><pubDate>Mon, 11 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/llm/00-foundations/info-judgment-frames/</guid><description>&lt;p>本地 LLM 的核心特性之一是「資訊更新得很快」。新模型 2 ~ 3 個月一個世代、推論伺服器幾週一個版本、社群文章每天大量產出。同樣一件事在不同來源講法可能差很遠：有的精準、有的混淆層級、有的引用過時資訊、有的拿單一情境當普遍能力。學會用一致的框架評估每則資訊、是本地 LLM 使用者最值得培養的能力。&lt;/p>
&lt;p>本章把前面五章的概念整理成五個判讀框架。每個框架對應一類常見資訊問題、給讀者一組可重複套用的提問清單。讀完後你會建立一個反射：看到 LLM 相關內容時、自動跑過這些框架、確認資訊夠不夠扎實再吸收。&lt;/p>
&lt;h2 id="本章目標">本章目標&lt;/h2>
&lt;p>讀完本章後，你應該能：&lt;/p>
&lt;ol>
&lt;li>看到「N 倍加速」「能跑 X 大小模型」這類量化宣稱時、知道要追問哪些變數。&lt;/li>
&lt;li>看到「X 工具支援 Y 功能」時、知道怎麼確認時間點與版本。&lt;/li>
&lt;li>把工具放回&lt;a href="https://tarrragon.github.io/blog/llm/00-foundations/three-layer-architecture/" data-link-title="0.2 介面 / 伺服器 / 模型三層架構" data-link-desc="把任何本地 LLM 工具放回正確的層級，用三層心智模型看懂工具關係">三層架構&lt;/a>、辨識「framework vs 伺服器 vs 模型」的混淆。&lt;/li>
&lt;li>區分「載得進記憶體」跟「實際好用」是兩件事。&lt;/li>
&lt;li>把「隱私」從「位置」改成「資料流」來思考。&lt;/li>
&lt;/ol>
&lt;hr>
&lt;h2 id="框架一追溯版本與時間點">框架一：追溯版本與時間點&lt;/h2>
&lt;p>本地 LLM 工具的功能支援會隨版本變化。同一句「X 工具支援 Y 功能」可能 2025 年成立、2026 年版本改了、或反過來。判讀任一則「支援 / 整合 / 加入」的宣稱、第一步是確認版本與時間點。&lt;/p>
&lt;h3 id="這個框架解什麼問題">這個框架解什麼問題&lt;/h3>
&lt;p>社群文章常省略版本資訊。「llama.cpp 加入 Gemma 4 MTP」這類句子若沒附上日期或版本號、就有三種可能：上游確實已合入、是某個 fork（從主 repo 分支出去的獨立版本）加的 patch（補丁修改）、或是社群討論的願景。三種狀態下「該怎麼用」的答案完全不同。&lt;/p>
&lt;h3 id="怎麼套用">怎麼套用&lt;/h3>
&lt;p>看到「X 工具支援 / 整合 / 加入 Y」時、按順序問：&lt;/p>
&lt;ol>
&lt;li>&lt;strong>版本與日期&lt;/strong>：在哪個版本加入？發布日期是？&lt;/li>
&lt;li>&lt;strong>支援程度&lt;/strong>：是 GA（一般可用）、beta、實驗性、還是 fork 上的 patch？&lt;/li>
&lt;li>&lt;strong>官方確認&lt;/strong>：是否在 release notes / changelog / 官方文件提到？&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>Ollama&lt;/td>
 &lt;td>&lt;code>github.com/ollama/ollama/releases&lt;/code>&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>llama.cpp&lt;/td>
 &lt;td>&lt;code>github.com/ggerganov/llama.cpp/releases&lt;/code>&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>LM Studio&lt;/td>
 &lt;td>應用程式內 About 頁、官網 changelog&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>MLX&lt;/td>
 &lt;td>&lt;code>github.com/ml-explore/mlx/releases&lt;/code>&lt;/td>
 &lt;/tr>
 &lt;/tbody>
&lt;/table>
&lt;h3 id="實際情境">實際情境&lt;/h3>
&lt;p>2026 年 5 月的具體狀態：Ollama v0.23.1（2026/5/7 釋出）一鍵支援 Gemma 4 MTP；llama.cpp 上游的 speculative decoding 框架仍 beta、Gemma 4 官方 drafter 整合是 feature request。同一個功能在兩個工具的狀態差很多、發表時間決定誰領先。&lt;/p>
&lt;p>這個案例的啟示是「Ollama 用 llama.cpp 當底層」這件事、跟「新功能必定先在 llama.cpp 出現」是兩件事。Ollama 維護自己的 fork 加 patch、有時搶先支援上游還沒接受的功能。看資訊時要明確區分。&lt;/p>
&lt;hr>
&lt;h2 id="框架二量化宣稱的三個變數">框架二：量化宣稱的三個變數&lt;/h2>
&lt;p>任何「N 倍加速」「快 X%」「達到 Y 分」的數字、都至少受三個變數影響：任務類型、比較基準、執行硬體。三個變數沒給齊時、跨情境比較會失準、把數字搬到自己場景常常對不上。&lt;/p>
&lt;h3 id="這個框架解什麼問題-1">這個框架解什麼問題&lt;/h3>
&lt;p>「&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> 加速 3 倍」這個句子省略了「在 coding 任務上、跟沒開 MTP 比、用 M4 Max 跑」這三個前提。同樣的 MTP 在創意寫作上加速可能只有 1.5 倍、在 M2 Pro 上絕對數字小很多。讀者拿到「3 倍」這個數字、放到自己的場景常常對不上。&lt;/p>
&lt;h3 id="怎麼套用-1">怎麼套用&lt;/h3>
&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>coding？對話？數學？翻譯？不同任務的加速幅度差很多&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>比較基準&lt;/td>
 &lt;td>跟「沒開該功能」比、還是跟「另一個工具」比？&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>執行硬體&lt;/td>
 &lt;td>M4 Max？M2 Pro？Mac Studio？硬體規格影響絕對數字&lt;/td>
 &lt;/tr>
 &lt;/tbody>
&lt;/table>
&lt;h3 id="實際情境-1">實際情境&lt;/h3>
&lt;p>&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> 的官方數據是「coding 任務 2 ~ 3 倍加速、其他任務 1.5 ~ 2 倍」。社群文章可能引用成「40% 加速」、這個數字若沒附上前提、無法判斷代表什麼任務或什麼硬體。回到 Google 官方技術報告比對、能還原原始三變數。&lt;/p></description><content:encoded><![CDATA[<p>本地 LLM 的核心特性之一是「資訊更新得很快」。新模型 2 ~ 3 個月一個世代、推論伺服器幾週一個版本、社群文章每天大量產出。同樣一件事在不同來源講法可能差很遠：有的精準、有的混淆層級、有的引用過時資訊、有的拿單一情境當普遍能力。學會用一致的框架評估每則資訊、是本地 LLM 使用者最值得培養的能力。</p>
<p>本章把前面五章的概念整理成五個判讀框架。每個框架對應一類常見資訊問題、給讀者一組可重複套用的提問清單。讀完後你會建立一個反射：看到 LLM 相關內容時、自動跑過這些框架、確認資訊夠不夠扎實再吸收。</p>
<h2 id="本章目標">本章目標</h2>
<p>讀完本章後，你應該能：</p>
<ol>
<li>看到「N 倍加速」「能跑 X 大小模型」這類量化宣稱時、知道要追問哪些變數。</li>
<li>看到「X 工具支援 Y 功能」時、知道怎麼確認時間點與版本。</li>
<li>把工具放回<a href="/blog/llm/00-foundations/three-layer-architecture/" data-link-title="0.2 介面 / 伺服器 / 模型三層架構" data-link-desc="把任何本地 LLM 工具放回正確的層級，用三層心智模型看懂工具關係">三層架構</a>、辨識「framework vs 伺服器 vs 模型」的混淆。</li>
<li>區分「載得進記憶體」跟「實際好用」是兩件事。</li>
<li>把「隱私」從「位置」改成「資料流」來思考。</li>
</ol>
<hr>
<h2 id="框架一追溯版本與時間點">框架一：追溯版本與時間點</h2>
<p>本地 LLM 工具的功能支援會隨版本變化。同一句「X 工具支援 Y 功能」可能 2025 年成立、2026 年版本改了、或反過來。判讀任一則「支援 / 整合 / 加入」的宣稱、第一步是確認版本與時間點。</p>
<h3 id="這個框架解什麼問題">這個框架解什麼問題</h3>
<p>社群文章常省略版本資訊。「llama.cpp 加入 Gemma 4 MTP」這類句子若沒附上日期或版本號、就有三種可能：上游確實已合入、是某個 fork（從主 repo 分支出去的獨立版本）加的 patch（補丁修改）、或是社群討論的願景。三種狀態下「該怎麼用」的答案完全不同。</p>
<h3 id="怎麼套用">怎麼套用</h3>
<p>看到「X 工具支援 / 整合 / 加入 Y」時、按順序問：</p>
<ol>
<li><strong>版本與日期</strong>：在哪個版本加入？發布日期是？</li>
<li><strong>支援程度</strong>：是 GA（一般可用）、beta、實驗性、還是 fork 上的 patch？</li>
<li><strong>官方確認</strong>：是否在 release notes / changelog / 官方文件提到？</li>
</ol>
<p>確認來源的最快路徑：</p>
<table>
  <thead>
      <tr>
          <th>工具</th>
          <th>看哪裡確認版本支援狀態</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>Ollama</td>
          <td><code>github.com/ollama/ollama/releases</code></td>
      </tr>
      <tr>
          <td>llama.cpp</td>
          <td><code>github.com/ggerganov/llama.cpp/releases</code></td>
      </tr>
      <tr>
          <td>LM Studio</td>
          <td>應用程式內 About 頁、官網 changelog</td>
      </tr>
      <tr>
          <td>MLX</td>
          <td><code>github.com/ml-explore/mlx/releases</code></td>
      </tr>
  </tbody>
</table>
<h3 id="實際情境">實際情境</h3>
<p>2026 年 5 月的具體狀態：Ollama v0.23.1（2026/5/7 釋出）一鍵支援 Gemma 4 MTP；llama.cpp 上游的 speculative decoding 框架仍 beta、Gemma 4 官方 drafter 整合是 feature request。同一個功能在兩個工具的狀態差很多、發表時間決定誰領先。</p>
<p>這個案例的啟示是「Ollama 用 llama.cpp 當底層」這件事、跟「新功能必定先在 llama.cpp 出現」是兩件事。Ollama 維護自己的 fork 加 patch、有時搶先支援上游還沒接受的功能。看資訊時要明確區分。</p>
<hr>
<h2 id="框架二量化宣稱的三個變數">框架二：量化宣稱的三個變數</h2>
<p>任何「N 倍加速」「快 X%」「達到 Y 分」的數字、都至少受三個變數影響：任務類型、比較基準、執行硬體。三個變數沒給齊時、跨情境比較會失準、把數字搬到自己場景常常對不上。</p>
<h3 id="這個框架解什麼問題-1">這個框架解什麼問題</h3>
<p>「<a href="/blog/llm/knowledge-cards/mtp/" data-link-title="Multi-Token Prediction (MTP)" data-link-desc="Google 為 Gemma 系列釋出的 speculative decoding 工程化實作">MTP</a> 加速 3 倍」這個句子省略了「在 coding 任務上、跟沒開 MTP 比、用 M4 Max 跑」這三個前提。同樣的 MTP 在創意寫作上加速可能只有 1.5 倍、在 M2 Pro 上絕對數字小很多。讀者拿到「3 倍」這個數字、放到自己的場景常常對不上。</p>
<h3 id="怎麼套用-1">怎麼套用</h3>
<p>看到量化宣稱時、回到下面三個維度確認：</p>
<table>
  <thead>
      <tr>
          <th>變數</th>
          <th>該問什麼</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>任務類型</td>
          <td>coding？對話？數學？翻譯？不同任務的加速幅度差很多</td>
      </tr>
      <tr>
          <td>比較基準</td>
          <td>跟「沒開該功能」比、還是跟「另一個工具」比？</td>
      </tr>
      <tr>
          <td>執行硬體</td>
          <td>M4 Max？M2 Pro？Mac Studio？硬體規格影響絕對數字</td>
      </tr>
  </tbody>
</table>
<h3 id="實際情境-1">實際情境</h3>
<p><a href="/blog/llm/knowledge-cards/mtp/" data-link-title="Multi-Token Prediction (MTP)" data-link-desc="Google 為 Gemma 系列釋出的 speculative decoding 工程化實作">MTP</a> 的官方數據是「coding 任務 2 ~ 3 倍加速、其他任務 1.5 ~ 2 倍」。社群文章可能引用成「40% 加速」、這個數字若沒附上前提、無法判斷代表什麼任務或什麼硬體。回到 Google 官方技術報告比對、能還原原始三變數。</p>
<p><a href="/blog/llm/knowledge-cards/swe-bench/" data-link-title="SWE-bench" data-link-desc="用真實 GitHub issue 量化 LLM coding 能力的 benchmark">SWE-bench</a> 的「77.2 分」也一樣：是 SWE-bench Verified（OpenAI 篩選過的子集）、還是 SWE-bench Lite 或 Full？變體間分數差很多、混為一談會誤判模型強弱。</p>
<h3 id="自己驗證的最穩做法">自己驗證的最穩做法</h3>
<p>公開 benchmark 是參考、不是結論。挑你日常工作流的 5 ~ 10 個真實任務當私人 benchmark、跑本地模型看通過率。這個方法繞過所有變數爭議、給你能用在自己場景的數字。</p>
<hr>
<h2 id="框架三工具放回三層架構">框架三：工具放回三層架構</h2>
<p>LLM 生態的工具屬於<a href="/blog/llm/00-foundations/three-layer-architecture/" data-link-title="0.2 介面 / 伺服器 / 模型三層架構" data-link-desc="把任何本地 LLM 工具放回正確的層級，用三層心智模型看懂工具關係">介面層、推論伺服器層、模型層</a>。各層之間用標準介面（<a href="/blog/llm/knowledge-cards/openai-compatible-api/" data-link-title="OpenAI 相容 API" data-link-desc="本地推論伺服器跟雲端 OpenAI 共用的 API 形狀標準">OpenAI 相容 API</a>、<a href="/blog/llm/knowledge-cards/gguf/" data-link-title="GGUF" data-link-desc="llama.cpp 生態定義的模型權重格式：把權重、tokenizer、metadata 打包成單一檔案">GGUF</a> 等）連接、各自可獨立替換。判讀工具相關資訊時、先確認它屬於哪一層、再評估宣稱。</p>
<h3 id="這個框架解什麼問題-2">這個框架解什麼問題</h3>
<p>工具名稱常被當成跨層通用詞。「Ollama 很快」「<a href="/blog/llm/knowledge-cards/mlx/" data-link-title="MLX" data-link-desc="Apple 釋出的 Apple Silicon 數值運算 framework：類似 PyTorch / JAX 的 Mac 對應物">MLX</a> 比 llama.cpp 強」「<a href="/blog/llm/00-foundations/mlx-mtp-omlx/" data-link-title="0.4 MLX / MTP / oMLX 的區別" data-link-desc="三個常被混為一談的術語：framework、加速技巧、特化 server，疊加而非互斥">oMLX</a> 是 Ollama 的 MLX 版」這類句子各自混淆了不同層：Ollama 是推論伺服器、MLX 是 framework、llama.cpp 同時是 library 跟 server、oMLX 是另一個推論伺服器。混淆層級的句子讀起來像在比較、實際上比較的對象不在同一層。</p>
<h3 id="怎麼套用-2">怎麼套用</h3>
<p>看到工具被比較或描述時、按下表分類：</p>
<table>
  <thead>
      <tr>
          <th>工具</th>
          <th>屬於哪一層</th>
          <th>比較對象應該是</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>Continue.dev</td>
          <td>介面層</td>
          <td>Cursor、aider、Open WebUI</td>
      </tr>
      <tr>
          <td>Ollama</td>
          <td>推論伺服器</td>
          <td>LM Studio、llama-server、oMLX</td>
      </tr>
      <tr>
          <td>llama.cpp</td>
          <td>library + 推論伺服器</td>
          <td>MLX、PyTorch（library 層）；llama-server 跟其他 server 比</td>
      </tr>
      <tr>
          <td>MLX</td>
          <td>framework / library</td>
          <td>PyTorch、JAX</td>
      </tr>
      <tr>
          <td>Gemma 4 / Qwen3</td>
          <td>模型</td>
          <td>其他模型</td>
      </tr>
      <tr>
          <td>OpenAI 相容 API</td>
          <td>跨層標準介面</td>
          <td>（是介面、不是工具）</td>
      </tr>
  </tbody>
</table>
<h3 id="實際情境-2">實際情境</h3>
<p>「Ollama 用 MLX 加速」這個句子若按本框架追問：Ollama 內部用 llama.cpp（library 層）當推論引擎、用 Metal backend 接 Apple Silicon 的 GPU。它跟 MLX 是平行的選擇、不是包含關係。要用 MLX 當 backend 要選 oMLX 或自己用 Python 把 mlx-lm 包成 server。「Ollama 用 MLX」混淆了 framework 層與 server 層。</p>
<p>「<a href="/blog/llm/00-foundations/mlx-mtp-omlx/" data-link-title="0.4 MLX / MTP / oMLX 的區別" data-link-desc="三個常被混為一談的術語：framework、加速技巧、特化 server，疊加而非互斥">oMLX</a> 比 Ollama 強」這類句子也要拆：oMLX 主要創新是 paged SSD KV cache、解的是長 context 場景的 <a href="/blog/llm/knowledge-cards/ttft/" data-link-title="TTFT" data-link-desc="Time To First Token：送出 prompt 到第一個 token 出現的等待時間">TTFT</a> 痛點。對短 prompt 場景、Ollama 跟 oMLX 速度差不多；對長 context 場景、oMLX 有針對性優勢。直接說「強」會丟失情境。</p>
<hr>
<h2 id="框架四載得進-vs-實際好用">框架四：載得進 vs 實際好用</h2>
<p>「能載入記憶體」跟「實際好用」是兩件事。看到「Mac 跑得起 X 模型」的截圖時、要追問體感速度與資源佔用、而非只看「啟動成功」。</p>
<h3 id="這個框架解什麼問題-3">這個框架解什麼問題</h3>
<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> + 系統保留）只是第一步。實際使用要看：生字速度體感如何、首字延遲多久、整台 Mac 其他工作是否變慢、長時間用會不會降頻。一張截圖只證明「載入成功」、跟「能日常用」是不同層次的問題。</p>
<h3 id="怎麼套用-3">怎麼套用</h3>
<p>看到「我在 Mac 上跑 X 模型」的報告時、按下表追問：</p>
<table>
  <thead>
      <tr>
          <th>指標</th>
          <th>體感分界</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td><a href="/blog/llm/knowledge-cards/tokens-per-second/" data-link-title="Tokens Per Second" data-link-desc="LLM 每秒能生成幾個 token：生字速度的標準量化指標">生字速度</a></td>
          <td>&lt; 10 tok/s 卡頓、20 ~ 40 tok/s 流暢、&gt; 40 即時</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>&gt; 10 秒打斷思路、&lt; 3 秒接近順暢</td>
      </tr>
      <tr>
          <td>整台 Mac 響應</td>
          <td>切 tab / 開 app / 滑滑鼠是否順暢</td>
      </tr>
      <tr>
          <td>記憶體 swap</td>
          <td>Activity Monitor 看 Memory Pressure 是否變紅</td>
      </tr>
      <tr>
          <td>風扇與降頻</td>
          <td>長時間用是否風扇狂轉、體感變熱</td>
      </tr>
  </tbody>
</table>
<h3 id="實際情境-3">實際情境</h3>
<p>16GB Mac「跑得起」31B 模型的截圖、實際多半是：模型剛載入時看起來能用、但系統正在 swap、生字速度掉到 1 ~ 2 tok/s、其他 app 全部變慢、整台 Mac 像泡在糖漿裡。這個狀態下「跑起來」的結論成立、「日常使用」的結論不成立。</p>
<p>換更激進量化（<a href="/blog/llm/knowledge-cards/quantization/" data-link-title="Quantization" data-link-desc="用較少 bits 表示模型權重：壓縮記憶體佔用、加快生字速度，代價是少量品質衰減">Q3</a>）來塞更大模型也踩同樣的陷阱。Q3 70B 在 24GB Mac 上勉強載入、但 coding 任務表現常輸給同硬體的 Q5 14B 模型；衰減的判讀訊號是「同任務通過率比未量化版本低 30% 以上」「hallucination 明顯上升（編造 API、忽略 prompt 約束）」、出現這些訊號就回頭重新評估量化等級。</p>
<p>判讀「我跑得起來」這類報告時、把上表五個指標都問一遍、才能還原真實體感。</p>
<hr>
<h2 id="框架五隱私是資料流不是位置">框架五：隱私是資料流、不是位置</h2>
<p>本地推論伺服器把 prompt 留在自己機器上、是隱私光譜的起點、不是終點。完整評估隱私要追資料流：prompt 從你按下 Enter 開始、經過哪些 process、儲存在哪、最終會不會以任何形式離開機器。</p>
<h3 id="這個框架解什麼問題-4">這個框架解什麼問題</h3>
<p>「跑在本地、所以絕對私密」這個結論預設「位置」是隱私的唯一變數、但實際隱私風險來自整條資料流。同樣是「本地 LLM」、不同配置的隱私邊界可以差很多。</p>
<h3 id="怎麼套用-4">怎麼套用</h3>
<p>把你的 LLM 使用環境畫成資料流圖、列出 prompt 經過的每個節點：</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">  ↓
</span></span><span class="line"><span class="ln"> 3</span><span class="cl">IDE / 介面層工具（Continue.dev、Cursor、Open WebUI）
</span></span><span class="line"><span class="ln"> 4</span><span class="cl">  ↓ 經過 OpenAI 相容 API
</span></span><span class="line"><span class="ln"> 5</span><span class="cl">本地推論伺服器（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">模型權重 + KV cache 在記憶體
</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">回應顯示在 IDE
</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">（可能）對話紀錄存到 SQLite / 雲端同步 / 第三方 telemetry</span></span></code></pre></div><p>每個節點問一次：</p>
<table>
  <thead>
      <tr>
          <th>節點</th>
          <th>該問什麼</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>IDE 介面層</td>
          <td>有沒有 telemetry？是否同時送雲端服務？</td>
      </tr>
      <tr>
          <td>推論伺服器配置</td>
          <td><code>OLLAMA_HOST</code> 是 <a href="/blog/llm/knowledge-cards/port-and-localhost/" data-link-title="Port 與 Localhost" data-link-desc="TCP port 與 listen address 如何決定 API server 的對外暴露範圍"><code>127.0.0.1</code></a> 還是 <code>0.0.0.0</code>？</td>
      </tr>
      <tr>
          <td>對話紀錄保存</td>
          <td>存到本機 SQLite？同步到 Notion / iCloud？</td>
      </tr>
      <tr>
          <td>介面 plugin</td>
          <td>有沒有第三方 plugin 把 prompt 送到別處？</td>
      </tr>
      <tr>
          <td>網路設定</td>
          <td>是否有區網其他裝置能存取本地伺服器？</td>
      </tr>
  </tbody>
</table>
<h3 id="實際情境-4">實際情境</h3>
<p>寫 NDA 客戶 code 時、即使用 Ollama 跑本地 LLM、若同時開著「自動同步 VS Code 設定到雲端」「Open WebUI 對話歷史備份到 iCloud」、prompt 仍可能間接外洩。Cursor 等 IDE 預設可能送 telemetry（含 prompt 片段）給自家服務；用 Cursor 接本地 Ollama 跟用 Continue.dev 接本地 Ollama 的隱私邊界不同。</p>
<p>把 <code>OLLAMA_HOST=0.0.0.0</code> 開出去（讓區網其他機器連）也常被忽略。家用網路風險低、公共 Wi-Fi 在沒設防火牆規則的情況下、本地 LLM 等同暴露給整個網段。預設值是 <code>127.0.0.1</code>、改動前先確認場景。</p>
<p>雲端 LLM 也提供 zero-retention 與「不訓練」選項（企業方案、API 預設等），多數合規場景能滿足。本地的隱私優勢在「物理上資料留在機器」、雲端的隱私保證來自合約與技術控制；兩條路在隱私光譜上各占一段、按實際需求挑。</p>
<hr>
<h2 id="把五個框架當反射">把五個框架當反射</h2>
<p>下表把五個框架壓成一張快速查表、看新資訊時對照：</p>
<table>
  <thead>
      <tr>
          <th>看到這類內容</th>
          <th>先跑哪個框架</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>「N 倍加速」「快 X%」</td>
          <td>框架二（任務、基準、硬體三變數）</td>
      </tr>
      <tr>
          <td>「達到 / 接近 GPT-X」</td>
          <td>框架二 + 框架四（變數 + 真實體感）</td>
      </tr>
      <tr>
          <td>「X 工具支援 Y 功能」</td>
          <td>框架一（版本與日期）</td>
      </tr>
      <tr>
          <td>「A 比 B 強」</td>
          <td>框架三（兩者是不是同一層）</td>
      </tr>
      <tr>
          <td>「我跑得起 X 模型」</td>
          <td>框架四（生字速度、TTFT、整機體感）</td>
      </tr>
      <tr>
          <td>「本地絕對私密」</td>
          <td>框架五（資料流每個節點）</td>
      </tr>
      <tr>
          <td>「換 model 就能做 Y」</td>
          <td>框架三（Y 是不是同一個架構家族？<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>）</td>
      </tr>
      <tr>
          <td>「量化越激進記憶體越省」</td>
          <td>框架四（量化後品質還夠嗎）</td>
      </tr>
  </tbody>
</table>
<p>五個框架彼此互補、不互斥。一則複雜資訊常需要同時跑兩三個框架才能完整評估。例如「16GB Mac 跑 70B Q3 模型很順、達到 GPT-4 等級」這句話、要同時跑框架二（達到 GPT-4 是什麼任務上的測試？）、框架四（生字速度多少？整台 Mac 還能用嗎？）、框架三（70B Q3 跟 GPT-4 不在同一層、有點混）。三個框架都跑過、就能還原原始宣稱的真實價值。</p>
<h2 id="框架的邊界何時可以省略">框架的邊界：何時可以省略</h2>
<p>五個框架是預設掃描清單、但不是每個情境都要五個一起跑。下表是「該框架不適用」的判讀：</p>
<table>
  <thead>
      <tr>
          <th>框架</th>
          <th>何時可以省略</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>一、追溯版本時間點</td>
          <td>物理上限類數字（記憶體頻寬、bus 寬度）— 不隨版本變化</td>
      </tr>
      <tr>
          <td>二、量化宣稱三變數</td>
          <td>物理常數或寫死的硬體規格（如 M4 Max 頻寬 546 GB/s）— 是硬體事實、非宣稱</td>
      </tr>
      <tr>
          <td>三、工具放回三層</td>
          <td>純應用層討論（如 prompt engineering、agent 設計）— 跟分層架構正交</td>
      </tr>
      <tr>
          <td>四、載得進 vs 好用</td>
          <td>純概念說明 / 教學文（不涉及實際跑模型）— 沒有「好用」維度要評估</td>
      </tr>
      <tr>
          <td>五、隱私資料流</td>
          <td>完全離線的設備（air-gapped Mac）— 資料流退化為單一節點</td>
      </tr>
  </tbody>
</table>
<p>判讀原則：框架不適用於「該維度根本不存在」的情境。寧可多跑一個框架、覆蓋率優先 — 跑了發現不適用比漏掉某維度風險小。</p>
<h2 id="框架是工具不是教條">框架是工具、不是教條</h2>
<p>跑這些框架的目的是「拿到能用在自己場景的判讀」、不是「找出每篇文章的錯」。多數作者寫東西時省略前提、是為了文章流暢、未必是有意誤導。把框架當成補完前提的工具：看到不完整的句子、自己補上「在什麼任務、什麼硬體、什麼版本」的脈絡、就能還原作者想表達的事。</p>
<p>對自己也用同一套標準。寫筆記、發推文、回答同事問題時、附上版本與硬體脈絡、能讓資訊更耐保存、半年後自己回看也仍能讀懂。</p>
<h2 id="下一步">下一步</h2>
<p>下一步：<a href="/blog/llm/01-local-llm-services/" data-link-title="模組一：本地 LLM 服務的安裝與應用" data-link-desc="Ollama、LM Studio、llama.cpp 的安裝與差異、VS Code &#43; Continue.dev 整合、模型選型與期望管理">模組一 本地 LLM 服務的安裝與應用</a>、把概念落地到實際安裝、整合 VS Code、選模型、做期望管理。</p>
]]></content:encoded></item><item><title>0.7 隱私 / 資安的資料流原理</title><link>https://tarrragon.github.io/blog/llm/00-foundations/privacy-data-flow/</link><pubDate>Mon, 11 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/llm/00-foundations/privacy-data-flow/</guid><description>&lt;p>&lt;a href="https://tarrragon.github.io/blog/llm/00-foundations/info-judgment-frames/" data-link-title="0.6 判讀本地 LLM 資訊的五個框架" data-link-desc="本地 LLM 資訊更新快，學會用版本、層級、變數、能力、資料流五個框架評估文章與宣稱">0.6 判讀框架五&lt;/a> 建立的反射是「隱私是資料流、不是位置」。本章把這個 framing 展開成可操作的設計原則：信任邊界該怎麼劃、本地推論 vs 雲端的合約模型差異、零信任原則套用到 LLM 工作流的具體做法、NDA / 企業合規場景的判讀框架。&lt;/p>
&lt;p>本章寫的是「無論工具怎麼演變、隱私設計都該這樣思考」的原理層。具體合規法規條文（GDPR、HIPAA、各地新法）、特定工具的 telemetry 設定（每家半年一變）不在本章——這些隨時間變、用本章建立的 framework 重新評估就好。本章是 framing；落地操作見 &lt;a href="https://tarrragon.github.io/blog/llm/06-security/" data-link-title="模組六：本地 LLM 的安全與權限" data-link-desc="個人 dev 在自己機器上跑本地 LLM 的安全議題：模型供應鏈、推論伺服器綁定、tool use 副作用、prompt injection 在 IDE、跨雲端 / 本地資料邊界">模組六 本地 LLM 的安全與權限&lt;/a>、把這些框架拆到推論伺服器綁定、tool use 權限、prompt injection、跨雲端邊界等具體決策。&lt;/p>
&lt;h2 id="本章目標">本章目標&lt;/h2>
&lt;p>讀完本章後、你應該能：&lt;/p>
&lt;ol>
&lt;li>用資料流圖描述自己的 LLM 工作流、辨識每個 hop 的信任邊界。&lt;/li>
&lt;li>區分「物理保證」與「合約保證」兩種隱私模型的取捨。&lt;/li>
&lt;li>把零信任原則套用到 LLM 系統設計。&lt;/li>
&lt;li>對 NDA / 企業合規場景做出有條理的判讀、不只看「是否本地」。&lt;/li>
&lt;/ol>
&lt;h2 id="從位置-thinking到資料流-thinking">從「位置 Thinking」到「資料流 Thinking」&lt;/h2>
&lt;p>「跑在本地、所以隱私」這個直覺假設「位置」是隱私的唯一變數。實際上隱私風險來自整條資料流的每個節點、位置只是其中一個維度。&lt;/p>
&lt;p>把問題從「我的 prompt 是否離開機器」改成「我的 prompt 從打字到最終結果、經過哪些 process、儲存在哪、誰能看到」。後者覆蓋面廣得多：&lt;/p>
&lt;ul>
&lt;li>prompt 在 IDE 內被 cache？&lt;/li>
&lt;li>IDE 有沒有開雲端同步？&lt;/li>
&lt;li>推論伺服器 log 留多久？&lt;/li>
&lt;li>對話歷史存到哪？&lt;/li>
&lt;li>第三方 plugin 有沒有偷 access prompt？&lt;/li>
&lt;li>結果寫到磁碟後、有沒有被自動備份到 iCloud / Dropbox？&lt;/li>
&lt;/ul>
&lt;p>「位置 thinking」對所有這些都看不到——只要推論在本地就覺得安全。「資料流 thinking」把整條 hop 攤開、每個節點單獨評估。&lt;/p>
&lt;p>這個 shift 是隱私設計的根本前提。沒做這個 shift、其他設計都建立在錯誤假設上。&lt;/p>
&lt;h2 id="信任邊界的定義">信任邊界的定義&lt;/h2>
&lt;p>LLM 工作流通常跨多層信任邊界（IDE / 推論伺服器 / 雲端同步 / 第三方 plugin / LAN）、隱私設計的第一步是把這些邊界明確畫出來。信任邊界（trust boundary）的概念來自系統安全設計：「誰能看到什麼資料」的明確分隔。穿越邊界的資料需要明確的授權跟稽核；同邊界內的資料假設安全。&lt;/p>
&lt;p>本地推論的天然信任邊界是「我的 Mac」——資料在這個邊界內預設安全（除非機器本身被入侵）。但實際 LLM 工作流會穿透這個邊界：&lt;/p>
&lt;ul>
&lt;li>&lt;strong>雲端同步穿透&lt;/strong>：VS Code 同步 settings、Notion 備份對話、iCloud 同步文件——資料從 Mac 走到雲、信任邊界被擴展到供應商。&lt;/li>
&lt;li>&lt;strong>Telemetry 穿透&lt;/strong>：IDE plugin、&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>、作業系統都可能送遙測資料、含 prompt 片段 / metadata。&lt;/li>
&lt;li>&lt;strong>第三方 plugin 穿透&lt;/strong>：裝的 VS Code extension、瀏覽器 plugin 都可能 access 同個 prompt context。&lt;/li>
&lt;li>&lt;strong>網路 expose 穿透&lt;/strong>：&lt;code>OLLAMA_HOST=0.0.0.0&lt;/code> 把本地伺服器暴露到 LAN、信任邊界從「我的 Mac」擴展到「整個區網」。&lt;/li>
&lt;/ul>
&lt;p>LLM 工作流通常有多層信任邊界、跟「我在本地跑」的單純直覺不一定一致。設計隱私時、先把所有信任邊界畫出來、再評估每個邊界的「誰能看到、能看到什麼」。&lt;/p>
&lt;p>信任邊界的判讀問題：&lt;/p>
&lt;ul>
&lt;li>這個 process 屬於哪個邊界內？&lt;/li>
&lt;li>跨邊界傳資料需要什麼授權？&lt;/li>
&lt;li>邊界外的 component 如果被入侵、能 access 到什麼？&lt;/li>
&lt;/ul>
&lt;p>這幾個問題答得清楚、隱私設計就有 ground truth；答得模糊、設計就建立在假設上。&lt;/p>
&lt;h2 id="本地-vs-雲端的合約模型">本地 vs 雲端的合約模型&lt;/h2>
&lt;p>本地推論跟雲端推論的隱私保證來自不同模型：&lt;/p>
&lt;h3 id="物理保證本地">物理保證（本地）&lt;/h3>
&lt;p>本地推論的隱私保證是「物理上資料留在這台機器」、可技術觀察：&lt;/p>
&lt;ul>
&lt;li>用 &lt;code>lsof&lt;/code>（list open files、看 process 持有的網路 socket）看推論伺服器的網路連線、確認沒對外送資料。&lt;/li>
&lt;li>用 &lt;code>tcpdump&lt;/code>（系統封包擷取工具）監聽流量、確認 prompt 沒外洩。&lt;/li>
&lt;li>看磁碟 IO、確認對話歷史沒被寫到雲端同步資料夾。&lt;/li>
&lt;/ul>
&lt;p>&lt;strong>這些工具的能力邊界&lt;/strong>：&lt;code>lsof&lt;/code> / &lt;code>tcpdump&lt;/code> 給的是「常態流量觀察」、不是完整安全證明。編譯期注入、kernel-level exfiltration、DNS tunneling 等繞過手法仍可能規避這些觀察視角。國家級威脅模型或高 stakes 合規場景下、要再加程式碼簽章驗證、SELinux / EndpointSecurity policy、出口防火牆等更深的控制；個人 / 中小企業場景下、這三個工具的觀察通常足以建立日常的信心。&lt;/p></description><content:encoded><![CDATA[<p><a href="/blog/llm/00-foundations/info-judgment-frames/" data-link-title="0.6 判讀本地 LLM 資訊的五個框架" data-link-desc="本地 LLM 資訊更新快，學會用版本、層級、變數、能力、資料流五個框架評估文章與宣稱">0.6 判讀框架五</a> 建立的反射是「隱私是資料流、不是位置」。本章把這個 framing 展開成可操作的設計原則：信任邊界該怎麼劃、本地推論 vs 雲端的合約模型差異、零信任原則套用到 LLM 工作流的具體做法、NDA / 企業合規場景的判讀框架。</p>
<p>本章寫的是「無論工具怎麼演變、隱私設計都該這樣思考」的原理層。具體合規法規條文（GDPR、HIPAA、各地新法）、特定工具的 telemetry 設定（每家半年一變）不在本章——這些隨時間變、用本章建立的 framework 重新評估就好。本章是 framing；落地操作見 <a href="/blog/llm/06-security/" data-link-title="模組六：本地 LLM 的安全與權限" data-link-desc="個人 dev 在自己機器上跑本地 LLM 的安全議題：模型供應鏈、推論伺服器綁定、tool use 副作用、prompt injection 在 IDE、跨雲端 / 本地資料邊界">模組六 本地 LLM 的安全與權限</a>、把這些框架拆到推論伺服器綁定、tool use 權限、prompt injection、跨雲端邊界等具體決策。</p>
<h2 id="本章目標">本章目標</h2>
<p>讀完本章後、你應該能：</p>
<ol>
<li>用資料流圖描述自己的 LLM 工作流、辨識每個 hop 的信任邊界。</li>
<li>區分「物理保證」與「合約保證」兩種隱私模型的取捨。</li>
<li>把零信任原則套用到 LLM 系統設計。</li>
<li>對 NDA / 企業合規場景做出有條理的判讀、不只看「是否本地」。</li>
</ol>
<h2 id="從位置-thinking到資料流-thinking">從「位置 Thinking」到「資料流 Thinking」</h2>
<p>「跑在本地、所以隱私」這個直覺假設「位置」是隱私的唯一變數。實際上隱私風險來自整條資料流的每個節點、位置只是其中一個維度。</p>
<p>把問題從「我的 prompt 是否離開機器」改成「我的 prompt 從打字到最終結果、經過哪些 process、儲存在哪、誰能看到」。後者覆蓋面廣得多：</p>
<ul>
<li>prompt 在 IDE 內被 cache？</li>
<li>IDE 有沒有開雲端同步？</li>
<li>推論伺服器 log 留多久？</li>
<li>對話歷史存到哪？</li>
<li>第三方 plugin 有沒有偷 access prompt？</li>
<li>結果寫到磁碟後、有沒有被自動備份到 iCloud / Dropbox？</li>
</ul>
<p>「位置 thinking」對所有這些都看不到——只要推論在本地就覺得安全。「資料流 thinking」把整條 hop 攤開、每個節點單獨評估。</p>
<p>這個 shift 是隱私設計的根本前提。沒做這個 shift、其他設計都建立在錯誤假設上。</p>
<h2 id="信任邊界的定義">信任邊界的定義</h2>
<p>LLM 工作流通常跨多層信任邊界（IDE / 推論伺服器 / 雲端同步 / 第三方 plugin / LAN）、隱私設計的第一步是把這些邊界明確畫出來。信任邊界（trust boundary）的概念來自系統安全設計：「誰能看到什麼資料」的明確分隔。穿越邊界的資料需要明確的授權跟稽核；同邊界內的資料假設安全。</p>
<p>本地推論的天然信任邊界是「我的 Mac」——資料在這個邊界內預設安全（除非機器本身被入侵）。但實際 LLM 工作流會穿透這個邊界：</p>
<ul>
<li><strong>雲端同步穿透</strong>：VS Code 同步 settings、Notion 備份對話、iCloud 同步文件——資料從 Mac 走到雲、信任邊界被擴展到供應商。</li>
<li><strong>Telemetry 穿透</strong>：IDE plugin、<a href="/blog/llm/knowledge-cards/inference-server/" data-link-title="Inference Server" data-link-desc="載入模型權重、處理 prompt、產生 token 的常駐 process">推論伺服器</a>、作業系統都可能送遙測資料、含 prompt 片段 / metadata。</li>
<li><strong>第三方 plugin 穿透</strong>：裝的 VS Code extension、瀏覽器 plugin 都可能 access 同個 prompt context。</li>
<li><strong>網路 expose 穿透</strong>：<code>OLLAMA_HOST=0.0.0.0</code> 把本地伺服器暴露到 LAN、信任邊界從「我的 Mac」擴展到「整個區網」。</li>
</ul>
<p>LLM 工作流通常有多層信任邊界、跟「我在本地跑」的單純直覺不一定一致。設計隱私時、先把所有信任邊界畫出來、再評估每個邊界的「誰能看到、能看到什麼」。</p>
<p>信任邊界的判讀問題：</p>
<ul>
<li>這個 process 屬於哪個邊界內？</li>
<li>跨邊界傳資料需要什麼授權？</li>
<li>邊界外的 component 如果被入侵、能 access 到什麼？</li>
</ul>
<p>這幾個問題答得清楚、隱私設計就有 ground truth；答得模糊、設計就建立在假設上。</p>
<h2 id="本地-vs-雲端的合約模型">本地 vs 雲端的合約模型</h2>
<p>本地推論跟雲端推論的隱私保證來自不同模型：</p>
<h3 id="物理保證本地">物理保證（本地）</h3>
<p>本地推論的隱私保證是「物理上資料留在這台機器」、可技術觀察：</p>
<ul>
<li>用 <code>lsof</code>（list open files、看 process 持有的網路 socket）看推論伺服器的網路連線、確認沒對外送資料。</li>
<li>用 <code>tcpdump</code>（系統封包擷取工具）監聽流量、確認 prompt 沒外洩。</li>
<li>看磁碟 IO、確認對話歷史沒被寫到雲端同步資料夾。</li>
</ul>
<p><strong>這些工具的能力邊界</strong>：<code>lsof</code> / <code>tcpdump</code> 給的是「常態流量觀察」、不是完整安全證明。編譯期注入、kernel-level exfiltration、DNS tunneling 等繞過手法仍可能規避這些觀察視角。國家級威脅模型或高 stakes 合規場景下、要再加程式碼簽章驗證、SELinux / EndpointSecurity policy、出口防火牆等更深的控制；個人 / 中小企業場景下、這三個工具的觀察通常足以建立日常的信心。</p>
<p>物理保證的特性：</p>
<ul>
<li><strong>可單機驗證</strong>：不需要信任供應商、能用本地工具觀察流量。</li>
<li><strong>能力上限受硬體限制</strong>：本地模型受 Mac 算力跟記憶體限制、能力比雲端旗艦低一個量級。</li>
<li><strong>不依賴合約承諾</strong>：供應商有沒有承諾「不訓練」「zero-retention」都跟本地推論無關——資料本來就沒去那裡。</li>
</ul>
<h3 id="合約保證雲端">合約保證（雲端）</h3>
<p>雲端推論的隱私保證是「供應商承諾不留資料、不訓練、合規 X 規範」、技術上單機不可驗證、靠合約與 audit 支撐：</p>
<ul>
<li>Anthropic、OpenAI 的企業方案明示 zero-retention、不訓練選項（2026 年 5 月當時的 ToS、雲端 ToS 半年一變、實際採用前以最新版為準）。</li>
<li>SOC 2、ISO 27001、HIPAA BAA 等合規認證提供第三方 audit。</li>
<li>供應商的 ToS / privacy policy 是法律承諾、違反可訴訟。</li>
</ul>
<p>合約保證的特性：</p>
<ul>
<li><strong>不可單機驗證</strong>：要信任供應商沒違反承諾、加上第三方 audit 補強。</li>
<li><strong>能力沒上限</strong>：能用上雲端最強模型（GPT-5、Claude Sonnet 4.6、Opus）、沒有硬體限制。</li>
<li><strong>受法律管轄影響</strong>：供應商所在管轄區的法律、未來變動會影響保證強度（如政府要求供應商交資料）。</li>
</ul>
<h3 id="兩種模型的取捨">兩種模型的取捨</h3>
<p>兩種模型不是「誰比較好」、是「在什麼情境下哪個適合」：</p>
<ul>
<li><strong>隱私要求極高 + 模型能力夠用</strong>：本地。物理保證可驗證、不需信任供應商。</li>
<li><strong>能力要求極高 + 隱私要求中等</strong>：雲端 + 合約保證。Claude / GPT 旗艦的能力本地短期內追不上。</li>
<li><strong>合規場景</strong>：看具體規範要求。HIPAA、PCI-DSS 等場景雲端 + BAA / DPA 合約 + technical control 是主流方案、不一定要本地。</li>
<li><strong>NDA + 客戶明示不得送雲</strong>：本地是預設、合約保證對「不得送雲」這條沒幫助。</li>
</ul>
<p>判讀「該選哪邊」不是 binary、是 spectrum：許多場景混用、敏感任務本地、需要能力的任務雲端 + 合約保證。混用模式有一個隱形 leak 風險：同一個 IDE 同時接本地與雲端 backend、prompt routing 設錯就會把該走本地的內容送到雲端。實作時要明確隔離（不同 workspace / 不同帳號 / 不同 plugin set）、用配置強制路由、而非依賴每次手動切換。Continue.dev 多 provider 設定的具體路由判讀見 <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>。</p>
<h2 id="零信任原則套用到-llm-工作流">零信任原則套用到 LLM 工作流</h2>
<p>零信任（zero trust）的核心是「不假設任何 component 是 trusted、每個 hop 都重新驗證」。傳統信任模型假設「邊界內安全」、零信任假設「邊界本身可能被穿透」、每次 access 都驗證。</p>
<p>套用到 LLM 工作流的具體實踐：</p>
<h3 id="不信任預設配置">不信任預設配置</h3>
<p>每個 component 的預設配置往往不是「最隱私」、是「最方便」。<code>OLLAMA_HOST</code> 預設 <code>127.0.0.1</code> 還算安全、但很多工具預設打開 telemetry、預設同步到雲端。在 NDA / 合規場景下、所有 component 的隱私相關設定通常需要逐項 review、預設值會根據場景調整。</p>
<h3 id="每個-hop-都評估">每個 hop 都評估</h3>
<p>不只是「我用 Ollama 所以隱私」、要評估從打字到結果的每個 hop：IDE telemetry、plugin 行為、推論伺服器 log、對話歷史儲存、檔案系統位置、雲端同步範圍。任何一個 hop 預設設定「外洩」、整條鏈的隱私就破。</p>
<h3 id="最小權限">最小權限</h3>
<p>每個 component 只給它必要的 access：</p>
<ul>
<li>推論伺服器：不需要存 prompt 歷史就關 log。</li>
<li>IDE plugin：不裝沒驗證的 third-party plugin。</li>
<li>雲端同步：個人場景白名單同步是低成本 default、NDA / 合規場景直接排除整個 LLM 相關目錄。</li>
</ul>
<p>「最小權限」需要主動設計、不會自動發生——預設都是「方便優先」。</p>
<h3 id="認假設不認直覺">認假設、不認直覺</h3>
<p>「跑在本地所以安全」是直覺、不是已驗證的事實。零信任要求每個假設都跑一次 audit 確認、用觀察取代感覺。</p>
<h2 id="資料流分析的具體做法">資料流分析的具體做法</h2>
<p>把抽象原則落地、要做資料流分析：把整個工作流畫成 graph、每個 node 是 process、每個 edge 是資料流動、標示資料類型跟流向。</p>
<p>具體步驟：</p>
<ol>
<li><strong>列出所有節點</strong>：使用者、IDE、IDE plugin、推論伺服器、模型、磁碟、雲端服務、第三方 service。</li>
<li><strong>畫出所有 edge</strong>：誰送資料給誰、什麼類型的資料、什麼觸發。</li>
<li><strong>標示信任邊界</strong>：哪些節點屬同一個邊界、邊界之間的 edge 標出來。</li>
<li><strong>每個跨邊界 edge 評估三個問題</strong>：
<ul>
<li>誰能看到流過這條 edge 的資料？</li>
<li>儲存多久？</li>
<li>會不會再轉送出去？</li>
</ul>
</li>
<li><strong>找出風險集中點</strong>：常見集中點是 IDE telemetry、雲端同步、第三方 plugin。</li>
</ol>
<p>這個分析做完、隱私風險不再是抽象的「會不會洩漏」、是具體的「哪個 edge 在洩漏什麼」。修補策略也跟著具體：關 telemetry、移除特定 plugin、改設定。</p>
<p>實務做這個分析、第一次通常會發現預期外的 edge——例如「我以為對話歷史只在本地、結果發現 IDE 的 sync settings 把它送到雲」、「我以為這個 plugin 只 access code、結果它也送 prompt 給自家 analytics」。</p>
<h2 id="nda--企業合規場景的判讀框架">NDA / 企業合規場景的判讀框架</h2>
<p>NDA 跟企業合規場景的隱私要求比個人使用嚴格、判讀方式：</p>
<h3 id="nda-場景">NDA 場景</h3>
<ul>
<li><strong>核心要求</strong>：客戶明示「不得送第三方 AI 服務」、本地是預設選擇。</li>
<li><strong>不夠的地方</strong>：本地推論只保證模型呼叫不出去、要 audit 整條資料流（IDE telemetry、雲端同步、plugin 行為）。</li>
<li><strong>常見的事故</strong>：以為 Ollama 跑就安全、但 Cursor / Copilot 同時開著還送 prompt 給自家 service、NDA 已穿透。</li>
<li><strong>強化做法</strong>：NDA 客戶程式碼專案開獨立 IDE workspace、停雲端同步、移除第三方 plugin、明確隔離。</li>
</ul>
<h3 id="企業合規場景">企業合規場景</h3>
<p>不同規範保護的核心點不同、每條規範需對應到該規範要求的 control、避免用單一 mitigation 一網打盡的做法：</p>
<table>
  <thead>
      <tr>
          <th>規範</th>
          <th>核心保護點</th>
          <th>常見對位 control</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>HIPAA</td>
          <td>健康資料（PHI）的接觸與儲存</td>
          <td>雲端供應商簽 BAA（Business Associate Agreement）+ 加密 + audit log</td>
      </tr>
      <tr>
          <td>PCI-DSS</td>
          <td>信用卡 cardholder data 的網路 segmentation</td>
          <td>把處理卡號的環境隔離、避免任意 process 接觸</td>
      </tr>
      <tr>
          <td>SOC 2</td>
          <td>服務組織的安全 / 可用 / 機密性整體控制</td>
          <td>跨組織技術 + 流程控制、用第三方 audit 驗證</td>
      </tr>
      <tr>
          <td>GDPR</td>
          <td>資料主體的存取 / 刪除 / 移植權</td>
          <td>DPA（Data Processing Agreement）+ 資料分類 + 主體請求流程</td>
      </tr>
  </tbody>
</table>
<p>判讀流程：列合規要求 → 對應資料流節點 → 找出缺哪個保護 → 補上技術或合約控制。本地推論滿足「資料留在內部」這條、但通常仍需要 audit log、access control、retention policy 等補強；雲端 + BAA / DPA + zero-retention 是另一條合規路徑、看規範允許哪條再做選擇。</p>
<h3 id="個人--一般工作場景">個人 + 一般工作場景</h3>
<ul>
<li>多數場景隱私風險中等、合理控制就夠。</li>
<li>預設關掉明顯外洩管道（telemetry、雲端同步敏感內容）、敏感任務本地、其他雲端、就 cover 90% 場景。</li>
<li>過度設計反而生產力大幅下降、得不償失。</li>
</ul>
<p>判讀框架的核心不是「該不該做隱私」、是「該做到什麼程度」。NDA / 合規場景要做到嚴、個人場景做到合理、過度都是浪費。</p>
<h2 id="常見的隱私邊界穿透">常見的隱私邊界穿透</h2>
<p>下列五個穿透模式都符合「位置看似安全、資料流卻外洩」的 pattern、即使用本地推論仍會破隱私：</p>
<h3 id="ide-雲端同步">IDE 雲端同步</h3>
<p>VS Code、JetBrains 系列預設可能開 settings sync、把對話歷史、recent files、command history 同步到雲。對話歷史尤其敏感——可能含 prompt 跟 LLM 回應全文。</p>
<p>判讀訊號：登入帳號後、跨機器 settings 自動同步——這條 pipe 通常也帶其他資料。</p>
<p>緩解：明確查看 sync 範圍、敏感場景關閉 sync 或開選擇性 sync（只同步配置、不同步歷史）。</p>
<h3 id="第三方-plugin-偷送-prompt">第三方 plugin 偷送 prompt</h3>
<p>裝 VS Code extension 時、權限模型較寬：理論上 plugin 能 access 整個 workspace、含 prompt 跟 LLM 回應。多數 plugin 安全、但供應鏈攻擊或惡意 plugin 存在。</p>
<p>判讀訊號：plugin 不是 verified publisher、下載量少、permission 列表廣。</p>
<p>緩解：敏感場景只用 verified plugin、定期 audit 已裝 plugin、移除不必要的。完整 tool use / MCP server 信任邊界見 <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>、IDE 場景的 prompt injection 攻擊面（codebase / 外部文件 / 剪貼簿）見 <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</a>。</p>
<h3 id="open-webui-對話歷史備份">Open WebUI 對話歷史備份</h3>
<p>Open WebUI（常見的本地 Web 對話介面、通常以 Docker 部署）把對話歷史存本機 SQLite、預設安全。但很多人把 <code>~/.openwebui</code> 放在 Dropbox / iCloud 同步目錄、歷史間接同步到雲。</p>
<p>判讀訊號：home directory 整個被雲端服務同步。</p>
<p>緩解：明確排除 LLM 相關目錄、或把 LLM 資料移到不被同步的位置。</p>
<h3 id="ollama_host0000-暴露區網"><code>OLLAMA_HOST=0.0.0.0</code> 暴露區網</h3>
<p>把 Ollama 從 <a href="/blog/llm/knowledge-cards/port-and-localhost/" data-link-title="Port 與 Localhost" data-link-desc="TCP port 與 listen address 如何決定 API server 的對外暴露範圍"><code>127.0.0.1</code></a> 改成 <code>0.0.0.0</code> 是常見配置（讓區網其他機器接）、但等於把本地 LLM 暴露在 LAN 上。風險視 LAN trust level 而定：純自家信任裝置的家用網路風險低、有 IoT / 訪客機 / 公共 Wi-Fi 的 LAN 環境風險顯著上升（IoT 裝置常被植入、預設要放在 untrusted segment、用 VLAN 或 firewall 隔離後再評估能否互通）。</p>
<p>判讀訊號：能從另一台機器 curl <code>&lt;你的 Mac IP&gt;:11434</code> 成功。</p>
<p>緩解：純自家信任裝置的 LAN 接受、混合 trust LAN 用防火牆規則限定 source IP、公共 Wi-Fi 改回 <code>127.0.0.1</code> 或用 SSH tunnel 隧道到遠端機器。完整綁定模式（loopback / LAN / reverse proxy + auth）跟誤開放後的後果見 <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>。</p>
<h3 id="ide-plugin-同時送雲">IDE Plugin 同時送雲</h3>
<p>Cursor 預設 telemetry 強、Copilot 本來就送 prompt 給 GitHub。即使在這些 IDE 內用 Continue.dev 接本地 Ollama、IDE 本身可能仍送 prompt 給自家 service。</p>
<p>判讀訊號：IDE 是「雲端 AI 為主」的工具、本地 LLM 接入只是附加功能。</p>
<p>緩解：敏感場景用「本地 AI 為主」的 IDE（如 VS Code + Continue.dev）、不用混合的雲端 IDE。跨 provider 切換的具體 routing 設計見 <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>。</p>
<h2 id="何時過時--何時不過時">何時過時 / 何時不過時</h2>
<p><strong>不會過時的部分</strong>：</p>
<ul>
<li>「資料流 thinking」對「位置 thinking」的優越性。</li>
<li>信任邊界的定義跟畫法。</li>
<li>物理保證 vs 合約保證的雙模型 framing。</li>
<li>零信任原則的四個套用實踐。</li>
<li>資料流分析的 5 步驟方法。</li>
<li>NDA / 合規 / 個人三類場景的判讀框架。</li>
</ul>
<p><strong>會變的部分</strong>：</p>
<ul>
<li>具體合規法規（GDPR、HIPAA、CCPA、各國新法會持續更新）。</li>
<li>特定工具的隱私行為（IDE / 雲端服務的 ToS、telemetry policy 會調整）。</li>
<li>雲端供應商的合約細節（BAA / DPA / SCC 條款會 evolve）。</li>
<li>「常見穿透模式」的具體例子（會隨工具生態變）。</li>
</ul>
<p>新工具、新法規、新雲端服務出來時、回到本章的方法重新跑一遍資料流分析、信任邊界評估——framework 不變、實例更新。</p>
<h2 id="下一步">下一步</h2>
<p>下一步：<a href="/blog/llm/01-local-llm-services/" data-link-title="模組一：本地 LLM 服務的安裝與應用" data-link-desc="Ollama、LM Studio、llama.cpp 的安裝與差異、VS Code &#43; Continue.dev 整合、模型選型與期望管理">模組一：本地 LLM 服務的安裝與應用</a>（Apple Silicon Mac）或 <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 調參">模組五：Windows / Linux + 獨立 GPU</a> 把心智模型落到實際操作。模組一 / 五跑穩之後、回到 <a href="/blog/llm/06-security/" data-link-title="模組六：本地 LLM 的安全與權限" data-link-desc="個人 dev 在自己機器上跑本地 LLM 的安全議題：模型供應鏈、推論伺服器綁定、tool use 副作用、prompt injection 在 IDE、跨雲端 / 本地資料邊界">模組六：本地 LLM 的安全與權限</a> 把本章建立的「資料流 thinking」「信任邊界」「物理 vs 合約保證」三組框架落到具體決策（伺服器綁定、tool use 權限、prompt injection、跨雲端 routing）。</p>
]]></content:encoded></item><item><title>0.8 Deterministic vs Fuzzy Engineering：軟體設計典範的位移</title><link>https://tarrragon.github.io/blog/llm/00-foundations/deterministic-vs-fuzzy-engineering/</link><pubDate>Thu, 14 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/llm/00-foundations/deterministic-vs-fuzzy-engineering/</guid><description>&lt;p>LLM 進到軟體工程的最大影響、不是「多了一個 API 可以呼叫」、而是軟體設計典範本身的位移（見 &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&lt;/a> 卡）。傳統軟體建立在 deterministic 假設上——同樣的 input 永遠對應同樣的 output、邏輯靠人類寫定、行為可以靠 test 鎖住。LLM 軟體則建立在 fuzzy 假設上——同樣的 input 在不同溫度、不同 sampling 下會給不同 output、邏輯是模型自己推、行為只能用統計方式驗證。&lt;/p>
&lt;p>這個位移影響的不只是「在某段程式裡呼叫 LLM」、而是整套設計思維：怎麼處理資料、怎麼定義「正確」、怎麼分解任務、怎麼版本控制、怎麼測試、怎麼除錯。本章把這個典範位移寫成跨應用都成立的心智模型、讓你在後續模組（特別是 &lt;a href="https://tarrragon.github.io/blog/llm/04-applications/" data-link-title="模組四：LLM 應用層原理" data-link-desc="Prompt 技術光譜、RAG、tool use、agent、應用層協議、人機協作、multi-agent、workflow 編排、eval 設計：跨工具不變的概念地圖">模組四 LLM 應用層&lt;/a>）讀到 RAG、agent、workflow pattern 時、知道自己在跟哪個典範打交道、該套哪一邊的設計直覺。&lt;/p>
&lt;h2 id="本章目標">本章目標&lt;/h2>
&lt;p>讀完本章後你能：&lt;/p>
&lt;ol>
&lt;li>區分一段程式碼是 deterministic 還是 fuzzy。&lt;/li>
&lt;li>列出兩個典範在四個維度（資料、邏輯、分解、實驗成本）的差異。&lt;/li>
&lt;li>判斷一個系統的哪段該 deterministic、哪段該 fuzzy。&lt;/li>
&lt;li>設計 fuzzy 邊界的 guardrail（schema / validator / HITL）。&lt;/li>
&lt;li>看到一個失敗案例、能定位是「典範用錯」還是「實作問題」。&lt;/li>
&lt;/ol>
&lt;h2 id="兩個典範的對照">兩個典範的對照&lt;/h2>
&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、form 欄位）&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 → 分佈、需 sample 多次才看見平均行為&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>分解原則&lt;/td>
 &lt;td>按職責 / 模組（monolith / microservice）&lt;/td>
 &lt;td>按角色 / agent（manager 思維：誰負責什麼任務）&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>測試方式&lt;/td>
 &lt;td>unit test、integration test、覆蓋率&lt;/td>
 &lt;td>eval、judge、distribution-level metric&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>除錯&lt;/td>
 &lt;td>step debugger、log、stack trace&lt;/td>
 &lt;td>trace、prompt diff、token-level inspection&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>版本控制&lt;/td>
 &lt;td>code diff 是行為差異的完整來源&lt;/td>
 &lt;td>code diff + prompt diff + model version 三者&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>實驗成本&lt;/td>
 &lt;td>高（改 code 要 review、可能影響穩定性）&lt;/td>
 &lt;td>低（改 prompt 即可、推翻重做便宜）&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>失敗模式&lt;/td>
 &lt;td>crash、wrong value、type error&lt;/td>
 &lt;td>hallucination、tone drift、partial completion&lt;/td>
 &lt;/tr>
 &lt;/tbody>
&lt;/table>
&lt;p>這張表是後續所有判讀的骨架。看到一段程式時、用這幾個維度自問「這段在哪個典範」、設計直覺自然分開。&lt;/p>
&lt;h2 id="為什麼這個位移是典範級不是只是換工具">為什麼這個位移是典範級、不是只是換工具&lt;/h2>
&lt;p>很多人把 LLM 當「多了一個 API」、結果是把 LLM 塞進 deterministic 設計框架裡、然後因為它「不夠 deterministic」而 frustrated。這個 framing 錯了。LLM 不是 deterministic 工具的下一代、是另一條工具線、需要另一套設計直覺。&lt;/p>
&lt;p>幾個容易踩的混淆：&lt;/p>
&lt;ul>
&lt;li>&lt;strong>把 LLM 行為當 bug 修&lt;/strong>：模型輸出不穩定、想用更多 &lt;code>if&lt;/code> 把它「夾」回固定行為。這條路會走到死巷——當 prompt 越夾越窄、模型反而開始失去原有能力。正確方向是讓邊界本身可以容忍變化（schema validation + retry、distribution metric、HITL）。&lt;/li>
&lt;li>&lt;strong>用 deterministic 的 test 思維測 LLM&lt;/strong>：寫了一個「input X 應該得到 output Y」的單元測試、期望 byte-exact match。LLM 行為是分佈、即使 temperature=0、prompt brittleness 也讓單次測試結果不穩。Fuzzy 系統的測試是「在 N 次採樣中、output 落在期望範圍內的比例」、或「分佈級別 metric」、不是「精確等於某 string」。&lt;/li>
&lt;li>&lt;strong>用 deterministic 的 code review 審 LLM-generated code&lt;/strong>：要求 generated code 完全符合 style guide、結果耗在 nitpick 而不是行為正確性。LLM 生成是 fuzzy 過程、review 焦點該是「功能對 + 安全 + 可讀」、style 交給 linter / formatter 後處理。&lt;/li>
&lt;/ul>
&lt;p>典範位移的真正意涵：&lt;strong>設計時就承認 fuzziness 存在、並圍繞它設計&lt;/strong>、不是假裝它不存在。&lt;/p></description><content:encoded><![CDATA[<p>LLM 進到軟體工程的最大影響、不是「多了一個 API 可以呼叫」、而是軟體設計典範本身的位移（見 <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</a> 卡）。傳統軟體建立在 deterministic 假設上——同樣的 input 永遠對應同樣的 output、邏輯靠人類寫定、行為可以靠 test 鎖住。LLM 軟體則建立在 fuzzy 假設上——同樣的 input 在不同溫度、不同 sampling 下會給不同 output、邏輯是模型自己推、行為只能用統計方式驗證。</p>
<p>這個位移影響的不只是「在某段程式裡呼叫 LLM」、而是整套設計思維：怎麼處理資料、怎麼定義「正確」、怎麼分解任務、怎麼版本控制、怎麼測試、怎麼除錯。本章把這個典範位移寫成跨應用都成立的心智模型、讓你在後續模組（特別是 <a href="/blog/llm/04-applications/" data-link-title="模組四：LLM 應用層原理" data-link-desc="Prompt 技術光譜、RAG、tool use、agent、應用層協議、人機協作、multi-agent、workflow 編排、eval 設計：跨工具不變的概念地圖">模組四 LLM 應用層</a>）讀到 RAG、agent、workflow pattern 時、知道自己在跟哪個典範打交道、該套哪一邊的設計直覺。</p>
<h2 id="本章目標">本章目標</h2>
<p>讀完本章後你能：</p>
<ol>
<li>區分一段程式碼是 deterministic 還是 fuzzy。</li>
<li>列出兩個典範在四個維度（資料、邏輯、分解、實驗成本）的差異。</li>
<li>判斷一個系統的哪段該 deterministic、哪段該 fuzzy。</li>
<li>設計 fuzzy 邊界的 guardrail（schema / validator / HITL）。</li>
<li>看到一個失敗案例、能定位是「典範用錯」還是「實作問題」。</li>
</ol>
<h2 id="兩個典範的對照">兩個典範的對照</h2>
<table>
  <thead>
      <tr>
          <th>維度</th>
          <th>Deterministic 軟體</th>
          <th>Fuzzy 軟體</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>資料形狀</td>
          <td>結構化（JSON、DB row、form 欄位）</td>
          <td>半結構化 / 非結構化（自由文字、圖像、音訊）</td>
      </tr>
      <tr>
          <td>邏輯來源</td>
          <td>人類寫死規則</td>
          <td>模型推論、依 prompt + context 浮動</td>
      </tr>
      <tr>
          <td>行為一致性</td>
          <td>同 input → 同 output</td>
          <td>同 input → 分佈、需 sample 多次才看見平均行為</td>
      </tr>
      <tr>
          <td>分解原則</td>
          <td>按職責 / 模組（monolith / microservice）</td>
          <td>按角色 / agent（manager 思維：誰負責什麼任務）</td>
      </tr>
      <tr>
          <td>測試方式</td>
          <td>unit test、integration test、覆蓋率</td>
          <td>eval、judge、distribution-level metric</td>
      </tr>
      <tr>
          <td>除錯</td>
          <td>step debugger、log、stack trace</td>
          <td>trace、prompt diff、token-level inspection</td>
      </tr>
      <tr>
          <td>版本控制</td>
          <td>code diff 是行為差異的完整來源</td>
          <td>code diff + prompt diff + model version 三者</td>
      </tr>
      <tr>
          <td>實驗成本</td>
          <td>高（改 code 要 review、可能影響穩定性）</td>
          <td>低（改 prompt 即可、推翻重做便宜）</td>
      </tr>
      <tr>
          <td>失敗模式</td>
          <td>crash、wrong value、type error</td>
          <td>hallucination、tone drift、partial completion</td>
      </tr>
  </tbody>
</table>
<p>這張表是後續所有判讀的骨架。看到一段程式時、用這幾個維度自問「這段在哪個典範」、設計直覺自然分開。</p>
<h2 id="為什麼這個位移是典範級不是只是換工具">為什麼這個位移是典範級、不是只是換工具</h2>
<p>很多人把 LLM 當「多了一個 API」、結果是把 LLM 塞進 deterministic 設計框架裡、然後因為它「不夠 deterministic」而 frustrated。這個 framing 錯了。LLM 不是 deterministic 工具的下一代、是另一條工具線、需要另一套設計直覺。</p>
<p>幾個容易踩的混淆：</p>
<ul>
<li><strong>把 LLM 行為當 bug 修</strong>：模型輸出不穩定、想用更多 <code>if</code> 把它「夾」回固定行為。這條路會走到死巷——當 prompt 越夾越窄、模型反而開始失去原有能力。正確方向是讓邊界本身可以容忍變化（schema validation + retry、distribution metric、HITL）。</li>
<li><strong>用 deterministic 的 test 思維測 LLM</strong>：寫了一個「input X 應該得到 output Y」的單元測試、期望 byte-exact match。LLM 行為是分佈、即使 temperature=0、prompt brittleness 也讓單次測試結果不穩。Fuzzy 系統的測試是「在 N 次採樣中、output 落在期望範圍內的比例」、或「分佈級別 metric」、不是「精確等於某 string」。</li>
<li><strong>用 deterministic 的 code review 審 LLM-generated code</strong>：要求 generated code 完全符合 style guide、結果耗在 nitpick 而不是行為正確性。LLM 生成是 fuzzy 過程、review 焦點該是「功能對 + 安全 + 可讀」、style 交給 linter / formatter 後處理。</li>
</ul>
<p>典範位移的真正意涵：<strong>設計時就承認 fuzziness 存在、並圍繞它設計</strong>、不是假裝它不存在。</p>
<h2 id="哪段該-deterministic哪段該-fuzzy">哪段該 Deterministic、哪段該 Fuzzy</h2>
<p>一個系統幾乎不會「全 deterministic」或「全 fuzzy」、實務上是混合。判讀「哪段該哪個」的決策框架：</p>
<table>
  <thead>
      <tr>
          <th>屬性</th>
          <th>偏 deterministic</th>
          <th>偏 fuzzy</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>行為定義</td>
          <td>規則可窮舉</td>
          <td>規則太多 / 邊界模糊</td>
      </tr>
      <tr>
          <td>失敗代價</td>
          <td>高（金錢、安全、不可逆）</td>
          <td>低（可 retry、可 fallback）</td>
      </tr>
      <tr>
          <td>解釋需求</td>
          <td>必須能解釋為什麼做這個決定</td>
          <td>解釋是 nice-to-have</td>
      </tr>
      <tr>
          <td>一致性需求</td>
          <td>必須 byte-exact 重現（auditing、test）</td>
          <td>統計上一致即可</td>
      </tr>
      <tr>
          <td>資料形狀</td>
          <td>結構化</td>
          <td>自由文字 / 多模態</td>
      </tr>
      <tr>
          <td>變化頻率</td>
          <td>規則穩定、長期不變</td>
          <td>需求 / 領域知識 / 用戶輸入快速變化</td>
      </tr>
      <tr>
          <td>邊界條件</td>
          <td>邊界清楚（valid / invalid 兩段式）</td>
          <td>邊界連續（差不多好 / 還行 / 不夠好）</td>
      </tr>
  </tbody>
</table>
<p>實務上一個 production LLM 應用的常見組合：</p>
<ul>
<li><strong>使用者輸入解析</strong>：偏 fuzzy（LLM 解意圖、parse 自由文字）。</li>
<li><strong>資料庫查詢 / 更新</strong>：偏 deterministic（SQL、API、schema validation）。</li>
<li><strong>業務規則檢查</strong>（如「能否退款」「能否變更地址」）：偏 deterministic（policy as code）。</li>
<li><strong>回應草稿生成</strong>：偏 fuzzy（LLM 寫 email、考慮語氣）。</li>
<li><strong>發送 / 寫入動作</strong>：偏 deterministic（API call、template render）。</li>
</ul>
<p>這個混合不是隨機、是按上述決策框架推出來的。LLM 強在「理解模糊輸入」跟「生成有風格的輸出」、其餘部分能 deterministic 就 deterministic。</p>
<h3 id="反模式典範用錯的訊號">反模式：典範用錯的訊號</h3>
<ul>
<li><strong>Deterministic 的需求硬用 fuzzy 解</strong>：例如用 LLM 算稅金、然後用 retry + LLM judge 校驗。這條路的成本跟錯誤率都遠高於直接寫 deterministic 規則。判讀訊號：能用 30 行 code 寫死的規則、不要 LLM。</li>
<li><strong>Fuzzy 的需求硬用 deterministic 解</strong>：例如用 regex 解析自由文字客服訊息、然後維護一個越來越長的 case list。判讀訊號：規則 list 每週都在加新 case、加完還是漏、就該換 fuzzy。</li>
<li><strong>邊界用錯</strong>：把 deterministic 的部分塞進 prompt（如「請計算 9.32 × 47 並退款」）、或把 fuzzy 的部分塞進 code（如 <code>if user_intent == &quot;refund&quot;</code>）。前者讓 LLM 出算術錯、後者讓 code 漏 case。判讀訊號：prompt 在做算術 / 字串解析、或 code 在做意圖分類、就該重切。</li>
</ul>
<h2 id="fuzzy-邊界的-guardrail-設計">Fuzzy 邊界的 Guardrail 設計</h2>
<p>承認 fuzziness 存在後、設計重點轉成「邊界要怎麼包」。Guardrail 是 deterministic 包 fuzzy 的設計模式、防止 fuzzy 行為溢出到不該影響的地方。</p>
<p>四種常見 guardrail：</p>
<h3 id="schema-validation">Schema validation</h3>
<p>LLM 輸出被強制符合某個 schema（JSON schema、Pydantic model、TypeScript type）。不符合就 retry 或 fallback。</p>
<p>適用：LLM 結果要直接餵給下游 deterministic 系統（API、DB、UI）。</p>
<p>實作位置：LLM call 之後、下游 system 之前。</p>
<p>失敗模式：schema 對了但語意錯（structurally valid、semantically wrong）——這層 guardrail 接不住、要加 semantic check。</p>
<h3 id="output-validator">Output validator</h3>
<p>對 LLM 輸出跑語意驗證、不是只看 schema。例：生成的 email 不能包含未經授權的折扣承諾、生成的 code 不能呼叫 deprecated API。</p>
<p>適用：LLM 輸出有「該做 / 不該做」的清單。</p>
<p>實作位置：LLM call 之後、deliver 之前。可以是 deterministic check（regex、AST 分析）、可以是另一個 LLM judge（見 <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>）。</p>
<p>失敗模式：validator 自己 hallucinate（如果是 LLM judge）、或漏 case（如果是 deterministic check）。混用兩種比較穩。</p>
<h3 id="action-gating">Action gating</h3>
<p>LLM 想做高代價動作前、強制走人類確認或外部驗證。例：寫 production DB 前要 human approval、發 email 前要 dry-run 給內部 review、執行 shell 前要看到 diff。</p>
<p>適用：副作用範圍大、失敗不可逆。對應 <a href="/blog/llm/04-applications/agent-architecture/" data-link-title="4.4 Agent 架構原理" data-link-desc="Agent loop 結構、失敗模式、什麼任務適合 vs 不適合、跟人類審查的協作模型">4.4 agent 架構</a> 的 step-by-step approval / HITL 協作模型。</p>
<p>實作位置：tool layer、不是 prompt layer。Prompt 「請小心」是不夠的、靠 tool 本身不執行才有保證。</p>
<p>失敗模式：人類疲勞（rubber-stamp approval）、確認流程變橡皮圖章。設計時要讓 high-risk 跟 low-risk 動作走不同 gate、不要全部要人類確認、否則人類會關掉腦袋。</p>
<h3 id="distribution-monitoring">Distribution monitoring</h3>
<p>不在 single call 層擋、而是看 LLM 行為的分佈。例：每天客服回應的「拒絕率」「退款承諾率」、跑 alert；新 prompt 上線後追 token 用量、語氣 polarity、user satisfaction 的 baseline 漂移。</p>
<p>適用：行為層面的 silent drift（個別 call 看不出問題、加總起來偏掉）。</p>
<p>實作位置：production observability、trace pipeline（見 <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>）。</p>
<p>失敗模式：baseline 沒先建、新 prompt 上線後不知道「正常範圍」是什麼、alert 無基準。</p>
<h3 id="四種-guardrail-怎麼選">四種 guardrail 怎麼選</h3>
<p>順序通常是：schema validation 最便宜先上、output validator 看內容風險再加、action gating 看不可逆性決定、distribution monitoring 是長期經營必備。</p>
<p>混用比例：一個成熟的 production LLM 應用通常四種都有、但分擔不同 risk class。輕量 query 只走 schema、會寫資料的走 schema + validator + gating、會影響多人的走全套加 monitoring。</p>
<h2 id="實驗成本的位移">實驗成本的位移</h2>
<p>Deterministic 軟體的實驗成本高、改 code 要 PR review、要跑 CI、要考慮回退、所以團隊文化是「想清楚再寫」。Fuzzy 軟體的實驗成本低——改 prompt 一行、跑兩個 case、就能看新行為——所以更接近「快速試、不行就丟」。</p>
<p>這個位移對工程師的工作方式有實質影響：</p>
<ul>
<li><strong>Throw-away code 更可接受</strong>：原本「寫了就要維護」、現在「先試、不行就重來」。</li>
<li><strong>Prompt 是 source、但生命週期不一樣</strong>：跟 code 一樣 version control（見 <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 取捨">4.10 衍生產物管理</a>）、但 iteration 速度比 code 快一個量級。</li>
<li><strong>Eval 比 unit test 重要</strong>：unit test 鎖行為、但 fuzzy 行為本來就會變、eval 看「行為分佈是否在期望範圍」才是有用的測試。</li>
<li><strong>失敗的歸因分層</strong>：壞掉時要問「是 prompt 問題、model 問題、context 問題、tool 問題、還是 deterministic glue 的 bug」——deterministic 軟體的歸因比較單一、fuzzy 軟體要分這幾層查。</li>
</ul>
<p>這個位移是雙面刃。便宜實驗讓 iteration 快、但也讓 prompt / config / 行為快速分裂、production 跑著的東西跟 git 上看到的東西可能不一致。Mitigation 是 prompt template 上 version control、prompt diff 進 CI、production behavior 進 distribution monitoring。</p>
<h2 id="跟-agent--workflow-設計的關係">跟 Agent / Workflow 設計的關係</h2>
<p>Agent 跟 multi-call workflow 是「fuzzy 軟體」最複雜的型態。<a href="/blog/llm/04-applications/agent-architecture/" data-link-title="4.4 Agent 架構原理" data-link-desc="Agent loop 結構、失敗模式、什麼任務適合 vs 不適合、跟人類審查的協作模型">4.4 agent 架構</a> 列出 agent 的三大失敗模式（context drift / goal drift / tool misread）、本質上都是 fuzzy 行為在多步累積後溢出 guardrail。</p>
<p>這個 framing 對 agent 設計的啟示：</p>
<ul>
<li><strong>Loop 的每一步都是一個 fuzzy 邊界</strong>：每步都要決定 schema / validator / gating / monitoring 的組合。</li>
<li><strong>越多步累積、越需要 deterministic checkpoint</strong>：「跑 10 步 fuzzy 推理、最後一步寫 DB」是高風險、要在中間插 deterministic verification。</li>
<li><strong>Termination 是 deterministic 邊界</strong>：靠模型自己說「完成了」是純 fuzzy、容易失控（見 <a href="/blog/llm/04-applications/agent-architecture/" data-link-title="4.4 Agent 架構原理" data-link-desc="Agent loop 結構、失敗模式、什麼任務適合 vs 不適合、跟人類審查的協作模型">4.4 termination 條件</a>）。混用 step cap、cost cap、external validation 是 deterministic guardrail 包 fuzzy loop 的標準做法。</li>
</ul>
<h2 id="何時過時--何時不過時">何時過時 / 何時不過時</h2>
<p><strong>不會過時的部分</strong>：</p>
<ul>
<li>兩個典範的四維對照（資料、邏輯、行為一致性、實驗成本）。</li>
<li>「哪段該 deterministic / 哪段該 fuzzy」的決策框架。</li>
<li>四種 guardrail 的分類跟組合原則。</li>
<li>Fuzzy 邊界要包 deterministic、不是反過來的設計直覺。</li>
</ul>
<p><strong>會變的部分</strong>：</p>
<ul>
<li>具體 schema 工具（Pydantic、Zod、各家 framework 的 typed output API）。</li>
<li>具體 LLM-as-judge 平台跟方法（見 <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</a>）。</li>
<li>各家 framework 的 guardrail SDK（隨工具世代換）。</li>
<li>Fuzzy / deterministic 的邊界位置會隨模型能力移動——模型越強、能 fuzzy 處理的範圍越大、但「該包 guardrail」的原則不變。</li>
</ul>
<h2 id="下一章">下一章</h2>
<p>下一章：<a href="/blog/llm/01-local-llm-services/" data-link-title="模組一：本地 LLM 服務的安裝與應用" data-link-desc="Ollama、LM Studio、llama.cpp 的安裝與差異、VS Code &#43; Continue.dev 整合、模型選型與期望管理">模組一 本地 LLM 服務</a> 進入工具層、或跳到 <a href="/blog/llm/04-applications/" data-link-title="模組四：LLM 應用層原理" data-link-desc="Prompt 技術光譜、RAG、tool use、agent、應用層協議、人機協作、multi-agent、workflow 編排、eval 設計：跨工具不變的概念地圖">模組四 LLM 應用層</a> 看這個典範怎麼落到 RAG / agent / workflow 設計。Agent 設計怎麼把 fuzzy / deterministic 邊界體現在 loop 結構上見 <a href="/blog/llm/04-applications/agent-architecture/" data-link-title="4.4 Agent 架構原理" data-link-desc="Agent loop 結構、失敗模式、什麼任務適合 vs 不適合、跟人類審查的協作模型">4.4 agent 架構</a>、人類介入點的設計選擇見 <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>、跨多 call workflow 的 fuzzy 邊界設計見 <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 編排模式</a>。</p>
]]></content:encoded></item><item><title>LLM 寫 code 工程實務指南：從心智模型到應用架構</title><link>https://tarrragon.github.io/blog/llm/</link><pubDate>Tue, 12 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/llm/</guid><description>&lt;p>本指南的核心目標是把「LLM 在寫 code 工作流的完整工程地圖」拆成可決策、可實作、可期望管理的工程問題。範圍覆蓋四條讀者旅程：(1) 在自己機器跑本地 LLM 寫 code 的最短可行路徑（Mac 或 PC）、(2) 想懂 LLM 內部運作機制（數學 + 理論基礎）、(3) 想做 LLM 應用開發（RAG / agent / tool use / VLM / benchmarking / 靜態 deployment）、(4) 關心 LLM 工作流的安全議題（本地 dev 視角 + 靜態網站視角）。網路上的 LLM 文章常把推論框架、加速技巧、應用模式、安全議題混為一談；本指南先把這些名詞放回正確的層級、再回答各層的具體取捨。&lt;/p>
&lt;p>本指南預設讀者已經會用過雲端 LLM（ChatGPT、Claude）、熟悉終端機操作、想以工程視角理解 LLM。&lt;strong>寫 code 場景是主要使用例、但模組二 / 三 / 四 / 六多數章節跨場景通用&lt;/strong>：想懂 reasoning model / RAG / embedding model 內部、即使不裝本地 LLM 也能讀。硬體前提分兩條路線：Apple Silicon Mac（M1 ~ M4、統一記憶體）走模組一；Windows / Linux + 獨立 GPU（NVIDIA / AMD、獨立 VRAM + 系統 RAM）走模組五。文章不販賣 LLM 焦慮、也不誇大本地能取代雲端的程度；它的責任是給每條讀者旅程的最短可行路徑、並標出每個階段的取捨。&lt;/p>
&lt;p>模組零（心智模型）是所有讀者旅程的共同前置。模組一跟模組五是「裝本地 LLM」的兩條硬體路線、依平台選一條；想懂底層走模組二跟模組三（跟硬體無關、含 reasoning model / speculative decoding 等推論細節）；想看 LLM 作為系統元件走模組四（12 章涵蓋 RAG、tool use、agent、應用層協議、workflow、production resource、long context、embedding model、benchmarking、vision、靜態 deployment）；本地工作流跑穩想看安全議題走模組六（個人 dev 視角的供應鏈、伺服器綁定、tool use 權限、prompt injection、跨雲端邊界、production routing）。&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;/td>
 &lt;td>本地 vs 雲端的差異、為何 LLM 生字慢、三層架構（介面 / 伺服器 / 模型）、&lt;a href="https://tarrragon.github.io/blog/llm/00-foundations/openai-compatible-api/" data-link-title="0.3 OpenAI 相容 API" data-link-desc="為什麼幾乎所有本地 LLM 工具不用改就能切到本地：背後是同一套 API 形狀">OpenAI 相容 API&lt;/a>&lt;/td>
 &lt;td>雲端 GPU 租用、AGI 預測&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>術語澄清&lt;/td>
 &lt;td>&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，疊加而非互斥">MLX&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，疊加而非互斥">MTP&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，疊加而非互斥">oMLX&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;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/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/moe-cpu-offload/" data-link-title="MoE CPU 卸載" data-link-desc="把 Mixture-of-Experts 模型不活躍的專家層權重放在系統 RAM、用到再走 PCIe 拉回 GPU、讓有限 VRAM 跑得了更大模型">MoE CPU 卸載&lt;/a>&lt;/td>
 &lt;td>post-training fine-tuning 細節&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>Mac 硬體現實&lt;/td>
 &lt;td>&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;/td>
 &lt;td>雲端 GPU 租用、資料中心訓練&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>PC 硬體現實&lt;/td>
 &lt;td>&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 把兩個世界連起來">VRAM + RAM 分層預算&lt;/a>、MoE 專家層 CPU 卸載、KV cache 量化、PCIe 頻寬限制&lt;/td>
 &lt;td>多卡 NVLink、資料中心級分散式推論&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>本地推論伺服器&lt;/td>
 &lt;td>&lt;a href="https://tarrragon.github.io/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&lt;/a>、&lt;a href="https://tarrragon.github.io/blog/llm/01-local-llm-services/lm-studio/" data-link-title="1.1 LM Studio：GUI 探索模型" data-link-desc="GUI 取向的本地推論伺服器：內建模型瀏覽器、speculative decoding 設定面板、適合探索新模型">LM Studio&lt;/a>、&lt;a href="https://tarrragon.github.io/blog/llm/01-local-llm-services/llama-cpp/" data-link-title="1.2 llama.cpp：底層推論引擎" data-link-desc="GGUF 格式、量化、MTP 仍 beta；多數讀者不需要直接接觸，Ollama 已經包好">llama.cpp&lt;/a>（Mac + PC 通用）&lt;/td>
 &lt;td>vLLM、TGI、Triton 等資料中心級 inference server&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>編輯器整合&lt;/td>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/llm/01-local-llm-services/vscode-continue-integration/" data-link-title="1.3 VS Code &amp;#43; Continue.dev 整合" data-link-desc="安裝 Continue 擴充套件、config.json 設定、Cmd&amp;#43;L 對話 / Cmd&amp;#43;I 行內編輯快捷鍵">Continue.dev + VS Code&lt;/a>、Cursor 對應關係&lt;/td>
 &lt;td>JetBrains 全套整合、Vim / Emacs 進階 plugin&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>模型挑選&lt;/td>
 &lt;td>&lt;a href="https://tarrragon.github.io/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 的取捨與適用情境">coding 場景的模型優先順序&lt;/a>、量化等級對體感影響&lt;/td>
 &lt;td>benchmark 跑分方法論的完整推導&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>期望管理&lt;/td>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/llm/01-local-llm-services/expectation-management/" data-link-title="1.5 期望管理：本地 LLM 的擅長領域與分工" data-link-desc="本地 LLM 是免費的初階 pair programmer：辨識它的擅長領域、跟雲端旗艦做結構性分工">本地 LLM 的擅長領域與分工&lt;/a>、混用雲端的時機&lt;/td>
 &lt;td>LLM 通用能力評估、AGI 預測&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>數學基礎&lt;/td>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/llm/02-math-foundations/linear-algebra-for-llm/" data-link-title="2.0 線性代數：向量、矩陣、空間" data-link-desc="LLM 內部運算的基底：向量、矩陣、向量空間、內積、norm、矩陣乘法的角色">線性代數&lt;/a>、&lt;a href="https://tarrragon.github.io/blog/llm/02-math-foundations/probability-and-information/" data-link-title="2.1 機率與資訊論" data-link-desc="LLM 輸出的本質是機率分佈：softmax、cross-entropy、KL divergence、perplexity 在訓練與推論中的角色">機率與資訊論&lt;/a>、&lt;a href="https://tarrragon.github.io/blog/llm/02-math-foundations/calculus-and-optimization/" data-link-title="2.2 微積分與最佳化" data-link-desc="從 gradient、chain rule 到 SGD / Adam：LLM 訓練如何更新數十億參數">最佳化&lt;/a>、&lt;a href="https://tarrragon.github.io/blog/llm/02-math-foundations/numerical-precision/" data-link-title="2.3 數值精度與量化的數學依據" data-link-desc="fp32 / bf16 / fp16 / int8 / int4 的差別、量化能省哪些 bits、品質衰減從哪裡來">數值精度&lt;/a> 在 LLM 中的角色&lt;/td>
 &lt;td>完整數學證明、測度論等屬於數學系範圍的主題&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>理論基礎&lt;/td>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/llm/03-theoretical-foundations/neural-network-basics/" data-link-title="3.0 神經網路基礎" data-link-desc="從單一 neuron 到 multi-layer：weights、activation function、forward / backward pass 的角色">神經網路&lt;/a>、&lt;a href="https://tarrragon.github.io/blog/llm/03-theoretical-foundations/embedding-spaces/" data-link-title="3.1 Embedding 空間" data-link-desc="token 怎麼變成向量、為什麼相似 token 在向量空間中靠近、embedding 是怎麼學出來的">embedding&lt;/a>、&lt;a href="https://tarrragon.github.io/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 的核心運算">attention&lt;/a>、&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&lt;/a>、&lt;a href="https://tarrragon.github.io/blog/llm/03-theoretical-foundations/training-pipeline/" data-link-title="3.4 訓練流程：pre-train → SFT → RLHF" data-link-desc="LLM 的三階段訓練：預訓練、指令微調、人類反饋強化學習；各階段目標與最新替代方案">訓練流程&lt;/a>、&lt;a href="https://tarrragon.github.io/blog/llm/03-theoretical-foundations/sampling-and-decoding/" data-link-title="3.5 Sampling 與 Decoding 策略" data-link-desc="Greedy、beam search、top-k、top-p、temperature、min-p：模型輸出後怎麼挑下一個 token">sampling&lt;/a>、&lt;a href="https://tarrragon.github.io/blog/llm/03-theoretical-foundations/tokenization-algorithms/" data-link-title="3.6 Tokenization：BPE、SentencePiece、Tiktoken" data-link-desc="把文字切成 token 的算法：為什麼不同模型切出不同 token 數、tokenizer 選擇對能力的影響">tokenization&lt;/a>、&lt;a href="https://tarrragon.github.io/blog/llm/03-theoretical-foundations/cross-language-tokenization/" data-link-title="3.7 跨語言場景的 tokenizer 與訓練分佈原理" data-link-desc="為什麼模型對不同語言表現不一致：tokenizer &amp;#43; 訓練資料分佈雙因素、語言選擇取捨">跨語言原理&lt;/a>&lt;/td>
 &lt;td>多模態擴展、最新研究細節交給 Stanford CS25&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>應用層原理&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 失敗的根本原因">RAG&lt;/a>、&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 表現崩潰">Tool use&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 不適合、跟人類審查的協作模型">Agent 架構&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 協議，三者的層級差異與組合方式">應用層協議&lt;/a>、&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 編排&lt;/a>、&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 的設計取捨">Production resource&lt;/a>、&lt;a href="https://tarrragon.github.io/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 取捨">Artifact 管理&lt;/a>&lt;/td>
 &lt;td>具體 framework 教學（LangChain / LlamaIndex）、prompt engineering&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>進階理論&lt;/td>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/llm/03-theoretical-foundations/reasoning-models/" data-link-title="3.8 Reasoning models：test-time compute paradigm" data-link-desc="Chain-of-thought 從 prompting 技巧演化成訓練 paradigm、reasoning model 的內部運作、本地可跑的選項與適用任務">Reasoning models&lt;/a>（o1 / R1 / QwQ 風格）、&lt;a href="https://tarrragon.github.io/blog/llm/03-theoretical-foundations/speculative-decoding-internals/" data-link-title="3.9 Speculative decoding 內部：drafter / 驗證 / 加速上限" data-link-desc="speculative decoding 的演算法細節、drafter 跟 target 怎麼配對、acceptance rate 怎麼決定實際加速、MTP 跟 EAGLE 等變體">Speculative decoding 內部&lt;/a>（drafter / MTP / EAGLE）&lt;/td>
 &lt;td>完整 paper 推導、最新研究 frontier&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>進階應用&lt;/td>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/llm/04-applications/long-context-engineering/" data-link-title="4.11 Long context engineering" data-link-desc="128K / 1M context 模型怎麼用：claimed vs effective context、lost-in-the-middle、context 設計策略、Long context vs RAG 取捨">Long context engineering&lt;/a>、&lt;a href="https://tarrragon.github.io/blog/llm/04-applications/embedding-model-internals/" data-link-title="4.12 Embedding model 內部：訓練、選型、in-domain fine-tune" data-link-desc="Embedding model 怎麼訓練（contrastive learning &amp;#43; hard negative mining）、怎麼挑（MTEB / 大小 / domain）、何時該自己 fine-tune">Embedding model 內部&lt;/a>、&lt;a href="https://tarrragon.github.io/blog/llm/04-applications/benchmarking-and-evaluation/" data-link-title="4.14 Benchmarking 與評估方法論" data-link-desc="判讀 model card benchmark 數字、做自己工作流的 in-house benchmark、量測本地推論速度的完整方法論">Benchmarking&lt;/a>、&lt;a href="https://tarrragon.github.io/blog/llm/04-applications/vision-in-coding-workflow/" data-link-title="4.15 Vision in coding workflow：本地 VLM 怎麼接寫 code" data-link-desc="VLM 在 coding 工作流的 use cases、本地 VLM 選型、跟雲端 VLM 的分工、Continue.dev / Ollama 整合現狀">Vision in coding&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">靜態 / serverless RAG deployment&lt;/a>&lt;/td>
 &lt;td>完整 LangChain / LlamaIndex 教學&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>Fine-tuning&lt;/td>
 &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;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/catastrophic-forgetting/" data-link-title="Catastrophic Forgetting" data-link-desc="Fine-tune 模型時、新訓練資料覆蓋掉原本學到的能力的現象、LoRA / 資料 mixing 是主要緩解">catastrophic forgetting&lt;/a>）+ &lt;a href="https://tarrragon.github.io/blog/llm/01-local-llm-services/hands-on/local-fine-tuning/" data-link-title="Hands-on：用 QLoRA 在本機 fine-tune coding 模型" data-link-desc="Apple Silicon Mac / PC 獨立 GPU 上跑 QLoRA fine-tune 的完整流程：環境、資料、訓練、evaluation、合併、部署到 Ollama">本機 hands-on&lt;/a>&lt;/td>
 &lt;td>完整資料工程、large-scale distributed fine-tune&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>隱私 / 安全&lt;/td>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/llm/00-foundations/privacy-data-flow/" data-link-title="0.7 隱私 / 資安的資料流原理" data-link-desc="從「位置」到「資料流」的思考升級：信任邊界、合約模型、零信任原則套用到 LLM 工作流">隱私資料流&lt;/a>、&lt;a href="https://tarrragon.github.io/blog/llm/06-security/" data-link-title="模組六：本地 LLM 的安全與權限" data-link-desc="個人 dev 在自己機器上跑本地 LLM 的安全議題：模型供應鏈、推論伺服器綁定、tool use 副作用、prompt injection 在 IDE、跨雲端 / 本地資料邊界">本地 dev 安全模組&lt;/a>（供應鏈 / 伺服器綁定 / tool use / prompt injection / 跨雲端邊界 / production routing）、&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">靜態網站 RAG 資安&lt;/a>、&lt;a href="https://tarrragon.github.io/blog/llm/01-local-llm-services/troubleshooting/" data-link-title="1.7 排錯方法論：用三層架構做故障定位" data-link-desc="故障定位的分層思考、症狀到層級的對應反射、log 在三層的角色差異、最小可重現的縮減策略">排錯方法論&lt;/a>&lt;/td>
 &lt;td>企業合規逐條檢核、SOC 2 / HIPAA 流程&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>進一步學習&lt;/td>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/llm/02-math-foundations/going-deeper-math/" data-link-title="2.4 想學更深：推薦公開課程" data-link-desc="MIT、Stanford、Harvard 等公開課程：數學基礎跟 LLM 預備知識的完整學習路線">數學公開課推薦&lt;/a>、&lt;a href="https://tarrragon.github.io/blog/llm/03-theoretical-foundations/going-deeper-theory/" data-link-title="3.11 想學更深：推薦公開課程" data-link-desc="Karpathy、Stanford CS224N / CS25 / CS336、DeepLearning.AI、Hugging Face：LLM 理論深入學習的完整路線">LLM 理論公開課推薦&lt;/a>&lt;/td>
 &lt;td>（交給推薦的課程跟書籍）&lt;/td>
 &lt;/tr>
 &lt;/tbody>
&lt;/table>
&lt;h2 id="學習路線">學習路線&lt;/h2>
&lt;p>本指南分成七個模組加一組前置卡片（111 張）。讀者依目的選讀、不需要從頭到尾全讀：&lt;/p></description><content:encoded><![CDATA[<p>本指南的核心目標是把「LLM 在寫 code 工作流的完整工程地圖」拆成可決策、可實作、可期望管理的工程問題。範圍覆蓋四條讀者旅程：(1) 在自己機器跑本地 LLM 寫 code 的最短可行路徑（Mac 或 PC）、(2) 想懂 LLM 內部運作機制（數學 + 理論基礎）、(3) 想做 LLM 應用開發（RAG / agent / tool use / VLM / benchmarking / 靜態 deployment）、(4) 關心 LLM 工作流的安全議題（本地 dev 視角 + 靜態網站視角）。網路上的 LLM 文章常把推論框架、加速技巧、應用模式、安全議題混為一談；本指南先把這些名詞放回正確的層級、再回答各層的具體取捨。</p>
<p>本指南預設讀者已經會用過雲端 LLM（ChatGPT、Claude）、熟悉終端機操作、想以工程視角理解 LLM。<strong>寫 code 場景是主要使用例、但模組二 / 三 / 四 / 六多數章節跨場景通用</strong>：想懂 reasoning model / RAG / embedding model 內部、即使不裝本地 LLM 也能讀。硬體前提分兩條路線：Apple Silicon Mac（M1 ~ M4、統一記憶體）走模組一；Windows / Linux + 獨立 GPU（NVIDIA / AMD、獨立 VRAM + 系統 RAM）走模組五。文章不販賣 LLM 焦慮、也不誇大本地能取代雲端的程度；它的責任是給每條讀者旅程的最短可行路徑、並標出每個階段的取捨。</p>
<p>模組零（心智模型）是所有讀者旅程的共同前置。模組一跟模組五是「裝本地 LLM」的兩條硬體路線、依平台選一條；想懂底層走模組二跟模組三（跟硬體無關、含 reasoning model / speculative decoding 等推論細節）；想看 LLM 作為系統元件走模組四（12 章涵蓋 RAG、tool use、agent、應用層協議、workflow、production resource、long context、embedding model、benchmarking、vision、靜態 deployment）；本地工作流跑穩想看安全議題走模組六（個人 dev 視角的供應鏈、伺服器綁定、tool use 權限、prompt injection、跨雲端邊界、production routing）。</p>
<h2 id="教材邊界">教材邊界</h2>
<table>
  <thead>
      <tr>
          <th>類型</th>
          <th>放在本指南</th>
          <th>不放在本指南</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>心智模型</td>
          <td>本地 vs 雲端的差異、為何 LLM 生字慢、三層架構（介面 / 伺服器 / 模型）、<a href="/blog/llm/00-foundations/openai-compatible-api/" data-link-title="0.3 OpenAI 相容 API" data-link-desc="為什麼幾乎所有本地 LLM 工具不用改就能切到本地：背後是同一套 API 形狀">OpenAI 相容 API</a></td>
          <td>雲端 GPU 租用、AGI 預測</td>
      </tr>
      <tr>
          <td>術語澄清</td>
          <td><a href="/blog/llm/00-foundations/mlx-mtp-omlx/" data-link-title="0.4 MLX / MTP / oMLX 的區別" data-link-desc="三個常被混為一談的術語：framework、加速技巧、特化 server，疊加而非互斥">MLX</a>、<a href="/blog/llm/00-foundations/mlx-mtp-omlx/" data-link-title="0.4 MLX / MTP / oMLX 的區別" data-link-desc="三個常被混為一談的術語：framework、加速技巧、特化 server，疊加而非互斥">MTP</a>、<a href="/blog/llm/00-foundations/mlx-mtp-omlx/" data-link-title="0.4 MLX / MTP / oMLX 的區別" data-link-desc="三個常被混為一談的術語：framework、加速技巧、特化 server，疊加而非互斥">oMLX</a>、<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/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/ttft/" data-link-title="TTFT" data-link-desc="Time To First Token：送出 prompt 到第一個 token 出現的等待時間">TTFT</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></td>
          <td>post-training fine-tuning 細節</td>
      </tr>
      <tr>
          <td>Mac 硬體現實</td>
          <td><a href="/blog/llm/00-foundations/hardware-memory-budget/" data-link-title="0.5 Apple Silicon 記憶體預算" data-link-desc="記憶體決定能跑什麼，Q4 量化下的可運作模型對照與系統保留">記憶體預算與模型大小</a>、量化選擇、首字延遲、風扇與功耗</td>
          <td>雲端 GPU 租用、資料中心訓練</td>
      </tr>
      <tr>
          <td>PC 硬體現實</td>
          <td><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 把兩個世界連起來">VRAM + RAM 分層預算</a>、MoE 專家層 CPU 卸載、KV cache 量化、PCIe 頻寬限制</td>
          <td>多卡 NVLink、資料中心級分散式推論</td>
      </tr>
      <tr>
          <td>本地推論伺服器</td>
          <td><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/lm-studio/" data-link-title="1.1 LM Studio：GUI 探索模型" data-link-desc="GUI 取向的本地推論伺服器：內建模型瀏覽器、speculative decoding 設定面板、適合探索新模型">LM Studio</a>、<a href="/blog/llm/01-local-llm-services/llama-cpp/" data-link-title="1.2 llama.cpp：底層推論引擎" data-link-desc="GGUF 格式、量化、MTP 仍 beta；多數讀者不需要直接接觸，Ollama 已經包好">llama.cpp</a>（Mac + PC 通用）</td>
          <td>vLLM、TGI、Triton 等資料中心級 inference server</td>
      </tr>
      <tr>
          <td>編輯器整合</td>
          <td><a href="/blog/llm/01-local-llm-services/vscode-continue-integration/" data-link-title="1.3 VS Code &#43; Continue.dev 整合" data-link-desc="安裝 Continue 擴充套件、config.json 設定、Cmd&#43;L 對話 / Cmd&#43;I 行內編輯快捷鍵">Continue.dev + VS Code</a>、Cursor 對應關係</td>
          <td>JetBrains 全套整合、Vim / Emacs 進階 plugin</td>
      </tr>
      <tr>
          <td>模型挑選</td>
          <td><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 的取捨與適用情境">coding 場景的模型優先順序</a>、量化等級對體感影響</td>
          <td>benchmark 跑分方法論的完整推導</td>
      </tr>
      <tr>
          <td>期望管理</td>
          <td><a href="/blog/llm/01-local-llm-services/expectation-management/" data-link-title="1.5 期望管理：本地 LLM 的擅長領域與分工" data-link-desc="本地 LLM 是免費的初階 pair programmer：辨識它的擅長領域、跟雲端旗艦做結構性分工">本地 LLM 的擅長領域與分工</a>、混用雲端的時機</td>
          <td>LLM 通用能力評估、AGI 預測</td>
      </tr>
      <tr>
          <td>數學基礎</td>
          <td><a href="/blog/llm/02-math-foundations/linear-algebra-for-llm/" data-link-title="2.0 線性代數：向量、矩陣、空間" data-link-desc="LLM 內部運算的基底：向量、矩陣、向量空間、內積、norm、矩陣乘法的角色">線性代數</a>、<a href="/blog/llm/02-math-foundations/probability-and-information/" data-link-title="2.1 機率與資訊論" data-link-desc="LLM 輸出的本質是機率分佈：softmax、cross-entropy、KL divergence、perplexity 在訓練與推論中的角色">機率與資訊論</a>、<a href="/blog/llm/02-math-foundations/calculus-and-optimization/" data-link-title="2.2 微積分與最佳化" data-link-desc="從 gradient、chain rule 到 SGD / Adam：LLM 訓練如何更新數十億參數">最佳化</a>、<a href="/blog/llm/02-math-foundations/numerical-precision/" data-link-title="2.3 數值精度與量化的數學依據" data-link-desc="fp32 / bf16 / fp16 / int8 / int4 的差別、量化能省哪些 bits、品質衰減從哪裡來">數值精度</a> 在 LLM 中的角色</td>
          <td>完整數學證明、測度論等屬於數學系範圍的主題</td>
      </tr>
      <tr>
          <td>理論基礎</td>
          <td><a href="/blog/llm/03-theoretical-foundations/neural-network-basics/" data-link-title="3.0 神經網路基礎" data-link-desc="從單一 neuron 到 multi-layer：weights、activation function、forward / backward pass 的角色">神經網路</a>、<a href="/blog/llm/03-theoretical-foundations/embedding-spaces/" data-link-title="3.1 Embedding 空間" data-link-desc="token 怎麼變成向量、為什麼相似 token 在向量空間中靠近、embedding 是怎麼學出來的">embedding</a>、<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 的核心運算">attention</a>、<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</a>、<a href="/blog/llm/03-theoretical-foundations/training-pipeline/" data-link-title="3.4 訓練流程：pre-train → SFT → RLHF" data-link-desc="LLM 的三階段訓練：預訓練、指令微調、人類反饋強化學習；各階段目標與最新替代方案">訓練流程</a>、<a href="/blog/llm/03-theoretical-foundations/sampling-and-decoding/" data-link-title="3.5 Sampling 與 Decoding 策略" data-link-desc="Greedy、beam search、top-k、top-p、temperature、min-p：模型輸出後怎麼挑下一個 token">sampling</a>、<a href="/blog/llm/03-theoretical-foundations/tokenization-algorithms/" data-link-title="3.6 Tokenization：BPE、SentencePiece、Tiktoken" data-link-desc="把文字切成 token 的算法：為什麼不同模型切出不同 token 數、tokenizer 選擇對能力的影響">tokenization</a>、<a href="/blog/llm/03-theoretical-foundations/cross-language-tokenization/" data-link-title="3.7 跨語言場景的 tokenizer 與訓練分佈原理" data-link-desc="為什麼模型對不同語言表現不一致：tokenizer &#43; 訓練資料分佈雙因素、語言選擇取捨">跨語言原理</a></td>
          <td>多模態擴展、最新研究細節交給 Stanford CS25</td>
      </tr>
      <tr>
          <td>應用層原理</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 失敗的根本原因">RAG</a>、<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 表現崩潰">Tool use</a>、<a href="/blog/llm/04-applications/agent-architecture/" data-link-title="4.4 Agent 架構原理" data-link-desc="Agent loop 結構、失敗模式、什麼任務適合 vs 不適合、跟人類審查的協作模型">Agent 架構</a>、<a href="/blog/llm/04-applications/application-protocols/" data-link-title="4.6 應用層協議：function calling / structured output / MCP" data-link-desc="三個常被混為一談的概念：模型能力、sampling 約束、server 協議，三者的層級差異與組合方式">應用層協議</a>、<a href="/blog/llm/04-applications/workflow-patterns/" data-link-title="4.7 Workflow 編排模式" data-link-desc="Pipeline / router / parallel / reflection：多 LLM call 組合的四種基本模式與退化條件">Workflow 編排</a>、<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 的設計取捨">Production resource</a>、<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 取捨">Artifact 管理</a></td>
          <td>具體 framework 教學（LangChain / LlamaIndex）、prompt engineering</td>
      </tr>
      <tr>
          <td>進階理論</td>
          <td><a href="/blog/llm/03-theoretical-foundations/reasoning-models/" data-link-title="3.8 Reasoning models：test-time compute paradigm" data-link-desc="Chain-of-thought 從 prompting 技巧演化成訓練 paradigm、reasoning model 的內部運作、本地可跑的選項與適用任務">Reasoning models</a>（o1 / R1 / QwQ 風格）、<a href="/blog/llm/03-theoretical-foundations/speculative-decoding-internals/" data-link-title="3.9 Speculative decoding 內部：drafter / 驗證 / 加速上限" data-link-desc="speculative decoding 的演算法細節、drafter 跟 target 怎麼配對、acceptance rate 怎麼決定實際加速、MTP 跟 EAGLE 等變體">Speculative decoding 內部</a>（drafter / MTP / EAGLE）</td>
          <td>完整 paper 推導、最新研究 frontier</td>
      </tr>
      <tr>
          <td>進階應用</td>
          <td><a href="/blog/llm/04-applications/long-context-engineering/" data-link-title="4.11 Long context engineering" data-link-desc="128K / 1M context 模型怎麼用：claimed vs effective context、lost-in-the-middle、context 設計策略、Long context vs RAG 取捨">Long context engineering</a>、<a href="/blog/llm/04-applications/embedding-model-internals/" data-link-title="4.12 Embedding model 內部：訓練、選型、in-domain fine-tune" data-link-desc="Embedding model 怎麼訓練（contrastive learning &#43; hard negative mining）、怎麼挑（MTEB / 大小 / domain）、何時該自己 fine-tune">Embedding model 內部</a>、<a href="/blog/llm/04-applications/benchmarking-and-evaluation/" data-link-title="4.14 Benchmarking 與評估方法論" data-link-desc="判讀 model card benchmark 數字、做自己工作流的 in-house benchmark、量測本地推論速度的完整方法論">Benchmarking</a>、<a href="/blog/llm/04-applications/vision-in-coding-workflow/" data-link-title="4.15 Vision in coding workflow：本地 VLM 怎麼接寫 code" data-link-desc="VLM 在 coding 工作流的 use cases、本地 VLM 選型、跟雲端 VLM 的分工、Continue.dev / Ollama 整合現狀">Vision in coding</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">靜態 / serverless RAG deployment</a></td>
          <td>完整 LangChain / LlamaIndex 教學</td>
      </tr>
      <tr>
          <td>Fine-tuning</td>
          <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> / <a href="/blog/llm/knowledge-cards/catastrophic-forgetting/" data-link-title="Catastrophic Forgetting" data-link-desc="Fine-tune 模型時、新訓練資料覆蓋掉原本學到的能力的現象、LoRA / 資料 mixing 是主要緩解">catastrophic forgetting</a>）+ <a href="/blog/llm/01-local-llm-services/hands-on/local-fine-tuning/" data-link-title="Hands-on：用 QLoRA 在本機 fine-tune coding 模型" data-link-desc="Apple Silicon Mac / PC 獨立 GPU 上跑 QLoRA fine-tune 的完整流程：環境、資料、訓練、evaluation、合併、部署到 Ollama">本機 hands-on</a></td>
          <td>完整資料工程、large-scale distributed fine-tune</td>
      </tr>
      <tr>
          <td>隱私 / 安全</td>
          <td><a href="/blog/llm/00-foundations/privacy-data-flow/" data-link-title="0.7 隱私 / 資安的資料流原理" data-link-desc="從「位置」到「資料流」的思考升級：信任邊界、合約模型、零信任原則套用到 LLM 工作流">隱私資料流</a>、<a href="/blog/llm/06-security/" data-link-title="模組六：本地 LLM 的安全與權限" data-link-desc="個人 dev 在自己機器上跑本地 LLM 的安全議題：模型供應鏈、推論伺服器綁定、tool use 副作用、prompt injection 在 IDE、跨雲端 / 本地資料邊界">本地 dev 安全模組</a>（供應鏈 / 伺服器綁定 / tool use / prompt injection / 跨雲端邊界 / production routing）、<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">靜態網站 RAG 資安</a>、<a href="/blog/llm/01-local-llm-services/troubleshooting/" data-link-title="1.7 排錯方法論：用三層架構做故障定位" data-link-desc="故障定位的分層思考、症狀到層級的對應反射、log 在三層的角色差異、最小可重現的縮減策略">排錯方法論</a></td>
          <td>企業合規逐條檢核、SOC 2 / HIPAA 流程</td>
      </tr>
      <tr>
          <td>進一步學習</td>
          <td><a href="/blog/llm/02-math-foundations/going-deeper-math/" data-link-title="2.4 想學更深：推薦公開課程" data-link-desc="MIT、Stanford、Harvard 等公開課程：數學基礎跟 LLM 預備知識的完整學習路線">數學公開課推薦</a>、<a href="/blog/llm/03-theoretical-foundations/going-deeper-theory/" data-link-title="3.11 想學更深：推薦公開課程" data-link-desc="Karpathy、Stanford CS224N / CS25 / CS336、DeepLearning.AI、Hugging Face：LLM 理論深入學習的完整路線">LLM 理論公開課推薦</a></td>
          <td>（交給推薦的課程跟書籍）</td>
      </tr>
  </tbody>
</table>
<h2 id="學習路線">學習路線</h2>
<p>本指南分成七個模組加一組前置卡片（111 張）。讀者依目的選讀、不需要從頭到尾全讀：</p>
<ul>
<li><strong>想用 Apple Silicon Mac 裝本地 LLM 寫 code</strong>：讀模組零 + 模組一（最短路徑）</li>
<li><strong>想用 Windows / Linux + 獨立 GPU 裝</strong>：讀模組零 + 模組五</li>
<li><strong>想懂 LLM 內部原理</strong>：模組二（數學） + 模組三（理論、含 reasoning models / speculative decoding）— 跟硬體無關</li>
<li><strong>想做 LLM 應用開發（含 RAG / agent / VLM / 靜態 deployment）</strong>：模組四（12 章、跨工具世代不變的原理）— 跟硬體無關</li>
<li><strong>想懂本地工作流的安全議題</strong>：模組一 / 五跑穩後接模組六（個人 dev 視角）</li>
<li><strong>想選 RAG 的 storage 方案（pickle / vector DB / hosted SaaS）</strong>：直接看 <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></li>
<li><strong>想在靜態網站加 RAG / 智能搜尋</strong>：直接看 <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 靜態 / serverless RAG deployment</a></li>
<li><strong>想在本機 fine-tune 模型</strong>：模組三 3.4 訓練流程原理 → <a href="/blog/llm/01-local-llm-services/hands-on/local-fine-tuning/" data-link-title="Hands-on：用 QLoRA 在本機 fine-tune coding 模型" data-link-desc="Apple Silicon Mac / PC 獨立 GPU 上跑 QLoRA fine-tune 的完整流程：環境、資料、訓練、evaluation、合併、部署到 Ollama">本機 QLoRA hands-on</a></li>
<li><strong>想跟最新進展接軌</strong>：讀完模組後進推薦的公開課程跟 paper（模組二 2.4 + 模組三 3.10）</li>
</ul>
<h3 id="前置知識卡片"><a href="/blog/llm/knowledge-cards/" data-link-title="Knowledge Cards" data-link-desc="用原子化卡片整理本地 LLM 寫 code 場景所需的概念詞彙">前置知識卡片</a></h3>
<p>用原子化卡片整理 <a href="/blog/llm/knowledge-cards/token/" data-link-title="Token" data-link-desc="LLM 處理文字時的最小單位：介於字元與單字之間">token</a>、<a href="/blog/llm/knowledge-cards/autoregressive/" data-link-title="Autoregressive" data-link-desc="LLM 一次生成一個 token、把已生成內容作為下一次輸入的架構">自回歸</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/quantization/" data-link-title="Quantization" data-link-desc="用較少 bits 表示模型權重：壓縮記憶體佔用、加快生字速度，代價是少量品質衰減">量化</a>、<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>、<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/inference-server/" data-link-title="Inference Server" data-link-desc="載入模型權重、處理 prompt、產生 token 的常駐 process">推論伺服器</a>、<a href="/blog/llm/knowledge-cards/openai-compatible-api/" data-link-title="OpenAI 相容 API" data-link-desc="本地推論伺服器跟雲端 OpenAI 共用的 API 形狀標準">OpenAI 相容 API</a>、<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/unified-memory/" data-link-title="Unified Memory Architecture" data-link-desc="Apple Silicon 讓 CPU / GPU / NE 共用同一塊記憶體：跑大模型的優勢來源">統一記憶體</a>、<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>、<a href="/blog/llm/knowledge-cards/context-window/" data-link-title="Context Window" data-link-desc="模型一次能處理的最大 token 數量：prompt 加生成的總和上限">context window</a>、<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> 等核心概念。章節文章專注情境推導、術語背景交由卡片維持一致。</p>
<h3 id="模組零基礎知識與心智模型"><a href="/blog/llm/00-foundations/" data-link-title="模組零：基礎知識與心智模型" data-link-desc="建立本地 LLM 的心智模型、釐清 MLX / MTP / oMLX 等常被混淆的術語、Apple Silicon 記憶體現實">模組零：基礎知識與心智模型</a></h3>
<p>整理本地 vs 雲端 LLM 的差異、自回歸架構與記憶體頻寬瓶頸、介面 / 伺服器 / 模型三層心智模型、OpenAI 相容 API 為何重要、MLX / MTP / oMLX 三個容易搞混的術語、Apple Silicon Mac 記憶體與模型大小的對應關係、判讀本地 LLM 資訊的五個框架。</p>
<h3 id="模組一本地-llm-服務的安裝與應用"><a href="/blog/llm/01-local-llm-services/" data-link-title="模組一：本地 LLM 服務的安裝與應用" data-link-desc="Ollama、LM Studio、llama.cpp 的安裝與差異、VS Code &#43; Continue.dev 整合、模型選型與期望管理">模組一：本地 LLM 服務的安裝與應用</a></h3>
<p>整理 Ollama、LM Studio、llama.cpp 三個主流推論伺服器的現況差異與安裝路徑、用 Continue.dev 把本地 LLM 接到 VS Code 的完整步驟、寫 code 場景下模型選型的優先順序、本地模型的期望管理、想進一步玩 coding agent、Web UI、產圖時的延伸方向。</p>
<h3 id="模組二llm-的數學基礎"><a href="/blog/llm/02-math-foundations/" data-link-title="模組二：LLM 的數學基礎" data-link-desc="整理 LLM 推論背後需要理解的線性代數、機率與資訊論、最佳化、數值精度等數學概念">模組二：LLM 的數學基礎</a></h3>
<p>整理 LLM 推論背後的數學工具：<a href="/blog/llm/02-math-foundations/linear-algebra-for-llm/" data-link-title="2.0 線性代數：向量、矩陣、空間" data-link-desc="LLM 內部運算的基底：向量、矩陣、向量空間、內積、norm、矩陣乘法的角色">線性代數</a>（向量、矩陣、空間）、<a href="/blog/llm/02-math-foundations/probability-and-information/" data-link-title="2.1 機率與資訊論" data-link-desc="LLM 輸出的本質是機率分佈：softmax、cross-entropy、KL divergence、perplexity 在訓練與推論中的角色">機率與資訊論</a>（softmax、cross-entropy、KL、perplexity）、<a href="/blog/llm/02-math-foundations/calculus-and-optimization/" data-link-title="2.2 微積分與最佳化" data-link-desc="從 gradient、chain rule 到 SGD / Adam：LLM 訓練如何更新數十億參數">微積分與最佳化</a>（gradient、SGD / Adam）、<a href="/blog/llm/02-math-foundations/numerical-precision/" data-link-title="2.3 數值精度與量化的數學依據" data-link-desc="fp32 / bf16 / fp16 / int8 / int4 的差別、量化能省哪些 bits、品質衰減從哪裡來">數值精度</a>（fp32 / bf16 / Q4 / Q8 的取捨）。每章末尾接到<a href="/blog/llm/02-math-foundations/going-deeper-math/" data-link-title="2.4 想學更深：推薦公開課程" data-link-desc="MIT、Stanford、Harvard 等公開課程：數學基礎跟 LLM 預備知識的完整學習路線">公開課推薦</a>。</p>
<h3 id="模組三llm-的理論基礎"><a href="/blog/llm/03-theoretical-foundations/" data-link-title="模組三：LLM 的理論基礎" data-link-desc="從神經網路、embedding、attention、Transformer 架構、訓練到 sampling：LLM 內部運作的完整理論圖像">模組三：LLM 的理論基礎</a></h3>
<p>整理 LLM 內部運作機制、共 11 章：<a href="/blog/llm/03-theoretical-foundations/neural-network-basics/" data-link-title="3.0 神經網路基礎" data-link-desc="從單一 neuron 到 multi-layer：weights、activation function、forward / backward pass 的角色">神經網路基礎</a>、<a href="/blog/llm/03-theoretical-foundations/embedding-spaces/" data-link-title="3.1 Embedding 空間" data-link-desc="token 怎麼變成向量、為什麼相似 token 在向量空間中靠近、embedding 是怎麼學出來的">embedding 空間</a>、<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 的核心運算">attention 機制</a>、<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 架構</a>、<a href="/blog/llm/03-theoretical-foundations/training-pipeline/" data-link-title="3.4 訓練流程：pre-train → SFT → RLHF" data-link-desc="LLM 的三階段訓練：預訓練、指令微調、人類反饋強化學習；各階段目標與最新替代方案">訓練流程</a>（pre-train → SFT → RLHF / DPO）、<a href="/blog/llm/03-theoretical-foundations/sampling-and-decoding/" data-link-title="3.5 Sampling 與 Decoding 策略" data-link-desc="Greedy、beam search、top-k、top-p、temperature、min-p：模型輸出後怎麼挑下一個 token">sampling 策略</a>、<a href="/blog/llm/03-theoretical-foundations/tokenization-algorithms/" data-link-title="3.6 Tokenization：BPE、SentencePiece、Tiktoken" data-link-desc="把文字切成 token 的算法：為什麼不同模型切出不同 token 數、tokenizer 選擇對能力的影響">tokenization 算法</a>、<a href="/blog/llm/03-theoretical-foundations/cross-language-tokenization/" data-link-title="3.7 跨語言場景的 tokenizer 與訓練分佈原理" data-link-desc="為什麼模型對不同語言表現不一致：tokenizer &#43; 訓練資料分佈雙因素、語言選擇取捨">跨語言場景原理</a>、<a href="/blog/llm/03-theoretical-foundations/reasoning-models/" data-link-title="3.8 Reasoning models：test-time compute paradigm" data-link-desc="Chain-of-thought 從 prompting 技巧演化成訓練 paradigm、reasoning model 的內部運作、本地可跑的選項與適用任務">Reasoning models</a>（o1 / R1 / QwQ 等 test-time compute paradigm）、<a href="/blog/llm/03-theoretical-foundations/speculative-decoding-internals/" data-link-title="3.9 Speculative decoding 內部：drafter / 驗證 / 加速上限" data-link-desc="speculative decoding 的演算法細節、drafter 跟 target 怎麼配對、acceptance rate 怎麼決定實際加速、MTP 跟 EAGLE 等變體">Speculative decoding 內部</a>（drafter / MTP / EAGLE）。每章末尾接到<a href="/blog/llm/03-theoretical-foundations/going-deeper-theory/" data-link-title="3.11 想學更深：推薦公開課程" data-link-desc="Karpathy、Stanford CS224N / CS25 / CS336、DeepLearning.AI、Hugging Face：LLM 理論深入學習的完整路線">公開課推薦</a>（Karpathy、Stanford CS224N / CS25 / CS336、DeepLearning.AI）。</p>
<h3 id="模組四llm-應用層原理"><a href="/blog/llm/04-applications/" data-link-title="模組四：LLM 應用層原理" data-link-desc="Prompt 技術光譜、RAG、tool use、agent、應用層協議、人機協作、multi-agent、workflow 編排、eval 設計：跨工具不變的概念地圖">模組四：LLM 應用層原理</a></h3>
<p>整理 LLM 作為系統元件的設計原理、共 12 章：<a href="/blog/llm/04-applications/rag-principles/" data-link-title="4.1 RAG 原理：retrieval &#43; augmentation 模式" data-link-desc="為什麼模型需要外掛知識、語意相似 vs 字面相似、chunking 的本質取捨、retrieval 失敗的根本原因">RAG</a>、<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 表現崩潰">tool use</a>、<a href="/blog/llm/04-applications/agent-architecture/" data-link-title="4.4 Agent 架構原理" data-link-desc="Agent loop 結構、失敗模式、什麼任務適合 vs 不適合、跟人類審查的協作模型">agent 架構</a>、<a href="/blog/llm/04-applications/application-protocols/" data-link-title="4.6 應用層協議：function calling / structured output / MCP" data-link-desc="三個常被混為一談的概念：模型能力、sampling 約束、server 協議，三者的層級差異與組合方式">應用層協議</a>、<a href="/blog/llm/04-applications/workflow-patterns/" data-link-title="4.7 Workflow 編排模式" data-link-desc="Pipeline / router / parallel / reflection：多 LLM call 組合的四種基本模式與退化條件">workflow 編排模式</a>、<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 的設計取捨">Production resource planning</a>、<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 取捨">衍生產物管理</a>、<a href="/blog/llm/04-applications/long-context-engineering/" data-link-title="4.11 Long context engineering" data-link-desc="128K / 1M context 模型怎麼用：claimed vs effective context、lost-in-the-middle、context 設計策略、Long context vs RAG 取捨">Long context engineering</a>、<a href="/blog/llm/04-applications/embedding-model-internals/" data-link-title="4.12 Embedding model 內部：訓練、選型、in-domain fine-tune" data-link-desc="Embedding model 怎麼訓練（contrastive learning &#43; hard negative mining）、怎麼挑（MTEB / 大小 / domain）、何時該自己 fine-tune">Embedding model 內部</a>、<a href="/blog/llm/04-applications/benchmarking-and-evaluation/" data-link-title="4.14 Benchmarking 與評估方法論" data-link-desc="判讀 model card benchmark 數字、做自己工作流的 in-house benchmark、量測本地推論速度的完整方法論">Benchmarking 方法論</a>、<a href="/blog/llm/04-applications/vision-in-coding-workflow/" data-link-title="4.15 Vision in coding workflow：本地 VLM 怎麼接寫 code" data-link-desc="VLM 在 coding 工作流的 use cases、本地 VLM 選型、跟雲端 VLM 的分工、Continue.dev / Ollama 整合現狀">Vision in coding workflow</a>（本地 VLM 接 IDE）、<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">靜態 / serverless RAG deployment</a>（沒 backend 場景）。本模組刻意只寫跨工具世代不變的原理、避開 LangChain / LlamaIndex 等具體 framework 教學。</p>
<h3 id="模組五windows--linux--獨立-gpu"><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 調參">模組五：Windows / Linux + 獨立 GPU</a></h3>
<p>整理消費級 PC（Windows / Linux + NVIDIA / AMD 獨立 GPU）跑本地 LLM 的硬體判讀模型與工程選項：<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 把兩個世界連起來">VRAM + RAM 分層預算</a>、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>（<code>--n-cpu-moe</code>）、KV cache 量化（K=Q8 / V=Q4）跟 context 長度的權衡、llama.cpp 在 PC 上的調參空間。本模組跟模組一是平行的硬體路線、共用模組零的心智模型跟卡片。</p>
<h3 id="模組六本地-llm-的安全與權限"><a href="/blog/llm/06-security/" data-link-title="模組六：本地 LLM 的安全與權限" data-link-desc="個人 dev 在自己機器上跑本地 LLM 的安全議題：模型供應鏈、推論伺服器綁定、tool use 副作用、prompt injection 在 IDE、跨雲端 / 本地資料邊界">模組六：本地 LLM 的安全與權限</a></h3>
<p>整理個人 dev 在自己機器上跑本地 LLM 的安全議題：<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 信任、量化版本污染、檔案完整性檢查">模型供應鏈與信任邊界</a>、<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 反代、預設安全、誤開放給內網的後果">推論伺服器的綁定與暴露範圍</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 信任、副作用的可逆性">tool use 與 MCP server 的權限模型</a>、<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 場景的差異">IDE 場景的 prompt injection</a>、<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 設定、隱私資料流、按敏感度分流的判讀">跨雲端 / 本地的資料邊界</a>、<a href="/blog/llm/06-security/routing-to-production-security/" data-link-title="6.5 跨進 production 的 routing 中樞" data-link-desc="個人 dev → 團隊 → production LLM 服務的三層演化、跟 backend/07 對應卡片的 routing 清單">跨進 production 的 routing 中樞</a>。framing 是個人 dev 視角、不是 enterprise 資安管理；production / 多租戶 LLM 服務的特殊資安議題見 <a href="/blog/backend/07-security-data-protection/" data-link-title="模組七：資安與資料保護" data-link-desc="以問題驅動方式擴充資安知識網：先定義服務環節問題，再以案例作為觸發式參考">Backend 模組七 資安與資料保護</a> 的 LLM 相關章節。</p>
<h2 id="模組之間怎麼配合">模組之間怎麼配合</h2>
<table>
  <thead>
      <tr>
          <th>模組</th>
          <th>角度</th>
          <th>跟其他模組的關係</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>模組零</td>
          <td>操作層心智模型</td>
          <td>是模組一跟模組五的共同前置</td>
      </tr>
      <tr>
          <td>模組一</td>
          <td>工具層、Mac 實際安裝</td>
          <td>用模組零的詞彙、跟模組三的理論互補</td>
      </tr>
      <tr>
          <td>模組二</td>
          <td>數學工具</td>
          <td>提供模組三需要的數學詞彙、跟硬體平台無關</td>
      </tr>
      <tr>
          <td>模組三</td>
          <td>理論機制</td>
          <td>用模組二的工具拼出完整 LLM、跟硬體平台無關</td>
      </tr>
      <tr>
          <td>模組四</td>
          <td>應用層原理</td>
          <td>用前面模組建的詞彙、看 LLM 作為系統元件</td>
      </tr>
      <tr>
          <td>模組五</td>
          <td>工具層、PC 獨立 GPU</td>
          <td>跟模組一平行、用模組零的詞彙、處理 VRAM 場景</td>
      </tr>
      <tr>
          <td>模組六</td>
          <td>安全層、個人 dev 視角</td>
          <td>在模組一 / 五的工作流上加安全判讀、cross-link backend/07 通用資安卡片</td>
      </tr>
  </tbody>
</table>
<p>模組二跟模組三可並讀。閱讀模組三遇到陌生數學詞時跳回模組二補完、再回模組三繼續。模組四在前面模組之上、但讀者熟悉 LLM 應用詞彙也可直接從這裡讀起。模組一跟模組五依硬體選一條主路線、共用模組零的心智模型與 <a href="/blog/llm/knowledge-cards/" data-link-title="Knowledge Cards" data-link-desc="用原子化卡片整理本地 LLM 寫 code 場景所需的概念詞彙">knowledge-cards</a>。模組六在模組一 / 五跑穩後接、處理「跑起來後該注意什麼」。</p>
<h2 id="適合的讀者">適合的讀者</h2>
<table>
  <thead>
      <tr>
          <th>背景</th>
          <th>適合程度</th>
          <th>建議起點</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>用過 ChatGPT / Claude、沒碰過本地模型</td>
          <td>直接適合</td>
          <td><a href="/blog/llm/00-foundations/" data-link-title="模組零：基礎知識與心智模型" data-link-desc="建立本地 LLM 的心智模型、釐清 MLX / MTP / oMLX 等常被混淆的術語、Apple Silicon 記憶體現實">模組零</a> 從頭讀</td>
      </tr>
      <tr>
          <td>裝過 Ollama 但被網路上的術語混淆</td>
          <td>直接適合</td>
          <td><a href="/blog/llm/00-foundations/mlx-mtp-omlx/" data-link-title="0.4 MLX / MTP / oMLX 的區別" data-link-desc="三個常被混為一談的術語：framework、加速技巧、特化 server，疊加而非互斥">MLX / MTP / oMLX 區分</a> + <a href="/blog/llm/00-foundations/info-judgment-frames/" data-link-title="0.6 判讀本地 LLM 資訊的五個框架" data-link-desc="本地 LLM 資訊更新快，學會用版本、層級、變數、能力、資料流五個框架評估文章與宣稱">判讀框架</a></td>
      </tr>
      <tr>
          <td>想知道 24GB / 32GB Mac 該選哪個模型</td>
          <td>直接適合</td>
          <td><a href="/blog/llm/00-foundations/hardware-memory-budget/" data-link-title="0.5 Apple Silicon 記憶體預算" data-link-desc="記憶體決定能跑什麼，Q4 量化下的可運作模型對照與系統保留">硬體記憶體預算</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></td>
      </tr>
      <tr>
          <td>想用本地 LLM 完全取代 Claude / GPT-5</td>
          <td>部分適合</td>
          <td><a href="/blog/llm/01-local-llm-services/expectation-management/" data-link-title="1.5 期望管理：本地 LLM 的擅長領域與分工" data-link-desc="本地 LLM 是免費的初階 pair programmer：辨識它的擅長領域、跟雲端旗艦做結構性分工">期望管理</a> 先看完再決定</td>
      </tr>
      <tr>
          <td>想懂 LLM 內部運作機制</td>
          <td>直接適合</td>
          <td><a href="/blog/llm/03-theoretical-foundations/" data-link-title="模組三：LLM 的理論基礎" data-link-desc="從神經網路、embedding、attention、Transformer 架構、訓練到 sampling：LLM 內部運作的完整理論圖像">模組三 理論基礎</a> 從頭讀（含 reasoning models / speculative decoding）</td>
      </tr>
      <tr>
          <td>想懂背後的數學</td>
          <td>直接適合</td>
          <td><a href="/blog/llm/02-math-foundations/" data-link-title="模組二：LLM 的數學基礎" data-link-desc="整理 LLM 推論背後需要理解的線性代數、機率與資訊論、最佳化、數值精度等數學概念">模組二 數學基礎</a> 從頭讀</td>
      </tr>
      <tr>
          <td>想懂 o1 / DeepSeek-R1 等 reasoning model 怎麼運作</td>
          <td>直接適合</td>
          <td><a href="/blog/llm/03-theoretical-foundations/reasoning-models/" data-link-title="3.8 Reasoning models：test-time compute paradigm" data-link-desc="Chain-of-thought 從 prompting 技巧演化成訓練 paradigm、reasoning model 的內部運作、本地可跑的選項與適用任務">3.8 Reasoning models</a> 從頭讀</td>
      </tr>
      <tr>
          <td>想做 LLM 應用開發（RAG / agent / tool use）</td>
          <td>直接適合</td>
          <td><a href="/blog/llm/04-applications/" data-link-title="模組四：LLM 應用層原理" data-link-desc="Prompt 技術光譜、RAG、tool use、agent、應用層協議、人機協作、multi-agent、workflow 編排、eval 設計：跨工具不變的概念地圖">模組四</a> 從 4.0 RAG 依序讀</td>
      </tr>
      <tr>
          <td>想在自家 Hugo / Astro 等靜態網站加 RAG</td>
          <td>直接適合</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 靜態 / serverless RAG deployment</a>（含資安取捨）</td>
      </tr>
      <tr>
          <td>想用 VLM 看截圖 / 設計稿輔助寫 code</td>
          <td>直接適合</td>
          <td><a href="/blog/llm/04-applications/vision-in-coding-workflow/" data-link-title="4.15 Vision in coding workflow：本地 VLM 怎麼接寫 code" data-link-desc="VLM 在 coding 工作流的 use cases、本地 VLM 選型、跟雲端 VLM 的分工、Continue.dev / Ollama 整合現狀">4.15 Vision in coding workflow</a></td>
      </tr>
      <tr>
          <td>想評估 LLM benchmark 數字、做 in-house eval</td>
          <td>直接適合</td>
          <td><a href="/blog/llm/04-applications/benchmarking-and-evaluation/" data-link-title="4.14 Benchmarking 與評估方法論" data-link-desc="判讀 model card benchmark 數字、做自己工作流的 in-house benchmark、量測本地推論速度的完整方法論">4.14 Benchmarking 方法論</a></td>
      </tr>
      <tr>
          <td>想在本機 fine-tune 模型懂自家 codebase 慣例</td>
          <td>直接適合</td>
          <td><a href="/blog/llm/03-theoretical-foundations/training-pipeline/" data-link-title="3.4 訓練流程：pre-train → SFT → RLHF" data-link-desc="LLM 的三階段訓練：預訓練、指令微調、人類反饋強化學習；各階段目標與最新替代方案">3.4 訓練流程</a> 原理 + <a href="/blog/llm/01-local-llm-services/hands-on/local-fine-tuning/" data-link-title="Hands-on：用 QLoRA 在本機 fine-tune coding 模型" data-link-desc="Apple Silicon Mac / PC 獨立 GPU 上跑 QLoRA fine-tune 的完整流程：環境、資料、訓練、evaluation、合併、部署到 Ollama">QLoRA hands-on</a></td>
      </tr>
      <tr>
          <td>想做 large-scale fine-tune / 從頭訓練</td>
          <td>部分適合</td>
          <td>讀完模組三後進入 <a href="/blog/llm/03-theoretical-foundations/going-deeper-theory/" data-link-title="3.11 想學更深：推薦公開課程" data-link-desc="Karpathy、Stanford CS224N / CS25 / CS336、DeepLearning.AI、Hugging Face：LLM 理論深入學習的完整路線">推薦的公開課程</a> 跟 Stanford CS336</td>
      </tr>
      <tr>
          <td>用 Windows / Linux + NVIDIA / AMD 獨立 GPU 跑本地 LLM</td>
          <td>直接適合</td>
          <td><a href="/blog/llm/00-foundations/" data-link-title="模組零：基礎知識與心智模型" data-link-desc="建立本地 LLM 的心智模型、釐清 MLX / MTP / oMLX 等常被混淆的術語、Apple Silicon 記憶體現實">模組零</a> 建心智模型 + <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 調參">模組五</a> 處理 VRAM 預算、MoE 卸載、KV cache 量化</td>
      </tr>
      <tr>
          <td>想知道本地 LLM 跑起來後的安全議題</td>
          <td>直接適合</td>
          <td><a href="/blog/llm/06-security/" data-link-title="模組六：本地 LLM 的安全與權限" data-link-desc="個人 dev 在自己機器上跑本地 LLM 的安全議題：模型供應鏈、推論伺服器綁定、tool use 副作用、prompt injection 在 IDE、跨雲端 / 本地資料邊界">模組六</a> 個人 dev 視角的安全與權限</td>
      </tr>
      <tr>
          <td>想把 LLM 部署成 production 服務、處理服務化資安</td>
          <td>部分適合</td>
          <td>個人視角見 <a href="/blog/llm/06-security/" data-link-title="模組六：本地 LLM 的安全與權限" data-link-desc="個人 dev 在自己機器上跑本地 LLM 的安全議題：模型供應鏈、推論伺服器綁定、tool use 副作用、prompt injection 在 IDE、跨雲端 / 本地資料邊界">模組六</a>；production 場景見 <a href="/blog/backend/07-security-data-protection/" data-link-title="模組七：資安與資料保護" data-link-desc="以問題驅動方式擴充資安知識網：先定義服務環節問題，再以案例作為觸發式參考">Backend 模組七 資安</a> 的 LLM 相關章節</td>
      </tr>
      <tr>
          <td>想在資料中心級 GPU（H100 / H200 / B200）部署</td>
          <td>部分適合</td>
          <td>心智模型跟 <a href="/blog/llm/knowledge-cards/" data-link-title="Knowledge Cards" data-link-desc="用原子化卡片整理本地 LLM 寫 code 場景所需的概念詞彙">knowledge-cards</a> 通用；vLLM / TGI / Triton 等資料中心 inference server 另尋專門教材</td>
      </tr>
      <tr>
          <td>想跑 Stable Diffusion / Midjourney 等產圖</td>
          <td>跟主題不同</td>
          <td>產圖是 Diffusion 架構、見 <a href="/blog/llm/knowledge-cards/diffusion/" data-link-title="Diffusion" data-link-desc="產圖用的生成式 AI 架構：跟寫 code 用的 Transformer 是不同路線">Diffusion 卡片</a>、另尋 ComfyUI / Draw Things 教材</td>
      </tr>
  </tbody>
</table>
<h2 id="用語約定">用語約定</h2>
<p>本指南使用的關鍵術語在第一次出現時都附原文。為避免歧義，下列詞彙在本指南內固定指涉：</p>
<ol>
<li><strong>本地 LLM</strong>：跑在使用者自己機器（Mac 或 PC）上的大型語言模型推論、prompt 留在本機。</li>
<li><strong>推論伺服器</strong>（inference server）：負責載入模型權重、處理 prompt、產生 token 的常駐程式、例如 Ollama、LM Studio 內建 server、llama.cpp <code>server</code>。</li>
<li><strong>介面層</strong>：使用者實際打字互動的工具、例如 VS Code + Continue.dev、CLI、Web UI。介面層透過 API 跟推論伺服器溝通。</li>
<li><strong>模型</strong>（model）：權重檔本身、例如 <code>gemma4:31b</code>、<code>qwen3-coder:30b</code>。模型可以在不同推論伺服器之間共用、前提是格式相容。</li>
<li><strong>量化</strong>（quantization）：把模型權重從高精度（如 bf16）壓成低精度（如 Q4）以減少記憶體佔用、代價是少許品質下降。</li>
</ol>
<h2 id="不在本指南內的主題">不在本指南內的主題</h2>
<p>本指南不討論：</p>
<ul>
<li><strong>Speech / audio LLM</strong>：跟核心文字 LLM 是不同方向、本指南不涵蓋。Vision（VLM）原本不放、但因 coding 工作流的 vision use case 進入主流、補上 <a href="/blog/llm/04-applications/vision-in-coding-workflow/" data-link-title="4.15 Vision in coding workflow：本地 VLM 怎麼接寫 code" data-link-desc="VLM 在 coding 工作流的 use cases、本地 VLM 選型、跟雲端 VLM 的分工、Continue.dev / Ollama 整合現狀">4.15 Vision in coding workflow</a>；video LLM 仍不放。</li>
<li><strong>資料中心訓練的工程細節</strong>：data parallelism、ZeRO、tensor parallelism 等屬於專門課程的範圍。</li>
<li><strong>向量資料庫的 vendor 比較</strong>（Pinecone vs Weaviate vs Chroma 等）：vendor 格局半年一變、不適合寫入教材。RAG 的 storage 工程原理（升級判讀、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>。</li>
<li><strong>Kubernetes / 資料中心級分散式推論</strong>：跟個人機器本地 LLM 方向不同、需另尋專門教材。</li>
<li><strong>多卡 NVLink、tensor parallelism</strong>：消費級 PC 場景通常單卡、本指南不涵蓋多卡分散式推論。</li>
</ul>
<p>若讀完本指南後想往這些方向走：</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>：先把 Ollama + Continue.dev 跑穩、再讀 <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/03-theoretical-foundations/going-deeper-theory/" data-link-title="3.11 想學更深：推薦公開課程" data-link-desc="Karpathy、Stanford CS224N / CS25 / CS336、DeepLearning.AI、Hugging Face：LLM 理論深入學習的完整路線">模組三 3.8 推薦</a> 的 DeepLearning.AI short courses。</li>
<li><strong>想跑 coding <a href="/blog/llm/knowledge-cards/agent/" data-link-title="LLM Agent" data-link-desc="把控制流交給 LLM 的應用模式：自主決策、跨多步呼叫工具、人類角色從主導變監督">agent</a></strong>：先讀 <a href="/blog/llm/04-applications/agent-architecture/" data-link-title="4.4 Agent 架構原理" data-link-desc="Agent loop 結構、失敗模式、什麼任務適合 vs 不適合、跟人類審查的協作模型">4.4 Agent 架構原理</a> 建立判讀、再看 <a href="/blog/llm/01-local-llm-services/extension-paths/" data-link-title="1.6 延伸方向：Web UI、coding agent、產圖" data-link-desc="日常路徑跑穩後可以玩的延伸：Open WebUI、aider、ComfyUI；先把基底跑穩再進階">1.6 延伸方向</a> 了解 aider、Cline 等工具的定位差異。</li>
<li><strong>想跑產圖模型</strong>：<a href="/blog/llm/knowledge-cards/diffusion/" data-link-title="Diffusion" data-link-desc="產圖用的生成式 AI 架構：跟寫 code 用的 Transformer 是不同路線">Diffusion</a> 跟 Transformer 是不同架構、請另尋 ComfyUI / Draw Things / Diffusers 教材。</li>
<li><strong>想自己訓練 / fine-tune</strong>：讀完模組三、進入 Karpathy zero-to-hero、Stanford CS336、Hugging Face NLP Course 等<a href="/blog/llm/03-theoretical-foundations/going-deeper-theory/" data-link-title="3.11 想學更深：推薦公開課程" data-link-desc="Karpathy、Stanford CS224N / CS25 / CS336、DeepLearning.AI、Hugging Face：LLM 理論深入學習的完整路線">推薦資源</a>。</li>
</ol>
<hr>
<p><em>文件版本：v0.7.0</em>
<em>最後更新：2026-05-12</em>
<em>系列狀態：七個模組 + 125 張知識卡片。模組零（9 章）/ 一（10 章 + hands-on、含 QLoRA + judge harness）/ 二（5 章）/ 三（12 章、含 reasoning / speculative / constrained decoding）/ 四（17 章、含 long context / embedding / benchmarking / VLM / 靜態 deployment / coding agent harness / prompt caching / agent memory / tracing / LLM-as-judge）/ 五（7 章）/ 六（7 章、含 OWASP 對照）。</em></p>
]]></content:encoded></item><item><title>0.0 本地 vs 雲端 LLM</title><link>https://tarrragon.github.io/blog/llm/00-foundations/local-vs-cloud/</link><pubDate>Mon, 11 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/llm/00-foundations/local-vs-cloud/</guid><description>&lt;p>本地 LLM 與雲端 LLM 的核心差異是「模型權重在哪台機器上跑、誰能看到對話內容」。把模型權重載到自己 Mac 的記憶體裡、用本機算力跑&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>，就是本地；把 prompt 透過 HTTPS 送到 Anthropic、OpenAI、Google 的伺服器，再把結果回傳，就是雲端。&lt;/p>
&lt;p>這個差異一拆，後續所有取捨都會自然展開：隱私、成本、速度、能力四個維度在本地與雲端的權衡方向都不一樣。本章的責任是把這四個維度先攤開，後續章節再分別處理「速度為何慢」「記憶體為何決定能力」等具體問題。&lt;/p>
&lt;h2 id="本章目標">本章目標&lt;/h2>
&lt;p>讀完本章後，你應該能回答：&lt;/p>
&lt;ol>
&lt;li>哪些情境下花時間在本地跑 LLM 比直接用雲端旗艦划算？&lt;/li>
&lt;li>本地 LLM 的「免費」實際成本怎麼算？&lt;/li>
&lt;li>本地 LLM 的速度跟雲端比、在不同任務上的差距如何？&lt;/li>
&lt;li>本地 LLM 在哪些任務上能跟 Claude / GPT-5 並肩、哪些任務改用雲端更划算？&lt;/li>
&lt;/ol>
&lt;h2 id="四個維度的差異">四個維度的差異&lt;/h2>
&lt;table>
 &lt;thead>
 &lt;tr>
 &lt;th>維度&lt;/th>
 &lt;th>本地 LLM&lt;/th>
 &lt;th>雲端 LLM&lt;/th>
 &lt;/tr>
 &lt;/thead>
 &lt;tbody>
 &lt;tr>
 &lt;td>隱私&lt;/td>
 &lt;td>prompt、code、檔案完全不離開本機&lt;/td>
 &lt;td>內容會送到第三方伺服器，受其資料保留與訓練政策約束&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>成本&lt;/td>
 &lt;td>一次性硬體投資（Mac 的記憶體），無 API 費用&lt;/td>
 &lt;td>按 token 計費，重度使用每月可達數百美元&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>速度&lt;/td>
 &lt;td>受本機算力與記憶體頻寬限制，首字延遲與生字速度都低於雲端旗艦模型&lt;/td>
 &lt;td>旗艦模型在資料中心級 GPU（NVIDIA H100 等）或 TPU 上跑，首字延遲低、生字速度快&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>能力&lt;/td>
 &lt;td>受模型大小與量化等級限制，2026 年 5 月可在 Mac 上跑的最強模型約等於 GPT-4 mini / Claude Haiku 等級&lt;/td>
 &lt;td>Claude Sonnet 4.6、Opus 4.7、GPT-5 等旗艦模型，能力斷崖式領先&lt;/td>
 &lt;/tr>
 &lt;/tbody>
&lt;/table>
&lt;p>這張表是後續所有章節的判讀基底。下面四個小節分別把每一格展開到「實際使用情境下會怎麼影響決策」。&lt;/p>
&lt;h2 id="隱私維度prompt-出境邊界">隱私維度：prompt 出境邊界&lt;/h2>
&lt;p>本地 LLM 在隱私維度的核心承諾是 prompt 內容不離開本機。對寫 code 來說這影響的是兩件事：手上的 code 會不會進入訓練資料、客戶 NDA 或公司資安政策能否接受 code 出境。&lt;/p>
&lt;p>接近真實的情境：&lt;/p>
&lt;ul>
&lt;li>接受 NDA 的外包專案，客戶明示不得把 code 上傳第三方 AI 服務。&lt;/li>
&lt;li>公司內部 monorepo 包含未公開的商業邏輯，資安政策禁止流向 OpenAI 或 Anthropic。&lt;/li>
&lt;li>個人 side project 沒有合規壓力，但仍想避免將 prompt 變成廣告或推薦演算法的訓練資料。&lt;/li>
&lt;/ul>
&lt;p>陷阱是把「本地 = 絕對私密」當成自動成立的事實。本地 LLM 的隱私保證僅在於 prompt 不離開機器；若同時開啟雲端同步、把對話紀錄存到 Notion、或用 IDE 的雲端 plugin 同時送 prompt 給其他服務，隱私邊界仍會被穿透。隱私是一條鏈，本地推論伺服器只是其中一環。&lt;/p>
&lt;p>雲端旗艦模型如 Claude 與 GPT 都提供 zero-retention 與不訓練選項（企業方案、API 預設等），合規上多數場景仍能滿足。隱私是訴求，不是非選本地不可的唯一理由。&lt;/p>
&lt;h2 id="成本維度一次性投資-vs-按-token-計費">成本維度：一次性投資 vs 按 token 計費&lt;/h2>
&lt;p>本地 LLM 的成本特性是「先付硬體錢，後續推論免費」。雲端 LLM 反過來：硬體完全不用管，但每個 prompt 都按 token 收費。&lt;/p>
&lt;p>接近真實的情境：&lt;/p>
&lt;ul>
&lt;li>一台 32GB Mac mini M4 約 NT$45,000，能持續跑 Gemma 4 31B 等中型模型。如果原本每月雲端 API 花費超過 NT$3,000，硬體成本約 15 個月攤平。&lt;/li>
&lt;li>偶爾使用者（每月 API 花費 NT$200 以下）若為了「省錢」買新 Mac，是負投資；只有重度使用者才會真正攤平。&lt;/li>
&lt;li>用 Claude Code 寫 code 的工程師，月費約 USD 200，一年 USD 2,400；硬體攤平的數學就要重算，特別是考慮到雲端能力斷崖式領先時，省下的時間成本通常超過 API 費用。&lt;/li>
&lt;/ul>
&lt;p>陷阱是把硬體成本當成沉沒成本、把雲端按月看成「持續流血」。實際上 Mac 本來就要買，邊際成本是「為了跑 LLM 多買 16GB 記憶體」這一段，這個邊際成本通常只有 NT$5,000 ~ 10,000，比看起來低很多。但這個邊際成本買到的是「不太強的模型」，能力差距見下一節。&lt;/p>
&lt;p>電費跟風扇噪音是被忽略的隱性成本。32GB Mac 跑大型模型時持續滿載，風扇可能整天轉、機殼會熱；fanless 機種（Air）會降頻，速度進一步下降。&lt;/p></description><content:encoded><![CDATA[<p>本地 LLM 與雲端 LLM 的核心差異是「模型權重在哪台機器上跑、誰能看到對話內容」。把模型權重載到自己 Mac 的記憶體裡、用本機算力跑<a href="/blog/llm/knowledge-cards/inference-server/" data-link-title="Inference Server" data-link-desc="載入模型權重、處理 prompt、產生 token 的常駐 process">推論</a>，就是本地；把 prompt 透過 HTTPS 送到 Anthropic、OpenAI、Google 的伺服器，再把結果回傳，就是雲端。</p>
<p>這個差異一拆，後續所有取捨都會自然展開：隱私、成本、速度、能力四個維度在本地與雲端的權衡方向都不一樣。本章的責任是把這四個維度先攤開，後續章節再分別處理「速度為何慢」「記憶體為何決定能力」等具體問題。</p>
<h2 id="本章目標">本章目標</h2>
<p>讀完本章後，你應該能回答：</p>
<ol>
<li>哪些情境下花時間在本地跑 LLM 比直接用雲端旗艦划算？</li>
<li>本地 LLM 的「免費」實際成本怎麼算？</li>
<li>本地 LLM 的速度跟雲端比、在不同任務上的差距如何？</li>
<li>本地 LLM 在哪些任務上能跟 Claude / GPT-5 並肩、哪些任務改用雲端更划算？</li>
</ol>
<h2 id="四個維度的差異">四個維度的差異</h2>
<table>
  <thead>
      <tr>
          <th>維度</th>
          <th>本地 LLM</th>
          <th>雲端 LLM</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>隱私</td>
          <td>prompt、code、檔案完全不離開本機</td>
          <td>內容會送到第三方伺服器，受其資料保留與訓練政策約束</td>
      </tr>
      <tr>
          <td>成本</td>
          <td>一次性硬體投資（Mac 的記憶體），無 API 費用</td>
          <td>按 token 計費，重度使用每月可達數百美元</td>
      </tr>
      <tr>
          <td>速度</td>
          <td>受本機算力與記憶體頻寬限制，首字延遲與生字速度都低於雲端旗艦模型</td>
          <td>旗艦模型在資料中心級 GPU（NVIDIA H100 等）或 TPU 上跑，首字延遲低、生字速度快</td>
      </tr>
      <tr>
          <td>能力</td>
          <td>受模型大小與量化等級限制，2026 年 5 月可在 Mac 上跑的最強模型約等於 GPT-4 mini / Claude Haiku 等級</td>
          <td>Claude Sonnet 4.6、Opus 4.7、GPT-5 等旗艦模型，能力斷崖式領先</td>
      </tr>
  </tbody>
</table>
<p>這張表是後續所有章節的判讀基底。下面四個小節分別把每一格展開到「實際使用情境下會怎麼影響決策」。</p>
<h2 id="隱私維度prompt-出境邊界">隱私維度：prompt 出境邊界</h2>
<p>本地 LLM 在隱私維度的核心承諾是 prompt 內容不離開本機。對寫 code 來說這影響的是兩件事：手上的 code 會不會進入訓練資料、客戶 NDA 或公司資安政策能否接受 code 出境。</p>
<p>接近真實的情境：</p>
<ul>
<li>接受 NDA 的外包專案，客戶明示不得把 code 上傳第三方 AI 服務。</li>
<li>公司內部 monorepo 包含未公開的商業邏輯，資安政策禁止流向 OpenAI 或 Anthropic。</li>
<li>個人 side project 沒有合規壓力，但仍想避免將 prompt 變成廣告或推薦演算法的訓練資料。</li>
</ul>
<p>陷阱是把「本地 = 絕對私密」當成自動成立的事實。本地 LLM 的隱私保證僅在於 prompt 不離開機器；若同時開啟雲端同步、把對話紀錄存到 Notion、或用 IDE 的雲端 plugin 同時送 prompt 給其他服務，隱私邊界仍會被穿透。隱私是一條鏈，本地推論伺服器只是其中一環。</p>
<p>雲端旗艦模型如 Claude 與 GPT 都提供 zero-retention 與不訓練選項（企業方案、API 預設等），合規上多數場景仍能滿足。隱私是訴求，不是非選本地不可的唯一理由。</p>
<h2 id="成本維度一次性投資-vs-按-token-計費">成本維度：一次性投資 vs 按 token 計費</h2>
<p>本地 LLM 的成本特性是「先付硬體錢，後續推論免費」。雲端 LLM 反過來：硬體完全不用管，但每個 prompt 都按 token 收費。</p>
<p>接近真實的情境：</p>
<ul>
<li>一台 32GB Mac mini M4 約 NT$45,000，能持續跑 Gemma 4 31B 等中型模型。如果原本每月雲端 API 花費超過 NT$3,000，硬體成本約 15 個月攤平。</li>
<li>偶爾使用者（每月 API 花費 NT$200 以下）若為了「省錢」買新 Mac，是負投資；只有重度使用者才會真正攤平。</li>
<li>用 Claude Code 寫 code 的工程師，月費約 USD 200，一年 USD 2,400；硬體攤平的數學就要重算，特別是考慮到雲端能力斷崖式領先時，省下的時間成本通常超過 API 費用。</li>
</ul>
<p>陷阱是把硬體成本當成沉沒成本、把雲端按月看成「持續流血」。實際上 Mac 本來就要買，邊際成本是「為了跑 LLM 多買 16GB 記憶體」這一段，這個邊際成本通常只有 NT$5,000 ~ 10,000，比看起來低很多。但這個邊際成本買到的是「不太強的模型」，能力差距見下一節。</p>
<p>電費跟風扇噪音是被忽略的隱性成本。32GB Mac 跑大型模型時持續滿載，風扇可能整天轉、機殼會熱；fanless 機種（Air）會降頻，速度進一步下降。</p>
<h2 id="速度維度首字延遲與生字速度">速度維度：首字延遲與生字速度</h2>
<p>本地 LLM 的速度有兩個獨立指標：<strong><a href="/blog/llm/knowledge-cards/ttft/" data-link-title="TTFT" data-link-desc="Time To First Token：送出 prompt 到第一個 token 出現的等待時間">首字延遲</a></strong>（Time To First Token, TTFT，從送出 prompt 到第一個 token 出現）跟**<a href="/blog/llm/knowledge-cards/tokens-per-second/" data-link-title="Tokens Per Second" data-link-desc="LLM 每秒能生成幾個 token：生字速度的標準量化指標">生字速度</a>**（tokens per second, tok/s，後續每秒能吐幾個字）。雲端跟本地在這兩個指標上的差距很不對稱。</p>
<p>接近真實的數字（2026 年 5 月、僅供量級參考、不是 benchmark）：</p>
<table>
  <thead>
      <tr>
          <th>模型 / 硬體</th>
          <th>TTFT</th>
          <th>生字速度（tok/s）</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>Claude Sonnet 4.6 雲端</td>
          <td>0.5 ~ 1 秒</td>
          <td>80 ~ 120</td>
      </tr>
      <tr>
          <td>GPT-5 雲端</td>
          <td>0.5 ~ 1 秒</td>
          <td>70 ~ 100</td>
      </tr>
      <tr>
          <td>Gemma 4 31B <a href="/blog/llm/knowledge-cards/mtp/" data-link-title="Multi-Token Prediction (MTP)" data-link-desc="Google 為 Gemma 系列釋出的 speculative decoding 工程化實作">MTP</a> / M4 Max 32GB</td>
          <td>1 ~ 3 秒</td>
          <td>25 ~ 40</td>
      </tr>
      <tr>
          <td>Qwen3-Coder 30B / M2 Pro 32GB</td>
          <td>2 ~ 4 秒</td>
          <td>15 ~ 25</td>
      </tr>
      <tr>
          <td>長 context（10K+ tokens）本地</td>
          <td>30 ~ 90 秒</td>
          <td>與短 context 相近</td>
      </tr>
  </tbody>
</table>
<p>讀這張表時要注意三件事：</p>
<ol>
<li>雲端的 TTFT 是「請求送到資料中心 + 模型開始推論 + 第一個 token 回傳」的總和；網路 RTT 通常佔 100 ~ 300ms。本地 TTFT 是純推論成本。</li>
<li>本地生字速度受 Apple Silicon 的<a href="/blog/llm/knowledge-cards/memory-bandwidth/" data-link-title="Memory Bandwidth" data-link-desc="記憶體每秒能讀寫多少 bytes：決定本地 LLM 生字速度的真正瓶頸">記憶體頻寬</a>限制、而不是算力。詳見 <a href="/blog/llm/00-foundations/why-llm-feels-slow/" data-link-title="0.1 為什麼 LLM 生字慢" data-link-desc="自回歸架構與記憶體頻寬瓶頸：為何即使 Mac 算力很強，本地 LLM 仍一個字一個字吐">0.1 為什麼 LLM 生字慢</a>。</li>
<li>長 context 的首字延遲是本地 LLM 最大的痛點、瓶頸落在 <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/kv-cache/" data-link-title="KV Cache" data-link-desc="已處理 token 的 attention 中間結果暫存：避免重算、加速後續生成">KV cache</a>。coding agent 場景塞了整個專案進 prompt 時、本地可能等 30 ~ 90 秒才開始吐字；這是為什麼後來出現 <a href="/blog/llm/00-foundations/mlx-mtp-omlx/" data-link-title="0.4 MLX / MTP / oMLX 的區別" data-link-desc="三個常被混為一談的術語：framework、加速技巧、特化 server，疊加而非互斥">oMLX 這種特化伺服器</a> 來解 KV cache 問題。</li>
</ol>
<p>簡單的 chat 跟短 prompt 的 code completion，本地速度體感堪用。複雜的多檔案重構、塞大量 context 的 agent 場景，本地速度落差會被放大到難以忍受。</p>
<h2 id="能力維度本地模型能做到哪裡">能力維度：本地模型能做到哪裡</h2>
<p>能力是本地 LLM 最被誇大、也最容易讓人失望的維度。實話實說：2026 年 5 月在 Mac 上能跑的最強本地模型（如 Gemma 4 31B、Qwen3-Coder 30B、gpt-oss 20B），能力大約在 GPT-4 mini / Claude Haiku 4.5 這個層級。比雲端旗艦模型（Claude Sonnet 4.6、Opus 4.7、GPT-5）差一個明顯的品質差距。</p>
<p>接近真實的判讀：</p>
<ul>
<li>簡單 function 寫作、單檔重構、加 type annotation、補 unit test、寫 docstring：本地堪用，速度差不多。</li>
<li>中等難度的 debug、解讀錯誤訊息、提建議：本地能給方向，但常需要追問才會收斂。</li>
<li>跨檔案重構、設計新架構、評估技術選型、寫長篇技術文件：雲端旗艦深度領先、改交給雲端更划算。</li>
<li>規劃 multi-step plan、把模糊需求拆成可執行步驟、做 deep debugging：規劃能力是雲端旗艦的明顯強項、現階段交給雲端是合理選擇。</li>
</ul>
<p>陷阱是把網路上 cherry-picked 的成功案例當成普遍能力。「Gemma 4 31B 解出某個 leetcode 題」這類截圖無法代表它在你日常工作流的表現。判讀方法是直接用自己一週內實際處理過的 5 ~ 10 個任務當 benchmark、跑本地模型看通過率。</p>
<h2 id="本地反而領先雲端的情境">本地反而領先雲端的情境</h2>
<p>雲端在「絕對能力」上領先、但本地在三類情境會反過來成為更好的選擇：</p>
<ol>
<li><strong>離線或網路受限環境</strong>：出差、保密廠房、機上工作、行動網路不穩、雲端 API 連不上的場景。本地是唯一可用選項、能力差距不再是判讀重點。</li>
<li><strong>極低延遲容忍度的高頻互動</strong>：短 prompt 的 inline code completion、即時補 type annotation 等場景。本地省去 100 ~ 300ms 的網路 RTT、體感比雲端跳字流暢、適合「打字打到一半 IDE 自動補完」這類工作流。</li>
<li><strong>短 context 但隱私嚴格</strong>：金融、醫療、法務工作流的單檔處理。Prompt 短到不會放大本地速度劣勢、隱私要求又排除雲端、加上若是有 NDA 限制、本地的合規性優勢直接覆蓋能力差距。</li>
</ol>
<p>這三類不是「本地通用領先」、而是「在這些限制下本地的劣勢被中和、優勢被放大」。除此之外的場景仍是雲端旗艦領先。</p>
<h2 id="混用是現階段的正確心態">混用是現階段的正確心態</h2>
<p>本地與雲端不是二選一。寫 code 場景下比較穩定的分工是：</p>
<ol>
<li>高頻、重複、隱私敏感、不需要極致品質的任務交給本地（補 type、寫測試、解釋 code、簡單重構）。</li>
<li>低頻、複雜、需要深度思考的任務交給雲端旗艦（設計、規劃、深度 debug、跨檔案重構）。</li>
<li>一台中型 Mac（<a href="/blog/llm/00-foundations/hardware-memory-budget/" data-link-title="0.5 Apple Silicon 記憶體預算" data-link-desc="記憶體決定能跑什麼，Q4 量化下的可運作模型對照與系統保留">24GB ~ 32GB 記憶體預算</a>） + 雲端旗艦訂閱（Claude Code / GPT-5）的組合、現階段是大多數工程師的甜蜜點。</li>
</ol>
<p>把本地 LLM 當成「免費的初階 pair programmer」而不是「Claude 替代品」，期望管理就會對齊現實。後續章節會回到這個心態，特別是 <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> 與 <a href="/blog/llm/01-local-llm-services/expectation-management/" data-link-title="1.5 期望管理：本地 LLM 的擅長領域與分工" data-link-desc="本地 LLM 是免費的初階 pair programmer：辨識它的擅長領域、跟雲端旗艦做結構性分工">期望管理</a>。</p>
<h2 id="下一章">下一章</h2>
<p>下一章：<a href="/blog/llm/00-foundations/why-llm-feels-slow/" data-link-title="0.1 為什麼 LLM 生字慢" data-link-desc="自回歸架構與記憶體頻寬瓶頸：為何即使 Mac 算力很強，本地 LLM 仍一個字一個字吐">0.1 為什麼 LLM 生字慢</a>，解釋為什麼即使你的 Mac 看起來算力很強，生字速度仍受記憶體頻寬限制。</p>
]]></content:encoded></item><item><title>模組零：基礎知識與心智模型</title><link>https://tarrragon.github.io/blog/llm/00-foundations/</link><pubDate>Mon, 11 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/llm/00-foundations/</guid><description>&lt;p>本模組的核心目標是把「本地跑 LLM」這件事拆成可討論的工程概念。先建立心智模型再進入工具選擇，可以避開大量網路文章把 framework、加速技巧、伺服器混為一談的陷阱；讀完模組零再進模組一，就能用同一套詞彙判讀任何新的本地 LLM 工具是在解哪一層的問題。&lt;/p>
&lt;p>讀完本模組後，你應該能清楚回答：本地跟雲端跑 LLM 的差別在哪、為什麼 LLM 一個字一個字吐而不是整段吐、什麼是介面 / 伺服器 / 模型三層架構、為何 OpenAI 相容 API 是整個生態的基石、MLX 跟 MTP 跟 oMLX 各自是什麼東西、自己這台 Mac 的記憶體能跑多大的模型。&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/llm/00-foundations/local-vs-cloud/" data-link-title="0.0 本地 vs 雲端 LLM" data-link-desc="從隱私、成本、速度、能力四個維度建立本地與雲端 LLM 的基本對照">0.0&lt;/a>&lt;/td>
 &lt;td>本地 vs 雲端 LLM&lt;/td>
 &lt;td>從隱私、成本、速度、能力四個維度建立基本對照&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/llm/00-foundations/why-llm-feels-slow/" data-link-title="0.1 為什麼 LLM 生字慢" data-link-desc="自回歸架構與記憶體頻寬瓶頸：為何即使 Mac 算力很強，本地 LLM 仍一個字一個字吐">0.1&lt;/a>&lt;/td>
 &lt;td>為什麼 LLM 生字慢&lt;/td>
 &lt;td>自回歸架構 + 記憶體頻寬瓶頸：一次只能吐一個 token&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&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;/td>
 &lt;td>介面 / 伺服器 / 模型三層架構&lt;/td>
 &lt;td>把任何本地 LLM 工具放回正確的層級，看懂工具關係&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/llm/00-foundations/openai-compatible-api/" data-link-title="0.3 OpenAI 相容 API" data-link-desc="為什麼幾乎所有本地 LLM 工具不用改就能切到本地：背後是同一套 API 形狀">0.3&lt;/a>&lt;/td>
 &lt;td>OpenAI 相容 API&lt;/td>
 &lt;td>為什麼幾乎所有工具不用改就能切到本地：背後是同一套 API 形狀&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&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&lt;/a>&lt;/td>
 &lt;td>MLX / MTP / oMLX 的區別&lt;/td>
 &lt;td>三者疊加而非互斥：framework、加速技巧、特化 server&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&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 量化下的可運作模型對照與系統保留">0.5&lt;/a>&lt;/td>
 &lt;td>Apple Silicon 記憶體預算&lt;/td>
 &lt;td>記憶體決定能跑什麼，Q4 量化下的可運作模型對照與系統保留&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/llm/00-foundations/info-judgment-frames/" data-link-title="0.6 判讀本地 LLM 資訊的五個框架" data-link-desc="本地 LLM 資訊更新快，學會用版本、層級、變數、能力、資料流五個框架評估文章與宣稱">0.6&lt;/a>&lt;/td>
 &lt;td>判讀本地 LLM 資訊的五個框架&lt;/td>
 &lt;td>版本時間、量化變數、三層架構、載入 vs 好用、隱私資料流&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/llm/00-foundations/privacy-data-flow/" data-link-title="0.7 隱私 / 資安的資料流原理" data-link-desc="從「位置」到「資料流」的思考升級：信任邊界、合約模型、零信任原則套用到 LLM 工作流">0.7&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/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&lt;/a>&lt;/td>
 &lt;td>Deterministic vs Fuzzy Engineering 典範&lt;/td>
 &lt;td>兩個典範的四維對照、guardrail 設計、跟 agent / workflow 的關係&lt;/td>
 &lt;/tr>
 &lt;/tbody>
&lt;/table>
&lt;h2 id="為什麼先讀模組零">為什麼先讀模組零&lt;/h2>
&lt;p>模組一的安裝步驟看起來只是 &lt;code>brew install&lt;/code> 加一行 &lt;code>ollama run&lt;/code>，但每個指令背後都隱含選擇：要選哪個推論伺服器、要拉哪個量化等級的模型、要不要打開 speculative decoding、API 接哪個 port。若沒有模組零的心智模型，這些選擇只能靠抄文章上的指令，遇到變化就無法判讀。&lt;/p>
&lt;p>例如網路上常見的「裝完 Ollama 就能用 MLX 加速」這種說法，背後混淆了三件事：Ollama 是不是用 MLX 當 backend、MLX 跟 Metal 在 Apple Silicon 上的關係、加速來自 MLX 還是 MTP 還是量化。讀完 &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&lt;/a> 後你會自然知道這句話該怎麼追問才能得到正確答案。&lt;/p></description><content:encoded><![CDATA[<p>本模組的核心目標是把「本地跑 LLM」這件事拆成可討論的工程概念。先建立心智模型再進入工具選擇，可以避開大量網路文章把 framework、加速技巧、伺服器混為一談的陷阱；讀完模組零再進模組一，就能用同一套詞彙判讀任何新的本地 LLM 工具是在解哪一層的問題。</p>
<p>讀完本模組後，你應該能清楚回答：本地跟雲端跑 LLM 的差別在哪、為什麼 LLM 一個字一個字吐而不是整段吐、什麼是介面 / 伺服器 / 模型三層架構、為何 OpenAI 相容 API 是整個生態的基石、MLX 跟 MTP 跟 oMLX 各自是什麼東西、自己這台 Mac 的記憶體能跑多大的模型。</p>
<h2 id="章節列表">章節列表</h2>
<table>
  <thead>
      <tr>
          <th>章節</th>
          <th>主題</th>
          <th>關鍵收穫</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td><a href="/blog/llm/00-foundations/local-vs-cloud/" data-link-title="0.0 本地 vs 雲端 LLM" data-link-desc="從隱私、成本、速度、能力四個維度建立本地與雲端 LLM 的基本對照">0.0</a></td>
          <td>本地 vs 雲端 LLM</td>
          <td>從隱私、成本、速度、能力四個維度建立基本對照</td>
      </tr>
      <tr>
          <td><a href="/blog/llm/00-foundations/why-llm-feels-slow/" data-link-title="0.1 為什麼 LLM 生字慢" data-link-desc="自回歸架構與記憶體頻寬瓶頸：為何即使 Mac 算力很強，本地 LLM 仍一個字一個字吐">0.1</a></td>
          <td>為什麼 LLM 生字慢</td>
          <td>自回歸架構 + 記憶體頻寬瓶頸：一次只能吐一個 token</td>
      </tr>
      <tr>
          <td><a href="/blog/llm/00-foundations/three-layer-architecture/" data-link-title="0.2 介面 / 伺服器 / 模型三層架構" data-link-desc="把任何本地 LLM 工具放回正確的層級，用三層心智模型看懂工具關係">0.2</a></td>
          <td>介面 / 伺服器 / 模型三層架構</td>
          <td>把任何本地 LLM 工具放回正確的層級，看懂工具關係</td>
      </tr>
      <tr>
          <td><a href="/blog/llm/00-foundations/openai-compatible-api/" data-link-title="0.3 OpenAI 相容 API" data-link-desc="為什麼幾乎所有本地 LLM 工具不用改就能切到本地：背後是同一套 API 形狀">0.3</a></td>
          <td>OpenAI 相容 API</td>
          <td>為什麼幾乎所有工具不用改就能切到本地：背後是同一套 API 形狀</td>
      </tr>
      <tr>
          <td><a href="/blog/llm/00-foundations/mlx-mtp-omlx/" data-link-title="0.4 MLX / MTP / oMLX 的區別" data-link-desc="三個常被混為一談的術語：framework、加速技巧、特化 server，疊加而非互斥">0.4</a></td>
          <td>MLX / MTP / oMLX 的區別</td>
          <td>三者疊加而非互斥：framework、加速技巧、特化 server</td>
      </tr>
      <tr>
          <td><a href="/blog/llm/00-foundations/hardware-memory-budget/" data-link-title="0.5 Apple Silicon 記憶體預算" data-link-desc="記憶體決定能跑什麼，Q4 量化下的可運作模型對照與系統保留">0.5</a></td>
          <td>Apple Silicon 記憶體預算</td>
          <td>記憶體決定能跑什麼，Q4 量化下的可運作模型對照與系統保留</td>
      </tr>
      <tr>
          <td><a href="/blog/llm/00-foundations/info-judgment-frames/" data-link-title="0.6 判讀本地 LLM 資訊的五個框架" data-link-desc="本地 LLM 資訊更新快，學會用版本、層級、變數、能力、資料流五個框架評估文章與宣稱">0.6</a></td>
          <td>判讀本地 LLM 資訊的五個框架</td>
          <td>版本時間、量化變數、三層架構、載入 vs 好用、隱私資料流</td>
      </tr>
      <tr>
          <td><a href="/blog/llm/00-foundations/privacy-data-flow/" data-link-title="0.7 隱私 / 資安的資料流原理" data-link-desc="從「位置」到「資料流」的思考升級：信任邊界、合約模型、零信任原則套用到 LLM 工作流">0.7</a></td>
          <td>隱私 / 資安的資料流原理</td>
          <td>從「位置」到「資料流」思考、信任邊界、零信任原則</td>
      </tr>
      <tr>
          <td><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</a></td>
          <td>Deterministic vs Fuzzy Engineering 典範</td>
          <td>兩個典範的四維對照、guardrail 設計、跟 agent / workflow 的關係</td>
      </tr>
  </tbody>
</table>
<h2 id="為什麼先讀模組零">為什麼先讀模組零</h2>
<p>模組一的安裝步驟看起來只是 <code>brew install</code> 加一行 <code>ollama run</code>，但每個指令背後都隱含選擇：要選哪個推論伺服器、要拉哪個量化等級的模型、要不要打開 speculative decoding、API 接哪個 port。若沒有模組零的心智模型，這些選擇只能靠抄文章上的指令，遇到變化就無法判讀。</p>
<p>例如網路上常見的「裝完 Ollama 就能用 MLX 加速」這種說法，背後混淆了三件事：Ollama 是不是用 MLX 當 backend、MLX 跟 Metal 在 Apple Silicon 上的關係、加速來自 MLX 還是 MTP 還是量化。讀完 <a href="/blog/llm/00-foundations/mlx-mtp-omlx/" data-link-title="0.4 MLX / MTP / oMLX 的區別" data-link-desc="三個常被混為一談的術語：framework、加速技巧、特化 server，疊加而非互斥">0.4</a> 後你會自然知道這句話該怎麼追問才能得到正確答案。</p>
<h2 id="模組零的閱讀策略">模組零的閱讀策略</h2>
<p>本模組八篇章節彼此獨立，但建議依下列順序讀：</p>
<ol>
<li>先讀 <a href="/blog/llm/00-foundations/local-vs-cloud/" data-link-title="0.0 本地 vs 雲端 LLM" data-link-desc="從隱私、成本、速度、能力四個維度建立本地與雲端 LLM 的基本對照">0.0 本地 vs 雲端</a> 跟 <a href="/blog/llm/00-foundations/why-llm-feels-slow/" data-link-title="0.1 為什麼 LLM 生字慢" data-link-desc="自回歸架構與記憶體頻寬瓶頸：為何即使 Mac 算力很強，本地 LLM 仍一個字一個字吐">0.1 為什麼 LLM 生字慢</a>，建立「本地 LLM 解什麼問題、不解什麼問題」的判斷。</li>
<li>接著讀 <a href="/blog/llm/00-foundations/three-layer-architecture/" data-link-title="0.2 介面 / 伺服器 / 模型三層架構" data-link-desc="把任何本地 LLM 工具放回正確的層級，用三層心智模型看懂工具關係">0.2 三層架構</a> 跟 <a href="/blog/llm/00-foundations/openai-compatible-api/" data-link-title="0.3 OpenAI 相容 API" data-link-desc="為什麼幾乎所有本地 LLM 工具不用改就能切到本地：背後是同一套 API 形狀">0.3 OpenAI 相容 API</a>，建立「工具如何拼裝」的判斷。</li>
<li>然後讀 <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>，避開最常見的術語陷阱。</li>
<li>接著讀 <a href="/blog/llm/00-foundations/hardware-memory-budget/" data-link-title="0.5 Apple Silicon 記憶體預算" data-link-desc="記憶體決定能跑什麼，Q4 量化下的可運作模型對照與系統保留">0.5 硬體記憶體</a> 跟 <a href="/blog/llm/00-foundations/info-judgment-frames/" data-link-title="0.6 判讀本地 LLM 資訊的五個框架" data-link-desc="本地 LLM 資訊更新快，學會用版本、層級、變數、能力、資料流五個框架評估文章與宣稱">0.6 判讀框架</a>、把心智模型對到自己手上這台 Mac 的現實、並建立評估新資訊的反射。</li>
<li>讀 <a href="/blog/llm/00-foundations/privacy-data-flow/" data-link-title="0.7 隱私 / 資安的資料流原理" data-link-desc="從「位置」到「資料流」的思考升級：信任邊界、合約模型、零信任原則套用到 LLM 工作流">0.7 隱私資料流原理</a>、把 0.6 框架五展開成可操作的設計原則。</li>
<li>最後讀 <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>、建立「LLM 軟體跟傳統軟體的設計典範差異」心智模型、為進入<a href="/blog/llm/04-applications/" data-link-title="模組四：LLM 應用層原理" data-link-desc="Prompt 技術光譜、RAG、tool use、agent、應用層協議、人機協作、multi-agent、workflow 編排、eval 設計：跨工具不變的概念地圖">模組四 LLM 應用層</a> 做準備。</li>
</ol>
<p>讀完後可進 <a href="/blog/llm/01-local-llm-services/" data-link-title="模組一：本地 LLM 服務的安裝與應用" data-link-desc="Ollama、LM Studio、llama.cpp 的安裝與差異、VS Code &#43; Continue.dev 整合、模型選型與期望管理">模組一：本地 LLM 服務的安裝與應用</a> 看安裝步驟、或直接進 <a href="/blog/llm/04-applications/" data-link-title="模組四：LLM 應用層原理" data-link-desc="Prompt 技術光譜、RAG、tool use、agent、應用層協議、人機協作、multi-agent、workflow 編排、eval 設計：跨工具不變的概念地圖">模組四 LLM 應用層</a> 看典範怎麼落到 RAG / agent / workflow 設計。</p>
<h2 id="不在本模組內的主題">不在本模組內的主題</h2>
<p>本模組聚焦「操作層心智模型」、其他層次交給對應模組：</p>
<ol>
<li><strong>Transformer 架構數學細節</strong>（attention、positional encoding、residual stream 等）→ <a href="/blog/llm/03-theoretical-foundations/" data-link-title="模組三：LLM 的理論基礎" data-link-desc="從神經網路、embedding、attention、Transformer 架構、訓練到 sampling：LLM 內部運作的完整理論圖像">模組三 LLM 理論基礎</a></li>
<li><strong>線性代數、機率、最佳化、數值精度等數學工具</strong> → <a href="/blog/llm/02-math-foundations/" data-link-title="模組二：LLM 的數學基礎" data-link-desc="整理 LLM 推論背後需要理解的線性代數、機率與資訊論、最佳化、數值精度等數學概念">模組二 數學基礎</a></li>
<li><strong>訓練、fine-tuning、RLHF、DPO</strong> → <a href="/blog/llm/03-theoretical-foundations/training-pipeline/" data-link-title="3.4 訓練流程：pre-train → SFT → RLHF" data-link-desc="LLM 的三階段訓練：預訓練、指令微調、人類反饋強化學習；各階段目標與最新替代方案">模組三 3.4 訓練流程</a></li>
<li><strong>具體工具的安裝步驟</strong> → <a href="/blog/llm/01-local-llm-services/" data-link-title="模組一：本地 LLM 服務的安裝與應用" data-link-desc="Ollama、LM Studio、llama.cpp 的安裝與差異、VS Code &#43; Continue.dev 整合、模型選型與期望管理">模組一 本地 LLM 服務</a></li>
<li><strong>雲端 GPU 部署</strong> → 本指南範圍只在 Apple Silicon Mac、請另尋資料中心 inference 教材</li>
</ol>
<p>本模組只提供「Mac 本地寫 code」這條最短路徑需要的概念基底；其他層次的學習路線見<a href="/blog/llm/" data-link-title="LLM 寫 code 工程實務指南：從心智模型到應用架構" data-link-desc="以寫 code 場景為主、涵蓋本地推論（Mac / PC）、雲端混用、LLM 數學與理論基礎、應用層架構（RAG / tool use / agent / VLM / 靜態 deployment）、reasoning model 與 speculative decoding、本地 dev 安全、跨工具世代不變的原理">首頁的模組對照表</a>。</p>
]]></content:encoded></item></channel></rss>