Files
sientia-dataops-laborious-l…/docs/drift_insufficient_data_explicit_failure.md
vitor-aignosi 8d34228d7b SIENTIAPDE-1646
Update E2E test report and enhance drift analysis handling

- Updated the E2E test report metrics to reflect the latest test results, showing 47 collected tests with all passing.
- Removed outdated sections related to failed tests and their causes, streamlining the report.
- Implemented a regression fix in the drift analysis to handle empty merged frames, ensuring workflows skip export when no drift metrics are available.
- Enhanced the `insert_sample_data` and `insert_sample_prediction` functions to allow customizable timestamps for better test accuracy.
- Refactored E2E tests to improve clarity and maintainability, particularly in handling repeat scenarios with distinct timestamps.
2026-05-11 11:49:30 -03:00

4.7 KiB

Drift: falha explícita quando dados são insuficientes (solução C)

Objetivo

Quando existir dado alvo no intervalo analisado mas o pipeline não produzir nenhuma métrica de drift (DataFrame vazio após DriftAnalysis e/ou após filtros em calculate_drift), o sistema deve responder de forma assertiva: mensagem clara, identificador de notificação estável e falha controlada (exceção ou erro de atividade), não apenas return [] ou workflow que termina sem export e sem erro.

Isso evita estados ambíguos (ex.: e2e ou operação assumindo que “sucesso + zero linhas” é válido quando na verdade o chunk_period ou o volume de pontos não permite calcular drift).

Comportamento atual (resumo)

  • ModelMetrics.calculate_drift (laborious/activities/model_metrics.py): se get_drift_metrics retornar vazio ou, após drift_floor.isin(target_floor), ficar vazio, registra warning e devolve [].
  • Drift.run (laborious/workflows/drift.py): se drift_data for falsy, não exporta e o workflow termina sem erro.

Nenhum dos dois distingue “não havia dados alvo” (já tratado com early return / short-circuit) de “havia dados, mas nenhuma métrica foi computada”.

Comportamento desejado (solução C)

Quando considerar “dados insuficientes / nenhuma métrica com dados presentes”

Disparar tratamento assertivo se todas forem verdade:

  1. Após pivot/dropna, target_data tem pelo menos uma linha com janela temporal válida.
  2. reference_data está disponível (ou o fallback de 30% foi aplicado) de forma que a análise deveria poder rodar.
  3. reference_columns (features efetivas do drift univariado) não está vazio — caso contrário, falha de configuração, não “insuficiência de amostra”.
  4. O resultado de get_drift_metrics é vazio, ou fica vazio somente após o filtro por target_floor / timestamps.

Opcionalmente, reforçar no sientia_model.analytics.drift_analysis.DriftAnalysis: se analysis_df não for vazio mas não houver chunks ou nenhuma linha univariada/multivariada, levantar exceção específica ou retornar um código/estrutura que o Laborious traduza em falha explícita (evita duplicar heurística só no Laborious).

Resposta assertiva mínima

  1. Log / notificação com ID estável, por exemplo: MODEL_METRICS_DRIFT_INSUFFICIENT_DATA (ou nome alinhado ao catálogo interno).
  2. Mensagem incluindo contexto acionável: model_id, chunk_period, contagem de linhas alvo, contagem de features, intervalo de tempo dos dados.
  3. Falha de atividade: em vez de return [], levantar ValueError (ou exceção de domínio dedicada) após enviar a notificação, para o Temporal marcar a execução como falha e testes/e2e poderem distinguir “sem dados” de “falha de insumos para o granularidade pedida”.

Ajuste no workflow Drift (opcional mas coerente)

Se calculate_drift passar a lançar nesse cenário, o workflow já falha na atividade; não é obrigatório alterar Drift.run além de garantir que erros não sejam engolidos.

Se por política não se quiser falhar o workflow, documentar explicitamente a alternativa (única): retorno estruturado {'status': 'insufficient_data', 'detail': ...} — não é a opção C pedida aqui, que prioriza assertividade e visibilidade.

Impacto em testes

  • Cenários e2e que hoje esperam sucesso silencioso com zero linhas (ex.: test_drift_chunk_period_seconds_preserves_seconds_in_chunk_start_date com poucos pontos e chunk_period='s') devem ser atualizados para esperar falha da atividade com mensagem/notificação, ou o teste deve fornecer volume de dados suficiente para gerar ao menos uma linha de drift — conforme o requisito de produto escolhido após esta mudança.

Appendix: problema REPEAT / UniqueViolation (contexto)

A “solução A” (novo timestamp na linha inserida pelo REPEAT) já está parcialmente implementada em sientia_do: _build_repeat_last_prediction_query faz INSERT ... SELECT com coluna timestamp = parâmetro :last_timestamp, não copia o timestamp da linha anterior.

O e2e ainda falha quando o valor de last_timestamp passado pelo workflow (prediction_process.path_flag_handler) é igual ao timestamp da única predição existente (ex.: seed fixo 2024-01-01 12:00:00+00:00). Nesse caso o INSERT tenta duplicar (model_id, timestamp) e o Postgres aplica unique_model_id_timestamp.

Correção típica: garantir que, no caminho REPEAT, last_timestamp seja o instante do batch / “agora” da execução, distinto do timestamp da última linha persistida — ou ajustar a atividade para derivar um timestamp único quando last_timestamp colide com a última linha.