你的 App 只想辨認語言、貼主題標籤或遮掉個資,真的需要把整段文字送到雲端大模型嗎?Desert Ant Labs 在同一個產品家族列出 18 個裝置端模型,答案看似變多,選型反而更難:任務、平台、stable/beta、首次下載與用量回報,只要漏看一項,「能在裝置上跑」就可能在上線前才變成不相容。
這篇會依 2026 年 9 月 11 日可取得的官方 manifest 與 JavaScript SDK v3.1.0,先把 18 個名字縮成真正可裝的候選,再用 Tongue、Gist、Redact 建立一個可重跑的三任務測試殼。這不是替所有手機宣布同一個速度冠軍;你會得到自己的冷載入、暖推論、品質與斷網紀錄,最後做出「留在裝置/受控升級雲端/不用 AI」的可回滾決策。
Desert Ant Labs 先說結論:不是 18 選 1
先記住這條選型公式:可用候選=任務吻合 × 平台可裝 × 資料邊界可接受 × 品質過關。乘號表示四關有一關是零,就不該進產品。排行榜只回答最後一小段;前面三關才是最常被忽略的部署條件。
- 先砍 lifecycle:官方目前列出 12 個 stable、6 個 closed beta;beta 的權重雖存在,但官方明寫「今天沒有可安裝的 SDK」。
- 再砍平台:Swift、Kotlin、JavaScript 並非每個模型都有。JavaScript 現在只有 7 個 stable 模型標示 live。
- 最後才 A/B:不同任務沒有共同的「正確率」。語言辨識看語種與可靠度,分類看允許標籤與 top-k,遮罩看漏遮與誤遮。
Desert Ant Labs 18 個模型怎麼分?
v3.1.0 官方 manifest 是最可靠的第一道篩網。12 個 stable 裡,語音/影音組包括 Align(字詞時間戳校正)、Clear(降噪與去殘響)、Clips(片段挑選)、Ear(語音語種辨識)、Uhm(贅詞定位)與 Voz(語音轉文字);文字與互動組包括 Emo(表情符號建議)、Gist(主題分類)、Redact(PII 遮罩)、Shapes(單筆畫辨識)、Title(標題與描述)及 Tongue(短文字語言辨識)。
6 個 closed beta 則是 Eye(畫面挑選)、Face(人臉比對)、Moderator(NSFW 圖片偵測)、Schemer(依 JSON schema 擷取)、Toxic(仇恨言論分流)與 Who(說話者分段)。這些名稱可以拿來觀察路線圖,不能拿來承諾目前交付日。

這一步也會修正一個很自然、卻會讓教學失真的想法:用 JavaScript 測「摘要」。Title 確實能產生短標題與描述,但目前只標示 Swift/Apple live,Kotlin 與 JavaScript 都是 none。因此本篇改用三個真的有 JavaScript 套件、又代表三種輸出型態的模型:Tongue 語言辨識、Gist 主題分類、Redact 個資遮罩。不是偷換題目,而是讓測試清單服從可安裝事實。
A/B Test 之前,先鎖死四個變因
這裡的 A/B Test 是同一批 fixture(固定測試案例)在兩個環境重跑:A 是可連線的首次載入,B 是斷網後的新程序。它不是把三個用途不同的模型硬排成總榜。開始前建立一份 receipt,至少保存 SDK 版本、作業系統、CPU 架構、裝置型號、電源模式與原始 JSON;如果 App 要支援三年前的低階手機,就不能只測開發者的最新筆電。
1. Tongue:語言答案之外,也看「有多不確定」
痛點:短句很容易同時像兩種語言。解法:每筆同時保存 language、候選清單、reliability 與 isTooCloseToCall;混合語句和只有漢字的日文要獨立成組。官方程式的字系路由會把只含 Han 字元的輸入直接縮到中文,因此「本日休業」這類無假名短句正是不能只看 top-1 的邊界案例。可觀察結果是:不確定時,產品會顯示候選或要求使用者確認,而不是假裝模型必然知道。
2. Gist:分類不是猜一個字,而是對齊你的 taxonomy
痛點:模型的 36 類不一定等於你的內容架構。解法:先替每筆文章定義「允許標籤集合」,用 classify(text, { topK: 3 }) 保存前三名與 score,再加一組不改語意的標題改寫。Gist 官方文件標示支援 101 種語言,但語言覆蓋不等於你的繁中語料已通過;可觀察結果應是同義改寫仍落在可接受集合,而不是某一筆漂亮 demo。
3. Redact:平均分數不如「漏了哪一筆」重要
痛點:PII 任務裡,一個漏遮的電話可能比十個正確遮罩更重要。解法:只用合成姓名、Email、電話與地址建立 golden spans,逐筆算應遮召回與誤遮,並保存 items 的 label、offset、confidence。Redact 文件說明預設神經模型門檻是 0.6,而且 ORG 不在預設遮罩集合;如果你的政策要求公司名也隱藏,就要明確傳入 labels,而不是以為套件會替你決定。

