From b2f743b5daf51efac4234248e490e3f9bfe3082b Mon Sep 17 00:00:00 2001 From: MpakobecEx Date: Wed, 14 Oct 2026 19:48:00 +0500 Subject: [PATCH] =?UTF-8?q?=D0=A1=D0=B1=D0=BE=D1=80=D0=BA=D0=B0=20=D0=B1?= =?UTF-8?q?=D0=B5=D0=B7=20OpenCV?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit На CI модуль зависал. Для i2i без него оставил консервативную проверку. --- README.md | 2 +- checklist.md | 2 +- moderation.py | 12 +++++++++--- requirements.txt | 1 - tests/test_moderation.py | 1 + 5 files changed, 12 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index f94070d..6aa22ca 100644 --- a/README.md +++ b/README.md @@ -118,7 +118,7 @@ BLOCKED_PUBLIC_FIGURES= - экстремизм + инструкции/символика; - обходные написания (`n_u_d_e`, `l0li`, `ch1ld` и т.п.). -Для i2i OpenCV проверяет наличие лица/человека на входном фото: NSFW-промпт в этом случае блокируется. +Для i2i: если установлен OpenCV, проверяется наличие лица/человека. В базовом образе OpenCV нет, поэтому NSFW-промпты в i2i блокируются консервативно — как если бы на фото был человек. При блокировке пользователь получает «Запрос нарушает правила. Звёзды не списаны.», а запись с `user_id`, временем, промптом и причиной сохраняется в таблицу `blocked_requests`. diff --git a/checklist.md b/checklist.md index 940227f..aa89889 100644 --- a/checklist.md +++ b/checklist.md @@ -324,7 +324,7 @@ ON requests(user_id) WHERE status IN ('queued', 'running'); - [x] Админы из `ADMIN_USER_IDS` обходят фильтр. - [x] Логирование блокировок в `blocked_requests`. - [x] Ответ «Запрос нарушает правила. Звёзды не списаны.». -- [x] i2i: детекция лица/человека через OpenCV. +- [x] i2i: OpenCV-детекция при наличии; иначе консервативный ручной флаг. - [x] Тесты правил и очереди. **DoD:** небезопасный промпт не попадает в очередь, причина пишется в БД, админ может отправлять без фильтра. diff --git a/moderation.py b/moderation.py index b2733d4..4cba946 100644 --- a/moderation.py +++ b/moderation.py @@ -301,12 +301,18 @@ def is_prompt_allowed( def detect_person(path: str | Path) -> bool: - """Ищет лицо или человека через OpenCV. При ошибке считает, что человека нет.""" + """Ищет лицо или человека через OpenCV. + + Если OpenCV не установлен, консервативно считаем, что человек есть: + NSFW-запросы в i2i будут блокироваться. + """ try: import cv2 # type: ignore[import-not-found] except ImportError: - logger.warning("OpenCV не установлен, детекция людей отключена") - return False + logger.warning( + "OpenCV не установлен: для i2i считаем, что на фото есть человек" + ) + return True try: image = cv2.imread(str(path)) diff --git a/requirements.txt b/requirements.txt index 587c5c8..76f3e41 100644 --- a/requirements.txt +++ b/requirements.txt @@ -7,4 +7,3 @@ fastapi>=0.115,<1 uvicorn>=0.30,<1 jinja2>=3.1,<4 pillow>=10,<13 -opencv-python-headless>=4.10,<5 diff --git a/tests/test_moderation.py b/tests/test_moderation.py index 5c73274..29ca5b7 100644 --- a/tests/test_moderation.py +++ b/tests/test_moderation.py @@ -63,6 +63,7 @@ def test_extra_public_figures() -> None: def test_detect_person_blank_image(tmp_path) -> None: + pytest.importorskip("cv2") path = tmp_path / "blank.png" with Image.new("RGB", (320, 240), (255, 255, 255)) as image: image.save(path)