lozanopastor commited on
Commit
3813ca8
·
verified ·
1 Parent(s): 23aeff8

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +92 -88
app.py CHANGED
@@ -39,33 +39,32 @@ css_style = """
39
  border-radius: 5px;
40
  border: 1px solid #ccc;
41
  }
42
- .sugerencias-box {
43
- padding: 15px;
44
- background-color: #fff;
45
- border-radius: 10px;
46
  border: 1px solid #e0e0e0;
 
 
47
  margin: 10px 0;
 
48
  }
49
- .suggestion-button {
50
  width: 100%;
51
- text-align: left;
52
- margin: 5px 0;
53
- padding: 10px;
54
  border-radius: 5px;
55
- border: 1px solid #e0e0e0;
56
- background-color: #f8f9fa;
57
  cursor: pointer;
58
- transition: all 0.3s;
59
  }
60
- .suggestion-button:hover {
61
- background-color: #e9ecef;
62
- border-color: #ced4da;
63
  }
64
  </style>
65
  """
66
 
67
  def eliminar_proceso_pensamiento(texto):
68
- texto_limpio = re.sub(r'', '', texto, flags=re.DOTALL)
69
  lineas = [line.strip() for line in texto_limpio.split('\n') if line.strip()]
70
  return lineas[-1] if lineas else "Respuesta no disponible"
71
 
@@ -109,9 +108,9 @@ def get_conversational_chain():
109
 
110
  def extract_metadata(vector_store):
111
  metadata_questions = {
112
- "title": "¿Cual es o podría ser el título del documento? Redacta una sola frase",
113
- "entity": "¿A qué entidad u organización pertenece este documento?",
114
- "date": "¿En qué fecha se implantará el contenido? Si no se detalla responde \"No se especifica\""
115
  }
116
 
117
  metadata = {}
@@ -132,38 +131,19 @@ def mostrar_respuesta(texto):
132
  with st.container():
133
  st.markdown(f'<div class="response-box">{texto}</div>', unsafe_allow_html=True)
134
 
135
- def procesar_consulta(user_question):
136
- if 'vector_store' not in st.session_state:
137
- st.error("Por favor carga un documento primero")
138
- return
139
-
140
- chain = get_conversational_chain()
141
- docs = st.session_state.vector_store.similarity_search(user_question)
142
-
143
- with st.spinner("Analizando documento..."):
144
- response = chain(
145
- {"input_documents": docs, "question": user_question},
146
- return_only_outputs=True
147
- )
148
-
149
- respuesta_final = eliminar_proceso_pensamiento(response['output_text'])
150
- mostrar_respuesta(respuesta_final)
151
-
152
  def generar_sugerencias():
153
- """Genera preguntas sugeridas usando los chunks más relevantes del documento"""
154
  if 'vector_store' not in st.session_state:
155
  return []
156
 
157
  try:
158
- # Obtener los fragmentos más relevantes
159
  docs = st.session_state.vector_store.similarity_search("", k=3)
160
  context = "\n".join([doc.page_content for doc in docs])
161
 
162
- # Prompt para generación de sugerencias
163
  prompt_template = """
164
- Basado en el siguiente contexto, genera exactamente 3 preguntas simples en español.
165
- Las preguntas deben ser muy generales, fáciles de entender y no específicas.
166
- Formato: Cada pregunta debe ser breve (menos de 8 palabras).
167
 
168
  Contexto:
169
  {context}
@@ -173,39 +153,54 @@ def generar_sugerencias():
173
  """
174
 
175
  model = ChatGroq(
176
- temperature=0.7,
177
  model_name="deepseek-r1-distill-llama-70b",
178
  groq_api_key=os.getenv("GROQ_API_KEY")
179
  )
180
 
181
  response = model.invoke(prompt_template.format(context=context))
182
 
183
- # Procesar la respuesta para extraer las preguntas
184
  preguntas = []
185
  for line in response.content.split("\n"):
186
- if line.strip() and any(c.isdigit() for c in line[:3]):
187
- pregunta = line.split('.', 1)[1].strip() if '.' in line else line.strip()
 
188
  if pregunta:
189
- preguntas.append(pregunta)
190
 
191
- return preguntas[:3] # Asegurar máximo 3 preguntas
192
 
193
  except Exception as e:
194
  st.error(f"Error generando sugerencias: {str(e)}")
195
  return []
196
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
197
  def main():
198
  st.set_page_config(page_title="PDF Consultor 🔍", page_icon="🔍", layout="wide")
199
  st.title("PDF Consultor 🔍")
200
  st.markdown(css_style, unsafe_allow_html=True)
201
 
202
- # Inicializa estados de sesión
203
- if 'documento_cargado' not in st.session_state:
204
- st.session_state.documento_cargado = False
205
- if 'sugerencias' not in st.session_state:
206
- st.session_state.sugerencias = []
207
- if 'pregunta_actual' not in st.session_state:
208
- st.session_state.pregunta_actual = ""
209
 
210
  # Sidebar - Carga de documentos
211
  with st.sidebar:
@@ -217,7 +212,7 @@ def main():
217
  label_visibility="collapsed"
