DeepSeek · Разработка

DeepSeek V3 для регулярных выражений

Регулярное выражение — это код, который почти невозможно прочитать глазами, зато очень легко проверить примерами. DeepSeek V3 стоит 2 токена за запрос, самая дешёвая модель подписки, и это меняет способ работы: паттерн не пишется с первого раза, а доводится за пять-десять итераций по контрпримерам. Дальше — как построить такой цикл и на чём регулярки ломаются в проде.

Почему DeepSeek V3 подходит для этой задачи

Цена определяет метод. При 2 токенах за запрос месячный тариф за 999 рублей даёт около 6000 обращений, а суточный доступ за 1 рубль — примерно 150. Это значит, что можно не выпрашивать идеальный паттерн одним запросом: отправили набор примеров, получили выражение, прогнали на своих данных, вернули строку, которая совпала зря, получили исправление. Пять кругов такого цикла стоят 10 токенов и дают результат, которого одним запросом не добиться ни у какой модели.

Регулярки — область с жёстким правильным ответом, и это редкая для языковых моделей ситуация: результат проверяется механически, за секунды, на ваших же данных. Ошибка модели здесь не опасна, потому что обнаруживается сразу — в отличие от текста, где неточность живёт до читателя. Поэтому недорогая модель на этой задаче ведёт себя достойно: её работу целиком верифицирует ваш тестовый набор.

Основная сложность не в синтаксисе, а в диалектах. PCRE, движок JavaScript, модуль re в Python, RE2 в Go, POSIX в grep и sed, встроенные регулярки MySQL — набор возможностей у них разный. Ретроспективная проверка работает не везде, именованные группы объявляются по-разному, RE2 сознательно не поддерживает обратные ссылки. Модель учитывает это, если диалект назван в запросе, и уверенно выдаёт нерабочий паттерн, если не назван.

Какие входные данные подготовить

Пять-десять строк, которые обязаны совпасть, — прямо из ваших настоящих данных, со всей грязью: пробелами, переносами, кириллицей, пустыми полями.

Столько же строк, которые совпасть не должны, особенно похожих на нужные. Без них паттерн получится шире задачи, и это выяснится на бою.

Диалект и место исполнения: JavaScript в браузере, Python, grep в скрипте, RE2 в Go, поиск в редакторе, колонка в базе. От этого зависит сама возможность написать паттерн.

Что делаете с совпадением: проверяете строку целиком, извлекаете группы, заменяете. Валидация и извлечение дают разные выражения при одном описании задачи.

Ограничения окружения: длина входной строки, поток данных или разовый разбор, можно ли позволить себе паттерн, который на плохом входе работает секунду.

Пошаговый процесс

Сначала соберите тестовый набор

Два списка — «должно совпасть» и «не должно» — это и есть техническое задание. Составлять их надо до запроса и из настоящих данных, а не из головы: реальные строки всегда содержат то, чего вы не ожидали. Хороший признак готовности набора: в списке отказов есть строки, отличающиеся от нужных одним символом.

Назовите диалект в первой строке

Не «регулярка», а «регулярное выражение для Python, модуль re» или «для grep -E в bash». Разница практическая: ретроспективная проверка есть в PCRE и в современном JavaScript, но её нет в RE2 — паттерн из интернета там просто не скомпилируется. Место исполнения тоже важно: у поиска в редакторе и у той же задачи в коде разные способы экранирования.

Требуйте разбор по частям, а не готовую строку

Просите вернуть выражение и отдельно расшифровку каждого блока: что делает эта группа, почему квантификатор ленивый, зачем здесь граница слова. Регулярку, которую вы не понимаете, невозможно поправить через месяц — придётся выбрасывать и писать заново. Расшифровка занимает те же 2 токена и остаётся в комментарии рядом с кодом.

Прогоняйте на реальных данных и возвращайте контрпримеры

Проверка идёт не в голове и не в ответе модели, а на вашем файле. Каждую строку, которая совпала зря или не совпала напрасно, отправляйте обратно одной репликой: «вот эта строка совпадает, а не должна». Цикл сходится за несколько итераций, и это самый быстрый путь к паттерну, который переживёт продакшн.

Проверьте паттерн на устойчивость и сохраните с комментарием

Отдельным запросом спросите, есть ли в выражении вложенные квантификаторы и как оно поведёт себя на длинной строке без совпадения. Финальный вариант кладите в код с комментарием: задача, диалект, пара примеров. Через полгода это единственное, что позволит его безопасно изменить.

Пример готового промпта

Составь регулярное выражение.

Диалект: [PCRE / JavaScript / Python re / RE2 (Go) / POSIX ERE для grep -E]
Где исполняется: [В КОДЕ / В КОНСОЛИ / В РЕДАКТОРЕ / В ЗАПРОСЕ К БАЗЕ]
Что нужно: [ПРОВЕРИТЬ СТРОКУ ЦЕЛИКОМ / НАЙТИ ВСЕ ВХОЖДЕНИЯ / ИЗВЛЕЧЬ ГРУППЫ / ЗАМЕНИТЬ]

