From 08e51f76fa6e8d2ddaaa124c33e2fa437532fd41 Mon Sep 17 00:00:00 2001 From: ajaysi Date: Tue, 31 Mar 2026 15:18:03 +0530 Subject: [PATCH] Profile-aware bootstrap gating in start_alwrity_backend.py - Add LINGUISTIC_REQUIRED_FEATURES set for profile-based gating - Add get_active_profile() helper to read from ALWRITY_ACTIVE_PROFILE, ALWRITY_PROFILE, ALWRITY_FEATURE_PROFILE - Add get_loaded_features() to read from ALWRITY_LOADED_FEATURES - Add should_bootstrap_linguistic_models() - runs for all/default or when loaded features intersect linguistic-required - Add should_bootstrap_local_llm_models() - skip for podcast/youtube/planning profiles - Gate bootstrap steps at module load time --- backend/start_alwrity_backend.py | 56 ++++++++++++++++++++++++++++++-- 1 file changed, 54 insertions(+), 2 deletions(-) diff --git a/backend/start_alwrity_backend.py b/backend/start_alwrity_backend.py index a2a00766..494fd4fc 100644 --- a/backend/start_alwrity_backend.py +++ b/backend/start_alwrity_backend.py @@ -11,6 +11,47 @@ import argparse from pathlib import Path +LINGUISTIC_REQUIRED_FEATURES = {"content_planning", "strategy_copilot", "facebook", "linkedin", "blog_writer", "persona"} + + +def get_active_profile() -> str: + """Get active profile from environment variables.""" + return os.getenv("ALWRITY_ACTIVE_PROFILE", os.getenv("ALWRITY_PROFILE", os.getenv("ALWRITY_FEATURE_PROFILE", os.getenv("ALWRITY_ROUTER_PROFILE", os.getenv("ALWRITY_FEATURE_TO_ENABLE", "all"))))).strip().lower() or "all" + + +def get_loaded_features() -> set: + """Get loaded features from environment variables.""" + features_str = os.getenv("ALWRITY_LOADED_FEATURES", os.getenv("ALWRITY_ENABLED_FEATURES", os.getenv("ALWRITY_FEATURES", ""))) + if not features_str: + return set() + return {f.strip().lower() for f in features_str.split(",") if f.strip()} + + +def should_bootstrap_linguistic_models() -> bool: + """Decide whether to bootstrap linguistic models based on profile.""" + profile = get_active_profile() + verbose = os.getenv("ALWRITY_VERBOSE", "false").lower() == "true" + + if profile in {"all", "default"}: + return True + + loaded_features = get_loaded_features() + if not loaded_features: + return False + + return bool(loaded_features & LINGUISTIC_REQUIRED_FEATURES) + + +def should_bootstrap_local_llm_models() -> bool: + """Decide whether to bootstrap local LLM models based on profile.""" + profile = get_active_profile() + + if profile in {"all", "default"}: + return True + + return profile not in {"podcast", "youtube", "planning"} + + def bootstrap_linguistic_models(): """ Bootstrap spaCy and NLTK models BEFORE any imports. @@ -145,8 +186,19 @@ def bootstrap_local_llm_models(): # Bootstrap linguistic models BEFORE any imports that might need them if __name__ == "__main__": - bootstrap_linguistic_models() - bootstrap_local_llm_models() + if should_bootstrap_linguistic_models(): + bootstrap_linguistic_models() + else: + verbose = os.getenv("ALWRITY_VERBOSE", "false").lower() == "true" + if verbose: + print("⏭️ Skipping linguistic model bootstrap (profile-gated)") + + if should_bootstrap_local_llm_models(): + bootstrap_local_llm_models() + else: + verbose = os.getenv("ALWRITY_VERBOSE", "false").lower() == "true" + if verbose: + print("⏭️ Skipping local LLM model bootstrap (profile-gated)") # NOW import modular utilities (after bootstrap) from alwrity_utils import (