<?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>模組一：本地 LLM 服務的安裝與應用 on Tarragon</title><link>https://tarrragon.github.io/blog/llm/01-local-llm-services/</link><description>Recent content in 模組一：本地 LLM 服務的安裝與應用 on Tarragon</description><generator>Hugo -- gohugo.io</generator><language>zh-TW</language><copyright>Tarragon (CC BY 4.0)</copyright><lastBuildDate>Mon, 11 May 2026 00:00:00 +0000</lastBuildDate><atom:link href="https://tarrragon.github.io/blog/llm/01-local-llm-services/index.xml" rel="self" type="application/rss+xml"/><item><title>1.1 LM Studio：GUI 探索模型</title><link>https://tarrragon.github.io/blog/llm/01-local-llm-services/lm-studio/</link><pubDate>Mon, 11 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/llm/01-local-llm-services/lm-studio/</guid><description>&lt;p>LM Studio 跟 Ollama 一樣屬於&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>、但定位完全不同：Ollama 是 CLI-first、LM Studio 是 GUI-first。它的核心承諾是「不打開終端機也能玩本地 LLM」、特別適合對 Hugging Face model hub（社群最大的開源模型 registry、提供權重檔下載與比較）、&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/speculative-decoding/" data-link-title="Speculative Decoding" data-link-desc="用小模型猜未來 token、大模型並行驗證的加速技巧">speculative decoding&lt;/a> 還在摸索階段的使用者。&lt;/p>
&lt;p>對寫 code 場景來說，LM Studio 不一定是日常主力（Ollama 通常更穩、生態更成熟），但它在「探索新模型」「視覺化看推論參數」「拿來教其他人本地 LLM」這幾個情境上明顯佔優勢。本章說明它的安裝、模型瀏覽器、server 模式啟用，以及跟 Ollama 並存的配置。&lt;/p>
&lt;h2 id="本章目標">本章目標&lt;/h2>
&lt;p>讀完本章後，你應該能：&lt;/p>
&lt;ol>
&lt;li>安裝 LM Studio 並下載第一個模型。&lt;/li>
&lt;li>在 GUI 跟模型對話、調整參數。&lt;/li>
&lt;li>啟用 LM Studio 的 OpenAI 相容 server 模式。&lt;/li>
&lt;li>判斷你的工作流適不適合用 LM Studio 當主力。&lt;/li>
&lt;li>讓 LM Studio 與 Ollama 並存。&lt;/li>
&lt;/ol>
&lt;h2 id="安裝">安裝&lt;/h2>
&lt;p>LM Studio 是商業軟體（個人使用免費），不在 Homebrew core repo 裡。直接從官網下載：&lt;/p>
&lt;ol>
&lt;li>開 &lt;a href="https://lmstudio.ai">lmstudio.ai&lt;/a>&lt;/li>
&lt;li>下載 macOS（Apple Silicon）版本&lt;/li>
&lt;li>把 LM Studio.app 拖到 Applications&lt;/li>
&lt;li>第一次開啟會被 macOS 安全提示擋，到「系統設定 &amp;gt; 隱私權與安全性」放行&lt;/li>
&lt;/ol>
&lt;p>裝完開啟 app，會看到三個主要分頁：&lt;/p>
&lt;ul>
&lt;li>&lt;strong>Discover&lt;/strong>：搜尋 Hugging Face model hub、下載模型&lt;/li>
&lt;li>&lt;strong>My Models&lt;/strong>：管理已下載模型&lt;/li>
&lt;li>&lt;strong>Chat / Developer&lt;/strong>：跟模型對話、啟用 server&lt;/li>
&lt;/ul>
&lt;h2 id="下載第一個模型">下載第一個模型&lt;/h2>
&lt;p>Discover 分頁把 Hugging Face 模型搜尋、&lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/quantization/" data-link-title="Quantization" data-link-desc="用較少 bits 表示模型權重：壓縮記憶體佔用、加快生字速度，代價是少量品質衰減">量化等級&lt;/a>挑選、記憶體適配判讀集中在同一個面板。在 Discover 分頁搜尋模型名（例如 &lt;code>gemma-4&lt;/code>）、會列出 Hugging Face 上的對應 repo：&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>Repo 名稱&lt;/td>
 &lt;td>例如 &lt;code>bartowski/gemma-4-31b-it-GGUF&lt;/code>&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>量化等級&lt;/td>
 &lt;td>Q4_K_M、Q5_K_M、Q8 等，列在每個檔案旁邊&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>檔案大小&lt;/td>
 &lt;td>直接顯示 GB 數，方便判斷是否塞得進記憶體&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>適配建議&lt;/td>
 &lt;td>LM Studio 會根據你 Mac 記憶體標「Recommended / Too Large」&lt;/td>
 &lt;/tr>
 &lt;/tbody>
&lt;/table>
&lt;p>選一個合適量化等級點下載。Q4_K_M 在多數場景是甜蜜點；32GB Mac 跑 31B Q5_K_M 也順暢。下載中可以繼續操作其他功能。&lt;/p>
&lt;p>陷阱：&lt;/p>
&lt;ol>
&lt;li>&lt;strong>Repo 來源要看&lt;/strong>。Hugging Face 上同一個模型有多個社群重新封裝的 repo。&lt;code>google/gemma-4-...&lt;/code> 是官方 repo；&lt;code>bartowski/...&lt;/code> 等是社群常見的高品質 quant 提供者。挑下載量高、最近更新的 repo 較安全。完整的供應鏈信任判讀（量化版本污染、權重完整性、registry 信任）見 &lt;a href="https://tarrragon.github.io/blog/llm/06-security/model-supply-chain-trust/" data-link-title="6.0 模型供應鏈與信任邊界" data-link-desc="個人 dev 用本地 LLM 時的模型權重來源信任：GGUF 完整性、Hugging Face / Ollama registry 信任、量化版本污染、檔案完整性檢查">6.0 模型供應鏈與信任邊界&lt;/a>。&lt;/li>
&lt;li>&lt;strong>不是所有檔案都要下載&lt;/strong>。一個 repo 可能有 5 ~ 10 個量化檔案，下載你選的那個就好。LM Studio UI 有時讓人誤以為要全選。&lt;/li>
&lt;li>&lt;strong>下載完成後檢查路徑&lt;/strong>：預設下載到 &lt;code>~/.cache/lm-studio/models/&lt;/code>、跟 Ollama 的 &lt;code>~/.ollama/models/&lt;/code> 分開。兩邊 model storage 各自獨立、想在兩個伺服器都用同一個模型要分別下載。&lt;/li>
&lt;/ol>
&lt;h2 id="chat-分頁與推論參數調整">Chat 分頁與推論參數調整&lt;/h2>
&lt;p>下載完到 Chat 分頁、左上角 model selector 選剛下載的模型。LM Studio 會把模型載入記憶體（30 ~ 60 秒）、然後就能對話。&lt;/p></description><content:encoded><![CDATA[<p>LM Studio 跟 Ollama 一樣屬於<a href="/blog/llm/00-foundations/three-layer-architecture/" data-link-title="0.2 介面 / 伺服器 / 模型三層架構" data-link-desc="把任何本地 LLM 工具放回正確的層級，用三層心智模型看懂工具關係">本地推論伺服器層</a>、但定位完全不同：Ollama 是 CLI-first、LM Studio 是 GUI-first。它的核心承諾是「不打開終端機也能玩本地 LLM」、特別適合對 Hugging Face model hub（社群最大的開源模型 registry、提供權重檔下載與比較）、<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> 還在摸索階段的使用者。</p>
<p>對寫 code 場景來說，LM Studio 不一定是日常主力（Ollama 通常更穩、生態更成熟），但它在「探索新模型」「視覺化看推論參數」「拿來教其他人本地 LLM」這幾個情境上明顯佔優勢。本章說明它的安裝、模型瀏覽器、server 模式啟用，以及跟 Ollama 並存的配置。</p>
<h2 id="本章目標">本章目標</h2>
<p>讀完本章後，你應該能：</p>
<ol>
<li>安裝 LM Studio 並下載第一個模型。</li>
<li>在 GUI 跟模型對話、調整參數。</li>
<li>啟用 LM Studio 的 OpenAI 相容 server 模式。</li>
<li>判斷你的工作流適不適合用 LM Studio 當主力。</li>
<li>讓 LM Studio 與 Ollama 並存。</li>
</ol>
<h2 id="安裝">安裝</h2>
<p>LM Studio 是商業軟體（個人使用免費），不在 Homebrew core repo 裡。直接從官網下載：</p>
<ol>
<li>開 <a href="https://lmstudio.ai">lmstudio.ai</a></li>
<li>下載 macOS（Apple Silicon）版本</li>
<li>把 LM Studio.app 拖到 Applications</li>
<li>第一次開啟會被 macOS 安全提示擋，到「系統設定 &gt; 隱私權與安全性」放行</li>
</ol>
<p>裝完開啟 app，會看到三個主要分頁：</p>
<ul>
<li><strong>Discover</strong>：搜尋 Hugging Face model hub、下載模型</li>
<li><strong>My Models</strong>：管理已下載模型</li>
<li><strong>Chat / Developer</strong>：跟模型對話、啟用 server</li>
</ul>
<h2 id="下載第一個模型">下載第一個模型</h2>
<p>Discover 分頁把 Hugging Face 模型搜尋、<a href="/blog/llm/knowledge-cards/quantization/" data-link-title="Quantization" data-link-desc="用較少 bits 表示模型權重：壓縮記憶體佔用、加快生字速度，代價是少量品質衰減">量化等級</a>挑選、記憶體適配判讀集中在同一個面板。在 Discover 分頁搜尋模型名（例如 <code>gemma-4</code>）、會列出 Hugging Face 上的對應 repo：</p>
<table>
  <thead>
      <tr>
          <th>顯示資訊</th>
          <th>解讀</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>Repo 名稱</td>
          <td>例如 <code>bartowski/gemma-4-31b-it-GGUF</code></td>
      </tr>
      <tr>
          <td>量化等級</td>
          <td>Q4_K_M、Q5_K_M、Q8 等，列在每個檔案旁邊</td>
      </tr>
      <tr>
          <td>檔案大小</td>
          <td>直接顯示 GB 數，方便判斷是否塞得進記憶體</td>
      </tr>
      <tr>
          <td>適配建議</td>
          <td>LM Studio 會根據你 Mac 記憶體標「Recommended / Too Large」</td>
      </tr>
  </tbody>
</table>
<p>選一個合適量化等級點下載。Q4_K_M 在多數場景是甜蜜點；32GB Mac 跑 31B Q5_K_M 也順暢。下載中可以繼續操作其他功能。</p>
<p>陷阱：</p>
<ol>
<li><strong>Repo 來源要看</strong>。Hugging Face 上同一個模型有多個社群重新封裝的 repo。<code>google/gemma-4-...</code> 是官方 repo；<code>bartowski/...</code> 等是社群常見的高品質 quant 提供者。挑下載量高、最近更新的 repo 較安全。完整的供應鏈信任判讀（量化版本污染、權重完整性、registry 信任）見 <a href="/blog/llm/06-security/model-supply-chain-trust/" data-link-title="6.0 模型供應鏈與信任邊界" data-link-desc="個人 dev 用本地 LLM 時的模型權重來源信任：GGUF 完整性、Hugging Face / Ollama registry 信任、量化版本污染、檔案完整性檢查">6.0 模型供應鏈與信任邊界</a>。</li>
<li><strong>不是所有檔案都要下載</strong>。一個 repo 可能有 5 ~ 10 個量化檔案，下載你選的那個就好。LM Studio UI 有時讓人誤以為要全選。</li>
<li><strong>下載完成後檢查路徑</strong>：預設下載到 <code>~/.cache/lm-studio/models/</code>、跟 Ollama 的 <code>~/.ollama/models/</code> 分開。兩邊 model storage 各自獨立、想在兩個伺服器都用同一個模型要分別下載。</li>
</ol>
<h2 id="chat-分頁與推論參數調整">Chat 分頁與推論參數調整</h2>
<p>下載完到 Chat 分頁、左上角 model selector 選剛下載的模型。LM Studio 會把模型載入記憶體（30 ~ 60 秒）、然後就能對話。</p>
<p>右側面板提供推論參數調整：</p>
<table>
  <thead>
      <tr>
          <th>參數</th>
          <th>預設</th>
          <th>何時調整</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>Temperature</td>
          <td>0.7</td>
          <td>寫 code 建議 0.2 ~ 0.4 增加確定性</td>
      </tr>
      <tr>
          <td>Top-K</td>
          <td>40</td>
          <td>通常不動</td>
      </tr>
      <tr>
          <td>Top-P</td>
          <td>0.95</td>
          <td>通常不動</td>
      </tr>
      <tr>
          <td>Repeat Penalty</td>
          <td>1.1</td>
          <td>模型一直重複時微調</td>
      </tr>
      <tr>
          <td>Context Length</td>
          <td>模型支援的最大值</td>
          <td>短 context 任務可以調小省記憶體</td>
      </tr>
      <tr>
          <td>GPU Offload Layers</td>
          <td>Auto</td>
          <td>M-series Mac 留 Auto，Apple Silicon 是統一記憶體</td>
      </tr>
  </tbody>
</table>
<p>對寫 code 場景的關鍵調整是 <strong>Temperature 降到 0.2 ~ 0.4</strong>，可以讓回答更穩定、減少幻覺。預設 0.7 是給創意寫作的設定。</p>
<h2 id="speculative-decoding-設定面板">Speculative decoding 設定面板</h2>
<p>LM Studio 內建 <a href="/blog/llm/knowledge-cards/speculative-decoding/" data-link-title="Speculative Decoding" data-link-desc="用小模型猜未來 token、大模型並行驗證的加速技巧">speculative decoding</a> 的 UI 設定。在 model 載入頁面下方有 <strong>Draft Model</strong> 設定區：</p>
<ol>
<li>選 target model（主力，例如 Gemma 4 31B）</li>
<li>選 draft model（小模型，例如 Gemma 4 E4B）</li>
<li>啟用 speculative decoding</li>
</ol>
<p><a href="/blog/llm/knowledge-cards/speculative-decoding/" data-link-title="Speculative Decoding" data-link-desc="用小模型猜未來 token、大模型並行驗證的加速技巧">Speculative decoding</a> 真的加速需要 target 與 <a href="/blog/llm/knowledge-cards/drafter-model/" data-link-title="Drafter Model" data-link-desc="speculative decoding 中用來快速猜未來 token 的小模型">drafter</a> 用同一個 tokenizer。Gemma 4 31B 配 Gemma 4 E4B 可以工作；Gemma 4 配 Llama 因 tokenizer 不同無法配對。LM Studio UI 會自動過濾相容的 draft 候選。</p>
<p>跟 Ollama 比，LM Studio 的優勢是「能看到並調整每個推論細節」。劣勢是「Gemma 4 的官方 MTP drafter 整合不是一鍵」，要自己挑 draft model。多數使用者用 Ollama 的 <code>gemma4:31b-coding-mtp-bf16</code> 一行解決就好；想自己組合 target + drafter 的進階使用者選 LM Studio。</p>
<h2 id="啟用-server-模式">啟用 Server 模式</h2>
<p>Server 模式是 LM Studio 暴露 OpenAI 相容 API 的開關、預設關閉以避免 GUI 使用者誤開網路 port。讓 VS Code 等介面層接 LM Studio、要開 <strong>Local Server</strong> 模式：</p>
<ol>
<li>切到 Developer 分頁（左側 icon 像 <code>&lt;/&gt;</code>）</li>
<li>在頂部 model selector 選要 serve 的模型</li>
<li>點 <strong>Start Server</strong></li>
</ol>
<p>預設聽 <code>localhost:1234</code>，提供 OpenAI 相容 API。</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">curl http://localhost:1234/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;gemma-4-31b-it&#34;,
</span></span></span><span class="line"><span class="ln">5</span><span class="cl"><span class="s1">    &#34;messages&#34;: [{&#34;role&#34;: &#34;user&#34;, &#34;content&#34;: &#34;Hello&#34;}],
</span></span></span><span class="line"><span class="ln">6</span><span class="cl"><span class="s1">    &#34;stream&#34;: false
</span></span></span><span class="line"><span class="ln">7</span><span class="cl"><span class="s1">  }&#39;</span></span></span></code></pre></div><p>回應的 JSON 應該包含 <code>choices[0].message.content</code>。</p>
<p>陷阱：</p>
<ol>
<li><strong>Server 跟 GUI 同生命週期</strong>。關閉 LM Studio 視窗或登出 macOS 會停止 server、IDE 連不上。修法：日常常駐改用 <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>、LM Studio 只在桌面 session 啟動探索。</li>
<li><strong>CORS 預設關</strong>。要從瀏覽器（如 Open WebUI 跑在不同 port）連，要去 Server 設定打開 CORS。</li>
<li><strong>Model name 不是 tag</strong>。LM Studio 在 API 用的 model name 是檔名（如 <code>gemma-4-31b-it</code>），跟 Ollama 的 tag 格式不同。</li>
</ol>
<h2 id="與-ollama-並存">與 Ollama 並存</h2>
<p>LM Studio（port 1234）跟 Ollama（port 11434）port 不同，可以同時跑。在 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;Ollama: Gemma 4 31B MTP&#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="nt">&#34;title&#34;</span><span class="p">:</span> <span class="s2">&#34;LM Studio: Qwen3-Coder 30B&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="ln">11</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">12</span><span class="cl">      <span class="nt">&#34;model&#34;</span><span class="p">:</span> <span class="s2">&#34;qwen3-coder-30b&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="ln">13</span><span class="cl">      <span class="nt">&#34;apiBase&#34;</span><span class="p">:</span> <span class="s2">&#34;http://localhost:1234/v1&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="ln">14</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">15</span><span class="cl">    <span class="p">}</span>
</span></span><span class="line"><span class="ln">16</span><span class="cl">  <span class="p">]</span>
</span></span><span class="line"><span class="ln">17</span><span class="cl"><span class="p">}</span></span></span></code></pre></div><p>UI 上可以下拉切換 model。這個設計讓你「Ollama 跑主力、LM Studio 跑實驗模型」，兩條工作流不互相干擾。</p>
<h2 id="lm-studio-適合誰">LM Studio 適合誰</h2>
<table>
  <thead>
      <tr>
          <th>你是這樣的人</th>
          <th>LM Studio 適合度</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>GUI 派、不愛打 CLI</td>
          <td>高</td>
      </tr>
      <tr>
          <td>想看推論參數細節並調整</td>
          <td>高</td>
      </tr>
      <tr>
          <td>想頻繁探索 Hugging Face 上新模型</td>
          <td>高</td>
      </tr>
      <tr>
          <td>想自己組合 target + drafter</td>
          <td>高</td>
      </tr>
      <tr>
          <td>想 server 隨開機常駐</td>
          <td>低（GUI app 不適合 daemon）</td>
      </tr>
      <tr>
          <td>想跟 Anthropic Claude Code 等工具整合</td>
          <td>中（API 相容但 model name 規則不同）</td>
      </tr>
      <tr>
          <td>已經習慣 Ollama CLI</td>
          <td>低（除非有探索需求）</td>
      </tr>
  </tbody>
</table>
<p>簡單的建議：<strong>LM Studio 適合當「副廚」、Ollama 適合當「主廚」</strong>。日常工作流用 Ollama 跑主力模型、需要探索新東西時開 LM Studio。</p>
<h2 id="何時改回-ollama-或-llamacpp">何時改回 Ollama 或 llama.cpp</h2>
<p>LM Studio 的 GUI 定位在以下情境會變成阻礙、建議改用其他伺服器：</p>
<table>
  <thead>
      <tr>
          <th>情境</th>
          <th>建議路由</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>Headless 環境（無 GUI 桌機 / 遠端 SSH）</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> — CLI-first、能用 launchd / systemd 跑</td>
      </tr>
      <tr>
          <td>CI / 自動化跑 batch 推論</td>
          <td>Ollama 或 llama-server — 可用 systemd / Docker 起、不依賴 GUI session</td>
      </tr>
      <tr>
          <td>需要 daemon 24/7 常駐</td>
          <td>Ollama 配 <a href="/blog/llm/knowledge-cards/launchd-service/" data-link-title="launchd Service" data-link-desc="macOS 原生的服務管理機制、把 process 註冊成自動啟動的 daemon 或 agent">launchd service</a> — LM Studio 視窗關閉 server 就停</td>
      </tr>
      <tr>
          <td>自己量化模型 / 跑特殊冷門模型</td>
          <td><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> — 直接面對 GGUF / quantize 工具</td>
      </tr>
      <tr>
          <td>想用 Ollama Library 的 1-tag 即裝</td>
          <td>Ollama — <code>ollama run gemma4:31b-coding-mtp-bf16</code> 已內含 MTP drafter、LM Studio 需手動挑 draft model</td>
      </tr>
  </tbody>
</table>
<p>LM Studio 的最佳定位是「需要 GUI、桌面 session 內探索、有人在電腦前操作」的場景；任何「沒人看著 / 後台跑 / 跨機器 daemon」的需求、Ollama 通常更穩。</p>
<h2 id="跟-anthropic-claude-api-的對比">跟 Anthropic Claude API 的對比</h2>
<p>如果你習慣 Claude 的工具用法（Anthropic Console、Claude Code）、LM Studio 的 GUI 體驗比較像 Anthropic Console：可以調 system prompt、看 token 計數、儲存對話。兩者都用 <a href="/blog/llm/00-foundations/openai-compatible-api/" data-link-title="0.3 OpenAI 相容 API" data-link-desc="為什麼幾乎所有本地 LLM 工具不用改就能切到本地：背後是同一套 API 形狀">OpenAI 相容 API</a> 形狀（Anthropic 自有 messages API 是另一條路徑、LM Studio 不接 Anthropic 格式）。差別是：</p>
<table>
  <thead>
      <tr>
          <th>維度</th>
          <th>Anthropic Console</th>
          <th>LM Studio</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>模型</td>
          <td>Claude Sonnet、Opus、Haiku（雲端）</td>
          <td>自己下載的本地模型</td>
      </tr>
      <tr>
          <td>隱私</td>
          <td>走 Anthropic 雲端</td>
          <td>完全本地</td>
      </tr>
      <tr>
          <td>計費</td>
          <td>按 token 計費</td>
          <td>一次性硬體</td>
      </tr>
      <tr>
          <td>進階功能</td>
          <td>Tools、Vision、Computer Use 完整</td>
          <td>視模型而定，多半較陽春</td>
      </tr>
      <tr>
          <td>Streaming UI</td>
          <td>流暢</td>
          <td>流暢</td>
      </tr>
      <tr>
          <td>Prompt 偵錯</td>
          <td>Workbench 完整</td>
          <td>Chat / Developer 分頁可調參數</td>
      </tr>
  </tbody>
</table>
<p>LM Studio 對寫 code 場景不是 Anthropic Console 的替代品，但作為「本地版 console」的體驗很完整。</p>
<h2 id="下一章">下一章</h2>
<p>下一章：<a href="/blog/llm/01-local-llm-services/llama-cpp/" data-link-title="1.2 llama.cpp：底層推論引擎" data-link-desc="GGUF 格式、量化、MTP 仍 beta；多數讀者不需要直接接觸，Ollama 已經包好">1.2 llama.cpp 底層引擎</a>，澄清網路上「llama.cpp 才是真本地」這類迷思。</p>
]]></content:encoded></item><item><title>1.2 llama.cpp：底層推論引擎</title><link>https://tarrragon.github.io/blog/llm/01-local-llm-services/llama-cpp/</link><pubDate>Mon, 11 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/llm/01-local-llm-services/llama-cpp/</guid><description>&lt;p>llama.cpp 是本地 LLM 生態的&lt;strong>底層推論引擎&lt;/strong>、2023 年由 ggerganov 釋出、後來成為 Ollama、LM Studio 等高層工具的內部 backend。它的核心承諾是「用純 C++ 寫一個高效能的 &lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/gguf/" data-link-title="GGUF" data-link-desc="llama.cpp 生態定義的模型權重格式：把權重、tokenizer、metadata 打包成單一檔案">GGUF&lt;/a> 模型推論器、跨平台、CPU/GPU/Apple Metal 都能跑」。&lt;/p>
&lt;p>對寫 code 場景的多數讀者來說、&lt;strong>Ollama 已涵蓋 llama.cpp 的直接使用情境&lt;/strong>。Ollama 已經把它包好、使用者看到的是 model tag 跟 CLI；llama.cpp 自己的編譯、量化、參數設定都被抽象掉。本章的目的是澄清網路上「llama.cpp 才是真本地、Ollama 是壓榨版」這類迷思、並給少數需要直接用 llama.cpp 的場景一條路。&lt;/p>
&lt;h2 id="本章目標">本章目標&lt;/h2>
&lt;p>讀完本章後，你應該能：&lt;/p>
&lt;ol>
&lt;li>理解 llama.cpp 在三層架構中的位置。&lt;/li>
&lt;li>知道 Ollama 與 llama.cpp 的關係（包含 / 上游）。&lt;/li>
&lt;li>判斷自己什麼情境下需要直接用 llama.cpp、什麼情境不用。&lt;/li>
&lt;li>看懂 GGUF 格式與量化標籤（Q4_K_M、Q5_K_S 等）。&lt;/li>
&lt;li>對「llama.cpp 整合 Gemma 4 MTP」這類消息建立判讀反射。&lt;/li>
&lt;/ol>
&lt;h2 id="llamacpp-在哪一層">llama.cpp 在哪一層&lt;/h2>
&lt;p>llama.cpp 同時跨&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>的兩層：&lt;/p>
&lt;ol>
&lt;li>&lt;strong>推論引擎&lt;/strong>（library、可被其他程式呼叫的程式碼集合）：核心 C++ library、把 GGUF 權重載入、跑 forward pass（神經網路把輸入算到最後一層產出 token 的單次計算）。Ollama、LM Studio、許多其他工具的 backend 就是這個 library。&lt;/li>
&lt;li>&lt;strong>CLI 工具與 server&lt;/strong>（&lt;code>llama-cli&lt;/code>、&lt;code>llama-server&lt;/code>）：附帶的命令列工具與 HTTP server、可以直接拿來用、但需要自己編譯與配置。&lt;/li>
&lt;/ol>
&lt;p>當你看到「我用 Ollama 跑 Gemma 4」，實際發生的事是：&lt;/p>





