Swathi6 commited on
Commit
7f366a4
·
verified ·
1 Parent(s): 9afd8d0

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +308 -36
app.py CHANGED
@@ -1,47 +1,319 @@
1
  from flask import Flask, render_template, request, jsonify
 
 
 
 
 
 
 
2
 
3
- app = Flask(__name__)
4
-
5
- # Basic logic for chatbot responses
6
- def bot_response(user_message):
7
- lower_case_message = user_message.lower()
8
- response = ""
9
-
10
- # Simple responses based on user input
11
- if "hello" in lower_case_message or "hi" in lower_case_message:
12
- response = "Hello! Welcome to our restaurant. How can I assist you today?"
13
- elif "menu" in lower_case_message:
14
- response = "Our menu includes: Pizza, Pasta, Burger, Salad, and Desserts. What would you like to order?"
15
- elif "order" in lower_case_message or "buy" in lower_case_message:
16
- response = "What would you like to order from the menu?"
17
- elif "pizza" in lower_case_message:
18
- response = "Great choice! Our pizzas are delicious. Would you like a small, medium, or large pizza?"
19
- elif "pasta" in lower_case_message:
20
- response = "Yum! Our pasta is freshly made. Would you like it with marinara sauce or Alfredo?"
21
- elif "burger" in lower_case_message:
22
- response = "Our burgers are served with fries. Would you like a vegetarian or beef burger?"
23
- elif "salad" in lower_case_message:
24
- response = "We have a variety of salads. Would you like a Caesar salad or a garden salad?"
25
- elif "dessert" in lower_case_message:
26
- response = "For dessert, we have cakes, ice cream, and pie. What would you like to try?"
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
27
  else:
28
- response = "I'm sorry, I didn't quite get that. Can you please repeat?"
 
 
 
29
 
30
- return response
 
 
 
 
 
 
 
 
 
 
 
 
 
31
 
32
- # Home route to serve the chatbot's HTML page
33
  @app.route('/')
34
  def index():
35
  return render_template('index.html')
36
 
37
- # API route for handling user input and getting the bot's response
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
38
  @app.route('/chat', methods=['POST'])
39
  def chat():
40
- user_message = request.json.get('message')
41
- if user_message:
42
- response = bot_response(user_message)
43
- return jsonify({'response': response})
44
- return jsonify({'response': 'Sorry, I could not understand that.'})
45
-
46
- if __name__ == "__main__":
47
- app.run(debug=True)
 
 
 
 
1
  from flask import Flask, render_template, request, jsonify
2
+ from simple_salesforce import Salesforce
3
+ from dotenv import load_dotenv
4
+ import os
5
+ import logging
6
+ import uuid
7
+ from datetime import datetime
8
+ from openai import OpenAI
9
 
