Nodes/ComfyDL/RNN Language Model (high-level)
ComfyUI Node

RNN Language Model (high-level)

RNN Language Model (high-level)

By Cynthia-lxx·Created 2 months ago·Updated about 16 hours ago· 6
RNN Language Model (high-level)
  • rnn
  • model
vocab_size32
lr0.010

A language model answers the question "given what I've seen so far, what comes next?" - and that single ability is the engine behind autocomplete, machine translation, and, at scale, basically everything generative. ComfyDL's CdlRNNLM takes any RNN or GRU you've built and wraps it in a full language model: an output layer that projects each step's hidden state to a probability over the whole vocabulary, plus the learning rate the model will train with. It's the node at the heart of the pack's flagship demo, where a character/word-level RNN writes text end-to-end.

The "(high-level)" tells you which of the two LM builders this is: it uses a modern LazyLinear output head on top of a stock nn.RNN/nn.GRU. If you want to see the output layer math, the sibling CdlRNNLMScratch spells it out with explicit weight matrices.

How it works

You feed it an already-built recurrent model (say a CdlGRU), and it does two things. First it adds an output projection: at every time step, the RNN's hidden state is pushed through a linear layer that maps num_hiddens units to vocab_size logits - one score per candidate next-token. Second, it tucks a learning rate into the wrapper, because the d2l models carry their optimizer configuration with them.

The trick to make this efficient is that the output layer is shared across all time steps - one LazyLinear, applied at every position, instead of a separate layer per step. It's called "Lazy" because it infers its input width from the RNN's hidden state on the first forward pass, so you don't have to tell it anything about the RNN's internals.

Inputs and outputs that matter

  • rnn - a cdlModel RNN or GRU (from CdlRNN or CdlGRU). Its num_inputs should equal the vocabulary size, because the model one-hot-encodes tokens to that width.
  • vocab_size (default 32, min 2) - how many distinct tokens the output layer predicts over. Set it from your vocabulary, the size a CdlVocabBuild node reports.
  • lr (default 0.01) - the learning rate baked into the model for training.

The model output expects a token-index tensor of shape (batch, num_steps) - note this is not time-major like the bare RNN; the LM wrapper transposes internally - and returns logits shaped (num_steps, batch, vocab_size). Since this model has a predict() method, it wires straight into ComfyDL's RNN LM Predict node: give it a prefix and a vocabulary and it generates the continuation.

Installing ComfyDL

cd ComfyUI/custom_nodes
git clone https://github.com/Cynthia-lxx/ComfyDL ./ComfyDL
pip install -r ./ComfyDL/requirements.txt

Restart ComfyUI afterwards. Requirements are light - matplotlib, IPython, matplotlib-inline - with no model files to download for building this node. If ComfyUI Manager can't find "ComfyDL", that's expected for a young pack; clone instead.

Gotchas

The rnn you connect must be a bare RNN/GRU, not an already-wrapped LM - wrap a wrapper and you'll double up output layers. And the vocab_size mismatch is the classic silent bug: the wrapper's job is to score the vocabulary, so if you feed it a vocab of 500 but set vocab_size to 32, the demo "works" but only ever predicts from 32 nonsense tokens. Build the vocab first, read its size, and wire that number in.

CategoryComfyDL/NLP Models

Inputs (3)

NameTypeDefaultDescription
rnncdlModel
vocab_sizeINT322–100000
lrFLOAT0.0100.0001–1

Outputs (1)

NameTypeDescription
modelcdlModel