Seq2Seq Encoder
Half a machine-translation model, built honestly
- model
If you've ever seen a diagram of a seq2seq model - the encoder-decoder architecture behind old-school machine translation - this node is the left half of that diagram, made real. CdlSeq2SeqEncoder builds the encoder: the part that reads a source sentence and compresses it into a state the decoder can later turn into a translation. It comes from ComfyDL, the pack that wraps the "Dive into Deep Learning" (d2l) textbook code into nodes, and it's about as textbook an encoder as you can build.
A quick honesty note before we get into it: the pack ships the encoder but no concrete decoder node, so you can't wire up a full English-to-French pipeline end to end today. What you can do is build, inspect, and forward the encoder half - which is exactly how the d2l book structures its machine-translation chapter, one half at a time. If you're learning, that's a feature, not a deficiency.
What's inside
Construction is three layers deep and entirely conventional:
- An
nn.Embeddingmaps each source token index to a learnedembed_size-dimensional vector. - That sequence runs through a stacked GRU with
num_hiddensunits per layer. - The whole thing gets Xavier-initialized automatically at build time (the code calls
apply(init_seq2seq)in the constructor), which matters more than people think - a badly initialized GRU can be nearly untrainable.
Feed it a batch of token indices shaped (batch_size, num_steps) and you get back two things: outputs (one hidden state per timestep, shaped (num_steps, batch_size, num_hiddens)) and state (the final per-layer state, (num_layers, batch_size, num_hiddens)). The last state is the "meaning" your decoder would start from.
The inputs that matter
- vocab_size - how many distinct source tokens exist. Must match the vocab you build with Vocab Build or your token indices will land outside the embedding table.
- embed_size - width of each token's learned vector. 16–64 is plenty for the toy datasets this pack targets.
- num_hiddens - GRU width per layer. This is where your model's capacity actually lives.
- num_layers - stacked GRU depth. Default is 2, which is the classic d2l machine-translation setup. More layers = slower and easier to overfit.
- dropout - applied between GRU layers, so it only does anything when
num_layers > 1. Zero by default.
There are no real surprises in the ranges - vocab up to 100k, layers up to 20, hiddens up to 4096 - but remember this is a teaching encoder. The defaults (16-wide embeddings, 2 layers) are tuned to train on a laptop in seconds, not to win benchmarks.
Wiring it
The model output is a cdlModel, so it slots into the usual ComfyDL plumbing: Model Info to inspect layers, Model Forward to run a dummy forward pass and confirm you understand the shapes, Model Params to count weights. There's also a sibling Init Seq2Seq Weights node if you ever want to re-apply Xavier initialization by hand - this encoder already does it for you at build time.
One shape gotcha that bites everyone: like the pack's RNN nodes, this encoder thinks in time-major land internally, but its input tensor is batch-first token indices (batch, seq), and the code transposes for you before the GRU. So feed it (batch, steps) of indices and you're fine - just don't also pre-transpose, or you'll get confusing errors from the embedding layer.
Installing ComfyDL
One install covers every node in this pack:
cd ComfyUI/custom_nodes
git clone https://github.com/Cynthia-lxx/ComfyDL ./ComfyDL
pip install -r ./ComfyDL/requirements.txt
Restart ComfyUI; you'll find this node under ComfyDL/NLP Models. The folder name must stay exactly ComfyDL, and because the repo's Comfy Registry PublisherId is still blank, ComfyUI Manager may not surface it in search - the clone above always works. Requirements are just matplotlib, IPython, and matplotlib-inline; torch comes with ComfyUI.
ComfyDL has essentially no community footprint yet, so don't expect Stack Overflow answers. The repo's FUNCTIONS.md is your reference, and the d2l chapter on sequence-to-sequence learning explains the encoder in the detail this node was built to illustrate.
Inputs (5)
| Name | Type | Default | Description |
|---|---|---|---|
| vocab_size | INT | 322–100000 | — |
| embed_size | INT | 161–4096 | — |
| num_hiddens | INT | 161–4096 | — |
| num_layers | INT | 21–20 | — |
| dropout | FLOAT | 0.000–0.9 | — |
Outputs (1)
| Name | Type | Description |
|---|---|---|
| model | cdlModel | — |