feat(features): per-feature freshness spec — JIT vs batched (#61)
Each ml/features/*.py now declares freshness, source, and fallback per feature. ProfileFeature gains ttl_sec (mirrored from registry.ts), freshness="batched", source, and fallback. context.py adds ContextFeatureSpec + CONTEXT_FEATURES for the three JIT features (hour_of_day, day_of_week, tasks). CI test parses ttlSec from registry.ts to catch drift. ml/README updated with split JIT/batched feature contract. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -2,12 +2,56 @@
|
||||
Context assembler — converts raw user signals into a PromptContext for LLM tip generation.
|
||||
|
||||
Usage:
|
||||
from ml.features.context import build_context
|
||||
from ml.features.context import build_context, CONTEXT_FEATURES
|
||||
ctx = build_context(tasks, hour_of_day=9, day_of_week=2)
|
||||
|
||||
Feature-spec (issue #61):
|
||||
All context features are JIT — they are assembled at request time from live
|
||||
sources (system clock, caller-supplied task list) rather than read from a
|
||||
cached profile store. They carry no TTL because they are never persisted.
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
from dataclasses import dataclass, field
|
||||
from typing import Literal
|
||||
|
||||
|
||||
@dataclass(frozen=True)
|
||||
class ContextFeatureSpec:
|
||||
name: str
|
||||
dtype: Literal["numeric", "categorical", "list"]
|
||||
freshness: Literal["jit", "batched"]
|
||||
source: str
|
||||
fallback: str
|
||||
description: str
|
||||
|
||||
|
||||
CONTEXT_FEATURES: tuple[ContextFeatureSpec, ...] = (
|
||||
ContextFeatureSpec(
|
||||
name="hour_of_day",
|
||||
dtype="numeric",
|
||||
freshness="jit",
|
||||
source="request",
|
||||
fallback="12",
|
||||
description="Current hour (0–23), supplied by the caller at score time.",
|
||||
),
|
||||
ContextFeatureSpec(
|
||||
name="day_of_week",
|
||||
dtype="numeric",
|
||||
freshness="jit",
|
||||
source="request",
|
||||
fallback="0",
|
||||
description="ISO weekday (0=Monday … 6=Sunday), supplied by the caller at score time.",
|
||||
),
|
||||
ContextFeatureSpec(
|
||||
name="tasks",
|
||||
dtype="list",
|
||||
freshness="jit",
|
||||
source="todoist-integration",
|
||||
fallback="[]",
|
||||
description="User's open tasks fetched live from the Todoist integration at request time.",
|
||||
),
|
||||
)
|
||||
|
||||
|
||||
@dataclass
|
||||
|
||||
Reference in New Issue
Block a user