Add AGENTS.md documentation for AI agent guidance
This commit is contained in:
91
app/config.py
Normal file
91
app/config.py
Normal file
@@ -0,0 +1,91 @@
|
||||
"""Configuration management for watsonx-openai-proxy."""
|
||||
|
||||
import os
|
||||
from typing import Dict, Optional
|
||||
from pydantic_settings import BaseSettings, SettingsConfigDict
|
||||
|
||||
|
||||
class Settings(BaseSettings):
|
||||
"""Application settings loaded from environment variables."""
|
||||
|
||||
# IBM Cloud Configuration
|
||||
ibm_cloud_api_key: str
|
||||
watsonx_project_id: str
|
||||
watsonx_cluster: str = "us-south"
|
||||
|
||||
# Server Configuration
|
||||
host: str = "0.0.0.0"
|
||||
port: int = 8000
|
||||
log_level: str = "info"
|
||||
|
||||
# API Configuration
|
||||
api_key: Optional[str] = None
|
||||
allowed_origins: str = "*"
|
||||
|
||||
# Token Management
|
||||
token_refresh_interval: int = 3000 # 50 minutes in seconds
|
||||
|
||||
model_config = SettingsConfigDict(
|
||||
env_file=".env",
|
||||
env_file_encoding="utf-8",
|
||||
case_sensitive=False,
|
||||
extra="allow", # Allow extra fields for model mapping
|
||||
)
|
||||
|
||||
@property
|
||||
def watsonx_base_url(self) -> str:
|
||||
"""Construct the watsonx.ai base URL from cluster."""
|
||||
return f"https://{self.watsonx_cluster}.ml.cloud.ibm.com/ml/v1"
|
||||
|
||||
@property
|
||||
def cors_origins(self) -> list[str]:
|
||||
"""Parse CORS origins from comma-separated string."""
|
||||
if self.allowed_origins == "*":
|
||||
return ["*"]
|
||||
return [origin.strip() for origin in self.allowed_origins.split(",")]
|
||||
|
||||
def get_model_mapping(self) -> Dict[str, str]:
|
||||
"""Extract model mappings from environment variables.
|
||||
|
||||
Looks for variables like MODEL_MAP_GPT4=ibm/granite-4-h-small
|
||||
and creates a mapping dict.
|
||||
"""
|
||||
import re
|
||||
mapping = {}
|
||||
|
||||
# Check os.environ first
|
||||
for key, value in os.environ.items():
|
||||
if key.startswith("MODEL_MAP_"):
|
||||
model_name = key.replace("MODEL_MAP_", "")
|
||||
model_name = re.sub(r'([A-Z]+)(\d+)', r'\1-\2', model_name)
|
||||
openai_model = model_name.lower().replace("_", "-")
|
||||
mapping[openai_model] = value
|
||||
|
||||
# Also check pydantic's extra fields (from .env file)
|
||||
# These come in as lowercase: model_map_gpt4 instead of MODEL_MAP_GPT4
|
||||
extra = getattr(self, '__pydantic_extra__', {}) or {}
|
||||
for key, value in extra.items():
|
||||
if key.startswith("model_map_"):
|
||||
# Convert back to uppercase for processing
|
||||
model_name = key.replace("model_map_", "").upper()
|
||||
model_name = re.sub(r'([A-Z]+)(\d+)', r'\1-\2', model_name)
|
||||
openai_model = model_name.lower().replace("_", "-")
|
||||
mapping[openai_model] = value
|
||||
|
||||
return mapping
|
||||
|
||||
def map_model(self, openai_model: str) -> str:
|
||||
"""Map an OpenAI model name to a watsonx model ID.
|
||||
|
||||
Args:
|
||||
openai_model: OpenAI model name (e.g., "gpt-4", "gpt-3.5-turbo")
|
||||
|
||||
Returns:
|
||||
Corresponding watsonx model ID, or the original name if no mapping exists
|
||||
"""
|
||||
model_map = self.get_model_mapping()
|
||||
return model_map.get(openai_model, openai_model)
|
||||
|
||||
|
||||
# Global settings instance
|
||||
settings = Settings()
|
||||
Reference in New Issue
Block a user