TKM03 commited on
Commit
db773fb
·
verified ·
1 Parent(s): 80cdf98

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +126 -269
app.py CHANGED
@@ -18,9 +18,9 @@ logging.basicConfig(
18
  )
19
  logger = logging.getLogger("CompanyChatbot")
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", "Your Company")
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.")
@@ -41,92 +41,81 @@ def save_conversation(user_id, conversation):
41
  json.dump(conversation, f)
42
  logger.info(f"Saved conversation for user {user_id}")
43
 
44
- # Main chat function - fixed to properly handle message format
45
- def respond(
46
- message,
47
- history,
48
- system_message,
49
- max_tokens,
50
- temperature,
51
- top_p,
52
- user_id
53
- ):
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
54
  if not message.strip():
55
- return history + [[message, "I'm sorry, I didn't receive any input. How can I help you today?"]]
56
 
57
  logger.info(f"User {user_id} sent message - Length: {len(message)}")
58
 
59
  try:
60
- messages = [{"role": "system", "content": system_message}]
61
-
62
- for user_msg, assistant_msg in history:
63
- if user_msg:
64
- messages.append({"role": "user", "content": user_msg})
65
- if assistant_msg:
66
- messages.append({"role": "assistant", "content": assistant_msg})
67
-
68
- messages.append({"role": "user", "content": message})
69
-
70
- full_response = ""
71
- start_time = datetime.now()
72
-
73
- # Ensure proper response format for streaming
74
- current_history = history.copy()
75
-
76
- for message_chunk in client.chat_completion(
77
- messages,
78
- max_tokens=max_tokens,
79
- stream=True,
80
- temperature=temperature,
81
- top_p=top_p,
82
- ):
83
- token = message_chunk.choices[0].delta.content
84
- if token:
85
- full_response += token
86
- # Always ensure a list of lists with pairs
87
- new_history = current_history + [[message, full_response]]
88
- yield new_history
89
 
90
- time_taken = (datetime.now() - start_time).total_seconds()
91
- logger.info(f"Response generated for user {user_id} in {time_taken:.2f}s - Length: {len(full_response)}")
 
92
 
 
93
  conversation_data = {
94
  "timestamp": datetime.now().isoformat(),
95
  "user_id": user_id,
96
- "messages": messages,
97
- "response": full_response,
98
- "parameters": {
99
- "max_tokens": max_tokens,
100
- "temperature": temperature,
101
- "top_p": top_p
102
- },
103
- "time_taken": time_taken
104
  }
105
  save_conversation(user_id, conversation_data)
106
 
107
- # Ensure final response is properly formatted
108
- if not full_response:
109
- return history
110
- return current_history + [[message, full_response]]
111
 
112
  except Exception as e:
113
- error_msg = f"An error occurred: {str(e)}"
114
- logger.error(f"Error generating response for user {user_id}: {str(e)}")
115
- return history + [[message, error_msg]]
 
116
 
117
- # Authentication function (replace with your actual auth system)
118
  def authenticate(username, password):
119
- # In production, this should check against your company's auth system
120
  valid_credentials = {
121
  "admin": {"password": "admin123", "role": "admin"},
122
  "user": {"password": "user123", "role": "user"}
123
- } # Example only
124
 
125
  if username in valid_credentials and valid_credentials[username]["password"] == password:
126
- return True, str(uuid.uuid4()), valid_credentials[username]["role"] # Return success, user_id, and role
127
  return False, None, None
128
 
129
- # Login interface with error handling
130
  def login(username, password):
131
  if not username or not password:
132
  return (
@@ -137,10 +126,9 @@ def login(username, password):
137
  gr.update(visible=True, value="Please enter both username and password")
138
  )
139
 
140
- # Simulate processing delay for security (prevents timing attacks)
141
  time.sleep(0.5)
142
-
143
  success, user_id, role = authenticate(username, password)
 
144
  if success:
145
  return (
146
  gr.update(visible=False),
@@ -158,16 +146,9 @@ def login(username, password):
158
  gr.update(visible=True, value="Invalid username or password")
159
  )
160
 
