从创意到成品:用 AIUI 打造「免手出行助手」——一篇能跟着做完的智能体实战教程

缘起:为什么要做「免手出行助手」

看到社区里有人用低代码平台做语音推理游戏,我在想:AIUI 这样的AI 原生 UI 框架,最该解决的其实是"戴眼镜时双手被占满"的出行场景——骑车、开车、拎东西时掏手机既危险又反人性。

于是决定自己动手:用 AIUI 做一个全语音驱动的出行助手——唤醒即用,天气、路况、行程全靠说,回复不只是一段话,而是一张能继续操作的卡片,甚至可以在我出门前把提醒推送到眼镜上。

先上结论:从脚手架到真机跑通,核心开发耗时约 2 天,不需要懂 3D 引擎、不需要学 AR SDK,会小程序/前端就能上手。下面是完整过程。

一、项目简介

解决什么问题:出行场景下"手被占用、眼被占用",用户无法安全地查天气、看路况、确认行程。传统语音助手只能"说一段话",信息密度低、不能继续操作。

目标用户:通勤族、骑行者、开车者、出差人群。

一句话介绍:「免手出行助手」是一个基于 AIUI 的智能体应用,用户通过语音唤醒,在 Rokid Glasses 上获得可交互的天气/路况卡片与沉浸式行程面板,并在关键时刻收到云端推送提醒——全程不用掏手机。

在这里插入图片描述

二、场景与用户意图

在这里插入图片描述

2.1 使用场景

  • 早晨出门前:“今天要带伞吗?” → 天气卡片 + 出行建议。
  • 通勤路上:“去公司堵不堵?” → 实时路况卡片(可刷新)。
  • 出差前:“明天 8 点的高铁,我该几点出门?” → 行程倒计时面板(沉浸式)。
    在这里插入图片描述

2.2 用户意图与承接方式

用户说法智能体理解响应/动作
“今天要带伞吗”意图:天气查询 + 建议返回天气卡片(可点"刷新"“24 小时趋势”)
“去公司堵不堵”意图:路况查询返回路况卡片 + TTS 播报一句话结论
“提醒我 7 点半出门”意图:设置提醒走云端通知 API,到点推送提醒到眼镜
“打开行程面板”意图:调起沉浸式页面进入沉浸式行程倒计时界面

意图理解要点:AIUI 的页面即"可被 AI 调用的工具"——每个页面在 <script def> 里声明 description(告诉模型何时调用)与 schema.data(入参结构),模型在对话中判断意图并自动携带参数调起页面。开发者不需要写一堆 if/else 的意图路由,把"说明书"写好即可。

三、方案设计

运行设备:Rokid Glasses 等带屏 AI 眼镜 · 开发平台:AIUI(js.rokid.com/AIUI,稳定版 0.15.0)

3.1 智能体定义

  • 身份:出行助手,语气简洁、结论先行,涉及安全(骑车/开车)时先给结论再给细节。
  • 核心规则:天气/路况优先返回卡片(对话内交互);行程类需求进入沉浸式面板;提醒类需求调用云端推送。
  • 数据/依赖:天气与路况 API、模型依赖(LLM),权限仅声明所需最小集(microphone/network)。

3.2 页面/卡片设计(两种形态都用到)

页面/卡片形态用途触发时机
欢迎卡片对话内介绍能力、显示常用指令唤醒后首轮
天气卡片对话内温度/天气/带伞建议,可刷新、看趋势用户问天气
路况卡片对话内通勤耗时/拥堵等级用户问路况
行程面板沉浸式倒计时、步骤清单、出发提醒用户要求"打开行程面板"

> 图注占位:此处插入天气卡片与行程面板设计稿/截图。

3.3 状态流转

唤醒 → 欢迎卡片 →(语音意图)
  ├─ 天气/路况 → LLM 解析 → 生成对应卡片(对话内,可继续点按钮)
  ├─ 设置提醒 → 云端通知 API → 到点推送到眼镜 → 卡片导航到提醒页
  └─ 打开行程面板 → 调起沉浸式页面(独立上下文,语音/按键驱动)

关键设计:对话内 vs 沉浸式分开管理。对话内卡片由 Agent Loop 内建渲染(Tool Rendering),简单可控;行程面板用 MCP Apps 方式承载独立界面,ASR/LLM/TTS 由页面自己接起来,做到高度自定义。

