2026-09-13-diet-ingredient-balance-design.md 3.5 KB

食材推荐均衡化设计

目标

改进饮食推荐首页的"今日菜篮"食材推荐,从单纯按菌属推荐分排序 → 综合考虑菌属推荐、营养均衡、烹饪便捷性、能量控制,选出 10-12 个食材。

设计

一、综合评分维度

每份食材计算 4 个维度的子分数(均归一化到 0-100),加权合成综合分:

维度 权重 计算方式
菌属推荐分 40% 知识库方向(推荐/避免/中性)+ 推荐指数修正
营养密度分 25% 基于类别的维生素/矿物质基础分 + 宏量营养素质量分
烹饪便捷分 20% 类别映射(快手=90,中等=60,耗时=35)
能量效率分 15% 营养密度/能量比值,能量低且营养高者分高

菌属推荐分:

  • 方向为 recommend → 基础 85 分,叠加推荐指数归一化修正(±10)
  • 方向为 avoid → 基础 15 分
  • 方向为 mixed/无 → 基础 50 分

营养密度分(基于类别启发式):

  • 蔬菜/水果 → 基础 85(维生素A/C/K丰富)
  • 水产品 → 基础 80(omega-3, VD, 碘, 硒)
  • 豆类及豆制品 → 基础 75(叶酸, 铁, 镁)
  • 蛋类 → 基础 70(胆碱, VD, B12)
  • 肉类 → 基础 65(铁, B12, 锌)
  • 乳制品 → 基础 60(钙, VD)
  • 主食 → 基础 45(碳水为主,微量营养素相对低)
  • 干果 → 基础 55(矿物质丰富但热量高)
  • 快餐 → 基础 20(加工食品,营养密度低)
  • 汤 → 基础 35

叠加宏量营养素质量修正(±15):

  • 高蛋白/高纤维 → 正向
  • 高脂肪/高胆固醇 → 负向

烹饪便捷分:

  • 快手(蔬菜、蛋类、水果、汤)→ 90 分
  • 中等(豆类、乳制品、干果、主食)→ 60 分
  • 耗时(水产品、肉类)→ 35 分

能量效率分:

  • energy_efficiency = 营养密度分 / max(能量KJ/1000, 0.5)
  • 归一化到 0-100,能量低且营养高的食材分高

二、组合优化策略(贪心算法)

  1. 计算所有食材的综合分
  2. 按类别分组
  3. 优先选:有菌属推荐标记的食材(bonus +10 分)
  4. 贪心填充:每次选当前未选且综合分最高的食材,但优先确保类别覆盖
  5. 类别配额约束:
    • 蔬菜: 2-3 个
    • 水果: 1-2 个
    • 水产品: 1-2 个
    • 肉类: 1-2 个
    • 蛋类: 1 个
    • 豆类: 1-2 个
    • 主食: 1-2 个
    • 其他类别: 0-1 个
  6. 总目标: 10-12 个,覆盖 5-6 个类别
  7. 换一批: 综合分加入种子扰动(±5分随机偏移),重新排序选择

三、新增数据结构

IngredientRecommendation 新增字段:

private Integer caloriesPer100g;  // 千卡/100g
private Integer cookingLevel;      // 1=快手, 2=中等, 3=耗时
private Integer nutritionScore;    // 营养密度分
private Integer cookingScore;      // 烹饪便捷分
private String balanceReason;      // 推荐理由(如"高蛋白·快手")

四、不涉及变更

  • 前端 API 调用方式不变(仍调 /api/diet/ingredients/suggest 和 /recommend)
  • 前端 refreshIngredients() 方法不变,seed 机制保留
  • 数据库表结构不变
  • 现有 foods 表无 vitamin/mineral 字段,评分完全在内存中计算

五、文件变更清单

文件 变更类型 说明
dto/IngredientRecommendation.java 修改 新增 4 个字段
service/BeijingNutritionService.java 修改 generateIngredientList() 重构为均衡化选择
service/DietIngredientService.java 修改 refreshIngredients() 传递 seed 给新算法