Создайте свой собственный API-детектор токсичных комментариев!
В этой статье я покажу, как построить API-детектор токсичных комментариев с помощью FastAPI.
Из приведенного ниже изображения видно, что API отреагировал на текст "trash stuff" с ответом "toxic comment" и степенью токсичности комментария.
Введение
Токсичность - это грубость, неуважение или иное поведение, которое может заставить человека покинуть дискуссию. Для создания API мы будем использовать Fastapi.
Посмотрите, как работает API:
Когда я ввожу комментарий, например: " trash stuff", как показано ниже:
API определяет, является ли " trash stuff" токсичным комментарием. Судя по приведенному ниже прогнозу, "trash stuff" определенно является токсичным комментарием.
Получение модели и векторизатора
Обученную модель и векторизатор, который поможет преобразовать слова в числовые векторы, можно скачать отсюда.
Вы также можете получить его из репозитория проекта.
Мы используем модель логистической регрессии.
Настройка приложения fastapi
- Создайте новую папку и откройте ее в редакторе кода
- Выполните в терминале следующую команду для создания новой виртуальной среды с именем
.venv
python -m venv .venv
- Активируйте виртуальную среду
.venv\Scripts\activate
- Выполните следующую команду для установки fastapi, pytest, scikit-learn
pip install "fastapi[all]" pytest scikit-learn
- Создайте новый каталог с именем
app
. Внутри каталогаapp
создайте файлыinit.py
,main.py
,schemas.py
,test_main.py
,dependencies.py
и каталог routers. Ваша директория должна иметь следующий вид:
main.py
: добавьте вmain.py
следующий код:
from fastapi import Depends, FastAPI
from .routers import comments
app = FastAPI()
app.include_router(comments.router)
Приведенный выше код устанавливает веб-приложение FastAPI с некоторыми начальными конфигурациями. Он создает экземпляр класса FastAPI и включает маршрутизатор, определяющий маршруты, связанные с комментариями.
schemas.py
: добавьте следующий код в файлschemas.py
:
from pydantic import BaseModel
class Comment(BaseModel):
comments: str
Приведенная выше модель Comment используется для определения структуры комментариев, в частности, они должны быть представлены в виде строк.
dependencies.py
: добавьте следующий код в файлdependencies.py
:
import pickle
from . import schemas
def check_toxicity(comment: schemas.Comment):
comment_dictionary = {}
comment_dictionary['comment_key'] = [comment.comments]
# load the vectorizer and vectorize comment
vectorizer = pickle.load(open("./Vectorize.pickle", "rb"))
testing = vectorizer.transform(comment_dictionary['comment_key'])
# load the model
with open('./Pickle_LR_Model.pkl', 'rb') as file:
lr_model = pickle.load(file)
# predict toxicity. prediction range from 0.0 to 1.0 (0.0 = non-toxic and 1.0 toxic)
prediction = lr_model.predict_proba(testing)[:, 1]
prediction = float(prediction)
if prediction >= 0.9 and prediction <= 1.0:
response_list = ["toxic comment", prediction]
return {"response": response_list}
elif prediction >= 0.0 and prediction <= 0.1:
response_list = ["non toxic comment", prediction]
return {"response": response_list}
else:
response_list = ["Manually check this", prediction]
return {"response": response_list}
Функция check_toxicity
получает комментарий, загружает векторизатор для преобразования комментария в числовые значения, а затем передает числовые значения в модель для предсказания токсичности комментария. Модель возвращает любое прогнозируемое значение от 0,0 до 1,0.
Прогноз с показателем 0,0 означает нетоксичный комментарий, а прогноз с показателем 1,0 - очень токсичный комментарий.
Для API я решил называть предсказания больше или равные 0,9 и меньше или равные 1,0 токсичными комментариями, поскольку в этих случаях модель достаточно уверена, предсказания больше или равные 0,0 и меньше или равные 0,1 нетоксичными комментариями и считать все предсказания от 0,2 до 0,8 ни токсичными, ни нетоксичными комментариями.
test_main.py
: добавьте в файлtest_main.py
следующий код:
from fastapi.testclient import TestClient
from .main import app
client = TestClient(app)
def test_check_toxicity():
response = client.post("/comments/")
response = client.post(
"/comments/",
json={"comments": "string"},
)
assert response.status_code == 200
def test_check_toxicity_wrong_datatype():
response = client.post(
"/comments/",
json={"comments": 20},
)
assert response.status_code == 422
assert response.json() == {
"detail": [
{
"type": "string_type",
"loc": [
"body",
"comments"
],
"msg": "Input should be a valid string",
"input": 20,
"url": "https://errors.pydantic.dev/2.3/v/string_type"
}
]
}
Эти тестовые примеры используют TestClient для имитации HTTP-запросов к приложению FastAPI и последующего подтверждения соответствия ответов ожидаемому поведению. Они позволяют убедиться в том, что конечная точка проверки токсичности комментариев корректно обрабатывает различные сценарии, включая неправильные типы данных и отсутствие данных.
- В каталоге
routers
создайте файлinit.py
и файлcomments.py
. В файлcomments.py
добавьте следующий код:
from typing import Annotated
from fastapi import APIRouter, Depends, HTTPException, status
from ..dependencies import check_toxicity
router = APIRouter(
prefix="/comments",
tags=["comments"],
)
@router.post('/')
async def check_toxic_comment(toxicity_check: Annotated[dict, Depends(check_toxicity)]):
return toxicity_check
Приведенный выше код определяет FastAPI-маршрутизатор (router), который обрабатывает HTTP POST-запросы к "/comments
/", используя зависимость check_toxicity
для валидации и проверки токсичности входящих данных. Сама конечная точка просто возвращает, является ли комментарий токсичным или нет. Использование аннотаций и зависимостей позволяет создать модульный и многократно используемый код, а также четко разделить проблемы.
Добавление модели и векторизатора
Добавьте загруженную модель и векторизатор в корневой каталог проекта.
- Также можно создать файл
.gitignore
и добавить в него следующее:
__pycache__/
.venv/
.pytest_cache
- Создайте файл
requirements.txt
с помощью следующей команды:
pip freeze > requirements.txt
Окончательный каталог проекта должен иметь следующий вид:
Тестирование приложения
Теперь можно протестировать проект.
- Откройте Postman
- Добавьте новый запрос
- Смените метод на POST
- Введите следующий url: http://127.0.0.1:8000/comments/
- Выберите Body, raw и JSON
- Введите для примера следующий JSON-комментарий и нажмите кнопку Send (Отправить):
{
"comments": "trash stuff"
}
API должен ответить следующим образом, чтобы показать, что "trash stuff" - это токсичный комментарий:
{
"response": [
"toxic comment",
0.9616073904446953
]
}
Заключение
По сути, когда вы отправляете JSON-комментарий, приложение fastapi принимает его и вызывает функцию check_toxic_comment
, которая вызывает зависимость check_toxicity
, предсказывающую, является ли комментарий токсичным или нет, и возвращает значение.
Полный код можно получить здесь: https://github.com/emmakodes/fastapi-toxic-comment-detector.