Spaces:
Running
Running
Update optimum_neuron_export.py
Browse files- optimum_neuron_export.py +66 -61
optimum_neuron_export.py
CHANGED
|
@@ -55,12 +55,11 @@ from optimum.neuron import (
|
|
| 55 |
|
| 56 |
from optimum.neuron.cache import synchronize_hub_cache
|
| 57 |
from synchronizer import synchronize_hub_cache_with_pr
|
|
|
|
| 58 |
|
| 59 |
SPACES_URL = "https://huggingface.co/spaces/optimum/neuron-export"
|
| 60 |
CUSTOM_CACHE_REPO = os.getenv("CUSTOM_CACHE_REPO")
|
| 61 |
HF_TOKEN = os.environ.get("HF_TOKEN")
|
| 62 |
-
os.environ["NEURON_PLATFORM_TARGET_OVERRIDE"] = "inf2"
|
| 63 |
-
|
| 64 |
|
| 65 |
# Task to NeuronModel mapping for transformers
|
| 66 |
TASK_TO_MODEL_CLASS = {
|
|
@@ -84,31 +83,37 @@ TASK_TO_MODEL_CLASS = {
|
|
| 84 |
|
| 85 |
# Diffusion pipeline mapping
|
| 86 |
DIFFUSION_PIPELINE_MAPPING = {
|
| 87 |
-
"text-to-image":
|
| 88 |
-
"image-to-image":
|
| 89 |
-
"inpaint":
|
| 90 |
-
"instruct-pix2pix":
|
| 91 |
-
"latent-consistency":
|
| 92 |
-
"stable-diffusion":
|
| 93 |
-
"stable-diffusion-xl":
|
| 94 |
-
"stable-diffusion-xl-img2img":
|
| 95 |
-
"stable-diffusion-xl-inpaint":
|
| 96 |
-
"controlnet":
|
| 97 |
-
"controlnet-xl":
|
| 98 |
-
"pixart-alpha":
|
| 99 |
-
"pixart-sigma":
|
| 100 |
-
"flux":
|
| 101 |
}
|
| 102 |
|
|
|
|
|
|
|
|
|
|
|
|
|
| 103 |
def get_default_inputs(task_or_pipeline: str) -> Dict[str, int]:
|
| 104 |
"""Get default input shapes based on task type or diffusion pipeline type."""
|
| 105 |
-
if task_or_pipeline in ["feature-extraction", "sentence-transformers", "fill-mask", "question-answering", "text-classification", "token-classification","text-generation"
|
| 106 |
return {"batch_size": 1, "sequence_length": 128}
|
| 107 |
elif task_or_pipeline == "multiple-choice":
|
| 108 |
return {"batch_size": 1, "num_choices": 4, "sequence_length": 128}
|
|
|
|
|
|
|
| 109 |
elif task_or_pipeline in ["image-classification", "semantic-segmentation", "object-detection"]:
|
| 110 |
return {"batch_size": 1, "num_channels": 3, "height": 224, "width": 224}
|
| 111 |
-
elif task_or_pipeline in ["audio-classification", "audio-frame-classification", "
|
| 112 |
return {"batch_size": 1, "audio_sequence_length": 16000}
|
| 113 |
elif task_or_pipeline in DIFFUSION_PIPELINE_MAPPING:
|
| 114 |
return {"batch_size": 1, "height": 1024, "width": 1024, "num_images_per_prompt": 1, "torch_dtype":torch.bfloat16}
|
|
@@ -116,33 +121,6 @@ def get_default_inputs(task_or_pipeline: str) -> Dict[str, int]:
|
|
| 116 |
# Default to text-based shapes
|
| 117 |
return {"batch_size": 1, "sequence_length": 128}
|
| 118 |
|
| 119 |
-
def prepare_compiler_flags(
|
| 120 |
-
auto_cast: str = "matmul",
|
| 121 |
-
auto_cast_type: str = "bf16",
|
| 122 |
-
optlevel: str = "2",
|
| 123 |
-
instance_type: str = "inf2",
|
| 124 |
-
):
|
| 125 |
-
if auto_cast is not None:
|
| 126 |
-
logger.info(f"Using Neuron: --auto-cast {auto_cast}")
|
| 127 |
-
auto_cast = "matmult" if auto_cast == "matmul" else auto_cast
|
| 128 |
-
compiler_args = ["--auto-cast", auto_cast]
|
| 129 |
-
|
| 130 |
-
logger.info(f"Using Neuron: --auto-cast-type {auto_cast_type}")
|
| 131 |
-
compiler_args.extend(["--auto-cast-type", auto_cast_type])
|
| 132 |
-
else:
|
| 133 |
-
compiler_args = ["--auto-cast", "none"]
|
| 134 |
-
|
| 135 |
-
compiler_args.extend(["--optlevel", optlevel])
|
| 136 |
-
logger.info(f"Using Neuron: --optlevel {optlevel}")
|
| 137 |
-
|
| 138 |
-
if instance_type == "trn2":
|
| 139 |
-
compiler_args.extend(["--target", "trn2"])
|
| 140 |
-
elif instance_type == "trn1":
|
| 141 |
-
compiler_args.extend(["--target", "trn1"])
|
| 142 |
-
|
| 143 |
-
compiler_args_str = " ".join(compiler_args)
|
| 144 |
-
return compiler_args_str
|
| 145 |
-
|
| 146 |
def previous_pr(api: "HfApi", model_id: str, pr_title: str) -> Optional["Discussion"]:
|
| 147 |
try:
|
| 148 |
discussions = api.get_repo_discussions(repo_id=model_id)
|
|
@@ -157,30 +135,57 @@ def previous_pr(api: "HfApi", model_id: str, pr_title: str) -> Optional["Discuss
|
|
| 157 |
return discussion
|
| 158 |
return None
|
| 159 |
|
| 160 |
-
def
|
| 161 |
|
| 162 |
yield f"📦 Exporting model `{model_id}` for task `{task_or_pipeline}`..."
|
| 163 |
|
| 164 |
-
|
| 165 |
-
|
| 166 |
-
|
| 167 |
-
raise Exception(f"❌ Unsupported task/pipeline: {task_or_pipeline}. Supported: {supported}")
|
| 168 |
-
|
| 169 |
inputs = get_default_inputs(task_or_pipeline)
|
| 170 |
-
compiler_args = prepare_compiler_flags()
|
| 171 |
yield f"🔧 Using default inputs: {inputs}"
|
| 172 |
-
|
| 173 |
-
|
| 174 |
-
|
| 175 |
-
model_id,
|
| 176 |
-
|
| 177 |
-
|
| 178 |
-
|
| 179 |
cpu_backend=True,
|
| 180 |
-
|
| 181 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 182 |
)
|
| 183 |
model.save_pretrained(folder)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 184 |
yield "✅ Export completed successfully."
|
| 185 |
except Exception as e:
|
| 186 |
yield f"❌ Export failed with error: {e}"
|
|
|
|
| 55 |
|
| 56 |
from optimum.neuron.cache import synchronize_hub_cache
|
| 57 |
from synchronizer import synchronize_hub_cache_with_pr
|
| 58 |
+
from optimum.exporters.neuron import main_export, build_stable_diffusion_components_mandatory_shapes,
|
| 59 |
|
| 60 |
SPACES_URL = "https://huggingface.co/spaces/optimum/neuron-export"
|
| 61 |
CUSTOM_CACHE_REPO = os.getenv("CUSTOM_CACHE_REPO")
|
| 62 |
HF_TOKEN = os.environ.get("HF_TOKEN")
|
|
|
|
|
|
|
| 63 |
|
| 64 |
# Task to NeuronModel mapping for transformers
|
| 65 |
TASK_TO_MODEL_CLASS = {
|
|
|
|
| 83 |
|
| 84 |
# Diffusion pipeline mapping
|
| 85 |
DIFFUSION_PIPELINE_MAPPING = {
|
| 86 |
+
"text-to-image": StableDiffusionPipeline,
|
| 87 |
+
"image-to-image": StableDiffusionImg2ImgPipeline,
|
| 88 |
+
"inpaint": StableDiffusionInpaintPipeline,
|
| 89 |
+
"instruct-pix2pix": StableDiffusionInstructPix2PixPipeline,
|
| 90 |
+
"latent-consistency": LatentConsistencyModelPipeline,
|
| 91 |
+
"stable-diffusion": StableDiffusionPipeline,
|
| 92 |
+
"stable-diffusion-xl": StableDiffusionXLPipeline,
|
| 93 |
+
"stable-diffusion-xl-img2img": StableDiffusionXLImg2ImgPipeline,
|
| 94 |
+
"stable-diffusion-xl-inpaint": StableDiffusionXLInpaintPipeline,
|
| 95 |
+
"controlnet": StableDiffusionControlNetPipeline,
|
| 96 |
+
"controlnet-xl": StableDiffusionXLControlNetPipeline,
|
| 97 |
+
"pixart-alpha": PixArtAlphaPipeline,
|
| 98 |
+
"pixart-sigma": PixArtSigmaPipeline,
|
| 99 |
+
"flux": FluxPipeline,
|
| 100 |
}
|
| 101 |
|
| 102 |
+
ENCODER_TASKS = {"feature-extraction","sentence-transformers","fill-mask","question-answering","text-classification","token-classification","multiple-choice","image-classification","semantic-segmentation","object-detection","audio-classification","audio-frame-classification","automatic-speech-recognition","audio-xvector"}
|
| 103 |
+
DECODER_TASKS = {"text-generation"}
|
| 104 |
+
SEQ2SEQ_TAKS = {"text2text-generation"}
|
| 105 |
+
|
| 106 |
def get_default_inputs(task_or_pipeline: str) -> Dict[str, int]:
|
| 107 |
"""Get default input shapes based on task type or diffusion pipeline type."""
|
| 108 |
+
if task_or_pipeline in ["feature-extraction", "sentence-transformers", "fill-mask", "question-answering", "text-classification", "token-classification","text-generation"]:
|
| 109 |
return {"batch_size": 1, "sequence_length": 128}
|
| 110 |
elif task_or_pipeline == "multiple-choice":
|
| 111 |
return {"batch_size": 1, "num_choices": 4, "sequence_length": 128}
|
| 112 |
+
elif task_or_pipeline == "text2text-generation":
|
| 113 |
+
return {"batch_size": 1, "sequence_length": 128, "num_beams":4}
|
| 114 |
elif task_or_pipeline in ["image-classification", "semantic-segmentation", "object-detection"]:
|
| 115 |
return {"batch_size": 1, "num_channels": 3, "height": 224, "width": 224}
|
| 116 |
+
elif task_or_pipeline in ["audio-classification", "audio-frame-classification", "audio-xvector"]:
|
| 117 |
return {"batch_size": 1, "audio_sequence_length": 16000}
|
| 118 |
elif task_or_pipeline in DIFFUSION_PIPELINE_MAPPING:
|
| 119 |
return {"batch_size": 1, "height": 1024, "width": 1024, "num_images_per_prompt": 1, "torch_dtype":torch.bfloat16}
|
|
|
|
| 121 |
# Default to text-based shapes
|
| 122 |
return {"batch_size": 1, "sequence_length": 128}
|
| 123 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 124 |
def previous_pr(api: "HfApi", model_id: str, pr_title: str) -> Optional["Discussion"]:
|
| 125 |
try:
|
| 126 |
discussions = api.get_repo_discussions(repo_id=model_id)
|
|
|
|
| 135 |
return discussion
|
| 136 |
return None
|
| 137 |
|
| 138 |
+
def export(model_id: str, task_or_pipeline:str, model_type: str, folder: str):
|
| 139 |
|
| 140 |
yield f"📦 Exporting model `{model_id}` for task `{task_or_pipeline}`..."
|
| 141 |
|
| 142 |
+
if model_type == "diffusers":
|
| 143 |
+
model_class = DIFFUSION_PIPELINE_MAPPING.get(task_or_pipeline)
|
| 144 |
+
|
|
|
|
|
|
|
| 145 |
inputs = get_default_inputs(task_or_pipeline)
|
|
|
|
| 146 |
yield f"🔧 Using default inputs: {inputs}"
|
| 147 |
+
|
| 148 |
+
if task_or_pipeline in ENCODER_TASKS or SEQ2SEQ_TAKS:
|
| 149 |
+
result = main_export(
|
| 150 |
+
model_name_or_path=model_id,
|
| 151 |
+
output=folder,
|
| 152 |
+
token=HF_TOKEN
|
| 153 |
+
task=task_or_pipeline,
|
| 154 |
cpu_backend=True,
|
| 155 |
+
do_validation=False,
|
| 156 |
+
input_shapes=**inputs
|
| 157 |
+
)
|
| 158 |
+
|
| 159 |
+
if task_or_pipeline in DECODER_TASKS:
|
| 160 |
+
neuron_config = NeuronModelForCausalLM.get_neuron_config(model_name_or_path=model_id, **inputs)
|
| 161 |
+
neuron_model = NeuronModelForCausalLM.export(
|
| 162 |
+
model_id=export_decoder_id,
|
| 163 |
+
neuron_config=neuron_config,
|
| 164 |
+
token = HF_TOKEN
|
| 165 |
)
|
| 166 |
model.save_pretrained(folder)
|
| 167 |
+
|
| 168 |
+
if task_or_pipeline in DIFFUSION_PIPELINE_MAPPING:
|
| 169 |
+
model = model_class.from_pretrained(model_id)
|
| 170 |
+
input_shapes = build_stable_diffusion_components_mandatory_shapes(**inputs)
|
| 171 |
+
compiler_kwargs = {"auto_cast": "matmul", "auto_cast_type": "bf16"}
|
| 172 |
+
|
| 173 |
+
result = main_export(
|
| 174 |
+
model_name_or_path=model_id,
|
| 175 |
+
output=folder,
|
| 176 |
+
compiler_kwargs=compiler_kwargs,
|
| 177 |
+
token=HF_TOKEN,
|
| 178 |
+
library_name=model_type,
|
| 179 |
+
cpu_backend=True,
|
| 180 |
+
model=model,
|
| 181 |
+
**input_shapes,
|
| 182 |
+
)
|
| 183 |
+
|
| 184 |
+
|
| 185 |
+
def export_and_git_add(model_id: str, task_or_pipeline: str, model_type: str, folder: str, token: str) -> Any:
|
| 186 |
+
|
| 187 |
+
try:
|
| 188 |
+
export(model_id, task_or_pipeline, model_type, folder)
|
| 189 |
yield "✅ Export completed successfully."
|
| 190 |
except Exception as e:
|
| 191 |
yield f"❌ Export failed with error: {e}"
|