kniv v7 small (ettin-encoder-32m)

One English encoder that gives a full linguistic analysis and extracts knowledge against a schema you supply at inference time.

  • Linguistic layer: part of speech, morphology, lemmas, named entities, dependency trees, semantic roles, dialogue act and sentiment per sentence, coreference.
  • Knowledge layer: entities of the types you name, facts for the relations you name (a name plus an optional description), and for every fact its polarity, modality, holder and time. In a conversation each speaker is an entity, so "I live in Berlin" yields (user, lives in, Berlin).

A small distilled student of the two kniv v7 models, kniv-v7-xlarge-u-en and kniv-v7-xlarge-d-en, on a 32M-parameter encoder (76M parameters with the heads): the same outputs, graphs and runtime as the larger models. It is close to them on tagging and parsing (POS 0.972, LAS 0.911) and gives usable entities, roles and facts, but it is clearly weaker on NER, semantic roles, coreference, relations and entity types (see Results and Limitations). For better quality at moderate size use kniv-v7-large-en.

GUIDE.md shows the known failure modes of the kniv v7 models and how to work around them in your own code; they apply to this model too.

The kniv v7 models, smallest first:

model base encoder parameters role
kniv-v7-tiny-en ettin-encoder-17m 55M distilled student
kniv-v7-small-en (this model) ettin-encoder-32m 76M distilled student
kniv-v7-medium-en ettin-encoder-68m 122M distilled student
kniv-v7-large-en ModernBERT-base 221M distilled student
kniv-v7-xlarge-d-en deberta-v3-large 538M teacher
kniv-v7-xlarge-u-en UltraBERT-380M 485M teacher

Model details

developed by Dragonscale (dragonscale-ai)
model type multi-task transformer encoder
version kniv v7 (ettin-32m-s30-coref), 2026-11-01
base model jhu-clsp/ettin-encoder-32m
parameters 76M
input up to 512 words per window (1,024 subwords)
language English
licence Apache-2.0

Uses

Intended. Analysing English prose and conversations; extracting entities and facts for your own schema without fine-tuning, for agent memory, knowledge graphs, search and document analytics.

Out of scope.

  • Languages other than English.
  • Acting on extracted facts without review where errors matter (medical, legal, financial or employment decisions about people).
  • Profiling individuals without their consent.

Installation

Everything needed to run the model is in this repository: the ONNX graphs, the tokenizer, the settings, and the kniv_v7 Python package that turns text into results. There is nothing else to install from elsewhere: download the repository and put it on your Python path.

pip install onnxruntime tokenizers numpy huggingface_hub
import sys
from huggingface_hub import snapshot_download

path = snapshot_download("dragonscale-ai/kniv-v7-small-en")    # includes kniv_v7/
sys.path.insert(0, path)
from kniv_v7 import Kniv

Quick start

kniv = Kniv(path)
out = kniv.analyse(
    turns=[("user", "I live in Berlin and work for Siemens."),
           ("assistant", "Nice, how long have you been there?")],
    relations=[{"name": "lives in", "description": "the place where the head resides"},
               {"name": "employer", "description": "the organization the head works for"}],
    entity_types=[{"name": "location"}, {"name": "organization"}, {"name": "person"}])

w = out[0]
for f in w["facts"]:
    print(w["entities"][f["head"]]["text"], f["relation"], w["entities"][f["tail"]]["text"],
          f["polarity"], f["modality"])
# user lives in Berlin positive asserted
# user employer Siemens positive asserted

Plain text works the same way:

out = kniv.analyse(
    "Henry Wager Halleck (January 16, 1815 โ€“ January 9, 1872) was a United States Army "
    "officer, scholar, and lawyer.",
    relations=[{"name": "date of birth", "description": "date on which the subject was born"},
               {"name": "date of death", "description": "date on which the subject died"},
               {"name": "military branch", "description": "branch to which this person belongs"}],
    entity_types=[{"name": "person"}, {"name": "organization"}, {"name": "date"}])

w = out[0]
for f in w["facts"]:
    print(w["entities"][f["head"]]["text"], f["relation"], w["entities"][f["tail"]]["text"],
          f["polarity"], f["modality"])
# Henry Wager Halleck date of birth January 16 , 1815 positive asserted
# Henry Wager Halleck date of death January 9 , 1872 positive asserted
# Henry Wager Halleck military branch United States Army positive asserted

Every kniv v7 model returns exactly these facts for both examples, in fp32 and INT8. (The sentence is from the English Wikipedia article on Henry Halleck, CC BY-SA 4.0.) Pass text as kniv.analyse(text, ...) (paragraphs separated by blank lines) or a conversation as turns. analyse returns one record per window:

