109 lines
5.3 KiB
PHP
109 lines
5.3 KiB
PHP
<?php
|
|
|
|
declare(strict_types=1);
|
|
|
|
return [
|
|
'queue' => env('DISCOVERY_QUEUE', env('RECOMMENDATIONS_QUEUE', env('VISION_QUEUE', 'default'))),
|
|
|
|
// Versioned from day one for safe future migrations/experiments.
|
|
'profile_version' => env('DISCOVERY_PROFILE_VERSION', 'profile-v1'),
|
|
'event_version' => env('DISCOVERY_EVENT_VERSION', 'event-v1'),
|
|
'algo_version' => env('DISCOVERY_ALGO_VERSION', env('RECOMMENDATIONS_ALGO_VERSION', 'clip-cosine-v1')),
|
|
'cache_version' => env('DISCOVERY_CACHE_VERSION', 'cache-v1'),
|
|
|
|
'decay' => [
|
|
// Exponential half-life: score * 0.5 every N hours.
|
|
'half_life_hours' => (float) env('DISCOVERY_DECAY_HALF_LIFE_HOURS', 72),
|
|
],
|
|
|
|
// Baseline event contribution weights.
|
|
'weights' => [
|
|
'view' => (float) env('DISCOVERY_WEIGHT_VIEW', 1.0),
|
|
'click' => (float) env('DISCOVERY_WEIGHT_CLICK', 2.0),
|
|
'favorite' => (float) env('DISCOVERY_WEIGHT_FAVORITE', 4.0),
|
|
'download' => (float) env('DISCOVERY_WEIGHT_DOWNLOAD', 3.0),
|
|
],
|
|
|
|
// Recommendation cache TTL in minutes (schema foundation only for now).
|
|
'cache_ttl_minutes' => (int) env('DISCOVERY_CACHE_TTL_MINUTES', 60),
|
|
|
|
// Phase 8B: versioned ranking blend weights.
|
|
// Blend components: w1=interest, w2=recency, w3=popularity, w4=novelty.
|
|
'ranking' => [
|
|
'default_weights' => [
|
|
'version' => env('DISCOVERY_RANKING_WEIGHTS_VERSION', 'rank-w-v1'),
|
|
'w1' => (float) env('DISCOVERY_RANKING_W1', 0.65),
|
|
'w2' => (float) env('DISCOVERY_RANKING_W2', 0.20),
|
|
'w3' => (float) env('DISCOVERY_RANKING_W3', 0.10),
|
|
'w4' => (float) env('DISCOVERY_RANKING_W4', 0.05),
|
|
],
|
|
|
|
// Per-algo overrides for safe rollout by algo_version.
|
|
'algo_weight_sets' => [
|
|
'clip-cosine-v1' => [
|
|
'version' => env('DISCOVERY_RANKING_WEIGHTS_VERSION_CLIP_COSINE_V1', 'rank-w-v1'),
|
|
'w1' => (float) env('DISCOVERY_RANKING_W1_CLIP_COSINE_V1', 0.65),
|
|
'w2' => (float) env('DISCOVERY_RANKING_W2_CLIP_COSINE_V1', 0.20),
|
|
'w3' => (float) env('DISCOVERY_RANKING_W3_CLIP_COSINE_V1', 0.10),
|
|
'w4' => (float) env('DISCOVERY_RANKING_W4_CLIP_COSINE_V1', 0.05),
|
|
],
|
|
'clip-cosine-v2' => [
|
|
'version' => env('DISCOVERY_RANKING_WEIGHTS_VERSION_CLIP_COSINE_V2', 'rank-w-v2-prod-1'),
|
|
'w1' => (float) env('DISCOVERY_RANKING_W1_CLIP_COSINE_V2', 0.52),
|
|
'w2' => (float) env('DISCOVERY_RANKING_W2_CLIP_COSINE_V2', 0.23),
|
|
'w3' => (float) env('DISCOVERY_RANKING_W3_CLIP_COSINE_V2', 0.15),
|
|
'w4' => (float) env('DISCOVERY_RANKING_W4_CLIP_COSINE_V2', 0.10),
|
|
],
|
|
],
|
|
],
|
|
|
|
// Phase 8 production rollout gates (deterministic user bucketing).
|
|
'rollout' => [
|
|
'enabled' => (bool) env('DISCOVERY_ROLLOUT_ENABLED', false),
|
|
'baseline_algo_version' => env('DISCOVERY_ROLLOUT_BASELINE_ALGO_VERSION', 'clip-cosine-v1'),
|
|
'candidate_algo_version' => env('DISCOVERY_ROLLOUT_CANDIDATE_ALGO_VERSION', 'clip-cosine-v2'),
|
|
|
|
// One of: g10, g50, g100.
|
|
'active_gate' => env('DISCOVERY_ROLLOUT_ACTIVE_GATE', 'g10'),
|
|
'gates' => [
|
|
'g10' => [
|
|
'name' => '10%',
|
|
'percentage' => (int) env('DISCOVERY_ROLLOUT_GATE_10_PERCENT', 10),
|
|
],
|
|
'g50' => [
|
|
'name' => '50%',
|
|
'percentage' => (int) env('DISCOVERY_ROLLOUT_GATE_50_PERCENT', 50),
|
|
],
|
|
'g100' => [
|
|
'name' => '100%',
|
|
'percentage' => (int) env('DISCOVERY_ROLLOUT_GATE_100_PERCENT', 100),
|
|
],
|
|
],
|
|
|
|
// Emergency rollback toggle: force all traffic to one algo_version.
|
|
'force_algo_version' => env('DISCOVERY_FORCE_ALGO_VERSION', ''),
|
|
|
|
// Guardrails (used operationally in runbook and dashboards).
|
|
'monitoring_thresholds' => [
|
|
'ctr_warn_drop_pct' => (float) env('DISCOVERY_ROLLOUT_WARN_CTR_DROP_PCT', 3.0),
|
|
'ctr_rollback_drop_pct' => (float) env('DISCOVERY_ROLLOUT_ROLLBACK_CTR_DROP_PCT', 5.0),
|
|
'long_dwell_warn_drop_pct' => (float) env('DISCOVERY_ROLLOUT_WARN_LONG_DWELL_DROP_PCT', 4.0),
|
|
'long_dwell_rollback_drop_pct' => (float) env('DISCOVERY_ROLLOUT_ROLLBACK_LONG_DWELL_DROP_PCT', 8.0),
|
|
'diversity_warn_concentration_rise_pct' => (float) env('DISCOVERY_ROLLOUT_WARN_DIVERSITY_CONCENTRATION_RISE_PCT', 10.0),
|
|
'diversity_rollback_concentration_rise_pct' => (float) env('DISCOVERY_ROLLOUT_ROLLBACK_DIVERSITY_CONCENTRATION_RISE_PCT', 15.0),
|
|
],
|
|
],
|
|
|
|
// Offline evaluation objective weights (manual/data-driven tuning).
|
|
'evaluation' => [
|
|
'objective_weights' => [
|
|
'ctr' => (float) env('DISCOVERY_EVAL_WEIGHT_CTR', 0.45),
|
|
'save_rate' => (float) env('DISCOVERY_EVAL_WEIGHT_SAVE_RATE', 0.35),
|
|
'long_dwell_share' => (float) env('DISCOVERY_EVAL_WEIGHT_LONG_DWELL', 0.25),
|
|
'bounce_rate_penalty' => (float) env('DISCOVERY_EVAL_WEIGHT_BOUNCE_PENALTY', 0.15),
|
|
],
|
|
// Temporary switch: keep save_rate visible but exclude it from objective score.
|
|
'save_rate_informational' => (bool) env('DISCOVERY_EVAL_SAVE_RATE_INFORMATIONAL', true),
|
|
],
|
|
];
|