File size: 7,552 Bytes
1838600 9d6dc45 1838600 9d6dc45 1838600 9d6dc45 cc22bc2 9d6dc45 1838600 9d6dc45 1838600 639c192 9d6dc45 e6999f9 9d6dc45 cc22bc2 9d6dc45 76908f5 6ece290 3fb98b1 76908f5 9d6dc45 1838600 9d6dc45 af01f41 1838600 82a7380 df5a519 4cc19a3 df5a519 4cc19a3 df5a519 667605e df5a519 82a7380 df5a519 82a7380 df5a519 82a7380 e6999f9 9d6dc45 cc22bc2 9d6dc45 cc22bc2 9d6dc45 1838600 639c192 9d6dc45 1838600 7b1aabb cc22bc2 639c192 cc22bc2 639c192 5d11c1e 1838600 9d6dc45 1838600 76908f5 1838600 76908f5 1838600 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 | # app/config.py - Application configuration (Production Hardened)
from pydantic_settings import BaseSettings, SettingsConfigDict
from typing import Optional
from functools import lru_cache
from dotenv import load_dotenv
import os
# โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
# FIX 1: HF-SAFE DOTENV LOADING
# On HuggingFace, secrets are injected at runtime. Don't override them.
# โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
if os.getenv("HF_SPACE_ID") is None:
load_dotenv(override=True) # Local dev โ .env
else:
load_dotenv(override=False) # HF prod โ Secrets only
class Settings(BaseSettings):
"""Application settings loaded from environment variables."""
# Application
APP_NAME: str = "Scam Honeypot API"
VERSION: str = "2.5.0"
DEBUG: bool = False
GUVI_API_KEY: str = "" # Must be set via Environment Variable (HF Secrets)
GUVI_CALLBACK_URL: str = "https://hackathon.guvi.in/api/updateHoneyPotFinalResult"
# SOC Hardening (SIEM Integration)
SYSLOG_ENABLED: bool = False
SYSLOG_HOST: str = "localhost"
SYSLOG_PORT: int = 514
# LLM Configuration
LLM_PROVIDER: str = "groq"
OPENAI_API_KEY: Optional[str] = None
ANTHROPIC_API_KEY: Optional[str] = None
GROQ_API_KEY: Optional[str] = None
OPENROUTER_API_KEY: Optional[str] = None
# Local HF (Offline / Free-Tier) Inference
# FIX: Enable by default as crash-proof fallback when Groq fails
USE_LOCAL_HF_MODEL: bool = True # Auto-fallback when API fails
HF_LOCAL_MODEL_NAME: str = "facebook/opt-125m" # Tiny model, runs on CPU
HF_LOCAL_MAX_TOKENS: int = 80 # Short responses like real SMS/chat
HF_LOCAL_DEVICE: str = "cpu" # Explicit so HF Spaces & local dev behave consistently
# โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
# FIX 2: EXPLICIT MODEL DEFAULTS (No None = No Surprises)
# Aligned with Groq limits and capability-aware fallback chains
# โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
GPT_MODEL: str = "gpt-4-turbo-preview"
CLAUDE_MODEL: str = "claude-3-sonnet-20240229"
GROQ_MODEL: str = "llama-3.3-70b-versatile"
# Per-task model routing (Production Grade)
MAX_RETRIES: int = 2
# โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
# FIX: HARD LLM CALL LIMITS (Prevent rate limit exhaustion)
# OPTIMIZED for GUVI's 30s timeout & Groq free tier rate limits
# โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
MAX_LLM_CALLS_PER_REQUEST: int = 6 # Reduced from 10 - fits within 20s timeout
MAX_LLM_CALLS_PER_SESSION: int = 20 # Reduced from 30 - prevents key exhaustion
# Per-task model routing (Production Grade)
# FIX: llama-3.3-70b fails JSON_SCHEMA mode with 400. Use qwen3-32b for structured.
GROQ_FAST_MODEL: str = "llama-3.1-8b-instant" # Blazing fast (~300 tokens/sec)
GROQ_SMART_MODEL: str = "qwen/qwen3-32b" # Native reasoning, 60 RPM
GROQ_NATURAL_MODEL: str = "moonshotai/kimi-k2-instruct-0905"
GROQ_STRUCTURED_MODEL: str = "qwen/qwen3-32b" # FIX: Supports JSON_SCHEMA properly
GROQ_SAFETY_MODEL: str = "meta-llama/llama-guard-4-12b"
GROQ_SAFEGUARD_MODEL: str = "openai/gpt-oss-safeguard-20b"
OPENROUTER_MODEL: str = "meta-llama/llama-3.1-70b-instruct"
# LLM parameters
LLM_TEMPERATURE: float = 0.7
LLM_MAX_TOKENS: int = 500
# Conversation
MAX_CONVERSATION_LENGTH: int = 50
CONVERSATION_TTL_HOURS: int = 24
# Rate Limiting
RATE_LIMIT_PER_MINUTE: int = 60
# Feature Flags
ENABLE_LLM_DETECTION: bool = True
ENABLE_LLM_RESPONSES: bool = True
ENABLE_THREAT_INTELLIGENCE: bool = True
ENABLE_LAW_ENFORCEMENT_API: bool = False # Disabled for hackathon
ENABLE_ENGAGEMENT_DELAY: bool = False
# Forensic Clinic (Compound Systems)
ENABLE_MATH_FORENSICS: bool = False # ๐งฎ Claim Verifier (Compound-Mini)
ENABLE_VISUAL_EVIDENCE: bool = False # ๐ Chart Lab (Compound)
# Database (SQLite default, PostgreSQL/Supabase via env)
DATABASE_URL: str = "sqlite+aiosqlite:///./data/honeypot.db"
# Compliance
SANDBOX_MODE: bool = False
ANONYMIZE_LOGS: bool = True
SYNTHETIC_DATA_ONLY: bool = False
model_config = SettingsConfigDict(
env_file=".env",
env_file_encoding="utf-8",
case_sensitive=True,
extra="allow"
)
@lru_cache()
def get_settings() -> Settings:
return Settings()
settings = get_settings()
# โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
# FIX 3 & 4: STARTUP VALIDATION (Fail Fast)
# โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
def validate_production_config():
"""Validates critical config at startup. Raises RuntimeError if invalid."""
errors = []
# FIX 3: GUVI_API_KEY must be set for scoring
if not settings.GUVI_API_KEY:
errors.append("GUVI_API_KEY missing โ scoring impossible")
# FIX 4: Exactly ONE *external* LLM provider key must be set
# EXCEPTION: When USE_LOCAL_HF_MODEL=True we allow zero external keys
active_keys = [
("GROQ_API_KEY", settings.GROQ_API_KEY),
("OPENAI_API_KEY", settings.OPENAI_API_KEY),
("ANTHROPIC_API_KEY", settings.ANTHROPIC_API_KEY),
("OPENROUTER_API_KEY", settings.OPENROUTER_API_KEY),
]
set_keys = [(name, key) for name, key in active_keys if key]
if len(set_keys) == 0 and not settings.USE_LOCAL_HF_MODEL:
errors.append("No LLM API key set โ system cannot function (set USE_LOCAL_HF_MODEL=True to enable offline mode)")
elif len(set_keys) > 1:
key_names = [name for name, _ in set_keys]
errors.append(f"Multiple LLM API keys set ({', '.join(key_names)}) โ please use exactly one")
# In production, fail hard
if errors and not settings.DEBUG:
raise RuntimeError("๐จ CONFIG VALIDATION FAILED:\n - " + "\n - ".join(errors))
elif errors:
# In debug mode, just warn
import warnings
for err in errors:
warnings.warn(f"โ ๏ธ CONFIG WARNING: {err}")
# Run validation at import time (fail fast)
validate_production_config()
|