| | import streamlit as st |
| | from transformers import AutoModelForSeq2SeqLM, AutoTokenizer |
| | import torch |
| |
|
| | st.set_page_config( |
| | page_title="kindify", |
| | page_icon="logo.png", |
| | layout="wide" |
| | ) |
| |
|
| |
|
| | st.markdown( |
| | """ |
| | <style> |
| | html, body, .stApp, [class*="css"] { |
| | color: #333333 !important; |
| | } |
| | div[role="alert"] div[data-testid="stMarkdownContainer"] p { |
| | color: black !important; |
| | } |
| | div[data-baseweb="notification"] div[data-testid="stMarkdownContainer"] p { |
| | color: black !important; |
| | } |
| | |
| | /* Основной фон приложения */ |
| | .stApp { |
| | background: linear-gradient(135deg, #dcd1d3 0%, #f6f7f9 100%); |
| | background-size: cover; |
| | background-repeat: no-repeat; |
| | background-attachment: fixed; |
| | } |
| | |
| | /* Базовый стиль всех кнопок */ |
| | .stButton>button { |
| | background-color: #cbbabe !important; |
| | color: white !important; |
| | border: 2px solid #cbbabe !important; |
| | transition: all 0.3s ease !important; |
| | } |
| | |
| | /* Стиль при наведении */ |
| | .stButton>button:hover { |
| | background-color: #a6989b !important; |
| | border-color: #a6989b !important; |
| | color: #000000 !important; |
| | } |
| | |
| | /* Стиль в момент нажатия */ |
| | .stButton>button:active { |
| | background-color: #82787a !important; |
| | border-color: #000000 !important; |
| | color: #000000 !important; |
| | transform: scale(0.98) !important; |
| | } |
| | |
| | /* Стиль после клика (фокус) */ |
| | .stButton>button:focus:not(:active) { |
| | background-color: #cbbabe !important; |
| | border-color: #000000; |
| | color: #000000 !important; |
| | } |
| | |
| | /* Стиль текстовых полей ввода */ |
| | .stTextArea textarea, |
| | .stTextInput input { |
| | border: 2px solid #cbbabe !important; |
| | border-radius: 8px !important; |
| | padding: 10px 12px !important; |
| | transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1) !important; |
| | background-color: #fff !important; |
| | color: #333333 !important; |
| | } |
| | |
| | /* Состояние при наведении */ |
| | .stTextArea textarea:hover, |
| | .stTextInput input:hover { |
| | border-color: #a6989b !important; |
| | } |
| | |
| | /* Активное состояние (фокус) */ |
| | .stTextArea textarea:focus, |
| | .stTextInput input:focus { |
| | border-color: #000000 !important; |
| | outline: none !important; |
| | border-color: #000000 !important; |
| | box-shadow: none !important; |
| | color: #333333 !important; |
| | } |
| | |
| | .stTextArea label, .stTextInput label { |
| | color: #333333 !important; |
| | font-weight: bold !important; |
| | } |
| | |
| | /* Плейсхолдер */ |
| | .stTextArea textarea::placeholder, |
| | .stTextInput input::placeholder { |
| | color: #999 !important; |
| | opacity: 1 !important; |
| | } |
| | |
| | [data-testid="stSidebar"] * { |
| | color: #333333 !important; |
| | } |
| | |
| | /* Основной фон сайдбара */ |
| | [data-testid="stSidebar"] { |
| | background-color: #ffffff !important; |
| | } |
| | |
| | </style> |
| | """, |
| | unsafe_allow_html=True |
| | ) |
| | st.title("Toxicity to Kindness Converter") |
| |
|
| |
|
| | with open("logo.svg", "r") as f: |
| | svg_content = f.read() |
| | |
| | top_cut = 120 |
| | right_cut = 50 |
| | bottom_cut = 30 |
| | left_cut = 280 |
| | scale_factor = 0.65 |
| |
|
| | st.sidebar.markdown('<div style="padding-top: 20px;"></div>', unsafe_allow_html=True) |
| |
|
| | st.sidebar.markdown( |
| | f''' |
| | |
| | <div style=" |
| | position: relative; |
| | width: 280px; |
| | height: 180px; |
| | margin: 0 auto; |
| | overflow: hidden; |
| | border-radius: 25px; |
| | background-color: rgba(255,255,255,0.2); |
| | backdrop-filter: blur(4px); |
| | box-shadow: 0 2px 8px rgba(0,0,0,0.1); |
| | "> |
| | <div style=" |
| | position: absolute; |
| | top: -{top_cut}px; |
| | left: -{left_cut}px; |
| | transform: scale({scale_factor}); |
| | transform-origin: top left; |
| | "> |
| | {svg_content} |
| | </div> |
| | </div> |
| | ''', |
| | unsafe_allow_html=True |
| | ) |
| |
|
| | with st.sidebar: |
| | |
| | st.markdown("<div style='height: 30px;'></div>", unsafe_allow_html=True) |
| |
|
| | st.markdown(""" |
| | <div style='text-align: center; margin-bottom: 0px;'> |
| | <h1>Your AI-Powered Rose-Colored Glasses</h1> |
| | </div> |
| | <p style=" |
| | text-align: center; |
| | margin-bottom: 20px; |
| | font-style: italic; |
| | font-family: Arial, sans-serif; |
| | "> |
| | We transform negativity into positive communication |
| | </p> |
| | <div style="padding-left: 30px;"> |
| | 1. Paste the harsh text<br> |
| | 2. Click <span style="font-weight: bold;">"✨ Kindify"</span><br> |
| | 3. Save the kinder version |
| | </div> |
| | """, unsafe_allow_html=True) |
| |
|
| |
|
| |
|
| | @st.cache_resource |
| | def load_model(model_name): |
| | model = AutoModelForSeq2SeqLM.from_pretrained(model_name) |
| | tokenizer = AutoTokenizer.from_pretrained(model_name) |
| | return model, tokenizer |
| |
|
| | model_name = "avo-milas/tox2kind" |
| | model, tokenizer = load_model(model_name) |
| | if 'history' not in st.session_state: |
| | st.session_state.history = [] |
| |
|
| |
|
| | col1, col2 = st.columns([3, 1]) |
| |
|
| | with col1: |
| |
|
| | query = st.text_area( |
| | "Your message:", |
| | value="This is absolute garbage. Do you even know what you’re doing? Rewrite it", |
| | placeholder="Enter the message here...", |
| | help="We’ll give this a cheerful twist", |
| | max_chars=300, |
| | height=100, |
| | key="user_input" |
| | ) |
| |
|
| | with col2: |
| |
|
| | st.markdown("<div style='height:28px'></div>", unsafe_allow_html=True) |
| | if st.button("✨ Kindify", |
| | use_container_width=True, |
| | type="secondary"): |
| | with st.spinner("Transforming..."): |
| | try: |
| |
|
| | inputs = tokenizer(query, return_tensors="pt", padding=True, truncation=True, max_length=32) |
| | with torch.no_grad(): |
| | outputs = model.generate( |
| | inputs['input_ids'], |
| | max_length=32, |
| | num_beams=5, |
| | do_sample=True, |
| | top_p=0.92, |
| | temperature=0.9, |
| | early_stopping=True |
| | ) |
| | |
| | result = tokenizer.decode(outputs[0], skip_special_tokens=True) |
| | |
| | st.session_state.history.append( |
| | (query, result) |
| | ) |
| |
|
| | |
| | |
| | except Exception as e: |
| | st.error(f"Error: {str(e)}") |
| |
|
| | if st.session_state.history: |
| | latest = st.session_state.history[-1] |
| | |
| | st.divider() |
| | st.subheader("Transformation Results") |
| | |
| | col1, col2 = st.columns(2) |
| | with col1: |
| | st.markdown("**Original Message**") |
| | st.warning(latest[0]) |
| | with col2: |
| | st.markdown("**Kind Version**") |
| | st.success(latest[1]) |
| |
|
| | if st.button("📋 Copy Kind Version", use_container_width=True): |
| | st.session_state.clipboard = latest[1] |
| | st.toast("Copied to clipboard!", icon="✔️") |
| |
|