Spaces:
Sleeping
Sleeping
from dotenv import load_dotenv | |
import streamlit as st | |
import os | |
import google.generativeai as genai | |
import datetime | |
from streamlit import session_state as state | |
# Cargar las variables de entorno | |
load_dotenv() | |
# Configurar la API de Google | |
genai.configure(api_key=os.getenv("GOOGLE_API_KEY")) | |
# Funci贸n para inicializar el modelo | |
def initialize_model(temperature=1.0): | |
return genai.GenerativeModel( | |
model_name="gemini-2.0-flash", | |
generation_config={"temperature": temperature} | |
) | |
# Initialize session state variables at the app level | |
session_state_vars = { | |
'headline_content': "", | |
'problem_content': "", | |
'solution_content': "", | |
'avatar_details': {}, | |
'product_details': {}, | |
'generated_sections': {}, | |
'metadata': {} | |
} | |
for var, default in session_state_vars.items(): | |
if var not in st.session_state: | |
st.session_state[var] = default | |
# Funci贸n para generar contenido y procesar el JSON | |
def generate_content(prompt, temperature=1.0): | |
model = initialize_model(temperature) | |
response = model.generate_content(prompt) | |
result = response.text | |
# Try to extract JSON metadata if present and remove it from the displayed text | |
try: | |
import json | |
import re | |
# Look for JSON data in the response (both with and without code blocks) | |
json_pattern = r'```json\s*(.*?)\s*```|(\{[\s\S]*"character"[\s\S]*\})' | |
json_match = re.search(json_pattern, result, re.DOTALL) | |
if json_match: | |
# Get the matched JSON string (either from code block or raw JSON) | |
json_str = json_match.group(1) if json_match.group(1) else json_match.group(2) | |
# Parse the JSON data | |
json_data = json.loads(json_str.strip()) | |
# Store the JSON data in session state | |
st.session_state.metadata = json_data | |
# Update avatar details and other metadata elements | |
metadata_fields = ['character', 'pain_points', 'emotional_triggers', 'obstacles', 'failed_solutions'] | |
for field in metadata_fields: | |
if field in json_data: | |
if field == 'character' and 'avatar_details' in st.session_state: | |
st.session_state.avatar_details.update(json_data[field]) | |
else: | |
st.session_state[field] = json_data[field] | |
# Remove the JSON block from the displayed text | |
result = re.sub(json_pattern, '', result, flags=re.DOTALL).strip() | |
except Exception as e: | |
# Log the error but don't disrupt the user experience | |
print(f"Error processing JSON metadata: {str(e)}") | |
return result | |
# Modify the display function to preserve content | |
def display_generated_content(column, content, key_prefix): | |
"""Display generated content in the specified column with download button.""" | |
if content: | |
column.markdown("### Contenido generado:") | |
column.markdown(content) | |
# Add download button | |
download_button_key = f"{key_prefix}_download_button" | |
timestamp = datetime.datetime.now().strftime("%Y%m%d_%H%M%S") | |
section_name = key_prefix.replace("_", "-") | |
filename = f"sales_page_{section_name}_{timestamp}.txt" | |
column.download_button( | |
label="Descargar contenido", | |
data=content, | |
file_name=filename, | |
mime="text/plain", | |
key=f"{key_prefix}_actual_download" | |
) | |
# Add this function to validate inputs | |
def validate_inputs(audience, product): | |
"""Validate that required inputs are provided.""" | |
return audience.strip() != "" and product.strip() != "" | |
# Make sure to define your UI elements before using them | |
# Add this before the submit button | |
st.set_page_config(layout="wide") # Set the page layout to wide | |
st.title("Generador de P谩ginas de Ventas") | |
# Load custom CSS from the styles folder | |
def load_css(css_file): | |
with open(css_file, 'r') as f: | |
css = f.read() | |
st.markdown(f'<style>{css}</style>', unsafe_allow_html=True) | |
# Load the CSS file | |
css_path = os.path.join(os.path.dirname(__file__), "styles", "styles.css") | |
load_css(css_path) | |
# Create two columns for layout with adjusted widths (40% left, 60% right) | |
col1, col2 = st.columns([4, 6]) | |
with col1: | |
st.subheader("Configuraci贸n") | |
# Input fields | |
sales_page_audience = st.text_input("P煤blico objetivo:", | |
help="Describe a qui茅n va dirigida tu p谩gina de ventas") | |
sales_page_product = st.text_input("Producto/Servicio:", | |
help="Describe el producto o servicio que est谩s vendiendo") | |
sales_page_offer = st.text_area("Oferta espec铆fica (opcional):", | |
help="Detalles espec铆ficos de tu oferta, como precio, bonos, etc.") | |
sales_page_section = st.selectbox( | |
"Secci贸n a generar:", | |
[ | |
"Above the Fold (Encabezado)", | |
"Problem (Problema)", | |
"Solution & Benefits (Soluci贸n y Beneficios)", | |
"Authority (Autoridad)", | |
"Offer & Bonus (Oferta y Bonus)", | |
"Social Proof (Prueba Social)", | |
"Guarantees (Garant铆as)", | |
"Call to Action (Llamada a la Acci贸n)", | |
"P.S. (Post-Data)", | |
"Final Call to Action (Llamada Final)" | |
] | |
) | |
sales_page_temperature = st.slider( | |
"Creatividad:", | |
min_value=0.0, | |
max_value=1.0, | |
value=0.7, | |
step=0.1, | |
help="Valores m谩s altos = m谩s creatividad, valores m谩s bajos = m谩s consistencia" | |
) | |
# Now create the submit button | |
submit_sales_page = st.button("Generar Secci贸n", key="generate_sales_page") | |
# Add these section generator functions before the section_functions dictionary | |
def load_prompt_template(filename): | |
"""Load a prompt template from the prompts directory.""" | |
prompt_path = os.path.join(os.path.dirname(__file__), "prompts", filename) | |
with open(prompt_path, "r", encoding="utf-8") as file: | |
return file.read() | |
def generate_above_the_fold(audience, product, temperature=0.7, offer=None): | |
"""Generate the Above the Fold (headline) section.""" | |
prompt_template = load_prompt_template("above_the_fold.txt") | |
# Create the prompt with the audience and product information | |
prompt = f"{prompt_template}\n\nAUDIENCE: {audience}\nPRODUCT/SERVICE: {product}" | |
if offer: | |
prompt += f"\nOFFER: {offer}" | |
# Generate the content | |
return generate_content(prompt, temperature) | |
def generate_problem_section(audience, product, temperature=0.7, offer=None): | |
"""Generate the Problem section.""" | |
prompt_template = load_prompt_template("problem.txt") | |
# Create context dictionary with any existing session state data | |
context = {} | |
if 'headline_content' in st.session_state: | |
context['headline_content'] = st.session_state.headline_content | |
if 'avatar_details' in st.session_state: | |
context['avatar_details'] = st.session_state.avatar_details | |
if 'product_details' in st.session_state: | |
context['product_details'] = st.session_state.product_details | |
# Create the prompt with the audience and product information | |
prompt = f"{prompt_template}\n\nAUDIENCE: {audience}\nPRODUCT/SERVICE: {product}\nCONTEXT: {context}" | |
if offer: | |
prompt += f"\nOFFER: {offer}" | |
# Generate the content | |
return generate_content(prompt, temperature) | |
def generate_solution_section(audience, product, temperature=0.7, offer=None): | |
"""Generate the Solution & Benefits section.""" | |
prompt_template = load_prompt_template("solution_benefits.txt") | |
# Create context dictionary with any existing session state data | |
context = {} | |
if 'headline_content' in st.session_state: | |
context['headline_content'] = st.session_state.headline_content | |
if 'problem_content' in st.session_state: | |
context['problem_content'] = st.session_state.problem_content | |
if 'avatar_details' in st.session_state: | |
context['avatar_details'] = st.session_state.avatar_details | |
# Create the prompt with the audience and product information | |
prompt = f"{prompt_template}\n\nAUDIENCE: {audience}\nPRODUCT/SERVICE: {product}\nCONTEXT: {context}" | |
if offer: | |
prompt += f"\nOFFER: {offer}" | |
# Generate the content | |
return generate_content(prompt, temperature) | |
def generate_authority_section(audience, product, temperature=0.7, offer=None): | |
"""Generate the Authority section.""" | |
prompt_template = load_prompt_template("authority.txt") | |
# Create the prompt with the audience and product information | |
prompt = f"{prompt_template}\n\nAUDIENCE: {audience}\nPRODUCT/SERVICE: {product}" | |
if offer: | |
prompt += f"\nOFFER: {offer}" | |
# Generate the content | |
return generate_content(prompt, temperature) | |
def generate_offer_section(audience, product, temperature=0.7, offer=None): | |
"""Generate the Offer & Bonus section.""" | |
prompt_template = load_prompt_template("offer_bonus.txt") | |
# Create the prompt with the audience and product information | |
prompt = f"{prompt_template}\n\nAUDIENCE: {audience}\nPRODUCT/SERVICE: {product}" | |
if offer: | |
prompt += f"\nOFFER DETAILS: {offer}" | |
else: | |
prompt += "\nOFFER DETAILS: Create a compelling offer based on the product/service and audience." | |
# Generate the content | |
return generate_content(prompt, temperature) | |
def generate_social_proof_section(audience, product, temperature=0.7, offer=None): | |
"""Generate the Social Proof section.""" | |
prompt_template = load_prompt_template("social_proof.txt") | |
# Create the prompt with the audience and product information | |
prompt = f"{prompt_template}\n\nAUDIENCE: {audience}\nPRODUCT/SERVICE: {product}" | |
if offer: | |
prompt += f"\nOFFER: {offer}" | |
# Generate the content | |
return generate_content(prompt, temperature) | |
def generate_guarantees_section(audience, product, temperature=0.7, offer=None): | |
"""Generate the Guarantees section.""" | |
prompt_template = load_prompt_template("guarantees.txt") | |
# Create the prompt with the audience and product information | |
prompt = f"{prompt_template}\n\nAUDIENCE: {audience}\nPRODUCT/SERVICE: {product}" | |
if offer: | |
prompt += f"\nOFFER: {offer}" | |
# Generate the content | |
return generate_content(prompt, temperature) | |
def generate_cta_section(audience, product, temperature=0.7, offer=None): | |
"""Generate the Call to Action section.""" | |
prompt_template = load_prompt_template("cta.txt") | |
# Create the prompt with the audience and product information | |
prompt = f"{prompt_template}\n\nAUDIENCE: {audience}\nPRODUCT/SERVICE: {product}" | |
if offer: | |
prompt += f"\nOFFER: {offer}" | |
# Generate the content | |
return generate_content(prompt, temperature) | |
def generate_ps_section(audience, product, temperature=0.7, offer=None): | |
"""Generate the P.S. (Post-Data) section.""" | |
prompt_template = load_prompt_template("ps.txt") | |
# Create the prompt with the audience and product information | |
prompt = f"{prompt_template}\n\nAUDIENCE: {audience}\nPRODUCT/SERVICE: {product}" | |
if offer: | |
prompt += f"\nOFFER: {offer}" | |
# Generate the content | |
return generate_content(prompt, temperature) | |
def generate_final_cta_section(audience, product, temperature=0.7, offer=None): | |
"""Generate the Final Call to Action section.""" | |
prompt_template = load_prompt_template("final_cta.txt") | |
# Create the prompt with the audience and product information | |
prompt = f"{prompt_template}\n\nAUDIENCE: {audience}\nPRODUCT/SERVICE: {product}" | |
if offer: | |
prompt += f"\nOFFER: {offer}" | |
# Generate the content | |
return generate_content(prompt, temperature) | |
# Define section functions mapping once | |
section_functions = { | |
"Above the Fold (Encabezado)": generate_above_the_fold, | |
"Problem (Problema)": generate_problem_section, | |
"Solution & Benefits (Soluci贸n y Beneficios)": generate_solution_section, | |
"Authority (Autoridad)": generate_authority_section, | |
"Offer & Bonus (Oferta y Bonus)": generate_offer_section, | |
"Social Proof (Prueba Social)": generate_social_proof_section, | |
"Guarantees (Garant铆as)": generate_guarantees_section, | |
"Call to Action (Llamada a la Acci贸n)": generate_cta_section, | |
"P.S. (Post-Data)": generate_ps_section, | |
"Final Call to Action (Llamada Final)": generate_final_cta_section | |
} | |
# Then use it in the conditional | |
if submit_sales_page: | |
# Validar entradas | |
if validate_inputs(sales_page_audience, sales_page_product): | |
try: | |
# Store current inputs in session state | |
st.session_state.last_audience = sales_page_audience | |
st.session_state.last_product = sales_page_product | |
st.session_state.last_offer = sales_page_offer | |
# Crear un contenedor para el spinner en la columna 2 | |
with col2: | |
with st.spinner("Generando secci贸n de p谩gina de ventas...", show_time=True): | |
# Obtener la funci贸n correspondiente | |
generator_func = section_functions[sales_page_section] | |
# Generar el contenido | |
generated_content = generator_func( | |
audience=sales_page_audience, | |
product=sales_page_product, | |
temperature=sales_page_temperature, | |
offer=sales_page_offer if sales_page_offer.strip() else None | |
) | |
# Store the generated content in session state with a key based on the section | |
section_key = sales_page_section.replace(" ", "_").lower() | |
st.session_state.generated_sections[section_key] = generated_content | |
# Mostrar el contenido generado fuera del bloque del spinner | |
display_generated_content(col2, generated_content, "sales_page_section") | |
except Exception as e: | |
st.error(f"Error al generar la secci贸n: {str(e)}") | |
else: | |
st.warning("Por favor, completa los campos de p煤blico objetivo y producto/servicio.") | |
else: | |
# Display previously generated content if available for the selected section | |
section_key = sales_page_section.replace(" ", "_").lower() | |
if section_key in st.session_state.generated_sections and st.session_state.generated_sections[section_key]: | |
display_generated_content(col2, st.session_state.generated_sections[section_key], "sales_page_section") |