fruitpicker01 commited on
Commit
b55aea3
1 Parent(s): 9a09e9c

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +167 -263
app.py CHANGED
@@ -8,7 +8,7 @@ from langchain_community.chat_models.gigachat import GigaChat
8
  from openpyxl import load_workbook
9
  import plotly.graph_objects as go
10
  import random
11
- import pymorphy2
12
  import string
13
  import json
14
  from mistralai import Mistral
@@ -17,37 +17,37 @@ import requests
17
  import base64
18
  import io
19
 
20
- #MISTRAL_API_KEY = os.getenv('MISTRAL_API_KEY')
21
  token = os.getenv('GITHUB_TOKEN')
22
 
23
  # Клиент для генерации сообщений
24
- #client_mistral_generate = Mistral(api_key=MISTRAL_API_KEY)
25
 
26
  # Клиент для выполнения проверок
27
- #client_mistral_check = Mistral(api_key=MISTRAL_API_KEY)
28
 
29
- morph = pymorphy2.MorphAnalyzer()
30
 
31
  # Авторизация в GigaChat Pro
32
- gc_key = os.getenv('GC_KEY')
33
  #chat_pro = GigaChat(credentials=gc_key, model='GigaChat', max_tokens=68, temperature=1.15, verify_ssl_certs=False)
34
- chat_pro = GigaChat(
35
- credentials=gc_key,
36
- model='GigaChat-Pro-preview',
37
- base_url='https://gigachat-preview.devices.sberbank.ru/api/v1/',
38
- max_tokens=68,
39
- temperature=1.15,
40
- verify_ssl_certs=False
41
- )
42
-
43
- chat_pro_check = GigaChat(
44
- credentials=gc_key,
45
- model='GigaChat-Pro-preview',
46
- base_url='https://gigachat-preview.devices.sberbank.ru/api/v1/',
47
- max_tokens=3000,
48
- temperature=0.8,
49
- verify_ssl_certs=False
50
- )
51
 
