Datavision / backend /config /settings.py
DataVision CI/CD Bot
release: clean production build for HuggingFace Space
09801ca
Raw
History Blame Contribute Delete
5.44 kB
"""
Settings configuration for the application
"""
import os
import logging
from pathlib import Path
from dotenv import load_dotenv
# Configure Basic Logging
# Configure Basic Logging
import sys
# Custom log filter to redact sensitive information
class SensitiveDataFilter(logging.Filter):
"""Filter to redact sensitive data from logs"""
SENSITIVE_PATTERNS = [
('gsk_', 8), # Groq API keys
('sk-', 20), # OpenAI-style keys
('Bearer ', 20), # JWT tokens
('password', 0), # Passwords
('secret', 0), # Secrets
('api_key', 0), # API keys
('token', 0), # Tokens
]
def filter(self, record):
if hasattr(record, 'msg') and isinstance(record.msg, str):
msg = record.msg
for pattern, chars_to_show in self.SENSITIVE_PATTERNS:
if pattern.lower() in msg.lower():
# Redact sensitive values
import re
# Redact values after = or :
msg = re.sub(
rf'({pattern}[=:\s]*)[^\s,\]}}]+',
rf'\1[REDACTED]',
msg,
flags=re.IGNORECASE
)
record.msg = msg
return True
# Create handler with filter
handler = logging.StreamHandler(sys.stdout)
handler.addFilter(SensitiveDataFilter())
logging.basicConfig(
level=logging.INFO,
format='%(asctime)s - %(name)s - %(levelname)s - %(message)s',
handlers=[handler],
force=True
)
logger = logging.getLogger("settings")
# Load .env file
PROJECT_ROOT = Path(__file__).resolve().parent.parent.parent
ENV_PATH = PROJECT_ROOT / ".env"
BACKEND_ENV = Path(__file__).resolve().parent.parent / ".env"
FRONTEND_ENV = PROJECT_ROOT / "frontend" / ".env"
env_loaded = False
for env_file in [ENV_PATH, BACKEND_ENV, FRONTEND_ENV]:
if env_file.exists():
load_dotenv(env_file, override=True)
logger.info(f"Loaded .env from: {env_file}")
env_loaded = True
if not env_loaded:
logger.warning("No specific .env file found, using system environment")
class Settings:
"""Application settings"""
# Base paths
BASE_DIR = Path(__file__).resolve().parent.parent
STORAGE = BASE_DIR / "storage"
UPLOADS = STORAGE / "uploads"
FAISS_DIR = STORAGE / "faiss"
GRAPH_DIR = STORAGE / "graph"
# API settings
API_VERSION = "v1"
# Model settings - GROQ PRIMARY
MODEL_NAME = "groq/llama-3.3-70b-versatile"
FAST_MODEL = "groq/llama-3.1-8b-instant"
REASONING_MODEL = "groq/llama-3.3-70b-versatile"
FALLBACK_MODEL = "groq/llama-3.1-8b-instant"
EMBEDDING_MODEL = "sentence-transformers/all-MiniLM-L6-v2"
# LLM Provider Support (groq | huggingface | ollama)
LLM_PROVIDER = os.environ.get("LLM_PROVIDER", "groq").lower()
# API Keys Management
GROQ_API_KEYS = []
# Processing settings
CHUNK_SIZE = 700
CHUNK_OVERLAP = 150
EMBED_DIM = 384
GRAPH_MAX_NODES = 100
# ⚡ PERFORMANCE OPTIMIZATION SETTINGS
FAST_MODE = False # Set True for faster (less detailed) responses
CACHE_ENABLED = True # Enable response caching
CACHE_TTL_SECONDS = 3600 # 1 hour cache TTL
MAX_TOKENS_FAST = 500 # Max tokens for fast mode
MAX_TOKENS_NORMAL = 1500 # Max tokens for normal mode
MAX_RAG_STEPS = 2 # Limit RAG iterations
MAX_AGENT_STEPS = 3 # Limit agent iterations
# Exchange Rates (MVP Static Source)
EXCHANGE_RATES = {
"INR_TO_USD": 88.0,
"INR_TO_EUR": 92.0,
"INR_TO_GBP": 110.0,
"USD_TO_INR": 88.0,
"EUR_TO_INR": 92.0,
"GBP_TO_INR": 110.0,
}
@classmethod
def load_api_keys(cls):
"""Robustly load API keys"""
# Primary Key
main_key = os.environ.get("GROQ_API_KEY")
if main_key:
cls.GROQ_API_KEYS.append(main_key)
# Fallback Keys (GROQ_KEY_1 to GROQ_KEY_10)
for i in range(1, 11):
key = os.environ.get(f"GROQ_KEY_{i}")
if key and key not in cls.GROQ_API_KEYS:
cls.GROQ_API_KEYS.append(key)
# List Keys
if os.environ.get("GROQ_API_KEYS_LIST"):
for k in os.environ.get("GROQ_API_KEYS_LIST").split(","):
clean_k = k.strip()
if clean_k and clean_k not in cls.GROQ_API_KEYS:
cls.GROQ_API_KEYS.append(clean_k)
if not cls.GROQ_API_KEYS:
logger.warning("No GROQ API keys found! Set GROQ_API_KEY in .env")
else:
# Set the primary key for libraries that expect it env-wide
os.environ["GROQ_API_KEY"] = cls.GROQ_API_KEYS[0]
logger.info(f"Loaded {len(cls.GROQ_API_KEYS)} Groq API keys")
# Gemini / Google
if os.environ.get("GEMINI_API_KEY"):
os.environ["GOOGLE_API_KEY"] = os.environ.get("GEMINI_API_KEY")
# Nvidia
if os.environ.get("NVIDIA_API_KEY"):
logger.info("Loaded Nvidia API key")
@classmethod
def ensure_directories(cls):
"""Create necessary directories"""
for path in [cls.STORAGE, cls.UPLOADS, cls.FAISS_DIR, cls.GRAPH_DIR]:
path.mkdir(exist_ok=True, parents=True)
# Initialize
Settings.load_api_keys()
Settings.ensure_directories()