Migue1804 commited on
Commit
99b3c55
·
verified ·
1 Parent(s): 8da5655

Upload 5 files

Browse files
.gitattributes CHANGED
@@ -33,3 +33,4 @@ saved_model/**/* filter=lfs diff=lfs merge=lfs -text
33
  *.zip filter=lfs diff=lfs merge=lfs -text
34
  *.zst filter=lfs diff=lfs merge=lfs -text
35
  *tfevents* filter=lfs diff=lfs merge=lfs -text
 
 
33
  *.zip filter=lfs diff=lfs merge=lfs -text
34
  *.zst filter=lfs diff=lfs merge=lfs -text
35
  *tfevents* filter=lfs diff=lfs merge=lfs -text
36
+ imagenes/Tu[[:space:]]mundo[[:space:]]en[[:space:]]una[[:space:]]servilleta[[:space:]]-[[:space:]]Dan[[:space:]]Roam.png filter=lfs diff=lfs merge=lfs -text
GD App.zip ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:427cf83a082b68de1b06e51867e4d59a0d40735e34b09c6e21039a5868cec8e4
3
+ size 204791
bookbot.py ADDED
@@ -0,0 +1,364 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import streamlit as st
2
+ import os
3
+ import requests
4
+ import base64
5
+ from typing import List, Dict
6
+
7
+ # Configuración de la aplicación
8
+ st.set_page_config(
9
+ page_title="Biblioteca de Resúmenes de Libros",
10
+ layout="wide",
11
+ initial_sidebar_state="expanded"
12
+ )
13
+
14
+ # Función para cargar imagen y codificarla en base64
15
+ def get_image_base64(image_path):
16
+ """Carga una imagen y la convierte a base64 para mostrarla"""
17
+ try:
18
+ with open(image_path, "rb") as img_file:
19
+ return base64.b64encode(img_file.read()).decode()
20
+ except Exception:
21
+ return None
22
+
23
+ # CSS personalizado para un diseño moderno y minimalista
24
+ def apply_custom_css():
25
+ st.markdown("""
26
+ <style>
27
+ /* Estilos generales */
28
+ .main {
29
+ padding: 2rem 3rem;
30
+ background-color: #f8f9fa;
31
+ }
32
+
33
+ /* Título principal */
34
+ .main h1 {
35
+ color: #1E3A8A;
36
+ font-size: 2.5rem;
37
+ font-weight: 600;
38
+ margin-bottom: 2rem;
39
+ }
40
+
41
+ /* Subtítulos */
42
+ .main h2, .main h3 {
43
+ color: #1E3A8A;
44
+ font-weight: 500;
45
+ }
46
+
47
+ /* Contenedor de chat */
48
+ .chat-container {
49
+ background-color: white;
50
+ border-radius: 8px;
51
+ padding: 20px;
52
+ margin-top: 20px;
53
+ box-shadow: 0 2px 10px rgba(0,0,0,0.05);
54
+ }
55
+
56
+ /* Mensajes del usuario */
57
+ .user-message {
58
+ background-color: #E7F3FF;
59
+ border-radius: 15px 15px 0 15px;
60
+ padding: 10px 15px;
61
+ margin: 10px 0;
62
+ max-width: 80%;
63
+ align-self: flex-end;
64
+ margin-left: auto;
65
+ }
66
+
67
+ /* Mensajes del asistente */
68
+ .assistant-message {
69
+ background-color: #F0F0F0;
70
+ border-radius: 15px 15px 15px 0;
71
+ padding: 10px 15px;
72
+ margin: 10px 0;
73
+ max-width: 80%;
74
+ }
75
+
76
+ /* Campo de entrada de texto */
77
+ .stTextInput input {
78
+ border-radius: 20px;
79
+ border: 1px solid #E0E0E0;
80
+ padding: 10px 15px;
81
+ font-size: 1rem;
82
+ }
83
+
84
+ /* Tarjeta del libro */
85
+ .book-card {
86
+ background-color: white;
87
+ border-radius: 8px;
88
+ padding: 15px;
89
+ box-shadow: 0 2px 8px rgba(0,0,0,0.05);
90
+ margin-bottom: 20px;
91
+ }
92
+
93
+ /* Imagen del libro */
94
+ .book-image {
95
+ width: 100%;
96
+ border-radius: 4px;
97
+ margin-bottom: 15px;
98
+ }
99
+
100
+ /* Separador */
101
+ hr {
102
+ margin: 1.5rem 0;
103
+ border: 0;
104
+ border-top: 1px solid #E0E0E0;
105
+ }
106
+
107
+ /* Botón de envío */
108
+ .stButton button {
109
+ background-color: #1E3A8A;
110
+ color: white;
111
+ border-radius: 20px;
112
+ padding: 5px 20px;
113
+ font-weight: 500;
114
+ border: none;
115
+ transition: all 0.3s;
116
+ }
117
+
118
+ .stButton button:hover {
119
+ background-color: #2563EB;
120
+ box-shadow: 0 4px 8px rgba(37, 99, 235, 0.2);
121
+ }
122
+
123
+ /* Sidebar */
124
+ .sidebar .sidebar-content {
125
+ background-color: #F8F9FA;
126
+ padding: 20px;
127
+ }
128
+
129
+ /* Título del sidebar */
130
+ .sidebar h2 {
131
+ color: #1E3A8A;
132
+ font-size: 1.5rem;
133
+ font-weight: 500;
134
+ margin-bottom: 1rem;
135
+ }
136
+ </style>
137
+ """, unsafe_allow_html=True)
138
+
139
+ # Función para cargar resúmenes de libros desde archivos de texto
140
+ def cargar_resumenes_libros(carpeta_libros: str) -> List[Dict[str, str]]:
141
+ """
142
+ Carga resúmenes de libros desde archivos de texto en una carpeta específica.
143
+
144
+ Args:
145
+ carpeta_libros (str): Ruta de la carpeta que contiene los resúmenes de libros.
146
+
147
+ Returns:
148
+ List[Dict[str, str]]: Lista de diccionarios con información de los libros.
149
+ """
150
+ resumenes = []
151
+ try:
152
+ # Verificar si la carpeta existe
153
+ if not os.path.exists(carpeta_libros):
154
+ st.error(f"La carpeta {carpeta_libros} no existe.")
155
+ return resumenes
156
+
157
+ # Listar archivos de texto en la carpeta
158
+ archivos = [f for f in os.listdir(carpeta_libros) if f.endswith('.txt')]
159
+
160
+ if not archivos:
161
+ st.warning("No se encontraron archivos de resúmenes en la carpeta.")
162
+ return resumenes
163
+
164
+ # Cargar cada archivo de resumen
165
+ for archivo in archivos:
166
+ ruta_archivo = os.path.join(carpeta_libros, archivo)
167
+ try:
168
+ with open(ruta_archivo, 'r', encoding='utf-8') as f:
169
+ # Extraer título del nombre del archivo (sin extensión)
170
+ titulo = os.path.splitext(archivo)[0]
171
+ # Leer contenido del archivo
172
+ contenido = f.read().strip()
173
+
174
+ # Extraer un breve resumen (primeros 200 caracteres)
175
+ breve_resumen = contenido[:200] + "..." if len(contenido) > 200 else contenido
176
+
177
+ # Agregar resumen a la lista
178
+ resumenes.append({
179
+ "titulo": titulo,
180
+ "resumen": contenido,
181
+ "breve_resumen": breve_resumen
182
+ })
183
+ except Exception as e:
184
+ st.error(f"Error al leer el archivo {archivo}: {str(e)}")
185
+
186
+ except Exception as e:
187
+ st.error(f"Error al cargar los resúmenes: {str(e)}")
188
+
189
+ return resumenes
190
+
191
+ # Configuración de la API de Hugging Face
192
+ API_URL = "https://api-inference.huggingface.co/models/deepseek-ai/DeepSeek-R1-Distill-Qwen-32B"
193
+
194
+ # Inicializar la sesión state para el historial de chat si no existe
195
+ if 'chat_history' not in st.session_state:
196
+ st.session_state.chat_history = []
197
+
198
+ # Función para obtener la API key de Hugging Face desde secrets
199
+ @st.cache_resource
200
+ def get_huggingface_api_key():
201
+ """Obtener la API key de Hugging Face desde secrets"""
202
+ try:
203
+ # Intenta acceder al token usando la clave HF_TOKEN
204
+ return st.secrets["HF_TOKEN"]
205
+ except KeyError:
206
+ # Si no está disponible con esa clave, intenta el formato anterior
207
+ try:
208
+ return st.secrets["huggingface"]["api_key"]
209
+ except:
210
+ return None
211
+
212
+ # Función para enviar solicitudes a la API de Hugging Face
213
+ def query_huggingface(payload):
214
+ """Envía una solicitud a la API de Hugging Face y retorna la respuesta"""
215
+ api_key = get_huggingface_api_key()
216
+ if not api_key:
217
+ st.error("No se proporcionó una API key de Hugging Face.")
218
+ return None
219
+
220
+ headers = {"Authorization": f"Bearer {api_key}"}
221
+ try:
222
+ # Añadido verify=False para ignorar la verificación SSL
223
+ response = requests.post(API_URL, headers=headers, json=payload, timeout=60, verify=False)
224
+ response.raise_for_status()
225
+ return response.json()
226
+ except requests.exceptions.Timeout:
227
+ st.error("La solicitud a la API de Hugging Face ha excedido el tiempo de espera.")
228
+ return None
229
+ except requests.exceptions.HTTPError as e:
230
+ st.error(f"Error HTTP: {e.response.status_code} - {e.response.text}")
231
+ return None
232
+ except Exception as e:
233
+ st.error(f"Error al comunicarse con la API de Hugging Face: {str(e)}")
234
+ return None
235
+
236
+ # Interfaz principal de la aplicación
237
+ def main():
238
+ # Aplicar CSS personalizado
239
+ apply_custom_css()
240
+
241
+ # Título principal
242
+ st.title("📚 Biblioteca de Resúmenes de Libros")
243
+
244
+ # Cargar resúmenes de libros
245
+ carpeta_libros = "libros" # Asegúrate de que esta carpeta exista en tu proyecto
246
+ resumenes = cargar_resumenes_libros(carpeta_libros)
247
+
248
+ # Verificar si se cargaron resúmenes
249
+ if not resumenes:
250
+ st.warning("No se pudieron cargar los resúmenes de libros.")
251
+ return
252
+
253
+ # Selector de libros (en la barra lateral)
254
+ with st.sidebar:
255
+ st.header("Selección de Libro")
256
+ titulos_libros = [libro["titulo"] for libro in resumenes]
257
+ libro_seleccionado = st.selectbox("Elige un libro para explorar", titulos_libros)
258
+
259
+ # Encontrar la información del libro seleccionado
260
+ libro_actual = next(
261
+ (libro for libro in resumenes if libro["titulo"] == libro_seleccionado),
262
+ None
263
+ )
264
+
265
+ if libro_actual:
266
+ st.subheader("Resumen Breve")
267
+ st.markdown(f"<div class='sidebar-summary'>{libro_actual['breve_resumen']}</div>", unsafe_allow_html=True)
268
+
269
+ # Información sobre el modelo
270
+ st.markdown("---")
271
+ st.caption("Asistente virtual potenciado por deepseek-ai/DeepSeek-R1-Distill-Qwen-32B")
272
+
273
+ # Contenido principal
274
+ if libro_actual:
275
+ col1, col2 = st.columns([1, 2])
276
+
277
+ with col1:
278
+ # Mostrar imagen del libro (buscar en la carpeta "imagenes")
279
+ st.markdown("<div class='book-card'>", unsafe_allow_html=True)
280
+
281
+ # Intentar cargar la imagen del libro
282
+ imagen_path = f"imagenes/{libro_seleccionado}.png"
283
+ if os.path.exists(imagen_path):
284
+ st.image(imagen_path, caption=libro_seleccionado, use_container_width=True)
285
+ else:
286
+ # Mostrar imagen de placeholder si no existe
287
+ st.error(f"Imagen no encontrada: {imagen_path}")
288
+ st.markdown("ℹ️ **Nota**: Asegúrate de tener una carpeta 'imagenes' con archivos PNG que coincidan con los nombres de tus libros.")
289
+
290
+ st.markdown("</div>", unsafe_allow_html=True)
291
+
292
+ with col2:
293
+ # Sección del chatbot
294
+ st.markdown("<div class='chat-container'>", unsafe_allow_html=True)
295
+ st.subheader("💬 Consulta sobre este libro")
296
+
297
+ # Mostrar el historial de chat
298
+ for message in st.session_state.chat_history:
299
+ if message["role"] == "user":
300
+ st.markdown(f"<div class='user-message'><strong>😀 Tú:</strong> {message['content']}</div>", unsafe_allow_html=True)
301
+ else:
302
+ st.markdown(f"<div class='assistant-message'><strong>🤖 Asistente:</strong> {message['content']}</div>", unsafe_allow_html=True)
303
+
304
+ # Crear el widget de entrada de usuario
305
+ user_input = st.text_input("", key="user_query", placeholder="Escribe tu pregunta sobre el libro...")
306
+ send_button = st.button("Enviar")
307
+
308
+ # Procesar la entrada del usuario
309
+ if user_input and send_button:
310
+ # Preparar el contexto
311
+ context = f"""
312
+ CONTEXTO DEL LIBRO:
313
+ Título: {libro_seleccionado}
314
+ Resumen: {libro_actual['resumen']}
315
+
316
+ PREGUNTA DEL USUARIO:
317
+ {user_input}
318
+
319
+ Responde de manera concisa y precisa, basándote en el resumen y contexto del libro.
320
+ """
321
+
322
+ # Mostrar un mensaje de espera personalizado con icono
323
+ with st.spinner("🧠 Pensando..."):
324
+ # Llamar a la API de Hugging Face
325
+ payload = {
326
+ "inputs": context,
327
+ "parameters": {
328
+ "max_new_tokens": 250,
329
+ "temperature": 0.7,
330
+ "top_p": 0.9,
331
+ "do_sample": True
332
+ }
333
+ }
334
+
335
+ response = query_huggingface(payload)
336
+
337
+ if response:
338
+ # Extraer la respuesta del modelo
339
+ if isinstance(response, list) and len(response) > 0:
340
+ bot_response = response[0].get("generated_text", "")
341
+ # Intentar extraer solo la respuesta del asistente
342
+ try:
343
+ bot_response = bot_response.split("Responde de manera concisa y precisa")[-1]
344
+ if "PREGUNTA DEL USUARIO:" in bot_response:
345
+ bot_response = bot_response.split("PREGUNTA DEL USUARIO:")[-1]
346
+ bot_response = bot_response.strip()
347
+ except:
348
+ # Si falla la extracción, usar la respuesta completa
349
+ pass
350
+ else:
351
+ bot_response = str(response)
352
+
353
+ # Agregar al historial de chat
354
+ st.session_state.chat_history.append({"role": "user", "content": user_input})
355
+ st.session_state.chat_history.append({"role": "assistant", "content": bot_response})
356
+
357
+ # Recargar la página para mostrar la nueva respuesta
358
+ st.experimental_rerun()
359
+
360
+ st.markdown("</div>", unsafe_allow_html=True)
361
+
362
+ # Ejecutar la aplicación principal
363
+ if __name__ == "__main__":
364
+ main()
imagenes/Tu mundo en una servilleta - Dan Roam.png ADDED

