from pathlib import Path import os BASE_DIR = Path(__file__).resolve().parent.parent SECRET_KEY = os.getenv('DJANGO_SECRET_KEY', 'dev-insecure-change-me') DEBUG = os.getenv('DJANGO_DEBUG', '1') == '1' ALLOWED_HOSTS = [h.strip() for h in os.getenv('DJANGO_ALLOWED_HOSTS', '127.0.0.1,localhost,10.0.2.2,.hf.space').split(',') if h.strip()] INSTALLED_APPS = [ 'django.contrib.admin', 'django.contrib.auth', 'django.contrib.contenttypes', 'django.contrib.sessions', 'django.contrib.messages', 'django.contrib.staticfiles', 'apps.chat.apps.ChatConfig', 'apps.service_intents.apps.ServiceIntentsConfig', 'apps.model_ops.apps.ModelOpsConfig', ] MIDDLEWARE = [ 'django.middleware.security.SecurityMiddleware', 'django.contrib.sessions.middleware.SessionMiddleware', 'django.middleware.common.CommonMiddleware', 'django.middleware.csrf.CsrfViewMiddleware', 'django.contrib.auth.middleware.AuthenticationMiddleware', 'django.contrib.messages.middleware.MessageMiddleware', 'django.middleware.clickjacking.XFrameOptionsMiddleware', ] ROOT_URLCONF = 'chatbot.urls' TEMPLATES = [ { 'BACKEND': 'django.template.backends.django.DjangoTemplates', 'DIRS': [BASE_DIR / 'templates'], 'APP_DIRS': True, 'OPTIONS': { 'context_processors': [ 'django.template.context_processors.debug', 'django.template.context_processors.request', 'django.contrib.auth.context_processors.auth', 'django.contrib.messages.context_processors.messages', ], }, }, ] WSGI_APPLICATION = 'chatbot.wsgi.application' DATABASES = { 'default': { 'ENGINE': 'django.db.backends.sqlite3', 'NAME': BASE_DIR / 'db.sqlite3', } } AUTH_PASSWORD_VALIDATORS = [ {'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator'}, {'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator'}, {'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator'}, {'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator'}, ] LANGUAGE_CODE = 'en-us' TIME_ZONE = 'UTC' USE_I18N = True USE_TZ = True STATIC_URL = '/static/' STATIC_ROOT = BASE_DIR / 'staticfiles' DEFAULT_AUTO_FIELD = 'django.db.models.BigAutoField' # Deployed orchestration service. Individual service definitions append their own path. N8N_BASE_URL = os.getenv('N8N_BASE_URL', 'https://mortadhabbb-n8n-service-orchestration.hf.space') N8N_TIMEOUT = int(os.getenv('N8N_TIMEOUT', '10')) # API key for /api/chat CHATBOT_API_KEY = os.getenv('CHATBOT_API_KEY', '') # Dataset QA_CSV = os.getenv('QA_CSV', 'apps/chat/training_models/data/chatbot.csv') SERVICE_INTENTS_CSV = os.getenv('SERVICE_INTENTS_CSV', 'apps/chat/training_models/data/service_intents.csv') SERVICE_INTENT_MODEL_TRAINING_CSV = os.getenv( 'SERVICE_INTENT_MODEL_TRAINING_CSV', 'apps/chat/training_models/data/service_intents_model_training.csv', ) SERVICE_INTENT_BASE_MODEL_ID = os.getenv('SERVICE_INTENT_BASE_MODEL_ID', 'google/flan-t5-base') SERVICE_INTENT_MODEL_DIR = os.getenv( 'SERVICE_INTENT_MODEL_DIR', str(BASE_DIR / 'artifacts' / 'service_intent_model'), ) SERVICE_INTENT_BASE_MODEL_DIR = os.getenv( 'SERVICE_INTENT_BASE_MODEL_DIR', str(BASE_DIR / 'artifacts' / 'hf_base_models' / SERVICE_INTENT_BASE_MODEL_ID.replace('/', '__')), ) SERVICE_INTENT_QUANTIZED_MODEL_DIR = os.getenv( 'SERVICE_INTENT_QUANTIZED_MODEL_DIR', str(BASE_DIR / 'artifacts' / 'service_intent_model_quantized'), ) SERVICE_INTENT_EXTRACTOR_ENABLED = os.getenv('SERVICE_INTENT_EXTRACTOR_ENABLED', 'True') == 'True' SERVICE_INTENT_EXTRACTOR_MAX_NEW_TOKENS = int(os.getenv('SERVICE_INTENT_EXTRACTOR_MAX_NEW_TOKENS', '256')) SERVICE_INTENT_TRAINING_SPACE_URL = os.getenv( 'SERVICE_INTENT_TRAINING_SPACE_URL', 'https://mortadhabbb-train-model-chatbot.hf.space', ) SERVICE_INTENT_TRAINING_SPACE_API_KEY = os.getenv('SERVICE_INTENT_TRAINING_SPACE_API_KEY', '') SERVICE_INTENT_TRAINING_OUTPUT_REPO_ID = os.getenv('SERVICE_INTENT_TRAINING_OUTPUT_REPO_ID', '') SERVICE_INTENT_TRAINING_POLL_SECONDS = int(os.getenv('SERVICE_INTENT_TRAINING_POLL_SECONDS', '20')) # Hugging Face HF_TOKEN = os.getenv('HF_TOKEN', '') HF_SPACE_ID = os.getenv('HF_SPACE_ID', 'mortadhabbb/chatbot-sports_academies-system') SPRING_CHATBOT_FILES_DIR = os.getenv( 'SPRING_CHATBOT_FILES_DIR', str(BASE_DIR.parent.parent / 'sports_management_project' / 'src' / 'main' / 'resources' / 'Files' / 'chatbotFiles') ) CHATBOT_TRANSLATION_ENABLED = os.getenv('CHATBOT_TRANSLATION_ENABLED', 'True') == 'True' # Tuning MIN_SIM = float(os.getenv('MIN_SIM', '0.18')) FUZZY_MIN = int(os.getenv('FUZZY_MIN', '90')) # ============================================================================ # LOGGING CONFIGURATION (Production-Ready) # ============================================================================ LOGGING = { 'version': 1, 'disable_existing_loggers': False, 'formatters': { 'verbose': { 'format': '[{levelname}] {asctime} {module} {funcName}:{lineno} - {message}', 'style': '{', 'datefmt': '%Y-%m-%d %H:%M:%S', }, 'simple': { 'format': '[{levelname}] {message}', 'style': '{', }, }, 'filters': { 'require_debug_false': { '()': 'django.utils.log.RequireDebugFalse', }, 'require_debug_true': { '()': 'django.utils.log.RequireDebugTrue', }, }, 'handlers': { 'console': { 'level': 'DEBUG' if DEBUG else 'INFO', 'class': 'logging.StreamHandler', 'formatter': 'verbose', }, 'file': { 'level': 'INFO', 'class': 'logging.handlers.RotatingFileHandler', 'filename': BASE_DIR / 'logs' / 'chatbot.log', 'maxBytes': 10485760, # 10MB 'backupCount': 5, 'formatter': 'verbose', }, 'error_file': { 'level': 'ERROR', 'class': 'logging.handlers.RotatingFileHandler', 'filename': BASE_DIR / 'logs' / 'errors.log', 'maxBytes': 10485760, # 10MB 'backupCount': 5, 'formatter': 'verbose', }, }, 'loggers': { 'django': { 'handlers': ['console', 'file'], 'level': 'INFO', 'propagate': False, }, 'chatbot': { 'handlers': ['console', 'file', 'error_file'], 'level': 'DEBUG' if DEBUG else 'INFO', 'propagate': False, }, 'ml_index': { 'handlers': ['console', 'file'], 'level': 'INFO', 'propagate': False, }, }, } # Create logs directory if it doesn't exist LOGS_DIR = BASE_DIR / 'logs' LOGS_DIR.mkdir(exist_ok=True) # ============================================================================ # CACHING CONFIGURATION (Development/Production) # ============================================================================ if os.getenv('DJANGO_CACHE_BACKEND', '').strip().lower() == 'locmem' or DEBUG: # Development: in-memory cache CACHES = { 'default': { 'BACKEND': 'django.core.cache.backends.locmem.LocMemCache', 'LOCATION': 'chatbot-cache', 'TIMEOUT': 3600, 'OPTIONS': {'MAX_ENTRIES': 1000} } } else: # Production: can be replaced with Redis/Memcached CACHES = { 'default': { 'BACKEND': 'django.core.cache.backends.db.DatabaseCache', 'LOCATION': 'cache_table', 'OPTIONS': {'MAX_ENTRIES': 5000} } } # ============================================================================ # SECURITY CONFIGURATION # ============================================================================ if not DEBUG: SECURE_SSL_REDIRECT = os.getenv('SECURE_SSL_REDIRECT', 'False') == 'True' SESSION_COOKIE_SECURE = os.getenv('SESSION_COOKIE_SECURE', 'False') == 'True' CSRF_COOKIE_SECURE = os.getenv('CSRF_COOKIE_SECURE', 'False') == 'True' SECURE_HSTS_SECONDS = int(os.getenv('SECURE_HSTS_SECONDS', '31536000')) SECURE_HSTS_INCLUDE_SUBDOMAINS = True SECURE_HSTS_PRELOAD = True SECURE_CONTENT_SECURITY_POLICY = { 'default-src': ("'self'",), 'script-src': ("'self'", "'unsafe-inline'"), 'style-src': ("'self'", "'unsafe-inline'"), } # ============================================================================ # RATE LIMITING & THROTTLING # ============================================================================ RATE_LIMIT_ENABLED = os.getenv('RATE_LIMIT_ENABLED', 'True') == 'True' RATE_LIMIT_REQUESTS = int(os.getenv('RATE_LIMIT_REQUESTS', '100')) # per minute RATE_LIMIT_PERIOD = int(os.getenv('RATE_LIMIT_PERIOD', '60')) # seconds # ============================================================================ # CHATBOT MONITORING # ============================================================================ CHATBOT_MAX_MESSAGE_LENGTH = 1000 CHATBOT_REQUEST_TIMEOUT = 30 # seconds CHATBOT_ENABLE_METRICS = True # Chatbot microservice-owned datasets CHATBOT_DATA_CSV = os.getenv("CHATBOT_DATA_CSV", str(BASE_DIR / "apps" / "chat" / "training_models" / "data" / "data.csv")) CHATBOT_MARKERS_CSV = os.getenv("CHATBOT_MARKERS_CSV", str(BASE_DIR / "apps" / "chat" / "training_models" / "data" / "markers_finetune_real_examples.csv")) CHATBOT_SERVICE_INTENTS_CSV = os.getenv("CHATBOT_SERVICE_INTENTS_CSV", str(BASE_DIR / "apps" / "chat" / "training_models" / "data" / "service_intents.csv")) # Extraction manifest: services for which the slot extractor model is allowed to run. SERVICE_EXTRACTION_MANIFEST = os.getenv('SERVICE_EXTRACTION_MANIFEST', 'apps/chat/training_models/data/service_extraction_manifest.json')