Spaces:
				
			
			
	
			
			
		Sleeping
		
	
	
	
			
			
	
	
	
	
		
		
		Sleeping
		
	Update app.py
Browse files
    	
        app.py
    CHANGED
    
    | 
         @@ -1,12 +1,14 @@ 
     | 
|
| 1 | 
         
            -
            import streamlit as st
         
     | 
| 2 | 
         
             
            from dotenv import load_dotenv
         
     | 
| 
         | 
|
| 3 | 
         
             
            import os
         
     | 
| 4 | 
         
             
            import google.generativeai as genai
         
     | 
| 5 | 
         
            -
             
     | 
| 6 | 
         
            -
             
     | 
| 7 | 
         
            -
            from  
     | 
| 8 | 
         
            -
             
     | 
| 9 | 
         
            -
             
     | 
| 
         | 
|
| 
         | 
|
| 10 | 
         | 
| 11 | 
         
             
            # Cargar las variables de entorno
         
     | 
| 12 | 
         
             
            load_dotenv()
         
     | 
| 
         @@ -14,319 +16,509 @@ load_dotenv() 
     | 
|
| 14 | 
         
             
            # Configurar la API de Google
         
     | 
| 15 | 
         
             
            genai.configure(api_key=os.getenv("GOOGLE_API_KEY"))
         
     | 
| 16 | 
         | 
| 17 | 
         
            -
            #  
     | 
| 18 | 
         
            -
             
     | 
| 19 | 
         
            -
                 
     | 
| 20 | 
         
            -
             
     | 
| 21 | 
         
            -
                 
     | 
| 22 | 
         
            -
             
     | 
| 23 | 
         
            -
             
     | 
| 24 | 
         
            -
             
     | 
| 25 | 
         
            -
             
     | 
| 26 | 
         
            -
             
     | 
| 27 | 
         
            -
             
     | 
| 28 | 
         
            -
                 
     | 
| 29 | 
         
            -
             
     | 
| 30 | 
         
            -
             
     | 
| 31 | 
         
            -
             
     | 
| 32 | 
         
            -
                 
     | 
| 33 | 
         
            -
             
     | 
| 34 | 
         
            -
             
     | 
| 35 | 
         
            -
             
     | 
| 36 | 
         
            -
             
     | 
| 37 | 
         
            -
             
     | 
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 38 | 
         
             
                    "temperature": temperature,
         
     | 
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 39 | 
         
             
                }
         
     | 
| 40 | 
         
            -
                return genai.GenerativeModel('gemini-2.0-flash', generation_config=generation_config)
         
     | 
| 41 | 
         | 
| 42 | 
         
            -
            #  
     | 
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 43 | 
         | 
| 44 | 
         
            -
             
     | 
| 45 | 
         
            -
             
     | 
| 46 | 
         
            -
             
     | 
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 47 | 
         | 
| 48 | 
         
            -
                 
     | 
| 49 | 
         
            -
             
     | 
| 50 | 
         
            -
                     
     | 
| 51 | 
         
            -
             
     | 
| 52 | 
         
            -
             
     | 
| 53 | 
         
            -
             
     | 
| 54 | 
         
            -
             
     | 
| 55 | 
         
            -
             
     | 
| 56 | 
         
            -
             
     | 
| 57 | 
         
            -
             
     | 
| 58 | 
         
            -
             
     | 
| 59 | 
         
            -
             
     | 
| 60 | 
         
            -
             
     | 
| 61 | 
         
            -
             
     | 
| 62 | 
         
            -
             
     | 
| 63 | 
         
            -
                     
     | 
| 64 | 
         
            -
             
     | 
| 65 | 
         
            -
                    return f"Error al generar el perfil: {str(e)}"
         
     | 
| 66 | 
         
            -
             
     | 
| 67 | 
         
            -
            # Modificar la funci贸n update_profile para que no use spinner
         
     | 
| 68 | 
         
            -
            def update_profile():
         
     | 
| 69 | 
         
            -
                # Solo actualizar la variable de sesi贸n
         
     | 
| 70 | 
         
            -
                st.session_state.submitted = True
         
     | 
| 71 | 
         
            -
             
     | 
| 72 | 
         
            -
            # Leer el contenido del archivo manual.md si existe
         
     | 
| 73 | 
         
            -
            try:
         
     | 
| 74 | 
         
            -
                with open("manual.md", "r", encoding="utf-8") as file:
         
     | 
| 75 | 
         
            -
                    manual_content = file.read()
         
     | 
| 76 | 
         
            -
                # Mostrar el contenido del manual en el sidebar
         
     | 
| 77 | 
         
            -
                st.sidebar.markdown(manual_content)
         
     | 
| 78 | 
         
            -
            except FileNotFoundError:
         
     | 
| 79 | 
         
            -
                st.sidebar.warning("Manual not found. Please create a manual.md file.")
         
     | 
| 80 | 
         
            -
            except Exception as e:
         
     | 
| 81 | 
         
            -
                st.sidebar.error(f"Error loading manual: {str(e)}")
         
     | 
| 82 | 
         
            -
             
     | 
| 83 | 
         
            -
            # Ocultar elementos de la interfaz
         
     | 
| 84 | 
         
            -
            st.markdown(styles["main_layout"], unsafe_allow_html=True)
         
     | 
| 85 | 
         
            -
             
     | 
| 86 | 
         
            -
            # Centrar el t铆tulo y el subt铆tulo
         
     | 
| 87 | 
         
            -
            st.markdown("<h1 style='text-align: center;'>Generador de Perfil de Cliente Ideal</h1>", unsafe_allow_html=True)
         
     | 
| 88 | 
         
            -
            st.markdown("<h4 style='text-align: center;'>Crea un perfil detallado de tu cliente ideal basado en tu producto y habilidades.</h4>", unsafe_allow_html=True)
         
     | 
| 89 | 
         
            -
             
     | 
| 90 | 
         
            -
            # A帽adir CSS personalizado para el bot贸n
         
     | 
| 91 | 
         
            -
            st.markdown(styles["button"], unsafe_allow_html=True)
         
     | 
| 92 | 
         
            -
            # A帽adir CSS personalizado para el bot贸n de descarga
         
     | 
| 93 | 
         
            -
            st.markdown(styles["download_button"], unsafe_allow_html=True)
         
     | 
| 94 | 
         
            -
             
     | 
| 95 | 
         
            -
            # Crear columnas
         
     | 
| 96 | 
         
            -
            col1, col2 = st.columns([1, 2])  
         
     | 
| 97 | 
         
            -
             
     | 
| 98 | 
         
            -
            # Columna de entrada
         
     | 
| 99 | 
         
            -
            with col1:
         
     | 
| 100 | 
         
            -
                product = st.text_area("驴Qu茅 producto o servicio ofreces?", 
         
     | 
| 101 | 
         
            -
                                      value=st.session_state.producto,
         
     | 
| 102 | 
         
            -
                                      placeholder="Ejemplo: Curso de Ingl茅s",
         
     | 
| 103 | 
         
            -
                                      key="producto_input",
         
     | 
| 104 | 
         
            -
                                      height=70)
         
     | 
| 105 | 
         
            -
                st.session_state.producto = product
         
     | 
| 106 | 
         | 
| 107 | 
         
            -
                 
     | 
| 108 | 
         
            -
             
     | 
| 109 | 
         
            -
             
     | 
| 110 | 
         
            -
             
     | 
| 111 | 
         
            -
             
     | 
| 112 | 
         
            -
             
     | 
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 113 | 
         | 
| 114 | 
         
            -
                #  
     | 
| 115 | 
         
            -
                 
     | 
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 116 | 
         | 
| 117 | 
         
            -
                #  
     | 
| 118 | 
         
            -
                 
     | 
| 119 | 
         
            -
             
     | 
| 120 | 
         
            -
             
     | 
| 121 | 
         
            -
             
     | 
| 122 | 
         
            -
             
     | 
| 123 | 
         
            -
             
     | 
| 124 | 
         
            -
             
     | 
| 125 | 
         
            -
             
     | 
| 126 | 
         
            -
             
     | 
| 127 | 
         
            -
             
     | 
| 128 | 
         
            -
             
     | 
| 129 | 
         
            -
             
     | 
| 130 | 
         
            -
             
     | 
| 131 | 
         
            -
             
     | 
| 132 | 
         
            -
             
     | 
| 133 | 
         
            -
             
     | 
