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() | |