semantica

semantica-agiMIT活跃维护 有专家点评

面向 AI 智能体的图原生上下文基础设施,用上下文图谱管理记忆与决策依据,让 AI 系统的行为可追溯、可问责。

Graph-Native Infrastructure for Context and Accountable AI Systems

v0.7.0发布于 2026-09-22 11:18 UTC14,527star +57 / 7 天1,713fork同步于 2026-11-11 05:25 UTC

专家点评

上手难度:进阶更新于 2026-11-11

给 Agent 决策过程建可查询的因果图,替代只存向量片段的记忆层

适用场景

  • 需要回答「这个 Agent 为什么这么决策」的审计场景:决策被写成图节点,trace_decision_chain 能拉出完整因果链,纯向量库做不到这种回溯
  • 多轮 Agent 会话中要复用历史先例:find_similar_decisions 在图结构上做语义检索,比在扁平 embedding 里捞相似片段多一层实体关系约束
  • 业务实体有明确本体(OWL/SHACL/SKOS)的领域:把业务语义显式建模进图,而不是让 LLM 从文本里猜关系
  • 离线构建上下文层、在线只做查询:构图和推理不依赖 LLM,可以把模型调用从构建链路里摘掉,控制成本和不确定性

踩坑

  • 图存储后端要自己选型配置(Oxigraph、Neo4j 等),pip install 之后 doctor 能过不代表能跑通真实负载,选后端这一步没有默认答案
  • issue 里反复出现的是存储后端集成诉求(向量库、SQLite+sqlite-vec、Neptune),说明开箱的存储适配面不宽,接自有数据库大概率要自己写适配层
  • 需要 Python 3.11+,且本体建模(OWL/SHACL)本身有学习成本,团队里没人写过本体的话,schema 设计会先卡住

同类对比

如果只是要向量检索加简单元数据过滤,直接用 pgvector 或 Qdrant 更省事;需要成熟图数据库加 Cypher 生态就上 Neo4j 自己搭,Semantica 的价值在决策溯源这层抽象,不在存储本身

怎么上手

由 README 提炼,执行前请确认
pip install semantica
semantica doctor
硬件要求按 README 说明

README 未说明

下载:源码 zip·GitHub Releases(安装包)本站不镜像安装包

项目说明

由 README 自动翻译提炼

把企业数据建成带决策溯源的知识图谱,给 LLM 和 Agent 提供可解释的上下文层

面向 AI 智能体的图原生上下文基础设施,用上下文图谱管理记忆与决策依据,让 AI 系统的行为可追溯、可问责。

核心能力

  • 用 ContextGraph 把每次 Agent 决策记录成可查询的图节点
  • 支持 trace_decision_chain 回溯完整因果链与决策来源
  • 内置 find_similar_decisions 做历史先例语义检索
  • 用 OWL/SHACL/SKOS 本体把实体业务含义显式建模
  • 图构建与推理不依赖 LLM,可选接入多家厂商模型

容易踩的坑

需要 Python 3.11+;图存储后端(Oxigraph、Neo4j 等)需按需单独配置;LLM 为可选依赖,不装也能构图和推理

内容由模型根据 README 生成,可能不完整或不准确,以官方文档为准。看原文 README

最近发版

