@aws/ml-container-creator 0.2.0 → 0.2.2
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.
- package/bin/cli.js +88 -86
- package/config/bootstrap-stack.json +211 -0
- package/config/parameter-schema.json +88 -0
- package/infra/ci-harness/bin/ci-harness.ts +26 -0
- package/infra/ci-harness/buildspec.yml +352 -0
- package/infra/ci-harness/cdk.json +27 -0
- package/infra/ci-harness/lambda/scanner/index.ts +199 -0
- package/infra/ci-harness/lib/ci-harness-stack.ts +609 -0
- package/infra/ci-harness/package-lock.json +3979 -0
- package/infra/ci-harness/package.json +32 -0
- package/infra/ci-harness/tsconfig.json +38 -0
- package/package.json +19 -10
- package/src/app.js +318 -318
- package/src/copy-tpl.js +19 -19
- package/src/lib/asset-manager.js +74 -74
- package/src/lib/aws-profile-parser.js +45 -45
- package/src/lib/bootstrap-command-handler.js +560 -547
- package/src/lib/bootstrap-config.js +45 -45
- package/src/lib/ci-register-helpers.js +19 -19
- package/src/lib/ci-report-helpers.js +37 -37
- package/src/lib/ci-stage-helpers.js +49 -49
- package/src/lib/comment-generator.js +4 -4
- package/src/lib/config-manager.js +105 -105
- package/src/lib/deployment-config-resolver.js +10 -10
- package/src/lib/deployment-registry.js +153 -153
- package/src/lib/engine-prefix-resolver.js +8 -8
- package/src/lib/key-value-parser.js +6 -6
- package/src/lib/manifest-cli.js +108 -108
- package/src/lib/prompt-runner.js +224 -224
- package/src/lib/prompts.js +121 -121
- package/src/lib/registry-command-handler.js +174 -174
- package/src/lib/registry-loader.js +52 -52
- package/src/lib/sensitive-redactor.js +9 -9
- package/src/lib/template-engine.js +1 -1
- package/src/lib/template-manager.js +62 -62
- package/src/prompt-adapter.js +18 -18
|
@@ -151,10 +151,10 @@ export default class ConfigManager {
|
|
|
151
151
|
// Ensure env var collections are properly merged (CLI over config file over registry)
|
|
152
152
|
// this.config already has the fully merged result from all sources
|
|
153
153
|
if (this.config.modelEnvVars && typeof this.config.modelEnvVars === 'object') {
|
|
154
|
-
finalConfig.modelEnvVars = { ...this.config.modelEnvVars }
|
|
154
|
+
finalConfig.modelEnvVars = { ...this.config.modelEnvVars };
|
|
155
155
|
}
|
|
156
156
|
if (this.config.serverEnvVars && typeof this.config.serverEnvVars === 'object') {
|
|
157
|
-
finalConfig.serverEnvVars = { ...this.config.serverEnvVars }
|
|
157
|
+
finalConfig.serverEnvVars = { ...this.config.serverEnvVars };
|
|
158
158
|
}
|
|
159
159
|
|
|
160
160
|
// Ensure all parameters from the matrix are included in final config
|
|
@@ -169,16 +169,16 @@ export default class ConfigManager {
|
|
|
169
169
|
// In prompted mode the PromptRunner may do this, but in --skip-prompts
|
|
170
170
|
// mode we need to do it here so the values are available for downstream logic.
|
|
171
171
|
if (finalConfig.deploymentConfig) {
|
|
172
|
-
const parts = this.deploymentConfigResolver.decompose(finalConfig.deploymentConfig)
|
|
173
|
-
finalConfig.architecture = parts.architecture
|
|
174
|
-
finalConfig.backend = parts.backend
|
|
172
|
+
const parts = this.deploymentConfigResolver.decompose(finalConfig.deploymentConfig);
|
|
173
|
+
finalConfig.architecture = parts.architecture;
|
|
174
|
+
finalConfig.backend = parts.backend;
|
|
175
175
|
// For http architecture, engine comes from the --engine CLI option or prompt
|
|
176
176
|
if (parts.architecture === 'http') {
|
|
177
177
|
if (!finalConfig.engine) {
|
|
178
|
-
finalConfig.engine = parts.engine
|
|
178
|
+
finalConfig.engine = parts.engine;
|
|
179
179
|
}
|
|
180
180
|
} else {
|
|
181
|
-
finalConfig.engine = parts.engine
|
|
181
|
+
finalConfig.engine = parts.engine;
|
|
182
182
|
}
|
|
183
183
|
}
|
|
184
184
|
|
|
@@ -191,23 +191,23 @@ export default class ConfigManager {
|
|
|
191
191
|
// Provide reasonable defaults for missing required parameters
|
|
192
192
|
if (param === 'modelFormat') {
|
|
193
193
|
// Infer model format from architecture/engine (skip for transformers/triton)
|
|
194
|
-
const architecture = finalConfig.architecture || 'http'
|
|
194
|
+
const architecture = finalConfig.architecture || 'http';
|
|
195
195
|
if (architecture === 'http') {
|
|
196
|
-
const engine = finalConfig.engine || 'sklearn'
|
|
196
|
+
const engine = finalConfig.engine || 'sklearn';
|
|
197
197
|
const formatMap = {
|
|
198
198
|
'sklearn': 'pkl',
|
|
199
199
|
'xgboost': 'json',
|
|
200
200
|
'tensorflow': 'keras'
|
|
201
|
-
}
|
|
202
|
-
finalConfig[param] = formatMap[engine] || 'pkl'
|
|
201
|
+
};
|
|
202
|
+
finalConfig[param] = formatMap[engine] || 'pkl';
|
|
203
203
|
}
|
|
204
204
|
} else if (param === 'instanceType') {
|
|
205
205
|
// Default to ml.m5.large for http, ml.g5.xlarge for transformers/triton
|
|
206
|
-
const architecture = finalConfig.architecture || 'http'
|
|
207
|
-
finalConfig[param] = architecture === 'http' ? 'ml.m5.large' : 'ml.g5.xlarge'
|
|
206
|
+
const architecture = finalConfig.architecture || 'http';
|
|
207
|
+
finalConfig[param] = architecture === 'http' ? 'ml.m5.large' : 'ml.g5.xlarge';
|
|
208
208
|
} else if (param === 'projectName') {
|
|
209
209
|
// Generate project name
|
|
210
|
-
finalConfig[param] = this._generateProjectName(finalConfig.architecture)
|
|
210
|
+
finalConfig[param] = this._generateProjectName(finalConfig.architecture);
|
|
211
211
|
} else if (config.default !== null) {
|
|
212
212
|
// Use default value if available
|
|
213
213
|
finalConfig[param] = config.default;
|
|
@@ -327,30 +327,30 @@ export default class ConfigManager {
|
|
|
327
327
|
'endpointDataCapturePercent',
|
|
328
328
|
'endpointVariantName',
|
|
329
329
|
'endpointVolumeSize'
|
|
330
|
-
]
|
|
330
|
+
];
|
|
331
331
|
const icParams = [
|
|
332
332
|
'icCpuCount',
|
|
333
333
|
'icMemorySize',
|
|
334
334
|
'icGpuCount',
|
|
335
335
|
'icCopyCount',
|
|
336
336
|
'icModelWeight'
|
|
337
|
-
]
|
|
337
|
+
];
|
|
338
338
|
|
|
339
|
-
const endpointConfig = {}
|
|
339
|
+
const endpointConfig = {};
|
|
340
340
|
for (const param of endpointParams) {
|
|
341
|
-
const shortKey = param.replace('endpoint', '')
|
|
342
|
-
const key = shortKey.charAt(0).toLowerCase() + shortKey.slice(1)
|
|
341
|
+
const shortKey = param.replace('endpoint', '');
|
|
342
|
+
const key = shortKey.charAt(0).toLowerCase() + shortKey.slice(1);
|
|
343
343
|
if (this.config[param] !== undefined && this.config[param] !== null) {
|
|
344
|
-
endpointConfig[key] = this.config[param]
|
|
344
|
+
endpointConfig[key] = this.config[param];
|
|
345
345
|
}
|
|
346
346
|
}
|
|
347
347
|
|
|
348
|
-
const icConfig = {}
|
|
348
|
+
const icConfig = {};
|
|
349
349
|
for (const param of icParams) {
|
|
350
|
-
const shortKey = param.replace('ic', '')
|
|
351
|
-
const key = shortKey.charAt(0).toLowerCase() + shortKey.slice(1)
|
|
350
|
+
const shortKey = param.replace('ic', '');
|
|
351
|
+
const key = shortKey.charAt(0).toLowerCase() + shortKey.slice(1);
|
|
352
352
|
if (this.config[param] !== undefined && this.config[param] !== null) {
|
|
353
|
-
icConfig[key] = this.config[param]
|
|
353
|
+
icConfig[key] = this.config[param];
|
|
354
354
|
}
|
|
355
355
|
}
|
|
356
356
|
|
|
@@ -360,11 +360,11 @@ export default class ConfigManager {
|
|
|
360
360
|
...icParams,
|
|
361
361
|
'modelEnvVars',
|
|
362
362
|
'serverEnvVars'
|
|
363
|
-
])
|
|
364
|
-
const core = {}
|
|
363
|
+
]);
|
|
364
|
+
const core = {};
|
|
365
365
|
for (const [key, value] of Object.entries(this.config)) {
|
|
366
366
|
if (!excludedFromCore.has(key) && key !== '_sourceManifest') {
|
|
367
|
-
core[key] = value
|
|
367
|
+
core[key] = value;
|
|
368
368
|
}
|
|
369
369
|
}
|
|
370
370
|
|
|
@@ -375,7 +375,7 @@ export default class ConfigManager {
|
|
|
375
375
|
modelEnvVars: { ...(this.config.modelEnvVars || {}) },
|
|
376
376
|
serverEnvVars: { ...(this.config.serverEnvVars || {}) },
|
|
377
377
|
manifest: [...this._sourceManifest]
|
|
378
|
-
}
|
|
378
|
+
};
|
|
379
379
|
}
|
|
380
380
|
|
|
381
381
|
/**
|
|
@@ -388,27 +388,27 @@ export default class ConfigManager {
|
|
|
388
388
|
mergeRegistryEnvVars(registryModelEnvVars = {}, registryServerEnvVars = {}) {
|
|
389
389
|
// Initialize collections if needed
|
|
390
390
|
if (!this.config.modelEnvVars || typeof this.config.modelEnvVars !== 'object') {
|
|
391
|
-
this.config.modelEnvVars = {}
|
|
391
|
+
this.config.modelEnvVars = {};
|
|
392
392
|
}
|
|
393
393
|
if (!this.config.serverEnvVars || typeof this.config.serverEnvVars !== 'object') {
|
|
394
|
-
this.config.serverEnvVars = {}
|
|
394
|
+
this.config.serverEnvVars = {};
|
|
395
395
|
}
|
|
396
396
|
|
|
397
397
|
// Merge registry model env vars (CLI takes precedence)
|
|
398
398
|
Object.entries(registryModelEnvVars).forEach(([key, value]) => {
|
|
399
399
|
if (!(key in this.config.modelEnvVars)) {
|
|
400
|
-
this.config.modelEnvVars[key] = value
|
|
401
|
-
this._recordSource(`modelEnvVars.${key}`, value, 'registry')
|
|
400
|
+
this.config.modelEnvVars[key] = value;
|
|
401
|
+
this._recordSource(`modelEnvVars.${key}`, value, 'registry');
|
|
402
402
|
}
|
|
403
|
-
})
|
|
403
|
+
});
|
|
404
404
|
|
|
405
405
|
// Merge registry server env vars (CLI takes precedence)
|
|
406
406
|
Object.entries(registryServerEnvVars).forEach(([key, value]) => {
|
|
407
407
|
if (!(key in this.config.serverEnvVars)) {
|
|
408
|
-
this.config.serverEnvVars[key] = value
|
|
409
|
-
this._recordSource(`serverEnvVars.${key}`, value, 'registry')
|
|
408
|
+
this.config.serverEnvVars[key] = value;
|
|
409
|
+
this._recordSource(`serverEnvVars.${key}`, value, 'registry');
|
|
410
410
|
}
|
|
411
|
-
})
|
|
411
|
+
});
|
|
412
412
|
}
|
|
413
413
|
|
|
414
414
|
/**
|
|
@@ -978,16 +978,16 @@ export default class ConfigManager {
|
|
|
978
978
|
// 1. The default is already a number (e.g. endpointInitialInstanceCount default: 1)
|
|
979
979
|
// 2. The parameter is schema-validated, default is null, and the value is purely numeric
|
|
980
980
|
// (string defaults like 'AllTraffic' won't match since their default type is string)
|
|
981
|
-
const paramConfig = this.parameterMatrix[parameter]
|
|
981
|
+
const paramConfig = this.parameterMatrix[parameter];
|
|
982
982
|
if (paramConfig && typeof value === 'string') {
|
|
983
|
-
const hasNumericDefault = (typeof paramConfig.default === 'number')
|
|
983
|
+
const hasNumericDefault = (typeof paramConfig.default === 'number');
|
|
984
984
|
const isNullDefaultNumericParam = (paramConfig.default === null &&
|
|
985
985
|
paramConfig.schemaValidated &&
|
|
986
|
-
/^-?\d+(\.\d+)?$/.test(value))
|
|
986
|
+
/^-?\d+(\.\d+)?$/.test(value));
|
|
987
987
|
if (hasNumericDefault || isNullDefaultNumericParam) {
|
|
988
|
-
const num = Number(value)
|
|
988
|
+
const num = Number(value);
|
|
989
989
|
if (!isNaN(num)) {
|
|
990
|
-
return num
|
|
990
|
+
return num;
|
|
991
991
|
}
|
|
992
992
|
}
|
|
993
993
|
}
|
|
@@ -1006,7 +1006,7 @@ export default class ConfigManager {
|
|
|
1006
1006
|
Object.entries(this.parameterMatrix).forEach(([param, config]) => {
|
|
1007
1007
|
if (config.default !== null) {
|
|
1008
1008
|
defaults[param] = config.default;
|
|
1009
|
-
this._recordSource(param, config.default, 'default')
|
|
1009
|
+
this._recordSource(param, config.default, 'default');
|
|
1010
1010
|
} else {
|
|
1011
1011
|
defaults[param] = null;
|
|
1012
1012
|
}
|
|
@@ -1228,15 +1228,15 @@ export default class ConfigManager {
|
|
|
1228
1228
|
dataCapturePercent: 'endpointDataCapturePercent',
|
|
1229
1229
|
variantName: 'endpointVariantName',
|
|
1230
1230
|
volumeSize: 'endpointVolumeSize'
|
|
1231
|
-
}
|
|
1231
|
+
};
|
|
1232
1232
|
Object.entries(value).forEach(([nestedKey, nestedValue]) => {
|
|
1233
|
-
const flatKey = endpointMapping[nestedKey]
|
|
1233
|
+
const flatKey = endpointMapping[nestedKey];
|
|
1234
1234
|
if (flatKey && this._isSourceSupported(flatKey, 'configFile')) {
|
|
1235
|
-
filteredConfig[flatKey] = nestedValue
|
|
1236
|
-
this._recordSource(flatKey, nestedValue, 'config-file')
|
|
1235
|
+
filteredConfig[flatKey] = nestedValue;
|
|
1236
|
+
this._recordSource(flatKey, nestedValue, 'config-file');
|
|
1237
1237
|
}
|
|
1238
|
-
})
|
|
1239
|
-
return
|
|
1238
|
+
});
|
|
1239
|
+
return;
|
|
1240
1240
|
}
|
|
1241
1241
|
|
|
1242
1242
|
// Handle nested icConfig object
|
|
@@ -1247,52 +1247,52 @@ export default class ConfigManager {
|
|
|
1247
1247
|
gpuCount: 'icGpuCount',
|
|
1248
1248
|
copyCount: 'icCopyCount',
|
|
1249
1249
|
modelWeight: 'icModelWeight'
|
|
1250
|
-
}
|
|
1250
|
+
};
|
|
1251
1251
|
Object.entries(value).forEach(([nestedKey, nestedValue]) => {
|
|
1252
|
-
const flatKey = icMapping[nestedKey]
|
|
1252
|
+
const flatKey = icMapping[nestedKey];
|
|
1253
1253
|
if (flatKey && this._isSourceSupported(flatKey, 'configFile')) {
|
|
1254
|
-
filteredConfig[flatKey] = nestedValue
|
|
1255
|
-
this._recordSource(flatKey, nestedValue, 'config-file')
|
|
1254
|
+
filteredConfig[flatKey] = nestedValue;
|
|
1255
|
+
this._recordSource(flatKey, nestedValue, 'config-file');
|
|
1256
1256
|
}
|
|
1257
|
-
})
|
|
1258
|
-
return
|
|
1257
|
+
});
|
|
1258
|
+
return;
|
|
1259
1259
|
}
|
|
1260
1260
|
|
|
1261
1261
|
// Handle modelEnvVars object (merge with CLI, CLI takes precedence)
|
|
1262
1262
|
if (key === 'modelEnvVars' && typeof value === 'object' && value !== null) {
|
|
1263
1263
|
if (!this.config.modelEnvVars) {
|
|
1264
|
-
this.config.modelEnvVars = {}
|
|
1264
|
+
this.config.modelEnvVars = {};
|
|
1265
1265
|
}
|
|
1266
1266
|
// Only set keys not already provided by CLI (CLI has higher precedence)
|
|
1267
|
-
const cliModelEnvVars = (this.explicitConfig && this.explicitConfig.modelEnvVars) || {}
|
|
1267
|
+
const cliModelEnvVars = (this.explicitConfig && this.explicitConfig.modelEnvVars) || {};
|
|
1268
1268
|
Object.entries(value).forEach(([envKey, envValue]) => {
|
|
1269
1269
|
if (!(envKey in cliModelEnvVars)) {
|
|
1270
|
-
this.config.modelEnvVars[envKey] = envValue
|
|
1271
|
-
this._recordSource(`modelEnvVars.${envKey}`, envValue, 'config-file')
|
|
1270
|
+
this.config.modelEnvVars[envKey] = envValue;
|
|
1271
|
+
this._recordSource(`modelEnvVars.${envKey}`, envValue, 'config-file');
|
|
1272
1272
|
}
|
|
1273
|
-
})
|
|
1274
|
-
return
|
|
1273
|
+
});
|
|
1274
|
+
return;
|
|
1275
1275
|
}
|
|
1276
1276
|
|
|
1277
1277
|
// Handle serverEnvVars object (merge with CLI, CLI takes precedence)
|
|
1278
1278
|
if (key === 'serverEnvVars' && typeof value === 'object' && value !== null) {
|
|
1279
1279
|
if (!this.config.serverEnvVars) {
|
|
1280
|
-
this.config.serverEnvVars = {}
|
|
1280
|
+
this.config.serverEnvVars = {};
|
|
1281
1281
|
}
|
|
1282
1282
|
// Only set keys not already provided by CLI (CLI has higher precedence)
|
|
1283
|
-
const cliServerEnvVars = (this.explicitConfig && this.explicitConfig.serverEnvVars) || {}
|
|
1283
|
+
const cliServerEnvVars = (this.explicitConfig && this.explicitConfig.serverEnvVars) || {};
|
|
1284
1284
|
Object.entries(value).forEach(([envKey, envValue]) => {
|
|
1285
1285
|
if (!(envKey in cliServerEnvVars)) {
|
|
1286
|
-
this.config.serverEnvVars[envKey] = envValue
|
|
1287
|
-
this._recordSource(`serverEnvVars.${envKey}`, envValue, 'config-file')
|
|
1286
|
+
this.config.serverEnvVars[envKey] = envValue;
|
|
1287
|
+
this._recordSource(`serverEnvVars.${envKey}`, envValue, 'config-file');
|
|
1288
1288
|
}
|
|
1289
|
-
})
|
|
1290
|
-
return
|
|
1289
|
+
});
|
|
1290
|
+
return;
|
|
1291
1291
|
}
|
|
1292
1292
|
|
|
1293
1293
|
if (this._isSourceSupported(key, 'configFile')) {
|
|
1294
1294
|
filteredConfig[key] = this._parseValue(key, value);
|
|
1295
|
-
this._recordSource(key, this._parseValue(key, value), 'config-file')
|
|
1295
|
+
this._recordSource(key, this._parseValue(key, value), 'config-file');
|
|
1296
1296
|
}
|
|
1297
1297
|
});
|
|
1298
1298
|
this._mergeConfig(filteredConfig);
|
|
@@ -1315,7 +1315,7 @@ export default class ConfigManager {
|
|
|
1315
1315
|
const value = process.env[envVar];
|
|
1316
1316
|
if (value !== undefined && value !== '' && this._isSourceSupported(configKey, 'envVar')) {
|
|
1317
1317
|
this.config[configKey] = this._parseValue(configKey, value);
|
|
1318
|
-
this._recordSource(configKey, this._parseValue(configKey, value), 'env-var')
|
|
1318
|
+
this._recordSource(configKey, this._parseValue(configKey, value), 'env-var');
|
|
1319
1319
|
// Track as explicit configuration — unless the env var is ambient
|
|
1320
1320
|
// (e.g. AWS_REGION is commonly set in shells as a default, not an override)
|
|
1321
1321
|
if (!ambient) {
|
|
@@ -1357,7 +1357,7 @@ export default class ConfigManager {
|
|
|
1357
1357
|
Object.entries(this.parameterMatrix).forEach(([param, config]) => {
|
|
1358
1358
|
if (config.cliOption && options[config.cliOption] !== undefined) {
|
|
1359
1359
|
this.config[param] = this._parseValue(param, options[config.cliOption]);
|
|
1360
|
-
this._recordSource(param, this._parseValue(param, options[config.cliOption]), 'cli')
|
|
1360
|
+
this._recordSource(param, this._parseValue(param, options[config.cliOption]), 'cli');
|
|
1361
1361
|
// Track as explicit configuration
|
|
1362
1362
|
if (!this.explicitConfig) {
|
|
1363
1363
|
this.explicitConfig = {};
|
|
@@ -1401,7 +1401,7 @@ export default class ConfigManager {
|
|
|
1401
1401
|
}
|
|
1402
1402
|
const { key, value } = parseKeyValue(entry);
|
|
1403
1403
|
this.config[configKey][key] = value;
|
|
1404
|
-
this._recordSource(`${configKey}.${key}`, value, 'cli')
|
|
1404
|
+
this._recordSource(`${configKey}.${key}`, value, 'cli');
|
|
1405
1405
|
}
|
|
1406
1406
|
|
|
1407
1407
|
// Track as explicit configuration
|
|
@@ -1539,11 +1539,11 @@ export default class ConfigManager {
|
|
|
1539
1539
|
* @private
|
|
1540
1540
|
*/
|
|
1541
1541
|
_recordSource(param, value, source) {
|
|
1542
|
-
const existingIndex = this._sourceManifest.findIndex(entry => entry.param === param)
|
|
1542
|
+
const existingIndex = this._sourceManifest.findIndex(entry => entry.param === param);
|
|
1543
1543
|
if (existingIndex >= 0) {
|
|
1544
|
-
this._sourceManifest[existingIndex] = { param, value, source }
|
|
1544
|
+
this._sourceManifest[existingIndex] = { param, value, source };
|
|
1545
1545
|
} else {
|
|
1546
|
-
this._sourceManifest.push({ param, value, source })
|
|
1546
|
+
this._sourceManifest.push({ param, value, source });
|
|
1547
1547
|
}
|
|
1548
1548
|
}
|
|
1549
1549
|
|
|
@@ -1561,9 +1561,9 @@ export default class ConfigManager {
|
|
|
1561
1561
|
// Special case: modelFormat is not required for transformers/triton/diffusors architectures
|
|
1562
1562
|
const requiredForConfig = promptableRequired.filter(param => {
|
|
1563
1563
|
if (param === 'modelFormat') {
|
|
1564
|
-
const architecture = this.config.architecture
|
|
1564
|
+
const architecture = this.config.architecture;
|
|
1565
1565
|
if (architecture === 'transformers' || architecture === 'triton' || architecture === 'diffusors') {
|
|
1566
|
-
return false
|
|
1566
|
+
return false;
|
|
1567
1567
|
}
|
|
1568
1568
|
}
|
|
1569
1569
|
return true;
|
|
@@ -1590,38 +1590,38 @@ export default class ConfigManager {
|
|
|
1590
1590
|
'xgboost-fastapi': 'Use --deployment-config=http-fastapi --engine=xgboost instead',
|
|
1591
1591
|
'tensorflow-flask': 'Use --deployment-config=http-flask --engine=tensorflow instead',
|
|
1592
1592
|
'tensorflow-fastapi': 'Use --deployment-config=http-fastapi --engine=tensorflow instead'
|
|
1593
|
-
}
|
|
1593
|
+
};
|
|
1594
1594
|
|
|
1595
1595
|
// Validate deployment-config
|
|
1596
1596
|
if (this.config.deploymentConfig) {
|
|
1597
|
-
const migrationMsg = oldFormatMigration[this.config.deploymentConfig]
|
|
1597
|
+
const migrationMsg = oldFormatMigration[this.config.deploymentConfig];
|
|
1598
1598
|
if (migrationMsg) {
|
|
1599
|
-
errors.push(`Unsupported deployment-config: ${this.config.deploymentConfig}. This value has been replaced. ${migrationMsg}`)
|
|
1599
|
+
errors.push(`Unsupported deployment-config: ${this.config.deploymentConfig}. This value has been replaced. ${migrationMsg}`);
|
|
1600
1600
|
} else if (!this.deploymentConfigResolver.isValid(this.config.deploymentConfig)) {
|
|
1601
|
-
const valid = this.deploymentConfigResolver.getAllConfigs().join(', ')
|
|
1602
|
-
errors.push(`Unsupported deployment-config: ${this.config.deploymentConfig}. Valid configs: ${valid}`)
|
|
1601
|
+
const valid = this.deploymentConfigResolver.getAllConfigs().join(', ');
|
|
1602
|
+
errors.push(`Unsupported deployment-config: ${this.config.deploymentConfig}. Valid configs: ${valid}`);
|
|
1603
1603
|
}
|
|
1604
1604
|
}
|
|
1605
1605
|
|
|
1606
1606
|
// Validate engine (only valid for http architecture)
|
|
1607
1607
|
if (this.config.engine) {
|
|
1608
|
-
const validEngines = ['sklearn', 'xgboost', 'tensorflow']
|
|
1608
|
+
const validEngines = ['sklearn', 'xgboost', 'tensorflow'];
|
|
1609
1609
|
if (!validEngines.includes(this.config.engine)) {
|
|
1610
|
-
errors.push(`Unsupported engine: ${this.config.engine}. Supported: ${validEngines.join(', ')}`)
|
|
1610
|
+
errors.push(`Unsupported engine: ${this.config.engine}. Supported: ${validEngines.join(', ')}`);
|
|
1611
1611
|
}
|
|
1612
1612
|
}
|
|
1613
1613
|
|
|
1614
1614
|
// Validate model format based on architecture/engine
|
|
1615
1615
|
if (this.config.modelFormat && this.config.deploymentConfig) {
|
|
1616
1616
|
try {
|
|
1617
|
-
const parts = this.deploymentConfigResolver.decompose(this.config.deploymentConfig)
|
|
1617
|
+
const parts = this.deploymentConfigResolver.decompose(this.config.deploymentConfig);
|
|
1618
1618
|
if (parts.architecture === 'http') {
|
|
1619
|
-
const engine = this.config.engine || parts.engine
|
|
1619
|
+
const engine = this.config.engine || parts.engine;
|
|
1620
1620
|
if (engine) {
|
|
1621
|
-
const supportedOptions = this._getSupportedOptions()
|
|
1622
|
-
const validFormats = supportedOptions.modelFormats[engine] || []
|
|
1621
|
+
const supportedOptions = this._getSupportedOptions();
|
|
1622
|
+
const validFormats = supportedOptions.modelFormats[engine] || [];
|
|
1623
1623
|
if (validFormats.length > 0 && !validFormats.includes(this.config.modelFormat)) {
|
|
1624
|
-
errors.push(`Unsupported model format '${this.config.modelFormat}' for engine '${engine}'. Supported: ${validFormats.join(', ')}`)
|
|
1624
|
+
errors.push(`Unsupported model format '${this.config.modelFormat}' for engine '${engine}'. Supported: ${validFormats.join(', ')}`);
|
|
1625
1625
|
}
|
|
1626
1626
|
}
|
|
1627
1627
|
}
|
|
@@ -1672,13 +1672,13 @@ export default class ConfigManager {
|
|
|
1672
1672
|
// Special case: modelFormat is not required for transformers/triton/diffusors
|
|
1673
1673
|
if (param === 'modelFormat') {
|
|
1674
1674
|
try {
|
|
1675
|
-
const parts = this.deploymentConfigResolver.decompose(this.config.deploymentConfig)
|
|
1675
|
+
const parts = this.deploymentConfigResolver.decompose(this.config.deploymentConfig);
|
|
1676
1676
|
if (parts.architecture === 'transformers' || parts.architecture === 'triton' || parts.architecture === 'diffusors') {
|
|
1677
|
-
return
|
|
1677
|
+
return;
|
|
1678
1678
|
}
|
|
1679
1679
|
} catch {
|
|
1680
1680
|
// If deploymentConfig is invalid, skip this check
|
|
1681
|
-
return
|
|
1681
|
+
return;
|
|
1682
1682
|
}
|
|
1683
1683
|
}
|
|
1684
1684
|
|
|
@@ -1692,11 +1692,11 @@ export default class ConfigManager {
|
|
|
1692
1692
|
// Validate that modelName is provided for diffusors architecture
|
|
1693
1693
|
if (this.config.deploymentConfig) {
|
|
1694
1694
|
try {
|
|
1695
|
-
const parts = this.deploymentConfigResolver.decompose(this.config.deploymentConfig)
|
|
1695
|
+
const parts = this.deploymentConfigResolver.decompose(this.config.deploymentConfig);
|
|
1696
1696
|
if (parts.architecture === 'diffusors') {
|
|
1697
|
-
const explicitModelName = this.explicitConfig && this.explicitConfig.modelName
|
|
1697
|
+
const explicitModelName = this.explicitConfig && this.explicitConfig.modelName;
|
|
1698
1698
|
if (!explicitModelName) {
|
|
1699
|
-
errors.push('Model name is required for diffusors architecture. Use --model-name to specify a HuggingFace diffusion model.')
|
|
1699
|
+
errors.push('Model name is required for diffusors architecture. Use --model-name to specify a HuggingFace diffusion model.');
|
|
1700
1700
|
}
|
|
1701
1701
|
}
|
|
1702
1702
|
} catch {
|
|
@@ -1708,12 +1708,12 @@ export default class ConfigManager {
|
|
|
1708
1708
|
// Validate schema-validated parameters (endpoint, iC)
|
|
1709
1709
|
Object.entries(this.parameterMatrix).forEach(([param, config]) => {
|
|
1710
1710
|
if (config.schemaValidated && this.config[param] !== null && this.config[param] !== undefined) {
|
|
1711
|
-
const result = this.schemaValidator.validate(param, this.config[param], this.config.deploymentTarget)
|
|
1711
|
+
const result = this.schemaValidator.validate(param, this.config[param], this.config.deploymentTarget);
|
|
1712
1712
|
if (!result.valid) {
|
|
1713
|
-
errors.push(result.error)
|
|
1713
|
+
errors.push(result.error);
|
|
1714
1714
|
}
|
|
1715
1715
|
}
|
|
1716
|
-
})
|
|
1716
|
+
});
|
|
1717
1717
|
|
|
1718
1718
|
return errors;
|
|
1719
1719
|
}
|
|
@@ -1914,38 +1914,38 @@ export default class ConfigManager {
|
|
|
1914
1914
|
'xgboost-fastapi': 'Use --deployment-config=http-fastapi --engine=xgboost instead',
|
|
1915
1915
|
'tensorflow-flask': 'Use --deployment-config=http-flask --engine=tensorflow instead',
|
|
1916
1916
|
'tensorflow-fastapi': 'Use --deployment-config=http-fastapi --engine=tensorflow instead'
|
|
1917
|
-
}
|
|
1918
|
-
const migrationMsg = oldFormatMigration[value]
|
|
1917
|
+
};
|
|
1918
|
+
const migrationMsg = oldFormatMigration[value];
|
|
1919
1919
|
if (migrationMsg) {
|
|
1920
1920
|
throw new ValidationError(
|
|
1921
1921
|
`Unsupported deployment-config: ${value}. This value has been replaced. ${migrationMsg}`,
|
|
1922
1922
|
parameter,
|
|
1923
1923
|
value
|
|
1924
|
-
)
|
|
1924
|
+
);
|
|
1925
1925
|
}
|
|
1926
1926
|
if (!this.deploymentConfigResolver.isValid(value)) {
|
|
1927
|
-
const valid = this.deploymentConfigResolver.getAllConfigs().join(', ')
|
|
1927
|
+
const valid = this.deploymentConfigResolver.getAllConfigs().join(', ');
|
|
1928
1928
|
throw new ValidationError(
|
|
1929
1929
|
`Unsupported deployment-config: ${value}. Valid configs: ${valid}`,
|
|
1930
1930
|
parameter,
|
|
1931
1931
|
value
|
|
1932
|
-
)
|
|
1932
|
+
);
|
|
1933
1933
|
}
|
|
1934
1934
|
}
|
|
1935
|
-
break
|
|
1935
|
+
break;
|
|
1936
1936
|
|
|
1937
1937
|
case 'engine':
|
|
1938
1938
|
if (value) {
|
|
1939
|
-
const validEngines = ['sklearn', 'xgboost', 'tensorflow']
|
|
1939
|
+
const validEngines = ['sklearn', 'xgboost', 'tensorflow'];
|
|
1940
1940
|
if (!validEngines.includes(value)) {
|
|
1941
1941
|
throw new ValidationError(
|
|
1942
1942
|
`Unsupported engine: ${value}. Supported: ${validEngines.join(', ')}`,
|
|
1943
1943
|
parameter,
|
|
1944
1944
|
value
|
|
1945
|
-
)
|
|
1945
|
+
);
|
|
1946
1946
|
}
|
|
1947
1947
|
}
|
|
1948
|
-
break
|
|
1948
|
+
break;
|
|
1949
1949
|
|
|
1950
1950
|
case 'modelFormat':
|
|
1951
1951
|
if (value && context.architecture === 'http' && context.engine) {
|
|
@@ -36,8 +36,8 @@ const CANONICAL_CONFIGS = new Map([
|
|
|
36
36
|
['triton-python', { architecture: 'triton', backend: 'python', engine: null }],
|
|
37
37
|
|
|
38
38
|
// Diffusors architecture (1)
|
|
39
|
-
['diffusors-vllm-omni', { architecture: 'diffusors', backend: 'vllm-omni', engine: null }]
|
|
40
|
-
])
|
|
39
|
+
['diffusors-vllm-omni', { architecture: 'diffusors', backend: 'vllm-omni', engine: null }]
|
|
40
|
+
]);
|
|
41
41
|
|
|
42
42
|
export default class DeploymentConfigResolver {
|
|
43
43
|
/**
|
|
@@ -48,14 +48,14 @@ export default class DeploymentConfigResolver {
|
|
|
48
48
|
* @throws {Error} if the deployment-config is not one of the 15 canonical values
|
|
49
49
|
*/
|
|
50
50
|
decompose(deploymentConfig) {
|
|
51
|
-
const parts = CANONICAL_CONFIGS.get(deploymentConfig)
|
|
51
|
+
const parts = CANONICAL_CONFIGS.get(deploymentConfig);
|
|
52
52
|
if (!parts) {
|
|
53
|
-
const valid = this.getAllConfigs().join(', ')
|
|
53
|
+
const valid = this.getAllConfigs().join(', ');
|
|
54
54
|
throw new Error(
|
|
55
55
|
`Unsupported deployment-config: ${deploymentConfig}. Valid configs: ${valid}`
|
|
56
|
-
)
|
|
56
|
+
);
|
|
57
57
|
}
|
|
58
|
-
return { ...parts }
|
|
58
|
+
return { ...parts };
|
|
59
59
|
}
|
|
60
60
|
|
|
61
61
|
/**
|
|
@@ -66,7 +66,7 @@ export default class DeploymentConfigResolver {
|
|
|
66
66
|
* @returns {string}
|
|
67
67
|
*/
|
|
68
68
|
compose(parts) {
|
|
69
|
-
return `${parts.architecture}-${parts.backend}
|
|
69
|
+
return `${parts.architecture}-${parts.backend}`;
|
|
70
70
|
}
|
|
71
71
|
|
|
72
72
|
/**
|
|
@@ -75,7 +75,7 @@ export default class DeploymentConfigResolver {
|
|
|
75
75
|
* @returns {string[]}
|
|
76
76
|
*/
|
|
77
77
|
getAllConfigs() {
|
|
78
|
-
return [...CANONICAL_CONFIGS.keys()]
|
|
78
|
+
return [...CANONICAL_CONFIGS.keys()];
|
|
79
79
|
}
|
|
80
80
|
|
|
81
81
|
/**
|
|
@@ -87,7 +87,7 @@ export default class DeploymentConfigResolver {
|
|
|
87
87
|
getConfigsForArchitecture(architecture) {
|
|
88
88
|
return this.getAllConfigs().filter(
|
|
89
89
|
(dc) => CANONICAL_CONFIGS.get(dc).architecture === architecture
|
|
90
|
-
)
|
|
90
|
+
);
|
|
91
91
|
}
|
|
92
92
|
|
|
93
93
|
/**
|
|
@@ -98,6 +98,6 @@ export default class DeploymentConfigResolver {
|
|
|
98
98
|
* @returns {boolean}
|
|
99
99
|
*/
|
|
100
100
|
isValid(deploymentConfig) {
|
|
101
|
-
return CANONICAL_CONFIGS.has(deploymentConfig)
|
|
101
|
+
return CANONICAL_CONFIGS.has(deploymentConfig);
|
|
102
102
|
}
|
|
103
103
|
}
|