kanso-laya

Laya fine-tuned to tell apart 16 kinds of LinkedIn post, exported to split ONNX (4-bit encoder + fp32 head) so it runs inside a browser tab with onnxruntime-web. It is the model Kanso Feed — a Chrome extension that hides the kinds of LinkedIn post you choose — downloads once on install. Nothing leaves the reader's computer: there is no server and no account.

Version 3.0.0, 361 MB.

  • Base model: convaiinnovations/laya, multilingual subfolder (mmBERT-base, 22 layers, d = 768, 256k vocabulary), Apache 2.0.
  • Task: one multiple-choice question per post — "What is the author doing in this LinkedIn post?" — with 17 options: hiring, open to work, career move, achievement, anecdote, company news, self-promotion, event, advice, news and analysis, opinion, humor, life lesson, gratitude, question, politics, and other. One kind per post; the probabilities sum to 100 %.
  • Training data: 684 fictional LinkedIn posts written for Kanso — 475 French, 209 English, one label each — × 3 question phrasings. --loss soft-ce --shuffle-options, 4 epochs, --max-len 768 --head-max-len 576, token embedding table frozen. Temperatures fitted on a split held out before training.
  • Files: encoder.onnx (4-bit MatMulNBits, blocks of 32, row-wise int8 embeddings), head.onnx (fp32 — it carries the calibration), tokenizer.json, rl_agent_config.json.

Results

Share of posts assigned the right kind, measured with the extension's own code (laya-ts + onnxruntime), at its three token budgets. 164 fictional posts never seen during training:

Reading Base Laya (multilingual) This model
448 / 256 tokens — the extension's default 36 % 78 %
768 / 576 tokens — 63 %
768 / 576, two readings averaged — 66 %

The smallest budget is both the fastest and the most accurate here, which is why it ships as the default.

On 279 real LinkedIn posts, hand-labelled, none of them in the training data: 81.7 % — the real feed turned out to be easier than the posts written for the test. What matters more for a reader is where the mistakes land, because the extension only hides a post when it is confident (60 % threshold):

share of the 279
right, above threshold 67.7 %
right but uncertain (left visible) 14.0 %
wrong but uncertain (left visible, harmless) 14.3 %
wrong and confident — the only case that hurts 3.9 %

The corpus of real posts is not published, and will not be: LinkedIn's terms rule out redistributing feed content. Only the fictional training and bench sets ship with the project.

Five languages it was never trained on (German, Spanish, Italian, Polish, Portuguese), 60 posts written for the purpose, 12 kinds × 5 languages: 78.3 %, with 3.3 % wrong and confident. mmBERT's multilingual base carries over; no measurable degradation outside French and English.

4-bit versus fp32: mean |Δp| 0.012, accuracy 79.3 % against 79.9 % on the same posts. Per-tensor int8 is much worse — use 4-bit blocks.

Speed (Apple Silicon, CPU only, onnxruntime-node, 4 threads, one post at a time): 188 ms/post on the fictional bench, and 562 ms/post on real posts, whose median length is 1 000 characters. Cost follows the length of what is sent, not the number of posts, so quote the second figure. Batching is slower, not faster: every item in a batch is padded to the longest.

Limits, read these

  • The training data is fictional. Posts were written for the project, so they are cleaner than a real feed. The 81.7 % above says that mattered less than expected, but it was measured on one reader's feed, in French, at one point in time.
  • The two confusions worth knowing: life lesson is pulled towards achievement, and job search towards career move. Those two are also where confident mistakes concentrate.
  • opinion is over-predicted. Five of the eleven confident mistakes on real posts land there.
  • One class is in the weights but not in the question. An "engagement request" class ("like if you agree 👇") was trained and then removed from the options offered by default. Removing it from the data cost 5 points overall, so it stayed in; adding the option back costs nothing (79.3 % against 78 %) and recovers about two thirds of such posts. Add it yourself if you want it.
  • The question wording is part of the model. Change the option descriptions or the budgets and the behaviour changes. Kanso keeps them in src/shared/categories.json; copy them from there.

Use

import laya
agent = laya.load("yueoss/kanso-laya")   # or a local directory

In the browser, laya-ts loads encoder.onnx + head.onnx directly. The question, the token budgets and the text normalisation must match the ones used for training.

License

Apache 2.0, inherited from convaiinnovations/laya. The extension itself is under a Fair Source licence (FSL-1.1-Apache-2.0), which is a different, stricter thing — this model is not.

Downloads last month
14
Inference Providers NEW
This model isn't deployed by any Inference Provider. 🙋 Ask for provider support

Model tree for yueoss/kanso-laya

Quantized
(92)
this model