Desert Ant Labs JavaScript 測試殼:從 3 行安裝開始
下面用 Node.js 建一個最小專案。Tongue 是純 JavaScript;Gist 與 Redact 在 Node 要從 /native 匯入。依官方平台說明,native build 支援 Linux x64、Linux arm64 與 Apple Silicon Mac;Windows Node 或其他架構請改走瀏覽器 WASM 路線,不要等到 CI 才發現 binary 不存在。
mkdir desert-ant-eval && cd desert-ant-eval
npm init -y && npm pkg set type=module
npm i --save-exact @desert-ant-labs/tongue@3.1.0 @desert-ant-labs/gist@3.1.0 @desert-ant-labs/redact@3.1.0
新增 eval.mjs。範例刻意不塞入「預期輸出」替你假造成績;它先留下可稽核的原始結果與每次延遲,品質判定再由各任務的 golden fixture 完成。
import { performance } from "node:perf_hooks";
import { writeFile } from "node:fs/promises";
import { Tongue } from "@desert-ant-labs/tongue";
import { Gist } from "@desert-ant-labs/gist/native";
import { Redact } from "@desert-ant-labs/redact/native";
const fixtures = {
Tongue: ["今天要測試本機模型", "This runs on my phone", "本日休業"],
Gist: ["在手機上執行語言辨識、主題分類與個資遮罩"],
Redact: ["王小明的信箱是 alice@example.com,電話 +886 912 345 678。"],
};
const specs = [
{
name: "Tongue",
load: () => Tongue.load(),
run: (m, text) => m.detect(text, 3),
},
{
name: "Gist",
load: () => Gist.load({ cacheRoot: ".dal-cache" }),
run: (m, text) => m.classify(text, { topK: 3 }),
close: (m) => m.dispose(),
},
{
name: "Redact",
load: () => Redact.load({ cacheRoot: ".dal-cache" }),
run: async (m, text) => {
const r = await m.redaction(text);
return { redactedText: r.redactedText, items: r.items };
},
close: (m) => m.dispose(),
},
];
async function bench(spec) {
const loadStart = performance.now();
const model = await spec.load();
const loadMs = performance.now() - loadStart;
const samples = [];
try {
for (const input of fixtures[spec.name]) {
const times = [];
let output;
for (let i = 0; i < 30; i++) {
const start = performance.now();
output = await spec.run(model, input);
times.push(performance.now() - start);
}
samples.push({ input, timesMs: times, output });
}
return { name: spec.name, loadMs, samples };
} finally {
spec.close?.(model);
}
}
const receipt = {
mode: process.env.RUN_MODE ?? "online",
node: process.version,
platform: process.platform,
arch: process.arch,
results: [],
};
for (const spec of specs) receipt.results.push(await bench(spec));
const file = `run-${receipt.mode}.json`;
await writeFile(file, JSON.stringify(receipt, null, 2));
console.log(`saved ${file}`);
第一次保持連線執行 RUN_MODE=online node eval.mjs,讓 Gist 與 Redact 把鎖定 revision 的模型下載到 .dal-cache。接著真正切斷 Wi-Fi/網路,開新程序執行 RUN_MODE=offline node eval.mjs。比較兩份 JSON:B 能否載入、輸出是否仍在允許範圍、暖推論的 p50/p95 是否符合你自己的 UI 預算。不要清掉全域 cache 來模擬冷啟動;用專案專屬目錄,測試才可回滾也不會碰到其他開發資料。
斷網重跑,還要看哪三種封包?
本機推論 ≠ 整個 SDK 零網路。官方文件顯示,Gist、Redact 等模型預設會在首次使用時從 Hugging Face Hub 下載、校驗後快取;也可以透過 Node 的 directory/cacheRoot 或瀏覽器的 modelBaseUrl 自行部署。Tongue 的約 2 MB 權重則隨 npm package 交付。這些是「模型交付」路徑,與輸入在哪裡推論是兩件事。
瀏覽器的 B 組要比 Node 更嚴格:已載入的 instance 能在斷網時推論,不代表重新整理後一定能離線重載。Gist 的 browser filesystem 是記憶體內狀態,重載仍仰賴瀏覽器 HTTP cache;正式產品應把模型與 LiteRT WASM 鎖定版本、自行託管,再用 Service Worker/Cache Storage 管理持久快取,最後以「離線重新整理」實際驗收。
另一條是用量回報。官方的usage protocol列出 https://platform.desertant.ai/api/v1/ingest,payload 包含產生的裝置 ID、平台、App/SDK 資訊與呼叫次數;目前規格明寫不送文字、結果或輸入長度。驗收仍要用瀏覽器 Network panel、Charles/Proxyman 或企業 proxy 保存 host 與 request body:已知模型資產與 ingest 可解釋,測試字串若出現在封包內容則直接 fail。
不要為了得到一張漂亮的「零請求」截圖就關掉正式環境的 metering。現行Desert Ant Labs Source-Available License 1.0要求保留 SDK telemetry,且禁止竄改;測試要驗證真實部署行為,不是繞過它。若組織要求 air-gapped(實體隔離)且完全不能送出用量封包,這不是調一個 flag 就能自行宣告合規,應在採用前取得能覆蓋該部署方式的書面條款。

