Files changed (1) hide show
  1. app.py +139 -79
app.py CHANGED
@@ -7,41 +7,82 @@ import threading
7
  import psutil
8
  import random
9
  from transformers import pipeline
10
- from sklearn.metrics import precision_score, recall_score, f1_score
11
  import requests
12
  from datasets import load_dataset
13
  import os
 
 
 
 
 
14
 
15
- # --- Ensure chat_log.txt exists ---
16
- log_file = "chat_log.txt"
17
- try:
18
- if not os.path.exists(log_file):
19
- with open(log_file, 'w') as f:
20
- f.write("Log file created.\n") # Write a simple message to the log file
21
- print(f"{log_file} is ready for logging.")
22
- except Exception as e:
23
- print(f"Error creating log file: {e}")
24
 
25
- # --- Logging Setup ---
26
- try:
27
- logging.basicConfig(filename=log_file, level=logging.DEBUG, format='%(asctime)s - %(levelname)s - %(message)s')
28
- logging.debug("Logging setup complete.")
29
- except Exception as e:
30
- print(f"Error setting up logging: {e}")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
31
 
32
  # Load the model
33
  try:
34
  ner_pipeline = pipeline("ner", model="Sevixdd/roberta-base-finetuned-ner")
35
- logging.debug("NER pipeline loaded.")
36
  except Exception as e:
37
- logging.error(f"Error loading NER pipeline: {e}")
38
 
39
  # Load the dataset
40
  try:
41
  dataset = load_dataset("surrey-nlp/PLOD-filtered")
42
- logging.debug("Dataset loaded.")
43
  except Exception as e:
44
- logging.error(f"Error loading dataset: {e}")
45
 
46
  # --- Prometheus Metrics Setup ---
47
  try:
@@ -52,14 +93,13 @@ try:
52
  CPU_USAGE = Gauge('system_cpu_usage_percent', 'System CPU usage in percent')
53
  MEM_USAGE = Gauge('system_memory_usage_percent', 'System memory usage in percent')
54
  QUEUE_LENGTH = Gauge('chat_queue_length', 'Length of the chat queue')
55
- logging.debug("Prometheus metrics setup complete.")
56
  except Exception as e:
57
- logging.error(f"Error setting up Prometheus metrics: {e}")
58
 
59
  # --- Queue and Metrics ---
60
  chat_queue = Queue() # Define chat_queue globally
61
 
