<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: JH5</title>
    <description>The latest articles on DEV Community by JH5 (@jh5_pulse).</description>
    <link>https://dev.to/jh5_pulse</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3550119%2Ff72bed2d-aa8f-4bcc-be09-3f550dd9a7cc.jpg</url>
      <title>DEV Community: JH5</title>
      <link>https://dev.to/jh5_pulse</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/jh5_pulse"/>
    <language>en</language>
    <item>
      <title>實測 NVIDIA Switchyard 疊加 PAIR：雙層混合推論架構</title>
      <dc:creator>JH5</dc:creator>
      <pubDate>Thu, 29 Oct 2026 06:58:54 +0000</pubDate>
      <link>https://dev.to/jh5_pulse/shi-ce-nvidia-switchyard-die-jia-pair-shuang-ceng-jia-gou-yu-yi-da-nao-diao-du-qi-jian-kua-qia-wang-ge-chi-xia-80-za-gong-yu-duan-xian-ling-miao-rong-cuo-41h8</link>
      <guid>https://dev.to/jh5_pulse/shi-ce-nvidia-switchyard-die-jia-pair-shuang-ceng-jia-gou-yu-yi-da-nao-diao-du-qi-jian-kua-qia-wang-ge-chi-xia-80-za-gong-yu-duan-xian-ling-miao-rong-cuo-41h8</guid>
      <description>&lt;p&gt;小朋友才做選擇，前面兩篇我們分別試過 &lt;a href="https://dev.to/jh5_pulse/shi-ce-nvidia-switchyardrtx-3050-bian-yuan-yu-yun-duan-hun-he-lu-you-1036"&gt;《實測 NVIDIA Switchyard：RTX 3050 邊緣與雲端混合路由》&lt;/a&gt; 和 &lt;a href="https://dev.to/jh5_pulse/shi-ce-nvidia-pair-hun-he-cong-ji-lu-you-di-duan-rtx-3050-chuan-jie-colab-a100-tu-po-multi-agent-pai-dui-ping-jing-3lk9"&gt;《實測 NVIDIA PAIR：RTX 3050 串接 Colab A100 混合叢集》&lt;/a&gt;， 也在文章稍微提過混合使用的可能情境，這一篇就來測試一下撒尿牛丸吧。&lt;/p&gt;




&lt;h2&gt;
  
  
  為什麼單一路由層無法滿足生產環境？
&lt;/h2&gt;

&lt;p&gt;實際落地時，單一方案都會在現場撞牆：&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;只用 Switchyard 的硬傷&lt;/strong&gt;：Switchyard 雖然能精準辨識出「日常庶務，派給本地 8B 即可」（見第二篇：&lt;a href="https://dev.to/jh5_pulse/shi-ce-nvidia-switchyardrtx-3050-bian-yuan-yu-yun-duan-hun-he-lu-you-1036"&gt;《實測 NVIDIA Switchyard：RTX 3050 邊緣與雲端混合路由》&lt;/a&gt;），但它預設只能指派給單一的本地端點，當 Multi-Agent 同時併發 10 個子任務時，單張 3050 顯卡當場被塞爆。&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;只用 PAIR 的硬傷&lt;/strong&gt;：PAIR 擅長在區域網路內做負載平衡輪詢（見第一篇：&lt;a href="https://dev.to/jh5_pulse/shi-ce-nvidia-pair-hun-he-cong-ji-lu-you-di-duan-rtx-3050-chuan-jie-colab-a100-tu-po-multi-agent-pai-dui-ping-jing-3lk9"&gt;《實測 NVIDIA PAIR：RTX 3050 串接 Colab A100 混合叢集》&lt;/a&gt;），不過它缺乏「對話語意辨識」與「多輪執行期狀態追蹤」能力，因此，當 Agent 在工具調用中連續 Deadlock 或ＧＧ後，PAIR 無法理解先前 context 的嚴重性，只是會一直撞牆的把請求拋給小模型，導致 Agent 陷入無限迴圈。&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  實測一：A100 14B 熱機純推論效能重測
&lt;/h2&gt;

&lt;p&gt;在第一篇 &lt;a href="https://dev.to/jh5_pulse/shi-ce-nvidia-pair-hun-he-cong-ji-lu-you-di-duan-rtx-3050-chuan-jie-colab-a100-tu-po-multi-agent-pai-dui-ping-jing-3lk9"&gt;PAIR 混合叢集實測&lt;/a&gt; 中，我們觀察到階層模型路由把任務送給 Colab A100 時，總耗時達 51.65 秒，會因為模型初次載入 VRAM 時包含了檔案讀取與權重載入的冷啟動成本（Cold-start Overhead），因此這次測試在權重完全就緒的狀態下，我們重新執行了相同的 5 組不同的評測任務：&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;非小細胞肺癌 EGFR L858R 標靶抗藥性多步論證&lt;/li&gt;
&lt;li&gt;Nextflow K8s Parabricks 容錯架構設計&lt;/li&gt;
&lt;li&gt;TP53 突變 ACMG/AMP 鑑別&lt;/li&gt;
&lt;li&gt;nnU-Net 3D CT 顯卡 VRAM OOM &lt;/li&gt;
&lt;li&gt;跨節點推論調度&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  實測數據對比（冷啟動 vs 熱機）：
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;評測項目&lt;/th&gt;
&lt;th&gt;冷啟動階段 (Cold Start)&lt;/th&gt;
&lt;th&gt;熱機就緒階段 (Warm Cache)&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;5 題總牆鐘時間&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;51.65 秒&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;15.68 秒&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;平均單題推論延遲&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;10.33 秒&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;3.14 秒&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;穩定生成速度&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;~14.5 tok/s&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;70.35 tok/s&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;數據顯示，扣除初次權重載入的硬體 I/O 後，A100-SXM4 憑藉 1.6 TB/s 的 HBM2e 記憶體頻寬，能以每秒超過 70 個 token 的極速穩定輸出 14B 深度推理報告。第一道題目因包含 KV-Cache 預熱花費 7.14 秒，後續四道題目全部整齊劃一地在 &lt;strong&gt;2.13 秒&lt;/strong&gt; 內瞬間完工。&lt;/p&gt;




&lt;h2&gt;
  
  
  實測二：雲端節點斷線之 Failover
&lt;/h2&gt;

&lt;p&gt;將雲端臨時算力（如 Google Colab、Spot Instance）納入叢集時，最擔憂的硬傷就是：&lt;strong&gt;如果雲端節點突然被 Google 收回或網路中斷， Agent 會不會直接崩潰？&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;我們在路由器中實作了主動健康監控與降級重試機制，並設計了包含 8 道連續請求的測試：&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;前 3 題&lt;/strong&gt;：正常派發至雲端 Colab A100。&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;第 4 題至第 8 題&lt;/strong&gt;：刻意阻斷雲端的 Port，模擬遠端伺服器中斷。&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  實測日誌與故障排除軌跡：
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;👉 請求 #1 [NORMAL]: "Check Docker status on worker-node-01..."
   ⚠️ [FAULT DETECTED] 主要節點無回應 (timed out)，觸發 PAIR 毫秒級容錯切換 (耗時 1501.6ms)...
   🔄 [RETRY/FALLBACK] 自動將請求重試轉發至地端 RTX 3050 (llama3.1:latest)...
   ⚡ 完成！伺服節點: Fallback (RTX 3050 Local) | 總耗時: 3.6631s | 產出: 80 tok

👉 請求 #2 [NORMAL]: "Parse FastQC summary text for adapter contamination..."
   🔄 [RETRY/FALLBACK] 自動將請求重試轉發至地端 RTX 3050 (llama3.1:latest)...
   ⚡ 完成！伺服節點: Fallback (RTX 3050 Local) | 總耗時: 0.7328s | 產出: 80 tok
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  容錯切換關鍵結論：
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Client Zero-Failure&lt;/strong&gt;：8 筆請求在遭遇斷線的情況下，Client 端回傳成功率依然是 &lt;strong&gt;8/8 (100%)&lt;/strong&gt;，沒有任何一筆請求噴出 500 錯誤或 ConnectionRefused。&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;故障熔斷速度&lt;/strong&gt;：初次逾時在 1.5 秒內即完成健康度標記並自動重新執行，改成 Request 本地 3050，單題延遲降回 &lt;strong&gt;0.73 秒&lt;/strong&gt;。&lt;/li&gt;
&lt;/ol&gt;




&lt;h2&gt;
  
  
  Switchyard + PAIR 實測
&lt;/h2&gt;

&lt;p&gt;在完成前面的驗證後，我們正式啟動 Switchyard + PAIR 的驗證，並將後端目標直接綁定 PAIR 與雲端 API：&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight toml"&gt;&lt;code&gt;&lt;span class="c"&gt;# routes.toml 關鍵雙層設定節錄&lt;/span&gt;
&lt;span class="k"&gt;[&lt;/span&gt;&lt;span class="n"&gt;routes&lt;/span&gt;&lt;span class="k"&gt;.&lt;/span&gt;&lt;span class="n"&gt;semantic_task_route&lt;/span&gt;&lt;span class="k"&gt;]&lt;/span&gt;
&lt;span class="n"&gt;id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;"semantic_task_route"&lt;/span&gt;
&lt;span class="n"&gt;type&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;"llm_classifier"&lt;/span&gt;
&lt;span class="n"&gt;classifier_target&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;"node_3050_judge"&lt;/span&gt;
&lt;span class="n"&gt;strong_target&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;"flagship_sonnet"&lt;/span&gt;
&lt;span class="n"&gt;weak_target&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;"node_3050_8b"&lt;/span&gt;

&lt;span class="k"&gt;[&lt;/span&gt;&lt;span class="n"&gt;routes&lt;/span&gt;&lt;span class="k"&gt;.&lt;/span&gt;&lt;span class="n"&gt;agent_resilience_route&lt;/span&gt;&lt;span class="k"&gt;]&lt;/span&gt;
&lt;span class="n"&gt;id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;"agent_resilience_route"&lt;/span&gt;
&lt;span class="n"&gt;type&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;"stage_router"&lt;/span&gt;
&lt;span class="n"&gt;picker&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;"efficient_first"&lt;/span&gt;
&lt;span class="n"&gt;capable_target&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;"flagship_sonnet"&lt;/span&gt;
&lt;span class="n"&gt;efficient_target&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;"node_3050_8b"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;在包含單輪語意分流與多輪 Agent 故障排除的四組聯調實測中，端到端耗時與路由行為紀錄如下：&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;測試案例&lt;/th&gt;
&lt;th&gt;情境描述&lt;/th&gt;
&lt;th&gt;路由通道&lt;/th&gt;
&lt;th&gt;實際命中節點&lt;/th&gt;
&lt;th&gt;總耗時 (ms)&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;CASE 1&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Routine Bash 指令&lt;/td&gt;
&lt;td&gt;semantic_task_route&lt;/td&gt;
&lt;td&gt;雲端 (Sonnet)&lt;/td&gt;
&lt;td&gt;2,030.8 ms&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;CASE 2&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;分散式快取時序撕裂&lt;/td&gt;
&lt;td&gt;semantic_task_route&lt;/td&gt;
&lt;td&gt;雲端 (Sonnet)&lt;/td&gt;
&lt;td&gt;2,002.1 ms&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;CASE 3&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;DevOps Agent 正常排障&lt;/td&gt;
&lt;td&gt;agent_resilience_route&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;地端 (3050)&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;431.3 ms&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;CASE 4&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;DB 死鎖除錯排查&lt;/td&gt;
&lt;td&gt;agent_resilience_route&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;地端 (3050)&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;550.1 ms&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;另外測試的過程中也紀錄一些 Note：&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;正規表達式與 Traceback 格式匹配的嚴格性&lt;/strong&gt;：在 CASE 4 中，若工具僅回傳純文字錯誤（如 &lt;code&gt;ERROR 40001&lt;/code&gt;）而不是標準 &lt;code&gt;Traceback (most recent call last):&lt;/code&gt; ，Switchyard 會判定由本地 3050 處理，而在第二篇 &lt;a href="https://dev.to/jh5_pulse/shi-ce-nvidia-switchyardrtx-3050-bian-yuan-yu-yun-duan-hun-he-lu-you-1036"&gt;Switchyard 實測&lt;/a&gt; 中，只要帶有完整的單元測試日誌，才會在 &lt;strong&gt;0.011 ms&lt;/strong&gt; 內觸發 &lt;code&gt;repeated_failure&lt;/code&gt; 並切換到雲端模型。&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;未微調 Judge 的 Fallback 防禦&lt;/strong&gt;：在 CASE 1 中，地端 8B 裁判對提示詞的格式解析稍有偏差時，Switchyard 的安全機制還是有發揮作用，果斷將請求送往雲端模型，不至於讓 Request 卡死在格式錯誤上。&lt;/li&gt;
&lt;/ol&gt;




&lt;h2&gt;
  
  
  推論的三個 Must
&lt;/h2&gt;

&lt;p&gt;經過這一輪測試也可以整理出一些經驗來分享：&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;大腦與肌肉必須分工&lt;/strong&gt;：不要在單一工具內搞定所有事。讓 NeMo Switchyard 專注做語意分析與 Agent 狀態管理（大腦），讓 PAIR 專注做 GPU 資源與連線管理（肌肉），架構最乾淨、維護成本最低。&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;模型預熱是剛性需求&lt;/strong&gt;：在生產管線啟動前，務必對叢集內的模型發送一次輕量 probe 進行模型預熱，避免第一位使用者承擔冷啟動成本。&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;雲地混合必備熔斷降級&lt;/strong&gt;：任何外部算力節點（不論是 Colab 還是雲端 Spot 執行個體）都必須在本地保留等效或輕量的 fallback 副本，才能在享受雲端算力擴展的同時，守住系統 99.9% 的可用性。&lt;/li&gt;
&lt;/ol&gt;




&lt;h2&gt;
  
  
  延伸閱讀：NVIDIA 地雲混合推論實測三部曲
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;第一篇（算力網格）&lt;/strong&gt;：&lt;a href="https://dev.to/jh5_pulse/shi-ce-nvidia-pair-hun-he-cong-ji-lu-you-di-duan-rtx-3050-chuan-jie-colab-a100-tu-po-multi-agent-pai-dui-ping-jing-3lk9"&gt;實測 NVIDIA PAIR：RTX 3050 串接 Colab A100 混合叢集&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;第二篇（語意大腦）&lt;/strong&gt;：&lt;a href="https://dev.to/jh5_pulse/shi-ce-nvidia-switchyardrtx-3050-bian-yuan-yu-yun-duan-hun-he-lu-you-1036"&gt;實測 NVIDIA Switchyard：RTX 3050 邊緣與雲端混合路由&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;第三篇（本篇）&lt;/strong&gt;：實測 NVIDIA Switchyard 疊加 PAIR：雙層混合推論架構&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>ai</category>
      <category>nvidia</category>
      <category>rust</category>
      <category>devops</category>
    </item>
    <item>
      <title>實測 NVIDIA Switchyard：RTX 3050 邊緣與雲端混合路由</title>
      <dc:creator>JH5</dc:creator>
      <pubDate>Thu, 29 Oct 2026 06:58:53 +0000</pubDate>
      <link>https://dev.to/jh5_pulse/shi-ce-nvidia-switchyardrtx-3050-bian-yuan-yu-yun-duan-hun-he-lu-you-1036</link>
      <guid>https://dev.to/jh5_pulse/shi-ce-nvidia-switchyardrtx-3050-bian-yuan-yu-yun-duan-hun-he-lu-you-1036</guid>
      <description>&lt;p&gt;每次看到月底 API 帳單上那些忽多忽少的美元的扣款，心裡總是噴血，點開日誌一看裡面有八成竟然都只是在叫 Claude 讀個檔案、跑個 Linter、處理 Git... &lt;br&gt;
如果在每個打到雲端 API 前的任務再加個 Routing，地端可以接球再決定要不要轉傳，是不是就可以幫忙處理很多種任務前置分流與動態執行任務的日常運用？&lt;/p&gt;


&lt;h2&gt;
  
  
  釐清架構盲點：為什麼單輪任務與 Agent 升級不能混為一談？
&lt;/h2&gt;

&lt;p&gt;很多團隊在評估動態模型路由（Model Routing）時，最常犯的直覺錯誤就是把所有請求當成同一種東西在分流。&lt;/p&gt;

&lt;p&gt;而 NVIDIA NeMo Switchyard 是基於 Rust 開發的開源動態模型路由層，特點是能將 Agent 在多輪對話中的每一步請求依據即時狀態分流到不同成本與能力的 LLM。&lt;/p&gt;

&lt;p&gt;但仔細看它的核心設計，其實切成了兩套運作邏輯截然不同的路由範式：&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;                              ┌── 範例 A：任務型前置分流 (Task Routing)
                              │   單輪進門 ──► 裁判模型預判難度 ──► 派發 (8B vs 旗艦)
  ─────    應用範例  ──────────┤
                              └── 範例 B：執行期動態升級 (Stage Routing)
                                  多輪 Agent ──► 預設本地 8B 跑雜工 ──► 連續撞牆 ──► 雲端旗艦模型接棒
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;如果你拿單輪的 URL 參數解析、SQL 分頁或常規文本摘要去跑多輪專用的 &lt;code&gt;stage_router&lt;/code&gt;，Switchyard 根本沒有進行任何語意推理，它只是因為你設了 &lt;code&gt;picker = "efficient_first"&lt;/code&gt; 而無腦套用預設值，那只能稱作靜態 fallback。&lt;/p&gt;

&lt;p&gt;真正的分流架構，必須把這兩件事拆開：&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;任務前置分流（Task Routing）&lt;/strong&gt;：由輕量 Judge 或意圖分類器在入口把關，依據單輪任務複雜度決定走便宜通道還是旗艦通道。&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;執行期動態升級（Stage Routing）&lt;/strong&gt;：專門為 Tool-Using Coding Agent 或 SRE 診斷腳本打造。前幾輪看檔案、跑 linter、查 status 全丟給本地端 RTX 3050（成本為 0 元）；只有在工具回傳連續報錯、卡死時，才強行 hot-swap 到雲端旗艦模型（例如 Claude-Sonnet-5.5 或 GPT-6）來收尾。&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;不過這裡也有一個可能會發生的架構卡點：Switchyard 本質上是一個「語意決策大腦」，預設是將本地任務指派給單一端點，當前端 Multi-Agent 同時併發多個任務時，單張 3050 顯卡依然可能被排隊隊列塞爆。如果要為本地端引入跨卡或跨設備的硬體推論網格，可以參考第一篇：&lt;a href="https://dev.to/jh5_pulse/shi-ce-nvidia-pair-hun-he-cong-ji-lu-you-di-duan-rtx-3050-chuan-jie-colab-a100-tu-po-multi-agent-pai-dui-ping-jing-3lk9"&gt;《實測 NVIDIA PAIR：RTX 3050 串接 Colab A100 混合叢集》&lt;/a&gt;；而將兩者融合成「大腦＋肌肉」的終極雙層架構，則記錄在第三篇：&lt;a href="https://dev.to/jh5_pulse/shi-ce-nvidia-switchyard-die-jia-pair-shuang-ceng-jia-gou-yu-yi-da-nao-diao-du-qi-jian-kua-qia-wang-ge-chi-xia-80-za-gong-yu-duan-xian-ling-miao-rong-cuo-41h8"&gt;《實測 NVIDIA Switchyard 疊加 PAIR：雙層混合推論架構》&lt;/a&gt;。&lt;/p&gt;