&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-text" data-lang="text">&lt;span class="line">&lt;span class="ln">1&lt;/span>&lt;span class="cl">你的指令
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">2&lt;/span>&lt;span class="cl"> ↓
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">3&lt;/span>&lt;span class="cl">Ollama CLI / server（包裝層、模型管理）
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">4&lt;/span>&lt;span class="cl"> ↓
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">5&lt;/span>&lt;span class="cl">llama.cpp library（推論核心）
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">6&lt;/span>&lt;span class="cl"> ↓
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">7&lt;/span>&lt;span class="cl">Metal API（Apple Silicon GPU）
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">8&lt;/span>&lt;span class="cl"> ↓
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">9&lt;/span>&lt;span class="cl">Apple Silicon 硬體&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>所以「Ollama vs llama.cpp」不是兩個競爭品，是「上層包裝」跟「底層引擎」的關係。&lt;/p>
&lt;h2 id="ollama-跟-llamacpp-的關係">Ollama 跟 llama.cpp 的關係&lt;/h2>
&lt;p>Ollama 是 llama.cpp 的下游 wrapper、但 fork 跟 upstream 不是即時同步的關係。Ollama 在自己的 repo 裡放一份 vendored（複製進來、跟隨 Ollama 自家發版節奏管理）的 llama.cpp source、加上他們自己的 patches（補丁修改）；新功能進入 Ollama 的順序通常是：&lt;/p>
&lt;ol>
&lt;li>llama.cpp 上游加新功能或修 bug&lt;/li>
&lt;li>Ollama 把該 commit cherry-pick（從另一個 branch 單獨挑出一個 commit 套用）進來&lt;/li>
&lt;li>Ollama 發新版&lt;/li>
&lt;/ol>
&lt;p>但反過來也成立：&lt;strong>Ollama 有時搶先在 fork 裡加上游還沒接受的功能&lt;/strong>，例如 Gemma 4 MTP 在 2026/5/7 的 Ollama v0.23.1 一鍵支援，當時 llama.cpp 上游的 Gemma 4 MTP 整合還是 feature request。&lt;/p>
&lt;p>這個關係的啟示：&lt;/p>
&lt;ol>
&lt;li>&lt;strong>「llama.cpp vs Ollama 誰先進」視功能而定&lt;/strong>：具體功能要實際對照 release notes、「上游 / 下游」直覺只是初步參考、未必符合實際版本狀態。&lt;/li>
&lt;li>&lt;strong>判讀支援度看 release notes&lt;/strong>：主版本號只是命名、實際功能列表要看具體版本的 changelog。&lt;/li>
&lt;li>&lt;strong>直接用 llama.cpp 跟靠近上游是兩件事&lt;/strong>：Ollama 的 patches 有時是「上游還沒接受、但已經實用的功能」。&lt;/li>
&lt;/ol>
&lt;h2 id="什麼情境真的需要直接用-llamacpp">什麼情境真的需要直接用 llama.cpp&lt;/h2>
&lt;p>絕大多數寫 code 場景，Ollama 完全夠用。直接用 llama.cpp 的合理情境只有少數：&lt;/p></description><content:encoded><![CDATA[<p>llama.cpp 是本地 LLM 生態的<strong>底層推論引擎</strong>、2023 年由 ggerganov 釋出、後來成為 Ollama、LM Studio 等高層工具的內部 backend。它的核心承諾是「用純 C++ 寫一個高效能的 <a href="/blog/llm/knowledge-cards/gguf/" data-link-title="GGUF" data-link-desc="llama.cpp 生態定義的模型權重格式：把權重、tokenizer、metadata 打包成單一檔案">GGUF</a> 模型推論器、跨平台、CPU/GPU/Apple Metal 都能跑」。</p>
<p>對寫 code 場景的多數讀者來說、<strong>Ollama 已涵蓋 llama.cpp 的直接使用情境</strong>。Ollama 已經把它包好、使用者看到的是 model tag 跟 CLI；llama.cpp 自己的編譯、量化、參數設定都被抽象掉。本章的目的是澄清網路上「llama.cpp 才是真本地、Ollama 是壓榨版」這類迷思、並給少數需要直接用 llama.cpp 的場景一條路。</p>
<h2 id="本章目標">本章目標</h2>
<p>讀完本章後，你應該能：</p>
<ol>
<li>理解 llama.cpp 在三層架構中的位置。</li>
<li>知道 Ollama 與 llama.cpp 的關係（包含 / 上游）。</li>
<li>判斷自己什麼情境下需要直接用 llama.cpp、什麼情境不用。</li>
<li>看懂 GGUF 格式與量化標籤（Q4_K_M、Q5_K_S 等）。</li>
<li>對「llama.cpp 整合 Gemma 4 MTP」這類消息建立判讀反射。</li>
</ol>
<h2 id="llamacpp-在哪一層">llama.cpp 在哪一層</h2>
<p>llama.cpp 同時跨<a href="/blog/llm/00-foundations/three-layer-architecture/" data-link-title="0.2 介面 / 伺服器 / 模型三層架構" data-link-desc="把任何本地 LLM 工具放回正確的層級，用三層心智模型看懂工具關係">三層架構</a>的兩層：</p>
<ol>
<li><strong>推論引擎</strong>（library、可被其他程式呼叫的程式碼集合）：核心 C++ library、把 GGUF 權重載入、跑 forward pass（神經網路把輸入算到最後一層產出 token 的單次計算）。Ollama、LM Studio、許多其他工具的 backend 就是這個 library。</li>
<li><strong>CLI 工具與 server</strong>（<code>llama-cli</code>、<code>llama-server</code>）：附帶的命令列工具與 HTTP server、可以直接拿來用、但需要自己編譯與配置。</li>
</ol>
<p>當你看到「我用 Ollama 跑 Gemma 4」，實際發生的事是：</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">Ollama CLI / server（包裝層、模型管理）
</span></span><span class="line"><span class="ln">4</span><span class="cl">  ↓
</span></span><span class="line"><span class="ln">5</span><span class="cl">llama.cpp library（推論核心）
</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">Metal API（Apple Silicon GPU）
</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">Apple Silicon 硬體</span></span></code></pre></div><p>所以「Ollama vs llama.cpp」不是兩個競爭品，是「上層包裝」跟「底層引擎」的關係。</p>
<h2 id="ollama-跟-llamacpp-的關係">Ollama 跟 llama.cpp 的關係</h2>
<p>Ollama 是 llama.cpp 的下游 wrapper、但 fork 跟 upstream 不是即時同步的關係。Ollama 在自己的 repo 裡放一份 vendored（複製進來、跟隨 Ollama 自家發版節奏管理）的 llama.cpp source、加上他們自己的 patches（補丁修改）；新功能進入 Ollama 的順序通常是：</p>
<ol>
<li>llama.cpp 上游加新功能或修 bug</li>
<li>Ollama 把該 commit cherry-pick（從另一個 branch 單獨挑出一個 commit 套用）進來</li>
<li>Ollama 發新版</li>
</ol>
<p>但反過來也成立：<strong>Ollama 有時搶先在 fork 裡加上游還沒接受的功能</strong>，例如 Gemma 4 MTP 在 2026/5/7 的 Ollama v0.23.1 一鍵支援，當時 llama.cpp 上游的 Gemma 4 MTP 整合還是 feature request。</p>
<p>這個關係的啟示：</p>
<ol>
<li><strong>「llama.cpp vs Ollama 誰先進」視功能而定</strong>：具體功能要實際對照 release notes、「上游 / 下游」直覺只是初步參考、未必符合實際版本狀態。</li>
<li><strong>判讀支援度看 release notes</strong>：主版本號只是命名、實際功能列表要看具體版本的 changelog。</li>
<li><strong>直接用 llama.cpp 跟靠近上游是兩件事</strong>：Ollama 的 patches 有時是「上游還沒接受、但已經實用的功能」。</li>
</ol>
<h2 id="什麼情境真的需要直接用-llamacpp">什麼情境真的需要直接用 llama.cpp</h2>
<p>絕大多數寫 code 場景，Ollama 完全夠用。直接用 llama.cpp 的合理情境只有少數：</p>
<table>
  <thead>
      <tr>
          <th>情境</th>
          <th>為什麼 Ollama 不夠</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>想自己量化模型（從 Safetensors 轉 GGUF）</td>
          <td>Ollama 不提供量化工具，要用 llama.cpp 的 <code>quantize</code></td>
      </tr>
      <tr>
          <td>想跑 Ollama registry 沒收的特殊模型</td>
          <td>要自己下載 GGUF、自己編譯 server</td>
      </tr>
      <tr>
          <td>想用 llama.cpp 最新 commit 的新功能</td>
          <td>Ollama 還沒 cherry-pick</td>
      </tr>
      <tr>
          <td>嵌入式 / 受限環境，要把 llama.cpp 編譯進別的 app</td>
          <td>Ollama 是獨立 daemon、適合作為 server；要 embed 改用 llama.cpp library</td>
      </tr>
      <tr>
          <td>純研究、想看推論程式碼</td>
          <td>llama.cpp 是 open source、可讀</td>
      </tr>
  </tbody>
</table>
<p>寫 code 場景的讀者通常不命中以上任何一條。</p>
<h2 id="安裝如果你真要試">安裝（如果你真要試）</h2>
<p>從原始碼編譯：</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="ln">1</span><span class="cl">git clone https://github.com/ggerganov/llama.cpp.git
</span></span><span class="line"><span class="ln">2</span><span class="cl"><span class="nb">cd</span> llama.cpp
</span></span><span class="line"><span class="ln">3</span><span class="cl">make</span></span></code></pre></div><p>或用 Homebrew（社群維護，版本可能稍舊）：</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="ln">1</span><span class="cl">brew install llama.cpp</span></span></code></pre></div><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"><span class="c1"># CLI 對話</span>
</span></span><span class="line"><span class="ln">2</span><span class="cl">llama-cli -m /path/to/model.gguf -p <span class="s2">&#34;Hello&#34;</span>
</span></span><span class="line"><span class="ln">3</span><span class="cl">
</span></span><span class="line"><span class="ln">4</span><span class="cl"><span class="c1"># HTTP server</span>
</span></span><span class="line"><span class="ln">5</span><span class="cl">llama-server -m /path/to/model.gguf --port <span class="m">8080</span> --host 127.0.0.1</span></span></code></pre></div><p><code>llama-server</code> 啟動後在 <code>localhost:8080</code> 提供 OpenAI 相容 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://localhost:8080/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;any-name&#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;Hi&#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><code>model</code> 欄位 llama-server 忽略，因為它一次只 serve 一個模型（不像 Ollama 可以動態切換）。</p>
<p><code>--host 127.0.0.1</code> 是 loopback 預設、只接受本機連線。改 <code>0.0.0.0</code> 會把伺服器暴露到整個 LAN、跟 Ollama 改 <code>OLLAMA_HOST</code> 同類別的決定；完整的綁定模式跟誤開放後果見 <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>
<h2 id="gguf-格式與量化標籤">GGUF 格式與量化標籤</h2>
<p>量化標籤是看 GGUF 檔名選模型的唯一線索、影響「記憶體 / 品質 / 速度」三軸的取捨。GGUF（GGML Unified Format）是 llama.cpp 定義的模型權重格式、把模型權重、tokenizer、metadata 打包成單一檔案。Ollama 內部存的就是 GGUF。</p>
<p>常見量化標籤：</p>
<table>
  <thead>
      <tr>
          <th>標籤</th>
          <th>bits/權重</th>
          <th>品質</th>
          <th>用途</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>F32</td>
          <td>32</td>
          <td>原始</td>
          <td>訓練、研究、極端品質</td>
      </tr>
      <tr>
          <td>F16 / BF16</td>
          <td>16</td>
          <td>幾乎無損</td>
          <td>評估、有大量記憶體</td>
      </tr>
      <tr>
          <td>Q8_0</td>
          <td>8</td>
          <td>幾乎無損</td>
          <td>32GB+ Mac、品質敏感</td>
      </tr>
      <tr>
          <td>Q6_K</td>
          <td>6.56</td>
          <td>接近無損</td>
          <td>平衡</td>
      </tr>
      <tr>
          <td>Q5_K_M</td>
          <td>5.5</td>
          <td>輕微衰減</td>
          <td>24GB Mac 甜蜜點</td>
      </tr>
      <tr>
          <td>Q4_K_M</td>
          <td>4.5</td>
          <td>可察覺但實用</td>
          <td>最主流</td>
      </tr>
      <tr>
          <td>Q4_K_S</td>
          <td>4.25</td>
          <td>略遜 Q4_K_M</td>
          <td>記憶體吃緊時退一步</td>
      </tr>
      <tr>
          <td>Q3_K_M</td>
          <td>3.5</td>
          <td>明顯衰減</td>
          <td>coding 任務 hallucination 顯著上升</td>
      </tr>
      <tr>
          <td>Q2_K</td>
          <td>2.5</td>
          <td>嚴重衰減</td>
          <td>實驗用</td>
      </tr>
  </tbody>
</table>
<p><code>_K_M</code>、<code>_K_S</code> 的 K 指 K-quants（更先進的量化方法）、M / S 指 mixed-medium / mixed-small（不同層用不同量化）。實務上選 <code>Q4_K_M</code> 或 <code>Q5_K_M</code> 是寫 code 場景的甜蜜點；極端記憶體緊張才往 <code>Q3</code> 走、但通常會發現換較小模型的 <code>Q5</code> 比強塞大模型的 <code>Q3</code> 好。</p>
<p><strong>為何 coding 任務對 Q3 以下特別敏感</strong>：寫 code 的回應要在 token 層保持高精度（變數名拼字、API 呼叫格式、括號配對都不容錯）、低 bit 量化會放大 token 分布失真、體感是 hallucination 上升、編造的 API 變多、長 context 累積誤差更明顯。一般對話容忍幾個錯字、code 一個錯字就跑不過。所以同 24GB Mac 上 Q5 14B 通常比 Q3 31B 適合寫 code、雖然參數量名義上少了一半。</p>
<h2 id="gemma-4-mtp-在-llamacpp-的狀態20265">Gemma 4 MTP 在 llama.cpp 的狀態（2026/5）</h2>
<p>2026 年 5 月時：</p>
<ul>
<li><strong>speculative decoding 框架</strong>：llama.cpp 已有 <code>--draft-model</code> 參數，整體 speculative decoding 功能 beta 階段。</li>
<li><strong>Gemma 4 官方 drafter 整合</strong>：feature request 開著（GitHub issue 上有討論），但尚未合進主分支。</li>
<li><strong>Ollama 對應狀態</strong>：v0.23.1 已一鍵支援 <code>gemma4:31b-coding-mtp-bf16</code>。</li>
</ul>
<p>這是少見的「Ollama 領先 llama.cpp 上游」情境，原因是 Ollama 團隊接到 Google 的合作後直接做 patch、不等上游 review 流程。</p>
<p>實務啟示：</p>
<ol>
<li>想用 Gemma 4 MTP，<strong>直接用 Ollama 是最快路徑</strong>。</li>
<li>想在 llama.cpp 直接跑 Gemma 4 MTP，要自己編譯帶上 Ollama 的 patches，或等上游合進來。</li>
<li>看到「llama.cpp 已整合 Gemma 4 MTP」的網路文章，先去 <a href="https://github.com/ggerganov/llama.cpp/pulls">llama.cpp 的 PR 列表</a> 確認時間點。</li>
</ol>
<h2 id="llamacpp-對-apple-silicon-的優化">llama.cpp 對 Apple Silicon 的優化</h2>
<p>llama.cpp 對 Apple Silicon 有針對性優化：</p>
<ol>
<li><strong>Metal backend</strong>：在 macOS 上自動啟用 Metal（Apple 的 GPU 加速 API）、把 GPU 算力吃滿。</li>
<li><strong>NEON / AMX</strong>：CPU 上用 ARM 向量指令集（NEON 是基本 SIMD、AMX 是 Apple 的矩陣加速器）加速 dequantization（把量化權重還原為計算精度的過程）。</li>
<li><strong>Unified Memory aware</strong>：不像 NVIDIA GPU 要透過 PCIe（連接 GPU 與系統其他元件的高速匯流排）把資料搬進 VRAM、Apple Silicon 直接共用記憶體、省下這趟搬移。</li>
</ol>
<p>這些優化都「免費」，不用使用者特別設定。但跟 <a href="/blog/llm/00-foundations/mlx-mtp-omlx/" data-link-title="0.4 MLX / MTP / oMLX 的區別" data-link-desc="三個常被混為一談的術語：framework、加速技巧、特化 server，疊加而非互斥">MLX</a> 比，llama.cpp 用的是 Metal 而不是 MLX framework；兩者效能各有勝負，差距通常 10 ~ 30%，不是「天差地遠」。</p>
<p>陷阱是看到「MLX 比 llama.cpp 快 N 倍」這類說法時，要追問：</p>
<ol>
<li>哪個模型？</li>
<li>哪個量化？</li>
<li>哪台 Mac？</li>
<li>llama.cpp 哪個版本？</li>
<li>量測腳本是什麼？</li>
</ol>
<p>多數網路 benchmark 沒有完整變數控制，差距常被誇大。對寫 code 場景的使用者，這個差距不值得糾結。</p>
<h2 id="直接用-llamacpp-跟-ollama-並存">直接用 llama.cpp 跟 Ollama 並存</h2>
<p>如果你真的想試 llama.cpp，可以跟 Ollama 並存（port 不同）：</p>
<table>
  <thead>
      <tr>
          <th>伺服器</th>
          <th>預設 port</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>Ollama</td>
          <td>11434</td>
      </tr>
      <tr>
          <td>llama-server</td>
          <td>8080</td>
      </tr>
      <tr>
          <td>LM Studio</td>
          <td>1234</td>
      </tr>
  </tbody>
</table>
<p>Continue.dev 可以同時連兩個：</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;Ollama default&#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="nt">&#34;title&#34;</span><span class="p">:</span> <span class="s2">&#34;llama.cpp experimental&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="ln">11</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">12</span><span class="cl">      <span class="nt">&#34;model&#34;</span><span class="p">:</span> <span class="s2">&#34;any&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="ln">13</span><span class="cl">      <span class="nt">&#34;apiBase&#34;</span><span class="p">:</span> <span class="s2">&#34;http://localhost:8080/v1&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="ln">14</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">15</span><span class="cl">    <span class="p">}</span>
</span></span><span class="line"><span class="ln">16</span><span class="cl">  <span class="p">]</span>
</span></span><span class="line"><span class="ln">17</span><span class="cl"><span class="p">}</span></span></span></code></pre></div><h2 id="給多數讀者的建議">給多數讀者的建議</h2>
<p>直接用 llama.cpp 的學習成本比 Ollama 高、換來的好處對寫 code 場景的使用者通常不命中需求。在「自己量化模型 / 跑特殊冷門模型 / 需要 llama.cpp 最新 commit」三個條件都不命中時、Ollama 是低成本的預設選擇。</p>
<p>把 llama.cpp 當成「Ollama 背後的引擎、值得知道存在、但不必直接面對」。這個定位足夠應付網路上 95% 的相關討論。</p>
<h2 id="何時不適用本章--該往哪去">何時不適用本章 / 該往哪去</h2>
<p>本章的「以 Ollama 為主、llama.cpp 作為底層理解」這個敘事在以下情境會失準、需要另外的路徑：</p>
<table>
  <thead>
      <tr>
          <th>情境</th>
          <th>該往哪去</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>想學 LLM 推論的內部機制（attention 實作、kernel）</td>
          <td>直接讀 llama.cpp 原始碼、本章只給定位、不教 internal</td>
      </tr>
      <tr>
          <td>把 llama.cpp embed 進 mobile / 嵌入式 app</td>
          <td>本章不涵蓋、見 llama.cpp 的 README 與 build flag 文件</td>
      </tr>
      <tr>
          <td>用 Windows / Linux + 獨立 GPU 跑</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>、本章假設 Apple Silicon</td>
      </tr>
      <tr>
          <td>需要 vLLM / TGI 等資料中心級 inference server</td>
          <td>不在本指南範圍、需找專門資料中心 inference 教材</td>
      </tr>
      <tr>
          <td>想自己訓練 / fine-tune</td>
          <td>模組三 <a href="/blog/llm/03-theoretical-foundations/training-pipeline/" data-link-title="3.4 訓練流程：pre-train → SFT → RLHF" data-link-desc="LLM 的三階段訓練：預訓練、指令微調、人類反饋強化學習；各階段目標與最新替代方案">訓練流程</a>、推論伺服器不負責訓練</td>
      </tr>
  </tbody>
</table>
<h2 id="下一章">下一章</h2>
<p>下一章：<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 行內編輯快捷鍵">1.3 VS Code + Continue.dev 整合</a>，把伺服器接到日常編輯器，這才是寫 code 的真正起點。</p>
]]></content:encoded></item><item><title>1.3 VS Code + Continue.dev 整合</title><link>https://tarrragon.github.io/blog/llm/01-local-llm-services/vscode-continue-integration/</link><pubDate>Mon, 11 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/llm/01-local-llm-services/vscode-continue-integration/</guid><description>&lt;p>把本地 LLM 接到 VS Code 是「本地 LLM 寫 code」工作流的真正起點。前面章節安裝的 Ollama 是&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>，本章要接的 Continue.dev 是&lt;strong>介面層&lt;/strong>：使用者實際在編輯器裡按快捷鍵、打字、看 inline diff 的工具。&lt;/p>
&lt;p>Continue.dev 是 2026 年 5 月時與本地 LLM 整合最成熟的 VS Code 擴充套件。對應到雲端世界、它的定位類似 Cursor、差別是 Continue.dev 預設綁本地、可以同時連雲端；Cursor 預設綁雲端、本地是次要 surface、設定深度較高。&lt;/p>
&lt;p>本章假設你已經裝好 Ollama 並至少跑過一次 &lt;code>ollama run&lt;/code>。沒裝過請先回 &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">1.0 Ollama&lt;/a>。&lt;/p>
&lt;h2 id="本章目標">本章目標&lt;/h2>
&lt;p>讀完本章後，你應該能：&lt;/p>
&lt;ol>
&lt;li>安裝 Continue.dev 擴充套件。&lt;/li>
&lt;li>在 &lt;code>~/.continue/config.json&lt;/code> 設定本地 Ollama 模型。&lt;/li>
&lt;li>用 Cmd+L 開對話、Cmd+I 做行內編輯。&lt;/li>
&lt;li>同時設定本地與雲端模型，按任務切換。&lt;/li>
&lt;li>排除 Continue 連不上 Ollama 的常見問題。&lt;/li>
&lt;/ol>
&lt;h2 id="安裝擴充套件">安裝擴充套件&lt;/h2>
&lt;p>Continue 擴充套件是 VS Code 內接到本地 LLM 的介面層入口、裝完才有 chat panel 與 inline edit 快捷鍵。在 VS Code 內按 Cmd+Shift+X 開啟 extensions panel、搜尋 &lt;code>Continue&lt;/code>。第一個結果作者是 &lt;code>Continue Dev, Inc.&lt;/code>（藍色 verified 標記）、點 Install。&lt;/p>
&lt;p>裝完後左側 sidebar 多一個 Continue icon（一個小方塊）。第一次點開會跳出 onboarding、可以略過。&lt;/p>
&lt;p>擴充套件本身是 open source、Continue Dev 帳號（公司提供的雲端服務 tier、跟 VS Code 的 Microsoft 帳號是兩件事）可選。「本地 LLM」場景使用 open source 部分就足夠、不必登入。&lt;/p>
&lt;h2 id="找到-configjson">找到 config.json&lt;/h2>
&lt;p>Continue 的設定檔在 &lt;code>~/.continue/config.json&lt;/code>（macOS 是 &lt;code>/Users/&amp;lt;你的帳號&amp;gt;/.continue/config.json&lt;/code>）。第一次開 Continue 後檔案會自動產生。&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">code ~/.continue/config.json&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>或在 VS Code Continue panel 點右上角齒輪 icon，會直接開 config.json。&lt;/p>
&lt;p>預設內容包含一些雲端範例 model（OpenAI、Anthropic、Mistral），我們要加自己的本地 model。&lt;/p>
&lt;h2 id="設定本地-ollama-模型">設定本地 Ollama 模型&lt;/h2>
&lt;p>把 &lt;code>models&lt;/code> 陣列改成這樣：&lt;/p>





&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-json" data-lang="json">&lt;span class="line">&lt;span class="ln"> 1&lt;/span>&lt;span class="cl">&lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 2&lt;/span>&lt;span class="cl"> &lt;span class="nt">&amp;#34;models&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="p">[&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 3&lt;/span>&lt;span class="cl"> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 4&lt;/span>&lt;span class="cl"> &lt;span class="nt">&amp;#34;title&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;Local: Gemma 4 31B MTP&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 5&lt;/span>&lt;span class="cl"> &lt;span class="nt">&amp;#34;provider&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;ollama&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 6&lt;/span>&lt;span class="cl"> &lt;span class="nt">&amp;#34;model&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;gemma4:31b-coding-mtp-bf16&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 7&lt;/span>&lt;span class="cl"> &lt;span class="nt">&amp;#34;apiBase&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;http://localhost:11434&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="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 9&lt;/span>&lt;span class="cl"> &lt;span class="p">],&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">10&lt;/span>&lt;span class="cl"> &lt;span class="nt">&amp;#34;tabAutocompleteModel&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">11&lt;/span>&lt;span class="cl"> &lt;span class="nt">&amp;#34;title&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;Local autocomplete&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">12&lt;/span>&lt;span class="cl"> &lt;span class="nt">&amp;#34;provider&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;ollama&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">13&lt;/span>&lt;span class="cl"> &lt;span class="nt">&amp;#34;model&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;gemma4:e4b&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">14&lt;/span>&lt;span class="cl"> &lt;span class="nt">&amp;#34;apiBase&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;http://localhost:11434&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">15&lt;/span>&lt;span class="cl"> &lt;span class="p">},&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">16&lt;/span>&lt;span class="cl"> &lt;span class="nt">&amp;#34;embeddingsProvider&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">17&lt;/span>&lt;span class="cl"> &lt;span class="nt">&amp;#34;provider&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;ollama&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">18&lt;/span>&lt;span class="cl"> &lt;span class="nt">&amp;#34;model&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;nomic-embed-text&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">19&lt;/span>&lt;span class="cl"> &lt;span class="nt">&amp;#34;apiBase&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;http://localhost:11434&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">20&lt;/span>&lt;span class="cl"> &lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">21&lt;/span>&lt;span class="cl">&lt;span class="p">}&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>每個欄位的意義：&lt;/p>
&lt;table>
 &lt;thead>
 &lt;tr>
 &lt;th>欄位&lt;/th>
 &lt;th>意義&lt;/th>
 &lt;/tr>
 &lt;/thead>
 &lt;tbody>
 &lt;tr>
 &lt;td>&lt;code>models&lt;/code>&lt;/td>
 &lt;td>可在 chat panel 下拉選擇的對話模型清單&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;code>tabAutocompleteModel&lt;/code>&lt;/td>
 &lt;td>在編輯器裡邊打邊補完的模型（按 Tab 接受）、建議用小模型加快回應&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;code>embeddingsProvider&lt;/code>&lt;/td>
 &lt;td>把 codebase 索引成向量、用於語意搜尋的 &lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/embedding-model/" data-link-title="Embedding Model" data-link-desc="把文字轉成向量的模型：用於 codebase 索引與語意搜尋">embedding 模型&lt;/a>。要先 &lt;code>ollama pull nomic-embed-text&lt;/code>&lt;/td>
 &lt;/tr>
 &lt;/tbody>