62
- # Label mapping
63
  label_mapping = {
64
  0: 'B-O',
65
  1: 'B-AC',
@@ -67,26 +107,10 @@ label_mapping = {
67
  4: 'I-LF'
68
  }
69
 
70
- # --- Chat Function with Monitoring ---
71
- def chat_function(index):
72
- logging.debug("Starting chat_function")
73
- with REQUEST_LATENCY.time():
74
- REQUEST_COUNT.inc()
75
- try:
76
- chat_queue.put(index)
77
- logging.info(f"Received index from user: {index}")
78
-
79
- # Get the example from the dataset
80
- example = dataset['train'][int(index)]
81
- tokens = example['tokens']
82
- ground_truth_labels = [label_mapping[label] for label in example['ner_tags']]
83
-
84
- logging.info(f"Tokens: {tokens}")
85
- logging.info(f"Ground Truth Labels: {ground_truth_labels}")
86
 
87
- # Predict using the model
88
- ner_results = ner_pipeline(" ".join(tokens))
89
- logging.debug(f"NER results: {ner_results}")
90
 
91
  detailed_response = []
92
  model_predicted_labels = []
@@ -99,42 +123,73 @@ def chat_function(index):
99
  detailed_response.append(f"Token: {token}, Entity: {label_mapping[label_id]}, Score: {score:.4f}")
100
 
101
  response = "\n".join(detailed_response)
102
- logging.info(f"Generated response: {response}")
103
-
104
  response_size = len(response.encode('utf-8'))
105
  RESPONSE_SIZE.observe(response_size)
106
 
107
  time.sleep(random.uniform(0.5, 2.5)) # Simulate processing time
108
 
109
- # Ensure the model and ground truth labels are the same length for comparison
110
- model_predicted_labels = model_predicted_labels[:len(ground_truth_labels)]
111
-
112
- precision = precision_score(ground_truth_labels, model_predicted_labels, average='weighted', zero_division=0)
113
- recall = recall_score(ground_truth_labels, model_predicted_labels, average='weighted', zero_division=0)
114
- f1 = f1_score(ground_truth_labels, model_predicted_labels, average='weighted', zero_division=0)
115
-
116
- metrics_response = (f"Precision: {precision:.4f}\n"
117
- f"Recall: {recall:.4f}\n"
118
- f"F1 Score: {f1:.4f}")
119
-
120
- full_response = f"**Record**:\nTokens: {tokens}\nGround Truth Labels: {ground_truth_labels}\n\n**Predictions**:\n{response}\n\n**Metrics**:\n{metrics_response}"
121
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
122
  chat_queue.get()
123
- logging.debug("Finished processing message")
124
  return full_response
125
  except Exception as e:
126
  ERROR_COUNT.inc()
127
- logging.error(f"Error in chat processing: {e}", exc_info=True)
128
  return f"An error occurred. Please try again. Error: {e}"
129
 
130
  # Function to simulate stress test
131
- def stress_test(num_requests, index, delay):
132
  def send_chat_message():
133
- response = requests.post("http://127.0.0.1:7860/api/predict/", json={
134
- "data": [index],
135
- "fn_index": 0 # This might need to be updated based on your Gradio app's function index
136
- })
137
- logging.debug(response.json())
 
 
 
 
138
 
139
  threads = []
140
  for _ in range(num_requests):
@@ -146,20 +201,21 @@ def stress_test(num_requests, index, delay):
146
  for t in threads:
147
  t.join()
148
 
 
149
  # --- Gradio Interface with Background Image and Three Windows ---
150
- with gr.Blocks(css="""
151
- body {
152
- background-image: url("stag.jpeg");
153
- background-size: cover;
154
- background-repeat: no-repeat;
155
- }
156
- """, title="PLOD Filtered with Monitoring") as demo: # Load CSS for background image
157
- with gr.Tab("Chat"):
158
  gr.Markdown("## Chat with the Bot")
159
- index_input = gr.Textbox(label="Enter dataset index:", lines=1)
160
  output = gr.Markdown(label="Response")
161
  chat_interface = gr.Interface(fn=chat_function, inputs=[index_input], outputs=output)
162
- chat_interface.render()
 
 
 
 
 
163
 
164
  with gr.Tab("Model Parameters"):
165
  model_params_display = gr.Textbox(label="Model Parameters", lines=20, interactive=False) # Display model parameters
@@ -191,7 +247,9 @@ body {
191
  stress_test_status.value = f"Stress test failed: {e}"
192
 
193
  stress_test_button.click(run_stress_test, [num_requests_input, index_input_stress, delay_input], stress_test_status)
194
-
 
 
195
  # --- Update Functions ---
196
  def update_metrics(request_count_display, avg_latency_display):
197
  while True:
@@ -214,9 +272,11 @@ body {
214
 
215
  def update_logs(logs_display):
216
  while True:
217
- with open(log_file, "r") as log_file_handler:
218
- logs = log_file_handler.readlines()
219
- logs_display.value = "".join(logs[-10:]) # Display last 10 lines
 
 
220
  time.sleep(1) # Update every 1 second
221
 
222
  def display_model_params(model_params_display):
@@ -235,7 +295,7 @@ body {
235
  threading.Thread(target=start_http_server, args=(8000,), daemon=True).start()
236
  threading.Thread(target=update_metrics, args=(request_count_display, avg_latency_display), daemon=True).start()
237
  threading.Thread(target=update_usage, args=(cpu_usage_display, mem_usage_display), daemon=True).start()
238
- threading.Thread(target=update_logs, args=(logs_display,), daemon=True).start()
239
  threading.Thread(target=display_model_params, args=(model_params_display,), daemon=True).start()
240
  threading.Thread(target=update_queue_length, daemon=True).start()
241
 
 
7
  import psutil
8
  import random
9
  from transformers import pipeline
10
+ from sklearn.metrics import precision_score, recall_score, f1_score, accuracy_score
11
  import requests
12
  from datasets import load_dataset
13
  import os
14
+ from logging import FileHandler
15
+ from __future__ import annotations
16
+ from typing import Iterable
17
+ from gradio.themes.base import Base
18
+ from gradio.themes.utils import colors, fonts, sizes
19
 
 
 
 
 
 
 
 
 
 
20
 
21
+ # Ensure the log files exist
22
+ log_file_path = 'chat_log.log'
23
+ debug_log_file_path = 'debug.log'
24
+ if not os.path.exists(log_file_path):
25
+ with open(log_file_path, 'w') as f:
26
+ f.write(" ")
27
+ if not os.path.exists(debug_log_file_path):
28
+ with open(debug_log_file_path, 'w') as f:
29
+ f.write(" ")
30
+
31
+
32
+ # Create logger instance
33
+ logger = logging.getLogger()
34
+ logger.setLevel(logging.DEBUG) # Set logger level to the lowest level needed
35
+
36
+ #Create formatter
37
+ formatter = logging.Formatter(
38
+ '%(asctime)s - %(name)s - %(levelname)s - %(message)s', datefmt='%d-%b-%y %H:%M:%S')
39
+
40
+ # Create handlers
41
+ info_handler = FileHandler( filename=log_file_path, mode='w+')
42
+ info_handler.setLevel(logging.INFO)
43
+ info_handler.setFormatter(formatter)
44
+
45
+ debug_handler = FileHandler(filename=debug_log_file_path, mode='w+')
46
+ debug_handler.setLevel(logging.DEBUG)
47
+ debug_handler.setFormatter(formatter)
48
+
49
+
50
+ # Function to capture logs for Gradio display
51
+ class GradioHandler(logging.Handler):
52
+ def __init__(self, logs_queue):
53
+ super().__init__()
54
+ self.logs_queue = logs_queue
55
+
56
+ def emit(self, record):
57
+ log_entry = self.format(record)
58
+ self.logs_queue.put(log_entry)
59
+
60
+ # Create a logs queue
61
+ logs_queue = Queue()
62
+
63
+ # Create and configure Gradio handler
64
+ gradio_handler = GradioHandler(logs_queue)
65
+ gradio_handler.setLevel(logging.INFO)
66
+ gradio_handler.setFormatter(formatter)
67
+
68
+ # Add handlers to the logger
69
+ logger.addHandler(info_handler)
70
+ logger.addHandler(debug_handler)
71
+ logger.addHandler(gradio_handler)
72
 
73
  # Load the model
74
  try:
75
  ner_pipeline = pipeline("ner", model="Sevixdd/roberta-base-finetuned-ner")
76
+ logger.debug("NER pipeline loaded.")
77
  except Exception as e:
78
+ logger.debug(f"Error loading NER pipeline: {e}")
79
 
80
  # Load the dataset
81
  try:
82
  dataset = load_dataset("surrey-nlp/PLOD-filtered")
83
+ logger.debug("Dataset loaded.")
84
  except Exception as e:
85
+ logger.debug(f"Error loading dataset: {e}")
86
 
87
  # --- Prometheus Metrics Setup ---
88
  try:
 
93
  CPU_USAGE = Gauge('system_cpu_usage_percent', 'System CPU usage in percent')
94
  MEM_USAGE = Gauge('system_memory_usage_percent', 'System memory usage in percent')
95
  QUEUE_LENGTH = Gauge('chat_queue_length', 'Length of the chat queue')
96
+ logger.debug("Prometheus metrics setup complete.")
97
  except Exception as e:
98
+ logger.debug(f"Error setting up Prometheus metrics: {e}")
99
 
100
  # --- Queue and Metrics ---
101
  chat_queue = Queue() # Define chat_queue globally
102
 
 
103
  label_mapping = {
104
  0: 'B-O',
105
  1: 'B-AC',
 
107
  4: 'I-LF'
108
  }
109
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
110
 
111
+ def classification(message):
112
+ # Predict using the model
113
+ ner_results = ner_pipeline(" ".join(message))
114
 
115
  detailed_response = []
116
  model_predicted_labels = []
 
123
  detailed_response.append(f"Token: {token}, Entity: {label_mapping[label_id]}, Score: {score:.4f}")
124
 
125
  response = "\n".join(detailed_response)
 
 
126
  response_size = len(response.encode('utf-8'))
127
  RESPONSE_SIZE.observe(response_size)
128
 
129
  time.sleep(random.uniform(0.5, 2.5)) # Simulate processing time
130
 
131
+ return response, model_predicted_labels
 
 
 
 
 
 
 
 
 
 
 
132
 
133
+ # --- Chat Function with Monitoring ---
134
+ def chat_function(input, datasets):
135
+ logger.debug("Starting chat_function")
136
+ with REQUEST_LATENCY.time():
137
+ REQUEST_COUNT.inc()
138
+ try:
139
+ if input.isnumeric():
140
+ chat_queue.put(input)
141
+ # Get the example from the dataset
142
+ if datasets:
143
+ example = datasets[int(input)]
144
+ else:
145
+ example = dataset['train'][int(input)]
146
+ tokens = example['tokens']
147
+ ground_truth_labels = [label_mapping[label] for label in example['ner_tags']]
148
+
149
+ # Call the classification function
150
+ response, model_predicted_labels = classification(tokens)
151
+
152
+
153
+ # Ensure the model and ground truth labels are the same length for comparison
154
+ model_predicted_labels = model_predicted_labels[:len(ground_truth_labels)]
155
+
156
+ precision = precision_score(ground_truth_labels, model_predicted_labels, average='weighted', zero_division=0)
157
+ recall = recall_score(ground_truth_labels, model_predicted_labels, average='weighted', zero_division=0)
158
+ f1 = f1_score(ground_truth_labels, model_predicted_labels, average='weighted', zero_division=0)
159
+ accuracy = accuracy_score(ground_truth_labels, model_predicted_labels)
160
+
161
+ metrics_response = (f"Precision: {precision:.4f}\n"
162
+ f"Recall: {recall:.4f}\n"
163
+ f"F1 Score: {f1:.4f}\n"
164
+ f"Accuracy: {accuracy:.4f}")
165
+
166
+ full_response = f"**Record**:\nTokens: {tokens}\nGround Truth Labels: {ground_truth_labels}\n\n**Predictions**:\n{response}\n\n**Metrics**:\n{metrics_response}"
167
+ logger.info(f"\nInput details: \n Received index from user: {input} Sending response to user: {full_response}")
168
+ else:
169
+ chat_queue.put(input)
170
+ response, predicted_labels = classification([input])
171
+ full_response = f"Input details: \n**Input Sentence:** {input}\n\n**Predictions**:\n{response}\n\n"
172
+ logger.info(full_response)
173
+
174
  chat_queue.get()
 
175
  return full_response
176
  except Exception as e:
177
  ERROR_COUNT.inc()
178
+ logger.error(f"Error in chat processing: {e}", exc_info=True)
179
  return f"An error occurred. Please try again. Error: {e}"
180
 
181
  # Function to simulate stress test
182
+ def stress_test(num_requests, message, delay):
183
  def send_chat_message():
184
+ try:
185
+ response = requests.post("http://127.0.0.1:7860/api/predict/", json={
186
+ "data": [message],
187
+ "fn_index": 0 # This might need to be updated based on your Gradio app's function index
188
+ })
189
+ logger.debug(f"Request payload: {message}",exc_info=True)
190
+ logger.debug(f"Response: {response.json()}",exc_info=True)
191
+ except Exception as e:
192
+ logger.debug(f"Error during stress test request: {e}", exc_info=True)
193
 
194
  threads = []
195
  for _ in range(num_requests):
 
201
  for t in threads:
202
  t.join()
203
 
204
+
205
  # --- Gradio Interface with Background Image and Three Windows ---
206
+ with gr.Blocks(title="PLOD Filtered with Monitoring") as demo: # Load CSS for background image
207
+
208
+ with gr.Tab("Sentence input"):
 
 
 
 
 
209
  gr.Markdown("## Chat with the Bot")
210
+ index_input = gr.Textbox(label="Enter A sentence:", lines=1)
211
  output = gr.Markdown(label="Response")
212
  chat_interface = gr.Interface(fn=chat_function, inputs=[index_input], outputs=output)
213
+
214
+ with gr.Tab("Dataset and Index Input"):
215
+ gr.Markdown("## Chat with the Bot")
216
+ interface = gr.Interface(fn = chat_function,
217
+ inputs=[gr.Textbox(label="Enter dataset index:", lines=1), gr.UploadButton(label ="Upload Dataset", file_types=[".csv", ".tsv"])],
218
+ outputs = gr.Markdown(label="Response"))
219
 
220
  with gr.Tab("Model Parameters"):
221
  model_params_display = gr.Textbox(label="Model Parameters", lines=20, interactive=False) # Display model parameters
 
247
  stress_test_status.value = f"Stress test failed: {e}"
248
 
249
  stress_test_button.click(run_stress_test, [num_requests_input, index_input_stress, delay_input], stress_test_status)
250
+ img = gr.Image(
251
+ "stag.jpeg", label="Image"
252
+ )
253
  # --- Update Functions ---
254
  def update_metrics(request_count_display, avg_latency_display):
255
  while True:
 
272
 
273
  def update_logs(logs_display):
274
  while True:
275
+ info_log_vector = []
276
+ logs = []
277
+ while not logs_queue.empty():
278
+ logs.append(logs_queue.get())
279
+ logs_display.value = "\n".join(logs[-10:])
280
  time.sleep(1) # Update every 1 second
281
 
282
  def display_model_params(model_params_display):
 
295
  threading.Thread(target=start_http_server, args=(8000,), daemon=True).start()
296
  threading.Thread(target=update_metrics, args=(request_count_display, avg_latency_display), daemon=True).start()
297
  threading.Thread(target=update_usage, args=(cpu_usage_display, mem_usage_display), daemon=True).start()
298
+ threading.Thread(target=update_logs, args=(logs_display), daemon=True).start()
299
  threading.Thread(target=display_model_params, args=(model_params_display,), daemon=True).start()
300
  threading.Thread(target=update_queue_length, daemon=True).start()
301