饮食分析机器人现在支持批量处理多张图片,可以一次性发送多张照片,每张照片会被当作独立的一餐进行分析,并支持批量导入到多维表格。
- 检测到多张图片时自动进入批量处理模式
- 每张图片独立分析,互不干扰
- 所有文字内容会附加到每张图片的分析中
- 每张图片发送独立的分析消息(不会被覆盖)
- 每条消息包含完整的 AI 分析和营养建议
- 每条消息都有独立的"导入到多维表格"按钮
- 可以单独导入某一条记录,也可以批量导入全部
- 每张图片作为独立的一餐记录
- 提取每张图片的时间水印(如果有)
- 分别识别日期、时间、餐次、营养成分等
- 所有图片分析完成后,发送最终汇总消息
- 显示所有记录的明细
- 计算总热量、总蛋白质、总碳水、总脂肪
- 显示平均饮食评分
- 单独导入:每条分析消息都可以单独点击导入
- 批量导入:汇总消息提供一键批量导入所有记录
- 每条记录保存各自的图片
- 显示导入进度和结果统计
步骤:
- 在飞书聊天中,一次性选择多张食物照片
- (可选)添加文字说明,会附加到每张图片
- 发送消息
- 机器人会逐个分析每张图片,每张图片发送一条独立的分析消息
- 每条分析消息都包含完整的营养分析和单独导入按钮
- 所有图片分析完成后,发送最终汇总消息
- 可以选择:
- 单独导入某条记录(点击该分析消息的按钮)
- 批量导入所有记录(点击汇总消息的批量导入按钮)
用户操作:
[上传3张照片]
- 早餐:豆浆油条(图片水印:2026-01-20 07:30)
- 午餐:麻辣香锅(图片水印:2026-01-20 12:30)
- 晚餐:烤鱼(图片水印:2026-01-20 19:00)
附加文字:"1月20日的饮食"
机器人响应 - 消息1(第1张图片的完整分析):
**营养分析** 🥛
从图片左下角的时间水印可以看到,这是 **2026年1月20日 07:30** 拍摄的照片!
豆浆油条是经典的中式早餐组合,让我帮你分析一下营养成分:
• 豆浆(1杯):约 120 kcal
• 油条(2根):约 230 kcal
总热量约:350 kcal
**营养建议** 💡
这是一顿比较传统的早餐,蛋白质和碳水都有...
---
📊 数据摘要
• 餐次:早餐
• 主餐:豆浆油条
• 热量:350 kcal
• 蛋白质:15 g
• 碳水:45 g
• 脂肪:12 g
• 评分:7/10
[按钮: 📥 导入到多维表格]机器人响应 - 消息2(第2张图片的完整分析):
**营养分析** 🍜
从图片左下角的时间水印可以看到,这是 **2026年1月20日 12:30** 拍摄的照片!
哇!麻辣香锅看起来超级诱人呀!让我帮你分析一下这顿午餐:
• 麻辣香锅(肉类+蔬菜):约 1200 kcal
**营养建议** 💡
这是一顿热量较高的餐食,但营养比较均衡...
---
📊 数据摘要
• 餐次:午餐
• 主餐:麻辣香锅
• 热量:1200 kcal
• 蛋白质:45 g
• 碳水:60 g
• 脂肪:55 g
• 评分:7/10
[按钮: 📥 导入到多维表格]机器人响应 - 消息3(第3张图片的完整分析):
**营养分析** 🐟
从图片左下角的时间水印可以看到,这是 **2026年1月20日 19:00** 拍摄的照片!
烤鱼是一道营养丰富的菜肴...
---
📊 数据摘要
• 餐次:晚餐
• 主餐:烤鱼
• 热量:800 kcal
• 蛋白质:50 g
• 碳水:35 g
• 脂肪:28 g
• 评分:8/10
[按钮: 📥 导入到多维表格]机器人响应 - 消息4(最终汇总):
📊 批量分析完成
成功分析 3 条饮食记录!
📝 记录明细
1. 2026-01-20 07:30 - 早餐:豆浆油条 (350 kcal)
2. 2026-01-20 12:30 - 午餐:麻辣香锅 (1200 kcal)
3. 2026-01-20 19:00 - 晚餐:烤鱼 (800 kcal)
🔢 营养总计
• 总热量:2350 kcal
• 总蛋白质:110 g
• 总碳水:140 g
• 总脂肪:95 g
• 平均评分:7.3/10
[按钮: 📥 批量导入 3 条记录到多维表格]操作选择:
- 选项1:点击消息1、2、3各自的按钮,单独导入每条记录
- 选项2:点击消息4(汇总)的批量导入按钮,一次性导入全部3条记录
用户操作:
[上传5张照片]
- 周一早餐
- 周一午餐
- 周一晚餐
- 周二早餐
- 周二午餐
机器人响应:
📊 批量分析完成
成功分析 5 条饮食记录!
📝 记录明细
1. 2026-01-20 07:45 - 早餐:鸡蛋三明治 (420 kcal)
2. 2026-01-20 12:15 - 午餐:宫保鸡丁 (950 kcal)
3. 2026-01-20 19:30 - 晚餐:水煮鱼 (1100 kcal)
4. 2026-01-21 08:00 - 早餐:牛奶麦片 (380 kcal)
5. 2026-01-21 12:45 - 午餐:烧鹅饭 (880 kcal)
🔢 营养总计
• 总热量:3730 kcal
• 总蛋白质:165 g
• 总碳水:380 g
• 总脂肪:145 g
• 平均评分:7.0/10
[按钮: 📥 批量导入 5 条记录到多维表格]在 bots/food_analyzer/bot.py 的 process_messages() 方法中:
def process_messages(self, chat_id: str, parts: List[MessagePart], status_msg_id: Optional[str]) -> str:
# 分离图片和文字
images = [part for part in parts if part.kind == "image" and part.image_key]
texts = [part for part in parts if part.kind == "text" and part.text]
combined_text = " ".join([t.text for t in texts]) if texts else ""
# 根据图片数量路由到不同处理器
if not images or len(images) == 1:
return self._process_single_meal(chat_id, parts, status_msg_id, combined_text)
else:
return self._process_multiple_meals(chat_id, images, combined_text, status_msg_id)def _process_multiple_meals(self, chat_id, images, combined_text, status_msg_id) -> str:
all_meal_data = []
# 逐个处理每张图片
for idx, image_part in enumerate(images, start=1):
# 构建单张图片的消息(图片 + 文字)
single_parts = [image_part]
if combined_text:
single_parts.append(MessagePart(kind="text", text=combined_text))
# 调用 AI 分析
messages = self._build_ai_messages(single_parts)
result = self._call_ai_streaming(chat_id, messages, status_msg_id)
# 提取并保存数据
meal_data = self._extract_json_data(result)
if meal_data:
meal_data["user_comment"] = combined_text
meal_data["image_key"] = image_part.image_key
meal_data["image_message_id"] = image_part.message_id
all_meal_data.append(meal_data)
# 生成汇总和交互式卡片
summary_text = self._build_batch_summary(all_meal_data)
card_content = self._build_batch_interactive_card(summary_text, all_meal_data)
return summary_text在 main.py 的 handle_card_action() 方法中:
def async_save():
# 检查是否为批量导入
is_batch = isinstance(meal_data, dict) and meal_data.get("batch") == True
if is_batch:
# 批量导入模式
meals = meal_data.get("meals", [])
success_count = 0
fail_count = 0
for idx, single_meal in enumerate(meals, start=1):
if self.bot._save_to_bitable(single_meal):
success_count += 1
else:
fail_count += 1
# 发送批量结果通知
result_msg = f"✅ **批量导入成功!**\n\n已成功保存 {success_count} 条饮食记录到多维表格"单条记录卡片按钮:
{
"value": {
"date": "2026-01-20",
"time": "12:30",
"meal_type": "午餐",
...
}
}批量记录卡片按钮:
{
"value": {
"batch": true,
"meals": [
{"date": "2026-01-20", "time": "07:30", ...},
{"date": "2026-01-20", "time": "12:30", ...},
{"date": "2026-01-20", "time": "19:00", ...}
]
}
}| 特性 | 单图模式 | 批量模式 |
|---|---|---|
| 触发条件 | 0或1张图片 | 2张及以上图片 |
| 分析方式 | 一次性分析 | 逐个独立分析 |
| 结果展示 | 详细分析+数据摘要 | 批量汇总+营养总计 |
| 导入按钮 | "📥 导入到多维表格" | "📥 批量导入 N 条记录到多维表格" |
| 保存方式 | 单条记录保存 | 循环保存多条记录 |
| 图片保存 | 保存该图片 | 每条记录保存各自的图片 |
- 每张图片需要独立调用 AI 进行分析
- AI 调用为串行处理(逐个分析,不是并行)
- 处理时间 = 单张图片处理时间 × 图片数量
- 建议一次不超过 10 张图片
- 飞书消息中可能对图片数量有限制
- 过多图片可能导致处理时间较长
- 批量保存失败时会显示部分成功的结果
批量处理时,状态消息会实时更新:
🔍 批量分析模式
检测到 3 张图片,正在逐个分析...
↓
🔍 正在分析第 1/3 张图片...
识别食物中...
↓
📝 正在分析中...
[第1张的分析内容]
正在生成中...
↓
🔍 正在分析第 2/3 张图片...
↓
...
↓
📊 批量分析完成
[汇总结果]
- 批量模式下,每张图片的日期和时间独立提取
- 优先使用各自图片的时间水印
- 如果用户添加了文字说明(如"1月20日的饮食"),会应用到所有图片
- 批量模式下,用户发送的文字会附加到每条记录的"附言"字段
- 所有记录共享相同的附言内容
- 每条记录保存各自对应的图片
- 图片上传到飞书云存储后获得 file_token
- 多维表格的"图片"字段保存对应的 file_token
- 如果某张图片分析失败,不影响其他图片
- 汇总中只包含成功分析的记录
- 日志中会记录失败原因
- 批量导入时,每条记录独立保存
- 显示成功和失败的数量
- 例如:"成功:2 条,失败:1 条"
- 如果所有图片都无法分析:显示"批量分析失败"
- 如果批量导入全部失败:显示具体错误信息
A:
- 单图模式(0或1张图片):显示详细的营养分析和建议
- 批量模式(2张及以上):显示汇总数据和记录明细,更注重整体统计
A:
- 用户发送的所有文字内容会合并
- 合并后的文字会附加到每一条记录的"附言"字段
- 例如:文字"今天吃得不错"会保存到所有3条记录中
A:
- 每张图片的时间水印独立提取
- 第1张图片:使用第1张的水印时间
- 第2张图片:使用第2张的水印时间
- 各自保存到对应的日期和时间
A:
- 系统会继续保存其他记录
- 最后显示成功和失败的统计
- 可以查看日志了解失败原因
- 可以手动重新导入失败的记录
A:
- 技术上没有硬性限制
- 但考虑到处理时间,建议一次不超过 10 张
- 每张图片需要调用 AI 分析,处理时间会随图片数量增加
A:
- 批量模式更注重汇总统计,不会显示每条记录的详细分析
- 如果需要详细分析,可以单独发送每张图片
- 或者在批量导入后,在多维表格中查看各条记录的详细数据
A:
- 会的!每条记录都会保存各自对应的图片
- 图片会上传到飞书云存储
- 多维表格的"图片"字段会显示对应的食物照片
用户发送多张图片
↓
process_messages() 检测到多张图片
↓
调用 _process_multiple_meals()
↓
循环处理每张图片:
- 更新状态:"正在分析第 N/M 张图片..."
- 构建消息:图片 + 文字
- 调用 AI 分析
- 提取 JSON 数据
- 添加图片信息和附言
- 保存到 all_meal_data 数组
↓
调用 _build_batch_summary() 生成汇总
↓
调用 _build_batch_interactive_card() 生成交互卡片
↓
更新消息显示汇总和按钮
↓
用户点击批量导入按钮
↓
handle_card_action() 检测到 batch=true
↓
循环保存每条记录:
- 调用 _save_to_bitable(single_meal)
- 统计成功和失败数量
↓
发送批量导入结果通知
- 消息路由:
bots/food_analyzer/bot.py:42-72(process_messages) - 批量处理:
bots/food_analyzer/bot.py:129-236(_process_multiple_meals) - 批量汇总:
bots/food_analyzer/bot.py:238-281(_build_batch_summary) - 批量卡片:
bots/food_analyzer/bot.py:283-324(_build_batch_interactive_card) - 批量保存:
main.py:165-231(handle_card_action的async_save内部逻辑)
批量处理时的日志示例:
[饮食分析助手] 开始分析饮食,消息片段数: 5
[饮食分析助手] 检测到 3 张图片,2 条文字
[饮食分析助手] 批量处理模式:3 张图片
[饮食分析助手] 处理第 1/3 张图片
[饮食分析助手] 处理第 2/3 张图片
[饮食分析助手] 处理第 3/张图片
[饮食分析助手] 批量分析完成,成功: 3/3
[饮食分析助手] 批量导入模式,共 3 条记录
[饮食分析助手] 保存第 1/3 条记录...
[饮食分析助手] 保存第 2/3 条记录...
[饮食分析助手] 保存第 3/3 条记录...
[饮食分析助手] 批量导入完成: 成功 3/3
批量处理功能不需要额外配置,使用现有的配置即可:
# config/food_analyzer/config.yaml
bitable:
enabled: true
app_token: "你的多维表格 app_token"
table_id: "你的数据表 table_id"
fields:
date: "日期" # 必须配置
time: "时间" # 必须配置
image: "图片" # 必须配置(附件字段)
# ... 其他字段批量图片处理功能让你可以:
- ✅ 一次性发送多张食物照片
- ✅ 每张照片独立分析为一餐记录
- ✅ 自动提取各自的日期和时间
- ✅ 查看所有记录的汇总统计
- ✅ 一键批量导入到多维表格
- ✅ 每条记录保存各自的图片
- ✅ 高效补录多天的饮食数据
特别适合:
- 补录过去几天的饮食
- 快速记录一整天的饮食
- 整理相册中的食物照片