|
""" |
|
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 |
|
|
|
|
|
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") |
|
|
|
|
|
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 |
|
|
|
|
|
try: |
|
|
|
subprocess.run(['git', '--version'], check=True, capture_output=True) |
|
|
|
|
|
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: |
|
|
|
os.chdir("src/gaia/agent/tests") |
|
|
|
|
|
result = subprocess.run( |
|
[sys.executable, "run_tests.py"], |
|
check=True, |
|
capture_output=True, |
|
text=True |
|
) |
|
|
|
logger.info("Test output:") |
|
logger.info(result.stdout) |
|
|
|
|
|
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) |
|
|
|
|
|
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") |
|
|
|
|
|
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() |
|
|
|
|
|
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") |
|
|
|
|
|
with open("requirements.txt", "r") as f: |
|
requirements = f.read().splitlines() |
|
|
|
|
|
required_packages = [ |
|
"langchain", |
|
"langchain_core", |
|
"langgraph", |
|
"openai", |
|
"pillow", |
|
"supabase", |
|
"duckduckgo-search", |
|
"youtube-transcript-api", |
|
"pydantic", |
|
"gradio" |
|
] |
|
|
|
|
|
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") |
|
|
|
|
|
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" |
|
] |
|
} |
|
|
|
|
|
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() |
|
|
|
|
|
token = os.environ.get("HF_TOKEN") |
|
|
|
|
|
|
|
repo_id = "your-username/gaia-agent" |
|
|
|
|
|
files_to_upload = [ |
|
"app.py", |
|
"requirements.txt", |
|
"README.md", |
|
".gitignore", |
|
"src/" |
|
] |
|
|
|
|
|
for file_path in files_to_upload: |
|
logger.info(f"Uploading {file_path}") |
|
|
|
if os.path.isdir(file_path): |
|
|
|
api.upload_folder( |
|
folder_path=file_path, |
|
repo_id=repo_id, |
|
repo_type="space", |
|
token=token |
|
) |
|
else: |
|
|
|
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") |
|
|
|
|
|
if not setup_environment(): |
|
logger.error("Environment setup failed. Aborting deployment.") |
|
return 1 |
|
|
|
|
|
if not args.skip_tests: |
|
if not run_tests(): |
|
logger.error("Tests failed. Aborting deployment.") |
|
return 1 |
|
else: |
|
logger.info("Skipping tests as requested") |
|
|
|
|
|
if not prepare_deployment_files(): |
|
logger.error("Failed to prepare deployment files. Aborting deployment.") |
|
return 1 |
|
|
|
|
|
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__": |
|
|
|
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) |