In December 2016, I published a JavaScript neural-network experiment for classifying text. The dated Brain.js archive is still public. It includes the application code, labeled examples, and screenshots of training and test outputs.
The task was narrow: learn patterns in short strings and return classifications associated with them. Questions, statements, and references within a sentence gave the experiment something concrete to learn. This was hands-on supervised learning years before the current chatbot boom.
In the 2026 revision, I replaced approximate output spelling with exact label lookup. The classifier scores 9 exact matches on 12 question/declaration checks.
Text classification starts with the target
A classifier maps an input to a defined set of outputs. In general notation, a model takes an encoded input x and produces fθ(x), where θ represents learned parameters. Training adjusts those parameters against labeled examples. The useful question is whether the resulting mapping holds up on the kinds of inputs the business will actually send it.
My experiment explored character-level text representation and a supervised feedforward network. I asked the output layer to reconstruct the text associated with a classification. That combined two jobs: recognizing a useful distinction and reproducing its spelling. The archive preserves what happened when the second job only partly worked.
The target is part of the specification. “Is this a question?” and “Is this customer unhappy?” are different tasks. They can share a classification approach while requiring different examples, labels, and acceptance criteria.
Representation changes what the model can learn
A neural network needs a representation of the input. Character-level representations preserve spelling and punctuation information. Other representations emphasize token counts, phrases, or learned features. Each choice makes certain distinctions easier to express and others harder.
For a business classifier, I would examine what the representation does to names, abbreviations, punctuation, and unusually long messages. Consider “Can you help?” and “You can help.” Much of the vocabulary is shared, but the role of the sentence changes. A useful evaluation has to include cases where superficial similarity is misleading.
This is also why preprocessing belongs inside the model's evaluation boundary. The complete system includes the input transformation, the trained model, and the rule that turns its output into a decision. Testing a saved network while changing those surrounding steps leaves you testing a different system.
From approximate spelling to exact labels
The archived outputs were fascinating to inspect: some strings approached parts of the intended words, while others were harder to interpret. Counting letters that look close is a poor interface for understanding a classifier, though. A small numerical error in an output character can still produce the wrong letter. I now score the selected labels directly.
In October 2026, I revisited the toy experiment with a simpler output contract: score a predefined set of labels, then map selected positions back to their exact names. The revised command-line implementation uses a GPU-capable backend. The dated archive preserves the 2016 character-output experiment; the 2026 revision uses exact label lookup.
2016 experiment / 2026 revisit
Same useful question.
A clearer output.
“What time is it?”
Archived character output
qtdsthnn siidA reader has to interpret an imperfect string.
Current label output
Exact names mapped from active output positions.
Observed output / explore the examples
A position lights up.
A label comes back.
Open a sentence to inspect its recorded result. 1 = selected; 0 = not selected. These seven positions are a selected view of this saved model’s 240-position output vector. Indices start at zero.
“What is my name?”Recorded result
Returned labels: my, name, question
“what's your name?”Recorded result
Returned labels: kit, question
“What time is it?”Recorded result
Returned labels: question, time
“time?”Recorded result
Returned labels: question, time
“master?”Recorded result
Returned labels: question
“How amazing!”Known miss
Returned labels: question
Here, “How amazing!” expresses an exclamation. The model returned question, so this example is a classification error. A familiar question word can still mislead it.
This is multi-label classification. “What is my name?” activates question, my, and name together. One active position would be a one-hot result; several active positions make it multi-hot. The network supplies scores, and a decision threshold determines which labels are selected. The names come from a fixed lookup, so the model no longer has to spell them.
The reference label kit comes from the historical experiment’s name for the assistant. “What’s your name?” returning kit, question identifies the assistant reference and sentence type. The lookup returns predefined labels.
Inspect the original terminal screenshot

Original public image in the dated archive. The terminal records the original input strings and character outputs.
What works now.
The revised 2026 classifier drops the spelling trick entirely: it scores a fixed set of labels and returns exact names from a lookup table. "What is my name?" returns my, name, and question together, multi-label, all three at once. Short inputs like "time?" return useful labels. On a 12-check question/declaration set it scores 9 exact matches. The known miss is documented: "How amazing!" returns question though it reads as an exclamation here.
I also removed the legacy inference-padding path that mishandled inputs at or above its training length. The revised encoder retains recognized features at the end of long sentences.
Training performance and workflow performance
A model can fit its examples while failing on inputs that differ from them. Near-duplicate sentences, repeated templates, and examples from the same conversation can make a random split look more convincing than it should.
The practical test is to hold out meaningful groups and inspect the mistakes. For customer messages, that could mean keeping an entire conversation on one side of the split. For a new customer deployment, it might mean evaluating examples from that business that were never used to tune the system.
There is a business decision behind each error. A classifier that moves a message to the wrong review queue creates a different risk from one that sends a reply automatically. The acceptance criteria should reflect the action the output will trigger.
What carries forward into AI agents
The same discipline applies when an agent reads incoming work, prepares a brief, or drafts a response. Define the task. Identify the approved information. Record the result. Make exceptions visible. Agree where a person reviews the work.
Sentence type is one useful routing signal. A question may need an answer; a declaration such as “The pump failed” may require urgent action. Request, urgency, and escalation are useful targets for additional labeled examples.
A small classifier can be one component in that larger workflow. It might prioritize feedback before a person reads it, or separate routine messages from those needing closer attention. A language model can prepare a draft downstream, with its own evaluation and permissions.
The sentiment-analysis article explores how to evaluate that kind of bounded classifier. For business implementation, AI-Rey's agent services start with the repeated task and the result worth preparing.
Scope, stated plainly. This is a toy dataset proving the interface works, not a production router. Broader annotated examples and independent evaluation come before any dependability claim.
Inspect the evidence
- The 2026 classifier revision contains the toy implementation, dataset follow-ups, tests, and documented limitations.
- The December 2016 commit history dates the public experiment.
- The archived README describes its task and discusses example outputs.
- Brain.js documentation describes the library used for this family of supervised models.