&lt;/table>
&lt;p>Embedding model 的角色跟 chat / autocomplete model 不同：chat model 負責「跟你對話」、embedding model 負責「把文字壓成向量、用來做語意相似比對」、是 &lt;code>@codebase&lt;/code> 功能的後端引擎。一般 chat model 沒法當 embedding model、要分開設定。&lt;/p></description><content:encoded><![CDATA[<p>把本地 LLM 接到 VS Code 是「本地 LLM 寫 code」工作流的真正起點。前面章節安裝的 Ollama 是<a href="/blog/llm/00-foundations/three-layer-architecture/" data-link-title="0.2 介面 / 伺服器 / 模型三層架構" data-link-desc="把任何本地 LLM 工具放回正確的層級，用三層心智模型看懂工具關係">伺服器層</a>，本章要接的 Continue.dev 是<strong>介面層</strong>：使用者實際在編輯器裡按快捷鍵、打字、看 inline diff 的工具。</p>
<p>Continue.dev 是 2026 年 5 月時與本地 LLM 整合最成熟的 VS Code 擴充套件。對應到雲端世界、它的定位類似 Cursor、差別是 Continue.dev 預設綁本地、可以同時連雲端；Cursor 預設綁雲端、本地是次要 surface、設定深度較高。</p>
<p>本章假設你已經裝好 Ollama 並至少跑過一次 <code>ollama run</code>。沒裝過請先回 <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">1.0 Ollama</a>。</p>
<h2 id="本章目標">本章目標</h2>
<p>讀完本章後，你應該能：</p>
<ol>
<li>安裝 Continue.dev 擴充套件。</li>
<li>在 <code>~/.continue/config.json</code> 設定本地 Ollama 模型。</li>
<li>用 Cmd+L 開對話、Cmd+I 做行內編輯。</li>
<li>同時設定本地與雲端模型，按任務切換。</li>
<li>排除 Continue 連不上 Ollama 的常見問題。</li>
</ol>
<h2 id="安裝擴充套件">安裝擴充套件</h2>
<p>Continue 擴充套件是 VS Code 內接到本地 LLM 的介面層入口、裝完才有 chat panel 與 inline edit 快捷鍵。在 VS Code 內按 Cmd+Shift+X 開啟 extensions panel、搜尋 <code>Continue</code>。第一個結果作者是 <code>Continue Dev, Inc.</code>（藍色 verified 標記）、點 Install。</p>
<p>裝完後左側 sidebar 多一個 Continue icon（一個小方塊）。第一次點開會跳出 onboarding、可以略過。</p>
<p>擴充套件本身是 open source、Continue Dev 帳號（公司提供的雲端服務 tier、跟 VS Code 的 Microsoft 帳號是兩件事）可選。「本地 LLM」場景使用 open source 部分就足夠、不必登入。</p>
<h2 id="找到-configjson">找到 config.json</h2>
<p>Continue 的設定檔在 <code>~/.continue/config.json</code>（macOS 是 <code>/Users/&lt;你的帳號&gt;/.continue/config.json</code>）。第一次開 Continue 後檔案會自動產生。</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">code ~/.continue/config.json</span></span></code></pre></div><p>或在 VS Code Continue panel 點右上角齒輪 icon，會直接開 config.json。</p>
<p>預設內容包含一些雲端範例 model（OpenAI、Anthropic、Mistral），我們要加自己的本地 model。</p>
<h2 id="設定本地-ollama-模型">設定本地 Ollama 模型</h2>
<p>把 <code>models</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;Local: Gemma 4 31B MTP&#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="nt">&#34;tabAutocompleteModel&#34;</span><span class="p">:</span> <span class="p">{</span>
</span></span><span class="line"><span class="ln">11</span><span class="cl">    <span class="nt">&#34;title&#34;</span><span class="p">:</span> <span class="s2">&#34;Local autocomplete&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="ln">12</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">13</span><span class="cl">    <span class="nt">&#34;model&#34;</span><span class="p">:</span> <span class="s2">&#34;gemma4:e4b&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="ln">14</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">15</span><span class="cl">  <span class="p">},</span>
</span></span><span class="line"><span class="ln">16</span><span class="cl">  <span class="nt">&#34;embeddingsProvider&#34;</span><span class="p">:</span> <span class="p">{</span>
</span></span><span class="line"><span class="ln">17</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">18</span><span class="cl">    <span class="nt">&#34;model&#34;</span><span class="p">:</span> <span class="s2">&#34;nomic-embed-text&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="ln">19</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">20</span><span class="cl">  <span class="p">}</span>
</span></span><span class="line"><span class="ln">21</span><span class="cl"><span class="p">}</span></span></span></code></pre></div><p>每個欄位的意義：</p>
<table>
  <thead>
      <tr>
          <th>欄位</th>
          <th>意義</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td><code>models</code></td>
          <td>可在 chat panel 下拉選擇的對話模型清單</td>
      </tr>
      <tr>
          <td><code>tabAutocompleteModel</code></td>
          <td>在編輯器裡邊打邊補完的模型（按 Tab 接受）、建議用小模型加快回應</td>
      </tr>
      <tr>
          <td><code>embeddingsProvider</code></td>
          <td>把 codebase 索引成向量、用於語意搜尋的 <a href="/blog/llm/knowledge-cards/embedding-model/" data-link-title="Embedding Model" data-link-desc="把文字轉成向量的模型：用於 codebase 索引與語意搜尋">embedding 模型</a>。要先 <code>ollama pull nomic-embed-text</code></td>
      </tr>
  </tbody>
</table>
<p>Embedding model 的角色跟 chat / autocomplete model 不同：chat model 負責「跟你對話」、embedding model 負責「把文字壓成向量、用來做語意相似比對」、是 <code>@codebase</code> 功能的後端引擎。一般 chat model 沒法當 embedding model、要分開設定。</p>
<p><code>provider: ollama</code> 是 Continue 內建的 Ollama 整合、比 <code>provider: openai</code> 多支援 model auto-pull 等功能。<code>apiBase</code> 不需要加 <code>/v1</code>、Continue 內部會處理。</p>
<p>存檔後 Continue 會自動 reload。</p>
<h2 id="用-cmdl-開對話">用 Cmd+L 開對話</h2>
<p>Cmd+L 是把當前 buffer 餵進 chat 的快捷路徑、context 由選取範圍決定。回到 VS Code、按 <code>Cmd+L</code>（macOS）開啟 Continue chat panel。預設快捷鍵：</p>
<table>
  <thead>
      <tr>
          <th>快捷鍵</th>
          <th>動作</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td><code>Cmd+L</code></td>
          <td>開啟 Continue panel、把當前選取的程式碼當 context</td>
      </tr>
      <tr>
          <td><code>Cmd+Shift+L</code></td>
          <td>把當前選取加進現有對話 context</td>
      </tr>
      <tr>
          <td><code>Cmd+I</code></td>
          <td>在編輯器裡開 inline edit prompt</td>
      </tr>
      <tr>
          <td><code>Cmd+;</code></td>
          <td>接受 inline edit 結果</td>
      </tr>
      <tr>
          <td><code>Cmd+'</code></td>
          <td>拒絕 inline edit 結果</td>
      </tr>
  </tbody>
</table>
<p>按 <code>Cmd+L</code> 後 panel 開啟，下方輸入區可以打 prompt。如果先選了一段 code，那段 code 會自動加進 context，你可以直接問「解釋這段 code」「改成 async」「加 type annotation」。</p>
<p>第一次提問時 Ollama 會載入 model（30 ~ 60 秒）、看到 Continue panel 有 spinner 是預期的。之後同一個 model 會留在記憶體（<a href="/blog/llm/01-local-llm-services/ollama/#%e6%a8%a1%e5%9e%8b%e5%b8%b8%e9%a7%90keep_alive" data-link-title="1.0 Ollama：主流推論伺服器" data-link-desc="一行 brew 裝完、ollama run 一鍵跑 Gemma 4 MTP、OpenAI 相容 API on localhost:11434">ollama keep_alive</a>）、對話速度會快得多。</p>
<h2 id="用-cmdi-做-inline-edit">用 Cmd+I 做 inline edit</h2>
<p>把游標放在你要修改的 code 上（或選取一段），按 <code>Cmd+I</code> 開 inline 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">加 type annotation</span></span></code></pre></div><p>或：</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="ln">1</span><span class="cl">把這個 callback 改成 async/await</span></span></code></pre></div><p>Enter 後 Continue 會把選取的 code + 你的指令送給本地模型，回傳的 diff 直接 inline 顯示。按 <code>Cmd+;</code> 接受、<code>Cmd+'</code> 拒絕。</p>
<p>陷阱是「選取範圍太大」。本地模型的 context window 雖然多半 8K 以上、但塞太多 code 會讓 <a href="/blog/llm/knowledge-cards/ttft/" data-link-title="TTFT" data-link-desc="Time To First Token：送出 prompt 到第一個 token 出現的等待時間">TTFT</a> 暴增。把選取範圍縮在一個 function 或一個 block 內、體感最好。</p>
<h2 id="同時設定本地與雲端模型按任務切換">同時設定本地與雲端模型（按任務切換）</h2>
<p>寫 code 場景的常見配置是「本地當預設、雲端當大難題備援」。修改 <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;Local: Gemma 4 31B MTP&#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="nt">&#34;title&#34;</span><span class="p">:</span> <span class="s2">&#34;Cloud: Claude Sonnet 4.6&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="ln">11</span><span class="cl">      <span class="nt">&#34;provider&#34;</span><span class="p">:</span> <span class="s2">&#34;anthropic&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="ln">12</span><span class="cl">      <span class="nt">&#34;model&#34;</span><span class="p">:</span> <span class="s2">&#34;claude-sonnet-4-6&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="ln">13</span><span class="cl">      <span class="nt">&#34;apiKey&#34;</span><span class="p">:</span> <span class="s2">&#34;sk-ant-xxx&#34;</span>
</span></span><span class="line"><span class="ln">14</span><span class="cl">    <span class="p">},</span>
</span></span><span class="line"><span class="ln">15</span><span class="cl">    <span class="p">{</span>
</span></span><span class="line"><span class="ln">16</span><span class="cl">      <span class="nt">&#34;title&#34;</span><span class="p">:</span> <span class="s2">&#34;Cloud: GPT-5&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="ln">17</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">18</span><span class="cl">      <span class="nt">&#34;model&#34;</span><span class="p">:</span> <span class="s2">&#34;gpt-5&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="ln">19</span><span class="cl">      <span class="nt">&#34;apiKey&#34;</span><span class="p">:</span> <span class="s2">&#34;sk-xxx&#34;</span>
</span></span><span class="line"><span class="ln">20</span><span class="cl">    <span class="p">}</span>
</span></span><span class="line"><span class="ln">21</span><span class="cl">  <span class="p">]</span>
</span></span><span class="line"><span class="ln">22</span><span class="cl"><span class="p">}</span></span></span></code></pre></div><p>Continue chat panel 下方有 model selector，可以下拉切換。建議的切換時機：</p>
<table>
  <thead>
      <tr>
          <th>任務類型</th>
          <th>建議模型</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>簡單 function 補完、加 type、寫 docstring</td>
          <td>本地 Gemma 4 31B</td>
      </tr>
      <tr>
          <td>解釋程式碼、寫單元測試</td>
          <td>本地 Gemma 4 31B</td>
      </tr>
      <tr>
          <td>跨檔案重構、規劃新模組</td>
          <td>雲端 Claude Sonnet / GPT-5</td>
      </tr>
      <tr>
          <td>深度 debug、解奇怪 bug</td>
          <td>雲端 Claude Sonnet / GPT-5</td>
      </tr>
      <tr>
          <td>處理含 NDA 的客戶 code</td>
          <td>本地（合規要求 prompt 留在本機時、走本地路線）</td>
      </tr>
      <tr>
          <td>寫 commit message</td>
          <td>本地（隱私 + 任務簡單）</td>
      </tr>
  </tbody>
</table>
<p>詳細的判斷邏輯見 <a href="/blog/llm/01-local-llm-services/expectation-management/" data-link-title="1.5 期望管理：本地 LLM 的擅長領域與分工" data-link-desc="本地 LLM 是免費的初階 pair programmer：辨識它的擅長領域、跟雲端旗艦做結構性分工">1.5 期望管理</a>。<strong>安全 / 資料邊界面向</strong>：同個 IDE 同時接本地跟雲端 provider、prompt routing 設錯就會把該走本地的 NDA / 客戶 code 送到雲端、見 <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>；codebase / 外部文件 / 剪貼簿成為 prompt injection 攻擊面的判讀見 <a href="/blog/llm/06-security/prompt-injection-in-ide/" data-link-title="6.3 IDE 場景的 prompt injection" data-link-desc="個人 dev 場景下 IDE 寫 code 工作流的 prompt injection：codebase 內容、外部文件、剪貼簿作為攻擊面、跟雲端 LLM 場景的差異">6.3 IDE 場景的 prompt injection</a>。</p>
<h2 id="codebase-索引與--命令">Codebase 索引與 @ 命令</h2>
<p><code>@</code> 命令是把外部 context（整個專案 / 終端機輸出 / docs）注入到 chat prompt 的擴充機制、讓 LLM 在回應時能參考超出選取範圍的資料。Continue 支援把整個 codebase 索引成向量資料庫、讓你用 <code>@codebase</code> 參考整個專案。要啟用：</p>
<ol>
<li><code>~/.continue/config.json</code> 設定 <code>embeddingsProvider</code>（前面已給範例）。</li>
<li>開新 chat 後在 prompt 內打 <code>@codebase</code>，Continue 會自動把相關片段加進 context。</li>
<li>第一次索引要 5 ~ 30 分鐘（看 repo 大小），之後增量更新。</li>
</ol>
<p><code>@codebase</code> 對中型專案（&lt; 1000 檔案）效果不錯、本地模型有機會找到合適片段；對大型專案（10000+ 檔案）效果受限於 embedding model 品質。大型專案的退路：拆 workspace 縮小索引範圍、改用 <code>@file</code> 明確指定相關檔案、或換較強的 embedding model（例如雲端 OpenAI <code>text-embedding-3-large</code>）。</p>
<p>其他 <code>@</code> 命令：</p>
<table>
  <thead>
      <tr>
          <th>命令</th>
          <th>用途</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td><code>@codebase</code></td>
          <td>整個專案的語意搜尋</td>
      </tr>
      <tr>
          <td><code>@docs</code></td>
          <td>加進 documentation context（要先設定）</td>
      </tr>
      <tr>
          <td><code>@terminal</code></td>
          <td>把終端機最後一段輸出加進 context</td>
      </tr>
      <tr>
          <td><code>@file</code></td>
          <td>指定特定檔案</td>
      </tr>
      <tr>
          <td><code>@tree</code></td>
          <td>加進專案結構</td>
      </tr>
      <tr>
          <td><code>@open</code></td>
          <td>加進目前開啟的所有 tab</td>
      </tr>
  </tbody>
</table>
<h2 id="處理-continue-連不上-ollama">處理 Continue 連不上 Ollama</h2>
<p>常見錯誤訊息與處理：</p>
<table>
  <thead>
      <tr>
          <th>錯誤訊息</th>
          <th>處理</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td><code>Failed to fetch http://localhost:11434/...</code></td>
          <td>Ollama server 沒在跑。<code>brew services start ollama</code></td>
      </tr>
      <tr>
          <td><code>model 'xxx' not found</code></td>
          <td>還沒 pull。<code>ollama pull xxx</code></td>
      </tr>
      <tr>
          <td><code>address already in use</code>（Ollama 那邊）</td>
          <td>已有 instance 在跑，<code>pkill -f &quot;ollama serve&quot;</code> 重啟</td>
      </tr>
      <tr>
          <td>Continue 無回應、長時間 spinner</td>
          <td>Model 正在載入。第一次 30 ~ 60 秒正常</td>
      </tr>
      <tr>
          <td>對話內容亂碼 / 一直重複</td>
          <td>模型品質不夠或 temperature 太高，換較大模型或調 temp</td>
      </tr>
      <tr>
          <td>Tab autocomplete 完全沒觸發</td>
          <td>確認 <code>tabAutocompleteModel</code> 設定、模型已 pull</td>
      </tr>
  </tbody>
</table>
<p>排錯時先用 curl 驗證 Ollama 本身正常：</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="ln">1</span><span class="cl">curl http://localhost:11434/api/tags</span></span></code></pre></div><p>如果這個都回不出來、問題在 Ollama；如果這個正常但 Continue 連不上、問題在 Continue 設定。</p>
<p>排錯時的機制判讀：</p>
<ul>
<li><strong><code>Failed to fetch</code></strong>：通常是 Ollama 沒跑、或 listen address 配置不一致（Continue config 跟 <code>OLLAMA_HOST</code> 對不上）。</li>
<li><strong><code>address already in use</code></strong>：另一個 Ollama instance 佔了 port、或 LM Studio 啟動時也搶 11434。先用 <code>lsof -i :11434</code> 找佔用方。</li>
<li><strong>長時間 spinner</strong>：第一次載入大模型（30 ~ 60 秒）正常；如果每次新 chat 都這樣、可能 keep_alive 太短、模型每次被 unload。</li>
<li><strong>對話內容亂碼 / 一直重複</strong>：小模型 capacity 不足以維持長 context 連貫性、或 <code>repeat_penalty</code> 預設值對該模型不合適。先換較大模型驗證是不是 model 本身的問題、再回頭調 temperature / repeat_penalty。</li>
<li><strong>Tab autocomplete 沒觸發</strong>：autocomplete 模型沒 pull 成功、或 model 名稱拼錯。<code>ollama list</code> 確認 model 真的在。</li>
</ul>
<h2 id="何時-continuedev-不適合">何時 Continue.dev 不適合</h2>
<p>Continue.dev 是 VS Code 環境內最成熟的本地 LLM 介面層、但在以下情境會撞到設計邊界、需要找替代路徑：</p>
<table>
  <thead>
      <tr>
          <th>情境</th>
          <th>替代路徑</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>非 VS Code-family 編輯器（Vim / Emacs / Sublime）</td>
          <td>各 editor 有自己的 LLM plugin（如 Vim 的 <code>llm.nvim</code>、Emacs 的 <code>gptel</code>）、Continue 本身僅支援 VS Code / JetBrains</td>
      </tr>
      <tr>
          <td>Jupyter Notebook 環境</td>
          <td>Notebook 的 cell 結構跟 .py 檔不同、Continue 對 .ipynb 支援有限、改用 Jupyter-AI 或自己用 LangChain</td>
      </tr>
      <tr>
          <td>大型 monorepo（10000+ 檔案）</td>
          <td><code>@codebase</code> 索引效果受 embedding 品質限制、改拆 workspace 或用 <code>@file</code> 明確指定</td>
      </tr>
      <tr>
          <td>CLI-first / git-aware 工作流</td>
          <td><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；先把基底跑穩再進階">aider</a> 直接在 CLI 操作 git + LLM、適合「沒打開 IDE 也想用 LLM」</td>
      </tr>
      <tr>
          <td>想跑 multi-step agent（自動探索 + 多輪修改）</td>
          <td>Cline、aider 等較完整 agent 工具的設計目標更貼近、Continue 偏單輪 chat + inline edit</td>
      </tr>
  </tbody>
</table>
<p>Continue 的甜蜜點是「VS Code 內、單檔到中型專案、人在駕駛位的 chat + inline edit」。離這個甜蜜點越遠、收益越低、改用 Cline / aider / Cursor 等工具更直接。</p>
<h2 id="continuedev-跟-cursor-的取捨">Continue.dev 跟 Cursor 的取捨</h2>
<p>如果你正考慮 Continue.dev vs Cursor，下表是寫 code 場景的取捨：</p>
<table>
  <thead>
      <tr>
          <th>維度</th>
          <th>Continue.dev</th>
          <th>Cursor</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>本地 LLM 支援</td>
          <td>First-class，多家 provider 完整支援</td>
          <td>有，但設定較深、不是主要使用情境</td>
      </tr>
      <tr>
          <td>雲端 LLM 支援</td>
          <td>多家 provider（OpenAI、Anthropic、本地）</td>
          <td>主要綁 Cursor 自己的服務、能接 OpenAI / Anthropic</td>
      </tr>
      <tr>
          <td>訂閱費</td>
          <td>免費（本地 LLM 完全免費；接雲端要自己付 API）</td>
          <td>月費 USD 20（含若干雲端用量）</td>
      </tr>
      <tr>
          <td>Inline edit 體驗</td>
          <td>良好（Cmd+I）</td>
          <td>優秀（Cursor 的招牌）</td>
      </tr>
      <tr>
          <td>Agent 模式</td>
          <td>較陽春，主打 chat + edit</td>
          <td>較完整，有 multi-step agent</td>
      </tr>
      <tr>
          <td>Codebase 索引</td>
          <td>自家 embedding（本地或雲端）</td>
          <td>雲端索引（要 opt-out）</td>
      </tr>
      <tr>
          <td>隱私</td>
          <td>完全可控（純本地）</td>
          <td>預設送 Cursor 雲端 telemetry</td>
      </tr>
  </tbody>
