用 AIUI 打造「免手出行助手」——一篇能跟着做完的智能体实战教程
从创意到成品:用 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>:description 与 schema.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)
- 通过 CLI/开发工具连接眼镜,安装调试包。
- 唤醒测试:确认 AGENTS.md 描述能正确调度到天气/行程页面。
- 语音闭环测试:ASR 识别 → LLM 决定卡片 → TTS 播报,逐项验证。
- 沉浸式事件测试:
onVoiceWakeup/onKeyDown是否按预期推进流程。 - 推送测试:用 curl 模拟云端通知,验证到点提醒与页面导航。
6.3 测试用例(节选)
| 用例 | 操作 | 预期 | 结果 |
|---|---|---|---|
| 天气意图 | 说"今天要带伞吗" | 返回天气卡片 + 播报结论 | ✅ |
| 路况意图 | 说"去公司堵不堵" | 返回路况卡片 | ✅ |
| 沉浸式调起 | 说"打开行程面板" | 进入倒计时界面,语音"下一步"推进 | ✅ |
| 未识别兜底 | 说无关内容 | 返回帮助卡片 | ✅ |
| 云端提醒 | curl 推送 | 眼镜收到提醒并导航到行程面板 | ✅ |
七、成果与复盘
7.1 可运行成果
- 智能体名称:免手出行助手
- 运行设备:Rokid Glasses(真机已验证主要链路)
- 演示材料:

7.2 遇到的问题与解决方案
| 问题 | 原因 | 解决 |
|---|---|---|
| AI 经常把"查天气"答成文字而不是卡片 | 天气页 description 写得模糊 | 重写为"当用户询问天气/带伞/出行建议时调用",并完善 schema.data 必填参数 |
| 沉浸式页面语音无反应 | 沉浸式是独立上下文,语音链路需页面自接 | 在 onVoiceWakeup 里自行接入 ASR/LLM/TTS,而不是依赖对话容器 |
| 提醒推送后没有跳到行程面板 | tool.name 与 app.json 注册路由不一致 | 统一页面路由名,参数透传对齐 schema |
| 真机唤醒偶发失败 | 权限声明过宽/未按最小权限配置 | 按 AGENTS.md 四原则收敛 Permissions 为 microphone/network |
| 长播报体验差 | 一次生成整段再播 | 改用 promptStreaming 流式输出,边生成边播报 |
7.3 后续迭代计划
- 增加通勤路况的实时刷新与拥堵预测(接入交通数据源)。
- 叠加摄像头/图像能力:识别前方路况或共享单车位置(多模态方向)。
- 把天气卡片、行程面板沉淀为可复用组件/模板开源到社区(征文"开源组件"方向)。
后记
给想动手的开发者三条建议:
- 先把 AGENTS.md 和页面 schema 写清楚——AIUI 的"意图路由"全靠它们,比写代码更关键。
- 先在 Craft/网页把逻辑跑通再上真机——意图匹配这类问题在模拟环境里调试效率高得多。
- 语音闭环三件套是通用底座——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 |
更多推荐



所有评论(0)