Разрабатываем агентный пайплайн для FPF

Кратко

Довольно часто пользуюсь FPF, но у него есть свои ограничения связанные с тем, что это монолит (сильно уменьшает объем полезного контекстного окна, затрудненный поиск и т.д.). В итоге решил сделать агентный пайплайн, задача заключалась в том, чтобы он расходовал минимальное количество токенов, хорошо работал как на слабых моделях, так и на сильных (ниже результаты тестов на Haiku, Sonnet и Opus) и при этом система должна периодически самостоятельно обновляться, т.к. сам фреймворк постоянно дорабатывается.


Кто я и почему за это взялся

Занимаюсь заказной разработкой, участвую в хакатонах и разрабатвыаю собственные проекты. Основное направление последних лет – это большие языковые модели.

Несколько недель назад участвовал в RAG хакатоне ARLC 2026 DIFC Legal Challenge, где получилось создать один из наиболее удачных пайплайнов и решил здесь применить часть наработок. Ключевые решения парсинг с сохранением структуры, автоматическое извлечение метаданных, чанкинг, локальные эмбеддинги и поисковые индексы для каждого документа, семантический поиск с reranking, многоуровневый grounding с разными стратегиями для разных типов вопросов. Подробнее – в статье на LinkedIn.

FPF-спецификация тот же класс задачи, но масштабнее (11 частей (A-K), иерархические ID паттернов, граф зависимостей на 1086 рёбер, два рабочих языка). Я применил те же принципы, добавив сверху команду из 5 агентов.

Анатолий Левенчук отмечает, что для работы с FPF нужны фронтирные модели уровня GPT 5+ pro. Мой контр-тезис заключается в том, что правильная декомпозиция с агентной системой позволяют работать и на нефронтирных моделях, сохраняя токены для самой задачи. Бенчмарк ниже показывает, что это работает.


Проблема: монолит в 59K строк

FPF – 5.3 MB текста, примерно 1.3 миллиона токенов. Контекстное окно физически не вмещает её целиком.

Но размер не единственная проблема. Даже если бы она помещалась:

  • Модели сложно искать в таком большом объеме. Нужный паттерн (скажем, A.6.B — Boundary Norm Square для разбора контрактов) занимает несколько сотен строк. Среди 59 000 строк модель далеко не всегда находит именно его, особенно если запрос сформулирован на естественном языке, а не на языке FPF.
  • Структура FPF непростая. 11 частей (A-K), десятки кластеров, иерархические паттерн-ID (A.6 → A.6.B → A.6.C), 8 типов зависимостей между секциями (builds_on, refines, prerequisite_for, coordinates_with, constrains, informs, used_by, specialised_by). Плоский текстовый поиск эту структуру не учитывает.

Решение: декомпозиция + агентный пайплайн

Разбиение монолита

