temporality
Изменить страницу↗
Инженерные документы

Priming v2: от каталога знаний к полезным рекомендациям

Статус: реализовано. Документ — план эпохи принятия; что изменилось в текущей реализации после внедрения (IDF-фильтр, семантический тир с квотой, часы переподтверждения, переходы состояний), — в §18.

#1. Цель и ключевой принцип

Подсказки (hints) — это не каталог знаний, а ограниченный по бюджету набор рекомендаций, предназначенных повлиять на конкретное решение агента в текущей задаче.

Из этого принципа следуют требования к системе priming:

Документ фиксирует ревизию текущей реализации, целевую модель отбора и план работ P0/P1/P2. Жизненный цикл Hint (proposed → used/ignored → outcome) и разделение Experience/Knowledge/Skill/Hint определены в docs/knowledge-evolution.md и здесь не пересматриваются.

Связанные документы: knowledge-evolution.md (модель опыта), knowledge-extraction.md (появление Knowledge), knowledge-model.md (сущность Knowledge и связи), living-skills.md §14–16 (связь навыков и знаний), agent-teams.md §9 (программные раны без подсказок).


#2. Ревизия реализации на момент проектирования

На момент написания в коде сосуществовали два механизма формирования подсказок — рабочий контур и параллельный прототип (§2.2). Проблема устранена: прототип удалён, единственный движок — observation.FindHints.

#2.1. Рабочий контур активации (observation/hints.go)

Путь, который реально исполняется в рантайме:

  1. AgentRun (kernel/agent/workflow.go) перед циклом ходов вызывает activity kernel.knowledge_hints с query = input.Prompt; лимит зашит в activity — 8 подсказок. Обращение best-effort: при недоступности пишется memory.read.failed, ран продолжается.
  2. Activity KnowledgeHints (kernel/agent/activities.go) делает POST /v1/observations/hints.
  3. Observation (observation/httpapi/server.go) пишет событие hint.query, вызывает FindHints (observation/hints.go) и пишет hint.offered на каждую отобранную подсказку (с proposition, state, matched_by).
  4. FindHints:
    • единица отбора — отдельное Knowledge, не группа;
    • терминальные состояния (invalidated / superseded / corrected) исключены полностью;
    • матчинг: пересечение Entities (tier 0) → Topics (tier 1) → фраза (tier 2) → термы, ≥2 совпадений (tier 3);
    • одношаговое расширение по Relationships (related:, via:) с tier+1;
    • сортировка детерминированная: matchTier → kindTier (claim < observation) → stateTier (confirmed < proposed < challenged) → KnowledgeID как tie-breaker;
    • cautions для proposed / challenged / at_risk; evidence ≤8, history ≤5.
  5. Workflow вставляет подсказки одним блоком (см. §18; на момент проектирования — отдельным system-сообщением на подсказку).
  6. Обратная связь уже существует: extraction вычисляет hint.used / hint.ignored по отражению терминов пропозиции в ответе модели, а также фиксирует hint.outcome.

Что уже хорошо и сохраняется в v2: единица отбора — отдельное знание; детерминированная сортировка с tie-breaker; исключение терминальных состояний из выдачи; cautions; события полного цикла offered → used/ignored → outcome.

Дефекты рабочего контура:

# Дефект Следствие
Р1 Лимит по количеству (8), токен-бюджета нет вообще; каждая пропозиция вставляется целиком без ограничения Контекст расходуется непредсказуемо; одна длинная пропозиция может съесть больше места, чем пять полезных коротких
Р2 Матчинг бинарный: любые совпавшие Entities дают tier 0 независимо от специфичности; внутри тира нет градации релевантности «gateway» и «temporality» весят одинаково; content-based сравнение фактически отсутствует
Р3 Лексика: точное совпадение токенов, нет словоформ и нормализации идентификаторов; русские стоп-слова неполные («не», «без» — не в списке) Реальные трейсы: matched_by: term:не, term:узел — мусорные совпадения проходят отбор
Р4 Отсутствует сигнал полезности: отбор не знает, помогало ли знание раньше (hint.outcome собирается, но в рейтинг не попадает) Ранжирование по формальным признакам, а не по пользе
Р5 Инвалидированное исключено молча: нет ни отрицательного опыта, ни подсказки о замене Агент повторяет уже опровергнутые подходы
Р6 Нет дедупликации: 8 почти одинаковых observation занимают весь лимит Бюджент набора тратится на повторы
Р7 Контекст агента не учитывается: query = сырой промпт; активные Skills, системный промпт, ранее выданные подсказки не влияют Temporality конкурирует с собственным контекстом агента
Р8 Каждая подсказка — отдельное system-сообщение с полной пропозицией Нет формата cue «правило + условие + основание»; проверяемого контракта knowledge_id нет