218
  )
219
 
220
- # Procesamiento automático al cargar documentos
221
  if pdf_docs and not st.session_state.documento_cargado:
222
  with st.spinner("Analizando documento..."):
223
  try:
@@ -235,62 +230,71 @@ def main():
235
  except Exception as e:
236
  st.error(f"Error procesando documento: {str(e)}")
237
 
238
- # Mostrar metadatos
239
  if 'metadata' in st.session_state:
 
240
  st.markdown("---")
241
  cols = st.columns(3)
242
- campos = [
243
  ("📄 Título", "title"),
244
  ("🏛️ Entidad", "entity"),
245
- ("📅 Fecha Implantación", "date")
246
  ]
247
 
248
- for col, (icono, key) in zip(cols, campos):
249
  with col:
250
  st.markdown(f"""
251
  <div class="metadata-box">
252
- <div class="metadata-title">{icono}</div>
253
  {st.session_state.metadata[key]}
254
  </div>
255
  """, unsafe_allow_html=True)
256
 
257
- # Mostrar sugerencias
258
  if st.session_state.sugerencias:
259
  st.markdown("---")
260
- st.subheader("💡 Preguntas sugeridas:")
261
-
262
- for i, pregunta in enumerate(st.session_state.sugerencias, 1):
263
- if st.button(
264
- pregunta,
265
- key=f"sug_{i}",
266
- help=f"Haz clic para usar esta pregunta",
267
- use_container_width=True
268
- ):
269
- # Guardar la pregunta seleccionada en el estado de sesión
270
- st.session_state.pregunta_actual = pregunta
271
-
272
- st.markdown("---")
 
 
 
 
 
273
 
274
- # Interfaz de consultas
275
  if st.session_state.documento_cargado:
276
- with st.form("consulta_form"):
277
  col1, col2 = st.columns([5, 1])
278
  with col1:
279
- user_question = st.text_input(
280
  "Escribe tu pregunta:",
281
- placeholder="Ej: ¿Qué normativa regula este proceso?",
282
- value=st.session_state.pregunta_actual, # Mostrar la pregunta seleccionada si existe
283
- key="input_pregunta"
284
  )
285
  with col2:
 
286
  enviar = st.form_submit_button("Enviar ▶")
 
 
 
 
 
 
287
 
288
- # Procesar la pregunta seleccionada o introducida manualmente
289
- if enviar or (st.session_state.pregunta_actual and not enviar):
290
- procesar_consulta(user_question or st.session_state.pregunta_actual)
291
- # Limpiar la pregunta actual después de procesarla
292
- if "pregunta_actual" in st.session_state:
293
- del st.session_state.pregunta_actual
294
 
295
- else:
296
- st.write("Por favor, sube un documento para continuar.")
 
39
  border-radius: 5px;
40
  border: 1px solid #ccc;
41
  }
42
+ .suggestion-container {
 
 
 
43
  border: 1px solid #e0e0e0;
44
+ border-radius: 8px;
45
+ padding: 15px;
46
  margin: 10px 0;
47
+ background: #f8f9fa;
48
  }
49
+ .suggestion-btn {
50
  width: 100%;
51
+ margin: 3px 0;
52
+ padding: 8px;
 
53
  border-radius: 5px;
54
+ border: 1px solid #252850;
55
+ background: white;
56
  cursor: pointer;
57
+ transition: all 0.2s;
58
  }
59
+ .suggestion-btn:hover {
60
+ background: #252850;
61
+ color: white;
62
  }
63
  </style>
64
  """
65
 
66
  def eliminar_proceso_pensamiento(texto):
67
+ texto_limpio = re.sub(r'<.*?>', '', texto, flags=re.DOTALL)
68
  lineas = [line.strip() for line in texto_limpio.split('\n') if line.strip()]
69
  return lineas[-1] if lineas else "Respuesta no disponible"
70
 
 
108
 
109
  def extract_metadata(vector_store):
110
  metadata_questions = {
111
+ "title": "¿Cuál es el título principal del documento?",
112
+ "entity": "¿A qué organización pertenece este documento?",
113
+ "date": "¿Qué fecha clave se menciona en el documento?"
114
  }
115
 
116
  metadata = {}
 
131
  with st.container():
132
  st.markdown(f'<div class="response-box">{texto}</div>', unsafe_allow_html=True)
133
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
134
  def generar_sugerencias():
135
+ """Genera preguntas sugeridas simples y generales"""
136
  if 'vector_store' not in st.session_state:
137
  return []
138
 
139
  try:
 
140
  docs = st.session_state.vector_store.similarity_search("", k=3)
141
  context = "\n".join([doc.page_content for doc in docs])
142
 
 
143
  prompt_template = """
144
+ Genera 3 preguntas simples en español basadas en este contexto.
145
+ Las preguntas deben ser generales y fáciles de entender.
146
+ Formato: Lista numerada sin explicaciones.
147
 
148
  Contexto:
149
  {context}
 
