fruitpicker01's picture
Update app.py
265bbe3 verified
import gradio as gr
import requests
import os
import json
import pandas as pd
import time
from langchain.schema import SystemMessage
from langchain_community.chat_models.gigachat import GigaChat
from openpyxl import load_workbook
from openpyxl.utils import get_column_letter
from openpyxl.styles import Alignment
import base64
from together import Together
import pymorphy3
import re
import string
import io
from datetime import datetime, timedelta
import plotly.express as px
from sklearn.feature_extraction.text import TfidfVectorizer
from sklearn.metrics.pairwise import cosine_similarity
from sentence_transformers import SentenceTransformer, util
import numpy as np
from mistralai import Mistral
#morph = pymorphy3.MorphAnalyzer()
morph = pymorphy3.MorphAnalyzer()
# Установка ключа API для OpenAI, GigaChat и Mistral
openai_api_key = os.getenv('GPT_KEY')
gc_key = os.getenv('GC_KEY')
token = os.getenv('GITHUB_TOKEN')
TOGETHER_API_KEY = os.getenv('TOGETHER_API_KEY')
MISTRAL_API_KEY = os.getenv('MISTRAL_API_KEY')
# Инициализация клиента для Together
client = Together(api_key=TOGETHER_API_KEY)
# Инициализация клиента для Mistral
client_mistral = Mistral(api_key=MISTRAL_API_KEY)
# Авторизация в сервисе GigaChat
chat_pro = GigaChat(credentials=gc_key, model='GigaChat-Pro', max_tokens=68, temperature=1.15, verify_ssl_certs=False)
chat_lite = GigaChat(credentials=gc_key, model='GigaChat', max_tokens=68, temperature=1.15, verify_ssl_certs=False)
chat_plus = GigaChat(credentials=gc_key, model='GigaChat-Plus', max_tokens=68, temperature=1.15, verify_ssl_certs=False)
# Загрузка данных из Excel-файла
try:
data = pd.read_excel('Признаки.xlsx', sheet_name=None)
except Exception as e:
print(f"Ошибка при загрузке Excel-файла: {e}")
data = {}
# Создание списка признаков и их значений
features = {}
for sheet_name, df in data.items():
try:
if sheet_name == "Пол Поколение Психотип":
# Создаем словарь, где ключи — это кортежи (Пол, Поколение, Психотип), а значения — инструкции
features[sheet_name] = df.set_index(['Пол', 'Поколение', 'Психотип'])['Инструкция'].to_dict()
else:
features[sheet_name] = df.set_index(df.columns[0]).to_dict()[df.columns[1]]
except Exception as e:
print(f"Ошибка при обработке данных листа {sheet_name}: {e}")
features[sheet_name] = {}
current_request_index = -1 # Изначально указывает на последний запрос
def download_current_message_database():
# Mapping of GitHub repositories and authors
repos = {
'Storage_1': 'Редакторы',
'Storage_Ira': 'Ира',
'Storage_Kate': 'Катя',
'Storage_Sveta': 'Света',
'Storage_Lera': 'Лера',
'Storage_Dasha': 'Даша',
}
# Base GitHub API URL
base_url = 'https://api.github.com/repos/fruitpicker01/{repo}/contents'
data_list = []
headers = {
"Authorization": f"token {token}",
"Content-Type": "application/json"
}
for repo_name, author in repos.items():
url = base_url.format(repo=repo_name)
response = requests.get(url, headers=headers)
if response.status_code == 200:
files = response.json()
# Filter files starting with 'file' and ending with '.json'
json_files = [file for file in files if file['name'].startswith("file") and file['name'].endswith('.json')]
for file_info in json_files:
file_name = file_info['name']
file_url = file_info['download_url']
# Extract timestamp from filename
try:
timestamp = file_name.split('_')[1].split('.')[0]
# Add 3 hours to the time
save_date = datetime.utcfromtimestamp(int(timestamp)) + timedelta(hours=3)
save_date = save_date.strftime('%Y-%m-%d %H:%M:%S')
except:
save_date = None # or set default value
# Download and decode file content
file_response = requests.get(file_url)
if file_response.status_code == 200:
data = json.loads(file_response.text)
normalized_data = pd.json_normalize(data)
normalized_data['Дата сохранения'] = save_date
normalized_data['Автор'] = author
data_list.append(normalized_data)
else:
print(f"Error downloading file {file_name} from repository {repo_name}: {file_response.status_code}")
else:
print(f"Error accessing repository {repo_name}: {response.status_code}")
if data_list:
df = pd.concat(data_list, ignore_index=True)
# Преобразуем 'Дата сохранения' в datetime и корректируем на +3 часа
df['Дата сохранения'] = pd.to_datetime(df['Дата сохранения'], format='%Y-%m-%d %H:%M:%S', errors='coerce')
# Удаляем дубликаты, игнорируя 'Дата сохранения'
columns_to_consider = df.columns.tolist()
columns_to_consider.remove('Дата сохранения')
df.drop_duplicates(subset=columns_to_consider, inplace=True)
# Сортируем по 'Дата сохранения' по убыванию
df.sort_values(by='Дата сохранения', ascending=False, inplace=True)
# *** Добавляем этот блок кода для удаления пустых строк ***
# Удаляем строки, где все три столбца одновременно пусты или содержат только пробелы
df = df[~(
df['Персонализированное сообщение'].fillna('').str.strip().eq('') &
df['Комментарий'].fillna('').str.strip().eq('') &
df['Откорректированное сообщение'].fillna('').str.strip().eq('')
)]
# Set column order
desired_columns = [
"Модель", "Автор", "Дата сохранения", "Персонализированное сообщение",
"Комментарий", "Откорректированное сообщение", "Описание предложения",
"Преимущества", "Ключевое сообщение", "Подход", "Пол", "Поколение",
"Психотип", "Стадия бизнеса", "Отрасль", "ОПФ",
"Неперсонализированный промпт", "Неперсонализированное сообщение",
"Персонализированный промпт"
]
# Ensure all specified columns are in the DataFrame
existing_columns = [col for col in desired_columns if col in df.columns]
df = df[existing_columns]
# Save Excel file in memory
output = io.BytesIO()
with pd.ExcelWriter(output, engine='openpyxl') as writer:
df.to_excel(writer, index=False)
# Get worksheet
workbook = writer.book
worksheet = writer.sheets['Sheet1']
# Adjust column widths and text wrapping
from openpyxl.styles import Alignment
# Columns to fit content width
columns_fit_content = ["Модель", "Автор", "Дата сохранения", "Пол", "Поколение", "Психотип", "Стадия бизнеса", "ОПФ"]
# Columns to set fixed width and wrap text
columns_wrap_text = ["Персонализированное сообщение", "Комментарий", "Откорректированное сообщение"]
for idx, col in enumerate(df.columns, 1):
column_letter = get_column_letter(idx)
if col in columns_fit_content:
max_length = 0
column = df[col].astype(str)
for cell_value in column:
if cell_value:
max_length = max(max_length, len(cell_value))
adjusted_width = (max_length + 2)
worksheet.column_dimensions[column_letter].width = adjusted_width
elif col in columns_wrap_text:
worksheet.column_dimensions[column_letter].width = 50 # Set fixed width
for cell in worksheet[column_letter]:
cell.alignment = Alignment(wrap_text=True)
else:
worksheet.column_dimensions[column_letter].width = 20 # Default width
output.seek(0) # Reset pointer
# Encode file content in base64 for uploading to GitHub
content = base64.b64encode(output.read()).decode('utf-8')
# Parameters for uploading file to GitHub
repo = "fruitpicker01/Storage_dev"
# Get current time and adjust by +3 hours
current_time = datetime.utcnow() + timedelta(hours=3)
filename = f"db_{current_time.strftime('%d.%m.%Y_%H.%M')}.xlsx"
path = filename # Use new filename
url = f"https://api.github.com/repos/{repo}/contents/{path}"
# Check if file already exists
get_response = requests.get(url, headers=headers)
if get_response.status_code == 200:
sha = get_response.json()['sha']
else:
sha = None
data = {
"message": f"Updated file {filename}",
"content": content,
}
if sha:
data["sha"] = sha # Needed for updating existing file
# Upload (or update) file on GitHub
put_response = requests.put(url, headers=headers, data=json.dumps(data))
if put_response.status_code in [200, 201]:
# Get download link
download_url = f"https://raw.githubusercontent.com/{repo}/main/{path}"
return download_url, df # Return file URL and DataFrame
else:
print(f"Error uploading file to GitHub: {put_response.status_code}, {put_response.text}")
return "Error uploading file to GitHub.", None
else:
return "No data to generate file.", None
def update_download_link():
result = download_current_message_database()
link, df = result if isinstance(result, tuple) else (result, None)
if isinstance(link, str) and link.startswith("http") and df is not None:
# Compute analytics
total_messages = len(df)
# Total messages without need for corrections
clean_df = df[
df['Персонализированное сообщение'].notna() & df['Персонализированное сообщение'].str.strip().ne('') &
((df['Комментарий'].isna()) | (df['Комментарий'].str.strip() == '')) &
((df['Откорректированное сообщение'].isna()) | (df['Откорректированное сообщение'].str.strip() == ''))
]
total_clean_messages = len(clean_df)
# Number of messages by model
model_counts = df['Модель'].value_counts()
# Number of messages without corrections by model
clean_model_counts = clean_df['Модель'].value_counts()
# Most active contributors
contributor_counts = df['Автор'].value_counts()
# Number of messages by date
df['Дата сохранения'] = pd.to_datetime(df['Дата сохранения'], errors='coerce')
date_counts = df['Дата сохранения'].dt.date.value_counts().sort_index()
# Вычисляем накопительное количество сообщений по моделям во времени
df['Дата сохранения'] = pd.to_datetime(df['Дата сохранения'], errors='coerce')
model_date_counts = df.groupby([df['Дата сохранения'].dt.date, 'Модель']).size().reset_index(name='counts')
model_date_pivot = model_date_counts.pivot(index='Дата сохранения', columns='Модель', values='counts').fillna(0)
model_date_pivot = model_date_pivot.sort_index()
model_cumulative = model_date_pivot.cumsum()
# После вычисления model_cumulative
# 1. Получаем накопительные итоги на последнюю дату
last_date_totals = model_cumulative.iloc[-1]
# 2. Сортируем модели по накопительным итогам
sorted_models = last_date_totals.sort_values(ascending=False).index.tolist()
# 3. Переупорядочиваем столбцы в model_cumulative
model_cumulative = model_cumulative[sorted_models]
# 4. Сбрасываем индекс и преобразуем DataFrame для построения графика
model_cumulative_reset = model_cumulative.reset_index()
model_cumulative_melted = model_cumulative_reset.melt(id_vars='Дата сохранения', var_name='Модель', value_name='Количество сообщений')
# Создаем график с указанием порядка категорий
cumulative_model_fig = px.line(
model_cumulative_melted,
x='Дата сохранения',
y='Количество сообщений',
color='Модель',
title='Накопительное количество сообщений по моделям',
category_orders={'Модель': sorted_models}
)
# Вычисляем накопительное количество сообщений без корректировок по моделям
clean_df['Дата сохранения'] = pd.to_datetime(clean_df['Дата сохранения'], errors='coerce')
# Группируем данные по дате и модели, считаем количество сообщений
clean_model_date_counts = clean_df.groupby([clean_df['Дата сохранения'].dt.date, 'Модель']).size().reset_index(name='counts')
# Поворачиваем таблицу так, чтобы модели были столбцами, а даты — строками
clean_model_date_pivot = clean_model_date_counts.pivot(index='Дата сохранения', columns='Модель', values='counts').fillna(0)
# Сортируем даты по возрастанию
clean_model_date_pivot = clean_model_date_pivot.sort_index()
# Вычисляем накопительную сумму по датам
clean_model_cumulative = clean_model_date_pivot.cumsum()
# После вычисления clean_model_cumulative
# 1. Получаем накопительные итоги на последнюю дату
last_date_clean_totals = clean_model_cumulative.iloc[-1]
# 2. Сортируем модели по накопительным итогам
sorted_clean_models = last_date_clean_totals.sort_values(ascending=False).index.tolist()
# 3. Переупорядочиваем столбцы в clean_model_cumulative
clean_model_cumulative = clean_model_cumulative[sorted_clean_models]
# 4. Сбрасываем индекс и преобразуем DataFrame для построения графика
clean_model_cumulative_reset = clean_model_cumulative.reset_index()
clean_model_cumulative_melted = clean_model_cumulative_reset.melt(id_vars='Дата сохранения', var_name='Модель', value_name='Количество сообщений без корректировок')
# Создаем график с указанием порядка категорий
cumulative_clean_model_fig = px.line(
clean_model_cumulative_melted,
x='Дата сохранения',
y='Количество сообщений без корректировок',
color='Модель',
title='Накопительное количество сообщений без корректировок по моделям',
category_orders={'Модель': sorted_clean_models}
)
# Вычисляем накопительное количество сообщений по авторам
df['Дата сохранения'] = pd.to_datetime(df['Дата сохранения'], errors='coerce')
# Группируем данные по дате и автору, считаем количество сообщений
author_date_counts = df.groupby([df['Дата сохранения'].dt.date, 'Автор']).size().reset_index(name='counts')
# Поворачиваем таблицу так, чтобы авторы были столбцами, а даты — строками
author_date_pivot = author_date_counts.pivot(index='Дата сохранения', columns='Автор', values='counts').fillna(0)
# Сортируем даты по возрастанию
author_date_pivot = author_date_pivot.sort_index()
# Вычисляем накопительную сумму по датам
author_cumulative = author_date_pivot.cumsum()
# После вычисления author_cumulative
# 1. Получаем накопительные итоги на последнюю дату
last_date_author_totals = author_cumulative.iloc[-1]
# 2. Сортируем авторов по накопительным итогам
sorted_authors = last_date_author_totals.sort_values(ascending=False).index.tolist()
# 3. Переупорядочиваем столбцы в author_cumulative
author_cumulative = author_cumulative[sorted_authors]
# 4. Сбрасываем индекс и преобразуем DataFrame для построения графика
author_cumulative_reset = author_cumulative.reset_index()
author_cumulative_melted = author_cumulative_reset.melt(id_vars='Дата сохранения', var_name='Автор', value_name='Количество сообщений')
# Создаем график с указанием порядка категорий
cumulative_author_fig = px.line(
author_cumulative_melted,
x='Дата сохранения',
y='Количество сообщений',
color='Автор',
title='Накопительное количество сообщений по авторам',
category_orders={'Автор': sorted_authors}
)
# Prepare display outputs
total_messages_display_value = f"**Общее количество сообщений:** {total_messages}"
total_clean_messages_display_value = f"**Общее количество сообщений без необходимости корректировок:** {total_clean_messages}"
# Create charts using plotly
model_pie_fig = px.pie(values=model_counts.values, names=model_counts.index, title='Все сообщения')
clean_model_pie_fig = px.pie(values=clean_model_counts.values, names=clean_model_counts.index, title='Сообщения без корректировок')
contributor_pie_fig = px.pie(values=contributor_counts.values, names=contributor_counts.index, title='Наиболее активные контрибьюторы')
date_message_fig = px.bar(x=date_counts.index, y=date_counts.values, labels={'x': 'Дата', 'y': 'Количество сообщений'}, title='Количество добавленных сообщений по датам')
# Сообщения без корректировок
messages_without_corrections = df[
(df['Персонализированное сообщение'].notna()) &
(df['Персонализированное сообщение'].str.strip() != '') &
((df['Комментарий'].isna()) | (df['Комментарий'].str.strip() == '')) &
((df['Откорректированное сообщение'].isna()) | (df['Откорректированное сообщение'].str.strip() == ''))
].copy()
messages_without_corrections['Сообщение'] = messages_without_corrections['Персонализированное сообщение']
# Откорректированные сообщения
corrected_messages = df[
(df['Откорректированное сообщение'].notna()) &
(df['Откорректированное сообщение'].str.strip() != '')
].copy()
corrected_messages['Сообщение'] = corrected_messages['Откорректированное сообщение']
# Объединяем сообщения
messages_df = pd.concat([messages_without_corrections, corrected_messages], ignore_index=True)
def remove_extra_text(message):
if pd.isnull(message):
return ''
# Удаляем строки вида "------\nКоличество знаков: число"
return re.sub(r'\n-{6,}\nКоличество знаков: \d+', '', message).strip()
# Применяем функцию к персонализированным и откорректированным сообщениям
messages_df['Сообщение'] = messages_df['Сообщение'].apply(remove_extra_text)
# Подсчитываем количество символов
messages_df['Количество символов'] = messages_df['Сообщение'].str.len()
mean_characters = messages_df['Количество символов'].mean()
median_characters = messages_df['Количество символов'].median()
# Подсчитываем количество предложений
messages_df['Количество предложений'] = messages_df['Сообщение'].apply(lambda x: len(re.findall(r'[.!?]+', x)))
# График распределения по количеству символов
character_counts = messages_df['Количество символов'].value_counts().sort_index()
char_count_fig = px.bar(
x=character_counts.index,
y=character_counts.values,
labels={'x': 'Количество символов', 'y': 'Количество сообщений'},
title='Распределение сообщений по количеству символов'
)
char_count_fig.add_vline(
x=mean_characters,
line_width=3,
line_dash="dash",
line_color="green",
annotation_text=f"Среднее: {mean_characters:.1f}"
)
# График распределения по количеству предложений
sentence_counts = messages_df['Количество предложений'].value_counts().sort_index()
sentence_count_fig = px.bar(
x=sentence_counts.index,
y=sentence_counts.values,
labels={'x': 'Количество предложений', 'y': 'Количество сообщений'},
title='Распределение сообщений по количеству предложений'
)
return (
f"[Скачать базу сообщений]({link})",
total_messages_display_value,
total_clean_messages_display_value,
model_pie_fig,
clean_model_pie_fig,
contributor_pie_fig,
date_message_fig,
cumulative_model_fig,
cumulative_clean_model_fig,
cumulative_author_fig,
char_count_fig,
sentence_count_fig
)
else:
return link, "", "", None, None, None, None
def correct_dash_usage(text):
morph = pymorphy3.MorphAnalyzer()
# Step 1: Replace any dash with long dash if surrounded by spaces
text = re.sub(r'\s[-–—]\s', ' — ', text)
# Step 2: Replace any dash with short dash if surrounded by numbers without spaces
text = re.sub(r'(?<=\d)[-–—](?=\d)', '–', text)
# Step 3: Replace any dash with hyphen if surrounded by letters or a combination of letters and digits
text = re.sub(r'(?<=[a-zA-Zа-яА-Я0-9])[-–—](?=[a-zA-Zа-яА-Я0-9])', '-', text)
# Step 4: Replace quotation marks "..." with «...»
text = re.sub(r'"([^\"]+)"', r'«\1»', text)
# Step 5: Remove single quotes
if text.count('"') == 1:
text = text.replace('"', '')
# Step 6: Remove outer quotes if the entire text is enclosed in quotes (straight or elided)
if (text.startswith('"') and text.endswith('"')) or (text.startswith('«') and text.endswith('»')):
text = text[1:-1].strip()
# Step 7: Replace 100k with 100 000
text = re.sub(r'(\d+)[kкКK]', r'\1 000', text, flags=re.IGNORECASE)
# Step 8: Remove first sentence if it contains greetings and is less than 5 words
greeting_patterns = [
r"привет\b", r"здравствуй", r"добрый\s(день|вечер|утро)",
r"дорогой\b", r"уважаемый\b", r"дорогая\b", r"уважаемая\b",
r"господин\b", r"госпожа\b", r"друг\b", r"коллега\b",
r"товарищ\b", r"приятель\b", r"подруга\b"
]
def is_greeting_sentence(sentence):
words = sentence.split()
if len(words) < 5: # Check if sentence is less than 5 words
for word in words:
parsed = morph.parse(word.lower())[0] # Parse the word to get its base form
for pattern in greeting_patterns:
if re.search(pattern, parsed.normal_form):
return True
return False
# Split text into sentences
sentences = re.split(r'(?<=[.!?])\s+', text)
# Check the first sentence for greetings and remove it if necessary
if sentences and is_greeting_sentence(sentences[0]):
sentences = sentences[1:]
# Join the sentences back
text = ' '.join(sentences)
def restore_yo(text):
morph = pymorphy3.MorphAnalyzer()
words = text.split()
restored_words = []
for word in words:
# Пропускать обработку, если слово полностью в верхнем регистре (аббревиатуры)
if word.isupper():
restored_words.append(word)
continue
# Пропускать обработку, если слово "все" (независимо от регистра)
if word.lower() == "все":
restored_words.append(word)
continue
# Обработка остальных слов
parsed = morph.parse(word)[0]
restored_word = parsed.word
# Сохраняем оригинальный регистр первой буквы
if word and word[0].isupper():
restored_word = restored_word.capitalize()
restored_words.append(restored_word)
return ' '.join(restored_words)
text = restore_yo(text)
# Step 9: Replace common abbreviations and acronyms (Ип -> ИП, Ооо -> ООО, Рф -> РФ)
text = re.sub(r'\bИп\b', 'ИП', text, flags=re.IGNORECASE)
text = re.sub(r'\bОоо\b', 'ООО', text, flags=re.IGNORECASE)
text = re.sub(r'\bРф\b', 'РФ', text, flags=re.IGNORECASE)
# Step 10: Replace specific words (пользуйтесь -> пользуйтесь, ею -> ей)
text = re.sub(r'\bпользовуйтесь\b', 'пользуйтесь', text, flags=re.IGNORECASE)
text = re.sub(r'\bею\b', 'ей', text, flags=re.IGNORECASE)
text = re.sub(r'\bповышьте\b', 'повысьте', text, flags=re.IGNORECASE)
text = re.sub(r'\bСбербизнес\b', 'СберБизнес', text, flags=re.IGNORECASE)
text = re.sub(r'\bСбербизнеса\b', 'СберБизнес', text, flags=re.IGNORECASE)
text = re.sub(r'\bСбербизнесе\b', 'СберБизнес', text, flags=re.IGNORECASE)
text = re.sub(r'\bСбербанк\b', 'СберБанк', text, flags=re.IGNORECASE)
text = re.sub(r'\bвашего ООО\b', 'вашей компании', text, flags=re.IGNORECASE)
text = re.sub(r'\b0₽\b', '0 р', text, flags=re.IGNORECASE)
text = re.sub(r'\b₽\b', 'р', text, flags=re.IGNORECASE)
# Step 11: Replace all forms of "рублей", "рубля", "руб." with "р"
# Используем два отдельных регулярных выражения для точности
# 1. Заменяем "руб." на "р", учитывая, что "руб." может быть перед символом "/" или другим несловесным символом
text = re.sub(r'\bруб\.(?=\W|$)', 'р', text, flags=re.IGNORECASE)
# 2. Заменяем "рубля" и "рублей" на "р"
text = re.sub(r'\bруб(?:ля|лей)\b', 'р', text, flags=re.IGNORECASE)
# Step 12: Replace thousands and millions with appropriate abbreviations
text = re.sub(r'(\d+)\s+тысяч(?:а|и)?(?:\s+рублей)?', r'\1 000 р', text, flags=re.IGNORECASE)
text = re.sub(r'(\d+)\s*тыс\.\s*руб\.', r'\1 000 р', text, flags=re.IGNORECASE)
text = re.sub(r'(\d+)\s*тыс\.\s*р\.', r'\1 000 р', text, flags=re.IGNORECASE)
text = re.sub(r'(\d+)\s*тыс\.\s*р', r'\1 000 р', text, flags=re.IGNORECASE)
# Replace millions with "млн"
text = re.sub(r'(\d+)\s+миллиона\b|\bмиллионов\b', r'\1 млн', text, flags=re.IGNORECASE)
text = re.sub(r'(\d+)\s*млн\s*руб\.', r'\1 млн р', text, flags=re.IGNORECASE)
# Ensure space formatting around currency abbreviations
text = re.sub(r'(\d+)\s*р\b', r'\1 р', text)
# Step 13: Remove sentences containing "никаких посещений" or "никаких визитов"
def remove_specific_sentences(text):
sentences = re.split(r'(?<=[.!?])\s+', text) # Разбиваем текст на предложения
filtered_sentences = [
sentence for sentence in sentences
if not re.search(r'\bникаких\s+(посещений|визитов)\b', sentence, flags=re.IGNORECASE)
]
return ' '.join(filtered_sentences)
# Шаг 14: Замена чисел вида "5 000 000 р" на "5 млн р"
text = re.sub(r'\b(\d+)\s+000\s+000\s*р\b', r'\1 млн р', text, flags=re.IGNORECASE)
text = remove_specific_sentences(text)
return text
def save_user_request_to_github(description, advantages, key_message, approach, personalization_params):
global current_request_index # Используем глобальную переменную
current_request_index = -1 # Сбрасываем позицию к последнему запросу
# Собираем все данные в один словарь
data_to_save = {
"description": description,
"advantages": advantages,
"key_message": key_message,
"approach": approach,
"personalization_params": personalization_params,
"timestamp": time.time()
}
# Преобразуем контент в JSON-строку и кодируем в base64
file_content_encoded = base64.b64encode(json.dumps(data_to_save).encode()).decode()
# Параметры для GitHub API
repo = "fruitpicker01/Storage_dev"
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
}
# Отправка POST-запроса на GitHub API для создания файла в репозитории
response = requests.put(url, headers=headers, data=json.dumps(data))
if response.status_code == 201:
print("Данные успешно сохранены на GitHub")
else:
print(f"Ошибка при сохранении данных на GitHub: {response.status_code} {response.text}")
def save_message_to_table(data):
# data is a dictionary containing the message and personalization parameters
repo = "fruitpicker01/Storage_dev"
file_path = "messages.csv" # Use 'messages.xlsx' if you prefer Excel
# Get the file from the repository
url = f"https://api.github.com/repos/{repo}/contents/{file_path}"
headers = {
"Authorization": f"token {token}",
"Content-Type": "application/json"
}
response = requests.get(url, headers=headers)
if response.status_code == 200:
# File exists, download and load it
content = response.json()
file_content = base64.b64decode(content['content'])
if file_path.endswith('.xlsx'):
df = pd.read_excel(io.BytesIO(file_content))
else:
df = pd.read_csv(io.StringIO(file_content.decode('utf-8')))
sha = content['sha'] # For updating the file later
elif response.status_code == 404:
# File does not exist, create an empty DataFrame
df = pd.DataFrame(columns=[
"Timestamp", "Персонализированное сообщение", "Откорректированное сообщение",
"Пол", "Поколение", "Психотип", "Стадия бизнеса", "Отрасль", "ОПФ"
])
sha = None # No sha since the file doesn't exist yet
else:
print(f"Error accessing the file: {response.status_code}")
return
# Append the new data using pd.concat
df = pd.concat([df, pd.DataFrame([data])], ignore_index=True)
# Convert the DataFrame back to a file
if file_path.endswith('.xlsx'):
with io.BytesIO() as output:
df.to_excel(output, index=False)
file_content_encoded = base64.b64encode(output.getvalue()).decode('utf-8')
else:
csv_string = df.to_csv(index=False)
file_content_encoded = base64.b64encode(csv_string.encode('utf-8')).decode('utf-8')
# Prepare the data for the API request
data = {
"message": "Update messages file",
"content": file_content_encoded,
"sha": sha # Include the sha if the file exists
}
# Send the PUT request to update the file
response = requests.put(url, headers=headers, data=json.dumps(data))
if response.status_code in [200, 201]:
print("Messages file updated successfully.")
else:
print(f"Error updating messages file: {response.status_code}")
def save_both(adapted_message, personalized_message, model_name, comment, corrected_message, description, advantages,
non_personalized_prompt, non_personalized_message, personalization_prompt, gender, generation, psychotype,
business_stage, industry, legal_form, key_message, approach):
# Вызываем функцию для сохранения в JSON-файл
save_to_github(adapted_message, personalized_message, model_name, comment, corrected_message, description,
advantages, non_personalized_prompt, non_personalized_message, personalization_prompt, gender,
generation, psychotype, business_stage, industry, legal_form, key_message, approach)
# Подготавливаем данные для сохранения в CSV/XLSX
data = {
"Timestamp": time.time(),
"Модель": model_name,
"Адаптированное сообщение": adapted_message,
"Персонализированное сообщение": personalized_message,
"Комментарий": comment,
"Откорректированное сообщение": corrected_message,
"Описание предложения": description,
"Преимущества": advantages,
"Ключевое сообщение": key_message,
"Подход": approach,
"Пол": gender,
"Поколение": generation,
"Психотип": psychotype,
"Стадия бизнеса": business_stage,
"Отрасль": industry,
"ОПФ": legal_form
}
# Вызываем функцию для сохранения в CSV/XLSX
save_message_to_table(data)
def load_previous_user_request_from_github():
global current_request_index # Используем глобальную переменную
repo = "fruitpicker01/Storage_dev"
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:
print("Нет сохраненных запросов.")
return "", "", "", "", "", "", "", "", "", "", None, 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)
description = data.get('description', "")
advantages = data.get('advantages', "")
key_message = data.get('key_message', "") # Load key message
approach = data.get('approach', "") # Load approach
personalization_params = data.get('personalization_params', [None] * 6) # Убедитесь, что размер списка соответствует количеству полей
# Возвращаем данные по отдельности для каждого компонента Gradio
return description, advantages, key_message, approach, *personalization_params
else:
print(f"Ошибка при загрузке файла: {file_response.status_code}")
return "", "", "", "", "", "", "", "", "", "", None, None, None, None, None, None
else:
print(f"Ошибка при обращении к GitHub: {response.status_code}")
return "", "", "", "", "", "", "", "", "", "", None, None, None, None, None, None
def get_reference_message(current_description, gender, generation, psychotype, business_stage, industry, legal_form):
import io
import numpy as np
from sentence_transformers import SentenceTransformer
from sklearn.metrics.pairwise import cosine_similarity
import base64
import pandas as pd
import requests
import re
# Fetching the data from the repository
repo = "fruitpicker01/Storage_dev"
file_path = "messages.csv"
url = f"https://api.github.com/repos/{repo}/contents/{file_path}"
headers = {
"Authorization": f"token {token}",
"Content-Type": "application/json"
}
response = requests.get(url, headers=headers)
if response.status_code == 200:
content = response.json()
file_content = base64.b64decode(content['content'])
df = pd.read_csv(io.StringIO(file_content.decode('utf-8')))
else:
print(f"Error accessing the file: {response.status_code}")
return None
# Cleaning up and filtering the DataFrame
for col in ["Пол", "Поколение", "Психотип", "Стадия бизнеса", "Отрасль", "ОПФ"]:
df[col] = df[col].astype(str).str.strip().str.lower()
params = {
"Пол": str(gender).strip().lower() if gender else None,
"Поколение": str(generation).strip().lower() if generation else None,
"Психотип": str(psychotype).strip().lower() if psychotype else None,
"Стадия бизнеса": str(business_stage).strip().lower() if business_stage else None,
"Отрасль": str(industry).strip().lower() if industry else None,
"ОПФ": str(legal_form).strip().lower() if legal_form else None
}
df = df[df["Комментарий"].isna() | (df["Комментарий"].str.strip() == '')]
filter_conditions = []
for col, value in params.items():
if value and value.lower() != 'none':
filter_conditions.append(df[col] == value)
if not filter_conditions:
print("Не заданы параметры персонализации.")
return None
filter_condition = filter_conditions[0]
for condition in filter_conditions[1:]:
filter_condition &= condition
filtered_df = df[filter_condition]
if filtered_df.empty:
print("Сообщения с заданными параметрами не найдены.")
return None
if 'Описание предложения' not in filtered_df.columns:
print("Описание предложения отсутствует в данных.")
return None
filtered_df['Описание предложения'] = filtered_df['Описание предложения'].fillna('')
# Using the model to generate embeddings
model = SentenceTransformer('sergeyzh/rubert-tiny-turbo')
descriptions = filtered_df['Описание предложения'].tolist()
descriptions.insert(0, current_description)
embeddings = model.encode(descriptions)
cosine_similarities = cosine_similarity([embeddings[0]], embeddings[1:]).flatten()
# Retrieve indices of top two most similar descriptions
top_two_indices = np.argsort(cosine_similarities)[-2:][::-1]
similar_rows = filtered_df.iloc[top_two_indices]
# Processing the messages
reference_messages = []
if 'Timestamp' not in similar_rows.columns:
print("Столбец 'Timestamp' отсутствует в данных.")
else:
similar_rows['Timestamp'] = pd.to_numeric(similar_rows['Timestamp'], errors='coerce')
similar_rows = similar_rows.sort_values(by='Timestamp', ascending=False)
for _, similar_row in similar_rows.iterrows():
if pd.notnull(similar_row.get("Откорректированное сообщение", None)) and similar_row["Откорректированное сообщение"].strip():
reference_message = similar_row["Откорректированное сообщение"]
else:
reference_message = similar_row.get("Персонализированное сообщение", "")
reference_message = re.sub(r'\n-{6,}\nКоличество знаков: \d+', '', reference_message).strip()
reference_messages.append(reference_message)
return reference_messages[:2] # Return the top two messages
def adapt_messages_to_best_example(
description,
personalized_gigachat_pro,
personalized_gigachat_lite,
personalized_gigachat_plus,
personalized_gpt4o,
personalized_meta_llama_405b,
key_message,
approach,
*selected_values
):
# Extract personalization parameters
gender = selected_values[0]
generation = selected_values[1]
psychotype = selected_values[2]
business_stage = selected_values[3]
industry = selected_values[4]
legal_form = selected_values[5]
# Get the two most similar reference messages
reference_messages = get_reference_message(description, gender, generation, psychotype, business_stage, industry, legal_form)
if not reference_messages or len(reference_messages) < 2:
# If reference messages are not found
adapted_message = "Эталонные сообщения не найдены для выбранных параметров персонализации."
yield adapted_message, adapted_message, adapted_message, adapted_message, adapted_message
else:
reference_message_1 = reference_messages[0]
reference_message_2 = reference_messages[1]
# Modify the prompt template to include two reference messages
prompt_template = (
"Сообщение для адаптации:\n\"{personalized_message}\"\n\n"
"Пример 1 (НЕ ИСПОЛЬЗУЙ ФАКТЫ ИЛИ ДАННЫЕ ИЗ ПРИМЕРА):\n\"{reference_message_1}\"\n\n"
"Пример 2 (НЕ ИСПОЛЬЗУЙ ФАКТЫ ИЛИ ДАННЫЕ ИЗ ПРИМЕРА):\n\"{reference_message_2}\"\n\n"
"1. Перепиши сообщение для адаптации, сохранив его смысл.\n"
"2. Используй стиль, построение предложений и лексику, максимально похожие на примеры.\n"
"3. НЕ ДОБАВЛЯЙ факты, цифры, или любую информацию из примеров.\n"
"4. Убедись, что итоговое сообщение содержит ТОЛЬКО информацию из сообщения для адаптации и адаптировано по стилю и структуре.\n"
"5. Проверь, что итоговое сообщение включает следующую информацию: \n\"{key_message}\""
)
# Initialize empty variables for the messages
adapted_gigachat_pro = ""
adapted_gigachat_lite = ""
adapted_gigachat_plus = ""
adapted_gpt4o = ""
adapted_meta_llama_405b = ""
# Adapt message for GigaChat-Pro
prompt = prompt_template.format(
reference_message_1=reference_message_1,
reference_message_2=reference_message_2,
key_message=key_message,
personalized_message=personalized_gigachat_pro
)
adapted_gigachat_pro = generate_message_gigachat_pro_with_retry(prompt)
adapted_gigachat_pro_length = len(adapted_gigachat_pro)
adapted_gigachat_pro_display = f"{adapted_gigachat_pro}\n\n------\nКоличество знаков: {adapted_gigachat_pro_length}"
yield adapted_gigachat_pro_display, "", "", "", ""
# Adapt message for GigaChat-Lite
prompt = prompt_template.format(
reference_message_1=reference_message_1,
reference_message_2=reference_message_2,
key_message=key_message,
personalized_message=personalized_gigachat_lite
)
adapted_gigachat_lite = generate_message_gigachat_lite_with_retry(prompt)
adapted_gigachat_lite_length = len(adapted_gigachat_lite)
adapted_gigachat_lite_display = f"{adapted_gigachat_lite}\n\n------\nКоличество знаков: {adapted_gigachat_lite_length}"
yield adapted_gigachat_pro_display, adapted_gigachat_lite_display, "", "", ""
# Adapt message for GigaChat-Plus
prompt = prompt_template.format(
reference_message_1=reference_message_1,
reference_message_2=reference_message_2,
key_message=key_message,
personalized_message=personalized_gigachat_plus
)
adapted_gigachat_plus = generate_message_gigachat_plus_with_retry(prompt)
adapted_gigachat_plus_length = len(adapted_gigachat_plus)
adapted_gigachat_plus_display = f"{adapted_gigachat_plus}\n\n------\nКоличество знаков: {adapted_gigachat_plus_length}"
yield adapted_gigachat_pro_display, adapted_gigachat_lite_display, adapted_gigachat_plus_display, "", ""
# Adapt message for GPT-4o
prompt = prompt_template.format(
reference_message_1=reference_message_1,
reference_message_2=reference_message_2,
key_message=key_message,
personalized_message=personalized_gpt4o
)
adapted_gpt4o = generate_message_gpt4o_with_retry(prompt)
adapted_gpt4o_length = len(adapted_gpt4o)
adapted_gpt4o_display = f"{adapted_gpt4o}\n\n------\nКоличество знаков: {adapted_gpt4o_length}"
yield adapted_gigachat_pro_display, adapted_gigachat_lite_display, adapted_gigachat_plus_display, adapted_gpt4o_display, ""
# Adapt message for Meta-Llama-3.1-405B
prompt = prompt_template.format(
reference_message_1=reference_message_1,
reference_message_2=reference_message_2,
key_message=key_message,
personalized_message=personalized_meta_llama_405b
)
adapted_meta_llama_405b = generate_message_meta_llama_3_1_405b_with_retry(prompt)
adapted_meta_llama_405b_length = len(adapted_meta_llama_405b)
adapted_meta_llama_405b_display = f"{adapted_meta_llama_405b}\n\n------\nКоличество знаков: {adapted_meta_llama_405b_length}"
yield adapted_gigachat_pro_display, adapted_gigachat_lite_display, adapted_gigachat_plus_display, adapted_gpt4o_display, adapted_meta_llama_405b_display
def update_best_example_prompt(description, *selected_values):
# Extract personalization parameters
gender = selected_values[0]
generation = selected_values[1]
psychotype = selected_values[2]
business_stage = selected_values[3]
industry = selected_values[4]
legal_form = selected_values[5]
# Retrieve two reference messages
reference_messages = get_reference_message(description, gender, generation, psychotype, business_stage, industry, legal_form)
if not reference_messages or len(reference_messages) < 2:
# No reference messages found
best_prompt = "Эталонные сообщения не найдены для выбранных параметров персонализации."
else:
reference_message_1 = reference_messages[0]
reference_message_2 = reference_messages[1]
# Update the prompt to include two reference messages
best_prompt = (
"Пример 1 (НЕ ИСПОЛЬЗУЙ ФАКТЫ ИЛИ ДАННЫЕ ИЗ ПРИМЕРА):\n\"{reference_message_1}\"\n\n"
"Пример 2 (НЕ ИСПОЛЬЗУЙ ФАКТЫ ИЛИ ДАННЫЕ ИЗ ПРИМЕРА):\n\"{reference_message_2}\"\n\n"
"1. Перепиши сообщение для адаптации, сохранив его смысл.\n"
"2. Используй стиль, построение предложений и лексику, максимально похожие на примеры.\n"
"3. НЕ ДОБАВЛЯЙ факты, цифры, или любую информацию из примеров.\n"
"4. Убедись, что итоговое сообщение содержит ТОЛЬКО информацию из сообщения для адаптации и адаптировано по стилю и структуре."
).format(reference_message_1=reference_message_1, reference_message_2=reference_message_2)
return best_prompt
def adapt_messages_and_perform_checks(
description_input,
personalized_gigachat_pro,
personalized_gigachat_lite,
personalized_gigachat_plus,
personalized_gpt4o,
personalized_meta_llama_405b,
key_message,
approach,
*selected_values
):
adaptation_generator = adapt_messages_to_best_example(
description_input,
personalized_gigachat_pro,
personalized_gigachat_lite,
personalized_gigachat_plus,
personalized_gpt4o,
personalized_meta_llama_405b,
key_message,
approach,
*selected_values
)
last_adaptation_result = None
for adaptation_result in adaptation_generator:
last_adaptation_result = adaptation_result
yield (
adaptation_result[0],
adaptation_result[1],
adaptation_result[2],
adaptation_result[3],
adaptation_result[4],
"", "", "", "", "" # Пустые строки для проверок
)
if last_adaptation_result:
# Выполнение проверок на адаптированных сообщениях
checks_gigachat_pro = perform_checks(last_adaptation_result[0], description, key_message)
checks_gigachat_lite = perform_checks(last_adaptation_result[1], description, key_message)
checks_gigachat_plus = perform_checks(last_adaptation_result[2], description, key_message)
checks_gpt4o = perform_checks(last_adaptation_result[3], description, key_message)
checks_meta_llama_405b = perform_checks(last_adaptation_result[4], description, key_message)
formatted_checks = [
format_checks(checks_gigachat_pro),
format_checks(checks_gigachat_lite),
format_checks(checks_gigachat_plus),
format_checks(checks_gpt4o),
format_checks(checks_meta_llama_405b)
]
yield (
last_adaptation_result[0],
last_adaptation_result[1],
last_adaptation_result[2],
last_adaptation_result[3],
last_adaptation_result[4],
formatted_checks[0],
formatted_checks[1],
formatted_checks[2],
formatted_checks[3],
formatted_checks[4]
)
# Функция для генерации стандартного промпта
def generate_standard_prompt(description, product_name, advantages, key_message, approach, *selected_values):
if approach == "Призыв к действию":
prompt = "Сгенерируй смс-сообщение для клиента. Начни сообщение с призыва к действию с продуктом.\n"
elif approach == "Указание на пользу":
prompt = "Сгенерируй смс-сообщение для клиента. Начни сообщение с указания на пользу продукта. Используй глагол в побудительном наклонении.\n"
elif approach == "Вопрос":
prompt = "Сгенерируй смс-сообщение для клиента. Начни сообщение с вопроса, который указывает на пользу продукта для клиента.\n"
elif approach == "None":
prompt = "Сгенерируй смс-сообщение для клиента.\n"
prompt += f"Не изменяй название продукта: {product_name}.\n"
prompt += (
f"Описание предложения: {description}\n"
f"Преимущества: {advantages}\n"
"В тексте смс запрещено использование:\n"
"- Запрещенные слова: № один, номер один, № 1, вкусный, дешёвый, продукт, спам, банкротство, долги, займ, срочно, лучший, главный, номер 1, гарантия, успех, лидер;\n"
"- Обращение к клиенту;\n"
"- Приветствие клиента;\n"
"- Обещания и гарантии;\n"
"- Использовать составные конструкции из двух глаголов;\n"
"- Причастия и причастные обороты;\n"
"- Деепричастия и деепричастные обороты;\n"
"- Превосходная степень прилагательных;\n"
"- Страдательный залог;\n"
"- Порядковые числительные от 10 прописью;\n"
"- Цепочки с придаточными предложениями;\n"
"- Разделительные повторяющиеся союзы;\n"
"- Вводные конструкции;\n"
"- Усилители;\n"
"- Паразиты времени;\n"
"- Несколько существительных подряд, в том числе отглагольных;\n"
"- Производные предлоги;\n"
"- Сложные предложения, в которых нет связи между частями;\n"
"- Сложноподчинённые предложения;\n"
"- Даты прописью;\n"
"- Близкие по смыслу однородные члены предложения;\n"
"- Шокирующие, экстравагантные, кликбейтные фразы;\n"
"- Абстрактные заявления без поддержки фактами и отсутствие доказательства пользы для клиента;\n"
"- Гарантирующие фразы;\n"
"- Узкоспециализированные термины;\n"
"- Фразы, способные создать двойственное ощущение, обидеть;\n"
"- Речевые клише, рекламные штампы, канцеляризмы;\n"
"Убедись, что в готовом тексте до 250 знаков с пробелами.\n"
)
if approach == "Призыв к действию":
prompt += "Убедись, что готовый текст начинается с призыва к действию с продуктом.\n"
elif approach == "Указание на пользу":
prompt += "Убедись, что готовый текст начинается с указания на пользу продукта и использования глагола в побудительном наклонении.\n"
elif approach == "Вопрос":
prompt += "Убедись, что готовый текст начинается с вопроса, который указывает на пользу продукта для клиента.\n"
elif approach == "None":
prompt += ""
prompt += f"Убедись, что в готовом тексте без изменений, синонимов и перестановок слов используется наименование продукта: {product_name}.\n"
if key_message.strip():
prompt += f"Убедись, что в готовом тексте есть следующая ключевая информация: {key_message.strip()}"
return prompt
# Функции для генерации сообщений
def generate_message_gpt4o(prompt):
try:
headers = {
"Content-Type": "application/json",
"Authorization": f"Bearer {openai_api_key}"
}
data = {
"model": "chatgpt-4o-latest",
"messages": [{"role": "system", "content": prompt}],
"max_tokens": 101,
"temperature": 1.1
}
response = requests.post("https://api.openai.com/v1/chat/completions", json=data, headers=headers)
response_data = response.json()
return response_data["choices"][0]["message"]["content"].strip()
except Exception as e:
return f"Ошибка при обращении к ChatGPT-4o-Latest: {e}"
def generate_message_gpt4o_mini(prompt):
try:
headers = {
"Content-Type": "application/json",
"Authorization": f"Bearer {openai_api_key}"
}
data = {
"model": "gpt-4o-mini",
"messages": [{"role": "system", "content": prompt}]
}
response = requests.post("https://api.openai.com/v1/chat/completions", json=data, headers=headers)
response_data = response.json()
return response_data["choices"][0]["message"]["content"].strip()
except Exception as e:
return f"Ошибка при обращении к GPT-4o-Mini: {e}"
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 generate_message_gigachat_pro(prompt):
try:
messages = [SystemMessage(content=prompt)]
res = chat_pro(messages)
cleaned_message = clean_message(res.content.strip())
return cleaned_message
except Exception as e:
return f"Ошибка при обращении к GigaChat-Pro: {e}"
def generate_message_gigachat_lite(prompt):
try:
time.sleep(2)
messages = [SystemMessage(content=prompt)]
res = chat_lite(messages)
cleaned_message = clean_message(res.content.strip())
return cleaned_message
except Exception as e:
return f"Ошибка при обращении к GigaChat-Lite: {e}"
def generate_message_gigachat_plus(prompt):
try:
time.sleep(2)
messages = [SystemMessage(content=prompt)]
res = chat_plus(messages)
cleaned_message = clean_message(res.content.strip())
return cleaned_message
except Exception as e:
return f"Ошибка при обращении к GigaChat-Plus: {e}"
def generate_message_meta_llama_3_1_405b(prompt):
try:
response = client.chat.completions.create(
model="meta-llama/Meta-Llama-3.1-405B-Instruct-Turbo",
messages=[{"role": "user", "content": prompt}],
max_tokens=74,
temperature=0.8
)
cleaned_message = clean_message(response.choices[0].message.content.strip())
return cleaned_message
except Exception as e:
return f"Ошибка при обращении к Meta-Llama-3.1-405B: {e}"
def generate_message_gpt4o_with_retry(prompt):
for _ in range(10): # Максимум 10 попыток
message = generate_message_gpt4o(prompt)
if len(message) <= 250:
return correct_dash_usage(message)
return message # Возвращаем последнее сгенерированное сообщение, если все попытки не удались
def generate_message_gigachat_pro_with_retry(prompt):
for _ in range(10):
message = generate_message_gigachat_pro(prompt)
if len(message) <= 250:
return correct_dash_usage(message)
return message
def generate_message_gigachat_lite_with_retry(prompt):
for _ in range(10):
message = generate_message_gigachat_lite(prompt)
if len(message) <= 250:
return correct_dash_usage(message)
return message
def generate_message_gigachat_plus_with_retry(prompt):
for _ in range(10):
message = generate_message_gigachat_plus(prompt)
if len(message) <= 250:
return correct_dash_usage(message)
return message
def generate_message_meta_llama_3_1_405b_with_retry(prompt):
for _ in range(10):
message = generate_message_meta_llama_3_1_405b(prompt)
if len(message) <= 250:
return correct_dash_usage(message)
return message
def generate_message_mistral(prompt, max_retries=5):
retries = 0
while retries < max_retries:
try:
chat_response = client_mistral.chat.complete(
model="open-mistral-nemo",
messages=[
{
"role": "user",
"content": prompt
},
],
max_tokens=3000, # Увеличено до 3000
temperature=0.2,
stop=["}"] # Останавливаем генерацию после закрывающей скобки
)
cleaned_message = chat_response.choices[0].message.content.strip()
return cleaned_message
except Exception as e:
if "Status 429" in str(e):
wait_time = 3 # Можно установить фиксированную задержку
print(f"Превышен лимит запросов. Ожидание {wait_time} секунд перед повторной попыткой...")
time.sleep(wait_time)
retries += 1
else:
print(f"Ошибка при обращении к Mistral: {e}")
return None
print("Ошибка: превышено количество попыток обращения к Mistral")
return None
def generate_messages(description, advantages, key_message, approach, *selected_values):
save_user_request_to_github(description, advantages, key_message, approach, selected_values)
standard_prompt = generate_standard_prompt(description, advantages, key_message, approach, *selected_values)
results = {
"prompt": standard_prompt,
"gigachat_pro": None,
"gigachat_lite": None,
"gigachat_plus": None,
"gpt4o": None,
"meta_llama_3_1_405b": None
}
yield results["prompt"], "", "", "", "", ""
# Generating messages using existing models (as before)
results["gigachat_pro"] = generate_message_gigachat_pro_with_retry(standard_prompt)
gigachat_pro_length = len(results["gigachat_pro"])
gigachat_pro_display = f"{results['gigachat_pro']}\n\n------\nКоличество знаков: {gigachat_pro_length}"
yield results["prompt"], gigachat_pro_display, "", "", "", ""
results["gigachat_lite"] = generate_message_gigachat_lite_with_retry(standard_prompt)
gigachat_lite_length = len(results["gigachat_lite"])
gigachat_lite_display = f"{results['gigachat_lite']}\n\n------\nКоличество знаков: {gigachat_lite_length}"
yield results["prompt"], gigachat_pro_display, gigachat_lite_display, "", "", ""
time.sleep(2)
results["gigachat_plus"] = generate_message_gigachat_plus_with_retry(standard_prompt)
gigachat_plus_length = len(results["gigachat_plus"])
gigachat_plus_display = f"{results['gigachat_plus']}\n\n------\nКоличество знаков: {gigachat_plus_length}"
yield results["prompt"], gigachat_pro_display, gigachat_lite_display, gigachat_plus_display, "", ""
time.sleep(2)
results["gpt4o"] = generate_message_gpt4o_with_retry(standard_prompt)
gpt4o_length = len(results["gpt4o"])
gpt4o_display = f"{results['gpt4o']}\n\n------\nКоличество знаков: {gpt4o_length}"
yield results["prompt"], gigachat_pro_display, gigachat_lite_display, gigachat_plus_display, gpt4o_display, ""
time.sleep(2)
results["meta_llama_3_1_405b"] = generate_message_meta_llama_3_1_405b_with_retry(standard_prompt)
meta_llama_405b_length = len(results["meta_llama_3_1_405b"])
meta_llama_405b_display = f"{results['meta_llama_3_1_405b']}\n\n------\nКоличество знаков: {meta_llama_405b_length}"
yield results["prompt"], gigachat_pro_display, gigachat_lite_display, gigachat_plus_display, gpt4o_display, meta_llama_405b_display
time.sleep(2)
return results
# Функция для генерации персонализированного промпта
def generate_personalization_prompt(product_name, key_message, approach, *selected_values):
prompt = f"Не изменяй название продукта: {product_name}.\n"
prompt += "Адаптируй, не превышая длину сообщения в 250 знаков с пробелами, текст с учетом следующих особенностей:\n"
gender, generation, psychotype = selected_values[0], selected_values[1], selected_values[2]
combined_instruction = ""
additional_instructions = ""
print(f"Выбранные значения: Пол={gender}, Поколение={generation}, Психотип={psychotype}")
# Проверяем, выбраны ли все три параметра: Пол, Поколение, Психотип
if gender and generation and psychotype:
# Получаем данные с листа "Пол Поколение Психотип"
sheet = features.get("Пол Поколение Психотип", {})
# Ищем ключ, соответствующий комбинации "Пол", "Поколение", "Психотип"
key = (gender, generation, psychotype)
if key in sheet:
combined_instruction = sheet[key]
print(f"Найдена комбинированная инструкция: {combined_instruction}")
else:
print(f"Комбинированная инструкция для ключа {key} не найдена.")
# Если не найдена комбинированная инструкция, добавляем индивидуальные инструкции
if not combined_instruction:
print("Добавляем индивидуальные инструкции для Пол, Поколение, Психотип.")
for i, feature in enumerate(["Пол", "Поколение", "Психотип"]):
if selected_values[i]:
try:
instruction = features[feature][selected_values[i]]
additional_instructions += f"{instruction}\n"
print(f"Добавлена инструкция из {feature}: {instruction}")
except KeyError:
return f"Ошибка: выбранное значение {selected_values[i]} не найдено в данных."
# Добавляем инструкции для остальных параметров (например, Отрасль)
for i, feature in enumerate(features.keys()):
if feature not in ["Пол", "Поколение", "Психотип", "Пол Поколение Психотип"]:
if i < len(selected_values) and selected_values[i]:
try:
instruction = features[feature][selected_values[i]]
additional_instructions += f"{instruction}\n"
print(f"Добавлена инструкция из {feature}: {instruction}")
except KeyError:
return f"Ошибка: выбранное значение {selected_values[i]} не найдено в данных."
# Формируем итоговый промпт
if combined_instruction:
prompt += combined_instruction # Добавляем комбинированную инструкцию, если она есть
if additional_instructions:
prompt += additional_instructions # Добавляем остальные инструкции
prompt += "Убедись, что в готовом тексте до 250 знаков с пробелами.\n"
if approach == "Призыв к действию":
prompt += "Убедись, что готовый текст начинается с призыва к действию с продуктом.\n"
elif approach == "Указание на пользу":
prompt += "Убедись, что готовый текст начинается с указания на пользу продукта и использования глагола в побудительном наклонении.\n"
elif approach == "Вопрос":
prompt += "Убедись, что готовый текст начинается с вопроса, который указывает на пользу продукта для клиента.\n"
elif approach == "None":
prompt += ""
prompt += f"Убедись, что в готовом тексте без изменений, синонимов и перестановок слов используется наименование продукта: {product_name}.\n"
prompt += f"Убедись, что в готовом тексте есть следующая ключевая информация: {key_message.strip()}"
if "призыва к действию" in prompt and "минимум прямых призывов к действию" in prompt:
prompt = re.sub(r"Убедись, что готовый текст начинается с призыва к действию с продуктом.\n", "", prompt)
return prompt.strip()
# Функция для выполнения персонализации на основе сгенерированного промпта и сообщения
def perform_personalization(standard_message, personalization_prompt):
full_prompt = f"{personalization_prompt}\n\nТекст для адаптации:\n{standard_message}"
return generate_message_gpt4o_with_retry(full_prompt)
# Также обновляем функции персонализации
def perform_personalization_gigachat(standard_message, personalization_prompt, model):
full_prompt = f"{personalization_prompt}\n\nТекст для адаптации:\n{standard_message}"
if model == "gigachat_pro":
result = generate_message_gigachat_pro_with_retry(full_prompt)
elif model == "gigachat_lite":
result = generate_message_gigachat_lite_with_retry(full_prompt)
elif model == "gigachat_plus":
result = generate_message_gigachat_plus_with_retry(full_prompt)
return clean_message(result)
def perform_personalization_meta_llama_405b(standard_message, personalization_prompt):
full_prompt = f"{personalization_prompt}\n\nТекст для адаптации:\n{standard_message}"
return generate_message_meta_llama_3_1_405b_with_retry(full_prompt)
# Updated function to include additional models in personalization
def personalize_messages_with_yield(
gigachat_pro_message,
gigachat_lite_message,
gigachat_plus_message,
gpt4o_message,
meta_llama_405b_message,
product_name,
key_message,
approach,
*selected_values
):
personalization_prompt = generate_personalization_prompt(product_name, key_message, approach, *selected_values)
yield personalization_prompt, "", "", "", "", ""
personalized_message_gigachat_pro = perform_personalization_gigachat(gigachat_pro_message, personalization_prompt, "gigachat_pro")
gigachat_pro_length = len(personalized_message_gigachat_pro)
gigachat_pro_display = f"{personalized_message_gigachat_pro}\n\n------\nКоличество знаков: {gigachat_pro_length}"
yield personalization_prompt, gigachat_pro_display, "", "", "", ""
personalized_message_gigachat_lite = perform_personalization_gigachat(gigachat_lite_message, personalization_prompt, "gigachat_lite")
gigachat_lite_length = len(personalized_message_gigachat_lite)
gigachat_lite_display = f"{personalized_message_gigachat_lite}\n\n------\nКоличество знаков: {gigachat_lite_length}"
yield personalization_prompt, gigachat_pro_display, gigachat_lite_display, "", "", ""
personalized_message_gigachat_plus = perform_personalization_gigachat(gigachat_plus_message, personalization_prompt, "gigachat_plus")
gigachat_plus_length = len(personalized_message_gigachat_plus)
gigachat_plus_display = f"{personalized_message_gigachat_plus}\n\n------\nКоличество знаков: {gigachat_plus_length}"
yield personalization_prompt, gigachat_pro_display, gigachat_lite_display, gigachat_plus_display, "", ""
personalized_message_gpt4o = perform_personalization(gpt4o_message, personalization_prompt)
gpt4o_length = len(personalized_message_gpt4o)
gpt4o_display = f"{personalized_message_gpt4o}\n\n------\nКоличество знаков: {gpt4o_length}"
yield personalization_prompt, gigachat_pro_display, gigachat_lite_display, gigachat_plus_display, gpt4o_display, ""
personalized_message_meta_llama_405b = perform_personalization_meta_llama_405b(meta_llama_405b_message, personalization_prompt)
meta_llama_405b_length = len(personalized_message_meta_llama_405b)
meta_llama_405b_display = f"{personalized_message_meta_llama_405b}\n\n------\nКоличество знаков: {meta_llama_405b_length}"
yield personalization_prompt, gigachat_pro_display, gigachat_lite_display, gigachat_plus_display, gpt4o_display, meta_llama_405b_display
# Добавьте проверки в personalize_messages_with_yield
is_valid_gigachat_pro = check_forbidden_words(personalized_message_gigachat_pro)
is_valid_gigachat_lite = check_forbidden_words(personalized_message_gigachat_lite)
is_valid_gigachat_plus = check_forbidden_words(personalized_message_gigachat_plus)
is_valid_gpt4o = check_forbidden_words(personalized_message_gpt4o)
is_valid_meta_llama_405b = check_forbidden_words(personalized_message_meta_llama_405b)
# Функция для генерации промпта проверки текста
def generate_error_check_prompt():
prompt = (
"Проверь текст SMS-сообщения на соответствие установленным правилам и ограничениям, касающимся его формирования. На основе выявленных несоответствий предоставь рекомендации по исправлению текста. "
"Особое внимание удели проверке: количества символов в тексте SMS-сообщения, орфографическим и пунктуационным ошибкам, определению частей речи (причастия, деепричастия, причастный оборот, деепричастный оборот). "
"Анализируй только текст SMS-сообщения, ничего не придумывай и не добавляй лишнего. "
"Правила и ограничения, которым должен соответствовать текст SMS-сообщения:\n"
"1. Количество символов в SMS-сообщении должно быть до 250 знаков с учетом пробелов.\n"
"2. В тексте должен быть призыв к действию с использованием глагола в повелительном наклонении (например: оформите, получите, разместите, размещайте, откройте, подключите, подайте заявку).\n"
"3. Должно соблюдаться соответствие фактов о продукте.\n"
"4. В генерациях смс запрещено использовать обещания и гарантии.\n"
"5. В генерациях смс запрещено использовать составные конструкции из двух глаголов.\n"
"6. В генерациях смс запрещено использовать причастия и причастные обороты.\n"
"7. В генерациях смс запрещено использовать деепричастия и деепричастные обороты.\n"
"8. В генерациях смс запрещено использовать превосходную степень прилагательных.\n"
"9. В генерациях смс запрещено использовать страдательный залог.\n"
"10. В генерациях смс запрещено использовать порядковые числительные от 10 прописью.\n"
"11. В генерациях смс запрещено использовать цепочки с придаточными предложениями.\n"
"12. В генерациях смс запрещено использовать разделительные повторяющиеся союзы.\n"
"13. В генерациях смс запрещено использовать вводные конструкции.\n"
"14. В генерациях смс запрещено использовать усилители.\n"
"15. В генерациях смс запрещено использовать паразиты времени.\n"
"16. В генерациях смс запрещено использовать несколько существительных подряд, в том числе отглагольных.\n"
"17. В генерациях смс запрещено использовать производные предлоги.\n"
"18. В генерациях смс запрещено использовать сложные предложения, в которых нет связи между частями.\n"
"19. В генерациях смс запрещено использовать сложноподчинённые предложения.\n"
"20. В генерациях смс запрещено использовать даты прописью.\n"
"21. В генерациях смс запрещено использовать близкие по смыслу однородные члены.\n"
"22. В генерациях смс запрещено использовать шокирующие, экстравагантные, кликбейтные фразы.\n"
"23. В генерациях смс запрещено использовать абстрактные заявления без поддержки фактами и отсутствие доказательства пользы для клиента.\n"
"24. В генерациях смс запрещено использовать гарантирующие фразы.\n"
"25. В генерациях смс запрещено использовать узкоспециализированные термины.\n"
"26. В генерациях смс запрещено использовать фразы, способные создать двойственное ощущение, обидеть.\n"
"27. В генерациях смс запрещено использовать речевые клише, рекламные штампы, канцеляризмы.\n"
"28. В генерациях смс запрещено использовать запрещенные слова: № один, номер один, № 1, вкусный, дешёвый, продукт, спам, банкротство, долги, займ, срочно, лучший, главный, номер 1, успех, лидер.\n"
"29. Сообщение должно быть написано без орфографических и грамматических ошибок.\n"
"30. Запрещены повторы слов.\n"
"31. В тексте должны использоваться правильные знаки препинания.\n"
"32. Если в тексте используются кавычки, они должны быть в форме «кавычки-ёлочки».\n"
"33. В тексте SMS сообщения должны обязательно присутствовать: название продукта, условия использования продукта / Преимущества продукта / Шаги для подключения или начала использования / Условия акции (если предложение по продукту акционное).\n"
"Форма ответа: [Ответ должен быть кратким, должен содержать только рекомендации по устранению найденных несоответствий, соответствия каждому пункту правил описывать категорически запрещено]."
)
return prompt
def save_to_github(adapted_message, personalized_message, model_name, comment, corrected_message, description, advantages, non_personalized_prompt, non_personalized_message, personalization_prompt, gender, generation, psychotype, business_stage, industry, legal_form, key_message, approach):
# Собираем все данные в один словарь
data_to_save = {
"Модель": model_name,
"Адаптированное сообщение": adapted_message,
"Персонализированное сообщение": personalized_message,
"Комментарий": comment,
"Откорректированное сообщение": corrected_message,
"Описание предложения": description,
"Преимущества": advantages,
"Ключевое сообщение": key_message,
"Подход": approach,
"Неперсонализированный промпт": non_personalized_prompt,
"Неперсонализированное сообщение": non_personalized_message,
"Персонализированный промпт": personalization_prompt,
"Пол": gender,
"Поколение": generation,
"Психотип": psychotype,
"Стадия бизнеса": business_stage,
"Отрасль": industry,
"ОПФ": legal_form
}
# Преобразуем контент в JSON-строку и кодируем в base64
file_content_encoded = base64.b64encode(json.dumps(data_to_save).encode()).decode()
# Параметры для GitHub API
repo = "fruitpicker01/Storage_dev"
path = f"file_{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
}
# Отправка POST-запроса на GitHub API для создания файла в репозитории
response = requests.put(url, headers=headers, data=json.dumps(data))
if response.status_code == 201:
print("Данные успешно сохранены на GitHub")
else:
print(f"Ошибка при сохранении данных на GitHub: {response.status_code} {response.text}")
def personalize_and_save(
gigachat_pro_message,
gigachat_lite_message,
gigachat_plus_message,
gpt4o_message,
meta_llama_405b_message,
description,
product_name,
advantages,
key_message,
approach,
*selected_values
):
# Персонализация с использованием yield для последовательного вывода
personalization_generator = personalize_messages_with_yield(
gigachat_pro_message,
gigachat_lite_message,
gigachat_plus_message,
gpt4o_message,
meta_llama_405b_message,
product_name,
key_message,
approach,
*selected_values
)
last_personalization_result = None
for personalization_result in personalization_generator:
last_personalization_result = personalization_result
yield (
personalization_result[0], # personalization_prompt
personalization_result[1], # gigachat_pro_message
personalization_result[2], # gigachat_lite_message
personalization_result[3], # gigachat_plus_message
personalization_result[4], # gpt4o_message
personalization_result[5], # meta_llama_405b_message
"", "", "", "", "" # Пустые строки для проверок
)
# После завершения персонализации, сохраняем результаты
if last_personalization_result:
checks_gigachat_pro = perform_checks(last_personalization_result[1], description, key_message)
checks_gigachat_lite = perform_checks(last_personalization_result[2], description, key_message)
checks_gigachat_plus = perform_checks(last_personalization_result[3], description, key_message)
checks_gpt4o = perform_checks(last_personalization_result[4], description, key_message)
checks_meta_llama_405b = perform_checks(last_personalization_result[5], description, key_message)
# Форматирование результатов проверок
formatted_checks = [
format_checks(checks_gigachat_pro),
format_checks(checks_gigachat_lite),
format_checks(checks_gigachat_plus),
format_checks(checks_gpt4o),
format_checks(checks_meta_llama_405b)
]
yield (
last_personalization_result[0], # personalization_prompt
last_personalization_result[1], # gigachat_pro_message
last_personalization_result[2], # gigachat_lite_message
last_personalization_result[3], # gigachat_plus_message
last_personalization_result[4], # gpt4o_message
last_personalization_result[5], # meta_llama_405b_message
formatted_checks[0], # validation_display_1
formatted_checks[1], # validation_display_2
formatted_checks[2], # validation_display_3
formatted_checks[3], # validation_display_4
formatted_checks[4] # validation_display_5
)
save_user_request_to_github(description, advantages, key_message, approach, selected_values)
def clear_outputs(*args):
return ('',) * len(args)
def prepare_button_text():
return gr.update(value="Сохраняется...", visible=True)
def update_button_text():
return gr.update(value="Сохранено!", visible=True)
def reset_button_text():
time.sleep(2) # Задержка в 2 секунды
return gr.update(value="Сохранить в базу", visible=True)
def regen_message_gpt4o(description, advantages, key_message, approach, *selected_values):
standard_prompt = generate_standard_prompt(description, advantages, key_message, approach, *selected_values)
gpt4o_message = generate_message_gpt4o_with_retry(standard_prompt)
gpt4o_length = len(gpt4o_message)
return f"{gpt4o_message}\n\n------\nКоличество знаков: {gpt4o_length}"
def regen_message_gigachat_pro(description, advantages, key_message, approach, *selected_values):
standard_prompt = generate_standard_prompt(description, advantages, key_message, approach, *selected_values)
gigachat_pro_message = generate_message_gigachat_pro_with_retry(standard_prompt)
gigachat_pro_length = len(gigachat_pro_message)
return f"{gigachat_pro_message}\n\n------\nКоличество знаков: {gigachat_pro_length}"
def regen_message_gigachat_lite(description, advantages, key_message, approach, *selected_values):
standard_prompt = generate_standard_prompt(description, advantages, key_message, approach, *selected_values)
gigachat_lite_message = generate_message_gigachat_lite_with_retry(standard_prompt)
gigachat_lite_length = len(gigachat_lite_message)
return f"{gigachat_lite_message}\n\n------\nКоличество знаков: {gigachat_lite_length}"
def regen_message_gigachat_plus(description, advantages, key_message, approach, *selected_values):
standard_prompt = generate_standard_prompt(description, advantages, key_message, approach, *selected_values)
gigachat_plus_message = generate_message_gigachat_plus_with_retry(standard_prompt)
gigachat_plus_length = len(gigachat_plus_message)
return f"{gigachat_plus_message}\n\n------\nКоличество знаков: {gigachat_plus_length}"
def regen_message_meta_llama_405b(description, advantages, key_message, approach, *selected_values):
standard_prompt = generate_standard_prompt(description, advantages, key_message, approach, *selected_values)
meta_llama_405b_message = generate_message_meta_llama_3_1_405b_with_retry(standard_prompt)
meta_llama_405b_length = len(meta_llama_405b_message)
return f"{meta_llama_405b_message}\n\n------\nКоличество знаков: {meta_llama_405b_length}"
def personalize_message_gigachat_pro(gigachat_pro_message, product_name, key_message, approach, *selected_values):
personalization_prompt = generate_personalization_prompt(product_name, key_message, approach, *selected_values)
personalized_message = perform_personalization_gigachat(gigachat_pro_message, personalization_prompt, "gigachat_pro")
gigachat_pro_length = len(personalized_message)
# Выполняем проверку сгенерированного сообщения
checks = perform_checks(personalized_message)
formatted_checks = format_checks(checks)
return f"{personalized_message}\n\n------\nКоличество знаков: {gigachat_pro_length}", formatted_checks
def personalize_message_gigachat_lite(gigachat_lite_message, product_name, key_message, approach, *selected_values):
personalization_prompt = generate_personalization_prompt(product_name, key_message, approach, *selected_values)
personalized_message = perform_personalization_gigachat(gigachat_lite_message, personalization_prompt, "gigachat_lite")
gigachat_lite_length = len(personalized_message)
# Выполняем проверку сгенерированного сообщения
checks = perform_checks(personalized_message)
formatted_checks = format_checks(checks)
return f"{personalized_message}\n\n------\nКоличество знаков: {gigachat_lite_length}", formatted_checks
def personalize_message_gigachat_plus(gigachat_plus_message, product_name, key_message, approach, *selected_values):
personalization_prompt = generate_personalization_prompt(product_name, key_message, approach, *selected_values)
personalized_message = perform_personalization_gigachat(gigachat_plus_message, personalization_prompt, "gigachat_plus")
gigachat_plus_length = len(personalized_message)
# Выполняем проверку сгенерированного сообщения
checks = perform_checks(personalized_message)
formatted_checks = format_checks(checks)
return f"{personalized_message}\n\n------\nКоличество знаков: {gigachat_plus_length}", formatted_checks
def personalize_message_gpt4o(gpt4o_message, product_name, key_message, approach, *selected_values):
personalization_prompt = generate_personalization_prompt(product_name, key_message, approach, *selected_values)
personalized_message = perform_personalization(gpt4o_message, personalization_prompt)
gpt4o_length = len(personalized_message)
# Выполняем проверку сгенерированного сообщения
checks = perform_checks(personalized_message)
formatted_checks = format_checks(checks)
return f"{personalized_message}\n\n------\nКоличество знаков: {gpt4o_length}", formatted_checks
def personalize_message_meta_llama_405b(meta_llama_405b_message, product_name, key_message, approach, *selected_values):
personalization_prompt = generate_personalization_prompt(product_name, key_message, approach, *selected_values)
personalized_message = perform_personalization_meta_llama_405b(meta_llama_405b_message, personalization_prompt)
meta_llama_405b_length = len(personalized_message)
# Выполняем проверку сгенерированного сообщения
checks = perform_checks(personalized_message)
formatted_checks = format_checks(checks)
return f"{personalized_message}\n\n------\nКоличество знаков: {meta_llama_405b_length}", formatted_checks
def generate_explanation_gigachat_pro(prompt):
messages = [SystemMessage(content=prompt)]
res = chat_pro_explain(messages)
return res.content.strip()
def generate_explanation_gigachat_lite(prompt):
messages = [SystemMessage(content=prompt)]
res = chat_lite_explain(messages)
return res.content.strip()
def generate_explanation_gigachat_plus(prompt):
messages = [SystemMessage(content=prompt)]
res = chat_plus_explain(messages)
return res.content.strip()
def generate_explanation_gpt4o(prompt):
try:
headers = {
"Content-Type": "application/json",
"Authorization": f"Bearer {openai_api_key}"
}
data = {
"model": "chatgpt-4o-latest",
"messages": [{"role": "system", "content": prompt}],
"temperature": 1.1
}
response = requests.post("https://api.openai.com/v1/chat/completions", json=data, headers=headers)
response_data = response.json()
return response_data["choices"][0]["message"]["content"].strip()
except Exception as e:
return f"Ошибка при обращении к ChatGPT-4o-Latest: {e}"
def generate_explanation_meta_llama_405b(prompt):
response = client.chat.completions.create(
model="meta-llama/Meta-Llama-3.1-405B-Instruct-Turbo",
messages=[{"role": "user", "content": prompt}],
temperature=0.8
)
return response.choices[0].message.content.strip()
def explain_compliance_gigachat_pro(personalized_message, personalization_prompt):
prompt = (
f"Есть инструкция по персонализации: {personalization_prompt}\n"
"Сообщи, учтены ли данные инструкции в тексте ниже, и укажи как они были учтены:\n"
f"Текст сообщения: {personalized_message}\n"
)
return generate_explanation_gigachat_pro(prompt)
def explain_compliance_gigachat_lite(personalized_message, personalization_prompt):
prompt = (
f"Есть инструкция по персонализации: {personalization_prompt}\n"
"Сообщи, учтены ли данные инструкции в тексте ниже, и укажи как они были учтены:\n"
f"Текст сообщения: {personalized_message}\n"
)
return generate_explanation_gigachat_lite(prompt)
def explain_compliance_gigachat_plus(personalized_message, personalization_prompt):
prompt = (
f"Есть инструкция по персонализации: {personalization_prompt}\n"
"Сообщи, учтены ли данные инструкции в тексте ниже, и укажи как они были учтены:\n"
f"Текст сообщения: {personalized_message}\n"
)
return generate_explanation_gigachat_plus(prompt)
def explain_compliance_gpt4o(personalized_message, personalization_prompt):
prompt = (
f"Есть инструкция по персонализации: {personalization_prompt}\n"
"Сообщи, учтены ли данные инструкции в тексте ниже, и укажи как они были учтены:\n"
f"Текст сообщения: {personalized_message}\n"
)
return generate_explanation_gpt4o(prompt)
def explain_compliance_meta_llama_405b(personalized_message, personalization_prompt):
prompt = (
f"Есть инструкция по персонализации: {personalization_prompt}\n"
"Сообщи, учтены ли данные инструкции в тексте ниже, и укажи как они были учтены:\n"
f"Текст сообщения: {personalized_message}\n"
)
return generate_explanation_meta_llama_405b(prompt)
def perform_analysis_with_yield(
gigachat_pro_message,
gigachat_lite_message,
gigachat_plus_message,
gpt4o_message,
meta_llama_405b_message,
personalization_prompt
):
# Start yielding results progressively
gigachat_pro_analysis = explain_compliance_gigachat_pro(gigachat_pro_message, personalization_prompt)
yield gigachat_pro_analysis, "", "", "", ""
gigachat_lite_analysis = explain_compliance_gigachat_lite(gigachat_lite_message, personalization_prompt)
yield gigachat_pro_analysis, gigachat_lite_analysis, "", "", ""
gigachat_plus_analysis = explain_compliance_gigachat_plus(gigachat_plus_message, personalization_prompt)
yield gigachat_pro_analysis, gigachat_lite_analysis, gigachat_plus_analysis, "", ""
gpt4o_analysis = explain_compliance_gpt4o(gpt4o_message, personalization_prompt)
yield gigachat_pro_analysis, gigachat_lite_analysis, gigachat_plus_analysis, gpt4o_analysis, ""
meta_llama_405b_analysis = explain_compliance_meta_llama_405b(meta_llama_405b_message, personalization_prompt)
yield gigachat_pro_analysis, gigachat_lite_analysis, gigachat_plus_analysis, gpt4o_analysis, meta_llama_405b_analysis
# ФУНКЦИИ ПРОВЕРОК (НАЧАЛО)
# 1. Запрещенные слова
def check_forbidden_words(message):
morph = pymorphy3.MorphAnalyzer()
# Перечень запрещённых слов и фраз
forbidden_patterns = [
r'№\s?1\b', r'номер\sодин\b', r'номер\s1\b',
r'вкусный', r'дешёвый', r'продукт',
r'спам', r'банкротство', r'долг[и]?', r'займ',
r'срочный', r'главный', r'зп', r'минималка',
r'гарантия', r'успех', r'лидер', r'никакой'
]
# Удаляем знаки препинания для корректного анализа
message_without_punctuation = message.translate(str.maketrans('', '', string.punctuation))
# Проверка на наличие подстроки "лучш" (без учета регистра)
if re.search(r'лучш', message_without_punctuation, re.IGNORECASE):
return False
# Лемматизация слов сообщения
words = message_without_punctuation.split()
lemmas = [morph.parse(word)[0].normal_form for word in words]
normalized_message = ' '.join(lemmas)
# Проверка на запрещённые фразы и леммы
for pattern in forbidden_patterns:
if re.search(pattern, normalized_message, re.IGNORECASE):
return False
return True
# 2 и #3. Обращение к клиенту и приветствие клиента
def check_no_greeting(message):
morph = pymorphy3.MorphAnalyzer()
# Список типичных обращений и приветствий
greeting_patterns = [
r"привет\b", r"здравствуй", r"добрый\s(день|вечер|утро)",
r"дорогой\b", r"уважаемый\b", r"дорогая\b", r"уважаемая\b",
r"господин\b", r"госпожа\b", r"друг\b", r"коллега\b",
r"товарищ\b", r"приятель\b", r"друг\b", r"подруга\b"
]
# Компилируем все шаблоны в один регулярное выражение
greeting_regex = re.compile('|'.join(greeting_patterns), re.IGNORECASE)
# Проверяем, начинается ли сообщение с шаблона приветствия или обращения
if greeting_regex.search(message.strip()):
return False
return True
# 4. Обещания и гарантии
def check_no_promises(message):
morph = pymorphy3.MorphAnalyzer()
promise_patterns = [
"обещать", "обещание", "гарантировать", "обязаться", "обязать", "обязательство", "обязательный"
]
words = message.split()
lemmas = [morph.parse(word)[0].normal_form for word in words]
for pattern in promise_patterns:
if pattern in lemmas:
return False
return True
# 5. Составные конструкции из двух глаголов
def check_no_double_verbs(message):
morph = pymorphy3.MorphAnalyzer()
# Разделяем текст по пробелам и знакам препинания
words = re.split(r'\s+|[.!?]', message)
morphs = [morph.parse(word)[0] for word in words]
for i in range(len(morphs) - 1):
# Проверяем, что оба слова являются глаголами (в любой форме, включая инфинитивы)
if (morphs[i].tag.POS in {'VERB', 'INFN'}) and (morphs[i+1].tag.POS in {'VERB', 'INFN'}):
# Проверяем, является ли первый глагол "хотеть" или "начинать"
if morphs[i].normal_form in ['хотеть', 'начинать', 'начать']:
return True
else:
return False
return True
# 6. Причастия и причастные обороты
def check_no_participles(message):
morph = pymorphy3.MorphAnalyzer()
words = message.split()
exceptions = {"повышенный", "увеличенный", "пониженный", "сниженный"}
for word in words:
parsed_word = morph.parse(word)[0]
lemma = parsed_word.normal_form
if 'PRTF' in parsed_word.tag and lemma not in exceptions:
return False
return True
# 7. Деепричастия и деепричастные обороты
def check_no_adverbial_participles(message):
morph = pymorphy3.MorphAnalyzer()
words = message.split()
morphs = [morph.parse(word)[0] for word in words]
for morph in morphs:
if 'GRND' in morph.tag:
return False
return True
# 8. Превосходная степень прилагательных
def check_no_superlative_adjectives(message):
morph = pymorphy3.MorphAnalyzer()
words = message.split()
morphs = [morph.parse(word)[0] for word in words]
for morph in morphs:
if 'COMP' in morph.tag or 'Supr' in morph.tag:
return False
return True
# 9. Страдательный залог
def check_no_passive_voice(message):
morph = pymorphy3.MorphAnalyzer()
words = message.split()
morphs = [morph.parse(word)[0] for word in words]
for morph in morphs:
if 'PRTF' in morph.tag and ('passive' in morph.tag or 'в' in morph.tag):
return False
return True
# 10. Порядковые числительные от 10 прописью
def check_no_written_out_ordinals(message):
morph = pymorphy3.MorphAnalyzer()
ordinal_words = [
"десятый", "одиннадцатый", "двенадцатый", "тринадцатый", "четырнадцатый", "пятнадцатый",
"шестнадцатый", "семнадцатый", "восемнадцатый", "девятнадцатый", "двадцатый"
]
words = message.split()
lemmas = [morph.parse(word)[0].normal_form for word in words]
for word in ordinal_words:
if word in lemmas:
return False
return True
# 11. Цепочки с придаточными предложениями
def check_no_subordinate_clauses_chain(message):
# Регулярное выражение, которое ищет последовательности придаточных предложений
subordinate_clause_patterns = [
r'\b(который|которая|которое|которые)\b',
r'\b(если|потому что|так как|что|когда)\b',
r'\b(хотя|несмотря на то что)\b'
]
count = 0
for pattern in subordinate_clause_patterns:
if re.search(pattern, message):
count += 1
# Если в предложении найдено более одного придаточного предложения подряд, возвращаем False
return count < 2
# 12. Разделительные повторяющиеся союзы
def check_no_repeating_conjunctions(message):
# Регулярное выражение для поиска разделительных повторяющихся союзов с запятой перед вторым союзом
repeating_conjunctions_patterns = r'\b(и|ни|то|не то|или|либо)\b\s*(.*?)\s*,\s*\b\1\b'
# Разделяем сообщение на предложения по точке, вопросительному и восклицательному знакам
sentences = re.split(r'[.!?]\s*', message)
# Проверяем каждое предложение отдельно
for sentence in sentences:
if re.search(repeating_conjunctions_patterns, sentence, re.IGNORECASE):
return False
return True
# 13. Вводные конструкции
def check_no_introductory_phrases(message):
introductory_phrases = [
r'\b(во-первых|во-вторых|с одной стороны|по сути|по правде говоря)\b',
r'\b(может быть|кстати|конечно|естественно|безусловно|возможно)\b'
]
for pattern in introductory_phrases:
if re.search(pattern, message, re.IGNORECASE):
return False
return True
# 14. Усилители
def check_no_amplifiers(message):
amplifiers = [
r'\b(очень|крайне|чрезвычайно|совсем|полностью|чисто)\b'
]
for pattern in amplifiers:
if re.search(pattern, message, re.IGNORECASE):
return False
return True
# 15. Паразиты времени
def check_no_time_parasites(message):
time_parasites = [
r'\b(немедленно|срочно|в данный момент)\b'
]
for pattern in time_parasites:
if re.search(pattern, message, re.IGNORECASE):
return False
return True
# 16. Несколько существительных подряд
def check_no_multiple_nouns(message):
noun_count = 0
words = re.split(r'\s+|[.!?]', message) # Разбиваем по пробелам и знакам препинания
morph = pymorphy3.MorphAnalyzer()
for word in words:
parsed_word = morph.parse(word)[0]
# Если слово — существительное
if 'NOUN' in parsed_word.tag:
noun_count += 1
# Если встречен конец предложения (точка, вопросительный знак, восклицательный знак)
elif re.match(r'[.!?]', word):
noun_count = 0
else:
noun_count = 0
if noun_count > 2:
return False
return True
# 17. Производные предлоги
def check_no_derived_prepositions(message):
derived_prepositions = [
r'\b(в течение|в ходе|вследствие|в связи с|по мере|при помощи|согласно|вопреки|на основании|на случай|в продолжение|по причине|вблизи|вдалеке|вокруг|внутри|вдоль|посередине|вне|снаружи|благодаря|невзирая на|исходя из)\b'
]
for pattern in derived_prepositions:
if re.search(pattern, message, re.IGNORECASE):
return False
return True
# 19. Сложноподчиненные предложения
def check_no_compound_sentences(message):
subordinating_conjunctions = [
r'\bкогда\b', r'\bкак только\b', r'\bпока\b', r'\bпосле того как\b',
r'\bпотому что\b', r'\bтак как\b', r'\bоттого что\b', r'\bблагодаря тому что\b',
r'\bчтобы\b', r'\bдля того чтобы\b', r'\bесли\b', r'\bкогда бы\b', r'\bесли бы\b',
r'\bхотя\b', r'\bнесмотря на то что\b', r'\bкак\b', r'\bбудто\b', r'\bсловно\b', r'\bкак будто\b'
]
# Убедимся, что слово "как" используется не в вопросе
for pattern in subordinating_conjunctions:
if re.search(pattern, message) and not re.search(r'\?', message):
return False
return True
# 20. Даты прописью
def check_no_dates_written_out(message):
# Ищем упоминания месяцев или слов, связанных с датами
months = [
"января", "февраля", "марта", "апреля", "мая", "июня",
"июля", "августа", "сентября", "октября", "ноября", "декабря"
]
# Слова для проверки чисел прописью
date_written_out_patterns = [
r'\b(первого|второго|третьего|четвертого|пятого|шестого|седьмого|восьмого|девятого|десятого|одиннадцатого|двенадцатого|тринадцатого|четырнадцатого|пятнадцатого|шестнадцатого|семнадцатого|восемнадцатого|девятнадцатого|двадцатого|двадцать первого|двадцать второго|двадцать третьего|двадцать четвертого|двадцать пятого|двадцать шестого|двадцать седьмого|двадцать восьмого|двадцать девятого|тридцатого|тридцать первого)\b'
]
for month in months:
for pattern in date_written_out_patterns:
if re.search(f'{pattern}\\s{month}', message, re.IGNORECASE):
return False
return True
# Доп правило. Повторы слов
def check_no_word_repetitions(message):
morph = pymorphy3.MorphAnalyzer()
# Список союзов и предлогов, которые мы будем игнорировать
ignore_words = set([
'и', 'а', 'но', 'или', 'да', 'ни', 'как', 'так',
'в', 'на', 'под', 'над', 'за', 'к', 'до', 'по', 'из', 'у', 'о', 'про', 'для',
'не', 'вот', 'это', 'тот', 'тем', 'при', 'чем',
'же', 'ли', 'бы', 'то',
])
# Разбиваем текст на слова, удаляя знаки препинания
words = re.findall(r'\b\w+\b', message.lower())
# Словарь для хранения нормализованных форм слов
normalized_words = {}
for word in words:
if word not in ignore_words:
# Получаем нормальную форму слова
normal_form = morph.parse(word)[0].normal_form
# Если слово уже встречалось, возвращаем False
if normal_form in normalized_words:
return False
# Добавляем слово в словарь
normalized_words[normal_form] = True
# Если мы дошли до этой точки, повторов не было
return True
# Проверки на LLM
import re
import json
def parse_json_response(response):
try:
# Попытка найти JSON-подобную структуру в ответе
match = re.search(r'\{.*', response)
if match:
json_str = match.group(0)
# Проверяем и добавляем недостающие кавычки и скобки
if json_str.count('"') % 2 != 0:
json_str += '"'
if json_str.count('{') > json_str.count('}'):
json_str += '}'
result = json.loads(json_str)
return result
# Если JSON не найден, пытаемся найти ключ-значение вручную
else:
decision_match = re.search(r'decision:\s*(true|false)', response)
explanation_match = re.search(r'explanation:\s*"(.+?)"', response)
result = {}
if decision_match:
decision_value = decision_match.group(1)
result['decision'] = True if decision_value == 'true' else False
if explanation_match:
result['explanation'] = explanation_match.group(1)
if result:
return result
else:
print("JSON не найден, и ключи 'decision' и 'explanation' не извлечены")
return None
except Exception as e:
print(f"Ошибка при разборе JSON: {e}")
return None
def cut_message(message):
# Удаляем любой дополнительный текст, например, "------\nКоличество знаков: ..."
# Разделяем сообщение по '------' и берем первую часть
if '------' in message:
message = message.split('------')[0].strip()
return message
# 22. Проверка сложных предложений без логической связи
def check_disconnected_sentences(message):
message_clean = cut_message(message)
print()
print()
print("СООБЩЕНИЕ:", message_clean)
print()
print("Проверка 22: Проверка сложных предложений без логической связи")
print()
prompt = f'''Проверь следующий текст на наличие сложных предложений, где отсутствует логическая связь между частями:
"{message_clean}"
Определи, есть ли в тексте предложения с несколькими частями, которые кажутся несвязанными, не поддерживают общую мысль или делают текст трудным для понимания.
Обрати внимание, что в контексте коротких рекламных сообщений допустимы краткие предложения, перечисления и фразы, которые вместе передают связную информацию о продукте или услуге. Не считай такие сообщения несвязанными, если их части логически связаны с предложением продукта или условиями его получения.
Пример ответа:
{{"decision": false, "explanation": "Текст понятен, и все предложения логически связаны между собой."}}
Если в тексте **есть** сложные предложения без логической связи между частями, **верни только** JSON {{"decision": true, "explanation": "<пояснение>"}};
если таких предложений **нет**, **верни только** JSON {{"decision": false, "explanation": "<пояснение>"}}.
**Не добавляй никакого дополнительного текста. Перед ответом убедись, что отвечаешь **только** в формате JSON с закрывающими кавычками и скобками.**'''
response = generate_message_gpt4o_mini(prompt)
time.sleep(3) # Задержка в 3 секунды между запросами
print("GPT-4o-mini response:", response) # Выводим полный ответ модели
result = parse_json_response(response)
if result is not None:
decision = result.get("decision", False)
explanation = result.get("explanation", "")
print("Explanation:", explanation)
return not decision # Инвертируем логику
else:
return None
# 23. Проверка на близкие по смыслу однородные члены
def check_synonymous_members(message):
print()
print("Проверка 23: Проверка на близкие по смыслу однородные члены")
print()
message_clean = cut_message(message)
prompt = f'''Проверь следующий текст на наличие однородных членов предложения, которые имеют одинаковый или практически одинаковый смысл и повторяют одну и ту же идею:
"{message_clean}"
Обрати внимание, что слова или выражения могут описывать разные аспекты продукта или услуги, и это не считается избыточным, если они не полностью дублируют значение друг друга. Например, такие слова как "премиальная" и "бизнес" могут описывать разные качества и не должны считаться синонимами.
Пример ответа:
{{"decision": true, "explanation": "В предложении используются синонимы 'быстрый' и 'скорый', которые повторяют одну и ту же идею."}}
Если такие слова или выражения есть, **верни только** JSON {{"decision": true, "explanation": "<пояснение>"}};
если таких слов или выражений нет, **верни только** JSON {{"decision": false, "explanation": "<пояснение>"}}.
**Не добавляй никакого дополнительного текста. Перед ответом убедись, что отвечаешь только в формате JSON с закрывающими кавычками и скобками.**'''
response = generate_message_gpt4o_mini(prompt)
time.sleep(3)
print("GPT-4o-mini response:", response)
result = parse_json_response(response)
if result is not None:
decision = result.get("decision", False)
explanation = result.get("explanation", "")
print("Explanation:", explanation)
return not decision # Инвертируем логику
else:
return None
# 24. Проверка на шокирующие, экстравагантные или кликбейтные фразы
def check_clickbait_phrases(message):
message_clean = cut_message(message)
print()
print("Проверка 24: Проверка на шокирующие, экстравагантные или кликбейтные фразы")
print()
prompt = f'''Проверь следующий текст на наличие шокирующих, экстравагантных или кликбейтных фраз:
"{message_clean}"
Инструкции:
1. Игнорируй фразы, которые основаны на фактической информации, даже если они выглядят сенсационно, такие как "лимит до миллиона" или "льготный период до 365 дней". Если эти данные подтверждаются и не являются преувеличением, их не следует считать кликбейтом.
2. Ищи фразы, которые явно преувеличивают или вводят в заблуждение, обещая нечто чрезмерно идеализированное или сенсационное, что не может быть доказано или подтверждено. Примеры кликбейтных фраз: "Шокирующая правда", "Вы не поверите, что произошло", "Это изменит вашу жизнь за один день".
3. Стандартные рекламные призывы к действию, такие как "купите сейчас" или "узнайте больше", не считаются кликбейтом, если они не преувеличивают преимущества или не используют явную манипуляцию эмоциями.
Пример ответа:
{{"decision": false, "explanation": "Текст нейтрален и не содержит кликбейтных фраз."}}
Если текст содержит кликбейтные фразы, **верни только** JSON {{"decision": true, "explanation": "<пояснение>"}};
если таких фраз нет, **верни только** JSON {{"decision": false, "explanation": "<пояснение>"}}.
**Не добавляй никакого дополнительного текста. Перед ответом убедись, что отвечаешь только в формате JSON с закрывающими кавычками и скобками.**'''
response = generate_message_gpt4o_mini(prompt)
time.sleep(3)
print("GPT-4o-mini response:", response)
result = parse_json_response(response)
if result is not None:
decision = result.get("decision", False)
explanation = result.get("explanation", "")
print("Explanation:", explanation)
return not decision # Инвертируем логику
else:
return None
# 25. Проверка на абстрактные заявления без поддержки фактами
def check_abstract_claims(message):
print()
print("Проверка 25: Проверка на абстрактные заявления без поддержки фактами")
print()
message_clean = cut_message(message)
prompt = f'''Проверь следующий текст на наличие чрезмерно абстрактных или неподкрепленных фактическими данными утверждений, которые могут усложнить понимание преимуществ продукта или услуги:
"{message_clean}"
Инструкции:
1. Исключи фразы, которые содержат конкретные числовые данные, обещания о времени выполнения или другие факты, которые могут быть проверены (например, "от 1 минуты", "24/7", "в течение 24 часов").
2. Не считай абстрактными фразами выражения, которые описывают конкретные выгодные условия, если они сопровождаются фактами или цифрами (например, "выгодные условия при покупке от 100 000 рублей" или "индивидуальные условия с процентной ставкой 3%").
3. Помечай абстрактными фразами любые утверждения, которые звучат эмоционально, но не сопровождаются конкретикой, такие как:
- "выгодное финансирование"
- "развивайте свой бизнес быстрее"
- "повышение эффективности"
- "эффективное управление"
- "надёжное решение"
- "оптимизируйте управление финансами"
- "выгодные условия для бизнеса"
- "лёгкие условия и кэшбэк"
- "мобильно, удобно, комфортно"
- "Ваш бизнес заслуживает лучшего!"
- "Подключите сейчас и оцените удобство!"
- "сэкономьте своё время"
- "быстро и бесплатно"
- "Удобство и комфорт для вас и ваших сотрудников!"
- "стал ещё удобнее"
- "Это удобно и экономит ваше время"
- "Это удобно и просто, особенно когда нужно быстро провести расчет"
- "Управляйте эффективно с «СберБизнес»!"
- "просто, быстро и удобно"
- "Всё просто"
- "Используй карту на полную мощь и контролируй расходы сотрудников"
- "Это позволит вам снизить затраты на обслуживание и оптимизировать бизнес-расходы"
- "в удобном для вас интернет-банке СберБизнес"
- "Условия просты и прозрачны"
4. Ищи эмоционально заряженные или мотивирующие фразы, которые не уточняют, как это достижимо, такие как:
- "эксклюзивные возможности"
- "новые возможности для твоего бизнеса"
- "Пора действовать!"
- "Откройте для себя комфорт классического Онлайна"
- "наслаждайтесь высокой ставкой"
- "Никаких минимальных сумм — ваш успех начинается здесь!"
- "Максимальная выгода и гибкие условия"
- "Присоединяйся к успеху уже сегодня!"
- "зарабатывай больше"
5. Ищи общие фразы, которые не дают представления о конкретной пользе, такие как "лучшее решение", "высокое качество", "отличный сервис", если они не сопровождаются пояснением о том, почему это так.
6. Учитывай, что в рекламных сообщениях допустимы эмоциональные и обобщённые фразы, если они достаточно конкретны для понимания аудитории, однако они должны сопровождаться фактами или подробными примерами.
Пример ответа:
{{"decision": false, "explanation": "Текст не содержит абстрактные утверждения без конкретики."}}
Если в тексте присутствуют абстрактные или неподкрепленные заявления, **верни только** JSON {{"decision": true, "explanation": "<пояснение>"}};
если таких утверждений нет, **верни только** JSON {{"decision": false, "explanation": "<пояснение>"}}.
**Не добавляй никакого дополнительного текста. Перед ответом убедись, что отвечаешь только в формате JSON с закрывающими кавычками и скобками.**'''
response = generate_message_gpt4o_mini(prompt)
time.sleep(3)
print("GPT-4o-mini response:", response)
result = parse_json_response(response)
if result is not None:
decision = result.get("decision", False)
explanation = result.get("explanation", "")
print("Explanation:", explanation)
return not decision # Инвертируем логическое значение
else:
return None
# 26. Проверка на узкоспециализированные термины
def check_specialized_terms(message):
print()
print("Проверка 26: Проверка на узкоспециализированные термины")
print()
message_clean = cut_message(message)
prompt = f'''Проверь следующий текст на наличие узкоспециализированных терминов или жаргона, которые могут быть непонятны широкой аудитории:
"{message_clean}"
Инструкции:
1. Игнорируй общеупотребительные термины, известные широкой аудитории, такие как "ИП", "ООО", "РФ", а также термины, связанные с обычными финансовыми продуктами (например, "кредитная карта", "интернет-банк", "Mastercard").
2. Ищи термины, характерные для узких профессиональных областей, таких как медицина, ИТ, право, инженерия и другие специализированные сферы.
3. Пример специализированных терминов: "интероперабельность", "кибернетика", "гипертензия", "аутентификация" и т.п.
Определи, содержит ли текст термины, которые известны только специалистам в определенной области и могут вызвать затруднения у обычных читателей.
Пример ответа:
{{"decision": false, "explanation": "В тексте отсутствуют узкоспециализированные термины."}}
Если в тексте есть такие узкоспециализированные термины, **верни только** JSON {{"decision": true, "explanation": "<пояснение>"}};
если таких терминов нет, **верни только** JSON {{"decision": false, "explanation": "<пояснение>"}}.
**Не добавляй никакого дополнительного текста. Перед ответом убедись, что отвечаешь только в формате JSON с закрывающими кавычками и скобками.**'''
response = generate_message_gpt4o_mini(prompt)
time.sleep(3)
print("GPT-4o-mini response:", response)
result = parse_json_response(response)
if result is not None:
decision = result.get("decision", False)
explanation = result.get("explanation", "")
print("Explanation:", explanation)
return not decision # Инвертируем логическое значение
else:
return None
# 27. Проверка на двусмысленные или обидные фразы
def check_offensive_phrases(message):
print()
print("Проверка 27: Проверка на двусмысленные или обидные фразы")
print()
message_clean = cut_message(message)
prompt = f'''Проверь следующий текст на наличие фраз, которые могут быть истолкованы двусмысленно или вызвать негативные эмоции у читателя:
"{message_clean}"
Определи, есть ли в тексте выражения, которые могут быть восприняты как оскорбительные, обидные или неуместные.
Обрати внимание, что фразы, используемые в обычном деловом контексте и не содержащие явных оскорблений, дискриминации или непристойностей, не считаются проблемными.
Например, фразы, объясняющие преимущества продукта, такие как "без отчётов и комиссий", являются допустимыми.
Пример ответа:
{{"decision": false, "explanation": "Текст не содержит обидных или двусмысленных фраз."}}
Если такие фразы есть, **верни только** JSON {{"decision": true, "explanation": "<пояснение>"}};
если таких фраз нет, **верни только** JSON {{"decision": false, "explanation": "<пояснение>"}}.
**Не добавляй никакого дополнительного текста. Перед ответом убедись, что отвечаешь только в формате JSON с закрывающими кавычками и скобками.**'''
response = generate_message_gpt4o_mini(prompt)
time.sleep(3)
print("GPT-4o-mini response:", response)
result = parse_json_response(response)
if result is not None:
decision = result.get("decision", False)
explanation = result.get("explanation", "")
print("Explanation:", explanation)
return not decision # Инвертируем логическое значение
else:
return None
# 28. Проверка на речевые клише, рекламные штампы и канцеляризмы
def check_cliches_and_bureaucratese(message):
print()
print("Проверка 28: Проверка на речевые клише, рекламные штампы и канцеляризмы")
print()
message_clean = cut_message(message)
prompt = f'''Проверь следующий текст на наличие речевых клише, излишне употребляемых фраз, рекламных штампов и канцеляризмов, которые делают текст менее выразительным и оригинальным:
"{message_clean}"
Обрати внимание **только** на избитые фразы, которые чрезмерно используются в рекламных текстах и не несут дополнительной ценности.
**Не считай клише или канцеляризмами следующие типы выражений:**
- Стандартные призывы к действию (например, "Получите", "Оформите", "Закажите сейчас"), но **не** их комбинации с общими, неопределёнными фразами, как например, "за считанные минуты", "быстро, удобно".
- Информацию о ценах, скидках, акциях или условиях покупки (например, "при покупках от 100 000 рублей в месяц").
- Описания способов оформления или получения услуг (например, "оформление возможно онлайн или в офисе").
- Стандартные отраслевые термины и фразы, необходимые для понимания сообщения (например, "премиальная бизнес-карта", "Mastercard Preferred"), но **не** их использование в комбинации с общими словами, как например, "идеальное решение для вашего бизнеса".
**Считай клише или канцеляризмами следующие типы выражений:**
- Избитые фразы, такие как:
- "Обеспечьте стабильность и развитие вашего бизнеса"
- "Заботьтесь о будущем семьи, сохраняя ресурсы."
- "Получите необходимые средства для развития бизнеса и обеспечения финансовой стабильности!"
- "Ваш успех — наша забота!"
- "Ваш рост — наша цель!"
- "Ваша финансовая стабильность и комфорт — наш приоритет."
- "Быстро и удобно развивайте свой бизнес"
- "Получите необходимые средства для развития бизнеса!"
- "Что может быть проще?"
- "Без лишней волокиты"
- "Быстро, удобно, без лишних хлопот!"
- "За считанные минуты"
- "Это идеальное предложение для вашего бизнеса!"
- "Удобное и надёжное решение для роста вашего капитала."
- "Первый шаг — уже за тобой!"
- "Не упустите свой шанс на развитие!"
- "Не упусти возможность!"
- "Не упусти свой шанс!"
- "Условия просты и прозрачны."
- "Спеши!"
Пример ответа:
{{"decision": false, "explanation": "Текст не содержит клише или канцеляризмов."}}
Если в тексте **нет** таких выражений, **верни только** JSON {{"decision": false, "explanation": "<пояснение>"}};
если в тексте **есть** такие выражения, **верни только** JSON {{"decision": true, "explanation": "<пояснение>"}}.
**Не добавляй никакого дополнительного текста. Перед ответом убедись, что отвечаешь только в формате JSON с закрывающими кавычками и скобками.**'''
response = generate_message_gpt4o_mini(prompt)
time.sleep(3)
print("GPT-4o-mini response:", response)
result = parse_json_response(response)
if result is not None:
decision = result.get("decision", False)
explanation = result.get("explanation", "")
print("Explanation:", explanation)
return not decision
else:
return None
# 29. Проверка на соответствие описанию предложения
def check_no_contradictions(message, description):
print()
print("Проверка 29: Проверка на отсутствие противоречий с описанием предложения")
print()
message_clean = cut_message(message)
prompt = f'''Проверь, не противоречит ли следующее сообщение описанию предложения.
Описание предложения:
"{description}"
Сообщение:
"{message_clean}"
Если сообщение не содержит фактов, которые отсутствуют в описании предложения, **верни только** JSON {{"decision": false, "explanation": "Противоречий не обнаружено."}}.
Если сообщение содержит факты, которые отсутствуют в описании предложения, **верни только** JSON {{"decision": true, "explanation": "<описание противоречий>"}}.
**Не добавляй никакого дополнительного текста. Отвечай только в формате JSON с закрывающими кавычками и скобками.**'''
response = generate_message_gpt4o_mini(prompt)
time.sleep(3)
print("GPT-4o-mini response:", response)
result = parse_json_response(response)
if result is not None:
decision = result.get("decision", False)
explanation = result.get("explanation", "")
print("Explanation:", explanation)
return not decision # Возвращаем True, если противоречий нет
else:
return None
# 30. Проверка на наличие ключевого сообщения
def check_contains_key_message(message, key_message):
print()
print("Проверка 30: Проверка на наличие ключевого сообщения")
print()
message_clean = cut_message(message)
prompt = f'''Проверь, содержит ли следующее сообщение ключевое сообщение.
Сообщение:
"{message_clean}"
Ключевой текст:
"{key_message}"
Если сообщение **содержит всю** информацию из ключевого текста, **верни только** JSON {{"decision": false, "explanation": "Ключевое текст присутствует."}}.
Если сообщение **не содержит всю** информацию из ключевого текста, **верни только** JSON {{"decision": true, "explanation": "Ключевое текст отсутствует."}}.
**Не добавляй никакого дополнительного текста. Отвечай только в формате JSON с закрывающими кавычками и скобками.**'''
response = generate_message_gpt4o_mini(prompt)
time.sleep(3)
print("GPT-4o-mini response:", response)
result = parse_json_response(response)
if result is not None:
decision = result.get("decision", False)
explanation = result.get("explanation", "")
print("Explanation:", explanation)
return not decision # Возвращаем True, если ключевое сообщение присутствует
else:
return None
# 31. Проверка на точное совпадение названий продуктов
def check_product_name_consistency(message, description):
print()
print("Проверка 31: Проверка на точное совпадение названий продуктов")
print()
message_clean = cut_message(message)
prompt = f'''Проверь, полностью ли совпадает название продукта в сообщении с названием продукта в описании предложения.
Не допускай никаких изменений, таких как перестановка слов, добавление или удаление кавычек, изменение порядка слов, пропуск или добавление слов. Название должно совпадать **точно**.
Описание предложения:
"{description}"
Сообщение:
"{message_clean}"
Если название продукта в сообщении **точно** совпадает с названием продукта в описании предложения, **верни только** JSON {{"decision": false, "explanation": "Название продукта полностью совпадает с описанием."}}.
Если название продукта **не** совпадает, **верни только** JSON {{"decision": true, "explanation": "<описание несоответствия>"}}.
**Не добавляй никакого дополнительного текста. Ответ должен быть только в формате JSON с закрывающими кавычками и скобками.**'''
response = generate_message_gpt4o_mini(prompt)
time.sleep(3)
print("GPT-4o-mini response:", response)
result = parse_json_response(response)
if result is not None:
decision = result.get("decision", False)
explanation = result.get("explanation", "")
print("Explanation:", explanation)
return not decision # Возвращаем True, если совпадение найдено
else:
return None
# ФУНКЦИИ ПРОВЕРОК (КОНЕЦ)
def safe_check(func, *args):
try:
return func(*args)
except Exception as e:
# Optionally, you can log the exception here if needed
return None # Indicate that the check could not be performed
def perform_checks(message, description, key_message):
checks = {
"forbidden_words": safe_check(check_forbidden_words, message),
"client_addressing": safe_check(check_no_greeting, message),
"promises": safe_check(check_no_promises, message),
"double_verbs": safe_check(check_no_double_verbs, message),
"participles": safe_check(check_no_participles, message),
"adverbial_participles": safe_check(check_no_adverbial_participles, message),
"superlative_adjectives": safe_check(check_no_superlative_adjectives, message),
"passive_voice": safe_check(check_no_passive_voice, message),
"written_out_ordinals": safe_check(check_no_written_out_ordinals, message),
"subordinate_clauses_chain": safe_check(check_no_subordinate_clauses_chain, message),
"repeating_conjunctions": safe_check(check_no_repeating_conjunctions, message),
"introductory_phrases": safe_check(check_no_introductory_phrases, message),
"amplifiers": safe_check(check_no_amplifiers, message),
"time_parasites": safe_check(check_no_time_parasites, message),
"multiple_nouns": safe_check(check_no_multiple_nouns, message),
"derived_prepositions": safe_check(check_no_derived_prepositions, message),
"compound_sentences": safe_check(check_no_compound_sentences, message),
"dates_written_out": safe_check(check_no_dates_written_out, message),
"no_word_repetitions": safe_check(check_no_word_repetitions, message),
# Проверки на LLM
"disconnected_sentences": safe_check(check_disconnected_sentences, message),
"synonymous_members": safe_check(check_synonymous_members, message),
"clickbait_phrases": safe_check(check_clickbait_phrases, message),
"abstract_claims": safe_check(check_abstract_claims, message),
"specialized_terms": safe_check(check_specialized_terms, message),
"offensive_phrases": safe_check(check_offensive_phrases, message),
"cliches_and_bureaucratese": safe_check(check_cliches_and_bureaucratese, message),
"no_contradictions": safe_check(check_no_contradictions, message, description),
"contains_key_message": safe_check(check_contains_key_message, message, key_message),
"product_name_consistency": safe_check(check_product_name_consistency, message, description)
}
return checks
def format_checks(checks):
translation = {
"forbidden_words": "Запрещенные слова",
"client_addressing": "Обращение к клиенту",
"promises": "Обещания и гарантии",
"double_verbs": "Два глагола подряд",
"participles": "Причастия",
"adverbial_participles": "Деепричастия",
"superlative_adjectives": "Превосходная степень",
"passive_voice": "Страдательный залог",
"written_out_ordinals": "Порядковые числительные",
"subordinate_clauses_chain": "Цепочки с придаточными предложениями",
"repeating_conjunctions": "Разделительные повторяющиеся союзы",
"introductory_phrases": "Вводные конструкции",
"amplifiers": "Усилители",
"time_parasites": "Паразиты времени",
"multiple_nouns": "Несколько существительных подряд",
"derived_prepositions": "Производные предлоги",
"compound_sentences": "Сложноподчиненные предложения",
"dates_written_out": "Даты прописью",
"no_word_repetitions": "Повторы слов",
# Проверки на LLM
"disconnected_sentences": "Сложные предложения без логической связи",
"synonymous_members": "Близкие по смыслу однородные члены предложения",
"clickbait_phrases": "Кликбейтные фразы",
"abstract_claims": "Абстрактные заявления без доказательств",
"specialized_terms": "Узкоспециализированные термины",
"offensive_phrases": "Двусмысленные или оскорбительные фразы",
"cliches_and_bureaucratese": "Речевые клише, рекламные штампы, канцеляризмы",
"no_contradictions": "Отсутствие противоречий с описанием предложения",
"contains_key_message": "Наличие ключевого сообщения",
"product_name_consistency": "Совпадение названия продукта с описанием предложения"
}
formatted_results = []
for rule, result in checks.items():
if result is True:
symbol = '✔️'
elif result is False:
symbol = '❌'
else:
symbol = '❓' # Indicates that the check could not be performed
formatted_results.append(f"{translation[rule]}: {symbol}")
return " \n".join(formatted_results)
# Создание интерфейса Gradio
with gr.Blocks() as demo:
gr.Markdown("# Генерация SMS-сообщений по заданным признакам")
with gr.Tabs() as tabs:
# Вкладка 1: Рабочее поле
with gr.TabItem("Рабочее поле", id=0):
with gr.Row():
with gr.Column(scale=1):
description_input = gr.Textbox(
label="Описание предложения (предзаполненный пример можно поменять на свой)",
lines=13,
value=(
"Необходимо предложить клиенту оформить дебетовую премиальную бизнес-карту Mastercard Preferred. "
"Обслуживание карты стоит 700 рублей в месяц, но клиент может пользоваться ей бесплатно. "
"Что необходимо сделать, чтобы воспользоваться предложением:\n"
"1. Оформить премиальную бизнес-карту в офисе банка или онлайн в интернет-банке СберБизнес.\n"
"2. Забрать карту.\n"
"3. В течение календарного месяца совершить по ней покупки на сумму от 100 000 рублей.\n"
"4. В течение следующего месяца пользоваться ей бесплатно."
)
)
product_name = gr.Textbox(
label="Неизменяемая часть наименования продукта (предзаполненный пример можно поменять на свой)",
lines=2,
value=(
"дебетовая премиальная бизнес-карта Mastercard Preferred"
),
interactive=True
)
advantages_input = gr.Textbox(
label="Преимущества (предзаполненный пример можно поменять на свой)",
lines=6,
value=(
"Предложение по бесплатному обслуживанию — бессрочное.\n"
"Оплата покупок без отчётов и платёжных поручений.\n"
"Платёжные документы без комиссии.\n"
"Лимиты на расходы сотрудников.\n"
"Мгновенные переводы на карты любых банков."
)
)
key_message_input = gr.Textbox(
label="Ключевое сообщение (предзаполненный пример можно поменять на свой)",
lines=3,
value="Бесплатное обслуживание при покупках от 100 000 рублей в месяц."
)
approach_input = gr.Dropdown(
label="Подход",
choices=["None", "Призыв к действию", "Указание на пользу", "Вопрос"],
value="None" # Default value
)
selections = []
gr.Markdown("**Персонализация**")
for feature in features.keys():
if feature not in ["Пол Поколение Психотип"]: # Исключаем этот лист из выбора
selections.append(gr.Dropdown(choices=[None] + list(features[feature].keys()), label=f"Выберите {feature}"))
with gr.Column(scale=2):
prompt_display = gr.Textbox(
label="Неперсонализированный промпт",
lines=47,
value=(
"Сгенерируй смс-сообщение для клиента.\n"
"Не изменяй название продукта: дебетовая премиальная бизнес-карта Mastercard Preferred.\n"
"Описание предложения: "
"Необходимо предложить клиенту оформить дебетовую премиальную бизнес-карту Mastercard Preferred. "
"Обслуживание карты стоит 700 рублей в месяц, но клиент может пользоваться ей бесплатно. "
"Что необходимо сделать, чтобы воспользоваться предложением:\n"
"1. Оформить премиальную бизнес-карту в офисе банка или онлайн в интернет-банке СберБизнес.\n"
"2. Забрать карту.\n"
"3. В течение календарного месяца совершить по ней покупки на сумму от 100 000 рублей.\n"
"4. В течение следующего месяца пользоваться ей бесплатно.\n"
"Преимущества: "
"Предложение по бесплатному обслуживанию — бессрочное.\n"
"Оплата покупок без отчётов и платёжных поручений.\n"
"Платёжные документы без комиссии.\n"
"Лимиты на расходы сотрудников.\n"
"Мгновенные переводы на карты любых банков.\n "
"В тексте смс запрещено использование:\n"
"- Запрещенные слова: № один, номер один, № 1, вкусный, дешёвый, продукт, спам, банкротство, долги, займ, срочно, лучший, главный, номер 1, гарантия, успех, лидер;\n"
"- Обращение к клиенту;\n"
"- Приветствие клиента;\n"
"- Обещания и гарантии;\n"
"- Использовать составные конструкции из двух глаголов;\n"
"- Причастия и причастные обороты;\n"
"- Деепричастия и деепричастные обороты;\n"
"- Превосходная степень прилагательных;\n"
"- Страдательный залог;\n"
"- Порядковые числительные от 10 прописью;\n"
"- Цепочки с придаточными предложениями;\n"
"- Разделительные повторяющиеся союзы;\n"
"- Вводные конструкции;\n"
"- Усилители;\n"
"- Паразиты времени;\n"
"- Несколько существительных подряд, в том числе отглагольных;\n"
"- Производные предлоги;\n"
"- Сложные предложения, в которых нет связи между частями;\n"
"- Сложноподчинённые предложения;\n"
"- Даты прописью;\n"
"- Близкие по смыслу однородные члены предложения;\n"
"- Шокирующие, экстравагантные, кликбейтные фразы;\n"
"- Абстрактные заявления без поддержки фактами и отсутствие доказательства пользы для клиента;\n"
"- Гарантирующие фразы;\n"
"- Узкоспециализированные термины;\n"
"- Фразы, способные создать двойственное ощущение, обидеть;\n"
"- Речевые клише, рекламные штампы, канцеляризмы;\n"
"Убедись, что в готовом тексте от 190 до 250 знаков с пробелами.\n"
"Убедись, что готовый текст начинается с призыва к действию с продуктом.\n"
"Убедись, что в готовом тексте без изменений, синонимов и перестановок слов используется наименование продукта: дебетовая премиальная бизнес-карта Mastercard Preferred.\n"
"Убедись, что в готовом тексте есть следующая ключевая информация: Бесплатное обслуживание при покупках от 100 000 рублей в месяц."
),
interactive=False)
personalization_prompt = gr.Textbox(label="Персонализированный промпт", lines=11, interactive=False)
best_example_prompt = gr.Textbox(label="Промпт для адаптации под лучший пример", lines=8, interactive=False)
with gr.Row():
submit_btn = gr.Button("1. Создать неперсонализированное сообщение")
personalize_btn = gr.Button("2. Выполнить персонализацию (нажимать только после кнопки 1)", elem_id="personalize_button")
best_example_btn = gr.Button("3. Выполнить адаптацию под лучший пример (нажимать только после кнопки 2)", elem_id="best_example_button")
load_btn = gr.Button("Вернуть параметры предыдущего запроса")
gr.Markdown("---") # Добавляет горизонтальную линию
# Ряд кнопок "Перегенерировать"
with gr.Row():
regen_gigachat_pro_btn = gr.Button("Перегенерировать")
regen_gigachat_lite_btn = gr.Button("Перегенерировать")
regen_gigachat_plus_btn = gr.Button("Перегенерировать")
regen_gpt4o_btn = gr.Button("Перегенерировать")
regen_meta_llama_405b_btn = gr.Button("Перегенерировать")
# Первый ряд: неперсонализированные сообщения
with gr.Row():
output_text_gigachat_pro = gr.Textbox(label="Неперсонализированное сообщение 1", lines=3, interactive=False)
output_text_gigachat_lite = gr.Textbox(label="Неперсонализированное сообщение 2", lines=3, interactive=False)
output_text_gigachat_plus = gr.Textbox(label="Неперсонализированное сообщение 3", lines=3, interactive=False)
output_text_gpt4o = gr.Textbox(label="Неперсонализированное сообщение 4", lines=3, interactive=False)
output_text_meta_llama_405b = gr.Textbox(label="Неперсонализированное сообщение 5", lines=3, interactive=False)
# Ряд кнопок "Персонализировать"
with gr.Row():
personalize_gigachat_pro_btn = gr.Button("Персонализировать")
personalize_gigachat_lite_btn = gr.Button("Персонализировать")
personalize_gigachat_plus_btn = gr.Button("Персонализировать")
personalize_gpt4o_btn = gr.Button("Персонализировать")
personalize_meta_llama_405b_btn = gr.Button("Персонализировать")
# Второй ряд: персонализированные сообщения
with gr.Row():
personalized_output_text_gigachat_pro = gr.Textbox(label="Персонализированное сообщение 1", lines=3, interactive=False)
personalized_output_text_gigachat_lite = gr.Textbox(label="Персонализированное сообщение 2", lines=3, interactive=False)
personalized_output_text_gigachat_plus = gr.Textbox(label="Персонализированное сообщение 3", lines=3, interactive=False)
personalized_output_text_gpt4o = gr.Textbox(label="Персонализированное сообщение 4", lines=3, interactive=False)
personalized_output_text_meta_llama_405b = gr.Textbox(label="Персонализированное сообщение 5", lines=3, interactive=False)
# Второй (с половиной:) ряд: адаптированные сообщения
with gr.Row():
adapted_output_text_gigachat_pro = gr.Textbox(label="Адаптированное сообщение 1", lines=3, interactive=False)
adapted_output_text_gigachat_lite = gr.Textbox(label="Адаптированное сообщение 2", lines=3, interactive=False)
adapted_output_text_gigachat_plus = gr.Textbox(label="Адаптированное сообщение 3", lines=3, interactive=False)
adapted_output_text_gpt4o = gr.Textbox(label="Адаптированное сообщение 4", lines=3, interactive=False)
adapted_output_text_meta_llama_405b = gr.Textbox(label="Адаптированное сообщение 5", lines=3, interactive=False)
# Третий ряд: комментарии
with gr.Row():
comment_gigachat_pro = gr.Textbox(label="Комментарий к сообщению 1", lines=3)
comment_gigachat_lite = gr.Textbox(label="Комментарий к сообщению 2", lines=3)
comment_gigachat_plus = gr.Textbox(label="Комментарий к сообщению 3", lines=3)
comment_gpt4o = gr.Textbox(label="Комментарий к сообщению 4", lines=3)
comment_meta_llama_405b = gr.Textbox(label="Комментарий к сообщению 5", lines=3)
# Четвертый ряд: откорректированные сообщения
with gr.Row():
corrected_gigachat_pro = gr.Textbox(label="Откорректированное сообщение 1", lines=3)
corrected_gigachat_lite = gr.Textbox(label="Откорректированное сообщение 2", lines=3)
corrected_gigachat_plus = gr.Textbox(label="Откорректированное сообщение 3", lines=3)
corrected_gpt4o = gr.Textbox(label="Откорректированное сообщение 4", lines=3)
corrected_meta_llama_405b = gr.Textbox(label="Откорректированное сообщение 5", lines=3)
# Добавляем ряд с рейтингами
with gr.Row():
rating_gigachat_pro = gr.Dropdown(
choices=["1", "2", "3"],
label="Рейтинг сообщения 1",
value="1",
interactive=True
)
rating_gigachat_lite = gr.Dropdown(
choices=["1", "2", "3", "4", "5", "6", "7", "8", "9", "10"],
label="Рейтинг сообщения 2",
value="1",
interactive=True
)
rating_gigachat_plus = gr.Dropdown(
choices=["1", "2", "3", "4", "5", "6", "7", "8", "9", "10"],
label="Рейтинг сообщения 3",
value="1",
interactive=True
)
rating_gpt4o = gr.Dropdown(
choices=["1", "2", "3", "4", "5", "6", "7", "8", "9", "10"],
label="Рейтинг сообщения 4",
value="1",
interactive=True
)
rating_meta_llama_405b = gr.Dropdown(
choices=["1", "2", "3", "4", "5", "6", "7", "8", "9", "10"],
label="Рейтинг сообщения 5",
value="1",
interactive=True
)
# Пятый ряд: кнопки сохранения
with gr.Row():
save_gigachat_pro_btn = gr.Button("Сохранить в базу")
save_gigachat_lite_btn = gr.Button("Сохранить в базу")
save_gigachat_plus_btn = gr.Button("Сохранить в базу")
save_gpt4o_btn = gr.Button("Сохранить в базу")
save_meta_llama_405b_btn = gr.Button("Сохранить в базу")
gr.Markdown("---")
with gr.Row():
validation_display_1 = gr.Markdown()
validation_display_2 = gr.Markdown()
validation_display_3 = gr.Markdown()
validation_display_4 = gr.Markdown()
validation_display_5 = gr.Markdown()
gr.Markdown("---")
# Вкладка 2: Аналитика
with gr.TabItem("Аналитика", id=1):
with gr.Row():
download_btn = gr.Button("Выгрузить актуальную базу сообщений (~ 45 сек)")
download_link = gr.Markdown(value="", label="Ссылка для скачивания")
gr.Markdown("---")
gr.Markdown("## Аналитика")
total_messages_display = gr.Markdown(value="", label="Общее количество сообщений")
total_clean_messages_display = gr.Markdown(value="", label="Общее количество сообщений без необходимости корректировок")
with gr.Row():
model_pie_chart = gr.Plot(label="График 1")
clean_model_pie_chart = gr.Plot(label="График 2")
contributor_pie_chart = gr.Plot(label="График 3")
date_message_chart = gr.Plot(label="График 4")
cumulative_model_chart = gr.Plot(label="График 5")
cumulative_clean_model_chart = gr.Plot(label="График 6")
cumulative_author_chart = gr.Plot(label="График 7")
character_count_chart = gr.Plot(label="График 8")
sentence_count_chart = gr.Plot(label="График 9")
gr.Markdown("---")
with gr.TabItem("Инструкция", id=2):
gr.Markdown("""
### Инструкция
Функционал адаптации сообщений под лучший пример — в beta-версии.
Если вы сгенерировали адаптированное сообщение, и оно вам понравилось (вы хотите сохранить его в базу), то скопируйте его, пожалуйста, в поле "Откорректированное сообщение" (а поле "Комментарий" оставьте пустым).
Когда вы нажимаете адаптировать, то результаты проверок ниже обновляются и приводятся для адаптированных (а не персонализированных) сообщений.
""")
# Очистка всех полей кроме prompt_display
description_input.change(
fn=clear_outputs, # Сначала вызываем функцию очистки полей
inputs=[
output_text_gigachat_pro,
output_text_gigachat_lite,
output_text_gigachat_plus,
output_text_gpt4o,
output_text_meta_llama_405b,
personalized_output_text_gigachat_pro,
personalized_output_text_gigachat_lite,
personalized_output_text_gigachat_plus,
personalized_output_text_gpt4o,
personalized_output_text_meta_llama_405b,
adapted_output_text_gigachat_pro,
adapted_output_text_gigachat_lite,
adapted_output_text_gigachat_plus,
adapted_output_text_gpt4o,
adapted_output_text_meta_llama_405b,
comment_gigachat_pro,
corrected_gigachat_pro,
comment_gigachat_lite,
corrected_gigachat_lite,
comment_gigachat_plus,
corrected_gigachat_plus,
comment_gpt4o,
corrected_gpt4o,
comment_meta_llama_405b,
corrected_meta_llama_405b,
validation_display_1,
validation_display_2,
validation_display_3,
validation_display_4,
validation_display_5
],
outputs=[
output_text_gigachat_pro,
output_text_gigachat_lite,
output_text_gigachat_plus,
output_text_gpt4o,
output_text_meta_llama_405b,
personalized_output_text_gigachat_pro,
personalized_output_text_gigachat_lite,
personalized_output_text_gigachat_plus,
personalized_output_text_gpt4o,
personalized_output_text_meta_llama_405b,
adapted_output_text_gigachat_pro,
adapted_output_text_gigachat_lite,
adapted_output_text_gigachat_plus,
adapted_output_text_gpt4o,
adapted_output_text_meta_llama_405b,
comment_gigachat_pro,
corrected_gigachat_pro,
comment_gigachat_lite,
corrected_gigachat_lite,
comment_gigachat_plus,
corrected_gigachat_plus,
comment_gpt4o,
corrected_gpt4o,
comment_meta_llama_405b,
corrected_meta_llama_405b,
validation_display_1,
validation_display_2,
validation_display_3,
validation_display_4,
validation_display_5
]
).then(
fn=generate_standard_prompt, # После очистки вызываем функцию для обновления промпта
inputs=[description_input, product_name, advantages_input, key_message_input, approach_input] + selections,
outputs=prompt_display # Мгновенно обновляем поле неперсонализированного промпта
).then(
fn=update_best_example_prompt,
inputs=[description_input] + selections,
outputs=best_example_prompt
)
product_name.change(
fn=clear_outputs, # Сначала вызываем функцию очистки полей
inputs=[
output_text_gigachat_pro,
output_text_gigachat_lite,
output_text_gigachat_plus,
output_text_gpt4o,
output_text_meta_llama_405b,
personalized_output_text_gigachat_pro,
personalized_output_text_gigachat_lite,
personalized_output_text_gigachat_plus,
personalized_output_text_gpt4o,
personalized_output_text_meta_llama_405b,
adapted_output_text_gigachat_pro,
adapted_output_text_gigachat_lite,
adapted_output_text_gigachat_plus,
adapted_output_text_gpt4o,
adapted_output_text_meta_llama_405b,
comment_gigachat_pro,
corrected_gigachat_pro,
comment_gigachat_lite,
corrected_gigachat_lite,
comment_gigachat_plus,
corrected_gigachat_plus,
comment_gpt4o,
corrected_gpt4o,
comment_meta_llama_405b,
corrected_meta_llama_405b,
validation_display_1,
validation_display_2,
validation_display_3,
validation_display_4,
validation_display_5
],
outputs=[
output_text_gigachat_pro,
output_text_gigachat_lite,
output_text_gigachat_plus,
output_text_gpt4o,
output_text_meta_llama_405b,
personalized_output_text_gigachat_pro,
personalized_output_text_gigachat_lite,
personalized_output_text_gigachat_plus,
personalized_output_text_gpt4o,
personalized_output_text_meta_llama_405b,
adapted_output_text_gigachat_pro,
adapted_output_text_gigachat_lite,
adapted_output_text_gigachat_plus,
adapted_output_text_gpt4o,
adapted_output_text_meta_llama_405b,
comment_gigachat_pro,
corrected_gigachat_pro,
comment_gigachat_lite,
corrected_gigachat_lite,
comment_gigachat_plus,
corrected_gigachat_plus,
comment_gpt4o,
corrected_gpt4o,
comment_meta_llama_405b,
corrected_meta_llama_405b,
validation_display_1,
validation_display_2,
validation_display_3,
validation_display_4,
validation_display_5
]
).then(
fn=generate_standard_prompt, # После очистки вызываем функцию для обновления промпта
inputs=[description_input, product_name, advantages_input, key_message_input, approach_input] + selections,
outputs=prompt_display # Мгновенно обновляем поле неперсонализированного промпта
).then(
fn=update_best_example_prompt,
inputs=[description_input] + selections,
outputs=best_example_prompt
)
# Очистка всех полей кроме prompt_display
advantages_input.change(
fn=clear_outputs, # Сначала вызываем функцию очистки полей
inputs=[
output_text_gigachat_pro,
output_text_gigachat_lite,
output_text_gigachat_plus,
output_text_gpt4o,
output_text_meta_llama_405b,
personalized_output_text_gigachat_pro,
personalized_output_text_gigachat_lite,
personalized_output_text_gigachat_plus,
personalized_output_text_gpt4o,
personalized_output_text_meta_llama_405b,
adapted_output_text_gigachat_pro,
adapted_output_text_gigachat_lite,
adapted_output_text_gigachat_plus,
adapted_output_text_gpt4o,
adapted_output_text_meta_llama_405b,
comment_gigachat_pro,
corrected_gigachat_pro,
comment_gigachat_lite,
corrected_gigachat_lite,
comment_gigachat_plus,
corrected_gigachat_plus,
comment_gpt4o,
corrected_gpt4o,
comment_meta_llama_405b,
corrected_meta_llama_405b,
validation_display_1,
validation_display_2,
validation_display_3,
validation_display_4,
validation_display_5
],
outputs=[
output_text_gigachat_pro,
output_text_gigachat_lite,
output_text_gigachat_plus,
output_text_gpt4o,
output_text_meta_llama_405b,
personalized_output_text_gigachat_pro,
personalized_output_text_gigachat_lite,
personalized_output_text_gigachat_plus,
personalized_output_text_gpt4o,
personalized_output_text_meta_llama_405b,
adapted_output_text_gigachat_pro,
adapted_output_text_gigachat_lite,
adapted_output_text_gigachat_plus,
adapted_output_text_gpt4o,
adapted_output_text_meta_llama_405b,
comment_gigachat_pro,
corrected_gigachat_pro,
comment_gigachat_lite,
corrected_gigachat_lite,
comment_gigachat_plus,
corrected_gigachat_plus,
comment_gpt4o,
corrected_gpt4o,
comment_meta_llama_405b,
corrected_meta_llama_405b,
validation_display_1,
validation_display_2,
validation_display_3,
validation_display_4,
validation_display_5
]
).then(
fn=generate_standard_prompt, # После очистки вызываем функцию для обновления промпта
inputs=[description_input, advantages_input, key_message_input, approach_input] + selections,
outputs=prompt_display # Мгновенно обновляем поле неперсонализированного промпта
)
# Очистка всех полей кроме prompt_display
key_message_input.change(
fn=clear_outputs, # Сначала вызываем функцию очистки полей
inputs=[
output_text_gigachat_pro,
output_text_gigachat_lite,
output_text_gigachat_plus,
output_text_gpt4o,
output_text_meta_llama_405b,
personalized_output_text_gigachat_pro,
personalized_output_text_gigachat_lite,
personalized_output_text_gigachat_plus,
personalized_output_text_gpt4o,
personalized_output_text_meta_llama_405b,
adapted_output_text_gigachat_pro,
adapted_output_text_gigachat_lite,
adapted_output_text_gigachat_plus,
adapted_output_text_gpt4o,
adapted_output_text_meta_llama_405b,
comment_gigachat_pro,
corrected_gigachat_pro,
comment_gigachat_lite,
corrected_gigachat_lite,
comment_gigachat_plus,
corrected_gigachat_plus,
comment_gpt4o,
corrected_gpt4o,
comment_meta_llama_405b,
corrected_meta_llama_405b,
validation_display_1,
validation_display_2,
validation_display_3,
validation_display_4,
validation_display_5
],
outputs=[
output_text_gigachat_pro,
output_text_gigachat_lite,
output_text_gigachat_plus,
output_text_gpt4o,
output_text_meta_llama_405b,
personalized_output_text_gigachat_pro,
personalized_output_text_gigachat_lite,
personalized_output_text_gigachat_plus,
personalized_output_text_gpt4o,
personalized_output_text_meta_llama_405b,
adapted_output_text_gigachat_pro,
adapted_output_text_gigachat_lite,
adapted_output_text_gigachat_plus,
adapted_output_text_gpt4o,
adapted_output_text_meta_llama_405b,
comment_gigachat_pro,
corrected_gigachat_pro,
comment_gigachat_lite,
corrected_gigachat_lite,
comment_gigachat_plus,
corrected_gigachat_plus,
comment_gpt4o,
corrected_gpt4o,
comment_meta_llama_405b,
corrected_meta_llama_405b,
validation_display_1,
validation_display_2,
validation_display_3,
validation_display_4,
validation_display_5
]
).then(
fn=generate_standard_prompt, # После очистки вызываем функцию для обновления промпта
inputs=[description_input, product_name, advantages_input, key_message_input, approach_input] + selections,
outputs=prompt_display # Мгновенно обновляем поле неперсонализированного промпта
)
# Очистка всех полей кроме prompt_display
approach_input.change(
fn=clear_outputs, # Сначала вызываем функцию очистки полей
inputs=[
output_text_gigachat_pro,
output_text_gigachat_lite,
output_text_gigachat_plus,
output_text_gpt4o,
output_text_meta_llama_405b,
personalized_output_text_gigachat_pro,
personalized_output_text_gigachat_lite,
personalized_output_text_gigachat_plus,
personalized_output_text_gpt4o,
personalized_output_text_meta_llama_405b,
adapted_output_text_gigachat_pro,
adapted_output_text_gigachat_lite,
adapted_output_text_gigachat_plus,
adapted_output_text_gpt4o,
adapted_output_text_meta_llama_405b,
comment_gigachat_pro,
corrected_gigachat_pro,
comment_gigachat_lite,
corrected_gigachat_lite,
comment_gigachat_plus,
corrected_gigachat_plus,
comment_gpt4o,
corrected_gpt4o,
comment_meta_llama_405b,
corrected_meta_llama_405b,
validation_display_1,
validation_display_2,
validation_display_3,
validation_display_4,
validation_display_5
],
outputs=[
output_text_gigachat_pro,
output_text_gigachat_lite,
output_text_gigachat_plus,
output_text_gpt4o,
output_text_meta_llama_405b,
personalized_output_text_gigachat_pro,
personalized_output_text_gigachat_lite,
personalized_output_text_gigachat_plus,
personalized_output_text_gpt4o,
personalized_output_text_meta_llama_405b,
adapted_output_text_gigachat_pro,
adapted_output_text_gigachat_lite,
adapted_output_text_gigachat_plus,
adapted_output_text_gpt4o,
adapted_output_text_meta_llama_405b,
comment_gigachat_pro,
corrected_gigachat_pro,
comment_gigachat_lite,
corrected_gigachat_lite,
comment_gigachat_plus,
corrected_gigachat_plus,
comment_gpt4o,
corrected_gpt4o,
comment_meta_llama_405b,
corrected_meta_llama_405b,
validation_display_1,
validation_display_2,
validation_display_3,
validation_display_4,
validation_display_5
]
).then(
fn=generate_standard_prompt, # После очистки вызываем функцию для обновления промпта
inputs=[description_input, product_name, advantages_input, key_message_input, approach_input] + selections,
outputs=prompt_display # Мгновенно обновляем поле неперсонализированного промпта
).then(
fn=generate_personalization_prompt, # Вызываем генерацию персонализированного промпта после изменения
inputs=[product_name, key_message_input, approach_input] + selections, # Передаем все нужные параметры
outputs=personalization_prompt # Обновляем поле с персонализированным промптом
)
# Добавляем обработчики для каждого поля в selections
for selection in selections:
# Очищаем все персонализированные сообщения и результаты проверок
selection.change(
fn=clear_outputs,
inputs=[
personalized_output_text_gigachat_pro,
personalized_output_text_gigachat_lite,
personalized_output_text_gigachat_plus,
personalized_output_text_gpt4o,
personalized_output_text_meta_llama_405b,
adapted_output_text_gigachat_pro,
adapted_output_text_gigachat_lite,
adapted_output_text_gigachat_plus,
adapted_output_text_gpt4o,
adapted_output_text_meta_llama_405b,
comment_gigachat_pro,
corrected_gigachat_pro,
comment_gigachat_lite,
corrected_gigachat_lite,
comment_gigachat_plus,
corrected_gigachat_plus,
comment_gpt4o,
corrected_gpt4o,
comment_meta_llama_405b,
corrected_meta_llama_405b,
validation_display_1,
validation_display_2,
validation_display_3,
validation_display_4,
validation_display_5],
outputs=[
personalized_output_text_gigachat_pro,
personalized_output_text_gigachat_lite,
personalized_output_text_gigachat_plus,
personalized_output_text_gpt4o,
personalized_output_text_meta_llama_405b,
adapted_output_text_gigachat_pro,
adapted_output_text_gigachat_lite,
adapted_output_text_gigachat_plus,
adapted_output_text_gpt4o,
adapted_output_text_meta_llama_405b,
comment_gigachat_pro,
corrected_gigachat_pro,
comment_gigachat_lite,
corrected_gigachat_lite,
comment_gigachat_plus,
corrected_gigachat_plus,
comment_gpt4o,
corrected_gpt4o,
comment_meta_llama_405b,
corrected_meta_llama_405b,
validation_display_1,
validation_display_2,
validation_display_3,
validation_display_4,
validation_display_5
]
).then(
fn=generate_personalization_prompt, # Вызываем генерацию персонализированного промпта после изменения
inputs=[product_name, key_message_input, approach_input] + selections, # Передаем все нужные параметры
outputs=personalization_prompt # Обновляем поле с персонализированным промптом
).then(
fn=update_best_example_prompt,
inputs=[description_input] + selections,
outputs=best_example_prompt
)
# Добавление функционала для кнопок
submit_btn.click(
clear_outputs,
inputs=[
personalized_output_text_gigachat_pro,
personalized_output_text_gigachat_lite,
personalized_output_text_gigachat_plus,
personalized_output_text_gpt4o,
personalized_output_text_meta_llama_405b,
adapted_output_text_gigachat_pro,
adapted_output_text_gigachat_lite,
adapted_output_text_gigachat_plus,
adapted_output_text_gpt4o,
adapted_output_text_meta_llama_405b,
comment_gigachat_pro,
corrected_gigachat_pro,
comment_gigachat_lite,
corrected_gigachat_lite,
comment_gigachat_plus,
corrected_gigachat_plus,
comment_gpt4o,
corrected_gpt4o,
comment_meta_llama_405b,
corrected_meta_llama_405b,
validation_display_1, # Очистка результатов проверок
validation_display_2,
validation_display_3,
validation_display_4,
validation_display_5
],
outputs=[
personalized_output_text_gigachat_pro,
personalized_output_text_gigachat_lite,
personalized_output_text_gigachat_plus,
personalized_output_text_gpt4o,
personalized_output_text_meta_llama_405b,
adapted_output_text_gigachat_pro,
adapted_output_text_gigachat_lite,
adapted_output_text_gigachat_plus,
adapted_output_text_gpt4o,
adapted_output_text_meta_llama_405b,
comment_gigachat_pro,
corrected_gigachat_pro,
comment_gigachat_lite,
corrected_gigachat_lite,
comment_gigachat_plus,
corrected_gigachat_plus,
comment_gpt4o,
corrected_gpt4o,
comment_meta_llama_405b,
corrected_meta_llama_405b,
validation_display_1, # Очистка результатов проверок
validation_display_2,
validation_display_3,
validation_display_4,
validation_display_5
]
)
submit_btn.click(
generate_messages,
inputs=[description_input, product_name, advantages_input, key_message_input, approach_input] + selections,
outputs=[
prompt_display,
output_text_gigachat_pro,
output_text_gigachat_lite,
output_text_gigachat_plus,
output_text_gpt4o,
output_text_meta_llama_405b
]
)
personalize_btn.click(
fn=clear_outputs,
inputs=[
personalized_output_text_gigachat_pro,
personalized_output_text_gigachat_lite,
personalized_output_text_gigachat_plus,
personalized_output_text_gpt4o,
personalized_output_text_meta_llama_405b,
adapted_output_text_gigachat_pro,
adapted_output_text_gigachat_lite,
adapted_output_text_gigachat_plus,
adapted_output_text_gpt4o,
adapted_output_text_meta_llama_405b,
comment_gigachat_pro,
corrected_gigachat_pro,
comment_gigachat_lite,
corrected_gigachat_lite,
comment_gigachat_plus,
corrected_gigachat_plus,
comment_gpt4o,
corrected_gpt4o,
comment_meta_llama_405b,
corrected_meta_llama_405b
],
outputs=[
personalized_output_text_gigachat_pro,
personalized_output_text_gigachat_lite,
personalized_output_text_gigachat_plus,
personalized_output_text_gpt4o,
personalized_output_text_meta_llama_405b,
adapted_output_text_gigachat_pro,
adapted_output_text_gigachat_lite,
adapted_output_text_gigachat_plus,
adapted_output_text_gpt4o,
adapted_output_text_meta_llama_405b,
comment_gigachat_pro,
corrected_gigachat_pro,
comment_gigachat_lite,
corrected_gigachat_lite,
comment_gigachat_plus,
corrected_gigachat_plus,
comment_gpt4o,
corrected_gpt4o,
comment_meta_llama_405b,
corrected_meta_llama_405b
]
)
personalize_btn.click(
fn=personalize_and_save,
inputs=[
output_text_gigachat_pro,
output_text_gigachat_lite,
output_text_gigachat_plus,
output_text_gpt4o,
output_text_meta_llama_405b,
description_input,
product_name,
advantages_input,
key_message_input,
approach_input,
] + selections,
outputs=[
personalization_prompt,
personalized_output_text_gigachat_pro,
personalized_output_text_gigachat_lite,
personalized_output_text_gigachat_plus,
personalized_output_text_gpt4o,
personalized_output_text_meta_llama_405b,
validation_display_1,
validation_display_2,
validation_display_3,
validation_display_4,
validation_display_5,
]
)
best_example_btn.click(
fn=adapt_messages_and_perform_checks,
inputs=[
description_input,
personalized_output_text_gigachat_pro,
personalized_output_text_gigachat_lite,
personalized_output_text_gigachat_plus,
personalized_output_text_gpt4o,
personalized_output_text_meta_llama_405b,
key_message_input,
approach_input,
] + selections,
outputs=[
adapted_output_text_gigachat_pro,
adapted_output_text_gigachat_lite,
adapted_output_text_gigachat_plus,
adapted_output_text_gpt4o,
adapted_output_text_meta_llama_405b,
validation_display_1,
validation_display_2,
validation_display_3,
validation_display_4,
validation_display_5
]
)
# Обработка клика по кнопке восстановления
load_btn.click(
fn=lambda: load_previous_user_request_from_github(),
inputs=[],
outputs=[
description_input, # Описание предложения
advantages_input, # Преимущества
key_message_input, # Ключевое сообщение
approach_input, # Подход
*selections, # Параметры персонализации (Пол, Поколение и т.д.)
]
).then(
fn=clear_outputs,
inputs=[
prompt_display,
personalization_prompt, # Очищаем personalization_prompt
output_text_gigachat_pro,
output_text_gigachat_lite,
output_text_gigachat_plus,
output_text_gpt4o,
output_text_meta_llama_405b,
personalized_output_text_gigachat_pro,
personalized_output_text_gigachat_lite,
personalized_output_text_gigachat_plus,
personalized_output_text_gpt4o,
personalized_output_text_meta_llama_405b,
adapted_output_text_gigachat_pro,
adapted_output_text_gigachat_lite,
adapted_output_text_gigachat_plus,
adapted_output_text_gpt4o,
adapted_output_text_meta_llama_405b,
comment_gigachat_pro,
corrected_gigachat_pro,
comment_gigachat_lite,
corrected_gigachat_lite,
comment_gigachat_plus,
corrected_gigachat_plus,
comment_gpt4o,
corrected_gpt4o,
comment_meta_llama_405b,
corrected_meta_llama_405b,
validation_display_1, # Очистка результатов проверок
validation_display_2,
validation_display_3,
validation_display_4,
validation_display_5
],
outputs=[
prompt_display,
personalization_prompt, # Очищаем personalization_prompt
output_text_gigachat_pro,
output_text_gigachat_lite,
output_text_gigachat_plus,
output_text_gpt4o,
output_text_meta_llama_405b,
personalized_output_text_gigachat_pro,
personalized_output_text_gigachat_lite,
personalized_output_text_gigachat_plus,
personalized_output_text_gpt4o,
personalized_output_text_meta_llama_405b,
adapted_output_text_gigachat_pro,
adapted_output_text_gigachat_lite,
adapted_output_text_gigachat_plus,
adapted_output_text_gpt4o,
adapted_output_text_meta_llama_405b,
comment_gigachat_pro,
corrected_gigachat_pro,
comment_gigachat_lite,
corrected_gigachat_lite,
comment_gigachat_plus,
corrected_gigachat_plus,
comment_gpt4o,
corrected_gpt4o,
comment_meta_llama_405b,
corrected_meta_llama_405b,
validation_display_1, # Очистка результатов проверок
validation_display_2,
validation_display_3,
validation_display_4,
validation_display_5
]
).then(
fn=generate_standard_prompt, # Генерация неперсонализированного промпта на основе загруженных данных
inputs=[description_input, advantages_input, key_message_input, approach_input] + selections,
outputs=prompt_display # Обновляем поле с неперсонализированным промптом
).then(
fn=generate_personalization_prompt, # Генерация персонализированного промпта
inputs=[key_message_input, approach_input] + selections,
outputs=personalization_prompt # Обновляем поле с персонализированным промптом
)
regen_gigachat_pro_btn.click(
fn=lambda: ("", "", ""), # Очищаем текст персонализированного сообщения и проверку
inputs=[],
outputs=[personalized_output_text_gigachat_pro, adapted_output_text_gigachat_pro, validation_display_1]
).then(
fn=regen_message_gigachat_pro,
inputs=[description_input, advantages_input, key_message_input, approach_input] + selections,
outputs=output_text_gigachat_pro
)
regen_gigachat_lite_btn.click(
fn=lambda: ("", "", ""), # Очищаем текст персонализированного сообщения и проверку
inputs=[],
outputs=[personalized_output_text_gigachat_lite, adapted_output_text_gigachat_lite, validation_display_2]
).then(
fn=regen_message_gigachat_lite,
inputs=[description_input, advantages_input, key_message_input, approach_input] + selections,
outputs=output_text_gigachat_lite
)
regen_gigachat_plus_btn.click(
fn=lambda: ("", "", ""), # Очищаем текст персонализированного сообщения и проверку
inputs=[],
outputs=[personalized_output_text_gigachat_plus, adapted_output_text_gigachat_plus, validation_display_3]
).then(
fn=regen_message_gigachat_plus,
inputs=[description_input, advantages_input, key_message_input, approach_input] + selections,
outputs=output_text_gigachat_plus
)
regen_gpt4o_btn.click(
fn=lambda: ("", "", ""), # Очищаем текст персонализированного сообщения и проверку
inputs=[],
outputs=[personalized_output_text_gpt4o, adapted_output_text_gpt4o, validation_display_4]
).then(
fn=regen_message_gpt4o,
inputs=[description_input, advantages_input, key_message_input, approach_input] + selections,
outputs=output_text_gpt4o
)
regen_meta_llama_405b_btn.click(
fn=lambda: ("", "", ""), # Очищаем текст персонализированного сообщения и проверку
inputs=[],
outputs=[personalized_output_text_meta_llama_405b, adapted_output_text_meta_llama_405b, validation_display_5]
).then(
fn=regen_message_meta_llama_405b,
inputs=[description_input, advantages_input, key_message_input, approach_input] + selections,
outputs=output_text_meta_llama_405b
)
personalize_gigachat_pro_btn.click(
personalize_message_gigachat_pro,
inputs=[output_text_gigachat_pro, product_name, key_message_input, approach_input] + selections,
outputs=[personalized_output_text_gigachat_pro, validation_display_1]
).then(
fn=lambda: (""),
inputs=[],
outputs=[adapted_output_text_gigachat_pro]
).then(
fn=generate_personalization_prompt, # Вызов генерации промпта
inputs=[product_name, key_message_input, approach_input] + selections, # Передача нужных данных
outputs=personalization_prompt # Вывод в поле с промптом
)
personalize_gigachat_lite_btn.click(
personalize_message_gigachat_lite,
inputs=[output_text_gigachat_lite, product_name, key_message_input, approach_input] + selections,
outputs=[personalized_output_text_gigachat_lite, validation_display_2] # Поле для проверки
).then(
fn=lambda: (""),
inputs=[],
outputs=[adapted_output_text_gigachat_lite]
).then(
fn=generate_personalization_prompt, # Вызов генерации промпта
inputs=[product_name, key_message_input, approach_input] + selections, # Передача нужных данных
outputs=personalization_prompt # Вывод в поле с промптом
)
personalize_gigachat_plus_btn.click(
personalize_message_gigachat_plus,
inputs=[output_text_gigachat_plus, product_name, key_message_input, approach_input] + selections,
outputs=[personalized_output_text_gigachat_plus, validation_display_3] # Добавляем результат проверки
).then(
fn=lambda: (""),
inputs=[],
outputs=[adapted_output_text_gigachat_plus]
).then(
fn=generate_personalization_prompt, # Вызов генерации промпта
inputs=[product_name, key_message_input, approach_input] + selections, # Передача нужных данных
outputs=personalization_prompt # Вывод в поле с промптом
)
personalize_gpt4o_btn.click(
personalize_message_gpt4o,
inputs=[output_text_gpt4o, product_name, key_message_input, approach_input] + selections,
outputs=[personalized_output_text_gpt4o, validation_display_4] # Добавляем результат проверки
).then(
fn=lambda: (""),
inputs=[],
outputs=[adapted_output_text_gpt4o]
).then(
fn=generate_personalization_prompt, # Вызов генерации промпта
inputs=[product_name, key_message_input, approach_input] + selections, # Передача нужных данных
outputs=personalization_prompt # Вывод в поле с промптом
)
personalize_meta_llama_405b_btn.click(
personalize_message_meta_llama_405b,
inputs=[output_text_meta_llama_405b, product_name, key_message_input, approach_input] + selections,
outputs=[personalized_output_text_meta_llama_405b, validation_display_5] # Добавляем результат проверки
).then(
fn=lambda: (""),
inputs=[],
outputs=[adapted_output_text_meta_llama_405b]
).then(
fn=generate_personalization_prompt, # Вызов генерации промпта
inputs=[product_name, key_message_input, approach_input] + selections, # Передача нужных данных
outputs=personalization_prompt # Вывод в поле с промптом
)
# Привязка кнопок к функциям сохранения
save_gigachat_pro_btn.click(
fn=prepare_button_text,
inputs=[],
outputs=[save_gigachat_pro_btn]
).then(
fn=lambda adapted_message, personalized_message, comment, corrected_message, description, advantages,
non_personalized_prompt, non_personalized_message, personalization_prompt, gender, generation, psychotype,
business_stage, industry, legal_form, key_message, approach:
save_both(adapted_message, personalized_message, "GigaChat-Pro", comment, corrected_message, description,
advantages, non_personalized_prompt, non_personalized_message, personalization_prompt, gender,
generation, psychotype, business_stage, industry, legal_form, key_message, approach),
inputs=[
adapted_output_text_gigachat_pro,
personalized_output_text_gigachat_pro,
comment_gigachat_pro,
corrected_gigachat_pro,
description_input,
advantages_input,
prompt_display,
output_text_gigachat_pro,
personalization_prompt,
selections[0], # Пол
selections[1], # Поколение
selections[2], # Психотип
selections[3], # Стадия бизнеса
selections[4], # Отрасль
selections[5], # ОПФ
key_message_input, # Ключевое сообщение
approach_input # Подход
],
outputs=None
).then(
fn=update_button_text,
outputs=[save_gigachat_pro_btn]
).then(
fn=reset_button_text,
outputs=[save_gigachat_pro_btn]
)
# Повторяем аналогично для других кнопок:
save_gigachat_lite_btn.click(
fn=prepare_button_text,
inputs=[],
outputs=[save_gigachat_lite_btn]
).then(
fn=lambda adapted_message, personalized_message, comment, corrected_message, description, advantages,
non_personalized_prompt, non_personalized_message, personalization_prompt, gender, generation, psychotype,
business_stage, industry, legal_form, key_message, approach:
save_both(adapted_message, personalized_message, "GigaChat-Lite", comment, corrected_message, description,
advantages, non_personalized_prompt, non_personalized_message, personalization_prompt, gender,
generation, psychotype, business_stage, industry, legal_form, key_message, approach),
inputs=[
adapted_output_text_gigachat_lite,
personalized_output_text_gigachat_lite,
comment_gigachat_lite,
corrected_gigachat_lite,
description_input,
advantages_input,
prompt_display,
output_text_gigachat_lite,
personalization_prompt,
selections[0],
selections[1],
selections[2],
selections[3],
selections[4],
selections[5],
key_message_input,
approach_input
],
outputs=None
).then(
fn=update_button_text,
outputs=[save_gigachat_lite_btn]
).then(
fn=reset_button_text,
outputs=[save_gigachat_lite_btn]
)
save_gigachat_plus_btn.click(
fn=prepare_button_text,
inputs=[],
outputs=[save_gigachat_plus_btn]
).then(
fn=lambda adapted_message, personalized_message, comment, corrected_message, description, advantages,
non_personalized_prompt, non_personalized_message, personalization_prompt, gender, generation, psychotype,
business_stage, industry, legal_form, key_message, approach:
save_both(adapted_message, personalized_message, "GigaChat-Lite+", comment, corrected_message, description,
advantages, non_personalized_prompt, non_personalized_message, personalization_prompt, gender,
generation, psychotype, business_stage, industry, legal_form, key_message, approach),
inputs=[
adapted_output_text_gigachat_plus,
personalized_output_text_gigachat_plus,
comment_gigachat_plus,
corrected_gigachat_plus,
description_input,
advantages_input,
prompt_display,
output_text_gigachat_plus,
personalization_prompt,
selections[0],
selections[1],
selections[2],
selections[3],
selections[4],
selections[5],
key_message_input,
approach_input
],
outputs=None
).then(
fn=update_button_text,
outputs=[save_gigachat_plus_btn]
).then(
fn=reset_button_text,
outputs=[save_gigachat_plus_btn]
)
save_gpt4o_btn.click(
fn=prepare_button_text,
inputs=[],
outputs=[save_gpt4o_btn]
).then(
fn=lambda adapted_message, personalized_message, comment, corrected_message, description, advantages,
non_personalized_prompt, non_personalized_message, personalization_prompt, gender, generation, psychotype,
business_stage, industry, legal_form, key_message, approach:
save_both(adapted_message, personalized_message, "GPT-4o", comment, corrected_message, description,
advantages, non_personalized_prompt, non_personalized_message, personalization_prompt, gender,
generation, psychotype, business_stage, industry, legal_form, key_message, approach),
inputs=[
adapted_output_text_gpt4o,
personalized_output_text_gpt4o,
comment_gpt4o,
corrected_gpt4o,
description_input,
advantages_input,
prompt_display,
output_text_gpt4o,
personalization_prompt,
selections[0],
selections[1],
selections[2],
selections[3],
selections[4],
selections[5],
key_message_input,
approach_input
],
outputs=None
).then(
fn=update_button_text,
outputs=[save_gpt4o_btn]
).then(
fn=reset_button_text,
outputs=[save_gpt4o_btn]
)
save_meta_llama_405b_btn.click(
fn=prepare_button_text,
inputs=[],
outputs=[save_meta_llama_405b_btn]
).then(
fn=lambda adapted_message, personalized_message, comment, corrected_message, description, advantages,
non_personalized_prompt, non_personalized_message, personalization_prompt, gender, generation, psychotype,
business_stage, industry, legal_form, key_message, approach:
save_both(adapted_message, personalized_message, "Meta-Llama-3.1-405B", comment, corrected_message, description,
advantages, non_personalized_prompt, non_personalized_message, personalization_prompt, gender,
generation, psychotype, business_stage, industry, legal_form, key_message, approach),
inputs=[
adapted_output_text_meta_llama_405b,
personalized_output_text_meta_llama_405b,
comment_meta_llama_405b,
corrected_meta_llama_405b,
description_input,
advantages_input,
prompt_display,
output_text_meta_llama_405b,
personalization_prompt,
selections[0],
selections[1],
selections[2],
selections[3],
selections[4],
selections[5],
key_message_input,
approach_input
],
outputs=None
).then(
fn=update_button_text,
outputs=[save_meta_llama_405b_btn]
).then(
fn=reset_button_text,
outputs=[save_meta_llama_405b_btn]
)
# Связываем кнопку с функцией
download_btn.click(
fn=update_download_link,
inputs=[],
outputs=[
download_link,
total_messages_display,
total_clean_messages_display,
model_pie_chart,
clean_model_pie_chart,
contributor_pie_chart,
date_message_chart,
cumulative_model_chart,
cumulative_clean_model_chart,
cumulative_author_chart,
character_count_chart,
sentence_count_chart
]
)
demo.launch()