Назад к блогу

Deckard: локальный детектор ИИ-текста в браузере

Deckard: локальный детектор ИИ-текста в браузере

Расширение для Chrome, которое определяет ИИ-текст прямо на открытых страницах, не отправляя данные на сторонние серверы. Все вычисления идут локально на ноутбуке, что делает инструмент бесплатной альтернативой облачным детекторам — ценой повышенного расхода памяти и меньшей точности.

Расширение для Chrome под названием Deckard обнаруживает текст, сгенерированный ИИ, прямо на посещаемых страницах. Оно названо в честь охотника за ИИ из «Бегущего по лезвию» и работает полностью локально: модель скачивается и запускается на ноутбуке, без обращения к внешним сервисам.

Автор — sgoedecke, репозиторий github.com/sgoedecke/deckard. В посте на seangoedecke.com он пишет, что собрал Deckard вместе с Astra. По его словам, автоматическое обнаружение ИИ-текста — «underserved niche», где единственный серьёзный игрок — Pangram; Deckard задуман как локальная и бесплатная альтернатива, хотя и менее надёжная.

Что именно изменилось

Установка выполняется одной командой, которая скачивает и сразу исполняет скрипт установки из релиза v0.6.4:

curl --proto '=https' --tlsv1.2 -fsSL https://github.com/sgoedecke/deckard/releases/download/v0.6.4/install.sh | bash

Флаги --proto '=https' и --tlsv1.2 разрешают только HTTPS и TLS версии 1.2, -fsSL включает тихий режим с выводом ошибок и следованием редиректам, а | bash передаёт скачанный скрипт на исполнение оболочке.

После установки расширение загружается в Chrome вручную: нужно открыть chrome://extensions, включить Developer mode, выбрать Load unpacked и указать папку ~/Deckard/extension. Затем Deckard стоит закрепить, чтобы он был виден на панели расширений.

Установщик по умолчанию использует ~/Deckard, а флаг --home DIR задаёт другое расположение. Старые установщики использовали ~/Library/Application Support/Deckard; чтобы перенести существующую установку, сначала запускают "$HOME/Library/Application Support/Deckard/current/bin/deckard" uninstall, удаляют старое расширение в Chrome, затем ставят новым установщиком и загружают ~/Deckard/extension. Папку нельзя перемещать вручную: регистрация native-host и PATH ссылаются на её установленное расположение. Сейчас это работает только на Apple Silicon Mac; для PC и других устройств приветствуются PR.

Как Deckard сканирует страницы

Текст разбивается на блоки обходом DOM через TreeWalker. Границы блока задают элементы, которые в разметке страницы образуют отдельные смысловые фрагменты — абзацы, заголовки, ячейки, — поэтому текст внутри одного такого элемента проверяется вместе, а при переходе к следующему накопленный фрагмент закрывается и начинается новый.

Слова внутри фрагмента нарезаются на куски примерно по 300 слов, но не более 20 000 символов. Фрагмент отправляется на проверку только после накопления минимум 50 слов.

Короткий ИИ-текст детектируется хуже именно из-за этого порога: Deckard сканирует кусками по 50 слов, и такой текст склеивается с окружающим текстом страницы.

Порог срабатывания

Порог по умолчанию задан константой FLAG_THRESHOLD = 0.97 — чуть выше 98% уверенности модели. Настраивается он ползунком в расширении: выставленное пользователем значение сохраняется в настройках расширения, и если оно попадает в допустимый диапазон от 0.70 до 0.99, применяется именно оно, иначе используется значение по умолчанию.

Автор прямо предупреждает: «Please don't use this as proof of AI usage; if you want to do that, paste it in to Pangram». То есть срабатывание Deckard не является доказательством AI-генерации — для этого текст нужно проверять в Pangram.

Потребление памяти

Активная модель занимает примерно 400 МБ–1,2 ГБ памяти, что автор сравнивает с пятью-шестью дополнительными открытыми вкладками Chrome. Если модель не используется пять минут, она выключается сама. В README указано, что Deckard скачивает и запускает модель Gradient на ноутбуке и это потребляет несколько сотен МБ памяти во время просмотра.

Как расширение связано с моделью

native messaging host регистрируется через манифест — конфигурационный файл, который описывает это приложение и лежит отдельно от самого исполняемого файла хоста. Манифест должен быть валидным JSON и содержать поля name, description, path, type и allowed_origins.

Поле name — имя хоста, которое клиенты передают при подключении к нативному приложению; допускаются только строчные буквенно-цифровые символы, подчёркивания и точки, имя не может начинаться или заканчиваться точкой, и точка не может идти сразу за точкой. Поле description — краткое описание приложения. Поле path — путь к исполняемому файлу хоста: на Linux и macOS он должен быть абсолютным, на Windows может быть относительным к каталогу манифеста, а процесс хоста запускается с текущим каталогом, равным каталогу с бинарником. Поле type задаёт тип интерфейса связи и имеет единственное возможное значение stdio, означающее, что Chrome использует stdin и stdout для обмена с хостом.

