From 719ca06da0eb9bc539be1bfa518a72e6c2896c78 Mon Sep 17 00:00:00 2001 From: ajaysi Date: Wed, 8 Oct 2025 15:06:35 +0530 Subject: [PATCH] ALwrity + Wordpress + Wix + GSC integration --- backend/alwrity_utils/dependency_manager.py | 43 +++++++++++++------ backend/alwrity_utils/production_optimizer.py | 26 +++++------ backend/render.yaml | 4 +- backend/start_alwrity_backend.py | 33 +++++++++----- 4 files changed, 67 insertions(+), 39 deletions(-) diff --git a/backend/alwrity_utils/dependency_manager.py b/backend/alwrity_utils/dependency_manager.py index 26c615a8..ed9d7a1a 100644 --- a/backend/alwrity_utils/dependency_manager.py +++ b/backend/alwrity_utils/dependency_manager.py @@ -91,7 +91,7 @@ class DependencyManager: return len(missing_packages) == 0, missing_packages def setup_spacy_model(self) -> bool: - """Set up spaCy English model (production-optimized).""" + """Set up spaCy English model.""" print("🧠 Setting up spaCy model...") try: @@ -107,30 +107,42 @@ class DependencyManager: print(f"✅ spaCy model '{model_name}' is available") return True except OSError: - print(f"⚠️ spaCy model '{model_name}' not found") - print(" Skipping spaCy setup in production mode") - return True # Don't fail for missing spaCy in production + # Model not found - try to download it + print(f"⚠️ spaCy model '{model_name}' not found, downloading...") + try: + subprocess.check_call([ + sys.executable, "-m", "spacy", "download", model_name + ]) + print(f"✅ spaCy model '{model_name}' downloaded successfully") + return True + except subprocess.CalledProcessError as e: + print(f"❌ Failed to download spaCy model: {e}") + print(" Please download manually with: python -m spacy download en_core_web_sm") + return False except ImportError: print("⚠️ spaCy not installed - skipping model setup") - return True # Don't fail for missing spaCy + return True # Don't fail for missing spaCy package return True def setup_nltk_data(self) -> bool: - """Set up NLTK data (production-optimized).""" + """Set up NLTK data.""" print("📚 Setting up NLTK data...") try: import nltk - # Only download essential data - essential_data = ['punkt', 'stopwords'] + # Essential NLTK data packages + essential_data = [ + ('punkt_tab', 'tokenizers/punkt_tab'), # Updated tokenizer + ('stopwords', 'corpora/stopwords'), + ('averaged_perceptron_tagger', 'taggers/averaged_perceptron_tagger') + ] - for data_package in essential_data: + for data_package, path in essential_data: try: - nltk.data.find(f'tokenizers/{data_package}' if data_package == 'punkt' - else f'corpora/{data_package}') + nltk.data.find(path) print(f" ✅ {data_package}") except LookupError: print(f" ⚠️ {data_package} - downloading...") @@ -139,12 +151,19 @@ class DependencyManager: print(f" ✅ {data_package} downloaded") except Exception as e: print(f" ⚠️ {data_package} download failed: {e}") + # Try fallback for punkt_tab -> punkt + if data_package == 'punkt_tab': + try: + nltk.download('punkt', quiet=True) + print(f" ✅ punkt (fallback) downloaded") + except: + pass print("✅ NLTK data setup complete") return True except ImportError: print("⚠️ NLTK not installed - skipping data setup") - return True # Don't fail for missing NLTK + return True # Don't fail for missing NLTK package return True diff --git a/backend/alwrity_utils/production_optimizer.py b/backend/alwrity_utils/production_optimizer.py index 6ea7d6e6..6ea87a2f 100644 --- a/backend/alwrity_utils/production_optimizer.py +++ b/backend/alwrity_utils/production_optimizer.py @@ -13,9 +13,9 @@ class ProductionOptimizer: def __init__(self): self.production_optimizations = { - 'disable_spacy_download': True, - 'disable_nltk_download': True, - 'skip_linguistic_setup': True, + 'disable_spacy_download': False, # Allow spaCy verification (required for persona generation) + 'disable_nltk_download': False, # Allow NLTK verification (required for persona generation) + 'skip_linguistic_setup': False, # Always verify linguistic models are available 'minimal_database_setup': True, 'skip_file_creation': True } @@ -39,7 +39,8 @@ class ProductionOptimizer: def _set_production_env_vars(self) -> None: """Set production-specific environment variables.""" production_vars = { - 'HOST': '0.0.0.0', + # Note: HOST is not set here - it's auto-detected by start_backend() + # Based on deployment environment (cloud vs local) 'PORT': '8000', 'RELOAD': 'false', 'LOG_LEVEL': 'INFO', @@ -53,19 +54,14 @@ class ProductionOptimizer: print(f" ✅ {key}={value}") def _disable_heavy_operations(self) -> None: - """Disable operations that are too heavy for production startup.""" - print(" ⚡ Disabling heavy operations for production...") + """Configure operations for production startup.""" + print(" ⚡ Configuring operations for production...") - # Disable spaCy model download - os.environ.setdefault('DISABLE_SPACY_DOWNLOAD', 'true') + # Note: spaCy and NLTK verification are allowed in production + # Models should be pre-installed during build phase (via render.yaml or similar) + # The setup will verify models exist without re-downloading - # Disable NLTK data download - os.environ.setdefault('DISABLE_NLTK_DOWNLOAD', 'true') - - # Skip linguistic analyzer setup - os.environ.setdefault('SKIP_LINGUISTIC_SETUP', 'true') - - print(" ✅ Heavy operations disabled") + print(" ✅ Production operations configured") def _optimize_logging(self) -> None: """Optimize logging for production.""" diff --git a/backend/render.yaml b/backend/render.yaml index 58ca37fd..b95f5ed7 100644 --- a/backend/render.yaml +++ b/backend/render.yaml @@ -3,10 +3,12 @@ services: - type: web name: alwrity-backend env: python - buildCommand: pip install -r requirements.txt + buildCommand: pip install -r requirements.txt && python -m spacy download en_core_web_sm && python -m nltk.downloader punkt_tab stopwords averaged_perceptron_tagger startCommand: python start_alwrity_backend.py --production healthCheckPath: /health envVars: + - key: DEPLOY_ENV + value: render - key: HOST value: 0.0.0.0 - key: PORT diff --git a/backend/start_alwrity_backend.py b/backend/start_alwrity_backend.py index cb47511d..b2505ef7 100644 --- a/backend/start_alwrity_backend.py +++ b/backend/start_alwrity_backend.py @@ -23,8 +23,17 @@ def start_backend(enable_reload=False, production_mode=False): """Start the backend server.""" print("🚀 Starting ALwrity Backend...") - # Set environment variables - os.environ.setdefault("HOST", "0.0.0.0") + # Set host based on environment and mode + # Use 127.0.0.1 for local production testing on Windows + # Use 0.0.0.0 for actual cloud deployments (Render, Railway, etc.) + default_host = os.getenv("RENDER") or os.getenv("RAILWAY_ENVIRONMENT") or os.getenv("DEPLOY_ENV") + if default_host: + # Cloud deployment detected - use 0.0.0.0 + os.environ.setdefault("HOST", "0.0.0.0") + else: + # Local deployment - use 127.0.0.1 for better Windows compatibility + os.environ.setdefault("HOST", "127.0.0.1") + os.environ.setdefault("PORT", "8000") # Set reload based on argument or environment variable @@ -35,7 +44,7 @@ def start_backend(enable_reload=False, production_mode=False): os.environ.setdefault("RELOAD", "false") print(" 🏭 Production mode: Auto-reload disabled") - host = os.getenv("HOST", "0.0.0.0") + host = os.getenv("HOST") port = int(os.getenv("PORT", "8000")) reload = os.getenv("RELOAD", "false").lower() == "true" @@ -187,17 +196,19 @@ def main(): if not database_setup.setup_essential_tables(): print("[WARNING] Database setup had issues, continuing...") - # Setup advanced features only in development + # Setup advanced features in development, verify in all modes if not production_mode: database_setup.setup_advanced_tables() - database_setup.verify_tables() - # Setup linguistic analysis (skip in production) - if not production_mode and not production_optimizer.skip_linguistic_setup(): - if not production_optimizer.skip_spacy_setup(): - dependency_manager.setup_spacy_model() - if not production_optimizer.skip_nltk_setup(): - dependency_manager.setup_nltk_data() + # Always verify database tables (important for both dev and production) + database_setup.verify_tables() + + # Setup linguistic analysis (always check, download only if needed) + # This ensures models are verified in both dev and production + if not production_optimizer.skip_spacy_setup(): + dependency_manager.setup_spacy_model() + if not production_optimizer.skip_nltk_setup(): + dependency_manager.setup_nltk_data() # Start backend return start_backend(enable_reload=enable_reload, production_mode=production_mode)