Back to blog
    為你的行動應用打造裝置端 AI 助手
    AI assistanton-device AIchatmobile AIimplementationsegment:mobile-builder

    為你的行動應用打造裝置端 AI 助手

    建構完全在使用者裝置上運行的對話式 AI 助手的架構模式。模型選擇、對話管理、UI 模式和生產環境考量。

    EErtas Team·

    裝置端 AI 助手是由在使用者手機上本地運行的語言模型驅動的對話介面。無雲端 API、無網路依賴、即時回應、完全隱私。

    本指南涵蓋從模型選擇到生產部署的架構。

    架構概覽

    裝置端助手有四個層次:

    1. 模型層: llama.cpp 載入並運行 GGUF 模型
    2. 對話層: 管理聊天歷史、系統提示詞和上下文視窗
    3. 介面層: 具有串流 token 顯示的聊天 UI
    4. 狀態層: 持久化對話、管理模型生命週期

    聊天的模型選擇

    對話式 AI 受益於較大的模型。微調 3B 模型是建議的起點:

    模型大小聊天品質多輪連貫性建議用途
    1B尚可2-3 輪簡單問答、常見問題機器人
    3B良好5-8 輪完整聊天助手

    微調對聊天至關重要。基礎 3B 模型會產生通用回應。微調 3B 模型用你的品牌語調說話、了解你的產品,並處理你的特定使用場景。

    對話管理

    提示詞範本

    每個模型系列都有特定的聊天範本。Llama 3.2 的範本:

    <|begin_of_text|><|start_header_id|>system<|end_header_id|>
    
    You are the RecipeHelper assistant. Help users find and modify recipes. Always include prep and cook times.<|eot_id|><|start_header_id|>user<|end_header_id|>
    
    Quick dinner for two?<|eot_id|><|start_header_id|>assistant<|end_header_id|>
    

    微調時,訓練框架會自動處理範本格式化。在推論時,你的應用程式必須在發送給 llama.cpp 之前將對話格式化為此範本。

    上下文視窗管理

    行動模型通常使用 2048-4096 token 的上下文視窗(可設定,但較大的視窗使用更多記憶體並減慢推論速度)。對話可能很快超過此限制。

    滑動視窗方法: 保留系統提示詞和最近的 N 輪對話。當視窗填滿時丟棄最舊的輪次:

    func buildPrompt(systemPrompt: String, turns: [Turn], maxTokens: Int) -> String {
        var prompt = formatSystem(systemPrompt)
        var tokenCount = countTokens(prompt)
    
        // 從最新到最舊加入輪次,視窗滿時停止
        var includedTurns: [Turn] = []
        for turn in turns.reversed() {
            let turnTokens = countTokens(formatTurn(turn))
            if tokenCount + turnTokens > maxTokens - 512 { break } // 為回應保留 512
            includedTurns.insert(turn, at: 0)
            tokenCount += turnTokens
        }
    
        for turn in includedTurns {
            prompt += formatTurn(turn)
        }
    
        return prompt
    }

    摘要方法: 當對話超出視窗時,將較舊的輪次摘要為緊湊的上下文並前置到系統提示詞中。這在保持 token 預算內的同時保留了關鍵資訊。但這需要一次額外的推論呼叫。

    對話持久化

    將對話儲存在本地儲存中(iOS 的 Core Data、Android 的 Room),以便使用者可以從上次中斷的地方繼續:

    • 儲存每則訊息(角色、內容、時間戳記)
    • 儲存對話元資料(標題、建立日期、最後活躍時間)
    • 限制儲存的對話數量以防止無限制的儲存增長
    • 允許使用者刪除對話

    串流 UI

    聊天介面應在 token 生成時即時顯示。這創造了快速、回應即時的助手感覺。

    iOS(SwiftUI)

    struct ChatView: View {
        @StateObject var viewModel = ChatViewModel()
    
        var body: some View {
            ScrollView {
                ForEach(viewModel.messages) { message in
                    MessageBubble(message: message)
                }
            }
            .onChange(of: viewModel.streamingText) { _ in
                // 自動捲動到底部
            }
    
            HStack {
                TextField("Message", text: $viewModel.input)
                Button("Send") { viewModel.send() }
            }
        }
    }

    Android(Compose)

    @Composable
    fun ChatScreen(viewModel: ChatViewModel) {
        val messages by viewModel.messages.collectAsState()
        val streaming by viewModel.streamingText.collectAsState()
    
        LazyColumn {
            items(messages) { message ->
                MessageBubble(message)
            }
            if (streaming.isNotEmpty()) {
                item { StreamingBubble(streaming) }
            }
        }
    
        Row {
            TextField(value = input, onValueChange = { input = it })
            Button(onClick = { viewModel.send(input) }) { Text("Send") }
        }
    }

    Token 顯示節奏

    llama.cpp 一次生成一個 token。逐一顯示每個 token 可能導致視覺抖動。在更新 UI 之前緩衝 2-3 個 tokens,以獲得更流暢的文字顯示效果:

    private var tokenBuffer = StringBuilder()
    private var bufferCount = 0
    
    fun onToken(token: String) {
        tokenBuffer.append(token)
        bufferCount++
        if (bufferCount >= 3 || token.contains("\n")) {
            updateUI(tokenBuffer.toString())
            tokenBuffer.clear()
            bufferCount = 0
        }
    }

    模型生命週期管理

    載入與卸載

    模型載入需要 1-3 秒,取決於模型大小和裝置。卸載是即時的。管理生命週期以平衡回應性與記憶體:

    • 在首次 AI 互動時載入: 不要在應用啟動時載入。在使用者開啟聊天功能時載入。
    • 在活躍會話期間保持載入: 使用者在聊天中時,保持模型在記憶體中。
    • 離開時卸載: 使用者離開聊天畫面時,卸載模型以釋放 RAM。
    • 處理記憶體警告: 註冊系統記憶體警告,觸發時卸載模型。

    載入指示器

    模型首次載入時顯示短暫的載入狀態(1-3 秒)。之後,回應會立即開始生成。使用者已習慣新功能的短暫載入狀態。

    為你的助手微調

    基礎模型和微調模型在聊天方面的品質差距是巨大的:

    指標基礎 3B微調 3B
    切題回應60-70%92-96%
    格式遵循55-65%94-98%
    領域準確度50-60%88-94%
    語調一致性40-50%90-95%

    聊天的訓練資料

    建立涵蓋以下內容的訓練範例:

    1. 常見問題: 使用者最常問的 50-100 個問題
    2. 邊界情況: 超出範圍的問題,搭配優雅的重新導向回應
    3. 多輪模式: 跨越 3-5 輪的對話,展示自然的後續追問
    4. 風格範例: 使用你品牌語調和偏好格式的回應

    500-2,000 個訓練對話可產出高品質的聊天助手。像 Ertas 這樣的平台處理訓練流程:上傳對話範例、使用 LoRA 微調、匯出 GGUF。

    生產環境考量

    回應品質防護欄

    裝置端模型可能生成偏離主題或不正確的回應。實施輕量級防護欄:

    • 輸入驗證: 檢查超長輸入或明顯的非文字內容
    • 輸出監控: 在本地記錄回應主題以識別品質問題
    • 回饋機制: 讓使用者標記不良回應。利用此回饋改善訓練資料

    效能監控

    追蹤裝置端指標:

    • 首個 token 時間(應低於 300ms)
    • 每秒 tokens 數(應保持在 10 以上)
    • 模型載入時間
    • 推論時的記憶體使用量
    • AI 互動期間的當機率

    模型更新

    透過你正常的模型傳遞流程推送模型改進:

    • 在應用啟動時檢查更新(有連線時)
    • 在背景下載
    • 在下一次聊天會話開始時替換模型檔案
    • 保留舊模型作為後備,直到新模型驗證通過

    最終結果是一個無處不在、即時回應、每次對話零成本、並完全保護使用者資料隱私的聊天助手。

    Ship AI that runs on your users' devices.

    Early bird pricing starts at $14.50/mo — locked in for life. Plans for builders and agencies.

    Ship AI that runs on your users' devices.

    Early bird pricing starts at $14.50/mo — locked in for life. Plans for builders and agencies.

    Keep reading