ParthBhuptani commited on
Commit
3bb9502
·
verified ·
1 Parent(s): c1285f8

Update app.py

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