Skip to content

AI 子系统设计

爱生活 的 AI 子系统采用双引擎架构,同时支持端侧推理和云端 Agent,确保在离线/弱网环境下也能提供智能助理体验。

1. 整体架构

┌─────────────────────────────────────────────────────────────┐
│                      表示层 (UI)                              │
│  AI 对话界面  │  快捷指令  │  智能补全  │  每日摘要           │
└─────────────────────────────────────────────────────────────┘


┌─────────────────────────────────────────────────────────────┐
│                   AI Agent 服务层                             │
│  cloudAgentChat()  │  edgeAgentChat()  │  parseActions()     │
└───────────────────────────┬─────────────────────────────────┘

              ┌─────────────┴─────────────┐
              ▼                           ▼
┌──────────────────────┐    ┌──────────────────────┐
│     云端 AI 引擎      │    │     边缘 AI 引擎      │
│                      │    │                      │
│  SSE 流式对话         │    │  Llama.cpp (App)     │
│  + Agent Pipeline    │    │  Transformers.js(H5) │
└──────────────────────┘    └──────────────────────┘
              │                           │
              ▼                           ▼
┌──────────────────────┐    ┌──────────────────────┐
│   Action 注册中心     │    │     模型管理器        │
│   40+ 原子操作        │    │   8 个预置模型        │
└──────────────────────┘    └──────────────────────┘
              │                           │
              ▼                           ▼
┌─────────────────────────────────────────────────────────────┐
│                    数据层 (Repository)                        │
└─────────────────────────────────────────────────────────────┘

设计原则

  • 离线优先:端侧 AI 可在完全离线环境下运行,覆盖核心操作
  • 能力对等:云端与端侧的 Action 注册表共享同一套 Schema 定义
  • 优雅降级:云端不可用时自动切换端侧;端侧不支持的操作提示用户联网
  • 流式体验:两端均支持流式输出,首字延迟控制在 500ms 以内

2. 边缘 AI 引擎

边缘 AI 让核心智能能力不依赖网络,始终可用。根据平台选择不同的推理方案:

维度App (iOS / Android)H5 (Web)
推理引擎Llama.cpp (Native)Transformers.js (WASM)
模型格式GGUFONNX / safetensors
硬件加速Metal (iOS) / Vulkan (Android)WebGPU (可选)
流式支持原生异步流式浏览器端迭代
存储位置_doc/models/IndexedDB

2.1 推理管线 (H5)

/src/ai/pipeline.ts — H5 端使用 Transformers.js 加载和运行模型,基于 WebAssembly 执行推理:

用户输入 → Tokenizer 编码 → 模型推理 → Tokenizer 解码 → 流式输出

管线的核心职责:

  • 初始化 Transformers.js 环境(WASM 运行时、模型配置)
  • 提供 downloadOnly() 接口,供模型管理器单独下载模型文件
  • 封装推理调用,屏蔽底层 API 差异

2.2 流式引擎

/src/ai/edge-stream.ts — 统一封装不同平台的流式推理接口,对上层提供一致的流式 API。

iOS 异步流式方案

端侧模型通过异步 Native 桥接实现真正的逐 token 输出:

chatStreamStart(modelId, messages)  → 启动推理会话

chatStreamPoll(sessionId)           → 每 120ms 轮询一次

chatStreamStop(sessionId)           → 停止推理

轮询间隔固定为 120ms,在延迟与性能之间取得平衡。返回协议格式:

STATUS | tokensUsed | promptTokens | delta
字段说明
STATUS状态码:0=生成中, 1=正常结束, 2=错误, 3=已停止
tokensUsed累计已消耗 token 数
promptTokens提示词 token 数
delta本次增量文本内容

Android 同步回退方案

当异步流式不可用时,回退到同步 chatStream() 调用,一次性获取完整结果。Android 上也计划支持异步轮询方案,当前以同步方式保障兼容性。

错误码映射

错误码含义
1会话未找到
2模型未加载
3推理引擎内部错误
4超时
5内存不足
6token 超限
7未知错误

对外暴露的函数

  • edgeChatStream(modelId, messages, onChunk) — 自动选择平台最优方案
  • edgeStopChatStream(sessionId) — 停止当前流式推理
  • 内部 chatStreamStart() / chatStreamPoll() / chatStreamStop() — iOS 三阶段原语

3. 模型管理