商用前別漏掉授權與成本門檻
「程式碼看得到」不等於開源。現行授權自稱 source-available,不是 OSI 開源授權;允許把模型嵌入 App,但要求歸屬標示,也限制把模型獨立轉售、做 hosted service,以及利用模型、輸出或紀錄訓練競爭模型。免費門檻是每個平台、每個模型每月未達 100,000 個活躍裝置;同一控制下的 App 會合併計算。換句話說,Tongue 與 Gist、iOS 與 Android 的計數不是一桶混算,但產品團隊也不能只看「總 MAU 還不到十萬」。
實作時把套件版本、隨附 LICENSE.md、模型 revision、必要 attribution 與月活裝置估算一起鎖進 release receipt。這不是文書作業:它決定你何時要談商業授權,也讓日後 SDK 或條款更新時知道哪個版本實際進了產品。
三路決策:留在裝置、升級雲端,或不用 AI
- 留在裝置:任務是窄而清楚的分類/辨識/遮罩,目標裝置都能安裝,斷網 B 組通過,而且尾端延遲不破壞互動。這時本機模型能換來可預測成本與較小的輸入外流面。
- 受控升級雲端:你需要生成、推理或固定 taxonomy 之外的語意,且資料政策允許。先把可本機處理的 PII 遮掉,再只送必要上下文;完整的 Redact+Claude 路由可接著看這篇本機去 PII 教學。
- 不用 AI:語言由使用者設定、主題只有三個確定規則、Email 可用結構式 recognizer 處理時,規則通常更小、更快、也更容易測。不要因為 SDK 存在,就把可確定解決的問題改成機率問題。
整合時再加一層 adapter 與 feature flag,例如 App 只呼叫 classifyLanguage()、tagTopics()、redactPII(),不要讓 UI 直接依賴 vendor 類別。旗標至少保留 off、local、cloud;模型載入失敗時回到明確的無 AI 流程。這與AI Agent Harness強調的邊界相同:把可換的模型包在可驗收、可撤回的外殼裡。
最常見的 7 個踩雷點
- 把 6 個 closed beta 當成可排程依賴;正確做法是只從 manifest 的 live SDK 建 backlog。
- 看到「Swift、Kotlin、JavaScript」就以為每個模型都有三套;實際要逐模型、逐平台查。
- 把首次下載算成每次推論延遲;冷載入與暖推論必須分欄。
- 同一個程序切斷網路就宣布離線;要重開程序,證明不是記憶體裡尚未釋放的模型。
- 只看平均值;互動產品至少看 p50、p95 與最慢裝置,PII 還要逐筆看漏遮。
- 把本機輸入與 SDK telemetry 混成一句「完全不連網」;兩條路徑要各自記錄。
- 讓 UI 直接綁 vendor API;沒有 adapter、feature flag 與無 AI fallback,就很難安全回滾。可搭配Agent Harness 實作指南建立驗收層,再用測試驗證方法保存不會被同一份假設污染的判準。
FAQ:Desert Ant Labs 選型常見問題
1. 18 個模型現在都能安裝嗎?
不能。v3.1.0 manifest 是 12 個 stable、6 個 closed beta;後者目前沒有 SDK 可裝。
2. JavaScript 可以跑 Title 做摘要嗎?
目前不行。Title 的 JavaScript 狀態是 none,而且它的任務是產生標題與一至兩句描述,不應先改名成通用摘要器。
3. 本機模型是否代表完全離線?
推論可以離線,不代表預設沒有任何網路。多數模型首次要下載權重,SDK 另有用量回報;要靠預先部署與斷網新程序證明你的實際路徑。
4. 用量回報會送出使用者文字嗎?
依目前官方 protocol,不會。規格列出的欄位是裝置 ID、平台、App/SDK 與呼叫數,並明寫不含輸入、輸出或文字長度;產品端仍應保存 network trace 驗收。
5. Desert Ant Labs 是開源嗎?
不是一般所說的開源。它採自己的 source-available license,有查看與嵌入權,也有用途、遙測、歸屬與競爭模型限制。
6. 低於 10 萬使用者就一定免費嗎?
不能用總使用者數一句帶過。現行門檻按每個模型、每個平台的月活裝置判定,同一控制下 App 還要合併;上線前應以實際 package 內條款核對。
7. 三個任務可以用同一個品質分數嗎?
不可以。Tongue 看語種與不確定性,Gist 看允許標籤與排序,Redact 看漏遮與誤遮;只有載入、延遲、錯誤率與網路紀錄可以共用格式。
8. 什麼時候應該升級雲端或不用 AI?
窄任務品質不足但需要開放式生成時,才考慮受控雲端;規則已能穩定解決時,就不用 AI。決策依任務與資料政策,不依模型數量。
給新手的 7 個重點
- 先查 lifecycle,closed beta 不算今天可交付。
- 再查單一模型的平台矩陣,不看家族級口號。
- 固定 SDK、模型 revision、裝置與 fixture。
- 冷載入、暖推論、品質與網路分開記。
- 斷網後要重開程序,不能只關掉一個 tab。
- 商用前保存 license、attribution 與月活裝置估算。
- 所有整合都要有 adapter、feature flag 與無 AI fallback。
接著閱讀
左右滑動查看更多推薦
結語:先縮候選,再讓自己的裝置回答
Desert Ant Labs 真正值得學的,不是「一次有 18 個模型」,而是裝置端 AI 選型終於可以拆成可驗收的小問題。回到文章開頭的公式:任務吻合、平台可裝、資料邊界可接受、品質過關,四項都成立才是候選。今天先複製測試殼、加入你產品最容易失敗的 10 筆 fixture,跑完 online/offline 兩份 receipt;若要把這套驗收思路擴成完整開發流程,可從 AlphaLab 的實作課程接著建立自己的可回滾 AI 工作流。






