File size: 4,902 Bytes
1972b5c
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
153
154
155
156
157
158
159
160
161
162
163
164
165
166
import gradio as gr
from transformers import pipeline
import PyPDF2
import torch

# ===== 1) اختر الموديل هنا =====
# موديل إنجليزي:
# MODEL_NAME = "csebuetnlp/mT5_multilingual_XLSum"

# موديل ملخص متعدد اللغات (يدعم العربية أفضل):
MODEL_NAME = "csebuetnlp/mT5_multilingual_XLSum"

# ===== 2) تجهيز الـ pipeline =====
device = 0 if torch.cuda.is_available() else -1

summarizer = pipeline(
    "summarization",
    model=MODEL_NAME,
    tokenizer=MODEL_NAME,
    device=device,
)

# ===== 3) قراءة الـ PDF =====
def read_pdf(file_obj):
    """
    يستقبل ملف PDF من Gradio (file_obj)،
    يرجّع النص المستخرج من كل الصفحات.
    """
    if file_obj is None:
        return ""

    reader = PyPDF2.PdfReader(file_obj)
    text = ""
    for page in reader.pages:
        page_text = page.extract_text()
        if page_text:
            text += page_text + "\n"

    return text


# ===== 4) تقسيم النص لقطع (عشان حدود الموديل) =====
def chunk_text(text, max_chars=2000):
    """
    يقسم النص إلى قطع صغيرة بعدد حروف أقصاه max_chars
    عشان لا نتجاوز حدود الموديل.
    """
    paragraphs = text.split("\n")
    chunks = []
    current = ""

    for p in paragraphs:
        p = p.strip()
        if not p:
            continue

        # لو نقدر نضيف الفقرة للجزء الحالي بدون ما نتعدى الحد
        if len(current) + len(p) + 1 <= max_chars:
            current += ("\n" + p) if current else p
        else:
            # نخزن الجزء القديم ونبدأ جزء جديد
            if current.strip():
                chunks.append(current.strip())
            current = p

    if current.strip():
        chunks.append(current.strip())

    return chunks


# ===== 5) دالة التلخيص الرئيسية =====
def summarize_pdf(file, max_summary_length=200):
    """
    تستقبل ملف PDF من واجهة Gradio،
    تقرأ النص، تقسمه لقطع، تلخص كل جزء،
    ثم تلخص التلخيصات مرة ثانية (لو كانت كثيرة).
    """
    if file is None:
        return "رجاءً ارفع ملف PDF أولاً."

    # 1) قراءة النص من الـ PDF
    text = read_pdf(file)

    if not text or len(text.strip()) < 50:
        return "لم أستطع قراءة نص واضح من الـ PDF. تأكد أن الملف ليس صورة ممسوحة فقط (scan)."

    # 2) تقسيم النص
    chunks = chunk_text(text, max_chars=2000)

    # 3) تلخيص كل جزء
    partial_summaries = []
    for idx, ch in enumerate(chunks, start=1):
        # نضمن طول منطقي للتلخيص
        try:
            result = summarizer(
                ch,
                max_length=max_summary_length,
                min_length=int(max_summary_length / 3),
                do_sample=False,
            )
            summary_text = result[0]["summary_text"]
        except Exception as e:
            summary_text = f"[خطأ في تلخيص الجزء {idx}: {e}]"

        partial_summaries.append(summary_text)

    combined = "\n\n".join(partial_summaries)

    # 4) لو الملف طويل جداً (أكثر من جزء واحد)، نلخص التلخيص النهائي
    if len(partial_summaries) > 1:
        try:
            final = summarizer(
                combined,
                max_length=max_summary_length,
                min_length=int(max_summary_length / 3),
                do_sample=False,
            )[0]["summary_text"]
            return final
        except Exception:
            # لو فشل التلخيص الثاني، نرجع دمج التلخيصات الأولية
            return combined
    else:
        return combined


# ===== 6) واجهة Gradio =====
with gr.Blocks() as demo:
    gr.Markdown(
        """
    # 📄 PDF Summarizer / ملخّص ملفات PDF

    ارفع ملف PDF وسيقوم النموذج بقراءة النص وتلخيصه بشكل تلقائي.
    يمكن تعديل طول التلخيص باستخدام الشريط أسفل.
    """
    )

    with gr.Row():
        pdf_input = gr.File(
            label="📎 ارفع ملف PDF",
            file_types=[".pdf"],
        )
        max_len = gr.Slider(
            minimum=50,
            maximum=400,
            step=50,
            value=200,
            label="أقصى طول للتلخيص (تقريبي)",
        )

    output = gr.Textbox(
        label="ملخص الملف",
        lines=15,
    )

    summarize_btn = gr.Button("✨ تلخيص PDF")

    summarize_btn.click(
        fn=summarize_pdf,
        inputs=[pdf_input, max_len],
        outputs=output,
    )

# مهم في Hugging Face Spaces:
demo.launch()