Почему водяные знаки в тексте — сложная задача
Закон ЕС об искусственном интеллекте (AI Act) вступит в силу в августе 2026 года — уже через месяц. Одно из ключевых требований, Статья 50, обязывает все результаты работы ИИ быть «обнаружимыми как искусственно сгенерированные». Иными словами, если провайдеры LLM хотят вести бизнес в ЕС, им придётся наносить на свои результаты водяной знак: скрытую подпись, по которой можно опознать контент, созданный ИИ.
Водяные знаки в тексте LLM — интересная инженерная задача. Как и многие лучшие инженерные проблемы, она теоретически неразрешима идеально, но допускает частичные решения: например, SynthID от Google и, как будет показано далее, тихие юникод-трюки от OpenAI и Anthropic. Любопытно будет наблюдать, как лаборатории ИИ будут балансировать между этими компромиссами до конца года.
В конце прошлого года уже поднимался вопрос об обнаружении ИИ-текста в материале AI detection tools cannot prove that text is AI-generated. Изображение легко пометить водяным знаком, потому что цифровые картинки содержат много «шума», незаметного человеческому глазу. Например, можно задать правило вида «эти двадцать пикселей в этих точных местах всегда будут одного цвета». С текстом всё гораздо сложнее. В отличие от изображений, текст — очень сжатая среда: нельзя внести в предложение изменение, которое человек не заметит (за одним исключением, о котором речь пойдёт дальше). Так как же его пометить?
По сути, это задача текстовой стеганографии (сокрытия секретного кода), усложнённая тем, что открытый текст нельзя произвольно менять. Любое изменение, вносимое ради водяного знака, снижает качество результата. Например, правило «каждая пятая буква — «е»» стало бы неплохим водяным знаком, но при наивной реализации превратило бы вывод модели в набор опечаток. Можно ли просто позволить модели самой подстроиться под такое ограничение? Мощные модели ИИ достаточно умны, чтобы жонглировать подобными ограничениями, но это тратило бы время на рассуждения, которое лучше потратить на решение задачи пользователя, и заставляло бы модель выглядеть куда менее способной, чем она есть на самом деле.
Нужны ли водяные знаки для обнаружения контента ИИ?
Действительно ли нужен водяной знак? Допустим, речь об Anthropic, которой нужно уметь проверять, сгенерировала ли её модель конкретный блок текста. Разве нельзя просто прогнать текст через каждую модель, замеряя по ходу, насколько предсказанные моделью токены совпадают с токенами исходного текста?
Не совсем. Пространство «всех возможных ответов Claude Sonnet на вопрос» гораздо больше, чем пространство «всех возможных ответов с водяным знаком». Иными словами, будет слишком много ложных срабатываний на человеческом тексте, который читается как написанный ИИ. Человеку куда вероятнее случайно написать текст в стиле Claude, чем случайно воспроизвести водяной знак.
К тому же было бы непомерно дорого прогонять каждую модель Anthropic против фрагмента текста ради простановки водяного знака. AI Act со временем обяжет такие лаборатории, как Anthropic, предоставлять бесплатные сервисы простановки водяных знаков каждому гражданину ЕС (см. Commitment 2). Подход «прогнать модель» для этого не подойдёт.
Как работает SynthID
Насколько известно, единственный провайдер ИИ, официально заявивший о нанесении водяных знаков на текстовый вывод, — это Google, использующая инструмент SynthID. Вот как он устроен.
Когда LLM генерирует текст, она формирует последовательность токенов (слов или частей слов). На каждом шаге модель выдаёт не один токен, а полный список из, скажем, 100 000 токенов своего словаря, каждый с пометкой о вероятности того, что именно он станет следующим. Инструменты вроде ChatGPT или Claude Code выбирают следующий токен полу-случайно из наиболее вероятных вариантов. Этот процесс полу-случайной выборки можно повлиять таким образом, чтобы результат стал детектируемым.
Например, можно выбрать стратегию выборки вида «берём второй по вероятности токен, затем первый, затем второй, затем первый и так далее». Это по-прежнему даст качественный результат, но позволит перепроверить модель на сгенерированном тексте и убедиться, что закономерность сохраняется. Однако такая проверка обходилась бы очень дорого, а любая небольшая правка вывода ломала бы шаблон и, соответственно, отпечаток. Есть ли способ лучше?
Да. SynthID — это процесс присвоения каждому токену «оценки» на основе предыдущих токенов (например, сумма ID токена с ID трёх предыдущих токенов по модулю 5). Чтобы нанести водяной знак, модель применяет стратегию выборки вида «из пяти наиболее вероятных токенов выбираем тот, у которого наивысшая оценка SynthID». Затем водяной знак можно обнаружить, вычислив суммарную оценку SynthID для блока текста. Если она подозрительно высока, весьма вероятно, что текст сгенерирован ИИ.
По сути, это версия распространённого совета определять LLM по использованию длинного тире, только вместо списка ключевых слов используется тонкая математическая связь между словами, которую человек не способен распознать. Поскольку процесс присвоения оценки тривиален, обнаружение водяного знака обходится очень дёшево.
Юникод-водяные знаки через гомоглифы
У Google есть сложное математическое обоснование того, почему SynthID не делает модель глупее: предполагается, что оценка SynthID достаточно случайна, чтобы вести себя как обычный псевдослучайный сэмплер токенов, просто оставляющий на выходе обнаружимый отпечаток. Но это, конечно, выглядит подозрительно. Например, часто используют инференс с температурой, равной нулю, при которой всегда выбирается наиболее вероятный следующий токен модели. В этом случае оставить отпечаток вообще нельзя (или же придётся игнорировать предпочтение пользователя и всё равно выбирать второй или третий вариант).
Если менять вывод модели нельзя, можно ли всё же пометить контент отпечатком? В некотором смысле — да. Есть основания полагать, что OpenAI и Anthropic иногда применяют хитрые юникод-трюки. Например, можно пройтись по тексту и заменить обычные пробелы " " (юникод U+0020) на «трёхкегельный» пробел " " (юникод U+2004) или на идеографический CJK-пробел " " (юникод U+3000). Такие символы называются «гомоглифами», и подборку можно найти здесь.
Разумеется, в человеческом тексте гомоглифы тоже встречаются часто. Но закодировать именно шаблон гомоглифов (скажем, «каждый третий пробел становится трёхкегельным») — тривиально, а вероятность такого совпадения в «дикой природе» гораздо ниже. Как и водяной знак SynthID, водяной знак на основе гомоглифов обнаруживается очень дёшево. При этом он ещё и дешевле в применении, чем SynthID: его можно реализовать целиком на стороне клиента.
Это не теория заговора. Claude Code точно применял подобный приём для маркировки подозрительных запросов от пользователей из Китая, эксплуатируя гомоглифы символа «’» в фразе «Today’s date» (позднее от этого отказались). За последние несколько лет неоднократно случалось, что при копировании блоков текста из ChatGPT в VSCode редактор помечал часть или все пробелы как необычные юникод-символы. Используют ли OpenAI и Anthropic гомоглифы именно как водяной знак ИИ-генерации — точно не известно. Но то, что они используют гомоглифы вообще, — факт.
Текстовые водяные знаки удаляются тривиально
AI Act (точнее, связанный с ним Code of Practice) требует, чтобы водяной знак был «встроен в контент таким образом, чтобы его было трудно от него отделить». Однако текстовые водяные знаки удаляются элементарно.
Чтобы убрать юникод-водяной знак на гомоглифах, достаточно заменить все гомоглифы их «настоящими» эквивалентами символов. Если есть доступ хотя бы к относительно слабой LLM без водяного знака, можно снять маркировку SynthID, попросив эту модель перефразировать текст. Поскольку водяной знак заложен в тонком выборе лексики, переформулировка содержимого убирает его. Это можно сделать даже вручную, хотя в таком случае контент уже трудно назвать сгенерированным ИИ. А поскольку рано или поздно появится какой-нибудь бесплатный публичный инструмент проверки водяных знаков, можно просто подгонять текст до тех пор, пока проверка не покажет отрицательный результат.
Более того, AI Act требует, чтобы техники нанесения водяных знаков были «интероперабельны... насколько это технически осуществимо». Это означает, что провайдерам ИИ придётся публиковать свой процесс простановки водяных знаков и, возможно, даже стремиться к стандартизации на одном и том же типе водяных знаков. Сложно представить, как это совместимо с принципом «безопасность через неясность», на котором держится вся идея текстовых водяных знаков LLM. В отличие от водяных знаков для изображений и видео, текстовые всегда будет тривиально удалить.
А как же C2PA?
В AI Act и Code of Practice много говорится о «цифровой подписи метаданных». Идея в том, чтобы включать раскрытие информации об ИИ прямо в метаданные файла, желательно так, чтобы их нельзя было подделать (например, подписав хэш содержимого файла). Этот процесс подписанных метаданных по сути и есть C2PA Content Credentials. Метаданные C2PA можно удалить, но (теоретически) нельзя подделать, поэтому файлу с меткой «создано человеком» можно доверять, а файлы вовсе без метаданных можно считать подозрительными.
Тема C2PA заслуживает отдельного разбора, но важно отметить главное: C2PA не заменяет текстовые водяные знаки. Он применим только к файлам. Как формулирует Code of Practice, речь идёт о «формате данных, поддерживающем прикрепление метаданных (например, аудио, изображение, видео или контейнеризованный текст)». Вывод чат-инструментов (и большая часть вывода ИИ-агентов) — это не контейнеризованный текст, а обычный простой текст, который нельзя подписать. Как вообще выглядела бы подпись вывода ChatGPT? Здесь просто нет артефакта, который можно передать.
Любопытный вопрос — должен ли Claude Code ставить C2PA-подпись на HTML-файлы или PDF, которые генерирует по запросу пользователя. Реализовать это правильно кажется довольно непростой задачей. Но в любом случае AI Act требует и полноценной простановки водяных знаков как таковой.
Заключение
Что же произойдёт в этом году? Наиболее вероятный сценарий: каждый провайдер ИИ (не только такие лаборатории, как OpenAI или Anthropic, но и сторонние провайдеры вроде Fireworks или Groq) встроит сэмплер токенов SynthID перед своим инференс-стеком. Это может касаться только пользователей из ЕС, а может и не ограничиваться ими, поскольку SynthID как минимум не хуже обычного top-k сэмплинга токенов.
Затем провайдеры ИИ предложат страницу «проверить на водяной знак», которая перетокенизирует текст пользователя, вычисляет оценку и проверяет, превышает ли она определённый порог. В зависимости от того, насколько серьёзно будет восприниматься требование интероперабельности, провайдеры могут даже стандартизировать общую настройку SynthID — тогда появится единая размещённая в ЕС страница «поставить водяной знак на этот текст».
Маловероятно, что юникод-водяные знаки будут признаны соответствующими требованиям AI Act, но некоторые провайдеры, не желающие настраивать SynthID, вполне могут пойти на такой шаг. В любом случае технически подкованные пользователи смогут снимать водяные знаки по желанию, а для менее технически подкованных появится масса готовых инструментов для этой же цели.
Заметка: пост вызвал обсуждение на Hacker News. Комментаторы в основном спорят о пользе водяных знаков и регулировании ИИ в целом. Один из комментаторов заметил, что криптографически подписать текст несложно. С этим можно согласиться, но сложность в другом — в хранении всех подписей (несмотря на опасения некоторых, компании, занимающиеся ИИ, не хранят и не могут хранить все промпты своих клиентов). Другие комментаторы жалуются, что удаление водяных знаков — преступление. Это не выглядит верным ни с юридической, ни с моральной точки зрения. По сути, это всё равно что заклеить стикером логотип на собственной вещи.