| 134 | 
         
            -
             
     | 
| 135 | 
         
            -
             
     | 
| 136 | 
         
            -
             
     | 
| 137 | 
         
            -
             
     | 
| 138 | 
         
            -
             
     | 
| 139 | 
         
            -
             
     | 
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 140 | 
         
             
                    )
         
     | 
| 141 | 
         
            -
                    st.session_state.formato = format_type
         
     | 
| 142 | 
         | 
| 143 | 
         
            -
                    #  
     | 
| 144 | 
         
            -
                     
     | 
| 145 | 
         
            -
                                           min_value=0.0, 
         
     | 
| 146 | 
         
            -
                                           max_value=2.0, 
         
     | 
| 147 | 
         
            -
                                           value=st.session_state.creatividad, 
         
     | 
| 148 | 
         
            -
                                           step=0.1,
         
     | 
| 149 | 
         
            -
                                           key="creatividad_slider")
         
     | 
| 150 | 
         
            -
                    st.session_state.creatividad = temperature
         
     | 
| 151 | 
         | 
| 152 | 
         
            -
                    #  
     | 
| 153 | 
         
            -
                     
     | 
| 154 | 
         
            -
             
     | 
| 155 | 
         
            -
                        # Replace underscores with spaces in the key
         
     | 
| 156 | 
         
            -
                        display_name = key.replace("_", " ")
         
     | 
| 157 | 
         
            -
                        consciousness_options.append(f"Nivel {i} - {display_name}")
         
     | 
| 158 | 
         | 
| 159 | 
         
            -
                     
     | 
| 160 | 
         
            -
             
     | 
| 161 | 
         
            -
             
     | 
| 162 | 
         
            -
             
     | 
| 163 | 
         
            -
             
     | 
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 164 | 
         
             
                    )
         
     | 
| 165 | 
         | 
| 166 | 
         
            -
                     
     | 
| 167 | 
         
            -
                    level_number = nivel_conciencia_display.split(" - ")[0].replace("Nivel ", "")
         
     | 
| 168 | 
         
            -
                    original_key = list(CONSCIOUSNESS_LEVELS.keys())[int(level_number) - 1]
         
     | 
| 169 | 
         
            -
                    nivel_conciencia = original_key.replace("_", " ")
         
     | 
| 170 | 
         | 
| 171 | 
         
            -
                    #  
     | 
| 172 | 
         
            -
                     
     | 
| 173 | 
         
            -
             
     | 
| 174 | 
         
            -
             
     | 
| 175 | 
         
            -
             
     | 
| 176 | 
         
            -
             
     | 
| 177 | 
         
            -
             
     | 
| 178 | 
         
            -
            #  
     | 
| 179 | 
         
            -
             
     | 
| 180 | 
         
            -
             
     | 
| 181 | 
         
            -
             
     | 
| 182 | 
         
            -
             
     | 
| 183 | 
         
            -
             
     | 
| 184 | 
         
            -
             
     | 
| 185 | 
         
            -
             
     | 
| 186 | 
         
            -
             
     | 
| 187 | 
         
            -
             
     | 
| 188 | 
         
            -
             
     | 
| 189 | 
         
            -
             
     | 
| 190 | 
         
            -
             
     | 
| 191 | 
         
            -
             
     | 
| 192 | 
         
            -
             
     | 
| 193 | 
         
            -
             
     | 
| 194 | 
         
            -
             
     | 
| 195 | 
         
            -
             
     | 
| 196 | 
         
            -
             
     | 
| 197 | 
         
            -
             
     | 
| 198 | 
         
            -
             
     | 
| 199 | 
         
            -
             
     | 
| 200 | 
         
            -
             
     | 
| 201 | 
         
            -
             
     | 
| 202 | 
         
            -
             
     | 
| 203 | 
         
            -
             
     | 
| 204 | 
         
            -
                                 
     | 
| 205 | 
         
            -
                                     
     | 
| 206 | 
         
            -
             
     | 
| 207 | 
         
            -
             
     | 
| 208 | 
         
            -
             
     | 
| 209 | 
         
            -
             
     | 
| 210 | 
         
            -
             
     | 
| 211 | 
         
            -
                                         
     | 
| 212 | 
         
            -
             
     | 
| 213 | 
         
            -
             
     | 
| 214 | 
         
            -
             
     | 
| 215 | 
         
            -
             
     | 
| 216 | 
         
            -
             
     | 
| 217 | 
         
            -
                                                pass
         
     | 
| 218 | 
         
            -
                                    
         
     | 
| 219 | 
         
            -
                                    # Limpiar l铆neas que parecen ser parte de un diccionario
         
     | 
| 220 | 
         
            -
                                    lines = buyer_persona.split('\n')
         
     | 
| 221 | 
         
            -
                                    cleaned_lines = []
         
     | 
| 222 | 
         
            -
                                    for line in lines:
         
     | 
| 223 | 
         
            -
                                        # Omitir l铆neas que parecen ser claves de diccionario
         
     | 
| 224 | 
         
            -
                                        if not re.match(r'^\s*["\']?[a-zA-Z_]+["\']?\s*:', line):
         
     | 
| 225 | 
         
            -
                                            cleaned_lines.append(line)
         
     | 
| 226 | 
         
            -
                                    
         
     | 
| 227 | 
         
            -
                                    buyer_persona = '\n'.join(cleaned_lines)
         
     | 
| 228 | 
         
            -
                                    
         
     | 
| 229 | 
         
            -
                                    # Eliminar llaves sueltas y corchetes
         
     | 
| 230 | 
         
            -
                                    buyer_persona = re.sub(r'[{}[\]]', '', buyer_persona)
         
     | 
| 231 | 
         
            -
                                    
         
     | 
| 232 | 
         
            -
                                    # Eliminar comillas y dos puntos que parecen ser de un diccionario
         
     | 
| 233 | 
         
            -
                                    buyer_persona = re.sub(r'["\']\s*:\s*["\']', '', buyer_persona)
         
     | 
| 234 | 
         
            -
                                    
         
     | 
| 235 | 
         
            -
                                    # Eliminar "template", "description", "example" y otras palabras clave comunes en el formato
         
     | 
| 236 | 
         
            -
                                    keywords = ["template", "description", "example", "Nivel de conciencia"]
         
     | 
| 237 | 
         
            -
                                    for keyword in keywords:
         
     | 
| 238 | 
         
            -
                                        buyer_persona = re.sub(rf'["\']?{keyword}["\']?\s*:\s*["\']?', '', buyer_persona)
         
     | 
| 239 | 
         
            -
                                    
         
     | 
| 240 | 
         
            -
                                    # Eliminar comillas sueltas
         
     | 
| 241 | 
         
            -
                                    buyer_persona = re.sub(r'^\s*["\']|["\']$', '', buyer_persona)
         
     | 
| 242 | 
         
            -
                                
         
     | 
| 243 | 
         
            -
                                # Normalizar espacios en blanco y sangr铆as
         
     | 
| 244 | 
         
            -
                                lines = buyer_persona.split('\n')
         
     | 
| 245 | 
         
            -
                                cleaned_lines = []
         
     | 
| 246 | 
         
            -
                                for line in lines:
         
     | 
| 247 | 
         
            -
                                    # Eliminar sangr铆as excesivas pero mantener estructura b谩sica
         
     | 
| 248 | 
         
            -
                                    cleaned_line = line.strip()
         
     | 
| 249 | 
         
            -
                                    if cleaned_line:  # Solo agregar l铆neas no vac铆as
         
     | 
| 250 | 
         
            -
                                        cleaned_lines.append(cleaned_line)
         
     | 
| 251 | 
         
            -
                                
         
     | 
| 252 | 
         
            -
                                # Unir las l铆neas con saltos de l铆nea adecuados
         
     | 
| 253 | 
         
            -
                                buyer_persona = '\n'.join(cleaned_lines)
         
     | 
| 254 | 
         
            -
                                
         
     | 
| 255 | 
         
            -
                                # Eliminar espacios en blanco adicionales
         
     | 
| 256 | 
         
            -
                                buyer_persona = re.sub(r'\n\s*\n', '\n\n', buyer_persona)
         
     | 
| 257 | 
         
            -
                                buyer_persona = buyer_persona.strip()
         
     | 
| 258 | 
         
            -
                                
         
     | 
