当前位置: 首页 > news >正文

开发日志(十):RAG 的智能菜单助手设计

一、项目背景

在境外旅行、跨文化聚餐或者浏览外文菜单时,用户经常会遇到以下问题:

  1. 菜单使用外语书写,无法快速理解菜品名称和配料;
  2. 菜单排版复杂,传统 OCR 只能识别文字,难以还原菜品与价格之间的对应关系;
  3. 用户可能存在过敏原、忌口、素食、低糖等饮食限制;
  4. 即使完成菜单翻译,用户仍然不知道“哪些菜适合自己”;
  5. 普通聊天模型不了解当前菜单内容,容易推荐菜单中不存在的菜品。

因此,本项目并没有将功能停留在“图片翻译”阶段,而是设计了一套完整的智能菜单理解与问答系统。

用户上传菜单图片后,系统首先使用多模态大模型识别菜单内容,将图片转换为结构化菜品数据;随后把菜品信息写入向量数据库;当用户针对菜单进行提问时,系统结合菜单知识、用户偏好和大语言模型生成个性化回答。

整个系统形成了如下业务闭环:

菜单图片上传 ↓ 多模态模型识别 ↓ 结构化菜品 JSON ↓ 文本切分与向量化 ↓ Chroma 向量数据库 ↓ 用户问题与偏好 ↓ 相关菜品检索 ↓ 大语言模型生成回答 ↓ Flutter 页面展示

这并不是简单地给原有应用增加一个聊天框,而是将“多模态识别、知识入库、向量检索、个性化推荐和移动端交互”整合成一条完整的 AI 工程链路。


二、项目需求分析

1. 菜单图片识别

系统需要支持用户上传真实菜单图片,并从图片中提取:

  • 原始菜品名称;
  • 中文翻译名称;
  • 菜品描述;
  • 价格;
  • 菜品标签;
  • 可能包含的食材;
  • 辣度、素食等属性。

传统 OCR 通常只能返回零散文字,例如:

Spicy Chicken 12.99 Beef Noodles 15.50

但系统真正需要的是结构化结果:

{"name_original":"Spicy Chicken","name_zh":"香辣鸡肉","description":"Chicken cooked with chili and vegetables","price":"12.99","tags":["辣","鸡肉"]}

因此,识别过程不仅包含 OCR,还包含语义理解、字段归类和结构化抽取。

2. 菜单知识问答

识别结果展示完成后,用户还可能继续提出问题,例如:

  • 哪一道菜不辣?
  • 有适合素食者的菜吗?
  • 我对花生过敏,哪些菜不能点?
  • 推荐一道价格较低的主食。
  • 这几道菜中哪一道热量可能更低?
  • 给我推荐两道适合分享的菜。

如果直接将问题发送给普通大模型,模型并不知道当前菜单里有哪些菜,也可能编造菜单中不存在的内容。

因此,系统需要使用 RAG 技术,将当前菜单作为外部知识来源。

3. 用户个性化偏好

不同用户的饮食需求并不相同,系统需要考虑:

  • 过敏原;
  • 忌口食材;
  • 素食或纯素需求;
  • 清真饮食需求;
  • 辣度偏好;
  • 口味偏好;
  • 价格倾向。

用户提出“帮我推荐一道菜”时,系统不能只根据菜品名称回答,而应结合用户个人信息进行推荐。

4. 移动端完整交互

Flutter 客户端需要实现完整流程:

选择图片 → 上传图片 → 等待识别 → 展示菜单 → 发起问题 → 等待后端生成 → 展示回答

此外还需要处理网络异常、模型异常、空结果、鉴权失效等情况,避免页面白屏或者一直处于加载状态。


三、什么是 RAG

RAG 的全称是 Retrieval-Augmented Generation,即“检索增强生成”。

它的核心思想是:

在大模型回答问题之前,先从外部知识库中检索相关内容,再让模型根据检索结果生成答案。

一个基本的 RAG 流程可以表示为:

用户问题 ↓ 问题向量化 ↓ 向量数据库相似度检索 ↓ 获取相关知识片段 ↓ 知识片段与问题拼接 ↓ 大模型生成回答