</table>
<p>對「本地 LLM 為主」的使用者，Continue.dev 是更直接的選擇。Cursor 是「雲端 LLM 為主、偶爾本地」的選擇。</p>
<h2 id="下一章">下一章</h2>
<p>下一章：<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 寫 code 場景的模型選型優先順序</a>，回答「Ollama 跑起來該裝哪個 model」。</p>
]]></content:encoded></item><item><title>1.4 寫 code 場景的模型選型優先順序</title><link>https://tarrragon.github.io/blog/llm/01-local-llm-services/model-selection-priority/</link><pubDate>Mon, 11 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/llm/01-local-llm-services/model-selection-priority/</guid><description>&lt;p>裝完伺服器後，下一個決策是「該裝哪個 model」。本地 LLM 模型百百種，但寫 code 場景的真正候選名單其實很短：2026 年 5 月有四個值得認真考慮的選擇，加幾個 niche 選項。&lt;/p>
&lt;p>本章用「優先順序」而不是「對比表羅列」呈現，因為實際使用上 95% 的讀者只需要從前兩三個選一個；後面的選擇是給特定情境用的補充。先給結論再給推導，讀者可以快速看到結論、有空再回頭看為什麼。&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>看到「最強本地模型」這類排名時、用具體任務脈絡判讀。&lt;/li>
&lt;/ol>
&lt;h2 id="優先順序總覽">優先順序總覽&lt;/h2>
&lt;p>對 32GB+ Mac 的讀者、建議的選型順序：&lt;/p>
&lt;ol>
&lt;li>&lt;strong>Gemma 4 31B &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;/strong>（首選）— 速度最快、coding 任務 MTP 加速 2 ~ 3 倍&lt;/li>
&lt;li>&lt;strong>Qwen3-Coder 30B&lt;/strong>（次選）— coding 專科、&lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/swe-bench/" data-link-title="SWE-bench" data-link-desc="用真實 GitHub issue 量化 LLM coding 能力的 benchmark">SWE-bench&lt;/a> 表現最強的本地模型&lt;/li>
&lt;li>&lt;strong>Qwen3 14B&lt;/strong>（通用備案）— 較小較快、記憶體吃緊或要跑 long context 時切回來&lt;/li>
&lt;li>&lt;strong>gpt-oss 20B&lt;/strong>（OpenAI 開源）— 風格較像 GPT、想嘗試 OpenAI 風味時用&lt;/li>
&lt;/ol>
&lt;p>對 24GB Mac、跳過 31B、從 14B 起步。對 16GB Mac、可用模型限於 7B 或 Gemma 4 E4B、能力明顯下降、建議混用雲端。&lt;/p>
&lt;h2 id="1-gemma-4-31b-mtp日常主力首選">1. Gemma 4 31B MTP：日常主力首選&lt;/h2>
&lt;p>Gemma 4 31B MTP 在「速度 × 能力 × 工具支援」三軸取得寫 code 場景的最佳平衡、是首選的原因。Gemma 4 31B 在 SWE-bench、&lt;a href="https://github.com/openai/human-eval">HumanEval&lt;/a>（OpenAI 提供的 164 題 Python 函式補完 benchmark）等 coding benchmark 上接近 Qwen3-Coder 30B、但因為 Google 釋出官方 MTP &lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/drafter-model/" data-link-title="Drafter Model" data-link-desc="speculative decoding 中用來快速猜未來 token 的小模型">drafter&lt;/a>、Ollama v0.23.1 一鍵整合、實際使用體感速度比 Qwen3-Coder 30B 快 2 ~ 3 倍（同硬體、同任務）。&lt;/p>
&lt;p>&lt;strong>Ollama tag&lt;/strong>：&lt;code>gemma4:31b-coding-mtp-bf16&lt;/code>&lt;/p>
&lt;p>&lt;strong>記憶體需求&lt;/strong>：~18GB（含 drafter），32GB Mac 順暢、24GB Mac 吃緊。&lt;/p>
&lt;p>&lt;strong>能力範圍&lt;/strong>：&lt;/p>
&lt;ul>
&lt;li>簡單 function 補完、改寫、加 type：強&lt;/li>
&lt;li>寫 unit test、寫 docstring：強&lt;/li>
&lt;li>解釋程式碼、提建議：中強&lt;/li>
&lt;li>跨檔案重構：中等（仍輸雲端旗艦）&lt;/li>
&lt;li>跟你討論架構設計：中等（會給合理方向但深度有限）&lt;/li>
&lt;li>多步驟 agent 規劃：弱（雲端旗艦領先明顯）&lt;/li>
&lt;/ul>
&lt;p>&lt;strong>為什麼選它而不是 Qwen3-Coder 30B&lt;/strong>：MTP 加速在寫 code 場景太明顯。Qwen3-Coder 在 benchmark 上略強，但實際工作流的「等模型回應」時間差會抵消那點 benchmark 差距。除非你的任務剛好命中 Qwen3-Coder 強過 Gemma 4 的部分（後面會說），Gemma 4 是更穩的預設。&lt;/p>
&lt;h2 id="2-qwen3-coder-30bcoding-專科">2. Qwen3-Coder 30B：coding 專科&lt;/h2>
&lt;p>Qwen3-Coder 30B 是「benchmark 最強、速度次之」的本地 coding 模型、做為 benchmark 敏感工作流的次選。Qwen3-Coder 在 SWE-bench Verified（OpenAI 篩過的高品質子集、500 題）上達 77.2 分（2026 年 4 月 Alibaba 釋出時的公開數據）、是本地模型中 coding 表現最強的。對「複雜程式碼任務、不在乎速度差一倍」的使用者、這是更好的選擇。&lt;/p></description><content:encoded><![CDATA[<p>裝完伺服器後，下一個決策是「該裝哪個 model」。本地 LLM 模型百百種，但寫 code 場景的真正候選名單其實很短：2026 年 5 月有四個值得認真考慮的選擇，加幾個 niche 選項。</p>
<p>本章用「優先順序」而不是「對比表羅列」呈現，因為實際使用上 95% 的讀者只需要從前兩三個選一個；後面的選擇是給特定情境用的補充。先給結論再給推導，讀者可以快速看到結論、有空再回頭看為什麼。</p>
<h2 id="本章目標">本章目標</h2>
<p>讀完本章後，你應該能：</p>
<ol>
<li>對自己的 Mac 規格，立刻知道該裝哪個模型。</li>
<li>理解每個模型的能力強項與適用情境。</li>
<li>看到新模型發表時，知道怎麼放進這個優先順序。</li>
<li>看到「最強本地模型」這類排名時、用具體任務脈絡判讀。</li>
</ol>
<h2 id="優先順序總覽">優先順序總覽</h2>
<p>對 32GB+ Mac 的讀者、建議的選型順序：</p>
<ol>
<li><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></strong>（首選）— 速度最快、coding 任務 MTP 加速 2 ~ 3 倍</li>
<li><strong>Qwen3-Coder 30B</strong>（次選）— 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> 表現最強的本地模型</li>
<li><strong>Qwen3 14B</strong>（通用備案）— 較小較快、記憶體吃緊或要跑 long context 時切回來</li>
<li><strong>gpt-oss 20B</strong>（OpenAI 開源）— 風格較像 GPT、想嘗試 OpenAI 風味時用</li>
</ol>
<p>對 24GB Mac、跳過 31B、從 14B 起步。對 16GB Mac、可用模型限於 7B 或 Gemma 4 E4B、能力明顯下降、建議混用雲端。</p>
<h2 id="1-gemma-4-31b-mtp日常主力首選">1. Gemma 4 31B MTP：日常主力首選</h2>
<p>Gemma 4 31B MTP 在「速度 × 能力 × 工具支援」三軸取得寫 code 場景的最佳平衡、是首選的原因。Gemma 4 31B 在 SWE-bench、<a href="https://github.com/openai/human-eval">HumanEval</a>（OpenAI 提供的 164 題 Python 函式補完 benchmark）等 coding benchmark 上接近 Qwen3-Coder 30B、但因為 Google 釋出官方 MTP <a href="/blog/llm/knowledge-cards/drafter-model/" data-link-title="Drafter Model" data-link-desc="speculative decoding 中用來快速猜未來 token 的小模型">drafter</a>、Ollama v0.23.1 一鍵整合、實際使用體感速度比 Qwen3-Coder 30B 快 2 ~ 3 倍（同硬體、同任務）。</p>
<p><strong>Ollama tag</strong>：<code>gemma4:31b-coding-mtp-bf16</code></p>
<p><strong>記憶體需求</strong>：~18GB（含 drafter），32GB Mac 順暢、24GB Mac 吃緊。</p>
<p><strong>能力範圍</strong>：</p>
<ul>
<li>簡單 function 補完、改寫、加 type：強</li>
<li>寫 unit test、寫 docstring：強</li>
<li>解釋程式碼、提建議：中強</li>
<li>跨檔案重構：中等（仍輸雲端旗艦）</li>
<li>跟你討論架構設計：中等（會給合理方向但深度有限）</li>
<li>多步驟 agent 規劃：弱（雲端旗艦領先明顯）</li>
</ul>
<p><strong>為什麼選它而不是 Qwen3-Coder 30B</strong>：MTP 加速在寫 code 場景太明顯。Qwen3-Coder 在 benchmark 上略強，但實際工作流的「等模型回應」時間差會抵消那點 benchmark 差距。除非你的任務剛好命中 Qwen3-Coder 強過 Gemma 4 的部分（後面會說），Gemma 4 是更穩的預設。</p>
<h2 id="2-qwen3-coder-30bcoding-專科">2. Qwen3-Coder 30B：coding 專科</h2>
<p>Qwen3-Coder 30B 是「benchmark 最強、速度次之」的本地 coding 模型、做為 benchmark 敏感工作流的次選。Qwen3-Coder 在 SWE-bench Verified（OpenAI 篩過的高品質子集、500 題）上達 77.2 分（2026 年 4 月 Alibaba 釋出時的公開數據）、是本地模型中 coding 表現最強的。對「複雜程式碼任務、不在乎速度差一倍」的使用者、這是更好的選擇。</p>
<p><strong>Ollama tag</strong>：<code>qwen3-coder:30b</code></p>
<p><strong>記憶體需求</strong>：~18 ~ 20GB，32GB Mac 順暢。</p>
<p><strong>Qwen3-Coder 30B 強項</strong>（JSON 結構穩定 / SQL Rust Go / 200+ 行 code / 演算法題）：</p>
<ul>
<li>需要嚴格遵循 prompt 結構（例如要求輸出 JSON）— Qwen3-Coder 較穩定</li>
<li>需要寫 SQL、Rust、Go 等較少見語言 — 訓練資料較多</li>
<li>需要產出較長 code（200+ 行）— 比較不容易在中段失控</li>
<li>需要解 leetcode 風格演算法題（注重題目模式 + 標準解）— benchmark 強項</li>
</ul>
<p><strong>為什麼不是首選</strong>：MTP 加速目前限於 Gemma 4 官方 drafter、Qwen3-Coder 還沒有對應的官方 drafter（2026 年 5 月）。生字速度明顯慢於 Gemma 4 31B MTP、體感等候時間長。</p>
<h2 id="3-qwen3-14b通用備案">3. Qwen3 14B：通用備案</h2>
<p>Qwen3 14B 是 32GB Mac 想留記憶體餘裕（多 model 並存、長 <a href="/blog/llm/knowledge-cards/kv-cache/" data-link-title="KV Cache" data-link-desc="已處理 token 的 attention 中間結果暫存：避免重算、加速後續生成">KV cache</a>、其他重 app）時的合理「降一級」選擇。能力較弱但記憶體佔用減半。</p>
<p><strong>Ollama tag</strong>：<code>qwen3:14b</code></p>
<p><strong>記憶體需求</strong>：~10GB，24GB Mac 順暢、32GB Mac 留更多空間給 IDE 與系統。</p>
<p><strong>能力範圍</strong>：</p>
<ul>
<li>簡單 function 補完、加 type：尚可</li>
<li>解釋程式碼：尚可</li>
<li>寫 unit test：有時會錯</li>
<li>跨檔案重構：明顯弱於 31B 等級</li>
<li>複雜推理：明顯弱</li>
</ul>
<p><strong>主要使用情境</strong>：</p>
<ol>
<li>24GB Mac 的預設選擇。</li>
<li>32GB Mac 但想留記憶體給其他重 app（如同時跑 Docker、跑大型測試）。</li>
<li>Tab autocomplete 的小模型（搭配主對話 31B 模型）。</li>
<li>長 context 場景（KV cache 佔用較少）。</li>
</ol>
<h2 id="4-gpt-oss-20bopenai-開源版">4. gpt-oss 20B：OpenAI 開源版</h2>
<p>gpt-oss 20B 是 OpenAI 在 2025 年釋出的開源模型、風格較接近 GPT 系列、定位是「習慣 GPT 語感的使用者」的補充選項。如果你已經很習慣 GPT 的回答方式、這個模型的「語感」會比 Gemma 或 Qwen 親切。</p>
<p><strong>Ollama tag</strong>：<code>gpt-oss:20b</code></p>
<p><strong>記憶體需求</strong>：~12GB，24GB Mac 起點可跑。</p>
<p><strong>能力範圍</strong>：</p>
<ul>
<li>coding 表現中等，輸 Gemma 4 31B、Qwen3-Coder 30B。</li>
<li>一般對話、解釋、寫作風格較 polished。</li>
<li>Tool use 支援較好（OpenAI 自家生態的優勢）。</li>
</ul>
<p><strong>主要使用情境</strong>：</p>
<ol>
<li>你已習慣 GPT 風格、不想換語感。</li>
<li>寫 code + 一般對話混用（一般對話 gpt-oss 較自然）。</li>
<li>24GB Mac 的進階選擇（比 Qwen3 14B 大、能力強，比 Gemma 4 31B 小、塞得進）。</li>
</ol>
<h2 id="16gb-mac-的選擇">16GB Mac 的選擇</h2>
<p>16GB Mac 是現實上的最小可用配置。能跑的選擇：</p>
<table>
  <thead>
      <tr>
          <th>模型</th>
          <th>Ollama tag</th>
          <th>體感</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>Gemma 4 E4B</td>
          <td><code>gemma4:e4b</code></td>
          <td>寫 code 勉強堪用、明顯弱於 14B 級</td>
      </tr>
      <tr>
          <td>Qwen3 7B</td>
          <td><code>qwen3:7b</code></td>
          <td>跟 E4B 類似</td>
      </tr>
      <tr>
          <td>Llama 3.2 8B</td>
          <td><code>llama3.2:8b</code></td>
          <td>通用任務尚可，coding 較弱</td>
      </tr>
  </tbody>
</table>
<p>實話：16GB Mac 跑這些模型只能做「簡單補完、解釋短段程式碼」、比較複雜的任務還是要切雲端。如果你想以本地 LLM 為主力寫 code、16GB 不在本指南推薦範圍；建議混用雲端、或評估升級到 24GB+ Mac。</p>
<h2 id="48gb-mac-的選擇">48GB+ Mac 的選擇</h2>
<p>48GB 以上記憶體可以跑更大模型，但邊際效益要考慮。可用選擇：</p>
<table>
  <thead>
      <tr>
          <th>模型</th>
          <th>Ollama tag</th>
          <th>記憶體</th>
          <th>體感</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>Qwen3-Coder 32B Q5</td>
          <td><code>qwen3-coder:32b-q5_K_M</code></td>
          <td>~22GB</td>
          <td>比 Q4 略強，差異不大</td>
      </tr>
      <tr>
          <td>Llama 3.3 70B Q4</td>
          <td><code>llama3.3:70b</code></td>
          <td>~42GB</td>
          <td>通用能力強，但 coding 不一定超越 31B</td>
      </tr>
      <tr>
          <td>Qwen3-Coder 32B bf16</td>
          <td><code>qwen3-coder:32b-bf16</code></td>
          <td>~64GB</td>
          <td>64GB Mac 才行，接近 GPT-4 mini</td>
      </tr>
  </tbody>
</table>
<p>48GB Mac 的主要收益不是「跑得到更大模型」，而是「同時跑兩個 model」或「長 context 不卡」。例如同時跑 31B 主對話 + 4B autocomplete + 留空間給 IDE。</p>
<h2 id="判斷新模型是否值得換的步驟">判斷新模型是否值得換的步驟</h2>
<p>本地模型發布速度很快、每 2 ~ 3 個月會有新候選。判斷要不要換的步驟：</p>
<ol>
<li><strong>看 <a href="/blog/llm/knowledge-cards/swe-bench/" data-link-title="SWE-bench" data-link-desc="用真實 GitHub issue 量化 LLM coding 能力的 benchmark">SWE-bench</a> Verified 分數</strong>：新模型在 SWE-bench Verified 上比現用模型高 5 分以上、值得試。</li>
<li><strong>看模型大小與記憶體預算</strong>：新模型大小落在 Mac 預算內、再進入下一步評估。</li>
<li><strong>看 <a href="/blog/llm/knowledge-cards/speculative-decoding/" data-link-title="Speculative Decoding" data-link-desc="用小模型猜未來 token、大模型並行驗證的加速技巧">speculative decoding</a> 支援</strong>：有 <a href="/blog/llm/knowledge-cards/drafter-model/" data-link-title="Drafter Model" data-link-desc="speculative decoding 中用來快速猜未來 token 的小模型">drafter</a> 的新模型在體感速度上常勝過稍強但沒加速的模型。</li>
<li><strong>用自己的 5 ~ 10 個日常任務當私人 benchmark</strong>：公開 benchmark 是參考、自己跑一遍才能拿到能用在自己場景的數字。</li>
<li><strong>看 Ollama / LM Studio 的 release notes</strong>：新模型要被伺服器支援、Ollama registry 已收錄的模型用起來最直接。</li>
</ol>
<p>合理的更換節奏是一年 2 ~ 3 次主力模型。每換一次要重新適應它的語感、prompt 風格、體感速度、切換成本不算低；穩定下來再換、收益比追新發布每個都試大。</p>
<h2 id="量化等級的選擇">量化等級的選擇</h2>
<p>對所有模型，量化等級的選擇大致一致：</p>
<table>
  <thead>
      <tr>
          <th>量化等級</th>
          <th>建議使用情境</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>Q8 / bf16</td>
          <td>32GB+ Mac、品質敏感任務、能塞得進就用</td>
      </tr>
      <tr>
          <td>Q5_K_M</td>
          <td>24GB Mac 跑 14B 模型；32GB Mac 跑 31B（記憶體稍緊）</td>
      </tr>
      <tr>
          <td>Q4_K_M</td>
          <td><strong>主流甜蜜點</strong>。32GB Mac 跑 31B Q4 是 2026 年最佳價格效能比</td>
      </tr>
      <tr>
          <td>Q3</td>
          <td>寫 code 場景品質下降明顯、慎用、見下方判讀</td>
      </tr>
  </tbody>
</table>
<p>量化等級的延伸判讀：</p>
<ul>
<li><strong>Q8 / bf16 的回退條件</strong>：模型載入時 swap 到 SSD（生字速度掉一個量級）就要往下降一級。</li>
<li><strong>Q5_K_M 的回退條件</strong>：載入後 KV cache 跟 IDE 一起擠到記憶體上限、改 Q4_K_M。</li>
<li><strong>Q4_K_M 的回退條件</strong>：跑 coding 任務通過率明顯下降（基準 vs Q5 / Q8 下降 10% 以上）就換較小模型的 Q5、不再下降到 Q3。</li>
<li><strong>Q3 的觸發訊號</strong>：hallucination 上升、編造 API、長 context 累積誤差。寫 code 場景的具體判讀：Q3 31B 在 coding 任務上常輸給 Q5 14B、選 model size 時先看任務通過率、再用量化調記憶體、不是反過來。</li>
</ul>
<h2 id="適合寫-code-以外場景的模型">適合寫 code 以外場景的模型</h2>
<p>以下五類模型各自有專屬定位、跟「寫 code 主力」是不同的工作流；放在寫 code 主力位置會踩到能力錯位。每類各自有不同的判讀條件、用同一個欄位塞會遺失各自的失敗模式。</p>
<h3 id="llama-3x-base-等-base-model">Llama 3.x base 等 base model</h3>
<p><a href="/blog/llm/knowledge-cards/base-model/" data-link-title="Base Model" data-link-desc="未經指令微調的原始模型：擅長文字接龍、適合下游微調用途">Base model</a> 是純粹做下一個 token 預測訓練、沒做 <a href="/blog/llm/knowledge-cards/instruction-tuned/" data-link-title="Instruction-Tuned Model" data-link-desc="經過指令微調的模型：會跟著 prompt 走、回答使用者問題">instruction-tuning</a> 的原始模型。直接拿來對話會跟著 prompt 隨機接龍、不會「回答你的問題」。適合下游 fine-tuning 跟研究；寫 code 場景改選同 family 的 instruction-tuned 版本（例如 <code>llama3.3:70b-instruct</code> 而不是 <code>llama3.3:70b</code>）。</p>
<h3 id="純對話模型vicunachatglm-早期等">純對話模型（Vicuna、ChatGLM 早期等）</h3>
<p>純對話模型是 2023 年早期對話研究的成果、訓練資料偏自然對話、coding 表現遠輸後來的專科模型。早期教學示範或對話技術 baseline 仍會用到；現階段 coding 任務直接選 Qwen3-Coder 或 Gemma 4、不在這條路線上糾結。</p>
<h3 id="多模態模型llavagemma-4-多模態版等">多模態模型（Llava、Gemma 4 多模態版等）</h3>
<p>多模態模型訓練資料含圖片 + 文字、能做圖片理解、UI 描述、OCR、圖文對應、適合「給 LLM 看截圖」這類工作流。寫 code 場景如果不需要看圖、改選同等級的純文字模型較省記憶體（多模態的 vision tower 佔額外 GB 級記憶體、純文字 coding 用不到）。</p>
<h3 id="中文特化模型">中文特化模型</h3>
<p>中文特化模型在純中文寫作、客服場景表現好、但 coding 仍以英文 prompt + 英文 code comment 為主流。寫 code 用通用模型 + 英文 prompt 通常表現較穩、中文特化模型反而在英文程式碼相關任務上劣勢。除非工作流真的有大量中文 docstring / 註解需求、否則用通用模型。</p>
<h3 id="最新最強測試模型">「最新最強」測試模型</h3>
<p>社群每週都有新模型釋出、號稱「跑分爆表」。日常主力建議等社群驗證 1 ~ 2 個月再採用、避免出「benchmark 強但 prompt 適應性差」「prompt 模板未進入主流工具預設」的事故。嘗鮮跟跑分是另一條工作流、用 LM Studio 探索性測試後再決定是否切主力。</p>
<h2 id="模型不只-chat還有-embedding">模型不只 chat、還有 embedding</h2>
<p>Continue.dev 的 codebase 索引功能要用 embedding model，這跟 chat model 是兩種不同的模型。常用 embedding：</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 pull nomic-embed-text</span></span></code></pre></div><p><code>nomic-embed-text</code> 約 274MB，記憶體佔用低，是 Continue.dev codebase 索引的好搭檔。其他選項：</p>
<table>
  <thead>
      <tr>
          <th>Embedding 模型</th>
          <th>大小</th>
          <th>用途</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td><code>nomic-embed-text</code></td>
          <td>274MB</td>
          <td>主流選擇，英文為主</td>
      </tr>
      <tr>
          <td><code>mxbai-embed-large</code></td>
          <td>670MB</td>
          <td>較強的英文 embedding</td>
      </tr>
      <tr>
          <td><code>bge-m3</code></td>
          <td>1.2GB</td>
          <td>多語言（含中文）embedding</td>
      </tr>
  </tbody>
</table>
<p>Embedding 模型的選擇對 codebase 搜尋品質有影響，但邊際效益遠小於 chat model。先用預設 <code>nomic-embed-text</code>，有需求再換。</p>
<h2 id="何時不適用本章優先順序">何時不適用本章優先順序</h2>
<p>本章選型假設「Apple Silicon Mac + 寫 code 為主 + 個人使用」。以下情境的選型邏輯不同、需要另外的判讀路徑：</p>
<table>
  <thead>
      <tr>
          <th>情境</th>
          <th>該往哪去</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>Windows / Linux + 獨立 GPU</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> — VRAM 限制 + MoE CPU 卸載決定選型</td>
      </tr>
      <tr>
          <td>需要 vision / multimodal</td>
          <td>改用多模態模型（如 Gemma 4 多模態版）、本章選型只覆蓋純文字 coding</td>
      </tr>
      <tr>
          <td>離線部署到生產（不接個人 Mac）</td>
          <td>考慮 vLLM、TGI 等資料中心 inference server、本章假設個人桌機推論</td>
      </tr>
      <tr>
          <td>訓練 / fine-tune 為主</td>
          <td>模組三 <a href="/blog/llm/03-theoretical-foundations/training-pipeline/" data-link-title="3.4 訓練流程：pre-train → SFT → RLHF" data-link-desc="LLM 的三階段訓練：預訓練、指令微調、人類反饋強化學習；各階段目標與最新替代方案">訓練流程</a>、推論優先順序不適用</td>
      </tr>
      <tr>
          <td>非英文工作流 / 中文寫作為主</td>
          <td>中文特化模型（DeepSeek、Yi 等）、本章 coding 場景以英文 prompt 為基準</td>
      </tr>
      <tr>
          <td>嘗鮮 / 跑分驗證新模型</td>
          <td>用 LM Studio 探索性測試、跟本章主力選型分開、避免日常主力被新模型 churn</td>
      </tr>
  </tbody>
</table>
<h2 id="給讀者的最快決策路徑">給讀者的最快決策路徑</h2>
<p>決策表把記憶體預算跟用途摺成一張快查、依情境定位、不需要重讀整章：</p>
<table>
  <thead>
      <tr>
          <th>你的情境</th>
          <th>該裝的 model</th>
          <th>觸發回退條件</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>32GB+ Mac、首次本地 LLM</td>
          <td><code>gemma4:31b-coding-mtp-bf16</code></td>
          <td>跑 Qwen3-Coder 強項任務時改用下一列</td>
      </tr>
      <tr>
          <td>32GB Mac、想要 coding 最強</td>
          <td><code>qwen3-coder:30b</code>、接受速度比 Gemma 慢</td>
          <td>體感等候時間太久、退回 Gemma 4 MTP</td>
      </tr>
      <tr>
          <td>24GB Mac</td>
          <td><code>qwen3:14b</code> 或 <code>gpt-oss:20b</code></td>
          <td>任務複雜度超過 14B 上限、改混用雲端</td>
      </tr>
      <tr>
          <td>16GB Mac</td>
          <td><code>gemma4:e4b</code> 或 <code>qwen3:7b</code>、主力仍雲端</td>
          <td>跨檔案 / 多步驟任務直接切雲端</td>
      </tr>
      <tr>
          <td>48GB+ Mac、要榨乾硬體</td>
          <td><code>qwen3-coder:32b-bf16</code> 或同時跑兩個 model</td>
          <td>同時跑兩 model 時 KV cache 擠到上限、改 Q5 量化</td>
      </tr>
      <tr>
          <td>想當 codebase 搜尋用</td>
          <td>+ <code>nomic-embed-text</code>（embedding model）</td>
          <td>大型 monorepo 索引品質差、換 cloud embedding model</td>
      </tr>
      <tr>
          <td>想當 tab autocomplete 用</td>
          <td>+ <code>gemma4:e4b</code> 或 <code>qwen3:7b</code>（速度優先）</td>
          <td>autocomplete 延遲 &gt; 500ms、降到更小的 model</td>
      </tr>
  </tbody>
</table>
<p>決策表的兩個閱讀方式：先按「你的情境」找對應 model、再注意「觸發回退條件」決定何時切換到下一行。回退條件常被忽略、導致讀者在條件變化時還抱著原本的選擇。</p>
<h2 id="下一章">下一章</h2>
<p>下一章：<a href="/blog/llm/01-local-llm-services/expectation-management/" data-link-title="1.5 期望管理：本地 LLM 的擅長領域與分工" data-link-desc="本地 LLM 是免費的初階 pair programmer：辨識它的擅長領域、跟雲端旗艦做結構性分工">1.5 期望管理</a>，把本地 LLM 放在「免費的初階 pair programmer」這個正確位置，避免錯誤期待造成的挫折。</p>
]]></content:encoded></item><item><title>1.5 期望管理：本地 LLM 的擅長領域與分工</title><link>https://tarrragon.github.io/blog/llm/01-local-llm-services/expectation-management/</link><pubDate>Mon, 11 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/llm/01-local-llm-services/expectation-management/</guid><description>&lt;p>本地 LLM 用得順不順、九成取決於「期待對齊現實」。把本地當成「免費、永遠在線的初階 pair programmer」、它的表現會超出預期、變成日常雜事的得力幫手；把它當成 Claude Sonnet / GPT-5 替代品、跨檔案重構失敗、規劃 multi-step 任務（把模糊目標拆成多個可執行步驟依序執行）崩潰、深度 debug 給平庸答案的場景就會接連出現、第一週體感很差。本地 vs 雲端的能力分工背景見 &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 本地 vs 雲端 LLM&lt;/a>。&lt;/p>
&lt;p>本章把期待校準到現實。讀完後你會清楚知道：哪些任務交本地、哪些交雲端、本地 LLM 一週後該怎麼判斷去留、什麼時候硬體升級才有意義。&lt;/p>
&lt;h2 id="本章目標">本章目標&lt;/h2>
&lt;p>讀完本章後，你應該能：&lt;/p>
&lt;ol>
&lt;li>區分本地擅長領域、雲端擅長領域、模糊地帶三類任務。&lt;/li>
&lt;li>建立「本地 vs 雲端」的切換反射、減少每次糾結。&lt;/li>
&lt;li>用一週實測決定本地 LLM 是否留在工作流。&lt;/li>
&lt;li>識別本地 LLM 對你個人是「日常主力」「偶爾備援」還是「整體無用」。&lt;/li>
&lt;/ol>
&lt;h2 id="本地擅長領域明確強項">本地擅長領域：明確強項&lt;/h2>
&lt;p>本地 LLM 在這些任務上的表現「足夠好、足夠快、值得每天用」：&lt;/p>
&lt;table>
 &lt;thead>
 &lt;tr>
 &lt;th>任務&lt;/th>
 &lt;th>為什麼適合本地&lt;/th>
 &lt;/tr>
 &lt;/thead>
 &lt;tbody>
 &lt;tr>
 &lt;td>補 type annotation&lt;/td>
 &lt;td>模式單純、context 短、本地速度快&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>寫 docstring&lt;/td>
 &lt;td>模式單純、有現成函式可看&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>寫 unit test 第一版&lt;/td>
 &lt;td>任務有結構、可以邊讀邊修&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>解釋程式碼片段&lt;/td>
 &lt;td>短 context、單檔內推理足夠&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>改名變數 / 函式（refactor rename）&lt;/td>
 &lt;td>任務範圍明確、不需要創造力&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>把 callback 改成 async/await&lt;/td>
 &lt;td>常見 pattern、模型訓練資料多&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>把 for loop 改成 list comprehension&lt;/td>
 &lt;td>同上&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>寫 SQL（簡單 query）&lt;/td>
 &lt;td>有明確語法、可以邊跑邊改&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>Git commit message&lt;/td>
 &lt;td>任務簡短、本地隱私邊界足夠&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>寫 README / changelog 草稿&lt;/td>
 &lt;td>草稿後人類會修、品質要求中等&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>解釋錯誤訊息&lt;/td>
 &lt;td>多半是已知 pattern&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>把 JSON / YAML 轉換格式&lt;/td>
 &lt;td>任務機械化&lt;/td>
 &lt;/tr>
 &lt;/tbody>
