← Назад в блог

Двухэтапный RAG: сначала стандарты, затем лабораторные факты

21 октября 2026 г. · 6 мин чтения
Двухэтапный RAG: сначала стандарты, затем лабораторные факты - Почему одноэтапный RAG дает сбои в комплаенсе. Как извлечение правил из стандартов формирует точные запросы к паспортам качества поставщиков.

Производитель проверяет рецептуру растительного молока для получения европейского сертификата V-Label.

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

Поисковый движок находит пять внешне подходящих фрагментов:

  1. Слайд презентации поставщика со словами: «Бета-каротин идентичен натуральному, подходит для вегетарианцев».
  2. Статья из энциклопедии пищевых добавок с определением провитамина А.
  3. Товарная накладная на поставку пятидесяти килограммов сырья на склад.
  4. Предупреждение об аллергенах: «Произведено на линии, где перерабатываются молочные продукты».
  5. Вводный раздел стандарта ISO 23662:2021 с общими терминами растительных продуктов.

Языковая модель получает эти фрагменты и выдает положительное заключение: «Бета-каротин имеет растительное происхождение и подходит для вегетарианцев; продукт соответствует требованиям, с оговоркой об общей производственной линии».

В промышленном комплаенсе такое заключение означает ложноположительную ошибку.

Система упустила главное требование стандарта. По регламентам V-Label и ISO 23662 сам бета-каротин редко вызывает вопросы. Проблема почти всегда заключается в веществе-носителе (carrier): кристаллы бета-каротина растворяются в масле и требуют эмульсии, в которой производители часто используют свиной желатин или глицерин животного происхождения. Для подтверждения соответствия стандарт требует протокол испытаний (CoA) с подтверждением отсутствия животной ДНК ниже порога 0.1 мг/кг.

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

Аналогия с инспектором аттракционов

Представьте инспектора по безопасности, прибывшего проверить американские горки перед открытием парка.

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

Двухэтапный инспектор действует иначе:

  1. Этап 1 (Нормативные правила): Не открывая папки техобслуживания, инспектор изучает нормативный кодекс безопасности: «Соединительный палец №8 должен иметь ультразвуковой сертификат испытания на срез возрастом не более 90 дней; давление в пневмосистеме торможения должно удерживать 120 PSI с падением не более 2% за шесть часов».
  2. Этап 2 (Целевые доказательства): Сформировав точный контрольный список из двух пунктов, инспектор идет на склад и запрашивает только акт ультразвукового контроля пальца №8 и журнал давления пневмосистемы за вчерашнюю смену.

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

Архитектура: разделение норм и фактов

Промышленный RAG для комплаенса делит процесс поиска на две последовательные операции:

Запрос: "Проверить рецептуру бета-каротина №204"
                      │
                      ▼
┌───────────────────────────────────────────────┐
│ ЭТАП 1: Поиск в нормативной базе             │
│ Источники: ISO 23662, V-Label, Vegan Society  │
│                                               │
│ Вывод модели (структурированная схема):        │
│ {                                             │
│   "target_substance": "Бета-каротин",         │
│   "carrier_restrictions": [                   │
│     "Запрещен желатин",                       │
│     "Глицерин только растительный/синтез"     │
│   ],                                          │
│   "mandatory_evidence": ["CoA", "HPLC"],      │
│   "max_animal_dna_ppm": 0.1                   │
│ }                                             │
└───────────────────────────────────────────────┘
                      │
                      ▼ (Генерация целевых фильтров и запросов)
┌───────────────────────────────────────────────┐
│ ЭТАП 2: Поиск доказательств в базе поставщика │
│ Источники: 50 000 паспортов качества (CoA)    │
│ Метафильтры:                                  │
│   batch_id == "LOT-9921"                      │
│   document_type IN ["CoA", "TDS_Addendum"]    │
│ Целевой запрос:                               │
│   "носитель матрица желатин глицерин ВЭЖХ"    │
└───────────────────────────────────────────────┘
                      │
                      ▼
┌───────────────────────────────────────────────┐
│ ЭТАП 3: Детерминированное сопоставление       │
│ Сравнение фактов этапа 2 с критериями этапа 1.│
│ Фиксация неподтвержденных параметров.         │
└───────────────────────────────────────────────┘

Этап 1: Формирование юридического чек-листа

Первичный поиск идет не по документам поставщиков, а по базе нормативных стандартов.

В ней собраны актуальные тексты регламентов: ISO 23662:2021, требования V-Label к сырью и методические указания торговых сетей.

Модель анализирует проверяемый ингредиент и формирует строгую схему требований:

