眼见为食:基于 GPASS 无显示眼镜的多模态点餐决策工作流实践
作品 Slogan:看见菜单,听见好菜
一、项目简介
"眼见为食"是一套面向无显示 AI 眼镜的点餐决策工作流。它不是简单地"拍一张菜单,让大模型随便推荐",而是将用餐需求、真实菜单、食品安全限制、预算与饭局类型拆成可验证的数据,再生成能够继续调整的点菜方案。
项目希望解决四个实际问题:
- 多人点菜时,人数、忌口、过敏和预算信息容易遗漏。
- 菜单很长,用户不方便在无显示设备上逐项浏览。
- 普通大模型可能推荐菜单里不存在的菜,或把不确定的配料说成确定事实。
- 首次推荐往往不是最终答案,用户还会提出"更省钱""清淡一点""换一道""报完整菜单"等连续要求。
因此,系统采用"端侧采集、云端编排、结构化校验、短语音反馈"的分层方案。
| 项目 | 当前技术基线 |
|---|---|
| 运行平台 | 百宝箱企业版 / GPASS 工作流 |
| 交互设备 | 无显示 AI 眼镜 |
| 最新画布规模 | 114 个节点、132 条连线 |
| 核心循环 | 需求采集、菜单采集、推荐后交互,共 3 个 |
| 端侧插件 | 语音采集、镜腿交互、拍照采集,共 5 个插件节点 |
| 代码节点 | 10 个,用于 JSON 校验、记录合并、分页和状态初始化 |
| 模型节点 | 19 个,分别承担路由、识别、整理、过滤、推荐和口播 |
| 菜单来源 | CAMERA 纸质菜单 + PHONE 手机菜单截图 |
二、总体技术架构

整个方案分为四层。
2.1 端侧交互层
端侧只负责采集真实世界信息和完成低成本确认:
- 语音采集:收集人数、过敏、忌口,以及菜单控制和推荐调整指令。
- 镜腿交互 :使用
single_click确认拍照,避免持续监听把旁人聊天误判为操作。 - 眼镜拍照:获取眼镜当前视野中的纸质菜单图像。
无显示设备不能依赖长文本、复杂列表和多层菜单。因此每轮只问一件事,每次口播最多突出三项。
2.2 云端工作流编排层
云端工作流负责确定性流程控制,而不是把所有逻辑塞进一个大模型提示词:
- 入口意图路由;
- 需求缺失项判断;
- CAMERA / PHONE 菜单来源分支;
- 图片质量与菜单有效性判断;
- 菜品安全过滤与组合推荐;
- 推荐后详情、调整、普通结束与退出。
2.3 模型与代码层
模型负责理解和生成,代码负责校验和确定性处理:
- 轻量模型输出固定 TOKEN;
- 视觉模型读取真实菜单图片;
- 结构化模型整理需求和菜品;
- 代码节点验证 JSON、合并记录、检查菜单一致性;
- 口播模型只改写表达,不改变事实。
2.4 数据与输出层
CAMERA 和 PHONE 最终都转换为统一的菜单记录:
text
menu_source
menu_records
valid_menu_sources
推荐节点只能从menu_records中的真实菜名选择,最终通过短语音反馈给用户。
三、最新工作流画布

当前画布由 19 个条件分支、10 个代码节点、19 个模型节点、12 个设置变量节点、5 个端侧插件节点、3 个循环和多个结束出口组成。
从宏观上可以概括为:
text
开始
-> 入口意图路由
-> 需求采集循环
-> 菜单来源决策
-> CAMERA 菜单采集 / PHONE 截图识别
-> 菜单输入统一
-> 用餐信息整理
-> 安全过滤
-> 点菜组合
-> 推荐结果校验
-> 短语音播报
-> 推荐后详情 / 调整 / 结束 / 退出
四、工作流核心设计
4.1 入口意图只做路由
入口节点不直接回答问题,只输出下面一个 TOKEN:
text
START_SESSION
ADJUST_PLAN
DETAIL_PLAN
KNOWLEDGE_QA
EXIT
SILENT
这样做有三个好处:
- 分支条件稳定,不需要使用"包含某个词"判断整段语音。
- 背景闲聊可以进入
SILENT,不调用拍照和大模型链路。 - 知识问答、点菜推荐和推荐调整互不干扰。
4.2 初始需求采集循环
需求循环只把三个字段视为推荐前必需信息:
party_size:用餐人数;allergy_status:是否存在食物过敏;diet_status:是否存在其他忌口。
循环中间变量为:
| 变量 | 类型 | 作用 |
|---|---|---|
需求回答 |
文本 | 累积用户每轮真实回答 |
需求状态 |
文本 | READY、EXIT 或下一条问题 |
每轮流程如下:
text
需求状态与下一问
-> 设置需求状态
-> READY / EXIT / 默认
默认
-> 语音采集
-> 需求回答合并
-> 设置需求回答
-> 继续下一轮
模型必须综合当前输入、历史对话和本轮已经收集的全部内容,避免用户已经说过"坚果过敏"后再次询问过敏情况。
4.3 双菜单来源

