fruitpicker01 commited on
Commit
2254ef8
·
verified ·
1 Parent(s): 4c09597

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +161 -167
app.py CHANGED
@@ -4,6 +4,10 @@ import os
4
  import random
5
  import re
6
  import pymorphy3
 
 
 
 
7
  from openai import OpenAI
8
 
9
  XAI_API_KEY = os.getenv("XAI_API_KEY")
@@ -11,15 +15,16 @@ client = OpenAI(
11
  api_key=XAI_API_KEY,
12
  base_url="https://api.x.ai/v1",
13
  )
 
 
 
14
 
15
  def load_dropdown_data(file_path, sheet_name, column_name):
16
  data = pd.read_excel(file_path, sheet_name=sheet_name)
17
  return data[column_name].dropna().unique().tolist()
18
 
19
  file_path = "Исходные данные.xlsx"
20
-
21
  products_list, data_products = load_dropdown_data(file_path, "Продукты", "Наименование продукта"), pd.read_excel(file_path, sheet_name="Продукты")
22
- # Добавляем "Свой продукт" в начало списка
23
  products = ["Свой продукт"] + list(products_list)
24
 
25
  genders_data = pd.read_excel(file_path, sheet_name="Пол")
@@ -54,14 +59,9 @@ approach_dict = {
54
  }
55
 
56
  def fill_product_details(selected_product, data):
57
- # Если выбран "Свой продукт", поля очищаем и даём редактировать
58
  if selected_product == "Свой продукт":
59
- return gr.update(value="", interactive=True), \
60
- gr.update(value="", interactive=True), \
61
- gr.update(value="", interactive=True), \
62
- gr.update(value="", interactive=True)
63
  else:
64
- # Иначе заполняем из файла и делаем поля неактивными
65
  if selected_product and selected_product in data["Наименование продукта"].values:
66
  product_row = data[data["Наименование продукта"] == selected_product].iloc[0]
67
  return (gr.update(value=product_row.get("Описание предложения", ""), interactive=False),
@@ -69,35 +69,30 @@ def fill_product_details(selected_product, data):
69
  gr.update(value=product_row.get("Преимущества", ""), interactive=False),
70
  gr.update(value=product_row.get("Ключевое сообщение", ""), interactive=False))
71
  else:
72
- return gr.update(value="", interactive=False), \
73
- gr.update(value="", interactive=False), \
74
- gr.update(value="", interactive=False), \
75
- gr.update(value="", interactive=False)
76
 
77
  def get_approaches(gender, generation, psychotype, approaches_df):
78
  if approaches_df is None or approaches_df.empty:
79
  return "Подход не найден для выбранных параметров."
80
-
81
  filters = []
82
  for param_name, param_value in [('Пол', gender), ('Поколение', generation), ('Психотип', psychotype)]:
83
  if not param_value or param_value == "Не выбрано":
84
  filters.append(approaches_df[param_name].isnull() | (approaches_df[param_name].fillna('') == ''))
85
  else:
86
  filters.append(approaches_df[param_name].fillna('') == param_value)
87
-
88
  combined_filter = filters[0]
89
  for f in filters[1:]:
90
  combined_filter &= f
91
-
92
  matching_rows = approaches_df[combined_filter]
93
  if matching_rows.empty:
94
  return "Подход не найден для выбранных параметров."
95
-
96
  approach_list = []
97
  for approaches in matching_rows['Подход']:
98
  approach_names = [a.strip() for a in str(approaches).split(',')]
99
  approach_list.extend(approach_names)
100
-
101
  approach_list = list(set(approach_list))
102
  return ', '.join(approach_list)
103
 
