fruitpicker01 commited on
Commit
2c6d327
·
verified ·
1 Parent(s): 64212bc

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +156 -1
app.py CHANGED
@@ -201,12 +201,167 @@ def clean_message(message):
201
  message = message[:last_period + 1]
202
  return message
203
 
204
- def generate_message_with_retry(model_prompt):
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
205
  last_message = ""
 
206
  for _ in range(10):
207
  msg = call_model(model_prompt)
208
  msg = correct_dash_usage(msg)
209
  msg = clean_message(msg)
 
210
  length = len(msg)
211
  if 160 <= length <= 250:
212
  msg += f"\n\n------\nКоличество знаков: {length}"
 
201
  message = message[:last_period + 1]
202
  return message
203
 
204
+ def tokenize_words(text):
205
+ """
206
+ Разбивает текст на слова, игнорируя знаки препинания.
207
+ """
208
+ return re.findall(r'\w+', text, re.UNICODE)
209
+
210
+ def normalize(word):
211
+ """
212
+ Возвращает начальную форму слова с помощью pymorphy3.
213
+ Приводит к нижнему регистру для унификации.
214
+ """
215
+ parsed = morph.parse(word)
216
+ if parsed:
217
+ return parsed[0].normal_form.lower()
218
+ return word.lower()
219
+
220
+ def find_word_matches(normalized_msg, normalized_prod):
221
+ """
222
+ Находит индексы начала совпадений названия продукта в нормализованных словах.
223
+ """
224
+ matches = []
225
+ prod_len = len(normalized_prod)
226
+ for i in range(len(normalized_msg) - prod_len + 1):
227
+ window = normalized_msg[i:i+prod_len]
228
+ if window == normalized_prod:
229
+ matches.append(i)
230
+ return matches
231
+
232
+ def get_word_positions(message):
233
+ """
234
+ Возвращает список кортежей (слово, start_index, end_index) для каждого слова в сообщении.
235
+ """
236
+ word_positions = []
237
+ for match in re.finditer(r'\w+', message):
238
+ word = match.group(0)
239
+ start = match.start()
240
+ end = match.end()
241
+ word_positions.append((word, start, end))
242
+ return word_positions
243
+
244
+ def capitalize_sentences(text):
245
+ """
246
+ Капитализирует первую букву каждого предложения в тексте.
247
+ Предложения считаются разделенными точками, восклицательными или вопросительными знаками.
248
+ """
249
+ # Разделяем текст на предложения
250
+ sentence_endings = re.compile(r'([.!?])')
251
+ parts = sentence_endings.split(text)
252
+
253
+ # Объединяем разделенные части и капитализируем первые буквы
254
+ sentences = []
255
+ for i in range(0, len(parts)-1, 2):
256
+ sentence = parts[i].strip()
257
+ punctuation = parts[i+1]
258
+ if sentence:
259
+ sentence = sentence[0].upper() + sentence[1:]
260
+ sentences.append(sentence + punctuation)
261
+
262
+ # Обработка возможного остатка текста без завершающего знака
263
+ if len(parts) % 2 != 0 and parts[-1].strip():
264
+ last_sentence = parts[-1].strip()
265
+ last_sentence = last_sentence[0].upper() + last_sentence[1:]
266
+ sentences.append(last_sentence)
267
+
268
+ # Объединяем обратно в текст
269
+ return ' '.join(sentences)
270
+
271
+ def process_message(message, product_name):
272
+ """
273
+ Обрабатывает сообщение, заменяя название продукта.
274
+ - Первое слово сохраняется в инфлектированной форме, как в сообщении.
275
+ - Остальные слова заменяются на оригинальные слова из названия продукта, сохраняя их капитализацию.
276
+ Возвращает обработанное сообщение.
277
+ """
278
+ # Токенизация сообщения (без пунктуации)
279
+ message_words = tokenize_words(message)
280
+ normalized_message = [normalize(word) for word in message_words]
281
+
282
+ # Токенизация названия продукта
283
+ product_words_original = tokenize_words(product_name) # Оригинальные слова с капитализацией
284
+ normalized_product = [normalize(word) for word in product_words_original]
285
+
286
+ # Поиск совпадений
287
+ matches = find_word_matches(normalized_message, normalized_product)
288
+
289
+ if not matches:
290
+ # Если совпадений нет, вернуть исходное сообщение с капитализацией предложений
291
+ return capitalize_sentences(message)
292
+
293
+ # Получаем позиции всех слов в сообщении
294
+ word_positions = get_word_positions(message)
295
+
296
+ # Обработка каждого совпадения
297
+ # Для избежания смещения индексов при множественных заменах, обрабатываем с конца
298
+ matches_sorted = sorted(matches, reverse=True)
299
+
300
+ final_message = message
301
+
302
+ for match in matches_sorted:
303
+ # Индексы слов
304
+ start_word_idx = match
305
+ end_word_idx = match + len(product_words_original) - 1
306
+
307
+ # Проверка, чтобы индексы не выходили за пределы списка
308
+ if end_word_idx >= len(word_positions):
309
+ continue # Пропускаем некоррект��ые совпадения
310
+
311
+ # Получаем позиции слов
312
+ start_char = word_positions[start_word_idx][1]
313
+ end_char = word_positions[end_word_idx][2]
314
+
315
+ # Проверяем, есть ли знаки препинания перед совпадением
316
+ if start_char > 0 and final_message[start_char -1] in ['«', '»', '-', '–', '.', ',', '!', '?', ';', ':']:
317
+ start_char -=1 # Включаем знак препинания в изменяемую часть
318
+
319
+ # Проверяем, есть ли знаки препинания после совпадения
320
+ if end_char < len(final_message) and final_message[end_char] in ['«', '»', '-', '–', '.', ',', '!', '?', ';', ':']:
321
+ end_char +=1 # Включаем знак препинания в изменяемую часть
322
+
323
+ # Извлечение изменяемой части
324
+ matched_substring = final_message[start_char:end_char]
325
+
326
+ # Извлечение неизменяемой части
327
+ before = final_message[:start_char]
328
+ after = final_message[end_char:]
329
+
330
+ # Разделяем изменяемую часть на слова
331
+ words = matched_substring.replace('«', '').replace('»', '').strip().split()
332
+
333
+ if len(words) < len(product_words_original):
334
+ # Несоответствие количества слов, пропускаем замену
335
+ continue
336
+
337
+ # Сохраняем первое слово как есть (инфлектированное)
338
+ first_word = words[0]
339
+
340
+ # Остальные слова берем из оригинального названия продукта
341
+ replaced_words = [first_word] + product_words_original[1:]
342
+
343
+ # Собираем обратно измененную часть
344
+ processed = ' '.join(replaced_words)
345
+
346
+ # Воссоединяем части сообщения
347
+ final_message = before + processed + after
348
+
349
+ # Удаляем лишние пробелы
350
+ final_message = re.sub(r'\s+', ' ', final_message).strip()
351
+
352
+ # Капитализируем предложения
353
+ final_message = capitalize_sentences(final_message)
354
+
355
+ return final_message
356
+
357
+ def generate_message_with_retry(model_prompt, product_name):
358
  last_message = ""
359
+ morph = pymorphy3.MorphAnalyzer()
360
  for _ in range(10):
361
  msg = call_model(model_prompt)
362
  msg = correct_dash_usage(msg)
363
  msg = clean_message(msg)
364
+ msg = process_message(msg)
365
  length = len(msg)
366
  if 160 <= length <= 250:
367
  msg += f"\n\n------\nКоличество знаков: {length}"