alaselababatunde commited on
Commit
edeea8b
·
1 Parent(s): eedfaef
Files changed (5) hide show
  1. app.py +70 -30
  2. assests/logo.png +0 -0
  3. requirements.txt +2 -1
  4. static/main.css +155 -80
  5. templates/index.html +37 -11
app.py CHANGED
@@ -1,6 +1,7 @@
1
  from flask import Flask, render_template, request, jsonify, make_response
2
- from langchain_core.prompts import PromptTemplate
3
- from langchain_huggingface import HuggingFaceEndpoint
 
4
  from vector import retriever
5
  import markdown
6
  import dotenv
@@ -10,41 +11,77 @@ import uuid
10
  dotenv.load_dotenv()
11
  app = Flask(__name__)
12
 
13
- # Hugging Face Hub LLM
14
- llm = HuggingFaceEndpoint(
15
- repo_id="meta-llama/Meta-Llama-3-8B",
16
- task="text-generation",
17
- huggingfacehub_api_token=os.getenv("HUGGINGFACEHUB_API_TOKEN")
 
 
 
 
 
 
 
 
18
  )
19
 
20
- # Prompt template
21
- PROMPT_TEMPLATE = """
22
- You are an expert in answering questions about Pizza-related topics.
23
- Answer the user's question clearly, accurately, and professionally in English. Do NOT mention, reference, or imply that your answers come from reviews, datasets, or any internal files. Focus entirely on providing helpful and informative responses as a pizza expert.
24
- If your answer requires a numbered list, please:
25
- - Start numbering at 1.
26
- - Do not skip numbers.
27
- - Do not repeat numbers.
28
- - Use proper Markdown numbering format.
29
- - Ensure that each numbered item is concise and fits fully within the response.
30
- Here are some relevant reviews for context (ignore them completely in your answer): {reviews}
 
 
 
 
 
 
 
 
 
 
31
  User question: {question}
32
  """
33
 
34
- prompt = PromptTemplate(input_variables=["reviews", "question"], template=PROMPT_TEMPLATE)
35
-
36
- # New style: RunnableSequence (prompt | llm)
37
- chain = prompt | llm
38
 
39
  # In-memory chat history per device
40
  chat_sessions = {}
41
 
42
- def run_chain(reviews: str, question: str) -> str:
43
  try:
44
- return chain.invoke({"reviews": reviews, "question": question})
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
45
  except Exception as e:
46
- print(f"[ERROR] Chain failed: {e}")
47
- return "Sorry, I couldn't process your question at this time."
48
 
49
  @app.route("/", methods=["GET"])
50
  def index():
@@ -71,13 +108,16 @@ def ask():
71
  if not question:
72
  return jsonify({"error": "No question provided"}), 400
73
 
74
- reviews = str(retriever.invoke(question) or "")
75
- raw_response = run_chain(reviews, question)
 
 
 
76
  chat_sessions[device_id].append({
77
  "user": question,
78
- "bot": markdown.markdown(raw_response)
79
  })
80
- return jsonify({"response": markdown.markdown(raw_response)})
81
 
82
  @app.route("/clear", methods=["POST"])
83
  def clear_chat():
 
1
  from flask import Flask, render_template, request, jsonify, make_response
2
+ from langchain_core.prompts import ChatPromptTemplate
3
+ from langchain_openai import ChatOpenAI
4
+ from langchain_community.tools import DuckDuckGoSearchRun
5
  from vector import retriever
6
  import markdown
7
  import dotenv
 
11
  dotenv.load_dotenv()
12
  app = Flask(__name__)
13
 
14
+ # OpenRouter LLM Configuration
15
+ # Using the secret key name provided by the user
16
+ OPENROUTER_API_KEY = os.getenv("DOMINOS_PIZZA_AI_SUPPORT_OPENROUTER_MODEL_KEY")
17
+ MODEL_NAME = "openai/gpt-oss-120b:free"
18
+
19
+ llm = ChatOpenAI(
20
+ model=MODEL_NAME,
21
+ openai_api_key=OPENROUTER_API_KEY,
22
+ openai_api_base="https://openrouter.ai/api/v1",
23
+ default_headers={
24
+ "HTTP-Referer": "https://www.dominos.ng/", # Site URL for OpenRouter
25
+ "X-Title": "Domino's Pizza AI Support"
26
+ }
27
  )
