gx
chenyc
2025-06-12 7b72ac13a83764a662159d4a49b7fffb90476ecb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
/**
 * @license
 * Copyright 2023 Google LLC.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 * =============================================================================
 */
/**
 *  Base class for Backbone models.
 */
/* Original source: keras_nlp/models/gpt2/gpt2_backbone.py */
import { serialization } from '@tensorflow/tfjs-core';
import { RandomNormal } from '../../../../initializers';
import { input } from '../../../../exports';
import { Embedding } from '../../../embeddings';
import { PositionEmbedding } from '../../modeling/position_embedding';
import { add } from '../../../../exports_layers';
import { Dropout } from '../../../core';
import { TransformerDecoder } from '../../modeling/transformer_decoder';
import { getActivation } from '../../../../activations';
import { LayerNormalization } from '../../../normalization';
import { Backbone } from '../backbone';
function gpt2KernelInitializer(stddev = 0.02) {
    return new RandomNormal({ stddev });
}
/**
 * GPT-2 core network with hyperparameters.
 *
 * This network implements a Transformer-based decoder network,
 * Generative Pretrained Transformer-2 (GPT-2), as described in
 * ["Language Models are Unsupervised Multitask Learners"](https://cdn.openai.com/better-language-models/language_models_are_unsupervised_multitask_learners.pdf).
 * It includes the embedding lookups and transformer layers.
 *
 * The default constructor gives a fully customizable, randomly initialized
 * GPT-2 model with any number of layers, heads, and embedding
 * dimensions. To load preset architectures and weights, use the `fromPreset`
 * constructor.
 *
 * Disclaimer: Pre-trained models are provided on an "as is" basis, without
 * warranties or conditions of any kind. The underlying model is provided by a
 * third party and subject to a separate license, available
 * [here](https://github.com/openai/gpt-2).
 *
 *
 * Example usage:
 * ```js
 * const tokenIds = tf.ones([1, 12]), dtype="int32");
 * const paddingMask = tf.tensor(
 *  [[1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0]], 'int32');
 *
 * # Pretrained GPT-2 decoder.
 * model = GPT2Backbone.fromPreset("gpt2_base_en");
 * model.apply(inputData, {paddingMask});
 *
 * # Randomly initialized GPT-2 decoder with custom config.
 * model = kerasNlp.models.GPT2Backbone({
 *     vocabularySize: 50257,
 *     numLayers: 12,
 *     numHeads: 12,
 *     hiddenDim: 768,
 *     intermediateDim: 3072,
 *     maxSequenceLength: 1024,
 * });
 * model.apply(inputData, {paddingMask});
 * ```
 */