&lt;h2&gt;
  
  
  格式避坑：Switchyard 雙路由 TOML
&lt;/h2&gt;

&lt;p&gt;網路上包括 KDnuggets 在內的多數教學文章都停留在 0.2.0 版本，好多範例都是過時的 &lt;code&gt;routes.random.yaml&lt;/code&gt;，在 0.3.0 版中，底層原生 Rust 伺服器已全面改為 TOML 結構。&lt;/p&gt;

&lt;p&gt;在 Python 環境安裝套件非常直接，直接安裝預編譯 wheel 檔即可：&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;pip &lt;span class="nb"&gt;install &lt;/span&gt;nemo-switchyard
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;在這次的邊緣與雲端混合架構中，我們在同一份 &lt;code&gt;routes.toml&lt;/code&gt; 裡同時定義兩個不同用途的路由：&lt;code&gt;task_route&lt;/code&gt; 負責單輪前置判定，&lt;code&gt;agent_stage_route&lt;/code&gt; 負責多輪 Agent 工具監控。&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight toml"&gt;&lt;code&gt;&lt;span class="n"&gt;schema_version&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;

&lt;span class="k"&gt;[&lt;/span&gt;&lt;span class="n"&gt;llm_clients&lt;/span&gt;&lt;span class="k"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ollama_local&lt;/span&gt;&lt;span class="k"&gt;]&lt;/span&gt;
&lt;span class="n"&gt;format&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;"openai_chat"&lt;/span&gt;
&lt;span class="n"&gt;base_url&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;"http://127.0.0.1:11434/v1"&lt;/span&gt;

&lt;span class="k"&gt;[&lt;/span&gt;&lt;span class="n"&gt;llm_clients&lt;/span&gt;&lt;span class="k"&gt;.&lt;/span&gt;&lt;span class="n"&gt;cloud_upstream&lt;/span&gt;&lt;span class="k"&gt;]&lt;/span&gt;
&lt;span class="n"&gt;format&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;"openai_chat"&lt;/span&gt;
&lt;span class="n"&gt;base_url&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;"http://127.0.0.1:19800/v1"&lt;/span&gt;

&lt;span class="k"&gt;[&lt;/span&gt;&lt;span class="n"&gt;targets&lt;/span&gt;&lt;span class="k"&gt;.&lt;/span&gt;&lt;span class="n"&gt;local_edge&lt;/span&gt;&lt;span class="k"&gt;]&lt;/span&gt;
&lt;span class="n"&gt;id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;"llama3.1:latest"&lt;/span&gt;
&lt;span class="n"&gt;llm_client&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;"ollama_local"&lt;/span&gt;

&lt;span class="k"&gt;[&lt;/span&gt;&lt;span class="n"&gt;targets&lt;/span&gt;&lt;span class="k"&gt;.&lt;/span&gt;&lt;span class="n"&gt;cloud_flagship&lt;/span&gt;&lt;span class="k"&gt;]&lt;/span&gt;
&lt;span class="n"&gt;id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;"claude-sonnet-5-5"&lt;/span&gt;
&lt;span class="n"&gt;llm_client&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;"cloud_upstream"&lt;/span&gt;

&lt;span class="k"&gt;[&lt;/span&gt;&lt;span class="n"&gt;targets&lt;/span&gt;&lt;span class="k"&gt;.&lt;/span&gt;&lt;span class="n"&gt;local_judge&lt;/span&gt;&lt;span class="k"&gt;]&lt;/span&gt;
&lt;span class="n"&gt;id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;"llama3.1-judge"&lt;/span&gt;
&lt;span class="n"&gt;llm_client&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;"ollama_local"&lt;/span&gt;

&lt;span class="c"&gt;# 範式一：單輪任務前置意圖分流 (Task-level Pre-Routing)&lt;/span&gt;
&lt;span class="k"&gt;[&lt;/span&gt;&lt;span class="n"&gt;routes&lt;/span&gt;&lt;span class="k"&gt;.&lt;/span&gt;&lt;span class="n"&gt;task_route&lt;/span&gt;&lt;span class="k"&gt;]&lt;/span&gt;
&lt;span class="n"&gt;id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;"task_route"&lt;/span&gt;
&lt;span class="n"&gt;type&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;"llm_classifier"&lt;/span&gt;
&lt;span class="n"&gt;classifier_target&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;"local_judge"&lt;/span&gt;
&lt;span class="n"&gt;strong_target&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;"cloud_flagship"&lt;/span&gt;
&lt;span class="n"&gt;weak_target&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;"local_edge"&lt;/span&gt;
&lt;span class="n"&gt;base_threshold&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;0.5&lt;/span&gt;
&lt;span class="n"&gt;threshold_step&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;0.0&lt;/span&gt;
&lt;span class="n"&gt;classify_trigger&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;"new_session"&lt;/span&gt;

&lt;span class="c"&gt;# 範式二：多輪自主 Agent 執行期動態升級 (Stage-level Execution Routing)&lt;/span&gt;
&lt;span class="k"&gt;[&lt;/span&gt;&lt;span class="n"&gt;routes&lt;/span&gt;&lt;span class="k"&gt;.&lt;/span&gt;&lt;span class="n"&gt;agent_stage_route&lt;/span&gt;&lt;span class="k"&gt;]&lt;/span&gt;
&lt;span class="n"&gt;id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;"agent_stage_route"&lt;/span&gt;
&lt;span class="n"&gt;type&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;"stage_router"&lt;/span&gt;
&lt;span class="n"&gt;picker&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;"efficient_first"&lt;/span&gt;
&lt;span class="n"&gt;capable_target&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;"cloud_flagship"&lt;/span&gt;
&lt;span class="n"&gt;efficient_target&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;"local_edge"&lt;/span&gt;
&lt;span class="n"&gt;confidence_threshold&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;0.5&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;這裡有一個很大的設定陷阱：Switchyard 的 Rust 引擎在同一條 route 內是拿 &lt;code&gt;model id&lt;/code&gt; 當 key，如果你把 &lt;code&gt;classifier_target&lt;/code&gt; 跟 &lt;code&gt;weak_target&lt;/code&gt; 都指向同一個字串 &lt;code&gt;llama3.1:latest&lt;/code&gt;，伺服器在初始化時會直接報錯，目前暫時的解決辦法是在 Ollama 裡用 &lt;code&gt;ollama cp llama3.1:latest llama3.1-judge&lt;/code&gt; 複製一個別名來暫時通過 Init 的驗證。&lt;/p&gt;

&lt;p&gt;在 Python 裡拉起原生伺服器只要兩行：&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;switchyard_rust.server&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Server&lt;/span&gt;

&lt;span class="c1"&gt;# 啟動 Rust 監聽伺服器
&lt;/span&gt;&lt;span class="n"&gt;sy_server&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Server&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;routes.toml&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;port&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;19888&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Switchyard 路由伺服器已上線：&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;sy_server&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;base_url&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  拆解任務前置分流：llm_classifier 在本地端到底靈不靈？
&lt;/h2&gt;

&lt;p&gt;第一個測試，我們先測試了全端開發常見的錯誤的分流能力&lt;/p&gt;

&lt;p&gt;當請求打到 &lt;code&gt;task_route&lt;/code&gt; 時，Switchyard 會先掛起請求，把任務送進 &lt;code&gt;classifier_target&lt;/code&gt;（我們部署在 RTX 3050 上的 &lt;code&gt;llama3.1-judge&lt;/code&gt;），接著，Switchyard 會透過 &lt;code&gt;TaskClassifierVerdict&lt;/code&gt;，要求裁判模型輸出 &lt;code&gt;crux&lt;/code&gt;、&lt;code&gt;primary_rule&lt;/code&gt;、&lt;code&gt;capability_boundary&lt;/code&gt; 以及解題機率 &lt;code&gt;p_solve&lt;/code&gt;。&lt;/p&gt;

&lt;p&gt;在全端常見錯誤（例如前端與 API Gateway 最頻繁遇到的 URL Query 參數解析與缺失防禦）中，裁判模型判斷小模型具備充足能力，信心值直接給出 1.0，請求順利被分發給本地 3050 上的 8B 模型：&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;INFO switchyard.request: libsy.run: switchyard_libsy::algorithms::util::llm_judge: consulting llm judge target="llama3.1-judge"
INFO switchyard.request: libsy.run: Model selected algorithm="llm_task_classifier" target=llama3.1:latest confidence=1.0
INFO switchyard.request: switchyard_server::request: LLM request handled wire_format=openai_chat status=200 requested_model="task_route" selected_model="llama3.1:latest"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;而因為我的前端選的是 Next.js，過程中好幾次遇到 Server Actions 引發的 JWT Session Cookie 覆蓋跟 WebSocket 斷線的錯誤，裁判模型判定超出能力範圍，Switchyard 果斷將請求直送雲端 Claude-Sonnet-5.5。&lt;/p&gt;

&lt;p&gt;另一個發現是，Switchyard 內建的 capability classifier 規範了 &lt;code&gt;SUP-1&lt;/code&gt; 到 &lt;code&gt;SUP-5&lt;/code&gt; 的規則列舉，如果本地 8B 裁判對提示詞的理解稍微有一點格式偏差，Switchyard 會直接將判定標記為無效，並觸發 &lt;code&gt;fall_through&lt;/code&gt; 安全轉換到比較強模型，這種保守的設計保證了生產環境不會因為判斷出錯而ＧＧ，但也代表在日常的業務情境下，如果要精準發揮前置分流的威力，還是必須要微調小模型或改寫專屬 prompt 。&lt;/p&gt;




&lt;h2&gt;
  
  
  實測執行期動態升級： 捕捉 repeated_failure
&lt;/h2&gt;

&lt;p&gt;前面有提到另一個常見場景就是 &lt;code&gt;stage_router&lt;/code&gt;的應用&lt;/p&gt;

&lt;p&gt;在 Coding Agent 與 DevOps 維運場景中，我們實測了四個常見的日常：&lt;/p&gt;

&lt;p&gt;第一組是規範檢查：Coding Agent 讀取 &lt;code&gt;src/auth_service.py&lt;/code&gt; 裡的 JWT 驗證邏輯，接著調用 &lt;code&gt;run_linter&lt;/code&gt; 工具，工具回傳 &lt;code&gt;SUCCESS: 0 warnings, 0 errors&lt;/code&gt;，確認了在 Switchyard 的歷史紀錄中看見全數正常，維持在本地 3050 處理，端到端耗時僅 438 ms。&lt;/p&gt;

&lt;p&gt;第二組是環境維護：DevOps Agent 執行 &lt;code&gt;git status&lt;/code&gt; 確認工作目錄乾淨，再執行 &lt;code&gt;hadolint&lt;/code&gt; 驗證多階段 Dockerfile ，沒有任何異常訊號，全程在本地 8B 解決。&lt;/p&gt;

&lt;p&gt;第三組是deadlock除錯：Agent 嘗試修復並呼叫 pytest 工具，結果第一次ＧＧ：&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Traceback (most recent call last):
  PostgreSQLError: 40001 could not serialize access due to concurrent update (deadlock detected)
FAILED tests/test_concurrency.py::test_deduct_balance
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Agent 嘗試修改程式碼後再次執行測試，又噴出了一模一樣的 40001 錯誤，不過就在連續失敗兩次後，Switchyard 發揮了它的價值～&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;INFO switchyard.request: switchyard_libsy::algorithms::util::stage: stage router override decision_source="override" override_reason="repeated_failure" target=claude-sonnet-5-5
INFO switchyard.request: libsy.run: Model selected algorithm="stage_router" target=claude-sonnet-5-5 confidence=1.0
INFO switchyard.request: switchyard_server::request: LLM request handled wire_format=openai_chat status=200 requested_model="agent_stage_route" selected_model="claude-sonnet-5-5" handling_duration_ms=300.96
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;從判斷出 &lt;code&gt;repeated_failure&lt;/code&gt; 到切換，只花了 &lt;strong&gt;11 微秒（0.011 ms）&lt;/strong&gt;，信心度也被拉到 1.0，直接將下一輪提示詞切換至雲端 Claude-Sonnet-5.5，讓雲端模型分析與接手處理。&lt;/p&gt;

&lt;p&gt;第四組是 Kubernetes 故障排查：DaemonSet Pod 連續兩次噴出 &lt;code&gt;ExitCode 137 (OOMKilled)&lt;/code&gt;，Switchyard 也順利的觸發了 &lt;code&gt;critical_error&lt;/code&gt; ，同樣的順利傳球給雲端模型接手處理。&lt;/p&gt;




&lt;h2&gt;
  
  
  實際運用的架構取捨
&lt;/h2&gt;

&lt;p&gt;雖然 Switchyard 的反應很快，但在生產環境部署與雲端混合架構時，實測完後還是有一些需要考慮的架構取捨問題。&lt;/p&gt;

&lt;p&gt;第一個是雲端 Prompt Caching 的失效問題，在一般的雲端架構裡，如果多輪對話全走同一家雲端 API，重複的前文享有高達 50% 到 90% 的快取折扣，但是在混合架構下，前三輪在本地 3050 跑 8B 模型，第四輪才因為 &lt;code&gt;repeated_failure&lt;/code&gt; 突然切換到雲端 Claude-Sonnet-5.5 時，上下文已經累積了一定數量的 tokens，這一次跳轉產生的首次 pre-fill 費用，可能還是會吃掉前幾輪省下來的差價。&lt;/p&gt;

&lt;p&gt;第二個是小模型的 Tool Use 穩定度，要讓本地 8B 模型跑前面幾輪的前提，是該模型必須具備穩定的 Function Calling 能力，如果 8B 模型在第二輪就產生了無效的 JSON 參數，導致工具根本無法執行，那它連觸發 &lt;code&gt;repeated_failure&lt;/code&gt; 的機會都沒有，反而會直接把 Agent 卡死在語法錯誤上。&lt;/p&gt;

&lt;p&gt;Switchyard 實測了幾天，的確是可以幫忙解決在 routine 工作的不少小雜事， 下一步要解決的，可能還有兩件事，第一個是前面有提到的，要怎麼從拿到適當的訓練資料來做微調，讓他分流可以更為精準，第二個則是目前另一個大花費，讓 Agent 在控制瀏覽器時如果多次遇到 repeated_failure ，可以從local的 Gemma4 自動換到雲端的模型，並順利接手前面試過的這些 screen context ，如果有測試到不錯的結果再來跟大家分享。&lt;/p&gt;




&lt;h2&gt;
  
  
  延伸閱讀：NVIDIA 地雲混合推論實測三部曲
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;第一篇（算力網格）&lt;/strong&gt;：&lt;a href="https://dev.to/jh5_pulse/shi-ce-nvidia-pair-hun-he-cong-ji-lu-you-di-duan-rtx-3050-chuan-jie-colab-a100-tu-po-multi-agent-pai-dui-ping-jing-3lk9"&gt;實測 NVIDIA PAIR：RTX 3050 串接 Colab A100 混合叢集&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;第二篇（本篇）&lt;/strong&gt;：實測 NVIDIA Switchyard：RTX 3050 邊緣與雲端混合路由&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;第三篇（雙層全棧）&lt;/strong&gt;：&lt;a href="https://dev.to/jh5_pulse/shi-ce-nvidia-switchyard-die-jia-pair-shuang-ceng-jia-gou-yu-yi-da-nao-diao-du-qi-jian-kua-qia-wang-ge-chi-xia-80-za-gong-yu-duan-xian-ling-miao-rong-cuo-41h8"&gt;實測 NVIDIA Switchyard 疊加 PAIR：雙層混合推論架構&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>ai</category>
      <category>nvidia</category>
      <category>rust</category>
      <category>devops</category>
    </item>
    <item>
      <title>實測 NVIDIA PAIR：RTX 3050 串接 Colab A100 混合叢集</title>
      <dc:creator>JH5</dc:creator>
      <pubDate>Thu, 29 Oct 2026 06:58:46 +0000</pubDate>
      <link>https://dev.to/jh5_pulse/shi-ce-nvidia-pair-hun-he-cong-ji-lu-you-di-duan-rtx-3050-chuan-jie-colab-a100-tu-po-multi-agent-pai-dui-ping-jing-3lk9</link>
      <guid>https://dev.to/jh5_pulse/shi-ce-nvidia-pair-hun-he-cong-ji-lu-you-di-duan-rtx-3050-chuan-jie-colab-a100-tu-po-multi-agent-pai-dui-ping-jing-3lk9</guid>
      <description>&lt;p&gt;不知道你有沒有過這種經驗，你手邊腳邊剛好有很多小卡，每張卡 VRAM 都可以支撐一些 7B/8B 的小模型，看起來就很適合拿來派發給 Subagent 同步開跑，只是實際上要怎麼部署，要怎麼跨節點來處理，要怎麼在降低延遲建立統一 API 端點，處理負載平衡與階層模型路由場景，這一篇適合在找尋低成本幫本地 Agent 佇列塞車解法的人來看一下。&lt;/p&gt;




&lt;h2&gt;
  
  
  釐清本質：NVIDIA PAIR 到底能做什麼、不能做什麼？
&lt;/h2&gt;

&lt;p&gt;在社群第一次看到 NVIDIA PAIR（Personal AI Router）開源時，直覺以為它是某種「VRAM 黑科技」，還幻想把家裡 8GB 小卡跟其他小卡記憶體黏在一起跑 70B 模型 （光是網路就崩潰了ＸＤ）&lt;/p&gt;

&lt;p&gt;NVIDIA PAIR 是基於 Apache 2.0 協議開源的本地推論路由代理層，特點是能將區域網路或混合雲的多台運算節點統一封裝為標準 OpenAI 與 Ollama 相容端點，透過請求層級（Request-level）的調度解決平行任務排隊問題。&lt;/p&gt;

&lt;p&gt;基本上，它&lt;strong&gt;不做&lt;/strong&gt; Tensor Parallelism，也不做跨機器的模型 Sharding，所以如果你跟我前面幻想的一樣，那應該是無解，但是它真正解決的痛點是：當主 Agent 同時喚起多個 Subagent 分頭進行程式碼撰寫、靜態分析、Code Review 解析與網路查詢時，單張顯卡只能循序一個個排隊處理，而 GPU 運算單元在單一請求未達 batch 飽和時又吃不滿，這時，PAIR 的價值在於扮演 LB，可以幫忙把互不相干的獨立推論請求瞬間打散到多個閒置節點上並行跑完。&lt;/p&gt;

