AI 離線部署EP.01

什麼是 Air-gapped AI?
從工廠內網 LLM 說起

為什麼有些企業的 AI 不能連網?什麼是隔離網路?
從我在鴻海深圳廠的實際部署經驗說起

Joseph Chen

2025
12 min read
實戰筆記

這篇文章要解決什麼問題

在生成式 AI (Generative AI) 爆發的時代,大多數開發者早已習慣直接呼叫 OpenAI、Claude 或 Gemini 等雲端 SaaS API。只要綁定信用卡、取得 API Key,幾行代碼就能建立一個強大的智能客服或知識助手。

但在製造業、金融業、智慧醫療或國防領域,事情完全不是這樣。想像一下,你手中有涉及新一代手機量產的機密良率報告、關鍵晶片的底層測試日誌,或是客戶極其私密的安全驗證憑證。如果將這些資料直接上傳到公有雲端 AI,哪怕服務商聲稱「不會用於模型訓練」,在合規與資安稽核面前也絕對是無法妥協的紅線。

因此,這些大型企業會要求核心開發環境與生產線網段必須與外界 Internet 徹底切斷,實行物理隔離。這在資安領域被稱為 Air-gap (氣隙隔離)

這篇文章要探討的核心問題是:當我們失去了 `pip install`、`docker pull` 與外網 API 呼叫的便利後,要如何在一台物理隔離、沒有任何外網訊號的內網伺服器上,成功架設並運行起一個商用級的本地化 LLM 推論與 Orchestration 平台?


真實案例與 Joseph 的現場經驗

2024 年,我加入鴻海深圳廠,接下了一個核心任務:在無聯網的自動化測試機房中部署一套能夠自主判讀異常 Log、提供 SOP 操作指引的本地 LLM 助手。

我還記得第一天踏入該網段機房時的震撼:所有的伺服器主機皆沒有插上實體網線,無線網卡在 BIOS 階段就被直接禁用,甚至所有 USB 連接埠都被貼上了帶有警示字樣的物理封條。在這樣的環境下,任何一次的軟體部署都像是戴著鐐銬跳舞。

💡 現場血淚經驗:部署痛點不在 AI 模型,而在運維依賴

我一開始也以為部署 AI 不過就是把 llama3 跑起來,直到我被擋在第一關:沒有外網。我沒辦法直接跑 `pip install requests`。在有網路的辦公室寫好的程式,帶進生產線時,只因為少了一個極小的 C-binding 函式庫,整套系統就直接崩潰。

在這種極端的 Air-gapped 環境下,任何軟體與模型的移入都必須經過層層審批:首先在有限度聯網的「開發機」下載所有的套件 Wheels 與 Docker 映像檔,經過公司的多重毒性掃描與人工代碼稽核後,打包成大壓縮檔,再透過特許的內部網路安全通道(跳板伺服器)單向傳輸進生產內網。

這段經歷讓我深刻體會到:在工廠端部署 AI,核心阻礙往往不是演算法的精準度,而是如何確保系統在零外網依賴下,依然具備 100% 的健壯度與可運維性。


核心概念解釋:氣隙網絡 (Air-gap) 的架構

要做到物理隔離,企業內部通常會將網段切分為不同的信任等級。典型的製造業工廠網段拓撲如下:

Air-Gapped AI 部署流程與拓撲架構

Step 01 / 辦公網段

Office Network

可正常存取外網。在此下載所需的 Python Wheel 依賴套件、Docker 映像檔,以及開源模型權重 (.gguf)。

💾 輸出轉存離線壓縮包
Step 02 / 資安審查

Security Gate

將打包的壓縮包與模型檔案送交資安團隊。執行 MD5 校驗、木馬毒性掃描與防洩密檢查,通過後傳送至特許跳板機。

🛡️ 雙重簽章與 MD5 驗證
Step 03 / 生產網段

Production (Air-gapped)

完全斷網。使用特許傳入的離線資源包,安裝 Python Wheels,載入本地 Docker 鏡像,拉起本地 Ollama 推論引擎。

🔒 物理隔離,100% 本地推論

在有網路的 Office Net 裡,我們能輕易進行軟體組裝;一旦要把程式搬移到完全斷網的 Production Net,就必須提前將以下三大核心資源進行「靜態化」與「離線打包」:

  • 運行庫依賴 (Runtime Dependencies):所有的 Python `.whl` 封裝,需包含底層的 C 延伸模組。
  • 運行環境 (Runtime Environment):包含基礎的 Docker base images、Ollama 二進位檔、及相關後台資料庫。
  • AI 模型權重 (Model Weights):一般為預先量化好的 GGUF 格式。量化不僅能壓縮體積,更大幅降低了對生產線伺服器顯示卡記憶體 (VRAM) 的硬體要求。