28
 
29
+ # Web Search Tool
30
+ search = DuckDuckGoSearchRun()
31
+
32
+ # System Prompt
33
+ SYSTEM_PROMPT = """
34
+ You are the official Domino's Pizza AI Support agent for Domino's Pizza Nigeria.
35
+ Your goal is to provide exceptional, professional, and friendly assistance to customers.
36
+
37
+ Guidelines:
38
+ 1. Always maintain a helpful and appetizing tone.
39
+ 2. Use Domino's branding and language where appropriate.
40
+ 3. If you don't know the answer or can't find it in the provided context, state that you'll look it up, and use your web search capabilities (simulated in this flow) to find the most accurate information from https://www.dominos.ng/.
41
+ 4. Format your responses beautifully using Markdown:
42
+ - Use bold for emphasis.
43
+ - Use lists for steps or menus.
44
+ - Use headers for structure.
45
+ 5. If the answer involves a logo, mention that more information can be found at the link associated with the Domino's logo.
46
+
47
+ Context from Domino's Reviews:
48
+ {reviews}
49
+
50
  User question: {question}
51
  """
52
 
53
+ prompt = ChatPromptTemplate.from_template(SYSTEM_PROMPT)
 
 
 
54
 
55
  # In-memory chat history per device
56
  chat_sessions = {}
57
 
58
+ def get_ai_response(question: str, reviews: str) -> str:
59
  try:
60
+ # First attempt with context
61
+ chain = prompt | llm
62
+ response = chain.invoke({"reviews": reviews, "question": question})
63
+ content = response.content
64
+
65
+ # Simple check if AI couldn't answer (heuristics)
66
+ fallback_phrases = ["i don't know", "i am not sure", "i couldn't find", "sorry, i can't"]
67
+ if any(phrase in content.lower() for phrase in fallback_phrases):
68
+ print(f"[INFO] Triggering web search for: {question}")
69
+ search_results = search.run(f"Domino's Pizza Nigeria {question}")
70
+
71
+ # Re-run with search results
72
+ search_prompt = ChatPromptTemplate.from_template(
73
+ "The user asked: {question}\n"
74
+ "I found this information on the web: {search_results}\n"
75
+ "Provide a final answer as Domino's AI Support using this information."
76
+ )
77
+ search_chain = search_prompt | llm
78
+ response = search_chain.invoke({"question": question, "search_results": search_results})
79
+ content = response.content
80
+
81
+ return content
82
  except Exception as e:
83
+ print(f"[ERROR] AI Response failed: {e}")
84
+ return "I apologize, but I'm having trouble connecting to the pizza ovens (our servers) right now. Please try again in a moment!"
85
 
86
  @app.route("/", methods=["GET"])
87
  def index():
 
108
  if not question:
109
  return jsonify({"error": "No question provided"}), 400
110
 
111
+ reviews = str(retriever.invoke(question) or "No specific reviews found.")
112
+ raw_response = get_ai_response(question, reviews)
113
+
114
+ formatted_response = markdown.markdown(raw_response, extensions=['extra', 'tables'])
115
+
116
  chat_sessions[device_id].append({
117
  "user": question,
118
+ "bot": formatted_response
119
  })
120
+ return jsonify({"response": formatted_response})
121
 
122
  @app.route("/clear", methods=["POST"])
123
  def clear_chat():
assests/logo.png ADDED
requirements.txt CHANGED
@@ -11,4 +11,5 @@ pandas
11
  sentence-transformers
12
  chromadb
13
  langchain-community
14
- python-dotenv
 
 
11
  sentence-transformers
12
  chromadb
13
  langchain-community
14
+ python-dotenvlangchain-openai
15
+ duckduckgo-search
static/main.css CHANGED
@@ -1,146 +1,221 @@
1
- /* Global Reset */
 
 
 
 
 
 
 
 
 
 
2
  * {
3
  margin: 0;
4
  padding: 0;
5
  box-sizing: border-box;
6
- font-family: 'Segoe UI', sans-serif;
7
  }
8
 
9
- html, body {
10
- height: 100%;
11
- width: 100%;
12
- background: #f0f2f5;
13
- overflow: hidden; /* Prevent page scroll */
 
 
 
14
  }
15
 
