UNPKG

aws-cdk-neuronx-patterns

Version:
158 lines 28.1 kB
"use strict"; var _a, _b; Object.defineProperty(exports, "__esModule", { value: true }); exports.VllmNxdInferenceCompiler = exports.VllmNxdInferenceCompileImage = void 0; const JSII_RTTI_SYMBOL_1 = Symbol.for("jsii.rtti"); const deploy_time_build_1 = require("@cdklabs/deploy-time-build"); const aws_cdk_lib_1 = require("aws-cdk-lib"); const ec2 = require("aws-cdk-lib/aws-ec2"); const constructs_1 = require("constructs"); const crypto_1 = require("crypto"); const path_1 = require("path"); const neuronx_1 = require("../base/neuronx"); const neuronx_compiler_1 = require("../base/neuronx-compiler"); const vllm_engine_1 = require("../base/server-engine/vllm-engine"); const vllm_nxd_inference_ecs_patterns_1 = require("./vllm-nxd-inference-ecs-patterns"); /** * Select an appropriate compile instance type based on model weight size. * Compilation requires roughly 2-3x the model weight size in RAM for * HLO generation, neuronx-cc compilation, and weight sharding. */ function selectCompileInstanceType(weightSize) { const requiredMemoryGiB = weightSize.toGibibytes() * 3; if (requiredMemoryGiB <= 16) { return ec2.InstanceType.of(ec2.InstanceClass.C7I, ec2.InstanceSize.XLARGE2); } else if (requiredMemoryGiB <= 32) { return ec2.InstanceType.of(ec2.InstanceClass.C7I, ec2.InstanceSize.XLARGE4); } else if (requiredMemoryGiB <= 64) { return ec2.InstanceType.of(ec2.InstanceClass.C7I, ec2.InstanceSize.XLARGE8); } else if (requiredMemoryGiB <= 96) { return ec2.InstanceType.of(ec2.InstanceClass.C7I, ec2.InstanceSize.XLARGE12); } else if (requiredMemoryGiB <= 192) { return ec2.InstanceType.of(ec2.InstanceClass.C7I, ec2.InstanceSize.XLARGE24); } else { return ec2.InstanceType.of(ec2.InstanceClass.C7I, ec2.InstanceSize.XLARGE48); } } /** * Compile runtime container image for vLLM NxD Inference */ class VllmNxdInferenceCompileImage extends vllm_nxd_inference_ecs_patterns_1.VllmNxdInferenceEcsImageBase { constructor(scope, id, vllmInferenceNeuronxImage) { vllmInferenceNeuronxImage ?? (vllmInferenceNeuronxImage = neuronx_1.VllmInferenceNeuronxImage.LATEST); super(vllmInferenceNeuronxImage); const build = new deploy_time_build_1.ContainerImageBuild(scope, id, { directory: (0, path_1.join)(__dirname, "../../scripts/compile/vllm-nxd-inference"), buildArgs: { IMAGE_NAME: vllmInferenceNeuronxImage.imageName, IMAGE_TAG: vllmInferenceNeuronxImage.imageTag, }, }); this.image = build.toEcsDockerImageCode(); } } exports.VllmNxdInferenceCompileImage = VllmNxdInferenceCompileImage; _a = JSII_RTTI_SYMBOL_1; VllmNxdInferenceCompileImage[_a] = { fqn: "aws-cdk-neuronx-patterns.VllmNxdInferenceCompileImage", version: "0.3.0" }; /** * Neuronx compiler construct for vLLM on NxD Inference. * Compile the model to work with Neuronx instance and upload it to an S3 bucket. */ class VllmNxdInferenceCompiler extends constructs_1.Construct { constructor(scope, id, props) { super(scope, id); const maxModelLen = props.vllmArgs?.maxModelLen ?? 128; const maxNumSeqs = props.vllmArgs?.maxNumSeqs ?? 1; 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, maxModelLen, maxNumSeqs) : (0, neuronx_1.inferMemoryFootprintFromParameters)(props.model.options.parameters, maxModelLen, maxNumSeqs); 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((instanceType) => !props.vllmArgs?.tensorParallelSize || instanceType.tp === props.vllmArgs.tensorParallelSize); if (availableInstancePatterns.length === 0) { throw new Error(`No available instance type. You can use tensorParallelSize are ${availableInstancePatterns.map((p) => p.tp).join(", ")}.`); } const tensorParallelSize = availableInstancePatterns[0].tp; const image = props.image ?? new VllmNxdInferenceCompileImage(this, "CompileImage"); const blockSize = props.vllmArgs?.blockSize ?? vllm_engine_1.BlockSize.SIZE_32; const vllmArgs = { ...props.vllmArgs, model: props.model.modelId, servedModelName: [props.model.modelName], maxModelLen, maxNumSeqs, tensorParallelSize, blockSize, }; // change dirname every engine args patterns const hash = (str) => (0, crypto_1.createHash)("sha256").update(str).digest("hex"); const artifactS3Prefix = `sdk-${image.neuronSdkVersion}/${hash(JSON.stringify(vllmArgs))}`; const vllmCliArgs = vllm_engine_1.VllmEngineArgumentsParser.cli(vllmArgs); const environment = { ...props.environment, VLLM_NEURON_FRAMEWORK: "neuronx-distributed-inference", NEURON_COMPILED_ARTIFACTS: "neuron-compiled-artifacts", NEURON_RT_NUM_CORES: tensorParallelSize.toString(), XLA_HANDLE_SPECIAL_SCALAR: "1", MODEL_ID: props.model.modelId, MODEL_NAME: props.model.modelName, COMPILED_ARTIFACTS_S3_URI: props.bucket.s3UrlForObject(artifactS3Prefix), COMPILED_ARTIFACTS_S3_PREFIX: artifactS3Prefix, }; const secrets = {}; if (props.vllmArgs?.hfToken) { secrets.HF_TOKEN = props.vllmArgs.hfToken; } const weightSize = aws_cdk_lib_1.Size.gibibytes(props.model.options.parameters.toBillion() * 2.5); const quantizedWightSize = props.vllmArgs?.overrideNeuronConfig?.quantized ? weightSize : aws_cdk_lib_1.Size.bytes(0); const volumeSize = aws_cdk_lib_1.Size.gibibytes(Math.ceil(weightSize.toGibibytes() + quantizedWightSize.toGibibytes() + neuronx_1.PytorchTrainingNeuronxImage.size.toGibibytes() + neuronx_1.NeuronOptimizedMachineImage.size.toGibibytes())); const compiler = new neuronx_compiler_1.NeuronxCrossCompiler(this, "Resource", { ...props, neuronxInstanceType: availableInstancePatterns[0].neuronxInstanceType, compileInstanceType: props.compileInstanceType ?? selectCompileInstanceType(weightSize), artifactS3Prefix, image: image, command: vllmCliArgs, environment, secrets, volumeSize, }); this.vllmArgs = vllmArgs; this.compiler = compiler; } /** * Compile the model and return the compiled model. * @returns The compiled model. */ compile() { return { ...this.compiler.compile(), vllmArgs: this.vllmArgs, }; } } exports.VllmNxdInferenceCompiler = VllmNxdInferenceCompiler; _b = JSII_RTTI_SYMBOL_1; VllmNxdInferenceCompiler[_b] = { fqn: "aws-cdk-neuronx-patterns.VllmNxdInferenceCompiler", version: "0.3.0" }; //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidmxsbS1ueGQtaW5mZXJlbmNlLWNvbXBpbGVyLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL3ZsbG0tbnhkLWluZmVyZW5jZS92bGxtLW54ZC1pbmZlcmVuY2UtY29tcGlsZXIudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7Ozs7QUFBQSxrRUFBaUU7QUFDakUsNkNBQW1DO0FBRW5DLDJDQUEyQztBQUkzQywyQ0FBdUM7QUFDdkMsbUNBQW9DO0FBQ3BDLCtCQUE0QjtBQUM1Qiw2Q0FZeUI7QUFDekIsK0RBS2tDO0FBQ2xDLG1FQUkyQztBQUMzQyx1RkFBaUY7QUFFakY7Ozs7R0FJRztBQUNILFNBQVMseUJBQXlCLENBQUMsVUFBZ0I7SUFDakQsTUFBTSxpQkFBaUIsR0FBRyxVQUFVLENBQUMsV0FBVyxFQUFFLEdBQUcsQ0FBQyxDQUFDO0lBQ3ZELElBQUksaUJBQWlCLElBQUksRUFBRSxFQUFFLENBQUM7UUFDNUIsT0FBTyxHQUFHLENBQUMsWUFBWSxDQUFDLEVBQUUsQ0FBQyxHQUFHLENBQUMsYUFBYSxDQUFDLEdBQUcsRUFBRSxHQUFHLENBQUMsWUFBWSxDQUFDLE9BQU8sQ0FBQyxDQUFDO0lBQzlFLENBQUM7U0FBTSxJQUFJLGlCQUFpQixJQUFJLEVBQUUsRUFBRSxDQUFDO1FBQ25DLE9BQU8sR0FBRyxDQUFDLFlBQVksQ0FBQyxFQUFFLENBQUMsR0FBRyxDQUFDLGFBQWEsQ0FBQyxHQUFHLEVBQUUsR0FBRyxDQUFDLFlBQVksQ0FBQyxPQUFPLENBQUMsQ0FBQztJQUM5RSxDQUFDO1NBQU0sSUFBSSxpQkFBaUIsSUFBSSxFQUFFLEVBQUUsQ0FBQztRQUNuQyxPQUFPLEdBQUcsQ0FBQyxZQUFZLENBQUMsRUFBRSxDQUFDLEdBQUcsQ0FBQyxhQUFhLENBQUMsR0FBRyxFQUFFLEdBQUcsQ0FBQyxZQUFZLENBQUMsT0FBTyxDQUFDLENBQUM7SUFDOUUsQ0FBQztTQUFNLElBQUksaUJBQWlCLElBQUksRUFBRSxFQUFFLENBQUM7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Q0FBQyxVQUFVO1lBQ1osQ0FBQyxDQUFDLGtCQUFJLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQyxDQUFDO1FBQ2xCLE1BQU0sVUFBVSxHQUFHLGtCQUFJLENBQUMsU0FBUyxDQUMvQixJQUFJLENBQUMsSUFBSSxDQUNQLFVBQVUsQ0FBQyxXQUFXLEVBQUU7WUFDdEIsa0JBQWtCLENBQUMsV0FBVyxFQUFFO1lBQ2hDLHFDQUEyQixDQUFDLElBQUksQ0FBQyxXQUFXLEVBQUU7WUFDOUMscUNBQTJCLENBQUMsSUFBSSxDQUFDLFdBQVcsRUFBRSxDQUNqRCxDQUNGLENBQUM7UUFFRixNQUFNLFFBQVEsR0FBRyxJQUFJLHVDQUFvQixDQUFDLElBQUksRUFBRSxVQUFVLEVBQUU7WUFDMUQsR0FBRyxLQUFLO1lBQ1IsbUJBQW1CLEVBQUUseUJBQXlCLENBQUMsQ0FBQyxDQUFDLENBQUMsbUJBQW1CO1lBQ3JFLG1CQUFtQixFQUNqQixLQUFLLENBQUMsbUJBQW1CLElBQUkseUJBQXlCLENBQUMsVUFBVSxDQUFDO1lBQ3BFLGdCQUFnQjtZQUNoQixLQUFLLEVBQUUsS0FBSztZQUNaLE9BQU8sRUFBRSxXQUFXO1lBQ3BCLFdBQVc7WUFDWCxPQUFPO1lBQ1AsVUFBVTtTQUNYLENBQUMsQ0FBQztRQUNILElBQUksQ0FBQyxRQUFRLEdBQUcsUUFBUSxDQUFDO1FBQ3pCLElBQUksQ0FBQyxRQUFRLEdBQUcsUUFBUSxDQUFDO0lBQzNCLENBQUM7SUFDRDs7O09BR0c7SUFDSCxPQUFPO1FBQ0wsT0FBTztZQUNMLEdBQUcsSUFBSSxDQUFDLFFBQVEsQ0FBQyxPQUFPLEVBQUU7WUFDMUIsUUFBUSxFQUFFLElBQUksQ0FBQyxRQUFRO1NBQ2dCLENBQUM7SUFDNUMsQ0FBQzs7QUE3SEgsNERBOEhDIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgQ29udGFpbmVySW1hZ2VCdWlsZCB9IGZyb20gXCJAY2RrbGFicy9kZXBsb3ktdGltZS1idWlsZFwiO1xuaW1wb3J0IHsgU2l6ZSB9IGZyb20gXCJhd3MtY2RrLWxpYlwiO1xuaW1wb3J0ICogYXMgYmF0Y2ggZnJvbSBcImF3cy1jZGstbGliL2F3cy1iYXRjaFwiO1xuaW1wb3J0ICogYXMgZWMyIGZyb20gXCJhd3MtY2RrLWxpYi9hd3MtZWMyXCI7XG5pbXBvcnQgeyBJVnBjLCBTdWJuZXRTZWxlY3Rpb24gfSBmcm9tIFwiYXdzLWNkay1saWIvYXdzLWVjMlwiO1xuaW1wb3J0IHsgQ29udGFpbmVySW1hZ2UgfSBmcm9tIFwiYXdzLWNkay1saWIvYXdzLWVjc1wiO1xuaW1wb3J0IHsgSUJ1Y2tldCB9IGZyb20gXCJhd3MtY2RrLWxpYi9hd3MtczNcIjtcbmltcG9ydCB7IENvbnN0cnVjdCB9IGZyb20gXCJjb25zdHJ1Y3RzXCI7XG5pbXBvcnQgeyBjcmVhdGVIYXNoIH0gZnJvbSBcImNyeXB0b1wiO1xuaW1wb3J0IHsgam9pbiB9IGZyb20gXCJwYXRoXCI7XG5pbXBvcnQge1xuICBjYWxjTWVtb3J5Rm9vdHByaW50LFxuICBjYWxjVGVuc29yUGFyYWxsZWwsXG4gIERhdGFUeXBlQml0cyxcbiAgSU5ldXJvbnhJbnN0YW5jZVR5cGUsXG4gIGluZmVyTWVtb3J5Rm9vdHByaW50RnJvbVBhcmFtZXRlcnMsXG4gIElWbGxtSW5mZXJlbmNlTmV1cm9ueEltYWdlLFxuICBNb2RlbCxcbiAgTmV1cm9uT3B0aW1pemVkTWFjaGluZUltYWdlLFxuICBOZXVyb254SW5zdGFuY2VUeXBlLFxuICBQeXRvcmNoVHJhaW5pbmdOZXVyb254SW1hZ2UsXG4gIFZsbG1JbmZlcmVuY2VOZXVyb254SW1hZ2UsXG59IGZyb20gXCIuLi9iYXNlL25ldXJvbnhcIjtcbmltcG9ydCB7XG4gIElOZXVyb254Q29tcGlsZXIsXG4gIElOZXVyb254Q29udGFpbmVySW1hZ2UsXG4gIE5ldXJvbnhDb21waWxlZE1vZGVsLFxuICBOZXVyb254Q3Jvc3NDb21waWxlcixcbn0gZnJvbSBcIi4uL2Jhc2UvbmV1cm9ueC1jb21waWxlclwiO1xuaW1wb3J0IHtcbiAgQmxvY2tTaXplLFxuICBWbGxtRW5naW5lQXJndW1lbnRzLFxuICBWbGxtRW5naW5lQXJndW1lbnRzUGFyc2VyLFxufSBmcm9tIFwiLi4vYmFzZS9zZXJ2ZXItZW5naW5lL3ZsbG0tZW5naW5lXCI7XG5pbXBvcnQgeyBWbGxtTnhkSW5mZXJlbmNlRWNzSW1hZ2VCYXNlIH0gZnJvbSBcIi4vdmxsbS1ueGQtaW5mZXJlbmNlLWVjcy1wYXR0ZXJuc1wiO1xuXG4vKipcbiAqIFNlbGVjdCBhbiBhcHByb3ByaWF0ZSBjb21waWxlIGluc3RhbmNlIHR5cGUgYmFzZWQgb24gbW9kZWwgd2VpZ2h0IHNpemUuXG4gKiBDb21waWxhdGlvbiByZXF1aXJlcyByb3VnaGx5IDItM3ggdGhlIG1vZGVsIHdlaWdodCBzaXplIGluIFJBTSBmb3JcbiAqIEhMTyBnZW5lcmF0aW9uLCBuZXVyb254LWNjIGNvbXBpbGF0aW9uLCBhbmQgd2VpZ2h0IHNoYXJkaW5nLlxuICovXG5mdW5jdGlvbiBzZWxlY3RDb21waWxlSW5zdGFuY2VUeXBlKHdlaWdodFNpemU6IFNpemUpOiBlYzIuSW5zdGFuY2VUeXBlIHtcbiAgY29uc3QgcmVxdWlyZWRNZW1vcnlHaUIgPSB3ZWlnaHRTaXplLnRvR2liaWJ5dGVzKCkgKiAzO1xuICBpZiAocmVxdWlyZWRNZW1vcnlHaUIgPD0gMTYpIHtcbiAgICByZXR1cm4gZWMyLkluc3RhbmNlVHlwZS5vZihlYzIuSW5zdGFuY2VDbGFzcy5DN0ksIGVjMi5JbnN0YW5jZVNpemUuWExBUkdFMik7XG4gIH0gZWxzZSBpZiAocmVxdWlyZWRNZW1vcnlHaUIgPD0gMzIpIHtcbiAgICByZXR1cm4gZWMyLkluc3RhbmNlVHlwZS5vZihlYzIuSW5zdGFuY2VDbGFzcy5DN0ksIGVjMi5JbnN0YW5jZVNpemUuWExBUkdFNCk7XG4gIH0gZWxzZSBpZiAocmVxdWlyZWRNZW1vcnlHaUIgPD0gNjQpIHtcbiAgICByZXR1cm4gZWMyLkluc3RhbmNlVHlwZS5vZihlYzIuSW5zdGFuY2VDbGFzcy5DN0ksIGVjMi5JbnN0YW5jZVNpemUuWExBUkdFOCk7XG4gIH0gZWxzZSBpZiAocmVxdWlyZWRNZW1vcnlHaUIgPD0gOTYpIHtcbiAgICByZXR1cm4gZWMyLkluc3RhbmNlVHlwZS5vZihcbiAgICAgIGVjMi5JbnN0YW5jZUNsYXNzLkM3SSxcbiAgICAgIGVjMi5JbnN0YW5jZVNpemUuWExBUkdFMTIsXG4gICAgKTtcbiAgfSBlbHNlIGlmIChyZXF1aXJlZE1lbW9yeUdpQiA8PSAxOTIpIHtcbiAgICByZXR1cm4gZWMyLkluc3RhbmNlVHlwZS5vZihcbiAgICAgIGVjMi5JbnN0YW5jZUNsYXNzLkM3SSxcbiAgICAgIGVjMi5JbnN0YW5jZVNpemUuWExBUkdFMjQsXG4gICAgKTtcbiAgfSBlbHNlIHtcbiAgICByZXR1cm4gZWMyLkluc3RhbmNlVHlwZS5vZihcbiAgICAgIGVjMi5JbnN0YW5jZUNsYXNzLkM3SSxcbiAgICAgIGVjMi5JbnN0YW5jZVNpemUuWExBUkdFNDgsXG4gICAgKTtcbiAgfVxufVxuXG4vKipcbiAqIENvbXBpbGUgcnVudGltZSBjb250YWluZXIgaW1hZ2UgZm9yIHZMTE0gTnhEIEluZmVyZW5jZVxuICovXG5leHBvcnQgY2xhc3MgVmxsbU54ZEluZmVyZW5jZUNvbXBpbGVJbWFnZSBleHRlbmRzIFZsbG1OeGRJbmZlcmVuY2VFY3NJbWFnZUJhc2Uge1xuICAvKipcbiAgICogVGhlIGNvbnRhaW5lciBpbWFnZS5cbiAgICovXG4gIHJlYWRvbmx5IGltYWdlOiBDb250YWluZXJJbWFnZTtcbiAgY29uc3RydWN0b3IoXG4gICAgc2NvcGU6IENvbnN0cnVjdCxcbiAgICBpZDogc3RyaW5nLFxuICAgIHZsbG1JbmZlcmVuY2VOZXVyb254SW1hZ2U/OiBJVmxsbUluZmVyZW5jZU5ldXJvbnhJbWFnZSxcbiAgKSB7XG4gICAgdmxsbUluZmVyZW5jZU5ldXJvbnhJbWFnZSA/Pz0gVmxsbUluZmVyZW5jZU5ldXJvbnhJbWFnZS5MQVRFU1Q7XG4gICAgc3VwZXIodmxsbUluZmVyZW5jZU5ldXJvbnhJbWFnZSk7XG4gICAgY29uc3QgYnVpbGQgPSBuZXcgQ29udGFpbmVySW1hZ2VCdWlsZChzY29wZSwgaWQsIHtcbiAgICAgIGRpcmVjdG9yeTogam9pbihfX2Rpcm5hbWUsIFwiLi4vLi4vc2NyaXB0cy9jb21waWxlL3ZsbG0tbnhkLWluZmVyZW5jZVwiKSxcbiAgICAgIGJ1aWxkQXJnczoge1xuICAgICAgICBJTUFHRV9OQU1FOiB2bGxtSW5mZXJlbmNlTmV1cm9ueEltYWdlLmltYWdlTmFtZSxcbiAgICAgICAgSU1BR0VfVEFHOiB2bGxtSW5mZXJlbmNlTmV1cm9ueEltYWdlLmltYWdlVGFnLFxuICAgICAgfSxcbiAgICB9KTtcbiAgICB0aGlzLmltYWdlID0gYnVpbGQudG9FY3NEb2NrZXJJbWFnZUNvZGUoKTtcbiAgfVxufVxuXG4vKipcbiAqIFByb3BzIG9mIFZsbG1OeGRJbmZlcmVuY2VDb21waWxlci5cbiAqL1xuZXhwb3J0IGludGVyZmFjZSBWbGxtTnhkSW5mZXJlbmNlQ29tcGlsZVByb3BzIHtcbiAgLyoqXG4gICAqIFZQQyBpbiB3aGljaCB0aGlzIHdpbGwgbGF1bmNoIGNvbXBpbGUgd29ya2VyIGluc3RhbmNlLlxuICAgKi9cbiAgcmVhZG9ubHkgdnBjOiBJVnBjO1xuICAvKipcbiAgICogVGhlIGJ1Y2tldCB0byB1cGxvYWQgY29tcGlsZWQgYXJ0aWZhY3RzLlxuICAgKi9cbiAgcmVhZG9ubHkgYnVja2V0OiBJQnVja2V0O1xuICAvKipcbiAgICogVGhlIGluc3RhbmNlIHR5cGUgb2YgY29tcGlsZSB3b3JrZXIgaW5zdGFuY2UuXG4gICAqL1xuICByZWFkb25seSBuZXVyb254SW5zdGFuY2VUeXBlPzogSU5ldXJvbnhJbnN0YW5jZVR5cGU7XG4gIC8qKlxuICAgKiBUaGUgbW9kZWwgdG8gYmUgY29tcGlsZWQuXG4gICAqL1xuICByZWFkb25seSBtb2RlbDogTW9kZWw7XG4gIC8qKlxuICAgKiBUaGUgcm9vdCB2b2x1bWUgb2Ygd29ya2VyIGluc3RhbmNlLlxuICAgKiBAZGVmYXVsdCAtIE4gYmlsaW9uIHBhcmFtZXRlcnMgKiA1R2lCIEVCU1xuICAgKi9cbiAgcmVhZG9ubHkgdm9sdW1lU2l6ZT86IFNpemU7XG4gIC8qKlxuICAgKiBXaGV0aGVyIG9yIG5vdCB0byB1c2Ugc3BvdCBpbnN0YW5jZXMuIFNwb3QgaW5zdGFuY2VzIGFyZSBsZXNzIGV4cGVuc2l2ZSBFQzIgaW5zdGFuY2VzIHRoYXQgY2FuIGJlIHJlY2xhaW1lZCBieSBFQzIgYXQgYW55IHRpbWU7IHlvdXIgam9iIHdpbGwgYmUgZ2l2ZW4gdHdvIG1pbnV0ZXMgb2Ygbm90aWNlIGJlZm9yZSByZWNsYW1hdGlvbi5cbiAgICpcbiAgICogQGRlZmF1bHQgZmFsc2VcbiAgICovXG4gIHJlYWRvbmx5IHNwb3Q/OiBib29sZWFuO1xuICAvKipcbiAgICogVGhlIFZQQyBTdWJuZXRzIHRoaXMgQ29tcHV0ZSBFbnZpcm9ubWVudCB3aWxsIGxhdW5jaCBpbnN0YW5jZXMgaW4uXG4gICAqXG4gICAqIEBkZWZhdWx0IC0gbmV3IHN1Ym5ldHMgd2lsbCBiZSBjcmVhdGVkXG4gICAqL1xuICByZWFkb25seSB2cGNTdWJuZXRzPzogU3VibmV0U2VsZWN0aW9uO1xuICAvKipcbiAgICogVGhlIGVudmlyb25tZW50IHZhcmlhYmxlcyB0byBwYXNzIHRvIHRoZSBjb250YWluZXIuXG4gICAqIFRoaXMgaXMgb25seSBhcHBsaWNhYmxlIHdoZW4gdXNpbmcgY29udGFpbmVyIHJ1bnRpbWUuXG4gICAqXG4gICAqIEBkZWZhdWx0IC0gTm8gZW52aXJvbm1lbnQgdmFyaWFibGVzLlxuICAgKi9cbiAgcmVhZG9ubHkgZW52aXJvbm1lbnQ/OiB7XG4gICAgW2tleTogc3RyaW5nXTogc3RyaW5nO1xuICB9O1xuICAvKipcbiAgICogVGhlIGFyZ3VtZW50cyB0byBwYXNzIHRvIHRoZSB2bGxtIGVuZ2luZS5cbiAgICogQGRlZmF1bHQgLSBubyBzcGVjaWZpYyB2YWx1ZXMuIHVzZSBkZWZhdWx0IHZhbHVlcy5cbiAgICovXG4gIHJlYWRvbmx5IHZsbG1BcmdzPzogVmxsbUVuZ2luZUFyZ3VtZW50cztcbiAgLyoqXG4gICAqIEFuIGltYWdlIG9mIHRoZSBjb250YWluZXIgd2hlcmUgdGhlIGNvbXBpbGUgam9iIGlzIGV4ZWN1dGVkLlxuICAgKiBAZGVmYXVsdCAtIGxhdGVzdCBpbWFnZVxuICAgKi9cbiAgcmVhZG9ubHkgaW1hZ2U/OiBJTmV1cm9ueENvbnRhaW5lckltYWdlO1xuICAvKipcbiAgICogVGhlIEVDMiBpbnN0YW5jZSB0eXBlIHRvIHVzZSBmb3IgY3Jvc3MtY29tcGlsYXRpb24uXG4gICAqIFRoaXMgc2hvdWxkIGJlIGEgbm9uLU5ldXJvbiBpbnN0YW5jZSB0eXBlIHdpdGggc3VmZmljaWVudCBtZW1vcnkgZm9yIG1vZGVsIGNvbXBpbGF0aW9uLlxuICAgKlxuICAgKiBAZGVmYXVsdCAtIEF1dG9tYXRpY2FsbHkgc2VsZWN0ZWQgYmFzZWQgb24gbW9kZWwgc2l6ZVxuICAgKi9cbiAgcmVhZG9ubHkgY29tcGlsZUluc3RhbmNlVHlwZT86IGVjMi5JbnN0YW5jZVR5cGU7XG59XG5cbi8qKlxuICogVGhlIG1vZGVsIGNvbXBpbGVkIGJ5IE5ldXJvbnggY29tcGlsZXIuXG4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgVmxsbU54ZEluZmVyZW5jZUNvbXBpbGVkTW9kZWwgZXh0ZW5kcyBOZXVyb254Q29tcGlsZWRNb2RlbCB7XG4gIC8qKlxuICAgKiBQYXNzZWQgdG8gdGhlIHZsbG0gZW5naW5lIGF0IGNvbXBpbGUgdGltZS5cbiAgICovXG4gIHJlYWRvbmx5IHZsbG1BcmdzOiBWbGxtRW5naW5lQXJndW1lbnRzO1xufVxuXG4vKipcbiAqIE5ldXJvbnggY29tcGlsZXIgY29uc3RydWN0IGZvciB2TExNIG9uIE54RCBJbmZlcmVuY2UuXG4gKiBDb21waWxlIHRoZSBtb2RlbCB0byB3b3JrIHdpdGggTmV1cm9ueCBpbnN0YW5jZSBhbmQgdXBsb2FkIGl0IHRvIGFuIFMzIGJ1Y2tldC5cbiAqL1xuZXhwb3J0IGNsYXNzIFZsbG1OeGRJbmZlcmVuY2VDb21waWxlciBleHRlbmRzIENvbnN0cnVjdCB7XG4gIHByaXZhdGUgcmVhZG9ubHkgdmxsbUFyZ3M6IFZsbG1FbmdpbmVBcmd1bWVudHM7XG4gIHByaXZhdGUgcmVhZG9ubHkgY29tcGlsZXI6IElOZXVyb254Q29tcGlsZXI7XG4gIGNvbnN0cnVjdG9yKFxuICAgIHNjb3BlOiBDb25zdHJ1Y3QsXG4gICAgaWQ6IHN0cmluZyxcbiAgICBwcm9wczogVmxsbU54ZEluZmVyZW5jZUNvbXBpbGVQcm9wcyxcbiAgKSB7XG4gICAgc3VwZXIoc2NvcGUsIGlkKTtcbiAgICBjb25zdCBtYXhNb2RlbExlbiA9IHByb3BzLnZsbG1BcmdzPy5tYXhNb2RlbExlbiA/PyAxMjg7XG4gICAgY29uc3QgbWF4TnVtU2VxcyA9IHByb3BzLnZsbG1BcmdzPy5tYXhOdW1TZXFzID8/IDE7XG4gICAgY29uc3QgbWVtb3J5Rm9vdHByaW50ID0gcHJvcHMubW9kZWwub3B0aW9ucy5jb25maWdcbiAgICAgID8gY2FsY01lbW9yeUZvb3RwcmludChcbiAgICAgICAgICBwcm9wcy5tb2RlbC5vcHRpb25zLmNvbmZpZy5lbWJlZGRpbmdEaW1lbnNpb24sXG4gICAgICAgICAgcHJvcHMubW9kZWwub3B0aW9ucy5jb25maWcubGF5ZXJzLFxuICAgICAgICAgIERhdGFUeXBlQml0cy5CRjE2X09SX0ZQMTYsXG4gICAgICAgICAgbWF4TW9kZWxMZW4sXG4gICAgICAgICAgbWF4TnVtU2VxcyxcbiAgICAgICAgKVxuICAgICAgOiBpbmZlck1lbW9yeUZvb3RwcmludEZyb21QYXJhbWV0ZXJzKFxuICAgICAgICAgIHByb3BzLm1vZGVsLm9wdGlvbnMucGFyYW1ldGVycyxcbiAgICAgICAgICBtYXhNb2RlbExlbixcbiAgICAgICAgICBtYXhOdW1TZXFzLFxuICAgICAgICApO1xuICAgIGNvbnN0IG5ldXJvbnhJbnN0YW5jZVR5cGVzID0gcHJvcHMubmV1cm9ueEluc3RhbmNlVHlwZVxuICAgICAgPyBbcHJvcHMubmV1cm9ueEluc3RhbmNlVHlwZV1cbiAgICAgIDogW1xuICAgICAgICAgIE5ldXJvbnhJbnN0YW5jZVR5cGUuSU5GMl84WExBUkdFLFxuICAgICAgICAgIE5ldXJvbnhJbnN0YW5jZVR5cGUuSU5GMl8yNFhMQVJHRSxcbiAgICAgICAgICBOZXVyb254SW5zdGFuY2VUeXBlLklORjJfNDhYTEFSR0UsXG4gICAgICAgIF07XG4gICAgY29uc3QgYXZhaWxhYmxlSW5zdGFuY2VQYXR0ZXJucyA9IG5ldXJvbnhJbnN0YW5jZVR5cGVzXG4gICAgICAuZmxhdE1hcCgobmV1cm9ueEluc3RhbmNlVHlwZSkgPT5cbiAgICAgICAgY2FsY1RlbnNvclBhcmFsbGVsKFxuICAgICAgICAgIG5ldXJvbnhJbnN0YW5jZVR5cGUsXG4gICAgICAgICAgbWVtb3J5Rm9vdHByaW50LFxuICAgICAgICAgIHByb3BzLm1vZGVsLm9wdGlvbnMuY29uZmlnPy5hdHRlbnRpb25IZWFkcyxcbiAgICAgICAgKS5tYXAoKHYpID0+ICh7XG4gICAgICAgICAgbmV1cm9ueEluc3RhbmNlVHlwZSxcbiAgICAgICAgICAuLi52LFxuICAgICAgICB9KSksXG4gICAgICApXG4gICAgICAuZmlsdGVyKFxuICAgICAgICAoaW5zdGFuY2VUeXBlKSA9PlxuICAgICAgICAgICFwcm9wcy52bGxtQXJncz8udGVuc29yUGFyYWxsZWxTaXplIHx8XG4gICAgICAgICAgaW5zdGFuY2VUeXBlLnRwID09PSBwcm9wcy52bGxtQXJncy50ZW5zb3JQYXJhbGxlbFNpemUsXG4gICAgICApO1xuICAgIGlmIChhdmFpbGFibGVJbnN0YW5jZVBhdHRlcm5zLmxlbmd0aCA9PT0gMCkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKFxuICAgICAgICBgTm8gYXZhaWxhYmxlIGluc3RhbmNlIHR5cGUuIFlvdSBjYW4gdXNlIHRlbnNvclBhcmFsbGVsU2l6ZSBhcmUgJHthdmFpbGFibGVJbnN0YW5jZVBhdHRlcm5zLm1hcCgocCkgPT4gcC50cCkuam9pbihcIiwgXCIpfS5gLFxuICAgICAgKTtcbiAgICB9XG4gICAgY29uc3QgdGVuc29yUGFyYWxsZWxTaXplID0gYXZhaWxhYmxlSW5zdGFuY2VQYXR0ZXJuc1swXS50cDtcbiAgICBjb25zdCBpbWFnZSA9XG4gICAgICBwcm9wcy5pbWFnZSA/PyBuZXcgVmxsbU54ZEluZmVyZW5jZUNvbXBpbGVJbWFnZSh0aGlzLCBcIkNvbXBpbGVJbWFnZVwiKTtcbiAgICBjb25zdCBibG9ja1NpemUgPSBwcm9wcy52bGxtQXJncz8uYmxvY2tTaXplID8/IEJsb2NrU2l6ZS5TSVpFXzMyO1xuICAgIGNvbnN0IHZsbG1BcmdzID0ge1xuICAgICAgLi4ucHJvcHMudmxsbUFyZ3MsXG4gICAgICBtb2RlbDogcHJvcHMubW9kZWwubW9kZWxJZCxcbiAgICAgIHNlcnZlZE1vZGVsTmFtZTogW3Byb3BzLm1vZGVsLm1vZGVsTmFtZV0sXG4gICAgICBtYXhNb2RlbExlbixcbiAgICAgIG1heE51bVNlcXMsXG4gICAgICB0ZW5zb3JQYXJhbGxlbFNpemUsXG4gICAgICBibG9ja1NpemUsXG4gICAgfSBzYXRpc2ZpZXMgVmxsbUVuZ2luZUFyZ3VtZW50cztcblxuICAgIC8vIGNoYW5nZSBkaXJuYW1lIGV2ZXJ5IGVuZ2luZSBhcmdzIHBhdHRlcm5zXG4gICAgY29uc3QgaGFzaCA9IChzdHI6IHN0cmluZykgPT5cbiAgICAgIGNyZWF0ZUhhc2goXCJzaGEyNTZcIikudXBkYXRlKHN0cikuZGlnZXN0KFwiaGV4XCIpO1xuICAgIGNvbnN0IGFydGlmYWN0UzNQcmVmaXggPSBgc2RrLSR7aW1hZ2UubmV1cm9uU2RrVmVyc2lvbn0vJHtoYXNoKEpTT04uc3RyaW5naWZ5KHZsbG1BcmdzKSl9YDtcbiAgICBjb25zdCB2bGxtQ2xpQXJncyA9IFZsbG1FbmdpbmVBcmd1bWVudHNQYXJzZXIuY2xpKHZsbG1BcmdzKTtcbiAgICBjb25zdCBlbnZpcm9ubWVudDogUmVjb3JkPHN0cmluZywgc3RyaW5nPiA9IHtcbiAgICAgIC4uLnByb3BzLmVudmlyb25tZW50LFxuICAgICAgVkxMTV9ORVVST05fRlJBTUVXT1JLOiBcIm5ldXJvbngtZGlzdHJpYnV0ZWQtaW5mZXJlbmNlXCIsXG4gICAgICBORVVST05fQ09NUElMRURfQVJUSUZBQ1RTOiBcIm5ldXJvbi1jb21waWxlZC1hcnRpZmFjdHNcIixcbiAgICAgIE5FVVJPTl9SVF9OVU1fQ09SRVM6IHRlbnNvclBhcmFsbGVsU2l6ZS50b1N0cmluZygpLFxuICAgICAgWExBX0hBTkRMRV9TUEVDSUFMX1NDQUxBUjogXCIxXCIsXG4gICAgICBNT0RFTF9JRDogcHJvcHMubW9kZWwubW9kZWxJZCxcbiAgICAgIE1PREVMX05BTUU6IHByb3BzLm1vZGVsLm1vZGVsTmFtZSxcbiAgICAgIENPTVBJTEVEX0FSVElGQUNUU19TM19VUkk6IHByb3BzLmJ1Y2tldC5zM1VybEZvck9iamVjdChhcnRpZmFjdFMzUHJlZml4KSxcbiAgICAgIENPTVBJTEVEX0FSVElGQUNUU19TM19QUkVGSVg6IGFydGlmYWN0UzNQcmVmaXgsXG4gICAgfTtcbiAgICBjb25zdCBzZWNyZXRzOiB7IFtrZXk6IHN0cmluZ106IGJhdGNoLlNlY3JldCB9ID0ge307XG4gICAgaWYgKHByb3BzLnZsbG1BcmdzPy5oZlRva2VuKSB7XG4gICAgICBzZWNyZXRzLkhGX1RPS0VOID0gcHJvcHMudmxsbUFyZ3MuaGZUb2tlbjtcbiAgICB9XG4gICAgY29uc3Qgd2VpZ2h0U2l6ZSA9IFNpemUuZ2liaWJ5dGVzKFxuICAgICAgcHJvcHMubW9kZWwub3B0aW9ucy5wYXJhbWV0ZXJzLnRvQmlsbGlvbigpICogMi41LFxuICAgICk7XG4gICAgY29uc3QgcXVhbnRpemVkV2lnaHRTaXplID0gcHJvcHMudmxsbUFyZ3M/Lm92ZXJyaWRlTmV1cm9uQ29uZmlnPy5xdWFudGl6ZWRcbiAgICAgID8gd2VpZ2h0U2l6ZVxuICAgICAgOiBTaXplLmJ5dGVzKDApO1xuICAgIGNvbnN0IHZvbHVtZVNpemUgPSBTaXplLmdpYmlieXRlcyhcbiAgICAgIE1hdGguY2VpbChcbiAgICAgICAgd2VpZ2h0U2l6ZS50b0dpYmlieXRlcygpICtcbiAgICAgICAgICBxdWFudGl6ZWRXaWdodFNpemUudG9HaWJpYnl0ZXMoKSArXG4gICAgICAgICAgUHl0b3JjaFRyYWluaW5nTmV1cm9ueEltYWdlLnNpemUudG9HaWJpYnl0ZXMoKSArXG4gICAgICAgICAgTmV1cm9uT3B0aW1pemVkTWFjaGluZUltYWdlLnNpemUudG9HaWJpYnl0ZXMoKSxcbiAgICAgICksXG4gICAgKTtcblxuICAgIGNvbnN0IGNvbXBpbGVyID0gbmV3IE5ldXJvbnhDcm9zc0NvbXBpbGVyKHRoaXMsIFwiUmVzb3VyY2VcIiwge1xuICAgICAgLi4ucHJvcHMsXG4gICAgICBuZXVyb254SW5zdGFuY2VUeXBlOiBhdmFpbGFibGVJbnN0YW5jZVBhdHRlcm5zWzBdLm5ldXJvbnhJbnN0YW5jZVR5cGUsXG4gICAgICBjb21waWxlSW5zdGFuY2VUeXBlOlxuICAgICAgICBwcm9wcy5jb21waWxlSW5zdGFuY2VUeXBlID8/IHNlbGVjdENvbXBpbGVJbnN0YW5jZVR5cGUod2VpZ2h0U2l6ZSksXG4gICAgICBhcnRpZmFjdFMzUHJlZml4LFxuICAgICAgaW1hZ2U6IGltYWdlLFxuICAgICAgY29tbWFuZDogdmxsbUNsaUFyZ3MsXG4gICAgICBlbnZpcm9ubWVudCxcbiAgICAgIHNlY3JldHMsXG4gICAgICB2b2x1bWVTaXplLFxuICAgIH0pO1xuICAgIHRoaXMudmxsbUFyZ3MgPSB2bGxtQXJncztcbiAgICB0aGlzLmNvbXBpbGVyID0gY29tcGlsZXI7XG4gIH1cbiAgLyoqXG4gICAqIENvbXBpbGUgdGhlIG1vZGVsIGFuZCByZXR1cm4gdGhlIGNvbXBpbGVkIG1vZGVsLlxuICAgKiBAcmV0dXJucyBUaGUgY29tcGlsZWQgbW9kZWwuXG4gICAqL1xuICBjb21waWxlKCk6IFZsbG1OeGRJbmZlcmVuY2VDb21waWxlZE1vZGVsIHtcbiAgICByZXR1cm4ge1xuICAgICAgLi4udGhpcy5jb21waWxlci5jb21waWxlKCksXG4gICAgICB2bGxtQXJnczogdGhpcy52bGxtQXJncyxcbiAgICB9IHNhdGlzZmllcyBWbGxtTnhkSW5mZXJlbmNlQ29tcGlsZWRNb2RlbDtcbiAgfVxufVxuIl19