Spaces:
Sleeping
Sleeping
ivanovot
commited on
Commit
·
6cc6c10
1
Parent(s):
e5d6f4d
Add application file
Browse files- LICENSE +21 -0
- app.py +56 -0
- main.py +22 -0
- model.pth +3 -0
- model/__init__.py +1 -0
- model/__pycache__/__init__.cpython-312.pyc +0 -0
- model/__pycache__/model.cpython-312.pyc +0 -0
- model/model.py +68 -0
- requirements.txt +0 -0
LICENSE
ADDED
@@ -0,0 +1,21 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
MIT License
|
2 |
+
|
3 |
+
Copyright (c) 2024 ivanovot
|
4 |
+
|
5 |
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
6 |
+
of this software and associated documentation files (the "Software"), to deal
|
7 |
+
in the Software without restriction, including without limitation the rights
|
8 |
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9 |
+
copies of the Software, and to permit persons to whom the Software is
|
10 |
+
furnished to do so, subject to the following conditions:
|
11 |
+
|
12 |
+
The above copyright notice and this permission notice shall be included in all
|
13 |
+
copies or substantial portions of the Software.
|
14 |
+
|
15 |
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16 |
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17 |
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
18 |
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19 |
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20 |
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
21 |
+
SOFTWARE.
|
app.py
ADDED
@@ -0,0 +1,56 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import gradio as gr
|
2 |
+
from model import model # Импортируем вашу модель
|
3 |
+
|
4 |
+
# Токсичные и нетоксичные комментарии для тестирования
|
5 |
+
examples = [
|
6 |
+
["Страницу обнови, дебил. Это тоже не оскорбление, а доказанный факт - не-дебил про себя во множественном числе писать не будет. Или мы в тебя верим - это ты и твои воображаемые друзья?"],
|
7 |
+
["УПАД Т! ТАМ НЕЛЬЗЯ СТРОИТЬ! ТЕХНОЛОГИЙ НЕТ! РАЗВОРУЮТ КАК ВСЕГДА! УЖЕ ТРЕЩИНАМИ ПОШ Л! ТУПЫЕ КИТАЗЫ НЕ МОГУТ НИЧЕГО НОРМАЛЬНО СДЕЛАТЬ!"],
|
8 |
+
["хорош врать, ты террорист-торчёк-шизофреник пруф: а вот без костюма да чутка учёный, миллиардер, филантроп"],
|
9 |
+
["Мне Вас очень жаль, если для Вас оскорбления - норма"],
|
10 |
+
["Осторожней на сверхманёврах. В предыдущей методичке у вас было написано, что добрые арабы никогда ни с кем не воевали, только торговали пряностями, лел. Шапочку из фольги сними"],
|
11 |
+
["Так то стоит около 12,5 тысяч, но мне вышло в 6636 рублей и бесплатная доставка"],
|
12 |
+
["Ну хочешь я стану твоим другом? Как тебя зовут? Чем увлекаешься?"],
|
13 |
+
["Ну так это в плане изготовления изделий своими руками,а вот готовить вроде умею.Короче буду сам на себе испытывать божественный напиток и куплю огнетушитель (промышленный на всякий случай)."],
|
14 |
+
["Я согласен, что это хорошая идея! Давайте подумаем, как можно улучшить её еще больше."],
|
15 |
+
["Очень полезная информация, спасибо за подробное объяснение! Я многому научился."],
|
16 |
+
["Мне нравится, как вы объясняете! Это действительно помогает разобраться в теме."],
|
17 |
+
["Отлично написано, теперь я лучше понимаю, как работать с этим инструментом."],
|
18 |
+
["Классная идея! Надо попробовать и посмотреть, как это работает на практике."],
|
19 |
+
["Ваши советы очень полезны. Это точно сэкономит мне время на следующий раз."],
|
20 |
+
["Спасибо за ваши рекомендации! Я обязательно попробую это в будущем."],
|
21 |
+
["Мне нравится ваше решение этой проблемы. Очень креативно и практично."],
|
22 |
+
["Спасибо за помощь! Вы помогли мне разобраться в ситуации и сэкономить много времени."],
|
23 |
+
["Согласен с вами, это действительно важный аспект, о котором стоит задуматься."],
|
24 |
+
["Очень вдохновляющий пост! Я буду следовать вашим рекомендациям."],
|
25 |
+
]
|
26 |
+
|
27 |
+
# Функция для предсказания токсичности текста
|
28 |
+
def predict_text(text):
|
29 |
+
word_count = len(text.split())
|
30 |
+
if word_count < 7:
|
31 |
+
return "Слишком короткий текст"
|
32 |
+
|
33 |
+
output = model.predict(text)
|
34 |
+
return "Токсичный" if output == 1 else "Не токсичный"
|
35 |
+
|
36 |
+
# Создаем интерфейс с улучшениями
|
37 |
+
demo = gr.Interface(
|
38 |
+
fn=predict_text, # Функция для предсказания
|
39 |
+
inputs=gr.Textbox(
|
40 |
+
label="Введите текст для проверки на токсичность", # Подпись для текстового поля
|
41 |
+
placeholder="Напишите комментарий для анализа", # Подсказка для поля ввода
|
42 |
+
lines=5, # Количество строк для текста
|
43 |
+
interactive=True, # Интерактивность для пользователя
|
44 |
+
),
|
45 |
+
outputs=gr.Textbox(
|
46 |
+
label="Результат анализа", # Подпись для вывода
|
47 |
+
placeholder="Результат токсичности текста будет здесь", # Подсказка для вывода
|
48 |
+
),
|
49 |
+
live=True, # Включаем live обновление
|
50 |
+
examples=examples, # Примеры для пользователей
|
51 |
+
title="Тестирование токсичности текста", # Заголовок интерфейса
|
52 |
+
description="Введите любой текст, чтобы проверить его на токсичность. Модель проанализирует, является ли текст токсичным или нет.", # Описание
|
53 |
+
)
|
54 |
+
|
55 |
+
# Запуск приложения с улучшенным интерфейсом
|
56 |
+
demo.launch(server_name="127.0.0.1", server_port=7860)
|
main.py
ADDED
@@ -0,0 +1,22 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
from fastapi import FastAPI, Query
|
2 |
+
from model import model # Импортируйте вашу модель
|
3 |
+
|
4 |
+
app = FastAPI()
|
5 |
+
|
6 |
+
@app.get("/", response_model=int)
|
7 |
+
async def predict(text: str = Query(...)):
|
8 |
+
"""
|
9 |
+
Эндпоинт для предсказания. Принимает текстовый параметр в запросе.
|
10 |
+
|
11 |
+
:param text: текст для предсказания
|
12 |
+
:return: предсказание модели
|
13 |
+
"""
|
14 |
+
# Получаем предсказание от модели
|
15 |
+
output = model.predict(text)
|
16 |
+
|
17 |
+
# Возвращаем результат
|
18 |
+
return output
|
19 |
+
|
20 |
+
if __name__ == "__main__":
|
21 |
+
import uvicorn
|
22 |
+
uvicorn.run(app, host="127.0.0.1", port=8000)
|
model.pth
ADDED
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
1 |
+
version https://git-lfs.github.com/spec/v1
|
2 |
+
oid sha256:d450dffd595a4046900b27864c6df703e62a658bf5e74e3a4230a2c86040f359
|
3 |
+
size 732509954
|
model/__init__.py
ADDED
@@ -0,0 +1 @@
|
|
|
|
|
1 |
+
from .model import model
|
model/__pycache__/__init__.cpython-312.pyc
ADDED
Binary file (176 Bytes). View file
|
|
model/__pycache__/model.cpython-312.pyc
ADDED
Binary file (3.69 kB). View file
|
|
model/model.py
ADDED
@@ -0,0 +1,68 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import torch
|
2 |
+
from transformers import BertTokenizer, BertModel
|
3 |
+
import torch.nn as nn
|
4 |
+
|
5 |
+
class PowerfulBinaryTextClassifier(nn.Module):
|
6 |
+
def __init__(self, model_name, lstm_hidden_size=256, num_layers=3, dropout_rate=0.2):
|
7 |
+
super(PowerfulBinaryTextClassifier, self).__init__()
|
8 |
+
self.bert = BertModel.from_pretrained(model_name)
|
9 |
+
|
10 |
+
# Добавляем несколько LSTM слоев с большим размером скрытого состояния
|
11 |
+
self.lstm = nn.LSTM(input_size=self.bert.config.hidden_size,
|
12 |
+
hidden_size=lstm_hidden_size,
|
13 |
+
num_layers=num_layers,
|
14 |
+
batch_first=True,
|
15 |
+
bidirectional=True,
|
16 |
+
dropout=dropout_rate if num_layers > 1 else 0)
|
17 |
+
|
18 |
+
# Полносвязный блок с увеличенным количеством нейронов и слоев Dropout
|
19 |
+
self.fc = nn.Sequential(
|
20 |
+
nn.Linear(lstm_hidden_size * 2, 2), # полносвязный слой
|
21 |
+
nn.Sigmoid()
|
22 |
+
)
|
23 |
+
|
24 |
+
self.tokenizer = BertTokenizer.from_pretrained(model_name) # Инициализация токенизатора
|
25 |
+
|
26 |
+
self.device = 'cuda' if torch.cuda.is_available() else 'cpu'
|
27 |
+
|
28 |
+
def forward(self, input_ids, attention_mask):
|
29 |
+
outputs = self.bert(input_ids=input_ids, attention_mask=attention_mask)
|
30 |
+
bert_outputs = outputs.last_hidden_state # (batch_size, sequence_length, hidden_size)
|
31 |
+
|
32 |
+
# Применяем LSTM
|
33 |
+
lstm_out, _ = self.lstm(bert_outputs) # (batch_size, sequence_length, lstm_hidden_size * 2)
|
34 |
+
|
35 |
+
# Берем выход последнего временного шага для классификации
|
36 |
+
last_time_step = lstm_out[:, -1, :] # (batch_size, lstm_hidden_size * 2)
|
37 |
+
|
38 |
+
logits = self.fc(last_time_step) # Применяем полносвязный блок
|
39 |
+
|
40 |
+
logits[:, 1] -= 0.995 # Умножаем логит для выбранного класса
|
41 |
+
|
42 |
+
return logits # Возвращаем логиты для двух классов
|
43 |
+
|
44 |
+
def predict(self, text):
|
45 |
+
self.to(self.device) # Переносим модель на выбранное устройство
|
46 |
+
|
47 |
+
# Токенизация текста
|
48 |
+
inputs = self.tokenizer(text, return_tensors="pt", padding=True, truncation=True, max_length=256)
|
49 |
+
input_ids = inputs['input_ids'].to(self.device) # Переносим на устройство
|
50 |
+
attention_mask = inputs['attention_mask'].to(self.device) # Переносим на устройство
|
51 |
+
|
52 |
+
# Получение предсказания
|
53 |
+
self.eval() # Переключаем модель в режим оценки
|
54 |
+
with torch.no_grad():
|
55 |
+
preds = self(input_ids, attention_mask) # Получаем логиты
|
56 |
+
|
57 |
+
# Возвращаем индекс класса с наибольшей вероятностью
|
58 |
+
return torch.argmax(preds, dim=1).item() # Возвращаем индекс класса
|
59 |
+
|
60 |
+
def load_weights(self, filepath):
|
61 |
+
# Загрузка весов модели
|
62 |
+
self.load_state_dict(torch.load(filepath, map_location=self.device, weights_only=True))
|
63 |
+
|
64 |
+
# Пример инициализации модели
|
65 |
+
model_name = "DeepPavlov/rubert-base-cased"
|
66 |
+
model = PowerfulBinaryTextClassifier(model_name)
|
67 |
+
|
68 |
+
model.load_weights('model.pth')
|
requirements.txt
ADDED
Binary file (2.25 kB). View file
|
|