52
  approach_stats = {
53
  "Начни сообщение с призыва к действию с продуктом.": {"failed_checks": defaultdict(int), "total_attempts": 0},
@@ -74,30 +74,6 @@ for sheet_name, df in data.items():
74
  print(f"Ошибка при обработке данных листа {sheet_name}: {e}")
75
  features[sheet_name] = {}
76
 
77
- # Функция для создания спидометра
78
- def create_gauge(value):
79
- fig = go.Figure(go.Indicator(
80
- mode="gauge+number",
81
- value=value,
82
- gauge={
83
- 'axis': {'range': [0, 100]},
84
- 'bar': {'color': "black"}, # Цвет стрелки
85
- 'steps': [
86
- {'range': [0, 40], 'color': "#55efc4"}, # Мягкий зеленый
87
- {'range': [40, 70], 'color': "#ffeaa7"}, # Желтый
88
- {'range': [70, 100], 'color': "#ff7675"} # Мягкий красный
89
- ],
90
- 'threshold': {
91
- 'line': {'color': "black", 'width': 4},
92
- 'thickness': 0.75,
93
- 'value': value
94
- }
95
- },
96
- number={'font': {'size': 48}} # Размер шрифта числа
97
- ))
98
- fig.update_layout(paper_bgcolor="#f8f9fa", font={'color': "#2d3436", 'family': "Arial"}, width=250, height=150)
99
- return fig
100
-
101
  def save_statistics_to_github(approach_stats):
102
  repo = "fruitpicker01/Storage_dev"
103
  timestamp = int(time.time())
@@ -170,10 +146,6 @@ def save_statistics_to_github(approach_stats):
170
  else:
171
  print(f"Ошибка при сохранении CSV-файла: {response.status_code} {response.text}")
172
 
173
- # Функция для генерации случайных значений спидометров
174
- def generate_random_gauges():
175
- return create_gauge(random.randint(80, 95)), create_gauge(random.randint(80, 95)), create_gauge(random.randint(80, 95))
176
-
177
  # Функция для смены вкладки
178
  def change_tab(id):
179
  return gr.Tabs(selected=id)
@@ -191,77 +163,77 @@ def clean_message(message):
191
  return message
192
 
193
  # Функция для генерации сообщения с GigaChat Pro
194
- def generate_message_gigachat_pro(prompt):
195
- try:
196
- messages = [SystemMessage(content=prompt)]
197
- res = chat_pro(messages)
198
- cleaned_message = clean_message(res.content.strip())
199
- return cleaned_message
200
- except Exception as e:
201
- return f"Ошибка при обращении к GigaChat-Pro: {e}"
202
-
203
- #def generate_message_mistral_generate(prompt, max_retries=5):
204
- # retries = 0
205
- # while retries < max_retries:
206
- # try:
207
- # chat_response = client_mistral_generate.chat.complete(
208
- # model="mistral-large-latest",
209
- # messages=[
210
- # {
211
- # "role": "user",
212
- # "content": prompt,
213
- # "max_tokens": 68,
214
- # "temperature": 0.8
215
- # },
216
- # ]
217
- # )
218
- # cleaned_message = clean_message(chat_response.choices[0].message.content.strip())
219
- # return cleaned_message
220
- # except Exception as e:
221
- # if "Status 429" in str(e):
222
- # wait_time = 3 # Можно установить фиксированную задержку
223
- # print(f"Превышен лимит запросов. Ожидание {wait_time} секунд перед повторной попыткой...")
224
- # time.sleep(wait_time)
225
- # retries += 1
226
- # else:
227
- # print(f"Ошибка при обращении к Mistral: {e}")
228
- # return None
229
-
230
- #def generate_message_mistral_check(prompt, max_retries=5):
231
- # retries = 0
232
- # while retries < max_retries:
233
- # try:
234
- # chat_response = client_mistral_check.chat.complete(
235
- # model="mistral-large-latest",
236
- # messages=[
237
- # {
238
- # "role": "user",
239
- # "content": prompt,
240
- # "max_tokens": 3000,
241
- # "temperature": 0.2
242
- # },
243
- # ]
244
- # )
245
- # cleaned_message = clean_message(chat_response.choices[0].message.content.strip())
246
- # return cleaned_message
247
- # except Exception as e:
248
- # if "Status 429" in str(e):
249
- # wait_time = 3 # Можно установить фиксированную задержку
250
- # print(f"Превышен лимит запросов. Ожидание {wait_time} секунд перед повторной попыткой...")
251
- # time.sleep(wait_time)
252
- # retries += 1
253
- # else:
254
- # print(f"Ошибка при обращении к Mistral: {e}")
255
- # return None
256
-
257
- def generate_check_gigachat_pro(prompt):
258
- try:
259
- messages = [SystemMessage(content=prompt)]
260
- res2 = chat_pro_check(messages)
261
- cleaned_message = clean_message(res2.content.strip())
262
- return cleaned_message
263
- except Exception as e:
264
- return f"Ошибка при обращении к GigaChat-Pro: {e}"
265
 
266
  # Функция для замены сокращений с 'k' или 'К' на тысячи
267
  def replace_k_with_thousands(message):
@@ -270,7 +242,7 @@ def replace_k_with_thousands(message):
270
  return message
271
 
272
  def correct_dash_usage(text):
273
- morph = pymorphy2.MorphAnalyzer()
274
  # Step 1: Replace any dash with long dash if surrounded by spaces
275
  text = re.sub(r'\s[-–—]\s', ' — ', text)
276
 
@@ -323,7 +295,7 @@ def correct_dash_usage(text):
323
  text = ' '.join(sentences)
324
 
325
  def restore_yo(text):
326
- morph = pymorphy2.MorphAnalyzer()
327
  words = text.split()
328
  restored_words = []
329
 
@@ -363,9 +335,13 @@ def correct_dash_usage(text):
363
  text = re.sub(r'\bповышьте\b', 'повысьте', text, flags=re.IGNORECASE)
364
 
365
  text = re.sub(r'\bСбербизнес\b', 'СберБизнес', text, flags=re.IGNORECASE)
 
 
366
  text = re.sub(r'\bСбербанк\b', 'СберБанк', text, flags=re.IGNORECASE)
367
  text = re.sub(r'\bвашего ООО\b', 'вашей компании', text, flags=re.IGNORECASE)
368
-
 
 
369
  # Step 11: Replace all forms of "рублей", "рубля", "руб." with "р"
370
  # Используем два отдельных регулярных выражения для точности
371
  # 1. Заменяем "руб." на "р", учитывая, что "руб." может быть перед символом "/" или другим несловесным символом
@@ -377,7 +353,8 @@ def correct_dash_usage(text):
377
  text = re.sub(r'(\d+)\s+тысяч(?:а|и)?(?:\s+рублей)?', r'\1 000 р', text, flags=re.IGNORECASE)
378
  text = re.sub(r'(\d+)\s*тыс\.\s*руб\.', r'\1 000 р', text, flags=re.IGNORECASE)
379
  text = re.sub(r'(\d+)\s*тыс\.\s*р\.', r'\1 000 р', text, flags=re.IGNORECASE)
380
-
 
381
  # Replace millions with "млн"
382
  text = re.sub(r'(\d+)\s+миллиона\b|\bмиллионов\b', r'\1 млн', text, flags=re.IGNORECASE)
383
  text = re.sub(r'(\d+)\s*млн\s*руб\.', r'\1 млн р', text, flags=re.IGNORECASE)
@@ -500,41 +477,12 @@ def notify_failed_checks(checks):
500
  gr.Warning("ВСЕ ПРОВЕРКИ ПРОЙДЕНЫ")
501
 
502
  # Модифицированная функция перегенерации сообщений с уведомлениями о номере попытки
503
- def generate_message_gigachat_pro_with_retry(prompt, current_prefix, description, key_message):
504
- global approach_stats
505
- last_message = None
506
- for attempt in range(30):
507
- gr.Info(f"Итерация {attempt + 1}: генерируется сообщение...")
508
- message = generate_message_gigachat_pro(prompt)
509
- message = replace_k_with_thousands(message)
510
- message = correct_dash_usage(message)
511
- message_length = len(message)
512
- if not notify_failed_length(message_length):
513
- last_message = message
514
- time.sleep(1)
515
- continue
516
- checks = perform_checks(message, description, key_message)
517
- last_message = message
518
- approach_stats[current_prefix]["total_attempts"] += 1
519
- for check_name, passed in checks.items():
520
- if passed is False:
521
- approach_stats[current_prefix]["failed_checks"][check_name] += 1
522
- break
523
- notify_failed_checks(checks) # Вызываем функцию независимо от результата проверок
524
- if all(checks.values()):
525
- return message
526
- prompt = append_errors_to_prompt(prompt, checks)
527
- time.sleep(1)
528
- gr.Info("Не удалось сгенерировать сообщение, соответствующее требованиям, за 20 итераций. Возвращаем последнее сгенерированное сообщение.")
529
- return last_message
530
-
531
-
532
- #def generate_message_mistral_with_retry(prompt, current_prefix, description, key_message):
533
  # global approach_stats
534
  # last_message = None
535
- # for attempt in range(20):
536
  # gr.Info(f"Итер��ция {attempt + 1}: генерируется сообщение...")
537
- # message = generate_message_mistral_generate(prompt)
538
  # message = replace_k_with_thousands(message)
539
  # message = correct_dash_usage(message)
540
  # message_length = len(message)
@@ -558,6 +506,35 @@ def generate_message_gigachat_pro_with_retry(prompt, current_prefix, description
558
  # return last_message
559
 
560
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
561
  # Функция для создания задания для копирайтера
562
  def generate_standard_prompt(description, advantages, key_message, *selected_values):
563
  prompt = (
@@ -695,7 +672,7 @@ def generate_all_messages(desc, benefits, key_message, gender, generation, psych
695
  yield standard_prompt, display_personalization_prompt, None, None, None, None, None, None
696
  flag += 1
697
  prompt = add_prefix_suffix(standard_prompt, prefixes[i], suffixes[i])
698
- non_personalized_message = generate_message_gigachat_pro_with_retry(prompt, current_prefix, desc, key_message)
699
  non_personalized_length = len(non_personalized_message)
700
  non_personalized_display = f"{non_personalized_message}\n------\nКоличество знаков: {non_personalized_length}"
701
  non_personalized_messages.append(non_personalized_display)
@@ -713,7 +690,7 @@ def generate_all_messages(desc, benefits, key_message, gender, generation, psych
713
 
714
  # Генерация персонализированного сообщения
715
  full_personalized_prompt = f"{personalization_prompt}\n\nТекст для адаптации: {non_personalized_message}"
716
- personalized_message = generate_message_gigachat_pro_with_retry(full_personalized_prompt, current_prefix, desc, key_message)
717
  personalized_length = len(personalized_message)
718
  personalized_display = f"{personalized_message}\n------\nКоличество знаков: {personalized_length}"
719
  personalized_messages.append(personalized_display)
@@ -739,7 +716,7 @@ def generate_all_messages(desc, benefits, key_message, gender, generation, psych
739
  # 1. Запрещенные слова
740
 
741
  def check_forbidden_words(message):
742
- morph = pymorphy2.MorphAnalyzer()
743
 
744
  # Перечень запрещённых слов и фраз
745
  forbidden_patterns = [
@@ -773,7 +750,7 @@ def check_forbidden_words(message):
773
  # 2 и #3. Обращение к клиенту и приветствие клиента
774
 
775
  def check_no_greeting(message):
776
- morph = pymorphy2.MorphAnalyzer()
777
  # Список типичных обращений и приветствий
778
  greeting_patterns = [
779
  r"привет\b", r"здравствуй", r"добрый\s(день|вечер|утро)",
@@ -793,7 +770,7 @@ def check_no_greeting(message):
793
  # 4. Обещания и гарантии
794
 
795
  def check_no_promises(message):
796
- morph = pymorphy2.MorphAnalyzer()
797
  promise_patterns = [
798
  "обещать", "обещание", "гарантировать", "обязаться", "обязать", "обязательство", "обязательный"
799
  ]
@@ -809,7 +786,7 @@ def check_no_promises(message):
809
  # 5. Составные конструкции из двух глаголов
810
 
811
  def check_no_double_verbs(message):
812
- morph = pymorphy2.MorphAnalyzer()
813
  # Разделяем текст по пробелам и знакам препинания
814
  words = re.split(r'\s+|[.!?]', message)
815
  morphs = [morph.parse(word)[0] for word in words]
@@ -827,7 +804,7 @@ def check_no_double_verbs(message):
827
  # 6. Причастия и причастные обороты
828
 
829
  def check_no_participles(message):
830
- morph = pymorphy2.MorphAnalyzer()
831
  words = message.split()
832
  exceptions = {"повышенный", "увеличенный", "пониженный", "сниженный"}
833
 
@@ -841,7 +818,7 @@ def check_no_participles(message):
841
  # 7. Деепричастия и деепричастные обороты
842
 
843
  def check_no_adverbial_participles(message):
844
- morph = pymorphy2.MorphAnalyzer()
845
  words = message.split()
846
  morphs = [morph.parse(word)[0] for word in words]
847
 
@@ -853,7 +830,7 @@ def check_no_adverbial_participles(message):
853
  # 8. Превосходная степень прилагательных
854
 
855
  def check_no_superlative_adjectives(message):
856
- morph = pymorphy2.MorphAnalyzer()
857
  words = message.split()
858
  morphs = [morph.parse(word)[0] for word in words]
859
 
@@ -865,7 +842,7 @@ def check_no_superlative_adjectives(message):
865
  # 9. Страдательный залог
866
 
867
  def check_no_passive_voice(message):
868
- morph = pymorphy2.MorphAnalyzer()
869
  words = message.split()
870
  morphs = [morph.parse(word)[0] for word in words]
871
 
@@ -877,7 +854,7 @@ def check_no_passive_voice(message):
877
  # 10. Порядковые числительные от 10 прописью
878
 
879
  def check_no_written_out_ordinals(message):
880
- morph = pymorphy2.MorphAnalyzer()
881
  ordinal_words = [
882
  "десятый", "одиннадцатый", "двенадцатый", "тринадцатый", "четырнадцатый", "пятнадцатый",
883
  "шестнадцатый", "семнадцатый", "восемнадцатый", "девятнадцатый", "двадцатый"
@@ -966,7 +943,7 @@ def check_no_time_parasites(message):
966
  def check_no_multiple_nouns(message):
967
  noun_count = 0
968
  words = re.split(r'\s+|[.!?]', message) # Разбиваем по пробелам и знакам препинания
969
- morph = pymorphy2.MorphAnalyzer()
970
 
971
  for word in words:
972
  parsed_word = morph.parse(word)[0]
@@ -1036,7 +1013,7 @@ def check_no_dates_written_out(message):
1036
  # Доп правило. Повторы слов
1037
 
1038
  def check_no_word_repetitions(message):
1039
- morph = pymorphy2.MorphAnalyzer()
1040
 
1041
  # Список союзов и предлогов, которые мы будем игнорировать
1042
  ignore_words = set([
@@ -1135,9 +1112,9 @@ def check_disconnected_sentences(message):
1135
  если таких предложений **нет**, **верни только** JSON {{"decision": false, "explanation": "<пояснение>"}}.
1136
  **Не добавляй никакого дополнительного текста. Перед ответом убедись, что отвечаешь **только** в формате JSON с закрывающими кавычками и скобками.**'''
1137
 
1138
- response = generate_check_gigachat_pro(prompt)
1139
  time.sleep(3) # Задержка в 3 секунды между запросами
1140
- print("GigaChat Pro response:", response) # Выводим полный ответ модели
1141
  result = parse_json_response(response)
1142
  if result is not None:
1143
  decision = result.get("decision", False)
@@ -1162,9 +1139,9 @@ def check_synonymous_members(message):
1162
  если таких слов или выражений нет, **верни только** JSON {{"decision": false, "explanation": "<пояснение>"}}.
1163
  **Не добавляй никакого дополнительного текста. Перед ответом убедись, что отвечаешь только в формате JSON с закрывающими кавычками и скобками.**'''
1164
 
1165
- response = generate_check_gigachat_pro(prompt)
1166
  time.sleep(3)
1167
- print("GigaChat Pro response:", response)
1168
  result = parse_json_response(response)
1169
  if result is not None:
1170
  decision = result.get("decision", False)
@@ -1195,9 +1172,9 @@ def check_clickbait_phrases(message):
1195
 
1196
  **Не добавляй никакого дополнительного текста. Перед ответом убедись, что отвечаешь только в формате JSON с закрывающими кавычками и скобками.**'''
1197
 
1198
- response = generate_check_gigachat_pro(prompt)
1199
  time.sleep(3)
1200
- print("GigaChat Pro response:", response)
1201
  result = parse_json_response(response)
1202
  if result is not None:
1203
  decision = result.get("decision", False)
@@ -1241,9 +1218,9 @@ def check_abstract_claims(message):
1241
 
1242
  **Не добавляй никакого дополнительного текста. Перед ответом убедись, что отвечаешь только в формате JSON с закрывающими кавычками и скобками.**'''
1243
 
1244
- response = generate_check_gigachat_pro(prompt)
1245
  time.sleep(3)
1246
- print("GigaChat Pro response:", response)
1247
  result = parse_json_response(response)
1248
  if result is not None:
1249
  decision = result.get("decision", False)
@@ -1278,9 +1255,9 @@ def check_specialized_terms(message):
1278
 
1279
  **Не добавляй никакого дополнительного текста. Перед ответом убедись, что отвечаешь только в формате JSON с закрывающими кавычками и скобками.**'''
1280
 
1281
- response = generate_check_gigachat_pro(prompt)
1282
  time.sleep(3)
1283
- print("GigaChat Pro response:", response)
1284
  result = parse_json_response(response)
1285
  if result is not None:
1286
  decision = result.get("decision", False)
@@ -1307,9 +1284,9 @@ def check_offensive_phrases(message):
1307
  если таких фраз нет, **верни только** JSON {{"decision": false, "explanation": "<пояснение>"}}.
1308
  **Не добавляй никакого дополнительного текста. Перед ответом убедись, что отвечаешь только в формате JSON с закрывающими кавычками и скобками.**'''
1309
 
1310
- response = generate_check_gigachat_pro(prompt)
1311
  time.sleep(3)
1312
- print("GigaChat Pro response:", response)
1313
  result = parse_json_response(response)
1314
  if result is not None:
1315
  decision = result.get("decision", False)
@@ -1350,9 +1327,9 @@ def check_cliches_and_bureaucratese(message):
1350
  если в тексте **есть** такие выражения, **верни только** JSON {{"decision": true, "explanation": "<пояснение>"}}.
1351
  **Не добавляй никакого дополнительного текста. Перед ответом убедись, что отвечаешь только в формате JSON с закрывающими кавычками и скобками.**'''
1352
 
1353
- response = generate_check_gigachat_pro(prompt)
1354
  time.sleep(3)
1355
- print("GigaChat Pro response:", response)
1356
  result = parse_json_response(response)
1357
  if result is not None:
1358
  decision = result.get("decision", False)
@@ -1377,9 +1354,9 @@ def check_no_contradictions(message, description):
1377
  Если сообщение содержит факты, которые отсутствуют в описании предложения, **верни только** JSON {{"decision": true, "explanation": "<описание противоречий>"}}.
1378
  **Не добавляй никакого дополнительного текста. Отвечай только в формате JSON с закрывающими кавычками и скобками.**'''
1379
 
1380
- response = generate_check_gigachat_pro(prompt)
1381
  time.sleep(3)
1382
- print("GigaChat Pro response:", response)
1383
  result = parse_json_response(response)
1384
  if result is not None:
1385
  decision = result.get("decision", False)
@@ -1404,9 +1381,9 @@ def check_contains_key_message(message, key_message):
1404
  Если сообщение **не содержит всю** информацию из ключевого текста, **верни только** JSON {{"decision": true, "explanation": "Ключевое текст отсутствует."}}.
1405
  **Не добавляй никакого дополнительного текста. Отвечай только в формате JSON с закрывающими кавычками и скобками.**'''
1406
 
1407
- response = generate_check_gigachat_pro(prompt)
1408
  time.sleep(3)
1409
- print("GigaChat Pro response:", response)
1410
  result = parse_json_response(response)
1411
  if result is not None:
1412
  decision = result.get("decision", False)
@@ -1429,7 +1406,7 @@ def safe_check(func, *args):
1429
  def perform_checks(message, description, key_message):
1430
  checks = {}
1431
 
1432
- # 2. Morphological checks using pymorphy2
1433
  morphological_checks = [
1434
  ("forbidden_words", check_forbidden_words),
1435
  ("client_addressing", check_no_greeting),
@@ -1542,74 +1519,6 @@ def format_checks(checks):
1542
  return " \n".join(formatted_results)
1543
 
1544
 
1545
- # Функция для обработки нажатия кнопки "Проверить"
1546
- def perform_all_checks_and_show_results(personalized_message_1, personalized_message_2, personalized_message_3):
1547
- # Моментально показываем все персонализированные сообщения
1548
- yield (
1549
- personalized_message_1, None, # Первое сообщение без проверки
1550
- personalized_message_2, None, # Второе сообщение без проверки
1551
- personalized_message_3, None, # Третье сообщение без проверки
1552
- None, None, None # Пустые графики для спидометров
1553
- )
1554
-
1555
- # Выполняем и показываем проверки с задержкой 1 секунда
1556
- checks_1 = perform_checks(personalized_message_1)
1557
- formatted_checks_1 = format_checks(checks_1)
1558
- time.sleep(1) # Задержка 1 секунда перед выводом первого результата проверки
1559
- yield (
1560
- personalized_message_1, formatted_checks_1, # Проверка для первого сообщения
1561
- personalized_message_2, None, # Второе сообщение без проверки
1562
- personalized_message_3, None, # Третье сообщение без проверки
1563
- None, None, None # Пустые графики для спидометров
1564
- )
1565
-
1566
- checks_2 = perform_checks(personalized_message_2)
1567
- formatted_checks_2 = format_checks(checks_2)
1568
- time.sleep(1) # Задержка 1 секунда перед выводом второго результата проверки
1569
- yield (
1570
- personalized_message_1, formatted_checks_1, # Проверка для первого сообщения
1571
- personalized_message_2, formatted_checks_2, # Проверка для второго сообщения
1572
- personalized_message_3, None, # Третье сообщение без проверки
1573
- None, None, None # Пустые графики для спидометров
1574
- )
1575
-
1576
- checks_3 = perform_checks(personalized_message_3)
1577
- formatted_checks_3 = format_checks(checks_3)
1578
- time.sleep(1) # Задержка 1 секунда перед выводом третьего результата проверки
1579
- yield (
1580
- personalized_message_1, formatted_checks_1, # Проверка для первого сообщения
1581
- personalized_message_2, formatted_checks_2, # Проверка для второго сообщения
1582
- personalized_message_3, formatted_checks_3, # Проверка для третьего сообщения
1583
- None, None, None # Пустые графики для спидометров
1584
- )
1585
-
1586
- # Генерация и показ графиков спидометров с задержкой 2 секунды
1587
- time.sleep(2)
1588
- gauges = generate_random_gauges()
1589
- yield (
1590
- personalized_message_1, formatted_checks_1, # Проверка для первого сообщения
1591
- personalized_message_2, formatted_checks_2, # Проверка для второго сообщения
1592
- personalized_message_3, formatted_checks_3, # Проверка для третьего сообщения
1593
- gauges[0], None, None # Первый график спидометра
1594
- )
1595
-
1596
- time.sleep(2)
1597
- yield (
1598
- personalized_message_1, formatted_checks_1, # Проверка для первого сообщения
1599
- personalized_message_2, formatted_checks_2, # Проверка для второго сообщения
1600
- personalized_message_3, formatted_checks_3, # Проверка для третьего сообщения
1601
- gauges[0], gauges[1], None # Первый и второй графики спидометра
1602
- )
1603
-
1604
- time.sleep(2)
1605
- yield (
1606
- personalized_message_1, formatted_checks_1, # Проверка для первого сообщения
1607
- personalized_message_2, formatted_checks_2, # Проверка для второго сообщения
1608
- personalized_message_3, formatted_checks_3, # Проверка для третьего сообщения
1609
- gauges[0], gauges[1], gauges[2] # Все три графика спидометра
1610
- )
1611
-
1612
-
1613
  # Интерфейс Gradio
1614
  with gr.Blocks() as demo:
1615
  # Твой интерфейс
@@ -1681,11 +1590,6 @@ with gr.Blocks() as demo:
1681
  non_personalized_messages = gr.Textbox(label="Стандартные сообщения", lines=12, interactive=False)
1682
  personalized_messages = gr.Textbox(label="Персонализированные сообщения", lines=12, interactive=False)
1683
 
1684
- # Четвертый ряд
1685
- with gr.Row():
1686
- btn_check = gr.Button("Проверить", elem_id="check3")
1687
- btn_check.click(fn=change_tab, inputs=[gr.Number(value=3, visible=False)], outputs=tabs)
1688
-
1689
  # Сначала переключаем вкладку, потом запускаем генерацию сообщений
1690
  btn_to_prompts.click(
1691
  fn=change_tab,
 
8
  from openpyxl import load_workbook
9
  import plotly.graph_objects as go
10
  import random
11
+ import pymorphy3
12
  import string
13
  import json
14
  from mistralai import Mistral
 
17
  import base64
18
  import io
19
 
20
+ MISTRAL_API_KEY = os.getenv('MISTRAL_API_KEY')
21
  token = os.getenv('GITHUB_TOKEN')
22
 
23
  # Клиент для генерации сообщений
24
+ client_mistral_generate = Mistral(api_key=MISTRAL_API_KEY)
25
 
26
  # Клиент для выполнения проверок
27
+ client_mistral_check = Mistral(api_key=MISTRAL_API_KEY)
28
 
29
+ morph = pymorphy3.MorphAnalyzer()
30
 
31
  # Авторизация в GigaChat Pro
32
+ #gc_key = os.getenv('GC_KEY')
33
  #chat_pro = GigaChat(credentials=gc_key, model='GigaChat', max_tokens=68, temperature=1.15, verify_ssl_certs=False)
34
+ #chat_pro = GigaChat(
35
+ # credentials=gc_key,
36
+ # model='GigaChat-Pro-preview',
37
+ # base_url='https://gigachat-preview.devices.sberbank.ru/api/v1/',
38
+ # max_tokens=68,
39
+ # temperature=1.15,
40
+ # verify_ssl_certs=False
41
+ #)
42
+
43
+ #chat_pro_check = GigaChat(
44
+ # credentials=gc_key,
45
+ # model='GigaChat-Pro-preview',
46
+ # base_url='https://gigachat-preview.devices.sberbank.ru/api/v1/',
47
+ # max_tokens=3000,
48
+ # temperature=0.8,
49
+ # verify_ssl_certs=False
50
+ #)
51
 
52
  approach_stats = {
53
  "Начни сообщение с призыва к действию с продуктом.": {"failed_checks": defaultdict(int), "total_attempts": 0},
 
74
  print(f"Ошибка при обработке данных листа {sheet_name}: {e}")
75
  features[sheet_name] = {}
76
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
77
  def save_statistics_to_github(approach_stats):
78
  repo = "fruitpicker01/Storage_dev"
79
  timestamp = int(time.time())
 
146
  else:
147
  print(f"Ошибка при сохранении CSV-файла: {response.status_code} {response.text}")
148
 
 
 
 
 
149
  # Функция для смены вкладки
150
  def change_tab(id):
151
  return gr.Tabs(selected=id)
 
163
  return message
164
 
165
  # Функция для генерации сообщения с GigaChat Pro
166
+ #def generate_message_gigachat_pro(prompt):
167
+ # try:
168
+ # messages = [SystemMessage(content=prompt)]
169
+ # res = chat_pro(messages)
170
+ # cleaned_message = clean_message(res.content.strip())
171
+ # return cleaned_message
172
+ # except Exception as e:
173
+ # return f"Ошибка при обращении к GigaChat-Pro: {e}"
174
+
175
+ def generate_message_mistral_generate(prompt, max_retries=5):
176
+ retries = 0
177
+ while retries < max_retries:
178
+ try:
179
+ chat_response = client_mistral_generate.chat.complete(
180
+ model="mistral-large-latest",
181
+ messages=[
182
+ {
183
+ "role": "user",
184
+ "content": prompt,
185
+ "max_tokens": 68,
186
+ "temperature": 0.8
187
+ },
188
+ ]
189
+ )
190
+ cleaned_message = clean_message(chat_response.choices[0].message.content.strip())
191
+ return cleaned_message
192
+ except Exception as e:
193
+ if "Status 429" in str(e):
194
+ wait_time = 3 # Можно установить фиксированную задержку
195
+ print(f"Превышен лимит запросов. Ожидание {wait_time} секунд перед повторной попыткой...")
196
+ time.sleep(wait_time)
197
+ retries += 1
198
+ else:
199
+ print(f"Ошибка при обращении к Mistral: {e}")
200
+ return None
201
+
202
+ def generate_message_mistral_check(prompt, max_retries=5):
203
+ retries = 0
204
+ while retries < max_retries:
205
+ try:
206
+ chat_response = client_mistral_check.chat.complete(
207
+ model="mistral-large-latest",
208
+ messages=[
209
+ {
210
+ "role": "user",
211
+ "content": prompt,
212
+ "max_tokens": 3000,
213
+ "temperature": 0.2
214
+ },
215
+ ]
216
+ )
217
+ cleaned_message = clean_message(chat_response.choices[0].message.content.strip())
218
+ return cleaned_message
219
+ except Exception as e:
220
+ if "Status 429" in str(e):
221
+ wait_time = 3 # Можно установить фиксированную задержку
222
+ print(f"Превышен лимит запросов. Ожидание {wait_time} секунд перед повторной попыткой...")
223
+ time.sleep(wait_time)
224
+ retries += 1
225
+ else:
226
+ print(f"Ошибка при обращении к Mistral: {e}")
227
+ return None
228
+
229
+ #def generate_check_gigachat_pro(prompt):
230
+ # try:
231
+ # messages = [SystemMessage(content=prompt)]
232
+ # res2 = chat_pro_check(messages)
233
+ # cleaned_message = clean_message(res2.content.strip())
234
+ # return cleaned_message
235
+ # except Exception as e:
236
+ # return f"Ошибка при обращении к GigaChat-Pro: {e}"
237
 
238
  # Функция для замены сокращений с 'k' или 'К' на тысячи
239
  def replace_k_with_thousands(message):
 
242
  return message
243
 
244
  def correct_dash_usage(text):
245
+ morph = pymorphy3.MorphAnalyzer()
246
  # Step 1: Replace any dash with long dash if surrounded by spaces
247
  text = re.sub(r'\s[-–—]\s', ' — ', text)
248
 
 
295
  text = ' '.join(sentences)
296
 
297
  def restore_yo(text):
298
+ morph = pymorphy3.MorphAnalyzer()
299
  words = text.split()
300
  restored_words = []
301
 
 
335
  text = re.sub(r'\bповышьте\b', 'повысьте', text, flags=re.IGNORECASE)
336
 
337
  text = re.sub(r'\bСбербизнес\b', 'СберБизнес', text, flags=re.IGNORECASE)
338
+ text = re.sub(r'\bСбербизнеса\b', 'СберБизнес', text, flags=re.IGNORECASE)
339
+ text = re.sub(r'\bСбербизнесе\b', 'СберБизнес', text, flags=re.IGNORECASE)
340
  text = re.sub(r'\bСбербанк\b', 'СберБанк', text, flags=re.IGNORECASE)
341
  text = re.sub(r'\bвашего ООО\b', 'вашей компании', text, flags=re.IGNORECASE)
342
+ text = re.sub(r'\b0₽\b', '0 р', text, flags=re.IGNORECASE)
343
+ text = re.sub(r'\b₽\b', 'р', text, flags=re.IGNORECASE)
344
+
345
  # Step 11: Replace all forms of "рублей", "рубля", "руб." with "р"
346
  # Используем два отдельных регулярных выражения для точности
347
  # 1. Заменяем "руб." на "р", учитывая, что "руб." может быть перед символом "/" или другим несловесным символом
 
353
  text = re.sub(r'(\d+)\s+тысяч(?:а|и)?(?:\s+рублей)?', r'\1 000 р', text, flags=re.IGNORECASE)
354
  text = re.sub(r'(\d+)\s*тыс\.\s*руб\.', r'\1 000 р', text, flags=re.IGNORECASE)
355
  text = re.sub(r'(\d+)\s*тыс\.\s*р\.', r'\1 000 р', text, flags=re.IGNORECASE)
356
+ text = re.sub(r'(\d+)\s*тыс\.\s*р', r'\1 000 р', text, flags=re.IGNORECASE)
357
+
358
  # Replace millions with "млн"
359
  text = re.sub(r'(\d+)\s+миллиона\b|\bмиллионов\b', r'\1 млн', text, flags=re.IGNORECASE)
360
  text = re.sub(r'(\d+)\s*млн\s*руб\.', r'\1 млн р', text, flags=re.IGNORECASE)
 
477
  gr.Warning("ВСЕ ПРОВЕРКИ ПРОЙДЕНЫ")
478
 
479
  # Модифицированная функция перегенерации сообщений с уведомлениями о номере попытки
480
+ #def generate_message_gigachat_pro_with_retry(prompt, current_prefix, description, key_message):
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
481
  # global approach_stats
482
  # last_message = None
483
+ # for attempt in range(30):
484
  # gr.Info(f"Итер��ция {attempt + 1}: генерируется сообщение...")
485
+ # message = generate_message_gigachat_pro(prompt)
486
  # message = replace_k_with_thousands(message)
487
  # message = correct_dash_usage(message)
488
  # message_length = len(message)
 
506
  # return last_message
507
 
508
 
509
+ def generate_message_mistral_with_retry(prompt, current_prefix, description, key_message):
510
+ global approach_stats
511
+ last_message = None
512
+ for attempt in range(20):
513
+ gr.Info(f"Итерация {attempt + 1}: генерируется сообщение...")
514
+ message = generate_message_mistral_generate(prompt)
515
+ message = replace_k_with_thousands(message)
516
+ message = correct_dash_usage(message)
517
+ message_length = len(message)
518
+ if not notify_failed_length(message_length):
519
+ last_message = message
520
+ time.sleep(1)
521
+ continue
522
+ checks = perform_checks(message, description, key_message)
523
+ last_message = message
524
+ approach_stats[current_prefix]["total_attempts"] += 1
525
+ for check_name, passed in checks.items():
526
+ if passed is False:
527
+ approach_stats[current_prefix]["failed_checks"][check_name] += 1
528
+ break
529
+ notify_failed_checks(checks) # Вызываем функцию независимо от результата проверок
530
+ if all(checks.values()):
531
+ return message
532
+ prompt = append_errors_to_prompt(prompt, checks)
533
+ time.sleep(1)
534
+ gr.Info("Не удалось сгенерировать сообщение, соответствующее требованиям, за 20 итераций. Возвращаем последнее сгенерированное сообщение.")
535
+ return last_message
536
+
537
+
538
  # Функция для создания задания для копирайтера
539
  def generate_standard_prompt(description, advantages, key_message, *selected_values):
540
  prompt = (
 
672
  yield standard_prompt, display_personalization_prompt, None, None, None, None, None, None
673
  flag += 1
674
  prompt = add_prefix_suffix(standard_prompt, prefixes[i], suffixes[i])
675
+ non_personalized_message = generate_message_mistral_with_retry(prompt, current_prefix, desc, key_message)
676
  non_personalized_length = len(non_personalized_message)
677
  non_personalized_display = f"{non_personalized_message}\n------\nКоличество знаков: {non_personalized_length}"
678
  non_personalized_messages.append(non_personalized_display)
 
690
 
691
  # Генерация персонализированного сообщения
692
  full_personalized_prompt = f"{personalization_prompt}\n\nТекст для адаптации: {non_personalized_message}"
693
+ personalized_message = generate_message_mistral_with_retry(full_personalized_prompt, current_prefix, desc, key_message)
694
  personalized_length = len(personalized_message)
695
  personalized_display = f"{personalized_message}\n------\nКоличество знаков: {personalized_length}"
696
  personalized_messages.append(personalized_display)
 
716
  # 1. Запрещенные слова
717
 
718
  def check_forbidden_words(message):
719
+ morph = pymorphy3.MorphAnalyzer()
720
 
721
  # Перечень запрещённых слов и фраз
722
  forbidden_patterns = [
 
750
  # 2 и #3. Обращение к клиенту и приветствие клиента
751
 
752
  def check_no_greeting(message):
753
+ morph = pymorphy3.MorphAnalyzer()
754
  # Список типичных обращений и приветствий
755
  greeting_patterns = [
756
  r"привет\b", r"здравствуй", r"добрый\s(день|вечер|утро)",
 
770
  # 4. Обещания и гарантии
771
 
772
  def check_no_promises(message):
773
+ morph = pymorphy3.MorphAnalyzer()
774
  promise_patterns = [
775
  "обещать", "обещание", "гарантировать", "обязаться", "обязать", "обязательство", "обязательный"
776
  ]
 
786
  # 5. Составные конструкции из двух глаголов
787
 
788
  def check_no_double_verbs(message):
789
+ morph = pymorphy3.MorphAnalyzer()
790
  # Разделяем текст по пробелам и знакам препинания
791
  words = re.split(r'\s+|[.!?]', message)
792
  morphs = [morph.parse(word)[0] for word in words]
 
804
  # 6. Причастия и причастные обороты
805
 
806
  def check_no_participles(message):
807
+ morph = pymorphy3.MorphAnalyzer()
808
  words = message.split()
809
  exceptions = {"повышенный", "увеличенный", "пониженный", "сниженный"}
810
 
 
818
  # 7. Деепричастия и деепричастные обороты
819
 
820
  def check_no_adverbial_participles(message):
821
+ morph = pymorphy3.MorphAnalyzer()
822
  words = message.split()
823
  morphs = [morph.parse(word)[0] for word in words]
824
 
 
830
  # 8. Превосходная степень прилагательных
831
 
832
  def check_no_superlative_adjectives(message):
833
+ morph = pymorphy3.MorphAnalyzer()
834
  words = message.split()
835
  morphs = [morph.parse(word)[0] for word in words]
836
 
 
842
  # 9. Страдательный залог
843
 
844
  def check_no_passive_voice(message):
845
+ morph = pymorphy3.MorphAnalyzer()
846
  words = message.split()
847
  morphs = [morph.parse(word)[0] for word in words]
848
 
 
854
  # 10. Порядковые числительные от 10 прописью
855
 
856
  def check_no_written_out_ordinals(message):
857
+ morph = pymorphy3.MorphAnalyzer()
858
  ordinal_words = [
859
  "десятый", "одиннадцатый", "двенадцатый", "тринадцатый", "четырнадцатый", "пятнадцатый",
860
  "шестнадцатый", "семнадцатый", "восемнадцатый", "девятнадцатый", "двадцатый"
 
943
  def check_no_multiple_nouns(message):
944
  noun_count = 0
945
  words = re.split(r'\s+|[.!?]', message) # Разбиваем по пробелам и знакам препинания
946
+ morph = pymorphy3.MorphAnalyzer()
947
 
948
  for word in words:
949
  parsed_word = morph.parse(word)[0]
 
1013
  # Доп правило. Повторы слов
1014
 
1015
  def check_no_word_repetitions(message):
1016
+ morph = pymorphy3.MorphAnalyzer()
1017
 
1018
  # Список союзов и предлогов, которые мы будем игнорировать
1019
  ignore_words = set([
 
1112
  если таких предложений **нет**, **верни только** JSON {{"decision": false, "explanation": "<пояснение>"}}.
1113
  **Не добавляй никакого дополнительного текста. Перед ответом убедись, что отвечаешь **только** в формате JSON с закрывающими кавычками и скобками.**'''
1114
 
1115
+ response = generate_message_mistral_check(prompt)
1116
  time.sleep(3) # Задержка в 3 секунды между запросами
1117
+ print("Mistral response:", response) # Выводим полный ответ модели
1118
  result = parse_json_response(response)
1119
  if result is not None:
1120
  decision = result.get("decision", False)
 
1139
  если таких слов или выражений нет, **верни только** JSON {{"decision": false, "explanation": "<пояснение>"}}.
1140
  **Не добавляй никакого дополнительного текста. Перед ответом убедись, что отвечаешь только в формате JSON с закрывающими кавычками и скобками.**'''
1141
 
1142
+ response = generate_message_mistral_check(prompt)
1143
  time.sleep(3)
1144
+ print("Mistral response:", response)
1145
  result = parse_json_response(response)
1146
  if result is not None:
1147
  decision = result.get("decision", False)
 
1172
 
1173
  **Не добавляй никакого дополнительного текста. Перед ответом убедись, что отвечаешь только в формате JSON с закрывающими кавычками и скобками.**'''
1174
 
1175
+ response = generate_message_mistral_check(prompt)
1176
  time.sleep(3)
1177
+ print("Mistral response:", response)
1178
  result = parse_json_response(response)
1179
  if result is not None:
1180
  decision = result.get("decision", False)
 
1218
 
1219
  **Не добавляй никакого дополнительного текста. Перед ответом убедись, что отвечаешь только в формате JSON с закрывающими кавычками и скобками.**'''
1220
 
1221
+ response = generate_message_mistral_check(prompt)
1222
  time.sleep(3)
1223
+ print("Mistral response:", response)
1224
  result = parse_json_response(response)
1225
  if result is not None:
1226
  decision = result.get("decision", False)
 
1255
 
1256
  **Не добавляй никакого дополнительного текста. Перед ответом убедись, что отвечаешь только в формате JSON с закрывающими кавычками и скобками.**'''
1257
 
1258
+ response = generate_message_mistral_check(prompt)
1259
  time.sleep(3)
1260
+ print("Mistral response:", response)
1261
  result = parse_json_response(response)
1262
  if result is not None:
1263
  decision = result.get("decision", False)
 
1284
  если таких фраз нет, **верни только** JSON {{"decision": false, "explanation": "<пояснение>"}}.
1285
  **Не добавляй никакого дополнительного текста. Перед ответом убедись, что отвечаешь только в формате JSON с закрывающими кавычками и скобками.**'''
1286
 
1287
+ response = generate_message_mistral_check(prompt)
1288
  time.sleep(3)
1289
+ print("Mistral response:", response)
1290
  result = parse_json_response(response)
1291
  if result is not None:
1292
  decision = result.get("decision", False)
 
1327
  если в тексте **есть** такие выражения, **верни только** JSON {{"decision": true, "explanation": "<пояснение>"}}.
1328
  **Не добавляй никакого дополнительного текста. Перед ответом убедись, что отвечаешь только в формате JSON с закрывающими кавычками и скобками.**'''
1329
 
1330
+ response = generate_message_mistral_check(prompt)
1331
  time.sleep(3)
1332
+ print("Mistral response:", response)
1333
  result = parse_json_response(response)
1334
  if result is not None:
1335
  decision = result.get("decision", False)
 
1354
  Если сообщение содержит факты, которые отсутствуют в описании предложения, **верни только** JSON {{"decision": true, "explanation": "<описание противоречий>"}}.
1355
  **Не добавляй никакого дополнительного текста. Отвечай только в формате JSON с закрывающими кавычками и скобками.**'''
1356
 
1357
+ response = generate_message_mistral_check(prompt)
1358
  time.sleep(3)
1359
+ print("Mistral response:", response)
1360
  result = parse_json_response(response)
1361
  if result is not None:
1362
  decision = result.get("decision", False)
 
1381
  Если сообщение **не содержит всю** информацию из ключевого текста, **верни только** JSON {{"decision": true, "explanation": "Ключевое текст отсутствует."}}.
1382
  **Не добавляй никакого дополнительного текста. Отвечай только в формате JSON с закрывающими кавычками и скобками.**'''
1383
 
1384
+ response = generate_message_mistral_check(prompt)
1385
  time.sleep(3)
1386
+ print("Mistral response:", response)
1387
  result = parse_json_response(response)
1388
  if result is not None:
1389
  decision = result.get("decision", False)
 
1406
  def perform_checks(message, description, key_message):
1407
  checks = {}
1408
 
1409
+ # 2. Morphological checks using pymorphy3
1410
  morphological_checks = [
1411
  ("forbidden_words", check_forbidden_words),
1412
  ("client_addressing", check_no_greeting),
 
1519
  return " \n".join(formatted_results)
1520
 
1521
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1522
  # Интерфейс Gradio
1523
  with gr.Blocks() as demo:
1524
  # Твой интерфейс
 
1590
  non_personalized_messages = gr.Textbox(label="Стандартные сообщения", lines=12, interactive=False)
1591
  personalized_messages = gr.Textbox(label="Персонализированные сообщения", lines=12, interactive=False)
1592
 
 
 
 
 
 
1593
  # Сначала переключаем вкладку, потом запускаем генерацию сообщений
1594
  btn_to_prompts.click(
1595
  fn=change_tab,