cesar commited on
Commit
b527142
·
verified ·
1 Parent(s): 85b6c95

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +37 -32
app.py CHANGED
@@ -41,33 +41,36 @@ def extraer_texto(pdf_path: str) -> str:
41
  texto_total += page.extract_text() or ""
42
  return texto_total
43
 
44
- def parsear_con_llm(texto_pdf: str, model: GenerativeModel) -> dict:
45
  """
46
- Usa el LLM para extraer preguntas y respuestas:
47
- - Considera que 'Explicá' o 'Explica' o 'Explique' es una pregunta,
48
- aunque no diga 'Pregunta:'.
49
- - Reconoce 'RESPUESTA', 'RESPUESTAS', con o sin dos puntos,
50
- como inicio de la respuesta.
 
 
 
51
  """
 
52
  prompt = f"""
53
- Eres un parser de texto.
54
- Te entrego el contenido de un PDF con una pregunta o varias,
55
- y su(s) respuesta(s). Usa estas reglas para interpretarlo:
56
- 1. Si ves 'Explicá', 'Explica', 'Explique', 'Teniendo en cuenta que...'
57
- o algo similar, asúmelo como una pregunta.
58
- Si no hay 'Pregunta:' literal, aun así consideralo pregunta.
59
- 2. Las respuestas podrían estar marcadas como 'RESPUESTAS', 'RESPUESTA', 'RESPUESTAS:', etc.
60
- 3. Devuelve un JSON con la estructura:
61
  {{
62
- "Pregunta 1": "Texto de la respuesta"
 
 
63
  }}
64
- Si hay más de una pregunta, enumerarlas como 'Pregunta 2', etc.
65
- 4. Si no hay nada reconocible, devuelve {{}}.
66
 
67
  Texto PDF:
68
  {texto_pdf}
69
 
70
- Devuelve solo el JSON, sin explicaciones ni texto extra.
71
  """
72
  part_text = Part.from_text(prompt)
73
 
@@ -87,13 +90,12 @@ Devuelve solo el JSON, sin explicaciones ni texto extra.
87
  return {}
88
 
89
  def comparar_preguntas_respuestas(dict_docente: dict, dict_alumno: dict) -> str:
 
90
  retroalimentacion = []
91
  for pregunta, resp_correcta in dict_docente.items():
92
  resp_alumno = dict_alumno.get(pregunta, None)
93
  if resp_alumno is None:
94
- retroalimentacion.append(
95
- f"**{pregunta}**\nNo fue asignada al alumno.\n"
96
- )
97
  else:
