monsimas commited on
Commit
5ee2a2a
1 Parent(s): 9634edc

major changes

Browse files
Files changed (3) hide show
  1. app.py +71 -25
  2. categorization_logs.log +5 -0
  3. requirements.txt +2 -1
app.py CHANGED
@@ -10,6 +10,10 @@ from collections import Counter
10
  import numpy as np
11
  import logging
12
  from collections import defaultdict
 
 
 
 
13
 
14
 
15
  # Configurer le niveau du logger racine
@@ -53,7 +57,7 @@ def make_request_with_retry(client, model, messages, temperature=0.7, retries=3,
53
  logging.error("Le nombre maximal de tentatives a été atteint sans succès.")
54
  raise Exception("Le nombre maximal de tentatives a été atteint")
55
 
56
- def get_consistent_categories(proposal, categories, client, model, temperature, allow_multiple_categories, validation_retries, coinciding_retries_threshold, max_attempts=5):
57
  proposal_str = str(proposal)
58
 
59
  responses = []
@@ -102,30 +106,55 @@ def get_consistent_categories(proposal, categories, client, model, temperature,
102
  return "Aucune catégorie trouvée", model_responses
103
 
104
  if allow_multiple_categories:
105
- # Retourner toutes les catégories uniques trouvées
106
- selected_categories = list(set(responses))
 
 
 
 
 
107
  category = ', '.join(selected_categories)
108
- return category, model_responses
109
  else:
110
- # Retourner la catégorie la plus fréquente
111
- category_counts = Counter(responses)
112
- most_common, _ = category_counts.most_common(1)[0]
113
- return most_common, model_responses
114
-
115
- def parse_category(response_text, categories):
 
 
 
 
 
116
  response_text_lower = response_text.lower()
117
  found_categories = []
118
 
119
  for category in categories:
120
- category_lower = category.lower()
121
- if category_lower in response_text_lower:
122
- # Vérifier si la catégorie est un mot ou une phrase autonome
123
- if re.search(r'\b' + re.escape(category_lower) + r'\b', response_text_lower):
124
- found_categories.append(category)
125
- else:
126
- # Vérifier si la catégorie est une sous-chaîne d'un mot
127
- if re.search(re.escape(category_lower), response_text_lower):
128
- found_categories.append(category)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
129
 
130
  return found_categories
131
 
@@ -193,7 +222,7 @@ def get_parameters(index):
193
  return temperature, validation_retries, coinciding_retries_threshold
194
 
195
 
196
- def categorize_proposals(excel_file, categories, proposal_column_index=0, index=1, allow_multiple_categories=False):
197
  df = pd.read_excel(excel_file, header=None)
198
  proposals = df.iloc[:, proposal_column_index].tolist()
199
  categorized_results = []
@@ -201,7 +230,7 @@ def categorize_proposals(excel_file, categories, proposal_column_index=0, index=
201
  temperature, validation_retries, coinciding_retries_threshold = get_parameters(index)
202
 
203
  for proposal in proposals:
204
- category, model_responses = get_consistent_categories(proposal, categories, client, model, temperature, allow_multiple_categories, validation_retries, coinciding_retries_threshold)
205
  if ', ' in category:
206
  categorized_results.append((proposal, category, ', '.join(model_responses)))
207
  else:
@@ -211,16 +240,30 @@ def categorize_proposals(excel_file, categories, proposal_column_index=0, index=
211
 
212
 
213
 
214
- def gradio_interface(excel_file, categories, index, allow_multiple_categories):
 
215
  try:
216
  categories_list = categories.split(',')
217
  temperature, validation_retries, coinciding_retries_threshold = get_parameters(index)
218
 
219
- results_df = categorize_proposals(excel_file.name, categories_list, index=index, allow_multiple_categories=allow_multiple_categories)
220
- return results_df.to_html(index=False)
 
 
 
 
 
 
 
 
 
 
 
 
 
221
  except Exception as e:
222
  logging.error(f"Une erreur s'est produite : {e}")
223
- return "Une erreur s'est produite lors du traitement de la requête. Veuillez réessayer plus tard."
224
 
225
  iface = gr.Interface(
226
  fn=gradio_interface,
@@ -244,6 +287,9 @@ iface = gr.Interface(
244
  label="Autoriser plusieurs catégories",
245
  info="Cochez cette case si une proposition peut appartenir à plusieurs catégories.",
246
  ),
 
 
 
247
  ],
248
  outputs=gr.HTML(label="Résultats de la catégorisation"),
249
  title="Outil de catégorisation des propositions",
 
10
  import numpy as np
11
  import logging
12
  from collections import defaultdict
13
+ from fuzzywuzzy import fuzz
14
+ import io
15
+ import base64
16
+
17
 
18
 
19
  # Configurer le niveau du logger racine
 
57
  logging.error("Le nombre maximal de tentatives a été atteint sans succès.")
58
  raise Exception("Le nombre maximal de tentatives a été atteint")
59
 
60
+ def get_consistent_categories(proposal, categories, client, model, temperature, allow_multiple_categories, validation_retries, coinciding_retries_threshold, max_attempts=5, max_categories=None):
61
  proposal_str = str(proposal)
62
 
63
  responses = []
 
106
  return "Aucune catégorie trouvée", model_responses
107
 
108
  if allow_multiple_categories:
109
+ # If max_categories is specified and valid, select the top N most common categories
110
+ if max_categories and max_categories > 0:
111
+ most_common_categories = category_counts.most_common(max_categories)
112
+ selected_categories = [category for category, count in most_common_categories]
113
+ else:
114
+ # Else, return all unique categories found
115
+ selected_categories = list(set(responses))
116
  category = ', '.join(selected_categories)
 
117
  else:
118
+ # Return the most frequent category or handle tie situations
119
+ if category_counts:
120
+ most_common_category, count = category_counts.most_common(1)[0]
121
+ if count >= coinciding_retries_threshold:
122
+ category = most_common_category
123
+ else:
124
+ category = most_common_category
125
+ else:
126
+ category = "Aucune catégorie trouvée"
127
+
128
+ def parse_category(response_text, categories, similarity_threshold=70, min_word_length=3):
129
  response_text_lower = response_text.lower()
130
  found_categories = []
131
 
132
  for category in categories:
133
+ category_lower = category.lower().strip()
134
+ category_words = category_lower.split()
135
+
136
+ # Exact match
137
+ if category_lower == response_text_lower:
138
+ found_categories = [category.strip()]
139
+ break
140
+
141
+ # Regular expression matching
142
+ pattern = re.compile(r'\b' + re.escape(category_lower) + r'\b', re.IGNORECASE)
143
+ if pattern.search(response_text_lower):
144
+ found_categories.append(category.strip())
145
+ continue
146
+
147
+ # Fuzzy string matching
148
+ similarity_score = fuzz.token_set_ratio(category_lower, response_text_lower)
149
+ if similarity_score >= similarity_threshold:
150
+ found_categories.append(category.strip())
151
+ continue
152
+
153
+ # Partial word matching
154
+ for word in category_words:
155
+ if len(word) >= min_word_length and word in response_text_lower:
156
+ found_categories.append(category.strip())
157
+ break
158
 
159
  return found_categories
160
 
 
222
  return temperature, validation_retries, coinciding_retries_threshold
223
 
224
 
225
+ def categorize_proposals(excel_file, categories, proposal_column_index=0, index=1, allow_multiple_categories=False, max_categories=None):
226
  df = pd.read_excel(excel_file, header=None)
227
  proposals = df.iloc[:, proposal_column_index].tolist()
228
  categorized_results = []
 
230
  temperature, validation_retries, coinciding_retries_threshold = get_parameters(index)
231
 
232
  for proposal in proposals:
233
+ category, model_responses = get_consistent_categories(proposal, categories, client, model, temperature, allow_multiple_categories, validation_retries, coinciding_retries_threshold, max_attempts=5, max_categories=max_categories)
234
  if ', ' in category:
235
  categorized_results.append((proposal, category, ', '.join(model_responses)))
236
  else:
 
240
 
241
 
242
 
243
+
244
+ def gradio_interface(excel_file, categories, index, allow_multiple_categories, max_categories=None):
245
  try:
246
  categories_list = categories.split(',')
247
  temperature, validation_retries, coinciding_retries_threshold = get_parameters(index)
248
 
249
+ results_df = categorize_proposals(excel_file.name, categories_list, index=index, allow_multiple_categories=allow_multiple_categories, max_categories=max_categories)
250
+
251
+ # Create an in-memory buffer for the Excel file
252
+ excel_buffer = io.BytesIO()
253
+
254
+ # Save the results DataFrame to the Excel buffer
255
+ results_df.to_excel(excel_buffer, index=False, sheet_name='Résultats de catégorisation')
256
+
257
+ # Set the buffer position to the beginning
258
+ excel_buffer.seek(0)
259
+
260
+ # Create a download link for the Excel file
261
+ excel_download_link = f'<a href="data:application/vnd.openxmlformats-officedocument.spreadsheetml.sheet;base64,{base64.b64encode(excel_buffer.getvalue()).decode()}" download="resultats_categorisation.xlsx">Télécharger les résultats en Excel</a>'
262
+
263
+ return [results_df.to_html(index=False), excel_download_link]
264
  except Exception as e:
265
  logging.error(f"Une erreur s'est produite : {e}")
266
+ return ["Une erreur s'est produite lors du traitement de la requête. Veuillez réessayer plus tard.", None]
267
 
268
  iface = gr.Interface(
269
  fn=gradio_interface,
 
287
  label="Autoriser plusieurs catégories",
288
  info="Cochez cette case si une proposition peut appartenir à plusieurs catégories.",
289
  ),
290
+ gr.Number(
291
+ label="Nombre maximum de catégories",
292
+ ),
293
  ],
294
  outputs=gr.HTML(label="Résultats de la catégorisation"),
295
  title="Outil de catégorisation des propositions",
categorization_logs.log CHANGED
@@ -521,3 +521,8 @@ Traceback (most recent call last):
521
  raise MistralException(
522
  mistralai.exceptions.MistralException: Unexpected exception (RemoteProtocolError): Server disconnected without sending a response.
523
  2024-03-11 15:12:46,859 - ERROR - An error occurred: Unexpected exception (RemoteProtocolError): Server disconnected without sending a response.
 
 
 
 
 
 
521
  raise MistralException(
522
  mistralai.exceptions.MistralException: Unexpected exception (RemoteProtocolError): Server disconnected without sending a response.
523
  2024-03-11 15:12:46,859 - ERROR - An error occurred: Unexpected exception (RemoteProtocolError): Server disconnected without sending a response.
524
+ 2024-03-12 12:53:31,589 - ERROR - Une erreur s'est produite : max() arg is an empty sequence
525
+ 2024-03-12 13:08:00,863 - ERROR - Une erreur s'est produite : name 'get_synonyms' is not defined
526
+ 2024-03-12 13:22:09,699 - ERROR - Une erreur s'est produite : name 'base64' is not defined
527
+ 2024-03-12 14:04:21,396 - ERROR - Une erreur s'est produite : categorize_proposals() got an unexpected keyword argument 'max_categories'
528
+ 2024-03-12 14:05:53,992 - ERROR - Une erreur s'est produite : get_consistent_categories() got an unexpected keyword argument 'max_categories'
requirements.txt CHANGED
@@ -2,4 +2,5 @@ pandas
2
  gradio
3
  mistralai
4
  xlrd>=2.0.1
5
- openpyxl
 
 
2
  gradio
3
  mistralai
4
  xlrd>=2.0.1
5
+ openpyxl
6
+ fuzzywuzzy