# Plan B:預置模型線上下載(R9 Contingency) > 這份文件是 **R9 .nef re-distribution 授權** 的 contingency 方案。 > 使用時機:發佈前 PM 與 Kneron 確認結果為「不允許將 .nef 內嵌於另一產品 re-distribution」。 > **目前不啟用**,只在 R9 被否決時才觸發;本文件不影響 M1–M6 開發計畫。 --- ## 1. 觸發條件 以下任一條件成立即觸發 Plan B: - M6(首次公開 release 前)PM 或使用者從 Kneron 官方 / OEM 窗口收到「不允許 re-distribute 預置 .nef」的書面回覆 - 發佈流程中任何時點發現授權問題 - Innovedus 法務自行判斷風險過高要求下架內嵌模型 **不觸發的情況**:任何「尚未確認」的狀態(與現行第四輪 R4-1 決策一致,維持內嵌不主動詢問)。 ## 2. 目標 用最小改動把預置 .nef 從「內嵌打包」改為「首次啟動線上下載」,**保留原本所有功能與使用體驗,僅犧牲「完全離線」承諾**。 **不重做**: - 使用者自訂上傳的 .nef(`data/custom-models/`)繼續走既有上傳流程 - Python runtime / KneronPLUS SDK / ffmpeg / yt-dlp 繼續內嵌(授權可重發布) **改動範圍**:只有預置 .nef(`server/data/nef/`,~73MB) ## 3. 架構修改 ### 3.1 移除 payload 中的 .nef ```diff visiona-local/payload/ ├── bin/ ├── python/ ├── scripts/ - └── data/ - ├── models.json - └── nef/ - ├── kl520/*.nef - └── kl720/*.nef + └── data/ + └── models.json ← 保留 metadata,nef 目錄留空 ``` 安裝檔大小降為 ~225MB(macOS)/ ~235MB(Windows)/ ~240MB(Linux)。 ### 3.2 新增下載邏輯 **位置**:`visiona-local/model_download.go`(新寫) **觸發點**:`.installed` 寫入後、首次 `launchServer()` 之前,插入一個「模型下載」精靈步驟。 ```go // 流程 func (inst *Installer) stepDownloadPresetModels(config InstallConfig) error { // 1. 讀 models.json → 取得清單 manifest := loadBundledManifest() // 2. 檢查本地 data/nef/ 下哪些已存在 missing := diffMissing(manifest, config.InstallDir) // 3. 全數存在 → 跳過 if len(missing) == 0 { return nil } // 4. 顯示下載進度 UI(Wails app 內建) inst.showProgress("下載預置模型...", len(missing)) // 5. 逐檔下載 + 驗證 sha256 for _, m := range missing { if err := downloadWithResume(m.URL, m.LocalPath, m.SHA256); err != nil { return fmt.Errorf("模型下載失敗:%w", err) } inst.incrementProgress() } return nil } ``` ### 3.3 manifest 格式 `payload/data/models.json`(擴充原有格式): ```json { "version": "1.0.0", "base_url": "https://releases.innovedus.com/visiona-local/models/v1.0.0/", "models": [ { "id": "kl520-classification-mobilenetv2", "device": "kl520", "task": "classification", "file": "kl520/classification_mobilenetv2.nef", "size_bytes": 6234521, "sha256": "abc123...", "url_path": "kl520/classification_mobilenetv2.nef" }, ... ] } ``` **sha256 欄位必填**:防止下載中間被竄改或損毀。 ### 3.4 下載來源 三選一(M6 前決定): | 選項 | 優點 | 缺點 | |------|------|------| | A. Innovedus 內部 Gitea Releases | 管理簡單、已有通路(若 R11 通過) | 對外需要 VPN | | B. AWS S3 + CloudFront | 速度快、全球 CDN | 需管 IAM / Bucket | | C. GitHub Releases(若 repo 公開) | 免費 + 自帶 CDN | 需公開 repo | **預設建議 B(S3 + CloudFront)**,與 R11 發佈通路解耦(安裝檔仍可放 Gitea,模型走 S3)。 ### 3.5 斷線處理 - **下載中斷** → `downloadWithResume` 支援 HTTP Range,下次啟動繼續 - **全部下載失敗** → 不擋安裝完成,但主 UI 顯示 warning:「預置模型未下載,部分示範功能無法使用」;使用者可在 Settings > 模型 手動點「重新下載預置模型」 - **完全離線環境** → 提供離線包下載頁(使用者自己 scp .nef 到 `data/nef/`),首次啟動偵測到檔案存在則跳過下載 ## 4. 安全與驗證 - sha256 驗證每個下載檔 - HTTPS only(不接受 HTTP) - 下載失敗自動 retry 3 次,指數退避(2s / 5s / 10s) - 下載時顯示進度條(總大小 ~73MB,10Mbps 連線約 60 秒) ## 5. 使用者體驗影響 | 項目 | 原方案(內嵌) | Plan B(線上下載) | |------|--------------|------------------| | 完全離線 | ✅ | ❌(首次需要網路) | | 首次安裝時間 | 3–5 分鐘 | 3–5 分鐘 + 下載時間(約 60–180 秒) | | 後續啟動 | 同 | 同(一次下載後本地使用) | | 使用者須知 | 無 | 首次啟動需要網路、之後離線可用 | ## 6. 估工 | 任務 | 規模 | |------|------| | model_download.go 新寫 | M(~300 行) | | 安裝精靈新增「下載模型」步驟 | S | | manifest 格式與 CDN 結構 | S | | 離線包下載頁與文件 | S | | 測試三平台 + 斷線恢復 | M | | 總計 | **~1 週工程師時間** | ## 7. 觸發後的行動清單 - [ ] 確認 Kneron 回覆書面紀錄 - [ ] 決定下載來源(A/B/C)並建置 - [ ] 實作 `model_download.go` - [ ] 修改安裝精靈 UI - [ ] 修改 payload 打包腳本移除 nef - [ ] 建立離線包下載頁 - [ ] 更新 PRD NFR「完全離線」章節加上註記 - [ ] 更新 packaging 文件與安裝檔大小估算 - [ ] 三平台測試 - [ ] 法務複核 About 頁模型授權聲明