| 259 | 
         
            -
                                # Al inicio del archivo, junto con las otras inicializaciones
         
     | 
| 260 | 
         
            -
                                if 'perfil_cliente_plain' not in st.session_state:
         
     | 
| 261 | 
         
            -
                                    st.session_state.perfil_cliente_plain = None
         
     | 
| 262 | 
         
            -
                                
         
     | 
| 263 | 
         
            -
                                # Guardar versi贸n sin formato antes de aplicar estilos HTML
         
     | 
| 264 | 
         
            -
                                st.session_state.perfil_cliente_plain = buyer_persona
         
     | 
| 265 | 
         
            -
                                
         
     | 
| 266 | 
         
            -
                                # Convertir los asteriscos de formato Markdown a HTML para una correcta visualizaci贸n
         
     | 
| 267 | 
         
            -
                                # Convertir **texto** a <strong>texto</strong>
         
     | 
| 268 | 
         
            -
                                buyer_persona = re.sub(r'\*\*(.*?)\*\*', r'<strong>\1</strong>', buyer_persona)
         
     | 
| 269 | 
         
            -
                                # Convertir *texto* a <em>texto</em>
         
     | 
| 270 | 
         
            -
                                buyer_persona = re.sub(r'\*(.*?)\*', r'<em>\1</em>', buyer_persona)
         
     | 
| 271 | 
         
            -
                                
         
     | 
| 272 | 
         
            -
                                # Mejorar el formato HTML para una mejor visualizaci贸n
         
     | 
| 273 | 
         
            -
                                buyer_persona = """
         
     | 
| 274 | 
         
            -
                                <div style="line-height: 1.3; text-align: left;">
         
     | 
| 275 | 
         
            -
                                    {}
         
     | 
| 276 | 
         
            -
                                </div>
         
     | 
| 277 | 
         
            -
                                """.format(buyer_persona.replace('\n', '<br><br>'))
         
     | 
| 278 | 
         
            -
                            
         
     | 
| 279 | 
         
            -
                            # Guardar en session_state
         
     | 
| 280 | 
         
            -
                            st.session_state.perfil_cliente = buyer_persona
         
     | 
| 281 | 
         
            -
                            # Resetear el estado de env铆o
         
     | 
| 282 | 
         
            -
                            st.session_state.submitted = False
         
     | 
| 283 | 
         
            -
                            
         
     | 
| 284 | 
         
            -
                        # Mostrar resultados
         
     | 
| 285 | 
         
            -
                        if not isinstance(st.session_state.perfil_cliente, str):
         
     | 
| 286 | 
         
            -
                            st.error("Error al generar el perfil de cliente ideal")
         
     | 
| 287 | 
         
            -
                        else:
         
     | 
| 288 | 
         
            -
                            # Crear un contenedor para el resultado
         
     | 
| 289 | 
         
            -
                            result_container = st.container()
         
     | 
| 290 | 
         
            -
                            
         
     | 
| 291 | 
         
            -
                            # Aplicar estilos del contenedor
         
     | 
| 292 | 
         
            -
                            st.markdown(styles["results_container"], unsafe_allow_html=True)
         
     | 
| 293 | 
         
            -
                            
         
     | 
| 294 | 
         
            -
                            with result_container:
         
     | 
| 295 | 
         
            -
                                # Mostrar el t铆tulo
         
     | 
| 296 | 
         
            -
                                st.markdown("<div class='results-title'>Tu Cliente Ideal</div>", unsafe_allow_html=True)
         
     | 
| 297 | 
         
            -
                                
         
     | 
| 298 | 
         
            -
                                # Mostrar el contenido como HTML para asegurar el formato correcto
         
     | 
| 299 | 
         
            -
                                st.markdown(st.session_state.perfil_cliente, unsafe_allow_html=True)
         
     | 
| 300 | 
         
            -
                            
         
     | 
| 301 | 
         
            -
                            # Opci贸n para descargar
         
     | 
| 302 | 
         
            -
                            # En la secci贸n de descarga anterior, asegurarse de usar la versi贸n plain si existe
         
     | 
| 303 | 
         
            -
                            st.download_button(
         
     | 
| 304 | 
         
            -
                                label="DESCARGAR MI CLIENTE SO脩ADO 鉃も灓",
         
     | 
| 305 | 
         
            -
                                data=st.session_state.perfil_cliente_plain if st.session_state.perfil_cliente_plain else st.session_state.perfil_cliente,
         
     | 
| 306 | 
         
            -
                                file_name="cliente_ideal.txt",
         
     | 
| 307 | 
         
            -
                                mime="text/plain"
         
     | 
| 308 | 
         
            -
                            )
         
     | 
| 309 | 
         
             
                    else:
         
     | 
| 310 | 
         
            -
                         
     | 
| 311 | 
         
            -
             
     | 
| 312 | 
         
            -
                elif st.session_state.perfil_cliente:
         
     | 
| 313 | 
         
            -
                    # Crear un contenedor para el resultado
         
     | 
| 314 | 
         
            -
                    result_container = st.container()
         
     | 
| 315 | 
         
            -
                    
         
     | 
| 316 | 
         
            -
                    # Aplicar estilos del contenedor
         
     | 
| 317 | 
         
            -
                    st.markdown(styles["results_container"], unsafe_allow_html=True)
         
     | 
| 318 | 
         
            -
                    
         
     | 
| 319 | 
         
            -
                    with result_container:
         
     | 
| 320 | 
         
            -
                        # Mostrar el t铆tulo
         
     | 
| 321 | 
         
            -
                        st.markdown("<div class='results-title'>Tu Cliente Ideal</div>", unsafe_allow_html=True)
         
     | 
| 322 | 
         
            -
                        
         
     | 
| 323 | 
         
            -
                        # Mostrar el contenido como HTML para asegurar el formato correcto
         
     | 
| 324 | 
         
            -
                        st.markdown(st.session_state.perfil_cliente, unsafe_allow_html=True)
         
     | 
| 325 | 
         
            -
                    
         
     | 
| 326 | 
         
            -
                    # Opci贸n para descargar
         
     | 
| 327 | 
         
            -
                    st.download_button(
         
     | 
| 328 | 
         
            -
                        label="DESCARGAR MI CLIENTE SO脩ADO 鉃も灓",
         
     | 
| 329 | 
         
            -
                        data=st.session_state.perfil_cliente,
         
     | 
| 330 | 
         
            -
                        file_name="cliente_ideal.txt",
         
     | 
| 331 | 
         
            -
                        mime="text/plain"
         
     | 
| 332 | 
         
            -
                    )
         
     | 
| 
         | 
|
| 
         | 
|
| 1 | 
         
             
            from dotenv import load_dotenv
         
     | 
| 2 | 
         
            +
            import streamlit as st
         
     | 
| 3 | 
         
             
            import os
         
     | 
| 4 | 
         
             
            import google.generativeai as genai
         
     | 
| 5 | 
         
            +
            import random
         
     | 
| 6 | 
         
            +
            import datetime                    
         
     | 
| 7 | 
         
            +
            from streamlit import session_state as state
         
     | 
| 8 | 
         
            +
            from angles import angles
         
     | 
| 9 | 
         
            +
            from formulas.webinar_formulas import webinar_formulas
         
     | 
| 10 | 
         
            +
            from formulas.webinar_name_formulas import webinar_name_formulas
         
     | 
| 11 | 
         
            +
            from formulas.angles_webinar_names import angles_webinar_names
         
     | 
| 12 | 
         | 
| 13 | 
         
             
            # Cargar las variables de entorno
         
     | 
| 14 | 
         
             
            load_dotenv()
         
     | 
| 
         | 
|
| 16 | 
         
             
            # Configurar la API de Google
         
     | 
| 17 | 
         
             
            genai.configure(api_key=os.getenv("GOOGLE_API_KEY"))
         
     | 
| 18 | 
         | 
| 19 | 
         
            +
            # Create a reusable function for the UI input section
         
     | 
| 20 | 
         
            +
            def create_input_section(col, audience_key, product_key, formula_options, formula_key):
         
     | 
| 21 | 
         
            +
                audience = col.text_input("驴Qui茅n es tu p煤blico objetivo?", placeholder="Ejemplo: Emprendedores digitales", key=audience_key)
         
     | 
| 22 | 
         
            +
                product = col.text_input("驴Sobre qu茅 tema es tu webinar?", placeholder="Ejemplo: Marketing en redes sociales", key=product_key)
         
     | 