from pydantic import BaseModel, Field

class VerificationCriterion(BaseModel):
    ingredient_name: str
    prohibited_processing_aids: list[str] = Field(
        description="Запрещенные вспомогательные вещества, например костный уголь, желатин"
    )
    carrier_restrictions: list[str] = Field(
        description="Требования к происхождению растворителей и веществ-носителей"
    )
    required_lab_tests: list[str] = Field(
        description="Обязательные лабораторные анализы, например ПЦР, ВЭЖХ"
    )
    max_threshold_ppm: float | None = Field(
        default=None,
        description="Предельно допустимый порог непреднамеренного перекрестного контакта"
    )

Для бета-каротина первый этап фиксирует:

  • prohibited_processing_aids: ["рыбный желатин", "свиной желатин", "костный уголь"]
  • carrier_restrictions: ["глицерин растительного происхождения", "подсолнечный лецитин"]
  • required_lab_tests: ["CoA", "ELISA-тест на молочный белок"]

Этап 2: Точечный поиск доказательств

Получив структурированный чек-лист, система не использует расплывчатые фразы вроде «Является ли бета-каротин веганским?».

Пайплайн строит точный запрос к базе паспортов качества поставщиков:

  1. Жесткая фильтрация по метаданным: Отбор файлов по критериям ingredient_code == "BC-204" и document_tier IN ["CoA", "TDS_Specification"].
  2. Гибридный поиск по выявленным ограничениям: Поиск строго по списку запрещенных носителей и требуемых методик: "Бета-каротин матрица носитель глицерин происхождение растворителя ВЭЖХ жирнокислотный состав"

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

Программный конвейер двухэтапного поиска

class TwoStageCompliancePipeline:
    def __init__(self, standards_retriever, evidence_retriever, criteria_extractor, auditor_llm):
        self.standards_retriever = standards_retriever
        self.evidence_retriever = evidence_retriever
        self.criteria_extractor = criteria_extractor
        self.auditor_llm = auditor_llm

    def audit_ingredient(self, ingredient_name: str, batch_id: str) -> dict:
        # Шаг 1: Поиск требований стандарта
        standards_chunks = self.standards_retriever.search(
            query=f"Требования и ограничения для {ingredient_name}",
            limit=5
        )

        # Шаг 2: Извлечение структурированного чек-листа критериев
        criteria = self.criteria_extractor.extract(
            ingredient=ingredient_name,
            standards_context=standards_chunks
        )

        # Шаг 3: Формирование целевого запроса к документам поставщика
        evidence_query = (
            f"{ingredient_name} вещество-носитель "
            f"{' '.join(criteria.prohibited_processing_aids)} "
            f"{' '.join(criteria.carrier_restrictions)}"
        )

        evidence_chunks = self.evidence_retriever.search(
            query=evidence_query,
            metadata_filter={"batch_id": batch_id, "doc_type": "CoA"},
            limit=5
        )

        # Шаг 4: Сопоставление фактов с требованиями стандарта
        audit_result = self.auditor_llm.evaluate(
            criteria=criteria,
            evidence=evidence_chunks
        )

        return audit_result

Почему последовательный поиск устраняет галлюцинации

Когда модель пытается совместить юридический анализ и поиск фактов в одном шаге, внимание распыляется по второстепенным деталям. Модель цепляется за громкие заявления («100% натуральный продукт») и пропускает отсутствие обязательного лабораторного документа.

Разделение норм и фактов меняет архитектуру проверки:

  • Отсутствие доказательств становится явным: Если нормативный этап требует тест ELISA на отсутствие казеина, а на втором этапе документов с типом CoA не обнаружено, система фиксирует пробел в данных: «Отсутствует обязательный лабораторный сертификат».
  • Прозрачность аудита: Эксперт видит конкретный пункт стандарта, извлеченный на первом шаге, и сопоставленный с ним пункт заводского паспорта качества со второго шага.
  • Экономия задержки: Вместо передачи 50 случайных документов через переранжирование система извлекает 3 четких правила, строит целевой запрос и проверяет 3 релевантных документа.

В пятницу, в восьмой главе, мы разберем Иерархический чанкинг и структуру матриц: почему прямое разбиение текста разрушает сложные таблицы ингредиентов (Сырье → Поставщик → Субингредиент → Носитель) и как метод родительских и дочерних фрагментов сохраняет контекст вложенных строк.


Используете ли вы многоэтапные поисковые пайплайны, где результаты первого запроса задают фильтры метаданных для следующего поиска?

Есть проект на прицеле?

Давайте обсудим, как мы можем помочь.

Есть идея проекта? →