161
- # CSS for better styling
162
  css = """
163
- body {
164
- font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
165
- background-color: #f9f9f9;
166
- }
167
- .container {
168
- max-width: 1400px !important;
169
- margin: auto;
170
- }
171
  .setting-panel {
172
  background-color: #f0f4f8;
173
  border-radius: 10px;
@@ -179,64 +160,12 @@ body {
179
  box-shadow: 0 2px 6px rgba(0,0,0,0.1);
180
  background-color: white;
181
  }
182
- .company-header {
183
- background-color: #2c3e50;
184
- color: white;
185
- padding: 15px;
186
- border-radius: 10px 10px 0 0;
187
- margin-bottom: 15px;
188
- }
189
- .footer {
190
- text-align: center;
191
- margin-top: 20px;
192
- color: #666;
193
- font-size: 0.8em;
194
- }
195
- .message-user {
196
- background-color: #e6f7ff !important;
197
- border-radius: 15px 15px 0 15px !important;
198
- }
199
- .message-bot {
200
- background-color: #f0f0f0 !important;
201
- border-radius: 15px 15px 15px 0 !important;
202
- }
203
- .login-container {
204
- max-width: 500px;
205
- margin: 50px auto;
206
- padding: 30px;
207
- background-color: white;
208
- border-radius: 10px;
209
- box-shadow: 0 4px 10px rgba(0,0,0,0.1);
210
- }
211
- .login-header {
212
- text-align: center;
213
- margin-bottom: 30px;
214
- }
215
- .error-message {
216
- color: #e74c3c;
217
- background-color: #fdedeb;
218
- padding: 10px;
219
- border-radius: 5px;
220
- margin-bottom: 15px;
221
- font-size: 14px;
222
- }
223
- .role-badge {
224
- font-size: 12px;
225
- padding: 3px 8px;
226
- border-radius: 10px;
227
- margin-left: 10px;
228
- }
229
- .admin-badge {
230
- background-color: #e74c3c;
231
- color: white;
232
- }
233
- .user-badge {
234
- background-color: #3498db;
235
- color: white;
236
- }
237
- .setting-disabled {
238
- opacity: 0.5;
239
  pointer-events: none;
 
240
  }
241
  """
242
 
@@ -245,188 +174,116 @@ with gr.Blocks(css=css, title=f"{COMPANY_NAME} AI Assistant") as demo:
245
  user_id = gr.State(None)
246
  user_role = gr.State(None)
247
 
248
- with gr.Row():
249
- gr.Markdown(f"<div class='company-header'><h1>{COMPANY_NAME} AI Assistant</h1></div>", elem_classes=["company-header"])
250
-
251
- # Login Group
252
  with gr.Group(visible=True) as login_group:
253
- with gr.Column(elem_classes=["login-container"]):
254
- gr.Markdown(f"<div class='login-header'><h2>Welcome to {COMPANY_NAME}</h2><p>Please log in to continue</p></div>")
255
-
256
- # Error message container (initially hidden)
257
- error_message = gr.Markdown(visible=False, value="", elem_classes=["error-message"])
258
-
259
- username = gr.Textbox(label="Username", placeholder="Enter your username")
260
- password = gr.Textbox(label="Password", type="password", placeholder="Enter your password")
261
-
262
- with gr.Row():
263
- login_button = gr.Button("Login", variant="primary", size="lg")
264
 
265
- # Chat Group (initially hidden)
266
  with gr.Group(visible=False) as chat_group:
267
  with gr.Row():
268
- # Left side: Settings Panel
269
- with gr.Column(scale=1, elem_classes=["setting-panel"]):
270
- # Role indicator
271
- role_indicator = gr.Markdown("", elem_id="role-indicator")
272
-
273
- gr.Markdown("### Configuration")
274
  system_message = gr.Textbox(
 
275
  value=DEFAULT_SYSTEM_PROMPT,
276
- label="System Instructions",
277
- lines=4
278
  )
279
 
280
- with gr.Group(elem_id="admin-settings") as admin_settings:
281
  max_tokens = gr.Slider(
282
  minimum=1,
283
  maximum=2048,
284
  value=512,
285
  step=1,
286
- label="Max Response Length"
287
  )
288
  temperature = gr.Slider(
289
  minimum=0.1,
290
  maximum=1.0,
291
  value=0.7,
292
  step=0.1,
293
- label="Temperature (Creativity)"
294
  )
295
  top_p = gr.Slider(
296
  minimum=0.1,
297
  maximum=1.0,
298
  value=0.95,
299
  step=0.05,
300
- label="Top-p (Variation)"
301
  )
