Контекст: обогащение

NOTE

Статус: Target design. Документ описывает целевую доменную модель. Соответствующий код реализован частично (см. backend/internal/core/) или пока не начат. Правила маркировки — в 50-processes/documentation-standard.md.

Назначение

Дополняет недостающие данные канонического товара: извлекает характеристики из описаний, генерирует/улучшает контент (описание, тэги), создаёт embeddings для семантического поиска. Использует LLM, rule-engines, периодически — оператора.

Enrichment — только источник для Catalog (через события). Он сам не правит canonical напрямую.

Главный смысл

Enrichment предлагает значения с confidence и source, но НИКОГДА не объявляет их critical attribute без явной верификации (manual или multi-supplier consensus). AI-данные не попадают в identity_signature без apply-policy от Catalog.

Агрегаты / сущности / value objects

ИмяТипНазначение
EnrichmentTask🟨 AggregateЗадача обогащения для конкретного canonical / offer / батча.
EnrichmentResultVOИзвлечённые поля + confidence + source.
EnrichmentSourceVO enumllm / rule_calculated / manual / vendor_doc.
LlmModelRefVO(model_name, version, prompt_hash) — для воспроизводимости.
EmbeddingVectorVODense vector для семантического поиска.
EnrichmentScopeVO(target_kind: canonical | offer, target_id, fields[]).
EnrichmentPolicyEКонфигурация: какие поля чем обогащать.

Доменные события

СобытиеПричина
ЗадачаОбогащенияСоздана (EnrichmentTaskCreated)Policy: пустые critical attrs / новый canonical
ХарактеристикаОбогащенаAI (CharacteristicEnrichedByAI)LLM извлёк значение из описания
ЗначениеРассчитано (ValueCalculated)Rule-engine: например, объём из габаритов
КонтентСгенерирован (ContentGenerated)Описание / SEO-текст / медиа alt
EmbeddingПостроен (EmbeddingComputed)Vector для нового описания
ОбогащениеОтклонено (EnrichmentRejected)Низкая confidence, конфликт с verified value
ВерификацияТребуется (EnrichmentReviewRequired)Policy: critical attr хочет manual confirm

Команды

КомандаАкторЦелевой агрегатРезультат
СоздатьЗадачуОбогащения (CreateEnrichmentTask)PolicyEnrichmentTaskEnrichmentTaskCreated
ПрименитьLLMИзвлечение (RunLlmExtraction)WorkerEnrichmentTaskCharacteristicEnrichedByAI / EnrichmentRejected
ПостроитьEmbedding (ComputeEmbedding)WorkerEmbeddingComputed
ПрименитьПравило (ApplyRule)WorkerValueCalculated
ОтправитьНаAIПроверку (SendForModeration)PolicyEnrichmentTaskEnrichmentReviewRequired (publish для Moderation BC)
ПрименитьРешениеМодерации (ApplyModerationDecision)Moderation BC consumerEnrichmentTaskCharacteristicEnrichedByAI (accepted) или EnrichmentRejected + ack

Политики

ТриггерРеакция
CanonicalCreated (Catalog) + есть пустые critical attrsCreateEnrichmentTask{kind=extract_critical}
OfferCharacteristicsUpdated (Offers) + новые поля в описанииCreateEnrichmentTask{kind=extract_supplementary}
EnrichmentTaskCreated + поля можно посчитать формулойApplyRule (раньше LLM)
EnrichmentTaskCreated + поля только в текстеRunLlmExtraction
CharacteristicEnrichedByAI + critical attrSendForModeration → AI-агент enrichment_critical_attr_review в Moderation BC
CharacteristicEnrichedByAI + non-critical + confidence ≥ threshold→ publish событие, Catalog применит без модерации
ProposedAction(AcceptEnrichment) от ModerationApplyModerationDecision → emit CharacteristicEnrichedByAI для Catalog + ack
ContentUpdated (Catalog)ComputeEmbedding

Read-модели

  • 🟩 enrichment_task_queue (PG).
  • 🟩 enrichment_history (CH) — для audit и обучения моделей.
  • 🟩 embedding_index (Elasticsearch dense_vector / pgvector) — для Search semantic.

Инварианты

  1. AI-значения не попадают в identity_signature (см. Catalog invariants).
  2. Каждый EnrichmentResult имеет (source, confidence, model_ref) — иначе rejected.
  3. Изменение prompt или model_version логируется в LlmModelRef. Производит pre-prod evaluation перед раскаткой.
  4. Если новое значение конфликтует с manually verified — EnrichmentRejected + alert.
  5. Embedding пересчитывается при изменении description или characteristics canonical’а.

Интеграционные события (публикуем)

Топик: enrichment.events.v1. Partition key: target_id.

ИмяКогда
CharacteristicEnrichedByAILLM-извлечение принято (либо напрямую non-critical, либо после Moderation)
ValueCalculatedПравило отработало
ContentGeneratedСгенерированный текст принят
EmbeddingComputedVector готов
EnrichmentReviewRequiredКейс enrichment_critical_attr_review для Moderation BC
DecisionApplied{case_id}Ack для Moderation после применения её ProposedAction

Подписанные интеграционные события

ИсточникСобытиеРеакция
CatalogCanonicalCreatedПолное обогащение
CatalogCanonicalCharacteristicsChangedEmbedding rebuild + пересмотр
OffersOfferCharacteristicsUpdatedИзвлечение из новых описаний
MatchingMatchDecided=probableEmbedding similarity как second signal
ModerationProposedAction(AcceptEnrichment|RejectEnrichment) для case.kind=enrichment_critical_attr_reviewApplyModerationDecision

Связи в context map

BCПаттернНазначение
CatalogPL (Enrichment → Catalog)Публикует CharacteristicEnrichedByAI; Catalog применяет через policy
SearchPL (Enrichment → Search)Публикует embeddings
MatchingOHS (Matching consumes embedding similarity)Сигнал для probable
OffersCustomer/Supplier (Offers — supplier)Слушает изменения товарных канв
ModerationCustomer/Supplier (Enrichment → Moderation, обратно через PL ProposedAction)Все ручные проверки critical attrs делегированы AI-агентам
ModerationSK (LlmModelRef)Общий kernel для model versioning

Мини event storming

flowchart LR
    subgraph C["Catalog"]
        E1["🟧 CanonicalCreated"]
    end
    subgraph EN["Enrichment"]
        P1["🟪 Policy: пустые critical?"]
        CMD1["🟦 CreateEnrichmentTask"]
        T["🟨 EnrichmentTask"]
        E2["🟧 EnrichmentTaskCreated"]
        D1{"🟪 Можно правилом?"}
        CMD2["🟦 ApplyRule"]
        CMD3["🟦 RunLlmExtraction"]
        E3["🟧 CharacteristicEnrichedByAI"]
        E4["🟧 EmbeddingComputed"]
    end
    subgraph M["Matching"]
        SM["🟪 Policy: signal для probable"]
    end
    subgraph S["Search"]
        IDX["🟩 embedding_index"]
    end

    E1 -.PL.-> P1 --> CMD1 --> T --> E2
    E2 --> D1
    D1 -->|да| CMD2
    D1 -->|нет| CMD3
    CMD3 --> E3
    E3 -.PL.-> C
    E3 -.signal.-> SM
    E1 --> CMD3
    CMD3 -.parallel.-> E4
    E4 --> IDX

Связанные файлы