apts-chatbot-api / diet_api.py
Amrita09's picture
feat : add diet and injury api
f0c74c4
import os
import logging
import json
from fastapi import APIRouter, HTTPException
from fastapi.responses import JSONResponse
from pydantic import BaseModel
import google.generativeai as genai
from dotenv import load_dotenv
import re # Extract JSON safely
# Load environment variables
load_dotenv()
# Retrieve API Key
API_KEY = os.getenv("GEMINI_API_KEY")
if not API_KEY:
raise ValueError("❌ Missing GEMINI_API_KEY. Please set it in the .env file.")
# Configure Gemini AI
genai.configure(api_key=API_KEY)
model = genai.GenerativeModel("gemini-2.0-flash")
# Initialize API Router
router = APIRouter()
# Configure Logging
logging.basicConfig(level=logging.INFO, format="%(asctime)s - %(levelname)s - %(message)s")
# Define Request Model
class PlayerProfile(BaseModel):
sport: str
position: str
age: int
weight: float
height: float
goal: str
# Function to extract JSON from AI response
def extract_json(response_text: str) -> dict:
"""Extract JSON from the AI response safely."""
try:
json_match = re.search(r"\{.*\}", response_text, re.DOTALL)
if json_match:
json_str = json_match.group(0)
return json.loads(json_str)
else:
raise ValueError("No valid JSON found in AI response.")
except Exception as e:
logging.error(f"⚠️ Error parsing AI JSON response: {e}")
return {"error": "AI response did not return valid JSON."}
# AI-based Diet Plan Generation
def generate_diet_plan(player_profile: PlayerProfile) -> dict:
try:
prompt = f"""
Suggest a **daily meal plan** for an athlete based on the following details:
- **Sport**: {player_profile.sport}
- **Position**: {player_profile.position}
- **Age**: {player_profile.age}
- **Weight**: {player_profile.weight} kg
- **Height**: {player_profile.height} cm
- **Training Goal**: {player_profile.goal}
Provide a structured meal plan including:
- **Breakfast**
- **Lunch**
- **Dinner**
- **Snacks**
- **Macronutrient Breakdown (Protein, Carbs, Fats)**
Return the response in this **JSON format**:
```json
{{
"diet_plan": {{
"overview": {{
"sport": "{player_profile.sport}",
"position": "{player_profile.position}",
"age": {player_profile.age},
"weight": {player_profile.weight},
"height": {player_profile.height},
"goal": "{player_profile.goal}"
}},
"meal_plan": {{
"breakfast": ["Example breakfast item 1", "Example breakfast item 2"],
"lunch": ["Example lunch item 1", "Example lunch item 2"],
"snacks": ["Example snack item 1", "Example snack item 2"],
"dinner": ["Example dinner item 1", "Example dinner item 2"]
}},
"macronutrients": {{
"protein": "Example grams of protein",
"carbs": "Example grams of carbs",
"fats": "Example grams of fats"
}}
}}
}}
```
Return only **valid JSON**.
"""
response = model.generate_content(prompt)
if not response or not response.text:
raise ValueError("AI response is empty.")
response_text = response.text.strip()
return extract_json(response_text) # Extract only valid JSON
except Exception as e:
logging.error(f"❌ Error in AI response: {str(e)}")
return {"error": "Failed to generate diet plan."}
# Diet Plan Endpoint
@router.post("/generate_diet/")
async def generate_diet(player_profile: PlayerProfile):
try:
logging.info(f"πŸ“© Received Diet Plan Request: {player_profile}")
diet_plan = generate_diet_plan(player_profile)
return JSONResponse(content=diet_plan, status_code=200)
except Exception as e:
logging.error(f"❌ Error Processing Request: {str(e)}")
raise HTTPException(status_code=500, detail="Internal Server Error")