Add whatsapp feature

This commit is contained in:
Urtzi Alfaro
2025-11-13 16:01:08 +01:00
parent d7df2b0853
commit 9bc048d360
74 changed files with 9765 additions and 533 deletions

View File

@@ -110,6 +110,89 @@ class PredictionService:
error=str(e))
# Features dict will use defaults (0.0) from _prepare_prophet_features
# CRITICAL FIX: Fetch POI (Point of Interest) features from external service
# Prophet models trained with POI features REQUIRE them during prediction
# This prevents "Regressor 'poi_retail_total_count' missing" errors
if 'tenant_id' in features:
try:
from shared.clients.external_client import ExternalServiceClient
from app.core.config import settings
external_client = ExternalServiceClient(settings, "forecasting-service")
poi_data = await external_client.get_poi_context(features['tenant_id'])
if poi_data and 'ml_features' in poi_data:
# Add all POI ML features to prediction features
poi_features = poi_data['ml_features']
features.update(poi_features)
logger.info("POI features enriched",
tenant_id=features['tenant_id'],
poi_feature_count=len(poi_features))
else:
logger.warning("No POI data available for tenant, using default POI features",
tenant_id=features['tenant_id'])
# Provide default POI features to prevent model errors
# These match ALL features generated by POI detection service
# Format: poi_{category}_{feature_name}
default_poi_features = {}
# POI categories from external service POI_CATEGORIES configuration
# These match the categories in services/external/app/core/poi_config.py
poi_categories = [
'schools', 'offices', 'gyms_sports', 'residential', 'tourism',
'competitors', 'transport_hubs', 'coworking', 'retail'
]
for category in poi_categories:
default_poi_features.update({
f'poi_{category}_proximity_score': 0.0,
f'poi_{category}_weighted_proximity_score': 0.0,
f'poi_{category}_count_0_100m': 0,
f'poi_{category}_count_100_300m': 0,
f'poi_{category}_count_300_500m': 0,
f'poi_{category}_count_500_1000m': 0,
f'poi_{category}_total_count': 0,
f'poi_{category}_distance_to_nearest_m': 9999.0,
f'poi_{category}_has_within_100m': 0,
f'poi_{category}_has_within_300m': 0,
f'poi_{category}_has_within_500m': 0,
})
features.update(default_poi_features)
logger.info("Using default POI features",
tenant_id=features['tenant_id'],
default_feature_count=len(default_poi_features))
except Exception as e:
logger.error("Failed to fetch POI features, using defaults",
error=str(e),
tenant_id=features.get('tenant_id'))
# On error, still provide default POI features to prevent prediction failures
default_poi_features = {}
# POI categories from external service POI_CATEGORIES configuration
# These match the categories in services/external/app/core/poi_config.py
poi_categories = [
'schools', 'offices', 'gyms_sports', 'residential', 'tourism',
'competitors', 'transport_hubs', 'coworking', 'retail'
]
for category in poi_categories:
default_poi_features.update({
f'poi_{category}_proximity_score': 0.0,
f'poi_{category}_weighted_proximity_score': 0.0,
f'poi_{category}_count_0_100m': 0,
f'poi_{category}_count_100_300m': 0,
f'poi_{category}_count_300_500m': 0,
f'poi_{category}_count_500_1000m': 0,
f'poi_{category}_total_count': 0,
f'poi_{category}_distance_to_nearest_m': 9999.0,
f'poi_{category}_has_within_100m': 0,
f'poi_{category}_has_within_300m': 0,
f'poi_{category}_has_within_500m': 0,
})
features.update(default_poi_features)
# Prepare features for Prophet model
prophet_df = self._prepare_prophet_features(features)
@@ -925,21 +1008,34 @@ class PredictionService:
'congestion_weekend_interaction': congestion * is_weekend
}
# CRITICAL FIX: Extract POI (Point of Interest) features from the features dict
# POI features start with 'poi_' prefix and must be included for models trained with them
# This prevents "Regressor 'poi_retail_total_count' missing" errors
poi_features = {}
for key, value in features.items():
if key.startswith('poi_'):
# Ensure POI features are numeric (float or int)
try:
poi_features[key] = float(value) if isinstance(value, (int, float, str)) else 0.0
except (ValueError, TypeError):
poi_features[key] = 0.0
# Combine all features
all_new_features = {**new_features, **interaction_features}
all_new_features = {**new_features, **interaction_features, **poi_features}
# Add all features at once using pd.concat to avoid fragmentation
new_feature_df = pd.DataFrame([all_new_features])
df = pd.concat([df, new_feature_df], axis=1)
logger.debug("Complete Prophet features prepared",
logger.debug("Complete Prophet features prepared",
feature_count=len(df.columns),
date=features['date'],
season=df['season'].iloc[0],
traffic_volume=df['traffic_volume'].iloc[0],
average_speed=df['average_speed'].iloc[0],
pedestrian_count=df['pedestrian_count'].iloc[0])
pedestrian_count=df['pedestrian_count'].iloc[0],
poi_feature_count=len(poi_features))
return df
except Exception as e: