oracle-ads 2.13.17rc0__py3-none-any.whl → 2.13.18__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (43) hide show
  1. ads/aqua/cli.py +7 -5
  2. ads/aqua/common/entities.py +88 -29
  3. ads/aqua/common/enums.py +7 -0
  4. ads/aqua/common/errors.py +5 -0
  5. ads/aqua/common/utils.py +87 -7
  6. ads/aqua/constants.py +3 -0
  7. ads/aqua/extension/deployment_handler.py +36 -0
  8. ads/aqua/modeldeployment/config_loader.py +10 -0
  9. ads/aqua/modeldeployment/constants.py +1 -0
  10. ads/aqua/modeldeployment/deployment.py +99 -22
  11. ads/aqua/modeldeployment/entities.py +4 -0
  12. ads/aqua/resources/gpu_shapes_index.json +315 -26
  13. ads/aqua/shaperecommend/__init__.py +6 -0
  14. ads/aqua/shaperecommend/constants.py +116 -0
  15. ads/aqua/shaperecommend/estimator.py +384 -0
  16. ads/aqua/shaperecommend/llm_config.py +283 -0
  17. ads/aqua/shaperecommend/recommend.py +493 -0
  18. ads/aqua/shaperecommend/shape_report.py +233 -0
  19. ads/aqua/version.json +1 -1
  20. ads/cli.py +9 -1
  21. ads/jobs/builders/infrastructure/dsc_job.py +1 -0
  22. ads/jobs/builders/infrastructure/dsc_job_runtime.py +9 -1
  23. ads/model/service/oci_datascience_model_deployment.py +46 -19
  24. ads/opctl/operator/lowcode/common/data.py +7 -2
  25. ads/opctl/operator/lowcode/common/transformations.py +207 -0
  26. ads/opctl/operator/lowcode/common/utils.py +8 -0
  27. ads/opctl/operator/lowcode/forecast/__init__.py +3 -0
  28. ads/opctl/operator/lowcode/forecast/__main__.py +53 -3
  29. ads/opctl/operator/lowcode/forecast/const.py +2 -0
  30. ads/opctl/operator/lowcode/forecast/errors.py +5 -0
  31. ads/opctl/operator/lowcode/forecast/meta_selector.py +310 -0
  32. ads/opctl/operator/lowcode/forecast/model/automlx.py +1 -1
  33. ads/opctl/operator/lowcode/forecast/model/base_model.py +119 -30
  34. ads/opctl/operator/lowcode/forecast/model/factory.py +33 -2
  35. ads/opctl/operator/lowcode/forecast/model/forecast_datasets.py +54 -17
  36. ads/opctl/operator/lowcode/forecast/model_evaluator.py +6 -1
  37. ads/opctl/operator/lowcode/forecast/schema.yaml +1 -0
  38. ads/pipeline/ads_pipeline.py +13 -9
  39. {oracle_ads-2.13.17rc0.dist-info → oracle_ads-2.13.18.dist-info}/METADATA +1 -1
  40. {oracle_ads-2.13.17rc0.dist-info → oracle_ads-2.13.18.dist-info}/RECORD +43 -36
  41. {oracle_ads-2.13.17rc0.dist-info → oracle_ads-2.13.18.dist-info}/WHEEL +0 -0
  42. {oracle_ads-2.13.17rc0.dist-info → oracle_ads-2.13.18.dist-info}/entry_points.txt +0 -0
  43. {oracle_ads-2.13.17rc0.dist-info → oracle_ads-2.13.18.dist-info}/licenses/LICENSE.txt +0 -0
