AI落地:关于鸡尾酒,我们还是选择在街上发小卡片吧

昨天又去探了个点,依旧不行。

问题其实很简单,一杯干马天尼被直接丢进了摇壶。当酒液倒进去的那一刻,iN 其实已经想退单了,心里的念头却是等等尝尝吧……最后果不其然。但这件事情真正让我在意的,并不是这杯酒做错了,而是现场没有任何人觉得这有什么问题。

这才是现实。

鸡尾酒在中国,大多数时候并不是一个被理解的产品,而是一个被"默认理解"的符号。很多人知道名字,甚至能说出几款经典,但一旦落到"它应该是什么味道、什么质地、什么收口",整个认知是空的。于是就出现一种很微妙的情况:做错了,没有人能指出来;做对了,也未必有人能感受到差别。如果只是行业内部的问题,那还好解决,培训、标准、时间都可以慢慢堆。但真正麻烦的地方在于用户端。一个对鸡尾酒没有判断能力的人,在面对菜单的时候,其实并不是在选择,而是在规避风险。他不会真的去理解那些名字,他只是尽量选一个"听起来不会出错"的东西。

这是所有细分行业的共同处境

从2019年开始就出现了很多关于 AI 渗透传统行业的讨论,大多数都停在"AI+餐饮""AI+零售"的口号层面,举的例子不是菜单图片识别,就是智能点餐机——本质上是把一个触摸屏换了个皮。真正有意思的问题不在于"能不能用 AI",而在于"在哪个具体的摩擦点上,AI 能做人做不到或者不愿意做的事"。

对于鸡尾酒这个场景,这个摩擦点非常明确:它发生在用户拿到菜单之后、开口点单之前的那几秒。那几秒里,用户需要在一堆陌生名字里做决策,没有参考系,没有人引导,又不想显得外行。这个时间窗口极短,调酒师也不可能在这个时候系统性地问每一个客人十个问题。

所以我们在Alchory就做了一个 AI 推荐系统,并且把入口设计成一张二维码小卡片,放在门口或者能顺路路过的地方,让用户在进店之前就完成"状态描述 → AI 选酒"这个过程。

系统架构总览


先把整体结构放出来,然后再一块一块讲。


整个链路从用户扫码进入首页,到看见推荐文字一个字一个字打出来,中间经过六个主要环节。每一个都有它存在的理由,没有一个是凑数的。

酒水知识库:给每杯酒建一份「画像」

推荐系统做好的前提,是要对推荐对象有足够细粒度的描述。如果每杯酒只有名字、价格、品类,那 AI 能做的事情非常有限。我们建立了一套酒水结构化画像(`recommend_profile`),以 JSON 格式存储在菜单售卖品表里,每条酒水记录都可以携带以下维度:

这套画像不是靠 AI 实时生成的,而是人工或运营侧对每款在售酒提前录入的结构化标签。当一款酒没有配置时,系统有一套启发式回退策略:从酒名、二级分类代码(如 `IPA`、`SOUR`、`LAGER`)、描述文本里推断近似的画像值。这个设计的好处在于,AI 在打分时永远有数据可用,但有人工配置的酒款会在排序中获得显著加分,倒逼运营认真维护数据质量。

这是 AI 落地里一个很典型的权衡:不能让系统完全依赖 LLM 实时生成的知识,因为那样既慢又不可控;但也不能要求人工把所有数据都做到极致,那不现实。画像系统是一个两者之间的中间层。

两阶段 LLM:把一件事分成两件事做

这是整个系统里最核心的架构决策,也是我们踩了很多坑之后才稳定下来的设计。

最早的版本是一个端到端的提示词:用户说什么 → LLM 直接生成推荐文案。这在演示里好看,但在生产里会持续出现各种问题:有时候文案里提到了菜单上没有的酒,有时候推荐了明显不符合用户描述的风格,有时候输出格式不稳定导致解析失败。更根本的问题是,这种设计把"判断选什么"和"怎么说"混在一起,哪出了错都很难排查。

后来我们把它拆成两个阶段:

Phase A:Planner(规划器)

规划器只负责做判断,不负责写给人看的句子。它的输入包括:用户的完整表述、历史会话记录、上一轮推荐的卡片摘要、当前在售酒水的结构化 manifest(JSON 格式的 id + 名称 + 类别 + 价格清单)、需求现实校验结果、以及门店的天气和环境信息。它的输出是一份纯结构化 JSON:

{

"intent_type": "recommend_drink",

"draft_item_ids": [42, 17, 88],

"preference_update": { "entry_pressure": "low", "pace": "slow" },

"soft_rerank_bias": { "preferred_secondary_codes": ["SOUR", "WHEAT"] },

"turn_kind": "new",

"should_redirect": false,

"input_quality": "clear"

}

规划器的系统提示里明确禁止它写任何面向用户的文案,禁止它输出 `style_note`,禁止它回复解释。它的唯一职责是输出路由决策。这样设计的好处是,这个 LLM 调用的输出是完全可验证的——服务端可以逐字段检查,不合法的 id 会被过滤,不支持的意图会走默认路径。

