Проверка спецификации с LLM: превращаем противоречия в вопросы автору
В одном разделе спецификации сессия живёт 30 минут, а в другом — 60. Разработчики выберут разные значения, тестировщик напишет проверку по третьему документу, и спор всплывёт перед выпуском. LLM полезна как помощник аналитика: она читает формулировки и предлагает пары требований, которые стоит согласовать. Рабочий результат — очередь вопросов автору с точными пунктами и контекстом.
Простой поиск разных чисел даёт много шума. Тридцать минут для обычного пользователя и шестьдесят для администратора могут быть намеренным правилом. Нужно сравнивать объект, условие, параметр и единицу измерения. Модель помогает извлечь эту структуру из текста, а явный алгоритм собирает кандидатов на конфликт.
Определите единицу сравнения
Для начала возьмите одну спецификацию и один тип требований — например, числовые ограничения. Каждое требование должно иметь стабильный ID и ссылку на раздел. Нормализуйте единицы до сравнения: час и 60 минут совпадают. Сложные условия вроде «после подтверждения операции, кроме режима обслуживания» следует сохранить целиком и передать аналитику, если их не удалось уверенно разобрать.
Вызов модели должен возвращать и извлечённые поля, и дословное основание. Человек проверяет несколько первых документов и уточняет инструкцию. Если модель потеряла условие «для администратора», последующее сравнение создаст ложный конфликт. Поэтому качество извлечения и полезность найденных вопросов оценивайте раздельно.
Постройте список вопросов
В примере вход — уже извлечённые и проверенные атомарные требования. Код не читает естественный язык. Он приводит минуты и часы к секундам, группирует одинаковые область действия и параметр, затем оставляет группы с разными значениями. Это законченная вычислительная часть для одного типа противоречий; её можно запускать после LLM-извлечения.
Все идентификаторы сохраняются. Вопрос нельзя показывать как «в документе противоречие» без пунктов: автору нужно открыть исходные формулировки и решить, какое правило действует. Запустите скрипт на Python; зависимости и внешние сервисы не нужны.
from collections import defaultdict
rows = [
{"id":"R1", "object":"session", "scope":"regular", "field":"idle_timeout", "value":30, "unit":"min"},
{"id":"R2", "object":"session", "scope":"regular", "field":"idle_timeout", "value":1, "unit":"hour"},
{"id":"R3", "object":"session", "scope":"admin", "field":"idle_timeout", "value":60, "unit":"min"},
{"id":"R4", "object":"session", "scope":"admin", "field":"idle_timeout", "value":1, "unit":"hour"}]
factor = {"min":60, "hour":3600}
groups = defaultdict(list)
seen = set()
for row in rows:
if row["id"] in seen:
raise ValueError("Duplicate requirement ID")
seen.add(row["id"])
seconds = row["value"] * factor[row["unit"]]
key = (row["object"], row["scope"], row["field"])
groups[key].append((row["id"], seconds))
questions = []
for key, items in groups.items():
if len({seconds for _, seconds in items}) > 1:
questions.append({"key":key, "requirements":[rid for rid, _ in items],
"values_seconds":sorted({v for _, v in items})})
assert len(questions) == 1
assert questions[0]["requirements"] == ["R1", "R2"]
assert questions[0]["values_seconds"] == [1800, 3600]
print(questions)
Начните с узкого задания на извлечение
Вход автора: «R1. Обычная сессия завершается после 30 минут бездействия. R2. Тайм-аут бездействия обычного пользователя равен одному часу». Модель должна распознать одну область действия regular и параметр idle_timeout, сохранив разные значения. Словари object, scope и field передаются в запросе явно.
Извлеки числовые ограничения из требований. Верни массив id, object, scope, field, value, unit, quote. Допустимые единицы min и hour. Сохрани условия применения и дословную цитату. Не решай, какой пункт правильный. Неизвестные поля пометь для ручного уточнения; не подставляй значения по умолчанию.
Ожидаемые записи для R1 и R2 совпадают по session / regular / idle_timeout и различаются значениями 30 min и 1 hour. После проверки цитат аналитик допускает записи к сравнению. Если scope неизвестен, запись идёт в очередь уточнения, иначе ложное объединение областей создаст искусственный конфликт.
Почему это ещё вопрос, а не найденный баг
Скрипт выдаст R1 и R2: для обычной сессии одновременно указаны 1800 и 3600 секунд. R3 и R4 не попадут в список, потому что их значения совпадают после нормализации. Автор спецификации может подтвердить ошибку, уточнить область действия или объяснить, что один пункт описывает будущий релиз. Итоговое решение должно вернуться в требования и тесты.
Сохраните у каждого вопроса статус, владельца и принятое решение. Закрытый конфликт полезно включить в регрессионный набор: при следующем редактировании документа ассистент не должен снова предлагать уже согласованную пару. При этом новая версия исходного пункта требует повторной проверки, даже если его ID сохранился.
С чего расширять проверку
После числовых ограничений можно перейти к обязательности полей и разрешённым переходам состояний. Для каждого типа понадобится своё правило сравнения. Универсальная просьба «найди всё противоречивое» удобна для первого просмотра, но плохо подходит для измеримого рабочего процесса. Считайте, какая доля вопросов действительно потребовала исправления и сколько известных конфликтов система пропустила.
Автоматизируйте чтение новых спецификаций
Следующая инженерная задача — подключить извлечение требований, сохранить версии инструкций и дать аналитику интерфейс проверки. На курсе вы пройдёте путь от LLM-цепочки к приложению с API, инструментами и веб-интерфейсом. Блоки PromptOps, метрик качества и наблюдаемости помогут разбирать, почему после изменения промпта стало больше ложных вопросов. Откройте программу платного курса «LangChain 1.0.x: c нуля до продакшн LLM-приложений».
Продолжить на практике
- LangChain 1.0.x: c нуля до продакшн LLM-приложений ↗
Практический курс по LangChain. Соберёте продакшн LLM-бота: RAG по PDF с цитатами, веб-поиск и трекинг заказов, многошаговый агент для анализа CSV и финальное веб-приложение (UI + API). Плюс профессиональные блоки: PromptOps и версионирование промптов, метрики качества RAG, гибридный поиск с реранком, observability/стоимость, надёжность (ретраи, таймауты), guardrails и отдельный модуль по LangGraph для устойчивых workflow. P.S. Полностью обновили материалы на актуальную версию LangChain
