Skip to content

Add Dockerfile and client.py; deploy to EC2 on AWS via Github Actions #19

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 102 commits into from
Mar 15, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
102 commits
Select commit Hold shift + click to select a range
14685b4
Add deploy.py; .env.example; Dockerfile; client_requirements.txt; doc…
abrichr Jan 14, 2024
5e02317
add .github/workflows/docker-build.yml
abrichr Jan 14, 2024
680c358
FORCE_CUDA=1
abrichr Jan 14, 2024
b5c88d8
add .cirun.yml
abrichr Jan 14, 2024
a84bbdd
add buildspec.yml
abrichr Jan 14, 2024
71c2504
attach CloudWatchLogsFullAccess
abrichr Jan 14, 2024
ae6eae6
fixes
abrichr Jan 14, 2024
ce5ff1d
fix
abrichr Jan 14, 2024
18f9e0e
fix
abrichr Jan 14, 2024
f44f5fa
fix
abrichr Jan 14, 2024
577815f
fix
abrichr Jan 14, 2024
2c74551
check out correct branch in buildspec
abrichr Jan 15, 2024
a514e4b
echo commit id
abrichr Jan 15, 2024
486b30b
increase verbosity
abrichr Jan 15, 2024
ea93775
increase verbosity
abrichr Jan 15, 2024
330bc0f
wip
abrichr Jan 15, 2024
f85bea9
wip
abrichr Jan 15, 2024
bb08590
udpate README
abrichr Jan 15, 2024
c197f70
LINUX_GPU_CONTAINER
abrichr Jan 15, 2024
a68d7c4
remove .cirun.yml
abrichr Jan 15, 2024
bbe3167
wip: configure_ec2_instance
abrichr Jan 15, 2024
bb9a9c8
generate_github_actions_workflow__ec2
abrichr Jan 15, 2024
219729d
set ec2 key in github secrets
abrichr Jan 16, 2024
295a8d0
push to ecr
abrichr Jan 16, 2024
4bdb600
add missing region
abrichr Jan 16, 2024
1d9b9eb
handle pending
abrichr Jan 16, 2024
06ae173
dummy script
abrichr Jan 16, 2024
407c52b
dummy script
abrichr Jan 16, 2024
9f305fa
update workflow
abrichr Jan 16, 2024
a257217
checkout branch
abrichr Jan 16, 2024
1098b96
fixes
abrichr Jan 16, 2024
b8eee3d
command_timeout
abrichr Jan 17, 2024
46a90e5
update ami
abrichr Jan 17, 2024
a0e116d
update ami
abrichr Jan 17, 2024
6ee924e
FORCE_CUDA=1
abrichr Jan 17, 2024
e06263b
devel base image
abrichr Jan 17, 2024
7ac2f4b
fixes
abrichr Feb 2, 2024
aec2dd6
fixes
abrichr Feb 2, 2024
d4e2554
nvidia-smi; --gpu all
abrichr Feb 2, 2024
3ca5175
regenerate docker-build-ec2.yml
abrichr Feb 2, 2024
1928e88
install nvidia-container-toolkit
abrichr Feb 2, 2024
ba0ddb5
remove --gpus from build command
abrichr Feb 2, 2024
2c421e6
nvidia-docker build
abrichr Feb 2, 2024
0ea528f
nvcc instead of nvidia-smi
abrichr Feb 2, 2024
ab5c5c2
force rebuild
abrichr Feb 2, 2024
9beb2f4
git pull
abrichr Feb 2, 2024
561abfd
ubuntu20.04 -> 22.04
abrichr Feb 2, 2024
4f6ba5c
install ninja-build; comment out python install; comment out nvidia-d…
abrichr Feb 2, 2024
23b5e0d
uncomment out python install
abrichr Feb 2, 2024
aa7f396
apt-get install ninja-build
abrichr Feb 2, 2024
fe37bbd
remove ninja-build from pip
abrichr Feb 2, 2024
2daea71
cu113 -> cu123
abrichr Feb 2, 2024
fd6edcc
set TORCH_CUDA_ARCH_LIST in ops/make.sh
abrichr Feb 2, 2024
8c24673
bash make
abrichr Feb 2, 2024
7e6d538
install wget
abrichr Feb 2, 2024
0acc3e0
add -repo to ECR repo name
abrichr Feb 2, 2024
5aa0f80
fix typo
abrichr Feb 2, 2024
f9a8975
pip install gradio
abrichr Feb 2, 2024
ecbcacb
regenerate
abrichr Feb 2, 2024
9f4dc66
upgrade pip
abrichr Feb 2, 2024
f42fd3f
pin client_requirements.txt versions
abrichr Feb 2, 2024
9aff7fd
pip install detectron2
abrichr Feb 5, 2024
e8c0ceb
regenerate yml
abrichr Feb 5, 2024
fa6be54
typo
abrichr Feb 5, 2024
fc59123
move detectron2 install to make.sh
abrichr Feb 5, 2024
ff0ce67
mpi4py
abrichr Feb 5, 2024
e8c324b
new yml
abrichr Feb 5, 2024
63d3a69
install seem package then 1.0
abrichr Feb 5, 2024
5c563cd
import seem in Dockerfile
abrichr Feb 5, 2024
4b9ba61
pin seem
abrichr Feb 6, 2024
20db398
expose 8092; env GRADIO_SERVER_NAME
abrichr Feb 6, 2024
808d69e
remove ECR, cleanup
abrichr Feb 6, 2024
86d5668
stop and remove container
abrichr Feb 6, 2024
1ecac8f
OPENAI_API_KEY
abrichr Feb 6, 2024
68892b4
pip install openai
abrichr Feb 6, 2024
a2ce943
typo
abrichr Feb 6, 2024
2fcdaa0
pydantic
abrichr Feb 6, 2024
3ae5d80
add entrypoint.sh
abrichr Feb 6, 2024
679146f
handle empty secret values
abrichr Feb 6, 2024
165ecc9
improve documentation
abrichr Feb 6, 2024
2694c9f
remove unused files
abrichr Feb 6, 2024
b66d7cf
gradio==3.50.2
abrichr Feb 7, 2024
31b4b13
prevent merge conflicts
abrichr Feb 7, 2024
96c47e5
gr.ImageEditor; gradio==4.17.0; client.py
abrichr Feb 7, 2024
e8fec63
bugfix
abrichr Feb 7, 2024
cb40446
add comment to docker-build-ec2.yml
abrichr Feb 7, 2024
61906df
new yml
abrichr Feb 7, 2024
39a62ae
formatting
abrichr Feb 8, 2024
7404129
Add Deploy class; rename public methods; improve documentation; add s…
abrichr Feb 9, 2024
61c55a2
Merge pull request #7 from microsoft/main
abrichr Mar 2, 2024
33ac5e7
fix typo/grammar
abrichr Mar 2, 2024
7dd00f1
Delete .github/workflows/docker-build-ec2.yml
abrichr Mar 2, 2024
3bbd0cf
simplify .env creation instructions
abrichr Mar 2, 2024
f98af4e
update documentation examples
abrichr Mar 5, 2024
bbf0c97
update documentation
abrichr Mar 5, 2024
a050919
'add workflow file'
abrichr Mar 5, 2024
923b720
add token documentation; automate git remote and set upstream
abrichr Mar 5, 2024
59a7c82
formatting
abrichr Mar 5, 2024
828a0e3
update documentation
abrichr Mar 5, 2024
d24cd62
'add workflow file'
abrichr Mar 5, 2024
7a8560f
remove .github
abrichr Mar 5, 2024
51f78fb
Update README.md
abrichr Mar 10, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions .env.example
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
AWS_ACCESS_KEY_ID=
AWS_SECRET_ACCESS_KEY=
AWS_REGION=
GITHUB_OWNER=
GITHUB_REPO=
GITHUB_TOKEN=
PROJECT_NAME=
# optional
OPENAI_API_KEY=
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -158,3 +158,5 @@ cython_debug/
# and can be added to the global gitignore or merged into this file. For a more nuclear
# option (not recommended) you can uncomment the following to ignore the entire idea folder.
#.idea/

