把會議紀錄整理成待辦事項,應該在手機上跑小型語言模型,還是送到伺服器處理?假設一款 App 要從會議紀錄擷取「負責人、行動、期限」,而且不能憑空補出日期。這是有邊界的擷取任務,不是研究會議主題的開放式助理。本機推論可避免傳送原始紀錄,但答案仍取決於 App、支援的手機及網路政策,不能只看模型標示的參數規模。
先定義工作,再選處理路徑
先訂輸出欄位和停止規則:原文沒有負責人或期限,就標示「未註明」;未經確認,不發送行事曆邀請。拿同一批留出的會議紀錄,比較規則式擷取器、本機小模型、伺服器模型及混合路由。對這種受限任務,規則式方法可能反而勝出。Meta 的Llama 3.2 公告介紹可用於摘要與改寫等邊緣工作負載的 1B、3B 文字模型;這證明有此類模型可選,不能證明它適合你的流程。平台支援也要查版本:Google 的LLM Inference 指南將 Android、iOS 實作標為已棄用,並引導行動端專案轉往 LiteRT-LM;網頁版並未列為已棄用。請鎖定要測的執行環境與模型版本,而不是依「邊緣 AI」標籤設計產品。
只有本機方案通過全部硬性門檻,包括離線可用性,才選本機。只有允許資料外傳,而且實測端到端收益值得承擔時,才考慮伺服器。混合方案也不是免費折衷:路由判斷、使用者同意及離線失敗時的行為,都得納入產品設計。若涉及受法規規範或特別敏感的文字,先做法律與資安審查;本文不能代替合規判定。
讓另一個團隊也能重做的測試
- 凍結測試集。從預定流程蒐集經同意、去識別化的會議紀錄,涵蓋一般、長篇、多語、OCR 雜訊、語意模糊、互相矛盾及對抗性案例。另留一組不參與調整的測試資料,標註版本,事先訂好各類案例的最低品質與該拒答時的正確行為。兩位審查者若判斷不同,回頭對照原始紀錄裁決,不要被模型流暢的措辭說服。
- 固定比較條件。記錄 App 版本、作業系統、裝置級距(含最低規格的支援機型)、執行環境與後端、模型及量化版本雜湊、提示詞與欄位格式、分詞器、輸入輸出長度、伺服器區域、網路類型及併發量。至少在兩種電量與散熱狀態重複測試,隨機變換候選方案順序,公布分布和信賴區間,而不是只挑最快的一次。一份裝置端推論研究比較了不同模型、量化與裝置配置;它支持「配置會影響結果」,不是可直接套用到你的手機上的跑分。
- 測量完整體驗。分開記錄全新啟動與暖機後的首次有用輸出時間、完成時間(p50/p95)、各類案例品質、拒答與錯誤率、其他 App 同時運作時的峰值工作記憶體、儲存與下載量,以及每個完成任務新增的電池耗能。把前處理、模型載入、排隊、上傳、路由與後處理全部算進去,並與現有流程比較。Apple 的電池用量分析指南介紹 Xcode、MetricKit 與 Instruments,也提醒溫度限制;請用平台工具與受控基線量測,不要拿每秒 token 數當耗能指標。
- 刻意弄壞路徑。測試飛航模式、需登入的 Wi‑Fi、慢速或斷續網路、伺服器逾時、模型下載失敗、裝置空間不足、記憶體吃緊、權限撤回、舊版作業系統及模型更新。記錄輸出是否正確、延遲、拒絕,或悄悄改走其他路徑;檢查網路遙測及當機回報的內容,確認哪些原始欄位真的離開裝置。
保留各方案逐筆結果和失敗類別。如果沒有路徑通過門檻,不要靠平均分硬選贏家;可縮小任務、增加人工覆核,或維持原流程。量化、提示詞或執行環境更新後,要重跑同一套測試。冷啟動成本可能顛倒暖機展示的排名;離線要求也可能讓遠端方案直接出局。
一個刻意使用虛構資料的決策門檻
以下 Python 3 標準函式庫程式不需要模型或網路。表格中的所有數值與門檻都是為演練政策而虛構,並非裝置實測或建議值。將程式存成 decision_harness.py,依序執行 python decision_harness.py 和 python decision_harness.py --allow-egress --no-offline。實際決策時以自己的 App 量測值替換資料列,政策門檻則應在看結果之前議定。「每月」金額只是虛構、可比較的營運成本估值,並非完整總持有成本;裝置耗能不包含伺服器用電。
#!/usr/bin/env python
"""Illustrative decision gate, NOT a model or device benchmark. Python 3 stdlib.
Usage: python decision_harness.py [--allow-egress] [--no-offline]
Replace ROWS with measured values from your own application and devices.
"""
import argparse
# Each row represents one workload stratum, with cold/warm application completion
# latency (seconds), measured peak working set (MiB), incremental device energy
# (joules/request), independently adjudicated task success fraction, and flags.
# All numbers below are fabricated to exercise the policy; do not quote them as
# hardware performance or infer server-side energy from device energy.
ROWS = [
dict(route="local", stratum="routine", quality=.97, cold=2.8, warm=.8,
memory=740, energy=3.2, raw_exits=False, offline=True, monthly=95),
dict(route="local", stratum="hard", quality=.77, cold=4.6, warm=1.8,
memory=790, energy=5.1, raw_exits=False, offline=True, monthly=95),
dict(route="hybrid", stratum="routine", quality=.97, cold=3.0, warm=.9,
memory=760, energy=3.4, raw_exits=False, offline=True, monthly=110),
dict(route="hybrid", stratum="hard", quality=.94, cold=5.1, warm=2.4,
memory=760, energy=4.6, raw_exits=True, offline=False, monthly=110),
dict(route="server", stratum="routine", quality=.98, cold=2.1, warm=1.2,
memory=130, energy=1.0, raw_exits=True, offline=False, monthly=140),
dict(route="server", stratum="hard", quality=.96, cold=3.8, warm=2.7,
memory=130, energy=1.5, raw_exits=True, offline=False, monthly=140),
]
# Example policy only: substitute thresholds, strata and costs before a real decision.
QUALITY_FLOOR = {"routine": .90, "hard": .90}
MAX_COLD_S, MAX_WARM_S = 6.0, 3.0
MAX_MEMORY_MIB, MAX_DEVICE_ENERGY_J = 900, 6.0
def assess(rows, allow_egress=False, require_offline=True):
by_route = {}
for row in rows:
by_route.setdefault(row["route"], []).append(row)
results = {}
for route, entries in sorted(by_route.items()):
issues = []
strata = [r["stratum"] for r in entries]
if sorted(strata) != sorted(QUALITY_FLOOR):
issues.append("missing/duplicate strata")
if len({r["monthly"] for r in entries}) != 1:
issues.append("inconsistent monthly cost")
for r in entries:
label = r["stratum"]
if label not in QUALITY_FLOOR or r["quality"] < QUALITY_FLOOR.get(label, 1):
issues.append(label + ": quality")
if r["cold"] > MAX_COLD_S or r["warm"] > MAX_WARM_S:
issues.append(label + ": latency")
if r["memory"] > MAX_MEMORY_MIB:
issues.append(label + ": memory")
if r["energy"] > MAX_DEVICE_ENERGY_J:
issues.append(label + ": device energy")
if r["raw_exits"] and not allow_egress:
issues.append(label + ": raw data egress")
if not r["offline"] and require_offline:
issues.append(label + ": offline failure")
results[route] = (entries[0]["monthly"], issues)
eligible = [(cost, route) for route, (cost, issues) in results.items() if not issues]
return results, min(eligible)[1] if eligible else None
def main():
p = argparse.ArgumentParser(description=__doc__)
p.add_argument("--allow-egress", action="store_true")
p.add_argument("--no-offline", action="store_true")
args = p.parse_args()
results, winner = assess(ROWS, args.allow_egress, not args.no_offline)
for route, (cost, issues) in sorted(results.items()):
print(f"{route}: ${cost}/month; " + ("PASS" if not issues else "FAIL: " + ", ".join(issues)))
print("Decision:", winner or "no eligible route; redesign, relax policy explicitly, or stop")
if __name__ == "__main__":
main()
預設情境下,本機方案未達困難案例的品質門檻;混合方案違反離線與原始資料不得外傳的門檻;伺服器方案也違反這兩項門檻,因此結論是沒有合格方案。若明確允許資料外傳、也不要求離線,混合方案通過,且其虛構月成本低於伺服器方案。這只是條件式範例,不能據此取消任何要求。程式只為每類案例設定一個整體品質比例,也沒有呈現各種散熱狀態的多次觀察;真實資料還需要不確定性區間、p95 尾端、隱私稽核證據、明確的抽樣比例,以及成本與門檻的敏感度分析。
手機與團隊各要付出什麼
模型檔大小不等於 App 峰值記憶體:分詞器、KV 快取、執行環境緩衝區、輸入長度及同時運作的 App 都會佔資源。下載與儲存、首次載入和持續推論要分開估算。量化可能同時改變大小與回答品質。走伺服器時,每次請求成本還包括輸入輸出量、重試、區域、資料保留與支援;混合路由增加開發、驗證與監控成本,本機則增加跨裝置測試、發佈、更新及使用者電池負擔。用預期請求組合及高用量情境比較成本,別把手機耗電當成整個系統的能源足跡。
本機可能給出看似合理、其實不存在的期限;遠端可能把私人紀錄傳出去;混合路由若錯判困難案例或逾時時偷偷切換,可能同時犯兩種錯。為每條路徑訂好停止狀態。介面應明示「在裝置上處理」或「傳送以進行加強處理」;若承諾本機處理,後者須取得使用者明確同意。離線的意思應是不嘗試遠端連線,而不是讓使用者無止境等待後備方案。延伸閱讀:Meydo Journal 的手機硬體討論探討較廣的裝置限制;本文聚焦於一個有明確邊界的流程。
資料走到哪裡,安全邊界就到哪裡
本機推論減少一條傳輸路徑,但共用、遺失或遭入侵的手機仍有風險。盤點本機紀錄快取、模型包、日誌、遙測、備份及當機回報;盡量少存敏感資料,明訂保留與刪除方式。混合路由器必須在上傳文字之前做決定;日誌要能查出使用了哪條路徑,但不必因此長期保留原始紀錄。平台的隱私保證不可直接移植:Google 的AICore 文件說明其自身處理流程的請求隔離與不保留輸入輸出,不保證其他 App 的分析工具或伺服器後備流程也如此。
鎖定並驗證模型與執行環境檔案的完整性,透過可信任的更新通道發佈,分階段推出,保留測試過的回復版本;每次變更都重跑品質與隱私檢查。即使沒有雲端請求,遭竄改的模型包或藏有提示注入的會議紀錄仍可能跨越信任邊界。將擷取出的待辦事項視為未受信任的建議;送出行事曆邀請或採取其他對外行動前,必須由人確認。上線選擇因此是營運決策:只有最低規格支援裝置的實測體驗及離線拒絕行為都通過預定門檻,才推出本機方案;否則,在允許且取得明確同意時選混合/伺服器方案,或暫不自動化這項工作。