程式碼實戰:從線上安裝到離線打包自動化

以下我們用程式碼來展示兩者的差距。第一段是開發階段常見的「直覺寫法」,這在離線環境會直接觸發網路連線錯誤;第二段則是我們實際採用的「離線分階段自動化打包腳本」。

錯誤的寫法:依賴外部即時下載與 API 呼叫(離線環境直接崩潰)

# ❌ 在生產線執行此腳本會直接 Crash,因為無法與 PyPI 或 Docker Hub 建立連線
import os
import requests

# 1. 現場嘗試線上安裝缺失套件
# os.system("pip install requests langchain langchain-community") 
# ConnectionTimeoutError: Failed to establish a new connection...

# 2. 嘗試呼叫外部公有雲 API
def call_online_llm(prompt):
    api_key = "sk-xxxxxxxxxxxxxxxxxxxxxxxx"
    url = "https://api.openai.com/v1/chat/completions"
    headers = {
        "Authorization": f"Bearer {api_key}",
        "Content-Type": "application/json"
    }
    data = {
        "model": "gpt-4o",
        "messages": [{"role": "user", "content": prompt}]
    }
    
    # 這裡在 Air-gapped 環境下會直接丟出 ConnectionError
    response = requests.post(url, headers=headers, json=data, timeout=5)
    return response.json()

if __name__ == "__main__":
    try:
        res = call_online_llm("分析當前工廠測試機台異常日誌")
        print(res)
    except Exception as e:
        print(f"❌ 部署失敗:找不到外部網絡連接。錯誤詳情: {e}")

改良後寫法:分階段下載、本地加載模型與離線部署自動化

我們將整個部署拆分為「有網開發機」的下載腳本,與「無網生產機」的本地安裝載入腳本:

# 🚀 步驟一:【在有網路的 Office 開發機執行】下載腳本
# download_assets.sh
# ----------------------------------------------------
# 1. 下載所有 Python wheels(包含所有子依賴,強制使用 binary 避免現場編譯)
# pip download -d ./offline_wheels -r requirements.txt --only-binary=:all:
#
# 2. 拉取並保存 Docker 映像檔
# docker pull ollama/ollama:latest
# docker save -o ollama_image.tar ollama/ollama:latest

# 🚀 步驟二:【在無網路的 Air-gapped 生產機執行】本地加載與推論 Python 腳本
# run_local_llm.py
# ----------------------------------------------------
import subprocess
import os
from openai import OpenAI

def init_offline_environment():
    print("📦 正在執行本地依賴包離線安裝...")
    # 在生產主機本地安裝準備好的 wheels,不連網且忽略 index
    # subprocess.run(["pip", "install", "--no-index", "--find-links=./offline_wheels", "-r", "requirements.txt"])
    
    print("🐳 正在導入離線 Docker 映像檔...")
    # subprocess.run(["docker", "load", "-i", "ollama_image.tar"])
    
    print("✅ 本地運維環境就緒。")

# 使用 Ollama Modelfile 載入特許搬入的本地 GGUF 模型檔
# 本地 Modelfile 內容:
# FROM /app/models/qwen2.5-7b-instruct.gguf
# PARAMETER temperature 0.3
# SYSTEM "你是一位精通半導體測試機台日誌分析的資深助理。"

def run_local_inference(prompt):
    # 呼叫已經在生產網伺服器背景運行起的本地 Ollama 服務 (127.0.0.1:11434)
    client = OpenAI(
        base_url="http://127.0.0.1:11434/v1",
        api_key="ollama" # 本地推論無須外網金鑰
    )
    
    response = client.chat.completions.create(
        model="qwen2.5-7b-custom",
        messages=[{"role": "user", "content": prompt}],
        temperature=0.3
    )
    return response.choices[0].message.content

if __name__ == "__main__":
    # 模擬本地初始化與離線推論
    # init_offline_environment()
    
    log_sample = "ERR 2026-05-19 22:15:50 [SYS] Serial port write timeout on controller board XY-04."
    print("🤖 送出分析日誌請求...")
    analysis = run_local_inference(f"請分析以下機台錯誤並給出除錯建議:\n{log_sample}")
    print("\n=== 本地 AI 分析結果 ===")
    print(analysis)

