cesar commited on
Commit
63918e4
·
verified ·
1 Parent(s): f025ed5

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +36 -42
app.py CHANGED
@@ -42,30 +42,32 @@ def extraer_texto(pdf_path: str) -> str:
42
  texto_total += page.extract_text() or ""
43
  return texto_total
44
 
45
- def parsear_con_llm_con_enumeraciones(texto_pdf: str, model: GenerativeModel) -> dict:
46
  """
47
- Usa el LLM para extraer las 'Preguntas' y sus 'Respuestas'.
48
- Reconoce enumeraciones en 'Preguntas' (ej. '1.' o '1)') y en 'RESPUESTAS'.
49
- Devuelve JSON con la forma:
50
- {
51
- "Pregunta 1": "Texto de la respuesta",
52
- "Pregunta 2": "Texto de la respuesta",
53
- ...
54
- }
55
  """
56
  prompt = f"""
57
- Eres un parser de texto que recibe el contenido de un PDF con dos secciones:
58
- 'Preguntas' y 'RESPUESTAS', cada una enumerada como '1.', '2)', etc.
59
- Tu tarea es emparejar cada pregunta con su respuesta correspondiente, basándote
60
- en el número que las identifica (1, 2, 3, ...).
61
- Devuelve un JSON con la estructura:
 
 
62
  {{
63
- "Pregunta 1": "texto de la respuesta",
64
- "Pregunta 2": "texto de la respuesta",
65
  ...
66
  }}
67
- Si no hay correspondencia entre pregunta y respuesta, la dejas vacía.
68
- Ejemplo de JSON vacío: {{}}
 
 
 
 
69
 
70
  Texto PDF:
71
  {texto_pdf}
@@ -79,6 +81,8 @@ Devuelve solo el JSON, sin explicaciones adicionales.
79
  safety_settings=safety_settings,
80
  stream=False
81
  )
 
 
82
  try:
83
  data = json.loads(response.text.strip())
84
  if isinstance(data, dict):
@@ -104,46 +108,36 @@ def comparar_preguntas_respuestas(dict_docente: dict, dict_alumno: dict) -> str:
104
  return "\n".join(retroalimentacion)
105
 
106
  def revisar_examen(json_cred, pdf_docente, pdf_alumno):
107
- """
108
- Función convertida en generador para mostrar 'progreso' en Gradio:
109
- en lugar de return final, se hace yield en varios pasos.
110
- """
111
- # Paso 1: Configurar credenciales
112
  yield "Cargando credenciales..."
113
  try:
114
  configurar_credenciales(json_cred.name)
115
-
116
- # Paso 2: Inicializar Vertex AI
117
  yield "Inicializando Vertex AI..."
118
  vertexai.init(project="deploygpt", location="us-central1")
119
 
120
- # Paso 3: Leer texto PDF
121
  yield "Extrayendo texto del PDF del docente..."
122
  texto_docente = extraer_texto(pdf_docente.name)
123
 
124
  yield "Extrayendo texto del PDF del alumno..."
125
  texto_alumno = extraer_texto(pdf_alumno.name)
126
 
127
- # Paso 4: Invocar modelo
128
- yield "Parseando preguntas y respuestas (Docente)..."
129
  model = GenerativeModel(
130
  "gemini-1.5-pro-001",
131
  system_instruction=["Eres un parser estricto."]
132
  )
133
- dict_docente = parsear_con_llm_con_enumeraciones(texto_docente, model)
134
 
135
- yield "Parseando preguntas y respuestas (Alumno)..."
136
- dict_alumno = parsear_con_llm_con_enumeraciones(texto_alumno, model)
137
 
138
- # Paso 5: Comparar
139
- yield "Comparando respuestas..."
140
  feedback = comparar_preguntas_respuestas(dict_docente, dict_alumno)
141
 
142
  if len(feedback.strip()) < 5:
143
  yield "No se encontraron preguntas o respuestas válidas."
144
- return # terminamos la función
145
 
146
- # Paso 6: Resumen final
147
  yield "Generando resumen final..."
148
  summary_prompt = f"""
149
  Eres un profesor experto de bioquímica. Te muestro la comparación de preguntas y respuestas:
@@ -158,14 +152,15 @@ def revisar_examen(json_cred, pdf_docente, pdf_alumno):
158
  safety_settings=safety_settings,
159
  stream=False
160
  )
161
- final_result = f"{feedback}\n\n**Resumen**\n{summary_resp.text.strip()}"
162
 
 
163
  yield final_result
164
 
165
  except Exception as e:
166
  yield f"Error al procesar: {str(e)}"
167
 
168
- # Interfaz Gradio
 
