TKM03 commited on
Commit
2a5f50f
·
verified ·
1 Parent(s): 78073c6

ADD MORE UI

Browse files
Files changed (1) hide show
  1. app.py +276 -50
app.py CHANGED
@@ -5,6 +5,7 @@ from huggingface_hub import InferenceClient
5
  from datetime import datetime
6
  import uuid
7
  import json
 
8
 
9
  # Configure logging
10
  logging.basicConfig(
@@ -15,12 +16,12 @@ logging.basicConfig(
15
  logging.StreamHandler()
16
  ]
17
  )
18
- logger = logging.getLogger("CompanyChatbot")
19
 
20
  # Environment variables (for production use)
21
  HF_MODEL = os.environ.get("HF_MODEL", "HuggingFaceH4/zephyr-7b-beta")
22
  HF_API_TOKEN = os.environ.get("HF_API_TOKEN", None) # Set your API token as env variable
23
- COMPANY_NAME = os.environ.get("COMPANY_NAME", "Your Company")
24
  DEFAULT_SYSTEM_PROMPT = os.environ.get("DEFAULT_SYSTEM_PROMPT",
25
  f"You are {COMPANY_NAME}'s professional AI assistant. Be helpful, accurate, and concise.")
26
 
@@ -43,7 +44,7 @@ def save_conversation(user_id, conversation):
43
  # Main chat function
