JeCabrera commited on
Commit
182e34e
·
verified ·
1 Parent(s): 87ee28e

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +310 -325
app.py CHANGED
@@ -1,326 +1,311 @@
1
- from dotenv import load_dotenv
2
- import streamlit as st
3
- import os
4
- import google.generativeai as genai
5
- from puv_formulas import puv_formulas
6
- from styles import apply_styles, format_creative_response
7
- from options import tone_options, creative_approaches
8
- import PyPDF2
9
- import docx
10
- from PIL import Image
11
- import datetime # Add this import for timestamp
12
-
13
- # Cargar variables de entorno
14
- load_dotenv()
15
-
16
- # Configurar API de Google Gemini
17
- genai.configure(api_key=os.getenv("GOOGLE_API_KEY"))
18
-
19
- # Función para obtener la respuesta del modelo Gemini
20
- def get_gemini_response(product_service, target_audience, main_benefit, tone_of_voice, temperature,
21
- file_content="", image_parts=None, creative_approach=""):
22
- # Check if we have at least one source of information
23
- has_file_content = bool(file_content.strip())
24
- has_image = image_parts is not None
25
- has_text_input = target_audience or product_service or main_benefit
26
-
27
- if not (has_file_content or has_image or has_text_input):
28
- return "Debes proporcionar al menos un tipo de información: público objetivo, producto/servicio, beneficio principal o un archivo de referencia."
29
-
30
- # If we only have file content but no other inputs, we can proceed
31
- if (has_file_content or has_image) and not has_text_input:
32
- # File-only mode
33
- business_info = "Analyze the provided reference material to extract business information.\n"
34
- else:
35
- # Regular mode with validation
36
- if not target_audience:
37
- return "El campo de público objetivo es obligatorio cuando no se proporciona un archivo de referencia completo."
38
-
39
- if not product_service:
40
- return "Debes proporcionar tu producto/servicio cuando no se proporciona un archivo de referencia completo."
41
-
42
- if not main_benefit:
43
- return "Debes proporcionar el beneficio principal cuando no se proporciona un archivo de referencia completo."
44
-
45
- # Adjust prompt based on what's provided
46
- business_info = f"Target Audience: {target_audience}\n"
47
- business_info += f"Product/Service: {product_service}\n"
48
- business_info += f"Main Benefit: {main_benefit}\n"
49
-
50
- if tone_of_voice:
51
- business_info += f"Brand Tone of Voice: {tone_of_voice}\n"
52
-
53
- # Add file content if available
54
- reference_info = ""
55
- if file_content:
56
- reference_info = f"\nREFERENCE MATERIAL:\n{file_content}\n"
57
-
58
- model = genai.GenerativeModel('gemini-2.0-flash')
59
- full_prompt = f"""
60
- You are a Creative Concept expert. Analyze (internally only, do not output the analysis) the following information:
61
- BUSINESS INFORMATION:
62
- {business_info}
63
- {reference_info}
64
-
65
- 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.
66
-
67
- First, analyze (but don't output) these points:
68
- 1. TARGET AUDIENCE ANALYSIS:
69
- - What everyday concepts are they familiar with?
70
- - What TV shows, movies, or cultural references resonate with them?
71
- - What emotions and experiences are meaningful to them?
72
- - What mental images would be easy for them to recall?
73
-
74
- 2. PRODUCT/SERVICE ANALYSIS:
75
- - What is the main benefit or promise?
76
- - What makes it unique or different?
77
- - What transformation does it offer?
78
- - What process or journey does the customer go through?
79
-
80
- Based on your internal analysis, create THREE different Creative Concepts in Spanish language.
81
- Each concept should be a DIRECT ANALOGY or METAPHOR that connects your product/service to something completely different but familiar.
82
-
83
- Examples of good creative concepts:
84
- - "Escribir copy es como cocinar tu plato favorito porque necesitas los ingredientes correctos para que todos quieran probarlo"
85
- - "Tu negocio es como un equipo de fútbol: necesita buenos jugadores (productos) y una estrategia clara para ganar clientes"
86
- - "Tu curso es como Netflix: ofrece contenido que engancha y soluciones que la gente realmente quiere ver"
87
-
88
- For each concept, include:
89
-
90
- CONCEPT: A clear statement of the main benefit
91
- CREATIVITY: A direct analogy or metaphor connecting your product to something completely different but familiar
92
-
93
- CRITICAL INSTRUCTIONS:
94
- - Each concept MUST use a direct "X es como Y porque Z" structure
95
- - Use SIMPLE, EVERYDAY language that anyone can understand
96
- - Avoid technical jargon, complex words, or business terminology
97
- - Write as if you're explaining to a friend in a casual conversation
98
- - Use everyday objects, activities, movies, TV shows or cultural references everyone knows
99
- - Make the connection SURPRISING and UNEXPECTED - connect things that normally wouldn't be connected
100
- - Challenge conventional thinking by finding parallels between your product and something completely different
101
- - Create analogies that make people say "I never thought of it that way!"
102
- - Focus on the main benefit
103
- - Create clear mental images
104
- - Be easy to remember
105
- - Use the brand's tone of voice if provided
106
- - Format with proper spacing between sections
107
-
108
- Output EXACTLY in this format (no additional text) in Spanish language:
109
-
110
- CONCEPTO CREATIVO 1:
111
-
112
- Concepto:
113
- [Main message/benefit in simple, conversational language]
114
-
115
- Creatividad:
116
- [Direct analogy using everyday language: "X es como Y porque Z"]
117
-
118
-
119
- CONCEPTO CREATIVO 2:
120
-
121
- Concepto:
122
- [Main message/benefit]
123
-
124
- Creatividad:
125
- [Direct analogy: "X es como Y porque Z"]
126
-
127
-
128
- CONCEPTO CREATIVO 3:
129
-
130
- Concepto:
131
- [Main message/benefit]
132
-
133
- Creatividad:
134
- [Direct analogy: "X es como Y porque Z"]
135
- """
136
-
137
- # Handle text-only or text+image requests
138
- if image_parts:
139
- response = model.generate_content([full_prompt, image_parts], generation_config={"temperature": temperature})
140
- else:
141
- response = model.generate_content([full_prompt], generation_config={"temperature": temperature})
142
-
143
- return response.parts[0].text if response and response.parts else "Error generating content."
144
-
145
- # Configurar la aplicación Streamlit
146
- st.set_page_config(page_title="Generador de Ideas Creativas", page_icon="💡", layout="wide")
147
-
148
- # Aplicar estilos
149
- st.markdown(apply_styles(), unsafe_allow_html=True)
150
-
151
- # Título de la app
152
- st.markdown("<h1>Generador de Ideas Creativas</h1>", unsafe_allow_html=True)
153
- 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)
154
-
155
- # Sidebar manual
156
- with open("manual.md", "r", encoding="utf-8") as file:
157
- manual_content = file.read()
158
- st.sidebar.markdown(manual_content)
159
-
160
- # Crear dos columnas
161
- col1, col2 = st.columns([1, 1])
162
-
163
- # Columna izquierda para inputs
164
- # In the app.py file, update the main_benefit field label and create an accordion for tone options
165
- with col1:
166
- product_service = st.text_area(
167
- "¿Cuál es tu producto o servicio?",
168
- placeholder="Ejemplo: Curso de copywriting con IA, Programa de coaching..."
169
- )
170
-
171
- main_benefit = st.text_area(
172
- "¿Cuál es tu Oferta Dorada/PUV?",
173
- placeholder="Ejemplo: Aprender copywriting a través de transformaciones reales de textos..."
174
- )
175
-
176
- target_audience = st.text_area(
177
- "¿Cuál es tu público objetivo?",
178
- placeholder="Ejemplo: Emprendedores que quieren mejorar sus textos comerciales..."
179
- )
180
-
181
- # Generate button after main inputs
182
- generate_button = st.button("Generar Ideas Creativas")
183
-
184
- with st.expander("Opciones avanzadas"):
185
- # Replace nested expanders with a selectbox for tone selection
186
- st.write("Tono de voz de la marca (opcional)")
187
-
188
- # Use selectbox for tone selection
189
- selected_tone = st.selectbox(
190
- "Selecciona un tono:",
191
- options=list(tone_options.keys()),
192
- index=0,
193
- key="tone_selectbox"
194
- )
195
-
196
- # Display the description of the selected tone
197
- if selected_tone != "Ninguno":
198
- st.info(tone_options[selected_tone])
199
- # Store the selected tone
200
- st.session_state.selected_tone = selected_tone
201
- else:
202
- # Clear any previously selected tone
203
- if "selected_tone" in st.session_state:
204
- del st.session_state.selected_tone
205
-
206
- # Use the stored tone or empty string
207
- tone_of_voice = st.session_state.get("selected_tone", "")
208
-
209
- # Añadir cargador de archivos
210
- uploaded_file = st.file_uploader("📄 Archivo o imagen de referencia",
211
- type=['txt', 'pdf', 'docx', 'jpg', 'jpeg', 'png'])
212
-
213
- file_content = ""
214
- is_image = False
215
- image_parts = None
216
-
217
- if uploaded_file is not None:
218
- file_type = uploaded_file.name.split('.')[-1].lower()
219
-
220
- # Manejar archivos de texto
221
- if file_type in ['txt', 'pdf', 'docx']:
222
- if file_type == 'txt':
223
- try:
224
- file_content = uploaded_file.read().decode('utf-8')
225
- except Exception as e:
226
- st.error(f"Error al leer el archivo TXT: {str(e)}")
227
- file_content = ""
228
-
229
- elif file_type == 'pdf':
230
- try:
231
- pdf_reader = PyPDF2.PdfReader(uploaded_file)
232
- file_content = ""
233
- for page in pdf_reader.pages:
234
- file_content += page.extract_text() + "\n"
235
- except Exception as e:
236
- st.error(f"Error al leer el archivo PDF: {str(e)}")
237
- file_content = ""
238
-
239
- elif file_type == 'docx':
240
- try:
241
- doc = docx.Document(uploaded_file)
242
- file_content = "\n".join([para.text for para in doc.paragraphs])
243
- except Exception as e:
244
- st.error(f"Error al leer el archivo DOCX: {str(e)}")
245
- file_content = ""
246
-
247
- # Manejar archivos de imagen
248
- elif file_type in ['jpg', 'jpeg', 'png']:
249
- try:
250
- image = Image.open(uploaded_file)
251
- image_bytes = uploaded_file.getvalue()
252
- image_parts = {
253
- "mime_type": uploaded_file.type,
254
- "data": image_bytes
255
- }
256
- is_image = True
257
- except Exception as e:
258
- st.error(f"Error al procesar la imagen: {str(e)}")
259
- is_image = False
260
-
261
-
262
- # Add creative approach selector (moved outside nested expander)
263
- selected_approach = st.selectbox(
264
- "Enfoque creativo:",
265
- options=list(creative_approaches.keys()),
266
- index=0,
267
- key="approach_selectbox"
268
- )
269
-
270
- # Display the description of the selected approach
271
- st.info(creative_approaches[selected_approach])
272
-
273
- # Store the selected approach
274
- st.session_state.selected_approach = selected_approach
275
-
276
- # Temperature slider
277
- temperature = st.slider(
278
- "Nivel de creatividad:",
279
- min_value=0.0,
280
- max_value=2.0,
281
- value=1.0,
282
- step=0.1,
283
- help="Valores más altos generan ideas más creativas pero menos predecibles."
284
- )
285
-
286
- with col2:
287
- if generate_button:
288
- # Store the response in session state so it persists across reruns
289
- with st.spinner("Creando tus ideas creativas..."):
290
- st.session_state.creative_response = get_gemini_response(
291
- product_service,
292
- target_audience,
293
- main_benefit,
294
- tone_of_voice,
295
- temperature,
296
- file_content,
297
- image_parts,
298
- st.session_state.get("selected_approach", "")
299
- # Removed contrast_level parameter
300
- )
301
-
302
- # Display the response if it exists in session state
303
- if 'creative_response' in st.session_state:
304
- st.write("### Conceptos Creativos")
305
-
306
- # Format the response with custom styling
307
- formatted_response = format_creative_response(st.session_state.creative_response)
308
-
309
- # Use markdown with HTML to display the formatted response
310
- st.markdown(formatted_response, unsafe_allow_html=True)
311
-
312
- # Add download button if we have a valid response
313
- if st.session_state.creative_response and not st.session_state.creative_response.startswith("Error") and not st.session_state.creative_response.startswith("Debes"):
314
- # Get current timestamp for the filename
315
- timestamp = datetime.datetime.now().strftime("%Y%m%d_%H%M%S")
316
-
317
- # Prepare content for download (use the original unformatted response)
318
- download_content = st.session_state.creative_response
319
-
320
- # Download button
321
- st.download_button(
322
- label="DESCARGAR IDEAS CREATIVAS",
323
- data=download_content,
324
- file_name=f"conceptos_creativos_{timestamp}.txt",
325
- mime="text/plain"
326
  )
 