Phase B:Renderer(渲染器)

渲染器在系统已经锁定了最终候选卡片之后才启动。它只需要把已经确定的酒款写成一段有温度的调酒师式对话。它的输入是确定好的 `final_cards`(含商品 id、名称、价格、描述摘要),以及用户原始问题。它的约束规则非常具体:不能更改或新增候选商品,不能编造「看来您喜欢…」类的伪记忆,不能照抄商品描述字段,输出格式是固定的 JSON(`bartender_message` + `style_note` + 每张卡的 `card_anchors`)。

这个拆分解决的核心问题是:让能犯错的部分(LLM 自由生成)只在不重要的地方犯错。酒的选择由规则引擎最终决定,LLM 对这个结果的影响是有限且可验证的;文案可以由 LLM 自由发挥,写错了顶多是说法不够好,不会出现推荐了不存在的酒这类硬错误。

需求现实校验:别让 AI 幻觉点名不在售的酒

这是一个容易被忽视但在真实场景里非常重要的模块。当用户说"我想喝个 IPA",而这家店今天没有 IPA 时,LLM 如果不知道这个事实,完全可能在输出里信誓旦旦地推荐一款根本不存在的酒,还配上煞有介事的描述。这不是假设,这在没有这个模块之前确实发生过。

需求现实校验(`demand_reality_check`)会在 LLM 调用之前运行,用菜单真实数据对用户的表述做比对,判断:用户点名的品类(IPA / 白酒 / 无酒精)是否在今天的在售菜单里有对应品项;如果没有,系统有几个选择——直接走「不可用」路径给出无存货提示,或者根据全局配置决定是否允许推荐替代品类。这个结果会以 JSON 快照的形式注入 Planner 的系统提示,要求模型遵守:

Planner 读到这个快照,会被明确告知"不要在候选里选 craft_beer 类商品",避免了幻觉的源头。这个设计的哲学是:AI 的幻觉问题很多时候可以通过在输入端提供更准确的事实来缓解,而不是在输出端做无尽的验证

{
"unavailable_request": true,
"recommendation_mode": "unavailable",
"triggered_families": ["craft_beer"],
"allow_substitution_effective": false
}

打分引擎:规则与 LLM 的分工边界

选出候选 id 之后,最终哪三款酒进入推荐不是由 LLM 随机决定的,而是经过一套多维打分引擎计算出来的。

打分的核心逻辑是把用户描述转化出来的偏好向量(`preference_profile`),与每款酒的结构化画像做匹配。偏好向量来自两个来源:一是服务端规则引擎直接解析用户话语(不调 LLM,纯正则 + 关键词),二是 Planner 输出的 `preference_update` 和 `soft_rerank_bias` 对规则基线做补充。

成立性判断先于打分:如果用户明确说不要甜的,所有 `sweetness` 值高的酒直接排除;如果有预算限制,单价超出人均预算约 1.5 倍的排除;如果用户要无酒精,含酒精品直接不参与。只有通过成立性检验的酒才会进入打分池。

打分维度里有一项值得专门说:`has_config`——也就是这款酒是否有人工配置的结构化画像。有配置的酒得分显著高于启发式兜底的酒,这是系统在用分数"告诉"运营:你认真配置数据,推荐质量就好。这种机制在没有人监督的情况下会自然激励数据维护行为。


多轮会话:让 AI 记住这次谈话

不是每个用户都会一次说清楚自己想要什么。有人先说"来杯清爽的",喝了觉得偏淡,下一句"还是换个烈一点的"——这时候系统需要理解这是一个跟进,而不是一个全新请求。

会话状态存储在 Redis 里(TTL 1 小时),每个会话包含:历史对话轮次、累积的偏好参数(`pref_accumulated`)、上一轮推荐的卡片、当前任务类型、候选域信息。每新的一轮,这些上下文都会被读出来注入 Planner 的提示词。

有一个设计细节是省略句短路:如果用户的新消息被判断为"含义太模糊但方向清楚的跟进"(比如"那个第二个"),系统直接从上一轮 `current_candidates` 里取对应的卡片返回,根本不调 Planner。这大幅降低了响应延迟,也避免了 LLM 在语义明显的情况下做多余的推理。

还有一个从系统安全角度考虑的设计:`non_alcoholic_request` 一旦在某一轮被确认,这个标记在整个会话里只升不降,哪怕用户后来说"算了,来杯有酒精的也行",系统也会继续保持无酒精推荐。这不是限制用户,而是默认保守——在不能百分之百确认用户意图改变的情况下,不主动给有酒精的推荐。

环境感知:天气和时间也是推荐的一部分

这个功能做起来比想象中简单,但影响比想象中微妙。系统从门店配置里读经纬度坐标,从 Redis 里读最近一次拉到的天气数据(温度、天气状况),把它拼成一行描述注入 Planner 的系统提示。