16
- /* Chat Container */
17
  .chat-container {
18
- position: fixed; /* Lock in place */
19
- top: 0;
20
- left: 0;
21
  width: 100%;
22
- height: 100%; /* Full page */
23
- background: #fff;
24
- border-radius: 0; /* No rounding on full-page layout */
 
 
 
25
  display: flex;
26
  flex-direction: column;
27
- padding-bottom: 20px;
 
28
  }
29
 
30
- /* Chat Header */
31
  .chat-header {
32
- background-color: #10a37f;
33
- padding: 10px;
34
- text-align: center;
35
- color: white;
36
- font-size: 1.2rem; /* Reduced size */
37
- font-weight: bold;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
38
  }
39
 
40
- /* Chat Box */
41
  .chat-box {
42
- flex: 1; /* Fill remaining space */
43
- padding: 20px;
 
44
  display: flex;
45
  flex-direction: column;
46
- gap: 15px;
47
- background-color: #fafafa;
48
- overflow-y: auto; /* Scroll inside chat box only */
 
 
 
 
 
 
 
 
 
49
  }
50
 
51
- /* Messages */
52
  .message {
53
- max-width: 80%;
54
- padding: 12px 18px;
55
- border-radius: 16px;
56
  font-size: 1rem;
57
- line-height: 1.5; /* Better line spacing for Markdown */
58
- white-space: pre-wrap;
59
- word-break: break-word;
60
- overflow-wrap: break-word;
61
- transform: translateY(20px);
62
- opacity: 0;
63
- animation: slide-in 0.3s forwards;
64
  }
65
 
66
- /* User messages */
67
  .message.user {
68
  align-self: flex-end;
69
- background-color: #10a37f;
70
  color: white;
 
71
  }
72
 
73
- /* Bot messages */
74
  .message.bot {
75
  align-self: flex-start;
76
- background-color: #e5e5ea;
77
- color: #000;
 
 
78
  }
79
 
80
- /* Lists inside messages */
81
- .message ol,
82
- .message ul {
83
- margin: 0 0 0 1.2em; /* Proper indent inside bubble */
84
- padding-left: 1.2em;
85
  }
86
 
87
- .message li {
88
- margin-bottom: 0.3em; /* Space between items */
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
89
  }
90
 
91
- /* Chat Input */
92
  .chat-input {
 
 
93
  display: flex;
94
- padding: 15px;
95
- border-top: 1px solid #ddd;
96
- background-color: #fff;
97
  }
98
 
99
  .chat-input textarea {
100
  flex: 1;
101
- padding: 12px;
102
- border: 1px solid #ccc;
103
- border-radius: 20px;
104
- outline: none;
 
105
  resize: none;
106
- min-height: 40px;
107
- max-height: 150px;
 
 
 
 
 
108
  }
109
 
110
  .chat-input button {
111
- padding: 10px 18px;
112
- margin-left: 10px;
113
- background-color: #10a37f;
114
  color: white;
115
  border: none;
116
- border-radius: 20px;
 
 
117
  cursor: pointer;
 
 
118
  }
119
 
120
  .chat-input button:hover {
121
- background-color: #0e8f6a;
 
122
  }
123
 
124
- /* Spinner */
125
- .spinner {
126
- border: 4px solid #f3f3f3;
127
- border-top: 4px solid #10a37f;
128
- border-radius: 50%;
129
- width: 20px;
130
- height: 20px;
131
- animation: spin 1s linear infinite;
132
- display: inline-block;
 
 
 
 
 
 
 
 
 
 
 
133
  }
134
 
135
  /* Animations */
136
- @keyframes spin {
137
- 0% { transform: rotate(0deg); }
138
- 100% { transform: rotate(360deg); }
139
  }
140
 
141
- @keyframes slide-in {
 
 
 
 
142
  to {
143
- transform: translateY(0);
144
  opacity: 1;
 
145
  }
146
  }
 
