From ccae24d695941cbd60d64872102cb29198f4e56e Mon Sep 17 00:00:00 2001 From: Yahav Date: Wed, 1 Jan 2025 14:32:39 -0800 Subject: [PATCH 01/45] gitignore --- flux_serve/.gitignore | 3 + flux_serve/README.md | 23 + flux_serve/app/Dockerfile-assets | 16 + flux_serve/app/Dockerfile.template | 21 + flux_serve/app/build-assets.sh | 50 + flux_serve/app/build.sh | 22 + flux_serve/app/flux_gradio.py | 143 + flux_serve/app/flux_model_api.py | 259 ++ flux_serve/oci-image-build/README.md | 34 + flux_serve/oci-image-build/cdk.out/cdk.out | 1 + .../flux-oci-image-inference-cdk.assets.json | 20 + ...flux-oci-image-inference-cdk.template.json | 1960 +++++++++++++ .../oci-image-build/cdk.out/manifest.json | 357 +++ flux_serve/oci-image-build/cdk.out/tree.json | 2599 +++++++++++++++++ flux_serve/oci-image-build/deploy-pipeline.sh | 12 + flux_serve/oci-image-build/package-lock.json | 615 ++++ flux_serve/oci-image-build/package.json | 9 + flux_serve/oci-image-build/pipeline-stack.js | 329 +++ flux_serve/oci-image-build/pipeline-stack.ts | 321 ++ flux_serve/oci-image-build/pipeline.js | 44 + flux_serve/oci-image-build/pipeline.ts | 10 + flux_serve/oci-image-build/tsconfig.json | 111 + flux_serve/src/README.md | 11 + flux_serve/src/compile.sh | 10 + flux_serve/src/decoder/compile.py | 62 + flux_serve/src/decoder/model.py | 19 + flux_serve/src/inference.py | 232 ++ flux_serve/src/inference.sh | 5 + flux_serve/src/text_encoder_1/compile.py | 45 + flux_serve/src/text_encoder_1/model.py | 33 + flux_serve/src/text_encoder_2/compile.py | 86 + flux_serve/src/text_encoder_2/model.py | 215 ++ flux_serve/src/transformer/compile.py | 218 ++ flux_serve/src/transformer/model.py | 475 +++ 34 files changed, 8370 insertions(+) create mode 100644 flux_serve/.gitignore create mode 100644 flux_serve/README.md create mode 100644 flux_serve/app/Dockerfile-assets create mode 100644 flux_serve/app/Dockerfile.template create mode 100755 flux_serve/app/build-assets.sh create mode 100755 flux_serve/app/build.sh create mode 100644 flux_serve/app/flux_gradio.py create mode 100644 flux_serve/app/flux_model_api.py create mode 100644 flux_serve/oci-image-build/README.md create mode 100644 flux_serve/oci-image-build/cdk.out/cdk.out create mode 100644 flux_serve/oci-image-build/cdk.out/flux-oci-image-inference-cdk.assets.json create mode 100644 flux_serve/oci-image-build/cdk.out/flux-oci-image-inference-cdk.template.json create mode 100644 flux_serve/oci-image-build/cdk.out/manifest.json create mode 100644 flux_serve/oci-image-build/cdk.out/tree.json create mode 100755 flux_serve/oci-image-build/deploy-pipeline.sh create mode 100644 flux_serve/oci-image-build/package-lock.json create mode 100644 flux_serve/oci-image-build/package.json create mode 100644 flux_serve/oci-image-build/pipeline-stack.js create mode 100644 flux_serve/oci-image-build/pipeline-stack.ts create mode 100644 flux_serve/oci-image-build/pipeline.js create mode 100644 flux_serve/oci-image-build/pipeline.ts create mode 100644 flux_serve/oci-image-build/tsconfig.json create mode 100644 flux_serve/src/README.md create mode 100755 flux_serve/src/compile.sh create mode 100644 flux_serve/src/decoder/compile.py create mode 100644 flux_serve/src/decoder/model.py create mode 100644 flux_serve/src/inference.py create mode 100755 flux_serve/src/inference.sh create mode 100644 flux_serve/src/text_encoder_1/compile.py create mode 100644 flux_serve/src/text_encoder_1/model.py create mode 100644 flux_serve/src/text_encoder_2/compile.py create mode 100644 flux_serve/src/text_encoder_2/model.py create mode 100644 flux_serve/src/transformer/compile.py create mode 100644 flux_serve/src/transformer/model.py diff --git a/flux_serve/.gitignore b/flux_serve/.gitignore new file mode 100644 index 0000000..4c9908f --- /dev/null +++ b/flux_serve/.gitignore @@ -0,0 +1,3 @@ +package-lock.json +.DS_Store +node_modules/* diff --git a/flux_serve/README.md b/flux_serve/README.md new file mode 100644 index 0000000..b9c4ba3 --- /dev/null +++ b/flux_serve/README.md @@ -0,0 +1,23 @@ +# Compile and serve ultra large vision transformers like Flux on Neuron devices at scale + +challenges in deploying large models for serving: +1/large model graph traces load - caching S3 buckets on EKS nodes with CSI drivers +https://docs.aws.amazon.com/eks/latest/userguide/s3-csi.html + +Using DLCs to simplify OCI image build - easy to streamline with automation + +https://awsdocs-neuron.readthedocs-hosted.com/en/latest/general/monitoring-tools.html#monitoring-tools are availible out of the box with container insights + +cost effectiveness requires to allocate the minimal required cores. The device plugin and myscheduler through Helm simplify deployment +https://awsdocs-neuron.readthedocs-hosted.com/en/latest/containers/kubernetes-getting-started.html +Neuron device plugin, Neuron scheduler extension, Neuron scheduler + +## Walkthrough +* [Create cluster with Karpenter node pools that provisions `trn1` instances](https://karpenter.sh/docs/getting-started/getting-started-with-karpenter/) +* Create an S3 bucket to store the model compiled graph and export the S3 bucket name as follow: +```bash +export MODEL_GRAPH_BUCKET="black-forest-labs-flux1-dev-neuron" +``` +* [Enable Amazon S3 objects with Mountpoint for Amazon S3 CSI driver](https://docs.aws.amazon.com/eks/latest/userguide/s3-csi.html) +* [Deploy the OCI image pipeline](./oci-image-build) +* diff --git a/flux_serve/app/Dockerfile-assets b/flux_serve/app/Dockerfile-assets new file mode 100644 index 0000000..e934b72 --- /dev/null +++ b/flux_serve/app/Dockerfile-assets @@ -0,0 +1,16 @@ +ARG image + +FROM public.ecr.aws/docker/library/python:latest as base +RUN apt-get update -y --fix-missing +RUN apt-get install -y python3-venv g++ gettext-base jq bc +RUN mkdir -p /etc/apt/keyrings/ +RUN curl -fsSL https://pkgs.k8s.io/core:/stable:/v1.29/deb/Release.key | gpg --dearmor -o /etc/apt/keyrings/kubernetes-apt-keyring.gpg +RUN echo 'deb [signed-by=/etc/apt/keyrings/kubernetes-apt-keyring.gpg] https://pkgs.k8s.io/core:/stable:/v1.29/deb/ /' | tee /etc/apt/sources.list.d/kubernetes.list +RUN apt-get update +RUN apt-get install -y kubectl +RUN kubectl version --client +RUN python -m pip install wget +RUN python -m pip install awscli +RUN pip install boto3 +RUN mkdir /root/.aws +ADD config /root/.aws diff --git a/flux_serve/app/Dockerfile.template b/flux_serve/app/Dockerfile.template new file mode 100644 index 0000000..3a22297 --- /dev/null +++ b/flux_serve/app/Dockerfile.template @@ -0,0 +1,21 @@ +FROM $BASE_IMAGE as base + +RUN apt-get update --fix-missing +RUN apt-get install -y apt-transport-https ca-certificates curl gpg net-tools gettext-base python3-venv g++ +RUN python -m pip install wget +RUN python -m pip install awscli +RUN python -m pip install gradio +RUN python -m pip install "uvicorn[standard]" +RUN python -m pip install fastapi +RUN python -m pip install matplotlib Pillow +RUN pip install diffusers==0.30.3 sentencepiece +RUN pip install httpx + +RUN apt-get update +RUN mkdir -p /etc/apt/keyrings/ +RUN curl -fsSL https://pkgs.k8s.io/core:/stable:/v1.29/deb/Release.key | gpg --dearmor -o /etc/apt/keyrings/kubernetes-apt-keyring.gpg +RUN echo 'deb [signed-by=/etc/apt/keyrings/kubernetes-apt-keyring.gpg] https://pkgs.k8s.io/core:/stable:/v1.29/deb/ /' | tee /etc/apt/sources.list.d/kubernetes.list +RUN apt-get update +RUN apt-get install -y kubectl +RUN kubectl version --client +COPY * / diff --git a/flux_serve/app/build-assets.sh b/flux_serve/app/build-assets.sh new file mode 100755 index 0000000..ee2439a --- /dev/null +++ b/flux_serve/app/build-assets.sh @@ -0,0 +1,50 @@ +#!/bin/bash -x +DLC_ECR_ACCOUNT="763104351884" + +DLC_NEURON_IMAGE="pytorch-inference-neuronx" +DLC_NEURON_TAG=$BASE_IMAGE_TAG +DLC_NEURON_ECR=$DLC_ECR_ACCOUNT".dkr.ecr.us-west-2.amazonaws.com" +if [ "$IMAGE_TAG" == "amd64-neuron" ]; then + docker logout + aws ecr get-login-password --region us-west-2 | docker login --username AWS --password-stdin $DLC_NEURON_ECR + docker pull $DLC_NEURON_ECR/$DLC_NEURON_IMAGE:$DLC_NEURON_TAG + dlc_xla_image_id=$(docker images | grep $DLC_ECR_ACCOUNT | grep $DLC_NEURON_IMAGE | awk '{print $3}') + docker tag $dlc_xla_image_id $AWS_ACCOUNT_ID.dkr.ecr.$AWS_REGION.amazonaws.com/$BASE_REPO:$DLC_NEURON_TAG + docker logout + aws ecr get-login-password --region $AWS_REGION | docker login --username AWS --password-stdin $AWS_ACCOUNT_ID.dkr.ecr.$AWS_REGION.amazonaws.com/$BASE_REPO + docker push $AWS_ACCOUNT_ID.dkr.ecr.$AWS_REGION.amazonaws.com/$BASE_REPO:$DLC_NEURON_TAG +fi +DLC_CUDA_IMAGE="pytorch-inference" +DLC_CUDA_TAG=$BASE_IMAGE_TAG +DLC_CUDA_ECR=$DLC_ECR_ACCOUNT".dkr.ecr.us-east-1.amazonaws.com" +if [ "$IMAGE_TAG" == "amd64-cuda" ]; then + docker logout + aws ecr get-login-password --region us-east-1 | docker login --username AWS --password-stdin $DLC_CUDA_ECR + docker pull $DLC_CUDA_ECR/$DLC_CUDA_IMAGE:$DLC_CUDA_TAG + dlc_cuda_image_id=$(docker images | grep $DLC_ECR_ACCOUNT | grep $DLC_CUDA_TAG | awk '{print $3}') + docker tag $dlc_cuda_image_id $AWS_ACCOUNT_ID.dkr.ecr.$AWS_REGION.amazonaws.com/$BASE_REPO:$DLC_CUDA_TAG + docker logout + aws ecr get-login-password --region $AWS_REGION | docker login --username AWS --password-stdin $AWS_ACCOUNT_ID.dkr.ecr.$AWS_REGION.amazonaws.com/$BASE_REPO + docker push $AWS_ACCOUNT_ID.dkr.ecr.$AWS_REGION.amazonaws.com/$BASE_REPO:$DLC_CUDA_TAG +fi +DLC_ARM_CPU_IMAGE="pytorch-inference-graviton" +DLC_ARM_CPU_TAG=$BASE_IMAGE_TAG +DLC_ARM_CPU_ECR=$DLC_ECR_ACCOUNT".dkr.ecr.us-east-1.amazonaws.com" +if [ "$IMAGE_TAG" == "aarch64-cpu" ]; then + docker logout + aws ecr get-login-password --region us-east-1 | docker login --username AWS --password-stdin $DLC_ARM_CPU_ECR + docker pull $DLC_ARM_CPU_ECR/$DLC_ARM_CPU_IMAGE:$DLC_ARM_CPU_TAG + dlc_arm_cpu_image_id=$(docker images | grep $DLC_ECR_ACCOUNT | grep $DLC_ARM_CPU_TAG | awk '{print $3}') + docker tag $dlc_arm_cpu_image_id $AWS_ACCOUNT_ID.dkr.ecr.$AWS_REGION.amazonaws.com/$BASE_REPO:$DLC_ARM_CPU_TAG + docker logout + aws ecr get-login-password --region $AWS_REGION | docker login --username AWS --password-stdin $AWS_ACCOUNT_ID.dkr.ecr.$AWS_REGION.amazonaws.com/$BASE_REPO + docker push $AWS_ACCOUNT_ID.dkr.ecr.$AWS_REGION.amazonaws.com/$BASE_REPO:$DLC_ARM_CPU_TAG +fi + +docker images + +ASSETS="-assets" +export IMAGE=$AWS_ACCOUNT_ID.dkr.ecr.$AWS_REGION.amazonaws.com/$BASE_REPO:$IMAGE_TAG$ASSETS +aws ecr get-login-password --region $AWS_REGION | docker login --username AWS --password-stdin $IMAGE +docker build -t $IMAGE --build-arg ai_chip=$IMAGE_TAG -f Dockerfile-assets . +docker push $IMAGE diff --git a/flux_serve/app/build.sh b/flux_serve/app/build.sh new file mode 100755 index 0000000..3beda15 --- /dev/null +++ b/flux_serve/app/build.sh @@ -0,0 +1,22 @@ +#!/bin/bash -x + +export AWS_ACCOUNT_ID=$(aws sts get-caller-identity --output text --query Account) + +ASSETS="-assets" +export BASE_IMAGE=$AWS_ACCOUNT_ID.dkr.ecr.$AWS_REGION.amazonaws.com/$BASE_REPO:$BASE_IMAGE_TAG +export ASSETS_IMAGE=$AWS_ACCOUNT_ID.dkr.ecr.$AWS_REGION.amazonaws.com/$BASE_REPO:$IMAGE_TAG$ASSETS +export IMAGE=$AWS_ACCOUNT_ID.dkr.ecr.$AWS_REGION.amazonaws.com/$BASE_REPO:$IMAGE_TAG + +#if [ "$IMAGE_TAG" == "1.13.1-neuronx-py310-sdk2.17.0-ubuntu20.04" ]; then +# docker tag $dlc_xla_image_id $BASE_IMAGE +#fi +#if [ "$IMAGE_TAG" == "2.0.1-gpu-py310-cu118-ubuntu20.04-ec2" ]; then +# docker tag $dlc_cuda_image_id $BASE_IMAGE +#fi +#docker images + +cat Dockerfile.template | envsubst > Dockerfile +cat Dockerfile +aws ecr get-login-password --region $AWS_REGION | docker login --username AWS --password-stdin $BASE_IMAGE +docker build -t $IMAGE . +docker push $IMAGE diff --git a/flux_serve/app/flux_gradio.py b/flux_serve/app/flux_gradio.py new file mode 100644 index 0000000..131ef9e --- /dev/null +++ b/flux_serve/app/flux_gradio.py @@ -0,0 +1,143 @@ +import gradio as gr +import requests +from PIL import Image +import io +import os +from fastapi import FastAPI +import base64 +import asyncio +import httpx + +app = FastAPI() + +model_id=os.environ['MODEL_ID'] + +models = [ + { + 'name': '256x144', + 'host_env': 'FLUX_NEURON_256X144_MODEL_API_SERVICE_HOST', + 'port_env': 'FLUX_NEURON_256X144_MODEL_API_SERVICE_PORT', + 'height': 256, + 'width': 144 + }, + { + 'name': '1024x576', + 'host_env': 'FLUX_NEURON_1024X576_MODEL_API_SERVICE_HOST', + 'port_env': 'FLUX_NEURON_1024X576_MODEL_API_SERVICE_PORT', + 'height': 1024, + 'width': 576 + }, + { + 'name': '512x512', + 'host_env': 'FLUX_NEURON_512X512_MODEL_API_SERVICE_HOST', + 'port_env': 'FLUX_NEURON_512X512_MODEL_API_SERVICE_PORT', + 'height': 512, + 'width': 512 + } +] + +for model in models: + host = os.environ[model['host_env']] + port = os.environ[model['port_env']] + model['url'] = f"http://{host}:{port}/generate" + +async def fetch_image(client, url, prompt, num_inference_steps): + payload = { + "prompt": prompt, + "num_inference_steps": int(num_inference_steps) + } + try: + response = await client.post(url, json=payload, timeout=60.0) + response.raise_for_status() + data = response.json() + image_bytes = base64.b64decode(data['image']) + image = Image.open(io.BytesIO(image_bytes)) + execution_time = data.get('execution_time', 0) + return image, f"{execution_time:.2f} seconds" + except httpx.RequestError as e: + return None, f"Request Error: {str(e)}" + except Exception as e: + return None, f"Error: {str(e)}" + +async def call_model_api(prompt, num_inference_steps): + async with httpx.AsyncClient() as client: + tasks = [ + fetch_image(client, model['url'], prompt, num_inference_steps) + for model in models + ] + results = await asyncio.gather(*tasks) + images = [] + exec_times = [] + for image, exec_time in results: + images.append(image) + exec_times.append(exec_time) + return images + exec_times + +@app.get("/health") +def healthy(): + return {"message": "Service is healthy"} + +@app.get("/readiness") +def ready(): + return {"message": "Service is ready"} + +with gr.Blocks() as interface: + gr.Markdown(f"# {model_id} Image Generation App") + gr.Markdown("Enter a prompt and specify the number of inference steps to generate images in different shapes.") + + with gr.Row(): + with gr.Column(scale=1): + prompt = gr.Textbox(label="Prompt", lines=1, placeholder="Enter your prompt here...",elem_id="prompt-box") + inference_steps = gr.Number( + label="Inference Steps", + value=10, + precision=0, + info="Enter the number of inference steps; higher number takes more time but produces better image", + elem_id="steps-number" + ) + generate_button = gr.Button("Generate Images",variant="primary") + + with gr.Column(scale=2): + image_components = [] + exec_time_components = [] + + with gr.Row(equal_height=True): + for idx, model in enumerate(models): + with gr.Column(scale=1,min_width=300): + img = gr.Image(label=f"{model['name']}",height=model['height'],width=model['width'],interactive=False) + exec_time = gr.Textbox(label=f"Execution Time ({model['name']})",interactive=False,lines=1,placeholder="Execution time will appear here...") + image_components.append(img) + exec_time_components.append(exec_time) + + # callback for the button + generate_button.click( + fn=call_model_api, + inputs=[prompt, inference_steps], + outputs=image_components + exec_time_components, + api_name="generate_images" + ) +app = gr.mount_gradio_app(app, interface, path="/serve") +''' +interface = gr.Interface( + fn=call_model_api, + inputs=[ + gr.Textbox(label="Prompt", lines=1, placeholder="Enter your prompt here..."), + gr.Number( + label="Inference Steps", + value=10, + precision=0, + info="Enter the number of inference steps; higher number takes more time but produces better image" + ) + ], + outputs=[ + gr.Image(label=f"Image from {models[0]['name']}", height=models[0]['height'], width=models[0]['width']), + gr.Textbox(label=f"Execution Time ({models[0]['name']})"), + gr.Image(label=f"Image from {models[1]['name']}", height=models[1]['height'], width=models[1]['width']), + gr.Textbox(label=f"Execution Time ({models[1]['name']})"), + gr.Image(label=f"Image from {models[2]['name']}", height=models[2]['height'], width=models[2]['width']), + gr.Textbox(label=f"Execution Time ({models[2]['name']})"), + ], + description="Enter a prompt and specify the number of inference steps to generate images using the model pipeline." +) +app = gr.mount_gradio_app(app,interface, path="/serve") +''' diff --git a/flux_serve/app/flux_model_api.py b/flux_serve/app/flux_model_api.py new file mode 100644 index 0000000..8f424ea --- /dev/null +++ b/flux_serve/app/flux_model_api.py @@ -0,0 +1,259 @@ +import math +import boto3 +import time +import argparse +import torch +import torch.nn as nn +import torch_neuronx +import neuronx_distributed +import os +from fastapi import FastAPI, HTTPException +from pydantic import BaseModel, Field +from typing import Any, Dict, Optional, Union +from huggingface_hub import login +from diffusers import FluxPipeline +from diffusers.models.modeling_outputs import Transformer2DModelOutput +from starlette.responses import StreamingResponse +import base64 + +cw_namespace='hw-agnostic-infer' +cloudwatch = boto3.client('cloudwatch', region_name='us-west-2') + +# Initialize FastAPI app +app = FastAPI() + +# Environment Variables +app_name=os.environ['APP'] +nodepool=os.environ['NODEPOOL'] +model_id = os.environ['MODEL_ID'] +device = os.environ["DEVICE"] +pod_name = os.environ['POD_NAME'] +hf_token = os.environ['HUGGINGFACE_TOKEN'].strip() +height = int(os.environ['HEIGHT']) +width = int(os.environ['WIDTH']) +max_sequence_length = int(os.environ['MAX_SEQ_LEN']) +guidance_scale = float(os.environ['GUIDANCE_SCALE']) +COMPILER_WORKDIR_ROOT = os.environ['COMPILER_WORKDIR_ROOT'] + +DTYPE=torch.bfloat16 + +def cw_pub_metric(metric_name,metric_value,metric_unit): + response = cloudwatch.put_metric_data( + Namespace=cw_namespace, + MetricData=[ + { + 'MetricName':metric_name, + 'Value':metric_value, + 'Unit':metric_unit, + }, + ] + ) + print(f"in pub_deployment_counter - response:{response}") + return response + +# Model Paths +TEXT_ENCODER_PATH = os.path.join( + COMPILER_WORKDIR_ROOT, + 'text_encoder_1/compiled_model/model.pt') +TEXT_ENCODER_2_PATH = os.path.join( + COMPILER_WORKDIR_ROOT, + 'text_encoder_2/compiled_model/model.pt') +VAE_DECODER_PATH = os.path.join( + COMPILER_WORKDIR_ROOT, + 'decoder/compiled_model/model.pt') + +EMBEDDERS_DIR = os.path.join( + COMPILER_WORKDIR_ROOT, + 'transformer/compiled_model/embedders') +OUT_LAYERS_DIR = os.path.join( + COMPILER_WORKDIR_ROOT, + 'transformer/compiled_model/out_layers') +SINGLE_TRANSFORMER_BLOCKS_DIR = os.path.join( + COMPILER_WORKDIR_ROOT, + 'transformer/compiled_model/single_transformer_blocks') +TRANSFORMER_BLOCKS_DIR = os.path.join( + COMPILER_WORKDIR_ROOT, + 'transformer/compiled_model/transformer_blocks') + +# Login to Hugging Face +login(hf_token, add_to_git_credential=True) + +class GenerateImageRequest(BaseModel): + prompt: str + num_inference_steps: int + +class GenerateImageResponse(BaseModel): + image: str = Field(..., description="Base64-encoded image") + execution_time: float + +class NeuronFluxTransformer2DModel(nn.Module): + def __init__( + self, + config, + x_embedder, + context_embedder + ): + super().__init__() + with torch_neuronx.experimental.neuron_cores_context(start_nc=4, + nc_count=8): + self.embedders_model = \ + neuronx_distributed.trace.parallel_model_load(EMBEDDERS_DIR) + self.transformer_blocks_model = \ + neuronx_distributed.trace.parallel_model_load( + TRANSFORMER_BLOCKS_DIR) + self.single_transformer_blocks_model = \ + neuronx_distributed.trace.parallel_model_load( + SINGLE_TRANSFORMER_BLOCKS_DIR) + self.out_layers_model = \ + neuronx_distributed.trace.parallel_model_load( + OUT_LAYERS_DIR) + self.config = config + self.x_embedder = x_embedder + self.context_embedder = context_embedder + self.device = torch.device("cpu") + + def forward( + self, + hidden_states: torch.Tensor, + encoder_hidden_states: torch.Tensor = None, + pooled_projections: torch.Tensor = None, + timestep: torch.LongTensor = None, + img_ids: torch.Tensor = None, + txt_ids: torch.Tensor = None, + guidance: torch.Tensor = None, + joint_attention_kwargs: Optional[Dict[str, Any]] = None, + return_dict: bool = False, + ) -> Union[torch.FloatTensor, Transformer2DModelOutput]: + + hidden_states = self.x_embedder(hidden_states) + + hidden_states, temb, image_rotary_emb = self.embedders_model( + hidden_states, + timestep, + guidance, + pooled_projections, + txt_ids, + img_ids + ) + + encoder_hidden_states = self.context_embedder(encoder_hidden_states) + + image_rotary_emb = image_rotary_emb.type(DTYPE) + + encoder_hidden_states, hidden_states = self.transformer_blocks_model( + hidden_states, + encoder_hidden_states, + temb, + image_rotary_emb + ) + + hidden_states = torch.cat([encoder_hidden_states, hidden_states], + dim=1) + + hidden_states = self.single_transformer_blocks_model( + hidden_states, + temb, + image_rotary_emb + ) + + hidden_states = hidden_states.to(DTYPE) + + return self.out_layers_model( + hidden_states, + encoder_hidden_states, + temb + ) + + +class NeuronFluxCLIPTextEncoderModel(nn.Module): + def __init__(self, dtype, encoder): + super().__init__() + self.dtype = dtype + self.encoder = encoder + self.device = torch.device("cpu") + + def forward(self, emb, output_hidden_states): + output = self.encoder(emb) + output = CLIPEncoderOutput(output) + return output + + +class CLIPEncoderOutput(): + def __init__(self, dictionary): + self.pooler_output = dictionary["pooler_output"] + + +class NeuronFluxT5TextEncoderModel(nn.Module): + def __init__(self, dtype, encoder): + super().__init__() + self.dtype = dtype + self.encoder = encoder + self.device = torch.device("cpu") + + def forward(self, emb, output_hidden_states): + return torch.unsqueeze(self.encoder(emb)["last_hidden_state"], 1) + +# Load the model pipeline +def load_model(): + pipe = FluxPipeline.from_pretrained( + "black-forest-labs/FLUX.1-dev", + torch_dtype=DTYPE) + with torch_neuronx.experimental.neuron_cores_context(start_nc=0): + pipe.text_encoder = NeuronFluxCLIPTextEncoderModel( + pipe.text_encoder.dtype, + torch.jit.load(TEXT_ENCODER_PATH)) + with torch_neuronx.experimental.neuron_cores_context(start_nc=8): + pipe.text_encoder_2 = NeuronFluxT5TextEncoderModel( + pipe.text_encoder_2.dtype, + torch.jit.load(TEXT_ENCODER_2_PATH)) + pipe.transformer = NeuronFluxTransformer2DModel( + pipe.transformer.config, + pipe.transformer.x_embedder, + pipe.transformer.context_embedder) + with torch_neuronx.experimental.neuron_cores_context(start_nc=8): + pipe.vae.decoder = torch.jit.load(VAE_DECODER_PATH) + return pipe + +model = load_model() + +# Define the image generation endpoint +@app.post("/generate", response_model=GenerateImageResponse) +def generate_image(request: GenerateImageRequest): + start_time = time.time() + try: + model_args = { + 'prompt': request.prompt, + 'height': height, + 'width': width, + 'max_sequence_length': max_sequence_length, + 'num_inference_steps': request.num_inference_steps, + 'guidance_scale': guidance_scale + } + with torch.no_grad(): + output = model(**model_args) + image = output.images[0] + # Save image to bytes + from io import BytesIO + buf = BytesIO() + image.save(buf, format='PNG') + image_bytes = buf.getvalue() + image_base64 = base64.b64encode(image_bytes).decode('utf-8') + total_time = time.time() - start_time + counter_metric=app_name+'-counter' + cw_pub_metric(counter_metric,1,'Count') + counter_metric=nodepool + cw_pub_metric(counter_metric,1,'Count') + latency_metric=app_name+'-latency' + cw_pub_metric(latency_metric,total_time,'Seconds') + return GenerateImageResponse(image=image_base64, execution_time=total_time) + except Exception as e: + raise HTTPException(status_code=500, detail=f"Image serialization failed: {img_err}") + +# Health and readiness endpoints +@app.get("/health") +def healthy(): + return {"message": f"{pod_name} is healthy"} + +@app.get("/readiness") +def ready(): + return {"message": f"{pod_name} is ready"} diff --git a/flux_serve/oci-image-build/README.md b/flux_serve/oci-image-build/README.md new file mode 100644 index 0000000..bf145c9 --- /dev/null +++ b/flux_serve/oci-image-build/README.md @@ -0,0 +1,34 @@ + +* Fork https://github.com/aws-samples/scalable-hw-agnostic-inference and populate the `GITHUB_USER` and `GITHUB_OAUTH_TOKEN` based on `Settings/Developer Settings/Personal access tokens`. +* Check the latest [DLC](https://github.com/aws/deep-learning-containers/blob/master/available_images.md) for `BASE_IMAGE_AMD_XLA_TAG` and `BASE_IMAGE_AMD_CUD_TAG` values. +* Export the following variables: +```bash +export AWS_ACCOUNT_ID=$(aws sts get-caller-identity --output text --query Account) +export AWS_REGION=us-west-2 +export BASE_IMAGE_AMD_XLA_TAG=2.5.1-neuronx-py310-sdk2.21.0-ubuntu22.04 +export BASE_IMAGE_AMD_CUD_TAG=2.3.0-gpu-py311-cu121-ubuntu20.04-ec2 +export BASE_IMAGE_ARM_CPU_TAG=2.3.0-cpu-py311-ubuntu20.04-ec2 +export IMAGE_AMD_XLA_TAG=amd64-neuron +export IMAGE_AMD_CUD_TAG=amd64-cuda +export IMAGE_ARM_CPU_TAG=aarch64-cpu +export BASE_REPO=model +export BASE_TAG=multiarch-ubuntu +export BASE_AMD_TAG=amd64 +export GITHUB_BRANCH=master +export GITHUB_USER=yahavb +export GITHUB_REPO=scalable-hw-agnostic-inference +export MODEL_DIR=sd2_compile_dir +export CF_STACK=flux-oci-image-inference-cdk +``` +* Install needed packages + +```bash +npm uninstall -g aws-cdk +npm install -g aws-cdk +``` + +* Deploy the pipeline + +```bash +./deploy-pipeline.sh +``` diff --git a/flux_serve/oci-image-build/cdk.out/cdk.out b/flux_serve/oci-image-build/cdk.out/cdk.out new file mode 100644 index 0000000..c6e6125 --- /dev/null +++ b/flux_serve/oci-image-build/cdk.out/cdk.out @@ -0,0 +1 @@ +{"version":"38.0.1"} \ No newline at end of file diff --git a/flux_serve/oci-image-build/cdk.out/flux-oci-image-inference-cdk.assets.json b/flux_serve/oci-image-build/cdk.out/flux-oci-image-inference-cdk.assets.json new file mode 100644 index 0000000..b7f5cc8 --- /dev/null +++ b/flux_serve/oci-image-build/cdk.out/flux-oci-image-inference-cdk.assets.json @@ -0,0 +1,20 @@ +{ + "version": "38.0.1", + "files": { + "54c3377f007eccdd78146d6ef1c9fe016f1cd6dc99c2088e7f65bb90e95689cc": { + "source": { + "path": "flux-oci-image-inference-cdk.template.json", + "packaging": "file" + }, + "destinations": { + "133573815653-us-west-2": { + "bucketName": "cdk-hnb659fds-assets-133573815653-us-west-2", + "objectKey": "54c3377f007eccdd78146d6ef1c9fe016f1cd6dc99c2088e7f65bb90e95689cc.json", + "region": "us-west-2", + "assumeRoleArn": "arn:${AWS::Partition}:iam::133573815653:role/cdk-hnb659fds-file-publishing-role-133573815653-us-west-2" + } + } + } + }, + "dockerImages": {} +} \ No newline at end of file diff --git a/flux_serve/oci-image-build/cdk.out/flux-oci-image-inference-cdk.template.json b/flux_serve/oci-image-build/cdk.out/flux-oci-image-inference-cdk.template.json new file mode 100644 index 0000000..21e29ef --- /dev/null +++ b/flux_serve/oci-image-build/cdk.out/flux-oci-image-inference-cdk.template.json @@ -0,0 +1,1960 @@ +{ + "Parameters": { + "BASEREPO": { + "Type": "String" + }, + "BASEIMAGEAMDXLATAG": { + "Type": "String" + }, + "BASEIMAGEAMDCUDTAG": { + "Type": "String" + }, + "BASEIMAGEARMCPUTAG": { + "Type": "String" + }, + "IMAGEAMDXLATAG": { + "Type": "String" + }, + "IMAGEAMDCUDTAG": { + "Type": "String" + }, + "IMAGEARMCPUTAG": { + "Type": "String" + }, + "GITHUBOAUTHTOKEN": { + "Type": "String" + }, + "GITHUBUSER": { + "Type": "String" + }, + "GITHUBREPO": { + "Type": "String" + }, + "GITHUBBRANCH": { + "Type": "String" + }, + "BootstrapVersion": { + "Type": "AWS::SSM::Parameter::Value", + "Default": "/cdk-bootstrap/hnb659fds/version", + "Description": "Version of the CDK Bootstrap resources in this environment, automatically retrieved from SSM Parameter Store. [cdk:skip]" + } + }, + "Resources": { + "baserepoCCF23216": { + "Type": "AWS::ECR::Repository", + "Properties": { + "ImageScanningConfiguration": { + "ScanOnPush": true + }, + "RepositoryName": { + "Ref": "BASEREPO" + } + }, + "UpdateReplacePolicy": "Retain", + "DeletionPolicy": "Retain", + "Metadata": { + "aws:cdk:path": "flux-oci-image-inference-cdk/base_repo/Resource" + } + }, + "BaseCodeBuildDeployRole2A53BD0D": { + "Type": "AWS::IAM::Role", + "Properties": { + "AssumeRolePolicyDocument": { + "Statement": [ + { + "Action": "sts:AssumeRole", + "Effect": "Allow", + "Principal": { + "Service": "codebuild.amazonaws.com" + } + } + ], + "Version": "2012-10-17" + }, + "RoleName": "hwagnisticBaseCodeBuildDeployRole" + }, + "Metadata": { + "aws:cdk:path": "flux-oci-image-inference-cdk/BaseCodeBuildDeployRole/Resource" + } + }, + "BaseCodeBuildDeployRoleDefaultPolicy93D8F557": { + "Type": "AWS::IAM::Policy", + "Properties": { + "PolicyDocument": { + "Statement": [ + { + "Action": [ + "ssm:*", + "s3:*" + ], + "Effect": "Allow", + "Resource": "*" + }, + { + "Action": [ + "logs:CreateLogGroup", + "logs:CreateLogStream", + "logs:PutLogEvents" + ], + "Effect": "Allow", + "Resource": [ + { + "Fn::Join": [ + "", + [ + "arn:", + { + "Ref": "AWS::Partition" + }, + ":logs:us-west-2:133573815653:log-group:/aws/codebuild/", + { + "Ref": "ImageCudAmdBuild23EA25C8" + } + ] + ] + }, + { + "Fn::Join": [ + "", + [ + "arn:", + { + "Ref": "AWS::Partition" + }, + ":logs:us-west-2:133573815653:log-group:/aws/codebuild/", + { + "Ref": "ImageCudAmdBuild23EA25C8" + }, + ":*" + ] + ] + } + ] + }, + { + "Action": [ + "codebuild:CreateReportGroup", + "codebuild:CreateReport", + "codebuild:UpdateReport", + "codebuild:BatchPutTestCases", + "codebuild:BatchPutCodeCoverages" + ], + "Effect": "Allow", + "Resource": { + "Fn::Join": [ + "", + [ + "arn:", + { + "Ref": "AWS::Partition" + }, + ":codebuild:us-west-2:133573815653:report-group/", + { + "Ref": "ImageCudAmdBuild23EA25C8" + }, + "-*" + ] + ] + } + }, + { + "Action": [ + "logs:CreateLogGroup", + "logs:CreateLogStream", + "logs:PutLogEvents" + ], + "Effect": "Allow", + "Resource": [ + { + "Fn::Join": [ + "", + [ + "arn:", + { + "Ref": "AWS::Partition" + }, + ":logs:us-west-2:133573815653:log-group:/aws/codebuild/", + { + "Ref": "ImageCpuArmBuild4791F7AA" + } + ] + ] + }, + { + "Fn::Join": [ + "", + [ + "arn:", + { + "Ref": "AWS::Partition" + }, + ":logs:us-west-2:133573815653:log-group:/aws/codebuild/", + { + "Ref": "ImageCpuArmBuild4791F7AA" + }, + ":*" + ] + ] + } + ] + }, + { + "Action": [ + "codebuild:CreateReportGroup", + "codebuild:CreateReport", + "codebuild:UpdateReport", + "codebuild:BatchPutTestCases", + "codebuild:BatchPutCodeCoverages" + ], + "Effect": "Allow", + "Resource": { + "Fn::Join": [ + "", + [ + "arn:", + { + "Ref": "AWS::Partition" + }, + ":codebuild:us-west-2:133573815653:report-group/", + { + "Ref": "ImageCpuArmBuild4791F7AA" + }, + "-*" + ] + ] + } + }, + { + "Action": [ + "logs:CreateLogGroup", + "logs:CreateLogStream", + "logs:PutLogEvents" + ], + "Effect": "Allow", + "Resource": [ + { + "Fn::Join": [ + "", + [ + "arn:", + { + "Ref": "AWS::Partition" + }, + ":logs:us-west-2:133573815653:log-group:/aws/codebuild/", + { + "Ref": "ImageXlaAmdBuild7511085C" + } + ] + ] + }, + { + "Fn::Join": [ + "", + [ + "arn:", + { + "Ref": "AWS::Partition" + }, + ":logs:us-west-2:133573815653:log-group:/aws/codebuild/", + { + "Ref": "ImageXlaAmdBuild7511085C" + }, + ":*" + ] + ] + } + ] + }, + { + "Action": [ + "codebuild:CreateReportGroup", + "codebuild:CreateReport", + "codebuild:UpdateReport", + "codebuild:BatchPutTestCases", + "codebuild:BatchPutCodeCoverages" + ], + "Effect": "Allow", + "Resource": { + "Fn::Join": [ + "", + [ + "arn:", + { + "Ref": "AWS::Partition" + }, + ":codebuild:us-west-2:133573815653:report-group/", + { + "Ref": "ImageXlaAmdBuild7511085C" + }, + "-*" + ] + ] + } + }, + { + "Action": [ + "logs:CreateLogGroup", + "logs:CreateLogStream", + "logs:PutLogEvents" + ], + "Effect": "Allow", + "Resource": [ + { + "Fn::Join": [ + "", + [ + "arn:", + { + "Ref": "AWS::Partition" + }, + ":logs:us-west-2:133573815653:log-group:/aws/codebuild/", + { + "Ref": "AssetsImageXlaAmdBuild4E3D098F" + } + ] + ] + }, + { + "Fn::Join": [ + "", + [ + "arn:", + { + "Ref": "AWS::Partition" + }, + ":logs:us-west-2:133573815653:log-group:/aws/codebuild/", + { + "Ref": "AssetsImageXlaAmdBuild4E3D098F" + }, + ":*" + ] + ] + } + ] + }, + { + "Action": [ + "codebuild:CreateReportGroup", + "codebuild:CreateReport", + "codebuild:UpdateReport", + "codebuild:BatchPutTestCases", + "codebuild:BatchPutCodeCoverages" + ], + "Effect": "Allow", + "Resource": { + "Fn::Join": [ + "", + [ + "arn:", + { + "Ref": "AWS::Partition" + }, + ":codebuild:us-west-2:133573815653:report-group/", + { + "Ref": "AssetsImageXlaAmdBuild4E3D098F" + }, + "-*" + ] + ] + } + }, + { + "Action": [ + "logs:CreateLogGroup", + "logs:CreateLogStream", + "logs:PutLogEvents" + ], + "Effect": "Allow", + "Resource": [ + { + "Fn::Join": [ + "", + [ + "arn:", + { + "Ref": "AWS::Partition" + }, + ":logs:us-west-2:133573815653:log-group:/aws/codebuild/", + { + "Ref": "AssetsImageCpuArmBuildBC43C501" + } + ] + ] + }, + { + "Fn::Join": [ + "", + [ + "arn:", + { + "Ref": "AWS::Partition" + }, + ":logs:us-west-2:133573815653:log-group:/aws/codebuild/", + { + "Ref": "AssetsImageCpuArmBuildBC43C501" + }, + ":*" + ] + ] + } + ] + }, + { + "Action": [ + "codebuild:CreateReportGroup", + "codebuild:CreateReport", + "codebuild:UpdateReport", + "codebuild:BatchPutTestCases", + "codebuild:BatchPutCodeCoverages" + ], + "Effect": "Allow", + "Resource": { + "Fn::Join": [ + "", + [ + "arn:", + { + "Ref": "AWS::Partition" + }, + ":codebuild:us-west-2:133573815653:report-group/", + { + "Ref": "AssetsImageCpuArmBuildBC43C501" + }, + "-*" + ] + ] + } + }, + { + "Action": [ + "logs:CreateLogGroup", + "logs:CreateLogStream", + "logs:PutLogEvents" + ], + "Effect": "Allow", + "Resource": [ + { + "Fn::Join": [ + "", + [ + "arn:", + { + "Ref": "AWS::Partition" + }, + ":logs:us-west-2:133573815653:log-group:/aws/codebuild/", + { + "Ref": "AssetsImageCudAmdBuild4322D558" + } + ] + ] + }, + { + "Fn::Join": [ + "", + [ + "arn:", + { + "Ref": "AWS::Partition" + }, + ":logs:us-west-2:133573815653:log-group:/aws/codebuild/", + { + "Ref": "AssetsImageCudAmdBuild4322D558" + }, + ":*" + ] + ] + } + ] + }, + { + "Action": [ + "codebuild:CreateReportGroup", + "codebuild:CreateReport", + "codebuild:UpdateReport", + "codebuild:BatchPutTestCases", + "codebuild:BatchPutCodeCoverages" + ], + "Effect": "Allow", + "Resource": { + "Fn::Join": [ + "", + [ + "arn:", + { + "Ref": "AWS::Partition" + }, + ":codebuild:us-west-2:133573815653:report-group/", + { + "Ref": "AssetsImageCudAmdBuild4322D558" + }, + "-*" + ] + ] + } + }, + { + "Action": [ + "ecr:BatchCheckLayerAvailability", + "ecr:GetDownloadUrlForLayer", + "ecr:BatchGetImage", + "ecr:CompleteLayerUpload", + "ecr:UploadLayerPart", + "ecr:InitiateLayerUpload", + "ecr:PutImage" + ], + "Effect": "Allow", + "Resource": { + "Fn::GetAtt": [ + "baserepoCCF23216", + "Arn" + ] + } + }, + { + "Action": "ecr:GetAuthorizationToken", + "Effect": "Allow", + "Resource": "*" + }, + { + "Action": [ + "s3:GetObject*", + "s3:GetBucket*", + "s3:List*" + ], + "Effect": "Allow", + "Resource": [ + { + "Fn::GetAtt": [ + "BuildBasePipelineArtifactsBucket51786A86", + "Arn" + ] + }, + { + "Fn::Join": [ + "", + [ + { + "Fn::GetAtt": [ + "BuildBasePipelineArtifactsBucket51786A86", + "Arn" + ] + }, + "/*" + ] + ] + } + ] + }, + { + "Action": [ + "kms:Decrypt", + "kms:DescribeKey" + ], + "Effect": "Allow", + "Resource": { + "Fn::GetAtt": [ + "BuildBasePipelineArtifactsBucketEncryptionKey04467E09", + "Arn" + ] + } + }, + { + "Action": [ + "kms:Decrypt", + "kms:Encrypt", + "kms:ReEncrypt*", + "kms:GenerateDataKey*" + ], + "Effect": "Allow", + "Resource": { + "Fn::GetAtt": [ + "BuildBasePipelineArtifactsBucketEncryptionKey04467E09", + "Arn" + ] + } + } + ], + "Version": "2012-10-17" + }, + "PolicyName": "BaseCodeBuildDeployRoleDefaultPolicy93D8F557", + "Roles": [ + { + "Ref": "BaseCodeBuildDeployRole2A53BD0D" + } + ] + }, + "Metadata": { + "aws:cdk:path": "flux-oci-image-inference-cdk/BaseCodeBuildDeployRole/DefaultPolicy/Resource" + } + }, + "githubSecret7D37FCC7": { + "Type": "AWS::SecretsManager::Secret", + "Properties": { + "SecretString": { + "Fn::Join": [ + "", + [ + "{\"token\":\"", + { + "Ref": "GITHUBOAUTHTOKEN" + }, + "\"}" + ] + ] + } + }, + "UpdateReplacePolicy": "Delete", + "DeletionPolicy": "Delete", + "Metadata": { + "aws:cdk:path": "flux-oci-image-inference-cdk/githubSecret/Resource" + } + }, + "ImageCudAmdBuild23EA25C8": { + "Type": "AWS::CodeBuild::Project", + "Properties": { + "Artifacts": { + "Type": "NO_ARTIFACTS" + }, + "Cache": { + "Modes": [ + "LOCAL_DOCKER_LAYER_CACHE", + "LOCAL_CUSTOM_CACHE" + ], + "Type": "LOCAL" + }, + "EncryptionKey": { + "Fn::GetAtt": [ + "BuildBasePipelineArtifactsBucketEncryptionKey04467E09", + "Arn" + ] + }, + "Environment": { + "ComputeType": "BUILD_GENERAL1_SMALL", + "Image": "aws/codebuild/amazonlinux2-x86_64-standard:3.0", + "ImagePullCredentialsType": "CODEBUILD", + "PrivilegedMode": true, + "Type": "LINUX_CONTAINER" + }, + "ServiceRole": { + "Fn::GetAtt": [ + "BaseCodeBuildDeployRole2A53BD0D", + "Arn" + ] + }, + "Source": { + "BuildSpec": { + "Fn::Join": [ + "", + [ + "{\n \"version\": \"0.2\",\n \"env\": {\n \"exported-variables\": [\n \"AWS_ACCOUNT_ID\",\n \"AWS_REGION\",\n \"BASE_REPO\",\n \"IMAGE_AMD_CUD_TAG\",\n \"BASE_IMAGE_AMD_CUD_TAG\"\n ]\n },\n \"phases\": {\n \"build\": {\n \"commands\": [\n \"export AWS_ACCOUNT_ID=\\\"133573815653\\\"\",\n \"export AWS_REGION=\\\"us-west-2\\\"\",\n \"export BASE_REPO=\\\"", + { + "Ref": "BASEREPO" + }, + "\\\"\",\n \"export IMAGE_TAG=\\\"", + { + "Ref": "IMAGEAMDCUDTAG" + }, + "\\\"\",\n \"export BASE_IMAGE_TAG=\\\"", + { + "Ref": "BASEIMAGEAMDCUDTAG" + }, + "\\\"\",\n \"cd app\",\n \"chmod +x ./build.sh && ./build.sh\"\n ]\n }\n },\n \"artifacts\": {\n \"files\": [\n \"imageDetail.json\"\n ]\n }\n}" + ] + ] + }, + "Type": "NO_SOURCE" + } + }, + "Metadata": { + "aws:cdk:path": "flux-oci-image-inference-cdk/ImageCudAmdBuild/Resource" + } + }, + "ImageCpuArmBuild4791F7AA": { + "Type": "AWS::CodeBuild::Project", + "Properties": { + "Artifacts": { + "Type": "NO_ARTIFACTS" + }, + "Cache": { + "Modes": [ + "LOCAL_DOCKER_LAYER_CACHE", + "LOCAL_CUSTOM_CACHE" + ], + "Type": "LOCAL" + }, + "EncryptionKey": { + "Fn::GetAtt": [ + "BuildBasePipelineArtifactsBucketEncryptionKey04467E09", + "Arn" + ] + }, + "Environment": { + "ComputeType": "BUILD_GENERAL1_LARGE", + "Image": "aws/codebuild/amazonlinux2-aarch64-standard:2.0", + "ImagePullCredentialsType": "CODEBUILD", + "PrivilegedMode": true, + "Type": "ARM_CONTAINER" + }, + "ServiceRole": { + "Fn::GetAtt": [ + "BaseCodeBuildDeployRole2A53BD0D", + "Arn" + ] + }, + "Source": { + "BuildSpec": { + "Fn::Join": [ + "", + [ + "{\n \"version\": \"0.2\",\n \"env\": {\n \"exported-variables\": [\n \"AWS_ACCOUNT_ID\",\n \"AWS_REGION\",\n \"BASE_REPO\",\n \"IMAGE_ARM_CPU_TAG\",\n \"BASE_IMAGE_ARM_CPU_TAG\"\n ]\n },\n \"phases\": {\n \"build\": {\n \"commands\": [\n \"export AWS_ACCOUNT_ID=\\\"133573815653\\\"\",\n \"export AWS_REGION=\\\"us-west-2\\\"\",\n \"export BASE_REPO=\\\"", + { + "Ref": "BASEREPO" + }, + "\\\"\",\n \"export IMAGE_TAG=\\\"", + { + "Ref": "IMAGEARMCPUTAG" + }, + "\\\"\",\n \"export BASE_IMAGE_TAG=\\\"", + { + "Ref": "BASEIMAGEARMCPUTAG" + }, + "\\\"\",\n \"cd app\",\n \"chmod +x ./build.sh && ./build.sh\"\n ]\n }\n },\n \"artifacts\": {\n \"files\": [\n \"imageDetail.json\"\n ]\n }\n}" + ] + ] + }, + "Type": "NO_SOURCE" + } + }, + "Metadata": { + "aws:cdk:path": "flux-oci-image-inference-cdk/ImageCpuArmBuild/Resource" + } + }, + "ImageXlaAmdBuild7511085C": { + "Type": "AWS::CodeBuild::Project", + "Properties": { + "Artifacts": { + "Type": "NO_ARTIFACTS" + }, + "Cache": { + "Modes": [ + "LOCAL_DOCKER_LAYER_CACHE", + "LOCAL_CUSTOM_CACHE" + ], + "Type": "LOCAL" + }, + "EncryptionKey": { + "Fn::GetAtt": [ + "BuildBasePipelineArtifactsBucketEncryptionKey04467E09", + "Arn" + ] + }, + "Environment": { + "ComputeType": "BUILD_GENERAL1_SMALL", + "Image": "aws/codebuild/amazonlinux2-x86_64-standard:3.0", + "ImagePullCredentialsType": "CODEBUILD", + "PrivilegedMode": true, + "Type": "LINUX_CONTAINER" + }, + "ServiceRole": { + "Fn::GetAtt": [ + "BaseCodeBuildDeployRole2A53BD0D", + "Arn" + ] + }, + "Source": { + "BuildSpec": { + "Fn::Join": [ + "", + [ + "{\n \"version\": \"0.2\",\n \"env\": {\n \"exported-variables\": [\n \"AWS_ACCOUNT_ID\",\n \"AWS_REGION\",\n \"BASE_REPO\",\n \"IMAGE_AMD_XLA_TAG\",\n \"BASE_IMAGE_AMD_XLA_TAG\"\n ]\n },\n \"phases\": {\n \"build\": {\n \"commands\": [\n \"export AWS_ACCOUNT_ID=\\\"133573815653\\\"\",\n \"export AWS_REGION=\\\"us-west-2\\\"\",\n \"export BASE_REPO=\\\"", + { + "Ref": "BASEREPO" + }, + "\\\"\",\n \"export IMAGE_TAG=\\\"", + { + "Ref": "IMAGEAMDXLATAG" + }, + "\\\"\",\n \"export BASE_IMAGE_TAG=\\\"", + { + "Ref": "BASEIMAGEAMDXLATAG" + }, + "\\\"\",\n \"cd app\",\n \"chmod +x ./build.sh && ./build.sh\"\n ]\n }\n },\n \"artifacts\": {\n \"files\": [\n \"imageDetail.json\"\n ]\n }\n}" + ] + ] + }, + "Type": "NO_SOURCE" + } + }, + "Metadata": { + "aws:cdk:path": "flux-oci-image-inference-cdk/ImageXlaAmdBuild/Resource" + } + }, + "AssetsImageXlaAmdBuild4E3D098F": { + "Type": "AWS::CodeBuild::Project", + "Properties": { + "Artifacts": { + "Type": "NO_ARTIFACTS" + }, + "Cache": { + "Modes": [ + "LOCAL_DOCKER_LAYER_CACHE", + "LOCAL_CUSTOM_CACHE" + ], + "Type": "LOCAL" + }, + "EncryptionKey": { + "Fn::GetAtt": [ + "BuildBasePipelineArtifactsBucketEncryptionKey04467E09", + "Arn" + ] + }, + "Environment": { + "ComputeType": "BUILD_GENERAL1_SMALL", + "Image": "aws/codebuild/amazonlinux2-x86_64-standard:3.0", + "ImagePullCredentialsType": "CODEBUILD", + "PrivilegedMode": true, + "Type": "LINUX_CONTAINER" + }, + "ServiceRole": { + "Fn::GetAtt": [ + "BaseCodeBuildDeployRole2A53BD0D", + "Arn" + ] + }, + "Source": { + "BuildSpec": { + "Fn::Join": [ + "", + [ + "{\n \"version\": \"0.2\",\n \"env\": {\n \"exported-variables\": [\n \"AWS_ACCOUNT_ID\",\n \"AWS_REGION\",\n \"BASE_REPO\",\n \"IMAGE_AMD_XLA_TAG\",\n \"BASE_IMAGE_AMD_XLA_TAG\"\n ]\n },\n \"phases\": {\n \"build\": {\n \"commands\": [\n \"export AWS_ACCOUNT_ID=\\\"133573815653\\\"\",\n \"export AWS_REGION=\\\"us-west-2\\\"\",\n \"export BASE_REPO=\\\"", + { + "Ref": "BASEREPO" + }, + "\\\"\",\n \"export IMAGE_TAG=\\\"", + { + "Ref": "IMAGEAMDXLATAG" + }, + "\\\"\",\n \"export BASE_IMAGE_TAG=\\\"", + { + "Ref": "BASEIMAGEAMDXLATAG" + }, + "\\\"\",\n \"cd app\",\n \"chmod +x ./build-assets.sh && ./build-assets.sh\"\n ]\n }\n },\n \"artifacts\": {\n \"files\": [\n \"imageDetail.json\"\n ]\n }\n}" + ] + ] + }, + "Type": "NO_SOURCE" + } + }, + "Metadata": { + "aws:cdk:path": "flux-oci-image-inference-cdk/AssetsImageXlaAmdBuild/Resource" + } + }, + "AssetsImageCpuArmBuildBC43C501": { + "Type": "AWS::CodeBuild::Project", + "Properties": { + "Artifacts": { + "Type": "NO_ARTIFACTS" + }, + "Cache": { + "Modes": [ + "LOCAL_DOCKER_LAYER_CACHE", + "LOCAL_CUSTOM_CACHE" + ], + "Type": "LOCAL" + }, + "EncryptionKey": { + "Fn::GetAtt": [ + "BuildBasePipelineArtifactsBucketEncryptionKey04467E09", + "Arn" + ] + }, + "Environment": { + "ComputeType": "BUILD_GENERAL1_LARGE", + "Image": "aws/codebuild/amazonlinux2-aarch64-standard:2.0", + "ImagePullCredentialsType": "CODEBUILD", + "PrivilegedMode": true, + "Type": "ARM_CONTAINER" + }, + "ServiceRole": { + "Fn::GetAtt": [ + "BaseCodeBuildDeployRole2A53BD0D", + "Arn" + ] + }, + "Source": { + "BuildSpec": { + "Fn::Join": [ + "", + [ + "{\n \"version\": \"0.2\",\n \"env\": {\n \"exported-variables\": [\n \"AWS_ACCOUNT_ID\",\n \"AWS_REGION\",\n \"BASE_REPO\",\n \"IMAGE_ARM_CPU_TAG\",\n \"BASE_IMAGE_ARM_CPU_TAG\"\n ]\n },\n \"phases\": {\n \"build\": {\n \"commands\": [\n \"export AWS_ACCOUNT_ID=\\\"133573815653\\\"\",\n \"export AWS_REGION=\\\"us-west-2\\\"\",\n \"export BASE_REPO=\\\"", + { + "Ref": "BASEREPO" + }, + "\\\"\",\n \"export IMAGE_TAG=\\\"", + { + "Ref": "IMAGEARMCPUTAG" + }, + "\\\"\",\n \"export BASE_IMAGE_TAG=\\\"", + { + "Ref": "BASEIMAGEARMCPUTAG" + }, + "\\\"\",\n \"cd app\",\n \"chmod +x ./build-assets.sh && ./build-assets.sh\"\n ]\n }\n },\n \"artifacts\": {\n \"files\": [\n \"imageDetail.json\"\n ]\n }\n}" + ] + ] + }, + "Type": "NO_SOURCE" + } + }, + "Metadata": { + "aws:cdk:path": "flux-oci-image-inference-cdk/AssetsImageCpuArmBuild/Resource" + } + }, + "AssetsImageCudAmdBuild4322D558": { + "Type": "AWS::CodeBuild::Project", + "Properties": { + "Artifacts": { + "Type": "NO_ARTIFACTS" + }, + "Cache": { + "Modes": [ + "LOCAL_DOCKER_LAYER_CACHE", + "LOCAL_CUSTOM_CACHE" + ], + "Type": "LOCAL" + }, + "EncryptionKey": { + "Fn::GetAtt": [ + "BuildBasePipelineArtifactsBucketEncryptionKey04467E09", + "Arn" + ] + }, + "Environment": { + "ComputeType": "BUILD_GENERAL1_SMALL", + "Image": "aws/codebuild/amazonlinux2-x86_64-standard:3.0", + "ImagePullCredentialsType": "CODEBUILD", + "PrivilegedMode": true, + "Type": "LINUX_CONTAINER" + }, + "ServiceRole": { + "Fn::GetAtt": [ + "BaseCodeBuildDeployRole2A53BD0D", + "Arn" + ] + }, + "Source": { + "BuildSpec": { + "Fn::Join": [ + "", + [ + "{\n \"version\": \"0.2\",\n \"env\": {\n \"exported-variables\": [\n \"AWS_ACCOUNT_ID\",\n \"AWS_REGION\",\n \"BASE_REPO\",\n \"IMAGE_AMD_CUD_TAG\",\n \"BASE_IMAGE_AMD_CUD_TAG\"\n ]\n },\n \"phases\": {\n \"build\": {\n \"commands\": [\n \"export AWS_ACCOUNT_ID=\\\"133573815653\\\"\",\n \"export AWS_REGION=\\\"us-west-2\\\"\",\n \"export BASE_REPO=\\\"", + { + "Ref": "BASEREPO" + }, + "\\\"\",\n \"export IMAGE_TAG=\\\"", + { + "Ref": "IMAGEAMDCUDTAG" + }, + "\\\"\",\n \"export BASE_IMAGE_TAG=\\\"", + { + "Ref": "BASEIMAGEAMDCUDTAG" + }, + "\\\"\",\n \"cd app\",\n \"chmod +x ./build-assets.sh && ./build-assets.sh\"\n ]\n }\n },\n \"artifacts\": {\n \"files\": [\n \"imageDetail.json\"\n ]\n }\n}" + ] + ] + }, + "Type": "NO_SOURCE" + } + }, + "Metadata": { + "aws:cdk:path": "flux-oci-image-inference-cdk/AssetsImageCudAmdBuild/Resource" + } + }, + "BuildBasePipelineArtifactsBucketEncryptionKey04467E09": { + "Type": "AWS::KMS::Key", + "Properties": { + "KeyPolicy": { + "Statement": [ + { + "Action": "kms:*", + "Effect": "Allow", + "Principal": { + "AWS": { + "Fn::Join": [ + "", + [ + "arn:", + { + "Ref": "AWS::Partition" + }, + ":iam::133573815653:root" + ] + ] + } + }, + "Resource": "*" + } + ], + "Version": "2012-10-17" + } + }, + "UpdateReplacePolicy": "Delete", + "DeletionPolicy": "Delete", + "Metadata": { + "aws:cdk:path": "flux-oci-image-inference-cdk/BuildBasePipeline/ArtifactsBucketEncryptionKey/Resource" + } + }, + "BuildBasePipelineArtifactsBucketEncryptionKeyAlias8A8421DF": { + "Type": "AWS::KMS::Alias", + "Properties": { + "AliasName": "alias/codepipeline-fluxociimageinferencecdkbuildbasepipeline01a0da38", + "TargetKeyId": { + "Fn::GetAtt": [ + "BuildBasePipelineArtifactsBucketEncryptionKey04467E09", + "Arn" + ] + } + }, + "UpdateReplacePolicy": "Delete", + "DeletionPolicy": "Delete", + "Metadata": { + "aws:cdk:path": "flux-oci-image-inference-cdk/BuildBasePipeline/ArtifactsBucketEncryptionKeyAlias/Resource" + } + }, + "BuildBasePipelineArtifactsBucket51786A86": { + "Type": "AWS::S3::Bucket", + "Properties": { + "BucketEncryption": { + "ServerSideEncryptionConfiguration": [ + { + "ServerSideEncryptionByDefault": { + "KMSMasterKeyID": { + "Fn::GetAtt": [ + "BuildBasePipelineArtifactsBucketEncryptionKey04467E09", + "Arn" + ] + }, + "SSEAlgorithm": "aws:kms" + } + } + ] + }, + "PublicAccessBlockConfiguration": { + "BlockPublicAcls": true, + "BlockPublicPolicy": true, + "IgnorePublicAcls": true, + "RestrictPublicBuckets": true + } + }, + "UpdateReplacePolicy": "Retain", + "DeletionPolicy": "Retain", + "Metadata": { + "aws:cdk:path": "flux-oci-image-inference-cdk/BuildBasePipeline/ArtifactsBucket/Resource" + } + }, + "BuildBasePipelineArtifactsBucketPolicy6568CEBB": { + "Type": "AWS::S3::BucketPolicy", + "Properties": { + "Bucket": { + "Ref": "BuildBasePipelineArtifactsBucket51786A86" + }, + "PolicyDocument": { + "Statement": [ + { + "Action": "s3:*", + "Condition": { + "Bool": { + "aws:SecureTransport": "false" + } + }, + "Effect": "Deny", + "Principal": { + "AWS": "*" + }, + "Resource": [ + { + "Fn::GetAtt": [ + "BuildBasePipelineArtifactsBucket51786A86", + "Arn" + ] + }, + { + "Fn::Join": [ + "", + [ + { + "Fn::GetAtt": [ + "BuildBasePipelineArtifactsBucket51786A86", + "Arn" + ] + }, + "/*" + ] + ] + } + ] + } + ], + "Version": "2012-10-17" + } + }, + "Metadata": { + "aws:cdk:path": "flux-oci-image-inference-cdk/BuildBasePipeline/ArtifactsBucket/Policy/Resource" + } + }, + "BuildBasePipelineRole8C8F77AD": { + "Type": "AWS::IAM::Role", + "Properties": { + "AssumeRolePolicyDocument": { + "Statement": [ + { + "Action": "sts:AssumeRole", + "Effect": "Allow", + "Principal": { + "Service": "codepipeline.amazonaws.com" + } + } + ], + "Version": "2012-10-17" + } + }, + "Metadata": { + "aws:cdk:path": "flux-oci-image-inference-cdk/BuildBasePipeline/Role/Resource" + } + }, + "BuildBasePipelineRoleDefaultPolicy7CA9EFF0": { + "Type": "AWS::IAM::Policy", + "Properties": { + "PolicyDocument": { + "Statement": [ + { + "Action": [ + "s3:GetObject*", + "s3:GetBucket*", + "s3:List*", + "s3:DeleteObject*", + "s3:PutObject", + "s3:PutObjectLegalHold", + "s3:PutObjectRetention", + "s3:PutObjectTagging", + "s3:PutObjectVersionTagging", + "s3:Abort*" + ], + "Effect": "Allow", + "Resource": [ + { + "Fn::GetAtt": [ + "BuildBasePipelineArtifactsBucket51786A86", + "Arn" + ] + }, + { + "Fn::Join": [ + "", + [ + { + "Fn::GetAtt": [ + "BuildBasePipelineArtifactsBucket51786A86", + "Arn" + ] + }, + "/*" + ] + ] + } + ] + }, + { + "Action": [ + "kms:Decrypt", + "kms:DescribeKey", + "kms:Encrypt", + "kms:ReEncrypt*", + "kms:GenerateDataKey*" + ], + "Effect": "Allow", + "Resource": { + "Fn::GetAtt": [ + "BuildBasePipelineArtifactsBucketEncryptionKey04467E09", + "Arn" + ] + } + }, + { + "Action": "sts:AssumeRole", + "Effect": "Allow", + "Resource": { + "Fn::GetAtt": [ + "BuildBasePipelineImageBuildAssetsImageXlaAmdBuildCodePipelineActionRole7C093488", + "Arn" + ] + } + }, + { + "Action": "sts:AssumeRole", + "Effect": "Allow", + "Resource": { + "Fn::GetAtt": [ + "BuildBasePipelineImageBuildAssetsImageCudAmdBuildCodePipelineActionRole7F47990C", + "Arn" + ] + } + }, + { + "Action": "sts:AssumeRole", + "Effect": "Allow", + "Resource": { + "Fn::GetAtt": [ + "BuildBasePipelineImageBuildAssetsImageCpuArmBuildCodePipelineActionRole67BCBC26", + "Arn" + ] + } + }, + { + "Action": "sts:AssumeRole", + "Effect": "Allow", + "Resource": { + "Fn::GetAtt": [ + "BuildBasePipelineImageBuildBaseImageAmdXlaBuildCodePipelineActionRoleD9124FCE", + "Arn" + ] + } + }, + { + "Action": "sts:AssumeRole", + "Effect": "Allow", + "Resource": { + "Fn::GetAtt": [ + "BuildBasePipelineImageBuildBaseImageArmCpuBuildCodePipelineActionRole4DF7F5DE", + "Arn" + ] + } + }, + { + "Action": "sts:AssumeRole", + "Effect": "Allow", + "Resource": { + "Fn::GetAtt": [ + "BuildBasePipelineImageBuildBaseImageAmdCudBuildCodePipelineActionRoleA29F5F5F", + "Arn" + ] + } + } + ], + "Version": "2012-10-17" + }, + "PolicyName": "BuildBasePipelineRoleDefaultPolicy7CA9EFF0", + "Roles": [ + { + "Ref": "BuildBasePipelineRole8C8F77AD" + } + ] + }, + "Metadata": { + "aws:cdk:path": "flux-oci-image-inference-cdk/BuildBasePipeline/Role/DefaultPolicy/Resource" + } + }, + "BuildBasePipelineE93F0563": { + "Type": "AWS::CodePipeline::Pipeline", + "Properties": { + "ArtifactStore": { + "EncryptionKey": { + "Id": { + "Fn::GetAtt": [ + "BuildBasePipelineArtifactsBucketEncryptionKey04467E09", + "Arn" + ] + }, + "Type": "KMS" + }, + "Location": { + "Ref": "BuildBasePipelineArtifactsBucket51786A86" + }, + "Type": "S3" + }, + "RoleArn": { + "Fn::GetAtt": [ + "BuildBasePipelineRole8C8F77AD", + "Arn" + ] + }, + "Stages": [ + { + "Actions": [ + { + "ActionTypeId": { + "Category": "Source", + "Owner": "ThirdParty", + "Provider": "GitHub", + "Version": "1" + }, + "Configuration": { + "Owner": { + "Ref": "GITHUBUSER" + }, + "Repo": { + "Ref": "GITHUBREPO" + }, + "Branch": { + "Ref": "GITHUBBRANCH" + }, + "OAuthToken": "{{resolve:secretsmanager:githubtoken:SecretString:token::}}", + "PollForSourceChanges": false + }, + "Name": "GitHub_Source", + "OutputArtifacts": [ + { + "Name": "Artifact_Source_GitHub_Source" + } + ], + "RunOrder": 1 + } + ], + "Name": "Source" + }, + { + "Actions": [ + { + "ActionTypeId": { + "Category": "Build", + "Owner": "AWS", + "Provider": "CodeBuild", + "Version": "1" + }, + "Configuration": { + "ProjectName": { + "Ref": "AssetsImageXlaAmdBuild4E3D098F" + } + }, + "InputArtifacts": [ + { + "Name": "Artifact_Source_GitHub_Source" + } + ], + "Name": "AssetsImageXlaAmdBuild", + "RoleArn": { + "Fn::GetAtt": [ + "BuildBasePipelineImageBuildAssetsImageXlaAmdBuildCodePipelineActionRole7C093488", + "Arn" + ] + }, + "RunOrder": 1 + }, + { + "ActionTypeId": { + "Category": "Build", + "Owner": "AWS", + "Provider": "CodeBuild", + "Version": "1" + }, + "Configuration": { + "ProjectName": { + "Ref": "AssetsImageCudAmdBuild4322D558" + } + }, + "InputArtifacts": [ + { + "Name": "Artifact_Source_GitHub_Source" + } + ], + "Name": "AssetsImageCudAmdBuild", + "RoleArn": { + "Fn::GetAtt": [ + "BuildBasePipelineImageBuildAssetsImageCudAmdBuildCodePipelineActionRole7F47990C", + "Arn" + ] + }, + "RunOrder": 1 + }, + { + "ActionTypeId": { + "Category": "Build", + "Owner": "AWS", + "Provider": "CodeBuild", + "Version": "1" + }, + "Configuration": { + "ProjectName": { + "Ref": "AssetsImageCpuArmBuildBC43C501" + } + }, + "InputArtifacts": [ + { + "Name": "Artifact_Source_GitHub_Source" + } + ], + "Name": "AssetsImageCpuArmBuild", + "RoleArn": { + "Fn::GetAtt": [ + "BuildBasePipelineImageBuildAssetsImageCpuArmBuildCodePipelineActionRole67BCBC26", + "Arn" + ] + }, + "RunOrder": 1 + }, + { + "ActionTypeId": { + "Category": "Build", + "Owner": "AWS", + "Provider": "CodeBuild", + "Version": "1" + }, + "Configuration": { + "ProjectName": { + "Ref": "ImageXlaAmdBuild7511085C" + } + }, + "InputArtifacts": [ + { + "Name": "Artifact_Source_GitHub_Source" + } + ], + "Name": "BaseImageAmdXlaBuild", + "RoleArn": { + "Fn::GetAtt": [ + "BuildBasePipelineImageBuildBaseImageAmdXlaBuildCodePipelineActionRoleD9124FCE", + "Arn" + ] + }, + "RunOrder": 2 + }, + { + "ActionTypeId": { + "Category": "Build", + "Owner": "AWS", + "Provider": "CodeBuild", + "Version": "1" + }, + "Configuration": { + "ProjectName": { + "Ref": "ImageCpuArmBuild4791F7AA" + } + }, + "InputArtifacts": [ + { + "Name": "Artifact_Source_GitHub_Source" + } + ], + "Name": "BaseImageArmCpuBuild", + "RoleArn": { + "Fn::GetAtt": [ + "BuildBasePipelineImageBuildBaseImageArmCpuBuildCodePipelineActionRole4DF7F5DE", + "Arn" + ] + }, + "RunOrder": 2 + }, + { + "ActionTypeId": { + "Category": "Build", + "Owner": "AWS", + "Provider": "CodeBuild", + "Version": "1" + }, + "Configuration": { + "ProjectName": { + "Ref": "ImageCudAmdBuild23EA25C8" + } + }, + "InputArtifacts": [ + { + "Name": "Artifact_Source_GitHub_Source" + } + ], + "Name": "BaseImageAmdCudBuild", + "RoleArn": { + "Fn::GetAtt": [ + "BuildBasePipelineImageBuildBaseImageAmdCudBuildCodePipelineActionRoleA29F5F5F", + "Arn" + ] + }, + "RunOrder": 2 + } + ], + "Name": "ImageBuild" + } + ] + }, + "DependsOn": [ + "BuildBasePipelineRoleDefaultPolicy7CA9EFF0", + "BuildBasePipelineRole8C8F77AD" + ], + "Metadata": { + "aws:cdk:path": "flux-oci-image-inference-cdk/BuildBasePipeline/Resource" + } + }, + "BuildBasePipelineSourceGitHubSourceWebhookResource72F821C3": { + "Type": "AWS::CodePipeline::Webhook", + "Properties": { + "Authentication": "GITHUB_HMAC", + "AuthenticationConfiguration": { + "SecretToken": "{{resolve:secretsmanager:githubtoken:SecretString:token::}}" + }, + "Filters": [ + { + "JsonPath": "$.ref", + "MatchEquals": "refs/heads/{Branch}" + } + ], + "RegisterWithThirdParty": true, + "TargetAction": "GitHub_Source", + "TargetPipeline": { + "Ref": "BuildBasePipelineE93F0563" + }, + "TargetPipelineVersion": 1 + }, + "Metadata": { + "aws:cdk:path": "flux-oci-image-inference-cdk/BuildBasePipeline/Source/GitHub_Source/WebhookResource" + } + }, + "BuildBasePipelineImageBuildAssetsImageXlaAmdBuildCodePipelineActionRole7C093488": { + "Type": "AWS::IAM::Role", + "Properties": { + "AssumeRolePolicyDocument": { + "Statement": [ + { + "Action": "sts:AssumeRole", + "Effect": "Allow", + "Principal": { + "AWS": { + "Fn::Join": [ + "", + [ + "arn:", + { + "Ref": "AWS::Partition" + }, + ":iam::133573815653:root" + ] + ] + } + } + } + ], + "Version": "2012-10-17" + } + }, + "Metadata": { + "aws:cdk:path": "flux-oci-image-inference-cdk/BuildBasePipeline/ImageBuild/AssetsImageXlaAmdBuild/CodePipelineActionRole/Resource" + } + }, + "BuildBasePipelineImageBuildAssetsImageXlaAmdBuildCodePipelineActionRoleDefaultPolicyB3BE9D03": { + "Type": "AWS::IAM::Policy", + "Properties": { + "PolicyDocument": { + "Statement": [ + { + "Action": [ + "codebuild:BatchGetBuilds", + "codebuild:StartBuild", + "codebuild:StopBuild" + ], + "Effect": "Allow", + "Resource": { + "Fn::GetAtt": [ + "AssetsImageXlaAmdBuild4E3D098F", + "Arn" + ] + } + } + ], + "Version": "2012-10-17" + }, + "PolicyName": "BuildBasePipelineImageBuildAssetsImageXlaAmdBuildCodePipelineActionRoleDefaultPolicyB3BE9D03", + "Roles": [ + { + "Ref": "BuildBasePipelineImageBuildAssetsImageXlaAmdBuildCodePipelineActionRole7C093488" + } + ] + }, + "Metadata": { + "aws:cdk:path": "flux-oci-image-inference-cdk/BuildBasePipeline/ImageBuild/AssetsImageXlaAmdBuild/CodePipelineActionRole/DefaultPolicy/Resource" + } + }, + "BuildBasePipelineImageBuildAssetsImageCudAmdBuildCodePipelineActionRole7F47990C": { + "Type": "AWS::IAM::Role", + "Properties": { + "AssumeRolePolicyDocument": { + "Statement": [ + { + "Action": "sts:AssumeRole", + "Effect": "Allow", + "Principal": { + "AWS": { + "Fn::Join": [ + "", + [ + "arn:", + { + "Ref": "AWS::Partition" + }, + ":iam::133573815653:root" + ] + ] + } + } + } + ], + "Version": "2012-10-17" + } + }, + "Metadata": { + "aws:cdk:path": "flux-oci-image-inference-cdk/BuildBasePipeline/ImageBuild/AssetsImageCudAmdBuild/CodePipelineActionRole/Resource" + } + }, + "BuildBasePipelineImageBuildAssetsImageCudAmdBuildCodePipelineActionRoleDefaultPolicy44AAF344": { + "Type": "AWS::IAM::Policy", + "Properties": { + "PolicyDocument": { + "Statement": [ + { + "Action": [ + "codebuild:BatchGetBuilds", + "codebuild:StartBuild", + "codebuild:StopBuild" + ], + "Effect": "Allow", + "Resource": { + "Fn::GetAtt": [ + "AssetsImageCudAmdBuild4322D558", + "Arn" + ] + } + } + ], + "Version": "2012-10-17" + }, + "PolicyName": "BuildBasePipelineImageBuildAssetsImageCudAmdBuildCodePipelineActionRoleDefaultPolicy44AAF344", + "Roles": [ + { + "Ref": "BuildBasePipelineImageBuildAssetsImageCudAmdBuildCodePipelineActionRole7F47990C" + } + ] + }, + "Metadata": { + "aws:cdk:path": "flux-oci-image-inference-cdk/BuildBasePipeline/ImageBuild/AssetsImageCudAmdBuild/CodePipelineActionRole/DefaultPolicy/Resource" + } + }, + "BuildBasePipelineImageBuildAssetsImageCpuArmBuildCodePipelineActionRole67BCBC26": { + "Type": "AWS::IAM::Role", + "Properties": { + "AssumeRolePolicyDocument": { + "Statement": [ + { + "Action": "sts:AssumeRole", + "Effect": "Allow", + "Principal": { + "AWS": { + "Fn::Join": [ + "", + [ + "arn:", + { + "Ref": "AWS::Partition" + }, + ":iam::133573815653:root" + ] + ] + } + } + } + ], + "Version": "2012-10-17" + } + }, + "Metadata": { + "aws:cdk:path": "flux-oci-image-inference-cdk/BuildBasePipeline/ImageBuild/AssetsImageCpuArmBuild/CodePipelineActionRole/Resource" + } + }, + "BuildBasePipelineImageBuildAssetsImageCpuArmBuildCodePipelineActionRoleDefaultPolicy723A3220": { + "Type": "AWS::IAM::Policy", + "Properties": { + "PolicyDocument": { + "Statement": [ + { + "Action": [ + "codebuild:BatchGetBuilds", + "codebuild:StartBuild", + "codebuild:StopBuild" + ], + "Effect": "Allow", + "Resource": { + "Fn::GetAtt": [ + "AssetsImageCpuArmBuildBC43C501", + "Arn" + ] + } + } + ], + "Version": "2012-10-17" + }, + "PolicyName": "BuildBasePipelineImageBuildAssetsImageCpuArmBuildCodePipelineActionRoleDefaultPolicy723A3220", + "Roles": [ + { + "Ref": "BuildBasePipelineImageBuildAssetsImageCpuArmBuildCodePipelineActionRole67BCBC26" + } + ] + }, + "Metadata": { + "aws:cdk:path": "flux-oci-image-inference-cdk/BuildBasePipeline/ImageBuild/AssetsImageCpuArmBuild/CodePipelineActionRole/DefaultPolicy/Resource" + } + }, + "BuildBasePipelineImageBuildBaseImageAmdXlaBuildCodePipelineActionRoleD9124FCE": { + "Type": "AWS::IAM::Role", + "Properties": { + "AssumeRolePolicyDocument": { + "Statement": [ + { + "Action": "sts:AssumeRole", + "Effect": "Allow", + "Principal": { + "AWS": { + "Fn::Join": [ + "", + [ + "arn:", + { + "Ref": "AWS::Partition" + }, + ":iam::133573815653:root" + ] + ] + } + } + } + ], + "Version": "2012-10-17" + } + }, + "Metadata": { + "aws:cdk:path": "flux-oci-image-inference-cdk/BuildBasePipeline/ImageBuild/BaseImageAmdXlaBuild/CodePipelineActionRole/Resource" + } + }, + "BuildBasePipelineImageBuildBaseImageAmdXlaBuildCodePipelineActionRoleDefaultPolicy1C329D4F": { + "Type": "AWS::IAM::Policy", + "Properties": { + "PolicyDocument": { + "Statement": [ + { + "Action": [ + "codebuild:BatchGetBuilds", + "codebuild:StartBuild", + "codebuild:StopBuild" + ], + "Effect": "Allow", + "Resource": { + "Fn::GetAtt": [ + "ImageXlaAmdBuild7511085C", + "Arn" + ] + } + } + ], + "Version": "2012-10-17" + }, + "PolicyName": "BuildBasePipelineImageBuildBaseImageAmdXlaBuildCodePipelineActionRoleDefaultPolicy1C329D4F", + "Roles": [ + { + "Ref": "BuildBasePipelineImageBuildBaseImageAmdXlaBuildCodePipelineActionRoleD9124FCE" + } + ] + }, + "Metadata": { + "aws:cdk:path": "flux-oci-image-inference-cdk/BuildBasePipeline/ImageBuild/BaseImageAmdXlaBuild/CodePipelineActionRole/DefaultPolicy/Resource" + } + }, + "BuildBasePipelineImageBuildBaseImageArmCpuBuildCodePipelineActionRole4DF7F5DE": { + "Type": "AWS::IAM::Role", + "Properties": { + "AssumeRolePolicyDocument": { + "Statement": [ + { + "Action": "sts:AssumeRole", + "Effect": "Allow", + "Principal": { + "AWS": { + "Fn::Join": [ + "", + [ + "arn:", + { + "Ref": "AWS::Partition" + }, + ":iam::133573815653:root" + ] + ] + } + } + } + ], + "Version": "2012-10-17" + } + }, + "Metadata": { + "aws:cdk:path": "flux-oci-image-inference-cdk/BuildBasePipeline/ImageBuild/BaseImageArmCpuBuild/CodePipelineActionRole/Resource" + } + }, + "BuildBasePipelineImageBuildBaseImageArmCpuBuildCodePipelineActionRoleDefaultPolicy31713CB8": { + "Type": "AWS::IAM::Policy", + "Properties": { + "PolicyDocument": { + "Statement": [ + { + "Action": [ + "codebuild:BatchGetBuilds", + "codebuild:StartBuild", + "codebuild:StopBuild" + ], + "Effect": "Allow", + "Resource": { + "Fn::GetAtt": [ + "ImageCpuArmBuild4791F7AA", + "Arn" + ] + } + } + ], + "Version": "2012-10-17" + }, + "PolicyName": "BuildBasePipelineImageBuildBaseImageArmCpuBuildCodePipelineActionRoleDefaultPolicy31713CB8", + "Roles": [ + { + "Ref": "BuildBasePipelineImageBuildBaseImageArmCpuBuildCodePipelineActionRole4DF7F5DE" + } + ] + }, + "Metadata": { + "aws:cdk:path": "flux-oci-image-inference-cdk/BuildBasePipeline/ImageBuild/BaseImageArmCpuBuild/CodePipelineActionRole/DefaultPolicy/Resource" + } + }, + "BuildBasePipelineImageBuildBaseImageAmdCudBuildCodePipelineActionRoleA29F5F5F": { + "Type": "AWS::IAM::Role", + "Properties": { + "AssumeRolePolicyDocument": { + "Statement": [ + { + "Action": "sts:AssumeRole", + "Effect": "Allow", + "Principal": { + "AWS": { + "Fn::Join": [ + "", + [ + "arn:", + { + "Ref": "AWS::Partition" + }, + ":iam::133573815653:root" + ] + ] + } + } + } + ], + "Version": "2012-10-17" + } + }, + "Metadata": { + "aws:cdk:path": "flux-oci-image-inference-cdk/BuildBasePipeline/ImageBuild/BaseImageAmdCudBuild/CodePipelineActionRole/Resource" + } + }, + "BuildBasePipelineImageBuildBaseImageAmdCudBuildCodePipelineActionRoleDefaultPolicy7D964952": { + "Type": "AWS::IAM::Policy", + "Properties": { + "PolicyDocument": { + "Statement": [ + { + "Action": [ + "codebuild:BatchGetBuilds", + "codebuild:StartBuild", + "codebuild:StopBuild" + ], + "Effect": "Allow", + "Resource": { + "Fn::GetAtt": [ + "ImageCudAmdBuild23EA25C8", + "Arn" + ] + } + } + ], + "Version": "2012-10-17" + }, + "PolicyName": "BuildBasePipelineImageBuildBaseImageAmdCudBuildCodePipelineActionRoleDefaultPolicy7D964952", + "Roles": [ + { + "Ref": "BuildBasePipelineImageBuildBaseImageAmdCudBuildCodePipelineActionRoleA29F5F5F" + } + ] + }, + "Metadata": { + "aws:cdk:path": "flux-oci-image-inference-cdk/BuildBasePipeline/ImageBuild/BaseImageAmdCudBuild/CodePipelineActionRole/DefaultPolicy/Resource" + } + }, + "CDKMetadata": { + "Type": "AWS::CDK::Metadata", + "Properties": { + "Analytics": "v2:deflate64:H4sIAAAAAAAA/02QO0/EMBCEf8v1zgJ3SNRASXFRrqBEjrPAxq/IDxCy/N/xI9JdNd96RuvRHuHh6QSPB/7rB7HIQdEM6RK4kOz104zccY0BHSv+R0LhIE24WU/Bur+auE6ZEdfFtgqbUXW0ikTLdcrMlx0YvOaGf2HZdmlzTXTKTNgF50hqgTQ6u6Jo7o7d3mhDRQZLYqcWueF3nL+tlZlJ7SG9YetQ5VkR93VoUPqcIL1EIXuHnbpcy9/OObMJvY1OtI/OMWwx9Ev018xMqQirv/s5lsvC/WH1RIOLJpBGmLr+A03QqEN4AQAA" + }, + "Metadata": { + "aws:cdk:path": "flux-oci-image-inference-cdk/CDKMetadata/Default" + } + } + }, + "Outputs": { + "githubOAuthTokenRuntimeOutput1": { + "Value": { + "Fn::Join": [ + "", + [ + "{{resolve:secretsmanager:", + { + "Ref": "githubSecret7D37FCC7" + }, + ":SecretString:token::}}" + ] + ] + } + }, + "githubOAuthTokenRuntimeOutput2": { + "Value": { + "Fn::Join": [ + "", + [ + "{{resolve:secretsmanager:", + { + "Ref": "githubSecret7D37FCC7" + }, + ":SecretString:token::}}" + ] + ] + } + } + }, + "Rules": { + "CheckBootstrapVersion": { + "Assertions": [ + { + "Assert": { + "Fn::Not": [ + { + "Fn::Contains": [ + [ + "1", + "2", + "3", + "4", + "5" + ], + { + "Ref": "BootstrapVersion" + } + ] + } + ] + }, + "AssertDescription": "CDK bootstrap stack version 6 required. Please run 'cdk bootstrap' with a recent version of the CDK CLI." + } + ] + } + } +} \ No newline at end of file diff --git a/flux_serve/oci-image-build/cdk.out/manifest.json b/flux_serve/oci-image-build/cdk.out/manifest.json new file mode 100644 index 0000000..a09edbf --- /dev/null +++ b/flux_serve/oci-image-build/cdk.out/manifest.json @@ -0,0 +1,357 @@ +{ + "version": "38.0.1", + "artifacts": { + "flux-oci-image-inference-cdk.assets": { + "type": "cdk:asset-manifest", + "properties": { + "file": "flux-oci-image-inference-cdk.assets.json", + "requiresBootstrapStackVersion": 6, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version" + } + }, + "flux-oci-image-inference-cdk": { + "type": "aws:cloudformation:stack", + "environment": "aws://133573815653/us-west-2", + "properties": { + "templateFile": "flux-oci-image-inference-cdk.template.json", + "terminationProtection": false, + "validateOnSynth": false, + "assumeRoleArn": "arn:${AWS::Partition}:iam::133573815653:role/cdk-hnb659fds-deploy-role-133573815653-us-west-2", + "cloudFormationExecutionRoleArn": "arn:${AWS::Partition}:iam::133573815653:role/cdk-hnb659fds-cfn-exec-role-133573815653-us-west-2", + "stackTemplateAssetObjectUrl": "s3://cdk-hnb659fds-assets-133573815653-us-west-2/54c3377f007eccdd78146d6ef1c9fe016f1cd6dc99c2088e7f65bb90e95689cc.json", + "requiresBootstrapStackVersion": 6, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version", + "additionalDependencies": [ + "flux-oci-image-inference-cdk.assets" + ], + "lookupRole": { + "arn": "arn:${AWS::Partition}:iam::133573815653:role/cdk-hnb659fds-lookup-role-133573815653-us-west-2", + "requiresBootstrapStackVersion": 8, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version" + } + }, + "dependencies": [ + "flux-oci-image-inference-cdk.assets" + ], + "metadata": { + "/flux-oci-image-inference-cdk/BASEREPO": [ + { + "type": "aws:cdk:logicalId", + "data": "BASEREPO" + } + ], + "/flux-oci-image-inference-cdk/BASEIMAGEAMDXLATAG": [ + { + "type": "aws:cdk:logicalId", + "data": "BASEIMAGEAMDXLATAG" + } + ], + "/flux-oci-image-inference-cdk/BASEIMAGEAMDCUDTAG": [ + { + "type": "aws:cdk:logicalId", + "data": "BASEIMAGEAMDCUDTAG" + } + ], + "/flux-oci-image-inference-cdk/BASEIMAGEARMCPUTAG": [ + { + "type": "aws:cdk:logicalId", + "data": "BASEIMAGEARMCPUTAG" + } + ], + "/flux-oci-image-inference-cdk/IMAGEAMDXLATAG": [ + { + "type": "aws:cdk:logicalId", + "data": "IMAGEAMDXLATAG" + } + ], + "/flux-oci-image-inference-cdk/IMAGEAMDCUDTAG": [ + { + "type": "aws:cdk:logicalId", + "data": "IMAGEAMDCUDTAG" + } + ], + "/flux-oci-image-inference-cdk/IMAGEARMCPUTAG": [ + { + "type": "aws:cdk:logicalId", + "data": "IMAGEARMCPUTAG" + } + ], + "/flux-oci-image-inference-cdk/GITHUBOAUTHTOKEN": [ + { + "type": "aws:cdk:logicalId", + "data": "GITHUBOAUTHTOKEN" + } + ], + "/flux-oci-image-inference-cdk/GITHUBUSER": [ + { + "type": "aws:cdk:logicalId", + "data": "GITHUBUSER" + } + ], + "/flux-oci-image-inference-cdk/GITHUBREPO": [ + { + "type": "aws:cdk:logicalId", + "data": "GITHUBREPO" + } + ], + "/flux-oci-image-inference-cdk/GITHUBBRANCH": [ + { + "type": "aws:cdk:logicalId", + "data": "GITHUBBRANCH" + } + ], + "/flux-oci-image-inference-cdk/base_repo/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "baserepoCCF23216" + } + ], + "/flux-oci-image-inference-cdk/BaseCodeBuildDeployRole/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "BaseCodeBuildDeployRole2A53BD0D" + } + ], + "/flux-oci-image-inference-cdk/BaseCodeBuildDeployRole/DefaultPolicy/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "BaseCodeBuildDeployRoleDefaultPolicy93D8F557" + } + ], + "/flux-oci-image-inference-cdk/githubSecret/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "githubSecret7D37FCC7" + } + ], + "/flux-oci-image-inference-cdk/githubOAuthTokenRuntimeOutput1": [ + { + "type": "aws:cdk:logicalId", + "data": "githubOAuthTokenRuntimeOutput1" + } + ], + "/flux-oci-image-inference-cdk/githubOAuthTokenRuntimeOutput2": [ + { + "type": "aws:cdk:logicalId", + "data": "githubOAuthTokenRuntimeOutput2" + } + ], + "/flux-oci-image-inference-cdk/ImageCudAmdBuild/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "ImageCudAmdBuild23EA25C8" + } + ], + "/flux-oci-image-inference-cdk/ImageCpuArmBuild/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "ImageCpuArmBuild4791F7AA" + } + ], + "/flux-oci-image-inference-cdk/ImageXlaAmdBuild/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "ImageXlaAmdBuild7511085C" + } + ], + "/flux-oci-image-inference-cdk/AssetsImageXlaAmdBuild/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "AssetsImageXlaAmdBuild4E3D098F" + } + ], + "/flux-oci-image-inference-cdk/AssetsImageCpuArmBuild/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "AssetsImageCpuArmBuildBC43C501" + } + ], + "/flux-oci-image-inference-cdk/AssetsImageCudAmdBuild/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "AssetsImageCudAmdBuild4322D558" + } + ], + "/flux-oci-image-inference-cdk/BuildBasePipeline": [ + { + "type": "aws:cdk:warning", + "data": "V1 pipeline type is implicitly selected when `pipelineType` is not set. If you want to use V2 type, set `PipelineType.V2`. [ack: @aws-cdk/aws-codepipeline:unspecifiedPipelineType]", + "trace": [ + "Annotations.addMessage (/Users/yahavb/aws-neuron-eks-samples/flux_serve/oci-image-build/node_modules/aws-cdk-lib/core/lib/annotations.js:1:1608)", + "Annotations.addWarningV2 (/Users/yahavb/aws-neuron-eks-samples/flux_serve/oci-image-build/node_modules/aws-cdk-lib/core/lib/annotations.js:1:825)", + "new Pipeline (/Users/yahavb/aws-neuron-eks-samples/flux_serve/oci-image-build/node_modules/aws-cdk-lib/aws-codepipeline/lib/pipeline.js:1:6677)", + "new PipelineStack (/Users/yahavb/aws-neuron-eks-samples/flux_serve/oci-image-build/pipeline-stack.ts:262:29)", + "Object. (/Users/yahavb/aws-neuron-eks-samples/flux_serve/oci-image-build/pipeline.ts:8:1)", + "Module._compile (node:internal/modules/cjs/loader:1566:14)", + "Module.m._compile (/Users/yahavb/aws-neuron-eks-samples/flux_serve/oci-image-build/node_modules/ts-node/src/index.ts:1618:23)", + "node:internal/modules/cjs/loader:1718:10", + "Object.require.extensions. [as .ts] (/Users/yahavb/aws-neuron-eks-samples/flux_serve/oci-image-build/node_modules/ts-node/src/index.ts:1621:12)", + "Module.load (node:internal/modules/cjs/loader:1305:32)", + "Function._load (node:internal/modules/cjs/loader:1119:12)", + "TracingChannel.traceSync (node:diagnostics_channel:322:14)", + "wrapModuleLoad (node:internal/modules/cjs/loader:220:24)", + "Function.executeUserEntryPoint [as runMain] (node:internal/modules/run_main:151:5)", + "phase4 (/Users/yahavb/aws-neuron-eks-samples/flux_serve/oci-image-build/node_modules/ts-node/src/bin.ts:649:14)", + "bootstrap (/Users/yahavb/aws-neuron-eks-samples/flux_serve/oci-image-build/node_modules/ts-node/src/bin.ts:95:10)", + "main (/Users/yahavb/aws-neuron-eks-samples/flux_serve/oci-image-build/node_modules/ts-node/src/bin.ts:55:10)", + "Object. (/Users/yahavb/aws-neuron-eks-samples/flux_serve/oci-image-build/node_modules/ts-node/src/bin.ts:800:3)", + "Module._compile (node:internal/modules/cjs/loader:1566:14)", + "Object. (node:internal/modules/cjs/loader:1718:10)", + "Module.load (node:internal/modules/cjs/loader:1305:32)", + "Function._load (node:internal/modules/cjs/loader:1119:12)", + "TracingChannel.traceSync (node:diagnostics_channel:322:14)", + "wrapModuleLoad (node:internal/modules/cjs/loader:220:24)", + "Function.executeUserEntryPoint [as runMain] (node:internal/modules/run_main:151:5)", + "node:internal/main/run_main_module:33:47" + ] + } + ], + "/flux-oci-image-inference-cdk/BuildBasePipeline/ArtifactsBucketEncryptionKey/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "BuildBasePipelineArtifactsBucketEncryptionKey04467E09" + } + ], + "/flux-oci-image-inference-cdk/BuildBasePipeline/ArtifactsBucketEncryptionKeyAlias/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "BuildBasePipelineArtifactsBucketEncryptionKeyAlias8A8421DF" + } + ], + "/flux-oci-image-inference-cdk/BuildBasePipeline/ArtifactsBucket/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "BuildBasePipelineArtifactsBucket51786A86" + } + ], + "/flux-oci-image-inference-cdk/BuildBasePipeline/ArtifactsBucket/Policy/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "BuildBasePipelineArtifactsBucketPolicy6568CEBB" + } + ], + "/flux-oci-image-inference-cdk/BuildBasePipeline/Role/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "BuildBasePipelineRole8C8F77AD" + } + ], + "/flux-oci-image-inference-cdk/BuildBasePipeline/Role/DefaultPolicy/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "BuildBasePipelineRoleDefaultPolicy7CA9EFF0" + } + ], + "/flux-oci-image-inference-cdk/BuildBasePipeline/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "BuildBasePipelineE93F0563" + } + ], + "/flux-oci-image-inference-cdk/BuildBasePipeline/Source/GitHub_Source/WebhookResource": [ + { + "type": "aws:cdk:logicalId", + "data": "BuildBasePipelineSourceGitHubSourceWebhookResource72F821C3" + } + ], + "/flux-oci-image-inference-cdk/BuildBasePipeline/ImageBuild/AssetsImageXlaAmdBuild/CodePipelineActionRole/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "BuildBasePipelineImageBuildAssetsImageXlaAmdBuildCodePipelineActionRole7C093488" + } + ], + "/flux-oci-image-inference-cdk/BuildBasePipeline/ImageBuild/AssetsImageXlaAmdBuild/CodePipelineActionRole/DefaultPolicy/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "BuildBasePipelineImageBuildAssetsImageXlaAmdBuildCodePipelineActionRoleDefaultPolicyB3BE9D03" + } + ], + "/flux-oci-image-inference-cdk/BuildBasePipeline/ImageBuild/AssetsImageCudAmdBuild/CodePipelineActionRole/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "BuildBasePipelineImageBuildAssetsImageCudAmdBuildCodePipelineActionRole7F47990C" + } + ], + "/flux-oci-image-inference-cdk/BuildBasePipeline/ImageBuild/AssetsImageCudAmdBuild/CodePipelineActionRole/DefaultPolicy/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "BuildBasePipelineImageBuildAssetsImageCudAmdBuildCodePipelineActionRoleDefaultPolicy44AAF344" + } + ], + "/flux-oci-image-inference-cdk/BuildBasePipeline/ImageBuild/AssetsImageCpuArmBuild/CodePipelineActionRole/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "BuildBasePipelineImageBuildAssetsImageCpuArmBuildCodePipelineActionRole67BCBC26" + } + ], + "/flux-oci-image-inference-cdk/BuildBasePipeline/ImageBuild/AssetsImageCpuArmBuild/CodePipelineActionRole/DefaultPolicy/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "BuildBasePipelineImageBuildAssetsImageCpuArmBuildCodePipelineActionRoleDefaultPolicy723A3220" + } + ], + "/flux-oci-image-inference-cdk/BuildBasePipeline/ImageBuild/BaseImageAmdXlaBuild/CodePipelineActionRole/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "BuildBasePipelineImageBuildBaseImageAmdXlaBuildCodePipelineActionRoleD9124FCE" + } + ], + "/flux-oci-image-inference-cdk/BuildBasePipeline/ImageBuild/BaseImageAmdXlaBuild/CodePipelineActionRole/DefaultPolicy/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "BuildBasePipelineImageBuildBaseImageAmdXlaBuildCodePipelineActionRoleDefaultPolicy1C329D4F" + } + ], + "/flux-oci-image-inference-cdk/BuildBasePipeline/ImageBuild/BaseImageArmCpuBuild/CodePipelineActionRole/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "BuildBasePipelineImageBuildBaseImageArmCpuBuildCodePipelineActionRole4DF7F5DE" + } + ], + "/flux-oci-image-inference-cdk/BuildBasePipeline/ImageBuild/BaseImageArmCpuBuild/CodePipelineActionRole/DefaultPolicy/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "BuildBasePipelineImageBuildBaseImageArmCpuBuildCodePipelineActionRoleDefaultPolicy31713CB8" + } + ], + "/flux-oci-image-inference-cdk/BuildBasePipeline/ImageBuild/BaseImageAmdCudBuild/CodePipelineActionRole/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "BuildBasePipelineImageBuildBaseImageAmdCudBuildCodePipelineActionRoleA29F5F5F" + } + ], + "/flux-oci-image-inference-cdk/BuildBasePipeline/ImageBuild/BaseImageAmdCudBuild/CodePipelineActionRole/DefaultPolicy/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "BuildBasePipelineImageBuildBaseImageAmdCudBuildCodePipelineActionRoleDefaultPolicy7D964952" + } + ], + "/flux-oci-image-inference-cdk/CDKMetadata/Default": [ + { + "type": "aws:cdk:logicalId", + "data": "CDKMetadata" + } + ], + "/flux-oci-image-inference-cdk/BootstrapVersion": [ + { + "type": "aws:cdk:logicalId", + "data": "BootstrapVersion" + } + ], + "/flux-oci-image-inference-cdk/CheckBootstrapVersion": [ + { + "type": "aws:cdk:logicalId", + "data": "CheckBootstrapVersion" + } + ] + }, + "displayName": "flux-oci-image-inference-cdk" + }, + "Tree": { + "type": "cdk:tree", + "properties": { + "file": "tree.json" + } + } + } +} \ No newline at end of file diff --git a/flux_serve/oci-image-build/cdk.out/tree.json b/flux_serve/oci-image-build/cdk.out/tree.json new file mode 100644 index 0000000..0e86e2f --- /dev/null +++ b/flux_serve/oci-image-build/cdk.out/tree.json @@ -0,0 +1,2599 @@ +{ + "version": "tree-0.1", + "tree": { + "id": "App", + "path": "", + "children": { + "flux-oci-image-inference-cdk": { + "id": "flux-oci-image-inference-cdk", + "path": "flux-oci-image-inference-cdk", + "children": { + "BASEREPO": { + "id": "BASEREPO", + "path": "flux-oci-image-inference-cdk/BASEREPO", + "constructInfo": { + "fqn": "aws-cdk-lib.CfnParameter", + "version": "2.173.4" + } + }, + "BASEIMAGEAMDXLATAG": { + "id": "BASEIMAGEAMDXLATAG", + "path": "flux-oci-image-inference-cdk/BASEIMAGEAMDXLATAG", + "constructInfo": { + "fqn": "aws-cdk-lib.CfnParameter", + "version": "2.173.4" + } + }, + "BASEIMAGEAMDCUDTAG": { + "id": "BASEIMAGEAMDCUDTAG", + "path": "flux-oci-image-inference-cdk/BASEIMAGEAMDCUDTAG", + "constructInfo": { + "fqn": "aws-cdk-lib.CfnParameter", + "version": "2.173.4" + } + }, + "BASEIMAGEARMCPUTAG": { + "id": "BASEIMAGEARMCPUTAG", + "path": "flux-oci-image-inference-cdk/BASEIMAGEARMCPUTAG", + "constructInfo": { + "fqn": "aws-cdk-lib.CfnParameter", + "version": "2.173.4" + } + }, + "IMAGEAMDXLATAG": { + "id": "IMAGEAMDXLATAG", + "path": "flux-oci-image-inference-cdk/IMAGEAMDXLATAG", + "constructInfo": { + "fqn": "aws-cdk-lib.CfnParameter", + "version": "2.173.4" + } + }, + "IMAGEAMDCUDTAG": { + "id": "IMAGEAMDCUDTAG", + "path": "flux-oci-image-inference-cdk/IMAGEAMDCUDTAG", + "constructInfo": { + "fqn": "aws-cdk-lib.CfnParameter", + "version": "2.173.4" + } + }, + "IMAGEARMCPUTAG": { + "id": "IMAGEARMCPUTAG", + "path": "flux-oci-image-inference-cdk/IMAGEARMCPUTAG", + "constructInfo": { + "fqn": "aws-cdk-lib.CfnParameter", + "version": "2.173.4" + } + }, + "GITHUBOAUTHTOKEN": { + "id": "GITHUBOAUTHTOKEN", + "path": "flux-oci-image-inference-cdk/GITHUBOAUTHTOKEN", + "constructInfo": { + "fqn": "aws-cdk-lib.CfnParameter", + "version": "2.173.4" + } + }, + "GITHUBUSER": { + "id": "GITHUBUSER", + "path": "flux-oci-image-inference-cdk/GITHUBUSER", + "constructInfo": { + "fqn": "aws-cdk-lib.CfnParameter", + "version": "2.173.4" + } + }, + "GITHUBREPO": { + "id": "GITHUBREPO", + "path": "flux-oci-image-inference-cdk/GITHUBREPO", + "constructInfo": { + "fqn": "aws-cdk-lib.CfnParameter", + "version": "2.173.4" + } + }, + "GITHUBBRANCH": { + "id": "GITHUBBRANCH", + "path": "flux-oci-image-inference-cdk/GITHUBBRANCH", + "constructInfo": { + "fqn": "aws-cdk-lib.CfnParameter", + "version": "2.173.4" + } + }, + "base_repo": { + "id": "base_repo", + "path": "flux-oci-image-inference-cdk/base_repo", + "children": { + "Resource": { + "id": "Resource", + "path": "flux-oci-image-inference-cdk/base_repo/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::ECR::Repository", + "aws:cdk:cloudformation:props": { + "imageScanningConfiguration": { + "scanOnPush": true + }, + "repositoryName": { + "Ref": "BASEREPO" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_ecr.CfnRepository", + "version": "2.173.4" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_ecr.Repository", + "version": "2.173.4" + } + }, + "BaseCodeBuildDeployRole": { + "id": "BaseCodeBuildDeployRole", + "path": "flux-oci-image-inference-cdk/BaseCodeBuildDeployRole", + "children": { + "ImportBaseCodeBuildDeployRole": { + "id": "ImportBaseCodeBuildDeployRole", + "path": "flux-oci-image-inference-cdk/BaseCodeBuildDeployRole/ImportBaseCodeBuildDeployRole", + "constructInfo": { + "fqn": "aws-cdk-lib.Resource", + "version": "2.173.4" + } + }, + "Resource": { + "id": "Resource", + "path": "flux-oci-image-inference-cdk/BaseCodeBuildDeployRole/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::IAM::Role", + "aws:cdk:cloudformation:props": { + "assumeRolePolicyDocument": { + "Statement": [ + { + "Action": "sts:AssumeRole", + "Effect": "Allow", + "Principal": { + "Service": "codebuild.amazonaws.com" + } + } + ], + "Version": "2012-10-17" + }, + "roleName": "hwagnisticBaseCodeBuildDeployRole" + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_iam.CfnRole", + "version": "2.173.4" + } + }, + "DefaultPolicy": { + "id": "DefaultPolicy", + "path": "flux-oci-image-inference-cdk/BaseCodeBuildDeployRole/DefaultPolicy", + "children": { + "Resource": { + "id": "Resource", + "path": "flux-oci-image-inference-cdk/BaseCodeBuildDeployRole/DefaultPolicy/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::IAM::Policy", + "aws:cdk:cloudformation:props": { + "policyDocument": { + "Statement": [ + { + "Action": [ + "ssm:*", + "s3:*" + ], + "Effect": "Allow", + "Resource": "*" + }, + { + "Action": [ + "logs:CreateLogGroup", + "logs:CreateLogStream", + "logs:PutLogEvents" + ], + "Effect": "Allow", + "Resource": [ + { + "Fn::Join": [ + "", + [ + "arn:", + { + "Ref": "AWS::Partition" + }, + ":logs:us-west-2:133573815653:log-group:/aws/codebuild/", + { + "Ref": "ImageCudAmdBuild23EA25C8" + } + ] + ] + }, + { + "Fn::Join": [ + "", + [ + "arn:", + { + "Ref": "AWS::Partition" + }, + ":logs:us-west-2:133573815653:log-group:/aws/codebuild/", + { + "Ref": "ImageCudAmdBuild23EA25C8" + }, + ":*" + ] + ] + } + ] + }, + { + "Action": [ + "codebuild:CreateReportGroup", + "codebuild:CreateReport", + "codebuild:UpdateReport", + "codebuild:BatchPutTestCases", + "codebuild:BatchPutCodeCoverages" + ], + "Effect": "Allow", + "Resource": { + "Fn::Join": [ + "", + [ + "arn:", + { + "Ref": "AWS::Partition" + }, + ":codebuild:us-west-2:133573815653:report-group/", + { + "Ref": "ImageCudAmdBuild23EA25C8" + }, + "-*" + ] + ] + } + }, + { + "Action": [ + "logs:CreateLogGroup", + "logs:CreateLogStream", + "logs:PutLogEvents" + ], + "Effect": "Allow", + "Resource": [ + { + "Fn::Join": [ + "", + [ + "arn:", + { + "Ref": "AWS::Partition" + }, + ":logs:us-west-2:133573815653:log-group:/aws/codebuild/", + { + "Ref": "ImageCpuArmBuild4791F7AA" + } + ] + ] + }, + { + "Fn::Join": [ + "", + [ + "arn:", + { + "Ref": "AWS::Partition" + }, + ":logs:us-west-2:133573815653:log-group:/aws/codebuild/", + { + "Ref": "ImageCpuArmBuild4791F7AA" + }, + ":*" + ] + ] + } + ] + }, + { + "Action": [ + "codebuild:CreateReportGroup", + "codebuild:CreateReport", + "codebuild:UpdateReport", + "codebuild:BatchPutTestCases", + "codebuild:BatchPutCodeCoverages" + ], + "Effect": "Allow", + "Resource": { + "Fn::Join": [ + "", + [ + "arn:", + { + "Ref": "AWS::Partition" + }, + ":codebuild:us-west-2:133573815653:report-group/", + { + "Ref": "ImageCpuArmBuild4791F7AA" + }, + "-*" + ] + ] + } + }, + { + "Action": [ + "logs:CreateLogGroup", + "logs:CreateLogStream", + "logs:PutLogEvents" + ], + "Effect": "Allow", + "Resource": [ + { + "Fn::Join": [ + "", + [ + "arn:", + { + "Ref": "AWS::Partition" + }, + ":logs:us-west-2:133573815653:log-group:/aws/codebuild/", + { + "Ref": "ImageXlaAmdBuild7511085C" + } + ] + ] + }, + { + "Fn::Join": [ + "", + [ + "arn:", + { + "Ref": "AWS::Partition" + }, + ":logs:us-west-2:133573815653:log-group:/aws/codebuild/", + { + "Ref": "ImageXlaAmdBuild7511085C" + }, + ":*" + ] + ] + } + ] + }, + { + "Action": [ + "codebuild:CreateReportGroup", + "codebuild:CreateReport", + "codebuild:UpdateReport", + "codebuild:BatchPutTestCases", + "codebuild:BatchPutCodeCoverages" + ], + "Effect": "Allow", + "Resource": { + "Fn::Join": [ + "", + [ + "arn:", + { + "Ref": "AWS::Partition" + }, + ":codebuild:us-west-2:133573815653:report-group/", + { + "Ref": "ImageXlaAmdBuild7511085C" + }, + "-*" + ] + ] + } + }, + { + "Action": [ + "logs:CreateLogGroup", + "logs:CreateLogStream", + "logs:PutLogEvents" + ], + "Effect": "Allow", + "Resource": [ + { + "Fn::Join": [ + "", + [ + "arn:", + { + "Ref": "AWS::Partition" + }, + ":logs:us-west-2:133573815653:log-group:/aws/codebuild/", + { + "Ref": "AssetsImageXlaAmdBuild4E3D098F" + } + ] + ] + }, + { + "Fn::Join": [ + "", + [ + "arn:", + { + "Ref": "AWS::Partition" + }, + ":logs:us-west-2:133573815653:log-group:/aws/codebuild/", + { + "Ref": "AssetsImageXlaAmdBuild4E3D098F" + }, + ":*" + ] + ] + } + ] + }, + { + "Action": [ + "codebuild:CreateReportGroup", + "codebuild:CreateReport", + "codebuild:UpdateReport", + "codebuild:BatchPutTestCases", + "codebuild:BatchPutCodeCoverages" + ], + "Effect": "Allow", + "Resource": { + "Fn::Join": [ + "", + [ + "arn:", + { + "Ref": "AWS::Partition" + }, + ":codebuild:us-west-2:133573815653:report-group/", + { + "Ref": "AssetsImageXlaAmdBuild4E3D098F" + }, + "-*" + ] + ] + } + }, + { + "Action": [ + "logs:CreateLogGroup", + "logs:CreateLogStream", + "logs:PutLogEvents" + ], + "Effect": "Allow", + "Resource": [ + { + "Fn::Join": [ + "", + [ + "arn:", + { + "Ref": "AWS::Partition" + }, + ":logs:us-west-2:133573815653:log-group:/aws/codebuild/", + { + "Ref": "AssetsImageCpuArmBuildBC43C501" + } + ] + ] + }, + { + "Fn::Join": [ + "", + [ + "arn:", + { + "Ref": "AWS::Partition" + }, + ":logs:us-west-2:133573815653:log-group:/aws/codebuild/", + { + "Ref": "AssetsImageCpuArmBuildBC43C501" + }, + ":*" + ] + ] + } + ] + }, + { + "Action": [ + "codebuild:CreateReportGroup", + "codebuild:CreateReport", + "codebuild:UpdateReport", + "codebuild:BatchPutTestCases", + "codebuild:BatchPutCodeCoverages" + ], + "Effect": "Allow", + "Resource": { + "Fn::Join": [ + "", + [ + "arn:", + { + "Ref": "AWS::Partition" + }, + ":codebuild:us-west-2:133573815653:report-group/", + { + "Ref": "AssetsImageCpuArmBuildBC43C501" + }, + "-*" + ] + ] + } + }, + { + "Action": [ + "logs:CreateLogGroup", + "logs:CreateLogStream", + "logs:PutLogEvents" + ], + "Effect": "Allow", + "Resource": [ + { + "Fn::Join": [ + "", + [ + "arn:", + { + "Ref": "AWS::Partition" + }, + ":logs:us-west-2:133573815653:log-group:/aws/codebuild/", + { + "Ref": "AssetsImageCudAmdBuild4322D558" + } + ] + ] + }, + { + "Fn::Join": [ + "", + [ + "arn:", + { + "Ref": "AWS::Partition" + }, + ":logs:us-west-2:133573815653:log-group:/aws/codebuild/", + { + "Ref": "AssetsImageCudAmdBuild4322D558" + }, + ":*" + ] + ] + } + ] + }, + { + "Action": [ + "codebuild:CreateReportGroup", + "codebuild:CreateReport", + "codebuild:UpdateReport", + "codebuild:BatchPutTestCases", + "codebuild:BatchPutCodeCoverages" + ], + "Effect": "Allow", + "Resource": { + "Fn::Join": [ + "", + [ + "arn:", + { + "Ref": "AWS::Partition" + }, + ":codebuild:us-west-2:133573815653:report-group/", + { + "Ref": "AssetsImageCudAmdBuild4322D558" + }, + "-*" + ] + ] + } + }, + { + "Action": [ + "ecr:BatchCheckLayerAvailability", + "ecr:GetDownloadUrlForLayer", + "ecr:BatchGetImage", + "ecr:CompleteLayerUpload", + "ecr:UploadLayerPart", + "ecr:InitiateLayerUpload", + "ecr:PutImage" + ], + "Effect": "Allow", + "Resource": { + "Fn::GetAtt": [ + "baserepoCCF23216", + "Arn" + ] + } + }, + { + "Action": "ecr:GetAuthorizationToken", + "Effect": "Allow", + "Resource": "*" + }, + { + "Action": [ + "s3:GetObject*", + "s3:GetBucket*", + "s3:List*" + ], + "Effect": "Allow", + "Resource": [ + { + "Fn::GetAtt": [ + "BuildBasePipelineArtifactsBucket51786A86", + "Arn" + ] + }, + { + "Fn::Join": [ + "", + [ + { + "Fn::GetAtt": [ + "BuildBasePipelineArtifactsBucket51786A86", + "Arn" + ] + }, + "/*" + ] + ] + } + ] + }, + { + "Action": [ + "kms:Decrypt", + "kms:DescribeKey" + ], + "Effect": "Allow", + "Resource": { + "Fn::GetAtt": [ + "BuildBasePipelineArtifactsBucketEncryptionKey04467E09", + "Arn" + ] + } + }, + { + "Action": [ + "kms:Decrypt", + "kms:Encrypt", + "kms:ReEncrypt*", + "kms:GenerateDataKey*" + ], + "Effect": "Allow", + "Resource": { + "Fn::GetAtt": [ + "BuildBasePipelineArtifactsBucketEncryptionKey04467E09", + "Arn" + ] + } + } + ], + "Version": "2012-10-17" + }, + "policyName": "BaseCodeBuildDeployRoleDefaultPolicy93D8F557", + "roles": [ + { + "Ref": "BaseCodeBuildDeployRole2A53BD0D" + } + ] + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_iam.CfnPolicy", + "version": "2.173.4" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_iam.Policy", + "version": "2.173.4" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_iam.Role", + "version": "2.173.4" + } + }, + "githubSecret": { + "id": "githubSecret", + "path": "flux-oci-image-inference-cdk/githubSecret", + "children": { + "Resource": { + "id": "Resource", + "path": "flux-oci-image-inference-cdk/githubSecret/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::SecretsManager::Secret", + "aws:cdk:cloudformation:props": { + "secretString": { + "Fn::Join": [ + "", + [ + "{\"token\":\"", + { + "Ref": "GITHUBOAUTHTOKEN" + }, + "\"}" + ] + ] + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_secretsmanager.CfnSecret", + "version": "2.173.4" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_secretsmanager.Secret", + "version": "2.173.4" + } + }, + "githubOAuthTokenRuntimeOutput1": { + "id": "githubOAuthTokenRuntimeOutput1", + "path": "flux-oci-image-inference-cdk/githubOAuthTokenRuntimeOutput1", + "constructInfo": { + "fqn": "aws-cdk-lib.CfnOutput", + "version": "2.173.4" + } + }, + "githubOAuthTokenRuntimeOutput2": { + "id": "githubOAuthTokenRuntimeOutput2", + "path": "flux-oci-image-inference-cdk/githubOAuthTokenRuntimeOutput2", + "constructInfo": { + "fqn": "aws-cdk-lib.CfnOutput", + "version": "2.173.4" + } + }, + "ImageCudAmdBuild": { + "id": "ImageCudAmdBuild", + "path": "flux-oci-image-inference-cdk/ImageCudAmdBuild", + "children": { + "Resource": { + "id": "Resource", + "path": "flux-oci-image-inference-cdk/ImageCudAmdBuild/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::CodeBuild::Project", + "aws:cdk:cloudformation:props": { + "artifacts": { + "type": "NO_ARTIFACTS" + }, + "cache": { + "type": "LOCAL", + "modes": [ + "LOCAL_DOCKER_LAYER_CACHE", + "LOCAL_CUSTOM_CACHE" + ] + }, + "encryptionKey": { + "Fn::GetAtt": [ + "BuildBasePipelineArtifactsBucketEncryptionKey04467E09", + "Arn" + ] + }, + "environment": { + "type": "LINUX_CONTAINER", + "image": "aws/codebuild/amazonlinux2-x86_64-standard:3.0", + "imagePullCredentialsType": "CODEBUILD", + "privilegedMode": true, + "computeType": "BUILD_GENERAL1_SMALL" + }, + "serviceRole": { + "Fn::GetAtt": [ + "BaseCodeBuildDeployRole2A53BD0D", + "Arn" + ] + }, + "source": { + "type": "NO_SOURCE", + "buildSpec": { + "Fn::Join": [ + "", + [ + "{\n \"version\": \"0.2\",\n \"env\": {\n \"exported-variables\": [\n \"AWS_ACCOUNT_ID\",\n \"AWS_REGION\",\n \"BASE_REPO\",\n \"IMAGE_AMD_CUD_TAG\",\n \"BASE_IMAGE_AMD_CUD_TAG\"\n ]\n },\n \"phases\": {\n \"build\": {\n \"commands\": [\n \"export AWS_ACCOUNT_ID=\\\"133573815653\\\"\",\n \"export AWS_REGION=\\\"us-west-2\\\"\",\n \"export BASE_REPO=\\\"", + { + "Ref": "BASEREPO" + }, + "\\\"\",\n \"export IMAGE_TAG=\\\"", + { + "Ref": "IMAGEAMDCUDTAG" + }, + "\\\"\",\n \"export BASE_IMAGE_TAG=\\\"", + { + "Ref": "BASEIMAGEAMDCUDTAG" + }, + "\\\"\",\n \"cd app\",\n \"chmod +x ./build.sh && ./build.sh\"\n ]\n }\n },\n \"artifacts\": {\n \"files\": [\n \"imageDetail.json\"\n ]\n }\n}" + ] + ] + } + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_codebuild.CfnProject", + "version": "2.173.4" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_codebuild.Project", + "version": "2.173.4" + } + }, + "ImageCpuArmBuild": { + "id": "ImageCpuArmBuild", + "path": "flux-oci-image-inference-cdk/ImageCpuArmBuild", + "children": { + "Resource": { + "id": "Resource", + "path": "flux-oci-image-inference-cdk/ImageCpuArmBuild/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::CodeBuild::Project", + "aws:cdk:cloudformation:props": { + "artifacts": { + "type": "NO_ARTIFACTS" + }, + "cache": { + "type": "LOCAL", + "modes": [ + "LOCAL_DOCKER_LAYER_CACHE", + "LOCAL_CUSTOM_CACHE" + ] + }, + "encryptionKey": { + "Fn::GetAtt": [ + "BuildBasePipelineArtifactsBucketEncryptionKey04467E09", + "Arn" + ] + }, + "environment": { + "type": "ARM_CONTAINER", + "image": "aws/codebuild/amazonlinux2-aarch64-standard:2.0", + "imagePullCredentialsType": "CODEBUILD", + "privilegedMode": true, + "computeType": "BUILD_GENERAL1_LARGE" + }, + "serviceRole": { + "Fn::GetAtt": [ + "BaseCodeBuildDeployRole2A53BD0D", + "Arn" + ] + }, + "source": { + "type": "NO_SOURCE", + "buildSpec": { + "Fn::Join": [ + "", + [ + "{\n \"version\": \"0.2\",\n \"env\": {\n \"exported-variables\": [\n \"AWS_ACCOUNT_ID\",\n \"AWS_REGION\",\n \"BASE_REPO\",\n \"IMAGE_ARM_CPU_TAG\",\n \"BASE_IMAGE_ARM_CPU_TAG\"\n ]\n },\n \"phases\": {\n \"build\": {\n \"commands\": [\n \"export AWS_ACCOUNT_ID=\\\"133573815653\\\"\",\n \"export AWS_REGION=\\\"us-west-2\\\"\",\n \"export BASE_REPO=\\\"", + { + "Ref": "BASEREPO" + }, + "\\\"\",\n \"export IMAGE_TAG=\\\"", + { + "Ref": "IMAGEARMCPUTAG" + }, + "\\\"\",\n \"export BASE_IMAGE_TAG=\\\"", + { + "Ref": "BASEIMAGEARMCPUTAG" + }, + "\\\"\",\n \"cd app\",\n \"chmod +x ./build.sh && ./build.sh\"\n ]\n }\n },\n \"artifacts\": {\n \"files\": [\n \"imageDetail.json\"\n ]\n }\n}" + ] + ] + } + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_codebuild.CfnProject", + "version": "2.173.4" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_codebuild.Project", + "version": "2.173.4" + } + }, + "ImageXlaAmdBuild": { + "id": "ImageXlaAmdBuild", + "path": "flux-oci-image-inference-cdk/ImageXlaAmdBuild", + "children": { + "Resource": { + "id": "Resource", + "path": "flux-oci-image-inference-cdk/ImageXlaAmdBuild/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::CodeBuild::Project", + "aws:cdk:cloudformation:props": { + "artifacts": { + "type": "NO_ARTIFACTS" + }, + "cache": { + "type": "LOCAL", + "modes": [ + "LOCAL_DOCKER_LAYER_CACHE", + "LOCAL_CUSTOM_CACHE" + ] + }, + "encryptionKey": { + "Fn::GetAtt": [ + "BuildBasePipelineArtifactsBucketEncryptionKey04467E09", + "Arn" + ] + }, + "environment": { + "type": "LINUX_CONTAINER", + "image": "aws/codebuild/amazonlinux2-x86_64-standard:3.0", + "imagePullCredentialsType": "CODEBUILD", + "privilegedMode": true, + "computeType": "BUILD_GENERAL1_SMALL" + }, + "serviceRole": { + "Fn::GetAtt": [ + "BaseCodeBuildDeployRole2A53BD0D", + "Arn" + ] + }, + "source": { + "type": "NO_SOURCE", + "buildSpec": { + "Fn::Join": [ + "", + [ + "{\n \"version\": \"0.2\",\n \"env\": {\n \"exported-variables\": [\n \"AWS_ACCOUNT_ID\",\n \"AWS_REGION\",\n \"BASE_REPO\",\n \"IMAGE_AMD_XLA_TAG\",\n \"BASE_IMAGE_AMD_XLA_TAG\"\n ]\n },\n \"phases\": {\n \"build\": {\n \"commands\": [\n \"export AWS_ACCOUNT_ID=\\\"133573815653\\\"\",\n \"export AWS_REGION=\\\"us-west-2\\\"\",\n \"export BASE_REPO=\\\"", + { + "Ref": "BASEREPO" + }, + "\\\"\",\n \"export IMAGE_TAG=\\\"", + { + "Ref": "IMAGEAMDXLATAG" + }, + "\\\"\",\n \"export BASE_IMAGE_TAG=\\\"", + { + "Ref": "BASEIMAGEAMDXLATAG" + }, + "\\\"\",\n \"cd app\",\n \"chmod +x ./build.sh && ./build.sh\"\n ]\n }\n },\n \"artifacts\": {\n \"files\": [\n \"imageDetail.json\"\n ]\n }\n}" + ] + ] + } + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_codebuild.CfnProject", + "version": "2.173.4" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_codebuild.Project", + "version": "2.173.4" + } + }, + "AssetsImageXlaAmdBuild": { + "id": "AssetsImageXlaAmdBuild", + "path": "flux-oci-image-inference-cdk/AssetsImageXlaAmdBuild", + "children": { + "Resource": { + "id": "Resource", + "path": "flux-oci-image-inference-cdk/AssetsImageXlaAmdBuild/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::CodeBuild::Project", + "aws:cdk:cloudformation:props": { + "artifacts": { + "type": "NO_ARTIFACTS" + }, + "cache": { + "type": "LOCAL", + "modes": [ + "LOCAL_DOCKER_LAYER_CACHE", + "LOCAL_CUSTOM_CACHE" + ] + }, + "encryptionKey": { + "Fn::GetAtt": [ + "BuildBasePipelineArtifactsBucketEncryptionKey04467E09", + "Arn" + ] + }, + "environment": { + "type": "LINUX_CONTAINER", + "image": "aws/codebuild/amazonlinux2-x86_64-standard:3.0", + "imagePullCredentialsType": "CODEBUILD", + "privilegedMode": true, + "computeType": "BUILD_GENERAL1_SMALL" + }, + "serviceRole": { + "Fn::GetAtt": [ + "BaseCodeBuildDeployRole2A53BD0D", + "Arn" + ] + }, + "source": { + "type": "NO_SOURCE", + "buildSpec": { + "Fn::Join": [ + "", + [ + "{\n \"version\": \"0.2\",\n \"env\": {\n \"exported-variables\": [\n \"AWS_ACCOUNT_ID\",\n \"AWS_REGION\",\n \"BASE_REPO\",\n \"IMAGE_AMD_XLA_TAG\",\n \"BASE_IMAGE_AMD_XLA_TAG\"\n ]\n },\n \"phases\": {\n \"build\": {\n \"commands\": [\n \"export AWS_ACCOUNT_ID=\\\"133573815653\\\"\",\n \"export AWS_REGION=\\\"us-west-2\\\"\",\n \"export BASE_REPO=\\\"", + { + "Ref": "BASEREPO" + }, + "\\\"\",\n \"export IMAGE_TAG=\\\"", + { + "Ref": "IMAGEAMDXLATAG" + }, + "\\\"\",\n \"export BASE_IMAGE_TAG=\\\"", + { + "Ref": "BASEIMAGEAMDXLATAG" + }, + "\\\"\",\n \"cd app\",\n \"chmod +x ./build-assets.sh && ./build-assets.sh\"\n ]\n }\n },\n \"artifacts\": {\n \"files\": [\n \"imageDetail.json\"\n ]\n }\n}" + ] + ] + } + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_codebuild.CfnProject", + "version": "2.173.4" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_codebuild.Project", + "version": "2.173.4" + } + }, + "AssetsImageCpuArmBuild": { + "id": "AssetsImageCpuArmBuild", + "path": "flux-oci-image-inference-cdk/AssetsImageCpuArmBuild", + "children": { + "Resource": { + "id": "Resource", + "path": "flux-oci-image-inference-cdk/AssetsImageCpuArmBuild/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::CodeBuild::Project", + "aws:cdk:cloudformation:props": { + "artifacts": { + "type": "NO_ARTIFACTS" + }, + "cache": { + "type": "LOCAL", + "modes": [ + "LOCAL_DOCKER_LAYER_CACHE", + "LOCAL_CUSTOM_CACHE" + ] + }, + "encryptionKey": { + "Fn::GetAtt": [ + "BuildBasePipelineArtifactsBucketEncryptionKey04467E09", + "Arn" + ] + }, + "environment": { + "type": "ARM_CONTAINER", + "image": "aws/codebuild/amazonlinux2-aarch64-standard:2.0", + "imagePullCredentialsType": "CODEBUILD", + "privilegedMode": true, + "computeType": "BUILD_GENERAL1_LARGE" + }, + "serviceRole": { + "Fn::GetAtt": [ + "BaseCodeBuildDeployRole2A53BD0D", + "Arn" + ] + }, + "source": { + "type": "NO_SOURCE", + "buildSpec": { + "Fn::Join": [ + "", + [ + "{\n \"version\": \"0.2\",\n \"env\": {\n \"exported-variables\": [\n \"AWS_ACCOUNT_ID\",\n \"AWS_REGION\",\n \"BASE_REPO\",\n \"IMAGE_ARM_CPU_TAG\",\n \"BASE_IMAGE_ARM_CPU_TAG\"\n ]\n },\n \"phases\": {\n \"build\": {\n \"commands\": [\n \"export AWS_ACCOUNT_ID=\\\"133573815653\\\"\",\n \"export AWS_REGION=\\\"us-west-2\\\"\",\n \"export BASE_REPO=\\\"", + { + "Ref": "BASEREPO" + }, + "\\\"\",\n \"export IMAGE_TAG=\\\"", + { + "Ref": "IMAGEARMCPUTAG" + }, + "\\\"\",\n \"export BASE_IMAGE_TAG=\\\"", + { + "Ref": "BASEIMAGEARMCPUTAG" + }, + "\\\"\",\n \"cd app\",\n \"chmod +x ./build-assets.sh && ./build-assets.sh\"\n ]\n }\n },\n \"artifacts\": {\n \"files\": [\n \"imageDetail.json\"\n ]\n }\n}" + ] + ] + } + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_codebuild.CfnProject", + "version": "2.173.4" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_codebuild.Project", + "version": "2.173.4" + } + }, + "AssetsImageCudAmdBuild": { + "id": "AssetsImageCudAmdBuild", + "path": "flux-oci-image-inference-cdk/AssetsImageCudAmdBuild", + "children": { + "Resource": { + "id": "Resource", + "path": "flux-oci-image-inference-cdk/AssetsImageCudAmdBuild/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::CodeBuild::Project", + "aws:cdk:cloudformation:props": { + "artifacts": { + "type": "NO_ARTIFACTS" + }, + "cache": { + "type": "LOCAL", + "modes": [ + "LOCAL_DOCKER_LAYER_CACHE", + "LOCAL_CUSTOM_CACHE" + ] + }, + "encryptionKey": { + "Fn::GetAtt": [ + "BuildBasePipelineArtifactsBucketEncryptionKey04467E09", + "Arn" + ] + }, + "environment": { + "type": "LINUX_CONTAINER", + "image": "aws/codebuild/amazonlinux2-x86_64-standard:3.0", + "imagePullCredentialsType": "CODEBUILD", + "privilegedMode": true, + "computeType": "BUILD_GENERAL1_SMALL" + }, + "serviceRole": { + "Fn::GetAtt": [ + "BaseCodeBuildDeployRole2A53BD0D", + "Arn" + ] + }, + "source": { + "type": "NO_SOURCE", + "buildSpec": { + "Fn::Join": [ + "", + [ + "{\n \"version\": \"0.2\",\n \"env\": {\n \"exported-variables\": [\n \"AWS_ACCOUNT_ID\",\n \"AWS_REGION\",\n \"BASE_REPO\",\n \"IMAGE_AMD_CUD_TAG\",\n \"BASE_IMAGE_AMD_CUD_TAG\"\n ]\n },\n \"phases\": {\n \"build\": {\n \"commands\": [\n \"export AWS_ACCOUNT_ID=\\\"133573815653\\\"\",\n \"export AWS_REGION=\\\"us-west-2\\\"\",\n \"export BASE_REPO=\\\"", + { + "Ref": "BASEREPO" + }, + "\\\"\",\n \"export IMAGE_TAG=\\\"", + { + "Ref": "IMAGEAMDCUDTAG" + }, + "\\\"\",\n \"export BASE_IMAGE_TAG=\\\"", + { + "Ref": "BASEIMAGEAMDCUDTAG" + }, + "\\\"\",\n \"cd app\",\n \"chmod +x ./build-assets.sh && ./build-assets.sh\"\n ]\n }\n },\n \"artifacts\": {\n \"files\": [\n \"imageDetail.json\"\n ]\n }\n}" + ] + ] + } + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_codebuild.CfnProject", + "version": "2.173.4" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_codebuild.Project", + "version": "2.173.4" + } + }, + "BuildBasePipeline": { + "id": "BuildBasePipeline", + "path": "flux-oci-image-inference-cdk/BuildBasePipeline", + "children": { + "ArtifactsBucketEncryptionKey": { + "id": "ArtifactsBucketEncryptionKey", + "path": "flux-oci-image-inference-cdk/BuildBasePipeline/ArtifactsBucketEncryptionKey", + "children": { + "Resource": { + "id": "Resource", + "path": "flux-oci-image-inference-cdk/BuildBasePipeline/ArtifactsBucketEncryptionKey/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::KMS::Key", + "aws:cdk:cloudformation:props": { + "keyPolicy": { + "Statement": [ + { + "Action": "kms:*", + "Effect": "Allow", + "Principal": { + "AWS": { + "Fn::Join": [ + "", + [ + "arn:", + { + "Ref": "AWS::Partition" + }, + ":iam::133573815653:root" + ] + ] + } + }, + "Resource": "*" + } + ], + "Version": "2012-10-17" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_kms.CfnKey", + "version": "2.173.4" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_kms.Key", + "version": "2.173.4" + } + }, + "ArtifactsBucketEncryptionKeyAlias": { + "id": "ArtifactsBucketEncryptionKeyAlias", + "path": "flux-oci-image-inference-cdk/BuildBasePipeline/ArtifactsBucketEncryptionKeyAlias", + "children": { + "Resource": { + "id": "Resource", + "path": "flux-oci-image-inference-cdk/BuildBasePipeline/ArtifactsBucketEncryptionKeyAlias/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::KMS::Alias", + "aws:cdk:cloudformation:props": { + "aliasName": "alias/codepipeline-fluxociimageinferencecdkbuildbasepipeline01a0da38", + "targetKeyId": { + "Fn::GetAtt": [ + "BuildBasePipelineArtifactsBucketEncryptionKey04467E09", + "Arn" + ] + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_kms.CfnAlias", + "version": "2.173.4" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_kms.Alias", + "version": "2.173.4" + } + }, + "ArtifactsBucket": { + "id": "ArtifactsBucket", + "path": "flux-oci-image-inference-cdk/BuildBasePipeline/ArtifactsBucket", + "children": { + "Resource": { + "id": "Resource", + "path": "flux-oci-image-inference-cdk/BuildBasePipeline/ArtifactsBucket/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::S3::Bucket", + "aws:cdk:cloudformation:props": { + "bucketEncryption": { + "serverSideEncryptionConfiguration": [ + { + "serverSideEncryptionByDefault": { + "sseAlgorithm": "aws:kms", + "kmsMasterKeyId": { + "Fn::GetAtt": [ + "BuildBasePipelineArtifactsBucketEncryptionKey04467E09", + "Arn" + ] + } + } + } + ] + }, + "publicAccessBlockConfiguration": { + "blockPublicAcls": true, + "blockPublicPolicy": true, + "ignorePublicAcls": true, + "restrictPublicBuckets": true + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_s3.CfnBucket", + "version": "2.173.4" + } + }, + "Policy": { + "id": "Policy", + "path": "flux-oci-image-inference-cdk/BuildBasePipeline/ArtifactsBucket/Policy", + "children": { + "Resource": { + "id": "Resource", + "path": "flux-oci-image-inference-cdk/BuildBasePipeline/ArtifactsBucket/Policy/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::S3::BucketPolicy", + "aws:cdk:cloudformation:props": { + "bucket": { + "Ref": "BuildBasePipelineArtifactsBucket51786A86" + }, + "policyDocument": { + "Statement": [ + { + "Action": "s3:*", + "Condition": { + "Bool": { + "aws:SecureTransport": "false" + } + }, + "Effect": "Deny", + "Principal": { + "AWS": "*" + }, + "Resource": [ + { + "Fn::GetAtt": [ + "BuildBasePipelineArtifactsBucket51786A86", + "Arn" + ] + }, + { + "Fn::Join": [ + "", + [ + { + "Fn::GetAtt": [ + "BuildBasePipelineArtifactsBucket51786A86", + "Arn" + ] + }, + "/*" + ] + ] + } + ] + } + ], + "Version": "2012-10-17" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_s3.CfnBucketPolicy", + "version": "2.173.4" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_s3.BucketPolicy", + "version": "2.173.4" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_s3.Bucket", + "version": "2.173.4" + } + }, + "Role": { + "id": "Role", + "path": "flux-oci-image-inference-cdk/BuildBasePipeline/Role", + "children": { + "ImportRole": { + "id": "ImportRole", + "path": "flux-oci-image-inference-cdk/BuildBasePipeline/Role/ImportRole", + "constructInfo": { + "fqn": "aws-cdk-lib.Resource", + "version": "2.173.4" + } + }, + "Resource": { + "id": "Resource", + "path": "flux-oci-image-inference-cdk/BuildBasePipeline/Role/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::IAM::Role", + "aws:cdk:cloudformation:props": { + "assumeRolePolicyDocument": { + "Statement": [ + { + "Action": "sts:AssumeRole", + "Effect": "Allow", + "Principal": { + "Service": "codepipeline.amazonaws.com" + } + } + ], + "Version": "2012-10-17" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_iam.CfnRole", + "version": "2.173.4" + } + }, + "DefaultPolicy": { + "id": "DefaultPolicy", + "path": "flux-oci-image-inference-cdk/BuildBasePipeline/Role/DefaultPolicy", + "children": { + "Resource": { + "id": "Resource", + "path": "flux-oci-image-inference-cdk/BuildBasePipeline/Role/DefaultPolicy/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::IAM::Policy", + "aws:cdk:cloudformation:props": { + "policyDocument": { + "Statement": [ + { + "Action": [ + "s3:GetObject*", + "s3:GetBucket*", + "s3:List*", + "s3:DeleteObject*", + "s3:PutObject", + "s3:PutObjectLegalHold", + "s3:PutObjectRetention", + "s3:PutObjectTagging", + "s3:PutObjectVersionTagging", + "s3:Abort*" + ], + "Effect": "Allow", + "Resource": [ + { + "Fn::GetAtt": [ + "BuildBasePipelineArtifactsBucket51786A86", + "Arn" + ] + }, + { + "Fn::Join": [ + "", + [ + { + "Fn::GetAtt": [ + "BuildBasePipelineArtifactsBucket51786A86", + "Arn" + ] + }, + "/*" + ] + ] + } + ] + }, + { + "Action": [ + "kms:Decrypt", + "kms:DescribeKey", + "kms:Encrypt", + "kms:ReEncrypt*", + "kms:GenerateDataKey*" + ], + "Effect": "Allow", + "Resource": { + "Fn::GetAtt": [ + "BuildBasePipelineArtifactsBucketEncryptionKey04467E09", + "Arn" + ] + } + }, + { + "Action": "sts:AssumeRole", + "Effect": "Allow", + "Resource": { + "Fn::GetAtt": [ + "BuildBasePipelineImageBuildAssetsImageXlaAmdBuildCodePipelineActionRole7C093488", + "Arn" + ] + } + }, + { + "Action": "sts:AssumeRole", + "Effect": "Allow", + "Resource": { + "Fn::GetAtt": [ + "BuildBasePipelineImageBuildAssetsImageCudAmdBuildCodePipelineActionRole7F47990C", + "Arn" + ] + } + }, + { + "Action": "sts:AssumeRole", + "Effect": "Allow", + "Resource": { + "Fn::GetAtt": [ + "BuildBasePipelineImageBuildAssetsImageCpuArmBuildCodePipelineActionRole67BCBC26", + "Arn" + ] + } + }, + { + "Action": "sts:AssumeRole", + "Effect": "Allow", + "Resource": { + "Fn::GetAtt": [ + "BuildBasePipelineImageBuildBaseImageAmdXlaBuildCodePipelineActionRoleD9124FCE", + "Arn" + ] + } + }, + { + "Action": "sts:AssumeRole", + "Effect": "Allow", + "Resource": { + "Fn::GetAtt": [ + "BuildBasePipelineImageBuildBaseImageArmCpuBuildCodePipelineActionRole4DF7F5DE", + "Arn" + ] + } + }, + { + "Action": "sts:AssumeRole", + "Effect": "Allow", + "Resource": { + "Fn::GetAtt": [ + "BuildBasePipelineImageBuildBaseImageAmdCudBuildCodePipelineActionRoleA29F5F5F", + "Arn" + ] + } + } + ], + "Version": "2012-10-17" + }, + "policyName": "BuildBasePipelineRoleDefaultPolicy7CA9EFF0", + "roles": [ + { + "Ref": "BuildBasePipelineRole8C8F77AD" + } + ] + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_iam.CfnPolicy", + "version": "2.173.4" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_iam.Policy", + "version": "2.173.4" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_iam.Role", + "version": "2.173.4" + } + }, + "Resource": { + "id": "Resource", + "path": "flux-oci-image-inference-cdk/BuildBasePipeline/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::CodePipeline::Pipeline", + "aws:cdk:cloudformation:props": { + "artifactStore": { + "type": "S3", + "location": { + "Ref": "BuildBasePipelineArtifactsBucket51786A86" + }, + "encryptionKey": { + "type": "KMS", + "id": { + "Fn::GetAtt": [ + "BuildBasePipelineArtifactsBucketEncryptionKey04467E09", + "Arn" + ] + } + } + }, + "roleArn": { + "Fn::GetAtt": [ + "BuildBasePipelineRole8C8F77AD", + "Arn" + ] + }, + "stages": [ + { + "name": "Source", + "actions": [ + { + "name": "GitHub_Source", + "outputArtifacts": [ + { + "name": "Artifact_Source_GitHub_Source" + } + ], + "actionTypeId": { + "category": "Source", + "version": "1", + "owner": "ThirdParty", + "provider": "GitHub" + }, + "configuration": { + "Owner": { + "Ref": "GITHUBUSER" + }, + "Repo": { + "Ref": "GITHUBREPO" + }, + "Branch": { + "Ref": "GITHUBBRANCH" + }, + "OAuthToken": "{{resolve:secretsmanager:githubtoken:SecretString:token::}}", + "PollForSourceChanges": false + }, + "runOrder": 1 + } + ] + }, + { + "name": "ImageBuild", + "actions": [ + { + "name": "AssetsImageXlaAmdBuild", + "inputArtifacts": [ + { + "name": "Artifact_Source_GitHub_Source" + } + ], + "actionTypeId": { + "category": "Build", + "version": "1", + "owner": "AWS", + "provider": "CodeBuild" + }, + "configuration": { + "ProjectName": { + "Ref": "AssetsImageXlaAmdBuild4E3D098F" + } + }, + "runOrder": 1, + "roleArn": { + "Fn::GetAtt": [ + "BuildBasePipelineImageBuildAssetsImageXlaAmdBuildCodePipelineActionRole7C093488", + "Arn" + ] + } + }, + { + "name": "AssetsImageCudAmdBuild", + "inputArtifacts": [ + { + "name": "Artifact_Source_GitHub_Source" + } + ], + "actionTypeId": { + "category": "Build", + "version": "1", + "owner": "AWS", + "provider": "CodeBuild" + }, + "configuration": { + "ProjectName": { + "Ref": "AssetsImageCudAmdBuild4322D558" + } + }, + "runOrder": 1, + "roleArn": { + "Fn::GetAtt": [ + "BuildBasePipelineImageBuildAssetsImageCudAmdBuildCodePipelineActionRole7F47990C", + "Arn" + ] + } + }, + { + "name": "AssetsImageCpuArmBuild", + "inputArtifacts": [ + { + "name": "Artifact_Source_GitHub_Source" + } + ], + "actionTypeId": { + "category": "Build", + "version": "1", + "owner": "AWS", + "provider": "CodeBuild" + }, + "configuration": { + "ProjectName": { + "Ref": "AssetsImageCpuArmBuildBC43C501" + } + }, + "runOrder": 1, + "roleArn": { + "Fn::GetAtt": [ + "BuildBasePipelineImageBuildAssetsImageCpuArmBuildCodePipelineActionRole67BCBC26", + "Arn" + ] + } + }, + { + "name": "BaseImageAmdXlaBuild", + "inputArtifacts": [ + { + "name": "Artifact_Source_GitHub_Source" + } + ], + "actionTypeId": { + "category": "Build", + "version": "1", + "owner": "AWS", + "provider": "CodeBuild" + }, + "configuration": { + "ProjectName": { + "Ref": "ImageXlaAmdBuild7511085C" + } + }, + "runOrder": 2, + "roleArn": { + "Fn::GetAtt": [ + "BuildBasePipelineImageBuildBaseImageAmdXlaBuildCodePipelineActionRoleD9124FCE", + "Arn" + ] + } + }, + { + "name": "BaseImageArmCpuBuild", + "inputArtifacts": [ + { + "name": "Artifact_Source_GitHub_Source" + } + ], + "actionTypeId": { + "category": "Build", + "version": "1", + "owner": "AWS", + "provider": "CodeBuild" + }, + "configuration": { + "ProjectName": { + "Ref": "ImageCpuArmBuild4791F7AA" + } + }, + "runOrder": 2, + "roleArn": { + "Fn::GetAtt": [ + "BuildBasePipelineImageBuildBaseImageArmCpuBuildCodePipelineActionRole4DF7F5DE", + "Arn" + ] + } + }, + { + "name": "BaseImageAmdCudBuild", + "inputArtifacts": [ + { + "name": "Artifact_Source_GitHub_Source" + } + ], + "actionTypeId": { + "category": "Build", + "version": "1", + "owner": "AWS", + "provider": "CodeBuild" + }, + "configuration": { + "ProjectName": { + "Ref": "ImageCudAmdBuild23EA25C8" + } + }, + "runOrder": 2, + "roleArn": { + "Fn::GetAtt": [ + "BuildBasePipelineImageBuildBaseImageAmdCudBuildCodePipelineActionRoleA29F5F5F", + "Arn" + ] + } + } + ] + } + ] + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_codepipeline.CfnPipeline", + "version": "2.173.4" + } + }, + "Source": { + "id": "Source", + "path": "flux-oci-image-inference-cdk/BuildBasePipeline/Source", + "children": { + "GitHub_Source": { + "id": "GitHub_Source", + "path": "flux-oci-image-inference-cdk/BuildBasePipeline/Source/GitHub_Source", + "children": { + "WebhookResource": { + "id": "WebhookResource", + "path": "flux-oci-image-inference-cdk/BuildBasePipeline/Source/GitHub_Source/WebhookResource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::CodePipeline::Webhook", + "aws:cdk:cloudformation:props": { + "authentication": "GITHUB_HMAC", + "authenticationConfiguration": { + "secretToken": "{{resolve:secretsmanager:githubtoken:SecretString:token::}}" + }, + "filters": [ + { + "jsonPath": "$.ref", + "matchEquals": "refs/heads/{Branch}" + } + ], + "registerWithThirdParty": true, + "targetAction": "GitHub_Source", + "targetPipeline": { + "Ref": "BuildBasePipelineE93F0563" + }, + "targetPipelineVersion": 1 + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_codepipeline.CfnWebhook", + "version": "2.173.4" + } + } + }, + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.4.2" + } + } + }, + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.4.2" + } + }, + "ImageBuild": { + "id": "ImageBuild", + "path": "flux-oci-image-inference-cdk/BuildBasePipeline/ImageBuild", + "children": { + "AssetsImageXlaAmdBuild": { + "id": "AssetsImageXlaAmdBuild", + "path": "flux-oci-image-inference-cdk/BuildBasePipeline/ImageBuild/AssetsImageXlaAmdBuild", + "children": { + "CodePipelineActionRole": { + "id": "CodePipelineActionRole", + "path": "flux-oci-image-inference-cdk/BuildBasePipeline/ImageBuild/AssetsImageXlaAmdBuild/CodePipelineActionRole", + "children": { + "ImportCodePipelineActionRole": { + "id": "ImportCodePipelineActionRole", + "path": "flux-oci-image-inference-cdk/BuildBasePipeline/ImageBuild/AssetsImageXlaAmdBuild/CodePipelineActionRole/ImportCodePipelineActionRole", + "constructInfo": { + "fqn": "aws-cdk-lib.Resource", + "version": "2.173.4" + } + }, + "Resource": { + "id": "Resource", + "path": "flux-oci-image-inference-cdk/BuildBasePipeline/ImageBuild/AssetsImageXlaAmdBuild/CodePipelineActionRole/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::IAM::Role", + "aws:cdk:cloudformation:props": { + "assumeRolePolicyDocument": { + "Statement": [ + { + "Action": "sts:AssumeRole", + "Effect": "Allow", + "Principal": { + "AWS": { + "Fn::Join": [ + "", + [ + "arn:", + { + "Ref": "AWS::Partition" + }, + ":iam::133573815653:root" + ] + ] + } + } + } + ], + "Version": "2012-10-17" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_iam.CfnRole", + "version": "2.173.4" + } + }, + "DefaultPolicy": { + "id": "DefaultPolicy", + "path": "flux-oci-image-inference-cdk/BuildBasePipeline/ImageBuild/AssetsImageXlaAmdBuild/CodePipelineActionRole/DefaultPolicy", + "children": { + "Resource": { + "id": "Resource", + "path": "flux-oci-image-inference-cdk/BuildBasePipeline/ImageBuild/AssetsImageXlaAmdBuild/CodePipelineActionRole/DefaultPolicy/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::IAM::Policy", + "aws:cdk:cloudformation:props": { + "policyDocument": { + "Statement": [ + { + "Action": [ + "codebuild:BatchGetBuilds", + "codebuild:StartBuild", + "codebuild:StopBuild" + ], + "Effect": "Allow", + "Resource": { + "Fn::GetAtt": [ + "AssetsImageXlaAmdBuild4E3D098F", + "Arn" + ] + } + } + ], + "Version": "2012-10-17" + }, + "policyName": "BuildBasePipelineImageBuildAssetsImageXlaAmdBuildCodePipelineActionRoleDefaultPolicyB3BE9D03", + "roles": [ + { + "Ref": "BuildBasePipelineImageBuildAssetsImageXlaAmdBuildCodePipelineActionRole7C093488" + } + ] + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_iam.CfnPolicy", + "version": "2.173.4" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_iam.Policy", + "version": "2.173.4" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_iam.Role", + "version": "2.173.4" + } + } + }, + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.4.2" + } + }, + "AssetsImageCudAmdBuild": { + "id": "AssetsImageCudAmdBuild", + "path": "flux-oci-image-inference-cdk/BuildBasePipeline/ImageBuild/AssetsImageCudAmdBuild", + "children": { + "CodePipelineActionRole": { + "id": "CodePipelineActionRole", + "path": "flux-oci-image-inference-cdk/BuildBasePipeline/ImageBuild/AssetsImageCudAmdBuild/CodePipelineActionRole", + "children": { + "ImportCodePipelineActionRole": { + "id": "ImportCodePipelineActionRole", + "path": "flux-oci-image-inference-cdk/BuildBasePipeline/ImageBuild/AssetsImageCudAmdBuild/CodePipelineActionRole/ImportCodePipelineActionRole", + "constructInfo": { + "fqn": "aws-cdk-lib.Resource", + "version": "2.173.4" + } + }, + "Resource": { + "id": "Resource", + "path": "flux-oci-image-inference-cdk/BuildBasePipeline/ImageBuild/AssetsImageCudAmdBuild/CodePipelineActionRole/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::IAM::Role", + "aws:cdk:cloudformation:props": { + "assumeRolePolicyDocument": { + "Statement": [ + { + "Action": "sts:AssumeRole", + "Effect": "Allow", + "Principal": { + "AWS": { + "Fn::Join": [ + "", + [ + "arn:", + { + "Ref": "AWS::Partition" + }, + ":iam::133573815653:root" + ] + ] + } + } + } + ], + "Version": "2012-10-17" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_iam.CfnRole", + "version": "2.173.4" + } + }, + "DefaultPolicy": { + "id": "DefaultPolicy", + "path": "flux-oci-image-inference-cdk/BuildBasePipeline/ImageBuild/AssetsImageCudAmdBuild/CodePipelineActionRole/DefaultPolicy", + "children": { + "Resource": { + "id": "Resource", + "path": "flux-oci-image-inference-cdk/BuildBasePipeline/ImageBuild/AssetsImageCudAmdBuild/CodePipelineActionRole/DefaultPolicy/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::IAM::Policy", + "aws:cdk:cloudformation:props": { + "policyDocument": { + "Statement": [ + { + "Action": [ + "codebuild:BatchGetBuilds", + "codebuild:StartBuild", + "codebuild:StopBuild" + ], + "Effect": "Allow", + "Resource": { + "Fn::GetAtt": [ + "AssetsImageCudAmdBuild4322D558", + "Arn" + ] + } + } + ], + "Version": "2012-10-17" + }, + "policyName": "BuildBasePipelineImageBuildAssetsImageCudAmdBuildCodePipelineActionRoleDefaultPolicy44AAF344", + "roles": [ + { + "Ref": "BuildBasePipelineImageBuildAssetsImageCudAmdBuildCodePipelineActionRole7F47990C" + } + ] + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_iam.CfnPolicy", + "version": "2.173.4" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_iam.Policy", + "version": "2.173.4" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_iam.Role", + "version": "2.173.4" + } + } + }, + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.4.2" + } + }, + "AssetsImageCpuArmBuild": { + "id": "AssetsImageCpuArmBuild", + "path": "flux-oci-image-inference-cdk/BuildBasePipeline/ImageBuild/AssetsImageCpuArmBuild", + "children": { + "CodePipelineActionRole": { + "id": "CodePipelineActionRole", + "path": "flux-oci-image-inference-cdk/BuildBasePipeline/ImageBuild/AssetsImageCpuArmBuild/CodePipelineActionRole", + "children": { + "ImportCodePipelineActionRole": { + "id": "ImportCodePipelineActionRole", + "path": "flux-oci-image-inference-cdk/BuildBasePipeline/ImageBuild/AssetsImageCpuArmBuild/CodePipelineActionRole/ImportCodePipelineActionRole", + "constructInfo": { + "fqn": "aws-cdk-lib.Resource", + "version": "2.173.4" + } + }, + "Resource": { + "id": "Resource", + "path": "flux-oci-image-inference-cdk/BuildBasePipeline/ImageBuild/AssetsImageCpuArmBuild/CodePipelineActionRole/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::IAM::Role", + "aws:cdk:cloudformation:props": { + "assumeRolePolicyDocument": { + "Statement": [ + { + "Action": "sts:AssumeRole", + "Effect": "Allow", + "Principal": { + "AWS": { + "Fn::Join": [ + "", + [ + "arn:", + { + "Ref": "AWS::Partition" + }, + ":iam::133573815653:root" + ] + ] + } + } + } + ], + "Version": "2012-10-17" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_iam.CfnRole", + "version": "2.173.4" + } + }, + "DefaultPolicy": { + "id": "DefaultPolicy", + "path": "flux-oci-image-inference-cdk/BuildBasePipeline/ImageBuild/AssetsImageCpuArmBuild/CodePipelineActionRole/DefaultPolicy", + "children": { + "Resource": { + "id": "Resource", + "path": "flux-oci-image-inference-cdk/BuildBasePipeline/ImageBuild/AssetsImageCpuArmBuild/CodePipelineActionRole/DefaultPolicy/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::IAM::Policy", + "aws:cdk:cloudformation:props": { + "policyDocument": { + "Statement": [ + { + "Action": [ + "codebuild:BatchGetBuilds", + "codebuild:StartBuild", + "codebuild:StopBuild" + ], + "Effect": "Allow", + "Resource": { + "Fn::GetAtt": [ + "AssetsImageCpuArmBuildBC43C501", + "Arn" + ] + } + } + ], + "Version": "2012-10-17" + }, + "policyName": "BuildBasePipelineImageBuildAssetsImageCpuArmBuildCodePipelineActionRoleDefaultPolicy723A3220", + "roles": [ + { + "Ref": "BuildBasePipelineImageBuildAssetsImageCpuArmBuildCodePipelineActionRole67BCBC26" + } + ] + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_iam.CfnPolicy", + "version": "2.173.4" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_iam.Policy", + "version": "2.173.4" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_iam.Role", + "version": "2.173.4" + } + } + }, + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.4.2" + } + }, + "BaseImageAmdXlaBuild": { + "id": "BaseImageAmdXlaBuild", + "path": "flux-oci-image-inference-cdk/BuildBasePipeline/ImageBuild/BaseImageAmdXlaBuild", + "children": { + "CodePipelineActionRole": { + "id": "CodePipelineActionRole", + "path": "flux-oci-image-inference-cdk/BuildBasePipeline/ImageBuild/BaseImageAmdXlaBuild/CodePipelineActionRole", + "children": { + "ImportCodePipelineActionRole": { + "id": "ImportCodePipelineActionRole", + "path": "flux-oci-image-inference-cdk/BuildBasePipeline/ImageBuild/BaseImageAmdXlaBuild/CodePipelineActionRole/ImportCodePipelineActionRole", + "constructInfo": { + "fqn": "aws-cdk-lib.Resource", + "version": "2.173.4" + } + }, + "Resource": { + "id": "Resource", + "path": "flux-oci-image-inference-cdk/BuildBasePipeline/ImageBuild/BaseImageAmdXlaBuild/CodePipelineActionRole/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::IAM::Role", + "aws:cdk:cloudformation:props": { + "assumeRolePolicyDocument": { + "Statement": [ + { + "Action": "sts:AssumeRole", + "Effect": "Allow", + "Principal": { + "AWS": { + "Fn::Join": [ + "", + [ + "arn:", + { + "Ref": "AWS::Partition" + }, + ":iam::133573815653:root" + ] + ] + } + } + } + ], + "Version": "2012-10-17" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_iam.CfnRole", + "version": "2.173.4" + } + }, + "DefaultPolicy": { + "id": "DefaultPolicy", + "path": "flux-oci-image-inference-cdk/BuildBasePipeline/ImageBuild/BaseImageAmdXlaBuild/CodePipelineActionRole/DefaultPolicy", + "children": { + "Resource": { + "id": "Resource", + "path": "flux-oci-image-inference-cdk/BuildBasePipeline/ImageBuild/BaseImageAmdXlaBuild/CodePipelineActionRole/DefaultPolicy/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::IAM::Policy", + "aws:cdk:cloudformation:props": { + "policyDocument": { + "Statement": [ + { + "Action": [ + "codebuild:BatchGetBuilds", + "codebuild:StartBuild", + "codebuild:StopBuild" + ], + "Effect": "Allow", + "Resource": { + "Fn::GetAtt": [ + "ImageXlaAmdBuild7511085C", + "Arn" + ] + } + } + ], + "Version": "2012-10-17" + }, + "policyName": "BuildBasePipelineImageBuildBaseImageAmdXlaBuildCodePipelineActionRoleDefaultPolicy1C329D4F", + "roles": [ + { + "Ref": "BuildBasePipelineImageBuildBaseImageAmdXlaBuildCodePipelineActionRoleD9124FCE" + } + ] + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_iam.CfnPolicy", + "version": "2.173.4" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_iam.Policy", + "version": "2.173.4" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_iam.Role", + "version": "2.173.4" + } + } + }, + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.4.2" + } + }, + "BaseImageArmCpuBuild": { + "id": "BaseImageArmCpuBuild", + "path": "flux-oci-image-inference-cdk/BuildBasePipeline/ImageBuild/BaseImageArmCpuBuild", + "children": { + "CodePipelineActionRole": { + "id": "CodePipelineActionRole", + "path": "flux-oci-image-inference-cdk/BuildBasePipeline/ImageBuild/BaseImageArmCpuBuild/CodePipelineActionRole", + "children": { + "ImportCodePipelineActionRole": { + "id": "ImportCodePipelineActionRole", + "path": "flux-oci-image-inference-cdk/BuildBasePipeline/ImageBuild/BaseImageArmCpuBuild/CodePipelineActionRole/ImportCodePipelineActionRole", + "constructInfo": { + "fqn": "aws-cdk-lib.Resource", + "version": "2.173.4" + } + }, + "Resource": { + "id": "Resource", + "path": "flux-oci-image-inference-cdk/BuildBasePipeline/ImageBuild/BaseImageArmCpuBuild/CodePipelineActionRole/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::IAM::Role", + "aws:cdk:cloudformation:props": { + "assumeRolePolicyDocument": { + "Statement": [ + { + "Action": "sts:AssumeRole", + "Effect": "Allow", + "Principal": { + "AWS": { + "Fn::Join": [ + "", + [ + "arn:", + { + "Ref": "AWS::Partition" + }, + ":iam::133573815653:root" + ] + ] + } + } + } + ], + "Version": "2012-10-17" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_iam.CfnRole", + "version": "2.173.4" + } + }, + "DefaultPolicy": { + "id": "DefaultPolicy", + "path": "flux-oci-image-inference-cdk/BuildBasePipeline/ImageBuild/BaseImageArmCpuBuild/CodePipelineActionRole/DefaultPolicy", + "children": { + "Resource": { + "id": "Resource", + "path": "flux-oci-image-inference-cdk/BuildBasePipeline/ImageBuild/BaseImageArmCpuBuild/CodePipelineActionRole/DefaultPolicy/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::IAM::Policy", + "aws:cdk:cloudformation:props": { + "policyDocument": { + "Statement": [ + { + "Action": [ + "codebuild:BatchGetBuilds", + "codebuild:StartBuild", + "codebuild:StopBuild" + ], + "Effect": "Allow", + "Resource": { + "Fn::GetAtt": [ + "ImageCpuArmBuild4791F7AA", + "Arn" + ] + } + } + ], + "Version": "2012-10-17" + }, + "policyName": "BuildBasePipelineImageBuildBaseImageArmCpuBuildCodePipelineActionRoleDefaultPolicy31713CB8", + "roles": [ + { + "Ref": "BuildBasePipelineImageBuildBaseImageArmCpuBuildCodePipelineActionRole4DF7F5DE" + } + ] + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_iam.CfnPolicy", + "version": "2.173.4" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_iam.Policy", + "version": "2.173.4" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_iam.Role", + "version": "2.173.4" + } + } + }, + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.4.2" + } + }, + "BaseImageAmdCudBuild": { + "id": "BaseImageAmdCudBuild", + "path": "flux-oci-image-inference-cdk/BuildBasePipeline/ImageBuild/BaseImageAmdCudBuild", + "children": { + "CodePipelineActionRole": { + "id": "CodePipelineActionRole", + "path": "flux-oci-image-inference-cdk/BuildBasePipeline/ImageBuild/BaseImageAmdCudBuild/CodePipelineActionRole", + "children": { + "ImportCodePipelineActionRole": { + "id": "ImportCodePipelineActionRole", + "path": "flux-oci-image-inference-cdk/BuildBasePipeline/ImageBuild/BaseImageAmdCudBuild/CodePipelineActionRole/ImportCodePipelineActionRole", + "constructInfo": { + "fqn": "aws-cdk-lib.Resource", + "version": "2.173.4" + } + }, + "Resource": { + "id": "Resource", + "path": "flux-oci-image-inference-cdk/BuildBasePipeline/ImageBuild/BaseImageAmdCudBuild/CodePipelineActionRole/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::IAM::Role", + "aws:cdk:cloudformation:props": { + "assumeRolePolicyDocument": { + "Statement": [ + { + "Action": "sts:AssumeRole", + "Effect": "Allow", + "Principal": { + "AWS": { + "Fn::Join": [ + "", + [ + "arn:", + { + "Ref": "AWS::Partition" + }, + ":iam::133573815653:root" + ] + ] + } + } + } + ], + "Version": "2012-10-17" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_iam.CfnRole", + "version": "2.173.4" + } + }, + "DefaultPolicy": { + "id": "DefaultPolicy", + "path": "flux-oci-image-inference-cdk/BuildBasePipeline/ImageBuild/BaseImageAmdCudBuild/CodePipelineActionRole/DefaultPolicy", + "children": { + "Resource": { + "id": "Resource", + "path": "flux-oci-image-inference-cdk/BuildBasePipeline/ImageBuild/BaseImageAmdCudBuild/CodePipelineActionRole/DefaultPolicy/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::IAM::Policy", + "aws:cdk:cloudformation:props": { + "policyDocument": { + "Statement": [ + { + "Action": [ + "codebuild:BatchGetBuilds", + "codebuild:StartBuild", + "codebuild:StopBuild" + ], + "Effect": "Allow", + "Resource": { + "Fn::GetAtt": [ + "ImageCudAmdBuild23EA25C8", + "Arn" + ] + } + } + ], + "Version": "2012-10-17" + }, + "policyName": "BuildBasePipelineImageBuildBaseImageAmdCudBuildCodePipelineActionRoleDefaultPolicy7D964952", + "roles": [ + { + "Ref": "BuildBasePipelineImageBuildBaseImageAmdCudBuildCodePipelineActionRoleA29F5F5F" + } + ] + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_iam.CfnPolicy", + "version": "2.173.4" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_iam.Policy", + "version": "2.173.4" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_iam.Role", + "version": "2.173.4" + } + } + }, + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.4.2" + } + } + }, + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.4.2" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_codepipeline.Pipeline", + "version": "2.173.4" + } + }, + "CDKMetadata": { + "id": "CDKMetadata", + "path": "flux-oci-image-inference-cdk/CDKMetadata", + "children": { + "Default": { + "id": "Default", + "path": "flux-oci-image-inference-cdk/CDKMetadata/Default", + "constructInfo": { + "fqn": "aws-cdk-lib.CfnResource", + "version": "2.173.4" + } + } + }, + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.4.2" + } + }, + "BootstrapVersion": { + "id": "BootstrapVersion", + "path": "flux-oci-image-inference-cdk/BootstrapVersion", + "constructInfo": { + "fqn": "aws-cdk-lib.CfnParameter", + "version": "2.173.4" + } + }, + "CheckBootstrapVersion": { + "id": "CheckBootstrapVersion", + "path": "flux-oci-image-inference-cdk/CheckBootstrapVersion", + "constructInfo": { + "fqn": "aws-cdk-lib.CfnRule", + "version": "2.173.4" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.Stack", + "version": "2.173.4" + } + }, + "Tree": { + "id": "Tree", + "path": "Tree", + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.4.2" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.App", + "version": "2.173.4" + } + } +} \ No newline at end of file diff --git a/flux_serve/oci-image-build/deploy-pipeline.sh b/flux_serve/oci-image-build/deploy-pipeline.sh new file mode 100755 index 0000000..6389271 --- /dev/null +++ b/flux_serve/oci-image-build/deploy-pipeline.sh @@ -0,0 +1,12 @@ +#!/bin/bash +rm -rf cdk.* package* node_modules/ +npm install -g aws-cdk +npm install aws-cdk-lib +npm install ts-node typescript +npm install typescript --save-dev +npx tsc --init +npx tsc +. ~/.bash_profile +cdk bootstrap aws://$AWS_ACCOUNT_ID/$AWS_REGION +npm install +cdk deploy --app "npx ts-node --prefer-ts-exts ./pipeline.ts" --parameters BASEIMAGEAMDXLATAG=$BASE_IMAGE_AMD_XLA_TAG --parameters BASEIMAGEAMDCUDTAG=$BASE_IMAGE_AMD_CUD_TAG --parameters BASEREPO=$BASE_REPO --parameters IMAGEAMDXLATAG=$IMAGE_AMD_XLA_TAG --parameters IMAGEAMDCUDTAG=$IMAGE_AMD_CUD_TAG --parameters GITHUBREPO=$GITHUB_REPO --parameters GITHUBUSER=$GITHUB_USER --parameters GITHUBBRANCH=$GITHUB_BRANCH --parameters GITHUBOAUTHTOKEN=$GITHUB_OAUTH_TOKEN --parameters BASEIMAGEARMCPUTAG=$BASE_IMAGE_ARM_CPU_TAG --parameters IMAGEARMCPUTAG=$IMAGE_ARM_CPU_TAG diff --git a/flux_serve/oci-image-build/package-lock.json b/flux_serve/oci-image-build/package-lock.json new file mode 100644 index 0000000..813ddc3 --- /dev/null +++ b/flux_serve/oci-image-build/package-lock.json @@ -0,0 +1,615 @@ +{ + "name": "oci-image-build", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "dependencies": { + "aws-cdk-lib": "^2.173.4", + "ts-node": "^10.9.2" + }, + "devDependencies": { + "typescript": "^5.7.2" + } + }, + "node_modules/@aws-cdk/asset-awscli-v1": { + "version": "2.2.217", + "resolved": "https://registry.npmjs.org/@aws-cdk/asset-awscli-v1/-/asset-awscli-v1-2.2.217.tgz", + "integrity": "sha512-vqMxZaMO3ILc7OuPGH59KryvGqY1wNx7RYLfxM4aMk6uda5eG/rCo1jGRovB1fXXQCPd9NedicJz3n+DkhxIzw==", + "license": "Apache-2.0" + }, + "node_modules/@aws-cdk/asset-kubectl-v20": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/@aws-cdk/asset-kubectl-v20/-/asset-kubectl-v20-2.1.3.tgz", + "integrity": "sha512-cDG1w3ieM6eOT9mTefRuTypk95+oyD7P5X/wRltwmYxU7nZc3+076YEVS6vrjDKr3ADYbfn0lDKpfB1FBtO9CQ==", + "license": "Apache-2.0" + }, + "node_modules/@aws-cdk/asset-node-proxy-agent-v6": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/@aws-cdk/asset-node-proxy-agent-v6/-/asset-node-proxy-agent-v6-2.1.0.tgz", + "integrity": "sha512-7bY3J8GCVxLupn/kNmpPc5VJz8grx+4RKfnnJiO1LG+uxkZfANZG3RMHhE+qQxxwkyQ9/MfPtTpf748UhR425A==", + "license": "Apache-2.0" + }, + "node_modules/@aws-cdk/cloud-assembly-schema": { + "version": "38.0.1", + "resolved": "https://registry.npmjs.org/@aws-cdk/cloud-assembly-schema/-/cloud-assembly-schema-38.0.1.tgz", + "integrity": "sha512-KvPe+NMWAulfNVwY7jenFhzhuLhLqJ/OPy5jx7wUstbjnYnjRVLpUHPU3yCjXFE0J8cuJVdx95BJ4rOs66Pi9w==", + "bundleDependencies": [ + "jsonschema", + "semver" + ], + "license": "Apache-2.0", + "dependencies": { + "jsonschema": "^1.4.1", + "semver": "^7.6.3" + } + }, + "node_modules/@aws-cdk/cloud-assembly-schema/node_modules/jsonschema": { + "version": "1.4.1", + "inBundle": true, + "license": "MIT", + "engines": { + "node": "*" + } + }, + "node_modules/@aws-cdk/cloud-assembly-schema/node_modules/semver": { + "version": "7.6.3", + "inBundle": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@cspotcode/source-map-support": { + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz", + "integrity": "sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==", + "license": "MIT", + "dependencies": { + "@jridgewell/trace-mapping": "0.3.9" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/@jridgewell/resolve-uri": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", + "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", + "license": "MIT", + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/sourcemap-codec": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.0.tgz", + "integrity": "sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==", + "license": "MIT" + }, + "node_modules/@jridgewell/trace-mapping": { + "version": "0.3.9", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.9.tgz", + "integrity": "sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==", + "license": "MIT", + "dependencies": { + "@jridgewell/resolve-uri": "^3.0.3", + "@jridgewell/sourcemap-codec": "^1.4.10" + } + }, + "node_modules/@tsconfig/node10": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.11.tgz", + "integrity": "sha512-DcRjDCujK/kCk/cUe8Xz8ZSpm8mS3mNNpta+jGCA6USEDfktlNvm1+IuZ9eTcDbNk41BHwpHHeW+N1lKCz4zOw==", + "license": "MIT" + }, + "node_modules/@tsconfig/node12": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/@tsconfig/node12/-/node12-1.0.11.tgz", + "integrity": "sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag==", + "license": "MIT" + }, + "node_modules/@tsconfig/node14": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@tsconfig/node14/-/node14-1.0.3.tgz", + "integrity": "sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow==", + "license": "MIT" + }, + "node_modules/@tsconfig/node16": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@tsconfig/node16/-/node16-1.0.4.tgz", + "integrity": "sha512-vxhUy4J8lyeyinH7Azl1pdd43GJhZH/tP2weN8TntQblOY+A0XbT8DJk1/oCPuOOyg/Ja757rG0CgHcWC8OfMA==", + "license": "MIT" + }, + "node_modules/@types/node": { + "version": "22.10.3", + "resolved": "https://registry.npmjs.org/@types/node/-/node-22.10.3.tgz", + "integrity": "sha512-DifAyw4BkrufCILvD3ucnuN8eydUfc/C1GlyrnI+LK6543w5/L3VeVgf05o3B4fqSXP1dKYLOZsKfutpxPzZrw==", + "license": "MIT", + "peer": true, + "dependencies": { + "undici-types": "~6.20.0" + } + }, + "node_modules/acorn": { + "version": "8.14.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.14.0.tgz", + "integrity": "sha512-cl669nCJTZBsL97OF4kUQm5g5hC2uihk0NxY3WENAC0TYdILVkAyHymAntgxGkl7K+t0cXIrH5siy5S4XkFycA==", + "license": "MIT", + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/acorn-walk": { + "version": "8.3.4", + "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.3.4.tgz", + "integrity": "sha512-ueEepnujpqee2o5aIYnvHU6C0A42MNdsIDeqy5BydrkuC5R1ZuUFnm27EeFJGoEHJQgn3uleRvmTXaJgfXbt4g==", + "license": "MIT", + "dependencies": { + "acorn": "^8.11.0" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/arg": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz", + "integrity": "sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==", + "license": "MIT" + }, + "node_modules/aws-cdk-lib": { + "version": "2.173.4", + "resolved": "https://registry.npmjs.org/aws-cdk-lib/-/aws-cdk-lib-2.173.4.tgz", + "integrity": "sha512-0reN94TzkWmyVZDDBlYB4qzJUig8wTHEe82YLHlWRUhrU78fT+drVGUr+lYZwwETaZ+8fLdCOl9ULvFNq7iczQ==", + "bundleDependencies": [ + "@balena/dockerignore", + "case", + "fs-extra", + "ignore", + "jsonschema", + "minimatch", + "punycode", + "semver", + "table", + "yaml", + "mime-types" + ], + "license": "Apache-2.0", + "dependencies": { + "@aws-cdk/asset-awscli-v1": "^2.2.208", + "@aws-cdk/asset-kubectl-v20": "^2.1.3", + "@aws-cdk/asset-node-proxy-agent-v6": "^2.1.0", + "@aws-cdk/cloud-assembly-schema": "^38.0.1", + "@balena/dockerignore": "^1.0.2", + "case": "1.6.3", + "fs-extra": "^11.2.0", + "ignore": "^5.3.2", + "jsonschema": "^1.4.1", + "mime-types": "^2.1.35", + "minimatch": "^3.1.2", + "punycode": "^2.3.1", + "semver": "^7.6.3", + "table": "^6.8.2", + "yaml": "1.10.2" + }, + "engines": { + "node": ">= 14.15.0" + }, + "peerDependencies": { + "constructs": "^10.0.0" + } + }, + "node_modules/aws-cdk-lib/node_modules/@balena/dockerignore": { + "version": "1.0.2", + "inBundle": true, + "license": "Apache-2.0" + }, + "node_modules/aws-cdk-lib/node_modules/ajv": { + "version": "8.17.1", + "inBundle": true, + "license": "MIT", + "dependencies": { + "fast-deep-equal": "^3.1.3", + "fast-uri": "^3.0.1", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/aws-cdk-lib/node_modules/ansi-regex": { + "version": "5.0.1", + "inBundle": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/aws-cdk-lib/node_modules/ansi-styles": { + "version": "4.3.0", + "inBundle": true, + "license": "MIT", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/aws-cdk-lib/node_modules/astral-regex": { + "version": "2.0.0", + "inBundle": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/aws-cdk-lib/node_modules/balanced-match": { + "version": "1.0.2", + "inBundle": true, + "license": "MIT" + }, + "node_modules/aws-cdk-lib/node_modules/brace-expansion": { + "version": "1.1.11", + "inBundle": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/aws-cdk-lib/node_modules/case": { + "version": "1.6.3", + "inBundle": true, + "license": "(MIT OR GPL-3.0-or-later)", + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/aws-cdk-lib/node_modules/color-convert": { + "version": "2.0.1", + "inBundle": true, + "license": "MIT", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/aws-cdk-lib/node_modules/color-name": { + "version": "1.1.4", + "inBundle": true, + "license": "MIT" + }, + "node_modules/aws-cdk-lib/node_modules/concat-map": { + "version": "0.0.1", + "inBundle": true, + "license": "MIT" + }, + "node_modules/aws-cdk-lib/node_modules/emoji-regex": { + "version": "8.0.0", + "inBundle": true, + "license": "MIT" + }, + "node_modules/aws-cdk-lib/node_modules/fast-deep-equal": { + "version": "3.1.3", + "inBundle": true, + "license": "MIT" + }, + "node_modules/aws-cdk-lib/node_modules/fast-uri": { + "version": "3.0.3", + "inBundle": true, + "license": "BSD-3-Clause" + }, + "node_modules/aws-cdk-lib/node_modules/fs-extra": { + "version": "11.2.0", + "inBundle": true, + "license": "MIT", + "dependencies": { + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, + "engines": { + "node": ">=14.14" + } + }, + "node_modules/aws-cdk-lib/node_modules/graceful-fs": { + "version": "4.2.11", + "inBundle": true, + "license": "ISC" + }, + "node_modules/aws-cdk-lib/node_modules/ignore": { + "version": "5.3.2", + "inBundle": true, + "license": "MIT", + "engines": { + "node": ">= 4" + } + }, + "node_modules/aws-cdk-lib/node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "inBundle": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/aws-cdk-lib/node_modules/json-schema-traverse": { + "version": "1.0.0", + "inBundle": true, + "license": "MIT" + }, + "node_modules/aws-cdk-lib/node_modules/jsonfile": { + "version": "6.1.0", + "inBundle": true, + "license": "MIT", + "dependencies": { + "universalify": "^2.0.0" + }, + "optionalDependencies": { + "graceful-fs": "^4.1.6" + } + }, + "node_modules/aws-cdk-lib/node_modules/jsonschema": { + "version": "1.4.1", + "inBundle": true, + "license": "MIT", + "engines": { + "node": "*" + } + }, + "node_modules/aws-cdk-lib/node_modules/lodash.truncate": { + "version": "4.4.2", + "inBundle": true, + "license": "MIT" + }, + "node_modules/aws-cdk-lib/node_modules/mime-db": { + "version": "1.52.0", + "inBundle": true, + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/aws-cdk-lib/node_modules/mime-types": { + "version": "2.1.35", + "inBundle": true, + "license": "MIT", + "dependencies": { + "mime-db": "1.52.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/aws-cdk-lib/node_modules/minimatch": { + "version": "3.1.2", + "inBundle": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/aws-cdk-lib/node_modules/punycode": { + "version": "2.3.1", + "inBundle": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/aws-cdk-lib/node_modules/require-from-string": { + "version": "2.0.2", + "inBundle": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/aws-cdk-lib/node_modules/semver": { + "version": "7.6.3", + "inBundle": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/aws-cdk-lib/node_modules/slice-ansi": { + "version": "4.0.0", + "inBundle": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.0.0", + "astral-regex": "^2.0.0", + "is-fullwidth-code-point": "^3.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/slice-ansi?sponsor=1" + } + }, + "node_modules/aws-cdk-lib/node_modules/string-width": { + "version": "4.2.3", + "inBundle": true, + "license": "MIT", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/aws-cdk-lib/node_modules/strip-ansi": { + "version": "6.0.1", + "inBundle": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/aws-cdk-lib/node_modules/table": { + "version": "6.8.2", + "inBundle": true, + "license": "BSD-3-Clause", + "dependencies": { + "ajv": "^8.0.1", + "lodash.truncate": "^4.4.2", + "slice-ansi": "^4.0.0", + "string-width": "^4.2.3", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/aws-cdk-lib/node_modules/universalify": { + "version": "2.0.1", + "inBundle": true, + "license": "MIT", + "engines": { + "node": ">= 10.0.0" + } + }, + "node_modules/aws-cdk-lib/node_modules/yaml": { + "version": "1.10.2", + "inBundle": true, + "license": "ISC", + "engines": { + "node": ">= 6" + } + }, + "node_modules/constructs": { + "version": "10.4.2", + "resolved": "https://registry.npmjs.org/constructs/-/constructs-10.4.2.tgz", + "integrity": "sha512-wsNxBlAott2qg8Zv87q3eYZYgheb9lchtBfjHzzLHtXbttwSrHPs1NNQbBrmbb1YZvYg2+Vh0Dor76w4mFxJkA==", + "license": "Apache-2.0", + "peer": true + }, + "node_modules/create-require": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/create-require/-/create-require-1.1.1.tgz", + "integrity": "sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==", + "license": "MIT" + }, + "node_modules/diff": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz", + "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==", + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.3.1" + } + }, + "node_modules/make-error": { + "version": "1.3.6", + "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz", + "integrity": "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==", + "license": "ISC" + }, + "node_modules/ts-node": { + "version": "10.9.2", + "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.9.2.tgz", + "integrity": "sha512-f0FFpIdcHgn8zcPSbf1dRevwt047YMnaiJM3u2w2RewrB+fob/zePZcrOyQoLMMO7aBIddLcQIEK5dYjkLnGrQ==", + "license": "MIT", + "dependencies": { + "@cspotcode/source-map-support": "^0.8.0", + "@tsconfig/node10": "^1.0.7", + "@tsconfig/node12": "^1.0.7", + "@tsconfig/node14": "^1.0.0", + "@tsconfig/node16": "^1.0.2", + "acorn": "^8.4.1", + "acorn-walk": "^8.1.1", + "arg": "^4.1.0", + "create-require": "^1.1.0", + "diff": "^4.0.1", + "make-error": "^1.1.1", + "v8-compile-cache-lib": "^3.0.1", + "yn": "3.1.1" + }, + "bin": { + "ts-node": "dist/bin.js", + "ts-node-cwd": "dist/bin-cwd.js", + "ts-node-esm": "dist/bin-esm.js", + "ts-node-script": "dist/bin-script.js", + "ts-node-transpile-only": "dist/bin-transpile.js", + "ts-script": "dist/bin-script-deprecated.js" + }, + "peerDependencies": { + "@swc/core": ">=1.2.50", + "@swc/wasm": ">=1.2.50", + "@types/node": "*", + "typescript": ">=2.7" + }, + "peerDependenciesMeta": { + "@swc/core": { + "optional": true + }, + "@swc/wasm": { + "optional": true + } + } + }, + "node_modules/typescript": { + "version": "5.7.2", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.7.2.tgz", + "integrity": "sha512-i5t66RHxDvVN40HfDd1PsEThGNnlMCMT3jMUuoh9/0TaqWevNontacunWyN02LA9/fIbEWlcHZcgTKb9QoaLfg==", + "license": "Apache-2.0", + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=14.17" + } + }, + "node_modules/undici-types": { + "version": "6.20.0", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.20.0.tgz", + "integrity": "sha512-Ny6QZ2Nju20vw1SRHe3d9jVu6gJ+4e3+MMpqu7pqE5HT6WsTSlce++GQmK5UXS8mzV8DSYHrQH+Xrf2jVcuKNg==", + "license": "MIT", + "peer": true + }, + "node_modules/v8-compile-cache-lib": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz", + "integrity": "sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg==", + "license": "MIT" + }, + "node_modules/yn": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz", + "integrity": "sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==", + "license": "MIT", + "engines": { + "node": ">=6" + } + } + } +} diff --git a/flux_serve/oci-image-build/package.json b/flux_serve/oci-image-build/package.json new file mode 100644 index 0000000..8926107 --- /dev/null +++ b/flux_serve/oci-image-build/package.json @@ -0,0 +1,9 @@ +{ + "dependencies": { + "aws-cdk-lib": "^2.173.4", + "ts-node": "^10.9.2" + }, + "devDependencies": { + "typescript": "^5.7.2" + } +} diff --git a/flux_serve/oci-image-build/pipeline-stack.js b/flux_serve/oci-image-build/pipeline-stack.js new file mode 100644 index 0000000..2cace63 --- /dev/null +++ b/flux_serve/oci-image-build/pipeline-stack.js @@ -0,0 +1,329 @@ +"use strict"; +var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + var desc = Object.getOwnPropertyDescriptor(m, k); + if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { + desc = { enumerable: true, get: function() { return m[k]; } }; + } + Object.defineProperty(o, k2, desc); +}) : (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + o[k2] = m[k]; +})); +var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { + Object.defineProperty(o, "default", { enumerable: true, value: v }); +}) : function(o, v) { + o["default"] = v; +}); +var __importStar = (this && this.__importStar) || (function () { + var ownKeys = function(o) { + ownKeys = Object.getOwnPropertyNames || function (o) { + var ar = []; + for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k; + return ar; + }; + return ownKeys(o); + }; + return function (mod) { + if (mod && mod.__esModule) return mod; + var result = {}; + if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]); + __setModuleDefault(result, mod); + return result; + }; +})(); +Object.defineProperty(exports, "__esModule", { value: true }); +exports.PipelineStack = void 0; +const aws_cdk_lib_1 = require("aws-cdk-lib"); +const ecr = __importStar(require("aws-cdk-lib/aws-ecr")); +const codebuild = __importStar(require("aws-cdk-lib/aws-codebuild")); +const codepipeline = __importStar(require("aws-cdk-lib/aws-codepipeline")); +const codepipeline_actions = __importStar(require("aws-cdk-lib/aws-codepipeline-actions")); +const iam = __importStar(require("aws-cdk-lib/aws-iam")); +const secretsmanager = __importStar(require("aws-cdk-lib/aws-secretsmanager")); +const cdk = __importStar(require("aws-cdk-lib/core")); +class PipelineStack extends aws_cdk_lib_1.Stack { + constructor(scope, id, props) { + super(scope, id, props); + const BASE_REPO = new aws_cdk_lib_1.CfnParameter(this, "BASEREPO", { type: "String" }); + const BASE_IMAGE_AMD_XLA_TAG = new aws_cdk_lib_1.CfnParameter(this, "BASEIMAGEAMDXLATAG", { type: "String" }); + const BASE_IMAGE_AMD_CUD_TAG = new aws_cdk_lib_1.CfnParameter(this, "BASEIMAGEAMDCUDTAG", { type: "String" }); + const BASE_IMAGE_ARM_CPU_TAG = new aws_cdk_lib_1.CfnParameter(this, "BASEIMAGEARMCPUTAG", { type: "String" }); + const IMAGE_AMD_XLA_TAG = new aws_cdk_lib_1.CfnParameter(this, "IMAGEAMDXLATAG", { type: "String" }); + const IMAGE_AMD_CUD_TAG = new aws_cdk_lib_1.CfnParameter(this, "IMAGEAMDCUDTAG", { type: "String" }); + const IMAGE_ARM_CPU_TAG = new aws_cdk_lib_1.CfnParameter(this, "IMAGEARMCPUTAG", { type: "String" }); + const GITHUB_OAUTH_TOKEN = new aws_cdk_lib_1.CfnParameter(this, "GITHUBOAUTHTOKEN", { type: "String" }); + const GITHUB_USER = new aws_cdk_lib_1.CfnParameter(this, "GITHUBUSER", { type: "String" }); + const GITHUB_REPO = new aws_cdk_lib_1.CfnParameter(this, "GITHUBREPO", { type: "String" }); + const GITHUB_BRANCH = new aws_cdk_lib_1.CfnParameter(this, "GITHUBBRANCH", { type: "String" }); + // uncomment when you test the stack and dont want to manually delete the ecr registry + const base_registry = new ecr.Repository(this, `base_repo`, { + repositoryName: BASE_REPO.valueAsString, + imageScanOnPush: true + }); + //const base_registry = ecr.Repository.fromRepositoryName(this,`base_repo`,BASE_REPO.valueAsString) + //create a roleARN for codebuild + const buildRole = new iam.Role(this, 'BaseCodeBuildDeployRole', { + roleName: 'hwagnisticBaseCodeBuildDeployRole', + assumedBy: new iam.ServicePrincipal('codebuild.amazonaws.com'), + }); + buildRole.addToPolicy(new iam.PolicyStatement({ + resources: ['*'], + actions: ['ssm:*', 's3:*'], + })); + const githubSecret = new secretsmanager.Secret(this, 'githubSecret', { + secretObjectValue: { + token: aws_cdk_lib_1.SecretValue.unsafePlainText(GITHUB_OAUTH_TOKEN.valueAsString) + }, + }); + const githubOAuthToken = aws_cdk_lib_1.SecretValue.secretsManager(githubSecret.secretArn, { jsonField: 'token' }); + new cdk.CfnOutput(this, 'githubOAuthTokenRuntimeOutput1', { + //value: SecretValue.secretsManager("githubtoken",{jsonField: "token"}).toString() + value: githubSecret.secretValueFromJson('token').toString() + }); + new cdk.CfnOutput(this, 'githubOAuthTokenRuntimeOutput2', { + value: aws_cdk_lib_1.SecretValue.secretsManager(githubSecret.secretArn, { jsonField: "token" }).toString() + }); + const base_image_amd_cud_build = new codebuild.Project(this, `ImageCudAmdBuild`, { + environment: { privileged: true, buildImage: codebuild.LinuxBuildImage.AMAZON_LINUX_2_3 }, + cache: codebuild.Cache.local(codebuild.LocalCacheMode.DOCKER_LAYER, codebuild.LocalCacheMode.CUSTOM), + role: buildRole, + buildSpec: codebuild.BuildSpec.fromObject({ + version: "0.2", + env: { + 'exported-variables': [ + 'AWS_ACCOUNT_ID', 'AWS_REGION', 'BASE_REPO', 'IMAGE_AMD_CUD_TAG', 'BASE_IMAGE_AMD_CUD_TAG' + ], + }, + phases: { + build: { + commands: [ + `export AWS_ACCOUNT_ID="${this.account}"`, + `export AWS_REGION="${this.region}"`, + `export BASE_REPO="${BASE_REPO.valueAsString}"`, + `export IMAGE_TAG="${IMAGE_AMD_CUD_TAG.valueAsString}"`, + `export BASE_IMAGE_TAG="${BASE_IMAGE_AMD_CUD_TAG.valueAsString}"`, + `cd app`, + `chmod +x ./build.sh && ./build.sh` + ], + } + }, + artifacts: { + files: ['imageDetail.json'] + }, + }), + }); + const base_image_arm_cpu_build = new codebuild.Project(this, `ImageCpuArmBuild`, { + environment: { privileged: true, buildImage: codebuild.LinuxBuildImage.AMAZON_LINUX_2_ARM_2 }, + cache: codebuild.Cache.local(codebuild.LocalCacheMode.DOCKER_LAYER, codebuild.LocalCacheMode.CUSTOM), + role: buildRole, + buildSpec: codebuild.BuildSpec.fromObject({ + version: "0.2", + env: { + 'exported-variables': [ + 'AWS_ACCOUNT_ID', 'AWS_REGION', 'BASE_REPO', 'IMAGE_ARM_CPU_TAG', 'BASE_IMAGE_ARM_CPU_TAG' + ], + }, + phases: { + build: { + commands: [ + `export AWS_ACCOUNT_ID="${this.account}"`, + `export AWS_REGION="${this.region}"`, + `export BASE_REPO="${BASE_REPO.valueAsString}"`, + `export IMAGE_TAG="${IMAGE_ARM_CPU_TAG.valueAsString}"`, + `export BASE_IMAGE_TAG="${BASE_IMAGE_ARM_CPU_TAG.valueAsString}"`, + `cd app`, + `chmod +x ./build.sh && ./build.sh` + ], + } + }, + artifacts: { + files: ['imageDetail.json'] + }, + }), + }); + const base_image_amd_xla_build = new codebuild.Project(this, `ImageXlaAmdBuild`, { + environment: { privileged: true, buildImage: codebuild.LinuxBuildImage.AMAZON_LINUX_2_3 }, + cache: codebuild.Cache.local(codebuild.LocalCacheMode.DOCKER_LAYER, codebuild.LocalCacheMode.CUSTOM), + role: buildRole, + buildSpec: codebuild.BuildSpec.fromObject({ + version: "0.2", + env: { + 'exported-variables': [ + 'AWS_ACCOUNT_ID', 'AWS_REGION', 'BASE_REPO', 'IMAGE_AMD_XLA_TAG', 'BASE_IMAGE_AMD_XLA_TAG' + ], + }, + phases: { + build: { + commands: [ + `export AWS_ACCOUNT_ID="${this.account}"`, + `export AWS_REGION="${this.region}"`, + `export BASE_REPO="${BASE_REPO.valueAsString}"`, + `export IMAGE_TAG="${IMAGE_AMD_XLA_TAG.valueAsString}"`, + `export BASE_IMAGE_TAG="${BASE_IMAGE_AMD_XLA_TAG.valueAsString}"`, + `cd app`, + `chmod +x ./build.sh && ./build.sh` + ], + } + }, + artifacts: { + files: ['imageDetail.json'] + }, + }), + }); + const assets_image_xla_amd_build = new codebuild.Project(this, `AssetsImageXlaAmdBuild`, { + environment: { privileged: true, buildImage: codebuild.LinuxBuildImage.AMAZON_LINUX_2_3 }, + cache: codebuild.Cache.local(codebuild.LocalCacheMode.DOCKER_LAYER, codebuild.LocalCacheMode.CUSTOM), + role: buildRole, + buildSpec: codebuild.BuildSpec.fromObject({ + version: "0.2", + env: { + 'exported-variables': [ + 'AWS_ACCOUNT_ID', 'AWS_REGION', 'BASE_REPO', 'IMAGE_AMD_XLA_TAG', 'BASE_IMAGE_AMD_XLA_TAG' + ], + }, + phases: { + build: { + commands: [ + `export AWS_ACCOUNT_ID="${this.account}"`, + `export AWS_REGION="${this.region}"`, + `export BASE_REPO="${BASE_REPO.valueAsString}"`, + `export IMAGE_TAG="${IMAGE_AMD_XLA_TAG.valueAsString}"`, + `export BASE_IMAGE_TAG="${BASE_IMAGE_AMD_XLA_TAG.valueAsString}"`, + `cd app`, + `chmod +x ./build-assets.sh && ./build-assets.sh` + ], + } + }, + artifacts: { + files: ['imageDetail.json'] + }, + }), + }); + const assets_image_cpu_arm_build = new codebuild.Project(this, `AssetsImageCpuArmBuild`, { + environment: { privileged: true, buildImage: codebuild.LinuxBuildImage.AMAZON_LINUX_2_ARM_2 }, + cache: codebuild.Cache.local(codebuild.LocalCacheMode.DOCKER_LAYER, codebuild.LocalCacheMode.CUSTOM), + role: buildRole, + buildSpec: codebuild.BuildSpec.fromObject({ + version: "0.2", + env: { + 'exported-variables': [ + 'AWS_ACCOUNT_ID', 'AWS_REGION', 'BASE_REPO', 'IMAGE_ARM_CPU_TAG', 'BASE_IMAGE_ARM_CPU_TAG' + ], + }, + phases: { + build: { + commands: [ + `export AWS_ACCOUNT_ID="${this.account}"`, + `export AWS_REGION="${this.region}"`, + `export BASE_REPO="${BASE_REPO.valueAsString}"`, + `export IMAGE_TAG="${IMAGE_ARM_CPU_TAG.valueAsString}"`, + `export BASE_IMAGE_TAG="${BASE_IMAGE_ARM_CPU_TAG.valueAsString}"`, + `cd app`, + `chmod +x ./build-assets.sh && ./build-assets.sh` + ], + } + }, + artifacts: { + files: ['imageDetail.json'] + }, + }), + }); + const assets_image_cud_amd_build = new codebuild.Project(this, `AssetsImageCudAmdBuild`, { + environment: { privileged: true, buildImage: codebuild.LinuxBuildImage.AMAZON_LINUX_2_3 }, + cache: codebuild.Cache.local(codebuild.LocalCacheMode.DOCKER_LAYER, codebuild.LocalCacheMode.CUSTOM), + role: buildRole, + buildSpec: codebuild.BuildSpec.fromObject({ + version: "0.2", + env: { + 'exported-variables': [ + 'AWS_ACCOUNT_ID', 'AWS_REGION', 'BASE_REPO', 'IMAGE_AMD_CUD_TAG', 'BASE_IMAGE_AMD_CUD_TAG' + ], + }, + phases: { + build: { + commands: [ + `export AWS_ACCOUNT_ID="${this.account}"`, + `export AWS_REGION="${this.region}"`, + `export BASE_REPO="${BASE_REPO.valueAsString}"`, + `export IMAGE_TAG="${IMAGE_AMD_CUD_TAG.valueAsString}"`, + `export BASE_IMAGE_TAG="${BASE_IMAGE_AMD_CUD_TAG.valueAsString}"`, + `cd app`, + `chmod +x ./build-assets.sh && ./build-assets.sh` + ], + } + }, + artifacts: { + files: ['imageDetail.json'] + }, + }), + }); + //we allow the buildProject principal to push images to ecr + base_registry.grantPullPush(assets_image_cud_amd_build.grantPrincipal); + base_registry.grantPullPush(assets_image_xla_amd_build.grantPrincipal); + base_registry.grantPullPush(assets_image_cpu_arm_build.grantPrincipal); + base_registry.grantPullPush(base_image_amd_xla_build.grantPrincipal); + base_registry.grantPullPush(base_image_amd_cud_build.grantPrincipal); + base_registry.grantPullPush(base_image_arm_cpu_build.grantPrincipal); + // here we define our pipeline and put together the assembly line + const sourceOutput = new codepipeline.Artifact(); + const basebuildpipeline = new codepipeline.Pipeline(this, `BuildBasePipeline`); + basebuildpipeline.addStage({ + stageName: 'Source', + actions: [ + new codepipeline_actions.GitHubSourceAction({ + actionName: 'GitHub_Source', + owner: GITHUB_USER.valueAsString, + repo: GITHUB_REPO.valueAsString, + branch: GITHUB_BRANCH.valueAsString, + output: sourceOutput, + oauthToken: aws_cdk_lib_1.SecretValue.secretsManager("githubtoken", { jsonField: "token" }), + trigger: codepipeline_actions.GitHubTrigger.WEBHOOK, + //oauthToken: SecretValue.unsafePlainText(GITHUB_OAUTH_TOKEN.valueAsString) + }) + ] + }); + basebuildpipeline.addStage({ + stageName: 'ImageBuild', + actions: [ + new codepipeline_actions.CodeBuildAction({ + actionName: 'AssetsImageXlaAmdBuild', + input: sourceOutput, + runOrder: 1, + project: assets_image_xla_amd_build + }), + new codepipeline_actions.CodeBuildAction({ + actionName: 'AssetsImageCudAmdBuild', + input: sourceOutput, + runOrder: 1, + project: assets_image_cud_amd_build + }), + new codepipeline_actions.CodeBuildAction({ + actionName: 'AssetsImageCpuArmBuild', + input: sourceOutput, + runOrder: 1, + project: assets_image_cpu_arm_build + }), + new codepipeline_actions.CodeBuildAction({ + actionName: 'BaseImageAmdXlaBuild', + input: sourceOutput, + runOrder: 2, + project: base_image_amd_xla_build + }), + new codepipeline_actions.CodeBuildAction({ + actionName: 'BaseImageArmCpuBuild', + input: sourceOutput, + runOrder: 2, + project: base_image_arm_cpu_build + }), + new codepipeline_actions.CodeBuildAction({ + actionName: 'BaseImageAmdCudBuild', + input: sourceOutput, + runOrder: 2, + project: base_image_amd_cud_build + }) + ] + }); + } +} +exports.PipelineStack = PipelineStack; diff --git a/flux_serve/oci-image-build/pipeline-stack.ts b/flux_serve/oci-image-build/pipeline-stack.ts new file mode 100644 index 0000000..a5beb03 --- /dev/null +++ b/flux_serve/oci-image-build/pipeline-stack.ts @@ -0,0 +1,321 @@ +import { Stack, StackProps,CfnParameter,SecretValue} from 'aws-cdk-lib'; +import { Construct } from 'constructs' +import * as codecommit from 'aws-cdk-lib/aws-codecommit'; +import * as ecr from 'aws-cdk-lib/aws-ecr'; +import * as codebuild from 'aws-cdk-lib/aws-codebuild'; +import * as codepipeline from 'aws-cdk-lib/aws-codepipeline'; +import * as codepipeline_actions from 'aws-cdk-lib/aws-codepipeline-actions'; +import * as iam from "aws-cdk-lib/aws-iam"; +import * as secretsmanager from 'aws-cdk-lib/aws-secretsmanager'; +import * as cdk from 'aws-cdk-lib/core'; +import * as cfn from 'aws-cdk-lib/aws-cloudformation'; + +export class PipelineStack extends Stack { + constructor(scope: Construct, id: string, props?: StackProps) { + super(scope, id, props); + const BASE_REPO = new CfnParameter(this,"BASEREPO",{type:"String"}); + const BASE_IMAGE_AMD_XLA_TAG = new CfnParameter(this,"BASEIMAGEAMDXLATAG",{type:"String"}); + const BASE_IMAGE_AMD_CUD_TAG = new CfnParameter(this,"BASEIMAGEAMDCUDTAG",{type:"String"}); + const BASE_IMAGE_ARM_CPU_TAG = new CfnParameter(this,"BASEIMAGEARMCPUTAG",{type:"String"}); + const IMAGE_AMD_XLA_TAG = new CfnParameter(this,"IMAGEAMDXLATAG",{type:"String"}); + const IMAGE_AMD_CUD_TAG = new CfnParameter(this,"IMAGEAMDCUDTAG",{type:"String"}); + const IMAGE_ARM_CPU_TAG = new CfnParameter(this,"IMAGEARMCPUTAG",{type:"String"}); + const GITHUB_OAUTH_TOKEN = new CfnParameter(this,"GITHUBOAUTHTOKEN",{type:"String"}); + const GITHUB_USER = new CfnParameter(this,"GITHUBUSER",{type:"String"}); + const GITHUB_REPO = new CfnParameter(this,"GITHUBREPO",{type:"String"}); + const GITHUB_BRANCH = new CfnParameter(this,"GITHUBBRANCH",{type:"String"}); + // uncomment when you test the stack and dont want to manually delete the ecr registry + const base_registry = new ecr.Repository(this,`base_repo`,{ + repositoryName:BASE_REPO.valueAsString, + imageScanOnPush: true + }); + + //const base_registry = ecr.Repository.fromRepositoryName(this,`base_repo`,BASE_REPO.valueAsString) + + //create a roleARN for codebuild + const buildRole = new iam.Role(this, 'BaseCodeBuildDeployRole',{ + roleName: 'hwagnisticBaseCodeBuildDeployRole', + assumedBy: new iam.ServicePrincipal('codebuild.amazonaws.com'), + }); + + buildRole.addToPolicy(new iam.PolicyStatement({ + resources: ['*'], + actions: ['ssm:*','s3:*'], + })); + + const githubSecret = new secretsmanager.Secret(this, 'githubSecret', { + secretObjectValue: { + token: SecretValue.unsafePlainText(GITHUB_OAUTH_TOKEN.valueAsString) + }, + }); + const githubOAuthToken = SecretValue.secretsManager(githubSecret.secretArn,{jsonField:'token'}); + new cdk.CfnOutput(this, 'githubOAuthTokenRuntimeOutput1', { + //value: SecretValue.secretsManager("githubtoken",{jsonField: "token"}).toString() + value: githubSecret.secretValueFromJson('token').toString() + }); + new cdk.CfnOutput(this, 'githubOAuthTokenRuntimeOutput2', { + value: SecretValue.secretsManager(githubSecret.secretArn,{jsonField: "token"}).toString() + }); + + const base_image_amd_cud_build = new codebuild.Project(this, `ImageCudAmdBuild`, { + environment: {privileged:true,buildImage: codebuild.LinuxBuildImage.AMAZON_LINUX_2_3}, + cache: codebuild.Cache.local(codebuild.LocalCacheMode.DOCKER_LAYER, codebuild.LocalCacheMode.CUSTOM), + role: buildRole, + buildSpec: codebuild.BuildSpec.fromObject( + { + version: "0.2", + env: { + 'exported-variables': [ + 'AWS_ACCOUNT_ID','AWS_REGION','BASE_REPO','IMAGE_AMD_CUD_TAG','BASE_IMAGE_AMD_CUD_TAG' + ], + }, + phases: { + build: { + commands: [ + `export AWS_ACCOUNT_ID="${this.account}"`, + `export AWS_REGION="${this.region}"`, + `export BASE_REPO="${BASE_REPO.valueAsString}"`, + `export IMAGE_TAG="${IMAGE_AMD_CUD_TAG.valueAsString}"`, + `export BASE_IMAGE_TAG="${BASE_IMAGE_AMD_CUD_TAG.valueAsString}"`, + `cd app`, + `chmod +x ./build.sh && ./build.sh` + ], + } + }, + artifacts: { + files: ['imageDetail.json'] + }, + } + ), + }); + + const base_image_arm_cpu_build = new codebuild.Project(this, `ImageCpuArmBuild`, { + environment: {privileged:true,buildImage: codebuild.LinuxBuildImage.AMAZON_LINUX_2_ARM_2}, + cache: codebuild.Cache.local(codebuild.LocalCacheMode.DOCKER_LAYER, codebuild.LocalCacheMode.CUSTOM), + role: buildRole, + buildSpec: codebuild.BuildSpec.fromObject( + { + version: "0.2", + env: { + 'exported-variables': [ + 'AWS_ACCOUNT_ID','AWS_REGION','BASE_REPO','IMAGE_ARM_CPU_TAG','BASE_IMAGE_ARM_CPU_TAG' + ], + }, + phases: { + build: { + commands: [ + `export AWS_ACCOUNT_ID="${this.account}"`, + `export AWS_REGION="${this.region}"`, + `export BASE_REPO="${BASE_REPO.valueAsString}"`, + `export IMAGE_TAG="${IMAGE_ARM_CPU_TAG.valueAsString}"`, + `export BASE_IMAGE_TAG="${BASE_IMAGE_ARM_CPU_TAG.valueAsString}"`, + `cd app`, + `chmod +x ./build.sh && ./build.sh` + ], + } + }, + artifacts: { + files: ['imageDetail.json'] + }, + } + ), + }); + + const base_image_amd_xla_build = new codebuild.Project(this, `ImageXlaAmdBuild`, { + environment: {privileged:true,buildImage: codebuild.LinuxBuildImage.AMAZON_LINUX_2_3}, + cache: codebuild.Cache.local(codebuild.LocalCacheMode.DOCKER_LAYER, codebuild.LocalCacheMode.CUSTOM), + role: buildRole, + buildSpec: codebuild.BuildSpec.fromObject( + { + version: "0.2", + env: { + 'exported-variables': [ + 'AWS_ACCOUNT_ID','AWS_REGION','BASE_REPO','IMAGE_AMD_XLA_TAG','BASE_IMAGE_AMD_XLA_TAG' + ], + }, + phases: { + build: { + commands: [ + `export AWS_ACCOUNT_ID="${this.account}"`, + `export AWS_REGION="${this.region}"`, + `export BASE_REPO="${BASE_REPO.valueAsString}"`, + `export IMAGE_TAG="${IMAGE_AMD_XLA_TAG.valueAsString}"`, + `export BASE_IMAGE_TAG="${BASE_IMAGE_AMD_XLA_TAG.valueAsString}"`, + `cd app`, + `chmod +x ./build.sh && ./build.sh` + ], + } + }, + artifacts: { + files: ['imageDetail.json'] + }, + } + ), + }); + + const assets_image_xla_amd_build = new codebuild.Project(this, `AssetsImageXlaAmdBuild`, { + environment: {privileged:true,buildImage: codebuild.LinuxBuildImage.AMAZON_LINUX_2_3}, + cache: codebuild.Cache.local(codebuild.LocalCacheMode.DOCKER_LAYER, codebuild.LocalCacheMode.CUSTOM), + role: buildRole, + buildSpec: codebuild.BuildSpec.fromObject( + { + version: "0.2", + env: { + 'exported-variables': [ + 'AWS_ACCOUNT_ID','AWS_REGION','BASE_REPO','IMAGE_AMD_XLA_TAG','BASE_IMAGE_AMD_XLA_TAG' + ], + }, + phases: { + build: { + commands: [ + `export AWS_ACCOUNT_ID="${this.account}"`, + `export AWS_REGION="${this.region}"`, + `export BASE_REPO="${BASE_REPO.valueAsString}"`, + `export IMAGE_TAG="${IMAGE_AMD_XLA_TAG.valueAsString}"`, + `export BASE_IMAGE_TAG="${BASE_IMAGE_AMD_XLA_TAG.valueAsString}"`, + `cd app`, + `chmod +x ./build-assets.sh && ./build-assets.sh` + ], + } + }, + artifacts: { + files: ['imageDetail.json'] + }, + } + ), + }); + + const assets_image_cpu_arm_build = new codebuild.Project(this, `AssetsImageCpuArmBuild`, { + environment: {privileged:true,buildImage: codebuild.LinuxBuildImage.AMAZON_LINUX_2_ARM_2}, + cache: codebuild.Cache.local(codebuild.LocalCacheMode.DOCKER_LAYER, codebuild.LocalCacheMode.CUSTOM), + role: buildRole, + buildSpec: codebuild.BuildSpec.fromObject( + { + version: "0.2", + env: { + 'exported-variables': [ + 'AWS_ACCOUNT_ID','AWS_REGION','BASE_REPO','IMAGE_ARM_CPU_TAG','BASE_IMAGE_ARM_CPU_TAG' + ], + }, + phases: { + build: { + commands: [ + `export AWS_ACCOUNT_ID="${this.account}"`, + `export AWS_REGION="${this.region}"`, + `export BASE_REPO="${BASE_REPO.valueAsString}"`, + `export IMAGE_TAG="${IMAGE_ARM_CPU_TAG.valueAsString}"`, + `export BASE_IMAGE_TAG="${BASE_IMAGE_ARM_CPU_TAG.valueAsString}"`, + `cd app`, + `chmod +x ./build-assets.sh && ./build-assets.sh` + ], + } + }, + artifacts: { + files: ['imageDetail.json'] + }, + } + ), + }); + + const assets_image_cud_amd_build = new codebuild.Project(this, `AssetsImageCudAmdBuild`, { + environment: {privileged:true,buildImage: codebuild.LinuxBuildImage.AMAZON_LINUX_2_3}, + cache: codebuild.Cache.local(codebuild.LocalCacheMode.DOCKER_LAYER, codebuild.LocalCacheMode.CUSTOM), + role: buildRole, + buildSpec: codebuild.BuildSpec.fromObject( + { + version: "0.2", + env: { + 'exported-variables': [ + 'AWS_ACCOUNT_ID','AWS_REGION','BASE_REPO','IMAGE_AMD_CUD_TAG','BASE_IMAGE_AMD_CUD_TAG' + ], + }, + phases: { + build: { + commands: [ + `export AWS_ACCOUNT_ID="${this.account}"`, + `export AWS_REGION="${this.region}"`, + `export BASE_REPO="${BASE_REPO.valueAsString}"`, + `export IMAGE_TAG="${IMAGE_AMD_CUD_TAG.valueAsString}"`, + `export BASE_IMAGE_TAG="${BASE_IMAGE_AMD_CUD_TAG.valueAsString}"`, + `cd app`, + `chmod +x ./build-assets.sh && ./build-assets.sh` + ], + } + }, + artifacts: { + files: ['imageDetail.json'] + }, + } + ), + }); + + //we allow the buildProject principal to push images to ecr + base_registry.grantPullPush(assets_image_cud_amd_build.grantPrincipal); + base_registry.grantPullPush(assets_image_xla_amd_build.grantPrincipal); + base_registry.grantPullPush(assets_image_cpu_arm_build.grantPrincipal); + base_registry.grantPullPush(base_image_amd_xla_build.grantPrincipal); + base_registry.grantPullPush(base_image_amd_cud_build.grantPrincipal); + base_registry.grantPullPush(base_image_arm_cpu_build.grantPrincipal); + + // here we define our pipeline and put together the assembly line + const sourceOutput = new codepipeline.Artifact(); + const basebuildpipeline = new codepipeline.Pipeline(this,`BuildBasePipeline`); + basebuildpipeline.addStage({ + stageName: 'Source', + actions: [ + new codepipeline_actions.GitHubSourceAction({ + actionName: 'GitHub_Source', + owner: GITHUB_USER.valueAsString, + repo: GITHUB_REPO.valueAsString, + branch: GITHUB_BRANCH.valueAsString, + output: sourceOutput, + oauthToken: SecretValue.secretsManager("githubtoken",{jsonField: "token"}), + trigger: codepipeline_actions.GitHubTrigger.WEBHOOK, + //oauthToken: SecretValue.unsafePlainText(GITHUB_OAUTH_TOKEN.valueAsString) + }) + ] + }); + + basebuildpipeline.addStage({ + stageName: 'ImageBuild', + actions: [ + new codepipeline_actions.CodeBuildAction({ + actionName: 'AssetsImageXlaAmdBuild', + input: sourceOutput, + runOrder: 1, + project: assets_image_xla_amd_build + }), + new codepipeline_actions.CodeBuildAction({ + actionName: 'AssetsImageCudAmdBuild', + input: sourceOutput, + runOrder: 1, + project: assets_image_cud_amd_build + }), + new codepipeline_actions.CodeBuildAction({ + actionName: 'AssetsImageCpuArmBuild', + input: sourceOutput, + runOrder: 1, + project: assets_image_cpu_arm_build + }), + new codepipeline_actions.CodeBuildAction({ + actionName: 'BaseImageAmdXlaBuild', + input: sourceOutput, + runOrder: 2, + project: base_image_amd_xla_build + }), + new codepipeline_actions.CodeBuildAction({ + actionName: 'BaseImageArmCpuBuild', + input: sourceOutput, + runOrder: 2, + project: base_image_arm_cpu_build + }), + new codepipeline_actions.CodeBuildAction({ + actionName: 'BaseImageAmdCudBuild', + input: sourceOutput, + runOrder: 2, + project: base_image_amd_cud_build + }) + ] + }); + } +} diff --git a/flux_serve/oci-image-build/pipeline.js b/flux_serve/oci-image-build/pipeline.js new file mode 100644 index 0000000..d8dc6e9 --- /dev/null +++ b/flux_serve/oci-image-build/pipeline.js @@ -0,0 +1,44 @@ +#!/usr/bin/env node +"use strict"; +var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + var desc = Object.getOwnPropertyDescriptor(m, k); + if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { + desc = { enumerable: true, get: function() { return m[k]; } }; + } + Object.defineProperty(o, k2, desc); +}) : (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + o[k2] = m[k]; +})); +var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { + Object.defineProperty(o, "default", { enumerable: true, value: v }); +}) : function(o, v) { + o["default"] = v; +}); +var __importStar = (this && this.__importStar) || (function () { + var ownKeys = function(o) { + ownKeys = Object.getOwnPropertyNames || function (o) { + var ar = []; + for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k; + return ar; + }; + return ownKeys(o); + }; + return function (mod) { + if (mod && mod.__esModule) return mod; + var result = {}; + if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]); + __setModuleDefault(result, mod); + return result; + }; +})(); +Object.defineProperty(exports, "__esModule", { value: true }); +require("source-map-support/register"); +const cdk = __importStar(require("aws-cdk-lib")); +const pipeline_stack_1 = require("./pipeline-stack"); +const app = new cdk.App(); +let stack = process.env.CF_STACK; +new pipeline_stack_1.PipelineStack(app, stack, { + env: { account: process.env.AWS_ACCOUNT_ID, region: process.env.AWS_REGION }, +}); diff --git a/flux_serve/oci-image-build/pipeline.ts b/flux_serve/oci-image-build/pipeline.ts new file mode 100644 index 0000000..f5f0bb6 --- /dev/null +++ b/flux_serve/oci-image-build/pipeline.ts @@ -0,0 +1,10 @@ +#!/usr/bin/env node +import 'source-map-support/register'; +import * as cdk from 'aws-cdk-lib'; +import { PipelineStack } from './pipeline-stack'; + +const app = new cdk.App(); +let stack = process.env.CF_STACK as string; +new PipelineStack(app,stack,{ + env: { account: process.env.AWS_ACCOUNT_ID, region: process.env.AWS_REGION}, +}); diff --git a/flux_serve/oci-image-build/tsconfig.json b/flux_serve/oci-image-build/tsconfig.json new file mode 100644 index 0000000..c9c555d --- /dev/null +++ b/flux_serve/oci-image-build/tsconfig.json @@ -0,0 +1,111 @@ +{ + "compilerOptions": { + /* Visit https://aka.ms/tsconfig to read more about this file */ + + /* Projects */ + // "incremental": true, /* Save .tsbuildinfo files to allow for incremental compilation of projects. */ + // "composite": true, /* Enable constraints that allow a TypeScript project to be used with project references. */ + // "tsBuildInfoFile": "./.tsbuildinfo", /* Specify the path to .tsbuildinfo incremental compilation file. */ + // "disableSourceOfProjectReferenceRedirect": true, /* Disable preferring source files instead of declaration files when referencing composite projects. */ + // "disableSolutionSearching": true, /* Opt a project out of multi-project reference checking when editing. */ + // "disableReferencedProjectLoad": true, /* Reduce the number of projects loaded automatically by TypeScript. */ + + /* Language and Environment */ + "target": "es2016", /* Set the JavaScript language version for emitted JavaScript and include compatible library declarations. */ + // "lib": [], /* Specify a set of bundled library declaration files that describe the target runtime environment. */ + // "jsx": "preserve", /* Specify what JSX code is generated. */ + // "experimentalDecorators": true, /* Enable experimental support for legacy experimental decorators. */ + // "emitDecoratorMetadata": true, /* Emit design-type metadata for decorated declarations in source files. */ + // "jsxFactory": "", /* Specify the JSX factory function used when targeting React JSX emit, e.g. 'React.createElement' or 'h'. */ + // "jsxFragmentFactory": "", /* Specify the JSX Fragment reference used for fragments when targeting React JSX emit e.g. 'React.Fragment' or 'Fragment'. */ + // "jsxImportSource": "", /* Specify module specifier used to import the JSX factory functions when using 'jsx: react-jsx*'. */ + // "reactNamespace": "", /* Specify the object invoked for 'createElement'. This only applies when targeting 'react' JSX emit. */ + // "noLib": true, /* Disable including any library files, including the default lib.d.ts. */ + // "useDefineForClassFields": true, /* Emit ECMAScript-standard-compliant class fields. */ + // "moduleDetection": "auto", /* Control what method is used to detect module-format JS files. */ + + /* Modules */ + "module": "commonjs", /* Specify what module code is generated. */ + // "rootDir": "./", /* Specify the root folder within your source files. */ + // "moduleResolution": "node10", /* Specify how TypeScript looks up a file from a given module specifier. */ + // "baseUrl": "./", /* Specify the base directory to resolve non-relative module names. */ + // "paths": {}, /* Specify a set of entries that re-map imports to additional lookup locations. */ + // "rootDirs": [], /* Allow multiple folders to be treated as one when resolving modules. */ + // "typeRoots": [], /* Specify multiple folders that act like './node_modules/@types'. */ + // "types": [], /* Specify type package names to be included without being referenced in a source file. */ + // "allowUmdGlobalAccess": true, /* Allow accessing UMD globals from modules. */ + // "moduleSuffixes": [], /* List of file name suffixes to search when resolving a module. */ + // "allowImportingTsExtensions": true, /* Allow imports to include TypeScript file extensions. Requires '--moduleResolution bundler' and either '--noEmit' or '--emitDeclarationOnly' to be set. */ + // "rewriteRelativeImportExtensions": true, /* Rewrite '.ts', '.tsx', '.mts', and '.cts' file extensions in relative import paths to their JavaScript equivalent in output files. */ + // "resolvePackageJsonExports": true, /* Use the package.json 'exports' field when resolving package imports. */ + // "resolvePackageJsonImports": true, /* Use the package.json 'imports' field when resolving imports. */ + // "customConditions": [], /* Conditions to set in addition to the resolver-specific defaults when resolving imports. */ + // "noUncheckedSideEffectImports": true, /* Check side effect imports. */ + // "resolveJsonModule": true, /* Enable importing .json files. */ + // "allowArbitraryExtensions": true, /* Enable importing files with any extension, provided a declaration file is present. */ + // "noResolve": true, /* Disallow 'import's, 'require's or ''s from expanding the number of files TypeScript should add to a project. */ + + /* JavaScript Support */ + // "allowJs": true, /* Allow JavaScript files to be a part of your program. Use the 'checkJS' option to get errors from these files. */ + // "checkJs": true, /* Enable error reporting in type-checked JavaScript files. */ + // "maxNodeModuleJsDepth": 1, /* Specify the maximum folder depth used for checking JavaScript files from 'node_modules'. Only applicable with 'allowJs'. */ + + /* Emit */ + // "declaration": true, /* Generate .d.ts files from TypeScript and JavaScript files in your project. */ + // "declarationMap": true, /* Create sourcemaps for d.ts files. */ + // "emitDeclarationOnly": true, /* Only output d.ts files and not JavaScript files. */ + // "sourceMap": true, /* Create source map files for emitted JavaScript files. */ + // "inlineSourceMap": true, /* Include sourcemap files inside the emitted JavaScript. */ + // "noEmit": true, /* Disable emitting files from a compilation. */ + // "outFile": "./", /* Specify a file that bundles all outputs into one JavaScript file. If 'declaration' is true, also designates a file that bundles all .d.ts output. */ + // "outDir": "./", /* Specify an output folder for all emitted files. */ + // "removeComments": true, /* Disable emitting comments. */ + // "importHelpers": true, /* Allow importing helper functions from tslib once per project, instead of including them per-file. */ + // "downlevelIteration": true, /* Emit more compliant, but verbose and less performant JavaScript for iteration. */ + // "sourceRoot": "", /* Specify the root path for debuggers to find the reference source code. */ + // "mapRoot": "", /* Specify the location where debugger should locate map files instead of generated locations. */ + // "inlineSources": true, /* Include source code in the sourcemaps inside the emitted JavaScript. */ + // "emitBOM": true, /* Emit a UTF-8 Byte Order Mark (BOM) in the beginning of output files. */ + // "newLine": "crlf", /* Set the newline character for emitting files. */ + // "stripInternal": true, /* Disable emitting declarations that have '@internal' in their JSDoc comments. */ + // "noEmitHelpers": true, /* Disable generating custom helper functions like '__extends' in compiled output. */ + // "noEmitOnError": true, /* Disable emitting files if any type checking errors are reported. */ + // "preserveConstEnums": true, /* Disable erasing 'const enum' declarations in generated code. */ + // "declarationDir": "./", /* Specify the output directory for generated declaration files. */ + + /* Interop Constraints */ + // "isolatedModules": true, /* Ensure that each file can be safely transpiled without relying on other imports. */ + // "verbatimModuleSyntax": true, /* Do not transform or elide any imports or exports not marked as type-only, ensuring they are written in the output file's format based on the 'module' setting. */ + // "isolatedDeclarations": true, /* Require sufficient annotation on exports so other tools can trivially generate declaration files. */ + // "allowSyntheticDefaultImports": true, /* Allow 'import x from y' when a module doesn't have a default export. */ + "esModuleInterop": true, /* Emit additional JavaScript to ease support for importing CommonJS modules. This enables 'allowSyntheticDefaultImports' for type compatibility. */ + // "preserveSymlinks": true, /* Disable resolving symlinks to their realpath. This correlates to the same flag in node. */ + "forceConsistentCasingInFileNames": true, /* Ensure that casing is correct in imports. */ + + /* Type Checking */ + "strict": true, /* Enable all strict type-checking options. */ + // "noImplicitAny": true, /* Enable error reporting for expressions and declarations with an implied 'any' type. */ + // "strictNullChecks": true, /* When type checking, take into account 'null' and 'undefined'. */ + // "strictFunctionTypes": true, /* When assigning functions, check to ensure parameters and the return values are subtype-compatible. */ + // "strictBindCallApply": true, /* Check that the arguments for 'bind', 'call', and 'apply' methods match the original function. */ + // "strictPropertyInitialization": true, /* Check for class properties that are declared but not set in the constructor. */ + // "strictBuiltinIteratorReturn": true, /* Built-in iterators are instantiated with a 'TReturn' type of 'undefined' instead of 'any'. */ + // "noImplicitThis": true, /* Enable error reporting when 'this' is given the type 'any'. */ + // "useUnknownInCatchVariables": true, /* Default catch clause variables as 'unknown' instead of 'any'. */ + // "alwaysStrict": true, /* Ensure 'use strict' is always emitted. */ + // "noUnusedLocals": true, /* Enable error reporting when local variables aren't read. */ + // "noUnusedParameters": true, /* Raise an error when a function parameter isn't read. */ + // "exactOptionalPropertyTypes": true, /* Interpret optional property types as written, rather than adding 'undefined'. */ + // "noImplicitReturns": true, /* Enable error reporting for codepaths that do not explicitly return in a function. */ + // "noFallthroughCasesInSwitch": true, /* Enable error reporting for fallthrough cases in switch statements. */ + // "noUncheckedIndexedAccess": true, /* Add 'undefined' to a type when accessed using an index. */ + // "noImplicitOverride": true, /* Ensure overriding members in derived classes are marked with an override modifier. */ + // "noPropertyAccessFromIndexSignature": true, /* Enforces using indexed accessors for keys declared using an indexed type. */ + // "allowUnusedLabels": true, /* Disable error reporting for unused labels. */ + // "allowUnreachableCode": true, /* Disable error reporting for unreachable code. */ + + /* Completeness */ + // "skipDefaultLibCheck": true, /* Skip type checking .d.ts files that are included with TypeScript. */ + "skipLibCheck": true /* Skip type checking all .d.ts files. */ + } +} diff --git a/flux_serve/src/README.md b/flux_serve/src/README.md new file mode 100644 index 0000000..7e7f6a6 --- /dev/null +++ b/flux_serve/src/README.md @@ -0,0 +1,11 @@ +# Compile Flux + +clean previous compilation +```bash +rm -rf decoder/compiler_workdir/ decoder/__pycache__/ text_encoder_1/compiler_workdir text_encoder_2/compiler_workdir/ text_encoder_2/compiler_workdir/ text_encoder_2/__pycache__/ transformer/compiler_workdir/ transformer/__pycache__/ transformer/compiled_model decoder/compiled_model text_encoder_1/compiled_model text_encoder_2/compiled_model/ text_encoder_1/__pycache__/ +``` +modify the shapes and:.... + +```bash +./compile.sh > compile.log 2>&1 & +``` diff --git a/flux_serve/src/compile.sh b/flux_serve/src/compile.sh new file mode 100755 index 0000000..40d4b2b --- /dev/null +++ b/flux_serve/src/compile.sh @@ -0,0 +1,10 @@ +#!/bin/bash +find . -type d \( -name "compiled_model" -o -name "__pycache__" -o -name "compiler_workdir" \) -exec rm -rf {} + + +myloc="$(dirname "$0")" + +python "$myloc/text_encoder_1/compile.py" +python "$myloc/text_encoder_2/compile.py" -m 32 +python "$myloc/transformer/compile.py" -hh 512 -w 512 -m 32 +python "$myloc/decoder/compile.py" -hh 512 -w 512 +echo "done!" diff --git a/flux_serve/src/decoder/compile.py b/flux_serve/src/decoder/compile.py new file mode 100644 index 0000000..51d7aaa --- /dev/null +++ b/flux_serve/src/decoder/compile.py @@ -0,0 +1,62 @@ +import argparse +import copy +import os +import torch +import torch_neuronx +from diffusers import FluxPipeline +from model import TracingVAEDecoderWrapper + +COMPILER_WORKDIR_ROOT = os.path.dirname(__file__) +DTYPE=torch.bfloat16 + +def trace_vae(height, width): + pipe = FluxPipeline.from_pretrained( + "black-forest-labs/FLUX.1-dev", + torch_dtype=torch.float32) + decoder = copy.deepcopy(pipe.vae.decoder) + decoder = TracingVAEDecoderWrapper(decoder) + del pipe + + latents = torch.rand([1, 16, height // 8, width // 8], + dtype=DTYPE) + + decoder_neuron = torch_neuronx.trace( + decoder, + latents, + compiler_workdir=os.path.join(COMPILER_WORKDIR_ROOT, + 'compiler_workdir'), + compiler_args="""--model-type=unet-inference""" + ) + + torch_neuronx.async_load(decoder_neuron) + + compiled_model_path = os.path.join(COMPILER_WORKDIR_ROOT, 'compiled_model') + if not os.path.exists(compiled_model_path): + os.mkdir(compiled_model_path) + decoder_filename = os.path.join(COMPILER_WORKDIR_ROOT, + 'compiled_model/model.pt') + torch.jit.save(decoder_neuron, decoder_filename) + + del decoder + del decoder_neuron + + +if __name__ == '__main__': + parser = argparse.ArgumentParser() + parser.add_argument( + "-hh", + "--height", + type=int, + default=1024, + help="height of images to be generated by compilation of this model" + ) + parser.add_argument( + "-w", + "--width", + type=int, + default=1024, + help="width of images to be generated by compilation of this model" + ) + args = parser.parse_args() + trace_vae(args.height, args.width) + diff --git a/flux_serve/src/decoder/model.py b/flux_serve/src/decoder/model.py new file mode 100644 index 0000000..43c24f6 --- /dev/null +++ b/flux_serve/src/decoder/model.py @@ -0,0 +1,19 @@ +import torch +import torch.nn as nn + +DTYPE=torch.bfloat16 + +class TracingVAEDecoderWrapper(nn.Module): + def __init__(self, decoder): + super().__init__() + self.decoder = decoder + + def forward( + self, + latents: torch.Tensor + ): + latents = latents.to(torch.float32) + return self.decoder( + latents + ) + diff --git a/flux_serve/src/inference.py b/flux_serve/src/inference.py new file mode 100644 index 0000000..57b4bc3 --- /dev/null +++ b/flux_serve/src/inference.py @@ -0,0 +1,232 @@ +import argparse +import torch +import torch.nn as nn +import torch_neuronx +import neuronx_distributed +import os + +from diffusers import FluxPipeline +from diffusers.models.modeling_outputs import Transformer2DModelOutput +from typing import Any, Dict, Optional, Union + +COMPILER_WORKDIR_ROOT = os.path.dirname(__file__) + +TEXT_ENCODER_PATH = os.path.join( + COMPILER_WORKDIR_ROOT, + 'text_encoder_1/compiled_model/model.pt') +TEXT_ENCODER_2_PATH = os.path.join( + COMPILER_WORKDIR_ROOT, + 'text_encoder_2/compiled_model/model.pt') +VAE_DECODER_PATH = os.path.join( + COMPILER_WORKDIR_ROOT, + 'decoder/compiled_model/model.pt') + +TEXT_ENCODER_2_DIR = os.path.join( + COMPILER_WORKDIR_ROOT, + 'text_encoder_2/compiled_model/text_encoder_2') +EMBEDDERS_DIR = os.path.join( + COMPILER_WORKDIR_ROOT, + 'transformer/compiled_model/embedders') +OUT_LAYERS_DIR = os.path.join( + COMPILER_WORKDIR_ROOT, + 'transformer/compiled_model/out_layers') +SINGLE_TRANSFORMER_BLOCKS_DIR = os.path.join( + COMPILER_WORKDIR_ROOT, + 'transformer/compiled_model/single_transformer_blocks') +TRANSFORMER_BLOCKS_DIR = os.path.join( + COMPILER_WORKDIR_ROOT, + 'transformer/compiled_model/transformer_blocks') + +class CustomFluxPipeline(FluxPipeline): + @property + def _execution_device(self): + return torch.device("cpu") + +class TextEncoder2Wrapper(nn.Module): + def __init__(self, sharded_model,dtype=torch.bfloat16): + super().__init__() + self.sharded_model = sharded_model + self.dtype = dtype + + def forward(self, input_ids, output_hidden_states=False, **kwargs): + attention_mask = (input_ids != 0).long() + output = self.sharded_model(input_ids,attention_mask) + last_hidden_state = output[0] + processed_output = last_hidden_state + return (processed_output,) + +class NeuronFluxTransformer2DModel(nn.Module): + def __init__( + self, + config, + x_embedder, + context_embedder + ): + super().__init__() + with torch_neuronx.experimental.neuron_cores_context(start_nc=0, nc_count=8): + self.embedders_model = neuronx_distributed.trace.parallel_model_load(EMBEDDERS_DIR) + self.out_layers_model = neuronx_distributed.trace.parallel_model_load(OUT_LAYERS_DIR) + self.transformer_blocks_model = neuronx_distributed.trace.parallel_model_load(TRANSFORMER_BLOCKS_DIR) + self.single_transformer_blocks_model = neuronx_distributed.trace.parallel_model_load(SINGLE_TRANSFORMER_BLOCKS_DIR) + + self.config = config + self.x_embedder = x_embedder + self.context_embedder = context_embedder + self.device = torch.device("cpu") + + def forward( + self, + hidden_states: torch.Tensor, + encoder_hidden_states: torch.Tensor = None, + pooled_projections: torch.Tensor = None, + timestep: torch.LongTensor = None, + img_ids: torch.Tensor = None, + txt_ids: torch.Tensor = None, + guidance: torch.Tensor = None, + joint_attention_kwargs: Optional[Dict[str, Any]] = None, + return_dict: bool = False, + ) -> Union[torch.FloatTensor, Transformer2DModelOutput]: + + hidden_states = self.x_embedder(hidden_states) + + hidden_states, temb, image_rotary_emb = self.embedders_model( + hidden_states, + timestep, + guidance, + pooled_projections, + txt_ids, + img_ids + ) + + encoder_hidden_states = self.context_embedder(encoder_hidden_states) + + image_rotary_emb = image_rotary_emb.type(torch.bfloat16) + + encoder_hidden_states, hidden_states = self.transformer_blocks_model( + hidden_states, + encoder_hidden_states, + temb, + image_rotary_emb + ) + + hidden_states = torch.cat([encoder_hidden_states, hidden_states], + dim=1) + + hidden_states = self.single_transformer_blocks_model( + hidden_states, + temb, + image_rotary_emb + ) + + hidden_states = hidden_states.to(torch.bfloat16) + + return self.out_layers_model( + hidden_states, + encoder_hidden_states, + temb + ) + + +class NeuronFluxCLIPTextEncoderModel(nn.Module): + def __init__(self, dtype, encoder): + super().__init__() + self.dtype = dtype + self.encoder = encoder + self.device = torch.device("cpu") + + def forward(self, emb, output_hidden_states): + output = self.encoder(emb) + output = CLIPEncoderOutput(output) + return output + + +class CLIPEncoderOutput(): + def __init__(self, dictionary): + self.pooler_output = dictionary["pooler_output"] + +def run_inference( + prompt, + height, + width, + max_sequence_length, + num_inference_steps): + + with torch_neuronx.experimental.neuron_cores_context(start_nc=8): + pipe = CustomFluxPipeline.from_pretrained( + "black-forest-labs/FLUX.1-dev", + torch_dtype=torch.bfloat16) + + with torch_neuronx.experimental.neuron_cores_context(start_nc=8): + pipe.text_encoder = NeuronFluxCLIPTextEncoderModel( + pipe.text_encoder.dtype, + torch.jit.load(TEXT_ENCODER_PATH)) + + with torch_neuronx.experimental.neuron_cores_context(start_nc=8): + pipe.vae.decoder = torch.jit.load(VAE_DECODER_PATH) + + with torch_neuronx.experimental.neuron_cores_context(start_nc=0, nc_count=8): + sharded_text_encoder_2 = neuronx_distributed.trace.parallel_model_load(TEXT_ENCODER_2_DIR) + pipe.text_encoder_2 = TextEncoder2Wrapper(sharded_text_encoder_2) + + + pipe.transformer = NeuronFluxTransformer2DModel( + pipe.transformer.config, + pipe.transformer.x_embedder, + pipe.transformer.context_embedder) + + image = pipe( + prompt, + height=height, + width=width, + guidance_scale=3.5, + num_inference_steps=num_inference_steps, + max_sequence_length=max_sequence_length + ).images[0] + image.save(os.path.join(COMPILER_WORKDIR_ROOT, "flux-dev.png")) + + +if __name__ == '__main__': + parser = argparse.ArgumentParser() + parser.add_argument( + "-p", + "--prompt", + type=str, + default="A cat holding a sign that says hello world", + help="prompt for image to be generated; generates cat by default" + ) + parser.add_argument( + "-hh", + "--height", + type=int, + default=256, + help="height of images to be generated by compilation of this model" + ) + parser.add_argument( + "-w", + "--width", + type=int, + default=256, + help="width of images to be generated by compilation of this model" + ) + parser.add_argument( + "-m", + "--max_sequence_length", + type=int, + default=32, + help="maximum sequence length for the text embeddings" + ) + parser.add_argument( + "-n", + "--num_inference_steps", + type=int, + default=50, + help="number of inference steps to run in generating image" + ) + args = parser.parse_args() + run_inference( + args.prompt, + args.height, + args.width, + args.max_sequence_length, + args.num_inference_steps) + diff --git a/flux_serve/src/inference.sh b/flux_serve/src/inference.sh new file mode 100755 index 0000000..51c4f60 --- /dev/null +++ b/flux_serve/src/inference.sh @@ -0,0 +1,5 @@ +#!/bin/bash + +myloc="$(dirname "$0")" + +python "$myloc/inference.py" -p "A cat holding a sign that says hello world" -hh 512 -w 512 -m 32 -n 50 diff --git a/flux_serve/src/text_encoder_1/compile.py b/flux_serve/src/text_encoder_1/compile.py new file mode 100644 index 0000000..84065b3 --- /dev/null +++ b/flux_serve/src/text_encoder_1/compile.py @@ -0,0 +1,45 @@ +import copy +import os +import torch +import torch_neuronx +from diffusers import FluxPipeline +from model import TracingCLIPTextEncoderWrapper + +COMPILER_WORKDIR_ROOT = os.path.dirname(__file__) +DTYPE=torch.bfloat16 + +def trace_text_encoder(): + pipe = FluxPipeline.from_pretrained( + "black-forest-labs/FLUX.1-dev", + torch_dtype=DTYPE) + text_encoder = copy.deepcopy(pipe.text_encoder) + del pipe + + text_encoder = TracingCLIPTextEncoderWrapper(text_encoder) + + emb = torch.zeros((1, 77), dtype=torch.int64) + + text_encoder_neuron = torch_neuronx.trace( + text_encoder.neuron_text_encoder, + emb, + compiler_workdir=os.path.join(COMPILER_WORKDIR_ROOT, + 'compiler_workdir'), + compiler_args=["--enable-fast-loading-neuron-binaries"] + ) + + torch_neuronx.async_load(text_encoder_neuron) + + compiled_model_path = os.path.join(COMPILER_WORKDIR_ROOT, 'compiled_model') + if not os.path.exists(compiled_model_path): + os.mkdir(compiled_model_path) + text_encoder_filename = os.path.join(COMPILER_WORKDIR_ROOT, + 'compiled_model/model.pt') + torch.jit.save(text_encoder_neuron, text_encoder_filename) + + del text_encoder + del text_encoder_neuron + + +if __name__ == '__main__': + trace_text_encoder() + diff --git a/flux_serve/src/text_encoder_1/model.py b/flux_serve/src/text_encoder_1/model.py new file mode 100644 index 0000000..c046b5c --- /dev/null +++ b/flux_serve/src/text_encoder_1/model.py @@ -0,0 +1,33 @@ +import torch +import torch.nn as nn +from transformers.modeling_outputs \ + import BaseModelOutputWithPooling +from typing import Optional, Union, Tuple + + +class TracingCLIPTextEncoderWrapper(nn.Module): + def __init__(self, text_encoder): + super().__init__() + self.neuron_text_encoder = text_encoder + self.config = text_encoder.config + self.dtype = text_encoder.dtype + self.device = text_encoder.device + + def forward( + self, + input_ids: Optional[torch.Tensor] = None, + attention_mask: Optional[torch.Tensor] = None, + position_ids: Optional[torch.Tensor] = None, + output_attentions: Optional[bool] = None, + output_hidden_states: Optional[bool] = False, + return_dict: Optional[bool] = True + ) -> Union[Tuple, BaseModelOutputWithPooling]: + + return self.neuron_text_encoder( + input_ids=input_ids, + attention_mask=attention_mask, + position_ids=position_ids, + output_attentions=output_attentions, + output_hidden_states=output_hidden_states, + return_dict=True, + ) diff --git a/flux_serve/src/text_encoder_2/compile.py b/flux_serve/src/text_encoder_2/compile.py new file mode 100644 index 0000000..74025f1 --- /dev/null +++ b/flux_serve/src/text_encoder_2/compile.py @@ -0,0 +1,86 @@ +import argparse +import copy +import os +import torch +import torch_neuronx +import neuronx_distributed +from diffusers import FluxPipeline +from transformers import T5EncoderModel + +from model import ( + TracingT5TextEncoderWrapper, + init_text_encoder_2, +) + +COMPILER_WORKDIR_ROOT = os.path.dirname(__file__) +TP_DEGREE=8 +DTYPE=torch.bfloat16 + +def build_text_encoder_2(): + """ + Build the T5 text encoder model, shard it, and wrap it in our tracing class. + Returns the final model + any (optional) kwargs in a dict, i.e. (model, {}). + This pattern is required by neuronx_distributed.trace.parallel_model_trace. + """ + # Load pipeline and copy the text_encoder_2 from your flux pipeline + pipe = FluxPipeline.from_pretrained( + "black-forest-labs/FLUX.1-dev", + torch_dtype=DTYPE + ) + # text_encoder_2 is presumably a T5EncoderModel or custom T5-based module + text_encoder_2 = copy.deepcopy(pipe.text_encoder_2) + del pipe + + # Optionally, if text_encoder_2 is not already a T5EncoderModel, you can + # modify the approach. But presumably, it's a T5EncoderModel or T5-like module. + # Shard the T5 model parameters across tp_degree ranks: + init_text_encoder_2(text_encoder_2) + + # Wrap it in a tracing module + wrapper = TracingT5TextEncoderWrapper(text_encoder_2) + + # Return the model plus optional kwargs (unused here) + return wrapper, {} + + +def trace_text_encoder_2(max_sequence_length=512): + """ + Trace the T5 text encoder with parallel model trace. + """ + input_ids = torch.zeros((1, max_sequence_length), dtype=torch.int64) + attention_mask = torch.ones((1, max_sequence_length), dtype=torch.int64) + + sample_inputs = (input_ids, attention_mask) + + model = neuronx_distributed.trace.parallel_model_trace( + build_text_encoder_2, + sample_inputs, + tp_degree=TP_DEGREE, + compiler_workdir=os.path.join(COMPILER_WORKDIR_ROOT, "compiler_workdir"), + compiler_args=["--enable-fast-loading-neuron-binaries"], + ) + + torch_neuronx.async_load(model) + + compiled_model_path = os.path.join(COMPILER_WORKDIR_ROOT, "compiled_model") + if not os.path.exists(compiled_model_path): + os.mkdir(compiled_model_path) + + model_filename = os.path.join(compiled_model_path, "text_encoder_2") + neuronx_distributed.trace.parallel_model_save(model, model_filename) + + del model + + +if __name__ == "__main__": + parser = argparse.ArgumentParser() + parser.add_argument( + "-m", + "--max_sequence_length", + type=int, + default=32, + help="maximum sequence length for the text embeddings" + ) + args = parser.parse_args() + trace_text_encoder_2(args.max_sequence_length) + diff --git a/flux_serve/src/text_encoder_2/model.py b/flux_serve/src/text_encoder_2/model.py new file mode 100644 index 0000000..3916ec5 --- /dev/null +++ b/flux_serve/src/text_encoder_2/model.py @@ -0,0 +1,215 @@ +import torch +import torch.nn as nn +from transformers.modeling_outputs import BaseModelOutput +from typing import Optional, Union, Tuple + +from neuronx_distributed.parallel_layers import parallel_state +from neuronx_distributed.parallel_layers.layers import ( + ColumnParallelLinear, + RowParallelLinear, +) + +DTYPE=torch.bfloat16 + +def get_sharded_data(data: torch.Tensor, dim: int) -> torch.Tensor: + """ + Utility function to slice a parameter across tensor-parallel ranks. + """ + tp_rank = parallel_state.get_tensor_model_parallel_rank() + tp_size = parallel_state.get_tensor_model_parallel_size() + per_partition_size = data.shape[dim] // tp_size + + if dim == 0: + return ( + data[per_partition_size * tp_rank : per_partition_size * (tp_rank + 1)] + .clone() + .to(DTYPE) + ) + elif dim == 1: + return ( + data[:, per_partition_size * tp_rank : per_partition_size * (tp_rank + 1)] + .clone() + .to(DTYPE) + ) + else: + raise ValueError("Partition dimension must be 0 or 1.") + +def shard_t5_attention(t5_attention): + """ + Shard the T5 self-attention q, k, v, o projections to ColumnParallel & RowParallel. + This is analogous to shard_attn() in transformer/model.py but adapted for T5. + """ + # Shard q + orig_q = t5_attention.q + t5_attention.q = ColumnParallelLinear( + orig_q.in_features, + orig_q.out_features, + bias=(orig_q.bias is not None), + gather_output=True + ) + t5_attention.q.weight.data = get_sharded_data(orig_q.weight.data, 0) + # T5 uses bias=False by default, but we handle it just in case + if orig_q.bias is not None: + t5_attention.q.bias.data = get_sharded_data(orig_q.bias.data, 0) + del orig_q + + # Shard k + orig_k = t5_attention.k + t5_attention.k = ColumnParallelLinear( + orig_k.in_features, + orig_k.out_features, + bias=(orig_k.bias is not None), + gather_output=True + ) + t5_attention.k.weight.data = get_sharded_data(orig_k.weight.data, 0) + if orig_k.bias is not None: + t5_attention.k.bias.data = get_sharded_data(orig_k.bias.data, 0) + del orig_k + + # Shard v + orig_v = t5_attention.v + t5_attention.v = ColumnParallelLinear( + orig_v.in_features, + orig_v.out_features, + bias=(orig_v.bias is not None), + gather_output=True + ) + t5_attention.v.weight.data = get_sharded_data(orig_v.weight.data, 0) + if orig_v.bias is not None: + t5_attention.v.bias.data = get_sharded_data(orig_v.bias.data, 0) + del orig_v + + # Shard o + orig_o = t5_attention.o + t5_attention.o = RowParallelLinear( + orig_o.in_features, + orig_o.out_features, + bias=(orig_o.bias is not None), + input_is_parallel=False + ) + t5_attention.o.weight.data = get_sharded_data(orig_o.weight.data, 1) + if orig_o.bias is not None: + t5_attention.o.bias.data = orig_o.bias.data.detach() + del orig_o + +def shard_t5_ff(ff_block): + """ + Shard the T5 feed-forward block (DenseReluDense or DenseGatedActDense). + Depending on the HF version, T5 may implement FF as: + - T5DenseReluDense, with attributes: ff_block.wi, ff_block.wo + - T5DenseGatedActDense, with attributes: ff_block.wi_0, ff_block.wi_1, ff_block.wo + We'll shard them similarly: + - ColumnParallel for the 'wi_*' inputs + - RowParallel for the 'wo' output + """ + + # Helper function for ColumnParallel + def make_column_parallel(orig_layer): + from neuronx_distributed.parallel_layers.layers import ColumnParallelLinear + new_layer = ColumnParallelLinear( + orig_layer.in_features, + orig_layer.out_features, + bias=(orig_layer.bias is not None), + gather_output=False + ) + new_layer.weight.data = get_sharded_data(orig_layer.weight.data, 0) + if orig_layer.bias is not None: + new_layer.bias.data = get_sharded_data(orig_layer.bias.data, 0) + return new_layer + + # Helper function for RowParallel + def make_row_parallel(orig_layer): + from neuronx_distributed.parallel_layers.layers import RowParallelLinear + new_layer = RowParallelLinear( + orig_layer.in_features, + orig_layer.out_features, + bias=(orig_layer.bias is not None), + input_is_parallel=True + ) + # For RowParallel, we shard dimension=1 + new_layer.weight.data = get_sharded_data(orig_layer.weight.data, 1) + if orig_layer.bias is not None: + new_layer.bias.data = orig_layer.bias.data.detach() + return new_layer + + # ------------------------------------------------------------- + # 1) T5DenseReluDense -> ff_block.wi, ff_block.wo + # ------------------------------------------------------------- + if hasattr(ff_block, "wi") and hasattr(ff_block, "wo"): + orig_wi = ff_block.wi + ff_block.wi = make_column_parallel(orig_wi) + del orig_wi + + orig_wo = ff_block.wo + ff_block.wo = make_row_parallel(orig_wo) + del orig_wo + + # ------------------------------------------------------------- + # 2) T5DenseGatedActDense -> ff_block.wi_0, ff_block.wi_1, ff_block.wo + # ------------------------------------------------------------- + elif hasattr(ff_block, "wi_0") and hasattr(ff_block, "wi_1") and hasattr(ff_block, "wo"): + orig_wi_0 = ff_block.wi_0 + ff_block.wi_0 = make_column_parallel(orig_wi_0) + del orig_wi_0 + + orig_wi_1 = ff_block.wi_1 + ff_block.wi_1 = make_column_parallel(orig_wi_1) + del orig_wi_1 + + orig_wo = ff_block.wo + ff_block.wo = make_row_parallel(orig_wo) + del orig_wo + + else: + raise ValueError( + f"Unsupported T5 FF block type: {type(ff_block).__name__}. " + f"Expected T5DenseReluDense or T5DenseGatedActDense." + ) + +def init_text_encoder_2(t5_encoder): + """ + Loop over T5Blocks in t5_encoder to shard the self-attention and FF modules. + Typically, T5EncoderModel has model.encoder.block[i].layer[0/1]. + """ + encoder_stack = t5_encoder.encoder # T5Stack + for block in encoder_stack.block: + # block.layer[0] => T5LayerSelfAttention + # block.layer[1] => T5LayerFF + attn = block.layer[0].SelfAttention + shard_t5_attention(attn) + ff = block.layer[1].DenseReluDense + shard_t5_ff(ff) + +class TracingT5TextEncoderWrapper(nn.Module): + """ + Wrap the T5 encoder in a forward that returns a stable tuple or BaseModelOutput, + suitable for compilation and serving on Neuron devices. + """ + def __init__(self, text_encoder): + super().__init__() + self.neuron_text_encoder = text_encoder + self.config = text_encoder.config + self.dtype = text_encoder.dtype + self.device = text_encoder.device + + def forward( + self, + input_ids: Optional[torch.LongTensor] = None, + attention_mask: Optional[torch.FloatTensor] = None, + head_mask: Optional[torch.FloatTensor] = None, + inputs_embeds: Optional[torch.FloatTensor] = None, + output_attentions: Optional[bool] = None, + output_hidden_states: Optional[bool] = False, + return_dict: Optional[bool] = False, + ) -> Union[Tuple[torch.FloatTensor], BaseModelOutput]: + + return self.neuron_text_encoder( + input_ids=input_ids, + attention_mask=attention_mask, + inputs_embeds=inputs_embeds, + head_mask=head_mask, + output_attentions=output_attentions, + output_hidden_states=output_hidden_states, + return_dict=return_dict, + ) + diff --git a/flux_serve/src/transformer/compile.py b/flux_serve/src/transformer/compile.py new file mode 100644 index 0000000..c33b21b --- /dev/null +++ b/flux_serve/src/transformer/compile.py @@ -0,0 +1,218 @@ +import argparse +import copy +import neuronx_distributed +import os +import torch +import torch_neuronx +from diffusers import FluxPipeline +from diffusers.models.transformers.transformer_flux \ + import FluxTransformer2DModel +from model import (TracingTransformerEmbedderWrapper, + TracingTransformerBlockWrapper, + TracingSingleTransformerBlockWrapper, + TracingTransformerOutLayerWrapper, + MyAttentionProcessor, + init_transformer) + +COMPILER_WORKDIR_ROOT = os.path.dirname(__file__) +TP_DEGREE=8 +DTYPE=torch.bfloat16 + +def trace_transformer_embedders(): + pipe = FluxPipeline.from_pretrained( + "black-forest-labs/FLUX.1-dev", + torch_dtype=DTYPE) + transformer: FluxTransformer2DModel = copy.deepcopy(pipe.transformer) + del pipe + init_transformer(transformer) + + mod_pipe_transformer_f = TracingTransformerEmbedderWrapper( + transformer.x_embedder, transformer.context_embedder, + transformer.time_text_embed, transformer.pos_embed) + return mod_pipe_transformer_f, {} + + +def trace_transformer_blocks(): + pipe = FluxPipeline.from_pretrained( + "black-forest-labs/FLUX.1-dev", + torch_dtype=DTYPE) + for block in pipe.transformer.transformer_blocks: + block.attn.processor = MyAttentionProcessor() + + transformer: FluxTransformer2DModel = copy.deepcopy(pipe.transformer) + del pipe + init_transformer(transformer) + + mod_pipe_transformer_f = TracingTransformerBlockWrapper( + transformer, transformer.transformer_blocks) + return mod_pipe_transformer_f, {} + + +def trace_single_transformer_blocks(): + pipe = FluxPipeline.from_pretrained( + "black-forest-labs/FLUX.1-dev", + torch_dtype=DTYPE) + for block in pipe.transformer.single_transformer_blocks: + block.attn.processor = MyAttentionProcessor() + transformer: FluxTransformer2DModel = copy.deepcopy(pipe.transformer) + del pipe + init_transformer(transformer) + + mod_pipe_transformer_f = TracingSingleTransformerBlockWrapper( + transformer, transformer.single_transformer_blocks) + return mod_pipe_transformer_f, {} + + +def trace_transformer_out_layers(): + pipe = FluxPipeline.from_pretrained( + "black-forest-labs/FLUX.1-dev", + torch_dtype=DTYPE) + transformer: FluxTransformer2DModel = copy.deepcopy(pipe.transformer) + del pipe + init_transformer(transformer) + + mod_pipe_transformer_f = TracingTransformerOutLayerWrapper( + transformer.norm_out, transformer.proj_out) + return mod_pipe_transformer_f, {} + + +def trace_transformer(height, width, max_sequence_length): + hidden_states = torch.rand([1, height * width // 256, 3072], + dtype=DTYPE) + timestep = torch.rand([1], dtype=DTYPE) + guidance = torch.rand([1], dtype=torch.float32) + pooled_projections = torch.rand([1, 768], dtype=DTYPE) + txt_ids = torch.rand([1, max_sequence_length, 3], dtype=DTYPE) + img_ids = torch.rand([1, height * width // 256, 3], dtype=DTYPE) + sample_inputs = hidden_states, timestep, guidance, pooled_projections, \ + txt_ids, img_ids + + model = neuronx_distributed.trace.parallel_model_trace( + trace_transformer_embedders, + sample_inputs, + tp_degree=TP_DEGREE, + compiler_workdir=os.path.join(COMPILER_WORKDIR_ROOT, + 'compiler_workdir'), + compiler_args="""--model-type=unet-inference""" + ) + + torch_neuronx.async_load(model) + + compiled_model_path = os.path.join(COMPILER_WORKDIR_ROOT, 'compiled_model') + if not os.path.exists(compiled_model_path): + os.mkdir(compiled_model_path) + model_filename = os.path.join(COMPILER_WORKDIR_ROOT, + 'compiled_model/embedders') + neuronx_distributed.trace.parallel_model_save(model, model_filename) + + del model + + hidden_states = torch.rand([1, height * width // 256, 3072], + dtype=DTYPE) + encoder_hidden_states = torch.rand([1, max_sequence_length, 3072], + dtype=DTYPE) + temb = torch.rand([1, 3072], dtype=DTYPE) + image_rotary_emb = torch.rand( + [1, 1, height * width // 256 + max_sequence_length, 64, 2, 2], + dtype=DTYPE) + sample_inputs = hidden_states, encoder_hidden_states, \ + temb, image_rotary_emb + + model = neuronx_distributed.trace.parallel_model_trace( + trace_transformer_blocks, + sample_inputs, + tp_degree=TP_DEGREE, + compiler_workdir=os.path.join(COMPILER_WORKDIR_ROOT, + 'compiler_workdir'), + compiler_args="""--model-type=unet-inference""" + ) + + torch_neuronx.async_load(model) + + model_filename = os.path.join(COMPILER_WORKDIR_ROOT, + 'compiled_model/transformer_blocks') + neuronx_distributed.trace.parallel_model_save(model, model_filename) + + del model + + hidden_states = torch.rand( + [1, height * width // 256 + max_sequence_length, 3072], + dtype=DTYPE) + temb = torch.rand([1, 3072], dtype=DTYPE) + image_rotary_emb = torch.rand( + [1, 1, height * width // 256 + max_sequence_length, 64, 2, 2], + dtype=DTYPE) + sample_inputs = hidden_states, temb, image_rotary_emb + + model = neuronx_distributed.trace.parallel_model_trace( + trace_single_transformer_blocks, + sample_inputs, + tp_degree=TP_DEGREE, + compiler_workdir=os.path.join(COMPILER_WORKDIR_ROOT, + 'compiler_workdir'), + compiler_args="""--model-type=unet-inference""" + ) + + torch_neuronx.async_load(model) + + model_filename = os.path.join(COMPILER_WORKDIR_ROOT, + 'compiled_model/single_transformer_blocks') + neuronx_distributed.trace.parallel_model_save(model, model_filename) + + del model + + hidden_states = torch.rand( + [1, height * width // 256 + max_sequence_length, 3072], + dtype=DTYPE) + encoder_hidden_states = torch.rand([1, max_sequence_length, 3072], + dtype=DTYPE) + temb = torch.rand([1, 3072], dtype=DTYPE) + sample_inputs = hidden_states, encoder_hidden_states, temb + + model = neuronx_distributed.trace.parallel_model_trace( + trace_transformer_out_layers, + sample_inputs, + tp_degree=TP_DEGREE, + compiler_workdir=os.path.join(COMPILER_WORKDIR_ROOT, + 'compiler_workdir'), + compiler_args="""--model-type=unet-inference""" + ) + + torch_neuronx.async_load(model) + + model_filename = os.path.join(COMPILER_WORKDIR_ROOT, + 'compiled_model/out_layers') + neuronx_distributed.trace.parallel_model_save(model, model_filename) + + del model + + +if __name__ == '__main__': + parser = argparse.ArgumentParser() + parser.add_argument( + "-hh", + "--height", + type=int, + default=256, + help="height of images to be generated by compilation of this model" + ) + parser.add_argument( + "-w", + "--width", + type=int, + default=256, + help="width of images to be generated by compilation of this model" + ) + parser.add_argument( + "-m", + "--max_sequence_length", + type=int, + default=32, + help="maximum sequence length for the text embeddings" + ) + args = parser.parse_args() + trace_transformer( + args.height, + args.width, + args.max_sequence_length) + diff --git a/flux_serve/src/transformer/model.py b/flux_serve/src/transformer/model.py new file mode 100644 index 0000000..f7ef7e4 --- /dev/null +++ b/flux_serve/src/transformer/model.py @@ -0,0 +1,475 @@ +import torch +import torch.nn as nn +from diffusers.models.attention import FeedForward +from diffusers.models.attention_processor import Attention +from diffusers.models.embeddings import TimestepEmbedding, \ + PixArtAlphaTextProjection +from neuronx_distributed.parallel_layers import parallel_state +from neuronx_distributed.parallel_layers.layers \ + import ColumnParallelLinear, RowParallelLinear + +from diffusers.models.attention_processor import AttnProcessor + +DTYPE=torch.bfloat16 + +class MyAttentionProcessor(AttnProcessor): + def __call__(self, attn, hidden_states,encoder_hidden_states=None,cross_attention_kwargs=None,**kwargs): + if hidden_states is not None: + # If norm_q has shape [128], we assume n_heads * 128 = hidden_states.shape[-1]. + n_heads = 24 # For example + head_dim = 128 + batch, seq_len, dim = hidden_states.shape + assert dim == n_heads * head_dim, f"Dim mismatch: got {dim}, expected {n_heads*head_dim}" + + # 1) [B, T, 3072] -> [B, T, n_heads, head_dim] = [B, T, 24, 128] + hidden_states = hidden_states.view(batch, seq_len, n_heads, head_dim) + # 2) Apply LN per-head + hidden_states = attn.norm_q(hidden_states) + # 3) Flatten back + hidden_states = hidden_states.view(batch, seq_len, dim) + return hidden_states, encoder_hidden_states + #return hidden_states + +class TracingTransformerEmbedderWrapper(nn.Module): + def __init__( + self, + x_embedder, + context_embedder, + time_text_embed, + pos_embed): + super().__init__() + self.x_embedder = x_embedder + self.context_embedder = context_embedder + self.time_text_embed = time_text_embed + self.pos_embed = pos_embed + + def forward( + self, + hidden_states, + timestep, + guidance, + pooled_projections, + txt_ids, + img_ids): + + timestep = timestep.to(hidden_states.dtype) * 1000 + if guidance is not None: + guidance = guidance.to(hidden_states.dtype) * 1000 + else: + guidance = None + temb = ( + self.time_text_embed(timestep, pooled_projections) + if guidance is None + else self.time_text_embed(timestep, guidance, pooled_projections) + ) + + ids = torch.cat((txt_ids, img_ids), dim=1) + image_rotary_emb = self.pos_embed(ids) + return hidden_states, temb, image_rotary_emb + + +class TracingTransformerBlockWrapper(nn.Module): + def __init__(self, transformer, transformerblock): + super().__init__() + self.transformerblock = transformerblock + self.config = transformer.config + self.dtype = transformer.dtype + self.device = transformer.device + + def forward( + self, + hidden_states, + encoder_hidden_states, + temb, + image_rotary_emb): + for block in self.transformerblock: + encoder_hidden_states, hidden_states = block( + hidden_states=hidden_states, + encoder_hidden_states=encoder_hidden_states, + temb=temb, + image_rotary_emb=image_rotary_emb + ) + return encoder_hidden_states, hidden_states + + +class TracingSingleTransformerBlockWrapper(nn.Module): + def __init__(self, transformer, transformerblock): + super().__init__() + self.transformerblock = transformerblock + self.config = transformer.config + self.dtype = transformer.dtype + self.device = transformer.device + + def forward(self, hidden_states, temb, image_rotary_emb): + for block in self.transformerblock: + hidden_states = block( + hidden_states=hidden_states, + temb=temb, + image_rotary_emb=image_rotary_emb + ) + return hidden_states + + +class TracingTransformerOutLayerWrapper(nn.Module): + def __init__(self, norm_out, proj_out): + super().__init__() + self.norm_out = norm_out + self.proj_out = proj_out + + def forward(self, hidden_states, encoder_hidden_states, temb): + hidden_states = hidden_states[:, encoder_hidden_states.shape[1]:, ...] + + hidden_states = self.norm_out(hidden_states, temb) + return (self.proj_out(hidden_states),) + + +class TracingSingleTransformerBlock(nn.Module): + def __init__(self): + super().__init__() + self.mlp_hidden_dim = None + + self.norm = None + self.proj_mlp = None + self.act_mlp = None + self.proj_out = None + self.proj_out_2 = None + + self.attn = None + + def forward( + self, + hidden_states: torch.FloatTensor, + temb: torch.FloatTensor, + image_rotary_emb=None, + ): + residual = hidden_states + norm_hidden_states, gate = self.norm(hidden_states, emb=temb) + mlp_hidden_states = self.act_mlp(self.proj_mlp(norm_hidden_states)) + + #attn_output = self.attn(hidden_states=norm_hidden_states,image_rotary_emb=image_rotary_emb,) + attn_output, cross_output = self.attn(hidden_states=norm_hidden_states, image_rotary_emb=image_rotary_emb) + gate = gate.unsqueeze(1) + hidden_states = gate * (self.proj_out(attn_output) + + self.proj_out_2(mlp_hidden_states)) + hidden_states = residual + hidden_states + if hidden_states.dtype == torch.float16: + hidden_states = hidden_states.clip(-65504, 65504) + print("norm_hidden_states.shape =", norm_hidden_states.shape) + out = self.proj_mlp(norm_hidden_states) + print("out.shape =", out.shape) + print("self.proj_mlp.bias.shape =", self.proj_mlp.bias.shape) + return hidden_states + + +def get_sharded_data(data, dim): + tp_rank = parallel_state.get_tensor_model_parallel_rank() + per_partition_size = \ + data.shape[dim] // parallel_state.get_tensor_model_parallel_size() + if dim == 0: + return data[ + per_partition_size * tp_rank: per_partition_size * (tp_rank + 1) + ].clone().to(DTYPE) + elif dim == 1: + return data[:, + per_partition_size * tp_rank: per_partition_size * + (tp_rank + 1) + ].clone().to(DTYPE) + else: + raise Exception( + f"Partiton value of 0,1 are supported, found {dim}." + ) + + +def shard_attn(attn: Attention): + #attn.heads = 3 + print("shard_attn -> attn.to_q.in_features =", attn.to_q.in_features) + print("shard_attn -> attn.norm_q.weight.shape =", attn.norm_q.weight.shape) + + orig_q = attn.to_q + attn.to_q = ColumnParallelLinear( + attn.to_q.in_features, + attn.to_q.out_features, + bias=(attn.to_q.bias is not None), + gather_output=True) + attn.to_q.weight.data = get_sharded_data(orig_q.weight.data, 0) + if attn.to_q.bias is not None: + attn.to_q.bias.data = get_sharded_data(orig_q.bias.data, 0) + del (orig_q) + + orig_k = attn.to_k + attn.to_k = ColumnParallelLinear( + attn.to_k.in_features, + attn.to_k.out_features, + bias=(attn.to_k.bias is not None), + gather_output=True) + attn.to_k.weight.data = get_sharded_data(orig_k.weight.data, 0) + if attn.to_k.bias is not None: + attn.to_k.bias.data = get_sharded_data(orig_k.bias.data, 0) + del (orig_k) + + orig_v = attn.to_v + attn.to_v = ColumnParallelLinear( + attn.to_v.in_features, + attn.to_v.out_features, + bias=(attn.to_v.bias is not None), + gather_output=True) + attn.to_v.weight.data = get_sharded_data(orig_v.weight.data, 0) + if attn.to_v.bias is not None: + attn.to_v.bias.data = get_sharded_data(orig_v.bias.data, 0) + del (orig_v) + + orig_q_proj = attn.add_q_proj + attn.add_q_proj = ColumnParallelLinear( + attn.add_q_proj.in_features, + attn.add_q_proj.out_features, + bias=(attn.add_q_proj.bias is not None), + gather_output=True) + attn.add_q_proj.weight.data = get_sharded_data(orig_q_proj.weight.data, 0) + if attn.add_q_proj.bias is not None: + attn.add_q_proj.bias.data = get_sharded_data(orig_q_proj.bias.data, 0) + del (orig_q_proj) + + orig_k_proj = attn.add_k_proj + attn.add_k_proj = ColumnParallelLinear( + attn.add_k_proj.in_features, + attn.add_k_proj.out_features, + bias=(attn.add_k_proj.bias is not None), + gather_output=True) + attn.add_k_proj.weight.data = get_sharded_data(orig_k_proj.weight.data, 0) + if attn.add_k_proj.bias is not None: + attn.add_k_proj.bias.data = get_sharded_data(orig_k_proj.bias.data, 0) + del (orig_k_proj) + + orig_v_proj = attn.add_v_proj + attn.add_v_proj = ColumnParallelLinear( + attn.add_v_proj.in_features, + attn.add_v_proj.out_features, + bias=(attn.add_v_proj.bias is not None), + gather_output=True) + attn.add_v_proj.weight.data = get_sharded_data(orig_v_proj.weight.data, 0) + if attn.add_v_proj.bias is not None: + attn.add_v_proj.bias.data = get_sharded_data(orig_v_proj.bias.data, 0) + del (orig_v_proj) + + orig_out = attn.to_out[0] + attn.to_out[0] = RowParallelLinear( + attn.to_out[0].in_features, + attn.to_out[0].out_features, + bias=(attn.to_out[0].bias is not None), + input_is_parallel=False) + attn.to_out[0].weight.data = get_sharded_data(orig_out.weight.data, 1) + if attn.to_out[0].bias is not None: + attn.to_out[0].bias.data = orig_out.bias.data.detach() + del (orig_out) + + orig_out = attn.to_add_out + attn.to_add_out = RowParallelLinear( + attn.to_add_out.in_features, + attn.to_add_out.out_features, + bias=(attn.to_add_out.bias is not None), + input_is_parallel=False) + attn.to_add_out.weight.data = get_sharded_data(orig_out.weight.data, 1) + if attn.to_add_out.bias is not None: + attn.to_add_out.bias.data = orig_out.bias.data.detach() + del (orig_out) + + return attn + + +def shard_attn_lite(block): + attn = block.attn + #attn.heads = 3 + + orig_q = attn.to_q + attn.to_q = ColumnParallelLinear( + attn.to_q.in_features, + attn.to_q.out_features, + bias=(attn.to_q.bias is not None), + gather_output=True) + attn.to_q.weight.data = get_sharded_data(orig_q.weight.data, 0) + if attn.to_q.bias is not None: + attn.to_q.bias.data = get_sharded_data(orig_q.bias.data, 0) + del (orig_q) + + orig_k = attn.to_k + attn.to_k = ColumnParallelLinear( + attn.to_k.in_features, + attn.to_k.out_features, + bias=(attn.to_k.bias is not None), + gather_output=True) + attn.to_k.weight.data = get_sharded_data(orig_k.weight.data, 0) + if attn.to_k.bias is not None: + attn.to_k.bias.data = get_sharded_data(orig_k.bias.data, 0) + del (orig_k) + + orig_v = attn.to_v + attn.to_v = ColumnParallelLinear( + attn.to_v.in_features, + attn.to_v.out_features, + bias=(attn.to_v.bias is not None), + gather_output=True) + attn.to_v.weight.data = get_sharded_data(orig_v.weight.data, 0) + if attn.to_v.bias is not None: + attn.to_v.bias.data = get_sharded_data(orig_v.bias.data, 0) + del (orig_v) + + orig_mlp = block.proj_mlp + block.proj_mlp = ColumnParallelLinear( + block.proj_mlp.in_features, + block.proj_mlp.out_features, + bias=(block.proj_mlp.bias is not None), + gather_output=False) + #print("proj_mlp in_features:", block.proj_mlp.in_features) + #print("proj_mlp out_features:", block.proj_mlp.out_features) + print("proj_mlp.bias.shape:", block.proj_mlp.bias.shape) + block.proj_mlp.weight.data = get_sharded_data(orig_mlp.weight.data, 0) + if block.proj_mlp.bias is not None: + block.proj_mlp.bias.data = get_sharded_data(orig_mlp.bias.data, 0) + del (orig_mlp) + + orig_out = block.proj_out + out_features = block.proj_out.out_features + bias = block.proj_out.bias + block.proj_out = RowParallelLinear( + 3072, + out_features, + bias=(bias is not None), + input_is_parallel=True) + block.proj_out.weight.data = get_sharded_data( + orig_out.weight.data[..., 0:3072], 1) + if block.proj_out.bias is not None: + block.proj_out.bias.data = orig_out.bias.data.detach() + + block.proj_out_2 = RowParallelLinear( + 12288, + out_features, + bias=False, + input_is_parallel=True) + block.proj_out_2.weight.data = get_sharded_data( + orig_out.weight.data[..., 3072:15360], 1) + del (orig_out) + + return attn + + +def shard_ff(ff: FeedForward) -> FeedForward: + orig_proj = ff.net[0].proj + ff.net[0].proj = ColumnParallelLinear( + ff.net[0].proj.in_features, + ff.net[0].proj.out_features, + bias=(ff.net[0].proj.bias is not None), + gather_output=False) + ff.net[0].proj.weight.data = get_sharded_data(orig_proj.weight.data, 0) + if ff.net[0].proj.bias is not None: + ff.net[0].proj.bias.data = get_sharded_data(orig_proj.bias.data, 0) + del (orig_proj) + orig_linear = ff.net[2] + ff.net[2] = RowParallelLinear( + ff.net[2].in_features, + ff.net[2].out_features, + bias=(ff.net[2].bias is not None), + input_is_parallel=True) + if ff.net[2].bias is not None: + ff.net[2].bias.data = orig_linear.bias.data.detach() + ff.net[2].weight.data = get_sharded_data(orig_linear.weight.data, 1) + del (orig_linear) + return ff + + +def init_transformer(transformer): + timestep_embedder: TimestepEmbedding = \ + transformer.time_text_embed.timestep_embedder + orig_linear_1 = timestep_embedder.linear_1 + timestep_embedder.linear_1 = ColumnParallelLinear( + timestep_embedder.linear_1.in_features, + timestep_embedder.linear_1.out_features, + bias=(timestep_embedder.linear_1.bias is not None), + gather_output=False) + timestep_embedder.linear_1.weight.data = \ + get_sharded_data(orig_linear_1.weight.data, 0) + if timestep_embedder.linear_1.bias is not None: + timestep_embedder.linear_1.bias.data = \ + get_sharded_data(orig_linear_1.bias.data, 0) + del (orig_linear_1) + orig_linear_2 = timestep_embedder.linear_2 + timestep_embedder.linear_2 = RowParallelLinear( + timestep_embedder.linear_2.in_features, + timestep_embedder.linear_2.out_features, + bias=(timestep_embedder.linear_2.bias is not None), + input_is_parallel=True) + if timestep_embedder.linear_2.bias is not None: + timestep_embedder.linear_2.bias.data = orig_linear_2.bias.data.detach() + timestep_embedder.linear_2.weight.data = \ + get_sharded_data(orig_linear_2.weight.data, 1) + del (orig_linear_2) + + guidance_embedder: TimestepEmbedding = \ + transformer.time_text_embed.guidance_embedder + orig_linear_1 = guidance_embedder.linear_1 + guidance_embedder.linear_1 = ColumnParallelLinear( + guidance_embedder.linear_1.in_features, + guidance_embedder.linear_1.out_features, + bias=(guidance_embedder.linear_1.bias is not None), + gather_output=False) + guidance_embedder.linear_1.weight.data = \ + get_sharded_data(orig_linear_1.weight.data, 0) + if guidance_embedder.linear_1.bias is not None: + guidance_embedder.linear_1.bias.data = \ + get_sharded_data(orig_linear_1.bias.data, 0) + del (orig_linear_1) + orig_linear_2 = guidance_embedder.linear_2 + guidance_embedder.linear_2 = RowParallelLinear( + guidance_embedder.linear_2.in_features, + guidance_embedder.linear_2.out_features, + bias=(guidance_embedder.linear_2.bias is not None), + input_is_parallel=True) + if guidance_embedder.linear_2.bias is not None: + guidance_embedder.linear_2.bias.data = orig_linear_2.bias.data.detach() + guidance_embedder.linear_2.weight.data = \ + get_sharded_data(orig_linear_2.weight.data, 1) + del (orig_linear_2) + + text_embedder: PixArtAlphaTextProjection = \ + transformer.time_text_embed.text_embedder + orig_linear_1 = text_embedder.linear_1 + text_embedder.linear_1 = ColumnParallelLinear( + text_embedder.linear_1.in_features, + text_embedder.linear_1.out_features, + bias=(text_embedder.linear_1.bias is not None), + gather_output=False) + text_embedder.linear_1.weight.data = \ + get_sharded_data(orig_linear_1.weight.data, 0) + if text_embedder.linear_1.bias is not None: + text_embedder.linear_1.bias.data = \ + get_sharded_data(orig_linear_1.bias.data, 0) + del (orig_linear_1) + orig_linear_2 = text_embedder.linear_2 + text_embedder.linear_2 = RowParallelLinear( + text_embedder.linear_2.in_features, + text_embedder.linear_2.out_features, + bias=(text_embedder.linear_2.bias is not None), + input_is_parallel=True) + if text_embedder.linear_2.bias is not None: + text_embedder.linear_2.bias.data = orig_linear_2.bias.data.detach() + text_embedder.linear_2.weight.data = \ + get_sharded_data(orig_linear_2.weight.data, 1) + del (orig_linear_2) + + for block_idx, block in enumerate(transformer.transformer_blocks): + block.attn = shard_attn(block.attn) + block.ff = shard_ff(block.ff) + block.ff_context = shard_ff(block.ff_context) + + for block_idx, block in enumerate(transformer.single_transformer_blocks): + newblock = TracingSingleTransformerBlock() + newblock.mlp_hidden_dim = block.mlp_hidden_dim + newblock.norm = block.norm + newblock.proj_mlp = block.proj_mlp + newblock.act_mlp = block.act_mlp + newblock.proj_out = block.proj_out + newblock.proj_out_2 = None + newblock.attn = block.attn + transformer.single_transformer_blocks[block_idx] = newblock + block = newblock + block.attn = shard_attn_lite(block) + From c1d6e2a202d73f6f1ee3271fc87201d5019f0063 Mon Sep 17 00:00:00 2001 From: Yahav Date: Wed, 1 Jan 2025 14:32:55 -0800 Subject: [PATCH 02/45] gitignore --- flux_serve/app/.Dockerfile.template.swp | Bin 0 -> 12288 bytes flux_serve/oci-image-build/cdk.out/cdk.out | 1 - .../flux-oci-image-inference-cdk.assets.json | 20 - ...flux-oci-image-inference-cdk.template.json | 1960 ------------- .../oci-image-build/cdk.out/manifest.json | 357 --- flux_serve/oci-image-build/cdk.out/tree.json | 2599 ----------------- 6 files changed, 4937 deletions(-) create mode 100644 flux_serve/app/.Dockerfile.template.swp delete mode 100644 flux_serve/oci-image-build/cdk.out/cdk.out delete mode 100644 flux_serve/oci-image-build/cdk.out/flux-oci-image-inference-cdk.assets.json delete mode 100644 flux_serve/oci-image-build/cdk.out/flux-oci-image-inference-cdk.template.json delete mode 100644 flux_serve/oci-image-build/cdk.out/manifest.json delete mode 100644 flux_serve/oci-image-build/cdk.out/tree.json diff --git a/flux_serve/app/.Dockerfile.template.swp b/flux_serve/app/.Dockerfile.template.swp new file mode 100644 index 0000000000000000000000000000000000000000..48e6538384097f669d2d60a8819350181d13da43 GIT binary patch literal 12288 zcmeI2!A=xG5QZDhq6YQgtzAt>Bs~KxppbAtMMDBYAeazBNY6~oY-eX@+U}lZHzFRr z_!u6HkKnJ>ht(jdAlq`BwtFwPP+g(#t{Z-9jvmH!4SzhIH-Xz0unXy;z zi{$Oqr!0QQSXVY=J192>k2_&ppN?QAuFp;nvOMfL^yR)485AbZ1T?L%vZYh7ew-Ga zJqxA{zSP=(kcUk$u}Z;nfELohAm_A41c<;n1V&hWYI349x>>uyuZ(V;V^7;efCvx) zB0vO)01+SpM1TnVO9Y%AVlVJO!~H{D>(4_!&Hb-55dk7V1c(3;AOb{y2oM1xKm>>Y z5g-D8ApsdNHhO`vLsa?y|IzRNua_A6g8GQsM$MzHqrP2a>=Wt@>HxKZnnlf^YN%n< zvk}HVqrVTR*Ql4M(*JW54I)4UhyW2F0z`la5CI}U1pZe7_t)09`EBmAjjhMLSp*Qe zl()fHm1kUtFjbJbYEx<_5^!8)*2y&GqI+b2YP--;c~7`>2Vo=UV-W;=$EqZQNCe#l zA6$sHi=E$uu2ETH{W7Y_z=0KIjQ+Zp=wz2SoYQvR_jNO|Uh}T?RPKklfq5U32vVHe zlit*vk3oFykMRTU0QhkXn-?Yo>!r#%FFFyaTB(u@3xj8g?dHlK1>1lWqy-PN#h{og z!iqqeR&Kb+e`N3*r>xRwH6w*j>NB1^3vacil|HUU399qUYNX=0zzf}WVPV3n9h^46O!O)QYykvSmAHm_^b= zyR`wY>b!^N52K(5k)%F=pTP`^xGplpsMAcwClp+M", - "Default": "/cdk-bootstrap/hnb659fds/version", - "Description": "Version of the CDK Bootstrap resources in this environment, automatically retrieved from SSM Parameter Store. [cdk:skip]" - } - }, - "Resources": { - "baserepoCCF23216": { - "Type": "AWS::ECR::Repository", - "Properties": { - "ImageScanningConfiguration": { - "ScanOnPush": true - }, - "RepositoryName": { - "Ref": "BASEREPO" - } - }, - "UpdateReplacePolicy": "Retain", - "DeletionPolicy": "Retain", - "Metadata": { - "aws:cdk:path": "flux-oci-image-inference-cdk/base_repo/Resource" - } - }, - "BaseCodeBuildDeployRole2A53BD0D": { - "Type": "AWS::IAM::Role", - "Properties": { - "AssumeRolePolicyDocument": { - "Statement": [ - { - "Action": "sts:AssumeRole", - "Effect": "Allow", - "Principal": { - "Service": "codebuild.amazonaws.com" - } - } - ], - "Version": "2012-10-17" - }, - "RoleName": "hwagnisticBaseCodeBuildDeployRole" - }, - "Metadata": { - "aws:cdk:path": "flux-oci-image-inference-cdk/BaseCodeBuildDeployRole/Resource" - } - }, - "BaseCodeBuildDeployRoleDefaultPolicy93D8F557": { - "Type": "AWS::IAM::Policy", - "Properties": { - "PolicyDocument": { - "Statement": [ - { - "Action": [ - "ssm:*", - "s3:*" - ], - "Effect": "Allow", - "Resource": "*" - }, - { - "Action": [ - "logs:CreateLogGroup", - "logs:CreateLogStream", - "logs:PutLogEvents" - ], - "Effect": "Allow", - "Resource": [ - { - "Fn::Join": [ - "", - [ - "arn:", - { - "Ref": "AWS::Partition" - }, - ":logs:us-west-2:133573815653:log-group:/aws/codebuild/", - { - "Ref": "ImageCudAmdBuild23EA25C8" - } - ] - ] - }, - { - "Fn::Join": [ - "", - [ - "arn:", - { - "Ref": "AWS::Partition" - }, - ":logs:us-west-2:133573815653:log-group:/aws/codebuild/", - { - "Ref": "ImageCudAmdBuild23EA25C8" - }, - ":*" - ] - ] - } - ] - }, - { - "Action": [ - "codebuild:CreateReportGroup", - "codebuild:CreateReport", - "codebuild:UpdateReport", - "codebuild:BatchPutTestCases", - "codebuild:BatchPutCodeCoverages" - ], - "Effect": "Allow", - "Resource": { - "Fn::Join": [ - "", - [ - "arn:", - { - "Ref": "AWS::Partition" - }, - ":codebuild:us-west-2:133573815653:report-group/", - { - "Ref": "ImageCudAmdBuild23EA25C8" - }, - "-*" - ] - ] - } - }, - { - "Action": [ - "logs:CreateLogGroup", - "logs:CreateLogStream", - "logs:PutLogEvents" - ], - "Effect": "Allow", - "Resource": [ - { - "Fn::Join": [ - "", - [ - "arn:", - { - "Ref": "AWS::Partition" - }, - ":logs:us-west-2:133573815653:log-group:/aws/codebuild/", - { - "Ref": "ImageCpuArmBuild4791F7AA" - } - ] - ] - }, - { - "Fn::Join": [ - "", - [ - "arn:", - { - "Ref": "AWS::Partition" - }, - ":logs:us-west-2:133573815653:log-group:/aws/codebuild/", - { - "Ref": "ImageCpuArmBuild4791F7AA" - }, - ":*" - ] - ] - } - ] - }, - { - "Action": [ - "codebuild:CreateReportGroup", - "codebuild:CreateReport", - "codebuild:UpdateReport", - "codebuild:BatchPutTestCases", - "codebuild:BatchPutCodeCoverages" - ], - "Effect": "Allow", - "Resource": { - "Fn::Join": [ - "", - [ - "arn:", - { - "Ref": "AWS::Partition" - }, - ":codebuild:us-west-2:133573815653:report-group/", - { - "Ref": "ImageCpuArmBuild4791F7AA" - }, - "-*" - ] - ] - } - }, - { - "Action": [ - "logs:CreateLogGroup", - "logs:CreateLogStream", - "logs:PutLogEvents" - ], - "Effect": "Allow", - "Resource": [ - { - "Fn::Join": [ - "", - [ - "arn:", - { - "Ref": "AWS::Partition" - }, - ":logs:us-west-2:133573815653:log-group:/aws/codebuild/", - { - "Ref": "ImageXlaAmdBuild7511085C" - } - ] - ] - }, - { - "Fn::Join": [ - "", - [ - "arn:", - { - "Ref": "AWS::Partition" - }, - ":logs:us-west-2:133573815653:log-group:/aws/codebuild/", - { - "Ref": "ImageXlaAmdBuild7511085C" - }, - ":*" - ] - ] - } - ] - }, - { - "Action": [ - "codebuild:CreateReportGroup", - "codebuild:CreateReport", - "codebuild:UpdateReport", - "codebuild:BatchPutTestCases", - "codebuild:BatchPutCodeCoverages" - ], - "Effect": "Allow", - "Resource": { - "Fn::Join": [ - "", - [ - "arn:", - { - "Ref": "AWS::Partition" - }, - ":codebuild:us-west-2:133573815653:report-group/", - { - "Ref": "ImageXlaAmdBuild7511085C" - }, - "-*" - ] - ] - } - }, - { - "Action": [ - "logs:CreateLogGroup", - "logs:CreateLogStream", - "logs:PutLogEvents" - ], - "Effect": "Allow", - "Resource": [ - { - "Fn::Join": [ - "", - [ - "arn:", - { - "Ref": "AWS::Partition" - }, - ":logs:us-west-2:133573815653:log-group:/aws/codebuild/", - { - "Ref": "AssetsImageXlaAmdBuild4E3D098F" - } - ] - ] - }, - { - "Fn::Join": [ - "", - [ - "arn:", - { - "Ref": "AWS::Partition" - }, - ":logs:us-west-2:133573815653:log-group:/aws/codebuild/", - { - "Ref": "AssetsImageXlaAmdBuild4E3D098F" - }, - ":*" - ] - ] - } - ] - }, - { - "Action": [ - "codebuild:CreateReportGroup", - "codebuild:CreateReport", - "codebuild:UpdateReport", - "codebuild:BatchPutTestCases", - "codebuild:BatchPutCodeCoverages" - ], - "Effect": "Allow", - "Resource": { - "Fn::Join": [ - "", - [ - "arn:", - { - "Ref": "AWS::Partition" - }, - ":codebuild:us-west-2:133573815653:report-group/", - { - "Ref": "AssetsImageXlaAmdBuild4E3D098F" - }, - "-*" - ] - ] - } - }, - { - "Action": [ - "logs:CreateLogGroup", - "logs:CreateLogStream", - "logs:PutLogEvents" - ], - "Effect": "Allow", - "Resource": [ - { - "Fn::Join": [ - "", - [ - "arn:", - { - "Ref": "AWS::Partition" - }, - ":logs:us-west-2:133573815653:log-group:/aws/codebuild/", - { - "Ref": "AssetsImageCpuArmBuildBC43C501" - } - ] - ] - }, - { - "Fn::Join": [ - "", - [ - "arn:", - { - "Ref": "AWS::Partition" - }, - ":logs:us-west-2:133573815653:log-group:/aws/codebuild/", - { - "Ref": "AssetsImageCpuArmBuildBC43C501" - }, - ":*" - ] - ] - } - ] - }, - { - "Action": [ - "codebuild:CreateReportGroup", - "codebuild:CreateReport", - "codebuild:UpdateReport", - "codebuild:BatchPutTestCases", - "codebuild:BatchPutCodeCoverages" - ], - "Effect": "Allow", - "Resource": { - "Fn::Join": [ - "", - [ - "arn:", - { - "Ref": "AWS::Partition" - }, - ":codebuild:us-west-2:133573815653:report-group/", - { - "Ref": "AssetsImageCpuArmBuildBC43C501" - }, - "-*" - ] - ] - } - }, - { - "Action": [ - "logs:CreateLogGroup", - "logs:CreateLogStream", - "logs:PutLogEvents" - ], - "Effect": "Allow", - "Resource": [ - { - "Fn::Join": [ - "", - [ - "arn:", - { - "Ref": "AWS::Partition" - }, - ":logs:us-west-2:133573815653:log-group:/aws/codebuild/", - { - "Ref": "AssetsImageCudAmdBuild4322D558" - } - ] - ] - }, - { - "Fn::Join": [ - "", - [ - "arn:", - { - "Ref": "AWS::Partition" - }, - ":logs:us-west-2:133573815653:log-group:/aws/codebuild/", - { - "Ref": "AssetsImageCudAmdBuild4322D558" - }, - ":*" - ] - ] - } - ] - }, - { - "Action": [ - "codebuild:CreateReportGroup", - "codebuild:CreateReport", - "codebuild:UpdateReport", - "codebuild:BatchPutTestCases", - "codebuild:BatchPutCodeCoverages" - ], - "Effect": "Allow", - "Resource": { - "Fn::Join": [ - "", - [ - "arn:", - { - "Ref": "AWS::Partition" - }, - ":codebuild:us-west-2:133573815653:report-group/", - { - "Ref": "AssetsImageCudAmdBuild4322D558" - }, - "-*" - ] - ] - } - }, - { - "Action": [ - "ecr:BatchCheckLayerAvailability", - "ecr:GetDownloadUrlForLayer", - "ecr:BatchGetImage", - "ecr:CompleteLayerUpload", - "ecr:UploadLayerPart", - "ecr:InitiateLayerUpload", - "ecr:PutImage" - ], - "Effect": "Allow", - "Resource": { - "Fn::GetAtt": [ - "baserepoCCF23216", - "Arn" - ] - } - }, - { - "Action": "ecr:GetAuthorizationToken", - "Effect": "Allow", - "Resource": "*" - }, - { - "Action": [ - "s3:GetObject*", - "s3:GetBucket*", - "s3:List*" - ], - "Effect": "Allow", - "Resource": [ - { - "Fn::GetAtt": [ - "BuildBasePipelineArtifactsBucket51786A86", - "Arn" - ] - }, - { - "Fn::Join": [ - "", - [ - { - "Fn::GetAtt": [ - "BuildBasePipelineArtifactsBucket51786A86", - "Arn" - ] - }, - "/*" - ] - ] - } - ] - }, - { - "Action": [ - "kms:Decrypt", - "kms:DescribeKey" - ], - "Effect": "Allow", - "Resource": { - "Fn::GetAtt": [ - "BuildBasePipelineArtifactsBucketEncryptionKey04467E09", - "Arn" - ] - } - }, - { - "Action": [ - "kms:Decrypt", - "kms:Encrypt", - "kms:ReEncrypt*", - "kms:GenerateDataKey*" - ], - "Effect": "Allow", - "Resource": { - "Fn::GetAtt": [ - "BuildBasePipelineArtifactsBucketEncryptionKey04467E09", - "Arn" - ] - } - } - ], - "Version": "2012-10-17" - }, - "PolicyName": "BaseCodeBuildDeployRoleDefaultPolicy93D8F557", - "Roles": [ - { - "Ref": "BaseCodeBuildDeployRole2A53BD0D" - } - ] - }, - "Metadata": { - "aws:cdk:path": "flux-oci-image-inference-cdk/BaseCodeBuildDeployRole/DefaultPolicy/Resource" - } - }, - "githubSecret7D37FCC7": { - "Type": "AWS::SecretsManager::Secret", - "Properties": { - "SecretString": { - "Fn::Join": [ - "", - [ - "{\"token\":\"", - { - "Ref": "GITHUBOAUTHTOKEN" - }, - "\"}" - ] - ] - } - }, - "UpdateReplacePolicy": "Delete", - "DeletionPolicy": "Delete", - "Metadata": { - "aws:cdk:path": "flux-oci-image-inference-cdk/githubSecret/Resource" - } - }, - "ImageCudAmdBuild23EA25C8": { - "Type": "AWS::CodeBuild::Project", - "Properties": { - "Artifacts": { - "Type": "NO_ARTIFACTS" - }, - "Cache": { - "Modes": [ - "LOCAL_DOCKER_LAYER_CACHE", - "LOCAL_CUSTOM_CACHE" - ], - "Type": "LOCAL" - }, - "EncryptionKey": { - "Fn::GetAtt": [ - "BuildBasePipelineArtifactsBucketEncryptionKey04467E09", - "Arn" - ] - }, - "Environment": { - "ComputeType": "BUILD_GENERAL1_SMALL", - "Image": "aws/codebuild/amazonlinux2-x86_64-standard:3.0", - "ImagePullCredentialsType": "CODEBUILD", - "PrivilegedMode": true, - "Type": "LINUX_CONTAINER" - }, - "ServiceRole": { - "Fn::GetAtt": [ - "BaseCodeBuildDeployRole2A53BD0D", - "Arn" - ] - }, - "Source": { - "BuildSpec": { - "Fn::Join": [ - "", - [ - "{\n \"version\": \"0.2\",\n \"env\": {\n \"exported-variables\": [\n \"AWS_ACCOUNT_ID\",\n \"AWS_REGION\",\n \"BASE_REPO\",\n \"IMAGE_AMD_CUD_TAG\",\n \"BASE_IMAGE_AMD_CUD_TAG\"\n ]\n },\n \"phases\": {\n \"build\": {\n \"commands\": [\n \"export AWS_ACCOUNT_ID=\\\"133573815653\\\"\",\n \"export AWS_REGION=\\\"us-west-2\\\"\",\n \"export BASE_REPO=\\\"", - { - "Ref": "BASEREPO" - }, - "\\\"\",\n \"export IMAGE_TAG=\\\"", - { - "Ref": "IMAGEAMDCUDTAG" - }, - "\\\"\",\n \"export BASE_IMAGE_TAG=\\\"", - { - "Ref": "BASEIMAGEAMDCUDTAG" - }, - "\\\"\",\n \"cd app\",\n \"chmod +x ./build.sh && ./build.sh\"\n ]\n }\n },\n \"artifacts\": {\n \"files\": [\n \"imageDetail.json\"\n ]\n }\n}" - ] - ] - }, - "Type": "NO_SOURCE" - } - }, - "Metadata": { - "aws:cdk:path": "flux-oci-image-inference-cdk/ImageCudAmdBuild/Resource" - } - }, - "ImageCpuArmBuild4791F7AA": { - "Type": "AWS::CodeBuild::Project", - "Properties": { - "Artifacts": { - "Type": "NO_ARTIFACTS" - }, - "Cache": { - "Modes": [ - "LOCAL_DOCKER_LAYER_CACHE", - "LOCAL_CUSTOM_CACHE" - ], - "Type": "LOCAL" - }, - "EncryptionKey": { - "Fn::GetAtt": [ - "BuildBasePipelineArtifactsBucketEncryptionKey04467E09", - "Arn" - ] - }, - "Environment": { - "ComputeType": "BUILD_GENERAL1_LARGE", - "Image": "aws/codebuild/amazonlinux2-aarch64-standard:2.0", - "ImagePullCredentialsType": "CODEBUILD", - "PrivilegedMode": true, - "Type": "ARM_CONTAINER" - }, - "ServiceRole": { - "Fn::GetAtt": [ - "BaseCodeBuildDeployRole2A53BD0D", - "Arn" - ] - }, - "Source": { - "BuildSpec": { - "Fn::Join": [ - "", - [ - "{\n \"version\": \"0.2\",\n \"env\": {\n \"exported-variables\": [\n \"AWS_ACCOUNT_ID\",\n \"AWS_REGION\",\n \"BASE_REPO\",\n \"IMAGE_ARM_CPU_TAG\",\n \"BASE_IMAGE_ARM_CPU_TAG\"\n ]\n },\n \"phases\": {\n \"build\": {\n \"commands\": [\n \"export AWS_ACCOUNT_ID=\\\"133573815653\\\"\",\n \"export AWS_REGION=\\\"us-west-2\\\"\",\n \"export BASE_REPO=\\\"", - { - "Ref": "BASEREPO" - }, - "\\\"\",\n \"export IMAGE_TAG=\\\"", - { - "Ref": "IMAGEARMCPUTAG" - }, - "\\\"\",\n \"export BASE_IMAGE_TAG=\\\"", - { - "Ref": "BASEIMAGEARMCPUTAG" - }, - "\\\"\",\n \"cd app\",\n \"chmod +x ./build.sh && ./build.sh\"\n ]\n }\n },\n \"artifacts\": {\n \"files\": [\n \"imageDetail.json\"\n ]\n }\n}" - ] - ] - }, - "Type": "NO_SOURCE" - } - }, - "Metadata": { - "aws:cdk:path": "flux-oci-image-inference-cdk/ImageCpuArmBuild/Resource" - } - }, - "ImageXlaAmdBuild7511085C": { - "Type": "AWS::CodeBuild::Project", - "Properties": { - "Artifacts": { - "Type": "NO_ARTIFACTS" - }, - "Cache": { - "Modes": [ - "LOCAL_DOCKER_LAYER_CACHE", - "LOCAL_CUSTOM_CACHE" - ], - "Type": "LOCAL" - }, - "EncryptionKey": { - "Fn::GetAtt": [ - "BuildBasePipelineArtifactsBucketEncryptionKey04467E09", - "Arn" - ] - }, - "Environment": { - "ComputeType": "BUILD_GENERAL1_SMALL", - "Image": "aws/codebuild/amazonlinux2-x86_64-standard:3.0", - "ImagePullCredentialsType": "CODEBUILD", - "PrivilegedMode": true, - "Type": "LINUX_CONTAINER" - }, - "ServiceRole": { - "Fn::GetAtt": [ - "BaseCodeBuildDeployRole2A53BD0D", - "Arn" - ] - }, - "Source": { - "BuildSpec": { - "Fn::Join": [ - "", - [ - "{\n \"version\": \"0.2\",\n \"env\": {\n \"exported-variables\": [\n \"AWS_ACCOUNT_ID\",\n \"AWS_REGION\",\n \"BASE_REPO\",\n \"IMAGE_AMD_XLA_TAG\",\n \"BASE_IMAGE_AMD_XLA_TAG\"\n ]\n },\n \"phases\": {\n \"build\": {\n \"commands\": [\n \"export AWS_ACCOUNT_ID=\\\"133573815653\\\"\",\n \"export AWS_REGION=\\\"us-west-2\\\"\",\n \"export BASE_REPO=\\\"", - { - "Ref": "BASEREPO" - }, - "\\\"\",\n \"export IMAGE_TAG=\\\"", - { - "Ref": "IMAGEAMDXLATAG" - }, - "\\\"\",\n \"export BASE_IMAGE_TAG=\\\"", - { - "Ref": "BASEIMAGEAMDXLATAG" - }, - "\\\"\",\n \"cd app\",\n \"chmod +x ./build.sh && ./build.sh\"\n ]\n }\n },\n \"artifacts\": {\n \"files\": [\n \"imageDetail.json\"\n ]\n }\n}" - ] - ] - }, - "Type": "NO_SOURCE" - } - }, - "Metadata": { - "aws:cdk:path": "flux-oci-image-inference-cdk/ImageXlaAmdBuild/Resource" - } - }, - "AssetsImageXlaAmdBuild4E3D098F": { - "Type": "AWS::CodeBuild::Project", - "Properties": { - "Artifacts": { - "Type": "NO_ARTIFACTS" - }, - "Cache": { - "Modes": [ - "LOCAL_DOCKER_LAYER_CACHE", - "LOCAL_CUSTOM_CACHE" - ], - "Type": "LOCAL" - }, - "EncryptionKey": { - "Fn::GetAtt": [ - "BuildBasePipelineArtifactsBucketEncryptionKey04467E09", - "Arn" - ] - }, - "Environment": { - "ComputeType": "BUILD_GENERAL1_SMALL", - "Image": "aws/codebuild/amazonlinux2-x86_64-standard:3.0", - "ImagePullCredentialsType": "CODEBUILD", - "PrivilegedMode": true, - "Type": "LINUX_CONTAINER" - }, - "ServiceRole": { - "Fn::GetAtt": [ - "BaseCodeBuildDeployRole2A53BD0D", - "Arn" - ] - }, - "Source": { - "BuildSpec": { - "Fn::Join": [ - "", - [ - "{\n \"version\": \"0.2\",\n \"env\": {\n \"exported-variables\": [\n \"AWS_ACCOUNT_ID\",\n \"AWS_REGION\",\n \"BASE_REPO\",\n \"IMAGE_AMD_XLA_TAG\",\n \"BASE_IMAGE_AMD_XLA_TAG\"\n ]\n },\n \"phases\": {\n \"build\": {\n \"commands\": [\n \"export AWS_ACCOUNT_ID=\\\"133573815653\\\"\",\n \"export AWS_REGION=\\\"us-west-2\\\"\",\n \"export BASE_REPO=\\\"", - { - "Ref": "BASEREPO" - }, - "\\\"\",\n \"export IMAGE_TAG=\\\"", - { - "Ref": "IMAGEAMDXLATAG" - }, - "\\\"\",\n \"export BASE_IMAGE_TAG=\\\"", - { - "Ref": "BASEIMAGEAMDXLATAG" - }, - "\\\"\",\n \"cd app\",\n \"chmod +x ./build-assets.sh && ./build-assets.sh\"\n ]\n }\n },\n \"artifacts\": {\n \"files\": [\n \"imageDetail.json\"\n ]\n }\n}" - ] - ] - }, - "Type": "NO_SOURCE" - } - }, - "Metadata": { - "aws:cdk:path": "flux-oci-image-inference-cdk/AssetsImageXlaAmdBuild/Resource" - } - }, - "AssetsImageCpuArmBuildBC43C501": { - "Type": "AWS::CodeBuild::Project", - "Properties": { - "Artifacts": { - "Type": "NO_ARTIFACTS" - }, - "Cache": { - "Modes": [ - "LOCAL_DOCKER_LAYER_CACHE", - "LOCAL_CUSTOM_CACHE" - ], - "Type": "LOCAL" - }, - "EncryptionKey": { - "Fn::GetAtt": [ - "BuildBasePipelineArtifactsBucketEncryptionKey04467E09", - "Arn" - ] - }, - "Environment": { - "ComputeType": "BUILD_GENERAL1_LARGE", - "Image": "aws/codebuild/amazonlinux2-aarch64-standard:2.0", - "ImagePullCredentialsType": "CODEBUILD", - "PrivilegedMode": true, - "Type": "ARM_CONTAINER" - }, - "ServiceRole": { - "Fn::GetAtt": [ - "BaseCodeBuildDeployRole2A53BD0D", - "Arn" - ] - }, - "Source": { - "BuildSpec": { - "Fn::Join": [ - "", - [ - "{\n \"version\": \"0.2\",\n \"env\": {\n \"exported-variables\": [\n \"AWS_ACCOUNT_ID\",\n \"AWS_REGION\",\n \"BASE_REPO\",\n \"IMAGE_ARM_CPU_TAG\",\n \"BASE_IMAGE_ARM_CPU_TAG\"\n ]\n },\n \"phases\": {\n \"build\": {\n \"commands\": [\n \"export AWS_ACCOUNT_ID=\\\"133573815653\\\"\",\n \"export AWS_REGION=\\\"us-west-2\\\"\",\n \"export BASE_REPO=\\\"", - { - "Ref": "BASEREPO" - }, - "\\\"\",\n \"export IMAGE_TAG=\\\"", - { - "Ref": "IMAGEARMCPUTAG" - }, - "\\\"\",\n \"export BASE_IMAGE_TAG=\\\"", - { - "Ref": "BASEIMAGEARMCPUTAG" - }, - "\\\"\",\n \"cd app\",\n \"chmod +x ./build-assets.sh && ./build-assets.sh\"\n ]\n }\n },\n \"artifacts\": {\n \"files\": [\n \"imageDetail.json\"\n ]\n }\n}" - ] - ] - }, - "Type": "NO_SOURCE" - } - }, - "Metadata": { - "aws:cdk:path": "flux-oci-image-inference-cdk/AssetsImageCpuArmBuild/Resource" - } - }, - "AssetsImageCudAmdBuild4322D558": { - "Type": "AWS::CodeBuild::Project", - "Properties": { - "Artifacts": { - "Type": "NO_ARTIFACTS" - }, - "Cache": { - "Modes": [ - "LOCAL_DOCKER_LAYER_CACHE", - "LOCAL_CUSTOM_CACHE" - ], - "Type": "LOCAL" - }, - "EncryptionKey": { - "Fn::GetAtt": [ - "BuildBasePipelineArtifactsBucketEncryptionKey04467E09", - "Arn" - ] - }, - "Environment": { - "ComputeType": "BUILD_GENERAL1_SMALL", - "Image": "aws/codebuild/amazonlinux2-x86_64-standard:3.0", - "ImagePullCredentialsType": "CODEBUILD", - "PrivilegedMode": true, - "Type": "LINUX_CONTAINER" - }, - "ServiceRole": { - "Fn::GetAtt": [ - "BaseCodeBuildDeployRole2A53BD0D", - "Arn" - ] - }, - "Source": { - "BuildSpec": { - "Fn::Join": [ - "", - [ - "{\n \"version\": \"0.2\",\n \"env\": {\n \"exported-variables\": [\n \"AWS_ACCOUNT_ID\",\n \"AWS_REGION\",\n \"BASE_REPO\",\n \"IMAGE_AMD_CUD_TAG\",\n \"BASE_IMAGE_AMD_CUD_TAG\"\n ]\n },\n \"phases\": {\n \"build\": {\n \"commands\": [\n \"export AWS_ACCOUNT_ID=\\\"133573815653\\\"\",\n \"export AWS_REGION=\\\"us-west-2\\\"\",\n \"export BASE_REPO=\\\"", - { - "Ref": "BASEREPO" - }, - "\\\"\",\n \"export IMAGE_TAG=\\\"", - { - "Ref": "IMAGEAMDCUDTAG" - }, - "\\\"\",\n \"export BASE_IMAGE_TAG=\\\"", - { - "Ref": "BASEIMAGEAMDCUDTAG" - }, - "\\\"\",\n \"cd app\",\n \"chmod +x ./build-assets.sh && ./build-assets.sh\"\n ]\n }\n },\n \"artifacts\": {\n \"files\": [\n \"imageDetail.json\"\n ]\n }\n}" - ] - ] - }, - "Type": "NO_SOURCE" - } - }, - "Metadata": { - "aws:cdk:path": "flux-oci-image-inference-cdk/AssetsImageCudAmdBuild/Resource" - } - }, - "BuildBasePipelineArtifactsBucketEncryptionKey04467E09": { - "Type": "AWS::KMS::Key", - "Properties": { - "KeyPolicy": { - "Statement": [ - { - "Action": "kms:*", - "Effect": "Allow", - "Principal": { - "AWS": { - "Fn::Join": [ - "", - [ - "arn:", - { - "Ref": "AWS::Partition" - }, - ":iam::133573815653:root" - ] - ] - } - }, - "Resource": "*" - } - ], - "Version": "2012-10-17" - } - }, - "UpdateReplacePolicy": "Delete", - "DeletionPolicy": "Delete", - "Metadata": { - "aws:cdk:path": "flux-oci-image-inference-cdk/BuildBasePipeline/ArtifactsBucketEncryptionKey/Resource" - } - }, - "BuildBasePipelineArtifactsBucketEncryptionKeyAlias8A8421DF": { - "Type": "AWS::KMS::Alias", - "Properties": { - "AliasName": "alias/codepipeline-fluxociimageinferencecdkbuildbasepipeline01a0da38", - "TargetKeyId": { - "Fn::GetAtt": [ - "BuildBasePipelineArtifactsBucketEncryptionKey04467E09", - "Arn" - ] - } - }, - "UpdateReplacePolicy": "Delete", - "DeletionPolicy": "Delete", - "Metadata": { - "aws:cdk:path": "flux-oci-image-inference-cdk/BuildBasePipeline/ArtifactsBucketEncryptionKeyAlias/Resource" - } - }, - "BuildBasePipelineArtifactsBucket51786A86": { - "Type": "AWS::S3::Bucket", - "Properties": { - "BucketEncryption": { - "ServerSideEncryptionConfiguration": [ - { - "ServerSideEncryptionByDefault": { - "KMSMasterKeyID": { - "Fn::GetAtt": [ - "BuildBasePipelineArtifactsBucketEncryptionKey04467E09", - "Arn" - ] - }, - "SSEAlgorithm": "aws:kms" - } - } - ] - }, - "PublicAccessBlockConfiguration": { - "BlockPublicAcls": true, - "BlockPublicPolicy": true, - "IgnorePublicAcls": true, - "RestrictPublicBuckets": true - } - }, - "UpdateReplacePolicy": "Retain", - "DeletionPolicy": "Retain", - "Metadata": { - "aws:cdk:path": "flux-oci-image-inference-cdk/BuildBasePipeline/ArtifactsBucket/Resource" - } - }, - "BuildBasePipelineArtifactsBucketPolicy6568CEBB": { - "Type": "AWS::S3::BucketPolicy", - "Properties": { - "Bucket": { - "Ref": "BuildBasePipelineArtifactsBucket51786A86" - }, - "PolicyDocument": { - "Statement": [ - { - "Action": "s3:*", - "Condition": { - "Bool": { - "aws:SecureTransport": "false" - } - }, - "Effect": "Deny", - "Principal": { - "AWS": "*" - }, - "Resource": [ - { - "Fn::GetAtt": [ - "BuildBasePipelineArtifactsBucket51786A86", - "Arn" - ] - }, - { - "Fn::Join": [ - "", - [ - { - "Fn::GetAtt": [ - "BuildBasePipelineArtifactsBucket51786A86", - "Arn" - ] - }, - "/*" - ] - ] - } - ] - } - ], - "Version": "2012-10-17" - } - }, - "Metadata": { - "aws:cdk:path": "flux-oci-image-inference-cdk/BuildBasePipeline/ArtifactsBucket/Policy/Resource" - } - }, - "BuildBasePipelineRole8C8F77AD": { - "Type": "AWS::IAM::Role", - "Properties": { - "AssumeRolePolicyDocument": { - "Statement": [ - { - "Action": "sts:AssumeRole", - "Effect": "Allow", - "Principal": { - "Service": "codepipeline.amazonaws.com" - } - } - ], - "Version": "2012-10-17" - } - }, - "Metadata": { - "aws:cdk:path": "flux-oci-image-inference-cdk/BuildBasePipeline/Role/Resource" - } - }, - "BuildBasePipelineRoleDefaultPolicy7CA9EFF0": { - "Type": "AWS::IAM::Policy", - "Properties": { - "PolicyDocument": { - "Statement": [ - { - "Action": [ - "s3:GetObject*", - "s3:GetBucket*", - "s3:List*", - "s3:DeleteObject*", - "s3:PutObject", - "s3:PutObjectLegalHold", - "s3:PutObjectRetention", - "s3:PutObjectTagging", - "s3:PutObjectVersionTagging", - "s3:Abort*" - ], - "Effect": "Allow", - "Resource": [ - { - "Fn::GetAtt": [ - "BuildBasePipelineArtifactsBucket51786A86", - "Arn" - ] - }, - { - "Fn::Join": [ - "", - [ - { - "Fn::GetAtt": [ - "BuildBasePipelineArtifactsBucket51786A86", - "Arn" - ] - }, - "/*" - ] - ] - } - ] - }, - { - "Action": [ - "kms:Decrypt", - "kms:DescribeKey", - "kms:Encrypt", - "kms:ReEncrypt*", - "kms:GenerateDataKey*" - ], - "Effect": "Allow", - "Resource": { - "Fn::GetAtt": [ - "BuildBasePipelineArtifactsBucketEncryptionKey04467E09", - "Arn" - ] - } - }, - { - "Action": "sts:AssumeRole", - "Effect": "Allow", - "Resource": { - "Fn::GetAtt": [ - "BuildBasePipelineImageBuildAssetsImageXlaAmdBuildCodePipelineActionRole7C093488", - "Arn" - ] - } - }, - { - "Action": "sts:AssumeRole", - "Effect": "Allow", - "Resource": { - "Fn::GetAtt": [ - "BuildBasePipelineImageBuildAssetsImageCudAmdBuildCodePipelineActionRole7F47990C", - "Arn" - ] - } - }, - { - "Action": "sts:AssumeRole", - "Effect": "Allow", - "Resource": { - "Fn::GetAtt": [ - "BuildBasePipelineImageBuildAssetsImageCpuArmBuildCodePipelineActionRole67BCBC26", - "Arn" - ] - } - }, - { - "Action": "sts:AssumeRole", - "Effect": "Allow", - "Resource": { - "Fn::GetAtt": [ - "BuildBasePipelineImageBuildBaseImageAmdXlaBuildCodePipelineActionRoleD9124FCE", - "Arn" - ] - } - }, - { - "Action": "sts:AssumeRole", - "Effect": "Allow", - "Resource": { - "Fn::GetAtt": [ - "BuildBasePipelineImageBuildBaseImageArmCpuBuildCodePipelineActionRole4DF7F5DE", - "Arn" - ] - } - }, - { - "Action": "sts:AssumeRole", - "Effect": "Allow", - "Resource": { - "Fn::GetAtt": [ - "BuildBasePipelineImageBuildBaseImageAmdCudBuildCodePipelineActionRoleA29F5F5F", - "Arn" - ] - } - } - ], - "Version": "2012-10-17" - }, - "PolicyName": "BuildBasePipelineRoleDefaultPolicy7CA9EFF0", - "Roles": [ - { - "Ref": "BuildBasePipelineRole8C8F77AD" - } - ] - }, - "Metadata": { - "aws:cdk:path": "flux-oci-image-inference-cdk/BuildBasePipeline/Role/DefaultPolicy/Resource" - } - }, - "BuildBasePipelineE93F0563": { - "Type": "AWS::CodePipeline::Pipeline", - "Properties": { - "ArtifactStore": { - "EncryptionKey": { - "Id": { - "Fn::GetAtt": [ - "BuildBasePipelineArtifactsBucketEncryptionKey04467E09", - "Arn" - ] - }, - "Type": "KMS" - }, - "Location": { - "Ref": "BuildBasePipelineArtifactsBucket51786A86" - }, - "Type": "S3" - }, - "RoleArn": { - "Fn::GetAtt": [ - "BuildBasePipelineRole8C8F77AD", - "Arn" - ] - }, - "Stages": [ - { - "Actions": [ - { - "ActionTypeId": { - "Category": "Source", - "Owner": "ThirdParty", - "Provider": "GitHub", - "Version": "1" - }, - "Configuration": { - "Owner": { - "Ref": "GITHUBUSER" - }, - "Repo": { - "Ref": "GITHUBREPO" - }, - "Branch": { - "Ref": "GITHUBBRANCH" - }, - "OAuthToken": "{{resolve:secretsmanager:githubtoken:SecretString:token::}}", - "PollForSourceChanges": false - }, - "Name": "GitHub_Source", - "OutputArtifacts": [ - { - "Name": "Artifact_Source_GitHub_Source" - } - ], - "RunOrder": 1 - } - ], - "Name": "Source" - }, - { - "Actions": [ - { - "ActionTypeId": { - "Category": "Build", - "Owner": "AWS", - "Provider": "CodeBuild", - "Version": "1" - }, - "Configuration": { - "ProjectName": { - "Ref": "AssetsImageXlaAmdBuild4E3D098F" - } - }, - "InputArtifacts": [ - { - "Name": "Artifact_Source_GitHub_Source" - } - ], - "Name": "AssetsImageXlaAmdBuild", - "RoleArn": { - "Fn::GetAtt": [ - "BuildBasePipelineImageBuildAssetsImageXlaAmdBuildCodePipelineActionRole7C093488", - "Arn" - ] - }, - "RunOrder": 1 - }, - { - "ActionTypeId": { - "Category": "Build", - "Owner": "AWS", - "Provider": "CodeBuild", - "Version": "1" - }, - "Configuration": { - "ProjectName": { - "Ref": "AssetsImageCudAmdBuild4322D558" - } - }, - "InputArtifacts": [ - { - "Name": "Artifact_Source_GitHub_Source" - } - ], - "Name": "AssetsImageCudAmdBuild", - "RoleArn": { - "Fn::GetAtt": [ - "BuildBasePipelineImageBuildAssetsImageCudAmdBuildCodePipelineActionRole7F47990C", - "Arn" - ] - }, - "RunOrder": 1 - }, - { - "ActionTypeId": { - "Category": "Build", - "Owner": "AWS", - "Provider": "CodeBuild", - "Version": "1" - }, - "Configuration": { - "ProjectName": { - "Ref": "AssetsImageCpuArmBuildBC43C501" - } - }, - "InputArtifacts": [ - { - "Name": "Artifact_Source_GitHub_Source" - } - ], - "Name": "AssetsImageCpuArmBuild", - "RoleArn": { - "Fn::GetAtt": [ - "BuildBasePipelineImageBuildAssetsImageCpuArmBuildCodePipelineActionRole67BCBC26", - "Arn" - ] - }, - "RunOrder": 1 - }, - { - "ActionTypeId": { - "Category": "Build", - "Owner": "AWS", - "Provider": "CodeBuild", - "Version": "1" - }, - "Configuration": { - "ProjectName": { - "Ref": "ImageXlaAmdBuild7511085C" - } - }, - "InputArtifacts": [ - { - "Name": "Artifact_Source_GitHub_Source" - } - ], - "Name": "BaseImageAmdXlaBuild", - "RoleArn": { - "Fn::GetAtt": [ - "BuildBasePipelineImageBuildBaseImageAmdXlaBuildCodePipelineActionRoleD9124FCE", - "Arn" - ] - }, - "RunOrder": 2 - }, - { - "ActionTypeId": { - "Category": "Build", - "Owner": "AWS", - "Provider": "CodeBuild", - "Version": "1" - }, - "Configuration": { - "ProjectName": { - "Ref": "ImageCpuArmBuild4791F7AA" - } - }, - "InputArtifacts": [ - { - "Name": "Artifact_Source_GitHub_Source" - } - ], - "Name": "BaseImageArmCpuBuild", - "RoleArn": { - "Fn::GetAtt": [ - "BuildBasePipelineImageBuildBaseImageArmCpuBuildCodePipelineActionRole4DF7F5DE", - "Arn" - ] - }, - "RunOrder": 2 - }, - { - "ActionTypeId": { - "Category": "Build", - "Owner": "AWS", - "Provider": "CodeBuild", - "Version": "1" - }, - "Configuration": { - "ProjectName": { - "Ref": "ImageCudAmdBuild23EA25C8" - } - }, - "InputArtifacts": [ - { - "Name": "Artifact_Source_GitHub_Source" - } - ], - "Name": "BaseImageAmdCudBuild", - "RoleArn": { - "Fn::GetAtt": [ - "BuildBasePipelineImageBuildBaseImageAmdCudBuildCodePipelineActionRoleA29F5F5F", - "Arn" - ] - }, - "RunOrder": 2 - } - ], - "Name": "ImageBuild" - } - ] - }, - "DependsOn": [ - "BuildBasePipelineRoleDefaultPolicy7CA9EFF0", - "BuildBasePipelineRole8C8F77AD" - ], - "Metadata": { - "aws:cdk:path": "flux-oci-image-inference-cdk/BuildBasePipeline/Resource" - } - }, - "BuildBasePipelineSourceGitHubSourceWebhookResource72F821C3": { - "Type": "AWS::CodePipeline::Webhook", - "Properties": { - "Authentication": "GITHUB_HMAC", - "AuthenticationConfiguration": { - "SecretToken": "{{resolve:secretsmanager:githubtoken:SecretString:token::}}" - }, - "Filters": [ - { - "JsonPath": "$.ref", - "MatchEquals": "refs/heads/{Branch}" - } - ], - "RegisterWithThirdParty": true, - "TargetAction": "GitHub_Source", - "TargetPipeline": { - "Ref": "BuildBasePipelineE93F0563" - }, - "TargetPipelineVersion": 1 - }, - "Metadata": { - "aws:cdk:path": "flux-oci-image-inference-cdk/BuildBasePipeline/Source/GitHub_Source/WebhookResource" - } - }, - "BuildBasePipelineImageBuildAssetsImageXlaAmdBuildCodePipelineActionRole7C093488": { - "Type": "AWS::IAM::Role", - "Properties": { - "AssumeRolePolicyDocument": { - "Statement": [ - { - "Action": "sts:AssumeRole", - "Effect": "Allow", - "Principal": { - "AWS": { - "Fn::Join": [ - "", - [ - "arn:", - { - "Ref": "AWS::Partition" - }, - ":iam::133573815653:root" - ] - ] - } - } - } - ], - "Version": "2012-10-17" - } - }, - "Metadata": { - "aws:cdk:path": "flux-oci-image-inference-cdk/BuildBasePipeline/ImageBuild/AssetsImageXlaAmdBuild/CodePipelineActionRole/Resource" - } - }, - "BuildBasePipelineImageBuildAssetsImageXlaAmdBuildCodePipelineActionRoleDefaultPolicyB3BE9D03": { - "Type": "AWS::IAM::Policy", - "Properties": { - "PolicyDocument": { - "Statement": [ - { - "Action": [ - "codebuild:BatchGetBuilds", - "codebuild:StartBuild", - "codebuild:StopBuild" - ], - "Effect": "Allow", - "Resource": { - "Fn::GetAtt": [ - "AssetsImageXlaAmdBuild4E3D098F", - "Arn" - ] - } - } - ], - "Version": "2012-10-17" - }, - "PolicyName": "BuildBasePipelineImageBuildAssetsImageXlaAmdBuildCodePipelineActionRoleDefaultPolicyB3BE9D03", - "Roles": [ - { - "Ref": "BuildBasePipelineImageBuildAssetsImageXlaAmdBuildCodePipelineActionRole7C093488" - } - ] - }, - "Metadata": { - "aws:cdk:path": "flux-oci-image-inference-cdk/BuildBasePipeline/ImageBuild/AssetsImageXlaAmdBuild/CodePipelineActionRole/DefaultPolicy/Resource" - } - }, - "BuildBasePipelineImageBuildAssetsImageCudAmdBuildCodePipelineActionRole7F47990C": { - "Type": "AWS::IAM::Role", - "Properties": { - "AssumeRolePolicyDocument": { - "Statement": [ - { - "Action": "sts:AssumeRole", - "Effect": "Allow", - "Principal": { - "AWS": { - "Fn::Join": [ - "", - [ - "arn:", - { - "Ref": "AWS::Partition" - }, - ":iam::133573815653:root" - ] - ] - } - } - } - ], - "Version": "2012-10-17" - } - }, - "Metadata": { - "aws:cdk:path": "flux-oci-image-inference-cdk/BuildBasePipeline/ImageBuild/AssetsImageCudAmdBuild/CodePipelineActionRole/Resource" - } - }, - "BuildBasePipelineImageBuildAssetsImageCudAmdBuildCodePipelineActionRoleDefaultPolicy44AAF344": { - "Type": "AWS::IAM::Policy", - "Properties": { - "PolicyDocument": { - "Statement": [ - { - "Action": [ - "codebuild:BatchGetBuilds", - "codebuild:StartBuild", - "codebuild:StopBuild" - ], - "Effect": "Allow", - "Resource": { - "Fn::GetAtt": [ - "AssetsImageCudAmdBuild4322D558", - "Arn" - ] - } - } - ], - "Version": "2012-10-17" - }, - "PolicyName": "BuildBasePipelineImageBuildAssetsImageCudAmdBuildCodePipelineActionRoleDefaultPolicy44AAF344", - "Roles": [ - { - "Ref": "BuildBasePipelineImageBuildAssetsImageCudAmdBuildCodePipelineActionRole7F47990C" - } - ] - }, - "Metadata": { - "aws:cdk:path": "flux-oci-image-inference-cdk/BuildBasePipeline/ImageBuild/AssetsImageCudAmdBuild/CodePipelineActionRole/DefaultPolicy/Resource" - } - }, - "BuildBasePipelineImageBuildAssetsImageCpuArmBuildCodePipelineActionRole67BCBC26": { - "Type": "AWS::IAM::Role", - "Properties": { - "AssumeRolePolicyDocument": { - "Statement": [ - { - "Action": "sts:AssumeRole", - "Effect": "Allow", - "Principal": { - "AWS": { - "Fn::Join": [ - "", - [ - "arn:", - { - "Ref": "AWS::Partition" - }, - ":iam::133573815653:root" - ] - ] - } - } - } - ], - "Version": "2012-10-17" - } - }, - "Metadata": { - "aws:cdk:path": "flux-oci-image-inference-cdk/BuildBasePipeline/ImageBuild/AssetsImageCpuArmBuild/CodePipelineActionRole/Resource" - } - }, - "BuildBasePipelineImageBuildAssetsImageCpuArmBuildCodePipelineActionRoleDefaultPolicy723A3220": { - "Type": "AWS::IAM::Policy", - "Properties": { - "PolicyDocument": { - "Statement": [ - { - "Action": [ - "codebuild:BatchGetBuilds", - "codebuild:StartBuild", - "codebuild:StopBuild" - ], - "Effect": "Allow", - "Resource": { - "Fn::GetAtt": [ - "AssetsImageCpuArmBuildBC43C501", - "Arn" - ] - } - } - ], - "Version": "2012-10-17" - }, - "PolicyName": "BuildBasePipelineImageBuildAssetsImageCpuArmBuildCodePipelineActionRoleDefaultPolicy723A3220", - "Roles": [ - { - "Ref": "BuildBasePipelineImageBuildAssetsImageCpuArmBuildCodePipelineActionRole67BCBC26" - } - ] - }, - "Metadata": { - "aws:cdk:path": "flux-oci-image-inference-cdk/BuildBasePipeline/ImageBuild/AssetsImageCpuArmBuild/CodePipelineActionRole/DefaultPolicy/Resource" - } - }, - "BuildBasePipelineImageBuildBaseImageAmdXlaBuildCodePipelineActionRoleD9124FCE": { - "Type": "AWS::IAM::Role", - "Properties": { - "AssumeRolePolicyDocument": { - "Statement": [ - { - "Action": "sts:AssumeRole", - "Effect": "Allow", - "Principal": { - "AWS": { - "Fn::Join": [ - "", - [ - "arn:", - { - "Ref": "AWS::Partition" - }, - ":iam::133573815653:root" - ] - ] - } - } - } - ], - "Version": "2012-10-17" - } - }, - "Metadata": { - "aws:cdk:path": "flux-oci-image-inference-cdk/BuildBasePipeline/ImageBuild/BaseImageAmdXlaBuild/CodePipelineActionRole/Resource" - } - }, - "BuildBasePipelineImageBuildBaseImageAmdXlaBuildCodePipelineActionRoleDefaultPolicy1C329D4F": { - "Type": "AWS::IAM::Policy", - "Properties": { - "PolicyDocument": { - "Statement": [ - { - "Action": [ - "codebuild:BatchGetBuilds", - "codebuild:StartBuild", - "codebuild:StopBuild" - ], - "Effect": "Allow", - "Resource": { - "Fn::GetAtt": [ - "ImageXlaAmdBuild7511085C", - "Arn" - ] - } - } - ], - "Version": "2012-10-17" - }, - "PolicyName": "BuildBasePipelineImageBuildBaseImageAmdXlaBuildCodePipelineActionRoleDefaultPolicy1C329D4F", - "Roles": [ - { - "Ref": "BuildBasePipelineImageBuildBaseImageAmdXlaBuildCodePipelineActionRoleD9124FCE" - } - ] - }, - "Metadata": { - "aws:cdk:path": "flux-oci-image-inference-cdk/BuildBasePipeline/ImageBuild/BaseImageAmdXlaBuild/CodePipelineActionRole/DefaultPolicy/Resource" - } - }, - "BuildBasePipelineImageBuildBaseImageArmCpuBuildCodePipelineActionRole4DF7F5DE": { - "Type": "AWS::IAM::Role", - "Properties": { - "AssumeRolePolicyDocument": { - "Statement": [ - { - "Action": "sts:AssumeRole", - "Effect": "Allow", - "Principal": { - "AWS": { - "Fn::Join": [ - "", - [ - "arn:", - { - "Ref": "AWS::Partition" - }, - ":iam::133573815653:root" - ] - ] - } - } - } - ], - "Version": "2012-10-17" - } - }, - "Metadata": { - "aws:cdk:path": "flux-oci-image-inference-cdk/BuildBasePipeline/ImageBuild/BaseImageArmCpuBuild/CodePipelineActionRole/Resource" - } - }, - "BuildBasePipelineImageBuildBaseImageArmCpuBuildCodePipelineActionRoleDefaultPolicy31713CB8": { - "Type": "AWS::IAM::Policy", - "Properties": { - "PolicyDocument": { - "Statement": [ - { - "Action": [ - "codebuild:BatchGetBuilds", - "codebuild:StartBuild", - "codebuild:StopBuild" - ], - "Effect": "Allow", - "Resource": { - "Fn::GetAtt": [ - "ImageCpuArmBuild4791F7AA", - "Arn" - ] - } - } - ], - "Version": "2012-10-17" - }, - "PolicyName": "BuildBasePipelineImageBuildBaseImageArmCpuBuildCodePipelineActionRoleDefaultPolicy31713CB8", - "Roles": [ - { - "Ref": "BuildBasePipelineImageBuildBaseImageArmCpuBuildCodePipelineActionRole4DF7F5DE" - } - ] - }, - "Metadata": { - "aws:cdk:path": "flux-oci-image-inference-cdk/BuildBasePipeline/ImageBuild/BaseImageArmCpuBuild/CodePipelineActionRole/DefaultPolicy/Resource" - } - }, - "BuildBasePipelineImageBuildBaseImageAmdCudBuildCodePipelineActionRoleA29F5F5F": { - "Type": "AWS::IAM::Role", - "Properties": { - "AssumeRolePolicyDocument": { - "Statement": [ - { - "Action": "sts:AssumeRole", - "Effect": "Allow", - "Principal": { - "AWS": { - "Fn::Join": [ - "", - [ - "arn:", - { - "Ref": "AWS::Partition" - }, - ":iam::133573815653:root" - ] - ] - } - } - } - ], - "Version": "2012-10-17" - } - }, - "Metadata": { - "aws:cdk:path": "flux-oci-image-inference-cdk/BuildBasePipeline/ImageBuild/BaseImageAmdCudBuild/CodePipelineActionRole/Resource" - } - }, - "BuildBasePipelineImageBuildBaseImageAmdCudBuildCodePipelineActionRoleDefaultPolicy7D964952": { - "Type": "AWS::IAM::Policy", - "Properties": { - "PolicyDocument": { - "Statement": [ - { - "Action": [ - "codebuild:BatchGetBuilds", - "codebuild:StartBuild", - "codebuild:StopBuild" - ], - "Effect": "Allow", - "Resource": { - "Fn::GetAtt": [ - "ImageCudAmdBuild23EA25C8", - "Arn" - ] - } - } - ], - "Version": "2012-10-17" - }, - "PolicyName": "BuildBasePipelineImageBuildBaseImageAmdCudBuildCodePipelineActionRoleDefaultPolicy7D964952", - "Roles": [ - { - "Ref": "BuildBasePipelineImageBuildBaseImageAmdCudBuildCodePipelineActionRoleA29F5F5F" - } - ] - }, - "Metadata": { - "aws:cdk:path": "flux-oci-image-inference-cdk/BuildBasePipeline/ImageBuild/BaseImageAmdCudBuild/CodePipelineActionRole/DefaultPolicy/Resource" - } - }, - "CDKMetadata": { - "Type": "AWS::CDK::Metadata", - "Properties": { - "Analytics": "v2:deflate64:H4sIAAAAAAAA/02QO0/EMBCEf8v1zgJ3SNRASXFRrqBEjrPAxq/IDxCy/N/xI9JdNd96RuvRHuHh6QSPB/7rB7HIQdEM6RK4kOz104zccY0BHSv+R0LhIE24WU/Bur+auE6ZEdfFtgqbUXW0ikTLdcrMlx0YvOaGf2HZdmlzTXTKTNgF50hqgTQ6u6Jo7o7d3mhDRQZLYqcWueF3nL+tlZlJ7SG9YetQ5VkR93VoUPqcIL1EIXuHnbpcy9/OObMJvY1OtI/OMWwx9Ev018xMqQirv/s5lsvC/WH1RIOLJpBGmLr+A03QqEN4AQAA" - }, - "Metadata": { - "aws:cdk:path": "flux-oci-image-inference-cdk/CDKMetadata/Default" - } - } - }, - "Outputs": { - "githubOAuthTokenRuntimeOutput1": { - "Value": { - "Fn::Join": [ - "", - [ - "{{resolve:secretsmanager:", - { - "Ref": "githubSecret7D37FCC7" - }, - ":SecretString:token::}}" - ] - ] - } - }, - "githubOAuthTokenRuntimeOutput2": { - "Value": { - "Fn::Join": [ - "", - [ - "{{resolve:secretsmanager:", - { - "Ref": "githubSecret7D37FCC7" - }, - ":SecretString:token::}}" - ] - ] - } - } - }, - "Rules": { - "CheckBootstrapVersion": { - "Assertions": [ - { - "Assert": { - "Fn::Not": [ - { - "Fn::Contains": [ - [ - "1", - "2", - "3", - "4", - "5" - ], - { - "Ref": "BootstrapVersion" - } - ] - } - ] - }, - "AssertDescription": "CDK bootstrap stack version 6 required. Please run 'cdk bootstrap' with a recent version of the CDK CLI." - } - ] - } - } -} \ No newline at end of file diff --git a/flux_serve/oci-image-build/cdk.out/manifest.json b/flux_serve/oci-image-build/cdk.out/manifest.json deleted file mode 100644 index a09edbf..0000000 --- a/flux_serve/oci-image-build/cdk.out/manifest.json +++ /dev/null @@ -1,357 +0,0 @@ -{ - "version": "38.0.1", - "artifacts": { - "flux-oci-image-inference-cdk.assets": { - "type": "cdk:asset-manifest", - "properties": { - "file": "flux-oci-image-inference-cdk.assets.json", - "requiresBootstrapStackVersion": 6, - "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version" - } - }, - "flux-oci-image-inference-cdk": { - "type": "aws:cloudformation:stack", - "environment": "aws://133573815653/us-west-2", - "properties": { - "templateFile": "flux-oci-image-inference-cdk.template.json", - "terminationProtection": false, - "validateOnSynth": false, - "assumeRoleArn": "arn:${AWS::Partition}:iam::133573815653:role/cdk-hnb659fds-deploy-role-133573815653-us-west-2", - "cloudFormationExecutionRoleArn": "arn:${AWS::Partition}:iam::133573815653:role/cdk-hnb659fds-cfn-exec-role-133573815653-us-west-2", - "stackTemplateAssetObjectUrl": "s3://cdk-hnb659fds-assets-133573815653-us-west-2/54c3377f007eccdd78146d6ef1c9fe016f1cd6dc99c2088e7f65bb90e95689cc.json", - "requiresBootstrapStackVersion": 6, - "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version", - "additionalDependencies": [ - "flux-oci-image-inference-cdk.assets" - ], - "lookupRole": { - "arn": "arn:${AWS::Partition}:iam::133573815653:role/cdk-hnb659fds-lookup-role-133573815653-us-west-2", - "requiresBootstrapStackVersion": 8, - "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version" - } - }, - "dependencies": [ - "flux-oci-image-inference-cdk.assets" - ], - "metadata": { - "/flux-oci-image-inference-cdk/BASEREPO": [ - { - "type": "aws:cdk:logicalId", - "data": "BASEREPO" - } - ], - "/flux-oci-image-inference-cdk/BASEIMAGEAMDXLATAG": [ - { - "type": "aws:cdk:logicalId", - "data": "BASEIMAGEAMDXLATAG" - } - ], - "/flux-oci-image-inference-cdk/BASEIMAGEAMDCUDTAG": [ - { - "type": "aws:cdk:logicalId", - "data": "BASEIMAGEAMDCUDTAG" - } - ], - "/flux-oci-image-inference-cdk/BASEIMAGEARMCPUTAG": [ - { - "type": "aws:cdk:logicalId", - "data": "BASEIMAGEARMCPUTAG" - } - ], - "/flux-oci-image-inference-cdk/IMAGEAMDXLATAG": [ - { - "type": "aws:cdk:logicalId", - "data": "IMAGEAMDXLATAG" - } - ], - "/flux-oci-image-inference-cdk/IMAGEAMDCUDTAG": [ - { - "type": "aws:cdk:logicalId", - "data": "IMAGEAMDCUDTAG" - } - ], - "/flux-oci-image-inference-cdk/IMAGEARMCPUTAG": [ - { - "type": "aws:cdk:logicalId", - "data": "IMAGEARMCPUTAG" - } - ], - "/flux-oci-image-inference-cdk/GITHUBOAUTHTOKEN": [ - { - "type": "aws:cdk:logicalId", - "data": "GITHUBOAUTHTOKEN" - } - ], - "/flux-oci-image-inference-cdk/GITHUBUSER": [ - { - "type": "aws:cdk:logicalId", - "data": "GITHUBUSER" - } - ], - "/flux-oci-image-inference-cdk/GITHUBREPO": [ - { - "type": "aws:cdk:logicalId", - "data": "GITHUBREPO" - } - ], - "/flux-oci-image-inference-cdk/GITHUBBRANCH": [ - { - "type": "aws:cdk:logicalId", - "data": "GITHUBBRANCH" - } - ], - "/flux-oci-image-inference-cdk/base_repo/Resource": [ - { - "type": "aws:cdk:logicalId", - "data": "baserepoCCF23216" - } - ], - "/flux-oci-image-inference-cdk/BaseCodeBuildDeployRole/Resource": [ - { - "type": "aws:cdk:logicalId", - "data": "BaseCodeBuildDeployRole2A53BD0D" - } - ], - "/flux-oci-image-inference-cdk/BaseCodeBuildDeployRole/DefaultPolicy/Resource": [ - { - "type": "aws:cdk:logicalId", - "data": "BaseCodeBuildDeployRoleDefaultPolicy93D8F557" - } - ], - "/flux-oci-image-inference-cdk/githubSecret/Resource": [ - { - "type": "aws:cdk:logicalId", - "data": "githubSecret7D37FCC7" - } - ], - "/flux-oci-image-inference-cdk/githubOAuthTokenRuntimeOutput1": [ - { - "type": "aws:cdk:logicalId", - "data": "githubOAuthTokenRuntimeOutput1" - } - ], - "/flux-oci-image-inference-cdk/githubOAuthTokenRuntimeOutput2": [ - { - "type": "aws:cdk:logicalId", - "data": "githubOAuthTokenRuntimeOutput2" - } - ], - "/flux-oci-image-inference-cdk/ImageCudAmdBuild/Resource": [ - { - "type": "aws:cdk:logicalId", - "data": "ImageCudAmdBuild23EA25C8" - } - ], - "/flux-oci-image-inference-cdk/ImageCpuArmBuild/Resource": [ - { - "type": "aws:cdk:logicalId", - "data": "ImageCpuArmBuild4791F7AA" - } - ], - "/flux-oci-image-inference-cdk/ImageXlaAmdBuild/Resource": [ - { - "type": "aws:cdk:logicalId", - "data": "ImageXlaAmdBuild7511085C" - } - ], - "/flux-oci-image-inference-cdk/AssetsImageXlaAmdBuild/Resource": [ - { - "type": "aws:cdk:logicalId", - "data": "AssetsImageXlaAmdBuild4E3D098F" - } - ], - "/flux-oci-image-inference-cdk/AssetsImageCpuArmBuild/Resource": [ - { - "type": "aws:cdk:logicalId", - "data": "AssetsImageCpuArmBuildBC43C501" - } - ], - "/flux-oci-image-inference-cdk/AssetsImageCudAmdBuild/Resource": [ - { - "type": "aws:cdk:logicalId", - "data": "AssetsImageCudAmdBuild4322D558" - } - ], - "/flux-oci-image-inference-cdk/BuildBasePipeline": [ - { - "type": "aws:cdk:warning", - "data": "V1 pipeline type is implicitly selected when `pipelineType` is not set. If you want to use V2 type, set `PipelineType.V2`. [ack: @aws-cdk/aws-codepipeline:unspecifiedPipelineType]", - "trace": [ - "Annotations.addMessage (/Users/yahavb/aws-neuron-eks-samples/flux_serve/oci-image-build/node_modules/aws-cdk-lib/core/lib/annotations.js:1:1608)", - "Annotations.addWarningV2 (/Users/yahavb/aws-neuron-eks-samples/flux_serve/oci-image-build/node_modules/aws-cdk-lib/core/lib/annotations.js:1:825)", - "new Pipeline (/Users/yahavb/aws-neuron-eks-samples/flux_serve/oci-image-build/node_modules/aws-cdk-lib/aws-codepipeline/lib/pipeline.js:1:6677)", - "new PipelineStack (/Users/yahavb/aws-neuron-eks-samples/flux_serve/oci-image-build/pipeline-stack.ts:262:29)", - "Object. (/Users/yahavb/aws-neuron-eks-samples/flux_serve/oci-image-build/pipeline.ts:8:1)", - "Module._compile (node:internal/modules/cjs/loader:1566:14)", - "Module.m._compile (/Users/yahavb/aws-neuron-eks-samples/flux_serve/oci-image-build/node_modules/ts-node/src/index.ts:1618:23)", - "node:internal/modules/cjs/loader:1718:10", - "Object.require.extensions. [as .ts] (/Users/yahavb/aws-neuron-eks-samples/flux_serve/oci-image-build/node_modules/ts-node/src/index.ts:1621:12)", - "Module.load (node:internal/modules/cjs/loader:1305:32)", - "Function._load (node:internal/modules/cjs/loader:1119:12)", - "TracingChannel.traceSync (node:diagnostics_channel:322:14)", - "wrapModuleLoad (node:internal/modules/cjs/loader:220:24)", - "Function.executeUserEntryPoint [as runMain] (node:internal/modules/run_main:151:5)", - "phase4 (/Users/yahavb/aws-neuron-eks-samples/flux_serve/oci-image-build/node_modules/ts-node/src/bin.ts:649:14)", - "bootstrap (/Users/yahavb/aws-neuron-eks-samples/flux_serve/oci-image-build/node_modules/ts-node/src/bin.ts:95:10)", - "main (/Users/yahavb/aws-neuron-eks-samples/flux_serve/oci-image-build/node_modules/ts-node/src/bin.ts:55:10)", - "Object. (/Users/yahavb/aws-neuron-eks-samples/flux_serve/oci-image-build/node_modules/ts-node/src/bin.ts:800:3)", - "Module._compile (node:internal/modules/cjs/loader:1566:14)", - "Object. (node:internal/modules/cjs/loader:1718:10)", - "Module.load (node:internal/modules/cjs/loader:1305:32)", - "Function._load (node:internal/modules/cjs/loader:1119:12)", - "TracingChannel.traceSync (node:diagnostics_channel:322:14)", - "wrapModuleLoad (node:internal/modules/cjs/loader:220:24)", - "Function.executeUserEntryPoint [as runMain] (node:internal/modules/run_main:151:5)", - "node:internal/main/run_main_module:33:47" - ] - } - ], - "/flux-oci-image-inference-cdk/BuildBasePipeline/ArtifactsBucketEncryptionKey/Resource": [ - { - "type": "aws:cdk:logicalId", - "data": "BuildBasePipelineArtifactsBucketEncryptionKey04467E09" - } - ], - "/flux-oci-image-inference-cdk/BuildBasePipeline/ArtifactsBucketEncryptionKeyAlias/Resource": [ - { - "type": "aws:cdk:logicalId", - "data": "BuildBasePipelineArtifactsBucketEncryptionKeyAlias8A8421DF" - } - ], - "/flux-oci-image-inference-cdk/BuildBasePipeline/ArtifactsBucket/Resource": [ - { - "type": "aws:cdk:logicalId", - "data": "BuildBasePipelineArtifactsBucket51786A86" - } - ], - "/flux-oci-image-inference-cdk/BuildBasePipeline/ArtifactsBucket/Policy/Resource": [ - { - "type": "aws:cdk:logicalId", - "data": "BuildBasePipelineArtifactsBucketPolicy6568CEBB" - } - ], - "/flux-oci-image-inference-cdk/BuildBasePipeline/Role/Resource": [ - { - "type": "aws:cdk:logicalId", - "data": "BuildBasePipelineRole8C8F77AD" - } - ], - "/flux-oci-image-inference-cdk/BuildBasePipeline/Role/DefaultPolicy/Resource": [ - { - "type": "aws:cdk:logicalId", - "data": "BuildBasePipelineRoleDefaultPolicy7CA9EFF0" - } - ], - "/flux-oci-image-inference-cdk/BuildBasePipeline/Resource": [ - { - "type": "aws:cdk:logicalId", - "data": "BuildBasePipelineE93F0563" - } - ], - "/flux-oci-image-inference-cdk/BuildBasePipeline/Source/GitHub_Source/WebhookResource": [ - { - "type": "aws:cdk:logicalId", - "data": "BuildBasePipelineSourceGitHubSourceWebhookResource72F821C3" - } - ], - "/flux-oci-image-inference-cdk/BuildBasePipeline/ImageBuild/AssetsImageXlaAmdBuild/CodePipelineActionRole/Resource": [ - { - "type": "aws:cdk:logicalId", - "data": "BuildBasePipelineImageBuildAssetsImageXlaAmdBuildCodePipelineActionRole7C093488" - } - ], - "/flux-oci-image-inference-cdk/BuildBasePipeline/ImageBuild/AssetsImageXlaAmdBuild/CodePipelineActionRole/DefaultPolicy/Resource": [ - { - "type": "aws:cdk:logicalId", - "data": "BuildBasePipelineImageBuildAssetsImageXlaAmdBuildCodePipelineActionRoleDefaultPolicyB3BE9D03" - } - ], - "/flux-oci-image-inference-cdk/BuildBasePipeline/ImageBuild/AssetsImageCudAmdBuild/CodePipelineActionRole/Resource": [ - { - "type": "aws:cdk:logicalId", - "data": "BuildBasePipelineImageBuildAssetsImageCudAmdBuildCodePipelineActionRole7F47990C" - } - ], - "/flux-oci-image-inference-cdk/BuildBasePipeline/ImageBuild/AssetsImageCudAmdBuild/CodePipelineActionRole/DefaultPolicy/Resource": [ - { - "type": "aws:cdk:logicalId", - "data": "BuildBasePipelineImageBuildAssetsImageCudAmdBuildCodePipelineActionRoleDefaultPolicy44AAF344" - } - ], - "/flux-oci-image-inference-cdk/BuildBasePipeline/ImageBuild/AssetsImageCpuArmBuild/CodePipelineActionRole/Resource": [ - { - "type": "aws:cdk:logicalId", - "data": "BuildBasePipelineImageBuildAssetsImageCpuArmBuildCodePipelineActionRole67BCBC26" - } - ], - "/flux-oci-image-inference-cdk/BuildBasePipeline/ImageBuild/AssetsImageCpuArmBuild/CodePipelineActionRole/DefaultPolicy/Resource": [ - { - "type": "aws:cdk:logicalId", - "data": "BuildBasePipelineImageBuildAssetsImageCpuArmBuildCodePipelineActionRoleDefaultPolicy723A3220" - } - ], - "/flux-oci-image-inference-cdk/BuildBasePipeline/ImageBuild/BaseImageAmdXlaBuild/CodePipelineActionRole/Resource": [ - { - "type": "aws:cdk:logicalId", - "data": "BuildBasePipelineImageBuildBaseImageAmdXlaBuildCodePipelineActionRoleD9124FCE" - } - ], - "/flux-oci-image-inference-cdk/BuildBasePipeline/ImageBuild/BaseImageAmdXlaBuild/CodePipelineActionRole/DefaultPolicy/Resource": [ - { - "type": "aws:cdk:logicalId", - "data": "BuildBasePipelineImageBuildBaseImageAmdXlaBuildCodePipelineActionRoleDefaultPolicy1C329D4F" - } - ], - "/flux-oci-image-inference-cdk/BuildBasePipeline/ImageBuild/BaseImageArmCpuBuild/CodePipelineActionRole/Resource": [ - { - "type": "aws:cdk:logicalId", - "data": "BuildBasePipelineImageBuildBaseImageArmCpuBuildCodePipelineActionRole4DF7F5DE" - } - ], - "/flux-oci-image-inference-cdk/BuildBasePipeline/ImageBuild/BaseImageArmCpuBuild/CodePipelineActionRole/DefaultPolicy/Resource": [ - { - "type": "aws:cdk:logicalId", - "data": "BuildBasePipelineImageBuildBaseImageArmCpuBuildCodePipelineActionRoleDefaultPolicy31713CB8" - } - ], - "/flux-oci-image-inference-cdk/BuildBasePipeline/ImageBuild/BaseImageAmdCudBuild/CodePipelineActionRole/Resource": [ - { - "type": "aws:cdk:logicalId", - "data": "BuildBasePipelineImageBuildBaseImageAmdCudBuildCodePipelineActionRoleA29F5F5F" - } - ], - "/flux-oci-image-inference-cdk/BuildBasePipeline/ImageBuild/BaseImageAmdCudBuild/CodePipelineActionRole/DefaultPolicy/Resource": [ - { - "type": "aws:cdk:logicalId", - "data": "BuildBasePipelineImageBuildBaseImageAmdCudBuildCodePipelineActionRoleDefaultPolicy7D964952" - } - ], - "/flux-oci-image-inference-cdk/CDKMetadata/Default": [ - { - "type": "aws:cdk:logicalId", - "data": "CDKMetadata" - } - ], - "/flux-oci-image-inference-cdk/BootstrapVersion": [ - { - "type": "aws:cdk:logicalId", - "data": "BootstrapVersion" - } - ], - "/flux-oci-image-inference-cdk/CheckBootstrapVersion": [ - { - "type": "aws:cdk:logicalId", - "data": "CheckBootstrapVersion" - } - ] - }, - "displayName": "flux-oci-image-inference-cdk" - }, - "Tree": { - "type": "cdk:tree", - "properties": { - "file": "tree.json" - } - } - } -} \ No newline at end of file diff --git a/flux_serve/oci-image-build/cdk.out/tree.json b/flux_serve/oci-image-build/cdk.out/tree.json deleted file mode 100644 index 0e86e2f..0000000 --- a/flux_serve/oci-image-build/cdk.out/tree.json +++ /dev/null @@ -1,2599 +0,0 @@ -{ - "version": "tree-0.1", - "tree": { - "id": "App", - "path": "", - "children": { - "flux-oci-image-inference-cdk": { - "id": "flux-oci-image-inference-cdk", - "path": "flux-oci-image-inference-cdk", - "children": { - "BASEREPO": { - "id": "BASEREPO", - "path": "flux-oci-image-inference-cdk/BASEREPO", - "constructInfo": { - "fqn": "aws-cdk-lib.CfnParameter", - "version": "2.173.4" - } - }, - "BASEIMAGEAMDXLATAG": { - "id": "BASEIMAGEAMDXLATAG", - "path": "flux-oci-image-inference-cdk/BASEIMAGEAMDXLATAG", - "constructInfo": { - "fqn": "aws-cdk-lib.CfnParameter", - "version": "2.173.4" - } - }, - "BASEIMAGEAMDCUDTAG": { - "id": "BASEIMAGEAMDCUDTAG", - "path": "flux-oci-image-inference-cdk/BASEIMAGEAMDCUDTAG", - "constructInfo": { - "fqn": "aws-cdk-lib.CfnParameter", - "version": "2.173.4" - } - }, - "BASEIMAGEARMCPUTAG": { - "id": "BASEIMAGEARMCPUTAG", - "path": "flux-oci-image-inference-cdk/BASEIMAGEARMCPUTAG", - "constructInfo": { - "fqn": "aws-cdk-lib.CfnParameter", - "version": "2.173.4" - } - }, - "IMAGEAMDXLATAG": { - "id": "IMAGEAMDXLATAG", - "path": "flux-oci-image-inference-cdk/IMAGEAMDXLATAG", - "constructInfo": { - "fqn": "aws-cdk-lib.CfnParameter", - "version": "2.173.4" - } - }, - "IMAGEAMDCUDTAG": { - "id": "IMAGEAMDCUDTAG", - "path": "flux-oci-image-inference-cdk/IMAGEAMDCUDTAG", - "constructInfo": { - "fqn": "aws-cdk-lib.CfnParameter", - "version": "2.173.4" - } - }, - "IMAGEARMCPUTAG": { - "id": "IMAGEARMCPUTAG", - "path": "flux-oci-image-inference-cdk/IMAGEARMCPUTAG", - "constructInfo": { - "fqn": "aws-cdk-lib.CfnParameter", - "version": "2.173.4" - } - }, - "GITHUBOAUTHTOKEN": { - "id": "GITHUBOAUTHTOKEN", - "path": "flux-oci-image-inference-cdk/GITHUBOAUTHTOKEN", - "constructInfo": { - "fqn": "aws-cdk-lib.CfnParameter", - "version": "2.173.4" - } - }, - "GITHUBUSER": { - "id": "GITHUBUSER", - "path": "flux-oci-image-inference-cdk/GITHUBUSER", - "constructInfo": { - "fqn": "aws-cdk-lib.CfnParameter", - "version": "2.173.4" - } - }, - "GITHUBREPO": { - "id": "GITHUBREPO", - "path": "flux-oci-image-inference-cdk/GITHUBREPO", - "constructInfo": { - "fqn": "aws-cdk-lib.CfnParameter", - "version": "2.173.4" - } - }, - "GITHUBBRANCH": { - "id": "GITHUBBRANCH", - "path": "flux-oci-image-inference-cdk/GITHUBBRANCH", - "constructInfo": { - "fqn": "aws-cdk-lib.CfnParameter", - "version": "2.173.4" - } - }, - "base_repo": { - "id": "base_repo", - "path": "flux-oci-image-inference-cdk/base_repo", - "children": { - "Resource": { - "id": "Resource", - "path": "flux-oci-image-inference-cdk/base_repo/Resource", - "attributes": { - "aws:cdk:cloudformation:type": "AWS::ECR::Repository", - "aws:cdk:cloudformation:props": { - "imageScanningConfiguration": { - "scanOnPush": true - }, - "repositoryName": { - "Ref": "BASEREPO" - } - } - }, - "constructInfo": { - "fqn": "aws-cdk-lib.aws_ecr.CfnRepository", - "version": "2.173.4" - } - } - }, - "constructInfo": { - "fqn": "aws-cdk-lib.aws_ecr.Repository", - "version": "2.173.4" - } - }, - "BaseCodeBuildDeployRole": { - "id": "BaseCodeBuildDeployRole", - "path": "flux-oci-image-inference-cdk/BaseCodeBuildDeployRole", - "children": { - "ImportBaseCodeBuildDeployRole": { - "id": "ImportBaseCodeBuildDeployRole", - "path": "flux-oci-image-inference-cdk/BaseCodeBuildDeployRole/ImportBaseCodeBuildDeployRole", - "constructInfo": { - "fqn": "aws-cdk-lib.Resource", - "version": "2.173.4" - } - }, - "Resource": { - "id": "Resource", - "path": "flux-oci-image-inference-cdk/BaseCodeBuildDeployRole/Resource", - "attributes": { - "aws:cdk:cloudformation:type": "AWS::IAM::Role", - "aws:cdk:cloudformation:props": { - "assumeRolePolicyDocument": { - "Statement": [ - { - "Action": "sts:AssumeRole", - "Effect": "Allow", - "Principal": { - "Service": "codebuild.amazonaws.com" - } - } - ], - "Version": "2012-10-17" - }, - "roleName": "hwagnisticBaseCodeBuildDeployRole" - } - }, - "constructInfo": { - "fqn": "aws-cdk-lib.aws_iam.CfnRole", - "version": "2.173.4" - } - }, - "DefaultPolicy": { - "id": "DefaultPolicy", - "path": "flux-oci-image-inference-cdk/BaseCodeBuildDeployRole/DefaultPolicy", - "children": { - "Resource": { - "id": "Resource", - "path": "flux-oci-image-inference-cdk/BaseCodeBuildDeployRole/DefaultPolicy/Resource", - "attributes": { - "aws:cdk:cloudformation:type": "AWS::IAM::Policy", - "aws:cdk:cloudformation:props": { - "policyDocument": { - "Statement": [ - { - "Action": [ - "ssm:*", - "s3:*" - ], - "Effect": "Allow", - "Resource": "*" - }, - { - "Action": [ - "logs:CreateLogGroup", - "logs:CreateLogStream", - "logs:PutLogEvents" - ], - "Effect": "Allow", - "Resource": [ - { - "Fn::Join": [ - "", - [ - "arn:", - { - "Ref": "AWS::Partition" - }, - ":logs:us-west-2:133573815653:log-group:/aws/codebuild/", - { - "Ref": "ImageCudAmdBuild23EA25C8" - } - ] - ] - }, - { - "Fn::Join": [ - "", - [ - "arn:", - { - "Ref": "AWS::Partition" - }, - ":logs:us-west-2:133573815653:log-group:/aws/codebuild/", - { - "Ref": "ImageCudAmdBuild23EA25C8" - }, - ":*" - ] - ] - } - ] - }, - { - "Action": [ - "codebuild:CreateReportGroup", - "codebuild:CreateReport", - "codebuild:UpdateReport", - "codebuild:BatchPutTestCases", - "codebuild:BatchPutCodeCoverages" - ], - "Effect": "Allow", - "Resource": { - "Fn::Join": [ - "", - [ - "arn:", - { - "Ref": "AWS::Partition" - }, - ":codebuild:us-west-2:133573815653:report-group/", - { - "Ref": "ImageCudAmdBuild23EA25C8" - }, - "-*" - ] - ] - } - }, - { - "Action": [ - "logs:CreateLogGroup", - "logs:CreateLogStream", - "logs:PutLogEvents" - ], - "Effect": "Allow", - "Resource": [ - { - "Fn::Join": [ - "", - [ - "arn:", - { - "Ref": "AWS::Partition" - }, - ":logs:us-west-2:133573815653:log-group:/aws/codebuild/", - { - "Ref": "ImageCpuArmBuild4791F7AA" - } - ] - ] - }, - { - "Fn::Join": [ - "", - [ - "arn:", - { - "Ref": "AWS::Partition" - }, - ":logs:us-west-2:133573815653:log-group:/aws/codebuild/", - { - "Ref": "ImageCpuArmBuild4791F7AA" - }, - ":*" - ] - ] - } - ] - }, - { - "Action": [ - "codebuild:CreateReportGroup", - "codebuild:CreateReport", - "codebuild:UpdateReport", - "codebuild:BatchPutTestCases", - "codebuild:BatchPutCodeCoverages" - ], - "Effect": "Allow", - "Resource": { - "Fn::Join": [ - "", - [ - "arn:", - { - "Ref": "AWS::Partition" - }, - ":codebuild:us-west-2:133573815653:report-group/", - { - "Ref": "ImageCpuArmBuild4791F7AA" - }, - "-*" - ] - ] - } - }, - { - "Action": [ - "logs:CreateLogGroup", - "logs:CreateLogStream", - "logs:PutLogEvents" - ], - "Effect": "Allow", - "Resource": [ - { - "Fn::Join": [ - "", - [ - "arn:", - { - "Ref": "AWS::Partition" - }, - ":logs:us-west-2:133573815653:log-group:/aws/codebuild/", - { - "Ref": "ImageXlaAmdBuild7511085C" - } - ] - ] - }, - { - "Fn::Join": [ - "", - [ - "arn:", - { - "Ref": "AWS::Partition" - }, - ":logs:us-west-2:133573815653:log-group:/aws/codebuild/", - { - "Ref": "ImageXlaAmdBuild7511085C" - }, - ":*" - ] - ] - } - ] - }, - { - "Action": [ - "codebuild:CreateReportGroup", - "codebuild:CreateReport", - "codebuild:UpdateReport", - "codebuild:BatchPutTestCases", - "codebuild:BatchPutCodeCoverages" - ], - "Effect": "Allow", - "Resource": { - "Fn::Join": [ - "", - [ - "arn:", - { - "Ref": "AWS::Partition" - }, - ":codebuild:us-west-2:133573815653:report-group/", - { - "Ref": "ImageXlaAmdBuild7511085C" - }, - "-*" - ] - ] - } - }, - { - "Action": [ - "logs:CreateLogGroup", - "logs:CreateLogStream", - "logs:PutLogEvents" - ], - "Effect": "Allow", - "Resource": [ - { - "Fn::Join": [ - "", - [ - "arn:", - { - "Ref": "AWS::Partition" - }, - ":logs:us-west-2:133573815653:log-group:/aws/codebuild/", - { - "Ref": "AssetsImageXlaAmdBuild4E3D098F" - } - ] - ] - }, - { - "Fn::Join": [ - "", - [ - "arn:", - { - "Ref": "AWS::Partition" - }, - ":logs:us-west-2:133573815653:log-group:/aws/codebuild/", - { - "Ref": "AssetsImageXlaAmdBuild4E3D098F" - }, - ":*" - ] - ] - } - ] - }, - { - "Action": [ - "codebuild:CreateReportGroup", - "codebuild:CreateReport", - "codebuild:UpdateReport", - "codebuild:BatchPutTestCases", - "codebuild:BatchPutCodeCoverages" - ], - "Effect": "Allow", - "Resource": { - "Fn::Join": [ - "", - [ - "arn:", - { - "Ref": "AWS::Partition" - }, - ":codebuild:us-west-2:133573815653:report-group/", - { - "Ref": "AssetsImageXlaAmdBuild4E3D098F" - }, - "-*" - ] - ] - } - }, - { - "Action": [ - "logs:CreateLogGroup", - "logs:CreateLogStream", - "logs:PutLogEvents" - ], - "Effect": "Allow", - "Resource": [ - { - "Fn::Join": [ - "", - [ - "arn:", - { - "Ref": "AWS::Partition" - }, - ":logs:us-west-2:133573815653:log-group:/aws/codebuild/", - { - "Ref": "AssetsImageCpuArmBuildBC43C501" - } - ] - ] - }, - { - "Fn::Join": [ - "", - [ - "arn:", - { - "Ref": "AWS::Partition" - }, - ":logs:us-west-2:133573815653:log-group:/aws/codebuild/", - { - "Ref": "AssetsImageCpuArmBuildBC43C501" - }, - ":*" - ] - ] - } - ] - }, - { - "Action": [ - "codebuild:CreateReportGroup", - "codebuild:CreateReport", - "codebuild:UpdateReport", - "codebuild:BatchPutTestCases", - "codebuild:BatchPutCodeCoverages" - ], - "Effect": "Allow", - "Resource": { - "Fn::Join": [ - "", - [ - "arn:", - { - "Ref": "AWS::Partition" - }, - ":codebuild:us-west-2:133573815653:report-group/", - { - "Ref": "AssetsImageCpuArmBuildBC43C501" - }, - "-*" - ] - ] - } - }, - { - "Action": [ - "logs:CreateLogGroup", - "logs:CreateLogStream", - "logs:PutLogEvents" - ], - "Effect": "Allow", - "Resource": [ - { - "Fn::Join": [ - "", - [ - "arn:", - { - "Ref": "AWS::Partition" - }, - ":logs:us-west-2:133573815653:log-group:/aws/codebuild/", - { - "Ref": "AssetsImageCudAmdBuild4322D558" - } - ] - ] - }, - { - "Fn::Join": [ - "", - [ - "arn:", - { - "Ref": "AWS::Partition" - }, - ":logs:us-west-2:133573815653:log-group:/aws/codebuild/", - { - "Ref": "AssetsImageCudAmdBuild4322D558" - }, - ":*" - ] - ] - } - ] - }, - { - "Action": [ - "codebuild:CreateReportGroup", - "codebuild:CreateReport", - "codebuild:UpdateReport", - "codebuild:BatchPutTestCases", - "codebuild:BatchPutCodeCoverages" - ], - "Effect": "Allow", - "Resource": { - "Fn::Join": [ - "", - [ - "arn:", - { - "Ref": "AWS::Partition" - }, - ":codebuild:us-west-2:133573815653:report-group/", - { - "Ref": "AssetsImageCudAmdBuild4322D558" - }, - "-*" - ] - ] - } - }, - { - "Action": [ - "ecr:BatchCheckLayerAvailability", - "ecr:GetDownloadUrlForLayer", - "ecr:BatchGetImage", - "ecr:CompleteLayerUpload", - "ecr:UploadLayerPart", - "ecr:InitiateLayerUpload", - "ecr:PutImage" - ], - "Effect": "Allow", - "Resource": { - "Fn::GetAtt": [ - "baserepoCCF23216", - "Arn" - ] - } - }, - { - "Action": "ecr:GetAuthorizationToken", - "Effect": "Allow", - "Resource": "*" - }, - { - "Action": [ - "s3:GetObject*", - "s3:GetBucket*", - "s3:List*" - ], - "Effect": "Allow", - "Resource": [ - { - "Fn::GetAtt": [ - "BuildBasePipelineArtifactsBucket51786A86", - "Arn" - ] - }, - { - "Fn::Join": [ - "", - [ - { - "Fn::GetAtt": [ - "BuildBasePipelineArtifactsBucket51786A86", - "Arn" - ] - }, - "/*" - ] - ] - } - ] - }, - { - "Action": [ - "kms:Decrypt", - "kms:DescribeKey" - ], - "Effect": "Allow", - "Resource": { - "Fn::GetAtt": [ - "BuildBasePipelineArtifactsBucketEncryptionKey04467E09", - "Arn" - ] - } - }, - { - "Action": [ - "kms:Decrypt", - "kms:Encrypt", - "kms:ReEncrypt*", - "kms:GenerateDataKey*" - ], - "Effect": "Allow", - "Resource": { - "Fn::GetAtt": [ - "BuildBasePipelineArtifactsBucketEncryptionKey04467E09", - "Arn" - ] - } - } - ], - "Version": "2012-10-17" - }, - "policyName": "BaseCodeBuildDeployRoleDefaultPolicy93D8F557", - "roles": [ - { - "Ref": "BaseCodeBuildDeployRole2A53BD0D" - } - ] - } - }, - "constructInfo": { - "fqn": "aws-cdk-lib.aws_iam.CfnPolicy", - "version": "2.173.4" - } - } - }, - "constructInfo": { - "fqn": "aws-cdk-lib.aws_iam.Policy", - "version": "2.173.4" - } - } - }, - "constructInfo": { - "fqn": "aws-cdk-lib.aws_iam.Role", - "version": "2.173.4" - } - }, - "githubSecret": { - "id": "githubSecret", - "path": "flux-oci-image-inference-cdk/githubSecret", - "children": { - "Resource": { - "id": "Resource", - "path": "flux-oci-image-inference-cdk/githubSecret/Resource", - "attributes": { - "aws:cdk:cloudformation:type": "AWS::SecretsManager::Secret", - "aws:cdk:cloudformation:props": { - "secretString": { - "Fn::Join": [ - "", - [ - "{\"token\":\"", - { - "Ref": "GITHUBOAUTHTOKEN" - }, - "\"}" - ] - ] - } - } - }, - "constructInfo": { - "fqn": "aws-cdk-lib.aws_secretsmanager.CfnSecret", - "version": "2.173.4" - } - } - }, - "constructInfo": { - "fqn": "aws-cdk-lib.aws_secretsmanager.Secret", - "version": "2.173.4" - } - }, - "githubOAuthTokenRuntimeOutput1": { - "id": "githubOAuthTokenRuntimeOutput1", - "path": "flux-oci-image-inference-cdk/githubOAuthTokenRuntimeOutput1", - "constructInfo": { - "fqn": "aws-cdk-lib.CfnOutput", - "version": "2.173.4" - } - }, - "githubOAuthTokenRuntimeOutput2": { - "id": "githubOAuthTokenRuntimeOutput2", - "path": "flux-oci-image-inference-cdk/githubOAuthTokenRuntimeOutput2", - "constructInfo": { - "fqn": "aws-cdk-lib.CfnOutput", - "version": "2.173.4" - } - }, - "ImageCudAmdBuild": { - "id": "ImageCudAmdBuild", - "path": "flux-oci-image-inference-cdk/ImageCudAmdBuild", - "children": { - "Resource": { - "id": "Resource", - "path": "flux-oci-image-inference-cdk/ImageCudAmdBuild/Resource", - "attributes": { - "aws:cdk:cloudformation:type": "AWS::CodeBuild::Project", - "aws:cdk:cloudformation:props": { - "artifacts": { - "type": "NO_ARTIFACTS" - }, - "cache": { - "type": "LOCAL", - "modes": [ - "LOCAL_DOCKER_LAYER_CACHE", - "LOCAL_CUSTOM_CACHE" - ] - }, - "encryptionKey": { - "Fn::GetAtt": [ - "BuildBasePipelineArtifactsBucketEncryptionKey04467E09", - "Arn" - ] - }, - "environment": { - "type": "LINUX_CONTAINER", - "image": "aws/codebuild/amazonlinux2-x86_64-standard:3.0", - "imagePullCredentialsType": "CODEBUILD", - "privilegedMode": true, - "computeType": "BUILD_GENERAL1_SMALL" - }, - "serviceRole": { - "Fn::GetAtt": [ - "BaseCodeBuildDeployRole2A53BD0D", - "Arn" - ] - }, - "source": { - "type": "NO_SOURCE", - "buildSpec": { - "Fn::Join": [ - "", - [ - "{\n \"version\": \"0.2\",\n \"env\": {\n \"exported-variables\": [\n \"AWS_ACCOUNT_ID\",\n \"AWS_REGION\",\n \"BASE_REPO\",\n \"IMAGE_AMD_CUD_TAG\",\n \"BASE_IMAGE_AMD_CUD_TAG\"\n ]\n },\n \"phases\": {\n \"build\": {\n \"commands\": [\n \"export AWS_ACCOUNT_ID=\\\"133573815653\\\"\",\n \"export AWS_REGION=\\\"us-west-2\\\"\",\n \"export BASE_REPO=\\\"", - { - "Ref": "BASEREPO" - }, - "\\\"\",\n \"export IMAGE_TAG=\\\"", - { - "Ref": "IMAGEAMDCUDTAG" - }, - "\\\"\",\n \"export BASE_IMAGE_TAG=\\\"", - { - "Ref": "BASEIMAGEAMDCUDTAG" - }, - "\\\"\",\n \"cd app\",\n \"chmod +x ./build.sh && ./build.sh\"\n ]\n }\n },\n \"artifacts\": {\n \"files\": [\n \"imageDetail.json\"\n ]\n }\n}" - ] - ] - } - } - } - }, - "constructInfo": { - "fqn": "aws-cdk-lib.aws_codebuild.CfnProject", - "version": "2.173.4" - } - } - }, - "constructInfo": { - "fqn": "aws-cdk-lib.aws_codebuild.Project", - "version": "2.173.4" - } - }, - "ImageCpuArmBuild": { - "id": "ImageCpuArmBuild", - "path": "flux-oci-image-inference-cdk/ImageCpuArmBuild", - "children": { - "Resource": { - "id": "Resource", - "path": "flux-oci-image-inference-cdk/ImageCpuArmBuild/Resource", - "attributes": { - "aws:cdk:cloudformation:type": "AWS::CodeBuild::Project", - "aws:cdk:cloudformation:props": { - "artifacts": { - "type": "NO_ARTIFACTS" - }, - "cache": { - "type": "LOCAL", - "modes": [ - "LOCAL_DOCKER_LAYER_CACHE", - "LOCAL_CUSTOM_CACHE" - ] - }, - "encryptionKey": { - "Fn::GetAtt": [ - "BuildBasePipelineArtifactsBucketEncryptionKey04467E09", - "Arn" - ] - }, - "environment": { - "type": "ARM_CONTAINER", - "image": "aws/codebuild/amazonlinux2-aarch64-standard:2.0", - "imagePullCredentialsType": "CODEBUILD", - "privilegedMode": true, - "computeType": "BUILD_GENERAL1_LARGE" - }, - "serviceRole": { - "Fn::GetAtt": [ - "BaseCodeBuildDeployRole2A53BD0D", - "Arn" - ] - }, - "source": { - "type": "NO_SOURCE", - "buildSpec": { - "Fn::Join": [ - "", - [ - "{\n \"version\": \"0.2\",\n \"env\": {\n \"exported-variables\": [\n \"AWS_ACCOUNT_ID\",\n \"AWS_REGION\",\n \"BASE_REPO\",\n \"IMAGE_ARM_CPU_TAG\",\n \"BASE_IMAGE_ARM_CPU_TAG\"\n ]\n },\n \"phases\": {\n \"build\": {\n \"commands\": [\n \"export AWS_ACCOUNT_ID=\\\"133573815653\\\"\",\n \"export AWS_REGION=\\\"us-west-2\\\"\",\n \"export BASE_REPO=\\\"", - { - "Ref": "BASEREPO" - }, - "\\\"\",\n \"export IMAGE_TAG=\\\"", - { - "Ref": "IMAGEARMCPUTAG" - }, - "\\\"\",\n \"export BASE_IMAGE_TAG=\\\"", - { - "Ref": "BASEIMAGEARMCPUTAG" - }, - "\\\"\",\n \"cd app\",\n \"chmod +x ./build.sh && ./build.sh\"\n ]\n }\n },\n \"artifacts\": {\n \"files\": [\n \"imageDetail.json\"\n ]\n }\n}" - ] - ] - } - } - } - }, - "constructInfo": { - "fqn": "aws-cdk-lib.aws_codebuild.CfnProject", - "version": "2.173.4" - } - } - }, - "constructInfo": { - "fqn": "aws-cdk-lib.aws_codebuild.Project", - "version": "2.173.4" - } - }, - "ImageXlaAmdBuild": { - "id": "ImageXlaAmdBuild", - "path": "flux-oci-image-inference-cdk/ImageXlaAmdBuild", - "children": { - "Resource": { - "id": "Resource", - "path": "flux-oci-image-inference-cdk/ImageXlaAmdBuild/Resource", - "attributes": { - "aws:cdk:cloudformation:type": "AWS::CodeBuild::Project", - "aws:cdk:cloudformation:props": { - "artifacts": { - "type": "NO_ARTIFACTS" - }, - "cache": { - "type": "LOCAL", - "modes": [ - "LOCAL_DOCKER_LAYER_CACHE", - "LOCAL_CUSTOM_CACHE" - ] - }, - "encryptionKey": { - "Fn::GetAtt": [ - "BuildBasePipelineArtifactsBucketEncryptionKey04467E09", - "Arn" - ] - }, - "environment": { - "type": "LINUX_CONTAINER", - "image": "aws/codebuild/amazonlinux2-x86_64-standard:3.0", - "imagePullCredentialsType": "CODEBUILD", - "privilegedMode": true, - "computeType": "BUILD_GENERAL1_SMALL" - }, - "serviceRole": { - "Fn::GetAtt": [ - "BaseCodeBuildDeployRole2A53BD0D", - "Arn" - ] - }, - "source": { - "type": "NO_SOURCE", - "buildSpec": { - "Fn::Join": [ - "", - [ - "{\n \"version\": \"0.2\",\n \"env\": {\n \"exported-variables\": [\n \"AWS_ACCOUNT_ID\",\n \"AWS_REGION\",\n \"BASE_REPO\",\n \"IMAGE_AMD_XLA_TAG\",\n \"BASE_IMAGE_AMD_XLA_TAG\"\n ]\n },\n \"phases\": {\n \"build\": {\n \"commands\": [\n \"export AWS_ACCOUNT_ID=\\\"133573815653\\\"\",\n \"export AWS_REGION=\\\"us-west-2\\\"\",\n \"export BASE_REPO=\\\"", - { - "Ref": "BASEREPO" - }, - "\\\"\",\n \"export IMAGE_TAG=\\\"", - { - "Ref": "IMAGEAMDXLATAG" - }, - "\\\"\",\n \"export BASE_IMAGE_TAG=\\\"", - { - "Ref": "BASEIMAGEAMDXLATAG" - }, - "\\\"\",\n \"cd app\",\n \"chmod +x ./build.sh && ./build.sh\"\n ]\n }\n },\n \"artifacts\": {\n \"files\": [\n \"imageDetail.json\"\n ]\n }\n}" - ] - ] - } - } - } - }, - "constructInfo": { - "fqn": "aws-cdk-lib.aws_codebuild.CfnProject", - "version": "2.173.4" - } - } - }, - "constructInfo": { - "fqn": "aws-cdk-lib.aws_codebuild.Project", - "version": "2.173.4" - } - }, - "AssetsImageXlaAmdBuild": { - "id": "AssetsImageXlaAmdBuild", - "path": "flux-oci-image-inference-cdk/AssetsImageXlaAmdBuild", - "children": { - "Resource": { - "id": "Resource", - "path": "flux-oci-image-inference-cdk/AssetsImageXlaAmdBuild/Resource", - "attributes": { - "aws:cdk:cloudformation:type": "AWS::CodeBuild::Project", - "aws:cdk:cloudformation:props": { - "artifacts": { - "type": "NO_ARTIFACTS" - }, - "cache": { - "type": "LOCAL", - "modes": [ - "LOCAL_DOCKER_LAYER_CACHE", - "LOCAL_CUSTOM_CACHE" - ] - }, - "encryptionKey": { - "Fn::GetAtt": [ - "BuildBasePipelineArtifactsBucketEncryptionKey04467E09", - "Arn" - ] - }, - "environment": { - "type": "LINUX_CONTAINER", - "image": "aws/codebuild/amazonlinux2-x86_64-standard:3.0", - "imagePullCredentialsType": "CODEBUILD", - "privilegedMode": true, - "computeType": "BUILD_GENERAL1_SMALL" - }, - "serviceRole": { - "Fn::GetAtt": [ - "BaseCodeBuildDeployRole2A53BD0D", - "Arn" - ] - }, - "source": { - "type": "NO_SOURCE", - "buildSpec": { - "Fn::Join": [ - "", - [ - "{\n \"version\": \"0.2\",\n \"env\": {\n \"exported-variables\": [\n \"AWS_ACCOUNT_ID\",\n \"AWS_REGION\",\n \"BASE_REPO\",\n \"IMAGE_AMD_XLA_TAG\",\n \"BASE_IMAGE_AMD_XLA_TAG\"\n ]\n },\n \"phases\": {\n \"build\": {\n \"commands\": [\n \"export AWS_ACCOUNT_ID=\\\"133573815653\\\"\",\n \"export AWS_REGION=\\\"us-west-2\\\"\",\n \"export BASE_REPO=\\\"", - { - "Ref": "BASEREPO" - }, - "\\\"\",\n \"export IMAGE_TAG=\\\"", - { - "Ref": "IMAGEAMDXLATAG" - }, - "\\\"\",\n \"export BASE_IMAGE_TAG=\\\"", - { - "Ref": "BASEIMAGEAMDXLATAG" - }, - "\\\"\",\n \"cd app\",\n \"chmod +x ./build-assets.sh && ./build-assets.sh\"\n ]\n }\n },\n \"artifacts\": {\n \"files\": [\n \"imageDetail.json\"\n ]\n }\n}" - ] - ] - } - } - } - }, - "constructInfo": { - "fqn": "aws-cdk-lib.aws_codebuild.CfnProject", - "version": "2.173.4" - } - } - }, - "constructInfo": { - "fqn": "aws-cdk-lib.aws_codebuild.Project", - "version": "2.173.4" - } - }, - "AssetsImageCpuArmBuild": { - "id": "AssetsImageCpuArmBuild", - "path": "flux-oci-image-inference-cdk/AssetsImageCpuArmBuild", - "children": { - "Resource": { - "id": "Resource", - "path": "flux-oci-image-inference-cdk/AssetsImageCpuArmBuild/Resource", - "attributes": { - "aws:cdk:cloudformation:type": "AWS::CodeBuild::Project", - "aws:cdk:cloudformation:props": { - "artifacts": { - "type": "NO_ARTIFACTS" - }, - "cache": { - "type": "LOCAL", - "modes": [ - "LOCAL_DOCKER_LAYER_CACHE", - "LOCAL_CUSTOM_CACHE" - ] - }, - "encryptionKey": { - "Fn::GetAtt": [ - "BuildBasePipelineArtifactsBucketEncryptionKey04467E09", - "Arn" - ] - }, - "environment": { - "type": "ARM_CONTAINER", - "image": "aws/codebuild/amazonlinux2-aarch64-standard:2.0", - "imagePullCredentialsType": "CODEBUILD", - "privilegedMode": true, - "computeType": "BUILD_GENERAL1_LARGE" - }, - "serviceRole": { - "Fn::GetAtt": [ - "BaseCodeBuildDeployRole2A53BD0D", - "Arn" - ] - }, - "source": { - "type": "NO_SOURCE", - "buildSpec": { - "Fn::Join": [ - "", - [ - "{\n \"version\": \"0.2\",\n \"env\": {\n \"exported-variables\": [\n \"AWS_ACCOUNT_ID\",\n \"AWS_REGION\",\n \"BASE_REPO\",\n \"IMAGE_ARM_CPU_TAG\",\n \"BASE_IMAGE_ARM_CPU_TAG\"\n ]\n },\n \"phases\": {\n \"build\": {\n \"commands\": [\n \"export AWS_ACCOUNT_ID=\\\"133573815653\\\"\",\n \"export AWS_REGION=\\\"us-west-2\\\"\",\n \"export BASE_REPO=\\\"", - { - "Ref": "BASEREPO" - }, - "\\\"\",\n \"export IMAGE_TAG=\\\"", - { - "Ref": "IMAGEARMCPUTAG" - }, - "\\\"\",\n \"export BASE_IMAGE_TAG=\\\"", - { - "Ref": "BASEIMAGEARMCPUTAG" - }, - "\\\"\",\n \"cd app\",\n \"chmod +x ./build-assets.sh && ./build-assets.sh\"\n ]\n }\n },\n \"artifacts\": {\n \"files\": [\n \"imageDetail.json\"\n ]\n }\n}" - ] - ] - } - } - } - }, - "constructInfo": { - "fqn": "aws-cdk-lib.aws_codebuild.CfnProject", - "version": "2.173.4" - } - } - }, - "constructInfo": { - "fqn": "aws-cdk-lib.aws_codebuild.Project", - "version": "2.173.4" - } - }, - "AssetsImageCudAmdBuild": { - "id": "AssetsImageCudAmdBuild", - "path": "flux-oci-image-inference-cdk/AssetsImageCudAmdBuild", - "children": { - "Resource": { - "id": "Resource", - "path": "flux-oci-image-inference-cdk/AssetsImageCudAmdBuild/Resource", - "attributes": { - "aws:cdk:cloudformation:type": "AWS::CodeBuild::Project", - "aws:cdk:cloudformation:props": { - "artifacts": { - "type": "NO_ARTIFACTS" - }, - "cache": { - "type": "LOCAL", - "modes": [ - "LOCAL_DOCKER_LAYER_CACHE", - "LOCAL_CUSTOM_CACHE" - ] - }, - "encryptionKey": { - "Fn::GetAtt": [ - "BuildBasePipelineArtifactsBucketEncryptionKey04467E09", - "Arn" - ] - }, - "environment": { - "type": "LINUX_CONTAINER", - "image": "aws/codebuild/amazonlinux2-x86_64-standard:3.0", - "imagePullCredentialsType": "CODEBUILD", - "privilegedMode": true, - "computeType": "BUILD_GENERAL1_SMALL" - }, - "serviceRole": { - "Fn::GetAtt": [ - "BaseCodeBuildDeployRole2A53BD0D", - "Arn" - ] - }, - "source": { - "type": "NO_SOURCE", - "buildSpec": { - "Fn::Join": [ - "", - [ - "{\n \"version\": \"0.2\",\n \"env\": {\n \"exported-variables\": [\n \"AWS_ACCOUNT_ID\",\n \"AWS_REGION\",\n \"BASE_REPO\",\n \"IMAGE_AMD_CUD_TAG\",\n \"BASE_IMAGE_AMD_CUD_TAG\"\n ]\n },\n \"phases\": {\n \"build\": {\n \"commands\": [\n \"export AWS_ACCOUNT_ID=\\\"133573815653\\\"\",\n \"export AWS_REGION=\\\"us-west-2\\\"\",\n \"export BASE_REPO=\\\"", - { - "Ref": "BASEREPO" - }, - "\\\"\",\n \"export IMAGE_TAG=\\\"", - { - "Ref": "IMAGEAMDCUDTAG" - }, - "\\\"\",\n \"export BASE_IMAGE_TAG=\\\"", - { - "Ref": "BASEIMAGEAMDCUDTAG" - }, - "\\\"\",\n \"cd app\",\n \"chmod +x ./build-assets.sh && ./build-assets.sh\"\n ]\n }\n },\n \"artifacts\": {\n \"files\": [\n \"imageDetail.json\"\n ]\n }\n}" - ] - ] - } - } - } - }, - "constructInfo": { - "fqn": "aws-cdk-lib.aws_codebuild.CfnProject", - "version": "2.173.4" - } - } - }, - "constructInfo": { - "fqn": "aws-cdk-lib.aws_codebuild.Project", - "version": "2.173.4" - } - }, - "BuildBasePipeline": { - "id": "BuildBasePipeline", - "path": "flux-oci-image-inference-cdk/BuildBasePipeline", - "children": { - "ArtifactsBucketEncryptionKey": { - "id": "ArtifactsBucketEncryptionKey", - "path": "flux-oci-image-inference-cdk/BuildBasePipeline/ArtifactsBucketEncryptionKey", - "children": { - "Resource": { - "id": "Resource", - "path": "flux-oci-image-inference-cdk/BuildBasePipeline/ArtifactsBucketEncryptionKey/Resource", - "attributes": { - "aws:cdk:cloudformation:type": "AWS::KMS::Key", - "aws:cdk:cloudformation:props": { - "keyPolicy": { - "Statement": [ - { - "Action": "kms:*", - "Effect": "Allow", - "Principal": { - "AWS": { - "Fn::Join": [ - "", - [ - "arn:", - { - "Ref": "AWS::Partition" - }, - ":iam::133573815653:root" - ] - ] - } - }, - "Resource": "*" - } - ], - "Version": "2012-10-17" - } - } - }, - "constructInfo": { - "fqn": "aws-cdk-lib.aws_kms.CfnKey", - "version": "2.173.4" - } - } - }, - "constructInfo": { - "fqn": "aws-cdk-lib.aws_kms.Key", - "version": "2.173.4" - } - }, - "ArtifactsBucketEncryptionKeyAlias": { - "id": "ArtifactsBucketEncryptionKeyAlias", - "path": "flux-oci-image-inference-cdk/BuildBasePipeline/ArtifactsBucketEncryptionKeyAlias", - "children": { - "Resource": { - "id": "Resource", - "path": "flux-oci-image-inference-cdk/BuildBasePipeline/ArtifactsBucketEncryptionKeyAlias/Resource", - "attributes": { - "aws:cdk:cloudformation:type": "AWS::KMS::Alias", - "aws:cdk:cloudformation:props": { - "aliasName": "alias/codepipeline-fluxociimageinferencecdkbuildbasepipeline01a0da38", - "targetKeyId": { - "Fn::GetAtt": [ - "BuildBasePipelineArtifactsBucketEncryptionKey04467E09", - "Arn" - ] - } - } - }, - "constructInfo": { - "fqn": "aws-cdk-lib.aws_kms.CfnAlias", - "version": "2.173.4" - } - } - }, - "constructInfo": { - "fqn": "aws-cdk-lib.aws_kms.Alias", - "version": "2.173.4" - } - }, - "ArtifactsBucket": { - "id": "ArtifactsBucket", - "path": "flux-oci-image-inference-cdk/BuildBasePipeline/ArtifactsBucket", - "children": { - "Resource": { - "id": "Resource", - "path": "flux-oci-image-inference-cdk/BuildBasePipeline/ArtifactsBucket/Resource", - "attributes": { - "aws:cdk:cloudformation:type": "AWS::S3::Bucket", - "aws:cdk:cloudformation:props": { - "bucketEncryption": { - "serverSideEncryptionConfiguration": [ - { - "serverSideEncryptionByDefault": { - "sseAlgorithm": "aws:kms", - "kmsMasterKeyId": { - "Fn::GetAtt": [ - "BuildBasePipelineArtifactsBucketEncryptionKey04467E09", - "Arn" - ] - } - } - } - ] - }, - "publicAccessBlockConfiguration": { - "blockPublicAcls": true, - "blockPublicPolicy": true, - "ignorePublicAcls": true, - "restrictPublicBuckets": true - } - } - }, - "constructInfo": { - "fqn": "aws-cdk-lib.aws_s3.CfnBucket", - "version": "2.173.4" - } - }, - "Policy": { - "id": "Policy", - "path": "flux-oci-image-inference-cdk/BuildBasePipeline/ArtifactsBucket/Policy", - "children": { - "Resource": { - "id": "Resource", - "path": "flux-oci-image-inference-cdk/BuildBasePipeline/ArtifactsBucket/Policy/Resource", - "attributes": { - "aws:cdk:cloudformation:type": "AWS::S3::BucketPolicy", - "aws:cdk:cloudformation:props": { - "bucket": { - "Ref": "BuildBasePipelineArtifactsBucket51786A86" - }, - "policyDocument": { - "Statement": [ - { - "Action": "s3:*", - "Condition": { - "Bool": { - "aws:SecureTransport": "false" - } - }, - "Effect": "Deny", - "Principal": { - "AWS": "*" - }, - "Resource": [ - { - "Fn::GetAtt": [ - "BuildBasePipelineArtifactsBucket51786A86", - "Arn" - ] - }, - { - "Fn::Join": [ - "", - [ - { - "Fn::GetAtt": [ - "BuildBasePipelineArtifactsBucket51786A86", - "Arn" - ] - }, - "/*" - ] - ] - } - ] - } - ], - "Version": "2012-10-17" - } - } - }, - "constructInfo": { - "fqn": "aws-cdk-lib.aws_s3.CfnBucketPolicy", - "version": "2.173.4" - } - } - }, - "constructInfo": { - "fqn": "aws-cdk-lib.aws_s3.BucketPolicy", - "version": "2.173.4" - } - } - }, - "constructInfo": { - "fqn": "aws-cdk-lib.aws_s3.Bucket", - "version": "2.173.4" - } - }, - "Role": { - "id": "Role", - "path": "flux-oci-image-inference-cdk/BuildBasePipeline/Role", - "children": { - "ImportRole": { - "id": "ImportRole", - "path": "flux-oci-image-inference-cdk/BuildBasePipeline/Role/ImportRole", - "constructInfo": { - "fqn": "aws-cdk-lib.Resource", - "version": "2.173.4" - } - }, - "Resource": { - "id": "Resource", - "path": "flux-oci-image-inference-cdk/BuildBasePipeline/Role/Resource", - "attributes": { - "aws:cdk:cloudformation:type": "AWS::IAM::Role", - "aws:cdk:cloudformation:props": { - "assumeRolePolicyDocument": { - "Statement": [ - { - "Action": "sts:AssumeRole", - "Effect": "Allow", - "Principal": { - "Service": "codepipeline.amazonaws.com" - } - } - ], - "Version": "2012-10-17" - } - } - }, - "constructInfo": { - "fqn": "aws-cdk-lib.aws_iam.CfnRole", - "version": "2.173.4" - } - }, - "DefaultPolicy": { - "id": "DefaultPolicy", - "path": "flux-oci-image-inference-cdk/BuildBasePipeline/Role/DefaultPolicy", - "children": { - "Resource": { - "id": "Resource", - "path": "flux-oci-image-inference-cdk/BuildBasePipeline/Role/DefaultPolicy/Resource", - "attributes": { - "aws:cdk:cloudformation:type": "AWS::IAM::Policy", - "aws:cdk:cloudformation:props": { - "policyDocument": { - "Statement": [ - { - "Action": [ - "s3:GetObject*", - "s3:GetBucket*", - "s3:List*", - "s3:DeleteObject*", - "s3:PutObject", - "s3:PutObjectLegalHold", - "s3:PutObjectRetention", - "s3:PutObjectTagging", - "s3:PutObjectVersionTagging", - "s3:Abort*" - ], - "Effect": "Allow", - "Resource": [ - { - "Fn::GetAtt": [ - "BuildBasePipelineArtifactsBucket51786A86", - "Arn" - ] - }, - { - "Fn::Join": [ - "", - [ - { - "Fn::GetAtt": [ - "BuildBasePipelineArtifactsBucket51786A86", - "Arn" - ] - }, - "/*" - ] - ] - } - ] - }, - { - "Action": [ - "kms:Decrypt", - "kms:DescribeKey", - "kms:Encrypt", - "kms:ReEncrypt*", - "kms:GenerateDataKey*" - ], - "Effect": "Allow", - "Resource": { - "Fn::GetAtt": [ - "BuildBasePipelineArtifactsBucketEncryptionKey04467E09", - "Arn" - ] - } - }, - { - "Action": "sts:AssumeRole", - "Effect": "Allow", - "Resource": { - "Fn::GetAtt": [ - "BuildBasePipelineImageBuildAssetsImageXlaAmdBuildCodePipelineActionRole7C093488", - "Arn" - ] - } - }, - { - "Action": "sts:AssumeRole", - "Effect": "Allow", - "Resource": { - "Fn::GetAtt": [ - "BuildBasePipelineImageBuildAssetsImageCudAmdBuildCodePipelineActionRole7F47990C", - "Arn" - ] - } - }, - { - "Action": "sts:AssumeRole", - "Effect": "Allow", - "Resource": { - "Fn::GetAtt": [ - "BuildBasePipelineImageBuildAssetsImageCpuArmBuildCodePipelineActionRole67BCBC26", - "Arn" - ] - } - }, - { - "Action": "sts:AssumeRole", - "Effect": "Allow", - "Resource": { - "Fn::GetAtt": [ - "BuildBasePipelineImageBuildBaseImageAmdXlaBuildCodePipelineActionRoleD9124FCE", - "Arn" - ] - } - }, - { - "Action": "sts:AssumeRole", - "Effect": "Allow", - "Resource": { - "Fn::GetAtt": [ - "BuildBasePipelineImageBuildBaseImageArmCpuBuildCodePipelineActionRole4DF7F5DE", - "Arn" - ] - } - }, - { - "Action": "sts:AssumeRole", - "Effect": "Allow", - "Resource": { - "Fn::GetAtt": [ - "BuildBasePipelineImageBuildBaseImageAmdCudBuildCodePipelineActionRoleA29F5F5F", - "Arn" - ] - } - } - ], - "Version": "2012-10-17" - }, - "policyName": "BuildBasePipelineRoleDefaultPolicy7CA9EFF0", - "roles": [ - { - "Ref": "BuildBasePipelineRole8C8F77AD" - } - ] - } - }, - "constructInfo": { - "fqn": "aws-cdk-lib.aws_iam.CfnPolicy", - "version": "2.173.4" - } - } - }, - "constructInfo": { - "fqn": "aws-cdk-lib.aws_iam.Policy", - "version": "2.173.4" - } - } - }, - "constructInfo": { - "fqn": "aws-cdk-lib.aws_iam.Role", - "version": "2.173.4" - } - }, - "Resource": { - "id": "Resource", - "path": "flux-oci-image-inference-cdk/BuildBasePipeline/Resource", - "attributes": { - "aws:cdk:cloudformation:type": "AWS::CodePipeline::Pipeline", - "aws:cdk:cloudformation:props": { - "artifactStore": { - "type": "S3", - "location": { - "Ref": "BuildBasePipelineArtifactsBucket51786A86" - }, - "encryptionKey": { - "type": "KMS", - "id": { - "Fn::GetAtt": [ - "BuildBasePipelineArtifactsBucketEncryptionKey04467E09", - "Arn" - ] - } - } - }, - "roleArn": { - "Fn::GetAtt": [ - "BuildBasePipelineRole8C8F77AD", - "Arn" - ] - }, - "stages": [ - { - "name": "Source", - "actions": [ - { - "name": "GitHub_Source", - "outputArtifacts": [ - { - "name": "Artifact_Source_GitHub_Source" - } - ], - "actionTypeId": { - "category": "Source", - "version": "1", - "owner": "ThirdParty", - "provider": "GitHub" - }, - "configuration": { - "Owner": { - "Ref": "GITHUBUSER" - }, - "Repo": { - "Ref": "GITHUBREPO" - }, - "Branch": { - "Ref": "GITHUBBRANCH" - }, - "OAuthToken": "{{resolve:secretsmanager:githubtoken:SecretString:token::}}", - "PollForSourceChanges": false - }, - "runOrder": 1 - } - ] - }, - { - "name": "ImageBuild", - "actions": [ - { - "name": "AssetsImageXlaAmdBuild", - "inputArtifacts": [ - { - "name": "Artifact_Source_GitHub_Source" - } - ], - "actionTypeId": { - "category": "Build", - "version": "1", - "owner": "AWS", - "provider": "CodeBuild" - }, - "configuration": { - "ProjectName": { - "Ref": "AssetsImageXlaAmdBuild4E3D098F" - } - }, - "runOrder": 1, - "roleArn": { - "Fn::GetAtt": [ - "BuildBasePipelineImageBuildAssetsImageXlaAmdBuildCodePipelineActionRole7C093488", - "Arn" - ] - } - }, - { - "name": "AssetsImageCudAmdBuild", - "inputArtifacts": [ - { - "name": "Artifact_Source_GitHub_Source" - } - ], - "actionTypeId": { - "category": "Build", - "version": "1", - "owner": "AWS", - "provider": "CodeBuild" - }, - "configuration": { - "ProjectName": { - "Ref": "AssetsImageCudAmdBuild4322D558" - } - }, - "runOrder": 1, - "roleArn": { - "Fn::GetAtt": [ - "BuildBasePipelineImageBuildAssetsImageCudAmdBuildCodePipelineActionRole7F47990C", - "Arn" - ] - } - }, - { - "name": "AssetsImageCpuArmBuild", - "inputArtifacts": [ - { - "name": "Artifact_Source_GitHub_Source" - } - ], - "actionTypeId": { - "category": "Build", - "version": "1", - "owner": "AWS", - "provider": "CodeBuild" - }, - "configuration": { - "ProjectName": { - "Ref": "AssetsImageCpuArmBuildBC43C501" - } - }, - "runOrder": 1, - "roleArn": { - "Fn::GetAtt": [ - "BuildBasePipelineImageBuildAssetsImageCpuArmBuildCodePipelineActionRole67BCBC26", - "Arn" - ] - } - }, - { - "name": "BaseImageAmdXlaBuild", - "inputArtifacts": [ - { - "name": "Artifact_Source_GitHub_Source" - } - ], - "actionTypeId": { - "category": "Build", - "version": "1", - "owner": "AWS", - "provider": "CodeBuild" - }, - "configuration": { - "ProjectName": { - "Ref": "ImageXlaAmdBuild7511085C" - } - }, - "runOrder": 2, - "roleArn": { - "Fn::GetAtt": [ - "BuildBasePipelineImageBuildBaseImageAmdXlaBuildCodePipelineActionRoleD9124FCE", - "Arn" - ] - } - }, - { - "name": "BaseImageArmCpuBuild", - "inputArtifacts": [ - { - "name": "Artifact_Source_GitHub_Source" - } - ], - "actionTypeId": { - "category": "Build", - "version": "1", - "owner": "AWS", - "provider": "CodeBuild" - }, - "configuration": { - "ProjectName": { - "Ref": "ImageCpuArmBuild4791F7AA" - } - }, - "runOrder": 2, - "roleArn": { - "Fn::GetAtt": [ - "BuildBasePipelineImageBuildBaseImageArmCpuBuildCodePipelineActionRole4DF7F5DE", - "Arn" - ] - } - }, - { - "name": "BaseImageAmdCudBuild", - "inputArtifacts": [ - { - "name": "Artifact_Source_GitHub_Source" - } - ], - "actionTypeId": { - "category": "Build", - "version": "1", - "owner": "AWS", - "provider": "CodeBuild" - }, - "configuration": { - "ProjectName": { - "Ref": "ImageCudAmdBuild23EA25C8" - } - }, - "runOrder": 2, - "roleArn": { - "Fn::GetAtt": [ - "BuildBasePipelineImageBuildBaseImageAmdCudBuildCodePipelineActionRoleA29F5F5F", - "Arn" - ] - } - } - ] - } - ] - } - }, - "constructInfo": { - "fqn": "aws-cdk-lib.aws_codepipeline.CfnPipeline", - "version": "2.173.4" - } - }, - "Source": { - "id": "Source", - "path": "flux-oci-image-inference-cdk/BuildBasePipeline/Source", - "children": { - "GitHub_Source": { - "id": "GitHub_Source", - "path": "flux-oci-image-inference-cdk/BuildBasePipeline/Source/GitHub_Source", - "children": { - "WebhookResource": { - "id": "WebhookResource", - "path": "flux-oci-image-inference-cdk/BuildBasePipeline/Source/GitHub_Source/WebhookResource", - "attributes": { - "aws:cdk:cloudformation:type": "AWS::CodePipeline::Webhook", - "aws:cdk:cloudformation:props": { - "authentication": "GITHUB_HMAC", - "authenticationConfiguration": { - "secretToken": "{{resolve:secretsmanager:githubtoken:SecretString:token::}}" - }, - "filters": [ - { - "jsonPath": "$.ref", - "matchEquals": "refs/heads/{Branch}" - } - ], - "registerWithThirdParty": true, - "targetAction": "GitHub_Source", - "targetPipeline": { - "Ref": "BuildBasePipelineE93F0563" - }, - "targetPipelineVersion": 1 - } - }, - "constructInfo": { - "fqn": "aws-cdk-lib.aws_codepipeline.CfnWebhook", - "version": "2.173.4" - } - } - }, - "constructInfo": { - "fqn": "constructs.Construct", - "version": "10.4.2" - } - } - }, - "constructInfo": { - "fqn": "constructs.Construct", - "version": "10.4.2" - } - }, - "ImageBuild": { - "id": "ImageBuild", - "path": "flux-oci-image-inference-cdk/BuildBasePipeline/ImageBuild", - "children": { - "AssetsImageXlaAmdBuild": { - "id": "AssetsImageXlaAmdBuild", - "path": "flux-oci-image-inference-cdk/BuildBasePipeline/ImageBuild/AssetsImageXlaAmdBuild", - "children": { - "CodePipelineActionRole": { - "id": "CodePipelineActionRole", - "path": "flux-oci-image-inference-cdk/BuildBasePipeline/ImageBuild/AssetsImageXlaAmdBuild/CodePipelineActionRole", - "children": { - "ImportCodePipelineActionRole": { - "id": "ImportCodePipelineActionRole", - "path": "flux-oci-image-inference-cdk/BuildBasePipeline/ImageBuild/AssetsImageXlaAmdBuild/CodePipelineActionRole/ImportCodePipelineActionRole", - "constructInfo": { - "fqn": "aws-cdk-lib.Resource", - "version": "2.173.4" - } - }, - "Resource": { - "id": "Resource", - "path": "flux-oci-image-inference-cdk/BuildBasePipeline/ImageBuild/AssetsImageXlaAmdBuild/CodePipelineActionRole/Resource", - "attributes": { - "aws:cdk:cloudformation:type": "AWS::IAM::Role", - "aws:cdk:cloudformation:props": { - "assumeRolePolicyDocument": { - "Statement": [ - { - "Action": "sts:AssumeRole", - "Effect": "Allow", - "Principal": { - "AWS": { - "Fn::Join": [ - "", - [ - "arn:", - { - "Ref": "AWS::Partition" - }, - ":iam::133573815653:root" - ] - ] - } - } - } - ], - "Version": "2012-10-17" - } - } - }, - "constructInfo": { - "fqn": "aws-cdk-lib.aws_iam.CfnRole", - "version": "2.173.4" - } - }, - "DefaultPolicy": { - "id": "DefaultPolicy", - "path": "flux-oci-image-inference-cdk/BuildBasePipeline/ImageBuild/AssetsImageXlaAmdBuild/CodePipelineActionRole/DefaultPolicy", - "children": { - "Resource": { - "id": "Resource", - "path": "flux-oci-image-inference-cdk/BuildBasePipeline/ImageBuild/AssetsImageXlaAmdBuild/CodePipelineActionRole/DefaultPolicy/Resource", - "attributes": { - "aws:cdk:cloudformation:type": "AWS::IAM::Policy", - "aws:cdk:cloudformation:props": { - "policyDocument": { - "Statement": [ - { - "Action": [ - "codebuild:BatchGetBuilds", - "codebuild:StartBuild", - "codebuild:StopBuild" - ], - "Effect": "Allow", - "Resource": { - "Fn::GetAtt": [ - "AssetsImageXlaAmdBuild4E3D098F", - "Arn" - ] - } - } - ], - "Version": "2012-10-17" - }, - "policyName": "BuildBasePipelineImageBuildAssetsImageXlaAmdBuildCodePipelineActionRoleDefaultPolicyB3BE9D03", - "roles": [ - { - "Ref": "BuildBasePipelineImageBuildAssetsImageXlaAmdBuildCodePipelineActionRole7C093488" - } - ] - } - }, - "constructInfo": { - "fqn": "aws-cdk-lib.aws_iam.CfnPolicy", - "version": "2.173.4" - } - } - }, - "constructInfo": { - "fqn": "aws-cdk-lib.aws_iam.Policy", - "version": "2.173.4" - } - } - }, - "constructInfo": { - "fqn": "aws-cdk-lib.aws_iam.Role", - "version": "2.173.4" - } - } - }, - "constructInfo": { - "fqn": "constructs.Construct", - "version": "10.4.2" - } - }, - "AssetsImageCudAmdBuild": { - "id": "AssetsImageCudAmdBuild", - "path": "flux-oci-image-inference-cdk/BuildBasePipeline/ImageBuild/AssetsImageCudAmdBuild", - "children": { - "CodePipelineActionRole": { - "id": "CodePipelineActionRole", - "path": "flux-oci-image-inference-cdk/BuildBasePipeline/ImageBuild/AssetsImageCudAmdBuild/CodePipelineActionRole", - "children": { - "ImportCodePipelineActionRole": { - "id": "ImportCodePipelineActionRole", - "path": "flux-oci-image-inference-cdk/BuildBasePipeline/ImageBuild/AssetsImageCudAmdBuild/CodePipelineActionRole/ImportCodePipelineActionRole", - "constructInfo": { - "fqn": "aws-cdk-lib.Resource", - "version": "2.173.4" - } - }, - "Resource": { - "id": "Resource", - "path": "flux-oci-image-inference-cdk/BuildBasePipeline/ImageBuild/AssetsImageCudAmdBuild/CodePipelineActionRole/Resource", - "attributes": { - "aws:cdk:cloudformation:type": "AWS::IAM::Role", - "aws:cdk:cloudformation:props": { - "assumeRolePolicyDocument": { - "Statement": [ - { - "Action": "sts:AssumeRole", - "Effect": "Allow", - "Principal": { - "AWS": { - "Fn::Join": [ - "", - [ - "arn:", - { - "Ref": "AWS::Partition" - }, - ":iam::133573815653:root" - ] - ] - } - } - } - ], - "Version": "2012-10-17" - } - } - }, - "constructInfo": { - "fqn": "aws-cdk-lib.aws_iam.CfnRole", - "version": "2.173.4" - } - }, - "DefaultPolicy": { - "id": "DefaultPolicy", - "path": "flux-oci-image-inference-cdk/BuildBasePipeline/ImageBuild/AssetsImageCudAmdBuild/CodePipelineActionRole/DefaultPolicy", - "children": { - "Resource": { - "id": "Resource", - "path": "flux-oci-image-inference-cdk/BuildBasePipeline/ImageBuild/AssetsImageCudAmdBuild/CodePipelineActionRole/DefaultPolicy/Resource", - "attributes": { - "aws:cdk:cloudformation:type": "AWS::IAM::Policy", - "aws:cdk:cloudformation:props": { - "policyDocument": { - "Statement": [ - { - "Action": [ - "codebuild:BatchGetBuilds", - "codebuild:StartBuild", - "codebuild:StopBuild" - ], - "Effect": "Allow", - "Resource": { - "Fn::GetAtt": [ - "AssetsImageCudAmdBuild4322D558", - "Arn" - ] - } - } - ], - "Version": "2012-10-17" - }, - "policyName": "BuildBasePipelineImageBuildAssetsImageCudAmdBuildCodePipelineActionRoleDefaultPolicy44AAF344", - "roles": [ - { - "Ref": "BuildBasePipelineImageBuildAssetsImageCudAmdBuildCodePipelineActionRole7F47990C" - } - ] - } - }, - "constructInfo": { - "fqn": "aws-cdk-lib.aws_iam.CfnPolicy", - "version": "2.173.4" - } - } - }, - "constructInfo": { - "fqn": "aws-cdk-lib.aws_iam.Policy", - "version": "2.173.4" - } - } - }, - "constructInfo": { - "fqn": "aws-cdk-lib.aws_iam.Role", - "version": "2.173.4" - } - } - }, - "constructInfo": { - "fqn": "constructs.Construct", - "version": "10.4.2" - } - }, - "AssetsImageCpuArmBuild": { - "id": "AssetsImageCpuArmBuild", - "path": "flux-oci-image-inference-cdk/BuildBasePipeline/ImageBuild/AssetsImageCpuArmBuild", - "children": { - "CodePipelineActionRole": { - "id": "CodePipelineActionRole", - "path": "flux-oci-image-inference-cdk/BuildBasePipeline/ImageBuild/AssetsImageCpuArmBuild/CodePipelineActionRole", - "children": { - "ImportCodePipelineActionRole": { - "id": "ImportCodePipelineActionRole", - "path": "flux-oci-image-inference-cdk/BuildBasePipeline/ImageBuild/AssetsImageCpuArmBuild/CodePipelineActionRole/ImportCodePipelineActionRole", - "constructInfo": { - "fqn": "aws-cdk-lib.Resource", - "version": "2.173.4" - } - }, - "Resource": { - "id": "Resource", - "path": "flux-oci-image-inference-cdk/BuildBasePipeline/ImageBuild/AssetsImageCpuArmBuild/CodePipelineActionRole/Resource", - "attributes": { - "aws:cdk:cloudformation:type": "AWS::IAM::Role", - "aws:cdk:cloudformation:props": { - "assumeRolePolicyDocument": { - "Statement": [ - { - "Action": "sts:AssumeRole", - "Effect": "Allow", - "Principal": { - "AWS": { - "Fn::Join": [ - "", - [ - "arn:", - { - "Ref": "AWS::Partition" - }, - ":iam::133573815653:root" - ] - ] - } - } - } - ], - "Version": "2012-10-17" - } - } - }, - "constructInfo": { - "fqn": "aws-cdk-lib.aws_iam.CfnRole", - "version": "2.173.4" - } - }, - "DefaultPolicy": { - "id": "DefaultPolicy", - "path": "flux-oci-image-inference-cdk/BuildBasePipeline/ImageBuild/AssetsImageCpuArmBuild/CodePipelineActionRole/DefaultPolicy", - "children": { - "Resource": { - "id": "Resource", - "path": "flux-oci-image-inference-cdk/BuildBasePipeline/ImageBuild/AssetsImageCpuArmBuild/CodePipelineActionRole/DefaultPolicy/Resource", - "attributes": { - "aws:cdk:cloudformation:type": "AWS::IAM::Policy", - "aws:cdk:cloudformation:props": { - "policyDocument": { - "Statement": [ - { - "Action": [ - "codebuild:BatchGetBuilds", - "codebuild:StartBuild", - "codebuild:StopBuild" - ], - "Effect": "Allow", - "Resource": { - "Fn::GetAtt": [ - "AssetsImageCpuArmBuildBC43C501", - "Arn" - ] - } - } - ], - "Version": "2012-10-17" - }, - "policyName": "BuildBasePipelineImageBuildAssetsImageCpuArmBuildCodePipelineActionRoleDefaultPolicy723A3220", - "roles": [ - { - "Ref": "BuildBasePipelineImageBuildAssetsImageCpuArmBuildCodePipelineActionRole67BCBC26" - } - ] - } - }, - "constructInfo": { - "fqn": "aws-cdk-lib.aws_iam.CfnPolicy", - "version": "2.173.4" - } - } - }, - "constructInfo": { - "fqn": "aws-cdk-lib.aws_iam.Policy", - "version": "2.173.4" - } - } - }, - "constructInfo": { - "fqn": "aws-cdk-lib.aws_iam.Role", - "version": "2.173.4" - } - } - }, - "constructInfo": { - "fqn": "constructs.Construct", - "version": "10.4.2" - } - }, - "BaseImageAmdXlaBuild": { - "id": "BaseImageAmdXlaBuild", - "path": "flux-oci-image-inference-cdk/BuildBasePipeline/ImageBuild/BaseImageAmdXlaBuild", - "children": { - "CodePipelineActionRole": { - "id": "CodePipelineActionRole", - "path": "flux-oci-image-inference-cdk/BuildBasePipeline/ImageBuild/BaseImageAmdXlaBuild/CodePipelineActionRole", - "children": { - "ImportCodePipelineActionRole": { - "id": "ImportCodePipelineActionRole", - "path": "flux-oci-image-inference-cdk/BuildBasePipeline/ImageBuild/BaseImageAmdXlaBuild/CodePipelineActionRole/ImportCodePipelineActionRole", - "constructInfo": { - "fqn": "aws-cdk-lib.Resource", - "version": "2.173.4" - } - }, - "Resource": { - "id": "Resource", - "path": "flux-oci-image-inference-cdk/BuildBasePipeline/ImageBuild/BaseImageAmdXlaBuild/CodePipelineActionRole/Resource", - "attributes": { - "aws:cdk:cloudformation:type": "AWS::IAM::Role", - "aws:cdk:cloudformation:props": { - "assumeRolePolicyDocument": { - "Statement": [ - { - "Action": "sts:AssumeRole", - "Effect": "Allow", - "Principal": { - "AWS": { - "Fn::Join": [ - "", - [ - "arn:", - { - "Ref": "AWS::Partition" - }, - ":iam::133573815653:root" - ] - ] - } - } - } - ], - "Version": "2012-10-17" - } - } - }, - "constructInfo": { - "fqn": "aws-cdk-lib.aws_iam.CfnRole", - "version": "2.173.4" - } - }, - "DefaultPolicy": { - "id": "DefaultPolicy", - "path": "flux-oci-image-inference-cdk/BuildBasePipeline/ImageBuild/BaseImageAmdXlaBuild/CodePipelineActionRole/DefaultPolicy", - "children": { - "Resource": { - "id": "Resource", - "path": "flux-oci-image-inference-cdk/BuildBasePipeline/ImageBuild/BaseImageAmdXlaBuild/CodePipelineActionRole/DefaultPolicy/Resource", - "attributes": { - "aws:cdk:cloudformation:type": "AWS::IAM::Policy", - "aws:cdk:cloudformation:props": { - "policyDocument": { - "Statement": [ - { - "Action": [ - "codebuild:BatchGetBuilds", - "codebuild:StartBuild", - "codebuild:StopBuild" - ], - "Effect": "Allow", - "Resource": { - "Fn::GetAtt": [ - "ImageXlaAmdBuild7511085C", - "Arn" - ] - } - } - ], - "Version": "2012-10-17" - }, - "policyName": "BuildBasePipelineImageBuildBaseImageAmdXlaBuildCodePipelineActionRoleDefaultPolicy1C329D4F", - "roles": [ - { - "Ref": "BuildBasePipelineImageBuildBaseImageAmdXlaBuildCodePipelineActionRoleD9124FCE" - } - ] - } - }, - "constructInfo": { - "fqn": "aws-cdk-lib.aws_iam.CfnPolicy", - "version": "2.173.4" - } - } - }, - "constructInfo": { - "fqn": "aws-cdk-lib.aws_iam.Policy", - "version": "2.173.4" - } - } - }, - "constructInfo": { - "fqn": "aws-cdk-lib.aws_iam.Role", - "version": "2.173.4" - } - } - }, - "constructInfo": { - "fqn": "constructs.Construct", - "version": "10.4.2" - } - }, - "BaseImageArmCpuBuild": { - "id": "BaseImageArmCpuBuild", - "path": "flux-oci-image-inference-cdk/BuildBasePipeline/ImageBuild/BaseImageArmCpuBuild", - "children": { - "CodePipelineActionRole": { - "id": "CodePipelineActionRole", - "path": "flux-oci-image-inference-cdk/BuildBasePipeline/ImageBuild/BaseImageArmCpuBuild/CodePipelineActionRole", - "children": { - "ImportCodePipelineActionRole": { - "id": "ImportCodePipelineActionRole", - "path": "flux-oci-image-inference-cdk/BuildBasePipeline/ImageBuild/BaseImageArmCpuBuild/CodePipelineActionRole/ImportCodePipelineActionRole", - "constructInfo": { - "fqn": "aws-cdk-lib.Resource", - "version": "2.173.4" - } - }, - "Resource": { - "id": "Resource", - "path": "flux-oci-image-inference-cdk/BuildBasePipeline/ImageBuild/BaseImageArmCpuBuild/CodePipelineActionRole/Resource", - "attributes": { - "aws:cdk:cloudformation:type": "AWS::IAM::Role", - "aws:cdk:cloudformation:props": { - "assumeRolePolicyDocument": { - "Statement": [ - { - "Action": "sts:AssumeRole", - "Effect": "Allow", - "Principal": { - "AWS": { - "Fn::Join": [ - "", - [ - "arn:", - { - "Ref": "AWS::Partition" - }, - ":iam::133573815653:root" - ] - ] - } - } - } - ], - "Version": "2012-10-17" - } - } - }, - "constructInfo": { - "fqn": "aws-cdk-lib.aws_iam.CfnRole", - "version": "2.173.4" - } - }, - "DefaultPolicy": { - "id": "DefaultPolicy", - "path": "flux-oci-image-inference-cdk/BuildBasePipeline/ImageBuild/BaseImageArmCpuBuild/CodePipelineActionRole/DefaultPolicy", - "children": { - "Resource": { - "id": "Resource", - "path": "flux-oci-image-inference-cdk/BuildBasePipeline/ImageBuild/BaseImageArmCpuBuild/CodePipelineActionRole/DefaultPolicy/Resource", - "attributes": { - "aws:cdk:cloudformation:type": "AWS::IAM::Policy", - "aws:cdk:cloudformation:props": { - "policyDocument": { - "Statement": [ - { - "Action": [ - "codebuild:BatchGetBuilds", - "codebuild:StartBuild", - "codebuild:StopBuild" - ], - "Effect": "Allow", - "Resource": { - "Fn::GetAtt": [ - "ImageCpuArmBuild4791F7AA", - "Arn" - ] - } - } - ], - "Version": "2012-10-17" - }, - "policyName": "BuildBasePipelineImageBuildBaseImageArmCpuBuildCodePipelineActionRoleDefaultPolicy31713CB8", - "roles": [ - { - "Ref": "BuildBasePipelineImageBuildBaseImageArmCpuBuildCodePipelineActionRole4DF7F5DE" - } - ] - } - }, - "constructInfo": { - "fqn": "aws-cdk-lib.aws_iam.CfnPolicy", - "version": "2.173.4" - } - } - }, - "constructInfo": { - "fqn": "aws-cdk-lib.aws_iam.Policy", - "version": "2.173.4" - } - } - }, - "constructInfo": { - "fqn": "aws-cdk-lib.aws_iam.Role", - "version": "2.173.4" - } - } - }, - "constructInfo": { - "fqn": "constructs.Construct", - "version": "10.4.2" - } - }, - "BaseImageAmdCudBuild": { - "id": "BaseImageAmdCudBuild", - "path": "flux-oci-image-inference-cdk/BuildBasePipeline/ImageBuild/BaseImageAmdCudBuild", - "children": { - "CodePipelineActionRole": { - "id": "CodePipelineActionRole", - "path": "flux-oci-image-inference-cdk/BuildBasePipeline/ImageBuild/BaseImageAmdCudBuild/CodePipelineActionRole", - "children": { - "ImportCodePipelineActionRole": { - "id": "ImportCodePipelineActionRole", - "path": "flux-oci-image-inference-cdk/BuildBasePipeline/ImageBuild/BaseImageAmdCudBuild/CodePipelineActionRole/ImportCodePipelineActionRole", - "constructInfo": { - "fqn": "aws-cdk-lib.Resource", - "version": "2.173.4" - } - }, - "Resource": { - "id": "Resource", - "path": "flux-oci-image-inference-cdk/BuildBasePipeline/ImageBuild/BaseImageAmdCudBuild/CodePipelineActionRole/Resource", - "attributes": { - "aws:cdk:cloudformation:type": "AWS::IAM::Role", - "aws:cdk:cloudformation:props": { - "assumeRolePolicyDocument": { - "Statement": [ - { - "Action": "sts:AssumeRole", - "Effect": "Allow", - "Principal": { - "AWS": { - "Fn::Join": [ - "", - [ - "arn:", - { - "Ref": "AWS::Partition" - }, - ":iam::133573815653:root" - ] - ] - } - } - } - ], - "Version": "2012-10-17" - } - } - }, - "constructInfo": { - "fqn": "aws-cdk-lib.aws_iam.CfnRole", - "version": "2.173.4" - } - }, - "DefaultPolicy": { - "id": "DefaultPolicy", - "path": "flux-oci-image-inference-cdk/BuildBasePipeline/ImageBuild/BaseImageAmdCudBuild/CodePipelineActionRole/DefaultPolicy", - "children": { - "Resource": { - "id": "Resource", - "path": "flux-oci-image-inference-cdk/BuildBasePipeline/ImageBuild/BaseImageAmdCudBuild/CodePipelineActionRole/DefaultPolicy/Resource", - "attributes": { - "aws:cdk:cloudformation:type": "AWS::IAM::Policy", - "aws:cdk:cloudformation:props": { - "policyDocument": { - "Statement": [ - { - "Action": [ - "codebuild:BatchGetBuilds", - "codebuild:StartBuild", - "codebuild:StopBuild" - ], - "Effect": "Allow", - "Resource": { - "Fn::GetAtt": [ - "ImageCudAmdBuild23EA25C8", - "Arn" - ] - } - } - ], - "Version": "2012-10-17" - }, - "policyName": "BuildBasePipelineImageBuildBaseImageAmdCudBuildCodePipelineActionRoleDefaultPolicy7D964952", - "roles": [ - { - "Ref": "BuildBasePipelineImageBuildBaseImageAmdCudBuildCodePipelineActionRoleA29F5F5F" - } - ] - } - }, - "constructInfo": { - "fqn": "aws-cdk-lib.aws_iam.CfnPolicy", - "version": "2.173.4" - } - } - }, - "constructInfo": { - "fqn": "aws-cdk-lib.aws_iam.Policy", - "version": "2.173.4" - } - } - }, - "constructInfo": { - "fqn": "aws-cdk-lib.aws_iam.Role", - "version": "2.173.4" - } - } - }, - "constructInfo": { - "fqn": "constructs.Construct", - "version": "10.4.2" - } - } - }, - "constructInfo": { - "fqn": "constructs.Construct", - "version": "10.4.2" - } - } - }, - "constructInfo": { - "fqn": "aws-cdk-lib.aws_codepipeline.Pipeline", - "version": "2.173.4" - } - }, - "CDKMetadata": { - "id": "CDKMetadata", - "path": "flux-oci-image-inference-cdk/CDKMetadata", - "children": { - "Default": { - "id": "Default", - "path": "flux-oci-image-inference-cdk/CDKMetadata/Default", - "constructInfo": { - "fqn": "aws-cdk-lib.CfnResource", - "version": "2.173.4" - } - } - }, - "constructInfo": { - "fqn": "constructs.Construct", - "version": "10.4.2" - } - }, - "BootstrapVersion": { - "id": "BootstrapVersion", - "path": "flux-oci-image-inference-cdk/BootstrapVersion", - "constructInfo": { - "fqn": "aws-cdk-lib.CfnParameter", - "version": "2.173.4" - } - }, - "CheckBootstrapVersion": { - "id": "CheckBootstrapVersion", - "path": "flux-oci-image-inference-cdk/CheckBootstrapVersion", - "constructInfo": { - "fqn": "aws-cdk-lib.CfnRule", - "version": "2.173.4" - } - } - }, - "constructInfo": { - "fqn": "aws-cdk-lib.Stack", - "version": "2.173.4" - } - }, - "Tree": { - "id": "Tree", - "path": "Tree", - "constructInfo": { - "fqn": "constructs.Construct", - "version": "10.4.2" - } - } - }, - "constructInfo": { - "fqn": "aws-cdk-lib.App", - "version": "2.173.4" - } - } -} \ No newline at end of file From aa995bd484746a1a244feff723db3a6f001d6ab7 Mon Sep 17 00:00:00 2001 From: Yahav Date: Wed, 1 Jan 2025 23:35:02 -0800 Subject: [PATCH 03/45] awscliconfig --- flux_serve/app/config | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 flux_serve/app/config diff --git a/flux_serve/app/config b/flux_serve/app/config new file mode 100644 index 0000000..539a043 --- /dev/null +++ b/flux_serve/app/config @@ -0,0 +1,4 @@ +[default] +retry_mode = adaptive +max_attempts = 10 +region = us-west-2 From 0100e29695d0da9123819b82805dc4165b4a5b10 Mon Sep 17 00:00:00 2001 From: Yahav Date: Wed, 1 Jan 2025 23:39:14 -0800 Subject: [PATCH 04/45] gitignore --- flux_serve/.gitignore | 2 + flux_serve/app/.Dockerfile.template.swp | Bin 12288 -> 0 bytes flux_serve/oci-image-build/README.md | 2 +- flux_serve/oci-image-build/pipeline-stack.js | 148 +---------------- flux_serve/oci-image-build/pipeline-stack.ts | 161 +------------------ 5 files changed, 8 insertions(+), 305 deletions(-) delete mode 100644 flux_serve/app/.Dockerfile.template.swp diff --git a/flux_serve/.gitignore b/flux_serve/.gitignore index 4c9908f..a6cae42 100644 --- a/flux_serve/.gitignore +++ b/flux_serve/.gitignore @@ -1,3 +1,5 @@ package-lock.json .DS_Store node_modules/* +oci-image-build/cdk.out/ +oci-image-build/node_modules/ diff --git a/flux_serve/app/.Dockerfile.template.swp b/flux_serve/app/.Dockerfile.template.swp deleted file mode 100644 index 48e6538384097f669d2d60a8819350181d13da43..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 12288 zcmeI2!A=xG5QZDhq6YQgtzAt>Bs~KxppbAtMMDBYAeazBNY6~oY-eX@+U}lZHzFRr z_!u6HkKnJ>ht(jdAlq`BwtFwPP+g(#t{Z-9jvmH!4SzhIH-Xz0unXy;z zi{$Oqr!0QQSXVY=J192>k2_&ppN?QAuFp;nvOMfL^yR)485AbZ1T?L%vZYh7ew-Ga zJqxA{zSP=(kcUk$u}Z;nfELohAm_A41c<;n1V&hWYI349x>>uyuZ(V;V^7;efCvx) zB0vO)01+SpM1TnVO9Y%AVlVJO!~H{D>(4_!&Hb-55dk7V1c(3;AOb{y2oM1xKm>>Y z5g-D8ApsdNHhO`vLsa?y|IzRNua_A6g8GQsM$MzHqrP2a>=Wt@>HxKZnnlf^YN%n< zvk}HVqrVTR*Ql4M(*JW54I)4UhyW2F0z`la5CI}U1pZe7_t)09`EBmAjjhMLSp*Qe zl()fHm1kUtFjbJbYEx<_5^!8)*2y&GqI+b2YP--;c~7`>2Vo=UV-W;=$EqZQNCe#l zA6$sHi=E$uu2ETH{W7Y_z=0KIjQ+Zp=wz2SoYQvR_jNO|Uh}T?RPKklfq5U32vVHe zlit*vk3oFykMRTU0QhkXn-?Yo>!r#%FFFyaTB(u@3xj8g?dHlK1>1lWqy-PN#h{og z!iqqeR&Kb+e`N3*r>xRwH6w*j>NB1^3vacil|HUU399qUYNX=0zzf}WVPV3n9h^46O!O)QYykvSmAHm_^b= zyR`wY>b!^N52K(5k)%F=pTP`^xGplpsMAcwClp+M Date: Thu, 2 Jan 2025 10:49:00 -0800 Subject: [PATCH 05/45] compile --- .../specs/amd-neuron-trn1-nodepool.yaml | 49 +++++++++++++++++++ flux_serve/specs/compile-flux-1024x576.yaml | 46 +++++++++++++++++ flux_serve/specs/flux-model-s3-storage.yaml | 33 +++++++++++++ 3 files changed, 128 insertions(+) create mode 100644 flux_serve/specs/amd-neuron-trn1-nodepool.yaml create mode 100644 flux_serve/specs/compile-flux-1024x576.yaml create mode 100644 flux_serve/specs/flux-model-s3-storage.yaml diff --git a/flux_serve/specs/amd-neuron-trn1-nodepool.yaml b/flux_serve/specs/amd-neuron-trn1-nodepool.yaml new file mode 100644 index 0000000..245ee15 --- /dev/null +++ b/flux_serve/specs/amd-neuron-trn1-nodepool.yaml @@ -0,0 +1,49 @@ +apiVersion: karpenter.sh/v1 +kind: NodePool +metadata: + name: amd-neuron-trn1 +spec: + template: + spec: + requirements: + - key: kubernetes.io/arch + operator: In + values: ["amd64"] + - key: karpenter.k8s.aws/instance-family + operator: In + values: ["trn1"] + - key: karpenter.sh/capacity-type + operator: In + values: ["on-demand"] + nodeClassRef: + group: karpenter.k8s.aws + kind: EC2NodeClass + name: amd-neuron + expireAfter: 720h # 30 * 24h = 720h + limits: + cpu: 1000 + disruption: + consolidationPolicy: WhenEmptyOrUnderutilized + consolidateAfter: 1m +--- +apiVersion: karpenter.k8s.aws/v1 +kind: EC2NodeClass +metadata: + name: amd-neuron +spec: + amiFamily: AL2 # Amazon Linux 2 + amiSelectorTerms: + - name: "amazon-eks-node-1.31-*" + role: "KarpenterNodeRole-flux-usw2" + subnetSelectorTerms: + - tags: + karpenter.sh/discovery: "flux-usw2" + securityGroupSelectorTerms: + - tags: + karpenter.sh/discovery: "flux-usw2" + blockDeviceMappings: + - deviceName: /dev/xvda + ebs: + volumeSize: 900Gi + volumeType: gp3 + encrypted: true diff --git a/flux_serve/specs/compile-flux-1024x576.yaml b/flux_serve/specs/compile-flux-1024x576.yaml new file mode 100644 index 0000000..fef3eb6 --- /dev/null +++ b/flux_serve/specs/compile-flux-1024x576.yaml @@ -0,0 +1,46 @@ +apiVersion: batch/v1 +kind: Job +metadata: + name: compile-1024x576 +spec: + template: + spec: + restartPolicy: OnFailure + nodeSelector: + karpenter.sh/nodepool: amd-neuron-trn1 + #serviceAccountName: appsimulator + schedulerName: my-scheduler + containers: + - name: app + image: 133573815653.dkr.ecr.us-west-2.amazonaws.com/model:amd64-neuron + imagePullPolicy: Always + volumeMounts: + - name: dshm + mountPath: /dev/shm + - name: s3-flux-pvc + mountPath: /model + command: ["sh", "-c", "while true; do sleep 3600; done"] + resources: + limits: + aws.amazon.com/neuron: 6 + requests: + aws.amazon.com/neuron: 6 + env: + - name: HEIGHT + value: "1024" + - name: WIDTH + value: "576" + - name: MODEL_ID + value: "black-forest-labs/FLUX.1-dev" + - name: HUGGINGFACE_TOKEN + valueFrom: + secretKeyRef: + name: hf-secrets + key: HUGGINGFACE_TOKEN + volumes: + - name: dshm + emptyDir: + medium: Memory + - name: s3-flux-pvc + persistentVolumeClaim: + claimName: s3-flux-pvc diff --git a/flux_serve/specs/flux-model-s3-storage.yaml b/flux_serve/specs/flux-model-s3-storage.yaml new file mode 100644 index 0000000..a40e583 --- /dev/null +++ b/flux_serve/specs/flux-model-s3-storage.yaml @@ -0,0 +1,33 @@ +apiVersion: v1 +kind: PersistentVolume +metadata: + name: s3-flux-pv +spec: + capacity: + storage: 1200Gi + accessModes: + - ReadWriteMany + storageClassName: "" + claimRef: + namespace: default + name: s3-flux-pvc + mountOptions: + - region us-west-2 + csi: + driver: s3.csi.aws.com + volumeHandle: s3-csi-driver-volume + volumeAttributes: + bucketName: black-forest-labs-flux1-dev-neuron +--- +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: s3-flux-pvc +spec: + accessModes: + - ReadWriteMany # Supported options: ReadWriteMany / ReadOnlyMany + storageClassName: "" # Required for static provisioning + resources: + requests: + storage: 1200Gi + volumeName: s3-flux-pv From 79ee1f089e263a23ee5b1b9196ec0ddc450bd004 Mon Sep 17 00:00:00 2001 From: Yahav Date: Thu, 2 Jan 2025 11:36:32 -0800 Subject: [PATCH 06/45] compile1 --- flux_serve/README.md | 40 ++++++++++++++++++- .../specs/amd-neuron-trn1-nodepool.yaml | 6 ++- flux_serve/specs/compile-flux-1024x576.yaml | 2 + flux_serve/src/compile.sh | 11 ++--- flux_serve/src/decoder/compile.py | 3 +- flux_serve/src/inference.py | 3 +- flux_serve/src/text_encoder_1/compile.py | 3 +- flux_serve/src/text_encoder_2/compile.py | 3 +- flux_serve/src/transformer/compile.py | 3 +- 9 files changed, 61 insertions(+), 13 deletions(-) diff --git a/flux_serve/README.md b/flux_serve/README.md index b9c4ba3..fc72b67 100644 --- a/flux_serve/README.md +++ b/flux_serve/README.md @@ -18,6 +18,44 @@ Neuron device plugin, Neuron scheduler extension, Neuron scheduler ```bash export MODEL_GRAPH_BUCKET="black-forest-labs-flux1-dev-neuron" ``` +* [Deploy your HggingFace user secret as a k8s secret](https://kubernetes.io/docs/concepts/configuration/secret/) +```bash +echo -n 'hf_myhftoken' | base64 +``` +replace the value with the `HUGGINGFACE_TOKEN` and apply the secret into the cluster +```yaml +apiVersion: v1 +kind: Secret +type: Opaque +metadata: + name: hf-secrets + namespace: default +data: + HUGGINGFACE_TOKEN: encodedhfmyhftoken +``` + * [Enable Amazon S3 objects with Mountpoint for Amazon S3 CSI driver](https://docs.aws.amazon.com/eks/latest/userguide/s3-csi.html) * [Deploy the OCI image pipeline](./oci-image-build) -* +* [Deploy the Neuron device plugin and scheduler extention](https://awsdocs-neuron.readthedocs-hosted.com/en/latest/containers/kubernetes-getting-started.html#deploy-neuron-device-plugin) +```bash +helm upgrade --install neuron-helm-chart oci://public.ecr.aws/neuron/neuron-helm-chart \ + --set "npd.enabled=false" +helm upgrade --install neuron-helm-chart oci://public.ecr.aws/neuron/neuron-helm-chart \ + --set "scheduler.enabled=true" \ + --set "npd.enabled=false" +``` +* Deploy the Karpenter `NodeClass` and `NodePool` that provisions `trn1` instances upon requests (`nodeSelector:karpenter.sh/nodepool: amd-neuron-trn1`) +```bash +kubectl -f specs/amd-neuron-trn1-nodepool.yaml +``` +* Deploy the S3 CSI driver storage PersistentVolume and PersistentVolumeClaim that stores the compiled Flux graphs. +Edit `bucketName` for the right bucket name created; `accessModes` set to `ReadWriteMany` because we demonstrate graph compilation (upload) and serving (download). +Note the `PersistentVolumeClaim` name; we will need it for the app deployment. +```bash +kubectl apply -f specs/flux-model-s3-storage.yaml +``` +* Compile the model for the requires shapes. We will demonstrate three shapes: 1024x576, 256x144, and 512x512 with `bfloat16` +```bash +kubectl -f specs/compile-flux-1024x576.yaml +``` + diff --git a/flux_serve/specs/amd-neuron-trn1-nodepool.yaml b/flux_serve/specs/amd-neuron-trn1-nodepool.yaml index 245ee15..2e7a23d 100644 --- a/flux_serve/specs/amd-neuron-trn1-nodepool.yaml +++ b/flux_serve/specs/amd-neuron-trn1-nodepool.yaml @@ -24,7 +24,7 @@ spec: cpu: 1000 disruption: consolidationPolicy: WhenEmptyOrUnderutilized - consolidateAfter: 1m + consolidateAfter: 10m --- apiVersion: karpenter.k8s.aws/v1 kind: EC2NodeClass @@ -33,7 +33,9 @@ metadata: spec: amiFamily: AL2 # Amazon Linux 2 amiSelectorTerms: - - name: "amazon-eks-node-1.31-*" + - id: "ami-0e73cfd34ee52b6a6" + - id: "ami-077b8064c2a1a3186" + - id: "ami-057dddc807f3f6644" role: "KarpenterNodeRole-flux-usw2" subnetSelectorTerms: - tags: diff --git a/flux_serve/specs/compile-flux-1024x576.yaml b/flux_serve/specs/compile-flux-1024x576.yaml index fef3eb6..568a14f 100644 --- a/flux_serve/specs/compile-flux-1024x576.yaml +++ b/flux_serve/specs/compile-flux-1024x576.yaml @@ -26,6 +26,8 @@ spec: requests: aws.amazon.com/neuron: 6 env: + - name: COMPILER_WORKDIR_ROOT + value: "/model" - name: HEIGHT value: "1024" - name: WIDTH diff --git a/flux_serve/src/compile.sh b/flux_serve/src/compile.sh index 40d4b2b..4e0d120 100755 --- a/flux_serve/src/compile.sh +++ b/flux_serve/src/compile.sh @@ -1,10 +1,11 @@ #!/bin/bash -find . -type d \( -name "compiled_model" -o -name "__pycache__" -o -name "compiler_workdir" \) -exec rm -rf {} + -myloc="$(dirname "$0")" +find $COMPILER_WORKDIR_ROOT -type d \( -name "compiled_model" -o -name "__pycache__" -o -name "compiler_workdir" \) -exec rm -rf {} + +myloc=$COMPILER_WORKDIR_ROOT python "$myloc/text_encoder_1/compile.py" python "$myloc/text_encoder_2/compile.py" -m 32 -python "$myloc/transformer/compile.py" -hh 512 -w 512 -m 32 -python "$myloc/decoder/compile.py" -hh 512 -w 512 -echo "done!" +python "$myloc/transformer/compile.py" -hh $HEIGHT -w $WIDTH -m 32 +python "$myloc/decoder/compile.py" -hh $HEIGHT -w $WIDTH +echo "done compiling; cleaning compiler_workdir" +find $COMPILER_WORKDIR_ROOT -type d \( -name "__pycache__" -o -name "compiler_workdir" \) -exec rm -rf {} + diff --git a/flux_serve/src/decoder/compile.py b/flux_serve/src/decoder/compile.py index 51d7aaa..2e7954b 100644 --- a/flux_serve/src/decoder/compile.py +++ b/flux_serve/src/decoder/compile.py @@ -6,7 +6,8 @@ from diffusers import FluxPipeline from model import TracingVAEDecoderWrapper -COMPILER_WORKDIR_ROOT = os.path.dirname(__file__) +#COMPILER_WORKDIR_ROOT = os.path.dirname(__file__) +COMPILER_WORKDIR_ROOT = os.environ['COMPILER_WORKDIR_ROOT'] DTYPE=torch.bfloat16 def trace_vae(height, width): diff --git a/flux_serve/src/inference.py b/flux_serve/src/inference.py index 57b4bc3..3df5755 100644 --- a/flux_serve/src/inference.py +++ b/flux_serve/src/inference.py @@ -9,7 +9,8 @@ from diffusers.models.modeling_outputs import Transformer2DModelOutput from typing import Any, Dict, Optional, Union -COMPILER_WORKDIR_ROOT = os.path.dirname(__file__) +#COMPILER_WORKDIR_ROOT = os.path.dirname(__file__) +COMPILER_WORKDIR_ROOT = os.environ['COMPILER_WORKDIR_ROOT'] TEXT_ENCODER_PATH = os.path.join( COMPILER_WORKDIR_ROOT, diff --git a/flux_serve/src/text_encoder_1/compile.py b/flux_serve/src/text_encoder_1/compile.py index 84065b3..1984a23 100644 --- a/flux_serve/src/text_encoder_1/compile.py +++ b/flux_serve/src/text_encoder_1/compile.py @@ -5,7 +5,8 @@ from diffusers import FluxPipeline from model import TracingCLIPTextEncoderWrapper -COMPILER_WORKDIR_ROOT = os.path.dirname(__file__) +#COMPILER_WORKDIR_ROOT = os.path.dirname(__file__) +COMPILER_WORKDIR_ROOT = os.environ['COMPILER_WORKDIR_ROOT'] DTYPE=torch.bfloat16 def trace_text_encoder(): diff --git a/flux_serve/src/text_encoder_2/compile.py b/flux_serve/src/text_encoder_2/compile.py index 74025f1..cbbb220 100644 --- a/flux_serve/src/text_encoder_2/compile.py +++ b/flux_serve/src/text_encoder_2/compile.py @@ -12,7 +12,8 @@ init_text_encoder_2, ) -COMPILER_WORKDIR_ROOT = os.path.dirname(__file__) +#COMPILER_WORKDIR_ROOT = os.path.dirname(__file__) +COMPILER_WORKDIR_ROOT = os.environ['COMPILER_WORKDIR_ROOT'] TP_DEGREE=8 DTYPE=torch.bfloat16 diff --git a/flux_serve/src/transformer/compile.py b/flux_serve/src/transformer/compile.py index c33b21b..abc0284 100644 --- a/flux_serve/src/transformer/compile.py +++ b/flux_serve/src/transformer/compile.py @@ -14,7 +14,8 @@ MyAttentionProcessor, init_transformer) -COMPILER_WORKDIR_ROOT = os.path.dirname(__file__) +#COMPILER_WORKDIR_ROOT = os.path.dirname(__file__) +COMPILER_WORKDIR_ROOT = os.environ['COMPILER_WORKDIR_ROOT'] TP_DEGREE=8 DTYPE=torch.bfloat16 From fc6dc5b979acb2980becaa4afba49ecf839112f6 Mon Sep 17 00:00:00 2001 From: Yahav Date: Thu, 2 Jan 2025 14:09:35 -0800 Subject: [PATCH 07/45] compile --- flux_serve/README.md | 9 ++------- flux_serve/app/Dockerfile.template | 2 +- flux_serve/{ => app}/src/README.md | 0 flux_serve/{ => app}/src/compile.sh | 0 flux_serve/{ => app}/src/decoder/compile.py | 0 flux_serve/{ => app}/src/decoder/model.py | 0 flux_serve/{ => app}/src/inference.py | 0 flux_serve/{ => app}/src/inference.sh | 0 flux_serve/{ => app}/src/text_encoder_1/compile.py | 0 flux_serve/{ => app}/src/text_encoder_1/model.py | 0 flux_serve/{ => app}/src/text_encoder_2/compile.py | 0 flux_serve/{ => app}/src/text_encoder_2/model.py | 0 flux_serve/{ => app}/src/transformer/compile.py | 0 flux_serve/{ => app}/src/transformer/model.py | 0 flux_serve/oci-image-build/README.md | 5 ----- flux_serve/oci-image-build/package-lock.json | 6 +++--- flux_serve/oci-image-build/pipeline-stack.js | 14 +++++++------- flux_serve/oci-image-build/pipeline-stack.ts | 8 ++++---- flux_serve/specs/compile-flux-1024x576.yaml | 6 +++--- flux_serve/specs/flux-model-s3-storage.yaml | 2 +- 20 files changed, 21 insertions(+), 31 deletions(-) rename flux_serve/{ => app}/src/README.md (100%) rename flux_serve/{ => app}/src/compile.sh (100%) rename flux_serve/{ => app}/src/decoder/compile.py (100%) rename flux_serve/{ => app}/src/decoder/model.py (100%) rename flux_serve/{ => app}/src/inference.py (100%) rename flux_serve/{ => app}/src/inference.sh (100%) rename flux_serve/{ => app}/src/text_encoder_1/compile.py (100%) rename flux_serve/{ => app}/src/text_encoder_1/model.py (100%) rename flux_serve/{ => app}/src/text_encoder_2/compile.py (100%) rename flux_serve/{ => app}/src/text_encoder_2/model.py (100%) rename flux_serve/{ => app}/src/transformer/compile.py (100%) rename flux_serve/{ => app}/src/transformer/model.py (100%) diff --git a/flux_serve/README.md b/flux_serve/README.md index fc72b67..20b373d 100644 --- a/flux_serve/README.md +++ b/flux_serve/README.md @@ -14,10 +14,6 @@ Neuron device plugin, Neuron scheduler extension, Neuron scheduler ## Walkthrough * [Create cluster with Karpenter node pools that provisions `trn1` instances](https://karpenter.sh/docs/getting-started/getting-started-with-karpenter/) -* Create an S3 bucket to store the model compiled graph and export the S3 bucket name as follow: -```bash -export MODEL_GRAPH_BUCKET="black-forest-labs-flux1-dev-neuron" -``` * [Deploy your HggingFace user secret as a k8s secret](https://kubernetes.io/docs/concepts/configuration/secret/) ```bash echo -n 'hf_myhftoken' | base64 @@ -33,8 +29,7 @@ metadata: data: HUGGINGFACE_TOKEN: encodedhfmyhftoken ``` - -* [Enable Amazon S3 objects with Mountpoint for Amazon S3 CSI driver](https://docs.aws.amazon.com/eks/latest/userguide/s3-csi.html) +* Create an S3 bucket to store the model compiled graph and [enable Amazon S3 objects with Mountpoint for Amazon S3 CSI driver](https://docs.aws.amazon.com/eks/latest/userguide/s3-csi.html) * [Deploy the OCI image pipeline](./oci-image-build) * [Deploy the Neuron device plugin and scheduler extention](https://awsdocs-neuron.readthedocs-hosted.com/en/latest/containers/kubernetes-getting-started.html#deploy-neuron-device-plugin) ```bash @@ -56,6 +51,6 @@ kubectl apply -f specs/flux-model-s3-storage.yaml ``` * Compile the model for the requires shapes. We will demonstrate three shapes: 1024x576, 256x144, and 512x512 with `bfloat16` ```bash -kubectl -f specs/compile-flux-1024x576.yaml +kubectl apply -f specs/compile-flux-1024x576.yaml ``` diff --git a/flux_serve/app/Dockerfile.template b/flux_serve/app/Dockerfile.template index 3a22297..2d79b7e 100644 --- a/flux_serve/app/Dockerfile.template +++ b/flux_serve/app/Dockerfile.template @@ -18,4 +18,4 @@ RUN echo 'deb [signed-by=/etc/apt/keyrings/kubernetes-apt-keyring.gpg] https://p RUN apt-get update RUN apt-get install -y kubectl RUN kubectl version --client -COPY * / +COPY . . diff --git a/flux_serve/src/README.md b/flux_serve/app/src/README.md similarity index 100% rename from flux_serve/src/README.md rename to flux_serve/app/src/README.md diff --git a/flux_serve/src/compile.sh b/flux_serve/app/src/compile.sh similarity index 100% rename from flux_serve/src/compile.sh rename to flux_serve/app/src/compile.sh diff --git a/flux_serve/src/decoder/compile.py b/flux_serve/app/src/decoder/compile.py similarity index 100% rename from flux_serve/src/decoder/compile.py rename to flux_serve/app/src/decoder/compile.py diff --git a/flux_serve/src/decoder/model.py b/flux_serve/app/src/decoder/model.py similarity index 100% rename from flux_serve/src/decoder/model.py rename to flux_serve/app/src/decoder/model.py diff --git a/flux_serve/src/inference.py b/flux_serve/app/src/inference.py similarity index 100% rename from flux_serve/src/inference.py rename to flux_serve/app/src/inference.py diff --git a/flux_serve/src/inference.sh b/flux_serve/app/src/inference.sh similarity index 100% rename from flux_serve/src/inference.sh rename to flux_serve/app/src/inference.sh diff --git a/flux_serve/src/text_encoder_1/compile.py b/flux_serve/app/src/text_encoder_1/compile.py similarity index 100% rename from flux_serve/src/text_encoder_1/compile.py rename to flux_serve/app/src/text_encoder_1/compile.py diff --git a/flux_serve/src/text_encoder_1/model.py b/flux_serve/app/src/text_encoder_1/model.py similarity index 100% rename from flux_serve/src/text_encoder_1/model.py rename to flux_serve/app/src/text_encoder_1/model.py diff --git a/flux_serve/src/text_encoder_2/compile.py b/flux_serve/app/src/text_encoder_2/compile.py similarity index 100% rename from flux_serve/src/text_encoder_2/compile.py rename to flux_serve/app/src/text_encoder_2/compile.py diff --git a/flux_serve/src/text_encoder_2/model.py b/flux_serve/app/src/text_encoder_2/model.py similarity index 100% rename from flux_serve/src/text_encoder_2/model.py rename to flux_serve/app/src/text_encoder_2/model.py diff --git a/flux_serve/src/transformer/compile.py b/flux_serve/app/src/transformer/compile.py similarity index 100% rename from flux_serve/src/transformer/compile.py rename to flux_serve/app/src/transformer/compile.py diff --git a/flux_serve/src/transformer/model.py b/flux_serve/app/src/transformer/model.py similarity index 100% rename from flux_serve/src/transformer/model.py rename to flux_serve/app/src/transformer/model.py diff --git a/flux_serve/oci-image-build/README.md b/flux_serve/oci-image-build/README.md index 635bed0..4052d04 100644 --- a/flux_serve/oci-image-build/README.md +++ b/flux_serve/oci-image-build/README.md @@ -6,18 +6,13 @@ export AWS_ACCOUNT_ID=$(aws sts get-caller-identity --output text --query Account) export AWS_REGION=us-west-2 export BASE_IMAGE_AMD_XLA_TAG=2.5.1-neuronx-py310-sdk2.21.0-ubuntu22.04 -export BASE_IMAGE_AMD_CUD_TAG=2.3.0-gpu-py311-cu121-ubuntu20.04-ec2 -export BASE_IMAGE_ARM_CPU_TAG=2.3.0-cpu-py311-ubuntu20.04-ec2 export IMAGE_AMD_XLA_TAG=amd64-neuron -export IMAGE_AMD_CUD_TAG=amd64-cuda -export IMAGE_ARM_CPU_TAG=aarch64-cpu export BASE_REPO=model export BASE_TAG=multiarch-ubuntu export BASE_AMD_TAG=amd64 export GITHUB_BRANCH=master export GITHUB_USER=yahavb export GITHUB_REPO=aws-neuron-eks-samples -export MODEL_DIR=sd2_compile_dir export CF_STACK=flux-oci-image-inference-cdk ``` * Install needed packages diff --git a/flux_serve/oci-image-build/package-lock.json b/flux_serve/oci-image-build/package-lock.json index 813ddc3..825107e 100644 --- a/flux_serve/oci-image-build/package-lock.json +++ b/flux_serve/oci-image-build/package-lock.json @@ -125,9 +125,9 @@ "license": "MIT" }, "node_modules/@types/node": { - "version": "22.10.3", - "resolved": "https://registry.npmjs.org/@types/node/-/node-22.10.3.tgz", - "integrity": "sha512-DifAyw4BkrufCILvD3ucnuN8eydUfc/C1GlyrnI+LK6543w5/L3VeVgf05o3B4fqSXP1dKYLOZsKfutpxPzZrw==", + "version": "22.10.4", + "resolved": "https://registry.npmjs.org/@types/node/-/node-22.10.4.tgz", + "integrity": "sha512-99l6wv4HEzBQhvaU/UGoeBoCK61SCROQaCCGyQSgX2tEQ3rKkNZ2S7CEWnS/4s1LV+8ODdK21UeyR1fHP2mXug==", "license": "MIT", "peer": true, "dependencies": { diff --git a/flux_serve/oci-image-build/pipeline-stack.js b/flux_serve/oci-image-build/pipeline-stack.js index 7622aaf..f886219 100644 --- a/flux_serve/oci-image-build/pipeline-stack.js +++ b/flux_serve/oci-image-build/pipeline-stack.js @@ -56,15 +56,15 @@ class PipelineStack extends aws_cdk_lib_1.Stack { const GITHUB_USER = new aws_cdk_lib_1.CfnParameter(this, "GITHUBUSER", { type: "String" }); const GITHUB_REPO = new aws_cdk_lib_1.CfnParameter(this, "GITHUBREPO", { type: "String" }); const GITHUB_BRANCH = new aws_cdk_lib_1.CfnParameter(this, "GITHUBBRANCH", { type: "String" }); - // uncomment when you test the stack and dont want to manually delete the ecr registry - const base_registry = new ecr.Repository(this, `base_repo`, { - repositoryName: BASE_REPO.valueAsString, - imageScanOnPush: true - }); - //const base_registry = ecr.Repository.fromRepositoryName(this,`base_repo`,BASE_REPO.valueAsString) + /* uncomment when you test the stack and dont want to manually delete the ecr registry + const base_registry = new ecr.Repository(this,`base_repo`,{ + repositoryName:BASE_REPO.valueAsString, + imageScanOnPush: true + });*/ + const base_registry = ecr.Repository.fromRepositoryName(this, `base_repo`, BASE_REPO.valueAsString); //create a roleARN for codebuild const buildRole = new iam.Role(this, 'BaseCodeBuildDeployRole', { - roleName: 'hwagnisticBaseCodeBuildDeployRole', + roleName: 'fluxneuronBaseCodeBuildDeployRole', assumedBy: new iam.ServicePrincipal('codebuild.amazonaws.com'), }); buildRole.addToPolicy(new iam.PolicyStatement({ diff --git a/flux_serve/oci-image-build/pipeline-stack.ts b/flux_serve/oci-image-build/pipeline-stack.ts index cea5897..c6a4d6b 100644 --- a/flux_serve/oci-image-build/pipeline-stack.ts +++ b/flux_serve/oci-image-build/pipeline-stack.ts @@ -24,17 +24,17 @@ export class PipelineStack extends Stack { const GITHUB_USER = new CfnParameter(this,"GITHUBUSER",{type:"String"}); const GITHUB_REPO = new CfnParameter(this,"GITHUBREPO",{type:"String"}); const GITHUB_BRANCH = new CfnParameter(this,"GITHUBBRANCH",{type:"String"}); - // uncomment when you test the stack and dont want to manually delete the ecr registry + /* uncomment when you test the stack and dont want to manually delete the ecr registry const base_registry = new ecr.Repository(this,`base_repo`,{ repositoryName:BASE_REPO.valueAsString, imageScanOnPush: true - }); + });*/ - //const base_registry = ecr.Repository.fromRepositoryName(this,`base_repo`,BASE_REPO.valueAsString) + const base_registry = ecr.Repository.fromRepositoryName(this,`base_repo`,BASE_REPO.valueAsString) //create a roleARN for codebuild const buildRole = new iam.Role(this, 'BaseCodeBuildDeployRole',{ - roleName: 'hwagnisticBaseCodeBuildDeployRole', + roleName: 'fluxneuronBaseCodeBuildDeployRole', assumedBy: new iam.ServicePrincipal('codebuild.amazonaws.com'), }); diff --git a/flux_serve/specs/compile-flux-1024x576.yaml b/flux_serve/specs/compile-flux-1024x576.yaml index 568a14f..1b82533 100644 --- a/flux_serve/specs/compile-flux-1024x576.yaml +++ b/flux_serve/specs/compile-flux-1024x576.yaml @@ -12,7 +12,7 @@ spec: schedulerName: my-scheduler containers: - name: app - image: 133573815653.dkr.ecr.us-west-2.amazonaws.com/model:amd64-neuron + image: 920372998901.dkr.ecr.us-west-2.amazonaws.com/model:amd64-neuron imagePullPolicy: Always volumeMounts: - name: dshm @@ -22,9 +22,9 @@ spec: command: ["sh", "-c", "while true; do sleep 3600; done"] resources: limits: - aws.amazon.com/neuron: 6 + aws.amazon.com/neuron: 8 requests: - aws.amazon.com/neuron: 6 + aws.amazon.com/neuron: 8 env: - name: COMPILER_WORKDIR_ROOT value: "/model" diff --git a/flux_serve/specs/flux-model-s3-storage.yaml b/flux_serve/specs/flux-model-s3-storage.yaml index a40e583..cf59de1 100644 --- a/flux_serve/specs/flux-model-s3-storage.yaml +++ b/flux_serve/specs/flux-model-s3-storage.yaml @@ -17,7 +17,7 @@ spec: driver: s3.csi.aws.com volumeHandle: s3-csi-driver-volume volumeAttributes: - bucketName: black-forest-labs-flux1-dev-neuron + bucketName: flux1-dev-neuron --- apiVersion: v1 kind: PersistentVolumeClaim From c4f3b8eaf6057f757ebfcf45da7cfd9844770a70 Mon Sep 17 00:00:00 2001 From: Yahav Date: Thu, 2 Jan 2025 17:24:53 -0800 Subject: [PATCH 08/45] compile --- flux_serve/app/src/compile.sh | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/flux_serve/app/src/compile.sh b/flux_serve/app/src/compile.sh index 4e0d120..8ac3208 100755 --- a/flux_serve/app/src/compile.sh +++ b/flux_serve/app/src/compile.sh @@ -1,11 +1,10 @@ #!/bin/bash -find $COMPILER_WORKDIR_ROOT -type d \( -name "compiled_model" -o -name "__pycache__" -o -name "compiler_workdir" \) -exec rm -rf {} + +find . -type d \( -name "compiled_model" -o -name "__pycache__" -o -name "compiler_workdir" \) -exec rm -rf {} + -myloc=$COMPILER_WORKDIR_ROOT -python "$myloc/text_encoder_1/compile.py" -python "$myloc/text_encoder_2/compile.py" -m 32 -python "$myloc/transformer/compile.py" -hh $HEIGHT -w $WIDTH -m 32 -python "$myloc/decoder/compile.py" -hh $HEIGHT -w $WIDTH +python "./text_encoder_1/compile.py" +python "./text_encoder_2/compile.py" -m 32 +python "./transformer/compile.py" -hh $HEIGHT -w $WIDTH -m 32 +python "./decoder/compile.py" -hh $HEIGHT -w $WIDTH echo "done compiling; cleaning compiler_workdir" -find $COMPILER_WORKDIR_ROOT -type d \( -name "__pycache__" -o -name "compiler_workdir" \) -exec rm -rf {} + +find . -type d \( -name "__pycache__" -o -name "compiler_workdir" \) -exec rm -rf {} + From 6e559b657eb09bdf02674d613df59cad51e3fcfc Mon Sep 17 00:00:00 2001 From: Yahav Date: Thu, 2 Jan 2025 21:10:51 -0800 Subject: [PATCH 09/45] compile --- flux_serve/app/src/compile.sh | 2 +- flux_serve/app/src/decoder/compile.py | 3 +-- flux_serve/app/src/text_encoder_1/compile.py | 3 +-- flux_serve/app/src/text_encoder_2/compile.py | 3 +-- flux_serve/app/src/transformer/compile.py | 3 +-- 5 files changed, 5 insertions(+), 9 deletions(-) diff --git a/flux_serve/app/src/compile.sh b/flux_serve/app/src/compile.sh index 8ac3208..863cc9e 100755 --- a/flux_serve/app/src/compile.sh +++ b/flux_serve/app/src/compile.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/bin/bash -x find . -type d \( -name "compiled_model" -o -name "__pycache__" -o -name "compiler_workdir" \) -exec rm -rf {} + diff --git a/flux_serve/app/src/decoder/compile.py b/flux_serve/app/src/decoder/compile.py index 2e7954b..51d7aaa 100644 --- a/flux_serve/app/src/decoder/compile.py +++ b/flux_serve/app/src/decoder/compile.py @@ -6,8 +6,7 @@ from diffusers import FluxPipeline from model import TracingVAEDecoderWrapper -#COMPILER_WORKDIR_ROOT = os.path.dirname(__file__) -COMPILER_WORKDIR_ROOT = os.environ['COMPILER_WORKDIR_ROOT'] +COMPILER_WORKDIR_ROOT = os.path.dirname(__file__) DTYPE=torch.bfloat16 def trace_vae(height, width): diff --git a/flux_serve/app/src/text_encoder_1/compile.py b/flux_serve/app/src/text_encoder_1/compile.py index 1984a23..84065b3 100644 --- a/flux_serve/app/src/text_encoder_1/compile.py +++ b/flux_serve/app/src/text_encoder_1/compile.py @@ -5,8 +5,7 @@ from diffusers import FluxPipeline from model import TracingCLIPTextEncoderWrapper -#COMPILER_WORKDIR_ROOT = os.path.dirname(__file__) -COMPILER_WORKDIR_ROOT = os.environ['COMPILER_WORKDIR_ROOT'] +COMPILER_WORKDIR_ROOT = os.path.dirname(__file__) DTYPE=torch.bfloat16 def trace_text_encoder(): diff --git a/flux_serve/app/src/text_encoder_2/compile.py b/flux_serve/app/src/text_encoder_2/compile.py index cbbb220..74025f1 100644 --- a/flux_serve/app/src/text_encoder_2/compile.py +++ b/flux_serve/app/src/text_encoder_2/compile.py @@ -12,8 +12,7 @@ init_text_encoder_2, ) -#COMPILER_WORKDIR_ROOT = os.path.dirname(__file__) -COMPILER_WORKDIR_ROOT = os.environ['COMPILER_WORKDIR_ROOT'] +COMPILER_WORKDIR_ROOT = os.path.dirname(__file__) TP_DEGREE=8 DTYPE=torch.bfloat16 diff --git a/flux_serve/app/src/transformer/compile.py b/flux_serve/app/src/transformer/compile.py index abc0284..c33b21b 100644 --- a/flux_serve/app/src/transformer/compile.py +++ b/flux_serve/app/src/transformer/compile.py @@ -14,8 +14,7 @@ MyAttentionProcessor, init_transformer) -#COMPILER_WORKDIR_ROOT = os.path.dirname(__file__) -COMPILER_WORKDIR_ROOT = os.environ['COMPILER_WORKDIR_ROOT'] +COMPILER_WORKDIR_ROOT = os.path.dirname(__file__) TP_DEGREE=8 DTYPE=torch.bfloat16 From 753d89182e30427ea9bfa22d6e63688a16e7e985 Mon Sep 17 00:00:00 2001 From: Yahav Date: Thu, 2 Jan 2025 21:42:35 -0800 Subject: [PATCH 10/45] compile --- flux_serve/app/src/decoder/compile.py | 3 +++ flux_serve/app/src/text_encoder_1/compile.py | 3 +++ flux_serve/app/src/text_encoder_2/compile.py | 3 +++ flux_serve/app/src/transformer/compile.py | 4 ++++ 4 files changed, 13 insertions(+) diff --git a/flux_serve/app/src/decoder/compile.py b/flux_serve/app/src/decoder/compile.py index 51d7aaa..69daf52 100644 --- a/flux_serve/app/src/decoder/compile.py +++ b/flux_serve/app/src/decoder/compile.py @@ -5,6 +5,9 @@ import torch_neuronx from diffusers import FluxPipeline from model import TracingVAEDecoderWrapper +from huggingface_hub import login +hf_token=os.environ['HUGGINGFACE_TOKEN'].strip() +login(hf_token,add_to_git_credential=True) COMPILER_WORKDIR_ROOT = os.path.dirname(__file__) DTYPE=torch.bfloat16 diff --git a/flux_serve/app/src/text_encoder_1/compile.py b/flux_serve/app/src/text_encoder_1/compile.py index 84065b3..b8f7856 100644 --- a/flux_serve/app/src/text_encoder_1/compile.py +++ b/flux_serve/app/src/text_encoder_1/compile.py @@ -4,6 +4,9 @@ import torch_neuronx from diffusers import FluxPipeline from model import TracingCLIPTextEncoderWrapper +from huggingface_hub import login +hf_token=os.environ['HUGGINGFACE_TOKEN'].strip() +login(hf_token,add_to_git_credential=True) COMPILER_WORKDIR_ROOT = os.path.dirname(__file__) DTYPE=torch.bfloat16 diff --git a/flux_serve/app/src/text_encoder_2/compile.py b/flux_serve/app/src/text_encoder_2/compile.py index 74025f1..e5b579d 100644 --- a/flux_serve/app/src/text_encoder_2/compile.py +++ b/flux_serve/app/src/text_encoder_2/compile.py @@ -11,6 +11,9 @@ TracingT5TextEncoderWrapper, init_text_encoder_2, ) +from huggingface_hub import login +hf_token=os.environ['HUGGINGFACE_TOKEN'].strip() +login(hf_token,add_to_git_credential=True) COMPILER_WORKDIR_ROOT = os.path.dirname(__file__) TP_DEGREE=8 diff --git a/flux_serve/app/src/transformer/compile.py b/flux_serve/app/src/transformer/compile.py index c33b21b..9a73465 100644 --- a/flux_serve/app/src/transformer/compile.py +++ b/flux_serve/app/src/transformer/compile.py @@ -14,6 +14,10 @@ MyAttentionProcessor, init_transformer) +from huggingface_hub import login +hf_token=os.environ['HUGGINGFACE_TOKEN'].strip() +login(hf_token,add_to_git_credential=True) + COMPILER_WORKDIR_ROOT = os.path.dirname(__file__) TP_DEGREE=8 DTYPE=torch.bfloat16 From 1460663d219f86a22fb01862d463245a75f63c21 Mon Sep 17 00:00:00 2001 From: Yahav Date: Thu, 2 Jan 2025 22:46:49 -0800 Subject: [PATCH 11/45] compile2 --- flux_serve/app/src/decoder/compile.py | 6 +++++- flux_serve/app/src/text_encoder_1/compile.py | 6 +++++- flux_serve/app/src/text_encoder_2/compile.py | 6 +++++- flux_serve/app/src/transformer/compile.py | 6 +++++- 4 files changed, 20 insertions(+), 4 deletions(-) diff --git a/flux_serve/app/src/decoder/compile.py b/flux_serve/app/src/decoder/compile.py index 69daf52..d8ef5c4 100644 --- a/flux_serve/app/src/decoder/compile.py +++ b/flux_serve/app/src/decoder/compile.py @@ -7,7 +7,11 @@ from model import TracingVAEDecoderWrapper from huggingface_hub import login hf_token=os.environ['HUGGINGFACE_TOKEN'].strip() -login(hf_token,add_to_git_credential=True) +try: + user_info = whoami() + print(f"Already logged in as {user_info['name']}") +except: + login(hf_token,add_to_git_credential=True) COMPILER_WORKDIR_ROOT = os.path.dirname(__file__) DTYPE=torch.bfloat16 diff --git a/flux_serve/app/src/text_encoder_1/compile.py b/flux_serve/app/src/text_encoder_1/compile.py index b8f7856..ef9a3f6 100644 --- a/flux_serve/app/src/text_encoder_1/compile.py +++ b/flux_serve/app/src/text_encoder_1/compile.py @@ -6,7 +6,11 @@ from model import TracingCLIPTextEncoderWrapper from huggingface_hub import login hf_token=os.environ['HUGGINGFACE_TOKEN'].strip() -login(hf_token,add_to_git_credential=True) +try: + user_info = whoami() + print(f"Already logged in as {user_info['name']}") +except: + login(hf_token,add_to_git_credential=True) COMPILER_WORKDIR_ROOT = os.path.dirname(__file__) DTYPE=torch.bfloat16 diff --git a/flux_serve/app/src/text_encoder_2/compile.py b/flux_serve/app/src/text_encoder_2/compile.py index e5b579d..48aae10 100644 --- a/flux_serve/app/src/text_encoder_2/compile.py +++ b/flux_serve/app/src/text_encoder_2/compile.py @@ -13,7 +13,11 @@ ) from huggingface_hub import login hf_token=os.environ['HUGGINGFACE_TOKEN'].strip() -login(hf_token,add_to_git_credential=True) +try: + user_info = whoami() + print(f"Already logged in as {user_info['name']}") +except: + login(hf_token,add_to_git_credential=True) COMPILER_WORKDIR_ROOT = os.path.dirname(__file__) TP_DEGREE=8 diff --git a/flux_serve/app/src/transformer/compile.py b/flux_serve/app/src/transformer/compile.py index 9a73465..a22d012 100644 --- a/flux_serve/app/src/transformer/compile.py +++ b/flux_serve/app/src/transformer/compile.py @@ -16,7 +16,11 @@ from huggingface_hub import login hf_token=os.environ['HUGGINGFACE_TOKEN'].strip() -login(hf_token,add_to_git_credential=True) +try: + user_info = whoami() + print(f"Already logged in as {user_info['name']}") +except: + login(hf_token,add_to_git_credential=True) COMPILER_WORKDIR_ROOT = os.path.dirname(__file__) TP_DEGREE=8 From 2122a8f0d5ee717e50454647a4216705e8c75d5e Mon Sep 17 00:00:00 2001 From: Yahav Date: Thu, 2 Jan 2025 23:17:58 -0800 Subject: [PATCH 12/45] compile10 --- flux_serve/app/src/decoder/compile.py | 1 + flux_serve/app/src/inference.py | 8 ++++++++ flux_serve/app/src/text_encoder_1/compile.py | 1 + flux_serve/app/src/text_encoder_2/compile.py | 1 + flux_serve/app/src/transformer/compile.py | 1 + 5 files changed, 12 insertions(+) diff --git a/flux_serve/app/src/decoder/compile.py b/flux_serve/app/src/decoder/compile.py index d8ef5c4..3d5cd7c 100644 --- a/flux_serve/app/src/decoder/compile.py +++ b/flux_serve/app/src/decoder/compile.py @@ -6,6 +6,7 @@ from diffusers import FluxPipeline from model import TracingVAEDecoderWrapper from huggingface_hub import login +from huggingface_hub import whoami hf_token=os.environ['HUGGINGFACE_TOKEN'].strip() try: user_info = whoami() diff --git a/flux_serve/app/src/inference.py b/flux_serve/app/src/inference.py index 3df5755..8a23989 100644 --- a/flux_serve/app/src/inference.py +++ b/flux_serve/app/src/inference.py @@ -8,6 +8,14 @@ from diffusers import FluxPipeline from diffusers.models.modeling_outputs import Transformer2DModelOutput from typing import Any, Dict, Optional, Union +from huggingface_hub import login +from huggingface_hub import whoami +hf_token=os.environ['HUGGINGFACE_TOKEN'].strip() +try: + user_info = whoami() + print(f"Already logged in as {user_info['name']}") +except: + login(hf_token,add_to_git_credential=True) #COMPILER_WORKDIR_ROOT = os.path.dirname(__file__) COMPILER_WORKDIR_ROOT = os.environ['COMPILER_WORKDIR_ROOT'] diff --git a/flux_serve/app/src/text_encoder_1/compile.py b/flux_serve/app/src/text_encoder_1/compile.py index ef9a3f6..ccb732a 100644 --- a/flux_serve/app/src/text_encoder_1/compile.py +++ b/flux_serve/app/src/text_encoder_1/compile.py @@ -5,6 +5,7 @@ from diffusers import FluxPipeline from model import TracingCLIPTextEncoderWrapper from huggingface_hub import login +from huggingface_hub import whoami hf_token=os.environ['HUGGINGFACE_TOKEN'].strip() try: user_info = whoami() diff --git a/flux_serve/app/src/text_encoder_2/compile.py b/flux_serve/app/src/text_encoder_2/compile.py index 48aae10..9d2fa10 100644 --- a/flux_serve/app/src/text_encoder_2/compile.py +++ b/flux_serve/app/src/text_encoder_2/compile.py @@ -12,6 +12,7 @@ init_text_encoder_2, ) from huggingface_hub import login +from huggingface_hub import whoami hf_token=os.environ['HUGGINGFACE_TOKEN'].strip() try: user_info = whoami() diff --git a/flux_serve/app/src/transformer/compile.py b/flux_serve/app/src/transformer/compile.py index a22d012..69db269 100644 --- a/flux_serve/app/src/transformer/compile.py +++ b/flux_serve/app/src/transformer/compile.py @@ -15,6 +15,7 @@ init_transformer) from huggingface_hub import login +from huggingface_hub import whoami hf_token=os.environ['HUGGINGFACE_TOKEN'].strip() try: user_info = whoami() From b0c03ba2c1bdccd5ede8ecc4654d33d1431ea68a Mon Sep 17 00:00:00 2001 From: Yahav Date: Fri, 3 Jan 2025 10:11:50 -0800 Subject: [PATCH 13/45] compile11 --- flux_serve/app/src/inference.sh | 4 +--- flux_serve/app/src/transformer/model.py | 15 +-------------- flux_serve/specs/compile-flux-1024x576.yaml | 13 ++++++++++--- flux_serve/specs/flux-model-s3-storage.yaml | 2 +- 4 files changed, 13 insertions(+), 21 deletions(-) diff --git a/flux_serve/app/src/inference.sh b/flux_serve/app/src/inference.sh index 51c4f60..4c3e7db 100755 --- a/flux_serve/app/src/inference.sh +++ b/flux_serve/app/src/inference.sh @@ -1,5 +1,3 @@ #!/bin/bash -myloc="$(dirname "$0")" - -python "$myloc/inference.py" -p "A cat holding a sign that says hello world" -hh 512 -w 512 -m 32 -n 50 +python "./inference.py" -p "A cat holding a sign that says hello world" -hh $HEIGHT -w $WIDTH -m 32 -n 50 diff --git a/flux_serve/app/src/transformer/model.py b/flux_serve/app/src/transformer/model.py index f7ef7e4..ce9f306 100644 --- a/flux_serve/app/src/transformer/model.py +++ b/flux_serve/app/src/transformer/model.py @@ -15,20 +15,15 @@ class MyAttentionProcessor(AttnProcessor): def __call__(self, attn, hidden_states,encoder_hidden_states=None,cross_attention_kwargs=None,**kwargs): if hidden_states is not None: - # If norm_q has shape [128], we assume n_heads * 128 = hidden_states.shape[-1]. - n_heads = 24 # For example + n_heads = 24 head_dim = 128 batch, seq_len, dim = hidden_states.shape assert dim == n_heads * head_dim, f"Dim mismatch: got {dim}, expected {n_heads*head_dim}" - # 1) [B, T, 3072] -> [B, T, n_heads, head_dim] = [B, T, 24, 128] hidden_states = hidden_states.view(batch, seq_len, n_heads, head_dim) - # 2) Apply LN per-head hidden_states = attn.norm_q(hidden_states) - # 3) Flatten back hidden_states = hidden_states.view(batch, seq_len, dim) return hidden_states, encoder_hidden_states - #return hidden_states class TracingTransformerEmbedderWrapper(nn.Module): def __init__( @@ -154,10 +149,7 @@ def forward( hidden_states = residual + hidden_states if hidden_states.dtype == torch.float16: hidden_states = hidden_states.clip(-65504, 65504) - print("norm_hidden_states.shape =", norm_hidden_states.shape) out = self.proj_mlp(norm_hidden_states) - print("out.shape =", out.shape) - print("self.proj_mlp.bias.shape =", self.proj_mlp.bias.shape) return hidden_states @@ -182,8 +174,6 @@ def get_sharded_data(data, dim): def shard_attn(attn: Attention): #attn.heads = 3 - print("shard_attn -> attn.to_q.in_features =", attn.to_q.in_features) - print("shard_attn -> attn.norm_q.weight.shape =", attn.norm_q.weight.shape) orig_q = attn.to_q attn.to_q = ColumnParallelLinear( @@ -319,9 +309,6 @@ def shard_attn_lite(block): block.proj_mlp.out_features, bias=(block.proj_mlp.bias is not None), gather_output=False) - #print("proj_mlp in_features:", block.proj_mlp.in_features) - #print("proj_mlp out_features:", block.proj_mlp.out_features) - print("proj_mlp.bias.shape:", block.proj_mlp.bias.shape) block.proj_mlp.weight.data = get_sharded_data(orig_mlp.weight.data, 0) if block.proj_mlp.bias is not None: block.proj_mlp.bias.data = get_sharded_data(orig_mlp.bias.data, 0) diff --git a/flux_serve/specs/compile-flux-1024x576.yaml b/flux_serve/specs/compile-flux-1024x576.yaml index 1b82533..2f640e6 100644 --- a/flux_serve/specs/compile-flux-1024x576.yaml +++ b/flux_serve/specs/compile-flux-1024x576.yaml @@ -19,15 +19,22 @@ spec: mountPath: /dev/shm - name: s3-flux-pvc mountPath: /model - command: ["sh", "-c", "while true; do sleep 3600; done"] + command: + - /bin/bash + - "-exc" + - | + set -x + mkdir -p /model/1024x576 + cd /src + ./compile.sh + cp -r * /model/1024x576 + while true; do sleep 3600; done resources: limits: aws.amazon.com/neuron: 8 requests: aws.amazon.com/neuron: 8 env: - - name: COMPILER_WORKDIR_ROOT - value: "/model" - name: HEIGHT value: "1024" - name: WIDTH diff --git a/flux_serve/specs/flux-model-s3-storage.yaml b/flux_serve/specs/flux-model-s3-storage.yaml index cf59de1..0d4471a 100644 --- a/flux_serve/specs/flux-model-s3-storage.yaml +++ b/flux_serve/specs/flux-model-s3-storage.yaml @@ -12,7 +12,7 @@ spec: namespace: default name: s3-flux-pvc mountOptions: - - region us-west-2 + - region=us-west-2 csi: driver: s3.csi.aws.com volumeHandle: s3-csi-driver-volume From 8d2da43e191ac0ed09a2bc9c3b8111f1e504f797 Mon Sep 17 00:00:00 2001 From: Yahav Date: Fri, 3 Jan 2025 20:46:59 -0800 Subject: [PATCH 14/45] compile12 --- flux_serve/README.md | 17 ++ flux_serve/app/benchmark-flux.py | 266 ++++++++++++++++++++ flux_serve/specs/compile-flux-1024x576.yaml | 3 + flux_serve/specs/flux-neuron-gradio.yaml | 53 ++++ flux_serve/specs/flux-neuron-ingress.yaml | 34 +++ 5 files changed, 373 insertions(+) create mode 100644 flux_serve/app/benchmark-flux.py create mode 100644 flux_serve/specs/flux-neuron-gradio.yaml create mode 100644 flux_serve/specs/flux-neuron-ingress.yaml diff --git a/flux_serve/README.md b/flux_serve/README.md index 20b373d..3184f14 100644 --- a/flux_serve/README.md +++ b/flux_serve/README.md @@ -31,6 +31,7 @@ data: ``` * Create an S3 bucket to store the model compiled graph and [enable Amazon S3 objects with Mountpoint for Amazon S3 CSI driver](https://docs.aws.amazon.com/eks/latest/userguide/s3-csi.html) * [Deploy the OCI image pipeline](./oci-image-build) +* [Deploy AWS Load Balancer controller](https://docs.aws.amazon.com/eks/latest/userguide/aws-load-balancer-controller.html) to enable public ingress access to the inference pods; export the k8s deployment as yaml and enforce nodeSelector to the non-neuron instances to avoid IMDS v1 limitation. * [Deploy the Neuron device plugin and scheduler extention](https://awsdocs-neuron.readthedocs-hosted.com/en/latest/containers/kubernetes-getting-started.html#deploy-neuron-device-plugin) ```bash helm upgrade --install neuron-helm-chart oci://public.ecr.aws/neuron/neuron-helm-chart \ @@ -52,5 +53,21 @@ kubectl apply -f specs/flux-model-s3-storage.yaml * Compile the model for the requires shapes. We will demonstrate three shapes: 1024x576, 256x144, and 512x512 with `bfloat16` ```bash kubectl apply -f specs/compile-flux-1024x576.yaml +kubectl apply -f specs/compile-flux-256x144.yaml +kubectl apply -f specs/compile-flux-512x512.yaml +``` +Note the three pending Jobs that Karpenter seeks to fulfill. Current setup requires `aws.amazon.com/neuron: 8` which is half od `trn1.32xlarge` so expect two `trn1.xlarge` to be launched. + +* Deploy the Flux serving backend that loads the model from HuggingFace and uses the preloaded neuron model graph from S3 and standby for inference requests. The backend includes Deployment Pods and Services that route inference requests to the Pods so each model-api shapes scales horizontly. +```bash +kubectl apply -f specs/flux-neuron-1024x576-model-api.yaml +kubectl apply -f specs/flux-neuron-256x144-model-api.yaml +kubectl apply -f specs/flux-neuron-512x512-model-api.yaml +``` +Note the three pending Deployment Pods that Karpenter seeks to fulfill. Current setup requires `aws.amazon.com/neuron: 8` which is half od `trn1.32xlarge` so expect two `trn1.xlarge` to be launched. + +* Deploy the Flux serving frontend that includes Gradio app. +```bash +kubectl apply -f specs/flux-neuron-gradio.yaml ``` diff --git a/flux_serve/app/benchmark-flux.py b/flux_serve/app/benchmark-flux.py new file mode 100644 index 0000000..f1f5e4f --- /dev/null +++ b/flux_serve/app/benchmark-flux.py @@ -0,0 +1,266 @@ +import math +import time +import argparse +import torch +import torch.nn as nn +import torch_neuronx +import neuronx_distributed +import os +import gradio as gr +from fastapi import FastAPI +from huggingface_hub import login + +from diffusers import FluxPipeline +from diffusers.models.modeling_outputs import Transformer2DModelOutput +from typing import Any, Dict, Optional, Union + + +prompt= "A cat holding a sign that says hello world" +num_inference_steps=20 + +nodepool=os.environ['NODEPOOL'] +model_id=os.environ['MODEL_ID'] +device=os.environ["DEVICE"] +pod_name=os.environ['POD_NAME'] +hf_token=os.environ['HUGGINGFACE_TOKEN'].strip() +height=int(os.environ['HEIGHT']) +width=int(os.environ['WIDTH']) +max_sequence_length=int(os.environ['MAX_SEQ_LEN']) +guidance_scale=float(os.environ['GUIDANCE_SCALE']) + +login(hf_token,add_to_git_credential=True) + +COMPILER_WORKDIR_ROOT=os.environ['COMPILER_WORKDIR_ROOT'] + +TEXT_ENCODER_PATH = os.path.join( + COMPILER_WORKDIR_ROOT, + 'text_encoder_1/compiled_model/model.pt') +TEXT_ENCODER_2_PATH = os.path.join( + COMPILER_WORKDIR_ROOT, + 'text_encoder_2/compiled_model/model.pt') +VAE_DECODER_PATH = os.path.join( + COMPILER_WORKDIR_ROOT, + 'decoder/compiled_model/model.pt') + +EMBEDDERS_DIR = os.path.join( + COMPILER_WORKDIR_ROOT, + 'transformer/compiled_model/embedders') +OUT_LAYERS_DIR = os.path.join( + COMPILER_WORKDIR_ROOT, + 'transformer/compiled_model/out_layers') +SINGLE_TRANSFORMER_BLOCKS_DIR = os.path.join( + COMPILER_WORKDIR_ROOT, + 'transformer/compiled_model/single_transformer_blocks') +TRANSFORMER_BLOCKS_DIR = os.path.join( + COMPILER_WORKDIR_ROOT, + 'transformer/compiled_model/transformer_blocks') + + +class NeuronFluxTransformer2DModel(nn.Module): + def __init__( + self, + config, + x_embedder, + context_embedder + ): + super().__init__() + with torch_neuronx.experimental.neuron_cores_context(start_nc=4, + nc_count=8): + self.embedders_model = \ + neuronx_distributed.trace.parallel_model_load(EMBEDDERS_DIR) + self.transformer_blocks_model = \ + neuronx_distributed.trace.parallel_model_load( + TRANSFORMER_BLOCKS_DIR) + self.single_transformer_blocks_model = \ + neuronx_distributed.trace.parallel_model_load( + SINGLE_TRANSFORMER_BLOCKS_DIR) + self.out_layers_model = \ + neuronx_distributed.trace.parallel_model_load( + OUT_LAYERS_DIR) + self.config = config + self.x_embedder = x_embedder + self.context_embedder = context_embedder + self.device = torch.device("cpu") + + def forward( + self, + hidden_states: torch.Tensor, + encoder_hidden_states: torch.Tensor = None, + pooled_projections: torch.Tensor = None, + timestep: torch.LongTensor = None, + img_ids: torch.Tensor = None, + txt_ids: torch.Tensor = None, + guidance: torch.Tensor = None, + joint_attention_kwargs: Optional[Dict[str, Any]] = None, + return_dict: bool = False, + ) -> Union[torch.FloatTensor, Transformer2DModelOutput]: + + hidden_states = self.x_embedder(hidden_states) + + hidden_states, temb, image_rotary_emb = self.embedders_model( + hidden_states, + timestep, + guidance, + pooled_projections, + txt_ids, + img_ids + ) + + encoder_hidden_states = self.context_embedder(encoder_hidden_states) + + image_rotary_emb = image_rotary_emb.type(torch.bfloat16) + + encoder_hidden_states, hidden_states = self.transformer_blocks_model( + hidden_states, + encoder_hidden_states, + temb, + image_rotary_emb + ) + + hidden_states = torch.cat([encoder_hidden_states, hidden_states], + dim=1) + + hidden_states = self.single_transformer_blocks_model( + hidden_states, + temb, + image_rotary_emb + ) + + hidden_states = hidden_states.to(torch.bfloat16) + + return self.out_layers_model( + hidden_states, + encoder_hidden_states, + temb + ) + + +class NeuronFluxCLIPTextEncoderModel(nn.Module): + def __init__(self, dtype, encoder): + super().__init__() + self.dtype = dtype + self.encoder = encoder + self.device = torch.device("cpu") + + def forward(self, emb, output_hidden_states): + output = self.encoder(emb) + output = CLIPEncoderOutput(output) + return output + + +class CLIPEncoderOutput(): + def __init__(self, dictionary): + self.pooler_output = dictionary["pooler_output"] + + +class NeuronFluxT5TextEncoderModel(nn.Module): + def __init__(self, dtype, encoder): + super().__init__() + self.dtype = dtype + self.encoder = encoder + self.device = torch.device("cpu") + + def forward(self, emb, output_hidden_states): + return torch.unsqueeze(self.encoder(emb)["last_hidden_state"], 1) + + +def load_model( + prompt, + height, + width, + max_sequence_length, + num_inference_steps): + pipe = FluxPipeline.from_pretrained( + "black-forest-labs/FLUX.1-dev", + torch_dtype=torch.bfloat16) + with torch_neuronx.experimental.neuron_cores_context(start_nc=0): + pipe.text_encoder = NeuronFluxCLIPTextEncoderModel( + pipe.text_encoder.dtype, + torch.jit.load(TEXT_ENCODER_PATH)) + with torch_neuronx.experimental.neuron_cores_context(start_nc=8): + pipe.text_encoder_2 = NeuronFluxT5TextEncoderModel( + pipe.text_encoder_2.dtype, + torch.jit.load(TEXT_ENCODER_2_PATH)) + pipe.transformer = NeuronFluxTransformer2DModel( + pipe.transformer.config, + pipe.transformer.x_embedder, + pipe.transformer.context_embedder) + with torch_neuronx.experimental.neuron_cores_context(start_nc=8): + pipe.vae.decoder = torch.jit.load(VAE_DECODER_PATH) + + return pipe + +def benchmark(n_runs, test_name, model, model_inputs): + if not isinstance(model_inputs, tuple): + model_inputs = model_inputs + + warmup_run = model(**model_inputs) + + latency_collector = LatencyCollector() + + for _ in range(n_runs): + latency_collector.pre_hook() + res = model(**model_inputs) + image=res.images[0] + image.save(os.path.join(COMPILER_WORKDIR_ROOT, "flux-dev.png")) + latency_collector.hook() + + p0_latency_ms = latency_collector.percentile(0) * 1000 + p50_latency_ms = latency_collector.percentile(50) * 1000 + p90_latency_ms = latency_collector.percentile(90) * 1000 + p95_latency_ms = latency_collector.percentile(95) * 1000 + p99_latency_ms = latency_collector.percentile(99) * 1000 + p100_latency_ms = latency_collector.percentile(100) * 1000 + + report_dict = dict() + report_dict["Latency P0"] = f'{p0_latency_ms:.1f}' + report_dict["Latency P50"]=f'{p50_latency_ms:.1f}' + report_dict["Latency P90"]=f'{p90_latency_ms:.1f}' + report_dict["Latency P95"]=f'{p95_latency_ms:.1f}' + report_dict["Latency P99"]=f'{p99_latency_ms:.1f}' + report_dict["Latency P100"]=f'{p100_latency_ms:.1f}' + + report = f'RESULT FOR {test_name}:' + for key, value in report_dict.items(): + report += f' {key}={value}' + print(report) + return report + +class LatencyCollector: + def __init__(self): + self.start = None + self.latency_list = [] + + def pre_hook(self, *args): + self.start = time.time() + + def hook(self, *args): + self.latency_list.append(time.time() - self.start) + + def percentile(self, percent): + latency_list = self.latency_list + pos_float = len(latency_list) * percent / 100 + max_pos = len(latency_list) - 1 + pos_floor = min(math.floor(pos_float), max_pos) + pos_ceil = min(math.ceil(pos_float), max_pos) + latency_list = sorted(latency_list) + return latency_list[pos_ceil] if pos_float - pos_floor > 0.5 else latency_list[pos_floor] + +def text2img(prompt,num_inference_steps): + start_time = time.time() + model_args={'prompt':prompt,'height':height,'width':width,'max_sequence_length':max_sequence_length,'num_inference_steps': int(num_inference_steps),'guidance_scale':guidance_scale} + image = model(**model_args).images[0] + total_time = time.time()-start_time + return image, str(total_time) + + +model=load_model( + prompt, + height, + width, + max_sequence_length, + num_inference_steps +) +model_inputs={'prompt':prompt,'height':height,'width':width,'max_sequence_length':max_sequence_length,'num_inference_steps': num_inference_steps,'guidance_scale':guidance_scale} +test_name="flux1-dev-50runs on "+nodepool+";num_inference_steps:"+num_inference_steps +benchmark(50,test_name,model,model_inputs) diff --git a/flux_serve/specs/compile-flux-1024x576.yaml b/flux_serve/specs/compile-flux-1024x576.yaml index 2f640e6..2e2f6bc 100644 --- a/flux_serve/specs/compile-flux-1024x576.yaml +++ b/flux_serve/specs/compile-flux-1024x576.yaml @@ -28,6 +28,7 @@ spec: cd /src ./compile.sh cp -r * /model/1024x576 + python /benchmark-flux.py while true; do sleep 3600; done resources: limits: @@ -35,6 +36,8 @@ spec: requests: aws.amazon.com/neuron: 8 env: + - name: COMPILER_WORKDIR_ROOT + value: "/model/1024x576" - name: HEIGHT value: "1024" - name: WIDTH diff --git a/flux_serve/specs/flux-neuron-gradio.yaml b/flux_serve/specs/flux-neuron-gradio.yaml new file mode 100644 index 0000000..e7ef5e8 --- /dev/null +++ b/flux_serve/specs/flux-neuron-gradio.yaml @@ -0,0 +1,53 @@ +apiVersion: v1 +kind: Service +metadata: + name: flux-neuron-gradio +spec: + selector: + app: flux-neuron-gradio + ports: + - protocol: TCP + port: 8000 + targetPort: 8000 + type: ClusterIP +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + labels: + app: flux-neuron-gradio + name: flux-neuron-gradio +spec: + selector: + matchLabels: + app: flux-neuron-gradio + template: + metadata: + labels: + app: flux-neuron-gradio + spec: + nodeSelector: + alpha.eksctl.io/nodegroup-name: flux-usw2-ng + #serviceAccountName: appsimulator + containers: + - name: app + image: 920372998901.dkr.ecr.us-west-2.amazonaws.com/model:amd64-neuron + imagePullPolicy: Always + #command: ["sh", "-c", "while true; do sleep 3600; done"] + command: ["sh", "-c", "uvicorn flux_gradio:app --host=0.0.0.0"] + ports: + - containerPort: 8000 + protocol: TCP + readinessProbe: + httpGet: + path: /readiness + port: 8000 + initialDelaySeconds: 60 + periodSeconds: 10 + env: + - name: MODEL_ID + value: "black-forest-labs/FLUX.1-dev" + - name: POD_NAME + valueFrom: + fieldRef: + fieldPath: metadata.name diff --git a/flux_serve/specs/flux-neuron-ingress.yaml b/flux_serve/specs/flux-neuron-ingress.yaml new file mode 100644 index 0000000..b27e4f0 --- /dev/null +++ b/flux_serve/specs/flux-neuron-ingress.yaml @@ -0,0 +1,34 @@ +apiVersion: networking.k8s.io/v1 +kind: Ingress +metadata: + name: flux-neuron + annotations: + kubernetes.io/ingress.class: alb + alb.ingress.kubernetes.io/scheme: internet-facing + alb.ingress.kubernetes.io/target-type: ip + alb.ingress.kubernetes.io/healthcheck-path: /health + alb.ingress.kubernetes.io/healthcheck-interval-seconds: '10' + alb.ingress.kubernetes.io/healthcheck-timeout-seconds: '9' + alb.ingress.kubernetes.io/healthy-threshold-count: '2' + alb.ingress.kubernetes.io/unhealthy-threshold-count: '10' + alb.ingress.kubernetes.io/success-codes: '200-301' + alb.ingress.kubernetes.io/listen-ports: '[{"HTTP":80}]' + alb.ingress.kubernetes.io/backend-protocol: HTTP + alb.ingress.kubernetes.io/target-group-attributes: stickiness.enabled=true,stickiness.lb_cookie.duration_seconds=10 + alb.ingress.kubernetes.io/load-balancer-name: flux-neuron + alb.ingress.kubernetes.io/actions.weighted-routing: > + {"type":"forward","forwardConfig":{"targetGroups":[{"serviceName":"flux-neuron-gradio","servicePort":8000,"weight":100}],"targetGroupStickinessConfig":{"enabled":true,"durationSeconds":200}}} + labels: + app: flux-neuron-gradio +spec: + ingressClassName: alb + rules: + - http: + paths: + - path: / + pathType: Prefix + backend: + service: + name: weighted-routing + port: + name: use-annotation From 0bbab64082a3213c45748f534ef3addf11a37f7f Mon Sep 17 00:00:00 2001 From: Yahav Date: Fri, 3 Jan 2025 23:49:22 -0800 Subject: [PATCH 15/45] compile13 --- flux_serve/app/benchmark-flux.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/flux_serve/app/benchmark-flux.py b/flux_serve/app/benchmark-flux.py index f1f5e4f..b592a99 100644 --- a/flux_serve/app/benchmark-flux.py +++ b/flux_serve/app/benchmark-flux.py @@ -20,8 +20,6 @@ nodepool=os.environ['NODEPOOL'] model_id=os.environ['MODEL_ID'] -device=os.environ["DEVICE"] -pod_name=os.environ['POD_NAME'] hf_token=os.environ['HUGGINGFACE_TOKEN'].strip() height=int(os.environ['HEIGHT']) width=int(os.environ['WIDTH']) From e64de7096e5bd6eb4b2478f45a6c8ed192e58563 Mon Sep 17 00:00:00 2001 From: Yahav Date: Sat, 4 Jan 2025 00:13:44 -0800 Subject: [PATCH 16/45] compile14 --- flux_serve/app/benchmark-flux.py | 26 ++++++++++++++------------ 1 file changed, 14 insertions(+), 12 deletions(-) diff --git a/flux_serve/app/benchmark-flux.py b/flux_serve/app/benchmark-flux.py index b592a99..4f958a1 100644 --- a/flux_serve/app/benchmark-flux.py +++ b/flux_serve/app/benchmark-flux.py @@ -40,6 +40,9 @@ COMPILER_WORKDIR_ROOT, 'decoder/compiled_model/model.pt') +TEXT_ENCODER_2_DIR = os.path.join( + COMPILER_WORKDIR_ROOT, + 'text_encoder_2/compiled_model/text_encoder_2') EMBEDDERS_DIR = os.path.join( COMPILER_WORKDIR_ROOT, 'transformer/compiled_model/embedders') @@ -168,23 +171,22 @@ def load_model( width, max_sequence_length, num_inference_steps): - pipe = FluxPipeline.from_pretrained( - "black-forest-labs/FLUX.1-dev", - torch_dtype=torch.bfloat16) - with torch_neuronx.experimental.neuron_cores_context(start_nc=0): + with torch_neuronx.experimental.neuron_cores_context(start_nc=8): + pipe = CustomFluxPipeline.from_pretrained( + "black-forest-labs/FLUX.1-dev", + torch_dtype=torch.bfloat16) + + with torch_neuronx.experimental.neuron_cores_context(start_nc=8): pipe.text_encoder = NeuronFluxCLIPTextEncoderModel( pipe.text_encoder.dtype, torch.jit.load(TEXT_ENCODER_PATH)) - with torch_neuronx.experimental.neuron_cores_context(start_nc=8): - pipe.text_encoder_2 = NeuronFluxT5TextEncoderModel( - pipe.text_encoder_2.dtype, - torch.jit.load(TEXT_ENCODER_2_PATH)) - pipe.transformer = NeuronFluxTransformer2DModel( - pipe.transformer.config, - pipe.transformer.x_embedder, - pipe.transformer.context_embedder) + with torch_neuronx.experimental.neuron_cores_context(start_nc=8): pipe.vae.decoder = torch.jit.load(VAE_DECODER_PATH) + + with torch_neuronx.experimental.neuron_cores_context(start_nc=0, nc_count=8): + sharded_text_encoder_2 = neuronx_distributed.trace.parallel_model_load(TEXT_ENCODER_2_DIR) + pipe.text_encoder_2 = TextEncoder2Wrapper(sharded_text_encoder_2) return pipe From c74af831fc352e7ea60c637b708fa1477ba65d76 Mon Sep 17 00:00:00 2001 From: Yahav Date: Sat, 4 Jan 2025 11:02:36 -0800 Subject: [PATCH 17/45] complie15 --- flux_serve/app/benchmark-flux.py | 86 ++++++++++++++++---------------- 1 file changed, 43 insertions(+), 43 deletions(-) diff --git a/flux_serve/app/benchmark-flux.py b/flux_serve/app/benchmark-flux.py index 4f958a1..9de60b3 100644 --- a/flux_serve/app/benchmark-flux.py +++ b/flux_serve/app/benchmark-flux.py @@ -6,17 +6,12 @@ import torch_neuronx import neuronx_distributed import os -import gradio as gr -from fastapi import FastAPI -from huggingface_hub import login from diffusers import FluxPipeline from diffusers.models.modeling_outputs import Transformer2DModelOutput from typing import Any, Dict, Optional, Union - - -prompt= "A cat holding a sign that says hello world" -num_inference_steps=20 +from huggingface_hub import login +from huggingface_hub import whoami nodepool=os.environ['NODEPOOL'] model_id=os.environ['MODEL_ID'] @@ -26,9 +21,17 @@ max_sequence_length=int(os.environ['MAX_SEQ_LEN']) guidance_scale=float(os.environ['GUIDANCE_SCALE']) -login(hf_token,add_to_git_credential=True) +prompt= "A cat holding a sign that says hello world" +num_inference_steps=20 -COMPILER_WORKDIR_ROOT=os.environ['COMPILER_WORKDIR_ROOT'] +hf_token=os.environ['HUGGINGFACE_TOKEN'].strip() +try: + user_info = whoami() + print(f"Already logged in as {user_info['name']}") +except: + login(hf_token,add_to_git_credential=True) + +COMPILER_WORKDIR_ROOT = os.environ['COMPILER_WORKDIR_ROOT'] TEXT_ENCODER_PATH = os.path.join( COMPILER_WORKDIR_ROOT, @@ -56,6 +59,23 @@ COMPILER_WORKDIR_ROOT, 'transformer/compiled_model/transformer_blocks') +class CustomFluxPipeline(FluxPipeline): + @property + def _execution_device(self): + return torch.device("cpu") + +class TextEncoder2Wrapper(nn.Module): + def __init__(self, sharded_model,dtype=torch.bfloat16): + super().__init__() + self.sharded_model = sharded_model + self.dtype = dtype + + def forward(self, input_ids, output_hidden_states=False, **kwargs): + attention_mask = (input_ids != 0).long() + output = self.sharded_model(input_ids,attention_mask) + last_hidden_state = output[0] + processed_output = last_hidden_state + return (processed_output,) class NeuronFluxTransformer2DModel(nn.Module): def __init__( @@ -65,19 +85,12 @@ def __init__( context_embedder ): super().__init__() - with torch_neuronx.experimental.neuron_cores_context(start_nc=4, - nc_count=8): - self.embedders_model = \ - neuronx_distributed.trace.parallel_model_load(EMBEDDERS_DIR) - self.transformer_blocks_model = \ - neuronx_distributed.trace.parallel_model_load( - TRANSFORMER_BLOCKS_DIR) - self.single_transformer_blocks_model = \ - neuronx_distributed.trace.parallel_model_load( - SINGLE_TRANSFORMER_BLOCKS_DIR) - self.out_layers_model = \ - neuronx_distributed.trace.parallel_model_load( - OUT_LAYERS_DIR) + with torch_neuronx.experimental.neuron_cores_context(start_nc=0, nc_count=8): + self.embedders_model = neuronx_distributed.trace.parallel_model_load(EMBEDDERS_DIR) + self.out_layers_model = neuronx_distributed.trace.parallel_model_load(OUT_LAYERS_DIR) + self.transformer_blocks_model = neuronx_distributed.trace.parallel_model_load(TRANSFORMER_BLOCKS_DIR) + self.single_transformer_blocks_model = neuronx_distributed.trace.parallel_model_load(SINGLE_TRANSFORMER_BLOCKS_DIR) + self.config = config self.x_embedder = x_embedder self.context_embedder = context_embedder @@ -153,18 +166,6 @@ class CLIPEncoderOutput(): def __init__(self, dictionary): self.pooler_output = dictionary["pooler_output"] - -class NeuronFluxT5TextEncoderModel(nn.Module): - def __init__(self, dtype, encoder): - super().__init__() - self.dtype = dtype - self.encoder = encoder - self.device = torch.device("cpu") - - def forward(self, emb, output_hidden_states): - return torch.unsqueeze(self.encoder(emb)["last_hidden_state"], 1) - - def load_model( prompt, height, @@ -188,6 +189,11 @@ def load_model( sharded_text_encoder_2 = neuronx_distributed.trace.parallel_model_load(TEXT_ENCODER_2_DIR) pipe.text_encoder_2 = TextEncoder2Wrapper(sharded_text_encoder_2) + pipe.transformer = NeuronFluxTransformer2DModel( + pipe.transformer.config, + pipe.transformer.x_embedder, + pipe.transformer.context_embedder) + return pipe def benchmark(n_runs, test_name, model, model_inputs): @@ -202,7 +208,7 @@ def benchmark(n_runs, test_name, model, model_inputs): latency_collector.pre_hook() res = model(**model_inputs) image=res.images[0] - image.save(os.path.join(COMPILER_WORKDIR_ROOT, "flux-dev.png")) + #image.save(os.path.join("/tmp", "flux-dev.png")) latency_collector.hook() p0_latency_ms = latency_collector.percentile(0) * 1000 @@ -254,13 +260,7 @@ def text2img(prompt,num_inference_steps): return image, str(total_time) -model=load_model( - prompt, - height, - width, - max_sequence_length, - num_inference_steps -) +model=load_model(prompt,height,width,max_sequence_length,num_inference_steps) model_inputs={'prompt':prompt,'height':height,'width':width,'max_sequence_length':max_sequence_length,'num_inference_steps': num_inference_steps,'guidance_scale':guidance_scale} -test_name="flux1-dev-50runs on "+nodepool+";num_inference_steps:"+num_inference_steps +test_name=f"flux1-dev-50runs on {nodepool};num_inference_steps:{num_inference_steps}" benchmark(50,test_name,model,model_inputs) From 741eb71e90f6a7d085c1f33fed8d28ac65ad5e48 Mon Sep 17 00:00:00 2001 From: Yahav Date: Sat, 4 Jan 2025 11:34:42 -0800 Subject: [PATCH 18/45] compile15 --- flux_serve/app/benchmark-flux.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/flux_serve/app/benchmark-flux.py b/flux_serve/app/benchmark-flux.py index 9de60b3..9dcda93 100644 --- a/flux_serve/app/benchmark-flux.py +++ b/flux_serve/app/benchmark-flux.py @@ -262,5 +262,5 @@ def text2img(prompt,num_inference_steps): model=load_model(prompt,height,width,max_sequence_length,num_inference_steps) model_inputs={'prompt':prompt,'height':height,'width':width,'max_sequence_length':max_sequence_length,'num_inference_steps': num_inference_steps,'guidance_scale':guidance_scale} -test_name=f"flux1-dev-50runs on {nodepool};num_inference_steps:{num_inference_steps}" +test_name=f"flux1-dev-50runs with dim {height}x{width} on {nodepool};num_inference_steps:{num_inference_steps}" benchmark(50,test_name,model,model_inputs) From 3fda9a2ae9144fe20a88027b1327e7b3d574d0bf Mon Sep 17 00:00:00 2001 From: Yahav Date: Sat, 4 Jan 2025 11:48:21 -0800 Subject: [PATCH 19/45] flux_model_api.py --- flux_serve/app/flux_model_api.py | 30 ++++++++++++++++++------------ 1 file changed, 18 insertions(+), 12 deletions(-) diff --git a/flux_serve/app/flux_model_api.py b/flux_serve/app/flux_model_api.py index 8f424ea..70857ed 100644 --- a/flux_serve/app/flux_model_api.py +++ b/flux_serve/app/flux_model_api.py @@ -55,13 +55,13 @@ def cw_pub_metric(metric_name,metric_value,metric_unit): TEXT_ENCODER_PATH = os.path.join( COMPILER_WORKDIR_ROOT, 'text_encoder_1/compiled_model/model.pt') -TEXT_ENCODER_2_PATH = os.path.join( - COMPILER_WORKDIR_ROOT, - 'text_encoder_2/compiled_model/model.pt') VAE_DECODER_PATH = os.path.join( COMPILER_WORKDIR_ROOT, 'decoder/compiled_model/model.pt') +TEXT_ENCODER_2_DIR = os.path.join( + COMPILER_WORKDIR_ROOT, + 'text_encoder_2/compiled_model/text_encoder_2') EMBEDDERS_DIR = os.path.join( COMPILER_WORKDIR_ROOT, 'transformer/compiled_model/embedders') @@ -193,25 +193,31 @@ def __init__(self, dtype, encoder): def forward(self, emb, output_hidden_states): return torch.unsqueeze(self.encoder(emb)["last_hidden_state"], 1) + + # Load the model pipeline def load_model(): - pipe = FluxPipeline.from_pretrained( - "black-forest-labs/FLUX.1-dev", - torch_dtype=DTYPE) - with torch_neuronx.experimental.neuron_cores_context(start_nc=0): + with torch_neuronx.experimental.neuron_cores_context(start_nc=8): + pipe = CustomFluxPipeline.from_pretrained( + "black-forest-labs/FLUX.1-dev", + torch_dtype=torch.bfloat16) + + with torch_neuronx.experimental.neuron_cores_context(start_nc=8): pipe.text_encoder = NeuronFluxCLIPTextEncoderModel( pipe.text_encoder.dtype, torch.jit.load(TEXT_ENCODER_PATH)) + with torch_neuronx.experimental.neuron_cores_context(start_nc=8): - pipe.text_encoder_2 = NeuronFluxT5TextEncoderModel( - pipe.text_encoder_2.dtype, - torch.jit.load(TEXT_ENCODER_2_PATH)) + pipe.vae.decoder = torch.jit.load(VAE_DECODER_PATH) + + with torch_neuronx.experimental.neuron_cores_context(start_nc=0, nc_count=8): + sharded_text_encoder_2 = neuronx_distributed.trace.parallel_model_load(TEXT_ENCODER_2_DIR) + pipe.text_encoder_2 = TextEncoder2Wrapper(sharded_text_encoder_2) + pipe.transformer = NeuronFluxTransformer2DModel( pipe.transformer.config, pipe.transformer.x_embedder, pipe.transformer.context_embedder) - with torch_neuronx.experimental.neuron_cores_context(start_nc=8): - pipe.vae.decoder = torch.jit.load(VAE_DECODER_PATH) return pipe model = load_model() From 3d355e2d72199d2887cdd94ca848b792ef51b950 Mon Sep 17 00:00:00 2001 From: Yahav Date: Sat, 4 Jan 2025 12:00:57 -0800 Subject: [PATCH 20/45] flux_model_api.py1 --- flux_serve/app/flux_model_api.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/flux_serve/app/flux_model_api.py b/flux_serve/app/flux_model_api.py index 70857ed..a4a8770 100644 --- a/flux_serve/app/flux_model_api.py +++ b/flux_serve/app/flux_model_api.py @@ -78,6 +78,11 @@ def cw_pub_metric(metric_name,metric_value,metric_unit): # Login to Hugging Face login(hf_token, add_to_git_credential=True) +class CustomFluxPipeline(FluxPipeline): + @property + def _execution_device(self): + return torch.device("cpu") + class GenerateImageRequest(BaseModel): prompt: str num_inference_steps: int From eeaa8cfb1741a5cecfba054f7a7975bb8b14e58e Mon Sep 17 00:00:00 2001 From: Yahav Date: Sat, 4 Jan 2025 12:27:23 -0800 Subject: [PATCH 21/45] flux_model_api.py1 --- flux_serve/app/flux_model_api.py | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/flux_serve/app/flux_model_api.py b/flux_serve/app/flux_model_api.py index a4a8770..cf0604d 100644 --- a/flux_serve/app/flux_model_api.py +++ b/flux_serve/app/flux_model_api.py @@ -83,6 +83,19 @@ class CustomFluxPipeline(FluxPipeline): def _execution_device(self): return torch.device("cpu") +class TextEncoder2Wrapper(nn.Module): + def __init__(self, sharded_model,dtype=torch.bfloat16): + super().__init__() + self.sharded_model = sharded_model + self.dtype = dtype + + def forward(self, input_ids, output_hidden_states=False, **kwargs): + attention_mask = (input_ids != 0).long() + output = self.sharded_model(input_ids,attention_mask) + last_hidden_state = output[0] + processed_output = last_hidden_state + return (processed_output,) + class GenerateImageRequest(BaseModel): prompt: str num_inference_steps: int From 86f3b377d10f7e130c97c1e85baf8c83e69fa585 Mon Sep 17 00:00:00 2001 From: Yahav Date: Sun, 5 Jan 2025 00:18:58 -0800 Subject: [PATCH 22/45] recompilewithtextenc2shard --- flux_serve/README.md | 9 +++ flux_serve/app/src/README.md | 2 +- flux_serve/app/src/compile.sh | 3 +- flux_serve/app/src/decoder/compile.py | 2 +- flux_serve/app/src/inference.py | 62 +++++++++++-------- flux_serve/app/src/text_encoder_1/compile.py | 2 +- flux_serve/app/src/text_encoder_1/model.py | 1 + flux_serve/app/src/text_encoder_2/compile.py | 63 ++++++++++++-------- flux_serve/app/src/text_encoder_2/model.py | 40 +++---------- flux_serve/app/src/transformer/compile.py | 53 +++++++--------- flux_serve/app/src/transformer/model.py | 54 +++++++---------- flux_serve/specs/compile-flux-1024x576.yaml | 8 ++- 12 files changed, 144 insertions(+), 155 deletions(-) diff --git a/flux_serve/README.md b/flux_serve/README.md index 3184f14..398ec86 100644 --- a/flux_serve/README.md +++ b/flux_serve/README.md @@ -69,5 +69,14 @@ Note the three pending Deployment Pods that Karpenter seeks to fulfill. Current * Deploy the Flux serving frontend that includes Gradio app. ```bash kubectl apply -f specs/flux-neuron-gradio.yaml +kubectl apply -f specs/flux-neuron-ingress.yaml ``` +Discover the model serving endpoint by: +```bash +kubectl get ingress +NAME CLASS HOSTS ADDRESS PORTS AGE +flux-neuron alb * flux-neuron-658286526.us-west-2.elb.amazonaws.com 80 7h20m +``` + +Use [flux-neuron-658286526.us-west-2.elb.amazonaws.com/serve/](flux-neuron-658286526.us-west-2.elb.amazonaws.com/serve/) diff --git a/flux_serve/app/src/README.md b/flux_serve/app/src/README.md index 7e7f6a6..f796700 100644 --- a/flux_serve/app/src/README.md +++ b/flux_serve/app/src/README.md @@ -1,4 +1,4 @@ -# Compile Flux +# flux-enigma clean previous compilation ```bash diff --git a/flux_serve/app/src/compile.sh b/flux_serve/app/src/compile.sh index 863cc9e..75cf813 100755 --- a/flux_serve/app/src/compile.sh +++ b/flux_serve/app/src/compile.sh @@ -1,5 +1,3 @@ -#!/bin/bash -x - find . -type d \( -name "compiled_model" -o -name "__pycache__" -o -name "compiler_workdir" \) -exec rm -rf {} + python "./text_encoder_1/compile.py" @@ -8,3 +6,4 @@ python "./transformer/compile.py" -hh $HEIGHT -w $WIDTH -m 32 python "./decoder/compile.py" -hh $HEIGHT -w $WIDTH echo "done compiling; cleaning compiler_workdir" find . -type d \( -name "__pycache__" -o -name "compiler_workdir" \) -exec rm -rf {} + + diff --git a/flux_serve/app/src/decoder/compile.py b/flux_serve/app/src/decoder/compile.py index 3d5cd7c..0ee3830 100644 --- a/flux_serve/app/src/decoder/compile.py +++ b/flux_serve/app/src/decoder/compile.py @@ -26,7 +26,7 @@ def trace_vae(height, width): del pipe latents = torch.rand([1, 16, height // 8, width // 8], - dtype=DTYPE) + dtype=torch.bfloat16) decoder_neuron = torch_neuronx.trace( decoder, diff --git a/flux_serve/app/src/inference.py b/flux_serve/app/src/inference.py index 8a23989..7530000 100644 --- a/flux_serve/app/src/inference.py +++ b/flux_serve/app/src/inference.py @@ -8,17 +8,8 @@ from diffusers import FluxPipeline from diffusers.models.modeling_outputs import Transformer2DModelOutput from typing import Any, Dict, Optional, Union -from huggingface_hub import login -from huggingface_hub import whoami -hf_token=os.environ['HUGGINGFACE_TOKEN'].strip() -try: - user_info = whoami() - print(f"Already logged in as {user_info['name']}") -except: - login(hf_token,add_to_git_credential=True) - -#COMPILER_WORKDIR_ROOT = os.path.dirname(__file__) -COMPILER_WORKDIR_ROOT = os.environ['COMPILER_WORKDIR_ROOT'] + +COMPILER_WORKDIR_ROOT = os.path.dirname(__file__) TEXT_ENCODER_PATH = os.path.join( COMPILER_WORKDIR_ROOT, @@ -33,6 +24,7 @@ TEXT_ENCODER_2_DIR = os.path.join( COMPILER_WORKDIR_ROOT, 'text_encoder_2/compiled_model/text_encoder_2') + EMBEDDERS_DIR = os.path.join( COMPILER_WORKDIR_ROOT, 'transformer/compiled_model/embedders') @@ -64,6 +56,7 @@ def forward(self, input_ids, output_hidden_states=False, **kwargs): processed_output = last_hidden_state return (processed_output,) + class NeuronFluxTransformer2DModel(nn.Module): def __init__( self, @@ -72,12 +65,19 @@ def __init__( context_embedder ): super().__init__() - with torch_neuronx.experimental.neuron_cores_context(start_nc=0, nc_count=8): - self.embedders_model = neuronx_distributed.trace.parallel_model_load(EMBEDDERS_DIR) - self.out_layers_model = neuronx_distributed.trace.parallel_model_load(OUT_LAYERS_DIR) - self.transformer_blocks_model = neuronx_distributed.trace.parallel_model_load(TRANSFORMER_BLOCKS_DIR) - self.single_transformer_blocks_model = neuronx_distributed.trace.parallel_model_load(SINGLE_TRANSFORMER_BLOCKS_DIR) - + with torch_neuronx.experimental.neuron_cores_context(start_nc=0, + nc_count=8): + self.embedders_model = \ + neuronx_distributed.trace.parallel_model_load(EMBEDDERS_DIR) + self.transformer_blocks_model = \ + neuronx_distributed.trace.parallel_model_load( + TRANSFORMER_BLOCKS_DIR) + self.single_transformer_blocks_model = \ + neuronx_distributed.trace.parallel_model_load( + SINGLE_TRANSFORMER_BLOCKS_DIR) + self.out_layers_model = \ + neuronx_distributed.trace.parallel_model_load( + OUT_LAYERS_DIR) self.config = config self.x_embedder = x_embedder self.context_embedder = context_embedder @@ -153,30 +153,40 @@ class CLIPEncoderOutput(): def __init__(self, dictionary): self.pooler_output = dictionary["pooler_output"] + +class NeuronFluxT5TextEncoderModel(nn.Module): + def __init__(self, dtype, encoder): + super().__init__() + self.dtype = dtype + self.encoder = encoder + self.device = torch.device("cpu") + + def forward(self, emb, output_hidden_states): + return torch.unsqueeze(self.encoder(emb)["last_hidden_state"], 1) + + def run_inference( prompt, height, width, max_sequence_length, num_inference_steps): - with torch_neuronx.experimental.neuron_cores_context(start_nc=8): pipe = CustomFluxPipeline.from_pretrained( "black-forest-labs/FLUX.1-dev", torch_dtype=torch.bfloat16) with torch_neuronx.experimental.neuron_cores_context(start_nc=8): - pipe.text_encoder = NeuronFluxCLIPTextEncoderModel( + pipe.text_encoder = NeuronFluxCLIPTextEncoderModel( pipe.text_encoder.dtype, torch.jit.load(TEXT_ENCODER_PATH)) with torch_neuronx.experimental.neuron_cores_context(start_nc=8): - pipe.vae.decoder = torch.jit.load(VAE_DECODER_PATH) + pipe.vae.decoder = torch.jit.load(VAE_DECODER_PATH) with torch_neuronx.experimental.neuron_cores_context(start_nc=0, nc_count=8): - sharded_text_encoder_2 = neuronx_distributed.trace.parallel_model_load(TEXT_ENCODER_2_DIR) - pipe.text_encoder_2 = TextEncoder2Wrapper(sharded_text_encoder_2) - + sharded_text_encoder_2 = neuronx_distributed.trace.parallel_model_load(TEXT_ENCODER_2_DIR) + pipe.text_encoder_2 = TextEncoder2Wrapper(sharded_text_encoder_2) pipe.transformer = NeuronFluxTransformer2DModel( pipe.transformer.config, @@ -207,21 +217,21 @@ def run_inference( "-hh", "--height", type=int, - default=256, + default=1024, help="height of images to be generated by compilation of this model" ) parser.add_argument( "-w", "--width", type=int, - default=256, + default=1024, help="width of images to be generated by compilation of this model" ) parser.add_argument( "-m", "--max_sequence_length", type=int, - default=32, + default=512, help="maximum sequence length for the text embeddings" ) parser.add_argument( diff --git a/flux_serve/app/src/text_encoder_1/compile.py b/flux_serve/app/src/text_encoder_1/compile.py index ccb732a..871f388 100644 --- a/flux_serve/app/src/text_encoder_1/compile.py +++ b/flux_serve/app/src/text_encoder_1/compile.py @@ -19,7 +19,7 @@ def trace_text_encoder(): pipe = FluxPipeline.from_pretrained( "black-forest-labs/FLUX.1-dev", - torch_dtype=DTYPE) + torch_dtype=torch.bfloat16) text_encoder = copy.deepcopy(pipe.text_encoder) del pipe diff --git a/flux_serve/app/src/text_encoder_1/model.py b/flux_serve/app/src/text_encoder_1/model.py index c046b5c..13151c4 100644 --- a/flux_serve/app/src/text_encoder_1/model.py +++ b/flux_serve/app/src/text_encoder_1/model.py @@ -31,3 +31,4 @@ def forward( output_hidden_states=output_hidden_states, return_dict=True, ) + diff --git a/flux_serve/app/src/text_encoder_2/compile.py b/flux_serve/app/src/text_encoder_2/compile.py index 9d2fa10..15e11c4 100644 --- a/flux_serve/app/src/text_encoder_2/compile.py +++ b/flux_serve/app/src/text_encoder_2/compile.py @@ -3,10 +3,10 @@ import os import torch import torch_neuronx -import neuronx_distributed from diffusers import FluxPipeline +from model import TracingT5TextEncoderWrapper +import neuronx_distributed from transformers import T5EncoderModel - from model import ( TracingT5TextEncoderWrapper, init_text_encoder_2, @@ -25,36 +25,15 @@ DTYPE=torch.bfloat16 def build_text_encoder_2(): - """ - Build the T5 text encoder model, shard it, and wrap it in our tracing class. - Returns the final model + any (optional) kwargs in a dict, i.e. (model, {}). - This pattern is required by neuronx_distributed.trace.parallel_model_trace. - """ - # Load pipeline and copy the text_encoder_2 from your flux pipeline - pipe = FluxPipeline.from_pretrained( - "black-forest-labs/FLUX.1-dev", - torch_dtype=DTYPE - ) - # text_encoder_2 is presumably a T5EncoderModel or custom T5-based module + pipe = FluxPipeline.from_pretrained("black-forest-labs/FLUX.1-dev",torch_dtype=DTYPE) text_encoder_2 = copy.deepcopy(pipe.text_encoder_2) del pipe - # Optionally, if text_encoder_2 is not already a T5EncoderModel, you can - # modify the approach. But presumably, it's a T5EncoderModel or T5-like module. - # Shard the T5 model parameters across tp_degree ranks: init_text_encoder_2(text_encoder_2) - - # Wrap it in a tracing module wrapper = TracingT5TextEncoderWrapper(text_encoder_2) - - # Return the model plus optional kwargs (unused here) return wrapper, {} - def trace_text_encoder_2(max_sequence_length=512): - """ - Trace the T5 text encoder with parallel model trace. - """ input_ids = torch.zeros((1, max_sequence_length), dtype=torch.int64) attention_mask = torch.ones((1, max_sequence_length), dtype=torch.int64) @@ -79,14 +58,46 @@ def trace_text_encoder_2(max_sequence_length=512): del model +''' +def trace_text_encoder_2(max_sequence_length): + pipe = FluxPipeline.from_pretrained( + "black-forest-labs/FLUX.1-dev", + torch_dtype=torch.bfloat16) + text_encoder_2 = copy.deepcopy(pipe.text_encoder_2) + del pipe + + text_encoder_2 = TracingT5TextEncoderWrapper(text_encoder_2) + + emb = torch.zeros((1, max_sequence_length), dtype=torch.int64) + + text_encoder_2_neuron = torch_neuronx.trace( + text_encoder_2.neuron_text_encoder, + emb, + compiler_workdir=os.path.join(COMPILER_WORKDIR_ROOT, + 'compiler_workdir'), + compiler_args=["--enable-fast-loading-neuron-binaries"] + ) + + torch_neuronx.async_load(text_encoder_2_neuron) + + compiled_model_path = os.path.join(COMPILER_WORKDIR_ROOT, 'compiled_model') + if not os.path.exists(compiled_model_path): + os.mkdir(compiled_model_path) + text_encoder_2_filename = os.path.join(COMPILER_WORKDIR_ROOT, + 'compiled_model/model.pt') + torch.jit.save(text_encoder_2_neuron, text_encoder_2_filename) + + del text_encoder_2 + del text_encoder_2_neuron +''' -if __name__ == "__main__": +if __name__ == '__main__': parser = argparse.ArgumentParser() parser.add_argument( "-m", "--max_sequence_length", type=int, - default=32, + default=512, help="maximum sequence length for the text embeddings" ) args = parser.parse_args() diff --git a/flux_serve/app/src/text_encoder_2/model.py b/flux_serve/app/src/text_encoder_2/model.py index 3916ec5..c63caed 100644 --- a/flux_serve/app/src/text_encoder_2/model.py +++ b/flux_serve/app/src/text_encoder_2/model.py @@ -1,5 +1,6 @@ import torch import torch.nn as nn + from transformers.modeling_outputs import BaseModelOutput from typing import Optional, Union, Tuple @@ -8,13 +9,9 @@ ColumnParallelLinear, RowParallelLinear, ) - DTYPE=torch.bfloat16 def get_sharded_data(data: torch.Tensor, dim: int) -> torch.Tensor: - """ - Utility function to slice a parameter across tensor-parallel ranks. - """ tp_rank = parallel_state.get_tensor_model_parallel_rank() tp_size = parallel_state.get_tensor_model_parallel_size() per_partition_size = data.shape[dim] // tp_size @@ -35,10 +32,6 @@ def get_sharded_data(data: torch.Tensor, dim: int) -> torch.Tensor: raise ValueError("Partition dimension must be 0 or 1.") def shard_t5_attention(t5_attention): - """ - Shard the T5 self-attention q, k, v, o projections to ColumnParallel & RowParallel. - This is analogous to shard_attn() in transformer/model.py but adapted for T5. - """ # Shard q orig_q = t5_attention.q t5_attention.q = ColumnParallelLinear( @@ -93,16 +86,6 @@ def shard_t5_attention(t5_attention): del orig_o def shard_t5_ff(ff_block): - """ - Shard the T5 feed-forward block (DenseReluDense or DenseGatedActDense). - Depending on the HF version, T5 may implement FF as: - - T5DenseReluDense, with attributes: ff_block.wi, ff_block.wo - - T5DenseGatedActDense, with attributes: ff_block.wi_0, ff_block.wi_1, ff_block.wo - We'll shard them similarly: - - ColumnParallel for the 'wi_*' inputs - - RowParallel for the 'wo' output - """ - # Helper function for ColumnParallel def make_column_parallel(orig_layer): from neuronx_distributed.parallel_layers.layers import ColumnParallelLinear @@ -132,9 +115,6 @@ def make_row_parallel(orig_layer): new_layer.bias.data = orig_layer.bias.data.detach() return new_layer - # ------------------------------------------------------------- - # 1) T5DenseReluDense -> ff_block.wi, ff_block.wo - # ------------------------------------------------------------- if hasattr(ff_block, "wi") and hasattr(ff_block, "wo"): orig_wi = ff_block.wi ff_block.wi = make_column_parallel(orig_wi) @@ -144,9 +124,6 @@ def make_row_parallel(orig_layer): ff_block.wo = make_row_parallel(orig_wo) del orig_wo - # ------------------------------------------------------------- - # 2) T5DenseGatedActDense -> ff_block.wi_0, ff_block.wi_1, ff_block.wo - # ------------------------------------------------------------- elif hasattr(ff_block, "wi_0") and hasattr(ff_block, "wi_1") and hasattr(ff_block, "wo"): orig_wi_0 = ff_block.wi_0 ff_block.wi_0 = make_column_parallel(orig_wi_0) @@ -167,10 +144,6 @@ def make_row_parallel(orig_layer): ) def init_text_encoder_2(t5_encoder): - """ - Loop over T5Blocks in t5_encoder to shard the self-attention and FF modules. - Typically, T5EncoderModel has model.encoder.block[i].layer[0/1]. - """ encoder_stack = t5_encoder.encoder # T5Stack for block in encoder_stack.block: # block.layer[0] => T5LayerSelfAttention @@ -180,11 +153,8 @@ def init_text_encoder_2(t5_encoder): ff = block.layer[1].DenseReluDense shard_t5_ff(ff) + class TracingT5TextEncoderWrapper(nn.Module): - """ - Wrap the T5 encoder in a forward that returns a stable tuple or BaseModelOutput, - suitable for compilation and serving on Neuron devices. - """ def __init__(self, text_encoder): super().__init__() self.neuron_text_encoder = text_encoder @@ -202,8 +172,10 @@ def forward( output_hidden_states: Optional[bool] = False, return_dict: Optional[bool] = False, ) -> Union[Tuple[torch.FloatTensor], BaseModelOutput]: + return_dict = return_dict if return_dict is not None \ + else self.config.use_return_dict - return self.neuron_text_encoder( + encoder_outputs = self.neuron_text_encoder( input_ids=input_ids, attention_mask=attention_mask, inputs_embeds=inputs_embeds, @@ -213,3 +185,5 @@ def forward( return_dict=return_dict, ) + return encoder_outputs + diff --git a/flux_serve/app/src/transformer/compile.py b/flux_serve/app/src/transformer/compile.py index 69db269..21fcd18 100644 --- a/flux_serve/app/src/transformer/compile.py +++ b/flux_serve/app/src/transformer/compile.py @@ -11,9 +11,7 @@ TracingTransformerBlockWrapper, TracingSingleTransformerBlockWrapper, TracingTransformerOutLayerWrapper, - MyAttentionProcessor, init_transformer) - from huggingface_hub import login from huggingface_hub import whoami hf_token=os.environ['HUGGINGFACE_TOKEN'].strip() @@ -25,12 +23,12 @@ COMPILER_WORKDIR_ROOT = os.path.dirname(__file__) TP_DEGREE=8 -DTYPE=torch.bfloat16 + def trace_transformer_embedders(): pipe = FluxPipeline.from_pretrained( "black-forest-labs/FLUX.1-dev", - torch_dtype=DTYPE) + torch_dtype=torch.bfloat16) transformer: FluxTransformer2DModel = copy.deepcopy(pipe.transformer) del pipe init_transformer(transformer) @@ -44,10 +42,7 @@ def trace_transformer_embedders(): def trace_transformer_blocks(): pipe = FluxPipeline.from_pretrained( "black-forest-labs/FLUX.1-dev", - torch_dtype=DTYPE) - for block in pipe.transformer.transformer_blocks: - block.attn.processor = MyAttentionProcessor() - + torch_dtype=torch.bfloat16) transformer: FluxTransformer2DModel = copy.deepcopy(pipe.transformer) del pipe init_transformer(transformer) @@ -60,9 +55,7 @@ def trace_transformer_blocks(): def trace_single_transformer_blocks(): pipe = FluxPipeline.from_pretrained( "black-forest-labs/FLUX.1-dev", - torch_dtype=DTYPE) - for block in pipe.transformer.single_transformer_blocks: - block.attn.processor = MyAttentionProcessor() + torch_dtype=torch.bfloat16) transformer: FluxTransformer2DModel = copy.deepcopy(pipe.transformer) del pipe init_transformer(transformer) @@ -75,7 +68,7 @@ def trace_single_transformer_blocks(): def trace_transformer_out_layers(): pipe = FluxPipeline.from_pretrained( "black-forest-labs/FLUX.1-dev", - torch_dtype=DTYPE) + torch_dtype=torch.bfloat16) transformer: FluxTransformer2DModel = copy.deepcopy(pipe.transformer) del pipe init_transformer(transformer) @@ -87,12 +80,12 @@ def trace_transformer_out_layers(): def trace_transformer(height, width, max_sequence_length): hidden_states = torch.rand([1, height * width // 256, 3072], - dtype=DTYPE) - timestep = torch.rand([1], dtype=DTYPE) + dtype=torch.bfloat16) + timestep = torch.rand([1], dtype=torch.bfloat16) guidance = torch.rand([1], dtype=torch.float32) - pooled_projections = torch.rand([1, 768], dtype=DTYPE) - txt_ids = torch.rand([1, max_sequence_length, 3], dtype=DTYPE) - img_ids = torch.rand([1, height * width // 256, 3], dtype=DTYPE) + pooled_projections = torch.rand([1, 768], dtype=torch.bfloat16) + txt_ids = torch.rand([1, max_sequence_length, 3], dtype=torch.bfloat16) + img_ids = torch.rand([1, height * width // 256, 3], dtype=torch.bfloat16) sample_inputs = hidden_states, timestep, guidance, pooled_projections, \ txt_ids, img_ids @@ -117,13 +110,13 @@ def trace_transformer(height, width, max_sequence_length): del model hidden_states = torch.rand([1, height * width // 256, 3072], - dtype=DTYPE) + dtype=torch.bfloat16) encoder_hidden_states = torch.rand([1, max_sequence_length, 3072], - dtype=DTYPE) - temb = torch.rand([1, 3072], dtype=DTYPE) + dtype=torch.bfloat16) + temb = torch.rand([1, 3072], dtype=torch.bfloat16) image_rotary_emb = torch.rand( [1, 1, height * width // 256 + max_sequence_length, 64, 2, 2], - dtype=DTYPE) + dtype=torch.bfloat16) sample_inputs = hidden_states, encoder_hidden_states, \ temb, image_rotary_emb @@ -146,11 +139,11 @@ def trace_transformer(height, width, max_sequence_length): hidden_states = torch.rand( [1, height * width // 256 + max_sequence_length, 3072], - dtype=DTYPE) - temb = torch.rand([1, 3072], dtype=DTYPE) + dtype=torch.bfloat16) + temb = torch.rand([1, 3072], dtype=torch.bfloat16) image_rotary_emb = torch.rand( [1, 1, height * width // 256 + max_sequence_length, 64, 2, 2], - dtype=DTYPE) + dtype=torch.bfloat16) sample_inputs = hidden_states, temb, image_rotary_emb model = neuronx_distributed.trace.parallel_model_trace( @@ -172,10 +165,10 @@ def trace_transformer(height, width, max_sequence_length): hidden_states = torch.rand( [1, height * width // 256 + max_sequence_length, 3072], - dtype=DTYPE) + dtype=torch.bfloat16) encoder_hidden_states = torch.rand([1, max_sequence_length, 3072], - dtype=DTYPE) - temb = torch.rand([1, 3072], dtype=DTYPE) + dtype=torch.bfloat16) + temb = torch.rand([1, 3072], dtype=torch.bfloat16) sample_inputs = hidden_states, encoder_hidden_states, temb model = neuronx_distributed.trace.parallel_model_trace( @@ -202,21 +195,21 @@ def trace_transformer(height, width, max_sequence_length): "-hh", "--height", type=int, - default=256, + default=1024, help="height of images to be generated by compilation of this model" ) parser.add_argument( "-w", "--width", type=int, - default=256, + default=1024, help="width of images to be generated by compilation of this model" ) parser.add_argument( "-m", "--max_sequence_length", type=int, - default=32, + default=512, help="maximum sequence length for the text embeddings" ) args = parser.parse_args() diff --git a/flux_serve/app/src/transformer/model.py b/flux_serve/app/src/transformer/model.py index ce9f306..3689de4 100644 --- a/flux_serve/app/src/transformer/model.py +++ b/flux_serve/app/src/transformer/model.py @@ -8,23 +8,8 @@ from neuronx_distributed.parallel_layers.layers \ import ColumnParallelLinear, RowParallelLinear -from diffusers.models.attention_processor import AttnProcessor - DTYPE=torch.bfloat16 -class MyAttentionProcessor(AttnProcessor): - def __call__(self, attn, hidden_states,encoder_hidden_states=None,cross_attention_kwargs=None,**kwargs): - if hidden_states is not None: - n_heads = 24 - head_dim = 128 - batch, seq_len, dim = hidden_states.shape - assert dim == n_heads * head_dim, f"Dim mismatch: got {dim}, expected {n_heads*head_dim}" - - hidden_states = hidden_states.view(batch, seq_len, n_heads, head_dim) - hidden_states = attn.norm_q(hidden_states) - hidden_states = hidden_states.view(batch, seq_len, dim) - return hidden_states, encoder_hidden_states - class TracingTransformerEmbedderWrapper(nn.Module): def __init__( self, @@ -141,15 +126,17 @@ def forward( norm_hidden_states, gate = self.norm(hidden_states, emb=temb) mlp_hidden_states = self.act_mlp(self.proj_mlp(norm_hidden_states)) - #attn_output = self.attn(hidden_states=norm_hidden_states,image_rotary_emb=image_rotary_emb,) - attn_output, cross_output = self.attn(hidden_states=norm_hidden_states, image_rotary_emb=image_rotary_emb) + attn_output = self.attn( + hidden_states=norm_hidden_states, + image_rotary_emb=image_rotary_emb, + ) gate = gate.unsqueeze(1) hidden_states = gate * (self.proj_out(attn_output) + self.proj_out_2(mlp_hidden_states)) hidden_states = residual + hidden_states if hidden_states.dtype == torch.float16: hidden_states = hidden_states.clip(-65504, 65504) - out = self.proj_mlp(norm_hidden_states) + return hidden_states @@ -160,12 +147,12 @@ def get_sharded_data(data, dim): if dim == 0: return data[ per_partition_size * tp_rank: per_partition_size * (tp_rank + 1) - ].clone().to(DTYPE) + ].clone().to(torch.bfloat16) elif dim == 1: return data[:, per_partition_size * tp_rank: per_partition_size * (tp_rank + 1) - ].clone().to(DTYPE) + ].clone().to(torch.bfloat16) else: raise Exception( f"Partiton value of 0,1 are supported, found {dim}." @@ -173,14 +160,14 @@ def get_sharded_data(data, dim): def shard_attn(attn: Attention): - #attn.heads = 3 + attn.heads = 3 orig_q = attn.to_q attn.to_q = ColumnParallelLinear( attn.to_q.in_features, attn.to_q.out_features, bias=(attn.to_q.bias is not None), - gather_output=True) + gather_output=False) attn.to_q.weight.data = get_sharded_data(orig_q.weight.data, 0) if attn.to_q.bias is not None: attn.to_q.bias.data = get_sharded_data(orig_q.bias.data, 0) @@ -191,7 +178,7 @@ def shard_attn(attn: Attention): attn.to_k.in_features, attn.to_k.out_features, bias=(attn.to_k.bias is not None), - gather_output=True) + gather_output=False) attn.to_k.weight.data = get_sharded_data(orig_k.weight.data, 0) if attn.to_k.bias is not None: attn.to_k.bias.data = get_sharded_data(orig_k.bias.data, 0) @@ -202,7 +189,7 @@ def shard_attn(attn: Attention): attn.to_v.in_features, attn.to_v.out_features, bias=(attn.to_v.bias is not None), - gather_output=True) + gather_output=False) attn.to_v.weight.data = get_sharded_data(orig_v.weight.data, 0) if attn.to_v.bias is not None: attn.to_v.bias.data = get_sharded_data(orig_v.bias.data, 0) @@ -213,7 +200,7 @@ def shard_attn(attn: Attention): attn.add_q_proj.in_features, attn.add_q_proj.out_features, bias=(attn.add_q_proj.bias is not None), - gather_output=True) + gather_output=False) attn.add_q_proj.weight.data = get_sharded_data(orig_q_proj.weight.data, 0) if attn.add_q_proj.bias is not None: attn.add_q_proj.bias.data = get_sharded_data(orig_q_proj.bias.data, 0) @@ -224,7 +211,7 @@ def shard_attn(attn: Attention): attn.add_k_proj.in_features, attn.add_k_proj.out_features, bias=(attn.add_k_proj.bias is not None), - gather_output=True) + gather_output=False) attn.add_k_proj.weight.data = get_sharded_data(orig_k_proj.weight.data, 0) if attn.add_k_proj.bias is not None: attn.add_k_proj.bias.data = get_sharded_data(orig_k_proj.bias.data, 0) @@ -235,7 +222,7 @@ def shard_attn(attn: Attention): attn.add_v_proj.in_features, attn.add_v_proj.out_features, bias=(attn.add_v_proj.bias is not None), - gather_output=True) + gather_output=False) attn.add_v_proj.weight.data = get_sharded_data(orig_v_proj.weight.data, 0) if attn.add_v_proj.bias is not None: attn.add_v_proj.bias.data = get_sharded_data(orig_v_proj.bias.data, 0) @@ -246,7 +233,7 @@ def shard_attn(attn: Attention): attn.to_out[0].in_features, attn.to_out[0].out_features, bias=(attn.to_out[0].bias is not None), - input_is_parallel=False) + input_is_parallel=True) attn.to_out[0].weight.data = get_sharded_data(orig_out.weight.data, 1) if attn.to_out[0].bias is not None: attn.to_out[0].bias.data = orig_out.bias.data.detach() @@ -257,25 +244,24 @@ def shard_attn(attn: Attention): attn.to_add_out.in_features, attn.to_add_out.out_features, bias=(attn.to_add_out.bias is not None), - input_is_parallel=False) + input_is_parallel=True) attn.to_add_out.weight.data = get_sharded_data(orig_out.weight.data, 1) if attn.to_add_out.bias is not None: attn.to_add_out.bias.data = orig_out.bias.data.detach() del (orig_out) - return attn def shard_attn_lite(block): attn = block.attn - #attn.heads = 3 + attn.heads = 3 orig_q = attn.to_q attn.to_q = ColumnParallelLinear( attn.to_q.in_features, attn.to_q.out_features, bias=(attn.to_q.bias is not None), - gather_output=True) + gather_output=False) attn.to_q.weight.data = get_sharded_data(orig_q.weight.data, 0) if attn.to_q.bias is not None: attn.to_q.bias.data = get_sharded_data(orig_q.bias.data, 0) @@ -286,7 +272,7 @@ def shard_attn_lite(block): attn.to_k.in_features, attn.to_k.out_features, bias=(attn.to_k.bias is not None), - gather_output=True) + gather_output=False) attn.to_k.weight.data = get_sharded_data(orig_k.weight.data, 0) if attn.to_k.bias is not None: attn.to_k.bias.data = get_sharded_data(orig_k.bias.data, 0) @@ -297,7 +283,7 @@ def shard_attn_lite(block): attn.to_v.in_features, attn.to_v.out_features, bias=(attn.to_v.bias is not None), - gather_output=True) + gather_output=False) attn.to_v.weight.data = get_sharded_data(orig_v.weight.data, 0) if attn.to_v.bias is not None: attn.to_v.bias.data = get_sharded_data(orig_v.bias.data, 0) diff --git a/flux_serve/specs/compile-flux-1024x576.yaml b/flux_serve/specs/compile-flux-1024x576.yaml index 2e2f6bc..600cf59 100644 --- a/flux_serve/specs/compile-flux-1024x576.yaml +++ b/flux_serve/specs/compile-flux-1024x576.yaml @@ -29,19 +29,25 @@ spec: ./compile.sh cp -r * /model/1024x576 python /benchmark-flux.py - while true; do sleep 3600; done + #while true; do sleep 3600; done resources: limits: aws.amazon.com/neuron: 8 requests: aws.amazon.com/neuron: 8 env: + - name: NODEPOOL + value: "amd-neuron-trn1" - name: COMPILER_WORKDIR_ROOT value: "/model/1024x576" - name: HEIGHT value: "1024" - name: WIDTH value: "576" + - name: MAX_SEQ_LEN + value: "32" + - name: GUIDANCE_SCALE + value: "3.5" - name: MODEL_ID value: "black-forest-labs/FLUX.1-dev" - name: HUGGINGFACE_TOKEN From 9745f23d97b32594cbf1ef79e310128b200a263b Mon Sep 17 00:00:00 2001 From: Yahav Date: Sun, 5 Jan 2025 10:34:14 -0800 Subject: [PATCH 23/45] model-warm-up-with-benchmark --- flux_serve/app/flux_model_api.py | 61 +++++++++++++++++++++++++++++++- 1 file changed, 60 insertions(+), 1 deletion(-) diff --git a/flux_serve/app/flux_model_api.py b/flux_serve/app/flux_model_api.py index cf0604d..2bf6d3f 100644 --- a/flux_serve/app/flux_model_api.py +++ b/flux_serve/app/flux_model_api.py @@ -211,7 +211,60 @@ def __init__(self, dtype, encoder): def forward(self, emb, output_hidden_states): return torch.unsqueeze(self.encoder(emb)["last_hidden_state"], 1) - +def benchmark(n_runs, test_name, model, model_inputs): + if not isinstance(model_inputs, tuple): + model_inputs = model_inputs + + warmup_run = model(**model_inputs) + + latency_collector = LatencyCollector() + + for _ in range(n_runs): + latency_collector.pre_hook() + res = model(**model_inputs) + image=res.images[0] + #image.save(os.path.join("/tmp", "flux-dev.png")) + latency_collector.hook() + p0_latency_ms = latency_collector.percentile(0) * 1000 + p50_latency_ms = latency_collector.percentile(50) * 1000 + p90_latency_ms = latency_collector.percentile(90) * 1000 + p95_latency_ms = latency_collector.percentile(95) * 1000 + p99_latency_ms = latency_collector.percentile(99) * 1000 + p100_latency_ms = latency_collector.percentile(100) * 1000 + + report_dict = dict() + report_dict["Latency P0"] = f'{p0_latency_ms:.1f}' + report_dict["Latency P50"]=f'{p50_latency_ms:.1f}' + report_dict["Latency P90"]=f'{p90_latency_ms:.1f}' + report_dict["Latency P95"]=f'{p95_latency_ms:.1f}' + report_dict["Latency P99"]=f'{p99_latency_ms:.1f}' + report_dict["Latency P100"]=f'{p100_latency_ms:.1f}' + + report = f'RESULT FOR {test_name}:' + for key, value in report_dict.items(): + report += f' {key}={value}' + print(report) + return report + +class LatencyCollector: + def __init__(self): + self.start = None + self.latency_list = [] + + def pre_hook(self, *args): + self.start = time.time() + + def hook(self, *args): + self.latency_list.append(time.time() - self.start) + + def percentile(self, percent): + latency_list = self.latency_list + pos_float = len(latency_list) * percent / 100 + max_pos = len(latency_list) - 1 + pos_floor = min(math.floor(pos_float), max_pos) + pos_ceil = min(math.ceil(pos_float), max_pos) + latency_list = sorted(latency_list) + return latency_list[pos_ceil] if pos_float - pos_floor > 0.5 else latency_list[pos_floor] # Load the model pipeline def load_model(): @@ -239,6 +292,12 @@ def load_model(): return pipe model = load_model() +#Warmup +prompt= "A cat holding a sign that says hello world" +num_inference_steps=10 +model_inputs={'prompt':prompt,'height':height,'width':width,'max_sequence_length':max_sequence_length,'num_inference_steps': num_inference_steps,'guidance_scale':guidance_scale} +test_name=f"flux1-dev-50runs with dim {height}x{width} on {nodepool};num_inference_steps:{num_inference_steps}" +benchmark(50,test_name,model,model_inputs) # Define the image generation endpoint @app.post("/generate", response_model=GenerateImageResponse) From cf32b28830f040d279fbf6173d5bc2ec561a7e13 Mon Sep 17 00:00:00 2001 From: Yahav Date: Sun, 5 Jan 2025 15:28:40 -0800 Subject: [PATCH 24/45] flux_gradio.py --- flux_serve/app/flux_gradio.py | 84 ++++++++++++++++++++++++----------- 1 file changed, 59 insertions(+), 25 deletions(-) diff --git a/flux_serve/app/flux_gradio.py b/flux_serve/app/flux_gradio.py index 131ef9e..36696cb 100644 --- a/flux_serve/app/flux_gradio.py +++ b/flux_serve/app/flux_gradio.py @@ -80,7 +80,7 @@ def healthy(): @app.get("/readiness") def ready(): return {"message": "Service is ready"} - +''' with gr.Blocks() as interface: gr.Markdown(f"# {model_id} Image Generation App") gr.Markdown("Enter a prompt and specify the number of inference steps to generate images in different shapes.") @@ -116,28 +116,62 @@ def ready(): outputs=image_components + exec_time_components, api_name="generate_images" ) -app = gr.mount_gradio_app(app, interface, path="/serve") -''' -interface = gr.Interface( - fn=call_model_api, - inputs=[ - gr.Textbox(label="Prompt", lines=1, placeholder="Enter your prompt here..."), - gr.Number( - label="Inference Steps", - value=10, - precision=0, - info="Enter the number of inference steps; higher number takes more time but produces better image" - ) - ], - outputs=[ - gr.Image(label=f"Image from {models[0]['name']}", height=models[0]['height'], width=models[0]['width']), - gr.Textbox(label=f"Execution Time ({models[0]['name']})"), - gr.Image(label=f"Image from {models[1]['name']}", height=models[1]['height'], width=models[1]['width']), - gr.Textbox(label=f"Execution Time ({models[1]['name']})"), - gr.Image(label=f"Image from {models[2]['name']}", height=models[2]['height'], width=models[2]['width']), - gr.Textbox(label=f"Execution Time ({models[2]['name']})"), - ], - description="Enter a prompt and specify the number of inference steps to generate images using the model pipeline." -) -app = gr.mount_gradio_app(app,interface, path="/serve") ''' +with gr.Blocks() as interface: + gr.Markdown(f"# {model_id} Image Generation App") + gr.Markdown("Enter a prompt and specify the number of inference steps to generate images in different shapes.") + + with gr.Row(): + with gr.Column(scale=1): + prompt = gr.Textbox( + label="Prompt", + lines=1, + placeholder="Enter your prompt here...", + elem_id="prompt-box" + ) + inference_steps = gr.Number( + label="Inference Steps", + value=10, + precision=0, + info="Enter the number of inference steps; higher number takes more time but produces better image", + elem_id="steps-number" + ) + generate_button = gr.Button("Generate Images", variant="primary") + + with gr.Column(scale=2): + image_components = [] + exec_time_components = [] + + with gr.Row(): + for idx, model in enumerate(models): + with gr.Column(): + # Title + gr.Markdown(f"**{model['name']}**") + + # Scale down the image + preview_height = int(model['height'] / 2) + preview_width = int(model['width'] / 2) + + img = gr.Image( + label="", + height=preview_height, + width=preview_width, + interactive=False + ) + # Use Markdown for simpler smaller text + exec_time = gr.Markdown(value="") + + image_components.append(img) + exec_time_components.append(exec_time) + + # callback for the button + generate_button.click( + fn=call_model_api, + inputs=[prompt, inference_steps], + outputs=image_components + exec_time_components, + api_name="generate_images" + ) + +app = gr.mount_gradio_app(app, interface, path="/serve") + +app = gr.mount_gradio_app(app, interface, path="/serve") From 5c8dcca9a431214ff77facecd04d7838eeefa003 Mon Sep 17 00:00:00 2001 From: Yahav Date: Sun, 5 Jan 2025 17:14:38 -0800 Subject: [PATCH 25/45] sample-readme --- README.md | 1 + flux_serve/README.md | 15 ++- flux_serve/app/benchmark-flux.py | 2 +- .../specs/amd-neuron-inf2-nodepool.yaml | 51 ++++++++++ flux_serve/specs/compile-flux-1024x576.yaml | 2 +- flux_serve/specs/compile-flux-256x144.yaml | 64 +++++++++++++ flux_serve/specs/compile-flux-512x512.yaml | 64 +++++++++++++ .../specs/flux-neuron-1024x576-model-api.yaml | 93 +++++++++++++++++++ .../specs/flux-neuron-256x144-model-api.yaml | 93 +++++++++++++++++++ .../specs/flux-neuron-512x512-model-api.yaml | 93 +++++++++++++++++++ flux_serve/specs/flux-sa.yaml | 7 ++ flux_serve/specs/load.yaml | 31 +++++++ 12 files changed, 505 insertions(+), 11 deletions(-) create mode 100644 flux_serve/specs/amd-neuron-inf2-nodepool.yaml create mode 100644 flux_serve/specs/compile-flux-256x144.yaml create mode 100644 flux_serve/specs/compile-flux-512x512.yaml create mode 100644 flux_serve/specs/flux-neuron-1024x576-model-api.yaml create mode 100644 flux_serve/specs/flux-neuron-256x144-model-api.yaml create mode 100644 flux_serve/specs/flux-neuron-512x512-model-api.yaml create mode 100644 flux_serve/specs/flux-sa.yaml create mode 100644 flux_serve/specs/load.yaml diff --git a/README.md b/README.md index 8ded88a..3eb23d9 100644 --- a/README.md +++ b/README.md @@ -19,6 +19,7 @@ Samples are organized by use case below: | Link | Description | Instance Type | | --- | --- | --- | | [SD inference](sd_hf_serve) | SD Inference workflow for creating an inference endpoint forwarded by ALB LoadBalancer powered by Karpenter's NodePool | Inf2 | +| [Flux inference](flux_serve) | FLUX.1 dev Inference workflow for creating an inference endpoint forwarded by ALB LoadBalancer powered by Karpenter's NodePool and S3 mountpoints | Trn1/Inf2 | ## Getting Help diff --git a/flux_serve/README.md b/flux_serve/README.md index 398ec86..f7816a5 100644 --- a/flux_serve/README.md +++ b/flux_serve/README.md @@ -1,16 +1,14 @@ # Compile and serve ultra large vision transformers like Flux on Neuron devices at scale -challenges in deploying large models for serving: -1/large model graph traces load - caching S3 buckets on EKS nodes with CSI drivers -https://docs.aws.amazon.com/eks/latest/userguide/s3-csi.html +[FLUX.1 dev](https://huggingface.co/black-forest-labs/FLUX.1-dev) is a 12 billion parameter rectified flow transformer capable of generating images from text. This example illustrates how to optimize its usage on Neuron devices that power EC2 Inferentia (Inf2) and Trainium (Trn1) instances deployed on EKS. Since the FLUX.1 dev model cannot fit on a single Neuron device, neuronx_distributed splits the model transformer into `N=8` chunks along a dimension. This ensures that each device holds only `1/N` chunk of the tensor. By performing partial chunk computation, the model generates partial outputs from all devices, maintaining accuracy and producing high-quality images. However, loading the traced model graph before serving significantly impacts the model loading time. This depends on the `tp_degree`, `N`, and the produced model graph traces `*.pt` need to be loaded during deployment and integrated into the OCI image, which can lead to prolonged load times. To address this, we cache the model traces (in the range of 10 GB) in [S3 Mountpoints](https://docs.aws.amazon.com/eks/latest/userguide/s3-csi.html), decoupling the OCI model load time from the model traces load time. -Using DLCs to simplify OCI image build - easy to streamline with automation +Next, we determine the compute type we intend to use. The initial step involves loading the model, executing a single inference, and assessing the image quality based on the number of inference steps. Subsequently, we determine the minimum inference latency with `Trn1` and `Inf2` under the specified acceptable quality parameters, currently set to `num_inference_steps`. Finally, we load each deployment unit, such as Flux on Trn1 8 Neuron devices or Flux on Inf2 6 Neuron devices, until it reaches its breaking point where the latency exceeds the acceptable thresholds. -https://awsdocs-neuron.readthedocs-hosted.com/en/latest/general/monitoring-tools.html#monitoring-tools are availible out of the box with container insights +The rest of this post offers a code sample walkthrough that explains the optimization strategies we adopted to streamline the deployment process using S3 CSI Driver and [Deep Learning Containers](https://github.com/aws/deep-learning-containers/blob/master/available_images.md). These strategies aim to reduce the cost of inference while enhancing model serving throughput. + + +TBD - https://awsdocs-neuron.readthedocs-hosted.com/en/latest/general/monitoring-tools.html#monitoring-tools are availible out of the box with container insights -cost effectiveness requires to allocate the minimal required cores. The device plugin and myscheduler through Helm simplify deployment -https://awsdocs-neuron.readthedocs-hosted.com/en/latest/containers/kubernetes-getting-started.html -Neuron device plugin, Neuron scheduler extension, Neuron scheduler ## Walkthrough * [Create cluster with Karpenter node pools that provisions `trn1` instances](https://karpenter.sh/docs/getting-started/getting-started-with-karpenter/) @@ -57,7 +55,6 @@ kubectl apply -f specs/compile-flux-256x144.yaml kubectl apply -f specs/compile-flux-512x512.yaml ``` Note the three pending Jobs that Karpenter seeks to fulfill. Current setup requires `aws.amazon.com/neuron: 8` which is half od `trn1.32xlarge` so expect two `trn1.xlarge` to be launched. - * Deploy the Flux serving backend that loads the model from HuggingFace and uses the preloaded neuron model graph from S3 and standby for inference requests. The backend includes Deployment Pods and Services that route inference requests to the Pods so each model-api shapes scales horizontly. ```bash kubectl apply -f specs/flux-neuron-1024x576-model-api.yaml diff --git a/flux_serve/app/benchmark-flux.py b/flux_serve/app/benchmark-flux.py index 9dcda93..6be481f 100644 --- a/flux_serve/app/benchmark-flux.py +++ b/flux_serve/app/benchmark-flux.py @@ -22,7 +22,7 @@ guidance_scale=float(os.environ['GUIDANCE_SCALE']) prompt= "A cat holding a sign that says hello world" -num_inference_steps=20 +num_inference_steps=10 hf_token=os.environ['HUGGINGFACE_TOKEN'].strip() try: diff --git a/flux_serve/specs/amd-neuron-inf2-nodepool.yaml b/flux_serve/specs/amd-neuron-inf2-nodepool.yaml new file mode 100644 index 0000000..840259f --- /dev/null +++ b/flux_serve/specs/amd-neuron-inf2-nodepool.yaml @@ -0,0 +1,51 @@ +apiVersion: karpenter.sh/v1 +kind: NodePool +metadata: + name: amd-neuron-inf2 +spec: + template: + spec: + requirements: + - key: kubernetes.io/arch + operator: In + values: ["amd64"] + - key: karpenter.k8s.aws/instance-family + operator: In + values: ["inf2"] + - key: karpenter.sh/capacity-type + operator: In + values: ["on-demand"] + nodeClassRef: + group: karpenter.k8s.aws + kind: EC2NodeClass + name: amd-neuron + expireAfter: 720h # 30 * 24h = 720h + limits: + cpu: 1000 + disruption: + consolidationPolicy: WhenEmptyOrUnderutilized + consolidateAfter: 10m +--- +apiVersion: karpenter.k8s.aws/v1 +kind: EC2NodeClass +metadata: + name: amd-neuron +spec: + amiFamily: AL2 # Amazon Linux 2 + amiSelectorTerms: + - id: "ami-0e73cfd34ee52b6a6" + - id: "ami-077b8064c2a1a3186" + - id: "ami-057dddc807f3f6644" + role: "KarpenterNodeRole-flux-usw2" + subnetSelectorTerms: + - tags: + karpenter.sh/discovery: "flux-usw2" + securityGroupSelectorTerms: + - tags: + karpenter.sh/discovery: "flux-usw2" + blockDeviceMappings: + - deviceName: /dev/xvda + ebs: + volumeSize: 900Gi + volumeType: gp3 + encrypted: true diff --git a/flux_serve/specs/compile-flux-1024x576.yaml b/flux_serve/specs/compile-flux-1024x576.yaml index 600cf59..1055b01 100644 --- a/flux_serve/specs/compile-flux-1024x576.yaml +++ b/flux_serve/specs/compile-flux-1024x576.yaml @@ -29,7 +29,7 @@ spec: ./compile.sh cp -r * /model/1024x576 python /benchmark-flux.py - #while true; do sleep 3600; done + while true; do sleep 3600; done resources: limits: aws.amazon.com/neuron: 8 diff --git a/flux_serve/specs/compile-flux-256x144.yaml b/flux_serve/specs/compile-flux-256x144.yaml new file mode 100644 index 0000000..aff6374 --- /dev/null +++ b/flux_serve/specs/compile-flux-256x144.yaml @@ -0,0 +1,64 @@ +apiVersion: batch/v1 +kind: Job +metadata: + name: compile-256x144 +spec: + template: + spec: + restartPolicy: OnFailure + nodeSelector: + karpenter.sh/nodepool: amd-neuron-trn1 + #serviceAccountName: appsimulator + schedulerName: my-scheduler + containers: + - name: app + image: 920372998901.dkr.ecr.us-west-2.amazonaws.com/model:amd64-neuron + imagePullPolicy: Always + volumeMounts: + - name: dshm + mountPath: /dev/shm + - name: s3-flux-pvc + mountPath: /model + command: + - /bin/bash + - "-exc" + - | + set -x + mkdir -p /model/256x144 + cd /src + ./compile.sh + cp -r * /model/256x144 + python /benchmark-flux.py + while true; do sleep 3600; done + resources: + limits: + aws.amazon.com/neuron: 8 + requests: + aws.amazon.com/neuron: 8 + env: + - name: NODEPOOL + value: "amd-neuron-trn1" + - name: COMPILER_WORKDIR_ROOT + value: "/model/256x144" + - name: HEIGHT + value: "256" + - name: WIDTH + value: "144" + - name: MAX_SEQ_LEN + value: "32" + - name: GUIDANCE_SCALE + value: "3.5" + - name: MODEL_ID + value: "black-forest-labs/FLUX.1-dev" + - name: HUGGINGFACE_TOKEN + valueFrom: + secretKeyRef: + name: hf-secrets + key: HUGGINGFACE_TOKEN + volumes: + - name: dshm + emptyDir: + medium: Memory + - name: s3-flux-pvc + persistentVolumeClaim: + claimName: s3-flux-pvc diff --git a/flux_serve/specs/compile-flux-512x512.yaml b/flux_serve/specs/compile-flux-512x512.yaml new file mode 100644 index 0000000..29c8220 --- /dev/null +++ b/flux_serve/specs/compile-flux-512x512.yaml @@ -0,0 +1,64 @@ +apiVersion: batch/v1 +kind: Job +metadata: + name: compile-512x512 +spec: + template: + spec: + restartPolicy: OnFailure + nodeSelector: + karpenter.sh/nodepool: amd-neuron-trn1 + #serviceAccountName: appsimulator + schedulerName: my-scheduler + containers: + - name: app + image: 920372998901.dkr.ecr.us-west-2.amazonaws.com/model:amd64-neuron + imagePullPolicy: Always + volumeMounts: + - name: dshm + mountPath: /dev/shm + - name: s3-flux-pvc + mountPath: /model + command: + - /bin/bash + - "-exc" + - | + set -x + #mkdir -p /model/512x512 + #cd /src + #./compile.sh + #cp -r * /model/512x512 + #python /benchmark-flux.py + while true; do sleep 3600; done + resources: + limits: + aws.amazon.com/neuron: 6 + requests: + aws.amazon.com/neuron: 6 + env: + - name: NODEPOOL + value: "amd-neuron-trn1" + - name: COMPILER_WORKDIR_ROOT + value: "/model/512x512" + - name: HEIGHT + value: "512" + - name: WIDTH + value: "512" + - name: MAX_SEQ_LEN + value: "32" + - name: GUIDANCE_SCALE + value: "3.5" + - name: MODEL_ID + value: "black-forest-labs/FLUX.1-dev" + - name: HUGGINGFACE_TOKEN + valueFrom: + secretKeyRef: + name: hf-secrets + key: HUGGINGFACE_TOKEN + volumes: + - name: dshm + emptyDir: + medium: Memory + - name: s3-flux-pvc + persistentVolumeClaim: + claimName: s3-flux-pvc diff --git a/flux_serve/specs/flux-neuron-1024x576-model-api.yaml b/flux_serve/specs/flux-neuron-1024x576-model-api.yaml new file mode 100644 index 0000000..9ae6c4b --- /dev/null +++ b/flux_serve/specs/flux-neuron-1024x576-model-api.yaml @@ -0,0 +1,93 @@ +apiVersion: v1 +kind: Service +metadata: + name: flux-neuron-1024x576-model-api +spec: + selector: + app: flux-neuron-1024x576-model-api + ports: + - protocol: TCP + port: 8000 + targetPort: 8000 + type: ClusterIP +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + labels: + app: flux-neuron-1024x576-model-api + name: flux-neuron-1024x576-model-api +spec: + selector: + matchLabels: + app: flux-neuron-1024x576-model-api + template: + metadata: + labels: + app: flux-neuron-1024x576-model-api + spec: + nodeSelector: + karpenter.sh/nodepool: amd-neuron-inf2 + serviceAccountName: flux-serviceaccount + schedulerName: my-scheduler + containers: + - name: app + image: 920372998901.dkr.ecr.us-west-2.amazonaws.com/model:amd64-neuron + imagePullPolicy: Always + volumeMounts: + - name: dshm + mountPath: /dev/shm + - name: s3-flux-pvc + mountPath: /model + command: ["sh", "-c", "uvicorn flux_model_api:app --host=0.0.0.0"] + resources: + requests: + aws.amazon.com/neuron: 6 + limits: + aws.amazon.com/neuron: 6 + ports: + - containerPort: 8000 + protocol: TCP + readinessProbe: + httpGet: + path: /readiness + port: 8000 + initialDelaySeconds: 60 + periodSeconds: 10 + env: + - name: APP + value: "flux1.1-dev-1024x576-inf2" + - name: NODEPOOL + value: "amd-neuron-inf2" + - name: DEVICE + value: "xla" + - name: MODEL_ID + value: "black-forest-labs/FLUX.1-dev" + - name: COMPILER_WORKDIR_ROOT + value: "/model/1024x576" + - name: HEIGHT + value: "1024" + - name: WIDTH + value: "576" + - name: MAX_SEQ_LEN + value: "32" + - name: GUIDANCE_SCALE + value: "3.5" + - name: HUGGINGFACE_TOKEN + valueFrom: + secretKeyRef: + name: hf-secrets + key: HUGGINGFACE_TOKEN + - name: POD_NAME + valueFrom: + fieldRef: + fieldPath: metadata.name + volumes: + - name: workdir + emptyDir: {} + - name: dshm + emptyDir: + medium: Memory + - name: s3-flux-pvc + persistentVolumeClaim: + claimName: s3-flux-pvc diff --git a/flux_serve/specs/flux-neuron-256x144-model-api.yaml b/flux_serve/specs/flux-neuron-256x144-model-api.yaml new file mode 100644 index 0000000..1f80515 --- /dev/null +++ b/flux_serve/specs/flux-neuron-256x144-model-api.yaml @@ -0,0 +1,93 @@ +apiVersion: v1 +kind: Service +metadata: + name: flux-neuron-256x144-model-api +spec: + selector: + app: flux-neuron-256x144-model-api + ports: + - protocol: TCP + port: 8000 + targetPort: 8000 + type: ClusterIP +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + labels: + app: flux-neuron-256x144-model-api + name: flux-neuron-256x144-model-api +spec: + selector: + matchLabels: + app: flux-neuron-256x144-model-api + template: + metadata: + labels: + app: flux-neuron-256x144-model-api + spec: + nodeSelector: + karpenter.sh/nodepool: amd-neuron-inf2 + serviceAccountName: flux-serviceaccount + schedulerName: my-scheduler + containers: + - name: app + image: 920372998901.dkr.ecr.us-west-2.amazonaws.com/model:amd64-neuron + imagePullPolicy: Always + volumeMounts: + - name: dshm + mountPath: /dev/shm + - name: s3-flux-pvc + mountPath: /model + command: ["sh", "-c", "uvicorn flux_model_api:app --host=0.0.0.0"] + resources: + requests: + aws.amazon.com/neuron: 6 + limits: + aws.amazon.com/neuron: 6 + ports: + - containerPort: 8000 + protocol: TCP + readinessProbe: + httpGet: + path: /readiness + port: 8000 + initialDelaySeconds: 60 + periodSeconds: 10 + env: + - name: APP + value: "flux1.1-dev-256x144-inf2" + - name: NODEPOOL + value: "amd-neuron-inf2" + - name: DEVICE + value: "xla" + - name: MODEL_ID + value: "black-forest-labs/FLUX.1-dev" + - name: COMPILER_WORKDIR_ROOT + value: "/model/256x144" + - name: HEIGHT + value: "256" + - name: WIDTH + value: "144" + - name: MAX_SEQ_LEN + value: "32" + - name: GUIDANCE_SCALE + value: "3.5" + - name: HUGGINGFACE_TOKEN + valueFrom: + secretKeyRef: + name: hf-secrets + key: HUGGINGFACE_TOKEN + - name: POD_NAME + valueFrom: + fieldRef: + fieldPath: metadata.name + volumes: + - name: workdir + emptyDir: {} + - name: dshm + emptyDir: + medium: Memory + - name: s3-flux-pvc + persistentVolumeClaim: + claimName: s3-flux-pvc diff --git a/flux_serve/specs/flux-neuron-512x512-model-api.yaml b/flux_serve/specs/flux-neuron-512x512-model-api.yaml new file mode 100644 index 0000000..ed2935e --- /dev/null +++ b/flux_serve/specs/flux-neuron-512x512-model-api.yaml @@ -0,0 +1,93 @@ +apiVersion: v1 +kind: Service +metadata: + name: flux-neuron-512x512-model-api +spec: + selector: + app: flux-neuron-512x512-model-api + ports: + - protocol: TCP + port: 8000 + targetPort: 8000 + type: ClusterIP +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + labels: + app: flux-neuron-512x512-model-api + name: flux-neuron-512x512-model-api +spec: + selector: + matchLabels: + app: flux-neuron-512x512-model-api + template: + metadata: + labels: + app: flux-neuron-512x512-model-api + spec: + nodeSelector: + karpenter.sh/nodepool: amd-neuron-inf2 + serviceAccountName: flux-serviceaccount + schedulerName: my-scheduler + containers: + - name: app + image: 920372998901.dkr.ecr.us-west-2.amazonaws.com/model:amd64-neuron + imagePullPolicy: Always + volumeMounts: + - name: dshm + mountPath: /dev/shm + - name: s3-flux-pvc + mountPath: /model + command: ["sh", "-c", "uvicorn flux_model_api:app --host=0.0.0.0"] + resources: + requests: + aws.amazon.com/neuron: 6 + limits: + aws.amazon.com/neuron: 6 + ports: + - containerPort: 8000 + protocol: TCP + readinessProbe: + httpGet: + path: /readiness + port: 8000 + initialDelaySeconds: 60 + periodSeconds: 10 + env: + - name: APP + value: "flux1.1-dev-512x512-inf2" + - name: NODEPOOL + value: "amd-neuron-inf2" + - name: DEVICE + value: "xla" + - name: MODEL_ID + value: "black-forest-labs/FLUX.1-dev" + - name: COMPILER_WORKDIR_ROOT + value: "/model/512x512" + - name: HEIGHT + value: "512" + - name: WIDTH + value: "512" + - name: MAX_SEQ_LEN + value: "32" + - name: GUIDANCE_SCALE + value: "3.5" + - name: HUGGINGFACE_TOKEN + valueFrom: + secretKeyRef: + name: hf-secrets + key: HUGGINGFACE_TOKEN + - name: POD_NAME + valueFrom: + fieldRef: + fieldPath: metadata.name + volumes: + - name: workdir + emptyDir: {} + - name: dshm + emptyDir: + medium: Memory + - name: s3-flux-pvc + persistentVolumeClaim: + claimName: s3-flux-pvc diff --git a/flux_serve/specs/flux-sa.yaml b/flux_serve/specs/flux-sa.yaml new file mode 100644 index 0000000..9f711b9 --- /dev/null +++ b/flux_serve/specs/flux-sa.yaml @@ -0,0 +1,7 @@ +apiVersion: v1 +kind: ServiceAccount +metadata: + name: flux-serviceaccount + namespace: default + annotations: + eks.amazonaws.com/role-arn: arn:aws:iam::920372998901:role/KarpenterNodeRole-flux-usw2 diff --git a/flux_serve/specs/load.yaml b/flux_serve/specs/load.yaml new file mode 100644 index 0000000..ae8463b --- /dev/null +++ b/flux_serve/specs/load.yaml @@ -0,0 +1,31 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + labels: + app: load + name: load +spec: + selector: + matchLabels: + app: load + template: + metadata: + labels: + app: load + spec: + nodeSelector: + alpha.eksctl.io/nodegroup-name: flux-usw2-ng + containers: + - name: load + image: public.ecr.aws/docker/library/python + imagePullPolicy: Always + command: + - /bin/bash + - -c + - -x + - | + SLEEP_TIME=10 + while true; do + curl -X POST -H "Content-Type: application/json" -d '{"prompt": "A majestic mountainscape in a surreal style","num_inference_steps": 10}' http://$FLUX_NEURON_256X144_MODEL_API_SERVICE_HOST:8000/generate + sleep $SLEEP_TIME + done From eb41df8f32e0d3a076161096222634777d194f35 Mon Sep 17 00:00:00 2001 From: Yahav Date: Sun, 5 Jan 2025 17:55:46 -0800 Subject: [PATCH 26/45] README --- flux_serve/README.md | 24 +++++++++++++++++++++-- flux_serve/figures/flux-quality-test.png | Bin 0 -> 738241 bytes 2 files changed, 22 insertions(+), 2 deletions(-) create mode 100644 flux_serve/figures/flux-quality-test.png diff --git a/flux_serve/README.md b/flux_serve/README.md index f7816a5..4a8a6ce 100644 --- a/flux_serve/README.md +++ b/flux_serve/README.md @@ -54,14 +54,14 @@ kubectl apply -f specs/compile-flux-1024x576.yaml kubectl apply -f specs/compile-flux-256x144.yaml kubectl apply -f specs/compile-flux-512x512.yaml ``` -Note the three pending Jobs that Karpenter seeks to fulfill. Current setup requires `aws.amazon.com/neuron: 8` which is half od `trn1.32xlarge` so expect two `trn1.xlarge` to be launched. +Note the three pending Jobs that Karpenter seeks to fulfill. Current setup requires `aws.amazon.com/neuron: 8` which is half of `trn1.32xlarge` so expect two `trn1.xlarge` to be launched. * Deploy the Flux serving backend that loads the model from HuggingFace and uses the preloaded neuron model graph from S3 and standby for inference requests. The backend includes Deployment Pods and Services that route inference requests to the Pods so each model-api shapes scales horizontly. ```bash kubectl apply -f specs/flux-neuron-1024x576-model-api.yaml kubectl apply -f specs/flux-neuron-256x144-model-api.yaml kubectl apply -f specs/flux-neuron-512x512-model-api.yaml ``` -Note the three pending Deployment Pods that Karpenter seeks to fulfill. Current setup requires `aws.amazon.com/neuron: 8` which is half od `trn1.32xlarge` so expect two `trn1.xlarge` to be launched. +Note the three pending Deployment Pods that Karpenter seeks to fulfill. Current setup requires either `aws.amazon.com/neuron: 8` which is half od `trn1.32xlarge` or `aws.amazon.com/neuron: 6` which is a full `inf2.24xlarge` instance. * Deploy the Flux serving frontend that includes Gradio app. ```bash @@ -76,4 +76,24 @@ flux-neuron alb * flux-neuron-658286526.us-west-2.elb.amazonaws.com ``` Use [flux-neuron-658286526.us-west-2.elb.amazonaws.com/serve/](flux-neuron-658286526.us-west-2.elb.amazonaws.com/serve/) +![Figure 1-Quality tests](./figures/flux-quality-test.png) +*Figure 1-Quality tests after deploying the model on Inf2 instances (Similar results were shown on Trn1 instances)* +We benchmarked the Flux serving latency on Trn1 and Inf2 by configuring the `nodeSelector` with the [Trn1 Karpenter nodepool](./specs/amd-neuron-trn1-nodepool.yaml) and the [Inf2 Karpenter nodepool](./specs/amd-neuron-inf2-nodepool.yaml) and launched the benchmark script [./app/benchmark-flux.py](./app/benchmark-flux.py) that is already executed post [compile job](./specs/compile-flux-256x144.yaml). Below are the results pulled by `kubectl logs ...`: +``` +RESULT FOR flux1-dev-50runs with dim 1024x576 on amd-neuron-trn1;num_inference_steps:10: Latency P0=3118.2 Latency P50=3129.3 Latency P90=3141.3 Latency P95=3147.2 Latency P99=3162.2 Latency P100=3162.2 + +RESULT FOR flux1-dev-50runs with dim 256x144 on amd-neuron-trn1;num_inference_steps:10: Latency P0=585.6 Latency P50=588.1 Latency P90=592.2 Latency P95=592.5 Latency P99=597.8 Latency P100=597.8 + +RESULT FOR flux1-dev-50runs with dim 1024x576 on amd-neuron-inf2;num_inference_steps:10: Latency P0=9040.2 Latency P50=9080.8 Latency P90=9115.6 Latency P95=9120.6 Latency P99=9123.7 Latency P100=9123.7 + +RESULT FOR flux1-dev-50runs with dim 256x144 on amd-neuron-inf2;num_inference_steps:10: Latency P0=3067.9 Latency P50=3075.7 Latency P90=3079.8 Latency P95=3081.2 Latency P99=3088.5 Latency P100=3088.5 +``` + +| **Dimension** | **Platform** | **Latency P0** | **Latency P50** | **Latency P90** | **Latency P95** | **Latency P99** | **Latency P100** | +|---------------|-------------:|---------------:|---------------:|---------------:|---------------:|---------------:|----------------:| +| 1024x576 | Trn1 | 3118.2 | 3129.3 | 3141.3 | 3147.2 | 3162.2 | 3162.2 | +| 256x144 | Trn1 | 585.6 | 588.1 | 592.2 | 592.5 | 597.8 | 597.8 | +| 1024x576 | Inf2 | 9040.2 | 9080.8 | 9115.6 | 9120.6 | 9123.7 | 9123.7 | +| 256x144 | Inf2 | 3067.9 | 3075.7 | 3079.8 | 3081.2 | 3088.5 | 3088.5 | +*Table 1-Latency benchmark between 8 Trn1 NDs and 6 Inf2 NDs with 10 inference_steps for 50 iterations* diff --git a/flux_serve/figures/flux-quality-test.png b/flux_serve/figures/flux-quality-test.png new file mode 100644 index 0000000000000000000000000000000000000000..a40ce49eadd2a1b887075c63e16063507e75113b GIT binary patch literal 738241 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 y1fxzxco=p9KFG?UuL7Yhh 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π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�F;0p>RQ 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

Nrq{L_08hiEt;!caC}1k8#o6;m!y+d5Z$Z+VQS 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 #0fERA1{^K&$P&0Zx?&* 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

7GOrY%v65`rBeCl`bXz((yXs?+fAHV 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

6^ZE}WY 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

201X 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%0A%vyS6m1 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

@`^FJyLq>4Q%kg^MmcnBPY0 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ï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�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 X8i@~&SG3;){umqGyj*+<7XE(#Yu6#- literal 0 HcmV?d00001 From 43ad24aa3e8f3c3fe62cc4780c577f9299e26aa1 Mon Sep 17 00:00:00 2001 From: Yahav Date: Sun, 5 Jan 2025 17:56:40 -0800 Subject: [PATCH 27/45] README --- flux_serve/README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/flux_serve/README.md b/flux_serve/README.md index 4a8a6ce..39bb351 100644 --- a/flux_serve/README.md +++ b/flux_serve/README.md @@ -96,4 +96,5 @@ RESULT FOR flux1-dev-50runs with dim 256x144 on amd-neuron-inf2;num_inference_st | 256x144 | Trn1 | 585.6 | 588.1 | 592.2 | 592.5 | 597.8 | 597.8 | | 1024x576 | Inf2 | 9040.2 | 9080.8 | 9115.6 | 9120.6 | 9123.7 | 9123.7 | | 256x144 | Inf2 | 3067.9 | 3075.7 | 3079.8 | 3081.2 | 3088.5 | 3088.5 | + *Table 1-Latency benchmark between 8 Trn1 NDs and 6 Inf2 NDs with 10 inference_steps for 50 iterations* From ef1e1d8baf293545c625d1e22caad87a219db55e Mon Sep 17 00:00:00 2001 From: Yahav Date: Mon, 6 Jan 2025 20:34:23 -0800 Subject: [PATCH 28/45] benchmark --- flux_serve/README.md | 6 ++---- flux_serve/specs/load.yaml | 2 +- 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/flux_serve/README.md b/flux_serve/README.md index 39bb351..82fec30 100644 --- a/flux_serve/README.md +++ b/flux_serve/README.md @@ -2,16 +2,14 @@ [FLUX.1 dev](https://huggingface.co/black-forest-labs/FLUX.1-dev) is a 12 billion parameter rectified flow transformer capable of generating images from text. This example illustrates how to optimize its usage on Neuron devices that power EC2 Inferentia (Inf2) and Trainium (Trn1) instances deployed on EKS. Since the FLUX.1 dev model cannot fit on a single Neuron device, neuronx_distributed splits the model transformer into `N=8` chunks along a dimension. This ensures that each device holds only `1/N` chunk of the tensor. By performing partial chunk computation, the model generates partial outputs from all devices, maintaining accuracy and producing high-quality images. However, loading the traced model graph before serving significantly impacts the model loading time. This depends on the `tp_degree`, `N`, and the produced model graph traces `*.pt` need to be loaded during deployment and integrated into the OCI image, which can lead to prolonged load times. To address this, we cache the model traces (in the range of 10 GB) in [S3 Mountpoints](https://docs.aws.amazon.com/eks/latest/userguide/s3-csi.html), decoupling the OCI model load time from the model traces load time. -Next, we determine the compute type we intend to use. The initial step involves loading the model, executing a single inference, and assessing the image quality based on the number of inference steps. Subsequently, we determine the minimum inference latency with `Trn1` and `Inf2` under the specified acceptable quality parameters, currently set to `num_inference_steps`. Finally, we load each deployment unit, such as Flux on Trn1 8 Neuron devices or Flux on Inf2 6 Neuron devices, until it reaches its breaking point where the latency exceeds the acceptable thresholds. +Next, we determine the compute type we intend to use. The initial step involves loading the model, executing a single inference, and assessing the image quality based on the number of inference steps. Subsequently, we determine the minimum inference latency with `Trn1` and `Inf2` under the specified acceptable quality parameters, currently set to `num_inference_steps`. Finally, we load each deployment unit, such as Flux on Trn1 8 Neuron devices or Flux on Inf2 6 Neuron devices, until it reaches its breaking point where the latency exceeds the acceptable thresholds. We measure the Neuron cores utilization using the built-in [Neuron monitoring tools](https://awsdocs-neuron.readthedocs-hosted.com/en/latest/general/monitoring-tools.html#monitoring-tools) that are included in Container Insights on Amazon EKS. The rest of this post offers a code sample walkthrough that explains the optimization strategies we adopted to streamline the deployment process using S3 CSI Driver and [Deep Learning Containers](https://github.com/aws/deep-learning-containers/blob/master/available_images.md). These strategies aim to reduce the cost of inference while enhancing model serving throughput. -TBD - https://awsdocs-neuron.readthedocs-hosted.com/en/latest/general/monitoring-tools.html#monitoring-tools are availible out of the box with container insights - - ## Walkthrough * [Create cluster with Karpenter node pools that provisions `trn1` instances](https://karpenter.sh/docs/getting-started/getting-started-with-karpenter/) +* [Setup Container Insights on Amazon EKS and Kubernetes](https://docs.aws.amazon.com/AmazonCloudWatch/latest/monitoring/Container-Insights-setup-EKS-quickstart.html) * [Deploy your HggingFace user secret as a k8s secret](https://kubernetes.io/docs/concepts/configuration/secret/) ```bash echo -n 'hf_myhftoken' | base64 diff --git a/flux_serve/specs/load.yaml b/flux_serve/specs/load.yaml index ae8463b..d845383 100644 --- a/flux_serve/specs/load.yaml +++ b/flux_serve/specs/load.yaml @@ -24,7 +24,7 @@ spec: - -c - -x - | - SLEEP_TIME=10 + SLEEP_TIME=2 while true; do curl -X POST -H "Content-Type: application/json" -d '{"prompt": "A majestic mountainscape in a surreal style","num_inference_steps": 10}' http://$FLUX_NEURON_256X144_MODEL_API_SERVICE_HOST:8000/generate sleep $SLEEP_TIME From 43296e1e282fc38cd41417b3ca1fcf6d9625776b Mon Sep 17 00:00:00 2001 From: Yahav Date: Mon, 6 Jan 2025 20:35:56 -0800 Subject: [PATCH 29/45] benchmark --- flux_serve/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/flux_serve/README.md b/flux_serve/README.md index 82fec30..8b33e86 100644 --- a/flux_serve/README.md +++ b/flux_serve/README.md @@ -2,7 +2,7 @@ [FLUX.1 dev](https://huggingface.co/black-forest-labs/FLUX.1-dev) is a 12 billion parameter rectified flow transformer capable of generating images from text. This example illustrates how to optimize its usage on Neuron devices that power EC2 Inferentia (Inf2) and Trainium (Trn1) instances deployed on EKS. Since the FLUX.1 dev model cannot fit on a single Neuron device, neuronx_distributed splits the model transformer into `N=8` chunks along a dimension. This ensures that each device holds only `1/N` chunk of the tensor. By performing partial chunk computation, the model generates partial outputs from all devices, maintaining accuracy and producing high-quality images. However, loading the traced model graph before serving significantly impacts the model loading time. This depends on the `tp_degree`, `N`, and the produced model graph traces `*.pt` need to be loaded during deployment and integrated into the OCI image, which can lead to prolonged load times. To address this, we cache the model traces (in the range of 10 GB) in [S3 Mountpoints](https://docs.aws.amazon.com/eks/latest/userguide/s3-csi.html), decoupling the OCI model load time from the model traces load time. -Next, we determine the compute type we intend to use. The initial step involves loading the model, executing a single inference, and assessing the image quality based on the number of inference steps. Subsequently, we determine the minimum inference latency with `Trn1` and `Inf2` under the specified acceptable quality parameters, currently set to `num_inference_steps`. Finally, we load each deployment unit, such as Flux on Trn1 8 Neuron devices or Flux on Inf2 6 Neuron devices, until it reaches its breaking point where the latency exceeds the acceptable thresholds. We measure the Neuron cores utilization using the built-in [Neuron monitoring tools](https://awsdocs-neuron.readthedocs-hosted.com/en/latest/general/monitoring-tools.html#monitoring-tools) that are included in Container Insights on Amazon EKS. +Next, we determine the compute type we intend to use. The initial step involves loading the model, executing a single inference, and assessing the image quality based on the number of inference steps. Subsequently, we determine the minimum inference latency with `Trn1` and `Inf2` under the specified acceptable quality parameters, currently set to `num_inference_steps`. Finally, we load each deployment unit, such as Flux on Trn1 8 Neuron devices or Flux on Inf2 6 Neuron devices, until it reaches its breaking point where the latency exceeds the acceptable thresholds. We measure the Neuron core utilization using the built-in [Neuron monitoring tools](https://awsdocs-neuron.readthedocs-hosted.com/en/latest/general/monitoring-tools.html#monitoring-tools) that are included in Container Insights on Amazon EKS. The rest of this post offers a code sample walkthrough that explains the optimization strategies we adopted to streamline the deployment process using S3 CSI Driver and [Deep Learning Containers](https://github.com/aws/deep-learning-containers/blob/master/available_images.md). These strategies aim to reduce the cost of inference while enhancing model serving throughput. From 6017ed5ef613a92aeb8c347a311f995e731d7f77 Mon Sep 17 00:00:00 2001 From: Yahav Date: Fri, 25 Apr 2025 17:38:00 -0700 Subject: [PATCH 30/45] mllma --- flux_serve/app/mllama-offline.py | 113 +++++++++++++++++++++++++++ flux_serve/oci-image-build/README.md | 2 +- 2 files changed, 114 insertions(+), 1 deletion(-) create mode 100644 flux_serve/app/mllama-offline.py diff --git a/flux_serve/app/mllama-offline.py b/flux_serve/app/mllama-offline.py new file mode 100644 index 0000000..6f657b5 --- /dev/null +++ b/flux_serve/app/mllama-offline.py @@ -0,0 +1,113 @@ +import math +import time +import torch +import os +import sys +import yaml +import requests +from PIL import Image +from vllm import LLM, SamplingParams, TextPrompt +from neuronx_distributed_inference.models.mllama.utils import add_instruct +from huggingface_hub import create_repo,upload_folder,login,snapshot_download + +hf_token = os.environ['HUGGINGFACE_TOKEN'].strip() +repo_id=os.environ['MODEL_ID'] +os.environ['NEURON_COMPILED_ARTIFACTS']=repo_id +os.environ['VLLM_NEURON_FRAMEWORK']='neuronx-distributed-inference' +login(hf_token,add_to_git_credential=True) + +config_path = "/vllm_config.yaml" +with open(config_path, 'r') as f: + model_vllm_config_yaml = f.read() + +model_vllm_config = yaml.safe_load(model_vllm_config_yaml) + +class LatencyCollector: + def __init__(self): + self.latency_list = [] + + def record(self, latency_sec): + self.latency_list.append(latency_sec) + + def percentile(self, percent): + if not self.latency_list: + return 0.0 + latency_list = sorted(self.latency_list) + pos_float = len(latency_list) * percent / 100 + max_pos = len(latency_list) - 1 + pos_floor = min(math.floor(pos_float), max_pos) + pos_ceil = min(math.ceil(pos_float), max_pos) + return latency_list[pos_ceil] if pos_float - pos_floor > 0.5 else latency_list[pos_floor] + + def report(self, test_name="Batch Inference"): + print(f"\nšŸ“Š LATENCY REPORT for {test_name}") + for p in [0, 50, 90, 95, 99, 100]: + value = self.percentile(p) * 1000 + print(f"Latency P{p}: {value:.2f} ms") + + +def get_image(image_url): + image = Image.open(requests.get(image_url, stream=True).raw) + return image + +# Model Inputs +PROMPTS = ["What is in this image? Tell me a story", + "What is the recipe of mayonnaise in two sentences?" , + "Describe this image", + "What is the capital of Italy famous for?", + ] +IMAGES = [get_image("https://github.com/meta-llama/llama-models/blob/main/models/resources/dog.jpg?raw=true"), + torch.empty((0,0)), + get_image("https://awsdocs-neuron.readthedocs-hosted.com/en/latest/_images/nxd-inference-block-diagram.jpg"), + torch.empty((0,0)), + ] +SAMPLING_PARAMS = [dict(top_k=1, temperature=1.0, top_p=1.0, max_tokens=256), + dict(top_k=1, temperature=0.9, top_p=1.0, max_tokens=256), + dict(top_k=10, temperature=0.9, top_p=0.5, max_tokens=512), + dict(top_k=10, temperature=0.75, top_p=0.5, max_tokens=1024), + ] + + +def get_VLLM_mllama_model_inputs(prompt, single_image, sampling_params): + input_image = single_image + has_image = torch.tensor([1]) + if isinstance(single_image, torch.Tensor) and single_image.numel() == 0: + has_image = torch.tensor([0]) + + instruct_prompt = add_instruct(prompt, has_image) + inputs = TextPrompt(prompt=instruct_prompt) + inputs["multi_modal_data"] = {"image": input_image} + # Create a sampling params object. + sampling_params = SamplingParams(**sampling_params) + return inputs, sampling_params + +def print_outputs(outputs): + # Print the outputs. + for output in outputs: + prompt = output.prompt + generated_text = output.outputs[0].text + print(f"Prompt: {prompt!r}, Generated text: {generated_text!r}") + + +llm_model = LLM(**model_vllm_config) +latency_collector = LatencyCollector() + +assert len(PROMPTS) == len(IMAGES) == len(SAMPLING_PARAMS), \ +f"""Text, image prompts and sampling parameters should have the same batch size, + got {len(PROMPTS)}, {len(IMAGES)}, and {len(SAMPLING_PARAMS)}""" + +batched_inputs = [] +batched_sample_params = [] +for i in range(1,21): + for pmpt, img, params in zip(PROMPTS, IMAGES, SAMPLING_PARAMS): + inputs, sampling_params = get_VLLM_mllama_model_inputs(pmpt, img, params) + # test batch-size = 1 + start_time = time.time() + outputs = llm_model.generate(inputs, sampling_params) + latency_sec = time.time() - start_time + latency_collector.record(latency_sec) + print_outputs(outputs) + batched_inputs.append(inputs) + batched_sample_params.append(sampling_params) + +latency_collector.report("MLLAMA") diff --git a/flux_serve/oci-image-build/README.md b/flux_serve/oci-image-build/README.md index 4052d04..a6f87cf 100644 --- a/flux_serve/oci-image-build/README.md +++ b/flux_serve/oci-image-build/README.md @@ -5,7 +5,7 @@ ```bash export AWS_ACCOUNT_ID=$(aws sts get-caller-identity --output text --query Account) export AWS_REGION=us-west-2 -export BASE_IMAGE_AMD_XLA_TAG=2.5.1-neuronx-py310-sdk2.21.0-ubuntu22.04 +export BASE_IMAGE_AMD_XLA_TAG=2.5.1-neuronx-py310-sdk2.22.0-ubuntu22.04 export IMAGE_AMD_XLA_TAG=amd64-neuron export BASE_REPO=model export BASE_TAG=multiarch-ubuntu From 93ef8f513ab942bfd82b1ad5aa902812eaf0a2a1 Mon Sep 17 00:00:00 2001 From: Yahav Date: Fri, 25 Apr 2025 18:17:33 -0700 Subject: [PATCH 31/45] vllm_model_api.py --- flux_serve/app/vllm_model_api.py | 172 +++++++++++++++++++++++++++++++ 1 file changed, 172 insertions(+) create mode 100644 flux_serve/app/vllm_model_api.py diff --git a/flux_serve/app/vllm_model_api.py b/flux_serve/app/vllm_model_api.py new file mode 100644 index 0000000..4a42087 --- /dev/null +++ b/flux_serve/app/vllm_model_api.py @@ -0,0 +1,172 @@ +import traceback +import math +import boto3 +import time +import argparse +import torch +import torch.nn as nn +#import torch_neuronx +#import neuronx_distributed +import os +from fastapi import FastAPI, HTTPException +from pydantic import BaseModel, Field +from typing import Any, Dict, Optional, Union +from huggingface_hub import login +from starlette.responses import StreamingResponse +import base64 +from vllm import LLM, SamplingParams +from sentence_transformers import SentenceTransformer +import yaml + +cw_namespace='hw-agnostic-infer' +default_max_new_tokens=50 +cloudwatch = boto3.client('cloudwatch', region_name='us-west-2') +sampling_params = SamplingParams(temperature=0.7,top_k=50,top_p=0.9,max_tokens=128,) + +app_name=os.environ['APP'] +nodepool=os.environ['NODEPOOL'] +pod_name = os.environ['POD_NAME'] +hf_token = os.environ['HUGGINGFACE_TOKEN'].strip() + +with open("/vllm_config.yaml", "r") as file: + vllm_config=yaml.safe_load(file) + +login(hf_token, add_to_git_credential=True) + +def gentext(prompt,max_new_tokens): + start_time = time.time() + outputs = model.generate(prompt,sampling_params) + response = outputs[0].outputs[0].text + total_time = time.time()-start_time + return str(response), float(total_time) + +def cw_pub_metric(metric_name,metric_value,metric_unit): + response = cloudwatch.put_metric_data( + Namespace=cw_namespace, + MetricData=[ + { + 'MetricName':metric_name, + 'Value':metric_value, + 'Unit':metric_unit, + }, + ] + ) + print(f"in pub_deployment_counter - response:{response}") + return response + +login(hf_token, add_to_git_credential=True) + +# TBD change to text from image +def benchmark(n_runs, test_name,model,prompt,max_new_tokens): + warmup_run = model.generate(prompt,sampling_params) + latency_collector = LatencyCollector() + + for _ in range(n_runs): + latency_collector.pre_hook() + res = model.generate(prompt,sampling_params) + latency_collector.hook() + + p0_latency_ms = latency_collector.percentile(0) * 1000 + p50_latency_ms = latency_collector.percentile(50) * 1000 + p90_latency_ms = latency_collector.percentile(90) * 1000 + p95_latency_ms = latency_collector.percentile(95) * 1000 + p99_latency_ms = latency_collector.percentile(99) * 1000 + p100_latency_ms = latency_collector.percentile(100) * 1000 + + report_dict = dict() + report_dict["Latency P0"] = f'{p0_latency_ms:.1f}' + report_dict["Latency P50"]=f'{p50_latency_ms:.1f}' + report_dict["Latency P90"]=f'{p90_latency_ms:.1f}' + report_dict["Latency P95"]=f'{p95_latency_ms:.1f}' + report_dict["Latency P99"]=f'{p99_latency_ms:.1f}' + report_dict["Latency P100"]=f'{p100_latency_ms:.1f}' + + report = f'RESULT FOR {test_name}:' + for key, value in report_dict.items(): + report += f' {key}={value}' + print(report) + return report + +class LatencyCollector: + def __init__(self): + self.start = None + self.latency_list = [] + + def pre_hook(self, *args): + self.start = time.time() + + def hook(self, *args): + self.latency_list.append(time.time() - self.start) + + def percentile(self, percent): + latency_list = self.latency_list + pos_float = len(latency_list) * percent / 100 + max_pos = len(latency_list) - 1 + pos_floor = min(math.floor(pos_float), max_pos) + pos_ceil = min(math.ceil(pos_float), max_pos) + latency_list = sorted(latency_list) + return latency_list[pos_ceil] if pos_float - pos_floor > 0.5 else latency_list[pos_floor] + +class GenerateRequest(BaseModel): + max_new_tokens: int + prompt: str + +class GenerateBenchmarkRequest(BaseModel): + n_runs: int + max_new_tokens: int + prompt: str + +class GenerateResponse(BaseModel): + text: str = Field(..., description="Base64-encoded text") + execution_time: float + +class GenerateBenchmarkResponse(BaseModel): + report: str = Field(..., description="Benchmark report") + +def load_model(): + model = LLM(**vllm_config) + return model + +model = load_model() +prompt= "What model are you?" +benchmark(10,"warmup",model,prompt,default_max_new_tokens) +app = FastAPI() + +@app.post("/benchmark",response_model=GenerateBenchmarkResponse) +def generate_benchmark_report(request: GenerateBenchmarkRequest): + print(f'DEBUG: GenerateBenchmarkRequest:{request}') + try: + with torch.no_grad(): + test_name=f'benchmark:{app_name} on {nodepool} with {request.max_new_tokens} output tokens' + response_report=benchmark(request.n_runs,test_name,model,request.prompt,request.max_new_tokens) + report_base64 = base64.b64encode(response_report.encode()).decode() + return GenerateBenchmarkResponse(report=report_base64) + except Exception as e: + traceback.print_exc() + raise HTTPException(status_code=500, detail=f"{e}") + +@app.post("/generate", response_model=GenerateResponse) +def generate_text_post(request: GenerateRequest): + try: + with torch.no_grad(): + response_text,total_time=gentext(request.prompt,request.max_new_tokens) + counter_metric=app_name+'-counter' + cw_pub_metric(counter_metric,1,'Count') + counter_metric=nodepool + cw_pub_metric(counter_metric,1,'Count') + latency_metric=app_name+'-latency' + cw_pub_metric(latency_metric,total_time,'Seconds') + text_base64 = base64.b64encode(response_text.encode()).decode() + return GenerateResponse(text=text_base64, execution_time=total_time) + except Exception as e: + traceback.print_exc() + raise HTTPException(status_code=500, detail=f"text serialization failed: {e}") + +# Health and readiness endpoints +@app.get("/health") +def healthy(): + return {"message": f"{pod_name} is healthy"} + +@app.get("/readiness") +def ready(): + return {"message": f"{pod_name} is ready"} From b57bf4b75205e578c4664219a7c63e324cc6004e Mon Sep 17 00:00:00 2001 From: Yahav Date: Sun, 27 Apr 2025 14:19:59 -0700 Subject: [PATCH 32/45] ../app/flux_model_api.py --- flux_serve/app/flux_model_api.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/flux_serve/app/flux_model_api.py b/flux_serve/app/flux_model_api.py index 2bf6d3f..a3ac2e6 100644 --- a/flux_serve/app/flux_model_api.py +++ b/flux_serve/app/flux_model_api.py @@ -297,7 +297,7 @@ def load_model(): num_inference_steps=10 model_inputs={'prompt':prompt,'height':height,'width':width,'max_sequence_length':max_sequence_length,'num_inference_steps': num_inference_steps,'guidance_scale':guidance_scale} test_name=f"flux1-dev-50runs with dim {height}x{width} on {nodepool};num_inference_steps:{num_inference_steps}" -benchmark(50,test_name,model,model_inputs) +benchmark(10,test_name,model,model_inputs) # Define the image generation endpoint @app.post("/generate", response_model=GenerateImageResponse) From fead2dcc9663f27bac32b2610a8561be843b6fcb Mon Sep 17 00:00:00 2001 From: Yahav Date: Sun, 27 Apr 2025 18:40:39 -0700 Subject: [PATCH 33/45] download_hf_model.py --- flux_serve/app/download_hf_model.py | 9 +++++++++ flux_serve/specs/amd-neuron-inf2-nodepool.yaml | 15 ++++++--------- flux_serve/specs/amd-neuron-trn1-nodepool.yaml | 15 ++++++--------- 3 files changed, 21 insertions(+), 18 deletions(-) create mode 100644 flux_serve/app/download_hf_model.py diff --git a/flux_serve/app/download_hf_model.py b/flux_serve/app/download_hf_model.py new file mode 100644 index 0000000..fde2467 --- /dev/null +++ b/flux_serve/app/download_hf_model.py @@ -0,0 +1,9 @@ +from huggingface_hub import login,snapshot_download +import os +hf_token=os.environ['HUGGINGFACE_TOKEN'].strip() +repo_id=os.environ['COMPILED_MODEL_ID'] +repo_dir=os.environ['NEURON_COMPILED_ARTIFACTS'] +login(hf_token, add_to_git_credential=True) +snapshot_download(repo_id=repo_id,local_dir=repo_dir,token=hf_token) +print(f"Repository '{repo_id}' downloaded to '{repo_dir}'.") + diff --git a/flux_serve/specs/amd-neuron-inf2-nodepool.yaml b/flux_serve/specs/amd-neuron-inf2-nodepool.yaml index 840259f..151b67d 100644 --- a/flux_serve/specs/amd-neuron-inf2-nodepool.yaml +++ b/flux_serve/specs/amd-neuron-inf2-nodepool.yaml @@ -18,7 +18,7 @@ spec: nodeClassRef: group: karpenter.k8s.aws kind: EC2NodeClass - name: amd-neuron + name: amd-neuron-al2023 expireAfter: 720h # 30 * 24h = 720h limits: cpu: 1000 @@ -29,20 +29,17 @@ spec: apiVersion: karpenter.k8s.aws/v1 kind: EC2NodeClass metadata: - name: amd-neuron + name: amd-neuron-al2023 spec: - amiFamily: AL2 # Amazon Linux 2 amiSelectorTerms: - - id: "ami-0e73cfd34ee52b6a6" - - id: "ami-077b8064c2a1a3186" - - id: "ami-057dddc807f3f6644" - role: "KarpenterNodeRole-flux-usw2" + - alias: "al2023@v20250419" + role: "KarpenterNodeRole-cova" subnetSelectorTerms: - tags: - karpenter.sh/discovery: "flux-usw2" + karpenter.sh/discovery: "cova" securityGroupSelectorTerms: - tags: - karpenter.sh/discovery: "flux-usw2" + karpenter.sh/discovery: "cova" blockDeviceMappings: - deviceName: /dev/xvda ebs: diff --git a/flux_serve/specs/amd-neuron-trn1-nodepool.yaml b/flux_serve/specs/amd-neuron-trn1-nodepool.yaml index 2e7a23d..556fb37 100644 --- a/flux_serve/specs/amd-neuron-trn1-nodepool.yaml +++ b/flux_serve/specs/amd-neuron-trn1-nodepool.yaml @@ -18,7 +18,7 @@ spec: nodeClassRef: group: karpenter.k8s.aws kind: EC2NodeClass - name: amd-neuron + name: amd-neuron-al2023 expireAfter: 720h # 30 * 24h = 720h limits: cpu: 1000 @@ -29,20 +29,17 @@ spec: apiVersion: karpenter.k8s.aws/v1 kind: EC2NodeClass metadata: - name: amd-neuron + name: amd-neuron-al2023 spec: - amiFamily: AL2 # Amazon Linux 2 amiSelectorTerms: - - id: "ami-0e73cfd34ee52b6a6" - - id: "ami-077b8064c2a1a3186" - - id: "ami-057dddc807f3f6644" - role: "KarpenterNodeRole-flux-usw2" + - alias: "al2023@v20250419" + role: "KarpenterNodeRole-cova" subnetSelectorTerms: - tags: - karpenter.sh/discovery: "flux-usw2" + karpenter.sh/discovery: "cova" securityGroupSelectorTerms: - tags: - karpenter.sh/discovery: "flux-usw2" + karpenter.sh/discovery: "cova" blockDeviceMappings: - deviceName: /dev/xvda ebs: From 06cc2d298ab2f876f980f31fe8cd90915bded9c0 Mon Sep 17 00:00:00 2001 From: Yahav Date: Sun, 27 Apr 2025 19:05:30 -0700 Subject: [PATCH 34/45] cova --- flux_serve/app/cova_gradio.py | 123 ++++++++++++++++++++++++++++++++++ 1 file changed, 123 insertions(+) create mode 100644 flux_serve/app/cova_gradio.py diff --git a/flux_serve/app/cova_gradio.py b/flux_serve/app/cova_gradio.py new file mode 100644 index 0000000..db2ec86 --- /dev/null +++ b/flux_serve/app/cova_gradio.py @@ -0,0 +1,123 @@ +import gradio as gr +import requests +from PIL import Image +import io +import os +from fastapi import FastAPI +import base64 +import asyncio +import httpx + +app = FastAPI() + +models = [ + { + 'name': '512x512', + 'host_env': 'FLUX_NEURON_512X512_MODEL_API_SERVICE_HOST', + 'port_env': 'FLUX_NEURON_512X512_MODEL_API_SERVICE_PORT', + 'height': 512, + 'width': 512 + } +] + +for model in models: + host = os.environ[model['host_env']] + port = os.environ[model['port_env']] + model['url'] = f"http://{host}:{port}/generate" + +async def fetch_image(client, url, prompt, num_inference_steps): + payload = { + "prompt": prompt, + "num_inference_steps": int(num_inference_steps) + } + try: + response = await client.post(url, json=payload, timeout=60.0) + response.raise_for_status() + data = response.json() + image_bytes = base64.b64decode(data['image']) + image = Image.open(io.BytesIO(image_bytes)) + execution_time = data.get('execution_time', 0) + return image, f"{execution_time:.2f} seconds" + except httpx.RequestError as e: + return None, f"Request Error: {str(e)}" + except Exception as e: + return None, f"Error: {str(e)}" + +async def call_model_api(prompt, num_inference_steps): + async with httpx.AsyncClient() as client: + tasks = [ + fetch_image(client, model['url'], prompt, num_inference_steps) + for model in models + ] + results = await asyncio.gather(*tasks) + images = [] + exec_times = [] + for image, exec_time in results: + images.append(image) + exec_times.append(exec_time) + return images + exec_times + +@app.get("/health") +def healthy(): + return {"message": "Service is healthy"} + +@app.get("/readiness") +def ready(): + return {"message": "Service is ready"} + +with gr.Blocks() as interface: + gr.Markdown(f"# {model_id} Image Generation App") + gr.Markdown("Enter a prompt and specify the number of inference steps to generate images in different shapes.") + + with gr.Row(): + with gr.Column(scale=1): + prompt = gr.Textbox( + label="Prompt", + lines=1, + placeholder="Enter your prompt here...", + elem_id="prompt-box" + ) + inference_steps = gr.Number( + label="Inference Steps", + value=10, + precision=0, + info="Enter the number of inference steps; higher number takes more time but produces better image", + elem_id="steps-number" + ) + generate_button = gr.Button("Generate Images", variant="primary") + + with gr.Column(scale=2): + image_components = [] + exec_time_components = [] + + with gr.Row(): + for idx, model in enumerate(models): + with gr.Column(): + # Title + gr.Markdown(f"**{model['name']}**") + + # Scale down the image + preview_height = int(model['height'] / 2) + preview_width = int(model['width'] / 2) + + img = gr.Image( + label="", + height=preview_height, + width=preview_width, + interactive=False + ) + # Use Markdown for simpler smaller text + exec_time = gr.Markdown(value="") + + image_components.append(img) + exec_time_components.append(exec_time) + + # callback for the button + generate_button.click( + fn=call_model_api, + inputs=[prompt, inference_steps], + outputs=image_components + exec_time_components, + api_name="generate_images" + ) + +app = gr.mount_gradio_app(app, interface, path="/serve") From cbcc840b17e243b62c2b58139b16552f5cafe970 Mon Sep 17 00:00:00 2001 From: Yahav Date: Sun, 27 Apr 2025 20:02:19 -0700 Subject: [PATCH 35/45] cova_gradio.py --- flux_serve/app/cova_gradio.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/flux_serve/app/cova_gradio.py b/flux_serve/app/cova_gradio.py index db2ec86..e9f22a1 100644 --- a/flux_serve/app/cova_gradio.py +++ b/flux_serve/app/cova_gradio.py @@ -66,7 +66,7 @@ def ready(): return {"message": "Service is ready"} with gr.Blocks() as interface: - gr.Markdown(f"# {model_id} Image Generation App") + gr.Markdown(f"# Image Generation App") gr.Markdown("Enter a prompt and specify the number of inference steps to generate images in different shapes.") with gr.Row(): From 831968f901437a56e27ac6782e555d6a28138397 Mon Sep 17 00:00:00 2001 From: Yahav Date: Sun, 27 Apr 2025 20:15:53 -0700 Subject: [PATCH 36/45] vllm_model_api.py --- flux_serve/app/vllm_model_api.py | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/flux_serve/app/vllm_model_api.py b/flux_serve/app/vllm_model_api.py index 4a42087..82eee60 100644 --- a/flux_serve/app/vllm_model_api.py +++ b/flux_serve/app/vllm_model_api.py @@ -17,6 +17,7 @@ from vllm import LLM, SamplingParams from sentence_transformers import SentenceTransformer import yaml +from transformers import AutoConfig cw_namespace='hw-agnostic-infer' default_max_new_tokens=50 @@ -124,6 +125,11 @@ class GenerateBenchmarkResponse(BaseModel): report: str = Field(..., description="Benchmark report") def load_model(): + model_id = vllm_config["model"] + config = AutoConfig.from_pretrained(model_id) + if config.rope_scaling is None: + config.rope_scaling = {"rope_type": "linear", "scaling_factor": 1.0} + vllm_config["model_config"] = config model = LLM(**vllm_config) return model From 1ba46f37136b5993067e84d9065bc87cfac4b667 Mon Sep 17 00:00:00 2001 From: Yahav Date: Sun, 27 Apr 2025 20:24:07 -0700 Subject: [PATCH 37/45] vllm_model_api.py --- flux_serve/app/vllm_model_api.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/flux_serve/app/vllm_model_api.py b/flux_serve/app/vllm_model_api.py index 82eee60..8b988bb 100644 --- a/flux_serve/app/vllm_model_api.py +++ b/flux_serve/app/vllm_model_api.py @@ -29,6 +29,9 @@ pod_name = os.environ['POD_NAME'] hf_token = os.environ['HUGGINGFACE_TOKEN'].strip() +repo_id=os.environ['MODEL_ID'] +os.environ['NEURON_COMPILED_ARTIFACTS']=repo_id + with open("/vllm_config.yaml", "r") as file: vllm_config=yaml.safe_load(file) From 43e8415baf9fbfa86c66de53cbcb30e4762ccf66 Mon Sep 17 00:00:00 2001 From: Yahav Date: Sun, 27 Apr 2025 20:36:58 -0700 Subject: [PATCH 38/45] download_hf_model.py --- flux_serve/app/download_hf_model.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/flux_serve/app/download_hf_model.py b/flux_serve/app/download_hf_model.py index fde2467..d46fc4c 100644 --- a/flux_serve/app/download_hf_model.py +++ b/flux_serve/app/download_hf_model.py @@ -1,9 +1,9 @@ from huggingface_hub import login,snapshot_download import os +repo_id=os.environ['MODEL_ID'] +os.environ['NEURON_COMPILED_ARTIFACTS']=repo_id hf_token=os.environ['HUGGINGFACE_TOKEN'].strip() -repo_id=os.environ['COMPILED_MODEL_ID'] -repo_dir=os.environ['NEURON_COMPILED_ARTIFACTS'] login(hf_token, add_to_git_credential=True) -snapshot_download(repo_id=repo_id,local_dir=repo_dir,token=hf_token) -print(f"Repository '{repo_id}' downloaded to '{repo_dir}'.") +snapshot_download(repo_id=repo_id,local_dir=repo_id,token=hf_token) +print(f"Repository '{repo_id}' downloaded to '{repo_id}'.") From aaa255145e958ecdb0f3b875224a72cedc850bb6 Mon Sep 17 00:00:00 2001 From: Yahav Date: Sun, 27 Apr 2025 20:53:52 -0700 Subject: [PATCH 39/45] vllm_model_api.py --- flux_serve/app/vllm_model_api.py | 6 ------ 1 file changed, 6 deletions(-) diff --git a/flux_serve/app/vllm_model_api.py b/flux_serve/app/vllm_model_api.py index 8b988bb..5c18dd7 100644 --- a/flux_serve/app/vllm_model_api.py +++ b/flux_serve/app/vllm_model_api.py @@ -17,7 +17,6 @@ from vllm import LLM, SamplingParams from sentence_transformers import SentenceTransformer import yaml -from transformers import AutoConfig cw_namespace='hw-agnostic-infer' default_max_new_tokens=50 @@ -128,11 +127,6 @@ class GenerateBenchmarkResponse(BaseModel): report: str = Field(..., description="Benchmark report") def load_model(): - model_id = vllm_config["model"] - config = AutoConfig.from_pretrained(model_id) - if config.rope_scaling is None: - config.rope_scaling = {"rope_type": "linear", "scaling_factor": 1.0} - vllm_config["model_config"] = config model = LLM(**vllm_config) return model From 8bec2fcfb2864ae58dcbed1c735c735ab928920f Mon Sep 17 00:00:00 2001 From: Yahav Date: Sun, 27 Apr 2025 21:33:35 -0700 Subject: [PATCH 40/45] download_hf_model.py --- flux_serve/app/download_hf_model.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/flux_serve/app/download_hf_model.py b/flux_serve/app/download_hf_model.py index d46fc4c..202a32a 100644 --- a/flux_serve/app/download_hf_model.py +++ b/flux_serve/app/download_hf_model.py @@ -4,6 +4,6 @@ os.environ['NEURON_COMPILED_ARTIFACTS']=repo_id hf_token=os.environ['HUGGINGFACE_TOKEN'].strip() login(hf_token, add_to_git_credential=True) -snapshot_download(repo_id=repo_id,local_dir=repo_id,token=hf_token) +snapshot_download(repo_id=repo_id,local_dir="/"+repo_id,token=hf_token) print(f"Repository '{repo_id}' downloaded to '{repo_id}'.") From c1409a1089cc6468e9cfe3c0f4056c64e4ad4e91 Mon Sep 17 00:00:00 2001 From: Yahav Date: Sun, 27 Apr 2025 22:45:26 -0700 Subject: [PATCH 41/45] cova_gradio_m.py --- flux_serve/app/cova_gradio_m.py | 132 ++++++++++++++++++++++++++++++++ 1 file changed, 132 insertions(+) create mode 100644 flux_serve/app/cova_gradio_m.py diff --git a/flux_serve/app/cova_gradio_m.py b/flux_serve/app/cova_gradio_m.py new file mode 100644 index 0000000..0901f37 --- /dev/null +++ b/flux_serve/app/cova_gradio_m.py @@ -0,0 +1,132 @@ +import os, io, base64, asyncio, json +from typing import Tuple, List +import gradio as gr +import httpx +from PIL import Image +from fastapi import FastAPI + +app = FastAPI() + +# --------------------------------------------------------------------------- +# ā¶ Model definitions -– extend with more rows if you deploy more shapes later +# --------------------------------------------------------------------------- +IMAGE_MODELS = [ + dict( + name="512 Ɨ 512", + host_env="FLUX_NEURON_512X512_MODEL_API_SERVICE_HOST", + port_env="FLUX_NEURON_512X512_MODEL_API_SERVICE_PORT", + height=512, + width=512, + # caption backend for this image size + caption_host_env="MLLAMA_32_11B_VLLM_TRN1_SERVICE_HOST", + caption_port_env="MLLAMA_32_11B_VLLM_TRN1_SERVICE_PORT", + # number of caption tokens to ask for per request + caption_max_new_tokens=64, + ) +] + +for m in IMAGE_MODELS: + m["image_url"] = f'http://{os.environ[m["host_env"]]}:{os.environ[m["port_env"]]}/generate' + m["caption_url"] = f'http://{os.environ[m["caption_host_env"]]}:{os.environ[m["caption_port_env"]]}/generate' + +# --------------------------------------------------------------------------- +# ā· Helpers +# --------------------------------------------------------------------------- +async def post_json(client: httpx.AsyncClient, url: str, payload: dict, timeout: float = 60.0): + """Small wrapper that returns (json, elapsed_seconds) or raises.""" + start = asyncio.get_event_loop().time() + r = await client.post(url, json=payload, timeout=timeout) + r.raise_for_status() + elapsed = asyncio.get_event_loop().time() - start + return r.json(), elapsed + +def pil_to_base64(img: Image.Image) -> str: + buf = io.BytesIO() + img.save(buf, format="PNG") + return base64.b64encode(buf.getvalue()).decode() + +async def fetch_end_to_end( + client : httpx.AsyncClient, + model_cfg : dict, + prompt : str, + num_steps : int +) -> Tuple[Image.Image, str, str]: + """ + Returns (image, latency_str, caption_str, caption_latency_str) + """ + # ā‘  Generate the image + img_payload = {"prompt": prompt, "num_inference_steps": int(num_steps)} + img_json, img_latency = await post_json(client, model_cfg["image_url"], img_payload) + image = Image.open(io.BytesIO(base64.b64decode(img_json["image"]))) + + # ā‘” Ask vLLM to describe that image + img_b64 = pil_to_base64(image) + caption_prompt = f"Describe the content of this image (base64 PNG follows): {img_b64}" + cap_payload = {"prompt": caption_prompt, + "max_new_tokens": model_cfg["caption_max_new_tokens"]} + cap_json, cap_latency = await post_json(client, model_cfg["caption_url"], cap_payload) + caption = base64.b64decode(cap_json["text"]).decode() + + return image, f"{img_latency:.2f}s", caption, f"{cap_latency:.2f}s" + +async def orchestrate_calls(prompt: str, num_steps: int): + async with httpx.AsyncClient() as client: + tasks = [fetch_end_to_end(client, cfg, prompt, num_steps) for cfg in IMAGE_MODELS] + results = await asyncio.gather(*tasks) + + # Flatten results for gradio → [img, img_lat, caption, cap_lat] * N + flat: List = [] + for tup in results: + flat.extend(tup) + return flat + +# --------------------------------------------------------------------------- +# āø Gradio UI +# --------------------------------------------------------------------------- +with gr.Blocks() as interface: + gr.Markdown("# ⚔ Flux Image-Gen + vLLM Caption Demo") + gr.Markdown("Enter a text prompt āžœ model draws an image āžœ LLM describes the image.") + + with gr.Row(): + # user controls + with gr.Column(scale=1): + prompt_in = gr.Textbox(lines=1, label="Prompt") + steps_in = gr.Number(label="Inference Steps", value=10, precision=0) + btn_generate = gr.Button("Generate", variant="primary") + + # results + with gr.Column(scale=2): + img_out_components: list = [] + img_lat_components: list = [] + cap_out_components: list = [] + cap_lat_components: list = [] + + for cfg in IMAGE_MODELS: + with gr.Group(): + gr.Markdown(f"### {cfg['name']}") + img = gr.Image(height=cfg["height"]//2, + width=cfg["width"]//2, + interactive=False) + lat = gr.Markdown() + cap = gr.Markdown() + cap_lat = gr.Markdown() + img_out_components.append(img) + img_lat_components.append(lat) + cap_out_components.append(cap) + cap_lat_components.append(cap_lat) + + # wire them all up + btn_generate.click( + orchestrate_calls, + inputs=[prompt_in, steps_in], + outputs=( + img_out_components + + img_lat_components + + cap_out_components + + cap_lat_components + ), + api_name="generate_and_caption", + ) + +app = gr.mount_gradio_app(app, interface, path="/serve") + From cc5695fc8eea86029876696122bb805d0879198c Mon Sep 17 00:00:00 2001 From: Yahav Date: Sun, 27 Apr 2025 23:01:44 -0700 Subject: [PATCH 42/45] cova_gradio_m.py --- flux_serve/app/cova_gradio_m.py | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/flux_serve/app/cova_gradio_m.py b/flux_serve/app/cova_gradio_m.py index 0901f37..000c82a 100644 --- a/flux_serve/app/cova_gradio_m.py +++ b/flux_serve/app/cova_gradio_m.py @@ -130,3 +130,10 @@ async def orchestrate_calls(prompt: str, num_steps: int): app = gr.mount_gradio_app(app, interface, path="/serve") +@app.get("/health") +def healthy(): + return {"message": "Service is healthy"} + +@app.get("/readiness") +def ready(): + return {"message": "Service is ready"} From 313782b35bb665cc0d9fe328f97af41a9d61f77a Mon Sep 17 00:00:00 2001 From: Yahav Date: Mon, 5 May 2025 09:17:02 -0700 Subject: [PATCH 43/45] t5_model_api.py --- flux_serve/app/t5_model_api.py | 172 +++++++++++++++++++++++++++++++++ 1 file changed, 172 insertions(+) create mode 100644 flux_serve/app/t5_model_api.py diff --git a/flux_serve/app/t5_model_api.py b/flux_serve/app/t5_model_api.py new file mode 100644 index 0000000..731e895 --- /dev/null +++ b/flux_serve/app/t5_model_api.py @@ -0,0 +1,172 @@ +import traceback +import math +import boto3 +import time +import argparse +import torch +import os +from fastapi import FastAPI, HTTPException +from pydantic import BaseModel, Field +from typing import Any, Dict, Optional, Union +from huggingface_hub import login,snapshot_download +import base64 +import torch +from transformers import T5Tokenizer +from neuronx_distributed.trace import parallel_model_load + +cw_namespace='hw-agnostic-infer' +default_max_new_tokens=50 +cloudwatch = boto3.client('cloudwatch', region_name='us-west-2') +sampling_params = SamplingParams(temperature=0.7,top_k=50,top_p=0.9,max_tokens=128,) + +app_name=os.environ['APP'] +nodepool=os.environ['NODEPOOL'] +pod_name = os.environ['POD_NAME'] +hf_token = os.environ['HUGGINGFACE_TOKEN'].strip() + +model_id=os.environ['MODEL_ID'] +repo_id=os.environ['COMPILED_MODEL_ID'] +local_dir=snapshot_download(repo_id,allow_patterns="tp_*.pt") +max_sequence_length = int(os.environ['MAX_SEQ_LEN']) + +tokenizer = T5Tokenizer.from_pretrained(model_id) +tokenizer.model_max_length = max_sequence_length +model = parallel_model_load(local_dir) + +def gentext(prompt,max_new_tokens): + start_time = time.time() + inputs = tokenizer(promp, return_tensors="pt", truncation=True, padding="max_length", max_length=max_new_tokens) + with torch.no_grad(): + output = model(inputs["input_ids"], inputs["attention_mask"]) + if isinstance(output, dict): + last_hidden_state = output["last_hidden_state"] + else: + last_hidden_state = output + embeddings = last_hidden_state.mean(dim=1).squeeze().to(torch.float32).cpu().numpy() + total_time = time.time()-start_time + return str(embeddings), float(total_time) + +def cw_pub_metric(metric_name,metric_value,metric_unit): + response = cloudwatch.put_metric_data( + Namespace=cw_namespace, + MetricData=[ + { + 'MetricName':metric_name, + 'Value':metric_value, + 'Unit':metric_unit, + }, + ] + ) + print(f"in pub_deployment_counter - response:{response}") + return response + +login(hf_token, add_to_git_credential=True) + +def benchmark(n_runs,test_name,prompt,max_new_tokens): + latency_collector = LatencyCollector() + + for _ in range(n_runs): + latency_collector.pre_hook() + gentext(prompt,max_new_tokens) + res = model.generate(prompt,sampling_params) + latency_collector.hook() + + p0_latency_ms = latency_collector.percentile(0) * 1000 + p50_latency_ms = latency_collector.percentile(50) * 1000 + p90_latency_ms = latency_collector.percentile(90) * 1000 + p95_latency_ms = latency_collector.percentile(95) * 1000 + p99_latency_ms = latency_collector.percentile(99) * 1000 + p100_latency_ms = latency_collector.percentile(100) * 1000 + + report_dict = dict() + report_dict["Latency P0"] = f'{p0_latency_ms:.1f}' + report_dict["Latency P50"]=f'{p50_latency_ms:.1f}' + report_dict["Latency P90"]=f'{p90_latency_ms:.1f}' + report_dict["Latency P95"]=f'{p95_latency_ms:.1f}' + report_dict["Latency P99"]=f'{p99_latency_ms:.1f}' + report_dict["Latency P100"]=f'{p100_latency_ms:.1f}' + + report = f'RESULT FOR {test_name}:' + for key, value in report_dict.items(): + report += f' {key}={value}' + print(report) + return report + +class LatencyCollector: + def __init__(self): + self.start = None + self.latency_list = [] + + def pre_hook(self, *args): + self.start = time.time() + + def hook(self, *args): + self.latency_list.append(time.time() - self.start) + + def percentile(self, percent): + latency_list = self.latency_list + pos_float = len(latency_list) * percent / 100 + max_pos = len(latency_list) - 1 + pos_floor = min(math.floor(pos_float), max_pos) + pos_ceil = min(math.ceil(pos_float), max_pos) + latency_list = sorted(latency_list) + return latency_list[pos_ceil] if pos_float - pos_floor > 0.5 else latency_list[pos_floor] + +class GenerateRequest(BaseModel): + max_new_tokens: int + prompt: str + +class GenerateBenchmarkRequest(BaseModel): + n_runs: int + max_new_tokens: int + prompt: str + +class GenerateResponse(BaseModel): + text: str = Field(..., description="Base64-encoded text") + execution_time: float + +class GenerateBenchmarkResponse(BaseModel): + report: str = Field(..., description="Benchmark report") + +prompt= "What model are you?" +benchmark(10,"warmup",prompt,default_max_new_tokens) +app = FastAPI() + +@app.post("/benchmark",response_model=GenerateBenchmarkResponse) +def generate_benchmark_report(request: GenerateBenchmarkRequest): + print(f'DEBUG: GenerateBenchmarkRequest:{request}') + try: + with torch.no_grad(): + test_name=f'benchmark:{app_name} on {nodepool} with {request.max_new_tokens} output tokens' + response_report=benchmark(request.n_runs,test_name,model,request.prompt,request.max_new_tokens) + report_base64 = base64.b64encode(response_report.encode()).decode() + return GenerateBenchmarkResponse(report=report_base64) + except Exception as e: + traceback.print_exc() + raise HTTPException(status_code=500, detail=f"{e}") + +@app.post("/generate", response_model=GenerateResponse) +def generate_text_post(request: GenerateRequest): + try: + with torch.no_grad(): + response_text,total_time=gentext(request.prompt,request.max_new_tokens) + counter_metric=app_name+'-counter' + cw_pub_metric(counter_metric,1,'Count') + counter_metric=nodepool + cw_pub_metric(counter_metric,1,'Count') + latency_metric=app_name+'-latency' + cw_pub_metric(latency_metric,total_time,'Seconds') + text_base64 = base64.b64encode(response_text.encode()).decode() + return GenerateResponse(text=text_base64, execution_time=total_time) + except Exception as e: + traceback.print_exc() + raise HTTPException(status_code=500, detail=f"text serialization failed: {e}") + +# Health and readiness endpoints +@app.get("/health") +def healthy(): + return {"message": f"{pod_name} is healthy"} + +@app.get("/readiness") +def ready(): + return {"message": f"{pod_name} is ready"} From f551dc9c7514db7458ddf4ce5f645adfb555fca0 Mon Sep 17 00:00:00 2001 From: Yahav Date: Mon, 5 May 2025 11:57:22 -0700 Subject: [PATCH 44/45] compile --- flux_serve/specs/compile.yaml | 72 +++++++++++++++++++++++++++++++++++ 1 file changed, 72 insertions(+) create mode 100644 flux_serve/specs/compile.yaml diff --git a/flux_serve/specs/compile.yaml b/flux_serve/specs/compile.yaml new file mode 100644 index 0000000..2556a4e --- /dev/null +++ b/flux_serve/specs/compile.yaml @@ -0,0 +1,72 @@ +apiVersion: batch/v1 +kind: Job +metadata: + name: compile +spec: + template: + spec: + restartPolicy: OnFailure + nodeSelector: + karpenter.sh/nodepool: amd-neuron-trn1 + #serviceAccountName: appsimulator + schedulerName: my-scheduler + containers: + - name: app + image: 920372998901.dkr.ecr.us-east-1.amazonaws.com/model:amd64-neuron + imagePullPolicy: Always + volumeMounts: + - name: dshm + mountPath: /dev/shm + - name: neuron-bits-use1-pvc + mountPath: /model + command: + - /bin/bash + - "-exc" + - | + set -x + python /download_hf_model.py + find /model -type f -name '*.deb' -exec sh -c ' + for pkg; do + cp "$pkg" / && + apt install -y "/$(basename "$pkg")" + done + ' _ {} + + find /model -type f -name '*.whl' -exec sh -c ' + for pkg; do + cp "$pkg" / && + pip install "/$(basename "$pkg")" + done + ' _ {} + + while true; do sleep 3600; done + resources: + limits: + aws.amazon.com/neuron: 16 + requests: + aws.amazon.com/neuron: 16 + env: + - name: NODEPOOL + value: "amd-neuron-trn1" + - name: COMPILER_WORKDIR_ROOT + value: "/model" + - name: HEIGHT + value: "512" + - name: WIDTH + value: "512" + - name: MAX_SEQ_LEN + value: "32" + - name: GUIDANCE_SCALE + value: "3.5" + - name: MODEL_ID + value: "black-forest-labs/FLUX.1-dev" + - name: HUGGINGFACE_TOKEN + valueFrom: + secretKeyRef: + name: hf-secrets + key: HUGGINGFACE_TOKEN + volumes: + - name: dshm + emptyDir: + medium: Memory + - name: neuron-bits-use1-pvc + persistentVolumeClaim: + claimName: neuron-bits-use1-pvc From c933cb5453359cc98c1e93d52f5def21c9d94ec9 Mon Sep 17 00:00:00 2001 From: Yahav Date: Fri, 23 May 2025 11:50:30 -0700 Subject: [PATCH 45/45] comm --- .../specs/amd-neuron-inf2-nodepool.yaml | 8 +- .../specs/amd-neuron-trn1-nodepool.yaml | 8 +- flux_serve/specs/compile-flux-256x144.yaml | 27 ++--- flux_serve/specs/compile-flux-512x512.yaml | 7 +- flux_serve/specs/cova-gradio-config.yaml | 18 +++ flux_serve/specs/cova-gradio-deploy.yaml | 64 ++++++++++ flux_serve/specs/cova-ingress.yaml | 34 ++++++ .../specs/flux-karpenter-inline-sts.json | 13 +++ flux_serve/specs/flux-model-s3-storage.yaml | 3 +- .../specs/flux-neuron-256x144-model-api.yaml | 18 ++- .../specs/flux-neuron-512x512-model-api.yaml | 20 +++- flux_serve/specs/flux-neuron-gradio.yaml | 6 +- flux_serve/specs/flux-neuron-ingress.yaml | 6 +- .../specs/mllama-32-11b-vllm-trn1-config.yaml | 24 ++++ .../specs/mllama-32-11b-vllm-trn1-deploy.yaml | 110 ++++++++++++++++++ flux_serve/specs/neuron-bits-s3-storage.yaml | 33 ++++++ 16 files changed, 360 insertions(+), 39 deletions(-) create mode 100644 flux_serve/specs/cova-gradio-config.yaml create mode 100644 flux_serve/specs/cova-gradio-deploy.yaml create mode 100644 flux_serve/specs/cova-ingress.yaml create mode 100644 flux_serve/specs/flux-karpenter-inline-sts.json create mode 100644 flux_serve/specs/mllama-32-11b-vllm-trn1-config.yaml create mode 100644 flux_serve/specs/mllama-32-11b-vllm-trn1-deploy.yaml create mode 100644 flux_serve/specs/neuron-bits-s3-storage.yaml diff --git a/flux_serve/specs/amd-neuron-inf2-nodepool.yaml b/flux_serve/specs/amd-neuron-inf2-nodepool.yaml index 151b67d..201eebb 100644 --- a/flux_serve/specs/amd-neuron-inf2-nodepool.yaml +++ b/flux_serve/specs/amd-neuron-inf2-nodepool.yaml @@ -32,14 +32,14 @@ metadata: name: amd-neuron-al2023 spec: amiSelectorTerms: - - alias: "al2023@v20250419" - role: "KarpenterNodeRole-cova" + - alias: "al2023@v20250501" + role: "KarpenterNodeRole-cova-use1" subnetSelectorTerms: - tags: - karpenter.sh/discovery: "cova" + karpenter.sh/discovery: "cova-use1" securityGroupSelectorTerms: - tags: - karpenter.sh/discovery: "cova" + karpenter.sh/discovery: "cova-use1" blockDeviceMappings: - deviceName: /dev/xvda ebs: diff --git a/flux_serve/specs/amd-neuron-trn1-nodepool.yaml b/flux_serve/specs/amd-neuron-trn1-nodepool.yaml index 556fb37..c8176d5 100644 --- a/flux_serve/specs/amd-neuron-trn1-nodepool.yaml +++ b/flux_serve/specs/amd-neuron-trn1-nodepool.yaml @@ -32,14 +32,14 @@ metadata: name: amd-neuron-al2023 spec: amiSelectorTerms: - - alias: "al2023@v20250419" - role: "KarpenterNodeRole-cova" + - alias: "al2023@v20250501" + role: "KarpenterNodeRole-cova-use1" subnetSelectorTerms: - tags: - karpenter.sh/discovery: "cova" + karpenter.sh/discovery: "cova-use1" securityGroupSelectorTerms: - tags: - karpenter.sh/discovery: "cova" + karpenter.sh/discovery: "cova-use1" blockDeviceMappings: - deviceName: /dev/xvda ebs: diff --git a/flux_serve/specs/compile-flux-256x144.yaml b/flux_serve/specs/compile-flux-256x144.yaml index aff6374..5f7b3d1 100644 --- a/flux_serve/specs/compile-flux-256x144.yaml +++ b/flux_serve/specs/compile-flux-256x144.yaml @@ -1,35 +1,36 @@ apiVersion: batch/v1 kind: Job metadata: - name: compile-256x144 + name: compile-256x256 spec: template: spec: restartPolicy: OnFailure nodeSelector: karpenter.sh/nodepool: amd-neuron-trn1 - #serviceAccountName: appsimulator + serviceAccountName: appsimulator schedulerName: my-scheduler containers: - name: app - image: 920372998901.dkr.ecr.us-west-2.amazonaws.com/model:amd64-neuron + image: 891377065549.dkr.ecr.us-west-2.amazonaws.com/model:amd64-neuron + #image: 920372998901.dkr.ecr.us-west-2.amazonaws.com/model:amd64-neuron imagePullPolicy: Always volumeMounts: - name: dshm mountPath: /dev/shm - - name: s3-flux-pvc - mountPath: /model + #- name: s3-flux-pvc + # mountPath: /model command: - /bin/bash - "-exc" - | set -x - mkdir -p /model/256x144 + while true; do sleep 3600; done + mkdir -p /model/256x256 cd /src ./compile.sh - cp -r * /model/256x144 + cp -r * /model/256x256 python /benchmark-flux.py - while true; do sleep 3600; done resources: limits: aws.amazon.com/neuron: 8 @@ -39,11 +40,11 @@ spec: - name: NODEPOOL value: "amd-neuron-trn1" - name: COMPILER_WORKDIR_ROOT - value: "/model/256x144" + value: "/model/256x256" - name: HEIGHT value: "256" - name: WIDTH - value: "144" + value: "256" - name: MAX_SEQ_LEN value: "32" - name: GUIDANCE_SCALE @@ -59,6 +60,6 @@ spec: - name: dshm emptyDir: medium: Memory - - name: s3-flux-pvc - persistentVolumeClaim: - claimName: s3-flux-pvc + #- name: s3-flux-pvc + # persistentVolumeClaim: + # claimName: s3-flux-pvc diff --git a/flux_serve/specs/compile-flux-512x512.yaml b/flux_serve/specs/compile-flux-512x512.yaml index 29c8220..1572338 100644 --- a/flux_serve/specs/compile-flux-512x512.yaml +++ b/flux_serve/specs/compile-flux-512x512.yaml @@ -12,7 +12,8 @@ spec: schedulerName: my-scheduler containers: - name: app - image: 920372998901.dkr.ecr.us-west-2.amazonaws.com/model:amd64-neuron + #image: 891377065549.dkr.ecr.us-west-2.amazonaws.com/model:amd64-neuron + image: 920372998901.dkr.ecr.us-east-1.amazonaws.com/model:amd64-neuron imagePullPolicy: Always volumeMounts: - name: dshm @@ -32,9 +33,9 @@ spec: while true; do sleep 3600; done resources: limits: - aws.amazon.com/neuron: 6 + aws.amazon.com/neuron: 16 requests: - aws.amazon.com/neuron: 6 + aws.amazon.com/neuron: 16 env: - name: NODEPOOL value: "amd-neuron-trn1" diff --git a/flux_serve/specs/cova-gradio-config.yaml b/flux_serve/specs/cova-gradio-config.yaml new file mode 100644 index 0000000..6b34cbb --- /dev/null +++ b/flux_serve/specs/cova-gradio-config.yaml @@ -0,0 +1,18 @@ +apiVersion: v1 +kind: ConfigMap +metadata: + name: cova-gradio-config +data: + models.json: | + [ + { + "name": "512 Ɨ 512", + "host_env": "FLUX_NEURON_512X512_MODEL_API_SERVICE_HOST", + "port_env": "FLUX_NEURON_512X512_MODEL_API_SERVICE_PORT", + "height": 512, + "width": 512, + "caption_host_env": "MLLAMA_32_11B_VLLM_TRN1_SERVICE_HOST", + "caption_port_env": "MLLAMA_32_11B_VLLM_TRN1_SERVICE_PORT", + "caption_max_new_tokens": 1024 + } + ] diff --git a/flux_serve/specs/cova-gradio-deploy.yaml b/flux_serve/specs/cova-gradio-deploy.yaml new file mode 100644 index 0000000..c84d003 --- /dev/null +++ b/flux_serve/specs/cova-gradio-deploy.yaml @@ -0,0 +1,64 @@ +apiVersion: v1 +kind: Service +metadata: + name: cova-gradio +spec: + selector: + app: cova-gradio + ports: + - protocol: TCP + port: 8000 + targetPort: 8000 + type: ClusterIP +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + labels: + app: cova-gradio + name: cova-gradio +spec: + selector: + matchLabels: + app: cova-gradio + template: + metadata: + labels: + app: cova-gradio + spec: + nodeSelector: + alpha.eksctl.io/nodegroup-name: kub316-ng + #serviceAccountName: appsimulator + containers: + - name: app + image: 891377065549.dkr.ecr.us-west-2.amazonaws.com/model:amd64-neuron + #image: 920372998901.dkr.ecr.us-west-2.amazonaws.com/model:amd64-neuron + imagePullPolicy: Always + volumeMounts: + - name: cova-gradio-volume + mountPath: /app + #command: ["sh", "-c", "while true; do sleep 3600; done"] + command: ["sh", "-c", "uvicorn cova_gradio_m:app --host=0.0.0.0"] + ports: + - containerPort: 8000 + protocol: TCP + readinessProbe: + httpGet: + path: /readiness + port: 8000 + initialDelaySeconds: 60 + periodSeconds: 10 + env: + - name: MODELS_FILE_PATH + value: "/app/models.json" + - name: POD_NAME + valueFrom: + fieldRef: + fieldPath: metadata.name + volumes: + - name: cova-gradio-volume + configMap: + name: cova-gradio-config + items: + - key: models.json + path: models.json diff --git a/flux_serve/specs/cova-ingress.yaml b/flux_serve/specs/cova-ingress.yaml new file mode 100644 index 0000000..928c6d7 --- /dev/null +++ b/flux_serve/specs/cova-ingress.yaml @@ -0,0 +1,34 @@ +apiVersion: networking.k8s.io/v1 +kind: Ingress +metadata: + name: cova + annotations: + kubernetes.io/ingress.class: alb + alb.ingress.kubernetes.io/scheme: internet-facing + alb.ingress.kubernetes.io/target-type: ip + alb.ingress.kubernetes.io/healthcheck-path: /health + alb.ingress.kubernetes.io/healthcheck-interval-seconds: '10' + alb.ingress.kubernetes.io/healthcheck-timeout-seconds: '9' + alb.ingress.kubernetes.io/healthy-threshold-count: '2' + alb.ingress.kubernetes.io/unhealthy-threshold-count: '10' + alb.ingress.kubernetes.io/success-codes: '200-301' + alb.ingress.kubernetes.io/listen-ports: '[{"HTTP":80}]' + alb.ingress.kubernetes.io/backend-protocol: HTTP + alb.ingress.kubernetes.io/target-group-attributes: stickiness.enabled=true,stickiness.lb_cookie.duration_seconds=10 + alb.ingress.kubernetes.io/load-balancer-name: cova + alb.ingress.kubernetes.io/actions.weighted-routing: > + {"type":"forward","forwardConfig":{"targetGroups":[{"serviceName":"cova-gradio","servicePort":8000,"weight":100}],"targetGroupStickinessConfig":{"enabled":true,"durationSeconds":200}}} + labels: + app: cova-neuron-gradio +spec: + ingressClassName: alb + rules: + - http: + paths: + - path: / + pathType: Prefix + backend: + service: + name: weighted-routing + port: + name: use-annotation diff --git a/flux_serve/specs/flux-karpenter-inline-sts.json b/flux_serve/specs/flux-karpenter-inline-sts.json new file mode 100644 index 0000000..7642272 --- /dev/null +++ b/flux_serve/specs/flux-karpenter-inline-sts.json @@ -0,0 +1,13 @@ +{ + "Version": "2012-10-17", + "Statement": [ + { + "Effect": "Allow", + "Action": [ + "sts:AssumeRole", + "sts:AssumeRoleWithWebIdentity" + ], + "Resource": "*" + } + ] +} diff --git a/flux_serve/specs/flux-model-s3-storage.yaml b/flux_serve/specs/flux-model-s3-storage.yaml index 0d4471a..884eb75 100644 --- a/flux_serve/specs/flux-model-s3-storage.yaml +++ b/flux_serve/specs/flux-model-s3-storage.yaml @@ -17,7 +17,8 @@ spec: driver: s3.csi.aws.com volumeHandle: s3-csi-driver-volume volumeAttributes: - bucketName: flux1-dev-neuron + bucketName: flux1-dev-neuron2 + #bucketName: flux1-dev-neuron --- apiVersion: v1 kind: PersistentVolumeClaim diff --git a/flux_serve/specs/flux-neuron-256x144-model-api.yaml b/flux_serve/specs/flux-neuron-256x144-model-api.yaml index 1f80515..1ada152 100644 --- a/flux_serve/specs/flux-neuron-256x144-model-api.yaml +++ b/flux_serve/specs/flux-neuron-256x144-model-api.yaml @@ -28,18 +28,30 @@ spec: spec: nodeSelector: karpenter.sh/nodepool: amd-neuron-inf2 - serviceAccountName: flux-serviceaccount + serviceAccountName: appsimulator + #serviceAccountName: flux-serviceaccount schedulerName: my-scheduler containers: - name: app - image: 920372998901.dkr.ecr.us-west-2.amazonaws.com/model:amd64-neuron + image: 891377065549.dkr.ecr.us-west-2.amazonaws.com/model:amd64-neuron + #image: 920372998901.dkr.ecr.us-west-2.amazonaws.com/model:amd64-neuron imagePullPolicy: Always volumeMounts: - name: dshm mountPath: /dev/shm - name: s3-flux-pvc mountPath: /model - command: ["sh", "-c", "uvicorn flux_model_api:app --host=0.0.0.0"] + command: + - /bin/bash + - "-exc" + - | + set -x + pip install --upgrade pip + pip config set global.extra-index-url https://pip.repos.neuron.amazonaws.com + pip install --upgrade "neuronx-distributed==0.11.0" --extra-index-url https://pip.repos.neuron.amazonaws.com + pip install --upgrade "neuronx-distributed-inference>=0.2.0" --extra-index-url https://pip.repos.neuron.amazonaws.com + pip install --upgrade tenacity diffusers + uvicorn flux_model_api:app --host=0.0.0.0 resources: requests: aws.amazon.com/neuron: 6 diff --git a/flux_serve/specs/flux-neuron-512x512-model-api.yaml b/flux_serve/specs/flux-neuron-512x512-model-api.yaml index ed2935e..a2cc706 100644 --- a/flux_serve/specs/flux-neuron-512x512-model-api.yaml +++ b/flux_serve/specs/flux-neuron-512x512-model-api.yaml @@ -29,9 +29,11 @@ spec: nodeSelector: karpenter.sh/nodepool: amd-neuron-inf2 serviceAccountName: flux-serviceaccount + #serviceAccountName: appsimulator schedulerName: my-scheduler containers: - name: app + #image: 891377065549.dkr.ecr.us-west-2.amazonaws.com/model:amd64-neuron image: 920372998901.dkr.ecr.us-west-2.amazonaws.com/model:amd64-neuron imagePullPolicy: Always volumeMounts: @@ -39,12 +41,22 @@ spec: mountPath: /dev/shm - name: s3-flux-pvc mountPath: /model - command: ["sh", "-c", "uvicorn flux_model_api:app --host=0.0.0.0"] + command: + - /bin/bash + - "-exc" + - | + set -x + pip install --upgrade pip + pip config set global.extra-index-url https://pip.repos.neuron.amazonaws.com + pip install --upgrade "neuronx-distributed==0.11.0" --extra-index-url https://pip.repos.neuron.amazonaws.com + pip install --upgrade "neuronx-distributed-inference>=0.2.0" --extra-index-url https://pip.repos.neuron.amazonaws.com + pip install --upgrade tenacity diffusers + uvicorn flux_model_api:app --host=0.0.0.0 resources: requests: - aws.amazon.com/neuron: 6 + aws.amazon.com/neuron: 8 limits: - aws.amazon.com/neuron: 6 + aws.amazon.com/neuron: 8 ports: - containerPort: 8000 protocol: TCP @@ -52,7 +64,7 @@ spec: httpGet: path: /readiness port: 8000 - initialDelaySeconds: 60 + initialDelaySeconds: 460 periodSeconds: 10 env: - name: APP diff --git a/flux_serve/specs/flux-neuron-gradio.yaml b/flux_serve/specs/flux-neuron-gradio.yaml index e7ef5e8..843c348 100644 --- a/flux_serve/specs/flux-neuron-gradio.yaml +++ b/flux_serve/specs/flux-neuron-gradio.yaml @@ -27,14 +27,14 @@ spec: app: flux-neuron-gradio spec: nodeSelector: - alpha.eksctl.io/nodegroup-name: flux-usw2-ng + alpha.eksctl.io/nodegroup-name: cova-ng #serviceAccountName: appsimulator containers: - name: app image: 920372998901.dkr.ecr.us-west-2.amazonaws.com/model:amd64-neuron imagePullPolicy: Always #command: ["sh", "-c", "while true; do sleep 3600; done"] - command: ["sh", "-c", "uvicorn flux_gradio:app --host=0.0.0.0"] + command: ["sh", "-c", "uvicorn cova_gradio:app --host=0.0.0.0"] ports: - containerPort: 8000 protocol: TCP @@ -45,8 +45,6 @@ spec: initialDelaySeconds: 60 periodSeconds: 10 env: - - name: MODEL_ID - value: "black-forest-labs/FLUX.1-dev" - name: POD_NAME valueFrom: fieldRef: diff --git a/flux_serve/specs/flux-neuron-ingress.yaml b/flux_serve/specs/flux-neuron-ingress.yaml index b27e4f0..d81c8a2 100644 --- a/flux_serve/specs/flux-neuron-ingress.yaml +++ b/flux_serve/specs/flux-neuron-ingress.yaml @@ -1,7 +1,7 @@ apiVersion: networking.k8s.io/v1 kind: Ingress metadata: - name: flux-neuron + name: cova annotations: kubernetes.io/ingress.class: alb alb.ingress.kubernetes.io/scheme: internet-facing @@ -15,11 +15,11 @@ metadata: alb.ingress.kubernetes.io/listen-ports: '[{"HTTP":80}]' alb.ingress.kubernetes.io/backend-protocol: HTTP alb.ingress.kubernetes.io/target-group-attributes: stickiness.enabled=true,stickiness.lb_cookie.duration_seconds=10 - alb.ingress.kubernetes.io/load-balancer-name: flux-neuron + alb.ingress.kubernetes.io/load-balancer-name: cova alb.ingress.kubernetes.io/actions.weighted-routing: > {"type":"forward","forwardConfig":{"targetGroups":[{"serviceName":"flux-neuron-gradio","servicePort":8000,"weight":100}],"targetGroupStickinessConfig":{"enabled":true,"durationSeconds":200}}} labels: - app: flux-neuron-gradio + app: cova-neuron-gradio spec: ingressClassName: alb rules: diff --git a/flux_serve/specs/mllama-32-11b-vllm-trn1-config.yaml b/flux_serve/specs/mllama-32-11b-vllm-trn1-config.yaml new file mode 100644 index 0000000..adbed23 --- /dev/null +++ b/flux_serve/specs/mllama-32-11b-vllm-trn1-config.yaml @@ -0,0 +1,24 @@ +--- +apiVersion: v1 +kind: ConfigMap +metadata: + name: mllama-32-11b-vllm-trn1-config +data: + vllm_config.yaml: | + model: "yahavb/Llama-3.2-11B-Vision-Instruct-neuron-checkpoint" + tensor_parallel_size: 32 + max_num_seqs: 1 + block_size: 4096 + max_model_len: 128000 + override_neuron_config: + skip_warmup: true + context_encoding_buckets: [1024, 16384] + token_generation_buckets: [1024, 16384] + sequence_parallel_enabled: False + is_continuous_batching: True + on_device_sampling_config: + global_topk: 64 + dynamic: True + deterministic: False + device: "neuron" +--- diff --git a/flux_serve/specs/mllama-32-11b-vllm-trn1-deploy.yaml b/flux_serve/specs/mllama-32-11b-vllm-trn1-deploy.yaml new file mode 100644 index 0000000..2837eea --- /dev/null +++ b/flux_serve/specs/mllama-32-11b-vllm-trn1-deploy.yaml @@ -0,0 +1,110 @@ +apiVersion: v1 +kind: Service +metadata: + name: mllama-32-11b-vllm-trn1 +spec: + selector: + app: mllama-32-11b-vllm-trn1 + ports: + - port: 8000 + targetPort: 8000 + type: NodePort +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + labels: + app: mllama-32-11b-vllm-trn1 + name: mllama-32-11b-vllm-trn1 +spec: + selector: + matchLabels: + app: mllama-32-11b-vllm-trn1 + template: + metadata: + labels: + app: mllama-32-11b-vllm-trn1 + spec: + nodeSelector: + karpenter.sh/nodepool: amd-neuron-trn1 + serviceAccountName: appsimulator + #serviceAccountName: flux-serviceaccount + schedulerName: my-scheduler + volumes: + - name: dshm + emptyDir: + medium: Memory + containers: + - name: app + image: 891377065549.dkr.ecr.us-west-2.amazonaws.com/model:amd64-neuron + #image: 920372998901.dkr.ecr.us-west-2.amazonaws.com/model:amd64-neuron + imagePullPolicy: Always + volumeMounts: + - mountPath: /vllm_config.yaml + name: vllm-config-volume + subPath: vllm_config.yaml + - mountPath: /dev/shm + name: dshm + command: + - /bin/bash + - "-exc" + - | + set -x + pip install --upgrade pip + pip config set global.extra-index-url https://pip.repos.neuron.amazonaws.com + pip install --upgrade "neuronx-distributed==0.11.0" --extra-index-url https://pip.repos.neuron.amazonaws.com + pip install --upgrade "neuronx-distributed-inference>=0.2.0" --extra-index-url https://pip.repos.neuron.amazonaws.com + pip install --upgrade transformers accelerate protobuf sentence_transformers tenacity torch-neuron + git clone -b neuron-2.22-vllm-v0.7.2 https://github.com/aws-neuron/upstreaming-to-vllm.git + cd upstreaming-to-vllm + pip install -r requirements-neuron.txt + VLLM_TARGET_DEVICE="neuron" pip install -e . + cd / + python /download_hf_model.py + #python /mllama-offline.py + uvicorn vllm_model_api_m:app --host=0.0.0.0 + resources: + requests: + aws.amazon.com/neuron: 16 + limits: + aws.amazon.com/neuron: 16 + env: + - name: VLLM_NEURON_FRAMEWORK + value: "neuronx-distributed-inference" + - name: MODEL_ID + value: "yahavb/Llama-3.2-11B-Vision-Instruct" + - name: APP + value: "Llama-3.2-11B-Vision-Instruct-NxDI-TRN1" + - name: NODEPOOL + value: "amd-neuron-trn1" + - name: POD_NAME + valueFrom: + fieldRef: + fieldPath: metadata.name + - name: HUGGINGFACE_TOKEN + valueFrom: + secretKeyRef: + name: hf-secrets + key: HUGGINGFACE_TOKEN + - name: MAX_NEW_TOKENS + value: "50" + ports: + - containerPort: 8000 + protocol: TCP + readinessProbe: + failureThreshold: 3 + httpGet: + path: /readiness + port: 8000 + scheme: HTTP + initialDelaySeconds: 280 + periodSeconds: 10 + successThreshold: 1 + timeoutSeconds: 5 + volumes: + - name: vllm-config-volume + configMap: + name: mllama-32-11b-vllm-trn1-config + - name: dshm + emptyDir: + medium: Memory diff --git a/flux_serve/specs/neuron-bits-s3-storage.yaml b/flux_serve/specs/neuron-bits-s3-storage.yaml new file mode 100644 index 0000000..c26379b --- /dev/null +++ b/flux_serve/specs/neuron-bits-s3-storage.yaml @@ -0,0 +1,33 @@ +apiVersion: v1 +kind: PersistentVolume +metadata: + name: neuron-bits-use1-pv +spec: + capacity: + storage: 1200Gi + accessModes: + - ReadWriteMany + storageClassName: "" + claimRef: + namespace: default + name: neuron-bits-use1-pvc + mountOptions: + - region=us-east-1 + csi: + driver: s3.csi.aws.com + volumeHandle: s3-csi-driver-volume + volumeAttributes: + bucketName: neuron-bits-use1 +--- +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: neuron-bits-use1-pvc +spec: + accessModes: + - ReadWriteMany # Supported options: ReadWriteMany / ReadOnlyMany + storageClassName: "" # Required for static provisioning + resources: + requests: + storage: 1200Gi + volumeName: neuron-bits-use1-pv