#2.2. Параллельный прототип (kernel/priming/priming.go)

Пакет kernel/priming выставлен как GET /v1/agent/priming, но рабочим контуром AgentRun не используется. Все дефекты, из-за которых он возник, подтверждены кодом:

#2.3. Первый долг — консолидация

Два механизма с разной семантикой — это риск расхождения поведения и удвоение стоимости правок. Решение:


#3. Целевая модель отбора

#3.1. Три уровня: Knowledge / Experience Pattern / Cue

Обратная крайность тоже запрещена: семь независимых подсказок об одном и том же случае — это провал бюджета. Нужны индивидуальный рейтинг (§3.3) плюс дедупликация (§9).

#3.2. Этап A — допуск (gating)

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

#3.3. Этап B — ранжирование полезности

Ранжирование отвечает на вопрос «что полезнее именно сейчас». Ранжируются четыре независимых свойства, которые сегодня смешаны в одну сумму:

Свойство Вопрос Источник сигнала
Релевантность текущей задаче похоже ли содержание на то, что решается лексический матч по признакам §4
Достоверность можно ли на это опираться состояние + cautions (вход допуска и подачи, не слагаемое)
Полезность в прошлом помогало ли это раньше агрегированный hint.outcome (§11), а не ReuseCount
Объём свидетельств насколько это проверено количество/свежесть evidence — влияет на формулировку основания, не на рейтинг

Факторы ранжирования:

Веса факторов конфигурируются, детерминированы и версионируются вместе с алгоритмом (§8).


#4. Содержательная релевантность

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

Признак Что искать Где взять
Содержание смысл пропозиции Proposition
Технические сущности библиотеки, API, классы, сервисы, файлы, CLI-флаги Entities, идентификаторы в пропозиции
Операция миграция, рефакторинг, отладка, тестирование, настройка глагольные формы, словарь классов операций
Условия применимости версия, окружение, ограничения, предпосылки пропозиция + evidence
Результат какой эффект подтверждён формулировка + состояние
Контекст org, проект, агент, Skill метаданные знания

#4.1. Нормализация для русского и английского

Текущий contentTokens (lowercase, буквы/цифры/_/-, токены длиннее 1 руны, короткий список стоп-слов) недостаточен: term:не в реальных трейсах — прямое следствие.

Требования к нормализации:

#4.2. Порядок внедрения

  1. Детерминированный лексический матч по признакам с IDF-подобным взвешиванием (P0).
  2. Если бенчмарк (§12) покажет недостаточность — семантическая оценка кандидатов после лексического префильтра (embeddings или LLM), но не векторный retrieval по всей базе сразу (P2).

#5. Бюджеты и формат cue

#5.1. Три отдельных ограничения

Ограничение Назначение Стартовое значение
Общий бюджет подсказок верхняя граница затрат контекста на priming ~600 токенов на запуск
Бюджет одного cue один cue не съедает весь набор ~120 токенов
Лимит элементов в cue группа не превращается в простыню ≤3–5 знаний

Токен-бюджет обязателен: сегодня лимит «8 подсказок» при неограниченной длине пропозиций бюджетом не является.

#5.2. Отбор: максимизация пользы набора

Цель — максимизировать ожидаемую пользу всего набора, а не сумму индивидуальных рейтингов:

max_{S}  Σ_{i∈S} U_i        при ограничениях: Σ tokens(S) ≤ Budget,
                             redundancy(S) ≤ R, |S| ≤ MaxCues

где U_i — оценка полезности cue (§3.3), а не популярности или достоверности.

На первом этапе достаточно жадного отбора: взять лучший cue, пересчитать новизну остальных с учётом уже выбранного (повторы штрафуются), взять следующий, пока бюджет не исчерпан или полезность не упала ниже порога. Сложный оптимизатор не нужен. Если первый cue сообщает важное правило, а следующие пять повторяют его другими словами — они не проходят.

#5.3. Формат cue