&lt;p&gt;這邊要特別注意的是，PAIR 只專注於處理對話 Request 的負載平衡，它本身並不負責解讀對話內容的難易度，如果你需要的是更具彈性的「語意大腦」，讓小模型扛日常雜工、遇到連續出錯才自動升級雲端高級模型，這需要搭配另一套路由機制（詳見第二篇：&lt;a href="https://dev.to/jh5_pulse/shi-ce-nvidia-switchyardrtx-3050-bian-yuan-yu-yun-duan-hun-he-lu-you-1036"&gt;《實測 NVIDIA Switchyard：RTX 3050 邊緣與雲端混合路由》&lt;/a&gt;）。&lt;/p&gt;




&lt;h2&gt;
  
  
  架構搭橋：透過 Colab CLI 與 SSH Tunnel 打通網路
&lt;/h2&gt;

&lt;p&gt;先前的文章有介紹過 &lt;a href="https://dev.to/jh5_pulse/mian-fei-de-colab-cli-a100h100-zhen-xiang--3dhk"&gt;免費的 Colab CLI A100/H100 真香 :)&lt;/a&gt; ，因此最近我都是把腳邊的小卡串接colab用好用滿，但是要把 Google Colab 上的 A100 納入本地 PAIR 叢集，最麻煩的是 Colab 執行個體位於 Google 內部容器網路，沒有固定公網 IP。&lt;/p&gt;

&lt;p&gt;如果用 ngrok 或 Cloudflare Tunnel，也免費頻寬限制，每次重連還得手動抓新網址，維護成本很高，後來我都是直接用 &lt;code&gt;google-colab-cli&lt;/code&gt; 提供的 &lt;code&gt;colab ssh --proxy-mode&lt;/code&gt;，配合 SSH 指令建立 WebSocket-stdio Tunnel:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# 1. 在本地背景建立一條專屬的 SSH 本地連接埠轉發 (Port Forwarding)&lt;/span&gt;
ssh &lt;span class="nt"&gt;-N&lt;/span&gt; &lt;span class="nt"&gt;-L&lt;/span&gt; 11435:127.0.0.1:11434 &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;-o&lt;/span&gt; &lt;span class="nv"&gt;ExitOnForwardFailure&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nb"&gt;yes&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;-o&lt;/span&gt; &lt;span class="nv"&gt;ServerAliveInterval&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;30 &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;-o&lt;/span&gt; &lt;span class="nv"&gt;ServerAliveCountMax&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;3 &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;-o&lt;/span&gt; &lt;span class="nv"&gt;StrictHostKeyChecking&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;no &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;-o&lt;/span&gt; &lt;span class="nv"&gt;UserKnownHostsFile&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;/dev/null &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;-o&lt;/span&gt; &lt;span class="nv"&gt;ProxyCommand&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"/home/lamanwu/.local/bin/colab ssh --proxy-mode -s a100-c2c"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
    root@colab &amp;amp;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;建起來後地端程式只要存取 &lt;code&gt;http://127.0.0.1:11435&lt;/code&gt;，封包就會透過 WebSocket 直通 Colab A100 上跑的 Ollama 服務。&lt;/p&gt;

&lt;p&gt;實際測一下連線品質，地端的 RTT 僅 3.08 ms，而 Colab 隧道的 RTT 落在 107.56 ms，如果是自己在家裡使用，100 ms 出頭的 delay 完全可以忽略。&lt;/p&gt;




&lt;h2&gt;
  
  
  基準實測
&lt;/h2&gt;

&lt;p&gt;我整理了一些平常開發或是工作滿常遇到的案例來測試 Agent 並行子任務，再觀察一下 Wall-clock time。&lt;/p&gt;

&lt;h3&gt;
  
  
  1. 單節點處理
&lt;/h3&gt;

&lt;p&gt;當 10 個請求同時灌進地端 llama3.1:8b 時，雖然底層推理服務具備基本的並行批次能力，但受到 VRAM 頻寬與運算核心限制，後續請求理所當然需要乖乖的排隊&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;總耗時&lt;/strong&gt;：&lt;strong&gt;9.138 秒&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;總產出 Token&lt;/strong&gt;：1,147 tokens&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;叢集有效吞吐量&lt;/strong&gt;：&lt;strong&gt;125.52 tok/s&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;平均每題等待延遲&lt;/strong&gt;：3.634 秒&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  2. PAIR 叢集負載平衡（RTX 3050 + Colab A100 對半平分）
&lt;/h3&gt;

&lt;p&gt;接著將相同 10 組任務交由 PAIR 分流器以 Round-Robin 方式平均指派：5 題送地端 3050，5 題送雲端 A100。兩端均使用相同的 &lt;code&gt;llama3.1:8b&lt;/code&gt;：&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;總耗時&lt;/strong&gt;：&lt;strong&gt;4.611 秒&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;總產出 Token&lt;/strong&gt;：1,160 tokens&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;叢集有效吞吐量&lt;/strong&gt;：&lt;strong&gt;251.56 tok/s&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;測試架構&lt;/th&gt;
&lt;th&gt;實體節點規格&lt;/th&gt;
&lt;th&gt;總執行耗時 (s)&lt;/th&gt;
&lt;th&gt;叢集吞吐量 (tok/s)&lt;/th&gt;
&lt;th&gt;加速倍率&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;單節點基準&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;地端 RTX 3050 (8GB) 獨扛&lt;/td&gt;
&lt;td&gt;9.138 s&lt;/td&gt;
&lt;td&gt;125.52 tok/s&lt;/td&gt;
&lt;td&gt;1.00x (基線)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;PAIR 負載平衡&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;RTX 3050 (8GB) + Colab A100 (40GB)&lt;/td&gt;
&lt;td&gt;4.611 s&lt;/td&gt;
&lt;td&gt;251.56 tok/s&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;1.98x&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;高並發壓力&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;20 請求灌入雙節點 (100% 成功率)&lt;/td&gt;
&lt;td&gt;4.930 s&lt;/td&gt;
&lt;td&gt;243.46 tok/s&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;1.94x&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;最亮眼的發現是：即使雲端 A100 承受了 107 ms 的網路往返延遲，但由於 A100 的強大記憶體頻寬（1.6 TB/s）與 40GB VRAM 容量，其單題生成速度完全彌補了網路損耗，雙節點完美維持同步收尾節奏。&lt;/p&gt;




&lt;h2&gt;
  
  
  階層式模型分流：大小模型各司其職的生產實踐
&lt;/h2&gt;

&lt;p&gt;除了齊頭式平分同一個模型之外，多節點混合架構另一個巨大優勢是&lt;strong&gt;模型階層分流（Model Tiering）&lt;/strong&gt;。&lt;/p&gt;

&lt;p&gt;在現實的軟體工程或生醫管線中，並不是每個請求都需要動用大參數模型。我們實測了這種工作流組態：&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;地端 RTX 3050 專責「日常例行雜工」&lt;/strong&gt;：掛載 &lt;code&gt;llama3.1:8b&lt;/code&gt;，專門處理 Bash 語法檢查、Regex 提取、FastQC 數值解讀。單題耗時落在 0.7s ~ 4.2s，地端零傳輸成本、零額外網路暴露。&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;雲端 Colab A100 專責「深度邏輯推理」&lt;/strong&gt;：掛載參數較大的 &lt;code&gt;qwen2.5:14b&lt;/code&gt;，專門扛下非小細胞肺癌 EGFR 標靶抗藥性機轉、Li-Fraumeni 症候群 TP53 致病性判斷等複雜多步論證。&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;在 10 題階層分級實測中，地端 3050 在 5 秒內就迅速清理完所有 routine 雜工，而 A100 則在 40GB VRAM 悠哉的完成 5 個 14B 深度推理報告。&lt;/p&gt;




&lt;h2&gt;
  
  
  20 並行任務高壓考驗：叢集容錯與真實瓶頸
&lt;/h2&gt;

&lt;p&gt;為了驗證架構在高峰時期的穩定度，我把並發任務稍微拉高到 20 個請求同時灌入 PAIR 叢集。&lt;/p&gt;

&lt;p&gt;實測結果也是滿不錯的：&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;20 個並行請求全部成功回傳（&lt;strong&gt;成功率 100%&lt;/strong&gt;，無任何 timeout 或連線中斷）。&lt;/li&gt;
&lt;li&gt;總耗時僅 4.93 秒，整體吞吐量維持在 &lt;strong&gt;243.46 tok/s&lt;/strong&gt; 的高檔水位。&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;不過這次也小踩了兩個小坑：&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Colab 連線生命週期風險&lt;/strong&gt;：Google Colab 免費或 Pro 執行個體隨時有因閒置或搶佔（Preemption）而斷線的可能，實際測試過程中就常常ＧＧ要再重新建立Tunnel，還好一般在正式環境中，PAIR 可以搭配Heartbeat 與「自動 Fallback」的重試機制，否則網路一斷，掛在上面的 Agent 就會現場翻車。&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;多節點 Model Cache 暖機成本&lt;/strong&gt;：第一次將請求派給尚未載入 VRAM 的節點時，Ollama 載入權重會產生一次性的記憶體搬移延遲（例如 3050 冷啟動約 16 秒）。因此在正式啟動 Agent 批量作業前，還是需要先對各節點發送請求來暖機一下。&lt;/li&gt;
&lt;/ol&gt;




&lt;h2&gt;
  
  
  三步搭建自己的 PAIR 混合叢集
&lt;/h2&gt;

&lt;p&gt;如果也想要在自己的開發環境踹踹這套架構，只需要三個具體步驟：&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;取得 NVIDIA PAIR 核心二進位檔&lt;/strong&gt;：
從官方倉庫 &lt;code&gt;NVIDIA/Personal-AI-Router&lt;/code&gt; 的 Releases 下載 Linux 版二進位包（內含 &lt;code&gt;nvpair-proxy&lt;/code&gt;、&lt;code&gt;inference-dispatcher&lt;/code&gt; 與 &lt;code&gt;nvpair-cluster-manager&lt;/code&gt;）。&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;建立背景連線隧道&lt;/strong&gt;：
使用你慣用的 SSH 工具（或 Colab CLI）將遠端 GPU 伺服器的 11434 連接埠映射至本機的閒置連接埠（如 11435），或是如果你的Local就有兩個 Node，網路也是通的就可以略過這個步驟。&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;設定統一路由轉發&lt;/strong&gt;：
設定 PAIR 代理監聽在本地 19800，將本機 11434 與隧道 11435 登記為後端池，日後前端任何 Agent 框架（如 LangChain、LlamaIndex ）只要將 Base URL 指向 &lt;code&gt;http://127.0.0.1:19800/v1&lt;/code&gt;，就能自動享受有 LB 的 LLM Endpoint。&lt;/li&gt;
&lt;/ol&gt;




&lt;h2&gt;
  
  
  直上 Production 嗎？
&lt;/h2&gt;

&lt;p&gt;但如果你跟我一樣三不五時就把 Agy/ Opencode 額度燒完，又三不五時會有一些小需求要處理，目前這樣搭配 3050 + 免費 A100 已經可以處理滿多日常任務了，很多目前在 本地 N8N上的日常抓資料小作業，我已經這樣 run了快一週了好像也沒出什麼太大差錯 （偶爾tool calling會秀逗秀逗），趁 Google 還沒把這台 A100 連線收回去之前 ，我應該會再把一些 Endpoint assign到這些endpoint上來玩～&lt;/p&gt;

&lt;p&gt;Production 建議還是先不要ＸＤ 有太多架構上 HAProxy 或是 Failover 這篇都省略了 ＸＤ&lt;/p&gt;




&lt;h2&gt;
  
  
  延伸閱讀：NVIDIA 地雲混合推論實測三部曲
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;第一篇（本篇）&lt;/strong&gt;：實測 NVIDIA PAIR：RTX 3050 串接 Colab A100 混合叢集&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;第二篇（語意大腦）&lt;/strong&gt;：&lt;a href="https://dev.to/jh5_pulse/shi-ce-nvidia-switchyardrtx-3050-bian-yuan-yu-yun-duan-hun-he-lu-you-1036"&gt;實測 NVIDIA Switchyard：RTX 3050 邊緣與雲端混合路由&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;第三篇（雙層全棧）&lt;/strong&gt;：&lt;a href="https://dev.to/jh5_pulse/shi-ce-nvidia-switchyard-die-jia-pair-shuang-ceng-jia-gou-yu-yi-da-nao-diao-du-qi-jian-kua-qia-wang-ge-chi-xia-80-za-gong-yu-duan-xian-ling-miao-rong-cuo-41h8"&gt;實測 NVIDIA Switchyard 疊加 PAIR：雙層混合推論架構&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>ai</category>
      <category>nvidia</category>
      <category>devops</category>
      <category>cloud</category>
    </item>
    <item>
      <title>自訓練Unsloth決策模型讓 CVE 漏洞分流</title>
      <dc:creator>JH5</dc:creator>
      <pubDate>Tue, 20 Oct 2026 09:44:19 +0000</pubDate>
      <link>https://dev.to/jh5_pulse/zi-xun-lian-unslothjue-ce-mo-xing-rang-cve-lou-dong-fen-liu-1d21</link>
      <guid>https://dev.to/jh5_pulse/zi-xun-lian-unslothjue-ce-mo-xing-rang-cve-lou-dong-fen-liu-1d21</guid>
      <description>&lt;p&gt;前兩篇我們聊過 &lt;a href="https://dev.to/jh5_pulse/vllm-decision-30-di-duan-shi-ce-45io"&gt;vLLM Decision 3.0 地端實測&lt;/a&gt; 與 &lt;a href="https://dev.to/jh5_pulse/lai-xun-lian-zi-ji-de-jev-mo-xing-ba--g4l"&gt;來訓練自己的 Jev 模型吧：)&lt;/a&gt;，大家對 Jev 與非自回歸決策架構應該都不陌生了。&lt;/p&gt;

&lt;p&gt;但回到日常開發的現場，痛點往往更現實：每次 GitLab CI 或 GitHub Actions 跑完 Trivy 容器掃描，吐出一整大坨 CVE 清單，如果無腦拿去餵一般 LLM，寫一堆「請輸出包含 severity、attack_vector、remediation_sla 的 JSON 格式」，後果通常很慘烈。&lt;/p&gt;

&lt;p&gt;當模型收到文字要先跑 Prefill，接著解碼 token 吐括號、鍵值和雙引號，而遇到新漏洞沒有明確 Patch 時，模型常在解碼階段胡思亂想，直接把下游的 Webhook 或自動化腳本炸爛。&lt;/p&gt;

&lt;h2&gt;
  
  
  設計決策目標
&lt;/h2&gt;

&lt;p&gt;這次選用的標準資料集是美國國家漏洞資料庫的 &lt;code&gt;harinpurumandla/cve-severity-dataset&lt;/code&gt;，收錄超過 15 萬筆資料。每筆資料包含原始 CVE 描述與標準 CVSS v3.1 向量字串（例如 &lt;code&gt;CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H&lt;/code&gt;）。&lt;/p&gt;

&lt;p&gt;我們寫了一套專屬的 CVSS 解析邏輯，直接從向量欄位抓取特徵，並將整體分類任務拆解為 3 個工程維運決策頭：&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;嚴重度分類 (&lt;code&gt;severity&lt;/code&gt;)&lt;/strong&gt;：&lt;code&gt;critical&lt;/code&gt;、&lt;code&gt;high&lt;/code&gt;、&lt;code&gt;medium&lt;/code&gt;、&lt;code&gt;low&lt;/code&gt; 四個等級。&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;攻擊路徑 (&lt;code&gt;attack_vector&lt;/code&gt;)&lt;/strong&gt;：&lt;code&gt;network&lt;/code&gt;（網路攻擊）、&lt;code&gt;adjacent&lt;/code&gt;（相鄰網路）、&lt;code&gt;local&lt;/code&gt;（本機攻擊）、&lt;code&gt;physical&lt;/code&gt;（實體接觸）。&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;修補 SLA 期限 (&lt;code&gt;remediation_sla&lt;/code&gt;)&lt;/strong&gt;：資安應變中心（SOC）的處理規範，包含 &lt;code&gt;4h_emergency&lt;/code&gt;（4 小時內緊急處置）、&lt;code&gt;24h_hotfix&lt;/code&gt;（24 小時內上熱修補）、&lt;code&gt;next_sprint&lt;/code&gt;（併入下個迭代處理）。&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;把這 3 個欄位封裝成 Decision Head 定義，整個架構就成了標準的多工分類器。模型完全不需要花心力學習怎麼生逗號或引號，只要在潛在空間把注意力集中在描述中的關鍵漏洞 Pattern 即可：&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# 3 個決策頭的題目與選項結構
&lt;/span&gt;&lt;span class="n"&gt;questions&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;severity&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;question&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;What is the severity of this vulnerability?&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;choices&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;critical&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;high&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;medium&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;low&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;attack_vector&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;question&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;What is the attack vector of this CVE?&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;choices&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;network&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;adjacent&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;local&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;physical&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;remediation_sla&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;question&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;What is the remediation SLA policy?&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;choices&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;4h_emergency&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;24h_hotfix&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;next_sprint&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;# 單次 Forward Pass 同步推論 3 個頭（僅 296 ms）
&lt;/span&gt;&lt;span class="n"&gt;prediction&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;FastDecisionModel&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;predict&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;tokenizer&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;state&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;cve_description&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;questions&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;questions&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;# 輸出結果保證合法，包含各頭的信心度分數：
# {
#   "severity": {"label": "critical", "confidence": 0.884},
#   "attack_vector": {"label": "network", "confidence": 0.921},
#   "remediation_sla": {"label": "4h_emergency", "confidence": 0.852}
# }
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  實測單卡訓練
&lt;/h2&gt;

&lt;p&gt;測試硬體是單張 NVIDIA GeForce RTX 3090 24GB，軟體環境為 PyTorch 2.6.0、CUDA 12.4 與 Unsloth 2026.10.3，底層模型挑選 &lt;code&gt;unsloth/Qwen3.5-4B&lt;/code&gt;，載入 4-bit 量化權重，並設定 LoRA rank 16、alpha 16。&lt;/p&gt;

&lt;p&gt;我們從資料庫抽取 1,000 筆作為訓練集，250 筆作為完全沒見過的獨立測試集。在微調前，我們先對驗證集進行 Zero-shot 評估，未訓練的隨機決策頭在 3 個目標上的綜合準確率只有 29.0%，而且 3 個頭同時猜對的機率直接見底掛零。&lt;/p&gt;

&lt;p&gt;訓練過程：&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Step 10: Loss = 1.1505 | Grad Norm = 1.76 | LR = 1.80e-4
Step 20: Loss = 0.8963 | Grad Norm = 1.17 | LR = 1.84e-4
Step 30: Loss = 0.7319 | Grad Norm = 10.32| LR = 1.36e-4
Step 40: Loss = 0.7806 | Grad Norm = 5.99 | LR = 7.51e-5
Step 50: Loss = 0.7162 | Grad Norm = 2.35 | LR = 2.29e-5
Step 60: Loss = 0.6414 | Grad Norm = 1.05 | LR = 1.97e-7
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;整整 60 個 Step 總共只跑了 547.8 秒（約 9.1 分鐘），最驚訝的是訓練過程中的 VRAM 峰值只有 &lt;strong&gt;7.453 GB&lt;/strong&gt;，這也代表可以在同張卡背景掛另一個小模型做監控，VRAM 依然綽綽有餘。&lt;/p&gt;

