Skip to content

Suggest ontology changes from text (experimental)

View Markdown

Your text already describes your domain. Interview transcripts name the tools people use, the documents they pass on, and who approves what. Fit from text reads that text and proposes the ontology changes it supports: new classes, new properties, new relations. Each proposal quotes the sentence that supports it. The proposals wait in the suggestion inbox until a person accepts or dismisses them, so nothing changes your ontology on its own.

Fit from text works like search by meaning. You declare on a class which properties hold the text, and the platform keeps the proposals in step with your graph. A new or changed instance is read after the next commit is published.

The fit proposes ontology changes only. Extracting the facts of each text (the people, tools and dates) stays with you.

Commit each text as an instance of a class, with the text in a string property. A transcript of 40,000 characters fits in one property. This example loads four short interviews in Turtle:

@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .
@prefix c: <https://example.org/class/> .
@prefix e: <https://example.org/interview/> .
@prefix p: <https://example.org/p/> .
e:jonas-berg a c:interview ;
rdfs:label "Interview with Jonas Berg" ;
p:transcript """Interviewer: How does a customer request reach your team?
Jonas: Every request becomes a ticket in Deskflow, our ticket system. ...""" .
Terminal window
curl -X POST "$LBB/v1/graph/import/rdf?format=turtle" \
-H "Authorization: Bearer $LBB_API_KEY" \
--data-binary @interviews.ttl

JSON records work the same way: commit an Interview with a transcript property. Documents from the SharePoint and Google Drive integrations already carry a text property.

The preview shows the fields the fit would read and the text of a few instances. It stores nothing and calls no model.

Terminal window
curl -X POST "$LBB/v1/ontology/fit-sources/preview" \
-H "Authorization: Bearer $LBB_API_KEY" -H 'Content-Type: application/json' \
--data '{"class": "https://example.org/class/interview", "from": ["transcript"]}'

from takes the same paths as an embedding: a property name (transcript), label, a prefixed name, a full IRI, or a path with one link. Without from, the long text facts of the class are chosen.

Add "propose": true for a dry run. The models read the first part of up to three instances, and every proposal comes back with the quote, the support score and what the checks made of it. Nothing is filed. The dry run waits at most 60 seconds for the models; an instance that has not finished by then is left out, and truncated says so.

In the console, open Review and click Suggest from text (also under Models → Ontology fit → From text). Pick the class and its text fields, write one sentence about the text, try it on 3 instances, and click Start reading. With the API:

Terminal window
curl -X PUT "$LBB/v1/ontology/fit-sources" \
-H "Authorization: Bearer $LBB_API_KEY" -H 'Content-Type: application/json' \
--data '{
"class": "https://example.org/class/interview",
"from": ["transcript"],
"context": "Interviews with employees about their work processes and the tools they use"
}'

context is one sentence about the text. The model reads it with every part of every text.

With the TypeScript client:

import { LbbClient } from "@littlebigbrain/client";
const client = new LbbClient({
baseUrl: process.env.LBB_URL!,
apiKey: process.env.LBB_API_KEY!,
});
const dryRun = await client.ontology.fitSources.preview({
class: "https://example.org/class/interview",
from: ["transcript"],
propose: true,
});
await client.ontology.fitSources.declare({
class: "https://example.org/class/interview",
from: ["transcript"],
context: "Interviews with employees about their work processes and the tools they use",
});

With Python, client.ontology.fit_sources.declare(class_, from_=[...], context=...) does the same. Agents use the MCP tools lbb_fit_sources and lbb_fit_sources_manage.

The platform now reads every interview. For each one:

  1. A reasoning model proposes changes for each part of about 40,000 characters, each with a quote from the text.
  2. Every quote is checked against the text. A proposal whose quote is not in the text is dropped.
  3. Every change is checked against your current ontology. Invalid changes and changes you have already are dropped.
  4. A decision model scores how well each quote supports its change. Weak support (below 0.5) is dropped.
  5. The kept proposals become suggestions. The same change from many interviews is one suggestion, with the number of interviews that support it and up to 20 quotes.

Check the progress:

Terminal window
curl "$LBB/v1/ontology/fit-sources?name=interview" -H "Authorization: Bearer $LBB_API_KEY"

The status shows the instances read, the changed instances still to read, the proposals kept and dropped per check, the suggestions filed, this month’s spend and the last error. POST /v1/ontology/fit-sources/refresh?name=interview asks the platform to read new instances now and returns at once; check the status again for the progress.

In the console, open Review. With the API, list the suggestions of the source:

Terminal window
curl "$LBB/v1/ontology/suggestions?origin_id=fit:interview" \
-H "Authorization: Bearer $LBB_API_KEY"

Each suggestion shows the change, the number of interviews that support it, and the quotes. Accept the changes you want, edit one before you accept it, or dismiss it with a reason.

A dismissed change is not filed again. It reopens only when the interviews that support it reach twice the count it had when you dismissed it, and at least three more.

Terminal window
curl -X POST "$LBB/v1/ontology/suggestions/accept?suggestion_id=sg_…" \
-H "Authorization: Bearer $LBB_API_KEY"

Accepting applies the change to the ontology as it is now. New interviews keep adding support to the open suggestions.

To try the fit on one text without a class, use Suggest from text in the console, or call POST /v1/ontology/fit-text with pasted text:

Terminal window
curl -X POST "$LBB/v1/ontology/fit-text" \
-H "Authorization: Bearer $LBB_API_KEY" -H "Content-Type: application/json" \
-d '{"name": "meeting-notes", "text": "We track every support ticket on a shared board. …",
"context": "Notes from a team meeting", "dry_run": true}'

Or with an uploaded PDF. Parse it first with the Parse documents workflow, then give its SHA-256 and, if you like, the pages to read:

Terminal window
curl -X POST "$LBB/v1/ontology/fit-text" \
-H "Authorization: Bearer $LBB_API_KEY" -H "Content-Type: application/json" \
-d '{"name": "parts-catalogue", "document": "<sha256>", "pages": {"from": 1, "to": 20},
"context": "A parts catalogue with one sheet per part."}'

The call runs the same checks as a fit source and returns every proposal with its outcome. With dry_run: true it files nothing. Otherwise the kept proposals go to the inbox under fit:<name>, each with its quote; for a PDF also the page and the line the quote is on. One call reads at most about 60,000 characters (16 parts) and takes about a minute and a half. A longer text is cut after the first pages that fit, and the answer says truncated: true and which pages it read. A file without parsed pages gives 409 document_not_parsed.

Each part of a text is one call to the reasoning model, and each text one call to the decision model. The calls count against a monthly budget for fit from text per stack (10 US dollars by default). At the limit the fit stops with 429 fit_budget_exceeded until the next month. Fit from text needs a Cloud plan.

Every model call is in the call log under Models, so you can check the proposals and the scores.