/src/ai/model-manager.ts — 管理端侧模型的完整生命周期:发现、下载、加载、切换、卸载。

3.1 模型目录

系统预置 8 个模型,按功能分为推理和嵌入两类:

模型名称参数量用途GGUF 大小适用平台
TinyLlama 1.1B1.1B通用对话~650MBApp + H5
Qwen2.5-0.5B0.5B轻量对话~350MBApp + H5
Qwen3-0.6B0.6B对话(新一代)~380MBApp + H5
Qwen2.5-1.5B1.5B高质量对话~900MBApp
Phi-3 Mini3.8B高性能推理~2.2GBApp
Gemma 2B2B通用推理~1.2GBApp
MiniLM22M文本嵌入~40MBApp + H5
BGE Small24M中文嵌入~45MBApp + H5

嵌入模型(MiniLM、BGE Small)用于语义搜索、知识库检索等非对话场景,参数量小,可同时常驻内存。

3.2 模型下载

H5 端(IndexedDB 存储)

模型管理器.downloadModel(modelId)
    → pipeline.downloadOnly(modelId, onProgress)
        → Transformers.js 下载模型到浏览器 IndexedDB

模型文件由 Transformers.js 内部管理,存储在浏览器 IndexedDB 中。前端通过 onProgress 回调获取下载进度。

App 端(GGUF 文件存储)

模型管理器.downloadModel(modelId)
    → uni.downloadFile({ url: modelUrl, filePath: `_doc/models/${filename}` })
        → 写入应用私有目录
            → 校验文件完整性 (MD5)

GGUF 文件存储在 {APP_DOC_DIR}/models/ 目录下。下载完成后执行 MD5 校验,确保文件完整。

3.3 模型加载

加载模型到内存中用于推理:

typescript
// App 端:Llama.cpp 加载 GGUF,全量 GPU 卸载
loadModel(modelId, { gpuLayers: -1 })

// H5 端:Transformers.js 从 IndexedDB 加载
loadModel(modelId)

App 端使用 gpuLayers: -1 将所有层卸载到 GPU(Metal / Vulkan),最大化推理速度。H5 端通过 Transformers.js 从 IndexedDB 读取模型文件到 WASM 内存。

ModelManager 维护一个已加载模型列表,仅允许同时加载 1 个对话模型(内存限制),嵌入模型可常驻。

3.4 ModelInfo 结构

每个模型对应一个 ModelInfo 对象:

字段类型说明
idstring模型唯一标识,如 qwen2.5-0.5b
namestring显示名称,如 Qwen2.5-0.5B
descriptionstring中文描述
urlstringGGUF 下载地址(App)
sizestring模型大小估算,如 ~350MB
parametersstring参数量,如 0.5B
typeenumchat / embedding
quantizationstring量化方式,如 Q4_K_M
hfModelIdstringHuggingFace 模型 ID(H5)

4. 云端 AI Agent

/src/services/ai-agent.service.ts — 云端 AI 的核心服务,负责对话管理和 Agent 指令执行。

4.1 流式对话

云端使用 SSE (Server-Sent Events) 实现流式对话:

用户输入 → 构建上下文 → POST /api/chat (SSE) → 逐 token 流式返回 → UI 实时渲染

SSE 连接持有对话历史,后端将完整上下文发送给大语言模型,模型以 data: {"delta":"..."} 格式逐 token 返回。前端每收到一个 chunk 立即追加到 UI,提供打字机效果。

4.2 Agent 指令解析

AI 回复中包含 [ACTION]...[/ACTION] 标记块,Agent 解析这些块并执行对应的数据操作:

[ACTION]
{ "name": "create_task", "content": "完成季度报告", "dueDate": "2026-08-08" }
[/ACTION]

解析流程:

AI 完整回复
    ↓ 正则匹配 [ACTION]...[/ACTION]
提取 JSON 块
    ↓ JSON 修复(见下文)
解析为 ActionCommand
    ↓ 查找 Action 注册表
执行 execute()

返回执行结果 → 追加到对话上下文

4.3 JSON 修复策略

边缘 AI 模型输出的 JSON 往往不完美,系统内置多层修复逻辑:

  • 标点修复:将中文标点("")替换为英文标点
  • 引号补全:缺失的属性名引号自动添加
  • 括号平衡:缺失的 { / } 自动补齐
  • 容错解析:优先使用 JSON.parse(),失败后回退到宽松解析器