10
+ # Load environment variables
11
+ load_dotenv()
12
+
13
+ # Set up logging
14
+ logging.basicConfig(level=logging.INFO)
15
+ logger = logging.getLogger(__name__)
16
+
17
+ app = Flask(__name__, template_folder='templates', static_folder='static')
18
+
19
+ # Salesforce connection function
20
+ def get_salesforce_connection():
21
+ try:
22
+ sf = Salesforce(
23
+ username=os.getenv('SFDC_USERNAME'),
24
+ password=os.getenv('SFDC_PASSWORD'),
25
+ security_token=os.getenv('SFDC_SECURITY_TOKEN'),
26
+ domain=os.getenv('SFDC_DOMAIN', 'login')
27
+ )
28
+ logger.info("Successfully connected to Salesforce")
29
+ return sf
30
+ except Exception as e:
31
+ logger.error(f"Error connecting to Salesforce: {e}")
32
+ return None
33
+
34
+ # Initialize Salesforce connection
35
+ sf = get_salesforce_connection()
36
+
37
+ # Initialize OpenAI client with your API key
38
+ openai_api_key = os.getenv('OPENAI_API_KEY', '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')
39
+ if not openai_api_key:
40
+ logger.error("OPENAI_API_KEY not found in .env. ChatGPT functionality disabled.")
41
+ client = None
42
+ else:
43
+ try:
44
+ client = OpenAI(api_key=openai_api_key)
45
+ test_response = client.chat.completions.create(
46
+ model="gpt-3.5-turbo",
47
+ messages=[{"role": "user", "content": "Test API key"}]
48
+ )
49
+ logger.info("OpenAI API key validated successfully")
50
+ except Exception as e:
51
+ logger.error(f"Invalid OpenAI API key or connection issue: {e}")
52
+ client = None
53
+
54
+ # Conversation storage
55
+ conversation_sessions = {}
56
+
57
+ def is_restaurant_related(query):
58
+ keywords = ['use', 'uses', 'dish', 'recipe', 'ingredient', 'food', 'menu', 'vegetarian', 'non-vegetarian',
59
+ 'rice', 'chicken', 'pasta', 'veggie', 'mutton', 'lamb', 'beef', 'pork', 'fish', 'seafood',
60
+ 'ingredients', 'nutrition', 'nutritional', 'info', 'message', 'messages']
61
+ return bool(query.strip() and any(keyword in query.lower() for keyword in keywords)) or any(item in query.lower() for item in ['mutton', 'rice', 'chicken'])
62
+
63
+ def get_chatgpt_response(prompt, session_id):
64
+ if not client:
65
+ logger.warning("No OpenAI client available, using mock ChatGPT response")
66
+ # Mock ChatGPT response as fallback
67
+ if any(item in prompt.lower() for item in ['mutton', 'rice', 'chicken']):
68
+ return f"{prompt.capitalize()} is great for curries or roasts in a restaurant!"
69
+ return "I can help with food! Try 'uses of mutton' or 'ingredients for rice'."
70
+
71
+ if session_id not in conversation_sessions:
72
+ conversation_sessions[session_id] = [
73
+ {"role": "system", "content": "You are a restaurant culinary assistant. Respond only to queries about ingredients, dishes, or recipes. Provide concise, friendly answers. For unclear queries, suggest: 'Try 'uses of mutton' or 'ingredients for rice'.'"}
74
+ ]
75
+
76
+ prompt = prompt.strip().lower()
77
+ logger.info(f"Processing prompt: {prompt}")
78
+ if not is_restaurant_related(prompt):
79
+ logger.info(f"Off-topic or empty query: {prompt}")
80
+ return "I can help with food! Try 'uses of mutton' or 'ingredients for rice'."
81
+
82
+ # Detect intent with fallback to uses for food items
83
+ intent = "uses"
84
+ item = prompt
85
+ if "what is the use of" in prompt or "uses of" in prompt:
86
+ item = prompt.replace("what is the use of ", "").replace("uses of ", "").strip() or prompt
87
+ prompt = f"Provide the culinary uses of '{item}' for a restaurant. Be concise and friendly. If unknown, say 'Great for many dishes!'"
88
+ elif any(word in prompt for word in ['suggest', 'recipe', 'dish']):
89
+ intent = "suggest"
90
+ prompt = f"Suggest a restaurant dish based on: {prompt}. Include ingredients and be concise."
91
+ elif any(word in prompt for word in ['ingredients', 'ingredient']):
92
+ intent = "ingredients"
93
+ item = prompt.replace("ingredients for ", "").replace("ingredient of ", "").strip() or prompt
94
+ prompt = f"List common ingredients for a restaurant dish using '{item}'. Be concise and realistic."
95
+ elif any(word in prompt for word in ['nutrition', 'nutritional', 'info']):
96
+ intent = "nutrition"
97
+ item = prompt.replace("nutrition of ", "").replace("nutritional info for ", "").strip() or prompt
98
+ prompt = f"Provide a concise, approximate nutritional overview (calories, protein, fat, carbs) for a restaurant portion of '{item}'. Use general culinary knowledge and keep it friendly."
99
+ elif any(item in prompt for item in ['mutton', 'rice', 'chicken', 'pasta', 'veggie', 'lamb', 'beef', 'pork', 'fish', 'seafood']):
100
+ prompt = f"Provide the culinary uses of '{item}' for a restaurant. Be concise and friendly. If unknown, say 'Great for many dishes!'"
101
  else:
102
+ logger.info(f"Unclear intent, defaulting to uses for: {prompt}")
103
+ prompt = f"Provide the culinary uses of '{prompt}' for a restaurant. Be concise and friendly. If unknown, say 'Great for many dishes!'"
104
+
105
+ conversation_sessions[session_id].append({"role": "user", "content": prompt})
106
 
107
+ try:
108
+ response = client.chat.completions.create(
109
+ model="gpt-3.5-turbo",
110
+ messages=conversation_sessions[session_id],
111
+ max_tokens=150,
112
+ timeout=10
113
+ )
114
+ reply = response.choices[0].message.content.strip()
115
+ conversation_sessions[session_id].append({"role": "assistant", "content": reply})
116
+ logger.info(f"ChatGPT response for '{prompt}': {reply}")
117
+ return reply
118
+ except Exception as e:
119
+ logger.error(f"OpenAI API error: {e}")
120
+ return f"Sorry, API failed. Mock response: {prompt.capitalize()} is great for curries or roasts!"
121
 
 
122
  @app.route('/')
123
  def index():
124
  return render_template('index.html')
125
 
