Spaces:
Sleeping
Sleeping
kissmihalyit
commited on
Commit
·
ea3f136
1
Parent(s):
94bf407
refactored code
Browse files- Dockerfile +15 -0
- Dockerfile.rasa +19 -0
- README.md +7 -3
- app.py +506 -0
- docker-compose.yml +37 -0
- huggingface-space.yml +7 -0
- rasa_app/__init__.py +1 -0
- rasa_app/actions/__init__.py +1 -0
- rasa_app/actions/actions.py +174 -0
- rasa_app/config.yml +23 -0
- rasa_app/credentials.yml +1 -0
- rasa_app/data/nlu/nlu.yml +187 -0
- rasa_app/data/rules/rules.yml +28 -0
- rasa_app/data/stories/stories.yml +91 -0
- rasa_app/domain.yml +138 -0
- rasa_app/endpoints.yml +2 -0
- requirements.txt +5 -0
- run.sh +15 -0
- train_rasa.py +31 -0
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:
|
3 |
-
emoji:
|
4 |
colorFrom: green
|
5 |
colorTo: blue
|
6 |
sdk: docker
|
|
|
|
|
7 |
pinned: false
|
8 |
---
|
9 |
|
10 |
-
|
|
|
|
|
|
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)
|