import gradio as gr import pandas as pd import os import random import re import pymorphy3 import requests import json import base64 import time from openai import OpenAI XAI_API_KEY = os.getenv("XAI_API_KEY") client = OpenAI( api_key=XAI_API_KEY, base_url="https://api.x.ai/v1", ) token = os.getenv('GITHUB_TOKEN') repo = "fruitpicker01/Storage_Anastasia" current_request_index = -1 def load_dropdown_data(file_path, sheet_name, column_name): data = pd.read_excel(file_path, sheet_name=sheet_name) return data[column_name].dropna().unique().tolist() file_path = "Исходные данные.xlsx" products_list, data_products = load_dropdown_data(file_path, "Продукты", "Наименование продукта"), pd.read_excel(file_path, sheet_name="Продукты") products = ["Свой продукт"] + list(products_list) genders_data = pd.read_excel(file_path, sheet_name="Пол") generations_data = pd.read_excel(file_path, sheet_name="Поколение") psychotypes_data = pd.read_excel(file_path, sheet_name="Психотип") business_stages_data = pd.read_excel(file_path, sheet_name="Стадия бизнеса") industries_data = pd.read_excel(file_path, sheet_name="Отрасль") opfs_data = pd.read_excel(file_path, sheet_name="ОПФ") genders = genders_data["Пол"].dropna().unique().tolist() generations = generations_data["Поколение"].dropna().unique().tolist() psychotypes = psychotypes_data["Психотип"].dropna().unique().tolist() business_stages = business_stages_data["Стадия бизнеса"].dropna().unique().tolist() industries = industries_data["Отрасль"].dropna().unique().tolist() opfs = opfs_data["ОПФ"].dropna().unique().tolist() approaches_data = pd.read_excel(file_path, sheet_name="Подход") approach_dict = { "Указание на пользу": { "prefix": "Начни SMS с указания на пользу продукта. Используй глагол в побудительном наклонении. Не начинай с вопроса", "suffix": "Убедись, что SMS начинается с указания на пользу продукта и использования глагола в побудительном наклонении и не начинается с вопроса" }, "Вопрос": { "prefix": "Начни сообщение с вопроса, который указывает на пользу продукта для клиента", "suffix": "Убедись, что готовый текст начинается с вопроса, который указывает на пользу продукта для клиента" }, "Призыв к действию": { "prefix": "Начни SMS с призыва к действию с продуктом. Не начинай с вопроса", "suffix": "Убедись, что готовый текст начинается с призыва к действию с продуктом и не начинается с вопроса" } } def fill_product_details(selected_product, data): if selected_product == "Свой продукт": return (gr.update(value="", interactive=True), gr.update(value="", interactive=True), gr.update(value="", interactive=True), gr.update(value="", interactive=True)) else: if selected_product and selected_product in data["Наименование продукта"].values: product_row = data[data["Наименование продукта"] == selected_product].iloc[0] return (gr.update(value=product_row.get("Описание предложения", ""), interactive=False), gr.update(value=product_row.get("Наименование продукта", ""), interactive=False), gr.update(value=product_row.get("Преимущества", ""), interactive=False), gr.update(value=product_row.get("Ключевое сообщение", ""), interactive=False)) else: return (gr.update(value="", interactive=False), gr.update(value="", interactive=False), gr.update(value="", interactive=False), gr.update(value="", interactive=False)) def get_approaches(gender, generation, psychotype, approaches_df): if approaches_df is None or approaches_df.empty: return "Подход не найден для выбранных параметров." filters = [] for param_name, param_value in [('Пол', gender), ('Поколение', generation), ('Психотип', psychotype)]: if not param_value or param_value == "Не выбрано": filters.append(approaches_df[param_name].isnull() | (approaches_df[param_name].fillna('') == '')) else: filters.append(approaches_df[param_name].fillna('') == param_value) combined_filter = filters[0] for f in filters[1:]: combined_filter &= f matching_rows = approaches_df[combined_filter] if matching_rows.empty: return "Подход не найден для выбранных параметров." approach_list = [] for approaches in matching_rows['Подход']: approach_names = [a.strip() for a in str(approaches).split(',')] approach_list.extend(approach_names) approach_list = list(set(approach_list)) return ', '.join(approach_list) def get_instructions_for_param(param_value, df, col): if not param_value or param_value == "Не выбрано": return None row = df[df[col] == param_value] if row.empty: return None instr1 = row.iloc[0].get("Инструкция 1", "") if not instr1.strip(): return None return instr1 def format_instruction_string(instr): terms = [t.strip() for t in instr.split(',') if t.strip()] return " или ".join(terms) if terms else "" def generate_display_prompts(description, product_name, benefits, key_message, chosen_approach, gender, generation, psychotype, business_stage, industry, opf): if chosen_approach == "Подход не найден для выбранных параметров.": return ("Для формирования промпта выберите хотя бы один личный персональный параметр для определения подхода", "Для формирования промпта выберите хотя бы один личный персональный параметр для определения подхода") approach_list = [a.strip() for a in chosen_approach.split(',') if a.strip()] prefix_parts = [] suffix_parts = [] for a in approach_list: if a in approach_dict: prefix_parts.append(approach_dict[a]["prefix"]) suffix_parts.append(approach_dict[a]["suffix"]) if len(prefix_parts) > 1: approach_prefix = " / ".join(prefix_parts) approach_suffix = " / ".join(suffix_parts) else: approach_prefix = prefix_parts[0] if prefix_parts else "" approach_suffix = suffix_parts[0] if suffix_parts else "" instructions_data = [ (gender, genders_data, "Пол"), (generation, generations_data, "Поколение"), (psychotype, psychotypes_data, "Психотип"), (business_stage, business_stages_data, "Стадия бизнеса"), (industry, industries_data, "Отрасль"), (opf, opfs_data, "ОПФ") ] chosen_params_instructions = [] for (param_value, df, col) in instructions_data: instr1 = get_instructions_for_param(param_value, df, col) if instr1: chosen_params_instructions.append(instr1) if not chosen_params_instructions: return ("Для формирования промпта выберите хотя бы один личный персональный параметр для определения подхода", "Для формирования промпта выберите хотя бы один личный персональный параметр для определения подхода") lines = [] for i, instr_line in enumerate(chosen_params_instructions, start=1): formatted_line = format_instruction_string(instr_line) lines.append(f"{i}. {formatted_line}.") mandatory_terms = "\n".join(lines) extra_line = "" if generation == "Z": extra_line = "Обратись в SMS на ты. " prompt_1 = f"""Напиши три или четыре предложения суммарной длиной от 160 до 250 знаков с учетом пробелов. {approach_prefix}. {extra_line}Напиши рекламное SMS для следующего продукта: «{description}». Не изменяй название продукта: «{product_name}». Преимущества: «{benefits}». ОБЯЗАТЕЛЬНО используй в SMS КАЖДЫЙ из следующих терминов, касающиеся клиента, которому направляется SMS: {mandatory_terms} Убедись, что написал не меньше трех и не больше четырех предложений суммарной длиной от 160 до 250 знаков с учетом пробелов. {approach_suffix}. Убедись, что УМЕСТНО использовал КАЖДЫЙ необходимый термин. Убедись, что в SMS без изменений, синонимов и перестановок слов используется наименование продукта: «{product_name}». Убедись, что в SMS есть следующая ключевая информация: «{key_message}».""" prompt_2 = f"""Напиши три или четыре предложения суммарной длиной от 160 до 250 знаков с учетом пробелов. {approach_prefix}. {extra_line}Напиши рекламное SMS для следующего продукта: «{description}». Не изменяй название продукта: «{product_name}». Преимущества: «{benefits}». Используй в SMS КАЖДЫЙ из следующих терминов, касающиеся клиента, которому направляется SMS: {mandatory_terms} Убедись, что написал не меньше трех и не больше четырех предложений суммарной длиной от 160 до 250 знаков с учетом пробелов. {approach_suffix}. Убедись, что УМЕСТНО использовал КАЖДЫЙ необходимый термин. Убедись, что в SMS без изменений, синонимов и перестановок слов используется наименование продукта: «{product_name}». Убедись, что в SMS есть следующая ключевая информация: «{key_message}».""" return prompt_1, prompt_2 def call_model(model_prompt): completion = client.chat.completions.create( model="grok-2-1212", messages=[ {"role": "system", "content": "You are a world-class expert in creating personalized SMS who returns only the SMS and nothing else."}, {"role": "user", "content": model_prompt}, ], ) return completion.choices[0].message.content.strip() def correct_dash_usage(text): return text def clean_message(message): if not message.endswith(('.', '!', '?')): last_period = max(message.rfind('.'), message.rfind('!'), message.rfind('?')) if last_period != -1: message = message[:last_period + 1] return message def tokenize_words(text): """ Разбивает текст на слова, игнорируя знаки препинания. """ return re.findall(r'\w+', text, re.UNICODE) def normalize(word): """ Возвращает начальную форму слова с помощью pymorphy3. Приводит к нижнему регистру для унификации. """ morph = pymorphy3.MorphAnalyzer() parsed = morph.parse(word) if parsed: return parsed[0].normal_form.lower() return word.lower() def find_word_matches(normalized_msg, normalized_prod): """ Находит индексы начала совпадений названия продукта в нормализованных словах. """ matches = [] prod_len = len(normalized_prod) for i in range(len(normalized_msg) - prod_len + 1): window = normalized_msg[i:i+prod_len] if window == normalized_prod: matches.append(i) return matches def get_word_positions(message): """ Возвращает список кортежей (слово, start_index, end_index) для каждого слова в сообщении. """ word_positions = [] for match in re.finditer(r'\w+', message): word = match.group(0) start = match.start() end = match.end() word_positions.append((word, start, end)) return word_positions def capitalize_sentences(text): """ Капитализирует первую букву каждого предложения в тексте. Предложения считаются разделенными точками, восклицательными или вопросительными знаками. """ # Разделяем текст на предложения sentence_endings = re.compile(r'([.!?])') parts = sentence_endings.split(text) # Объединяем разделенные части и капитализируем первые буквы sentences = [] for i in range(0, len(parts)-1, 2): sentence = parts[i].strip() punctuation = parts[i+1] if sentence: sentence = sentence[0].upper() + sentence[1:] sentences.append(sentence + punctuation) # Обработка возможного остатка текста без завершающего знака if len(parts) % 2 != 0 and parts[-1].strip(): last_sentence = parts[-1].strip() last_sentence = last_sentence[0].upper() + last_sentence[1:] sentences.append(last_sentence) # Объединяем обратно в текст return ' '.join(sentences) def process_message(message, product_name): """ Обрабатывает сообщение, заменяя название продукта. - Первое слово сохраняется в инфлектированной форме, как в сообщении. - Остальные слова заменяются на оригинальные слова из названия продукта, сохраняя их капитализацию. Возвращает обработанное сообщение. """ # Токенизация сообщения (без пунктуации) message_words = tokenize_words(message) normalized_message = [normalize(word) for word in message_words] # Токенизация названия продукта product_words_original = tokenize_words(product_name) # Оригинальные слова с капитализацией normalized_product = [normalize(word) for word in product_words_original] # Поиск совпадений matches = find_word_matches(normalized_message, normalized_product) if not matches: # Если совпадений нет, вернуть исходное сообщение с капитализацией предложений return capitalize_sentences(message) # Получаем позиции всех слов в сообщении word_positions = get_word_positions(message) # Обработка каждого совпадения # Для избежания смещения индексов при множественных заменах, обрабатываем с конца matches_sorted = sorted(matches, reverse=True) final_message = message for match in matches_sorted: # Индексы слов start_word_idx = match end_word_idx = match + len(product_words_original) - 1 # Проверка, чтобы индексы не выходили за пределы списка if end_word_idx >= len(word_positions): continue # Пропускаем некорректные совпадения # Получаем позиции слов start_char = word_positions[start_word_idx][1] end_char = word_positions[end_word_idx][2] # Проверяем, есть ли знаки препинания перед совпадением if start_char > 0 and final_message[start_char -1] in ['«', '»', '-', '–', '.', ',', '!', '?', ';', ':']: start_char -=1 # Включаем знак препинания в изменяемую часть # Проверяем, есть ли знаки препинания после совпадения if end_char < len(final_message) and final_message[end_char] in ['«', '»', '-', '–', '.', ',', '!', '?', ';', ':']: end_char +=1 # Включаем знак препинания в изменяемую часть # Извлечение изменяемой части matched_substring = final_message[start_char:end_char] # Извлечение неизменяемой части before = final_message[:start_char] after = final_message[end_char:] # Разделяем изменяемую часть на слова words = matched_substring.replace('«', '').replace('»', '').strip().split() if len(words) < len(product_words_original): # Несоответствие количества слов, пропускаем замену continue # Сохраняем первое слово как есть (инфлектированное) first_word = words[0] # Остальные слова берем из оригинального названия продукта replaced_words = [first_word] + product_words_original[1:] # Собираем обратно измененную часть processed = ' '.join(replaced_words) # Воссоединяем части сообщения final_message = before + processed + after # Удаляем лишние пробелы final_message = re.sub(r'\s+', ' ', final_message).strip() # Капитализируем предложения final_message = capitalize_sentences(final_message) return final_message def generate_message_with_retry(model_prompt, product_name): last_message = "" for _ in range(10): msg = call_model(model_prompt) msg = correct_dash_usage(msg) msg = clean_message(msg) msg = process_message(msg, product_name) length = len(msg) if 160 <= length <= 250: msg += f"\n\n------\nКоличество знаков: {length}" return msg last_message = msg length = len(last_message) last_message += f"\n\n------\nКоличество знаков: {length}" return last_message def update_prompts_on_params_change(description, product_name, benefits, key_message, gender, generation, psychotype, business_stage, industry, opf): chosen_approach = get_approaches(gender, generation, psychotype, approaches_data) prompt_1, prompt_2 = generate_display_prompts(description, product_name, benefits, key_message, chosen_approach, gender, generation, psychotype, business_stage, industry, opf) return chosen_approach, prompt_1, prompt_2 def save_user_request_to_github(selected_product, description, product_name, benefits, key_message, approach, personalization_params): global current_request_index current_request_index = -1 data_to_save = { "selected_product": selected_product, "description": description, "product_name": product_name, "benefits": benefits, "key_message": key_message, "approach": approach, "personalization_params": personalization_params, "timestamp": time.time() } file_content_encoded = base64.b64encode(json.dumps(data_to_save).encode()).decode() path = f"user_request_{int(time.time())}.json" url = f"https://api.github.com/repos/{repo}/contents/{path}" headers = { "Authorization": f"token {token}", "Content-Type": "application/json" } data = { "message": f"Добавлен новый файл {path}", "content": file_content_encoded } requests.put(url, headers=headers, data=json.dumps(data)) def load_previous_user_request_from_github(): global current_request_index url = f"https://api.github.com/repos/{repo}/contents" headers = { "Authorization": f"token {token}", "Content-Type": "application/json" } response = requests.get(url, headers=headers) if response.status_code == 200: files = response.json() json_files = [file for file in files if file['name'].startswith("user_request_")] if not json_files: return products[0], "", "", "", "", "", None, None, None, None, None, "", "", "", "", "", "" current_request_index -= 1 if abs(current_request_index) > len(json_files): current_request_index = -len(json_files) target_file = json_files[current_request_index] file_url = target_file['download_url'] file_response = requests.get(file_url) if file_response.status_code == 200: data = json.loads(file_response.text) selected_product = data.get('selected_product', products[0]) description = data.get('description', "") product_name = data.get('product_name', "") benefits = data.get('benefits', "") key_message = data.get('key_message', "") approach = data.get('approach', "") personalization_params = data.get('personalization_params', [None]*6) if len(personalization_params) < 6: personalization_params += [None]*(6-len(personalization_params)) return (selected_product, description, product_name, benefits, key_message, approach, *personalization_params) else: return products[0], "", "", "", "", "", None, None, None, None, None, "", "", "", "", "", "" else: return products[0], "", "", "", "", "", None, None, None, None, None, "", "", "", "", "", "" def generate_final_prompt_from_display(prompt_text, single_approach, is_prompt_1=True): chosen_prefix = approach_dict[single_approach]["prefix"] chosen_suffix = approach_dict[single_approach]["suffix"] for approach in approach_dict: if approach != single_approach: other_prefix = approach_dict[approach]["prefix"] other_suffix = approach_dict[approach]["suffix"] prompt_text = prompt_text.replace(other_prefix, "") prompt_text = prompt_text.replace(other_suffix, "") prompt_text = prompt_text.replace(" / ", " ") prompt_text = re.sub(r"\s{2,}", " ", prompt_text).strip() if chosen_prefix not in prompt_text: prompt_text = re.sub(r"с учетом пробелов\. [^.\n]*\.", f"с учетом пробелов. {chosen_prefix}.", prompt_text) if chosen_suffix not in prompt_text: prompt_text = re.sub(r"\n[^\n]*Убедись, что УМЕСТНО использовал КАЖДЫЙ необходимый термин.\n[^\n]*Убедись, что в SMS без.*\n[^\n]*Убедись, что в SMS есть следующая ключевая информация:", f"\n{chosen_suffix}.\nУбедись, что УМЕСТНО использовал КАЖДЫЙ необходимый термин.\nУбедись, что в SMS без изменений, синонимов и перестановок слов используется наименование продукта:\nУбедись, что в SMS есть следующая ключевая информация:", prompt_text, flags=re.DOTALL) prompt_text = re.sub(r"\s+([.,!?])", r"\1", prompt_text) return prompt_text final_prompt_1_state = gr.State("") final_prompt_2_state = gr.State("") def generate_personalized_sms_wrapper(selected_product, description, product_name, benefits, key_message, gender, generation, psychotype, business_stage, industry, opf, chosen_approach, prompt_1, prompt_2): if "Для формирования промпта выберите хотя бы один личный персональный параметр" in prompt_1 or chosen_approach == "Подход не найден для выбранных параметров.": gr.Warning("Задайте хотя бы один личный персональный параметр для определения подхода") return "", "", "", "" approach_list = [a.strip() for a in chosen_approach.split(',') if a.strip()] if not approach_list: gr.Warning("Задайте хотя бы один личный персональный параметр для определения подхода") return "", "", "", "" chosen_single_approach_1 = random.choice(approach_list) if len(approach_list) > 1 else approach_list[0] chosen_single_approach_2 = random.choice(approach_list) if len(approach_list) > 1 else approach_list[0] final_prompt_1 = generate_final_prompt_from_display(prompt_1, chosen_single_approach_1, is_prompt_1=True) final_prompt_2 = generate_final_prompt_from_display(prompt_2, chosen_single_approach_2, is_prompt_1=False) print("Final Prompt 1:", final_prompt_1) print("Final Prompt 2:", final_prompt_2) sms_1 = generate_message_with_retry(final_prompt_1, product_name) sms_2 = generate_message_with_retry(final_prompt_2, product_name) personalization_params = [gender, generation, psychotype, business_stage, industry, opf] save_user_request_to_github(selected_product, description, product_name, benefits, key_message, chosen_approach, personalization_params) return sms_1, sms_2, final_prompt_1, final_prompt_2 def on_regenerate( selected_product, description, product_name, benefits, key_message, gender, generation, psychotype, business_stage, industry, opf, chosen_approach, presence_in_db, model_1_name, prompt_1, final_prompt_1, sms_1, model_2_name, prompt_2, final_prompt_2, sms_2 ): """ Функция для кнопки «Перегенерировать SMS (не нравится ни одно из SMS)». 1) Перегенерирует sms_1, sms_2 с помощью final_prompt_1, final_prompt_2 и product_name. 2) Сохраняет все те же данные, что и on_prefer_sms_1/2, но с chosen_sms="none". 3) Возвращает новые sms_1, sms_2 для обновления интерфейса. """ # Перегенерируем SMS (аналогично regen_sms) if not final_prompt_1.strip() or not final_prompt_2.strip(): gr.Warning("Нечего перегенерировать, сначала создайте SMS.") return "", "" print("Regen Final Prompt 1:", final_prompt_1) print("Regen Final Prompt 2:", final_prompt_2) sms_1 = generate_message_with_retry(final_prompt_1, product_name) sms_2 = generate_message_with_retry(final_prompt_2, product_name) # Теперь сохраняем всё, как при «Я предпочитаю это SMS», # только chosen_sms="none" save_preferred_sms_to_github( selected_product, description, product_name, benefits, key_message, gender, generation, psychotype, business_stage, industry, opf, chosen_approach, presence_in_db, model_1_name, prompt_1, final_prompt_1, new_sms_1, model_2_name, prompt_2, final_prompt_2, new_sms_2, chosen_sms="none" # <-- признак, что ни одно SMS не выбрано ) return sms_1, sms_2 def on_load_previous(): loaded_data = load_previous_user_request_from_github() if not loaded_data or len(loaded_data) < 11: return (products[0], "", "", "", "", None, None, None, None, None, None, "", "", "", "", "", "") selected_product_val, description_val, product_name_val, benefits_val, key_message_val, approach_val = loaded_data[0], loaded_data[1], loaded_data[2], loaded_data[3], loaded_data[4], loaded_data[5] gender_val, generation_val, psychotype_val, business_stage_val, industry_val, opf_val = loaded_data[6:12] chosen_approach_val, p1, p2 = update_prompts_on_params_change(description_val, product_name_val, benefits_val, key_message_val, gender_val, generation_val, psychotype_val, business_stage_val, industry_val, opf_val) return (selected_product_val, description_val, product_name_val, benefits_val, key_message_val, gender_val, generation_val, psychotype_val, business_stage_val, industry_val, opf_val, chosen_approach_val, p1, p2, "", "", "") def save_preferred_sms_to_github( selected_product, description, product_name, benefits, key_message, gender, generation, psychotype, business_stage, industry, opf, chosen_approach, presence_in_db, model_1_name, prompt_1, final_prompt_1, sms_1, model_2_name, prompt_2, final_prompt_2, sms_2, chosen_sms ): """ Сохраняет выбранные поля в отдельный JSON-файл на GitHub, чтобы не смешивать с предыдущими действиями, сохраняем под другим названием. """ # Собираем все данные data_to_save = { "timestamp": time.time(), "product_dropdown": selected_product, "description": description, "product_name": product_name, "benefits": benefits, "key_message": key_message, "gender": gender, "generation": generation, "psychotype": psychotype, "business_stage": business_stage, "industry": industry, "opf": opf, "chosen_approach": chosen_approach, "comment": presence_in_db, "model_1_name": model_1_name, "prompt_1": prompt_1, "final_prompt_1": final_prompt_1, "sms_1": sms_1, "model_2_name": model_2_name, "prompt_2": prompt_2, "final_prompt_2": final_prompt_2, "sms_2": sms_2, "preferred_sms": chosen_sms # "sms_1" или "sms_2" } file_content_encoded = base64.b64encode(json.dumps(data_to_save).encode()).decode() filename = f"preferred_sms_{int(time.time())}.json" url = f"https://api.github.com/repos/{repo}/contents/{filename}" headers = { "Authorization": f"token {token}", "Content-Type": "application/json" } data = { "message": f"Добавлен файл {filename} со сведениями о предпочтённом SMS", "content": file_content_encoded } response = requests.put(url, headers=headers, data=json.dumps(data)) if response.status_code == 201: print(f"Файл {filename} успешно сохранен.") else: print(f"Ошибка при сохранении данных: {response.status_code}, {response.text}") def on_prefer_sms_1( selected_product, description, product_name, benefits, key_message, gender, generation, psychotype, business_stage, industry, opf, chosen_approach, presence_in_db, model_1_name, prompt_1, final_prompt_1, sms_1, model_2_name, prompt_2, final_prompt_2, sms_2 ): """ Вызывается при нажатии кнопки «Я предпочитаю это SMS» (для SMS 1). """ save_preferred_sms_to_github( selected_product, description, product_name, benefits, key_message, gender, generation, psychotype, business_stage, industry, opf, chosen_approach, presence_in_db, model_1_name, prompt_1, final_prompt_1, sms_1, model_2_name, prompt_2, final_prompt_2, sms_2, chosen_sms="sms_1" ) return "Предпочтение SMS 1 сохранено в GitHub" def on_prefer_sms_2( selected_product, description, product_name, benefits, key_message, gender, generation, psychotype, business_stage, industry, opf, chosen_approach, presence_in_db, model_1_name, prompt_1, final_prompt_1, sms_1, model_2_name, prompt_2, final_prompt_2, sms_2 ): """ Вызывается при нажатии кнопки «Я предпочитаю это SMS» (для SMS 2). """ save_preferred_sms_to_github( selected_product, description, product_name, benefits, key_message, gender, generation, psychotype, business_stage, industry, opf, chosen_approach, presence_in_db, model_1_name, prompt_1, final_prompt_1, sms_1, model_2_name, prompt_2, final_prompt_2, sms_2, chosen_sms="sms_2" ) return "Предпочтение SMS 2 сохранено в GitHub" with gr.Blocks(theme="default") as demo: gr.Markdown("**Процент созданных SMS по выбранному продукту**") progress_bar_html = """
""" gr.HTML(progress_bar_html) with gr.Row(): with gr.Column(scale=1): gr.Markdown("**Продукт**") product_dropdown = gr.Dropdown(label="Продукт", choices=products, value=products[0]) description = gr.Textbox(label="Описание предложения", lines=5, value="", interactive=True) product_name = gr.Textbox(label="Наименование продукта", lines=1, value="", interactive=True) benefits = gr.Textbox(label="Преимущества", lines=9, value="", interactive=True) key_message = gr.Textbox(label="Ключевое сообщение", lines=2, value="") def on_product_change(selected, description, product_name, benefits, key_message, gender, generation, psychotype, business_stage, industry, opf): if selected == "Свой продукт": new_desc = "" new_pname = "" new_ben = "" new_kmsg = "" else: if selected and selected in data_products["Наименование продукта"].values: product_row = data_products[data_products["Наименование продукта"] == selected].iloc[0] new_desc = product_row.get("Описание предложения", "") new_pname = product_row.get("Наименование продукта", "") new_ben = product_row.get("Преимущества", "") new_kmsg = product_row.get("Ключевое сообщение", "") else: new_desc = "" new_pname = "" new_ben = "" new_kmsg = "" chosen_approach_val, p1, p2 = update_prompts_on_params_change(new_desc, new_pname, new_ben, new_kmsg, gender, generation, psychotype, business_stage, industry, opf) return (gr.update(value=new_desc, interactive=(selected=="Свой продукт")), gr.update(value=new_pname, interactive=(selected=="Свой продукт")), gr.update(value=new_ben, interactive=(selected=="Свой продукт")), gr.update(value=new_kmsg, interactive=(selected=="Свой продукт")), chosen_approach_val, p1, p2, "", "", "", "", "", "") with gr.Column(scale=1): gr.Markdown("**Клиент**") gender_dropdown = gr.Dropdown(label="Пол", choices=["Не выбрано"]+genders, value=None) generation_dropdown = gr.Dropdown(label="Поколение", choices=["Не выбрано"]+generations, value=None) psychotype_dropdown = gr.Dropdown(label="Психотип", choices=["Не выбрано"]+psychotypes, value=None) business_stage_dropdown = gr.Dropdown(label="Стадия бизнеса", choices=["Не выбрано"]+business_stages, value=None) industry_dropdown = gr.Dropdown(label="Отрасль", choices=["Не выбрано"]+industries, value=None) opf_dropdown = gr.Dropdown(label="ОПФ", choices=["Не выбрано"]+opfs, value=None) chosen_approach = gr.Textbox(label="Выбранный подход", lines=1, value="", interactive=False) presence_in_db = gr.Textbox(label="Комментарий", lines=1, value="", interactive=False) with gr.Row(): return_params_btn = gr.Button("Вернуть параметры предыдущего запроса") set_unused_params_btn = gr.Button("Задать ранее невыставленные параметры (кнопка пока не работает)") create_personal_sms_btn = gr.Button("Создать персонализированное SMS") with gr.Row(): with gr.Column(): model_1_name = gr.Textbox(label="Модель 1", value="Grok-2-1212", interactive=False) prompt_1 = gr.Textbox(label="Промпт 1", value="", interactive=False, lines=10) sms_1 = gr.Textbox(label="SMS 1", lines=3, value="", interactive=False) with gr.Column(): model_2_name = gr.Textbox(label="Модель 2", value="Grok-2-1212", interactive=False) prompt_2 = gr.Textbox(label="Промпт 2", value="", interactive=False, lines=10) sms_2 = gr.Textbox(label="SMS 2", lines=3, value="", interactive=False) with gr.Row(): prefer_sms_1_btn = gr.Button("Я предпочитаю это SMS") prefer_sms_2_btn = gr.Button("Я предпочитаю это SMS") regen_btn = gr.Button("Перегенерировать SMS (не нравится ни одно из SMS)") with gr.Row(): comment_sms_1 = gr.Textbox(label="Комментарий к SMS 1", lines=2, value="") comment_sms_2 = gr.Textbox(label="Комментарий к SMS 2", lines=2, value="") with gr.Row(): corrected_sms_1 = gr.Textbox(label="Откорректированное SMS 1", lines=3, value="") corrected_sms_2 = gr.Textbox(label="Откорректированное SMS 2", lines=3, value="") with gr.Row(): save_sms_1_btn = gr.Button("Сохранить в базу (кнопка пока не работает)") save_sms_2_btn = gr.Button("Сохранить в базу (кнопка пока не работает)") final_prompt_1_state = gr.State("") final_prompt_2_state = gr.State("") product_dropdown.change( fn=on_product_change, inputs=[product_dropdown, description, product_name, benefits, key_message, gender_dropdown, generation_dropdown, psychotype_dropdown, business_stage_dropdown, industry_dropdown, opf_dropdown], outputs=[description, product_name, benefits, key_message, chosen_approach, prompt_1, prompt_2, sms_1, sms_2, comment_sms_1, comment_sms_2, corrected_sms_1, corrected_sms_2] ) def params_change_wrapper(description, product_name, benefits, key_message, gender, generation, psychotype, business_stage, industry, opf): chosen_approach_val, p1, p2 = update_prompts_on_params_change(description, product_name, benefits, key_message, gender, generation, psychotype, business_stage, industry, opf) return chosen_approach_val, p1, p2, "", "", "", "", "", "" client_params = [gender_dropdown, generation_dropdown, psychotype_dropdown, business_stage_dropdown, industry_dropdown, opf_dropdown] for cp in client_params: cp.change( fn=params_change_wrapper, inputs=[description, product_name, benefits, key_message, gender_dropdown, generation_dropdown, psychotype_dropdown, business_stage_dropdown, industry_dropdown, opf_dropdown], outputs=[chosen_approach, prompt_1, prompt_2, sms_1, sms_2, comment_sms_1, comment_sms_2, corrected_sms_1, corrected_sms_2] ) create_personal_sms_btn.click( fn=generate_personalized_sms_wrapper, inputs=[product_dropdown, description, product_name, benefits, key_message, gender_dropdown, generation_dropdown, psychotype_dropdown, business_stage_dropdown, industry_dropdown, opf_dropdown, chosen_approach, prompt_1, prompt_2], outputs=[sms_1, sms_2, final_prompt_1_state, final_prompt_2_state] ) regen_btn.click( fn=on_regenerate, inputs=[ product_dropdown, description, product_name, benefits, key_message, gender_dropdown, generation_dropdown, psychotype_dropdown, business_stage_dropdown, industry_dropdown, opf_dropdown, chosen_approach, presence_in_db, model_1_name, prompt_1, final_prompt_1_state, sms_1, model_2_name, prompt_2, final_prompt_2_state, sms_2 ], outputs=[sms_1, sms_2] ) return_params_btn.click( fn=on_load_previous, inputs=[], outputs=[product_dropdown, description, product_name, benefits, key_message, gender_dropdown, generation_dropdown, psychotype_dropdown, business_stage_dropdown, industry_dropdown, opf_dropdown, chosen_approach, prompt_1, prompt_2, sms_1, sms_2, comment_sms_1, comment_sms_2, corrected_sms_1, corrected_sms_2] ) prefer_sms_1_btn.click( fn=on_prefer_sms_1, inputs=[ product_dropdown, description, product_name, benefits, key_message, gender_dropdown, generation_dropdown, psychotype_dropdown, business_stage_dropdown, industry_dropdown, opf_dropdown, chosen_approach, presence_in_db, model_1_name, prompt_1, final_prompt_1_state, sms_1, model_2_name, prompt_2, final_prompt_2_state, sms_2 ], outputs=[] ) prefer_sms_2_btn.click( fn=on_prefer_sms_2, inputs=[ product_dropdown, description, product_name, benefits, key_message, gender_dropdown, generation_dropdown, psychotype_dropdown, business_stage_dropdown, industry_dropdown, opf_dropdown, chosen_approach, presence_in_db, model_1_name, prompt_1, final_prompt_1_state, sms_1, model_2_name, prompt_2, final_prompt_2_state, sms_2 ], outputs=[] ) demo.queue().launch()