例如,用户提问:

我不能吃辣,推荐一道主食。

系统会先从当前菜单知识库中检索与“不辣”“主食”“推荐”等语义相关的菜品,再将检索结果传给大模型。

最终发送给模型的内容可能类似:

用户偏好: - 不吃辣 - 偏好主食 菜单检索结果: 1. Mushroom Pasta,奶油蘑菇意面,价格 13.99,标签:不辣、主食 2. Spicy Beef Noodles,香辣牛肉面,价格 15.99,标签:辣、主食 用户问题: 我不能吃辣,推荐一道主食。 请只根据菜单检索结果回答。

模型便可以推荐奶油蘑菇意面,并说明不推荐香辣牛肉面的原因。


四、为什么不能只使用大模型

直接调用大模型虽然实现简单,但存在几个明显问题。

1. 大模型不了解当前菜单

当前菜单属于用户实时上传的数据,不在模型原有训练知识中。

2. 容易出现幻觉

如果让模型自由回答,它可能生成菜单中不存在的菜品、价格或配料。

3. 菜单内容会不断变化

每次上传的菜单都不同,无法通过固定提示词保存全部菜单信息。

4. 长菜单会占用大量上下文

直接把完整菜单放入 Prompt,会增加 Token 消耗,也可能降低模型对重点信息的关注度。

RAG 可以只检索与当前问题相关的若干菜品,从而减少上下文长度,提高回答相关性。


五、本项目采用的核心技术

1. Qwen 多模态大模型

多模态模型负责理解菜单图片。

与传统 OCR 相比,多模态模型不仅能够识别文字,还可以理解:

  • 菜名与价格之间的对应关系;
  • 菜品分类;
  • 描述和菜名之间的从属关系;
  • 菜品可能具有的标签;
  • 图片中的版面结构。

模型输出经过约束后转换为统一的 JSON 格式,为后续处理提供基础。

2. LangChain

LangChain 用于组织 RAG 处理流程,包括:

  • 将菜品 JSON 转换为 Document;
  • 调用 Embedding 模型生成向量;
  • 管理检索过程;
  • 构造问答 Prompt;
  • 调用聊天模型生成答案。

3. Embedding 向量模型

Embedding 模型负责将文本转换为向量。

语义相近的文本在向量空间中的距离通常也更近。例如:

“不辣的菜” “清淡菜品” “没有辣椒的食物”

虽然文字不完全相同,但经过向量化后具有较高的语义相似度。

4. Chroma 向量数据库

Chroma 用于存储菜品文本向量和菜品元数据。

系统可以根据用户问题执行相似度搜索,返回最相关的 top-k 个菜品文档。

5. FastAPI

后端使用 FastAPI 提供接口,主要负责:

  • 接收菜单图片;
  • 调用多模态模型;
  • 解析结构化结果;
  • 执行向量入库;
  • 接收用户问题;
  • 查询用户偏好;
  • 调用 RAG 问答服务;
  • 返回统一格式的数据。

6. Flutter

Flutter 客户端负责:

  • 图片选择和上传;
  • 菜单结果展示;
  • RAG 对话交互;
  • 用户偏好传递;
  • 收藏和购物车等原有业务;
  • 异常提示和加载状态管理。

六、系统的四层架构

第一层:菜单感知层

输入是非结构化菜单图片,输出是结构化菜品 JSON。

这一层的核心任务不是单纯识别文字,而是将图片内容转换为后端可以稳定处理的数据结构。

第二层:知识入库层

结构化菜品需要重新组织成适合语义检索的文本,例如:

菜品原名:Spicy Chicken 中文名称:香辣鸡肉 描述:鸡肉搭配辣椒和蔬菜烹制 价格:12.99 标签:辣、鸡肉、主菜

随后生成向量并写入 Chroma 数据库。

第三层:检索增强问答层

用户提问后,系统先检索相关菜品,再结合用户偏好构建 Prompt,最后调用聊天模型回答。

第四层:前后端业务闭环层