*.sw[m-p]
43 changes: 43 additions & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
FROM nvidia/cuda:12.3.1-devel-ubuntu22.04

# Install system dependencies
RUN apt-get update && \
apt-get install -y \
python3-pip python3-dev git ninja-build wget \
ffmpeg libsm6 libxext6 \
openmpi-bin libopenmpi-dev && \
ln -sf /usr/bin/python3 /usr/bin/python && \
ln -sf /usr/bin/pip3 /usr/bin/pip

# Set the working directory in the container
WORKDIR /usr/src/app

# Copy the current directory contents into the container at /usr/src/app
COPY . .

ENV FORCE_CUDA=1

# Upgrade pip
RUN python -m pip install --upgrade pip

# Install Python dependencies
RUN pip install torch torchvision torchaudio --extra-index-url https://download.pytorch.org/whl/cu123 \
&& pip install git+https://github.com/UX-Decoder/Segment-Everything-Everywhere-All-At-Once.git@33f2c898fdc8d7c95dda014a4b9ebe4e413dbb2b \
&& pip install git+https://github.com/facebookresearch/segment-anything.git \
&& pip install git+https://github.com/UX-Decoder/Semantic-SAM.git@package \
&& cd ops && bash make.sh && cd .. \
&& pip install mpi4py \
&& pip install openai \
&& pip install gradio==4.17.0

