Spaces:
Sleeping
Sleeping
File size: 5,495 Bytes
87edca7 27c3f18 87edca7 27c3f18 87edca7 27c3f18 87edca7 27c3f18 3244390 27c3f18 87edca7 27c3f18 87edca7 27c3f18 c1285f8 27c3f18 87edca7 27c3f18 87edca7 27c3f18 87edca7 27c3f18 87edca7 3244390 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 |
import gradio as gr
import requests
import os
from fpdf import FPDF
import uuid
import re
import matplotlib.pyplot as plt
import tempfile
# Load your Nebius API key and Folder ID from environment variables
NEBIUS_API_KEY = os.getenv("NEBIUS_API_KEY") or "YOUR_NEBIUS_API_KEY"
FOLDER_ID = os.getenv("FOLDER_ID") or "YOUR_FOLDER_ID"
def generate_meal(preferences, ingredients, time):
prompt = f"""
You're a smart kitchen agent.
Given:
- Dietary preferences: {preferences}
- Ingredients available: {ingredients}
- Time available: {time} minutes
Tasks:
1. Suggest one meal idea
2. Provide step-by-step recipe instructions
3. List missing ingredients (Shopping List)
4. Estimate nutrition (calories, protein, carbs, fat)
Output in this format:
Meal Name: ...
Steps:
1. ...
2. ...
Shopping List:
- ...
Nutrition:
- Calories: ... kcal
- Protein: ... g
- Carbs: ... g
- Fat: ... g
"""
headers = {
"Authorization": f"Api-Key {NEBIUS_API_KEY}",
"Content-Type": "application/json"
}
data = {
"modelUri": f"gpt://{FOLDER_ID}/yandexgpt-lite",
"completionOptions": {"stream": False, "temperature": 0.7, "maxTokens": 700},
"messages": [{"role": "user", "text": prompt.strip()}]
}
response = requests.post(
"https://llm.api.cloud.yandex.net/foundationModels/v1/completion",
headers=headers, json=data
)
try:
text = response.json()["result"]["alternatives"][0]["message"]["text"]
except Exception as e:
return f"❌ Error: Could not fetch recipe. {e}"
return text
def extract_nutrition(recipe_text):
# More robust pattern allowing newlines and flexible spacing
pattern = (
r"Calories:\s*([\d\.]+)\s*kcal.*?"
r"Protein:\s*([\d\.]+)\s*g.*?"
r"Carbs:\s*([\d\.]+)\s*g.*?"
r"Fat:\s*([\d\.]+)\s*g"
)
match = re.search(pattern, recipe_text.replace("\n", " "))
if match:
calories, protein, carbs, fat = map(float, match.groups())
return {"Calories": calories, "Protein": protein, "Carbs": carbs, "Fat": fat}
return None
def plot_nutrition_chart(nutrition):
fig, ax = plt.subplots()
nutrients = list(nutrition.keys())
values = list(nutrition.values())
colors = ['#ff9999','#66b3ff','#99ff99','#ffcc99']
ax.pie(values, labels=nutrients, autopct='%1.1f%%', startangle=140, colors=colors)
ax.axis('equal')
plt.tight_layout()
temp_file = tempfile.NamedTemporaryFile(suffix=".png", delete=False)
plt.savefig(temp_file.name)
plt.close(fig)
return temp_file.name
def handle_generate(preferences, ingredients, time):
recipe = generate_meal(preferences, ingredients, time)
nutrition = extract_nutrition(recipe)
chart_path = None
if nutrition:
chart_path = plot_nutrition_chart(nutrition)
return recipe, chart_path
def save_pdf(recipe_text):
pdf = FPDF()
pdf.add_page()
pdf.set_font("Arial", size=12)
for line in recipe_text.split('\n'):
pdf.multi_cell(0, 10, line)
temp_file = tempfile.NamedTemporaryFile(suffix=".pdf", delete=False)
pdf.output(temp_file.name)
return temp_file.name
# Optional: placeholder function for speech-to-text (you can replace with real STT)
def dummy_speech_to_text(audio):
# This just returns a fixed string for demo. Replace with actual STT model call if you want.
if audio is None:
return ""
return "tomato, onion, garlic"
with gr.Blocks(css="""
body { background-color: #111; color: #eee; font-family: 'Segoe UI', sans-serif; }
.gradio-container { max-width: 900px; margin: auto; }
.input-label { font-weight: 600; margin-bottom: 5px; }
.footer { font-size: 0.8rem; color: #666; padding: 10px; text-align: center; }
@media (max-width: 600px) {
.gradio-container { padding: 10px; }
}
""") as demo:
gr.Markdown("# 👨🍳 AgentChef: AI Recipe Planner & Smart Kitchen Assistant")
with gr.Row():
with gr.Column(scale=1, min_width=200):
preferences = gr.Textbox(label="🥗 Dietary Preferences", placeholder="e.g. vegetarian, keto")
ingredients = gr.Textbox(label="🧂 Ingredients You Have", placeholder="e.g. rice, tomato, onion", lines=3)
mic = gr.Audio(type="filepath", label="🎤 Speak Ingredients")
transcribed = gr.Textbox(label="📝 Transcribed Ingredients (from mic)", interactive=False)
mic.change(dummy_speech_to_text, inputs=mic, outputs=transcribed)
# Add a button to copy transcribed text to ingredients textbox if needed
copy_btn = gr.Button("Copy Transcription to Ingredients")
copy_btn.click(lambda txt: txt, inputs=transcribed, outputs=ingredients)
time = gr.Slider(5, 60, value=20, step=5, label="⏱️ Time Available (minutes)")
generate_btn = gr.Button("🍽️ Generate Recipe")
with gr.Column(scale=1, min_width=300):
recipe_output = gr.Textbox(label="📝 Recipe Output", lines=15, interactive=False)
nutrition_chart = gr.Image(label="📊 Nutrition Breakdown", interactive=False)
pdf_btn = gr.Button("📄 Export as PDF")
generate_btn.click(handle_generate,
inputs=[preferences, ingredients, time],
outputs=[recipe_output, nutrition_chart])
pdf_btn.click(save_pdf, inputs=[recipe_output], outputs=gr.File(label="📥 Download Recipe PDF"))
demo.launch() |