&lt;p&gt;訓練完成後重新驗證：&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;驗證集總體準確率從 29.0% 暴增到 &lt;strong&gt;75.67%&lt;/strong&gt;，提升 &lt;strong&gt;+46.67%&lt;/strong&gt;。&lt;/li&gt;
&lt;li&gt;3 個決策全部同時命中的比例，直接從 0% 飆升到 &lt;strong&gt;55.0%&lt;/strong&gt;。&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;在完全未參與訓練與校準的 250 筆獨立測試集（Held-out Test Set）上，模型拿到了 &lt;strong&gt;52.67%&lt;/strong&gt; 的準確率，3 個決策頭同時命中率為 26.8%，對於一個只餵了不到 1,000 筆資料、跑不到 10 分鐘的 4B 模型來說，它已經能精準抓出 CVE 描述裡的關鍵攻擊特徵，應該已經很有潛力繼續往下探索了。&lt;/p&gt;

&lt;h2&gt;
  
  
  推論測試
&lt;/h2&gt;

&lt;p&gt;模型訓練出來之後，上不上線完全取決於推論延遲速度。&lt;/p&gt;

&lt;p&gt;我們抽取 50 筆測試案例讓微調後的 Decision Model 推論，因為是單次 Forward Pass 同時算完 3 個分類頭，50 筆全部跑完只花了 14.8 秒，平均每筆樣本耗時 &lt;strong&gt;296.2 毫秒&lt;/strong&gt;。&lt;/p&gt;

&lt;p&gt;為了公平比對，我們載入同樣是 4-bit 量化的 &lt;code&gt;unsloth/Qwen3.5-4B&lt;/code&gt; 標準語言模型（FastLanguageModel），使用系統 Prompt 要求它解析相同 CVE 並輸出乾淨的 JSON 欄位。&lt;/p&gt;

&lt;p&gt;在同樣的GPU上，生成平均產生 60 個 tokens 就花了 &lt;strong&gt;4,076.28 毫秒&lt;/strong&gt;。&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;評測維度&lt;/th&gt;
&lt;th&gt;傳統生成式 LLM (JSON Prompt)&lt;/th&gt;
&lt;th&gt;Unsloth 決策模型 (FastDecisionModel)&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;單次推論延遲&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;4,076.28 ms&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;296.20 ms&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;推論吞吐量 (Throughput)&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;~0.24 筆/秒&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;~3.38 筆/秒&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;訓練 VRAM 峰值&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;~14-16 GB (全量文字微調)&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;7.453 GB (LoRA + 決策頭)&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;結構化保證&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;依賴 Regex 驗證或重試&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;100% 型別與合法值約束&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;輸出內容&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;自回歸生成 token 字串&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;各決策頭 Logits 與信心度數值&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;296 毫秒對 CI/CD 與資安通報意味著什麼？過去每分鐘只能處理 14 筆通報的單卡 Worker，換成決策模型後每分鐘可以消化超過 200 筆。當 Pipeline 掃完幾十個容器映像檔、湧入幾百筆 CVE 需要快速分流時，這 13 倍的差距就是 Pipeline 在 10 秒內跑完跟直接Timeout的差別。&lt;/p&gt;

&lt;h2&gt;
  
  
  執行溫度校準：讓決策頭信心度貼近真實防禦門檻
&lt;/h2&gt;

&lt;p&gt;決策模型還有一個生成式 LLM 難以望其項背的優勢：機率校準。&lt;/p&gt;

&lt;p&gt;生成式模型說「我 90% 確定這是 Critical」，通常只是當下 token 預測機率產生的假象，但決策模型輸出的是標準 Softmax 分佈，這讓我們可以透過驗證集計算溫度係數（Temperature Scaling）來縮放各決策頭的 Logits，讓模型回傳的信心度能真實對應到現實世界的命中機率。&lt;/p&gt;

&lt;p&gt;實測結果滿有趣的，在 250 筆未參與微調的獨立測試集上，校準前的預期校準誤差（ECE, Expected Calibration Error）為 0.1457，但經過 100 筆驗證集算出來後，ECE 反而微幅飄到了 0.1799。&lt;/p&gt;

&lt;p&gt;當驗證集只有 100 筆時，溫度參數容易過度貼合該小樣本的特定邊界，一旦推論到真實分佈稍有偏移的外部分佈（OOD）測試集，就會造成輕微的「過度平滑（Over-smoothing）」，這也告訴我們在正式環境裡，拿來算校準溫度的驗證集規模至少要拉到 500 到 1,000 筆或更多才夠讓表現更穩健。&lt;/p&gt;

&lt;p&gt;不過即使是 0.1799 的水準，也足以讓我們在自動化流程中設定合理的門檻：例如「只有當 severity 信心度超過 0.85 時才自動觸發 PagerDuty 或開 Jira Ticket，其餘降級為人工二次檢核」，避免日常工作被垃圾告警疲勞轟炸。&lt;/p&gt;

&lt;h2&gt;
  
  
  盤點實作踩坑
&lt;/h2&gt;

&lt;p&gt;在將 Qwen3.5 移植為決策模型的過程中，有兩個 Note:&lt;/p&gt;

&lt;p&gt;第一，&lt;strong&gt;&lt;code&gt;ClefDecisionModel&lt;/code&gt; 沒有 &lt;code&gt;.generate()&lt;/code&gt; 方法&lt;/strong&gt;。當你用 &lt;code&gt;FastDecisionModel.from_pretrained()&lt;/code&gt; 載入模型時，Unsloth 會把 Transformer Backbone拔掉底層的 &lt;code&gt;lm_head&lt;/code&gt; 改接 &lt;code&gt;JointClassifierHead&lt;/code&gt;，如果你想在同一個物件上呼叫 &lt;code&gt;.generate()&lt;/code&gt; 測試生成，程式會直接拋出 &lt;code&gt;AttributeError&lt;/code&gt; 錯誤給你看，要進行生成式比對，還是必須另外透過 &lt;code&gt;FastLanguageModel&lt;/code&gt; 載入標準權重。&lt;/p&gt;

&lt;p&gt;第二，&lt;strong&gt;Qwen3.5 的 Processor 輸入格式要求&lt;/strong&gt;。Qwen3.5 預設載入的是多模態的 &lt;code&gt;Qwen2_5_VLProcessor&lt;/code&gt;，在呼叫 Tokenizer 時，如果直接寫 &lt;code&gt;tokenizer(prompt)&lt;/code&gt;，在某些版本的 Hugging Face 套件中，會被誤判成帶有未指定影像特徵的參數，請明確指定關鍵字參數：&lt;code&gt;tokenizer(text=prompt, return_tensors="pt")&lt;/code&gt;，才能保證單純的文字輸入正確被轉換。&lt;/p&gt;

&lt;h2&gt;
  
  
  評估架構選型：高併發 AIOps 該選生成還是決策？
&lt;/h2&gt;

&lt;p&gt;當所有人都在談 Agent、都在想著怎麼讓模型用 Function Calling 寫 JSON 時，我們常常忘了工程的核心是「用最低成本、最快速度、最高可靠度解決問題」。&lt;/p&gt;

&lt;p&gt;文字生成模型適合寫長篇分析、出滲透測試報告，但面對 Trivy 掃出來成百上千筆的 CVE 分流、Log 等級降噪、SRE 告警過濾這些需要確定性的日常雜工，把它們丟進一般的 LLM 根本是大砲打蒼蠅，還很容易給未來的自己挖坑。&lt;/p&gt;

&lt;p&gt;而簡單訓練過後的決策模型，不到 10 分鐘的訓練時間、7.5 GB 的顯卡記憶體，換來的是 296 毫秒的極速反應與 100% 格式合規，在追求吞吐量與極致穩定的 CI/CD 現場，這才是把大模型落地最乾淨、最不折磨人的工程實踐。&lt;/p&gt;

</description>
      <category>devops</category>
      <category>ai</category>
      <category>security</category>
      <category>llm</category>
    </item>
    <item>
      <title>來訓練自己的 Jev 模型吧：)</title>
      <dc:creator>JH5</dc:creator>
      <pubDate>Mon, 19 Oct 2026 14:14:02 +0000</pubDate>
      <link>https://dev.to/jh5_pulse/lai-xun-lian-zi-ji-de-jev-mo-xing-ba--g4l</link>
      <guid>https://dev.to/jh5_pulse/lai-xun-lian-zi-ji-de-jev-mo-xing-ba--g4l</guid>
      <description>&lt;p&gt;覺得在應用中頻繁呼叫 Microsoft-Decision-1 或 Jev 等決策模型 API 太昂貴嗎？在現代的 AI Agent 架構中，高達八成的判斷節點需要的其實是「System 1」的直覺反射，而非傳統語言模型耗時的自回歸生成。&lt;/p&gt;

&lt;p&gt;接下來的文章將完整記錄如何利用手邊的消費級GPU，在本地環境訓練出與微軟同款 Decision Head 架構的 Qwen3.5 決策模型，紀錄完整的訓練流程、A/B 對照組的延遲數據、機率校準表現，以及實際的應用場景，適合不想被雲端 API 綁架、希望在私有環境建立毫秒級高吞吐決策節點的工程師參考。&lt;/p&gt;




&lt;h2&gt;
  
  
  微軟 Microsoft-Decision-1 與 Jev 到底在做什麼
&lt;/h2&gt;

&lt;p&gt;微軟在 2026 年 10 月推出了 Microsoft-Decision-1，號稱決策速度比 GPT-6 快上 35 倍，目前也直接掛在 Azure Foundry 和 OpenRouter 上收費，翻開規格一看，微軟採用的底模其實就是阿里巴巴開源的 Qwen3.5-9B，把開源底座加上分類訓練結果直接開賣，在商業上的手腳超快。&lt;/p&gt;

&lt;p&gt;就想我們上一篇提到的，&lt;a href="https://dev.to/jh5_pulse/vllm-decision-30-di-duan-shi-ce-45io"&gt;vLLM Decision 3.0 地端實測&lt;/a&gt;，&lt;br&gt;
過去我們要把一段 Log 或工單分類，標準做法是寫一段長長的 Prompt，請模型「請只回傳 JSON 格式 &lt;code&gt;{"category": "billing"}&lt;/code&gt;」，接著祈禱它不要加上 markdown 語法，然後在應用端用 Pydantic 或正規表達式硬解，一個二選一的問題，模型在背後自回歸吐了數十到數百個 token，動輒花費數秒，偶爾還會吐出格式炸裂的字串導致系統噴錯。&lt;/p&gt;

&lt;p&gt;決策模型走的則是完全相反的路線。它代表的是認知架構裡的「System 1」— 直覺反射神經。&lt;/p&gt;

&lt;p&gt;傳統語言模型在最後一層要將隱藏狀態投影到高達 15 萬維度（Vocab Size 約 152,064）的詞表空間，計算成本極為昂貴，而像 TypeSafe AI 的 Jev、Cloudflare 的 Clef，或是 Unsloth 這次整合的 Decision Head，是把 Sequence 的最後隱藏狀態抓出來做 Pooling，直接接上一組精簡的 Decision Head 再做一次 Forward Pass，幾百個維度的選項機率就全部算完了，推論過程根本不需要 decoding 迴圈。&lt;/p&gt;


&lt;h2&gt;
  
  
  24GB VRAM 微調
&lt;/h2&gt;

&lt;p&gt;我拿手邊這台有 24GB VRAM 的機器來進行完整訓練與驗證。&lt;/p&gt;

&lt;p&gt;底模選擇 &lt;code&gt;unsloth/Qwen3.5-4B&lt;/code&gt;，搭配 4-bit 量化與 LoRA（rank=16, alpha=16），資料集採用開源決策基準 &lt;code&gt;LocalLLaMA/typed-decisions&lt;/code&gt;，包含 1,120 筆訓練樣本、80 筆驗證樣本以及 400 筆獨立測試樣本。&lt;/p&gt;

&lt;p&gt;訓練與驗證的核心數據如下：&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;指標項目&lt;/th&gt;
&lt;th&gt;基準數據 / 實測結果&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;底模與量化&lt;/td&gt;
&lt;td&gt;Qwen3.5-4B (4-bit QLoRA)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;訓練峰值 VRAM&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;7.95 GB&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;訓練耗時&lt;/td&gt;
&lt;td&gt;910.6 秒（約 15 分鐘）&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;零樣本初始準確率&lt;/td&gt;
&lt;td&gt;30.5%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;訓練後驗證集準確率&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;80.5%&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;400 筆未見測試集準確率&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;74.9%&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;期望校準誤差（ECE）&lt;/td&gt;
&lt;td&gt;0.187 → &lt;strong&gt;0.036&lt;/strong&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;單次前向傳播平均延遲&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;191.4 ms&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;VRAM 的花費滿省的，4B 模型在 4-bit 狀態下，整趟訓練跑完 VRAM 最高峰值只有 7.95 GB，換算一下微軟採用的 Qwen3.5-9B 的 base Model，換算下來 VRAM 大概落在 14 到 16 GB 之間，如果手邊機器資源允許的話也可以上9B模型。&lt;/p&gt;


&lt;h2&gt;
  
  
  對照推論速度
&lt;/h2&gt;

&lt;p&gt;雖然知道決策模型一定快，但是為了驗證「到底快了多少」，我在相同的 GPU 上進行了嚴格的 A/B 測試，一邊用傳統 Prompt 叫 Qwen3.5-4B 吐 JSON，另一邊用微調後的 Decision Head 進行測試。&lt;/p&gt;

&lt;p&gt;實測數據差距：&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;對比項目&lt;/th&gt;
&lt;th&gt;傳統生成式 Prompt&lt;/th&gt;
&lt;th&gt;決策模型（Decision Head）&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;平均推論延遲&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;
&lt;strong&gt;3,679.8 ms&lt;/strong&gt;（約 3.7 秒）&lt;/td&gt;
&lt;td&gt;
&lt;strong&gt;191.4 ms&lt;/strong&gt;（0.19 秒）&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;運算機制&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;逐 Token 生成（耗損 64 tokens）&lt;/td&gt;
&lt;td&gt;單次 Forward Pass&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;格式可靠性&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;頻繁冒出 &lt;code&gt;&amp;lt;think&amp;gt;&lt;/code&gt; 思考鏈、未完結&lt;/td&gt;
&lt;td&gt;保證 100% 符合 JSON 格式&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;信心度資訊&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;無&lt;/td&gt;
&lt;td&gt;自帶校準機率分佈向量&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;在測試傳統生成式模型時，新一代推理模型甚至在 Prompt 中自動冒出 &lt;code&gt;&amp;lt;think&amp;gt;&lt;/code&gt; 思考標籤，寫到一半就撞上 &lt;code&gt;max_tokens&lt;/code&gt; 限制，根本連 JSON 閉合括號都沒吐出來。而決策模型在 191 ms 內就交出乾淨的機率字典。&lt;/p&gt;


&lt;h2&gt;
  
  
  壓測多元任務並行
&lt;/h2&gt;

&lt;p&gt;由於現實的情境通常沒那麼單純，我整理了幾種情況來測試它在多任務擴展與面對異常資料時的表現。&lt;/p&gt;
&lt;h3&gt;
  
  
  1. 多題擴展邊際成本：每題僅多 16 ms
&lt;/h3&gt;

&lt;p&gt;在很多場景中，我們常希望同一段文字能同時回答多個問題（例如同時判斷「負責組別」與「緊急程度」）。&lt;/p&gt;

&lt;p&gt;實測推論延遲的拆解結果：&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;單一問題（只問 team）&lt;/strong&gt;：平均 &lt;strong&gt;175.28 ms&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;雙重問題（同時問 team + priority）&lt;/strong&gt;：平均 &lt;strong&gt;191.35 ms&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;多問一個問題的邊際耗時&lt;/strong&gt;：&lt;strong&gt;16.07 ms&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;主要原因還是因為整個context的 Backbone 特徵編碼只需要算一次，後面掛載的 Decision Head 只是非常輕量級的線性投影，這也意味著就算一次掛載 5 個分類判斷（組別、急迫性、情感、PII 洩漏、語言），推論延遲頂多增加 60 到 80 ms。&lt;/p&gt;
&lt;h3&gt;
  
  
  2. 面對無關垃圾訊息與歧義的機率反應
&lt;/h3&gt;

&lt;p&gt;當我們丟入完全不相干的文字（例如抒情詩句「秋風穿過月光下的金黃落葉」）時，模型會亂問亂答嗎？&lt;/p&gt;

&lt;p&gt;實測顯示，模型的最高信心度直接從原本的 99.9% 暴跌至 &lt;strong&gt;54.3%&lt;/strong&gt;，機率被分散到各個選項中（billing 15.7%、technical_support 30.0%、account_management 54.3%）。&lt;/p&gt;

&lt;p&gt;這個結果剛好可以用簡單的門檻值過濾異常輸入，避免LLM服務上線時被拿來亂戳亂打。&lt;/p&gt;


&lt;h2&gt;
  
  
  驗證跨領域場景
&lt;/h2&gt;

&lt;p&gt;訓練完成後，我挑了兩個跨領域的實際情境來踹踹&lt;/p&gt;
&lt;h3&gt;
  
  
  情境一：高爭議客服工單路由
&lt;/h3&gt;

&lt;p&gt;輸入情境：&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"Hi, I was charged twice for invoice #4411. Please refund the duplicate transaction today."&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;模型輸出結果：&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"team"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"choice"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"choice"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"billing"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"confidence"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;0.9997&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"probabilities"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"billing"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;0.9997&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"technical_support"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;0.0001&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"account_management"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;0.0002&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"priority"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"choice"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"choice"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"high"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"confidence"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;0.8931&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"probabilities"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"high"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;0.8931&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"medium"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;0.1053&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"low"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;0.0016&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;模型毫不猶豫地給出 99.97% 的 billing 機率，並且把牽涉到重複扣款的問題評定為 89.31% 的 high priority。&lt;/p&gt;

&lt;h3&gt;
  
  
  情境二：生物資訊管線次世代定序（NGS）品質異常警報
&lt;/h3&gt;

&lt;p&gt;在我們的基因檢測分析管線中，定序批次的品質檢測往往需要工程師人工看圖判斷。我給了模型一段真實的品質異常描述：&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"Sample HG002 WGS sequencing run finished. FastQC reports mean Phred score Q18 at read cycle 120-150, duplication rate 42%, GC content abnormal spike at 65%. DeepVariant call rate dropped by 28%."&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;要求模型給出處置動作與風險評估：&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"action"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"choice"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"choice"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"manual_bioinfo_review"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"confidence"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;0.7721&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"probabilities"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"resequence"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;0.2215&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"manual_bioinfo_review"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;0.7721&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"pass_to_pipeline"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;0.0063&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"risk_level"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"choice"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"choice"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"moderate"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"confidence"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;0.847&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"probabilities"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"critical"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;0.1527&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"moderate"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;0.847&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"low"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;0.0002&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;這個結果滿有意思的，模型沒有直接放行（pass 機率只有 0.63%），但也沒有武斷地要求重跑，而是給出 77.21% 的信心度要求人為介入複查。&lt;/p&gt;




