import os from pathlib import Path from dotenv import load_dotenv BASE_DIR = Path(__file__).resolve().parents[3] load_dotenv(BASE_DIR / ".env", override=False) SECRET_KEY = os.getenv("DJANGO_SECRET_KEY", "dev-only-change-me") DEBUG = os.getenv("DJANGO_DEBUG", "false").lower() == "true" ALLOWED_HOSTS = os.getenv("DJANGO_ALLOWED_HOSTS", "localhost,127.0.0.1").split(",") INSTALLED_APPS = [ "django.contrib.admin", "django.contrib.auth", "django.contrib.contenttypes", "django.contrib.sessions", "django.contrib.messages", "django.contrib.postgres", "django.contrib.staticfiles", "corsheaders", "apps.accounts", "apps.audit", "apps.system", "apps.tickets", "apps.workitems", "apps.solutions", "apps.knowledge", "apps.modelhub", "apps.skills", "apps.agents", "apps.tools", "apps.channels", ] MIDDLEWARE = [ "corsheaders.middleware.CorsMiddleware", "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 = "config.urls" TEMPLATES = [ { "BACKEND": "django.template.backends.django.DjangoTemplates", "DIRS": [], "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 = "config.wsgi.application" ASGI_APPLICATION = "config.asgi.application" DATABASES = { "default": { "ENGINE": "django.db.backends.postgresql", "NAME": os.getenv("POSTGRES_DB", "ai_ticket_platform"), "USER": os.getenv("POSTGRES_USER", "ai_ticket"), "PASSWORD": os.getenv("POSTGRES_PASSWORD", "ai_ticket"), "HOST": os.getenv("POSTGRES_HOST", "localhost"), "PORT": int(os.getenv("POSTGRES_PORT", "5432")), } } LANGUAGE_CODE = "zh-hans" TIME_ZONE = "Asia/Shanghai" USE_I18N = True USE_TZ = True AUTH_PASSWORD_VALIDATORS = [ { "NAME": "django.contrib.auth.password_validation.UserAttributeSimilarityValidator", }, { "NAME": "django.contrib.auth.password_validation.MinimumLengthValidator", "OPTIONS": {"min_length": 8}, }, { "NAME": "django.contrib.auth.password_validation.CommonPasswordValidator", }, { "NAME": "django.contrib.auth.password_validation.NumericPasswordValidator", }, ] STATIC_URL = "static/" DEFAULT_AUTO_FIELD = "django.db.models.BigAutoField" CORS_ALLOWED_ORIGINS = os.getenv( "CORS_ALLOWED_ORIGINS", "http://localhost:5173", ).split(",") CORS_ALLOW_CREDENTIALS = True CSRF_TRUSTED_ORIGINS = os.getenv( "CSRF_TRUSTED_ORIGINS", "http://localhost:5173,http://127.0.0.1:5173", ).split(",") FRONTEND_APP_URL = os.getenv("FRONTEND_APP_URL", "http://localhost:5173").rstrip("/") OIDC_CALLBACK_BASE_URL = os.getenv("OIDC_CALLBACK_BASE_URL", "").rstrip("/") DJANGO_SUPERUSER_USERNAME = os.getenv("DJANGO_SUPERUSER_USERNAME", "admin") DJANGO_SUPERUSER_PASSWORD = os.getenv("DJANGO_SUPERUSER_PASSWORD", "admin12345") DJANGO_SUPERUSER_EMAIL = os.getenv("DJANGO_SUPERUSER_EMAIL", "admin@example.com") CELERY_BROKER_URL = os.getenv("CELERY_BROKER_URL", "redis://localhost:6379/0") CELERY_RESULT_BACKEND = os.getenv("CELERY_RESULT_BACKEND", "redis://localhost:6379/1") AI_CREDENTIAL_ENCRYPTION_KEY = os.getenv("AI_CREDENTIAL_ENCRYPTION_KEY", "") INTERNAL_MCP_TOKEN = os.getenv("INTERNAL_MCP_TOKEN", "") METRICS_TOKEN = os.getenv("METRICS_TOKEN", "") AI_RUN_RETENTION_DAYS = int(os.getenv("AI_RUN_RETENTION_DAYS", "90")) AI_SLOW_RUN_THRESHOLD_SECONDS = int(os.getenv("AI_SLOW_RUN_THRESHOLD_SECONDS", "20")) AI_AGENT_MODEL_TIMEOUT_SECONDS = int(os.getenv("AI_AGENT_MODEL_TIMEOUT_SECONDS", "20")) KNOWLEDGE_EMBEDDING_DEPLOYMENT_ID = int( os.getenv("KNOWLEDGE_EMBEDDING_DEPLOYMENT_ID", "0") ) KNOWLEDGE_EMBEDDING_DIMENSIONS = int(os.getenv("KNOWLEDGE_EMBEDDING_DIMENSIONS", "1536")) KNOWLEDGE_EMBEDDING_ALLOW_HASH_FALLBACK = ( os.getenv("KNOWLEDGE_EMBEDDING_ALLOW_HASH_FALLBACK", "false").lower() == "true" ) KNOWLEDGE_RETRIEVAL_TEXT_WEIGHT = float( os.getenv("KNOWLEDGE_RETRIEVAL_TEXT_WEIGHT", "0.45") ) KNOWLEDGE_RETRIEVAL_VECTOR_WEIGHT = float( os.getenv("KNOWLEDGE_RETRIEVAL_VECTOR_WEIGHT", "0.35") ) KNOWLEDGE_RETRIEVAL_SCOPE_WEIGHT = float( os.getenv("KNOWLEDGE_RETRIEVAL_SCOPE_WEIGHT", "0.20") ) KNOWLEDGE_RERANK_DEPLOYMENT_ID = int(os.getenv("KNOWLEDGE_RERANK_DEPLOYMENT_ID", "0")) KNOWLEDGE_RERANK_CANDIDATE_LIMIT = int( os.getenv("KNOWLEDGE_RERANK_CANDIDATE_LIMIT", "30") ) KNOWLEDGE_RERANK_MODEL_WEIGHT = float(os.getenv("KNOWLEDGE_RERANK_MODEL_WEIGHT", "0.60")) TICKET_AUTO_RESOLVE_ENABLED = ( os.getenv("TICKET_AUTO_RESOLVE_ENABLED", "false").lower() == "true" ) TICKET_AUTO_RESOLVE_MIN_SCORE = float( os.getenv("TICKET_AUTO_RESOLVE_MIN_SCORE", "0.85") ) WORK_ITEM_DEFAULT_SLA_HOURS = int(os.getenv("WORK_ITEM_DEFAULT_SLA_HOURS", "24")) WORK_ITEM_INTAKE_FAILURE_SLA_HOURS = int( os.getenv("WORK_ITEM_INTAKE_FAILURE_SLA_HOURS", "4") ) WORK_ITEM_SUPPORT_FAILURE_SLA_HOURS = int( os.getenv("WORK_ITEM_SUPPORT_FAILURE_SLA_HOURS", "4") ) WORK_ITEM_CUSTOMER_REPLY_SLA_HOURS = int( os.getenv("WORK_ITEM_CUSTOMER_REPLY_SLA_HOURS", "8") ) WORK_ITEM_TICKET_CLOSE_SLA_HOURS = int( os.getenv("WORK_ITEM_TICKET_CLOSE_SLA_HOURS", "24") ) TICKET_DRAFT_RETENTION_HOURS = int(os.getenv("TICKET_DRAFT_RETENTION_HOURS", "24")) TICKET_MATERIAL_MAX_FILE_BYTES = int( os.getenv("TICKET_MATERIAL_MAX_FILE_BYTES", str(20 * 1024 * 1024)) ) TICKET_MATERIAL_MAX_FILES = int(os.getenv("TICKET_MATERIAL_MAX_FILES", "10")) TICKET_MATERIAL_MAX_TOTAL_BYTES = int( os.getenv("TICKET_MATERIAL_MAX_TOTAL_BYTES", str(100 * 1024 * 1024)) ) TICKET_MATERIAL_MAX_PARSED_CHARS = int( os.getenv("TICKET_MATERIAL_MAX_PARSED_CHARS", "200000") ) TICKET_MATERIAL_SCANNER_BACKEND = os.getenv("TICKET_MATERIAL_SCANNER_BACKEND", "clamav") CLAMAV_HOST = os.getenv("CLAMAV_HOST", "localhost") CLAMAV_PORT = int(os.getenv("CLAMAV_PORT", "3310")) CLAMAV_TIMEOUT_SECONDS = int(os.getenv("CLAMAV_TIMEOUT_SECONDS", "30")) MINIO_ENDPOINT = os.getenv("MINIO_ENDPOINT", "localhost:9000") MINIO_ACCESS_KEY = os.getenv("MINIO_ACCESS_KEY", os.getenv("MINIO_ROOT_USER", "minio")) MINIO_SECRET_KEY = os.getenv("MINIO_SECRET_KEY", os.getenv("MINIO_ROOT_PASSWORD", "minio123")) MINIO_BUCKET = os.getenv("MINIO_BUCKET", "ai-ticket-platform") MINIO_SECURE = os.getenv("MINIO_SECURE", "false").lower() == "true" CELERY_BEAT_SCHEDULE = { "cleanup-expired-agent-runs": { "task": "apps.agents.tasks.cleanup_expired_agent_runs", "schedule": 86400.0, }, "cleanup-expired-ticket-drafts": { "task": "apps.tickets.tasks.cleanup_expired_ticket_drafts", "schedule": 3600.0, }, }