1
+ /* Domino's Pizza AI Support - Premium CSS */
2
+
3
+ :root {
4
+ --dominos-blue: #006491;
5
+ --dominos-red: #E31837;
6
+ --dominos-white: #FFFFFF;
7
+ --bg-gradient: linear-gradient(135deg, #006491 0%, #004d70 100%);
8
+ --glass: rgba(255, 255, 255, 0.9);
9
+ --glass-border: rgba(255, 255, 255, 0.2);
10
+ }
11
+
12
  * {
13
  margin: 0;
14
  padding: 0;
15
  box-sizing: border-box;
16
+ font-family: 'Outfit', 'Inter', -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
17
  }
18
 
19
+ body {
20
+ height: 100vh;
21
+ width: 100vw;
22
+ background: var(--bg-gradient);
23
+ display: flex;
24
+ align-items: center;
25
+ justify-content: center;
26
+ overflow: hidden;
27
  }
28
 
 
29
  .chat-container {
 
 
 
30
  width: 100%;
31
+ max-width: 900px;
32
+ height: 90vh;
33
+ background: var(--glass);
34
+ backdrop-filter: blur(10px);
35
+ border-radius: 24px;
36
+ box-shadow: 0 20px 50px rgba(0,0,0,0.3);
37
  display: flex;
38
  flex-direction: column;
39
+ overflow: hidden;
40
+ border: 1px solid var(--glass-border);
41
  }
42
 
 
43
  .chat-header {
44
+ background: var(--dominos-white);
45
+ padding: 20px 30px;
46
+ display: flex;
47
+ align-items: center;
48
+ justify-content: space-between;
49
+ border-bottom: 2px solid #eee;
50
+ z-index: 10;
51
+ }
52
+
53
+ .chat-header h2 {
54
+ color: var(--dominos-blue);
55
+ font-weight: 800;
56
+ font-size: 1.5rem;
57
+ display: flex;
58
+ align-items: center;
59
+ gap: 12px;
60
+ }
61
+
62
+ .chat-header img {
63
+ height: 40px;
64
  }
65
 
 
66
  .chat-box {
67
+ flex: 1;
68
+ padding: 30px;
69
+ overflow-y: auto;
70
  display: flex;
71
  flex-direction: column;
72
+ gap: 20px;
73
+ background: rgba(245, 247, 250, 0.5);
74
+ scroll-behavior: smooth;
75
+ }
76
+
77
+ .chat-box::-webkit-scrollbar {
78
+ width: 6px;
79
+ }
80
+
81
+ .chat-box::-webkit-scrollbar-thumb {
82
+ background: rgba(0,0,0,0.1);
83
+ border-radius: 10px;
84
  }
85
 
 
86
  .message {
87
+ max-width: 75%;
88
+ padding: 16px 20px;
89
+ border-radius: 20px;
90
  font-size: 1rem;
91
+ line-height: 1.6;
92
+ position: relative;
93
+ transition: all 0.3s ease;
94
+ box-shadow: 0 4px 15px rgba(0,0,0,0.05);
 
 
 
95
  }
96
 
 
97
  .message.user {
98
  align-self: flex-end;
99
+ background: var(--dominos-blue);
100
  color: white;
101
+ border-bottom-right-radius: 4px;
102
  }
103
 
 
104
  .message.bot {
105
  align-self: flex-start;
106
+ background: white;
107
+ color: #333;
108
+ border-bottom-left-radius: 4px;
109
+ border-left: 4px solid var(--dominos-red);
110
  }
111
 
112
+ .message.bot img.bot-logo {
113
+ width: 24px;
114
+ height: 24px;
115
+ margin-right: 10px;
116
+ vertical-align: middle;
117
  }
118
 
119
+ /* AI Thinking Animation */
120
+ .thinking-container {
121
+ display: flex;
122
+ gap: 4px;
123
+ padding: 10px 0;
124
+ }
125
+
126
+ .thinking-dot {
127
+ width: 8px;
128
+ height: 8px;
129
+ background: var(--dominos-red);
130
+ border-radius: 50%;
131
+ animation: bounce 1.4s infinite ease-in-out both;
132
+ }
133
+
134
+ .thinking-dot:nth-child(1) { animation-delay: -0.32s; }
135
+ .thinking-dot:nth-child(2) { animation-delay: -0.16s; }
136
+
137
+ @keyframes bounce {
138
+ 0%, 80%, 100% { transform: scale(0); }
139
+ 40% { transform: scale(1); }
140
  }
141
 
 
142
  .chat-input {
143
+ background: white;
144
+ padding: 24px 30px;
145
  display: flex;
146
+ gap: 15px;
147
+ align-items: flex-end;
148
+ border-top: 1px solid #eee;
149
  }
150
 
151
  .chat-input textarea {
152
  flex: 1;
153
+ background: #f8f9fa;
154
+ border: 2px solid #eee;
155
+ border-radius: 16px;
156
+ padding: 14px 20px;
157
+ font-size: 1rem;
158
  resize: none;
159
+ max-height: 120px;
160
+ outline: none;
161
+ transition: border-color 0.3s ease;
162
+ }
163
+
164
+ .chat-input textarea:focus {
165
+ border-color: var(--dominos-blue);
166
  }
167
 
168
  .chat-input button {
169
+ background: var(--dominos-red);
 
 
170
  color: white;
171
  border: none;
172
+ border-radius: 14px;
173
+ padding: 14px 28px;
174
+ font-weight: 700;
175
  cursor: pointer;
176
+ transition: transform 0.2s ease, background 0.2s ease;
177
+ height: 52px;
178
  }
179
 
180
  .chat-input button:hover {
181
+ background: #c1142d;
182
+ transform: translateY(-2px);
183
  }
184
 
185
+ .chat-input button:active {
186
+ transform: translateY(0);
187
+ }
188
+
189
+ /* Markdown Styling */
190
+ .message h1, .message h2, .message h3 {
191
+ margin: 10px 0;
192
+ color: var(--dominos-blue);
193
+ }
194
+
195
+ .message ul, .message ol {
196
+ margin-left: 20px;
197
+ }
198
+
199
+ .message li {
200
+ margin-bottom: 8px;
201
+ }
202
+
203
+ .message p {
204
+ margin-bottom: 12px;
205
  }
206
 
207
  /* Animations */
208
+ .slide-in-bottom {
209
+ animation: slideIn 0.4s ease-out forwards;
 
210
  }
211
 
212
+ @keyframes slideIn {
213
+ from {
214
+ opacity: 0;
215
+ transform: translateY(20px);
216
+ }
217
  to {
 
218
  opacity: 1;
219
+ transform: translateY(0);
220
  }
221
  }
templates/index.html CHANGED
@@ -3,25 +3,30 @@
3
  <head>
4
  <meta charset="UTF-8" />
5
  <meta name="viewport" content="width=device-width, initial-scale=1" />
6
- <title>Pizza AI</title>
7
  <link rel="stylesheet" href="{{ url_for('static', filename='main.css') }}" />
 
8
  </head>
9
  <body>
10
  <div class="chat-container">
11
  <div class="chat-header">
12
- <h2>🍕 Pizza AI</h2>
 
13
  </div>
14
 
15
  <div class="chat-box" id="chat-box">
16
  {% for message in chat_history %}
17
  <div class="message user slide-in-bottom">{{ message.user }}</div>
18
- <div class="message bot slide-in-bottom">{{ message.bot|safe }}</div>
 
 
 
19
  {% endfor %}
20
  </div>
21
 
22
  <form id="chat-form" class="chat-input" autocomplete="off">
23
- <textarea name="question" id="input" placeholder="Ask me anything about Pizza..." required></textarea>
24
- <button type="submit">Send</button>
25
  </form>
26
  </div>
27
 
@@ -29,6 +34,7 @@
29
  const chatForm = document.getElementById('chat-form');
30
  const chatBox = document.getElementById('chat-box');
31
  const input = document.getElementById('input');
 
32
 
33
  // Auto-expand textarea
34
  input.addEventListener('input', () => {
@@ -36,6 +42,13 @@
36
  input.style.height = input.scrollHeight + 'px';
37
  });
38
 
 
 
 
 
 
 
 
39
  chatForm.addEventListener('submit', async (e) => {
40
  e.preventDefault();
41
  const question = input.value.trim();
@@ -51,15 +64,24 @@
51
  // Clear input immediately
52
  input.value = '';
53
  input.style.height = 'auto';
 
 
54
 
55
- // Add bot message with spinner
56
  const botMessage = document.createElement('div');
57
  botMessage.classList.add('message', 'bot', 'slide-in-bottom');
58
- botMessage.innerHTML = '<div class="spinner"></div>';
 
 
 
 
 
 
 
59
  chatBox.appendChild(botMessage);
60
  botMessage.scrollIntoView({ block: "start", behavior: "smooth" });
61
 
62
- // Send POST request via JSON
63
  try {
64
  const res = await fetch('/ask', {
65
  method: 'POST',
@@ -68,11 +90,15 @@
68
  });
69
  const data = await res.json();
70
 
71
- // Replace spinner with bot response
72
- botMessage.innerHTML = data.response || data.error;
73
  botMessage.scrollIntoView({ block: "start", behavior: "smooth" });
74
  } catch (err) {
75
- botMessage.textContent = 'Error: could not get response';
 
 
 
 
76
  }
77
  });
78
  </script>
 
3
  <head>
4
  <meta charset="UTF-8" />
5
  <meta name="viewport" content="width=device-width, initial-scale=1" />
6
+ <title>Domino's Pizza AI Support</title>
7
  <link rel="stylesheet" href="{{ url_for('static', filename='main.css') }}" />
8
+ <link rel="icon" href="{{ url_for('static', filename='assests/logo.png') }}" type="image/png">
9
  </head>
10
  <body>
11
  <div class="chat-container">
12
  <div class="chat-header">
13
+ <h2><img src="/assests/logo.png" alt="Domino's Logo"> Domino's AI Support</h2>
14
+ <button onclick="clearChat()" style="background: transparent; border: none; color: var(--dominos-red); cursor: pointer; font-weight: bold;">Clear Chat</button>
15
  </div>
16
 
17
  <div class="chat-box" id="chat-box">
18
  {% for message in chat_history %}
19
  <div class="message user slide-in-bottom">{{ message.user }}</div>
20
+ <div class="message bot slide-in-bottom">
21
+ <img src="/assests/logo.png" class="bot-logo" alt="Domino's">
22
+ {{ message.bot|safe }}
23
+ </div>
24
  {% endfor %}
25
  </div>
26
 
27
  <form id="chat-form" class="chat-input" autocomplete="off">
28
+ <textarea name="question" id="input" placeholder="How can Domino's help you today?" required></textarea>
29
+ <button type="submit" id="send-btn">Send Order</button>
30
  </form>
31
  </div>
32
 
 
34
  const chatForm = document.getElementById('chat-form');
35
  const chatBox = document.getElementById('chat-box');
36
  const input = document.getElementById('input');
37
+ const sendBtn = document.getElementById('send-btn');
38
 
39
  // Auto-expand textarea
40
  input.addEventListener('input', () => {
 
42
  input.style.height = input.scrollHeight + 'px';
43
  });
44
 
45
+ async function clearChat() {
46
+ if (confirm('Are you sure you want to clear the pizza party? (Chat history)')) {
47
+ await fetch('/clear', { method: 'POST' });
48
+ window.location.reload();
49
+ }
50
+ }
51
+
52
  chatForm.addEventListener('submit', async (e) => {
53
  e.preventDefault();
54
  const question = input.value.trim();
 
64
  // Clear input immediately
65
  input.value = '';
66
  input.style.height = 'auto';
67
+ input.disabled = true;
68
+ sendBtn.disabled = true;
69
 
70
+ // Add bot message with thinking animation
71
  const botMessage = document.createElement('div');
72
  botMessage.classList.add('message', 'bot', 'slide-in-bottom');
73
+ botMessage.innerHTML = `
74
+ <img src="/assests/logo.png" class="bot-logo" alt="Domino's">
75
+ <div class="thinking-container">
76
+ <div class="thinking-dot"></div>
77
+ <div class="thinking-dot"></div>
78
+ <div class="thinking-dot"></div>
79
+ </div>
80
+ `;
81
  chatBox.appendChild(botMessage);
82
  botMessage.scrollIntoView({ block: "start", behavior: "smooth" });
83
 
84
+ // Send POST request
85
  try {
86
  const res = await fetch('/ask', {
87
  method: 'POST',
 
90
  });
91
  const data = await res.json();
92
 
93
+ // Replace thinking animation with bot response
94
+ botMessage.innerHTML = `<img src="/assests/logo.png" class="bot-logo" alt="Domino's"> ${data.response || data.error}`;
95
  botMessage.scrollIntoView({ block: "start", behavior: "smooth" });
96
  } catch (err) {
97
+ botMessage.innerHTML = `<img src="/assests/logo.png" class="bot-logo" alt="Domino's"> Sorry, something went wrong in the kitchen.`;
98
+ } finally {
99
+ input.disabled = false;
100
+ sendBtn.disabled = false;
101
+ input.focus();
102
  }
103
  });
104
  </script>