内容
🥗 营养计划 — AI 驱动的周餐计划
> 一个使用 Google ADK 和 Gemini 2.5 Flash 构建的多智能体 AI 系统,帮助您规划一周的餐食,分析营养,生成购物清单,查找附近商店,并将完整计划通过电子邮件发送给您。
---
## 🌐 在线演示
- **Web UI:** https://nutri-plan-965093005624.us-central1.run.app/dev-ui/
- **API 端点:** https://nutri-plan-965093005624.us-central1.run.app---
## 📌 问题陈述
**多智能体生产** — 构建一个体 AI 系统,通过与多个数据源交互,帮助用户管理时间表和信息。
通过以下方式解决这个问题:
- 📅 每周餐食 **计划**,包含每餐营养- 🛒 **购物任务清单**,包含成本
- 📍 **商店,基于位置
- **信息传递**,通过电子邮件
---
## 🤖 智能体架构
营养计划使用一个 **5 智能体顺序管道**,由根 LlmAgent 协调,可选的电子邮件在用户请求时触发。
root_agent (LlmAgent协调器)
│
├── (SequentialAgent)
││ ├── 1. profile_agent → 从会话状态中提取用户偏好
│ ├── 2. meal_planner_agent → 创建 7 天的餐食计划,包含内联营养信息
│ ├── 3. recipe_nutrition_agent → 通过 MCP 工具验证营养信息
│ ├── 4. grocery_agent 构建分类购物清单印度卢比成本 └── 5. storefinder_agent → 商店 + 呈现完整输出
│
└── email_agent 在用户请求时通过发送完整计划
### 智能体职责
| 智能体 | 角色 | 输出 |
|---|---|---|
| `profile_agent` | 提取饮食限制、预算、卡路里/宏量营养目标 | JSON 到会话状态 |
| `meal_planner_agent` | 创建 7 天餐食计划,包含每餐营养信息 | 餐到会话状态 |
| `recipe_nutrition_agent` |/Open Food Facts MCP 验证营养估计 | 验证备注 |
| `grocery_agent` | 合并所有配料,估计印度卢比成本,按类别分组 | 购物清单到会话状态 |
| `storefinder_agent` | 通过 Google Maps API 查找附近超市,呈现最终输出 | 完整格式化响应 |
| `email_agent 通过 Gmail SMTP 编译并发送完整计划 | 电子邮件确认## 🛠️ 工具和 MCP 服务器
| 工具 | 类型 | 目的 |
|---|---|---|
| **营养 MCP** | 自定义 Python MCP 服务器 | 从 Open Food Facts 和 USDA FoodData 获取营养数据 |
| **Google Maps API** | FunctionTool(直接 httpx 调用) | 地理编码、附近商店搜索、距离矩阵 |
| **Gmail SMTP** | FunctionTool | 发送格式化 HTML 电子邮件与完整计划 |
### 为什么在 Maps 和 Email 中使用 FunctionTools 而不是 MCP?
Google ADK 安装了一个 `sitecustomize` 钩子,拦截所有 Python 子进程调用,并将它们重定向到 ADK Web 服务器。这使得通过 `subprocess`/`StdioServerParameters` 启动的 MCP 服务器在 Cloud Run 上不可靠。Maps 和 Email 实现为异步 `FunctionTool`,直接在智能中运行 — 不需要子进程。
营养 MCP (`nutrition_mcp_server.py`) 有效,因为它通过指向同一个 Python 进程的 `sys.executable` 调用,而 ADK 正确处理它。
---
## 📁 项目结构
nutri-plan/
├── nutri_plan/
│ ├── init.py # ADK 智能体模块入口│ └── agent.py # 所有智能体、工具、root_agent 定义
├── nutrition_mcp_server.py # 自定义营养数据 MCP 服务器
├── requirements.txt # Python 依赖项
├── Dockerfile # 容器定义(Python 3.13-slim)
├── entrypoint.sh # ADK Web 服务器启动脚本
├── .gitignore # 排除 service-account.json 和凭据
└── README.md # 本文件
---
## 💬 示例交互
**用户:**
3 人,非素食,无海鲜, ₹6000 每周预算,
2000 卡路里/天 每人g 蛋白质/天,布巴瓦尔
**营养计划响应:**
🥗 营 — 您的每周计划
📅 7 天餐食营养
第 1 天 — 星期一
🌅 早餐 — 马萨拉煎蛋(3 个鸡蛋)+ 2 个全麦饼 + 脱脂牛奶
卡路里: 卡路里 | 蛋白质:30 | 碳水化合物:42g | 肪:17g
☀️ 午餐 —肉咖喱(200g)+ 糙米 + 沙拉
卡路里:~700 卡路里 | 蛋白质:65g | 碳水化合物:60g | 脂肪:22g
🌙 晚餐 — 达尔马哈尼 + 2 个饼 + 混合蔬菜萨布齐
卡路里:~810 卡路里 | 蛋白质:34g | 碳水化合物:110g | 脂肪:28g
当天总计 — ~1960 卡路里 | 蛋白质: | 碳水化合物:212g 脂肪:67[... 持续 7]
🛒 购物清单
蔬菜
洋葱 2.5 公100
西红柿 2 公斤
[...]
预计总成本 ₹XXXX
🏪 最近的商店
信赖鲜超市
Galaxy Mall, Patia, 布巴内什瓦尔
4.8 公里 钟
📧 需要我将此计划通过电子邮件您吗?只需分享您的电子邮件地址!
**用户:** `发送到 myemail@gmail.com`
**营养计划:** `✅ 计划!请查看您的收件箱。`
---
## 🚀 技术栈
| 组件 |
|---|---|
|体框架 | Google 开发工具包(AD1.28+ |
| LLM | Gemini 2.5 Flash 通过 Vertex AI |
| 身份验证 | 应用程序据(ADC) 营养数据 | Open Food Facts API + USDA FoodData Central(两者免费,无密钥) |
| 地图和位置 | Google Maps 平台(地理编码、地点、距离矩阵 API) |
| 电子邮件 | Gmail SMTP 与应用程序密码 |
| 容器化 | Docker(Python 3.13-slim) |
| 部署 | Google Cloud Run(us-central1) |
| 容器 | Google 容器(gcr.io| 云项目 | nutri-plan-26 |
---
## ⚙️ 环境变量
| 变量 | 描述 |
|---|---|
| `GOOGLE_MAP_KEY` | Google Maps密钥 |
|MAIL_USER` | 用于发送电子邮件的 Gmail 地址 |
GMAIL_APP_PASSWORD` | 16 位 Gmail 应用程序密码 |
| `GOOGLE_PROJECT` | GCP 项目 ID(`nutri-plan-26`) |
| `_CLOUD_LOCATION` | 区域(`1`) |
|OGLE_GENAI_USE_VERTEXAI` | 设置为 ` 以使用 Vertex AI |
🏃 本地运行 先决条件
- 已安装并认证的 Google Cloud SDK
- 已安装 Docker Google Maps API 密钥 Gmail 应用程序密码
### 步骤
```bash
# 克隆仓库
git clone https://github.com/Rar/nutri-plan.git nutri-plan
# 使用 Google Cloud 认证
gcloud auth application-default login
gcloud config set project nutri-plan-26
# 构建 Docker 镜像
docker build -t nutri-plan-fresh .
# 本地运行 run --rm -p 8080:8080 \
-v/gcloud:/root/.config/gcloud \
-e GOOGLE_MAPS_API_KEY="your_maps_api_key" \
GMAIL_USER=".com" \
-MAIL_APP_PASSWORD="_password" \
nutriresh
# 在浏览器中打开
open http://8080/dev-ui/
```
---
## ☁️ 部署到 Cloud Run
```bash
# 构建并推送到容器注册表
g submit --tag gcr-plan-26/nutri-plan-fresh .
# 获取镜像摘要
gcloud container images describe gcr.io/nutri-plan-26/nutri-plan-fresh \
--format="value(image_summary.digest)" > /tmp/digest.txt
IMAGE_DIGEST=$(cat /tmp/digest.txt)
# 部署
gcloud run deploy nutri-plan \
--image=gcr.io/nutri-plan-26/nutri-plan-fresh@$IMAGE_DIGEST \
--region=us-central1 \
--allow-unauthenticated \
--port=8080 \
--memory=1Gi \
--set-env-vars="GOOGLE_MAPS_API_KEY=...,GMAIL_USER=...,GMAIL_APP_PASSWORD=..."
```
---
## 🔑 关键设计决策
**顺序管道优于并行智能体** — 每个智能通过会话状态 (`output_key`) 馈送智能体。这确保购物清单基于实际餐食计划,最终输出包含所有先前上下文。
**FunctionTools于 MCP for Maps 和 Email** — ADK 在 Cloud Run 上的子进程外部 MCP 服务器不可靠。通过 `httpx` Tools 的直接异步 HTTP 调用是进程本地的,可更快。
**Gemini.5 Flash 通过** — 无需 API 密钥。使用与 GCP 项目帐户绑定的应用程序默认凭据,避免 AI Studio 配额限制。
**单一容器部署** — 所有智能体、营养 MCP 服务器和 ADK Web UI 都从一个 Cloud Run 容器中提供,端口为 8080,保持部署简单和成本效益。
---
## 👤 作者
**Ritam Kar**
- GitHub: [@Ritam-Kar](https://github.com/Ritam-Kar)
- 项目:NutriPlan(多智能体生产力助手赛道)