mirror of
http://88.130.71.182:3000/BlitTech/contexta_be.git
synced 2026-06-13 08:56:20 +00:00
357 lines
14 KiB
Python
357 lines
14 KiB
Python
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/deepseek-v3p2": {
|
|
"name": "DeepSeek V3.2",
|
|
"provider": "Fireworks AI",
|
|
"badge": "Smart",
|
|
"description": "Latest DeepSeek — faster and more capable",
|
|
},
|
|
"accounts/fireworks/models/kimi-k2-instruct": {
|
|
"name": "Kimi K2",
|
|
"provider": "Fireworks AI",
|
|
"badge": "Multilingual",
|
|
"description": "Strong multilingual and coding capabilities",
|
|
},
|
|
"accounts/fireworks/models/kimi-k2p5-instruct": {
|
|
"name": "Kimi K2.5",
|
|
"provider": "Fireworks AI",
|
|
"badge": "Multilingual",
|
|
"description": "Upgraded Kimi — stronger reasoning and multilingual",
|
|
},
|
|
|
|
# ── 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/deepseek-v3p2": "fireworks",
|
|
"accounts/fireworks/models/kimi-k2-instruct": "fireworks",
|
|
"accounts/fireworks/models/kimi-k2p5-instruct": "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/deepseek-v3p2",
|
|
"accounts/fireworks/models/kimi-k2-instruct",
|
|
"accounts/fireworks/models/kimi-k2p5-instruct",
|
|
]
|
|
_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 ─────────────────────────────────────────────────────────────────
|
|
# Build, test, and go live with one chatbot — no card needed.
|
|
"free": {
|
|
"max_chatbots": 999999,
|
|
"max_published": 1, # can publish 1 chatbot
|
|
"max_documents_per_chatbot": 3,
|
|
"max_document_size_mb": 5,
|
|
"models": ["accounts/fireworks/models/llama-v3p3-70b-instruct"],
|
|
"conversations_limit": 100, # 100 real conversations/month
|
|
"code_export": False,
|
|
"analytics": False,
|
|
"gap_suggestions": False,
|
|
"channels": [], # no messaging channels
|
|
"url_sources": 0,
|
|
"leads_per_month": 0,
|
|
"inbox_replies": False, # read-only inbox
|
|
"leads_editing": False, # view-only leads
|
|
"show_branding": True, # cannot remove badge
|
|
"appointments": False,
|
|
"appointments_chatbots": 0,
|
|
"campaigns": False,
|
|
"campaigns_per_month": 0,
|
|
"max_campaign_recipients": 0,
|
|
},
|
|
# ── Starter $19/mo ───────────────────────────────────────────────────────
|
|
# For solo operators: live chat, leads, booking, and campaigns.
|
|
"starter": {
|
|
"max_chatbots": 999999,
|
|
"max_published": 3,
|
|
"max_documents_per_chatbot": 10,
|
|
"max_document_size_mb": 10,
|
|
"models": _ALL_FIREWORKS,
|
|
"conversations_limit": 1500,
|
|
"code_export": False,
|
|
"analytics": True,
|
|
"gap_suggestions": False,
|
|
"channels": ["telegram"],
|
|
"url_sources": 5,
|
|
"leads_per_month": 500,
|
|
"inbox_replies": True,
|
|
"leads_editing": True,
|
|
"show_branding": True, # badge stays on Starter
|
|
"appointments": True,
|
|
"appointments_chatbots": 1, # booking on 1 chatbot
|
|
"campaigns": True,
|
|
"campaigns_per_month": 3,
|
|
"max_campaign_recipients": 500,
|
|
},
|
|
# ── Business $49/mo ──────────────────────────────────────────────────────
|
|
# For growing businesses: premium AI, unlimited booking, full analytics.
|
|
"business": {
|
|
"max_chatbots": 999999,
|
|
"max_published": 10,
|
|
"max_documents_per_chatbot": 50,
|
|
"max_document_size_mb": 50,
|
|
"models": _ALL_FIREWORKS + _ALL_PREMIUM,
|
|
"conversations_limit": 5000,
|
|
"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, # can remove badge
|
|
"appointments": True,
|
|
"appointments_chatbots": 999999,
|
|
"campaigns": True,
|
|
"campaigns_per_month": 999999,
|
|
"max_campaign_recipients": 5000,
|
|
},
|
|
# ── Agency $99/mo ────────────────────────────────────────────────────────
|
|
# For agencies: unlimited everything, unlimited campaign recipients.
|
|
"agency": {
|
|
"max_chatbots": 999999,
|
|
"max_published": 999999,
|
|
"max_documents_per_chatbot": 999999,
|
|
"max_document_size_mb": 200,
|
|
"models": _ALL_FIREWORKS + _ALL_PREMIUM,
|
|
"conversations_limit": 20000,
|
|
"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,
|
|
},
|
|
# ── 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,
|
|
},
|
|
} |