Никто не любит капчу. Угадай слово по плохой картинке, собери пазл, отличи светофор от гидранта, сложи два числа и так далее. Формы бывают разные, но суть всегда одна: мы тратим своё время и нервы.
Чуть больше года назад моя команда взялась за модернизацию старой капчи Яндекса. Обычно в таких задачах стремятся повысить качество и полноту отсева ботов, оставив человеку шанс прорваться через капчу. Но мы зашли с другой стороны: решили сделать капчу более дружелюбной к людям, не ухудшив при этом защиту от ботов. Казалось бы, наивный подход. Но у нас получилось.
Сегодня я расскажу об этом подробнее. Вы узнаете, как мы отказались от распознавания текста и перешли к его генерации. Покажу примеры дружелюбной капчи. Расскажу о необычном опыте применения капчи в образовании. А ещё покажу текущий вариант капчи без капчи и немного поразмышляю о будущем.
Несколько слов о том, зачем нужна капча. Уверен, это и так не секрет, но историю всё же стоит начать с основ, чтобы быть на одной волне.
Капча — это инструмент, который помогает сервису понять, обратился к нему человек или робот. Это полезно, потому что роботы создают нагрузку или даже занимаются откровенным вредительством. При этом нужно показывать капчу не всем, а только тем, чьи запросы похожи на автоматические. Для этого надо проанализировать запрос. Анализ — это уже давно не просто подсчёт числа заходов с конкретного IP. Факторов для анализа намного больше, чем один. С другой стороны — сервис с нагрузкой в сотни тысяч RPS и с жёстким требованием к скорости ответа пользователю. Если снизить скорость ответа, то пострадают пользователи. Если снизить полноту выявления ботов, то в итоге опять же пострадают пользователи. Значит, нужно искать баланс между этими крайностями. И получается, всегда будут люди, которым покажут капчу.
Первые шаги
Год назад наши пользователи видели примерно такие задания:
![](https://habrastorage.org/getpro/habr/upload_files/6f8/315/838/6f8315838b19d4b02c688eadf4d651c8.jpg)
Два слова. Одно мы знаем. Другое хотим узнать. Вряд ли я открою большой секрет, если расскажу, что капчу часто применяют для обучения компьютерного зрения. Раньше так было и у нас.
В целом ничего жуткого, да? Но могу и жути нагнать. Вот примеры более сложных (но крайне редких) вариантов:
![](https://habrastorage.org/getpro/habr/upload_files/058/64b/87f/05864b87f5ad72496229eb23c5791c72.png)
Мы, конечно, такое вычищали. Использовали для этого как классификаторы неоднозначно читаемых картинок, так и данные о поведении пользователей (если человек даже не пытается ввести текст, то это плохой сигнал). Но и после таких изменений людям было очень сложно. Можно сказать, что старая капча отлично экономила ресурсы: её не могли пройти ни боты, ни люди. Только 35% реальных пользователей справлялись с первой попытки. Очень страшное число. Нужно было что-то менять.
Начали с анализа наиболее частых ошибок. В топе оказались знаки препинания, верхний и нижний регистр букв, лишние пробелы. Посчитали, как у ботов с этими проблемами. Оказалось, что можно безболезненно отказаться от их учёта при проверке результата. Эти элементарные, быстрые решения принесли нам с ходу +15%. Но дальше простые идеи закончились. Нужно было подойти к задачке более глобально.
Свои картинки с текстом
Поговорим о картинках. Так как их мы не генерировали, а вырезали из готовых, иногда там встречались очень необычные тексты. Их вы уже видели выше: это и перевёрнутые штрихкоды, и логарифмы. Их можно фильтровать с переменным успехом, но гибкости в работе с ними нет. Нельзя оперативно управлять сложностью, контролировать допустимый словарный запас, выбирать язык для разных стран. Если хочешь полностью контролировать качество капчи, то выход только один — генерировать картинки самостоятельно. Так мы и поступили.
Мы хотели создать капчу, которая будет существенно легче читаться людьми, но не ботами. На входе у нас есть какой-то текст и какой-то фон. Осталось понять, что нужно с ними сделать, чтобы добиться желаемого.
Наиболее эффектно, пожалуй, выглядит способ точечно искажать исходную картинку так, чтобы машина видела в ней совершенно не то, что видит человек.
![Лёгкий шум превратил горы в собаку и рыбку в краба. Источник: https://arxiv.org/pdf/1710.06081v2.pdf Лёгкий шум превратил горы в собаку и рыбку в краба. Источник: https://arxiv.org/pdf/1710.06081v2.pdf](https://habrastorage.org/getpro/habr/upload_files/bbc/163/170/bbc1631703435dd8312dee370ae647a0.jpg)
Но такой подход крайне чувствителен к изменениям алгоритмов распознавания на стороне роботов. Пришлось бы мониторить их особенно тщательно и слишком часто адаптироваться. Поэтому мы подошли более консервативно.
Задачу распознавания текста нейросетями сейчас решают хорошо, причём уже далеко не только лидеры индустрии. Но трудные задачки по-прежнему встречаются. Наиболее сложные датасеты с распознаванием слов на сегодняшний день представляют собой сильно искривлённые тексты (irregular text recognition).
![](https://habrastorage.org/getpro/habr/upload_files/4fe/525/54f/4fe52554fb9d1b1523f6e00b80e83d49.jpg)
Это то, с чем человек справляется относительно просто. Но не робот. Этот подход мы применили и у себя. Пример такой капчи:
![](https://habrastorage.org/getpro/habr/upload_files/d5d/c02/cd9/d5dc02cd91e7659c3b42fc9de776f22b.jpg)
Выглядит проще, чем раньше? Наши пользователи тоже так считают: эту капчу легко преодолевают уже 85% пользователей. А вот ребятам, которые учатся обходить нашу капчу, работы прибавилось.
![Скриншот с одного из «секретных» форумов об автоматизации Скриншот с одного из «секретных» форумов об автоматизации](https://habrastorage.org/getpro/habr/upload_files/1fd/57b/6a4/1fd57b6a4818ef70bb7286f49349de34.png)
Конечно, со временем к ней адаптировались, но масштабы проблемы в итоге не больше, чем у старой капчи. При этом людям стало существенно проще.
Полезная и добрая капча
Успех с генерацией собственных картинок воодушевил нас. Мы осознали, что капче не обязательно быть исключительным злом в глазах пользователей. Она может быть такой, какой мы захотим её сделать. Например, полезной для людей.
Каждый октябрь в России отмечают День учителя. Мы решили отпраздновать его по-своему и с пользой. Собрали данные о том, в каких словах пользователи чаще всего делают ошибки. (Яндекс по понятным причинам неплохо в этом разбирается.) На базе этого словаря сгенерировали капчу, отметив те буквы, в которых люди ошибаются. Выкатили на огромную аудиторию. Ботам это ничем не помогло, а вот людям (хочется верить!) пользу принесло.
![](https://habrastorage.org/getpro/habr/upload_files/e23/d4f/edf/e23d4fedf41024782d24eeb7b9ec9881.png)
Ещё примеры:
![](https://habrastorage.org/getpro/habr/upload_files/c44/6fc/566/c446fc5668df882a6f9f6b648cb5e093.png)
Другой пример работы с капчей, чуть ближе к концу 2020 года. Хотелось немного поднять пользователям настроение. Придумали использовать для генерации капчи не какие попало слова и фразы, а только те, что несут положительный эмоциональный заряд. Проще говоря, такие слова, которые как минимум не портят настроение ещё больше, а в идеале улучшают его.
Собрали данные с помощью толокеров. Сгенерировали. Получили капчу, которая содержала фразы «Приятных эмоций», «Вам всё по плечу», «Продуктивного дня» и подобные.
![](https://habrastorage.org/getpro/habr/upload_files/9ea/8c1/8e6/9ea8c18e66bd6d6597651f7738938356.png)
В общем, идей для работы с капчей много. Но нельзя забывать самую главную: лучшая капча — это та, которой нет.
Капча без капчи
Вернёмся в самое начало нашей истории. Там я рассказывал о том, что капчу предлагают только тем пользователям, чьи запросы в результате быстрого анализа показались нам подозрительными. Быстрый анализ отрабатывает примерно за одну (!) миллисекунду. Делать это дольше без вреда для высоконагруженного сервиса и миллионов пользователей нельзя. Это значит, что нужно использовать быстрые алгоритмы, а они не всегда самые точные. Из-за этого люди видят капчу. Как можно обойти это узкое место? Использовать промежуточный шаг!
Если быстрый анализ вынес вердикт о подозрительности запроса, то мы можем перенаправить его на страницу с капчей. Но саму капчу пока что не показывать. Потому что в этот момент у нас появляется время на второй, более глубокий и сложный анализ. Мы можем потратить намного больше, чем одна миллисекунда, а значит, спасти существенное количество наших пользователей от необходимости преодолевать пусть и не страшную, но всё же капчу.
Теперь это работает так. Если человеку не повезло попасть на страницу с капчей, то вместо капчи он видит предложение поставить галочку и подтвердить, что он не робот.
![](https://habrastorage.org/getpro/habr/upload_files/b3c/bc8/a26/b3cbc8a263d2270a33f21161634fa186.jpg)
Пока пользователь ставит галочку, мы проводим дополнительный анализ с использованием более сложной ML-модели. Если всё хорошо, то возвращаем на сервис. Если «подозрительность» сохраняется, то показываем текстовую капчу.
И ещё кое-что важное. Переход от бинарных вердиктов (бот — не бот) на первом этапе к вероятностным («робот на N%») на втором позволяет нам управлять сложностью капчи! Если на втором этапе мы по-прежнему считаем запрос подозрительным, но степень уверенности в этом не такая высокая, то показываем простейшую капчу. А вот если мы уверены, что перед нами робот, то можем сложность и приподнять. Простое, но эффективное решение.
Несколько слов о значимости этого решения для людей. Выше мы радовались тому, что 85% (а не 35%, как было раньше) пользователей справляются с новой текстовой капчей с первой попытки. Но с галочкой «Я не робот» ситуация изменилась радикально: теперь более половины пользователей возвращаются в сервис вообще без необходимости разгадывать капчу! Вот такая вот капча без капчи.
За последний год мы прошли длинный путь, но идей на будущее от этого меньше не стало. Мы уже работаем над тем, чтобы получать более точные вердикты в реальном времени и без перенаправления на промежуточные страницы. И уже есть первые успехи. Один частный пример: теперь в Safari в режиме Инкогнито встретиться даже с галочкой «Я не робот» вероятность примерно в десять раз ниже, чем раньше. Кроме того, хотим пробовать новые, более добрые форматы капчи для тех случаев, когда без неё никак.
Формы капчи могут быть разные, но главное в том, чтобы относиться к людям по-человечески и уважать их время.