
黑马点评项目升级集成GME-Qwen2-VL-2B实现菜品图片自动点评生成1. 引言做餐饮点评平台的朋友们应该都遇到过类似的难题用户上传了精美的菜品照片但到了写评论的时候却常常词穷要么写个“好吃”要么干脆不写。这不仅让内容显得单薄也浪费了那些诱人图片带来的分享价值。我们之前做的“黑马点评”项目就是一个仿照主流点评平台的学习项目核心功能都跑通了。但最近在思考能不能让这个系统更“聪明”一点比如当用户上传一张美食图片系统能不能“看懂”图片并主动给用户一些写评论的灵感这个想法促使我们进行了一次功能升级。我们集成了GME-Qwen2-VL-2B这个多模态大模型。现在用户上传菜品图片后系统除了保存图片还会在后台悄悄调用这个模型“看图说话”生成一段模拟用户口吻的点评建议比如“这份红烧肉色泽油亮肥瘦相间看起来非常下饭”然后自动填充到评论框里。用户可以直接发送也可以基于这个建议修改大大降低了写评论的门槛。这篇文章我就来分享一下我们是如何在“黑马点评”这个经典项目中落地这个“图片自动生成点评”功能的。整个过程不复杂但效果很实在希望能给你带来一些启发。2. 为什么选择GME-Qwen2-VL-2B市面上能“看懂”图片的模型不少为什么我们最终选了GME-Qwen2-VL-2B呢主要是基于几个很实际的考虑。首先它足够“轻量”。名字里的“2B”指的是20亿参数这在多模态模型里算是比较小巧的。对于“黑马点评”这样一个学习项目或者对于中小型业务初期我们不需要动辄百亿、千亿参数的“巨无霸”。轻量意味着部署资源要求低推理速度快成本也更可控。我们的服务器资源有限这个模型刚好合适。其次它的中文理解能力很强。毕竟我们的点评平台主要面向中文用户生成的点评文字不仅要准确描述图片内容还要符合中文的表达习惯甚至带点“烟火气”。GME-Qwen2-VL-2B在这方面表现不错生成的文本比较自然不会像翻译软件那样生硬。最后也是很重要的一点它支持“视觉-语言”的端到端理解。简单说就是模型能真正把看到的图像信息和要生成的文字信息联系起来。对于菜品点评这个场景我们需要模型不仅能识别出“红烧肉”还能联想到“色泽”、“肥瘦”、“下饭”这些相关的描述性词汇它在这方面做得挺好。当然它也不是万能的。对于极其复杂、包含多种罕见菜品的图片或者对菜品有非常专业、细致的品鉴要求比如米其林餐厅评测它的能力可能就有边界了。但对于我们“激发用户评论灵感”这个核心目标来说它完全够用是一个性价比很高的选择。3. 整体方案设计与架构调整原来的“黑马点评”项目上传图片的流程很简单前端传图 - 后端接收并存储到对象存储比如MinIO- 把图片访问地址存到数据库 - 返回成功。现在要加入自动生成点评的功能我们就得在这个流程里插入一个“智能处理”环节。我们的设计思路是异步处理体验优先。具体来说当用户上传图片后后端主线程只负责快速完成图片的存储和基础信息记录然后立刻返回响应给前端告诉用户“图片上传成功”。与此同时系统会创建一个异步任务这个任务负责去调用GME-Qwen2-VL-2B服务分析刚上传的图片并把生成的点评建议文本更新到对应的数据库记录中。这样设计的好处是用户不会因为等待AI分析而觉得页面卡顿。上传体验和以前一样快。生成的点评建议我们计划在用户进入写评论页面时再通过一次单独的查询从数据库里取出来填充到评论框里。整个架构的微调如下图所示此处用文字描述原有的“上传服务”模块在保存图片后会向一个“消息队列”如RabbitMQ发送一个任务事件。新增加的“AI点评生成服务”作为一个独立的消费者监听这个队列。一旦收到任务它就取出对应的图片地址调用GME-Qwen2-VL-2B的API拿到结果后回写到数据库的comment_draft评论草稿字段。而前端在加载评论页面时会查询这个字段并预填。4. 核心实现步骤详解下面我挑几个关键步骤用代码和说明来展示具体是怎么做的。4.1 服务端改造图片上传接口我们首先改造后端的图片上传控制器。核心是将其拆分为同步存储和异步分析两部分。RestController RequestMapping(/upload) public class UploadController { Autowired private FileStorageService fileStorageService; // 原有的文件存储服务 Autowired private DishService dishService; // 菜品服务 Autowired private AsyncCommentGenerateService asyncCommentGenerateService; // 新增的异步服务 PostMapping(/dish-image) public Result uploadDishImage(RequestParam(file) MultipartFile file, RequestParam(dishId) Long dishId) { // 1. 同步处理上传图片到对象存储 String imageUrl fileStorageService.uploadFile(file); // 2. 同步处理将图片URL与菜品关联存入数据库这里假设是dish_image表 DishImage dishImage new DishImage(); dishImage.setDishId(dishId); dishImage.setUrl(imageUrl); dishImage.setStatus(0); // 0-待分析1-分析完成2-分析失败 dishService.saveDishImage(dishImage); // 3. 触发异步任务生成点评建议 asyncCommentGenerateService.generateCommentDraft(dishImage.getId(), imageUrl); // 4. 立即返回成功包含图片URL return Result.ok(imageUrl); } }注意我们给dish_image表增加了一个status字段和一个comment_draft字段分别用来记录分析状态和存储生成的点评草稿。4.2 服务端实现异步点评生成服务接下来我们实现异步服务。这里使用Spring的Async注解来简化异步调用。Service Slf4j public class AsyncCommentGenerateService { Autowired private GMEQwenVLClient gmeQwenVLClient; // 封装好的模型调用客户端 Autowired private DishService dishService; Async(taskExecutor) // 指定自定义的线程池执行器 public void generateCommentDraft(Long dishImageId, String imageUrl) { try { log.info(开始为图片[{}]生成点评草稿, dishImageId); // 1. 构建调用多模态模型的提示词(Prompt) String prompt 请仔细观看这张美食图片然后以一名普通食客的口吻写一段简短、生动、有食欲的点评。只输出点评文字本身不要有其他说明。; // 2. 调用GME-Qwen2-VL-2B服务 String generatedComment gmeQwenVLClient.analyzeImageAndGenerateText(imageUrl, prompt); // 3. 对生成结果进行简单后处理如去除多余空格、换行 generatedComment generatedComment.trim(); // 4. 更新数据库记录 dishService.updateDishImageDraft(dishImageId, generatedComment, 1); // 状态更新为1-分析完成 log.info(图片[{}]点评草稿生成成功{}, dishImageId, generatedComment.substring(0, Math.min(50, generatedComment.length())) ...); } catch (Exception e) { log.error(为图片[{}]生成点评草稿失败, dishImageId, e); // 更新状态为分析失败 dishService.updateDishImageStatus(dishImageId, 2); } } }其中GMEQwenVLClient是我们封装的一个HTTP客户端负责与部署好的GME-Qwen2-VL-2B模型API进行通信。你需要根据模型具体的部署方式比如通过API网关或直接调用容器服务来实现这个客户端。4.3 前端评论页预填点评建议前端改动相对较小。在用户进入对某个菜品的评论页面时我们需要在拉取菜品详情的同时也请求一下是否已经生成了点评建议。// 假设在评论页组件加载时 async function loadPageData(dishId) { // 1. 获取菜品基本信息... // 2. 获取该菜品最新的已上传图片用于生成点评的那张 const latestImageRes await api.getDishLatestImage(dishId); if (latestImageRes.data latestImageRes.data.status 1) { // 状态为1表示分析完成且有草稿 const draftText latestImageRes.data.commentDraft; // 3. 将草稿文本预填到评论框 document.getElementById(comment-textarea).value draftText; // 可以加个提示告诉用户这是AI生成的建议可随意修改 showToast(已为您生成点评建议可直接发送或修改~); } }5. 实际效果与场景展示功能上线后我们做了一些内部测试效果挺有意思的。我们上传了一张清蒸鲈鱼的图片。大约几秒钟后取决于异步任务队列的繁忙程度和模型推理速度生成的点评建议是“这条清蒸鲈鱼看起来非常鲜嫩葱丝和辣椒丝点缀得恰到好处蒸出来的汤汁清澈感觉鱼肉入口即化是一道很地道的家常菜。”这个建议已经相当完整了描述了菜品的状态鲜嫩、配料葱丝、辣椒丝、汤汁清澈和口感入口即化甚至还给出了一个“地道家常菜”的评价。用户如果懒得想完全可以直接发送。如果想个性化也可以在此基础上修改比如加上“火候掌握得真好”或者“比我妈做的还香”。另一个例子是一张麻辣香锅的图片。生成的建议是“这一大锅麻辣香锅内容真丰富能看到大虾、午餐肉、藕片、土豆红油汤底看着就让人食欲大开麻辣鲜香的感觉仿佛隔着屏幕都能闻到适合喜欢重口味的朋友。”这段建议抓住了“内容丰富”、“红油汤底”、“麻辣鲜香”和“重口味”这几个关键点非常贴合麻辣香锅的特点而且语言很有煽动性能激发用户的分享欲。当然也不是每次都能完美命中。比如对于一些摆盘极其精致、食材罕见的融合菜模型可能只会中规中矩地描述看到的食材缺少更深入的“美食家”视角。但这完全在我们的预期之内我们的核心目标是“激发灵感”和“降低门槛”而不是替代专业美食评论家。6. 实践经验与优化建议在实际开发和测试过程中我们积累了几点经验也发现了一些可以继续优化的地方。第一提示词Prompt的调优很重要。最开始我们用的提示词是“描述这张图片”结果模型生成的是一段客观描述“一个白色的盘子里装着红色的肉和绿色的蔬菜。” 这完全不是我们想要的点评。后来我们不断调整加上了“以食客口吻”、“生动”、“有食欲”、“只输出点评文字”这些约束才得到了理想的结果。提示词工程是影响生成质量的关键。第二要做好错误处理和降级。网络波动、模型服务暂时不可用、图片本身不清晰等情况都可能发生。我们的异步服务里必须有完善的异常捕获和状态记录。一旦生成失败前端就当作没有建议回归到普通的评论框不影响核心流程。绝对不能因为AI功能挂了导致用户无法评论。第三可以考虑加入人工审核或过滤机制可选。虽然目前测试中模型输出都很正面但为了绝对安全对于一些公开显示的内容可以增加一个简单的关键词过滤或者对于高风险场景如非常规图片可以设置生成的点评先不直接预填而是标记为“待确认”。第四后续可以做的扩展。比如我们可以不只生成一段话而是生成几个不同风格或侧重点的点评短语供用户选择如“侧重口感”、“侧重外观”、“风趣幽默版”。或者根据用户的历史评论偏好对生成的建议进行微调让建议更个性化。7. 总结这次给“黑马点评”项目集成GME-Qwen2-VL-2B实现图片自动生成点评的功能整个过程更像是一次务实的“功能增强”而不是颠覆性的重构。我们通过“异步处理”的设计保证了用户体验的流畅通过选择一款轻量且中文能力强的多模态模型以可控的成本带来了实实在在的价值。从结果来看这个功能确实能有效解决用户“不知道写什么”的痛点为平台增加了有趣且实用的智能交互层。生成的点评建议质量足够作为“初稿”或“灵感来源”能显著提升UGC内容的丰富度和发布意愿。如果你也在做类似的内容社区或带有评论功能的项目不妨考虑加入这样的智能辅助功能。它技术门槛不算高但带来的体验提升是立竿见影的。当然最重要的是想清楚你的核心目标是什么然后选择最适合的技术方案去实现它而不是盲目追求技术的“高大上”。获取更多AI镜像想探索更多AI镜像和应用场景访问 CSDN星图镜像广场提供丰富的预置镜像覆盖大模型推理、图像生成、视频生成、模型微调等多个领域支持一键部署。