Files
contracts/History/topics/prompt-strategy.md
T

11 KiB
Raw Blame History

Prompt Management Strategy

Дата: 2026-06-23 | Версия: v1.0 | Контекст: v1.0.109, обсуждение архитектуры промптов


А. Несколько промптов — зачем и как

Смешиваются две разные потребности — их нельзя путать:

1. Версионирование одного промпта (ОБЯЗАТЕЛЬНО)

Это не «несколько промптов», а история эволюции одного.

Почему критично:

  • prompt_version уже кладётся в spec_events (provenance, Opus раунд 2).
  • Значит промпт обязан быть иммутабельным — правка «на месте» сломает трассировку: старые события будут ссылаться на текст, которого больше нет.
  • Правка = новая версия, а не перезапись. Откат, аудит «какая версия породила какой результат», сравнение версий — бесплатно.

2. Несколько РАЗНЫХ промптов одновременно

Сценарий Вердикт
По роли в пайплайне — разные LLM-вызовы (извлечение услуг vs сравнение vs резолв имён) У каждого свой промпт. Настоящая причина «несколько» — по задаче.
Варианты для эксперимента — форкнул активный, сделал строже, прогнал на тестах, сравнил Loop «дублировать → изменить → протестировать → активировать» — правильно.
Каталог из 20 промптов «на всякий случай» Ловушка. Для узкого домена (colocation/ЦОД) нужен ОДИН хороший промпт на задачу.

Рекомендуемая модель: prompt-as-version (не prompt-as-document)

Одна таблица, один активный на role, вся история — строки:

Поле Тип Смысл
id UUID PK Версия (иммутабельная)
role VARCHAR Шаг пайплайна: extract, diff
name VARCHAR Человеческое имя («default-v3», «strict-prices»)
body TEXT Тело промпта с плейсхолдерами
parent_id UUID FK→prompts.id От какой версии форкнут
is_active BOOLEAN UNIQUE(role, is_active) с частичным индексом WHERE is_active
created_at TIMESTAMP
created_by VARCHAR Мульти-юзер
notes TEXT Что изменили и зачем

Операции:

  • Править = INSERT новой строки с parent_id на предыдущую. Не UPDATE.
  • Активировать = переключить is_active (старая теряет флаг).
  • Дублировать = копия под новым name (форк).
  • Откат = активировать старую версию.

Никогда не UPDATE текста на месте.


Б. Как составлять промпт

Стартовый шаблон — ОБЯЗАТЕЛЕН

Пустое поле ввода — катастрофа для качества. Всегда форкать от выверенного дефолта, не с нуля.

Структура (8 секций, порядок важен)

Для доменной задачи без structural output (gpt-oss-120b):

┌─────────────────────────────────────────────┐
│ 1. РОЛЬ / КОНТЕКСТ                          │
│    «ты эксперт по договорам colocation       │
│     и облачных услуг ЦОД»                    │
├─────────────────────────────────────────────┤
│ 2. ЗАДАЧА                                   │
│    «сравни текущую спецификацию с документом,│
│     верни операции изменений»                │
├─────────────────────────────────────────────┤
│ 3. ДОМЕННЫЙ ГЛОССАРИЙ                       │
│    стойко-место, кВт мощности, colocation,   │
│    единицы измерения, типы услуг.            │
│    Без этого модель путает домен.            │
├─────────────────────────────────────────────┤
│ 4. ФОРМАТ ВХОДА                             │
│    Как подаётся spec_current (с ID r1..rN),  │
│    как подаётся текст документа.             │
├─────────────────────────────────────────────┤
│ 5. КОНТРАКТ ВЫВОДА                          │
│    Строгая JSON-схема ops: поля, типы,       │
│    обязательность. КРИТИЧНО — structural     │
│    output нет, схема держится промптом.      │
├─────────────────────────────────────────────┤
│ 6. ПРАВИЛА / ОГРАНИЧЕНИЯ                    │
│    «ссылайся только на id из spec_current»,  │
│    «верни source_quote», «верни confidence», │
│    «name существующих строк не переписывай»  │
├─────────────────────────────────────────────┤
│ 7. FEW-SHOT ПРИМЕРЫ (2-3)                   │
│    ⭐ САМЫЙ МОЩНЫЙ РЫЧАГ для бесплатной      │
│    модели без fine-tune. Примеры учат и      │
│    формату, и поведению лучше инструкций.    │
│    Вход→Выход на ВАШЕМ домене (ЦОД).        │
├─────────────────────────────────────────────┤
│ 8. EDGE-CASES                               │
│    Как помечать неоднозначность, что делать  │
│    при low-confidence.                       │
└─────────────────────────────────────────────┘

Принцип разделения: статика vs рантайм

[версионируемая часть — в БД]     [рантайм-инъекция — в коде]
роль + глоссарий + правила     +  {spec_current} + {document_text}
+ few-shot + контракт вывода
  • Статическая инструкция (секции 1-8) → версионируется в prompts.body.
  • Динамические данные ({spec_current}, {document_text}, {date}) → подставляются в рантайме через плейсхолдеры.
  • В БД хранится тело промпта с плейсхолдерами, не с конкретными данными.

В. Prompt CI — как с этим работать

 ┌──────────┐    ┌──────────┐    ┌───────────┐    ┌──────────┐
 │ Дублировать │ → │ Изменить  │ → │ Прогнать на │ → │ Активировать │
 │ (форк)     │    │ (новая v) │    │ golden-наборе│   │ (is_active) │
 └──────────┘    └──────────┘    └───────────┘    └──────────┘
  1. Форкнуть активный промпт → новый id, is_active=false
  2. Изменить тело
  3. Прогнать на golden-наборе (3-5 реальных ДС с известным результатом)
  4. Сравнить метрики (precision/recall по ops)
  5. Если лучше — активировать. Если хуже — оставить как эксперимент или удалить.

Г. Текущее состояние (v1.0.109)

Промпты жёстко зашиты в llm_prompt.py:

  • _build_initial() — для первого документа
  • _build_diff() — для сравнения (основной)

Что уже хорошо:

  • JSON-контракт вывода описан
  • target_id (r1..rN) вместо target_hash
  • Правила: mode full_replace, UPDATE только изменённые поля, UNRESOLVED для неоднозначного

Чего не хватает (по приоритету):

  1. Few-shot примеры на домене ЦОД — самый большой рычаг качества
  2. Доменный глоссарий — чтобы модель понимала единицы измерения и термины
  3. source_quote в контракте вывода — для provenance
  4. confidence в контракте вывода — самооценка модели
  5. Edge-cases инструкция — как вести себя при неоднозначности

Д. План миграции (если делать)

Шаг Что Сложность
1 Таблица prompts в PostgreSQL (Lucee datasource baza) Низкая
2 CRUD в api.cfm для prompts (list, get, create, set_active) Средняя
3 llm_prompt.py → читает активный промпт из Lucee API вместо хардкода Средняя
4 prompt_version в spec_events — ссылка на prompts.id Низкая
5 UI для prompts в index.cfm (список версий, редактор, активация) Высокая
6 Golden-набор: 3-5 ДС + эталонные ops Ручная работа
7 Prompt CI: скрипт прогона на golden-наборе + сравнение метрик Средняя

Первый практический шаг (максимум пользы, минимум кода): добавить few-shot примеры в текущие промпты прямо в llm_prompt.py, не дожидаясь таблицы prompts.