Before any engineering change, one question: what else does this touch?
The answer is spread across specs, procedures, supplier records and test reports.
A knowledge graph traces it. Direct dependencies first, then everything downstream.
16 is not a spec. 16 bar is.
Engineering data lives in unit tables, spec sheets and diagrams, exactly where generic parsing breaks.
Parse it properly, add GraphRAG, and Lettria beats VectorRAG results by up to 30% in our benchmarks.
Every contract is a network pretending to be a document.
Clauses reference clauses. Obligations bind parties.
Perseus captures clauses, references and metadata as a graph, so review follows the links instead of reading page by page.
A new regulation shouldn't mean a rebuilt knowledge base.
Graph the new document, then:
kg = perseus_client.interlink(kbs=[corpus, update])
Shared entities merge into one node. Every edge follows the merge. Entities of different types never merge.
Healthcare AI should augment clinical expertise, not route around it.
Humans stay at the center, from data input to answer verification. Patient data stays on European servers, with regular audits by outside experts.
A generic extractor gives you Things related to Things.
Hand Perseus an ontology and a clinical note comes back as Patient, Condition, Treatment: the vocabulary your clinicians already use.
build_graph(file_paths=[...], ontology_path="clinical.ttl")
In finance, an answer you can't trace is an answer you can't use.
Every Lettria answer ships with its working: the graph it followed and the exact snippets it came from.
No leap of faith required.
Every graph perseus-client returns is already serialized twice, before you ask.
kg.ttl_content → Turtle, for reasoners and SPARQL
kg.cql_content → Cypher, for Neo4j and FalkorDB
Plus to_rdflib(), to_json(), save_to_neo4j(). Change stacks without re-extracting.
Most LLM mistakes with financial tables aren't reasoning failures. They're parsing failures.
Lettria's parser is trained on earnings statements, risk assessments and investor reports: Word, Excel, PowerPoint, scanned PDFs, emails, CSV, JSON, XML.
interlink() is picky on purpose. Three ways it declines to merge two entities sharing a label:
1. their rdf:types differ
2. they disagree on an immutable property — name, hasName, hasFullName
3. neither carries the interlinking key
A bad merge is worse than a duplicate.
build_graph() doesn't blindly spend.
It uploads, then finds the newest job for that (file, ontology):
· RUNNING → attaches to it
· SUCCEEDED → reuses the output
· FAILED → submits a new one
Ctrl-C and re-run costs nothing. refresh_graph=True forces a fresh one.
The answer is rarely in one document. It's split across five.
Perseus builds a graph per document, then folds them into one — same entity becomes one node, and every edge follows it.
kg = perseus_client.interlink(kbs=graphs)
Multi-hop across the whole corpus.
Extraction without a schema gives you a graph. Extraction with a schema gives you *your* graph.
build_graph(file_paths=[...], ontology_path="domain.ttl")
One argument decides whether the output speaks your domain's language or a generic one.
Most of what your company knows is locked in prose, and prose does not answer questions.
Perseus reads the documents and hands back a graph: typed entities, real relations, queryable.
import perseus_client
graphs = perseus_client.build_graph(file_paths=["contract.pdf"])
Somewhere in a 200-page PDF is the mounting height of a streetlight.
Get it wrong and you send a crew out without a crane.
Magnus Helander on why vector search got his team to 90% accuracy — and why the last 10% needed a graph.
youtu.be/HHFJxYlGN8s
We gave 138 AI models the same homework.
Here's a document. Write down every fact in it, and how those facts connect.
Then we graded what each model found, what it missed, what it made up.
Three columns, not one score.
Empty machine to a queryable graph database, with nothing skipped:
1. docker run falkordb
2. build_graph() → 13 entities, 21 relations
3. kg.save_to_falkordb()
4. MATCH (n) RETURN labels(n), count(*)
No config file. No cluster. No schema up front. <30 seconds.