class GPT2Backbone extends Backbone {
    constructor(args) {
        var _a, _b, _c, _d;
        args.dropout = (_a = args.dropout) !== null && _a !== void 0 ? _a : 0.1;
        args.maxSequenceLength = (_b = args.maxSequenceLength) !== null && _b !== void 0 ? _b : 1024;
        // Inputs
        const tokenIds = input({ shape: [null], dtype: 'int32', name: 'token_ids' });
        const paddingMask = input({ shape: [null], dtype: 'int32', name: 'padding_mask' });
        // Embed tokens, positions.
        const tokenEmbedding = new Embedding({
            inputDim: args.vocabularySize,
            outputDim: args.hiddenDim,
            embeddingsInitializer: gpt2KernelInitializer(0.01),
            name: 'token_embedding',
        }).apply(tokenIds);
        const positionEmbedding = new PositionEmbedding({
            initializer: gpt2KernelInitializer(0.02),
            sequenceLength: args.maxSequenceLength,
            name: 'position_embedding',
        }).apply(tokenEmbedding);
        // Sum and apply dropout to embeddings.
        let x = add({ name: 'embeddings_add' })
            .apply([tokenEmbedding, positionEmbedding]);
        x = new Dropout({ rate: args.dropout, name: 'embeddings_dropout' })
            .apply(x);
        // Apply successive transformer decoder blocks.
        for (let i = 0; i < args.numLayers; i++) {
            x = new TransformerDecoder({
                intermediateDim: args.intermediateDim,
                numHeads: args.numHeads,
                dropout: args.dropout,
                layerNormEpsilon: 1e-05,
                // TODO(pforderique): Implement gelu.
                activation: getActivation('relu'),
                kernelInitializer: gpt2KernelInitializer(0.02),
                normalizeFirst: true,
                name: `transformer_layer_${i}`,
            }).apply(x, { decoderPaddingMask: paddingMask });
        }
        const sequenceOutput = new LayerNormalization({
            name: 'layer_norm',
            axis: -1,
            epsilon: 1e-05,
            dtype: 'float32',
        }).apply(x);
        // Instantiate using Functional API Model constructor.
        super({
            inputs: [tokenIds, paddingMask],
            outputs: sequenceOutput,
            name: 'gpt2_backbone'
        });
        this.vocabularySize = args.vocabularySize;
        this.numLayers = args.numLayers;
        this.numHeads = args.numHeads;
        this.hiddenDim = args.hiddenDim;
        this.intermediateDim = args.intermediateDim;
        this.dropout = (_c = args.dropout) !== null && _c !== void 0 ? _c : 0.1;
        this.maxSequenceLength = (_d = args.maxSequenceLength) !== null && _d !== void 0 ? _d : 1024;
    }
    getConfig() {
        const config = {
            vocabularySize: this.vocabularySize,
            numLayers: this.numLayers,
            numHeads: this.numHeads,
            hiddenDim: this.hiddenDim,
            intermediateDim: this.intermediateDim,
            dropout: this.dropout,
            maxSequenceLength: this.maxSequenceLength,
        };
        const baseConfig = super.getConfig();
        Object.assign(config, baseConfig);
        return config;
    }
    get tokenEmbedding() {
        return this.getLayer('token_embedding');
    }
}
/** @nocollapse */
GPT2Backbone.className = 'GPT2Backbone';
export { GPT2Backbone };
serialization.registerClass(GPT2Backbone);
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZ3B0Ml9iYWNrYm9uZS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uLy4uLy4uLy4uLy4uLy4uL3RmanMtbGF5ZXJzL3NyYy9sYXllcnMvbmxwL21vZGVscy9ncHQyL2dwdDJfYmFja2JvbmUudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUE7Ozs7Ozs7Ozs7Ozs7OztHQWVHO0FBRUg7O0dBRUc7QUFFSCw2REFBNkQ7QUFDN0QsT0FBTyxFQUFFLGFBQWEsRUFBRSxNQUFNLHVCQUF1QixDQUFDO0FBRXRELE9BQU8sRUFBRSxZQUFZLEVBQUUsTUFBTSwwQkFBMEIsQ0FBQztBQUN4RCxPQUFPLEVBQUUsS0FBSyxFQUFFLE1BQU0scUJBQXFCLENBQUM7QUFDNUMsT0FBTyxFQUFFLFNBQVMsRUFBRSxNQUFNLHFCQUFxQixDQUFDO0FBRWhELE9BQU8sRUFBRSxpQkFBaUIsRUFBRSxNQUFNLG1DQUFtQyxDQUFDO0FBQ3RFLE9BQU8sRUFBRSxHQUFHLEVBQUUsTUFBTSw0QkFBNEIsQ0FBQztBQUNqRCxPQUFPLEVBQUUsT0FBTyxFQUFFLE1BQU0sZUFBZSxDQUFDO0FBQ3hDLE9BQU8sRUFBRSxrQkFBa0IsRUFBRSxNQUFNLG9DQUFvQyxDQUFDO0FBQ3hFLE9BQU8sRUFBRSxhQUFhLEVBQUUsTUFBTSx5QkFBeUIsQ0FBQztBQUN4RCxPQUFPLEVBQUUsa0JBQWtCLEVBQUUsTUFBTSx3QkFBd0IsQ0FBQztBQUM1RCxPQUFPLEVBQUUsUUFBUSxFQUFFLE1BQU0sYUFBYSxDQUFDO0FBRXZDLFNBQVMscUJBQXFCLENBQUMsTUFBTSxHQUFHLElBQUk7SUFDMUMsT0FBTyxJQUFJLFlBQVksQ0FBQyxFQUFDLE1BQU0sRUFBQyxDQUFDLENBQUM7QUFDcEMsQ0FBQztBQTZDRDs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztHQXdDRztBQUNILE1BQWEsWUFBYSxTQUFRLFFBQVE7SUFZeEMsWUFBWSxJQUFzQjs7UUFDaEMsSUFB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QUMiLCJzb3VyY2VzQ29udGVudCI6WyIvKipcbiAqIEBsaWNlbnNlXG4gKiBDb3B5cmlnaHQgMjAyMyBHb29nbGUgTExDLlxuICogTGljZW5zZWQgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlIFwiTGljZW5zZVwiKTtcbiAqIHlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2Ugd2l0aCB0aGUgTGljZW5zZS5cbiAqIFlvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdFxuICpcbiAqIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuICpcbiAqIFVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbiAqIGRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbiAqIFdJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuICogU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxuICogbGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG4gKiA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PVxuICovXG5cbi8qKlxuICogIEJhc2UgY2xhc3MgZm9yIEJhY2tib25lIG1vZGVscy5cbiAqL1xuXG4vKiBPcmlnaW5hbCBzb3VyY2U6IGtlcmFzX25scC9tb2RlbHMvZ3B0Mi9ncHQyX2JhY2tib25lLnB5ICovXG5pbXBvcnQgeyBzZXJpYWxpemF0aW9uIH0gZnJvbSAnQHRlbnNvcmZsb3cvdGZqcy1jb3JlJztcblxuaW1wb3J0IHsgUmFuZG9tTm9ybWFsIH0gZnJvbSAnLi4vLi4vLi4vLi4vaW5pdGlhbGl6ZXJzJztcbmltcG9ydCB7IGlucHV0IH0gZnJvbSAnLi4vLi4vLi4vLi4vZXhwb3J0cyc7XG5pbXBvcnQgeyBFbWJlZGRpbmcgfSBmcm9tICcuLi8uLi8uLi9lbWJlZGRpbmdzJztcbmltcG9ydCB7IFN5bWJvbGljVGVuc29yIH0gZnJvbSAnLi4vLi4vLi4vLi4vZW5naW5lL3RvcG9sb2d5JztcbmltcG9ydCB7IFBvc2l0aW9uRW1iZWRkaW5nIH0gZnJvbSAnLi4vLi4vbW9kZWxpbmcvcG9zaXRpb25fZW1iZWRkaW5nJztcbmltcG9ydCB7IGFkZCB9IGZyb20gJy4uLy4uLy4uLy4uL2V4cG9ydHNfbGF5ZXJzJztcbmltcG9ydCB7IERyb3BvdXQgfSBmcm9tICcuLi8uLi8uLi9jb3JlJztcbmltcG9ydCB7IFRyYW5zZm9ybWVyRGVjb2RlciB9IGZyb20gJy4uLy4uL21vZGVsaW5nL3RyYW5zZm9ybWVyX2RlY29kZXInO1xuaW1wb3J0IHsgZ2V0QWN0aXZhdGlvbiB9IGZyb20gJy4uLy4uLy4uLy4uL2FjdGl2YXRpb25zJztcbmltcG9ydCB7IExheWVyTm9ybWFsaXphdGlvbiB9IGZyb20gJy4uLy4uLy4uL25vcm1hbGl6YXRpb24nO1xuaW1wb3J0IHsgQmFja2JvbmUgfSBmcm9tICcuLi9iYWNrYm9uZSc7XG5cbmZ1bmN0aW9uIGdwdDJLZXJuZWxJbml0aWFsaXplcihzdGRkZXYgPSAwLjAyKSB7XG4gIHJldHVybiBuZXcgUmFuZG9tTm9ybWFsKHtzdGRkZXZ9KTtcbn1cblxuZXhwb3J0IGludGVyZmFjZSBHUFQyQmFja2JvbmVBcmdzICB7XG4gIC8qKlxuICAgKiBJbnRlZ2VyLiBUaGUgc2l6ZSBvZiB0aGUgdG9rZW4gdm9jYWJ1bGFyeS5cbiAgICovXG4gIHZvY2FidWxhcnlTaXplOiBudW1iZXI7XG5cbiAgLyoqXG4gICAqIEludGVnZXIuIFRoZSBudW1iZXIgb2YgdHJhbnNmb3JtZXIgbGF5ZXJzLlxuICAgKi9cbiAgbnVtTGF5ZXJzOiBudW1iZXI7XG5cbiAgLyoqXG4gICAqIEludGVnZXIuIFRoZSBudW1iZXIgb2YgYXR0ZW50aW9uIGhlYWRzIGZvciBlYWNoIHRyYW5zZm9ybWVyLlxuICAgKiBUaGUgaGlkZGVuIHNpemUgbXVzdCBiZSBkaXZpc2libGUgYnkgdGhlIG51bWJlciBvZiBhdHRlbnRpb24gaGVhZHMuXG4gICAqL1xuICBudW1IZWFkczogbnVtYmVyO1xuXG4gIC8qKlxuICAgKiBJbnRlZ2VyLiBUaGUgc2l6ZSBvZiB0aGUgdHJhbnNmb3JtZXIgZW5jb2RpbmcgYW5kIHBvb2xlciBsYXllcnMuXG4gICAqL1xuICBoaWRkZW5EaW06IG51bWJlcjtcblxuICAvKipcbiAgICogSW50ZWdlci4gVGhlIG91dHB1dCBkaW1lbnNpb24gb2YgdGhlIGZpcnN0IERlbnNlIGxheWVyIGluIGEgdHdvLWxheWVyXG4gICAqIGZlZWRmb3J3YXJkIG5ldHdvcmsgZm9yIGVhY2ggdHJhbnNmb3JtZXIuXG4gICAqL1xuICBpbnRlcm1lZGlhdGVEaW06IG51bWJlcjtcblxuICAvKipcbiAgICogRmxvYXQuIERyb3BvdXQgcHJvYmFiaWxpdHkgZm9yIHRoZSBUcmFuc2Zvcm1lciBlbmNvZGVyLlxuICAgKiBEZWZhdWx0cyB0byAwLjIuXG4gICAqL1xuICBkcm9wb3V0PzogbnVtYmVyO1xuXG4gIC8qKlxuICAgKiBJbnRlZ2VyLiBUaGUgbWF4aW11bSBzZXF1ZW5jZSBsZW5ndGggdGhhdCB0aGlzIGVuY29kZXIgY2FuIGNvbnN1bWUuXG4gICAqIElmIGBudWxsYCwgYG1heFNlcXVlbmNlTGVuZ3RoYCB1c2VzIHRoZSB2YWx1ZSBmcm9tIHNlcXVlbmNlIGxlbmd0aC5cbiAgICogVGhpcyBkZXRlcm1pbmVzIHRoZSB2YXJpYWJsZSBzaGFwZSBmb3IgcG9zaXRpb25hbCBlbWJlZGRpbmdzLlxuICAgKiBEZWZhdWx0cyB0byAxMDI0LlxuICAgKi9cbiAgbWF4U2VxdWVuY2VMZW5ndGg/OiBudW1iZXI7XG59XG5cbi8qKlxuICogR1BULTIgY29yZSBuZXR3b3JrIHdpdGggaHlwZXJwYXJhbWV0ZXJzLlxuICpcbiAqIFRoaXMgbmV0d29yayBpbXBsZW1lbnRzIGEgVHJhbnNmb3JtZXItYmFzZWQgZGVjb2RlciBuZXR3b3JrLFxuICogR2VuZXJhdGl2ZSBQcmV0cmFpbmVkIFRyYW5zZm9ybWVyLTIgKEdQVC0yKSwgYXMgZGVzY3JpYmVkIGluXG4gKiBbXCJMYW5ndWFnZSBNb2RlbHMgYXJlIFVuc3VwZXJ2aXNlZCBNdWx0aXRhc2sgTGVhcm5lcnNcIl0oaHR0cHM6Ly9jZG4ub3BlbmFpLmNvbS9iZXR0ZXItbGFuZ3VhZ2UtbW9kZWxzL2xhbmd1YWdlX21vZGVsc19hcmVfdW5zdXBlcnZpc2VkX211bHRpdGFza19sZWFybmVycy5wZGYpLlxuICogSXQgaW5jbHVkZXMgdGhlIGVtYmVkZGluZyBsb29rdXBzIGFuZCB0cmFuc2Zvcm1lciBsYXllcnMuXG4gKlxuICogVGhlIGRlZmF1bHQgY29uc3RydWN0b3IgZ2l2ZXMgYSBmdWxseSBjdXN0b21pemFibGUsIHJhbmRvbWx5IGluaXRpYWxpemVkXG4gKiBHUFQtMiBtb2RlbCB3aXRoIGFueSBudW1iZXIgb2YgbGF5ZXJzLCBoZWFkcywgYW5kIGVtYmVkZGluZ1xuICogZGltZW5zaW9ucy4gVG8gbG9hZCBwcmVzZXQgYXJjaGl0ZWN0dXJlcyBhbmQgd2VpZ2h0cywgdXNlIHRoZSBgZnJvbVByZXNldGBcbiAqIGNvbnN0cnVjdG9yLlxuICpcbiAqIERpc2NsYWltZXI6IFByZS10cmFpbmVkIG1vZGVscyBhcmUgcHJvdmlkZWQgb24gYW4gXCJhcyBpc1wiIGJhc2lzLCB3aXRob3V0XG4gKiB3YXJyYW50aWVzIG9yIGNvbmRpdGlvbnMgb2YgYW55IGtpbmQuIFRoZSB1bmRlcmx5aW5nIG1vZGVsIGlzIHByb3ZpZGVkIGJ5IGFcbiAqIHRoaXJkIHBhcnR5IGFuZCBzdWJqZWN0IHRvIGEgc2VwYXJhdGUgbGljZW5zZSwgYXZhaWxhYmxlXG4gKiBbaGVyZV0oaHR0cHM6Ly9naXRodWIuY29tL29wZW5haS9ncHQtMikuXG4gKlxuICpcbiAqIEV4YW1wbGUgdXNhZ2U6XG4gKiBgYGBqc1xuICogY29uc3QgdG9rZW5JZHMgPSB0Zi5vbmVzKFsxLCAxMl0pLCBkdHlwZT1cImludDMyXCIpO1xuICogY29uc3QgcGFkZGluZ01hc2sgPSB0Zi50ZW5zb3IoXG4gKiAgW1sxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAwLCAwXV0sICdpbnQzMicpO1xuICpcbiAqICMgUHJldHJhaW5lZCBHUFQtMiBkZWNvZGVyLlxuICogbW9kZWwgPSBHUFQyQmFja2JvbmUuZnJvbVByZXNldChcImdwdDJfYmFzZV9lblwiKTtcbiAqIG1vZGVsLmFwcGx5KGlucHV0RGF0YSwge3BhZGRpbmdNYXNrfSk7XG4gKlxuICogIyBSYW5kb21seSBpbml0aWFsaXplZCBHUFQtMiBkZWNvZGVyIHdpdGggY3VzdG9tIGNvbmZpZy5cbiAqIG1vZGVsID0ga2VyYXNObHAubW9kZWxzLkdQVDJCYWNrYm9uZSh7XG4gKiAgICAgdm9jYWJ1bGFyeVNpemU6IDUwMjU3LFxuICogICAgIG51bUxheWVyczogMTIsXG4gKiAgICAgbnVtSGVhZHM6IDEyLFxuICogICAgIGhpZGRlbkRpbTogNzY4LFxuICogICAgIGludGVybWVkaWF0ZURpbTogMzA3MixcbiAqICAgICBtYXhTZXF1ZW5jZUxlbmd0aDogMTAyNCxcbiAqIH0pO1xuICogbW9kZWwuYXBwbHkoaW5wdXREYXRhLCB7cGFkZGluZ01hc2t9KTtcbiAqIGBgYFxuICovXG5leHBvcnQgY2xhc3MgR1BUMkJhY2tib25lIGV4dGVuZHMgQmFja2JvbmUge1xuICAvKiogQG5vY29sbGFwc2UgKi9cbiAgc3RhdGljIG92ZXJyaWRlIGNsYXNzTmFtZSA9ICdHUFQyQmFja2JvbmUnO1xuXG4gIHByaXZhdGUgdm9jYWJ1bGFyeVNpemU6IG51bWJlcjtcbiAgcHJpdmF0ZSBudW1MYXllcnM6IG51bWJlcjtcbiAgcHJpdmF0ZSBudW1IZWFkczogbnVtYmVyO1xuICBwcml2YXRlIGhpZGRlbkRpbTogbnVtYmVyO1xuICBwcml2YXRlIGludGVybWVkaWF0ZURpbTogbnVtYmVyO1xuICBwcml2YXRlIGRyb3BvdXQ6IG51bWJlcjtcbiAgcHJpdmF0ZSBtYXhTZXF1ZW5jZUxlbmd0aDogbnVtYmVyO1xuXG4gIGNvbnN0cnVjdG9yKGFyZ3M6IEdQVDJCYWNrYm9uZUFyZ3MpIHtcbiAgICBhcmdzLmRyb3BvdXQgPSBhcmdzLmRyb3BvdXQgPz8gMC4xO1xuICAgIGFyZ3MubWF4U2VxdWVuY2VMZW5ndGggPSBhcmdzLm1heFNlcXVlbmNlTGVuZ3RoID8/IDEwMjQ7XG5cbiAgICAvLyBJbnB1dHNcbiAgICBjb25zdCB0b2tlbklkcyA9IGlucHV0KHtzaGFwZTogW251bGxdLCBkdHlwZTogJ2ludDMyJywgbmFtZTogJ3Rva2VuX2lkcyd9KTtcbiAgICBjb25zdCBwYWRkaW5nTWFzayA9XG4gICAgICBpbnB1dCh7c2hhcGU6IFtudWxsXSwgZHR5cGU6ICdpbnQzMicsIG5hbWU6ICdwYWRkaW5nX21hc2snfSk7XG5cbiAgICAvLyBFbWJlZCB0b2tlbnMsIHBvc2l0aW9ucy5cbiAgICBjb25zdCB0b2tlbkVtYmVkZGluZyA9IG5ldyBFbWJlZGRpbmcoe1xuICAgICAgaW5wdXREaW06IGFyZ3Mudm9jYWJ1bGFyeVNpemUsXG4gICAgICBvdXRwdXREaW06IGFyZ3MuaGlkZGVuRGltLFxuICAgICAgZW1iZWRkaW5nc0luaXRpYWxpemVyOiBncHQyS2VybmVsSW5pdGlhbGl6ZXIoMC4wMSksXG4gICAgICBuYW1lOiAndG9rZW5fZW1iZWRkaW5nJyxcbiAgICB9KS5hcHBseSh0b2tlbklkcykgYXMgU3ltYm9saWNUZW5zb3I7XG5cbiAgICBjb25zdCBwb3NpdGlvbkVtYmVkZGluZyA9IG5ldyBQb3NpdGlvbkVtYmVkZGluZyh7XG4gICAgICBpbml0aWFsaXplcjogZ3B0Mktlcm5lbEluaXRpYWxpemVyKDAuMDIpLFxuICAgICAgc2VxdWVuY2VMZW5ndGg6IGFyZ3MubWF4U2VxdWVuY2VMZW5ndGgsXG4gICAgICBuYW1lOiAncG9zaXRpb25fZW1iZWRkaW5nJyxcbiAgICB9KS5hcHBseSh0b2tlbkVtYmVkZGluZykgYXMgU3ltYm9saWNUZW5zb3I7XG5cbiAgICAvLyBTdW0gYW5kIGFwcGx5IGRyb3BvdXQgdG8gZW1iZWRkaW5ncy5cbiAgICBsZXQgeCA9IGFkZCh7bmFtZTogJ2VtYmVkZGluZ3NfYWRkJ30pXG4gICAgICAuYXBwbHkoW3Rva2VuRW1iZWRkaW5nLCBwb3NpdGlvbkVtYmVkZGluZ10pIGFzIFN5bWJvbGljVGVuc29yO1xuICAgIHggPSBuZXcgRHJvcG91dCh7cmF0ZTogYXJncy5kcm9wb3V0LCBuYW1lOiAnZW1iZWRkaW5nc19kcm9wb3V0J30pXG4gICAgICAuYXBwbHkoeCkgYXMgU3ltYm9saWNUZW5zb3I7XG5cbiAgICAvLyBBcHBseSBzdWNjZXNzaXZlIHRyYW5zZm9ybWVyIGRlY29kZXIgYmxvY2tzLlxuICAgIGZvcihsZXQgaSA9IDA7IGkgPCBhcmdzLm51bUxheWVyczsgaSsrKSB7XG4gICAgICB4ID0gbmV3IFRyYW5zZm9ybWVyRGVjb2Rlcih7XG4gICAgICAgIGludGVybWVkaWF0ZURpbTogYXJncy5pbnRlcm1lZGlhdGVEaW0sXG4gICAgICAgIG51bUhlYWRzOiBhcmdzLm51bUhlYWRzLFxuICAgICAgICBkcm9wb3V0OiBhcmdzLmRyb3BvdXQsXG4gICAgICAgIGxheWVyTm9ybUVwc2lsb246IDFlLTA1LFxuICAgICAgICAvLyBUT0RPKHBmb3JkZXJpcXVlKTogSW1wbGVtZW50IGdlbHUuXG4gICAgICAgIGFjdGl2YXRpb246IGdldEFjdGl2YXRpb24oJ3JlbHUnKSxcbiAgICAgICAga2VybmVsSW5pdGlhbGl6ZXI6IGdwdDJLZXJuZWxJbml0aWFsaXplcigwLjAyKSxcbiAgICAgICAgbm9ybWFsaXplRmlyc3Q6IHRydWUsXG4gICAgICAgIG5hbWU6IGB0cmFuc2Zvcm1lcl9sYXllcl8ke2l9YCxcbiAgICAgIH0pLmFwcGx5KHgsIHtkZWNvZGVyUGFkZGluZ01hc2s6IHBhZGRpbmdNYXNrfSkgYXMgU3ltYm9saWNUZW5zb3I7XG4gICAgfVxuXG4gICAgY29uc3Qgc2VxdWVuY2VPdXRwdXQgPSBuZXcgTGF5ZXJOb3JtYWxpemF0aW9uKHtcbiAgICAgIG5hbWU6ICdsYXllcl9ub3JtJyxcbiAgICAgIGF4aXM6IC0xLFxuICAgICAgZXBzaWxvbjogMWUtMDUsXG4gICAgICBkdHlwZTogJ2Zsb2F0MzInLFxuICAgIH0pLmFwcGx5KHgpIGFzIFN5bWJvbGljVGVuc29yO1xuXG4gICAgLy8gSW5zdGFudGlhdGUgdXNpbmcgRnVuY3Rpb25hbCBBUEkgTW9kZWwgY29uc3RydWN0b3IuXG4gICAgc3VwZXIoe1xuICAgICAgaW5wdXRzOiBbdG9rZW5JZHMsIHBhZGRpbmdNYXNrXSxcbiAgICAgIG91dHB1dHM6IHNlcXVlbmNlT3V0cHV0LFxuICAgICAgbmFtZTogJ2dwdDJfYmFja2JvbmUnXG4gICAgfSk7XG4gICAgdGhpcy52b2NhYnVsYXJ5U2l6ZSA9IGFyZ3Mudm9jYWJ1bGFyeVNpemU7XG4gICAgdGhpcy5udW1MYXllcnMgPSBhcmdzLm51bUxheWVycztcbiAgICB0aGlzLm51bUhlYWRzID0gYXJncy5udW1IZWFkcztcbiAgICB0aGlzLmhpZGRlbkRpbSA9IGFyZ3MuaGlkZGVuRGltO1xuICAgIHRoaXMuaW50ZXJtZWRpYXRlRGltID0gYXJncy5pbnRlcm1lZGlhdGVEaW07XG4gICAgdGhpcy5kcm9wb3V0ID0gYXJncy5kcm9wb3V0ID8/IDAuMTtcbiAgICB0aGlzLm1heFNlcXVlbmNlTGVuZ3RoID0gYXJncy5tYXhTZXF1ZW5jZUxlbmd0aCA/PyAxMDI0O1xuICB9XG5cbiAgb3ZlcnJpZGUgZ2V0Q29uZmlnKCk6IHNlcmlhbGl6YXRpb24uQ29uZmlnRGljdCB7XG4gICAgY29uc3QgY29uZmlnOiBzZXJpYWxpemF0aW9uLkNvbmZpZ0RpY3QgPSB7XG4gICAgICB2b2NhYnVsYXJ5U2l6ZTogdGhpcy52b2NhYnVsYXJ5U2l6ZSxcbiAgICAgIG51bUxheWVyczogdGhpcy5udW1MYXllcnMsXG4gICAgICBudW1IZWFkczogdGhpcy5udW1IZWFkcyxcbiAgICAgIGhpZGRlbkRpbTogdGhpcy5oaWRkZW5EaW0sXG4gICAgICBpbnRlcm1lZGlhdGVEaW06IHRoaXMuaW50ZXJtZWRpYXRlRGltLFxuICAgICAgZHJvcG91dDogdGhpcy5kcm9wb3V0LFxuICAgICAgbWF4U2VxdWVuY2VMZW5ndGg6IHRoaXMubWF4U2VxdWVuY2VMZW5ndGgsXG4gICAgfTtcbiAgICBjb25zdCBiYXNlQ29uZmlnID0gc3VwZXIuZ2V0Q29uZmlnKCk7XG4gICAgT2JqZWN0LmFzc2lnbihjb25maWcsIGJhc2VDb25maWcpO1xuICAgIHJldHVybiBjb25maWc7XG4gIH1cblxuICBvdmVycmlkZSBnZXQgdG9rZW5FbWJlZGRpbmcoKTogRW1iZWRkaW5nIHtcbiAgICByZXR1cm4gdGhpcy5nZXRMYXllcigndG9rZW5fZW1iZWRkaW5nJykgYXMgRW1iZWRkaW5nO1xuICB9XG59XG5zZXJpYWxpemF0aW9uLnJlZ2lzdGVyQ2xhc3MoR1BUMkJhY2tib25lKTtcbiJdfQ==