limdu is a small classification library for Node.js with online learning
Machine-learning for Node.js
At a glance
- What is it?
- limdu is a JavaScript machine learning library for Node.js that focuses on multi-label classification and learning from examples one at a time, which makes it a reasonable fit for intent detection in dialog systems and chatbots. It ships a menu of classifiers, a feature engineering layer, serialization and cross-validation, and it labels itself alpha, with a single published release from 2023.
- Who is it for?
- limdu suits a JavaScript team that needs intent detection for a chatbot, wants to learn from examples as they arrive rather than in batches, and is comfortable maintaining a small dependency itself. It is the wrong choice for a project that needs a maintained deep learning stack, and the wrong choice for anything where the licence terms of LGPL-3.0 are a problem.
- Can I use it commercially?
- Yes, with conditions. LGPL-3.0 is a weak copyleft licence: you can use it inside commercial and closed-source software, but if you distribute changes to its own files, you must publish those changes under the same licence.
- Is it still maintained?
- Activity is slowing. The repository last received commits 6 months ago.
- What is it written in?
- Mainly JavaScript, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on October 20, 2026, and from our analysis. They are not legal advice.
Editorial analysis
A classification library, not a machine learning platform
limdu describes itself as a machine learning framework for Node.js that supports multi-label classification, online learning and real-time classification, and says it is therefore especially suited for natural language understanding in dialog systems and chatbots.
The scope is deliberately small. The package contains classifiers, a feature engineering layer, some utilities and a test suite, and the entry point is `index.js`. It is a library of algorithms rather than a framework with a training pipeline, a model registry, a serving layer or a notebook. The dependency list matches that reading, with the notable entries being `brain.js` for the neural network, `svm` for the support vector machine, `languagemodel`, `wordsworth` and `graph-paths`.
The runtime requirement is stated as Node.js 0.12 and later, which is a holdover from the library's origins and a useful signal about how old the code is.
The audience, then, is a JavaScript developer who wants to put a classifier into a running service, most likely a bot, without leaving the Node ecosystem and without running a separate model server. It is a library to read, vendor or depend on rather than a platform to operate.
The project is explicit about its state. The README says limdu is in an alpha state, that some parts are working and some parts are missing or not tested, and that contributions are welcome. That sentence is the first thing a potential user should read, because it describes exactly the trade being made here.
Online learning is the part aimed at dialog systems
Of the three capabilities the description names, online learning is the one that changes how you build the thing rather than just what you call at the end.
The difference shows up in the API. Batch learning takes an array of input and output pairs, and the classifier is trained in one go.
var limdu = require('limdu');
var colorClassifier = new limdu.classifiers.NeuralNetwork();
colorClassifier.trainBatch([
{input: { r: 0.03, g: 0.7, b: 0.5 }, output: 0},
{input: { r: 0.16, g: 0.09, b: 0.2 }, output: 1},
{input: { r: 0.5, g: 0.5, b: 1.0 }, output: 1}
]);
console.log(colorClassifier.classify({ r: 1, g: 0.4, b: 0 }));Online learning takes one example at a time, so the classifier changes as the conversation happens.
var birdClassifier = new limdu.classifiers.Winnow({
default_positive_weight: 1,
default_negative_weight: 1,
threshold: 0
});
birdClassifier.trainOnline({'wings': 1, 'flight': 1, 'beak': 1, 'eagle': 1}, 1);
birdClassifier.trainOnline({'wings': 0, 'flight': 0, 'beak': 0, 'dog': 1}, 0);The example that follows is the clearest illustration of why this matters for a dialog system. A penguin is initially classified as not a bird, because it does not fly, and the classifier is then shown a penguin that is a bird, and a bat that is not. After that, a chicken is correctly classified as a bird, and the explanation says why, because it has wings and a beak.
That is a conversational correction. The user says something the system got wrong, the system learns from the correction, and the next request behaves differently. A batch classifier would need the correction added to a training set and the model retrained, which is a much heavier loop for a live chat product.
The mechanism suits the data too. The Winnow classifier here is the Modified Balanced Margin Winnow, credited to Carvalho and Cohen from 2006, and the features in the example are binary indicators, which is exactly the shape a bag of words representation takes.
The classifier list mixes ports with one original
The set of binary classifiers is unusual, and worth listing because it tells you what you are actually depending on.
The NeuralNetwork is `brain.js` by Heather Arthur, the example is credited to the same source. The Bayesian classifier uses `classifier.js` by Heather Arthur, the Perceptron is loosely based on `perceptron.js` by John Chesley, the SVM uses `svm.js` by Andrej Karpathy, and the Decision Tree is based on two ID3 implementations, one by Ankit Kuwadekar and one by Will Kurt. The Linear SVM classifiers are wrappers around SVM-Perf and Lib-Linear, and they are covered by their own section in the table of contents.
The Winnow classifier is the one implementation that is the project's own, the Modified Balanced Margin Winnow.
So the library is, in part, a common interface over a set of existing JavaScript machine learning implementations, with one original algorithm and a set of wrappers for native tools. That is a useful thing to have, because choosing between a naive Bayes, a perceptron, a winnow and an SVM is a decision most people make by copying an example, and here they are behind one API.
The important caveat is stated plainly in the documentation. The library is still under construction, and not all features work for all classifiers. For a full list of the features that do work, the documentation points at the test folder, which is the honest way to answer that question, and a better one than a feature matrix that drifts.
There is also a small consistency wrinkle in the README itself, which describes the additional binary classifiers as being in version 0.2 while the package manifest says 1.0.0. The kind of stale sentence that happens in a project whose maintainer is the main contributor.
Explanations are for showing, not for parsing
Some classifiers can return explanations, which the documentation describes as additional information that explains how the classification result has been derived. The second argument to `classify` is an explanation level.
The format is classifier specific, and the two documented examples show how different they are. For the Bayesian classifier, the explanation is the probability for each category.
{ classes: 'white',
explanation: [ 'white: 0.0621402182289608', 'black: 0.031460948468170505' ] }For the Winnow classifier, the explanation is the relevance of each feature, computed as the feature value times the feature weight, including a bias term.
{ classification: 1,
explanation: [ 'bias+1.12', 'r+1.08', 'g+0.25', 'b+0.00' ] }The feature level explanation is the more useful of the two for a chat application, because it can be turned into a sentence for a user, such as the bird example, where the system can say it classified something as a bird because it has wings and a beak.
The warning about the format is the part to take seriously. The documentation says the internal format of the explanations might change without notice, and that the explanations should be used for presentation purposes only, and not, for example, for extracting the actual numbers. The feature is also described as experimental and as being supported differently for different classifiers.
In other words, the explanation is a debugging and transparency aid, not a stable API. It is worth building a user interface on, and not worth parsing.
Multi-label classification is built on binary relevance
Multi-label classification is the feature the project description leads with, and the implementation shows how it is put together.
In binary classification the output is 0 or 1. In multi-label classification the output is a set of zero or more labels, which matches a chat use case where one utterance can carry more than one intent.
The approach is binary relevance, so each label is handled by its own binary classifier and the outputs are combined.
var MyWinnow = limdu.classifiers.Winnow.bind(0, {retrain_count: 10});
var intentClassifier = new limdu.classifiers.multilabel.BinaryRelevance({
binaryClassifierType: MyWinnow
});Note the `bind` call. The documentation has a section on binding, which describes using JavaScript's binding capabilities to create custom classes made of existing classes and pre-specified parameters, so a classifier with a fixed configuration becomes its own named class.
var MyWinnow = limdu.classifiers.Winnow.bind(0, {
default_positive_weight: 1,
default_negative_weight: 1,
threshold: 0
});
var birdClassifier = new MyWinnow();This is a small idea with a large effect on readability. Configuration that would otherwise be repeated at every call site becomes a class name, and a project ends up with a set of named classifiers, one per intent family, each with its own parameters.
The rest of the library's structure is described by its table of contents. The sections cover feature engineering with feature extraction for converting an input sample into feature value pairs, input normalization, and a feature lookup table that converts custom features to integer features. There are also sections on serialization, cross-validation, back-classification which is described as generation, the SVM wrappers, and a section on undocumented features. The feature engineering layer is the part that matters most in practice, since the classifiers all take the same kind of input, a plain object of feature values, and putting a good representation in front of them is where most of the accuracy comes from.
One release in 2023 and a last push in April 2026
The maintenance picture needs stating plainly, because it affects the decision more than the feature list does.
The repository has a single GitHub release, v1.0.0, published on 2023-06-19. The last push was on 2026-04-10, so there has been work in the tree well after that tag, but no new published version since then. The project is not archived.
The release process is visible in the manifest, with `semantic-release` and its plugins for changelog, commit analysis, git, GitHub and npm release notes. That tooling is what produced the 1.0.0 tag and it is configured to keep producing tags, so the absence of one since 2023 says more about activity than about setup.
The licence is LGPL-3.0, which is the one legal point worth attention for a JavaScript library. LGPL is a weak copyleft licence, so if you use limdu as a library that your users import rather than linking into a closed product, the obligations are light. If you modify the library and distribute the modified version, those modifications have to be made available under the same terms. For most teams the practical effect is that they read the licence text once and then leave it alone, but for an organisation with a blanket policy against LGPL dependencies it is a blocker that no amount of good code fixes.
The licence is why this project is worth understanding before its code. The classification algorithms it offers are mostly other people's work, ported and wrapped, and the value is the interface, the feature engineering, the online learning and the multi-label support.
Editorial conclusion
limdu suits a JavaScript team that needs intent detection for a chatbot, wants to learn from examples as they arrive rather than in batches, and is comfortable maintaining a small dependency itself. It is the wrong choice for a project that needs a maintained deep learning stack, and the wrong choice for anything where the licence terms of LGPL-3.0 are a problem. Check first which classifiers support which features, because the documentation states that not all features work for all classifiers and points at the test folder as the authoritative list, and note that the only published release is v1.0.0 from 2023-06-19 with the last push on 2026-04-10.
Frequently asked questions
What is limdu and what is it used for?
limdu is a machine learning framework for Node.js that supports multi-label classification, online learning and real-time classification, and the project describes it as especially suited for natural language understanding in dialog systems and chatbots. It is installed with `npm install limdu` and runs on Node.js 0.12 and later.
Which classifiers does limdu include?
The binary classifiers include Winnow, NeuralNetwork, Bayesian, Perceptron, SVM, Linear SVM wrappers around SVM-Perf and Lib-Linear, and Decision Tree based on ID3 implementations. The documentation states that not all features work for all classifiers and points at the test folder for the full list.
What is the difference between trainBatch and trainOnline in limdu?
trainBatch learns from an array of input and output pairs in one go, while trainOnline learns from a single example at a time, so the classifier changes as new examples arrive. The project documentation uses the bird example to show a penguin being misclassified and then corrected, which suits a live chat system.
Can I rely on the limdu explanation output format?
Not for parsing. The documentation warns that the internal format of the explanations might change without notice and that the explanations should be used for presentation purposes only, and the feature is described as experimental with different support for different classifiers.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/erelsgl-limdu)Was this useful?