&lt;h2&gt;
  
  
  專模專用的 System 1 架構
&lt;/h2&gt;

&lt;p&gt;過去兩年，我們習慣依賴大型語言模型解決「複雜邏輯推理」與「表達」的問題。但回到真實的系統架構中，每天成千上萬次的意圖路由、資安過濾或狀態判斷，需要的只是快、準、省資源的「條件反射」。&lt;/p&gt;

&lt;p&gt;在我的實測經驗中，如果系統每天需要吞吐大量決策，完全不值得承擔雲端 API 的 Token 費用與動輒數百毫秒的網路延遲。只要有一張消費級顯卡，我們就能在本地端完成 Decision Head 訓練與部署。特別是對於需要處理機敏資料或病患資訊（如前述的基因定序品質檢測）的場景，資料不落地且自帶機率信心度的決策模型，才是企業級 AI 應用真正具備高性價比的架構選擇。&lt;/p&gt;

</description>
      <category>llm</category>
      <category>qwen</category>
      <category>machinelearning</category>
      <category>ai</category>
    </item>
    <item>
      <title>vLLM Decision 3.0 地端實測</title>
      <dc:creator>JH5</dc:creator>
      <pubDate>Mon, 19 Oct 2026 13:19:50 +0000</pubDate>
      <link>https://dev.to/jh5_pulse/vllm-decision-30-di-duan-shi-ce-45io</link>
      <guid>https://dev.to/jh5_pulse/vllm-decision-30-di-duan-shi-ce-45io</guid>
      <description>&lt;p&gt;讓 LLM 做分類或路由判斷時，是不是也常常等待 JSON 慢慢吐字，甚至有時候還會遇到格式解析失敗？&lt;/p&gt;

&lt;p&gt;vLLM 官方 Semantic Router 專案近期推出的 Decision 3.0 (d3) 打破了這個痛點，作為一款開源的多模態基礎決策模型，它的最大特色是「完全不生成文字」，而是直接在單次 Forward Pass 中輸出 Choice、Yes/No 與 Score 的校準機率分佈，這不僅免去了文字生成的延遲，更徹底根絕了格式錯誤的問題。&lt;/p&gt;

&lt;p&gt;下面的文章我們將實測如何在單張 24GB VRAM 的地端環境中，利用 d3 解決 DevOps 事故自動分流，甚至挑戰高難度的醫療影像結構化判斷。&lt;/p&gt;

&lt;h2&gt;
  
  
  24GB VRAM 扛得住嗎？
&lt;/h2&gt;

&lt;p&gt;在模型選擇時，發現 27B 模型原生 BF16 權重高達 52.2 GB，我的24G VRAM 一定是ＧＧ，不過透過 &lt;code&gt;bitsandbytes&lt;/code&gt; 動態掛載為 4-bit NF4 量化，也成功將它塞進單張 24GB 的 VRAM 裏。&lt;/p&gt;

&lt;p&gt;實測記錄下來的真實硬體開銷如下：&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;指標&lt;/th&gt;
&lt;th&gt;9B (&lt;code&gt;d3-flash&lt;/code&gt;)&lt;/th&gt;
&lt;th&gt;27B (&lt;code&gt;d3&lt;/code&gt; 原版)&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;運行精度&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;原生 BF16&lt;/td&gt;
&lt;td&gt;BitsAndBytes 4-bit (NF4)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;磁碟快取空間&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;14.9 GB&lt;/td&gt;
&lt;td&gt;52.2 GB&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;冷啟動載入時間&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;4.51 秒&lt;/td&gt;
&lt;td&gt;15.49 秒&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;GPU VRAM 佔用&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;15.64 GB&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;14.33 GB&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;文字 3 題並行延遲&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;239.5 ms&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;808.6 ms&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;CXR 高解析影像延遲&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;~2,500 ms&lt;/td&gt;
&lt;td&gt;~5,900 ms&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;8 秒影片裁判延遲&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;~1,900 ms&lt;/td&gt;
&lt;td&gt;~5,000 ms&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;實測數據中最反直覺的亮點在於 VRAM 佔用：27B 透過 4-bit 量化後（14.33 GB），居然比 9B 原生 BF16（15.64 GB）還要低。不過，代價反映在運算成本上，27B 的推論耗時約 808 毫秒，比 9B 慢了 3 倍。但若對比傳統 27B LLM 動輒數秒的生成延遲，這樣的回應速度在決策任務上依然極具優勢。&lt;/p&gt;

&lt;h2&gt;
  
  
  DevOps 實戰：CI/CD 事故自動診斷與分流
&lt;/h2&gt;

&lt;p&gt;我們挑選了現代軟體工程中最常造成工程師半夜驚醒的四個具體維運情境，讓兩顆模型同時回答一組結構化問題。&lt;/p&gt;

&lt;h3&gt;
  
  
  1. 案例：CI/CD 建置失敗自動診斷（Sidecar 連線逾時）
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;輸入情境&lt;/strong&gt;：GitLab CI 跑測試時失敗，Log 結尾顯示 &lt;code&gt;Error: connect ECONNREFUSED 127.0.0.1:5432&lt;/code&gt; 與 &lt;code&gt;postgres service failed to start within 30s&lt;/code&gt;，但本次 PR 僅修改前端 CSS 按鈕樣式。&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;模型判斷&lt;/strong&gt;：

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;故障歸因&lt;/strong&gt;：9B 與 27B 皆以 99.9% 機率精準圈選 &lt;code&gt;dependency_service_timeout&lt;/code&gt;，沒有誤判為程式碼錯誤。&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;是否安全重試（Yes/No）&lt;/strong&gt;：9B 給出 94.06% YES，27B 給出 &lt;strong&gt;98.35% YES&lt;/strong&gt;。&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;阻擋等級&lt;/strong&gt;：兩者皆正確評定為 &lt;code&gt;Feature PR Branch&lt;/code&gt;，未引發虛驚。&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;兩者皆可以判別這是常見的依賴容器delay start，直接自動Retry 即可解，無需人為介入。&lt;/p&gt;

&lt;h2&gt;
  
  
  多模態極限測試：胸部 X 光急診分流盲測
&lt;/h2&gt;

&lt;p&gt;多模態是 Decision 3.0 最具威脅性的戰場，我們給了 4 張不同臨床特徵的真實胸部 X 光片，要求模型同步輸出「影像診斷分類（Choice）」、「急性危急生命指標（Noul）」與「門診急診分流佇列等級（Score 3 級：Routine / Urgent / STAT）」。&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;CXR 案例&lt;/th&gt;
&lt;th&gt;9B (&lt;code&gt;d3-flash&lt;/code&gt;) 判定結果&lt;/th&gt;
&lt;th&gt;27B (&lt;code&gt;d3&lt;/code&gt; 4-bit) 判定結果&lt;/th&gt;
&lt;th&gt;臨床分流深度觀察&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;strong&gt;案例 1：正常常規胸片&lt;/strong&gt;&lt;br&gt;&lt;code&gt;cxr_normal.png&lt;/code&gt; (4.2MB)&lt;/td&gt;
&lt;td&gt;• 診斷：&lt;code&gt;normal_clear&lt;/code&gt; (98.33%)&lt;br&gt;• 急診：&lt;strong&gt;NO&lt;/strong&gt; (0.24%)&lt;br&gt;• 分流：&lt;code&gt;Routine&lt;/code&gt; (99.52%)&lt;br&gt;• 耗時：2,651 ms&lt;/td&gt;
&lt;td&gt;• 診斷：&lt;code&gt;normal_clear&lt;/code&gt; (97.73%)&lt;br&gt;• 急診：&lt;strong&gt;NO&lt;/strong&gt; (0.34%)&lt;br&gt;• 分流：&lt;code&gt;Routine&lt;/code&gt; (99.64%)&lt;br&gt;• 耗時：6,054 ms&lt;/td&gt;
&lt;td&gt;兩者皆零誤報，無症狀常規體檢胸片完全不佔用急診資源。&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;strong&gt;案例 2：急性氣胸&lt;/strong&gt;&lt;br&gt;&lt;code&gt;cxr_pneumothorax.jpg&lt;/code&gt; (1.2MB)&lt;/td&gt;
&lt;td&gt;• 診斷：&lt;code&gt;pneumothorax&lt;/code&gt; (99.66%)&lt;br&gt;• 急診：&lt;strong&gt;YES&lt;/strong&gt; (94.02%)&lt;br&gt;• 分流：&lt;code&gt;STAT&lt;/code&gt; (88.46%)&lt;br&gt;• 耗時：2,430 ms&lt;/td&gt;
&lt;td&gt;• 診斷：&lt;code&gt;pneumothorax&lt;/code&gt; (99.90%)&lt;br&gt;• 急診：&lt;strong&gt;YES&lt;/strong&gt; (97.81%)&lt;br&gt;• 分流：&lt;code&gt;STAT&lt;/code&gt; (&lt;strong&gt;98.79%&lt;/strong&gt;)&lt;br&gt;• 耗時：5,951 ms&lt;/td&gt;
&lt;td&gt;
&lt;strong&gt;27B 的決策果斷很多&lt;/strong&gt;。9B 分流時留了 11.33% 機率在 Urgent，而 27B 直接以 98.79% 壓倒性機率觸發紅燈 STAT 廣播。&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;strong&gt;案例 3：大葉性肺炎&lt;/strong&gt;&lt;br&gt;&lt;code&gt;cxr_lobar_pneumonia.jpg&lt;/code&gt; (3.2MB)&lt;/td&gt;
&lt;td&gt;• 診斷：&lt;code&gt;lobar_pneumonia&lt;/code&gt; (99.65%)&lt;br&gt;• 急診：&lt;strong&gt;YES&lt;/strong&gt; (92.62%)&lt;br&gt;• 分流：&lt;code&gt;Urgent&lt;/code&gt; (63.74%) / STAT (35.74%)&lt;br&gt;• 耗時：2,509 ms&lt;/td&gt;
&lt;td&gt;• 診斷：&lt;code&gt;lobar_pneumonia&lt;/code&gt; (97.98%)&lt;br&gt;• 急診：&lt;strong&gt;YES&lt;/strong&gt; (81.81%)&lt;br&gt;• 分流：&lt;code&gt;Urgent&lt;/code&gt; (&lt;strong&gt;90.28%&lt;/strong&gt;) / STAT (6.65%)&lt;br&gt;• 耗時：5,992 ms&lt;/td&gt;
&lt;td&gt;
&lt;strong&gt;臨床階層認知的明顯落差&lt;/strong&gt;。大葉性肺炎需當日住院抗生素治療（Urgent），但不至於像張力性氣胸需立即插胸管（STAT）。9B 出現 35.74% 誤分流到 STAT，27B 則以 90.28% 準確分流至 Urgent。&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;strong&gt;案例 4：心律調節器導線&lt;/strong&gt;&lt;br&gt;&lt;code&gt;cxr_pacemaker_leads.jpg&lt;/code&gt; (48KB)&lt;/td&gt;
&lt;td&gt;• 診斷：&lt;code&gt;pacemaker_implant&lt;/code&gt; (99.26%)&lt;br&gt;• 急診：&lt;strong&gt;NO&lt;/strong&gt; (1.42%)&lt;br&gt;• 分流：&lt;code&gt;Routine&lt;/code&gt; (97.94%)&lt;br&gt;• 耗時：545 ms&lt;/td&gt;
&lt;td&gt;• 診斷：&lt;code&gt;pacemaker_implant&lt;/code&gt; (98.85%)&lt;br&gt;• 急診：&lt;strong&gt;NO&lt;/strong&gt; (4.29%)&lt;br&gt;• 分流：&lt;code&gt;Routine&lt;/code&gt; (75.36%)&lt;br&gt;• 耗時：1,556 ms&lt;/td&gt;
&lt;td&gt;小圖（48KB）視覺 patch 數量少，推論速度翻倍，且兩者均精確辨識植入物並排除急性氣胸。&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;




&lt;h2&gt;
  
  
  落地部署建議：非對稱的雙層防禦架構
&lt;/h2&gt;

&lt;p&gt;如果在地端的VRAM資源有限，又想要把這兩顆模型都部署到開發或產品環境裡，分工邏輯非常明確：高頻即時與第一線守門直接選 &lt;strong&gt;9B BF16&lt;/strong&gt;，文字決策約 240 毫秒、多模態影像約 2 秒、VRAM 佔用 15.6 GB，掛在 CI/CD Webhook、內部 Slack Bot 或前台影像上傳當做第一道篩檢守衛，完全不會拖慢系統回應。&lt;/p&gt;

&lt;p&gt;而關鍵防線與高風險門禁則交給 &lt;strong&gt;27B 4-bit&lt;/strong&gt;，文字決策約 800 毫秒、多模態影像約 5 到 6 秒，VRAM 反而只吃 14.3 GB，如果當遇到線上漏洞評級、資料庫Migrate變更、或是涉及臨床醫療分流（如區分氣胸 STAT 與肺炎 Urgent）時，27B 對微小線索的洞察力與嚴謹度顯著優於 9B，甚至資源夠時，也可以略過量化的步驟。&lt;/p&gt;

&lt;p&gt;Decision 3.0 的出現，為需要低延遲、高穩定性的結構化決策場景提供了一個極佳的開源方案，讓我們能在有限的地端算力下，打造出兼具速度與準確度的企業級 Agent 路由中樞。&lt;/p&gt;

&lt;p&gt;你目前在 DevOps 或 MLOps 流程中，也有遇到 LLM 輸出不穩定或 API 延遲過高的痛點嗎？歡迎在留言區分享你的看法。&lt;/p&gt;

</description>
      <category>ai</category>
      <category>devops</category>
      <category>llm</category>
      <category>mlops</category>
    </item>
    <item>
      <title>免費的 Colab CLI A100/H100 真香 :)</title>
      <dc:creator>JH5</dc:creator>
      <pubDate>Tue, 13 Oct 2026 07:56:52 +0000</pubDate>
      <link>https://dev.to/jh5_pulse/mian-fei-de-colab-cli-a100h100-zhen-xiang--3dhk</link>
      <guid>https://dev.to/jh5_pulse/mian-fei-de-colab-cli-a100h100-zhen-xiang--3dhk</guid>
      <description>&lt;p&gt;前幾天同事在 Slack 丟了 AIPostHub 那篇 &lt;a href="https://www.aiposthub.com/google-ai-pro-colab-a100-80gb-gemma-experiments/" rel="noopener noreferrer"&gt;Google AI Pro 加入 Colab 算力：A100 80GB 能讓 Gemma 實驗走多遠？&lt;/a&gt;，大家都在討論手上訂閱的 Google AI Pro 到底能不能拿來當臨時運算節點。畢竟在Lab平常腳邊只有 24 GB VRAM，平常測 26B 或 31B 模型 VRAM 塞到 20.7 GB 就快見底，稍微放長一點的 Prompt 就容易 OOM。&lt;/p&gt;

&lt;p&gt;剛好手上有訂閱，決定直接拿本地主機連上去，從認證、實例開立到模型載入，把整個真實工作流徹底測過一遍。&lt;/p&gt;




&lt;h2&gt;
  
  
  拆解 CLI 雙胞胎
&lt;/h2&gt;

&lt;p&gt;在本地終端機想要自動化調度 Colab，第一個最常踩的巨雷就是套件名稱。&lt;/p&gt;

&lt;p&gt;PyPI 上有一個老套件叫 &lt;code&gt;colab-cli&lt;/code&gt;（版本 2.2.5），如果你下了 &lt;code&gt;pip install colab-cli&lt;/code&gt;，它會把環境裡的 &lt;code&gt;click&lt;/code&gt; 降級到 7.1.2，當場套件依賴衝突直接翻車。翻一下它的原始碼就知道，它只是幾年前包了 &lt;code&gt;pydrive&lt;/code&gt; 的上傳小工具，只能把本地 &lt;code&gt;.ipynb&lt;/code&gt; 同步到 Google Drive 再幫你開瀏覽器分頁，根本沒有遠端調用 GPU 的能力。&lt;/p&gt;

&lt;p&gt;真正的官方工具是 Google 在 2026 年推出的 &lt;strong&gt;&lt;code&gt;google-colab-cli&lt;/code&gt;&lt;/strong&gt;（最新版本 0.7.4，執行檔名稱為 &lt;code&gt;colab&lt;/code&gt;，要求 Python 3.12+）：&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# 用 uv 安裝官方 CLI&lt;/span&gt;
uv tool &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;--python&lt;/span&gt; 3.12 google-colab-cli
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;安裝完成後敲 &lt;code&gt;colab --help&lt;/code&gt;，你會看到包括 &lt;code&gt;colab new&lt;/code&gt;、&lt;code&gt;colab exec&lt;/code&gt;、&lt;code&gt;colab ssh&lt;/code&gt;、&lt;code&gt;colab usage&lt;/code&gt;、&lt;code&gt;colab log&lt;/code&gt;、&lt;code&gt;colab run&lt;/code&gt; 在內的整套現代管理指令。&lt;/p&gt;




&lt;h2&gt;
  
  
  接軌官方工具：google-colab-cli 搞定 OAuth 與 A100 實例
&lt;/h2&gt;

&lt;p&gt;第一次使用時，執行 &lt;code&gt;colab usage&lt;/code&gt; 會觸發 Google OAuth 授權流程。終端機會印出一串 Google 帳號授權 URL，用瀏覽器打開、登入訂閱了 Google AI Pro 的帳號並核准權限後，把網頁上的授權碼貼回終端機：&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Enter the authorization code: 4/0AXlqoi4...
Current balance: 200.00 compute units
Usage rate: 0.00/hr
Active assignments: 0
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Google AI Pro 帳號直接帶入 &lt;strong&gt;200.00 點運算單元（Compute Units）&lt;/strong&gt;。&lt;/p&gt;

&lt;p&gt;接著直接下一行指令，在背景向 Google 要求一台 A100 執行個體：&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;colab new &lt;span class="nt"&gt;--session&lt;/span&gt; gemma-test &lt;span class="nt"&gt;--gpu&lt;/span&gt; A100
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;只花了大約 5 秒鐘，終端機就回傳 &lt;code&gt;[colab] Session READY.&lt;/code&gt;。&lt;/p&gt;




&lt;h2&gt;
  
  
  實測 Gemma 4 推論：100% GPU 卸載飆出 179 tok/s
&lt;/h2&gt;

&lt;p&gt;A100 是 NVIDIA 專為高負載計算設計的加速卡，特點是具備極高的記憶體頻寬與張量核心算力，能讓大規模語言模型維持全 GPU 卸載執行。&lt;/p&gt;

