Spaces:
Sleeping
Sleeping
import gradio as gr | |
import pdfplumber | |
import torch | |
from transformers import AutoTokenizer, AutoModelForSeq2SeqLM | |
# ------------------------------------------------------------------------------ | |
# 1) Modell laden (valhalla/t5-base-qg-hl) | |
# ------------------------------------------------------------------------------ | |
MODEL_NAME = "valhalla/t5-base-qg-hl" | |
print(f"Lade Tokenizer und Modell: {MODEL_NAME}") | |
tokenizer = AutoTokenizer.from_pretrained(MODEL_NAME) | |
model = AutoModelForSeq2SeqLM.from_pretrained(MODEL_NAME) | |
# Optional: auf CPU behalten (gratis, aber langsamer) oder GPU nutzen, wenn Hugging Face | |
# Community GPU verfügbar ist (dann model.to("cuda")) | |
device = torch.device("cpu") | |
model.to(device) | |
# ------------------------------------------------------------------------------ | |
# 2) PDF-Text extrahieren | |
# ------------------------------------------------------------------------------ | |
def extract_text_from_pdf(pdf_file): | |
""" | |
Extrahiert den Text aller Seiten aus einem hochgeladenen PDF. | |
""" | |
if pdf_file is None: | |
return "" | |
text = "" | |
with pdfplumber.open(pdf_file) as pdf: | |
for page in pdf.pages: | |
text += page.extract_text() + "\n" | |
# Minimales Cleaning | |
text = " ".join(text.split()) | |
return text | |
# ------------------------------------------------------------------------------ | |
# 3) Question Generation mit T5 | |
# Dieses Modell ("valhalla/t5-base-qg-hl") nutzt einen 'Highlight-basierten' | |
# Ansatz. Am einfachsten probieren wir, den gesamten Text an das Modell zu geben. | |
# Für bessere Qualität könnte man (a) Text kürzen, (b) "answer highlighting" machen. | |
# ------------------------------------------------------------------------------ | |
def generate_questions(text_chunk, max_length=128): | |
""" | |
Fragt das T5-QG-Modell nach Fragen für den gegebenen Text. | |
Achtung: 'valhalla/t5-base-qg-hl' erwartet i.d.R. 'question: ... context: ...' oder | |
'generate question: ...' Prompts. Wir machen ein einfaches prompt-engineering. | |
""" | |
# Einfacher Prompt: wir fügen "generate question:" voran | |
prompt_text = f"generate question: {text_chunk}" | |
inputs = tokenizer.encode(prompt_text, return_tensors="pt").to(device) | |
output = model.generate( | |
inputs, | |
max_length=max_length, | |
num_beams=4, | |
early_stopping=True | |
) | |
question = tokenizer.decode(output[0], skip_special_tokens=True) | |
return question | |
# ------------------------------------------------------------------------------ | |
# 4) Gradio-Workflows | |
# ------------------------------------------------------------------------------ | |
def process_pdf(pdf_file, num_questions): | |
""" | |
1) PDF extrahieren | |
2) Kürzen (Text chunk) | |
3) Mehrere Fragen generieren | |
""" | |
if pdf_file is None: | |
return "Keine PDF hochgeladen." | |
# PDF-Text holen | |
text = extract_text_from_pdf(pdf_file.name) | |
if not text: | |
return "Text konnte nicht extrahiert werden oder PDF ist leer." | |
# Ggf. nur ersten 1500 Zeichen nehmen, damit wir das Modell nicht überfüttern | |
text_chunk = text[:1500] | |
# Generiere mehrere Fragen | |
questions_output = [] | |
for i in range(num_questions): | |
q = generate_questions(text_chunk) | |
questions_output.append(f"Frage {i+1}: {q}") | |
# Kombiniere das als Ausgabe | |
final_output = "\n\n".join(questions_output) | |
return final_output | |
def build_app(): | |
with gr.Blocks() as demo: | |
gr.Markdown("# QG-PDF – Fragegenerierung aus PDF (ohne OpenAI)") | |
gr.Markdown( | |
"Lade ein PDF hoch und wähle, wie viele Fragen generiert werden sollen. " | |
"Wir verwenden das Modell **valhalla/t5-base-qg-hl**, " | |
"das (meist) eine offene Frage ausgibt." | |
) | |
with gr.Row(): | |
pdf_file = gr.File(label="📄 PDF hochladen") | |
q_slider = gr.Slider( | |
minimum=1, | |
maximum=5, | |
step=1, | |
value=3, | |
label="Anzahl Fragen" | |
) | |
generate_btn = gr.Button("Fragen generieren") | |
output_box = gr.Textbox( | |
label="Generierte Fragen", | |
lines=10 | |
) | |
def on_click_generate(pdf, q_num): | |
return process_pdf(pdf, q_num) | |
generate_btn.click( | |
fn=on_click_generate, | |
inputs=[pdf_file, q_slider], | |
outputs=[output_box] | |
) | |
return demo | |
demo = build_app() | |
if __name__ == "__main__": | |
demo.launch() | |