技術方案比較

不同 AI 部署方案在開發效率、安全合規與維護成本上各有優劣,以下為實戰經驗整理:

部署方案優點缺點適合場景
雲端 SaaS API (OpenAI)免硬體成本、開發極快、模型能力最強資料外洩風險高、依賴外網穩定性、費用高新創產品驗證、無隱私限制的公開業務
企業內網/私有雲部署資料不出企業網、能與內部帳號 SSO 整合需自備高階 GPU 伺服器、內部網路需打通通道一般企業內部的 ERP、HR 助手、內部文件庫
物理隔離 (Air-gapped) 本地部署100% 防止資料外洩、極高資安合規、免授權費初次部署門檻極高、無法自動更新、資源受限智慧工廠生產線、核心金融系統、國家防務

常見錯誤與踩坑實錄

🔴

只用 `pip download` 下載源碼卻缺少編譯工具

我第一次打包 Python 套件時,直接執行了下載。到現場才發現,某些套件在安裝時需要呼叫本機的 `gcc` 或 `make` 來編譯 C 語言擴充模組。但生產線伺服器是最小化安裝版(Minimal OS),根本沒有編譯環境。
正解: 必須在下載時加上 `--only-binary=:all:` 參數,強迫下載預先編譯好的二進位 Wheel 檔。

🔴

容器內外時區不同步導致憑證過期

在隔離環境下,我們部署了 Dify 容器。結果有些 API 呼叫本地資料庫時一直報錯。最後排查才發現,宿主機時區是 UTC+8,但 Docker 容器預設採用 UTC 時區。由於時間相差 8 小時,觸發了內部安全憑證的逾期保護機制。
正解: 在 Docker Compose 的 `volumes` 中,將本機的 `/etc/localtime` 單向掛載進容器中,強制時區一致。

🔴

未作大模型檔案的雜湊值校驗 (Checksum)

有一次搬運一個 14B 的 GGUF 大模型(約 9GB)。傳入工廠內網後,Ollama 載入時一直拋出 `segmentation fault` 核心崩潰。查了半天程式,最後才發現是隨身碟因多次插拔損壞,導致寫入的檔案少了幾個 bytes。
正解: 在 Office 網段打包時,先計算檔案的 MD5 雜湊值(`md5sum model.gguf`)。搬運進生產伺服器後,必須重新計算比對,一致才允許運行。


實務操作建議

要在 Air-gapped 環境長期維持 AI 系統穩定,建議將以下工作寫入維運標準 SOP:

建立私有離線倉庫鏡像 (Private Mirror)

當工廠端規模擴大時,頻繁用隨身碟搬運 wheel 檔極易出錯。建議在工廠的特許中繼網段架設內部 Nexus Repository 或 PyPI 私有鏡像,統一集中管理依賴版本。

一鍵 Compose 化部署與備份

生產線伺服器不容許繁雜的手動設定。務必使用 Docker Compose 將 Ollama、Dify、PostgreSQL、Redis 整套架構服務容器化,並實作一鍵啟動與狀態定期備份腳本。

模型與業務代碼分離 (Model Decoupling)

不要將 GGUF 權重檔包進業務 Docker image。應透過磁碟路徑掛載將模型目錄映射進推論容器,未來模型升級(如從 Qwen-7B 升級到 Qwen-14B)時,只需替換檔案並重啟 Ollama,不需重新構建映像檔。


與本系列其他文章的關聯

這篇文章是整個「AI 離線實戰系列」的開篇。當你理解了隔離網路的運維限制後,接下來我們將進入更具體的實作章節:


總結

物理隔離 (Air-gapped) 並不代表與現代技術絕緣。相反地,它迫使我們回到軟體工程的底層邏輯,以更清晰、低耦合的方式進行架構設計。

透過離線包預編譯、Docker 鏡像映射以及本地 Ollama 引擎,我們不僅在無網的工廠深處順利跑起了大模型,更建立了一套符合企業資安紅線的 AI 運維架構。這套經驗除了適用於製造業,對隱私要求極高的金融與醫療產業同樣有高度參考價值。


延伸閱讀:更多 AI 技術分享

上一篇

這是系列的第一篇

下一篇

EP.02 — Ollama 本地模型部署

AI 離線部署Air-gappedLLMOllamaDify企業 AIEP.01