|
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 |
|
|
|
|
|
load_dotenv() |
|
|
|
|
|
genai.configure(api_key=os.getenv("GOOGLE_API_KEY")) |
|
|
|
|
|
def get_gemini_response(product_service, target_audience, main_benefit, tone_of_voice, temperature, file_content="", image_parts=None, creative_approach=""): |
|
|
|
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" |
|
|
|
|
|
if creative_approach: |
|
|
|
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" |
|
|
|
|
|
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"] |
|
""" |
|
|
|
|
|
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." |
|
|
|
|
|
st.set_page_config(page_title="Generador de Ideas Creativas", page_icon="💡", layout="wide") |
|
|
|
|
|
st.markdown(apply_styles(), unsafe_allow_html=True) |
|
|
|
|
|
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) |
|
|
|
|
|
with open("manual.md", "r", encoding="utf-8") as file: |
|
manual_content = file.read() |
|
st.sidebar.markdown(manual_content) |
|
|
|
|
|
col1, col2 = st.columns([1, 1]) |
|
|
|
|
|
|
|
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 = st.button("Generar Ideas Creativas") |
|
|
|
with st.expander("Opciones avanzadas"): |
|
|
|
st.write("Tono de voz de la marca (opcional)") |
|
|
|
|
|
selected_tone = st.selectbox( |
|
"Selecciona un tono:", |
|
options=list(tone_options.keys()), |
|
index=0, |
|
key="tone_selectbox" |
|
) |
|
|
|
|
|
if selected_tone != "Ninguno": |
|
st.info(tone_options[selected_tone]) |
|
|
|
st.session_state.selected_tone = selected_tone |
|
else: |
|
|
|
if "selected_tone" in st.session_state: |
|
del st.session_state.selected_tone |
|
|
|
|
|
tone_of_voice = st.session_state.get("selected_tone", "") |
|
|
|
|
|
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() |
|
|
|
|
|
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 = "" |
|
|
|
|
|
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 |
|
|
|
|
|
|
|
selected_approach = st.selectbox( |
|
"Enfoque creativo:", |
|
options=list(creative_approaches.keys()), |
|
index=0, |
|
key="approach_selectbox" |
|
) |
|
|
|
|
|
st.info(creative_approaches[selected_approach]) |
|
|
|
|
|
st.session_state.selected_approach = selected_approach |
|
|
|
|
|
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: |
|
|
|
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", "") |
|
|
|
) |
|
|
|
|
|
if 'creative_response' in st.session_state: |
|
st.write("### Conceptos Creativos") |
|
|
|
|
|
formatted_response = format_creative_response(st.session_state.creative_response) |
|
|
|
|
|
st.markdown(formatted_response, unsafe_allow_html=True) |
|
|
|
|
|
if st.session_state.creative_response and not st.session_state.creative_response.startswith("Error") and not st.session_state.creative_response.startswith("Debes"): |
|
|
|
timestamp = datetime.datetime.now().strftime("%Y%m%d_%H%M%S") |
|
|
|
|
|
download_content = st.session_state.creative_response |
|
|
|
|
|
st.download_button( |
|
label="DESCARGAR IDEAS CREATIVAS", |
|
data=download_content, |
|
file_name=f"conceptos_creativos_{timestamp}.txt", |
|
mime="text/plain" |
|
) |