content generationon-device AIdraftingmobile AIimplementation
端侧内容生成:离线也能用的 AI 草稿功能
如何构建无需互联网即可运行的 AI 草稿功能。邮件回复、消息建议、笔记扩展和内容模板,全部在用户设备上本地生成。
Edward Xi Yang
邮件回复建议、消息自动补全、笔记扩展、社交帖子草稿。这些功能有一个共同模式:用户提供简短输入,AI 生成更长、更精练的输出。
内容生成是端侧 AI 最自然的应用场景之一(仅次于分类)。它充分发挥了语言模型的优势,同 时保持在移动设备硬件的性能预算之内。
端侧生成擅长处理的场景
短文本内容(200 词以内)
| 应用场景 | 输入 | 输出 | 模型大小 |
|---|---|---|---|
| 邮件回复 | 收到的邮件 + "接受" | 2-3 句回复 | 3B |
| 消息建议 | 对话上下文 | 3-5 个回复选项(每个 1 句话) | 1-3B |
| 笔记扩展 | 要点列表 | 段落 | 3B |
| 社交文案 | 照片上下文 + 关键词 | 1-2 句文案 | 1-3B |
| 评论回复 | 帖子 + 用户情感 | 1-2 句回复 | 1-3B |
| 表单填充 | 字段标签 + 上下文 | 建议值 | 1B |
短文本生成是最佳应用场景。模型生成 50-200 个 token(1-3 句话到一个短段落),3B 模型耗时 2-5 秒,1B 模型耗时 1-3 秒。
中等长度内容(200-500 词)
| 应用场景 | 输入 | 输出 | 模型大小 |
|---|---|---|---|
| 邮件草稿 | 主题 + 要点 | 完整邮件正文 | 3B |
| 会议摘要 | 会议记录摘录 | 摘要段落 | 3B |
| 产品描述 | 产品名称 + 特性 | 营销文案 | 3B |
| 博客大纲 | 主题 + 受众 | 结构化大纲 | 3B |
中等长度内容在 3B 模型上需要 5-15 秒。当用户主动请求草稿(点击"起草邮件"按钮)时这是可接受的,但对于内联建议来说太慢了。
架构模式
一键起草
参与度最高的模式。向用户展示一个按钮,根据上下文生成完整草稿:
[收到关于安排会议的邮件]
[接受] [拒绝] [建议替代方案]
> 点击"接受"
草稿:"感谢您的来信。周二下午 2 点对我来说没问题。
我会发送日历邀请。期待与您的会面。"
[发送] [编辑]
AI 根据用户选择的操作生成草稿。无需打字。用户审阅后发送(或先编辑)。
内联自动补全
当用户打字时,提供补全建议:
用户输入:"感谢更新。我会查看这个..."
建议(灰色文字):"...文档,并在周五之前给您回复。"
[按 Tab 接受]
自动补全要求最低延迟。建议必须在用户停顿后 200-300 毫秒内出现。在旗舰设备上使用 1B 模型可以实现(35-50 tok/s = 200 毫秒内生成 7-10 个词)。
模板扩展
用户选择模板,AI 填入上下文细节:
模板:"会议后跟进"
上下文:与 Sarah 关于 Q3 预算审查的会议
生成内容:
"Sarah 您好,感谢今天关于 Q3 预算审查的富有成效的讨论。
如约定,我会在下周三之前准备好修订后的预测。
如有其他需要,请随时告知。"
实现方式
生成接口
// iOS:草稿生成
class DraftGenerator {
private let model: LlamaContext
func generateReply(
incomingMessage: String,
action: ReplyAction,
onToken: @escaping (String) -> Void
) async -> String {
let prompt = buildPrompt(message: incomingMessage, action: action)
var fullResponse = ""
await model.generate(prompt: prompt, maxTokens: 256) { token in
fullResponse += token
onToken(token) // 流式输出到 UI
}
return fullResponse
}
private func buildPrompt(message: String, action: ReplyAction) -> String {
return """
Write a brief reply to this message. Action: \(action.rawValue)
Message: \(message)
Reply:
"""
}
}多条建议
生成 2-3 个替代草稿,让用户选择:
// Android:生成多条建议
suspend fun generateSuggestions(
context: String,
count: Int = 3
): List<String> {
return (1..count).map {
model.generate(
prompt = buildSuggestionPrompt(context),
maxTokens = 64,
temperature = 0.8f // 更高的温度以产生多样性
)
}
}建议之间使用 0.7-0.9 的温度以获得多样性。当需要单一一致的高质量草稿时,使用较低温度(0.1-0.3)。
上下文管理
好的草稿需要好的上下文。为模型提供: