jeanbaptdzd's picture
feat: Clean deployment to HuggingFace Space with model config test endpoint
8c0b652
#!/usr/bin/env python3
"""
Unified Deployment Script for LinguaCustodia Financial AI API
Supports multiple deployment platforms with a single interface.
"""
import os
import sys
import logging
import argparse
from typing import Dict, Any
from dotenv import load_dotenv
# Load environment variables
load_dotenv()
# Configure logging
logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s')
logger = logging.getLogger(__name__)
def deploy_to_huggingface():
"""Deploy to HuggingFace Spaces."""
logger.info("πŸš€ Deploying to HuggingFace Spaces...")
try:
from deployment_config import get_huggingface_config
config = get_huggingface_config()
logger.info(f"πŸ“¦ Space: {config.space_name}")
logger.info(f"πŸ–₯️ Hardware: {config.hardware}")
logger.info(f"πŸ’Ύ Storage: {config.storage_size}")
# For HuggingFace Spaces, we just need to ensure the app is ready
logger.info("βœ… HuggingFace Spaces deployment ready")
logger.info("πŸ“ Next steps:")
logger.info(" 1. Push code to HuggingFace repository")
logger.info(" 2. Configure space settings in HuggingFace UI")
logger.info(" 3. Set environment variables in space settings")
return True
except Exception as e:
logger.error(f"❌ HuggingFace deployment failed: {e}")
return False
def deploy_to_scaleway():
"""Deploy to Scaleway cloud platform."""
logger.info("πŸš€ Deploying to Scaleway...")
try:
from deployment_config import get_scaleway_config
from scaleway_deployment import ScalewayDeployment
config = get_scaleway_config()
deployment = ScalewayDeployment()
# List existing deployments
logger.info("πŸ“‹ Checking existing deployments...")
existing = deployment.list_deployments()
logger.info(f"Found {existing['total_namespaces']} namespaces and {existing['total_functions']} functions")
# Use existing namespace or create new one
if existing['total_namespaces'] > 0:
logger.info("πŸ“ Using existing namespace...")
namespace = {
"namespace_id": existing['namespaces'][0]['id'],
"name": existing['namespaces'][0]['name']
}
logger.info(f"βœ… Using existing namespace: {namespace['namespace_id']}")
else:
logger.info("πŸ—οΈ Creating container namespace...")
namespace = deployment.create_container_namespace(config.namespace_name)
logger.info(f"βœ… Namespace created: {namespace['namespace_id']}")
# Deploy container
logger.info("πŸš€ Deploying LinguaCustodia API container...")
container = deployment.deploy_container(
namespace['namespace_id'],
config.container_name
)
logger.info(f"βœ… Container created: {container['container_id']}")
if container.get('endpoint'):
logger.info(f"🌐 API endpoint: {container['endpoint']}")
return True
except Exception as e:
logger.error(f"❌ Scaleway deployment failed: {e}")
return False
def deploy_to_koyeb():
"""Deploy to Koyeb cloud platform."""
logger.info("πŸš€ Deploying to Koyeb...")
try:
from deployment_config import get_koyeb_config
config = get_koyeb_config()
logger.info(f"πŸ“¦ App: {config.app_name}")
logger.info(f"πŸ”§ Service: {config.service_name}")
logger.info(f"πŸ–₯️ Instance: {config.instance_type}")
logger.info(f"πŸ“ Region: {config.region}")
# For Koyeb, we would use their API or CLI
logger.info("βœ… Koyeb deployment configuration ready")
logger.info("πŸ“ Next steps:")
logger.info(" 1. Install Koyeb CLI: curl -fsSL https://cli.koyeb.com/install.sh | sh")
logger.info(" 2. Login: koyeb auth login")
logger.info(" 3. Deploy: koyeb app create --name lingua-custodia-api")
return True
except Exception as e:
logger.error(f"❌ Koyeb deployment failed: {e}")
return False
def deploy_to_docker():
"""Deploy using Docker."""
logger.info("πŸš€ Deploying with Docker...")
try:
import subprocess
# Build Docker image
logger.info("πŸ”¨ Building Docker image...")
result = subprocess.run([
"docker", "build", "-t", "lingua-custodia-api", "."
], capture_output=True, text=True)
if result.returncode != 0:
logger.error(f"❌ Docker build failed: {result.stderr}")
return False
logger.info("βœ… Docker image built successfully")
# Run container
logger.info("πŸš€ Starting Docker container...")
result = subprocess.run([
"docker", "run", "-d",
"--name", "lingua-custodia-api",
"-p", "8000:8000",
"--env-file", ".env",
"lingua-custodia-api"
], capture_output=True, text=True)
if result.returncode != 0:
logger.error(f"❌ Docker run failed: {result.stderr}")
return False
logger.info("βœ… Docker container started successfully")
logger.info("🌐 API available at: http://localhost:8000")
return True
except Exception as e:
logger.error(f"❌ Docker deployment failed: {e}")
return False
def list_deployments():
"""List existing deployments."""
logger.info("πŸ“‹ Listing existing deployments...")
try:
from deployment_config import get_scaleway_config
from scaleway_deployment import ScalewayDeployment
config = get_scaleway_config()
deployment = ScalewayDeployment()
deployments = deployment.list_deployments()
logger.info(f"πŸ“¦ Namespaces ({deployments['total_namespaces']}):")
for ns in deployments['namespaces']:
logger.info(f" - {ns['name']} ({ns['id']})")
logger.info(f"⚑ Functions ({deployments['total_functions']}):")
for func in deployments['functions']:
logger.info(f" - {func['name']} ({func['id']})")
return True
except Exception as e:
logger.error(f"❌ Failed to list deployments: {e}")
return False
def validate_environment():
"""Validate deployment environment."""
logger.info("πŸ” Validating deployment environment...")
try:
from deployment_config import get_deployment_config, validate_deployment_config, get_environment_info
# Get configuration
config = get_deployment_config()
# Validate configuration
if not validate_deployment_config(config):
return False
# Get environment info
env_info = get_environment_info()
logger.info("βœ… Environment validation passed")
logger.info(f"πŸ“¦ Platform: {config.platform}")
logger.info(f"🌍 Environment: {config.environment}")
logger.info(f"🏷️ App name: {config.app_name}")
logger.info(f"πŸ”Œ Port: {config.app_port}")
logger.info(f"πŸ€– Model: {config.default_model}")
return True
except Exception as e:
logger.error(f"❌ Environment validation failed: {e}")
return False
def main():
"""Main deployment function."""
parser = argparse.ArgumentParser(description="Deploy LinguaCustodia Financial AI API")
parser.add_argument("platform", choices=["huggingface", "scaleway", "koyeb", "docker"],
help="Deployment platform")
parser.add_argument("--validate", action="store_true", help="Validate environment only")
parser.add_argument("--list", action="store_true", help="List existing deployments")
args = parser.parse_args()
try:
logger.info("πŸš€ LinguaCustodia Financial AI API Deployment")
logger.info("=" * 50)
# Validate environment first
if not validate_environment():
logger.error("❌ Environment validation failed")
sys.exit(1)
if args.validate:
logger.info("βœ… Environment validation completed")
return
if args.list:
list_deployments()
return
# Deploy to selected platform
success = False
if args.platform == "huggingface":
success = deploy_to_huggingface()
elif args.platform == "scaleway":
success = deploy_to_scaleway()
elif args.platform == "koyeb":
success = deploy_to_koyeb()
elif args.platform == "docker":
success = deploy_to_docker()
if success:
logger.info("πŸŽ‰ Deployment completed successfully!")
else:
logger.error("❌ Deployment failed")
sys.exit(1)
except Exception as e:
logger.error(f"❌ Deployment error: {e}")
sys.exit(1)
if __name__ == "__main__":
main()