&lt;/table>
&lt;p>本地擅長的共通結構：&lt;strong>模式單純度高 + context 短 + 結果可驗證&lt;/strong>。遇到新任務時用這三條判讀：模式有沒有大量訓練資料覆蓋（補 type / 寫 docstring 屬高、設計新架構屬低）、需要的 context 是不是單檔內（單檔內屬短、跨檔屬長）、回應對不對自己看得出來（測試跑得過 / 註解讀得通 = 可驗證、深度 debug 的結論對錯難以即時驗證 = 不可驗證）。三條都打勾、本地通常勝任；任一缺項、考慮切雲端。&lt;/p>
&lt;p>這份清單覆蓋了一般工程師每天 60 ~ 80% 的 LLM 使用情境。對主要靠雲端 API 訂閱（Claude Code、ChatGPT Plus、API tokens）的使用者、把這些餵給本地能讓雲端費用 / 配額用在真正困難的任務上。&lt;/p>
&lt;h2 id="雲端擅長領域本地較弱改用雲端更划算">雲端擅長領域：本地較弱、改用雲端更划算&lt;/h2>
&lt;p>下列任務在雲端旗艦上的表現明顯領先本地、預設交給雲端可以省下「先試本地、發現品質不夠、再切雲端」的時間成本：&lt;/p>
&lt;table>
 &lt;thead>
 &lt;tr>
 &lt;th>任務&lt;/th>
 &lt;th>為什麼雲端旗艦較適合&lt;/th>
 &lt;/tr>
 &lt;/thead>
 &lt;tbody>
 &lt;tr>
 &lt;td>跨多個檔案的重構&lt;/td>
 &lt;td>context window 較大 + 推理深度足夠&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>設計新模組的架構&lt;/td>
 &lt;td>需要綜合判斷、雲端旗艦深度領先&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>規劃 multi-step 任務（拆 todo）&lt;/td>
 &lt;td>規劃能力是雲端旗艦的明顯強項&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>深度 debug（非常見錯誤）&lt;/td>
 &lt;td>需要推理能力與大量訓練資料&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>評估技術選型（A vs B）&lt;/td>
 &lt;td>需要廣泛知識與權衡能力&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>寫長篇技術文件&lt;/td>
 &lt;td>篇幅大、邏輯連貫要求高&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>從模糊需求拆出 acceptance criteria&lt;/td>
 &lt;td>需要產品意識、模型訓練資料中較少&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>數學推理（複雜演算法）&lt;/td>
 &lt;td>雲端旗艦的 reasoning effort 模式領先明顯&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>解少見語言（COBOL、Erlang）&lt;/td>
 &lt;td>訓練資料較多、hallucination 較少&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>處理長 &lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/context-window/" data-link-title="Context Window" data-link-desc="模型一次能處理的最大 token 數量：prompt 加生成的總和上限">context&lt;/a>（10K+ tokens）&lt;/td>
 &lt;td>雲端的 &lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/prefill/" data-link-title="Prefill" data-link-desc="Prompt 首次處理時的計算階段：把整段輸入跑過模型、產生 KV cache">prefill&lt;/a> 算力遠高於 Apple Silicon&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/agent/" data-link-title="LLM Agent" data-link-desc="把控制流交給 LLM 的應用模式：自主決策、跨多步呼叫工具、人類角色從主導變監督">Agent&lt;/a> 模式（複雜 multi-step tool use）&lt;/td>
 &lt;td>本地 &lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/function-calling/" data-link-title="Function Calling" data-link-desc="模型訓練階段建立的「呼叫工具」能力：知道何時該呼叫、傳什麼參數">tool use&lt;/a> 支援陽春、雲端 agent 框架成熟、見 &lt;a href="https://tarrragon.github.io/blog/llm/04-applications/agent-architecture/" data-link-title="4.4 Agent 架構原理" data-link-desc="Agent loop 結構、失敗模式、什麼任務適合 vs 不適合、跟人類審查的協作模型">4.4 Agent 架構原理&lt;/a>&lt;/td>
 &lt;/tr>
 &lt;/tbody>
&lt;/table>
&lt;p>雲端擅長的共通結構：&lt;strong>context window 大 + reasoning depth 深 + 訓練資料密度高&lt;/strong>。雲端旗艦的 context 動輒 200K+ tokens、reasoning effort 模式能跑深推理 chain、訓練資料量級遠超開源模型。新任務若涉及「跨多檔閱讀 + 多步驟規劃 + 領域知識深度」、預設交雲端比較划算。&lt;/p></description><content:encoded><![CDATA[<p>本地 LLM 用得順不順、九成取決於「期待對齊現實」。把本地當成「免費、永遠在線的初階 pair programmer」、它的表現會超出預期、變成日常雜事的得力幫手；把它當成 Claude Sonnet / GPT-5 替代品、跨檔案重構失敗、規劃 multi-step 任務（把模糊目標拆成多個可執行步驟依序執行）崩潰、深度 debug 給平庸答案的場景就會接連出現、第一週體感很差。本地 vs 雲端的能力分工背景見 <a href="/blog/llm/00-foundations/local-vs-cloud/" data-link-title="0.0 本地 vs 雲端 LLM" data-link-desc="從隱私、成本、速度、能力四個維度建立本地與雲端 LLM 的基本對照">0.0 本地 vs 雲端 LLM</a>。</p>
<p>本章把期待校準到現實。讀完後你會清楚知道：哪些任務交本地、哪些交雲端、本地 LLM 一週後該怎麼判斷去留、什麼時候硬體升級才有意義。</p>
<h2 id="本章目標">本章目標</h2>
<p>讀完本章後，你應該能：</p>
<ol>
<li>區分本地擅長領域、雲端擅長領域、模糊地帶三類任務。</li>
<li>建立「本地 vs 雲端」的切換反射、減少每次糾結。</li>
<li>用一週實測決定本地 LLM 是否留在工作流。</li>
<li>識別本地 LLM 對你個人是「日常主力」「偶爾備援」還是「整體無用」。</li>
</ol>
<h2 id="本地擅長領域明確強項">本地擅長領域：明確強項</h2>
<p>本地 LLM 在這些任務上的表現「足夠好、足夠快、值得每天用」：</p>
<table>
  <thead>
      <tr>
          <th>任務</th>
          <th>為什麼適合本地</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>補 type annotation</td>
          <td>模式單純、context 短、本地速度快</td>
      </tr>
      <tr>
          <td>寫 docstring</td>
          <td>模式單純、有現成函式可看</td>
      </tr>
      <tr>
          <td>寫 unit test 第一版</td>
          <td>任務有結構、可以邊讀邊修</td>
      </tr>
      <tr>
          <td>解釋程式碼片段</td>
          <td>短 context、單檔內推理足夠</td>
      </tr>
      <tr>
          <td>改名變數 / 函式（refactor rename）</td>
          <td>任務範圍明確、不需要創造力</td>
      </tr>
      <tr>
          <td>把 callback 改成 async/await</td>
          <td>常見 pattern、模型訓練資料多</td>
      </tr>
      <tr>
          <td>把 for loop 改成 list comprehension</td>
          <td>同上</td>
      </tr>
      <tr>
          <td>寫 SQL（簡單 query）</td>
          <td>有明確語法、可以邊跑邊改</td>
      </tr>
      <tr>
          <td>Git commit message</td>
          <td>任務簡短、本地隱私邊界足夠</td>
      </tr>
      <tr>
          <td>寫 README / changelog 草稿</td>
          <td>草稿後人類會修、品質要求中等</td>
      </tr>
      <tr>
          <td>解釋錯誤訊息</td>
          <td>多半是已知 pattern</td>
      </tr>
      <tr>
          <td>把 JSON / YAML 轉換格式</td>
          <td>任務機械化</td>
      </tr>
  </tbody>
</table>
<p>本地擅長的共通結構：<strong>模式單純度高 + context 短 + 結果可驗證</strong>。遇到新任務時用這三條判讀：模式有沒有大量訓練資料覆蓋（補 type / 寫 docstring 屬高、設計新架構屬低）、需要的 context 是不是單檔內（單檔內屬短、跨檔屬長）、回應對不對自己看得出來（測試跑得過 / 註解讀得通 = 可驗證、深度 debug 的結論對錯難以即時驗證 = 不可驗證）。三條都打勾、本地通常勝任；任一缺項、考慮切雲端。</p>
<p>這份清單覆蓋了一般工程師每天 60 ~ 80% 的 LLM 使用情境。對主要靠雲端 API 訂閱（Claude Code、ChatGPT Plus、API tokens）的使用者、把這些餵給本地能讓雲端費用 / 配額用在真正困難的任務上。</p>
<h2 id="雲端擅長領域本地較弱改用雲端更划算">雲端擅長領域：本地較弱、改用雲端更划算</h2>
<p>下列任務在雲端旗艦上的表現明顯領先本地、預設交給雲端可以省下「先試本地、發現品質不夠、再切雲端」的時間成本：</p>
<table>
  <thead>
      <tr>
          <th>任務</th>
          <th>為什麼雲端旗艦較適合</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>跨多個檔案的重構</td>
          <td>context window 較大 + 推理深度足夠</td>
      </tr>
      <tr>
          <td>設計新模組的架構</td>
          <td>需要綜合判斷、雲端旗艦深度領先</td>
      </tr>
      <tr>
          <td>規劃 multi-step 任務（拆 todo）</td>
          <td>規劃能力是雲端旗艦的明顯強項</td>
      </tr>
      <tr>
          <td>深度 debug（非常見錯誤）</td>
          <td>需要推理能力與大量訓練資料</td>
      </tr>
      <tr>
          <td>評估技術選型（A vs B）</td>
          <td>需要廣泛知識與權衡能力</td>
      </tr>
      <tr>
          <td>寫長篇技術文件</td>
          <td>篇幅大、邏輯連貫要求高</td>
      </tr>
      <tr>
          <td>從模糊需求拆出 acceptance criteria</td>
          <td>需要產品意識、模型訓練資料中較少</td>
      </tr>
      <tr>
          <td>數學推理（複雜演算法）</td>
          <td>雲端旗艦的 reasoning effort 模式領先明顯</td>
      </tr>
      <tr>
          <td>解少見語言（COBOL、Erlang）</td>
          <td>訓練資料較多、hallucination 較少</td>
      </tr>
      <tr>
          <td>處理長 <a href="/blog/llm/knowledge-cards/context-window/" data-link-title="Context Window" data-link-desc="模型一次能處理的最大 token 數量：prompt 加生成的總和上限">context</a>（10K+ tokens）</td>
          <td>雲端的 <a href="/blog/llm/knowledge-cards/prefill/" data-link-title="Prefill" data-link-desc="Prompt 首次處理時的計算階段：把整段輸入跑過模型、產生 KV cache">prefill</a> 算力遠高於 Apple Silicon</td>
      </tr>
      <tr>
          <td><a href="/blog/llm/knowledge-cards/agent/" data-link-title="LLM Agent" data-link-desc="把控制流交給 LLM 的應用模式：自主決策、跨多步呼叫工具、人類角色從主導變監督">Agent</a> 模式（複雜 multi-step tool use）</td>
          <td>本地 <a href="/blog/llm/knowledge-cards/function-calling/" data-link-title="Function Calling" data-link-desc="模型訓練階段建立的「呼叫工具」能力：知道何時該呼叫、傳什麼參數">tool use</a> 支援陽春、雲端 agent 框架成熟、見 <a href="/blog/llm/04-applications/agent-architecture/" data-link-title="4.4 Agent 架構原理" data-link-desc="Agent loop 結構、失敗模式、什麼任務適合 vs 不適合、跟人類審查的協作模型">4.4 Agent 架構原理</a></td>
      </tr>
  </tbody>
</table>
<p>雲端擅長的共通結構：<strong>context window 大 + reasoning depth 深 + 訓練資料密度高</strong>。雲端旗艦的 context 動輒 200K+ tokens、reasoning effort 模式能跑深推理 chain、訓練資料量級遠超開源模型。新任務若涉及「跨多檔閱讀 + 多步驟規劃 + 領域知識深度」、預設交雲端比較划算。</p>
<p>這份清單覆蓋了「LLM 真正取代人類思考的部分」、雲端旗艦的能力斷崖式領先。</p>
<h2 id="模糊地帶先試本地視結果切換">模糊地帶：先試本地、視結果切換</h2>
<p>下列任務本地能否做好視具體 case 而定。預設策略是「先試本地、看到觸發訊號再切雲端」：</p>
<table>
  <thead>
      <tr>
          <th>任務</th>
          <th>切到雲端的觸發訊號（可量化）</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>解釋一個 bug 的根本原因</td>
          <td>同 prompt 試 2 次本地仍給通用解釋（沒點到具體 root cause）/ 跟錯誤 stack trace 對不上</td>
      </tr>
      <tr>
          <td>改寫一段較複雜的 function</td>
          <td>測試 fail 超過 1 條 / 行為跟 docstring 矛盾 / 出現未匹配的括號或語法錯</td>
      </tr>
      <tr>
          <td>寫一段中等長度（&lt; 50 行）的新 code</td>
          <td>第一版跑不過 / 結構跟你 prompt 描述偏差 &gt; 30% / 用了未 import 的 symbol</td>
      </tr>
      <tr>
          <td>翻譯 code 註解到另一種語言</td>
          <td>翻完讀起來語意失準 / 專有名詞被翻成意譯而非保留 / 結果跟原文長度差超過 50%</td>
      </tr>
      <tr>
          <td>寫單元測試（中等複雜度的函式）</td>
          <td>測試覆蓋 &lt; 60% 分支 / 沒涵蓋邊界條件（空 input、超大 input、null）</td>
      </tr>
      <tr>
          <td>回答一個技術概念性問題</td>
          <td>答案跟你已知矛盾 / 來源不明 / 沒給可驗證的細節（API 名、版本、行為）</td>
      </tr>
  </tbody>
</table>
<p>觸發訊號的設計目標是「不依賴主觀判斷」、用具體跡象避免「總覺得本地不夠好就一律切雲端」的偏誤。建立自己的觸發訊號清單後、切換變成反射動作、不再每次糾結。模糊地帶切到雲端是正常工作流、是「先用便宜的工具、不夠再升級」的合理做法、跟本地「失敗」是兩件事。</p>
<h2 id="切換的具體流程">切換的具體流程</h2>
<p>Continue.dev 的 chat panel 下方（輸入框上方的下拉選單）有 model selector、可以直接切。建議的反射動作：</p>
<ol>
<li><strong>預設用本地</strong>：開啟 Continue panel 時、先選本地 model。</li>
<li><strong>碰到雲端擅長任務直接切</strong>：上面雲端擅長表格的任務、第一次提問就選雲端。</li>
<li><strong>模糊地帶試一次本地</strong>：本地的回答堪用就用、看到觸發訊號就切雲端重提。</li>
<li><strong>記錄本地 hit rate</strong>：用一週、記錄哪些任務本地通過。第二週開始就有自己的判斷依據。</li>
</ol>
<p>把本地當工具、把切換當常態。本地的價值在於「該用時隨手可用」、不是「裝了就要硬用」。</p>
<h2 id="用一週實測去留決策">用一週實測：去留決策</h2>
<p>裝完本地 LLM 後、建議用一週實測決定是否留下來。實測時做四件事：</p>
<ol>
<li><strong>每次用 LLM 都先試本地</strong>、讓本地有機會證明自己。</li>
<li><strong>記錄 hit rate</strong>：簡單試算表、欄位放任務描述、本地通過、雲端通過。</li>
<li><strong>記錄體感速度</strong>：本地的等待感是「順暢」「可接受」「心煩」哪一級。</li>
<li><strong>記錄記憶體與發熱</strong>：Mac 是否變慢、風扇是否狂轉影響其他工作。</li>
</ol>
<p>一週後做決策（hit rate 閾值是經驗值、可依任務分佈微調）：</p>
<table>
  <thead>
      <tr>
          <th>觀察結果</th>
          <th>建議</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>Hit rate &gt; 60%、體感速度可接受、Mac 沒崩</td>
          <td><strong>留下</strong>、本地當日常主力</td>
      </tr>
      <tr>
          <td>Hit rate 40 ~ 60%、體感速度可接受</td>
          <td><strong>留下</strong>、混用雲端更積極</td>
      </tr>
      <tr>
          <td>Hit rate &lt; 40%</td>
          <td><strong>改評估</strong>換更大模型、或退到偶爾備援</td>
      </tr>
      <tr>
          <td>體感速度太慢（&lt; 10 <a href="/blog/llm/knowledge-cards/tokens-per-second/" data-link-title="Tokens Per Second" data-link-desc="LLM 每秒能生成幾個 token：生字速度的標準量化指標">tok/s</a>）</td>
          <td>換較小模型或考慮升級硬體</td>
      </tr>
      <tr>
          <td>Mac 持續變慢、風扇狂轉</td>
          <td>記憶體不足、換較小模型或承認 Mac 規格較適合偶爾使用</td>
      </tr>
      <tr>
          <td>雲端 API 費用沒降</td>
          <td>切換習慣還沒養成、回去檢查預設選項</td>
      </tr>
  </tbody>
</table>
<p>這個實測比看 benchmark 重要得多、因為你的工作流跟 benchmark 設定的任務分佈未必一致。</p>
<h2 id="本地-llm-的角色定位">本地 LLM 的角色定位</h2>
<p>把本地 LLM 定位成「免費的初階 pair programmer」、期待會自然對齊現實：</p>
<ol>
<li><strong>初階 pair programmer 是有用的</strong>：能寫測試、能解釋程式碼、能補 type、能改 callback。這些事一個 junior 同事每天做得很好。</li>
<li><strong>初階 pair programmer 有適用範圍</strong>：設計新架構、跨檔案重構、評估技術選型適合交給 senior（雲端旗艦）、跟交給 junior 同事的判斷一致。</li>
<li><strong>初階 pair programmer 隨時在線、不用付薪水</strong>：這是本地 LLM 比 junior 同事還好的地方。</li>
<li><strong>初階 pair programmer 跟 senior 互補</strong>：本地處理量、雲端處理難度、兩者組合讓 senior 把時間花在真正困難的部分。</li>
</ol>
<p>陷阱是把本地當「便宜的 senior」。它的能力等級是 junior；明確這個定位後、你會自然把日常雜事丟給本地、把難題留給雲端。</p>
<h2 id="跟雲端旗艦的協作姿勢">跟雲端旗艦的協作姿勢</h2>
<p>「混用」是有結構的協作姿勢、不是隨機切換。下表是寫 code 場景的典型分工：</p>
<table>
  <thead>
      <tr>
          <th>場景</th>
          <th>流程</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>我有個新 feature 要開發</td>
          <td>雲端旗艦規劃 → 本地寫 boilerplate → 雲端旗艦審 critical 部分</td>
      </tr>
      <tr>
          <td>我要 debug 一個 bug</td>
          <td>本地解釋錯誤訊息 → 自己看 code → 雲端旗艦審 root cause</td>
      </tr>
      <tr>
          <td>我要重構一個 module</td>
          <td>雲端旗艦設計新結構 → 本地實際改 code → 雲端旗艦審差異</td>
      </tr>
      <tr>
          <td>我要寫一份技術文件</td>
          <td>雲端旗艦寫大綱 → 本地寫各節草稿 → 自己潤稿 → 雲端旗艦審稿</td>
      </tr>
      <tr>
          <td>我要寫測試</td>
          <td>本地寫 → 自己跑 → 缺漏處交雲端旗艦補</td>
      </tr>
      <tr>
          <td>我要 commit</td>
          <td>本地寫 commit message、自己審</td>
      </tr>
      <tr>
          <td>我要解釋一段 code 給同事看</td>
          <td>本地寫解釋、自己審</td>
      </tr>
  </tbody>
</table>
<p>這個結構讓「雲端旗艦的高品質」用在最值錢的地方（規劃 + 審稿）、「本地的免費 + 速度」用在批量產出。雲端 API 費用會大幅下降、思考品質仍然維持高水準。</p>
<h2 id="硬體升級的判斷時機">硬體升級的判斷時機</h2>
<p>裝完本地、用一週後、可能會想「升級 Mac 是否值得」。判斷依據（記憶體預算的完整推導見 <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>）：</p>
<ol>
<li><strong>記憶體預算</strong>：跑 14B 模型體感卡 → 升 24GB；跑 31B 卡 → 升 32GB；跑 70B 卡 → 升 64GB。</li>
<li><strong>生字速度</strong>：用最強量化與較小模型仍 &lt; 10 tok/s 表示要換更輕的模型、不是升級硬體。</li>
<li><strong>Hit rate 太低</strong>：問題在本地模型能力上限、不在硬體、升級沒幫助。</li>
<li><strong>長 context 場景</strong>：升級到 48GB+ 才能順暢處理 16K+ context。</li>
</ol>
<p>陷阱是把「想換新 Mac」混在「正當理由」裡。先用一個月再決定；多數情況下省下的 API 費用攤平不了升級成本。</p>
<h2 id="識別本地對你個人沒用的訊號">識別「本地對你個人沒用」的訊號</h2>
<p>下列訊號表示本地 LLM 在你工作流上幫助有限、可以乾脆卸載：</p>
<ol>
<li>一週後雲端 API 費用沒降、因為切換習慣始終沒養成。</li>
<li>本地回答太慢、實際使用頻率低、Ollama 卻在背景吃記憶體。</li>
<li>Mac 規格本來就吃緊、跑本地讓其他工作變慢。</li>
<li>你的工作主要是規劃、設計、複雜推理、本地擅長領域跟你的主場交集小。</li>
</ol>
<p>卸載屬於合理結論、不算失敗。本地 LLM 適合特定工作流；你的工作流跟它的擅長領域交集小、改用雲端是更划算的選擇。</p>
<p>完整卸載 Ollama 跟 Continue.dev 的指令：</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="ln">1</span><span class="cl">brew services stop ollama
</span></span><span class="line"><span class="ln">2</span><span class="cl">brew uninstall ollama
</span></span><span class="line"><span class="ln">3</span><span class="cl">rm -rf ~/.ollama
</span></span><span class="line"><span class="ln">4</span><span class="cl">
</span></span><span class="line"><span class="ln">5</span><span class="cl"><span class="c1"># 卸載 Continue.dev 擴充套件</span>
</span></span><span class="line"><span class="ln">6</span><span class="cl"><span class="c1"># 在 VS Code Extensions panel 找到 Continue 點 Uninstall</span>
</span></span><span class="line"><span class="ln">7</span><span class="cl">rm -rf ~/.continue</span></span></code></pre></div><p>卸載後可以雲端 API 全用 Claude Code、Cursor 或其他雲端 IDE plugin、體驗一樣完整。</p>
<h2 id="何時不適用本章建議">何時不適用本章建議</h2>
<p>本章假設你的工作流可以「混用本地 + 雲端」。以下情境的混用前提不成立、本章建議要調整：</p>
<table>
  <thead>
      <tr>
          <th>情境</th>
          <th>該怎麼處理</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>工作流 100% 離線環境</td>
          <td>雲端不是選項、放棄「切雲端」反射、改成「本地能做的盡量做、做不到的等回到線上」</td>
      </tr>
      <tr>
          <td>NDA 嚴格禁止任何 AI 工具</td>
          <td>連本地 LLM 都要評估是否在 NDA 範圍、見 <a href="/blog/llm/00-foundations/privacy-data-flow/" data-link-title="0.7 隱私 / 資安的資料流原理" data-link-desc="從「位置」到「資料流」的思考升級：信任邊界、合約模型、零信任原則套用到 LLM 工作流">0.7 隱私資料流</a> 的判讀流程</td>
      </tr>
      <tr>
          <td>公司只允許特定雲端服務</td>
          <td>切換選擇受限、模糊地帶直接走允許的雲端、不用試本地</td>
      </tr>
      <tr>
          <td>純研究 / 學術工作流</td>
          <td>本章寫 code 場景的判讀不直接套用、研究場景需要的是模型行為觀察、不是 hit rate</td>
      </tr>
  </tbody>
</table>
<h2 id="下一章">下一章</h2>
<p>下一章：<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>、講日常路徑跑穩後可以玩的延伸（Open WebUI、aider、產圖）。</p>
]]></content:encoded></item><item><title>1.6 延伸方向：Web UI、coding agent、產圖</title><link>https://tarrragon.github.io/blog/llm/01-local-llm-services/extension-paths/</link><pubDate>Mon, 11 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/llm/01-local-llm-services/extension-paths/</guid><description>&lt;p>模組一前五章覆蓋了「Ollama + Continue.dev」這條最短路徑。日常路徑跑穩後，你可能會想往以下方向延伸：加裝 ChatGPT 風格的 Web UI、跑 coding agent、嘗試產圖。本章把這些延伸方向逐一列出、給優先順序、講清楚哪些是「換工具」、哪些是「換領域」。&lt;/p>
&lt;p>關鍵原則：&lt;strong>先把寫 code 跑穩、再考慮延伸&lt;/strong>。同時推進三條延伸通常會讓每條都停在半生不熟階段、累積成果有限。本章建議的順序是先 Web UI、再 coding agent、最後產圖；如果你只想嘗試一個、依自己最常用的場景挑。&lt;/p>
&lt;h2 id="本章目標">本章目標&lt;/h2>
&lt;p>讀完本章後，你應該能：&lt;/p>
&lt;ol>
&lt;li>列出三條延伸方向的代表工具與基本定位。&lt;/li>
&lt;li>知道每個方向跟寫 code 主路徑的關係。&lt;/li>
&lt;li>判斷自己現階段該不該往延伸方向走。&lt;/li>
&lt;li>對「產圖」這條歧路建立正確認知（不是換 model 就好）。&lt;/li>
&lt;/ol>
&lt;h2 id="延伸方向一chatgpt-風格-web-uiopen-webui">延伸方向一：ChatGPT 風格 Web UI（Open WebUI）&lt;/h2>
&lt;p>&lt;strong>定位&lt;/strong>：在瀏覽器跑一個類 ChatGPT 介面，連到本地 LLM 或雲端 LLM。屬於&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>的介面層，跟 Continue.dev 同層、解決不同情境（瀏覽器 vs IDE）。&lt;/p>
&lt;p>&lt;strong>典型使用情境&lt;/strong>：&lt;/p>
&lt;ol>
&lt;li>不在寫 code 但想跟 LLM 對話（解釋技術概念、寫文章草稿）。&lt;/li>
&lt;li>跟同事 / 家人分享 LLM 使用，他們不會用 VS Code。&lt;/li>
&lt;li>從手機 / iPad 連回家裡 Mac 跑的 Ollama。&lt;/li>
&lt;li>多輪深度對話、希望有歷史紀錄保存。&lt;/li>
&lt;/ol>
&lt;h3 id="主流選擇open-webui">主流選擇：Open WebUI&lt;/h3>
&lt;p>Open WebUI 是 open source 的 ChatGPT-clone，連 Ollama 與 OpenAI 相容 API。安裝最快路徑是 Docker：&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">docker run -d --name open-webui -p 3000:8080 &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> -e &lt;span class="nv">OLLAMA_BASE_URL&lt;/span>&lt;span class="o">=&lt;/span>http://host.docker.internal:11434 &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> -v open-webui:/app/backend/data &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> --restart always &lt;span class="se">\
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">5&lt;/span>&lt;span class="cl">&lt;span class="se">&lt;/span> ghcr.io/open-webui/open-webui:main&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>&lt;code>host.docker.internal&lt;/code> 是 Docker Desktop 提供的 DNS 名稱、container 內透過它連到宿主機（macOS 本身）跑的 Ollama；Linux Docker 沒這個別名、要改用 &lt;code>--add-host=host.docker.internal:host-gateway&lt;/code> 或直接填宿主 IP。啟動後開 &lt;code>http://localhost:3000&lt;/code>、註冊本地帳號（資料只存本機 SQLite）、就有完整 ChatGPT 介面：&lt;/p>
&lt;ul>
&lt;li>對話歷史保存（本地 SQLite）&lt;/li>
&lt;li>多 model 切換、可同時對比兩個 model 回答&lt;/li>
&lt;li>系統 prompt 自訂、prompt template 管理&lt;/li>
&lt;li>上傳檔案分析（PDF、txt 等）&lt;/li>
&lt;li>圖片支援（如果本地 model 是多模態）&lt;/li>
&lt;/ul>
&lt;p>&lt;strong>陷阱&lt;/strong>：&lt;/p>
&lt;ol>
&lt;li>沒裝 Docker 的話要先學 Docker，是不小的前置學習。&lt;/li>
&lt;li>Open WebUI 預設不需要驗證，跑在 &lt;code>0.0.0.0&lt;/code> 會暴露在 LAN 上。要從外網用記得加 reverse proxy + auth。&lt;/li>
&lt;li>對話紀錄存在 Docker volume，刪 container 要小心保留 volume，否則歷史會消失。&lt;/li>
&lt;/ol>
&lt;p>&lt;strong>何時做這個延伸&lt;/strong>：日常 Continue.dev + Ollama 跑穩、用了至少一週、確認本地 LLM 對你有用，再加 Open WebUI 擴展使用情境。&lt;/p>
&lt;h2 id="延伸方向二coding-agentaidercline-等">延伸方向二：Coding Agent（aider、Cline 等）&lt;/h2>
&lt;p>&lt;strong>定位&lt;/strong>：比 Continue.dev 更主動的 LLM 寫 code 工具。Continue.dev 是「你提問、LLM 答」的對話模式；coding &lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/agent/" data-link-title="LLM Agent" data-link-desc="把控制流交給 LLM 的應用模式：自主決策、跨多步呼叫工具、人類角色從主導變監督">agent&lt;/a> 是「你給目標、LLM 自己分多步驟改 code、跑測試、修錯誤」的代理模式。詳細的 agent loop 結構、失敗模式、人類審查協作見 &lt;a href="https://tarrragon.github.io/blog/llm/04-applications/agent-architecture/" data-link-title="4.4 Agent 架構原理" data-link-desc="Agent loop 結構、失敗模式、什麼任務適合 vs 不適合、跟人類審查的協作模型">4.4 Agent 架構原理&lt;/a>。&lt;/p></description><content:encoded><![CDATA[<p>模組一前五章覆蓋了「Ollama + Continue.dev」這條最短路徑。日常路徑跑穩後，你可能會想往以下方向延伸：加裝 ChatGPT 風格的 Web UI、跑 coding agent、嘗試產圖。本章把這些延伸方向逐一列出、給優先順序、講清楚哪些是「換工具」、哪些是「換領域」。</p>
<p>關鍵原則：<strong>先把寫 code 跑穩、再考慮延伸</strong>。同時推進三條延伸通常會讓每條都停在半生不熟階段、累積成果有限。本章建議的順序是先 Web UI、再 coding agent、最後產圖；如果你只想嘗試一個、依自己最常用的場景挑。</p>
<h2 id="本章目標">本章目標</h2>
<p>讀完本章後，你應該能：</p>
<ol>
<li>列出三條延伸方向的代表工具與基本定位。</li>
<li>知道每個方向跟寫 code 主路徑的關係。</li>
<li>判斷自己現階段該不該往延伸方向走。</li>
<li>對「產圖」這條歧路建立正確認知（不是換 model 就好）。</li>
</ol>
<h2 id="延伸方向一chatgpt-風格-web-uiopen-webui">延伸方向一：ChatGPT 風格 Web UI（Open WebUI）</h2>
<p><strong>定位</strong>：在瀏覽器跑一個類 ChatGPT 介面，連到本地 LLM 或雲端 LLM。屬於<a href="/blog/llm/00-foundations/three-layer-architecture/" data-link-title="0.2 介面 / 伺服器 / 模型三層架構" data-link-desc="把任何本地 LLM 工具放回正確的層級，用三層心智模型看懂工具關係">三層架構</a>的介面層，跟 Continue.dev 同層、解決不同情境（瀏覽器 vs IDE）。</p>
<p><strong>典型使用情境</strong>：</p>
<ol>
<li>不在寫 code 但想跟 LLM 對話（解釋技術概念、寫文章草稿）。</li>
<li>跟同事 / 家人分享 LLM 使用，他們不會用 VS Code。</li>
<li>從手機 / iPad 連回家裡 Mac 跑的 Ollama。</li>
<li>多輪深度對話、希望有歷史紀錄保存。</li>
</ol>
<h3 id="主流選擇open-webui">主流選擇：Open WebUI</h3>
<p>Open WebUI 是 open source 的 ChatGPT-clone，連 Ollama 與 OpenAI 相容 API。安裝最快路徑是 Docker：</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">docker run -d --name open-webui -p 3000:8080 <span class="se">\
</span></span></span><span class="line"><span class="ln">2</span><span class="cl"><span class="se"></span>  -e <span class="nv">OLLAMA_BASE_URL</span><span class="o">=</span>http://host.docker.internal:11434 <span class="se">\
</span></span></span><span class="line"><span class="ln">3</span><span class="cl"><span class="se"></span>  -v open-webui:/app/backend/data <span class="se">\
</span></span></span><span class="line"><span class="ln">4</span><span class="cl"><span class="se"></span>  --restart always <span class="se">\
</span></span></span><span class="line"><span class="ln">5</span><span class="cl"><span class="se"></span>  ghcr.io/open-webui/open-webui:main</span></span></code></pre></div><p><code>host.docker.internal</code> 是 Docker Desktop 提供的 DNS 名稱、container 內透過它連到宿主機（macOS 本身）跑的 Ollama；Linux Docker 沒這個別名、要改用 <code>--add-host=host.docker.internal:host-gateway</code> 或直接填宿主 IP。啟動後開 <code>http://localhost:3000</code>、註冊本地帳號（資料只存本機 SQLite）、就有完整 ChatGPT 介面：</p>
<ul>
<li>對話歷史保存（本地 SQLite）</li>
<li>多 model 切換、可同時對比兩個 model 回答</li>
<li>系統 prompt 自訂、prompt template 管理</li>
<li>上傳檔案分析（PDF、txt 等）</li>
<li>圖片支援（如果本地 model 是多模態）</li>
</ul>
<p><strong>陷阱</strong>：</p>
<ol>
<li>沒裝 Docker 的話要先學 Docker，是不小的前置學習。</li>
<li>Open WebUI 預設不需要驗證，跑在 <code>0.0.0.0</code> 會暴露在 LAN 上。要從外網用記得加 reverse proxy + auth。</li>
<li>對話紀錄存在 Docker volume，刪 container 要小心保留 volume，否則歷史會消失。</li>
</ol>
<p><strong>何時做這個延伸</strong>：日常 Continue.dev + Ollama 跑穩、用了至少一週、確認本地 LLM 對你有用，再加 Open WebUI 擴展使用情境。</p>
<h2 id="延伸方向二coding-agentaidercline-等">延伸方向二：Coding Agent（aider、Cline 等）</h2>
<p><strong>定位</strong>：比 Continue.dev 更主動的 LLM 寫 code 工具。Continue.dev 是「你提問、LLM 答」的對話模式；coding <a href="/blog/llm/knowledge-cards/agent/" data-link-title="LLM Agent" data-link-desc="把控制流交給 LLM 的應用模式：自主決策、跨多步呼叫工具、人類角色從主導變監督">agent</a> 是「你給目標、LLM 自己分多步驟改 code、跑測試、修錯誤」的代理模式。詳細的 agent 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>。</p>
<p><strong>主流選擇</strong>：</p>
<table>
  <thead>
      <tr>
          <th>工具</th>
          <th>介面</th>
          <th>定位</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>aider</td>
          <td>CLI</td>
          <td>git-aware、把 LLM 改的 diff 直接 commit、支援 multi-file edit</td>
      </tr>
      <tr>
          <td>Cline</td>
          <td>VS Code 擴充</td>
          <td>在 VS Code 內跑 agent、可執行 shell command</td>
      </tr>
      <tr>
          <td>Cursor Agent</td>
          <td>Cursor 內建</td>
          <td>Cursor 訂閱戶可用、雲端綁定</td>
      </tr>
  </tbody>
