Skip to content

Modelo de domínio

Objetos centrais

SeriesKey

Representa a identidade canônica de uma série para treino, promoção, versionamento, artefatos e forecast.

Invariantes:

  • tenant, series_id e dimensões não podem ser nulos;
  • series_kind declara o nível semântico da série, como sku_store, category_store ou outro agrupamento definido pela plataforma;
  • dimensions guarda os identificadores que formam a série, como SKU, loja, categoria, região ou agrupamentos comerciais;
  • grain faz parte da identidade estável da série;
  • o valor precisa ser seguro para uso em persistência, logs e nomes derivados.

SeriesKey não é mais limitado a sku_id + store_id. Esse par continua sendo apenas um tipo de série (sku_store) validado no contrato canônico bruto de demanda. Antes do treino, o frame canônico é aceito por uma DemandValidationRuleSet e projetado explicitamente por uma SeriesProjectionRecipe; não existe fallback implícito para sku_store nem atalho por campo legado. Séries agregadas, como categoria em uma loja, usam o mesmo objeto com series_kind e dimensões próprias, mantendo treino, promoção, artefatos e auditoria independentes por série.

Demanda para treino

Neste bounded context, o processo de treino de forecast faz parte do problema de negócio. Por isso, o domínio de demanda não fica só com SeriesKey: ele também carrega os conceitos semânticos que organizam esse treino offline.

Objetos centrais em src/domain/demand/training.py:

  • DemandSnapshotManifest: snapshot congelado de demanda usado como âncora do treino;
  • SeriesTrainingContext: contexto semântico por série treinável;
  • TrainingDataset: conjunto de séries preparado para um ciclo de treino;
  • SeriesHoldoutSplit: partição temporal semântica usada na avaliação.

O que continua fora do domínio é a representação técnica desses conceitos:

  • biblioteca concreta de frame (polars, pandas, spark);
  • leitura de parquet, CSV e storage;
  • normalização de schema físico;
  • pipelines concretas de materialização.

Em outras palavras: o domínio modela o que significa treinar com um snapshot de demanda e com uma série preparada; control/data_preparation expõe as portas; e infra/data_preparation/spark executa isso sobre o backend concreto do runtime de jobs.

ModelDefinition

Aggregate root de governança do modelo.

Ele concentra:

  • escopo por organization_id;
  • horizonte, janela e lags;
  • políticas de validação do frame canônico agrupadas por fase (validation_policies);
  • receita de projeção do frame canônico para a série alvo (series_projection_recipe);
  • receita de features (feature_recipe) padrão, com override por estratégia ou série quando a configuração resolvida exigir outro frame;
  • política de reaproveitamento de campeãs (champion_reuse_policy);
  • avaliadores, métrica primária e thresholds;
  • estratégias habilitadas;
  • versões e instâncias treinadas.

Invariantes:

  • ao menos um avaliador e uma estratégia;
  • primary_metric precisa existir entre os avaliadores;
  • apenas uma instância ACTIVE por série;
  • thresholds só podem referenciar métricas conhecidas.

ModelVersion e ModelInstance

ModelVersion congela a configuração usada no treino. ModelInstance representa a materialização treinada para uma série.

Garantias:

  • a instância aponta para a versão congelada usada no treino;
  • mudanças em política de validação, projeção de série, receita de features, política de campeã, horizonte, janela, avaliação, métricas ou estratégias entram no snapshot de ModelVersion;
  • instâncias non-draft exigem training explícito, com referência do artefato treinado, training_run_id e snapshot_id quando existirem;
  • referências de treino carregam hashes de configuração resolvida, validação, projeção, feature recipe, parâmetros da estratégia e política de seleção;
  • métricas persistidas precisam ser numéricas finitas.

Ciclos de vida principais

Treino e promoção

  1. definir um ModelDefinition;
  2. congelar configuração em ModelVersion;
  3. registrar candidatas DRAFT por série;
  4. promover a campeã para ACTIVE.

O que fica fora do domínio

O domínio não conhece:

  • FastAPI;
  • ClickHouse;
  • S3;
  • MLflow;
  • Spark;
  • contratos HTTP.

Esses detalhes entram por boundaries de control, control/data_preparation e infra.

Onde continuar