Поле allowed_origins задаёт список расширений, которым разрешён доступ к этому хосту. Оно ограничивает, какие расширения могут подключаться к нативному приложению, и его значения не могут содержать подстановочные знаки. В примере манифеста поле содержит конкретный идентификатор расширения: "allowed_origins": ["chrome-extension://knldjmfmopnpolahpmmgbagdohdnhkik/"]. Когда в этом ключе указано несколько расширений, нативный хост получает первым аргументом origin вызывающего, обычно chrome-extension://[ID of allowed extension], что позволяет хосту определить источник сообщения.

На Windows установщик приложения должен создать ключ реестра либо HKEY_LOCAL_MACHINE\SOFTWARE\Google\Chrome\NativeMessagingHosts\com.my_company.my_application, либо HKEY_CURRENT_USER\SOFTWARE\Google\Chrome\NativeMessagingHosts\com.my_company.my_application, и записать в значение по умолчанию этого ключа полный путь к файлу манифеста. Это делается командой REG ADD с флагом /ve (значение по умолчанию), типом REG_SZ и данными — путём к манифесту. Эквивалентная запись в .reg-файле использует символ @ для значения по умолчанию того же ключа. При поиске хостов Chrome сначала обращается к 32-битному реестру, затем к 64-битному.

Два способа обмена сообщениями

При постоянном подключении к нативному приложению создаётся порт обмена сообщениями, и Chrome запускает процесс хоста и держит его работающим, пока порт не будет уничтожен. При разовой отправке сообщения без создания порта Chrome запускает новый процесс хоста для каждого сообщения; первое сообщение, сгенерированное процессом хоста, обрабатывается как ответ на исходный запрос и передаётся в callback ответа, а все остальные сообщения хоста игнорируются. Оба способа требуют объявления разрешения "nativeMessaging" в манифесте расширения. Эти способы недоступны внутри content scripts — только в страницах расширения и service worker.

Ограничения протокола

Сообщения кодируются одинаково в обоих направлениях: каждое сериализуется с помощью JSON, кодируется в UTF-8 и предваряется 32-битной длиной сообщения в собственном порядке байтов. Максимальный размер одного сообщения от хоста составляет 1 MB — в первую очередь для защиты Chrome от неправильно работающих приложений. Максимальный размер сообщения, отправляемого хосту, — 64 MiB. Длина сообщения не должна превышать 1024*1024, а размер сообщения должен быть равен числу байтов в сообщении, что может отличаться от «длины» строки, поскольку символы могут быть представлены несколькими байтами. На Windows режим ввода-вывода программы должен быть установлен в O_BINARY: по умолчанию O_TEXT портит формат сообщения, заменяя переводы строк (\n = 0A) на окончания строк в стиле Windows (\r\n = 0D 0A).

Отладка native messaging

При сбоях диагностика пишется в лог ошибок Chrome. На Linux и macOS Chrome запускают с флагами --enable-logging=stderr --log-level=1, а вывод фильтруют через grep по строкам native_messag и launch_context. На Windows Chrome запускают как chrome.exe --enable-logging --log-level=1. Также можно открыть chrome_debug.log в текстовом редакторе и искать launch_context.cc или native_message_process_host.cc.

Сбои поиска и разбора манифеста в launch_context.cc логируются как предупреждения, поэтому нужен --log-level=1, а не 2 (ERROR), который подавляет эти стартовые диагностики. Строку launch_context ищут для ошибок манифеста и запуска бинарника, а native_messag — для ошибок размера полезной нагрузки и связи через pipe.

Что было до этого

Модель, которую запускает Deckard, называется Gradient MLX 4-bit. MLX — это среда исполнения модели. «4-bit» в названии относится к четырёхбитной аффинной квантизации весов: при квантизации веса разбиваются на группы, и внутри каждой группы диапазон значений аппроксимируется линейно. Формат упакованного чекпоинта обозначается как "gradient-mlx-affine-q4-group64-v1".

При такой квантизации для каждого веса создаются три тензора — сами веса, scales и biases, которые затем используются при де-квантизации и в квантованном матричном умножении. В упакованном чекпоинте эти три части хранятся под именами entry.target, module + ".scales" и module + ".biases".

Что это меняет на практике

Единственные числовые показатели Pangram: доля ИИ-текста в соцсетях — в среднем 25% постов объёмом свыше 250 слов полностью сгенерированы нейросетями, а заявленный уровень ложных срабатываний — 0,01% false positive rate.

Для самого Deckard известны два числа: порог детекции по умолчанию чуть выше 98% и сканирование блоками по 50 слов. Из этого следует, что инструмент рассчитан на низкий уровень ложных срабатываний в ущерб чувствительности на коротких фрагментах.

Источники

Похожее