Spaces:
Sleeping
Sleeping
| import gradio as gr | |
| import json | |
| import os | |
| import pandas as pd | |
| import re | |
| import glob | |
| from typing import Dict, List, Any | |
| from main3 import run_rag_tool_router, execute_diet_tool | |
| from diet_tool import generate_diet_plan, get_diet_recommendations, calculate_nutrition_info | |
| # Ensure outputs directory exists | |
| os.makedirs("outputs", exist_ok=True) | |
| # Global chat history | |
| chat_history = [] | |
| def format_json_to_table(json_data: Any, title: str = "") -> str: | |
| """Convert JSON data to a formatted table string""" | |
| if not json_data: | |
| return "" | |
| try: | |
| if isinstance(json_data, str): | |
| json_data = json.loads(json_data) | |
| if isinstance(json_data, dict): | |
| return format_dict_to_table(json_data, title) | |
| elif isinstance(json_data, list): | |
| return format_list_to_table(json_data, title) | |
| else: | |
| return str(json_data) | |
| except: | |
| return str(json_data) | |
| def format_dict_to_table(data: dict, title: str = "") -> str: | |
| """Format dictionary as a table""" | |
| if not data: | |
| return "" | |
| result = f"## {title}\n\n" if title else "" | |
| # Check if it's a simple key-value dict | |
| if all(not isinstance(v, (dict, list)) for v in data.values()): | |
| result += "| Key | Value |\n" | |
| result += "|-----|-------|\n" | |
| for key, value in data.items(): | |
| result += f"| **{key}** | {value} |\n" | |
| else: | |
| # Complex nested structure | |
| for key, value in data.items(): | |
| if isinstance(value, dict): | |
| result += f"### {key}\n" | |
| result += format_dict_to_table(value) | |
| elif isinstance(value, list): | |
| result += f"### {key}\n" | |
| result += format_list_to_table(value) | |
| else: | |
| result += f"**{key}**: {value}\n" | |
| return result | |
| def format_list_to_table(data: list, title: str = "") -> str: | |
| """Format list as a table""" | |
| if not data: | |
| return "" | |
| result = f"## {title}\n\n" if title else "" | |
| if not data: | |
| return result | |
| # Check if all items are dictionaries with similar keys | |
| if all(isinstance(item, dict) for item in data): | |
| # Get all unique keys | |
| all_keys = set() | |
| for item in data: | |
| all_keys.update(item.keys()) | |
| if all_keys: | |
| # Create table header | |
| result += "| " + " | ".join(all_keys) + " |\n" | |
| result += "|" + "|".join(["---"] * len(all_keys)) + "|\n" | |
| # Add rows | |
| for item in data: | |
| row = [] | |
| for key in all_keys: | |
| value = item.get(key, "") | |
| if isinstance(value, (dict, list)): | |
| value = json.dumps(value, ensure_ascii=False)[:50] + "..." | |
| row.append(str(value)) | |
| result += "| " + " | ".join(row) + " |\n" | |
| else: | |
| result += "Empty list\n" | |
| else: | |
| # Simple list | |
| for i, item in enumerate(data): | |
| result += f"{i+1}. {item}\n" | |
| return result | |
| def format_diet_plan_result(result: dict) -> str: | |
| """Format diet plan result specifically""" | |
| if not result or "error" in result: | |
| return f"❌ Error: {result.get('error', 'Unknown error')}" | |
| formatted = "## 🍽️ Diet Plan\n\n" | |
| if "plan_type" in result: | |
| formatted += f"**Plan Type**: {result['plan_type']}\n\n" | |
| if "plan" in result: | |
| plan = result["plan"] | |
| # Daily totals | |
| if "daily_totals" in plan: | |
| totals = plan["daily_totals"] | |
| formatted += "### 📊 Daily Nutrition Summary\n\n" | |
| formatted += "| Nutrient | Amount |\n" | |
| formatted += "|----------|--------|\n" | |
| formatted += f"| **Calories** | {totals.get('calories', 0)} kcal |\n" | |
| formatted += f"| **Protein** | {totals.get('protein', 0)} g |\n" | |
| formatted += f"| **Carbs** | {totals.get('carbs', 0)} g |\n" | |
| formatted += f"| **Fat** | {totals.get('fat', 0)} g |\n" | |
| formatted += f"| **Fiber** | {totals.get('fiber', 0)} g |\n\n" | |
| # Meals | |
| if "meals" in plan: | |
| formatted += "### 🍽️ Meals\n\n" | |
| for meal in plan["meals"]: | |
| formatted += f"#### {meal.get('meal_name', 'Meal')} ({meal.get('time_range', '')})\n\n" | |
| # Meal nutrition | |
| if "nutrition" in meal: | |
| nutrition = meal["nutrition"] | |
| formatted += "**Nutrition**: " | |
| formatted += f"{nutrition.get('calories', 0)} kcal, " | |
| formatted += f"{nutrition.get('protein', 0)}g protein, " | |
| formatted += f"{nutrition.get('carbs', 0)}g carbs, " | |
| formatted += f"{nutrition.get('fat', 0)}g fat\n\n" | |
| # Foods | |
| if "foods" in meal: | |
| formatted += "**Foods**:\n" | |
| for food in meal["foods"]: | |
| formatted += f"- **{food.get('name', 'Unknown')}** " | |
| formatted += f"({food.get('portion_grams', 0)}g) - " | |
| formatted += f"{food.get('calories', 0)} kcal\n" | |
| formatted += "\n" | |
| elif "plans" in result: | |
| # Weekly plan | |
| plans = result["plans"] | |
| formatted += f"### 📅 Weekly Plan ({len(plans)} days)\n\n" | |
| for i, plan in enumerate(plans): # Show all days | |
| formatted += f"#### Day {i+1} - {plan.get('date', '')}\n" | |
| if "daily_totals" in plan: | |
| totals = plan["daily_totals"] | |
| formatted += f"**Total**: {totals.get('calories', 0)} kcal, " | |
| formatted += f"{totals.get('protein', 0)}g protein\n\n" | |
| return formatted | |
| def format_recommendations_result(result: dict) -> str: | |
| """Format recommendations result specifically""" | |
| if not result or "error" in result: | |
| return f"❌ Error: {result.get('error', 'Unknown error')}" | |
| formatted = "## 📊 Diet Recommendations\n\n" | |
| # Basic metrics | |
| if "bmr" in result: | |
| formatted += f"**BMR (Basal Metabolic Rate)**: {result['bmr']} kcal/day\n" | |
| if "tdee" in result: | |
| formatted += f"**TDEE (Total Daily Energy Expenditure)**: {result['tdee']} kcal/day\n" | |
| if "target_calories" in result: | |
| formatted += f"**Target Calories**: {result['target_calories']} kcal/day\n\n" | |
| # Macro ratios | |
| if "macro_ratios" in result: | |
| ratios = result["macro_ratios"] | |
| formatted += "### 🎯 Macro Ratios\n\n" | |
| formatted += "| Macronutrient | Percentage |\n" | |
| formatted += "|---------------|------------|\n" | |
| for macro, ratio in ratios.items(): | |
| formatted += f"| **{macro.title()}** | {ratio} |\n" | |
| formatted += "\n" | |
| # Macro grams | |
| if "macro_grams" in result: | |
| grams = result["macro_grams"] | |
| formatted += "### ⚖️ Daily Macro Targets (grams)\n\n" | |
| formatted += "| Macronutrient | Grams |\n" | |
| formatted += "|---------------|-------|\n" | |
| for macro, grams_val in grams.items(): | |
| formatted += f"| **{macro.title()}** | {grams_val} g |\n" | |
| formatted += "\n" | |
| # Recommendations | |
| if "recommendations" in result: | |
| recs = result["recommendations"] | |
| formatted += "### 💡 Recommendations\n\n" | |
| for key, value in recs.items(): | |
| formatted += f"**{key.replace('_', ' ').title()}**: {value}\n" | |
| return formatted | |
| def format_nutrition_result(result: dict) -> str: | |
| """Format nutrition calculation result specifically""" | |
| if not result or "error" in result: | |
| return f"❌ Error: {result.get('error', 'Unknown error')}" | |
| formatted = "## 🧮 Nutrition Information\n\n" | |
| if "food_name" in result: | |
| formatted += f"**Food**: {result['food_name']}\n" | |
| if "portion_grams" in result: | |
| formatted += f"**Portion**: {result['portion_grams']} grams\n\n" | |
| # Basic nutrition | |
| formatted += "### 📊 Nutritional Values\n\n" | |
| formatted += "| Nutrient | Amount |\n" | |
| formatted += "|----------|--------|\n" | |
| nutrients = ["calories", "protein", "carbs", "fat", "fiber"] | |
| for nutrient in nutrients: | |
| if nutrient in result: | |
| unit = "kcal" if nutrient == "calories" else "g" | |
| formatted += f"| **{nutrient.title()}** | {result[nutrient]} {unit} |\n" | |
| # Vitamins and minerals | |
| if "vitamins" in result and result["vitamins"]: | |
| formatted += "\n### 🥕 Vitamins\n\n" | |
| if isinstance(result["vitamins"], list): | |
| for vitamin in result["vitamins"]: | |
| formatted += f"- {vitamin}\n" | |
| else: | |
| formatted += str(result["vitamins"]) | |
| if "minerals" in result and result["minerals"]: | |
| formatted += "\n### ⚡ Minerals\n\n" | |
| if isinstance(result["minerals"], list): | |
| for mineral in result["minerals"]: | |
| formatted += f"- {mineral}\n" | |
| else: | |
| formatted += str(result["minerals"]) | |
| return formatted | |
| def load_latest_json_output() -> str: | |
| """Load and format the latest JSON output file""" | |
| outputs_dir = "outputs" | |
| if not os.path.exists(outputs_dir): | |
| return "❌ No outputs directory found" | |
| # Get all JSON files in outputs directory | |
| json_files = glob.glob(os.path.join(outputs_dir, "*.json")) | |
| if not json_files: | |
| return "❌ No JSON files found in outputs directory" | |
| # Sort by modification time and get the latest | |
| latest_file = max(json_files, key=os.path.getmtime) | |
| try: | |
| with open(latest_file, 'r', encoding='utf-8') as f: | |
| data = json.load(f) | |
| # Extract filename for title | |
| filename = os.path.basename(latest_file) | |
| # Format based on file type | |
| if "diet_plan" in filename: | |
| if "weekly" in filename: | |
| return format_weekly_diet_plan(data, filename) | |
| else: | |
| return format_daily_diet_plan(data, filename) | |
| elif "recommendations" in filename: | |
| return format_recommendations_result(data, filename) | |
| elif "nutrition" in filename: | |
| return format_nutrition_result(data, filename) | |
| else: | |
| return format_json_data_to_table(data, f"Latest Output: {filename}") | |
| except Exception as e: | |
| return f"❌ Error reading {latest_file}: {str(e)}" | |
| def format_weekly_diet_plan(data: dict, filename: str) -> str: | |
| """Format weekly diet plan from JSON file""" | |
| if not data or "result" not in data: | |
| return f"❌ Invalid data in {filename}" | |
| result = data["result"] | |
| if "plans" not in result: | |
| return f"❌ No plans found in {filename}" | |
| plans = result["plans"] | |
| formatted = f"## 📅 Weekly Diet Plan ({len(plans)} days)\n\n" | |
| formatted += f"**File**: {filename}\n\n" | |
| # Summary table for all days | |
| formatted += "### 📊 Weekly Summary\n\n" | |
| formatted += "| Day | Date | Calories | Protein | Carbs | Fat | Fiber |\n" | |
| formatted += "|-----|------|----------|---------|-------|-----|-------|\n" | |
| for i, plan in enumerate(plans): | |
| totals = plan.get("daily_totals", {}) | |
| date = plan.get("date", f"Day {i+1}") | |
| formatted += f"| {i+1} | {date} | {totals.get('calories', 0)} | {totals.get('protein', 0)}g | {totals.get('carbs', 0)}g | {totals.get('fat', 0)}g | {totals.get('fiber', 0)}g |\n" | |
| # Detailed view for all days | |
| formatted += "\n### 🍽️ Detailed Meals (All Days)\n\n" | |
| for i, plan in enumerate(plans): | |
| date = plan.get("date", f"Day {i+1}") | |
| formatted += f"#### Day {i+1} - {date}\n\n" | |
| meals = plan.get("meals", []) | |
| for meal in meals: | |
| meal_name = meal.get("meal_name", "Meal") | |
| time_range = meal.get("time_range", "") | |
| nutrition = meal.get("nutrition", {}) | |
| formatted += f"**{meal_name}** ({time_range})\n" | |
| formatted += f"- Calories: {nutrition.get('calories', 0)} | Protein: {nutrition.get('protein', 0)}g | Carbs: {nutrition.get('carbs', 0)}g | Fat: {nutrition.get('fat', 0)}g\n" | |
| # Foods | |
| foods = meal.get("foods", []) | |
| if foods: | |
| formatted += " - Foods: " | |
| food_names = [f.get("name", "Unknown") for f in foods[:3]] # Show first 3 foods | |
| formatted += ", ".join(food_names) | |
| if len(foods) > 3: | |
| formatted += f" (+{len(foods)-3} more)" | |
| formatted += "\n" | |
| formatted += "\n" | |
| return formatted | |
| def format_daily_diet_plan(data: dict, filename: str) -> str: | |
| """Format daily diet plan from JSON file""" | |
| if not data or "result" not in data: | |
| return f"❌ Invalid data in {filename}" | |
| result = data["result"] | |
| if "plan" not in result: | |
| return f"❌ No plan found in {filename}" | |
| plan = result["plan"] | |
| formatted = f"## 🍽️ Daily Diet Plan\n\n" | |
| formatted += f"**File**: {filename}\n\n" | |
| # Daily totals | |
| if "daily_totals" in plan: | |
| totals = plan["daily_totals"] | |
| formatted += "### 📊 Daily Nutrition Summary\n\n" | |
| formatted += "| Nutrient | Amount |\n" | |
| formatted += "|----------|--------|\n" | |
| formatted += f"| **Calories** | {totals.get('calories', 0)} kcal |\n" | |
| formatted += f"| **Protein** | {totals.get('protein', 0)} g |\n" | |
| formatted += f"| **Carbs** | {totals.get('carbs', 0)} g |\n" | |
| formatted += f"| **Fat** | {totals.get('fat', 0)} g |\n" | |
| formatted += f"| **Fiber** | {totals.get('fiber', 0)} g |\n\n" | |
| # Meals | |
| if "meals" in plan: | |
| formatted += "### 🍽️ Meals\n\n" | |
| for meal in plan["meals"]: | |
| meal_name = meal.get("meal_name", "Meal") | |
| time_range = meal.get("time_range", "") | |
| nutrition = meal.get("nutrition", {}) | |
| formatted += f"#### {meal_name} ({time_range})\n\n" | |
| formatted += f"**Nutrition**: {nutrition.get('calories', 0)} kcal, {nutrition.get('protein', 0)}g protein, {nutrition.get('carbs', 0)}g carbs, {nutrition.get('fat', 0)}g fat\n\n" | |
| # Foods | |
| foods = meal.get("foods", []) | |
| if foods: | |
| formatted += "**Foods**:\n" | |
| for food in foods: | |
| name = food.get("name", "Unknown") | |
| portion = food.get("portion_grams", 0) | |
| calories = food.get("calories", 0) | |
| formatted += f"- **{name}** ({portion}g) - {calories} kcal\n" | |
| formatted += "\n" | |
| return formatted | |
| def list_all_json_outputs() -> str: | |
| """List all JSON output files with their details""" | |
| outputs_dir = "outputs" | |
| if not os.path.exists(outputs_dir): | |
| return "❌ No outputs directory found" | |
| json_files = glob.glob(os.path.join(outputs_dir, "*.json")) | |
| if not json_files: | |
| return "❌ No JSON files found in outputs directory" | |
| # Sort by modification time (newest first) | |
| json_files.sort(key=os.path.getmtime, reverse=True) | |
| formatted = "## 📁 Available JSON Outputs\n\n" | |
| formatted += "| File | Type | Size | Modified |\n" | |
| formatted += "|------|------|------|----------|\n" | |
| for file_path in json_files: | |
| filename = os.path.basename(file_path) | |
| file_type = "Unknown" | |
| if "diet_plan_weekly" in filename: | |
| file_type = "Weekly Diet Plan" | |
| elif "diet_plan_daily" in filename: | |
| file_type = "Daily Diet Plan" | |
| elif "recommendations" in filename: | |
| file_type = "Recommendations" | |
| elif "nutrition" in filename: | |
| file_type = "Nutrition Info" | |
| file_size = os.path.getsize(file_path) | |
| mod_time = os.path.getmtime(file_path) | |
| mod_date = pd.Timestamp.fromtimestamp(mod_time).strftime("%Y-%m-%d %H:%M") | |
| formatted += f"| {filename} | {file_type} | {file_size:,} bytes | {mod_date} |\n" | |
| return formatted | |
| def extract_and_format_json_in_text(text: str) -> str: | |
| """Extract JSON objects from text and format them as tables""" | |
| if not text: | |
| return text | |
| formatted_text = text | |
| # First, try to find JSON in code blocks | |
| code_block_pattern = r'```(?:json)?\s*(\{.*?\})\s*```' | |
| matches = list(re.finditer(code_block_pattern, formatted_text, re.DOTALL | re.IGNORECASE)) | |
| for match in reversed(matches): | |
| json_str = match.group(1).strip() | |
| try: | |
| json_data = json.loads(json_str) | |
| table = format_json_data_to_table(json_data) | |
| formatted_text = formatted_text[:match.start()] + table + formatted_text[match.end():] | |
| except: | |
| continue | |
| # Then, try to find standalone JSON objects | |
| # Look for patterns that start with { and end with } | |
| json_pattern = r'\{[^{}]*(?:\{[^{}]*\}[^{}]*)*\}' | |
| matches = list(re.finditer(json_pattern, formatted_text, re.DOTALL)) | |
| for match in reversed(matches): | |
| json_str = match.group(0).strip() | |
| # Skip if it's already been processed or is too short | |
| if len(json_str) < 10 or '|' in json_str: | |
| continue | |
| try: | |
| json_data = json.loads(json_str) | |
| # Only format if it looks like structured data | |
| if isinstance(json_data, (dict, list)) and len(str(json_data)) > 20: | |
| table = format_json_data_to_table(json_data) | |
| formatted_text = formatted_text[:match.start()] + table + formatted_text[match.end():] | |
| except: | |
| continue | |
| return formatted_text | |
| def format_json_data_to_table(json_data: Any) -> str: | |
| """Format JSON data to a table string""" | |
| if isinstance(json_data, dict): | |
| return format_dict_to_table(json_data, "Data") | |
| elif isinstance(json_data, list): | |
| return format_list_to_table(json_data, "Data") | |
| else: | |
| return str(json_data) | |
| def process_user_input(user_input: str, history: List) -> tuple: | |
| """Process user input through RAG system""" | |
| global chat_history | |
| if not user_input.strip(): | |
| return history, "" | |
| # Convert Gradio history format to our format | |
| rag_history = [] | |
| for msg in history: | |
| if isinstance(msg, dict): | |
| rag_history.append(msg) | |
| else: | |
| # Handle old format | |
| user_msg, bot_msg = msg | |
| rag_history.append({"role": "user", "content": user_msg}) | |
| rag_history.append({"role": "assistant", "content": bot_msg}) | |
| # Process through RAG system | |
| result = run_rag_tool_router(user_input, rag_history) | |
| # Update our chat history | |
| chat_history.append({"role": "user", "content": user_input}) | |
| # Handle different response types | |
| if isinstance(result, dict) and "final" in result: | |
| response = result["final"] | |
| # Format any JSON in the response | |
| formatted_response = extract_and_format_json_in_text(response) | |
| chat_history.append({"role": "assistant", "content": formatted_response}) | |
| history.append({"role": "user", "content": user_input}) | |
| history.append({"role": "assistant", "content": formatted_response}) | |
| return history, "" | |
| elif isinstance(result, dict) and "action" in result: | |
| action = result["action"] | |
| args = result.get("args", {}) | |
| # Show the action being taken | |
| action_response = f"**Executing**: {action}\n\n**Arguments**:\n```json\n{json.dumps(args, indent=2)}\n```" | |
| # Execute diet tools | |
| if action in ["generate_diet_plan", "get_diet_recommendations", "calculate_nutrition_info", "expand_diet_database"]: | |
| diet_result = execute_diet_tool(action, args) | |
| if diet_result.get("success"): | |
| final_response = f"✅ **{diet_result.get('message', 'Operation completed successfully')}**\n\n" | |
| if "result" in diet_result: | |
| # Format the result based on action type | |
| if action == "generate_diet_plan": | |
| formatted_result = format_diet_plan_result(diet_result['result']) | |
| elif action == "get_diet_recommendations": | |
| formatted_result = format_recommendations_result(diet_result['result']) | |
| elif action == "calculate_nutrition_info": | |
| formatted_result = format_nutrition_result(diet_result['result']) | |
| else: | |
| formatted_result = format_json_to_table(diet_result['result'], "Result") | |
| final_response += formatted_result | |
| else: | |
| final_response = f"❌ **Error**: {diet_result.get('error', 'Unknown error occurred')}" | |
| # Add to history | |
| history.append({"role": "user", "content": user_input}) | |
| history.append({"role": "assistant", "content": action_response + "\n\n" + final_response}) | |
| chat_history.append({"role": "assistant", "content": final_response}) | |
| else: | |
| # For other tools, show placeholder | |
| final_response = "🔄 This tool is not yet implemented in the web interface." | |
| history.append({"role": "user", "content": user_input}) | |
| history.append({"role": "assistant", "content": action_response + "\n\n" + final_response}) | |
| chat_history.append({"role": "assistant", "content": final_response}) | |
| return history, "" | |
| else: | |
| # Handle errors or other responses | |
| error_response = f"❌ **Error**: {json.dumps(result, indent=2, ensure_ascii=False)}" | |
| chat_history.append({"role": "assistant", "content": error_response}) | |
| history.append({"role": "user", "content": user_input}) | |
| history.append({"role": "assistant", "content": error_response}) | |
| return history, "" | |
| def create_diet_plan_interface(age: int, sex: str, height_cm: float, weight_kg: float, | |
| activity_level: str, goal: str, plan_type: str) -> str: | |
| """Create diet plan using the interface""" | |
| user_profile = { | |
| "age": age, | |
| "sex": sex, | |
| "height_cm": height_cm, | |
| "weight_kg": weight_kg, | |
| "activity_level": activity_level, | |
| "goal": goal, | |
| "dietary_restrictions": [], | |
| "allergies": [], | |
| "preferences": [] | |
| } | |
| try: | |
| result = generate_diet_plan(user_profile, plan_type) | |
| return format_diet_plan_result(result) | |
| except Exception as e: | |
| return f"❌ Error: {str(e)}" | |
| def get_recommendations_interface(age: int, sex: str, height_cm: float, weight_kg: float, | |
| activity_level: str, goal: str) -> str: | |
| """Get diet recommendations using the interface""" | |
| user_profile = { | |
| "age": age, | |
| "sex": sex, | |
| "height_cm": height_cm, | |
| "weight_kg": weight_kg, | |
| "activity_level": activity_level, | |
| "goal": goal, | |
| "dietary_restrictions": [], | |
| "allergies": [], | |
| "preferences": [] | |
| } | |
| try: | |
| result = get_diet_recommendations(user_profile) | |
| return format_recommendations_result(result) | |
| except Exception as e: | |
| return f"❌ Error: {str(e)}" | |
| def calculate_nutrition_interface(food_name: str, portion_grams: float) -> str: | |
| """Calculate nutrition info using the interface""" | |
| try: | |
| result = calculate_nutrition_info(food_name, portion_grams) | |
| return format_nutrition_result(result) | |
| except Exception as e: | |
| return f"❌ Error: {str(e)}" | |
| # Create Gradio interface | |
| with gr.Blocks(title="RAG Diet Assistant") as app: | |
| gr.Markdown("# 🍽️ RAG Diet Assistant") | |
| gr.Markdown("Your intelligent nutrition planning assistant powered by RAG (Retrieval-Augmented Generation)") | |
| with gr.Tabs(): | |
| # Chat Interface Tab | |
| with gr.Tab("💬 Chat Assistant"): | |
| gr.Markdown("Ask me anything about diet planning, nutrition, or health!") | |
| chatbot = gr.Chatbot( | |
| label="Conversation", | |
| height=500, | |
| type="messages", | |
| render_markdown=True | |
| ) | |
| with gr.Row(): | |
| msg = gr.Textbox( | |
| label="Your message", | |
| placeholder="Ask me to create a diet plan, calculate nutrition, or get recommendations...", | |
| lines=2, | |
| scale=4 | |
| ) | |
| send_btn = gr.Button("Send", variant="primary", scale=1) | |
| # Action buttons | |
| with gr.Row(): | |
| clear_btn = gr.Button("Clear Chat", variant="secondary") | |
| load_latest_btn = gr.Button("📄 Load Latest JSON", variant="secondary") | |
| list_outputs_btn = gr.Button("📁 List All Outputs", variant="secondary") | |
| # Event handlers | |
| msg.submit(process_user_input, [msg, chatbot], [chatbot, msg]) | |
| send_btn.click(process_user_input, [msg, chatbot], [chatbot, msg]) | |
| clear_btn.click(lambda: ([], ""), outputs=[chatbot, msg]) | |
| load_latest_btn.click(lambda: ([{"role": "assistant", "content": load_latest_json_output()}], ""), outputs=[chatbot, msg]) | |
| list_outputs_btn.click(lambda: ([{"role": "assistant", "content": list_all_json_outputs()}], ""), outputs=[chatbot, msg]) | |
| # Diet Plan Creator Tab | |
| with gr.Tab("📋 Diet Plan Creator"): | |
| gr.Markdown("Create personalized diet plans based on your profile") | |
| with gr.Row(): | |
| with gr.Column(): | |
| gr.Markdown("### Personal Information") | |
| age = gr.Number(label="Age", value=30, minimum=15, maximum=100) | |
| sex = gr.Dropdown(label="Gender", choices=["male", "female"], value="male") | |
| height_cm = gr.Number(label="Height (cm)", value=175, minimum=100, maximum=250) | |
| weight_kg = gr.Number(label="Weight (kg)", value=75, minimum=30, maximum=300) | |
| gr.Markdown("### Activity & Goals") | |
| activity_level = gr.Dropdown( | |
| label="Activity Level", | |
| choices=["sedentary", "light", "moderate", "active", "very_active"], | |
| value="moderate" | |
| ) | |
| goal = gr.Dropdown( | |
| label="Goal", | |
| choices=["weight_loss", "muscle_gain", "maintenance", "keto", "mediterranean"], | |
| value="weight_loss" | |
| ) | |
| plan_type = gr.Dropdown( | |
| label="Plan Type", | |
| choices=["daily", "weekly"], | |
| value="daily" | |
| ) | |
| create_plan_btn = gr.Button("Create Diet Plan", variant="primary") | |
| with gr.Column(): | |
| plan_output = gr.Textbox( | |
| label="Diet Plan", | |
| lines=20, | |
| max_lines=30 | |
| ) | |
| create_plan_btn.click( | |
| create_diet_plan_interface, | |
| inputs=[age, sex, height_cm, weight_kg, activity_level, goal, plan_type], | |
| outputs=plan_output | |
| ) | |
| # Recommendations Tab | |
| with gr.Tab("📊 Diet Recommendations"): | |
| gr.Markdown("Get personalized nutrition recommendations") | |
| with gr.Row(): | |
| with gr.Column(): | |
| gr.Markdown("### Personal Information") | |
| rec_age = gr.Number(label="Age", value=30, minimum=15, maximum=100) | |
| rec_sex = gr.Dropdown(label="Gender", choices=["male", "female"], value="male") | |
| rec_height_cm = gr.Number(label="Height (cm)", value=175, minimum=100, maximum=250) | |
| rec_weight_kg = gr.Number(label="Weight (kg)", value=75, minimum=30, maximum=300) | |
| gr.Markdown("### Activity & Goals") | |
| rec_activity_level = gr.Dropdown( | |
| label="Activity Level", | |
| choices=["sedentary", "light", "moderate", "active", "very_active"], | |
| value="moderate" | |
| ) | |
| rec_goal = gr.Dropdown( | |
| label="Goal", | |
| choices=["weight_loss", "muscle_gain", "maintenance", "keto", "mediterranean"], | |
| value="weight_loss" | |
| ) | |
| get_rec_btn = gr.Button("Get Recommendations", variant="primary") | |
| with gr.Column(): | |
| rec_output = gr.Textbox( | |
| label="Recommendations", | |
| lines=15, | |
| max_lines=20 | |
| ) | |
| get_rec_btn.click( | |
| get_recommendations_interface, | |
| inputs=[rec_age, rec_sex, rec_height_cm, rec_weight_kg, rec_activity_level, rec_goal], | |
| outputs=rec_output | |
| ) | |
| # Nutrition Calculator Tab | |
| with gr.Tab("🧮 Nutrition Calculator"): | |
| gr.Markdown("Calculate nutritional values for specific foods") | |
| with gr.Row(): | |
| with gr.Column(): | |
| food_name = gr.Textbox( | |
| label="Food Name", | |
| placeholder="e.g., Chicken Breast, Apple, Brown Rice...", | |
| value="Chicken Breast" | |
| ) | |
| portion_grams = gr.Number( | |
| label="Portion (grams)", | |
| value=150, | |
| minimum=1, | |
| maximum=1000 | |
| ) | |
| calc_nutrition_btn = gr.Button("Calculate Nutrition", variant="primary") | |
| with gr.Column(): | |
| nutrition_output = gr.Textbox( | |
| label="Nutritional Information", | |
| lines=15, | |
| max_lines=20 | |
| ) | |
| calc_nutrition_btn.click( | |
| calculate_nutrition_interface, | |
| inputs=[food_name, portion_grams], | |
| outputs=nutrition_output | |
| ) | |
| def create_gradio_interface(): | |
| """Create and return the Gradio interface for Hugging Face Spaces""" | |
| return app | |
| if __name__ == "__main__": | |
| # For local development | |
| app.launch( | |
| server_name="0.0.0.0", | |
| server_port=7860, | |
| share=False | |
| ) | |