local-tool/: visionA-local desktop app
- M1: Wails shell + Go server + Next.js UI + Mock mode (macOS dmg ready)
- M2: i18n (zh-TW/en) + Settings 4-tab refactor
- M3: Embedded Python 3.12 runtime (python-build-standalone) + KneronPLUS wheels
- M4: Windows Inno Setup script (build on Windows runner)
- M5: Linux AppImage script + udev rule (build on Linux runner)
- M6: ffmpeg (GPL, pending legal review) + yt-dlp bundled
- Lifecycle: watchServer health check, fatal native dialog,
Wails IPC raise endpoint, stale process cleanup
.autoflow/: full PRD / Design Spec / Architecture / Testing docs
(4 rounds tri-party discussion + cross review)
.github/workflows/: macOS / Windows / Linux build CI
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
5.5 KiB
5.5 KiB
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
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() 之前,插入一個「模型下載」精靈步驟。
// 流程
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(擴充原有格式):
{
"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 頁模型授權聲明