1
+ from dotenv import load_dotenv
2
+ import streamlit as st
3
+ import os
4
+ import google.generativeai as genai
5
+ from puv_formulas import puv_formulas
6
+ from styles import apply_styles, format_creative_response
7
+ from options import tone_options, creative_approaches
8
+ import PyPDF2
9
+ import docx
10
+ from PIL import Image
11
+ import datetime # Add this import for timestamp
12
+
13
+ # Cargar variables de entorno
14
+ load_dotenv()
15
+
16
+ # Configurar API de Google Gemini
17
+ genai.configure(api_key=os.getenv("GOOGLE_API_KEY"))
18
+
19
+ # Función para obtener la respuesta del modelo Gemini
20
+ def get_gemini_response(product_service, target_audience, main_benefit, tone_of_voice, temperature, file_content="", image_parts=None, creative_approach=""):
21
+ # Adjust prompt based on what's provided
22
+ business_info = f"Target Audience: {target_audience}\n"
23
+ business_info += f"Product/Service: {product_service}\n"
24
+ business_info += f"Main Benefit: {main_benefit}\n"
25
+
26
+ if tone_of_voice:
27
+ business_info += f"Brand Tone of Voice: {tone_of_voice}\n"
28
+
29
+ # Add creative approach to business info if provided
30
+ if creative_approach:
31
+ # Get the description from the dictionary
32
+ from options import creative_approaches
33
+ approach_description = creative_approaches.get(creative_approach, "")
34
+ business_info += f"\nCREATIVE APPROACH: {creative_approach}\n"
35
+ business_info += f"Description: {approach_description}\n"
36
+ business_info += f"IMPORTANT: Please follow this creative approach strictly when generating concepts.\n"
37
+
38
+ # Add file content if available
39
+ reference_info = ""
40
+ if file_content:
41
+ reference_info = f"\nREFERENCE MATERIAL:\n{file_content}\n"
42
+
43
+ model = genai.GenerativeModel('gemini-2.0-flash')
44
+ full_prompt = f"""
45
+ You are a Creative Concept expert. Analyze (internally only, do not output the analysis) the following information:
46
+ BUSINESS INFORMATION:
47
+ {business_info}
48
+ {reference_info}
49
+
50
+ 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.
51
+
52
+ First, analyze (but don't output) these points:
53
+ 1. TARGET AUDIENCE ANALYSIS:
54
+ - What everyday concepts are they familiar with?
55
+ - What TV shows, movies, or cultural references resonate with them?
56
+ - What emotions and experiences are meaningful to them?
57
+ - What mental images would be easy for them to recall?
58
+
59
+ 2. PRODUCT/SERVICE ANALYSIS:
60
+ - What is the main benefit or promise?
61
+ - What makes it unique or different?
62
+ - What transformation does it offer?
63
+ - What process or journey does the customer go through?
64
+
65
+ Based on your internal analysis, create THREE different Creative Concepts in Spanish language.
66
+ Each concept should be a DIRECT ANALOGY or METAPHOR that connects your product/service to something completely different but familiar.
67
+
68
+ Examples of good creative concepts:
69
+ - "Escribir copy es como cocinar tu plato favorito porque necesitas los ingredientes correctos para que todos quieran probarlo"
70
+ - "Tu negocio es como un equipo de fútbol: necesita buenos jugadores (productos) y una estrategia clara para ganar clientes"
71
+ - "Tu curso es como Netflix: ofrece contenido que engancha y soluciones que la gente realmente quiere ver"
72
+
73
+ For each concept, include:
74
+
75
+ CONCEPT: A clear statement of the main benefit
76
+ CREATIVITY: A direct analogy or metaphor connecting your product to something completely different but familiar
77
+
78
+ CRITICAL INSTRUCTIONS:
79
+ - Each concept MUST use a direct "X es como Y porque Z" structure
80
+ - Use SIMPLE, EVERYDAY language that anyone can understand
81
+ - Avoid technical jargon, complex words, or business terminology
82
+ - Write as if you're explaining to a friend in a casual conversation
83
+ - Use everyday objects, activities, movies, TV shows or cultural references everyone knows
84
+ - Make the connection SURPRISING and UNEXPECTED - connect things that normally wouldn't be connected
85
+ - Challenge conventional thinking by finding parallels between your product and something completely different
86
+ - Create analogies that make people say "I never thought of it that way!"
87
+ - Focus on the main benefit
88
+ - Create clear mental images
89
+ - Be easy to remember
90
+ - Use the brand's tone of voice if provided
91
+ - Format with proper spacing between sections
92
+
93
+ Output EXACTLY in this format (no additional text) in Spanish language:
94
+
95
+ CONCEPTO CREATIVO 1:
96
+
97
+ Concepto:
98
+ [Main message/benefit in simple, conversational language]
99
+
100
+ Creatividad:
101
+ [Direct analogy using everyday language: "X es como Y porque Z"]
102
+
103
+
104
+ CONCEPTO CREATIVO 2:
105
+
106
+ Concepto:
107
+ [Main message/benefit]
108
+
109
+ Creatividad:
110
+ [Direct analogy: "X es como Y porque Z"]
111
+
112
+
113
+ CONCEPTO CREATIVO 3:
114
+
115
+ Concepto:
116
+ [Main message/benefit]
117
+
118
+ Creatividad:
119
+ [Direct analogy: "X es como Y porque Z"]
120
+ """
121
+
122
+ # Handle text-only or text+image requests
123
+ if image_parts:
124
+ response = model.generate_content([full_prompt, image_parts], generation_config={"temperature": temperature})
125
+ else:
126
+ response = model.generate_content([full_prompt], generation_config={"temperature": temperature})
127
+
128
+ return response.parts[0].text if response and response.parts else "Error generating content."
129
+
130
+ # Configurar la aplicación Streamlit
131
+ st.set_page_config(page_title="Generador de Ideas Creativas", page_icon="💡", layout="wide")
132
+
133
+ # Aplicar estilos
134
+ st.markdown(apply_styles(), unsafe_allow_html=True)
135
+
136
+ # Título de la app
137
+ st.markdown("<h1>Generador de Ideas Creativas</h1>", unsafe_allow_html=True)
138
+ 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)
139
+
140
+ # Sidebar manual
141
+ with open("manual.md", "r", encoding="utf-8") as file:
142
+ manual_content = file.read()
143
+ st.sidebar.markdown(manual_content)
144
+
145
+ # Crear dos columnas
146
+ col1, col2 = st.columns([1, 1])
147
+
148
+ # Columna izquierda para inputs
149
+ # In the app.py file, update the main_benefit field label and create an accordion for tone options
150
+ with col1:
151
+ product_service = st.text_area(
152
+ "¿Cuál es tu producto o servicio?",
153
+ placeholder="Ejemplo: Curso de copywriting con IA, Programa de coaching..."
154
+ )
155
+
156
+ main_benefit = st.text_area(
157
+ "¿Cuál es tu Oferta Dorada/PUV?",
158
+ placeholder="Ejemplo: Aprender copywriting a través de transformaciones reales de textos..."
159
+ )
160
+
161
+ target_audience = st.text_area(
162
+ "¿Cuál es tu público objetivo?",
163
+ placeholder="Ejemplo: Emprendedores que quieren mejorar sus textos comerciales..."
164
+ )
165
+
166
+ # Generate button after main inputs
167
+ generate_button = st.button("Generar Ideas Creativas")
168
+
169
+ with st.expander("Opciones avanzadas"):
170
+ # Replace nested expanders with a selectbox for tone selection
171
+ st.write("Tono de voz de la marca (opcional)")
172
+
173
+ # Use selectbox for tone selection
174
+ selected_tone = st.selectbox(
175
+ "Selecciona un tono:",
176
+ options=list(tone_options.keys()),
177
+ index=0,
178
+ key="tone_selectbox"
179
+ )
180
+
181
+ # Display the description of the selected tone
182
+ if selected_tone != "Ninguno":
183
+ st.info(tone_options[selected_tone])
184
+ # Store the selected tone
185
+ st.session_state.selected_tone = selected_tone
186
+ else:
187
+ # Clear any previously selected tone
188
+ if "selected_tone" in st.session_state:
189
+ del st.session_state.selected_tone
190
+
191
+ # Use the stored tone or empty string
192
+ tone_of_voice = st.session_state.get("selected_tone", "")
193
+
194
+ # Añadir cargador de archivos
195
+ uploaded_file = st.file_uploader("📄 Archivo o imagen de referencia",
196
+ type=['txt', 'pdf', 'docx', 'jpg', 'jpeg', 'png'])
197
+
198
+ file_content = ""
199
+ is_image = False
200
+ image_parts = None
201
+
202
+ if uploaded_file is not None:
203
+ file_type = uploaded_file.name.split('.')[-1].lower()
204
+
205
+ # Manejar archivos de texto
206
+ if file_type in ['txt', 'pdf', 'docx']:
207
+ if file_type == 'txt':
208
+ try:
209
+ file_content = uploaded_file.read().decode('utf-8')
210
+ except Exception as e:
211
+ st.error(f"Error al leer el archivo TXT: {str(e)}")
212
+ file_content = ""
213
+
214
+ elif file_type == 'pdf':
215
+ try:
216
+ pdf_reader = PyPDF2.PdfReader(uploaded_file)
217
+ file_content = ""
218
+ for page in pdf_reader.pages:
219
+ file_content += page.extract_text() + "\n"
220
+ except Exception as e:
221
+ st.error(f"Error al leer el archivo PDF: {str(e)}")
222
+ file_content = ""
223
+
224
+ elif file_type == 'docx':
225
+ try:
226
+ doc = docx.Document(uploaded_file)
227
+ file_content = "\n".join([para.text for para in doc.paragraphs])
228
+ except Exception as e:
229
+ st.error(f"Error al leer el archivo DOCX: {str(e)}")
230
+ file_content = ""
231
+
232
+ # Manejar archivos de imagen
233
+ elif file_type in ['jpg', 'jpeg', 'png']:
234
+ try:
235
+ image = Image.open(uploaded_file)
236
+ image_bytes = uploaded_file.getvalue()
237
+ image_parts = {
238
+ "mime_type": uploaded_file.type,
239
+ "data": image_bytes
240
+ }
241
+ is_image = True
242
+ except Exception as e:
243
+ st.error(f"Error al procesar la imagen: {str(e)}")
244
+ is_image = False
245
+
246
+
247
+ # Add creative approach selector (moved outside nested expander)
248
+ selected_approach = st.selectbox(
249
+ "Enfoque creativo:",
250
+ options=list(creative_approaches.keys()),
251
+ index=0,
252
+ key="approach_selectbox"
253
+ )
254
+
255
+ # Display the description of the selected approach
256
+ st.info(creative_approaches[selected_approach])
257
+
258
+ # Store the selected approach
259
+ st.session_state.selected_approach = selected_approach
260
+
261
+ # Temperature slider
262
+ temperature = st.slider(
263
+ "Nivel de creatividad:",
264
+ min_value=0.0,
265
+ max_value=2.0,
266
+ value=1.0,
267
+ step=0.1,
268
+ help="Valores más altos generan ideas más creativas pero menos predecibles."
269
+ )
270
+
271
+ with col2:
272
+ if generate_button:
273
+ # Store the response in session state so it persists across reruns
274
+ with st.spinner("Creando tus ideas creativas..."):
275
+ st.session_state.creative_response = get_gemini_response(
276
+ product_service,
277
+ target_audience,
278
+ main_benefit,
279
+ tone_of_voice,
280
+ temperature,
281
+ file_content,
282
+ image_parts,
283
+ st.session_state.get("selected_approach", "")
284
+ # Removed contrast_level parameter
285
+ )
286
+
287
+ # Display the response if it exists in session state
288
+ if 'creative_response' in st.session_state:
289
+ st.write("### Conceptos Creativos")
290
+
291
+ # Format the response with custom styling
292
+ formatted_response = format_creative_response(st.session_state.creative_response)
293
+
294
+ # Use markdown with HTML to display the formatted response
295
+ st.markdown(formatted_response, unsafe_allow_html=True)
296
+
297
+ # Add download button if we have a valid response
298
+ if st.session_state.creative_response and not st.session_state.creative_response.startswith("Error") and not st.session_state.creative_response.startswith("Debes"):
299
+ # Get current timestamp for the filename
300
+ timestamp = datetime.datetime.now().strftime("%Y%m%d_%H%M%S")
301
+
302
+ # Prepare content for download (use the original unformatted response)
303
+ download_content = st.session_state.creative_response
304
+
305
+ # Download button
306
+ st.download_button(
307
+ label="DESCARGAR IDEAS CREATIVAS",
308
+ data=download_content,
309
+ file_name=f"conceptos_creativos_{timestamp}.txt",
310
+ mime="text/plain"
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
311
  )