kissmihalyit commited on
Commit
ea3f136
·
1 Parent(s): 94bf407

refactored code

Browse files
Dockerfile ADDED
@@ -0,0 +1,15 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ FROM python:3.8-slim
2
+
3
+ WORKDIR /app
4
+
5
+ COPY requirements.txt .
6
+ RUN pip install --no-cache-dir -r requirements.txt
7
+
8
+ COPY . .
9
+
10
+ ENV PYTHONPATH="/app"
11
+ ENV PORT=7860
12
+
13
+ EXPOSE 7860
14
+
15
+ CMD ["python", "app.py"]
Dockerfile.rasa ADDED
@@ -0,0 +1,19 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ FROM python:3.8-slim
2
+
3
+ WORKDIR /app
4
+
5
+ RUN apt-get update && apt-get install -y curl && rm -rf /var/lib/apt/lists/*
6
+
7
+ COPY requirements.txt .
8
+ RUN pip install --no-cache-dir -r requirements.txt
9
+
10
+ COPY ./rasa_app /app/rasa_app
11
+
12
+ ENV PYTHONPATH="/app"
13
+
14
+ EXPOSE 5005
15
+
16
+ HEALTHCHECK --interval=30s --timeout=10s --start-period=15s --retries=3 \
17
+ CMD curl -f http://localhost:5005/ || exit 1
18
+
19
+ CMD ["python", "-m", "rasa", "run", "--enable-api", "--cors", "*"]
README.md CHANGED
@@ -1,10 +1,14 @@
1
  ---
2
- title: IHCI Diet
3
- emoji: 📉
4
  colorFrom: green
5
  colorTo: blue
6
  sdk: docker
 
 
7
  pinned: false
8
  ---
9
 
10
- Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
 
 
 
1
  ---
2
+ title: Diet Planning Chatbot
3
+ emoji: 🥗
4
  colorFrom: green
5
  colorTo: blue
6
  sdk: docker
7
+ sdk_version: "3.0.0"
8
+ app_file: app.py
9
  pinned: false
10
  ---
11
 
12
+ # Diet Planning Chatbot
13
+
14
+ A personalized diet and meal planning assistant that creates custom meal plans based on your preferences, restrictions, and health goals.
app.py ADDED
@@ -0,0 +1,506 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import gradio as gr
2
+ import cohere
3
+ import os
4
+ import re
5
+ from dotenv import load_dotenv
6
+
7
+ load_dotenv()
8
+ COHERE_API_KEY = os.getenv("COHERE_API_KEY")
9
+ co = cohere.Client(COHERE_API_KEY)
10
+
11
+ custom_css = """
12
+ .gradio-container {
13
+ font-family: 'Inter', -apple-system, BlinkMacSystemFont, sans-serif;
14
+ }
15
+ .app-header {
16
+ text-align: center;
17
+ margin-bottom: 20px;
18
+ }
19
+ .app-title {
20
+ background: linear-gradient(90deg, #2e7d32, #1976d2);
21
+ -webkit-background-clip: text;
22
+ -webkit-text-fill-color: transparent;
23
+ font-weight: 700;
24
+ font-size: 2.5em;
25
+ margin-bottom: 8px;
26
+ }
27
+ .markdown-text p {
28
+ margin-bottom: 12px;
29
+ line-height: 1.5;
30
+ }
31
+ .diet-header {
32
+ font-size: 1.5em;
33
+ margin-top: 24px;
34
+ margin-bottom: 16px;
35
+ font-weight: 600;
36
+ color: #2e7d32;
37
+ border-bottom: 1px solid rgba(0, 0, 0, 0.1);
38
+ padding-bottom: 6px;
39
+ }
40
+ .day-header {
41
+ font-size: 1.2em;
42
+ margin-top: 20px;
43
+ margin-bottom: 12px;
44
+ font-weight: 600;
45
+ color: #1976d2;
46
+ background-color: #f5f5f5;
47
+ padding: 8px 12px;
48
+ border-radius: 6px;
49
+ }
50
+ .meal-type {
51
+ font-weight: 600;
52
+ color: #d32f2f;
53
+ margin-right: 4px;
54
+ }
55
+ .markdown-text ul, .markdown-text ol {
56
+ margin-bottom: 12px;
57
+ padding-left: 24px;
58
+ }
59
+ .markdown-text li {
60
+ margin-bottom: 4px;
61
+ }
62
+ .markdown-text strong {
63
+ font-weight: 600;
64
+ }
65
+ .message-bubble {
66
+ padding: 16px;
67
+ border-radius: 12px;
68
+ max-width: 90%;
69
+ margin-bottom: 8px;
70
+ }
71
+ .user-message {
72
+ background-color: #e3f2fd;
73
+ align-self: flex-end;
74
+ }
75
+ .bot-message {
76
+ background-color: #f1f8e9;
77
+ align-self: flex-start;
78
+ }
79
+ .center-content {
80
+ display: flex;
81
+ flex-direction: column;
82
+ align-items: center;
83
+ }
84
+ .diet-card {
85
+ border: 1px solid #e0e0e0;
86
+ border-radius: 12px;
87
+ padding: 20px;
88
+ box-shadow: 0 2px 10px rgba(0, 0, 0, 0.05);
89
+ background-color: white;
90
+ margin-top: 10px;
91
+ margin-bottom: 20px;
92
+ width: 100%;
93
+ line-height: 1.6;
94
+ }
95
+ .diet-card ul li::marker {
96
+ color: #2e7d32;
97
+ }
98
+ .diet-card p {
99
+ margin-bottom: 8px;
100
+ }
101
+ .diet-list {
102
+ list-style-type: none;
103
+ padding-left: 0;
104
+ }
105
+ .diet-list li {
106
+ background-color: #f9f9f9;
107
+ margin-bottom: 6px;
108
+ padding: 6px 10px;
109
+ border-radius: 4px;
110
+ border-left: 3px solid #2e7d32;
111
+ }
112
+ .input-container {
113
+ background-color: white;
114
+ border-radius: 10px;
115
+ padding: 10px;
116
+ box-shadow: 0 2px 10px rgba(0, 0, 0, 0.05);
117
+ }
118
+ .features-container {
119
+ display: flex;
120
+ flex-wrap: wrap;
121
+ margin-top: 24px;
122
+ gap: 16px;
123
+ }
124
+ .feature-card {
125
+ flex: 1 1 calc(33% - 16px);
126
+ min-width: 200px;
127
+ background-color: white;
128
+ padding: 16px;
129
+ border-radius: 10px;
130
+ box-shadow: 0 2px 10px rgba(0, 0, 0, 0.05);
131
+ }
132
+ .feature-icon {
133
+ font-size: 24px;
134
+ margin-bottom: 10px;
135
+ color: #2e7d32;
136
+ }
137
+ .footer {
138
+ text-align: center;
139
+ margin-top: 30px;
140
+ font-size: 0.9em;
141
+ color: #666;
142
+ }
143
+ """
144
+
145
+ def format_markdown(text):
146
+ if "## Diet Overview" in text:
147
+ text = text.replace("## Diet Overview", '<h2 class="diet-header">Diet Overview</h2>')
148
+ text = text.replace("## Weekly Meal Plan", '<h2 class="diet-header">Weekly Meal Plan</h2>')
149
+ text = text.replace("## General Recommendations", '<h2 class="diet-header">General Recommendations</h2>')
150
+
151
+ for day in ["Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday"]:
152
+ text = text.replace(f"### {day}", f'<h3 class="day-header">{day}</h3>')
153
+
154
+ for meal in ["Breakfast", "Lunch", "Dinner", "Snacks"]:
155
+ text = text.replace(f"**{meal}**:", f'<strong class="meal-type">{meal}</strong>:')
156
+
157
+ lines = text.split('\n')
158
+ formatted_lines = []
159
+
160
+ in_list = False
161
+ list_items = []
162
+
163
+ for line in lines:
164
+ if line.strip().startswith('- '):
165
+ in_list = True
166
+ list_items.append(line.strip()[2:])
167
+ else:
168
+ if in_list:
169
+ formatted_list = '<ul class="diet-list">\n'
170
+ for item in list_items:
171
+ formatted_list += f' <li>{item}</li>\n'
172
+ formatted_list += '</ul>'
173
+ formatted_lines.append(formatted_list)
174
+ in_list = False
175
+ list_items = []
176
+
177
+ formatted_lines.append(line)
178
+
179
+ if in_list:
180
+ formatted_list = '<ul class="diet-list">\n'
181
+ for item in list_items:
182
+ formatted_list += f' <li>{item}</li>\n'
183
+ formatted_list += '</ul>'
184
+ formatted_lines.append(formatted_list)
185
+
186
+ text = '\n'.join(formatted_lines)
187
+
188
+ text = f'<div class="diet-card markdown-text">{text}</div>'
189
+
190
+ return text
191
+
192
+ class ConversationState:
193
+ def __init__(self):
194
+ self.reset()
195
+
196
+ def reset(self):
197
+ self.current_step = "greeting"
198
+ self.user_profile = {
199
+ "dietary_preference": None,
200
+ "health_goal": None,
201
+ "age": None,
202
+ "weight": None,
203
+ "height": None,
204
+ "gender": None,
205
+ "activity_level": None,
206
+ "restrictions": [],
207
+ "allergies": []
208
+ }
209
+
210
+ state = ConversationState()
211
+
212
+ def extract_info(message):
213
+ """Extract all relevant information from a message at once"""
214
+ info = {}
215
+
216
+ preferences = ["vegetarian", "vegan", "keto", "paleo", "gluten-free", "low-carb",
217
+ "pescatarian", "mediterranean", "dash", "plant-based", "flexitarian",
218
+ "low-fat", "carnivore", "whole food"]
219
+ for pref in preferences:
220
+ if pref in message.lower():
221
+ info["dietary_preference"] = pref
222
+ break
223
+
224
+ goals = {
225
+ "lose weight": "weight loss",
226
+ "weight loss": "weight loss",
227
+ "gain weight": "weight gain",
228
+ "weight gain": "weight gain",
229
+ "maintain": "weight maintenance",
230
+ "muscle": "muscle building",
231
+ "energy": "improved energy",
232
+ "health": "better health"
233
+ }
234
+ for key, goal in goals.items():
235
+ if key in message.lower():
236
+ info["health_goal"] = goal
237
+ break
238
+
239
+ age_match = re.search(r'(\d+)\s*(?:years|year|yr|y)(?:\s*old)?', message.lower())
240
+ if age_match:
241
+ info["age"] = age_match.group(1)
242
+
243
+ weight_match = re.search(r'(\d+(?:\.\d+)?)\s*(?:kg|kilos?|pounds?|lbs?)', message.lower())
244
+ if weight_match:
245
+ info["weight"] = weight_match.group(0)
246
+
247
+ height_match = re.search(r'(\d+(?:\.\d+)?)\s*(?:cm|centimeters?|meters?|m|feet|foot|ft|\'|inches|in|")', message.lower())
248
+ if height_match:
249
+ info["height"] = height_match.group(0)
250
+
251
+ if "male" in message.lower():
252
+ info["gender"] = "male"
253
+ elif "female" in message.lower():
254
+ info["gender"] = "female"
255
+
256
+ activity_keywords = {
257
+ "sedentary": ["sedentary", "inactive", "not active", "desk job"],
258
+ "lightly active": ["lightly active", "light activity", "light exercise", "walk"],
259
+ "moderately active": ["moderately active", "moderate activity", "moderate exercise"],
260
+ "very active": ["very active", "active", "highly active", "exercise regularly"]
261
+ }
262
+
263
+ for level, keywords in activity_keywords.items():
264
+ if any(keyword in message.lower() for keyword in keywords):
265
+ info["activity_level"] = level
266
+ break
267
+
268
+ restrictions = ["lactose intolerance", "high sodium", "added sugar", "low fodmap",
269
+ "low carb", "celiac", "gluten", "high cholesterol", "ibs"]
270
+
271
+ found_restrictions = [r for r in restrictions if r in message.lower()]
272
+ if found_restrictions:
273
+ info["restrictions"] = found_restrictions
274
+
275
+ allergies = ["nuts", "shellfish", "eggs", "dairy", "wheat", "soy", "fish",
276
+ "peanuts"]
277
+
278
+ found_allergies = [a for a in allergies if a in message.lower()]
279
+ if found_allergies:
280
+ info["allergies"] = found_allergies
281
+
282
+ return info
283
+
284
+ def chat_with_diet_bot(message, history):
285
+ if not message.strip():
286
+ return "", history
287
+
288
+ if any(word in message.lower() for word in ["reset", "start over"]):
289
+ state.reset()
290
+ response = "I've reset your information. Would you like to create a diet plan?"
291
+ state.current_step = "request_diet_plan"
292
+ return "", history + [[message, response]]
293
+
294
+ if any(word in message.lower() for word in ["goodbye", "bye", "exit"]):
295
+ state.reset()
296
+ response = "Goodbye! Feel free to come back anytime for diet advice."
297
+ return "", history + [[message, response]]
298
+
299
+ info = extract_info(message)
300
+ for key, value in info.items():
301
+ if key == "restrictions" or key == "allergies":
302
+ state.user_profile[key] = value
303
+ elif value:
304
+ state.user_profile[key] = value
305
+
306
+ if state.current_step == "greeting":
307
+ response = "Hello! I can help create a personalized meal plan based on your preferences and goals. Would you like me to help with that?"
308
+ state.current_step = "request_diet_plan"
309
+
310
+ elif state.current_step == "request_diet_plan":
311
+ if any(word in message.lower() for word in ["yes", "sure", "okay", "please", "diet", "plan"]):
312
+ response = "Great! What type of diet are you following? (e.g., vegetarian, vegan, keto, paleo, gluten-free, or no specific diet)"
313
+ state.current_step = "ask_dietary_preference"
314
+
315
+ elif state.current_step == "ask_dietary_preference":
316
+ if state.user_profile["dietary_preference"]:
317
+ response = f"Thanks for letting me know you follow a {state.user_profile['dietary_preference']} diet. What's your health goal? (e.g., weight loss, weight gain, maintenance, muscle building)"
318
+ else:
319
+ state.user_profile["dietary_preference"] = "standard balanced"
320
+ response = "I'll focus on a standard balanced diet plan. What's your health goal? (e.g., weight loss, weight gain, maintenance, muscle building)"
321
+ state.current_step = "ask_health_goal"
322
+
323
+ elif state.current_step == "ask_health_goal":
324
+ if state.user_profile["health_goal"]:
325
+ response = "Could you share your age, weight, height, gender, and activity level? For example: '35 years old, 70kg, 175cm, male, moderate activity'"
326
+ else:
327
+ state.user_profile["health_goal"] = "general health"
328
+ response = "I'll focus on general health improvements. Could you share your age, weight, height, gender, and activity level?"
329
+ state.current_step = "ask_personal_info"
330
+
331
+ elif state.current_step == "ask_personal_info":
332
+ personal_info = ["age", "weight", "height", "gender", "activity_level"]
333
+ missing = [item for item in personal_info if not state.user_profile[item]]
334
+
335
+ if missing:
336
+ response = f"Thanks for that information. I still need your {', '.join(missing)}. Could you provide that?"
337
+ else:
338
+ response = "Do you have any dietary restrictions I should be aware of? (e.g., lactose intolerance, low sodium, low sugar)"
339
+ state.current_step = "ask_restrictions"
340
+
341
+ elif state.current_step == "ask_restrictions":
342
+ if "no" in message.lower() or "none" in message.lower():
343
+ state.user_profile["restrictions"] = []
344
+
345
+ response = "Do you have any food allergies? (e.g., nuts, shellfish, eggs, dairy)"
346
+ state.current_step = "ask_allergies"
347
+
348
+ elif state.current_step == "ask_allergies":
349
+ if "no" in message.lower() or "none" in message.lower():
350
+ state.user_profile["allergies"] = []
351
+
352
+ profile = state.user_profile
353
+ response = (
354
+ f"I've collected the following information:\n"
355
+ f"Dietary preference: {profile['dietary_preference']}\n"
356
+ f"Health goal: {profile['health_goal']}\n"
357
+ f"Age: {profile['age']}\n"
358
+ f"Weight: {profile['weight']}\n"
359
+ f"Height: {profile['height']}\n"
360
+ f"Gender: {profile['gender']}\n"
361
+ f"Activity level: {profile['activity_level']}\n"
362
+ f"Restrictions: {', '.join(profile['restrictions']) if profile['restrictions'] else 'None'}\n"
363
+ f"Allergies: {', '.join(profile['allergies']) if profile['allergies'] else 'None'}\n\n"
364
+ f"Is this information correct? I'll use it to create your personalized diet plan."
365
+ )
366
+ state.current_step = "confirm_information"
367
+
368
+ elif state.current_step == "confirm_information":
369
+ if any(word in message.lower() for word in ["yes", "correct", "right", "good", "ok", "okay", "fine", "sure"]):
370
+ response = "Thanks for confirming! I'm now generating your personalized diet plan..."
371
+ state.current_step = "generate_diet_plan"
372
+
373
+ profile = state.user_profile
374
+ prompt = f"""
375
+ Create a personalized weekly meal plan based on the following user information:
376
+
377
+ Dietary Preference: {profile['dietary_preference']}
378
+ Health Goal: {profile['health_goal']}
379
+ Age: {profile['age']}
380
+ Weight: {profile['weight']}
381
+ Height: {profile['height']}
382
+ Gender: {profile['gender']}
383
+ Activity Level: {profile['activity_level']}
384
+ Dietary Restrictions: {', '.join(profile['restrictions']) if profile['restrictions'] else 'None'}
385
+ Allergies: {', '.join(profile['allergies']) if profile['allergies'] else 'None'}
386
+
387
+ Generate a complete meal plan with:
388
+ 1. Diet Overview - Brief summary of the diet approach
389
+ 2. Weekly Meal Plan - Day-by-day plan with breakfast, lunch, dinner, and snacks
390
+ 3. General Recommendations - Additional advice and nutrition tips
391
+
392
+ Format in Markdown with clear headers and bullet points.
393
+ """
394
+
395
+ try:
396
+ response = co.generate(
397
+ prompt=prompt,
398
+ model="command",
399
+ max_tokens=2000,
400
+ temperature=0.7,
401
+ ).generations[0].text
402
+
403
+ formatted_response = format_markdown(response)
404
+ response = formatted_response + "\n\nI hope this meal plan helps you achieve your goals! Feel free to ask if you have any nutrition questions."
405
+ state.current_step = "diet_questions"
406
+
407
+ except Exception:
408
+ response = "I'm sorry, I couldn't generate a diet plan at the moment. Please try again later."
409
+ state.current_step = "greeting"
410
+ else:
411
+ response = "Let's update your information. What would you like to change?"
412
+ state.current_step = "update_information"
413
+
414
+ elif state.current_step == "update_information":
415
+ profile = state.user_profile
416
+ response = (
417
+ f"I've updated your information:\n"
418
+ f"Dietary preference: {profile['dietary_preference']}\n"
419
+ f"Health goal: {profile['health_goal']}\n"
420
+ f"Age: {profile['age']}\n"
421
+ f"Weight: {profile['weight']}\n"
422
+ f"Height: {profile['height']}\n"
423
+ f"Gender: {profile['gender']}\n"
424
+ f"Activity level: {profile['activity_level']}\n"
425
+ f"Restrictions: {', '.join(profile['restrictions']) if profile['restrictions'] else 'None'}\n"
426
+ f"Allergies: {', '.join(profile['allergies']) if profile['allergies'] else 'None'}\n\n"
427
+ f"Is this information correct now?"
428
+ )
429
+ state.current_step = "confirm_information"
430
+
431
+ elif state.current_step == "diet_questions":
432
+ prompt = f"""
433
+ Answer this nutrition question clearly and accurately:
434
+ Question: {message}
435
+ Provide helpful, evidence-based advice with practical tips.
436
+ """
437
+
438
+ try:
439
+ response = co.generate(
440
+ prompt=prompt,
441
+ model="command",
442
+ max_tokens=800,
443
+ temperature=0.7,
444
+ ).generations[0].text
445
+ except Exception:
446
+ response = "I'm sorry, I couldn't answer your question at the moment. Please try again later."
447
+
448
+ return "", history + [[message, response]]
449
+
450
+ with gr.Blocks(css=custom_css, theme=gr.themes.Soft()) as demo:
451
+ with gr.Column():
452
+ gr.HTML("""
453
+ <div class="app-header">
454
+ <h1 class="app-title">Diet Planning Chatbot</h1>
455
+ </div>
456
+ """)
457
+
458
+ gr.Markdown(
459
+ """
460
+ Hello! I can help you create a weekly meal plan based on your dietary preferences, health goals, and personal information.
461
+
462
+ ### How to use:
463
+ 1. Start by saying hello or asking for a diet plan
464
+ 2. The chatbot will ask about your dietary needs, health goals, and other informations
465
+ 3. After confirming, it will generate a personalized weekly meal plan
466
+ """
467
+ )
468
+
469
+ chatbot = gr.Chatbot(
470
+ [],
471
+ elem_id="chatbot",
472
+ avatar_images=["https://api.dicebear.com/7.x/thumbs/svg?seed=user", "https://api.dicebear.com/7.x/thumbs/svg?seed=bot&backgroundColor=2e7d32"],
473
+ height=500,
474
+ render_markdown=True
475
+ )
476
+
477
+ with gr.Row(elem_classes="input-container"):
478
+ msg = gr.Textbox(
479
+ show_label=False,
480
+ placeholder="Type your message here...",
481
+ scale=9,
482
+ )
483
+ clear = gr.Button("Clear", scale=1)
484
+
485
+ msg.submit(chat_with_diet_bot, [msg, chatbot], [msg, chatbot])
486
+ clear.click(lambda: [], None, chatbot)
487
+
488
+ gr.HTML("""
489
+ <div class="features-container">
490
+ <div class="feature-card">
491
+ <h3>Weekly Meal Plans</h3>
492
+ <p>Complete 7-day meal plans with breakfast, lunch, dinner, and snacks.</p>
493
+ </div>
494
+ <div class="feature-card">
495
+ <h3>Personalized</h3>
496
+ <p>Tailored to your specific dietary needs and health goals.</p>
497
+ </div>
498
+ <div class="feature-card">
499
+ <h3>Dietary Restrictions</h3>
500
+ <p>Support for vegetarian, vegan, keto, gluten-free and more.</p>
501
+ </div>
502
+ </div>
503
+ """)
504
+
505
+ if __name__ == "__main__":
506
+ demo.launch(server_name="0.0.0.0")
docker-compose.yml ADDED
@@ -0,0 +1,37 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ version: '3'
2
+
3
+ services:
4
+ rasa:
5
+ build:
6
+ context: .
7
+ dockerfile: Dockerfile.rasa
8
+ container_name: rasa
9
+ ports:
10
+ - "5005:5005"
11
+ environment:
12
+ - COHERE_API_KEY=${COHERE_API_KEY}
13
+ volumes:
14
+ - ./rasa_app:/app/rasa_app
15
+ command: ["python", "-m", "rasa", "run", "--enable-api", "--cors", "*"]
16
+ healthcheck:
17
+ test: ["CMD", "curl", "-f", "http://localhost:5005/"]
18
+ interval: 10s
19
+ timeout: 5s
20
+ retries: 5
21
+ start_period: 15s
22
+
23
+ app:
24
+ build:
25
+ context: .
26
+ container_name: diet-app
27
+ depends_on:
28
+ rasa:
29
+ condition: service_healthy
30
+ ports:
31
+ - "7860:7860"
32
+ environment:
33
+ - COHERE_API_KEY=${COHERE_API_KEY}
34
+ - RASA_URL=http://rasa:5005/webhooks/rest/webhook
35
+ volumes:
36
+ - .:/app
37
+ command: ["python", "app.py"]
huggingface-space.yml ADDED
@@ -0,0 +1,7 @@
 
 
 
 
 
 
 
 
1
+ title: Diet Planning Chatbot
2
+ emoji: 🥗
3
+ colorFrom: green
4
+ colorTo: blue
5
+ sdk: docker
6
+ app_port: 7860
7
+ pinned: false
rasa_app/__init__.py ADDED
@@ -0,0 +1 @@
 
 
1
+ # Rasa app package
rasa_app/actions/__init__.py ADDED
@@ -0,0 +1 @@
 
 
1
+ # Actions package
rasa_app/actions/actions.py ADDED
@@ -0,0 +1,174 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from typing import Any, Text, Dict, List
2
+ from rasa_sdk import Action, Tracker
3
+ from rasa_sdk.executor import CollectingDispatcher
4
+ from rasa_sdk.events import SlotSet
5
+ import cohere
6
+ import os
7
+ from dotenv import load_dotenv
8
+ import json
9
+ import markdown
10
+
11
+ load_dotenv()
12
+ COHERE_API_KEY = os.getenv("COHERE_API_KEY")
13
+
14
+ co = cohere.Client(COHERE_API_KEY)
15
+
16
+ def format_user_profile(tracker):
17
+ dietary_preference = tracker.get_slot("dietary_preference") or "not specified"
18
+ health_goal = tracker.get_slot("health_goal") or "not specified"
19
+ age = tracker.get_slot("age") or "not specified"
20
+ weight = tracker.get_slot("weight") or "not specified"
21
+ height = tracker.get_slot("height") or "not specified"
22
+ gender = tracker.get_slot("gender") or "not specified"
23
+ activity_level = tracker.get_slot("activity_level") or "not specified"
24
+ restrictions = tracker.get_slot("restrictions") or []
25
+ allergies = tracker.get_slot("allergies") or []
26
+
27
+ profile = {
28
+ "dietary_preference": dietary_preference,
29
+ "health_goal": health_goal,
30
+ "age": age,
31
+ "weight": weight,
32
+ "height": height,
33
+ "gender": gender,
34
+ "activity_level": activity_level,
35
+ "restrictions": restrictions,
36
+ "allergies": allergies
37
+ }
38
+
39
+ return profile
40
+
41
+ class ActionGenerateDietPlan(Action):
42
+ def name(self) -> Text:
43
+ return "action_generate_diet_plan"
44
+
45
+ def run(self, dispatcher: CollectingDispatcher,
46
+ tracker: Tracker,
47
+ domain: Dict[Text, Any]) -> List[Dict[Text, Any]]:
48
+
49
+ user_profile = format_user_profile(tracker)
50
+
51
+ prompt = f"""
52
+ Create a personalized weekly meal plan based on the following user information:
53
+
54
+ Dietary Preference: {user_profile['dietary_preference']}
55
+ Health Goal: {user_profile['health_goal']}
56
+ Age: {user_profile['age']}
57
+ Weight: {user_profile['weight']}
58
+ Height: {user_profile['height']}
59
+ Gender: {user_profile['gender']}
60
+ Activity Level: {user_profile['activity_level']}
61
+ Dietary Restrictions: {', '.join(user_profile['restrictions']) if user_profile['restrictions'] else 'None'}
62
+ Allergies: {', '.join(user_profile['allergies']) if user_profile['allergies'] else 'None'}
63
+
64
+ Generate a complete, well-structured meal plan with the following sections:
65
+ 1. Diet Overview - Brief summary of the diet approach and how it aligns with their goals and preferences
66
+ 2. Weekly Meal Plan - Detailed day-by-day plan with breakfast, lunch, dinner, and snacks
67
+ 3. General Recommendations - Additional advice, serving sizes, and nutrition tips
68
+
69
+ Format the response in Markdown with clear headers and bullet points.
70
+ """
71
+
72
+ try:
73
+ response = co.generate(
74
+ prompt=prompt,
75
+ model="command",
76
+ max_tokens=2000,
77
+ temperature=0.7,
78
+ )
79
+
80
+ diet_plan = response.generations[0].text
81
+
82
+ dispatcher.utter_message(text=diet_plan)
83
+
84
+ return [SlotSet("user_profile_complete", True)]
85
+
86
+ except Exception as e:
87
+ dispatcher.utter_message(text=f"I'm sorry, I couldn't generate a diet plan at the moment. Error: {str(e)}")
88
+ return []
89
+
90
+ class ActionAnswerDietQuestion(Action):
91
+ def name(self) -> Text:
92
+ return "action_answer_diet_question"
93
+
94
+ def run(self, dispatcher: CollectingDispatcher,
95
+ tracker: Tracker,
96
+ domain: Dict[Text, Any]) -> List[Dict[Text, Any]]:
97
+
98
+ last_message = tracker.latest_message.get("text")
99
+
100
+ prompt = f"""
101
+ Answer the following nutrition or diet-related question clearly and accurately:
102
+
103
+ Question: {last_message}
104
+
105
+ Provide a helpful, evidence-based response with practical advice when applicable.
106
+ If it would be beneficial, include a few bullet points with key takeaways.
107
+ """
108
+
109
+ try:
110
+ response = co.generate(
111
+ prompt=prompt,
112
+ model="command",
113
+ max_tokens=800,
114
+ temperature=0.7,
115
+ )
116
+
117
+ answer = response.generations[0].text
118
+
119
+ dispatcher.utter_message(text=answer)
120
+
121
+ return []
122
+
123
+ except Exception as e:
124
+ dispatcher.utter_message(text=f"I'm sorry, I couldn't answer your question at the moment. Error: {str(e)}")
125
+ return []
126
+
127
+ class ActionUpdateDietPlan(Action):
128
+ def name(self) -> Text:
129
+ return "action_update_diet_plan"
130
+
131
+ def run(self, dispatcher: CollectingDispatcher,
132
+ tracker: Tracker,
133
+ domain: Dict[Text, Any]) -> List[Dict[Text, Any]]:
134
+
135
+ user_request = tracker.latest_message.get("text")
136
+ user_profile = format_user_profile(tracker)
137
+
138
+ prompt = f"""
139
+ Update the previously generated meal plan based on the following user feedback:
140
+
141
+ User Profile:
142
+ Dietary Preference: {user_profile['dietary_preference']}
143
+ Health Goal: {user_profile['health_goal']}
144
+ Age: {user_profile['age']}
145
+ Weight: {user_profile['weight']}
146
+ Height: {user_profile['height']}
147
+ Gender: {user_profile['gender']}
148
+ Activity Level: {user_profile['activity_level']}
149
+ Dietary Restrictions: {', '.join(user_profile['restrictions']) if user_profile['restrictions'] else 'None'}
150
+ Allergies: {', '.join(user_profile['allergies']) if user_profile['allergies'] else 'None'}
151
+
152
+ User Feedback: {user_request}
153
+
154
+ Generate an updated meal plan that addresses the user's feedback while still keeping their health goals and dietary needs in mind.
155
+ Format the response in Markdown with clear headers and bullet points.
156
+ """
157
+
158
+ try:
159
+ response = co.generate(
160
+ prompt=prompt,
161
+ model="command",
162
+ max_tokens=2000,
163
+ temperature=0.7,
164
+ )
165
+
166
+ updated_plan = response.generations[0].text
167
+
168
+ dispatcher.utter_message(text=updated_plan)
169
+
170
+ return []
171
+
172
+ except Exception as e:
173
+ dispatcher.utter_message(text=f"I'm sorry, I couldn't update the diet plan at the moment. Error: {str(e)}")
174
+ return []
rasa_app/config.yml ADDED
@@ -0,0 +1,23 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ language: en
2
+
3
+ pipeline:
4
+ - name: WhitespaceTokenizer
5
+ - name: RegexFeaturizer
6
+ - name: LexicalSyntacticFeaturizer
7
+ - name: CountVectorsFeaturizer
8
+ - name: CountVectorsFeaturizer
9
+ analyzer: "char_wb"
10
+ min_ngram: 1
11
+ max_ngram: 4
12
+ - name: DIETClassifier
13
+ epochs: 100
14
+ - name: EntitySynonymMapper
15
+ - name: ResponseSelector
16
+ epochs: 100
17
+
18
+ policies:
19
+ - name: MemoizationPolicy
20
+ - name: TEDPolicy
21
+ max_history: 5
22
+ epochs: 100
23
+ - name: RulePolicy
rasa_app/credentials.yml ADDED
@@ -0,0 +1 @@
 
 
1
+ rest:
rasa_app/data/nlu/nlu.yml ADDED
@@ -0,0 +1,187 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ version: "3.1"
2
+
3
+ nlu:
4
+ - intent: greet
5
+ examples: |
6
+ - hey
7
+ - hello
8
+ - hi
9
+ - hello there
10
+ - good morning
11
+ - good evening
12
+ - hey there
13
+ - greetings
14
+ - hi there
15
+
16
+ - intent: goodbye
17
+ examples: |
18
+ - bye
19
+ - goodbye
20
+ - see you around
21
+ - see you later
22
+ - bye bye
23
+ - later
24
+ - exit
25
+ - quit
26
+
27
+ - intent: affirm
28
+ examples: |
29
+ - yes
30
+ - indeed
31
+ - of course
32
+ - that sounds good
33
+ - correct
34
+ - sure
35
+ - absolutely
36
+ - definitely
37
+ - yeah
38
+ - yep
39
+ - sounds good
40
+ - that's right
41
+ - ok
42
+ - okay
43
+ - that's correct
44
+ - you got it
45
+ - right
46
+ - perfect
47
+ - great
48
+
49
+ - intent: deny
50
+ examples: |
51
+ - no
52
+ - never
53
+ - I don't think so
54
+ - don't like that
55
+ - no way
56
+ - not really
57
+ - nope
58
+ - negative
59
+ - not correct
60
+ - that's wrong
61
+ - that's not right
62
+ - not interested
63
+ - nah
64
+ - no thanks
65
+
66
+ - intent: request_diet_plan
67
+ examples: |
68
+ - I need a diet plan
69
+ - Can you create a meal plan for me?
70
+ - I want a personalized diet
71
+ - I need help with meal planning
72
+ - Can you suggest a diet?
73
+ - Help me plan my meals
74
+ - I'm looking for nutritional advice
75
+ - Create a weekly meal plan for me
76
+ - I need a diet suggestion
77
+ - Can you recommend a meal plan?
78
+ - I want to improve my eating habits
79
+ - Help me eat better
80
+ - I need a food plan
81
+ - Give me a diet recommendation
82
+ - Plan my meals for the week
83
+ - What should I eat?
84
+ - What's a good diet for me?
85
+ - Can you make me a diet plan?
86
+
87
+ - intent: provide_dietary_preference
88
+ examples: |
89
+ - I'm [vegetarian](dietary_preference)
90
+ - I follow a [vegan](dietary_preference) diet
91
+ - I'm on a [keto](dietary_preference) diet
92
+ - I eat [paleo](dietary_preference)
93
+ - I'm on a [gluten-free](dietary_preference) diet
94
+ - I don't have any specific diet
95
+ - My diet is [low-carb](dietary_preference)
96
+ - I'm [pescatarian](dietary_preference)
97
+ - I eat a [Mediterranean](dietary_preference) diet
98
+ - I follow a [DASH](dietary_preference) diet
99
+ - I'm on a [plant-based](dietary_preference) diet
100
+ - I prefer a [flexitarian](dietary_preference) approach
101
+ - I follow a [high-protein](dietary_preference) diet
102
+ - I don't follow any specific [diet](dietary_preference)
103
+
104
+ - intent: provide_health_goal
105
+ examples: |
106
+ - I want to [lose weight](health_goal)
107
+ - I'm trying to [gain weight](health_goal)
108
+ - I need to [maintain my weight](health_goal)
109
+ - I'm looking to [build muscle](health_goal)
110
+ - I want to [improve my energy](health_goal)
111
+ - I need [better nutrition](health_goal)
112
+ - I want to eat for [better health](health_goal)
113
+ - I want to [manage my diabetes](health_goal)
114
+ - I'm trying to [lower my blood pressure](health_goal)
115
+ - I want to [reduce inflammation](health_goal)
116
+ - I need to [improve my gut health](health_goal)
117
+ - I'm looking to [enhance athletic performance](health_goal)
118
+ - I'm looking to [improve mental clarity](health_goal)
119
+ - I want to [reduce stress](health_goal)
120
+
121
+ - intent: provide_personal_info
122
+ examples: |
123
+ - I'm [25](age) years old, [65](weight) kg, [170](height) cm, [male](gender), [moderate](activity_level) activity
124
+ - [35](age) years old, [70](weight) kg, [175](height) cm, [female](gender), [sedentary](activity_level) lifestyle
125
+ - I'm [40](age), weight [80](weight) kg, height [180](height) cm, [male](gender), [very active](activity_level)
126
+ - [19](age) years, [55](weight) kg, [165](height) cm, [female](gender), [lightly active](activity_level)
127
+ - I'm [30](age) years old, [75](weight) kg, [178](height) cm, [non-binary](gender), [active](activity_level)
128
+ - Age [45](age), weight [90](weight) kg, [185](height) cm tall, [male](gender), [sedentary](activity_level)
129
+ - I'm [27](age), [68](weight) kilos, [172](height) centimeters, [female](gender), [highly active](activity_level)
130
+ - [50](age) years, [82](weight) kg, [176](height) cm, [male](gender), [moderately active](activity_level)
131
+ - Age is [22](age), weight is [58](weight) kg, height is [160](height) cm, [female](gender), [active](activity_level)
132
+ - intent: provide_restrictions
133
+ examples: |
134
+ - I have [lactose intolerance](restriction)
135
+ - I need to avoid [high sodium](restriction) foods
136
+ - I can't eat foods with [added sugar](restriction)
137
+ - I have to follow a [low FODMAP](restriction) diet
138
+ - I need [low carb](restriction) options
139
+ - I have [celiac disease](restriction) so I can't have gluten
140
+ - I need to avoid [high cholesterol](restriction) foods
141
+ - I have [IBS](restriction) so I need to be careful
142
+ - I need a [low histamine](restriction) diet
143
+ - I have to watch my [oxalate](restriction) intake
144
+ - I'm on a [low residue](restriction) diet
145
+ - I need a [low acidic](restriction) diet
146
+ - I have [fructose malabsorption](restriction)
147
+ - I need [kidney-friendly](restriction) options
148
+ - I require a [renal diet](restriction)
149
+ - I have [diverticulitis](restriction)
150
+ - I'm on a [low iodine](restriction) diet
151
+
152
+ - intent: provide_allergies
153
+ examples: |
154
+ - I'm allergic to [nuts](allergy)
155
+ - I have a [shellfish](allergy) allergy
156
+ - I can't eat [eggs](allergy)
157
+ - I have a [dairy](allergy) allergy
158
+ - I'm allergic to [wheat](allergy)
159
+ - I can't have [soy](allergy)
160
+ - I have a [fish](allergy) allergy
161
+ - I'm allergic to [peanuts](allergy)
162
+ - I can't eat [sesame](allergy)
163
+ - I have an [almond](allergy) allergy
164
+ - I'm allergic to [mustard](allergy)
165
+ - I'm allergic to [molluscs](allergy)
166
+ - I can't eat [sulfites](allergy)
167
+ - I have a [corn](allergy) allergy
168
+ - I have a [banana](allergy) allergy
169
+ - I'm allergic to [latex fruits](allergy)
170
+
171
+ - intent: ask_diet_question
172
+ examples: |
173
+ - What foods are high in protein?
174
+ - How many calories should I consume daily?
175
+ - Is intermittent fasting effective?
176
+ - What's the best time to eat before a workout?
177
+ - Are eggs healthy?
178
+ - How much water should I drink daily?
179
+ - What are good sources of fiber?
180
+ - What should I eat before bed?
181
+ - How can I increase my metabolism?
182
+ - What's the healthiest cooking oil?
183
+ - How much protein do I need daily?
184
+ - What supplements should I take?
185
+ - What fruits are lowest in sugar?
186
+ - Is dairy necessary for calcium?
187
+ - What's the best diet for heart health?
rasa_app/data/rules/rules.yml ADDED
@@ -0,0 +1,28 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ version: "3.1"
2
+
3
+ rules:
4
+ - rule: Say goodbye anytime the user says goodbye
5
+ steps:
6
+ - intent: goodbye
7
+ - action: utter_goodbye
8
+
9
+ - rule: Say hello anytime the user says hello
10
+ steps:
11
+ - intent: greet
12
+ - action: utter_greet
13
+
14
+ - rule: Answer diet questions
15
+ steps:
16
+ - intent: ask_diet_question
17
+ - action: action_answer_diet_question
18
+
19
+ - rule: Provide recommendation when asked
20
+ steps:
21
+ - intent: ask_for_recommendation
22
+ - action: action_answer_diet_question
23
+
24
+ - rule: Handle changes to diet plan
25
+ steps:
26
+ - intent: ask_for_changes
27
+ - action: utter_acknowledge_changes
28
+ - action: action_update_diet_plan
rasa_app/data/stories/stories.yml ADDED
@@ -0,0 +1,91 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ version: "3.1"
2
+
3
+ stories:
4
+ - story: happy path - dietary planning
5
+ steps:
6
+ - intent: greet
7
+ - action: utter_greet
8
+ - intent: request_diet_plan
9
+ - action: utter_ask_dietary_preference
10
+ - intent: provide_dietary_preference
11
+ - action: utter_ask_health_goal
12
+ - intent: provide_health_goal
13
+ - action: utter_ask_personal_info
14
+ - intent: provide_personal_info
15
+ - action: utter_ask_restrictions
16
+ - intent: provide_restrictions
17
+ - action: utter_ask_allergies
18
+ - intent: provide_allergies
19
+ - action: utter_confirm_information
20
+ - intent: affirm
21
+ - action: utter_generating_plan
22
+ - action: action_generate_diet_plan
23
+ - intent: ask_for_changes
24
+ - action: utter_ask_for_changes
25
+ - intent: provide_dietary_preference
26
+ - action: utter_acknowledge_changes
27
+ - action: action_update_diet_plan
28
+
29
+ - story: direct diet plan request
30
+ steps:
31
+ - intent: request_diet_plan
32
+ - action: utter_ask_dietary_preference
33
+ - intent: provide_dietary_preference
34
+ - action: utter_ask_health_goal
35
+ - intent: provide_health_goal
36
+ - action: utter_ask_personal_info
37
+ - intent: provide_personal_info
38
+ - action: utter_ask_restrictions
39
+ - intent: provide_restrictions
40
+ - action: utter_ask_allergies
41
+ - intent: provide_allergies
42
+ - action: utter_confirm_information
43
+ - intent: affirm
44
+ - action: utter_generating_plan
45
+ - action: action_generate_diet_plan
46
+
47
+ - story: diet plan with no restrictions or allergies
48
+ steps:
49
+ - intent: greet
50
+ - action: utter_greet
51
+ - intent: request_diet_plan
52
+ - action: utter_ask_dietary_preference
53
+ - intent: provide_dietary_preference
54
+ - action: utter_ask_health_goal
55
+ - intent: provide_health_goal
56
+ - action: utter_ask_personal_info
57
+ - intent: provide_personal_info
58
+ - action: utter_ask_restrictions
59
+ - intent: deny
60
+ - action: utter_ask_allergies
61
+ - intent: deny
62
+ - action: utter_confirm_information
63
+ - intent: affirm
64
+ - action: utter_generating_plan
65
+ - action: action_generate_diet_plan
66
+
67
+ - story: ask diet question
68
+ steps:
69
+ - intent: ask_diet_question
70
+ - action: action_answer_diet_question
71
+
72
+ - story: ask for recommendation
73
+ steps:
74
+ - intent: ask_for_recommendation
75
+ - action: action_answer_diet_question
76
+
77
+ - story: reject generated plan and request changes
78
+ steps:
79
+ - action: action_generate_diet_plan
80
+ - intent: deny
81
+ - action: utter_ask_for_changes
82
+ - intent: ask_for_changes
83
+ - action: utter_acknowledge_changes
84
+ - action: action_update_diet_plan
85
+
86
+ - story: greet and goodbye
87
+ steps:
88
+ - intent: greet
89
+ - action: utter_greet
90
+ - intent: goodbye
91
+ - action: utter_goodbye
rasa_app/domain.yml ADDED
@@ -0,0 +1,138 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ version: "3.1"
2
+
3
+ intents:
4
+ - greet
5
+ - goodbye
6
+ - affirm
7
+ - deny
8
+ - request_diet_plan
9
+ - provide_dietary_preference
10
+ - provide_health_goal
11
+ - provide_personal_info
12
+ - provide_restrictions
13
+ - provide_allergies
14
+ - ask_diet_question
15
+ - ask_for_changes
16
+ - ask_for_recommendation
17
+
18
+ entities:
19
+ - dietary_preference
20
+ - health_goal
21
+ - age
22
+ - weight
23
+ - height
24
+ - gender
25
+ - activity_level
26
+ - restriction
27
+ - allergy
28
+
29
+ slots:
30
+ dietary_preference:
31
+ type: text
32
+ influence_conversation: true
33
+ mappings:
34
+ - type: from_entity
35
+ entity: dietary_preference
36
+ health_goal:
37
+ type: text
38
+ influence_conversation: true
39
+ mappings:
40
+ - type: from_entity
41
+ entity: health_goal
42
+ age:
43
+ type: text
44
+ influence_conversation: false
45
+ mappings:
46
+ - type: from_entity
47
+ entity: age
48
+ weight:
49
+ type: text
50
+ influence_conversation: false
51
+ mappings:
52
+ - type: from_entity
53
+ entity: weight
54
+ height:
55
+ type: text
56
+ influence_conversation: false
57
+ mappings:
58
+ - type: from_entity
59
+ entity: height
60
+ gender:
61
+ type: text
62
+ influence_conversation: false
63
+ mappings:
64
+ - type: from_entity
65
+ entity: gender
66
+ activity_level:
67
+ type: text
68
+ influence_conversation: false
69
+ mappings:
70
+ - type: from_entity
71
+ entity: activity_level
72
+ restrictions:
73
+ type: list
74
+ influence_conversation: true
75
+ mappings:
76
+ - type: from_entity
77
+ entity: restriction
78
+ allergies:
79
+ type: list
80
+ influence_conversation: true
81
+ mappings:
82
+ - type: from_entity
83
+ entity: allergy
84
+ user_profile_complete:
85
+ type: bool
86
+ initial_value: false
87
+ influence_conversation: true
88
+ mappings:
89
+ - type: custom
90
+
91
+ responses:
92
+ utter_greet:
93
+ - text: "Hello! I'm your diet planning assistant. I can help you create a personalized meal plan. Would you like me to create a diet plan for you?"
94
+
95
+ utter_goodbye:
96
+ - text: "Goodbye! Feel free to come back anytime for diet advice."
97
+
98
+ utter_ask_dietary_preference:
99
+ - text: "What type of diet are you following? (e.g., vegetarian, vegan, keto, paleo, gluten-free, or no specific diet)"
100
+
101
+ utter_ask_health_goal:
102
+ - text: "What's your health goal? (e.g., weight loss, weight gain, maintenance, muscle building, improved energy)"
103
+
104
+ utter_ask_personal_info:
105
+ - text: "To provide the most accurate recommendations, I need some basic information. Could you share your age, weight, height, gender, and activity level? For example: '35 years old, 70kg, 175cm, male, moderate activity'"
106
+
107
+ utter_ask_restrictions:
108
+ - text: "Do you have any dietary restrictions I should be aware of? (e.g., lactose intolerance, low sodium, low sugar)"
109
+
110
+ utter_ask_allergies:
111
+ - text: "Do you have any food allergies? (e.g., nuts, shellfish, eggs, dairy)"
112
+
113
+ utter_confirm_information:
114
+ - text: "I've collected the following information:\nDietary preference: {dietary_preference}\nHealth goal: {health_goal}\nAge: {age}\nWeight: {weight}\nHeight: {height}\nGender: {gender}\nActivity level: {activity_level}\nRestrictions: {restrictions}\nAllergies: {allergies}\n\nIs this information correct? I'll use it to create your personalized diet plan."
115
+
116
+ utter_generating_plan:
117
+ - text: "Thanks for confirming! I'm now generating your personalized diet plan based on your information. This will just take a moment..."
118
+
119
+ utter_ask_diet_question:
120
+ - text: "I'd be happy to answer your diet-related questions. What would you like to know?"
121
+
122
+ utter_ask_for_changes:
123
+ - text: "Would you like to make any changes to the diet plan I've suggested?"
124
+
125
+ utter_acknowledge_changes:
126
+ - text: "I'll adjust the diet plan based on your feedback. Let me update it for you."
127
+
128
+ utter_default:
129
+ - text: "I'm not sure I understand. Could you rephrase that?"
130
+
131
+ actions:
132
+ - action_generate_diet_plan
133
+ - action_answer_diet_question
134
+ - action_update_diet_plan
135
+
136
+ session_config:
137
+ session_expiration_time: 60
138
+ carry_over_slots_to_new_session: true
rasa_app/endpoints.yml ADDED
@@ -0,0 +1,2 @@
 
 
 
1
+ action_endpoint:
2
+ url: "http://localhost:5055/webhook"
requirements.txt ADDED
@@ -0,0 +1,5 @@
 
 
 
 
 
 
1
+ gradio==3.41.0
2
+ cohere==4.27
3
+ python-dotenv==1.0.0
4
+ requests==2.31.0
5
+ markdown==3.4.3
run.sh ADDED
@@ -0,0 +1,15 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #!/bin/bash
2
+
3
+ if [ ! -f .env ]; then
4
+ cp .env.example .env
5
+ exit 1
6
+ fi
7
+
8
+ cd rasa_app && rasa run --enable-api --cors "*" &
9
+ RASA_PID=$!
10
+
11
+ sleep 5
12
+
13
+ cd .. && python app.py
14
+
15
+ trap "kill $RASA_PID" EXIT
train_rasa.py ADDED
@@ -0,0 +1,31 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os
2
+ import subprocess
3
+ import sys
4
+
5
+ def train_rasa_model():
6
+
7
+ os.chdir('./rasa_app')
8
+
9
+ try:
10
+ result = subprocess.run(
11
+ ["python", "-m", "rasa", "train"],
12
+ check=True,
13
+ stdout=subprocess.PIPE,
14
+ stderr=subprocess.PIPE,
15
+ text=True
16
+ )
17
+
18
+ if result.returncode == 0:
19
+ return True
20
+ else:
21
+ return False
22
+
23
+ except subprocess.CalledProcessError as e:
24
+ return False
25
+ except Exception as e:
26
+ return False
27
+
28
+ if __name__ == "__main__":
29
+ success = train_rasa_model()
30
+ if not success:
31
+ sys.exit(1)