169
  interface = gr.Interface(
170
  fn=revisar_examen,
171
  inputs=[
@@ -173,13 +168,12 @@ interface = gr.Interface(
173
  gr.File(label="PDF del Docente"),
174
  gr.File(label="PDF Alumno")
175
  ],
176
- # Cuando la función es un generador, definimos outputs="text" (o gr.Textbox()).
177
  outputs="text",
178
- title="Revisión de Exámenes con Enumeraciones (Progreso)",
179
  description=(
180
- "Sube tus credenciales, el PDF del docente y del alumno. El LLM "
181
- "detectará enumeraciones (1., 2), etc.) en 'Preguntas' y 'RESPUESTAS' "
182
- "y mostrará progreso a medida que avanza."
183
  )
184
  )
185
 
 
42
  texto_total += page.extract_text() or ""
43
  return texto_total
44
 
45
+ def parsear_con_llm(texto_pdf: str, model: GenerativeModel) -> dict:
46
  """
47
+ Prompt más flexible:
48
+ - Reconoce enumeraciones en secciones 'Preguntas' y 'RESPUESTAS', p. ej. '1.', '2)', '3-'.
49
+ - Permite que las preguntas tengan texto como "Teniendo en cuenta que..." sin la palabra "Pregunta".
50
+ - Devuelve un JSON que asocia la pregunta X con la respuesta X.
 
 
 
 
51
  """
52
  prompt = f"""
53
+ Eres un parser de texto que recibe el contenido de un PDF con:
54
+ - Una sección de \"Preguntas\" enumeradas (1., 2., 3..., etc.).
55
+ - Una sección de \"RESPUESTAS\" enumeradas de la misma forma.
56
+
57
+ Para cada número (1, 2, 3, 4, 5, 6...), empareja la pregunta con la respuesta.
58
+ Devuélvelo en un JSON con el siguiente formato:
59
+
60
  {{
61
+ "Pregunta 1": "texto de la respuesta 1",
62
+ "Pregunta 2": "texto de la respuesta 2",
63
  ...
64
  }}
65
+
66
+ Reglas:
67
+ 1. Si una pregunta dice \"1. Teniendo en cuenta...\", eso es \"Pregunta 1\".
68
+ 2. Si en la sección RESPUESTAS dice \"1. Metabolismo...\", esa es la Respuesta 1.
69
+ 3. Si no hay correspondencia entre pregunta y respuesta, deja la respuesta como cadena vacía.
70
+ 4. Si no hay nada, devuelve un JSON vacío: {{}}.
71
 
72
  Texto PDF:
73
  {texto_pdf}
 
81
  safety_settings=safety_settings,
82
  stream=False
83
  )
84
+
85
+ # Intentamos parsear el contenido como JSON
86
  try:
87
  data = json.loads(response.text.strip())
88
  if isinstance(data, dict):
 
108
  return "\n".join(retroalimentacion)
109
 
110
  def revisar_examen(json_cred, pdf_docente, pdf_alumno):
111
+ """Función generadora que muestra progreso en Gradio con yield."""
 
 
 
 
112
  yield "Cargando credenciales..."
113
  try:
114
  configurar_credenciales(json_cred.name)
 
 
115
  yield "Inicializando Vertex AI..."
116
  vertexai.init(project="deploygpt", location="us-central1")
117
 
 
118
  yield "Extrayendo texto del PDF del docente..."
119
  texto_docente = extraer_texto(pdf_docente.name)
120
 
121
  yield "Extrayendo texto del PDF del alumno..."
122
  texto_alumno = extraer_texto(pdf_alumno.name)
123
 
124
+ yield "Parseando preguntas/respuestas del docente..."
 
125
  model = GenerativeModel(
126
  "gemini-1.5-pro-001",
127
  system_instruction=["Eres un parser estricto."]
128
  )
129
+ dict_docente = parsear_con_llm(texto_docente, model)
130
 
131
+ yield "Parseando preguntas/respuestas del alumno..."
132
+ dict_alumno = parsear_con_llm(texto_alumno, model)
133
 
134
+ yield "Comparando..."
 
135
  feedback = comparar_preguntas_respuestas(dict_docente, dict_alumno)
136
 
137
  if len(feedback.strip()) < 5:
138
  yield "No se encontraron preguntas o respuestas válidas."
139
+ return
140
 
 
141
  yield "Generando resumen final..."
142
  summary_prompt = f"""
143
  Eres un profesor experto de bioquímica. Te muestro la comparación de preguntas y respuestas:
 
152
  safety_settings=safety_settings,
153
  stream=False
154
  )
 
155
 
156
+ final_result = f"{feedback}\n\n**Resumen**\n{summary_resp.text.strip()}"
157
  yield final_result
158
 
159
  except Exception as e:
160
  yield f"Error al procesar: {str(e)}"
161
 
162
+ import gradio as gr
163
+
164
  interface = gr.Interface(
165
  fn=revisar_examen,
166
  inputs=[
 
168
  gr.File(label="PDF del Docente"),
169
  gr.File(label="PDF Alumno")
170
  ],
 
171
  outputs="text",
172
+ title="Revisión de Exámenes (Preguntas enumeradas + RESPUESTAS enumeradas)",
173
  description=(
174
+ "Sube tus credenciales, el PDF del docente y el PDF del alumno. El LLM "
175
+ "buscará enumeraciones (1., 2., 3., etc.) en PREGUNTAS y RESPUESTAS y "
176
+ "mostrará el avance paso a paso."
177
  )
178
  )
179