Feature stores: Feast e alternativas
- ⬜🔁 MLOps: ciclo de vida completo(MLOps — ML em produção)
Recomendamos completar os pré-requisitos antes de seguir, mas nada te impede de continuar.
Por que feature store existe
Quando o segundo modelo do time começa a reusar features do primeiro, você descobre três problemas ao mesmo tempo: cada time reimplementa a mesma transformação de jeito ligeiramente diferente, o SQL de training não bate com o código Python de serving, e ninguém consegue responder quem é dono daquela coluna. Feature store resolve isso centralizando o contrato de features.
Definindo features no Feast
from datetime import timedelta
from feast import Entity, FeatureView, Field, FileSource
from feast.types import Float32, Int64
cliente = Entity(name="cliente_id", join_keys=["cliente_id"])
source = FileSource(
path="s3://ffv-ml/features/cliente_agregados.parquet",
timestamp_field="event_timestamp",
)
cliente_fv = FeatureView(
name="cliente_agregados",
entities=[cliente],
ttl=timedelta(days=7),
schema=[
Field(name="ticket_medio_30d", dtype=Float32),
Field(name="pedidos_90d", dtype=Int64),
Field(name="dias_desde_ultima_compra", dtype=Int64),
],
source=source,
online=True,
tags={"owner": "growth-ml", "pii": "false"},
) O mesmo objeto serve training (via get_historical_features) e serving (via get_online_features). O contrato de nome, tipo e semântica fica em um só lugar versionado em Git.
Point-in-time correctness
A parte pedagogicamente crítica: ao montar dataset de training, você precisa buscar o valor da feature que existia no instante do evento, não o valor mais recente. Caso contrário, vaza informação do futuro e o modelo fica otimista em eval e fraco em produção.
- → mesma definição
- → mesma definição
- → previne
- → previne
- Conceito de arquitetura
- Banco de dados
O desenho existe para deixar claro que a loja online não é um cache do histórico: são dois caminhos com requisitos opostos — reconstruir o passado versus responder o presente — alimentados pela MESMA definição. É a definição compartilhada, não o armazenamento, que justifica a ferramenta.
- 1 · A feature é definida uma vez. Média de compras nos últimos 30 dias precisa significar exatamente a mesma coisa no treino e na inferência. Duas implementações — uma em SQL, outra em Python no serviço — divergem com o tempo, e ninguém percebe.
- 2 · O treino precisa do valor de então. Para um rótulo de março, a feature tem de ser calculada com o que se sabia em março. Usar o valor de hoje entrega ao modelo informação do futuro.
- 3 · A junção respeita o carimbo de tempo. É esse detalhe que dá nome ao conceito: cada linha do conjunto de treino é montada com o estado que existia no instante daquele evento, não com o estado atual da tabela.
- 4 · O serving precisa do valor de agora. Em produção não há histórico a reconstruir: só o último valor, entregue em poucos milissegundos. Daí a loja online ser outra tecnologia, otimizada para leitura por chave.
- 5 · Sem isso, o modelo brilha no treino e falha na estreia. Vazamento temporal produz métrica excelente na validação e queda imediata em produção — e como a validação continua verde, procura-se o defeito no lugar errado por semanas.
from feast import FeatureStore
import pandas as pd
store = FeatureStore(repo_path=".")
entity_df = pd.DataFrame({
"cliente_id": [101, 202, 303],
"event_timestamp": pd.to_datetime([
"2026-01-10 14:00", "2026-01-11 09:30", "2026-01-12 18:45",
]),
})
training_df = store.get_historical_features(
entity_df=entity_df,
features=[
"cliente_agregados:ticket_medio_30d",
"cliente_agregados:pedidos_90d",
],
).to_df()Sem point-in-time join, você está treinando com data leakage. O modelo parece ótimo em validação e decepciona em produção.
Que problema uma central de atributos resolve?
Serving online em tempo real
features = store.get_online_features(
features=[
"cliente_agregados:ticket_medio_30d",
"cliente_agregados:pedidos_90d",
],
entity_rows=[{"cliente_id": 101}],
).to_dict()
# features['ticket_medio_30d'] = [182.5]
# Latencia tipica p99 < 10ms com Redis online storeAlternativas e quando escolher cada
- Feast: open-source, leve, bom para começar. Não tem transformations server-side fortes.
- Tecton: comercial, transformations streaming nativas, operação gerenciada.
- Hopsworks: open-core, integra bem com Spark e Flink, forte em EU/regulado.
- DIY (tabela + Redis): racional para um único modelo — mas documente o contrato.
Comece com Feast se já há 2+ modelos compartilhando features. Evolua para Tecton quando transformations em streaming virarem gargalo.
Perguntas frequentes
❓ O que um repositório de atributos resolve?
❓ Preciso de repositório de atributos desde o começo?
❓ Qual o custo escondido?
Fixando
O que significa correção temporal na construção do conjunto de treino?
Quando uma central de atributos NÃO se justifica?
Terminou de ler?
Marcar como concluído registra o XP, mantém sua sequência e coloca 3 cartas deste módulo na fila de revisão espaçada.
Próximos passos sugeridos
Temas deste módulo
Discussão
Carregando comentários…