此设计让端侧小模型也能可靠执行结构化操作,降低对云端模型的依赖。

4.4 Agent 对话函数

函数说明
cloudAgentChat(messages, onChunk)云端 SSE 流式对话 + Agent 指令解析
edgeAgentChat(messages, onChunk)端侧流式对话 + Agent 指令解析
parseActions(content)从文本中提取并执行所有 [ACTION]

两个对话函数接口一致,上层调用方无需关心使用的是云端还是端侧引擎——这也是"双引擎对等"的体现。

5. Action 注册中心

/src/ai/actions.ts — 定义 Agent 可执行的所有原子操作。云端和端侧共享同一份 Action 注册表。

5.1 Action Schema 结构

每个 Action 遵循统一的结构:

typescript
interface ActionDefinition {
  name: string           // 操作名,对应 JSON 中的 name 字段
  description: string    // 操作描述,写入 System Prompt 供 AI 理解
  schema: ZodSchema      // 参数校验 Schema(基于 Zod)
  execute: (params) => Promise<ActionResult>  // 执行函数
}

interface ActionResult {
  success: boolean
  message: string        // 人类可读的结果描述,反馈给 AI
  data?: any
}

5.2 已注册 Action 清单

系统共注册 40+ 个原子操作,覆盖全部 8 个模块分类:

任务管理(Task):

Action说明
create_task创建任务
complete_task完成任务
list_tasks查询任务列表
update_task更新任务
delete_task删除任务

日程与习惯(Event & Habit):

Action说明
create_event创建日程
list_events查询日程列表
update_event更新日程
delete_event删除日程
check_in_habit习惯打卡
create_habit创建习惯
list_habits查询习惯列表
update_habit更新习惯
delete_habit删除习惯

笔记与日记(Note & Diary):

Action说明
create_note创建笔记
list_notes查询笔记列表
update_note更新笔记
delete_note删除笔记
write_diary写日记

财务管理(Finance):

Action说明
record_transaction记录收支
list_transactions查询交易列表

健康管理(Health):

Action说明
record_mood记录心情
list_moods查询心情记录
record_diet记录饮食
list_diets查询饮食记录
record_water记录饮水
list_water查询饮水记录
record_sleep记录睡眠
record_body记录身体数据
record_medicine记录用药
record_period记录经期
record_health记录健康指标
list_health查询健康数据
get_focus_today获取当日专注数据

目标与成就(Goal & Achievement):

Action说明
create_goal创建目标
list_goals查询目标列表
update_goal_progress更新目标进度
list_achievements查询成就列表

生活工具(Life Tools):

Action说明
add_shopping_item添加购物项
list_shopping查询购物清单
mark_shopping_bought标记已购
add_wishlist_item添加心愿单
list_wishlist查询心愿单
list_countdowns查询倒计时
create_countdown创建倒计时
delete_countdown删除倒计时
create_memo创建便签
list_memos查询便签列表
list_channels查询频道列表
record_trajectory记录轨迹
list_trajectories查询轨迹列表
get_today_summary获取今日摘要
web_search联网搜索

资产管理(Inventory & Lend):

Action说明
list_inventory查询物品清单
create_inventory_item添加物品
delete_inventory_item删除物品
record_item_lend记录物品借出
record_money_lend记录借还款

模式与扩展(Mode & Extras):

Action说明
switch_mode切换模式
get_current_mode获取当前模式
record_dream记录梦境
record_movie记录影视
add_birthday添加生日
list_birthdays查询生日列表
list_subscriptions查询订阅列表
add_book添加书籍
create_study_plan创建学习计划
create_idea记录灵感
record_pet_activity记录宠物活动
record_plant_watering记录植物浇水
add_recipe添加食谱
record_medical记录就诊
add_person添加联系人
add_address添加地址
add_coupon添加优惠券

5.3 Action 示例

create_task 为例,展示一个完整的 Action 定义:

typescript
{
  name: 'create_task',
  description: '创建一个新的待办任务',
  schema: z.object({
    content: z.string().describe('任务内容'),
    priority: z.enum(['high', 'medium', 'low']).optional(),
    dueDate: z.string().optional().describe('截止日期 YYYY-MM-DD'),
    categoryId: z.string().optional().describe('所属分类 ID'),
    tags: z.array(z.string()).optional().describe('标签列表'),
  }),
  execute: async (params) => {
    const task = await taskRepo.create({
      content: params.content,
      priority: params.priority || 'medium',
      dueDate: params.dueDate,
      categoryId: params.categoryId,
      tags: params.tags || [],
    })
    return {
      success: true,
      message: `已创建任务:${task.content},截止日期 ${task.dueDate || '无'}`,
      data: task,
    }
  }
}

