Модерация комментариев нейросетью: пример на Python
Спам, оскорбления, реклама, нормальные комментарии — нейросеть раскладывает их по ярлыкам, а спорные отдаёт модератору. Показываем код и считаем стоимость.
3 мин · · разработка · бизнес
Модерировать комментарии вручную утомительно: каждый нужно прочитать и решить, нормальный он или это спам, оскорбление, реклама. При тысячах комментариев в день очередь растёт быстрее, чем её разбирают. Ниже — система автоматической модерации через API с очередью для сомнительных случаев, пакетной обработкой и честным расчётом стоимости.
Как работает модерация
Каждый комментарий получает ярлык:
- ok: нормальный комментарий, публикуем.
- spam: явный спам, удаляем.
- insult: оскорбление, скрываем.
- ads: реклама, удаляем.
Плюс значение уверенности (confidence). Если модель не уверена (confidence ниже порога), комментарий идёт в очередь к модератору. Так автоматизация берёт на себя очевидные случаи, а человек решает спорные.
Быстрая модерация с glm-5.3-flash
Начнём с самой дешёвой модели Zukko — glm-5.3-flash ($0,04/$0,04 за 1M токенов). Подходит ли она для ваших комментариев, проверим ниже на размеченной выборке.
import json
from openai import OpenAI
client = OpenAI(
base_url="https://api.zukko.pro/v1",
api_key="fetch_ваш_ключ",
)
LABELS = ["ok", "spam", "insult", "ads"]
SYSTEM_PROMPT = """Ты модератор комментариев. Оцени комментарий и выбери ярлык.
Ярлыки:
- ok: нормальный комментарий, публиковатьМаршрутизация: автоматически или к человеку
Не все случаи очевидны. Если уверенность ниже порога, комментарий идёт модератору:
ACTIONS = {"ok": "publish", "spam": "delete", "insult": "hide", "ads": "delete"}
def route_comment(text: str, threshold: float = 0.8) -> dict:
"""Решает: опубликовать, удалить или отправить на проверку"""
result = moderate_comment(text)
confidence = float(result.get("confidence", 0))
if confidence < threshold or result["label"] not in ACTIONS:
return {
"action": "manual_review",
"suggested_label": result["label"],
"confidence": confidence,
"reason": result.get("reasoning", ""),
}
return {"action": ACTIONS[result["label"]], "label": result["label"], "confidence": confidence}
if __name__ == "__main__":
for comment in ["Отличная статья!", "Может, это реклама, а может, и нет", "СПАМ!!!!"]:
print(comment, "->", route_comment(comment)["action"])confidence модель выставляет сама, это не откалиброванная вероятность. Порог 0,8 — стартовое значение; подберите своё по выборке, где правильные ярлыки уже проставлены людьми.
Пакетная обработка: десятки комментариев за запрос
Для ночной проверки или разбора архива удобно отправлять комментарии пачками по 20–50 штук. Просим модель вернуть номер комментария, чтобы ответы не перепутались:
def moderate_batch(comments: list[str], model: str = "glm-5.3-flash") -> dict[int, dict]:
"""Модерирует пачку комментариев, возвращает {номер: результат}"""
batch_text = "\n---\n".join(f"Комментарий {i}:\n{c}" for i, c in enumerate(comments, 1))
system_for_batch = SYSTEM_PROMPT + """
Тебе пришло несколько комментариев. Для КАЖДОГО выведи одну строку JSON:
{"id": <номер комментария>, "label": "...", "confidence": 0.9}
Одна строка — один объект, без лишнего текста.
"""
response = client.chat.completions.create(
model=model,
max_tokens=60 * len(comments) + 100,
messages=[
{"role": "system", "content": system_for_batch},
{"role": "user", "content": batch_text},Очередь для модератора
Комментарии с низкой уверенностью копятся в отдельной очереди. Модератор подтверждает или исправляет решение:
class ModerationQueue:
def __init__(self):
self.items = [] # в реальном проекте — таблица в базе
def add(self, comment_id: str, text: str, suggestion: dict):
self.items.append({
"id": comment_id,
"text": text,
"suggestion": suggestion, # что предложила модель
"status": "pending",
})
def resolve(self, comment_id: str, final_label: str):
"""Модератор принял решение"""Сохраняйте финальные решения модератора вместе с предложением модели: из этих пар получится размеченная выборка, по которой можно пересчитывать точность и подбирать порог.
Стоимость
Расчёт для 10 000 комментариев в месяц на glm-5.3-flash, в среднем 200 входных и 50 выходных токенов на комментарий:
(10 000 × 200 × 0.04 / 1M) + (10 000 × 50 × 0.04 / 1M)
= $0.08 + $0.02 = $0.10 в месяц
Если перепроверять спорные комментарии на claude-sonnet-5 ($0,30/$0,30), каждая тысяча таких перепроверок добавит 1000 × 250 × 0.30 / 1M = $0.075. Какая доля окажется спорной, зависит от вашей площадки и порога — посчитайте на своих данных.
Актуальные цены и модели: GET https://api.zukko.pro/v1/models или страница «Модели» в кабинете.
Настройка ключа
Создайте ключ в кабинете Zukko, разрешите ему только нужные модели и поставьте месячный лимит — для 10 тысяч комментариев с запасом хватит $1. См. также быстрый старт и примеры на Python.
Частые вопросы
Как часто разбирать очередь?
Зависит от площадки. Где комментарии видны сразу и важна реакция (новости, соцсети), очередь разбирают в течение дня. На форумах и в блогах достаточно одного-двух раз в день.
Может ли модель учиться на решениях модератора?
Сама по себе нет. Но решения модератора можно добавлять в промпт как примеры («такой комментарий — ads») и периодически пересчитывать точность. Если точность падает, перенесите спорные случаи на другую модель и сравните результат на той же выборке.
Что если комментарии на нескольких языках?
Укажите в промпте, что комментарии могут быть на разных языках, и добавьте в тестовую выборку примеры на каждом. Сравните точность glm-5.3-flash и claude-sonnet-5 на этих примерах — так вы узнаете, нужна ли более дорогая модель.
Стоит ли модерировать старые комментарии?
Если архив раньше не проверялся, пакетная обработка позволит пройтись по нему недорого: 10 000 комментариев на glm-5.3-flash обойдутся примерно в $0.10.
zukko
Платите в 25×
меньше
за Claude Code & ChatGPT
Один ключ fetch_* и base URL api.zukko.pro — в Cursor, Claude Code, Codex и любом SDK.
Похожие статьи
- Промпт-инъекция: что это и как защитить бота и агентаОбъясняем, как работает промпт-инъекция через пользовательский ввод и чужие документы, и какие меры снижают ущерб: изоляция данных, права инструментов, лимиты ключа.
- Свой прокси к нейросети на Node.js: не показывать API-ключ во фронтендеНебольшой сервер на Express между вашим фронтендом и API нейросети: ключ остаётся на сервере, а модели, длина запроса и частота ограничены.
- DeepSeek API на Python: запросы, стриминг, JSON и обработка ошибокГотовый код для DeepSeek V4.1 Flash и V4 Pro на OpenAI SDK: запрос, стриминг, разбор JSON и аккуратная обработка ошибок.
- Промпт-инжиниринг: примеры и 12 готовых шаблонов для работыДвенадцать шаблонов промптов для рабочих задач: что в них написано, почему именно так и сколько стоит один вызов по API.