Гайд · TNWS AI
Как проверить согласованность AI-разметки для повторяющегося вопроса
Находим противоречивые эталонные метки одинакового вопроса в AI-корпусе и останавливаем оценку до ручного разбора.
Практическая задача
Не считать ошибкой модели случай, когда редакторы присвоили одному и тому же вопросу разные expected-метки. Прежде чем сравнивать prediction с золотым набором, проверьте сам набор. Два одинаковых нормализованных текста с метками urgent и normal сигнализируют конфликт разметки; автоматическое большинство не решает, какое бизнес-правило верно. В примере exact-normalization выполняется trim и casefold, без удаления пунктуации и без семантического сравнения перефразов. Если такие записи относятся к разным регионам, тарифам или этапам диалога, простой текстовый ключ недостаточен: контекст должен быть отдельным полем фикстуры и участвовать в сравнении. После решения редактора зафиксируйте причину в истории набора, чтобы следующий импорт не вернул конфликт. Разные аннотаторы должны увидеть оба ID и исходный контекст до того, как в одном из кейсов изменится эталон. Этот сценарий применим, когда у команды есть контроль над корпусом AI-приложения и требуется конкретный сигнал о нарушении правила, а не общее впечатление от нескольких ответов. Все входы ниже вымышлены; числовые результаты относятся только к этим примерам.
Документация методов Python и синтаксиса workflow сверена 19.09.2026. Если вы используете другое окружение, проверьте совместимость до копирования команд. Статья не утверждает, что показанный код измеряет качество конкретной модели или заменяет предметную разметку людьми.
Подготовка и проверяемый контракт
Перед запуском запишите, какие данные считаются входом, что является ожидаемым результатом, что именно означает отказ и кому предстоит разбирать расхождение. Для AI-оценки важно отдельно хранить вход, ожидаемую метку и фактический результат: если они смешаны, тест может подтверждать сам себя. Используйте стабильные синтетические ID, чтобы видеть ошибку в журнале, не раскрывая содержимое клиентских обращений.
Сначала прогоните тест на маленьком входе, где правильное поведение известно вручную. Затем внесите одну контролируемую ошибку и убедитесь, что код её замечает. После этого верните корректный набор и только тогда расширяйте проверку до реальных данных. Не переносите демонстрационные численные значения или пороги в производство без отдельного обоснования: они выбраны для наглядности, а не рассчитаны по вашей аудитории.
Вход и ожидаемый результат
Одна строка Срочно: оплата не проходит размечена urgent, вторая такая же в другом регистре — normal. Ожидается конфликт пары IDs. A1 и A2 попадают в один нормализованный ключ, но имеют разные метки; B1 не участвует. Выход показывает только ID и метки, не текст пользовательского обращения. Перед тем как применять правило к закрытому корпусу, обсудите пограничные случаи, которые могут поменять интерпретацию входа. Запись в документации о границах теста не менее важна, чем зелёный check.
Пошаговые действия
- Создайте
scripts/check.pyв корне репозитория и вставьте код из блока ниже. Он использует названия функций стандартной библиотеки, указанные в официальных ссылках в конце статьи. - Выполните
python scripts/check.pyлокально. Не продолжайте, если уже демонстрационная фикстура даёт иной результат: сначала проверьте копирование кода и кодировку файла. - Запустите скрипт и проверьте обнаружение A1/A2. В рабочем корпусе при конфликте останавливайте оценку с ненулевым кодом и передавайте обе записи ответственному редактору. После согласования правила исправьте expected или разделите сценарии дополнительным контекстом, который делает случаи действительно разными. Если даже при одинаковом тексте результат зависит от истории диалога, включите нужный контекст в ключ сравнения, не объявляйте проблему дубликатом по умолчанию.
- Создайте
.github/workflows/ai-corpus-check.ymlиз YAML-шаблона. Событиеpull_requestполезно для проверки корпуса до слияния; чтение репозитория ограниченоpermissions: contents: read. Скрипт не должен получать ключ внешней модели или реальные секреты. - В разделе Actions откройте job
check, сопоставьте его код завершения с локальным прогоном и зафиксируйте ссылку на проверенный коммит в PR. Не принимайте зелёный результат на старой ревизии за проверку последнего изменения.
# scripts/check.py
from collections import defaultdict
cases = [("A1","Срочно: оплата не проходит","urgent"),
("A2","срочно: оплата не проходит","normal"),
("B1","Когда чек?","normal")]
groups = defaultdict(list)
for case_id, text, label in cases:
if label not in {"urgent", "normal"}:
raise SystemExit("Unknown label in " + case_id)
groups[text.strip().casefold()].append((case_id,label))
conflicts = {text: entries for text,entries in groups.items()
if len({label for _,label in entries}) > 1}
if not conflicts:
raise SystemExit("Demo conflict was not detected")
for entries in conflicts.values():
print("Conflicting fixture IDs:", entries)
name: AI corpus checks
on:
pull_request:
permissions:
contents: read
jobs:
check:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v7
- uses: actions/setup-python@v7
with:
python-version: '3.13'
- run: python scripts/check.py
Ошибки интерпретации и границы
Метод не находят перефразы и может ошибочно считать дубликатом две записи с разным невидимым контекстом. Ручной разбор — часть процесса, а не недостаток скрипта. Не перенастраивайте модель по противоречивому эталону. Если вы увеличиваете корпус, добавляйте не только новые примеры, но и отрицательные случаи, на которых тест обязан упасть. Проверяйте, что изменение expected прошло ревью отдельно от изменения кода: иначе можно незаметно изменить правило под текущий ответ системы. Избегайте вывода полного корпуса в CI и не сохраняйте в артефактах ответ закрытой модели без решения о доступе и хранении.
Ошибка выполнения самого Python, нераспознанный формат входа и обнаруженный бизнес-дефект — разные ситуации. В сообщении теста указывайте тип проблемы и безопасный ID. Если тест требует внешний сервис, вынесите его из PR с недоверенным кодом и явно ограничьте доступ к токенам; этот пример намеренно работает локально. Перед публикацией каких-либо результатов опишите методику, размер и происхождение набора, иначе читатель воспримет демонстрационную арифметику как характеристику продукта.
Чек-лист финальной проверки
- Синтетический вход и ожидаемый исход согласованы предметным владельцем.
- Команда
python scripts/check.pyработает локально и в CI на одной версии файлов. - Негативный случай обнаруживается, а не только успешный случай проходит.
- Имена ID и меток уникальны там, где этого требует контракт.
- В репозитории, логах и артефактах нет реальных секретов и приватных текстов.
- Понятно, какой дефект тест находит и каких выводов о качестве AI он не даёт.
- Ссылки на применённые функции и синтаксис workflow перепроверены при переносе.
FAQ
Почему не выбрать наиболее частую метку?
Большинство может закрепить неверную разметку; нужен контекст и решение эксперта.
Как учитывать историю диалога?
Сделайте её явной частью входа и ключа сравнения.
Зачем проверять до AI-запросов?
Некачественный эталон обесценивает оценку и расходует ресурсы.
Найдутся ли разные формулировки одного смысла?
Нет, здесь проверяется совпадение после trim/casefold.
Что делать после обнаружения сбоя
Сохраните конкретный ID, воспроизведите его на текущей ревизии и отделите ошибку входного корпуса от ошибки функции. Если неверна разметка, исправьте её после предметного ревью; если неверен код, сначала оставьте проваливающийся тест, затем вносите исправление. После зелёного запуска просмотрите соседние случаи с похожими признаками, чтобы локальная правка не изменила другое согласованное поведение. Сохраните версии кода, набора и параметров запуска рядом с выводом: без них сравнивать результаты в будущем нельзя. Не приводите цифру из синтетического примера как измеренный показатель продукта.
Официальные первоисточники
Проверено 19.09.2026: 1, 2, 3, 4. Описание переписано своими словами; изменяемые версии и поля нужно повторно сверять перед дальнейшим использованием.
Читайте также
Как исключить bias из weight decay через Optax
Optax 0.2.6: маска add_decayed_weights применяет decay к kernel и оставляет bias без изменения.
Как использовать Huber loss в Optax для регрессии с выбросами
Optax 0.2.6: Huber loss квадратичен около нуля и линеен после delta; проверяем ошибки 0,5 и 2.
Как использовать sigmoid focal loss в Optax
Optax 0.2.6: focal loss для logits 0 и labels 0/1 при gamma=2; проверка симметричного базового значения.
Комментарии
Пока тихо. Скажите первое слово