| 23 | 
         
            +
                
         
     | 
| 24 | 
         
            +
                selected_formula_key = col.selectbox(
         
     | 
| 25 | 
         
            +
                    "Selecciona un framework de webinar" if "script" in audience_key else "Selecciona una f贸rmula para tus nombres de webinar",
         
     | 
| 26 | 
         
            +
                    options=list(formula_options.keys()),
         
     | 
| 27 | 
         
            +
                    key=formula_key
         
     | 
| 28 | 
         
            +
                )
         
     | 
| 29 | 
         
            +
                
         
     | 
| 30 | 
         
            +
                return audience, product, selected_formula_key
         
     | 
| 31 | 
         
            +
             
     | 
| 32 | 
         
            +
            # Create a reusable function for generation and display
         
     | 
| 33 | 
         
            +
            def generate_and_display(col, generator_func, audience, product, temperature, selected_formula, **kwargs):
         
     | 
| 34 | 
         
            +
                if validate_inputs(audience, product):
         
     | 
| 35 | 
         
            +
                    try:
         
     | 
| 36 | 
         
            +
                        with col:
         
     | 
| 37 | 
         
            +
                            with st.spinner("Generando contenido...", show_time=True):
         
     | 
| 38 | 
         
            +
                                # Extract only the parameters that the generator function accepts
         
     | 
| 39 | 
         
            +
                                if generator_func.__name__ == "generate_webinar_script":
         
     | 
| 40 | 
         
            +
                                    generated_content = generator_func(
         
     | 
| 41 | 
         
            +
                                        audience=audience,
         
     | 
| 42 | 
         
            +
                                        topic=product,
         
     | 
| 43 | 
         
            +
                                        temperature=temperature,
         
     | 
| 44 | 
         
            +
                                        selected_formula=selected_formula
         
     | 
| 45 | 
         
            +
                                    )
         
     | 
| 46 | 
         
            +
                                else:
         
     | 
| 47 | 
         
            +
                                    generated_content = generator_func(
         
     | 
| 48 | 
         
            +
                                        audience=audience,
         
     | 
| 49 | 
         
            +
                                        topic=product,
         
     | 
| 50 | 
         
            +
                                        temperature=temperature,
         
     | 
| 51 | 
         
            +
                                        selected_formula=selected_formula,
         
     | 
| 52 | 
         
            +
                                        **kwargs
         
     | 
| 53 | 
         
            +
                                    )
         
     | 
| 54 | 
         
            +
                            
         
     | 
| 55 | 
         
            +
                            # For webinar scripts, add download buttons
         
     | 
| 56 | 
         
            +
                            if "script" in kwargs.get("content_type", ""):
         
     | 
| 57 | 
         
            +
                                timestamp = datetime.datetime.now().strftime("%Y%m%d_%H%M%S")
         
     | 
| 58 | 
         
            +
                                st.download_button(
         
     | 
| 59 | 
         
            +
                                    label="DESCARGAR GUION DE MI WEBINAR",
         
     | 
| 60 | 
         
            +
                                    data=generated_content,
         
     | 
| 61 | 
         
            +
                                    file_name=f"guion_webinar_{timestamp}.md",
         
     | 
| 62 | 
         
            +
                                    mime="text/markdown",
         
     | 
| 63 | 
         
            +
                                    key="download_top"
         
     | 
| 64 | 
         
            +
                                )
         
     | 
| 65 | 
         
            +
                            
         
     | 
| 66 | 
         
            +
                            st.subheader("Tu " + ("gui贸n de webinar:" if "script" in kwargs.get("content_type", "") else "nombres de webinar:"))
         
     | 
| 67 | 
         
            +
                            st.markdown(generated_content)
         
     | 
| 68 | 
         
            +
                            
         
     | 
| 69 | 
         
            +
                            # Add bottom download button for scripts
         
     | 
| 70 | 
         
            +
                            if "script" in kwargs.get("content_type", ""):
         
     | 
| 71 | 
         
            +
                                st.download_button(
         
     | 
| 72 | 
         
            +
                                    label="DESCARGAR GUION DE MI WEBINAR",
         
     | 
| 73 | 
         
            +
                                    data=generated_content,
         
     | 
| 74 | 
         
            +
                                    file_name=f"guion_webinar_{timestamp}.md",
         
     | 
| 75 | 
         
            +
                                    mime="text/markdown",
         
     | 
| 76 | 
         
            +
                                    key="download_bottom"
         
     | 
| 77 | 
         
            +
                                )
         
     | 
| 78 | 
         
            +
                    except ValueError as e:
         
     | 
| 79 | 
         
            +
                        col.error(f"Error: {str(e)}")
         
     | 
| 80 | 
         
            +
                else:
         
     | 
| 81 | 
         
            +
                    col.error("Por favor, proporciona el p煤blico objetivo y el tema del webinar.")
         
     | 
| 82 | 
         
            +
             
     | 
| 83 | 
         
            +
            # Funci贸n para crear la configuraci贸n del modelo (evita duplicaci贸n)
         
     | 
| 84 | 
         
            +
            def create_model_config(temperature):
         
     | 
| 85 | 
         
            +
                return {
         
     | 
| 86 | 
         
             
                    "temperature": temperature,
         
     | 
| 87 | 
         
            +
                    "top_p": 0.65,
         
     | 
| 88 | 
         
            +
                    "top_k": 360,
         
     | 
| 89 | 
         
            +
                    "max_output_tokens": 8196,
         
     | 
| 90 | 
         
             
                }
         
     | 
| 
         | 
|
| 91 | 
         | 
| 92 | 
         
            +
            # Funci贸n para inicializar el modelo
         
     | 
| 93 | 
         
            +
            def initialize_model(temperature):
         
     | 
| 94 | 
         
            +
                config = create_model_config(temperature)
         
     | 
| 95 | 
         
            +
                return genai.GenerativeModel(
         
     | 
| 96 | 
         
            +
                    model_name="gemini-2.0-flash",
         
     | 
| 97 | 
         
            +
                    generation_config=config,
         
     | 
| 98 | 
         
            +
                )
         
     | 
| 99 | 
         
            +
             
     | 
| 100 | 
         
            +
            # Refactored model interaction function to reduce duplication
         
     | 
| 101 | 
         
            +
            def generate_content(prompt_instructions, temperature):
         
     | 
| 102 | 
         
            +
                model = initialize_model(temperature)
         
     | 
| 103 | 
         
            +
                chat_session = model.start_chat(
         
     | 
| 104 | 
         
            +
                    history=[
         
     | 
| 105 | 
         
            +
                        {
         
     | 
| 106 | 
         
            +
                            "role": "user",
         
     | 
| 107 | 
         
            +
                            "parts": [prompt_instructions],
         
     | 
| 108 | 
         
            +
                        },
         
     | 
| 109 | 
         
            +
                    ]
         
     | 
| 110 | 
         
            +
                )
         
     | 
| 111 | 
         
            +
                response = chat_session.send_message("Generate the content following exactly the provided instructions. All content must be in Spanish.")
         
     | 
| 112 | 
         
            +
                return response.text
         
     | 
| 113 | 
         | 
| 114 | 
         
            +
            # Funci贸n para generar nombres de webinars
         
     | 
| 115 | 
         
            +
            def generate_webinar_names(number_of_names, target_audience, product, temperature, selected_formula, selected_angle=None):
         
     | 
| 116 | 
         
            +
                # Incluir las instrucciones del sistema en el prompt principal
         
     | 
