Spaces:
Running
Running
from dotenv import load_dotenv | |
import streamlit as st | |
import os | |
import google.generativeai as genai | |
from story_formulas import story_formulas | |
from styles import apply_styles, format_story_output | |
from story_moods import story_moods # Agregar esta importación al inicio | |
# 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(input_prompt, formula_type, length, mood, target_audience, cta_type, temperature): | |
if not input_prompt: | |
return "Por favor, escribe un mensaje para generar contenido." | |
formula = story_formulas[formula_type] | |
model = genai.GenerativeModel('gemini-2.0-flash') | |
full_prompt = f""" | |
IDENTITY | |
You're a renowned world expert in writing emotional stories that turn narrative into a silent yet powerful tool of persuasion. Trained by the legendary minds of Gary Halbert, Gary Bencivenga, and David Ogilvy, you blend timeless copywriting principles with modern psychological insight to craft stories that don’t just move people—they mobilize them. You know how to uncover hidden desires, real fears, and internal conflicts within an audience, then shape them into stories that create instant connection and inevitable action. You think like an emotional strategist: every story you write isn’t just content—it’s an intimate conversation between what the reader feels and what they need to decide. | |
JOBS | |
Investigar el contexto emocional del público objetivo. | |
Identificar conflictos internos, frustraciones o deseos no resueltos. | |
Crear una historia original que conecte con ese conflicto y lo transforme en una oportunidad. | |
Usar lenguaje conversacional, claro y cotidiano. | |
Incorporar un llamado a la acción natural que se sienta como parte de la historia, no como una venta directa. | |
Adaptar el tono emocional según la intención del mensaje (inspirador, reflexivo, melancólico, esperanzador, etc.). | |
Cumplir con una cantidad específica de palabras y mantener la coherencia narrativa en ese límite. | |
Escribir un titular emocional y atractivo al inicio de cada historia. | |
INSTRUCTIONS | |
Write THREE different {mood} stories in Spanish about "{input_prompt}" using everyday words and natural conversation. | |
Each story should use exactly {length} words. | |
Target Audience: {target_audience} | |
Call to Action: {cta_type} | |
Story Formula: {formula_type} | |
{formula["description"]} | |
Keep in mind: | |
Write for {target_audience} | |
Use simple, clear language | |
Tell the story in short paragraphs | |
The CTA must be conversational and focus on benefits, por ejemplo: | |
En vez de: "Inscríbete al curso de marketing" | |
Usa: "¿Quieres aprender a conseguir más clientes? Acompáñanos este jueves..." | |
En vez de: "Reserva tu consulta" | |
Usa: "Da el primer paso hacia tu transformación aquí..." | |
Start each story with a short, emotional headline that captures attention and sets the mood. | |
Ejemplo: “Pensé que ya era tarde para mí”, “La llamada que me cambió la vida”, “No sabía cuánto lo necesitaba” | |
CRITICAL INSTRUCTIONS: | |
Output ONLY the story text | |
DO NOT include any labels like (Problem), (Solution), etc. | |
DO NOT include structural markers or formula explanations | |
Start each story with a headline as the first line | |
Write the story as a continuous narrative with natural paragraph breaks | |
The story should flow naturally between sections without any visible structure markers | |
Make the CTA feel like a natural part of the conversation, focusing on what the reader will gain | |
Avoid promotional language in the CTA | |
DO NOT explain or mention the formula parts in the text | |
Separate each story with "---" | |
Format: Three clean story texts, each starting with a headline, separated by "---", no labels, no explanations. | |
""" | |
response = model.generate_content([full_prompt], generation_config={"temperature": temperature}) | |
return response.parts[0].text if response and response.parts else "Error al generar contenido." | |
# Configurar la aplicación Streamlit | |
st.set_page_config(page_title="Story Generator", page_icon=":pencil:", layout="wide") | |
st.markdown(apply_styles(), unsafe_allow_html=True) # Add this line here | |
# Leer y mostrar el manual en el sidebar | |
with open("manual.md", "r", encoding="utf-8") as file: | |
manual_content = file.read() | |
st.sidebar.markdown(manual_content) | |
# Título de la app | |
st.markdown("<h1>Story Genius Maker</h1>", unsafe_allow_html=True) | |
st.markdown("<h3>Teje historias inolvidables en segundos, guiado por la magia de la inteligencia artificial que da vida a tus ideas en relatos cautivadores.</h3>", unsafe_allow_html=True) | |
# Crear dos columnas | |
col1, col2 = st.columns([1, 1]) | |
# Columna izquierda para inputs | |
# Remove the benefit input field | |
with col1: | |
# Entrada de texto principal | |
input_prompt = st.text_area("Escribe de qué quieres que trate la historia:", placeholder="Escribe aquí tu idea...") | |
target_audience = st.text_input("Público Objetivo:", placeholder="Ejemplo: Profesionales de 25-35 años...") | |
cta_type = st.text_input("Llamado a la acción:", placeholder="Ejemplo: Incribete a nuestro Curso de marketing digital...") | |
with st.expander("Opciones avanzadas"): | |
formula_type = st.selectbox( | |
"Fórmula narrativa:", | |
options=list(story_formulas.keys()), | |
) | |
mood = st.selectbox( | |
"Ángulo de Historia:", | |
options=list(story_moods.keys()), | |
) | |
length = st.slider("Longitud del texto (palabras):", | |
min_value=100, | |
max_value=150, | |
value=125, | |
step=5) | |
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 historias más creativas pero menos predecibles. Valores más bajos producen historias más consistentes." | |
) | |
generate_button = st.button("Generar historia") | |
# Al inicio de la app | |
apply_styles() | |
# En la sección donde muestras la historia generada | |
with col2: | |
if generate_button: | |
response = get_gemini_response( | |
input_prompt, formula_type, length, | |
mood, target_audience, cta_type, | |
temperature | |
) | |
stories = response.split("---") | |
for i, story in enumerate(stories, 1): | |
st.subheader(f"Historia {i}:") | |
st.write(story.strip()) | |
st.divider() |