JoachimVC's picture
Implement full GAIA agent solution with formatter and multimodal processing
460ec88
"""
GAIA Agent Deployment Script
This script prepares and deploys the GAIA agent to Hugging Face Space.
It handles packaging, file preparation, and deployment of the latest version.
"""
import os
import sys
import shutil
import subprocess
import argparse
import logging
from datetime import datetime
# Set up logging
logging.basicConfig(
level=logging.INFO,
format='%(asctime)s - %(name)s - %(levelname)s - %(message)s',
handlers=[
logging.FileHandler("deployment.log"),
logging.StreamHandler()
]
)
logger = logging.getLogger("gaia_deploy")
def setup_environment():
"""
Set up the deployment environment and verify dependencies.
Returns:
bool: True if setup succeeds, False otherwise
"""
logger.info("Setting up deployment environment")
# Check for required environmental variables
required_env_vars = ["HF_TOKEN"]
missing_vars = [var for var in required_env_vars if not os.environ.get(var)]
if missing_vars:
logger.error(f"Missing required environment variables: {', '.join(missing_vars)}")
logger.error("Please set the HF_TOKEN environment variable with your Hugging Face API token")
return False
# Check for required dependencies
try:
# Check for git
subprocess.run(['git', '--version'], check=True, capture_output=True)
# Check for huggingface_hub
import huggingface_hub
logger.info(f"Using huggingface_hub version: {huggingface_hub.__version__}")
except (subprocess.SubprocessError, ImportError) as e:
logger.error(f"Missing required dependency: {str(e)}")
logger.error("Please install required dependencies: pip install huggingface_hub")
return False
logger.info("Environment setup successful")
return True
def run_tests():
"""
Run the test suite to ensure everything is working correctly.
Returns:
bool: True if all tests pass, False otherwise
"""
logger.info("Running GAIA agent tests")
try:
# Change to the tests directory
os.chdir("src/gaia/agent/tests")
# Run the tests
result = subprocess.run(
[sys.executable, "run_tests.py"],
check=True,
capture_output=True,
text=True
)
logger.info("Test output:")
logger.info(result.stdout)
# Go back to the original directory
os.chdir("../../../..")
logger.info("All tests passed successfully")
return True
except subprocess.CalledProcessError as e:
logger.error("Tests failed")
logger.error(e.stdout)
logger.error(e.stderr)
# Go back to the original directory
os.chdir("../../../..")
return False
def prepare_deployment_files():
"""
Prepare files for deployment by ensuring all necessary files are present.
Returns:
bool: True if preparation succeeds, False otherwise
"""
logger.info("Preparing deployment files")
# Check for required files
required_files = [
"app.py",
"requirements.txt",
"README.md",
"src/gaia/agent/agent_integrated.py",
"src/gaia/agent/answer_formatter.py",
"src/gaia/agent/multimodal_processor.py"
]
missing_files = [file for file in required_files if not os.path.exists(file)]
if missing_files:
logger.error(f"Missing required files: {', '.join(missing_files)}")
return False
# Update requirements.txt if needed
update_requirements()
# Create version info file
create_version_info()
logger.info("Deployment files prepared successfully")
return True
def update_requirements():
"""Update requirements.txt to ensure all dependencies are listed."""
logger.info("Updating requirements.txt")
# Read existing requirements
with open("requirements.txt", "r") as f:
requirements = f.read().splitlines()
# Add any missing requirements
required_packages = [
"langchain",
"langchain_core",
"langgraph",
"openai",
"pillow",
"supabase",
"duckduckgo-search",
"youtube-transcript-api",
"pydantic",
"gradio"
]
# Check if each package is in the requirements
new_requirements = requirements.copy()
for package in required_packages:
if not any(req.startswith(f"{package}==") or req == package for req in requirements):
new_requirements.append(package)
logger.info(f"Added {package} to requirements.txt")
# Write updated requirements
if new_requirements != requirements:
with open("requirements.txt", "w") as f:
f.write("\n".join(new_requirements))
logger.info("Updated requirements.txt")
def create_version_info():
"""Create a version info file with deployment timestamp."""
logger.info("Creating version info file")
version_info = {
"version": "1.0.0",
"deployed_at": datetime.now().isoformat(),
"components": [
"integrated_agent",
"answer_formatter",
"multimodal_processor",
"component_analyzers"
]
}
# Write version info to a file
version_file = "src/gaia/version.py"
with open(version_file, "w") as f:
f.write(f"VERSION = \"{version_info['version']}\"\n")
f.write(f"DEPLOYED_AT = \"{version_info['deployed_at']}\"\n")
f.write(f"COMPONENTS = {version_info['components']}\n")
logger.info(f"Created version info at {version_file}")
def deploy_to_huggingface():
"""
Deploy the agent to Hugging Face Space.
Returns:
bool: True if deployment succeeds, False otherwise
"""
logger.info("Deploying to Hugging Face Space")
try:
from huggingface_hub import HfApi
api = HfApi()
# Get Hugging Face token from environment
token = os.environ.get("HF_TOKEN")
# Set repository ID (username/space-name)
# TODO: Replace with your actual repository ID
repo_id = "your-username/gaia-agent"
# Files to upload
files_to_upload = [
"app.py",
"requirements.txt",
"README.md",
".gitignore",
"src/"
]
# Upload each file/directory
for file_path in files_to_upload:
logger.info(f"Uploading {file_path}")
if os.path.isdir(file_path):
# Upload directory recursively
api.upload_folder(
folder_path=file_path,
repo_id=repo_id,
repo_type="space",
token=token
)
else:
# Upload single file
api.upload_file(
path_or_fileobj=file_path,
path_in_repo=file_path,
repo_id=repo_id,
repo_type="space",
token=token
)
logger.info("Deployment to Hugging Face successful")
return True
except Exception as e:
logger.error(f"Deployment failed: {str(e)}")
logger.error(traceback.format_exc())
return False
def main():
"""Main deployment function."""
parser = argparse.ArgumentParser(description="Deploy GAIA agent to Hugging Face Space")
parser.add_argument("--skip-tests", action="store_true", help="Skip running tests")
parser.add_argument("--prepare-only", action="store_true", help="Only prepare files without deploying")
args = parser.parse_args()
logger.info("Starting GAIA agent deployment process")
# Set up environment
if not setup_environment():
logger.error("Environment setup failed. Aborting deployment.")
return 1
# Run tests
if not args.skip_tests:
if not run_tests():
logger.error("Tests failed. Aborting deployment.")
return 1
else:
logger.info("Skipping tests as requested")
# Prepare deployment files
if not prepare_deployment_files():
logger.error("Failed to prepare deployment files. Aborting deployment.")
return 1
# Deploy to Hugging Face
if not args.prepare_only:
if not deploy_to_huggingface():
logger.error("Deployment failed.")
return 1
else:
logger.info("Files prepared successfully. Skipping deployment as requested.")
logger.info("Deployment process completed successfully")
return 0
if __name__ == "__main__":
# Add traceback import for exception handling
import traceback
try:
sys.exit(main())
except Exception as e:
logger.error(f"Unhandled exception: {str(e)}")
logger.error(traceback.format_exc())
sys.exit(1)