每个 Action 执行完毕后,返回的 message 作为 AI 上下文反馈,让模型了解操作结果并做出后续响应。

6. Agent 提示词设计

/src/ai/agent-prompt.ts — 构建 Agent 的 System Prompt,让模型理解可用操作和输出格式。

6.1 提示词结构

System Prompt 由以下部分组装而成:

你是一个 AI 生活助理,当前时间是 {当前日期}。

可用操作(必须用 [ACTION] 格式调用):
{所有 Action 的 name + description + schema}

输出格式:
用自然语言回复用户。
如需执行操作,在回复末单独放置 [ACTION] 块:
[ACTION]
{{ "name": "操作名", "参数": "值" }}
[/ACTION]

每个 [ACTION] 块只能包含一个操作。

示例:
{12 个示例对话}

6.2 示例对话

提示词中包含 12 个示例对话,覆盖常见场景:

场景用户输入预期 Action
创建任务"帮我记一个任务,明天下班前提交周报"create_task
完成任务"把提交周报这个任务标记完成"complete_task
查看任务"我还有哪些没完成的任务"list_tasks
创建日程"帮我安排周五下午3点开会"create_event
习惯打卡"我今天冥想打卡"check_in_habit
记录心情"今天心情不错"record_mood
记笔记"帮我记个笔记:数据库连接字符串"create_note
记录收支"午饭花了35块"record_transaction
添加购物项"我要买牛奶"add_shopping_item
喝水记录"刚喝了一杯水"record_water
睡眠记录"昨晚睡了7个半小时"record_sleep
写日记"写个日记:今天效率很高"write_diary

示例对话教给模型两件事:

  1. 意图识别:从自然语言中提取操作类型和参数
  2. 格式规范:严格按照 [ACTION] + JSON 的格式输出

6.3 设计考量

  • 注入当前日期:让模型能正确理解"今天"、"明天"、"下周"等相对时间
  • 仅 JSON 格式:Action 只接受 JSON,不接受自然语言参数描述,减少解析错误
  • 一个 Action 一个块:多个操作需要多个 [ACTION] 块,避免嵌套 JSON 的解析复杂度
  • schema 直译:将 Zod Schema 的描述信息直接写入提示词,无需手动维护两份定义

7. 错误处理与降级

7.1 降级策略

用户发起对话

检测网络状态 & 模型状态

┌─ 在线 + 云端可用 ──→ 使用云端 Agent
├─ 在线 + 端侧已加载 → 提示用户选择
├─ 离线 + 端侧已加载 → 自动切换端侧
├─ 离线 + 端侧未下载 → 提示下载模型
└─ 离线 + 端侧不支持  → 提示联网后重试

7.2 异常处理

场景处理方式
云端 SSE 连接中断自动重连(最多 3 次),失败后降级到端侧
端侧推理超时30 秒超时,提示用户简化问题或切换云端
模型加载失败重试一次,失败后提示重新下载
JSON 解析失败三层修复 → 若仍失败,跳过该 Action,回复自然语言部分
Action 执行异常捕获错误,返回 { success: false, message: 错误描述 } 反馈给 AI
存储空间不足下载前检查可用空间,不足时提示清理

7.3 端侧不支持的 Action

部分 Action(如 web_search)在端侧无法执行。当端侧模型尝试调用这些 Action 时,系统返回明确的错误反馈,由 AI 模型在对话中告知用户需要联网。

8. 扩展点

8.1 新增 Action

actions.ts 中按以下步骤添加:

  1. 定义 Zod Schema
  2. 实现 execute 函数
  3. 注册到 allActions 数组

注册后自动出现在 System Prompt 中,无需修改提示词模板。

8.2 新增模型

model-manager.tsMODEL_CATALOG 数组中追加 ModelInfo 对象。需提供:

  • GGUF 下载地址(App 端)
  • HuggingFace 模型 ID(H5 端)
  • 量化方式、参数量等元信息

8.3 自定义 Agent 策略

ai-agent.service.tsparseActions() 和对话函数可被替换或装饰,以支持自定义的 Agent 行为(如多轮确认、人机协作审批等)。