DevGang
Авторизоваться

Создайте свой собственный 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.

Источник:

#Python #FastAPI
Комментарии
Чтобы оставить комментарий, необходимо авторизоваться

Присоединяйся в тусовку

В этом месте могла бы быть ваша реклама

Разместить рекламу