Yermek68 commited on
Commit
a1a5c33
·
verified ·
1 Parent(s): 7bfdf8f

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +128 -100
app.py CHANGED
@@ -3,65 +3,78 @@ from transformers import pipeline
3
  from fastapi import FastAPI
4
  from fastapi.middleware.cors import CORSMiddleware
5
  from langdetect import detect
 
 
 
6
 
7
- # 🔹 Кэш моделей
8
- summarizers = {}
9
- analyzers = {}
10
 
11
- # 🔹 Подбор модели суммаризации
12
- def get_summarizer(lang: str):
 
13
  if lang == "ru":
14
- model_name = "IlyaGusev/mbart_ru_sum_gazeta"
 
 
 
 
 
 
15
  else:
16
- model_name = "facebook/bart-large-cnn"
17
- if model_name not in summarizers:
18
- summarizers[model_name] = pipeline("summarization", model=model_name)
19
- return summarizers[model_name]
20
 
21
- # 🔹 Подбор модели анализа настроения
22
  def get_sentiment_analyzer(lang: str):
23
  if lang == "ru":
24
- model_name = "blanchefort/rubert-base-cased-sentiment"
25
  else:
26
- model_name = "nlptown/bert-base-multilingual-uncased-sentiment"
27
- if model_name not in analyzers:
28
- analyzers[model_name] = pipeline("sentiment-analysis", model=model_name)
29
- return analyzers[model_name]
 
 
 
 
 
 
 
 
30
 
31
- # 🔹 Определение темы (простая эвристика)
32
  def detect_topic(text: str):
33
  topics = {
34
- "Политика": ["правительство", "закон", "президент", "выборы", "партия"],
35
- "Экономика": ["доллар", "рынок", "инфляция", "инвестиции", "компания", "бизнес"],
36
- "Технологии": ["AI", "искусственный интеллект", "технологии", "робот", "интернет"],
37
- "Спорт": ["матч", "игра", "команда", "футбол", "спортсмен"],
38
- "Наука": ["исследование", "учёные", "эксперимент", "данные", "результаты"]
39
  }
40
- text_lower = text.lower()
41
- for topic, keywords in topics.items():
42
- if any(word.lower() in text_lower for word in keywords):
43
  return topic
44
  return "Общее / неопределённое направление"
45
 
46
- # 🔹 Очистка текста от мусора
47
- def clean_text(text: str):
48
- text = (
49
- text.replace("▁", " ")
50
- .replace("<n>", "\n")
51
- .replace("<s>", "")
52
- .replace("</s>", "")
53
- .replace("Ġ", " ")
54
- .replace("Â", "")
55
- .replace("", "")
56
- .replace("�", "")
57
- .strip()
58
- )
59
- while " " in text:
60
- text = text.replace(" ", " ")
61
- return text
62
-
63
- # 🔹 Главная функция
64
- def summarize_text(text: str):
65
  if not text.strip():
66
  return "❌ Введите текст для анализа."
67
 
@@ -70,91 +83,106 @@ def summarize_text(text: str):
70
  except:
71
  lang = "en"
72
 
73
- summarizer = get_summarizer(lang)
 
 
 
 
74
  sentiment_model = get_sentiment_analyzer(lang)
75
 
76
- # Оптимизация под длину текста
77
- words = len(text.split())
78
  if words < 50:
79
- # Короткий текст — возвращаем TL;DR напрямую
80
- summary = text.strip()
81
  else:
82
- if words < 100:
83
- max_len, min_len = 80, 20
84
- elif words < 300:
85
- max_len, min_len = 150, 40
86
- else:
87
- max_len, min_len = 250, 60
88
-
89
- # Суммаризация
90
- summary_raw = summarizer(
91
- text, max_length=max_len, min_length=min_len, do_sample=False
92
- )[0]["summary_text"]
93
-
94
- # Безопасное декодирование и очистка
95
- if isinstance(summary_raw, bytes):
96
- summary = summary_raw.decode("utf-8", errors="ignore")
97
- else:
98
- summary = str(summary_raw).encode("utf-8", errors="ignore").decode("utf-8", errors="ignore")
99
- summary = clean_text(summary)
100
-
101
- # Анализ настроения
102
- sentiment_result = sentiment_model(summary)[0]
103
- sentiment = sentiment_result["label"]
104
- if "POS" in sentiment or "5" in sentiment:
105
- sentiment = "😊 Позитивное"
106
- elif "NEG" in sentiment or "1" in sentiment:
107
- sentiment = "😞 Негативное"
108
- else:
109
- sentiment = "😐 Нейтральное"
110
 
111
- # Определение темы
112
  topic = detect_topic(text)
 
113
 
114
- # Улучшенное форматирование Markdown
 
 
 
