UNPKG

aws-cdk-neuronx-patterns

Version:
95 lines 18.9 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.SageMakerInferenceToolkitTnxCompiler = exports.SageMakerInferenceToolkitTnxCompileImage = void 0; const aws_ecs_1 = require("aws-cdk-lib/aws-ecs"); const constructs_1 = require("constructs"); const path_1 = require("path"); const neuronx_1 = require("../base/neuronx"); const neuronx_compiler_1 = require("../base/neuronx-compiler"); /** * Compile image for SageMakerInferenceToolkitTnxCompile. * @example * new SageMakerInferenceToolkitTnxCompileImage(PytorchTrainingNeuronxImage.LATEST); */ class SageMakerInferenceToolkitTnxCompileImage { constructor(neruonxImage) { this.image = aws_ecs_1.ContainerImage.fromAsset((0, path_1.join)(__dirname, "../../scripts/compile/sagemaker-inference-toolkit-tnx"), { buildArgs: { IMAGE_NAME: neruonxImage.imageName, IMAGE_TAG: neruonxImage.imageTag, }, }); this.sdkVersion = neruonxImage.sdkVersion; } } exports.SageMakerInferenceToolkitTnxCompileImage = SageMakerInferenceToolkitTnxCompileImage; /** * Neuronx compile construct. Compile the model to work with Inferentia2 and Trainium1 and upload it to an S3 bucket. */ class SageMakerInferenceToolkitTnxCompiler extends constructs_1.Construct { constructor(scope, id, props) { super(scope, id); const optLevel = props.compileOptions?.optLevel ?? neuronx_1.OptLevel.BEST_BALANCE; const batchSize = props.compileOptions?.batchSize ?? 1; const nPositions = props.compileOptions?.nPositions ?? 4096; const quantDtype = props.compileOptions?.quantDtype; const memoryFootprint = props.model.options.config ? (0, neuronx_1.calcMemoryFootprint)(props.model.options.config.embeddingDimension, props.model.options.config.layers, neuronx_1.DataTypeBits.BF16_OR_FP16, nPositions, batchSize) : (0, neuronx_1.inferMemoryFootprintFromParameters)(props.model.options.parameters, nPositions, batchSize); const neuronxInstanceTypes = props.neuronxInstanceType ? [props.neuronxInstanceType] : [ neuronx_1.NeuronxInstanceType.INF2_8XLARGE, neuronx_1.NeuronxInstanceType.INF2_24XLARGE, neuronx_1.NeuronxInstanceType.INF2_48XLARGE, ]; const availableInstancePatterns = neuronxInstanceTypes .flatMap((neuronxInstanceType) => (0, neuronx_1.calcTensorParallel)(neuronxInstanceType, memoryFootprint, props.model.options.config?.attentionHeads).map((v) => ({ neuronxInstanceType, ...v, }))) .filter((pattern) => !props.compileOptions?.tpDegree || pattern.tp === props.compileOptions.tpDegree); if (availableInstancePatterns.length === 0) { throw new Error(`No available instance type. You can use tpDegree are ${availableInstancePatterns.map((p) => p.tp).join(", ")}.`); } const tpDegree = availableInstancePatterns[0].tp; const image = props.image ?? new SageMakerInferenceToolkitTnxCompileImage(neuronx_1.PytorchTrainingNeuronxImage.LATEST); let compiledArtifactPathPrefix = `${props.model.modelId}/neuronx-${image.sdkVersion}/tp${tpDegree}-np${nPositions}-opt${optLevel}`; if (quantDtype) { compiledArtifactPathPrefix = `${compiledArtifactPathPrefix}-quant${quantDtype}`; } const compiler = new neuronx_compiler_1.NeuronxCompiler(this, "Resource", { ...props, neuronxInstanceType: availableInstancePatterns[0].neuronxInstanceType, artifactS3Prefix: "test", image: image, environment: { MODEL_ID: props.model.modelId, TP_DEGREE: tpDegree.toString(), N_POSITIONS: nPositions.toString(), OPT_LEVEL: optLevel.toString(), QUANT_DTYPE: quantDtype?.toString() ?? "", ARTIFACT_S3_URL: props.bucket.s3UrlForObject(compiledArtifactPathPrefix), }, }); this.tpDegree = tpDegree; this.nPositions = nPositions; this.quantDtype = quantDtype; this.optLevel = optLevel; this.model = props.model; this.compiler = compiler; } compile() { return { ...this.compiler.compile(), tpDegree: this.tpDegree, optLevel: this.optLevel, nPositions: this.nPositions, quantDtype: this.quantDtype, }; } } exports.SageMakerInferenceToolkitTnxCompiler = SageMakerInferenceToolkitTnxCompiler; //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic2FnZW1ha2VyLWluZmVyZW5jZS10b29sa2l0LXRueC1jb21waWxlci5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9zYWdlbWFrZXItaW5mZXJlbmNlLXRvb2xraXQtdG54L3NhZ2VtYWtlci1pbmZlcmVuY2UtdG9vbGtpdC10bngtY29tcGlsZXIudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7O0FBRUEsaURBQXFEO0FBRXJELDJDQUF1QztBQUN2QywrQkFBNEI7QUFDNUIsNkNBWXlCO0FBQ3pCLCtEQUlrQztBQXlDbEM7Ozs7R0FJRztBQUNILE1BQWEsd0NBQXdDO0lBS25ELFlBQVksWUFBMkI7UUFDckMsSUFBSSxDQUFDLEtBQUssR0FBRyx3QkFBYyxDQUFDLFNBQVMsQ0FDbkMsSUFBQSxXQUFJLEVBQUMsU0FBUyxFQUFFLHVEQUF1RCxDQUFDLEVBQ3hFO1lBQ0UsU0FBUyxFQUFFO2dCQUNULFVBQVUsRUFBRSxZQUFZLENBQUMsU0FBUztnQkFDbEMsU0FBUyxFQUFFLFlBQVksQ0FBQyxRQUFRO2FBQ2pDO1NBQ0YsQ0FDRixDQUFDO1FBQ0YsSUFBSSxDQUFDLFVBQVUsR0FBRyxZQUFZLENBQUMsVUFBVSxDQUFDO0lBQzVDLENBQUM7Q0FDRjtBQWpCRCw0RkFpQkM7QUFtREQ7O0dBRUc7QUFDSCxNQUFhLG9DQUFxQyxTQUFRLHNCQUFTO0lBT2pFLFlBQ0UsS0FBZ0IsRUFDaEIsRUFBVSxFQUNWLEtBQWdEO1FBRWhELEtBQUssQ0FBQyxLQUFLLEVBQUUsRUFBRSxDQUFDLENBQUM7UUFDakIsTUFBTSxRQUFRLEdBQUcsS0FBSyxDQUFDLGNBQWMsRUFBRSxRQUFRLElBQUksa0JBQVEsQ0FBQyxZQUFZLENBQUM7UUFDekUsTUFBTSxTQUFTLEdBQUcsS0FBSyxDQUFDLGNBQWMsRUFBRSxTQUFTLElBQUksQ0FBQyxDQUFDO1FBQ3ZELE1BQU0sVUFBVSxHQUFHLEtBQUssQ0FBQyxjQUFjLEVBQUUsVUFBVSxJQUFJLElBQUksQ0FBQztR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U0FBUyxFQUFFLFFBQVEsQ0FBQyxRQUFRLEVBQUU7Z0JBQzlCLFdBQVcsRUFBRSxVQUFVLEVBQUUsUUFBUSxFQUFFLElBQUksRUFBRTtnQkFDekMsZUFBZSxFQUFFLEtBQUssQ0FBQyxNQUFNLENBQUMsY0FBYyxDQUMxQywwQkFBMEIsQ0FDM0I7YUFDRjtTQUNGLENBQUMsQ0FBQztRQUNILElBQUksQ0FBQyxRQUFRLEdBQUcsUUFBUSxDQUFDO1FBQ3pCLElBQUksQ0FBQyxVQUFVLEdBQUcsVUFBVSxDQUFDO1FBQzdCLElBQUksQ0FBQyxVQUFVLEdBQUcsVUFBVSxDQUFDO1FBQzdCLElBQUksQ0FBQyxRQUFRLEdBQUcsUUFBUSxDQUFDO1FBQ3pCLElBQUksQ0FBQyxLQUFLLEdBQUcsS0FBSyxDQUFDLEtBQUssQ0FBQztRQUN6QixJQUFJLENBQUMsUUFBUSxHQUFHLFFBQVEsQ0FBQztJQUMzQixDQUFDO0lBQ0QsT0FBTztRQUNMLE9BQU87WUFDTCxHQUFHLElBQUksQ0FBQyxRQUFRLENBQUMsT0FBTyxFQUFFO1lBQzFCLFFBQVEsRUFBRSxJQUFJLENBQUMsUUFBUTtZQUN2QixRQUFRLEVBQUUsSUFBSSxDQUFDLFFBQVE7WUFDdkIsVUFBVSxFQUFFLElBQUksQ0FBQyxVQUFVO1lBQzNCLFVBQVUsRUFBRSxJQUFJLENBQUMsVUFBVTtTQUM1QixDQUFDO0lBQ0osQ0FBQztDQUNGO0FBcEdELG9GQW9HQyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IFNpemUgfSBmcm9tIFwiYXdzLWNkay1saWJcIjtcbmltcG9ydCAqIGFzIGVjMiBmcm9tIFwiYXdzLWNkay1saWIvYXdzLWVjMlwiO1xuaW1wb3J0IHsgQ29udGFpbmVySW1hZ2UgfSBmcm9tIFwiYXdzLWNkay1saWIvYXdzLWVjc1wiO1xuaW1wb3J0IHsgSUJ1Y2tldCB9IGZyb20gXCJhd3MtY2RrLWxpYi9hd3MtczNcIjtcbmltcG9ydCB7IENvbnN0cnVjdCB9IGZyb20gXCJjb25zdHJ1Y3RzXCI7XG5pbXBvcnQgeyBqb2luIH0gZnJvbSBcInBhdGhcIjtcbmltcG9ydCB7XG4gIGNhbGNNZW1vcnlGb290cHJpbnQsXG4gIGNhbGNUZW5zb3JQYXJhbGxlbCxcbiAgRGF0YVR5cGVCaXRzLFxuICBJTmV1cm9ueEltYWdlLFxuICBJTmV1cm9ueEluc3RhbmNlVHlwZSxcbiAgaW5mZXJNZW1vcnlGb290cHJpbnRGcm9tUGFyYW1ldGVycyxcbiAgTW9kZWwsXG4gIE5ldXJvbnhJbnN0YW5jZVR5cGUsXG4gIE9wdExldmVsLFxuICBQeXRvcmNoVHJhaW5pbmdOZXVyb254SW1hZ2UsXG4gIFF1YW50RHR5cGUsXG59IGZyb20gXCIuLi9iYXNlL25ldXJvbnhcIjtcbmltcG9ydCB7XG4gIElOZXVyb254Q29udGFpbmVySW1hZ2UsXG4gIE5ldXJvbnhDb21waWxlZE1vZGVsLFxuICBOZXVyb254Q29tcGlsZXIsXG59IGZyb20gXCIuLi9iYXNlL25ldXJvbngtY29tcGlsZXJcIjtcblxuLyoqXG4gKiBDb21waWxlIG9wdGlvbnMuXG4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgU2FnZU1ha2VySW5mZXJlbmNlVG9vbGtpdFRueENvbXBpbGVPcHRpb25zIHtcbiAgLyoqXG4gICAqIE51bWJlciBvZiB0ZW5zb3IgcGFyYWxsZWwgZ3JvdXBzLlxuICAgKiBAZGVmYXVsdCAtIGNhbGMgZnJvbSBwYXJhbWV0ZXJzIGFuZCBxdWFudER0eXBlXG4gICAqL1xuICByZWFkb25seSB0cERlZ3JlZT86IG51bWJlcjtcbiAgLyoqXG4gICAqIE1heGltdW0gbnVtYmVyIG9mIHNlcXVlbmNlcyBwZXIgaXRlcmF0aW9uLlxuICAgKiBAZGVmYXVsdCAxXG4gICAqL1xuICByZWFkb25seSBiYXRjaFNpemU/OiBudW1iZXI7XG4gIC8qKlxuICAgKiBAZGVmYXVsdCAtIE5vIHF1YW50XG4gICAqL1xuICByZWFkb25seSBxdWFudER0eXBlPzogUXVhbnREdHlwZTtcbiAgLyoqXG4gICAqIEBkZWZhdWx0IDQwOTZcbiAgICovXG4gIHJlYWRvbmx5IG5Qb3NpdGlvbnM/OiBudW1iZXI7XG4gIC8qKlxuICAgKiBAZGVmYXVsdCBPcHRMZXZlbC5CRVNUX0JBTEFOQ0VcbiAgICovXG4gIHJlYWRvbmx5IG9wdExldmVsPzogT3B0TGV2ZWw7XG59XG5cbi8qKlxuICogVGhlIG1vZGVsIGNvbXBpbGVkIGJ5IE5ldXJvbnggY29tcGlsZXIuXG4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgU2FnZU1ha2VySW5mZXJlbmNlVG9vbGtpdFRueENvbXBpbGVkTW9kZWxcbiAgZXh0ZW5kcyBOZXVyb254Q29tcGlsZWRNb2RlbCB7XG4gIHJlYWRvbmx5IHF1YW50RHR5cGU/OiBRdWFudER0eXBlO1xuICByZWFkb25seSBvcHRMZXZlbD86IE9wdExldmVsO1xuICByZWFkb25seSB0cERlZ3JlZTogbnVtYmVyO1xuICByZWFkb25seSBuUG9zaXRpb25zOiBudW1iZXI7XG59XG5cbi8qKlxuICogQ29tcGlsZSBpbWFnZSBmb3IgU2FnZU1ha2VySW5mZXJlbmNlVG9vbGtpdFRueENvbXBpbGUuXG4gKiBAZXhhbXBsZVxuICogbmV3IFNhZ2VNYWtlckluZmVyZW5jZVRvb2xraXRUbnhDb21waWxlSW1hZ2UoUHl0b3JjaFRyYWluaW5nTmV1cm9ueEltYWdlLkxBVEVTVCk7XG4gKi9cbmV4cG9ydCBjbGFzcyBTYWdlTWFrZXJJbmZlcmVuY2VUb29sa2l0VG54Q29tcGlsZUltYWdlXG4gIGltcGxlbWVudHMgSU5ldXJvbnhDb250YWluZXJJbWFnZVxue1xuICByZWFkb25seSBpbWFnZTogQ29udGFpbmVySW1hZ2U7XG4gIHJlYWRvbmx5IHNka1ZlcnNpb246IHN0cmluZztcbiAgY29uc3RydWN0b3IobmVydW9ueEltYWdlOiBJTmV1cm9ueEltYWdlKSB7XG4gICAgdGhpcy5pbWFnZSA9IENvbnRhaW5lckltYWdlLmZyb21Bc3NldChcbiAgICAgIGpvaW4oX19kaXJuYW1lLCBcIi4uLy4uL3NjcmlwdHMvY29tcGlsZS9zYWdlbWFrZXItaW5mZXJlbmNlLXRvb2xraXQtdG54XCIpLFxuICAgICAge1xuICAgICAgICBidWlsZEFyZ3M6IHtcbiAgICAgICAgICBJTUFHRV9OQU1FOiBuZXJ1b254SW1hZ2UuaW1hZ2VOYW1lLFxuICAgICAgICAgIElNQUdFX1RBRzogbmVydW9ueEltYWdlLmltYWdlVGFnLFxuICAgICAgICB9LFxuICAgICAgfSxcbiAgICApO1xuICAgIHRoaXMuc2RrVmVyc2lvbiA9IG5lcnVvbnhJbWFnZS5zZGtWZXJzaW9uO1xuICB9XG59XG5cbi8qKlxuICogUHJvcHMgb2YgTmV1cm9ueENvbXBpbGUuXG4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgU2FnZU1ha2VySW5mZXJlbmNlVG9vbGtpdFRueENvbXBpbGVyUHJvcHMge1xuICAvKipcbiAgICogVlBDIGluIHdoaWNoIHRoaXMgd2lsbCBsYXVuY2ggY29tcGlsZSB3b3JrZXIgaW5zdGFuY2UuXG4gICAqL1xuICByZWFkb25seSB2cGM6IGVjMi5JVnBjO1xuICAvKipcbiAgICogVGhlIGJ1Y2tldCB0byB1cGxvYWQgY29tcGlsZWQgYXJ0aWZhY3RzLlxuICAgKi9cbiAgcmVhZG9ubHkgYnVja2V0OiBJQnVja2V0O1xuICAvKipcbiAgICogVGhlIG1vZGVsIHRvIGJlIGNvbXBpbGVkLlxuICAgKi9cbiAgcmVhZG9ubHkgbW9kZWw6IE1vZGVsO1xuICAvKipcbiAgICogVGhlIGluc3RhbmNlIHR5cGUgb2YgY29tcGlsZSB3b3JrZXIgaW5zdGFuY2UuXG4gICAqL1xuICByZWFkb25seSBuZXVyb254SW5zdGFuY2VUeXBlPzogSU5ldXJvbnhJbnN0YW5jZVR5cGU7XG4gIC8qKlxuICAgKiBUaGUgcm9vdCB2b2x1bWUgb2Ygd29ya2VyIGluc3RhbmNlLlxuICAgKiBAZGVmYXVsdCAtIE4gYmlsaW9uIHBhcmFtZXRlcnMgKiA1R2lCIEVCU1xuICAgKi9cbiAgcmVhZG9ubHkgdm9sdW1lU2l6ZT86IFNpemU7XG4gIC8qKlxuICAgKiBDb21waWxlIHJ1bnRpbWUgaW1hZ2UuXG4gICAqIEBkZWZhdWx0IC0gbGF0ZXN0IGltYWdlXG4gICAqL1xuICByZWFkb25seSBpbWFnZT86IFNhZ2VNYWtlckluZmVyZW5jZVRvb2xraXRUbnhDb21waWxlSW1hZ2U7XG4gIC8qKlxuICAgKiBOZXVyb254IGNvbXBpbGUgb3B0aW9ucy5cbiAgICogQGRlZmF1bHQgLSBFYWNoIHByb3BlcnRpZXMgYXJlIHNldCBkZWZhdWx0LlxuICAgKi9cbiAgcmVhZG9ubHkgY29tcGlsZU9wdGlvbnM/OiBTYWdlTWFrZXJJbmZlcmVuY2VUb29sa2l0VG54Q29tcGlsZU9wdGlvbnM7XG4gIC8qKlxuICAgKiBXaGV0aGVyIG9yIG5vdCB0byB1c2Ugc3BvdCBpbnN0YW5jZXMuIFNwb3QgaW5zdGFuY2VzIGFyZSBsZXNzIGV4cGVuc2l2ZSBFQzIgaW5zdGFuY2VzIHRoYXQgY2FuIGJlIHJlY2xhaW1lZCBieSBFQzIgYXQgYW55IHRpbWU7IHlvdXIgam9iIHdpbGwgYmUgZ2l2ZW4gdHdvIG1pbnV0ZXMgb2Ygbm90aWNlIGJlZm9yZSByZWNsYW1hdGlvbi5cbiAgICpcbiAgICogQGRlZmF1bHQgZmFsc2VcbiAgICovXG4gIHJlYWRvbmx5IHNwb3Q/OiBib29sZWFuO1xuICAvKipcbiAgICogVGhlIFZQQyBTdWJuZXRzIHRoaXMgQ29tcHV0ZSBFbnZpcm9ubWVudCB3aWxsIGxhdW5jaCBpbnN0YW5jZXMgaW4uXG4gICAqXG4gICAqIEBkZWZhdWx0IC0gbmV3IHN1Ym5ldHMgd2lsbCBiZSBjcmVhdGVkXG4gICAqL1xuICByZWFkb25seSB2cGNTdWJuZXRzPzogZWMyLlN1Ym5ldFNlbGVjdGlvbjtcbn1cblxuLyoqXG4gKiBOZXVyb254IGNvbXBpbGUgY29uc3RydWN0LiBDb21waWxlIHRoZSBtb2RlbCB0byB3b3JrIHdpdGggSW5mZXJlbnRpYTIgYW5kIFRyYWluaXVtMSBhbmQgdXBsb2FkIGl0IHRvIGFuIFMzIGJ1Y2tldC5cbiAqL1xuZXhwb3J0IGNsYXNzIFNhZ2VNYWtlckluZmVyZW5jZVRvb2xraXRUbnhDb21waWxlciBleHRlbmRzIENvbnN0cnVjdCB7XG4gIHJlYWRvbmx5IHF1YW50RHR5cGU/OiBRdWFudER0eXBlO1xuICByZWFkb25seSBvcHRMZXZlbD86IE9wdExldmVsO1xuICByZWFkb25seSB0cERlZ3JlZTogbnVtYmVyO1xuICByZWFkb25seSBuUG9zaXRpb25zOiBudW1iZXI7XG4gIG1vZGVsOiBNb2RlbDtcbiAgcHJpdmF0ZSByZWFkb25seSBjb21waWxlcjogTmV1cm9ueENvbXBpbGVyO1xuICBjb25zdHJ1Y3RvcihcbiAgICBzY29wZTogQ29uc3RydWN0LFxuICAgIGlkOiBzdHJpbmcsXG4gICAgcHJvcHM6IFNhZ2VNYWtlckluZmVyZW5jZVRvb2xraXRUbnhDb21waWxlclByb3BzLFxuICApIHtcbiAgICBzdXBlcihzY29wZSwgaWQpO1xuICAgIGNvbnN0IG9wdExldmVsID0gcHJvcHMuY29tcGlsZU9wdGlvbnM/Lm9wdExldmVsID8/IE9wdExldmVsLkJFU1RfQkFMQU5DRTtcbiAgICBjb25zdCBiYXRjaFNpemUgPSBwcm9wcy5jb21waWxlT3B0aW9ucz8uYmF0Y2hTaXplID8/IDE7XG4gICAgY29uc3QgblBvc2l0aW9ucyA9IHByb3BzLmNvbXBpbGVPcHRpb25zPy5uUG9zaXRpb25zID8/IDQwOTY7XG4gICAgY29uc3QgcXVhbnREdHlwZSA9IHByb3BzLmNvbXBpbGVPcHRpb25zPy5xdWFudER0eXBlO1xuICAgIGNvbnN0IG1lbW9yeUZvb3RwcmludCA9IHByb3BzLm1vZGVsLm9wdGlvbnMuY29uZmlnXG4gICAgICA/IGNhbGNNZW1vcnlGb290cHJpbnQoXG4gICAgICAgICAgcHJvcHMubW9kZWwub3B0aW9ucy5jb25maWcuZW1iZWRkaW5nRGltZW5zaW9uLFxuICAgICAgICAgIHByb3BzLm1vZGVsLm9wdGlvbnMuY29uZmlnLmxheWVycyxcbiAgICAgICAgICBEYXRhVHlwZUJpdHMuQkYxNl9PUl9GUDE2LFxuICAgICAgICAgIG5Qb3NpdGlvbnMsXG4gICAgICAgICAgYmF0Y2hTaXplLFxuICAgICAgICApXG4gICAgICA6IGluZmVyTWVtb3J5Rm9vdHByaW50RnJvbVBhcmFtZXRlcnMoXG4gICAgICAgICAgcHJvcHMubW9kZWwub3B0aW9ucy5wYXJhbWV0ZXJzLFxuICAgICAgICAgIG5Qb3NpdGlvbnMsXG4gICAgICAgICAgYmF0Y2hTaXplLFxuICAgICAgICApO1xuICAgIGNvbnN0IG5ldXJvbnhJbnN0YW5jZVR5cGVzID0gcHJvcHMubmV1cm9ueEluc3RhbmNlVHlwZVxuICAgICAgPyBbcHJvcHMubmV1cm9ueEluc3RhbmNlVHlwZV1cbiAgICAgIDogW1xuICAgICAgICAgIE5ldXJvbnhJbnN0YW5jZVR5cGUuSU5GMl84WExBUkdFLFxuICAgICAgICAgIE5ldXJvbnhJbnN0YW5jZVR5cGUuSU5GMl8yNFhMQVJHRSxcbiAgICAgICAgICBOZXVyb254SW5zdGFuY2VUeXBlLklORjJfNDhYTEFSR0UsXG4gICAgICAgIF07XG4gICAgY29uc3QgYXZhaWxhYmxlSW5zdGFuY2VQYXR0ZXJucyA9IG5ldXJvbnhJbnN0YW5jZVR5cGVzXG4gICAgICAuZmxhdE1hcCgobmV1cm9ueEluc3RhbmNlVHlwZSkgPT5cbiAgICAgICAgY2FsY1RlbnNvclBhcmFsbGVsKFxuICAgICAgICAgIG5ldXJvbnhJbnN0YW5jZVR5cGUsXG4gICAgICAgICAgbWVtb3J5Rm9vdHByaW50LFxuICAgICAgICAgIHByb3BzLm1vZGVsLm9wdGlvbnMuY29uZmlnPy5hdHRlbnRpb25IZWFkcyxcbiAgICAgICAgKS5tYXAoKHYpID0+ICh7XG4gICAgICAgICAgbmV1cm9ueEluc3RhbmNlVHlwZSxcbiAgICAgICAgICAuLi52LFxuICAgICAgICB9KSksXG4gICAgICApXG4gICAgICAuZmlsdGVyKFxuICAgICAgICAocGF0dGVybikgPT5cbiAgICAgICAgICAhcHJvcHMuY29tcGlsZU9wdGlvbnM/LnRwRGVncmVlIHx8XG4gICAgICAgICAgcGF0dGVybi50cCA9PT0gcHJvcHMuY29tcGlsZU9wdGlvbnMudHBEZWdyZWUsXG4gICAgICApO1xuICAgIGlmIChhdmFpbGFibGVJbnN0YW5jZVBhdHRlcm5zLmxlbmd0aCA9PT0gMCkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKFxuICAgICAgICBgTm8gYXZhaWxhYmxlIGluc3RhbmNlIHR5cGUuIFlvdSBjYW4gdXNlIHRwRGVncmVlIGFyZSAke2F2YWlsYWJsZUluc3RhbmNlUGF0dGVybnMubWFwKChwKSA9PiBwLnRwKS5qb2luKFwiLCBcIil9LmAsXG4gICAgICApO1xuICAgIH1cbiAgICBjb25zdCB0cERlZ3JlZSA9IGF2YWlsYWJsZUluc3RhbmNlUGF0dGVybnNbMF0udHA7XG4gICAgY29uc3QgaW1hZ2UgPVxuICAgICAgcHJvcHMuaW1hZ2UgPz9cbiAgICAgIG5ldyBTYWdlTWFrZXJJbmZlcmVuY2VUb29sa2l0VG54Q29tcGlsZUltYWdlKFxuICAgICAgICBQeXRvcmNoVHJhaW5pbmdOZXVyb254SW1hZ2UuTEFURVNULFxuICAgICAgKTtcbiAgICBsZXQgY29tcGlsZWRBcnRpZmFjdFBhdGhQcmVmaXggPSBgJHtwcm9wcy5tb2RlbC5tb2RlbElkfS9uZXVyb254LSR7aW1hZ2Uuc2RrVmVyc2lvbn0vdHAke3RwRGVncmVlfS1ucCR7blBvc2l0aW9uc30tb3B0JHtvcHRMZXZlbH1gO1xuICAgIGlmIChxdWFudER0eXBlISEpIHtcbiAgICAgIGNvbXBpbGVkQXJ0aWZhY3RQYXRoUHJlZml4ID0gYCR7Y29tcGlsZWRBcnRpZmFjdFBhdGhQcmVmaXh9LXF1YW50JHtxdWFudER0eXBlfWA7XG4gICAgfVxuICAgIGNvbnN0IGNvbXBpbGVyID0gbmV3IE5ldXJvbnhDb21waWxlcih0aGlzLCBcIlJlc291cmNlXCIsIHtcbiAgICAgIC4uLnByb3BzLFxuICAgICAgbmV1cm9ueEluc3RhbmNlVHlwZTogYXZhaWxhYmxlSW5zdGFuY2VQYXR0ZXJuc1swXS5uZXVyb254SW5zdGFuY2VUeXBlLFxuICAgICAgYXJ0aWZhY3RTM1ByZWZpeDogXCJ0ZXN0XCIsXG4gICAgICBpbWFnZTogaW1hZ2UsXG4gICAgICBlbnZpcm9ubWVudDoge1xuICAgICAgICBNT0RFTF9JRDogcHJvcHMubW9kZWwubW9kZWxJZCxcbiAgICAgICAgVFBfREVHUkVFOiB0cERlZ3JlZS50b1N0cmluZygpLFxuICAgICAgICBOX1BPU0lUSU9OUzogblBvc2l0aW9ucy50b1N0cmluZygpLFxuICAgICAgICBPUFRfTEVWRUw6IG9wdExldmVsLnRvU3RyaW5nKCksXG4gICAgICAgIFFVQU5UX0RUWVBFOiBxdWFudER0eXBlPy50b1N0cmluZygpID8/IFwiXCIsXG4gICAgICAgIEFSVElGQUNUX1MzX1VSTDogcHJvcHMuYnVja2V0LnMzVXJsRm9yT2JqZWN0KFxuICAgICAgICAgIGNvbXBpbGVkQXJ0aWZhY3RQYXRoUHJlZml4LFxuICAgICAgICApLFxuICAgICAgfSxcbiAgICB9KTtcbiAgICB0aGlzLnRwRGVncmVlID0gdHBEZWdyZWU7XG4gICAgdGhpcy5uUG9zaXRpb25zID0gblBvc2l0aW9ucztcbiAgICB0aGlzLnF1YW50RHR5cGUgPSBxdWFudER0eXBlO1xuICAgIHRoaXMub3B0TGV2ZWwgPSBvcHRMZXZlbDtcbiAgICB0aGlzLm1vZGVsID0gcHJvcHMubW9kZWw7XG4gICAgdGhpcy5jb21waWxlciA9IGNvbXBpbGVyO1xuICB9XG4gIGNvbXBpbGUoKTogU2FnZU1ha2VySW5mZXJlbmNlVG9vbGtpdFRueENvbXBpbGVkTW9kZWwge1xuICAgIHJldHVybiB7XG4gICAgICAuLi50aGlzLmNvbXBpbGVyLmNvbXBpbGUoKSxcbiAgICAgIHRwRGVncmVlOiB0aGlzLnRwRGVncmVlLFxuICAgICAgb3B0TGV2ZWw6IHRoaXMub3B0TGV2ZWwsXG4gICAgICBuUG9zaXRpb25zOiB0aGlzLm5Qb3NpdGlvbnMsXG4gICAgICBxdWFudER0eXBlOiB0aGlzLnF1YW50RHR5cGUsXG4gICAgfTtcbiAgfVxufVxuIl19