&lt;p&gt;我們透過 &lt;code&gt;colab exec&lt;/code&gt; 直接在遠端實例部署 Ollama，並拉取參數量達 25.8B 的 &lt;code&gt;gemma4:26b&lt;/code&gt;（GGUF Q4_K_M，檔案 17.9 GB）進行臨床變異推論測試。&lt;/p&gt;

&lt;p&gt;在 Colab A100 上的實際執行數據如下：&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# 查詢遠端實例 VRAM 分佈&lt;/span&gt;
nvidia-smi &lt;span class="nt"&gt;--query-gpu&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;name,memory.total,memory.used &lt;span class="nt"&gt;--format&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;csv
&lt;span class="c"&gt;# 輸出：NVIDIA A100-SXM4-40GB, 40960 MiB, 20072 MiB&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;模型順利吃下 &lt;strong&gt;20,072 MiB VRAM&lt;/strong&gt;，達到 100% GPU 卸載，主機還有 83.5 GB RAM 與超過 20 GB 的 VRAM 緩衝空間。&lt;/p&gt;

&lt;p&gt;我們輸入經典的乳癌基因臨床考題：&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;"What is the role of BRCA1 in breast cancer? Give a 2-sentence clinical summary."&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;模型先觸發內建的思考鏈（Thinking Process）完成約 270 個 tokens 的自我推導，隨後產出結構完整的兩句話臨床結論：&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;BRCA1 is a critical tumor suppressor gene responsible for maintaining genomic stability through the repair of double-strand DNA breaks via homologous recombination. Pathogenic mutations in this gene impair DNA repair mechanisms, significantly increasing the lifetime risk of developing hereditary breast, ovarian, and other related malignancies.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;效能表現相當驚人：&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;生成時間&lt;/strong&gt;：2.16 秒（共產出 369 tokens）&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;生成速度&lt;/strong&gt;：⚡ &lt;strong&gt;179.42 tok/s&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;上下文視窗&lt;/strong&gt;：Ollama 預設分配 32,768 tokens（32K context）&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  盤點即時監控維度：從點數流速到一鍵導出 ipynb
&lt;/h2&gt;

&lt;p&gt;當你的任務正在 Colab 遠端執行時，你還可以透過 CLI 監控健康度與資源消耗：&lt;/p&gt;

&lt;h3&gt;
  
  
  1. 算力與點數計費狀態（&lt;code&gt;colab usage&lt;/code&gt;）
&lt;/h3&gt;

&lt;p&gt;這條指令會回傳帳號層級的點數流速：&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Current balance: 197.28 compute units
Usage rate: 5.30/hr
Active assignments: 1
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;我們從一開始的 200.00 點跑完環境建置、下載 18GB 模型與推論，大約過了 30 分鐘，點數扣至 197.28 點，實際驗證扣款速率確實鎖定在 &lt;strong&gt;5.30 點/小時&lt;/strong&gt;。&lt;/p&gt;

&lt;h3&gt;
  
  
  2. 實例運作狀態（&lt;code&gt;colab status -s gemma-test&lt;/code&gt;）
&lt;/h3&gt;

&lt;p&gt;查詢實例生命週期與最近一次命令執行：&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;[gemma-test] gpu-a100-s-kkb-usc1f1-ryarjq9kw3qd | Hardware: A100 | Shape: Standard | Variant: GPU | Status: IDLE
  Last Execution: stdin at 2026-10-12 08:26:15
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;當任務正在跑時狀態會轉為 &lt;code&gt;RUNNING&lt;/code&gt;，空閒時為 &lt;code&gt;IDLE&lt;/code&gt;。&lt;/p&gt;

&lt;h3&gt;
  
  
  3. 硬體級別監控（&lt;code&gt;colab exec -s gemma-test "nvidia-smi"&lt;/code&gt;）
&lt;/h3&gt;

&lt;p&gt;可以直接撈出 GPU 實體指標：&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;溫度與功耗&lt;/strong&gt;：32°C，待機 47.19W（推論瞬間衝上 180W+，硬體上限 400W）&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;VRAM 分配&lt;/strong&gt;：20,072 MiB / 40,960 MiB（空載時僅佔 6 MiB）&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;主機組態&lt;/strong&gt;：12 個 CPU 邏輯核心、83.47 GB 主機記憶體、235.68 GB NVMe 磁碟空間&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  4. 服務層監控（&lt;code&gt;colab exec -s gemma-test "ollama ps"&lt;/code&gt;）
&lt;/h3&gt;

&lt;p&gt;確認模型是否真正常駐 VRAM：&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;NAME          ID              SIZE      PROCESSOR    CONTEXT    RUNNER
gemma4:26b    001e5dafc3c7    1.2 GB    100% GPU     32768      llamacpp
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Ollama 預設在閒置 5 分鐘後會自動釋放 VRAM，避免背景長駐佔用資源。&lt;/p&gt;

&lt;h3&gt;
  
  
  5. 執行歷史與一鍵導出 Notebook（&lt;code&gt;colab log&lt;/code&gt;）
&lt;/h3&gt;

&lt;p&gt;這是我認為官方 CLI 最強大的功能之一。它在本地紀錄了每次透過 stdin 或檔案丟上去的 microsecond 級別執行日誌。下這行指令：&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;colab log &lt;span class="nt"&gt;-s&lt;/span&gt; gemma-test &lt;span class="nt"&gt;-o&lt;/span&gt; colab_a100_gemma4_replay.ipynb
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;它會直接把這半小時內所有的輸入、輸出、測試日誌自動打平成一份 728 KB 的標準 &lt;code&gt;.ipynb&lt;/code&gt; 檔案。其他人打開就能看見所有 cell 的輸出結果，完全重現實驗。&lt;/p&gt;




&lt;h2&gt;
  
  
  解讀點數與定價機制：Pay As You Go 隨選加購怎麼算
&lt;/h2&gt;

&lt;p&gt;在 Colab 介面點選資源分頁的「深入瞭解」，或者在終端機敲 &lt;code&gt;colab pay&lt;/code&gt;，系統會直接引導你打開官方的 &lt;a href="https://colab.research.google.com/signup?utm_source=resource_tab&amp;amp;utm_medium=link&amp;amp;utm_campaign=payg_learn_more" rel="noopener noreferrer"&gt;Colab 付費方案與定價說明頁面（Colab Paid Services Pricing）&lt;/a&gt;。&lt;/p&gt;

&lt;p&gt;這個頁面說明了 Google 對 Colab 算力的計費哲學：&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Google AI Pro / Colab Pro 訂閱制&lt;/strong&gt;：&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;每月固定配發算力點數（如 Google AI Pro 配發 200 點）。&lt;/li&gt;
&lt;li&gt;解鎖高階硬體配額（A100、TPU v5e 等），並擁有比免費版更高的排隊優先權。&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Pay As You Go（隨選運算單元）加購制&lt;/strong&gt;：&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;當你的 200 點在某個月高強度微調用光時，不需要被綁定更貴的企業合約，可以單次隨選加購點數（100 點約 9.99 美元）。&lt;/li&gt;
&lt;li&gt;加購的運算單元只要帳號有效就不會過期，會自動接在每月的免費額度後面扣除。&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;真實消耗時間折算&lt;/strong&gt;：&lt;br&gt;
依我們這次實測的真實扣點速率（標準 A100 實例每小時扣除 &lt;strong&gt;5.30 點&lt;/strong&gt;）：&lt;br&gt;
&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;   200 點 ÷ 5.30 點/小時 ≈ 37.7 小時
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;連續跑能撐 37.7 小時。如果每一次 Prompt 評測只佔用 20 分鐘，這 200 點足夠支撐超過 100 次完整的推論工作階段。&lt;/p&gt;

&lt;p&gt;最省錢的操作是利用 CLI 提供的 Ephemeral Job Runner：&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;colab run &lt;span class="nt"&gt;-s&lt;/span&gt; gemma-eval &lt;span class="nt"&gt;--gpu&lt;/span&gt; A100 my_benchmark.py
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;這個指令會在雲端開機、跑完腳本、抓回輸出、立刻自動關機釋放，連手動下 &lt;code&gt;colab stop&lt;/code&gt; 都不用，點數一秒鐘都不會多漏。&lt;/p&gt;




&lt;h2&gt;
  
  
  結語與日常建議
&lt;/h2&gt;

&lt;p&gt;「免費的 Colab CLI + A100/H100」是個漂亮的社群包裝，本質上是 Google AI Pro 每月 200 點運算額度的精準變現。&lt;/p&gt;

&lt;p&gt;換算下來每個月能拿來跑約 37.7 小時的 A100 高算力。只要搭配 &lt;code&gt;google-colab-cli&lt;/code&gt; 的自動化指令，配合 &lt;code&gt;colab run&lt;/code&gt; 或跑完隨手 &lt;code&gt;colab stop&lt;/code&gt;，把它當作地端 3090 吃緊時的臨時雲端外掛，就是目前性價比最高的用法。&lt;/p&gt;

</description>
      <category>gemma</category>
      <category>googlecolab</category>
      <category>machinelearning</category>
      <category>llmops</category>
    </item>
    <item>
      <title>「辛苦弄了半天，老闆卻說：這一定是 AI 做的吧？」

這兩年導入 AI 開發，很多人面臨一個荒謬的循環：功勞被 AI 稀釋，但只要有一點小 Bug，責任就被無限放大，被唸說「你是不是都貼 AI 產生的沒檢查？」。

這其實是「AI 功勞歸因偏誤」。旁人只看見 AI 三秒產出程式碼，卻忽略了工程師為了驗證輸出、處理系統特例所花費的龐大心力。過去在白板上的討論與掙扎，現在都被隱藏在跟 AI 的對話框裡了。

身處 AI 時代，我們該如何自處？

#軟體工程 #工程師 #技術管理 #職場溝通 #職涯發展 #AI</title>
      <dc:creator>JH5</dc:creator>
      <pubDate>Wed, 30 Sep 2026 13:14:37 +0000</pubDate>
      <link>https://dev.to/jh5_pulse/xin-ku-nong-liao-ban-tian-lao-ban-que-shuo-zhe-ding-shi-ai-zuo-de-ba-zhe-liang-nian-dao-ru-ai-kai-fa-hen-duo-ren-mian-lin-ge-huang-miu-de-xun-huan-gong-lao-bei-ai-xi-shi-dan-zhi-yao-you-dian-xiao-bugze-ren-jiu-bei-wu-xian-fang-da-bei-nian-shuo-ni-shi-bu-shi-du-tie-ai-ge2</link>
      <guid>https://dev.to/jh5_pulse/xin-ku-nong-liao-ban-tian-lao-ban-que-shuo-zhe-ding-shi-ai-zuo-de-ba-zhe-liang-nian-dao-ru-ai-kai-fa-hen-duo-ren-mian-lin-ge-huang-miu-de-xun-huan-gong-lao-bei-ai-xi-shi-dan-zhi-yao-you-dian-xiao-bugze-ren-jiu-bei-wu-xian-fang-da-bei-nian-shuo-ni-shi-bu-shi-du-tie-ai-ge2</guid>
      <description>&lt;div class="ltag__link--embedded"&gt;
  &lt;div class="crayons-story "&gt;
  &lt;a href="https://dev.to/jh5_pulse/ai-gong-lao-gui-yin-pian-wu-yu-qiu-sheng-fa-2ici" class="crayons-story__hidden-navigation-link"&gt;做得好算 AI 的、做錯算你無腦貼？拆解 AI 功勞歸因偏誤與瑞士刀求生法&lt;/a&gt;


  &lt;div class="crayons-story__body crayons-story__body-full_post"&gt;
    &lt;div class="crayons-story__top"&gt;
      &lt;div class="crayons-story__meta"&gt;
        &lt;div class="crayons-story__author-pic"&gt;

          &lt;a href="/jh5_pulse" class="crayons-avatar  crayons-avatar--l  "&gt;
            &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3550119%2Ff72bed2d-aa8f-4bcc-be09-3f550dd9a7cc.jpg" alt="jh5_pulse profile" class="crayons-avatar__image"&gt;
          &lt;/a&gt;
        &lt;/div&gt;
        &lt;div&gt;
          &lt;div&gt;
            &lt;a href="/jh5_pulse" class="crayons-story__secondary fw-medium m:hidden"&gt;
              JH5
            &lt;/a&gt;
            &lt;div class="profile-preview-card relative mb-4 s:mb-0 fw-medium hidden m:inline-block"&gt;
              
                JH5
                
                
              
              &lt;div id="story-author-preview-content-4774346" class="profile-preview-card__content crayons-dropdown branded-7 p-4 pt-0"&gt;
                &lt;div class="gap-4 grid"&gt;
                  &lt;div class="-mt-4"&gt;
                    &lt;a href="/jh5_pulse" class="flex"&gt;
                      &lt;span class="crayons-avatar crayons-avatar--xl mr-2 shrink-0"&gt;
                        &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3550119%2Ff72bed2d-aa8f-4bcc-be09-3f550dd9a7cc.jpg" class="crayons-avatar__image" alt=""&gt;
                      &lt;/span&gt;
                      &lt;span class="crayons-link crayons-subtitle-2 mt-5"&gt;JH5&lt;/span&gt;
                    &lt;/a&gt;
                  &lt;/div&gt;
                  &lt;div class="print-hidden"&gt;
                    
                      Follow
                    
                  &lt;/div&gt;
                  &lt;div class="author-preview-metadata-container"&gt;&lt;/div&gt;
                &lt;/div&gt;
              &lt;/div&gt;
            &lt;/div&gt;

          &lt;/div&gt;
          &lt;a href="https://dev.to/jh5_pulse/ai-gong-lao-gui-yin-pian-wu-yu-qiu-sheng-fa-2ici" class="crayons-story__tertiary fs-xs"&gt;&lt;time&gt;Sep 30&lt;/time&gt;&lt;span class="time-ago-indicator-initial-placeholder"&gt;&lt;/span&gt;&lt;/a&gt;
        &lt;/div&gt;
      &lt;/div&gt;

    &lt;/div&gt;

    &lt;div class="crayons-story__indention"&gt;
      &lt;h2 class="crayons-story__title crayons-story__title-full_post"&gt;
        &lt;a href="https://dev.to/jh5_pulse/ai-gong-lao-gui-yin-pian-wu-yu-qiu-sheng-fa-2ici" id="article-link-4774346"&gt;
          做得好算 AI 的、做錯算你無腦貼？拆解 AI 功勞歸因偏誤與瑞士刀求生法
        &lt;/a&gt;
      &lt;/h2&gt;
        &lt;div class="crayons-story__tags"&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/career"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;career&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/productivity"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;productivity&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/management"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;management&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/ai"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;ai&lt;/a&gt;
        &lt;/div&gt;
      &lt;div class="crayons-story__bottom"&gt;
        &lt;div class="crayons-story__details"&gt;
            &lt;a href="https://dev.to/jh5_pulse/ai-gong-lao-gui-yin-pian-wu-yu-qiu-sheng-fa-2ici#comments" class="crayons-btn crayons-btn--s crayons-btn--ghost crayons-btn--icon-left flex items-center"&gt;
              

              &lt;span class="hidden s:inline"&gt;Add&amp;nbsp;Comment&lt;/span&gt;
            &lt;/a&gt;
        &lt;/div&gt;
        &lt;div class="crayons-story__save"&gt;
          &lt;small class="crayons-story__tertiary fs-xs mr-2"&gt;
            1 min read
          &lt;/small&gt;
        &lt;/div&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/div&gt;
&lt;/div&gt;

&lt;/div&gt;


</description>
    </item>
    <item>
      <title>KubeSummit 2026 小記</title>
      <dc:creator>JH5</dc:creator>
      <pubDate>Mon, 14 Sep 2026 14:15:09 +0000</pubDate>
      <link>https://dev.to/jh5_pulse/kubesummit-2026-xiao-ji-55cb</link>
      <guid>https://dev.to/jh5_pulse/kubesummit-2026-xiao-ji-55cb</guid>
      <description>&lt;p&gt;上週去了 KubeSummit 2026，每年晃去總會湧現一股「想當年」的懷舊感，腦海中不禁浮現早期為了架設 1.1x 環境而加班的日子，不過也強烈感受到 Kubernetes 生態系已經徹底從早期的微服務調度，全面轉向 AI 工作負載 (AI Workloads) 。&lt;/p&gt;

&lt;p&gt;特別是 Agent AI 跳耀式發展的這兩年，跟平台工程有關的的技術討論收斂非常明顯，稍微記錄一下有聽到＋沒聽到＋有想到的幾個議題。&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;K8s 基礎設施的 M 型化
這兩年來這1-2年來特別是 DRA 的成熟，解決了過去 GPU 資源分配僵化的痛點，對 GPU 切割 (MIG, Time-slicing) 有了更原生的支援，而 eBPF 提供的Observability也幾乎解掉過去網路與資安的不少盲點＆issue。&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;從現場的擺攤的幾家大型地端提供商來看，因為 AI 算力資料不出境、醫療或高科技製造的隱私需求，企業必須在地端自建龐大的 GPU 叢集，而這也促使各大基礎設施廠商快速跟進，提供整合式的 GPU 驅動與監控方案，整體技術成熟度與客戶規模都有著顯著的成長。&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Day 2 維運與 SRE Agent 的實踐&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;面對極度複雜的 Day 2 維運，SRE Agent 成為釋放 Infra 團隊壓力的解方，今年議程中展示了利用類似 ReAct 模式的 Agent 架構來處理系統異常。當開發者遇到 Pod Pending 或 OOM 時，SRE Agent 能自動調用 kubectl 或查詢log/metrics，並用自然語言回覆診斷結果，必要時也可以在規定的namespace內直接動手修復，這種將 LLM 結合工具呼叫 (Tool Calling) 的應用，直接把SRE 升級成高級大人版ＸＤ。&lt;/p&gt;

&lt;p&gt;不過，相比於年中在 CyberSec 看到各大廠積極推展的 SIEM Agent，K8s 領域的 SRE Agent 實際落地的企業案例在體感上似乎相對較少，這點值得持續觀察。&lt;/p&gt;




&lt;p&gt;也記錄一下一些想聽沒聽到的topic&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Ray Serve + vLLM&lt;br&gt;
雖然 vLLM 已經是 LLMOps 的標配，但在處理大規模、跨節點的分散式推論請求時，滿多blog post 都會推崇 Ray Serve 作為排程與資源分配的上層框架，再結合底層的 vLLM 引擎，這次好像沒有看到類似的分享。&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;企業級地端 LLM Serving 的架構斷層&lt;br&gt;
大家都知道怎麼用 vLLM 把模型跑起來，現場的解決方案商也都有在自己的場次提到可行，但要讓內部開發者享受到類似 Claude 或 GitHub Copilot 的體驗，地端架構在「算力」與「體驗」之間仍存在一層厚厚的斷層。這包含了需要 LiteLLM 來統一 API 與分流任務、上下文管理、RAG 基礎設施，以及完整的工具呼叫層。如果有個support百人團隊的地端 Qwen/Gemma 服務經驗分享，是不是很棒？&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;WebAssembly (Wasm) 與邊緣輕量化&lt;br&gt;
Wasm 比 Container 更極致的微秒級冷啟動速度與沙盒安全性，對於未來需要部署到極端邊緣 (Edge AI) 或是高度要求冷啟動效能的 Serverless 推論場景，Wasm 與 K8s 的深度綁定極具潛力，也十分期待未來能聽到更多相關的實戰技術體驗。&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;