</table>
<p>選擇三個工具的延伸判讀：</p>
<ul>
<li><strong>aider</strong>：當主要工作流是「在 terminal + git 內完成」、想讓 LLM 把 diff 直接 commit 進 history、aider 的 CLI-first + git-aware 設計最對位。失敗模式：跨多檔修改超過 5 個檔時、aider 的 prompt 規劃容易斷裂；改回 Continue.dev 手動逐檔修可能更穩。</li>
<li><strong>Cline</strong>：當你已在 VS Code 內工作、想要 agent 能跑 shell command（執行測試、跑 build 看錯誤）並 loop 修錯時、Cline 比 aider 更貼近「IDE 內 agent」。失敗模式：本地模型在「規劃 → 執行 shell → 解讀錯誤 → 改 code」這個 loop 上接受度不穩、常需要人工接管。</li>
<li><strong>Cursor Agent</strong>：當你已是 Cursor 訂閱戶、agent 預設綁雲端旗艦（成功率最高、但 prompt / code 會送到 Cursor 雲端）。NDA / 合規場景不適用、本地 LLM 接入也是次要 surface。</li>
</ul>
<p><strong>為什麼是 advanced</strong>：coding agent 需要本地模型能「跟著規劃跑多步驟、用 tools、不偏離目標」。這部分是本地 LLM 的弱項（見 <a href="/blog/llm/01-local-llm-services/expectation-management/" data-link-title="1.5 期望管理：本地 LLM 的擅長領域與分工" data-link-desc="本地 LLM 是免費的初階 pair programmer：辨識它的擅長領域、跟雲端旗艦做結構性分工">1.5 期望管理</a>）；現階段本地模型跑 coding agent 的成功率明顯低於雲端旗艦。</p>
<p><strong>用 aider 跑本地 LLM 的最小範例</strong>：</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="ln">1</span><span class="cl"><span class="c1"># 裝 aider</span>
</span></span><span class="line"><span class="ln">2</span><span class="cl">pip install aider-chat
</span></span><span class="line"><span class="ln">3</span><span class="cl">
</span></span><span class="line"><span class="ln">4</span><span class="cl"><span class="c1"># 在 git repo 內啟動，用本地 Ollama</span>
</span></span><span class="line"><span class="ln">5</span><span class="cl">aider --model ollama/gemma4:31b-coding-mtp-bf16 <span class="se">\
</span></span></span><span class="line"><span class="ln">6</span><span class="cl"><span class="se"></span>  --ollama-base-url http://localhost:11434</span></span></code></pre></div><p>aider 會把當前 repo 的相關檔案打進 prompt、把 LLM 生成的 diff apply 到本機、自動 commit。簡單任務（單檔重構、加 test）成功率還行；複雜任務（跨檔案、需要規劃）失敗率高。</p>
<p><strong>陷阱</strong>：</p>
<ol>
<li>本地 LLM 跑 aider 比跑 Continue.dev 慢得多、因為每輪 agent loop 都要重新處理長 context。</li>
<li>coding agent 對 long context 敏感、本地 <a href="/blog/llm/knowledge-cards/ttft/" data-link-title="TTFT" data-link-desc="Time To First Token：送出 prompt 到第一個 token 出現的等待時間">TTFT</a> 痛點被放大。Agent loop 每輪都會 mutate prompt（前一輪結果加入下一輪的 context）、<a href="/blog/llm/knowledge-cards/kv-cache/" data-link-title="KV Cache" data-link-desc="已處理 token 的 attention 中間結果暫存：避免重算、加速後續生成">KV cache</a> 命中率低、每輪都要重新做完整 prefill。</li>
<li>失敗時 agent 可能 commit 不可用的 code、要記得 <code>git diff</code> 審過再 push。</li>
</ol>
<p><strong>何時做這個延伸</strong>：本地模型在 Continue.dev 對話模式下表現穩定、且你想看看「multi-step 自動化」能幫到什麼程度。對多數讀者、這條延伸在 2026 年 5 月時是「值得試一週、但不一定留下」。</p>
<p><strong>何時該停</strong>：以下訊號出現時、agent 路線在你的工作流暫時不成立、回到 Continue.dev 對話模式：</p>
<ul>
<li>連續 5 個 multi-step 任務都需要人工接管 / 中途介入修錯</li>
<li>TTFT 持續 &gt; 30 秒、agent loop 的「等待 → 接管」節奏比手寫快不了多少</li>
<li>agent commit 進 git history 的 diff 通過率 &lt; 50%、審查與 revert 的成本超過自己寫</li>
<li>簡單任務（單檔重構、加 test）本地 agent 也常失敗、表示模型 capacity 對 agent 規劃不足</li>
</ul>
<h2 id="延伸方向三產圖stable-diffusionflux-等">延伸方向三：產圖（Stable Diffusion、Flux 等）</h2>
<p>產圖是另一個專業領域、工具鏈跟概念體系另起一套、跟 LLM 寫 code 沒有共用的伺服器層或 model layer。產圖用的是 <strong>Diffusion 架構</strong>、跟寫 code 用的 <strong>Transformer 架構</strong>是兩個獨立的神經網路類型。</p>
<p>四個維度上產圖跟寫 code 的工作流互不相通：</p>
<ol>
<li><strong>工具鏈各自獨立</strong>：Ollama 服務 <a href="/blog/llm/knowledge-cards/transformer/" data-link-title="Transformer" data-link-desc="寫 code 用的 LLM 神經網路架構：基於 attention 機制、自回歸生成 token">Transformer</a> LLM、Draw Things / ComfyUI 服務 <a href="/blog/llm/knowledge-cards/diffusion/" data-link-title="Diffusion" data-link-desc="產圖用的生成式 AI 架構：跟寫 code 用的 Transformer 是不同路線">Diffusion</a> 模型、兩條路線的伺服器與生態互不通用。</li>
<li><strong>prompt 風格不同</strong>：寫 code 是 instruction 形式、產圖是 descriptive prompt + negative prompt + sampler 參數。</li>
<li><strong>學習成本各自獨立</strong>：產圖有自己的 LoRA、ControlNet、IP-Adapter、refiner 等概念體系、學起來等於進入新領域。</li>
<li><strong>硬體最適規格不同</strong>：寫 code 看記憶體預算（<a href="/blog/llm/knowledge-cards/unified-memory/" data-link-title="Unified Memory Architecture" data-link-desc="Apple Silicon 讓 CPU / GPU / NE 共用同一塊記憶體：跑大模型的優勢來源">跑大模型</a>）、產圖看 GPU 算力與 VRAM 頻寬。</li>
</ol>
<p>本章只給入口資訊、不展開教學。</p>
<p><strong>主流工具</strong>：</p>
<table>
  <thead>
      <tr>
          <th>工具</th>
          <th>定位</th>
          <th>適合誰</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>Draw Things</td>
          <td>Mac 原生 app，GUI 友善，免費</td>
          <td>macOS 使用者入門首選</td>
      </tr>
      <tr>
          <td>ComfyUI</td>
          <td>節點式工作流，跨平台，需要 Python 環境</td>
          <td>想客製化流程、進階使用者</td>
      </tr>
      <tr>
          <td>AUTOMATIC1111</td>
          <td>Web UI，跨平台，需要 Python</td>
          <td>Linux / NVIDIA 玩家為主</td>
      </tr>
      <tr>
          <td>Diffusers</td>
          <td>Hugging Face 的 Python library</td>
          <td>開發者、要嵌入產品</td>
      </tr>
  </tbody>
</table>
<p><strong>主流模型</strong>：</p>
<table>
  <thead>
      <tr>
          <th>模型</th>
          <th>風格特色</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>Stable Diffusion 3.5</td>
          <td>通用、社群成熟、生態最大</td>
      </tr>
      <tr>
          <td>Flux</td>
          <td>質感高、prompt 跟隨度高</td>
      </tr>
      <tr>
          <td>SDXL</td>
          <td>SD 1.5 的進階版，仍有大量 LoRA</td>
      </tr>
  </tbody>
</table>
<p><strong>Apple Silicon Mac 跑產圖的現實</strong>：</p>
<ol>
<li>24GB+ Mac 可以順暢跑 SDXL / Flux。記憶體需求其實比 LLM 低（一張圖 ~ 8GB），但對 GPU 算力敏感。</li>
<li>M4 Max 跑 Flux 生 1024x1024 圖約 15 ~ 30 秒一張，可接受。</li>
<li>Draw Things 在 Mac App Store 可下載，是最簡單的入門路徑。</li>
</ol>
<p><strong>本指南的立場</strong>：先把寫 code 跑穩、再考慮產圖。產圖屬於獨立的學習主題、另外找專門教材會學得更有效率。</p>
<h2 id="給讀者的延伸順序">給讀者的延伸順序</h2>
<p>如果你想嘗試延伸方向，建議的順序：</p>
<ol>
<li><strong>先用一個月本地 LLM 寫 code</strong>。確認 Ollama + Continue.dev 對你有用、習慣了切換。</li>
<li><strong>第一個延伸：Open WebUI</strong>。加裝最低成本（只多裝 Docker），擴展使用情境到非 VS Code 場景。</li>
<li><strong>第二個延伸：aider 或 Cline</strong>。試 coding agent，評估本地模型能 handle 多複雜的多步驟任務。</li>
<li><strong>第三個延伸：產圖</strong>。完全獨立的學習投入，跟前面工具鏈無關。</li>
</ol>
<p>依序進階。先讓基底穩、再疊加延伸、學習曲線最平滑。</p>
<h2 id="不在本章範圍內的延伸">不在本章範圍內的延伸</h2>
<p>下列延伸方向值得知道存在，但不在本指南內展開：</p>
<table>
  <thead>
      <tr>
          <th>方向</th>
          <th>為什麼不展開</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td><a href="/blog/llm/knowledge-cards/rag/" data-link-title="RAG" data-link-desc="Retrieval-Augmented Generation：動態外掛知識給 LLM、繞開模型參數記憶的靜態限制">RAG</a>（檢索增強生成）</td>
          <td>需要 vector database、文件 chunking、embedding 設計、見 <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></td>
      </tr>
      <tr>
          <td>Fine-tuning</td>
          <td>訓練流程跟跑現成模型是不同工程；資源、資料、評估都複雜</td>
      </tr>
      <tr>
          <td>Multi-modal（語音、影片）</td>
          <td>工具鏈跟生態完全獨立</td>
      </tr>
      <tr>
          <td><a href="/blog/llm/knowledge-cards/mcp/" data-link-title="MCP（Model Context Protocol）" data-link-desc="LLM application ↔ 外部 tool server 之間的標準化協議、複用 OpenAI 相容 API 的成功模式">MCP</a>（Model Context Protocol）伺服器整合</td>
          <td>是工具串接協定、見 <a href="/blog/llm/04-applications/application-protocols/" data-link-title="4.6 應用層協議：function calling / structured output / MCP" data-link-desc="三個常被混為一談的概念：模型能力、sampling 約束、server 協議，三者的層級差異與組合方式">4.6 應用層協議</a></td>
      </tr>
      <tr>
          <td>部署到雲端 GPU / Linux server</td>
          <td>本指南範圍只在 Apple Silicon Mac</td>
      </tr>
  </tbody>
</table>
<p>需要這些方向時請另尋專門資源；硬塞進來會稀釋本指南「Mac 本地寫 code」這條最短路徑。</p>
<h2 id="下一步">下一步</h2>
<p>實作範例（含 ComfyUI / Whisper / Piper TTS / RAG / MCP）見 <a href="/blog/llm/01-local-llm-services/hands-on/" data-link-title="Hands-on：本地 AI 工具實作筆記" data-link-desc="Ollama / ComfyUI / Whisper / Piper TTS：實際安裝、驗證、跑通的紀錄。隨工具版本演化、跟 1.x 原理章節互補。">Hands-on 章節</a>。</p>
<p>讀到這裡、本指南的核心內容就完了。下一步是回到 <a href="/blog/llm/00-foundations/" data-link-title="模組零：基礎知識與心智模型" data-link-desc="建立本地 LLM 的心智模型、釐清 MLX / MTP / oMLX 等常被混淆的術語、Apple Silicon 記憶體現實">模組零</a> 或 <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 整合、模型選型與期望管理">模組一</a> 任一章節做深度閱讀、或實際打開終端機跑第一個 <code>ollama run</code>、把概念變成肌肉記憶。</p>
]]></content:encoded></item><item><title>1.7 排錯方法論：用三層架構做故障定位</title><link>https://tarrragon.github.io/blog/llm/01-local-llm-services/troubleshooting/</link><pubDate>Mon, 11 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/llm/01-local-llm-services/troubleshooting/</guid><description>&lt;p>本地 LLM 工作流出問題時、第一個本能反應常是「重啟試試看」。本章建立另一種反射：用&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>（介面 / &lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/inference-server/" data-link-title="Inference Server" data-link-desc="載入模型權重、處理 prompt、產生 token 的常駐 process">推論伺服器&lt;/a> / 模型）的視角先確認「哪一層壞」、再針對該層做具體診斷。這個方法不依賴記住每個工具的具體錯誤訊息、跨工具世代都成立。&lt;/p>
&lt;p>具體錯誤訊息對照表（「&lt;code>address already in use&lt;/code> 要這樣修」「&lt;code>model not found&lt;/code> 要那樣修」）不在本章——這些隨工具版本變、查 release notes 跟 GitHub issue 更快。本章寫的是「換工具之後仍成立」的排錯思維。&lt;/p>
&lt;h2 id="本章目標">本章目標&lt;/h2>
&lt;p>讀完本章後、你應該能：&lt;/p>
&lt;ol>
&lt;li>看到症狀時、先定位是介面 / 伺服器 / 模型哪一層的問題。&lt;/li>
&lt;li>知道在每一層該看什麼 log。&lt;/li>
&lt;li>用「最小可重現」策略快速縮減問題範圍。&lt;/li>
&lt;li>識別「跨層級的誤判」常見模式、把 server 層問題正確歸位、避開瞎調 model 的繞路。&lt;/li>
&lt;/ol>
&lt;h2 id="故障定位的核心原則先確認哪一層壞">故障定位的核心原則：先確認哪一層壞&lt;/h2>
&lt;p>模組零 &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> 的視角延伸到排錯：故障可能落在介面層（Continue.dev / Cursor 等 IDE 整合）、伺服器層（Ollama / LM Studio / llama.cpp）、或模型層（權重檔本身的能力 / 量化選擇）。在不知道哪一層壞之前、任何修法都是亂槍打鳥——重啟 Continue.dev 解不了模型量化太激進的問題、重 pull 模型解不了 IDE 設定錯的問題。&lt;/p>
&lt;p>先定位再修補的 ROI 高於直接修補、因為沒有定位的修法常常掃過正確答案還不知道是哪個動作生效。定位用的工具不複雜：&lt;/p>
&lt;ul>
&lt;li>&lt;strong>直接 curl 伺服器 API&lt;/strong>：繞過介面層、直接驗證伺服器是否回應正常。&lt;/li>
&lt;li>&lt;strong>&lt;code>ollama ps&lt;/code> / 等價指令&lt;/strong>：看伺服器層 model 狀態、確認 model 真的載入。&lt;/li>
&lt;li>&lt;strong>換 model 試試&lt;/strong>：同樣 prompt、不同 model 表現一致就是介面 / 伺服器層、不一致就是 model 層。&lt;/li>
&lt;li>&lt;strong>換 prompt 試試&lt;/strong>：簡單 prompt OK、複雜 prompt 崩、可能是 context 長度或 model 容量問題。&lt;/li>
&lt;/ul>
&lt;p>這四個動作能 cover 90% 的定位需求。學會這個反射、排錯時間大幅縮短。&lt;/p>
&lt;h2 id="症狀到層級的對應反射">症狀到層級的對應反射&lt;/h2>
&lt;p>不同症狀對應到不同最有可能的故障層、建立對應反射能省下大量試錯時間。下表是寫 code 場景常見症狀的對應：&lt;/p>
&lt;table>
 &lt;thead>
 &lt;tr>
 &lt;th>症狀&lt;/th>
 &lt;th>最可能層級&lt;/th>
 &lt;th>第一步驗證&lt;/th>
 &lt;/tr>
 &lt;/thead>
 &lt;tbody>
 &lt;tr>
 &lt;td>Continue.dev 完全沒回應&lt;/td>
 &lt;td>介面層 / 伺服器層&lt;/td>
 &lt;td>curl 伺服器、看伺服器是否正常&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>Continue.dev 報「connection refused」&lt;/td>
 &lt;td>伺服器層&lt;/td>
 &lt;td>伺服器沒在跑 / port 不對&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>Continue.dev 顯示請求送出但無回應&lt;/td>
 &lt;td>介面層 / 伺服器層&lt;/td>
 &lt;td>curl 同 prompt、比較行為&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>回答內容亂碼 / 一直重複&lt;/td>
 &lt;td>模型層&lt;/td>
 &lt;td>換&lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/quantization/" data-link-title="Quantization" data-link-desc="用較少 bits 表示模型權重：壓縮記憶體佔用、加快生字速度，代價是少量品質衰減">量化&lt;/a>等級或換模型試&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>回答邏輯離譜 / 答非所問&lt;/td>
 &lt;td>模型層&lt;/td>
 &lt;td>model 能力不足、考慮換大一點 model&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>TTFT 異常變長&lt;/td>
 &lt;td>模型層 / 推論機制&lt;/td>
 &lt;td>prompt 變長了？KV cache 失效？&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>整台 Mac 變慢、Ollama 沒崩&lt;/td>
 &lt;td>伺服器層 / 系統&lt;/td>
 &lt;td>記憶體 swap、看 Activity Monitor&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>Ollama 自己 crash&lt;/td>
 &lt;td>伺服器層&lt;/td>
 &lt;td>看 server log、通常 OOM 或 bug&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>跨 session 設定遺失&lt;/td>
 &lt;td>介面層&lt;/td>
 &lt;td>IDE 設定沒存或被 reset&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>Tab autocomplete 完全不觸發&lt;/td>
 &lt;td>介面層&lt;/td>
 &lt;td>autocomplete model 沒配對 / 沒 pull&lt;/td>
 &lt;/tr>
 &lt;/tbody>
