系列:從現場踩坑到 AI 工具 — IT Diagnostic Agent 開發實錄
Day 18 講過,因為 Ollama 提供 OpenAI 相容端點,callOllama 這個函式幾乎是複製貼上的。
程式碼是最簡單的部分。
真正花時間的是三件跟程式碼無關的事:
Ollama 能不能用,取決於使用者環境有沒有設對。而設錯的時候,錯誤訊息通常是 Failed to fetch——這對使用者來說等於沒有訊息。
所以我做了一個切換到 Ollama 時強制出現的確認 modal,分成兩個部署情境:
☐ 已在這台電腦安裝 Ollama(ollama.com)
☐ Ollama 服務已啟動(ollama serve)
☐ 已下載模型(例如 ollama pull gemma3:12b)
☐ 端點設定為 http://localhost:11434(預設值)
☐ 內網 Ollama Server 已安裝並啟動
☐ 已在設定頁面填入正確的伺服器 IP(例如 http://192.168.1.100:11434)
☐ 防火牆已開放 11434 port(或自訂 port)
☐ Ollama 已設定允許外部連線(OLLAMA_HOST=0.0.0.0)
☐ 已下載所需模型至伺服器
底部兩個按鈕:「切換回雲端模型」 和 「我已確認,繼續使用」。
這個設計不是為了完整,是因為兩種情境的失敗原因完全不同。
本機部署失敗,通常是服務沒啟動或模型沒下載——都在使用者自己的電腦上,都能自己解決。
區網部署失敗,多半是防火牆或 OLLAMA_HOST 沒設。特別是 OLLAMA_HOST=0.0.0.0 這一項——Ollama 預設只監聽 localhost,所以區網 Server 裝好、服務跑起來、模型也下載了,但從別台電腦就是連不上。
這一項不設,其他四項全對也沒用。 而它是最不直覺的一項,因為「服務明明在跑」。
把兩種情境分開,使用者才知道該對照哪一份清單。一份混在一起的十項清單,等於沒有清單。
這是整個功能裡最麻煩的問題,而且它跟程式寫得好不好完全無關。
問題是這樣的:
https://
http://localhost:11434
結果:在 GitHub Pages 上打開工具,本地模型連不上。而且瀏覽器不會給你有用的錯誤訊息。
這個衝突很諷刺:
我把工具部署到 GitHub Pages,是為了讓使用者「打開網址就能用」。
而正是這個便利性,破壞了本地模型支援。
所以 modal 裡有這段警告:
⚠️ 若透過 HTTPS 網址(如 GitHub Pages)存取本工具,瀏覽器安全限制可能封鎖 HTTP 本地端點。建議將
index.html下載後在本機直接開啟,或確保 Ollama Server 有 HTTPS 支援。
「建議將 index.html 下載後在本機直接開啟」——這句話能成立,是因為 Day 06 那個決定。
因為整個工具是單一個靜態 HTML 檔,所以「下載下來用 file:// 開啟」是一個可行的建議。
如果我當初用了 React:
那麼混合內容這個問題就會變成:本地模型只能在你自己架 server 的情況下用。 那基本上等於這個功能死了。
我在 Day 06 選純靜態 HTML 的理由是「現場環境限制」。當時完全沒想到本地模型這件事。
但那個為了 A 做的決定,四個月後解決了 B。
這是我在這個專案裡學到最有價值的一課:保持簡單的架構,會在你預料不到的地方付出紅利。 不是因為簡單很優雅,是因為簡單的東西有更多種使用方式。
這是最實際的問題,也是我原本最擔心的一點。
工具的預設值是 gemma3:12b——一個 12B 參數的模型,在一台有獨立顯卡的筆電上跑得動。
它當然比不上雲端旗艦模型。所以問題是:夠用嗎?
而我認為要回答這個問題,得先問一個更前面的問題。
回到第三章。
IT Diagnostic Agent 的架構是:
決策樹(結構強制紀律,覆蓋主要路徑)
↓
AI 對話(處理樹外情況)
在決策樹裡,模型完全不參與。 節點是人寫的,分支是人定的,順序是我用二十年經驗排的。這條路徑上,模型大小是零相關。
在 AI 對話裡,模型要做的是什麼?
不是要它憑空發明一套診斷方法論——那套方法論已經寫在 systemPrompt 裡了(Day 12 的五條規則)。
它要做的是:
這些任務對模型能力的要求,比「從零建構診斷邏輯」低得多。
這是我認為第三章和第四章真正的連結點:
當你把紀律做進結構和 Prompt 裡,你就不需要一個聰明到能自己發明紀律的模型。
換個說法:
| 架構 | 對模型的要求 |
|---|---|
| 什麼都交給 LLM 自由發揮 | 需要最強的模型(因為它要自己想出好的診斷流程) |
| 紀律寫在結構與 Prompt 裡 | 需要一個「聽得懂話、照著做」的模型 |
第二種對模型的要求低很多。而「聽得懂話、照著做」是小模型也做得到的事。
所以第三章那些關於結構性紀律的討論,不只是設計哲學上的潔癖,它有一個非常實際的後果:它讓本地小模型變成可行的選項。
而根據 Day 19,本地模型可行與否,決定了某些企業能不能用這個工具。
一條線串起來是:
結構性紀律 → 降低模型能力需求 → 小模型可行 → 本地部署可行
→ 通過資料落地否決條件 → 企業能用
Day 14 那篇看起來最理論的文章,最後撐起的是一個商業上的可能性。
但這條鏈裡有一節我還沒有驗證過,而且那一節剛好是最關鍵的一節。 下面就講這件事。
上面那條漂亮的因果鏈,我要自己打一個問號。
因為我當初的測試,只做了決策樹那一半。
回想我實際做過的驗證:
| 測試對象 | 做了嗎 | 驗證了什麼 |
|---|---|---|
| 決策樹在本地模型環境下 | ✅ | 工具能開、節點能走、流程正常 |
| Ollama 連線與回覆 | ✅ | 端點通、有回應、不報錯 |
| AI 對話在小模型下的診斷品質 | ❌ | 沒測 |
問題是:決策樹本來就不用模型。
它是靜態節點,走訪邏輯是純 JavaScript。無論後面接的是雲端旗艦模型還是 3B 小模型,決策樹的行為都一模一樣——因為它根本沒去呼叫模型。
所以我測「決策樹在小模型環境下正常」這件事,驗證的其實是「工具沒被我改壞」,不是「小模型夠用」。
這兩件事我當時混在一起了。
寫到這裡我才發現一件事,讓我有點笑不出來。
Day 15 的稽核發現:五條規則唯一沒被實作的地方,是 AI 對話路徑。
今天的檢視發現:小模型唯一沒被測試的地方,也是 AI 對話路徑。
同一條路徑,既是紀律最薄弱的地方,也是驗證最空白的地方。
而這不是巧合,是同一個認知偏差造成的:
我從一開始就把 AI 對話當「逃生門」看待。
逃生門的心態是:它存在就好,反正大部分人走主通道。所以我沒有把診斷紀律寫進它的 Prompt,也沒有測試它在受限環境下的表現。
而如果本地模型是企業能不能用這個工具的否決條件(Day 19),那這扇逃生門就不是逃生門了——它是企業客戶的主要通道之一。
我用逃生門的標準,在維護一條可能是主幹道的路。
把已驗證和未驗證分開講:
已成立
尚未驗證
所以「結構性紀律降低模型能力需求」目前的狀態是:一個有理論根據的假設,不是一個結論。
而且它現在還多了一個前提——那五條規則要先真的被寫進 systemPrompt(Day 15 那兩行的修正)。在修正之前,這個假設連測都測不了,因為要測的紀律根本不在那段 Prompt 裡。
把它寫下來,當成接下來的實際工作項目:
用五條規則當評測標準,而不是主觀感受。 這樣得到的才是可以寫進 README、可以拿去跟企業客戶談的東西。
我完全可以在這篇編一組 benchmark 數字。沒有人會去驗證。
但 Day 15 那篇文章的核心教訓就是「把假設當成事實是最容易犯的錯」。如果我在 Day 20 這樣做,前面十九天就白寫了。
而且說實話,這個缺口本身比一組漂亮的數字有價值。 它揭露的是一個結構性的認知偏差:
你怎麼定位一個功能,就決定了你會怎麼對待它。而錯誤的定位會同時造成設計缺口和驗證缺口,因為兩者出自同一個判斷。
我把 AI 對話定位成逃生門,於是它同時缺了紀律和測試。這兩個缺口不是兩個獨立的疏失,是一個定位錯誤的兩個症狀。
核心 vs 外部
本地模型的核心價值不是省錢,是資料落地(Day 19)。技術路徑(Ollama 相容 OpenAI 格式)是外部條件,而且它剛好很容易。
可控 vs 不可控
瀏覽器的混合內容政策不可控。但「工具是不是單一檔案、能不能用 file:// 開啟」是可控的——而那個可控的選擇,接住了不可控的限制。
靜態 vs 動態
模型生態是高度動態的。今天的 gemma3:12b 不會是明年的建議值。所以模型名稱在工具裡是一個使用者可編輯的欄位,不是寫死的常數。
同樣的道理,端點也是可編輯的(Day 18)。凡是會變的東西,都不該寫死。
Day 16 到 Day 20,這一章的主題是「留退路」:
這章最重要的兩句話:
加分條件可以互相補償,否決條件不能。一個又快又便宜的方案,不會因為快和便宜就變得合規。
還有一句是今天才學到的:你怎麼定位一個功能,就決定了你會怎麼對待它。 我把 AI 對話當逃生門,於是它同時缺了紀律(Day 15)和測試(Day 20)——兩個缺口,一個病根。
預告(第五章): 前面二十天都在講這個工具。接下來五天要講一件我一直沒完整交代的事——這個工具、還有你正在讀的這些文章,實際上是怎麼被做出來的。Anthropic 說 Claude 的使用者裡軟體開發只佔三成多,剩下那七成長什麼樣子?我就是其中一個樣本。
作者:Rich Chang | IT 基礎建設工程師 | 越南・柬埔寨・台灣