鸿蒙 + Flutter 下美食探索场景为什么 AI 推荐比传统搜索更自然
适合谁看
-
在做内容探索型产品的人
-
想知道 AI 推荐到底解决了什么产品问题的人
-
不想把 AI 功能做成"只是换个搜索框"的开发者
-
想理解搜索和 AI 推荐如何在鸿蒙端协同的人
问题背景
传统搜索并不是没用。它非常适合:
-
我知道关键词
-
我知道要找哪个对象
-
我只想快速定位结果
但美食探索场景有一个天然难点:用户很多时候并不知道具体想找什么。
他更可能说的是:
-
想吃点鸡蛋做的,但别太单调
-
最近下雨,想来点热乎的
-
有没有适合第一次尝试的异国吃法
这类输入如果完全按传统搜索框理解,往往会很别扭。
项目中的真实场景
食界探味当前已经同时具备两种路径:
|
路径 |
入口 |
适合场景 |
|---|---|---|
|
普通搜索页 |
|
已知目标,精确关键词 |
|
AI 助手页 |
|
模糊意图,探索发现 |
AI 助手背后通过 4 个工具把模糊问题转成真实菜品结果:
-
search_dishes— 多维度条件搜索 -
get_random_dish— 随机推荐惊喜 -
get_dishes_by_ingredient— 同食材全球吃法 -
get_dish_detail— 菜品详情
探索页上两种入口并存:
// explore_screen.dart
// 搜索入口 — 精确查找
SearchEntryBar(horizontalPadding: horizontalPadding),
// AI 入口 — 模糊探索
if (AppConfig.enableAi)
AiEntryCard(
onTap: () => context.push('/ai-assistant'),
),
这说明当前 AI 推荐并不是脱离搜索存在,而是在补搜索不擅长的那部分语义理解。
核心实现
先说结论:
在美食探索场景下,AI 推荐之所以更自然,不是因为它更"智能"这个抽象词,而是因为它更适合承接模糊、带情绪、带场景的用户意图。
一、传统搜索更像"定位已知目标"
搜索的优势非常明确:输入关键词 → 快速匹配 → 返回结果列表。
食界探味的传统搜索页实现:
// search_screen.dart
void _onQueryChanged(String text) {
_debounce?.cancel();
_debounce = Timer(const Duration(milliseconds: 300), () {
ref.read(searchProvider.notifier).search(text);
});
}
300ms 防抖后触发搜索,结果直接渲染为菜品列表。这在下面这些场景里很好用:
-
我就想搜"寿喜锅"
-
我就想找"牛肉"
-
我知道自己要什么
但一旦用户输入开始带上情绪、场景、模糊偏好,传统搜索就会开始显得很硬。
二、AI 推荐更适合承接"模糊意图"
食界探味当前 AI 助手的系统提示词里,已经把意图理解写得很明确:
// ai_explore_coordinator.dart → _systemPrompt
const _systemPrompt = '''
你是「食界探味 AI 探味助手」,帮助用户从食材出发探索全球吃法。
## 工作流程
1. 理解用户意图:提取食材、口味偏好、排除项、场景等信息
2. 调用 search_dishes 工具检索匹配菜品
3. 如果用户想随机探索,调用 get_random_dish
4. 如果用户想看某道菜的详情,调用 get_dish_detail
5. 如果用户想看同食材的其他吃法,调用 get_dishes_by_ingredient
## 风格
- 温暖、有趣,像朋友推荐美食
- 极简,话越少越好,点到即止
''';
AI 助手不是在机械匹配词,而是在先把用户那句自然语言还原成更结构化的意图。比如用户说"想吃鸡蛋做的,但别太家常",AI 会理解为:
-
食材: 鸡蛋
-
避免: 家常口味
-
需要: 有特色的做法
然后调用 search_dishes 工具:
// search_dishes_tool.dart → parametersSchema
'ingredients': { 'description': '食材名称列表,如 ["鸡蛋", "番茄"]' },
'flavorTags': { 'description': '偏好的口味标签,如 ["鲜", "甜"]' },
'avoidTags': { 'description': '排除的口味标签,如 ["辣"]' },
'region': { 'description': '地域偏好,如 "亚洲"、"欧洲"、"美洲"' },
AI 把"别太家常"翻译成 avoidTags: ["家常"],把"鸡蛋做的"翻译成 ingredients: ["鸡蛋"],然后用结构化参数去查数据库。这一步就是 AI 推荐比传统搜索更自然的关键——它能理解自然语言背后的结构化意图。
三、四个工具分别解决什么类型的模糊意图
食界探味的 4 个工具不是随机设计的,它们分别对应 4 类不同的用户意图:
|
工具 |
解决的意图类型 |
示例输入 |
|---|---|---|
|
|
多条件组合探索 |
"想吃牛肉,清淡一点,不要辣" |
|
|
完全随机惊喜 |
"给我一个惊喜""随便推荐" |
|
|
同食材全球吃法 |
"牛肉在其他国家怎么做" |
|
|
深入了解某道菜 |
"这道菜的详细介绍" |
search_dishes 是最核心的工具,支持 5 个维度的条件组合:
// search_dishes_tool.dart
Map<String, dynamic> get parametersSchema => {
'properties': {
'ingredients': { 'description': '食材名称列表' },
'flavorTags': { 'description': '偏好的口味标签' },
'avoidTags': { 'description': '排除的口味标签' },
'region': { 'description': '地域偏好' },
'limit': { 'description': '返回数量,默认 5' },
},
};
这意味着 AI 可以同时处理"要什么"和"不要什么"——传统搜索很难同时表达"要牛肉"和"不要辣"。
get_random_dish 则解决了一类传统搜索完全无法处理的意图:
// get_random_dish_tool.dart
String get description =>
'随机获取一道菜品,适合用户说"随便推荐一个"或"给我一个惊喜"的场景。';
"给我一个惊喜"——这种输入用传统搜索根本无法处理,但 AI 可以理解它是"随机推荐"的意图。
四、AI 推荐在这里解决的是"表达门槛"
传统搜索要求用户先把问题收得很准:
用户想表达:"我想吃鸡蛋做的,清淡一点,适合一个人吃的"
传统搜索输入框:鸡蛋 清淡 ← 用户被迫精简
搜索结果:番茄炒蛋、蒸蛋羹 ← 匹配到的可能不是用户想要的
AI 推荐允许用户保持自然说话方式:
用户想表达:"我想吃鸡蛋做的,清淡一点,适合一个人吃的"
AI 助手输入框:今晚想吃点鸡蛋做的,清淡一点,一个人吃
AI 理解:食材=鸡蛋,口味=清淡,场景=一人食
AI 回复:为你找到了 3 道适合一个人的鸡蛋吃法:日式茶碗蒸、
西班牙蛋饼、泰式蒸蛋。茶碗蒸最清淡,西班牙蛋饼更饱腹。
这种输入方式对用户来说更轻。而对产品来说,它降低的是用户表达意图的门槛。
AI 助手页面的欢迎页示例也体现了这一点:
// ai_assistant_screen.dart → _WelcomeView
static const _examples = [
'今晚想吃点热乎的', // 场景 + 情绪
'家里有鸡蛋,做什么好', // 食材 + 开放式
'来个异国风味的牛肉', // 食材 + 地域偏好
'不想吃辣,清淡一点', // 排除 + 偏好
'给我一个惊喜', // 完全随机
];
这 5 个示例没有一个是"精确关键词",全部是自然语言表达。它们在告诉用户:你不需要想好要搜什么,随便说就行。
五、搜索页如何智能引导到 AI 助手
食界探味还有一个很聪明的设计:当用户在搜索页输入了自然语言时,会自动提示"试试 AI 探味助手":
// search_screen.dart
static bool _looksLikeNaturalLanguage(String query) {
if (query.length < 6) return false;
const intentWords = [
'想', '不要', '适合', '推荐', '来个',
'有', '做', '吃', '喜欢', '清淡', '热乎',
];
return intentWords.any((w) => query.contains(w));
}
当检测到搜索词像自然语言时:
if (AppConfig.enableAi && _looksLikeNaturalLanguage(state.query))
_AiSearchHint(
query: state.query,
onTap: () => context.push(
'/ai-assistant?q=${Uri.encodeComponent(state.query)}',
),
),
这个设计的巧妙之处在于:
-
不替代搜索 — 搜索页仍然正常展示搜索结果
-
智能识别 — 通过关键词检测判断输入是否像自然语言
-
无缝引导 — 点击后带着原始 query 跳转到 AI 助手
-
产品逻辑 — 搜索无结果时也显示这个提示,给用户一条退路
比如用户在搜索页输入"今晚想吃点热乎的":
搜索结果:无(因为没有菜名叫"热乎的")
提示:试试用 AI 探味助手理解你的需求 →
点击后跳转到 AI 助手,带着 query"今晚想吃点热乎的",AI 会理解为"热的、汤类、暖胃",然后推荐合适的菜品。
六、AI 输出不是替代搜索结果,而是"组织推荐方向"
食界探味的 AI 助手输出有一个关键设计:AI 不直接展示菜品详情,而是简短文字 + 菜品卡片。
系统提示词明确规定:
你的文字回复下方会自动展示菜品卡片,用户可以点击卡片查看详情。
所以你的文字部分要非常简短,不要重复卡片上已有的信息。
推荐多道菜时,格式如下(整段控制在3-5句话以内):
为你找到了N道XX相关的吃法:菜名A、菜名B、菜名C。
然后用1-2句话做一个整体点评或亮点提示。
这意味着 AI 在这里的角色是:
用户 → AI 理解意图 → AI 调用工具 → AI 组织推荐语义 → 卡片展示真实菜品
↓
不是:
AI 编造内容 → 直接展示文本
AI 负责"把探索方向讲清楚",真实内容仍然由菜品卡片和详情页承接。这比"让 AI 直接编一整页内容"更稳,也更适合真实产品。
七、为什么说它"更自然",不是"更万能"
AI 推荐并不是要替代所有搜索。更准确的理解应该是:
|
场景 |
适合路径 |
原因 |
|---|---|---|
|
"我要找寿喜锅" |
传统搜索 |
精确目标,直接匹配 |
|
"牛肉怎么做" |
传统搜索 |
食材关键词,搜索能处理 |
|
"想吃点清淡的鸡蛋" |
AI 推荐 |
模糊偏好,需要意图理解 |
|
"来个惊喜" |
AI 推荐 |
随机推荐,搜索无法处理 |
|
"适合下雨天吃的热乎东西" |
AI 推荐 |
场景 + 情绪,搜索无法理解 |
|
"有没有异国风味的牛肉" |
AI 推荐 |
地域 + 食材组合,需要语义理解 |
食界探味当前同时保留搜索页和 AI 助手页,本身就说明了这一点。它们不是谁替代谁,而是在解决两类不同问题。
八、在鸿蒙端,语音输入让 AI 推荐更自然
这是鸿蒙端特有的优势。鸿蒙设备支持语音输入,用户可以直接用嘴说出模糊意图:
用户对着鸿蒙手机说:"想吃点鸡蛋做的,别太家常"
↓
鸿蒙 SpeechRecognitionPlugin 识别为文本
↓
Flutter SpeechRecognitionChannel 接收文本
↓
AI 助手理解意图:食材=鸡蛋,避免=家常
↓
调用 search_dishes(ingredients: ["鸡蛋"], avoidTags: ["家常"])
↓
推荐:日式茶碗蒸、西班牙蛋饼、泰式蒸蛋
↓
用户点击卡片查看详情
语音输入让"自然语言表达"变得更加自然——用户不需要打字,直接说就行。在鸿蒙设备上,这个体验链路是:
嘴 → 鸿蒙语音识别 → Flutter AI 助手 → 工具调用 → 菜品卡片
比传统搜索的体验链路更短、更自然:
想 → 打字 → 搜索框 → 关键词匹配 → 结果列表
而且语音输入天然支持更长、更复杂的表达。打字时用户可能会精简为"鸡蛋 清淡",但语音时用户会说完整句子"想吃鸡蛋做的,清淡一点,不要太家常"——这让 AI 能获取更丰富的意图信息。
九、TTS 播报让推荐结果可以"被听"
鸿蒙端的 TTS 能力让 AI 推荐的结果可以被语音播报:
// ai_explore_coordinator.dart
Future<void> speakText(String text) async {
final cleaned = _stripForTts(text);
await TextToSpeechChannel.speak(cleaned);
}
用户看完 AI 推荐后,可以点击"语音播报"按钮,让鸿蒙 TTS 引擎把推荐文案读出来。这在以下场景特别有用:
-
用户在做饭时,不方便看手机
-
用户在开车时,想听 AI 推荐
-
用户视力不便时,语音推荐更友好
语音输入 + AI 推荐 + TTS 播报,形成了一个完整的"说话 → 听推荐"闭环:
说话(鸿蒙 ASR)→ AI 理解 → 工具调用 → AI 组织推荐 → 听推荐(鸿蒙 TTS)
关键代码位置
|
文件 |
作用 |
|---|---|
|
|
传统搜索页 + AI 引导 |
|
|
AI 助手页 + 欢迎示例 |
|
|
探索页,两种入口并存 |
|
|
AI 流程编排 + 系统提示词 |
|
|
多条件搜索工具 |
|
|
随机推荐工具 |
|
|
同食材查询工具 |
|
|
菜品详情工具 |
|
|
鸿蒙语音识别通道 |
|
|
鸿蒙 TTS 通道 |
搜索与 AI 推荐的协作架构
┌─────────────────────────────────────────────────────┐
│ 用户输入 │
│ │
│ "寿喜锅" "想吃点热乎的鸡蛋" "给我惊喜" │
│ │ │ │ │
│ ▼ ▼ ▼ │
│ ┌──────────┐ ┌──────────┐ ┌──────────┐ │
│ │ 传统搜索 │ │ 智能检测 │ │ AI 入口 │ │
│ │ 关键词匹配│ │ 自然语言? │ │ 直接进入 │ │
│ └────┬─────┘ └────┬─────┘ └────┬─────┘ │
│ │ │ │ │
│ ▼ ▼ ▼ │
│ ┌──────────┐ ┌──────────┐ ┌──────────┐ │
│ │ 搜索结果 │ │ 搜索结果 │ │ AI 助手 │ │
│ │ 列表展示 │ │ + AI 引导 │ │ 意图理解 │ │
│ └──────────┘ └────┬─────┘ └────┬─────┘ │
│ │ │ │
│ ▼ ▼ │
│ ┌─────────────────────────────┐ │
│ │ AI 工具调用层 │ │
│ │ search_dishes / random / │ │
│ │ by_ingredient / detail │ │
│ └──────────────┬──────────────┘ │
│ │ │
│ ▼ │
│ ┌─────────────────────────────┐ │
│ │ 菜品卡片 + 详情页承接 │ │
│ └─────────────────────────────┘ │
│ │
├──────────────────────────────────────────────────────┤
│ 鸿蒙原生能力增强 │
│ │
│ 语音输入(SpeechRecognitionPlugin) │
│ → 让模糊表达更容易,获取更丰富的意图信息 │
│ │
│ TTS 播报(TextToSpeechPlugin) │
│ → 让推荐结果可以被听,支持不方便看手机的场景 │
│ │
└──────────────────────────────────────────────────────┘
常见坑
-
把 AI 推荐做成"换皮搜索框" — 如果 AI 只是把用户输入原样丢给搜索,那就失去了语义理解的价值
-
让 AI 输出替代真实内容页 — AI 编造的菜品信息不可靠,必须用工具调用真实数据
-
只强调模型回答,不把真实业务卡片接回来 — AI 推荐的价值在于"组织方向",真实内容仍需卡片承接
-
误以为 AI 推荐要取代搜索 — 搜索适合已知目标,AI 适合模糊探索,两者互补
-
搜索页不引导到 AI — 当用户输入自然语言时,应该主动提示"试试 AI 助手"
-
AI 欢迎页没有示例 — 用户不知道能问什么,示例引导非常重要
-
鸿蒙端语音输入没有接入 AI — 语音识别的结果应该直接喂给 AI 助手,而不是只给搜索框
可复用模板
搜索与 AI 协同思路
传统搜索适合
- 已知目标
- 精确关键词
- 快速定位
AI 推荐适合
- 模糊意图
- 场景表达
- 灵感探索
- 随机惊喜
协同方式
- 搜索页检测自然语言 → 引导到 AI
- AI 用工具调用真实数据 → 不编造内容
- AI 输出简短推荐语 → 卡片承接真实内容
- 详情页继续深入 → 形成完整链路
AI 系统提示词模板(探索型推荐)
const systemPrompt = '''
你是[产品名]的 AI 助手,帮助用户从[核心维度]出发探索[内容类型]。
## 工作流程
1. 理解用户意图:提取[维度1]、[维度2]、排除项、场景等信息
2. 调用工具检索匹配内容
3. 基于真实数据给出有温度的推荐
## 输出格式
用纯文本回复,简短(3-5句话以内)。
内容下方会自动展示卡片,不要重复卡片上的信息。
## 风格
- 温暖、有趣,像朋友推荐
- 必须基于工具返回的真实数据
- 没有完全匹配时诚实告知
''';
搜索页自然语言检测模板
static bool looksLikeNaturalLanguage(String query) {
if (query.length < 6) return false;
const intentWords = [
'想', '不要', '适合', '推荐', '来个',
'有', '做', '吃', '喜欢', '清淡',
];
return intentWords.any((w) => query.contains(w));
}
// 检测到自然语言时引导到 AI
if (looksLikeNaturalLanguage(query))
AiSearchHint(
onTap: () => context.push('/ai-assistant?q=$query'),
);
本篇总结
美食探索场景下,AI 推荐比传统搜索更自然,核心不在"模型更强",而在它更适合承接模糊、带场景、带情绪的用户意图。
食界探味当前的设计之所以顺,关键在于:
-
搜索和 AI 互补 — 搜索处理精确查找,AI 处理模糊探索
-
AI 不替代内容 — AI 负责理解意图和组织推荐语义,真实菜品由卡片承接
-
工具调用真实数据 — AI 不编造内容,4 个工具分别对应不同类型的意图
-
搜索页智能引导 — 检测到自然语言时主动提示"试试 AI 助手"
-
鸿蒙语音增强 — 语音输入让模糊表达更容易,TTS 让推荐可以被听
在鸿蒙设备上,"嘴 → 语音识别 → AI 理解 → 工具调用 → 菜品卡片 → 语音播报"形成了一个完整的闭环,比传统"打字 → 搜索框 → 关键词匹配"的链路更短、更自然。这不是 AI 替代搜索,而是 AI 补了搜索在模糊意图理解上的短板。
更多推荐



所有评论(0)