From a3026255fe43fc983fb18d4a7d6fa1abeb07a0dd Mon Sep 17 00:00:00 2001 From: Richard Abrich Date: Wed, 5 Jun 2024 19:16:18 -0400 Subject: [PATCH 1/4] add gradio_client to requirements; add ssh command; add Docker Quickstart to README --- README.md | 10 ++++++++- deploy.py | 45 ++++++++++++++++++++++++++++++++++++++--- deploy_requirements.txt | 1 + 3 files changed, 52 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 194f8ee9..4a6a31dc 100644 --- a/README.md +++ b/README.md @@ -51,6 +51,14 @@ Our method compiles the following models to generate the set of marks: We are standing on the shoulder of the giant GPT-4V ([playground](https://chat.openai.com/))! +### :rocket: Docker Quick Start + +# Build the image +sudo nvidia-docker build -t som . + +# Run the image +sudo docker run -d -p 6092:6092 --gpus all --name som-container som + ### :rocket: Quick Start * Install segmentation packages @@ -90,7 +98,7 @@ And you will see this interface: To deploy SoM to EC2 on AWS via Github Actions: 1. Fork this repository and clone your fork to your local machine. -2. Follow the instructions at the top of `deploy.py`. +2. Follow the instructions at the top of [`deploy.py`](https://github.com/microsoft/SoM/blob/main/deploy.py). ### :point_right: Comparing standard GPT-4V and its combination with SoM Prompting ![teaser_github](https://github.com/microsoft/SoM/assets/11957155/e4720105-b4b2-40c0-9303-2d8f1cb27d91) diff --git a/deploy.py b/deploy.py index 79fbf713..9413a66a 100644 --- a/deploy.py +++ b/deploy.py @@ -702,19 +702,58 @@ def stop( @staticmethod def status() -> None: """ - Lists all EC2 instances tagged with the project name. + Lists all EC2 instances tagged with the project name, along with their HTTP URLs. Returns: None """ ec2 = boto3.resource('ec2') - instances = ec2.instances.filter( Filters=[{'Name': 'tag:Name', 'Values': [config.PROJECT_NAME]}] ) for instance in instances: - logger.info(f"Instance ID: {instance.id}, State: {instance.state['Name']}") + public_ip = instance.public_ip_address + if public_ip: + http_url = f"http://{public_ip}:6092" # assuming port 6092 is used for the Gradio server + logger.info(f"Instance ID: {instance.id}, State: {instance.state['Name']}, HTTP URL: {http_url}") + else: + logger.info(f"Instance ID: {instance.id}, State: {instance.state['Name']}, HTTP URL: Not available (no public IP)") + + @staticmethod + def ssh(project_name: str = config.PROJECT_NAME) -> None: + """ + Establishes an SSH connection to the EC2 instance associated with the specified project name using subprocess. + + Args: + project_name (str): The project name used to tag the instance. Defaults to config.PROJECT_NAME. + + Returns: + None + """ + ec2 = boto3.resource('ec2') + instances = ec2.instances.filter( + Filters=[ + {'Name': 'tag:Name', 'Values': [project_name]}, + {'Name': 'instance-state-name', 'Values': ['running']} + ] + ) + + for instance in instances: + logger.info(f"Attempting to SSH into instance: ID - {instance.id}, IP - {instance.public_ip_address}") + + # Build the SSH command + ssh_command = [ + "ssh", + "-i", config.AWS_EC2_KEY_PATH, + f"ubuntu@{instance.public_ip_address}" + ] + + # Start an interactive shell session + try: + subprocess.run(ssh_command, check=True) + except subprocess.CalledProcessError as e: + logger.error(f"SSH connection failed: {e}") if __name__ == "__main__": fire.Fire(Deploy) diff --git a/deploy_requirements.txt b/deploy_requirements.txt index 1eca6464..f2b1e0aa 100644 --- a/deploy_requirements.txt +++ b/deploy_requirements.txt @@ -1,6 +1,7 @@ boto3==1.34.18 fire==0.5.0 gitpython==3.1.41 +gradio_client==0.17.0 jinja2==3.1.3 loguru==0.7.2 paramiko==3.4.0 From 84728dbb4b0a2b3cd26d7b2dca2b9ad383b15166 Mon Sep 17 00:00:00 2001 From: Richard Abrich Date: Wed, 5 Jun 2024 19:24:27 -0400 Subject: [PATCH 2/4] update instructions in deploy.py --- deploy.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/deploy.py b/deploy.py index 9413a66a..59b004a3 100644 --- a/deploy.py +++ b/deploy.py @@ -47,6 +47,10 @@ python deploy.py status + 8. (optional) SSH into the server: + + python deploy.py ssh + Troubleshooting Token Scope Error: If you encounter an error similar to the following when pushing changes to From 2259f3ccc0edd34dfb1cfac2663c69722345a885 Mon Sep 17 00:00:00 2001 From: Richard Abrich Date: Wed, 5 Jun 2024 19:27:12 -0400 Subject: [PATCH 3/4] "ubuntu" -> config.AWS_EC2_USER --- deploy.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/deploy.py b/deploy.py index 59b004a3..66560f4d 100644 --- a/deploy.py +++ b/deploy.py @@ -449,7 +449,7 @@ def configure_ec2_instance( ssh_retries = 0 while ssh_retries < max_ssh_retries: try: - ssh_client.connect(hostname=ec2_instance_ip, username='ubuntu', pkey=key) + ssh_client.connect(hostname=ec2_instance_ip, username=config.AWS_EC2_USER, pkey=key) break # Successful SSH connection, break out of the loop except Exception as e: ssh_retries += 1 @@ -750,7 +750,7 @@ def ssh(project_name: str = config.PROJECT_NAME) -> None: ssh_command = [ "ssh", "-i", config.AWS_EC2_KEY_PATH, - f"ubuntu@{instance.public_ip_address}" + f"{config.AWS_EC2_USER}@{instance.public_ip_address}" ] # Start an interactive shell session From 2ec8a70fa336e78a928918fd011a3ddbe6319899 Mon Sep 17 00:00:00 2001 From: Richard Abrich Date: Wed, 5 Jun 2024 19:29:23 -0400 Subject: [PATCH 4/4] 6092 -> config.PORT --- deploy.py | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/deploy.py b/deploy.py index 66560f4d..a30fafb0 100644 --- a/deploy.py +++ b/deploy.py @@ -128,6 +128,9 @@ class Config(BaseSettings): AWS_EC2_INSTANCE_TYPE: str = "g4dn.xlarge" # (T4 16GB $0.526/hr x86_64) AWS_EC2_USER: str = "ubuntu" + # Note: changing this requires changing the hard-coded value in other files + PORT = 6092 + class Config: env_file = ".env" env_file_encoding = 'utf-8' @@ -250,7 +253,7 @@ def create_key_pair(key_name: str = config.AWS_EC2_KEY_NAME, key_path: str = con logger.error(f"Error creating key pair: {e}") return None -def get_or_create_security_group_id(ports: list[int] = [22, 6092]) -> str | None: +def get_or_create_security_group_id(ports: list[int] = [22, config.PORT]) -> str | None: """ Retrieves or creates a security group with the specified ports opened. @@ -560,7 +563,7 @@ def get_gradio_server_url(ip_address: str) -> str: Returns: str: The Gradio server URL """ - url = f"http://{ip_address}:6092" # TODO: make port configurable + url = f"http://{ip_address}:{config.PORT}" return url def git_push_set_upstream(branch_name: str): @@ -719,7 +722,7 @@ def status() -> None: for instance in instances: public_ip = instance.public_ip_address if public_ip: - http_url = f"http://{public_ip}:6092" # assuming port 6092 is used for the Gradio server + http_url = f"http://{public_ip}:{config.PORT}" logger.info(f"Instance ID: {instance.id}, State: {instance.state['Name']}, HTTP URL: {http_url}") else: logger.info(f"Instance ID: {instance.id}, State: {instance.state['Name']}, HTTP URL: Not available (no public IP)")