3.4 能力调用关系

用户语音 → ASR(听懂)→ LLM(理解意图/决定返回哪种 UI)
        → 卡片/页面渲染(.ink 组件)
        → TTS(说回来)
        → 云端通知(提醒类:HTTP/curl 或 @yodaos-pkg/cloud-integration)

四、AIUI 实现与智能体实操(核心章节)

下面按"建工程 → 写说明书 → 写页面 → 接语音 → 接云端"五步,给出可直接照做的实操代码。

实操第 1 步:脚手架创建项目

AIUI 提供官方脚手架,一条命令生成完整工程模板:

npm create @yodaos-pkg/aiui-agent my-commute-agent
cd my-commute-agent

生成的标准结构(AIUI 深度兼容微信小程序规范):

my-commute-agent/
├── app.js          # 应用逻辑,全局生命周期
├── app.json        # 全局配置:页面路径、窗口外观
├── app.wxss        # 全局样式
├── AGENTS.md       # 智能体描述文件(核心!)
└── pages/
    └── index/
        ├── index.ink       # 单文件组件(也可拆分为 js/wxml/wxss/json)
        ├── weather.ink     # 天气卡片页
        └── trip.ink        # 沉浸式行程面板

说明:AIUI 支持传统多文件结构与 .ink 单文件组件两种方式;同一页面两种文件都存在时,框架优先加载 .ink。本文全部使用 .ink
在这里插入图片描述

实操第 2 步:写 AGENTS.md——智能体的"身份证+说明书"

AGENTS.md 是 AIUI 最 AI 原生的一部分:平台靠它理解、调度你的智能体。标准结构包含身份、系统指令、能力、配置与依赖五大部分:

# Agent: 免手出行助手
- **Version**: 1.0.0
- **Description**: 全语音出行助手:天气/路况卡片、行程面板、出门提醒。
- **Author**: [你的昵称]

## System Prompts
你是一个出行助手,规则如下:
- 结论先行,语气简洁,适合语音播报。
- 问天气/路况时,返回对应卡片页(pages/weather/index)。
- 用户要求"行程""几点出门"时,调起沉浸式行程面板(pages/trip/index)。
- 涉及骑车/开车场景,先给安全建议。

## Capabilities
- `fs.read`: 允许读取项目文件
- `fs.write`: 允许修改项目文件
- `network.http`: 允许发起外部 HTTP 请求(天气/路况/云端通知)
- Permissions: microphone, network

## Configuration
- `WEATHER_API`: 天气服务地址
- `TRAFFIC_API`: 路况服务地址

## Dependencies
- Model: `gpt-4` 或等效模型
- Services: weather-api, traffic-api, cloud-notification

编写四原则(踩过坑后总结):清晰明确(System Prompts 写具体规则)、最小权限(只用得到的才声明)、版本控制(Version 随能力演进递增)、严格 Markdown(机器可解析)。

实操第 3 步:写第一个 .ink 页面——天气卡片(对话内交互)

.ink 单文件组件把配置、逻辑、结构、样式写进一个文件,四块结构如下。关键在 <script def>descriptionschema.data 让 AI 知道"什么时候调这个页面、传什么参数"——这就是"页面即 MCP UI 组件"。

<!-- pages/weather/index.ink -->
<script def>
{
  "navigationBarTitleText": "天气卡片",
  "description": "查询天气并返回可刷新、可看趋势的天气卡片。当用户询问天气、要不要带伞、出门建议时调用。",
  "schema": {
    "data": {
      "type": "object",
      "properties": {
        "location": { "type": "string", "description": "城市名,如 杭州" },
        "date": { "type": "string", "description": "日期,默认今天" }
      },
      "required": ["location"]
    }
  }
}
</script>

<script setup>
export default {
  data: {
    location: '',
    weather: '--',
    temp: '--',
    advice: '正在获取...',
    loading: true
  },
  // 页面被 AI 调起时,query 携带 schema 中的参数
  onLoad(query) {
    this.location = query.location || '杭州'
    this.fetchWeather()
  },
  fetchWeather() {
    // 真实项目:调用 WEATHER_API(此处省略请求细节)
    this.setData({
      weather: '多云', temp: '26℃',
      advice: '体感舒适,无需带伞。',
      loading: false
    })
  },
  refresh() { this.fetchWeather() },
  showTrend() {
    // 触发 LLM 生成趋势说明(见语音闭环)
    this.triggerLLM('请用两句话说明杭州未来 24 小时天气趋势')
  }
}
</script>

