Compare commits

..
Author SHA1 Message Date
Zohaib Hassnain 7e27ad373d correct schema 2026-09-03 14:40:33 +05:00
Zohaib Hassnain 1213f79e03 docs(quickstart): read parsed full_text 2026-09-03 14:35:57 +05:00
6 changed files with 343 additions and 360 deletions
+183 -4
View File
@@ -1,9 +1,14 @@
/* ============================================================
SEMANTICA DOCS — DESIGN SYSTEM
SEMANTICA DOCS — PREMIUM DESIGN SYSTEM
Dark-first (#080C10 bg, #10B981 emerald accent)
Minimal, static styling — no decorative motion.
============================================================ */
/* ── Keyframes ─────────────────────────────────────────────── */
@keyframes pageFadeIn {
from { opacity: 0; transform: translateY(6px); }
to { opacity: 1; transform: translateY(0); }
}
/* ── Global ─────────────────────────────────────────────────── */
html {
scroll-behavior: smooth;
@@ -24,7 +29,16 @@ html {
}
::-webkit-scrollbar-thumb:hover { background: rgba(16, 185, 129, 0.4); }
/* ── Focus rings (accessibility — kept) ─────────────────────── */
/* ── Page entrance ──────────────────────────────────────────── */
main,
article,
[class*="content-area"],
[class*="ContentArea"],
[class*="prose"] {
animation: pageFadeIn 0.35s ease both;
}
/* ── Focus rings ─────────────────────────────────────────────── */
*:focus-visible {
outline: 2px solid rgba(16, 185, 129, 0.55) !important;
outline-offset: 3px !important;
@@ -45,7 +59,7 @@ h1::after {
left: 0;
width: 44px;
height: 2px;
background: #10B981;
background: linear-gradient(90deg, #10B981 0%, transparent 100%);
border-radius: 1px;
}
@@ -57,6 +71,9 @@ article a,
[class*="prose"] a {
text-decoration-color: rgba(16, 185, 129, 0.35);
text-underline-offset: 3px;
transition:
text-decoration-color 0.15s ease,
color 0.15s ease;
}
article a:hover,
@@ -72,6 +89,14 @@ blockquote {
padding: 0.9rem 1.2rem !important;
font-style: italic;
color: rgba(255, 255, 255, 0.68) !important;
transition:
border-color 0.2s ease,
background-color 0.2s ease !important;
}
blockquote:hover {
border-left-color: rgba(16, 185, 129, 0.65) !important;
background: rgba(16, 185, 129, 0.07) !important;
}
/* ── HR / Divider ────────────────────────────────────────────── */
@@ -98,11 +123,165 @@ table thead th {
border-bottom: 1px solid rgba(16, 185, 129, 0.18) !important;
}
table tbody tr {
transition: background-color 0.15s ease;
cursor: default;
}
table tbody tr:hover {
background-color: rgba(16, 185, 129, 0.06) !important;
}
table tbody tr:hover td {
background-color: transparent !important;
}
table td,
table th {
transition: background-color 0.15s ease;
}
/* ── CODE BLOCKS ─────────────────────────────────────────────── */
pre,
[class*="codeblock"],
[class*="code-group"],
[class*="CodeBlock"],
[data-rehype-pretty-code-fragment] {
transition:
box-shadow 0.25s cubic-bezier(0.4, 0, 0.2, 1),
border-color 0.25s cubic-bezier(0.4, 0, 0.2, 1),
transform 0.25s cubic-bezier(0.4, 0, 0.2, 1) !important;
}
pre:hover,
[class*="codeblock"]:hover,
[class*="CodeBlock"]:hover,
[data-rehype-pretty-code-fragment]:hover {
transform: translateY(-1px) !important;
box-shadow:
0 0 0 1px rgba(16, 185, 129, 0.18),
0 2px 12px rgba(16, 185, 129, 0.06),
0 8px 32px rgba(0, 0, 0, 0.2) !important;
border-color: rgba(16, 185, 129, 0.2) !important;
}
/* ── CARDS ───────────────────────────────────────────────────── */
[class*="card"],
[class*="Card"],
[data-card],
.group\/card {
transition:
transform 0.22s ease,
box-shadow 0.22s ease,
border-color 0.22s ease !important;
}
[class*="card"]:hover,
[class*="Card"]:hover,
[data-card]:hover,
.group\/card:hover {
transform: translateY(-3px) !important;
box-shadow:
0 8px 28px rgba(0, 0, 0, 0.18),
0 0 0 1px rgba(16, 185, 129, 0.22) !important;
border-color: rgba(16, 185, 129, 0.28) !important;
}
/* ── CALLOUTS / ADMONITIONS ──────────────────────────────────── */
[class*="callout"],
[class*="Callout"],
[class*="admonition"] {
transition:
box-shadow 0.2s ease,
border-color 0.2s ease !important;
}
[class*="callout"]:hover,
[class*="Callout"]:hover,
[class*="admonition"]:hover {
box-shadow: 0 2px 16px rgba(16, 185, 129, 0.08) !important;
border-color: rgba(16, 185, 129, 0.35) !important;
}
/* ── STEPS ───────────────────────────────────────────────────── */
[class*="step"],
[class*="Step"] {
transition: background-color 0.15s ease !important;
}
[class*="step"]:hover,
[class*="Step"]:hover {
background-color: rgba(16, 185, 129, 0.04) !important;
}
/* ── INLINE CODE ─────────────────────────────────────────────── */
:not(pre) > code {
transition:
background-color 0.15s ease,
color 0.15s ease !important;
cursor: text;
}
:not(pre) > code:hover {
background-color: rgba(16, 185, 129, 0.16) !important;
}
/* ── NAVIGATION / SIDEBAR ────────────────────────────────────── */
nav a,
[class*="sidebar"] a,
[class*="Sidebar"] a {
transition: color 0.15s ease !important;
text-decoration: none;
position: relative;
}
nav a::after,
[class*="sidebar"] a::after,
[class*="Sidebar"] a::after {
content: "";
position: absolute;
bottom: -1px;
left: 0;
width: 0;
height: 1px;
background: #10B981;
transition: width 0.2s ease;
}
nav a:hover::after,
[class*="sidebar"] a:hover::after,
[class*="Sidebar"] a:hover::after {
width: 100%;
}
/* ── TEXT / LIST ITEMS ───────────────────────────────────────── */
ul > li,
ol > li {
border-radius: 3px;
transition: background-color 0.12s ease;
}
ul > li:hover,
ol > li:hover {
background-color: rgba(16, 185, 129, 0.04);
}
/* ── PRIMARY BUTTON / CTA ────────────────────────────────────── */
button[class*="primary"],
a[class*="primary"],
[class*="btn-primary"],
[class*="ButtonPrimary"] {
transition:
box-shadow 0.2s ease,
transform 0.2s ease !important;
}
button[class*="primary"]:hover,
a[class*="primary"]:hover,
[class*="btn-primary"]:hover,
[class*="ButtonPrimary"]:hover {
box-shadow: 0 0 22px rgba(16, 185, 129, 0.28) !important;
transform: translateY(-1px) !important;
}
/* ── HIDE THEME TOGGLE ───────────────────────────────────────── */
+80 -111
View File
@@ -38,19 +38,18 @@ This structure makes knowledge **searchable**, **connectable**, **queryable**, a
Scanning text to find and classify real-world entities:
```python
# "Apple Inc. was founded by Steve Jobs in 1976 in Cupertino."
[
Entity(text="Apple Inc.", label="ORG", start_char=0, end_char=10, confidence=0.98),
Entity(text="Steve Jobs", label="PERSON", start_char=25, end_char=35, confidence=0.99),
Entity(text="1976", label="DATE", start_char=39, end_char=43, confidence=0.95),
Entity(text="Cupertino", label="GPE", start_char=47, end_char=56, confidence=0.97),
]
# Input: "Apple Inc. was founded by Steve Jobs in 1976 in Cupertino."
{
"entities": [
{"text": "Apple Inc.", "type": "ORGANIZATION", "confidence": 0.98},
{"text": "Steve Jobs", "type": "PERSON", "confidence": 0.99},
{"text": "1976", "type": "DATE", "confidence": 0.95},
{"text": "Cupertino", "type": "LOCATION", "confidence": 0.97}
]
}
```
`NERExtractor(method=...).extract(text)` returns a list of `Entity` objects, each
with a `label`, character offsets (`start_char` / `end_char`), a `confidence`
score, and a `metadata` dict recording the extraction method. Three methods are
available:
Each entity gets a type, confidence score, and a link to its source document. Three extraction methods are available:
| Method | Speed | Accuracy | Requirements |
| :------ | :----- | :-------- | :------------ |
@@ -63,19 +62,15 @@ available:
Finding how entities connect to each other:
```python
jobs = Entity(text="Steve Jobs", label="PERSON", start_char=25, end_char=35)
apple = Entity(text="Apple Inc.", label="ORG", start_char=0, end_char=10)
[
Relation(subject=jobs, predicate="founded", object=apple, confidence=0.92),
Relation(subject=apple, predicate="located_in", object=Entity(text="Cupertino", label="GPE", start_char=47, end_char=56), confidence=0.89),
]
{
"relationships": [
{"subject": "Steve Jobs", "predicate": "founded", "object": "Apple Inc.", "confidence": 0.92},
{"subject": "Apple Inc.", "predicate": "located_in", "object": "Cupertino", "confidence": 0.89}
]
}
```
`RelationExtractor(method=...).extract(text, entities=entities)` returns a list of
`Relation` objects: typed subject-predicate-object triples (the endpoints are
`Entity` objects) with confidence scores and source attribution. Extraction runs
via pattern rules, ML models, or LLMs.
Relationships can be extracted via rule-based methods, ML models, or LLMs: each producing typed triplets with confidence scores and source attribution.
## Knowledge Graph vs. Vector Store
@@ -99,10 +94,9 @@ Both store information for AI retrieval: but they're built for different jobs.
```python
from semantica.kg import GraphBuilder, PathFinder
graph = GraphBuilder(merge_entities=True).build(
{"entities": entities, "relationships": rels}
)
path = PathFinder().dijkstra_shortest_path(graph, "Steve Jobs", "Tim Cook")
graph = GraphBuilder(merge_entities=True).build(entities=entities, relationships=rels)
finder = PathFinder()
path = finder.dijkstra_shortest_path(graph, "Steve Jobs", "Tim Cook")
```
</Tab>
@@ -146,16 +140,8 @@ Both store information for AI retrieval: but they're built for different jobs.
context = AgentContext(
vector_store=VectorStore(backend="faiss", dimension=768),
knowledge_graph=ContextGraph(advanced_analytics=True),
graph_expansion=True,
)
# store() extracts entities and populates the graph + vector index
context.store([{"content": "Steve Jobs co-founded Apple Inc. in 1976."}])
# retrieve() blends vector similarity with graph traversal
results = context.retrieve("Who founded Apple?", use_graph=True, expand_graph=True)
for r in results:
print(r["score"], r["content"], r["source"])
result = context.query("Who founded Apple?", mode="graphrag")
```
</Tab>
</Tabs>
@@ -235,80 +221,70 @@ Inferred: Steve Jobs has a connection to Cupertino
Applies IF/THEN rules repeatedly until no new facts can be derived. Best for alert systems, compliance checks, and trigger-based workflows.
```python
from semantica.reasoning import Reasoner
from semantica.reasoning import Reasoner, Rule, Fact, RuleType
engine = Reasoner()
engine.add_fact("Manager(Alice)")
engine.add_rule("IF Manager(?x) THEN HasAuthority(?x)")
results = engine.forward_chain() # list of InferenceResult
for r in results:
print(r.conclusion) # "HasAuthority(Alice)"
engine.add_fact(Fact(subject="Alice", predicate="is_a", obj="Manager"))
engine.add_rule(Rule(
rule_type=RuleType.FORWARD_CHAIN,
conditions=[{"subject": "?x", "predicate": "is_a", "object": "Manager"}],
conclusion={"subject": "?x", "predicate": "has_authority", "object": "true"}
))
result = engine.infer()
```
</Tab>
<Tab title="Rete Network">
Efficient pattern matching for large rule sets: the Rete algorithm avoids re-evaluating rules whose preconditions haven't changed. Best for thousands of rules over millions of facts.
```python
from semantica.reasoning import ReteEngine, Rule, Fact
from semantica.reasoning import ReteEngine
engine = ReteEngine()
engine.build_network([
Rule(rule_id="r1", name="manager_authority",
conditions=["Manager(?x)"], conclusion="HasAuthority(?x)"),
])
engine.add_fact(Fact(fact_id="f1", predicate="Manager", arguments=["Alice"]))
matches = engine.match_patterns()
results = engine.execute_matches(matches) # ["HasAuthority(?x)"]
engine.load_rules("rules/domain_rules.json")
results = engine.run(kg)
```
</Tab>
<Tab title="LLM Reasoning">
`GraphReasoner` answers open-ended questions over a knowledge graph with an
LLM, returning a natural-language answer grounded in the graph's facts. Best
for exploratory and investigative questions that fixed rules can't anticipate.
<Tab title="Deductive & Abductive">
**Deductive**: classical syllogistic reasoning from premises to guaranteed conclusions.
**Abductive**: infers the most likely explanation for observed evidence. Best for diagnostic and investigative use cases.
```python
from semantica.reasoning import GraphReasoner
reasoner = GraphReasoner(provider="openai", model="gpt-4o-mini")
answer = reasoner.reason(kg, "Which suppliers are indirectly exposed to the Acme outage?")
graph_reasoner = GraphReasoner(kg)
graph_reasoner.add_rule({"if": [{"subject": "?a", "predicate": "parent_of", "object": "?b"}], "then": {"subject": "?a", "predicate": "ancestor_of", "object": "?b"}})
inferences = graph_reasoner.infer(kg)
```
</Tab>
<Tab title="Datalog (v0.4.0)">
Recursive Horn clause rules with fixpoint semantics: handles transitive closure and recursive relationships that forward chaining cannot express.
```python
from semantica.reasoning import DatalogReasoner
from semantica.reasoning import DatalogReasoner, DatalogFact, DatalogRule
reasoner = DatalogReasoner()
reasoner.add_fact("parent(alice, bob)")
reasoner.add_fact("parent(bob, charlie)")
reasoner.add_rule("ancestor(X, Y) :- parent(X, Y).")
reasoner.add_rule("ancestor(X, Z) :- parent(X, Y), ancestor(Y, Z).")
reasoner.derive_all()
results = reasoner.query("ancestor(alice, ?Z)") # {"Z": "bob"} and {"Z": "charlie"}, order not guaranteed
reasoner.add_fact(DatalogFact("parent", ("alice", "bob")))
reasoner.add_rule(DatalogRule("ancestor(?X, ?Y) :- parent(?X, ?Y)."))
reasoner.evaluate()
results = reasoner.query("ancestor(alice, ?Z)")
```
</Tab>
<Tab title="Engine Comparison">
| Engine | Class | Best For |
| :------ | :----- | :-------- |
| Forward chaining | `Reasoner` | Alert systems, compliance checks |
| Rete network | `ReteEngine` | Large rule sets, high fact throughput |
| SPARQL expansion | `SPARQLReasoner` | Semantic web, ontology reasoning over RDF |
| Datalog (v0.4.0) | `DatalogReasoner` | Transitive closure, graph reachability |
| Temporal | `TemporalReasoningEngine` | Allen interval algebra, time-aware inference |
| LLM over the graph | `GraphReasoner` | Open-ended, investigative questions |
| Engine | Description | Best For |
| :------ | :----------- | :-------- |
| Forward chaining | Applies rules until fixpoint | Alert systems, compliance checks |
| Rete network | Efficient pattern matching | Large rule sets, high fact throughput |
| Deductive | Classical syllogistic reasoning | Mathematical and logical inference |
| Abductive | Most likely explanation | Diagnostics, investigation |
| SPARQL | Query-based inference over RDF | Semantic web, ontology reasoning |
| Datalog (v0.4.0) | Recursive Horn clause rules | Transitive closure, graph reachability |
</Tab>
</Tabs>
`Reasoner.forward_chain()` returns `InferenceResult` objects that carry the rule
applied (`rule_used`) and the premises it fired on, and `ExplanationGenerator`
turns one into a step-by-step natural-language justification: reasoning here is
**not** a black box.
All engines produce **explainable inference paths**: not black-box conclusions. Every derived fact includes the rules and premises that produced it.
## Temporal Intelligence
@@ -337,16 +313,11 @@ Explore the semantic neighborhood of any entity in your graph: useful for unders
```python
from semantica.kg import SimilarityCalculator
calc = SimilarityCalculator(method="cosine") # "cosine" | "euclidean" | "manhattan" | "correlation"
# Similarity for every unique pair of node embeddings: {(node_a, node_b): score}
pairs = calc.pairwise_similarity({"apple": vec_apple, "google": vec_google, "nest": vec_nest})
# Or rank a set of embeddings by closeness to one query vector
nearest = calc.find_most_similar(embeddings, query_embedding, top_k=10)
calc = SimilarityCalculator()
scores = calc.calculate_similarity(entity_a, entity_b)
```
**Features:** N×N semantic distance matrices, ego-mode visualization, distance band classification (`direct` / `near` / `mid-range` / `distant`), embedding cache optimization for large graphs.
**Features:** N×N semantic distance matrices, ego-mode visualization, distance band classification (`near` / `mid` / `far`), embedding cache optimization for large graphs.
The [Visualization module](/reference/visualization) renders distance matrices as interactive heatmaps and ego-mode neighborhood graphs. The [Explorer](/reference/explorer) embeds distance intelligence directly in the browser dashboard.
@@ -370,11 +341,11 @@ Real-world data contains the same entity under many names: "Apple", "Apple Inc."
```python
from semantica.deduplication import DuplicateDetector, EntityMerger
detector = DuplicateDetector(similarity_threshold=0.85)
candidates = detector.detect_duplicates(entities)
detector = DuplicateDetector(similarity_threshold=0.85)
duplicates = detector.detect_duplicates(entities)
merger = EntityMerger()
operations = merger.merge_duplicates(entities, strategy="keep_most_complete")
merger = EntityMerger()
deduplicated_entities = merger.merge_duplicates(entities)
```
</Tab>
</Tabs>
@@ -390,21 +361,19 @@ Every fact in Semantica links back to:
- The **reasoning steps** that produced any inferred fact
<Note>
This is W3C PROV-O compliant lineage: suitable for regulated industries that require audit trails (HIPAA, SOX, GDPR, FDA 21 CFR Part 11). `ProvenanceManager.export_prov(format="turtle")` serialises the recorded lineage as PROV-O RDF.
This is W3C PROV-O compliant lineage: suitable for regulated industries that require audit trails (HIPAA, SOX, GDPR, FDA 21 CFR Part 11). Use `RDFExporter(include_provenance=True)` to embed provenance inline in any RDF export.
</Note>
```python
from semantica.provenance import ProvenanceManager
prov = ProvenanceManager()
prov.track_entity("apple_inc", source="report.pdf",
metadata={"extractor": "NamedEntityRecognizer", "confidence": 0.98})
prov = ProvenanceManager()
lineage = prov.get_entity_lineage("apple_inc")
record = prov.get_provenance("apple_inc") # dict; use get_lineage() for the full chain
print(record["source_document"])
print(record["timestamp"])
print(record["checksum"])
print(record["metadata"]) # extractor, confidence, and any custom keys
print(f"Source: {lineage.source_document}")
print(f"Method: {lineage.extraction_method}")
print(f"Extracted: {lineage.timestamp}")
print(f"Checksum: {lineage.checksum}")
```
@@ -487,27 +456,27 @@ Semantica is designed for extension. Any component: ingestor, extractor, graph b
**Extension points available:** ingestors, parsers, normalizers, extractors, reasoning engines, export formats, vector store backends, graph store backends, visualization renderers.
</Accordion>
<Accordion title="MethodRegistry: swap a built-in graph operation for your own">
<Accordion title="MethodRegistry: add domain-specific graph operations">
`method_registry` lets you register an alternative implementation for a
knowledge-graph task (`build`, `analyze`, `centrality`, `resolve`, …) under a
name, then select it wherever that task runs.
`MethodRegistry` lets you register custom methods on knowledge graph objects by name: useful for adding domain-specific graph operations without subclassing.
```python
from semantica.kg import method_registry
from semantica.kg.methods import calculate_centrality
from semantica.kg import MethodRegistry
def fast_centrality(graph, **kwargs):
"""Custom centrality implementation."""
registry = MethodRegistry()
def find_supply_chain_hops(graph, source_node, max_hops=3):
"""Custom BFS traversal for supply chain graphs."""
...
# register(task, name, func)
method_registry.register("centrality", "fast_centrality", fast_centrality)
# Register under a string key
registry.register("supply_chain_hops", find_supply_chain_hops)
# The task wrappers consult method_registry, so the name is now selectable:
scores = calculate_centrality(kg, method="fast_centrality")
# Call by name on any graph object
result = registry.call("supply_chain_hops", kg, source_node="Supplier_A", max_hops=5)
print(method_registry.list_all("centrality")) # {"centrality": ["fast_centrality", ...]}
# List all registered methods
print(registry.list_methods()) # ["supply_chain_hops", ...]
```
</Accordion>
+29 -30
View File
@@ -2,7 +2,7 @@
"$schema": "https://mintlify.com/docs.json",
"theme": "mint",
"name": "Semantica",
"description": "The Context and Semantic Layer for AI in High-Stakes Domains — Context Graphs · Decision Intelligence · Full Provenance",
"description": "The Accountability and Context Layer for AI — Context Graphs · Decision Intelligence · Full Provenance",
"colors": {
"primary": "#10B981",
"light": "#10B981",
@@ -43,7 +43,7 @@
"raiseIssue": true
},
"metadata": {
"og:title": "Semantica — Context & Semantic Layer for AI in High-Stakes Domains",
"og:title": "Semantica — Accountability & Context Layer for AI",
"og:description": "Build explainable, auditable knowledge graphs with full provenance. Open source. MIT licensed.",
"og:image": "/assets/img/semantica-logo.png",
"twitter:card": "summary_large_image",
@@ -121,23 +121,6 @@
"pages": [
"vector_stores/pgvector"
]
},
{
"group": "FAQ",
"pages": [
"faq"
]
},
{
"group": "Community",
"pages": [
"community",
"community-projects",
"contributing-guide",
"governance",
"citation",
"project-license"
]
}
]
},
@@ -184,17 +167,7 @@
"guides/policy-engine",
"guides/visualization",
"guides/distance-intelligence",
"guides/graph-analytics"
]
}
]
},
{
"tab": "API Reference",
"groups": [
{
"group": "Context & Intelligence",
"pages": [
"guides/graph-analytics",
"reference/context",
"reference/kg",
"reference/temporal",
@@ -263,6 +236,32 @@
]
}
]
},
{
"tab": "FAQ",
"groups": [
{
"group": "FAQ",
"pages": [
"faq"
]
},
{
"group": "Community",
"pages": [
"community",
"community-projects",
"contributing-guide",
"governance",
"citation",
"project-license"
]
}
]
},
{
"tab": "Changelog",
"href": "https://github.com/semantica-agi/semantica/releases"
}
]
},
+51 -41
View File
@@ -1,87 +1,97 @@
---
title: "Semantica"
description: "The Context and Semantic Layer for AI in High-Stakes Domains: Context Graphs · Decision Intelligence · Full Provenance"
description: "The Accountability and Context Layer for AI: Context Graphs · Decision Intelligence · Full Provenance"
---
```bash
pip install semantica
```
Most AI agents store embeddings, not meaning. They can't say why a fact was recalled, where it came from, or what led to a decision. In healthcare, finance, legal, and government, that lack of a traceable record blocks production deployment.
Your AI agent just made a decision. Now someone needs to explain it.
Semantica is the context and semantic layer for AI in high-stakes domains, sitting beneath your existing agent framework. It doesn't replace LangChain or LlamaIndex; it makes their outputs traceable.
*What did it know at the time? Which facts shaped the outcome? Where did those facts come from? Has it made the same call before: and did that go well?*
If your stack can't answer those questions with a traceable record, you have a gap. Not a capability gap: an **accountability gap**. It's the reason AI hasn't landed at scale in healthcare, finance, legal, and government. And it's why teams building for those markets keep rebuilding the same guardrails from scratch.
**Semantica closes that gap.** It's the context and accountability layer that sits beneath your existing agent framework: not a replacement for LangChain or LlamaIndex, but the infrastructure that makes their outputs trustworthy.
## What Most AI Stacks Are Missing
## The Problem Every Production AI Team Hits
**No memory structure.** Agents store embeddings, not meaning.
Powerful agents aren't automatically trustworthy ones. Five structural blind spots make modern AI systems impossible to deploy in regulated environments:
**No memory structure** — agents store embeddings, not meaning
- No way to ask *why* a fact was recalled
- No link from a recalled fact back to its source document
- Context is a black box that resets on every run
**No decision trail.** Agents act continuously but record nothing.
**No decision trail** — agents act continuously but record nothing
- No history to hand to a regulator or auditor
- No way to replay or reproduce a past decision
- Debugging means re-running, not reviewing
**No provenance.** Outputs can't be traced to source facts.
- A hard compliance blocker in healthcare, finance, and legal
**No provenance** — outputs can't be traced to source facts
- In healthcare, finance, and legal: this is a hard compliance blocker
- No lineage from inference back to the original document
- No way to demonstrate what the agent actually relied on
- Impossible to demonstrate what the agent actually relied on
**No reasoning transparency.** Black-box answers with no explanation.
- No way to validate the reasoning path
- No way to contest a specific conclusion
**No reasoning transparency** — black-box answers with no explanation
- Impossible to validate the reasoning path
- Impossible to contest a specific conclusion
- No basis for improving or correcting future behavior
**No conflict detection.** Contradictory facts silently coexist in vector stores.
**No conflict detection** — contradictory facts silently coexist in vector stores
- No detection when two sources disagree
- Outputs become inconsistent and unpredictable over time
- Silent failures compound as the knowledge base grows
<Note>
These aren't edge cases. They're why enterprise AI pilots stall: and why your compliance team keeps saying *not yet*.
</Note>
## What Semantica Adds to Your Stack
Semantica gives every agent the infrastructure it needs to be accountable, and it drops into an existing setup in minutes.
Semantica gives every agent the infrastructure it needs to be accountable. Drop it into your existing setup in minutes:
**Context Graphs.** A structured, queryable graph of everything your agent knows, decides, and reasons about.
- Persistent across agent runs, with no context loss between sessions
**Context Graphs** — a structured, queryable graph of everything your agent knows, decides, and reasons about
- Persistent across agent runs: no context loss between sessions
- Queryable with SPARQL and full graph algorithms
- Temporal model with `valid_from` / `valid_until` on nodes and edges
- Point-in-time snapshots of the full knowledge state
**Decision Intelligence.** Every decision is a first-class object in your system.
**Decision Intelligence** — every decision is a first-class object in your system
- `record_decision()` captures full lifecycle and causal chain
- Hybrid precedent search over past decisions for consistency
- `analyze_decision_impact()` shows downstream consequences
- Causal chain visualization from trigger to outcome
**Full Provenance.** Every fact links to its source document and ingestion event.
**Full Provenance** — every fact links to its source document and ingestion event
- W3C PROV-O compliant lineage across all modules
- Full traceability from raw input to final inference
- `recorded_at` stamping with OWL-Time export
- Audit-ready for HIPAA, SOX, GDPR, FDA 21 CFR Part 11
**Reasoning Engines.** Explainable reasoning paths, not black boxes.
**Reasoning Engines** — explainable reasoning paths, not black boxes
- Forward chaining, Rete, deductive, abductive
- SPARQL query-based inference over RDF graphs
- Datalog with recursive Horn clause rules
- Every conclusion backed by a traceable derivation path
**Temporal Intelligence.** Your graph knows not just *what*, but *when*.
- Allen interval algebra covering all 13 temporal relations
**Temporal Intelligence** — your graph knows not just *what*, but *when*
- Allen interval algebra: all 13 temporal relations
- Point-in-time queries over historical graph states
- Temporal provenance stamping on every fact
- OWL-Time export for standards-compliant archiving
**Ontology Hub.** Full ontology lifecycle in the browser.
**Ontology Hub** — full ontology lifecycle in the browser
- Visual editor for schema design and editing
- SHACL Studio for constraint authoring and validation
- Alignment authoring across multiple ontologies
- Health dashboard and version control built in
<Tip>
Works alongside any LLM provider and any agent framework. Add it to an existing stack without changing your architecture.
Works alongside any LLM provider and any agent framework: add it to an existing stack without changing your architecture.
</Tip>
<img src="/assets/img/diagrams/architecture-overview.svg" alt="Semantica four-layer architecture: Ingestion → Processing → Intelligence → Application" style={{ width: '100%', borderRadius: '12px', margin: '24px 0' }} />
@@ -175,17 +185,17 @@ decision_id = context.record_decision(
</CodeGroup>
- [Full Quickstart](/quickstart): step-by-step pipeline walkthrough
- [Cookbook](/cookbook): 40+ real-world Jupyter notebooks
- [Join Discord](https://discord.gg/sV34vps5hH): community chat and support
- [Full Quickstart](/quickstart) — Step-by-step pipeline walkthrough
- [Cookbook](/cookbook) 40+ real-world Jupyter notebooks
- [Join Discord](https://discord.gg/sV34vps5hH) — Community chat and support
## Industry Use Cases
## Built for Where Mistakes Have Consequences
Semantica is used in domains where every decision must be explainable and every fact must be traceable.
Semantica was designed for domains where every decision must be explainable and every fact must be traceable.
<Warning>
**This is system-level explainability, not foundation-model explainability.** Semantica does not expose, reconstruct, or explain what happens *inside* the LLM/foundation model. Its internal reasoning or chain-of-thought stays opaque, as it does for any external system. What Semantica explains is *outside* the model: the context and data fed in, the decision produced, its provenance, the relevant relationships, the policies applied, and the full execution trail. See [Core Concepts](/concepts) for the full scope note.
**This is system-level explainability, not foundation-model explainability.** Semantica does not expose, reconstruct, or explain what happens *inside* the LLM/foundation model — its internal reasoning or chain-of-thought stays opaque, as it does for any external system. What Semantica explains is *outside* the model: the context and data fed in, the decision produced, its provenance, the relevant relationships, the policies applied, and the full execution trail. See [Core Concepts](/concepts) for the full scope note.
</Warning>
**Healthcare & Life Sciences**
@@ -246,7 +256,7 @@ Semantica is used in domains where every decision must be explainable and every
- Knowledge graphs vs. vector stores: when to use each
- What GraphRAG is and how Semantica implements it
- How provenance and decision tracking work together
- The context and semantic layer architecture
- The accountability layer architecture
</Step>
<Step title="Go deep on any module">
Every module has a dedicated [reference page](/reference/context) with:
@@ -256,12 +266,12 @@ Semantica is used in domains where every decision must be explainable and every
</Step>
</Steps>
- [Installation](/installation): get Semantica installed in under a minute
- [Quickstart](/quickstart): build a complete knowledge graph pipeline in 5 minutes
- [Core Concepts](/concepts): the mental model behind the API
- [API Reference](/reference/context): exact module, class, and method details
- [Cookbook](/cookbook): domain notebooks for real-world use cases
- [Changelog](https://github.com/semantica-agi/semantica/releases): release history
- [Installation](/installation) — Get Semantica installed in under a minute
- [Quickstart](/quickstart) — Build a complete knowledge graph pipeline in 5 minutes
- [Core Concepts](/concepts) — The mental model behind the API
- [API Reference](/reference/context) — Exact module, class, and method details
- [Cookbook](/cookbook) — Domain notebooks for real-world use cases
- [Changelog](https://github.com/semantica-agi/semantica/releases) — Release history
## Full Capabilities
@@ -384,20 +394,20 @@ Semantica is used in domains where every decision must be explainable and every
## Why Semantica?
**Open Source, MIT.** No vendor lock-in, no paywalled features.
**Open Source, MIT** No vendor lock-in. No paywalled features.
- Full source available on GitHub
- Every line auditable by your security team
- Fork, extend, and self-host with no restrictions
- No telemetry, no usage reporting
**Production Ready.** Built for teams that can't afford surprises.
**Production Ready** Built for teams that can't afford surprises.
- 1,000+ passing tests with full regression coverage
- `PipelineValidator` catches configuration errors at startup
- `FailureHandler` with exponential backoff and dead-letter queues
- Ongoing security hardening, with fixes shipped in every release ([CHANGELOG](https://github.com/semantica-agi/semantica/blob/main/CHANGELOG.md))
- Ongoing security hardening: fixes shipped in every release ([CHANGELOG](https://github.com/semantica-agi/semantica/blob/main/CHANGELOG.md))
**Modular by Design.** Import only what you need.
**Modular by Design** Import only what you need.
- Use `NERExtractor` without a graph store
- Use `ContextGraph` without vector storage
- Every component independently swappable and testable
- No framework lock-in, and works with any agent stack
- No framework lock-in: works with any agent stack
-32
View File
@@ -416,38 +416,6 @@ class WeaviateStore:
)
raise ProcessingError(f"Failed to add objects: {str(e)}")
def delete_vectors(self, vector_ids: List[str], **options) -> Dict[str, Any]:
"""Delete vectors (objects) from the collection by their ids.
Args:
vector_ids: Object uuids to delete
**options: Additional options (ignored, kept for API parity)
Returns:
A dict with the number of successfully deleted objects
(``delete_count``).
"""
if self.collection is None or not WEAVIATE_AVAILABLE:
raise ProcessingError("Collection not initialized or Weaviate unavailable")
if not vector_ids:
return {"delete_count": 0}
deleted = 0
try:
data = self.collection.data
for vector_id in vector_ids:
if not vector_id:
continue
# delete_by_id returns False (not an error) for a uuid that is
# not present, and True when an object was deleted. Count only
# actual deletes so delete_count never over-reports.
if data.delete_by_id(vector_id):
deleted += 1
return {"delete_count": deleted}
except Exception as e:
raise ProcessingError(f"Failed to delete vectors: {str(e)}")
def get_vector(self, vector_id: str) -> Optional[np.ndarray]:
"""Get vector by ID."""
if self.collection is None or not WEAVIATE_AVAILABLE:
@@ -1,142 +0,0 @@
"""Tests for WeaviateStore.delete_vectors (#1374)."""
from unittest import TestCase
from unittest.mock import MagicMock, patch
from semantica.context.erasure import STATUS_ERASED, ErasureCoordinator
from semantica.utils.exceptions import ProcessingError
from semantica.vector_store import VectorStore
from semantica.vector_store.weaviate_store import WeaviateStore
class WeaviateStoreDeleteVectorsTest(TestCase):
def setUp(self):
self.patches = [
patch("semantica.vector_store.weaviate_store.WEAVIATE_AVAILABLE", True)
]
for p in self.patches:
p.start()
def tearDown(self):
for p in reversed(self.patches):
p.stop()
def _store(self, error=None):
"""Return (store, data) where data records delete_by_id calls."""
data = MagicMock()
data.delete_by_id = MagicMock()
coll = MagicMock()
coll.data = data
if error is not None:
data.delete_by_id.side_effect = error
store = WeaviateStore()
store.collection = coll
return store, data
def test_delete_single_id_calls_delete_by_id(self):
store, data = self._store()
ret = store.delete_vectors(["abc"])
data.delete_by_id.assert_called_once_with("abc")
self.assertEqual(ret, {"delete_count": 1})
def test_delete_many_ids_calls_each(self):
store, data = self._store()
ret = store.delete_vectors(["a", "b", "c"])
self.assertEqual(data.delete_by_id.call_count, 3)
self.assertEqual(ret, {"delete_count": 3})
def test_delete_skips_ids_that_report_missing(self):
store, data = self._store()
def _fake(uuid):
return uuid != "missing"
data.delete_by_id.side_effect = _fake
ret = store.delete_vectors(["present", "missing", "also-here"])
self.assertEqual(data.delete_by_id.call_count, 3)
self.assertEqual(ret, {"delete_count": 2})
def test_delete_drops_empty_ids(self):
store, data = self._store()
store.delete_vectors(["", "abc"])
data.delete_by_id.assert_called_once_with("abc")
self.assertEqual(data.delete_by_id.call_count, 1)
def test_delete_empty_ids_is_noop(self):
store, data = self._store()
ret = store.delete_vectors([])
self.assertEqual(ret, {"delete_count": 0})
data.delete_by_id.assert_not_called()
def test_delete_without_collection_raises(self):
store = WeaviateStore()
with self.assertRaises(ProcessingError):
store.delete_vectors(["a"])
def test_delete_backend_error_raises_processing_error(self):
store, _ = self._store(error=RuntimeError("connection reset"))
with self.assertRaises(ProcessingError):
store.delete_vectors(["a"])
class WeaviateErasureIntegrationTest(TestCase):
"""ErasureCoordinator reaches the real WeaviateStore.delete_vectors path."""
def setUp(self):
self._patch = patch(
"semantica.vector_store.weaviate_store.WEAVIATE_AVAILABLE", True
)
self._patch.start()
def tearDown(self):
self._patch.stop()
def _bind_weaviate_as_vector_store(self):
vs = VectorStore(backend="weaviate", config={"dimension": 3})
weaviate = WeaviateStore()
data = MagicMock()
coll = MagicMock()
coll.data = data
weaviate.collection = coll
vs._backend_store = weaviate
return vs, data
def test_erasure_reports_erased_when_delete_runs(self):
vs, data = self._bind_weaviate_as_vector_store()
coord = ErasureCoordinator(vector_store=vs)
receipt = coord.erase_entity("customer-4471")
data.delete_by_id.assert_called()
self.assertEqual(receipt.stores["vectors"]["status"], STATUS_ERASED)
def test_erasure_reports_erased_when_nothing_was_found(self):
"""delete_by_id returns False (404) for an id that is not in the store.
For erasure that still means the goal is met: nothing remains under
that id. The receipt keeps the honest zero count in backend_result
instead of raising a false failed status.
"""
vs, data = self._bind_weaviate_as_vector_store()
data.delete_by_id.return_value = False
coord = ErasureCoordinator(vector_store=vs)
receipt = coord.erase_entity("customer-4471")
self.assertEqual(receipt.stores["vectors"]["status"], STATUS_ERASED)
self.assertEqual(
receipt.stores["vectors"]["backend_result"], {"delete_count": 0}
)
def test_erasure_backend_name_is_weaviate(self):
vs, _ = self._bind_weaviate_as_vector_store()
coord = ErasureCoordinator(vector_store=vs)
receipt = coord.erase_entity("customer-4471")
self.assertEqual(receipt.stores["vectors"]["backend"], "weaviate")
def test_facade_delete_vectors_forwards_to_weaviate(self):
vs, data = self._bind_weaviate_as_vector_store()
def _fake(uuid):
return uuid != "missing"
data.delete_by_id.side_effect = _fake
ret = vs.delete_vectors(["present", "missing"])
self.assertEqual(data.delete_by_id.call_count, 2)
self.assertEqual(ret, {"delete_count": 1})