from pydantic_settings import BaseSettings from typing import List, Optional import os class Settings(BaseSettings): # App app_env: str = "development" app_secret_key: str = "dev-secret-key" allowed_origins: str = "http://localhost:5173,http://localhost:3000" # Supabase supabase_url: str = "" supabase_anon_key: str = "" supabase_service_role_key: str = "" supabase_jwt_secret: Optional[str] = None # Settings → API → JWT Secret in Supabase dashboard # Qdrant qdrant_url: str = "http://localhost:6333" qdrant_api_key: Optional[str] = None # LLM Providers openai_api_key: Optional[str] = None anthropic_api_key: Optional[str] = None google_api_key: Optional[str] = None fireworks_api_key: Optional[str] = None # Embeddings embedding_model: str = "text-embedding-3-small" # Stripe stripe_secret_key: str = "" stripe_webhook_secret: str = "" stripe_starter_price_id: str = "" stripe_business_price_id: str = "" stripe_agency_price_id: str = "" # Redis redis_url: str = "redis://localhost:6379" # Sentry sentry_dsn: Optional[str] = None # Files max_file_size_mb: int = 50 # App URL (for widget embedding) app_url: str = "http://localhost:5173" # Backend API URL (used for Telegram webhook registration) api_url: str = "http://localhost:8000" # n8n Handoff webhook n8n_handoff_webhook_url: Optional[str] = None # Supabase Storage supabase_storage_url: str = "" @property def allowed_origins_list(self) -> List[str]: return [o.strip() for o in self.allowed_origins.split(",")] class Config: env_file = ".env" case_sensitive = False settings = Settings() # ═══════════════════════════════════════════════════════════════════════════════ # MODEL CATALOG — Single source of truth for all model metadata # ═══════════════════════════════════════════════════════════════════════════════ # To add a new model: # 1. Add it here with name/provider/badge/description # 2. Add its model_id → provider mapping in MODEL_PROVIDERS # 3. Add it to the appropriate plan(s) in PLAN_LIMITS # That's it — the frontend loads everything from GET /api/v1/models/available # ═══════════════════════════════════════════════════════════════════════════════ MODEL_CATALOG = { # ── Free tier (Fireworks - lightweight) ──────────────────────────────────── "accounts/fireworks/models/llama-v3p3-70b-instruct": { "name": "Llama 3.3 70B", "provider": "Fireworks AI", "badge": "Free", "description": "Free model for building and testing chatbots", }, # ── Starter tier (Fireworks - powerful serverless models) ────────────────── "accounts/fireworks/models/qwen3-235b-a22b": { "name": "Qwen3 235B", "provider": "Fireworks AI", "badge": "Powerful", "description": "High-capability open model with great reasoning", }, "accounts/fireworks/models/deepseek-v3p1": { "name": "DeepSeek V3.1", "provider": "Fireworks AI", "badge": "Smart", "description": "Cost-effective and highly capable model", }, "accounts/fireworks/models/kimi-k2-instruct-0905": { "name": "Kimi K2", "provider": "Fireworks AI", "badge": "Multilingual", "description": "Strong multilingual and coding capabilities", }, "accounts/fireworks/models/gpt-oss-120b": { "name": "GPT OSS 120B", "provider": "Fireworks AI", "badge": "Powerful", "description": "Large open-source model with strong reasoning", }, # ── Pro tier (Premium providers) ─────────────────────────────────────────── # OpenAI "gpt-4o": { "name": "GPT-4o", "provider": "OpenAI", "badge": "Powerful", "description": "Most capable OpenAI model", }, "gpt-4o-mini": { "name": "GPT-4o Mini", "provider": "OpenAI", "badge": "Efficient", "description": "Fast and cost-effective OpenAI model", }, # Anthropic "claude-haiku-4-5-20251001": { "name": "Claude Haiku 4.5", "provider": "Anthropic", "badge": "Fast", "description": "Fast and affordable Anthropic model", }, # Google Gemini "gemini-2.5-flash": { "name": "Gemini 2.5 Flash", "provider": "Google", "badge": "Fast", "description": "Fast and efficient Google model", }, "gemini-2.5-lite": { "name": "Gemini 2.5 Lite", "provider": "Google", "badge": "Lightweight", "description": "Cost-effective Google model", }, "gemini-2.5-pro": { "name": "Gemini 2.5 Pro", "provider": "Google", "badge": "Advanced", "description": "Most capable Google model with long context", }, } # ─── Model ID → LLM provider mapping (used by llm_client.py for routing) ───── MODEL_PROVIDERS = { # Fireworks "accounts/fireworks/models/llama-v3p3-70b-instruct": "fireworks", "accounts/fireworks/models/qwen3-235b-a22b": "fireworks", "accounts/fireworks/models/deepseek-v3p1": "fireworks", "accounts/fireworks/models/kimi-k2-instruct-0905": "fireworks", "accounts/fireworks/models/gpt-oss-120b": "fireworks", # OpenAI "gpt-4o": "openai", "gpt-4o-mini": "openai", # Anthropic "claude-haiku-4-5-20251001": "anthropic", # Google "gemini-2.5-flash": "google", "gemini-2.5-lite": "google", "gemini-2.5-pro": "google", } # ─── Default model per plan (pre-selected in the frontend) ──────────────────── DEFAULT_MODELS = { "free": "accounts/fireworks/models/llama-v3p3-70b-instruct", "starter": "accounts/fireworks/models/qwen3-235b-a22b", "business": "gpt-4o", "agency": "gpt-4o", "enterprise": "gpt-4o", } # ═══════════════════════════════════════════════════════════════════════════════ # PLAN LIMITS — Pricing: Starter $19/mo, Business $49/mo, Agency $99/mo # ═══════════════════════════════════════════════════════════════════════════════ # # Cost analysis (per 1M tokens approx): # Fireworks Llama 3.3 70B: $0.90/M # Fireworks Qwen3 235B: $0.22 in / $0.88 out # Fireworks DeepSeek V3.1: $0.56 in / $1.68 out # Fireworks Kimi K2: $0.60 in / $2.50 out # GPT-4o: $2.50 in / $10.00 out # GPT-4o Mini: $0.15 in / $0.60 out # Claude Haiku 4.5: $0.80 in / $4.00 out # Gemini 2.5 Flash: ~$0.15 in / $0.60 out # Gemini 2.5 Lite: ~$0.075 in / $0.30 out # Gemini 2.5 Pro: ~$1.25 in / $10.00 out # # Avg conversation: ~2K tokens input + 1K output = ~3K tokens # Fireworks models: ~$0.001-$0.004 per conversation # GPT-4o: ~$0.015 per conversation # # Starter $19/mo, 1500 convos: max cost ~$6/mo (fireworks mix) → margin OK # Business $49/mo, 5000 convos: max cost ~$15/mo (mixed models) → margin OK # Agency $99/mo, 20000 convos: max cost ~$30/mo (fireworks) → healthy margin # ═══════════════════════════════════════════════════════════════════════════════ _ALL_FIREWORKS = [ "accounts/fireworks/models/llama-v3p3-70b-instruct", "accounts/fireworks/models/qwen3-235b-a22b", "accounts/fireworks/models/deepseek-v3p1", "accounts/fireworks/models/kimi-k2-instruct-0905", "accounts/fireworks/models/gpt-oss-120b", ] _ALL_PREMIUM = [ "gpt-4o", "gpt-4o-mini", "claude-haiku-4-5-20251001", "gemini-2.5-flash", "gemini-2.5-lite", "gemini-2.5-pro", ] PLAN_LIMITS = { # ── Free ───────────────────────────────────────────────────────────────── # Generous enough to validate the product, limited enough to drive upgrades. "free": { "max_chatbots": 999999, "max_published": 1, "max_documents_per_chatbot": 5, "max_document_size_mb": 5, "models": ["accounts/fireworks/models/llama-v3p3-70b-instruct"], "conversations_limit": 300, "code_export": False, "analytics": False, "gap_suggestions": False, "channels": [], "url_sources": 2, "leads_per_month": 0, "inbox_replies": False, "leads_editing": False, "show_branding": True, "appointments": False, "appointments_chatbots": 0, "campaigns": False, "campaigns_per_month": 0, "max_campaign_recipients": 0, }, # ── Starter $19/mo ─────────────────────────────────────────────────────── # Complete package for individuals and small businesses. "starter": { "max_chatbots": 999999, "max_published": 3, "max_documents_per_chatbot": 20, "max_document_size_mb": 20, "models": _ALL_FIREWORKS, "conversations_limit": 2000, "code_export": False, "analytics": True, "gap_suggestions": False, "channels": ["telegram"], "url_sources": 10, "leads_per_month": 999999, "inbox_replies": True, "leads_editing": True, "show_branding": False, # branding removal starts at Starter "appointments": True, "appointments_chatbots": 3, "campaigns": True, "campaigns_per_month": 5, "max_campaign_recipients": 1000, }, # ── Business $49/mo ────────────────────────────────────────────────────── # Same features as Starter + premium AI models and serious scale. "business": { "max_chatbots": 999999, "max_published": 10, "max_documents_per_chatbot": 100, "max_document_size_mb": 100, "models": _ALL_FIREWORKS + _ALL_PREMIUM, "conversations_limit": 8000, "code_export": False, "analytics": True, "gap_suggestions": True, "channels": ["telegram"], "url_sources": 999999, "leads_per_month": 999999, "inbox_replies": True, "leads_editing": True, "show_branding": False, "appointments": True, "appointments_chatbots": 999999, "campaigns": True, "campaigns_per_month": 999999, "max_campaign_recipients": 5000, }, # ── Agency $99/mo ──────────────────────────────────────────────────────── # For heavy users and agencies. Reserved tier for WhatsApp and future channels. "agency": { "max_chatbots": 999999, "max_published": 999999, "max_documents_per_chatbot": 999999, "max_document_size_mb": 500, "models": _ALL_FIREWORKS + _ALL_PREMIUM, "conversations_limit": 25000, "code_export": True, "analytics": True, "gap_suggestions": True, "channels": ["telegram"], # whatsapp added here when ready "url_sources": 999999, "leads_per_month": 999999, "inbox_replies": True, "leads_editing": True, "show_branding": False, "appointments": True, "appointments_chatbots": 999999, "campaigns": True, "campaigns_per_month": 999999, "max_campaign_recipients": 999999, }, # ── Enterprise (custom) ─────────────────────────────────────────────────── "enterprise": { "max_chatbots": 999999, "max_published": 999999, "max_documents_per_chatbot": 999999, "max_document_size_mb": 999999, "models": ["*"], "conversations_limit": 999999, "code_export": True, "analytics": True, "gap_suggestions": True, "channels": ["telegram"], "url_sources": 999999, "leads_per_month": 999999, "inbox_replies": True, "leads_editing": True, "show_branding": False, "appointments": True, "appointments_chatbots": 999999, "campaigns": True, "campaigns_per_month": 999999, "max_campaign_recipients": 999999, }, }