Yermek68 commited on
Commit
11a33db
·
verified ·
1 Parent(s): 7b6676b

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +94 -52
app.py CHANGED
@@ -1,13 +1,12 @@
 
1
  import gradio as gr
2
  from transformers import pipeline
3
  import pdfplumber
4
- import os
5
 
6
  # OCR
7
  try:
8
  import pytesseract
9
  from pdf2image import convert_from_path
10
- from PIL import Image
11
  OCR_AVAILABLE = True
12
  except ImportError:
13
  OCR_AVAILABLE = False
@@ -16,11 +15,19 @@ except ImportError:
16
  from docx import Document
17
  from fpdf import FPDF
18
 
19
- # ---------- МОДЕЛЬ ----------
20
 
 
 
 
 
 
 
21
  summarizer = None
22
 
23
- def load_model():
 
 
 
24
  global summarizer
25
  if summarizer is None:
26
  summarizer = pipeline(
@@ -29,10 +36,11 @@ def load_model():
29
  )
30
  return summarizer
31
 
 
32
  # ---------- ЧТЕНИЕ ФАЙЛА ----------
33
 
34
  def extract_pdf_text(path: str):
35
- """Пытаемся вытащить текст из PDF. Если текста нет пробуем OCR."""
36
  text = ""
37
 
38
  # 1) обычный текстовый PDF
@@ -48,10 +56,11 @@ def extract_pdf_text(path: str):
48
  if text.strip():
49
  return text, None
50
 
51
- # 2) если текст не найден пробуем OCR
52
  if not OCR_AVAILABLE:
53
- return "", "PDF выглядит как скан (изображение). Для OCR нужно pytesseract + tesseract-ocr."
54
 
 
55
  try:
56
  images = convert_from_path(path, dpi=200)
57
  ocr_text = ""
@@ -65,10 +74,10 @@ def extract_pdf_text(path: str):
65
 
66
 
67
  def read_file(path: str):
 
68
  if not path:
69
  return "", "Файл не передан."
70
 
71
- path = str(path).strip()
72
  lower = path.lower()
73
 
74
  if lower.endswith(".pdf"):
@@ -81,6 +90,7 @@ def read_file(path: str):
81
  except Exception as e:
82
  return "", f"Ошибка при чтении TXT: {e}"
83
 
 
84
  # ---------- ЧАНКИНГ ТЕКСТА ----------
85
 
86
  def chunk_text(text: str, max_chars: int = 2500):
@@ -93,85 +103,117 @@ def chunk_text(text: str, max_chars: int = 2500):
93
  cut = cut[:last_dot + 1]
94
  chunks.append(cut)
95
  text = text[len(cut):]
96
- chunks.append(text)
 
97
  return chunks
98
 
99
- # ---------- СОХРАНЕНИЕ РЕЗЮМЕ В DOCX/PDF ----------
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
100
 
101
  def save_docx(summary: str) -> str:
102
  doc = Document()
103
  doc.add_heading("Eroha Summarizer – Резюме документа", level=1)
104
  for paragraph in summary.split("\n"):
105
  doc.add_paragraph(paragraph)
106
- path = "/tmp/summary.docx"
107
- doc.save(path)
108
- return path
 
109
 
110
  def save_pdf(summary: str) -> str:
111
  pdf = FPDF()
112
  pdf.add_page()
113
- pdf.set_auto_page_break(auto=True, margin=15)
114
- pdf.set_font("Arial", size=12)
 
 
 
 
 
 
115
 
116
  for line in summary.split("\n"):
117
- # multi_cell сам переносит строки
118
- pdf.multi_cell(0, 8, line)
119
- path = "/tmp/summary.pdf"
120
- pdf.output(path)
121
- return path
 
 
 
 
 
122
 
123
- # ---------- ОСНОВНАЯ ФУНКЦИЯ ----------
124
 
125
- def summarize_file(path: str):
126
- text, err = read_file(path)
127
  if err:
128
  return f"⚠️ {err}", None, None
129
 
130
  if not text.strip():
131
  return "⚠️ Не удалось извлечь текст из файла.", None, None
132
 
