Files changed (1) hide show
  1. app.py +17 -18
app.py CHANGED
@@ -1,5 +1,6 @@
1
  import os
2
  import json
 
3
  from flask import Flask, request, jsonify, render_template
4
  import PyPDF2
5
  from openai import OpenAI
@@ -9,11 +10,9 @@ import pytesseract
9
  import io
10
 
11
  # 1. Configuración de Flask
12
- # Usa '.' como carpeta de plantillas si index.html está en la raíz.
13
  app = Flask(__name__, template_folder='.')
14
 
15
  # 2. Configuración de OpenAI
16
- # Lee la clave de API desde la variable de entorno 'OPENAI_API_KEY'.
17
  client = OpenAI(
18
  api_key=os.environ.get("OPENAI_API_KEY"),
19
  )
@@ -22,7 +21,6 @@ def ocr_page(img_bytes):
22
  """Realiza OCR en una imagen (byte stream) usando Tesseract."""
23
  try:
24
  image = Image.open(io.BytesIO(img_bytes))
25
- # Usa el idioma español ('spa').
26
  text = pytesseract.image_to_string(image, lang='spa')
27
  return text
28
  except Exception as e:
@@ -44,13 +42,10 @@ def extract_text_from_file(file):
44
  for page in pdf_reader.pages:
45
  total_text += page.extract_text() or ""
46
 
47
- # Si se extrajo una cantidad significativa de texto, úsalo.
48
  if len(total_text.strip()) > 100:
49
- print("Extracción: Éxito nativo.")
50
  return total_text.strip()
51
 
52
  elif file.filename.endswith('.txt'):
53
- print("Extracción: Éxito TXT.")
54
  return file_bytes.decode('utf-8').strip()
55
 
56
  except Exception:
@@ -62,21 +57,18 @@ def extract_text_from_file(file):
62
  document = fitz.open(stream=file_bytes, filetype="pdf")
63
  ocr_text = ""
64
 
65
- # ITERAR SOBRE TODAS las páginas
66
  for i in range(len(document)):
67
  page = document.load_page(i)
68
- pix = page.get_pixmap(dpi=300) # 300 DPI para buena precisión
69
 
70
  img_bytes = pix.tobytes("ppm")
71
 
72
  ocr_text += ocr_page(img_bytes) + "\n"
73
 
74
  if len(ocr_text.strip()) > 100:
75
- print("Extracción: Éxito OCR.")
76
  return ocr_text.strip()
77
 
78
  except Exception as e:
79
- print(f"Fallo el proceso OCR con Tesseract: {e}")
80
  raise Exception("Fallo la extracción de texto del PDF. Asegúrate de que el documento no sea un archivo de imagen corrupto.")
81
 
82
  return ""
@@ -87,7 +79,6 @@ def generate_summary_openai(text):
87
  Genera un análisis experto en formato JSON.