key content
tokens, sentences words; sentence spans (and speakers)
words per word: pos, morph, lemma, head (0 = root, else 1-based), deprel
ner [type, start, end) named-entity spans
srl frames: predicate and args as [role, start, end)
sentence_layers per sentence: dialogue acts (cls), sentiment
coref clusters of [start, end] word spans (inclusive)
entities type, text, mentions, spans (speakers first in a conversation)
facts head, relation, tail (indices into entities), margin, polarity, modality, holder, time

kniv.extract(...) returns entities and facts only. Without entity_types, entities get six coarse types (PER, ORG, LOC, TIME, NUM, MISC).

Variants

variant load for
fp32 Kniv(path) reference
FP16 Kniv(path, variant="fp16") half the download; GPUs (providers=["CUDAExecutionProvider"])
INT8 Kniv(path, int8=True) CPU speed: about 1.2x faster than fp32 (at this size much of the time is in the heads and the host code)

FP16 matches fp32 within 0.001 on every task. INT8 stays within 0.8 points. To download only the FP16 files:

path = snapshot_download("dragonscale-ai/kniv-v7-small-en", ignore_patterns=[
    "model.pt", "onnx/plain.onnx", "onnx/label.onnx", "onnx/marker.onnx"])
kniv = Kniv(path, variant="fp16")

PyTorch

model.pt holds the PyTorch weights. They are used through the model code in kniv-nlp-models:

from kniv_v7 import Kniv
from v6.export.torch_backend import TorchBackend

kniv = Kniv(path, backend=TorchBackend.from_release(path))

How it works

One encoder runs up to three times per window:

  1. Plain pass. Every linguistic head, coreference and the entity typer.
  2. Label pass. Your type and relation names become vectors, cached per schema.
  3. Marker pass. The window with every entity mention marked. Every entity pair is scored against every relation, then each kept fact's attributes.

Decoding thresholds are in calibration.json, and every one can be changed at run time (see GUIDE.md).

Results

benchmark score
UD English EWT, POS 0.972
UD English EWT, lemma / morphology 0.974 / 0.972
UD English EWT, UAS / LAS 0.932 / 0.911
OntoNotes 5, NER 0.827
PropBank, SRL 0.773
SGD, dialogue acts 0.756
LitBank, coreference 0.620
Re-DocRED, relations (gold / predicted entities) 0.672 / 0.567
FewRel, zero-shot relations (5 / 10 / 15-way) 0.787 / 0.667 / 0.577
CrossNER, zero-shot entity types 0.410
Few-NERD, entity types 0.461
LongMemEval, answer in extracted entities / facts 0.747 / 0.447

Bias, risks and limitations

  • Coverage. People, places and organisations from well-covered regions are recognised and related more reliably than others.
  • Privacy. The model extracts facts about people, speakers included. Store and use them with the consent and data-protection care that implies.
  • Facts are candidates. Treat each fact as a candidate with a confidence (margin), not as verified truth. Keep a human in the loop where facts about people drive decisions.
  • Document-level relations. More facts are missed than with the larger models (Re-DocRED end to end 0.567 against 0.627 for the better teacher and 0.608 for the 150M student). Lower the thresholds for recall (GUIDE.md).
  • Harder tasks. Against the better teacher: NER 0.827 against 0.870, semantic roles 0.773 against 0.810, relations with gold entities 0.672 against 0.733.
  • Coreference is the largest gap: LitBank 0.620 against 0.707.
  • New entity types. Typing entities with type names it has not seen: CrossNER 0.410 against 0.580, Few-NERD 0.461 against 0.523.
  • More facts, lower precision. On conversations it returns more facts than the larger models (178 per LongMemEval question, against 134 for the 150M student and 73 for the UltraBERT model), many with low margins. Raise the thresholds or filter on margin for precision (GUIDE.md).
  • Entity grouping is rule-based. Partial names ("Obama" / "Barack Obama") are not merged.
  • Per-window facts. Facts are per window; nothing is linked across windows or documents.
  • Long windows. Text past 1,024 subwords in a window is not analysed.
  • English only.

Licence

Apache-2.0. The base encoder (jhu-clsp/ettin-encoder-32m) is MIT.

Citation

@misc{kniv_v7_2026,
  title        = {kniv v7: one encoder for linguistic analysis and schema-conditioned knowledge extraction},
  author       = {{Dragonscale}},
  year         = {2026},
  howpublished = {\url{https://huggingface.co/dragonscale-ai/kniv-v7-small-en}}
}

Contact

Questions and issues: https://github.com/rustic-ai/kniv-nlp-models/issues.

Downloads last month
24
Inference Providers NEW
This model isn't deployed by any Inference Provider. ๐Ÿ™‹ Ask for provider support

Model tree for dragonscale-ai/kniv-v7-small-en

Quantized
(15)
this model

Collection including dragonscale-ai/kniv-v7-small-en

Article mentioning dragonscale-ai/kniv-v7-small-en

Evaluation results