Atlas
Relation explainability
Click any edge in the entity graph and eli.ai answers three questions a consultant or analyst always asks: how strong is this link, really? — which way does it point? — why do you say so? The answer is a fully deterministic edge insight: zero LLM calls, computed on the fly from tables the graph already has (mentions, relations, relation_evidence, canonical_relations). Same inputs, same numbers, every time.
Why raw mention counts aren't the strength
The co-occurrence layer accumulates a mentionCount per edge — every document where two entities appear together bumps it. That is a fine thickness heuristic and a bad strengthheuristic: a ubiquitous entity ("Finance", "the platform") co-occurs with everything, so six shared documents with a hub mean far less than three with a rare entity. This is the classic degree bias from the collocation and link-prediction literature, and eli.ai corrects for it with two standard, bounded measures over the document universe:
- NPMI (normalized pointwise mutual information, Bouma 2009) — compares how often the pair actually shares documents against what chance predicts, normalized into
[-1, 1]: 0 means statistically independent, 1 means they always appear together, negative means less than chance. Two popular entities that overlap only at the chance rate land near 0; a rare-but-tight pairing lands near 1. - Jaccard — of all documents mentioning either entity, the share mentioning both (
[0, 1]). Always defined, so it is the fallback when NPMI is degenerate: fewer than two documents in the universe, or the pair never shares a document (thennpmiis reported asnull).
The probability space is documents, not word windows: p(x) is the fraction of entity-mentioning documents that mention x's canonical cluster, p(x,y) the fraction mentioning both.
The composite score
Association is only half the story. An edge is strong if it is eitherdirectly asserted in the text ("Dana works at Northwind") or strongly associated statistically — a single hard works_at statement is a strong edge even with weak co-occurrence. So the score combines two orthogonal terms with a probabilistic OR:
- Saturating assertions— the first and second direct statements move the needle a lot, the twentieth barely at all, matching how a reader trusts "two independent sources said so" far more than one but "twenty" not much more than "ten". Only assertional types count here, so co-occurrence weight isn't double-counted (it already drives
A). - Clamped association — independent or negatively-associated pairs contribute 0 to strength; they are not evidence of a real link.
- Soft OR — symmetric, bounded, monotonic in both terms, and there are no tuning weights to justify.
score, jaccard, and npmi are rounded to 4 decimal places at the API boundary, so displays are stable and tests can assert equality. Raw mentionCount still exists — as edge thickness in the graph view, never as the strength number.
Direction semantics
Direction is a property of the relation type, not of the individual edge — the RDF/OWL split between directed predicates and owl:SymmetricProperty. The classification is deterministic:
- Symmetric types —
related_toandmentions: storage order is an extraction artefact, so they render without a preferred direction (direction: "symmetric"). - Everything else is directed —
works_at,part_of,reports_to,owns,feeds,uses,manages, and any future or unknown type — preserving the storedsrc → dstorder (the safe default: the extractor writes triples subject-first). Because a stored row may sit either way around relative to the pair you queried, the insight resolves it to"src->dst"or"dst->src"for your orientation.
The workspace ontology describes relation types; this classification is intentionally independent of it, so strength and direction stay deterministic even in workspaces whose ontology is sparse.
Evidence, best first
A weighted edge is not yet a readable claim — the "why" is the actual quotes. The insight separates two kinds:
- Assertional evidence— quotes backing typed relations ("Dana reports to the CFO"), each deep-linking to its source document and chunk. These state the relationship and are ordered first.
- Associational context — the documents where the two entities merely co-occur. These situate the relationship and come after the real statements.
Finally, a fixed template assembles the explanation sentence — no LLM, so it is reproducible and free: the top assertional relation rendered in its resolved direction with a per-type verb phrase (works_at→ "works at"), the direct-statement count, the co-occurrence count, and a bucketed qualifier for the association ("strong" ≥ 0.5, "moderate" ≥ 0.25, "weak" > 0, else "chance-level"):
Where it surfaces
One shared card renders the insight everywhere — explanation sentence, strength bar with the three measures behind it (plain-word tooltips), every relation with its direction glyph, evidence quotes with document deep-links, and co-mention chips:
- Graph explorer — clicking an edge (not a node) opens the edge side panel with the full insight. The graph view also uses the bulk per-edge scores for edge thickness and direction arrows.
- Entity detail — every relation row in an entity's neighborhood panel carries a
Why?expander that loads the insight for that pair (cached per pair, so collapsing and re-expanding never refetches). - Document view — the entities rail beside the editor shows In this document (type-colored chips for every entity the document mentions) and Related (entities the document does not mention but that connect through the graph), each related row with its
viapath, a mini strength bar, and the sameWhy?expander. See Documents & editing.
The backing endpoints are workspace-scoped and member-gated: GET /api/w/:workspaceId/graph/edge?src&dst for one full insight, GET …/graph/edge-strengths for the bulk per-edge scores, and GET …/documents/:docId/entities for the document rail.
Merged entities resolve to their canonical head
The research behind the formulas
docs/research/relation-explainability.md in the repository. The formulas there are mirrored verbatim in the implementation.