Spaces:
Sleeping
Sleeping
| 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 | |
| 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") | |