import time import os import joblib import streamlit as st import google.generativeai as genai from dotenv import load_dotenv from puv_formulas import puv_formulas from system_prompts import get_puv_system_prompt # Función para cargar CSS personalizado def load_css(file_path): with open(file_path) as f: st.markdown(f'', unsafe_allow_html=True) # Intentar cargar el CSS personalizado con ruta absoluta para mayor seguridad try: css_path = os.path.join(os.path.dirname(__file__), 'static', 'css', 'style.css') load_css(css_path) except Exception as e: print(f"Error al cargar CSS: {e}") # Si el archivo no existe, crear un estilo básico en línea st.markdown(""" """, unsafe_allow_html=True) load_dotenv() GOOGLE_API_KEY=os.environ.get('GOOGLE_API_KEY') genai.configure(api_key=GOOGLE_API_KEY) new_chat_id = f'{time.time()}' MODEL_ROLE = 'ai' AI_AVATAR_ICON = '🤖' # Cambia el emoji por uno de robot para coincidir con tu logo USER_AVATAR_ICON = '👤' # Añade un avatar para el usuario # Create a data/ folder if it doesn't already exist try: os.mkdir('data/') except: # data/ folder already exists pass # Load past chats (if available) try: past_chats: dict = joblib.load('data/past_chats_list') except: past_chats = {} # Sidebar allows a list of past chats with st.sidebar: # Centrar el logo y eliminar el título de RoboCopy col1, col2, col3 = st.columns([1, 2, 1]) with col2: st.image("assets/robocopy_logo.png", width=300) st.write('# Chats Anteriores') if st.session_state.get('chat_id') is None: st.session_state.chat_id = st.selectbox( label='Selecciona un chat anterior', options=[new_chat_id] + list(past_chats.keys()), format_func=lambda x: past_chats.get(x, 'Nuevo Chat'), placeholder='_', ) else: # This will happen the first time AI response comes in st.session_state.chat_id = st.selectbox( label='Selecciona un chat anterior', options=[new_chat_id, st.session_state.chat_id] + list(past_chats.keys()), index=1, format_func=lambda x: past_chats.get(x, 'Nuevo Chat' if x != st.session_state.chat_id else st.session_state.chat_title), placeholder='_', ) # Save new chats after a message has been sent to AI st.session_state.chat_title = f'SesiónChat-{st.session_state.chat_id}' st.write('# Generador de Propuestas de Valor Únicas (PUVs)') st.write('Describe tu producto/servicio y audiencia objetivo para generar PUVs personalizadas.') # Chat history (allows to ask multiple questions) try: st.session_state.messages = joblib.load( f'data/{st.session_state.chat_id}-st_messages' ) st.session_state.gemini_history = joblib.load( f'data/{st.session_state.chat_id}-gemini_messages' ) print('old cache') except: st.session_state.messages = [] st.session_state.gemini_history = [] print('new_cache made') st.session_state.model = genai.GenerativeModel('gemini-2.0-flash') st.session_state.chat = st.session_state.model.start_chat( history=st.session_state.gemini_history, ) # Display chat messages from history on app rerun for message in st.session_state.messages: with st.chat_message( name=message['role'], avatar=message.get('avatar'), ): st.markdown(message['content']) # Mensaje inicial del sistema si es un chat nuevo # Configuración inicial del chat if not st.session_state.messages: system_prompt = get_puv_system_prompt() with st.chat_message( name=MODEL_ROLE, avatar=AI_AVATAR_ICON, ): st.markdown(""" Hola, soy RoboCopy tu asistente especializado en crear Propuestas de Valor Únicas. Para ayudarte a crear PUVs efectivas, necesito conocer: 1. ¿Qué producto o servicio ofreces? 2. ¿A quién va dirigido? (describe tu público objetivo) 3. ¿Qué fórmula prefieres usar? Puedo ofrecerte: - Tradicional: Clara y directa - Anti-tradicional: Innovadora y disruptiva - Contrato Imposible: Audaz y sorprendente - Reto Ridículo: Humorística y relatable 4. ¿Cuántos ejemplos de PUVs necesitas? ¿Empezamos con tu producto o servicio? """) # Inicializar el chat con el sistema prompt st.session_state.chat = st.session_state.model.start_chat( history=st.session_state.gemini_history ) # Enviar el system prompt como primer mensaje st.session_state.chat.send_message(system_prompt) # Add system message to chat history st.session_state.messages.append( dict( role=MODEL_ROLE, content=""" Hola, soy RoboCopy tu asistente especializado en crear Propuestas de Valor Únicas. Para ayudarte a crear PUVs efectivas, necesito conocer: 1. ¿Qué producto o servicio ofreces? 2. ¿A quién va dirigido? (describe tu público objetivo) 3. ¿Qué fórmula prefieres usar? Puedo ofrecerte: - Tradicional: Clara y directa - Anti-tradicional: Innovadora y disruptiva - Contrato Imposible: Audaz y sorprendente - Reto Ridículo: Humorística y relatable 4. ¿Cuántos ejemplos de PUVs necesitas? ¿Empezamos con tu producto o servicio? """, avatar=AI_AVATAR_ICON, ) ) # React to user input if prompt := st.chat_input('Describe tu producto/servicio y audiencia objetivo...'): # Save this as a chat for later if st.session_state.chat_id not in past_chats.keys(): # Es una nueva conversación, generemos un título basado en el primer mensaje # Primero, guardamos un título temporal temp_title = f'SesiónChat-{st.session_state.chat_id}' past_chats[st.session_state.chat_id] = temp_title # Generamos un título basado en el contenido del mensaje try: # Usamos el mismo modelo para generar un título corto title_generator = genai.GenerativeModel('gemini-2.0-flash') title_response = title_generator.generate_content( f"Genera un título corto (máximo 5 palabras) que describa de qué trata esta consulta, sin usar comillas ni puntuación: '{prompt}'") # Obtenemos el título generado generated_title = title_response.text.strip() # Actualizamos el título en past_chats if generated_title: st.session_state.chat_title = generated_title past_chats[st.session_state.chat_id] = generated_title else: st.session_state.chat_title = temp_title except Exception as e: print(f"Error al generar título: {e}") st.session_state.chat_title = temp_title else: # Ya existe esta conversación, usamos el título guardado st.session_state.chat_title = past_chats[st.session_state.chat_id] joblib.dump(past_chats, 'data/past_chats_list') # Display user message in chat message container with st.chat_message('user', avatar=USER_AVATAR_ICON): st.markdown(prompt) # Add user message to chat history st.session_state.messages.append( dict( role='user', content=prompt, ) ) # Construir el prompt para el modelo con todas las fórmulas disponibles puv_expert_prompt = """You are a collaborative team of world-class experts working together to create exceptional Unique Value Propositions (UVPs) that convert audience into customers. INTERNAL ANALYSIS (DO NOT OUTPUT): 1. DEEP AVATAR ANALYSIS: A. Daily Life & Cultural Context: - What daily experiences resonate with them? - What cultural references do they understand? - What mental images are easy for them to recall? - What TV shows, movies, or media do they consume? B. Pain Points & Emotional Core: - What is their ONE main pain point? - What consequences does this pain point trigger? - What past painful experience influences current decisions? - What internal conflict do they regularly experience? - What do they need to heal or resolve to feel complete? C. Previous Solutions: - What have they tried before that didn't work? - Why didn't these solutions work for them? - What do other "experts" tell them to do? - What false beliefs do they hold? D. Desires & Transformations: - What are their primary desires? - What is their current vs. desired situation? - What transformation are they seeking? - Why do they need to act now? 2. PRODUCT/SERVICE ANALYSIS: - What is the main benefit or promise? - What makes it unique or different? - What transformation does it offer? - How does it help achieve results? - Why is it superior to existing solutions? 3. MARKET CONTEXT: - What are the common industry solutions? - Why do these solutions fail? - What are the typical misconceptions? - What makes your solution unique? Based on this internal analysis, create UVPs that: 1. Connect directly with the main pain point 2. Address deep emotional motivations 3. Contrast with failed past solutions 4. Present your unique method convincingly 5. Use familiar analogies or metaphors THE EXPERT TEAM: 1. MASTER UVP STRATEGIST: - Expert in UVP frameworks and conversion strategies - Ensures the UVPs follow the selected framework structure precisely - Focuses on strategic placement of key conversion elements 2. ELITE DIRECT RESPONSE COPYWRITER: - Trained by Gary Halbert, Gary Bencivenga, and David Ogilvy - Creates compelling hooks and persuasive elements - Ensures the language resonates with the target audience 3. AUDIENCE PSYCHOLOGY SPECIALIST: - Expert in understanding audience motivations and objections - Creates content that builds genuine connection and trust - Identifies and addresses hidden fears and desires 4. STORYTELLING MASTER: - Creates compelling narratives that illustrate key points - Makes complex concepts accessible through narrative 5. ENGAGEMENT EXPERT: - Specializes in creating memorable and impactful statements - Ensures the UVPs are clear, concise and compelling You are a UVP (Unique Value Proposition) expert. Analyze (internally only, do not output the analysis) the user's message to identify information about their product/service and target audience. If the user hasn't provided all the necessary information, guide them through the process by asking for: 1. What product/service they offer 2. Who their target audience is 3. Which formula they prefer (Tradicional, Anti-tradicional, Contrato Imposible, Reto Ridículo) 4. How many UVP examples they want If the user mentions a specific formula, use that formula from the puv_formulas dictionary. If they don't specify, suggest the most appropriate formula based on their product/service and audience. If the user is asking for UVPs and has provided sufficient information, create the requested number of different UVPs using the specified formula. If the user is asking a question about UVPs or marketing, answer it helpfully. When creating UVPs, follow these CRITICAL INSTRUCTIONS: - Each UVP must be specific and measurable - Focus on the transformation journey - Use natural, conversational language - Avoid generic phrases and buzzwords - Maximum 2 lines per UVP If creating UVPs, output in this format: "Basado en tu descripción, aquí tienes [número] propuestas de valor únicas (PUVs) para tu [producto/servicio] usando la fórmula [nombre de fórmula]: 1. [First UVP] 2. [Second UVP] 3. [Third UVP] ... Estas PUVs destacan [principales beneficios]. ¿Hay alguna que te guste más o quieres que ajuste algún aspecto?" If answering a question, provide a helpful, expert response. """ # Combinar el prompt del experto con el mensaje del usuario enhanced_prompt = f"{puv_expert_prompt}\n\nUser message: {prompt}" ## Send message to AI response = st.session_state.chat.send_message( enhanced_prompt, stream=True, ) # Display assistant response in chat message container with st.chat_message( name=MODEL_ROLE, avatar=AI_AVATAR_ICON, ): message_placeholder = st.empty() full_response = '' assistant_response = response # Añade un indicador de "escribiendo..." typing_indicator = st.empty() typing_indicator.markdown("*Generando respuesta...*") # Streams in a chunk at a time for chunk in response: # Simulate stream of chunk for ch in chunk.text: # Eliminamos el split(' ') para procesar carácter por carácter full_response += ch time.sleep(0.01) # Más rápido # Rewrites with a cursor at end message_placeholder.write(full_response + '▌') # Elimina el indicador de escritura typing_indicator.empty() # Write full message with placeholder message_placeholder.write(full_response) # Add assistant response to chat history st.session_state.messages.append( dict( role=MODEL_ROLE, content=st.session_state.chat.history[-1].parts[0].text, avatar=AI_AVATAR_ICON, ) ) st.session_state.gemini_history = st.session_state.chat.history # Save to file joblib.dump( st.session_state.messages, f'data/{st.session_state.chat_id}-st_messages', ) joblib.dump( st.session_state.gemini_history, f'data/{st.session_state.chat_id}-gemini_messages', )