pkgprateek's picture
fix: fix LANGCHAIN_TRACING for LANGSMITH monitoring
5857a45
"""Configuration management using Pydantic Settings."""
from pydantic import Field
from pydantic_settings import BaseSettings, SettingsConfigDict
class Settings(BaseSettings):
"""Application settings loaded from environment variables."""
model_config = SettingsConfigDict(
env_file=".env", env_file_encoding="utf-8", case_sensitive=False, extra="ignore"
)
# === LLM Providers ===
openrouter_api_key: str = Field(..., description="OpenRouter API key")
# === Search APIs ===
tavily_api_key: str = Field(..., description="Tavily API key for web search")
brave_search_api_key: str | None = Field(
None, description="Brave Search API key (optional backup)"
)
# === Observability ===
langsmith_api_key: str | None = Field(
None, description="LangSmith API key for tracing"
)
langchain_tracing: bool = Field(True, description="Enable LangChain tracing")
langchain_project: str = Field(
"market-intelligence-prod", description="LangSmith project name"
)
langchain_endpoint: str = Field(
"https://api.smith.langchain.com", description="LangSmith endpoint"
)
# === Application Settings ===
environment: str = Field(
"development", description="Environment: development, production"
)
default_model: str = Field(
"x-ai/grok-4.1-fast:free", # Free for testing; production: anthropic/claude-sonnet-4.5 or google/gemini-3-pro-preview
description="Default LLM model (via OpenRouter)",
)
max_cost_per_run: float = Field(
2.0, description="Maximum cost per workflow run (USD)"
)
# === Optional: Local LLM ===
ollama_base_url: str | None = Field(
None, description="Ollama base URL for local models"
)
ollama_model: str = Field("llama3.2:3b", description="Ollama model name")
@property
def is_production(self) -> bool:
"""Check if running in production."""
return self.environment.lower() == "production"
@property
def openrouter_base_url(self) -> str:
"""OpenRouter API base URL."""
return "https://openrouter.ai/api/v1"
def get_settings() -> Settings:
"""Get settings instance (lazy-loaded)."""
return Settings() # type: ignore[call-arg]
# For convenience, but use get_settings() in tests
settings = None # Will be initialized when needed