44
  def respond(
45
  message,
46
- history: list[tuple[str, str]],
47
  system_message,
48
  max_tokens,
49
  temperature,
@@ -51,7 +52,7 @@ def respond(
51
  user_id
52
  ):
53
  if not message.strip():
54
- return "I'm sorry, I didn't receive any input. How can I help you today?"
55
 
56
  # Log the incoming request
57
  logger.info(f"User {user_id} sent message - Length: {len(message)}")
@@ -60,7 +61,7 @@ def respond(
60
  messages = [{"role": "system", "content": system_message}]
61
 
62
  # Build conversation history
63
- for user_msg, assistant_msg in history:
64
  if user_msg:
65
  messages.append({"role": "user", "content": user_msg})
66
  if assistant_msg:
@@ -81,7 +82,7 @@ def respond(
81
  ):
82
  token = message_chunk.choices[0].delta.content
83
  full_response += token if token else ""
84
- yield full_response
85
 
86
  # Log completion
87
  time_taken = (datetime.now() - start_time).total_seconds()
@@ -105,76 +106,301 @@ def respond(
105
  except Exception as e:
106
  error_msg = f"An error occurred: {str(e)}"
107
  logger.error(f"Error generating response for user {user_id}: {str(e)}")
108
- return error_msg
109
 
110
  # Authentication function (replace with your actual auth system)
111
  def authenticate(username, password):
112
  # In production, this should check against your company's auth system
113
- valid_credentials = {"admin": "admin123", "user": "user123"} # Example only
 
 
 
114
 
115
- if username in valid_credentials and valid_credentials[username] == password:
116
- return True, str(uuid.uuid4()) # Generate user session ID
117
- return False, None
118
 
119
- # Login interface
120
  def login(username, password):
121
- success, user_id = authenticate(username, password)
122
- if success:
123
- return gr.update(visible=False), gr.update(visible=True), user_id
124
- else:
125
- return gr.update(visible=True), gr.update(visible=False), None
126
-
127
- # Main application
128
- with gr.Blocks(css="styles.css", title=f"{COMPANY_NAME} AI Assistant") as demo:
129
- user_id = gr.State(None)
130
 
131
- with gr.Row():
132
- gr.Markdown(f"# {COMPANY_NAME} AI Assistant")
133
 
134
- with gr.Group(visible=True) as login_group:
135
- gr.Markdown("### Please log in to continue")
136
- username = gr.Textbox(label="Username")
137
- password = gr.Textbox(label="Password", type="password")
138
- login_button = gr.Button("Login")
139
-
140
- with gr.Group(visible=False) as chat_group:
141
- chatbot = gr.ChatInterface(
142
- respond,
143
- additional_inputs=[
144
- gr.Textbox(value=DEFAULT_SYSTEM_PROMPT, label="System Instructions"),
145
- gr.Slider(minimum=1, maximum=2048, value=512, step=1, label="Max Response Length"),
146
- gr.Slider(minimum=0.1, maximum=1.0, value=0.7, step=0.1, label="Temperature (Creativity)"),
147
- gr.Slider(minimum=0.1, maximum=1.0, value=0.95, step=0.05, label="Top-p (Variation)"),
148
- user_id
149
- ],
150
- analytics_enabled=True,
151
- title=None,
152
  )
153
-
154
- login_button.click(
155
- login,
156
- inputs=[username, password],
157
- outputs=[login_group, chat_group, user_id]
158
- )
159
 
160
- # For CSS styling
161
  css = """
162
  body {
163
  font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
164
  background-color: #f9f9f9;
165
  }
166
- .gradio-container {
167
- max-width: 1200px !important;
168
  margin: auto;
169
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
170
  .footer {
171
  text-align: center;
172
  margin-top: 20px;
173
  color: #666;
174
  font-size: 0.8em;
175
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
176
  """
177
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
178
  with open("styles.css", "w") as f:
179
  f.write(css)
180
 
 
5
  from datetime import datetime
6
  import uuid
7
  import json
8
+ import time
9
 
10
  # Configure logging
11
  logging.basicConfig(
 
16
  logging.StreamHandler()
17
  ]
18
  )
19
+ logger = logging.getLogger("Chatbot")
20
 
21
  # Environment variables (for production use)
22
  HF_MODEL = os.environ.get("HF_MODEL", "HuggingFaceH4/zephyr-7b-beta")
23
  HF_API_TOKEN = os.environ.get("HF_API_TOKEN", None) # Set your API token as env variable
24
+ COMPANY_NAME = os.environ.get("COMPANY_NAME", "ROYAL SELANGOR")
25
  DEFAULT_SYSTEM_PROMPT = os.environ.get("DEFAULT_SYSTEM_PROMPT",
26
  f"You are {COMPANY_NAME}'s professional AI assistant. Be helpful, accurate, and concise.")
27
 
 
44
  # Main chat function
45
  def respond(
46
  message,
47
+ chat_history,
48
  system_message,
49
  max_tokens,
50
  temperature,
 
52
  user_id
53
  ):
54
  if not message.strip():
55
+ return chat_history + [(message, "I'm sorry, I didn't receive any input. How can I help you today?")]
56
 
57
  # Log the incoming request
58
  logger.info(f"User {user_id} sent message - Length: {len(message)}")
 
61
  messages = [{"role": "system", "content": system_message}]
62
 
63
  # Build conversation history
64
+ for user_msg, assistant_msg in chat_history:
65
  if user_msg:
66
  messages.append({"role": "user", "content": user_msg})
67
  if assistant_msg:
 
82
  ):
83
  token = message_chunk.choices[0].delta.content
84
  full_response += token if token else ""
85
+ yield chat_history + [(message, full_response)]
86
 
87
  # Log completion
88
  time_taken = (datetime.now() - start_time).total_seconds()
 
106
  except Exception as e:
107
  error_msg = f"An error occurred: {str(e)}"
108
  logger.error(f"Error generating response for user {user_id}: {str(e)}")
109
+ return chat_history + [(message, error_msg)]
110
 
111
  # Authentication function (replace with your actual auth system)
112
  def authenticate(username, password):
113
  # In production, this should check against your company's auth system
114
+ valid_credentials = {
115
+ "admin": {"password": "admin123", "role": "admin"},
116
+ "user": {"password": "user123", "role": "user"}
117
+ } # Example only
118
 
119
+ if username in valid_credentials and valid_credentials[username]["password"] == password:
120
+ return True, str(uuid.uuid4()), valid_credentials[username]["role"] # Return success, user_id, and role
121
+ return False, None, None
122
 
123
+ # Login interface with error handling
124
  def login(username, password):
125
+ if not username or not password:
126
+ return (
127
+ gr.update(visible=True),
128
+ gr.update(visible=False),
129
+ None,
130
+ None,
131
+ gr.update(visible=True, value="Please enter both username and password")
132
+ )
 
133
 
134
+ # Simulate processing delay for security (prevents timing attacks)
135
+ time.sleep(0.5)
136
 
137
+ success, user_id, role = authenticate(username, password)
138
+ if success:
139
+ return (
140
+ gr.update(visible=False),
141
+ gr.update(visible=True),
142
+ user_id,
143
+ role,
144
+ gr.update(visible=False)
145
+ )
146
+ else:
147
+ return (
148
+ gr.update(visible=True),
149
+ gr.update(visible=False),
150
+ None,
151
+ None,
152
+ gr.update(visible=True, value="Invalid username or password")
 
 
153
  )
 
 
 
 
 
 
154
 
155
+ # CSS for better styling
156
  css = """
157
  body {
158
  font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
159
  background-color: #f9f9f9;
160
  }
161
+ .container {
162
+ max-width: 1400px !important;
163
  margin: auto;
164
  }
165
+ .setting-panel {
166
+ background-color: #f0f4f8;
167
+ border-radius: 10px;
168
+ padding: 15px;
169
+ box-shadow: 0 2px 6px rgba(0,0,0,0.1);
170
+ }
171
+ .chat-container {
172
+ border-radius: 10px;
173
+ box-shadow: 0 2px 6px rgba(0,0,0,0.1);
174
+ background-color: white;
175
+ }
176
+ .company-header {
177
+ background-color: #2c3e50;
178
+ color: white;
179
+ padding: 15px;
180
+ border-radius: 10px 10px 0 0;
181
+ margin-bottom: 15px;
182
+ }
183
  .footer {
184
  text-align: center;
185
  margin-top: 20px;
186
  color: #666;
187
  font-size: 0.8em;
188
  }
189
+ .message-user {
190
+ background-color: #e6f7ff !important;
191
+ border-radius: 15px 15px 0 15px !important;
192
+ }
193
+ .message-bot {
194
+ background-color: #f0f0f0 !important;
195
+ border-radius: 15px 15px 15px 0 !important;
196
+ }
197
+ .login-container {
198
+ max-width: 500px;
199
+ margin: 50px auto;
200
+ padding: 30px;
201
+ background-color: white;
202
+ border-radius: 10px;
203
+ box-shadow: 0 4px 10px rgba(0,0,0,0.1);
204
+ }
205
+ .login-header {
206
+ text-align: center;
207
+ margin-bottom: 30px;
208
+ }
209
+ .error-message {
210
+ color: #e74c3c;
211
+ background-color: #fdedeb;
212
+ padding: 10px;
213
+ border-radius: 5px;
214
+ margin-bottom: 15px;
215
+ font-size: 14px;
216
+ }
217
+ .role-badge {
218
+ font-size: 12px;
219
+ padding: 3px 8px;
220
+ border-radius: 10px;
221
+ margin-left: 10px;
222
+ }
223
+ .admin-badge {
224
+ background-color: #e74c3c;
225
+ color: white;
226
+ }
227
+ .user-badge {
228
+ background-color: #3498db;
229
+ color: white;
230
+ }
231
+ .setting-disabled {
232
+ opacity: 0.5;
233
+ pointer-events: none;
234
+ }
235
  """
236
 
237
+ # Main application
238
+ with gr.Blocks(css=css, title=f"{COMPANY_NAME} AI Assistant") as demo:
239
+ user_id = gr.State(None)
240
+ user_role = gr.State(None)
241
+
242
+ with gr.Row():
243
+ gr.Markdown(f"<div class='company-header'><h1>{COMPANY_NAME} AI Assistant</h1></div>", elem_classes=["company-header"])
244
+
245
+ # Login Group
246
+ with gr.Group(visible=True) as login_group:
247
+ with gr.Column(elem_classes=["login-container"]):
248
+ gr.Markdown(f"<div class='login-header'><h2>Welcome to {COMPANY_NAME}</h2><p>Please log in to continue</p></div>")
249
+
250
+ # Error message container (initially hidden)
251
+ error_message = gr.Markdown(visible=False, value="", elem_classes=["error-message"])
252
+
253
+ username = gr.Textbox(label="Username", placeholder="Enter your username")
254
+ password = gr.Textbox(label="Password", type="password", placeholder="Enter your password")
255
+
256
+ with gr.Row():
257
+ login_button = gr.Button("Login", variant="primary", size="lg")
258
+
259
+ # Chat Group (initially hidden)
260
+ with gr.Group(visible=False) as chat_group:
261
+ with gr.Row():
262
+ # Left side: Settings Panel
263
+ with gr.Column(scale=1, elem_classes=["setting-panel"]):
264
+ # Role indicator
265
+ role_indicator = gr.Markdown("", elem_id="role-indicator")
266
+
267
+ gr.Markdown("### Configuration")
268
+ system_message = gr.Textbox(
269
+ value=DEFAULT_SYSTEM_PROMPT,
270
+ label="System Instructions",
271
+ lines=4
272
+ )
273
+
274
+ with gr.Group(elem_id="admin-settings") as admin_settings:
275
+ max_tokens = gr.Slider(
276
+ minimum=1,
277
+ maximum=2048,
278
+ value=512,
279
+ step=1,
280
+ label="Max Response Length"
281
+ )
282
+ temperature = gr.Slider(
283
+ minimum=0.1,
284
+ maximum=1.0,
285
+ value=0.7,
286
+ step=0.1,
287
+ label="Temperature (Creativity)"
288
+ )
289
+ top_p = gr.Slider(
290
+ minimum=0.1,
291
+ maximum=1.0,
292
+ value=0.95,
293
+ step=0.05,
294
+ label="Top-p (Variation)"
295
+ )
296
+
297
+ gr.Markdown("---")
298
+
299
+ gr.Markdown("### Chat Actions")
300
+ with gr.Row():
301
+ clear_btn = gr.Button("Clear Chat", variant="secondary")
302
+ export_btn = gr.Button("Export Conversation", variant="secondary")
303
+
304
+ # Logout button
305
+ logout_btn = gr.Button("Logout", variant="stop")
306
+
307
+ gr.Markdown(f"<div class='footer'>© {datetime.now().year} {COMPANY_NAME}. All rights reserved.</div>")
308
+
309
+ # Right side: Chat Interface
310
+ with gr.Column(scale=2, elem_classes=["chat-container"]):
311
+ chatbot = gr.Chatbot(elem_classes=["chatbox"])
312
+ with gr.Row():
313
+ msg = gr.Textbox(
314
+ show_label=False,
315
+ placeholder="Type your message here...",
316
+ container=False
317
+ )
318
+ submit_btn = gr.Button("Send", variant="primary")
319
+
320
+ # Event handlers
321
+ def update_role_display(role):
322
+ if role == "admin":
323
+ return f"<h3>Role: <span class='role-badge admin-badge'>Administrator</span></h3>"
324
+ else:
325
+ return f"<h3>Role: <span class='role-badge user-badge'>Standard User</span></h3>"
326
+
327
+ def handle_role_permissions(role):
328
+ if role == "admin":
329
+ return gr.update(visible=True)
330
+ else:
331
+ return gr.update(visible=True, elem_classes=["setting-disabled"])
332
+
333
+ # Login handler with role-based permission setting
334
+ login_button.click(
335
+ login,
336
+ inputs=[username, password],
337
+ outputs=[login_group, chat_group, user_id, user_role, error_message]
338
+ ).then(
339
+ update_role_display,
340
+ inputs=[user_role],
341
+ outputs=[role_indicator]
342
+ ).then(
343
+ handle_role_permissions,
344
+ inputs=[user_role],
345
+ outputs=[admin_settings]
346
+ )
347
+
348
+ # Chat functionality
349
+ def chat_with_saved_params(message, history, uid, role):
350
+ # For non-admin users, use default values
351
+ system_msg = system_message.value
352
+ tokens = max_tokens.value
353
+ temp = temperature.value
354
+ topp = top_p.value
355
+ return respond(message, history, system_msg, tokens, temp, topp, uid)
356
+
357
+ msg_and_submit = msg.submit(
358
+ chat_with_saved_params,
359
+ inputs=[msg, chatbot, user_id, user_role],
360
+ outputs=[chatbot],
361
+ show_progress=True
362
+ )
363
+
364
+ submit_click = submit_btn.click(
365
+ chat_with_saved_params,
366
+ inputs=[msg, chatbot, user_id, user_role],
367
+ outputs=[chatbot],
368
+ show_progress=True
369
+ )
370
+
371
+ # Clear the textbox when message is sent
372
+ msg_and_submit.then(lambda: gr.update(value=""), None, [msg])
373
+ submit_click.then(lambda: gr.update(value=""), None, [msg])
374
+
375
+ # Clear chat button
376
+ clear_btn.click(lambda: None, None, chatbot, queue=False)
377
+
378
+ # Export conversation
379
+ def export_conversation(chat_history, uid):
380
+ timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
381
+ filename = f"conversations/export_{uid}_{timestamp}.json"
382
+ os.makedirs(os.path.dirname(filename), exist_ok=True)
383
+ with open(filename, 'w') as f:
384
+ json.dump(chat_history, f)
385
+ logger.info(f"Exported conversation for user {uid}")
386
+ return gr.update(value=f"Conversation exported to {filename}", visible=True)
387
+
388
+ export_btn.click(
389
+ export_conversation,
390
+ inputs=[chatbot, user_id],
391
+ outputs=[error_message]
392
+ )
393
+
394
+ # Logout functionality
395
+ def logout():
396
+ return gr.update(visible=True), gr.update(visible=False), None, None
397
+
398
+ logout_btn.click(
399
+ logout,
400
+ outputs=[login_group, chat_group, user_id, user_role]
401
+ )
402
+
403
+ # Generate CSS file
404
  with open("styles.css", "w") as f:
405
  f.write(css)
406