&lt;p&gt;從 Infrastructure as Code 到現今的 AI as a Service，Kubernetes 正在經歷一場本質上的蛻變，它不再只是一個單純的容器調度平台，而是逐漸成為企業級 AI 算力與 Agentic 應用的底層作業系統。&lt;/p&gt;

</description>
      <category>ai</category>
      <category>devops</category>
      <category>kubernetes</category>
      <category>agents</category>
    </item>
    <item>
      <title>用 Vercel AI SDK 玩轉 Chrome Built-in AI</title>
      <dc:creator>JH5</dc:creator>
      <pubDate>Sat, 29 Aug 2026 01:02:59 +0000</pubDate>
      <link>https://dev.to/jh5_pulse/yong-vercel-ai-sdk-wan-zhuan-chrome-built-in-ai-58ln</link>
      <guid>https://dev.to/jh5_pulse/yong-vercel-ai-sdk-wan-zhuan-chrome-built-in-ai-58ln</guid>
      <description>&lt;p&gt;Google 官方關於 Chrome Built-in AI 與 Vercel AI SDK 的文件寫了一大堆，但看完會發現官方範例只教你怎麼印出 Hello World，好多坑都沒有交代。&lt;/p&gt;

&lt;p&gt;如果模型還沒下載完該怎麼辦？瀏覽器不支援時怎麼辦？Tool Calling 的介面要怎麼安全的接上？ 附上在 Chrome上的一些踩坑小筆記，幫你想在前端加上本地 LLM 時少走彎路（雖然彎路的都記得比較久ＸＤ）！&lt;/p&gt;




&lt;h2&gt;
  
  
  官方範例
&lt;/h2&gt;

&lt;p&gt;Google 官方有兩篇基礎教學，繁體中文版都寫得清楚：&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://developer.chrome.com/blog/prompt-api-with-vercel-ai?hl=zh_tw" rel="noopener noreferrer"&gt;Prompt API 搭配 Vercel AI SDK&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://developer.chrome.com/blog/prompt-ui-ai-elements-with-vercel-ai?hl=zh_tw#demo" rel="noopener noreferrer"&gt;使用 AI Elements 打造 UI（含 demo）&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;看完你大概可以了解，可以用&lt;code&gt;browserAI()&lt;/code&gt; 把 model 丟進 &lt;code&gt;generateText&lt;/code&gt;、&lt;code&gt;streamText&lt;/code&gt;、&lt;code&gt;Output.object&lt;/code&gt;，大概 30 行就能跑，但官方範例大多著重在「API 長什麼樣」...&lt;/p&gt;

&lt;h2&gt;
  
  
  @browser-ai/core
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;@browser-ai/core&lt;/code&gt; 是 Chrome Built-in AI 接到 AI SDK 的 provider，特點是同時支援 AI SDK v5-7，且跨三個本地引擎(Prompt API、Transformers.js、WebLLM )共用同一套 API，目前在「瀏覽器本地推理」這個領域已經是最主要的Tool。&lt;/p&gt;

&lt;p&gt;作者是 &lt;a href="https://github.com/jakobhoeg/browser-ai" rel="noopener noreferrer"&gt;jakobhoeg/browser-ai&lt;/a&gt;的 Jakob Hoeg Mørk，2025 年開始維護，進過 Chrome for Developers 的贊助名單，現在掛在 Vercel OSS Program 底下。&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;generateText&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;ai&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;browserAI&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@browser-ai/core&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;generateText&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;model&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;browserAI&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
  &lt;span class="na"&gt;prompt&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Invent a new holiday.&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;當「模型還沒下載」的狀況發生時，&lt;code&gt;availability()&lt;/code&gt; 會回 &lt;code&gt;unavailable&lt;/code&gt;（瀏覽器不支援）或 &lt;code&gt;downloadable&lt;/code&gt;（可以下載），配合 &lt;code&gt;createSessionWithProgress&lt;/code&gt; 我們就能拿到下載百分比，這對于前端無論開發什麼樣的應用，都是給使用者第一層的UX，大部分的首次下載要吞好幾 GB的等待時間。&lt;/p&gt;

&lt;h2&gt;
  
  
  next-hybrid
&lt;/h2&gt;

&lt;p&gt;在 &lt;code&gt;jakobhoeg/browser-ai&lt;/code&gt; 同一個 repo 底下的 &lt;code&gt;examples/next-hybrid&lt;/code&gt; 也滿值得一看的，它比官方範例完整太多，而且目前都是完整的可demo範例，建議可以直接當 template 複製，他也像我們之前測試transformer/webgpu 一樣，同時接了三種引擎（browser / transformers-js / web-llm）也在ＵＩ上做了下拉選單可以即時切換，讓使用者可以同一份 &lt;code&gt;streamText&lt;/code&gt; 程式碼，本地模型、WebGPU 模型、雲端模型切換成整合或是測試。&lt;/p&gt;

&lt;p&gt;有兩個實作細節滿值得整合前端應用的參考的：&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;自訂 ChatTransport 接 &lt;code&gt;useChat&lt;/code&gt;&lt;br&gt;
用 &lt;code&gt;ClientSideChatTransport&lt;/code&gt; 把 React 的 &lt;code&gt;useChat&lt;/code&gt; 綁到本地模型來讓整個聊天流程跑在客戶端，連 server 都不用起，萬一有一天你不想用本地模型了，換回 &lt;code&gt;DefaultChatTransport&lt;/code&gt; 就切到 server API，前端程式碼一行不用改。&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;tool calling 的完整流程&lt;br&gt;
它示範了 &lt;code&gt;webSearch&lt;/code&gt;（用 Exa API）和 &lt;code&gt;getCurrentTime&lt;/code&gt; 兩個 tool，加上 &lt;code&gt;toolApproval&lt;/code&gt; 的確認 UI，如果模型想動用外部 API 前，會先跳出一個確認框讓使用者同意確認，這對安全敏感的醫療或金融企業場景，可以配合紀錄一些符合法規面需求的Audit Log&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  domainstack.io
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fhozib88tc53vywyajrz4.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fhozib88tc53vywyajrz4.png" alt="domainstack demo page" width="799" height="384"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/jakejarvis/domainstack.io" rel="noopener noreferrer"&gt;jakejarvis/domainstack.io&lt;/a&gt; 是目前找得到最接近 production 的案例，而且是少數用 &lt;code&gt;@browser-ai/core&lt;/code&gt; 的第三方專案，它做的是網域名稱查詢工具，雖然串接 AI 只是其中一小部分功能，但架構完整到可以拿來當作範本。&lt;/p&gt;

&lt;p&gt;跟我們前面提到的場域類似，核心設計是三種模式自動切換：&lt;code&gt;local&lt;/code&gt;（本機）、&lt;code&gt;cloud&lt;/code&gt;（雲端）、&lt;code&gt;auto&lt;/code&gt;（本機不可用就 fallback），&lt;code&gt;useBrowserAI&lt;/code&gt; hook 會先查 &lt;code&gt;availability()&lt;/code&gt;，如果瀏覽器不支援就默默的切到雲端 API，對於使用者完全無感。另外它示範了讓本地模型呼叫 tRPC 的 tool（WHOIS、DNS、SSL 查詢），也證明本地 LLM 做 agentic workflow 是可行的，不是只能聊天。&lt;/p&gt;

&lt;h2&gt;
  
  
  實測小小筆記
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;API 只能在安全環境（Secure Context）運行&lt;br&gt;
如果你在 about:blank 測試，window.LanguageModel 會直接回傳 undefined，改到 &lt;a href="http://localhost" rel="noopener noreferrer"&gt;http://localhost&lt;/a&gt; 或 HTTPS 環境下，API 才會正常。&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;模型下載必須由「真實使用者互動」觸發&lt;br&gt;
直接在程式碼初始化呼叫 LanguageModel.create() 會直接報錯：NotAllowedError: Requires a user gesture，這代表不能在頁面載入時自動背景下載，必須由使用者點擊按鈕等主動觸發。因此，如果你用 Headless 測試，必須透過 CDP（Chrome DevTools Protocol）發送 Input.dispatchMouseEvent 來模擬真實的滑鼠點擊事件才可以正常的執行。&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;硬體硬性門檻&lt;br&gt;
在 chrome://on-device-internals 的 Broker State 系統紀錄中，明確標示需要 20480 MiB required，測試時我的 MBA 原本只剩 4.7GB，模型下載停住，直到清出 23GB 空間後，下載狀態才順利轉綠開始執行。&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;




&lt;p&gt;總結來說，Chrome Built-in AI 的核心優勢不在於頂尖的算力或模型表現，而是在於零 API Key 成本、零代管費用，以及資料絕對不出裝置的隱私安全，再搭配 Vercel AI SDK 後，本地模型與雲端 LLM 的切換只需要一行 Provider 設定就可以搞定。&lt;/p&gt;

&lt;p&gt;如果你正準備踹踹，建議路線如下：&lt;/p&gt;

&lt;p&gt;快速驗證：用 browserAI() + generateText，30 行內快速跑通。&lt;/p&gt;

&lt;p&gt;完整架構學習：直接 Fork next-hybrid 當專案骨架。&lt;/p&gt;

&lt;p&gt;生產環境：參考 domainstack.io 的自動 Fallback 策略與 Tool Calling 設計。&lt;/p&gt;

&lt;p&gt;目前整個瀏覽器本地 AI 生態還處於早期階段，大部分開發者都還在摸索，趁現在掌握這些工具與解決方案，就能為你的前端專案搶先整合本地 AI 的優勢！&lt;/p&gt;

</description>
      <category>chrome</category>
      <category>ai</category>
      <category>webdev</category>
      <category>vercel</category>
    </item>
    <item>
      <title>如何用 WebMCP 讓你的網站對 Agent 開放？</title>
      <dc:creator>JH5</dc:creator>
      <pubDate>Thu, 20 Aug 2026 13:52:13 +0000</pubDate>
      <link>https://dev.to/jh5_pulse/ru-he-yong-webmcp-rang-ni-de-wang-zhan-dui-agent-kai-fang--5dbj</link>
      <guid>https://dev.to/jh5_pulse/ru-he-yong-webmcp-rang-ni-de-wang-zhan-dui-agent-kai-fang--5dbj</guid>
      <description>&lt;p&gt;想像一下，未來的 AI Agent 幫你在網頁上訂機票、買東西時，不再需要靠「螢幕截圖 + 猜按鈕」這種網站一改版就崩潰的方式，而是你的網站主動對 Agent 宣告：「我有這些 API，你可以直接呼叫」。&lt;/p&gt;

&lt;p&gt;這就是 W3C 正熱烈討論中的 WebMCP（Web Model Context Protocol）。&lt;/p&gt;

&lt;p&gt;如果說各路大神推出的 MCP 是讓 AI 操作你的「後端伺服器」，那麼 WebMCP 就是讓 AI 直接在「使用者瀏覽器」裡流暢操作 UI 的關鍵最後一哩路，這篇文章會用 Chrome 151 實測，帶你快速掌握宣告式（Declarative）與命令式（Imperative）API 的差異，並透過官方 3 個真實使用者案例，看看工具如何隨頁面動態長出！&lt;/p&gt;




&lt;h2&gt;
  
  
  WebMCP 是什麼?
&lt;/h2&gt;

&lt;p&gt;WebMCP（Web Model Context Protocol）是 W3C 正在討論的網頁標準，核心概念是網站用 JavaScript 或 HTML 註解，向具備代理能力的瀏覽器註冊「工具」，而當 Agent 代理碰到註冊過的工具，就可以直接呼叫相關函式並拿到結構化結果，不用再靠螢幕截圖 + 猜按鈕。&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;MCP 是後端標準，讓代理連到你的伺服器拿資料；WebMCP 是前端標準，讓代理在你開著的這個分頁裡操作 UI&lt;/strong&gt;。&lt;/p&gt;

&lt;p&gt;MCP 的生命週期是永久的（伺服器常駐），而WebMCP 是暫時的（關掉分頁就沒了），在你的服務上如果同時提供了MCP與WebMCP，便可以理解成 MCP 管核心邏輯，WebMCP 管最後一哩的使用者介面處理。&lt;/p&gt;

&lt;h2&gt;
  
  
  宣告式 API：兩個屬性，表單直接變成工具
&lt;/h2&gt;

&lt;p&gt;宣告式 API 是 WebMCP 的最吸引人的部分，你不用寫一行 JavaScript，直接在 &lt;code&gt;&amp;lt;form&amp;gt;&lt;/code&gt; 上加上 &lt;code&gt;toolname&lt;/code&gt; 和 &lt;code&gt;tooldescription&lt;/code&gt;的注記就完成tool的註冊：&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;form&lt;/span&gt; &lt;span class="na"&gt;toolname=&lt;/span&gt;&lt;span class="s"&gt;"createSupportRequest"&lt;/span&gt;
      &lt;span class="na"&gt;tooldescription=&lt;/span&gt;&lt;span class="s"&gt;"Submits a request for customer support."&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;label&lt;/span&gt; &lt;span class="na"&gt;for=&lt;/span&gt;&lt;span class="s"&gt;"name"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;姓名&lt;span class="nt"&gt;&amp;lt;/label&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;input&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"text"&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"name"&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"name"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;label&lt;/span&gt; &lt;span class="na"&gt;for=&lt;/span&gt;&lt;span class="s"&gt;"topic"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;問題類型&lt;span class="nt"&gt;&amp;lt;/label&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;select&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"topic"&lt;/span&gt; &lt;span class="na"&gt;toolparamdescription=&lt;/span&gt;&lt;span class="s"&gt;"決定問題要路由給哪個團隊"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;option&lt;/span&gt; &lt;span class="na"&gt;value=&lt;/span&gt;&lt;span class="s"&gt;"billing"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;帳單問題&lt;span class="nt"&gt;&amp;lt;/option&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;option&lt;/span&gt; &lt;span class="na"&gt;value=&lt;/span&gt;&lt;span class="s"&gt;"tech"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;技術問題&lt;span class="nt"&gt;&amp;lt;/option&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/select&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;button&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"submit"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;送出&lt;span class="nt"&gt;&amp;lt;/button&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/form&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;實測後發現 &lt;code&gt;document.modelContext.getTools()&lt;/code&gt; 會自動把這個表單轉成完整的 JSON Schema——&lt;code&gt;&amp;lt;select&amp;gt;&lt;/code&gt; 的選項變成 &lt;code&gt;anyOf&lt;/code&gt; + &lt;code&gt;enum&lt;/code&gt;，&lt;code&gt;toolparamdescription&lt;/code&gt; ，而 &lt;code&gt;&amp;lt;label&amp;gt;&lt;/code&gt; 的中文文字變成欄位說明，也就是說當Agent 識別到這個 schema 後，就知道這個表單可以填什麼，以及每個欄位接受什麼值。&lt;/p&gt;

&lt;p&gt;進階控制有三個屬性可以玩：&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;toolparamdescription&lt;/code&gt;：單一欄位的用途說明，沒寫就用 &lt;code&gt;&amp;lt;label&amp;gt;&lt;/code&gt; 的文字。&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;toolautosubmit&lt;/code&gt;：加上後，代理呼叫工具會直接提交表單並導航，不用等人按送出。&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;SubmitEvent.agentInvoked&lt;/code&gt;：表單提交時這個布林值會告訴你「這次提交是代理發起的」。搭配 &lt;code&gt;respondWith(Promise)&lt;/code&gt; 可以讓代理拿到非同步的執行結果。&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;另外還有 &lt;code&gt;:tool-form-active&lt;/code&gt; 和 &lt;code&gt;:tool-submit-active&lt;/code&gt; 兩個 CSS pseudo-class，讓代理在填表單時可以用來顯示正在輸入的欄位，使用者也可以看得到「AI 正在幫我填」的ＵＩ顯示。&lt;/p&gt;

&lt;h2&gt;
  
  
  命令式 API
&lt;/h2&gt;

&lt;p&gt;命令式 API 適合在不是表單處理的場景來做使用——像是查訂單狀態、跑診斷、做狀態管理，主要提供三個方法，全部掛在 &lt;code&gt;document.modelContext&lt;/code&gt; 上：&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// 註冊工具&lt;/span&gt;
&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;modelContext&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;registerTool&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;get_order_status&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;description&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;查詢訂單狀態，回傳訂單編號、運送狀態與地點&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;inputSchema&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;object&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;properties&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;orderId&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;string&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;description&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;訂單編號&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="na"&gt;required&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;orderId&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="na"&gt;execute&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;orderId&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="s2"&gt;`訂單 &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;orderId&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; 已出貨，狀態：運送中`&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="c1"&gt;// 列出可用工具&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;tools&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;modelContext&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getTools&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="c1"&gt;// 手動執行工具&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;modelContext&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;executeTool&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;tools&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;{"orderId": "ORD-123"}&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;實測的三個方法全部正常：&lt;code&gt;registerTool&lt;/code&gt; 成功註冊、&lt;code&gt;getTools()&lt;/code&gt; 同時列出自訂工具和宣告式表單工具、&lt;code&gt;executeTool&lt;/code&gt; 正確回傳執行結果，另外 &lt;code&gt;toolchange&lt;/code&gt; 事件在工具清單變更時會觸發，&lt;code&gt;AbortSignal&lt;/code&gt; 則可以取消工具執行或註冊。&lt;/p&gt;

&lt;p&gt;不過有個說明有寫但是不是太清楚的部分是，&lt;strong&gt;Chrome 150 已把 &lt;code&gt;navigator.modelContext&lt;/code&gt; 淘汰，改用 &lt;code&gt;document.modelContext&lt;/code&gt;&lt;/strong&gt; （W3C Web Incubator Community Group 討論中）。不過我的 Chrome 151 上兩者都還是 object，記得此時此刻如果要開工的話，就一律用 &lt;code&gt;document.modelContext&lt;/code&gt; 就對了。&lt;/p&gt;

&lt;h2&gt;
  
  
  官方 demo 的旅程
&lt;/h2&gt;

&lt;p&gt;官方 &lt;a href="https://github.com/GoogleChromeLabs/webmcp-tools" rel="noopener noreferrer"&gt;webmcp-tools&lt;/a&gt; repo 的 demos 資料夾有 15 個情境，我試了幾個比較完整 UX 的實測，這邊有一個跟Server MCP比較不一樣的，WebMCP &lt;strong&gt;工具不是一次全給的，而是會跟著頁面狀態長出來&lt;/strong&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  WebMCP Sports
&lt;/h3&gt;

