惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

Exploit-DB.com RSS Feed
Exploit-DB.com RSS Feed
A
About on SuperTechFans
IT之家
IT之家
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
Blog — PlanetScale
Blog — PlanetScale
aimingoo的专栏
aimingoo的专栏
云风的 BLOG
云风的 BLOG
The GitHub Blog
The GitHub Blog
Vercel News
Vercel News
G
Google Developers Blog
J
Java Code Geeks
宝玉的分享
宝玉的分享
T
Tailwind CSS Blog
Cloudbric
Cloudbric
L
LINUX DO - 最新话题
MyScale Blog
MyScale Blog
H
Heimdal Security Blog
PCI Perspectives
PCI Perspectives
Attack and Defense Labs
Attack and Defense Labs
S
Security @ Cisco Blogs
Latest news
Latest news
I
Intezer
L
Lohrmann on Cybersecurity
C
CXSECURITY Database RSS Feed - CXSecurity.com
月光博客
月光博客
T
Threatpost
博客园 - 【当耐特】
S
Schneier on Security
P
Privacy International News Feed
G
GRAHAM CLULEY
T
Tenable Blog
AWS News Blog
AWS News Blog
Threat Intelligence Blog | Flashpoint
Threat Intelligence Blog | Flashpoint
雷峰网
雷峰网
博客园 - Franky
Engineering at Meta
Engineering at Meta
美团技术团队
S
Secure Thoughts
T
Troy Hunt's Blog
Microsoft Security Blog
Microsoft Security Blog
SecWiki News
SecWiki News
V
Visual Studio Blog
人人都是产品经理
人人都是产品经理
Application and Cybersecurity Blog
Application and Cybersecurity Blog
Cisco Talos Blog
Cisco Talos Blog
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
Martin Fowler
Martin Fowler
Webroot Blog
Webroot Blog
Google DeepMind News
Google DeepMind News
H
Hackread – Cybersecurity News, Data Breaches, AI and More

Все публикации подряд на Хабре