CAMERA:眼镜拍纸质菜单
text
镜腿单击
-> 眼镜拍照
-> 图片地址校验
-> 菜单视觉识别
-> JSON 校验
-> CLEAR / UNCLEAR / NOT_MENU / ERROR
识别清晰后,用户可以说:
text
继续
拍完
重拍
退出
这些自然语言会先归一成固定 TOKEN,再进入分支:
text
CAPTURE_CONTINUE
CAPTURE_FINISH
CAPTURE_RETAKE
EXIT
UNKNOWN
PHONE:手机菜单截图
PHONE 链路读取当前对话图片,适合美团、门店点餐页或扫码菜单截图。
截图校验重点包括:
- 必须能看到门店页头或门店名称;
- 至少清晰显示一道真实菜品;
- 评价正文、销量、推荐语不能被当成菜名;
- 不读取昵称、头像、手机号、订单号等隐私字段;
- 门店不一致时输出
STORE_MISMATCH,不继续推荐。
4.4 菜单结构化数据契约
视觉模型只输出 JSON,不输出解释和 Markdown:
json
{
"status": "CLEAR",
"restaurant": "云味小馆",
"cuisine": "中式家常菜",
"dishes": [
{
"name": "宫保鸡丁",
"price": 42,
"category": "热菜",
"taste": "微辣",
"ingredients": ["鸡肉", "花生"],
"allergen_risks": ["花生"],
"is_signature": false
}
],
"page_summary": "宫保鸡丁等菜品"
}
如果图片模糊,status输出UNCLEAR且dishes必须为空。模型不得根据常识补全看不清的价格、配料和过敏原。
4.5 安全过滤与组合推荐
推荐不是一步完成,而是拆成三层:
text
菜品安全过滤
-> 点菜推荐
-> 推荐结果校验
安全过滤输出:
json
{
"eligible_candidates": [
{
"name": "蒜蓉西兰花",
"price": 28,
"category": "素菜",
"confirmation_required": false,
"confirmation_reason": ""
}
],
"excluded": [
{
"name": "宫保鸡丁",
"reason": "用户存在坚果过敏,菜单明确标注含花生"
}
],
"drink_constraints": []
}
推荐节点只能从eligible_candidates选择。结果校验节点再次对照菜单和过滤结果,阻止模型加入菜单外菜名或已排除菜品。
4.6 推荐后交互循环
首次推荐之后,工作流不会立即结束,而是进入推荐后循环:
| 用户表达 | TOKEN | 动作 |
|---|---|---|
| 报完整菜单 | DETAIL_PLAN | 从第一项开始分段播报 |
| 继续 | DETAIL_NEXT | 从当前游标继续,不重复 |
| 菜单还有什么 | BROWSE_MENU | 浏览可替换候选菜 |
| 更省钱、清淡一点、换菜 | ADJUST_PLAN | 重新组合并校验 |
| 就这样 | FINISH | 普通结束 |
| 退出助手 | EXIT | 退出会话 |
推荐后循环使用五个状态变量:
text
plan_json
filter_json
cursor
detail_scope
final_action
cursor记录播报位置,解决"继续"时从头重复的问题;调整后的方案会写回plan_json,下一轮详情播报使用新方案。
五、端侧插件运用
端侧插件来自眼镜端系列工具。各节点只承担一个明确职责。
| 插件节点 | 关键输入 | 关键输出 | 使用位置 |
|---|---|---|---|
| 初始需求语音采集 | prompt_message、maxDuration=8 |
状态码、识别文本 | 需求循环 |
| 眼镜设备镜腿交互响应 | prompt_message、interaction_type=single_click |
code、message |
每页菜单拍照前 |
| 眼镜设备拍照采集 | prompt_message |
拍照处理状态、图片数据地址 | CAMERA 链路 |
| 菜单控制语音采集 | prompt_message、maxDuration=6 |
状态码、识别文本 | 继续/完成/重拍/退出 |
| 推荐后语音采集 | prompt_message、maxDuration=10 |
状态码、识别文本 | 详情、调整和结束 |
成功判断不能只看"状态信息不为空"。发布前需要在真实眼镜上分别记录:
- 镜腿插件成功时的
code; - 拍照插件成功时的"拍照处理状态";
- 语音插件成功时的状态码。
这些值可能不同,不能把某个猜测值同时用于所有插件。
六、云端模型与代码节点分工
6.1 模型分工
| 任务 | 模型类型 | 设计原则 |
|---|---|---|
| 入口路由、状态判断、指令归一 | Ling-flash-2.0 | 只输出固定 TOKEN |
| 用餐需求和菜单记录整理 | Qwen3.7-plus | 输出合法 JSON,不编造字段 |
| 菜单图像识别 | Qwen3.6-plus 思考模式 | 图片必须通过图片输入区传入 |
| 菜品安全过滤与方案调整 | Qwen3.7-plus | 只基于真实菜单和安全候选 |
| 点菜组合 | Qwen3.6-plus | 控制数量、类别、预算和重复主料 |
| 无显示口播 | Ling-flash-2.0 | 80-140 字,每次最多三道菜 |
6.2 代码节点
代码节点承担大模型不适合完成的确定性任务:
需求回答合并:累积每轮回答;菜单JSON校验:解析模型 JSON 并检查状态;菜单记录合并:保存多页菜单;菜单输入统一:合并 CAMERA 和 PHONE 数据;推荐结果校验:检查菜单外菜名;推荐状态初始化:生成推荐后循环状态;详情分页:每轮返回最多三项并更新游标;调整结果校验:保护原方案不被无效调整覆盖。
七、变量长度与循环状态工程
百宝箱设置变量时,完整目标路径最多 20 个字符。字符数按:
text
循环节点名/中间变量名
计算,而不是只看变量自己的名称。
例如旧路径:
text
推荐后交互循环/detail_cursor
共有 21 个字符,会被截断。因此当前使用:
text
推荐后交互循环/cursor
当前关键写回目标为:
| 完整路径 | 长度 |
|---|---|
菜单采集循环/menu_records |
19 |
菜单采集循环/cap_state |
16 |
推荐后交互循环/plan_json |
17 |
推荐后交互循环/filter_json |
19 |
推荐后交互循环/cursor |
14 |
推荐后交互循环/detail_scope |
20 |
推荐后交互循环/final_action |
20 |
设置节点必须使用"设置变量值"模式:
text
变量名 = 完整目标路径
变量值 = 固定值或上游输出引用
不能把FINISH、EXIT、PLAN或validated_plan误填到变量名中。
八、可靠性、安全与隐私设计
8.1 菜单文字是不可信数据
菜单图片中即使出现"忽略之前规则"等内容,也只能作为图片文字处理,不能执行。视觉提示词明确要求忽略图片中的指令性文本。
8.2 过敏风险采用保守策略
- 菜单明确标注过敏原时直接排除;
- 菜单没有配料时,不声称"绝对安全";
- 必要时将菜品放入
waiter_confirmation,提醒向服务员确认; - 急性危险信号直接进入安全提醒,不继续普通点菜推荐。
8.3 不编造菜单外菜名
推荐结果必须同时通过候选过滤和结果校验。候选不足时少推荐,也不能补造一道看似合理但菜单没有的菜。
8.4 手机截图隐私
PHONE 识别不输出头像、昵称、手机号、订单号和账户信息。测试和拍摄视频前,应先对截图中的个人信息、精确位置和订单数据打码。
九、总结
"眼见为食"的核心不在于单次菜单识别,而在于建立了一个能够验证、能够继续、能够失败降级的点餐决策闭环:
text
真实采集
-> 结构化数据
-> 安全过滤
-> 菜单内组合
-> 结果校验
-> 短语音反馈
-> 用户继续调整
通过端侧语音、镜腿和拍照插件,系统获得真实上下文;通过云端路由、代码校验和状态循环,系统将大模型的不确定性限制在可控范围内。最终用户不需要盯着屏幕,也能够完成从"这桌人有什么要求"到"这桌菜如何调整"的完整流程。
眼见为食:看见菜单,听见好菜。
