Повесть нейросетевых охот
Путь длиной в 40 экспериментов, 8 моделей, 172 размеченных вакансий и 20 признаков, чтобы научиться отличать нормальную шабашку от развода. Я расскажу, как это работает и почему просто спросить у нейросети “это нормальная вакансия?” недостаточно.
Тайны пермской шабашки
Помните пост про сортировщика рыболовных снастей в группе Ростова или про человека для подсчета трупов в морге? Начала собирать вакансии из Telegram-каналов Перми и поняла, что нахожусь на вражеской территории.
На hh.ru все прилично: компания, требования, трудовой договор, а в Telegram-каналах вот это:
Сегодня к 10.00 одного грузчика… по 350/3 оплата сразу
Для любой корпоративной системы это красный флаг: нет компании, нет договора, не указаны никакие подробности и требования. А для телеграмчика вполне приемлемо, реальная подработка.
Вопрос: как научить машину отличать реальную шабашку от развода под прикрытием?
План А: спросить у нейросети напрямую
Самое очевидное решение: берем пост, отправляем в нейросеть и просим: “Оцени подозрительность от 0 до 100” легко и просто казалось бы, что еще придумывать. Но результат вышел смешной, нейросеть в целом понимает, что подозрительно, а что нет, но с числами у нее беда. Один и тот же пост сегодня получает 45, завтра – 68, а важно, чтобы система была последовательной.
Максимум, что удалось выжать из прямого подхода:
- Точность по категориям: 74.4%
- Ошибка в оценке: 13-17 баллов на разных экспериментах
Неплохо, но для прода так себе. Когда пользователь спрашивает “почему эта вакансия получила 72 балла?” ответ “нейросеть так придумала”… сомнииительно но окей.
План Б: разделяем задачи
Есть другой вариант, которым я пошла: кидать кубик d20 5 раз нейросеть умеет находить паттерны из контекста, но с математическими вычислениями справляется медленнее калькулятора.
Поэтому я разделила задачу на две:
- Нейросеть отвечает только на вопросы “да/нет” (или ставит оценку от 0 до 1)
- Формула собирает эти ответы в итоговую оценку
Так родилась система из 16 иллюзорных факторов. Шестнадцатым арканом Таро является карта Башни: символ разрушения старого, у меня тоже 16 признаков, которые обрушаются на способы мошенничества 🤓
🛠 Техническая часть, если кто-то знает слова LLM и микросервис
Чтобы вы понимали масштаб бедствия (и инженерной мысли), не вдаваясь в подробности реализации, расскажу из каких слоев состоит кх.
Слой 0. Входной фильтр
Прежде чем вакансия попадет в систему, она проходит через проверку уверенности. У каждого поста есть параметр confidence – насколько микросервис коллектора уверен, что это вообще вакансия, на интерфейсе это подписано “Уверенность извлечения: n%”.
Если confidence < 0.5, пост отбрасывается сразу. Но все равно проскакивают посты, которые вакансиями не являются, хотя были распознаны как таковые.
Слой 1. Железо и софт
Все крутится на Ollama, она позволяет гонять нейросети локально. Модель gemma3:12b от Google
Слой 2. Извлечение контактов
Первым делом микросервис обработки достает из поста контакты и другие данные: телефоны, Telegram-юзернеймы, почту, адреса. Гибридный подход: сначала регулярные выражения (быстрее), потом LLM (точнее + больше контекста).
Дальше мы проверяем, существует ли этот контакт в Telegram. По API смотрим, есть ли юзер. Это, кстати, одна из причин, почему всё так долго – Telegram не спешит отвечать и иногда валится в подключении.
Cлой 3. Правила и паттерны
Перед обработкой LLM выявляются базовые паттерны мошенничества с rule engine – набор регулярных выражений (regex),которые задают контекст для последующего LLM анализа.
Слой 4. Извлечение факторов
Нейросеть получает промпт с четкими инструкциями проверки факторов, температуру установили в ноль, чтобы модель не фантазировала. Промпт собран через DSPy – библиотеку, которая сама подбирает удачные примеры для обучения.
Rule engine сам по себе ловит только 40% скамов, но он важен как контекст: когда мы передаем его результаты нейросети, качество анализа LLM растет на 16%.
Слой 5. Формула расчета
Дальше вступает математика: у каждого фактора есть вес – число, которое говорит, насколько сильно этот признак влияет на итог. Веса подбирал Optuna – алгоритм, который перебрал 500 комбинаций, чтобы найти баланс на нашем датасете из 172 размеченных вакансий.
Слой 6. Репутация автора
Отдельный модуль следит за авторами постов. У каждого poster_id копится история:
- Средний уровень подозрительности
- Количество скамных постов
- Доверительный скоринг
Если дяденька постоянно постит скам, его новые вакансии получают штрафные баллы. Если репутация чистая.. ну он молодец, без штрафа остается, можем опустить на 5 баллов подозрительность (средняя подозрительность вакансий <31 и его вакансий >2).
Слой 7. Финальный вердикт
Все подсчеты собираются в одну кучу:
if llm_score > 0:
финальный_балл = min(100, llm_score + репутация)
else:
финальный_балл = min(100, rule_engine_score + репутация) # аварийный режим
Потом балл округляется, сжимается в диапазон 0–100 и летит в базу. Это результат, который уже видите вы.
16 причин почему
Что понижает подозрительность:
- Есть конкретный адрес (улица, дом)
- Указана компания или ИП
- Понятно, чем именно заниматься (не просто “курьер”)
- Требуется опыт (да, это плюс значит, не “золотые горы” для всех подряд)
- Есть телефон или почта (не только Telegram)
- Указана зарплата цифрами
- Грамотный текст (без “здарасвуйте” и “ЧАС0В”)
Что повышает подозрительность:
- Пост не содержит деталей (“нужны люди, пишите в лс”)
- Только Telegram для связи (никакого телефона)
- Искусственная срочность (“ГОРИТ! Осталось 2 места!”)
- Вовлекают несовершеннолетних, берут с 14-16 лет + непонятно на что
- Легкие деньги без опыта
- Зарплата явно выше рынка для такой работы
- Орфографические ошибки и замена символов кириллицы (классика ботов)
- Размытые детали вакансии курьеров/доставщиков
- Работа рядом с важными объектами (жд вокзал, вышка, полицейский участок) без названия компании
Следовало бы понять ранее
Я перебирала факторы и поняла, что важнее не вес, а его формулировка.
Сначала были размытые вопросы, как план А, только по пунктам признаков: “насколько пост расплывчатый?” (оценка от 0 до 1) модель такое обрабатывала слишком субъективно.
Как только заменила на четкие “да/нет” и пошла пошла работааа:
- “Пост не содержит деталей” вместо “оцените расплывчатость”
- “Зарплата подозрительно высокая” вместо “оцените реалистичность”
Как мы настраивали веса
У каждого фактора есть вес, значение насколько сильно он влияет на итоговую оценку. Вот что показала оптимизация:
| Фактор | Был вес | Стал вес | Почему |
|---|---|---|---|
| Легкие деньги | 25 | 40 | Самый сильный сигнал недокручивали |
| Размытые детали доставки | 25 | 42 | В Telegram это почти всегда развод |
| Буквы-цифры | 30 | 44 | Если видите “ЧАС0В” бегите |
| Зарплата выше рынка | 22 | 6 | Нейросеть слишком часто била тревогу на реальных стройках или вахте |
Комбо-бонусы
Отдельная магия сочетания факторов. По отдельности они могут быть не страшны, но вместе являются верным признаком мошенничества:
- “Только Telegram” + “Легкие деньги” = +25 баллов
- “Размытые детали доставки” + “Только Telegram” = +24 балла
- “Вовлечение несовершеннолетних” + “Легкие деньги” = +16 баллов
- “Только Telegram” + “Зарплата выше рынка” = +15 баллов
Что получилось в итоге
Сравните сами:
| Метрика | Просто спросили нейросеть | Наша система |
|---|---|---|
| Точность по категориям | 74.4% | 79.1% |
| Ошибка в оценке | ±17 баллов | ±13.7 балла |
| Можно объяснить результат? | Нет (“так сказала нейросеть”) | Да (вот 16 факторов) |
| Ловит ли скам | Да, 85% | Да, 74% (чуть хуже) |
| Ошибается ли на нормальных | Да, 21% ложных тревог | Нет, только 13% |
Еще мы сознательно пожертвовали от 10,7% до 17,4% обнаружения скамов ради того, чтобы в 2 раза реже ошибаться на нормальных вакансиях, потому что когда система говорит “это скам” на реальную шабашку, ей перестают верить. Хотя недавние исследования заставили меня сомневаться во всех одобрительных расчетах…
Как это работает сейчас
Пример поста:
Нужны два человека на объект по адресу Целинная 29А устанавливать розетки и выключатели. Работы на неделю. 400 рублей/час. Пишите в личку или звоните [телефон]
Система видит: адрес есть, работа конкретная, зарплата указана, телефон есть. Итог: 0 баллов (зеленый).
А вот другой:
Здарасвуйте нам требуються сотруднки на халтурку. ЗП 10 000 за 2-4 ЧАС0В. Берем без опыта. Пиши в лс
Здесь: “ЧАС0В” (буква-цифра), “халтурка” без деталей, только Telegram, легкие деньги. 100 баллов (красный).
Что дальше
Сейчас система:
- Смотрит на 16 факторов
- Складывает их с оптимизированными весами
- Добавляет бонусы за опасные сочетания
- Учитывает репутацию автора
В планах:
- Добрать данных в “серой зоне” (30-60 баллов)
- Научить систему лучше отличать реально высокие зарплаты от развода
- Добавить вторую нейросеть для перепроверки сложных случаев
Но.
Параллельно тому, как писала этот пост, я собирала отклики с других вакансий и нашла то, чего в нашей системе пока нет. Новые прикрытия, которые надо извлекать из контекста ОЧЕНЬ аккуратно, это значит что система факторов и сочетаний будет дорабатываться и вероятно не раз.
Скам не стоит на месте и за ним надо поспевать, так что «Что дальше» это про бесконечную гонку, где они придумывают новые способы обмана, мы – новые способы их ловить.
Вот такие дела, stay tuned