98
  retroalimentacion.append(
99
  f"**{pregunta}**\n"
@@ -107,26 +109,27 @@ def revisar_examen(json_cred, pdf_docente, pdf_alumno):
107
  configurar_credenciales(json_cred.name)
108
  vertexai.init(project="deploygpt", location="us-central1")
109
 
 
110
  texto_docente = extraer_texto(pdf_docente.name)
111
  texto_alumno = extraer_texto(pdf_alumno.name)
112
 
113
- # 1) Instanciar el modelo
114
  model = GenerativeModel(
115
  "gemini-1.5-pro-001",
116
  system_instruction=["Eres un parser estricto."]
117
  )
118
 
119
- # 2) Convertir PDF Docente y Alumno en dict {Pregunta X: Respuesta X}
120
- dict_docente = parsear_con_llm(texto_docente, model)
121
- dict_alumno = parsear_con_llm(texto_alumno, model)
122
 
123
- # 3) Comparar y generar feedback
124
  feedback = comparar_preguntas_respuestas(dict_docente, dict_alumno)
125
 
126
  if len(feedback.strip()) < 5:
127
  return "No se encontraron preguntas o respuestas válidas."
128
 
129
- # 4) Generar un resumen
130
  summary_prompt = f"""
131
  Eres un profesor experto de bioquímica. Te muestro la comparación de preguntas y respuestas:
132
  {feedback}
@@ -151,14 +154,16 @@ interface = gr.Interface(
151
  fn=revisar_examen,
152
  inputs=[
153
  gr.File(label="Credenciales JSON"),
154
- gr.File(label="PDF Docente"),
155
  gr.File(label="PDF Alumno")
156
  ],
157
  outputs=gr.Markdown(),
158
- title="Revisión de Exámenes con LLM (Permisivo)",
159
- description=("Sube credenciales, el PDF del docente y del alumno; "
160
- "se emplea un LLM para encontrar 'Explicá' y 'RESPUESTAS' etc. "
161
- "y evitar alucinaciones.")
 
 
162
  )
163
 
164
  interface.launch(debug=True)
 
41
  texto_total += page.extract_text() or ""
42
  return texto_total
43
 
44
+ def parsear_con_llm_con_enumeraciones(texto_pdf: str, model: GenerativeModel) -> dict:
45
  """
46
+ Usa el LLM para extraer las 'Preguntas' y sus 'Respuestas'.
47
+ Reconoce enumeraciones en 'Preguntas' (ej. '1.' o '1)') y en 'RESPUESTAS'.
48
+ Devuelve JSON con la forma:
49
+ {
50
+ "Pregunta 1": "Texto de la respuesta",
51
+ "Pregunta 2": "Texto de la respuesta",
52
+ ...
53
+ }
54
  """
55
+ # Prompt que describe el formato “Preguntas” y “RESPUESTAS”
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}
72
 
73
+ Devuelve solo el JSON, sin explicaciones adicionales.
74
  """
75
  part_text = Part.from_text(prompt)
76
 
 
90
  return {}
91
 
92
  def comparar_preguntas_respuestas(dict_docente: dict, dict_alumno: dict) -> str:
93
+ """Compara dict_docente vs dict_alumno y retorna retroalimentación."""
94
  retroalimentacion = []
95
  for pregunta, resp_correcta in dict_docente.items():
96
  resp_alumno = dict_alumno.get(pregunta, None)
97
  if resp_alumno is None:
98
+ retroalimentacion.append(f"**{pregunta}**\nNo fue asignada al alumno.\n")
 
 
99
  else:
100
  retroalimentacion.append(
101
  f"**{pregunta}**\n"
 
109
  configurar_credenciales(json_cred.name)
110
  vertexai.init(project="deploygpt", location="us-central1")
111
 
112
+ # Leer texto de ambos PDFs
113
  texto_docente = extraer_texto(pdf_docente.name)
114
  texto_alumno = extraer_texto(pdf_alumno.name)
115
 
116
+ # Instanciar el modelo
117
  model = GenerativeModel(
118
  "gemini-1.5-pro-001",
119
  system_instruction=["Eres un parser estricto."]
120
  )
121
 
122
+ # Parsear 'Preguntas' y 'RESPUESTAS' para docente y alumno
123
+ dict_docente = parsear_con_llm_con_enumeraciones(texto_docente, model)
124
+ dict_alumno = parsear_con_llm_con_enumeraciones(texto_alumno, model)
125
 
126
+ # Comparar y generar retroalimentación
127
  feedback = comparar_preguntas_respuestas(dict_docente, dict_alumno)
128
 
129
  if len(feedback.strip()) < 5:
130
  return "No se encontraron preguntas o respuestas válidas."
131
 
132
+ # Generar resumen final
133
  summary_prompt = f"""
134
  Eres un profesor experto de bioquímica. Te muestro la comparación de preguntas y respuestas:
135
  {feedback}
 
154
  fn=revisar_examen,
155
  inputs=[
156
  gr.File(label="Credenciales JSON"),
157
+ gr.File(label="PDF del Docente"),
158
  gr.File(label="PDF Alumno")
159
  ],
160
  outputs=gr.Markdown(),
161
+ title="Revisión de Exámenes con Enumeraciones",
162
+ description=(
163
+ "Sube tus credenciales, el PDF del docente y del alumno. El LLM "
164
+ "detectará enumeraciones (1., 2), etc.) en 'Preguntas' y 'RESPUESTAS' "
165
+ "para armar un JSON y compararlos."
166
+ )
167
  )
168
 
169
  interface.launch(debug=True)