badaoui HF Staff commited on
Commit
cc6b586
·
verified ·
1 Parent(s): 94ae31d

Update optimum_neuron_export.py

Browse files
Files changed (1) hide show
  1. 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": NeuronStableDiffusionPipeline,
88
- "image-to-image": NeuronStableDiffusionImg2ImgPipeline,
89
- "inpaint": NeuronStableDiffusionInpaintPipeline,
90
- "instruct-pix2pix": NeuronStableDiffusionInstructPix2PixPipeline,
91
- "latent-consistency": NeuronLatentConsistencyModelPipeline,
92
- "stable-diffusion": NeuronStableDiffusionPipeline,
93
- "stable-diffusion-xl": NeuronStableDiffusionXLPipeline,
94
- "stable-diffusion-xl-img2img": NeuronStableDiffusionXLImg2ImgPipeline,
95
- "stable-diffusion-xl-inpaint": NeuronStableDiffusionXLInpaintPipeline,
96
- "controlnet": NeuronStableDiffusionControlNetPipeline,
97
- "controlnet-xl": NeuronStableDiffusionXLControlNetPipeline,
98
- "pixart-alpha": NeuronPixArtAlphaPipeline,
99
- "pixart-sigma": NeuronPixArtSigmaPipeline,
100
- "flux": NeuronFluxPipeline,
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","text2text-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", "automatic-speech-recognition", "audio-xvector"]:
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 export_and_git_add(model_id: str, task_or_pipeline: str, model_type: str, folder: str, token: str) -> Any:
161
 
162
  yield f"📦 Exporting model `{model_id}` for task `{task_or_pipeline}`..."
163
 
164
- model_class = TASK_TO_MODEL_CLASS.get(task_or_pipeline) if model_type == "transformers" else DIFFUSION_PIPELINE_MAPPING.get(task_or_pipeline)
165
- if model_class is None:
166
- supported = list(TASK_TO_MODEL_CLASS.keys()) if model_type == "transformers" else list(DIFFUSION_PIPELINE_MAPPING.keys())
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
- try:
174
- model = model_class.from_pretrained(
175
- model_id,
176
- export=True,
177
- tensor_parallel_size=1,
178
- token=HF_TOKEN,
179
  cpu_backend=True,
180
- compiler_args=compiler_args,
181
- **inputs,
 
 
 
 
 
 
 
 
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}"