Spaces:
Sleeping
Sleeping
File size: 4,978 Bytes
00832a8 b54a6bc 19c3ca0 7cba34a 19c3ca0 7cba34a 19c3ca0 d329e85 19c3ca0 7cba34a b54a6bc e341366 4d995a1 b54a6bc 19c3ca0 1b22788 19c3ca0 1b22788 19c3ca0 1b22788 19c3ca0 1b22788 19c3ca0 b54a6bc 7cba34a b54a6bc e341366 d35d511 19c3ca0 1b22788 19c3ca0 1b22788 19c3ca0 1b22788 19c3ca0 1e129b0 19c3ca0 1e129b0 1b22788 7cba34a 1b22788 19c3ca0 7cba34a b54a6bc 7cba34a 19c3ca0 7cba34a f61af4a 1b22788 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 |
import gradio as gr
import PyPDF2
import os
import json
import vertexai
from vertexai.generative_models import GenerativeModel, Part, SafetySetting
# Configuración global
generation_config = {
"max_output_tokens": 4096,
"temperature": 0,
"top_p": 0.8,
}
safety_settings = [
SafetySetting(
category=SafetySetting.HarmCategory.HARM_CATEGORY_HATE_SPEECH,
threshold=SafetySetting.HarmBlockThreshold.OFF
),
SafetySetting(
category=SafetySetting.HarmCategory.HARM_CATEGORY_DANGEROUS_CONTENT,
threshold=SafetySetting.HarmBlockThreshold.OFF
),
SafetySetting(
category=SafetySetting.HarmCategory.HARM_CATEGORY_SEXUALLY_EXPLICIT,
threshold=SafetySetting.HarmBlockThreshold.OFF
),
SafetySetting(
category=SafetySetting.HarmCategory.HARM_CATEGORY_HARASSMENT,
threshold=SafetySetting.HarmBlockThreshold.OFF
),
]
def configurar_credenciales(json_path: str):
os.environ["GOOGLE_APPLICATION_CREDENTIALS"] = json_path
def extraer_texto(pdf_path: str) -> str:
texto_total = ""
with open(pdf_path, "rb") as f:
lector = PyPDF2.PdfReader(f)
for page in lector.pages:
texto_total += page.extract_text() or ""
return texto_total
def parsear_con_llm(texto_pdf: str, model: GenerativeModel) -> dict:
# Instrucciones para parsear:
prompt = f"""
Eres un parser de texto.
A continuación tienes el contenido de un PDF con un examen (o respuestas).
Debes extraer todas las preguntas y sus respuestas.
Considera que las palabras podrían estar en mayúsculas, minúsculas o plural
(por ejemplo 'Pregunta', 'PREGUNTA', 'Preguntas', 'RESPUESTA', 'RESPUESTAS', etc.).
Devuélvelas en formato JSON puro, sin explicación adicional.
Usa este formato de salida:
{{
"Pregunta 1": "Texto de la respuesta",
"Pregunta 2": "Texto de la respuesta"
}}
Si hay preguntas sin respuesta, pon la respuesta como cadena vacía.
Si no hay ninguna pregunta, devuelve un JSON vacío: {{}}
Texto PDF:
{texto_pdf}
"""
part_text = Part.from_text(prompt)
response = model.generate_content(
[part_text],
generation_config=generation_config,
safety_settings=safety_settings,
stream=False
)
try:
data = json.loads(response.text.strip())
if isinstance(data, dict):
return data
else:
return {}
except:
return {}
def comparar_preguntas_respuestas(dict_docente: dict, dict_alumno: dict) -> str:
retroalimentacion = []
for pregunta, resp_correcta in dict_docente.items():
resp_alumno = dict_alumno.get(pregunta, None)
if resp_alumno is None:
retroalimentacion.append(f"**{pregunta}**\nNo fue asignada al alumno.\n")
else:
retroalimentacion.append(
f"**{pregunta}**\n"
f"Respuesta del alumno: {resp_alumno}\n"
f"Respuesta correcta: {resp_correcta}\n"
)
return "\n".join(retroalimentacion)
def revisar_examen(json_cred, pdf_docente, pdf_alumno):
try:
configurar_credenciales(json_cred.name)
vertexai.init(project="deploygpt", location="us-central1")
texto_docente = extraer_texto(pdf_docente.name)
texto_alumno = extraer_texto(pdf_alumno.name)
model = GenerativeModel(
"gemini-1.5-pro-001",
system_instruction=["Eres un parser estricto."]
)
dict_docente = parsear_con_llm(texto_docente, model)
dict_alumno = parsear_con_llm(texto_alumno, model)
feedback = comparar_preguntas_respuestas(dict_docente, dict_alumno)
if len(feedback.strip()) < 5:
return "No se encontraron preguntas o respuestas válidas."
summary_prompt = f"""
Eres un profesor experto. Te muestro la comparación de preguntas y respuestas:
{feedback}
Por favor, genera un breve resumen del desempeño del alumno
sin inventar preguntas adicionales.
"""
summary_part = Part.from_text(summary_prompt)
summary_resp = model.generate_content(
[summary_part],
generation_config=generation_config,
safety_settings=safety_settings,
stream=False
)
return f"{feedback}\n\n**Resumen**\n{summary_resp.text.strip()}"
except Exception as e:
return f"Error al procesar: {str(e)}"
import gradio as gr
interface = gr.Interface(
fn=revisar_examen,
inputs=[
gr.File(label="Credenciales JSON"),
gr.File(label="PDF Docente"),
gr.File(label="PDF Alumno")
],
outputs=gr.Markdown(),
title="Revisión de Exámenes con LLM (Permisivo)",
description="Sube credenciales, el PDF del docente y del alumno; se emplea un LLM para encontrar 'Pregunta/Respuesta' aun con variaciones."
)
interface.launch(debug=True)
|