File size: 3,503 Bytes
317d1fd 45df059 317d1fd 28471a4 317d1fd 28471a4 1fda7a5 45df059 1fda7a5 45df059 260a069 2a0dea8 260a069 2a0dea8 260a069 2a0dea8 45df059 1fda7a5 45df059 1fda7a5 45df059 260a069 45df059 317d1fd 86b116d 317d1fd |
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 |
import os
import re
import urllib.parse
from dotenv import load_dotenv
class Config:
"""Singleton configuration class with thread-safe implementation"""
_instance = None
_initialized = False
def __new__(cls):
if cls._instance is None:
cls._instance = super(Config, cls).__new__(cls)
return cls._instance
def __init__(self):
if not self._initialized:
load_dotenv()
# Detect if running on HF Spaces
self.is_hf_space = bool(os.getenv("SPACE_ID"))
# API tokens
self.hf_token = os.getenv("HF_TOKEN")
self.openai_api_key = os.getenv("OPENAI_API_KEY")
self.nasa_api_key = os.getenv("NASA_API_KEY")
# API endpoints
self.hf_api_url = self._sanitize_url(os.getenv("HF_API_ENDPOINT_URL", "https://api-inference.huggingface.co/v1/"))
# Fallback settings
self.use_fallback = os.getenv("USE_FALLBACK", "true").lower() == "true"
# Local model configuration
self.local_model_name = os.getenv("LOCAL_MODEL_NAME", "mistral:latest")
self.ollama_host = self._sanitize_url(os.getenv("OLLAMA_HOST", ""))
# OpenWeather API
self.openweather_api_key = os.getenv("OPENWEATHER_API_KEY")
self._initialized = True
def _sanitize_url(self, url: str) -> str:
"""Sanitize URL by removing whitespace and control characters"""
if not url:
return ""
# Remove leading/trailing whitespace and control characters
url = url.strip()
# Remove any newlines, carriage returns, tabs, and null bytes
url = re.sub(r'[\r\n\t\0\x0b\x0c]+', '', url)
# Remove any trailing URL encoding artifacts
url = url.rstrip('%0a').rstrip('%0d')
# Handle the specific case where environment variable name is included
if 'hf_api_endpoint_url=' in url.lower():
# Extract the actual URL part
url = url.split('=')[-1]
# Remove any protocol prefix issues
url = url.replace('hf_api_endpoint_url=', '')
url = url.replace('HF_API_ENDPOINT_URL=', '')
# Ensure proper URL format
if url and not url.startswith(('http://', 'https://')):
# Check if it looks like a domain
if re.match(r'^[a-zA-Z0-9.-]+(?:\.[a-zA-Z]{2,})+', url) or 'huggingface.cloud' in url:
url = 'https://' + url
else:
url = 'https://' + url
# Remove double slashes (but keep ://)
if '://' in url:
protocol, rest = url.split('://', 1)
rest = re.sub(r'//+', '/', rest)
url = protocol + '://' + rest
return url
def _sanitize_host(self, host: str) -> str:
"""Sanitize host by removing whitespace and control characters"""
if not host:
return ""
# Remove leading/trailing whitespace and control characters
host = host.strip()
# Remove any newlines, carriage returns, tabs, and null bytes
host = re.sub(r'[\r\n\t\0\x0b\x0c]+', '', host)
# Remove any trailing URL encoding artifacts
host = host.rstrip('%0a').rstrip('%0d')
return host
# Global config instance
config = Config()
|