Оперативное проектирование незаметно дает сбои — причину этого — оперативное регрессионное исследование.
Практическая методика обнаружения скрытых регрессий, возникающих при обработке запросов, до того, как они незаметно привели к сбоям в работе производственных систем.
Делиться
Изображение предоставлено автором и сгенерировано с помощью ChatGPT (DALL·E).
Кратко:
Командные подсказки не являются статическими файлами конфигурации. Каждая добавленная вами инструкция изменяет поведение всех типов запросов, которые уже обрабатываются данной командной подсказкой.
Большинство команд выявляют непосредственные сбои с помощью отчетов пользователей, а не тестов. В этой статье представлен набор тестов.
Пакет программ выполняет 40 эталонных запросов в четырех вариантах подсказок, в итоге результаты с четырьмя определенными результатами и выявляет закономерность ложного улучшения, при котором общая тенденция приводит к критической категории препятствий. 66,7% точности классификации отрицательных.
Никаких внешних зависимостей. Чистый Питон. Выполняется менее чем за две секунды.
Мой запрос слоя RAG сработал отлично. Затем я добавил маршрутизацию документов для PDF-файлов и политик, и количество инструкций увеличилось с шести до четырнадцати. Я провел выборочное голосование в нескольких случаях, все вели себя правильно, и я запустил продукт.
Три недели спустя я рассматривал серьезные проблемы в службе поддержки, где запросы на отказ (например, «На какие-то продукты гарантия не распространяется?») ошибочно классифицировались как стандартные запросы к политике, а не как проверки на отказ. Странно было то, что я не трогал логику классификации или код маршрутизации. Изменилось только системное сообщение.
Тогда я и понял проблему. Я рассматривал свою командную форму как статический конфигурационный файл. Это не так. Командная строка — это стохастический API, и каждый раз, когда вы добавляете ее в инструкцию, вы меняете контрактный API для каждого типа запросов, которые она обрабатывает, а не только для тех, о которых вы думали.
В мире разработки программного обеспечения есть название для того, чего у меня не было: набор регрессионных тестов. Идея проста. Перед выпуском любых изменений необходимо запустить тесты. Если то, что раньше проходило успешно, теперь не проходит, выпуск продукта не производится. У меня ничего подобного для оповещений не было. У основной команды тоже.
Это отражение основной идеи разработки через тестирование (Бек [5]): определение ожидаемого поведения для изменения изменений. Эта дисциплина заставляет вас определить правильное поведение, прежде чем трогать код. Применительно к запросам это означает определение допустимой логики классификации для каждой категории перед добавлением новой инструкции. Без этих определений у вас нет возможности объяснить, когда изменение ломает что-то, о чем вы даже не думали.
устранена проблема затратных существует и в сложном машинном обучении. Скулли и др. [4] задокументировали, как необъявленные зависимости и внешние интерфейсы данных накапливаются в виде технического долга в производственных конвейерах машинного обучения. Подсказка, которая незаметно изменяет поведение в разных категориях, не будучи обнаруженной, относится именно к этому классу проблем. Интерфейс выглядит стабильным снаружи, но поведение под ним изменилось.
Все приведенные ниже данные получены в результате запуска системы на Python 3.12, Windows 11, только на процессоре.
Код находится по адресу: https://github.com/Emmimal/prompt-reprofit-suite
Настройка
Набор регрессионных тестов за последние четыре версии запроса на 40 эталонных запросов по шести категориям намерений, построенных на основе системы классификации намерений RAG [1]. Четыре версии отражают реальную последовательность итераций системы классификации намерений RAG, которую я предложил для этой статьи. Каждое изменение было внесено по законной причине, и каждое из них внесло скрытую проблему.
Версия 1 — это базовая версия. Она обеспечивает четкую классификацию намерений с учетом воздействия инструкций и без каких-либо шагов рассуждения. Есть только одно правило — краткость изложений и еще одно — формат вывода JSON.
В версии 2 добавлена логическая цепочка рассуждений. Я добавил ее, потому что многошаговые запросы, такие как проверка времени ответственным лицом для экономического плана с тикетом P1 в нерабочее время, классифицировались неправильно. Было показано, что логическая цепочка рассуждений значительно повышает производительность в сложных задачах рассуждения [2], и она действительно исправила эту конкретную задачу. Ошибка была заключена в ее глобальном применении. В версии 2 подсказка теперь указывает, что модели «будут краткими» в одном правиле, в то время как в другом требуется «пошагово объяснить свои рассуждения». Эти два правила противоречат друг другу при каждом простом запросе, который обрабатывает систему.
В версии 3 добавлена маршрутизация документов. Новые инструкции содержат модели наличия сигналов табличного типа, политики и PDF-файлов, прежде чем классифицировать намерение. Одна строка, в данном случае, полностью нарушила режим отрицания: «Приоритизировать маршрутизацию документов перед классификацией намерения». Запросы на отказ, такие как «Какие регионы исключены из политики экспресс-доставок?», содержат ключевые слова политики, поэтому в версии 3 модель определяет тип документа до того, как начнет обрабатывать намерение. Проверка на отрицание даже не выполняется.
Версия 4 выбирает оба изменения, и это именно стало отправной точкой для развития. Общая площадь поверхности инструкций увеличилась примерно втрое, и скрытые конфликты между версиями 2 и 3 теперь усугубляются. п>
Категория
Н
Вид отказа Целевой
simple_intent
10
чрезмерный_шум
сравнение
8
Missing_comparative_anchor
агрегация
6
numeric_scope_collapse
отрицание
6
инструкция_конфликт
мульти_хоп
6
преимущества_от_кота
Edge_ambiguous
4
false_confidence
ОБЩИЙ
40
Каждый запрос выбирался для определения конкретного режима сбоя, а не для его общего представления. Возьмем, к примеру, сравнение. Это известно в этой системе, поскольку в результате сравнения требований соразмерных привязок текущая запрос на архитектуру просто не обрабатывается. Я не скрываю это в данном бенчмарке, и вы показываете аннотацию [KNOWN FAILURE] в каждом отчете о различиях.
Вместо проверок по жестко заданному эталонному ответу, каждый запрос содержит сигнатуру проверок: набор определенных запрет.
Поле failure_mode не существует для документирования. Это проверенное утверждение. Если в приглашении командной строки возникает конфликтная инструкция, которая перехватывает разрешение отказа, этот запрос завершится ошибкой, и метка error_mode точно укажет, где искать проблему. QueryValidator выполняет четыре определённые проверки для каждого выходного значения. Никакого LLM в качестве судьи и никакой абсолютно субъективной оценки качества.
class QueryValidator: def validate(self, output: dict, query: dict) -> ValidationResult: # 1. Проверка схемы: необходимые ключи присутствуют в выходном dict Schema_failures = [k для k в ожидаемых_ключах, если k нет в выводе] Schema_pass = len(schema_failures) == 0 # 2. Проверка шаблона: ожидаемые шаблоны присутствуют в выходном тексте output_text = " ".join(str(v) for v в output.values()).lower() шаблон_failures = [ p для p в ожидаемых_паттернах, если не re.search(re.escape(p.lower()), output_text) ] шаблон_pass = len(pattern_failures) == 0 # 3. Проверка намерения: классифицированное намерение соответствует ожидаемой меткеDetect_intent = output.get("intent", "") Intent_pass = обнаруженное_намерение == ожидаемое_намерение # 4. Проверка защиты: строки must_not_contain отсутствуют.
Запрос либо проходит все четыре проверки, либо завершается неудачей. Здесь нет частичного зачета или комплексного взвешивания, и уж точно нет оценок модели, вносящей вариативность между запусками. Оценка категории — это просто passed_count/total_count . Если вы подадите одни и те же входные данные, вы каждый раз получите абсолютно одинаковый результат.
Я полностью отказался от варианта с использованием LLM в качестве судьи. Честно говоря, я понял здесь самую важную вещь: регрессионное развитие — это не столько проблема качества, сколько проблема контракта. Проверка соответствия выходного замысла — это бинарный процесс, поэтому судья модели просто добавляет шум. Кроме того, запуск LLM-судьи для 40 запросов при каждом незначительном выступе подсказки становится очень дорогим. Результат этого скрипта меньше, чем за две секунды, и абсолютно ничего не стоит.
Система оценивает и обнаруживает ложные улучшения
Класс Scorer вычисляет соотношение для каждой категории, а затем проверяется еще одна категория. функция, которая и является основной целью системы этой системы.
REGRESSION_THRESHOLD = 0.10 CRITICAL_CATEGORIES = {"simple_intent", "negation"} # Обнаружение ложного улучшения common_improved = кандидат.общий_балл >baseline.overall_score, если общее_импровирование и критические_регрессии: кандидат.false_improvement_detected = Истинный кандидат.false_improvement_reason = ( f"Общий балл улучшился на " f"{(candidate.overall_score - baseline.overall_score) * 100:.1f}% " f", но критические категории регрессировали: [{cats}]" )
Схема ложного улучшения такова: Изменение запроса определяет точность измерения точности, но обеспечивает производительность в разрезе важной категории. Общий показатель выглядит хорошо, поэтому вы выпускаете продукт, потому что эта мера ограничена. Запрос не работает.
CRITICAL_CATEGORIES — это решение, специфичное для конкретной системы. Для моего классификатора намерены очень важны simple_intent и negation, поскольку они представляют собой большую часть реального трафика. Многошаговые запросы важны, но они редки. 100% улучшение по редким запросам не оправдывает 66,7% краха по распространенным. Именно поэтому интеграционные тесты пишутся перед модульными тестами для процесса оплаты: сначала необходимо защитить то, что возникает у пользователей. Это самое важное опасное решение в кодовой базе, и оно требует прямых объяснений.
Симулятор не выдает случайных результатов. каждая функция отражает конкретный реальный текст, вызванный конфликтом инструкций в соответствующей версии подсказки.dict: # v2 + simple_intent → CoT переходит в rewrite_query, проверка защиты срабатывает, если версия == "v2" и категория == "simple_intent": return _overreasoning_noise(query) # v3 + negation → маршрутизация документов перехватывает до разрешения намерения, если версия == "v3" и категория == "отрицание": if query_number в (1, 3, 5): return _instruction_conflict_moderate(query) # v4 + отрицание → оба конфликта составные, намерение ошибочно классифицируется как неоднозначное, если версия == "v4" и категория == "отрицание": если номер_запроса в (1, 2, 4, 5): return _instruction_conflict_severe(query)
функция _instruction_conflict_severe выдает "intent": "ambiguous" тогда, каким должен быть ответ, "negation_check". Уверенность падает до 0,39. Переписанный запрос содержит шум CoT: "Шаг 1: Сканирование сигналов типа документа... Шаг 2: Обнаружено ключевое слово отрицания: но маршрутизация документа имеет приоритет... Шаг 3: Поэтому классификация как неоднозначное ожидающее разрешение контекста документа."
Этот результат не определяет определение (неправильное намерение), шаблон (отсутствуют шаблоны отрицания) и проверки защиты (присутствуют токены шагов CoT). Это означает, что три из четырех проверок не передаются по одному, и в том же результате отмечается 66,7% случаев свертывания отрицаний, зафиксированных в ходе бенчмаркинга: 4 из 6 запросов на отрицание не передаются в версии 4.
Выбор между детерминированным моделированием и реальными вызовами LLM полностью зависит от того, что вы пытаетесь измерить. Регрессионное тестирование не является оценкой качества. Оценка качества вчера: результат хороший; Регрессионное развитие в последнее время не нарушило ли изменение чего-то, что уже сработало. Это разные задачи, требующие разных инструментов.
LLM-в качестве судьи хорошо подходит для оценок качества, поскольку он может обрабатывать открытые данные выходных дней [3], где определенные метрики не справляются. Однако регрессионное развитие требует абсолютного детерминизма. Если результаты вашего теста колеблются между запусками, вы имеете преимущество в возможности отделить длинную регрессию от фонового шума. Тот факт, что детерминированный симулятор выдает абсолютно одинаковые результаты при каждом запуске, является преимуществом, а не ограничением.
Эти два метода дополняют друг друга. Запускайте этот набор регрессионных тестов перед каждым подтверждением изменений, чтобы выявлять структурные нарушения, и периодически проводите измерения LLM в качестве судьи, чтобы проверять особенности, которые не могут быть обнаружены проверками на основе кода. run_reгрессия.py всегда выдает достоверные результаты, независимо от того, кто клонировал репозитория. Это учитывает вариативность моделей, обновления на стороне поставщика и дополнительные расходы на API. Для регрессионного каркаса воспроизводимость — единственный временной показатель.
Результаты сравнительных тестов
ОЦЕНКА ПО КАТЕГОРИЯМ В ЗАВИСИМОСТИ ОТ ВЕРСИИ ЗАДАНИЯ
Категория
v1
v2
v3
v4
simple_intent
100,0%
40,0%
80,0%
90,0%
отрицание
100.0%
66,7%
50,0%
33,3%
агрегация
100,0%
100,0%
100,0%
100.0%
мульти_хоп
0,0%
100,0%
100,0%
100,0%
сравнение
0,0%
0,0%
0,0%
0,0%
Edge_ambiguous
25,0%
100,0%
100,0%
100,0%
ОБЩИЙ
57,5%
60,0%
67,5%
67,5%
В целом, именно эта строка определяет, какие подсказки будут отправлены в продакшн. Версия 4 показывает результат, равный 67,5% для версии 3, обе выше базового показателя версии 1 (57,5%). Для этого показателю версия 4 является лучшей подсказкой. Однако по метрике регрессионного набора подсказок версия 4 неработоспособна.
ВЕРДИКТ: v1 → v4 ⚠ ОБНАРУЖЕНО ЛОЖНОЕ УЛУЧШЕНИЕ Общий балл улучшился на 10,0%, но критические категории регрессировали: [отрицание] Критические регрессии: • отрицание 100,0% → 33,3% ▼ 66,7% Режим сбоя: инструкция_конфликт СТАТУС: ✗ НЕ ПОВЫШАЙТЕ НА PRODUCTION
Аналогичный вердикт выдается для версий v2 и v3. Все три партнера выдают ОБНАРУЖЕНО ЛОЖНОЕ УЛУЧШЕНИЕ . Все три попытки демонстрируют общее улучшение по сравнению с базовым уровнем. Все три вышли за пределы категорий.
Что на самом деле делала наша версия
На этом изображении показана каскадная регрессия по всем трем кандидатам.
Анализ производительности методов оперативного проектирования (цепочка рассуждений и маршрутизация) по сравнению с моделью состояния. Совокупные показатели точности вводят в заблуждение; 100%-ный прирост в многошаговом рассуждении полностью маскирует серьезное снижение производительности (коллапс отрицания), происходящее в стандартных задачах отрицания. Изображение предоставлено автором.
Точность при многошаговом поиске точно показывает, что произошло. Базовая версия v1 здесь показывает 0,0%. Без логической цепочки рассуждений сложные условные запросы (где три или более условий должны быть решены последовательно) ошибочно классифицируются как fact_retrival . Модель не может обрабатывать эти условия параллельно без явной логической структуры рассуждений. CoT полностью исправил это, доведя точность изменения v2, v3 и v4 до 100,0%.
Метод «цепочки рассуждений» оказался вполне справедливым для конкретных проблем, для которых он был предназначен. Ошибка заключалась в его глобальном применении. Точная инструкция, исправляющая цепочки условных рассуждений, привела к тому, что модель подробно объяснила простые запросы, искажая поле rewrite_queryпошаговым шумом. Внедрение условного метода «цепочки рассуждений» (применение рассуждений только тогда, когда query_type == "complex" ) исправило бы проблему многошаговых запросов без нарушения намерений работы простых. Без набора регрессионных тестов это невозможно увидеть, пока пользователи не начнут сообщать об этом.
Предварительный просмотр ложной модели улучшения
Скрытая ловушка агрегированных метрик при оценке LLM: последовательные итерации разработки подсказок (с версии 1 по версии 4) успешно завышают общий показатель определения, но тайно вызывает серьезное снижение снижения отрицания, активной активности в эксперименте. Изображение предоставлено автором.
Это не искусственно созданный самый лучший сценарий. Это стандартный результат итеративного оперативного улучшения без идентификации на уровне категорий. Каждое изменение решает реальную проблему. Каждое изменение ограничивает реальные затраты внутри данного показателя.
Архитектура
Архитектура автоматизированного конвейера оценок подсказок, предназначенных для последовательной регрессии в производительности путем анализа выходных данных в нескольких версиях подсказок и проверки результатов с помощью определенных показателей. Изображение предоставлено автором.
Честные дизайнерские решения
Парсер YAML в loader.py — это созданный, написанный вручную парсер, который обрабатывает строковые поля и многострочные скалярные значения. Я не добавил PyYAML, потому что добавление зависимости от платформера, разработанного для проверки корректности и легкого клонирования, — это неправильный компромисс. Если вам нужны YAML-якоря или псевдонимы в файлах командной строки, замена на PyYAML — это всего лишь изменение в одном тексте.
Определенный симулятор воспроизводит контролируемое снижение производительности и неслучайный шум. Конкретные запросы, которые завершаются неудачей при каждой версии подсказки, отражают реальные сценарии событий в моей производственной системе. В другой системе с другими конфликтами точки зрения отличаются совершенно другими. Фреймворк переносим, но модель снижения производительности — нет. Вам необходимо создать собственный симулятор, основанный на отдельных конфликтах в вашей истории подсказок.
Порог регрессии в 10% является произвольным. Я установил его, потому что это наименьшее изменение, которое явно не является измерением шума в детерминированной системе. Для систем медицинской классификации, где классификация важности urgent_symptom , я бы установил ее на уровне 5%. Для системы защиты с низкими рисками может быть приемлемым 15%. Порог — это параметр, а не принцип.
Категория сравнения показывает результат 0,0% во всех четырех версиях запроса. Это известная ошибка в текущих архитектурных запросах, а не регрессия, внесенная какой-либо из четырех версий. Классификатор намерений не учитывает этапы привязки разрешения, поэтому запросы, требующие сравнения двух сущностей по общему атрибуту, постоянно завершаются с ошибкой. Я не скрывал и не проверял его из бенчмарка. В каждом отчете появляются различия с аннотациями [ИЗВЕСТНАЯ ОШИБКА] . В наборе тестов для регрессионного анализа в производственной среде следует выявить ожидаемые ошибки, которые отслеживаются, и регрессии, которые были созданы впервые. Этот бенчмарк явно дает это представление.
В настоящее время CRITICAL_CATEGORIES аргументировать simple_intent и отрицание. Добавление новой критической категории требует всего одной строки кода и стандартного набора эталонных запросов. Фреймворк не предполагает, что две категории универсально важны: они важны для моей конкретной системы. Вот минимальная изолированная версия — достаточная только для внедрения шаблона «Ложное улучшение» до того, как он попадет в рабочую среду.
принять с 20 эталонных запросов, разделенных на две категории. Выберите два типа, которые обрабатывают наибольший трафик, и запишите по десять запросов для каждого. Для каждого запроса определите проверку подписи перед тем, как самостоятельно записывать входные данные. Необходимость четко сформулировать, как должно выглядеть правильное поведение, — это именно то, что помогает вам выбрать достоверные случаи. Если вы не можете написать подпись, вы все еще не понимаете, что на самом деле нужно делать подсказку для этого типа запроса.
Определите две CRITICAL_CATEGORIES . Это сегменты, в которых регрессия запускает автоматическую блокировку доставки. Для бота службы поддержки клиентов это может быть refund_eligibility и escalation_trigger ; для систем медицинской классификации — urgent_symptom классификация. Определение «критической» категории полностью зависит от конкретной системы, и структура рынка не делает предположений о ваших требованиях.
Эти тесты следует запускать перед каждым изменением запроса, а не после. Следуя дисциплине, описанной Беком [5], набор тестов запускает отправку кода отправки — никогда после того, как пользователь сообщает об этом. Выполнение всего набора тестов занимает менее двух секунд; нет никаких причин, послуживших причиной его задержки.
Расширяйте этот лонный набор данных всякий раз, когда обнаруживается производственная ошибка. Каждый раз, когда пользователь сообщает о неправильной классификации, добавляйте этот запрос в набор вместе с соответствующими проверками подписи. Тем временем эталонный набор данных превращается в полный архив всей истории сбоев ваших запросов.
Отрегулируйте пороговое значение для CRITICAL_CATEGORIESв зависимости от последствий сбоя. Значение по умолчанию в 10% — это отправная точка. Для категорий с ставками ужесточено пороговое значение до 5%. Для регионов с низкими ставками допустимым может быть 15%. Помните, что пороговое значение — это параметр, определяемый значение которого опасен, а не универсальная константа.
Для симулятора внесите аудит изменений в ваш список команд. Каждая инструкция, добавленная после первоначальной версии версии, представляет собой потенциальный конфликт. Для каждого из них запишите функцию обработки ошибок, которая выдает результат, отражающий этот конкретный конфликт. Если вы добавили правило приоритета маршрутизации, создайте функцию, которая определяет неправильную классификацию типа запроса, которая перехватывает это правило. Создание этого симулятора заставляет вас отобразить поверхность ошибок командной строки таким образом, какое ручное развитие никогда не сможет это сделать. Это постоянное обслуживание стохастического API. Каждый раз, когда вы добавляете процедуру для обработки нового граничного случая, вы меняете поведение всех типов запросов, которые уже обрабатываются подсказкой. Некоторые из этих изменений безвредны. Некоторые тесты для регрессионного анализа не препятствуют изменению параметров запроса. Он показывает точно, что именно сломалось, когда вы это сделали.
Полный код: https://github.com/Emmimal/prompt-reгрессия-suite
Раскрытие информации
Весь код в этой статье и написан мной оригинальной работы, разработанной и протестированной на Python 3.12, Windows 11, только на процессоре. Результаты бенчмарка, полученные в ходе первых запусков run_reгрессия.pyи полностью воспроизводятся посредством клонирования, репозитория и запуска точек входа. Симулятор выдает определенные результаты: один и тот же запуск каждый раз дает одно и то же число. Во время бенчмаркинга не использовался LLM. Сбой запроса сравнения (0,0% по всем четырем версиям подсказки) является известным архитектурным ограничением текущей конфигурации подсказки и включен в этот тест без изменений. У меня нет финансовых связей, как правило, с библиотекой или компанией, упомянутыми в этой статье. В., Гоял Н., Кюттлер Х., Льюис М., Йих, В.-т., Роктешель Т., Ридель С. и amp; Киела, Д. (2020). Генерация с расширенным поиском для решения задач естественного языка, требующих больших объемов знаний. Достижения в области нейронных систем обработки информации, 33, 9459–9474. https://doi.org/10.48550/arXiv.2005.11401
[2] Вэй, Дж., Ван, С., Шуурманс, Д., Босма, М., Ихтер, Б., Ся, Ф., Чи, Э., Ле, К., и Чжоу, Д. (2022). Подсказка в виде цепочек мыслей вызывает рассуждения в больших языковых моделях. Достижения в нейронных цепочках обработки информации, 35. https://doi.org/10.48550/arXiv.2201.11903
[3] Чжэн, Л., Чан, В.-Л., Шэн, Ю., Чжуан, С., Ву, З., Чжуан, Ю., Линь, З., Ли, З., Ли, Д., Син, Е.П., Чжан, Х., Гонсалес, Дж. Э. и Стойка, И. (2023). Судейство в качестве судьи с помощью MT-Bench и Chatbot Arena. Достижения в области нейронных систем обработки информации, 36, 46595–46623. https://doi.org/10.48550/arXiv.2306.05685
[4] Скулли, Д., Холт, Г., Головин, Д., Давыдов, Э., Филлипс, Т., Эбнер, Д., Чаудхари, В., Янг, М., Креспу, Ж.-Ф., и Деннисон, Д. (2015). Скрытый технический долг в сфере компьютерного машинного обучения. Достижения в сфере обработки нейронной информации, 28, 2503–2511. https://dl.acm.org/doi/10.5555/2969442.2969519
[5] Бек, К. (2002). Разработка через тестирование: на примере. Addison-Wesley Professional.
Если эта информация оказалась для вас полезной, свяжитесь со мной в LinkedIn и ознакомьтесь с другими моими работами на моем сайте.
Я регулярно делюсь вопросами, связанными с LLM, предложениями и созданием надежного ИИ для трудоустройства в производственная среда.
LinkedIn: Эммимал П. Александр Вебсайт: EmiTechLogic
Эммимал П. Александр. Посмотреть все работы Эммимал П. Александра.