| 117 | 
         
            +
                system_prompt = """You are a world-class copywriter, with expertise in crafting compelling webinar titles that immediately capture the audience's attention and drive registrations.
         
     | 
| 118 | 
         
            +
             
     | 
| 119 | 
         
            +
            FORMAT RULES:
         
     | 
| 120 | 
         
            +
            - Each webinar name must start with number and period
         
     | 
| 121 | 
         
            +
            - One webinar name per line
         
     | 
| 122 | 
         
            +
            - No explanations or categories
         
     | 
| 123 | 
         
            +
            - Add a line break between each name
         
     | 
| 124 | 
         
            +
            - Avoid unnecessary : symbols
         
     | 
| 125 | 
         
            +
            - Each webinar name must be a complete and intriguing title
         
     | 
| 126 | 
         
            +
            - WRITE ALL WEBINAR NAMES IN SPANISH
         
     | 
| 127 | 
         
            +
             
     | 
| 128 | 
         
            +
            FORMAT EXAMPLE:
         
     | 
| 129 | 
         
            +
            1. Nombre del Webinar 1.
         
     | 
| 130 | 
         
            +
             
     | 
| 131 | 
         
            +
            2. Nombre del Webinar 2.
         
     | 
| 132 | 
         
            +
             
     | 
| 133 | 
         
            +
            3. Nombre del Webinar 3.
         
     | 
| 134 | 
         
            +
             
     | 
| 135 | 
         
            +
            4. Nombre del Webinar 4.
         
     | 
| 136 | 
         
            +
             
     | 
| 137 | 
         
            +
            5. Nombre del Webinar 5.
         
     | 
| 138 | 
         
            +
             
     | 
| 139 | 
         
            +
            IMPORTANT:
         
     | 
| 140 | 
         
            +
            - Each webinar name must be unique and memorable
         
     | 
| 141 | 
         
            +
            - Avoid clich茅s and generalities
         
     | 
| 142 | 
         
            +
            - Maintain an intriguing but credible tone
         
     | 
| 143 | 
         
            +
            - Adapt speaking language from the audience
         
     | 
| 144 | 
         
            +
            - Focus on transformative benefits
         
     | 
| 145 | 
         
            +
            - Follow the selected formula structure
         
     | 
| 146 | 
         
            +
            - WRITE ALL WEBINAR NAMES IN SPANISH"""
         
     | 
| 147 | 
         
            +
             
     | 
| 148 | 
         
            +
                # Iniciar el prompt con las instrucciones del sistema
         
     | 
| 149 | 
         
            +
                webinar_names_instruction = f"{system_prompt}\n\n"
         
     | 
| 150 | 
         | 
| 151 | 
         
            +
                # A帽adir instrucciones de 谩ngulo solo si no es "NINGUNO" y se proporcion贸 un 谩ngulo
         
     | 
| 152 | 
         
            +
                if selected_angle and selected_angle != "NINGUNO":
         
     | 
| 153 | 
         
            +
                    webinar_names_instruction += f"""
         
     | 
| 154 | 
         
            +
            MAIN ANGLE: {selected_angle}
         
     | 
| 155 | 
         
            +
            SPECIFIC ANGLE INSTRUCTIONS:
         
     | 
| 156 | 
         
            +
            {angles_webinar_names[selected_angle]["instruction"]}
         
     | 
| 157 | 
         
            +
             
     | 
| 158 | 
         
            +
            IMPORTANT: The {selected_angle} angle should be applied as a "style layer" over the formula structure:
         
     | 
| 159 | 
         
            +
            1. Keep the base structure of the formula intact
         
     | 
| 160 | 
         
            +
            2. Apply the tone and style of the {selected_angle} angle
         
     | 
| 161 | 
         
            +
            3. Ensure that each element of the formula reflects the angle
         
     | 
| 162 | 
         
            +
            4. The angle affects "how" it is said, not "what" is said
         
     | 
| 163 | 
         
            +
             
     | 
| 164 | 
         
            +
            SUCCESSFUL EXAMPLES OF THE {selected_angle} ANGLE:
         
     | 
| 165 | 
         
            +
            """
         
     | 
| 166 | 
         
            +
                    for example in angles_webinar_names[selected_angle]["examples"]:
         
     | 
| 167 | 
         
            +
                        webinar_names_instruction += f"- {example}\n"
         
     | 
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 168 | 
         | 
| 169 | 
         
            +
                # Instrucciones espec铆ficas para la tarea
         
     | 
| 170 | 
         
            +
                webinar_names_instruction += (
         
     | 
| 171 | 
         
            +
                    f"\nYour task is to create {number_of_names} irresistible webinar names for {target_audience} "
         
     | 
| 172 | 
         
            +
                    f"that instantly capture attention and generate registrations for a webinar about {product}. "
         
     | 
| 173 | 
         
            +
                    f"Focus on awakening genuine interest and communicating the value they will get by registering."
         
     | 
| 174 | 
         
            +
                    f"\n\n"
         
     | 
| 175 | 
         
            +
                    f"IMPORTANT: Carefully study these examples of the selected formula. "
         
     | 
| 176 | 
         
            +
                    f"Each example represents the style and structure to follow"
         
     | 
| 177 | 
         
            +
                    f":\n\n"
         
     | 
| 178 | 
         
            +
                )
         
     | 
| 179 | 
         | 
| 180 | 
         
            +
                # Agregar ejemplos aleatorios de la f贸rmula (keeping examples in Spanish)
         
     | 
| 181 | 
         
            +
                random_examples = random.sample(selected_formula['examples'], min(5, len(selected_formula['examples'])))
         
     | 
| 182 | 
         
            +
                webinar_names_instruction += "EXAMPLES OF THE FORMULA TO FOLLOW:\n"
         
     | 
| 183 | 
         
            +
                for i, example in enumerate(random_examples, 1):
         
     | 
| 184 | 
         
            +
                    webinar_names_instruction += f"{i}. {example}\n"
         
     | 
| 185 | 
         | 
| 186 | 
         
            +
                # Instrucciones espec铆ficas (translated to English)
         
     | 
| 187 | 
         
            +
                webinar_names_instruction += "\nSPECIFIC INSTRUCTIONS:\n"
         
     | 
| 188 | 
         
            +
                webinar_names_instruction += "1. Maintain the same structure and length as the previous examples\n"
         
     | 
| 189 | 
         
            +
                webinar_names_instruction += "2. Use the same tone and writing style\n"
         
     | 
| 190 | 
         
            +
                webinar_names_instruction += "3. Replicate the phrase construction patterns\n"
         
     | 
| 191 | 
         
            +
                webinar_names_instruction += "4. Preserve the level of specificity and detail\n"
         
     | 
| 192 | 
         
            +
                webinar_names_instruction += f"5. Adapt the content for {target_audience} while maintaining the essence of the examples\n\n"
         
     | 
| 193 | 
         
            +
                webinar_names_instruction += f"FORMULA TO FOLLOW:\n{selected_formula['description']}\n\n"
         
     | 
| 194 | 
         
            +
                webinar_names_instruction += f"""
         
     | 
| 195 | 
         
            +
            GENERATE NOW:
         
     | 
| 196 | 
         
            +
            Create {number_of_names} webinar names that faithfully follow the style and structure of the examples shown.
         
     | 
| 197 | 
         
            +
            """
         
     | 
| 198 | 
         
            +
             
     | 
| 199 | 
         
            +
                # Enviar el mensaje al modelo
         
     | 
| 200 | 
         
            +
                # Use the common generate_content function
         
     | 
| 201 | 
         
            +
                return generate_content(webinar_names_instruction, temperature)
         
     | 
| 202 | 
         
            +
             
     | 
| 203 | 
         
            +
            def generate_webinar_script(audience, topic, temperature, selected_formula):
         
     | 
| 204 | 
         
            +
                model = initialize_model(temperature)
         
     | 
| 205 | 
         
            +
                
         
     | 
| 206 | 
         
            +
                # Incluir las instrucciones del sistema en el prompt principal
         
     | 
