Spaces:
Running
Running
File size: 5,439 Bytes
09801ca | 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 164 165 166 167 168 169 | """
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()
|