&lt;/table>
&lt;p>對應的具體驗證指令範例：&lt;/p></description><content:encoded><![CDATA[<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/inference-server/" data-link-title="Inference Server" data-link-desc="載入模型權重、處理 prompt、產生 token 的常駐 process">推論伺服器</a> / 模型）的視角先確認「哪一層壞」、再針對該層做具體診斷。這個方法不依賴記住每個工具的具體錯誤訊息、跨工具世代都成立。</p>
<p>具體錯誤訊息對照表（「<code>address already in use</code> 要這樣修」「<code>model not found</code> 要那樣修」）不在本章——這些隨工具版本變、查 release notes 跟 GitHub issue 更快。本章寫的是「換工具之後仍成立」的排錯思維。</p>
<h2 id="本章目標">本章目標</h2>
<p>讀完本章後、你應該能：</p>
<ol>
<li>看到症狀時、先定位是介面 / 伺服器 / 模型哪一層的問題。</li>
<li>知道在每一層該看什麼 log。</li>
<li>用「最小可重現」策略快速縮減問題範圍。</li>
<li>識別「跨層級的誤判」常見模式、把 server 層問題正確歸位、避開瞎調 model 的繞路。</li>
</ol>
<h2 id="故障定位的核心原則先確認哪一層壞">故障定位的核心原則：先確認哪一層壞</h2>
<p>模組零 <a href="/blog/llm/00-foundations/three-layer-architecture/" data-link-title="0.2 介面 / 伺服器 / 模型三層架構" data-link-desc="把任何本地 LLM 工具放回正確的層級，用三層心智模型看懂工具關係">三層架構</a> 的視角延伸到排錯：故障可能落在介面層（Continue.dev / Cursor 等 IDE 整合）、伺服器層（Ollama / LM Studio / llama.cpp）、或模型層（權重檔本身的能力 / 量化選擇）。在不知道哪一層壞之前、任何修法都是亂槍打鳥——重啟 Continue.dev 解不了模型量化太激進的問題、重 pull 模型解不了 IDE 設定錯的問題。</p>
<p>先定位再修補的 ROI 高於直接修補、因為沒有定位的修法常常掃過正確答案還不知道是哪個動作生效。定位用的工具不複雜：</p>
<ul>
<li><strong>直接 curl 伺服器 API</strong>：繞過介面層、直接驗證伺服器是否回應正常。</li>
<li><strong><code>ollama ps</code> / 等價指令</strong>：看伺服器層 model 狀態、確認 model 真的載入。</li>
<li><strong>換 model 試試</strong>：同樣 prompt、不同 model 表現一致就是介面 / 伺服器層、不一致就是 model 層。</li>
<li><strong>換 prompt 試試</strong>：簡單 prompt OK、複雜 prompt 崩、可能是 context 長度或 model 容量問題。</li>
</ul>
<p>這四個動作能 cover 90% 的定位需求。學會這個反射、排錯時間大幅縮短。</p>
<h2 id="症狀到層級的對應反射">症狀到層級的對應反射</h2>
<p>不同症狀對應到不同最有可能的故障層、建立對應反射能省下大量試錯時間。下表是寫 code 場景常見症狀的對應：</p>
<table>
  <thead>
      <tr>
          <th>症狀</th>
          <th>最可能層級</th>
          <th>第一步驗證</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>Continue.dev 完全沒回應</td>
          <td>介面層 / 伺服器層</td>
          <td>curl 伺服器、看伺服器是否正常</td>
      </tr>
      <tr>
          <td>Continue.dev 報「connection refused」</td>
          <td>伺服器層</td>
          <td>伺服器沒在跑 / port 不對</td>
      </tr>
      <tr>
          <td>Continue.dev 顯示請求送出但無回應</td>
          <td>介面層 / 伺服器層</td>
          <td>curl 同 prompt、比較行為</td>
      </tr>
      <tr>
          <td>回答內容亂碼 / 一直重複</td>
          <td>模型層</td>
          <td>換<a href="/blog/llm/knowledge-cards/quantization/" data-link-title="Quantization" data-link-desc="用較少 bits 表示模型權重：壓縮記憶體佔用、加快生字速度，代價是少量品質衰減">量化</a>等級或換模型試</td>
      </tr>
      <tr>
          <td>回答邏輯離譜 / 答非所問</td>
          <td>模型層</td>
          <td>model 能力不足、考慮換大一點 model</td>
      </tr>
      <tr>
          <td>TTFT 異常變長</td>
          <td>模型層 / 推論機制</td>
          <td>prompt 變長了？KV cache 失效？</td>
      </tr>
      <tr>
          <td>整台 Mac 變慢、Ollama 沒崩</td>
          <td>伺服器層 / 系統</td>
          <td>記憶體 swap、看 Activity Monitor</td>
      </tr>
      <tr>
          <td>Ollama 自己 crash</td>
          <td>伺服器層</td>
          <td>看 server log、通常 OOM 或 bug</td>
      </tr>
      <tr>
          <td>跨 session 設定遺失</td>
          <td>介面層</td>
          <td>IDE 設定沒存或被 reset</td>
      </tr>
      <tr>
          <td>Tab autocomplete 完全不觸發</td>
          <td>介面層</td>
          <td>autocomplete model 沒配對 / 沒 pull</td>
      </tr>
  </tbody>
</table>
<p>對應的具體驗證指令範例：</p>
<ul>
<li><strong>回答亂碼 / 重複</strong>：<code>ollama list</code> 確認當前 model tag、改跑 <code>ollama run &lt;較高量化版本&gt;</code>（例如 Q4 → Q5）；同 prompt 換 model 確認是不是 model 本身能力問題、不是伺服器。</li>
<li><strong>TTFT 異常變長</strong>：<code>ollama ps</code> 看 model 是否被 unload 又重載（<a href="/blog/llm/01-local-llm-services/ollama/#%e6%a8%a1%e5%9e%8b%e5%b8%b8%e9%a7%90keep_alive" data-link-title="1.0 Ollama：主流推論伺服器" data-link-desc="一行 brew 裝完、ollama run 一鍵跑 Gemma 4 MTP、OpenAI 相容 API on localhost:11434">keep_alive</a> 太短）；檢查 prompt 字數是否暴增（10K+ tokens 進入 <a href="/blog/llm/knowledge-cards/prefill/" data-link-title="Prefill" data-link-desc="Prompt 首次處理時的計算階段：把整段輸入跑過模型、產生 KV cache">prefill</a> 痛點區）。</li>
<li><strong>Ollama 自己 crash</strong>：<a href="/blog/llm/knowledge-cards/launchd-service/" data-link-title="launchd Service" data-link-desc="macOS 原生的服務管理機制、把 process 註冊成自動啟動的 daemon 或 agent">launchd service</a> 模式看 <code>/opt/homebrew/var/log/ollama.log</code>、前景模式看啟動 terminal 的 stderr。</li>
</ul>
<p>這張表的核心訊號：</p>
<ul>
<li>「沒回應」「connection 系」→ 通常 server 層。</li>
<li>「內容怪」「答非所問」「重複」→ 通常 model 層。</li>
<li>「設定怪」「快捷鍵不對」→ 通常介面層。</li>
<li>「整機卡」→ 系統資源、不一定哪層的「bug」、可能是規格不夠。</li>
</ul>
<p>把這個 mapping 內化、看症狀立刻有第一手猜測、不用每次從零思考。</p>
<h2 id="log-在三層的角色差異">Log 在三層的角色差異</h2>
<p>每一層的 log 看的東西不同、用法不同：</p>
<h3 id="介面層-log">介面層 log</h3>
<ul>
<li><strong>位置</strong>：IDE plugin 的 console（VS Code Developer Tools、JetBrains 的 plugin log）。</li>
<li><strong>看什麼</strong>：請求是否發出、發到哪個 endpoint、回應 status code、parse error。</li>
<li><strong>常見訊號</strong>：請求根本沒發 → 介面層配置錯；請求發了但伺服器拒 → 伺服器層；請求成功但 parse 失敗 → 介面層或伺服器層回應格式不對。</li>
</ul>
<h3 id="伺服器層-log">伺服器層 log</h3>
<ul>
<li><strong>位置</strong>：Ollama 在 <code>~/.ollama/logs/server.log</code> 或類似位置、LM Studio 在 console 輸出、llama.cpp 在啟動 terminal。</li>
<li><strong>看什麼</strong>：模型載入過程、推論進度、error trace、記憶體狀態。</li>
<li><strong>常見訊號</strong>：載入 model 卡住 / 失敗 → model file 損壞或記憶體不足；推論時 OOM → 量化太激進或 context 太長；連線錯誤 → port 配置或 host binding。</li>
</ul>
<h3 id="模型層的觀察訊號">模型層的觀察訊號</h3>
<p>模型層通常沒有獨立的 log——權重檔本身不會 log、行為要透過伺服器層觀察。判讀模型問題的訊號通常是：</p>
<ul>
<li>「載入成功、推論時崩」→ 量化等級或記憶體配對問題。</li>
<li>「載入成功、推論結果差」→ 模型能力或量化品質問題。</li>
<li>「不同 prompt 表現不一致」→ 可能是 model 對特定 pattern 弱、不是 bug。</li>
</ul>
<p>模型層問題多半不是「壞了」、是「能力上限」——換更大模型或調量化是主要解法、不是「修 bug」。</p>
<h3 id="log-level-預設夠用針對性提升">log level 預設夠用、針對性提升</h3>
<p>實務上 default log level 提供的訊息已涵蓋多數排錯需要；全部開 verbose 反而把 noise 蓋過 signal、要找的關鍵錯誤被淹沒。有問題時針對該層提升 log level（其他層保持 default）、定位完再降回來。</p>
<h2 id="最小可重現的縮減策略">最小可重現的縮減策略</h2>
<p>症狀複雜時、把問題縮到最小、再逐步加回來。這個方法在所有軟體 debug 都通用、套用到 LLM 場景的具體流程：</p>
<ol>
<li>
<p><strong>直接 curl 伺服器、用最簡 prompt 復現</strong>：</p>
<ul>
<li>繞過介面層、確認伺服器本身行為。</li>
<li>prompt 用 <code>&quot;Hello&quot;</code> 這種最短的、排除 prompt 複雜度因素。</li>
<li>如果這步就崩 → 伺服器 / 模型層問題、可以排除介面層。</li>
</ul>
</li>
<li>
<p><strong>換不同 model 試</strong>：</p>
<ul>
<li>同樣 prompt、換 <code>gemma4:e4b</code> 或 <code>llama3.2:1b</code>。</li>
<li>不同 model 都正常 → 原 model 問題。</li>
<li>不同 model 也崩 → 伺服器層問題。</li>
</ul>
</li>
<li>
<p><strong>換不同伺服器試</strong>：</p>
<ul>
<li>Ollama 接不上、用 LM Studio 同模型試。</li>
<li>兩個都崩 → 模型或系統層問題。</li>
<li>一個好一個壞 → 該伺服器特有問題。</li>
</ul>
</li>
<li>
<p><strong>改變一個變數一次</strong>：</p>
<ul>
<li>每次只改一個變數（設定 / model / IDE 重啟三選一）、確保行為變化能對應到具體動作。</li>
<li>每次只改一項、觀察行為變化。</li>
</ul>
</li>
<li>
<p><strong>記錄每一步</strong>：</p>
<ul>
<li>排錯 30 分鐘還沒解時、開始會忘記試過什麼。</li>
<li>簡單 notebook 記錄「改了什麼、行為怎麼變」、避免轉圈。</li>
</ul>
</li>
</ol>
<p>這個方法看起來慢、實際上比「亂試一通」快很多。亂試的代價是「以為改了 A 沒效、其實改 A 跟改 B 互相抵銷、不知道」。最小可重現是 disciplined approach、值得花時間建立習慣。</p>
<h2 id="跨層級的常見誤判">跨層級的常見誤判</h2>
<p>排錯時常踩的陷阱是「把某層的問題誤判成另一層」、修錯方向白費力氣。常見誤判模式：</p>
<h3 id="把伺服器問題誤當模型問題">把伺服器問題誤當模型問題</h3>
<p>例：Ollama 因為 port 被佔啟動失敗、IDE 看到 connection refused、誤以為「model 載不起來、需要換 model」。實際上換 model 也救不了、要看 server log 才知道是 port 問題。</p>
<p>判讀：connection 系問題 → server 層、不是 model 層。</p>
<h3 id="把模型問題誤當伺服器問題">把模型問題誤當伺服器問題</h3>
<p>例：用 Q3 量化跑 7B 模型、輸出全是亂碼、誤以為「Ollama bug」、開 issue 報。實際上是量化太激進、模型本身輸出崩、換 Q4 就好。</p>
<p>判讀：「server 看起來正常、輸出怪」→ 通常 model 層、改量化或換 model。</p>
<h3 id="把介面問題誤當伺服器問題">把介面問題誤當伺服器問題</h3>
<p>例：Continue.dev 的 <code>config.json</code> 寫錯 <code>apiBase</code>、IDE 顯示 connection error、誤以為「Ollama 掛了」。實際上 Ollama 正常、curl 過得去、IDE 配置錯。</p>
<p>判讀：curl 過得去、IDE 過不去 → 介面層配置問題。</p>
<h3 id="把系統資源問題誤當軟體-bug">把系統資源問題誤當軟體 bug</h3>
<p>例：32GB Mac 跑 31B + 同時開大量 app、Mac 整體變慢、誤以為「Ollama 越來越慢」。實際上是記憶體 swap、Ollama 沒問題。</p>
<p>判讀：Activity Monitor 看 Memory Pressure 變紅 / swap 大量、是系統資源、不是軟體 bug。</p>
<h3 id="把-prompt-問題誤當模型問題">把 prompt 問題誤當模型問題</h3>
<p>例：給 model 超長 <a href="/blog/llm/knowledge-cards/context-window/" data-link-title="Context Window" data-link-desc="模型一次能處理的最大 token 數量：prompt 加生成的總和上限">context</a>（30K token）、<a href="/blog/llm/knowledge-cards/ttft/" data-link-title="TTFT" data-link-desc="Time To First Token：送出 prompt 到第一個 token 出現的等待時間">TTFT</a> 30 秒、誤以為「model 變慢了」。實際上是 <a href="/blog/llm/knowledge-cards/prefill/" data-link-title="Prefill" data-link-desc="Prompt 首次處理時的計算階段：把整段輸入跑過模型、產生 KV cache">prefill</a> 階段需要時間、跟 model 沒變慢無關。</p>
<p>判讀：短 prompt 正常、長 prompt 慢 → prefill 問題、可預期、不是 bug。</p>
<p>每種誤判的根因都是「症狀對應到錯的層級」。內化「症狀 → 層級」對應反射、能避開多數誤判。</p>
<h2 id="排錯工具箱">排錯工具箱</h2>
<p>四個基本工具能 cover 90% 的排錯場景：</p>
<h3 id="curl">curl</h3>
<ul>
<li><strong>角色</strong>：直接打伺服器 API、繞過介面層。</li>
<li><strong>用法</strong>：<code>curl http://localhost:11434/api/version</code> 看伺服器是否回應、<code>curl http://localhost:11434/v1/chat/completions</code> 帶最簡 prompt 試完整流程（11434 是 Ollama 預設 <a href="/blog/llm/knowledge-cards/port-and-localhost/" data-link-title="Port 與 Localhost" data-link-desc="TCP port 與 listen address 如何決定 API server 的對外暴露範圍">port</a>、見 <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">1.0 Ollama</a>）。</li>
<li><strong>價值</strong>：排除介面層、確認伺服器層行為。</li>
</ul>
<h3 id="ollama-ps--等價指令"><code>ollama ps</code> / 等價指令</h3>
<ul>
<li><strong>角色</strong>：看伺服器層當前 model 狀態。</li>
<li><strong>用法</strong>：<code>ollama ps</code> 列出載入記憶體的 model、看 size、idle timer。</li>
<li><strong>價值</strong>：確認「我以為載入了」跟「真的載入了」是否一致；看記憶體佔用是否合理。</li>
</ul>
<h3 id="activity-monitor--system-monitor">Activity Monitor / system monitor</h3>
<ul>
<li><strong>角色</strong>：看系統資源狀態。</li>
<li><strong>用法</strong>：Memory Pressure 是否變紅、CPU / GPU 使用率、swap 量、過熱降頻。</li>
<li><strong>價值</strong>：區分「軟體 bug」跟「規格不夠」。多數本地 LLM 慢的問題是規格、不是 bug。</li>
</ul>
<h3 id="ide-開發者工具">IDE 開發者工具</h3>
<ul>
<li><strong>角色</strong>：看介面層請求 / 回應。</li>
<li><strong>用法</strong>：VS Code 的 Help → Toggle Developer Tools、看 Network tab、看 Console。</li>
<li><strong>價值</strong>：確認介面層真的把請求發出去、看 server 回什麼。</li>
</ul>
<p>這四個工具學會用、寫 code 場景 90% 的排錯都能處理。剩 10% 的 deep issue（如 driver 問題、模型權重檔損壞、framework 內部 bug）需要更專業的工具、但這 10% 對寫 code 使用者來說、通常該求助社群或回報 maintainer、不是自己 debug。</p>
<h2 id="排錯流程的決策樹">排錯流程的決策樹</h2>
<p>把上面的內容整合成一個流程：</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="ln"> 1</span><span class="cl">症狀出現
</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">curl 伺服器（伺服器層活著嗎）
</span></span><span class="line"><span class="ln"> 4</span><span class="cl">  ├─ curl 失敗 → 看 server log（伺服器層問題）
</span></span><span class="line"><span class="ln"> 5</span><span class="cl">  │   ├─ port 衝突 → 改 port 或 kill 舊 instance
</span></span><span class="line"><span class="ln"> 6</span><span class="cl">  │   ├─ model 載入失敗 → 看 file / 記憶體
</span></span><span class="line"><span class="ln"> 7</span><span class="cl">  │   └─ crash → bug report、看版本是否最新
</span></span><span class="line"><span class="ln"> 8</span><span class="cl">  └─ curl 成功 → 介面層或 model 層問題
</span></span><span class="line"><span class="ln"> 9</span><span class="cl">      ↓
</span></span><span class="line"><span class="ln">10</span><span class="cl">      換最簡 prompt 試（model 在簡單 prompt 上正常嗎）
</span></span><span class="line"><span class="ln">11</span><span class="cl">      ├─ 簡單 prompt 也崩 → model 層問題
</span></span><span class="line"><span class="ln">12</span><span class="cl">      │   ├─ 換 model 試 → 不同 model 都崩 → 系統或伺服器
</span></span><span class="line"><span class="ln">13</span><span class="cl">      │   └─ 同 model 換量化等級 → 量化太激進
</span></span><span class="line"><span class="ln">14</span><span class="cl">      └─ 簡單 prompt OK、複雜 prompt 崩
</span></span><span class="line"><span class="ln">15</span><span class="cl">          ↓
</span></span><span class="line"><span class="ln">16</span><span class="cl">          看 prompt 長度跟 context 限制
</span></span><span class="line"><span class="ln">17</span><span class="cl">          ├─ context 超出 → 縮短 prompt 或換 long-context model
</span></span><span class="line"><span class="ln">18</span><span class="cl">          └─ context 在範圍內 → model 能力上限、考慮換大 model
</span></span><span class="line"><span class="ln">19</span><span class="cl">              ↓
</span></span><span class="line"><span class="ln">20</span><span class="cl">              （如果伺服器、prompt、model 都檢查過還是壞）
</span></span><span class="line"><span class="ln">21</span><span class="cl">              介面層配置問題
</span></span><span class="line"><span class="ln">22</span><span class="cl">              ├─ 看 IDE plugin developer console
</span></span><span class="line"><span class="ln">23</span><span class="cl">              ├─ 比對 config.json 跟最簡 working example
</span></span><span class="line"><span class="ln">24</span><span class="cl">              └─ reset 設定後重試</span></span></code></pre></div><p>這棵樹不是「按順序跑完」、是「定位後對應到具體分支」。學會用症狀直接 jump 到對應分支、不必每次從根跑起。</p>
<h2 id="何時不適用本章方法論">何時不適用本章方法論</h2>
<p>本章「三層架構定位」假設「單機、單 user、單一伺服器實例、人在駕駛位」的個人開發場景。以下情境的方法論需要擴充：</p>
<table>
  <thead>
      <tr>
          <th>情境</th>
          <th>為什麼三層定位失效 / 需要擴充</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>Multi-tenant 共用伺服器</td>
          <td>多個 user 共用 Ollama instance、症狀可能是「不同 user 的請求互相干擾」、單純三層定位看不出、需加 user / session 層</td>
      </tr>
      <tr>
          <td>容器化部署（Docker / k8s）</td>
          <td>介面 / 伺服器之間多一層網路命名空間、connection refused 可能是 container network 配置、不是伺服器層</td>
      </tr>
      <tr>
          <td>跨機器分散式 inference</td>
          <td>伺服器層拆成多 process / 多 node、單一 <code>ollama ps</code> 看不到全貌、需 cluster-level observability</td>
      </tr>
      <tr>
          <td>後端 production 服務</td>
          <td>排錯依賴 SLI / SLO + 監控告警支撐、而非「重啟試試」的探索式做法；本章方法論偏個人開發、production 場景需另尋資料中心 SRE 教材</td>
      </tr>
      <tr>
          <td>Agent loop 內部失敗</td>
          <td>失敗可能在 LLM 規劃 / tool execution / state machine 任一處、超出三層定位、見 <a href="/blog/llm/04-applications/agent-architecture/" data-link-title="4.4 Agent 架構原理" data-link-desc="Agent loop 結構、失敗模式、什麼任務適合 vs 不適合、跟人類審查的協作模型">4.4 Agent 架構</a></td>
      </tr>
  </tbody>
</table>
<p>本章方法論的甜蜜點是「個人 Mac、一個 IDE、一個 Ollama instance」的場景。離開這個甜蜜點、要把「三層」擴充成更多層（user / network / cluster）、或改用 production-grade 觀察工具。</p>
<h2 id="何時過時--何時不過時">何時過時 / 何時不過時</h2>
<p><strong>不會過時的部分</strong>：</p>
<ul>
<li>三層架構視角排錯（介面 / 伺服器 / 模型）。</li>
<li>「先定位、再修補」的反射。</li>
<li>最小可重現的縮減策略。</li>
<li>五類跨層級誤判模式的識別。</li>
<li>四個基本工具的概念（curl / process status / system monitor / dev tools）。</li>
</ul>
<p><strong>會變的部分</strong>：</p>
<ul>
<li>具體錯誤訊息文字（隨 Ollama / LM Studio / Continue.dev 版本變）。</li>
<li>log 檔位置（隨工具更新可能調整）。</li>
<li>特定指令名稱（如 <code>ollama ps</code> 將來可能改名）。</li>
<li>特定工具的開發者面板路徑。</li>
</ul>
<p>換工具或工具升級之後、本章的方法仍適用、只需要重新對應到「新工具的對應指令在哪」。看到新錯誤訊息時、回到三層架構定位、用最小可重現縮減——這比 google 錯誤訊息字面快得多、也比「重啟一次再試」可靠得多。</p>
<h2 id="下一章">下一章</h2>
<p>下一章：<a href="/blog/llm/02-math-foundations/" data-link-title="模組二：LLM 的數學基礎" data-link-desc="整理 LLM 推論背後需要理解的線性代數、機率與資訊論、最佳化、數值精度等數學概念">模組二 LLM 的數學基礎</a>、或回到 <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 整合、模型選型與期望管理">模組一首頁</a> 看其他章節。</p>
]]></content:encoded></item><item><title>1.0 Ollama：主流推論伺服器</title><link>https://tarrragon.github.io/blog/llm/01-local-llm-services/ollama/</link><pubDate>Mon, 11 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/llm/01-local-llm-services/ollama/</guid><description>&lt;p>Ollama 是本地 LLM 生態的&lt;strong>主流推論伺服器&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;/a> backend）、API 暴露（預設 &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> 上的 &lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/openai-compatible-api/" data-link-title="OpenAI 相容 API" data-link-desc="本地推論伺服器跟雲端 OpenAI 共用的 API 形狀標準">OpenAI 相容 API&lt;/a> 與原生 API）。它的設計取捨偏向「拿來就跑」、把 &lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/gguf/" data-link-title="GGUF" data-link-desc="llama.cpp 生態定義的模型權重格式：把權重、tokenizer、metadata 打包成單一檔案">GGUF 格式&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> 等底層細節都包進 CLI、使用者面對的只有 &lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/model-tag/" data-link-title="Model Tag" data-link-desc="Ollama 等推論伺服器用來定位特定模型版本的命名規則">model tag&lt;/a> 跟幾個指令。&lt;/p>
&lt;p>對「在 VS Code 接本地 LLM 寫 code」這條最短路徑、Ollama 多半是唯一需要的伺服器層。本章先給 5 分鐘可跑通的最短路徑、再展開日常使用所需的模型管理跟 API 細節、最後才進階主題（背景常駐、MTP 加速、安全暴露、版本升級）。已經把 Ollama 跑起來的讀者可以直接跳到&lt;a href="#%e6%97%a5%e5%b8%b8%e4%bd%bf%e7%94%a8%e6%a8%a1%e5%9e%8b%e7%ae%a1%e7%90%86%e8%88%87-api-%e5%bd%a2%e7%8b%80">日常使用&lt;/a>或&lt;a href="#%e6%8e%92%e9%8c%af%e5%bf%ab%e9%80%9f%e5%88%a4%e8%ae%80">排錯&lt;/a>。&lt;/p>
&lt;h2 id="本章目標">本章目標&lt;/h2>
&lt;p>讀完本章後、你應該能：&lt;/p>
&lt;ol>
&lt;li>裝好 Ollama 並驗證它正在跑。&lt;/li>
&lt;li>用 CLI 拉一個模型並開始對話。&lt;/li>
&lt;li>用 curl 驗證 OpenAI 相容 API 在 11434 正常回應。&lt;/li>
&lt;li>看懂 model tag 命名規則、選對 Gemma 4 MTP 版本。&lt;/li>
&lt;li>排查 port 撞、記憶體不足、模型載入慢、cache 過大等情境。&lt;/li>
&lt;/ol>
&lt;h2 id="最短路徑5-分鐘把-ollama-跑起來">最短路徑：5 分鐘把 Ollama 跑起來&lt;/h2>
&lt;p>最短路徑的設計目標是「裝、跑、驗證三步、其他細節留到日常使用段」。三個指令用到的 macOS 工具分別是 &lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/homebrew/" data-link-title="Homebrew" data-link-desc="macOS 上社群維護的套件管理器、用一行指令安裝 CLI 工具與背景服務">Homebrew 套件管理器&lt;/a>（&lt;code>brew install&lt;/code>）跟 &lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/shell-background-process/" data-link-title="Shell 背景 Process" data-link-desc="終端機 process 的前景 / 背景生命週期、訊號控制、找出佔用 port 的 process">shell 前景 process&lt;/a>（&lt;code>ollama serve&lt;/code> 預設前景跑、&lt;code>Ctrl+C&lt;/code> 結束）。&lt;/p>





&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-bash" data-lang="bash">&lt;span class="line">&lt;span class="ln">1&lt;/span>&lt;span class="cl">&lt;span class="c1"># 1. 安裝&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">2&lt;/span>&lt;span class="cl">brew install ollama
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">3&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">4&lt;/span>&lt;span class="cl">&lt;span class="c1"># 2. 啟動 server（前景跑、Ctrl+C 結束）&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">5&lt;/span>&lt;span class="cl">ollama serve
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">6&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">7&lt;/span>&lt;span class="cl">&lt;span class="c1"># 3. 在另一個 terminal 拉一個小模型驗證&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">8&lt;/span>&lt;span class="cl">ollama run gemma3:1b&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>第三步首次執行會下載權重（約 815 MB、頻寬足夠的話 1 ~ 3 分鐘）、下載完自動進入 REPL：&lt;/p>