| 207 | 
         
            +
                system_prompt = f"""You are a collaborative team of world-class experts working together to create an exceptional webinar script that converts audience into customers.
         
     | 
| 208 | 
         
            +
             
     | 
| 209 | 
         
            +
            THE EXPERT TEAM:
         
     | 
| 210 | 
         
            +
             
     | 
| 211 | 
         
            +
            1. MASTER WEBINAR STRATEGIST:
         
     | 
| 212 | 
         
            +
               - Expert in webinar frameworks and conversion strategies
         
     | 
| 213 | 
         
            +
               - Trained in the Perfect Webinar methodology by Russell Brunson
         
     | 
| 214 | 
         
            +
               - Ensures the script follows the selected framework structure precisely
         
     | 
| 215 | 
         
            +
               - Focuses on strategic placement of key conversion elements
         
     | 
| 216 | 
         
            +
             
     | 
| 217 | 
         
            +
            2. ELITE DIRECT RESPONSE COPYWRITER:
         
     | 
| 218 | 
         
            +
               - Trained by Gary Halbert, Gary Bencivenga, and David Ogilvy
         
     | 
| 219 | 
         
            +
               - Creates compelling hooks, stories, and persuasive elements
         
     | 
| 220 | 
         
            +
               - Crafts irresistible calls to action that drive conversions
         
     | 
| 221 | 
         
            +
               - Ensures the language resonates with the target audience
         
     | 
| 222 | 
         
            +
             
     | 
| 223 | 
         
            +
            3. AUDIENCE PSYCHOLOGY SPECIALIST:
         
     | 
| 224 | 
         
            +
               - Expert in understanding audience motivations and objections
         
     | 
| 225 | 
         
            +
               - Creates content that builds genuine connection and trust
         
     | 
| 226 | 
         
            +
               - Identifies and addresses hidden fears and desires
         
     | 
| 227 | 
         
            +
               - Ensures the content feels personal and relevant
         
     | 
| 228 | 
         
            +
             
     | 
| 229 | 
         
            +
            4. STORYTELLING MASTER:
         
     | 
| 230 | 
         
            +
               - Creates compelling narratives that illustrate key points
         
     | 
| 231 | 
         
            +
               - Develops relatable examples and case studies
         
     | 
| 232 | 
         
            +
               - Ensures stories support the transformation being offered
         
     | 
| 233 | 
         
            +
               - Makes complex concepts accessible through narrative
         
     | 
| 234 | 
         
            +
             
     | 
| 235 | 
         
            +
            5. WEBINAR ENGAGEMENT EXPERT:
         
     | 
| 236 | 
         
            +
               - Specializes in maintaining audience attention throughout
         
     | 
| 237 | 
         
            +
               - Creates interactive elements and engagement hooks
         
     | 
| 238 | 
         
            +
               - Develops compelling transitions between sections
         
     | 
| 239 | 
         
            +
               - Ensures the webinar flows naturally and keeps interest high
         
     | 
| 240 | 
         
            +
             
     | 
| 241 | 
         
            +
            AUDIENCE UNDERSTANDING:
         
     | 
| 242 | 
         
            +
            You understand how real people interact with webinar content:
         
     | 
| 243 | 
         
            +
            - They quickly lose interest if the content feels generic or corporate
         
     | 
| 244 | 
         
            +
            - They only stay engaged when the content feels personal and sparks genuine curiosity
         
     | 
| 245 | 
         
            +
            - They respond to messages that seem delivered by a real person, not a corporation
         
     | 
| 246 | 
         
            +
            - They engage with content that hooks them from the first line and maintains interest throughout
         
     | 
| 247 | 
         
            +
             
     | 
| 248 | 
         
            +
            FORMAT RULES:
         
     | 
| 249 | 
         
            +
            - Create a complete webinar script with clear sections and subsections
         
     | 
| 250 | 
         
            +
            - Include specific talking points for each section
         
     | 
| 251 | 
         
            +
            - Write in a conversational, engaging tone
         
     | 
| 252 | 
         
            +
            - Include persuasive elements and calls to action
         
     | 
| 253 | 
         
            +
            - Follow the selected webinar framework structure exactly
         
     | 
| 254 | 
         
            +
            - WRITE THE ENTIRE SCRIPT IN SPANISH
         
     | 
| 255 | 
         
            +
            - DO NOT include any introductory text or explanations about the script
         
     | 
| 256 | 
         
            +
            - Start directly with the webinar content
         
     | 
| 257 | 
         
            +
             
     | 
| 258 | 
         
            +
            IMPORTANT:
         
     | 
| 259 | 
         
            +
            - The script must be comprehensive and ready to use
         
     | 
| 260 | 
         
            +
            - Include specific examples and stories relevant to the topic
         
     | 
| 261 | 
         
            +
            - Maintain a persuasive but authentic tone
         
     | 
| 262 | 
         
            +
            - Adapt language to match the target audience
         
     | 
| 263 | 
         
            +
            - Focus on transformative benefits and clear value proposition
         
     | 
| 264 | 
         
            +
            - Follow the selected formula structure precisely
         
     | 
| 265 | 
         
            +
            - WRITE THE ENTIRE SCRIPT IN SPANISH
         
     | 
| 266 | 
         
            +
            - DO NOT include phrases like "Aqu铆 tienes un guion completo" or any other meta-commentary
         
     | 
| 267 | 
         
            +
             
     | 
| 268 | 
         
            +
            COLLABORATIVE PROCESS:
         
     | 
| 269 | 
         
            +
            As a team of experts, you will:
         
     | 
| 270 | 
         
            +
             
     | 
| 271 | 
         
            +
            1. Analyze the framework '{selected_formula['description']}' to understand its core principles
         
     | 
| 272 | 
         
            +
            2. Identify how to best adapt this framework for {audience} learning about {topic}
         
     | 
| 273 | 
         
            +
            3. Determine the most effective storytelling opportunities within the framework
         
     | 
| 274 | 
         
            +
            4. Create persuasive language that resonates with {audience}
         
     | 
| 275 | 
         
            +
            5. Ensure the script maintains engagement throughout
         
     | 
| 276 | 
         
            +
            6. Adapt the content to be accessible to beginners while still valuable to experienced individuals
         
     | 
| 277 | 
         
            +
            7. Follow the exact structure provided in the framework
         
     | 
| 278 | 
         
            +
             
     | 
| 279 | 
         
            +
            Each expert will contribute their specialized knowledge to create a cohesive, compelling script that:
         
     | 
| 280 | 
         
            +
            - Follows the exact structure of the selected framework
         
     | 
| 281 | 
         
            +
            - Engages the audience from start to finish
         
     | 
| 282 | 
         
            +
            - Addresses audience pain points and desires
         
     | 
| 283 | 
         
            +
            - Presents {topic} in a clear, compelling way
         
     | 
| 284 | 
         
            +
            - Drives conversions through strategic calls to action"""
         
     | 
| 285 | 
         
            +
             
     | 
| 286 | 
         
            +
                # Iniciar el prompt con las instrucciones del sistema
         
     | 
| 287 | 
         
            +
                webinar_script_instruction = f"{system_prompt}\n\n"
         
     | 
| 288 | 
         
            +
                
         
     | 
| 289 | 
         
            +
                # Instrucciones espec铆ficas para la tarea
         
     | 
| 290 | 
         
            +
                webinar_script_instruction += (
         
     | 
| 291 | 
         
            +
                    f"\nYour task is to create a complete webinar script IN SPANISH for {audience} "
         
     | 
| 292 | 
         
            +
                    f"about {topic} that is persuasive and converts the audience into customers. "
         
     | 
| 293 | 
         
            +
                    f"The script must follow exactly the structure of the framework '{selected_formula['description']}' "
         
     | 
| 294 | 
         
            +
                    f"and must include all the necessary elements for a successful webinar."
         
     | 
| 295 | 
         
            +
                    f"\n\n"
         
     | 
| 296 | 
         
            +
                )
         
     | 
| 297 | 
         
            +
             
     | 
| 298 | 
         
            +
                # Estructura del webinar
         
     | 
| 299 | 
         
            +
                webinar_script_instruction += "WEBINAR STRUCTURE TO FOLLOW:\n"
         
     | 
| 300 | 
         
            +
                for i, step in enumerate(selected_formula['structure'], 1):
         
     | 
| 301 | 
         
            +
                    webinar_script_instruction += f"{i}. {step}\n"
         
     | 
| 302 | 
         
            +
             
     | 
| 303 | 
         
            +
                # Ejemplos de webinars exitosos
         
     | 
| 304 | 
         
            +
                webinar_script_instruction += "\n\nEXAMPLES OF SUCCESSFUL WEBINARS WITH THIS STRUCTURE:\n"
         
     | 
| 305 | 
         
            +
                for i, example in enumerate(selected_formula['examples'], 1):
         
     | 
| 306 | 
         
            +
                    webinar_script_instruction += f"{i}. {example}\n"
         
     | 
| 307 | 
         
            +
             
     | 
| 308 | 
         
            +
                # Instrucciones espec铆ficas
         
     | 
