routeur_ia_api / config /settings.py
Cyril Dupland
With daily
a7400dd
raw
history blame
4.54 kB
"""Application settings using pydantic-settings."""
from pydantic_settings import BaseSettings, SettingsConfigDict
from typing import Optional, Dict
class Settings(BaseSettings):
"""Application settings loaded from environment variables."""
# API Keys
openai_api_key: str
mistralai_api_key: str
# JWT Security
jwt_secret_key: str
jwt_algorithm: str = "HS256"
jwt_expiration_minutes: int = 60
# API Config
api_title: str = "CAPL Routeur IA API"
api_version: str = "1.0.0"
environment: str = "development"
# LangSmith (optional)
langchain_tracing_v2: bool = False
langchain_api_key: Optional[str] = None
langchain_project: str = "routeur-ia"
# Supabase / RAG
supabase_url: Optional[str] = None
supabase_key: Optional[str] = None
supabase_table: str = "documents"
supabase_match_fn: str = "match_documents"
rag_top_k: int = 5
# Multi-index (logical index name -> Supabase table + match function)
# Can be overridden via .env using a JSON structure if desired
vector_indexes: Dict[str, Dict[str, str]] = {
"default": {"table": "documents", "query_name": "match_documents"},
# Example additional indexes (create corresponding table and function in Supabase)
"projects": {"table": "project_documents", "query_name": "match_project_documents"},
# "formations": {"table": "formations", "query_name": "match_formations"},
}
# Upload & chunking (PDF ingestion)
max_upload_mb_pdf: int = 50
chunk_size: int = 1000
chunk_overlap: int = 100
doc_default_type: str = "project_doc"
# Post-processing pipeline configuration
postprocessors_enabled: list[str] = [
"carbon_impact",
"pricing",
"equivalences",
]
currency: str = "USD"
# Pricing per 1,000,000 tokens (input/output)
pricing: dict = {
# Complete or override in .env via nested JSON if needed
"mistral-medium-latest": {"input_per_1m": 0.40, "output_per_1m": 2.00},
"mistral-small-latest": {"input_per_1m": 0.10, "output_per_1m": 0.30},
"mistral-large-latest": {"input_per_1m": 2.00, "output_per_1m": 6.00},
"magistral-small-latest": {"input_per_1m": 0.50, "output_per_1m": 1.50},
"magistral-medium-latest": {"input_per_1m": 2.00, "output_per_1m": 5.00},
}
# Equivalence ratios using kgCO2eq as input
equivalence_ratios: dict = {
# https://impactco2.fr/outils/comparateur
# Ratios expressed as UNITS per kgCO2eq (invert of kgCO2 per unit)
# smartphone: 85.9 kgCO2 per unit β†’ 1 / 85.9 β‰ˆ 0.011643 smartphones per kgCO2
"smartphone_per_kgCO2eq": 0.011643,
# car (km): 219 g CO2 per km β†’ 0.219 kg per km β†’ 1 / 0.219 β‰ˆ 4.566210 km per kgCO2
"car_km_per_kgCO2eq": 4.566210,
# tgv (km): 2.93 g CO2 per km β†’ 0.00293 kg per km β†’ 1 / 0.00293 β‰ˆ 341.296928 km per kgCO2
"tgv_km_per_kgCO2eq": 341.296928,
# water (l): 321 g CO2 per liter β†’ 0.321 kg per liter β†’ 1 / 0.321 β‰ˆ 3.115265 liters per kgCO2
"water_l_per_kgCO2eq": 3.115265,
}
# Voice / Pipecat
voice_enabled: bool = True
voice_stt_model: str = "whisper-1"
voice_stt_language: str = "fr"
voice_tts_voice: str = "alloy"
voice_tts_model: str = "tts-1"
voice_default_model: str = "mistral-large-latest"
voice_max_response_length: int = 500
# VAD (Voice Activity Detection) defaults - overridable via client request_data
voice_vad_stop_secs: float = 0.2
voice_vad_start_secs: float = 0.2
voice_vad_confidence: float = 0.7
voice_vad_min_volume: float = 0.6
# Voice / WebRTC ICE servers (TURN/STUN for NAT traversal)
# Option 1: Static JSON array in VOICE_ICE_SERVERS (e.g. from Metered dashboard)
voice_ice_servers: Optional[str] = None
# Option 2: Twilio TURN - often works on HF Spaces (streamlit-webrtc examples)
twilio_account_sid: Optional[str] = None
twilio_auth_token: Optional[str] = None
# Option 3: Metered API - fetch dynamically at startup
metered_app_name: Optional[str] = None
metered_api_key: Optional[str] = None
# Voice / Daily.co (alternative transport for HF Spaces, NAT traversal)
daily_api_key: Optional[str] = None
model_config = SettingsConfigDict(
env_file=".env",
env_file_encoding="utf-8",
case_sensitive=False,
extra="ignore"
)
# Singleton instance
settings = Settings()