JeCabrera's picture
Update app.py
6f3095d verified
from dotenv import load_dotenv
import streamlit as st
import os
import google.generativeai as genai
from puv_formulas import puv_formulas
from styles import apply_styles, format_creative_response
from options import tone_options, creative_approaches
import PyPDF2
import docx
from PIL import Image
import datetime # Add this import for timestamp
# Cargar variables de entorno
load_dotenv()
# Configurar API de Google Gemini
genai.configure(api_key=os.getenv("GOOGLE_API_KEY"))
# Función para obtener la respuesta del modelo Gemini
def get_gemini_response(product_service, target_audience, main_benefit, tone_of_voice, temperature, file_content="", image_parts=None, creative_approach=""):
# Adjust prompt based on what's provided
business_info = f"Target Audience: {target_audience}\n"
business_info += f"Product/Service: {product_service}\n"
business_info += f"Main Benefit: {main_benefit}\n"
if tone_of_voice:
business_info += f"Brand Tone of Voice: {tone_of_voice}\n"
# Add creative approach to business info if provided
if creative_approach:
# Get the description from the dictionary
from options import creative_approaches
approach_description = creative_approaches.get(creative_approach, "")
business_info += f"\nCREATIVE APPROACH: {creative_approach}\n"
business_info += f"Description: {approach_description}\n"
business_info += f"IMPORTANT: Please follow this creative approach strictly when generating concepts.\n"
# Add file content if available
reference_info = ""
if file_content:
reference_info = f"\nREFERENCE MATERIAL:\n{file_content}\n"
model = genai.GenerativeModel('gemini-2.0-flash')
full_prompt = f"""
You are a Creative Concept expert. Analyze (internally only, do not output the analysis) the following information:
BUSINESS INFORMATION:
{business_info}
{reference_info}
A Creative Idea is a set of pieces created to sell a brand, product, or service, united by the same idea that is transmitted through a creative concept.
First, analyze (but don't output) these points:
1. TARGET AUDIENCE ANALYSIS:
- What everyday concepts are they familiar with?
- What TV shows, movies, or cultural references resonate with them?
- What emotions and experiences are meaningful to them?
- What mental images would be easy for them to recall?
2. PRODUCT/SERVICE ANALYSIS:
- What is the main benefit or promise?
- What makes it unique or different?
- What transformation does it offer?
- What process or journey does the customer go through?
Based on your internal analysis, create THREE different Creative Concepts in Spanish language.
Each concept should be a DIRECT ANALOGY or METAPHOR that connects your product/service to something completely different but familiar.
Examples of good creative concepts:
- "Escribir copy es como cocinar tu plato favorito porque necesitas los ingredientes correctos para que todos quieran probarlo"
- "Tu negocio es como un equipo de fútbol: necesita buenos jugadores (productos) y una estrategia clara para ganar clientes"
- "Tu curso es como Netflix: ofrece contenido que engancha y soluciones que la gente realmente quiere ver"
For each concept, include:
CONCEPT: A clear statement of the main benefit
CREATIVITY: A direct analogy or metaphor connecting your product to something completely different but familiar
CRITICAL INSTRUCTIONS:
- Each concept MUST use a direct "X es como Y porque Z" structure
- Use SIMPLE, EVERYDAY language that anyone can understand
- Avoid technical jargon, complex words, or business terminology
- Write as if you're explaining to a friend in a casual conversation
- Use everyday objects, activities, movies, TV shows or cultural references everyone knows
- Make the connection SURPRISING and UNEXPECTED - connect things that normally wouldn't be connected
- Challenge conventional thinking by finding parallels between your product and something completely different
- Create analogies that make people say "I never thought of it that way!"
- Focus on the main benefit
- Create clear mental images
- Be easy to remember
- Use the brand's tone of voice if provided
- Format with proper spacing between sections
Output EXACTLY in this format (no additional text) in Spanish language:
CONCEPTO CREATIVO 1:
Concepto:
[Main message/benefit in simple, conversational language]
Creatividad:
[Direct analogy using everyday language: "X es como Y porque Z"]
CONCEPTO CREATIVO 2:
Concepto:
[Main message/benefit]
Creatividad:
[Direct analogy: "X es como Y porque Z"]
CONCEPTO CREATIVO 3:
Concepto:
[Main message/benefit]
Creatividad:
[Direct analogy: "X es como Y porque Z"]
"""
# Handle text-only or text+image requests
if image_parts:
response = model.generate_content([full_prompt, image_parts], generation_config={"temperature": temperature})
else:
response = model.generate_content([full_prompt], generation_config={"temperature": temperature})
return response.parts[0].text if response and response.parts else "Error generating content."
# Configurar la aplicación Streamlit
st.set_page_config(page_title="Generador de Ideas Creativas", page_icon="💡", layout="wide")
# Aplicar estilos
st.markdown(apply_styles(), unsafe_allow_html=True)
# Título de la app
st.markdown("<h1>Generador de Ideas Creativas</h1>", unsafe_allow_html=True)
st.markdown("<h3>Crea conceptos creativos poderosos que conecten con tu audiencia y transmitan el valor de tu marca de manera memorable.</h3>", unsafe_allow_html=True)
# Sidebar manual
with open("manual.md", "r", encoding="utf-8") as file:
manual_content = file.read()
st.sidebar.markdown(manual_content)
# Crear dos columnas
col1, col2 = st.columns([1, 1])
# Columna izquierda para inputs
# In the app.py file, update the main_benefit field label and create an accordion for tone options
with col1:
product_service = st.text_area(
"¿Cuál es tu producto o servicio?",
placeholder="Ejemplo: Curso de copywriting con IA, Programa de coaching..."
)
main_benefit = st.text_area(
"¿Cuál es tu Oferta Dorada/PUV?",
placeholder="Ejemplo: Aprender copywriting a través de transformaciones reales de textos..."
)
target_audience = st.text_area(
"¿Cuál es tu público objetivo?",
placeholder="Ejemplo: Emprendedores que quieren mejorar sus textos comerciales..."
)
# Generate button after main inputs
generate_button = st.button("Generar Ideas Creativas")
with st.expander("Opciones avanzadas"):
# Replace nested expanders with a selectbox for tone selection
st.write("Tono de voz de la marca (opcional)")
# Use selectbox for tone selection
selected_tone = st.selectbox(
"Selecciona un tono:",
options=list(tone_options.keys()),
index=0,
key="tone_selectbox"
)
# Display the description of the selected tone
if selected_tone != "Ninguno":
st.info(tone_options[selected_tone])
# Store the selected tone
st.session_state.selected_tone = selected_tone
else:
# Clear any previously selected tone
if "selected_tone" in st.session_state:
del st.session_state.selected_tone
# Use the stored tone or empty string
tone_of_voice = st.session_state.get("selected_tone", "")
# Añadir cargador de archivos
uploaded_file = st.file_uploader("📄 Archivo o imagen de referencia",
type=['txt', 'pdf', 'docx', 'jpg', 'jpeg', 'png'])
file_content = ""
is_image = False
image_parts = None
if uploaded_file is not None:
file_type = uploaded_file.name.split('.')[-1].lower()
# Manejar archivos de texto
if file_type in ['txt', 'pdf', 'docx']:
if file_type == 'txt':
try:
file_content = uploaded_file.read().decode('utf-8')
except Exception as e:
st.error(f"Error al leer el archivo TXT: {str(e)}")
file_content = ""
elif file_type == 'pdf':
try:
pdf_reader = PyPDF2.PdfReader(uploaded_file)
file_content = ""
for page in pdf_reader.pages:
file_content += page.extract_text() + "\n"
except Exception as e:
st.error(f"Error al leer el archivo PDF: {str(e)}")
file_content = ""
elif file_type == 'docx':
try:
doc = docx.Document(uploaded_file)
file_content = "\n".join([para.text for para in doc.paragraphs])
except Exception as e:
st.error(f"Error al leer el archivo DOCX: {str(e)}")
file_content = ""
# Manejar archivos de imagen
elif file_type in ['jpg', 'jpeg', 'png']:
try:
image = Image.open(uploaded_file)
image_bytes = uploaded_file.getvalue()
image_parts = {
"mime_type": uploaded_file.type,
"data": image_bytes
}
is_image = True
except Exception as e:
st.error(f"Error al procesar la imagen: {str(e)}")
is_image = False
# Add creative approach selector (moved outside nested expander)
selected_approach = st.selectbox(
"Enfoque creativo:",
options=list(creative_approaches.keys()),
index=0,
key="approach_selectbox"
)
# Display the description of the selected approach
st.info(creative_approaches[selected_approach])
# Store the selected approach
st.session_state.selected_approach = selected_approach
# Temperature slider
temperature = st.slider(
"Nivel de creatividad:",
min_value=0.0,
max_value=2.0,
value=1.0,
step=0.1,
help="Valores más altos generan ideas más creativas pero menos predecibles."
)
with col2:
if generate_button:
# Store the response in session state so it persists across reruns
with st.spinner("Creando tus ideas creativas..."):
st.session_state.creative_response = get_gemini_response(
product_service,
target_audience,
main_benefit,
tone_of_voice,
temperature,
file_content,
image_parts,
st.session_state.get("selected_approach", "")
# Removed contrast_level parameter
)
# Display the response if it exists in session state
if 'creative_response' in st.session_state:
st.write("### Conceptos Creativos")
# Format the response with custom styling
formatted_response = format_creative_response(st.session_state.creative_response)
# Use markdown with HTML to display the formatted response
st.markdown(formatted_response, unsafe_allow_html=True)
# Add download button if we have a valid response
if st.session_state.creative_response and not st.session_state.creative_response.startswith("Error") and not st.session_state.creative_response.startswith("Debes"):
# Get current timestamp for the filename
timestamp = datetime.datetime.now().strftime("%Y%m%d_%H%M%S")
# Prepare content for download (use the original unformatted response)
download_content = st.session_state.creative_response
# Download button
st.download_button(
label="DESCARGAR IDEAS CREATIVAS",
data=download_content,
file_name=f"conceptos_creativos_{timestamp}.txt",
mime="text/plain"
)