CoolFace
Apppublic

JeCabrera/Perfect_Webinar_FrameWork

sourceHugging Facemitupdated 2y agoView on Hugging Face
0likes
app.py393 linesDownload Raw Back to root
1import streamlit as st2import google.generativeai as genai3import os4import time5from dotenv import load_dotenv6from styles import get_custom_css, get_response_html_wrapper7from formulas import offer_formulas, formula_formatting8import PyPDF29import docx10from PIL import Image11import io12 13# Import the bullet generator14from bullets.generator import create_bullet_instruction15# Import the bonus generator16from bonuses.generator import create_bonus_instruction17# Import the offer instruction generator18from prompts import create_offer_instruction19# Import sophistication levels20from sophistication import sophistication_levels21 22# Set page to wide mode to use full width23st.set_page_config(layout="wide")24 25# Load environment variables26load_dotenv()27 28# Configure Google Gemini API29genai.configure(api_key=os.getenv('GOOGLE_API_KEY'))30model = genai.GenerativeModel('gemini-2.0-flash')31 32# Initialize session state variables if they don't exist33if 'submitted' not in st.session_state:34    st.session_state.submitted = False35if 'offer_result' not in st.session_state:36    st.session_state.offer_result = ""37if 'generated' not in st.session_state:38    st.session_state.generated = False39 40# Hide Streamlit menu and footer41st.markdown("""42<style>43#MainMenu {visibility: hidden;}44footer {visibility: hidden;}45header {visibility: hidden;}46</style>47""", unsafe_allow_html=True)48 49# Custom CSS50st.markdown(get_custom_css(), unsafe_allow_html=True)51 52# App title and description53st.markdown('<h1 style="text-align: center;">Great Offer Generator</h1>', unsafe_allow_html=True)54st.markdown('<h3 style="text-align: center;">Transform your skills into compelling offers!</h3>', unsafe_allow_html=True)55 56# Create two columns for layout - left column 40%, right column 60%57col1, col2 = st.columns([4, 6])58 59# Main input section in left column60with col1:61    # Define the generate_offer function first62    def handle_generate_button():  # Renamed to avoid conflict63        has_manual_input = bool(skills or product_service)64        has_file_input = bool(uploaded_file is not None and not is_image)65        has_image_input = bool(uploaded_file is not None and is_image)66 67        # Simple validation - check if we have at least one input type68        if not (has_manual_input or has_file_input or has_image_input):69            st.error('Por favor ingresa texto o sube un archivo/imagen')70            return71        72        st.session_state.submitted = True73        st.session_state.generated = False  # Reset generated flag74        75        # Store inputs based on what's available76        if has_manual_input:77            st.session_state.skills = skills if skills else ""78            st.session_state.product_service = product_service if product_service else ""79        80        if has_file_input:81            st.session_state.file_content = file_content82            83        if has_image_input:84            st.session_state.image_parts = image_parts85        86        # Set input type based on what's available87        if has_image_input:88            if has_manual_input:89                st.session_state.input_type = "manual_image"90            else:91                st.session_state.input_type = "image"92        else:93            if has_manual_input and has_file_input:94                st.session_state.input_type = "both"95            elif has_file_input:96                st.session_state.input_type = "file"97            elif has_manual_input:98                st.session_state.input_type = "manual"99        100        # Store common settings101        st.session_state.target_audience = target_audience102        st.session_state.temperature = temperature103        st.session_state.formula_type = formula_type104        st.session_state.sophistication_level = sophistication_level105 106    # Keep only the manual input tab107    with st.container():108        skills = st.text_area('💪 Tus Habilidades', height=70, 109                            help='Lista tus habilidades y experiencia clave')110        product_service = st.text_area('🎯 Producto/Servicio', height=70,111                                    help='Describe tu producto o servicio')112        113        # Generate button moved here - right after product/service114        st.button('Generar Oferta 🎉', on_click=handle_generate_button)  # Updated function name115    116    # Accordion for additional settings117    with st.expander('⚙️ Configuración Avanzada'):118        target_audience = st.text_area('👥 Público Objetivo', height=70,119                                    help='Describe tu cliente o público ideal')120        121        # Add sophistication level selector122        sophistication_level = st.selectbox(123            '🧠 Nivel de Sofisticación del Mercado',124            options=list(sophistication_levels.keys()),125            help='Selecciona el nivel de conocimiento que tiene tu público sobre soluciones similares'126        )127        128        # Add file/image uploader here129        uploaded_file = st.file_uploader("📄 Sube un archivo o imagen", 130                                        type=['txt', 'pdf', 'docx', 'jpg', 'jpeg', 'png'])131        132        if uploaded_file is not None:133            file_type = uploaded_file.name.split('.')[-1].lower()134            135            # Handle text files136            if file_type in ['txt', 'pdf', 'docx']:137                if file_type == 'txt':138                    try:139                        file_content = uploaded_file.read().decode('utf-8')140                    except Exception as e:141                        st.error(f"Error al leer el archivo TXT: {str(e)}")142                        file_content = ""143                    144                elif file_type == 'pdf':145                    try:146                        import PyPDF2147                        pdf_reader = PyPDF2.PdfReader(uploaded_file)148                        file_content = ""149                        for page in pdf_reader.pages:150                            file_content += page.extract_text() + "\n"151                    except Exception as e:152                        st.error(f"Error al leer el archivo PDF: {str(e)}")153                        file_content = ""154                        155                elif file_type == 'docx':156                    try:157                        import docx158                        doc = docx.Document(uploaded_file)159                        file_content = "\n".join([para.text for para in doc.paragraphs])160                    except Exception as e:161                        st.error(f"Error al leer el archivo DOCX: {str(e)}")162                        file_content = ""163                164                # Remove success message - no notification shown165                166                # Set file type flag167                # Initialize is_image variable168                is_image = False169            170            # Handle image files171            elif file_type in ['jpg', 'jpeg', 'png']:172                try:173                    image = Image.open(uploaded_file)174                    st.image(image, caption="Imagen cargada", use_container_width=True)175                    176                    image_bytes = uploaded_file.getvalue()177                    image_parts = [178                        {179                            "mime_type": uploaded_file.type,180                            "data": image_bytes181                        }182                    ]183                    184                    # Set file type flag185                    is_image = True186                except Exception as e:187                    st.error(f"Error al procesar la imagen: {str(e)}")188                    is_image = False189        190        # Selector de fórmula191        formula_type = st.selectbox(192            '📋 Tipo de Fórmula',193            options=list(offer_formulas.keys()),194            help='Selecciona el tipo de fórmula para tu oferta'195        )196        197        temperature = st.slider('🌡️ Nivel de Creatividad', min_value=0.0, max_value=2.0, value=1.0,198                            help='Valores más altos hacen que el resultado sea más creativo pero menos enfocado')199 200# Results column201# In the section where you're generating the offer202with col2:203    if st.session_state.submitted and not st.session_state.generated:204        with st.spinner('Creando tu oferta perfecta...'):205            # Use the create_offer_instruction function to generate the prompt206            target_audience_value = st.session_state.target_audience if hasattr(st.session_state, 'target_audience') and st.session_state.target_audience else 'General audience'207            208            # Get product_service from session state or use the current value209            product_service_value = st.session_state.product_service if hasattr(st.session_state, 'product_service') and st.session_state.product_service else product_service210            211            # Get skills from session state or use empty string212            skills_value = st.session_state.skills if hasattr(st.session_state, 'skills') and st.session_state.skills else ""213                214            # Preparar el contenido del archivo si existe215            file_content = ""216            if hasattr(st.session_state, 'file_content') and st.session_state.input_type in ["file", "both"]:217                file_content = st.session_state.file_content218                219            # Preparar el contenido para los bullets y bonos220            bullet_content = None221            bonus_content = None222            if hasattr(st.session_state, 'file_content') and st.session_state.input_type in ["file", "both"]:223                bullet_content = st.session_state.file_content224                bonus_content = st.session_state.file_content225                226            # Get the instruction using the formula227            from prompts import create_integrated_instruction228            229            # Construir la instrucción integrada230            instruction = create_integrated_instruction(231                target_audience=target_audience_value,232                product_service=product_service_value,233                selected_formula_name=st.session_state.formula_type,234                file_content=file_content,235                bullet_content=bullet_content,236                bonus_content=bonus_content,  # Añadir parámetro explícito237                skills=skills_value,238                sophistication_level=st.session_state.sophistication_level if hasattr(st.session_state, 'sophistication_level') else None239            )240 241            # Validar componentes de la fórmula Contraste Revelador242            if formula_type == "Contraste Revelador":243                # Initialize variables with default empty values if they don't exist244                situacion = st.session_state.get('situacion', '')245                solucion = st.session_state.get('solucion', '')246                resultado = st.session_state.get('resultado', '')247                248                # Now perform your validation249                if situacion and not any(keyword in situacion for keyword in ["problema", "frustración", "dificultad", "obstáculo"]):250                    st.warning("La situación debe describir claramente un problema o frustración del público objetivo")251                252                # Continue with other validations253                if solucion and not solucion.isupper():254                    st.warning("La solución transformadora debe estar completamente en MAYÚSCULAS")255                256                if resultado and not any(char.isdigit() for char in resultado):257                    st.warning("El resultado emocional debe incluir algún número específico como prueba social")258 259            # Eliminar esta instrucción redundante para los bonos260            # La función create_integrated_instruction ya incluye las instrucciones para los bonos261            262            try:263                generation_config = genai.GenerationConfig(temperature=st.session_state.temperature)264                265                if "image" in st.session_state.input_type:266                    response = model.generate_content([instruction, st.session_state.image_parts[0]], generation_config=generation_config)267                else:268                    response = model.generate_content(instruction, generation_config=generation_config)269                270                # Get the response text271                response_text = response.text272                273                # Apply formatting to all formulas274                # Obtener la configuración de formato para la fórmula actual275                current_formula = st.session_state.formula_type276                format_config = formula_formatting.get(current_formula, {277                    "uppercase_lines": [],278                    "spacing": "single",279                    "product_integration": False,280                    "replace_terms": [],281                    "capitalize_first_only": []282                })283                284                # Aplicar formato según la configuración285                lines = response_text.split('\n')286                lines = [line.lstrip() for line in lines]  # Elimina espacios al inicio de cada línea287                288                # Aplicar mayúsculas a líneas específicas289                for line_index in format_config["uppercase_lines"]:290                    if line_index < len(lines):291                        lines[line_index] = lines[line_index].upper()292                293                # Aplicar capitalización solo a la primera letra en líneas específicas294                for line_index in format_config.get("capitalize_first_only", []):295                    if line_index < len(lines) and lines[line_index].strip():296                        # Convertir a minúsculas primero, luego capitalizar solo la primera letra297                        lines[line_index] = lines[line_index].lower()298                        lines[line_index] = lines[line_index][0].upper() + lines[line_index][1:]299                300                # Eliminar líneas en blanco extras301                lines = [line for line in lines if line.strip()]302                303                # Aplicar espaciado304                if format_config["spacing"] == "double":305                    response_text = '\n\n'.join(lines)306                else:307                    response_text = '\n'.join(lines)308                309                # Integrar nombre del producto si está configurado310                if format_config["product_integration"]:311                    # Verificar si el usuario proporcionó un nombre de producto312                    has_product_name = hasattr(st.session_state, 'product_service') and st.session_state.product_service313                    314                    # Si no hay nombre de producto pero el nivel de sofisticación es 3 o mayor, generar uno genérico315                    if not has_product_name and hasattr(st.session_state, 'sophistication_level'):316                        sophistication_level = st.session_state.sophistication_level317                        if sophistication_level and sophistication_level.startswith(('nivel_3', 'nivel_4', 'nivel_5')):318                            # Generar un nombre genérico basado en la industria o tema319                            industry = st.session_state.get('industry', '')320                            if industry:321                                if 'marketing' in industry.lower():322                                    product_service_value = "Sistema de Marketing Estratégico"323                                elif 'finanzas' in industry.lower() or 'inversión' in industry.lower():324                                    product_service_value = "Método de Inversión Inteligente"325                                elif 'salud' in industry.lower() or 'bienestar' in industry.lower():326                                    product_service_value = "Programa de Transformación Integral"327                                elif 'productividad' in industry.lower():328                                    product_service_value = "Sistema de Productividad Avanzada"329                                else:330                                    product_service_value = "Sistema Transformador"331                            else:332                                product_service_value = "Sistema Transformador"333                            334                            # Guardar el nombre generado para uso futuro335                            st.session_state.generated_product_name = product_service_value336                        else:337                            # Para niveles 1-2, no hacemos nada especial338                            # Simplemente usamos los términos genéricos que ya están en el texto339                            product_service_value = None340                    else:341                        # Usar el nombre proporcionado por el usuario342                        product_service_value = st.session_state.product_service if has_product_name else None343                    344                    # Procesar cada línea si tenemos un nombre de producto345                    # Solo hacemos reemplazos si hay un nombre de producto Y no estamos en nivel 1-2346                    # O si el usuario proporcionó explícitamente un nombre347                    if product_service_value:348                        lines = response_text.split('\n')349                        for i in range(len(lines)):350                            # Eliminar comillas alrededor del nombre del producto351                            lines[i] = lines[i].replace(f'"{product_service_value}"', product_service_value)352                            lines[i] = lines[i].replace(f"'{product_service_value}'", product_service_value)353                            354                            # Reemplazar términos genéricos con el nombre del producto355                            for term in format_config["replace_terms"]:356                                if term.lower() in lines[i].lower() and product_service_value.lower() not in lines[i].lower():357                                    lines[i] = lines[i].replace(term, product_service_value, 1)358                        359                        # Rejuntar las líneas con el espaciado adecuado360                        if format_config["spacing"] == "double":361                            response_text = '\n\n'.join(lines)362                        else:363                            response_text = '\n'.join(lines)364                365                st.session_state.offer_result = response_text366                st.session_state.generated = True  # Mark as generated367                368            except Exception as e:369                st.error(f'Ocurrió un error: {str(e)}')370                st.session_state.submitted = False371    372    # Display results if we have an offer result373    if st.session_state.generated:374        # Remove the visualization mode option375        376        # Display the formatted result directly377        st.markdown(get_response_html_wrapper(st.session_state.offer_result), unsafe_allow_html=True)378        379        # Add a small space380        st.markdown('<div style="height: 15px;"></div>', unsafe_allow_html=True)381        382        # Apply the custom button style before rendering the download button383        st.markdown('<style>div.stDownloadButton > button {your-custom-styles-here}</style>', unsafe_allow_html=True)384        st.download_button(385            label="Descargar Oferta",386            data=st.session_state.offer_result,387            file_name="oferta_generada.txt",388            mime="text/plain"389        )390 391# Footer392st.markdown('---')393st.markdown('Made with ❤️ by Jesús Cabrera')