115
  output = f"""
116
- # 🧠 **Eroha Summarizer PRO++**
117
  _(Автоязык: {'Русский' if lang == 'ru' else 'Английский'})_
118
 
119
  ---
120
 
121
- ### 📌 **Основная тема:** {topic}
122
- ### 💬 **Настроение:** {sentiment}
 
123
 
124
  ---
125
 
126
- ## 📘 **Резюме**
127
  {summary}
128
 
129
  ---
130
 
131
- ### ✨ **TL;DR**
132
  {summary[:200]}{'...' if len(summary) > 200 else ''}
133
- """
134
 
 
 
 
 
135
  return output.strip()
136
 
137
- # 🔹 FastAPI backend
138
- app = FastAPI(title="Eroha Summarizer PRO++", version="1.4")
139
- app.add_middleware(
140
- CORSMiddleware,
141
- allow_origins=["*"],
142
- allow_methods=["*"],
143
- allow_headers=["*"],
144
- )
145
 
146
- @app.post("/api/summarize")
147
- async def summarize_api(data: dict):
148
  text = data.get("text", "")
149
- return {"summary": summarize_text(text)}
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
150
 
151
- # 🔹 Gradio интерфейс
152
  iface = gr.Interface(
153
- fn=summarize_text,
154
  inputs=gr.Textbox(lines=10, label="Введите текст для анализа и суммаризации"),
155
  outputs=gr.Markdown(label="Результат"),
156
- title="Eroha Summarizer PRO++",
157
- description="AI-инструмент для анализа, определения языка, темы и настроения текста (рус/англ).",
158
  )
159
 
160
  if __name__ == "__main__":
 
3
  from fastapi import FastAPI
4
  from fastapi.middleware.cors import CORSMiddleware
5
  from langdetect import detect
6
+ from functools import lru_cache
7
+ import asyncio
8
+ import re
9
 
10
+ # ======================================================
11
+ # 🚀 Eroha Summarizer PRO+++ v2.0 (by Yermek68)
12
+ # ======================================================
13
 
14
+ # Кэш пайплайнов
15
+ @lru_cache(maxsize=10)
16
+ def get_summarizer(lang: str, long: bool = False):
17
  if lang == "ru":
18
+ model = "IlyaGusev/mbart_ru_sum_gazeta"
19
+ elif lang == "de":
20
+ model = "ml6team/mbart-large-cc25-cnn-distilled-german"
21
+ elif lang == "es":
22
+ model = "mrm8488/bert2bert_shared-spanish-finetuned-summarization"
23
+ elif lang == "fr":
24
+ model = "mrm8488/mbart-large-finetuned-opus-fr-en"
25
  else:
26
+ model = "facebook/bart-large-cnn" if not long else "pszemraj/led-large-book-summary"
27
+ return pipeline("summarization", model=model)
 
 
28
 
29
+ @lru_cache(maxsize=10)
30
  def get_sentiment_analyzer(lang: str):
31
  if lang == "ru":
32
+ model = "cointegrated/rubert-tiny2-emo"
33
  else:
34
+ model = "j-hartmann/emotion-english-distilroberta-base"
35
+ return pipeline("text-classification", model=model, top_k=None)
36
+
37
+ # ======================================
38
+ # 🧠 Вспомогательные функции
39
+ # ======================================
40
+
41
+ def clean_text(text: str) -> str:
42
+ text = re.sub(r"[^\x00-\x7Fа-яА-ЯёЁ.,!?;:\-–—«»\"'()\[\] ]", "", text)
43
+ text = text.replace("▁", " ").replace("<n>", "\n").replace("<s>", "").replace("</s>", "")
44
+ text = text.replace("Ġ", " ").replace("Â", "").replace("", "").replace("�", "").strip()
45
+ return re.sub(" +", " ", text)
46
 
 
47
  def detect_topic(text: str):
48
  topics = {
49
+ "Политика": ["правительство", "закон", "президент", "выборы"],
50
+ "Экономика": ["компания", "рынок", "инвестиции", "бизнес"],
51
+ "Технологии": ["AI", "робот", "интернет", "технологии"],
52
+ "Спорт": ["команда", "матч", "игра"],
53
+ "Наука": ["исследование", "данные", "учёные"],
54
  }
55
+ t = text.lower()
56
+ for topic, keys in topics.items():
57
+ if any(k in t for k in keys):
58
  return topic
59
  return "Общее / неопределённое направление"
60
 
61
+ def detect_genre(text: str):
62
+ t = text.lower()
63
+ if any(w in t for w in ["заявил", "сообщил", "вчера", "компания", "год"]):
64
+ return "📰 Новость"
65
+ if any(w in t for w in ["исследование", "данные", "анализ", "эксперимент"]):
66
+ return "📊 Аналитика"
67
+ if any(w in t for w in ["купил", "доволен", "рекомендую", "��е советую"]):
68
+ return "🗣️ Отзыв"
69
+ if any(w in t for w in ["коммерческий", "продукт", "цена", "скидка"]):
70
+ return "📢 Реклама"
71
+ return "📄 Текст общего типа"
72
+
73
+ # =====================================================
74
+ # 🧩 Основная функция суммаризации
75
+ # =====================================================
76
+
77
+ async def summarize_text(text: str):
 
 
78
  if not text.strip():