126
+ @app.route('/get_menu_items', methods=['POST'])
127
+ def get_menu_items():
128
+ global sf
129
+ if not sf:
130
+ sf = get_salesforce_connection()
131
+ if not sf:
132
+ return jsonify({"error": "Unable to connect to Salesforce"}), 500
133
+
134
+ dietary_preference = request.json.get('dietary_preference', 'both').lower()
135
+ try:
136
+ soql = "SELECT Name, Image_URL__c, Category__c, Description__c FROM Sector_Detail__c"
137
+ if dietary_preference == 'vegetarian':
138
+ soql += " WHERE Category__c = 'Veg'"
139
+ elif dietary_preference == 'non-vegetarian':
140
+ soql += " WHERE Category__c = 'Non-Veg'"
141
+ soql += " LIMIT 200"
142
+ result = sf.query(soql)
143
+ items = [{"name": r['Name'], "image_url": r.get('Image_URL__c', ''), "category": r.get('Category__c', ''), "description": r.get('Description__c', 'No description')} for r in result['records'] if 'Name' in r]
144
+ return jsonify({"menu_items": items})
145
+ except Exception as e:
146
+ logger.error(f"Failed to fetch items: {e}")
147
+ return jsonify({"error": f"Failed to fetch items: {e}"}), 500
148
+
149
+ @app.route('/get_sector_item_details', methods=['POST'])
150
+ def get_sector_item_details():
151
+ global sf
152
+ if not sf:
153
+ sf = get_salesforce_connection()
154
+ if not sf:
155
+ return jsonify({"error": "Unable to connect to Salesforce"}), 500
156
+
157
+ item_name = request.json.get('item_name', '').strip()
158
+ if not item_name:
159
+ return jsonify({"error": "Item name is required"}), 400
160
+
161
+ try:
162
+ soql = f"SELECT Name, Image_URL__c, Category__c, Description__c FROM Sector_Detail__c WHERE Name LIKE '%{item_name}%' LIMIT 1"
163
+ logger.info(f"Executing SOQL query: {soql}")
164
+ result = sf.query(soql)
165
+
166
+ if result['totalSize'] == 0:
167
+ return jsonify({"error": f"No item found matching '{item_name}' in Sector_Detail__c"}), 404
168
+
169
+ record = result['records'][0]
170
+ item_details = {
171
+ "name": record.get('Name', ''),
172
+ "image_url": record.get('Image_URL__c', 'https://via.placeholder.com/30'),
173
+ "category": record.get('Category__c', ''),
174
+ "description": record.get('Description__c', 'No description available')
175
+ }
176
+ logger.info(f"Fetched details for '{item_name}' from Sector_Detail__c")
177
+ return jsonify({"item_details": item_details})
178
+ except Exception as e:
179
+ logger.error(f"Failed to fetch item details from Sector_Detail__c: {e}")
180
+ return jsonify({"error": f"Failed to fetch item details: {e}"}), 500
181
+
182
+ @app.route('/suggest_items', methods=['POST'])
183
+ def suggest_items():
184
+ global sf
185
+ if not sf:
186
+ sf = get_salesforce_connection()
187
+ if not sf:
188
+ return jsonify({"error": "Unable to connect to Salesforce"}), 500
189
+
190
+ search_term = request.json.get('search_term', '').strip()
191
+ if not search_term:
192
+ return jsonify({"error": "Search term is required"}), 400
193
+
194
+ try:
195
+ soql = f"SELECT Ingredient_Name__c, Image_URL__c FROM Ingredient_Object__c WHERE Ingredient_Name__c LIKE '%{search_term}%' LIMIT 10"
196
+ logger.info(f"Executing SOQL query: {soql}")
197
+ result = sf.query(soql)
198
+ suggestions = [
199
+ {"name": record['Ingredient_Name__c'], "image_url": record.get('Image_URL__c', '')}
200
+ for record in result['records'] if 'Ingredient_Name__c' in record
201
+ ]
202
+ logger.info(f"Fetched {len(suggestions)} suggestions for '{search_term}'")
203
+ return jsonify({"suggestions": suggestions})
204
+ except Exception as e:
205
+ logger.error(f"Failed to fetch suggestions: {e}")
206
+ return jsonify({"error": f"Failed to fetch suggestions: {e}"}), 500
207
+
208
+ @app.route('/get_item_details', methods=['POST'])
209
+ def get_item_details():
210
+ global sf
211
+ if not sf:
212
+ sf = get_salesforce_connection()
213
+ if not sf:
214
+ return jsonify({"error": "Unable to connect to Salesforce"}), 500
215
+
216
+ item_name = request.json.get('item_name', '').strip()
217
+ if not item_name:
218
+ return jsonify({"error": "Item name is required"}), 400
219
+
220
+ try:
221
+ soql = f"SELECT Ingredient_Name__c, Image_URL__c FROM Ingredient_Object__c WHERE Ingredient_Name__c LIKE '%{item_name}%' LIMIT 1"
222
+ logger.info(f"Executing SOQL query: {soql}")
223
+ result = sf.query(soql)
224
+
225
+ if result['totalSize'] == 0:
226
+ return jsonify({"error": f"No item found matching '{item_name}' in Ingredient_Object__c"}), 404
227
+
228
+ record = result['records'][0]
229
+ item_details = {
230
+ "name": record.get('Ingredient_Name__c', ''),
231
+ "image_url": record.get('Image_URL__c', '')
232
+ }
233
+ logger.info(f"Fetched details for '{item_name}'")
234
+ return jsonify({"item_details": item_details})
235
+ except Exception as e:
236
+ logger.error(f"Failed to fetch item details: {e}")
237
+ return jsonify({"error": f"Failed to fetch item details: {e}"}), 500
238
+
239
+ @app.route('/submit_items', methods=['POST'])
240
+ def submit_items():
241
+ global sf
242
+ if not sf:
243
+ sf = get_salesforce_connection()
244
+ if not sf:
245
+ return jsonify({"error": "Unable to connect to Salesforce"}), 500
246
+
247
+ items = request.json.get('items', [])
248
+ custom_order_name = request.json.get('custom_order_name', '')
249
+ if not items:
250
+ return jsonify({"error": "No items to submit"}), 400
251
+
252
+ try:
253
+ ingredient_name = custom_order_name or f"Order_{datetime.now().strftime('%Y%m%d')}_{uuid.uuid4().hex[:8]}"
254
+ item_names = ', '.join(item['name'] for item in items)
255
+ description = f"Contains: {item_names}"
256
+
257
+ for item in items:
258
+ sf.Ingredient_Object__c.create({
259
+ 'Ingredient_Name__c': ingredient_name,
260
+ 'Category__c': item.get('category', ''),
261
+ 'Description__c': f"{item.get('description', 'No description')} - {description}",
262
+ 'Image_URL__c': item.get('image_url', ''),
263
+ 'Quantity__c': item.get('quantity', 1)
264
+ })
265
+
266
+ return jsonify({"success": f"Submitted {len(items)} items under {ingredient_name}", "ingredient_name": ingredient_name})
267
+ except Exception as e:
268
+ logger.error(f"Failed to submit items: {e}")
269
+ return jsonify({"error": f"Failed to submit items: {e}"}), 500
270
+
271
+ @app.route('/get_item_info', methods=['POST'])
272
+ def get_item_info():
273
+ global sf, client
274
+ item_name = request.json.get('item_name', '').strip()
275
+ if not item_name or not client:
276
+ return jsonify({"error": "Item name required or OpenAI unavailable"}), 400
277
+
278
+ try:
279
+ soql = f"SELECT Name, Description__c FROM Sector_Detail__c WHERE Name LIKE '%{item_name}%' LIMIT 1"
280
+ result = sf.query(soql)
281
+ if result['totalSize'] == 0:
282
+ return jsonify({"error": f"No item found matching '{item_name}'"}), 404
283
+
284
+ record = result['records'][0]
285
+ base_info = record.get('Description__c', 'No description available')
286
+
287
+ prompt = f"Based on general culinary knowledge, provide a concise list of common ingredients and an approximate nutritional overview (calories, protein, fat, carbs) for a restaurant portion of '{item_name}'. Use realistic values and keep it friendly."
288
+ response = client.chat.completions.create(
289
+ model="gpt-3.5-turbo",
290
+ messages=[{"role": "user", "content": prompt}],
291
+ max_tokens=150,
292
+ timeout=10
293
+ )
294
+ ai_response = response.choices[0].message.content.strip()
295
+
296
+ item_info = {
297
+ "name": record['Name'],
298
+ "description": base_info,
299
+ "details": ai_response
300
+ }
301
+ logger.info(f"Generated info for '{item_name}'")
302
+ return jsonify({"item_info": item_info})
303
+ except Exception as e:
304
+ logger.error(f"Failed to get item info: {e}")
305
+ return jsonify({"error": f"Failed to get item info: {e}"}), 500
306
+
307
  @app.route('/chat', methods=['POST'])
308
  def chat():
309
+ user_message = request.json.get('message', '').strip()
310
+ session_id = request.json.get('session_id', 'default')
311
+ if not user_message:
312
+ return jsonify({"error": "No message provided"}), 400
313
+
314
+ response = get_chatgpt_response(user_message, session_id)
315
+ logger.info(f"Chat response sent: {response}")
316
+ return jsonify({"response": response})
317
+
318
+ if __name__ == '__main__':
319
+ app.run(debug=True, host='0.0.0.0', port=7860)