# Download pretrained models
RUN sh download_ckpt.sh

# Make port 6092 available to the world outside this container
EXPOSE 6092

# Make Gradio server accessible outside 127.0.0.1
ENV GRADIO_SERVER_NAME="0.0.0.0"

RUN chmod +x /usr/src/app/entrypoint.sh
CMD ["/usr/src/app/entrypoint.sh"]
8 changes: 8 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -158,3 +158,11 @@ If you find our work helpful for your research, please consider citing the follo
journal={arXiv preprint arXiv:2310.11441},
year={2023},
}
```

## Deploy to AWS

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`.
36 changes: 36 additions & 0 deletions client.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
"""
This module provides a command-line interface to interact with the SoM server.

The server URL is printed during deployment via `python deploy.py run`.

Usage:
python client.py "http://<server_ip>:6092"
"""

import fire
from gradio_client import Client
from loguru import logger

def predict(server_url: str):
"""
Makes a prediction using the Gradio client with the provided IP address.

Args:
server_url (str): The URL of the SoM Gradio server.
"""
client = Client(server_url)
result = client.predict(
{
"background": "https://raw.githubusercontent.com/gradio-app/gradio/main/test/test_files/bus.png",
}, # filepath in 'parameter_1' Image component
2.5, # float (numeric value between 1 and 3) in 'Granularity' Slider component
"Automatic", # Literal['Automatic', 'Interactive'] in 'Segmentation Mode' Radio component
0.5, # float (numeric value between 0 and 1) in 'Mask Alpha' Slider component
"Number", # Literal['Number', 'Alphabet'] in 'Mark Mode' Radio component
["Mark"], # List[Literal['Mask', 'Box', 'Mark']] in 'Annotation Mode' Checkboxgroup component
api_name="/inference"
)
logger.info(result)

if __name__ == "__main__":
fire.Fire(predict)
34 changes: 12 additions & 22 deletions demo_gpt4v_som.py
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,10 @@
def inference(image, slider, mode, alpha, label_mode, anno_mode, *args, **kwargs):
global history_images; history_images = []
global history_masks; history_masks = []

_image = image['background'].convert('RGB')
_mask = image['layers'][0].convert('L') if image['layers'] else None