Ловим музу за клавиатуру: как айтишнику стать автором Что умеет Midjourney в 2026? Мой немного грустный разбор этого шикарного инструмента Никто не любит писать тесты, но ИИ может исправить это IPv8 выглядит как мечта. Поэтому почти наверняка не взлетит Производители вернули в продажу материнки с DDR3. Что происходит? Управление агентом с телефона через Telegram теперь в KodaCode От координации к лидерству: как меняется роль руководителя разработки Я сделала родителям бизнес вместо пенсии: зарабатываем 70 тысяч, мама не даёт продать В три раза быстрее приемка товара и оптимизация трудозатрат на 73%: как «РСТ-Инвент» помог Gulliver Group ИИ-шечный мир победил? О влиянии искусственного интеллекта на игропром Кремль снижает давление на Телеграмм пока Европа строит интернет по паспорту Как CEO, CTO и CIO за 8 часов собрали ИИ-директора, который умеет держать позицию под давлением Как (не) потерять домен за выходные Вместо 8 разных VPS: как я организовал практику студентам на одном сервере Почему твой Open Source проект не замечают? R&D: искусство управления неопределенностью в разработке AI-дефляция: вакансий для разработчиков больше, а рост зарплат — худший за 15 лет Мы отдали управление роботами OpenClaw. Что из этого вышло Галактический ID: система идентификации для всех форм разумной жизни Шесть основ бизнес-анализа: начинаем с вопроса «Кто в игре?» Код-ревью, в котором дело не в коде Данные переехали. Команда — нет Системной подход к сдаче OSWE в 2025 Почему комната управления реактором покрашена в цвет морской пены 4 YAML-файла вместо PySpark: как аналитикам строить пайплайны без разработчиков LLM-агент для поиска свободных доменов: автоматизируем подбор Когда, зачем и как правильно начинать новую сессию в Claude Code? Как я заставил нейросеть писать макросы для FreeCAD Анатомия ИИ‑агента для подбора персонала. От тысячи резюме к топ‑10 за минуты Опыт разработчика как экономика внимания Автономность как точка невозврата: кто будет субъектом в цифровом будущем Обучение ИИ в «диких» условиях: как рутинные действия превращаются в датасеты Как измерить LLM для задач кибербеза: обзор открытых бенчмарков Где хранить код? Сравнение GitHub, GitLab и Bitbucket Математика объясняет, почему нормальное распределение встречается повсюду Почему ваш FinOps не работает: 12 тезисов от практиков Как подписать проектную документацию УКЭП с использованием бесплатных лицензий Pilot Адаптивное администрирование Sigla Vision Я грузил уран в бочки, а потом 20 лет строил ИТ в атомной отрасли Чем позвонить с Эвереста? История и обзор спутниковой связи. Часть 2 Как языковая модель помогает контролировать качество инструктажей по охране труда в металлургии Как не передать на desktop свой IP в РКН Анатомия SAP Privileges: как устроено управление правами в macOS MoneyDev: Сказка про три главных слова Обновлённый токенизатор видео K-VAE 2.0 от Сбера Как сделать диспетчеризацию дома на 1284 квартиры почти бесплатно Как мы разогнали железную дорогу Мы дали агентам рутину. Теперь надо решить — что делать с освободившимся временем Токсичный контент, промпт-хакинг и защита ИИ — всё о Guardrails для LLM Умный город начинается с точного взгляда: как «Фалькон Тех» меняет пространство к лучшему Навайбкодил приложение для анализа графов Почему Дюну так интересно читать? Упрощаем работу с рутиной или как стать Гендальфом Белым Деконструкция Go: CPU, RAM и что там происходит. Go Assembler база. Часть 1.1 Какие профессии исчезнут из-за ИИ, а какие появятся? И что с этим делать Как мы построили IT-отдел, где хочется расти: архитектурные встречи, прозрачные метрики и книжные подарки Rufler: Делаем из Claude Code автономный рой через один YAML-конфиг Sing-box и белый список приложений Как построить надёжный обмен сообщениями в микросервисах: лучшие практики для enterprise OpenAI строит MLM-пирамиду, а McKinsey и Accenture помогают ей в этом Дом, который не построил Фишер (Часть 2) «Сверхзвуковой математик» против «Вдумчивого логиста»: битва алгоритмов 3D-упаковки Мультимодальные модели – грубый и дорогой инструмент Разговоры ничего не стоят. Код тоже Проверки физических лиц: с кого начнет ФНС Топ-10 бесплатных нейросетей для создания видео в 2026 году Первые слои кода: как наши решения сегодня определяют архитектуру ИИ на десятилетия Разработка нового статического анализатора: PVS-Studio JavaScript Поиск уязвимостей ПО: базовый минимум или роскошный максимум Почему оценка персонала не работает как инструмент управления Как мы разработали ИИ-ассистента и сократили рутину продуктовой команды на 50% Как я ушел из найма, нажарил косточек и продал на маркетплейсах на 168 млн в год Когда 1С:ERP уже внедрена, а нормального производственного плана всё ещё нет Как я сделал Claude мультимодальным, подключив к нему Qwen Omni Как приглашение на вакансию мечты превращается в атаку Infrastructure as Code: философия и лучшие практики IaC Тестируем Yandex Code Assistant на задаче, в которой нужно хранить секреты nxs-universal-chart v3.0: новое поколение универсального Helm-чарта Callback Injection: Техника, которая отправила Microsoft Defender в глухой нокаут «Все идеи на стол»: митап как способ вывести проект из тупика Сегодня я узнал нечто новое о GPU благодаря багу в своей игре Как заставить LLM ̶ ̶г̶а̶л̶л̶ю̶ ̶ эволюционировать Карта событий как фундамент аналитики: практический кейс для E-commerce Что выбрать для AI: x86, ARM или RISC-V? Дайджест железа за март Роль соматических мутаций в развитии аутоиммунных заболеваний: путь к избирательной терапии Mythos от Anthropic — тревожный сигнал для всех, а не только для банков Guardrails для LLM на Java: как приручить промпт‑инъекции и токсичные ответы Green-VLA: как мы собрали VLA-модель для реального антропоморфного робота и не потеряли обобщение Финансовая гонка вооружений: почему умные люди добровольно в ней участвуют Эра ИИ-агентов наступила: выбираем лучшего цифрового сотрудника # Практический опыт внедрения WinCC Redundancy на производственном предприятии Сделал MVP за 3 дня, а потом неделю прикручивал оплату. Оно того стоило? Физика против Маска: почему Starship V3 может оказаться ещё одной катастрофой Нефть Венесуэлы: крупнейшие запасы в мире, но не крупнейшая нефтяная держава JPA 4. Переосмысление Hibernate Почему зеркальная фотокамера Nikon D5 десятилетней давности идеально подошла для миссии «Артемида-2» Проект «Уровень-Спутник» или как мы сделали платформу для гидрологов «Замедлиться, чтобы ускориться»: почему ИИ повышает цену ошибок в требованиях и архитектуре Как с нуля поднять трафик IT-компании на 1657% при бюджете 55 тыс. и выжить Pixel-perfect Downsampling — идеальная отрисовка 50 миллионов точек без потерь
Как мы встроили LLM в Data Quality и не потеряли контроль
just_ai (Jus · 2026-04-22 · via Все публикации подряд на Хабре

Уровень сложностиСредний

Время на прочтение12 мин

Охват и читатели22

Кейс

Привет, Хабр! Меня зовут Макунина Арина, я аналитик и инженер данных в Just AI. Наша команда аналитики обожает, чтобы рутина в данных была максимально предсказуемой. Если что-то ломается, то должно быть понятно что, где, почему и что делать дальше. Когда мы поработали с Data Quality в продакшене, выяснилось, что правила качества сами по себе есть базовый минимум, но время утекает в две черные дыры.

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

Вторая — это проблема интерпретации инцидента. Проверки у нас уже есть, как вдруг внезапно одна падает, прилетает алерт и начинается расследование, которое почти всегда одинаковое: это массовая проблема или одноразовый выброс? Сломался источник данных или что-то прошло не так в процессе трансформации? Проблема появилась сегодня или деградировало всю рабочую неделю? Кто вообще владелец этих данных? Расследование первопричины проблемы каждый раз съедает достаточно много времени.

На фоне того, как индустрия двигается к тенденции фиксации ожиданий (data contracts) и видения поведения данных во времени (data observability), возникает естественный вопрос: можно ли использовать LLM там, где команда тратит часы на повторяющиеся задачи качества данных? 

Мы попробовали пойти в эту сторону, но с важной оговоркой: LLM у нас не умный аналитик с доступом ко всему, а строго ограниченный помощник. Он не ходит в продовую базу, не принимает решений и не меняет пайплайны. Его задача — генерировать проверяемые артефакты, а именно стартовые DQ-правила для новых структур, и объяснять уже случившиеся инциденты.

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

Архитектура решения

Концептуально архитектура состоит из трех логических уровней, каждый из которых решает свою задачу.

Первый уровень — платформа данных. Это существующая инфраструктура, где живут сами данные и связанные с ними метаданные: DDL-схемы, история запусков проверок, агрегаты профилирования и примеры данных. Именно отсюда формируется контекст, который используется для генерации правил качества и анализа инцидентов.

Второй уровень — прикладной слой качества данных. Здесь находятся сервисы, которые понимают предметную область качества данных: генерация правил, интерпретация инцидентов, работа с результатами проверок и хранение артефактов. Именно они формируют структурированный контекст, который может быть передан модели.

Третий уровень — платформенный слой LLM. Это единый шлюз для работы с моделями и AI-сервисами. В нашем случае эту роль выполняет Caila. Платформа отвечает за управление моделями, маршрутизацию запросов, аудит вызовов, контроль доступа и защиту данных.

Однако даже при такой архитектуре напрямую соединять прикладной слой и LLM было бы рискованно. Поэтому между уровнями мы ввели набор правил взаимодействия, которые определяют, какой контекст может видеть LLM, какие результаты она может генерировать и в каком формате эти результаты должны возвращаться.

Правила использования LLM при работе с данными

Правило первое: не упоминать о LLM не имеет прямого доступа к продовой базе. Никаких просьб выполнить запрос из модели. Модель видит только заранее подготовленный контекст, а именно DDL/метаданные, агрегаты/профили, примеры данных (но уже замаскированные), историю запусков. Это снижает класс рисков: от утечек до случайных нежелательных рекомендаций. 

Правило второе: не упоминать нигде о LLM пишет артефакты, а не выносит приговор. Артефакты в данном случае это правила в нашей библиотеке проверки качества данных или проверки, которые потом детерминировано исполняются человеком и дают измеримый результат. Это паттерн «tests as code», где тест возвращает строки‑нарушители, а если строк нет, то тест прошел. 

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

Архитектура получилась намеренно скучной, и в этом ее плюс. Мы сознательно жертвуем магией, чтобы сохранить контроль, воспроизводимость и проверяемость. LLM не знает бизнес-правил вашей системы. Она не понимает, что какой-то идентификатор может дублироваться до пяти раз просто потому, что так устроен процесс. Значит, ее нужно ставить в рамки.

Как выглядят правила качества у нас

У нас проверки данных работают по одному и тому же шаблону:

  1. Выбираем данные;

  2. Применяем правило;

  3. Собираем нарушения;

  4. Возвращаем результат в едином формате.

Нам было важно не просто писать отдельные проверки под каждую таблицу, а иметь единый, воспроизводимый и расширяемый механизм. Поэтому мы приняли решение сделать собственную Python-библиотеку для проверок качества данных. В ней мы зафиксировали свой формат описания правил, свой формат результата и единый способ исполнения проверок.

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

Контур AI‑помощника

Часть первая: генерация стартовых проверок для новой таблицы

Когда появляется новая таблица, мы делаем три вещи и все они обычно доступны даже без глубокого знания домена. Вытаскиваем DDL/метаданные, что дает LLM понимание структуры данных, делаем профиль данных и агрегаты, что существенно улучшает качество предложений, а также даем LLM наш словарь проверок, т.е. перечень доступных типов правил и их параметры. С этим джентльменским набором уверенно просим LLM сгенерировать комплект стартовых правил для конкретной таблицы. Чтобы это работало стабильно и даже автоматизировано, мы используем жесткий формат вывода.

Пример промпта:

Роль: ведущий инженер по качеству данных.

Задача:
На основе структуры таблицы, профиля колонок и словаря доступных правил
сгенерируй стартовый набор проверок качества данных.

Работай по правилам:
1. Используй только типы проверок из переданного словаря.
2. Не придумывай новые колонки, поля и бизнес-ограничения.
3. Если для правила не хватает доменной информации, не угадывай — пометь его как needs_domain_info.
4. Для каждого правила укажи, на каких фактах оно основано:
   - имя колонки
   - тип данных
   - null_ratio
   - distinct_ratio
   - top_values
   - min/max
   - примеры значений
5. Предлагай только те правила, которые выглядят разумными как стартовый baseline.
6. Не предлагай взаимоисключающие или явно избыточные проверки.

Формат ответа:
Верни только JSON-массив объектов следующего вида:
{
  "column": "string",
  "rule_type": "string",
  "params": {},
  "status": "auto_ok | needs_review | needs_domain_info",
  "reason": "string",
  "evidence": ["string"],
  "questions_for_owner": ["string"]
}

Критерии качества ответа:
- JSON должен быть валидным.
- Все rule_type должны быть из разрешенного списка.
- Если уверенность низкая, это должно быть явно отражено в status и questions_for_owner.
- Не добавляй текст вне JSON.

Контекст:
[DDL и метаданные таблицы]
[Профиль данных]
[Словарь доступных правил и их параметров]

Смысл “needs_domain_info” простой. Мы не пытаемся заставить LLM угадывать бизнес-семантику, например, что NULL в date_closed допустим, потому что заявка в процессе. Она дает разумный дефолт и список вопросов, которые реально нужно задать владельцу. 

Часть вторая: интерпретация инцидента

Когда правило нарушено, мы пытаемся превратить уведомление об ошибке в actionable alert. Мы собираем контекст ровно из тех фактов, которые у нас уже есть:

  • что за правило;

  • результаты выполнения;

  • примеры проблемных строк;

  • запросы для быстрого просмотра проблемных записей;

  • история изменений.

LLM таким образом объясняет проблему человеческим языком, оценивает масштаб, формирует гипотезы с пометкой уверенности, предлагает конкретный чек‑лист следующих шагов.

Удобно воспользоваться сгенерированным запросом под конкретную таблицу и вывести все проблемные записи. Результаты проверок храним так, чтобы можно было построить тренды, взглянуть на пару примеров проблемных строк, сопоставить падение с последними изменениями и владельцами.

Промпт‑шаблон:

Роль: ведущий инженер по качеству данных.

Задача:
Объясни нарушение правила качества данных, опираясь только на факты из контекста.

Критически важно:
- Не выдавай гипотезу за установленную причину.
- Если причина не доказана, пометь её как hypothesis.
- Не придумывай изменения в данных, коде или пайплайне, если их нет в контексте.
- Все предлагаемые действия должны быть проверяемыми.

Верни результат в структурированном markdown со следующими разделами:

1. Summary
   Кратко опиши, что именно сломалось и насколько это серьёзно.

2. Facts
   Только подтверждённые факты из входных данных:
   - правило
   - таблица/колонка
   - expected / actual
   - масштаб
   - примеры проблемных строк
   - динамика было/стало, если она есть

3. Impact
   На что это может повлиять технически и бизнесово.

4. Top hypotheses
   До 3 гипотез.
   Для каждой гипотезы укажи:
   - hypothesis
   - confidence: high | medium | low
   - why
   - how_to_verify

5. Next steps
   До 7 конкретных запросов к базе данных на чтение данных, которые помогут локализовать проблему.

Ключевые ограничения, которые мы держим в голове, это то, что LLM может написать красиво и убедительно, но это не значит, что она права.

Как это выглядит в жизни

Подключаем новую таблицу

  1. Инженер добавляет таблицу в реестр DQ (таблица, владелец, критичность).

  2. Система самостоятельно собирает DDL и строит профиль колонок (агрегаты + примеры).

  3. LLM генерирует набор правил.

  4. Мы рассматриваем предложения и правим спорные места.

  5. Правила уходят в репозиторий.

templates:
  id_column:
  - unique
  - not_null
  email_column:
  - not_null
  - format_check: email
  date_column:
  - not_null
  - date_range: min_date=2020-01-01, max_date=today()

tables:
- name: *****_intermediate.account
  description: Таблица '*****_intermediate.account' из PostgreSQL
  columns:

    # recommended_tests:
    #   - not_null: condition="="  # Проверяет отсутствие NULL/NaN в столбце.
    #   - unique: condition="="  # Проверяет, что значения в столбце уникальны.
    #   - data_type: condition="=", fmt="numeric"  # Проверяет тип данных столбца.
    #   - range_check: min_value=1, max_value=999999999, condition=">="  # Проверяет числовые значения на попадание в диапазон.
    - name: id
      description: Колонка 'id' таблицы '*****_intermediate.account'
      tests: []

    # recommended_tests:
    #   - data_type: condition="all", fmt="numeric"  # Проверяет тип данных столбца.
    #   - range_check: min_value=46480545.0, max_value=1000172858.0, condition="not_null"  # Проверяет числовые значения на попадание в диапазон.
    #   - unique: condition="not_null"  # Проверяет, что значения в столбце уникальны.
    - name: cc_account_id
      description: Колонка 'cc_account_id' таблицы '*****_intermediate.account'
      tests: []

    # recommended_tests:
    #   - not_null: condition="=="  # Проверяет отсутствие NULL/NaN в столбце.
    #   - data_type: condition="==", fmt="datetime"  # Проверяет тип данных столбца.
    #   - date_range: min_date="2020-01-01", max_date="2030-12-31", date_format="%Y-%m-%d %H:%M:%S", condition="between"  # Проверяет, что даты в столбце в заданном диапазоне.
    - name: transaction_time_utc
      description: Колонка 'transaction_time_utc' таблицы '*****_intermediate.account'
      tests: []

    # recommended_tests:
    #   - not_null: condition="all"  # Проверяет отсутствие NULL/NaN в столбце.
    #   - data_type: condition="all", fmt="datetime"  # Проверяет тип данных столбца.
    - name: transaction_time_msk
      description: Колонка 'transaction_time_msk' таблицы '*****_intermediate.account'
      tests: []

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

Однако в выводе можно заметить и косяки LLM. В одном месте condition="=", в другом condition="==", потом condition="all", condition="not_null" и condition="between". По самому выводу видно, что модель, скорее всего, начала додумывать допустимые значения, а не выбирать их из жесткого словаря.

Последнее замечание по структуре — модель не использует шаблоны, хотя они здесь явно подходят. У нас уже есть id_column и date_column, но для id и transaction_time_* LLM не сослалась на template, который предоставляет интерфейс библиотеки, а развернула рекомендации вручную.

Логично выглядят проверки для id, transaction_time_utc и transaction_time_msk. Это нормальный стартовый baseline. А вот range_check для id и cc_account_id обычно плохая идея, потому что текущие min/max это не бизнес-ограничение, а просто снимок сегодняшнего состояния. Через месяц диапазон вырастет и мы получим ложные алерты.

unique для cc_account_id может быть правильным, а может быть совсем неправильным - это как раз зависит от предметной области. Если это внешний account id и он должен быть 1 к 1, тогда все хорошо. Если это ссылка на аккаунт, к которой может относиться несколько строк, unique будет ложным правилом. То есть это хороший пример теста со статусом needs_domain_info, а не auto_ok.

date_range до 2030-12-31 тоже больше похоже на догадку модели, чем на правило системы. Это выглядит как признак отсутствия жесткого контракта генерации.

Отдельно видно, что модель пропустила связь между transaction_time_utc и transaction_time_msk. Вот здесь LLM как раз недодумала. Если у нас есть два поля: UTC и MSK-время одной и той же транзакции, напрашивается проверка согласованности между ними.

Для этого примера мы использовали модель Claude Sonnet 4. Поведение LLM в таких задачах сильно зависит от конкретной модели, и те огрехи, которые видны в YAML-выводе, стоит интерпретировать именно в контексте выбранной модели и заданного промпта, а не как свойство подхода в целом.

Инженерная ценность здесь в том, что мы превращаем исследование новой таблицы в стандартизированный процесс и тем самым решаем проблему чистого листа.

Упало правило

  1. Алерт формируется с приоритетом и базовой статистикой.

  2. LLM‑интерпретатор получает контекст и пишет объяснение:

  • что именно сломалось,

  • насколько массово,

  • что могло изменить распределение,

  • какие запросы сделать дальше,

  • кому пинговать.

Пример уведомления:

⚠️  Обнаружена ошибка качества данных
🚩 Проверка format_check не прошла в таблице *****_intermediate.registration_utm, поле email.
Ожидалось: значение должно соответствовать принятому в системе правилу валидации email
Получено: ['bblkovo@gmail', 'sdsdsdsdsd@1212', 'proskurin231@45', 'solowwomon@gmail', 'belluchi99@bk']
Детали: 28 значений не прошли проверку формата (0.01% от 340785 строк)
Кратко
В таблице *****_intermediate.registration_utm обнаружены значения в колонке email, которые не соответствуют используемому у нас правилу валидации email. Нарушение точечное: 28 записей из 340785 (0.01%).
Факты
Таблица: *****_intermediate.registration_utm (PostgreSQL)
Колонка: email
Количество нарушений: 28 из 340785 строк (0.01%)
Примеры значений: bblkovo@gmail, sdsdsdsdsd@1212, proskurin231@45, solowwomon@gmail, belluchi99@bk
Тип нарушения: значение не прошло текущее regex-правило проверки email
Влияние
Масштаб нарушения низкий, проблема выглядит точечной, а не массовой
Некорректные значения в email могут приводить к ошибкам в уведомлениях, коммуникациях и downstream-процессах
Возможны искажения в сегментации, отчётности и аналитике по email-каналу
Если такие записи продолжают накапливаться, точечная проблема может перерасти в системную
Топ гипотез
На части сценариев записи email недостаточно строгая прикладная валидация
Уверенность: medium
Почему: среди примеров есть значения, похожие на типичные ошибки ручного ввода или неполные домены
Как проверить:
сверить текущую frontend- и backend-валидацию email;
проверить, все ли точки входа используют одинаковые правила.
Часть записей пришла из внешнего источника или batch-загрузки в обход основной валидации
Уверенность: medium
Почему: единичные аномалии такого типа часто приходят не из основного пользовательского сценария, а из импортов или технических интеграций
Как проверить:
сопоставить время появления некорректных записей с загрузками и ETL-джобами;
проверить source system / ingestion path для этих строк.
Текущее regex-правило строже, чем реально допустимый формат в вашем продукте
Уверенность: low
Почему: часть “некорректных” адресов может нарушать именно ваш проектный паттерн, а не общий синтаксис email
Как проверить:
зафиксировать целевое бизнес-правило валидности email;
сравнить его с текущей regex-проверкой и правилами в приложении.
Следующие шаги
Посмотреть все 28 записей и сгруппировать их по типу ошибки
Проверить, из каких каналов и в какой период они появились
Сравнить правила валидации на frontend, backend и в DQ-проверке
Проверить, не проходят ли такие значения через импортные пайплайны
После локализации причины решить, нужна ли корректировка валидации, очистка данных или исключение для отдельных сценариев
Рекомендации
📌 Сначала синхронизировать единое правило валидности email между приложением, ETL и DQ
📌 Не вводить жёсткие ограничения в БД, пока не подтверждено целевое бизнес-правило
📌 Добавить разметку источника записи, чтобы быстрее разделять ошибки ввода и импортные артефакты
📌 Оставить мониторинг на этот кейс и следить, растёт ли количество нарушений во времени
Диагностические запросы
SELECT email, COUNT(*) AS cnt
FROM *****_intermediate.registration_utm
WHERE email !~ '^[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,}$'
GROUP BY email
ORDER BY cnt DESC
LIMIT 50;

SELECT LENGTH(email) AS email_length, COUNT(*) AS cnt
FROM *****_intermediate.registration_utm
WHERE email !~ '^[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,}$'
GROUP BY LENGTH(email)
ORDER BY email_length;
⚠️  Анализ от LLM может быть неточным. Перед изменениями в пайплайнах проверьте гипотезы.

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

Если при чтении кажется, что модель местами повторяется, это нормально. Здесь сама проблема очень простая и наглядная, поэтому ключевые мысли неизбежно дублируются. Кроме того, LLM у нас работает по жёсткой инструкции и ей нужно заполнить все блоки ответа, даже если часть содержания между ними пересекается. Для такого инженерного сценария это скорее плюс, чем минус, так как формат получается чуть менее изящным, зато более стабильным, проверяемым и удобным для дальнейшей работы.

На практике такой разбор сильно сокращает время до первой полезной гипотезы.

Как не утонуть в стоимости

На практике деньги улетают на генерацию алертов, зачастую даже одинаковых. Поэтому у нас три техники:

  • кэшируем объяснения по набору (таблица, правило, сигнатура инцидента);

  • используем маршрутизацию моделей, где дешёвые модельки направляем на типовые тексты, а сильные на расследования, где нужен анализ контекста;

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

Безопасность, контроль и мониторинг

Мы заранее приняли истину, что LLM потенциально небезопасный компонент и надо выстроить архитектуру защиты данных.

Первый слой — маскирование данных на пути в LLM. У нас это решается шлюзом защиты данных, который анализирует поля запроса и маскирует чувствительные сущности, с возможностью восстановить их в ответе.

Второй слой — управление ключами, правами и лимитами. На уровне платформы мы можем выдавать ключи с ограничениями по правам доступа, лимитами, временем жизни. Это важно, чтобы AI‑помощник был таким же субъектом доступа, как сервисный аккаунт.

Третий слой — защита от вредных советов. Проблема prompt injection возникает, когда в контекст может попасть текст вида «игнорируй инструкции». Поэтому мы разделяем доверительный контекст (DDL, метрики, результаты проверок, то есть то, что генерирует система) и недоверительный контекст (описания, текстовые поля, комментарии) и жестко фиксируем разграничение в инструкциях.

Что получилось в итоге

В цифрах эффект оказался вполне приземленным. Если смотреть на оба сценария вместе, то экономия времени больше 80%, относительно ручного расследования и заполнения конфигураций Data Quality.

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