<page>
  <view class="card">
    <view class="row">
      <text class="city">{{location}}</text>
      <text class="temp">{{temp}}</text>
    </view>
    <text class="weather">{{weather}}</text>
    <text class="advice">{{advice}}</text>
    <view class="actions">
      <button bindtap="refresh">刷新</button>
      <button bindtap="showTrend">24 小时趋势</button>
    </view>
  </view>
</page>

<style>
.card { padding: 40rpx; border-radius: 24rpx; background: #10232B; border: 1rpx solid #1E4650; }
.row { display: flex; justify-content: space-between; align-items: baseline; }
.city { font-size: 36rpx; color: #E8FFEF; }
.temp { font-size: 64rpx; color: #40FF5E; font-weight: bold; }
.weather { font-size: 28rpx; color: #9FE8C0; margin-top: 8rpx; }
.advice { font-size: 24rpx; color: #CFF5DC; margin-top: 16rpx; }
.actions { display: flex; gap: 16rpx; margin-top: 24rpx; }
button { flex: 1; height: 64rpx; line-height: 64rpx; border-radius: 32rpx;
  background: #00C853; color: #04220F; font-size: 26rpx; }
</style>

要点回顾:

  • 对话内交互的本质:AI 在对话流里直接返回一张"还能继续点"的卡片,交互不跳出聊天。
  • bindtap 绑定按钮事件,setData 更新数据驱动界面。
  • 颜色/间距/圆角对齐 AIUI 单绿设计系统(主色 #40FF5E 一类的绿色 token,适配眼镜单绿色显示)。

实操第 4 步:接语音闭环——ASR · LLM · TTS 三件套

AR 眼镜最自然的交互是"动嘴"。AIUI 提供完整的语音闭环,三个 API 正好对应"听、想、说":

① ASR——听懂用户:

const recognition = new SpeechRecognition()
recognition.onresult = (event) => {
  const best = event.results[0][0]
  console.log('识别结果:', best.transcript)   // 拿到转写文本
}
recognition.onerror = (event) => {
  console.error('识别错误:', event.error)
}
recognition.start()   // start/stop/abort 三个方法控制一轮识别

② LLM——理解与生成(含工具调用与流式):

// 1. 检查可用性
const status = await LanguageModel.availability()

// 2. 创建会话(带系统指令)
const session = await LanguageModel.create({
  initialPrompts: [{ role: 'system', content: '请用简洁中文回答,结论先行。' }]
})

// 3. 一次请求
const text = await session.prompt('今天杭州适合骑行吗?')

// 4. 流式输出(边生成边播报,体验更好)
const stream = session.promptStreaming('说明未来 24 小时天气趋势')
while (true) {
  const { done, value } = await stream.read()
  if (done) break
  if (value !== undefined) console.log(value)
}

提示:创建会话时可声明 tools,模型需要时会触发 toolcall 事件,JS 侧接收结构化调用请求并执行(如查路况接口)。会话是"有上下文的交互单元",页面离开时记得 destroy()

③ TTS——说给用户听:

const utterance = new SpeechSynthesisUtterance('今天杭州多云,26 度,无需带伞。')
utterance.lang = 'zh-CN'
utterance.rate = 1.0    // 语速
utterance.pitch = 1.0   // 音高
utterance.volume = 1.0  // 音量 0.0~1.0
speechSynthesis.speak(utterance)

三步串起来,就是"你说话 → AI 想清楚 → 它说回来"的全免手闭环。

实操第 5 步:沉浸式页面与设备事件(行程面板)

行程面板是独立界面,用 onVoiceWakeup / onKeyDown 处理语音与按键(注意 event.preventDefault() 可拦截默认行为):

<!-- pages/trip/index.ink -->
<script setup>
export default {
  data: { minutes: 0, steps: ['洗漱 10 分钟', '早餐 15 分钟', '打车 25 分钟'], done: [] },
  onLoad(query) { this.minutes = Number(query.leaveIn || 60) },
  onVoiceWakeup(event) {
    // 语音指令直达:说"下一步"就推进流程
    const cmd = event.data || ''
    if (cmd.includes('下一步')) this.nextStep()
  },
  onKeyDown(event) {
    // 眼镜按键:确认键推进,返回键退出
    if (event.keyCode === 13) this.nextStep()
  },
  nextStep() {
    if (this.steps.length > 0) {
      this.done.push(this.steps.shift())
      this.setData({ steps: this.steps, done: this.done })
      this.speak(`已完成:${this.done[this.done.length - 1]}`)
    }
  },
  speak(text) {
    const u = new SpeechSynthesisUtterance(text)
    u.lang = 'zh-CN'
    speechSynthesis.speak(u)
  }
}
</script>

<page>
  <view class="panel">
    <text class="title">出发倒计时 {{minutes}} 分钟</text>
    <text class="sub">已完成 {{done.length}}/{{done.length + steps.length}} 项</text>
    <view class="list">
      <text wx:for="{{done}}" wx:key="*this" class="item done">✓ {{item}}</text>
      <text wx:for="{{steps}}" wx:key="*this" class="item">{{item}}</text>
    </view>
    <text class="hint">说"下一步"或按确认键推进</text>
  </view>
</page>

<style>
.panel { padding: 48rpx; }
.title { font-size: 40rpx; color: #40FF5E; font-weight: bold; }
.sub { font-size: 26rpx; color: #9FE8C0; margin-top: 12rpx; }
.item { display: block; font-size: 30rpx; color: #E8FFEF; padding: 16rpx 0; }
.item.done { color: #00C853; }
.hint { font-size: 22rpx; color: #5FA07C; margin-top: 32rpx; }
</style>

沉浸式与对话内的区别:对话内由 Agent Loop 内建渲染;沉浸式由 AGENTS.md 描述直接调起整个 agent,进入 app.json 配置的第一个页面,语音链路(ASR/LLM/TTS)由页面自己接——自由度更高。

在这里插入图片描述

实操第 6 步:云端通知——出门提醒推到眼镜

提醒类需求走 AIUI 云端通知(Cloud Integration)。两种方式:

方式 A:官方 npm 包 @yodaos-pkg/cloud-integration(零运行时依赖):

npm install @yodaos-pkg/cloud-integration

方式 B:HTTP/curl 直接调用

curl --location 'https://rcs.rokid.com/metis/callback/message' \
  --header 'Content-Type: application/json' \
  --header "Authorization: Bearer ${ROKID_SK}" \
  --data '{
    "message_id": "msg-commute-001",
    "account_id": "user-1",
    "message": {
      "agent_id": "commute-agent-1",
      "content": "该出发了!距离高铁发车还有 40 分钟。",
      "tool": { "name": "pages/trip/index" }
    }
  }'

要点:tool.name 匹配 app.json 注册的页面路由,参数透传——推送到达后直接导航到行程面板;必填字段为 message_id / account_id / agent_id / content

实操第 7 步:用 AI 辅助开发(aiui-dev Skill)

AIUI 官方提供开发 Skill,让 Coding Agent 直接具备按 AIUI 规范写代码的能力:

npx skills add https://github.com/jsar-project/AIUI/tree/main/skills/aiui-dev

装上后 AI 助手会严格按 AIUI 的目录结构、.ink 规范、组件体系(view/text/image/button/canvas/chart/lottie)与单绿设计系统生成代码——连可穿戴的尺寸、圆角、卡片布局都对齐。另一个 aiui-cloud-integration Skill 则教 AI 如何通过 npm 包或 HTTP 把通知推到 Rokid Glasses。

实操经验:让 AI 写 .ink 之前,先把 AGENTS.md 和页面 schema 写好——AI 生成的页面参数与意图描述越准确,真机效果越符合预期。

五、交互与体验

5.1 操作路径(全程免手)

唤醒:"乐奇,打开免手出行助手"
→ 欢迎卡片 + TTS 播报可用指令
→ 语音:"今天要带伞吗?" → 天气卡片(可点刷新/趋势)
→ 语音:"打开行程面板" → 沉浸式倒计时界面(语音/按键推进)
→ 出门前 → 云端推送提醒 → 卡片导航到行程面板

5.2 反馈机制

  • 语音反馈:TTS 播报结论(ASR→LLM→TTS 闭环),无需看屏幕。
  • 界面反馈:卡片按钮点击有高亮、列表项完成后打勾(沉浸式面板 标记)。
  • 错误兜底:ASR onerror 时提示"没听清,请再说一次";LLM 未识别意图时返回帮助卡片列出可用指令。

六、调试与验证

6.1 Craft 工作台预览

AIUI 配套 Craft 一体化工作台:导入项目、编辑文件、实时预览。先把逻辑跑通再上真机——网页/Craft 调试比真机快得多,尤其是 schema 与意图匹配这类逻辑问题。

6.2 真机联调(Rokid Glasses)

  1. 通过 CLI/开发工具连接眼镜,安装调试包。
  2. 唤醒测试:确认 AGENTS.md 描述能正确调度到天气/行程页面。
  3. 语音闭环测试:ASR 识别 → LLM 决定卡片 → TTS 播报,逐项验证。
  4. 沉浸式事件测试:onVoiceWakeup/onKeyDown 是否按预期推进流程。
  5. 推送测试:用 curl 模拟云端通知,验证到点提醒与页面导航。

6.3 测试用例(节选)

用例操作预期结果
天气意图说"今天要带伞吗"返回天气卡片 + 播报结论
路况意图说"去公司堵不堵"返回路况卡片
沉浸式调起说"打开行程面板"进入倒计时界面,语音"下一步"推进
未识别兜底说无关内容返回帮助卡片
云端提醒curl 推送眼镜收到提醒并导航到行程面板

七、成果与复盘

7.1 可运行成果

  • 智能体名称:免手出行助手
  • 运行设备:Rokid Glasses(真机已验证主要链路)
  • 演示材料:
  • 在这里插入图片描述

7.2 遇到的问题与解决方案

问题原因解决
AI 经常把"查天气"答成文字而不是卡片天气页 description 写得模糊重写为"当用户询问天气/带伞/出行建议时调用",并完善 schema.data 必填参数
沉浸式页面语音无反应沉浸式是独立上下文,语音链路需页面自接onVoiceWakeup 里自行接入 ASR/LLM/TTS,而不是依赖对话容器
提醒推送后没有跳到行程面板tool.nameapp.json 注册路由不一致统一页面路由名,参数透传对齐 schema
真机唤醒偶发失败权限声明过宽/未按最小权限配置按 AGENTS.md 四原则收敛 Permissions 为 microphone/network
长播报体验差一次生成整段再播改用 promptStreaming 流式输出,边生成边播报

7.3 后续迭代计划

  1. 增加通勤路况的实时刷新与拥堵预测(接入交通数据源)。
  2. 叠加摄像头/图像能力:识别前方路况或共享单车位置(多模态方向)。
  3. 把天气卡片、行程面板沉淀为可复用组件/模板开源到社区(征文"开源组件"方向)。

后记

给想动手的开发者三条建议:

  1. 先把 AGENTS.md 和页面 schema 写清楚——AIUI 的"意图路由"全靠它们,比写代码更关键。
  2. 先在 Craft/网页把逻辑跑通再上真机——意图匹配这类问题在模拟环境里调试效率高得多。
  3. 语音闭环三件套是通用底座——ASR/LLM/TTS 一旦打通,任何"免手"场景都能复用。

AI 时代的创造门槛正在下降,但"把界面交到 AI 手里"这件事,AIUI 已经替你铺好了路——剩下的,就是把你的场景写进 .ink

附:项目信息

内容
智能体名称免手出行助手
开发平台AIUI(js.rokid.com/AIUI · 稳定版 0.15.0)/ AIUI Studio(aiui.rokid.com)
运行设备Rokid Glasses 等带屏 AI 眼镜
核心能力对话内卡片(天气/路况)+ 沉浸式行程面板 + ASR/LLM/TTS 语音闭环 + 云端通知
开发耗时约 2 天
技术栈.ink 单文件组件、AGENTS.md、SpeechRecognition / LanguageModel / SpeechSynthesis、cloud-integration
官方资源AIUI 文档 js.rokid.com/AIUI · GitHub jsar-project/AIUI · Gitee jsar-project/AIUI · AIX jsar-project/aix

更多推荐