File size: 4,514 Bytes
d0fff4c
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
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()