| 309 | 
         
            +
                webinar_script_instruction += f"""
         
     | 
| 310 | 
         
            +
            SPECIFIC INSTRUCTIONS:
         
     | 
| 311 | 
         
            +
            1. Create a complete script that follows exactly the provided structure
         
     | 
| 312 | 
         
            +
            2. Include persuasive elements and clear calls to action
         
     | 
| 313 | 
         
            +
            3. Adapt the language and examples specifically for {audience}
         
     | 
| 314 | 
         
            +
            4. Focus on the transformative benefits of {topic}
         
     | 
| 315 | 
         
            +
            5. Include relevant stories and examples that reinforce your points
         
     | 
| 316 | 
         
            +
            6. Use a conversational but professional tone
         
     | 
| 317 | 
         
            +
            7. Make sure each section fulfills its specific purpose in the framework
         
     | 
| 318 | 
         
            +
            8. IMPORTANT: Write the entire script in Spanish
         
     | 
| 319 | 
         
            +
             
     | 
| 320 | 
         
            +
            GENERATE NOW:
         
     | 
| 321 | 
         
            +
            Create a complete webinar script following faithfully the structure of the selected framework.
         
     | 
| 322 | 
         
            +
            """
         
     | 
| 323 | 
         
            +
             
     | 
| 324 | 
         
            +
                # Enviar el mensaje al modelo
         
     | 
| 325 | 
         
            +
                chat_session = model.start_chat(
         
     | 
| 326 | 
         
            +
                    history=[
         
     | 
| 327 | 
         
            +
                        {
         
     | 
| 328 | 
         
            +
                            "role": "user",
         
     | 
| 329 | 
         
            +
                            "parts": [webinar_script_instruction],
         
     | 
| 330 | 
         
            +
                        },
         
     | 
| 331 | 
         
            +
                    ]
         
     | 
| 332 | 
         
            +
                )
         
     | 
| 333 | 
         
            +
                response = chat_session.send_message("Generate the webinar script IN NEUTRAL SPANISH following exactly the provided structure. All content must be in neutral Spanish (not Spain Spanish).")
         
     | 
| 334 | 
         
            +
                
         
     | 
| 335 | 
         
            +
                return response.text
         
     | 
| 336 | 
         
            +
             
     | 
| 337 | 
         
            +
            # Funci贸n para validar entradas (evita duplicaci贸n)
         
     | 
| 338 | 
         
            +
            def validate_inputs(audience, product):
         
     | 
| 339 | 
         
            +
                has_audience = audience.strip() != ""
         
     | 
| 340 | 
         
            +
                has_product = product.strip() != ""
         
     | 
| 341 | 
         
            +
                return has_audience and has_product
         
     | 
| 342 | 
         
            +
             
     | 
| 343 | 
         
            +
            # Update the load_css function comment to be more descriptive
         
     | 
| 344 | 
         
            +
            def load_css():
         
     | 
| 345 | 
         
            +
                css_path = "styles/styles.css"
         
     | 
| 346 | 
         
            +
                if os.path.exists(css_path):
         
     | 
| 347 | 
         
            +
                    try:
         
     | 
| 348 | 
         
            +
                        with open(css_path, "r") as f:
         
     | 
| 349 | 
         
            +
                            st.markdown(f"<style>{f.read()}</style>", unsafe_allow_html=True)
         
     | 
| 350 | 
         
            +
                    except Exception as e:
         
     | 
| 351 | 
         
            +
                        st.warning(f"Error al cargar el archivo CSS: {str(e)}")
         
     | 
| 352 | 
         
            +
                else:
         
     | 
| 353 | 
         
            +
                    st.warning(f"No se encontr贸 el archivo CSS en {css_path}")
         
     | 
| 354 | 
         
            +
             
     | 
| 355 | 
         
            +
            # Create a reusable function for custom buttons
         
     | 
| 356 | 
         
            +
            # At the top of your file, define the styles dictionary
         
     | 
| 357 | 
         
            +
            styles = {
         
     | 
| 358 | 
         
            +
                "button": """
         
     | 
| 359 | 
         
            +
                    <style>
         
     | 
| 360 | 
         
            +
                    div.stButton > button:first-child {
         
     | 
| 361 | 
         
            +
                        background-color: #FF4B4B;
         
     | 
| 362 | 
         
            +
                        color: white;
         
     | 
| 363 | 
         
            +
                        font-weight: bold;
         
     | 
| 364 | 
         
            +
                        padding: 0.5rem 1rem;
         
     | 
| 365 | 
         
            +
                        border-radius: 0.5rem;
         
     | 
| 366 | 
         
            +
                        border: none;
         
     | 
| 367 | 
         
            +
                        transition: all 0.3s;
         
     | 
| 368 | 
         
            +
                    }
         
     | 
| 369 | 
         
            +
                    div.stButton > button:hover {
         
     | 
| 370 | 
         
            +
                        background-color: #FF2525;
         
     | 
| 371 | 
         
            +
                        transform: translateY(-2px);
         
     | 
| 372 | 
         
            +
                        box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
         
     | 
| 373 | 
         
            +
                    }
         
     | 
| 374 | 
         
            +
                    </style>
         
     | 
| 375 | 
         
            +
                """,
         
     | 
| 376 | 
         
            +
                "download_button": """
         
     | 
| 377 | 
         
            +
                    <style>
         
     | 
| 378 | 
         
            +
                    div.stDownloadButton > button:first-child {
         
     | 
| 379 | 
         
            +
                        background-color: #4CAF50;
         
     | 
| 380 | 
         
            +
                        color: white;
         
     | 
| 381 | 
         
            +
                        font-weight: bold;
         
     | 
| 382 | 
         
            +
                        padding: 0.5rem 1rem;
         
     | 
| 383 | 
         
            +
                        border-radius: 0.5rem;
         
     | 
| 384 | 
         
            +
                        border: none;
         
     | 
| 385 | 
         
            +
                        transition: all 0.3s;
         
     | 
| 386 | 
         
            +
                    }
         
     | 
| 387 | 
         
            +
                    div.stDownloadButton > button:hover {
         
     | 
| 388 | 
         
            +
                        background-color: #45a049;
         
     | 
| 389 | 
         
            +
                        transform: translateY(-2px);
         
     | 
| 390 | 
         
            +
                        box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
         
     | 
| 391 | 
         
            +
                    }
         
     | 
| 392 | 
         
            +
                    </style>
         
     | 
| 393 | 
         
            +
                """
         
     | 
| 394 | 
         
            +
            }
         
     | 
| 395 | 
         
            +
             
     | 
| 396 | 
         
            +
            # Then modify your create_custom_button function to be much simpler:
         
     | 
| 397 | 
         
            +
            def create_custom_button(label, button_key):
         
     | 
| 398 | 
         
            +
                # Apply the button style once at the beginning of your app
         
     | 
| 399 | 
         
            +
                # (You can move this to your main app code if you prefer)
         
     | 
| 400 | 
         
            +
                st.markdown(styles["button"], unsafe_allow_html=True)
         
     | 
| 401 | 
         
            +
                
         
     | 
| 402 | 
         
            +
                # Just return a regular Streamlit button
         
     | 
| 403 | 
         
            +
                return st.button(label, key=button_key)
         
     | 
| 404 | 
         
            +
             
     | 
| 405 | 
         
            +
            # Modify the page config section to include the CSS loading
         
     | 
| 406 | 
         
            +
            st.set_page_config(page_title="Perfect Webinar Framework", layout="wide")
         
     | 
| 407 | 
         
            +
            load_css()
         
     | 
| 408 | 
         
            +
             
     | 
| 409 | 
         
            +
            # Leer el contenido del archivo manual.md
         
     | 
| 410 | 
         
            +
            with open("manual.md", "r", encoding="utf-8") as file:
         
     | 
| 411 | 
         
            +
                manual_content = file.read()
         
     | 
| 412 | 
         
            +
             
     | 
| 413 | 
         
            +
            # Mostrar el contenido del manual en el sidebar
         
     | 
| 414 | 
         
            +
            st.sidebar.markdown(manual_content)
         
     | 
| 415 | 
         
            +
             
     | 
| 416 | 
         
            +
            # Crear pesta帽as para la interfaz
         
     | 
| 417 | 
         
            +
            tab1, tab2 = st.tabs(["Guiones de Webinar", "Nombres de Webinar"])
         
     | 
| 418 | 
         
            +
             
     | 
| 419 | 
         
            +
            # Primera pesta帽a - Generador de Guiones de Webinar
         
     | 
| 420 | 
         
            +
            with tab1:
         
     | 
| 421 | 
         
            +
                tab1.subheader("Script Webinar")
         
     | 
| 422 | 
         
            +
                
         
     | 
| 423 | 
         
            +
                # Crear columnas para la interfaz
         
     | 
| 424 | 
         
            +
                col1, col2 = tab1.columns([1, 2])
         
     | 