302
-
303
- gr.Markdown("---")
304
-
305
- gr.Markdown("### Chat Actions")
306
- with gr.Row():
307
- clear_btn = gr.Button("Clear Chat", variant="secondary")
308
- export_btn = gr.Button("Export Conversation", variant="secondary")
309
 
310
- # Logout button
311
- logout_btn = gr.Button("Logout", variant="stop")
312
-
313
- gr.Markdown(f"<div class='footer'>© {datetime.now().year} {COMPANY_NAME}. All rights reserved.</div>")
314
 
315
- # Right side: Chat Interface
316
- with gr.Column(scale=2, elem_classes=["chat-container"]):
317
- chatbot = gr.Chatbot(elem_classes=["chatbox"])
318
- with gr.Row():
319
- msg = gr.Textbox(
320
- show_label=False,
321
- placeholder="Type your message here...",
322
- container=False
323
- )
324
- submit_btn = gr.Button("Send", variant="primary")
325
 
326
- # Event handlers
327
- def update_role_display(role):
328
- if role == "admin":
329
- return f"<h3>Role: <span class='role-badge admin-badge'>Administrator</span></h3>"
330
- else:
331
- return f"<h3>Role: <span class='role-badge user-badge'>Standard User</span></h3>"
 
332
 
333
- def handle_role_permissions(role):
334
- # Only disable settings for non-admin users
335
- if role == "admin":
336
- return gr.update(visible=True, elem_classes=[]) # Remove any disabled classes
337
- else:
338
- return gr.update(visible=True, elem_classes=["setting-disabled"])
 
 
 
 
339
 
340
- # Login handler with role-based permission setting
341
  login_button.click(
342
  login,
343
  inputs=[username, password],
344
  outputs=[login_group, chat_group, user_id, user_role, error_message]
345
  ).then(
346
- update_role_display,
347
- inputs=[user_role],
348
- outputs=[role_indicator]
349
- ).then(
350
- handle_role_permissions,
351
  inputs=[user_role],
352
- outputs=[admin_settings]
353
  )
354
 
355
- # Chat functionality
356
- def chat_with_saved_params(message, history, uid, role):
357
- # Get current values of parameters
358
- system_msg = system_message.value
359
- tokens = max_tokens.value if role == "admin" else 512 # Default value for non-admin
360
- temp = temperature.value if role == "admin" else 0.7 # Default value for non-admin
361
- topp = top_p.value if role == "admin" else 0.95 # Default value for non-admin
362
-
363
- return respond(message, history, system_msg, tokens, temp, topp, uid)
364
-
365
- msg_and_submit = msg.submit(
366
- chat_with_saved_params,
367
  inputs=[msg, chatbot, user_id, user_role],
368
- outputs=[chatbot],
369
- show_progress=True
370
- )
371
 
372
- submit_click = submit_btn.click(
373
- chat_with_saved_params,
374
  inputs=[msg, chatbot, user_id, user_role],
375
- outputs=[chatbot],
376
- show_progress=True
377
- )
378
-
379
- # Clear the textbox when message is sent
380
- msg_and_submit.then(lambda: gr.update(value=""), None, [msg])
381
- submit_click.then(lambda: gr.update(value=""), None, [msg])
382
-
383
- # Clear chat button - fixed to properly reset the history list
384
- clear_btn.click(lambda: [], None, chatbot, queue=False)
385
-
386
- # Export conversation
387
- def export_conversation(chat_history, uid):
388
- timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
389
- filename = f"conversations/export_{uid}_{timestamp}.json"
390
- os.makedirs(os.path.dirname(filename), exist_ok=True)
391
- with open(filename, 'w') as f:
392
- json.dump(chat_history, f)
393
- logger.info(f"Exported conversation for user {uid}")
394
- return gr.update(value=f"Conversation exported to {filename}", visible=True)
395
-
396
- export_btn.click(
397
- export_conversation,
398
- inputs=[chatbot, user_id],
399
- outputs=[error_message]
400
- )
401
 
402
- # Logout functionality
403
- def logout():
404
- return gr.update(visible=True), gr.update(visible=False), None, None
405
 
406
- logout_btn.click(
407
- logout,
 
 
 
 
 
 
408
  outputs=[login_group, chat_group, user_id, user_role]
409
  )
410
 