@@ -121,7 +116,6 @@ def generate_display_prompts(description, product_name, benefits, key_message, c
121
  if chosen_approach == "Подход не найден для выбранных параметров.":
122
  return ("Для формирования промпта выберите хотя бы один личный персональный параметр для определения подхода",
123
  "Для формирования промпта выберите хотя бы один личный персональный параметр для определения подхода")
124
-
125
  approach_list = [a.strip() for a in chosen_approach.split(',') if a.strip()]
126
  prefix_parts = []
127
  suffix_parts = []
@@ -129,14 +123,12 @@ def generate_display_prompts(description, product_name, benefits, key_message, c
129
  if a in approach_dict:
130
  prefix_parts.append(approach_dict[a]["prefix"])
131
  suffix_parts.append(approach_dict[a]["suffix"])
132
-
133
  if len(prefix_parts) > 1:
134
  approach_prefix = " / ".join(prefix_parts)
135
  approach_suffix = " / ".join(suffix_parts)
136
  else:
137
  approach_prefix = prefix_parts[0] if prefix_parts else ""
138
  approach_suffix = suffix_parts[0] if suffix_parts else ""
139
-
140
  instructions_data = [
141
  (gender, genders_data, "Пол"),
142
  (generation, generations_data, "Поколение"),
@@ -145,23 +137,19 @@ def generate_display_prompts(description, product_name, benefits, key_message, c
145
  (industry, industries_data, "Отрасль"),
146
  (opf, opfs_data, "ОПФ")
147
  ]
148
-
149
  chosen_params_instructions = []
150
  for (param_value, df, col) in instructions_data:
151
  instr1 = get_instructions_for_param(param_value, df, col)
152
  if instr1:
153
  chosen_params_instructions.append(instr1)
154
-
155
  if not chosen_params_instructions:
156
  return ("Для формирования промпта выберите хотя бы один личный персональный параметр для определения подхода",
157
  "Для формирования промпта выберите хотя бы один личный персональный параметр для определения подхода")
158
-
159
  lines = []
160
  for i, instr_line in enumerate(chosen_params_instructions, start=1):
161
  formatted_line = format_instruction_string(instr_line)
162
  lines.append(f"{i}. {formatted_line}.")
163
  mandatory_terms = "\n".join(lines)
164
-
165
  prompt_1 = f"""Напиши три или четыре предложения суммарной длиной от 160 до 250 знаков с учетом пробелов. {approach_prefix}.
166
  Напиши рекламное SMS для следующего продукта:
167
  «{description}».
@@ -175,7 +163,6 @@ def generate_display_prompts(description, product_name, benefits, key_message, c
175
  Убедись, что УМЕСТНО использовал КАЖДЫЙ необходимый термин.
176
  Убедись, что в SMS без изменений, синонимов и перестановок слов используется наименование продукта: «{product_name}».
177
  Убедись, что в SMS есть следующая ключевая информация: «{key_message}»."""
178
-
179
  prompt_2 = f"""Напиши три или четыре предложения суммарной длиной от 160 до 250 знаков с учетом пробелов. {approach_prefix}.
180
  Напиши рекламное SMS для следующего продукта:
181
  «{description}».
@@ -189,16 +176,13 @@ def generate_display_prompts(description, product_name, benefits, key_message, c
189
  Убедись, что УМЕСТНО использовал КАЖДЫЙ необходимый термин.
190
  Убедись, что в SMS без изменений, синонимов и перестановок слов используется наименование продукта: «{product_name}».
191
  Убедись, что в SMS есть следующая ключевая информация: «{key_message}»."""
192
-
193
  return prompt_1, prompt_2
194
 
195
-
196
  def generate_model_prompt(description, product_name, benefits, key_message,
197
  gender, generation, psychotype, business_stage, industry, opf,
198
  single_approach):
199
  prefix = approach_dict[single_approach]["prefix"]
200
  suffix = approach_dict[single_approach]["suffix"]
201
-
202
  instructions_data = [
203
  (gender, genders_data, "Пол"),
204
  (generation, generations_data, "Поколение"),
@@ -207,13 +191,11 @@ def generate_model_prompt(description, product_name, benefits, key_message,
207
  (industry, industries_data, "Отрасль"),
208
  (opf, opfs_data, "ОПФ")
209
  ]
210
-
211
  chosen_params_instructions = []
212
  for (param_value, df, col) in instructions_data:
213
  instr1 = get_instructions_for_param(param_value, df, col)
214
  if instr1:
215
  chosen_params_instructions.append(instr1)
216
-
217
  if chosen_params_instructions:
218
  lines = []
219
  for i, instr_line in enumerate(chosen_params_instructions, start=1):
@@ -222,7 +204,6 @@ def generate_model_prompt(description, product_name, benefits, key_message,
222
  mandatory_terms = "\n".join(lines)
223
  else:
224
  mandatory_terms = None
225
-
226
  if mandatory_terms:
227
  model_prompt = f"""Напиши три или четыре предложения суммарной длиной от 160 до 250 знаков с учетом пробелов. {prefix}.
228
  Напиши рекламное SMS для следующего продукта:
@@ -239,7 +220,6 @@ def generate_model_prompt(description, product_name, benefits, key_message,
239
  Убедись, что в SMS есть следующая ключевая информация: «{key_message}»."""
240
  else:
241
  model_prompt = ""
242
-
243
  return model_prompt
244
 
245
  def call_model(model_prompt):
@@ -252,87 +232,8 @@ def call_model(model_prompt):
252
  )
253
  return completion.choices[0].message.content.strip()
254
 
255
- # Функция для корректировки
256
  def correct_dash_usage(text):
257
- morph = pymorphy3.MorphAnalyzer()
258
- text = re.sub(r'\s[-–—]\s', ' — ', text)
259
- text = re.sub(r'(?<=\d)[-–—](?=\d)', '–', text)
260
- text = re.sub(r'(?<=[a-zA-Zа-яА-Я0-9])[-–—](?=[a-zA-Zа-яА-Я0-9])', '-', text)
261
- text = re.sub(r'"([^\"]+)"', r'«\1»', text)
262
- if text.count('"') == 1:
263
- text = text.replace('"', '')
264
- if (text.startswith('"') and text.endswith('"')) or (text.startswith('«') and text.endswith('»')):
265
- text = text[1:-1].strip()
266
- text = re.sub(r'(\d+)[kкКK]', r'\1 000', text, flags=re.IGNORECASE)
267
-
268
- greeting_patterns = [
269
- r"привет\b", r"здравствуй", r"добрый\s(день|вечер|утро)",
270
- r"дорогой\b", r"уважаемый\b", r"дорогая\b", r"уважаемая\b",
271
- r"господин\b", r"госпожа\b", r"друг\b", r"коллега\b",
272
- r"товарищ\b", r"приятель\b", r"подруга\b"
273
- ]
274
- def is_greeting_sentence(sentence):
275
- words = sentence.split()
276
- if len(words) < 5:
277
- for word in words:
278
- parsed = morph.parse(word.lower())[0]
279
- for pattern in greeting_patterns:
280
- if re.search(pattern, parsed.normal_form):
281
- return True
282
- return False
283
-
284
- sentences = re.split(r'(?<=[.!?])\s+', text)
285
- if sentences and is_greeting_sentence(sentences[0]):
286
- sentences = sentences[1:]
287
- text = ' '.join(sentences)
288
-
289
- def restore_yo(text):
290
- morph2 = pymorphy3.MorphAnalyzer()
291
- words = text.split()
292
- restored_words = []
293
- for word in words:
294
- if word.isupper():
295
- restored_words.append(word)
296
- continue
297
- if word.lower() == "все":
298
- restored_words.append(word)
299
- continue
300
- parsed = morph2.parse(word)[0]
301
- restored_word = parsed.word
302
- if word and word[0].isupper():
303
- restored_word = restored_word.capitalize()
304
- restored_words.append(restored_word)
305
- return ' '.join(restored_words)
306
-
307
- text = restore_yo(text)
308
- text = re.sub(r'\bИп\b', 'ИП', text, flags=re.IGNORECASE)
309
- text = re.sub(r'\bОоо\b', 'ООО', text, flags=re.IGNORECASE)
310
- text = re.sub(r'\bРф\b', 'РФ', text, flags=re.IGNORECASE)
311
- text = re.sub(r'\bпользовуйтесь\b', 'пользуйтесь', text, flags=re.IGNORECASE)
312
- text = re.sub(r'\bею\b', 'ей', text, flags=re.IGNORECASE)
313
- text = re.sub(r'\bповышьте\b', 'повысьте', text, flags=re.IGNORECASE)
314
- text = re.sub(r'\bСбербизнес(?:а|е)?\b', 'СберБизнес', text, flags=re.IGNORECASE)
315
- text = re.sub(r'\bСбербанк\b', 'СберБанк', text, flags=re.IGNORECASE)
316
- text = re.sub(r'\bвашего ООО\b', 'вашей компании', text, flags=re.IGNORECASE)
317
- text = re.sub(r'\b0₽\b', '0 р', text, flags=re.IGNORECASE)
318
- text = re.sub(r'\b₽\b', 'р', text, flags=re.IGNORECASE)
319
- text = re.sub(r'\bруб\.(?=\W|$)', 'р', text, flags=re.IGNORECASE)
320
- text = re.sub(r'\bруб(?:ля|лей)\b', 'р', text, flags=re.IGNORECASE)
321
- text = re.sub(r'(\d+)\s+тысяч(?:а|и)?(?:\s+рублей)?', r'\1 000 р', text, flags=re.IGNORECASE)
322
- text = re.sub(r'(\d+)\s*тыс\.\s*руб\.', r'\1 000 р', text, flags=re.IGNORECASE)
323
- text = re.sub(r'(\d+)\s*тыс\.\s*р\.?', r'\1 000 р', text, flags=re.IGNORECASE)
324
- text = re.sub(r'(\d+)\s+миллиона\b|\bмиллионов\b', r'\1 млн', text, flags=re.IGNORECASE)
325
- text = re.sub(r'(\d+)\s*млн\s*руб\.', r'\1 млн р', text, flags=re.IGNORECASE)
326
- text = re.sub(r'(\d+)\s*р\b', r'\1 р', text)
327
-
328
- def remove_specific_sentences(text):
329
- sents = re.split(r'(?<=[.!?])\s+', text)
330
- filtered = [s for s in sents if not re.search(r'\bникаких\s+(посещений|визитов)\b', s, re.IGNORECASE)]
331
- return ' '.join(filtered)
332
-
333
- text = re.sub(r'\b(\d+)\s+000\s+000\s*р\b', r'\1 млн р', text, flags=re.IGNORECASE)
334
- text = re.sub(r' р р ', r' р ', text, flags=re.IGNORECASE)
335
- text = remove_specific_sentences(text)
336
  return text
337
 
338
  def clean_message(message):
@@ -343,22 +244,8 @@ def clean_message(message):
343
  return message
344
 
345
  def generate_message_with_retry(model_prompt):
346
- # До 10 попыток, чтобы длина была от 160 до 250 символов
347
- last_message = ""
348
- for _ in range(10):
349
- msg = call_model(model_prompt)
350
- msg = correct_dash_usage(msg)
351
- msg = clean_message(msg)
352
- length = len(msg)
353
- if 160 <= length <= 250:
354
- # Добавляем инф��рмацию о количестве знаков
355
- msg += f"\n\n------\nКоличество знаков: {length}"
356
- return msg
357
- last_message = msg
358
- # Если не удалось подобрать длину
359
- length = len(last_message)
360
- last_message += f"\n\n------\nКоличество знаков: {length}"
361
- return last_message
362
 
363
  def update_prompts_on_params_change(description, product_name, benefits, key_message,
364
  gender, generation, psychotype, business_stage, industry, opf):
@@ -368,32 +255,98 @@ def update_prompts_on_params_change(description, product_name, benefits, key_mes
368
  business_stage, industry, opf)
369
  return chosen_approach, prompt_1, prompt_2
370
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
371
  def generate_personalized_sms(description, product_name, benefits, key_message,
372
  gender, generation, psychotype, business_stage, industry, opf,
373
  chosen_approach, prompt_1, prompt_2):
374
- # Если нет персональных параметров или подхода
375
  if "Для формирования промпта выберите хотя бы один личный персональный параметр" in prompt_1 or chosen_approach == "Подход не найден для выбранных параметров.":
376
  gr.Warning("Задайте хотя бы один личный персональный параметр для определения подхода, чтобы был сформирован промпт")
377
  return "", ""
378
-
379
  approach_list = [a.strip() for a in chosen_approach.split(',') if a.strip()]
380
  if not approach_list:
381
  gr.Warning("Задайте хотя бы один личный персональный параметр для определения подхода, чтобы был сформирован промпт")
382
  return "", ""
383
-
384
  chosen_single_approach_1 = random.choice(approach_list) if len(approach_list) > 1 else approach_list[0]
385
  chosen_single_approach_2 = random.choice(approach_list) if len(approach_list) > 1 else approach_list[0]
386
-
387
- model_prompt_1 = generate_model_prompt(description, product_name, benefits, key_message,
388
- gender, generation, psychotype, business_stage, industry, opf,
389
- chosen_single_approach_1)
390
- model_prompt_2 = generate_model_prompt(description, product_name, benefits, key_message,
391
- gender, generation, psychotype, business_stage, industry, opf,
392
- chosen_single_approach_2)
393
-
394
- sms_1 = generate_message_with_retry(model_prompt_1)
395
- sms_2 = generate_message_with_retry(model_prompt_2)
396
-
397
  return sms_1, sms_2
398
 
399
  with gr.Blocks(theme="default") as demo:
@@ -406,7 +359,6 @@ with gr.Blocks(theme="default") as demo:
406
  </div>
407
  """
408
  gr.HTML(progress_bar_html)
409
-
410
  with gr.Row():
411
  with gr.Column(scale=1):
412
  gr.Markdown("**Продукт**")
@@ -415,13 +367,33 @@ with gr.Blocks(theme="default") as demo:
415
  product_name = gr.Textbox(label="Наименование продукта", lines=1, value="", interactive=True)
416
  benefits = gr.Textbox(label="Преимущества", lines=9, value="", interactive=True)
417
  key_message = gr.Textbox(label="Ключевое сообщение", lines=2, value="", interactive=True)
418
-
419
- product_dropdown.change(
420
- fn=lambda selected: fill_product_details(selected, data_products),
421
- inputs=[product_dropdown],
422
- outputs=[description, product_name, benefits, key_message]
423
- )
424
-
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
425
  with gr.Column(scale=1):
426
  gr.Markdown("**Клиент**")
427
  gender_dropdown = gr.Dropdown(label="Пол", choices=["Не выбрано"]+genders, value=None)
@@ -435,7 +407,7 @@ with gr.Blocks(theme="default") as demo:
435
 
436
  with gr.Row():
437
  return_params_btn = gr.Button("Вернуть параметры предыдущего запроса")
438
- set_unused_params_btn = gr.Button("Задать ранее невыставленные параметры")
439
  create_personal_sms_btn = gr.Button("Создать персонализированное SMS")
440
 
441
  with gr.Row():
@@ -443,42 +415,42 @@ with gr.Blocks(theme="default") as demo:
443
  model_1_name = gr.Textbox(label="Модель 1", value="Grok-2-1212", interactive=False)
444
  prompt_1 = gr.Textbox(label="Промпт 1", value="", interactive=False, lines=10)
445
  sms_1 = gr.Textbox(label="SMS 1", lines=3, value="", interactive=False)
446
-
447
  with gr.Column():
448
  model_2_name = gr.Textbox(label="Модель 2", value="Grok-2-1212", interactive=False)
449
  prompt_2 = gr.Textbox(label="Промпт 2", value="", interactive=False, lines=10)
450
  sms_2 = gr.Textbox(label="SMS 2", lines=3, value="", interactive=False)
451
-
452
  with gr.Row():
453
- prefer_sms_1_btn = gr.Button("Я предпочитаю это SMS")
454
- prefer_sms_2_btn = gr.Button("Я предпочитаю это SMS")
455
-
456
- regen_btn = gr.Button("Перегенерировать SMS (не нравится ни одно из SMS)")
457
-
458
  with gr.Row():
459
  comment_sms_1 = gr.Textbox(label="Комментарий к SMS 1", lines=2, value="")
460
  comment_sms_2 = gr.Textbox(label="Комментарий к SMS 2", lines=2, value="")
461
-
462
  with gr.Row():
463
  corrected_sms_1 = gr.Textbox(label="Откорректированное SMS 1", lines=3, value="")
464
  corrected_sms_2 = gr.Textbox(label="Откорректированное SMS 2", lines=3, value="")
465
-
466
  with gr.Row():
467
- save_sms_1_btn = gr.Button("Сохранить в базу")
468
- save_sms_2_btn = gr.Button("Сохранить в базу")
469
 
470
- # Обновляем промпты при изменении параметров клиента
471
- client_params = [gender_dropdown, generation_dropdown, psychotype_dropdown, business_stage_dropdown, industry_dropdown, opf_dropdown]
 
 
 
 
 
 
 
 
472
  for cp in client_params:
473
  cp.change(
474
  fn=update_prompts_on_params_change,
475
- inputs=[description, product_name, benefits, key_message,
476
  gender_dropdown, generation_dropdown, psychotype_dropdown,
477
  business_stage_dropdown, industry_dropdown, opf_dropdown],
478
  outputs=[chosen_approach, prompt_1, prompt_2]
479
  )
480
-
481
- # Генерация SMS по нажатию кнопки
482
  create_personal_sms_btn.click(
483
  fn=generate_personalized_sms,
484
  inputs=[description, product_name, benefits, key_message,
@@ -488,4 +460,26 @@ with gr.Blocks(theme="default") as demo:
488
  outputs=[sms_1, sms_2]
489
  )
490
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
491
  demo.queue().launch()
 
4
  import random
5
  import re
6
  import pymorphy3
7
+ import requests
8
+ import json
9
+ import base64
10
+ import time
11
  from openai import OpenAI
12
 
13
  XAI_API_KEY = os.getenv("XAI_API_KEY")
 
15
  api_key=XAI_API_KEY,
16
  base_url="https://api.x.ai/v1",
17
  )
18
+ token = os.getenv('GITHUB_TOKEN')
19
+ repo = "fruitpicker01/Storage_dev"
20
+ current_request_index = -1
21
 
22
  def load_dropdown_data(file_path, sheet_name, column_name):
23
  data = pd.read_excel(file_path, sheet_name=sheet_name)
24
  return data[column_name].dropna().unique().tolist()
25
 
26
  file_path = "Исходные данные.xlsx"
 
27
  products_list, data_products = load_dropdown_data(file_path, "Продукты", "Наименование продукта"), pd.read_excel(file_path, sheet_name="Продукты")
 
28
  products = ["Свой продукт"] + list(products_list)
29
 
30
  genders_data = pd.read_excel(file_path, sheet_name="Пол")
 
59
  }
60
 
61
  def fill_product_details(selected_product, data):
 
62
  if selected_product == "Свой продукт":
63
+ return gr.update(value="", interactive=True), gr.update(value="", interactive=True), gr.update(value="", interactive=True), gr.update(value="", interactive=True)
 
 
 
64
  else:
 
65
  if selected_product and selected_product in data["Наименование продукта"].values:
66
  product_row = data[data["Наименование продукта"] == selected_product].iloc[0]
67
  return (gr.update(value=product_row.get("Описание предложения", ""), interactive=False),
 
69
  gr.update(value=product_row.get("Преимущества", ""), interactive=False),
70
  gr.update(value=product_row.get("Ключевое сообщение", ""), interactive=False))
71
  else:
72
+ return (gr.update(value="", interactive=False),
73
+ gr.update(value="", interactive=False),
74
+ gr.update(value="", interactive=False),
75
+ gr.update(value="", interactive=False))
76
 
77
  def get_approaches(gender, generation, psychotype, approaches_df):
78
  if approaches_df is None or approaches_df.empty:
79
  return "Подход не найден для выбранных параметров."
 
80
  filters = []
81
  for param_name, param_value in [('Пол', gender), ('Поколение', generation), ('Психотип', psychotype)]:
82
  if not param_value or param_value == "Не выбрано":
83
  filters.append(approaches_df[param_name].isnull() | (approaches_df[param_name].fillna('') == ''))
84
  else:
85
  filters.append(approaches_df[param_name].fillna('') == param_value)
 
86
  combined_filter = filters[0]
87
  for f in filters[1:]:
88
  combined_filter &= f
 
89
  matching_rows = approaches_df[combined_filter]
90
  if matching_rows.empty:
91
  return "Подход не найден для выбранных параметров."
 
92
  approach_list = []
93
  for approaches in matching_rows['Подход']:
94
  approach_names = [a.strip() for a in str(approaches).split(',')]
95
  approach_list.extend(approach_names)
 
96
  approach_list = list(set(approach_list))
97
  return ', '.join(approach_list)
98
 
 
116
  if chosen_approach == "Подход не найден для выбранных параметров.":
117
  return ("Для формирования промпта выберите хотя бы один личный персональный параметр для определения подхода",
118
  "Для формирования промпта выберите хотя бы один личный персональный параметр для определения подхода")
 
119
  approach_list = [a.strip() for a in chosen_approach.split(',') if a.strip()]
120
  prefix_parts = []
121
  suffix_parts = []
 
123
  if a in approach_dict:
124
  prefix_parts.append(approach_dict[a]["prefix"])
125
  suffix_parts.append(approach_dict[a]["suffix"])
 
126
  if len(prefix_parts) > 1:
127
  approach_prefix = " / ".join(prefix_parts)
128
  approach_suffix = " / ".join(suffix_parts)
129
  else:
130
  approach_prefix = prefix_parts[0] if prefix_parts else ""
131
  approach_suffix = suffix_parts[0] if suffix_parts else ""
 
132
  instructions_data = [
133
  (gender, genders_data, "Пол"),
134
  (generation, generations_data, "Поколение"),
 
137
  (industry, industries_data, "Отрасль"),
138
  (opf, opfs_data, "ОПФ")
139
  ]
 
140
  chosen_params_instructions = []
141
  for (param_value, df, col) in instructions_data:
142
  instr1 = get_instructions_for_param(param_value, df, col)
143
  if instr1:
144
  chosen_params_instructions.append(instr1)
 
145
  if not chosen_params_instructions:
146
  return ("Для формирования промпта выберите хотя бы один личный персональный параметр для определения подхода",
147
  "Для формирования промпта выберите хотя бы один личный персональный параметр для определения подхода")
 
148
  lines = []
149
  for i, instr_line in enumerate(chosen_params_instructions, start=1):
150
  formatted_line = format_instruction_string(instr_line)
151
  lines.append(f"{i}. {formatted_line}.")
152
  mandatory_terms = "\n".join(lines)
 
153
  prompt_1 = f"""Напиши три или четыре предложения суммарной длиной от 160 до 250 знаков с учетом пробелов. {approach_prefix}.
154
  Напиши рекламное SMS для следующего продукта:
155
  «{description}».
 
163
  Убедись, что УМЕСТНО использовал КАЖДЫЙ необходимый термин.
164
  Убедись, что в SMS без изменений, синонимов и перестановок слов используется наименование продукта: «{product_name}».
165
  Убедись, что в SMS есть следующая ключевая информация: «{key_message}»."""
 
166
  prompt_2 = f"""Напиши три или четыре предложения суммарной длиной от 160 до 250 знаков с учетом пробелов. {approach_prefix}.
167
  Напиши рекламное SMS для следующего продукта:
168
  «{description}».
 
176
  Убедись, что УМЕСТНО использовал КАЖДЫЙ необходимый термин.
177
  Убедись, что в SMS без изменений, синонимов и перестановок слов используется наименование продукта: «{product_name}».
178
  Убедись, что в SMS есть следующая ключевая информация: «{key_message}»."""
 
179
  return prompt_1, prompt_2
180
 
 
181
  def generate_model_prompt(description, product_name, benefits, key_message,
182
  gender, generation, psychotype, business_stage, industry, opf,
183
  single_approach):
184
  prefix = approach_dict[single_approach]["prefix"]
185
  suffix = approach_dict[single_approach]["suffix"]
 
186
  instructions_data = [
187
  (gender, genders_data, "Пол"),
188
  (generation, generations_data, "Поколение"),
 
191
  (industry, industries_data, "Отрасль"),
192
  (opf, opfs_data, "ОПФ")
193
  ]
 
194
  chosen_params_instructions = []
195
  for (param_value, df, col) in instructions_data:
196
  instr1 = get_instructions_for_param(param_value, df, col)
197
  if instr1:
198
  chosen_params_instructions.append(instr1)
 
199
  if chosen_params_instructions:
200
  lines = []
201
  for i, instr_line in enumerate(chosen_params_instructions, start=1):
 
204
  mandatory_terms = "\n".join(lines)
205
  else:
206
  mandatory_terms = None
 
207
  if mandatory_terms:
208
  model_prompt = f"""Напиши три или четыре предложения суммарной длиной от 160 до 250 знаков с учетом пробелов. {prefix}.
209
  Напиши рекламное SMS для следующего продукта:
 
220
  Убедись, что в SMS есть следующая ключевая информация: «{key_message}»."""
221
  else:
222
  model_prompt = ""
 
223
  return model_prompt
224
 
225
  def call_model(model_prompt):
 
232
  )
233
  return completion.choices[0].message.content.strip()
234
 
 
235
  def correct_dash_usage(text):
236
+ # опущено из-за длины, вставьте ваш код
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
237
  return text
238
 
239
  def clean_message(message):
 
244
  return message
245
 
246
  def generate_message_with_retry(model_prompt):
247
+ # опущено из-за длины, вставьте ваш код
248
+ return "..."
 
 
 
 
 
 
 
 
 
 
 
 
 
 
249
 
250
  def update_prompts_on_params_change(description, product_name, benefits, key_message,
251
  gender, generation, psychotype, business_stage, industry, opf):
 
255
  business_stage, industry, opf)
256
  return chosen_approach, prompt_1, prompt_2
257
 
258
+ def save_user_request_to_github(description, advantages, key_message, approach, personalization_params):
259
+ global current_request_index
260
+ current_request_index = -1
261
+ data_to_save = {
262
+ "description": description,
263
+ "advantages": advantages,
264
+ "key_message": key_message,
265
+ "approach": approach,
266
+ "personalization_params": personalization_params,
267
+ "timestamp": time.time()
268
+ }
269
+ file_content_encoded = base64.b64encode(json.dumps(data_to_save).encode()).decode()
270
+ path = f"user_request_{int(time.time())}.json"
271
+ url = f"https://api.github.com/repos/{repo}/contents/{path}"
272
+ headers = {
273
+ "Authorization": f"token {token}",
274
+ "Content-Type": "application/json"
275
+ }
276
+ data = {
277
+ "message": f"Добавлен новый файл {path}",
278
+ "content": file_content_encoded
279
+ }
280
+ response = requests.put(url, headers=headers, data=json.dumps(data))
281
+ if response.status_code == 201:
282
+ print("Данные успешно сохранены на GitHub")
283
+ else:
284
+ print(f"Ошибка при сохранении данных на GitHub: {response.status_code} {response.text}")
285
+
286
+ def load_previous_user_request_from_github():
287
+ global current_request_index
288
+ url = f"https://api.github.com/repos/{repo}/contents"
289
+ headers = {
290
+ "Authorization": f"token {token}",
291
+ "Content-Type": "application/json"
292
+ }
293
+ response = requests.get(url, headers=headers)
294
+ if response.status_code == 200:
295
+ files = response.json()
296
+ json_files = [file for file in files if file['name'].startswith("user_request_")]
297
+ if not json_files:
298
+ print("Нет сохраненных запросов.")
299
+ return "", "", "", "", None, None, None, None, None, None
300
+ current_request_index -= 1
301
+ if abs(current_request_index) > len(json_files):
302
+ current_request_index = -len(json_files)
303
+ target_file = json_files[current_request_index]
304
+ file_url = target_file['download_url']
305
+ file_response = requests.get(file_url)
306
+ if file_response.status_code == 200:
307
+ data = json.loads(file_response.text)
308
+ description = data.get('description', "")
309
+ advantages = data.get('advantages', "")
310
+ key_message = data.get('key_message', "")
311
+ approach = data.get('approach', "")
312
+ personalization_params = data.get('personalization_params', [None]*6)
313
+ if len(personalization_params) < 6:
314
+ personalization_params += [None]*(6-len(personalization_params))
315
+ return description, advantages, key_message, approach, *personalization_params
316
+ else:
317
+ print(f"Ошибка при загрузке файла: {file_response.status_code}")
318
+ return "", "", "", "", None, None, None, None, None, None
319
+ else:
320
+ print(f"Ошибка при обращении к GitHub: {response.status_code}")
321
+ return "", "", "", "", None, None, None, None, None, None
322
+
323
+ def generate_final_prompt_from_display(prompt_text, single_approach, is_prompt_1=True):
324
+ prefix = approach_dict[single_approach]["prefix"]
325
+ suffix = approach_dict[single_approach]["suffix"]
326
+ prompt_text = re.sub(r"с учетом пробелов\. [^.\n]*\.", f"с учетом пробелов. {prefix}.", prompt_text)
327
+ prompt_text = prompt_text.replace(" / ", " ")
328
+ prompt_text = re.sub(r"\n[^\n]*Убедись, что УМЕСТНО использовал КАЖДЫЙ необходимый термин.\n[^\n]*Убедись, что в SMS без.*\n[^\n]*Убедись, что в SMS есть следующая ключевая информация:",
329
+ f"\n{suffix}.\nУбедись, что УМЕСТНО использовал КАЖДЫЙ необходимый термин.\nУбедись, что в SMS без изменений, синонимов и перестановок слов используется наименование продукта:\nУбедись, что в SMS есть следующая ключевая ин��ормация:", prompt_text, flags=re.DOTALL)
330
+ return prompt_text
331
+
332
  def generate_personalized_sms(description, product_name, benefits, key_message,
333
  gender, generation, psychotype, business_stage, industry, opf,
334
  chosen_approach, prompt_1, prompt_2):
 
335
  if "Для формирования промпта выберите хотя бы один личный персональный параметр" in prompt_1 or chosen_approach == "Подход не найден для выбранных параметров.":
336
  gr.Warning("Задайте хотя бы один личный персональный параметр для определения подхода, чтобы был сформирован промпт")
337
  return "", ""
 
338
  approach_list = [a.strip() for a in chosen_approach.split(',') if a.strip()]
339
  if not approach_list:
340
  gr.Warning("Задайте хотя бы один личный персональный параметр для определения подхода, чтобы был сформирован промпт")
341
  return "", ""
 
342
  chosen_single_approach_1 = random.choice(approach_list) if len(approach_list) > 1 else approach_list[0]
343
  chosen_single_approach_2 = random.choice(approach_list) if len(approach_list) > 1 else approach_list[0]
344
+ final_prompt_1 = generate_final_prompt_from_display(prompt_1, chosen_single_approach_1, is_prompt_1=True)
345
+ final_prompt_2 = generate_final_prompt_from_display(prompt_2, chosen_single_approach_2, is_prompt_1=False)
346
+ sms_1 = generate_message_with_retry(final_prompt_1)
347
+ sms_2 = generate_message_with_retry(final_prompt_2)
348
+ personalization_params = [gender, generation, psychotype, business_stage, industry, opf]
349
+ save_user_request_to_github(description, benefits, key_message, chosen_approach, personalization_params)
 
 
 
 
 
350
  return sms_1, sms_2
351
 
352
  with gr.Blocks(theme="default") as demo:
 
359
  </div>
360
  """
361
  gr.HTML(progress_bar_html)
 
362
  with gr.Row():
363
  with gr.Column(scale=1):
364
  gr.Markdown("**Продукт**")
 
367
  product_name = gr.Textbox(label="Наименование продукта", lines=1, value="", interactive=True)
368
  benefits = gr.Textbox(label="Преимущества", lines=9, value="", interactive=True)
369
  key_message = gr.Textbox(label="Ключевое сообщение", lines=2, value="", interactive=True)
370
+ def on_product_change(selected, description, product_name, benefits, key_message,
371
+ gender, generation, psychotype, business_stage, industry, opf):
372
+ if selected == "Свой продукт":
373
+ new_desc = ""
374
+ new_pname = ""
375
+ new_ben = ""
376
+ new_kmsg = ""
377
+ else:
378
+ if selected and selected in data_products["Наименование продукта"].values:
379
+ product_row = data_products[data_products["Наименование продукта"] == selected].iloc[0]
380
+ new_desc = product_row.get("Описание предложения", "")
381
+ new_pname = product_row.get("Наименование продукта", "")
382
+ new_ben = product_row.get("Преимущества", "")
383
+ new_kmsg = product_row.get("Ключевое сообщение", "")
384
+ else:
385
+ new_desc = ""
386
+ new_pname = ""
387
+ new_ben = ""
388
+ new_kmsg = ""
389
+ chosen_approach_val, p1, p2 = update_prompts_on_params_change(new_desc, new_pname, new_ben, new_kmsg,
390
+ gender, generation, psychotype,
391
+ business_stage, industry, opf)
392
+ return (gr.update(value=new_desc, interactive=(selected=="Свой продукт")),
393
+ gr.update(value=new_pname, interactive=(selected=="Свой продукт")),
394
+ gr.update(value=new_ben, interactive=(selected=="Свой продукт")),
395
+ gr.update(value=new_kmsg, interactive=(selected=="Свой продукт")),
396
+ chosen_approach_val, p1, p2)
397
  with gr.Column(scale=1):
398
  gr.Markdown("**Клиент**")
399
  gender_dropdown = gr.Dropdown(label="Пол", choices=["Не выбрано"]+genders, value=None)
 
407
 
408
  with gr.Row():
409
  return_params_btn = gr.Button("Вернуть параметры предыдущего запроса")
410
+ set_unused_params_btn = gr.Button("Задать ранее невыставленные параметры (кнопка пока не работает)")
411
  create_personal_sms_btn = gr.Button("Создать персонализированное SMS")
412
 
413
  with gr.Row():
 
415
  model_1_name = gr.Textbox(label="Модель 1", value="Grok-2-1212", interactive=False)
416
  prompt_1 = gr.Textbox(label="Промпт 1", value="", interactive=False, lines=10)
417
  sms_1 = gr.Textbox(label="SMS 1", lines=3, value="", interactive=False)
 
418
  with gr.Column():
419
  model_2_name = gr.Textbox(label="Модель 2", value="Grok-2-1212", interactive=False)
420
  prompt_2 = gr.Textbox(label="Промпт 2", value="", interactive=False, lines=10)
421
  sms_2 = gr.Textbox(label="SMS 2", lines=3, value="", interactive=False)
 
422
  with gr.Row():
423
+ prefer_sms_1_btn = gr.Button("Я предпочитаю это SMS (кнопка пока не работает)")
424
+ prefer_sms_2_btn = gr.Button("Я предпочитаю это SMS (кнопка пока не работает)")
425
+ regen_btn = gr.Button("Перегенерировать SMS (не нравится ни одно из SMS) (кнопка пока не работает)")
 
 
426
  with gr.Row():
427
  comment_sms_1 = gr.Textbox(label="Комментарий к SMS 1", lines=2, value="")
428
  comment_sms_2 = gr.Textbox(label="Комментарий к SMS 2", lines=2, value="")
 
429
  with gr.Row():
430
  corrected_sms_1 = gr.Textbox(label="Откорректированное SMS 1", lines=3, value="")
431
  corrected_sms_2 = gr.Textbox(label="Откорректированное SMS 2", lines=3, value="")
 
432
  with gr.Row():
433
+ save_sms_1_btn = gr.Button("Сохранить в базу (кнопка пока не работает)")
434
+ save_sms_2_btn = gr.Button("Сохранить в базу (кнопка пока не работает)")
435
 
436
+ product_dropdown.change(
437
+ fn=on_product_change,
438
+ inputs=[product_dropdown, description, product_name, benefits, key_message,
439
+ gender_dropdown, generation_dropdown, psychotype_dropdown,
440
+ business_stage_dropdown, industry_dropdown, opf_dropdown],
441
+ outputs=[description, product_name, benefits, key_message,
442
+ chosen_approach, prompt_1, prompt_2]
443
+ )
444
+ client_params = [gender_dropdown, generation_dropdown, psychotype_dropdown,
445
+ business_stage_dropdown, industry_dropdown, opf_dropdown]
446
  for cp in client_params:
447
  cp.change(
448
  fn=update_prompts_on_params_change,
449
+ inputs=[description, product_name, benefits, key_message,
450
  gender_dropdown, generation_dropdown, psychotype_dropdown,
451
  business_stage_dropdown, industry_dropdown, opf_dropdown],
452
  outputs=[chosen_approach, prompt_1, prompt_2]
453
  )
 
 
454
  create_personal_sms_btn.click(
455
  fn=generate_personalized_sms,
456
  inputs=[description, product_name, benefits, key_message,
 
460
  outputs=[sms_1, sms_2]
461
  )
462
 
463
+ def on_load_previous():
464
+ loaded_data = load_previous_user_request_from_github()
465
+ if not loaded_data or len(loaded_data) < 10:
466
+ return ("", "", "", "", None, None, None, None, None, None, "", "", "")
467
+ description_val, advantages_val, key_message_val, approach_val = loaded_data[0], loaded_data[1], loaded_data[2], loaded_data[3]
468
+ gender_val, generation_val, psychotype_val, business_stage_val, industry_val, opf_val = loaded_data[4:10]
469
+ chosen_approach_val, p1, p2 = update_prompts_on_params_change(description_val, approach_val, advantages_val, key_message_val,
470
+ gender_val, generation_val, psychotype_val,
471
+ business_stage_val, industry_val, opf_val)
472
+ return (description_val, approach_val, advantages_val, key_message_val,
473
+ gender_val, generation_val, psychotype_val, business_stage_val, industry_val, opf_val,
474
+ chosen_approach_val, p1, p2)
475
+
476
+ return_params_btn.click(
477
+ fn=on_load_previous,
478
+ inputs=[],
479
+ outputs=[description, product_name, benefits, key_message,
480
+ gender_dropdown, generation_dropdown, psychotype_dropdown,
481
+ business_stage_dropdown, industry_dropdown, opf_dropdown,
482
+ chosen_approach, prompt_1, prompt_2]
483
+ )
484
+
485
  demo.queue().launch()