133
- # Модель
134
- model = load_model()
135
-
136
- # Чанкинг
137
- chunks = chunk_text(text, max_chars=2500)
138
- partial_summaries = []
139
-
140
- for chunk in chunks:
141
- if not chunk.strip():
142
- continue
143
- try:
144
- summary = model(
145
- chunk,
146
- max_length=180,
147
- min_length=60,
148
- do_sample=False
149
- )
150
- partial_summaries.append(summary[0]["summary_text"])
151
- except Exception as e:
152
- partial_summaries.append(f"[Ошибка в блоке суммаризации: {e}]")
153
 
154
- if not partial_summaries:
155
- return "⚠️ Не удалось создать резюме.", None, None
 
 
 
156
 
157
- final_summary = "\n\n".join(partial_summaries)
 
 
 
 
 
158
 
159
- # Файлы экспорта
160
- docx_path = save_docx(final_summary)
161
- pdf_path = save_pdf(final_summary)
 
 
162
 
163
  return final_summary, docx_path, pdf_path
164
 
 
165
  # ---------- ИНТЕРФЕЙС GRADIO ----------
166
 
167
  with gr.Blocks() as demo:
168
  gr.Markdown("# Eroha Summarizer 🧠")
169
- gr.Markdown("Загрузите документ (PDF или TXT), и модель создаст краткое резюме с возможностью скачивания DOCX и PDF.")
 
 
 
170
 
171
  with gr.Row():
172
- file_input = gr.File(type="filepath", label="Загрузите файл (.pdf или .txt)")
 
 
 
173
  with gr.Column():
174
- summary_output = gr.Textbox(label="Результат суммаризации", lines=20)
 
 
 
175
  docx_output = gr.File(label="Скачать DOCX")
176
  pdf_output = gr.File(label="Скачать PDF")
177
 
 
1
+ import os
2
  import gradio as gr
3
  from transformers import pipeline
4
  import pdfplumber
 
5
 
6
  # OCR
7
  try:
8
  import pytesseract
9
  from pdf2image import convert_from_path
 
10
  OCR_AVAILABLE = True
11
  except ImportError:
12
  OCR_AVAILABLE = False
 
15
  from docx import Document
16
  from fpdf import FPDF
17
 
 
18
 
19
+ # ---------- НАСТРОЙКИ ----------
20
+
21
+ # Имя файла шрифта в корне Space
22
+ FONT_PATH = "DejaVuSans.ttf"
23
+
24
+ # Глобальная модель (ленивая загрузка)
25
  summarizer = None
26
 
27
+
28
+ # ---------- МОДЕЛЬ ----------
29
+
30
+ def get_summarizer():
31
  global summarizer
32
  if summarizer is None:
33
  summarizer = pipeline(
 
36
  )
37
  return summarizer
38
 
39
+
40
  # ---------- ЧТЕНИЕ ФАЙЛА ----------
41
 
42
  def extract_pdf_text(path: str):
43
+ """Пытаемся вытащить текст из PDF. Если нет текста пробуем OCR (если доступен)."""
44
  text = ""
45
 
46
  # 1) обычный текстовый PDF
 
56
  if text.strip():
57
  return text, None
58
 
59
+ # 2) если текста нет и OCR недоступен
60
  if not OCR_AVAILABLE:
61
+ return "", "PDF выглядит как скан. Для OCR нужен pytesseract + pdf2image + tesseract-ocr."
62
 
63
+ # 3) OCR по картинкам
64
  try:
65
  images = convert_from_path(path, dpi=200)
66
  ocr_text = ""
 
74
 
75
 
76
  def read_file(path: str):
77
+ """Чтение PDF или текстового файла по пути."""
78
  if not path:
79
  return "", "Файл не передан."
80
 
 
81
  lower = path.lower()
82
 
83
  if lower.endswith(".pdf"):
 
90
  except Exception as e:
91
  return "", f"Ошибка при чтении TXT: {e}"
92
 
93
+
94
  # ---------- ЧАНКИНГ ТЕКСТА ----------
95
 
96
  def chunk_text(text: str, max_chars: int = 2500):
 
103
  cut = cut[:last_dot + 1]
104
  chunks.append(cut)
105
  text = text[len(cut):]
106
+ if text:
107
+ chunks.append(text)
108
  return chunks