411
- # Generate CSS file
412
- with open("styles.css", "w") as f:
413
- f.write(css)
414
-
415
- css = css.replace(
416
- ".setting-disabled {",
417
- ".setting-disabled input, .setting-disabled button, .setting-disabled select, .setting-disabled textarea {"
418
- )
419
-
420
  if __name__ == "__main__":
421
- # Check if we're running in production
422
- if os.environ.get("PRODUCTION", "false").lower() == "true":
423
- demo.launch(
424
- server_name="0.0.0.0",
425
- server_port=int(os.environ.get("PORT", 7860)),
426
- share=False,
427
- show_error=False,
428
- auth=None, # We handle auth in the app
429
- )
430
- else:
431
- # Development mode
432
- demo.launch(share=True)
 
18
  )
19
  logger = logging.getLogger("CompanyChatbot")
20
 
21
+ # Environment variables
22
  HF_MODEL = os.environ.get("HF_MODEL", "HuggingFaceH4/zephyr-7b-beta")
23
+ HF_API_TOKEN = os.environ.get("HF_API_TOKEN", None)
24
  COMPANY_NAME = os.environ.get("COMPANY_NAME", "Your Company")
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.")
 
41
  json.dump(conversation, f)
42
  logger.info(f"Saved conversation for user {user_id}")
43
 
44
+ def generate_response(message, history, system_message, max_tokens, temperature, top_p, user_id):
45
+ messages = [{"role": "system", "content": system_message}]
46
+
47
+ # Add history to messages
48
+ for h in history:
49
+ messages.append({"role": "user", "content": h[0]})
50
+ messages.append({"role": "assistant", "content": h[1]})
51
+
52
+ # Add current message
53
+ messages.append({"role": "user", "content": message})
54
+
55
+ # Generate response
56
+ try:
57
+ response = client.text_generation(
58
+ prompt=message,
59
+ max_new_tokens=max_tokens,
60
+ temperature=temperature,
61
+ top_p=top_p,
62
+ )
63
+ return response
64
+ except Exception as e:
65
+ logger.error(f"Error generating response: {str(e)}")
66
+ return f"An error occurred: {str(e)}"
67
+
68
+ def chat(message, history, system_message, max_tokens, temperature, top_p, user_id):
69
  if not message.strip():
70
+ return history
71
 
72
  logger.info(f"User {user_id} sent message - Length: {len(message)}")
73
 
74
  try:
75
+ response = generate_response(
76
+ message,
77
+ history,
78
+ system_message,
79
+ max_tokens,
80
+ temperature,
81
+ top_p,
82
+ user_id
83
+ )
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
84
 
85
+ # Format response
86
+ new_history = list(history or [])
87
+ new_history.append([message, str(response)])
88
 
89
+ # Save conversation
90
  conversation_data = {
91
  "timestamp": datetime.now().isoformat(),
92
  "user_id": user_id,
93
+ "message": message,
94
+ "response": str(response),
95
+ "history": new_history
 
 
 
 
 
96
  }
97
  save_conversation(user_id, conversation_data)
98
 
99
+ return new_history
 
 
 
100
 
101
  except Exception as e:
102
+ logger.error(f"Error in chat function: {str(e)}")
103
+ new_history = list(history or [])
104
+ new_history.append([message, f"An error occurred: {str(e)}"])
105
+ return new_history
106
 
107
+ # Authentication
108
  def authenticate(username, password):
 
109
  valid_credentials = {
110
  "admin": {"password": "admin123", "role": "admin"},
111
  "user": {"password": "user123", "role": "user"}
112
+ }
113
 
114
  if username in valid_credentials and valid_credentials[username]["password"] == password:
115
+ return True, str(uuid.uuid4()), valid_credentials[username]["role"]
116
  return False, None, None
117
 
118
+ # Login interface
119
  def login(username, password):
120
  if not username or not password:
121
  return (
 
126
  gr.update(visible=True, value="Please enter both username and password")
127
  )
128
 
 
129
  time.sleep(0.5)
 
130
  success, user_id, role = authenticate(username, password)
131
+
132
  if success:
133
  return (
134
  gr.update(visible=False),
 
146
  gr.update(visible=True, value="Invalid username or password")
147
  )
148
 
149
+ # CSS
150
  css = """
151
+ .container { max-width: 1400px !important; margin: auto; }
 
 
 
 
 
 
 
152
  .setting-panel {
153
  background-color: #f0f4f8;
154
  border-radius: 10px;
 
160
  box-shadow: 0 2px 6px rgba(0,0,0,0.1);
161
  background-color: white;
162
  }
163
+ .setting-disabled input,
164
+ .setting-disabled select,
165
+ .setting-disabled textarea,
166
+ .setting-disabled button {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
167
  pointer-events: none;
168
+ opacity: 0.6;
169
  }
170
  """
