Design note — адаптивное планирование (§26, §24)¶
Статус: спайк (реализовано) · Область: хук на runtime, чтобы реактор мог выбирать среди кандидатов; жёсткие правила отсекают, ранжирование только упорядочивает, LLM разруливает ничьи редко.
Почему это ложится на кодовую базу¶
Runtime — это реактивный fan-out: arun_once строит список кандидатов work
(agent×event) и запускает все матчеры (§24). У вопроса «какой шаг сильнее
всего снижает неопределённость» сегодня нет дома — хук это один вызов в
arun_once перед _dispatch и перед budget-ограничением (порядок важен и
тогда, когда budget обрезает список):
По умолчанию None → текущее поведение; примитивы не тронуты.
Контракт политики (три стадии + два guard'а)¶
filter (жёсткие правила → МОГУТ отсеять) → rank (метрика → только порядок) → LLM-разруливание (редко)
- filter — доменные правила отсекают кандидатов, которые вообще не подходят, так что они никогда не доходят до ранжирования (например, опровергнутая гипотеза, или capability 'b' не разрешена для тега 'x').
- rank — метрика упорядочивает кандидатов; она никогда не отсеивает (§26:
не каждое решение нуждается в LLM). Опциональный
rank_limit=kобрезает до top-k после ранжирования (закреплённые HITL-кандидаты никогда не учитываются; непустой ранжированный список никогда не опустошается → нет голодания). - LLM-разруливание — только когда разрыв метрики между топ-2 ≤
llm_tie_breakи есть модель; один вызовstructured_llmупорядочивает пару. Офлайн → пропускается. - HITL pin — любой кандидат, который разрешает отвеченный
PendingQuestion, принудительно ставится в начало (§60): подтверждение человека никогда не проигрывает ранжированию. - Fallback против голодания — если фильтрация опустошила бы набор кандидатов, сохраняется исходный список: единственный путь к прогрессу обязан выжить.
Адаптивность возникает ограниченно по усилиям: каждая итерация переранжирует относительно свежего контекста, так что события самого ценного кандидата двигают следующий раунд (§24).
API¶
from reactifact import Runtime
from reactifact.scheduler import uncertainty_policy
runtime = Runtime(
ctx,
agents=[...],
scheduler=uncertainty_policy(
rules=[not_refuted], # Rule = (context, agent, event) -> bool
metric=support_split, # Metric = (context, agent, event) -> float
llm_tie_break=0.05, # LLM при почти-ничьей (редко), system-промпт владеет приложение
rank_limit=1, # опциональное "выбрать top-k" (безопасно: никогда не опустошает)
),
)
Agent.capabilities (§25) — метаданные, которые политика и LLM-разруливание
используют для описания кандидатов; сами по себе они ничего не меняют.
reactifact.scheduler.relation_balance_metric — встроенная uncertainty-driven
Metric: ранжирует кандидата по тому, насколько несимметричны связи
supports/contradicts у артефакта, к которому относится его событие —
детерминированно, без привязки к провайдеру, тот же структурный сигнал,
который examples/medic_lab раньше считал вручную только для отчёта
(produce/evaluate.py). medic_lab теперь подключает его через собственный
Runtime(scheduler=medic_lab_scheduler()), так что самая противоречивая
открытая гипотеза реально исследуется первой, а не просто оказывается
наверху в итоговом отчёте.
Чем это НЕ является¶
- Не альтернативный исполнитель — графа путей нет, runtime по-прежнему реагирует на события.
- Не «обязательно выбрать одного» — только ранжирование; отсев — работа filter, подстрахованная fallback'ом против голодания.
- Не «LLM везде» — только ничьи, с бюджетом, безопасно офлайн.
- Системный промпт для разруливания принадлежит приложению: передайте
llm_system=вuncertainty_policy/Scheduler(по умолчаниюDEFAULT_TIE_BREAK_SYSTEM), чтобы решение формулировалось в терминах домена.
Что поставляется со спайком¶
reactifact/scheduler.py—Scheduler,uncertainty_policy,relation_balance_metric, типы.- Хук в runtime (параметр
scheduler=),Agent.capabilities. examples/adaptive— два конкурирующих «художника» + HITL-подтверждение.examples/medic_lab—medic_lab_scheduler()подключаетrelation_balance_metricи в консольный (chat.py), и в веб (api/chat.py) вход.tests/test_adaptive.py— ранжирование, отсев, fallback, LLM-разруливание, пропуск офлайн, HITL pin, прогон демо,relation_balance_metric(веса, кастомные имена связей, сквозное планирование).tests/test_medic_lab.py—medic_lab_scheduler()приоритизирует более противоречивую открытую гипотезу.