kniv v7: Turn Conversations and Documents into Knowledge Your Agents Can Use
An agent can save every word of a conversation and still remember the wrong thing.
"I work at Acme. Next month I'm joining Northstar."
Two organizations, and two different relationships to them. Here is what the released model returns, with one relation in the schema, employer:
user employer Acme positive · asserted · holder: user
user employer Northstar positive · planned · holder: user
(kniv-v7-xlarge-d-en, INT8 on a laptop CPU.)
One organization the user works for. One they plan to join. Two different memories, from one call.
kniv v7 turns conversations and documents into the entities and relationships your application defines. Each relationship comes with predicted attributes that distinguish an assertion from a plan, a negation or a reported claim. You provide the schema. kniv performs the extraction, locally. Your application decides what to remember.
From Text to Useful Knowledge
Most pipelines give an application one of two things: the raw text, or a list of names found in it. Neither is what an application acts on.
kniv returns knowledge in a shape an application can use directly:
- entities, typed with the types you named, speakers included;
- relationships between them, for the relations you named;
- the context of each relationship:
- polarity: positive or negated;
- modality: asserted, planned, hoped for, asked about, hypothetical or reported. "I plan to move to Berlin" is a plan, not a move;
- holder: who says so, whether the user, the assistant or someone they quoted;
- time: when it applies.
A negated statement is still knowledge. "I don't work there anymore" matters. The polarity attribute exists so that a negated statement is represented as negated, not flattened into a positive assertion.
Information is often spread across sentences: someone is named in one, and what they did arrives in the next as "she". kniv reads the surrounding window together, so it can connect the two (more on this below).
kniv also returns the full grammar of every sentence: parts of speech, who did what to whom, and which "she" means which person. It's there for pipelines that need more than facts.
Reading Across Sentences
Most extraction models read one sentence at a time. Documents don't cooperate: a person is named in one sentence, and what they did arrives in the next as "she" or "the company". In a standard document-level benchmark, about half of all facts span sentences.
kniv reads a page at a time. It links the mentions across that page and relates entities wherever the evidence sits. Facts whose entities are two or more sentences apart are extracted almost as well as facts inside one sentence: 0.73 against 0.75 F1 for our xlarge-d model.
"Ada Lovelace was born in London in 1815. She later worked with Charles Babbage on his Analytical Engine."
Ada Lovelace born in London
Ada Lovelace worked with Charles Babbage <- read through "She"
(kniv-v7-xlarge-d-en, INT8 on a laptop CPU.)
Hand it a report, a ticket thread or a long chat, and it splits the text into page-sized windows and reads each as a whole. That's the difference between extracting names from sentences and extracting knowledge from documents.
Your Application Defines the Schema
You describe what you want in plain English: a name and a short description for each relation and entity type. You pass that schema in at run time.

relations = [
{"name": "lives in", "description": "the place where the user resides"},
{"name": "employer", "description": "the organization the user works for"},
]
entity_types = [{"name": "location"}, {"name": "organization"}, {"name": "person"}]There's no training project per schema and no labelled data. The same model serves a memory system today and a support desk tomorrow. Changing what it extracts means changing a list, not retraining a model.
kniv ships with a bank of 1,423 relations and 1,559 entity types, each with a description, as starting points.
What You Can Build With It
Agent memory. Conversations become a knowledge graph of people, places, preferences and plans. Planned relationships are kept apart from asserted ones, with polarity and attribution predicted for each. This is the job kniv was built for, inside uniko, our agent memory library.
Customer support. Mine tickets for product, reported issue and requested refund. Predicted modality separates "it broke" from "it might break".
Sales and CRM. Turn call notes into works for, decision maker, budget and competitor considered, each with a predicted holder: who said it.
Documents and research. Turn contracts, reports and papers into a domain graph with your own types, stored in Uni and queried with rules.
Same model, different schema. No retraining between them.
Better, Faster and Free

