mirror of
https://github.com/GoogleCloudPlatform/vertex-ai-samples.git
synced 2026-09-26 14:42:04 +00:00
Peft docker fix (#3751)
* Updated util files to fix peft docker * fix imports * fix imports fileutils.py
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
"""Common utility lib for prediction on images."""
|
||||
|
||||
from typing import Any, Dict, List
|
||||
from typing import Any, Dict, List, Tuple
|
||||
|
||||
import numpy as np
|
||||
from PIL import Image
|
||||
@@ -10,6 +10,28 @@ import yaml
|
||||
from util import image_format_converter
|
||||
|
||||
|
||||
def convert_list_to_label_map(
|
||||
input_list: List[str],
|
||||
) -> Tuple[Dict[str, Dict[int, str]], List[int]]:
|
||||
"""Converts a list of labels to a dictionary and numerical encoding.
|
||||
|
||||
Args:
|
||||
input_list: A list of strings representing class labels.
|
||||
|
||||
Returns:
|
||||
A tuple containing:
|
||||
label_map: A dictionary mapping unique labels to integer indices.
|
||||
encoded_list: A list of integers corresponding to the labels in the input
|
||||
list.
|
||||
"""
|
||||
unique_labels = set(input_list)
|
||||
label_map_reverse = {label: idx for idx, label in enumerate(unique_labels)}
|
||||
label_map = {idx: label for idx, label in enumerate(unique_labels)}
|
||||
encoded_list = [label_map_reverse[label] for label in input_list]
|
||||
|
||||
return {"label_map": label_map}, encoded_list
|
||||
|
||||
|
||||
def get_prediction_instances(image: Image.Image) -> List[Dict[str, Any]]:
|
||||
"""Gets prediction instances.
|
||||
|
||||
@@ -40,14 +62,14 @@ def get_label_map(label_map_yaml_filepath: str) -> Dict[str, Any]:
|
||||
|
||||
|
||||
def get_object_detection_endpoint_predictions(
|
||||
detection_endpoint: ...,
|
||||
detector_endpoint: ...,
|
||||
input_image: np.ndarray,
|
||||
detection_thresh: float = 0.2,
|
||||
) -> np.ndarray:
|
||||
"""Gets endpoint predictions.
|
||||
|
||||
Args:
|
||||
detection_endpoint: image object detection endpoint.
|
||||
detector_endpoint: image object detection endpoint.
|
||||
input_image: Input image.
|
||||
detection_thresh: Detection threshold.
|
||||
|
||||
@@ -55,9 +77,10 @@ def get_object_detection_endpoint_predictions(
|
||||
Object detection predictions from endpoints.
|
||||
"""
|
||||
height, width, _ = input_image.shape
|
||||
predictions = detection_endpoint.predict(
|
||||
predictions = detector_endpoint.predict(
|
||||
get_prediction_instances(Image.fromarray(input_image))
|
||||
).predictions
|
||||
|
||||
detection_scores = np.array(predictions[0]["detection_scores"])
|
||||
detection_classes = np.array(predictions[0]["detection_classes"])
|
||||
detection_boxes = np.array(
|
||||
@@ -66,6 +89,29 @@ def get_object_detection_endpoint_predictions(
|
||||
for b in predictions[0]["detection_boxes"]
|
||||
]
|
||||
)
|
||||
return merge_boxes_and_classes(
|
||||
detection_scores, detection_boxes, detection_classes, detection_thresh
|
||||
)
|
||||
|
||||
|
||||
def merge_boxes_and_classes(
|
||||
detection_scores: np.ndarray,
|
||||
detection_boxes: np.ndarray,
|
||||
detection_classes: np.ndarray,
|
||||
detection_thresh: float = 0.2,
|
||||
) -> np.ndarray:
|
||||
"""Merges prediction boxes and classes.
|
||||
|
||||
Args:
|
||||
detection_scores: array of detection scores.
|
||||
detection_boxes: array of detection boxes.
|
||||
detection_classes: array of detection classes.
|
||||
detection_thresh: float indicating the detection threshold.
|
||||
|
||||
Returns:
|
||||
preds_merge_cls: a numpy array containing the detection boxes, scores and
|
||||
classes.
|
||||
"""
|
||||
thresh_indices = [
|
||||
x for x, val in enumerate(detection_scores) if val > detection_thresh
|
||||
]
|
||||
@@ -76,4 +122,5 @@ def get_object_detection_endpoint_predictions(
|
||||
preds_merge_cls = np.column_stack(
|
||||
(preds_merge_conf, detection_classes[thresh_indices])
|
||||
)
|
||||
|
||||
return preds_merge_cls
|
||||
|
||||
@@ -36,6 +36,12 @@ BEST_CKPT_METRIC_COMP = 'higher'
|
||||
|
||||
# Reported hyperparameter tuning metric tag.
|
||||
HP_METRIC_TAG = 'model_performance'
|
||||
HP_LOSS_TAG = 'model_loss'
|
||||
|
||||
# Reported places.
|
||||
REPORT_TO_NONE = 'none'
|
||||
REPORT_TO_WANDB = 'wandb'
|
||||
REPORT_TO_TENSORBOARD = 'tensorboard'
|
||||
|
||||
# HPT trial prefix.
|
||||
TRIAL_PREFIX = 'trial_'
|
||||
@@ -45,7 +51,7 @@ ML_USE_TRAINING = 'training'
|
||||
ML_USE_VALIDATION = 'validation'
|
||||
ML_USE_TEST = 'test'
|
||||
|
||||
# COCO json keys
|
||||
# COCO json keys.
|
||||
COCO_JSON_ANNOTATIONS = 'annotations'
|
||||
COCO_JSON_ANNOTATION_IMAGE_ID = 'image_id'
|
||||
COCO_JSON_ANNOTATION_CATEGORY_ID = 'category_id'
|
||||
@@ -60,36 +66,88 @@ COCO_JSON_IMAGE_HEIGHT = 'height'
|
||||
COCO_JSON_IMAGE_COCO_URL = 'coco_url'
|
||||
COCO_ANNOTATION_BBOX = 'bbox'
|
||||
|
||||
# GCS prefixes
|
||||
# GCS prefixes.
|
||||
GCS_URI_PREFIX = 'gs://'
|
||||
GCSFUSE_URI_PREFIX = '/gcs/'
|
||||
|
||||
LOCAL_EVALUATION_RESULT_DIR = '/tmp/evaluation_result_dir'
|
||||
LOCAL_MODEL_DIR = '/tmp/model_dir'
|
||||
LOCAL_LORA_DIR = '/tmp/lora_dir'
|
||||
LOCAL_BASE_MODEL_DIR = '/tmp/base_model_dir'
|
||||
LOCAL_DATA_DIR = '/tmp/data'
|
||||
LOCAL_OUTPUT_DIR = '/tmp/output_dir'
|
||||
LOCAL_PREDICTION_RESULT_DIR = '/tmp/prediction_result_dir'
|
||||
SHARED_MEM_DIR = '/dev/shm'
|
||||
|
||||
# Huggingface files.
|
||||
HF_MODEL_WEIGHTS_SUFFIX = '.bin'
|
||||
|
||||
# PEFT finetuning constants.
|
||||
TEXT_TO_IMAGE = 'text-to-image'
|
||||
TEXT_TO_IMAGE_LORA = 'text-to-image-lora'
|
||||
TEXT_TO_IMAGE_DREAMBOOTH = 'text-to-image-dreambooth'
|
||||
TEXT_TO_IMAGE_DREAMBOOTH_LORA = 'text-to-image-dreambooth-lora'
|
||||
TEXT_TO_IMAGE_DREAMBOOTH_LORA_SDXL = 'text-to-image-dreambooth-lora-sdxl'
|
||||
SEQUENCE_CLASSIFICATION_LORA = 'sequence-classification-lora'
|
||||
CAUSAL_LANGUAGE_MODELING_LORA = 'causal-language-modeling-lora'
|
||||
MERGE_CAUSAL_LANGUAGE_MODEL_LORA = 'merge-causal-language-model-lora'
|
||||
QUANTIZE_MODEL = 'quantize-model'
|
||||
INSTRUCT_LORA = 'instruct-lora'
|
||||
CAUSAL_LANGUAGE_MODELING_LORA_TARGET_MODULES = [
|
||||
"q_proj",
|
||||
"v_proj",
|
||||
]
|
||||
INSTRUCT_LORA_TARGET_MODULES = [
|
||||
"query_key_value",
|
||||
"dense",
|
||||
"dense_h_to_4h",
|
||||
"dense_4h_to_h",
|
||||
]
|
||||
VALIDATE_DATASET_WITH_TEMPLATE = 'validate-dataset-with-template'
|
||||
DEFAULT_TEXT_COLUMN_IN_DATASET = 'quote'
|
||||
DEFAULT_TEXT_COLUMN_IN_QUANTIZATION_DATASET = 'text'
|
||||
DEFAULT_INSTRUCT_COLUMN_IN_DATASET = 'text'
|
||||
|
||||
FINAL_CHECKPOINT_DIRNAME = 'checkpoint-final'
|
||||
|
||||
# ImageBind inference constants.
|
||||
FEATURE_EMBEDDING_GENERATION = 'feature-embedding-generation'
|
||||
ZERO_SHOT_CLASSIFICATION = 'zero-shot-classification'
|
||||
|
||||
# Precision modes for loading model weights.
|
||||
PRECISION_MODE_2 = '2bit'
|
||||
PRECISION_MODE_3 = '3bit'
|
||||
PRECISION_MODE_4 = '4bit'
|
||||
PRECISION_MODE_8 = '8bit'
|
||||
PRECISION_MODE_FP8 = 'float8' # to use fbgemm_fp8 quantization
|
||||
PRECISION_MODE_16 = 'float16'
|
||||
PRECISION_MODE_16B = 'bfloat16'
|
||||
PRECISION_MODE_32 = 'float32'
|
||||
|
||||
# Quantization modes.
|
||||
GPTQ = 'gptq'
|
||||
AWQ = 'awq'
|
||||
|
||||
# AWQ versions.
|
||||
GEMM = 'GEMM'
|
||||
GEMV = 'GEMV'
|
||||
|
||||
# Environment variable keys.
|
||||
PRIVATE_BUCKET_ENV_KEY = 'AIP_PRIVATE_BUCKET_NAME'
|
||||
|
||||
# Kfp pipeline constants.
|
||||
TFVISION_TRAIN_OUTPUT_ARTIFACT_NAME = 'checkpoint_dir'
|
||||
|
||||
# Vertex IOD type.
|
||||
AUTOML = 'AUTOML'
|
||||
MODEL_GARDEN = 'MODEL_GARDEN'
|
||||
|
||||
# LRU Disk Cache constants.
|
||||
MD5_HASHMAP_FILENAME = 'md5_hashmap.json'
|
||||
|
||||
# Prediction request keys.
|
||||
PREDICT_INSTANCE_KEY = 'instances'
|
||||
PREDICT_INSTANCE_IMAGE_KEY = 'image'
|
||||
PREDICT_INSTANCE_POSE_IMAGE_KEY = 'pose_image'
|
||||
PREDICT_INSTANCE_TEXT_KEY = 'text'
|
||||
PREDICT_INSTANCE_PROMPT_KEY = 'prompt'
|
||||
|
||||
PREDICT_PARAMETERS_KEY = 'parameters'
|
||||
PREDICT_PARAMETERS_NUM_INFERENCE_STEPS_KEY = 'num_inference_steps'
|
||||
PREDICT_PARAMETERS_HEIGHT_KEY = 'height'
|
||||
PREDICT_PARAMETERS_WIDTH_KEY = 'width'
|
||||
PREDICT_PARAMETERS_GUIDANCE_SCALE_KEY = 'guidance_scale'
|
||||
PREDICT_PARAMETERS_NEGATIVE_PROMPT_KEY = 'negative_prompt'
|
||||
PREDICT_PARAMETERS_LORA_ID_KEY = 'lora_id'
|
||||
PREDICT_PARAMETERS_IGNORE_LORA_CACHE_KEY = 'ignore_lora_cache'
|
||||
|
||||
PREDICT_OUTPUT_KEY = 'output'
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
"""Fileutil lib to copy files between gcs and local."""
|
||||
|
||||
import glob
|
||||
import fnmatch
|
||||
import os
|
||||
import pathlib
|
||||
import shutil
|
||||
from typing import Tuple
|
||||
from typing import List, Optional, Tuple
|
||||
import uuid
|
||||
|
||||
from absl import logging
|
||||
@@ -13,6 +13,17 @@ from google.cloud import storage
|
||||
from util import constants
|
||||
|
||||
|
||||
_GCS_CLIENT = None
|
||||
|
||||
|
||||
def _get_gcs_client() -> storage.Client:
|
||||
"""Gets the default GCS client."""
|
||||
global _GCS_CLIENT
|
||||
if _GCS_CLIENT is None:
|
||||
_GCS_CLIENT = storage.Client()
|
||||
return _GCS_CLIENT
|
||||
|
||||
|
||||
def generate_tmp_path(extension: str = '') -> str:
|
||||
"""Generates a temporary file path with UUID.
|
||||
|
||||
@@ -36,6 +47,16 @@ def force_gcs_fuse_path(gcs_uri: str) -> str:
|
||||
return gcs_uri
|
||||
|
||||
|
||||
def force_gcs_path(uri: str) -> str:
|
||||
"""Converts /gcs/ uris to their gs:// equivalents. No-op for other uris."""
|
||||
if uri.startswith(constants.GCSFUSE_URI_PREFIX):
|
||||
return uri.replace(
|
||||
constants.GCSFUSE_URI_PREFIX, constants.GCS_URI_PREFIX, 1
|
||||
)
|
||||
else:
|
||||
return uri
|
||||
|
||||
|
||||
def download_gcs_file_to_local_dir(gcs_uri: str, local_dir: str):
|
||||
"""Download a gcs file to a local dir.
|
||||
|
||||
@@ -62,15 +83,47 @@ def download_gcs_file_to_local(gcs_uri: str, local_path: str):
|
||||
raise ValueError(
|
||||
f'{gcs_uri} is not a GCS path starting with {constants.GCS_URI_PREFIX}.'
|
||||
)
|
||||
client = storage.Client()
|
||||
client = _get_gcs_client()
|
||||
os.makedirs(os.path.dirname(local_path), exist_ok=True)
|
||||
with open(local_path, 'wb') as f:
|
||||
client.download_blob_to_file(gcs_uri, f)
|
||||
|
||||
|
||||
def download_gcs_file_list_to_local(
|
||||
gcs_uri_list: List[str], local_dir: str
|
||||
) -> List[str]:
|
||||
"""Downloads a list of GCS files to a local directory.
|
||||
|
||||
Args:
|
||||
gcs_uri_list: A list of GCS file paths.
|
||||
local_dir: Local directory in which the GCS files are saved.
|
||||
|
||||
Returns:
|
||||
The local file paths corresponding to the input GCS file paths.
|
||||
|
||||
Raises:
|
||||
ValueError: An input file path is not a GCS path.
|
||||
"""
|
||||
local_paths = []
|
||||
for gcs_uri in gcs_uri_list:
|
||||
if not is_gcs_path(gcs_uri):
|
||||
raise ValueError(
|
||||
f'{gcs_uri} is not a GCS path starting with'
|
||||
f' {constants.GCS_URI_PREFIX}.'
|
||||
)
|
||||
local_path = os.path.join(local_dir, gcs_uri.replace('gs://', ''))
|
||||
download_gcs_file_to_local(gcs_uri, local_path)
|
||||
local_paths.append(local_path)
|
||||
return local_paths
|
||||
|
||||
|
||||
def download_gcs_dir_to_local(
|
||||
gcs_dir: str, local_dir: str, skip_hf_model_bin: bool = False
|
||||
):
|
||||
gcs_dir: str,
|
||||
local_dir: str,
|
||||
skip_hf_model_bin: bool = False,
|
||||
allow_patterns: Optional[List[str]] = None,
|
||||
log: bool = True,
|
||||
) -> None:
|
||||
"""Downloads files in a GCS directory to a local directory.
|
||||
|
||||
For example:
|
||||
@@ -78,16 +131,21 @@ def download_gcs_dir_to_local(
|
||||
gs://bucket/foo/a -> /tmp/bar/a
|
||||
gs://bucket/foo/b/c -> /tmp/bar/b/c
|
||||
|
||||
Arguments:
|
||||
Args:
|
||||
gcs_dir: A string of directory path on GCS.
|
||||
local_dir: A string of local directory path.
|
||||
skip_hf_model_bin: True to skip downloading HF model bin files.
|
||||
allow_patterns: A list of allowed patterns. If provided, only files matching
|
||||
one or more patterns are downloaded.
|
||||
log: True to log each downloaded file.
|
||||
"""
|
||||
if not is_gcs_path(gcs_dir):
|
||||
raise ValueError(f'{gcs_dir} is not a GCS path starting with gs://.')
|
||||
bucket_name = gcs_dir.split('/')[2]
|
||||
prefix = gcs_dir[len(constants.GCS_URI_PREFIX + bucket_name) :].strip('/')
|
||||
client = storage.Client()
|
||||
prefix = (
|
||||
gcs_dir[len(constants.GCS_URI_PREFIX + bucket_name) :].strip('/') + '/'
|
||||
)
|
||||
client = _get_gcs_client()
|
||||
blobs = client.list_blobs(bucket_name, prefix=prefix)
|
||||
for blob in blobs:
|
||||
if blob.name[-1] == '/':
|
||||
@@ -95,43 +153,63 @@ def download_gcs_dir_to_local(
|
||||
file_path = blob.name[len(prefix) :].strip('/')
|
||||
local_file_path = os.path.join(local_dir, file_path)
|
||||
os.makedirs(os.path.dirname(local_file_path), exist_ok=True)
|
||||
if allow_patterns and all(
|
||||
[not fnmatch.fnmatch(file_path, p) for p in allow_patterns]
|
||||
):
|
||||
continue
|
||||
if (
|
||||
file_path.endswith(constants.HF_MODEL_WEIGHTS_SUFFIX)
|
||||
and skip_hf_model_bin
|
||||
):
|
||||
logging.info('Skip downloading model bin %s', file_path)
|
||||
if log:
|
||||
logging.info('Skip downloading model bin %s', file_path)
|
||||
with open(local_file_path, 'w') as f:
|
||||
f.write(f'{constants.GCS_URI_PREFIX}{bucket_name}/{prefix}/{file_path}')
|
||||
f.write(f'{constants.GCS_URI_PREFIX}{bucket_name}/{prefix}{file_path}')
|
||||
else:
|
||||
logging.info('Downloading %s to %s', file_path, local_file_path)
|
||||
if log:
|
||||
logging.info('Downloading %s to %s', file_path, local_file_path)
|
||||
blob.download_to_filename(local_file_path)
|
||||
|
||||
|
||||
def _get_relative_paths(base_dir: str) -> List[str]:
|
||||
"""Gets relative paths of all files in a local base directory."""
|
||||
path = pathlib.Path(base_dir)
|
||||
relative_paths = []
|
||||
for local_file in path.rglob('*'):
|
||||
if os.path.isfile(local_file):
|
||||
relative_path = os.path.relpath(local_file, base_dir)
|
||||
relative_paths.append(relative_path)
|
||||
return relative_paths
|
||||
|
||||
|
||||
def _upload_local_files_to_gcs(
|
||||
relative_paths: List[str], local_dir: str, gcs_dir: str
|
||||
):
|
||||
"""Uploads local files to gcs."""
|
||||
bucket_name = gcs_dir.split('/')[2]
|
||||
blob_dir = '/'.join(gcs_dir.split('/')[3:])
|
||||
client = _get_gcs_client()
|
||||
bucket = client.bucket(bucket_name)
|
||||
for relative_path in relative_paths:
|
||||
blob = bucket.blob(os.path.join(blob_dir, relative_path))
|
||||
blob.upload_from_filename(os.path.join(local_dir, relative_path))
|
||||
|
||||
|
||||
def upload_local_dir_to_gcs(local_dir: str, gcs_dir: str):
|
||||
"""Uploads local dir to gcs.
|
||||
|
||||
For example:
|
||||
upload_local_dir_to_gcs(/tmp/bar, gs://bucket/foo)
|
||||
gs://bucket/foo/a -> /tmp/bar/a
|
||||
gs://bucket/foo/b/c -> /tmp/bar/b/c
|
||||
/tmp/bar/a -> gs://bucket/foo/a
|
||||
/tmp/bar/b/c -> gs://bucket/foo/b/c
|
||||
|
||||
Arguments:
|
||||
local_dir: A string of local directory path.
|
||||
gcs_dir: A string of directory path on GCS.
|
||||
"""
|
||||
bucket_name = gcs_dir.split('/')[2]
|
||||
blob_dir = '/'.join(gcs_dir.split('/')[3:])
|
||||
client = storage.Client()
|
||||
bucket = client.bucket(bucket_name)
|
||||
for local_file in glob.glob(local_dir + '/**'):
|
||||
if os.path.isfile(local_file):
|
||||
logging.info(
|
||||
'Uploading %s to %s',
|
||||
local_file,
|
||||
os.path.join(constants.GCS_URI_PREFIX, bucket_name, blob_dir),
|
||||
)
|
||||
blob = bucket.blob(os.path.join(blob_dir, os.path.basename(local_file)))
|
||||
blob.upload_from_filename(local_file)
|
||||
# Relative paths of all files in local_dir.
|
||||
relative_paths = _get_relative_paths(local_dir)
|
||||
_upload_local_files_to_gcs(relative_paths, local_dir, gcs_dir)
|
||||
|
||||
|
||||
def upload_file_to_gcs_path(
|
||||
@@ -155,7 +233,7 @@ def upload_file_to_gcs_path(
|
||||
if not source_path_obj.exists():
|
||||
raise RuntimeError(f'Source path does not exist: {source_path}')
|
||||
|
||||
storage_client = storage.Client()
|
||||
storage_client = _get_gcs_client()
|
||||
source_file_path = source_path
|
||||
destination_file_uri = destination_uri
|
||||
logging.info('Uploading "%s" to "%s"', source_file_path, destination_file_uri)
|
||||
@@ -174,7 +252,9 @@ def is_gcs_path(input_path: str) -> bool:
|
||||
Returns:
|
||||
True if the input path is a GCS path, False otherwise.
|
||||
"""
|
||||
return input_path.startswith(constants.GCS_URI_PREFIX)
|
||||
return input_path is not None and input_path.startswith(
|
||||
constants.GCS_URI_PREFIX
|
||||
)
|
||||
|
||||
|
||||
def release_text_assets(
|
||||
@@ -232,13 +312,10 @@ def download_video_from_gcs_to_local(video_file_path: str) -> Tuple[str, str]:
|
||||
"""
|
||||
_, local_video_file_name = os.path.split(video_file_path)
|
||||
file_extension = os.path.splitext(video_file_path)[1]
|
||||
if file_extension:
|
||||
remote_video_file_name = local_video_file_name.replace(
|
||||
file_extension, '_overlay.mp4'
|
||||
)
|
||||
else:
|
||||
remote_video_file_name = local_video_file_name + '_overlay.mp4'
|
||||
local_file_path = generate_tmp_path(file_extension)
|
||||
remote_video_file_name = local_video_file_name.replace(
|
||||
file_extension, '_overlay.mp4'
|
||||
)
|
||||
local_file_path = generate_tmp_path(os.path.splitext(video_file_path)[1])
|
||||
logging.info('Downloading %s to %s...', video_file_path, local_file_path)
|
||||
download_gcs_file_to_local(video_file_path, local_file_path)
|
||||
return local_file_path, remote_video_file_name
|
||||
@@ -254,10 +331,28 @@ def get_output_video_file(video_output_file_path: str) -> str:
|
||||
str: Local video output file path.
|
||||
"""
|
||||
file_extension = os.path.splitext(video_output_file_path)[1]
|
||||
if file_extension:
|
||||
out_local_video_file_name = video_output_file_path.replace(
|
||||
file_extension, '_overlay' + file_extension
|
||||
)
|
||||
else:
|
||||
out_local_video_file_name = video_output_file_path + '_overlay'
|
||||
out_local_video_file_name = video_output_file_path.replace(
|
||||
file_extension, '_overlay' + file_extension
|
||||
)
|
||||
return out_local_video_file_name
|
||||
|
||||
|
||||
def write_first_party_model_metadata(
|
||||
output_path: str, required_container_uri: str
|
||||
) -> None:
|
||||
"""Write Vertex internal model metadata for first party artifacts."""
|
||||
model_metadata_fname = 'model_metadata.jsonl'
|
||||
if len(required_container_uri) > 126:
|
||||
raise ValueError(f'Docker URI exceeds 126 chars: {required_container_uri}')
|
||||
payload = '\n{}{}'.format( # serialized proto
|
||||
chr(len(required_container_uri)),
|
||||
required_container_uri,
|
||||
)
|
||||
os.makedirs(output_path, exist_ok=True)
|
||||
output_dirs = [output_path]
|
||||
if output_path.startswith('/gcs'):
|
||||
# include all parent dirs, except "/", "/gcs"
|
||||
output_dirs.extend([str(p) for p in pathlib.Path(output_path).parents][:-2])
|
||||
for output_dir in output_dirs:
|
||||
with open(os.path.join(output_dir, model_metadata_fname), 'w') as f:
|
||||
f.write(payload)
|
||||
|
||||
@@ -20,3 +20,11 @@ def get_trial_id_from_environment() -> str:
|
||||
_ENVIRONMENT_VARIABLE_FOR_TRIAL_ID,
|
||||
)
|
||||
return os.environ.get(_ENVIRONMENT_VARIABLE_FOR_TRIAL_ID, '0')
|
||||
|
||||
|
||||
def maybe_append_trial_id(path: str) -> str:
|
||||
"""Appends trial_N to path if running in a Hyperparameter Tuning Job."""
|
||||
trial_id = os.environ.get(_ENVIRONMENT_VARIABLE_FOR_TRIAL_ID)
|
||||
if trial_id is None:
|
||||
return path
|
||||
return os.path.join(path, f'trial_{trial_id}')
|
||||
|
||||
Reference in New Issue
Block a user