Flutter 与 FastAPI 完成接口联调,确保菜单识别结果能够自动入库,并能够在结果页中进行真实问答。


七、项目整体特点

本项目可以概括为一个:

多模态菜单识别 + 向量检索 + 个性化推荐 + 移动端交互闭环的复合式 RAG 系统。

它同时涉及:

  • 非结构化图片理解;
  • 结构化信息抽取;
  • 菜品知识表示;
  • 向量索引构建;
  • 检索增强生成;
  • 用户偏好融合;
  • 前后端接口编排;
  • 模型运行环境管理;
  • 异常处理与工程兜底。

相比普通的聊天问答功能,这类系统的难点不只在模型本身,更在于如何让每个环节真正连接起来。

下一篇文章将详细介绍该系统的具体开发过程,包括菜单处理接口、Document 构造、Chroma 入库、RAG 问答服务和 Flutter 结果页改造。

http://www.gsyq.cn/news/1509184.html

相关文章:

  • 网络安全干货:护网行动实战经验分享
  • 如何用LinkSwift快速获取九大网盘直链下载地址:告别限速烦恼
  • 荆门市黄金回收白银回收铂金回收彩金回收靠谱门店TOP排行榜及联系方式地址电话+诚信店铺推荐 - 大熊猫898989
  • Qdrant源码与算法
  • 荆州市黄金回收白银回收铂金回收彩金回收靠谱门店TOP排行榜及联系方式地址电话+诚信店铺推荐 - 大熊猫898989
  • XGP存档提取终极指南:3分钟释放你的游戏进度自由
  • PyTorch工程化起点:可复现、可扩展、可交付的训练模板
  • 景德镇市黄金回收白银回收铂金回收彩金回收靠谱门店TOP排行榜及联系方式地址电话+诚信店铺推荐 - 大熊猫898989
  • 从一段DXF数据看懂CAD图元结构:手把手教你用VBA解析Polyline的组码含义
  • 探讨乌兰察布广告标识定制公司,靠谱推荐费用多少 - myqiye
  • 042、Edge Impulse的实时推理与数据流
  • C# WinForm工程:原生调用Windows PnP接口实现安卓手机等MTP设备的文件上传下载
  • 深入AutoSar DCM:从诊断会话状态机到DcmDspSessionCallback回调函数设计
  • 2026年电采暖厂家排名前十,分析电采暖靠谱企业如何选择与口碑对比 - myqiye
  • Proteus中M45PE80 Flash芯片SPI读写擦除全流程仿真工程(含Keil C51源码与DSN电路图)
  • 别再被误导了!这才是 Agent ↔ Tools 循环的真实底层逻辑(无误区完整版)
  • iOS应用开发完整指南:从零到App Store上架(2026版,含费用清单)
  • 当Excel成为CAD的遥控器:揭秘Office与AutoCAD的COM接口交互实战
  • 2026年6月在线pH监测仪主要品牌排行榜:市场格局、核心技术参数与选型实战全解析 - 仪表品牌榜
  • 地理空间数据正在被军事化:宝可梦GO事件的技术复盘与警示
  • 2026年高陵区哪家上门回收机构口碑好 - mypinpai
  • 达州市黄金回收白银回收铂金回收彩金回收靠谱门店TOP排行榜及联系方式地址电话+诚信店铺推荐 - 大熊猫898989
  • 白银市黄金回收白银回收铂金回收彩金回收靠谱门店TOP排行榜及联系方式地址电话+诚信店铺推荐 - 大熊猫898989
  • ncmdump:打破网易云音乐格式枷锁的本地解密利器
  • 045、Edge Impulse的视觉分类实战
  • 046、Edge Impulse的加速度计手势识别实战
  • 基于Python的高校广告投放智能选校系统:从人工经验到数据决策
  • 潜江汽车烧机油治理,多少钱能搞定? - mypinpai
  • 2026年福建漂染化工原料供应商深度分析:技术、服务与区域协同新趋势 - 优质品牌商家
  • Windows原生开发开箱即用的核心头文件包:含windows.h及基础构建示例