&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-text" data-lang="text">&lt;span class="line">&lt;span class="ln">1&lt;/span>&lt;span class="cl">&amp;gt;&amp;gt;&amp;gt; 寫一個 Python function 計算 fibonacci
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">2&lt;/span>&lt;span class="cl">def fibonacci(n):
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">3&lt;/span>&lt;span class="cl"> if n &amp;lt;= 1:
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">4&lt;/span>&lt;span class="cl"> return n
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">5&lt;/span>&lt;span class="cl"> return fibonacci(n - 1) + fibonacci(n - 2)
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">6&lt;/span>&lt;span class="cl">&amp;gt;&amp;gt;&amp;gt; /bye&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>驗證 server 正常聽 11434：&lt;/p>





&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-bash" data-lang="bash">&lt;span class="line">&lt;span class="ln">1&lt;/span>&lt;span class="cl">curl http://localhost:11434/api/version
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">2&lt;/span>&lt;span class="cl">&lt;span class="c1"># 回 {&amp;#34;version&amp;#34;:&amp;#34;0.23.x&amp;#34;}&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>驗證 OpenAI 相容 API 可以做 chat completion：&lt;/p></description><content:encoded><![CDATA[<p>Ollama 是本地 LLM 生態的<strong>主流推論伺服器</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</a> backend）、API 暴露（預設 <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> 上的 <a href="/blog/llm/knowledge-cards/openai-compatible-api/" data-link-title="OpenAI 相容 API" data-link-desc="本地推論伺服器跟雲端 OpenAI 共用的 API 形狀標準">OpenAI 相容 API</a> 與原生 API）。它的設計取捨偏向「拿來就跑」、把 <a href="/blog/llm/knowledge-cards/gguf/" data-link-title="GGUF" data-link-desc="llama.cpp 生態定義的模型權重格式：把權重、tokenizer、metadata 打包成單一檔案">GGUF 格式</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> 等底層細節都包進 CLI、使用者面對的只有 <a href="/blog/llm/knowledge-cards/model-tag/" data-link-title="Model Tag" data-link-desc="Ollama 等推論伺服器用來定位特定模型版本的命名規則">model tag</a> 跟幾個指令。</p>
<p>對「在 VS Code 接本地 LLM 寫 code」這條最短路徑、Ollama 多半是唯一需要的伺服器層。本章先給 5 分鐘可跑通的最短路徑、再展開日常使用所需的模型管理跟 API 細節、最後才進階主題（背景常駐、MTP 加速、安全暴露、版本升級）。已經把 Ollama 跑起來的讀者可以直接跳到<a href="#%e6%97%a5%e5%b8%b8%e4%bd%bf%e7%94%a8%e6%a8%a1%e5%9e%8b%e7%ae%a1%e7%90%86%e8%88%87-api-%e5%bd%a2%e7%8b%80">日常使用</a>或<a href="#%e6%8e%92%e9%8c%af%e5%bf%ab%e9%80%9f%e5%88%a4%e8%ae%80">排錯</a>。</p>
<h2 id="本章目標">本章目標</h2>
<p>讀完本章後、你應該能：</p>
<ol>
<li>裝好 Ollama 並驗證它正在跑。</li>
<li>用 CLI 拉一個模型並開始對話。</li>
<li>用 curl 驗證 OpenAI 相容 API 在 11434 正常回應。</li>
<li>看懂 model tag 命名規則、選對 Gemma 4 MTP 版本。</li>
<li>排查 port 撞、記憶體不足、模型載入慢、cache 過大等情境。</li>
</ol>
<h2 id="最短路徑5-分鐘把-ollama-跑起來">最短路徑：5 分鐘把 Ollama 跑起來</h2>
<p>最短路徑的設計目標是「裝、跑、驗證三步、其他細節留到日常使用段」。三個指令用到的 macOS 工具分別是 <a href="/blog/llm/knowledge-cards/homebrew/" data-link-title="Homebrew" data-link-desc="macOS 上社群維護的套件管理器、用一行指令安裝 CLI 工具與背景服務">Homebrew 套件管理器</a>（<code>brew install</code>）跟 <a href="/blog/llm/knowledge-cards/shell-background-process/" data-link-title="Shell 背景 Process" data-link-desc="終端機 process 的前景 / 背景生命週期、訊號控制、找出佔用 port 的 process">shell 前景 process</a>（<code>ollama serve</code> 預設前景跑、<code>Ctrl+C</code> 結束）。</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="ln">1</span><span class="cl"><span class="c1"># 1. 安裝</span>
</span></span><span class="line"><span class="ln">2</span><span class="cl">brew install ollama
</span></span><span class="line"><span class="ln">3</span><span class="cl">
</span></span><span class="line"><span class="ln">4</span><span class="cl"><span class="c1"># 2. 啟動 server（前景跑、Ctrl+C 結束）</span>
</span></span><span class="line"><span class="ln">5</span><span class="cl">ollama serve
</span></span><span class="line"><span class="ln">6</span><span class="cl">
</span></span><span class="line"><span class="ln">7</span><span class="cl"><span class="c1"># 3. 在另一個 terminal 拉一個小模型驗證</span>
</span></span><span class="line"><span class="ln">8</span><span class="cl">ollama run gemma3:1b</span></span></code></pre></div><p>第三步首次執行會下載權重（約 815 MB、頻寬足夠的話 1 ~ 3 分鐘）、下載完自動進入 REPL：</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">&gt;&gt;&gt; 寫一個 Python function 計算 fibonacci
</span></span><span class="line"><span class="ln">2</span><span class="cl">def fibonacci(n):
</span></span><span class="line"><span class="ln">3</span><span class="cl">    if n &lt;= 1:
</span></span><span class="line"><span class="ln">4</span><span class="cl">        return n
</span></span><span class="line"><span class="ln">5</span><span class="cl">    return fibonacci(n - 1) + fibonacci(n - 2)
</span></span><span class="line"><span class="ln">6</span><span class="cl">&gt;&gt;&gt; /bye</span></span></code></pre></div><p>驗證 server 正常聽 11434：</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="ln">1</span><span class="cl">curl http://localhost:11434/api/version
</span></span><span class="line"><span class="ln">2</span><span class="cl"><span class="c1"># 回 {&#34;version&#34;:&#34;0.23.x&#34;}</span></span></span></code></pre></div><p>驗證 OpenAI 相容 API 可以做 chat completion：</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;gemma3:1b&#34;,
</span></span></span><span class="line"><span class="ln">5</span><span class="cl"><span class="s1">    &#34;messages&#34;: [{&#34;role&#34;: &#34;user&#34;, &#34;content&#34;: &#34;Hello&#34;}],
</span></span></span><span class="line"><span class="ln">6</span><span class="cl"><span class="s1">    &#34;stream&#34;: false
</span></span></span><span class="line"><span class="ln">7</span><span class="cl"><span class="s1">  }&#39;</span></span></span></code></pre></div><p>回應 JSON 包含 <code>choices[0].message.content</code>、最短路徑就完成。實際寫 code 用的模型大小通常是 14B / 31B 級、選型詳見 <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>；完整安裝紀錄含 <a href="/blog/llm/knowledge-cards/launchd-service/" data-link-title="launchd Service" data-link-desc="macOS 原生的服務管理機制、把 process 註冊成自動啟動的 daemon 或 agent">launchd service</a> 設定見 <a href="/blog/llm/01-local-llm-services/hands-on/ollama-setup/" data-link-title="Hands-on：安裝 Ollama &#43; 拉第一個 Gemma 模型" data-link-desc="brew install ollama、launchd service、ollama pull、curl 驗證 OpenAI 相容 API">Hands-on：Ollama 安裝</a>。</p>
<h2 id="日常使用模型管理與-api-形狀">日常使用：模型管理與 API 形狀</h2>
<h3 id="模型管理指令">模型管理指令</h3>
<p>Ollama 用四個指令覆蓋日常模型管理。每個指令承擔一個語意責任：</p>
<table>
  <thead>
      <tr>
          <th>指令</th>
          <th>責任</th>
          <th>何時使用</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td><code>ollama pull &lt;tag&gt;</code></td>
          <td>只下載權重、不啟動對話</td>
          <td>CI / 自動化、先下載再離線使用</td>
      </tr>
      <tr>
          <td><code>ollama run &lt;tag&gt;</code></td>
          <td>下載（若還沒）+ 啟動對話 REPL</td>
          <td>互動驗證、快速試模型</td>
      </tr>
      <tr>
          <td><code>ollama list</code></td>
          <td>列出已下載模型與大小</td>
          <td>檢查磁碟用量、確認模型存在</td>
      </tr>
      <tr>
          <td><code>ollama rm &lt;tag&gt;</code></td>
          <td>刪除模型權重與 registry metadata</td>
          <td>釋出 SSD 空間</td>
      </tr>
  </tbody>
</table>
<p>模型權重存在 <code>~/.ollama/models/</code>、單一大模型（30B+）可能佔 18 ~ 30 GB、累積超過 100 GB 很常見。清理路徑統一用 <code>ollama rm</code>、Ollama 會同步更新 registry metadata、後續 <code>ollama list</code> 與 <code>ollama pull</code> 才能正確判斷既存模型狀態。</p>
<h3 id="model-tag-命名規則">Model tag 命名規則</h3>
<p><a href="/blog/llm/knowledge-cards/model-tag/" data-link-title="Model Tag" data-link-desc="Ollama 等推論伺服器用來定位特定模型版本的命名規則">Model tag</a> 是 Ollama 的模型定位符、形式為 <code>family:size-variant-quantization</code>。同一個 model family 可能有十幾個 tag、對應不同參數量、訓練變體跟量化等級。</p>
<table>
  <thead>
      <tr>
          <th>範例</th>
          <th>拆解</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td><code>gemma4:e4b</code></td>
          <td>Gemma 4、E4B（edge dense）、預設量化</td>
      </tr>
      <tr>
          <td><code>gemma4:31b-instruct-q5_K_M</code></td>
          <td>Gemma 4、31B、instruct-tuned、Q5_K_M 量化</td>
      </tr>
      <tr>
          <td><code>gemma4:31b-coding-mtp-bf16</code></td>
          <td>Gemma 4、31B、coding 特化、含 MTP drafter、bf16</td>
      </tr>
      <tr>
          <td><code>qwen3-coder:30b</code></td>
          <td>Qwen3-Coder、30B 參數、預設量化</td>
      </tr>
      <tr>
          <td><code>llama3.3:70b-instruct-q4_K_M</code></td>
          <td>Llama 3.3、70B、instruct、Q4_K_M</td>
      </tr>
  </tbody>
</table>
<p>選 tag 時的兩個判讀重點：variant（<code>instruct</code> / <code>coding</code> 等用途特化、影響回應風格）、quantization（量化等級、影響記憶體佔用與品質、見 <a href="/blog/llm/01-local-llm-services/llama-cpp/#gguf-%e6%a0%bc%e5%bc%8f%e8%88%87%e9%87%8f%e5%8c%96%e6%a8%99%e7%b1%a4" data-link-title="1.2 llama.cpp：底層推論引擎" data-link-desc="GGUF 格式、量化、MTP 仍 beta；多數讀者不需要直接接觸，Ollama 已經包好">1.2 llama.cpp 的量化標籤對照</a>）。完整 tag 清單在 <a href="https://ollama.com/library">ollama.com/library</a>。寫 code 場景的推薦選擇詳見 <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>
<h3 id="兩套-api選哪一套">兩套 API：選哪一套</h3>
<p>Ollama 在 11434 同時提供兩套 API、用途互補：</p>
<table>
  <thead>
      <tr>
          <th>路徑前綴</th>
          <th>目的</th>
          <th>適合誰</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td><code>/v1/…</code></td>
          <td>OpenAI 相容、用 <code>messages</code> 結構</td>
          <td>IDE plugin（Continue.dev 等）、CLI 工具、想無痛切換 cloud / local</td>
      </tr>
      <tr>
          <td><code>/api/…</code></td>
          <td>Ollama 原生、支援模型管理</td>
          <td>想動態切換模型、寫 model 管理腳本</td>
      </tr>
  </tbody>
</table>
<p>寫 code 場景多半用 <code>/v1/…</code>、因為 IDE plugin 預設講這套形狀。詳細協定背景見 <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>。</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;gemma3:1b&#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 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>Streaming 回應是一連串 <code>data: {...}</code> 行、每行一個 token chunk。Ollama 原生 <code>/api/generate</code> 還支援 <code>num_predict</code>、<code>temperature</code>、<code>stop</code> 等細項、IDE plugin 內部會自行轉換、終端使用者通常用不到。</p>
<h2 id="進階主題按需閱讀">進階主題（按需閱讀）</h2>
<p>進階段的特色是「沒有它最短路徑仍能跑、但搞懂後體驗大幅提升」。最短路徑只想跑通的讀者可以先跳到<a href="#%e6%8e%92%e9%8c%af%e5%bf%ab%e9%80%9f%e5%88%a4%e8%ae%80">排錯</a>、需要時再回來。</p>
<h3 id="背景常駐launchd-service">背景常駐：launchd service</h3>
<p><code>ollama serve</code> 預設<a href="/blog/llm/knowledge-cards/shell-background-process/" data-link-title="Shell 背景 Process" data-link-desc="終端機 process 的前景 / 背景生命週期、訊號控制、找出佔用 port 的 process">在前景跑</a>、terminal 關掉就停。日常使用建議讓 Ollama 開機自動啟動、用 macOS 的 <a href="/blog/llm/knowledge-cards/launchd-service/" data-link-title="launchd Service" data-link-desc="macOS 原生的服務管理機制、把 process 註冊成自動啟動的 daemon 或 agent">launchd service</a> 機制：</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="ln">1</span><span class="cl">brew services start ollama</span></span></code></pre></div><p>這個指令做兩件事、決定 Ollama 之後的行為：</p>
<ol>
<li>寫一個 launchd plist 到 <code>~/Library/LaunchAgents/homebrew.mxcl.ollama.plist</code></li>
<li>立刻啟動 ollama serve、之後重開機自動拉起</li>
</ol>
<p>launchd 是 macOS 原生的服務管理機制、把 process 註冊成 daemon / agent、由系統負責生命週期。<code>brew services</code> 是 <a href="/blog/llm/knowledge-cards/homebrew/" data-link-title="Homebrew" data-link-desc="macOS 上社群維護的套件管理器、用一行指令安裝 CLI 工具與背景服務">Homebrew</a> 對 launchd 的封裝、把 plist 模板跟啟動指令簡化成一行。Log 統一寫到 <code>/opt/homebrew/var/log/ollama.log</code>（Apple Silicon Mac）、出問題第一步先看這個檔。</p>
<p>對應的服務管理指令：</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="ln">1</span><span class="cl">brew services stop ollama      <span class="c1"># 停掉、保留 plist</span>
</span></span><span class="line"><span class="ln">2</span><span class="cl">brew services restart ollama   <span class="c1"># 升級後重啟</span></span></span></code></pre></div><p>完整 plist 內容與 log 範例見 <a href="/blog/llm/01-local-llm-services/hands-on/ollama-setup/" data-link-title="Hands-on：安裝 Ollama &#43; 拉第一個 Gemma 模型" data-link-desc="brew install ollama、launchd service、ollama pull、curl 驗證 OpenAI 相容 API">Hands-on：Ollama 安裝</a>。</p>
<h3 id="gemma-4-mtp-一鍵加速">Gemma 4 MTP 一鍵加速</h3>
<p><a href="/blog/llm/knowledge-cards/mtp/" data-link-title="Multi-Token Prediction (MTP)" data-link-desc="Google 為 Gemma 系列釋出的 speculative decoding 工程化實作">Multi-Token Prediction（MTP）</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/drafter-model/" data-link-title="Drafter Model" data-link-desc="speculative decoding 中用來快速猜未來 token 的小模型">drafter</a> 預測多個 token、再由 target model 驗證、coding 任務有 2 ~ 3 倍加速。Ollama v0.23.1（2026/5/7 釋出）內建 Gemma 4 的 MTP 一鍵支援、啟用方式只需要 pull 對應 model tag：</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>這個 tag 內含 target model（31B）跟 drafter（Google 釋出的官方小模型）、Ollama 自動把兩個 model 載入記憶體、推論時並行驗證。記憶體佔用約 18 GB（drafter 約 1 GB、其餘為 target）、適合 32GB+ Mac。詳細原理見 <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>
<p>判讀 MTP tag 時的三個重點：</p>
<ol>
<li><strong>Tag 裡的 <code>bf16</code> 描述的是 drafter 精度</strong>。Target model 內部已套用量化、實際佔用約 18 GB、跟「整個 31B 用 bf16 跑、要 60+ GB」是兩件事。</li>
<li><strong>加速幅度跟任務 pattern 預測度成正比</strong>。Coding（pattern 強）2 ~ 3 倍、純創意寫作或隨機字串生成大約 1.5 倍。</li>
<li><strong>品質由 target model 保證</strong>。Drafter 猜錯時 target 會拒絕該預測、最終輸出跟「直接由 target 生成」一致、drafter 只影響速度。</li>
</ol>
<h3 id="模型常駐keep_alive">模型常駐：keep_alive</h3>
<p><code>ollama run</code> 第一次跑某個 model 時、需要 30 ~ 60 秒把權重從 SSD 載入記憶體；後續對話則用 cached 權重、快得多。Ollama 預設把載入的 model 留在記憶體 5 分鐘（<code>keep_alive</code> 預設值）、長時間不用會被 unload 釋放記憶體。</p>
<p>長時間穩定使用的場景可以延長 keep_alive：</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="ln">1</span><span class="cl"><span class="nv">OLLAMA_KEEP_ALIVE</span><span class="o">=</span>-1 ollama serve     <span class="c1"># 永久保留</span>
</span></span><span class="line"><span class="ln">2</span><span class="cl"><span class="nv">OLLAMA_KEEP_ALIVE</span><span class="o">=</span>2h ollama serve     <span class="c1"># 保留 2 小時</span></span></span></code></pre></div><p><code>-1</code> 設定會持續佔用記憶體、適合「整天頻繁用」的工作流；偶爾用一次的場景保持預設、讓系統自動釋放更省記憶體。</p>
<h3 id="對外暴露與信任邊界">對外暴露與信任邊界</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>、外部裝置連不上。讓 LAN 內其他機器（例如桌機跑 server、筆電當 client）能用、把 listen address 改成 <code>0.0.0.0</code>：</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="ln">1</span><span class="cl"><span class="nv">OLLAMA_HOST</span><span class="o">=</span>0.0.0.0:11434 ollama serve</span></span></code></pre></div><p>這個設定把 Ollama 暴露在整個區網、任何同網路裝置都能呼叫 API。信任邊界的三種典型情境：</p>
<ul>
<li><strong>家用 / 信任的辦公網路</strong>：風險低、可以直接開</li>
<li><strong>公共 Wi-Fi、共用網路</strong>：透過 SSH tunnel 把 11434 隧道到遠端、或加防火牆規則限制 source IP</li>
<li><strong>暴露到 Internet</strong>：需要 reverse proxy 加 auth、Ollama 本身沒有內建身分認證</li>
</ul>
<p>完整資料流判讀見 <a href="/blog/llm/00-foundations/privacy-data-flow/" data-link-title="0.7 隱私 / 資安的資料流原理" data-link-desc="從「位置」到「資料流」的思考升級：信任邊界、合約模型、零信任原則套用到 LLM 工作流">0.7 隱私 / 資安資料流</a>、綁定模式（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="版本管理">版本管理</h3>
<p>Ollama 釋出節奏快、每兩三週可能加新功能或修嚴重 bug。升級流程：</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="ln">1</span><span class="cl">brew upgrade ollama
</span></span><span class="line"><span class="ln">2</span><span class="cl">brew services restart ollama   <span class="c1"># 若用 launchd service 跑</span></span></span></code></pre></div><p>升級前先看 <a href="https://github.com/ollama/ollama/releases">release notes</a>、確認三件事：</p>
<ol>
<li>是否引入 breaking API change（IDE plugin 可能要對應更新）</li>
<li>是否棄用舊 model tag（拉新 tag 取代）</li>
<li>是否帶來想要的新功能（例如新模型支援、加速優化）</li>
</ol>
<h2 id="排錯快速判讀">排錯快速判讀</h2>
<p>排錯段的設計是「先給操作原則、再列觸發條件」、讓讀者快速定位現象屬於哪一類。</p>
<h3 id="port-11434-已被佔用">Port 11434 已被佔用</h3>
<p>操作原則：先檢查是不是舊 Ollama 還在跑、再決定 kill 或換 port。<a href="/blog/llm/knowledge-cards/shell-background-process/" data-link-title="Shell 背景 Process" data-link-desc="終端機 process 的前景 / 背景生命週期、訊號控制、找出佔用 port 的 process"><code>lsof</code> / <code>pkill</code> 的角色</a>是找出佔用方並送終止訊號。</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="ln">1</span><span class="cl">lsof -i :11434          <span class="c1"># 看誰佔 11434</span>
</span></span><span class="line"><span class="ln">2</span><span class="cl">pkill -f <span class="s2">&#34;ollama serve&#34;</span> <span class="c1"># 確認是舊 Ollama 才 kill</span>
</span></span><span class="line"><span class="ln">3</span><span class="cl">ollama serve <span class="p">&amp;</span>          <span class="c1"># 重啟、&amp; 是把 process 丟背景</span></span></span></code></pre></div><p>需要兩個 Ollama 並存的場景、改 port 啟動：</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="ln">1</span><span class="cl"><span class="nv">OLLAMA_HOST</span><span class="o">=</span>127.0.0.1:11435 ollama serve</span></span></code></pre></div><p>IDE plugin 的 <code>apiBase</code> 也要對應改成 11435。</p>
<h3 id="記憶體不足模型崩潰">記憶體不足、模型崩潰</h3>
<p>操作原則：先用 <code>ollama ps</code> 看實際載入了什麼、再對照 <a href="/blog/llm/00-foundations/hardware-memory-budget/" data-link-title="0.5 Apple Silicon 記憶體預算" data-link-desc="記憶體決定能跑什麼，Q4 量化下的可運作模型對照與系統保留">0.5 記憶體預算</a> 決定降級。</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="ln">1</span><span class="cl">ollama ps
</span></span><span class="line"><span class="ln">2</span><span class="cl"><span class="c1"># NAME           ID      SIZE     PROCESSOR    UNTIL</span>
</span></span><span class="line"><span class="ln">3</span><span class="cl"><span class="c1"># gemma4:31b...  abc123  18 GB    100% GPU     5 minutes from now</span></span></span></code></pre></div><p>模型大小超過 Mac 記憶體預算時的可選路徑：</p>
<ul>
<li>換較小 model（例如 31B → 14B）</li>
<li>換較激進量化（例如 Q5_K_M → Q4_K_M）</li>
<li>縮短 context window（在 IDE plugin 端設定）</li>
</ul>
<h3 id="模型載入很慢">模型載入很慢</h3>
<p>操作原則：第一次載入慢屬於正常、後續呼叫如果還是慢、檢查 keep_alive 設定。</p>
<p>第一次載入 18 GB 權重需要 30 ~ 60 秒、屬於 SSD → RAM 的真實 I/O 時間。如果發現「每次第一個請求都慢」、表示 keep_alive 太短、模型每次被 unload 又重新載入。延長 keep_alive 解決：</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="ln">1</span><span class="cl"><span class="nv">OLLAMA_KEEP_ALIVE</span><span class="o">=</span>1h ollama serve</span></span></code></pre></div><p>代價是模型常駐記憶體、其他應用可用記憶體變少。</p>
<h3 id="model-cache-過大佔滿-ssd">Model cache 過大佔滿 SSD</h3>
<p>操作原則：清理用 <code>ollama rm &lt;tag&gt;</code>、Ollama 才會同步更新 registry metadata。</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 list             <span class="c1"># 看哪些 model 佔空間</span>
</span></span><span class="line"><span class="ln">2</span><span class="cl">ollama rm &lt;tag&gt;         <span class="c1"># 刪除單一 model</span></span></span></code></pre></div><p>手動 <code>rm -rf ~/.ollama/models/</code> 會留下 registry metadata 不一致、後續 <code>ollama list</code> 出錯、<code>ollama pull</code> 也可能誤判已存在。需要完全重置的場景、用：</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="ln">1</span><span class="cl">brew services stop ollama
</span></span><span class="line"><span class="ln">2</span><span class="cl">rm -rf ~/.ollama
</span></span><span class="line"><span class="ln">3</span><span class="cl">brew services start ollama</span></span></code></pre></div><p>這會清掉所有 model 跟設定、重新從零開始。</p>
<h2 id="跟其他伺服器並存">跟其他伺服器並存</h2>
<p>Ollama 設計上可以跟 LM Studio、llama.cpp 同時在一台 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、CLI 工作流</td>
      </tr>
      <tr>
          <td>LM Studio</td>
          <td>1234</td>
          <td>GUI 探索新模型、視覺化參數</td>
      </tr>
      <tr>
          <td>llama.cpp</td>
          <td>8080</td>
          <td>底層研究、自訂量化</td>
      </tr>
      <tr>
          <td>oMLX</td>
          <td>8000</td>
          <td>特化 MLX 場景</td>
      </tr>
  </tbody>
</table>
<p>並存的好處是「主力穩定跑 Ollama、實驗模型用 LM Studio」、Continue.dev 等介面層可以同時設多個 model、UI 上下拉切換。並存設定範例見 <a href="/blog/llm/01-local-llm-services/lm-studio/#%e8%88%87-ollama-%e4%b8%a6%e5%ad%98" data-link-title="1.1 LM Studio：GUI 探索模型" data-link-desc="GUI 取向的本地推論伺服器：內建模型瀏覽器、speculative decoding 設定面板、適合探索新模型">1.1 LM Studio</a>。</p>
<h2 id="下一章">下一章</h2>
<p>下一章可選擇：</p>
<ul>
<li>想對比 GUI 派的選擇：<a href="/blog/llm/01-local-llm-services/lm-studio/" data-link-title="1.1 LM Studio：GUI 探索模型" data-link-desc="GUI 取向的本地推論伺服器：內建模型瀏覽器、speculative decoding 設定面板、適合探索新模型">1.1 LM Studio</a></li>
<li>想了解底層 / Ollama 跟 llama.cpp 的關係：<a href="/blog/llm/01-local-llm-services/llama-cpp/" data-link-title="1.2 llama.cpp：底層推論引擎" data-link-desc="GGUF 格式、量化、MTP 仍 beta；多數讀者不需要直接接觸，Ollama 已經包好">1.2 llama.cpp</a></li>
<li>直接進入 VS Code 整合：<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 行內編輯快捷鍵">1.3 VS Code + Continue.dev</a></li>
</ul>
]]></content:encoded></item></channel></rss>