109
 
110
+
111
+ def summarize_long_text(text: str) -> str:
112
+ model = get_summarizer()
113
+ parts = []
114
+ for chunk in chunk_text(text, max_chars=2500):
115
+ if not chunk.strip():
116
+ continue
117
+ summary = model(
118
+ chunk,
119
+ max_length=180,
120
+ min_length=60,
121
+ do_sample=False
122
+ )
123
+ parts.append(summary[0]["summary_text"])
124
+ return "\n\n".join(parts)
125
+
126
+
127
+ # ---------- ЭКСПОРТ В DOCX / PDF ----------
128
 
129
  def save_docx(summary: str) -> str:
130
  doc = Document()
131
  doc.add_heading("Eroha Summarizer – Резюме документа", level=1)
132
  for paragraph in summary.split("\n"):
133
  doc.add_paragraph(paragraph)
134
+ out_path = "/tmp/summary.docx"
135
+ doc.save(out_path)
136
+ return out_path
137
+
138
 
139
  def save_pdf(summary: str) -> str:
140
  pdf = FPDF()
141
  pdf.add_page()
142
+
143
+ # Подключаем Unicode-шрифт
144
+ try:
145
+ pdf.add_font("DejaVu", "", FONT_PATH, uni=True)
146
+ pdf.set_font("DejaVu", size=12)
147
+ except Exception:
148
+ # Фоллбек – латинский Arial (кириллица может не сохраниться, но ошибок не будет)
149
+ pdf.set_font("Arial", size=12)
150
 
151
  for line in summary.split("\n"):
152
+ try:
153
+ pdf.multi_cell(0, 8, line)
154
+ except Exception:
155
+ # Если шрифт не поддерживает символы – пропускаем проблемную строку
156
+ continue
157
+
158
+ out_path = "/tmp/summary.pdf"
159
+ pdf.output(out_path)
160
+ return out_path
161
+
162
 
163
+ # ---------- ОСНОВНАЯ ФУНКЦИЯ ДЛЯ GRADIO ----------
164
 
165
+ def summarize_file(file_path: str):
166
+ text, err = read_file(file_path)
167
  if err:
168
  return f"⚠️ {err}", None, None
169
 
170
  if not text.strip():
171
  return "⚠️ Не удалось извлечь текст из файла.", None, None
172
 
173
+ if len(text.strip()) < 80:
174
+ return "⚠️ Слишком мало текста для суммаризации.", None, None
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
175
 
176
+ # Суммаризация с чанкингом
177
+ try:
178
+ final_summary = summarize_long_text(text)
179
+ except Exception as e:
180
+ return f"⚠️ Ошибка суммаризации: {e}", None, None
181
 
182
+ # Экспорт в DOCX / PDF
183
+ try:
184
+ docx_path = save_docx(final_summary)
185
+ except Exception as e:
186
+ docx_path = None
187
+ final_summary += f"\n\n[Предупреждение: ошибка сохранения DOCX: {e}]"
188
 
189
+ try:
190
+ pdf_path = save_pdf(final_summary)
191
+ except Exception as e:
192
+ pdf_path = None
193
+ final_summary += f"\n\n[Предупреждение: ошибка сохранения PDF: {e}]"
194
 
195
  return final_summary, docx_path, pdf_path
196
 
197
+
198
  # ---------- ИНТЕРФЕЙС GRADIO ----------
199
 
200
  with gr.Blocks() as demo:
201
  gr.Markdown("# Eroha Summarizer 🧠")
202
+ gr.Markdown(
203
+ "Загрузите документ (**PDF или TXT**), и модель создаст краткое резюме "
204
+ "с возможностью скачивания **DOCX** и **PDF**."
205
+ )
206
 
207
  with gr.Row():
208
+ file_input = gr.File(
209
+ type="filepath",
210
+ label="Загрузите файл (.pdf или .txt)"
211
+ )
212
  with gr.Column():
213
+ summary_output = gr.Textbox(
214
+ label="Результат суммаризации",
215
+ lines=20
216
+ )
217
  docx_output = gr.File(label="Скачать DOCX")
218
  pdf_output = gr.File(label="Скачать PDF")
219