Rulga commited on
Commit
f14b205
·
1 Parent(s): acdfff5

No code changes made; skipping commit.

Browse files
Files changed (1) hide show
  1. app.py +175 -40
app.py CHANGED
@@ -26,58 +26,60 @@ from web.training_interface import (
26
  if not HF_TOKEN:
27
  raise ValueError("HUGGINGFACE_TOKEN not found in environment variables")
28
 
29
- # Extended model information
30
  MODEL_DETAILS = {
31
  "llama-7b": {
32
  "full_name": "Meta Llama 2 7B Chat",
33
  "capabilities": [
34
- "Multilingual (supports Russian, English and other languages)",
35
  "Good performance on legal texts",
36
  "Free model with open license",
37
- "Easy to run on computers with 16GB+ RAM"
38
  ],
39
  "limitations": [
40
  "Limited knowledge of specific legal terminology",
41
- "May give incorrect answers to complex legal questions",
42
- "Knowledge limited by training data"
43
  ],
44
  "use_cases": [
45
  "Legal document analysis",
46
  "Answering general legal questions",
47
- "Legal knowledge base search",
48
- "Document drafting assistance"
49
  ],
50
  "documentation": "https://huggingface.co/meta-llama/Llama-2-7b-chat-hf"
51
  },
52
  "zephyr-7b": {
53
  "full_name": "HuggingFaceH4 Zephyr 7B Beta",
54
  "capabilities": [
55
- "High performance on instruction tasks",
56
  "Good response accuracy",
57
- "Advanced reasoning",
58
  "Excellent text generation quality"
59
  ],
60
  "limitations": [
61
- "May require API payment for usage",
62
  "Limited support for languages other than English",
63
- "Less optimization for legal topics than specialized models"
64
  ],
65
  "use_cases": [
66
  "Complex legal reasoning",
67
- "Case law analysis",
68
- "Legislative research",
69
  "Structured legal text generation"
70
  ],
71
  "documentation": "https://huggingface.co/HuggingFaceH4/zephyr-7b-beta"
72
  }
73
  }
74
 
75
- # Путь к файлу с пользовательскими настройками
76
  USER_PREFERENCES_PATH = os.path.join(os.path.dirname(__file__), "user_preferences.json")
 
77
 
78
- # Глобальные переменные
79
  client = None
80
  context_store = {}
 
81
 
82
  print(f"Chat histories will be saved to: {CHAT_HISTORY_PATH}")
83
 
@@ -132,6 +134,33 @@ def initialize_client(model_id=None):
132
  )
133
  return client
134
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
135
  def get_context(message, conversation_id):
136
  """Get context from knowledge base"""
137
  vector_store = load_vector_store()
@@ -191,7 +220,11 @@ def respond(
191
  max_tokens,
192
  temperature,
193
  top_p,
 
194
  ):
 
 
 
195
  # Create ID for new conversation
196
  if not conversation_id:
197
  import uuid