if slider < 1.5:
model_name = 'seem'
elif slider > 2.5:
Expand Down Expand Up @@ -119,26 +123,26 @@ def inference(image, slider, mode, alpha, label_mode, anno_mode, *args, **kwargs
semantic=False

if mode == "Interactive":
labeled_array, num_features = label(np.asarray(image['mask'].convert('L')))
labeled_array, num_features = label(np.asarray(_mask))
spatial_masks = torch.stack([torch.from_numpy(labeled_array == i+1) for i in range(num_features)])

if model_name == 'semantic-sam':
model = model_semsam
output, mask = inference_semsam_m2m_auto(model, image['image'], level, text, text_part, text_thresh, text_size, hole_scale, island_scale, semantic, label_mode=label_mode, alpha=alpha, anno_mode=anno_mode, *args, **kwargs)
output, mask = inference_semsam_m2m_auto(model, _image, level, text, text_part, text_thresh, text_size, hole_scale, island_scale, semantic, label_mode=label_mode, alpha=alpha, anno_mode=anno_mode, *args, **kwargs)

elif model_name == 'sam':
model = model_sam
if mode == "Automatic":
output, mask = inference_sam_m2m_auto(model, image['image'], text_size, label_mode, alpha, anno_mode)
output, mask = inference_sam_m2m_auto(model, _image, text_size, label_mode, alpha, anno_mode)
elif mode == "Interactive":
output, mask = inference_sam_m2m_interactive(model, image['image'], spatial_masks, text_size, label_mode, alpha, anno_mode)
output, mask = inference_sam_m2m_interactive(model, _image, spatial_masks, text_size, label_mode, alpha, anno_mode)

elif model_name == 'seem':
model = model_seem
if mode == "Automatic":
output, mask = inference_seem_pano(model, image['image'], text_size, label_mode, alpha, anno_mode)
output, mask = inference_seem_pano(model, _image, text_size, label_mode, alpha, anno_mode)
elif mode == "Interactive":
output, mask = inference_seem_interactive(model, image['image'], spatial_masks, text_size, label_mode, alpha, anno_mode)
output, mask = inference_seem_interactive(model, _image, spatial_masks, text_size, label_mode, alpha, anno_mode)

# convert output to PIL image
history_masks.append(mask)
Expand Down Expand Up @@ -173,30 +177,16 @@ def highlight(mode, alpha, label_mode, anno_mode, *args, **kwargs):
sections.append((mask_i, r))
return (history_images[0], sections)

class ImageMask(gr.components.Image):
"""
Sets: source="canvas", tool="sketch"
"""

is_template = True

def __init__(self, **kwargs):
super().__init__(source="upload", tool="sketch", interactive=True, **kwargs)

def preprocess(self, x):
return super().preprocess(x)

'''
launch app
'''

demo = gr.Blocks()
image = ImageMask(label="Input", type="pil", brush_radius=20.0, brush_color="#FFFFFF", height=512)
# image = gr.Image(label="Input", type="pil", height=512)
image = gr.ImageMask(label="Input", type="pil", sources=["upload"], interactive=True, brush=gr.Brush(colors=["#FFFFFF"]))
slider = gr.Slider(1, 3, value=1.8, label="Granularity") # info="Choose in [1, 1.5), [1.5, 2.5), [2.5, 3] for [seem, semantic-sam (multi-level), sam]"
mode = gr.Radio(['Automatic', 'Interactive', ], value='Automatic', label="Segmentation Mode")
anno_mode = gr.CheckboxGroup(choices=["Mark", "Mask", "Box"], value=['Mark'], label="Annotation Mode")
image_out = gr.AnnotatedImage(label="SoM Visual Prompt",type="pil", height=512)
image_out = gr.AnnotatedImage(label="SoM Visual Prompt", height=512)
runBtn = gr.Button("Run")
highlightBtn = gr.Button("Highlight")
bot = gr.Chatbot(label="GPT-4V + SoM", height=256)
Expand Down
35 changes: 12 additions & 23 deletions demo_som.py
Original file line number Diff line number Diff line change
Expand Up @@ -62,14 +62,17 @@

@torch.no_grad()
def inference(image, slider, mode, alpha, label_mode, anno_mode, *args, **kwargs):
_image = image['background'].convert('RGB')
_mask = image['layers'][0].convert('L') if image['layers'] else None

if slider < 1.5:
model_name = 'seem'
elif slider > 2.5:
model_name = 'sam'
else:
if mode == 'Automatic':
model_name = 'semantic-sam'
if slider < 1.5 + 0.14:
if slider < 1.5 + 0.14:
level = [1]
elif slider < 1.5 + 0.28:
level = [2]
Expand Down Expand Up @@ -98,48 +101,35 @@ def inference(image, slider, mode, alpha, label_mode, anno_mode, *args, **kwargs
semantic=False

if mode == "Interactive":
labeled_array, num_features = label(np.asarray(image['mask'].convert('L')))
labeled_array, num_features = label(np.asarray(_mask))
spatial_masks = torch.stack([torch.from_numpy(labeled_array == i+1) for i in range(num_features)])

if model_name == 'semantic-sam':
model = model_semsam
output, mask = inference_semsam_m2m_auto(model, image['image'], level, text, text_part, text_thresh, text_size, hole_scale, island_scale, semantic, label_mode=label_mode, alpha=alpha, anno_mode=anno_mode, *args, **kwargs)
output, mask = inference_semsam_m2m_auto(model, _image, level, text, text_part, text_thresh, text_size, hole_scale, island_scale, semantic, label_mode=label_mode, alpha=alpha, anno_mode=anno_mode, *args, **kwargs)

elif model_name == 'sam':
model = model_sam
if mode == "Automatic":
output, mask = inference_sam_m2m_auto(model, image['image'], text_size, label_mode, alpha, anno_mode)
output, mask = inference_sam_m2m_auto(model, _image, text_size, label_mode, alpha, anno_mode)
elif mode == "Interactive":
output, mask = inference_sam_m2m_interactive(model, image['image'], spatial_masks, text_size, label_mode, alpha, anno_mode)
output, mask = inference_sam_m2m_interactive(model, _image, spatial_masks, text_size, label_mode, alpha, anno_mode)

elif model_name == 'seem':
model = model_seem
if mode == "Automatic":
output, mask = inference_seem_pano(model, image['image'], text_size, label_mode, alpha, anno_mode)
output, mask = inference_seem_pano(model, _image, text_size, label_mode, alpha, anno_mode)
elif mode == "Interactive":
output, mask = inference_seem_interactive(model, image['image'], spatial_masks, text_size, label_mode, alpha, anno_mode)
output, mask = inference_seem_interactive(model, _image, spatial_masks, text_size, label_mode, alpha, anno_mode)

return output

class ImageMask(gr.components.Image):
"""
Sets: source="canvas", tool="sketch"
"""

is_template = True

def __init__(self, **kwargs):
super().__init__(source="upload", tool="sketch", interactive=True, **kwargs)

def preprocess(self, x):
return super().preprocess(x)

'''
launch app
'''

demo = gr.Blocks()
image = ImageMask(label="Input", type="pil", brush_radius=20.0, brush_color="#FFFFFF")
image = gr.ImageMask(label="Input", type="pil", sources=["upload"], interactive=True, brush=gr.Brush(colors=["#FFFFFF"]))
slider = gr.Slider(1, 3, value=2, label="Granularity", info="Choose in [1, 1.5), [1.5, 2.5), [2.5, 3] for [seem, semantic-sam (multi-level), sam]")
mode = gr.Radio(['Automatic', 'Interactive', ], value='Automatic', label="Segmentation Mode")
image_out = gr.Image(label="Auto generation",type="pil")
Expand Down Expand Up @@ -168,7 +158,7 @@ def preprocess(self, x):
with gr.Column():
image_out.render()
runBtn.render()
with gr.Row():
with gr.Row():
example = gr.Examples(
examples=[
["examples/ironing_man.jpg"],
Expand All @@ -189,4 +179,3 @@ def preprocess(self, x):
outputs = image_out)

demo.queue().launch(share=True,server_port=6092)

Loading