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轮简单问答、FAQ机器人
    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个token,以实现更平滑的文本呈现:

    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交互时加载: 不要在应用启动时加载。在用户打开聊天功能时加载。
    • 活跃会话期间保持加载: 当用户在聊天中时,保持模型在内存中。
    • 离开时卸载: 当用户离开聊天界面时,卸载模型以释放内存。
    • 处理内存警告: 注册系统内存警告,触发时卸载模型。

    加载指示器

    模型首次加载时显示简短的加载状态(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