@@ -231,10 +264,6 @@ def respond(
231
  # Debug: print API messages
232
  print("Debug - API messages:", messages)
233
 
234
- # Send API request and stream response
235
- response = ""
236
- is_complete = False
237
-
238
  try:
239
  # Non-streaming version for debugging
240
  full_response = client.chat_completion(
@@ -248,6 +277,9 @@ def respond(
248
  response = full_response.choices[0].message.content
249
  print(f"Debug - Full response from API: {response}")
250
 
 
 
 
251
  # Return complete response immediately
252
  final_history = history.copy() if history else []
253
  final_history.append((message, response))
@@ -255,10 +287,92 @@ def respond(
255
 
256
  except Exception as e:
257
  print(f"Debug - Error during API call: {str(e)}")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
258
  error_history = history.copy() if history else []
259
- error_history.append((message, f"An error occurred: {str(e)}"))
260
  yield error_history, conversation_id
261
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
262
 
263
  def update_kb():
264
  """Function to update existing knowledge base with new documents"""
@@ -341,14 +455,29 @@ def respond_and_clear(message, history, conversation_id):
341
  # Debug the response
342
  print("Debug - Final history:", new_history)
343
 
344
- # Save chat history after response
 
 
 
 
345
  save_chat_history(new_history, conv_id)
346
 
347
  return new_history, conv_id, "" # Clear message input
348
 
349
  except Exception as e:
350
  print(f"Error in respond_and_clear: {str(e)}")
351
- error_history = history + [(message, f"An error occurred: {str(e)}")]
 
 
 
 
 
 
 
 
 
 
 
352
 
353
  # Still try to save history with error
354
  if conversation_id:
@@ -372,7 +501,7 @@ def update_model_info(model_key):
372
  def get_model_details_html(model_key):
373
  """Get detailed HTML for model information panel"""
374
  if model_key not in MODEL_DETAILS:
375
- return "<p>Информация о модели недоступна</p>"
376
 
377
  details = MODEL_DETAILS[model_key]
378
 
@@ -380,22 +509,22 @@ def get_model_details_html(model_key):
380
  <div style="padding: 15px; border: 1px solid #ccc; border-radius: 5px; margin-top: 10px;">
381
  <h3>{details['full_name']}</h3>
382
 
383
- <h4>Возможности:</h4>
384
  <ul>
385
  {"".join([f"<li>{cap}</li>" for cap in details['capabilities']])}
386
  </ul>
387
 
388
- <h4>Ограничения:</h4>
389
  <ul>
390
  {"".join([f"<li>{lim}</li>" for lim in details['limitations']])}
391
  </ul>
392
 
393
- <h4>Рекомендуемое использование:</h4>
394
  <ul>
395
  {"".join([f"<li>{use}</li>" for use in details['use_cases']])}
396
  </ul>
397
 
398
- <p><a href="{details['documentation']}" target="_blank">Документация модели</a></p>
399
  </div>
400
  """
401
 
@@ -403,9 +532,12 @@ def get_model_details_html(model_key):
403
 
404
  def change_model(model_key):
405
  """Change active model and update parameters"""
406
- global client, ACTIVE_MODEL
407
 
408
  try:
 
 
 
409
  # Update active model
410
  ACTIVE_MODEL = MODELS[model_key]
411
 
@@ -415,7 +547,7 @@ def change_model(model_key):
415
  token=HF_TOKEN
416
  )
417
 
418
- # Сохраняем выбранную модель в предпочтениях
419
  save_user_preferences(model_key)
420
 
421
  # Return both model info and updated parameters
@@ -445,7 +577,7 @@ def save_parameters(model_key, max_len, temp, top_p_val, rep_pen):
445
  ACTIVE_MODEL['parameters']['top_p'] = top_p_val
446
  ACTIVE_MODEL['parameters']['repetition_penalty'] = rep_pen
447
 
448
- # Сохраняем параметры в предпочтениях
449
  params = {
450
  'max_length': max_len,
451
  'temperature': temp,
@@ -465,19 +597,19 @@ def initialize_app():
465
  preferences = load_user_preferences()
466
  selected_model = preferences.get("selected_model", DEFAULT_MODEL)
467
 
468
- # Убедиться, что выбранная модель существует
469
  if selected_model not in MODELS:
470
  selected_model = DEFAULT_MODEL
471
 
472
- # Установить активную модель
473
  ACTIVE_MODEL = MODELS[selected_model]
474
 
475
- # Загрузить сохраненные параметры, если они есть
476
  saved_params = preferences.get("parameters", {}).get(selected_model)
477
  if saved_params:
478
  ACTIVE_MODEL['parameters'].update(saved_params)
479
 
480
- # Инициализировать клиент
481
  client = InferenceClient(
482
  ACTIVE_MODEL["id"],
483
  token=HF_TOKEN
@@ -491,10 +623,10 @@ selected_model = initialize_app()
491
 
492
  # Create interface
493
  with gr.Blocks() as demo:
494
- # Определяем функцию clear_conversation внутри блока для доступа к компонентам
495
  def clear_conversation():
496
  """Clear conversation and save history before clearing"""
497
- return [], None # Просто возвращаем пустые значения
498
 
499
  with gr.Tabs():
500
  with gr.Tab("Chat"):
@@ -604,7 +736,7 @@ with gr.Blocks() as demo:
604
  interactive=True
605
  )
606
 
607
- # Save parameters button
608
  save_params_btn = gr.Button("Save Parameters", variant="primary")
609
 
610
  gr.Markdown("""
@@ -672,14 +804,14 @@ with gr.Blocks() as demo:
672
  outputs=[model_info, max_length, temperature, top_p, rep_penalty, model_loading]
673
  )
674
 
675
- # Update model details panel when model changes
676
  model_selector.change(
677
  fn=get_model_details_html,
678
  inputs=[model_selector],
679
  outputs=[model_details]
680
  )
681
 
682
- # Parameters save handler
683
  save_params_btn.click(
684
  fn=save_parameters,
685
  inputs=[model_selector, max_length, temperature, top_p, rep_penalty],
@@ -688,8 +820,11 @@ with gr.Blocks() as demo:
688
 
689
  # Launch application
690
  if __name__ == "__main__":
 
 
 
691
  # Check knowledge base availability in dataset
692
  if not load_vector_store():
693
  print("Knowledge base not found. Please create it through the interface.")
694
 
695
- demo.launch()
 
26
  if not HF_TOKEN:
27
  raise ValueError("HUGGINGFACE_TOKEN not found in environment variables")
28
 
29
+ # Enhanced model details for UI
30
  MODEL_DETAILS = {
31
  "llama-7b": {
32
  "full_name": "Meta Llama 2 7B Chat",
33
  "capabilities": [
34
+ "Multilingual support ",
35
  "Good performance on legal texts",
36
  "Free model with open license",
37
+ "Can run on computers with 16GB+ RAM"
38
  ],
39
  "limitations": [
40
  "Limited knowledge of specific legal terminology",
41
+ "May provide incorrect answers to complex legal questions",
42
+ "Knowledge is limited to training data"
43
  ],
44
  "use_cases": [
45
  "Legal document analysis",
46
  "Answering general legal questions",
47
+ "Searching through legal knowledge base",
48
+ "Assistance in document drafting"
49
  ],
50
  "documentation": "https://huggingface.co/meta-llama/Llama-2-7b-chat-hf"
51
  },
52
  "zephyr-7b": {
53
  "full_name": "HuggingFaceH4 Zephyr 7B Beta",
54
  "capabilities": [
55
+ "High performance on instruction-following tasks",
56
  "Good response accuracy",
57
+ "Advanced reasoning capabilities",
58
  "Excellent text generation quality"
59
  ],
60
  "limitations": [
61
+ "May require paid API for usage",
62
  "Limited support for languages other than English",
63
+ "Less optimization for legal topics compared to specialized models"
64
  ],
65
  "use_cases": [
66
  "Complex legal reasoning",
67
+ "Case analysis",
68
+ "Legal research",
69
  "Structured legal text generation"
70
  ],
71
  "documentation": "https://huggingface.co/HuggingFaceH4/zephyr-7b-beta"
72
  }
73
  }
74
 
75
+ # Path for user preferences file
76
  USER_PREFERENCES_PATH = os.path.join(os.path.dirname(__file__), "user_preferences.json")
77
+ ERROR_LOGS_PATH = os.path.join(os.path.dirname(__file__), "error_logs")
78
 
79
+ # Global variables
80
  client = None
81
  context_store = {}
82
+ fallback_model_attempted = False
83
 
84
  print(f"Chat histories will be saved to: {CHAT_HISTORY_PATH}")
85
 
 
134
  )
135
  return client
136
 
137
+ def switch_to_model(model_key):
138
+ """Switch to specified model and update global variables"""
139
+ global ACTIVE_MODEL, client
140
+
141
+ try:
142
+ # Update active model
143
+ ACTIVE_MODEL = MODELS[model_key]
144
+
145
+ # Reinitialize client with new model
146
+ client = InferenceClient(
147
+ ACTIVE_MODEL["id"],
148
+ token=HF_TOKEN
149
+ )
150
+
151
+ print(f"Switched to model: {model_key}")
152
+ return True
153
+ except Exception as e:
154
+ print(f"Error switching to model {model_key}: {str(e)}")
155
+ return False
156
+
157
+ def get_fallback_model(current_model):
158
+ """Get a fallback model different from the current one"""
159
+ for key in MODELS.keys():
160
+ if key != current_model:
161
+ return key
162
+ return None # No fallback available
163
+
164
  def get_context(message, conversation_id):
165
  """Get context from knowledge base"""
166
  vector_store = load_vector_store()
 
220
  max_tokens,
221
  temperature,
222
  top_p,
223
+ attempt_fallback=True
224
  ):
225
+ """Generate response using the current model with fallback option"""
226
+ global fallback_model_attempted
227
+
228
  # Create ID for new conversation
229
  if not conversation_id:
230
  import uuid
 
264
  # Debug: print API messages
265
  print("Debug - API messages:", messages)
266
 
 
 
 
 
267
  try:
268
  # Non-streaming version for debugging
269
  full_response = client.chat_completion(
 
277
  response = full_response.choices[0].message.content
278
  print(f"Debug - Full response from API: {response}")
279
 
280
+ # Reset fallback flag on successful API call
281
+ fallback_model_attempted = False
282
+
283
  # Return complete response immediately
284
  final_history = history.copy() if history else []
285
  final_history.append((message, response))
 
287
 
288
  except Exception as e:
289
  print(f"Debug - Error during API call: {str(e)}")
290
+ error_message = str(e)
291
+ current_model_key = None
292
+
293
+ # Find current model key
294
+ for key, model in MODELS.items():
295
+ if model["id"] == ACTIVE_MODEL["id"]:
296
+ current_model_key = key
297
+ break
298
+
299
+ # Try fallback model if appropriate
300
+ if attempt_fallback and ("402" in error_message or "429" in error_message) and not fallback_model_attempted:
301
+ fallback_model_key = get_fallback_model(current_model_key)
302
+ if fallback_model_key:
303
+ fallback_model_attempted = True
304
+
305
+ # Log fallback attempt
306
+ print(f"Attempting to fallback from {current_model_key} to {fallback_model_key}")
307
+ log_api_error(message, error_message, ACTIVE_MODEL["id"], is_fallback=True)
308
+
309
+ # Switch model temporarily
310
+ original_model = ACTIVE_MODEL.copy()
311
+ if switch_to_model(fallback_model_key):
312
+ # Try with fallback model (but don't fallback again)
313
+ fallback_generator = respond(
314
+ message,
315
+ history,
316
+ conversation_id,
317
+ system_message,
318
+ max_tokens,
319
+ temperature,
320
+ top_p,
321
+ attempt_fallback=False
322
+ )
323
+
324
+ yield from fallback_generator
325
+
326
+ # Restore original model
327
+ ACTIVE_MODEL.update(original_model)
328
+ initialize_client(ACTIVE_MODEL["id"])
329
+ return
330
+
331
+ # Format user-friendly error message
332
+ if "402" in error_message and "Payment Required" in error_message:
333
+ friendly_error = (
334
+ "⚠️ API Error: Free request limit exceeded for this model.\n\n"
335
+ "Solutions:\n"
336
+ "1. Switch to another model in the 'Model Settings' tab\n"
337
+ "2. Use a local model version\n"
338
+ "3. Subscribe to Hugging Face PRO for higher limits"
339
+ )
340
+ elif "401" in error_message and "Unauthorized" in error_message:
341
+ friendly_error = (
342
+ "⚠️ API Error: Authentication problem. Please check your API key."
343
+ )
344
+ elif "429" in error_message and "Too Many Requests" in error_message:
345
+ friendly_error = (
346
+ "⚠️ API Error: Too many requests. Please try again later."
347
+ )
348
+ else:
349
+ friendly_error = f"⚠️ API Error: There was an error accessing the model. Details: {error_message}"
350
+
351
+ # Log the error
352
+ log_api_error(message, error_message, ACTIVE_MODEL["id"])
353
+
354
  error_history = history.copy() if history else []
355
+ error_history.append((message, friendly_error))
356
  yield error_history, conversation_id
357
 
358
+ def log_api_error(user_message, error_message, model_id, is_fallback=False):
359
+ """Log API errors to a separate file for monitoring"""
360
+ try:
361
+ os.makedirs(ERROR_LOGS_PATH, exist_ok=True)
362
+
363
+ timestamp = datetime.datetime.now().strftime("%Y%m%d-%H%M%S")
364
+ log_path = os.path.join(ERROR_LOGS_PATH, f"api_error_{timestamp}.log")
365
+
366
+ with open(log_path, 'w', encoding='utf-8') as f:
367
+ f.write(f"Timestamp: {datetime.datetime.now().isoformat()}\n")
368
+ f.write(f"Model: {model_id}\n")
369
+ f.write(f"User message: {user_message}\n")
370
+ f.write(f"Error: {error_message}\n")
371
+ f.write(f"Fallback attempt: {is_fallback}\n")
372
+
373
+ print(f"API error logged to {log_path}")
374
+ except Exception as e:
375
+ print(f"Failed to log API error: {str(e)}")
376
 
377
  def update_kb():
378
  """Function to update existing knowledge base with new documents"""
 
455
  # Debug the response
456
  print("Debug - Final history:", new_history)
457
 
458
+ # Check if the history contains errors (special formatting for error messages)
459
+ last_message = new_history[-1] if new_history else None
460
+ is_error = last_message and isinstance(last_message[1], str) and "⚠️ API Error" in last_message[1]
461
+
462
+ # Save chat history after response (even with errors)
463
  save_chat_history(new_history, conv_id)
464
 
465
  return new_history, conv_id, "" # Clear message input
466
 
467
  except Exception as e:
468
  print(f"Error in respond_and_clear: {str(e)}")
469
+
470
+ # Create a more readable error message
471
+ if "incompatible with messages format" in str(e):
472
+ error_message = (
473
+ "⚠️ Message processing error: Problem with message format.\n\n"
474
+ "Please try to clear the chat history using the 'Clear' button or "
475
+ "switch to another model."
476
+ )
477
+ else:
478
+ error_message = f"⚠️ Error: {str(e)}"
479
+
480
+ error_history = history + [(message, error_message)]
481
 
482
  # Still try to save history with error
483
  if conversation_id:
 
501
  def get_model_details_html(model_key):
502
  """Get detailed HTML for model information panel"""
503
  if model_key not in MODEL_DETAILS:
504
+ return "<p>Model information not available</p>"
505
 
506
  details = MODEL_DETAILS[model_key]
507
 
 
509
  <div style="padding: 15px; border: 1px solid #ccc; border-radius: 5px; margin-top: 10px;">
510
  <h3>{details['full_name']}</h3>
511
 
512
+ <h4>Capabilities:</h4>
513
  <ul>
514
  {"".join([f"<li>{cap}</li>" for cap in details['capabilities']])}
515
  </ul>
516
 
517
+ <h4>Limitations:</h4>
518
  <ul>
519
  {"".join([f"<li>{lim}</li>" for lim in details['limitations']])}
520
  </ul>
521
 
522
+ <h4>Recommended Use Cases:</h4>
523
  <ul>
524
  {"".join([f"<li>{use}</li>" for use in details['use_cases']])}
525
  </ul>
526
 
527
+ <p><a href="{details['documentation']}" target="_blank">Model Documentation</a></p>
528
  </div>
529
  """
530
 
 
532
 
533
  def change_model(model_key):
534
  """Change active model and update parameters"""
535
+ global client, ACTIVE_MODEL, fallback_model_attempted
536
 
537
  try:
538
+ # Reset fallback flag when explicitly changing model
539
+ fallback_model_attempted = False
540
+
541
  # Update active model
542
  ACTIVE_MODEL = MODELS[model_key]
543
 
 
547
  token=HF_TOKEN
548
  )
549
 
550
+ # Save selected model in preferences
551
  save_user_preferences(model_key)
552
 
553
  # Return both model info and updated parameters
 
577
  ACTIVE_MODEL['parameters']['top_p'] = top_p_val
578
  ACTIVE_MODEL['parameters']['repetition_penalty'] = rep_pen
579
 
580
+ # Save parameters in preferences
581
  params = {
582
  'max_length': max_len,
583
  'temperature': temp,
 
597
  preferences = load_user_preferences()
598
  selected_model = preferences.get("selected_model", DEFAULT_MODEL)
599
 
600
+ # Make sure the selected model exists
601
  if selected_model not in MODELS:
602
  selected_model = DEFAULT_MODEL
603
 
604
+ # Set active model
605
  ACTIVE_MODEL = MODELS[selected_model]
606
 
607
+ # Load saved parameters if they exist
608
  saved_params = preferences.get("parameters", {}).get(selected_model)
609
  if saved_params:
610
  ACTIVE_MODEL['parameters'].update(saved_params)
611
 
612
+ # Initialize client
613
  client = InferenceClient(
614
  ACTIVE_MODEL["id"],
615
  token=HF_TOKEN
 
623
 
624
  # Create interface
625
  with gr.Blocks() as demo:
626
+ # Define clear_conversation function within the block for component access
627
  def clear_conversation():
628
  """Clear conversation and save history before clearing"""
629
+ return [], None # Just return empty values
630
 
631
  with gr.Tabs():
632
  with gr.Tab("Chat"):
 
736
  interactive=True
737
  )
738
 
739
+ # Button to save parameters
740
  save_params_btn = gr.Button("Save Parameters", variant="primary")
741
 
742
  gr.Markdown("""
 
804
  outputs=[model_info, max_length, temperature, top_p, rep_penalty, model_loading]
805
  )
806
 
807
+ # Update model details panel when changing model
808
  model_selector.change(
809
  fn=get_model_details_html,
810
  inputs=[model_selector],
811
  outputs=[model_details]
812
  )
813
 
814
+ # Parameter save handler
815
  save_params_btn.click(
816
  fn=save_parameters,
817
  inputs=[model_selector, max_length, temperature, top_p, rep_penalty],
 
820
 
821
  # Launch application
822
  if __name__ == "__main__":
823
+ # Create error logs directory
824
+ os.makedirs(ERROR_LOGS_PATH, exist_ok=True)
825
+
826
  # Check knowledge base availability in dataset
827
  if not load_vector_store():
828
  print("Knowledge base not found. Please create it through the interface.")
829
 
830
+ demo.launch()