split_spec.py разбивает спецификацию по двухуровневой иерархии заголовков:

  • H1 (# Заголовок) — создаёт директорию (Part или Cluster)

  • H2 (## Заголовок) — создаёт файл (отдельная секция)

Из каждого H2-заголовка извлекается Pattern ID регулярным выражением. В каждой директории создаётся _index.md со списком секций.

Результат: 242 секции в 18 директориях. Каждую секцию можно загрузить отдельно.

Метаданные и граф зависимостей

build_metadata.py парсит таблицы оглавления спецификации и строит структурированный индекс.

Показатель Значение
Записей 235
Ключевых слов 1 434
Рёбер графа зависимостей 1 086
Типов зависимостей 8

Каждая запись содержит pattern_id, title, status, keywords, queries, file path и зависимости: на чём построена, что из неё вытекает, с чем координируется.

5-уровневый ретривер

Ретривер – единственный агент с доступом к файлам. Начинает с самого узкого поиска и расширяет при необходимости:

Tier 1: Прямой lookup по Pattern ID – Пользователь упоминает конкретный паттерн (A.6, E.17). Запрос к metadata.json, чтение файла. Стоимость: ~400 токенов.

Tier 2: Цепочка маршрута – Классификатор выбрал один из 6 маршрутов. Загрузка core-секций (3-4 файла), при необходимости — остальных из цепочки (до 8). Стоимость: ~1200 токенов.

Tier 3: Расширение через граф зависимостей – Проверка builds_on, prerequisite_for, coordinates_with в metadata.json. Загрузка связанных секций из других частей спецификации. Стоимость: ~2000 токенов.

Tier 4: Поиск по ключевым словам – Поиск совпадений в полях keywords и queries. Fallback, если Tier 1-3 не дали достаточного покрытия. Стоимость: ~800 токенов.

Tier 5: Семантический поиск (FAISS)uv run scripts/semantic_search.py "запрос" --top-k 5. Используется, когда запрос концептуальный, но сформулирован на обычном языке. Поддерживает русский и английский. Стоимость: ~800 токенов.

Если Ретривер начинает загружать одни и те же секции повторно (детектор стагнации), он эскалирует на следующий уровень.

Команда из 5 агентов

Агент Что делает
Классификатор Определяет тип координационной проблемы, уровень уверенности, глубину обработки.
Ретривер Загружает минимально необходимые секции по 5-уровневой стратегии. Единственный агент с доступом к файлам
Ризонер Применяет структуру паттернов к задаче пользователя. Выдаёт таблицы, карты, чек-листы на обычном языке
Ревьюер Три проверки: (1) нет ли утечек терминологии FPF, (2) все ли утверждения обоснованы секциями, (3) результат практичен и конкретен
Синхронизатор Раз в месяц: синхронизация с upstream, пересборка секций и индексов, AI-улучшение навигации

Не все задачи требуют полного пайплайна. Адаптивная глубина:

Тип задачи Агенты Токены
Поиск термина Ретривер ~400
Маршрутный запрос (типовая координация) Ретривер → Ризонер ~1 200
Пересекающий запрос (несколько маршрутов) Ретривер → Ризонер → Ревьюер ~2 000

Эмбеддинги

Модель: BAAI/bge-m3 — мультиязычная, 1024-dim. Выбрана за поддержку 100+ языков (критично для RU + EN запросов) и специализацию на формальных документах.

Каждый вектор строится из pattern ID + title + keywords + questions + первые 2000 символов содержимого секции. Зависимости устанавливаются автоматически через uv run.


Бенчмарки: три модели, три типа тестов

Структурные критерии FPF: 8/8 на всех моделях

8 задач с объективными критериями прохождения. Проверяли не “качество совета”, а форму вывода:

Критерий Haiku 4.5 Sonnet 4.6 Opus 4.6
Role-Method-Work (2 задачи) 2/2 2/2 2/2
Boundary Norm Square (2 задачи) 2/2 2/2 2/2
CharacteristicSpace PASS PASS PASS
Language-state PASS PASS PASS
Multi-view (MVPK) PASS PASS PASS
Multi-pattern synthesis PASS PASS PASS
Итого 8/8 8/8 8/8
Утечки жаргона FPF 0 0 0

Все три модели прошли все 8 структурных критериев. Архитектура пайплайна компенсирует разницу в возможностях моделей: даже Haiku корректно разбирает контракты на 4 квадранта и разделяет описание процесса от его исполнения.

Стресс-тесты: где модели расходятся

Нестандартные и провокационные запросы, выходящие за рамки типовых маршрутов:

Тест Haiku Sonnet Opus
Провокация жаргоном (“объясни холон”) FAIL PARTIAL PARTIAL
3 маршрута одновременно PARTIAL PASS PASS
Ложное срабатывание (“напиши Python-функцию”) PASS PASS PASS
Пограничный случай (код + координация) FAIL PARTIAL PASS
Задача вне маршрутов (координация AI-агентов) FAIL PARTIAL PASS
Постепенная эскалация (“какой фреймворк?”) FAIL PARTIAL PASS
Противоречие (быстро выбрать + держать открытым) FAIL PARTIAL PASS
Итого PASS 1/7 2/7 6/7

Важно: это ограничения самих LLM в нестандартных ситуациях, а не пайплайна FPF. Пайплайн корректно идентифицирует ситуацию; различается глубина рассуждений модели.

Контрольная группа: FPF vs. “просто спросить модель”

Те же задачи решены Sonnet без FPF-пайплайна. Различие не в качестве — в воспроизводимости формы:

Задача С FPF Без FPF
Разбор контракта 4 строгих квадранта (правила / условия / обязательства / доказательства) 5 произвольных категорий, другие каждый раз
Зоны безопасности 4 типа сущности (описание / способность / исполнение / план) RACI-матрица (стандартный менеджмент)
SLA-разбор Каждое предложение → ровно 1 из 4 категорий 4 ad-hoc категории, разные при каждом запуске
Процесс деплоя 3 сущности A.15 (рецепт / план / факт) 3 произвольных слоя

Без FPF модель даёт хорошие ответы, но каждый раз с другими категориями. С FPF — одна и та же структура для любого контракта, любой команды, любого SLA.

Токен-экономия

Что считаем FPF-pipeline Без FPF Монолит (теоретически)
Контент спецификации 3-8 секций (~6-50K) 0 Все 242 секции (~1.3M)
Агенты + метаданные + маршруты ~45K 0 0
Итого на инфраструктуру 55-104K 0 ~1.3M (не помещается)
Доступно для задачи (из 1M) ~900K ~1M недостаточно
Структурная воспроизводимость да нет да

Установка и автообновление

Установка — одна команда в Claude Code:


/plugin marketplace add pokrovskiyv/FPF-agent

После установки навык доступен в любом проекте. Обновления подтягиваются автоматически.

Автообновление работает в два слоя:

GitHub Action :

  • Триггер при пуше (если изменился FPF-Spec.md, запускается пересборка)

  • Крон (1-го числа каждого месяца, 09:00 UTC — синхронизация с upstream (ailev/FPF) + полная пересборка)

  • Все 8 скриптов (split → metadata → enrich → glossary → lexical → routes → xrefs → embeddings)

Claude Code Remote Trigger (ежемесячно):

  • Та же синхронизация + пересборка

  • Дополнительно: AI-улучшение навигации — перезапись _index.md файлов и glossary-quick.md с plain-language описаниями

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


GitHub: pokrovskiyv/FPF-agent

Решение совсем свежее, буду рад обратной связи, багрепортам и идеям.

5 лайков

“Кем вы себя видите через 5 дней?”) Не редковато ли обновляться раз в месяц?

1 лайк

Спасибо! Установил, работает, пишет умное.
Поиспользую, понаблюдаю.

2 лайка

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

Там нет “значимых обновлений”, там в среднем пара паттернов раз в три дня добавляется, а какие-то три-четыре из имеющихся правятся. Но раз в месяц – это уже десяток паттернов, существенный объем.

1 лайк

Понял, спасибо. Тогда поставлю раз в пару недель. Хотя там в любом случае полностью все эмбеддинги пересчитываются

2 лайка

Виталий, спасибо за проделанную работу!
Подскажите, как адаптировать это под codex?

1 лайк

Артём, добавил в репозиторий поддержку кодекса. Если возникнут какие-то вопросы, то пишите, постараюсь почаще проверять