Python SDK for the Overton platform.
Project description
Overton SDK
Overton is a probabilistic knowledge graph that resolves entities and relations from unstructured text. You write raw evidence in natural language; Overton handles LLM-based extraction, entity deduplication, and uncertainty quantification.
Prerequisites
You need two things from Overton:
- An API token (
ovtn_...) - Your hostname (e.g.
api.overton.bio)
Overton is a hosted platform — there's nothing to run or operate on your side. Contact us to get a token.
Installation
pip install overton-sdk
Requires Python 3.11+. The only dependency is httpx.
Authorization and client initialization
Overton authenticates with the bearer token (ovtn_...) Overton issued you.
Construct an auth object and pass it to the client, along with your hostname:
import os
import overton_sdk
client = overton_sdk.OvertonClient(
auth=overton_sdk.UserTokenAuth(os.environ["OVERTON_TOKEN"]),
hostname="overton.example.com", # bare host; scheme defaults to https
)
Environment variables
If OVERTON_TOKEN and OVERTON_HOSTNAME are set, the client picks them up with no
arguments:
export OVERTON_TOKEN=ovtn_...
export OVERTON_HOSTNAME=overton.example.com
client = overton_sdk.OvertonClient()
Configuration
Tune transport behavior with a Config object:
from overton_sdk import Config
client = overton_sdk.OvertonClient(
auth=overton_sdk.UserTokenAuth(token),
hostname="overton.example.com",
config=Config(timeout=60.0, max_retries=3, verify=True),
)
Use the client as a context manager to ensure connections are closed:
with overton_sdk.OvertonClient() as client:
m = client.manifold("my-manifold")
...
[!TIP] For local development you can point at a server over plain HTTP by passing a full
hostname="http://localhost:8000"— an explicit scheme is respected.
Core concepts
| Concept | What it is |
|---|---|
| Manifold | A named knowledge graph. Create as many as you need — one per domain, project, or dataset. |
| Evidence | A piece of text you write in. Overton extracts entities and relations from it using an LLM. |
| Contributor ID | What write() returns — the ID of the evidence you just wrote. Use it for raw reads and curation. |
| Entity ID | The ID of a resolved real-world entity. Different from a contributor ID. Get entity IDs from query(). |
| Covariate | Structured metadata on evidence ({"source": "reuters", "year": "2024"}). Overton uses it to build conditional distributions. |
Quickstart
import os
import overton_sdk
client = overton_sdk.OvertonClient(
auth=overton_sdk.UserTokenAuth(os.environ["OVERTON_TOKEN"]),
hostname="overton.example.com",
)
m = client.manifold("earnings")
# Write evidence
ids = m.write("Apple reported record profits of $94B in Q1 2024, driven by iPhone sales")
# Query resolved entities
results = m.query("tech company earnings", top_k=5)
for entity in results:
print(entity.entity_id, entity.point_estimate(), entity.type_distribution)
# Manifold statistics
stats = m.measures()
print(f"{stats.entity_count} entities, entropy={stats.aggregate_entropy:.3f}")
Writing evidence
# Single string
m.write("Google acquired DeepMind for £400M in 2014")
# Multiple items in one call
m.write(
"Apple reported record Q1 profits",
"Microsoft Azure revenue grew 29% year over year",
)
# With source and covariates
m.write({
"text": "Apple reported record Q1 profits",
"source": "reuters",
"covariates": {"quarter": "Q1-2024", "sentiment": "positive"},
})
# Mix of strings and dicts
m.write(
"Apple reported record profits",
{"text": "Google missed analyst estimates", "covariates": {"sentiment": "negative"}},
)
write() returns a list of contributor IDs — one per entity or relation mention
extracted from your text by the LLM.
Reading
# Raw read — get back the original text using a contributor ID
text = m.read(contributor_id, raw=True)
# Resolved read — get the entity distribution using an entity ID
# Note: entity IDs come from query(), not from write()
entity = m.read(entity_id)
print(entity.type_distribution) # {"ORG": 0.91, "PERSON": 0.09}
print(entity.point_estimate()) # "ORG"
print(entity.contributor_weights) # which evidence pieces contributed and how much
# Read a relation
relation = m.read_relation(relation_id)
print(relation.type_distribution)
print(relation.point_estimate({"cell_line": "HeLa"})) # conditional on a covariate
Querying
results = m.query("pharmaceutical company", top_k=10)
for entity in results:
print(entity.entity_id)
print(entity.point_estimate()) # most likely type
print(entity.type_distribution) # full probability distribution
print(entity.alias_ids) # other IDs this entity was known by
Results are EntityDistribution objects ranked by semantic similarity.
Measures
# Manifold-level
mm = m.measures()
mm.entity_count # number of resolved entities
mm.relation_count # number of resolved relations
mm.aggregate_entropy # average type uncertainty across all entities (nats)
mm.component_count # number of connected subgraphs
mm.uncertainty_map # {entity_id: entropy} for every entity
# Entity-level
em = m.entity_measures(entity_id)
em.type_entropy # uncertainty over entity type (0 = certain, ln(N) = maximally uncertain)
em.evidence_concentration # 1.0 = one source dominates, 0.0 = evidence spread evenly
em.effective_sample_size # Kish ESS — effective number of independent evidence pieces
# Relation-level
rm = m.relation_measures(relation_id)
rm.marginal_entropy # uncertainty over relation type
rm.marginal_perplexity # effective number of competing relation types
rm.is_contradictory # True if evidence strongly conflicts
rm.mutual_information # list[CovariateMI] — which covariates are informative
# Divergence between two entities or relations
div = m.divergence(entity_id_a, entity_id_b) # Jensen-Shannon (default)
div = m.divergence(entity_id_a, entity_id_b, metric="kl") # KL divergence
print(div.value) # 0.0 = identical distributions, 1.0 = maximally different
Curation
# Retract — soft delete, reversible. Evidence is ignored in future resolutions.
event = m.retract(contributor_id)
print(event.reversible) # True
# Hard delete — permanent. Evidence is removed entirely.
event = m.hard_delete(contributor_id)
print(event.reversible) # False
# Merge — declare that two entity IDs refer to the same real-world entity
new_entity_id, events = m.merge(["entity-abc", "entity-xyz"])
# Split — declare that one entity ID actually contains multiple distinct entities.
# partition is a list of contributor ID groups, one group per new entity.
new_entity_ids, events = m.split(entity_id, partition=[
["contributor-1", "contributor-2"], # -> entity A
["contributor-3"], # -> entity B
])
# Full audit log
log = m.event_log()
for event in log:
print(event.kind, event.timestamp, event.actor, event.reversible)
Error handling
All SDK exceptions subclass OvertonError, which exposes .status_code. Concrete
subclasses are keyed by HTTP status code:
from overton_sdk import NotFoundError, UnauthorizedError, OvertonError
try:
entity = m.read("entity-123")
except NotFoundError:
print("entity not found")
except UnauthorizedError:
print("invalid or expired API token")
except OvertonError as e:
print(f"API error {e.status_code}: {e}")
| Exception | HTTP status | When |
|---|---|---|
BadRequestError |
400 | Malformed request |
UnauthorizedError |
401 | Missing or invalid API token |
PermissionDeniedError |
403 | Token lacks permission for this action |
NotFoundError |
404 | Entity, relation, or contributor not found |
UnprocessableEntityError |
422 | Request failed validation |
InternalServerError |
5xx | Server-side failure |
OvertonError |
any | Base class — exposes .status_code |
[!NOTE]
AuthErrorandValidationErrorremain available as aliases ofUnauthorizedErrorandUnprocessableEntityErrorfor backwards compatibility.
Static type analysis
The SDK ships a py.typed marker (PEP 561), so type checkers like mypy and pyright
resolve its annotations out of the box.
from overton_sdk import (
OvertonClient,
ManifoldHandle,
EntityDistribution,
RelationDistribution,
ManifoldMeasures,
EntityMeasures,
RelationMeasures,
DivergenceResult,
CurationEvent,
)
def analyse(m: ManifoldHandle) -> list[EntityDistribution]:
return m.query("some query", top_k=20)
Full example — biomedical literature
import os
import overton_sdk
client = overton_sdk.OvertonClient(
auth=overton_sdk.UserTokenAuth(os.environ["OVERTON_TOKEN"]),
hostname="overton.example.com",
)
m = client.manifold("biomedical")
# Ingest papers with provenance
m.write(
{
"text": "BRCA1 strongly activates PARP1 in the presence of DNA damage",
"source": "pmid:12345678",
"covariates": {"cell_line": "HeLa", "year": "2021"},
},
{
"text": "BRCA1 was shown to inhibit PARP1 under normoxic conditions",
"source": "pmid:99887766",
"covariates": {"cell_line": "MCF7", "year": "2023"},
},
)
# Find the BRCA1-PARP1 relation
results = m.query("BRCA1 PARP1 interaction", top_k=5)
if results:
entity = results[0]
print(f"Entity: {entity.point_estimate()} (confidence: {max(entity.type_distribution.values()):.2f})")
# Check manifold health
mm = m.measures()
print(f"Manifold: {mm.entity_count} entities, {mm.relation_count} relations")
print(f"Mean uncertainty: {mm.aggregate_entropy:.3f} nats")
Version
import overton_sdk
print(overton_sdk.__version__) # "0.1.0"
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file overton_sdk-0.1.0.tar.gz.
File metadata
- Download URL: overton_sdk-0.1.0.tar.gz
- Upload date:
- Size: 22.3 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.11.5
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
0c523347279a2933d592fc387634a2fc0e1a9e23644d827e4888125d47caa75b
|
|
| MD5 |
341bc6e87cd6befb89ac1086cce4c608
|
|
| BLAKE2b-256 |
02d1fb4a1e6946d32ebbd61900ec14a29c336cfd376da0ed3a4e45e27eb0d2ba
|
File details
Details for the file overton_sdk-0.1.0-py3-none-any.whl.
File metadata
- Download URL: overton_sdk-0.1.0-py3-none-any.whl
- Upload date:
- Size: 15.8 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.11.5
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
3d37af4bc175fccd8d6035dfe294efbd6cff0de90c0f3fe85c9687460564dada
|
|
| MD5 |
6768325e6380156c0c7aab9c8574b966
|
|
| BLAKE2b-256 |
ad9c88fa7636b573910769097e1397424218e79b2938560b70df9ab07e1335df
|