MaheshP98's picture
Update app.py
95cc670 verified
raw
history blame
18.9 kB
import gradio as gr
import numpy as np
from transformers import WhisperProcessor, WhisperForConditionalGeneration
import json
import hashlib
import os
import logging
# Set up logging
logging.basicConfig(level=logging.INFO)
logger = logging.getLogger(__name__)
# Preload Whisper model for audio transcription
try:
logger.info("Preloading Whisper model...")
processor = WhisperProcessor.from_pretrained("openai/whisper-small")
speech_model = WhisperForConditionalGeneration.from_pretrained("openai/whisper-small")
logger.info("Whisper model preloaded successfully")
except Exception as e:
logger.error(f"Error preloading Whisper model: {e}")
processor = WhisperProcessor.from_pretrained("openai/whisper-small")
speech_model = WhisperForConditionalGeneration.from_pretrained("openai/whisper-small")
# Predefined local food data (replacing USDA Local Food Directories API)
LOCAL_FOODS = [
{"name": "Rice", "price_per_unit": 60, "unit": "kg", "source": "Local Mandi"},
{"name": "Dal", "price_per_unit": 120, "unit": "kg", "source": "Farmers' Market"},
{"name": "Potatoes", "price_per_unit": 30, "unit": "kg", "source": "Local Vendor"},
{"name": "Chicken", "price_per_unit": 300, "unit": "kg", "source": "Poultry Farm"}
]
# Custom theme with improved visibility
custom_theme = gr.themes.Base(
primary_hue=gr.themes.colors.teal,
secondary_hue=gr.themes.colors.yellow,
neutral_hue=gr.themes.colors.gray,
text_size=gr.themes.sizes.text_lg,
font=[gr.themes.GoogleFont("Noto Sans")]
)
# Convert height to feet and inches
def format_height(height_ft):
feet = int(height_ft)
inches = round((height_ft - feet) * 12)
return f"{feet} ft {inches} in"
# Encrypt user data for caching
def encrypt_data(data):
return hashlib.sha256(data.encode()).hexdigest()
# Transcribe audio to text
def transcribe_audio(audio):
if audio is None:
return "Farmer"
try:
audio_data = np.frombuffer(audio, dtype=np.int16)
input_features = processor(audio_data, sampling_rate=16000, return_tensors="pt").input_features
predicted_ids = speech_model.generate(input_features, max_new_tokens=30)
transcription = processor.decode(predicted_ids[0], skip_special_tokens=True)
logger.info(f"Transcribed audio to: {transcription}")
return transcription[:50]
except Exception as e:
logger.error(f"Audio transcription failed: {e}")
return "Farmer"
# Translate function for multilingual support
def translate_output(text, lang):
translations = {
"en": {
"app_title": "Personalized Diet Generator",
"dietitian_review": "Dietitian Review",
"your_feedback": "Your Feedback",
"age": "Age (years)",
"gender": "Gender",
"weight": "Weight (kg)",
"height": "Height (ft)",
"occupation": "Occupation",
"activity_level": "Activity Level",
"health_conditions": "Health Conditions (e.g., diabetes)",
"dietary_preferences": "Dietary Preferences (e.g., vegetarian)",
"allergies": "Allergies",
"weekly_budget": "Weekly Budget (₹)",
"pincode": "Pincode",
"cultural_preferences": "Cultural Preferences",
"consent": "I consent to data processing",
"status_success": "Diet plan generated successfully",
"status_cached": "Loaded cached diet plan (offline mode)",
"status_error": "Error: Please consent to data processing",
"feedback_dietitian": "Feedback submitted successfully!",
"feedback_user": "Thank you for your feedback!",
"monday": "Monday", "tuesday": "Tuesday", "wednesday": "Wednesday",
"thursday": "Thursday", "friday": "Friday", "saturday": "Saturday", "sunday": "Sunday",
"breakfast": "Breakfast", "lunch": "Lunch", "dinner": "Dinner"
},
"hi": {
"app_title": "वैयक्तिकृत आहार जनरेटर",
"dietitian_review": "डायटिशियन समीक्षा",
"your_feedback": "आपकी प्रतिक्रिया",
"age": "आयु (वर्ष)",
"gender": "लिंग",
"weight": "वजन (किग्रा)",
"height": "ऊंचाई (फीट)",
"occupation": "पेशा",
"activity_level": "गतिविधि स्तर",
"health_conditions": "स्वास्थ्य स्थितियाँ (जैसे, मधुमेह)",
"dietary_preferences": "आहार प्राथमिकताएँ (जैसे, शाकाहारी)",
"allergies": "एलर्जी",
"weekly_budget": "साप्ताहिक बजट (₹)",
"pincode": "पिनकोड",
"cultural_preferences": "सांस्कृतिक प्राथमिकताएँ",
"consent": "मैं डेटा प्रसंस्करण के लिए सहमति देता हूँ",
"status_success": "आहार योजना सफलतापूर्वक उत्पन्न की गई",
"status_cached": "संरक्षित आहार योजना लोड की गई (ऑफलाइन मोड)",
"status_error": "त्रुटि: कृपया डेटा प्रसंस्करण के लिए सहमति दें",
"feedback_dietitian": "प्रतिक्रिया सफलतापूर्वक जमा की गई!",
"feedback_user": "आपकी प्रतिक्रिया के लिए धन्यवाद!",
"monday": "सोमवार", "tuesday": "मंगलवार", "wednesday": "बुधवार",
"thursday": "गुरुवार", "friday": "शुक्रवार", "saturday": "शनिवार", "sunday": "रविवार",
"breakfast": "नाश्ता", "lunch": "दोपहर का भोजन", "dinner": "रात का भोजन"
}
}
lang_map = {"English": "en", "Hindi": "hi"}
lang_code = lang_map.get(lang, "en")
return translations.get(lang_code, translations["en"])
# Generate diet plan
def generate_diet_plan(age, gender, weight, height, occupation, activity_level, health_conditions,
dietary_preferences, allergies, budget, zip_code, cultural_preferences, consent, lang, audio=None):
logger.info("Generating diet plan with inputs: age=%s, gender=%s, weight=%s, height=%s, occupation=%s, consent=%s",
age, gender, weight, height, occupation, consent)
if not consent:
return translate_output("status_error", lang), [], ""
if audio is not None:
occupation = transcribe_audio(audio)
user_data = {
"age": age, "gender": gender, "weight": weight, "height": height, "occupation": occupation,
"activity_level": activity_level, "health_conditions": health_conditions,
"dietary_preferences": dietary_preferences, "allergies": allergies, "budget": budget,
"cultural_preferences": cultural_preferences
}
user_id = encrypt_data(json.dumps(user_data))
cached_plan = load_cached_plan(user_id)
if cached_plan:
logger.info("Loaded cached diet plan for user_id: %s", user_id)
diet_plan_output = format_diet_plan(cached_plan, lang)
local_foods_output = format_local_foods(LOCAL_FOODS, lang)
return translate_output("status_cached", lang), local_foods_output, diet_plan_output
formatted_height = format_height(height)
diet_plan = {
"Monday": {"breakfast": "Roti with dal", "lunch": "Rice and potato curry", "dinner": "Chicken curry"},
"Tuesday": {"breakfast": "Poha", "lunch": "Dal and roti", "dinner": "Vegetable stir-fry"},
"Wednesday": {"breakfast": "Upma", "lunch": "Rice and sambar", "dinner": "Chicken gravy"},
"Thursday": {"breakfast": "Idli with chutney", "lunch": "Roti and dal", "dinner": "Potato sabzi"},
"Friday": {"breakfast": "Dosa", "lunch": "Rice and chicken curry", "dinner": "Dal and roti"},
"Saturday": {"breakfast": "Puri with aloo", "lunch": "Vegetable pulao", "dinner": "Chicken fry"},
"Sunday": {"breakfast": "Paratha", "lunch": "Rice and sambar", "dinner": "Dal tadka"}
}
if "South Indian" in cultural_preferences.lower():
diet_plan.update({"Monday": {"breakfast": "Idli with sambar", "lunch": "Rice and rasam", "dinner": "Vegetable curry"},
"Friday": {"breakfast": "Dosa with chutney", "lunch": "Rice and fish curry", "dinner": "Dal"}})
elif "North Indian" in cultural_preferences.lower():
diet_plan.update({"Monday": {"breakfast": "Paratha with curd", "lunch": "Roti and paneer", "dinner": "Dal makhani"},
"Friday": {"breakfast": "Puri with aloo", "lunch": "Roti and chole", "dinner": "Vegetable pulao"}})
cache_diet_plan(user_id, diet_plan)
logger.info("Diet plan generated and cached for user_id: %s", user_id)
diet_plan_output = format_diet_plan(diet_plan, lang)
local_foods_output = format_local_foods(LOCAL_FOODS, lang)
return translate_output("status_success", lang), local_foods_output, diet_plan_output
# Format diet plan and local foods
def format_diet_plan(diet_plan, lang):
trans = translate_output("", lang)
output = ""
for day, meals in diet_plan.items():
output += f"### {trans[day.lower()]}\n"
output += f"- **{trans['breakfast']}**: {meals['breakfast']}\n"
output += f"- **{trans['lunch']}**: {meals['lunch']}\n"
output += f"- **{trans['dinner']}**: {meals['dinner']}\n\n"
return output
def format_local_foods(local_foods, lang):
return [f"{food['name']} - ₹{food['price_per_unit']}/{food['unit']} from {food['source']}" for food in local_foods]
# Cache and load functions for offline support
def cache_diet_plan(user_id, diet_plan):
logger.info(f"Caching diet plan for user: {user_id}")
try:
with open(f"cache_{user_id}.json", "w") as f:
json.dump(diet_plan, f)
except Exception as e:
logger.error(f"Error caching diet plan: {e}")
def load_cached_plan(user_id):
logger.info(f"Loading cached diet plan for user: {user_id}")
try:
with open(f"cache_{user_id}.json", "r") as f:
return json.load(f)
except:
return None
# Submit feedback
def submit_dietitian_feedback(feedback, lang):
logger.info(f"Submitting dietitian feedback: {feedback}")
if not feedback or feedback.strip() == "":
return "Error: Please provide feedback"
try:
with open("dietitian_feedback.json", "a") as f:
f.write(json.dumps({"feedback": feedback, "lang": lang}) + "\n")
except Exception as e:
logger.error(f"Error saving dietitian feedback: {e}")
return translate_output("feedback_dietitian", lang)
def submit_user_feedback(feedback, lang):
logger.info(f"Submitting user feedback: {feedback}")
if not feedback or feedback.strip() == "":
return "Error: Please provide feedback"
try:
with open("user_feedback.json", "a") as f:
f.write(json.dumps({"feedback": feedback, "lang": lang}) + "\n")
except Exception as e:
logger.error(f"Error saving user feedback: {e}")
return translate_output("feedback_user", lang)
# Main interface
def main():
with gr.Blocks(title="Personalized Diet Generator", theme=custom_theme, css="""
.container { max-width: 900px; margin: 20px auto; padding: 25px; background: #00695C; border-radius: 15px; box-shadow: 0 4px 8px rgba(0,0,0,0.1); }
.card { background: #BF360C; padding: 20px; margin-bottom: 25px; border-radius: 10px; box-shadow: 0 2px 6px rgba(0,0,0,0.1); color: #FFFFFF; }
.diet-plan { min-height: 400px; font-size: 18px; color: #FFFFFF; }
.gr-button { background: #FFCA28; color: #000000; padding: 12px 25px; border: none; border-radius: 8px; font-size: 16px; }
.gr-button:hover { background: #FFB300; }
.gr-textbox { font-size: 16px; padding: 10px; border: 2px solid #FFCA28; border-radius: 5px; background: #FFFFFF; color: #000000; }
.gr-slider { width: 100%; }
.gr-dropdown { font-size: 16px; padding: 10px; background: #FFFFFF; color: #000000; }
h3 { color: #FFCA28; font-size: 24px; }
""") as demo:
language = gr.Dropdown(
choices=["English", "Hindi"],
value="English",
label="Select Language"
)
def update_interface(lang):
trans = translate_output("", lang)
return gr.Markdown(f"### {trans['app_title']}", elem_classes="container"), \
gr.Markdown(f"### {trans['dietitian_review']}", visible=True), \
gr.Markdown(f"### {trans['your_feedback']}", visible=True), \
gr.Slider(minimum=18, maximum=80, value=35, label=trans["age"], step=1), \
gr.Dropdown(choices=["Male", "Female", "Other"], value="Male", label=trans["gender"]), \
gr.Slider(minimum=20, maximum=150, value=60, label=trans["weight"], step=0.5), \
gr.Slider(minimum=4.0, maximum=6.5, value=5.2, step=0.01, label=trans["height"]), \
gr.Textbox(label=trans["occupation"], value="Farmer"), \
gr.Microphone(label=trans["occupation"] + " (Optional)"), \
gr.Dropdown(choices=["Low", "Moderate", "High"], value="Moderate", label=trans["activity_level"]), \
gr.Textbox(label=trans["health_conditions"], value="None"), \
gr.Textbox(label=trans["dietary_preferences"], value="None"), \
gr.Textbox(label=trans["allergies"], value="None"), \
gr.Slider(minimum=830, maximum=41500, value=5000, label=trans["weekly_budget"]), \
gr.Textbox(label=trans["pincode"], value="500075"), \
gr.Textbox(label=trans["cultural_preferences"], value="South Indian"), \
gr.Checkbox(label=trans["consent"], value=False)
language.change(
fn=update_interface,
inputs=[language],
outputs=[
gr.Markdown(elem_classes="container"),
gr.Markdown(visible=True),
gr.Markdown(visible=True),
gr.Slider(),
gr.Dropdown(),
gr.Slider(),
gr.Slider(),
gr.Textbox(),
gr.Microphone(),
gr.Dropdown(),
gr.Textbox(),
gr.Textbox(),
gr.Textbox(),
gr.Slider(),
gr.Textbox(),
gr.Textbox(),
gr.Checkbox()
]
)
trans_init = translate_output("", "English")
with gr.Row(elem_classes="container"):
with gr.Column(scale=1, elem_classes="card"):
age = gr.Slider(minimum=18, maximum=80, value=35, label=trans_init["age"], step=1)
gender = gr.Dropdown(choices=["Male", "Female", "Other"], value="Male", label=trans_init["gender"])
weight = gr.Slider(minimum=20, maximum=150, value=60, label=trans_init["weight"], step=0.5)
height = gr.Slider(minimum=4.0, maximum=6.5, value=5.2, step=0.01, label=trans_init["height"])
occupation = gr.Textbox(label=trans_init["occupation"], value="Farmer")
audio_input = gr.Microphone(label=trans_init["occupation"] + " (Optional)")
with gr.Column(scale=1, elem_classes="card"):
activity_level = gr.Dropdown(choices=["Low", "Moderate", "High"], value="Moderate", label=trans_init["activity_level"])
health_conditions = gr.Textbox(label=trans_init["health_conditions"], value="None")
dietary_preferences = gr.Textbox(label=trans_init["dietary_preferences"], value="None")
allergies = gr.Textbox(label=trans_init["allergies"], value="None")
budget = gr.Slider(minimum=830, maximum=41500, value=5000, label=trans_init["weekly_budget"])
with gr.Row(elem_classes="container"):
with gr.Column(scale=1, elem_classes="card"):
zip_code = gr.Textbox(label=trans_init["pincode"], value="500075")
cultural_preferences = gr.Textbox(label=trans_init["cultural_preferences"], value="South Indian")
consent = gr.Checkbox(label=trans_init["consent"], value=False)
submit_button = gr.Button("Generate Diet Plan")
with gr.Row(elem_classes="container"):
with gr.Column(scale=1, elem_classes="card"):
status = gr.Textbox(label="Status")
local_foods = gr.Textbox(label="Local Food Sources", lines=4)
diet_plan = gr.Markdown(label="Weekly Diet Plan", elem_classes="diet-plan")
with gr.Row(elem_classes="container"):
with gr.Column(scale=1, elem_classes="card"):
gr.Markdown(f"### {trans_init['dietitian_review']}")
dietitian_feedback = gr.Textbox(label="Dietitian Feedback", value="Plan looks balanced. Suggest adding more greens.")
dietitian_submit = gr.Button("Submit Feedback")
dietitian_output = gr.Textbox(label="Feedback Status")
with gr.Row(elem_classes="container"):
with gr.Column(scale=1, elem_classes="card"):
gr.Markdown(f"### {trans_init['your_feedback']}")
user_feedback = gr.Textbox(label="Your Feedback")
user_submit = gr.Button("Submit Feedback")
user_output = gr.Textbox(label="Feedback Status")
# Event handlers
submit_button.click(
fn=generate_diet_plan,
inputs=[age, gender, weight, height, occupation, activity_level, health_conditions,
dietary_preferences, allergies, budget, zip_code, cultural_preferences, consent, language, audio_input],
outputs=[status, local_foods, diet_plan]
)
dietitian_submit.click(
fn=submit_dietitian_feedback,
inputs=[dietitian_feedback, language],
outputs=dietitian_output
)
user_submit.click(
fn=submit_user_feedback,
inputs=[user_feedback, language],
outputs=user_output
)
return demo
if __name__ == "__main__":
demo = main()
demo.launch(server_name="0.0.0.0", server_port=7860)