| 425 | 
         
            +
                
         
     | 
| 426 | 
         
            +
                # Columna de entrada usando la funci贸n reutilizable
         
     | 
| 427 | 
         
            +
                with col1:
         
     | 
| 428 | 
         
            +
                    webinar_script_audience, webinar_script_product, selected_webinar_formula_key = create_input_section(
         
     | 
| 429 | 
         
            +
                        col1, 
         
     | 
| 430 | 
         
            +
                        "webinar_script_audience", 
         
     | 
| 431 | 
         
            +
                        "webinar_script_product", 
         
     | 
| 432 | 
         
            +
                        webinar_formulas, 
         
     | 
| 433 | 
         
            +
                        "webinar_formula"
         
     | 
| 434 | 
         
             
                    )
         
     | 
| 
         | 
|
| 435 | 
         | 
| 436 | 
         
            +
                    # Usar la funci贸n reutilizable para crear el bot贸n personalizado
         
     | 
| 437 | 
         
            +
                    submit_webinar_script = create_custom_button("Generar Gui贸n de Webinar", "generate_webinar_script")
         
     | 
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 438 | 
         | 
| 439 | 
         
            +
                    # Opciones avanzadas
         
     | 
| 440 | 
         
            +
                    with st.expander("Personaliza tu gui贸n de webinar"):
         
     | 
| 441 | 
         
            +
                        webinar_script_temperature = st.slider("Creatividad", min_value=0.0, max_value=2.0, value=1.0, step=0.1, key="webinar_script_temp")
         
     | 
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 442 | 
         | 
| 443 | 
         
            +
                    selected_webinar_formula = webinar_formulas[selected_webinar_formula_key]
         
     | 
| 444 | 
         
            +
                
         
     | 
| 445 | 
         
            +
                # Generar y mostrar el gui贸n usando la funci贸n reutilizable
         
     | 
| 446 | 
         
            +
                if submit_webinar_script:
         
     | 
| 447 | 
         
            +
                    generate_and_display(
         
     | 
| 448 | 
         
            +
                        col2,
         
     | 
| 449 | 
         
            +
                        generate_webinar_script,
         
     | 
| 450 | 
         
            +
                        webinar_script_audience,
         
     | 
| 451 | 
         
            +
                        webinar_script_product,
         
     | 
| 452 | 
         
            +
                        webinar_script_temperature,
         
     | 
| 453 | 
         
            +
                        selected_webinar_formula,
         
     | 
| 454 | 
         
            +
                        content_type="script"
         
     | 
| 455 | 
         
            +
                    )
         
     | 
| 456 | 
         
            +
             
     | 
| 457 | 
         
            +
            # Segunda pesta帽a - Generador de Nombres de Webinar
         
     | 
| 458 | 
         
            +
            with tab2:
         
     | 
| 459 | 
         
            +
                tab2.subheader("Nombres de Webinar")
         
     | 
| 460 | 
         
            +
                
         
     | 
| 461 | 
         
            +
                # Crear columnas para la interfaz
         
     | 
| 462 | 
         
            +
                col1, col2 = tab2.columns([1, 2])
         
     | 
| 463 | 
         
            +
                
         
     | 
| 464 | 
         
            +
                # Columna de entrada usando la funci贸n reutilizable
         
     | 
| 465 | 
         
            +
                with col1:
         
     | 
| 466 | 
         
            +
                    webinar_name_audience, webinar_name_product, selected_webinar_name_formula_key = create_input_section(
         
     | 
| 467 | 
         
            +
                        col1, 
         
     | 
| 468 | 
         
            +
                        "webinar_name_audience", 
         
     | 
| 469 | 
         
            +
                        "webinar_name_product", 
         
     | 
| 470 | 
         
            +
                        webinar_name_formulas, 
         
     | 
| 471 | 
         
            +
                        "webinar_name_formula"
         
     | 
| 472 | 
         
             
                    )
         
     | 
| 473 | 
         | 
| 474 | 
         
            +
                    number_of_names = st.selectbox("N煤mero de nombres", options=[1, 2, 3, 4, 5, 6, 7, 8, 9, 10], index=4, key="number_of_names")
         
     | 
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 475 | 
         | 
| 476 | 
         
            +
                    # Usar la funci贸n reutilizable para crear el bot贸n personalizado
         
     | 
| 477 | 
         
            +
                    submit_webinar_names = create_custom_button("Generar Nombres de Webinar", "generate_webinar_names")
         
     | 
| 478 | 
         
            +
             
     | 
| 479 | 
         
            +
                    # Opciones avanzadas
         
     | 
| 480 | 
         
            +
                    with st.expander("Personaliza tus nombres de webinar"):
         
     | 
| 481 | 
         
            +
                        webinar_name_temperature = st.slider("Creatividad", min_value=0.0, max_value=2.0, value=1.0, step=0.1, key="webinar_name_temp")
         
     | 
| 482 | 
         
            +
             
     | 
| 483 | 
         
            +
                        # Configurar opciones de 谩ngulo
         
     | 
| 484 | 
         
            +
                        angle_keys = ["NINGUNO"] + sorted([key for key in angles_webinar_names.keys() if key != "NINGUNO"])
         
     | 
| 485 | 
         
            +
                        selected_angle = st.selectbox(
         
     | 
| 486 | 
         
            +
                            "Selecciona el 谩ngulo para tus nombres",
         
     | 
| 487 | 
         
            +
                            options=angle_keys,
         
     | 
| 488 | 
         
            +
                            key="webinar_name_angle"
         
     | 
| 489 | 
         
            +
                        )
         
     | 
| 490 | 
         
            +
             
     | 
| 491 | 
         
            +
                    selected_webinar_name_formula = webinar_name_formulas[selected_webinar_name_formula_key]
         
     | 
| 492 | 
         
            +
             
     | 
| 493 | 
         
            +
                # Generar y mostrar los nombres usando la funci贸n reutilizable
         
     | 
| 494 | 
         
            +
                if submit_webinar_names:
         
     | 
| 495 | 
         
            +
                    generate_and_display(
         
     | 
| 496 | 
         
            +
                        col2,
         
     | 
| 497 | 
         
            +
                        generate_webinar_names,
         
     | 
| 498 | 
         
            +
                        webinar_name_audience,
         
     | 
| 499 | 
         
            +
                        webinar_name_product,
         
     | 
| 500 | 
         
            +
                        webinar_name_temperature,
         
     | 
| 501 | 
         
            +
                        selected_webinar_name_formula,
         
     | 
| 502 | 
         
            +
                        content_type="names",
         
     | 
| 503 | 
         
            +
                        number_of_names=number_of_names,
         
     | 
| 504 | 
         
            +
                        selected_angle=selected_angle if selected_angle != "NINGUNO" else None
         
     | 
| 505 | 
         
            +
                    )
         
     | 
| 506 | 
         
            +
                    if validate_inputs(webinar_name_audience, webinar_name_product):
         
     | 
| 507 | 
         
            +
                        try:
         
     | 
| 508 | 
         
            +
                            with col2:
         
     | 
| 509 | 
         
            +
                                with st.spinner("Generando tus nombres de webinar...", show_time=True):
         
     | 
| 510 | 
         
            +
                                    generated_webinar_names = generate_webinar_names(
         
     | 
| 511 | 
         
            +
                                        number_of_names,
         
     | 
| 512 | 
         
            +
                                        webinar_name_audience,
         
     | 
| 513 | 
         
            +
                                        webinar_name_product,
         
     | 
| 514 | 
         
            +
                                        webinar_name_temperature,
         
     | 
| 515 | 
         
            +
                                        selected_webinar_name_formula,
         
     | 
| 516 | 
         
            +
                                        selected_angle if selected_angle != "NINGUNO" else None
         
     | 
| 517 | 
         
            +
                                    )
         
     | 
| 518 | 
         
            +
                                st.subheader("Tus nombres de webinar:")
         
     | 
| 519 | 
         
            +
                                st.markdown(generated_webinar_names)
         
     | 
| 520 | 
         
            +
                        except ValueError as e:
         
     | 
| 521 | 
         
            +
                            col2.error(f"Error: {str(e)}")
         
     | 
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 522 | 
         
             
                    else:
         
     | 
| 523 | 
         
            +
                        col2.error("Por favor, proporciona el p煤blico objetivo y el tema del webinar.")
         
     | 
| 524 | 
         
            +
             
     | 
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         |