88
  """
89
  try:
90
- # Define el esquema JSON para asegurar la estructura de la respuesta
91
  json_schema = {
92
  "type": "object",
93
  "properties": {
@@ -120,20 +111,19 @@ def generate_summary_openai(text):
120
  )
121
 
122
  json_string = response.choices[0].message.content.strip()
123
-
124
  structured_data = json.loads(json_string)
125
 
126
  return structured_data
127
 
128
  except Exception as e:
129
  print(f"Error al generar el resumen/JSON con OpenAI: {e}")
130
- raise Exception("Error al generar el JSON. Verifica que la APIKey o que el documento sea legible y contenga texto relevante.")
 
131
 
132
  # --- Rutas de Flask ---
133
 
134
  @app.route('/')
135
  def index():
136
- # Renderiza index.html desde la raíz
137
  return render_template('index.html')
138
 
139
  @app.route('/summarize', methods=['POST'])
@@ -153,18 +143,27 @@ def summarize():
153
 
154
  structured_summary = generate_summary_openai(raw_text)
155
 
156
- # Convertimos el diccionario a una lista de strings formateados para el panel de Summary en el frontend
157
  summary_list = [f"**{k.replace('_', ' ').title()}:** {v}" for k, v in structured_summary.items()]
158
 
159
- # Devolvemos el JSON completo y la lista formateada
160
  return jsonify({
161
  'structured_data': structured_summary,
162
  'summary': summary_list
163
  })
164
 
165
  except Exception as e:
166
- print(f"Error general en la ruta /summarize: {e}")
167
- return jsonify({'error': f"Error interno del servidor: {str(e)}"}), 500
 
 
 
 
 
 
 
 
 
 
 
168
 
169
  if __name__ == '__main__':
170
  app.run(debug=True)
 
1
  import os
2
  import json
3
+ import traceback # <--- AÑADIDO PARA DIAGNÓSTICO
4
  from flask import Flask, request, jsonify, render_template
5
  import PyPDF2
6
  from openai import OpenAI
 
10
  import io
11
 
12
  # 1. Configuración de Flask
 
13
  app = Flask(__name__, template_folder='.')
14
 
15
  # 2. Configuración de OpenAI
 
16
  client = OpenAI(
17
  api_key=os.environ.get("OPENAI_API_KEY"),
18
  )
 
21
  """Realiza OCR en una imagen (byte stream) usando Tesseract."""
22
  try:
23
  image = Image.open(io.BytesIO(img_bytes))
 
24
  text = pytesseract.image_to_string(image, lang='spa')
25
  return text
26
  except Exception as e:
 
42
  for page in pdf_reader.pages:
43
  total_text += page.extract_text() or ""
44
 
 
45
  if len(total_text.strip()) > 100:
 
46
  return total_text.strip()
47
 
48
  elif file.filename.endswith('.txt'):
 
49
  return file_bytes.decode('utf-8').strip()
50
 
51
  except Exception:
 
57
  document = fitz.open(stream=file_bytes, filetype="pdf")
58
  ocr_text = ""
59
 
 
60
  for i in range(len(document)):
61
  page = document.load_page(i)
62
+ pix = page.get_pixmap(dpi=300)
63
 
64
  img_bytes = pix.tobytes("ppm")
65
 
66
  ocr_text += ocr_page(img_bytes) + "\n"
67
 
68
  if len(ocr_text.strip()) > 100:
 
69
  return ocr_text.strip()
70
 
71
  except Exception as e:
 
72
  raise Exception("Fallo la extracción de texto del PDF. Asegúrate de que el documento no sea un archivo de imagen corrupto.")
73
 
74
  return ""
 
79
  Genera un análisis experto en formato JSON.
80
  """
81
  try:
 
82
  json_schema = {
83
  "type": "object",
84
  "properties": {
 
111
  )
112
 
113
  json_string = response.choices[0].message.content.strip()
 
114
  structured_data = json.loads(json_string)
115
 
116
  return structured_data
117
 
118
  except Exception as e:
119
  print(f"Error al generar el resumen/JSON con OpenAI: {e}")
120
+ # Relanzamos el error para que sea capturado por el bloque except de summarize
121
+ raise
122
 
123
  # --- Rutas de Flask ---
124
 
125
  @app.route('/')
126
  def index():
 
127
  return render_template('index.html')
128
 
129
  @app.route('/summarize', methods=['POST'])
 
143
 
144
  structured_summary = generate_summary_openai(raw_text)
145
 
 
146
  summary_list = [f"**{k.replace('_', ' ').title()}:** {v}" for k, v in structured_summary.items()]
147
 
 
148
  return jsonify({
149
  'structured_data': structured_summary,
150
  'summary': summary_list
151
  })
152
 
153
  except Exception as e:
154
+ # --- BLOQUE DE DIAGNÓSTICO CRÍTICO ---
155
+ # 1. Imprime el traceback completo en la consola
156
+ print("\n" + "="*50)
157
+ print("DIAGNÓSTICO: ERROR 500 DURANTE EL PROCESAMIENTO")
158
+ print(f"Tipo de Error: {type(e).__name__}")
159
+ print("Traceback Completo:")
160
+ traceback.print_exc() # Imprime el stack trace completo
161
+ print("="*50 + "\n")
162
+ # ----------------------------------------
163
+
164
+ # 2. Devuelve el error de forma segura al usuario
165
+ # El frontend recibirá un mensaje de error que incluye el tipo de error
166
+ return jsonify({'error': f"Error interno del servidor. Detalle: {type(e).__name__} - {str(e)}"}), 500
167
 
168
  if __name__ == '__main__':
169
  app.run(debug=True)