The obvious alternative is to ask a hosted LLM to do the extraction. We compared kniv v7 with GPT-6 Sol on the same standard test sets:
| what the task asks | kniv v7 xlarge-u | GPT-6 Sol |
|---|---|---|
| finds the relations in a document, with its entities supplied | 0.73 | 0.48 |
| recognises names of people, places and organisations | 0.87 | 0.85 |
| works out who did what to whom | 0.86 | 0.81 |
| parses sentence structure | 0.93 | 0.89 |
| works out who "she" is | 0.71 | 0.70 |
The gap is widest exactly where memory needs it most: deciding which things in a document are actually related. Most of GPT-6 Sol's misses were connections it never considered. Most of its false facts linked things that had nothing to do with each other.
Then we timed both on the same workload: 60 real chat messages with their context (a median of 141 words), against a memory schema of 30 relations and 15 entity types.
| median per message | billed API tokens per message | runs on | |
|---|---|---|---|
| GPT-6 Sol | 31.4 seconds | about 4,000 | a hosted API |
| kniv v7 xlarge-u, INT8 | 0.35 seconds | none | a laptop CPU (M2 Max) |
On that workload kniv is about 90 times faster, with no per-message API fees and nothing leaving your machine. And that's one of our two largest models: on a 200-word window, xlarge-u takes 0.47 seconds on that laptop, large 0.23 and tiny 0.09. The weights are Apache-2.0 and were trained only on data licensed for commercial use.
Task-specific benchmark scores (accuracy, attachment score or F1, depending on the task), from our own bake-off with zero-shot prompts. GPT-6 Sol's linguistic scores used 300-item samples of each test set; kniv's are on the full test sets. The relation row supplies the reference entities to both; kniv's fully end-to-end score is 0.63. Full protocol in the technical post.
Where kniv Fits

Our stack, end to end:
| layer | product | job |
|---|---|---|
| agents | Rustic AI | guilds of agents that work together |
| memory | uniko | what the agent knows, compiled for fast recall |
| reasoning | Uni | graph, vector, text and rules in one embedded engine |
| understanding | kniv | turns raw text into structured knowledge |
A message arrives in a Rustic AI guild. kniv extracts what it says, and uniko compiles that into memory. Uni stores the memory and reasons over it. Understanding, remembering and reasoning all run inside your own process, with an LLM only where you choose to use one.
Each piece works on its own. kniv doesn't need the rest of the stack: if you just need knowledge out of text, it's a pip install away.
Get Started
pip install onnxruntime tokenizers numpy huggingface_hub
import sys
from huggingface_hub import snapshot_download
path = snapshot_download("dragonscale-ai/kniv-v7-xlarge-u-en")
sys.path.insert(0, path)
from kniv_v7 import Kniv
kniv = Kniv(path, int8=True)
out = kniv.extract(
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"}])
# user lives in Berlin (positive, asserted)
# user employer Siemens (positive, asserted)
That's a CPU, with no GPU and no API key. One call returns the entities, the relationships and their context.
Choosing a model. Six sizes, one call: swap the repository name and nothing else changes.
- kniv-v7-xlarge-u-en: open schemas, new relation and entity types, long inputs.
- kniv-v7-xlarge-d-en: the most accurate parsing, and the better reader of plans in conversation.
- kniv-v7-large-en: less than half their size and about twice as fast, within a point or two on most tasks. The one to start with.
- kniv-v7-medium-en: close to
largeon parsing, semantic roles and relations at about half its size. - kniv-v7-small-en and kniv-v7-tiny-en: smaller still, for small devices. They miss more, especially coreference and unfamiliar entity types.
What kniv Doesn't Do
- Reason or generate text. kniv handles language understanding, not the reasoning or writing tasks of an LLM.
- Connect facts across documents. kniv reads each page-sized window as a whole, but it doesn't link facts across windows or documents. That's your memory layer's job. It also groups mentions by name and doesn't resolve all references to the same entity: "the company" isn't yet merged with "Acme Robotics".
- Guarantee accurate attributes. Plans are its strongest distinction. Negation and reported speech are its weakest: in our own spot checks, "I don't work there anymore" can still come back as a positive fact, and a quoted claim is often attributed to the speaker. Treat the attributes as signals to check. The guide lists the known failure modes, with workarounds.
- Support languages beyond English. Multilingual support isn't available yet.
Try It
- Models: the six repositories above, on Hugging Face.
- How we built it: Bring Your Own Schema: How We Built kniv v7, the technical companion to this post.
- Code: github.com/rustic-ai/kniv-nlp-models.
Bring a schema from your own domain and tell us where it breaks. That's the feedback that makes the next version better.