5 个版本v0.7.0
  1. v0.7.0最新正式版2026-09-22 · 2026-09-22 11:18 UTC

    Semantica v0.7.0

    Released: 2026-09-22 Tag: v0.7.0 · Compare: v0.6.8...v0.7.0 · PyPI: semantica 0.7.0

    Highlights

    Core install is now 4x lighter — direct dependencies dropped from 44 to 22 packages, with heavy ML/NLP, visualization, document-parsing, and ingestion libraries (torch, spacy, sentence-transformers, matplotlib, faiss-cpu, python-docx, and more) moved into granular optional extras; pip install "semantica[all]" keeps the previous fully-bundled behavior. This is also the first release requiring Python 3.10+ (3.8/3.9 dropped, 3.14 not yet supported), with a committed uv.lock for reproducible dev installs.

    Ships: Hierarchical Community GraphRAG (multi-level Louvain/Leiden community detection, LLM-summarized community reports, and global Map-Reduce + DRIFT hybrid search); six new data connectors — BigQuery, Amazon Redshift, Power BI, Apache Airflow, plus line-delimited JSON ingestion; schema-guided extraction (SchemaValidator + bootstrap_schema); source-aware truth maintenance with corroboration-based trust tiers for graph facts; a persistent SQLite backend for ExtractionCache; new MCP semantic retrieval tools (store_document/retrieve_context/update_document/remove_document); and SPARQLReasoner.execute_query running real queries instead of a no-op.

    Also fixes 40+ correctness bugs (in-memory vector-ID reuse corrupting live vectors, FAISS/Qdrant/Milvus vector-store gaps, Explorer temporal-scrubber and ontology-linking bugs, CLI commands calling nonexistent APIs, and more) and closes a Neptune credential-logging leak, a pip-audit CVE-alias matching gap, and unpatched chromadb/json-repair CVEs via removing the crewai extra — see CHANGELOG.md for the full breakdown.

    Breaking changes: Entity.confidence is now Optional[float] (was float = 1.0); PolicyEngine.check_compliance now raises ProcessingError instead of returning False for unevaluable rules; the dev extra is replaced by a PEP 735 dependency group (pip install -e . --group dev); semantica[crewai] no longer installs crewai automatically; Python 3.8/3.9 are no longer supported.

    What's Changed

    • #1473 · a5994497 · fix: correct production env var to SEMANTICA_API_KEY (fixes #1429) · @v01dst
    • #1455 · ce0ae1cb · refactor(context): expose public temporal normalizer · @Saket7002
    • #1381 · 754fe5fd · fix(context): deep-copy store results in ErasureReceipt.to_dict() · @BinarySpecter
    • #1465 · ebd659a9 · Closes #1351: [BUG] semantica ingest reports "✓ Ingested" but persists nothing to a configured Neo4j backend (silent no-op) · @evgenyponomarev
    • #1476 · a65874e4 · chore(release): prepare v0.6.8 · @KaifAhmad1
    • #1372 · 14d25cab · fix(cli): dispatch reason run and store connect to real APIs · @7487
    • #1441 · [
  2. v0.6.82026-09-05 · 2026-09-05 14:01 UTC
    查看更新说明

    Semantica v0.6.8

    Released: 2026-09-05 Tag: v0.6.8 · Compare: v0.6.7...v0.6.8 · PyPI: semantica 0.6.8

    Highlights

    Every release from here on is cryptographically signed — the build now runs SLSA build-provenance attestation plus Sigstore signing, and .sigstore.json bundles ship alongside the wheel/sdist on every GitHub Release, closing the OpenSSF Scorecard Signed-Releases gap. This is also the release that actually exercises that pipeline for the first time: it surfaced a latent bug where the Sigstore output broke PyPI publishing, now fixed by running publish before signing writes into dist/.

    Ships: real vector-store enumeration (scan_vectors()/iter_vectors()) across FAISS, SQLiteVec, PgVector, Qdrant, Weaviate, Pinecone, and Milvus, making semantica store migrate functional between backends for the first time; first-class Anthropic, Gemini, Ollama, DeepSeek, and Novita LLM provider wrappers in semantica.llms; a deterministic, CI-friendly ontology quality gate; first-class Google ADK integration; a Salesforce ingestor; ErasureCoordinator (completing the erasure workflow purge_node() only started, so a purged entity no longer survives verbatim in AgentMemory or as an embedding); and Explorer's read-only Markdown viewer becoming a full editor for live ContextGraph nodes and host-supplied AgentMemory items.

    Also fixes: 35 correctness bugs (Python 3.9 install breakage, FAISS save/load metadata loss, semantica ingest's silent no-op against a configured graph store, MCP persistence, Explorer graph rendering, ontology property-collision handling, and more) and closes 12 Dependabot aiohttp alerts, 5 HIGH-severity Trivy container findings, and 2 npm advisories — see CHANGELOG.md for the full breakdown.

    What's Changed

    • #1231 · 56d9e9a8 · fix(ontology): coalesce normalized property collisions · @T1mn
    • #1241 · 5376f046 · fix(explorer): dedupe temporal snapshot requests and apply latest-wins · @ALDRIN121
    • #1236 · da642f12 · fix(export): @vocab mints into the shipped ns# namespace · @pkupt
    • #1041 · d3183d0a · feat(explorer): add deterministic rendering E2E example and test (#1037) · @alexsmolya
    • #1240 · 4bf525d4 · feat(ingest): add production-ready Salesforce ingestor · @Sameer6305
    • #1024 · 85d6ccd0 · fix(memory): find_by_entity returns all matches by default · @yzxcj797
    • #1249 · e13c953b · ci: resync github/codeql-action pin to current v4 · @ZohaibHassan16
    • #1245 · 30592b12 · fix(split): validate sliding window progress · @HsienW
    • [#1232](ht
  3. v0.6.72026-08-28 · 2026-08-28 10:28 UTC
    查看更新说明

    Semantica v0.6.7

    Released: 2026-08-28 Tag: v0.6.7 · Compare: v0.6.6...v0.6.7 · PyPI: semantica 0.6.7

    Highlights

    Feature release, plus one SSRF hardening fix and a large batch of correctness fixes across the RDF/ontology export pipeline.

    Ships: first-class LangChain integration (semantica[langchain]), a SAP OData ingestor (semantica[ingest-sap]), ContextGraph Markdown round-trip persistence, a reasoning Action layer (rule-driven Assert/Retract/Call/EmitEvent with optional provenance), a public run_shacl_validation API, and a read-only Explorer Markdown content viewer.

    Also fixes: Agno/OpenClaw SSRF hardening, PipelineBuilder.set_parallelism() now actually parallelizes independent steps, flatten_dict() no longer drops data on a key collision, Config.get() honors boolean environment overrides, the MCP server's export_graph tool works again on every format, and a dozen ontology/RDF export correctness bugs (OWL property/class export, SHACL target namespace, one canonical confidence datatype, reachable OWL-Time reification, JSON-LD default-graph and content-derived document identity, full metadata passthrough — see CHANGELOG.md for the full breakdown).

    What's Changed

    • #1071 · 54c274e0 · test(ingest): track relationship provenance via ProvenanceManager · @dex0shubham
    • #897 · c5d382ee · test(visualization): isolate optional dependency mocks · @luantaraschi
    • #1045 · 4801ff34 · security(deps): bump anthropic from 0.121.0 to 0.122.0 · @dependabot
    • #1078 · 96f60e61 · feat(explorer): add markdown content preview and source view · @sakshi04-ui
    • #1115 · a3074ec4 · fix(kg): keep relationship endpoint aliases in sync · @T1mn
    • #1123 · e3405ebc · Read the ontology shape the generator actually emits, and stop minting empty class IRIs (#1103) · @fabio-rovai
    • #1124 · cbb0a6dd · Target the namespace the data uses, and stop attaching domain-less properties to every class (#1104, #1105) · @fabio-rovai
    • #1125 · 0dc26350 · Write confidence as one typed decimal on every serialization path (#1100, #1102) · @fabio-rovai
    • #1126 · a279e744 · Give the OWL-Time interval a subject the graph can reach (#1106) · @fabio-rovai
    • #1127 · 46451ae2 · Let a registe
  4. v0.6.62026-08-20 · 2026-08-20 08:11 UTC
    查看更新说明

    Semantica v0.6.6

    Released: 2026-08-20 Tag: v0.6.6 · Compare: v0.6.5...v0.6.6 · PyPI: semantica 0.6.6

    Highlights

    Security release — upgrading is strongly recommended. Fixes for a privately disclosed batch of vulnerabilities spanning backup/restore, database export, outbound requests, and triplet-store backends, plus SSRF hardening across ingestion (tarball path traversal, SQL injection, DNS-rebinding TOCTOU, stored XSS, SPARQL injection, credential leakage across redirects, and more — see CHANGELOG.md for the full breakdown).

    Also ships: first-class CrewAI integration, ContextGraph retraction and purge, a declared Semantica RDF vocabulary with deterministic entity/relationship IRIs, and timezone-aware timestamps across export/ and provenance/.

    What's Changed

    • #862 · 918830a8 · fix(pipeline): resolve broken import and missing run() in PipelineWithProvenance · @Karunasagar12
    • #857 · 229cb69c · Added custom _filter_by_metadata for each memory backend · @TaherTadpatri
    • #870 · 22bf5810 · fix(mcp): report package version · @oiahoon
    • #871 · 9ec79598 · Bump fastapi minimum version to fix PYSEC-2024-38 (starlette DoS) · @agu2347
    • #873 · bc63e962 · test(seed): use a real file for CSV loading · @nightcityblade
    • #929 · 687a1807 · fix(context): take the lock in ContextGraph.to_dict() · @pravit-amp
    • #912 · c1154b6e · fix(security): header injection, link-prediction DoS, import ID sanitization · @Sunil56224972
    • #878 · 1a3dd503 · docs(kg): document GraphBuilder public methods · @cakeni
    • #941 · 1ee3f2f2 · fix(kg): align GraphBuilder raw-text extraction defaults with the documented contract · @dex0shubham
    • #879 · b0080c36 · fix(export): log DistanceExporter metric computation failures instead of swallowing them · @AmirF194
    • #881 · 18f1d55d · test(normalize): make optional tests deterministic · @aoright
    • #882 · 0fa3483b · fix(context): clarify get_node_property not-f
  5. v0.6.52026-08-11 · 2026-08-11 17:19 UTC
    查看更新说明

    Release Date: August 11, 2026 Version: 0.6.5

    Semantica 0.6.5 is a security release closing 6 externally-reported vulnerabilities across the Explorer API and the graph/triplet store backends — including a Critical missing-authentication gap and a Critical Cypher-injection path — plus a CodeQL-flagged ReDoS. It also ships an embedded Oxigraph TripletStore backend, full PROV-O trust/spec completeness for ProvenanceManager, the Altair Anzo triplet store backend, and closes out 25+ correctness bugs across vector stores, provenance, ontology validation, and the Explorer frontend.

    Upgrading is strongly recommended for all deployments, especially anyone running the Explorer API.

    What's Changed

    Security

    • Missing authentication on all Explorer API routes (#909, GHSA-j4mq-hprp-987v, Critical) by @KaifAhmad1

      • Every route across all 11 API routers (graph, ontology, SPARQL, SHACL, provenance, temporal, analytics, import/export) was reachable with no credential — full read/write graph access and arbitrary SPARQL execution for anyone who could reach the port
      • New Depends(require_auth) validates X-API-Key against SEMANTICA_API_KEY; fails closed (503) when unset, rather than silently allowing anonymous access
      • SEMANTICA_ALLOW_ANONYMOUS=true remains available as an explicit opt-out for local/dev use
    • SSRF via redirect bypass in ontology URL fetching, plus DNS check-then-use hardening (#898, #916, GHSA-8c7v-62gr-hj6g, High) by @Sunil56224972 and @KaifAhmad1

      • A validated public first hop could redirect (302) to http://169.254.169.254/... (cloud instance metadata) or an internal service with no re-validation; redirects are now followed manually, capped at 5 hops, with every hop's target (including relative Location headers) re-validated
      • Follow-up (#916) closed a secondary DNS check-then-use (TOCTOU) window: the connection is now pinned directly to the validated IP via a custom requests adapter, with the real hostname still presented for the HTTP Host header and TLS SNI/certificate verification
      • Verified with real (non-mocked) local HTTP/HTTPS test servers, including a negative control confirming a hostname/cert mismatch is still rejected
    • Cypher injection via unvalidated node labels, relationship types, and property keys (#910, GHSA-482h-hw99-h62p, Critical) by @KaifAhmad1, review fix by @Sameer6305

      • Labels and property keys can't be parameterized like values; a document-derived entity type or property name could close the current Cypher token early and append arbitrary statements (e.g. DETACH DELETE) across the Neptune, Neo4j, and FalkorDB backends
      • New shared semantica/graph_store/query_sanitize.py validates every label/relationship-type/property-key interpolation site
    • SPARQL injection via unvalidated triplet IRIs (#911, #916, GHSA-8vgg-8mr4-r236, Critical) by @KaifAhmad1, review fix by @ZohaibHassan16

      • A subject/predicate/object containing > could close the <...> IRI token early and append arbitrary SPARQL (e.g. CLEAR ALL) across the Blazegraph, RDF4J, and Jena backends
      • Applied sparql_escaping.validate_uri() at every interpolation site; a follow-up (#916) closed a remaining gap where an already-<...>-wrapped object skipped validation
    • Missing Origin validation on the WebSocket handshake (#917, GHSA-4643-wpgq-w329, Moderate — anonymous-mode only) by @KaifAhmad1

      • CORSMiddleware doesn't cover WebSocket handshakes; under SEMANTICA_ALLOW_ANONYMOUS=true, /ws/graph-updates accepted a connection from any browser origin
      • Now checks Origin against the same allowlist CORSMiddleware already enforces for HTTP, before the key check
    • Polynomial-time ReDoS in the SPARQL route's _PREFIX_DECL regex (#915, CodeQL py/polynomial-redos) by @Sameer6305

      • Two overlapping quantifiers allowed O(n²) backtracking, reachable from req.query; fixed by making them character-disjoint, plus

用户点评

登录用户的真实使用记录,可按版本和硬件筛选
共 0 条

    还没有人点评。第一个说出真实体验的人最有价值。

    README 原文

    未翻译

    Graph-Native Infrastructure for Context and Accountable AI Systems

    Developer-first, knowledge infrastructure for AI, alternative to expensive enterprise platforms.

    Ingest your enterprise data, extract what matters, build a Context Graph and knowledge graph (KG), and run graph analytics and causal reasoning over all of it, with full decision provenance baked in. Explainable, traceable, and trustworthy by design.

    Context Management  ·  Knowledge Modeling  ·  Deterministic Reasoning  ·  Ontology Management  ·  Decision Intelligence  ·  End-to-End Traceability

    Open Source  ·  Governed  ·  Zero Vendor Lock-In

    Polyglot Graph Storage  ·  RDF & LPG Support  ·  W3C Standards  ·  Interoperable

    Built for High-Stakes, Regulated Domains

    GitHub Stars GitHub Forks Contributors PyPI Total Downloads Python 3.11+ License: MIT CI Install Matrix OpenSSF Scorecard Ask DeepWiki

    Website Docs Community X

    YouTube

    pip install semantica
    

    English · Deutsch · Français · Español · Italiano · Português · العربية · اردو · हिन्दी · 中文 · 日本語 · 한국어


    Knowledge Explorer · Context Graphs · Reasoning Engine · Decision Intelligence · Ontology Hub

    ▶ Watch the full platform walkthrough


    Most AI agents run on embeddings, not meaning: similarity scores with no structure, no relationships, and no way to explain why a result came back.

    Semantica is the semantic/context layer underneath your LLM, vector store, and agent framework: deterministic infrastructure (no LLM required for graph construction, reasoning, or provenance; where an LLM is used, it's optional and vendor-neutral, every major provider supported, OpenAI, Anthropic, Gemini, and more, via semantica.llms) that turns fragmented enterprise data into a structured, queryable Context Graph and knowledge graph that carries the business context, not just the data structure. Ontologies and controlled vocabularies (OWL, SHACL, SKOS) make what an entity means to your business, its definitions, relationships, and rules, as explicit as the data itself, not just its embedding.

    Decision provenance and audit trails aren't the product. They fall out of that structure for free, and in domains a regulator can question, the same structure that makes your agent smarter also gives you a straight answer to "why."

    [!NOTE] System-level explainability, not foundation-model explainability. Semantica doesn't expose or reconstruct what happens inside the LLM: its internal reasoning stays opaque, like it does for any external system. Semantica explains what's outside the model: the context fed in, the decision produced, its provenance, relevant relationships, applied policies, and the full execution trail.

    Who it's for:

    • AI/ML platform teams shipping agents that make consequential decisions and need structured, queryable context, not just a vector index
    • Enterprise data teams on Databricks, Snowflake, or SAP turning tables already in the lakehouse or warehouse into a governed, lineage-tracked knowledge graph, without exporting to a third-party SaaS
    • Compliance, risk, and audit teams who need a straight answer to "why did the AI do that?" in a format a regulator accepts
    • Regulated enterprises (finance, healthcare, legal, government, defense) that can't ship a black box or hand their data to someone else's SaaS to get one
    • Platform and infra engineers who want the KG, reasoning, and provenance stack self-hosted and swappable, not locked to one vendor's backend
    • Data and knowledge engineers building a KG from messy, multi-source data, where conflicting facts get flagged and duplicates get merged, not silently overwritten

    Quick Start  ·  Architecture  ·  What You Get  ·  Why Semantica  ·  Decision Intelligence  ·  Context Graphs  ·  Recipe: Audit Trail  ·  Module Reference  ·  Integrations  ·  CLI  ·  Performance  ·  Install


    What Semantica Gives You

    • Context Graphs: A structured, queryable graph of everything your agent knows, decides, and reasons about
    • Decision Intelligence: Every decision is a first-class object: traceable, searchable by precedent, and causally linked
    • AI Governance & Ontology: SHACL constraints, conflict detection, compliance rules, OWL generation, and SKOS vocabularies, all with a visual editor
    • Full Auditability: W3C PROV-O provenance on every fact, exportable to JSON, CSV, or RDF
    • Deterministic Reasoning: Forward chaining, Rete network, Datalog, and SPARQL, with fully explainable paths, not black boxes
    • Knowledge Pipeline: Multi-source ingestion, entity-aware chunking, NER/relation/event extraction, and graph construction, with semantic dedup and provenance-preserving merges built in
    • Enterprise Data Platforms: Native connectors for Databricks (Unity Catalog + Delta Lake), Snowflake, and SAP OData, so data already in your lakehouse or warehouse becomes graph nodes with provenance, no export/import hop
    • Graph Analytics: Centrality, community detection, link prediction, and shortest-path queries over the graph you just built
    • Polyglot Graph Storage: RDF (Oxigraph, Blazegraph, Jena, RDF4J) and Labeled Property Graphs (Neo4j, FalkorDB, AGE, Neptune), plus vector stores, all swappable without touching your code
    • Visualization: Explore any graph, ontology, or timeline in an interactive browser workbench
    • Drop-in Integrations: Agno, CrewAI, and LangChain support, a full MCP server, a CLI, a REST API, and plugins across major editors

    Why Semantica

    Vector DB + RAGPlain LLM MemorySemantica
    Recall methodEmbedding similarityToken windowGraph traversal + semantic search
    Decision historyNot storedNot storedFirst-class queryable objects
    ProvenanceNoneNoneW3C PROV-O, source-linked
    ReasoningNoneBlack boxForward chain, Rete, Datalog, SPARQL
    Conflict detectionSilent overwriteSilent overwriteDetected, flagged, resolved
    Time travelNoNoPoint-in-time graph snapshots
    Compliance exportNoneNonePROV-O, SHACL, OWL, RDF
    Policy enforcementNoneNoneBuilt-in rule engine + SHACL
    Entity resolutionNoNoBlocking + semantic deduplication
    Multi-agent contextSeparate per agentSeparate per agentSingle shared intelligence layer

    Semantica complements your existing stack rather than replacing it. Keep your LLM, vector store, and agent framework exactly as they are; Semantica adds the decision records, causal reasoning, provenance, ontology governance, conflict detection, and audit trails on top. The reasoning engines, KG construction, and provenance layer are fully deterministic; no LLM is required to use them.


    Quick Start

    pip install semantica
    
    from semantica.context import ContextGraph
    
    graph = ContextGraph(advanced_analytics=True)
    
    # Every agent decision becomes a queryable, auditable knowledge node
    decision_id = graph.record_decision(
        category="vendor_selection",
        scenario="Choose cloud provider for HIPAA workload",
        reasoning="AWS offers BAA, mature HIPAA tooling, and existing team expertise",
        outcome="selected_aws",
        confidence=0.93,
    )
    
    # Ask "why did this happen?" and get a real, structured answer
    chain     = graph.trace_decision_chain(decision_id)       # full causal ancestry
    similar   = graph.find_similar_decisions("cloud vendor", max_results=5)  # precedents
    impact    = graph.analyze_decision_impact(decision_id)    # downstream influence map
    
    # Policy gate: checks the fields you pass against the default rules
    # (confidence >= 0.7, outcome in approved/rejected/flagged, decision_maker set)
    compliant = graph.check_decision_rules({
        "category": "vendor_selection",
        "outcome": "approved",
        "confidence": 0.93,
        "decision_maker": "platform-team",
    })  # {'compliant': True, 'violations': [], ...}
    

    Verify your install in 5 seconds:

    semantica doctor
    

    Running in a script or CI? Progress bars are written only when stdout is an interactive terminal (or a Jupyter notebook), so piping and redirecting stay clean by default. Override with SEMANTICA_DISABLE_PROGRESS=1 to silence progress everywhere, or SEMANTICA_FORCE_PROGRESS=1 to keep it when stdout is redirected. SEMANTICA_DISABLE_PROGRESS takes precedence.

    If Semantica solves a real problem for you, a star helps others find it.

    ⭐ Star on GitHub  ·  Join Discord


    Architecture

    Semantica is a real end-to-end pipeline, not a single library with a marketing name. Every stage below is a shipping module, independently importable:

    Sources → Ingest → Parse → Normalize → Split → Extract → Conflict Detection → Deduplication
       → Knowledge Graph → [ Ontology · Reasoning · Provenance · Decisions ] → Enriched KG
       → Vector Store + Polyglot Graph Store (RDF & LPG) → Export / Visualize / REST · MCP · CLI
    
    • Ingest: files, web, databases, enterprise data platforms (Databricks, Snowflake, SAP), cloud (Google Drive, Elasticsearch), streams (Kafka, Kinesis), Git, email, MCP
    • Parse → Normalize → Split: document parsing, text/entity/date normalization, GraphRAG-native entity-aware chunking
    • Extract → Conflict Detection → Deduplication: NER, relations, events, triplets; conflicting facts flagged and resolved before they merge
    • Knowledge Graph: GraphBuilder constructs the graph; bi-temporal facts and full graph analytics (centrality, communities, link prediction) run on top of it
    • Ontology · Reasoning · Provenance · Decisions: the intelligence layer sitting on the KG, with SHACL/OWL governance, Rete/Datalog/SPARQL inference, W3C PROV-O lineage, and first-class decision records
    • Storage: polyglot by design, with RDF triple stores (embedded Oxigraph, Blazegraph, Apache Jena, Eclipse RDF4J), Labeled Property Graphs (Neo4j, FalkorDB, Apache AGE, AWS Neptune), and vector stores, all swappable without touching your code
    • Outputs: export (RDF, OWL, Parquet, Cypher, JSON-LD), interactive visualization, and access via REST API, MCP server, or CLI

    → Full Mermaid diagrams for the pipeline and the decision intelligence lifecycle


    Decision Intelligence

    Decision Intelligence turns every AI choice from an ephemeral inference into a permanent, auditable, queryable record. It answers "what did your AI decide, why, and what happened next?": the question regulators and enterprise risk teams ask with increasing urgency.

    In Semantica, a decision is not a log line. It is a first-class graph node with a full lifecycle. In regulated domains, every AI decision must be traceable to a source and defensible to an auditor: record_decision() creates a permanent, structured record exportable as W3C PROV-O, the format most compliance frameworks accept for regulator submission.

    record_decision()             → stored as a graph node with full structured context
    add_causal_relationship()     → linked to upstream causes and downstream effects
    find_similar_decisions()      → semantic precedent search across all past decisions
    trace_decision_chain()        → full causal ancestry back to root causes
    analyze_decision_impact()     → downstream influence map - everything this decision affected
    check_decision_rules()        → policy compliance gate against configurable rule sets
    export / audit trail          → W3C PROV-O, CSV, or JSON for regulator submission
    
    from semantica.context import ContextGraph
    
    graph = ContextGraph(advanced_analytics=True)
    
    # Record decisions with full structured context
    app_id = graph.record_decision(
        category="credit_application",
        scenario="Personal loan, $85k income, 31% DTI, 3yr employment",
        reasoning="Income meets threshold; employment stable; no adverse credit events",
        outcome="proceed_to_underwriting",
        confidence=0.88,
        metadata={"applicant_id": "A-7291"},
    )
    uw_id = graph.record_decision(
        category="loan_underwriting",
        scenario="Underwriting review for A-7291",
        reasoning="DTI within policy; clean 36-month credit history",
        outcome="approved",
        confidence=0.94,
    )
    rate_id = graph.record_decision(
        category="interest_rate",
        scenario="Rate assignment for approved loan A-7291",
        outcome="rate_set_8.9pct",
        reasoning="Prime + 2.4% based on risk tier B2",
        confidence=0.99,
    )
    
    # Build the auditable causal chain - relationship_type must be one of
    # CAUSED, INFLUENCED, or PRECEDENT_FOR
    graph.add_causal_relationship(app_id, uw_id,   relationship_type="CAUSED")
    graph.add_causal_relationship(uw_id,  rate_id, relationship_type="INFLUENCED")
    
    # Query the intelligence
    chain     = graph.trace_decision_chain(rate_id)
    similar   = graph.find_similar_decisions("personal loan approval, 31% DTI", max_results=5)
    impact    = graph.analyze_decision_impact(uw_id)
    compliant = graph.check_decision_rules({
        "category": "loan_underwriting",
        "outcome": "approved",
        "confidence": 0.94,
        "decision_maker": "underwriting_agent",
    })
    insights  = graph.get_decision_insights()
    

    Context Graphs

    A Context Graph is the structured memory layer that traditional RAG is missing. Instead of flat embeddings that answer "what is similar?", a Context Graph answers "what is connected, why, and how?" Every entity, relationship, decision, and fact is a first-class node, queryable by graph traversal. Entities link to source documents, decisions link to evidence and consequences, facts carry full provenance, and conflicts are detected, not silently overwritten.

    from semantica.context import ContextGraph, AgentContext
    from semantica.vector_store import VectorStore
    
    graph = ContextGraph(advanced_analytics=True)
    
    # Add nodes with typed properties
    graph.add_node("acme_corp",    "Organization", name="Acme Corp", industry="SaaS")
    graph.add_node("alice_chen",   "Person",       name="Alice Chen", role="CTO")
    graph.add_node("contract_001", "Contract",     value=2_400_000, currency="USD")
    
    # Add typed, weighted edges (extra kwargs become edge metadata)
    graph.add_edge("alice_chen", "acme_corp",    edge_type="works_for",  since="2019-03-01")
    graph.add_edge("acme_corp",  "contract_001", edge_type="party_to",   signed="2024-01-15")
    
    # BFS traversal - hop through the graph from any node
    neighbors = graph.get_neighbors("acme_corp", hops=2)
    
    # Point-in-time snapshot - the graph as it existed on any past date
    snapshot  = graph.state_at("2024-01-01")
    
    # AgentContext - high-level API for agent memory workflows
    vs  = VectorStore(backend="faiss")
    ctx = AgentContext(vector_store=vs, knowledge_graph=graph)
    ctx.store("Alice approved the Acme renewal in Q1 2024", conversation_id="conv_001")
    retrieved = ctx.retrieve("who approved the Acme contract?")
    

    Why graph over embeddings: traversal finds connections embeddings miss (a person 3 hops from a contract); every node carries provenance so you can always ask "where did this come from?"; conflicts are flagged before they corrupt your knowledge base; point-in-time snapshots let you replay history without reprocessing.


    Recipe: Audit Trail for a Regulated Decision

    One pattern built on the same Context Graph: record a causally-linked decision chain, attach provenance to every entity, and export a regulator-ready audit trail.

    from semantica.context import ContextGraph
    from semantica.provenance import ProvenanceManager
    from semantica.export import RDFExporter
    
    graph = ContextGraph(advanced_analytics=True)
    prov  = ProvenanceManager(storage_path="./audit.db")
    
    # Record the decision chain
    d1 = graph.record_decision(
        category="drug_interaction_check", scenario="Patient P-4821: warfarin + amiodarone co-prescribed",
        reasoning="Amiodarone potentiates warfarin's anticoagulant effect", outcome="flag_for_review", confidence=0.91,
    )
    d2 = graph.record_decision(
        category="dosage_adjustment", scenario="INR monitoring plan for P-4821",
        reasoning="Reduce warfarin dose per interaction severity; recheck INR in 5 days", outcome="dose_reduced_30pct", confidence=0.87,
    )
    # relationship_type must be one of CAUSED, INFLUENCED, or PRECEDENT_FOR
    graph.add_causal_relationship(d1, d2, relationship_type="CAUSED")
    
    # Track provenance for every entity
    prov.track_entity("patient_P4821", source="ehr/medication_orders_2024.json",
                      metadata={"extractor": "NamedEntityRecognizer"})
    
    # Export W3C PROV-O for regulator submission - to_kg_dict() is the official
    # adapter that emits the {"entities": [...], "relationships": [...]} /
    # source_id shape RDFExporter expects, so no manual field mapping is needed
    kg = graph.to_kg_dict()
    RDFExporter().export(kg, "audit_trail.ttl", format="turtle")
    

    More recipes (GraphRAG pipelines, an AML rules engine, ontology-to-KG in one pass) are in More Recipes below.


    Explore the Platform

    Every module below is independently importable, with working code samples verified against the current source tree; use one or all of them.

    ModuleWhat it does
    semantica.ingestFiles, web, databases, APIs, streams, email, Git, Parquet, Databricks, Snowflake, SAP, MCP
    semantica.semantic_extractNER, relation extraction, event detection, triplet generation
    semantica.kgGraph construction, centrality, communities, link prediction
    semantica.reasoningForward chaining, Rete, Datalog, SPARQL, fully explainable
    semantica.vector_storeFAISS, Qdrant, Weaviate, Milvus, Pinecone, PgVector, hybrid search
    semantica.splitEntity-aware, relation-aware, ontology-aware chunking for GraphRAG
    semantica.provenanceW3C PROV-O lineage on every fact
    semantica.ontologyOWL generation, SHACL validation, SKOS vocabularies
    semantica.conflictsDetect and resolve conflicting facts across sources
    semantica.deduplicationEntity resolution at scale
    semantica.normalizeText, entity, date, and number normalization; dataset cleaning
    semantica.pipelineDeclarative, parallel pipeline DSL for ingest → extract → build → export
    semantica.exportRDF, OWL, Parquet, Cypher, JSON-LD
    semantica.visualizationForce-directed graphs, ontology hierarchies, temporal dashboards
    Temporal IntelligenceBi-temporal facts, Allen interval algebra, time travel
    Multi-Agent (Agno)One shared context graph across every agent on a team

    ↓ Expand Module Reference below for every module's working example, or jump to More Recipes, the full Integrations matrix, MCP tool list, and REST endpoints.


    Module Reference

    Expand any module below for its runnable example.

    Ingest from files, web, databases, APIs, streams, email, Git repos, Parquet, Databricks, Snowflake, SAP, or MCP servers, all through a unified interface.

    # WebIngestor needs the documents extra: pip install "semantica[documents]"
    from semantica.ingest import FileIngestor, WebIngestor, ParquetIngestor, DBIngestor
    
    # Ingest an entire directory of contracts (PDF, DOCX, HTML, TXT)
    docs = FileIngestor().ingest_directory("./contracts/", recursive=True)
    
    # Ingest live web content with robots.txt compliance
    pages = WebIngestor().ingest_url("https://example.com/reports/annual-2024.html")
    
    # Ingest structured data from Parquet with Snappy compression
    records = ParquetIngestor().ingest("./data/transactions.parquet")
    
    # Ingest from a SQL database - specify which tables to pull
    rows = DBIngestor().ingest_database(
        connection_string="postgresql://user:pass@localhost/mydb",
        include_tables=["customer_events"],
        max_rows_per_table=50_000,
    )
    
    # Enterprise data platforms - pull tables straight out of your lakehouse
    # or warehouse, with lineage, instead of exporting to CSV first
    from semantica.ingest import DatabricksIngestor, SnowflakeIngestor
    
    # pip install "semantica[db-databricks]"
    databricks = DatabricksIngestor(
        host="https://adb-xxx.azuredatabricks.net",
        token="dapi-xxxxxxxx",              # or client_id/client_secret for OAuth M2M
        http_path="/sql/1.0/warehouses/xxxxxxxx",
        catalog="main",
    )
    customers    = databricks.ingest_table("customers", limit=10_000)
    sales        = databricks.ingest_query("SELECT * FROM sales WHERE region = 'EMEA'")
    table_lineage = databricks.get_table_lineage("customers", catalog="main", schema="default")  # Unity Catalog lineage
    
    # pip install semantica[db-snowflake]
    snowflake = SnowflakeIngestor(
        account="myaccount",
        user="myuser",
        password="mypassword",              # or private_key=... for key-pair; use authenticator="oauth", token=... for OAuth
        warehouse="COMPUTE_WH",
        database="MYDB",
    )
    orders = snowflake.ingest_table("ORDERS", limit=10_000)
    

    Security Note: Never hardcode credentials (token, password, private_key) in production code; pass them via environment variables (e.g., DATABRICKS_TOKEN, SNOWFLAKE_PASSWORD) or a secrets manager.

    Supported sources: Local files (PDF, DOCX, PPTX, HTML, TXT, CSV, JSON, YAML, Excel, XML) · Web pages · RSS/Atom feeds · REST APIs · Databases (PostgreSQL, MySQL, SQLite, Oracle, SQL Server) · Parquet datasets · Databricks (Unity Catalog + Delta Lake) · Snowflake · SAP (OData v2/v4) · Git repositories · Email (IMAP/POP3) · Message streams (Kafka, RabbitMQ, Kinesis, Pulsar) · MCP resources · Apache Arrow/Feather/IPC (ArrowIngestor)

    DuckDB, Elasticsearch, Google Drive, HuggingFace, MongoDB, and Pandas ingestion also ship (DuckDBIngestor, ElasticIngestor, GDriveIngestor, HuggingFaceIngestor, MongoIngestor, PandasIngestor) but aren't re-exported from the top-level semantica.ingest namespace yet — import them directly: from semantica.ingest.duckdb_ingestor import DuckDBIngestor.

    Extract structured knowledge from raw text in one pass.

    from semantica.semantic_extract import (
        NamedEntityRecognizer,
        RelationExtractor,
        EventDetector,
        TripletExtractor,
    )
    
    text = """
    Anthropic CEO Dario Amodei announced a $7.3B Series E funding round in partnership
    with Google and Spark Capital, valuing the company at $61.5B as of Q4 2024.
    """
    
    # Named entity recognition with confidence thresholding
    ner = NamedEntityRecognizer(confidence_threshold=0.7)
    entities = ner.extract_entities(text)
    # → [Entity(name="Dario Amodei", type="PERSON"), Entity(name="Anthropic", type="ORG"),
    #    Entity(name="Google", type="ORG"), Entity(name="$7.3B", type="MONEY"), ...]
    
    # Relationship extraction - bidirectional support
    rel_extractor = RelationExtractor(confidence_threshold=0.6, bidirectional=True)
    relations = rel_extractor.extract_relations(text, entities=entities)
    # → [Relation(subject="Dario Amodei", predicate="ceo_of", object="Anthropic"),
    #    Relation(subject="Anthropic", predicate="raised", object="$7.3B Series E"), ...]
    
    # Event detection with temporal processing
    events = EventDetector(extract_participants=True, extract_time=True).detect_events(text)
    # → [Event(type="FUNDING", participants=["Anthropic","Google","Spark Capital"],
    #          amount="$7.3B", date="Q4 2024")]
    
    # RDF triplets with optional provenance metadata
    triplets = TripletExtractor(include_temporal=True, include_provenance=True).extract_triplets(text)
    # → [("Anthropic", "valuation", "$61.5B"), ("Dario Amodei", "is_ceo_of", "Anthropic"), ...]
    

    Batch processing across many documents uses ner.process_batch([...]), not a per-call extract_entities_batch on the facade class.

    Build a production knowledge graph from documents and run graph algorithms over it.

    from semantica.ingest import FileIngestor
    from semantica.kg import (
        GraphBuilder,
        GraphAnalyzer,
        CentralityCalculator,
        CommunityDetector,
        PathFinder,
        LinkPredictor,
        BiTemporalFact,
    )
    from datetime import datetime
    
    # Build KG - merge duplicate entities, track temporal edges
    sources = FileIngestor().ingest_directory("./contracts/", recursive=True)
    kg = GraphBuilder(merge_entities=True, enable_temporal=True).build(sources)
    
    # Graph analytics
    analyzer    = GraphAnalyzer()
    analysis    = analyzer.analyze_graph(kg)             # full graph metrics
    
    centrality  = CentralityCalculator()
    degree      = centrality.calculate_degree_centrality(kg)    # most-connected entities
    betweenness = centrality.calculate_betweenness_centrality(kg)
    
    communities = CommunityDetector().detect_communities(kg, method="louvain")  # natural clusters
    path        = PathFinder().find_shortest_path(kg, "alice_chen", "contract_001")
    predictions = LinkPredictor().predict_links(kg, top_k=10)   # relationship predictions
    
    # Bi-temporal facts - track valid time vs. recorded time independently
    fact = BiTemporalFact(
        valid_from=datetime(2024, 3, 1),
        valid_until=datetime(2025, 1, 1),
        recorded_at=datetime(2024, 3, 5),
    )
    

    Run explainable rule-based inference, not a black box.

    from semantica.reasoning import ReteEngine, Rule, Fact, RuleType
    
    rete = ReteEngine()
    rete.build_network([
        Rule(
            rule_id="aml_flag",
            name="Flag high-risk transactions",
            conditions=[
                {"field": "amount",  "operator": ">",  "value": 10_000},
                {"field": "country", "operator": "in", "value": ["IR", "KP", "SY"]},
            ],
            conclusion="flag_for_compliance_review",
            rule_type=RuleType.IMPLICATION,
        ),
        Rule(
            rule_id="velocity_check",
            name="Flag rapid sequential transfers",
            conditions=[
                {"field": "transfers_in_1h", "operator": ">", "value": 5},
                {"field": "total_amount",    "operator": ">", "value": 50_000},
            ],
            conclusion="flag_velocity_breach",
            rule_type=RuleType.IMPLICATION,
        ),
    ])
    
    rete.add_fact(Fact("tx_001", "transaction", [{"amount": 15_000, "country": "IR"}]))
    flagged = rete.match_patterns()
    # → [{"rule": "aml_flag", "matched_facts": ["tx_001"], "conclusion": "flag_for_compliance_review"}]
    

    Current limitation: ReteEngine's alpha-node condition matcher is intentionally simple in this release — validate match_patterns() output against your actual rule set before wiring it into a production compliance gate; more selective condition evaluation is on the roadmap.

    # Recursive Datalog - natural language for graph queries
    from semantica.reasoning import DatalogReasoner
    
    engine = DatalogReasoner()
    engine.add_fact("parent(tom, bob)")
    engine.add_fact("parent(bob, ann)")
    engine.add_fact("parent(ann, pat)")
    engine.add_rule("ancestor(X, Y) :- parent(X, Y).")
    engine.add_rule("ancestor(X, Z) :- parent(X, Y), ancestor(Y, Z).")
    ancestors = engine.query("ancestor(tom, ?X)")
    # → [{"X": "bob"}, {"X": "ann"}, {"X": "pat"}]
    
    # Explainable reasoning - trace the path, not just the answer
    from semantica.reasoning import ExplanationGenerator, Reasoner
    
    reasoner = Reasoner()
    reasoner.add_fact("parent(tom, bob)")
    reasoner.add_rule("ancestor(X, Y) :- parent(X, Y)")
    result = reasoner.forward_chain()
    
    explainer = ExplanationGenerator()
    explanation = explainer.generate_explanation(result)
    # → Explanation(conclusion="...", steps=[ReasoningStep(...)], justification=Justification(...))
    

    Drop-in vector store with multiple backends, hybrid search, and decision-aware retrieval.

    from semantica.vector_store import VectorStore, HybridSearch
    
    # In-memory backend shown here: HybridSearch and explain_decision() work out of the box.
    # Swap backend="qdrant" / "weaviate" / "milvus" / "pinecone" / "pgvector" / "faiss" once you
    # scale past a single process — search() and store_decision() work identically on all of them.
    vs = VectorStore(backend="inmemory", dimension=1536)
    
    # Store a decision with scenario description and outcome
    vs.store_decision(
        scenario="Personal loan A-7291, $85k income, 31% DTI, 3yr employment",
        outcome="approved",
        confidence=0.94,
        category="loan_underwriting",
    )
    
    # Semantic similarity search
    results = vs.search(
        query="personal loan approval with low DTI",
        limit=10,
    )
    
    # Hybrid search - dense + sparse retrieval in one pass with RRF fusion
    hs   = HybridSearch(vector_store=vs)
    hits = hs.search("high-risk transactions 2024")
    
    # Explain why a decision was retrieved
    explanation = vs.explain_decision(results[0]["id"])
    

    Backends: faiss · qdrant · weaviate · milvus · pinecone · pgvector · sqlite · inmemory

    KG-aware splitting that preserves entity boundaries, relation triplets, and ontology concepts, essential for GraphRAG pipelines.

    from semantica.split import TextSplitter, EntityAwareChunker, RelationAwareChunker
    
    text = open("contracts/master_agreement.txt").read()
    
    # Standard recursive chunking
    chunks = TextSplitter(method="recursive", chunk_size=1000, chunk_overlap=200).split(text)
    
    # Entity-aware chunking - never splits a named entity across chunks (GraphRAG)
    chunks = TextSplitter(method="entity_aware", ner_method="llm", chunk_size=1000).split(text)
    
    # Relation-aware chunking - preserves (subject, predicate, object) triplets intact
    chunks = RelationAwareChunker(chunk_size=1000, preserve_triplets=True).chunk(text)
    
    # Graph-based chunking - uses centrality to find natural community boundaries
    chunks = TextSplitter(method="graph_based", chunk_size=1000).split(text)
    
    # Hierarchical chunking - multi-level (section → paragraph → sentence)
    chunks = TextSplitter(method="hierarchical", levels=["section", "paragraph"]).split(text)
    

    Supported methods: recursive · token · sentence · paragraph · semantic_transformer · entity_aware · relation_aware · graph_based · ontology_aware · hierarchical · community_detection · centrality_based · llm

    Every fact is linked to its source. No black boxes, no mystery outputs.

    from semantica.provenance import ProvenanceManager
    
    prov = ProvenanceManager(storage_path="./provenance.db")
    
    # Track where every entity came from
    prov.track_entity(
        entity_id="acme_corp",
        source="contracts/acme_master_agreement_2024.pdf",
        metadata={"page": 1, "confidence": 0.97, "extractor": "NamedEntityRecognizer"},
    )
    
    # Track a relationship's provenance - entity linkage travels in metadata
    prov.track_relationship(
        relationship_id="alice_works_for_acme",
        source="hr_records/employees_q1_2024.csv",
        metadata={"source_entity_id": "alice_chen", "target_entity_id": "acme_corp"},
    )
    
    # Answer "where did this come from?"
    lineage = prov.get_lineage("acme_corp")
    trail   = prov.trace_lineage("alice_chen")   # full ancestor chain
    entry   = prov.get_provenance("acme_corp")
    

    Generate ontologies from data, validate shapes, and manage your vocabulary.

    from semantica.ontology import OntologyGenerator, OntologyValidator
    
    data = {
        "entities": [
            {"id": "acme_corp",  "type": "Organization", "industry": "SaaS", "founded": 2012},
            {"id": "alice_chen", "type": "Person",        "role": "CTO",     "since": 2019},
        ],
        "relationships": [
            {"source": "alice_chen", "target": "acme_corp", "type": "works_for"},
        ],
    }
    
    gen       = OntologyGenerator(base_uri="https://semantica.dev/ontology/")
    ontology  = gen.generate_ontology(data)
    classes   = gen.infer_classes(data)
    props     = gen.infer_properties(data, classes)
    optimized = gen.optimize_ontology(ontology)
    
    # Validate against SHACL shapes
    validator = OntologyValidator()
    report    = validator.validate(ontology)
    # → ValidationResult(valid=True, consistent=True, satisfiable=True, errors=[], warnings=[])
    

    Detect and resolve conflicting facts from multiple sources before they corrupt your knowledge base.

    from semantica.conflicts import ConflictDetector, ConflictResolver, SourceTracker
    
    entities_from_source_a = [
        {"id": "alice_chen", "role": "CTO",   "salary": 250_000, "start_date": "2019-03-01"},
    ]
    entities_from_source_b = [
        {"id": "alice_chen", "role": "VP Eng", "salary": 275_000, "start_date": "2019-03-01"},
    ]
    
    # Detect all conflict types: value, type, relationship, temporal, logical
    detector   = ConflictDetector()
    conflicts  = detector.detect_conflicts(entities_from_source_a + entities_from_source_b)
    # → [Conflict(entity="alice_chen", field="role",   values=["CTO","VP Eng"], severity="HIGH"),
    #    Conflict(entity="alice_chen", field="salary",  values=[250000,275000],   severity="MEDIUM")]
    
    # Resolve using multiple strategies
    resolver = ConflictResolver()
    resolved = resolver.resolve_conflicts(conflicts, strategy="credibility_weighted")  # weighted by source trust
    resolved = resolver.resolve_conflicts(conflicts, strategy="most_recent")          # prefer most recent
    resolved = resolver.resolve_conflicts(conflicts, strategy="voting")               # majority wins
    
    # Track source credibility over time
    tracker = SourceTracker()
    tracker.register_source("source_a", source_type="document", credibility_score=0.85)
    tracker.register_source("source_b", source_type="document", credibility_score=0.72)
    

    Block, cluster, and merge duplicates with semantic similarity.

    from semantica.deduplication import DuplicateDetector, EntityMerger
    
    entities = [
        {"id": "e1", "name": "Acme Corporation",  "domain": "acme.com"},
        {"id": "e2", "name": "Acme Corp.",         "domain": "acme.com"},
        {"id": "e3", "name": "ACME Corp",          "domain": "acme.co"},
        {"id": "e4", "name": "Globex Industries",  "domain": "globex.com"},
    ]
    
    detector   = DuplicateDetector(similarity_threshold=0.75, use_clustering=True)
    candidates = detector.detect_duplicates(entities)
    groups     = detector.detect_duplicate_groups(entities)
    # → DuplicateGroup(entities=["e1","e2","e3"], confidence=0.91, strategy="semantic+blocking")
    
    merger  = EntityMerger(preserve_provenance=True)
    ops     = merger.merge_duplicates(entities, strategy="keep_most_complete")
    history = merger.get_merge_history()
    

    Standardize text, entities, dates, numbers, and encodings before building your knowledge graph.

    from semantica.normalize import (
        TextNormalizer,
        EntityNormalizer,
        DateNormalizer,
        NumberNormalizer,
        DataCleaner,
    )
    
    # Unicode, whitespace, casing, HTML tags, smart quotes
    text  = TextNormalizer().normalize("  Acme Corp.'s Q4 report...  ")
    # → "Acme Corp.'s Q4 report..."
    
    # Alias resolution + entity disambiguation with confidence scores
    canonical = EntityNormalizer().normalize_entity("ACME Corp.")
    # → NormalizedEntity(canonical="Acme Corporation", type="Organization", confidence=0.91)
    
    # Natural language date parsing with timezone conversion
    dt    = DateNormalizer().normalize_date("3 weeks ago")
    # → datetime(2026, 7, 1, tzinfo=UTC)
    
    # Numbers with currency symbols and magnitude suffixes
    price = NumberNormalizer().normalize_number("$1.25M")
    # → 1250000.0
    
    # Deduplicate, validate, and impute missing values across a dataset
    clean = DataCleaner().clean_data(records, remove_duplicates=True, handle_missing=True)
    

    Compose ingestion, extraction, and graph-building into a declarative, parallel pipeline.

    from semantica.pipeline import PipelineBuilder, ExecutionEngine
    
    builder = PipelineBuilder()
    
    # add_step() returns the created PipelineStep, not the builder, so these don't chain
    builder.add_step("ingest",      step_type="ingest",           source="./contracts/", recursive=True)
    builder.add_step("extract",     step_type="ner_extract")
    builder.add_step("relations",   step_type="relation_extract")
    builder.add_step("build_kg",    step_type="kg_build",         merge_entities=True)
    builder.add_step("deduplicate", step_type="deduplicate",      threshold=0.75)
    builder.add_step("export",      step_type="export",           format="turtle", output="kg.ttl")
    
    # connect_steps() and set_parallelism() return the builder, so these do chain
    pipeline = (
        builder
        .connect_steps("ingest",      "extract")
        .connect_steps("extract",     "relations")
        .connect_steps("relations",   "build_kg")
        .connect_steps("build_kg",    "deduplicate")
        .connect_steps("deduplicate", "export")
        .set_parallelism(4)
        .build(name="contracts_pipeline")
    )
    
    engine   = ExecutionEngine()
    result   = engine.execute_pipeline(pipeline)
    status   = engine.get_pipeline_status(pipeline.name)
    progress = engine.get_progress(pipeline.name)
    

    Track when facts were true in the world vs. when they were recorded, and query either axis.

    from semantica.context import ContextGraph
    from semantica.kg import (
        BiTemporalFact,
        TemporalGraphQuery,
        TemporalNormalizer,
    )
    from datetime import datetime
    
    graph = ContextGraph(advanced_analytics=True)
    graph.add_node("alice_chen", "Person",       role="VP Engineering")
    graph.add_node("acme_corp",  "Organization", valuation=1_200_000_000)
    
    # A temporally-bounded edge - valid_from/valid_until define when it held true
    graph.add_edge(
        "alice_chen", "acme_corp", edge_type="works_for",
        valid_from="2024-03-01T00:00:00", valid_until="2025-01-01T00:00:00",
    )
    
    # Point-in-time snapshots - replay history without reprocessing
    snapshot_2023 = graph.state_at("2023-06-01")
    snapshot_2024 = graph.state_at("2024-01-01")
    
    # Bi-temporal facts - valid_time is when true in the world;
    # recorded_at is when you learned about it
    fact = BiTemporalFact(
        valid_from=datetime(2024, 3, 1),
        valid_until=datetime(2025, 1, 1),
        recorded_at=datetime(2024, 3, 5),
    )
    
    # Query facts valid within a time window - to_kg_dict() is the official
    # adapter that emits {"entities", "relationships"} with source_id/target_id
    # keys, the shape query_time_range() expects (no manual mapping required)
    kg = graph.to_kg_dict()
    
    tq = TemporalGraphQuery()
    facts_in_window = tq.query_time_range(
        kg, query="valid_facts", start_time="2024-01-01", end_time="2024-12-31"
    )
    
    # Normalize natural language temporal expressions - returns a (start, end) range
    norm = TemporalNormalizer(reference_date=datetime(2026, 1, 1))
    start, end = norm.normalize("last quarter")
    

    Export to any format required by regulators, graph databases, or downstream systems.

    from semantica.export import (
        RDFExporter,
        JSONExporter,
        ParquetExporter,
        LPGExporter,
        ReportGenerator,
    )
    
    kg = {"entities": [...], "relationships": [...]}
    
    rdf = RDFExporter()
    turtle_str = rdf.export_to_rdf(kg, format="turtle")     # returns string
    jsonld_str = rdf.export_to_rdf(kg, format="json-ld")
    
    rdf.export(kg, "kg_audit.ttl",    format="turtle")
    rdf.export(kg, "kg_audit.jsonld", format="json-ld")
    rdf.export(kg, "kg_audit.nt",     format="ntriples")
    
    # Columnar analytics - Snappy-compressed Parquet (writes kg_snapshot_entities.parquet
    # and kg_snapshot_relationships.parquet)
    ParquetExporter(compression="snappy").export_knowledge_graph(kg, "kg_snapshot")
    
    # JSON knowledge graph
    JSONExporter().export_knowledge_graph(kg, "kg.json")
    
    # Neo4j / Memgraph Cypher statements for graph database import
    LPGExporter().export(kg, "kg_import.cypher")
    
    # Human-readable HTML report
    ReportGenerator().generate_report(
        {"title": "KG Audit Report", "summary": "Weekly ingestion summary", "metrics": {"entities": len(kg["entities"])}},
        file_path="audit_report.html",
        format="html",
    )
    

    Render force-directed graphs, community maps, ontology hierarchies, and temporal dashboards.

    from semantica.visualization import (
        KGVisualizer,
        OntologyVisualizer,
        EmbeddingVisualizer,
        TemporalVisualizer,
    )
    import numpy as np
    
    kg = {"entities": [...], "relationships": [...]}
    
    # Interactive force-directed graph (opens in browser)
    viz = KGVisualizer(layout="force", color_scheme="default")
    viz.visualize_network(kg, output="interactive", file_path="kg.html")
    viz.visualize_communities(kg, communities, output="interactive")
    viz.visualize_centrality(kg, centrality, centrality_type="degree")
    viz.visualize_entity_types(kg, output="html", file_path="entity_types.html")
    
    # Ontology class hierarchy
    OntologyVisualizer().visualize_hierarchy(ontology, output="interactive")
    
    # 2D embedding projection (UMAP / t-SNE / PCA)
    EmbeddingVisualizer().visualize_2d_projection(
        embeddings=np.array([...]),
        labels=["entity_a", "entity_b"],
        method="umap",
    )
    
    # Timeline scrubber - watch the graph evolve
    TemporalVisualizer().visualize_timeline(kg, output="interactive")
    

    One shared intelligence layer. All agents read and write to the same context graph.

    # pip install semantica[agno]
    from agno.agent import Agent
    from agno.team import Team
    from agno.models.anthropic import Claude
    from semantica.context import ContextGraph
    from semantica.vector_store import VectorStore
    from integrations.agno import AgnoSharedContext, AgnoDecisionKit, AgnoKGToolkit
    
    shared = AgnoSharedContext(
        vector_store=VectorStore(backend="faiss"),
        knowledge_graph=ContextGraph(advanced_analytics=True),
        decision_tracking=True,
    )
    
    researcher = Agent(
        name="Researcher",
        model=Claude(id="claude-sonnet-4-5"),
        memory=shared.bind_agent("researcher"),
        tools=[AgnoKGToolkit(context=shared)],
    )
    analyst = Agent(
        name="Analyst",
        model=Claude(id="claude-sonnet-4-5"),
        memory=shared.bind_agent("analyst"),
        tools=[AgnoDecisionKit(context=shared)],
    )
    
    team = Team(agents=[researcher, analyst], mode="coordinate")
    # Researcher's findings are instantly available to the Analyst - no copy, no sync
    

    → runnable notebooks in the cookbook, each self-contained and runnable in under 5 minutes


    More Recipes

    The audit-trail recipe is above. Here are three more common patterns.

    from semantica.ingest import FileIngestor
    from semantica.split import TextSplitter
    from semantica.semantic_extract import NamedEntityRecognizer, RelationExtractor
    from semantica.kg import GraphBuilder
    from semantica.vector_store import VectorStore, HybridSearch
    from semantica.context import AgentContext
    
    # 1. Ingest
    docs = FileIngestor().ingest_directory("./docs/", recursive=True)
    
    # 2. Entity-aware chunking - never splits an entity across a chunk boundary
    splitter = TextSplitter(method="entity_aware", chunk_size=1000)
    chunks   = [splitter.split(doc.text) for doc in docs]
    
    # 3. Extract entities and relations
    ner      = NamedEntityRecognizer(confidence_threshold=0.7)
    rel_ext  = RelationExtractor(confidence_threshold=0.6)
    entities = [ner.extract_entities(chunk.text) for chunk_group in chunks for chunk in chunk_group]
    
    # 4. Build KG
    kg = GraphBuilder(merge_entities=True, enable_temporal=True).build(docs)
    
    # 5. Hybrid retrieval
    vs  = VectorStore(backend="inmemory")
    ctx = AgentContext(vector_store=vs, knowledge_graph=kg)
    ctx.store("Alice approved the Acme renewal in Q1 2024", conversation_id="c1")
    
    results = HybridSearch(vector_store=vs).search("who approved the renewal?")
    
    from semantica.reasoning import ReteEngine, Rule, Fact, RuleType
    
    rete = ReteEngine()
    rete.build_network([
        Rule(
            rule_id="sanctions_check",
            name="Flag sanctioned-country transactions",
            conditions=[
                {"field": "amount",  "operator": ">",  "value": 10_000},
                {"field": "country", "operator": "in", "value": ["IR", "KP", "SY", "CU"]},
            ],
            conclusion="flag_for_compliance_review",
            rule_type=RuleType.IMPLICATION,
        ),
    ])
    
    # Run the rule across a batch of incoming transactions, not just one
    for tx in [
        Fact("tx_101", "transaction", [{"amount": 25_000, "country": "IR"}]),
        Fact("tx_102", "transaction", [{"amount": 4_500,  "country": "DE"}]),
        Fact("tx_103", "transaction", [{"amount": 60_000, "country": "KP"}]),
    ]:
        rete.add_fact(tx)
    
    flagged = rete.match_patterns()
    

    Same condition-matcher caveat as above applies — validate against your rule set before production use.

    from semantica.ingest import FileIngestor
    from semantica.semantic_extract import NamedEntityRecognizer, RelationExtractor
    from semantica.kg import GraphBuilder
    from semantica.ontology import OntologyGenerator, OntologyValidator
    from semantica.export import RDFExporter
    
    sources   = FileIngestor().ingest_directory("./contracts/")
    ner       = NamedEntityRecognizer(confidence_threshold=0.7)
    entities  = ner.process_batch([s["text"] for s in sources])
    
    kg  = GraphBuilder(merge_entities=True).build(sources)
    gen = OntologyGenerator(base_uri="https://myco.dev/ontology/")
    ont = gen.generate_ontology({"entities": entities[0], "relationships": []})
    
    report = OntologyValidator().validate(ont)
    if report.valid:
        RDFExporter().export({"entities": entities[0]}, "ontology.ttl", format="turtle")
    

    Features at a Glance

    CapabilityHighlights
    Context GraphsQueryable graph of entities, decisions, relationships; causal links; cross-graph navigation
    Decision Intelligencerecord_decision · trace_decision_chain · find_similar_decisions · analyze_decision_impact · check_decision_rules
    Temporal IntelligencePoint-in-time snapshots · Allen interval algebra (13 relations) · TemporalNormalizer · bi-temporal provenance
    Distance IntelligenceN×N semantic distance matrices · ego-mode visualization · distance bands · embedding cache
    Semantic ExtractionNER · relation extraction · event detection · triplet generation · coreference
    Reasoning EnginesForward chaining · Rete · deductive · abductive · SPARQL · Datalog with explainable output
    GraphRAG ChunkingEntity-aware · relation-aware · graph-based · ontology-aware · community-detection chunking
    Conflict DetectionValue / type / relationship / temporal / logical conflicts · multiple resolution strategies
    ProvenanceW3C PROV-O · every fact traced to source · audit log export JSON/CSV/RDF
    Ontology HubSHACL Studio · visual editor · cross-ontology alignments · health dashboard
    Vector StoreFAISS · Pinecone · Weaviate · Qdrant · Milvus · PgVector · hybrid + filtered search
    Graph Databases (LPG)Neo4j · FalkorDB · Apache AGE · AWS Neptune
    Triple Stores (RDF)Oxigraph (embedded) · Blazegraph · Apache Jena · Eclipse RDF4J · unified TripletStore interface · SPARQL query & bulk load
    Enterprise Data PlatformsDatabricks (DatabricksIngestor: Unity Catalog + Delta Lake, PAT/OAuth M2M, table/query ingestion, catalog/schema/table/lineage introspection) · Snowflake (SnowflakeIngestor: warehouse/database/schema, password/key-pair/OAuth auth) · SAP (SAPIngestor: OData v2/v4, OAuth2/Basic auth, Business Partners/Sales Orders)
    LLM ProvidersAll already supported today: OpenAI (GPT-4o, o1, o3) · Anthropic (Claude) · Google Gemini · Mistral · Meta Llama · Groq · Cohere · Azure OpenAI · AWS Bedrock · Ollama · DeepSeek · Perplexity · Together AI · Fireworks AI · Replicate · HuggingFace · via semantica.llms and LiteLLM

    Performance

    Benchmarks from v0.5.0 on a 118,000-node production graph:

    OperationBeforeAfterImprovement
    Node search (118k nodes)24 ms0.004 ms6,000× faster
    Embedding cache hitcold loadrevision-based cache10× throughput
    Semantic deduplicationbaselineoptimized candidate gen6.98× faster
    Candidate generationbaselineblocking strategy63.6% faster

    Measured on a 118,000-node production graph (AMD EPYC, 64 GB RAM); the deduplication/candidate-generation figures are historical measurements recorded in CHANGELOG.md rather than an automated tests/ assertion. Results vary by hardware, dataset topology, and backend selection — run pytest tests/vector_store/test_performance_benchmarks.py -s to measure your own data.


    CLI

    Every capability is available from the terminal. The CLI ships with the package, no separate install required.

    pip install semantica
    semantica        # startup dashboard
    semantica doctor # health check
    semantica --help # full grouped command reference
    

    Start with semantica, verify with doctor, build a graph, and explore the command groups from one terminal.

    Command groups: ingest · parse · extract · kg · reason · decision · temporal · provenance · ontology · embed · deduplicate · validate · export · visualize · pipeline · server · explorer · mcp · doctor · shell · init · watch

    → Full CLI reference


    Integrations

    Native plugin bundles for Claude Code, Cursor, Codex, Windsurf, Cline, Continue, VS Code, OpenClaw, and pi; a full-featured MCP server for any MCP-compatible client; a comprehensive REST API; and first-class Agno, CrewAI, and LangChain support for agentic frameworks. Every major LLM provider is already supported via semantica.llms and LiteLLM: OpenAI, Anthropic, Gemini, Mistral, Llama, Groq, Cohere, Azure, Bedrock, Ollama, DeepSeek, HuggingFace, and more.

    MCP setup takes 30 seconds — see MCP Server below.