Подсказка содержит три вещи:

  1. Правило/вывод — что нужно знать.
  2. Условие применимости — когда это имеет значение.
  3. Основание/статус — насколько проверено и куда обратиться за подробностями (knowledge_id).

Пример:

При изменении API-контракта в этом проекте проверь generated client и
integration tests. Правило подтверждено предыдущими запусками.
knowledge_id=K123

Это полезнее перечисления фактов из одной темы. В P0 cue рендерится шаблонно и детерминированно (пропозиция + условия + маркер состояния + id); LLM-компакция — опциональный P2, допускается только если обгоняет шаблон на бенчмарке.

Инъекция в промпт — одним структурированным блоком с соблюдением бюджета, а не N отдельными system-сообщениями неограниченной длины.


#6. Политика состояний и отрицательный опыт

Инвалидированное знание нельзя выдавать как действующее правило. Но именно оно часто содержит самый ценный опыт: какой подход уже пробовали и почему он оказался ошибочным.

Состояние Режим выдачи
confirmed действующее правило при подходящем контексте
proposed только при высокой релевантности, с явной маркировкой неопределённости («гипотеза, не подтверждена»)
challenged / at_risk не как истина; учитывать при оценке риска, с caution
invalidated / superseded / corrected не как активная инструкция; допускается короткое предупреждение о прежнем способе или ссылка на заменившее знание

Требования:


#7. Учёт существующего контекста агента

Если агенту подключён Skill, подробно описывающий процедуру миграции, не нужно выдавать ту же процедуру как подсказку при каждом запуске. Вход отбора расширяется:

Правила:

Технически: HintRequest пополняется полем контекста (список skill-ids, digest уже выданного); ядро передаёт его при запросе /v1/observations/hints.


#8. Детерминизм

Детерминизм — необходимое условие отладки и A/B-сравнения версий алгоритма.

Единый порядок отбора:

  1. Допуск по scope и lifecycle (§3.2) — стабильный набор кандидатов.
  2. Рейтинг по содержательной релевантности и полезности (§3.3).
  3. Устойчивый tie-breaker: score по убыванию, затем KnowledgeID по возрастанию.
  4. Детерминированный жадный отбор в бюджете (§5.2).

Дополнительно фиксируются: порядок сигналов/элементов внутри cue (например, по времени evidence), правила дедупликации, алгоритм усечения.

Контракт: одинаковый вход и конфигурация → одинаковое множество и порядок cue (отличаться могут только GeneratedAt и идентификаторы). Каждый результат несёт algorithm_version, по которому воспроизводится конфигурация весов и порогов. Текущий FindHints уже детерминирован — это свойство сохраняется и защищается тестом на N прогонов.


#9. Дедупликация и разнообразие

Даже идеальный скоринг выдаст почти-дубликаты: задача про OAuth может получить три формулировки одного правила аутентификации — все релевантны, но вторая и третья почти ничего не добавляют.

Этап diversification после ранжирования:

Разнообразие не самоцель: если задача требует пяти разных правил одной темы, их нельзя разбавлять нерелевантными. Смысловая дедупликация моделью — P2, если детерминированных методов не хватит (по бенчмарку).


#10. Дозагрузка по knowledge_id

Компактная подсказка — точка входа в подробное знание, а не его урезанная копия.

  1. Priming возвращает короткий cue с knowledge_id.
  2. Агент оценивает, достаточно ли этого для решения.
  3. Если нужны обоснование или детали — запрашивает полное Knowledge по ID через инструмент knowledge_lookup (новый агентский инструмент; activity kernel.knowledge_lookup уже существует как внутренняя — её нужно вынести в доступный агенту инструмент с тем же контрактом).
  4. Полное Knowledge содержит proposition, evidence, состояние, scope и связи (включая замены).
  5. Дозагрузка проходит те же проверки авторизации и доступа к проекту, что и обычное чтение Knowledge.

Правила:

Сегодня дозагрузку подменяет доставка evidence (≤8) и history (≤5) внутри структуры Hint, но в промпт они не попадают, а инструмента у агента нет — контракт разорван.


#11. Замкнутый цикл полезности

Инфраструктура обратной связи уже есть и является преимуществом Temporality:

Что добавить:


#12. Benchmark качества

Главная недостающая вещь: никакие существующие тесты (priming_test.go, server_test.go) не доказывают, что подсказки помогают решать задачи.