171
 
 
174
  user_id = gr.State(None)
175
  user_role = gr.State(None)
176
 
177
+ # Login Interface
 
 
 
178
  with gr.Group(visible=True) as login_group:
179
+ username = gr.Textbox(label="Username")
180
+ password = gr.Textbox(label="Password", type="password")
181
+ login_button = gr.Button("Login")
182
+ error_message = gr.Markdown(visible=False)
 
 
 
 
 
 
 
183
 
184
+ # Chat Interface
185
  with gr.Group(visible=False) as chat_group:
186
  with gr.Row():
187
+ # Settings Panel
188
+ with gr.Column(scale=1):
189
+ role_display = gr.Markdown("")
 
 
 
190
  system_message = gr.Textbox(
191
+ label="System Message",
192
  value=DEFAULT_SYSTEM_PROMPT,
193
+ lines=3
 
194
  )
195
 
196
+ with gr.Group() as settings_group:
197
  max_tokens = gr.Slider(
198
  minimum=1,
199
  maximum=2048,
200
  value=512,
201
  step=1,
202
+ label="Max Tokens"
203
  )
204
  temperature = gr.Slider(
205
  minimum=0.1,
206
  maximum=1.0,
207
  value=0.7,
208
  step=0.1,
209
+ label="Temperature"
210
  )
211
  top_p = gr.Slider(
212
  minimum=0.1,
213
  maximum=1.0,
214
  value=0.95,
215
  step=0.05,
216
+ label="Top P"
217
  )
 
 
 
 
 
 
 
218
 
219
+ clear_button = gr.Button("Clear Chat")
220
+ logout_button = gr.Button("Logout")
 
 
221
 
222
+ # Chat Panel
223
+ with gr.Column(scale=2):
224
+ chatbot = gr.Chatbot()
225
+ msg = gr.Textbox(
226
+ show_label=False,
227
+ placeholder="Type your message here..."
228
+ )
229
+ submit_button = gr.Button("Send")
 
 
230
 
231
+ # Event Handlers
232
+ def update_interface(role):
233
+ settings_class = [] if role == "admin" else ["setting-disabled"]
234
+ return (
235
+ f"Current Role: {role.title()}",
236
+ gr.update(elem_classes=settings_class)
237
+ )
238
 
239
+ def chat_wrapper(message, history, uid, role):
240
+ if not message.strip():
241
+ return history
242
+
243
+ system_msg = system_message.value
244
+ max_tok = max_tokens.value if role == "admin" else 512
245
+ temp = temperature.value if role == "admin" else 0.7
246
+ tp = top_p.value if role == "admin" else 0.95
247
+
248
+ return chat(message, history, system_msg, max_tok, temp, tp, uid)
249
 
250
+ # Login flow
251
  login_button.click(
252
  login,
253
  inputs=[username, password],
254
  outputs=[login_group, chat_group, user_id, user_role, error_message]
255
  ).then(
256
+ update_interface,
 
 
 
 
257
  inputs=[user_role],
258
+ outputs=[role_display, settings_group]
259
  )
260
 
261
+ # Chat flow
262
+ submit_button.click(
263
+ chat_wrapper,
 
 
 
 
 
 
 
 
 
264
  inputs=[msg, chatbot, user_id, user_role],
265
+ outputs=[chatbot]
266
+ ).then(lambda: "", None, msg)
 
267
 
268
+ msg.submit(
269
+ chat_wrapper,
270
  inputs=[msg, chatbot, user_id, user_role],
271
+ outputs=[chatbot]
272
+ ).then(lambda: "", None, msg)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
273
 
274
+ # Clear chat
275
+ clear_button.click(lambda: None, None, chatbot)
 
276
 
277
+ # Logout
278
+ logout_button.click(
279
+ lambda: (
280
+ gr.update(visible=True),
281
+ gr.update(visible=False),
282
+ None,
283
+ None
284
+ ),
285
  outputs=[login_group, chat_group, user_id, user_role]
286
  )
287
 
 
 
 
 
 
 
 
 
 
288
  if __name__ == "__main__":
289
+ demo.launch(share=True)