@@ -0,0 +1,116 @@
1
+ #!/usr/bin/env python
2
+ # Copyright (c) 2024, 2025 Oracle and/or its affiliates.
3
+ # Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl/
4
+
5
+ """
6
+ aqua.shaperecommend.constants
7
+ ~~~~~~~~~~~~~~
8
+
9
+ This module contains constants used in Aqua GPU Recommendation for Models.
10
+
11
+ LLAMA_REQUIRED_FIELDS refer to fields necessary for calculating model memory for GQA Architecture Models
12
+
13
+ MOE_REQUIRED_FIELDS refer to fields necessary for Mixture of Experts (MoE) Architecture Models
14
+
15
+ NEXT_QUANT suggests the next quantization level based on the current quantization (if applied) or the model weights (if no quantization yet)
16
+ """
17
+
18
+ LLAMA_REQUIRED_FIELDS = [
19
+ "num_hidden_layers",
20
+ "hidden_size",
21
+ "num_attention_heads",
22
+ "num_key_value_heads",
23
+ "head_dim",
24
+ "intermediate_size",
25
+ "vocab_size",
26
+ ]
27
+
28
+ MOE_REQUIRED_FIELDS = LLAMA_REQUIRED_FIELDS + ["num_local_experts", "intermediate_size"]
29
+
30
+ NEXT_QUANT = {
31
+ "float32": ["8bit", "4bit"],
32
+ "bfloat16": ["8bit", "4bit"],
33
+ "float16": ["8bit", "4bit"],
34
+ "int8": ["4bit"],
35
+ "fp8": ["4bit"],
36
+ "8bit": ["4bit"],
37
+ "int4": ["No smaller quantization available"],
38
+ "4bit": ["No smaller quantization available"],
39
+ }
40
+
41
+
42
+ TEXT_GENERATION = "text_generation"
43
+ SAFETENSORS = "safetensors"
44
+
45
+ QUANT_METHODS = [
46
+ "aqlm",
47
+ "awq",
48
+ "deepspeedfp",
49
+ "tpu_int8",
50
+ "fp8",
51
+ "ptpc_fp8",
52
+ "fbgemm_fp8",
53
+ "modelopt",
54
+ "modelopt_fp4",
55
+ "marlin",
56
+ "bitblas",
57
+ "gguf",
58
+ "gptq_marlin_24",
59
+ "gptq_marlin",
60
+ "gptq_bitblas",
61
+ "awq_marlin",
62
+ "gptq",
63
+ "compressed-tensors",
64
+ "bitsandbytes",
65
+ "qqq",
66
+ "hqq",
67
+ "experts_int8",
68
+ "neuron_quant",
69
+ "ipex",
70
+ "quark",
71
+ "moe_wna16",
72
+ "torchao",
73
+ "auto-round",
74
+ "rtn",
75
+ "inc",
76
+ "mxfp4",
77
+ ]
78
+
79
+ IN_FLIGHT_QUANTIZATION = {"4bit"} # vLLM only supports 4bit in-flight-quantization
80
+
81
+ TROUBLESHOOT_MSG = "The selected model is too large to fit on standard GPU shapes with the current configuration.\nAs troubleshooting, we have suggested the two largest available GPU shapes using the smallest quantization level ('4bit') to maximize chances of fitting the model. "
82
+
83
+ VLLM_PARAMS = {
84
+ "max_model_len": "--max-model-len",
85
+ "in_flight_quant": "--quantization bitsandbytes --load-format bitsandbytes",
86
+ }
87
+
88
+ DEFAULT_WEIGHT_SIZE = "float32"
89
+
90
+ BITS_AND_BYTES_8BIT = "8bit"
91
+ BITS_AND_BYTES_4BIT = "4bit"
92
+
93
+ BITSANDBYTES = "bitsandbytes"
94
+
95
+
96
+ QUANT_MAPPING = {
97
+ "float32": 4,
98
+ "bfloat16": 2,
99
+ "float16": 2,
100
+ "fp16": 2,
101
+ "half": 2,
102
+ "int8": 1,
103
+ "fp8": 1,
104
+ "8bit": 1,
105
+ "4bit": 0.5,
106
+ "int4": 0.5,
107
+ }
108
+
109
+ SHAPE_MAP = {
110
+ "NVIDIA_GPU": "GPU",
111
+ "AMD_ROME": "CPU",
112
+ "GENERIC": "CPU",
113
+ "LEGACY": "CPU",
114
+ "ARM": "CPU",
115
+ "UNKNOWN_ENUM_VALUE": "N/A",
116
+ }
@@ -0,0 +1,384 @@
1
+ #!/usr/bin/env python
2
+ # Copyright (c) 2025 Oracle and/or its affiliates.
3
+ # Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl/
4
+ from typing import Optional
5
+
6
+ from pydantic import BaseModel, Field
7
+
8
+ from ads.aqua.app import logger
9
+ from ads.aqua.shaperecommend.constants import (
10
+ IN_FLIGHT_QUANTIZATION,
11
+ LLAMA_REQUIRED_FIELDS,
12
+ MOE_REQUIRED_FIELDS,
13
+ NEXT_QUANT,
14
+ QUANT_MAPPING,
15
+ VLLM_PARAMS,
16
+ )
17
+ from ads.aqua.shaperecommend.llm_config import LLMConfig
18
+
19
+
20
+ class MemoryEstimator(BaseModel):
21
+ """
22
+ The generic estimator for Transformer Architecture models (OPT/ Bloom)
23
+ Used as a fallback estimator if model identified is not a MoE or GQA Architecture Model.
24
+ Has properties to estimate the KV Cache size, Model size, and total footprint (KV Cache + Model size)
25
+
26
+ KV cache: Use num_attention_heads (all heads, no GQA)
27
+ Parameter estimation: Standard decoder-only, untied embeddings possible
28
+ """
29
+
30
+ llm_config: LLMConfig = Field(
31
+ ...,
32
+ description="The model's config.json file with the necessary parameters for model size and KV cache estimation.",
33
+ )
34
+ batch_size: Optional[int] = (
35
+ 1 # we assume that estimation for batch sizes are not supported yet
36
+ )
37
+ seq_len: int = Field(
38
+ ..., description="The max-seq-len to estimate the size of the KV cache."
39
+ )
40
+
41
+ @property
42
+ def kv_cache_memory(self) -> float:
43
+ """
44
+ Estimates the KV cache size (in GB) using the LLM config.json parameters.
45
+
46
+ Uses num_attention_heads (assumes no GQA, each attention head has its own query, key, value) for estimation.
47
+ """
48
+ seq_len = self.seq_len or self.llm_config.max_seq_len
49
+ c = self.llm_config
50
+ kv_cache_dtype_bytes = QUANT_MAPPING.get(
51
+ c.weight_dtype, 2
52
+ ) # vLLM uses model's weight applied to KV cache
53
+
54
+ total_bytes = (
55
+ self.batch_size
56
+ * c.num_hidden_layers
57
+ * 2
58
+ * c.num_attention_heads
59
+ * seq_len
60
+ * c.head_dim
61
+ * kv_cache_dtype_bytes
62
+ )
63
+ return total_bytes / 1e9
64
+
65
+ @property
66
+ def model_memory(self) -> float:
67
+ """
68
+ Estimates the model size (in GB) based on estimating the model parameter size and model weights.
69
+
70
+ Model Parameter estimation: Standard decoder-only, untied/tied embeddings possible.
71
+ """
72
+ c = self.llm_config
73
+ embedding_count = 1 if getattr(c, "tie_word_embeddings", True) else 2
74
+ embedding_params = (
75
+ embedding_count * c.vocab_size * c.hidden_size
76
+ ) # input and output untied
77
+ layer_params = 12 * c.num_hidden_layers * (c.hidden_size**2) # GPT-style
78
+ num_params = layer_params + embedding_params
79
+
80
+ return num_params * c.bytes_per_parameter / 1e9
81
+
82
+ @property
83
+ def total_memory(self) -> float:
84
+ """
85
+ Computes the total memory footprint of the model (KV cache & model size from estimated parameters).
86
+ """
87
+ return self.model_memory + self.kv_cache_memory
88
+
89
+ def validate_shape(
90
+ self, allowed_gpu_memory: float, gpu_utilization: float = 0.9
91
+ ) -> bool:
92
+ """
93
+ Validates if a given model estimator fits within the allowed GPU memory budget, using a fixed utilization margin.
94
+
95
+ Parameters
96
+ ----------
97
+ estimator : MemoryEstimator
98
+ The estimator with current shape/memory needs.
99
+ allowed_gpu_memory : float
100
+ The maximum allowed GPU memory.
101
+
102
+ Returns
103
+ -------
104
+ bool
105
+ True if estimator uses less than adjusted GPU memory, else False.
106
+ """
107
+ return (allowed_gpu_memory * gpu_utilization) > self.total_memory
108
+
109
+ def construct_deployment_params(self) -> str:
110
+ """
111
+ Constructs a deployment parameter string for the model.
112
+
113
+ This method assembles runtime configuration parameters to be passed
114
+ during model deployment. It:
115
+ - Overrides the max sequence length if a shorter length is provided.
116
+ - Suggests in-flight quantization **only if the model is unquantized**
117
+ and in-flight quantization (such as '4bit') is requested in config.
118
+
119
+ Returns
120
+ -------
121
+ str: Parameter string for model deployment.
122
+ """
123
+ c = self.llm_config
124
+ params = []
125
+ if self.seq_len < c.max_seq_len:
126
+ params.append(VLLM_PARAMS["max_model_len"])
127
+ params.append(str(self.seq_len))
128
+
129
+ # Only suggest in-flight quantization for unquantized models when such quantization is requested
130
+ if not c.quantization and c.in_flight_quantization in IN_FLIGHT_QUANTIZATION:
131
+ # vLLM only supports 4bit in-flight quantization
132
+ params.append(VLLM_PARAMS["in_flight_quant"])
133
+
134
+ params = " ".join(params) if params else ""
135
+ return params
136
+
137
+ def suggest_param_advice(self, allowed: float) -> str:
138
+ """
139
+ Suggests parameter modifications to help a model fit within GPU memory limits.
140
+
141
+ Parameters
142
+ ----------
143
+ estimator : MemoryEstimator
144
+ The memory estimator object.
145
+ allowed : float
146
+ Allowed GPU memory in GB.
147
+
148
+ Returns
149
+ -------
150
+ str
151
+ Advice message with suggestions.
152
+ """
153
+ kv_gb = self.kv_cache_memory
154
+ wt_gb = self.model_memory
155
+ batch_size = self.batch_size
156
+ seq_len = self.seq_len
157
+ weight_size = getattr(self.llm_config, "weight_dtype", "unknown")
158
+ config = self.llm_config
159
+
160
+ suggested_quant_msg = None
161
+ quant_advice = ", ".join(config.suggested_quantizations)
162
+ quantization = getattr(config, "quantization", None)
163
+
164
+ advice = []
165
+
166
+ if config.suggested_quantizations:
167
+ to_do = f", which is smaller than the current {quantization if quantization in NEXT_QUANT else weight_size} format."
168
+ if "No" in quant_advice:
169
+ suggested_quant_msg = "No smaller quantized version exists. Use a model with fewer parameters."
170
+ elif not quant_advice:
171
+ suggested_quant_msg = (
172
+ "Use a quantized version of the same model (e.g., INT8 or other)"
173
+ + to_do
174
+ )
175
+ else:
176
+ suggested_quant_msg = (
177
+ f"Either use a pre-quantized model at {quant_advice}, or apply in-flight {quant_advice} quantization"
178
+ + to_do
179
+ )
180
+
181
+ kv_advice = [f"Reduce maximum context length (set --max-model-len < {seq_len})"]
182
+
183
+ if batch_size != 1:
184
+ kv_advice.append(f"Reduce batch size to less than {batch_size}.")
185
+
186
+ wt_advice = [
187
+ "Use a model with fewer parameters.",
188
+ f"{suggested_quant_msg}" if suggested_quant_msg else "",
189
+ ]
190
+
191
+ if kv_gb > wt_gb and kv_gb > allowed * 0.5:
192
+ main = "KV cache memory usage is the main limiting factor"
193
+ advice = kv_advice
194
+ elif wt_gb > kv_gb and wt_gb > allowed * 0.5:
195
+ main = "Model weights are the main limiting factor"
196
+ advice = wt_advice
197
+ else:
198
+ main = "Both model weights and KV cache are significant contributors to memory use"
199
+ advice = kv_advice
200
+ advice.extend(wt_advice)
201
+
202
+ advice_str = "\n".join(f"{i}. {item}" for i, item in enumerate(advice, 1))
203
+
204
+ return (
205
+ f"{advice_str}\n\n{main} (KV cache: {kv_gb:.1f}GB, Weights: {wt_gb:.1f}GB)."
206
+ )
207
+
208
+ def limiting_factor(
209
+ self, allowed_gpu_memory: float, warn_delta: float = 0.85
210
+ ) -> str:
211
+ """
212
+ Determines the memory limiting factor for a model deployment and returns advice.
213
+
214
+ Parameters
215
+ ----------
216
+ estimator : MemoryEstimator
217
+ The memory estimator object with current model configuration.
218
+ allowed_gpu_memory : float
219
+ The maximum allowed GPU memory (in GBs).
220
+ warn_delta : float, optional
221
+ The threshold (fraction) of allowed GPU memory to trigger a warning (default=0.85).
222
+
223
+ Returns
224
+ -------
225
+ str
226
+ Advice message about model fit and limiting factors.
227
+ """
228
+ required = self.total_memory
229
+
230
+ # Warn if required is close to but under allowed
231
+ if allowed_gpu_memory > required > allowed_gpu_memory * warn_delta:
232
+ model_params = self.suggest_param_advice(allowed_gpu_memory)
233
+ advice = (
234
+ f"While the selected compute shape is estimated to work "
235
+ f"({required:.1f}GB used / {allowed_gpu_memory:.1f}GB allowed), "
236
+ f"the model configuration is close to the GPU memory limit.\n\n"
237
+ "If you encounter issues with this shape, consider the following options to reduce memory usage:\n\n"
238
+ f"{model_params.lstrip()}"
239
+ )
240
+ elif required > allowed_gpu_memory:
241
+ model_params = self.suggest_param_advice(allowed_gpu_memory)
242
+ advice = (
243
+ f"Model does not fit within GPU memory budget. "
244
+ "Consider the following options to reduce memory usage:\n\n"
245
+ f"{model_params.lstrip()}"
246
+ )
247
+ else:
248
+ advice = (
249
+ f"No override PARAMS needed. \n\nModel fits well within the allowed compute shape "
250
+ f"({required:.1f}GB used / {allowed_gpu_memory:.1f}GB allowed)."
251
+ )
252
+ return advice
253
+
254
+
255
+ # Specialized estimators:
256
+ class LlamaMemoryEstimator(MemoryEstimator):
257
+ """
258
+ Estimator for GQA-type architectures. Handles tied (memory savings) and untied embeddings,
259
+ and uses grouped attention (GQA) for more efficient KV cache memory estimation.
260
+
261
+ KV cache: Use num_attention_heads (assumes GQA)
262
+ Model Parameter estimation: Standard decoder-only, untied/tied embeddings possible
263
+ """
264
+
265
+ @property
266
+ def model_memory(self) -> float:
267
+ """
268
+ Returns estimated model parameter memory (in GB), accurately accounting
269
+ for Llama-style attention and MLP, and tied or untied embeddings.
270
+ """
271
+ c = self.llm_config
272
+
273
+ embedding_params, attn_params = self._calc_attn_embed_params()
274
+
275
+ # MLP params
276
+ gate_proj = c.hidden_size * c.intermediate_size
277
+ up_proj = c.hidden_size * c.intermediate_size
278
+ down_proj = c.intermediate_size * c.hidden_size
279
+ mlp_params = gate_proj + up_proj + down_proj
280
+
281
+ # Total per-layer
282
+ layer_params = attn_params + mlp_params
283
+ # Total params
284
+ num_params = c.num_hidden_layers * layer_params + embedding_params
285
+
286
+ return num_params * c.bytes_per_parameter / 1e9
287
+
288
+ @property
289
+ def kv_cache_memory(self) -> float:
290
+ """
291
+ Returns estimated KV cache memory in GB for GQA models.
292
+
293
+ Grouped Query Attention uses num_key_value_heads, which groups of Q heads share a K and V projection.
294
+ num_key_value_heads < num_attention_heads, which reduces the KV Cache size.
295
+ """
296
+ c = self.llm_config
297
+ seq_len = self.seq_len or getattr(c, "max_seq_len", 2048)
298
+ kv_cache_dtype_bytes = QUANT_MAPPING.get(c.weight_dtype, 2)
299
+ kv_heads = c.num_key_value_heads
300
+
301
+ total_bytes = (
302
+ self.batch_size
303
+ * c.num_hidden_layers
304
+ * 2
305
+ * kv_heads
306
+ * seq_len
307
+ * c.head_dim
308
+ * kv_cache_dtype_bytes
309
+ )
310
+ return total_bytes / 1e9
311
+
312
+ def _calc_attn_embed_params(self) -> tuple:
313
+ """
314
+ Returns the embedding parameter count and attention parameter count for Llama-family (GQA) models.
315
+ """
316
+ c = self.llm_config
317
+
318
+ # Embedding parameters
319
+ # assume tied embeddings unless tie_word_embeddings = False
320
+ embedding_count = 1 if getattr(c, "tie_word_embeddings", True) else 2
321
+ embedding_params = embedding_count * c.vocab_size * c.hidden_size
322
+
323
+ q_proj = c.hidden_size * c.hidden_size
324
+ k_proj = c.hidden_size * (c.num_key_value_heads * c.head_dim)
325
+ v_proj = c.hidden_size * (c.num_key_value_heads * c.head_dim)
326
+ o_proj = c.hidden_size * c.hidden_size
327
+ attn_params = q_proj + k_proj + v_proj + o_proj
328
+
329
+ return embedding_params, attn_params
330
+
331
+
332
+ class MixtureMemoryEstimator(LlamaMemoryEstimator):
333
+ """
334
+ Estimator for Mixture-of-Experts (MoE) architectures (e.g., Mixtral, MoE Llama).
335
+ Adds extra expert parallelism block parameter count to LlamaMemoryEstimator logic.
336
+ """
337
+
338
+ @property
339
+ def model_memory(self) -> float:
340
+ """
341
+ Accounts for the increase in model parameters due to additional expert MLP blocks in MoE Models.
342
+
343
+ Returns the estimated memory size of the MoE Model (in GB).
344
+ """
345
+ c = self.llm_config
346
+ # Attention parameter count (Llama-style)
347
+ embedding_params, attn_params = self._calc_attn_embed_params()
348
+
349
+ # MoE MLP params per layer
350
+ moe_params_per_layer = (
351
+ c.num_local_experts * 3 * c.hidden_size * c.intermediate_size
352
+ )
353
+ total_params = (
354
+ c.num_hidden_layers * (attn_params + moe_params_per_layer)
355
+ + embedding_params
356
+ )
357
+
358
+ # Convert to GB
359
+ return total_params * c.bytes_per_parameter / 1e9
360
+
361
+
362
+ def get_estimator(llm_config, **kwargs) -> MemoryEstimator:
363
+ """
364
+ Extracts the correct estimator based on the defined parameters in the config.json
365
+ See constants.py for LLMConfig parameters necessary for specific estimators.
366
+ Uses MemoryEstimator as a fallback if parameters needed for GQA and MoE Architectures are missing.
367
+
368
+ Returns the appropriate MemoryEstimator based on the fields defined by the model's config.json (as represented by LLMConfig).
369
+ """
370
+ if all(
371
+ hasattr(llm_config, f) and getattr(llm_config, f) is not None
372
+ for f in MOE_REQUIRED_FIELDS
373
+ ):
374
+ return MixtureMemoryEstimator(llm_config=llm_config, **kwargs)
375
+ elif all(
376
+ hasattr(llm_config, f) and getattr(llm_config, f) is not None
377
+ for f in LLAMA_REQUIRED_FIELDS
378
+ ):
379
+ return LlamaMemoryEstimator(llm_config=llm_config, **kwargs)
380
+ else:
381
+ logger.warning(
382
+ "Falling back to generic GPT estimator: required fields missing from config.json file in model."
383
+ )
384
+ return MemoryEstimator(llm_config=llm_config, **kwargs)