#12.1. Корпус

Постоянный набор из 30–50 реальных задач из запусков Temporality (затравка — сценарии из фикстур benchmark-корпуса). Для каждой задачи фиксируется:

Формат — JSON-фикстуры в репозитории; прогон — командой/тестом в CI.

#12.2. Метрики

Метрика Что измеряет
Precision@K / Precision@Budget доля выбранных подсказок, действительно относящихся к задаче
Recall@Budget сколько из известных полезных подсказок передано в пределах бюджета
Redundancy ratio доля бюджета, потраченная на повторяющуюся информацию
Stale / invalidated leakage как часто устаревшее знание попадает в контекст как действующая инструкция
Token efficiency полезных подсказок на единицу токен-бюджета
Behavioral impact изменилось ли поведение и результат агента благодаря подсказкам

Behavioral impact — важнейшая и самая сложная метрика: одинаковые задачи с priming и без, одна модель и инструменты, несколько повторов для стохастики. Качество подсказки ≠ улучшение результата: высокая точность retrieval не доказывает, что агент воспользовался подсказкой.

#12.3. Правило сравнения

Каждое изменение алгоритма (веса, нормализация, пороги) прогоняется на корпусе; отчёт сравнивает версии по всем метрикам. Без улучшения на корпусе изменение не принимается.


#13. Наблюдаемость


#14. План работ

#Статус реализации (2026-10-10)

Происхождение реализации: P0 доставлена в main одной веткой, P1 — последующими коммитами (diversification, replacement, usefulness loop + benchmark-корпус).

Сделано в рамках P0:

Сделано в рамках P1 (завершено, HintsAlgorithmVersion → lexical-entity-topic.v3):

Попутно исправлено: RenderHintBlock не учитывал руны-разделители \n при склейке блока — блок мог превысить бюджет на ~1 токен; теперь каждая строка несёт свой сепаратор (ceil субаддитивен, инвариант доказуем), RenderResult.KeptIDs открывает попозиционный учёт.

Не сделано: P2 целиком (семантика/LLM-оценка/адаптация весов — только если бенчмарк покажет потолок текущего движка).

#P0 — базовая семантика (консолидация и контракт)

  1. Консолидация: единственный движок отбора — FindHints v2 в observation; kernel/priming выводится из рантайма (эндпоинт — удалить или проксировать).
  2. Разделить допуск и рейтинг: gating-инварианты (§3.2) отдельно от ранжирования (§3.3); исключить выдачу инвалидированного как действующего правила.
  3. Ранжировать отдельные Knowledge по содержанию: признаки §4, нормализация ru/en (§4.1), IDF-взвешивание, расширение стоп-слов, сегментация идентификаторов.
  4. Детерминированная сортировка с tie-breaker + algorithm_version в результате (тест на воспроизводимость).
  5. Бюджеты: общий (~600 токенов), на cue (~120), лимит элементов; жадный отбор по marginal utility.
  6. Формат cue (правило + условие + статус + knowledge_id) и инъекция одним блоком в промпт.
  7. Связь замены: типизированный replaces/superseded_by заполняется при инвалидации; замена предлагается вместо исключения.

#P1 — полезность набора

  1. Дедупликация и разнообразие (точная, Jaccard, лимит на группу) — §9. ✅
  2. Учёт активных Skills и уже выданного контекста — §7. ✅
  3. Инструмент knowledge_lookup для агента — §10. ✅
  4. Benchmark-корпус 30–50 задач, метрики §12, сравнение версий в CI. ✅
  5. Замыкание полезности: агрегированный hint.outcome как фактор B4 — §11. ✅
  6. Опционально: Experience Pattern как слой подачи — дескоупнуто (см. статус выше).

#P2 — дорогие методы (только если оправданы бенчмарком)

  1. Семантическое ранжирование кандидатов после лексического префильтра.
  2. LLM-оценка полезности кандидатов.
  3. Смысловая дедупликация моделью.
  4. Адаптация весов стратегии по исходам применений.
  5. LLM-компакция cue (против шаблонной — решает бенчмарк).

#15. Критерии готовности

P0:

P1:

Общие:


#16. Что не входит в скоуп


#17. Открытые вопросы


#18. Что изменилось после внедрения (текущее состояние)

План выше выполнен, но механика выросла за его пределы:

Полезность (B4), новизна (B5), дедупликация и бюджеты — как в плане.