&lt;p&gt;WebMCP Sports 是 Angular 寫的體育用品電商，首頁有 5 個全站工具：&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;search_product&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;view_product&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;get_product_info&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;open_cart&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;get_store_promos_and_rules&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fly4rk251b4a2qhc1fkei.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fly4rk251b4a2qhc1fkei.png" alt="WebMCP Sports 首頁：全站工具已註冊，getTools() 回傳 5 個" width="800" height="500"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;在實測中 &lt;code&gt;search_product&lt;/code&gt; &lt;code&gt;{"query":"basketball","category":"BASKETBALL"}&lt;/code&gt;，得到回傳 &lt;code&gt;count:5&lt;/code&gt; 並切到搜尋結果頁，&lt;code&gt;getTools()&lt;/code&gt; 結果直接變成 8 個，多出 &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;refine_search&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;get_current_search_results&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;add_search_result_to_cart&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fq8540g7tptj3x7lrt1yx.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fq8540g7tptj3x7lrt1yx.png" alt="搜尋結果頁：代理執行 search_product 後，工具從 5 個變成 8 個" width="800" height="500"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;接著再呼叫 &lt;code&gt;open_cart&lt;/code&gt; 開購物車，工具一口氣長到 13 個ＸＤ&lt;br&gt;
結帳相關的tool都飄出來了&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;start_checkout&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;confirm_order&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;update_cart_delivery_option&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;remove_from_cart&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;get_cart&lt;/code&gt; &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F7lrreb6n3lbc26138cbk.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F7lrreb6n3lbc26138cbk.png" alt="購物車開啟：工具長到 13 個，start_checkout 與 confirm_order 在這一層才出現" width="800" height="500"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;突然有一種以前在練習寫購物車的架構與function標準答案 一一浮現的感覺。&lt;/p&gt;

&lt;p&gt;三層 scope 的設計讓全站工具、搜尋頁工具、購物車工具分層註冊，Agent 當下能看到的最小工具set，永遠只跟目前 UI 狀態匹配，比起一般的 MCP 一次註冊 20 個工具，這種設計讓Agent不會亂呼叫不該叫的工具反而好很多，應該也比較省Token。&lt;/p&gt;

&lt;p&gt;而工具自己也會驗證參數。我故意傳 &lt;code&gt;{"price_range":"wrong"}&lt;/code&gt; 給 &lt;code&gt;refine_search&lt;/code&gt;，結果 WebMCP 回傳 &lt;code&gt;{"success":false,"message":"Invalid price range 'undefined'. Must be one of: 'all', '0-49.99', '50-99.99', '100+'"}&lt;/code&gt;。&lt;/p&gt;

&lt;p&gt;另外它還內嵌一個 Gemini on-site AI assistant，站在網站自己那一側幫你聊天導購。「網站自帶代理」跟瀏覽器層級的代理是兩條路線，這個 demo 兩條都示範了。&lt;/p&gt;
&lt;h3&gt;
  
  
  L'Atelier 飯店訂房
&lt;/h3&gt;

&lt;p&gt;另一個範例 L'Atelier 是 React 寫的豪華飯店訂房 app，東京、巴黎、紐約三家分店。首頁先是註冊了 三個工具。&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;search_location&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;view_hotel&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;lookup_amenity&lt;/code&gt; &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;我從 DevTools Protocol 直接呼叫 &lt;code&gt;executeTool(search_location, {"query":"Tokyo"})&lt;/code&gt;，回傳值是這樣的：&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nl"&gt;"content"&lt;/span&gt;&lt;span class="p"&gt;:[{&lt;/span&gt;&lt;span class="nl"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="s2"&gt;"text"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nl"&gt;"text"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="s2"&gt;"{&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;success&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;:true,&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;message&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;:&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;Navigated to search results for Tokyo with active search filters applied.&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;}"&lt;/span&gt;&lt;span class="p"&gt;}]}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;這邊要注意的是回傳的結果包了一層 &lt;code&gt;content&lt;/code&gt; 陣列，很多時候 WebMCP 的執行結果就是 MCP 的 content block 格式，而在我呼叫完 &lt;code&gt;getTools()&lt;/code&gt;，工具清單又變成 6 個，多出了&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;filter_search_results&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;get_current_search_results&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;reset_filters&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;搜尋結果頁有自己的工具，代理跳到哪一頁，哪一頁的工具才上線。&lt;/p&gt;

&lt;p&gt;除了基本的防呆之外，WebMCP 也提供狀態檢查，我手癢直接 &lt;code&gt;view_hotel&lt;/code&gt;，回傳 &lt;code&gt;{"success":false,"error":"Could not find a hotel matching \"1\". Please search first."}&lt;/code&gt;。&lt;/p&gt;

&lt;p&gt;而代理亂呼叫也是會被擋的，&lt;code&gt;start_booking&lt;/code&gt; 在搜尋結果頁根本不存在，要到飯店詳情頁才註冊，而整條操作旅程的最後一步（&lt;code&gt;complete_booking&lt;/code&gt; 填客人資料）是宣告式表單，命令式 API 開頭、宣告式API 收尾，跟在真實 app 裡的架構上滿match的。&lt;/p&gt;

&lt;h2&gt;
  
  
  一些小限制們
&lt;/h2&gt;

&lt;p&gt;WebMCP 有三個明確的限制：&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;一定要有瀏覽器環境。&lt;/strong&gt; 工具呼叫是在 JavaScript 裡處理的，所以代理必須真的開著一個可見的分頁或 WebView，headless 環境下無法呼叫，這跟 MCP server 隨時待命完全不同。&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;網站太複雜會很痛。&lt;/strong&gt; 如果頁面狀態複雜，要利用 JavaScript 去處理應用程式和 UI 狀態的同步，宣告式 API 也幫不了你，Agent能不能利用工具來探索性也是問題，也之後就會有給 Agent看的 sitemap ？ &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;權限政策和跨源 iframe。&lt;/strong&gt; 工具預設被 &lt;code&gt;tools&lt;/code&gt; Permissions Policy 擋住（Same-Origin Policy），跨源 iframe 要加 &lt;code&gt;allow="tools"&lt;/code&gt; 且網域需在白名單內，跨源分享工具還要 &lt;code&gt;exposedTo&lt;/code&gt; + &lt;code&gt;fromOrigins&lt;/code&gt; 兩個參數都設定才生效，以防止潛在的 Clickjacking 與工具注入攻擊&lt;/p&gt;

&lt;h2&gt;
  
  
  開始的起手式
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;開 flag&lt;/strong&gt;：&lt;code&gt;chrome://flags/#enable-webmcp-testing&lt;/code&gt; 設為 Enabled，重啟 Chrome。正式環境去加入 WebMCP origin trial。&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;選一個表單下手&lt;/strong&gt;：找站上最常用的搜尋或表單，加上 &lt;code&gt;toolname&lt;/code&gt; 和 &lt;code&gt;tooldescription&lt;/code&gt;，最多 5 分鐘。&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;用 Inspector 驗證&lt;/strong&gt;：裝 Model Context Tool Inspector 擴充功能，看工具有沒有正確註冊、schema 對不對，再用自然語言 prompt 叫代理執行。&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;從「給人看」到「給 Agent 用」的 Web 前端新浪潮&lt;/p&gt;

&lt;p&gt;WebMCP 的核心價值，不是讓網站多一個花哨的 AI 聊天視窗，而是讓你的網站直接升級為 Agent Ecosystem（代理生態系）的成員。&lt;/p&gt;

</description>
      <category>chrome</category>
      <category>webmcp</category>
      <category>agents</category>
      <category>webdev</category>
    </item>
    <item>
      <title>瀏覽器跑 LLM 的實際體感與骨感限制</title>
      <dc:creator>JH5</dc:creator>
      <pubDate>Thu, 13 Aug 2026 03:07:17 +0000</pubDate>
      <link>https://dev.to/jh5_pulse/liu-lan-qi-pao-llm-de-gu-gan-xian-zhi-140d</link>
      <guid>https://dev.to/jh5_pulse/liu-lan-qi-pao-llm-de-gu-gan-xian-zhi-140d</guid>
      <description>&lt;p&gt;直接在瀏覽器跑 LLM，既兼顧隱私又不用複雜的GPU設定，太完美了吧？&lt;/p&gt;

&lt;p&gt;從 WebLLM 到 Transformers.js，前端社群有一群反骨仔吹起一股「邊緣 LLM」的熱潮，可是，當真正將模型落地到使用者的瀏覽器時，第一個面對的考驗就是，WebGPU 真的有比 WASM 快嗎？&lt;/p&gt;

&lt;p&gt;這陣子實測的結論比想像中更加戲劇化， 500M 以下的微型模型，WASM 反而快了 12%，但是對於 3B 以上的大模型，WASM 直接變成悲劇，直接讓Chrome撞的頭破血流（Chrome 沒有頭 ＝ Headless Chrome）。&lt;/p&gt;

&lt;h2&gt;
  
  
  測試環境
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;項目&lt;/th&gt;
&lt;th&gt;規格&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;機器&lt;/td&gt;
&lt;td&gt;MacBook Air M2, 8GB RAM&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;GPU&lt;/td&gt;
&lt;td&gt;Apple M2, 8 核心&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;磁碟可用空間&lt;/td&gt;
&lt;td&gt;9.7GB&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;瀏覽器&lt;/td&gt;
&lt;td&gt;Chrome 136 (Playwright headless)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;框架&lt;/td&gt;
&lt;td&gt;WebLLM 0.2.84, @xenova/transformers 2.17.2&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;一開始遇到我的破MBA 8GB 機型的磁碟剩 9.7GB，這直接觸發了瀏覽器 Cache API 的物理配額限制（約為可用空間的 10%，即 ~970MB），這個限制直接決定了前端能載入的模型體積。&lt;/p&gt;

&lt;h2&gt;
  
  
  Phi-3.5 Mini @ MBA
&lt;/h2&gt;

&lt;p&gt;原定計畫是測試熱門輕量級模型 Phi-3.5-mini-instruct（3.8B 參數），然而在 8GB MacBook Air 上，模型連載入都不行。&lt;/p&gt;

&lt;p&gt;Phi-3.5-mini-instruct-q4f16_1-MLC 需佔用約 2,520 MB VRAM，當權重檔案下載到瀏覽器後，就出線 QuotaExceededError，即使換了一些快取的策略，還是都不行：&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Cache API（預設）：QuotaExceededError: Quota exceeded&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;IndexedDB：ArtifactIndexedDBCache failed to fetch&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;OPFS：SecurityError: unsafe file access&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;在 8GB 記憶體且磁碟空間不足的裝置上，3.8B 模型完全無法運作，瀏覽器儲存配額（Storage Quota）直接被吃滿。&lt;/p&gt;

&lt;h2&gt;
  
  
  Phi-3.5 Mini @ MStudio
&lt;/h2&gt;

&lt;p&gt;為了確認是否是儲存配額問題，我改用 M2 Max 運行相同的 WebLLM 代碼與 Phi-3.5-mini-instruct-q4f16_1-MLC 模型：&lt;/p&gt;

&lt;p&gt;結果：&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;指標&lt;/th&gt;
&lt;th&gt;M2 Max&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;tok/s&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;57.4&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;準確率&lt;/td&gt;
&lt;td&gt;
&lt;strong&gt;90.0%&lt;/strong&gt;（10 題對 9 題）&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;總 tokens&lt;/td&gt;
&lt;td&gt;956&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;總時間&lt;/td&gt;
&lt;td&gt;16.66s&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;模型載入&lt;/td&gt;
&lt;td&gt;一次成功&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;輸出 57.4 tok/s 速度在中文字的回覆上極度流暢，簡單的丟了一些問題，數學邏輯題，程式碼產出與生物資訊（Variant calling/WES）相關問答回答的也是有模有樣的。&lt;/p&gt;




&lt;p&gt;輕薄的Client跑不動前端 LLM，真正的第一道關卡往往是瀏覽器的 Storage Allocator，而非 GPU 本身，那我的 MBA 到底可以跑什麼模型？&lt;/p&gt;

&lt;h2&gt;
  
  
  1. TinyLlama-1.1B
&lt;/h2&gt;

&lt;p&gt;改用 @xenova/transformers (v2.17.2) 執行 TinyLlama-1.1B-Chat 時，雖然可成功下載權重，但推理的瞬間會拋出錯誤，&lt;br&gt;
RangeError: offset is out of bounds at Uint8Array.set&lt;br&gt;
，餵狗後發現這應該是 舊版 ONNX Runtime Web 處理特定運算子時超越 WASM 記憶體上限的已知issue。&lt;/p&gt;
&lt;h2&gt;
  
  
  2. SmolLM2-360M
&lt;/h2&gt;

&lt;p&gt;再測試了 SmolLM2-360M-Instruct (q4f16)：&lt;/p&gt;

&lt;p&gt;速度：38.4 tok/s&lt;/p&gt;

&lt;p&gt;聽說底層做了編譯優化，跑起來也是相當的穩定。但 360M 參數推理能力相當有限，回答問題的能力連ChatGPT剛出來時都不如啊... (雖然也知道參數大小差很多，但是已經被LLM寵壞了)&lt;/p&gt;
&lt;h2&gt;
  
  
  WebGPU vs WASM 效能對比
&lt;/h2&gt;

&lt;p&gt;我內心還是覺得應該要公平比較 WebGPU vs WASM在效能上的差異，因此又找了一些模型在MAC Studio 上來比拼，先用 GPT-2（124M）跑了兩輪。&lt;/p&gt;

&lt;p&gt;GPT-2（124M）是 2019 年的模型，答題水準大概長這樣...&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Q: What is 2 + 2?
A: The answer is 2 + 2.  ← ...

Q: How many legs does a cat have?
A: The answer is no.  ← WTF

Q: Write a Python function to add two numbers:
A: def add_number(x, y): return x + y + 1 + 1 + 1 + 1...  ← 有 def，但多加了一堆 1

Q: What is the capital of France?
A: The capital of France is the capital of France.  ← 跳針
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  結果
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;後端&lt;/th&gt;
&lt;th&gt;tok/s&lt;/th&gt;
&lt;th&gt;準確率&lt;/th&gt;
&lt;th&gt;總時間&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;WASM&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;23.2&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;30%&lt;/td&gt;
&lt;td&gt;16.39s&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;WebGPU&lt;/td&gt;
&lt;td&gt;20.4&lt;/td&gt;
&lt;td&gt;30%&lt;/td&gt;
&lt;td&gt;18.68s&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;在 124M 模型下，WASM 竟然反超 WebGPU 約 12%！&lt;/p&gt;

&lt;p&gt;為什麼微型模型下 WASM 會贏？&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;資料傳送Overhead：Token 需要頻繁在 CPU 與 GPU 記憶體間複製，當計算量不夠大時，搬運時間直接侵蝕效能。&lt;/li&gt;
&lt;li&gt;Kernel 啟動成本：每次啟動 GPU Kernel 都有固定開銷，無法被小規模平行運算攤平。&lt;/li&gt;
&lt;li&gt;WASM 的進化：成熟的指令集與 JIT 優化，已足以讓 CPU 高效處理 124M 規模的矩陣運算。&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  3.8B 模型對比
&lt;/h2&gt;

&lt;p&gt;上面 GPT-2 的結論是「124M 小模型 WASM 贏 12%」，好像就直接打臉我上一篇的農場標題ＸＤ &lt;a href="https://dev.to/jh5_pulse/tensorflowjs-kuai-kan-bu-dao-litertjs-de-che-wei-deng-liao-4f3j"&gt;TensorFlow.js 快看不到 LiteRT.js 的車尾燈了 &lt;/a&gt; ，&lt;br&gt;
那如果換成更大的模型呢？我在 M2 Max上用同一個 &lt;code&gt;Phi-3.5-mini-instruct-q4f16_1&lt;/code&gt; 模型分別跑了 WebGPU和 WASM，來看看結果如何。&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;後端&lt;/th&gt;
&lt;th&gt;tok/s&lt;/th&gt;
&lt;th&gt;準確率&lt;/th&gt;
&lt;th&gt;總 tokens&lt;/th&gt;
&lt;th&gt;總時間&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;WebGPU&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;59.7&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;70%（10 題對 7 題）&lt;/td&gt;
&lt;td&gt;490&lt;/td&gt;
&lt;td&gt;8.20s&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;WASM&lt;/td&gt;
&lt;td&gt;0.5&lt;/td&gt;
&lt;td&gt;60%（10 題對 6 題）&lt;/td&gt;
&lt;td&gt;413&lt;/td&gt;
&lt;td&gt;827s（13.8 分鐘）&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;結果看去裡，WASM 慢了 &lt;strong&gt;119 倍&lt;/strong&gt;，總共 10 題要跑將近 14 分鐘，而且單題延遲 72-100 秒，WebGPU 只要 0.8 秒左右。&lt;/p&gt;

&lt;p&gt;為什麼差這麼多？合理的推測是因為 WASM 是 CPU 跑，CPU 的記憶體頻寬和算力是固定的 （還是MAC的CPU問題？），而模型從 124M 漲到 3.8B，每單位 token 的計算量跟著漲，但 CPU 的速度不會變。WebGPU 則是把運算丟給 GPU 的 parallel cores，理論上模型越大、GPU 的相對優勢越明顯。&lt;/p&gt;

&lt;p&gt;反而像GPT-2 那種 124M 的規模，GPU 的 kernel 啟動和資料傳輸開銷反而吃掉平行化的好處，超過某個臨界點（大概 1B 左右）之後，WebGPU 的優勢就出現了。&lt;/p&gt;

&lt;p&gt;又手癢補跑了一顆更大的模型 Qwen2.5-7B-Instruct（7B，q4f16）在 WebGPU 上：&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;指標&lt;/th&gt;
&lt;th&gt;數值&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;tok/s&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;35.5&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;準確率&lt;/td&gt;
&lt;td&gt;
&lt;strong&gt;80%&lt;/strong&gt;（10 題對 8 題）&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;總 tokens&lt;/td&gt;
&lt;td&gt;643&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;總時間&lt;/td&gt;
&lt;td&gt;18.13s&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;7B 的模型在瀏覽器裡能跑到 35.5 tok/s，還能答對 8 題，不過這顆模型的變異較大，跑起來很明顯的卡頓與瀏覽器快往生的感覺，又回頭處理scaling 的部分，Phi-3.5 Mini 在 WebGPU 上把 max_tokens 從 50 拉到 400，準確率從 70% 升到 100%，tok/s 穩定在 59.7-65.2 之間，給模型更多生成空間，答案品質會明顯變好，而且速度幾乎不受影響。&lt;/p&gt;

&lt;h2&gt;
  
  
  小結
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;小模型不用硬上 WebGPU：若任務僅需 &amp;lt;500M 的微型模型，直接採用 WASM 即可，不僅可以避開 WebGPU 在不同瀏覽器（如舊版 Safari）的相容性問題，也無需撰寫繁複的 Fallback 邏輯。&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;儲存空間是隱形殺手：部署 &amp;gt;1B 模型時，除了關心使用者的顯示卡，務必優先檢查 Storage Quota。使用者硬碟空間不足導致的快取失敗，往往才是用戶體驗崩潰的主因。&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>webgpu</category>
      <category>webassembly</category>
      <category>llm</category>
      <category>browser</category>
    </item>
  </channel>
</rss>
