别人问我在厨房里摆一堆塑料管和泵干什么,我说在造一台能听懂人话的汽水机。按字面意思理解就行:你对它说一句模糊的话,比如“来一杯傍晚六点的海边”,过一会儿杯子里真的会出现一杯带柚子皮和海盐味的苏打水。这台机器我从立项到稳定出杯花了8个月,属于典型的中配DIY:没有工业机器人那么贵,但也绝对不像玩具那样只是喷点糖水。它背后串起了本地大模型、配方引擎、蠕动泵、二氧化碳碳酸化和一堆清洗逻辑。这篇文章不是晒成品图,我想把整个项目的思路、选型、软件链路和踩过的坑一次性说清楚,给同样想折腾AI硬件、又不想只做个语音灯牌的人一些参考。
1. 项目缘起与整体设计
1.1 为什么会想做一台“会说人话”的汽水机
传统自动售货机的交互逻辑是“按键选择”,杯装可乐就三种:原味、无糖、零度。想喝“气泡足一点、酸一点、尾段回一丁点咸”的饮料?按键解决不了,因为选项根本不在面板上。人描述味道的时候本来就模糊,比如“清爽”可以指柠檬酸、薄荷凉、气泡刺激,也可以指冰镇带来的低温感。如果能让机器直接听懂自然语言,就等于把无限种描述和有限种原料桥接起来。
前期的想法其实很简单:话筒进文本,大模型把文本转成结构化配方,泵再把配方变成液体。听起来是标准AI Agent,真正做起来发现难的是“结构化配方”这件事。大模型很容易吐出“好的,为您准备一杯夏夜海风”这种漂亮废话,但如果后面没有可执行的参数,机器只能干瞪眼。整个项目推倒重来两次,第一次卡在配方解析,第二次卡在剂量精度,第三次才算跑通。
1.2 “五十万种抽象口味”是怎么凑出来的
先说结论:机器里并没有50万瓶香精,50万种口味的本质是参数组合空间。我设计了一杯饮料的12个自由变量,包括甜度、酸度、苦度、咸度、气泡强度、温度、风味标签、修饰维度等。每个变量不是连续浮点,而是被离散成合理档位。比如甜度0到1分成20档,酸度分成20档,气泡分成10档,温度设置常温/冷藏/冰三档,风味库里有30个标签,最多选2个组合。
这样粗算一下:20乘20乘10乘3乘C(30,2),已经超过500万种组合,哪怕只暴露十分之一,也远远超过“50万”。但你不会让用户手动去调浮点参数,而是让AI根据用户描述去匹配这些组合。所以“50万种抽象口味”不是一张静态菜单,而是一个生成空间。用户每次输入一个抽象词,AI在这个空间里取一个合理且有约束的落点,最后出来的饮料就带有无法用固定菜谱复现的“个人感”。
1.3 中配方案的整体架构和成本构成
所谓“中配”,是我在硬件选型上没上工业级,也没用玩具级。整机物料成本大约8000元上下,不含3D打印外骨架和人工。整体架构分成五层:交互层负责语音识别和文本确认;AI决策层运行本地大模型,负责把口语转成配方参数;配方引擎层负责校验、计算体积和生成执行序列;执行层用ESP32控制泵和阀;安全层包括称重传感器、漏液检测和异常停机。
这样做最大的原因是“稳定优先”。如果AI用云端接口,断网就变成摆设;如果所有逻辑都塞进ESP32,7B模型根本跑不动。所以我让迷你主机干“脑力活”,ESP32干“体力活”,两者通过串口通信。迷你主机跑量化后的7B模型和Whisper,ESP32只管按照指令泵多少毫升液体。脑体分离之后,单独调试任何一个环节都方便,不会出现“改一句Prompt就要重新烧固件”的尴尬。
2. 口味引擎:怎么把自然语言变成一杯饮料
2.1 口味空间设计:原料库和维度
原料库是整台机器的“词汇表”。如果风味库里没这个词,AI再聪明也没法映射。我设置了六个糖浆通道、两个口感修饰通道和一个气泡水通道,具体如下:
| 通道 | 原料类型 | 作用 |
|---|---|---|
| 甜味底 | 蔗糖糖浆 | 提供甜感和厚度 |
| 酸味底 | 柠檬酸+苹果酸混合液 | 调整酸度,增加清爽感 |
| 咸味底 | 海盐水 | 增加咸味,提升回甘 |
| 苦味底 | 咖啡提取物/柚子皮浸液 | 增加层次和余味 |
| 风味1 | 草莓、香草、焦糖、薄荷等 | 主风味 |
| 风味2 | 柚子、椰子、青瓜、姜等 | 副风味或转折 |
| 气泡水 | CO₂碳酸水 | 口感和气体刺激 |
每个口味有六个维度:甜度、酸度、苦度、咸度、气泡、温度。再加两个修饰维度:醇厚度和清爽感,修饰维度不直接增加原料,而是改变糖浆比例和碳酸水比例。比如“醇厚”会把糖浆总量提高,同时减少气泡水比例;“清爽”则反过来把酸液比例调高、糖浆压低。原料库不能太杂,否则管路多、清洗麻烦,但也不能太少,要不然AI翻译完没有对应物料,等于白说。
2.2 让大模型输出配方参数,而不是输出菜谱
刚开始我犯过一个典型错误:让大模型直接输出“加10毫升柚子糖浆、5毫升薄荷糖浆、2毫升海盐水”。这种输出表面精确,实际上很危险,模型对物理单位的感知不可靠,它会自信地编一个毫升数,而且不同描述之间没有一致性。正确做法是让模型输出语义参数,再由本地配方引擎换算成体积。
我用的Prompt大概长这样:
[System] 你是一台汽水机的配方顾问。请把用户对口味的要求转换成JSON。 字段如下: sweetness: 0到1的小数 sourness: 0到1的小数 bitterness: 0到1的小数 saltiness: 0到1的小数 bubble: 0到1的小数 temperature: "常温" 或 "冷藏" 或 "冰" flavors: 最多2个字符串,必须来自风味库 modifiers: 最多2个字符串,表示醇厚、清爽、烟熏等口感修饰 如果用户说的是场景或抽象词,请用合理想象补全。 只输出JSON,不要解释,不要客套。 [User] 来一杯夏夜海风关键不是让模型“懂饮料”,而是让它“懂JSON”。约束只输出JSON,解析成功率会有非常大的提升。解析失败时,程序自动重试一次,还是失败就落到关键词匹配兜底,保证机器不会因为一句话没听懂就罢工。
2.3 随机扰动与安全边界:为什么同一句话每次喝起来会有变化
“五百万种组合”听上去很多,但如果不引入扰动,同一个描述每次都会映射到同一个点,用户喝几次就觉得AI其实是个固定菜谱。所以我在配方引擎里加了一个随机种子,以大模型输出的参数为中心,在百分之十的范围内做轻微扰动。甜度0.3可能实际执行成0.31,酸度0.5可能变成0.48,这样同一句“夏夜海风”每次出杯都有细微区别,类似手调咖啡的批次差异。
但扰动绝不能乱来。甜酸比必须守住底线,如果甜度太低、酸度太高,整杯就像醋精;苦味不得超过0.6,否则像喝药;咸味底液单杯不超过3毫升,避免变成生理盐水。这些硬约束放在校验器里,任何参数经过校验器之后,超出范围就会被拉回边界,或者直接拒绝请求。没有这道保险,AI的“创造性”只会做出没法喝的东西。
3. 硬件系统:泵、阀、气瓶和管路的组装
3.1 中配硬件怎么选:泵、阀、主控和大脑
硬件选型花了我不少时间。最开始想省钱,用普通水泵,就是鱼缸那种,结果泵腔里有叶轮,糖浆进去之后根本洗不干净,第二天就发黏。后来换成蠕动泵,液体始终在硅胶管里流动,泵体不接触液体,食品卫生和清洗都省心很多。中配方案用六路12V直流蠕动泵,流量在30到60毫升每分钟之间,固定电压工作,不用PWM调速。
主控用的是ESP32,理由很朴素:IO口多、便宜、资料多。ESP32负责控制继电器和泵,读取重量传感器,看漏液检测,还负责和迷你主机的串口通信。AI大脑则是一台带8GB内存的迷你主机,跑量化后的7B本地大模型和Whisper语音识别。为什么不用树莓派跑模型?树莓派跑7B实在太慢,CPU推理一句话要半分钟,体验很差。迷你主机体积并不大,塞在机器底座里刚好。
3.2 管路布局与剂量控制:毫升到底怎么算
管路布局图不画了,核心原则是“每路独立、出液汇合”。每个原料瓶接一根食品级硅胶管,经过蠕动泵后汇合到同一个出液头。糖浆泵出口必须装止回阀,否则碳化水压力会倒灌进糖浆管,第二天你会看到糖浆瓶里冒着小气泡。
剂量计算靠时间和重量双重控制。校准过程:每种液体泵10秒,称量实际重量,多次求平均,得到“毫升每秒”系数。执行时先按时间预估,再由杯子底部的3公斤称重传感器实时修正,当出液总重量达到目标量前100毫秒就关闭泵。这样能抵消糖浆粘度、温度带来的流量偏差。如果你忽略校准,第一杯出来可能糖浆占了一半,甜到怀疑人生。
3.3 制冷、碳酸化和出杯顺序的小实验
碳酸化最忌讳水温高。CO₂在4度水里的溶解度远高于常温,所以净水要先经过制冷循环水槽,把水温降到2到5度,再进碳酸化罐。罐体我用5L不锈钢罐,接CO₂钢瓶,压力控制在3bar,静置10分钟以上让气体溶解。一开始我把压力调到3.5bar,结果出杯时碳酸水接触到杯底就瞬间炸泡,整杯全是沫,后来降到3bar并在出液管上加了0.5米缓压管路,泡才细下来。
出杯顺序也试过几个版本。先加糖浆、后加碳酸水最不容易消泡,因为糖浆落杯,碳酸水从上面冲入,搅拌作用刚好。反过来先出水后出糖浆,糖浆会沉底,喝前还得手动摇匀。清洗顺序则完全反过来:每次调制完成后,清水泵启动10到15秒,冲洗出液头和混合管路,把残留糖浆带走,避免下一杯串味。
4. 软件与控制逻辑:从语音到泵动作的完整链路
4.1 语音输入怎么做才不会听错
语音识别最现实的坑不是“识别不出来”,而是“识别错了但你还不知道”。比如“海盐”很容易被识别成“海燕”,“柚子皮”可能变成“柚子啤”。所以我在交互层做了文本确认:用户按录音键说话,Whisper把音频转成文本显示在屏幕上,用户确认无误后,文本才送进大模型。这个步骤只多一次点击,却把整个链路的错误率降了一个量级。
开始我还想加关键词唤醒,让机器一直监听“AI汽水”四个字。后来发现本地Whisper在CPU上识别并不快,误唤醒也多,最后改成物理按钮。这个改动其实很反直觉,但更符合家用场景:自己家里用,按一下按钮并不可耻。
4.2 配方生成与执行链路的10个环节
整套流程可以拆成10个环节,每个环节都有明确的输入和输出:
- 用户说话或打字
- Whisper把音频转文本
- 文本在屏幕上确认
- 迷你主机把文本发给本地大模型
- 大模型输出JSON配方
- 校验器检查参数是否越界
- 配方引擎计算每种原料的毫升数
- 毫升数换算成泵运行时间
- ESP32按顺序启动泵和电磁阀
- 重量传感器闭环停止,提示取杯并启动清洗
第6步很容易被忽略,但极其重要。模型可能输出sweetness为0,用户只说“苦咖啡”,机器就真的完全不加糖,做出来难喝到怀疑人生。校验器会判断如果苦度大于0.5,最低甜度必须保持0.15以上。这些规则不是AI学出来的,是我一杯一杯喝出来的,属于项目里的隐性成本。
4.3 安全保护和异常恢复:防止机器“下毒”
AI汽水机不是玩具,涉及泵、高压CO₂、食品原料,所以安全逻辑一定要做全。第一道防线是重量传感器,出液量超过目标百分之十立即停机;第二道防线是泵的电流检测,蠕动泵空转时电流会比有液体时低,一旦检测到空转就自动停泵并报警;第三道防线是水浸传感器,如果底盘有液体泄漏,直接切断主泵电源,避免糖浆流得到处都是。
太相信大模型也会出问题。早期测试时,模型曾给“加了点辣椒油”这种描述输出“辣椒油”风味标签,但风味库里根本没有这个物料。校验器会拒绝未知标签,转成“原味苏打水+微量酸液”,不让机器执行不存在的配方。断点恢复也要考虑:如果调制中途断电,开机后先检测清洗记录,如果上次没有完成清洗,就强制进入清洗程序,防止管路里残留糖浆干结。
5. 实际调制效果与调试过程
5.1 一杯“夏夜海风”是怎么从语言变成液体的
拿一个真实例子说流程。我在输入框打了“夏夜海风”,屏幕确认后,大模型返回这样的JSON:
{ "sweetness": 0.3, "sourness": 0.5, "bitterness": 0.1, "saltiness": 0.4, "bubble": 0.9, "temperature": "冰", "flavors": ["柚子", "薄荷"], "modifiers": ["海盐"] }配方引擎按300毫升总量计算:基础糖浆20毫升,酸液6毫升,海盐水1.5毫升,柚子糖浆10毫升,薄荷糖浆6毫升,剩下大约256毫升用碳化水补满。执行时先泵入所有液体,再开碳化水阀,重量到300克左右关闭。出杯后气泡很细,柚子香气先出来,中段是薄荷凉感,尾端海盐咸味才慢慢浮现。不能说多好喝,但确实像一杯“海风”而不是一杯糖水。
5.2 调试中翻过的车:剂量漂移、口感失衡、气泡失控
剂量漂移是最耗时的坑。泵管用了一段时间后,被蠕动泵轮反复挤压,回弹能力下降,实际流量比校准值低了不少。同样的泵10秒,第一天出15毫升,两周后可能只出12毫升。后来我把校准频率固定为每周一次,硅胶管每三个月换一批,流量才稳定下来。
口感失衡的问题出在大模型的“自由发挥”。有次用户说“来一杯人生”,模型给出的苦度是0.8,整杯像中药,完全没法入口。我在校验器里加了规则:苦度大于0.6时强制拉回0.4,甜度低于0.1时强制提到0.15。规则不复杂,但能让极端输出回到可喝范围。
气泡失控也折腾了很久。压力过高、水温不够低、出液管太短都会导致出杯后大量气泡溢出。最后解决方案是“低温水、3bar恒定压力、出液管加长到0.5米、杯口倾斜摆放”,四个措施缺一不可。只降低压力会导致气泡感不足,只加长管路又会让水流变慢,必须配合调整。
5.3 实测几个抽象口味的“风味报告”
| 用户描述 | 大模型抽取的风味 | 实测感受 |
|---|---|---|
| 外婆家的老木柜 | 香草、焦糖、一点烟熏 | 饮料偏厚,像加了坚果糖浆 |
| 周一早晨 | 咖啡、奶感、微苦 | 跟拿铁气泡水差不多 |
| 代码终于跑通了 | 薄荷、柠檬、气泡拉满 | 很清爽,尾端有点酸 |
| 楼下刚割完的草坪 | 青瓜、薄荷、青柠 | 一言难尽,但确实有植物感 |
| 八月午后的雷阵雨 | 白桃、茉莉、微咸 | 意外好喝,像白桃冷泡茶 |
这些结果说明,抽象口味能不能喝并不完全取决于AI,而是取决于你原料库里准备了什么。风味库越贴近日常食物,抽象描述落地后越容易好喝。如果非要映射“机油味”,原料库做不到,校验器也会拦下来。
6. 常见问题与避坑指南
6.1 高频问题速查表
| 现象 | 可能原因 | 解决办法 |
|---|---|---|
| 出液量偏少 | 泵管老化,流量下降 | 每周校准,三个月换硅胶管 |
| 出杯后全是大气泡 | 碳化水压力过高或水温高 | 压力稳定在3bar,预冷到4度 |
| 有上一杯味道残留 | 清洗时间不足 | 清洗延长到15秒,拆洗混合头 |
| 模型输出不是JSON | Prompt约束不够严格 | 重试一次,失败落到关键词兜底 |
| 语音识别成错别字 | 环境噪音或麦克风位置不好 | 增加文本确认环节 |
| 糖浆倒灌 | 泵出口没有止回阀 | 每个糖浆泵出口加装止回阀 |
| 调制中途停机 | 重量传感器读数跳变 | 检查传感器固定是否松动,重新去皮 |
6.2 原料安全、管路清洗和长期维护
原料安全是底线。所有接触液体的管子必须用食品级铂金硫化硅胶管,别用普通PVC软管,糖浆和酸液会把工业管里的增塑剂泡出来。自制的海盐水、酸液和糖浆要贴标签,标注配置日期。糖浆类原料开封后放冰箱保存,最多一周换一次,否则管路里容易滋生细菌。
气瓶安全同样不能马虎。CO₂钢瓶一定要竖直固定,防止倾倒。减压阀选带压力表的型号,每次使用前检查压力是否正常,管路接口用卡箍锁紧。自制冷饮设备没有质检背书,自己喝没问题,但如果要给别人喝,务必在显眼位置标注原料成分和过敏提示,不要让人盲猜。
6.3 如果你想复刻一台,我的建议
不要一上来就搞自由语音加无限口味。先把机械部分调稳,做一个只有三个固定配方的按钮版,验证泵和清洗没问题后,再加AI推荐层。等AI层稳定了,最后再放开抽象描述。这个顺序能帮你把问题分层,不然一旦出错,你根本不知道是泵的问题、模型的问题还是Prompt的问题。
预算上可以适当压缩。如果你已经有电脑能用大模型API,本地迷你主机可以省掉,用API替代也能跑。真正不能省的是蠕动泵、止回阀和重量传感器,这三样决定了你的饮料能不能“按量出杯”。至于外壳和外观,最后再考虑,机器能稳定出第一杯能喝的饮料之前,不需要好看。
做完这台机器,我最大的体会是:AI硬件项目里,真正难的不是AI,而是让液体按照你的要求一滴不多一滴不少落在杯子里。那些看起来“智能”的部分,可能只占20%工作量,剩下80%都是泵、阀、管子和清洗。但正因如此,当一杯别人描述不出来的汽水被端出来时,那种满足感还是很值得。最后再分享一个小技巧:如果家里有碳酸饮料爱好者,可以把出杯温度恒定在4度,气泡感会明显更好;温度一高,配方再好也白搭。这台机器我暂时不拆,下一步计划给它加奶泡模块,到时候再来更新。