这不是为了炫技,而是因为天气对饮酒状态的影响是真实的。梅雨季闷热的下午,和秋天傍晚带点凉意的时候,一个正常的调酒师会有不同的推荐倾向。Planner 拿到这个信息不一定每次都用到,但在临界情况下——比如两款酒打分接近,一款更适合凉爽环境,另一款更适合燥热——天气数据可以成为分辨依据。

门店环境注入 Planner 的样式:
Site: ALCHORY天津奥城店. Weather: 多云 16°C.


SSE 流式:把等待变成过程

前面所有的模块都在解决"推荐得准"的问题,这个模块在解决"等待时用户的体验"问题。

Planner 调用大约需要 1-3 秒,Renderer 调用同样需要 1-3 秒。加在一起是 2-6 秒的空白等待,放在一个手机页面上是很不友好的交互。最早的版本就是一个 loading 圆圈,事实证明用户不太能接受这个。

用户视角的 SSE 事件序列:
t=0ms 点击「看看适合我的」
t=50ms ← thinking: "读取今晚在售酒单…"
t=200ms ← thinking: "将您的描述发给 AI 分析…" ← Planner 开始(用户已看到 2 条进展)
t=2100ms ← thinking: "在酒单里锁定几款备选…" ← Planner 返回,打分完成
t=2200ms ← thinking: "正在撰写推荐文案…" ← Renderer 开始
t=2350ms ← token: "今晚" ← Renderer 开始流式输出
t=2380ms ← token: "你"
t=2400ms ← token: "这个状态"
... ← 文字逐字打出(用户在读)
t=4500ms ← result: { cards: [...], message: ... } ← 推荐卡片出现

后端使用 `text/event-stream` 响应,在每个真实处理阶段之间 `yield` 一条事件出来。前端用 `fetch` 配合 `ReadableStream` 消费(`EventSource` API 不支持 POST body,所以不用)。

Renderer 阶段的 token 流式是整个体验的核心。当用户看到推荐文字一个字一个字打出来的时候,等待感几乎消失了——因为他在读,不是在等。这个效果的实现需要在后端用流式 LLM 调用(`stream: true`),再从流式 JSON 里实时解析出 `bartender_message` 字段里的字符序列,逐 token 推送。

一个需要特别注意的细节:Renderer 返回的完整 JSON 里,`bartender_message` 总是第一个字段出现,所以流式解析器不需要等整个 JSON 完成就可以开始提取。系统维护了一个简单的状态机,识别进入和离开 `"bartender_message"` 字符串值的时机,在此期间把每个字符推出去。

宣传卡入口流程

把上面所有技术放在一起,用户的实际体验是这样的:

整个流程可以在进店前完成,不需要登录,不需要注册,不需要懂鸡尾酒。用户带着一个粗略的答案走进去,对着调酒师说"我看了一下,你们那个 XX 听起来不错",而不是沉默地对着菜单发呆。

这件事的真实困难在哪里?

把所有技术写完,iN觉得有必要说说它真正难的地方,不是代码,是边界

AI 推荐系统能做到的是:理解用户今晚的大致状态,在真实在售的酒单里找到三款在画像维度上最匹配的,用自然语言解释推荐理由,在等待时让用户看到过程而不是空白。这些做到了。

AI 推荐系统做不到的是:判断调酒师今天的发挥是否稳定,判断一杯干马天尼是否该进摇壶,判断现场的氛围是否让用户觉得舒适。那些需要人,需要时间,需要整个行业认知水位的抬升。

一些事是AI可以解决的,而另一些事情例如作出标准的酒则是Alchory所擅长的,而引入AI的初衷则是——我们只是想先解决那个"拿着菜单不知道从哪里开始"的瞬间,仅此而已。

其他的,慢慢来。


对行业的一点想法

AI 渗透各个行业的路径,其实有规律可循。凡是信息不对称严重、决策成本对普通用户来说偏高、同时又不适合用大量文字或视频来提前教育用户的领域,AI 作为实时的、个性化的引导工具就有机会。鸡尾酒是这样,精品咖啡的豆子选择是这样,高端护肤品的成分搭配是这样,定制家具的方案选型也是这样。

但有一个共同的前提经常被忽略:AI 的输出质量上限,取决于结构化数据的质量下限。我们花在建立酒水画像体系、维护现实数据准确性、设计打分引擎约束条件上的时间,远远超过了调 LLM 提示词的时间。这个比例大概是 7:3,而大多数人的直觉是反过来的。

那张印着二维码的小卡片,背后是这些。

展开阅读全文

更新时间:2026-04-16

标签:美食   鸡尾酒   卡片   用户   系统   画像   数据   菜单   酒水   文案   提示

1 2 3 4 5

上滑加载更多 ↓
推荐阅读:
友情链接:
更多:

本站资料均由网友自行发布提供,仅用于学习交流。如有版权问题,请与我联系,QQ:4156828  

© CopyRight All Rights Reserved.
Powered By 61893.com 闽ICP备11008920号
闽公网安备35020302035593号

Top