Git LFS Details

  • SHA256: db7fac73d7327e1fd7ef2bec6cd2b4a84ce43f1a4f49aee5829bba93c3dc3280
  • Pointer size: 131 Bytes
  • Size of remote file: 186 kB
libros/Tu mundo en una servilleta - Dan Roam.txt ADDED
@@ -0,0 +1,49 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ "The Back of the Napkin" por Dan Roam
2
+ Este resumen se centra en el marco de 6 preguntas, el SQVID y las estrategias visuales recomendadas en el libro "The Back of the Napkin" de Dan Roam para resolver problemas y vender ideas.
3
+
4
+ El libro argumenta que el pensamiento visual, utilizando dibujos sencillos, es una herramienta poderosa para la resolución de problemas y la comunicación efectiva. Roam explica que cualquier problema se puede aclarar con una imagen, y cualquier imagen se puede crear utilizando un conjunto simple de herramientas y reglas. [1]
5
+
6
+ El Marco de las 6 Preguntas (6W)
7
+ Roam propone un marco de seis preguntas fundamentales, conocidas como las 6W, para analizar y abordar cualquier problema:
8
+
9
+ Quién/Qué (Who/What): Define los actores y objetos involucrados.
10
+ Cuánto (How Much): Analiza las cantidades, medidas y datos.
11
+ Dónde (Where): Ubica el problema en un contexto espacial.
12
+ Cuándo (When): Establece un marco temporal para el problema.
13
+ Cómo (How): Describe los procesos y relaciones de causa y efecto.
14
+ Por qué (Why): Explora las razones, motivaciones y causas subyacentes.
15
+ Estas preguntas no solo ayudan a comprender el problema, sino que también guían la elección del gráfico o estrategia visual más efectiva para comunicarlo. [2, 3]
16
+
17
+ El SQVID como Herramienta de Imaginación
18
+ El SQVID es un acrónimo que representa cinco preguntas para activar la imaginación visual y explorar diferentes perspectivas de una idea:
19
+
20
+ Simple (Simple) vs. Elaborado (Elaborate): ¿Se necesita una representación simple o detallada?
21
+ Cualitativo (Qualitative) vs. Cuantitativo (Quantitative): ¿Se enfatizan las características o los datos numéricos?
22
+ Visión (Vision) vs. Ejecución (Execution): ¿Se busca inspirar o mostrar los pasos concretos?
23
+ Individual (Individual) vs. Comparación (Comparison): ¿Se presenta una sola idea o se compara con otras?
24
+ Cambio (Change) vs. Status Quo: ¿Se propone una transformación o se describe la situación actual? [4, 5]
25
+ Al responder estas preguntas, se pueden generar múltiples representaciones visuales de una idea y elegir la más efectiva para la audiencia y el objetivo. [5, 6]
26
+
27
+ Gráficos y Estrategias Visuales Recomendadas
28
+ El libro presenta seis marcos visuales principales, cada uno correspondiente a una de las 6W:
29
+
30
+ Retrato (Portrait): Para mostrar quién/qué (ej. un organigrama, un diagrama de personajes) [7, 8]
31
+ Gráfico (Chart): Para visualizar cuánto (ej. gráfico de barras, gráfico circular) [7, 8]
32
+ Mapa (Map): Para representar dónde (ej. mapa mental, diagrama de flujo de procesos) [7, 8]
33
+ Línea de Tiempo (Timeline): Para ilustrar cuándo (ej. cronograma, diagrama de Gantt) [7, 8]
34
+ Diagrama de Flujo (Flowchart): Para explicar cómo (ej. diagrama de flujo de trabajo, algoritmo) [7, 8]
35
+ Gráfico de Múltiples Variables (Multiple-variable Plot): Para analizar por qué (ej. gráfico de dispersión, mapa de calor) [7, 8]
36
+ El libro ofrece ejemplos concretos y consejos prácticos para dibujar cada tipo de gráfico y adaptarlo al problema específico. [9]
37
+
38
+ Combinando el Marco de 6W y el SQVID: El Codex
39
+ El Codex de Pensamiento Visual es una herramienta que combina las 6W y el SQVID para guiar la creación de la imagen más efectiva. Permite seleccionar el marco visual adecuado (ej. mapa) y la versión más apropiada según el SQVID (ej. simple, cualitativo). [10-12]
40
+
41
+ Consejos para "Mostrar y Contar"
42
+ El libro también destaca la importancia de saber presentar las imágenes de manera efectiva. Se recomienda un proceso de "mostrar y contar" que implica:
43
+
44
+ Mirar en Voz Alta (Looking Aloud): Guiar a la audiencia a través de los elementos visuales clave.
45
+ Ver en Voz Alta (Seeing Aloud): Ayudar a la audiencia a interpretar la información visual y descubrir patrones.
46
+ Imaginar en Voz Alta (Imagining Aloud): Fomentar la generación de ideas y soluciones a partir de la imagen.
47
+ Mostrar en Voz Alta (Showing Aloud): Presentar la imagen como un punto de partida para la conversación y la toma de decisiones. [13-15]
48
+ En resumen, "The Back of the Napkin" ofrece un enfoque práctico y accesible para utilizar el pensamiento visual como herramienta para la resolución de problemas y la comunicación efectiva en el mundo empresarial.
49
+
requirements.txt ADDED
@@ -0,0 +1,4 @@
 
 
 
 
 
1
+ streamlit
2
+ pandas
3
+ plotly
4
+ prophet