153
  """
154
 
155
  model = ChatGroq(
156
+ temperature=0.4,
157
  model_name="deepseek-r1-distill-llama-70b",
158
  groq_api_key=os.getenv("GROQ_API_KEY")
159
  )
160
 
161
  response = model.invoke(prompt_template.format(context=context))
162
 
 
163
  preguntas = []
164
  for line in response.content.split("\n"):
165
+ line = line.strip()
166
+ if line and line[0].isdigit():
167
+ pregunta = line.split('. ', 1)[1] if '. ' in line else line[2:]
168
  if pregunta:
169
+ preguntas.append(pregunta[:60])
170
 
171
+ return preguntas[:3]
172
 
173
  except Exception as e:
174
  st.error(f"Error generando sugerencias: {str(e)}")
175
  return []
176
 
177
+ def procesar_consulta(user_question):
178
+ if 'vector_store' not in st.session_state:
179
+ st.error("Por favor carga un documento primero")
180
+ return
181
+
182
+ chain = get_conversational_chain()
183
+ docs = st.session_state.vector_store.similarity_search(user_question)
184
+
185
+ with st.spinner("Analizando documento..."):
186
+ response = chain(
187
+ {"input_documents": docs, "question": user_question},
188
+ return_only_outputs=True
189
+ )
190
+
191
+ respuesta_final = eliminar_proceso_pensamiento(response['output_text'])
192
+ mostrar_respuesta(respuesta_final)
193
+
194
  def main():
195
  st.set_page_config(page_title="PDF Consultor 🔍", page_icon="🔍", layout="wide")
196
  st.title("PDF Consultor 🔍")
197
  st.markdown(css_style, unsafe_allow_html=True)
198
 
199
+ # Estados de sesión
200
+ estados_requeridos = ['documento_cargado', 'sugerencias', 'pregunta_actual']
201
+ for estado in estados_requeridos:
202
+ if estado not in st.session_state:
203
+ st.session_state[estado] = False if estado == 'documento_cargado' else []
 
 
204
 
205
  # Sidebar - Carga de documentos
206
  with st.sidebar:
 
212
  label_visibility="collapsed"
213
  )
214
 
215
+ # Procesamiento de documentos
216
  if pdf_docs and not st.session_state.documento_cargado:
217
  with st.spinner("Analizando documento..."):
218
  try:
 
230
  except Exception as e:
231
  st.error(f"Error procesando documento: {str(e)}")
232
 
233
+ # Sección principal
234
  if 'metadata' in st.session_state:
235
+ # Mostrar metadatos
236
  st.markdown("---")
237
  cols = st.columns(3)
238
+ campos_metadata = [
239
  ("📄 Título", "title"),
240
  ("🏛️ Entidad", "entity"),
241
+ ("📅 Fecha clave", "date")
242
  ]
243
 
244
+ for col, (icono, key) in zip(cols, campos_metadata):
245
  with col:
246
  st.markdown(f"""
247
  <div class="metadata-box">
248
+ <div style="font-size:16px; margin-bottom:10px;">{icono}</div>
249
  {st.session_state.metadata[key]}
250
  </div>
251
  """, unsafe_allow_html=True)
252
 
253
+ # Sugerencias
254
  if st.session_state.sugerencias:
255
  st.markdown("---")
256
+ with st.container():
257
+ st.markdown("""
258
+ <div class="suggestion-container">
259
+ <div style="font-size:14px; color:#666; margin-bottom:8px;">💡 ¿Necesitas ideas?</div>
260
+ """, unsafe_allow_html=True)
261
+
262
+ cols_sugerencias = st.columns(3)
263
+ for i, (col, pregunta) in enumerate(zip(cols_sugerencias, st.session_state.sugerencias)):
264
+ with col:
265
+ if st.button(
266
+ pregunta,
267
+ key=f"sug_{i}",
268
+ help="Haz clic para usar esta pregunta",
269
+ use_container_width=True
270
+ ):
271
+ st.session_state.pregunta_actual = pregunta
272
+
273
+ st.markdown("</div>", unsafe_allow_html=True)
274
 
275
+ # Formulario de consulta
276
  if st.session_state.documento_cargado:
277
+ with st.form(key="consulta_form"):
278
  col1, col2 = st.columns([5, 1])
279
  with col1:
280
+ pregunta_usuario = st.text_input(
281
  "Escribe tu pregunta:",
282
+ value=st.session_state.get('pregunta_actual', ''),
283
+ placeholder="Ej: ¿De qué trata este documento?",
284
+ label_visibility="collapsed"
285
  )
286
  with col2:
287
+ st.markdown("<br>", unsafe_allow_html=True)
288
  enviar = st.form_submit_button("Enviar ▶")
289
+
290
+ if enviar or st.session_state.pregunta_actual:
291
+ pregunta_final = pregunta_usuario or st.session_state.pregunta_actual
292
+ procesar_consulta(pregunta_final)
293
+ if 'pregunta_actual' in st.session_state:
294
+ del st.session_state.pregunta_actual
295
 
296
+ elif not st.session_state.documento_cargado:
297
+ st.info("Por favor, sube un documento PDF para comenzar.")
 
 
 
 
298
 
299
+ if __name__ == "__main__":
300
+ main()