Beable's picture
Update app.py
34089a0 verified
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
)