secryst 0.1.0 → 1.0.0

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 919071d9eb29b220b762212fafe8f7f7ace0f0605cde7c0402dbbe8eac2584c6
4
- data.tar.gz: de1b20e79c10d14261c71e0043e82a196b38b531da2fcdec0db44bcb992c7239
3
+ metadata.gz: 185de54f6ce981b7739770b422262452752460c5559e029e4b5039f67f6483ef
4
+ data.tar.gz: df7df11ff4fc5a476074e8155448a3b1ab0577ab693c37e796a98c0cf7934af8
5
5
  SHA512:
6
- metadata.gz: 94bfb8aff36218341cd5baa3bcb0eb48e5be147c54f4a8b072e25a82ae027c07bacc7769fafb7f657cff9f638f9a0a4a21385108f0a45384bdf1a7796c74ea67
7
- data.tar.gz: a1fee058281400822908c30a2d5fcf27ceb320dfed8d78878986460323d4028e78fa89db1579146870864fd2104238ee038e9f7468710863ed16ab6c8652ce03
6
+ metadata.gz: 1c51c600385d5a05e9f9298925f2ba7fb1c32a49b26f0345d877c8a11da04459a50d4adb5a23aedac480212e5b83af621a917db472382194ddeb716bd2ae5c4f
7
+ data.tar.gz: 558249e6dcf7ec5cb927512f6487ee8edd911cb06f9f1685bd4ab1b00ec651e230940880cc2c0f3cd61a095a37c3dc0cad046ea4299b25acdd5ee2669ba35df4
data/README.adoc CHANGED
@@ -1,3 +1,53 @@
1
+ == secryst 1.0 — modernized
2
+
3
+ *Secryst* is coined from *scrying* + *crystal*: gazing into an opaque
4
+ script to reveal its hidden reading — the vowels, phonemes, and word
5
+ boundaries that live in the reader's mind but not on the page. This gem
6
+ is the Ruby crystal of the family (Python: `pip install secryst` at
7
+ https://github.com/secryst/secryst-py[secryst/secryst-py]; TypeScript:
8
+ `npm i secryst`). All crystals implement the *interscript-ml* contract —
9
+ the `models.yaml` index, IMF v1 model zips, and shared golden sets
10
+ (https://github.com/interscript/interscript-ml[interscript/interscript-ml]) — and
11
+ are diffed against each other in CI. Overrides: `SECRYST_INDEX`,
12
+ `SECRYST_CACHE` (default `~/.cache/secryst`).
13
+
14
+ Secryst transliterates text using neural sequence-to-sequence models,
15
+ with training in Python (PyTorch + HuggingFace) and inference in pure
16
+ Ruby via https://github.com/secryst/onnxruntime[secryst/onnxruntime] —
17
+ no libtorch, no native compilation.
18
+
19
+ === New in 1.0
20
+
21
+ - *Byte-level models (ByT5 family)*: model zips now contain
22
+ `encoder.onnx` + `decoder.onnx` + `metadata.yaml` (`name: byt5`).
23
+ The tokenizer is UTF-8 bytes themselves (pad=0, EOS=1) — no vocab
24
+ files.
25
+ - *Modern training stack*: ByT5/umt5 fine-tuning, Muon optimizer
26
+ variants, CTC/curriculum ablations, Modal pipelines (see `src/`,
27
+ `train_*.py`, `docs/RESULTS.md`).
28
+ - *Legacy single-file ONNX zips* (vocabs.yaml based) still load.
29
+ - The old Ruby trainer and libtorch/TorchScript path are removed —
30
+ training lives in Python now.
31
+
32
+ === Export a trained checkpoint
33
+
34
+ ....
35
+ python scripts/export_onnx_byt5.py <hf_checkpoint_dir> khm-latn-byt5.zip
36
+ ....
37
+
38
+ === Use from Ruby
39
+
40
+ ....
41
+ translator = Secryst::Translator.new(model_file: 'khm-latn-byt5.zip')
42
+ translator.translate('ភាសាខ្មែរ')
43
+ ....
44
+
45
+ === CLI
46
+
47
+ ....
48
+ secryst translate -f khm-latn-byt5.zip -i 'ភាសាខ្មែរ'
49
+ secryst install <model-name> # via Secrystfile remotes
50
+ ....
1
51
  = Secryst
2
52
 
3
53
  image:https://github.com/secryst/secryst/workflows/test/badge.svg["Build status", link="https://github.com/secryst/secryst/actions?workflow=test"]
@@ -17,22 +67,143 @@ The goal is to allow:
17
67
  * Users of the library in Ruby who only want to "use" the trained models should not require special bindings to run.
18
68
 
19
69
 
20
- == Status
70
+ == Introduction
21
71
 
22
- Currently Secryst works with the Khmer Romanization system as cited below.
72
+ Secryst works with a number of Romanization and transliteration systems.
73
+
74
+ It is composed of two separate pieces of software (Ruby gems):
75
+
76
+ * Secryst Translator: `secryst`, for users of trained models
77
+ * Secryst Trainer: `secryst-trainer` for users who wish to train models
78
+
79
+ Secryst models are platform-independent, interoperable
80
+ and transferrable across installations.
81
+
82
+ There are two types of Secryst models:
83
+
84
+ Secryst ONNX model (recommended)::
85
+ These can be run on any platform without `libtorch`
86
+ (which requires installation of development tools).
87
+
88
+ Secryst Torch model::
89
+ These require `libtorch` to run. Secryst Torch models are trained in Ruby.
90
+
91
+ Secryst Torch models can be converted to Secryst ONNX models
92
+ via Python using instructions below.
93
+
94
+ Secryst Trainer also supports checkpoint resumption.
95
+
96
+
97
+ == Examples
98
+
99
+ Under the `examples/` directory the following systems are provided
100
+
101
+ * `examples/khm-latn`: Khmer Romanization
102
+ * `examples/arm-latn`: Armenian Romanization based on Wikipedia data
23
103
 
24
104
 
25
105
  == Prerequisites
26
106
 
27
- * Ruby 2.7 (*MUST* - 2.6 does not work with the latest torch-rb)
28
107
 
29
- * `libtorch` (1.6.0)
108
+ === Secryst Translator
109
+
110
+ ==== Basic (usage of Secryst ONNX models only)
111
+
112
+ If you only need to use Secryst ONNX models, there is no need
113
+ to install `libtorch` and development tools.
114
+
115
+
116
+ macOS and Ubuntu:
117
+
118
+ [source,sh]
119
+ ----
120
+ $ gem install bundler
121
+ $ bundle install
122
+ ----
123
+
124
+
125
+ On macOS:
126
+
127
+ [source,sh]
128
+ ----
129
+ $ gem install bundler
130
+ $ bundle install
131
+ ----
132
+
133
+
134
+ ==== To use Secryst Torch models
135
+
136
+ Usage of Secryst Torch models require `libtorch`, which
137
+ requires installation of the following packages:
138
+
139
+ * `libtorch` (1.8.1)
30
140
  * `fftw`
31
141
  * `gsl`
142
+
143
+ And also you must explicitly add `torch` gem to your Gemfile:
144
+
145
+ [source,ruby]
146
+ ----
147
+ gem 'torch-rb', '~> 0.6'
148
+ ----
149
+
150
+ On Ubuntu:
151
+
152
+ [source,sh]
153
+ ----
154
+ $ sudo apt-get -y install libfftw3-dev libgsl-dev unzip automake \
155
+ make gcc g++ libtorch libtorch-dev
156
+ $ wget https://download.pytorch.org/libtorch/cpu/libtorch-cxx11-abi-shared-with-deps-1.9.0%2Bcpu.zip
157
+ $ unzip libtorch-cxx11-abi-shared-with-deps-1.8.1%2Bcpu.zip
158
+
159
+ $ gem install bundler
160
+ $ bundle config build.torch-rb \
161
+ --with-torch-dir=$(pwd)/libtorch
162
+
163
+ $ bundle install
164
+ ----
165
+
166
+
167
+ On Fedora:
168
+
169
+ [source,sh]
170
+ ----
171
+ $ sudo dnf -y install ruby-devel gsl-devel fftw-devel rubygem-bundler unzip \
172
+ automake make gcc gcc-c++
173
+ $ git clone --recurse-submodules --depth=5 -b release/1.7 https://github.com/pytorch/pytorch.git
174
+ $ pushd pytorch
175
+ $ python setup.py install
176
+ $ popd
177
+ $ TORCH_DIR=$HOME/.local/lib/python3.9/site-packages/torch # Ensure this dir exists
178
+ $ ln -s lib $TORCH_DIR/lib64
179
+
180
+ $ bundle config build.torch-rb \
181
+ --with-torch-dir=$TORCH_DIR
182
+
183
+ $ bundle install
184
+ ----
185
+
186
+
187
+ On macOS:
188
+
189
+ [source,sh]
190
+ ----
191
+ $ brew install libtorch gsl fftw automake gcc
192
+ $ gem install bundler
193
+ $ bundle config build.torch-rb \
194
+ --with-torch-dir=$(brew --prefix libtorch)
195
+ $ bundle install
196
+ ----
197
+
198
+
199
+
200
+ === Secryst Trainer
201
+
202
+ In order to use Secryst Trainer two additional components are necessary:
203
+
32
204
  * `lapack`
33
205
  * `openblas`
34
206
 
35
-
36
207
  On Ubuntu:
37
208
 
38
209
  [source,sh]
@@ -40,14 +211,17 @@ On Ubuntu:
40
211
  $ sudo apt-get -y install libfftw3-dev libgsl-dev libopenblas-dev \
41
212
  liblapack-dev liblapacke-dev unzip automake make gcc g++ \
42
213
  libtorch libtorch-dev
43
- $ wget https://download.pytorch.org/libtorch/cu102/libtorch-cxx11-abi-shared-with-deps-1.6.0.zip
44
- $ unzip libtorch-cxx11-abi-shared-with-deps-1.6.0.zip
214
+ $ wget https://download.pytorch.org/libtorch/cu111/libtorch-cxx11-abi-shared-with-deps-1.8.1%2Bcu111.zip
215
+ $ unzip libtorch-cxx11-abi-shared-with-deps-1.8.1%2Bcu111.zip
45
216
 
46
- $ gem install bundler -v "~> 2"
217
+ $ gem install bundler
47
218
  $ bundle config build.torch-rb \
48
219
  --with-torch-dir=$(pwd)/libtorch
49
220
 
50
221
  $ bundle install
222
+
223
+ # To enable ONNX training, you must also install the Python portions
224
+ $ pip3 install -r requirements.txt
51
225
  ----
52
226
 
53
227
 
@@ -57,12 +231,17 @@ On macOS:
57
231
  ----
58
232
  $ brew install libtorch gsl lapack openblas fftw automake gcc
59
233
 
60
- $ gem install bundler -v "~> 2"
234
+ $ gem install bundler
61
235
  $ bundle config build.numo-linalg \
62
- --with-openblas-dir=/usr/local/opt/openblas \
63
- --with-lapack-lib=/usr/local/opt/lapack
236
+ --with-openblas-dir=$(brew --prefix openblas) \
237
+ --with-lapack-lib=$(brew --prefix lapack)
238
+ $ bundle config build.torch-rb \
239
+ --with-torch-dir=$(brew --prefix libtorch)
64
240
 
65
241
  $ bundle install
242
+
243
+ # To enable ONNX training, you must also install the Python portions
244
+ $ pip3 install -r requirements.txt
66
245
  ----
67
246
 
68
247
 
@@ -77,6 +256,223 @@ $ bundle exec gem uninstall numo-linalg
77
256
  ----
78
257
 
79
258
 
259
+ == Usage
260
+
261
+ Secryst provides a CLI for training models and re-using trained models.
262
+
263
+
264
+ === Using trained models
265
+
266
+ You will need to install the `secryst` gem (prerequisites must be fulfilled):
267
+
268
+ [source,sh]
269
+ ----
270
+ $ gem install secryst
271
+ ----
272
+
273
+ To utilize a trained model:
274
+
275
+ [source,sh]
276
+ ----
277
+ # Transform all individual lines of `--input_text_file`.
278
+ # Specifying:
279
+ # - trained model zip archive at `--model-file`.
280
+ # Must include `metadata.yaml`, `vocabs.yaml` and
281
+ # an `.pth` or `.onnx` model file.
282
+
283
+ secryst translate \
284
+ --input_text_file=examples/to-translate.txt \
285
+ --model-file=examples/checkpoints/checkpoint-500.zip
286
+ ----
287
+
288
+ Both Secryst ONNX models and Secryst Torch models can
289
+ be used with this command.
290
+
291
+
292
+ === Training models in Ruby (output: Secryst Torch model)
293
+
294
+ Secryst supports training models in Ruby into the Secryst Torch model format.
295
+ These created models can then be used by other users through the `secryst` gem.
296
+
297
+ NOTE: To make a trained Secryst model available for all platforms,
298
+ you should convert the Secryst Torch model into a Secryst ONNX model.
299
+
300
+ You will need to install the `secryst-trainer` gem (prerequisites must be fulfilled):
301
+
302
+ [source,sh]
303
+ ----
304
+ $ gem install secryst-trainer
305
+ ----
306
+
307
+ NOTE: The `secryst` gem will be automatically installed alongside `secryst-trainer`.
308
+
309
+
310
+ Training a typical model:
311
+
312
+ [source,sh]
313
+ ----
314
+ # Train all individual lines of the file specified in `-i` to the
315
+ # corresponding line in target `-t`.
316
+ #
317
+ # Specifying:
318
+ # - `max-epochs` specifies how many epochs training will be run
319
+ # - `log-interval` specifies how often should Secryst report on
320
+ # learning parameters.
321
+ # - `checkpoint-every` indicates how often Secryst saves a checkpoint
322
+ # file to `checkpoint_dir`, in the format `checkpoint-{epoch}.zip`.
323
+ # - `checkpoint_dir` specifies the directory to store checkpoint files. If some checkpoints are already in the directory, the training will continue from the latest
324
+
325
+ secryst-trainer train \
326
+ -i 'data/khm-latn-small/input.csv' \
327
+ -t 'data/khm-latn-small/target.csv' \
328
+ --max-epochs=500 \
329
+ --log-interval=1 \
330
+ --checkpoint-every=50 \
331
+ --checkpoint_dir=examples/checkpoints
332
+ ----
333
+
334
+
335
+ Training with all options:
336
+
337
+ [source,sh]
338
+ ----
339
+ # Train all individual lines of the file specified in `-i` to the
340
+ # corresponding line in target `-t`.
341
+ #
342
+ # Specifying:
343
+ # - `batch-size` specifies the batch size for training
344
+ # - `max-epochs` specifies how many epochs training will be run
345
+ # - `log-interval` specifies how often should Secryst report on
346
+ # learning parameters.
347
+ # - `checkpoint-every` indicates how often Secryst saves a checkpoint
348
+ # file to `checkpoint_dir`, in the format `checkpoint-{epoch}.zip`.
349
+ # - `checkpoint_dir` specifies the directory to store checkpoint. If some checkpoints are already in the directory, the training will continue from the latest
350
+ # - `gamma` specifies the gamma value used
351
+ # - hyperparameters in a key-value pair format
352
+
353
+ secryst-trainer train --model=transformer \
354
+ -i 'data/khm-latn-small/input.csv' \
355
+ -t 'data/khm-latn-small/target.csv' \
356
+ --batch-size=32 \
357
+ --max-epochs=500 \
358
+ --log-interval=1 \
359
+ --checkpoint-every=50 \
360
+ --checkpoint_dir=checkpoints \
361
+ --gamma=0.2 \
362
+ -h d_model:64 nhead:8 num_encoder_layers:4 num_decoder_layers:4 \
363
+ dim_feedforward:256 dropout:0.05 activation:relu
364
+ ----
365
+
366
+
367
+ === Convert Secryst Torch models to Secryst ONNX models
368
+
369
+ Due to a limitation of https://pytorch.org/cppdocs/[libtorch's C++ interface]
370
+ not being able to encode trained models in ONNX, we have to use PyTorch to
371
+ convert Secryst Torch models into Secryst ONNX models.
372
+
373
+ Secryst supports generation of Secryst ONNX models using PyTorch.
374
+
375
+ First, clone this current repository.
376
+
377
+ To convert a Secryst Torch model to a Secryst ONNX model, run:
378
+
379
+ [source,sh]
380
+ ----
381
+ python3 python/pth_to_onnx.py checkpoint.zip output.zip
382
+ ----
383
+
384
+ The trained Secryst ONNX model can be used as usual:
385
+
386
+ [source,sh]
387
+ ----
388
+ bundle exec secryst translate --model-file output.zip -t texts.txt
389
+ ----
390
+
391
+
392
+
393
+ === Resuming training
394
+
395
+ Secryst Trainer supports checkpoint resumption.
396
+
397
+ It will detect whether you already have checkpoint model files in the model output
398
+ directory (in the filename of `checkpoint-nnn.zip`), and attempt to
399
+ resume training from there. Notice that in resuming training, you
400
+ must use identical parameters and the identical training dataset,
401
+ otherwise the process will throw out an error.
402
+
403
+
404
+ === Importing non-Secryst ONNX models
405
+
406
+ You can easily utilize non-Secryst trained ONNX models in Secryst as well.
407
+
408
+ You need to prepare a zip file with:
409
+
410
+ * An `.onnx` model file
411
+ * The `vocabs.yaml` file
412
+
413
+ The `vocabs.yaml` file has to contain two keys - `input` and `target` (it's okay if they are the same), which contain all tokens from vocabulary placed in original order.
414
+
415
+ Like this:
416
+
417
+ [source,yaml]
418
+ ----
419
+ input:
420
+ - [UNK]
421
+ - ...
422
+ target:
423
+ - [UNK]
424
+ - ...
425
+ ----
426
+
427
+ Then just utilize model usually as described above. You can find an example of this in the examples folder (`onnx_import.rb`).
428
+
429
+ === Training on GPU
430
+
431
+ To allow training on CUDA drivers Secryst ships Python trainer.
432
+
433
+ Install the python version 3.8, and required packages:
434
+
435
+ [source,sh]
436
+ ----
437
+ pip3 install -r requirements.txt
438
+ ----
439
+
440
+ And start the training (all the options are the same as Ruby trainer):
441
+
442
+ [source,sh]
443
+ ----
444
+ python3 python/train.py -i 'data/khm-latn-small/input.csv' \
445
+ -t 'data/khm-latn-small/target.csv' \
446
+ --max-epochs=500 \
447
+ --log-interval=1 \
448
+ --checkpoint-every=50 \
449
+ --checkpoint-dir=examples/checkpoints
450
+ ----
451
+
452
+
453
+ == Examples
454
+
455
+ The Khmer transliteration system is implemented as an example.
456
+
457
+ To run the training:
458
+
459
+ [source,sh]
460
+ ----
461
+ $ bundle exec examples/training.rb
462
+ ----
463
+
464
+ To run translations through the transformer:
465
+
466
+ [source,sh]
467
+ ----
468
+ $ bundle exec examples/translating.rb
469
+ ----
470
+
471
+ * Checkpoint files are generated as `examples/checkpoints/*.zip`
472
+ * It includes `metadata.yaml`, `model.pth` and `vocabs.yaml` files
473
+
474
+
475
+
80
476
 
81
477
  == References
82
478
 
@@ -88,10 +484,6 @@ based on:
88
484
  Attention is all you need. 2017. In:
89
485
  _Advances in Neural Information Processing Systems_, pages 6000-6010.
90
486
 
91
- The sample transliteration system implemented is the Khmer system:
92
-
93
- * https://viblo.asia/p/nlp-khmer-word-segmentation-YWOZrgNNlQ0
94
- * https://viblo.asia/p/nlp-khmer-romanization-using-seq2seq-m68Z07OQKkG
95
487
 
96
488
 
97
489
  == Origin of name
data/bin/secryst ADDED
@@ -0,0 +1,42 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require "thor"
4
+ require "secryst"
5
+
6
+ class SecrystCli < Thor
7
+ def self.exit_on_failure?
8
+ true
9
+ end
10
+ desc "translate", "Translate input sequence using specified model"
11
+ method_option :source, :aliases => "-s", :desc => "Add a model index to provision the model"
12
+ method_option :input_text, :aliases => "-i", :desc => "String of text to translate"
13
+ method_option :input_text_file, :aliases => "-t", :desc => "Path to file with text to translate"
14
+ method_option :model_file, :aliases => "-f", :desc => "Specify model name or a checkpoint .zip file", :required => true
15
+
16
+ def translate
17
+ Secryst::Provisioning.add_remote(options[:source]) if options[:source]
18
+
19
+ translator = Secryst::Translator.new(
20
+ model_file: options[:model_file],
21
+ )
22
+
23
+ if options[:input_text]
24
+ puts translator.translate(options[:input_text])
25
+ elsif options[:input_text_file]
26
+ File.readlines(options[:input_text_file]).each do |line|
27
+ puts translator.translate(line)
28
+ end
29
+ end
30
+ end
31
+
32
+ desc "install <name>", "Installs a model locally"
33
+ method_option :source, :aliases => "-s", :desc => "Add a model index to provision the model"
34
+
35
+ def install(name)
36
+ Secryst::Provisioning.add_remote(options[:source]) if options[:source]
37
+
38
+ Secryst::Provisioning.locate(name)
39
+ end
40
+ end
41
+
42
+ SecrystCli.start
@@ -0,0 +1,103 @@
1
+ require 'zip'
2
+ require 'onnxruntime'
3
+ require 'tmpdir'
4
+
5
+ module Secryst
6
+ # Byte-level seq2seq (ByT5 family) inference over ONNX sessions from an
7
+ # IMF v1 model zip: sha256-verified graphs, greedy KV-cache decode when
8
+ # the zip ships decoder-kv.onnx (default), plain full-recompute
9
+ # fallback otherwise. Tokenization is the canonical ByT5 table
10
+ # (byte b -> id b+3, trailing EOS) — see Secryst::IMF.
11
+ class Byt5Onnx
12
+ def initialize(zip_path)
13
+ @manifest = IMF.manifest(zip_path)
14
+ graphs = IMF.verify_and_read(zip_path)
15
+ @tmpdir = Dir.mktmpdir('secryst-imf')
16
+ @encoder = build_session(graphs, 'encoder.onnx')
17
+ @kv = @manifest['decoder'] == 'kv' && graphs.key?('decoder-kv.onnx')
18
+ @decoder = build_session(graphs, @kv ? 'decoder-kv.onnx' : 'decoder.onnx')
19
+ @pasts = @kv ? zero_pasts : {}
20
+ end
21
+
22
+ def translate(text, max_seq_length: 256)
23
+ ids = IMF.encode(text)
24
+ return '' if ids.length == 1 # only the trailing EOS: empty input
25
+
26
+ hidden = @encoder.predict({ input_ids: [ids] })['last_hidden_state']
27
+ tokens = @kv ? greedy_kv(hidden, max_seq_length) : greedy_plain(hidden, max_seq_length)
28
+ IMF.decode(tokens)
29
+ end
30
+
31
+ def id
32
+ @manifest['id']
33
+ end
34
+
35
+ private
36
+
37
+ # The onnxruntime gem loads from paths, not bytes: verified bytes go
38
+ # to a private tmpdir.
39
+ def build_session(graphs, name)
40
+ path = File.join(@tmpdir, name)
41
+ File.binwrite(path, graphs.fetch(name))
42
+ OnnxRuntime::Model.new(path)
43
+ end
44
+
45
+ def zero_pasts
46
+ @decoder.inputs.each_with_object({}) do |meta, pasts|
47
+ next unless meta[:name].start_with?('past_')
48
+ shape = meta[:shape] # [batch, heads, past_seq, d_kv]; dynamic dims are Strings
49
+ heads = shape[1].is_a?(Integer) ? shape[1] : 4
50
+ d_kv = shape[3].is_a?(Integer) ? shape[3] : 8
51
+ # Numo carries the explicit [1, heads, 0, d_kv] shape through;
52
+ # nested Ruby arrays cannot express a zero-length dim.
53
+ pasts[meta[:name]] = Numo::DFloat.zeros(1, heads, 0, d_kv)
54
+ end
55
+ end
56
+
57
+ def argmax(row)
58
+ best = 0
59
+ best_val = -Float::INFINITY
60
+ row.each_with_index do |value, index|
61
+ if value > best_val
62
+ best_val = value
63
+ best = index
64
+ end
65
+ end
66
+ best
67
+ end
68
+
69
+ def greedy_kv(hidden, max_seq_length)
70
+ pasts = @pasts.dup
71
+ current = [IMF::PAD_ID]
72
+ generated = []
73
+ max_seq_length.times do
74
+ results = @decoder.predict(
75
+ { input_ids: [current], encoder_hidden_states: hidden }.merge(pasts)
76
+ )
77
+ token = argmax(results['logits'].first.last)
78
+ break if token == IMF::EOS_ID
79
+
80
+ generated << token
81
+ pasts = pasts.keys.to_h { |name| [name, results[name.sub('past_', 'present_')]] }
82
+ current = [token]
83
+ end
84
+ generated
85
+ end
86
+
87
+ def greedy_plain(hidden, max_seq_length)
88
+ decoder_ids = [IMF::PAD_ID]
89
+ generated = []
90
+ max_seq_length.times do
91
+ logits = @decoder.predict(
92
+ { input_ids: [decoder_ids], encoder_hidden_states: hidden }
93
+ )['logits']
94
+ token = argmax(logits.first.last)
95
+ break if token == IMF::EOS_ID
96
+
97
+ generated << token
98
+ decoder_ids = decoder_ids + [token]
99
+ end
100
+ generated
101
+ end
102
+ end
103
+ end