79
  return "❌ Введите текст для анализа."
80
 
 
83
  except:
84
  lang = "en"
85
 
86
+ text = clean_text(text)
87
+ words = len(text.split())
88
+
89
+ long_doc = words > 800
90
+ summarizer = get_summarizer(lang, long_doc)
91
  sentiment_model = get_sentiment_analyzer(lang)
92
 
 
 
93
  if words < 50:
94
+ summary = text
 
95
  else:
96
+ max_len, min_len = (250, 60) if words > 300 else (120, 40)
97
+ loop = asyncio.get_event_loop()
98
+ summary_raw = await loop.run_in_executor(None, lambda: summarizer(text, max_length=max_len, min_length=min_len, do_sample=False)[0]["summary_text"])
99
+ summary = clean_text(summary_raw)
100
+
101
+ # Анализ эмоций
102
+ loop = asyncio.get_event_loop()
103
+ emotions = await loop.run_in_executor(None, lambda: sentiment_model(summary))
104
+ emo_label = emotions[0]["label"]
105
+ emo_score = emotions[0].get("score", 0)
106
+
107
+ # Маппинг эмоций
108
+ emo_map = {
109
+ "joy": "😊 Радость",
110
+ "sadness": "😢 Грусть",
111
+ "anger": "😠 Гнев",
112
+ "fear": "😨 Тревога",
113
+ "neutral": "😐 Нейтральное",
114
+ "surprise": "😲 Удивление",
115
+ "disgust": "🤢 Отвращение"
116
+ }
117
+ emotion = emo_map.get(emo_label.lower(), "😐 Нейтральное")
 
 
 
 
 
 
118
 
119
+ # Определение темы и жанра
120
  topic = detect_topic(text)
121
+ genre = detect_genre(text)
122
 
123
+ # Цветовое оформление
124
+ color = "green" if "Радость" in emotion else "red" if "Гнев" in emotion or "Грусть" in emotion else "orange"
125
+
126
+ # Форматированный вывод
127
  output = f"""
128
+ # 🧠 <span style='color:#0073e6'>Eroha Summarizer PRO+++ v2.0</span>
129
  _(Автоязык: {'Русский' if lang == 'ru' else 'Английский'})_
130
 
131
  ---
132
 
133
+ ### 📌 Тема: <b>{topic}</b>
134
+ ### 🗂️ Жанр: {genre}
135
+ ### 💬 Настроение: <span style='color:{color}'>{emotion}</span> ({emo_score:.2f})
136
 
137
  ---
138
 
139
+ ## 📘 Резюме:
140
  {summary}
141
 
142
  ---
143
 
144
+ ### ✨ TL;DR:
145
  {summary[:200]}{'...' if len(summary) > 200 else ''}
 
146
 
147
+ ---
148
+
149
+ *Eroha Intelligence Suite — Multilingual AI summarizer powered by Hugging Face*
150
+ """
151
  return output.strip()
152
 
153
+ # =====================================================
154
+ # 🌐 FastAPI backend
155
+ # =====================================================
156
+
157
+ app = FastAPI(title="Eroha Summarizer PRO+++ v2.0", version="2.0")
158
+ app.add_middleware(CORSMiddleware, allow_origins=["*"], allow_methods=["*"], allow_headers=["*"])
 
 
159
 
160
+ @app.post("/api/full")
161
+ async def api_full(data: dict):
162
  text = data.get("text", "")
163
+ summary = await summarize_text(text)
164
+ return {"summary": summary}
165
+
166
+ @app.post("/api/lite")
167
+ async def api_lite(data: dict):
168
+ text = data.get("text", "")
169
+ result = await summarize_text(text)
170
+ clean_result = re.sub(r"<[^>]+>", "", result)
171
+ return {"tldr": clean_result[:300]}
172
+
173
+ # =====================================================
174
+ # 🎨 Gradio интерфейс
175
+ # =====================================================
176
+
177
+ def gradio_summary(text):
178
+ return asyncio.run(summarize_text(text))
179
 
 
180
  iface = gr.Interface(
181
+ fn=gradio_summary,
182
  inputs=gr.Textbox(lines=10, label="Введите текст для анализа и суммаризации"),
183
  outputs=gr.Markdown(label="Результат"),
184
+ title="Eroha Summarizer PRO+++ v2.0",
185
+ description="AI-инструмент нового поколения для анализа, определения языка, темы, эмоций и настроения текста (рус/англ/нем/исп/фр)."
186
  )
187
 
188
  if __name__ == "__main__":