Должны совпасть:
[СТРОКА 1]
[СТРОКА 2]
[СТРОКА 3]

Не должны совпасть:
[СТРОКА 1]
[СТРОКА 2]
[СТРОКА 3]

Верни ответ в таком порядке:
1. Само выражение одной строкой, без обрамляющих символов языка.
2. Разбор по частям: каждый блок и что он делает.
3. Проверка: пройдись по каждой моей строке из обоих списков и скажи, совпадает она или нет и почему.
4. Пять дополнительных проверочных строк, которые способны сломать этот паттерн, — граничные случаи, о которых я не подумал.
5. Готовая вставка для моего языка с правильным экранированием.
6. Риски: есть ли вложенные квантификаторы и что будет на строке длиной 10 000 символов без совпадения.

Возможности, которых нет в указанном диалекте, не используй. Если задача регулярным выражением решается плохо — скажи об этом и предложи разбор кодом.

Пункт 4 — самый полезный. Модель придумывает граничные случаи охотнее, чем человек, который уже держит в голове удачную форму данных: пустая строка, перенос внутри поля, юникодный пробел, строка в 40 килобайт.

Как проверить результат

Паттерн прогнан на всём вашем реальном файле, а не на трёх примерах из запроса.

Отдельно проверены граничные строки: пустая, очень длинная, с переносом строки, с кириллицей и с юникодными пробелами.

Проверено поведение на строке, где совпадения нет: время выполнения не растёт скачком.

Выражение вставлено в код и запущено там — экранирование в языке-хосте часто отличается от исходной записи.

Типичные ошибки

Просить паттерн без списка отказов

Примеры «что должно совпасть» задают только нижнюю границу, и модель честно выдаёт выражение, которое их покрывает — заодно вместе с половиной файла. Классика: паттерн для номера договора начинает ловить любые числа в тексте, потому что в запросе не было ни одной строки, которую он обязан пропустить. Список отказов важнее списка совпадений, и составлять его надо из похожих строк.

Забыть про экранирование в языке-хосте

Выражение работает в онлайн-тестере и не работает в коде — почти всегда дело в обратных слэшах. В строковом литерале, в JSON-конфиге и в YAML слэш нужно удваивать, а в некоторых оболочках ещё и защищать от подстановки. Человек в этот момент правит сам паттерн, ломает его окончательно и уходит в отладку на час. Проверять надо ровно ту форму записи, которая лежит в файле.

Соглашаться на вложенные квантификаторы

Конструкции вида (a+)+ и (.*)* модель предлагает довольно охотно — они простые и внешне решают задачу. На входе, где совпадения нет, такой паттерн уходит в перебор, и время выполнения растёт лавинообразно: обработчик, съедающий процессор на одной подставленной строке, — известный способ уронить сервис. Проверять всегда, а на пользовательском вводе предпочитать разбор кодом.

Частые вопросы

Почему для регулярок берут самую дешёвую модель?

Потому что результат проверяется механически и мгновенно. Там, где ошибку видно сразу на своих данных, ценность дорогой модели невелика — важнее число итераций, а при 2 токенах за запрос их может быть сколько угодно. Дорогая модель оправдана в другом месте: когда надо решить, что регулярка тут вообще не подходит.

Модель учитывает разницу между диалектами?

Если диалект указан — да, и это заметно: для RE2 она не станет предлагать обратные ссылки, для POSIX не использует ретроспективную проверку. Если не указан, ответ будет в духе PCRE, потому что таких примеров больше всего, и в Go или в grep он не скомпилируется. Одна строка в запросе экономит вечер.

Можно ли проверить регулярку прямо в чате?

Модель может пройтись по вашим строкам и объяснить, почему каждая совпадает или нет, — это полезный разбор. Но это рассуждение, а не запуск движка: окончательная проверка делается на вашем файле в вашем окружении. Расхождения между разбором и реальным поведением случаются как раз на граничных случаях, ради которых всё и затевалось.

Что делать, если регулярка получается на три строки?

Обычно это сигнал сменить инструмент. Вложенные скобки, кавычки внутри кавычек, разметка — для них есть парсеры, а регулярное выражение будет ломаться на каждом новом формате данных. Спросите модель прямо: «решается ли эта задача регулярным выражением надёжно» — и попросите альтернативу кодом.

Сколько запросов даёт подписка?

DeepSeek V3 стоит 2 токена — это самая дешёвая модель в наборе. Месячный тариф за 999 рублей даёт 12 000 токенов, то есть около 6000 запросов; суточный доступ за 1 рубль — примерно 150, чего хватает на несколько полных циклов доводки. Баланс общий с ботом, так что править паттерн можно и с телефона.

Модель DeepSeek V3 доступна в FatherGPT: без VPN, картой РФ, единый баланс токенов на все нейросети. Переключайтесь между моделями в одном чате — под каждую задачу своя.