mirror of
https://github.com/semantica-agi/semantica.git
synced 2026-09-13 04:04:09 +00:00
Compare commits
5
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
d0d6b9ab5c | ||
|
|
b17ce71f56 | ||
|
|
6a2173027e | ||
|
|
66632a9437 | ||
|
|
f83d2a8b12 |
+2694
-256
File diff suppressed because it is too large
Load Diff
@@ -403,7 +403,7 @@ cuda-pathfinder==1.6.0 \
|
|||||||
# via
|
# via
|
||||||
# -c requirements-ci.txt
|
# -c requirements-ci.txt
|
||||||
# cuda-bindings
|
# cuda-bindings
|
||||||
cuda-toolkit==13.0.3 \
|
cuda-toolkit==13.0.3.0 \
|
||||||
--hash=sha256:d693caaa261214ddd7dbb60d68e71cbed884e68c2be7509778f3051da0b91c3f
|
--hash=sha256:d693caaa261214ddd7dbb60d68e71cbed884e68c2be7509778f3051da0b91c3f
|
||||||
# via
|
# via
|
||||||
# -c requirements-ci.txt
|
# -c requirements-ci.txt
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
+18
-30
@@ -93,14 +93,27 @@ jobs:
|
|||||||
npm run test:graph-workspace
|
npm run test:graph-workspace
|
||||||
npm run test:plugin-registry
|
npm run test:plugin-registry
|
||||||
npm run test:deterministic-e2e
|
npm run test:deterministic-e2e
|
||||||
npm run test:graph-legend-e2e
|
|
||||||
- name: Build Explorer frontend
|
- name: Build Explorer frontend
|
||||||
working-directory: explorer
|
working-directory: explorer
|
||||||
run: npm run build
|
run: npm run build
|
||||||
- name: Install core package and base dependencies
|
- name: Install Explorer backend test dependencies
|
||||||
run: |
|
run: |
|
||||||
# Verify that core semantica installs cleanly with only its base dependencies
|
# Run the deterministic backend path before the all-extras CI
|
||||||
# (no optional extras) and that core imports and lazy missing-dependency hints work.
|
# environment is installed. The Explorer extra supplies the
|
||||||
|
# production API dependencies without importing optional vector
|
||||||
|
# providers such as Pinecone during test collection.
|
||||||
|
#
|
||||||
|
# --no-deps + a separate hash-pinned install (rather than the old
|
||||||
|
# `pip install -e ".[explorer]" pytest==9.1.1`) so every fetched
|
||||||
|
# package is hash-verified (Scorecard Pinned-Dependencies); the
|
||||||
|
# local editable install itself has nothing to hash.
|
||||||
|
# .github/requirements/explorer-extra-py311.txt is
|
||||||
|
# `uv pip compile pyproject.toml --extra explorer --python-version 3.11 --constraint requirements-ci.txt --generate-hashes`
|
||||||
|
# - regenerate it the same way if pyproject.toml's base/explorer
|
||||||
|
# deps change. Resolved specifically for this job's python 3.11
|
||||||
|
# (see the Dockerfile's explorer-extra-py313.txt for why this
|
||||||
|
# can't be shared with python 3.13: audioread needs extra
|
||||||
|
# standard-aifc/standard-sunau hashes only on 3.13+).
|
||||||
#
|
#
|
||||||
# --no-deps only skips *runtime* dependency resolution - `-e .`
|
# --no-deps only skips *runtime* dependency resolution - `-e .`
|
||||||
# still does a PEP 517 build, which by default creates an isolated
|
# still does a PEP 517 build, which by default creates an isolated
|
||||||
@@ -111,31 +124,8 @@ jobs:
|
|||||||
# copies instead of fetching its own.
|
# copies instead of fetching its own.
|
||||||
pip install -r .github/requirements/pep517-build.txt --require-hashes
|
pip install -r .github/requirements/pep517-build.txt --require-hashes
|
||||||
pip install --no-deps --no-build-isolation -e .
|
pip install --no-deps --no-build-isolation -e .
|
||||||
pip install -r .github/requirements/base-deps.txt --require-hashes
|
|
||||||
pip install -r .github/requirements/pytest-tool.txt --require-hashes
|
|
||||||
- name: Verify core-only package importability and slim behavior
|
|
||||||
run: |
|
|
||||||
python -c "
|
|
||||||
import semantica
|
|
||||||
print('semantica', semantica.__version__, 'core installed and importable')
|
|
||||||
"
|
|
||||||
pytest -q tests/test_issue_1513_slim_core.py
|
|
||||||
pytest -q tests/test_docs_check.py
|
|
||||||
- name: Install Explorer backend test dependencies
|
|
||||||
run: |
|
|
||||||
# Run the deterministic backend path before the all-extras CI
|
|
||||||
# environment is installed. The Explorer extra supplies the
|
|
||||||
# production API dependencies without importing optional vector
|
|
||||||
# providers such as Pinecone during test collection.
|
|
||||||
#
|
|
||||||
# .github/requirements/explorer-extra-py311.txt is
|
|
||||||
# `uv pip compile pyproject.toml --extra explorer --python-version 3.11 --constraint requirements-ci.txt --generate-hashes`
|
|
||||||
# - regenerate it the same way if pyproject.toml's base/explorer
|
|
||||||
# deps change. Resolved specifically for this job's python 3.11
|
|
||||||
# (see the Dockerfile's explorer-extra-py313.txt for why this
|
|
||||||
# can't be shared with python 3.13: audioread needs extra
|
|
||||||
# standard-aifc/standard-sunau hashes only on 3.13+).
|
|
||||||
pip install -r .github/requirements/explorer-extra-py311.txt --require-hashes
|
pip install -r .github/requirements/explorer-extra-py311.txt --require-hashes
|
||||||
|
pip install -r .github/requirements/pytest-tool.txt --require-hashes
|
||||||
- name: Test deterministic Explorer backend path
|
- name: Test deterministic Explorer backend path
|
||||||
run: |
|
run: |
|
||||||
pytest -q tests/explorer/test_explorer_deterministic_rendering_e2e.py
|
pytest -q tests/explorer/test_explorer_deterministic_rendering_e2e.py
|
||||||
@@ -178,5 +168,3 @@ jobs:
|
|||||||
|
|
||||||
print("Explorer frontend is packaged")
|
print("Explorer frontend is packaged")
|
||||||
PY
|
PY
|
||||||
- name: Run Google ADK Integration Tests
|
|
||||||
run: pytest tests/integrations/google_adk/
|
|
||||||
|
|||||||
@@ -34,7 +34,7 @@ jobs:
|
|||||||
# meaningful state carried over from a failed attempt.
|
# meaningful state carried over from a failed attempt.
|
||||||
- name: Initialize CodeQL (attempt 1)
|
- name: Initialize CodeQL (attempt 1)
|
||||||
id: codeql-init-1
|
id: codeql-init-1
|
||||||
uses: github/codeql-action/init@b96794f015dfd88f77b49b1c93e0fa7110f94c63 # v4
|
uses: github/codeql-action/init@cdf488f595d80d6e07e03d4674febd5ab45fa938 # v4
|
||||||
continue-on-error: true
|
continue-on-error: true
|
||||||
with:
|
with:
|
||||||
languages: python
|
languages: python
|
||||||
@@ -44,7 +44,7 @@ jobs:
|
|||||||
- name: Initialize CodeQL (attempt 2)
|
- name: Initialize CodeQL (attempt 2)
|
||||||
id: codeql-init-2
|
id: codeql-init-2
|
||||||
if: steps.codeql-init-1.outcome == 'failure'
|
if: steps.codeql-init-1.outcome == 'failure'
|
||||||
uses: github/codeql-action/init@b96794f015dfd88f77b49b1c93e0fa7110f94c63 # v4
|
uses: github/codeql-action/init@cdf488f595d80d6e07e03d4674febd5ab45fa938 # v4
|
||||||
continue-on-error: true
|
continue-on-error: true
|
||||||
with:
|
with:
|
||||||
languages: python
|
languages: python
|
||||||
@@ -54,17 +54,17 @@ jobs:
|
|||||||
- name: Initialize CodeQL (attempt 3)
|
- name: Initialize CodeQL (attempt 3)
|
||||||
id: codeql-init-3
|
id: codeql-init-3
|
||||||
if: steps.codeql-init-2.outcome == 'failure'
|
if: steps.codeql-init-2.outcome == 'failure'
|
||||||
uses: github/codeql-action/init@b96794f015dfd88f77b49b1c93e0fa7110f94c63 # v4
|
uses: github/codeql-action/init@cdf488f595d80d6e07e03d4674febd5ab45fa938 # v4
|
||||||
with:
|
with:
|
||||||
languages: python
|
languages: python
|
||||||
queries: security-and-quality
|
queries: security-and-quality
|
||||||
config-file: .github/codeql/codeql-config.yml
|
config-file: .github/codeql/codeql-config.yml
|
||||||
|
|
||||||
- name: Autobuild
|
- name: Autobuild
|
||||||
uses: github/codeql-action/autobuild@b96794f015dfd88f77b49b1c93e0fa7110f94c63 # v4
|
uses: github/codeql-action/autobuild@cdf488f595d80d6e07e03d4674febd5ab45fa938 # v4
|
||||||
|
|
||||||
- name: Perform CodeQL Analysis
|
- name: Perform CodeQL Analysis
|
||||||
uses: github/codeql-action/analyze@b96794f015dfd88f77b49b1c93e0fa7110f94c63 # v4
|
uses: github/codeql-action/analyze@cdf488f595d80d6e07e03d4674febd5ab45fa938 # v4
|
||||||
with:
|
with:
|
||||||
category: "/language:python"
|
category: "/language:python"
|
||||||
upload: false
|
upload: false
|
||||||
@@ -74,7 +74,7 @@ jobs:
|
|||||||
# Uploads results only when Default Setup is not active.
|
# Uploads results only when Default Setup is not active.
|
||||||
# If Default Setup is still enabled, this step skips gracefully
|
# If Default Setup is still enabled, this step skips gracefully
|
||||||
# instead of failing the workflow with HTTP 409.
|
# instead of failing the workflow with HTTP 409.
|
||||||
uses: github/codeql-action/upload-sarif@b96794f015dfd88f77b49b1c93e0fa7110f94c63 # v4
|
uses: github/codeql-action/upload-sarif@cdf488f595d80d6e07e03d4674febd5ab45fa938 # v4
|
||||||
with:
|
with:
|
||||||
sarif_file: ${{ steps.codeql.outputs.sarif-output }}
|
sarif_file: ${{ steps.codeql.outputs.sarif-output }}
|
||||||
category: "/language:python"
|
category: "/language:python"
|
||||||
|
|||||||
@@ -61,7 +61,7 @@ jobs:
|
|||||||
|
|
||||||
- name: Upload Trivy SARIF
|
- name: Upload Trivy SARIF
|
||||||
if: always()
|
if: always()
|
||||||
uses: github/codeql-action/upload-sarif@b96794f015dfd88f77b49b1c93e0fa7110f94c63 # v4
|
uses: github/codeql-action/upload-sarif@cdf488f595d80d6e07e03d4674febd5ab45fa938 # v4
|
||||||
with:
|
with:
|
||||||
sarif_file: trivy-results.sarif
|
sarif_file: trivy-results.sarif
|
||||||
category: trivy-container
|
category: trivy-container
|
||||||
|
|||||||
@@ -59,7 +59,7 @@ jobs:
|
|||||||
# avoiding the guardian.cmd/checkov exit-code bug in the MSDO wrapper.
|
# avoiding the guardian.cmd/checkov exit-code bug in the MSDO wrapper.
|
||||||
tools: eslint,templateanalyzer,terrascan
|
tools: eslint,templateanalyzer,terrascan
|
||||||
- name: Upload results to Security tab
|
- name: Upload results to Security tab
|
||||||
uses: github/codeql-action/upload-sarif@b96794f015dfd88f77b49b1c93e0fa7110f94c63 # v4
|
uses: github/codeql-action/upload-sarif@cdf488f595d80d6e07e03d4674febd5ab45fa938 # v4
|
||||||
with:
|
with:
|
||||||
sarif_file: ${{ steps.msdo.outputs.sarifFile }}
|
sarif_file: ${{ steps.msdo.outputs.sarifFile }}
|
||||||
|
|
||||||
@@ -100,7 +100,7 @@ jobs:
|
|||||||
run: python .github/scripts/filter_checkov_skipped.py reports/results_json.json reports/results_sarif.sarif reports/checkov.sarif
|
run: python .github/scripts/filter_checkov_skipped.py reports/results_json.json reports/results_sarif.sarif reports/checkov.sarif
|
||||||
|
|
||||||
- name: Upload Checkov results to Security tab
|
- name: Upload Checkov results to Security tab
|
||||||
uses: github/codeql-action/upload-sarif@b96794f015dfd88f77b49b1c93e0fa7110f94c63 # v4
|
uses: github/codeql-action/upload-sarif@cdf488f595d80d6e07e03d4674febd5ab45fa938 # v4
|
||||||
if: always()
|
if: always()
|
||||||
with:
|
with:
|
||||||
sarif_file: reports/checkov.sarif
|
sarif_file: reports/checkov.sarif
|
||||||
|
|||||||
@@ -67,12 +67,6 @@ jobs:
|
|||||||
run: |
|
run: |
|
||||||
pip install -r .github/requirements/twine.txt --require-hashes
|
pip install -r .github/requirements/twine.txt --require-hashes
|
||||||
twine check dist/*
|
twine check dist/*
|
||||||
# pypi-publish uploads everything under packages-dir (default: dist/) with
|
|
||||||
# no glob/include filter, so it must run before anything else writes a
|
|
||||||
# non-distribution file into dist/ - the Sigstore step below does exactly
|
|
||||||
# that (dist/*.sigstore.json), and pypi-publish fails on it with
|
|
||||||
# "InvalidDistribution: Unknown distribution format" if it runs after.
|
|
||||||
- uses: pypa/gh-action-pypi-publish@dc37677b2e1c63e2034f94d8a5b11f265b73ba33 # release/v1
|
|
||||||
- name: Attest build provenance
|
- name: Attest build provenance
|
||||||
uses: actions/attest-build-provenance@4d101475d8b20a2381f78447822ac1eab6504dd8 # v4
|
uses: actions/attest-build-provenance@4d101475d8b20a2381f78447822ac1eab6504dd8 # v4
|
||||||
with:
|
with:
|
||||||
@@ -81,7 +75,7 @@ jobs:
|
|||||||
# OpenSSF Scorecard's Signed-Releases check does not inspect - it looks for
|
# OpenSSF Scorecard's Signed-Releases check does not inspect - it looks for
|
||||||
# signature files attached as release assets. Sign here too so
|
# signature files attached as release assets. Sign here too so
|
||||||
# `dist/*.sigstore.json` bundles ship alongside the wheel/sdist on the
|
# `dist/*.sigstore.json` bundles ship alongside the wheel/sdist on the
|
||||||
# GitHub Release itself. This must run after pypi-publish (see above).
|
# GitHub Release itself.
|
||||||
- name: Sign artifacts with Sigstore
|
- name: Sign artifacts with Sigstore
|
||||||
uses: sigstore/gh-action-sigstore-python@790bc6befb9d733738f18d8f895854b453640ec9 # v3.5.0
|
uses: sigstore/gh-action-sigstore-python@790bc6befb9d733738f18d8f895854b453640ec9 # v3.5.0
|
||||||
with:
|
with:
|
||||||
@@ -94,3 +88,4 @@ jobs:
|
|||||||
dist/*.whl
|
dist/*.whl
|
||||||
dist/*.tar.gz
|
dist/*.tar.gz
|
||||||
dist/*.sigstore.json
|
dist/*.sigstore.json
|
||||||
|
- uses: pypa/gh-action-pypi-publish@dc37677b2e1c63e2034f94d8a5b11f265b73ba33 # release/v1
|
||||||
|
|||||||
@@ -40,6 +40,6 @@ jobs:
|
|||||||
retention-days: 5
|
retention-days: 5
|
||||||
|
|
||||||
- name: Upload to code-scanning
|
- name: Upload to code-scanning
|
||||||
uses: github/codeql-action/upload-sarif@b96794f015dfd88f77b49b1c93e0fa7110f94c63 # v4
|
uses: github/codeql-action/upload-sarif@cdf488f595d80d6e07e03d4674febd5ab45fa938 # v4
|
||||||
with:
|
with:
|
||||||
sarif_file: results.sarif
|
sarif_file: results.sarif
|
||||||
|
|||||||
@@ -154,21 +154,13 @@ jobs:
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
# Vulnerability IDs reviewed and accepted as non-actionable for this
|
# Vulnerability IDs reviewed and accepted as non-actionable for this
|
||||||
# project:
|
# project. Empty for now: pip-audit's OSV-backed database doesn't
|
||||||
# - GHSA-4j2p-28q2-5m79 (aka CVE-2026-69112): accelerate<=1.14.0
|
# currently carry either of the findings Safety used to flag here
|
||||||
# (transitive via docling-slim). Path traversal in sharded checkpoint
|
# (cuda-toolkit CVE-2025-33228, torchvision CVE-2026-65918), so
|
||||||
# index loading (load_checkpoint_in_model). 1.14.0 is the latest
|
# there's nothing to exclude. Left in place so a future finding can
|
||||||
# available PyPI release; no upstream patch exists yet. Semantica does
|
# be added the same way without restructuring this step - see git
|
||||||
# not load arbitrary user checkpoints. Re-evaluate once accelerate
|
# history on this file for the reasoning behind past entries.
|
||||||
# releases a fixed version.
|
IGNORED_VULN_IDS=""
|
||||||
# NOTE: pip-audit's OSV-backed report may surface either identifier as
|
|
||||||
# the primary `id` (with the other listed under `aliases`) depending on
|
|
||||||
# which alias the backing database picks as canonical, so both need to
|
|
||||||
# be listed here and the matching below checks aliases too - see
|
|
||||||
# https://github.com/semantica-agi/semantica/actions/runs/34296586683
|
|
||||||
# where this ignore list had only the GHSA id but the report's `id`
|
|
||||||
# was the CVE, so the gate still failed.
|
|
||||||
IGNORED_VULN_IDS="GHSA-4j2p-28q2-5m79,CVE-2026-69112"
|
|
||||||
|
|
||||||
# Exported so the "Comment PR with Security Results" step below can
|
# Exported so the "Comment PR with Security Results" step below can
|
||||||
# apply the same exclusion list to the raw report - it reads
|
# apply the same exclusion list to the raw report - it reads
|
||||||
@@ -184,16 +176,9 @@ jobs:
|
|||||||
# no vulns field at all (see the skip_reason handling above) -
|
# no vulns field at all (see the skip_reason handling above) -
|
||||||
# without the fallback, iterating `null[]` raises inside jq and
|
# without the fallback, iterating `null[]` raises inside jq and
|
||||||
# this whole computation silently evaluates to empty.
|
# this whole computation silently evaluates to empty.
|
||||||
#
|
|
||||||
# Matching checks `.id` AND `.aliases` (pip-audit includes aliases by
|
|
||||||
# default for JSON output): the OSV-backed report can surface either
|
|
||||||
# the GHSA or the CVE identifier as the canonical `id` for the same
|
|
||||||
# advisory, with the other one demoted to an alias, so matching on
|
|
||||||
# `.id` alone is not reliable.
|
|
||||||
VULNS=$(jq --arg ignored "$IGNORED_VULN_IDS" '
|
VULNS=$(jq --arg ignored "$IGNORED_VULN_IDS" '
|
||||||
($ignored | split(",") | map(select(length > 0))) as $ignore_list
|
($ignored | split(",") | map(select(length > 0))) as $ignore_list
|
||||||
| [.dependencies[] | (.vulns // [])[]
|
| [.dependencies[] | (.vulns // [])[] | select(.id as $id | ($ignore_list | index($id)) | not)]
|
||||||
| select(([.id] + (.aliases // [])) as $ids | ($ids - $ignore_list | length) == ($ids | length))]
|
|
||||||
| length
|
| length
|
||||||
' pip-audit-report.json 2>/dev/null)
|
' pip-audit-report.json 2>/dev/null)
|
||||||
|
|
||||||
@@ -214,8 +199,7 @@ jobs:
|
|||||||
jq --arg ignored "$IGNORED_VULN_IDS" -r '
|
jq --arg ignored "$IGNORED_VULN_IDS" -r '
|
||||||
($ignored | split(",") | map(select(length > 0))) as $ignore_list
|
($ignored | split(",") | map(select(length > 0))) as $ignore_list
|
||||||
| .dependencies[] as $dependency
|
| .dependencies[] as $dependency
|
||||||
| ($dependency.vulns // [])[]
|
| ($dependency.vulns // [])[] | select(.id as $id | ($ignore_list | index($id)) | not)
|
||||||
| select(([.id] + (.aliases // [])) as $ids | ($ids - $ignore_list | length) == ($ids | length))
|
|
||||||
| "- \($dependency.name)==\($dependency.version): \(.id)"
|
| "- \($dependency.name)==\($dependency.version): \(.id)"
|
||||||
' pip-audit-report.json || true
|
' pip-audit-report.json || true
|
||||||
exit 1
|
exit 1
|
||||||
@@ -361,16 +345,9 @@ jobs:
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
// A vuln's canonical `id` and its `aliases` (e.g. GHSA vs. CVE
|
|
||||||
// for the same advisory) are checked together - mirrors the
|
|
||||||
// shell gate above, which needs the same fallback because
|
|
||||||
// pip-audit's OSV-backed report doesn't consistently pick the
|
|
||||||
// same identifier as canonical across advisories.
|
|
||||||
return data.dependencies.flatMap((dependency) =>
|
return data.dependencies.flatMap((dependency) =>
|
||||||
(dependency.vulns || [])
|
(dependency.vulns || [])
|
||||||
.filter((vulnerability) =>
|
.filter((vulnerability) => !ignoredVulnIds.includes(vulnerability.id))
|
||||||
![vulnerability.id, ...(vulnerability.aliases || [])].some((id) => ignoredVulnIds.includes(id))
|
|
||||||
)
|
|
||||||
.map(
|
.map(
|
||||||
(vulnerability) => `- \`${dependency.name}==${dependency.version}\`: ${vulnerability.id}` +
|
(vulnerability) => `- \`${dependency.name}==${dependency.version}\`: ${vulnerability.id}` +
|
||||||
(vulnerability.fix_versions?.length ? ` (fixed by ${vulnerability.fix_versions.join(', ')})` : '')
|
(vulnerability.fix_versions?.length ? ` (fixed by ${vulnerability.fix_versions.join(', ')})` : '')
|
||||||
|
|||||||
BIN
Binary file not shown.
+1
-148
@@ -11,43 +11,6 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|||||||
|
|
||||||
### Added
|
### Added
|
||||||
|
|
||||||
- **Schema-guided extraction validation** (#1510) by @Besokus
|
|
||||||
- New `SchemaValidator` (`semantica.semantic_extract`, lazy export): a deterministic sibling of `ExtractionValidator` that checks extraction output for *conformance to a domain ontology* — an axis orthogonal to `ExtractionValidator`'s confidence checks. It mirrors the same interface (`validate_entities()` / `validate_relations()` returning `ValidationResult`, batch-aware), so the two compose back-to-back
|
|
||||||
- Entity labels must be concepts in the schema; relation predicates must be in the schema and satisfy their `domain` / `range`. Violations are reported in `ValidationResult.errors` with counts in `metrics` and `score` = conformance ratio; `filter_by_schema()` / `filter_relations_by_schema()` return the conforming subset (mirroring `filter_by_confidence`). No LLM required
|
|
||||||
- New `ExtractionSchema` (`semantica.semantic_extract`, lazy export): a lightweight, read-only view over a domain ontology (allowed concepts + predicates with optional `domain` / `range`). Reuses the project's existing OWL ontology representation rather than a parallel type — build one from a `generate_ontology`-style dict (`ExtractionSchema.from_ontology`) or an OWL/Turtle file/string (`ExtractionSchema.from_owl`, via the existing `rdflib` dependency). An empty `domain`/`range` means unconstrained, matching OWL
|
|
||||||
- Implements the deterministic core of ontology-based information extraction (OBIE; Wimalasuriya & Dou, 2010). No new runtime dependencies
|
|
||||||
- New `tests/semantic_extract/test_schema_validator.py`
|
|
||||||
|
|
||||||
## [0.7.0] - 2026-09-07
|
|
||||||
|
|
||||||
### Changed
|
|
||||||
|
|
||||||
- **Slim core dependencies: moved ~22 heavy packages to optional extras** (#1513)
|
|
||||||
- Core dependencies in `pyproject.toml` are now reduced to exactly 22 direct packages: `numpy`, `pandas`, `scipy`, `scikit-learn`, `rdflib`, `networkx`, `requests`, `chardet`, `protobuf`, `grpcio`, `pillow`, `pydantic`, `click`, `rich`, `tqdm`, `pyyaml`, `toml`, `python-dotenv`, `loguru`, `structlog`, `httpx`, and `pyarrow`.
|
|
||||||
- Heavy ML/NLP, visualization, document parsing, and ingestion packages moved into granular optional extras:
|
|
||||||
- `models-huggingface`: `torch`, `transformers`
|
|
||||||
- `embeddings-local`: `sentence-transformers`, `fastembed`, `onnxruntime`, `tokenizers`
|
|
||||||
- `nlp-spacy`: `spacy`
|
|
||||||
- `viz`: expanded to include `matplotlib`, `seaborn`, `plotly`, `ipywidgets`, `umap-learn`, alongside `pyvis`, `graphviz`, and `d3blocks`
|
|
||||||
- `media`: `librosa`, `opencv-python`
|
|
||||||
- `vectorstore-faiss`: `faiss-cpu` (also included in `vectorstore-all`)
|
|
||||||
- `documents`: `python-docx`, `openpyxl`, `lxml`, `beautifulsoup4`
|
|
||||||
- `ingest-git`: `GitPython`
|
|
||||||
- `graph-embeddings`: `gensim` (also included in `graph-all`)
|
|
||||||
- Full bundled behavior preserved via `pip install "semantica[all]"`, which includes all optional extras. Pinning `semantica<0.7.0` remains a permanent escape hatch for legacy workflows.
|
|
||||||
- Safe lazy construction across parsers and visualizers:
|
|
||||||
- `DOCXParser`, `ExcelParser`, `HTMLParser`, and `XMLParser` remain constructible without error on `__init__()`. They fail only upon calling `.parse()` with actionable error messages directing users to install `semantica[documents]`.
|
|
||||||
- `XMLParser` automatically falls back to standard library `xml.etree` (`_parse_with_etree`) when `lxml` is not installed, preserving XML parsing capabilities without extra dependencies.
|
|
||||||
- `EmbeddingVisualizer` and `OntologyVisualizer` safely guard `matplotlib` and optional reduction packages, advising `pip install 'semantica[viz]'`.
|
|
||||||
- `RepoIngestor` guards `GitPython` with a clear error pointing to `semantica[ingest-git]`.
|
|
||||||
- `PublicAPIIngestor` guards `lxml` and `_SAFE_XML_PARSER`.
|
|
||||||
- Updated user-facing installation hints across CLI doctor commands, node embeddings (`NodeEmbedder`), vector stores (`FAISSStore`), and model loaders.
|
|
||||||
- Recompiled CI lockfiles (`requirements-ci.txt`, `.github/requirements/explorer-extra-py311.txt`, `.github/requirements/explorer-extra-py313.txt`, and `.github/requirements/base-deps.txt`).
|
|
||||||
|
|
||||||
## [0.6.8] - 2026-09-05
|
|
||||||
|
|
||||||
### Added
|
|
||||||
|
|
||||||
- **Salesforce ingestor** (#1240) by @Sameer6305
|
- **Salesforce ingestor** (#1240) by @Sameer6305
|
||||||
- New `SalesforceConnector` / `SalesforceData` / `SalesforceIngestor` (`semantica.ingest`, lazy export), following the same Connector + Data + Ingestor pattern already used for Snowflake/Databricks/SAP
|
- New `SalesforceConnector` / `SalesforceData` / `SalesforceIngestor` (`semantica.ingest`, lazy export), following the same Connector + Data + Ingestor pattern already used for Snowflake/Databricks/SAP
|
||||||
- Auth covers both landscapes Salesforce actually uses: username + password + security token (SOAP login), session_id + instance_url (reusing an existing session), and username + consumer_key + private key (JWT Bearer); production and sandbox are selected via `domain`, and credentials can come from environment variables. Credential material is never intentionally written to logs, exceptions, or `repr()`
|
- Auth covers both landscapes Salesforce actually uses: username + password + security token (SOAP login), session_id + instance_url (reusing an existing session), and username + consumer_key + private key (JWT Bearer); production and sandbox are selected via `domain`, and credentials can come from environment variables. Credential material is never intentionally written to logs, exceptions, or `repr()`
|
||||||
@@ -55,6 +18,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|||||||
- New `pip install semantica[db-salesforce]` extra (`simple-salesforce>=1.12.0`)
|
- New `pip install semantica[db-salesforce]` extra (`simple-salesforce>=1.12.0`)
|
||||||
- New `tests/test_salesforce_ingestor.py`
|
- New `tests/test_salesforce_ingestor.py`
|
||||||
- Docs: `docs/integrations/salesforce.md`
|
- Docs: `docs/integrations/salesforce.md`
|
||||||
|
|
||||||
- **`ErasureCoordinator` completes the erasure workflow `purge_node()` only starts — the graph node was removed while the same content survived verbatim in `AgentMemory` and as an embedding** (closes #1018) by @pravit-amp
|
- **`ErasureCoordinator` completes the erasure workflow `purge_node()` only starts — the graph node was removed while the same content survived verbatim in `AgentMemory` and as an embedding** (closes #1018) by @pravit-amp
|
||||||
- New `semantica/context/erasure.py`, exporting `ErasureCoordinator` and `ErasureReceipt` from `semantica.context`. `purge_node()`/`purge_edge()` (#957) are graph-scope by design and their changelog entry documents this gap explicitly; the changelog also names GDPR Article 17 as the motivation, and an Article 17 erasure that removes the node while the content stays retrievable by similarity search is not an erasure — it is worse than not offering one, because `purge_node()` returns `True` and writes a tombstone attesting the content is gone
|
- New `semantica/context/erasure.py`, exporting `ErasureCoordinator` and `ErasureReceipt` from `semantica.context`. `purge_node()`/`purge_edge()` (#957) are graph-scope by design and their changelog entry documents this gap explicitly; the changelog also names GDPR Article 17 as the motivation, and an Article 17 erasure that removes the node while the content stays retrievable by similarity search is not an erasure — it is worse than not offering one, because `purge_node()` returns `True` and writes a tombstone attesting the content is gone
|
||||||
- The coordinator **composes** the existing public APIs — nothing in `context_graph.py` or `agent_memory.py` changes behaviorally, and `ContextGraph` keeps its documented graph-scope contract rather than acquiring references to `AgentMemory`/`vector_store` that would invert the dependency
|
- The coordinator **composes** the existing public APIs — nothing in `context_graph.py` or `agent_memory.py` changes behaviorally, and `ContextGraph` keeps its documented graph-scope contract rather than acquiring references to `AgentMemory`/`vector_store` that would invert the dependency
|
||||||
@@ -75,117 +39,6 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|||||||
- **Fixed during review** (Qodo): the constructor's "at least one store" guard used `not vector_store`, rejecting a valid store whose `__bool__`/`__len__` makes an empty instance falsey, and reporting `vector_store=None` in the error when an object had been passed; it now distinguishes `None` (absent) from `False` (deliberately disabled) from any other value (provided), and echoes what it actually received
|
- **Fixed during review** (Qodo): the constructor's "at least one store" guard used `not vector_store`, rejecting a valid store whose `__bool__`/`__len__` makes an empty instance falsey, and reporting `vector_store=None` in the error when an object had been passed; it now distinguishes `None` (absent) from `False` (deliberately disabled) from any other value (provided), and echoes what it actually received
|
||||||
- **Fixed during review** (Qodo): `at` annotations accepted only `str`/`datetime` while the shared `ContextGraph` normalizer they delegate to also takes epoch seconds; widened to `int`/`float` with the docstrings updated, so the coordinator no longer advertises less than the graph API it wraps
|
- **Fixed during review** (Qodo): `at` annotations accepted only `str`/`datetime` while the shared `ContextGraph` normalizer they delegate to also takes epoch seconds; widened to `int`/`float` with the docstrings updated, so the coordinator no longer advertises less than the graph API it wraps
|
||||||
- **Known limitation, unchanged by this PR**: erasure still cannot be *completed* on FAISS/Milvus/Weaviate — `delete_vectors()` is declared on the `VectorStore` facade (`vector_store.py:786`) but not implemented across the backend set, under at least three different names. That is worth its own issue; the coordinator ships reporting `unsupported` and starts reporting `erased` for those backends once it is fixed, with no API change here
|
- **Known limitation, unchanged by this PR**: erasure still cannot be *completed* on FAISS/Milvus/Weaviate — `delete_vectors()` is declared on the `VectorStore` facade (`vector_store.py:786`) but not implemented across the backend set, under at least three different names. That is worth its own issue; the coordinator ships reporting `unsupported` and starts reporting `erased` for those backends once it is fixed, with no API change here
|
||||||
- **Ontology package gains a deterministic, CI-friendly quality gate for ontologies and knowledge graphs** (#1397, closes #1393) by @T1mn — machine-readable quality findings with severities, metrics, statistics, and configurable thresholds; deterministic checks cover ontology structure, class/property coverage, domain/range references, and KG relationship endpoints. Reuses the existing `OntologyValidator`, `OntologyEvaluator`, and `GraphValidator` with no new runtime dependencies. Exposed through `semantica.ontology` and `OntologyEngine`. New `semantica/ontology/quality_gate.py`; new `tests/ontology/test_ontology_quality_gate.py`, and the full targeted ontology/graph-validator suite the author ran alongside it: 63 passed, 4 skipped. This first version reports findings only — no auto-fix, dashboard, or benchmark integration yet.
|
|
||||||
- **`VectorStore` gains `scan_vectors()`/`iter_vectors()` enumeration, and `store migrate` becomes functional** (#1264, part of #1265) by @ZohaibHassan16 — previously vector stores exposed only `get_vector(id)`/`count()`, so there was no way to loop over all vectors, and `semantica store migrate` always told users to export/reindex manually. Adds `scan_vectors(offset, limit)` to `FAISSStore`, `SQLiteVecStore`, and `PgVectorStore` — backends that can support normal positional pagination; in-memory is handled directly by the facade, other backends delegate when they support it, and unsupported backends raise `NotImplementedError` rather than silently returning nothing. `store migrate` now actually migrates between faiss/sqlite/pgvector, copying vectors and metadata in batches and stamping `--namespace` onto metadata that doesn't already have one. Pinecone/Qdrant/Milvus/Weaviate are deferred to follow-up PRs since each backend paginates differently. 22 new tests covering backend scanning, facade behavior, and the migrate CLI.
|
|
||||||
- **`VectorStore.iter_vectors()` dispatches to a new `iter_all()` cursor primitive, with Qdrant as the first cursor-based backend** (#1316, part of #1265) by @ZohaibHassan16 — none of Qdrant/Pinecone/Milvus/Weaviate's native pagination APIs can properly implement positional `scan_vectors(offset, limit)` (Qdrant's cursor is a point ID, Pinecone's is an opaque continuation token, Milvus's `offset` is capped at a 16,384-result window, Weaviate's cursor is the previous object's UUID), so rather than faking positional offsets, backends can now implement `iter_all(batch_size)` as a generator over their native paging API; the facade uses it via `callable()` when present (consistent with existing `count()` dispatch) and falls back to the `scan_vectors()` loop otherwise. `QdrantStore.iter_all()` threads `scroll()`'s `next_page_offset` between requests — correctly yielding a final non-empty page even when the cursor is already exhausted — and raises on an uninitialized store rather than returning empty, so `store migrate` can't report success after copying zero vectors (the failure mode from #1083). Also fixes `store migrate` inferring vector dimension from a nonexistent `._backend_store.dimension` attribute on Qdrant/Milvus/Weaviate (silently falling back to a wrong default of 768) by reading dimension off the first scanned record and chaining it back into the iterator. Qdrant is added to `store migrate`'s supported backends. 6 facade dispatch tests, new `tests/vector_store/test_qdrant_store.py` (10 tests), and 5 CLI dimension-inference tests.
|
|
||||||
- **`WeaviateStore.iter_all()` adds cursor-based full-collection iteration for Weaviate** (#1317, part of #1265, stacked on #1316) by @ZohaibHassan16 — Weaviate's `fetch_objects(after=<uuid>)` pagination has no way to map a numeric offset to a cursor, so this reuses/extracts the cursor-loop and version-fallback logic already in `filter_by_metadata`. Unlike that method's `seen_ids` set (unbounded memory over a full scan), `iter_all()` detects a stalled scan by checking whether the next cursor advanced, keeping memory use O(1). An empty page under cursor pagination is not treated as end-of-scan on its own — `after` has no server-issued continuation value of its own, so a batch could in principle land entirely on a gap (tombstoned objects) with live data past it, the same risk previously confirmed for Qdrant's scroll cursor — so the iterator falls back to an offset-based check once before ending the scan. Also fixes `_extract_vector()` silently producing a corrupted 0-d array against a real (non-mocked) Weaviate collection by unwrapping weaviate-client v4's `{'default': [...]}` vector shape. New `tests/vector_store/test_weaviate_store.py` covering cursor threading, short-page termination, the empty-page/gap fallback, stalled-cursor termination, and the offset fallback when a client rejects `after`. Wiring Weaviate into `store migrate` itself is deferred to #1335 — the facade's write dispatch (`store_vectors()` only recognizes `add`/`add_vectors`, not Weaviate's `add_objects`) and initialization (the facade never calls `connect()`/collection-selection) aren't ready for a backend shaped like this one.
|
|
||||||
- **`MilvusStore.iter_all()` adds Milvus to the `iter_vectors()` cursor family via Milvus's query iterator** (#1326, part of #1265, stacked on #1316) by @ZohaibHassan16 — Milvus's `query(offset=...)` caps `offset + limit` at a documented 16,384-result window, so an offset-based scan would silently truncate any collection larger than that; `query_iterator()` is the primitive actually meant for scans beyond it. The iterator is closed in a `finally` block since it holds server-side state, covered by tests for both normal exhaustion and early/exception-path abandonment. Matches the missing-iterator-raises-rather-than-returns-empty behavior established for Qdrant (#1316) and Weaviate (#1317), so an unsupported `pymilvus` version can't make `store migrate` look like it copied an empty collection successfully; `store migrate` wiring for Milvus is left for a separate PR. New `tests/vector_store/test_milvus_store.py`: 13 tests (Milvus had no dedicated test file before).
|
|
||||||
- **`WeaviateStore` gains `delete_vectors()`, completing Weaviate support for `ErasureCoordinator`** (#1392) by @pkupt — Weaviate half of #1374 (Milvus landed in #1391; FAISS stays unsupported since flat indices can't delete in place). IDs are the object UUIDs `store_vectors()` returns, deleted one at a time via `collection.data.delete_by_id`, which returns `False` rather than raising for a missing UUID, so the erasure receipt's `backend_result` count stays honest. 10 tests cover single/multi-id deletes, not-found-uuid counting, empty ids, and the missing-collection path, plus two integration tests binding `WeaviateStore` as a backend; author notes this is logic-level coverage since Weaviate wasn't available locally to verify live wire behavior.
|
|
||||||
- **`semantica.llms` gains a first-class `Anthropic` provider wrapper** (#1255, closes #1253) by @ZohaibHassan16 — matches the existing `Groq`/`OpenAI` wrapper pattern (`generate`, `generate_structured`, `generate_typed`, `is_available`) over the `AnthropicProvider` already used internally by semantic extraction; previously reachable only through the generic LiteLLM passthrough. New docs section in `docs/guides/llm-integrations.md`; 6 new tests in `tests/test_llm_anthropic.py`.
|
|
||||||
- **`semantica.llms` gains `Gemini`, `Ollama`, `DeepSeek`, and `Novita` provider wrappers** (#1262, closes #1261) by @ZohaibHassan16 — these four providers already existed in `semantic_extract/providers.py` but weren't exposed from the public `semantica.llms` API. Each follows the same `generate`/`generate_structured`/`generate_typed`/`is_available` pattern as `Groq`/`OpenAI`/`Anthropic`. Adds the missing `llm-novita` extra to `pyproject.toml` (uses the `openai` dependency, like DeepSeek), included in `llm-all`; docs added for Gemini/Ollama/DeepSeek, and the existing Novita docs updated to use the new wrapper instead of calling `create_provider()` directly. 32 new tests (8 per provider), following the `test_llm_anthropic.py` pattern.
|
|
||||||
- **Explorer's read-only Markdown viewer becomes a full editor for live `ContextGraph` nodes and host-supplied `AgentMemory` items** (#1349, closes #1327) by @genni613
|
|
||||||
- New canonical single-resource Markdown export/apply methods on `ContextGraph` and `AgentMemory`; resource IDs are validated against frontmatter before mutation, stale writes are rejected via `expected_revision` with HTTP 409, and writes validate fully before commit so failures can't leave a partial mutation. Edits apply to the live in-memory runtime object only — this PR does not introduce disk or restart persistence.
|
|
||||||
- New Explorer endpoints: `GET`/`PUT /api/markdown/{kind}/{resource_id:path}` and paginated `GET /api/memories`, returning structured 404/409/422/500 responses behind existing Explorer auth; `/api/info` now exposes `capabilities.agent_memory` so the UI can detect whether a host app supplied a memory store.
|
|
||||||
- Explorer UI gains Edit/Apply/Cancel alongside the existing Preview/Source/Copy; edits validate against the full canonical document (including supported frontmatter), no-op Applies are disabled, drafts persist across validation/conflict/network/server errors, navigation is guarded when a draft has unapplied changes, and Apply refreshes canonical source, revision, graph content, and labels. A new Memories workspace appears only when the host app supplies `create_app(agent_memory=...)`.
|
|
||||||
- Test coverage: domain round-trip/identity/validation/rollback tests, API success/conflict/authorization/failure-path tests, editor interaction tests (Apply/Cancel/dirty-navigation/retry), and capability/Memories-workspace tests. Author-reported: targeted Python acceptance suite 133 passed, 2 skipped; `npm run test:graph-workspace` 106 passed; `test:graph-store`, `test:deterministic-e2e`, and `test:plugin-registry` (7 passed) all green; `npm run build` passed. Full Python test collection was blocked locally by unrelated NumPy/h5py/spaCy binary incompatibilities.
|
|
||||||
- **New deterministic Explorer rendering example and end-to-end test covering build -> persist -> API -> frontend hydration -> canvas rendering** (#1041, closes #1037) by @alexsmolya — new `examples/explorer_deterministic_rendering_example.py` builds a canonical 4-node/3-edge graph (`Alice --WORKS_AT--> Acme`, `Bob --KNOWS--> Alice`, `Acme --LOCATED_IN--> New York`), persists it with `ContextGraph.save_to_file()`, and reloads with `GraphSession.from_file()`, printing setup/auth/launch guidance. New backend test `tests/explorer/test_explorer_deterministic_rendering_e2e.py` covers graph construction/serialization, `GraphSession`, and exact `/api/graph/*` node/edge/label responses across auth modes. New frontend tests (`deterministicExplorerRendering.test.ts`, `.e2e.ts`) mount the real Explorer app in Chromium, hydrate the real graph store through `useLoadGraph`, render the real Sigma canvas, and assert `WORKS_AT`/`KNOWS`/`LOCATED_IN` are actually drawn and stay labeled after zoom; redundant extra `label` plumbing is removed now that edge labels render from the already-hydrated `edgeType`. Author-reported: backend e2e 5 passed; frontend deterministic suites 49 graph-workspace + 1 graph-store + 7 plugin + 1 Chromium canvas E2E test passed; broader `tests/explorer` run 261 passed, 2 skipped, 2 pre-existing unrelated SHACL failures.
|
|
||||||
- **`integrations/google_adk`: first-class Google ADK support** (#1312, resubmit) by @Hitesh-XS — new `integrations/google_adk/` package (`kg_tools.py`, `decision_tools.py`, `session_service.py`) exposing Semantica's context-graph and decision-intelligence APIs as Google ADK tools and a session service, with its own README. Bundles `google-adk` into the Agentic Framework Integrations section of `pyproject.toml` and into the `all` extra. Also restores packaging state that had regressed on `main` (pinned `anthropic`/`pyarrow` bounds, `ingest-sap`, `langchain`, and package-data fixes) and replaces the deprecated `pinecone-client` dependency with the official `pinecone` package, which had been crashing context-graph initialization — and with it every integration test touching Pinecone. `mcp/` is renamed to `semantica_mcp/mcp/`, with import paths updated across MCP tests and tools. Author reports all 36 tests in `tests/integrations/google_adk/` passing against the corrected Pinecone dependency.
|
|
||||||
|
|
||||||
### Changed
|
|
||||||
|
|
||||||
- **`docs/guides/decision-intelligence.md`: fixed a broken `add_decision` pattern and a wrong hybrid-search description** (#1466) by @ZohaibHassan16 — the alternative "build a `Decision` object, pass to `add_decision`" pattern silently produced nodes invisible to `find_precedents`/`get_causal_chain`/`get_decision_insights` and raised `ValueError` on trace; replaced with the working keyword-argument form. Corrected the hybrid search description (was described as semantic similarity + Node2Vec embeddings at 0.7/0.3; actually word-level Jaccard overlap + connection-count structural similarity) and fixed a wrong decision id in the banking loan example that silently attached to a phantom node
|
|
||||||
- **Tightened prose for clarity and conciseness across the setup, architecture, cookbook, resources, glossary, modules, contributing, and community-facing docs** (#1459, #1458, #1457, #1456, #1454, #1453, #1452, #1442) by @Deep070203 — `cli-setup.md`, `explorer-setup.md`, `installation.md`, `quickstart.md`, `architecture.md`, `cookbook.md`, `citation.md`, `faq.md`, `learning-more.md`, `project-license.md`, `glossary.md`, `choose-your-module.md`, `modules.md`, `contributing-guide.md`, `community-projects.md`, `community.md`, and `governance.md`; no technical content changed
|
|
||||||
- **`docs/reference/ontology.md`: documented Quality Gate threshold semantics** (#1450) by @KaifAhmad1 — added a `### Thresholds` table covering `min_coverage`, `max_errors`, `max_warnings`, and `fail_on_warnings` (noting the latter is a separate constructor/call parameter, not a `thresholds` key), verified against `OntologyQualityGate.DEFAULT_THRESHOLDS`
|
|
||||||
- **Replaced the retired `claude-sonnet-4-20250514` model id in docs and LLM wrappers** (#1449) by @ZohaibHassan16 — updated roughly 15 examples across `graphrag.md`, `llm-integrations.md`, `multi-agent.md`, `ontology.md`, and `reference/llms.md` (plus the LiteLLM/Anthropic wrapper defaults) to `claude-sonnet-5`, `claude-opus-4-7`, and a current Bedrock model id
|
|
||||||
- **`docs/guides/semantic-extraction.md`: fixed a wrong triplet count and a retired model id** (#1448) by @ZohaibHassan16 — the pipeline example printed `{}/{} triplets valid` using the Turtle output's string length instead of the triplet count (producing output like `7/4231`); now uses a real `triplets_total` value. Also replaced `claude-sonnet-4-6` with the dated model id used elsewhere, and clarified the sample NER output is illustrative
|
|
||||||
- **`docs/reference/reasoning.md`: clarified Datalog query result ordering** (#1447) by @ZohaibHassan16 — the `datalog.query(...)` example implied a fixed result order; results are set-backed and unordered, so the comment no longer implies otherwise
|
|
||||||
- **`docs/index.md`: rewrote the landing page as a lean developer welcome** (#1446) by @KaifAhmad1 — replaced the long feature-dump page with a shorter one built around Semantica's deterministic semantic/context-infrastructure positioning, trimming the module table, use-case grid, and duplicate link lists (kept as a collapsed accordion so the module-coverage check still passes)
|
|
||||||
- **`docs/guides/pipeline.md`: fixed the retry-policy example** (#1444) by @ZohaibHassan16 — the example configured a `FailureHandler` with custom retry policies but never assigned it to the `ExecutionEngine`, which builds its own handler, so the configured policies were silently ignored; added `engine.failure_handler = handler`. Also replaced a hardcoded node/edge-count output comment with a shape-only example
|
|
||||||
- **`docs/modules.md`: fixed code examples across the module catalogue to match the current API** (#1443) by @ZohaibHassan16 — corrected snippets using nonexistent or outdated APIs (e.g. `NERExtractor`'s `method="llm"`, `SimilarityCalculator.calculate_similarity()`, `Reasoner.apply_transitivity()`/`infer()`, `EntityResolver`, `ConflictDetector.resolve()`, treating `Pipeline` as a builder/runtime API) across extraction, graph building, reasoning, deduplication, conflicts, embeddings, vector store, export, pipeline, seed data, and evals sections; all 31 code blocks now parse and were run against current source
|
|
||||||
- **`docs/integrations/langchain.md`: tightened integration prose** (#1432) by @taljeon — replaced a remaining em dash with direct sentences and reformatted the component list as name/type pairs; no technical content changed
|
|
||||||
- **`docs/guides/graphrag.md`: fixed broken example strings and clarified `max_hops`** (#1431) by @ZohaibHassan16 — the banking example's multi-line string literals raised `IndentationError`; wrapped in parentheses to match the working Clinical example. Clarified that `AgentContext.retrieve(max_hops=)` only bounds anchored proximity scoring rather than graph-expansion depth (`max_expansion_hops` controls that); also fixed a made-up node/edge count comment
|
|
||||||
- **Tightened prose and fixed two broken relative links in `concepts.md`, `guides/graphrag.md`, and `reference/context.md`** (#1422) by @KaifAhmad1 — removed em dashes from explanatory prose (left intact in simulated document/alert examples); fixed `reference/context.md` links to `reasoning`/`provenance` that were missing a leading slash and would 404; updated `concepts.md`'s intro tagline to match #1421
|
|
||||||
- **`docs/index.md`: rewrote landing-page prose to be crisp and direct** (#1421) by @KaifAhmad1 — cut the marketing/storytelling framing and all em dashes; updated the tagline to "The Context and Semantic Layer for AI in High-Stakes Domains" across `docs.json` and `index.md`, keeping audit trail/accountability as a property rather than the headline
|
|
||||||
- **Restructured the docs nav** (#1419) by @KaifAhmad1 — dropped the standalone FAQ and Changelog tabs (their pages moved under Overview) and added a dedicated API Reference tab holding the `reference/*` pages split out of Modules
|
|
||||||
- **`docs/assets/custom.css`: replaced decorative hover/fade animations with static styling** (#1418) by @KaifAhmad1 — removed the page-load fade-in and hover lift/glow effects on code blocks, cards, buttons, and nav links site-wide, keeping the existing color palette and accessibility focus rings
|
|
||||||
- **`docs/concepts.md`: fixed 9 of 13 code examples that no longer matched the current API** (#1417) by @ZohaibHassan16 — corrected the `GraphBuilder`, GraphRAG, forward-chaining/Rete/Datalog reasoning, `GraphReasoner`, `SimilarityCalculator`, provenance, and `MethodRegistry` snippets, plus the distance-band terminology and engine comparison table
|
|
||||||
- **`docs/quickstart.md`: fixed the parsed-document example to read `full_text`** (#1415) by @ZohaibHassan16
|
|
||||||
- **`docs/getting-started.md`: fixed broken Knowledge Graph and GraphRAG "Choose Your Path" examples** (#1414) by @ZohaibHassan16 — the extractor calls now pass parsed text instead of a `FileObject`, and the GraphRAG example uses `context.store()` + `retrieve(use_graph=True, ...)` instead of the nonexistent `load_graph()`/`query(mode=...)` APIs
|
|
||||||
- **Fixed ~300 relative body links across 74 docs pages that 404'd on the live site** (#1407, closes #1405) by @Duansg — GitHub Pages' trailing-slash redirect resolved hand-written relative Markdown links against the wrong base path; links are now rewritten as root paths
|
|
||||||
- **Fixed two broken cookbook notebook links** (#1403) by @ZohaibHassan16 — `docs/learning-more.md` pointed to a nonexistent `09_Embeddings.ipynb` (now the correct `12_Embedding_Generation.ipynb`), and `docs/reference/distance.md`'s dead link to a nonexistent Distance Intelligence notebook was removed
|
|
||||||
- **`docs/quickstart.md`/`docs/faq.md`: addressed Qodo review findings** (#1402, follow-up to #1401) by @ZohaibHassan16
|
|
||||||
- **`docs/quickstart.md`: fixed the Full Pipeline walkthrough against current APIs** (#1401) by @ZohaibHassan16 — corrected the parse, extract, ingest (`WebIngestor`/`XMLIngestor`), export (`ArangoAQLExporter`, Parquet), OCR, and `PipelineBuilder` examples, and fixed a stale `Pipeline(workers=N)` example also present in `faq.md`
|
|
||||||
- **Updated stale latest-version references to v0.6.7** across `docs/faq.md`, `docs/index.md`, and `docs/quickstart.md` (#1400) by @ZohaibHassan16
|
|
||||||
- **`docs/reference/mcp_server.md` and related pages: documented all 15 MCP tools** (#1399) by @ZohaibHassan16 — added the three previously-undocumented tools (`query_graph`, `update_node`, `delete_node`) and corrected the tool count everywhere it appeared
|
|
||||||
- **`docs/reference/evals.md`: rewritten to match the shipped `semantica.evals` API** (#1398) by @ZohaibHassan16 — replaced the stale "not yet implemented" placeholder with `evaluate()`, `list_evaluators()`, `EvalMetric`/`CaseResult`/`EvalSummary`, all 10 built-in evaluators, and the `decision_scores` sub-checks
|
|
||||||
- **README: propagated SAP OData connector mentions consistently and trimmed the audience list** (#1396) by @KaifAhmad1 — added SAP mentions to the Enterprise Data Platforms bullet, ingest summary, module reference table, and supported-sources line (previously only in "What's New"); tightened the "Who it's for" bullets; removed sample `semantica doctor` output from the quickstart snippet
|
|
||||||
- **Rewrote the Semantic Layer Basics cookbook lesson as a runnable introductory workflow** (#1361, closes #1325) by @taoche — replaced the removed `advanced/09_Semantic_Layer_Construction.ipynb`, which never used `TripletStore`, left mappings empty, and never executed a query, with `introduction/26_Semantic_Layer_Basics.ipynb`, whose ontology, mappings, RDF, and SPARQL query now agree end to end
|
|
||||||
- **Rewrote cookbook notebook 08 into a real, rerunnable knowledge-graph workflow** (#1359, closes #1289) by @taoche — it previously read the wrong parser key, substituted hard-coded extraction fixtures, bypassed `GraphBuilder`, and never called `KGVisualizer`; it now runs parse → NER/relation extraction → `GraphBuilder` → `KGVisualizer` end to end
|
|
||||||
- **Fixed cookbook notebook 07's graph mapping and deduplication output** (#1357, closes #1287) by @taoche — edges were built from loop indices instead of extracted relation endpoints, and the dedup output showed only merge operations, making 5 mentions falsely appear to collapse to 1 entity instead of the correct 4
|
|
||||||
- **README: repositioned Semantica's opening pitch around the semantic/context/knowledge layer** (#1348) by @KaifAhmad1 — leads with Context Graph, KG, and ontology governance (OWL/SHACL/SKOS) rather than framing audit trails as the flagship pattern; reordered the hero pillar list to lead with Context Management/Knowledge Modeling ahead of Decision Intelligence
|
|
||||||
- **Hash-pin every pip install across the Dockerfile and CI workflows for Scorecard Pinned-Dependencies** (#1338) by @KaifAhmad1 — CI/build hardening, no runtime behavior change. Closes 21 OpenSSF Scorecard alerts: existing `pkg==X.Y.Z` version pins (even installs already reading a hashed `requirements-ci.txt`) still scored low because no hash is visible on the install command itself. Adds hash-locked `.github/requirements/*.txt` files (via `uv pip compile --generate-hashes`) for every pip target not already covered, adds `--require-hashes` to all `-r requirements-ci.txt` installs, and splits local-source installs into `pip install --no-deps -e .` plus a separately hash-pinned dependency install (a local source tree has nothing to hash directly). The Dockerfile now installs from a pre-generated `explorer-extra.txt` rather than extracting constraints at build time
|
|
||||||
- **Test-only contributions**: fixed `sys.modules` mock leakage in `test_extractors_dispatch.py` that made 132 tests pass in isolation but fail in a full-suite run, by installing the mocks per-test via `patch.dict`/`addCleanup` instead of at module scope (#1337, closes #1336, by @dex0shubham); added missing `__init__.py` package markers to `tests/integrations/crewai/` and `tests/integrations/langchain/`, fixing a pytest collection abort from two same-named `test_degradation.py` files colliding under prepend import mode (#1252, closes #1251, by @dex0shubham); guarded fastapi-dependent Explorer test modules so `tests/explorer/` and `tests/test_security_regression.py` collect successfully without the `explorer` extra installed (#1232, closes #1167, by @dex0shubham)
|
|
||||||
- **`ContextGraph`'s temporal-input normalizer is now a public API** (#1455, closes #1377) by @Saket7002 — `normalize_temporal_input` is exposed publicly so `context/erasure.py`'s `ErasureCoordinator` can call it directly instead of reaching across modules for a private helper. No behavior change. Regression coverage added for the public normalizer; full targeted run (`test_context_graph_retraction.py` + `test_erasure_coordinator.py`): 101 passed.
|
|
||||||
- **New acceptance tests pin known contract gaps between `VectorStore`'s facade and the Qdrant/Pinecone/Milvus/Weaviate backends, as strict `xfail`** (#1332) by @ZohaibHassan16 — existing vector-store tests all bypass `_init_backend_store` (the code path that actually constructs cloud backend adapters), either mocking backend internals directly or injecting a fake backend, which is how #1316 could be fully green while broken end to end: a Qdrant-backed `VectorStore` can't read (no connection/collection ever established) and can't write (`store_vectors()` doesn't dispatch to `QdrantStore.insert_vectors`). New `tests/vector_store/test_backend_facade_contract.py` constructs each backend through the real facade path and marks the two capability gaps `xfail(strict=True)` for Qdrant/Pinecone/Weaviate (Milvus already passes, pinned separately as a control) — a fix will flip these to unexpected passes and fail the suite until the marker is removed, making them acceptance criteria rather than assertions of the broken behavior itself. 13 new tests (6 pass, 7 xfail); no application code changed.
|
|
||||||
- **CI now reports required status checks correctly on docs-only PRs** (#1410) by @Sameer6305 — `ci.yml`/`security-scan.yml` still trigger on every PR including docs-only changes, but skip their expensive jobs for docs-only diffs while still reporting a check status, so required checks don't block on jobs that never ran; full build/security scans are preserved for source or mixed changes, and non-PR triggers are unaffected.
|
|
||||||
- **CI gains npm Dependabot coverage for `explorer/` and container image scanning** (#1286) by @KaifAhmad1 — `dependabot.yml` previously had no `npm` ecosystem entry for `explorer/`, which is why the `brace-expansion`/`nanoid` CVEs fixed in #1280 went undetected until a manual check; added, mirroring the existing `pip` entry's schedule/labels/reviewers. New `container-scan.yml` builds the Dockerfile image, scans it with Trivy (CRITICAL/HIGH to the Security tab as SARIF, `ignore-unfixed: true`), and generates an SPDX SBOM with Syft, running on push to main, weekly, and on manual dispatch. Trivy runs report-only for now (no `exit-code` gate) until the first CRITICAL/HIGH baseline is triaged.
|
|
||||||
- **Distribution and trust-signal infrastructure: reusable install action, a PyPI install matrix, and release-pipeline hardening** (#1266) by @KaifAhmad1
|
|
||||||
- New `.github/actions/setup-semantica` composite action other repos can call to install and verify `semantica` in one step
|
|
||||||
- New `install-matrix.yml` verifies the *published* PyPI package installs and imports cleanly across Ubuntu/macOS/Windows and Python 3.9-3.12, on a weekly schedule and on every release, backing a new "pip install" README badge
|
|
||||||
- New `scorecard.yml` runs OpenSSF Scorecard analysis weekly and on push to main, backing a new README trust-signal badge
|
|
||||||
- `release.yml` gains a `twine check` gate before publish, catching a broken PyPI long-description render before it ships; the existing Trusted Publishing/OIDC + SLSA attestation signing flow is otherwise unchanged
|
|
||||||
- New `CITATION.cff` (enables GitHub's native "Cite this repository" button alongside the existing `docs/citation.md`) and `examples/ci/` copy-paste GitHub Actions/GitLab CI/CircleCI templates for downstream adopters
|
|
||||||
- New `GROWTH.md` tracks distribution-channel status with explicit guardrails against artificially inflating download/install metrics
|
|
||||||
- No application code changed; new workflow YAML validated with `yaml.safe_load` and new action pins verified against the GitHub API
|
|
||||||
- **Resynced `github/codeql-action` pin to current v4 SHA** (#1249) by @ZohaibHassan16 — the v4 tag's underlying SHA had changed, failing "Verify Action Pins" on every PR; all 8 refs across `codeql.yml` and `defender-for-devops.yml` updated and reverified (40/40 clean).
|
|
||||||
|
|
||||||
### Fixed
|
|
||||||
|
|
||||||
- **README's production deploy instructions pointed at an environment variable that exists nowhere in the codebase** (#1473, fixes #1429) by @v01dst — `README.md:1546` told deployers to set `SEMANTICA_SECRET_KEY`, but the Explorer auth code (`semantica/explorer/dependencies.py:30`) reads `SEMANTICA_API_KEY` (with `SEMANTICA_ALLOW_ANONYMOUS=true` as the opt-out), so a deploy following the README set a silently-ignored variable and then hit 503s or unintended anonymous mode. One-line docs fix; `grep SEMANTICA_SECRET_KEY README.md` shows 0 hits afterward
|
|
||||||
- **The Python 3.9 install matrix was still broken after the spaCy/thinc fix in #1329** (#1445, closes #1347) by @ZohaibHassan16 — `scikit-learn`, `requests`, `chardet`, `grpcio`, `pillow`, `click`, and `onnxruntime` all now ship minimum versions requiring Python 3.10+, so a plain no-extras install on 3.9 failed to resolve. Adds Python-version markers for each, following the existing spaCy/thinc pattern: 3.9 is capped at the latest compatible release per package, 3.10+ stays unconstrained. Verified with `uv pip compile --python-version 3.9` for Linux/Windows/macOS, plus 3.10 and 3.12
|
|
||||||
- **Ontology property generation inferred framework bookkeeping fields as business datatype properties** (#1420, closes #1416) by @pkupt — `_extract_data_properties` only skipped `id`/`type`/`entity_type`/`text`/`label`/`confidence`, so structural fields `GraphBuilder` and `EntityMerger` attach to entity dicts (`properties`, `relationships`, `metadata`, `provenance`, `merged_from`, `merge_strategy`) were emitted as bogus datatype properties alongside real attributes. The skip set is now a single `_CONTROL_FIELDS` constant covering all of them; flat top-level business attributes are unaffected. New `tests/ontology/test_ontology_framework_fields.py`
|
|
||||||
- **`ErasureCoordinator(vector_store=False)` didn't actually stop all vector deletion — it only stopped the coordinator's own leg** (#1395, closes #1378) by @Harsh4r0ra — disabling the vector leg made the coordinator itself report `status="not_configured"`, but `AgentMemory.batch_delete()` → `delete_memory()` still ran its own best-effort vector-delete cascade internally, catching any failure and returning `True` regardless, so `receipt.complete` could read `True` while an embedding was still live. A `skip_vector` flag is now threaded from `ErasureCoordinator` into a new keyword-only `AgentMemory.batch_delete(skip_vector=...)` parameter whenever the vector leg is explicitly disabled. The existing test that had asserted the buggy behavior is rewritten, plus a new regression test pinning `delete_calls == 0`
|
|
||||||
- **MCP graph persistence and setup were broken across multiple surfaces** (#1394, closes #1134) by @Sameer6305 — the root MCP server loaded graphs with a non-existent method instead of `load_from_file()`, and mutations made through MCP tools weren't persisted back to `SEMANTICA_KG_PATH` on either server implementation. Fixed graph loading, wired persistence through for both MCP server implementations, corrected the MCP installation and Claude Code setup docs (including the `claude mcp add` invocation and documenting the required `PYTHONPATH`), and added end-to-end MCP stdio JSON-RPC regression coverage
|
|
||||||
- **CI's Safety-based security scan crashed intermittently instead of reporting real findings** (#1390, closes #1389) by @ZohaibHassan16 — the same crash pattern previously seen with `cuda-toolkit` recurred with `torchvision`, and identical runs against `requirements-ci.txt` could either succeed or crash, so `IGNORED_VULN_IDS` couldn't help — Safety crashed before it ever wrote a report. Replaces the Safety step in `security-scan.yml` with `pip-audit` (already used successfully in `security.yml` against the same dependencies) and removes `security.yml` entirely now that `security-scan.yml` covers everything it did, plus Bandit, Semgrep, and PR reporting on a broader trigger set. `IGNORED_VULN_IDS` is now empty since `pip-audit`'s OSV source doesn't carry either CVE Safety was flagging. Verified via YAML/embedded-JS syntax checks, report-handling tests against six report shapes, and `verify-action-pins.sh` passing with 47 action references (down from 49 after removing `security.yml`)
|
|
||||||
- **`verify-action-pins.sh` failed after `actions/deploy-pages`'s v5 tag moved** (#1387) by @ZohaibHassan16 — the tag advanced from v5.0.0 to v5.0.1 (backoff/jitter added to deployment polling, confirmed via the GitHub API); the pinned SHA in `docs.yml` is updated to match. Verified all 49 action references pass
|
|
||||||
- **CI's security scan failed on an unreachable, transitive `torchvision` CVE** (#1385, closes #1384) by @ZohaibHassan16 — `SFTY-20260723-60537` (CVE-2026-65918) is a GIF-decoder finding in `torchvision`, pulled in transitively via `safetensors`/`sentence-transformers` and never used directly (confirmed by grep across `semantica/`, `mcp/`, `integrations/`); fixed upstream in commit `4e05dc2` but not yet in any released `torchvision`. Added to `IGNORED_VULN_IDS`, matching the existing `cuda-toolkit` precedent
|
|
||||||
- **`ErasureReceipt.to_dict()` returned nested dicts shared by reference with the live receipt** (#1381, fixes #1376) by @BinarySpecter — `backend_result`'s nested dicts weren't copied, so a caller mutating the returned dict could corrupt the receipt's own internal state; the audit record it's meant to be is no longer safe to hand out. Fixed with a proper deep copy in `semantica/context/erasure.py`. `tests/context/test_erasure_coordinator.py`: 49 passed, 3 subtests
|
|
||||||
- **The `--ignore`-based Safety CVE suppression added in #1370 crashed CI on the very next run** (#1371) by @KaifAhmad1 — a correction to #1370: `--ignore` only crashes once Safety has to apply itself against a real match, and the push-triggered run on `main` immediately after #1370 merged hit the exact `'cuda-toolkit'` crash #1131/#1157 had already fixed, even though a plain scan (no `--ignore`) had run clean moments earlier on the same dependencies. The author notes their own pre-merge local testing was misleading — their local Safety database didn't surface the CVE at all, so `--ignore` never had a real match to crash against locally. Fix: drop `--ignore` entirely, run the plain scan proven not to crash, and filter the accepted vulnerability ID out of the JSON report in `jq` before both the count check and detail-printing. Also fixes a latent bug where `.vulnerabilities | length` silently returned `0` for a null/missing `vulnerabilities` key instead of erroring, which the existing Guard 2 comment had assumed already happened. Validated the jq filter against six synthetic report shapes rather than relying on a local Safety run
|
|
||||||
- **CI's security scan failed on a real, unfixable-upstream `cuda-toolkit` CVE with no released fix available** (#1370) by @KaifAhmad1 — `SFTY-20260120-40557` (CVE-2025-33228) is a hard `==13.0.3` pin from `torch==2.13.0`'s own wheel metadata (the latest available torch release), so no version bump can resolve it; the CVE itself is OS command injection in NVIDIA Nsight Systems' `gfx_hotspot` recipe, which Semantica never invokes and which isn't among the CUDA extras torch actually requests here. Added `--ignore SFTY-20260120-40557` to the `safety check` invocation, scoped to this one vulnerability ID with an inline comment explaining why and when to revisit. Verified locally against Safety 3.8.1 that the ignore only suppresses this ID and no others. (Superseded the following day by #1371, which found this `--ignore` itself reintroduced a Safety crash in live CI)
|
|
||||||
- **A malformed Safety report could be silently read as a clean scan** (#1366) by @T1mn — the Security Scan workflow had no check that `safety-report.json` actually contained a well-formed, array-valued `vulnerabilities` field before counting findings, so a present-but-malformed report risked passing as zero findings. Adds an independent fail-closed check that validates the field's shape and renders an explicit invalid-report warning instead of treating malformed data as clean; the existing `--file requirements-ci.txt` Safety scan and the separate `security.yml` pip-audit workflow are unchanged
|
|
||||||
- **The bundled Claude Code plugin failed to install entirely** (#1363, fixes #1350) by @7487 — `plugins/.claude-plugin/plugin.json` declared `"agents": "./agents"`, but unlike `skills`, Claude Code's plugin schema rejects a bare directory string for `agents` (`Validation errors: agents: Invalid input`) and requires an explicit array of `.md` file paths. Replaced with `["./agents/decision-advisor.md", "./agents/explainability.md", "./agents/kg-assistant.md"]`. New `tests/test_plugin_manifest.py` guards that `agents` stays a non-empty array of existing `.md` paths in sync with `plugins/agents/`. Verified with the official validator (Claude Code 2.1.231): validation now passes
|
|
||||||
- **Checkov's own suppressed findings kept reopening as brand-new GitHub code-scanning alerts on every rescan** (#1346) by @KaifAhmad1 — the same 4 Checkov k8s findings on `deploy/helm/knowledge-explorer` (namespace/seccomp) were already suppressed via working `checkov.io/skipN` annotations and correctly marked `SKIPPED` in Checkov's JSON output, but Checkov's SARIF exporter emits every evaluated check as an ordinary `level: warning` result regardless of skip status and never populates SARIF's own `suppressions` field — so GitHub had no way to know these were suppressed and opened new alert numbers across three separate scans. New `.github/scripts/filter_checkov_skipped.py` cross-references Checkov's JSON `skipped_checks` against the SARIF `results` (matched on check ID plus the last two path segments, since JSON and SARIF use different path roots) and drops already-suppressed results before the SARIF reaches GitHub. Verified locally against a real checkov 3.3.1 + helm 3.16.4 run: removed exactly the 4 known-suppressed results, left 2 genuinely real findings elsewhere in the repo untouched
|
|
||||||
- **A Scorecard Pinned-Dependencies alert flagged an install step for a directory that doesn't exist in the repo** (#1345) by @KaifAhmad1 — `benchmark.yml:51` ran `pip install -r benchmarks/requirements.txt`, but `benchmarks/` doesn't exist anywhere in the repository, so the step couldn't be hash-pinned and the job already failed on the very next real step (`benchmarks/benchmarks_runner.py`, also missing) — the line did nothing useful. Dropped it rather than leave it unpinned. Also closed directly via the API without a PR: #6099 (Dockerfile Pinned-Dependencies, dismissed won't-fix — installing our own git-tracked source with `--no-deps --no-build-isolation` has no third-party fetch to pin, and pip rejects `--hash`/`--require-hashes` on local directory targets) and #6112–#6115 (same suppressed-Checkov-alert root cause as #1346, dismissed as false positive)
|
|
||||||
- **`MilvusStore.get_collection()` attached to a mismatched collection and only failed later, far from the root cause** (#1344, closes #1331) by @pkupt — the method wrapped `Collection(name)` right after the `has_collection` guard with no schema check, so an INT64-pk or metadata-less collection attached successfully and only surfaced an error deep inside `get_vector`/`get_metadata`. A schema check now runs immediately after attach, before the store assigns `self.collection`, so a mismatch is caught early with an error naming the actual problem. 9 new focused tests in `tests/vector_store/test_milvus_get_collection.py` cover the matching case and each rejection case
|
|
||||||
- **The Docker build broke outright after #1338, failing Container Security Scan on the build step itself rather than just SBOM/Trivy** (#1341) by @KaifAhmad1 — `explorer-extra.txt` was compiled with `--python-version 3.11` but installed on the Dockerfile's actual `python:3.13-slim` interpreter; `librosa`'s `audioread` dependency needs `standard-aifc`/`standard-sunau` only under `python_version >= "3.13"` (Python 3.13 dropped `aifc`/`sunau` from stdlib), and a lockfile resolved for 3.11 carries no hashes for those packages at all, so `--require-hashes` failed outright once pip resolved against the real 3.13 environment. Split into `explorer-extra-py311.txt` (used by `ci.yml`, unchanged resolution) and a newly-compiled `explorer-extra-py313.txt` (used by the Dockerfile, including the `standard-aifc`/`standard-sunau`/`standard-chunk` hashes), with `.github/requirements/README.md` documenting why the two can't be recombined
|
|
||||||
- **The Neo4j persistence example in `docs/quickstart.md` raised `AttributeError` when followed as written** (#1340, fixes #1135) by @Sameer6305 — the example passed a raw `Neo4jStore` backend directly to `GraphBuilder(graph_store=store)`, but `GraphBuilder` expects the `GraphStore` facade and calls `add_nodes()`/`add_edges()`, which the raw backend doesn't expose (`'Neo4jStore' object has no attribute 'add_nodes'`). Updated the example to construct `GraphStore(backend="neo4j", ...)` instead. New regression test in `tests/kg/test_graph_builder_with_graph_store.py` covering `GraphBuilder` against the `GraphStore` facade
|
|
||||||
- **`pip install semantica` failed on Python 3.9 across all three OSes** (#1329) by @KaifAhmad1 — `spacy` had no upper bound, so pip resolved spacy 3.8.16 whose `thinc>=8.3.12` requirement has no cp39 wheels and no working sdist build path either. Caps `spacy<3.8.8` and adds `thinc<8.3.5` for `python_version < '3.10'` (py3.10+ stays unconstrained); verified with a dry-run resolve against manylinux/win_amd64/macosx_arm64, all landing on prebuilt wheels (spacy 3.8.7 + thinc 8.3.4). Also pins Docker base images by digest and remaining unpinned CI tool installs, and adds Sigstore signing so `dist/*.sigstore.json` ships alongside release artifacts (OpenSSF Scorecard Pinned-Dependencies/Signed-Releases hardening)
|
|
||||||
- **FAISS vector store silently lost `vector_ids`/`metadata` across save/load, so a reloaded index reported zero vectors and `semantica store migrate --from faiss` silently copied zero records** (#1314, closes #1272) by @AhmadBilalDSA — loading a saved index reinitialized `vector_ids = []` and `metadata = {}`, so `scan_vectors()` returned `[]` and `count()` returned `0` despite a valid binary index on disk. Metadata now persists to an atomic companion `.meta.json` file written alongside the index, restored exactly on reload, with a `RuntimeWarning` plus a logged warning when the binary index exists but its sidecar is missing. New end-to-end regression test verifying `scan_vectors()` matches the original records across fresh store instances
|
|
||||||
- **Registered ontologies opened the Ontology Editor to an empty canvas, and ontology deep links didn't land on the Editor at all** (#1278, closes #1274) by @taoche — the app shell ignored `ontologyTab`/`ontologyEntity` URL state, and even when the Editor did open, it loaded registry metadata but never fetched the selected ontology's schema nodes and structural edges. Adds `GET /api/ontology/graph?uri=...` returning the bounded schema subgraph, wires deep-link state into startup tab selection, and maps the response into React Flow nodes/edges with loading/error/selection handling. 40 backend tests plus 77 explorer graph-workspace tests pass
|
|
||||||
- **Explorer's Full Graph view rendered small, multi-component graphs as unlabeled dots with relationships suppressed** (#1277, closes #1275) by @taoche — coordinate-free graphs of any size got the same large-graph seed layout, ForceAtlas2 stabilization, and overview edge LOD, which crushes node spacing and hides ordinary edges on a small graph. Adds a deterministic, component-aware layout path for coordinate-free graphs of up to 48 nodes — skips force stabilization, keeps labels visible, preserves relationship edges — while larger graphs and graphs with existing coordinates are unaffected. 81 explorer tests pass
|
|
||||||
- **Explorer graph-loading failures showed only a generic `Fetch failed: <status>` message, discarding the server's actionable error detail** (#1260, closes #1256) by @wanglin1111111 — e.g. an unconfigured `SEMANTICA_API_KEY` returns a specific remediation string in the response body's `detail` field, but the UI overlay showed a generic "check that the backend is running" hint instead, sending users down the wrong troubleshooting path. `useLoadGraph.ts` now reads the JSON body on a non-OK response and appends `detail` to the thrown error, degrading gracefully when the body isn't JSON
|
|
||||||
- **`ConsoleProgressDisplay` wrote progress bars to `sys.stdout`, corrupting the JSON-RPC protocol on stdio MCP servers** (#1254, closes #1134) by @dex0shubham — stdio MCP servers frame newline-delimited JSON-RPC on stdout, so an interleaved progress bar could make a response body unparseable. Progress now defaults to `sys.stderr` (resolved per-write via a property so a later rebinding, e.g. pytest capture, is honored), with an optional `stream` override; the cp1252 emoji-capability probe now inspects the actual target stream instead of always stdout. 9 new tests in `tests/utils/test_progress_stream.py`
|
|
||||||
- **`SlidingWindowChunker` accepted a zero or negative `stride`, and a failed `chunk_with_overlap()` call could leave chunker state un-restored** (#1245, closes #1244) by @HsienW — the fixed-size chunking path depends on `stride` to advance the cursor, but an explicit non-positive value passed validation; a temporary overlap override used internally by `chunk_with_overlap()` could also derive a non-positive stride, and the original overlap/custom stride weren't guaranteed to be restored if chunking raised. Non-positive stride/overlap values are now rejected before chunking, and the temporary override is restored via `try`/`finally` on both success and failure. 13 new/updated tests
|
|
||||||
- **Explorer's temporal scrubber sent duplicate snapshot requests and could apply a stale response over a newer one** (#1241, closes #1128) by @ALDRIN121 — repeated `onTimeChange` calls at the same timestamp (timeline recreation, play ticks, drag events) each fired a fresh `/api/temporal/snapshot` request with no dedup — 13+ identical-`at` requests observed at ~500ms cadence — and under variable network latency an older position's response could land after a newer one's, leaving the active-node chip visibly lagging the scrubber. New `temporalSnapshotGuards.ts` dedupes in-flight requests per scrubber position, caches and re-applies snapshots on revisit, and applies a response only while the scrubber is still on that position; state resets when the graph summary changes. 16 new unit tests
|
|
||||||
- **Distinct property spellings normalizing to the same ontology name produced duplicate property definitions, and object/data properties could collide under one IRI** (#1231) by @T1mn — follow-up to #1170/#1171. Same-kind properties normalizing to the same name are now merged, preserving their domains and ranges; a normalized name shared across an object and a data property now raises a structured `ValidationError` instead of silently colliding
|
|
||||||
- **Class inference could emit duplicate ontology classes for source types that normalize to the same name (e.g. `Person`/`person`), silently misassigning properties to the first class** (#1230) by @T1mn — follow-up to #1171. The collision is now detected and rejected with a structured `ValidationError` before duplicate classes or misassigned properties are emitted. New regression test for the `Person`/`person` case
|
|
||||||
- **`OntologyGenerator.infer_properties`'s public entry point still fell back to `owl:Thing` when relationship endpoints were given by entity ID or alias**, even though the main generation pipeline had already been fixed (#1229) by @T1mn — follow-up to #1170. The endpoint-resolution logic is now extracted into a shared `relationship_utils.py` helper used by both `PropertyGenerator` and the public inference path, so the two can't drift again
|
|
||||||
- **`auto_generate_id=False` on the six decision-model dataclasses was unreachable dead code** (#1153, fixes #1152) by @cxzg007 — `Decision`, `DecisionContext`, `Policy`, `PolicyException`, `Precedent`, and `ApprovalChain` declared `auto_generate_id` only as a plain `__post_init__` parameter rather than a dataclass field or `InitVar`, so the generated `__init__` never forwarded it — it was always `True`, and the "require a caller-supplied id" validation branch could never run. Declared as `InitVar[bool] = True` on each dataclass, restoring the intended contract with no serialization change (`InitVar` isn't a real field, so `to_dict()`/`from_dict()` are unaffected). 38 tests pass in `tests/context/test_decision_models.py`; 108 downstream tests unaffected
|
|
||||||
- **Three functions used mutable list-literal default arguments**, a classic Python pitfall where the same list object persists and can accumulate mutations across calls (#1068) by @yzxcj797 — `GraphAnalyzer.analyze_temporal_evolution(metrics=[...])`, `HierarchicalChunker.__init__(levels=[...])`, and `split_hierarchical(levels=[...])` now default to `None` with a fresh list built in-body. New regression tests in `tests/kg/test_kg.py` and `tests/split/test_chunkers.py`
|
|
||||||
- **`AgentMemory.find_by_entity()` defaulted to `limit=10`, silently truncating results** (#1024) by @yzxcj797 — the erasure workflow added in #1018 (`ErasureCoordinator`) computing what references an entity from a truncated page could leave the untruncated remainder live after a supposedly-complete erasure. Default changed to `limit=None` (all matches), with explicit limits still supported for pagination. New regression tests in `tests/context/test_agent_memory_find_by_entity.py`
|
|
||||||
- **Explorer SHACL validation error messages didn't name the environment variable that controls the limit being hit** (#1437, closes #1430) by @pkupt — the Turtle-size, triple-count, and timeout limit-exceeded messages in `validate_shacl` now name the specific env var to change, and `docs/guides/shacl-validation.md` documents all four resource-limit variables with their defaults. Existing message-assertion tests extended to also check the env var name appears.
|
|
||||||
- **Explorer's `POST /api/export` only supported `json`/`csv`, while the MCP `export_graph` tool already resolved Turtle, N-Triples, RDF/XML, JSON-LD, and GraphML through the same exporters** (#1157, closes #1131) by @13g4d0 — the Explorer route now reaches the same `semantica.export` exporters the MCP tool uses (`RDFExporter.export_to_rdf`, `GraphMLExporter.export`) rather than reimplementing anything, with an alias table shared with (and tested against) `mcp/tools/export.py`'s `_FORMAT_ALIASES`, correct media types/extensions per format, a 422 message that now names the supported formats instead of just saying the requested one isn't, and a missing optional dependency now returning 503 instead of a misleading 422. Parquet export is explicitly left out — it writes a file/path rather than a response body, and deserves its own review. Tests parse each of the seven RDF spellings with `rdflib` rather than asserting on strings, plus a canary that the Explorer and MCP alias tables agree; `tests/explorer/test_explorer_api.py`: 110 passed.
|
|
||||||
- **`semantica ingest` reported "✓ Ingested" while writing nothing to a configured Neo4j backend** (#1465, closes #1351) by @evgenyponomarev — `ingest()`/`ingest_file()` never referenced a graph store at all, so `--store`/`GRAPH_STORE_DEFAULT_BACKEND` were accepted and silently discarded; the command now raises a clear error when a non-memory graph backend is configured, naming both this and the related `kg build` no-op (#1352) rather than recommending a workaround that fails the same way. `--output <file>.json` writes the ingested result instead (via the existing `_write_result_output` helper), and `_json_default` now expands dataclasses (`FileObject`) and decodes `bytes` so the written file holds real content, not a Python repr. 3 new regression tests; full `tests/test_cli_commands.py`: 270 passed
|
|
||||||
|
|
||||||
### Security
|
|
||||||
|
|
||||||
- **Five HIGH-severity Trivy findings in the built container image** (#1334) by @KaifAhmad1 — `setuptools` 70.3.0 (CVE-2025-47273, path traversal; base-image-bundled and never touched by our own build) upgraded explicitly to 78.1.1. `msgpack` 1.1.2 (GHSA-6v7p-g79w-8964, OOB read/crash on Unpacker reuse) shipped because the Dockerfile's bare `pip install ".[explorer]"` re-resolved dependencies from scratch instead of reusing the audited, hash-pinned `requirements-ci.txt` (which already pins `msgpack==1.2.1`) — the image now installs against a constraints file derived from `requirements-ci.txt` so it matches what's actually been audited. `openssl`/`libssl3t64` (CVE-2026-14456, QUIC server DoS) has no packaged fix yet in Debian's `trixie-security`; an upgrade step is added so the next rebuild picks it up automatically, documented as non-exploitable here since the image only serves plain HTTP via uvicorn and never opens a QUIC listener
|
|
||||||
- **Two npm advisories in `explorer/package-lock.json` flagged by OpenSSF Scorecard, plus over-broad workflow token permissions** (#1280) by @KaifAhmad1 — `brace-expansion` (transitive via `minimatch`) 5.0.8→5.0.9 and `nanoid` (transitive via `postcss`) 3.3.16→3.3.18 close GHSA-rgw5-rvv9-x895 and GHSA-2v37-7h3g-55p8 (both unbounded/looping-input DoS); lockfile-only, both versions already satisfy their parents' declared ranges. Also narrows `security-events: write`/`actions: read` from workflow-level to job-level scope in `codeql.yml` and `defender-for-devops.yml`, matching least-privilege token-permission guidance
|
|
||||||
- **12 Dependabot alerts against `aiohttp`** (request smuggling, websocket/parser bugs, cookie/redirect and deserialization issues, one rated High), pinned transitively via `checkov` in `.github/requirements/checkov.txt` (#1342) by @KaifAhmad1 — root cause: `checkov==3.3.1` itself constrained `aiohttp<3.14.0`, excluding every patched release. Bumping to `checkov==3.3.16` relaxes that to `aiohttp<3.15.0`, letting `aiohttp` resolve to the patched `3.14.3` and clearing all 12 alerts at once. Two related alerts are documented as left open rather than fixed here: `asteval` (checkov 3.3.16 still hard-pins `asteval==1.0.6` with no compatible range yet) and `ecdsa` (`0.19.2` is already latest; no fix exists yet for the Minerva timing-attack advisory GHSA-wj6h-64fc-37mp, which upstream has declared out of scope) — both assessed as non-exploitable here since these are checkov's own transitive dependencies used only for local static IaC analysis, with no network-signing or cloud-auth code path exercised
|
|
||||||
|
|
||||||
### Dependencies
|
|
||||||
|
|
||||||
- Routine version bump fixing 2 disclosed advisories with no application-facing behavior change: `browserslist` (transitive dev dependency in `explorer/`) 4.28.2→4.28.8, closing GHSA-73wf-gq98-2v4g and GHSA-c83g-rgw3-j3cx (#1382)
|
|
||||||
|
|
||||||
## [0.6.7] - 2026-08-28
|
## [0.6.7] - 2026-08-28
|
||||||
|
|
||||||
|
|||||||
+2
-2
@@ -7,8 +7,8 @@ authors:
|
|||||||
repository-code: "https://github.com/semantica-agi/semantica"
|
repository-code: "https://github.com/semantica-agi/semantica"
|
||||||
url: "https://getsemantica.ai"
|
url: "https://getsemantica.ai"
|
||||||
license: MIT
|
license: MIT
|
||||||
version: 0.7.0
|
version: 0.6.7
|
||||||
date-released: 2026-09-05
|
date-released: 2026-08-28
|
||||||
keywords:
|
keywords:
|
||||||
- knowledge-graph
|
- knowledge-graph
|
||||||
- context-graph
|
- context-graph
|
||||||
|
|||||||
+1
-12
@@ -20,18 +20,7 @@ RUN mkdir -p /app/semantica && npm run build
|
|||||||
# .github/dependabot.yml opens a PR bumping the digest pin above. Also: this
|
# .github/dependabot.yml opens a PR bumping the digest pin above. Also: this
|
||||||
# image only serves plain HTTP via uvicorn and never opens a QUIC listener,
|
# image only serves plain HTTP via uvicorn and never opens a QUIC listener,
|
||||||
# so the bug isn't reachable here regardless.
|
# so the bug isn't reachable here regardless.
|
||||||
#
|
FROM python:3.13-slim@sha256:7ce4b6dfe35e55397b7cda544f8a13f191b7ae28dc5aad71fe664dbc9bc2623f AS runtime
|
||||||
# Pinned to 3.13, NOT 3.14: #1290 bumped this to python:3.14-slim and broke
|
|
||||||
# the build outright (Container Security Scan, every run since) - gensim
|
|
||||||
# (a base, non-extras-gated dependency) ships no cp314 wheel on PyPI yet, so
|
|
||||||
# pip falls back to building it from source, which needs a C compiler this
|
|
||||||
# slim image doesn't carry ("error: [Errno 2] No such file or directory:
|
|
||||||
# 'gcc'"). Revisit the 3.14 bump once gensim (and anything else pulled in
|
|
||||||
# transitively) publishes cp314 wheels - check with
|
|
||||||
# `pip index versions gensim` / the project's PyPI files page, not just
|
|
||||||
# whether `uv pip compile` resolves (resolution only reads sdist metadata,
|
|
||||||
# it doesn't attempt the build that fails here).
|
|
||||||
FROM python:3.14-slim@sha256:cad9a2c871761c413caa6fdd6441c783451e740a48aaeba60ae62a8b53525ef6 AS runtime
|
|
||||||
|
|
||||||
ENV PYTHONDONTWRITEBYTECODE=1 \
|
ENV PYTHONDONTWRITEBYTECODE=1 \
|
||||||
PYTHONUNBUFFERED=1 \
|
PYTHONUNBUFFERED=1 \
|
||||||
|
|||||||
@@ -14,7 +14,7 @@
|
|||||||
|
|
||||||
### Graph-Native Infrastructure for Context and Accountable AI Systems
|
### Graph-Native Infrastructure for Context and Accountable AI Systems
|
||||||
|
|
||||||
#### *Developer-first, knowledge infrastructure for AI, alternative to expensive enterprise platforms.*
|
#### *The Open Source Palantir for AI Agents*
|
||||||
|
|
||||||
> 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.
|
> 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.
|
||||||
|
|
||||||
@@ -28,13 +28,7 @@
|
|||||||
|
|
||||||
[](https://github.com/semantica-agi/semantica) [](https://github.com/semantica-agi/semantica/network/members) [](https://github.com/semantica-agi/semantica/graphs/contributors) [](https://pypi.org/project/semantica/) [](https://pepy.tech/project/semantica) [](https://www.python.org/) [](https://opensource.org/licenses/MIT) [](https://github.com/semantica-agi/semantica/actions) [](https://github.com/semantica-agi/semantica/actions/workflows/install-matrix.yml) [](https://scorecard.dev/viewer/?uri=github.com/semantica-agi/semantica) [](https://deepwiki.com/semantica-agi/semantica)
|
[](https://github.com/semantica-agi/semantica) [](https://github.com/semantica-agi/semantica/network/members) [](https://github.com/semantica-agi/semantica/graphs/contributors) [](https://pypi.org/project/semantica/) [](https://pepy.tech/project/semantica) [](https://www.python.org/) [](https://opensource.org/licenses/MIT) [](https://github.com/semantica-agi/semantica/actions) [](https://github.com/semantica-agi/semantica/actions/workflows/install-matrix.yml) [](https://scorecard.dev/viewer/?uri=github.com/semantica-agi/semantica) [](https://deepwiki.com/semantica-agi/semantica)
|
||||||
|
|
||||||
[](https://getsemantica.ai/)
|
[](https://getsemantica.ai/) [](https://docs.getsemantica.ai/) [](https://discord.gg/sV34vps5hH) [](https://x.com/BuildSemantica) [](https://www.youtube.com/watch?v=QfnNZg4-dZA) [](CHANGELOG.md)
|
||||||
[](https://docs.getsemantica.ai/)
|
|
||||||
[](https://discord.gg/sV34vps5hH)
|
|
||||||
[](https://x.com/BuildSemantica)
|
|
||||||
|
|
||||||
[](https://www.youtube.com/watch?v=QfnNZg4-dZA)
|
|
||||||
|
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
pip install semantica
|
pip install semantica
|
||||||
@@ -42,8 +36,6 @@ pip install semantica
|
|||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
[English](https://readme-i18n.com/semantica-agi/semantica?lang=en) · [Deutsch](https://readme-i18n.com/semantica-agi/semantica?lang=de) · [Français](https://readme-i18n.com/semantica-agi/semantica?lang=fr) · [Español](https://readme-i18n.com/semantica-agi/semantica?lang=es) · [Italiano](https://readme-i18n.com/semantica-agi/semantica?lang=it) · [Português](https://readme-i18n.com/semantica-agi/semantica?lang=pt) · [العربية](https://readme-i18n.com/semantica-agi/semantica?lang=ar) · [اردو](https://readme-i18n.com/semantica-agi/semantica?lang=ur) · [हिन्दी](https://readme-i18n.com/semantica-agi/semantica?lang=hi) · [中文](https://readme-i18n.com/semantica-agi/semantica?lang=zh) · [日本語](https://readme-i18n.com/semantica-agi/semantica?lang=ja) · [한국어](https://readme-i18n.com/semantica-agi/semantica?lang=ko)
|
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
<div align="center">
|
<div align="center">
|
||||||
@@ -64,21 +56,16 @@ pip install semantica
|
|||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
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.
|
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: a deterministic infrastructure layer (no LLM required for graph construction, reasoning, or provenance) that turns fragmented enterprise data into a structured, queryable Context Graph and knowledge graph, governed by ontologies and controlled vocabularies (OWL, SHACL, SKOS) so the meaning of your data is explicit, not just its embedding. Decision provenance and audit trails fall out of that structure as a property, not the product itself; in domains a regulator can question, that same structure just happens to double as a straight answer to "why."
|
||||||
|
|
||||||
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.
|
> ⚠️ **System-level explainability, not foundation-model explainability.** Semantica does not expose or reconstruct what happens *inside* the LLM — its internal reasoning or chain-of-thought stays opaque, as it does for any external system. Semantica explains what's *outside* the model: the context and data fed in, the decision produced, its provenance, relevant relationships, applied policies, and the full execution trail.
|
||||||
|
|
||||||
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:**
|
**Who it's for:**
|
||||||
|
|
||||||
- **AI/ML platform teams** shipping agents that make consequential decisions and need structured, queryable context, not just a vector index
|
- **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
|
- **Data platform teams on Databricks or Snowflake** turning tables already in Unity Catalog or a 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
|
- **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
|
- **Regulated enterprises** (finance, healthcare, legal, government, defense) that can't ship a black box or send 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
|
- **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
|
- **Data and knowledge engineers** building a KG from messy, multi-source data, where conflicting facts get flagged and duplicates get merged, not silently overwritten
|
||||||
|
|
||||||
@@ -90,15 +77,15 @@ Decision provenance and audit trails aren't the product. They fall out of that s
|
|||||||
|
|
||||||
- **Context Graphs:** A structured, queryable graph of everything your agent knows, decides, and reasons about
|
- **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
|
- **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
|
- **AI Governance & Ontology:** SHACL constraints, conflict detection, compliance rules, OWL generation, and SKOS vocabulary management with a visual editor
|
||||||
- **Full Auditability:** W3C PROV-O provenance on every fact, exportable to JSON, CSV, or RDF
|
- **Full Auditability:** W3C PROV-O provenance on every fact, with audit trails exportable to JSON, CSV, or RDF
|
||||||
- **Deterministic Reasoning:** Forward chaining, Rete network, Datalog, and SPARQL, with fully explainable paths, not black boxes
|
- **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
|
- **Knowledge Pipeline:** Multi-source ingestion, entity-aware chunking, NER/relation/event extraction, and knowledge graph construction, with semantic deduplication and provenance-preserving merges throughout
|
||||||
- **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
|
- **Enterprise Data Platforms:** Native connectors for Databricks (Unity Catalog + Delta Lake, PAT/OAuth M2M auth, catalog/schema/table/lineage introspection), Snowflake (warehouse/database/schema, key-pair and OAuth auth), and SAP OData (Business Partners, Sales Orders, OAuth2/Basic auth), so data already living in your lakehouse or warehouse becomes graph nodes with provenance, not another export/import hop
|
||||||
- **Graph Analytics:** Centrality, community detection, link prediction, and shortest-path queries over the graph you just built
|
- **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
|
- **Polyglot Graph Storage:** Native RDF (embedded Oxigraph, Blazegraph, Apache Jena, Eclipse RDF4J via SPARQL) and Labeled Property Graphs (Neo4j, FalkorDB, Apache AGE, AWS Neptune via Cypher), plus vector stores, all swappable without touching your code
|
||||||
- **Visualization:** Explore any graph, ontology, or timeline in an interactive browser workbench
|
- **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
|
- **Drop-in Integrations:** Native Agno, CrewAI, and LangChain support, a full-featured MCP server, a comprehensive CLI, a REST API, and plugins across major editors
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
@@ -1413,9 +1400,6 @@ semantica-mcp
|
|||||||
| `get_graph_analytics` | Centrality, communities |
|
| `get_graph_analytics` | Centrality, communities |
|
||||||
| `export_graph` | Export to RDF/JSON/Parquet |
|
| `export_graph` | Export to RDF/JSON/Parquet |
|
||||||
| `get_graph_summary` | Graph statistics |
|
| `get_graph_summary` | Graph statistics |
|
||||||
| `query_graph` | Fetch a node, walk neighbours, keyword search |
|
|
||||||
| `update_node` | Merge properties onto a node |
|
|
||||||
| `delete_node` | Archive (soft-delete) a node |
|
|
||||||
|
|
||||||
### REST API
|
### REST API
|
||||||
|
|
||||||
@@ -1471,81 +1455,73 @@ semantica-explorer --graph my_graph.json
|
|||||||
|
|
||||||
For contributor / dev-server setup: **[explorer/README.md: Local Setup Guide](explorer/README.md)**
|
For contributor / dev-server setup: **[explorer/README.md: Local Setup Guide](explorer/README.md)**
|
||||||
|
|
||||||
The CLI exposes the loaded `ContextGraph`. To also browse and edit an existing
|
---
|
||||||
`AgentMemory`, create the ASGI app programmatically with both live objects:
|
|
||||||
|
|
||||||
```python
|
## What's New in v0.6.7
|
||||||
from semantica.context import AgentMemory, ContextGraph
|
|
||||||
from semantica.explorer.app import create_app
|
|
||||||
from semantica.explorer.session import GraphSession
|
|
||||||
|
|
||||||
graph = ContextGraph()
|
**Feature release**, plus one SSRF hardening fix and a large batch of correctness fixes across the RDF/ontology export pipeline:
|
||||||
memory = AgentMemory()
|
|
||||||
app = create_app(session=GraphSession(graph), agent_memory=memory)
|
|
||||||
```
|
|
||||||
|
|
||||||
The Memories workspace is shown only when `agent_memory` is provided. Apply
|
- **First-class LangChain integration** (`semantica[langchain]`): a `BaseRetriever` and `VectorStore` over `HybridSearch`, plus graph/decision-query tools
|
||||||
updates the supplied runtime object; it does not add disk persistence.
|
- **SAP OData ingestor** (`semantica[ingest-sap]`): OAuth2/Basic-auth, SSRF-guarded ingestion for Business Partners and Sales Orders, following the existing Snowflake/Databricks connector pattern
|
||||||
|
- **`ContextGraph` gains deterministic, human-editable Markdown round-trip persistence** alongside the existing JSON API, and the Explorer graph inspector gains a read-only Markdown content viewer
|
||||||
|
- **`reasoning` gains a structured Action layer**: rule-driven `Assert`/`Retract`/`Call`/`EmitEvent` actions with optional provenance, turning the reasoner into a production-rule system
|
||||||
|
- **`run_shacl_validation` is now a public, documented API**, and a dozen ontology/RDF export correctness fixes land: OWL property/class export, SHACL target-namespace resolution, one canonical confidence datatype across all four RDF formats, reachable OWL-Time reification, JSON-LD default-graph and content-derived document identity, and full metadata passthrough on every RDF serializer
|
||||||
|
- **Security**: Agno's `AgnoKnowledgeGraph.load_urls()` and OpenClaw's MCP tool now route outbound requests through the shared SSRF guard
|
||||||
|
|
||||||
## What's New in v0.6.8
|
Also fixes: `PipelineBuilder.set_parallelism()` now actually parallelizes independent pipeline steps, `flatten_dict()` no longer silently drops data on a key collision, `Config.get()` honors boolean environment overrides, and the MCP server's `export_graph` tool works again on every format.
|
||||||
|
|
||||||
**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. Beyond that, this is a large fix-and-hardening release plus a batch of vector-store and LLM-provider additions:
|
|
||||||
|
|
||||||
- **Vector store gains real enumeration**: `scan_vectors()`/`iter_vectors()` land across FAISS, SQLiteVec, PgVector, Qdrant, Weaviate, and Milvus (each via the pagination primitive its API actually supports), making `semantica store migrate` functional between backends for the first time; Weaviate also gains `delete_vectors()` for `ErasureCoordinator` support
|
|
||||||
- **`semantica.llms` gains first-class `Anthropic`, `Gemini`, `Ollama`, `DeepSeek`, and `Novita` provider wrappers**, matching the existing `Groq`/`OpenAI` pattern
|
|
||||||
- **Ontology package gains a deterministic, CI-friendly quality gate** for ontologies and knowledge graphs, plus first-class Google ADK integration and a Salesforce ingestor
|
|
||||||
- **Explorer's read-only Markdown viewer becomes a full editor** for live `ContextGraph` nodes and host-supplied `AgentMemory` items
|
|
||||||
- **`ErasureCoordinator`** completes the erasure workflow `purge_node()` only started, so a purged entity no longer survives verbatim in `AgentMemory` or as an embedding
|
|
||||||
- **Security**: 12 Dependabot `aiohttp` alerts, 5 HIGH-severity Trivy container findings, and 2 npm advisories all resolved
|
|
||||||
|
|
||||||
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 a large batch of documentation corrections across the site.
|
|
||||||
|
|
||||||
→ [Full release notes](RELEASE_NOTES.md) · [Changelog](CHANGELOG.md)
|
→ [Full release notes](RELEASE_NOTES.md) · [Changelog](CHANGELOG.md)
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
## Built for High-Stakes Domains
|
||||||
|
|
||||||
|
Semantica is designed for environments where AI outputs must be explainable, auditable, and defensible, and where the data itself can't leave your infrastructure. Self-hostable with zero vendor lock-in, it's built as much for organizations handling confidential or classified data as for regulated industries chasing an audit trail:
|
||||||
|
|
||||||
|
- **Finance:** Loan underwriting audit trails, fraud detection, AML compliance, regulatory risk knowledge graphs
|
||||||
|
- **Healthcare:** Clinical decision support, drug interaction graphs, and patient safety audit trails
|
||||||
|
- **Legal:** Evidence-backed research, contract analysis, case law reasoning, and privilege tracking
|
||||||
|
- **Government & Defense:** Policy decision records, classified information governance, and regulatory reporting, fully self-hosted with no data leaving your perimeter
|
||||||
|
- **Law Enforcement:** Case linkage, evidence provenance chains, and investigative knowledge graphs that hold up under legal scrutiny
|
||||||
|
- **Cybersecurity:** Threat attribution, incident response timelines, and IOC provenance tracking
|
||||||
|
- **Autonomous Systems:** Decision logs, safety validation, and explainable AI for certification
|
||||||
|
|
||||||
|
> ⚠️ **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. In short, Semantica explains and audits what the AI system did, not the LLM's private internal reasoning.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
## Installation
|
## Installation
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
pip install semantica # lightweight core (22 essential dependencies)
|
pip install semantica # core
|
||||||
pip install "semantica[all]" # full bundled behavior with all extras
|
pip install semantica[all] # everything
|
||||||
```
|
```
|
||||||
|
|
||||||
> **Note:** Heavy machine learning, NLP, visualization, and document dependencies live in optional extras to keep core installation lightweight and fast. If you want the previous bundled installation, install with `pip install "semantica[all]"`.
|
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
# Granular Extras
|
pip install semantica[agno] # Agno multi-agent integration
|
||||||
pip install "semantica[documents]" # Document parsing (docx, openpyxl, lxml, beautifulsoup4)
|
pip install semantica[crewai] # CrewAI integration
|
||||||
pip install "semantica[embeddings-local]" # Local embeddings (sentence-transformers, fastembed, onnxruntime)
|
pip install semantica[langchain] # LangChain / LangGraph integration
|
||||||
pip install "semantica[models-huggingface]" # HuggingFace models (transformers, torch)
|
pip install semantica[llm-litellm] # OpenAI, Anthropic, Gemini, Mistral, Llama, Groq, Cohere, Bedrock, Ollama, DeepSeek, and more
|
||||||
pip install "semantica[nlp-spacy]" # spaCy NLP pipelines (spacy)
|
pip install semantica[graph-neo4j] # Neo4j graph store (LPG)
|
||||||
pip install "semantica[viz]" # Visualization (matplotlib, seaborn, plotly, pyvis, graphviz)
|
pip install semantica[graph-falkordb] # FalkorDB graph store (LPG)
|
||||||
pip install "semantica[media]" # Audio & computer vision (librosa, opencv-python)
|
pip install semantica[graph-apache-age] # Apache AGE graph store (LPG)
|
||||||
pip install "semantica[graph-embeddings]" # Knowledge graph embeddings (gensim / Node2Vec)
|
pip install semantica[graph-amazon-neptune] # AWS Neptune graph store (LPG)
|
||||||
pip install "semantica[ingest-git]" # Git repository ingestor (GitPython)
|
pip install semantica[tripletstore-oxigraph] # Embedded in-memory/on-disk RDF store
|
||||||
pip install "semantica[vectorstore-faiss]" # FAISS vector store
|
|
||||||
pip install "semantica[vectorstore-all]" # All vector stores (Qdrant, Pinecone, Weaviate, FAISS, PgVector, SQLite)
|
|
||||||
pip install "semantica[agno]" # Agno multi-agent integration
|
|
||||||
pip install "semantica[crewai]" # CrewAI integration
|
|
||||||
pip install "semantica[langchain]" # LangChain / LangGraph integration
|
|
||||||
pip install "semantica[llm-all]" # All LLM provider clients
|
|
||||||
pip install "semantica[graph-neo4j]" # Neo4j graph store (LPG)
|
|
||||||
pip install "semantica[graph-falkordb]" # FalkorDB graph store (LPG)
|
|
||||||
pip install "semantica[graph-apache-age]" # Apache AGE graph store (LPG)
|
|
||||||
pip install "semantica[graph-amazon-neptune]" # AWS Neptune graph store (LPG)
|
|
||||||
pip install "semantica[tripletstore-oxigraph]" # Embedded in-memory/on-disk RDF store
|
|
||||||
# RDF triple stores (Blazegraph, Apache Jena, Eclipse RDF4J) need no extra:
|
# RDF triple stores (Blazegraph, Apache Jena, Eclipse RDF4J) need no extra:
|
||||||
# semantica.triplet_store talks SPARQL over HTTP using the core `requests` dependency
|
# semantica.triplet_store talks SPARQL over HTTP using the core `requests` dependency
|
||||||
pip install "semantica[db-snowflake]" # Snowflake
|
pip install semantica[vectorstore-qdrant] # Qdrant vector store
|
||||||
pip install "semantica[db-databricks]" # Databricks (SDK + SQL connector)
|
pip install semantica[vectorstore-pinecone] # Pinecone vector store
|
||||||
pip install "semantica[ingest-sap]" # SAP OData
|
pip install semantica[db-snowflake] # Snowflake
|
||||||
pip install "semantica[ingest-parquet]" # Parquet / PyArrow
|
pip install semantica[db-databricks] # Databricks (SDK + SQL connector)
|
||||||
pip install "semantica[ingest-arrow]" # Apache Arrow, Feather, IPC
|
pip install semantica[ingest-sap] # SAP OData
|
||||||
pip install "semantica[watch]" # Directory file watcher
|
pip install semantica[ingest-parquet] # Parquet / PyArrow
|
||||||
pip install "semantica[explorer]" # Knowledge Explorer dashboard
|
pip install semantica[ingest-arrow] # Apache Arrow, Feather, IPC
|
||||||
|
pip install semantica[viz] # HTML interactive visualization
|
||||||
|
pip install semantica[watch] # Directory file watcher
|
||||||
|
pip install semantica[explorer] # Knowledge Explorer dashboard
|
||||||
```
|
```
|
||||||
|
|
||||||
For production deployments, use Docker or Kubernetes rather than a local `pip install`. Set `SEMANTICA_API_KEY`, configure a persistent LPG graph store (Neo4j / FalkorDB / Apache AGE / AWS Neptune) and/or RDF triple store (Blazegraph / Apache Jena / Eclipse RDF4J), and point the vector store at a hosted backend (Qdrant / Pinecone). See [ARCHITECTURE.md](ARCHITECTURE.md) for the full deployment topology.
|
For production deployments, use Docker or Kubernetes rather than a local `pip install`. Set `SEMANTICA_SECRET_KEY`, configure a persistent LPG graph store (Neo4j / FalkorDB / Apache AGE / AWS Neptune) and/or RDF triple store (Blazegraph / Apache Jena / Eclipse RDF4J), and point the vector store at a hosted backend (Qdrant / Pinecone). See [ARCHITECTURE.md](ARCHITECTURE.md) for the full deployment topology.
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
# From source
|
# From source
|
||||||
|
|||||||
@@ -149,25 +149,25 @@ registry.register_plugin("my_plugin", MyPlugin, version="1.0.0")
|
|||||||
|
|
||||||
<Accordion title="Modularity: use only what you need" icon="puzzle-piece">
|
<Accordion title="Modularity: use only what you need" icon="puzzle-piece">
|
||||||
|
|
||||||
Every component works standalone. `NERExtractor` runs without a graph store. `VectorStore` runs without decision tracking. The framework never forces a full stack instantiation; you pay only for what you import.
|
Every component works standalone. `NERExtractor` runs without a graph store. `VectorStore` runs without decision tracking. The framework never forces a full stack instantiation: you pay only for what you import.
|
||||||
|
|
||||||
</Accordion>
|
</Accordion>
|
||||||
|
|
||||||
<Accordion title="Pluggability: extend without modifying core" icon="plug">
|
<Accordion title="Pluggability: extend without modifying core" icon="plug">
|
||||||
|
|
||||||
Custom ingestors, extractors, validators, and exporters follow the same base class pattern. Register them via `PluginRegistry` and they participate in the full pipeline (provenance tracking, retry policies, and parallel execution included) with no changes to core code.
|
Custom ingestors, extractors, validators, and exporters follow the same base class pattern. Register them via `PluginRegistry` and they participate in the full pipeline: provenance tracking, retry policies, and parallel execution included: with no changes to core code.
|
||||||
|
|
||||||
</Accordion>
|
</Accordion>
|
||||||
|
|
||||||
<Accordion title="Provenance by default" icon="link">
|
<Accordion title="Provenance by default" icon="link">
|
||||||
|
|
||||||
Lineage tracking is built into graph construction at the lowest level. Every node and edge carries a `source_id` pointing back to the originating document, extraction method, and timestamp. There is no opt-in required; provenance is always on.
|
Lineage tracking is built into graph construction at the lowest level. Every node and edge carries a `source_id` pointing back to the originating document, extraction method, and timestamp. There's no opt-in required: provenance is always on.
|
||||||
|
|
||||||
</Accordion>
|
</Accordion>
|
||||||
|
|
||||||
<Accordion title="Configuration over convention" icon="sliders">
|
<Accordion title="Configuration over convention" icon="sliders">
|
||||||
|
|
||||||
Centralized `ConfigManager` with environment variable overrides. No magic defaults; all behavior is explicit and overridable. Suitable for multi-environment deployments where dev, staging, and production need different backends.
|
Centralized `ConfigManager` with environment variable overrides. No magic defaults: all behavior is explicit and overridable. Suitable for multi-environment deployments where dev, staging, and production need different backends.
|
||||||
|
|
||||||
</Accordion>
|
</Accordion>
|
||||||
|
|
||||||
@@ -179,13 +179,13 @@ Centralized `ConfigManager` with environment variable overrides. No magic defaul
|
|||||||
| Characteristic | Mechanism |
|
| Characteristic | Mechanism |
|
||||||
| :-------------- | :--------- |
|
| :-------------- | :--------- |
|
||||||
| **Parallel execution** | `Pipeline(workers=N)` with configurable workers per stage |
|
| **Parallel execution** | `Pipeline(workers=N)` with configurable workers per stage |
|
||||||
| **Delta processing** | Incremental graph updates (no full recompute on new data) |
|
| **Delta processing** | Incremental graph updates: no full recompute on new data |
|
||||||
| **Streaming ingestion** | Process large corpora without loading everything into memory |
|
| **Streaming ingestion** | Process large corpora without loading everything into memory |
|
||||||
| **Backend flexibility** | Swap in-memory NetworkX for Neo4j / FalkorDB with no API changes |
|
| **Backend flexibility** | Swap in-memory NetworkX for Neo4j / FalkorDB with no API changes |
|
||||||
| **Deduplication v2** | `blocking_v2`, `hybrid_v2`, `semantic_v2`: up to 7x faster than v1 |
|
| **Deduplication v2** | `blocking_v2`, `hybrid_v2`, `semantic_v2`: up to 7x faster than v1 |
|
||||||
| **Indexed search** | Explorer search at 0.004ms on 118k nodes (v0.5.0) |
|
| **Indexed search** | Explorer search at 0.004ms on 118k nodes (v0.5.0) |
|
||||||
|
|
||||||
- [Modules](/modules): full module documentation with code examples.
|
- [Modules](/modules) — Full module documentation with code examples.
|
||||||
- [Learning More](/learning-more): configuration reference, performance guide, and troubleshooting.
|
- [Learning More](/learning-more) — Configuration reference, performance guide, and troubleshooting.
|
||||||
- [Pipeline Reference](/reference/pipeline): pipeline orchestration, workers, and retry policies.
|
- [Pipeline Reference](/reference/pipeline) — Pipeline orchestration, workers, and retry policies.
|
||||||
- [Core Reference](/reference/core): framework lifecycle, plugin registry, and configuration.
|
- [Core Reference](/reference/core) — Framework lifecycle, plugin registry, and configuration.
|
||||||
|
|||||||
+183
-4
@@ -1,9 +1,14 @@
|
|||||||
/* ============================================================
|
/* ============================================================
|
||||||
SEMANTICA DOCS — DESIGN SYSTEM
|
SEMANTICA DOCS — PREMIUM DESIGN SYSTEM
|
||||||
Dark-first (#080C10 bg, #10B981 emerald accent)
|
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 ─────────────────────────────────────────────────── */
|
/* ── Global ─────────────────────────────────────────────────── */
|
||||||
html {
|
html {
|
||||||
scroll-behavior: smooth;
|
scroll-behavior: smooth;
|
||||||
@@ -24,7 +29,16 @@ html {
|
|||||||
}
|
}
|
||||||
::-webkit-scrollbar-thumb:hover { background: rgba(16, 185, 129, 0.4); }
|
::-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 {
|
*:focus-visible {
|
||||||
outline: 2px solid rgba(16, 185, 129, 0.55) !important;
|
outline: 2px solid rgba(16, 185, 129, 0.55) !important;
|
||||||
outline-offset: 3px !important;
|
outline-offset: 3px !important;
|
||||||
@@ -45,7 +59,7 @@ h1::after {
|
|||||||
left: 0;
|
left: 0;
|
||||||
width: 44px;
|
width: 44px;
|
||||||
height: 2px;
|
height: 2px;
|
||||||
background: #10B981;
|
background: linear-gradient(90deg, #10B981 0%, transparent 100%);
|
||||||
border-radius: 1px;
|
border-radius: 1px;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -57,6 +71,9 @@ article a,
|
|||||||
[class*="prose"] a {
|
[class*="prose"] a {
|
||||||
text-decoration-color: rgba(16, 185, 129, 0.35);
|
text-decoration-color: rgba(16, 185, 129, 0.35);
|
||||||
text-underline-offset: 3px;
|
text-underline-offset: 3px;
|
||||||
|
transition:
|
||||||
|
text-decoration-color 0.15s ease,
|
||||||
|
color 0.15s ease;
|
||||||
}
|
}
|
||||||
|
|
||||||
article a:hover,
|
article a:hover,
|
||||||
@@ -72,6 +89,14 @@ blockquote {
|
|||||||
padding: 0.9rem 1.2rem !important;
|
padding: 0.9rem 1.2rem !important;
|
||||||
font-style: italic;
|
font-style: italic;
|
||||||
color: rgba(255, 255, 255, 0.68) !important;
|
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 ────────────────────────────────────────────── */
|
/* ── HR / Divider ────────────────────────────────────────────── */
|
||||||
@@ -98,11 +123,165 @@ table thead th {
|
|||||||
border-bottom: 1px solid rgba(16, 185, 129, 0.18) !important;
|
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 ────────────────────────────────────── */
|
/* ── NAVIGATION / SIDEBAR ────────────────────────────────────── */
|
||||||
nav a,
|
nav a,
|
||||||
[class*="sidebar"] a,
|
[class*="sidebar"] a,
|
||||||
[class*="Sidebar"] a {
|
[class*="Sidebar"] a {
|
||||||
|
transition: color 0.15s ease !important;
|
||||||
text-decoration: none;
|
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 ───────────────────────────────────────── */
|
/* ── HIDE THEME TOGGLE ───────────────────────────────────────── */
|
||||||
|
|||||||
+19
-19
@@ -5,7 +5,7 @@ icon: "compass"
|
|||||||
---
|
---
|
||||||
|
|
||||||
<Info>
|
<Info>
|
||||||
Every module works independently: import only what you need. This page maps developer goals to starting points. The [Module Reference](/modules) covers every module in depth.
|
Every module works independently — import only what you need. This page maps developer goals to starting points. The [Module Reference](/modules) covers every module in depth.
|
||||||
</Info>
|
</Info>
|
||||||
|
|
||||||
## Quick Reference
|
## Quick Reference
|
||||||
@@ -75,7 +75,7 @@ Pick your goal to see the minimum imports and a working skeleton.
|
|||||||
sources = FileIngestor().ingest("report.pdf")
|
sources = FileIngestor().ingest("report.pdf")
|
||||||
parsed = DocumentParser().parse_document("report.pdf")
|
parsed = DocumentParser().parse_document("report.pdf")
|
||||||
|
|
||||||
# No API key required: pattern-based extraction
|
# No API key required — pattern-based extraction
|
||||||
entities = NERExtractor(method="pattern").extract(parsed)
|
entities = NERExtractor(method="pattern").extract(parsed)
|
||||||
relationships = RelationExtractor(method="rule").extract(parsed, entities=entities)
|
relationships = RelationExtractor(method="rule").extract(parsed, entities=entities)
|
||||||
|
|
||||||
@@ -89,7 +89,7 @@ Pick your goal to see the minimum imports and a working skeleton.
|
|||||||
Pass `method="pattern"` to `NERExtractor` for zero-cost, zero-API-key extraction. Switch to `method="llm"` with any of the supported providers for higher recall.
|
Pass `method="pattern"` to `NERExtractor` for zero-cost, zero-API-key extraction. Switch to `method="llm"` with any of the supported providers for higher recall.
|
||||||
</Tip>
|
</Tip>
|
||||||
|
|
||||||
See the [Quickstart →](/quickstart) for a full pipeline with visualization and export.
|
**Next:** [Quickstart →](/quickstart) — full pipeline with visualization and export.
|
||||||
</Tab>
|
</Tab>
|
||||||
|
|
||||||
<Tab title="Build GraphRAG">
|
<Tab title="Build GraphRAG">
|
||||||
@@ -109,7 +109,7 @@ Pick your goal to see the minimum imports and a working skeleton.
|
|||||||
knowledge_graph=ContextGraph(advanced_analytics=True),
|
knowledge_graph=ContextGraph(advanced_analytics=True),
|
||||||
)
|
)
|
||||||
|
|
||||||
# Store facts: retrieval uses both vectors and graph structure
|
# Store facts — retrieval uses both vectors and graph structure
|
||||||
context.store("Apple Inc. was co-founded by Steve Jobs in 1976 in Cupertino.")
|
context.store("Apple Inc. was co-founded by Steve Jobs in 1976 in Cupertino.")
|
||||||
|
|
||||||
# GraphRAG query with multi-hop reasoning trace
|
# GraphRAG query with multi-hop reasoning trace
|
||||||
@@ -206,11 +206,11 @@ Pick your goal to see the minimum imports and a working skeleton.
|
|||||||
```python
|
```python
|
||||||
from semantica.export import RDFExporter, ParquetExporter, LPGExporter, ArangoAQLExporter
|
from semantica.export import RDFExporter, ParquetExporter, LPGExporter, ArangoAQLExporter
|
||||||
|
|
||||||
# RDF: multiple serialization formats
|
# RDF — multiple serialization formats
|
||||||
RDFExporter().export(graph, "graph.ttl", format="turtle")
|
RDFExporter().export(graph, "graph.ttl", format="turtle")
|
||||||
RDFExporter().export(graph, "graph.jsonld", format="jsonld")
|
RDFExporter().export(graph, "graph.jsonld", format="jsonld")
|
||||||
|
|
||||||
# Parquet: for Spark, BigQuery, Databricks, Snowflake
|
# Parquet — for Spark, BigQuery, Databricks, Snowflake
|
||||||
ParquetExporter().export(graph, "output/graph.parquet")
|
ParquetExporter().export(graph, "output/graph.parquet")
|
||||||
|
|
||||||
# Neo4j / Memgraph via Cypher
|
# Neo4j / Memgraph via Cypher
|
||||||
@@ -225,15 +225,15 @@ Pick your goal to see the minimum imports and a working skeleton.
|
|||||||
**Next:** [Export module reference →](/reference/export)
|
**Next:** [Export module reference →](/reference/export)
|
||||||
</Tab>
|
</Tab>
|
||||||
|
|
||||||
<Tab title="MCP: Claude / Cursor">
|
<Tab title="MCP — Claude / Cursor">
|
||||||
Use Semantica from Claude Desktop, Cursor, VS Code, or any MCP-aware tool; no Python code required after setup. 15 tools are available.
|
Use Semantica from Claude Desktop, Cursor, VS Code, or any MCP-aware tool — no Python code required after setup. 15 tools available instantly.
|
||||||
|
|
||||||
**Step 1: Install**
|
**Step 1 — Install:**
|
||||||
```bash
|
```bash
|
||||||
pip install semantica
|
pip install semantica
|
||||||
```
|
```
|
||||||
|
|
||||||
**Step 2: Add to your MCP client config**
|
**Step 2 — Add to your MCP client config:**
|
||||||
|
|
||||||
<CodeGroup>
|
<CodeGroup>
|
||||||
|
|
||||||
@@ -273,10 +273,10 @@ Pick your goal to see the minimum imports and a working skeleton.
|
|||||||
</Tabs>
|
</Tabs>
|
||||||
|
|
||||||
|
|
||||||
## Architecture Selection Guidance
|
## Still Unsure?
|
||||||
|
|
||||||
<AccordionGroup>
|
<AccordionGroup>
|
||||||
<Accordion title="Knowledge graph vs. vector store selection" icon="scale-balanced">
|
<Accordion title="Knowledge graph vs. vector store — which do I need?" icon="scale-balanced">
|
||||||
Use a **knowledge graph** (`kg`) when you need structured reasoning, multi-hop traversal, provenance, or compliance audit trails.
|
Use a **knowledge graph** (`kg`) when you need structured reasoning, multi-hop traversal, provenance, or compliance audit trails.
|
||||||
|
|
||||||
Use a **vector store** (`vector_store`) when you need fast fuzzy similarity search over large text corpora and relationships between items don't matter.
|
Use a **vector store** (`vector_store`) when you need fast fuzzy similarity search over large text corpora and relationships between items don't matter.
|
||||||
@@ -286,12 +286,12 @@ Pick your goal to see the minimum imports and a working skeleton.
|
|||||||
See also: [Core Concepts](/concepts)
|
See also: [Core Concepts](/concepts)
|
||||||
</Accordion>
|
</Accordion>
|
||||||
|
|
||||||
<Accordion title="Fast local pipeline setup" icon="rocket">
|
<Accordion title="I just want to run something quickly." icon="rocket">
|
||||||
Start with the [Quickstart](/quickstart). It builds a complete pipeline (ingest → parse → extract → graph → visualize → export) with no API key required.
|
Start with the [Quickstart](/quickstart). It builds a complete pipeline (ingest → parse → extract → graph → visualize → export) with no API key required.
|
||||||
</Accordion>
|
</Accordion>
|
||||||
|
|
||||||
<Accordion title="Minimum configuration for existing agents" icon="plug">
|
<Accordion title="I'm adding Semantica to an existing agent — what's the minimum?" icon="plug">
|
||||||
Add `AgentContext` to equip an existing agent with memory, decision tracking, and precedent search, with no changes to your LLM provider or agent framework required.
|
Add `AgentContext`. It wraps your existing agent with memory, decision tracking, and precedent search — no changes to your LLM provider or agent framework needed.
|
||||||
|
|
||||||
```python
|
```python
|
||||||
from semantica.context import AgentContext, ContextGraph
|
from semantica.context import AgentContext, ContextGraph
|
||||||
@@ -307,7 +307,7 @@ Pick your goal to see the minimum imports and a working skeleton.
|
|||||||
[Context module reference →](/reference/context)
|
[Context module reference →](/reference/context)
|
||||||
</Accordion>
|
</Accordion>
|
||||||
|
|
||||||
<Accordion title="Minimum stack for compliance-ready pipelines" icon="shield-check">
|
<Accordion title="I need a compliance-ready pipeline — what's the minimum stack?" icon="shield-check">
|
||||||
| Layer | Module | Key class |
|
| Layer | Module | Key class |
|
||||||
| :---- | :------ | :--------- |
|
| :---- | :------ | :--------- |
|
||||||
| Ingestion | `ingest` | `FileIngestor` |
|
| Ingestion | `ingest` | `FileIngestor` |
|
||||||
@@ -322,6 +322,6 @@ Pick your goal to see the minimum imports and a working skeleton.
|
|||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
- [Quickstart](/quickstart): full pipeline in 5 minutes.
|
- [Quickstart](/quickstart) — Full pipeline in 5 minutes.
|
||||||
- [Module Reference](/modules): every module with examples and common chains.
|
- [Module Reference](/modules) — Every module with examples and common chains.
|
||||||
- [API Reference](/reference/context): complete class and method documentation.
|
- [API Reference](/reference/context) — Complete class and method documentation.
|
||||||
|
|||||||
+3
-3
@@ -43,10 +43,10 @@ icon: "quote-left"
|
|||||||
|
|
||||||
## Share Your Research
|
## Share Your Research
|
||||||
|
|
||||||
If you publish research using Semantica, [let us know](https://github.com/semantica-agi/semantica/issues) so we can feature your work.
|
Published research using Semantica? [Let us know](https://github.com/semantica-agi/semantica/issues): we may feature your work.
|
||||||
|
|
||||||
|
|
||||||
## See Also
|
## See Also
|
||||||
|
|
||||||
- [License](/project-license): MIT License details.
|
- [License](/project-license) — MIT License details.
|
||||||
- [Community](/community): connect with the Semantica community.
|
- [Community](/community) — Connect with the Semantica community.
|
||||||
|
|||||||
+11
-11
@@ -18,7 +18,7 @@ After installation the following commands are available:
|
|||||||
| Command | Entry point | What it does |
|
| Command | Entry point | What it does |
|
||||||
| :------- | :----------- | :------------ |
|
| :------- | :----------- | :------------ |
|
||||||
| `semantica` | `semantica.cli:main` | General-purpose CLI for pipeline runs, extraction, and graph operations |
|
| `semantica` | `semantica.cli:main` | General-purpose CLI for pipeline runs, extraction, and graph operations |
|
||||||
| `semantica-server` | `semantica.server:main` | FastAPI/uvicorn REST API server bound to `127.0.0.1:8000` by default (set `SEMANTICA_HOST` to override) |
|
| `semantica-server` | `semantica.server:main` | FastAPI/uvicorn REST API server bound to `0.0.0.0:8000` |
|
||||||
| `semantica-worker` | `semantica.worker:main` | Background worker process entry point for Semantica deployments |
|
| `semantica-worker` | `semantica.worker:main` | Background worker process entry point for Semantica deployments |
|
||||||
| `semantica-explorer` | `semantica.explorer:main` | Interactive browser dashboard for knowledge graph exploration |
|
| `semantica-explorer` | `semantica.explorer:main` | Interactive browser dashboard for knowledge graph exploration |
|
||||||
| `semantica-mcp` | `semantica.mcp_server:main` | MCP server (stdio) for Claude Desktop, Cursor, Windsurf, and other MCP clients |
|
| `semantica-mcp` | `semantica.mcp_server:main` | MCP server (stdio) for Claude Desktop, Cursor, Windsurf, and other MCP clients |
|
||||||
@@ -49,11 +49,11 @@ python -c "import semantica; print(semantica.__version__)"
|
|||||||
|
|
||||||
## When to Use Each Command
|
## When to Use Each Command
|
||||||
|
|
||||||
- **semantica**: general-purpose CLI. Use it for one-off pipeline runs, entity extraction, and graph operations from a shell script or CI job.
|
- **semantica** — The general-purpose CLI. Use it for one-off pipeline runs, entity extraction, and graph operations from a shell script or CI job.
|
||||||
- **semantica-server**: starts the REST API server. Binds to `127.0.0.1:8000` by default; set `SEMANTICA_HOST` to expose beyond localhost. Use this when another service or application needs programmatic access to Semantica over HTTP.
|
- **semantica-server** — Starts the REST API server. Binds to `0.0.0.0:8000`. Use this when another service or application needs programmatic access to Semantica over HTTP.
|
||||||
- **semantica-worker**: background task processor. Run alongside `semantica-server` when you need async pipeline execution outside the request cycle. Start the server first, then start one or more workers pointing at the same backend.
|
- **semantica-worker** — Background task processor. Run alongside `semantica-server` when you need async pipeline execution outside the request cycle. Start the server first, then start one or more workers pointing at the same backend.
|
||||||
- **semantica-explorer**: launches the browser dashboard. Requires `pip install semantica[explorer]`. Use this to explore a saved knowledge graph interactively. See [Explorer Setup](/explorer-setup).
|
- **semantica-explorer** — Launches the browser dashboard. Requires `pip install semantica[explorer]`. Use this to explore a saved knowledge graph interactively. See [Explorer Setup](/explorer-setup).
|
||||||
- **semantica-mcp**: runs the MCP server over stdio. Configure it in your MCP client's settings file to expose all 15 tools and 3 resources to Claude Desktop, Cursor, Windsurf, or any MCP-aware client. See [MCP Server](/reference/mcp_server).
|
- **semantica-mcp** — Runs the MCP server over stdio. Configure it in your MCP client's settings file to expose all 15 tools and 3 resources to Claude Desktop, Cursor, Windsurf, or any MCP-aware client. See [MCP Server](/reference/mcp_server).
|
||||||
|
|
||||||
|
|
||||||
## Usage Examples
|
## Usage Examples
|
||||||
@@ -61,7 +61,7 @@ python -c "import semantica; print(semantica.__version__)"
|
|||||||
<Tabs>
|
<Tabs>
|
||||||
<Tab title="REST server">
|
<Tab title="REST server">
|
||||||
```bash
|
```bash
|
||||||
# Starts FastAPI + uvicorn on 127.0.0.1:8000 (set SEMANTICA_HOST to change)
|
# Starts FastAPI + uvicorn on 0.0.0.0:8000
|
||||||
semantica-server
|
semantica-server
|
||||||
```
|
```
|
||||||
|
|
||||||
@@ -228,7 +228,7 @@ Install the [Microsoft Visual C++ Redistributable](https://aka.ms/vs/17/release/
|
|||||||
|
|
||||||
## Next Steps
|
## Next Steps
|
||||||
|
|
||||||
- [Explorer Setup](/explorer-setup): build a graph, save it, and launch the browser dashboard.
|
- [Explorer Setup](/explorer-setup) — Build a graph, save it, and launch the browser dashboard.
|
||||||
- [MCP Server](/reference/mcp_server): all 15 tools and 3 resources exposed over the MCP protocol.
|
- [MCP Server](/reference/mcp_server) — All 15 tools and 3 resources exposed over the MCP protocol.
|
||||||
- [Installation](/installation): virtual environments, optional extras, and platform-specific notes.
|
- [Installation](/installation) — Virtual environments, optional extras, and platform-specific notes.
|
||||||
- [Quickstart](/quickstart): end-to-end pipeline walkthrough with working code.
|
- [Quickstart](/quickstart) — End-to-end pipeline walkthrough with working code.
|
||||||
|
|||||||
@@ -66,12 +66,12 @@ Production deployments span regulated and high-stakes industries where AI accoun
|
|||||||
| :-------- | :---- |
|
| :-------- | :---- |
|
||||||
| **OpenAI** | GPT-4o, GPT-4, GPT-3.5 |
|
| **OpenAI** | GPT-4o, GPT-4, GPT-3.5 |
|
||||||
| **Anthropic** | Claude Opus, Sonnet, Haiku |
|
| **Anthropic** | Claude Opus, Sonnet, Haiku |
|
||||||
| **Google Gemini** | Gemini Pro and other Gemini models |
|
| **Google Gemini** |: |
|
||||||
| **Groq** | LLaMA, Mixtral (fast inference) |
|
| **Groq** | LLaMA, Mixtral: fast inference |
|
||||||
| **Ollama** | Fully local, air-gapped |
|
| **Ollama** | Fully local, air-gapped |
|
||||||
| **HuggingFace** | Transformers-based local LLM models |
|
| **HuggingFace** |: |
|
||||||
| **DeepSeek** | deepseek-chat and reasoning models |
|
| **DeepSeek** |: |
|
||||||
| **Novita AI** | OpenAI-compatible gateway, DeepSeek-V3.2 default |
|
| **Novita AI** |: |
|
||||||
| **LiteLLM** | 100+ model gateway |
|
| **LiteLLM** | 100+ model gateway |
|
||||||
</Tab>
|
</Tab>
|
||||||
<Tab title="NLP Libraries">
|
<Tab title="NLP Libraries">
|
||||||
@@ -114,7 +114,7 @@ See [Architecture](/architecture#extension-points) for the full extension guide.
|
|||||||
|
|
||||||
## How to Contribute
|
## How to Contribute
|
||||||
|
|
||||||
- [Contributing Guide](/contributing-guide): submit code, documentation, tests, or cookbook notebooks.
|
- [Contributing Guide](/contributing-guide) — Submit code, documentation, tests, or cookbook notebooks.
|
||||||
- [GitHub Issues](https://github.com/semantica-agi/semantica/issues): report bugs, request features, or propose integrations.
|
- [GitHub Issues](https://github.com/semantica-agi/semantica/issues) — Report bugs, request features, or propose integrations.
|
||||||
- [Discord](https://discord.gg/sV34vps5hH): share what you're building with the community.
|
- [Discord](https://discord.gg/sV34vps5hH) — Share what you're building with the community.
|
||||||
- [GitHub Discussions](https://github.com/semantica-agi/semantica/discussions): long-form questions, design discussions, and ideas.
|
- [GitHub Discussions](https://github.com/semantica-agi/semantica/discussions) — Long-form questions, design discussions, and ideas.
|
||||||
|
|||||||
+8
-8
@@ -9,10 +9,10 @@ Semantica is built in the open, with contributions from researchers, engineers,
|
|||||||
|
|
||||||
## Get Help
|
## Get Help
|
||||||
|
|
||||||
- [GitHub Issues](https://github.com/semantica-agi/semantica/issues): file bug reports and feature requests with full context.
|
- [GitHub Issues](https://github.com/semantica-agi/semantica/issues) — File bug reports and feature requests with full context.
|
||||||
- [GitHub Discussions](https://github.com/semantica-agi/semantica/discussions): ask questions, share ideas, and discuss design decisions.
|
- [GitHub Discussions](https://github.com/semantica-agi/semantica/discussions) — Ask questions, share ideas, and discuss design decisions.
|
||||||
- [Pull Requests](https://github.com/semantica-agi/semantica/pulls): browse open contributions and submit your own.
|
- [Pull Requests](https://github.com/semantica-agi/semantica/pulls) — Browse open contributions and submit your own.
|
||||||
- [Security Issues](https://github.com/semantica-agi/semantica/security/advisories/new): report vulnerabilities privately (never in public issues).
|
- [Security Issues](https://github.com/semantica-agi/semantica/security/advisories/new) — Report vulnerabilities privately: never in public issues.
|
||||||
|
|
||||||
|
|
||||||
## Community Guidelines
|
## Community Guidelines
|
||||||
@@ -68,7 +68,7 @@ See the [Contributing Guide](/contributing-guide) for the full development workf
|
|||||||
|
|
||||||
## See Also
|
## See Also
|
||||||
|
|
||||||
- [Contributing Guide](/contributing-guide): step-by-step guide for submitting PRs and setting up your dev environment.
|
- [Contributing Guide](/contributing-guide) — Step-by-step guide for submitting PRs and setting up your dev environment.
|
||||||
- [Community Projects](/community-projects): projects and integrations built by the community.
|
- [Community Projects](/community-projects) — Projects and integrations built by the community.
|
||||||
- [FAQ](/faq): common questions answered.
|
- [FAQ](/faq) — Common questions answered.
|
||||||
- [Governance](/governance): how the project is run and decisions are made.
|
- [Governance](/governance) — How the project is run and decisions are made.
|
||||||
|
|||||||
+90
-121
@@ -8,16 +8,16 @@ icon: "book-open"
|
|||||||
New here? Start with [Getting Started](/getting-started) for hands-on examples, then return here for deeper understanding.
|
New here? Start with [Getting Started](/getting-started) for hands-on examples, then return here for deeper understanding.
|
||||||
</Info>
|
</Info>
|
||||||
|
|
||||||
Semantica transforms unstructured data (documents, web pages, reports, databases) into **knowledge graphs**: structured representations that AI systems can query, reason about, and trace back to sources.
|
Semantica transforms unstructured data: documents, web pages, reports, databases: into **knowledge graphs**: structured representations that AI systems can query, reason about, and trace back to sources.
|
||||||
|
|
||||||
At its core, Semantica adds a context and semantic layer on top of your existing AI stack. It doesn't replace LangChain, LlamaIndex, or your LLM provider. It makes their outputs grounded, traceable, and auditable.
|
At its core, Semantica adds a **context and accountability layer** on top of your existing AI stack. It doesn't replace LangChain, LlamaIndex, or your LLM provider: it makes their outputs **grounded**, **traceable**, and **auditable**.
|
||||||
|
|
||||||
- **Context Layer.** Knowledge graphs, GraphRAG retrieval, semantic embeddings, and temporal intelligence ground every LLM response in structured, queryable facts.
|
- **Context Layer** — Knowledge graphs, GraphRAG retrieval, semantic embeddings, and temporal intelligence ground every LLM response in structured, queryable facts.
|
||||||
- **Accountability Layer.** Provenance tracking, decision intelligence, conflict detection, and W3C PROV-O compliance make every claim in your AI stack auditable and explainable.
|
- **Accountability Layer** — Provenance tracking, decision intelligence, conflict detection, and W3C PROV-O compliance make every claim in your AI stack auditable and explainable.
|
||||||
- **Extension Layer.** `PluginRegistry` and `MethodRegistry` let you replace or augment any component (ingestors, extractors, reasoning engines, backends) without changing framework code.
|
- **Extension Layer** — `PluginRegistry` and `MethodRegistry` let you replace or augment any component: ingestors, extractors, reasoning engines, backends: without changing framework code.
|
||||||
|
|
||||||
<Warning>
|
<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. In short, Semantica explains and audits *what the AI system did*, not the foundation model's private internal reasoning.
|
**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. In short, Semantica explains and audits *what the AI system did*, not the foundation model's private internal reasoning.
|
||||||
</Warning>
|
</Warning>
|
||||||
|
|
||||||
## Knowledge Graphs
|
## Knowledge Graphs
|
||||||
@@ -30,7 +30,7 @@ The foundation of everything in Semantica. A knowledge graph stores information
|
|||||||
- **Edges (relationships)**: `works_for`, `located_in`, `founded_by`
|
- **Edges (relationships)**: `works_for`, `located_in`, `founded_by`
|
||||||
- **Properties**: name, date, confidence score, source URL
|
- **Properties**: name, date, confidence score, source URL
|
||||||
|
|
||||||
This structure makes knowledge searchable, connectable, and queryable. Critically, it's explainable: every answer can be traced back to the facts and relationships that produced it.
|
This structure makes knowledge **searchable**, **connectable**, **queryable**, and: critically: **explainable**: every answer can be traced back to the facts and relationships that produced it.
|
||||||
|
|
||||||
|
|
||||||
## Entity Extraction (NER)
|
## Entity Extraction (NER)
|
||||||
@@ -38,19 +38,18 @@ This structure makes knowledge searchable, connectable, and queryable. Criticall
|
|||||||
Scanning text to find and classify real-world entities:
|
Scanning text to find and classify real-world entities:
|
||||||
|
|
||||||
```python
|
```python
|
||||||
# "Apple Inc. was founded by Steve Jobs in 1976 in Cupertino."
|
# Input: "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),
|
"entities": [
|
||||||
Entity(text="Steve Jobs", label="PERSON", start_char=25, end_char=35, confidence=0.99),
|
{"text": "Apple Inc.", "type": "ORGANIZATION", "confidence": 0.98},
|
||||||
Entity(text="1976", label="DATE", start_char=39, end_char=43, confidence=0.95),
|
{"text": "Steve Jobs", "type": "PERSON", "confidence": 0.99},
|
||||||
Entity(text="Cupertino", label="GPE", start_char=47, end_char=56, confidence=0.97),
|
{"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
|
Each entity gets a type, confidence score, and a link to its source document. Three extraction methods are available:
|
||||||
with a `label`, character offsets (`start_char` / `end_char`), a `confidence`
|
|
||||||
score, and a `metadata` dict recording the extraction method. Three methods are
|
|
||||||
available:
|
|
||||||
|
|
||||||
| Method | Speed | Accuracy | Requirements |
|
| Method | Speed | Accuracy | Requirements |
|
||||||
| :------ | :----- | :-------- | :------------ |
|
| :------ | :----- | :-------- | :------------ |
|
||||||
@@ -63,19 +62,15 @@ available:
|
|||||||
Finding how entities connect to each other:
|
Finding how entities connect to each other:
|
||||||
|
|
||||||
```python
|
```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)
|
"relationships": [
|
||||||
|
{"subject": "Steve Jobs", "predicate": "founded", "object": "Apple Inc.", "confidence": 0.92},
|
||||||
[
|
{"subject": "Apple Inc.", "predicate": "located_in", "object": "Cupertino", "confidence": 0.89}
|
||||||
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),
|
}
|
||||||
]
|
|
||||||
```
|
```
|
||||||
|
|
||||||
`RelationExtractor(method=...).extract(text, entities=entities)` returns a list of
|
Relationships can be extracted via rule-based methods, ML models, or LLMs: each producing typed triplets with confidence scores and source attribution.
|
||||||
`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.
|
|
||||||
|
|
||||||
|
|
||||||
## Knowledge Graph vs. Vector Store
|
## Knowledge Graph vs. Vector Store
|
||||||
@@ -99,10 +94,9 @@ Both store information for AI retrieval: but they're built for different jobs.
|
|||||||
```python
|
```python
|
||||||
from semantica.kg import GraphBuilder, PathFinder
|
from semantica.kg import GraphBuilder, PathFinder
|
||||||
|
|
||||||
graph = GraphBuilder(merge_entities=True).build(
|
graph = GraphBuilder(merge_entities=True).build(entities=entities, relationships=rels)
|
||||||
{"entities": entities, "relationships": rels}
|
finder = PathFinder()
|
||||||
)
|
path = finder.dijkstra_shortest_path(graph, "Steve Jobs", "Tim Cook")
|
||||||
path = PathFinder().dijkstra_shortest_path(graph, "Steve Jobs", "Tim Cook")
|
|
||||||
```
|
```
|
||||||
</Tab>
|
</Tab>
|
||||||
|
|
||||||
@@ -146,16 +140,8 @@ Both store information for AI retrieval: but they're built for different jobs.
|
|||||||
context = AgentContext(
|
context = AgentContext(
|
||||||
vector_store=VectorStore(backend="faiss", dimension=768),
|
vector_store=VectorStore(backend="faiss", dimension=768),
|
||||||
knowledge_graph=ContextGraph(advanced_analytics=True),
|
knowledge_graph=ContextGraph(advanced_analytics=True),
|
||||||
graph_expansion=True,
|
|
||||||
)
|
)
|
||||||
|
result = context.query("Who founded Apple?", mode="graphrag")
|
||||||
# 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"])
|
|
||||||
```
|
```
|
||||||
</Tab>
|
</Tab>
|
||||||
</Tabs>
|
</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.
|
Applies IF/THEN rules repeatedly until no new facts can be derived. Best for alert systems, compliance checks, and trigger-based workflows.
|
||||||
|
|
||||||
```python
|
```python
|
||||||
from semantica.reasoning import Reasoner
|
from semantica.reasoning import Reasoner, Rule, Fact, RuleType
|
||||||
|
|
||||||
engine = Reasoner()
|
engine = Reasoner()
|
||||||
engine.add_fact("Manager(Alice)")
|
engine.add_fact(Fact(subject="Alice", predicate="is_a", obj="Manager"))
|
||||||
engine.add_rule("IF Manager(?x) THEN HasAuthority(?x)")
|
engine.add_rule(Rule(
|
||||||
|
rule_type=RuleType.FORWARD_CHAIN,
|
||||||
results = engine.forward_chain() # list of InferenceResult
|
conditions=[{"subject": "?x", "predicate": "is_a", "object": "Manager"}],
|
||||||
for r in results:
|
conclusion={"subject": "?x", "predicate": "has_authority", "object": "true"}
|
||||||
print(r.conclusion) # "HasAuthority(Alice)"
|
))
|
||||||
|
result = engine.infer()
|
||||||
```
|
```
|
||||||
</Tab>
|
</Tab>
|
||||||
<Tab title="Rete Network">
|
<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.
|
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
|
```python
|
||||||
from semantica.reasoning import ReteEngine, Rule, Fact
|
from semantica.reasoning import ReteEngine
|
||||||
|
|
||||||
engine = ReteEngine()
|
engine = ReteEngine()
|
||||||
engine.build_network([
|
engine.load_rules("rules/domain_rules.json")
|
||||||
Rule(rule_id="r1", name="manager_authority",
|
results = engine.run(kg)
|
||||||
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)"]
|
|
||||||
```
|
```
|
||||||
</Tab>
|
</Tab>
|
||||||
<Tab title="LLM Reasoning">
|
<Tab title="Deductive & Abductive">
|
||||||
`GraphReasoner` answers open-ended questions over a knowledge graph with an
|
**Deductive**: classical syllogistic reasoning from premises to guaranteed conclusions.
|
||||||
LLM, returning a natural-language answer grounded in the graph's facts. Best
|
|
||||||
for exploratory and investigative questions that fixed rules can't anticipate.
|
**Abductive**: infers the most likely explanation for observed evidence. Best for diagnostic and investigative use cases.
|
||||||
|
|
||||||
```python
|
```python
|
||||||
from semantica.reasoning import GraphReasoner
|
from semantica.reasoning import GraphReasoner
|
||||||
|
|
||||||
reasoner = GraphReasoner(provider="openai", model="gpt-4o-mini")
|
graph_reasoner = GraphReasoner(kg)
|
||||||
answer = reasoner.reason(kg, "Which suppliers are indirectly exposed to the Acme outage?")
|
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>
|
||||||
<Tab title="Datalog (v0.4.0)">
|
<Tab title="Datalog (v0.4.0)">
|
||||||
Recursive Horn clause rules with fixpoint semantics: handles transitive closure and recursive relationships that forward chaining cannot express.
|
Recursive Horn clause rules with fixpoint semantics: handles transitive closure and recursive relationships that forward chaining cannot express.
|
||||||
|
|
||||||
```python
|
```python
|
||||||
from semantica.reasoning import DatalogReasoner
|
from semantica.reasoning import DatalogReasoner, DatalogFact, DatalogRule
|
||||||
|
|
||||||
reasoner = DatalogReasoner()
|
reasoner = DatalogReasoner()
|
||||||
reasoner.add_fact("parent(alice, bob)")
|
reasoner.add_fact(DatalogFact("parent", ("alice", "bob")))
|
||||||
reasoner.add_fact("parent(bob, charlie)")
|
reasoner.add_rule(DatalogRule("ancestor(?X, ?Y) :- parent(?X, ?Y)."))
|
||||||
reasoner.add_rule("ancestor(X, Y) :- parent(X, Y).")
|
reasoner.evaluate()
|
||||||
reasoner.add_rule("ancestor(X, Z) :- parent(X, Y), ancestor(Y, Z).")
|
results = reasoner.query("ancestor(alice, ?Z)")
|
||||||
|
|
||||||
reasoner.derive_all()
|
|
||||||
results = reasoner.query("ancestor(alice, ?Z)") # {"Z": "bob"} and {"Z": "charlie"}, order not guaranteed
|
|
||||||
```
|
```
|
||||||
</Tab>
|
</Tab>
|
||||||
<Tab title="Engine Comparison">
|
<Tab title="Engine Comparison">
|
||||||
|
|
||||||
| Engine | Class | Best For |
|
| Engine | Description | Best For |
|
||||||
| :------ | :----- | :-------- |
|
| :------ | :----------- | :-------- |
|
||||||
| Forward chaining | `Reasoner` | Alert systems, compliance checks |
|
| Forward chaining | Applies rules until fixpoint | Alert systems, compliance checks |
|
||||||
| Rete network | `ReteEngine` | Large rule sets, high fact throughput |
|
| Rete network | Efficient pattern matching | Large rule sets, high fact throughput |
|
||||||
| SPARQL expansion | `SPARQLReasoner` | Semantic web, ontology reasoning over RDF |
|
| Deductive | Classical syllogistic reasoning | Mathematical and logical inference |
|
||||||
| Datalog (v0.4.0) | `DatalogReasoner` | Transitive closure, graph reachability |
|
| Abductive | Most likely explanation | Diagnostics, investigation |
|
||||||
| Temporal | `TemporalReasoningEngine` | Allen interval algebra, time-aware inference |
|
| SPARQL | Query-based inference over RDF | Semantic web, ontology reasoning |
|
||||||
| LLM over the graph | `GraphReasoner` | Open-ended, investigative questions |
|
| Datalog (v0.4.0) | Recursive Horn clause rules | Transitive closure, graph reachability |
|
||||||
|
|
||||||
</Tab>
|
</Tab>
|
||||||
</Tabs>
|
</Tabs>
|
||||||
|
|
||||||
`Reasoner.forward_chain()` returns `InferenceResult` objects that carry the rule
|
All engines produce **explainable inference paths**: not black-box conclusions. Every derived fact includes the rules and premises that produced it.
|
||||||
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.
|
|
||||||
|
|
||||||
|
|
||||||
## Temporal Intelligence
|
## Temporal Intelligence
|
||||||
@@ -337,16 +313,11 @@ Explore the semantic neighborhood of any entity in your graph: useful for unders
|
|||||||
```python
|
```python
|
||||||
from semantica.kg import SimilarityCalculator
|
from semantica.kg import SimilarityCalculator
|
||||||
|
|
||||||
calc = SimilarityCalculator(method="cosine") # "cosine" | "euclidean" | "manhattan" | "correlation"
|
calc = SimilarityCalculator()
|
||||||
|
scores = calc.calculate_similarity(entity_a, entity_b)
|
||||||
# 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)
|
|
||||||
```
|
```
|
||||||
|
|
||||||
**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.
|
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
|
```python
|
||||||
from semantica.deduplication import DuplicateDetector, EntityMerger
|
from semantica.deduplication import DuplicateDetector, EntityMerger
|
||||||
|
|
||||||
detector = DuplicateDetector(similarity_threshold=0.85)
|
detector = DuplicateDetector(similarity_threshold=0.85)
|
||||||
candidates = detector.detect_duplicates(entities)
|
duplicates = detector.detect_duplicates(entities)
|
||||||
|
|
||||||
merger = EntityMerger()
|
merger = EntityMerger()
|
||||||
operations = merger.merge_duplicates(entities, strategy="keep_most_complete")
|
deduplicated_entities = merger.merge_duplicates(entities)
|
||||||
```
|
```
|
||||||
</Tab>
|
</Tab>
|
||||||
</Tabs>
|
</Tabs>
|
||||||
@@ -390,21 +361,19 @@ Every fact in Semantica links back to:
|
|||||||
- The **reasoning steps** that produced any inferred fact
|
- The **reasoning steps** that produced any inferred fact
|
||||||
|
|
||||||
<Note>
|
<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>
|
</Note>
|
||||||
|
|
||||||
```python
|
```python
|
||||||
from semantica.provenance import ProvenanceManager
|
from semantica.provenance import ProvenanceManager
|
||||||
|
|
||||||
prov = ProvenanceManager()
|
prov = ProvenanceManager()
|
||||||
prov.track_entity("apple_inc", source="report.pdf",
|
lineage = prov.get_entity_lineage("apple_inc")
|
||||||
metadata={"extractor": "NamedEntityRecognizer", "confidence": 0.98})
|
|
||||||
|
|
||||||
record = prov.get_provenance("apple_inc") # dict; use get_lineage() for the full chain
|
print(f"Source: {lineage.source_document}")
|
||||||
print(record["source_document"])
|
print(f"Method: {lineage.extraction_method}")
|
||||||
print(record["timestamp"])
|
print(f"Extracted: {lineage.timestamp}")
|
||||||
print(record["checksum"])
|
print(f"Checksum: {lineage.checksum}")
|
||||||
print(record["metadata"]) # extractor, confidence, and any custom keys
|
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
@@ -487,32 +456,32 @@ 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.
|
**Extension points available:** ingestors, parsers, normalizers, extractors, reasoning engines, export formats, vector store backends, graph store backends, visualization renderers.
|
||||||
|
|
||||||
</Accordion>
|
</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
|
`MethodRegistry` lets you register custom methods on knowledge graph objects by name: useful for adding domain-specific graph operations without subclassing.
|
||||||
knowledge-graph task (`build`, `analyze`, `centrality`, `resolve`, …) under a
|
|
||||||
name, then select it wherever that task runs.
|
|
||||||
|
|
||||||
```python
|
```python
|
||||||
from semantica.kg import method_registry
|
from semantica.kg import MethodRegistry
|
||||||
from semantica.kg.methods import calculate_centrality
|
|
||||||
|
|
||||||
def fast_centrality(graph, **kwargs):
|
registry = MethodRegistry()
|
||||||
"""Custom centrality implementation."""
|
|
||||||
|
def find_supply_chain_hops(graph, source_node, max_hops=3):
|
||||||
|
"""Custom BFS traversal for supply chain graphs."""
|
||||||
...
|
...
|
||||||
|
|
||||||
# register(task, name, func)
|
# Register under a string key
|
||||||
method_registry.register("centrality", "fast_centrality", fast_centrality)
|
registry.register("supply_chain_hops", find_supply_chain_hops)
|
||||||
|
|
||||||
# The task wrappers consult method_registry, so the name is now selectable:
|
# Call by name on any graph object
|
||||||
scores = calculate_centrality(kg, method="fast_centrality")
|
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>
|
</Accordion>
|
||||||
</AccordionGroup>
|
</AccordionGroup>
|
||||||
|
|
||||||
- [Quickstart Tutorial](/quickstart): build a full pipeline with code.
|
- [Quickstart Tutorial](/quickstart) — Build a full pipeline with code.
|
||||||
- [Modules Guide](/modules): every module explained with examples.
|
- [Modules Guide](/modules) — Every module explained with examples.
|
||||||
- [API Reference](/reference/context): complete technical reference.
|
- [API Reference](/reference/context) — Complete technical reference.
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ description: "How to contribute code, documentation, tests, and community suppor
|
|||||||
icon: "code-pull-request"
|
icon: "code-pull-request"
|
||||||
---
|
---
|
||||||
|
|
||||||
Contributions of all kinds are welcome (code, documentation, tests, and community support). Every contribution is recognized in release notes and the GitHub contributors list.
|
Contributions of all kinds are welcome: code, documentation, tests, and community support. Every contribution is recognized in release notes and the GitHub contributors list.
|
||||||
|
|
||||||
|
|
||||||
## Quick Start
|
## Quick Start
|
||||||
@@ -17,15 +17,15 @@ pip install -e ".[dev]"
|
|||||||
pytest
|
pytest
|
||||||
```
|
```
|
||||||
|
|
||||||
First-time contributors can start with [`good-first-issue`](https://github.com/semantica-agi/semantica/labels/good-first-issue) labeled tickets, which are scoped to be completable in a few hours without deep codebase knowledge.
|
New to the project? Start with [`good-first-issue`](https://github.com/semantica-agi/semantica/labels/good-first-issue) labeled tickets: they're scoped to be completable in a few hours without deep codebase knowledge.
|
||||||
|
|
||||||
|
|
||||||
## Ways to Contribute
|
## Ways to Contribute
|
||||||
|
|
||||||
- **Code**: fix bugs, implement features, optimize performance, or add new ingestors, parsers, and exporters using the plugin registry.
|
- **Code** — Fix bugs, implement features, optimize performance, or add new ingestors, parsers, and exporters using the plugin registry.
|
||||||
- **Documentation**: fix typos, improve clarity, add missing examples, write tutorials, or keep the API reference accurate as modules evolve.
|
- **Documentation** — Fix typos, improve clarity, add missing examples, write tutorials, or keep the API reference accurate as modules evolve.
|
||||||
- **Testing**: add test coverage for untested modules or edge cases, reproduce reported bugs with minimal repros, or improve cross-platform reliability.
|
- **Testing** — Add test coverage for untested modules or edge cases, reproduce reported bugs with minimal repros, or improve cross-platform reliability.
|
||||||
- **Community**: answer questions in GitHub Issues and Discussions, review pull requests with constructive feedback, or share Semantica in blog posts and talks.
|
- **Community** — Answer questions in GitHub Issues and Discussions, review pull requests with constructive feedback, or share Semantica in blog posts and talks.
|
||||||
|
|
||||||
|
|
||||||
## Development Setup
|
## Development Setup
|
||||||
@@ -76,7 +76,7 @@ Before submitting a PR, confirm:
|
|||||||
|
|
||||||
## Code of Conduct
|
## Code of Conduct
|
||||||
|
|
||||||
All contributors are expected to follow the [Contributor Covenant Code of Conduct](https://github.com/semantica-agi/semantica/blob/main/CODE_OF_CONDUCT.md). Be respectful, patient, and constructive, especially toward newcomers. Report violations by opening an issue with the `[CoC]` prefix.
|
All contributors are expected to follow the [Contributor Covenant Code of Conduct](https://github.com/semantica-agi/semantica/blob/main/CODE_OF_CONDUCT.md). Be respectful, patient, and constructive: especially toward newcomers. Report violations by opening an issue with the `[CoC]` prefix.
|
||||||
|
|
||||||
|
|
||||||
## Help
|
## Help
|
||||||
@@ -85,5 +85,5 @@ All contributors are expected to follow the [Contributor Covenant Code of Conduc
|
|||||||
- [GitHub Discussions](https://github.com/semantica-agi/semantica/discussions)
|
- [GitHub Discussions](https://github.com/semantica-agi/semantica/discussions)
|
||||||
- [Discord](https://discord.gg/sV34vps5hH)
|
- [Discord](https://discord.gg/sV34vps5hH)
|
||||||
|
|
||||||
- [Community](/community): community guidelines and values.
|
- [Community](/community) — Community guidelines and values.
|
||||||
- [Governance](/governance): how decisions are made and the project is run.
|
- [Governance](/governance) — How decisions are made and the project is run.
|
||||||
|
|||||||
+25
-25
@@ -18,43 +18,43 @@ icon: "flask"
|
|||||||
|
|
||||||
## Featured Recipe
|
## Featured Recipe
|
||||||
|
|
||||||
- **[Your First Knowledge Graph](https://github.com/semantica-agi/semantica/blob/main/cookbook/introduction/08_Your_First_Knowledge_Graph.ipynb)**: go from raw text to a queryable knowledge graph in 20 minutes. Topics: Extraction, Graph Construction, Visualization · *Beginner*
|
- **[Your First Knowledge Graph](https://github.com/semantica-agi/semantica/blob/main/cookbook/introduction/08_Your_First_Knowledge_Graph.ipynb)** — Go from raw text to a queryable knowledge graph in 20 minutes. Topics: Extraction, Graph Construction, Visualization · *Beginner*
|
||||||
|
|
||||||
|
|
||||||
## Core Tutorials
|
## Core Tutorials
|
||||||
|
|
||||||
Essential guides to master the Semantica framework.
|
Essential guides to master the Semantica framework.
|
||||||
|
|
||||||
- **[Welcome to Semantica](https://github.com/semantica-agi/semantica/blob/main/cookbook/introduction/01_Welcome_to_Semantica.ipynb)**: interactive introduction to the framework's core philosophy and all modules. Topics: Framework Overview, Architecture · *Beginner*
|
- **[Welcome to Semantica](https://github.com/semantica-agi/semantica/blob/main/cookbook/introduction/01_Welcome_to_Semantica.ipynb)** — Interactive introduction to the framework's core philosophy and all modules. Topics: Framework Overview, Architecture · *Beginner*
|
||||||
- **[Data Ingestion](https://github.com/semantica-agi/semantica/blob/main/cookbook/introduction/02_Data_Ingestion.ipynb)**: loading data from files, web, databases, streams, feeds, repositories, email, and MCP. Topics: FileIngestor, WebIngestor, DBIngestor · *Beginner*
|
- **[Data Ingestion](https://github.com/semantica-agi/semantica/blob/main/cookbook/introduction/02_Data_Ingestion.ipynb)** — Loading data from files, web, databases, streams, feeds, repositories, email, and MCP. Topics: FileIngestor, WebIngestor, DBIngestor · *Beginner*
|
||||||
- **[Document Parsing](https://github.com/semantica-agi/semantica/blob/main/cookbook/introduction/03_Document_Parsing.ipynb)**: extracting clean text from complex formats like PDF, DOCX, and HTML. Topics: OCR, PDF Parsing, Text Extraction · *Beginner*
|
- **[Document Parsing](https://github.com/semantica-agi/semantica/blob/main/cookbook/introduction/03_Document_Parsing.ipynb)** — Extracting clean text from complex formats like PDF, DOCX, and HTML. Topics: OCR, PDF Parsing, Text Extraction · *Beginner*
|
||||||
- **[Data Normalization](https://github.com/semantica-agi/semantica/blob/main/cookbook/introduction/04_Data_Normalization.ipynb)**: pipelines for cleaning, normalizing, and preparing text. Topics: Text Cleaning, Unicode, Formatting · *Beginner*
|
- **[Data Normalization](https://github.com/semantica-agi/semantica/blob/main/cookbook/introduction/04_Data_Normalization.ipynb)** — Pipelines for cleaning, normalizing, and preparing text. Topics: Text Cleaning, Unicode, Formatting · *Beginner*
|
||||||
- **[Entity Extraction](https://github.com/semantica-agi/semantica/blob/main/cookbook/introduction/05_Entity_Extraction.ipynb)**: using NER to identify people, organizations, and custom entities. Topics: NER, spaCy, LLM Extraction · *Beginner*
|
- **[Entity Extraction](https://github.com/semantica-agi/semantica/blob/main/cookbook/introduction/05_Entity_Extraction.ipynb)** — Using NER to identify people, organizations, and custom entities. Topics: NER, spaCy, LLM Extraction · *Beginner*
|
||||||
- **[Relation Extraction](https://github.com/semantica-agi/semantica/blob/main/cookbook/introduction/06_Relation_Extraction.ipynb)**: discovering and classifying relationships between entities. Topics: Relation Classification, Dependency Parsing · *Beginner*
|
- **[Relation Extraction](https://github.com/semantica-agi/semantica/blob/main/cookbook/introduction/06_Relation_Extraction.ipynb)** — Discovering and classifying relationships between entities. Topics: Relation Classification, Dependency Parsing · *Beginner*
|
||||||
- **[Embedding Generation](https://github.com/semantica-agi/semantica/blob/main/cookbook/introduction/12_Embedding_Generation.ipynb)**: creating and managing vector embeddings for semantic search. Topics: Embeddings, OpenAI, HuggingFace · *Intermediate*
|
- **[Embedding Generation](https://github.com/semantica-agi/semantica/blob/main/cookbook/introduction/12_Embedding_Generation.ipynb)** — Creating and managing vector embeddings for semantic search. Topics: Embeddings, OpenAI, HuggingFace · *Intermediate*
|
||||||
- **[Vector Store](https://github.com/semantica-agi/semantica/blob/main/cookbook/introduction/13_Vector_Store.ipynb)**: setting up vector stores for similarity search and retrieval. *Intermediate*
|
- **[Vector Store](https://github.com/semantica-agi/semantica/blob/main/cookbook/introduction/13_Vector_Store.ipynb)** — Setting up vector stores for similarity search and retrieval. *Intermediate*
|
||||||
- **[Graph Store](https://github.com/semantica-agi/semantica/blob/main/cookbook/introduction/09_Graph_Store.ipynb)**: persisting knowledge graphs in Neo4j or FalkorDB. Topics: Neo4j, Cypher, Persistence · *Intermediate*
|
- **[Graph Store](https://github.com/semantica-agi/semantica/blob/main/cookbook/introduction/09_Graph_Store.ipynb)** — Persisting knowledge graphs in Neo4j or FalkorDB. Topics: Neo4j, Cypher, Persistence · *Intermediate*
|
||||||
- **[Ontology](https://github.com/semantica-agi/semantica/blob/main/cookbook/introduction/14_Ontology.ipynb)**: defining domain schemas and ontologies to structure your data. Topics: OWL, RDF, Schema Design · *Intermediate*
|
- **[Ontology](https://github.com/semantica-agi/semantica/blob/main/cookbook/introduction/14_Ontology.ipynb)** — Defining domain schemas and ontologies to structure your data. Topics: OWL, RDF, Schema Design · *Intermediate*
|
||||||
- **[Seed Data](https://github.com/semantica-agi/semantica/blob/main/cookbook/introduction/25_Seed_Data.ipynb)**: bootstrapping a knowledge graph from trusted CSV, JSON, database, and API sources before extraction runs. Topics: SeedDataManager, Foundation Graphs · *Intermediate*
|
- **[Seed Data](https://github.com/semantica-agi/semantica/blob/main/cookbook/introduction/25_Seed_Data.ipynb)** — Bootstrapping a knowledge graph from trusted CSV, JSON, database, and API sources before extraction runs. Topics: SeedDataManager, Foundation Graphs · *Intermediate*
|
||||||
- **[Semantic Layer Basics](https://github.com/semantica-agi/semantica/blob/main/cookbook/introduction/26_Semantic_Layer_Basics.ipynb)**: capstone tutorial that combines a knowledge graph, generated ontology, explicit mappings, ontology-aligned RDF, and a SPARQL query. Topics: Semantic Layer, Ontology Mapping, Oxigraph, SPARQL · *Intermediate*
|
- **[Semantic Layer Basics](https://github.com/semantica-agi/semantica/blob/main/cookbook/introduction/26_Semantic_Layer_Basics.ipynb)** — Capstone tutorial that combines a knowledge graph, generated ontology, explicit mappings, ontology-aligned RDF, and a SPARQL query. Topics: Semantic Layer, Ontology Mapping, Oxigraph, SPARQL · *Intermediate*
|
||||||
|
|
||||||
|
|
||||||
## Advanced Concepts
|
## Advanced Concepts
|
||||||
|
|
||||||
Deep dive into advanced features, customization, and complex workflows.
|
Deep dive into advanced features, customization, and complex workflows.
|
||||||
|
|
||||||
- **[Advanced Extraction](https://github.com/semantica-agi/semantica/blob/main/cookbook/advanced/01_Advanced_Extraction.ipynb)**: custom extractors, LLM-based extraction, and complex pattern matching. Topics: Custom Models, Regex, LLMs · *Advanced*
|
- **[Advanced Extraction](https://github.com/semantica-agi/semantica/blob/main/cookbook/advanced/01_Advanced_Extraction.ipynb)** — Custom extractors, LLM-based extraction, and complex pattern matching. Topics: Custom Models, Regex, LLMs · *Advanced*
|
||||||
- **[Advanced Graph Analytics](https://github.com/semantica-agi/semantica/blob/main/cookbook/advanced/02_Advanced_Graph_Analytics.ipynb)**: centrality, community detection, and pathfinding algorithms. Topics: PageRank, Louvain, Shortest Path · *Advanced*
|
- **[Advanced Graph Analytics](https://github.com/semantica-agi/semantica/blob/main/cookbook/advanced/02_Advanced_Graph_Analytics.ipynb)** — Centrality, community detection, and pathfinding algorithms. Topics: PageRank, Louvain, Shortest Path · *Advanced*
|
||||||
- **[Advanced Context Engineering](https://github.com/semantica-agi/semantica/blob/main/cookbook/advanced/11_Advanced_Context_Engineering.ipynb)**: persistent memory system for AI agents using FAISS and Neo4j. Topics: Agent Memory, GraphRAG, Entity Injection · *Advanced*
|
- **[Advanced Context Engineering](https://github.com/semantica-agi/semantica/blob/main/cookbook/advanced/11_Advanced_Context_Engineering.ipynb)** — Production-grade memory system for AI agents using FAISS and Neo4j. Topics: Agent Memory, GraphRAG, Entity Injection · *Advanced*
|
||||||
- **[Complete Visualization Suite](https://github.com/semantica-agi/semantica/blob/main/cookbook/advanced/03_Complete_Visualization_Suite.ipynb)**: interactive network, analytics, and temporal visualizations for graphs. Topics: PyVis, NetworkX, D3.js · *Intermediate*
|
- **[Complete Visualization Suite](https://github.com/semantica-agi/semantica/blob/main/cookbook/advanced/03_Complete_Visualization_Suite.ipynb)** — Interactive, publication-ready visualizations of your graphs. Topics: PyVis, NetworkX, D3.js · *Intermediate*
|
||||||
- **[Conflict Resolution](https://github.com/semantica-agi/semantica/blob/main/cookbook/introduction/17_Conflict_Detection_and_Resolution.ipynb)**: strategies for handling contradictory information from multiple sources. Topics: Truth Discovery, Voting, Confidence · *Advanced*
|
- **[Conflict Resolution](https://github.com/semantica-agi/semantica/blob/main/cookbook/introduction/17_Conflict_Detection_and_Resolution.ipynb)** — Strategies for handling contradictory information from multiple sources. Topics: Truth Discovery, Voting, Confidence · *Advanced*
|
||||||
- **[Multi-Format Export](https://github.com/semantica-agi/semantica/blob/main/cookbook/advanced/05_Multi_Format_Export.ipynb)**: exporting to RDF, OWL, JSON-LD, and NetworkX formats. Topics: Serialization, Interoperability · *Intermediate*
|
- **[Multi-Format Export](https://github.com/semantica-agi/semantica/blob/main/cookbook/advanced/05_Multi_Format_Export.ipynb)** — Exporting to RDF, OWL, JSON-LD, and NetworkX formats. Topics: Serialization, Interoperability · *Intermediate*
|
||||||
- **[Multi-Source Integration](https://github.com/semantica-agi/semantica/blob/main/cookbook/advanced/06_Multi_Source_Data_Integration.ipynb)**: merging data from disparate sources into a unified graph. Topics: Entity Resolution, Merging, Fusion · *Advanced*
|
- **[Multi-Source Integration](https://github.com/semantica-agi/semantica/blob/main/cookbook/advanced/06_Multi_Source_Data_Integration.ipynb)** — Merging data from disparate sources into a unified graph. Topics: Entity Resolution, Merging, Fusion · *Advanced*
|
||||||
- **[Reasoning and Inference](https://github.com/semantica-agi/semantica/blob/main/cookbook/advanced/08_Reasoning_and_Inference.ipynb)**: using logical reasoning to infer new knowledge from existing facts. Topics: Logic Rules, Inference Engines · *Advanced*
|
- **[Reasoning and Inference](https://github.com/semantica-agi/semantica/blob/main/cookbook/advanced/08_Reasoning_and_Inference.ipynb)** — Using logical reasoning to infer new knowledge from existing facts. Topics: Logic Rules, Inference Engines · *Advanced*
|
||||||
- **[Temporal Knowledge Graphs](https://github.com/semantica-agi/semantica/blob/main/cookbook/advanced/10_Temporal_Knowledge_Graphs.ipynb)**: modeling and querying data that changes over time. Topics: Time Series, Temporal Logic, Allen Algebra · *Advanced*
|
- **[Temporal Knowledge Graphs](https://github.com/semantica-agi/semantica/blob/main/cookbook/advanced/10_Temporal_Knowledge_Graphs.ipynb)** — Modeling and querying data that changes over time. Topics: Time Series, Temporal Logic, Allen Algebra · *Advanced*
|
||||||
- **[Provenance Tracking](https://github.com/semantica-agi/semantica/blob/main/cookbook/introduction/22_Provenance_Tracking.ipynb)**: W3C PROV-O-aligned lineage tracking and checksum verification for entities, relationships, and chunks. Topics: PROV-O, Lineage, Checksums, Invalidation · *Advanced*
|
- **[Provenance Tracking](https://github.com/semantica-agi/semantica/blob/main/cookbook/introduction/22_Provenance_Tracking.ipynb)** — Audit-grade, W3C PROV-O-aligned tracking of where every entity, relationship, and chunk came from. Topics: PROV-O, Lineage, Checksums, Invalidation · *Advanced*
|
||||||
- **[Reasoning Module](https://github.com/semantica-agi/semantica/blob/main/cookbook/introduction/23_Reasoning.ipynb)**: deriving new knowledge from existing facts with forward chaining, backward chaining, and Datalog strategies. Topics: Reasoner, Datalog, Explanations · *Advanced*
|
- **[Reasoning Module](https://github.com/semantica-agi/semantica/blob/main/cookbook/introduction/23_Reasoning.ipynb)** — Deriving new knowledge from existing facts with forward chaining, backward chaining, and Datalog strategies. Topics: Reasoner, Datalog, Explanations · *Advanced*
|
||||||
- **[Change Management](https://github.com/semantica-agi/semantica/blob/main/cookbook/introduction/24_Change_Management.ipynb)**: versioning, audit trails, and data-integrity checks for knowledge graphs and ontologies. Topics: ChangeLogEntry, Version Storage, Data Integrity · *Advanced*
|
- **[Change Management](https://github.com/semantica-agi/semantica/blob/main/cookbook/introduction/24_Change_Management.ipynb)** — Versioning, audit trails, and data-integrity checks for knowledge graphs and ontologies. Topics: ChangeLogEntry, Version Storage, Data Integrity · *Advanced*
|
||||||
|
|
||||||
|
|
||||||
## How to Run
|
## How to Run
|
||||||
|
|||||||
+30
-32
@@ -2,7 +2,7 @@
|
|||||||
"$schema": "https://mintlify.com/docs.json",
|
"$schema": "https://mintlify.com/docs.json",
|
||||||
"theme": "mint",
|
"theme": "mint",
|
||||||
"name": "Semantica",
|
"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": {
|
"colors": {
|
||||||
"primary": "#10B981",
|
"primary": "#10B981",
|
||||||
"light": "#10B981",
|
"light": "#10B981",
|
||||||
@@ -43,7 +43,7 @@
|
|||||||
"raiseIssue": true
|
"raiseIssue": true
|
||||||
},
|
},
|
||||||
"metadata": {
|
"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:description": "Build explainable, auditable knowledge graphs with full provenance. Open source. MIT licensed.",
|
||||||
"og:image": "/assets/img/semantica-logo.png",
|
"og:image": "/assets/img/semantica-logo.png",
|
||||||
"twitter:card": "summary_large_image",
|
"twitter:card": "summary_large_image",
|
||||||
@@ -107,8 +107,7 @@
|
|||||||
"integrations/docling",
|
"integrations/docling",
|
||||||
"integrations/snowflake",
|
"integrations/snowflake",
|
||||||
"integrations/databricks",
|
"integrations/databricks",
|
||||||
"integrations/salesforce",
|
"integrations/salesforce"
|
||||||
"integrations/redshift"
|
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -122,23 +121,6 @@
|
|||||||
"pages": [
|
"pages": [
|
||||||
"vector_stores/pgvector"
|
"vector_stores/pgvector"
|
||||||
]
|
]
|
||||||
},
|
|
||||||
{
|
|
||||||
"group": "FAQ",
|
|
||||||
"pages": [
|
|
||||||
"faq"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"group": "Community",
|
|
||||||
"pages": [
|
|
||||||
"community",
|
|
||||||
"community-projects",
|
|
||||||
"contributing-guide",
|
|
||||||
"governance",
|
|
||||||
"citation",
|
|
||||||
"project-license"
|
|
||||||
]
|
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
@@ -185,17 +167,7 @@
|
|||||||
"guides/policy-engine",
|
"guides/policy-engine",
|
||||||
"guides/visualization",
|
"guides/visualization",
|
||||||
"guides/distance-intelligence",
|
"guides/distance-intelligence",
|
||||||
"guides/graph-analytics"
|
"guides/graph-analytics",
|
||||||
]
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"tab": "API Reference",
|
|
||||||
"groups": [
|
|
||||||
{
|
|
||||||
"group": "Context & Intelligence",
|
|
||||||
"pages": [
|
|
||||||
"reference/context",
|
"reference/context",
|
||||||
"reference/kg",
|
"reference/kg",
|
||||||
"reference/temporal",
|
"reference/temporal",
|
||||||
@@ -264,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"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -109,7 +109,7 @@ Explorer loads a graph from a JSON file on disk. You need to create that file fi
|
|||||||
</Steps>
|
</Steps>
|
||||||
|
|
||||||
<Tip>
|
<Tip>
|
||||||
Pipelines that already produced a saved graph can skip straight to Step 2, provided the file was saved with `ContextGraph.save_to_file()`.
|
Already have a graph from a pipeline run? Skip straight to Step 2. The only requirement is that the file was saved with `ContextGraph.save_to_file()`.
|
||||||
</Tip>
|
</Tip>
|
||||||
|
|
||||||
|
|
||||||
@@ -264,7 +264,7 @@ Once running, Explorer exposes a REST API and dashboard for:
|
|||||||
|
|
||||||
The full endpoint catalogue is documented in the Swagger UI at `/docs` and in the reference page below.
|
The full endpoint catalogue is documented in the Swagger UI at `/docs` and in the reference page below.
|
||||||
|
|
||||||
- [Explorer Reference](/reference/explorer): every REST endpoint, WebSocket events, analytics, and all supported flags.
|
- [Explorer Reference](/reference/explorer) — Every REST endpoint, WebSocket events, analytics, and all supported flags.
|
||||||
- [CLI Setup](/cli-setup): all five Semantica executables and when to use each one.
|
- [CLI Setup](/cli-setup) — All five Semantica executables and when to use each one.
|
||||||
- [Context Module](/reference/context): full documentation for ContextGraph (build, query, save, and load).
|
- [Context Module](/reference/context) — Full documentation for ContextGraph: build, query, save, and load.
|
||||||
- [Quickstart](/quickstart): end-to-end pipeline (ingest → extract → build graph → export).
|
- [Quickstart](/quickstart) — End-to-end pipeline: ingest → extract → build graph → export.
|
||||||
|
|||||||
+11
-11
@@ -5,7 +5,7 @@ icon: "circle-question"
|
|||||||
---
|
---
|
||||||
|
|
||||||
<Info>
|
<Info>
|
||||||
Use **Ctrl+F** / **Cmd+F** to search this page. Common jumps: [Installation](#installation) · [Data & Features](#data-&-features) · [Troubleshooting](#troubleshooting)
|
Use **Ctrl+F** / **Cmd+F** to search this page. Common jumps: [Installation](#installation) · [Data & Features](#data--features) · [Troubleshooting](#troubleshooting)
|
||||||
</Info>
|
</Info>
|
||||||
|
|
||||||
## Quick Answers
|
## Quick Answers
|
||||||
@@ -17,7 +17,7 @@ icon: "circle-question"
|
|||||||
| API key required? | Optional: pattern extraction works with no keys |
|
| API key required? | Optional: pattern extraction works with no keys |
|
||||||
| Works with LangChain / LlamaIndex? | Yes: Semantica is a layer on top, not a replacement |
|
| Works with LangChain / LlamaIndex? | Yes: Semantica is a layer on top, not a replacement |
|
||||||
| Production-ready? | Yes: 1,000+ tests, security fixes shipped in every release (see [CHANGELOG](https://github.com/semantica-agi/semantica/blob/main/CHANGELOG.md)) |
|
| Production-ready? | Yes: 1,000+ tests, security fixes shipped in every release (see [CHANGELOG](https://github.com/semantica-agi/semantica/blob/main/CHANGELOG.md)) |
|
||||||
| Latest version? | **v0.6.8** (September 2026) |
|
| Latest version? | **v0.6.7** (August 2026) |
|
||||||
| Local LLMs? | Yes: Ollama via LiteLLM, HuggingFaceLLM for air-gapped |
|
| Local LLMs? | Yes: Ollama via LiteLLM, HuggingFaceLLM for air-gapped |
|
||||||
|
|
||||||
|
|
||||||
@@ -27,7 +27,7 @@ icon: "circle-question"
|
|||||||
|
|
||||||
<Accordion title="What is Semantica?" icon="info-circle">
|
<Accordion title="What is Semantica?" icon="info-circle">
|
||||||
|
|
||||||
Semantica is an open-source framework for building context graphs and decision intelligence layers for AI. It transforms unstructured data (documents, APIs, databases) into structured knowledge graphs with full provenance tracking, making AI systems explainable and auditable.
|
Semantica is an open-source framework for building context graphs and decision intelligence layers for AI. It transforms unstructured data: documents, APIs, databases: into structured knowledge graphs with full provenance tracking, making AI systems explainable and auditable.
|
||||||
|
|
||||||
It's not a replacement for LangChain or LlamaIndex. It's the **accountability layer** that goes on top: recording decisions, tracing facts to sources, and making reasoning transparent.
|
It's not a replacement for LangChain or LlamaIndex. It's the **accountability layer** that goes on top: recording decisions, tracing facts to sources, and making reasoning transparent.
|
||||||
|
|
||||||
@@ -46,7 +46,7 @@ It's not a replacement for LangChain or LlamaIndex. It's the **accountability la
|
|||||||
|
|
||||||
<Accordion title="What makes Semantica different from LangChain or LlamaIndex?" icon="scale-balanced">
|
<Accordion title="What makes Semantica different from LangChain or LlamaIndex?" icon="scale-balanced">
|
||||||
|
|
||||||
Most frameworks stop at retrieval or generation. Semantica adds an **accountability layer**: every decision is recorded, every fact links to a source, and every reasoning step is explainable. It's designed for environments where you need to audit *why* an AI reached a conclusion, not just what it said.
|
Most frameworks stop at retrieval or generation. Semantica adds an **accountability layer**: every decision is recorded, every fact links to a source, and every reasoning step is explainable. It's designed for environments where you need to audit *why* an AI reached a conclusion: not just what it said.
|
||||||
|
|
||||||
Semantica works alongside these frameworks, not against them.
|
Semantica works alongside these frameworks, not against them.
|
||||||
|
|
||||||
@@ -54,11 +54,11 @@ Semantica works alongside these frameworks, not against them.
|
|||||||
|
|
||||||
<Accordion title="Does Semantica explain an LLM's internal reasoning or chain-of-thought?" icon="triangle-exclamation">
|
<Accordion title="Does Semantica explain an LLM's internal reasoning or chain-of-thought?" icon="triangle-exclamation">
|
||||||
|
|
||||||
No. 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.
|
No. 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: what context and data were used, what decision was produced, the provenance behind it, the relevant relationships, the policies applied, and the resulting decision trail.
|
What Semantica explains is *outside* the model: what context and data were used, what decision was produced, the provenance behind it, the relevant relationships, the policies applied, and the resulting decision trail.
|
||||||
|
|
||||||
In short, Semantica explains and audits *what the AI system did*, not the foundation model's private internal reasoning.
|
In short: Semantica explains and audits *what the AI system did* — not the foundation model's private internal reasoning.
|
||||||
|
|
||||||
</Accordion>
|
</Accordion>
|
||||||
|
|
||||||
@@ -70,9 +70,9 @@ Yes: MIT licensed, no vendor lock-in, no paywalled features. Some capabilities r
|
|||||||
|
|
||||||
<Accordion title="What's the latest version?" icon="star">
|
<Accordion title="What's the latest version?" icon="star">
|
||||||
|
|
||||||
**v0.6.8**: released September 2026.
|
**v0.6.7**: released August 2026.
|
||||||
|
|
||||||
Highlights: every release is now cryptographically signed (SLSA build provenance + Sigstore, closing the OpenSSF Scorecard Signed-Releases gap), real vector-store enumeration (`scan_vectors()`/`iter_vectors()`) across FAISS/SQLiteVec/PgVector/Qdrant/Weaviate/Milvus making `store migrate` functional, first-class Anthropic/Gemini/Ollama/DeepSeek/Novita LLM provider wrappers, a CI-friendly ontology quality gate, and 35 correctness fixes. The 0.6.x line also added first-class LangChain and CrewAI support and the Semantica RDF vocabulary with deterministic IRIs. See the [CHANGELOG](https://github.com/semantica-agi/semantica/blob/main/CHANGELOG.md) for the full history.
|
Highlights: first-class LangChain integration, SAP OData ingestor, human-editable Markdown round-trip persistence for `ContextGraph`, a structured Action layer for the reasoning engine, and a public `run_shacl_validation` entry point. The 0.6.x line also added first-class CrewAI support and the Semantica RDF vocabulary with deterministic IRIs. See the [CHANGELOG](https://github.com/semantica-agi/semantica/blob/main/CHANGELOG.md) for the full history.
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
pip install --upgrade semantica
|
pip install --upgrade semantica
|
||||||
@@ -348,6 +348,6 @@ set PYTHONIOENCODING=utf-8
|
|||||||
|
|
||||||
## Support
|
## Support
|
||||||
|
|
||||||
- [Discord](https://discord.gg/sV34vps5hH): community chat and live support.
|
- [Discord](https://discord.gg/sV34vps5hH) — Community chat and live support.
|
||||||
- [GitHub Issues](https://github.com/semantica-agi/semantica/issues): bug reports and feature requests.
|
- [GitHub Issues](https://github.com/semantica-agi/semantica/issues) — Bug reports and feature requests.
|
||||||
- [Contributing](/contributing-guide): help improve Semantica.
|
- [Contributing](/contributing-guide) — Help improve Semantica.
|
||||||
|
|||||||
+16
-24
@@ -42,7 +42,7 @@ icon: "rocket"
|
|||||||
Verify installation:
|
Verify installation:
|
||||||
```python
|
```python
|
||||||
import semantica
|
import semantica
|
||||||
print(semantica.__version__) # 0.6.8
|
print(semantica.__version__) # 0.6.7
|
||||||
```
|
```
|
||||||
</Check>
|
</Check>
|
||||||
</Step>
|
</Step>
|
||||||
@@ -84,13 +84,13 @@ icon: "rocket"
|
|||||||
# 1. Ingest
|
# 1. Ingest
|
||||||
sources = FileIngestor().ingest("data/report.pdf")
|
sources = FileIngestor().ingest("data/report.pdf")
|
||||||
|
|
||||||
# 2. Parse (extract_text returns a plain string for any supported format)
|
# 2. Parse
|
||||||
text = DocumentParser().extract_text(sources[0].path)
|
parsed = DocumentParser().parse(sources[0])
|
||||||
|
|
||||||
# 3. Extract (extractors take text, return Entity / Relation objects)
|
# 3. Extract
|
||||||
ner = NERExtractor(method="pattern") # no API key needed
|
ner = NERExtractor(method="pattern") # no API key needed
|
||||||
entities = ner.extract(text)
|
entities = ner.extract(parsed)
|
||||||
relationships = RelationExtractor(method="pattern").extract(text, entities=entities)
|
relationships = RelationExtractor().extract(parsed, entities=entities)
|
||||||
|
|
||||||
# 4. Build
|
# 4. Build
|
||||||
graph = GraphBuilder(merge_entities=True).build(
|
graph = GraphBuilder(merge_entities=True).build(
|
||||||
@@ -144,30 +144,22 @@ icon: "rocket"
|
|||||||
context = AgentContext(
|
context = AgentContext(
|
||||||
vector_store=VectorStore(backend="faiss", dimension=768),
|
vector_store=VectorStore(backend="faiss", dimension=768),
|
||||||
knowledge_graph=ContextGraph(advanced_analytics=True),
|
knowledge_graph=ContextGraph(advanced_analytics=True),
|
||||||
graph_expansion=True, # blend graph traversal into retrieval
|
|
||||||
max_expansion_hops=3, # how far to walk from the seed nodes
|
|
||||||
)
|
)
|
||||||
|
|
||||||
# store() runs extraction and populates both the vector index and the graph
|
# Load your knowledge graph
|
||||||
context.store([
|
context.load_graph("company_kg.json")
|
||||||
{"content": "Steve Wozniak co-founded Apple with Steve Jobs in 1976."},
|
|
||||||
{"content": "Tony Fadell led the iPod team at Apple, then founded Nest."},
|
|
||||||
])
|
|
||||||
|
|
||||||
# GraphRAG retrieval: seed from vector matches, expand along graph edges
|
# Multi-hop GraphRAG query
|
||||||
results = context.retrieve(
|
result = context.query(
|
||||||
"What companies were founded by people who worked at Apple?",
|
"What companies were founded by people who worked at Apple?",
|
||||||
use_graph=True,
|
mode="graphrag",
|
||||||
expand_graph=True,
|
reasoning=True,
|
||||||
)
|
)
|
||||||
for r in results:
|
|
||||||
print(f"[{r['score']:.3f}] {r['content'][:70]} (source: {r['source']})")
|
|
||||||
```
|
|
||||||
|
|
||||||
Each result carries `content`, `score`, `source`, and `metadata`. For a
|
# Every claim links back to a source node
|
||||||
grounded natural-language answer plus an auditable traversal, use
|
for claim in result.claims:
|
||||||
`context.query_with_reasoning(query, llm_provider=...)` — it returns
|
print(f"{claim.text} → source: {claim.source_node}")
|
||||||
`response`, `reasoning_path`, `sources`, and `confidence`.
|
```
|
||||||
|
|
||||||
**Next:** [GraphRAG concepts →](/concepts#graphrag)
|
**Next:** [GraphRAG concepts →](/concepts#graphrag)
|
||||||
</Tab>
|
</Tab>
|
||||||
|
|||||||
+32
-32
@@ -23,16 +23,16 @@ A persistent, queryable graph of everything an agent knows, decides, and reasons
|
|||||||
A first-class object in Semantica: a recorded agent choice with category, scenario, reasoning, outcome, confidence score, causal chain, and source provenance. Stored and searchable via `context.record_decision()`.
|
A first-class object in Semantica: a recorded agent choice with category, scenario, reasoning, outcome, confidence score, causal chain, and source provenance. Stored and searchable via `context.record_decision()`.
|
||||||
|
|
||||||
**Entity**
|
**Entity**
|
||||||
A distinct object or concept in the real world (person, organization, location, event, or abstract concept). Entities are nodes in a knowledge graph, each with typed properties and a source provenance record.
|
A distinct object or concept in the real world: a person, organization, location, event, or abstract concept. Entities are nodes in a knowledge graph, each with typed properties and a source provenance record.
|
||||||
|
|
||||||
**Knowledge Graph (KG)**
|
**Knowledge Graph (KG)**
|
||||||
A structured representation of knowledge using entities (nodes) and relationships (edges). Knowledge graphs enable reasoning, querying, semantic search, and traceable inference, unlike flat vector stores.
|
A structured representation of knowledge using entities (nodes) and relationships (edges). Knowledge graphs enable reasoning, querying, semantic search, and traceable inference: unlike flat vector stores.
|
||||||
|
|
||||||
**Relationship**
|
**Relationship**
|
||||||
A directed, typed connection between two entities (e.g., `works_for`, `located_in`, `founded_by`). Relationships carry confidence scores and provenance back to the source document.
|
A directed, typed connection between two entities: e.g., `works_for`, `located_in`, `founded_by`. Relationships carry confidence scores and provenance back to the source document.
|
||||||
|
|
||||||
**Semantic**
|
**Semantic**
|
||||||
Relating to meaning in language or logic. Semantic understanding captures context and intent, going beyond keyword matching to understand what text *means*.
|
Relating to meaning in language or logic. Semantic understanding captures context and intent: going beyond keyword matching to understand what text *means*.
|
||||||
|
|
||||||
|
|
||||||
## Data Processing
|
## Data Processing
|
||||||
@@ -41,19 +41,19 @@ Relating to meaning in language or logic. Semantic understanding captures contex
|
|||||||
Splitting large documents into smaller pieces while preserving semantic context. Semantica supports recursive, semantic boundary, entity-aware, relation-aware, sliding window, structural, and table-aware chunking strategies.
|
Splitting large documents into smaller pieces while preserving semantic context. Semantica supports recursive, semantic boundary, entity-aware, relation-aware, sliding window, structural, and table-aware chunking strategies.
|
||||||
|
|
||||||
**Ingestion**
|
**Ingestion**
|
||||||
Loading data from external sources (files, databases, APIs, streams) into the pipeline as a unified `SourceDocument`. The first stage in every Semantica pipeline.
|
Loading data from external sources: files, databases, APIs, streams: into the pipeline as a unified `SourceDocument`. The first stage in every Semantica pipeline.
|
||||||
|
|
||||||
**Normalization**
|
**Normalization**
|
||||||
Standardizing data into a consistent canonical form by converting dates to ISO format, canonicalizing entity names, fixing encoding issues, and stripping noise. Ensures downstream extraction works on clean, consistent text.
|
Standardizing data into a consistent canonical form: converting dates to ISO format, canonicalizing entity names, fixing encoding issues, stripping noise. Ensures downstream extraction works on clean, consistent text.
|
||||||
|
|
||||||
**Parsing**
|
**Parsing**
|
||||||
Extracting structured text, layout, and metadata from unstructured or semi-structured documents (PDFs, Word files, HTML, PPTX). `DoclingParser` additionally handles multi-column layouts, merged-cell tables, and OCR.
|
Extracting structured text, layout, and metadata from unstructured or semi-structured documents: PDFs, Word files, HTML, PPTX. `DoclingParser` additionally handles multi-column layouts, merged-cell tables, and OCR.
|
||||||
|
|
||||||
|
|
||||||
## Artificial Intelligence
|
## Artificial Intelligence
|
||||||
|
|
||||||
**Abductive Reasoning**
|
**Abductive Reasoning**
|
||||||
Inference to the most plausible explanation for observed facts. One of six reasoning engines in `semantica.reasoning`, returning the most likely hypothesis given available evidence.
|
Inference to the most plausible explanation for observed facts. One of six reasoning engines in `semantica.reasoning`: returns the most likely hypothesis given available evidence.
|
||||||
|
|
||||||
**Datalog**
|
**Datalog**
|
||||||
A declarative logic programming language for knowledge base queries. Semantica's `DatalogEngine` supports recursive Horn clause rules with bottom-up semi-naive fixpoint semantics. Added in v0.4.0.
|
A declarative logic programming language for knowledge base queries. Semantica's `DatalogEngine` supports recursive Horn clause rules with bottom-up semi-naive fixpoint semantics. Added in v0.4.0.
|
||||||
@@ -62,7 +62,7 @@ A declarative logic programming language for knowledge base queries. Semantica's
|
|||||||
An advanced RAG approach that combines vector similarity search with knowledge graph traversal. Every LLM response is grounded in structured graph context, with each claim traceable to a source node. Eliminates hallucination without source attribution.
|
An advanced RAG approach that combines vector similarity search with knowledge graph traversal. Every LLM response is grounded in structured graph context, with each claim traceable to a source node. Eliminates hallucination without source attribution.
|
||||||
|
|
||||||
**Inference**
|
**Inference**
|
||||||
Deriving new facts or conclusions from existing knowledge using logical rules, without the derived facts being explicitly present in the source data.
|
Deriving new facts or conclusions from existing knowledge using logical rules: without the derived facts being explicitly present in the source data.
|
||||||
|
|
||||||
**LLM (Large Language Model)**
|
**LLM (Large Language Model)**
|
||||||
An AI model trained on large text corpora, capable of understanding and generating natural language. Semantica integrates with 8+ LLM providers for entity extraction, relation extraction, and reasoning.
|
An AI model trained on large text corpora, capable of understanding and generating natural language. Semantica integrates with 8+ LLM providers for entity extraction, relation extraction, and reasoning.
|
||||||
@@ -74,7 +74,7 @@ A technique that enhances LLM outputs by retrieving relevant context from a know
|
|||||||
## Knowledge Graph Components
|
## Knowledge Graph Components
|
||||||
|
|
||||||
**Allen Interval Algebra**
|
**Allen Interval Algebra**
|
||||||
A system of 13 relations for describing how two time intervals relate (before, after, meets, overlaps, during, starts, finishes, equals, and their inverses). Supported in `TemporalKnowledgeGraph` since v0.4.0.
|
A system of 13 relations for describing how two time intervals relate: before, after, meets, overlaps, during, starts, finishes, equals, and their inverses. Supported in `TemporalKnowledgeGraph` since v0.4.0.
|
||||||
|
|
||||||
**BiTemporalFact**
|
**BiTemporalFact**
|
||||||
A fact with two independent time dimensions: *valid time* (when it was true in the world) and *transaction time* (when it was recorded in the system). Enables full audit trails for slowly changing data.
|
A fact with two independent time dimensions: *valid time* (when it was true in the world) and *transaction time* (when it was recorded in the system). Enables full audit trails for slowly changing data.
|
||||||
@@ -86,43 +86,43 @@ A directed connection between two nodes in a graph, representing a typed relatio
|
|||||||
A vertex in a knowledge graph representing an entity or concept. Nodes carry typed properties, a confidence score, and provenance linking back to the source document.
|
A vertex in a knowledge graph representing an entity or concept. Nodes carry typed properties, a confidence score, and provenance linking back to the source document.
|
||||||
|
|
||||||
**Property**
|
**Property**
|
||||||
An attribute or characteristic of an entity or relationship, such as name, date, URI, confidence score, or source URL.
|
An attribute or characteristic of an entity or relationship: name, date, URI, confidence score, source URL.
|
||||||
|
|
||||||
**Temporal Graph**
|
**Temporal Graph**
|
||||||
A knowledge graph where nodes and edges carry `valid_from` / `valid_until` time windows, enabling point-in-time queries and historical state reconstruction.
|
A knowledge graph where nodes and edges carry `valid_from` / `valid_until` time windows, enabling point-in-time queries and historical state reconstruction.
|
||||||
|
|
||||||
**Triplet**
|
**Triplet**
|
||||||
The atomic unit of knowledge: a `(subject, predicate, object)` triple (e.g., `(Apple_Inc, founded_by, Steve_Jobs)`). The building block of RDF and SPARQL-based storage.
|
The atomic unit of knowledge: a `(subject, predicate, object)` triple: e.g., `(Apple_Inc, founded_by, Steve_Jobs)`. The building block of RDF and SPARQL-based storage.
|
||||||
|
|
||||||
|
|
||||||
## Entity Recognition & Extraction
|
## Entity Recognition & Extraction
|
||||||
|
|
||||||
**Coreference Resolution**
|
**Coreference Resolution**
|
||||||
Determining when multiple expressions in text refer to the same entity (e.g., "Apple" and "the company" both referring to Apple Inc.). Handled by `CoreferenceResolver` in `semantica.semantic_extract`.
|
Determining when multiple expressions in text refer to the same entity: e.g., "Apple" and "the company" both referring to Apple Inc. Handled by `CoreferenceResolver` in `semantica.semantic_extract`.
|
||||||
|
|
||||||
**Entity Resolution**
|
**Entity Resolution**
|
||||||
Determining when two entity mentions across different documents refer to the same real-world entity. Also called entity linking or deduplication. Uses similarity scoring, blocking, and semantic embeddings.
|
Determining when two entity mentions across different documents refer to the same real-world entity. Also called entity linking or deduplication. Uses similarity scoring, blocking, and semantic embeddings.
|
||||||
|
|
||||||
**Event Detection**
|
**Event Detection**
|
||||||
Identifying and classifying events in text (acquisitions, partnerships, product launches, regulatory decisions). Handled by `EventDetector` in `semantica.semantic_extract`.
|
Identifying and classifying events in text: acquisitions, partnerships, product launches, regulatory decisions. Handled by `EventDetector` in `semantica.semantic_extract`.
|
||||||
|
|
||||||
**Named Entity Recognition (NER)**
|
**Named Entity Recognition (NER)**
|
||||||
Identifying and classifying named entities in text into predefined categories (persons, organizations, locations, dates, products, and custom types). Three modes: pattern-based, ML-based, and LLM-based.
|
Identifying and classifying named entities in text into predefined categories: persons, organizations, locations, dates, products, and custom types. Three modes: pattern-based, ML-based, and LLM-based.
|
||||||
|
|
||||||
**Relationship Extraction**
|
**Relationship Extraction**
|
||||||
Identifying and extracting typed semantic relationships between entities (such as `(Google, acquired, DeepMind)`) from raw text.
|
Identifying and extracting typed semantic relationships between entities: e.g., `(Google, acquired, DeepMind)`: from raw text.
|
||||||
|
|
||||||
|
|
||||||
## Ontology & Schema
|
## Ontology & Schema
|
||||||
|
|
||||||
**Axiom**
|
**Axiom**
|
||||||
A statement accepted as true in an ontology, used to define logical constraints (e.g., "every Person must have a name", "Organization can have at most one CEO at a time").
|
A statement accepted as true in an ontology, used to define logical constraints: e.g., "every Person must have a name", "Organization can have at most one CEO at a time".
|
||||||
|
|
||||||
**Class**
|
**Class**
|
||||||
A category or type of entity in an ontology (`Person`, `Organization`, `Location`). Classes form a hierarchy and carry constraints validated by SHACL.
|
A category or type of entity in an ontology: `Person`, `Organization`, `Location`. Classes form a hierarchy and carry constraints validated by SHACL.
|
||||||
|
|
||||||
**Ontology**
|
**Ontology**
|
||||||
A formal specification of domain concepts, relationships, and constraints, typically expressed in OWL. Semantica can auto-generate ontologies from knowledge graphs or import existing OWL/RDF/Turtle files.
|
A formal specification of domain concepts, relationships, and constraints: typically expressed in OWL. Semantica can auto-generate ontologies from knowledge graphs or import existing OWL/RDF/Turtle files.
|
||||||
|
|
||||||
**Ontology Hub**
|
**Ontology Hub**
|
||||||
Semantica's v0.5.0 visual browser UI for the full ontology lifecycle: visual class editor, SHACL Studio, alignment authoring, health dashboard, and version-controlled diffs.
|
Semantica's v0.5.0 visual browser UI for the full ontology lifecycle: visual class editor, SHACL Studio, alignment authoring, health dashboard, and version-controlled diffs.
|
||||||
@@ -140,13 +140,13 @@ A W3C standard for representing controlled vocabularies, taxonomies, and thesaur
|
|||||||
## Storage & Retrieval
|
## Storage & Retrieval
|
||||||
|
|
||||||
**Embedding**
|
**Embedding**
|
||||||
A dense numerical vector that represents text, images, or other data in a continuous semantic space. Entities with similar meaning produce vectors that are close together, enabling similarity search and semantic matching.
|
A dense numerical vector that represents text, images, or other data in a continuous semantic space. Entities with similar meaning produce vectors that are close together: enabling similarity search and semantic matching.
|
||||||
|
|
||||||
**Graph Database**
|
**Graph Database**
|
||||||
A database optimized for storing and querying graph-structured data using node and edge primitives. Semantica supports Neo4j, FalkorDB, Apache AGE, and Amazon Neptune.
|
A database optimized for storing and querying graph-structured data using node and edge primitives. Semantica supports Neo4j, FalkorDB, Apache AGE, and Amazon Neptune.
|
||||||
|
|
||||||
**Hybrid Search**
|
**Hybrid Search**
|
||||||
A retrieval strategy combining vector similarity search with keyword or metadata filtering, achieving higher accuracy than either approach alone.
|
A retrieval strategy combining vector similarity search with keyword or metadata filtering: higher accuracy than either approach alone.
|
||||||
|
|
||||||
**Triplet Store**
|
**Triplet Store**
|
||||||
A database designed specifically for storing and querying RDF `(subject, predicate, object)` triples. Semantica supports embedded Oxigraph as well as Blazegraph, Apache Jena, and RDF4J.
|
A database designed specifically for storing and querying RDF `(subject, predicate, object)` triples. Semantica supports embedded Oxigraph as well as Blazegraph, Apache Jena, and RDF4J.
|
||||||
@@ -158,19 +158,19 @@ A database optimized for storing and searching high-dimensional embedding vector
|
|||||||
## Graph Analytics
|
## Graph Analytics
|
||||||
|
|
||||||
**Centrality**
|
**Centrality**
|
||||||
A measure of a node's importance in the graph. Common metrics include PageRank (link-based importance), betweenness centrality (bridge nodes), and closeness centrality (average distance to all others).
|
A measure of a node's importance in the graph. Common metrics: PageRank (link-based importance), betweenness centrality (bridge nodes), closeness centrality (average distance to all others).
|
||||||
|
|
||||||
**Community Detection**
|
**Community Detection**
|
||||||
Identifying groups of densely connected nodes (clusters that share more internal links than external ones). Used for finding subject communities, fraud rings, and organizational clusters.
|
Identifying groups of densely connected nodes: clusters that share more internal links than external ones. Used for finding subject communities, fraud rings, and organizational clusters.
|
||||||
|
|
||||||
**Distance Band**
|
**Distance Band**
|
||||||
A classification of a node's semantic proximity to a target (`near`, `mid`, or `far`) based on embedding distance thresholds. Part of Distance Intelligence (v0.5.0).
|
A classification of a node's semantic proximity to a target: `near`, `mid`, or `far`, based on embedding distance thresholds. Part of Distance Intelligence (v0.5.0).
|
||||||
|
|
||||||
**Distance Intelligence**
|
**Distance Intelligence**
|
||||||
Semantica's v0.5.0 feature for semantic neighborhood exploration, including N×N distance matrices, ego-mode visualization centered on a single entity, and distance band classification across the graph.
|
Semantica's v0.5.0 feature for semantic neighborhood exploration: N×N distance matrices, ego-mode visualization centered on a single entity, and distance band classification across the graph.
|
||||||
|
|
||||||
**PageRank**
|
**PageRank**
|
||||||
An algorithm measuring node importance based on the structure of incoming relationships; originally designed for web pages, but applicable to any directed graph.
|
An algorithm measuring node importance based on the structure of incoming relationships: originally designed for web pages, applicable to any directed graph.
|
||||||
|
|
||||||
|
|
||||||
## Query Languages & Standards
|
## Query Languages & Standards
|
||||||
@@ -194,13 +194,13 @@ The W3C query language for RDF data. Semantica's `SparqlReasoner` uses SPARQL fo
|
|||||||
Handling contradictory facts from multiple sources in the same knowledge graph. Semantica's `ConflictDetector` surfaces conflicts; resolution strategies include prefer-most-recent, prefer-most-reliable, majority-vote, and flag-for-review.
|
Handling contradictory facts from multiple sources in the same knowledge graph. Semantica's `ConflictDetector` surfaces conflicts; resolution strategies include prefer-most-recent, prefer-most-reliable, majority-vote, and flag-for-review.
|
||||||
|
|
||||||
**Data Provenance**
|
**Data Provenance**
|
||||||
Complete information about the origin, history, and lineage of every fact (source document, extraction method, timestamp, confidence score). W3C PROV-O compliant in Semantica.
|
Complete information about the origin, history, and lineage of every fact: source document, extraction method, timestamp, confidence score. W3C PROV-O compliant in Semantica.
|
||||||
|
|
||||||
**Deduplication**
|
**Deduplication**
|
||||||
Identifying and merging duplicate entity records. Semantica v2 strategies (`blocking_v2`, `hybrid_v2`, `semantic_v2`) are up to 7x faster than v1.
|
Identifying and merging duplicate entity records. Semantica v2 strategies (`blocking_v2`, `hybrid_v2`, `semantic_v2`) are up to 7x faster than v1.
|
||||||
|
|
||||||
**W3C PROV-O**
|
**W3C PROV-O**
|
||||||
The W3C provenance ontology standard. Semantica tracks lineage across all modules in PROV-O compliant format, suitable for HIPAA, SOX, GDPR, and FDA 21 CFR Part 11 compliance.
|
The W3C provenance ontology standard. Semantica tracks lineage across all modules in PROV-O compliant format: suitable for HIPAA, SOX, GDPR, and FDA 21 CFR Part 11 compliance.
|
||||||
|
|
||||||
|
|
||||||
## Security Terms
|
## Security Terms
|
||||||
@@ -214,7 +214,7 @@ A vulnerability in XML parsers that allows attackers to read arbitrary files or
|
|||||||
|
|
||||||
## See Also
|
## See Also
|
||||||
|
|
||||||
- [Core Concepts](/concepts): deeper explanation of key ideas with code examples.
|
- [Core Concepts](/concepts) — Deeper explanation of key ideas with code examples.
|
||||||
- [Getting Started](/getting-started): first working examples with no prior graph experience required.
|
- [Getting Started](/getting-started) — First working examples: no prior graph experience required.
|
||||||
- [Modules Guide](/modules): all 27 modules explained with code and pipeline chains.
|
- [Modules Guide](/modules) — All 27 modules explained with code and pipeline chains.
|
||||||
- [API Reference](/reference/context): complete technical reference for every class and method.
|
- [API Reference](/reference/context) — Complete technical reference for every class and method.
|
||||||
|
|||||||
+10
-10
@@ -9,9 +9,9 @@ icon: "scale-balanced"
|
|||||||
|
|
||||||
## Roles
|
## Roles
|
||||||
|
|
||||||
- **Maintainers**: Semantica team. Review and merge PRs, manage releases and code quality, set project direction and community standards.
|
- **Maintainers** — Semantica team: review and merge PRs, manage releases and code quality, set project direction and community standards.
|
||||||
- **Contributors**: submit code, documentation, and bug reports. Help with issues and reviews. Recognized in [CONTRIBUTORS.md](https://github.com/semantica-agi/semantica/blob/main/CONTRIBUTORS.md).
|
- **Contributors** — Submit code, documentation, and bug reports. Help with issues and reviews. Recognized in [CONTRIBUTORS.md](https://github.com/semantica-agi/semantica/blob/main/CONTRIBUTORS.md).
|
||||||
- **Community Members**: use Semantica, provide feedback, share use cases, and participate in GitHub Discussions and Discord.
|
- **Community Members** — Use Semantica, provide feedback, share use cases, and participate in GitHub Discussions and Discord.
|
||||||
|
|
||||||
|
|
||||||
## Decision Process
|
## Decision Process
|
||||||
@@ -65,11 +65,11 @@ Semantica follows **Semantic Versioning** (`MAJOR.MINOR.PATCH`):
|
|||||||
|
|
||||||
## Project Goals
|
## Project Goals
|
||||||
|
|
||||||
- **Usability**: easy to use and understand with sensible defaults, clear documentation, and minimal ceremony.
|
- **Usability** — Easy to use and understand: sensible defaults, clear documentation, minimal ceremony.
|
||||||
- **Reliability**: production-ready quality tested across Python versions, platforms, and real-world workloads.
|
- **Reliability** — Production-ready quality: tested across Python versions, platforms, and real-world workloads.
|
||||||
- **Performance**: efficient and scalable from single-machine notebooks to enterprise graph databases.
|
- **Performance** — Efficient and scalable: from single-machine notebooks to enterprise graph databases.
|
||||||
- **Extensibility**: easy to extend with plugins and custom modules via the `PluginRegistry` pattern.
|
- **Extensibility** — Easy to extend with plugins and custom modules via the `PluginRegistry` pattern.
|
||||||
- **Community**: welcoming and inclusive. All backgrounds and experience levels contribute and are recognized.
|
- **Community** — Welcoming and inclusive: all backgrounds and experience levels contribute and are recognized.
|
||||||
|
|
||||||
|
|
||||||
## License
|
## License
|
||||||
@@ -79,5 +79,5 @@ MIT License: see [LICENSE](https://github.com/semantica-agi/semantica/blob/main/
|
|||||||
|
|
||||||
## See Also
|
## See Also
|
||||||
|
|
||||||
- [Contributing](/contributing-guide): how to submit changes.
|
- [Contributing](/contributing-guide) — How to submit changes.
|
||||||
- [Community](/community): community guidelines and channels.
|
- [Community](/community) — Community guidelines and channels.
|
||||||
|
|||||||
@@ -661,7 +661,7 @@ print("Total memories: {}".format(s.get("total_items", 0)))
|
|||||||
- [Decision Intelligence](/guides/decision-intelligence) — Recording decisions as graph nodes with causal chains and policy gating.
|
- [Decision Intelligence](/guides/decision-intelligence) — Recording decisions as graph nodes with causal chains and policy gating.
|
||||||
- [Multi-Agent Systems](/guides/multi-agent) — Coordinating multiple agents through a shared `AgentContext` and save/load handoffs.
|
- [Multi-Agent Systems](/guides/multi-agent) — Coordinating multiple agents through a shared `AgentContext` and save/load handoffs.
|
||||||
- [LLM Integrations](/guides/llm-integrations) — Configuring the LLM provider passed to `query_with_reasoning()`.
|
- [LLM Integrations](/guides/llm-integrations) — Configuring the LLM provider passed to `query_with_reasoning()`.
|
||||||
- [Deduplication Guide](/guides/deduplication) — Full reference for `DuplicateDetector`, `EntityMerger`, similarity methods, and cluster strategies.
|
- [Deduplication Guide](deduplication) — Full reference for `DuplicateDetector`, `EntityMerger`, similarity methods, and cluster strategies.
|
||||||
- [Ontology Management](/guides/ontology) — Generate and validate OWL ontologies from the knowledge graph; export to Turtle, OWL/XML, JSON-LD.
|
- [Ontology Management](ontology) — Generate and validate OWL ontologies from the knowledge graph; export to Turtle, OWL/XML, JSON-LD.
|
||||||
- [Context Module Reference](../reference/context) — Full API: `AgentContext`, `AgentMemory`, `MemoryItem`, `ContextRetriever`.
|
- [Context Module Reference](../reference/context) — Full API: `AgentContext`, `AgentMemory`, `MemoryItem`, `ContextRetriever`.
|
||||||
- [Vector Store Reference](../reference/vector_store) — FAISS, Qdrant, pgvector, Pinecone backends.
|
- [Vector Store Reference](../reference/vector_store) — FAISS, Qdrant, pgvector, Pinecone backends.
|
||||||
|
|||||||
@@ -497,7 +497,7 @@ print("Model v1.1 verified and approved for production.")
|
|||||||
## Related Guides
|
## Related Guides
|
||||||
|
|
||||||
- [Context Graphs](/guides/context-graphs) — `ContextGraph.to_dict()` feeds `create_snapshot()`
|
- [Context Graphs](/guides/context-graphs) — `ContextGraph.to_dict()` feeds `create_snapshot()`
|
||||||
- [Ontology Management](/guides/ontology) — pair ontology versioning with graph versioning for a complete schema + data audit trail
|
- [Ontology Management](ontology) — pair ontology versioning with graph versioning for a complete schema + data audit trail
|
||||||
- [SHACL Validation](/guides/shacl-validation) — validate graph data at each version gate before snapshotting
|
- [SHACL Validation](/guides/shacl-validation) — validate graph data at each version gate before snapshotting
|
||||||
- [Provenance](/guides/provenance) — combine change management with W3C PROV-O lineage for a full audit trail
|
- [Provenance](provenance) — combine change management with W3C PROV-O lineage for a full audit trail
|
||||||
- [Visualization](/guides/visualization) — `TemporalVisualizer.visualize_snapshot_comparison()` and `visualize_metrics_evolution()` render version diffs as interactive charts
|
- [Visualization](visualization) — `TemporalVisualizer.visualize_snapshot_comparison()` and `visualize_metrics_evolution()` render version diffs as interactive charts
|
||||||
|
|||||||
@@ -65,7 +65,7 @@ flowchart TD
|
|||||||
G --> H[SHACL Validation]
|
G --> H[SHACL Validation]
|
||||||
```
|
```
|
||||||
|
|
||||||
1. **Deduplication** — Merge duplicate nodes so each entity has exactly one canonical record. Conflict resolution operates on a single canonical entity; you must identify it before comparing what different sources say about it. See [Deduplication](/guides/deduplication).
|
1. **Deduplication** — Merge duplicate nodes so each entity has exactly one canonical record. Conflict resolution operates on a single canonical entity; you must identify it before comparing what different sources say about it. See [Deduplication](deduplication).
|
||||||
2. **Conflict Detection** — Call `detect_entity_conflicts()` to surface all property disagreements at once, or `detect_value_conflicts()` to target a specific property.
|
2. **Conflict Detection** — Call `detect_entity_conflicts()` to surface all property disagreements at once, or `detect_value_conflicts()` to target a specific property.
|
||||||
3. **Resolution** — For each conflict, apply a strategy (`CREDIBILITY_WEIGHTED`, `MOST_RECENT`, `VOTING`, etc.) or route it for expert review (`EXPERT_REVIEW`).
|
3. **Resolution** — For each conflict, apply a strategy (`CREDIBILITY_WEIGHTED`, `MOST_RECENT`, `VOTING`, etc.) or route it for expert review (`EXPERT_REVIEW`).
|
||||||
4. **Persist Canonical Values** — Write resolved values back to your canonical entities or graph store. See [Persisting resolved values](#persisting-resolved-values).
|
4. **Persist Canonical Values** — Write resolved values back to your canonical entities or graph store. See [Persisting resolved values](#persisting-resolved-values).
|
||||||
@@ -696,8 +696,8 @@ Calling `set_resolution_rule()` for every entity-property pair just to apply the
|
|||||||
|
|
||||||
## Related Guides
|
## Related Guides
|
||||||
|
|
||||||
- [Deduplication](/guides/deduplication) — remove duplicate nodes before running conflict detection
|
- [Deduplication](deduplication) — remove duplicate nodes before running conflict detection
|
||||||
- [Provenance](/guides/provenance) — track which source each resolved value came from, and verify the audit trail cryptographically
|
- [Provenance](provenance) — track which source each resolved value came from, and verify the audit trail cryptographically
|
||||||
- [SHACL Validation](/guides/shacl-validation) — enforce structural constraints after conflicts are resolved
|
- [SHACL Validation](/guides/shacl-validation) — enforce structural constraints after conflicts are resolved
|
||||||
- [Change Management](/guides/change-management) — snapshot the graph before and after conflict resolution runs
|
- [Change Management](/guides/change-management) — snapshot the graph before and after conflict resolution runs
|
||||||
- [Ontology Management](/guides/ontology) — align entity types to a shared vocabulary to reduce type conflicts at the schema level
|
- [Ontology Management](ontology) — align entity types to a shared vocabulary to reduce type conflicts at the schema level
|
||||||
|
|||||||
@@ -489,7 +489,7 @@ context2.load("agent_state/")
|
|||||||
|
|
||||||
## Common Pitfalls
|
## Common Pitfalls
|
||||||
|
|
||||||
**Duplicate entities.** Adding "APT-29", "APT29", and "Cozy Bear" as separate nodes fragments the graph when they should be one entity. Use consistent naming conventions upfront, or use `detect_duplicates()` and `EntityMerger` from the [Deduplication](/guides/deduplication) guide to merge them after ingestion.
|
**Duplicate entities.** Adding "APT-29", "APT29", and "Cozy Bear" as separate nodes fragments the graph when they should be one entity. Use consistent naming conventions upfront, or use `detect_duplicates()` and `EntityMerger` from the [Deduplication](deduplication) guide to merge them after ingestion.
|
||||||
|
|
||||||
**Inconsistent naming conventions.** Mixing "ThreatActor", "threat_actor", and "Threat-Actor" as node types breaks queries that filter by type. Pick one convention and enforce it across all data sources.
|
**Inconsistent naming conventions.** Mixing "ThreatActor", "threat_actor", and "Threat-Actor" as node types breaks queries that filter by type. Pick one convention and enforce it across all data sources.
|
||||||
|
|
||||||
@@ -706,8 +706,8 @@ for n in stress_reach:
|
|||||||
|
|
||||||
- [Graph Analytics](/guides/graph-analytics) — centrality rankings, community detection, node embeddings, and link prediction on a populated `ContextGraph`
|
- [Graph Analytics](/guides/graph-analytics) — centrality rankings, community detection, node embeddings, and link prediction on a populated `ContextGraph`
|
||||||
- [Decision Intelligence](/guides/decision-intelligence) — recording decisions as typed nodes, causal chain analysis, precedent search, and policy enforcement
|
- [Decision Intelligence](/guides/decision-intelligence) — recording decisions as typed nodes, causal chain analysis, precedent search, and policy enforcement
|
||||||
- [Ingest](/guides/ingest) — loading data from PDFs, APIs, databases, STIX bundles, and RSS feeds into the graph
|
- [Ingest](ingest) — loading data from PDFs, APIs, databases, STIX bundles, and RSS feeds into the graph
|
||||||
- [Deduplication](/guides/deduplication) — detecting and merging near-duplicate nodes before insertion to prevent graph fragmentation
|
- [Deduplication](deduplication) — detecting and merging near-duplicate nodes before insertion to prevent graph fragmentation
|
||||||
- [Reasoning](/guides/reasoning) — temporal interval algebra (Allen relations), forward/backward chaining, and SPARQL over the knowledge graph
|
- [Reasoning](reasoning) — temporal interval algebra (Allen relations), forward/backward chaining, and SPARQL over the knowledge graph
|
||||||
- [Ontology Management](/guides/ontology) — deriving formal OWL ontologies from `graph.to_dict()` for downstream reasoning engines
|
- [Ontology Management](ontology) — deriving formal OWL ontologies from `graph.to_dict()` for downstream reasoning engines
|
||||||
- [Context Module Reference](../reference/context) — full API for `AgentContext`, `ContextGraph`, `ContextNode`, `ContextEdge`
|
- [Context Module Reference](../reference/context) — full API for `AgentContext`, `ContextGraph`, `ContextNode`, `ContextEdge`
|
||||||
|
|||||||
@@ -102,8 +102,9 @@ The `Decision` dataclass that backs this node has the following fields — these
|
|||||||
from semantica.context import Decision
|
from semantica.context import Decision
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
|
|
||||||
|
# Constructing a Decision explicitly (alternative to record_decision)
|
||||||
d = Decision(
|
d = Decision(
|
||||||
decision_id = None, # required arg — None/"" auto-generates a UUID
|
decision_id = "dec_001", # UUID — auto-generated if omitted via record_decision
|
||||||
category = "threat_classification",
|
category = "threat_classification",
|
||||||
scenario = "Unattributed C2 cluster",
|
scenario = "Unattributed C2 cluster",
|
||||||
reasoning = "Infrastructure overlaps APT29 ASN",
|
reasoning = "Infrastructure overlaps APT29 ASN",
|
||||||
@@ -116,29 +117,9 @@ d = Decision(
|
|||||||
valid_until = "2025-09-30T23:59:59", # ISO datetime
|
valid_until = "2025-09-30T23:59:59", # ISO datetime
|
||||||
metadata = {"source_feed": "isac_partner_b"},
|
metadata = {"source_feed": "isac_partner_b"},
|
||||||
)
|
)
|
||||||
|
graph.add_decision(d)
|
||||||
```
|
```
|
||||||
|
|
||||||
To actually store a decision built this way, pass its fields to `ContextGraph.add_decision()` as keyword arguments — this is the alternative to `record_decision()` for cases where you want `valid_from`/`valid_until` or extra metadata fields alongside the required ones:
|
|
||||||
|
|
||||||
```python
|
|
||||||
decision_id = graph.add_decision(
|
|
||||||
category = "threat_classification",
|
|
||||||
scenario = "Unattributed C2 cluster",
|
|
||||||
reasoning = "Infrastructure overlaps APT29 ASN",
|
|
||||||
outcome = "classified_as_apt29_cluster",
|
|
||||||
confidence = 0.88, # float 0.0–1.0
|
|
||||||
decision_maker = "cti_pipeline_v2",
|
|
||||||
# optional fields:
|
|
||||||
valid_from = "2025-07-01T00:00:00", # ISO datetime
|
|
||||||
valid_until = "2025-09-30T23:59:59", # ISO datetime
|
|
||||||
source_feed = "isac_partner_b", # extra kwargs are stored as metadata
|
|
||||||
)
|
|
||||||
```
|
|
||||||
|
|
||||||
<Warning>
|
|
||||||
Only pass keyword arguments to `add_decision()`, not a pre-built `Decision` object. `add_decision(Decision(...))` stores the node directly and skips the indexing step that `record_decision()` performs, so the decision becomes invisible to `find_precedents()`, `get_causal_chain()`, and `get_decision_insights()`, and `trace_decision_causality()` raises `ValueError` if you call it on one. The keyword-argument form above does not have this problem — it delegates to `record_decision()` internally. Note that, like `record_decision()`, it always generates its own `decision_id` (returned from the call); there is no way to force a specific ID.
|
|
||||||
</Warning>
|
|
||||||
|
|
||||||
## Searching Precedents Before Deciding
|
## Searching Precedents Before Deciding
|
||||||
|
|
||||||
Before making a significant call, the system should search past decisions for similar scenarios. This is how you prevent the same cluster being classified differently across two agent runs — the second agent finds the first agent's decision and uses it as a prior.
|
Before making a significant call, the system should search past decisions for similar scenarios. This is how you prevent the same cluster being classified differently across two agent runs — the second agent finds the first agent's decision and uses it as a prior.
|
||||||
@@ -156,7 +137,7 @@ for p in precedents:
|
|||||||
print(" Similarity: {:.3f}".format(p.metadata.get("similarity_score", 0)))
|
print(" Similarity: {:.3f}".format(p.metadata.get("similarity_score", 0)))
|
||||||
```
|
```
|
||||||
|
|
||||||
Hybrid search blends two signals: lexical overlap between the query and each decision's `scenario`, `reasoning`, and `entities` text (weight 0.7 — word-level Jaccard similarity, with a character-bigram fallback for CJK-style queries), and structural similarity based on how many other nodes each decision connects to in the graph (weight 0.3, only computed when the graph was built with `advanced_analytics=True`). The result is a ranked list of `Decision` objects, filtered to those scoring at least `similarity_threshold` (default 0.5) — because the match is lexical rather than embedding-based, precedents phrased very differently from the query may not surface even if they describe a similar scenario.
|
Hybrid search blends two signals: semantic similarity over the `scenario` and `reasoning` text (weight 0.7), and structural graph proximity via Node2Vec embeddings (weight 0.3). The result is a ranked list of `Decision` objects — the most similar past decisions float to the top regardless of how differently they were phrased.
|
||||||
|
|
||||||
## Building a Causal Chain
|
## Building a Causal Chain
|
||||||
|
|
||||||
@@ -281,13 +262,8 @@ d = Decision(
|
|||||||
)
|
)
|
||||||
|
|
||||||
if engine.check_compliance(d, "cti_confidence_gate"):
|
if engine.check_compliance(d, "cti_confidence_gate"):
|
||||||
# Pass fields as kwargs, not the Decision object itself — see the
|
graph.add_decision(d)
|
||||||
# warning above. add_decision() generates its own decision_id.
|
engine.record_policy_application(d.decision_id, "cti_confidence_gate", "1.0")
|
||||||
decision_id = graph.add_decision(
|
|
||||||
category=d.category, scenario=d.scenario, reasoning=d.reasoning,
|
|
||||||
outcome=d.outcome, confidence=d.confidence, decision_maker=d.decision_maker,
|
|
||||||
)
|
|
||||||
engine.record_policy_application(decision_id, "cti_confidence_gate", "1.0")
|
|
||||||
print("Decision recorded — policy compliant.")
|
print("Decision recorded — policy compliant.")
|
||||||
else:
|
else:
|
||||||
print("Decision blocked — confidence 0.62 below policy minimum 0.80.")
|
print("Decision blocked — confidence 0.62 below policy minimum 0.80.")
|
||||||
@@ -614,7 +590,7 @@ if engine.check_compliance(d, "lending_policy_v3"):
|
|||||||
decision_maker=d.decision_maker,
|
decision_maker=d.decision_maker,
|
||||||
)
|
)
|
||||||
graph.add_causal_relationship(stress_id, loan_id, "INFLUENCED")
|
graph.add_causal_relationship(stress_id, loan_id, "INFLUENCED")
|
||||||
engine.record_policy_application(loan_id, "lending_policy_v3", "3.0")
|
engine.record_policy_application(d.decision_id, "lending_policy_v3", "3.0")
|
||||||
print("Loan decision recorded — policy compliant.")
|
print("Loan decision recorded — policy compliant.")
|
||||||
|
|
||||||
# SR 11-7 explainability report
|
# SR 11-7 explainability report
|
||||||
@@ -664,6 +640,6 @@ results = context.find_precedents("APT29 infrastructure attribution", limit=5)
|
|||||||
|
|
||||||
- [Context Graphs](/guides/context-graphs) — how `ContextGraph` stores decision nodes and causal edges
|
- [Context Graphs](/guides/context-graphs) — how `ContextGraph` stores decision nodes and causal edges
|
||||||
- [Distance Intelligence](/guides/distance-intelligence) — `trace_decision_causality()` annotates causal chains with confidence decay and distance bands
|
- [Distance Intelligence](/guides/distance-intelligence) — `trace_decision_causality()` annotates causal chains with confidence decay and distance bands
|
||||||
- [Provenance](/guides/provenance) — W3C PROV-O audit trail that wraps decision records in standards-compliant provenance
|
- [Provenance](provenance) — W3C PROV-O audit trail that wraps decision records in standards-compliant provenance
|
||||||
- [MCP Server](/guides/mcp-server) — expose decision recording and precedent search to LLM agents via the `record_decision` and `find_precedents` tools
|
- [MCP Server](/guides/mcp-server) — expose decision recording and precedent search to LLM agents via the `record_decision` and `find_precedents` tools
|
||||||
- [Change Management](/guides/change-management) — checkpoint decision state with `flush_checkpoint()` for versioned snapshots
|
- [Change Management](/guides/change-management) — checkpoint decision state with `flush_checkpoint()` for versioned snapshots
|
||||||
|
|||||||
@@ -611,8 +611,8 @@ The similarity threshold controls sensitivity. Start at 0.7 and examine false po
|
|||||||
|
|
||||||
## Related Guides
|
## Related Guides
|
||||||
|
|
||||||
- [Ingest Anything](/guides/ingest) — multi-source ingestion creates the duplicates this module resolves
|
- [Ingest Anything](ingest) — multi-source ingestion creates the duplicates this module resolves
|
||||||
- [Context Graphs](/guides/context-graphs) — store deduplicated entities directly in the knowledge graph
|
- [Context Graphs](/guides/context-graphs) — store deduplicated entities directly in the knowledge graph
|
||||||
- [Conflict Resolution](/guides/conflict-resolution) — after merging, reconcile disagreeing property values on the canonical entity
|
- [Conflict Resolution](/guides/conflict-resolution) — after merging, reconcile disagreeing property values on the canonical entity
|
||||||
- [Provenance](/guides/provenance) — track merge lineage so every canonical entity traces back to its original sources
|
- [Provenance](provenance) — track merge lineage so every canonical entity traces back to its original sources
|
||||||
- [Pipeline](/guides/pipeline) — chain ingest, deduplicate, and store as a `PipelineBuilder` workflow
|
- [Pipeline](pipeline) — chain ingest, deduplicate, and store as a `PipelineBuilder` workflow
|
||||||
|
|||||||
@@ -561,4 +561,4 @@ for chain in chains:
|
|||||||
- [Graph Analytics](/guides/graph-analytics) — centrality, community detection, Node2Vec embeddings, link prediction
|
- [Graph Analytics](/guides/graph-analytics) — centrality, community detection, Node2Vec embeddings, link prediction
|
||||||
- [Agent Memory](/guides/agent-memory) — proximity-blended retrieval (`proximity_weight`) integrates distance intelligence into memory search
|
- [Agent Memory](/guides/agent-memory) — proximity-blended retrieval (`proximity_weight`) integrates distance intelligence into memory search
|
||||||
- [Decision Intelligence](/guides/decision-intelligence) — `trace_decision_causality()` for causal chains with distance annotations
|
- [Decision Intelligence](/guides/decision-intelligence) — `trace_decision_causality()` for causal chains with distance annotations
|
||||||
- [Reasoning & Rules](/guides/reasoning) — `TemporalReasoningEngine` for Allen interval algebra over time-bounded graph nodes
|
- [Reasoning & Rules](reasoning) — `TemporalReasoningEngine` for Allen interval algebra over time-bounded graph nodes
|
||||||
|
|||||||
@@ -444,7 +444,7 @@ For semantic reasoning and ontology work, OWL/XML is the format — it is the on
|
|||||||
## Related Guides
|
## Related Guides
|
||||||
|
|
||||||
- [Context Graphs](/guides/context-graphs) — the `ContextGraph` object whose `to_dict()` feeds all exports
|
- [Context Graphs](/guides/context-graphs) — the `ContextGraph` object whose `to_dict()` feeds all exports
|
||||||
- [Ontology Management](/guides/ontology) — export OWL ontologies generated from your graph
|
- [Ontology Management](ontology) — export OWL ontologies generated from your graph
|
||||||
- [Reasoning & Rules](/guides/reasoning) — reasoning results can be exported as RDF triples
|
- [Reasoning & Rules](reasoning) — reasoning results can be exported as RDF triples
|
||||||
- [Change Management](/guides/change-management) — snapshot a graph before exporting to prove the export was made from a verified state
|
- [Change Management](/guides/change-management) — snapshot a graph before exporting to prove the export was made from a verified state
|
||||||
- [Pipeline](/guides/pipeline) — chain ingest, extract, and export in a single `PipelineBuilder`
|
- [Pipeline](pipeline) — chain ingest, extract, and export in a single `PipelineBuilder`
|
||||||
|
|||||||
@@ -539,6 +539,6 @@ print(f"\n{len(result['communities'])} exposure clusters "
|
|||||||
## Related Guides
|
## Related Guides
|
||||||
|
|
||||||
- [Context Graphs](/guides/context-graphs) — building and querying the underlying `ContextGraph`
|
- [Context Graphs](/guides/context-graphs) — building and querying the underlying `ContextGraph`
|
||||||
- [Visualization](/guides/visualization) — render centrality rankings and community clusters as interactive dashboards
|
- [Visualization](visualization) — render centrality rankings and community clusters as interactive dashboards
|
||||||
- [Decision Intelligence](/guides/decision-intelligence) — link prediction and structural similarity applied to decision nodes
|
- [Decision Intelligence](/guides/decision-intelligence) — link prediction and structural similarity applied to decision nodes
|
||||||
- [GraphRAG](/guides/graphrag) — using analytics results to ground LLM generation in the most contextually relevant subgraph
|
- [GraphRAG](/guides/graphrag) — using analytics results to ground LLM generation in the most contextually relevant subgraph
|
||||||
|
|||||||
+42
-55
@@ -1,9 +1,9 @@
|
|||||||
---
|
---
|
||||||
title: "GraphRAG: Graph-Augmented Retrieval"
|
title: "GraphRAG — Graph-Augmented Retrieval"
|
||||||
description: "Go beyond vector search: retrieve facts, trace reasoning paths, and ground LLM responses in your knowledge graph."
|
description: "Go beyond vector search: retrieve facts, trace reasoning paths, and ground LLM responses in your knowledge graph."
|
||||||
---
|
---
|
||||||
|
|
||||||
GraphRAG combines vector similarity with knowledge graph traversal so retrieval finds structurally connected facts, not just text that sounds related. When a `ContextGraph` is attached to `AgentContext`, every retrieval call automatically blends semantic search with multi-hop graph expansion, and `query_with_reasoning()` returns an auditable reasoning path alongside the LLM answer.
|
GraphRAG combines vector similarity with knowledge graph traversal so retrieval finds structurally connected facts, not just text that sounds related. When a `ContextGraph` is attached to `AgentContext`, every retrieval call automatically blends semantic search with multi-hop graph expansion — and `query_with_reasoning()` returns an auditable reasoning path alongside the LLM answer.
|
||||||
|
|
||||||
## What Is GraphRAG?
|
## What Is GraphRAG?
|
||||||
|
|
||||||
@@ -11,7 +11,7 @@ GraphRAG (Graph-Augmented Retrieval-Augmented Generation) enhances traditional R
|
|||||||
|
|
||||||
**GraphRAG vs. traditional vector-only RAG:** Vector RAG finds documents similar to your query text. GraphRAG finds documents similar to your query AND documents connected to those through entity relationships, even if they don't mention your query terms directly.
|
**GraphRAG vs. traditional vector-only RAG:** Vector RAG finds documents similar to your query text. GraphRAG finds documents similar to your query AND documents connected to those through entity relationships, even if they don't mention your query terms directly.
|
||||||
|
|
||||||
**The role of graph traversal:** Starting from entities found in vector-similar documents, GraphRAG expands outward through relationship edges to discover related facts. This reveals connections that pure text similarity would miss, like finding that a threat actor targets healthcare by following the path: Actor → Tool → Victim Organization → Industry Sector.
|
**The role of graph traversal:** Starting from entities found in vector-similar documents, GraphRAG expands outward through relationship edges to discover related facts. This reveals connections that pure text similarity would miss — like finding that a threat actor targets healthcare by following the path: Actor → Tool → Victim Organization → Industry Sector.
|
||||||
|
|
||||||
## Why Use GraphRAG?
|
## Why Use GraphRAG?
|
||||||
|
|
||||||
@@ -96,7 +96,7 @@ context = AgentContext(
|
|||||||
)
|
)
|
||||||
```
|
```
|
||||||
|
|
||||||
Now ingest your documents. `store()` with `extract_entities=True` runs the full extraction pipeline internally (Named Entity Recognition, relation extraction, and entity linking) and populates both the vector index and the graph simultaneously:
|
Now ingest your documents. `store()` with `extract_entities=True` runs the full extraction pipeline internally — Named Entity Recognition (NER), relation extraction, and entity linking — and populates both the vector index and the graph simultaneously:
|
||||||
|
|
||||||
```python
|
```python
|
||||||
intel_documents = [
|
intel_documents = [
|
||||||
@@ -132,17 +132,16 @@ stats = context.store(
|
|||||||
print("Graph built: {} nodes, {} edges".format(
|
print("Graph built: {} nodes, {} edges".format(
|
||||||
stats["graph_nodes"], stats["graph_edges"]
|
stats["graph_nodes"], stats["graph_edges"]
|
||||||
))
|
))
|
||||||
|
# Graph built: 18 nodes, 14 edges
|
||||||
|
# Nodes: APT29, HAMMERTOSS, NATO, LifeCare, AS59796, CISA Sector 6, ...
|
||||||
|
# Edges: deployed, observed_on, classified_as, targets, operates_in, ...
|
||||||
```
|
```
|
||||||
|
|
||||||
`store()` returns a dict with `stored_count`, `memory_ids`, `graph_nodes`, and
|
The graph now contains a connected subgraph linking APT29 to healthcare infrastructure across four document boundaries — something that would be invisible to a pure vector search.
|
||||||
`graph_edges`. The extracted nodes (APT29, HAMMERTOSS, LifeCare, AS59796, …) and
|
|
||||||
edges (`deployed`, `observed_on`, `classified_as`, …) now span all four documents.
|
|
||||||
|
|
||||||
The graph now contains a connected subgraph linking APT29 to healthcare infrastructure across four document boundaries, something that would be invisible to a pure vector search.
|
|
||||||
|
|
||||||
## Retrieving the relevant subgraph
|
## Retrieving the relevant subgraph
|
||||||
|
|
||||||
With the graph populated, a plain `retrieve()` call already does more than vector search. When `use_graph=True`, the retriever seeds the graph traversal from the top-k vector matches and expands outward by following edges. Expansion depth is set once, by `max_expansion_hops` on the `AgentContext` constructor:
|
With the graph populated, a plain `retrieve()` call already does more than vector search. When `use_graph=True`, the retriever seeds the graph traversal from the top-k vector matches and expands outward by following edges, collecting connected facts within `max_hops`:
|
||||||
|
|
||||||
```python
|
```python
|
||||||
results = context.retrieve(
|
results = context.retrieve(
|
||||||
@@ -150,6 +149,7 @@ results = context.retrieve(
|
|||||||
use_graph=True,
|
use_graph=True,
|
||||||
max_results=10,
|
max_results=10,
|
||||||
expand_graph=True,
|
expand_graph=True,
|
||||||
|
max_hops=3,
|
||||||
)
|
)
|
||||||
|
|
||||||
for r in results:
|
for r in results:
|
||||||
@@ -169,25 +169,17 @@ Notice the top results: while pure vector search might rank connected facts lowe
|
|||||||
When you know specifically which entity you want to anchor the traversal to, pass `anchor_node`:
|
When you know specifically which entity you want to anchor the traversal to, pass `anchor_node`:
|
||||||
|
|
||||||
```python
|
```python
|
||||||
# Anchor on APT29 explicitly: proximity scores are calculated from this node
|
# Anchor on APT29 explicitly — proximity scores are calculated from this node
|
||||||
apt29_intel = context.retrieve(
|
apt29_intel = context.retrieve(
|
||||||
"C2 infrastructure beaconing patterns",
|
"C2 infrastructure beaconing patterns",
|
||||||
use_graph=True,
|
use_graph=True,
|
||||||
anchor_node="APT29",
|
anchor_node="APT29",
|
||||||
proximity_weight=0.7, # strongly favour nodes close to APT29
|
proximity_weight=0.7, # strongly favour nodes close to APT29
|
||||||
max_hops=3, # with an anchor, this bounds the proximity radius
|
max_hops=3,
|
||||||
max_results=8,
|
max_results=8,
|
||||||
)
|
)
|
||||||
```
|
```
|
||||||
|
|
||||||
<Note>
|
|
||||||
`max_hops` on `retrieve()` only takes effect when `anchor_node` is set: it
|
|
||||||
bounds the proximity radius used for scoring and drops results farther than
|
|
||||||
`max_hops` from the anchor. Without an `anchor_node` it is ignored. It does
|
|
||||||
**not** change how far graph expansion reaches: that is fixed by
|
|
||||||
`max_expansion_hops` on the constructor.
|
|
||||||
</Note>
|
|
||||||
|
|
||||||
## Getting a grounded LLM answer with a reasoning path
|
## Getting a grounded LLM answer with a reasoning path
|
||||||
|
|
||||||
`retrieve()` gives you the grounded context. `query_with_reasoning()` goes one step further: it passes that subgraph context to an LLM and returns the answer together with the multi-hop path the retrieval system traced through the graph. That path is your audit trail.
|
`retrieve()` gives you the grounded context. `query_with_reasoning()` goes one step further: it passes that subgraph context to an LLM and returns the answer together with the multi-hop path the retrieval system traced through the graph. That path is your audit trail.
|
||||||
@@ -195,7 +187,7 @@ apt29_intel = context.retrieve(
|
|||||||
```python
|
```python
|
||||||
from semantica.llms import LiteLLM
|
from semantica.llms import LiteLLM
|
||||||
|
|
||||||
llm = LiteLLM(model="anthropic/claude-sonnet-5")
|
llm = LiteLLM(model="anthropic/claude-sonnet-4-20250514")
|
||||||
|
|
||||||
result = context.query_with_reasoning(
|
result = context.query_with_reasoning(
|
||||||
"What are APT29's known TTPs against healthcare infrastructure, "
|
"What are APT29's known TTPs against healthcare infrastructure, "
|
||||||
@@ -205,7 +197,7 @@ result = context.query_with_reasoning(
|
|||||||
max_hops=3,
|
max_hops=3,
|
||||||
)
|
)
|
||||||
|
|
||||||
# The LLM answer, grounded in graph-retrieved context, not training memory
|
# The LLM answer — grounded in graph-retrieved context, not training memory
|
||||||
print(result["response"])
|
print(result["response"])
|
||||||
|
|
||||||
# The multi-hop trace: APT29 → deployed → HAMMERTOSS → observed_on → LifeCare → ...
|
# The multi-hop trace: APT29 → deployed → HAMMERTOSS → observed_on → LifeCare → ...
|
||||||
@@ -221,7 +213,7 @@ for src in result["sources"]:
|
|||||||
print(" [{:.3f}] {}".format(src["score"], src["content"][:80]))
|
print(" [{:.3f}] {}".format(src["score"], src["content"][:80]))
|
||||||
```
|
```
|
||||||
|
|
||||||
The `reasoning_path` field is what separates GraphRAG from a black-box LLM call. When an analyst asks "how do you know APT29 targeted healthcare?", you can show them the exact traversal the system made across your own documents, not a claim the model generated from training data.
|
The `reasoning_path` field is what separates GraphRAG from a black-box LLM call. When an analyst asks "how do you know APT29 targeted healthcare?", you can show them the exact traversal the system made across your own documents — not a claim the model generated from training data.
|
||||||
|
|
||||||
The full return structure from `query_with_reasoning()`:
|
The full return structure from `query_with_reasoning()`:
|
||||||
|
|
||||||
@@ -240,11 +232,11 @@ The full return structure from `query_with_reasoning()`:
|
|||||||
|
|
||||||
<Tabs>
|
<Tabs>
|
||||||
|
|
||||||
<Tab title="Defense: CTI/Threat">
|
<Tab title="Defense — CTI/Threat">
|
||||||
|
|
||||||
Multi-INT intelligence fusion: OSINT threat feeds, NVD CVE data, and HUMINT summaries ingested into a single graph, then queried with multi-hop reasoning to trace C2 infrastructure chains and attribute campaigns to specific actors.
|
Multi-INT intelligence fusion: OSINT threat feeds, NVD CVE data, and HUMINT summaries ingested into a single graph, then queried with multi-hop reasoning to trace C2 infrastructure chains and attribute campaigns to specific actors.
|
||||||
|
|
||||||
In classified environments the graph can be partitioned by data handling caveat: each `AgentContext` operates over the subset of documents cleared for the querying user. The `reasoning_path` output doubles as a sanitisable audit trail for downgraded reporting.
|
In classified environments the graph can be partitioned by data handling caveat — each `AgentContext` operates over the subset of documents cleared for the querying user. The `reasoning_path` output doubles as a sanitisable audit trail for downgraded reporting.
|
||||||
|
|
||||||
```python
|
```python
|
||||||
from semantica.context import AgentContext, ContextGraph
|
from semantica.context import AgentContext, ContextGraph
|
||||||
@@ -281,7 +273,7 @@ context.store(
|
|||||||
link_entities=True,
|
link_entities=True,
|
||||||
)
|
)
|
||||||
|
|
||||||
llm = LiteLLM(model="anthropic/claude-sonnet-5")
|
llm = LiteLLM(model="anthropic/claude-sonnet-4-20250514")
|
||||||
result = context.query_with_reasoning(
|
result = context.query_with_reasoning(
|
||||||
"Trace the C2 infrastructure chain for APT29 operations targeting "
|
"Trace the C2 infrastructure chain for APT29 operations targeting "
|
||||||
"ITAR-controlled contractors in 2025. Include IP ranges, ASNs, and TTPs.",
|
"ITAR-controlled contractors in 2025. Include IP ranges, ASNs, and TTPs.",
|
||||||
@@ -308,11 +300,11 @@ proximate = context.retrieve(
|
|||||||
|
|
||||||
</Tab>
|
</Tab>
|
||||||
|
|
||||||
<Tab title="Security: SOC/Incident">
|
<Tab title="Security — SOC/Incident">
|
||||||
|
|
||||||
Security operations: real-time alert triage against a graph containing hosts, CVEs, user accounts, runbooks, and historical incidents. GraphRAG retrieves the relevant runbook and similar past incidents in a single call, reducing mean-time-to-respond.
|
Security operations: real-time alert triage against a graph containing hosts, CVEs, user accounts, runbooks, and historical incidents. GraphRAG retrieves the relevant runbook and similar past incidents in a single call, reducing mean-time-to-respond.
|
||||||
|
|
||||||
The `decision_tracking=True` flag records every triage query as an auditable decision, with the full context that was provided to the LLM. That's essential for post-incident review and SOC metrics.
|
The `decision_tracking=True` flag records every triage query as an auditable decision, with the full context that was provided to the LLM — essential for post-incident review and SOC metrics.
|
||||||
|
|
||||||
```python
|
```python
|
||||||
from semantica.context import AgentContext, ContextGraph
|
from semantica.context import AgentContext, ContextGraph
|
||||||
@@ -351,7 +343,7 @@ Parent: wmiprvse.exe
|
|||||||
Sigma match: T1053.005 Scheduled Task/Job
|
Sigma match: T1053.005 Scheduled Task/Job
|
||||||
"""
|
"""
|
||||||
|
|
||||||
llm = LiteLLM(model="anthropic/claude-sonnet-5")
|
llm = LiteLLM(model="anthropic/claude-sonnet-4-20250514")
|
||||||
triage = soc_context.query_with_reasoning(
|
triage = soc_context.query_with_reasoning(
|
||||||
"Triage this SIEM alert and identify the correct response runbook:\n{}".format(alert_text),
|
"Triage this SIEM alert and identify the correct response runbook:\n{}".format(alert_text),
|
||||||
llm_provider=llm,
|
llm_provider=llm,
|
||||||
@@ -377,7 +369,7 @@ for inc in similar:
|
|||||||
|
|
||||||
</Tab>
|
</Tab>
|
||||||
|
|
||||||
<Tab title="Life Science: Clinical/Pharma">
|
<Tab title="Life Science — Clinical/Pharma">
|
||||||
|
|
||||||
Clinical decision support: FDA drug labels, clinical guidelines, and trial summaries ingested into a graph where drug-enzyme-metabolite-interaction chains become traversable paths. A three-hop query (drug → enzyme → metabolite → contraindication) surfaces interaction risks that no single document would make explicit.
|
Clinical decision support: FDA drug labels, clinical guidelines, and trial summaries ingested into a graph where drug-enzyme-metabolite-interaction chains become traversable paths. A three-hop query (drug → enzyme → metabolite → contraindication) surfaces interaction risks that no single document would make explicit.
|
||||||
|
|
||||||
@@ -425,7 +417,7 @@ Patient: 68F, AF, CKD stage 3b (eGFR 32). On warfarin (INR target 2.0–3.0).
|
|||||||
Presenting for elective hip replacement. Concurrent: amiodarone 200mg, atorvastatin 40mg.
|
Presenting for elective hip replacement. Concurrent: amiodarone 200mg, atorvastatin 40mg.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
llm = LiteLLM(model="anthropic/claude-sonnet-5")
|
llm = LiteLLM(model="anthropic/claude-sonnet-4-20250514")
|
||||||
answer = clinical_context.query_with_reasoning(
|
answer = clinical_context.query_with_reasoning(
|
||||||
"What is the evidence-based warfarin bridging protocol for this patient "
|
"What is the evidence-based warfarin bridging protocol for this patient "
|
||||||
"given CKD and amiodarone interaction risk?\n\n{}".format(patient_context),
|
"given CKD and amiodarone interaction risk?\n\n{}".format(patient_context),
|
||||||
@@ -451,7 +443,7 @@ contra_chain = clinical_context.retrieve(
|
|||||||
|
|
||||||
</Tab>
|
</Tab>
|
||||||
|
|
||||||
<Tab title="Banking: Risk/Compliance">
|
<Tab title="Banking — Risk/Compliance">
|
||||||
|
|
||||||
Regulatory compliance: Basel III (CRE20), BCBS 239, SR 11-7, and EBA IRRBB guidelines ingested as a graph where regulation articles cross-reference each other as edges. Multi-hop queries traverse those cross-references automatically, so a question about commercial real estate RWA pulls the relevant CRE20 paragraphs and the BCBS 239 data quality requirements that govern their calculation in a single call.
|
Regulatory compliance: Basel III (CRE20), BCBS 239, SR 11-7, and EBA IRRBB guidelines ingested as a graph where regulation articles cross-reference each other as edges. Multi-hop queries traverse those cross-references automatically, so a question about commercial real estate RWA pulls the relevant CRE20 paragraphs and the BCBS 239 data quality requirements that govern their calculation in a single call.
|
||||||
|
|
||||||
@@ -474,17 +466,12 @@ compliance_context = AgentContext(
|
|||||||
retention_days=2555, # 7-year regulatory retention
|
retention_days=2555, # 7-year regulatory retention
|
||||||
)
|
)
|
||||||
|
|
||||||
# In production the text comes from a parsed file, e.g. FileIngestor().ingest_file(path).text;
|
# In production these come from ingest_file() — shown as strings here for brevity
|
||||||
# inline strings here for brevity
|
basel_cre20_text = "CRE20.32: For income-producing real estate where repayment depends on "
|
||||||
basel_cre20_text = (
|
"property cash flows, RWA = exposure × risk weight, where risk weight "
|
||||||
"CRE20.32: For income-producing real estate where repayment depends on "
|
"is determined by LTV bucket per Table CRE20.3..."
|
||||||
"property cash flows, RWA = exposure × risk weight, where risk weight "
|
bcbs239_text = "Principle 3: Risk data should be accurate and have a single authoritative source. "
|
||||||
"is determined by LTV bucket per Table CRE20.3..."
|
"Where data is aggregated across systems, reconciliation must be documented..."
|
||||||
)
|
|
||||||
bcbs239_text = (
|
|
||||||
"Principle 3: Risk data should be accurate and have a single authoritative source. "
|
|
||||||
"Where data is aggregated across systems, reconciliation must be documented..."
|
|
||||||
)
|
|
||||||
|
|
||||||
compliance_context.store(
|
compliance_context.store(
|
||||||
[
|
[
|
||||||
@@ -495,7 +482,7 @@ compliance_context.store(
|
|||||||
extract_relationships=True,
|
extract_relationships=True,
|
||||||
)
|
)
|
||||||
|
|
||||||
llm = LiteLLM(model="anthropic/claude-sonnet-5")
|
llm = LiteLLM(model="anthropic/claude-sonnet-4-20250514")
|
||||||
answer = compliance_context.query_with_reasoning(
|
answer = compliance_context.query_with_reasoning(
|
||||||
"Under Basel III CRE20, what are the RWA calculation requirements for "
|
"Under Basel III CRE20, what are the RWA calculation requirements for "
|
||||||
"commercial real estate exposures with LTV > 80%? "
|
"commercial real estate exposures with LTV > 80%? "
|
||||||
@@ -509,7 +496,7 @@ print(answer["response"])
|
|||||||
print("Regulatory sources cited: {}".format(answer["num_sources"]))
|
print("Regulatory sources cited: {}".format(answer["num_sources"]))
|
||||||
print("Confidence: {:.1%}".format(answer["confidence"]))
|
print("Confidence: {:.1%}".format(answer["confidence"]))
|
||||||
|
|
||||||
# The reasoning path is the audit log: show it to the regulator
|
# The reasoning path is the audit log — show it to the regulator
|
||||||
print("\n--- Reasoning Path (audit log) ---")
|
print("\n--- Reasoning Path (audit log) ---")
|
||||||
print(answer["reasoning_path"])
|
print(answer["reasoning_path"])
|
||||||
```
|
```
|
||||||
@@ -537,18 +524,18 @@ The `hybrid_alpha` parameter set in the `AgentContext` constructor establishes a
|
|||||||
When targeting a specific `anchor_node`, you can apply `proximity_weight` in `retrieve()` to dynamically blend structural distance from the anchor into the final score:
|
When targeting a specific `anchor_node`, you can apply `proximity_weight` in `retrieve()` to dynamically blend structural distance from the anchor into the final score:
|
||||||
|
|
||||||
```python
|
```python
|
||||||
# Anchor node provided: let vector semantics lead, graph proximity only slightly boosts
|
# Anchor node provided — let vector semantics lead, graph proximity only slightly boosts
|
||||||
results = context.retrieve(
|
results = context.retrieve(
|
||||||
query, use_graph=True, anchor_node="APT29", proximity_weight=0.2
|
query, use_graph=True, anchor_node="APT29", proximity_weight=0.2
|
||||||
)
|
)
|
||||||
|
|
||||||
# Known-entity tracing: topology drives the retrieval
|
# Known-entity tracing — topology drives the retrieval
|
||||||
results = context.retrieve(
|
results = context.retrieve(
|
||||||
query, use_graph=True, anchor_node="APT29", proximity_weight=0.8
|
query, use_graph=True, anchor_node="APT29", proximity_weight=0.8
|
||||||
)
|
)
|
||||||
```
|
```
|
||||||
|
|
||||||
Each additional expansion hop exponentially increases the subgraph size. Practical defaults by domain:
|
Each additional hop in `max_hops` exponentially increases the subgraph size. Practical defaults by domain:
|
||||||
|
|
||||||
```text
|
```text
|
||||||
General Q&A max_expansion_hops=2 (95% of useful facts within 2 hops)
|
General Q&A max_expansion_hops=2 (95% of useful facts within 2 hops)
|
||||||
@@ -557,7 +544,7 @@ Drug interactions max_expansion_hops=3 (drug → enzyme → metabolite
|
|||||||
Regulatory cross-ref max_expansion_hops=2 (rule → article → article)
|
Regulatory cross-ref max_expansion_hops=2 (rule → article → article)
|
||||||
```
|
```
|
||||||
|
|
||||||
Expansion depth is a constructor setting only (`max_expansion_hops`); there is no per-call override on `retrieve()`. `query_with_reasoning()` does take a per-call `max_hops` argument.
|
Set globally in the constructor; override per call with the `max_hops` argument to `retrieve()`.
|
||||||
|
|
||||||
## How GraphRAG works internally
|
## How GraphRAG works internally
|
||||||
|
|
||||||
@@ -589,9 +576,9 @@ The vector search and graph traversal run independently, then their scores are f
|
|||||||
|
|
||||||
## Related Guides
|
## Related Guides
|
||||||
|
|
||||||
- [Semantic Extraction](/guides/semantic-extraction): build the graph from raw unstructured text
|
- [Semantic Extraction](/guides/semantic-extraction) — build the graph from raw unstructured text
|
||||||
- [Agent Memory](/guides/agent-memory): store, retrieve, and persist agent memories
|
- [Agent Memory](/guides/agent-memory) — store, retrieve, and persist agent memories
|
||||||
- [Context Graphs](/guides/context-graphs): build and traverse the knowledge graph directly
|
- [Context Graphs](/guides/context-graphs) — build and traverse the knowledge graph directly
|
||||||
- [Reasoning](/guides/reasoning): derive new facts and run inference rules over the graph
|
- [Reasoning](reasoning) — derive new facts and run inference rules over the graph
|
||||||
- [Decision Intelligence](/guides/decision-intelligence): causal chains, policy enforcement, decision tracking
|
- [Decision Intelligence](/guides/decision-intelligence) — causal chains, policy enforcement, decision tracking
|
||||||
- [LLM Integrations](/guides/llm-integrations): connect Groq, OpenAI, Anthropic, HuggingFace, and 100+ more
|
- [LLM Integrations](/guides/llm-integrations) — connect Groq, OpenAI, Anthropic, HuggingFace, and 100+ more
|
||||||
|
|||||||
@@ -950,9 +950,9 @@ print(f"Compliance graph: {graph.stats()['node_count']} nodes, "
|
|||||||
|
|
||||||
## Related Guides
|
## Related Guides
|
||||||
|
|
||||||
- [Pipeline](/guides/pipeline) — chain ingest steps with `PipelineBuilder` for automated, retryable, parallelised workflows
|
- [Pipeline](pipeline) — chain ingest steps with `PipelineBuilder` for automated, retryable, parallelised workflows
|
||||||
- [Context Graphs](/guides/context-graphs) — storing and querying the entities you ingest as a typed property graph
|
- [Context Graphs](/guides/context-graphs) — storing and querying the entities you ingest as a typed property graph
|
||||||
- [Semantic Extraction](/guides/semantic-extraction) — NER, relation extraction, and triplet extraction from ingested text
|
- [Semantic Extraction](/guides/semantic-extraction) — NER, relation extraction, and triplet extraction from ingested text
|
||||||
- [Provenance](/guides/provenance) — tracking the origin document, confidence score, and ingestion timestamp for every extracted entity
|
- [Provenance](provenance) — tracking the origin document, confidence score, and ingestion timestamp for every extracted entity
|
||||||
- [Databricks Integration](../integrations/databricks) — Unity Catalog setup, PAT/OAuth M2M authentication, and lineage introspection
|
- [Databricks Integration](../integrations/databricks) — Unity Catalog setup, PAT/OAuth M2M authentication, and lineage introspection
|
||||||
- [Snowflake Integration](../integrations/snowflake) — warehouse setup and password/key-pair/OAuth authentication
|
- [Snowflake Integration](../integrations/snowflake) — warehouse setup and password/key-pair/OAuth authentication
|
||||||
|
|||||||
@@ -275,20 +275,20 @@ print(data)
|
|||||||
|
|
||||||
**LiteLLM** is a universal adapter that provides a single interface to over 100 different LLM providers, including Anthropic Claude, Azure OpenAI, AWS Bedrock, Google Vertex AI, and local Ollama instances. It acts as a translation layer, converting your unified API calls into provider-specific requests, enabling easy switching between providers without code changes.
|
**LiteLLM** is a universal adapter that provides a single interface to over 100 different LLM providers, including Anthropic Claude, Azure OpenAI, AWS Bedrock, Google Vertex AI, and local Ollama instances. It acts as a translation layer, converting your unified API calls into provider-specific requests, enabling easy switching between providers without code changes.
|
||||||
|
|
||||||
`LiteLLM` is the Swiss Army knife. It wraps the `litellm` library, which speaks to every major provider using a unified completion API. The model string encodes both provider and model name: `"anthropic/claude-sonnet-5"`, `"azure/gpt-4o"`, `"bedrock/anthropic.claude-sonnet-4-5-20250929-v1:0"`, `"ollama/llama3.2"`. Change the string, change the provider — no other code changes needed.
|
`LiteLLM` is the Swiss Army knife. It wraps the `litellm` library, which speaks to every major provider using a unified completion API. The model string encodes both provider and model name: `"anthropic/claude-sonnet-4-20250514"`, `"azure/gpt-4o"`, `"bedrock/anthropic.claude-3-5-sonnet-20241022-v2:0"`, `"ollama/llama3.2"`. Change the string, change the provider — no other code changes needed.
|
||||||
|
|
||||||
```python
|
```python
|
||||||
from semantica.llms import LiteLLM
|
from semantica.llms import LiteLLM
|
||||||
|
|
||||||
# Anthropic Claude — highest accuracy for complex reasoning
|
# Anthropic Claude — highest accuracy for complex reasoning
|
||||||
llm = LiteLLM(model="anthropic/claude-sonnet-5")
|
llm = LiteLLM(model="anthropic/claude-sonnet-4-20250514")
|
||||||
# Reads ANTHROPIC_API_KEY from environment
|
# Reads ANTHROPIC_API_KEY from environment
|
||||||
|
|
||||||
# Azure OpenAI — compliance and data-residency requirements
|
# Azure OpenAI — compliance and data-residency requirements
|
||||||
llm = LiteLLM(model="azure/gpt-4o", api_key="YOUR_AZURE_KEY")
|
llm = LiteLLM(model="azure/gpt-4o", api_key="YOUR_AZURE_KEY")
|
||||||
|
|
||||||
# AWS Bedrock — existing cloud agreement, no new vendor
|
# AWS Bedrock — existing cloud agreement, no new vendor
|
||||||
llm = LiteLLM(model="bedrock/anthropic.claude-sonnet-4-5-20250929-v1:0")
|
llm = LiteLLM(model="bedrock/anthropic.claude-3-5-sonnet-20241022-v2:0")
|
||||||
|
|
||||||
# Google Vertex AI
|
# Google Vertex AI
|
||||||
llm = LiteLLM(model="vertex_ai/gemini-1.5-pro")
|
llm = LiteLLM(model="vertex_ai/gemini-1.5-pro")
|
||||||
@@ -306,7 +306,7 @@ The environment-variable convention for each provider: `ANTHROPIC_API_KEY`, `AZU
|
|||||||
import os
|
import os
|
||||||
|
|
||||||
PROVIDER_MAP = {
|
PROVIDER_MAP = {
|
||||||
"prod": "anthropic/claude-sonnet-5",
|
"prod": "anthropic/claude-sonnet-4-20250514",
|
||||||
"staging": "openai/gpt-4o-mini",
|
"staging": "openai/gpt-4o-mini",
|
||||||
"local": "ollama/llama3.2",
|
"local": "ollama/llama3.2",
|
||||||
"azure": "azure/gpt-4o",
|
"azure": "azure/gpt-4o",
|
||||||
@@ -378,7 +378,7 @@ print("FAST: {} (conf={:.0%})".format(fast_result["response"], fast_result["con
|
|||||||
|
|
||||||
# Tier 2: deep answer with Claude if confidence is below threshold
|
# Tier 2: deep answer with Claude if confidence is below threshold
|
||||||
if fast_result["confidence"] < 0.85:
|
if fast_result["confidence"] < 0.85:
|
||||||
deep_llm = LiteLLM(model="anthropic/claude-sonnet-5")
|
deep_llm = LiteLLM(model="anthropic/claude-sonnet-4-20250514")
|
||||||
deep_result = context.query_with_reasoning(
|
deep_result = context.query_with_reasoning(
|
||||||
query, llm_provider=deep_llm, max_results=15, max_hops=3
|
query, llm_provider=deep_llm, max_results=15, max_hops=3
|
||||||
)
|
)
|
||||||
@@ -574,7 +574,7 @@ print("TRIAGE: {} (conf={:.0%})".format(triage["response"], triage["confidence"]
|
|||||||
|
|
||||||
# Tier 2: escalate to Claude for deep analysis if Tier 1 is uncertain
|
# Tier 2: escalate to Claude for deep analysis if Tier 1 is uncertain
|
||||||
if triage["confidence"] < 0.88:
|
if triage["confidence"] < 0.88:
|
||||||
deep_llm = LiteLLM(model="anthropic/claude-sonnet-5")
|
deep_llm = LiteLLM(model="anthropic/claude-sonnet-4-20250514")
|
||||||
deep = context.query_with_reasoning(
|
deep = context.query_with_reasoning(
|
||||||
"Full MITRE ATT&CK analysis of this alert: identify the attack chain, "
|
"Full MITRE ATT&CK analysis of this alert: identify the attack chain, "
|
||||||
"blast radius, affected systems, and recommended containment steps.",
|
"blast radius, affected systems, and recommended containment steps.",
|
||||||
@@ -630,7 +630,7 @@ for d in drugs:
|
|||||||
# trastuzumab (conf=0.98), pertuzumab (conf=0.97), docetaxel (conf=0.96)
|
# trastuzumab (conf=0.98), pertuzumab (conf=0.97), docetaxel (conf=0.96)
|
||||||
|
|
||||||
# Report synthesis with Claude — switch to azure/gpt-4o for HIPAA by changing one string
|
# Report synthesis with Claude — switch to azure/gpt-4o for HIPAA by changing one string
|
||||||
report_llm = LiteLLM(model="anthropic/claude-sonnet-5")
|
report_llm = LiteLLM(model="anthropic/claude-sonnet-4-20250514")
|
||||||
# For HIPAA-constrained Azure deployment:
|
# For HIPAA-constrained Azure deployment:
|
||||||
# report_llm = LiteLLM(model="azure/gpt-4o", api_key="YOUR_AZURE_KEY")
|
# report_llm = LiteLLM(model="azure/gpt-4o", api_key="YOUR_AZURE_KEY")
|
||||||
|
|
||||||
@@ -682,7 +682,7 @@ question = (
|
|||||||
|
|
||||||
# Two-provider consensus — same query, same graph, different LLMs
|
# Two-provider consensus — same query, same graph, different LLMs
|
||||||
gpt4o = OpenAI(model="gpt-4o", api_key="YOUR_OAI_KEY")
|
gpt4o = OpenAI(model="gpt-4o", api_key="YOUR_OAI_KEY")
|
||||||
claude = LiteLLM(model="anthropic/claude-sonnet-5")
|
claude = LiteLLM(model="anthropic/claude-sonnet-4-20250514")
|
||||||
|
|
||||||
answer_a = context.query_with_reasoning(question, llm_provider=gpt4o, max_results=10)
|
answer_a = context.query_with_reasoning(question, llm_provider=gpt4o, max_results=10)
|
||||||
answer_b = context.query_with_reasoning(question, llm_provider=claude, max_results=10)
|
answer_b = context.query_with_reasoning(question, llm_provider=claude, max_results=10)
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ icon: "plug"
|
|||||||
|
|
||||||
MCP stands for the Model Context Protocol. It is an open standard that allows external AI assistants (like Claude Desktop, Cursor, or Windsurf) to securely access local tools and data sources.
|
MCP stands for the Model Context Protocol. It is an open standard that allows external AI assistants (like Claude Desktop, Cursor, or Windsurf) to securely access local tools and data sources.
|
||||||
|
|
||||||
The Semantica MCP server exposes your knowledge graph as 15 callable tools. By connecting it, any compatible AI client can traverse the graph live, record decisions, run analytics, and export results during a conversation — without you having to write custom tool wrappers.
|
The Semantica MCP server exposes your knowledge graph as 12 callable tools. By connecting it, any compatible AI client can traverse the graph live, record decisions, run analytics, and export results during a conversation — without you having to write custom tool wrappers.
|
||||||
|
|
||||||
<Info>
|
<Info>
|
||||||
The Semantica MCP server exposes 15 tools and 3 read-only resources. All tools accept and return JSON. No configuration beyond an optional environment variable for graph persistence is required.
|
The Semantica MCP server exposes 15 tools and 3 read-only resources. All tools accept and return JSON. No configuration beyond an optional environment variable for graph persistence is required.
|
||||||
@@ -40,7 +40,7 @@ Connecting your AI client follows a standard progression:
|
|||||||
1. **Install**: Install Semantica in your Python environment.
|
1. **Install**: Install Semantica in your Python environment.
|
||||||
2. **Configure Client**: Add the `semantica-mcp` command and absolute graph paths to your AI client's JSON configuration.
|
2. **Configure Client**: Add the `semantica-mcp` command and absolute graph paths to your AI client's JSON configuration.
|
||||||
3. **Start Client**: Launch Claude Desktop or Windsurf, which automatically spawns the MCP server.
|
3. **Start Client**: Launch Claude Desktop or Windsurf, which automatically spawns the MCP server.
|
||||||
4. **Tool Calls**: Prompt the AI in natural language. The AI autonomously chains the 15 available tools.
|
4. **Tool Calls**: Prompt the AI in natural language. The AI autonomously chains the 12 available tools.
|
||||||
5. **Graph Updates**: The AI directly modifies your local graph, adding entities, edges, and decisions.
|
5. **Graph Updates**: The AI directly modifies your local graph, adding entities, edges, and decisions.
|
||||||
|
|
||||||
---
|
---
|
||||||
@@ -342,8 +342,8 @@ The result is a fully auditable credit decision trail with precedent links, read
|
|||||||
|
|
||||||
## Related Guides
|
## Related Guides
|
||||||
|
|
||||||
- [Reasoning & Rules](/guides/reasoning) — the engine behind the `run_reasoning` tool
|
- [Reasoning & Rules](reasoning) — the engine behind the `run_reasoning` tool
|
||||||
- [Decision Intelligence](/guides/decision-intelligence) — how decisions are stored as causal graph nodes
|
- [Decision Intelligence](/guides/decision-intelligence) — how decisions are stored as causal graph nodes
|
||||||
- [Context Graphs](/guides/context-graphs) — the graph that `add_entity` and `add_relationship` write to
|
- [Context Graphs](/guides/context-graphs) — the graph that `add_entity` and `add_relationship` write to
|
||||||
- [Export & Serialization](/guides/export) — all export formats available via `export_graph`
|
- [Export & Serialization](export) — all export formats available via `export_graph`
|
||||||
- [Ontology Management](/guides/ontology) — generate OWL ontologies from the graph built via MCP
|
- [Ontology Management](ontology) — generate OWL ontologies from the graph built via MCP
|
||||||
|
|||||||
@@ -197,7 +197,7 @@ reasoning_agent.load("./pipeline/enriched_intel/")
|
|||||||
# All memories, graph nodes, and vector embeddings from both ingestion agents are now available.
|
# All memories, graph nodes, and vector embeddings from both ingestion agents are now available.
|
||||||
|
|
||||||
# Use a high-capability model for the synthesis step
|
# Use a high-capability model for the synthesis step
|
||||||
llm = LiteLLM(model="anthropic/claude-sonnet-5")
|
llm = LiteLLM(model="anthropic/claude-sonnet-4-20250514")
|
||||||
|
|
||||||
synthesis = reasoning_agent.query_with_reasoning(
|
synthesis = reasoning_agent.query_with_reasoning(
|
||||||
"Summarize the APT29 exploitation of CVE-2024-3400: affected products, "
|
"Summarize the APT29 exploitation of CVE-2024-3400: affected products, "
|
||||||
@@ -428,7 +428,7 @@ tier1.store(
|
|||||||
|
|
||||||
# --- Tier 2: deep investigation when Tier 1 confidence is low ---
|
# --- Tier 2: deep investigation when Tier 1 confidence is low ---
|
||||||
if triage["confidence"] < 0.90:
|
if triage["confidence"] < 0.90:
|
||||||
deep_llm = LiteLLM(model="anthropic/claude-sonnet-5")
|
deep_llm = LiteLLM(model="anthropic/claude-sonnet-4-20250514")
|
||||||
|
|
||||||
investigation = tier2.query_with_reasoning(
|
investigation = tier2.query_with_reasoning(
|
||||||
"Full MITRE ATT&CK analysis of incident {}. "
|
"Full MITRE ATT&CK analysis of incident {}. "
|
||||||
@@ -533,7 +533,7 @@ t1.start(); t2.start()
|
|||||||
t1.join(); t2.join()
|
t1.join(); t2.join()
|
||||||
|
|
||||||
# Chief agent synthesizes across literature and experimental data
|
# Chief agent synthesizes across literature and experimental data
|
||||||
llm = LiteLLM(model="anthropic/claude-sonnet-5")
|
llm = LiteLLM(model="anthropic/claude-sonnet-4-20250514")
|
||||||
|
|
||||||
synthesis = chief.query_with_reasoning(
|
synthesis = chief.query_with_reasoning(
|
||||||
"Identify the top two candidate compounds for KRAS G12C NSCLC that show "
|
"Identify the top two candidate compounds for KRAS G12C NSCLC that show "
|
||||||
@@ -576,7 +576,7 @@ credit_officer = make_desk_agent()
|
|||||||
committee_chair = make_desk_agent()
|
committee_chair = make_desk_agent()
|
||||||
|
|
||||||
app_id = "LOAN-2025-88421"
|
app_id = "LOAN-2025-88421"
|
||||||
llm = LiteLLM(model="anthropic/claude-sonnet-5")
|
llm = LiteLLM(model="anthropic/claude-sonnet-4-20250514")
|
||||||
|
|
||||||
# --- Risk Desk: PD/LGD/EL analysis ---
|
# --- Risk Desk: PD/LGD/EL analysis ---
|
||||||
risk_desk.store(
|
risk_desk.store(
|
||||||
|
|||||||
@@ -477,7 +477,7 @@ regs = [
|
|||||||
]
|
]
|
||||||
|
|
||||||
# Use an LLM to extract the conceptual model from regulatory prose
|
# Use an LLM to extract the conceptual model from regulatory prose
|
||||||
llm_gen = LLMOntologyGenerator(provider="anthropic", model="claude-sonnet-5")
|
llm_gen = LLMOntologyGenerator(provider="anthropic", model="claude-sonnet-4-20250514")
|
||||||
ontology = llm_gen.generate_ontology_from_text(
|
ontology = llm_gen.generate_ontology_from_text(
|
||||||
"\n\n".join(r.text[:8000] for r in regs) # token-safe excerpt per document
|
"\n\n".join(r.text[:8000] for r in regs) # token-safe excerpt per document
|
||||||
)
|
)
|
||||||
@@ -504,7 +504,7 @@ else:
|
|||||||
## Related Guides
|
## Related Guides
|
||||||
|
|
||||||
- [SHACL Validation](/guides/shacl-validation) — generate W3C SHACL constraint shapes from your ontology and validate live graph data against them
|
- [SHACL Validation](/guides/shacl-validation) — generate W3C SHACL constraint shapes from your ontology and validate live graph data against them
|
||||||
- [Reasoning & Rules](/guides/reasoning) — apply forward/backward-chaining rules over your ontology to derive new facts
|
- [Reasoning & Rules](reasoning) — apply forward/backward-chaining rules over your ontology to derive new facts
|
||||||
- [Export & Serialization](/guides/export) — export graphs to RDF, GraphML, CSV, and Neo4j Cypher
|
- [Export & Serialization](export) — export graphs to RDF, GraphML, CSV, and Neo4j Cypher
|
||||||
- [Semantic Extraction](/guides/semantic-extraction) — extract entities and relationships that feed ontology generation
|
- [Semantic Extraction](/guides/semantic-extraction) — extract entities and relationships that feed ontology generation
|
||||||
- [Context Graphs](/guides/context-graphs) — the knowledge graph that ontology generation reads from
|
- [Context Graphs](/guides/context-graphs) — the knowledge graph that ontology generation reads from
|
||||||
|
|||||||
@@ -127,7 +127,7 @@ engine = ExecutionEngine(max_workers=4, retry_on_failure=True)
|
|||||||
result = engine.execute_pipeline(pipeline)
|
result = engine.execute_pipeline(pipeline)
|
||||||
|
|
||||||
print(f"Success: {result.success}")
|
print(f"Success: {result.success}")
|
||||||
print(f"Output: {result.output}") # the final step's return value, e.g. {"node_count": ..., "edge_count": ...}
|
print(f"Output: {result.output}") # {"node_count": 312, "edge_count": 847}
|
||||||
print(f"Duration: {result.metrics['execution_time']:.2f}s")
|
print(f"Duration: {result.metrics['execution_time']:.2f}s")
|
||||||
print(f"Steps completed: {result.metrics['steps_executed']}")
|
print(f"Steps completed: {result.metrics['steps_executed']}")
|
||||||
```
|
```
|
||||||
@@ -197,9 +197,7 @@ engine = ExecutionEngine(
|
|||||||
max_workers = 4,
|
max_workers = 4,
|
||||||
retry_on_failure = True,
|
retry_on_failure = True,
|
||||||
)
|
)
|
||||||
# ExecutionEngine builds its own FailureHandler; replace it with the configured one
|
# The engine uses handler.get_retry_policy(step.step_type) when a step fails
|
||||||
engine.failure_handler = handler
|
|
||||||
# The engine now calls engine.failure_handler.get_retry_policy(step.step_type) on failure
|
|
||||||
```
|
```
|
||||||
|
|
||||||
`handler.classify_error()` distinguishes `ValidationError` (low severity, usually don't retry), `ProcessingError` (high severity), and timeout/connection errors (medium severity, always retry). You can inspect the classification:
|
`handler.classify_error()` distinguishes `ValidationError` (low severity, usually don't retry), `ProcessingError` (high severity), and timeout/connection errors (medium severity, always retry). You can inspect the classification:
|
||||||
@@ -718,7 +716,7 @@ print(f"Compliance delta update: {result.output}")
|
|||||||
|
|
||||||
## Related Guides
|
## Related Guides
|
||||||
|
|
||||||
- [Ingest](/guides/ingest) — all source types for the ingest step: PDFs, APIs, databases, RSS feeds, STIX directories, and streams
|
- [Ingest](ingest) — all source types for the ingest step: PDFs, APIs, databases, RSS feeds, STIX directories, and streams
|
||||||
- [Semantic Extraction](/guides/semantic-extraction) — NER, relation extraction, triplet extraction, and event detection for the extract step
|
- [Semantic Extraction](/guides/semantic-extraction) — NER, relation extraction, triplet extraction, and event detection for the extract step
|
||||||
- [Context Graphs](/guides/context-graphs) — building and querying the `ContextGraph` that the store step populates
|
- [Context Graphs](/guides/context-graphs) — building and querying the `ContextGraph` that the store step populates
|
||||||
- [Provenance](/guides/provenance) — tracking the origin document, confidence score, and pipeline run ID for every extracted entity
|
- [Provenance](provenance) — tracking the origin document, confidence score, and pipeline run ID for every extracted entity
|
||||||
|
|||||||
@@ -663,8 +663,8 @@ print("Policy updated to v2.4.0")
|
|||||||
## Related Guides
|
## Related Guides
|
||||||
|
|
||||||
- [Decision Intelligence](/guides/decision-intelligence) — `record_decision()`, causal chains, and precedent search — the decisions that `check_compliance()` evaluates
|
- [Decision Intelligence](/guides/decision-intelligence) — `record_decision()`, causal chains, and precedent search — the decisions that `check_compliance()` evaluates
|
||||||
- [Reasoning & Rules](/guides/reasoning) — complement policy rules with formal inference for logical conflict detection
|
- [Reasoning & Rules](reasoning) — complement policy rules with formal inference for logical conflict detection
|
||||||
- [SHACL Validation](/guides/shacl-validation) — enforce structural constraints on policy nodes themselves
|
- [SHACL Validation](/guides/shacl-validation) — enforce structural constraints on policy nodes themselves
|
||||||
- [Change Management](/guides/change-management) — version-snapshot the policy graph alongside the knowledge graph
|
- [Change Management](/guides/change-management) — version-snapshot the policy graph alongside the knowledge graph
|
||||||
- [Provenance](/guides/provenance) — W3C PROV-O lineage for every policy decision and exception
|
- [Provenance](provenance) — W3C PROV-O lineage for every policy decision and exception
|
||||||
- [MCP Server](/guides/mcp-server) — expose `record_decision` and `find_precedents` as MCP tools for AI agents
|
- [MCP Server](/guides/mcp-server) — expose `record_decision` and `find_precedents` as MCP tools for AI agents
|
||||||
|
|||||||
@@ -661,5 +661,5 @@ Note: the banking example above passes `agent_id="credit_data_service_v2"` to `t
|
|||||||
|
|
||||||
- [Semantic Extraction](/guides/semantic-extraction) — the NER and relation extraction pipeline that auto-generates provenance entries for every extracted entity
|
- [Semantic Extraction](/guides/semantic-extraction) — the NER and relation extraction pipeline that auto-generates provenance entries for every extracted entity
|
||||||
- [Conflict Resolution](/guides/conflict-resolution) — provenance property sources feed directly into conflict detection; every resolved value is traceable to its source
|
- [Conflict Resolution](/guides/conflict-resolution) — provenance property sources feed directly into conflict detection; every resolved value is traceable to its source
|
||||||
- [Deduplication](/guides/deduplication) — merge operations are recorded in merge history; pair with provenance for a complete lineage from source to canonical entity
|
- [Deduplication](deduplication) — merge operations are recorded in merge history; pair with provenance for a complete lineage from source to canonical entity
|
||||||
- [Provenance Reference](../reference/provenance) — full storage backend API, `InMemoryStorage`, `SQLiteStorage`, and `ProvenanceEntry` schema
|
- [Provenance Reference](../reference/provenance) — full storage backend API, `InMemoryStorage`, `SQLiteStorage`, and `ProvenanceEntry` schema
|
||||||
|
|||||||
@@ -840,7 +840,7 @@ if proof:
|
|||||||
|
|
||||||
- [Semantic Extraction](/guides/semantic-extraction) — extract the entities and relationships that populate the graph facts you reason over
|
- [Semantic Extraction](/guides/semantic-extraction) — extract the entities and relationships that populate the graph facts you reason over
|
||||||
- [GraphRAG](/guides/graphrag) — retrieve graph-grounded context for LLM responses
|
- [GraphRAG](/guides/graphrag) — retrieve graph-grounded context for LLM responses
|
||||||
- [Ontology Management](/guides/ontology) — generate OWL ontologies to give your rules formal semantics
|
- [Ontology Management](ontology) — generate OWL ontologies to give your rules formal semantics
|
||||||
- [Decision Intelligence](/guides/decision-intelligence) — record and trace inferred decisions through the full causal chain
|
- [Decision Intelligence](/guides/decision-intelligence) — record and trace inferred decisions through the full causal chain
|
||||||
- [Context Graphs](/guides/context-graphs) — the knowledge graph that reasoning operates over
|
- [Context Graphs](/guides/context-graphs) — the knowledge graph that reasoning operates over
|
||||||
- [MCP Server](/guides/mcp-server) — expose `run_reasoning` as a tool for Claude and other agents
|
- [MCP Server](/guides/mcp-server) — expose `run_reasoning` as a tool for Claude and other agents
|
||||||
|
|||||||
@@ -71,7 +71,7 @@ This pipeline transforms documents like "APT29 deployed HAMMERTOSS malware targe
|
|||||||
`semantica.semantic_extract` turns unstructured text into structured graph-ready output: it identifies named entities, extracts relationships between them, detects time-anchored events, resolves coreferences, and serialises everything as RDF triplets. Use it to populate a `ContextGraph` from raw documents — intelligence reports, clinical notes, regulatory filings, or any free-text corpus.
|
`semantica.semantic_extract` turns unstructured text into structured graph-ready output: it identifies named entities, extracts relationships between them, detects time-anchored events, resolves coreferences, and serialises everything as RDF triplets. Use it to populate a `ContextGraph` from raw documents — intelligence reports, clinical notes, regulatory filings, or any free-text corpus.
|
||||||
|
|
||||||
<Info>
|
<Info>
|
||||||
Extracted entities and relationships feed into `ContextGraph` via `AgentContext.store()`. For how they are attributed back to source documents, see the [Provenance Guide](/guides/provenance). For how the populated graph is queried and traversed, see [Context Graphs](/guides/context-graphs).
|
Extracted entities and relationships feed into `ContextGraph` via `AgentContext.store()`. For how they are attributed back to source documents, see the [Provenance Guide](provenance). For how the populated graph is queried and traversed, see [Context Graphs](/guides/context-graphs).
|
||||||
</Info>
|
</Info>
|
||||||
|
|
||||||
## Step 1 — Named Entity Recognition: who and what is in the text
|
## Step 1 — Named Entity Recognition: who and what is in the text
|
||||||
@@ -100,15 +100,14 @@ ner = NamedEntityRecognizer(
|
|||||||
methods=["llm", "ml", "pattern"],
|
methods=["llm", "ml", "pattern"],
|
||||||
confidence_threshold=0.75,
|
confidence_threshold=0.75,
|
||||||
provider="anthropic",
|
provider="anthropic",
|
||||||
llm_model="claude-sonnet-5",
|
llm_model="claude-sonnet-4-6",
|
||||||
)
|
)
|
||||||
entities = ner.extract_entities(report)
|
entities = ner.extract_entities(report)
|
||||||
|
|
||||||
for e in entities:
|
for e in entities:
|
||||||
print("[{:>5.2f}] {:15s} {}".format(e.confidence, e.label, e.text))
|
print("[{:>5.2f}] {:15s} {}".format(e.confidence, e.label, e.text))
|
||||||
|
|
||||||
# Illustrative output — exact labels and scores depend on the method and model.
|
# Expected output (abbreviated):
|
||||||
# Abbreviated:
|
|
||||||
# [ 0.94] THREAT_ACTOR GAMMA-7
|
# [ 0.94] THREAT_ACTOR GAMMA-7
|
||||||
# [ 0.91] THREAT_ACTOR DELTA-3
|
# [ 0.91] THREAT_ACTOR DELTA-3
|
||||||
# [ 0.97] MALWARE HAMMERTOSS
|
# [ 0.97] MALWARE HAMMERTOSS
|
||||||
@@ -263,18 +262,16 @@ from semantica.semantic_extract import TripletExtractor
|
|||||||
tri = TripletExtractor(
|
tri = TripletExtractor(
|
||||||
method="llm",
|
method="llm",
|
||||||
provider="anthropic",
|
provider="anthropic",
|
||||||
llm_model="claude-sonnet-5",
|
llm_model="claude-sonnet-4-6",
|
||||||
include_temporal=True, # attach time context to triplets when available
|
include_temporal=True, # attach time context to triplets when available
|
||||||
include_provenance=True, # embed source document reference in each triplet
|
include_provenance=True, # embed source document reference in each triplet
|
||||||
validate=False, # return raw triplets; validate explicitly below
|
|
||||||
)
|
)
|
||||||
|
|
||||||
# Feed in the entities and relations you already extracted — the extractor
|
# Feed in the entities and relations you already extracted — the extractor
|
||||||
# uses them to constrain what it produces
|
# uses them to constrain and validate what it produces
|
||||||
triplets = tri.extract_triplets(report, entities, relations)
|
triplets = tri.extract_triplets(report, entities, relations)
|
||||||
|
|
||||||
# Filter malformed triplets before serialisation
|
# Filter malformed triplets before serialisation
|
||||||
# (extract_triplets validates automatically unless validate=False, as above)
|
|
||||||
valid = tri.validate_triplets(triplets)
|
valid = tri.validate_triplets(triplets)
|
||||||
print("Valid: {}/{}".format(len(valid), len(triplets)))
|
print("Valid: {}/{}".format(len(valid), len(triplets)))
|
||||||
|
|
||||||
@@ -323,7 +320,7 @@ def ingest_intel_report(
|
|||||||
methods=[method, "pattern"],
|
methods=[method, "pattern"],
|
||||||
confidence_threshold=0.70,
|
confidence_threshold=0.70,
|
||||||
provider="anthropic",
|
provider="anthropic",
|
||||||
llm_model="claude-sonnet-5",
|
llm_model="claude-sonnet-4-6",
|
||||||
)
|
)
|
||||||
entities = ner.extract_entities(text)
|
entities = ner.extract_entities(text)
|
||||||
classified = ner.classify_entities(entities)
|
classified = ner.classify_entities(entities)
|
||||||
@@ -338,7 +335,7 @@ def ingest_intel_report(
|
|||||||
relation_types=["deployed", "targets", "exploits", "operates_from", "provided_to"],
|
relation_types=["deployed", "targets", "exploits", "operates_from", "provided_to"],
|
||||||
confidence_threshold=0.65,
|
confidence_threshold=0.65,
|
||||||
provider="anthropic",
|
provider="anthropic",
|
||||||
llm_model="claude-sonnet-5",
|
llm_model="claude-sonnet-4-6",
|
||||||
)
|
)
|
||||||
relations = rel.extract_relations(text, entities)
|
relations = rel.extract_relations(text, entities)
|
||||||
|
|
||||||
@@ -350,10 +347,9 @@ def ingest_intel_report(
|
|||||||
tri = TripletExtractor(
|
tri = TripletExtractor(
|
||||||
method=method,
|
method=method,
|
||||||
provider="anthropic",
|
provider="anthropic",
|
||||||
llm_model="claude-sonnet-5",
|
llm_model="claude-sonnet-4-6",
|
||||||
include_temporal=True,
|
include_temporal=True,
|
||||||
include_provenance=True,
|
include_provenance=True,
|
||||||
validate=False, # keep raw triplets so the summary can report rejections
|
|
||||||
)
|
)
|
||||||
triplets = tri.extract_triplets(text, entities, relations)
|
triplets = tri.extract_triplets(text, entities, relations)
|
||||||
valid = tri.validate_triplets(triplets)
|
valid = tri.validate_triplets(triplets)
|
||||||
@@ -381,7 +377,6 @@ def ingest_intel_report(
|
|||||||
"coref_chains": len(chains),
|
"coref_chains": len(chains),
|
||||||
"relations": len(relations),
|
"relations": len(relations),
|
||||||
"events": len(events),
|
"events": len(events),
|
||||||
"triplets_total": len(triplets),
|
|
||||||
"triplets_valid": len(valid),
|
"triplets_valid": len(valid),
|
||||||
"graph_nodes": graph_stats.get("graph_nodes", 0),
|
"graph_nodes": graph_stats.get("graph_nodes", 0),
|
||||||
"graph_edges": graph_stats.get("graph_edges", 0),
|
"graph_edges": graph_stats.get("graph_edges", 0),
|
||||||
@@ -407,7 +402,7 @@ for text, doc_id in reports:
|
|||||||
summary["relations"],
|
summary["relations"],
|
||||||
summary["events"],
|
summary["events"],
|
||||||
summary["triplets_valid"],
|
summary["triplets_valid"],
|
||||||
summary["triplets_total"],
|
len(summary["rdf_turtle"]),
|
||||||
))
|
))
|
||||||
```
|
```
|
||||||
|
|
||||||
@@ -426,7 +421,7 @@ ner = NamedEntityRecognizer(
|
|||||||
methods=["llm", "pattern"],
|
methods=["llm", "pattern"],
|
||||||
confidence_threshold=0.75,
|
confidence_threshold=0.75,
|
||||||
provider="anthropic",
|
provider="anthropic",
|
||||||
llm_model="claude-sonnet-5",
|
llm_model="claude-sonnet-4-6",
|
||||||
)
|
)
|
||||||
entities = ner.extract_entities(fintel_text)
|
entities = ner.extract_entities(fintel_text)
|
||||||
grouped = ner.classify_entities(entities)
|
grouped = ner.classify_entities(entities)
|
||||||
@@ -443,14 +438,14 @@ rel = RelationExtractor(
|
|||||||
relation_types=["operates_from", "deployed", "targets", "exploits"],
|
relation_types=["operates_from", "deployed", "targets", "exploits"],
|
||||||
confidence_threshold=0.70,
|
confidence_threshold=0.70,
|
||||||
provider="anthropic",
|
provider="anthropic",
|
||||||
llm_model="claude-sonnet-5",
|
llm_model="claude-sonnet-4-6",
|
||||||
)
|
)
|
||||||
relations = rel.extract_relations(fintel_text, entities)
|
relations = rel.extract_relations(fintel_text, entities)
|
||||||
|
|
||||||
tri = TripletExtractor(
|
tri = TripletExtractor(
|
||||||
method="llm",
|
method="llm",
|
||||||
provider="anthropic",
|
provider="anthropic",
|
||||||
llm_model="claude-sonnet-5",
|
llm_model="claude-sonnet-4-6",
|
||||||
include_temporal=True,
|
include_temporal=True,
|
||||||
include_provenance=True,
|
include_provenance=True,
|
||||||
)
|
)
|
||||||
@@ -549,14 +544,14 @@ rel = RelationExtractor(
|
|||||||
relation_types=["treats", "causes_adverse_event", "has_efficacy", "evaluated_in"],
|
relation_types=["treats", "causes_adverse_event", "has_efficacy", "evaluated_in"],
|
||||||
confidence_threshold=0.65,
|
confidence_threshold=0.65,
|
||||||
provider="anthropic",
|
provider="anthropic",
|
||||||
llm_model="claude-sonnet-5",
|
llm_model="claude-sonnet-4-6",
|
||||||
)
|
)
|
||||||
relations = rel.extract_relations(paper, entities)
|
relations = rel.extract_relations(paper, entities)
|
||||||
|
|
||||||
tri = TripletExtractor(
|
tri = TripletExtractor(
|
||||||
method="llm",
|
method="llm",
|
||||||
provider="anthropic",
|
provider="anthropic",
|
||||||
llm_model="claude-sonnet-5",
|
llm_model="claude-sonnet-4-6",
|
||||||
triplet_types=["treats", "has_efficacy", "causes_adverse_event"],
|
triplet_types=["treats", "has_efficacy", "causes_adverse_event"],
|
||||||
include_temporal=True,
|
include_temporal=True,
|
||||||
include_provenance=True,
|
include_provenance=True,
|
||||||
@@ -600,7 +595,7 @@ ner = NamedEntityRecognizer(
|
|||||||
methods=["llm", "ml", "pattern"],
|
methods=["llm", "ml", "pattern"],
|
||||||
confidence_threshold=0.70,
|
confidence_threshold=0.70,
|
||||||
provider="anthropic",
|
provider="anthropic",
|
||||||
llm_model="claude-sonnet-5",
|
llm_model="claude-sonnet-4-6",
|
||||||
)
|
)
|
||||||
entities = ner.extract_entities(credit_memo)
|
entities = ner.extract_entities(credit_memo)
|
||||||
grouped = ner.classify_entities(entities)
|
grouped = ner.classify_entities(entities)
|
||||||
@@ -617,14 +612,14 @@ rel = RelationExtractor(
|
|||||||
relation_types=["guaranteed_by", "secured_by", "classified_as", "exposed_to"],
|
relation_types=["guaranteed_by", "secured_by", "classified_as", "exposed_to"],
|
||||||
confidence_threshold=0.65,
|
confidence_threshold=0.65,
|
||||||
provider="anthropic",
|
provider="anthropic",
|
||||||
llm_model="claude-sonnet-5",
|
llm_model="claude-sonnet-4-6",
|
||||||
)
|
)
|
||||||
relations = rel.extract_relations(credit_memo, entities)
|
relations = rel.extract_relations(credit_memo, entities)
|
||||||
|
|
||||||
tri = TripletExtractor(
|
tri = TripletExtractor(
|
||||||
method="llm",
|
method="llm",
|
||||||
provider="anthropic",
|
provider="anthropic",
|
||||||
llm_model="claude-sonnet-5",
|
llm_model="claude-sonnet-4-6",
|
||||||
include_temporal=True,
|
include_temporal=True,
|
||||||
include_provenance=True,
|
include_provenance=True,
|
||||||
)
|
)
|
||||||
@@ -668,9 +663,9 @@ The fallback behaviour is automatic: if the primary method returns an empty list
|
|||||||
|
|
||||||
## Related Guides
|
## Related Guides
|
||||||
|
|
||||||
- [Provenance Guide](/guides/provenance) — track every extracted entity and chunk back to its source document
|
- [Provenance Guide](provenance) — track every extracted entity and chunk back to its source document
|
||||||
- [Agent Memory Guide](/guides/agent-memory) — store extracted knowledge as searchable agent memories with graph enrichment
|
- [Agent Memory Guide](/guides/agent-memory) — store extracted knowledge as searchable agent memories with graph enrichment
|
||||||
- [Context Graphs Guide](/guides/context-graphs) — how extracted entities populate `ContextGraph` nodes and edges
|
- [Context Graphs Guide](/guides/context-graphs) — how extracted entities populate `ContextGraph` nodes and edges
|
||||||
- [GraphRAG Guide](/guides/graphrag) — retrieve facts from the populated graph to ground LLM responses
|
- [GraphRAG Guide](/guides/graphrag) — retrieve facts from the populated graph to ground LLM responses
|
||||||
- [Reasoning Guide](/guides/reasoning) — derive new facts, run SPARQL queries, and apply inference rules over the extracted graph
|
- [Reasoning Guide](reasoning) — derive new facts, run SPARQL queries, and apply inference rules over the extracted graph
|
||||||
- [Semantic Extract Reference](../reference/semantic_extract) — full API for all extractor classes, providers, and validators
|
- [Semantic Extract Reference](../reference/semantic_extract) — full API for all extractor classes, providers, and validators
|
||||||
|
|||||||
@@ -707,22 +707,6 @@ report_dict = report.to_dict()
|
|||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## Resource limits
|
|
||||||
|
|
||||||
Live SHACL validation in the Explorer enforces four resource limits, all configurable
|
|
||||||
through environment variables. When a limit trips, the error message names the
|
|
||||||
variable that controls it.
|
|
||||||
|
|
||||||
| Environment variable | Default | What it bounds |
|
|
||||||
| --- | --- | --- |
|
|
||||||
| `SEMANTICA_MAX_SHACL_TURTLE_BYTES` | `262144` (256 KB) | Size of the submitted SHACL Turtle |
|
|
||||||
| `SEMANTICA_MAX_SHACL_TRIPLES` | `1000` | Triple count of the parsed shapes graph |
|
|
||||||
| `SEMANTICA_MAX_SHACL_TIMEOUT` | `15.0` | Validation timeout in seconds |
|
|
||||||
| `SEMANTICA_MAX_SHACL_CONCURRENCY` | `4` | Concurrent validations per process |
|
|
||||||
|
|
||||||
The first three are surfaced in the validation error message when exceeded; the
|
|
||||||
concurrency limit applies as a semaphore and does not appear in responses.
|
|
||||||
|
|
||||||
## Using SHACL validation as a CI/CD gate
|
## Using SHACL validation as a CI/CD gate
|
||||||
|
|
||||||
Call this function as a pre-publish gate; exit code 1 blocks the pipeline.
|
Call this function as a pre-publish gate; exit code 1 blocks the pipeline.
|
||||||
@@ -753,8 +737,8 @@ def validate_before_publish(data_graph_str: str, ontology: dict) -> None:
|
|||||||
|
|
||||||
## Related Guides
|
## Related Guides
|
||||||
|
|
||||||
- [Ontology Management](/guides/ontology) — generate the OWL ontology that SHACL shapes are derived from
|
- [Ontology Management](ontology) — generate the OWL ontology that SHACL shapes are derived from
|
||||||
- [Reasoning & Rules](/guides/reasoning) — complement SHACL structural constraints with logical inference rules
|
- [Reasoning & Rules](reasoning) — complement SHACL structural constraints with logical inference rules
|
||||||
- [Export & Serialization](/guides/export) — serialize graph data to Turtle/RDF/XML for `run_shacl_validation` input
|
- [Export & Serialization](export) — serialize graph data to Turtle/RDF/XML for `run_shacl_validation` input
|
||||||
- [Conflict Resolution](/guides/conflict-resolution) — detect and resolve data conflicts before SHACL validation
|
- [Conflict Resolution](/guides/conflict-resolution) — detect and resolve data conflicts before SHACL validation
|
||||||
- [Change Management](/guides/change-management) — version-gate SHACL shapes alongside ontology versions
|
- [Change Management](/guides/change-management) — version-gate SHACL shapes alongside ontology versions
|
||||||
|
|||||||
@@ -615,7 +615,7 @@ fig.write_html("out.html") # manual export
|
|||||||
## Related Guides
|
## Related Guides
|
||||||
|
|
||||||
- [Context Graphs](/guides/context-graphs) — `graph.to_dict()` is the primary input for `KGVisualizer`
|
- [Context Graphs](/guides/context-graphs) — `graph.to_dict()` is the primary input for `KGVisualizer`
|
||||||
- [Ontology Management](/guides/ontology) — `OntologyVisualizer` renders ontologies produced by `OntologyGenerator`
|
- [Ontology Management](ontology) — `OntologyVisualizer` renders ontologies produced by `OntologyGenerator`
|
||||||
- [Change Management](/guides/change-management) — `TemporalVersionManager` snapshots feed `visualize_metrics_evolution()` and `visualize_snapshot_comparison()`
|
- [Change Management](/guides/change-management) — `TemporalVersionManager` snapshots feed `visualize_metrics_evolution()` and `visualize_snapshot_comparison()`
|
||||||
- [Graph Analytics](/guides/graph-analytics) — centrality scores, community dicts, and connectivity results that feed the `AnalyticsVisualizer`
|
- [Graph Analytics](/guides/graph-analytics) — centrality scores, community dicts, and connectivity results that feed the `AnalyticsVisualizer`
|
||||||
- [Export & Serialization](/guides/export) — export the same graph to GraphML, GEXF, or DOT for Gephi and Graphviz
|
- [Export & Serialization](export) — export the same graph to GraphML, GEXF, or DOT for Gephi and Graphviz
|
||||||
|
|||||||
+304
-25
@@ -1,31 +1,109 @@
|
|||||||
---
|
---
|
||||||
title: "Welcome to Semantica"
|
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
|
```bash
|
||||||
pip install semantica
|
pip install semantica
|
||||||
```
|
```
|
||||||
|
|
||||||
Most AI agents run on embeddings, not meaning. A similarity score has no structure, no relationships, and no way to explain why a result came back.
|
Your AI agent just made a decision. Now someone needs to explain it.
|
||||||
|
|
||||||
Semantica is the semantic and context layer underneath your LLM, vector store, and agent framework: deterministic infrastructure, not a model. Graph construction, reasoning, and provenance all run without an LLM in the loop. It turns fragmented enterprise data into a structured, queryable context graph and knowledge graph, governed by ontologies, taxonomies, and controlled vocabularies (OWL, SHACL, SKOS), so your data's meaning is explicit rather than approximated by an embedding.
|
*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?*
|
||||||
|
|
||||||
Provenance and audit trails aren't a bolt-on. They fall out naturally once your data has that structure, so the same graph that powers retrieval and reasoning also gives you a straight answer when a regulator asks why.
|
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.
|
||||||
|
|
||||||
## What you get
|
**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.
|
||||||
|
|
||||||
- **[Context graphs](/guides/context-graphs)**: a persistent, queryable graph of everything your agent knows, decides, and reasons about
|
|
||||||
- **Decision intelligence**: `record_decision()` captures the full lifecycle and causal chain of every decision
|
## The Problem Every Production AI Team Hits
|
||||||
- **[Full provenance](/guides/provenance)**: every fact links back to its source, W3C PROV-O compliant and audit-ready for HIPAA, SOX, and GDPR
|
|
||||||
- **[Explainable reasoning](/guides/reasoning)**: forward chaining, Datalog, and SPARQL, each with a derivation path you can inspect
|
Powerful agents aren't automatically trustworthy ones. Five structural blind spots make modern AI systems impossible to deploy in regulated environments:
|
||||||
- **Temporal intelligence**: Allen interval algebra and point-in-time snapshots, so the graph knows not just *what* but *when*
|
|
||||||
|
**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 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
|
||||||
|
- In healthcare, finance, and legal: this is a hard compliance blocker
|
||||||
|
- No lineage from inference back to the original document
|
||||||
|
- Impossible to demonstrate what the agent actually relied on
|
||||||
|
|
||||||
|
**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 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. 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: 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
|
||||||
|
- `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
|
||||||
|
- 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
|
||||||
|
- 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: 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
|
||||||
|
- 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>
|
<Tip>
|
||||||
Works alongside any LLM provider and any agent framework, and ingests directly from enterprise data platforms like Databricks, SAP, Salesforce, and Snowflake. 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>
|
</Tip>
|
||||||
|
|
||||||
## Try it
|
<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' }} />
|
||||||
|
|
||||||
|
|
||||||
|
## See It In Action
|
||||||
|
|
||||||
|
One pip install. A few lines to connect your agent. Everything else becomes traceable.
|
||||||
|
|
||||||
|
```bash
|
||||||
|
pip install semantica
|
||||||
|
```
|
||||||
|
|
||||||
<CodeGroup>
|
<CodeGroup>
|
||||||
|
|
||||||
@@ -107,28 +185,229 @@ decision_id = context.record_decision(
|
|||||||
|
|
||||||
</CodeGroup>
|
</CodeGroup>
|
||||||
|
|
||||||
## Start here
|
- [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
|
||||||
|
|
||||||
|
|
||||||
|
## Built for Where Mistakes Have Consequences
|
||||||
|
|
||||||
|
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.
|
||||||
|
</Warning>
|
||||||
|
|
||||||
|
**Healthcare & Life Sciences**
|
||||||
|
- Clinical decision support with full audit trails
|
||||||
|
- Drug interaction and contraindication graphs
|
||||||
|
- Patient safety event tracking and root-cause analysis
|
||||||
|
- HIPAA-compliant provenance chains out of the box
|
||||||
|
|
||||||
|
**Finance & Risk**
|
||||||
|
- Fraud detection knowledge graphs
|
||||||
|
- Risk assessment trails built to survive an audit
|
||||||
|
- SOX, GDPR, and MiFID II compliance infrastructure
|
||||||
|
- Model decision lineage for regulatory reporting
|
||||||
|
|
||||||
|
**Legal & Compliance**
|
||||||
|
- Evidence-backed research with every cited fact provenance-linked
|
||||||
|
- Contract analysis with traceable clause extraction
|
||||||
|
- Regulatory change tracking across jurisdictions
|
||||||
|
- Full reasoning paths ready for court-admissible documentation
|
||||||
|
|
||||||
|
**Cybersecurity**
|
||||||
|
- Threat attribution graphs linking actors, TTPs, and indicators
|
||||||
|
- Incident response timelines with full event provenance
|
||||||
|
- Security audit trails across the complete kill chain
|
||||||
|
- MITRE ATT&CK-aligned knowledge graph integration
|
||||||
|
|
||||||
|
**Government & Defense**
|
||||||
|
- Policy decision trails from brief to outcome
|
||||||
|
- Classified information handling with provenance chains
|
||||||
|
- Chain-of-custody scrutiny for intelligence reporting
|
||||||
|
- Air-gapped deployment with local LLM support
|
||||||
|
|
||||||
|
**Critical Infrastructure**
|
||||||
|
- Power grid state tracking with temporal intelligence
|
||||||
|
- Transportation safety event graphs
|
||||||
|
- Emergency response coordination with decision audit trails
|
||||||
|
- Consequence modeling for high-stakes operational decisions
|
||||||
|
|
||||||
|
|
||||||
|
## Start Here
|
||||||
|
|
||||||
<Steps>
|
<Steps>
|
||||||
<Step title="Install">
|
<Step title="Install Semantica">
|
||||||
```bash
|
```bash
|
||||||
pip install semantica
|
pip install semantica
|
||||||
```
|
```
|
||||||
Optional extras: `[all]`, `[neo4j]`, `[pinecone]`. See [Installation](/installation).
|
See [Installation](/installation) for optional extras (`[all]`, `[neo4j]`, `[pinecone]`) and environment setup.
|
||||||
</Step>
|
</Step>
|
||||||
<Step title="Build a pipeline">
|
<Step title="Run the Quickstart">
|
||||||
Follow the [Quickstart](/quickstart) to ingest documents, extract entities, build a graph, and record a decision in 5 minutes.
|
Build a complete knowledge graph pipeline in [5 minutes](/quickstart):
|
||||||
|
- Ingest documents from any source
|
||||||
|
- Extract entities and relationships
|
||||||
|
- Build and query the graph
|
||||||
|
- Record and trace a decision
|
||||||
</Step>
|
</Step>
|
||||||
<Step title="Learn the model">
|
<Step title="Learn the mental model">
|
||||||
[Core Concepts](/concepts) covers knowledge graphs vs. vector stores, GraphRAG, and how provenance and decisions fit together.
|
[Core Concepts](/concepts) covers:
|
||||||
|
- 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 accountability layer architecture
|
||||||
</Step>
|
</Step>
|
||||||
<Step title="Go deep">
|
<Step title="Go deep on any module">
|
||||||
Every module has a [reference page](/reference/context) with full API docs and runnable examples.
|
Every module has a dedicated [reference page](/reference/context) with:
|
||||||
|
- Full class and method documentation
|
||||||
|
- Parameter tables with types and defaults
|
||||||
|
- Runnable code examples for each feature
|
||||||
</Step>
|
</Step>
|
||||||
</Steps>
|
</Steps>
|
||||||
|
|
||||||
More: the [Cookbook](/cookbook) for real-world notebooks, [Discord](https://discord.gg/sV34vps5hH) for help.
|
- [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
|
||||||
|
|
||||||
|
<AccordionGroup>
|
||||||
|
|
||||||
|
<Accordion title="Context & Decision Intelligence" icon="brain">
|
||||||
|
|
||||||
|
### Context Graphs
|
||||||
|
|
||||||
|
- Structured, persistent graph of entities, relationships, and decisions
|
||||||
|
- Temporal model with `valid_from` / `valid_until` on every node and edge
|
||||||
|
- Point-in-time queries across historical graph states
|
||||||
|
- Distance Intelligence: semantic neighborhoods and N×N distance matrices
|
||||||
|
|
||||||
|
### Decision Tracking
|
||||||
|
|
||||||
|
- `record_decision()` with full lifecycle management and causal chains
|
||||||
|
- Hybrid similarity search over past decisions for consistency enforcement
|
||||||
|
- `analyze_decision_impact()` and `analyze_decision_influence()` for consequence modeling
|
||||||
|
- Ego-mode exploration for targeted neighborhood investigation
|
||||||
|
|
||||||
<Accordion title="Full module list">
|
|
||||||
`semantica.ingest`, `semantica.parse`, `semantica.split`, `semantica.normalize`, `semantica.semantic_extract`, `semantica.kg`, `semantica.ontology`, `semantica.reasoning`, `semantica.embeddings`, `semantica.vector_store`, `semantica.graph_store`, `semantica.triplet_store`, `semantica.context`, `semantica.provenance`, `semantica.change_management`, `semantica.deduplication`, `semantica.conflicts`, `semantica.export`, `semantica.visualization`, `semantica.pipeline`, `semantica.seed`, `semantica.llms`, `semantica.mcp_server`, `semantica.explorer`, `semantica.evals`, `semantica.utils`, `semantica.core`. See the [API Reference](/reference/context) for full docs on each.
|
|
||||||
</Accordion>
|
</Accordion>
|
||||||
|
|
||||||
|
<Accordion title="Knowledge Engineering" icon="diagram-project">
|
||||||
|
|
||||||
|
### Entity & Relation Extraction
|
||||||
|
|
||||||
|
- Named entity recognition: pattern, ML, or LLM methods
|
||||||
|
- Typed triplet extraction via LLM or rule-based pipelines
|
||||||
|
- Event extraction with temporal and causal linking
|
||||||
|
|
||||||
|
### Ontology & Schema
|
||||||
|
|
||||||
|
- Ontology Hub: visual editor, SHACL Studio, alignments, health dashboard
|
||||||
|
- Deduplication v2: `blocking_v2`, `hybrid_v2`, `semantic_v2`: up to 7x faster
|
||||||
|
- Datalog reasoning: recursive Horn clause rules with fixpoint semantics
|
||||||
|
- SPARQL reasoning: query-based inference over RDF graphs
|
||||||
|
|
||||||
|
</Accordion>
|
||||||
|
|
||||||
|
<Accordion title="Provenance & Auditability" icon="shield-check">
|
||||||
|
|
||||||
|
### Lineage Tracking
|
||||||
|
|
||||||
|
- W3C PROV-O lineage across all modules: every fact has a source
|
||||||
|
- `recorded_at` stamping with full OWL-Time export
|
||||||
|
- Change management with SHA-256 checksums and version control
|
||||||
|
- Full audit trails from ingestion event to final inference
|
||||||
|
|
||||||
|
### Compliance Infrastructure
|
||||||
|
|
||||||
|
- HIPAA: patient data handling with audit-ready provenance chains
|
||||||
|
- SOX / MiFID II: financial decision records with full traceability
|
||||||
|
- GDPR: data lineage for subject access and right-to-erasure workflows
|
||||||
|
- FDA 21 CFR Part 11: electronic records and signature compliance
|
||||||
|
|
||||||
|
</Accordion>
|
||||||
|
|
||||||
|
<Accordion title="Data Ingestion & Export" icon="database">
|
||||||
|
|
||||||
|
### Ingestion Formats
|
||||||
|
|
||||||
|
- Documents: PDF, DOCX, HTML, PPTX, Docling layout analysis
|
||||||
|
- Structured data: JSON, CSV, Excel, Parquet, XML
|
||||||
|
- Sources: web crawl, SQL, Snowflake, feeds, email, code repositories, MCP
|
||||||
|
|
||||||
|
### Vector Stores
|
||||||
|
|
||||||
|
- FAISS, Pinecone, Weaviate, Qdrant, Milvus, PgVector, in-memory
|
||||||
|
|
||||||
|
### Graph Stores
|
||||||
|
|
||||||
|
- Neo4j, FalkorDB, Apache AGE, Amazon Neptune
|
||||||
|
|
||||||
|
### Export Formats
|
||||||
|
|
||||||
|
- RDF: Turtle, JSON-LD, N-Triples, RDF/XML
|
||||||
|
- Tabular: Parquet, CSV, Arrow
|
||||||
|
- Graph: GraphML, GEXF, DOT, ArangoDB AQL
|
||||||
|
- Ontology: OWL, SKOS, SHACL
|
||||||
|
|
||||||
|
</Accordion>
|
||||||
|
|
||||||
|
</AccordionGroup>
|
||||||
|
|
||||||
|
|
||||||
|
## Module Reference
|
||||||
|
|
||||||
|
| Module | What it provides |
|
||||||
|
| :-------- | :----------------- |
|
||||||
|
| `semantica.context` | Context graphs, agent memory, decision tracking, causal analysis, precedent search |
|
||||||
|
| `semantica.kg` | KG construction, graph algorithms, temporal model, Allen interval algebra |
|
||||||
|
| `semantica.semantic_extract` | NER, relation extraction, event extraction, triplet generation |
|
||||||
|
| `semantica.reasoning` | Forward chaining, Rete, deductive, abductive, SPARQL, Datalog |
|
||||||
|
| `semantica.ontology` | SHACL, SKOS, alignments, diff/migration, auto-generation, OWL/RDF |
|
||||||
|
| `semantica.explorer` | FastAPI Knowledge Explorer, Ontology Hub, Distance Intelligence, SHACL Studio |
|
||||||
|
| `semantica.mcp_server` | MCP stdio server: 15 tools for Claude Desktop, VS Code, Cursor, Windsurf, Cline |
|
||||||
|
| `semantica.vector_store` | FAISS, Pinecone, Weaviate, Qdrant, Milvus, PgVector |
|
||||||
|
| `semantica.graph_store` | Neo4j, FalkorDB, Apache AGE, Amazon Neptune |
|
||||||
|
| `semantica.triplet_store` | In-memory and persistent RDF triple store with SPARQL |
|
||||||
|
| `semantica.ingest` | Files, web, feeds, databases, Snowflake, Parquet, XML, MCP |
|
||||||
|
| `semantica.parse` | Document parsing: PDF, DOCX, HTML, PPTX, Docling layout analysis |
|
||||||
|
| `semantica.split` | Text chunking: sentence, paragraph, token, semantic boundary strategies |
|
||||||
|
| `semantica.normalize` | Text normalization, entity canonicalization, whitespace and encoding cleanup |
|
||||||
|
| `semantica.embeddings` | Sentence-Transformers, FastEmbed, OpenAI, BGE, Ollama local embeddings |
|
||||||
|
| `semantica.pipeline` | Pipeline DSL, parallel workers, retry policies, failure handling |
|
||||||
|
| `semantica.export` | RDF, Parquet, ArangoDB AQL, CSV, OWL, Arrow, GraphML, GEXF, DOT |
|
||||||
|
| `semantica.visualization` | Programmatic graph rendering: force, hierarchical, circular, spring layouts |
|
||||||
|
| `semantica.deduplication` | Entity deduplication v1/v2, similarity scoring, blocking, merging |
|
||||||
|
| `semantica.conflicts` | Conflict detection and resolution across overlapping knowledge sources |
|
||||||
|
| `semantica.provenance` | W3C PROV-O lineage tracking, source attribution, audit trails |
|
||||||
|
| `semantica.change_management` | Version control with SHA-256 checksums, diff, rollback |
|
||||||
|
| `semantica.llms` | Groq, OpenAI, Anthropic, Gemini, Ollama, DeepSeek, Novita AI, LiteLLM, HuggingFace |
|
||||||
|
| `semantica.seed` | Foundation graph seeding from CSV, JSON, SQL, API, and RDF sources |
|
||||||
|
| `semantica.evals` | Evaluation harness: KG quality, extraction F1, pipeline benchmarking, regression tracking |
|
||||||
|
| `semantica.core` | Orchestration, ConfigManager, LifecycleManager, PluginRegistry, MethodRegistry |
|
||||||
|
| `semantica.utils` | Logging, validation, progress tracking, hash utilities, nested dict helpers |
|
||||||
|
|
||||||
|
|
||||||
|
## Why Semantica?
|
||||||
|
|
||||||
|
**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.
|
||||||
|
- 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: fixes shipped in every release ([CHANGELOG](https://github.com/semantica-agi/semantica/blob/main/CHANGELOG.md))
|
||||||
|
|
||||||
|
**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: works with any agent stack
|
||||||
|
|||||||
@@ -183,6 +183,6 @@ Install the [Microsoft Visual C++ Redistributable](https://aka.ms/vs/17/release/
|
|||||||
|
|
||||||
## Next Steps
|
## Next Steps
|
||||||
|
|
||||||
- [Getting Started](/getting-started): understand what Semantica does before you build.
|
- [Getting Started](/getting-started) — Understand what Semantica does before you build.
|
||||||
- [Build the Pipeline](/quickstart): follow the end-to-end workflow with code.
|
- [Build the Pipeline](/quickstart) — Follow the end-to-end workflow with code.
|
||||||
- [Browse Examples](/cookbook): see notebook examples organized by use case.
|
- [Browse Examples](/cookbook) — See notebook examples organized by use case.
|
||||||
|
|||||||
@@ -12,13 +12,13 @@ icon: "link"
|
|||||||
pip install "semantica[langchain]"
|
pip install "semantica[langchain]"
|
||||||
```
|
```
|
||||||
|
|
||||||
Requires `langchain-core >= 0.3`. If langchain-core is not installed, the integration still imports. Every class carries the full Semantica API and degrades gracefully (`build()` returns `None`; branch on `LANGCHAIN_AVAILABLE`).
|
Requires `langchain-core >= 0.3`. If langchain-core is not installed, the integration still imports — every class carries the full Semantica API and degrades gracefully (`build()` returns `None`; branch on `LANGCHAIN_AVAILABLE`).
|
||||||
|
|
||||||
## Components at a Glance
|
## Components at a Glance
|
||||||
|
|
||||||
- **SemanticaRetriever** (`BaseRetriever`): hybrid-search seeds retrieval, then graph edges are walked `hops` steps (default 2) for GraphRAG-style results.
|
- **SemanticaRetriever** — `BaseRetriever`: hybrid-search seeds retrieval, then graph edges are walked `hops` steps (default 2) for GraphRAG-style results.
|
||||||
- **SemanticaVectorStore** (`VectorStore`): `add_texts` / `similarity_search` / `similarity_search_with_score` / `from_texts` over `HybridSearch`.
|
- **SemanticaVectorStore** — `VectorStore`: `add_texts` / `similarity_search` / `similarity_search_with_score` / `from_texts` over `HybridSearch`.
|
||||||
- **SemanticaKGTool** / **SemanticaDecisionTool** (`BaseTool` subclasses): `semantica_query_graph` and `semantica_query_decisions` for LangGraph / tool-calling agents.
|
- **SemanticaKGTool** / **SemanticaDecisionTool** — `BaseTool` subclasses: `semantica_query_graph` and `semantica_query_decisions` for LangGraph / tool-calling agents.
|
||||||
|
|
||||||
## Component Details
|
## Component Details
|
||||||
|
|
||||||
|
|||||||
@@ -1,342 +0,0 @@
|
|||||||
---
|
|
||||||
title: "Amazon Redshift Integration"
|
|
||||||
description: "Ingest structured data from Amazon Redshift tables and queries into Semantica's KG pipeline."
|
|
||||||
icon: "database"
|
|
||||||
---
|
|
||||||
|
|
||||||
> Extract data from Amazon Redshift into Semantica with password/native or IAM-role authentication, using the PostgreSQL-compatible wire protocol.
|
|
||||||
|
|
||||||
|
|
||||||
## Installation
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# Install with Redshift support
|
|
||||||
pip install "semantica[db-redshift]"
|
|
||||||
|
|
||||||
# Or install the connector separately
|
|
||||||
pip install redshift-connector>=2.0.0
|
|
||||||
```
|
|
||||||
|
|
||||||
`redshift-connector` is an optional dependency. A plain `pip install semantica` never pulls it in, and `import semantica.ingest` never loads it eagerly — the SDK is imported only when you first use `RedshiftConnector` or `RedshiftIngestor`.
|
|
||||||
|
|
||||||
<Note>
|
|
||||||
This connector uses the Redshift database wire protocol for read ingestion. COPY, UNLOAD, S3 integration, Spectrum external tables, and the Redshift Data API are outside the current scope of this integration.
|
|
||||||
</Note>
|
|
||||||
|
|
||||||
|
|
||||||
## Basic Usage
|
|
||||||
|
|
||||||
```python
|
|
||||||
from semantica.ingest import RedshiftIngestor
|
|
||||||
import os
|
|
||||||
|
|
||||||
ingestor = RedshiftIngestor(
|
|
||||||
host=os.getenv("REDSHIFT_HOST"),
|
|
||||||
database=os.getenv("REDSHIFT_DATABASE"),
|
|
||||||
user=os.getenv("REDSHIFT_USER"),
|
|
||||||
password=os.getenv("REDSHIFT_PASSWORD"),
|
|
||||||
)
|
|
||||||
|
|
||||||
data = ingestor.ingest_table("customers")
|
|
||||||
print(f"Retrieved {data.row_count} rows — columns: {data.columns}")
|
|
||||||
```
|
|
||||||
|
|
||||||
<Tip>
|
|
||||||
Use environment variables (or a `.env` file with `python-dotenv`) to keep credentials out of source code. `RedshiftIngestor()` with no arguments reads from `REDSHIFT_*` environment variables automatically.
|
|
||||||
</Tip>
|
|
||||||
|
|
||||||
|
|
||||||
## Authentication
|
|
||||||
|
|
||||||
<Tabs>
|
|
||||||
<Tab title="Password / Native">
|
|
||||||
The standard Redshift database username and password:
|
|
||||||
|
|
||||||
```python
|
|
||||||
import os
|
|
||||||
from semantica.ingest import RedshiftIngestor
|
|
||||||
|
|
||||||
ingestor = RedshiftIngestor(
|
|
||||||
host=os.getenv("REDSHIFT_HOST"), # e.g. cluster.abc.us-east-1.redshift.amazonaws.com
|
|
||||||
database=os.getenv("REDSHIFT_DATABASE"),
|
|
||||||
user=os.getenv("REDSHIFT_USER"),
|
|
||||||
password=os.getenv("REDSHIFT_PASSWORD"),
|
|
||||||
port=5439, # default; omit to use the default
|
|
||||||
ssl=True, # default
|
|
||||||
)
|
|
||||||
```
|
|
||||||
|
|
||||||
Required environment variables:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
export REDSHIFT_HOST="cluster.abc.us-east-1.redshift.amazonaws.com"
|
|
||||||
export REDSHIFT_DATABASE="dev"
|
|
||||||
export REDSHIFT_USER="awsuser"
|
|
||||||
export REDSHIFT_PASSWORD="your-password"
|
|
||||||
```
|
|
||||||
</Tab>
|
|
||||||
<Tab title="IAM Role (Recommended for AWS)">
|
|
||||||
Use `iam=True` to obtain temporary credentials via
|
|
||||||
`GetClusterCredentials`. The connector delegates credential resolution
|
|
||||||
entirely to `redshift-connector` / boto3 — Semantica never calls AWS
|
|
||||||
APIs directly.
|
|
||||||
|
|
||||||
**Profile-based** (reads `~/.aws/credentials`):
|
|
||||||
|
|
||||||
```python
|
|
||||||
import os
|
|
||||||
from semantica.ingest import RedshiftIngestor
|
|
||||||
|
|
||||||
ingestor = RedshiftIngestor(
|
|
||||||
host=os.getenv("REDSHIFT_HOST"),
|
|
||||||
database=os.getenv("REDSHIFT_DATABASE"),
|
|
||||||
iam=True,
|
|
||||||
db_user=os.getenv("REDSHIFT_DB_USER"),
|
|
||||||
cluster_identifier=os.getenv("REDSHIFT_CLUSTER_IDENTIFIER"),
|
|
||||||
profile="default", # AWS credentials-file profile
|
|
||||||
)
|
|
||||||
```
|
|
||||||
|
|
||||||
**Explicit AWS credentials** (e.g. for CI/CD or IAM roles with short-lived keys):
|
|
||||||
|
|
||||||
```python
|
|
||||||
ingestor = RedshiftIngestor(
|
|
||||||
host=os.getenv("REDSHIFT_HOST"),
|
|
||||||
database=os.getenv("REDSHIFT_DATABASE"),
|
|
||||||
iam=True,
|
|
||||||
db_user=os.getenv("REDSHIFT_DB_USER"),
|
|
||||||
cluster_identifier=os.getenv("REDSHIFT_CLUSTER_IDENTIFIER"),
|
|
||||||
region=os.getenv("REDSHIFT_REGION"),
|
|
||||||
access_key_id=os.getenv("REDSHIFT_ACCESS_KEY_ID"),
|
|
||||||
secret_access_key=os.getenv("REDSHIFT_SECRET_ACCESS_KEY"),
|
|
||||||
session_token=os.getenv("REDSHIFT_SESSION_TOKEN"), # only for temporary creds
|
|
||||||
)
|
|
||||||
```
|
|
||||||
|
|
||||||
When neither `profile` nor explicit keys are supplied, `redshift-connector`
|
|
||||||
falls back to the standard AWS credential chain: `AWS_*` environment
|
|
||||||
variables, instance-profile metadata, etc.
|
|
||||||
|
|
||||||
Required for IAM mode: `host`, `database`, `db_user`, `cluster_identifier`.
|
|
||||||
The `region` parameter is optional when it can be inferred from the
|
|
||||||
credential chain or the cluster endpoint.
|
|
||||||
</Tab>
|
|
||||||
</Tabs>
|
|
||||||
|
|
||||||
|
|
||||||
## Environment Variables
|
|
||||||
|
|
||||||
All constructor parameters have `REDSHIFT_*` environment-variable fallbacks.
|
|
||||||
Explicit constructor values always take precedence.
|
|
||||||
|
|
||||||
| Variable | Parameter | Default |
|
|
||||||
|---|---|---|
|
|
||||||
| `REDSHIFT_HOST` | `host` | — |
|
|
||||||
| `REDSHIFT_DATABASE` | `database` | — |
|
|
||||||
| `REDSHIFT_USER` | `user` | — |
|
|
||||||
| `REDSHIFT_PASSWORD` | `password` | — |
|
|
||||||
| `REDSHIFT_PORT` | `port` | `5439` |
|
|
||||||
| `REDSHIFT_SCHEMA` | `schema` | `"public"` |
|
|
||||||
| `REDSHIFT_DB_USER` | `db_user` | — |
|
|
||||||
| `REDSHIFT_CLUSTER_IDENTIFIER` | `cluster_identifier` | — |
|
|
||||||
| `REDSHIFT_REGION` | `region` | — |
|
|
||||||
| `REDSHIFT_PROFILE` | `profile` | — |
|
|
||||||
| `REDSHIFT_ACCESS_KEY_ID` | `access_key_id` | — |
|
|
||||||
| `REDSHIFT_SECRET_ACCESS_KEY` | `secret_access_key` | — |
|
|
||||||
| `REDSHIFT_SESSION_TOKEN` | `session_token` | — |
|
|
||||||
|
|
||||||
|
|
||||||
## Querying
|
|
||||||
|
|
||||||
### Ingest a table
|
|
||||||
|
|
||||||
```python
|
|
||||||
data = ingestor.ingest_table("orders")
|
|
||||||
print(f"{data.row_count} rows, columns: {data.columns}")
|
|
||||||
```
|
|
||||||
|
|
||||||
### Schema, filters, and pagination
|
|
||||||
|
|
||||||
```python
|
|
||||||
data = ingestor.ingest_table(
|
|
||||||
"orders",
|
|
||||||
schema="sales", # defaults to the ingestor's schema attribute ("public")
|
|
||||||
database="analytics", # defaults to the connector's database
|
|
||||||
where="status = 'shipped' AND total > 100",
|
|
||||||
order_by="created_at DESC",
|
|
||||||
limit=5000,
|
|
||||||
offset=0,
|
|
||||||
)
|
|
||||||
```
|
|
||||||
|
|
||||||
<Warning>
|
|
||||||
`where` and `order_by` accept raw SQL fragments and must be trusted, operator-controlled input. Do not pass raw end-user strings here. They are validated against a blocklist that rejects statement separators, `UNION`, DML/DDL keywords, and time-based injection patterns, but this is not a full parser.
|
|
||||||
</Warning>
|
|
||||||
|
|
||||||
### Custom SQL
|
|
||||||
|
|
||||||
```python
|
|
||||||
data = ingestor.ingest_query("""
|
|
||||||
SELECT customer_id, SUM(total) AS lifetime_value
|
|
||||||
FROM sales.orders
|
|
||||||
WHERE status = 'completed'
|
|
||||||
GROUP BY customer_id
|
|
||||||
ORDER BY lifetime_value DESC
|
|
||||||
LIMIT 1000
|
|
||||||
""")
|
|
||||||
print(f"{data.row_count} rows")
|
|
||||||
```
|
|
||||||
|
|
||||||
### Parameterized queries
|
|
||||||
|
|
||||||
Use `%s` placeholders (DB-API 2.0 `format` paramstyle, which is the default for `redshift-connector`):
|
|
||||||
|
|
||||||
```python
|
|
||||||
data = ingestor.ingest_query(
|
|
||||||
"SELECT id, name FROM users WHERE region = %s AND active = %s",
|
|
||||||
params=("us-east-1", True),
|
|
||||||
)
|
|
||||||
```
|
|
||||||
|
|
||||||
### Batch fetching for large result sets
|
|
||||||
|
|
||||||
Use `batch_size` to control the driver fetch size — rows are fetched from
|
|
||||||
the server in chunks of that size rather than all at once, and each chunk is
|
|
||||||
converted immediately before the next is requested:
|
|
||||||
|
|
||||||
```python
|
|
||||||
data = ingestor.ingest_query(
|
|
||||||
"SELECT * FROM large_events_table",
|
|
||||||
batch_size=10000,
|
|
||||||
)
|
|
||||||
```
|
|
||||||
|
|
||||||
`batch_size` controls how many rows the driver reads from Redshift per
|
|
||||||
round-trip. The returned `RedshiftData.data` list still contains all matching
|
|
||||||
rows; use `LIMIT`/`OFFSET` in the query itself if you need to cap the total
|
|
||||||
result size.
|
|
||||||
|
|
||||||
|
|
||||||
## Schema Discovery
|
|
||||||
|
|
||||||
### List base tables in a schema
|
|
||||||
|
|
||||||
```python
|
|
||||||
tables = ingestor.list_tables(schema="public")
|
|
||||||
print(tables) # ["customers", "orders", "products", ...]
|
|
||||||
```
|
|
||||||
|
|
||||||
Views are excluded; only base tables are returned.
|
|
||||||
|
|
||||||
### Inspect column metadata
|
|
||||||
|
|
||||||
```python
|
|
||||||
schema = ingestor.get_table_schema("customers", schema="public")
|
|
||||||
|
|
||||||
for col in schema["columns"]:
|
|
||||||
print(f"{col['name']}: {col['type']} (nullable={col['nullable']})")
|
|
||||||
|
|
||||||
print("Primary keys:", schema["primary_keys"])
|
|
||||||
```
|
|
||||||
|
|
||||||
Each column dict contains:
|
|
||||||
|
|
||||||
| Key | Type | Description |
|
|
||||||
|---|---|---|
|
|
||||||
| `name` | `str` | Column name |
|
|
||||||
| `type` | `str` | Redshift data type (e.g. `"integer"`, `"character varying"`) |
|
|
||||||
| `nullable` | `bool` | Whether the column accepts `NULL` |
|
|
||||||
|
|
||||||
`primary_keys` is a list of column-name strings (empty list when no primary key is defined).
|
|
||||||
|
|
||||||
|
|
||||||
## Export as Semantica Documents
|
|
||||||
|
|
||||||
Convert ingested rows to the document format that `GraphBuilder` consumes:
|
|
||||||
|
|
||||||
```python
|
|
||||||
documents = ingestor.export_as_documents(
|
|
||||||
data,
|
|
||||||
id_field="customer_id", # column used as document ID; defaults to "id"
|
|
||||||
text_fields=["name", "notes"], # columns joined as document text; omit to auto-select
|
|
||||||
)
|
|
||||||
|
|
||||||
print(f"Created {len(documents)} documents")
|
|
||||||
# Each document:
|
|
||||||
# {
|
|
||||||
# "id": "12345",
|
|
||||||
# "text": "Alice Acme customer notes here",
|
|
||||||
# "metadata": {
|
|
||||||
# "source": "redshift",
|
|
||||||
# "table": "customers",
|
|
||||||
# "database": "analytics",
|
|
||||||
# "schema": "public",
|
|
||||||
# "row_data": { ... full cleaned row ... }
|
|
||||||
# }
|
|
||||||
# }
|
|
||||||
```
|
|
||||||
|
|
||||||
**ID resolution**: `str(row.get(id_field, row_index))` — the integer row index is used as a deterministic fallback when the `id_field` column is absent.
|
|
||||||
|
|
||||||
**Text when `text_fields` is provided**: each non-`None` field value is converted to a string and joined with a single space.
|
|
||||||
|
|
||||||
**Text when `text_fields=None`**: only columns whose values are already `str` type are joined. Integer, float, boolean, and `None` values are excluded, matching the Snowflake and Databricks connector behavior.
|
|
||||||
|
|
||||||
Pass the documents directly to `GraphBuilder`:
|
|
||||||
|
|
||||||
```python
|
|
||||||
from semantica.kg import GraphBuilder
|
|
||||||
|
|
||||||
builder = GraphBuilder()
|
|
||||||
graph = builder.build(documents)
|
|
||||||
print(f"Entities: {graph['metadata']['num_entities']}")
|
|
||||||
```
|
|
||||||
|
|
||||||
|
|
||||||
## Context Manager
|
|
||||||
|
|
||||||
Prefer the context manager for jobs that run multiple queries — it opens one connection on entry and closes it on exit, so every call inside the `with` block reuses the same authenticated session:
|
|
||||||
|
|
||||||
```python
|
|
||||||
with RedshiftIngestor(
|
|
||||||
host=os.getenv("REDSHIFT_HOST"),
|
|
||||||
database=os.getenv("REDSHIFT_DATABASE"),
|
|
||||||
user=os.getenv("REDSHIFT_USER"),
|
|
||||||
password=os.getenv("REDSHIFT_PASSWORD"),
|
|
||||||
) as ingestor:
|
|
||||||
customers = ingestor.ingest_table("customers", limit=50000)
|
|
||||||
orders = ingestor.ingest_table("orders", limit=50000)
|
|
||||||
schema = ingestor.get_table_schema("customers")
|
|
||||||
tables = ingestor.list_tables()
|
|
||||||
# Connection closed automatically on exit, even if an exception is raised.
|
|
||||||
```
|
|
||||||
|
|
||||||
Standalone calls (without `with`) open and close a transient connection per call.
|
|
||||||
|
|
||||||
|
|
||||||
## Connection Test
|
|
||||||
|
|
||||||
```python
|
|
||||||
from semantica.ingest import RedshiftConnector
|
|
||||||
|
|
||||||
connector = RedshiftConnector(
|
|
||||||
host="cluster.abc.us-east-1.redshift.amazonaws.com",
|
|
||||||
database="dev",
|
|
||||||
user="awsuser",
|
|
||||||
password="your-password",
|
|
||||||
)
|
|
||||||
if connector.test_connection():
|
|
||||||
print("Connection OK")
|
|
||||||
else:
|
|
||||||
print("Connection failed — check host, credentials, and network access")
|
|
||||||
```
|
|
||||||
|
|
||||||
|
|
||||||
## See Also
|
|
||||||
|
|
||||||
- [Ingest Module](../reference/ingest) — Full `RedshiftIngestor` reference and all other ingestors.
|
|
||||||
- [Snowflake Integration](/integrations/snowflake) — SQL data warehouse connector with similar table/query ingestion.
|
|
||||||
- [Databricks Integration](/integrations/databricks) — Delta Lake / Unity Catalog connector.
|
|
||||||
- [Pipeline](../reference/pipeline) — Use Redshift ingestion as a pipeline step.
|
|
||||||
- [Installation](../installation) — All optional dependency extras.
|
|
||||||
- [Knowledge Graph](../reference/kg) — Build a knowledge graph from ingested Redshift data.
|
|
||||||
+28
-50
@@ -9,9 +9,9 @@ Whether you're running your first pipeline or deploying Semantica in production,
|
|||||||
|
|
||||||
## Learning Paths
|
## Learning Paths
|
||||||
|
|
||||||
- **Beginner (1–2 hrs)**: new to Semantica and knowledge graphs. [Start with Installation →](/installation)
|
- **Beginner (1–2 hrs)** — New to Semantica and knowledge graphs. [Start with Installation →](/installation)
|
||||||
- **Intermediate (4–6 hrs)**: comfortable with basics, building real applications. [Start with Modules →](/modules)
|
- **Intermediate (4–6 hrs)** — Comfortable with basics, building real applications. [Start with Modules →](/modules)
|
||||||
- **Advanced (8+ hrs)**: enterprise deployments, customization, and extension. [Start with Architecture →](/architecture)
|
- **Advanced (8+ hrs)** — Enterprise deployments, customization, and extension. [Start with Architecture →](/architecture)
|
||||||
|
|
||||||
<Tabs>
|
<Tabs>
|
||||||
<Tab title="Beginner (1–2 hrs)">
|
<Tab title="Beginner (1–2 hrs)">
|
||||||
@@ -64,7 +64,7 @@ Whether you're running your first pipeline or deploying Semantica in production,
|
|||||||
[Temporal Graphs notebook](https://github.com/semantica-agi/semantica/blob/main/cookbook/advanced/10_Temporal_Knowledge_Graphs.ipynb): `valid_from`/`valid_until`, Allen interval algebra, point-in-time queries.
|
[Temporal Graphs notebook](https://github.com/semantica-agi/semantica/blob/main/cookbook/advanced/10_Temporal_Knowledge_Graphs.ipynb): `valid_from`/`valid_until`, Allen interval algebra, point-in-time queries.
|
||||||
</Step>
|
</Step>
|
||||||
<Step title="Ontology-driven knowledge bases">
|
<Step title="Ontology-driven knowledge bases">
|
||||||
[Ontology notebook](https://github.com/semantica-agi/semantica/blob/main/cookbook/introduction/14_Ontology.ipynb): auto-generation, SHACL validation, Ontology Hub.
|
[Ontology notebook](https://github.com/semantica-agi/semantica/blob/main/cookbook/introduction/14_Ontology.ipynb): auto-generation, SHACL validation, Ontology Hub (v0.5.0).
|
||||||
</Step>
|
</Step>
|
||||||
<Step title="Advanced visualization">
|
<Step title="Advanced visualization">
|
||||||
[Complete Visualization Suite notebook](https://github.com/semantica-agi/semantica/blob/main/cookbook/advanced/03_Complete_Visualization_Suite.ipynb): UMAP, t-SNE, community layouts, embedding projections.
|
[Complete Visualization Suite notebook](https://github.com/semantica-agi/semantica/blob/main/cookbook/advanced/03_Complete_Visualization_Suite.ipynb): UMAP, t-SNE, community layouts, embedding projections.
|
||||||
@@ -86,10 +86,10 @@ All settings can be overridden with environment variables: no code changes neede
|
|||||||
| OpenAI API Key | `OPENAI_API_KEY` | `None` |
|
| OpenAI API Key | `OPENAI_API_KEY` | `None` |
|
||||||
| Groq API Key | `GROQ_API_KEY` | `None` |
|
| Groq API Key | `GROQ_API_KEY` | `None` |
|
||||||
| Anthropic API Key | `ANTHROPIC_API_KEY` | `None` |
|
| Anthropic API Key | `ANTHROPIC_API_KEY` | `None` |
|
||||||
| Graph Store Backend | `GRAPH_STORE_DEFAULT_BACKEND` | `"neo4j"` |
|
| Embedding Provider | `SEMANTICA_EMBEDDING_PROVIDER` | `"openai"` |
|
||||||
| Vector Store Backend | `VECTOR_STORE_DEFAULT_BACKEND` | `"faiss"` |
|
| Graph Backend | `SEMANTICA_GRAPH_BACKEND` | `"networkx"` |
|
||||||
| Server Host | `SEMANTICA_HOST` | `"127.0.0.1"` |
|
| Log Level | `SEMANTICA_LOG_LEVEL` | `"INFO"` |
|
||||||
| Server API Key | `SEMANTICA_API_KEY` | `None` |
|
| Log Format | `SEMANTICA_LOG_FORMAT` | `"text"` |
|
||||||
|
|
||||||
|
|
||||||
## Troubleshooting
|
## Troubleshooting
|
||||||
@@ -116,7 +116,7 @@ pip install "semantica[gpu]" # GPU acceleration
|
|||||||
|
|
||||||
<Accordion title="AuthenticationError" icon="lock">
|
<Accordion title="AuthenticationError" icon="lock">
|
||||||
|
|
||||||
Set your API key as an environment variable (never hardcode keys in source files):
|
Set your API key as an environment variable — never hardcode keys in source files:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
export OPENAI_API_KEY="sk-..."
|
export OPENAI_API_KEY="sk-..."
|
||||||
@@ -146,15 +146,10 @@ Also reduce batch sizes and enable streaming ingestion for large corpora.
|
|||||||
Enable parallel execution and GPU acceleration:
|
Enable parallel execution and GPU acceleration:
|
||||||
|
|
||||||
```python
|
```python
|
||||||
from semantica.pipeline import ParallelismManager, Task
|
from semantica.pipeline import Pipeline
|
||||||
|
|
||||||
# Run pipeline tasks concurrently across worker threads
|
pipeline = Pipeline(workers=8, batch_size=32)
|
||||||
manager = ParallelismManager(max_workers=8)
|
pipeline.run(sources)
|
||||||
tasks = [
|
|
||||||
Task("task_1", lambda: "process part 1"),
|
|
||||||
Task("task_2", lambda: "process part 2"),
|
|
||||||
]
|
|
||||||
results = manager.execute_parallel(tasks)
|
|
||||||
```
|
```
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
@@ -165,19 +160,19 @@ pip install "semantica[gpu]" # CUDA-backed embeddings
|
|||||||
|
|
||||||
<Accordion title="Windows [all] installation fails" icon="windows">
|
<Accordion title="Windows [all] installation fails" icon="windows">
|
||||||
|
|
||||||
Upgrade to the latest release:
|
Fixed in **v0.5.0**. Upgrade:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
pip install --upgrade semantica
|
pip install --upgrade semantica
|
||||||
```
|
```
|
||||||
|
|
||||||
Or install extras individually: `pip install semantica`, then add `[llm-openai]`, `[gpu]`, etc. as needed.
|
Or install extras individually: `pip install "semantica[core]"`, then add `[llm-openai]`, `[gpu]`, etc. as needed.
|
||||||
|
|
||||||
</Accordion>
|
</Accordion>
|
||||||
|
|
||||||
<Accordion title="cp1252 encoding crash on Windows" icon="windows">
|
<Accordion title="cp1252 encoding crash on Windows" icon="windows">
|
||||||
|
|
||||||
Set the encoding environment variable:
|
Fixed in **v0.5.0**. For earlier versions, set the encoding environment variable:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
set PYTHONIOENCODING=utf-8
|
set PYTHONIOENCODING=utf-8
|
||||||
@@ -207,44 +202,27 @@ Use NetworkX for local development and prototyping. Switch to a persistent backe
|
|||||||
|
|
||||||
<Accordion title="Batch processing for large corpora" icon="layer-group">
|
<Accordion title="Batch processing for large corpora" icon="layer-group">
|
||||||
|
|
||||||
Process documents in batches rather than one at a time. Split large texts into chunks and extract entities in batches:
|
Process documents in batches rather than one at a time. Configure `chunk_size` based on available RAM: a good starting point is 1,000 documents per batch on a 16 GB machine.
|
||||||
|
|
||||||
```python
|
```python
|
||||||
from semantica.split import TextSplitter
|
from semantica.pipeline import Pipeline
|
||||||
from semantica.semantic_extract import NERExtractor
|
|
||||||
|
|
||||||
document_text = "Acme Corp announced record revenue in Seattle. CEO Jane Doe presented results."
|
pipeline = Pipeline(workers=8, batch_size=32)
|
||||||
splitter = TextSplitter(chunk_size=1000, chunk_overlap=100)
|
pipeline.run(sources)
|
||||||
chunks = splitter.split(document_text)
|
|
||||||
|
|
||||||
extractor = NERExtractor()
|
|
||||||
batch_entities = extractor.extract_entities_batch([c.text for c in chunks])
|
|
||||||
```
|
```
|
||||||
|
|
||||||
</Accordion>
|
</Accordion>
|
||||||
|
|
||||||
<Accordion title="Deduplication v2: up to 7× faster" icon="bolt">
|
<Accordion title="Deduplication v2: up to 7× faster" icon="bolt">
|
||||||
|
|
||||||
If deduplication is a bottleneck, use candidate blocking to reduce O(n²) comparisons before similarity scoring:
|
If deduplication is a bottleneck, switch from v1 strategies to the v2 engine:
|
||||||
|
|
||||||
```python
|
```python
|
||||||
from semantica.deduplication import DuplicateDetector, EntityMerger
|
resolver = EntityResolver()
|
||||||
|
merged = resolver.resolve(entities, strategy="semantic_v2") # up to 7x faster
|
||||||
entities = [
|
|
||||||
{"id": "1", "name": "Acme Corp", "type": "Company"},
|
|
||||||
{"id": "2", "name": "Acme Corporation", "type": "Company"},
|
|
||||||
{"id": "3", "name": "Globex", "type": "Company"},
|
|
||||||
]
|
|
||||||
|
|
||||||
# Fast candidate blocking for large entity sets
|
|
||||||
detector = DuplicateDetector(similarity_threshold=0.8)
|
|
||||||
duplicates = detector.detect_duplicates(entities, candidate_strategy="blocking_v2")
|
|
||||||
|
|
||||||
merger = EntityMerger()
|
|
||||||
merged = merger.merge_duplicates(entities, strategy="keep_most_complete")
|
|
||||||
```
|
```
|
||||||
|
|
||||||
The `blocking_v2` and `hybrid_v2` candidate strategies filter candidate pairs before calculating fine-grained similarity.
|
The `blocking_v2`, `hybrid_v2`, and `semantic_v2` strategies reduce O(n²) comparisons via candidate blocking before similarity scoring.
|
||||||
|
|
||||||
</Accordion>
|
</Accordion>
|
||||||
|
|
||||||
@@ -255,9 +233,9 @@ The `blocking_v2` and `hybrid_v2` candidate strategies filter candidate pairs be
|
|||||||
|
|
||||||
- **API keys**: store in environment variables or a secrets manager; never commit them to version control; rotate on a schedule
|
- **API keys**: store in environment variables or a secrets manager; never commit them to version control; rotate on a schedule
|
||||||
- **Sensitive data**: use local embedding models (Ollama, HuggingFace) for PII or classified content; avoid sending sensitive data to external APIs without data handling agreements
|
- **Sensitive data**: use local embedding models (Ollama, HuggingFace) for PII or classified content; avoid sending sensitive data to external APIs without data handling agreements
|
||||||
- **Graph exports**: encrypt sensitive exports at rest; use SSRF-safe `base_url` validation when configuring custom LLM gateways
|
- **Graph exports**: encrypt sensitive exports at rest; use the v0.5.0 SSRF-safe `base_url` validation when configuring custom LLM gateways
|
||||||
- **XML ingestion**: always use `XMLIngestor`, which uses the XXE-safe lxml backend; never parse untrusted XML with the standard library parser
|
- **XML ingestion**: always use `XMLIngestor` (v0.5.0), which uses the XXE-safe lxml backend; never parse untrusted XML with the standard library parser
|
||||||
|
|
||||||
- [Cookbook](/cookbook): interactive Jupyter notebooks from beginner to advanced.
|
- [Cookbook](/cookbook) — Interactive Jupyter notebooks from beginner to advanced.
|
||||||
- [FAQ](/faq): common questions answered.
|
- [FAQ](/faq) — Common questions answered.
|
||||||
- [API Reference](/reference/core): complete technical documentation.
|
- [API Reference](/reference/core) — Complete technical documentation.
|
||||||
|
|||||||
+135
-176
@@ -5,32 +5,30 @@ icon: "puzzle-piece"
|
|||||||
---
|
---
|
||||||
|
|
||||||
<Info>
|
<Info>
|
||||||
Jump to the [Module Index](#module-index) for a quick reference.
|
Looking for a quick reference? Jump to the [Module Index](#module-index) at the bottom.
|
||||||
</Info>
|
</Info>
|
||||||
|
|
||||||
<Tip>
|
<Tip>
|
||||||
The [Choose the Right Module](/choose-your-module) guide maps 35+ developer goals to modules with code examples; start there if you're orienting for the first time.
|
Not sure which module to use? The [Choose the Right Module](/choose-your-module) guide maps 35+ developer goals to modules with code examples — start there if you're orienting for the first time.
|
||||||
</Tip>
|
</Tip>
|
||||||
|
|
||||||
Semantica is organized into **27 modules** across six logical layers. Each module is independently importable: you never pay for what you don't use.
|
Semantica is organized into **27 modules** across six logical layers. Each module is independently importable: you never pay for what you don't use.
|
||||||
|
|
||||||
## Architecture Overview
|
## Architecture Overview
|
||||||
|
|
||||||
- **Input Layer**: data ingestion and preparation. Modules: `ingest`, `parse`, `split`, `normalize`
|
- **Input Layer** — Data ingestion and preparation. Modules: `ingest`, `parse`, `split`, `normalize`
|
||||||
- **Core Processing**: intelligence and understanding. Modules: `semantic_extract`, `kg`, `ontology`, `reasoning`
|
- **Core Processing** — Intelligence and understanding. Modules: `semantic_extract`, `kg`, `ontology`, `reasoning`
|
||||||
- **Storage**: persistent data storage. Modules: `embeddings`, `vector_store`, `graph_store`, `triplet_store`
|
- **Storage** — Persistent data storage. Modules: `embeddings`, `vector_store`, `graph_store`, `triplet_store`
|
||||||
- **Quality Assurance**: data quality and consistency. Modules: `deduplication`, `conflicts`
|
- **Quality Assurance** — Data quality and consistency. Modules: `deduplication`, `conflicts`
|
||||||
- **Context & Memory**: agent memory and decision tracking. Modules: `context`, `provenance`, `change_management`
|
- **Context & Memory** — Agent memory and decision tracking. Modules: `context`, `provenance`, `change_management`
|
||||||
- **Output & Orchestration**: export, visualization, and workflows. Modules: `export`, `visualization`, `pipeline`, `explorer`
|
- **Output & Orchestration** — Export, visualization, and workflows. Modules: `export`, `visualization`, `pipeline`, `explorer`
|
||||||
|
|
||||||
|
|
||||||
## Input Layer
|
## Input Layer
|
||||||
|
|
||||||
### Ingest
|
### Ingest
|
||||||
|
|
||||||
Loads data from files, web, databases, and streams. Each ingestor returns its own
|
Loads data from files, web, databases, and streams into a unified `SourceDocument` format.
|
||||||
result type (`FileIngestor` → `FileObject`, `WebIngestor` → `WebContent`, …);
|
|
||||||
document-oriented ones expose a `.text` payload and `.metadata`.
|
|
||||||
|
|
||||||
```python
|
```python
|
||||||
from semantica.ingest import FileIngestor, WebIngestor, ParquetIngestor, XMLIngestor, DatabricksIngestor
|
from semantica.ingest import FileIngestor, WebIngestor, ParquetIngestor, XMLIngestor, DatabricksIngestor
|
||||||
@@ -39,7 +37,7 @@ from semantica.ingest import FileIngestor, WebIngestor, ParquetIngestor, XMLInge
|
|||||||
ingestor = FileIngestor()
|
ingestor = FileIngestor()
|
||||||
documents = ingestor.ingest_directory("data/")
|
documents = ingestor.ingest_directory("data/")
|
||||||
|
|
||||||
# Web page: returns a WebContent with .text, .title, .links, .metadata
|
# Web crawl
|
||||||
web_ingestor = WebIngestor()
|
web_ingestor = WebIngestor()
|
||||||
page = web_ingestor.ingest_url("https://example.com")
|
page = web_ingestor.ingest_url("https://example.com")
|
||||||
|
|
||||||
@@ -51,7 +49,7 @@ sources = parquet.ingest("data/events.parquet")
|
|||||||
xml = XMLIngestor()
|
xml = XMLIngestor()
|
||||||
sources = xml.ingest("data/records/", schema_path="schema.xsd")
|
sources = xml.ingest("data/records/", schema_path="schema.xsd")
|
||||||
|
|
||||||
# Enterprise lakehouse/warehouse: Unity Catalog + Delta Lake, or a Snowflake warehouse
|
# Enterprise lakehouse/warehouse — Unity Catalog + Delta Lake, or a Snowflake warehouse
|
||||||
databricks = DatabricksIngestor(host="...", token="...", http_path="...")
|
databricks = DatabricksIngestor(host="...", token="...", http_path="...")
|
||||||
customers = databricks.ingest_table("customers")
|
customers = databricks.ingest_table("customers")
|
||||||
```
|
```
|
||||||
@@ -59,7 +57,7 @@ customers = databricks.ingest_table("customers")
|
|||||||
**Available ingestors:** `FileIngestor`, `WebIngestor`, `ParquetIngestor`, `XMLIngestor`, `RESTIngestor`, `PublicAPIIngestor`, `DBIngestor`, `DatabricksIngestor`, `SnowflakeIngestor`, `EmailIngestor`, `FeedIngestor`, `MCPIngestor`, `OntologyIngestor`, `RepoIngestor`, `StreamIngestor`, `ArrowIngestor`, `CloudStorageIngestor`
|
**Available ingestors:** `FileIngestor`, `WebIngestor`, `ParquetIngestor`, `XMLIngestor`, `RESTIngestor`, `PublicAPIIngestor`, `DBIngestor`, `DatabricksIngestor`, `SnowflakeIngestor`, `EmailIngestor`, `FeedIngestor`, `MCPIngestor`, `OntologyIngestor`, `RepoIngestor`, `StreamIngestor`, `ArrowIngestor`, `CloudStorageIngestor`
|
||||||
|
|
||||||
<Note>
|
<Note>
|
||||||
`DuckDBIngestor`, `ElasticIngestor`, `GDriveIngestor`, `HuggingFaceIngestor`, `MongoIngestor`, and `PandasIngestor` also ship but aren't re-exported from the top-level `semantica.ingest` namespace yet; import them directly, e.g. `from semantica.ingest.duckdb_ingestor import DuckDBIngestor`.
|
`DuckDBIngestor`, `ElasticIngestor`, `GDriveIngestor`, `HuggingFaceIngestor`, `MongoIngestor`, and `PandasIngestor` also ship but aren't re-exported from the top-level `semantica.ingest` namespace yet — import them directly, e.g. `from semantica.ingest.duckdb_ingestor import DuckDBIngestor`.
|
||||||
</Note>
|
</Note>
|
||||||
|
|
||||||
### Parse
|
### Parse
|
||||||
@@ -69,13 +67,13 @@ Extracts structured text and layout metadata from raw documents.
|
|||||||
```python
|
```python
|
||||||
from semantica.parse import DocumentParser, DoclingParser
|
from semantica.parse import DocumentParser, DoclingParser
|
||||||
|
|
||||||
# Standard parser: all common formats. parse() takes a path, returns a dict
|
# Standard parser: all common formats
|
||||||
parser = DocumentParser()
|
parser = DocumentParser()
|
||||||
parsed = parser.parse("document.pdf") # {"full_text": ..., "metadata": ..., ...}
|
parsed = parser.parse_document("document.pdf")
|
||||||
|
|
||||||
# Advanced parser (pip install semantica[parse-docling]): tables, OCR, layout
|
# Advanced parser: multi-column PDFs, merged-cell tables, OCR
|
||||||
parser = DoclingParser(export_format="markdown", enable_ocr=True)
|
parser = DoclingParser(extract_tables=True, extract_images=True, output_format="markdown")
|
||||||
parsed = parser.parse("data/annual_report.pdf") # dict with full_text, tables, pages
|
parsed = parser.parse("data/annual_report.pdf")
|
||||||
```
|
```
|
||||||
|
|
||||||
**Available parsers:** `DocumentParser`, `DoclingParser`, `CodeParser`, `CSVParser`, `DocxParser`, `EmailParser`, `ExcelParser`, `HTMLParser`, `ImageParser`, `JSONParser`, `MCPParser`, `MediaParser`, `PDFParser`, `PPTXParser`, `StructuredDataParser`, `WebParser`, `XMLParser`
|
**Available parsers:** `DocumentParser`, `DoclingParser`, `CodeParser`, `CSVParser`, `DocxParser`, `EmailParser`, `ExcelParser`, `HTMLParser`, `ImageParser`, `JSONParser`, `MCPParser`, `MediaParser`, `PDFParser`, `PPTXParser`, `StructuredDataParser`, `WebParser`, `XMLParser`
|
||||||
@@ -87,12 +85,11 @@ Chunks text for embedding and RAG pipelines with awareness of semantic boundarie
|
|||||||
```python
|
```python
|
||||||
from semantica.split import TextSplitter
|
from semantica.split import TextSplitter
|
||||||
|
|
||||||
# chunk_size / chunk_overlap are constructor arguments
|
splitter = TextSplitter(method="semantic_transformer")
|
||||||
splitter = TextSplitter(method="semantic_transformer", chunk_size=1000, chunk_overlap=200)
|
chunks = splitter.split(text, chunk_size=1000, chunk_overlap=200)
|
||||||
chunks = splitter.split(text)
|
|
||||||
```
|
```
|
||||||
|
|
||||||
**Chunking methods:** `recursive`, `token`, `sentence`, `paragraph`, `semantic_transformer`, `entity_aware`, `relation_aware`, `graph_based`, `ontology_aware`, `hierarchical`, `community_detection`, `centrality_based`, `llm`
|
**Chunking strategies:** `recursive`, `semantic_transformer`, `entity_aware`, `relation_aware`, `sliding_window`, `structural`
|
||||||
|
|
||||||
### Normalize
|
### Normalize
|
||||||
|
|
||||||
@@ -118,18 +115,17 @@ Named entity recognition, relation extraction, and triplet generation.
|
|||||||
```python
|
```python
|
||||||
from semantica.semantic_extract import NERExtractor, RelationExtractor, TripletExtractor
|
from semantica.semantic_extract import NERExtractor, RelationExtractor, TripletExtractor
|
||||||
|
|
||||||
# LLM method: provider + llm_model select the backend; the API key comes from the env
|
ner = NERExtractor(method="llm", llm_provider=llm)
|
||||||
ner = NERExtractor(method="llm", provider="groq", llm_model="llama-3.3-70b-versatile")
|
entities = ner.extract("Apple Inc. was founded by Steve Jobs.")
|
||||||
entities = ner.extract("Apple Inc. was founded by Steve Jobs.") # list[Entity]
|
|
||||||
|
|
||||||
rel = RelationExtractor(method="llm", provider="groq", llm_model="llama-3.3-70b-versatile")
|
rel = RelationExtractor(method="llm", llm_provider=llm)
|
||||||
relationships = rel.extract(text, entities=entities) # list[Relation]
|
relationships = rel.extract(text, entities=entities)
|
||||||
|
|
||||||
trip = TripletExtractor(method="pattern")
|
trip = TripletExtractor(method="llm", llm_provider=llm)
|
||||||
triplets = trip.extract(text) # list[Triplet]
|
triplets = trip.extract(text)
|
||||||
```
|
```
|
||||||
|
|
||||||
**Extraction methods:** `"pattern"` (no API key), `"ml"` (local spaCy model), `"llm"` (any of the 9 supported providers)
|
**Extraction methods:** `"pattern"` (no API key), `"ml"` (local model), `"llm"` (any of the 8 supported providers)
|
||||||
|
|
||||||
**Additional extractors:** `CoreferenceResolver`, `EventDetector`, `SemanticAnalyzer`, `SemanticNetworkExtractor`
|
**Additional extractors:** `CoreferenceResolver`, `EventDetector`, `SemanticAnalyzer`, `SemanticNetworkExtractor`
|
||||||
|
|
||||||
@@ -141,17 +137,17 @@ Graph construction, graph algorithms, temporal model, and distance intelligence.
|
|||||||
from semantica.kg import GraphBuilder, GraphAnalyzer, TemporalGraphQuery, SimilarityCalculator
|
from semantica.kg import GraphBuilder, GraphAnalyzer, TemporalGraphQuery, SimilarityCalculator
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
|
|
||||||
# Build: build() takes a {"entities": ..., "relationships": ...} dict
|
# Build
|
||||||
builder = GraphBuilder(merge_entities=True)
|
builder = GraphBuilder(merge_entities=True)
|
||||||
kg = builder.build({"entities": entities, "relationships": relationships})
|
kg = builder.build(entities=entities, relationships=relationships)
|
||||||
|
|
||||||
# Temporal graphs (v0.4.0)
|
# Temporal graphs (v0.4.0)
|
||||||
query_engine = TemporalGraphQuery(enable_temporal_reasoning=True)
|
query_engine = TemporalGraphQuery(enable_temporal_reasoning=True)
|
||||||
snapshot = query_engine.query_at_time(kg, query="", at_time=datetime(2021, 6, 15))
|
snapshot = query_engine.query_at_time(kg, query="", at_time=datetime(2021, 6, 15))
|
||||||
|
|
||||||
# Semantic similarity (v0.5.0): operates on embedding vectors
|
# Semantic similarity (v0.5.0)
|
||||||
calc = SimilarityCalculator(method="cosine")
|
calc = SimilarityCalculator()
|
||||||
score = calc.cosine_similarity(vec_a, vec_b)
|
scores = calc.calculate_similarity(entity_a, entity_b)
|
||||||
```
|
```
|
||||||
|
|
||||||
**Graph algorithms available:** centrality calculation, community detection, connectivity analysis, entity resolution, link prediction, path finding, similarity calculation
|
**Graph algorithms available:** centrality calculation, community detection, connectivity analysis, entity resolution, link prediction, path finding, similarity calculation
|
||||||
@@ -179,23 +175,19 @@ Derives new facts from existing knowledge using multiple inference strategies.
|
|||||||
```python
|
```python
|
||||||
from semantica.reasoning import Reasoner, DatalogReasoner
|
from semantica.reasoning import Reasoner, DatalogReasoner
|
||||||
|
|
||||||
# Forward chaining: facts and rules as predicate(args) / IF-THEN strings
|
# Rule-based reasoning
|
||||||
engine = Reasoner()
|
engine = Reasoner()
|
||||||
engine.add_fact("Manager(Alice)")
|
engine.apply_transitivity("located_in")
|
||||||
engine.add_rule("IF Manager(?x) THEN HasAuthority(?x)")
|
engine.apply_symmetry("knows")
|
||||||
results = engine.forward_chain() # list[InferenceResult] with .conclusion, .rule_used
|
result = engine.infer()
|
||||||
|
|
||||||
# Datalog: recursive Horn clause rules (v0.4.0)
|
# Datalog: recursive Horn clause rules (v0.4.0)
|
||||||
datalog = DatalogReasoner()
|
datalog = DatalogEngine()
|
||||||
datalog.add_fact("parent(tom, bob)")
|
|
||||||
datalog.add_fact("parent(bob, ann)")
|
|
||||||
datalog.add_rule("ancestor(X, Y) :- parent(X, Y).")
|
|
||||||
datalog.add_rule("ancestor(X, Z) :- parent(X, Y), ancestor(Y, Z).")
|
datalog.add_rule("ancestor(X, Z) :- parent(X, Y), ancestor(Y, Z).")
|
||||||
datalog.derive_all()
|
results = datalog.query("ancestor(alice, ?)")
|
||||||
results = datalog.query("ancestor(tom, ?Z)") # [{"Z": "bob"}, {"Z": "ann"}], order not guaranteed
|
|
||||||
```
|
```
|
||||||
|
|
||||||
**Engines:** `Reasoner` (forward/backward chaining), `ReteEngine`, `SPARQLReasoner`, `DatalogReasoner`, `TemporalReasoningEngine`, `GraphReasoner` (LLM)
|
**Engines:** forward chaining, Rete network, deductive, abductive, SPARQL, Datalog: all produce explainable inference paths
|
||||||
|
|
||||||
|
|
||||||
## Storage
|
## Storage
|
||||||
@@ -207,9 +199,9 @@ Generates and manages vector embeddings for semantic similarity.
|
|||||||
```python
|
```python
|
||||||
from semantica.embeddings import EmbeddingGenerator
|
from semantica.embeddings import EmbeddingGenerator
|
||||||
|
|
||||||
generator = EmbeddingGenerator()
|
generator = EmbeddingGenerator(model="sentence-transformers")
|
||||||
embeddings = generator.generate_embeddings(["text1", "text2"]) # np.ndarray
|
embeddings = generator.generate(["text1", "text2"])
|
||||||
similarity = generator.compare_embeddings(embeddings[0], embeddings[1])
|
similarity = generator.similarity(embeddings[0], embeddings[1])
|
||||||
```
|
```
|
||||||
|
|
||||||
**Supported models:** Sentence-Transformers, FastEmbed, OpenAI, BGE
|
**Supported models:** Sentence-Transformers, FastEmbed, OpenAI, BGE
|
||||||
@@ -223,18 +215,12 @@ Multi-backend vector database with hybrid search support.
|
|||||||
```python
|
```python
|
||||||
from semantica.vector_store import VectorStore
|
from semantica.vector_store import VectorStore
|
||||||
|
|
||||||
store = VectorStore(backend="faiss", dimension=768)
|
store = VectorStore(backend="faiss", dimension=768)
|
||||||
|
store.add_vectors(embeddings, ids)
|
||||||
# Raw vectors
|
results = store.search(query_vector, top_k=10)
|
||||||
ids = store.store_vectors(embeddings) # returns generated ids
|
|
||||||
hits = store.search_vectors(query_vector, k=10)
|
|
||||||
|
|
||||||
# Or store text and let the store embed it
|
|
||||||
store.add_documents(["Apple was founded in 1976.", "Google was founded in 1998."])
|
|
||||||
results = store.search("tech company founding dates", limit=10)
|
|
||||||
```
|
```
|
||||||
|
|
||||||
**Backends:** FAISS, Pinecone, Weaviate, Qdrant, Milvus, PgVector, SQLite, in-memory
|
**Backends:** FAISS, Pinecone, Weaviate, Qdrant, Milvus, PgVector, in-memory
|
||||||
|
|
||||||
**Search modes:** semantic top-k, hybrid (vector + keyword), metadata-filtered
|
**Search modes:** semantic top-k, hybrid (vector + keyword), metadata-filtered
|
||||||
|
|
||||||
@@ -246,8 +232,8 @@ Connects to graph databases for persistent, query-able storage.
|
|||||||
from semantica.graph_store import GraphStore
|
from semantica.graph_store import GraphStore
|
||||||
|
|
||||||
store = GraphStore(backend="neo4j")
|
store = GraphStore(backend="neo4j")
|
||||||
store.add_nodes([{"id": "acme", "type": "Organization", "properties": {"name": "Acme"}}])
|
store.add_nodes(entities)
|
||||||
store.add_edges([{"source": "alice", "target": "acme", "type": "works_for"}])
|
store.add_edges(relationships)
|
||||||
results = store.query("MATCH (n)-[r]->(m) RETURN n, r, m")
|
results = store.query("MATCH (n)-[r]->(m) RETURN n, r, m")
|
||||||
```
|
```
|
||||||
|
|
||||||
@@ -260,9 +246,9 @@ RDF triple-based storage with SPARQL query support.
|
|||||||
```python
|
```python
|
||||||
from semantica.triplet_store import TripletStore
|
from semantica.triplet_store import TripletStore
|
||||||
|
|
||||||
store = TripletStore(backend="oxigraph")
|
store = TripletStore(backend="blazegraph")
|
||||||
store.add_triplets(triplets) # list of Triplet objects (or add_triplet for one)
|
store.add_triplets(subject, predicate, obj)
|
||||||
results = store.execute_query("SELECT ?s ?p ?o WHERE { ?s ?p ?o }")
|
results = store.sparql("SELECT ?s ?p ?o WHERE { ?s ?p ?o }")
|
||||||
```
|
```
|
||||||
|
|
||||||
**Backends:** Oxigraph (embedded), Blazegraph, Apache Jena, RDF4J
|
**Backends:** Oxigraph (embedded), Blazegraph, Apache Jena, RDF4J
|
||||||
@@ -275,18 +261,15 @@ results = store.execute_query("SELECT ?s ?p ?o WHERE { ?s ?p ?o }")
|
|||||||
Detects, scores, and merges duplicate entities across sources.
|
Detects, scores, and merges duplicate entities across sources.
|
||||||
|
|
||||||
```python
|
```python
|
||||||
from semantica.deduplication import DuplicateDetector, EntityMerger
|
from semantica.deduplication import EntityResolver
|
||||||
|
|
||||||
detector = DuplicateDetector(similarity_threshold=0.85)
|
resolver = EntityResolver()
|
||||||
candidates = detector.detect_duplicates(entities)
|
merged = resolver.resolve(entities, strategy="semantic_v2")
|
||||||
|
|
||||||
merger = EntityMerger()
|
|
||||||
operations = merger.merge_duplicates(entities, strategy="keep_most_complete")
|
|
||||||
```
|
```
|
||||||
|
|
||||||
**v2 candidate-generation modes** (`blocking_v2`, `hybrid_v2`, `semantic_v2`) are up to 7x faster than v1.
|
**v2 strategies** (`blocking_v2`, `hybrid_v2`, `semantic_v2`) are up to 7x faster than v1.
|
||||||
|
|
||||||
**Components:** `DuplicateDetector`, `EntityMerger`, `ClusterBuilder`, `MergeStrategyManager`
|
**Components:** `EntityResolver`, `DuplicateDetector`, `EntityMerger`, `SimilarityCalculator`, `ClusterBuilder`
|
||||||
|
|
||||||
**`DuplicateDetector` options:** `max_results`, `top_k_per_entity`, `min_similarity`, `sort_by`
|
**`DuplicateDetector` options:** `max_results`, `top_k_per_entity`, `min_similarity`, `sort_by`
|
||||||
|
|
||||||
@@ -295,13 +278,14 @@ operations = merger.merge_duplicates(entities, strategy="keep_most_complete")
|
|||||||
Detects and resolves fact conflicts across overlapping knowledge sources.
|
Detects and resolves fact conflicts across overlapping knowledge sources.
|
||||||
|
|
||||||
```python
|
```python
|
||||||
from semantica.conflicts import ConflictDetector, ConflictResolver
|
from semantica.conflicts import ConflictDetector
|
||||||
|
|
||||||
conflicts = ConflictDetector().detect_conflicts(entities) # list of entity dicts
|
detector = ConflictDetector()
|
||||||
resolved = ConflictResolver().resolve_conflicts(conflicts, strategy="most_recent")
|
conflicts = detector.detect_conflicts(kg)
|
||||||
|
resolved = detector.resolve(conflicts, strategy="most_recent")
|
||||||
```
|
```
|
||||||
|
|
||||||
**Detection types:** value conflicts, type conflicts, relationship conflicts, temporal conflicts, logical conflicts
|
**Detection types:** value conflicts, type conflicts, temporal conflicts, logical conflicts
|
||||||
|
|
||||||
**Resolution strategies:** prefer most recent, prefer most reliable source, majority vote, flag for manual review
|
**Resolution strategies:** prefer most recent, prefer most reliable source, majority vote, flag for manual review
|
||||||
|
|
||||||
@@ -314,7 +298,6 @@ Agent context graphs, decision tracking, causal chains, and precedent search.
|
|||||||
|
|
||||||
```python
|
```python
|
||||||
from semantica.context import AgentContext, ContextGraph
|
from semantica.context import AgentContext, ContextGraph
|
||||||
from semantica.vector_store import VectorStore
|
|
||||||
|
|
||||||
context = AgentContext(
|
context = AgentContext(
|
||||||
vector_store=VectorStore(backend="faiss", dimension=768),
|
vector_store=VectorStore(backend="faiss", dimension=768),
|
||||||
@@ -345,7 +328,7 @@ W3C PROV-O compliant lineage tracking across all modules.
|
|||||||
from semantica.provenance import ProvenanceManager
|
from semantica.provenance import ProvenanceManager
|
||||||
|
|
||||||
manager = ProvenanceManager()
|
manager = ProvenanceManager()
|
||||||
manager.track_entity("entity_1", source="document.pdf", metadata={"type": "person"})
|
manager.track_entity("entity_1", "document.pdf", "person")
|
||||||
lineage = manager.get_lineage("entity_1")
|
lineage = manager.get_lineage("entity_1")
|
||||||
```
|
```
|
||||||
|
|
||||||
@@ -381,8 +364,8 @@ RDFExporter().export(graph, file_path="graph.ttl", format="turtle")
|
|||||||
# Analytics
|
# Analytics
|
||||||
ParquetExporter().export(graph, file_path="output/graph.parquet")
|
ParquetExporter().export(graph, file_path="output/graph.parquet")
|
||||||
|
|
||||||
# ArangoDB: writes AQL INSERT statements to the given path
|
# ArangoDB
|
||||||
ArangoAQLExporter().export(graph, file_path="graph.aql")
|
aql = ArangoAQLExporter().export(graph)
|
||||||
```
|
```
|
||||||
|
|
||||||
**Export formats:** RDF (Turtle, JSON-LD, N-Triples, XML), Parquet, ArangoDB AQL, CSV, OWL, Arrow, LPG, YAML, distance matrices
|
**Export formats:** RDF (Turtle, JSON-LD, N-Triples, XML), Parquet, ArangoDB AQL, CSV, OWL, Arrow, LPG, YAML, distance matrices
|
||||||
@@ -407,24 +390,16 @@ viz.visualize_network(graph, output="html", file_path="graph.html")
|
|||||||
Pipeline DSL with parallel workers, retry policies, and failure handling.
|
Pipeline DSL with parallel workers, retry policies, and failure handling.
|
||||||
|
|
||||||
```python
|
```python
|
||||||
from semantica.pipeline import PipelineBuilder, ExecutionEngine
|
from semantica.pipeline import Pipeline
|
||||||
from semantica.ingest import FileIngestor
|
|
||||||
from semantica.semantic_extract import NERExtractor
|
|
||||||
|
|
||||||
builder = PipelineBuilder()
|
pipeline = Pipeline()
|
||||||
|
pipeline.add_step("ingest", FileIngestor())
|
||||||
# Each step type dispatches to a handler you register (or supply explicitly)
|
pipeline.add_step("extract", NERExtractor())
|
||||||
builder.register_step_handler("ingest", lambda data, **c: FileIngestor().ingest(c["source"]))
|
pipeline.add_step("build", GraphBuilder())
|
||||||
builder.register_step_handler("extract", lambda docs, **c: NERExtractor(method="pattern").extract(docs[0].text))
|
result = pipeline.run("data/")
|
||||||
|
|
||||||
builder.add_step("ingest", step_type="ingest", source="data/")
|
|
||||||
builder.add_step("extract", step_type="extract")
|
|
||||||
|
|
||||||
pipeline = builder.connect_steps("ingest", "extract").build(name="docs_to_entities")
|
|
||||||
result = ExecutionEngine().execute_pipeline(pipeline)
|
|
||||||
```
|
```
|
||||||
|
|
||||||
**Components:** `PipelineBuilder`, `Pipeline`, `ExecutionEngine`, `FailureHandler`, `PipelineValidator`, `ParallelismManager`, `ResourceScheduler`
|
**Components:** `Pipeline`, `PipelineBuilder`, `ExecutionEngine`, `FailureHandler`, `PipelineValidator`, `ParallelismManager`, `ResourceScheduler`
|
||||||
|
|
||||||
### Explorer
|
### Explorer
|
||||||
|
|
||||||
@@ -453,7 +428,7 @@ llm = OpenAI(model="gpt-4o", api_key=os.getenv("OPENAI_API_KEY"))
|
|||||||
llm = LiteLLM(model="anthropic/claude-opus-4-7", api_key=os.getenv("ANTHROPIC_API_KEY"))
|
llm = LiteLLM(model="anthropic/claude-opus-4-7", api_key=os.getenv("ANTHROPIC_API_KEY"))
|
||||||
```
|
```
|
||||||
|
|
||||||
**Supported providers:** OpenAI, Anthropic, Google Gemini, Groq, Ollama, DeepSeek, Novita AI, HuggingFace, plus LiteLLM (100+ models via one interface)
|
**Supported providers:** OpenAI, Anthropic, Google Gemini, Groq, Ollama, DeepSeek, Novita AI, LiteLLM (20+ models via one interface)
|
||||||
|
|
||||||
### MCP Server
|
### MCP Server
|
||||||
|
|
||||||
@@ -463,50 +438,51 @@ Exposes Semantica as an MCP stdio server for IDE and agent integrations.
|
|||||||
python -m semantica.mcp_server
|
python -m semantica.mcp_server
|
||||||
```
|
```
|
||||||
|
|
||||||
**Integrations:** Claude Desktop, VS Code, Cursor, Windsurf, Cline. 15 MCP tools are exposed.
|
**Integrations:** Claude Desktop, VS Code, Cursor, Windsurf, Cline: 15 MCP tools exposed
|
||||||
|
|
||||||
### Seed
|
### Seed
|
||||||
|
|
||||||
Bootstrap knowledge graphs from verified structured sources: fixed-point reference data, controlled vocabularies, and domain anchors.
|
Bootstrap knowledge graphs from verified structured sources: fixed-point reference data, controlled vocabularies, and domain anchors.
|
||||||
|
|
||||||
```python
|
```python
|
||||||
from semantica.seed import SeedDataManager
|
from semantica.seed import SeedManager
|
||||||
|
|
||||||
seed = SeedDataManager()
|
seed = SeedManager()
|
||||||
|
seed.populate(kg, dataset="companies", count=100)
|
||||||
|
|
||||||
# Load trusted reference data from CSV / JSON / a database / an API
|
# Load domain seeds from file or built-in datasets
|
||||||
seed_data = seed.load_from_csv("seed_data/industries.csv", entity_type="Industry")
|
seed.load_from_file("seed_data/industries.json")
|
||||||
|
seed.inject(kg) # merges seed nodes without duplicating existing entities
|
||||||
# Merge seed data with extraction output (seed values win on conflict by default)
|
|
||||||
combined = seed.integrate_with_extracted(
|
|
||||||
{"entities": seed_data, "relationships": []},
|
|
||||||
{"entities": extracted_entities, "relationships": extracted_relationships},
|
|
||||||
merge_strategy="seed_first",
|
|
||||||
)
|
|
||||||
```
|
```
|
||||||
|
|
||||||
**Use cases:** anchoring extraction with known entities, pre-populating ontology classes, deterministic test graph generation.
|
**Use cases:** anchoring extraction with known entities, pre-populating ontology classes, deterministic test graph generation.
|
||||||
|
|
||||||
### Evals
|
### Evals
|
||||||
|
|
||||||
Scores decision-intelligence outputs (decision records, audit trails, reasoning
|
Evaluation framework for measuring KG quality, extraction accuracy, and pipeline performance.
|
||||||
text) with a registry of deterministic and model-backed evaluators plus a small
|
|
||||||
run harness.
|
|
||||||
|
|
||||||
```python
|
```python
|
||||||
from semantica.evals import evaluate, list_evaluators
|
from semantica.evals import KGEvaluator, ExtractionEvaluator, PipelineEvaluator, RegressionTracker
|
||||||
|
|
||||||
list_evaluators()
|
# KG quality
|
||||||
# ['decision_scores', 'exact_match', 'keyword_check', 'length_range',
|
report = KGEvaluator().evaluate(kg, ontology=ontology)
|
||||||
# 'levenshtein', 'llm_as_judge', 'numeric_range', 'regex_match', 'rouge',
|
print(f"Completeness: {report.completeness:.2%} Consistency: {report.consistency:.2%}")
|
||||||
# 'temporal_range']
|
|
||||||
|
|
||||||
cases = [("apple", "aple"), ("night", "nacht")]
|
# Extraction accuracy
|
||||||
summary = evaluate(cases, evaluators=["levenshtein"])
|
report = ExtractionEvaluator().evaluate_ner(predictions=extracted, gold_standard=annotated)
|
||||||
print(summary.total, summary.passed, summary.pass_rate)
|
print(f"Precision: {report.precision:.3f} Recall: {report.recall:.3f} F1: {report.f1:.3f}")
|
||||||
|
|
||||||
|
# Pipeline throughput and latency
|
||||||
|
metrics = PipelineEvaluator().benchmark(pipeline, data="data/", bench_runs=5)
|
||||||
|
print(f"Throughput: {metrics.docs_per_second:.1f} docs/sec")
|
||||||
|
|
||||||
|
# Regression tracking across runs
|
||||||
|
tracker = RegressionTracker(db_path="eval_history.db")
|
||||||
|
run_id = tracker.record_run(pipeline_version="v1.2.0", metrics=metrics)
|
||||||
|
diff = tracker.compare(run_id, baseline_run_id="run_abc123")
|
||||||
```
|
```
|
||||||
|
|
||||||
**Public API:** `evaluate(cases, evaluators, config=None)`, `list_evaluators()`, `get_evaluator(name)`, and the `EvalMetric` / `CaseResult` / `EvalSummary` result types. See the [Evals reference](/reference/evals).
|
**Components:** `KGEvaluator`, `ExtractionEvaluator`, `PipelineEvaluator`, `RegressionTracker`
|
||||||
|
|
||||||
### Core
|
### Core
|
||||||
|
|
||||||
@@ -515,20 +491,20 @@ Base classes, shared data models, and the plugin registry used across all module
|
|||||||
```python
|
```python
|
||||||
from semantica.core import Semantica, PluginRegistry, ConfigManager
|
from semantica.core import Semantica, PluginRegistry, ConfigManager
|
||||||
|
|
||||||
# ConfigManager loads a Config; Config.get() does dotted lookups
|
# Top-level orchestrator
|
||||||
config = ConfigManager().load_from_file("config.yaml")
|
sem = Semantica(config_path="config.yaml")
|
||||||
batch = config.get("processing.batch_size", default=32)
|
|
||||||
|
|
||||||
# Top-level orchestrator: pass the Config object (or a dict), not a path
|
|
||||||
sem = Semantica(config=config)
|
|
||||||
sem.initialize()
|
sem.initialize()
|
||||||
|
|
||||||
# Plugin registry: register custom components under a name
|
# Plugin registry: register custom components
|
||||||
registry = PluginRegistry()
|
registry = PluginRegistry()
|
||||||
registry.register_plugin("my_ingestor", MyCustomIngestor, version="1.0.0")
|
registry.register("my_ingestor", MyCustomIngestor)
|
||||||
|
|
||||||
|
# Config management
|
||||||
|
config = ConfigManager(config_path="config.yaml")
|
||||||
|
batch = config.get("processing.batch_size", default=32)
|
||||||
```
|
```
|
||||||
|
|
||||||
**Components:** `Semantica`, `PluginRegistry`, `ConfigManager`, `Config`, `LifecycleManager`, `HealthStatus`, `MethodRegistry`
|
**Components:** `Semantica`, `PluginRegistry`, `ConfigManager`, `LifecycleManager`, `HealthMonitor`, `Config`
|
||||||
|
|
||||||
### Utils
|
### Utils
|
||||||
|
|
||||||
@@ -556,13 +532,11 @@ from semantica.semantic_extract import NERExtractor, RelationExtractor
|
|||||||
from semantica.kg import GraphBuilder
|
from semantica.kg import GraphBuilder
|
||||||
|
|
||||||
sources = FileIngestor().ingest("data/")
|
sources = FileIngestor().ingest("data/")
|
||||||
text = DocumentParser().parse(sources[0].path)["full_text"]
|
parsed = DocumentParser().parse(sources[0])
|
||||||
ner = NERExtractor(method="llm", provider="groq", llm_model="llama-3.3-70b-versatile")
|
entities = NERExtractor(method="llm", llm_provider=llm).extract(parsed)
|
||||||
rel = RelationExtractor(method="llm", provider="groq", llm_model="llama-3.3-70b-versatile")
|
relationships = RelationExtractor(method="llm", llm_provider=llm).extract(parsed, entities=entities)
|
||||||
entities = ner.extract(text)
|
|
||||||
relationships = rel.extract(text, entities=entities)
|
|
||||||
graph = GraphBuilder(merge_entities=True).build(
|
graph = GraphBuilder(merge_entities=True).build(
|
||||||
{"entities": entities, "relationships": relationships}
|
entities=entities, relationships=relationships
|
||||||
)
|
)
|
||||||
```
|
```
|
||||||
|
|
||||||
@@ -581,20 +555,16 @@ from semantica.vector_store import VectorStore
|
|||||||
context = AgentContext(
|
context = AgentContext(
|
||||||
vector_store=VectorStore(backend="faiss", dimension=768),
|
vector_store=VectorStore(backend="faiss", dimension=768),
|
||||||
knowledge_graph=ContextGraph(advanced_analytics=True),
|
knowledge_graph=ContextGraph(advanced_analytics=True),
|
||||||
graph_expansion=True,
|
|
||||||
)
|
)
|
||||||
|
context.load_graph("company_kg.json")
|
||||||
|
|
||||||
# store() extracts entities and populates the graph + vector index
|
result = context.query(
|
||||||
context.store([{"content": "Steve Wozniak co-founded Apple with Steve Jobs."}])
|
|
||||||
|
|
||||||
# retrieve() blends vector similarity with multi-hop graph traversal
|
|
||||||
results = context.retrieve(
|
|
||||||
"What companies did Apple alumni found?",
|
"What companies did Apple alumni found?",
|
||||||
use_graph=True,
|
mode="graphrag",
|
||||||
expand_graph=True,
|
reasoning=True,
|
||||||
)
|
)
|
||||||
for r in results:
|
for claim in result.claims:
|
||||||
print(f"[{r['score']:.3f}] {r['content']} (source: {r['source']})")
|
print(f"{claim.text} → {claim.source_node}")
|
||||||
```
|
```
|
||||||
|
|
||||||
**Best for:** question-answering systems, RAG with source attribution, research assistants
|
**Best for:** question-answering systems, RAG with source attribution, research assistants
|
||||||
@@ -636,22 +606,18 @@ precedents = context.find_precedents("model selection", limit=5)
|
|||||||
|
|
||||||
```python
|
```python
|
||||||
from semantica.ingest import FileIngestor
|
from semantica.ingest import FileIngestor
|
||||||
from semantica.parse import DocumentParser
|
|
||||||
from semantica.semantic_extract import NERExtractor
|
from semantica.semantic_extract import NERExtractor
|
||||||
from semantica.kg import GraphBuilder
|
from semantica.kg import GraphBuilder
|
||||||
from semantica.provenance import ProvenanceManager
|
from semantica.provenance import ProvenanceManager
|
||||||
from semantica.export import RDFExporter
|
from semantica.export import RDFExporter
|
||||||
|
|
||||||
sources = FileIngestor().ingest("records/")
|
sources = FileIngestor().ingest("records/")
|
||||||
ner = NERExtractor(method="llm", provider="groq", llm_model="llama-3.3-70b-versatile")
|
entities = NERExtractor(method="llm", llm_provider=llm).extract(sources)
|
||||||
entities = ner.extract(DocumentParser().parse(sources[0].path)["full_text"])
|
graph = GraphBuilder(merge_entities=True).build(entities=entities, relationships=[])
|
||||||
graph = GraphBuilder(merge_entities=True).build({"entities": entities, "relationships": []})
|
|
||||||
|
|
||||||
prov = ProvenanceManager()
|
prov = ProvenanceManager()
|
||||||
prov.track_entity("entity_id", source="records/filing.pdf", metadata={"extractor": "llm"})
|
lineage = prov.get_entity_lineage("entity_id")
|
||||||
lineage = prov.get_lineage("entity_id")
|
|
||||||
|
|
||||||
RDFExporter().export(graph, file_path="audit.ttl", format="turtle")
|
RDFExporter(include_provenance=True).export(graph, file_path="audit.ttl", format="turtle")
|
||||||
```
|
```
|
||||||
|
|
||||||
**Best for:** HIPAA, SOX, GDPR, FDA 21 CFR Part 11 deployments
|
**Best for:** HIPAA, SOX, GDPR, FDA 21 CFR Part 11 deployments
|
||||||
@@ -666,25 +632,18 @@ RDFExporter().export(graph, file_path="audit.ttl", format="turtle")
|
|||||||
from semantica.ingest import WebIngestor
|
from semantica.ingest import WebIngestor
|
||||||
from semantica.normalize import TextNormalizer
|
from semantica.normalize import TextNormalizer
|
||||||
from semantica.semantic_extract import NERExtractor, RelationExtractor
|
from semantica.semantic_extract import NERExtractor, RelationExtractor
|
||||||
from semantica.graph_store import GraphStore
|
from semantica.graph_store import Neo4jStore
|
||||||
from semantica.kg import GraphBuilder
|
|
||||||
|
|
||||||
ingestor = WebIngestor()
|
pages = WebIngestor(max_depth=2).ingest("https://example.com")
|
||||||
normalizer = TextNormalizer()
|
normalizer = TextNormalizer()
|
||||||
ner = NERExtractor(method="pattern")
|
store = Neo4jStore(uri="bolt://localhost:7687", user="neo4j", password="password")
|
||||||
rel = RelationExtractor(method="pattern")
|
|
||||||
|
|
||||||
# The generic GraphStore wrapper exposes the add_nodes/add_edges interface
|
for page in pages:
|
||||||
# GraphBuilder persists through; a raw Neo4jStore does not
|
|
||||||
store = GraphStore(backend="neo4j", uri="bolt://localhost:7687", user="neo4j", password="password")
|
|
||||||
builder = GraphBuilder(merge_entities=True, graph_store=store)
|
|
||||||
|
|
||||||
for url in ["https://example.com/a", "https://example.com/b"]:
|
|
||||||
page = ingestor.ingest_url(url) # WebContent, has .text
|
|
||||||
text = normalizer.normalize_text(page.text)
|
text = normalizer.normalize_text(page.text)
|
||||||
entities = ner.extract(text)
|
entities = NERExtractor().extract(text)
|
||||||
relationships = rel.extract(text, entities=entities)
|
relationships = RelationExtractor().extract(text, entities=entities)
|
||||||
builder.build({"entities": entities, "relationships": relationships})
|
store.add_nodes(entities)
|
||||||
|
store.add_edges(relationships)
|
||||||
```
|
```
|
||||||
|
|
||||||
**Best for:** competitive intelligence, news monitoring, research aggregation
|
**Best for:** competitive intelligence, news monitoring, research aggregation
|
||||||
@@ -733,8 +692,8 @@ versioner.create_snapshot(kg, "2024-Q1", author="user@example.com", description=
|
|||||||
| [vector_store](/reference/vector_store) | Vector database | `VectorStore` |
|
| [vector_store](/reference/vector_store) | Vector database | `VectorStore` |
|
||||||
| [graph_store](/reference/graph_store) | Graph database | `GraphStore` |
|
| [graph_store](/reference/graph_store) | Graph database | `GraphStore` |
|
||||||
| [triplet_store](/reference/triplet_store) | RDF triple store | `TripletStore` |
|
| [triplet_store](/reference/triplet_store) | RDF triple store | `TripletStore` |
|
||||||
| [deduplication](/reference/deduplication) | Entity resolution | `DuplicateDetector`, `EntityMerger`, `ClusterBuilder`, `MergeStrategyManager` |
|
| [deduplication](/reference/deduplication) | Entity resolution | `EntityResolver`, `DuplicateDetector`, `ClusterBuilder`, `MergeStrategyManager` |
|
||||||
| [conflicts](/reference/conflicts) | Conflict resolution | `ConflictDetector`, `ConflictResolver`, `SourceTracker` |
|
| [conflicts](/reference/conflicts) | Conflict resolution | `ConflictDetector` |
|
||||||
| [context](/reference/context) | Agent context & decisions | `AgentContext`, `ContextGraph` |
|
| [context](/reference/context) | Agent context & decisions | `AgentContext`, `ContextGraph` |
|
||||||
| [provenance](/reference/provenance) | W3C PROV-O lineage | `ProvenanceManager` |
|
| [provenance](/reference/provenance) | W3C PROV-O lineage | `ProvenanceManager` |
|
||||||
| [change_management](/reference/change_management) | Version control | `TemporalVersionManager` |
|
| [change_management](/reference/change_management) | Version control | `TemporalVersionManager` |
|
||||||
@@ -744,11 +703,11 @@ versioner.create_snapshot(kg, "2024-Q1", author="user@example.com", description=
|
|||||||
| [explorer](/reference/explorer) | Knowledge Explorer UI | `semantica-explorer --graph <file>` |
|
| [explorer](/reference/explorer) | Knowledge Explorer UI | `semantica-explorer --graph <file>` |
|
||||||
| [llms](/reference/llms) | LLM providers | `Groq`, `OpenAI`, `create_provider` |
|
| [llms](/reference/llms) | LLM providers | `Groq`, `OpenAI`, `create_provider` |
|
||||||
| [mcp_server](/reference/mcp_server) | MCP stdio server | `python -m semantica.mcp_server` |
|
| [mcp_server](/reference/mcp_server) | MCP stdio server | `python -m semantica.mcp_server` |
|
||||||
| [seed](/reference/seed) | KG bootstrapping from structured sources | `SeedDataManager` |
|
| [seed](/reference/seed) | KG bootstrapping from structured sources | `SeedManager` |
|
||||||
| [evals](/reference/evals) | Decision-intelligence evaluation | `evaluate`, `list_evaluators`, `EvalSummary` |
|
| [evals](/reference/evals) | Quality evaluation | `KGEvaluator`, `ExtractionEvaluator`, `PipelineEvaluator`, `RegressionTracker` |
|
||||||
| [core](/reference/core) | Base classes & registry | `Semantica`, `ConfigManager`, `PluginRegistry`, `LifecycleManager` |
|
| [core](/reference/core) | Base classes & registry | `Semantica`, `ConfigManager`, `PluginRegistry`, `LifecycleManager` |
|
||||||
| [utils](/reference/utils) | Shared utilities | `helpers`, `validators` |
|
| [utils](/reference/utils) | Shared utilities | `helpers`, `validators` |
|
||||||
|
|
||||||
- [Getting Started](/getting-started): your first knowledge graph in 5 minutes.
|
- [Getting Started](/getting-started) — Your first knowledge graph in 5 minutes.
|
||||||
- [Cookbook](/cookbook): 40+ domain notebooks with real-world examples.
|
- [Cookbook](/cookbook) — 40+ domain notebooks with real-world examples.
|
||||||
- [API Reference](/reference/context): full technical documentation.
|
- [API Reference](/reference/context) — Full technical documentation.
|
||||||
|
|||||||
@@ -76,5 +76,5 @@ By contributing to Semantica, you agree that your contributions will be licensed
|
|||||||
|
|
||||||
## See Also
|
## See Also
|
||||||
|
|
||||||
- [Contributing](/contributing-guide): how to contribute to the project.
|
- [Contributing](/contributing-guide) — How to contribute to the project.
|
||||||
- [Citation](/citation): how to cite Semantica in research.
|
- [Citation](/citation) — How to cite Semantica in research.
|
||||||
|
|||||||
+13
-15
@@ -5,7 +5,7 @@ icon: "rocket"
|
|||||||
---
|
---
|
||||||
|
|
||||||
<Info>
|
<Info>
|
||||||
**v0.6.8**: cryptographically signed releases (SLSA provenance + Sigstore), real vector-store enumeration across FAISS/Qdrant/Weaviate/Milvus, and first-class Anthropic/Gemini/Ollama/DeepSeek/Novita LLM provider wrappers. <a href="https://github.com/semantica-agi/semantica/releases" style={{color:"#10B981",fontWeight:600,textDecoration:"none"}}>What's new →</a>
|
**v0.6.7** — first-class LangChain integration, SAP OData ingestor, human-editable Markdown persistence for `ContextGraph`, and a structured Action layer for the reasoning engine. <a href="https://github.com/semantica-agi/semantica/releases" style={{color:"#10B981",fontWeight:600,textDecoration:"none"}}>What's new →</a>
|
||||||
</Info>
|
</Info>
|
||||||
|
|
||||||
This guide walks you through the end-to-end pipeline for building your first knowledge graph. Start here after installation. An LLM API key is optional: pattern-based extraction works out of the box.
|
This guide walks you through the end-to-end pipeline for building your first knowledge graph. Start here after installation. An LLM API key is optional: pattern-based extraction works out of the box.
|
||||||
@@ -35,7 +35,7 @@ Verify:
|
|||||||
|
|
||||||
```bash
|
```bash
|
||||||
python -c "import semantica; print(semantica.__version__)"
|
python -c "import semantica; print(semantica.__version__)"
|
||||||
# 0.6.8
|
# 0.6.7
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
@@ -78,13 +78,11 @@ from semantica.parse import DocumentParser
|
|||||||
parser = DocumentParser()
|
parser = DocumentParser()
|
||||||
parsed = parser.parse(sources[0].path) # parse() takes a path string
|
parsed = parser.parse(sources[0].path) # parse() takes a path string
|
||||||
|
|
||||||
print(parsed["full_text"][:200]) # extracted text
|
print(parsed["text"][:200]) # extracted text
|
||||||
print(parsed["metadata"]) # document properties (fields vary by format)
|
print(parsed["metadata"]) # file_path, encoding, size, and format-specific keys
|
||||||
```
|
```
|
||||||
|
|
||||||
`parse()` returns a `dict`. `full_text` and `metadata` are present for every
|
`parse()` returns a `dict` with `text`, `full_text`, and `metadata` keys.
|
||||||
format; other keys depend on the parser (`pages` for PDF, `tables` and
|
|
||||||
`paragraphs` for DOCX, `tables` for `DoclingParser`).
|
|
||||||
|
|
||||||
<Tip>
|
<Tip>
|
||||||
For PDFs with tables, charts, or multi-column layouts, use `DoclingParser` (`pip install semantica[parse-docling]`): it applies advanced layout analysis and returns structured table data alongside text.
|
For PDFs with tables, charts, or multi-column layouts, use `DoclingParser` (`pip install semantica[parse-docling]`): it applies advanced layout analysis and returns structured table data alongside text.
|
||||||
@@ -109,7 +107,7 @@ Identify named entities and extract typed relationships between them.
|
|||||||
```python Pattern-based (fast, no API key)
|
```python Pattern-based (fast, no API key)
|
||||||
from semantica.semantic_extract import NERExtractor, RelationExtractor
|
from semantica.semantic_extract import NERExtractor, RelationExtractor
|
||||||
|
|
||||||
text = parsed["full_text"]
|
text = parsed["text"]
|
||||||
|
|
||||||
ner = NERExtractor(method="pattern")
|
ner = NERExtractor(method="pattern")
|
||||||
entities = ner.extract(text)
|
entities = ner.extract(text)
|
||||||
@@ -124,7 +122,7 @@ relationships = rel.extract(text, entities=entities)
|
|||||||
from semantica.semantic_extract import NERExtractor, RelationExtractor
|
from semantica.semantic_extract import NERExtractor, RelationExtractor
|
||||||
|
|
||||||
# Reads GROQ_API_KEY from the environment; provider/llm_model select the backend
|
# Reads GROQ_API_KEY from the environment; provider/llm_model select the backend
|
||||||
text = parsed["full_text"]
|
text = parsed["text"]
|
||||||
|
|
||||||
ner = NERExtractor(method="llm", provider="groq", llm_model="llama-3.3-70b-versatile")
|
ner = NERExtractor(method="llm", provider="groq", llm_model="llama-3.3-70b-versatile")
|
||||||
entities = ner.extract(text)
|
entities = ner.extract(text)
|
||||||
@@ -279,7 +277,7 @@ builder = GraphBuilder(merge_entities=True)
|
|||||||
|
|
||||||
all_entities, all_rels = [], []
|
all_entities, all_rels = [], []
|
||||||
for source in FileIngestor().ingest("data/reports/"):
|
for source in FileIngestor().ingest("data/reports/"):
|
||||||
text = parser.parse(source.path)["full_text"]
|
text = parser.parse(source.path)["text"]
|
||||||
entities = ner.extract(text)
|
entities = ner.extract(text)
|
||||||
rels = rel.extract(text, entities=entities)
|
rels = rel.extract(text, entities=entities)
|
||||||
all_entities.extend(entities)
|
all_entities.extend(entities)
|
||||||
@@ -415,7 +413,7 @@ store = GraphStore(backend="neo4j", uri="bolt://localhost:7687",
|
|||||||
builder = GraphBuilder(merge_entities=True, graph_store=store)
|
builder = GraphBuilder(merge_entities=True, graph_store=store)
|
||||||
|
|
||||||
for info in ingestor.scan_directory("data/reports/", recursive=True):
|
for info in ingestor.scan_directory("data/reports/", recursive=True):
|
||||||
text = parser.parse(info["path"])["full_text"] # one document loaded at a time
|
text = parser.parse(info["path"])["text"] # one document loaded at a time
|
||||||
entities = ner.extract(text)
|
entities = ner.extract(text)
|
||||||
rels = rel.extract(text, entities=entities)
|
rels = rel.extract(text, entities=entities)
|
||||||
builder.build({"entities": entities, "relationships": rels})
|
builder.build({"entities": entities, "relationships": rels})
|
||||||
@@ -454,7 +452,7 @@ pip install --upgrade semantica
|
|||||||
|
|
||||||
## Next Steps
|
## Next Steps
|
||||||
|
|
||||||
- [Core Concepts](/concepts): knowledge graphs, ontologies, and reasoning engines (the mental model behind Semantica).
|
- [Core Concepts](/concepts) — Knowledge graphs, ontologies, reasoning engines: the mental model behind Semantica.
|
||||||
- [Module Reference](/modules): every module explained with key classes and common chains.
|
- [Module Reference](/modules) — Every module explained with key classes and common chains.
|
||||||
- [API Reference](/reference/context): complete documentation for every module, class, and parameter.
|
- [API Reference](/reference/context) — Complete documentation for every module, class, and parameter.
|
||||||
- [Cookbook](/cookbook): 40+ interactive Jupyter notebooks with real-world datasets.
|
- [Cookbook](/cookbook) — 40+ interactive Jupyter notebooks with real-world datasets.
|
||||||
|
|||||||
@@ -350,7 +350,7 @@ for record in history:
|
|||||||
</Accordion>
|
</Accordion>
|
||||||
</AccordionGroup>
|
</AccordionGroup>
|
||||||
|
|
||||||
- [Provenance](/reference/provenance) — W3C PROV-O lineage tracking.
|
- [Provenance](provenance) — W3C PROV-O lineage tracking.
|
||||||
- [Knowledge Graph](/reference/kg) — The graph being versioned.
|
- [Knowledge Graph](/reference/kg) — The graph being versioned.
|
||||||
- [Export](/reference/export) — Export versioned snapshots.
|
- [Export](export) — Export versioned snapshots.
|
||||||
- [Conflicts](/reference/conflicts) — Detect conflicts introduced between versions.
|
- [Conflicts](/reference/conflicts) — Detect conflicts introduced between versions.
|
||||||
|
|||||||
@@ -317,7 +317,7 @@ chain = tracker.get_traceability_chain("apple_inc")
|
|||||||
</Warning>
|
</Warning>
|
||||||
|
|
||||||
<Tip>
|
<Tip>
|
||||||
**Combine with provenance.** The `SourceTracker` feeds directly into the [Provenance](/reference/provenance) module's audit trail. If you need to explain how a resolved value was chosen, provenance records give you the full chain.
|
**Combine with provenance.** The `SourceTracker` feeds directly into the [Provenance](provenance) module's audit trail. If you need to explain how a resolved value was chosen, provenance records give you the full chain.
|
||||||
</Tip>
|
</Tip>
|
||||||
|
|
||||||
## ConflictAnalyzer
|
## ConflictAnalyzer
|
||||||
@@ -450,7 +450,7 @@ class InvestigationStep:
|
|||||||
</Accordion>
|
</Accordion>
|
||||||
</AccordionGroup>
|
</AccordionGroup>
|
||||||
|
|
||||||
- [Deduplication](/reference/deduplication) — Resolve duplicate entities before conflict detection.
|
- [Deduplication](deduplication) — Resolve duplicate entities before conflict detection.
|
||||||
- [Ontology](/reference/ontology) — Logical conflicts use SHACL shapes and ontology axioms.
|
- [Ontology](ontology) — Logical conflicts use SHACL shapes and ontology axioms.
|
||||||
- [Provenance](/reference/provenance) — Track which source each conflicting fact came from.
|
- [Provenance](provenance) — Track which source each conflicting fact came from.
|
||||||
- [Knowledge Graph](/reference/kg) — The graph being checked for conflicts.
|
- [Knowledge Graph](/reference/kg) — The graph being checked for conflicts.
|
||||||
|
|||||||
+21
-21
@@ -30,28 +30,28 @@ icon: "brain"
|
|||||||
|
|
||||||
## What You Get
|
## What You Get
|
||||||
|
|
||||||
- **AgentContext**: memory, decision tracking, and graph-backed retrieval behind one API
|
- **AgentContext** — Memory, decision tracking, and graph-backed retrieval behind one API
|
||||||
- Conversation history and checkpoint diffing
|
- Conversation history and checkpoint diffing
|
||||||
- Persist and restore full context state to disk
|
- Persist and restore full context state to disk
|
||||||
- **ContextGraph**: thread-safe in-memory knowledge graph
|
- **ContextGraph** — Thread-safe in-memory knowledge graph
|
||||||
- PageRank, centrality, community detection, temporal validity
|
- PageRank, centrality, community detection, temporal validity
|
||||||
- Cross-graph navigation and link traversal
|
- Cross-graph navigation and link traversal
|
||||||
- **AgentMemory**: embedding-backed memory with retention policy
|
- **AgentMemory** — Embedding-backed memory with retention policy
|
||||||
- LRU eviction at configurable `max_memory_size`
|
- LRU eviction at configurable `max_memory_size`
|
||||||
- Per-conversation history isolation
|
- Per-conversation history isolation
|
||||||
- **DecisionRecorder**: records decisions with causal chains and confidence scores
|
- **DecisionRecorder** — Records decisions with causal chains and confidence scores
|
||||||
- Temporal validity windows (`valid_from` / `valid_until`)
|
- Temporal validity windows (`valid_from` / `valid_until`)
|
||||||
- Cross-system context capture on every decision
|
- Cross-system context capture on every decision
|
||||||
- **PolicyEngine**: versioned policy storage in the knowledge graph
|
- **PolicyEngine** — Versioned policy storage in the knowledge graph
|
||||||
- Compliance checking against recorded decisions
|
- Compliance checking against recorded decisions
|
||||||
- Policy exception tracking with approver audit trail
|
- Policy exception tracking with approver audit trail
|
||||||
- **EntityLinker**: maps entity text to stable URIs
|
- **EntityLinker** — Maps entity text to stable URIs
|
||||||
- Creates typed links between entity IDs
|
- Creates typed links between entity IDs
|
||||||
- Prevents "Apple", "Apple Inc.", "AAPL" becoming separate nodes
|
- Prevents "Apple", "Apple Inc.", "AAPL" becoming separate nodes
|
||||||
- **ContextRetriever**: fuses vector similarity, graph traversal, and agent memory
|
- **ContextRetriever** — Fuses vector similarity, graph traversal, and agent memory
|
||||||
- Richer context than pure vector search
|
- Richer context than pure vector search
|
||||||
- Configurable `hybrid_alpha` and expansion hops
|
- Configurable `hybrid_alpha` and expansion hops
|
||||||
- **CausalChainAnalyzer**: traces upstream causes and downstream effects of any decision
|
- **CausalChainAnalyzer** — Traces upstream causes and downstream effects of any decision
|
||||||
- Explainability paths with relationship types
|
- Explainability paths with relationship types
|
||||||
- Configurable depth and direction
|
- Configurable depth and direction
|
||||||
|
|
||||||
@@ -273,7 +273,7 @@ icon: "brain"
|
|||||||
</Tip>
|
</Tip>
|
||||||
|
|
||||||
<Tip>
|
<Tip>
|
||||||
**Persist your context between runs.** `VectorStore` does not auto-persist; passing `index_path=` to its constructor is a no-op. Call `context.save("agent_state/")` to write memory, the vector index, and the graph to disk, and `context.load("agent_state/")` on the next process to restore them. See the "Persist & Restore" tab under [Real-World Patterns](#real-world-patterns) below.
|
**Persist your context between runs.** `VectorStore` does not auto-persist — passing `index_path=` to its constructor is a no-op. Call `context.save("agent_state/")` to write memory, the vector index, and the graph to disk, and `context.load("agent_state/")` on the next process to restore them. See the "Persist & Restore" tab under [Real-World Patterns](#real-world-patterns) below.
|
||||||
</Tip>
|
</Tip>
|
||||||
|
|
||||||
### Memory Methods
|
### Memory Methods
|
||||||
@@ -449,7 +449,7 @@ print("Nodes: {}, Edges: {}".format(stats["node_count"], stats["edge_count"]))
|
|||||||
`ContextGraph` exposes a full Distance Intelligence API for exploring semantic neighborhoods and blending proximity into retrieval.
|
`ContextGraph` exposes a full Distance Intelligence API for exploring semantic neighborhoods and blending proximity into retrieval.
|
||||||
|
|
||||||
<Info>
|
<Info>
|
||||||
Full Distance Intelligence reference (distance matrices, API endpoints, embedding cache, Explorer UI) is covered in the dedicated [Distance Intelligence](/reference/distance) page. This section documents the context-layer API.
|
Full Distance Intelligence reference — distance matrices, API endpoints, embedding cache, Explorer UI — is covered in the dedicated [Distance Intelligence](/reference/distance) page. This section documents the context-layer API.
|
||||||
</Info>
|
</Info>
|
||||||
|
|
||||||
### Neighbors with Distance Metadata
|
### Neighbors with Distance Metadata
|
||||||
@@ -480,7 +480,7 @@ for n in neighbors:
|
|||||||
| Added field | Type | Description |
|
| Added field | Type | Description |
|
||||||
| :---------- | :---- | :----------- |
|
| :---------- | :---- | :----------- |
|
||||||
| `distance_band` | `str` | `"direct"` (1 hop) / `"near"` (2) / `"mid-range"` (3–4) / `"distant"` (5+) |
|
| `distance_band` | `str` | `"direct"` (1 hop) / `"near"` (2) / `"mid-range"` (3–4) / `"distant"` (5+) |
|
||||||
| `confidence_decay` | `float` | `edge_weight ^ hop_count`; decays with each hop |
|
| `confidence_decay` | `float` | `edge_weight ^ hop_count` — decays with each hop |
|
||||||
| `path_to_anchor` | `List[str]` | Shortest path from anchor node to this neighbor |
|
| `path_to_anchor` | `List[str]` | Shortest path from anchor node to this neighbor |
|
||||||
| `hop_count` | `int` | BFS depth from anchor |
|
| `hop_count` | `int` | BFS depth from anchor |
|
||||||
|
|
||||||
@@ -659,7 +659,7 @@ if not receipt.complete:
|
|||||||
```
|
```
|
||||||
|
|
||||||
<Warning>
|
<Warning>
|
||||||
Check the receipt. The call returning is not proof the data is gone. FAISS,
|
Check the receipt — the call returning is not proof the data is gone. FAISS,
|
||||||
Milvus, and Weaviate expose no delete method, so erasure cannot be completed on
|
Milvus, and Weaviate expose no delete method, so erasure cannot be completed on
|
||||||
those backends today; the receipt reports `unsupported` rather than a success it
|
those backends today; the receipt reports `unsupported` rather than a success it
|
||||||
did not achieve.
|
did not achieve.
|
||||||
@@ -687,9 +687,9 @@ At least one store is required; a store that is not supplied reports
|
|||||||
|
|
||||||
| Status | Meaning |
|
| Status | Meaning |
|
||||||
| :--- | :--- |
|
| :--- | :--- |
|
||||||
| `erased` | Reached, data removed. On the vectors leg this means the store accepted the delete for the ids given; backends offer no portable existence check, so it is not a count of embeddings that were really there |
|
| `erased` | Reached, data removed. On the vectors leg this means the store accepted the delete for the ids given — backends offer no portable existence check, so it is not a count of embeddings that were really there |
|
||||||
| `not_found` | Reached, held nothing for this entity |
|
| `not_found` | Reached, held nothing for this entity |
|
||||||
| `not_configured` | No such store was bound: normal, not a failure |
|
| `not_configured` | No such store was bound — normal, not a failure |
|
||||||
| `unsupported` | The store cannot delete at all; retrying will not help |
|
| `unsupported` | The store cannot delete at all; retrying will not help |
|
||||||
| `failed` | The store was reached and the deletion did not succeed |
|
| `failed` | The store was reached and the deletion did not succeed |
|
||||||
|
|
||||||
@@ -721,7 +721,7 @@ receipt.to_dict()
|
|||||||
# }
|
# }
|
||||||
```
|
```
|
||||||
|
|
||||||
Erasure runs outward-in: vectors, then memory, then the graph. The tombstone is
|
Erasure runs outward-in — vectors, then memory, then the graph. The tombstone is
|
||||||
the durable attestation that an erasure happened, so it is written last: a crash
|
the durable attestation that an erasure happened, so it is written last: a crash
|
||||||
mid-cascade leaves the node present and the receipt incomplete, rather than a
|
mid-cascade leaves the node present and the receipt incomplete, rather than a
|
||||||
tombstone claiming more than actually happened. A store that raises is recorded
|
tombstone claiming more than actually happened. A store that raises is recorded
|
||||||
@@ -1087,10 +1087,10 @@ class EntityLink:
|
|||||||
</Tab>
|
</Tab>
|
||||||
</Tabs>
|
</Tabs>
|
||||||
|
|
||||||
- [Vector Store](/reference/vector_store): embedding storage backend for memory retrieval.
|
- [Vector Store](/reference/vector_store) — Embedding storage backend for memory retrieval.
|
||||||
- [Knowledge Graph](/reference/kg): graph algorithms and analytics used inside ContextGraph.
|
- [Knowledge Graph](/reference/kg) — Graph algorithms and analytics used inside ContextGraph.
|
||||||
- [Reasoning](/guides/reasoning): logical inference layered on top of context.
|
- [Reasoning](reasoning) — Logical inference layered on top of context.
|
||||||
- [Provenance](/guides/provenance): W3C PROV-O lineage for every stored fact.
|
- [Provenance](provenance) — W3C PROV-O lineage for every stored fact.
|
||||||
|
|
||||||
- [Context Module](https://github.com/semantica-agi/semantica/blob/main/cookbook/introduction/19_Context_Module.ipynb): memory and decision tracking · Intermediate
|
- [Context Module](https://github.com/semantica-agi/semantica/blob/main/cookbook/introduction/19_Context_Module.ipynb) — Memory and decision tracking · Intermediate
|
||||||
- [Advanced Context Engineering](https://github.com/semantica-agi/semantica/blob/main/cookbook/advanced/11_Advanced_Context_Engineering.ipynb): production FAISS + Neo4j setup · Advanced
|
- [Advanced Context Engineering](https://github.com/semantica-agi/semantica/blob/main/cookbook/advanced/11_Advanced_Context_Engineering.ipynb) — Production FAISS + Neo4j setup · Advanced
|
||||||
|
|||||||
@@ -226,7 +226,7 @@ result = build_knowledge_base(sources=["doc.pdf"], method="fast")
|
|||||||
Use `Semantica` and `LifecycleManager` only when building a long-running application (e.g. a FastAPI service) that needs ordered startup, health checks, and graceful shutdown. For scripts and notebooks, use individual modules directly.
|
Use `Semantica` and `LifecycleManager` only when building a long-running application (e.g. a FastAPI service) that needs ordered startup, health checks, and graceful shutdown. For scripts and notebooks, use individual modules directly.
|
||||||
</Tip>
|
</Tip>
|
||||||
|
|
||||||
- [Pipeline](/reference/pipeline) — Pipeline execution and step orchestration.
|
- [Pipeline](pipeline) — Pipeline execution and step orchestration.
|
||||||
- [Utils](/reference/utils) — Shared utilities used by Core internally.
|
- [Utils](/reference/utils) — Shared utilities used by Core internally.
|
||||||
- [Getting Started](../getting-started) — Learn the basics before using Core.
|
- [Getting Started](../getting-started) — Learn the basics before using Core.
|
||||||
- [LLMs](/reference/llms) — Configure LLM providers via ConfigManager.
|
- [LLMs](/reference/llms) — Configure LLM providers via ConfigManager.
|
||||||
|
|||||||
@@ -440,4 +440,4 @@ result = calculate_similarity(entity_a, entity_b, method="drug_name")
|
|||||||
- [Conflicts](/reference/conflicts) — Detect value conflicts between non-duplicate entities.
|
- [Conflicts](/reference/conflicts) — Detect value conflicts between non-duplicate entities.
|
||||||
- [Knowledge Graph](/reference/kg) — GraphBuilder uses deduplication during construction.
|
- [Knowledge Graph](/reference/kg) — GraphBuilder uses deduplication during construction.
|
||||||
- [Normalize](/reference/normalize) — Normalize entity names before deduplication.
|
- [Normalize](/reference/normalize) — Normalize entity names before deduplication.
|
||||||
- [Provenance](/reference/provenance) — Track merged entity lineage.
|
- [Provenance](provenance) — Track merged entity lineage.
|
||||||
|
|||||||
@@ -609,5 +609,5 @@ The Knowledge Explorer embeds Distance Intelligence directly in the browser dash
|
|||||||
|
|
||||||
- [Context Module](/reference/context) — `ContextGraph.get_neighbors()` and proximity-blended retrieval.
|
- [Context Module](/reference/context) — `ContextGraph.get_neighbors()` and proximity-blended retrieval.
|
||||||
- [Knowledge Graph Module](/reference/kg) — `NodeEmbedder`, `SimilarityCalculator`, and graph analytics.
|
- [Knowledge Graph Module](/reference/kg) — `NodeEmbedder`, `SimilarityCalculator`, and graph analytics.
|
||||||
- [Visualization](/reference/visualization) — Programmatic distance heatmaps and ego-mode graph renders.
|
- [Visualization](visualization) — Programmatic distance heatmaps and ego-mode graph renders.
|
||||||
- [Explorer](/reference/explorer) — Knowledge Explorer with built-in Distance Intelligence dashboard.
|
- [Explorer](/reference/explorer) — Knowledge Explorer with built-in Distance Intelligence dashboard.
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
---
|
---
|
||||||
title: "Embeddings Module"
|
title: "Embeddings Module"
|
||||||
description: "Text and graph embedding generation (FastEmbed, Sentence-Transformers, OpenAI, BGE) with pooling strategies and a provider-agnostic API."
|
description: "Text and graph embedding generation: FastEmbed, Sentence-Transformers, OpenAI, BGE: with pooling strategies and provider-agnostic API."
|
||||||
icon: "vector-square"
|
icon: "vector-square"
|
||||||
---
|
---
|
||||||
|
|
||||||
@@ -41,12 +41,12 @@ Semantica uses embeddings for:
|
|||||||
|
|
||||||
## What You Get
|
## What You Get
|
||||||
|
|
||||||
- **EmbeddingGenerator**: provider-agnostic main entry point that handles batching automatically across all backends.
|
- **EmbeddingGenerator** — Main entry point: provider-agnostic, handles batching automatically across all backends.
|
||||||
- **TextEmbedder**: text-specific embedder with automatic batching and progress tracking. Default method is FastEmbed.
|
- **TextEmbedder** — Text-specific with automatic batching and progress tracking. Default method is FastEmbed.
|
||||||
- **GraphEmbeddingManager**: node and edge embeddings for graph databases (Neo4j, NetworkX, FalkorDB).
|
- **GraphEmbeddingManager** — Node and edge embeddings for graph databases: Neo4j, NetworkX, FalkorDB.
|
||||||
- **VectorEmbeddingManager**: prepare, normalize, and format embeddings for FAISS, Weaviate, Qdrant, and Milvus.
|
- **VectorEmbeddingManager** — Prepare, normalize, and format embeddings for FAISS, Weaviate, Qdrant, and Milvus.
|
||||||
- **Provider Stores**: `OpenAIStore`, `BGEStore`, `FastEmbedStore`, and `ProviderStoreFactory`.
|
- **Provider Stores** — `OpenAIStore`, `BGEStore`, `FastEmbedStore`, and `ProviderStoreFactory`.
|
||||||
- **Pooling Strategies**: Mean, Max, CLS, Attention, and Hierarchical control token-to-vector aggregation.
|
- **Pooling Strategies** — Mean, Max, CLS, Attention, and Hierarchical: control token-to-vector aggregation.
|
||||||
|
|
||||||
## Provider Setup
|
## Provider Setup
|
||||||
|
|
||||||
@@ -71,7 +71,7 @@ Semantica uses embeddings for:
|
|||||||
</Check>
|
</Check>
|
||||||
|
|
||||||
<Warning>
|
<Warning>
|
||||||
**FastEmbed ignores the `device` parameter.** FastEmbed uses ONNX Runtime and manages its own execution providers; passing `device="cuda"` has no effect. Switch to `method="sentence_transformers"` if you need explicit GPU control.
|
**FastEmbed ignores the `device` parameter.** FastEmbed uses ONNX Runtime and manages its own execution providers: passing `device="cuda"` has no effect. Switch to `method="sentence_transformers"` if you need explicit GPU control.
|
||||||
</Warning>
|
</Warning>
|
||||||
</Tab>
|
</Tab>
|
||||||
<Tab title="Sentence-Transformers">
|
<Tab title="Sentence-Transformers">
|
||||||
@@ -153,7 +153,7 @@ providers = check_available_providers()
|
|||||||
|
|
||||||
## Getting Started
|
## Getting Started
|
||||||
|
|
||||||
`EmbeddingGenerator` is the fastest path to embeddings. The default method is FastEmbed (ONNX, no GPU needed):
|
`EmbeddingGenerator` is the fastest path to embeddings: the default method is FastEmbed (ONNX, no GPU needed):
|
||||||
|
|
||||||
```python
|
```python
|
||||||
from semantica.embeddings import EmbeddingGenerator
|
from semantica.embeddings import EmbeddingGenerator
|
||||||
@@ -173,7 +173,7 @@ print(f"Similarity: {score:.3f}")
|
|||||||
```
|
```
|
||||||
|
|
||||||
<Tip>
|
<Tip>
|
||||||
**Always use the same model for indexing and querying.** Vectors from different models are not comparable; they live in different vector spaces. Switching models requires re-embedding your entire corpus.
|
**Always use the same model for indexing and querying.** Vectors from different models are not comparable: they live in different vector spaces. Switching models requires re-embedding your entire corpus.
|
||||||
</Tip>
|
</Tip>
|
||||||
|
|
||||||
To switch provider after construction:
|
To switch provider after construction:
|
||||||
@@ -258,7 +258,7 @@ generator.set_text_model("sentence_transformers", "BAAI/bge-large-en-v1.5")
|
|||||||
similarity = generator.compare_embeddings(embeddings[0], embeddings[1])
|
similarity = generator.compare_embeddings(embeddings[0], embeddings[1])
|
||||||
```
|
```
|
||||||
|
|
||||||
**Best for:** CPU-only production and lowest latency without GPU. The default works out of the box.
|
**Best for:** CPU-only production, lowest latency without GPU. Default: works out of the box.
|
||||||
</Tab>
|
</Tab>
|
||||||
<Tab title="Sentence-Transformers">
|
<Tab title="Sentence-Transformers">
|
||||||
```python
|
```python
|
||||||
@@ -390,7 +390,7 @@ store = ProviderStoreFactory.create(provider="bge", model_name="BAAI/bge-large-e
|
|||||||
|
|
||||||
## Pooling Strategies
|
## Pooling Strategies
|
||||||
|
|
||||||
Pooling aggregates a set of embeddings into a single vector. Useful when you have multiple chunk embeddings to combine:
|
Pooling aggregates a set of embeddings into a single vector: useful when you have multiple chunk embeddings to combine:
|
||||||
|
|
||||||
<Tabs>
|
<Tabs>
|
||||||
<Tab title="MeanPooling (default)">
|
<Tab title="MeanPooling (default)">
|
||||||
@@ -401,7 +401,7 @@ Pooling aggregates a set of embeddings into a single vector. Useful when you hav
|
|||||||
pooled = pooler.pool(token_embeddings) # shape: (hidden_dim,)
|
pooled = pooler.pool(token_embeddings) # shape: (hidden_dim,)
|
||||||
```
|
```
|
||||||
|
|
||||||
**Best for:** retrieval, semantic search, and clustering. Averages all contributions.
|
**Best for:** retrieval, semantic search, and clustering: averages all contributions.
|
||||||
</Tab>
|
</Tab>
|
||||||
<Tab title="MaxPooling">
|
<Tab title="MaxPooling">
|
||||||
```python
|
```python
|
||||||
@@ -411,7 +411,7 @@ Pooling aggregates a set of embeddings into a single vector. Useful when you hav
|
|||||||
pooled = pooler.pool(token_embeddings)
|
pooled = pooler.pool(token_embeddings)
|
||||||
```
|
```
|
||||||
|
|
||||||
**Best for:** capturing the presence of any feature. Takes the max activation per dimension.
|
**Best for:** capturing the presence of any feature: takes the max activation per dimension.
|
||||||
</Tab>
|
</Tab>
|
||||||
<Tab title="CLSPooling">
|
<Tab title="CLSPooling">
|
||||||
```python
|
```python
|
||||||
@@ -432,7 +432,7 @@ Pooling aggregates a set of embeddings into a single vector. Useful when you hav
|
|||||||
pooled = pooler.pool(token_embeddings, chunk_size=10)
|
pooled = pooler.pool(token_embeddings, chunk_size=10)
|
||||||
```
|
```
|
||||||
|
|
||||||
**Best for:** long documents (chunk-level mean pooling, then global mean pooling across chunks).
|
**Best for:** long documents: chunk-level mean pooling, then global mean pooling across chunks.
|
||||||
</Tab>
|
</Tab>
|
||||||
<Tab title="Strategy Comparison">
|
<Tab title="Strategy Comparison">
|
||||||
|
|
||||||
@@ -619,7 +619,7 @@ providers = check_available_providers()
|
|||||||
# → {"sentence_transformers": True, "fastembed": True, "openai": False}
|
# → {"sentence_transformers": True, "fastembed": True, "openai": False}
|
||||||
```
|
```
|
||||||
|
|
||||||
- [Vector Store](/reference/vector_store): store and search the generated embeddings.
|
- [Vector Store](/reference/vector_store) — Store and search the generated embeddings.
|
||||||
- [Split](/reference/split): chunk text before embedding for better retrieval quality.
|
- [Split](/reference/split) — Chunk text before embedding for better retrieval quality.
|
||||||
- [KG Module](/reference/kg): Distance Intelligence uses graph embeddings for semantic neighbourhoods.
|
- [KG Module](/reference/kg) — Distance Intelligence uses graph embeddings for semantic neighbourhoods.
|
||||||
- [Deduplication](/reference/deduplication): semantic deduplication uses embedding distance for entity resolution.
|
- [Deduplication](deduplication) — Semantic deduplication uses embedding distance for entity resolution.
|
||||||
|
|||||||
@@ -404,6 +404,6 @@ Semantic neighborhood requires node embeddings stored in node properties (keys `
|
|||||||
Session state is in-memory only. Use `POST /api/export` to save a JSON snapshot before shutting down.
|
Session state is in-memory only. Use `POST /api/export` to save a JSON snapshot before shutting down.
|
||||||
|
|
||||||
- [Context](/reference/context) — Build and save the ContextGraph that Explorer loads.
|
- [Context](/reference/context) — Build and save the ContextGraph that Explorer loads.
|
||||||
- [Ontology](/reference/ontology) — Programmatic ontology management and SHACL generation.
|
- [Ontology](ontology) — Programmatic ontology management and SHACL generation.
|
||||||
- [Visualization](/reference/visualization) — Programmatic graph rendering without the Explorer server.
|
- [Visualization](visualization) — Programmatic graph rendering without the Explorer server.
|
||||||
- [Export](/reference/export) — Export to RDF, Parquet, and other formats without launching a server.
|
- [Export](export) — Export to RDF, Parquet, and other formats without launching a server.
|
||||||
|
|||||||
@@ -395,6 +395,6 @@ The `export_csv` convenience function delegates to `CSVExporter.export()`. For p
|
|||||||
</Tip>
|
</Tip>
|
||||||
|
|
||||||
- [Triplet Store](/reference/triplet_store) — Store RDF exports in a SPARQL-queryable backend.
|
- [Triplet Store](/reference/triplet_store) — Store RDF exports in a SPARQL-queryable backend.
|
||||||
- [Ontology](/reference/ontology) — Export OWL ontologies.
|
- [Ontology](ontology) — Export OWL ontologies.
|
||||||
- [Provenance](/reference/provenance) — Include provenance metadata in RDF exports.
|
- [Provenance](provenance) — Include provenance metadata in RDF exports.
|
||||||
- [Pipeline](/reference/pipeline) — Add export as a final pipeline step.
|
- [Pipeline](pipeline) — Add export as a final pipeline step.
|
||||||
|
|||||||
@@ -505,5 +505,5 @@ stats = store.get_stats()
|
|||||||
|
|
||||||
- [KG Module](/reference/kg) — Build the graph before persisting it.
|
- [KG Module](/reference/kg) — Build the graph before persisting it.
|
||||||
- [Triplet Store](/reference/triplet_store) — RDF triple store for semantic web and SPARQL queries.
|
- [Triplet Store](/reference/triplet_store) — RDF triple store for semantic web and SPARQL queries.
|
||||||
- [Visualization](/reference/visualization) — Visualize graphs stored in any backend.
|
- [Visualization](visualization) — Visualize graphs stored in any backend.
|
||||||
- [Context](/reference/context) — AgentContext uses GraphStore for memory retrieval.
|
- [Context](/reference/context) — AgentContext uses GraphStore for memory retrieval.
|
||||||
|
|||||||
@@ -647,7 +647,7 @@ result = ingest_file("source_path", method="my_format")
|
|||||||
```
|
```
|
||||||
|
|
||||||
- [Parse](/reference/parse) — Parse raw sources into structured text and tables.
|
- [Parse](/reference/parse) — Parse raw sources into structured text and tables.
|
||||||
- [Pipeline](/reference/pipeline) — Orchestrate ingest as the first pipeline step.
|
- [Pipeline](pipeline) — Orchestrate ingest as the first pipeline step.
|
||||||
- [Snowflake Integration](../integrations/snowflake) — Snowflake-specific setup and authentication guide.
|
- [Snowflake Integration](../integrations/snowflake) — Snowflake-specific setup and authentication guide.
|
||||||
- [Databricks Integration](../integrations/databricks) — Databricks Unity Catalog setup, authentication, and lineage guide.
|
- [Databricks Integration](../integrations/databricks) — Databricks Unity Catalog setup, authentication, and lineage guide.
|
||||||
- [Provenance](/reference/provenance) — Track lineage from ingest through to inference.
|
- [Provenance](provenance) — Track lineage from ingest through to inference.
|
||||||
|
|||||||
@@ -477,7 +477,7 @@ kg:
|
|||||||
|
|
||||||
- [Graph Store](/reference/graph_store) — Persist graphs in Neo4j, FalkorDB, or Apache AGE.
|
- [Graph Store](/reference/graph_store) — Persist graphs in Neo4j, FalkorDB, or Apache AGE.
|
||||||
- [Semantic Extract](/reference/semantic_extract) — Source of entities and relationships fed to GraphBuilder.
|
- [Semantic Extract](/reference/semantic_extract) — Source of entities and relationships fed to GraphBuilder.
|
||||||
- [Visualization](/reference/visualization) — Visualize knowledge graphs interactively.
|
- [Visualization](visualization) — Visualize knowledge graphs interactively.
|
||||||
- [Conflicts](/reference/conflicts) — Conflict detection and resolution.
|
- [Conflicts](/reference/conflicts) — Conflict detection and resolution.
|
||||||
|
|
||||||
### Cookbooks
|
### Cookbooks
|
||||||
|
|||||||
@@ -27,7 +27,7 @@ from semantica.llms import Groq, OpenAI, LiteLLM, HuggingFaceLLM
|
|||||||
| `HuggingFaceLLM` | Local HuggingFace Transformers | None (local) |
|
| `HuggingFaceLLM` | Local HuggingFace Transformers | None (local) |
|
||||||
|
|
||||||
<Tip>
|
<Tip>
|
||||||
**Anthropic, Gemini, Ollama, DeepSeek, Azure, Bedrock, Cohere, and 90+ others** are all available via `LiteLLM` using their model-string prefix. See the [LiteLLM section](#litellm-100+-providers) below.
|
**Anthropic, Gemini, Ollama, DeepSeek, Azure, Bedrock, Cohere, and 90+ others** are all available via `LiteLLM` using their model-string prefix. See the [LiteLLM section](#litellm-100-providers) below.
|
||||||
</Tip>
|
</Tip>
|
||||||
|
|
||||||
## What You Get
|
## What You Get
|
||||||
@@ -129,7 +129,7 @@ from semantica.llms import Groq, OpenAI, LiteLLM, HuggingFaceLLM
|
|||||||
from semantica.llms import LiteLLM
|
from semantica.llms import LiteLLM
|
||||||
|
|
||||||
llm = LiteLLM(
|
llm = LiteLLM(
|
||||||
model="anthropic/claude-sonnet-5",
|
model="anthropic/claude-sonnet-4-20250514",
|
||||||
api_key=os.getenv("ANTHROPIC_API_KEY"),
|
api_key=os.getenv("ANTHROPIC_API_KEY"),
|
||||||
temperature=0.0,
|
temperature=0.0,
|
||||||
)
|
)
|
||||||
@@ -198,7 +198,7 @@ llm = Groq(api_key=os.getenv("GROQ_API_KEY"), model="llama-3.1-8b-instant")
|
|||||||
# Method 3: Multiple providers via LiteLLM
|
# Method 3: Multiple providers via LiteLLM
|
||||||
providers = {
|
providers = {
|
||||||
"fast": LiteLLM(model="groq/llama-3.1-8b-instant", api_key=os.getenv("GROQ_API_KEY")),
|
"fast": LiteLLM(model="groq/llama-3.1-8b-instant", api_key=os.getenv("GROQ_API_KEY")),
|
||||||
"smart": LiteLLM(model="anthropic/claude-sonnet-5", api_key=os.getenv("ANTHROPIC_API_KEY"))
|
"smart": LiteLLM(model="anthropic/claude-sonnet-4-20250514", api_key=os.getenv("ANTHROPIC_API_KEY"))
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
@@ -252,7 +252,7 @@ from semantica.llms import LiteLLM
|
|||||||
# pip install "semantica[llm-litellm]"
|
# pip install "semantica[llm-litellm]"
|
||||||
|
|
||||||
# Anthropic Claude
|
# Anthropic Claude
|
||||||
llm = LiteLLM(model="anthropic/claude-opus-4-7", api_key=os.getenv("ANTHROPIC_API_KEY"))
|
llm = LiteLLM(model="anthropic/claude-opus-4-5", api_key=os.getenv("ANTHROPIC_API_KEY"))
|
||||||
|
|
||||||
# Google Gemini
|
# Google Gemini
|
||||||
llm = LiteLLM(model="gemini/gemini-1.5-pro", api_key=os.getenv("GOOGLE_API_KEY"))
|
llm = LiteLLM(model="gemini/gemini-1.5-pro", api_key=os.getenv("GOOGLE_API_KEY"))
|
||||||
@@ -267,7 +267,7 @@ llm = LiteLLM(model="deepseek/deepseek-chat", api_key=os.getenv("DEEP
|
|||||||
llm = LiteLLM(model="azure/gpt-4o", api_key=os.getenv("AZURE_API_KEY"))
|
llm = LiteLLM(model="azure/gpt-4o", api_key=os.getenv("AZURE_API_KEY"))
|
||||||
|
|
||||||
# AWS Bedrock
|
# AWS Bedrock
|
||||||
llm = LiteLLM(model="bedrock/anthropic.claude-sonnet-4-5-20250929-v1:0")
|
llm = LiteLLM(model="bedrock/anthropic.claude-3-5-sonnet-20241022-v2:0")
|
||||||
|
|
||||||
# Novita AI
|
# Novita AI
|
||||||
llm = LiteLLM(model="novita/deepseek/deepseek-v3.2", api_key=os.getenv("NOVITA_API_KEY"))
|
llm = LiteLLM(model="novita/deepseek/deepseek-v3.2", api_key=os.getenv("NOVITA_API_KEY"))
|
||||||
@@ -297,12 +297,12 @@ from semantica.llms import LiteLLM
|
|||||||
|
|
||||||
# Pattern: LiteLLM(model="<provider>/<model-name>")
|
# Pattern: LiteLLM(model="<provider>/<model-name>")
|
||||||
providers = {
|
providers = {
|
||||||
"Anthropic": LiteLLM(model="anthropic/claude-opus-4-7", api_key=os.getenv("ANTHROPIC_API_KEY")),
|
"Anthropic": LiteLLM(model="anthropic/claude-opus-4-5", api_key=os.getenv("ANTHROPIC_API_KEY")),
|
||||||
"Gemini": LiteLLM(model="gemini/gemini-1.5-pro", api_key=os.getenv("GOOGLE_API_KEY")),
|
"Gemini": LiteLLM(model="gemini/gemini-1.5-pro", api_key=os.getenv("GOOGLE_API_KEY")),
|
||||||
"Ollama": LiteLLM(model="ollama/llama3.2:3b", api_base="http://localhost:11434"),
|
"Ollama": LiteLLM(model="ollama/llama3.2:3b", api_base="http://localhost:11434"),
|
||||||
"DeepSeek": LiteLLM(model="deepseek/deepseek-chat", api_key=os.getenv("DEEPSEEK_API_KEY")),
|
"DeepSeek": LiteLLM(model="deepseek/deepseek-chat", api_key=os.getenv("DEEPSEEK_API_KEY")),
|
||||||
"Azure": LiteLLM(model="azure/gpt-4o", api_key=os.getenv("AZURE_API_KEY")),
|
"Azure": LiteLLM(model="azure/gpt-4o", api_key=os.getenv("AZURE_API_KEY")),
|
||||||
"Bedrock": LiteLLM(model="bedrock/anthropic.claude-sonnet-4-5-20250929-v1:0"),
|
"Bedrock": LiteLLM(model="bedrock/anthropic.claude-3-5-sonnet-20241022-v2:0"),
|
||||||
"Cohere": LiteLLM(model="cohere/command-r-plus", api_key=os.getenv("COHERE_API_KEY")),
|
"Cohere": LiteLLM(model="cohere/command-r-plus", api_key=os.getenv("COHERE_API_KEY")),
|
||||||
"Novita AI": LiteLLM(model="novita/deepseek/deepseek-v3.2", api_key=os.getenv("NOVITA_API_KEY")),
|
"Novita AI": LiteLLM(model="novita/deepseek/deepseek-v3.2", api_key=os.getenv("NOVITA_API_KEY")),
|
||||||
}
|
}
|
||||||
@@ -416,7 +416,7 @@ for text in texts:
|
|||||||
| :---------- | :--------------------------- | :----------- |
|
| :---------- | :--------------------------- | :----------- |
|
||||||
| **Entity Extraction** | `Groq("llama-3.3-70b-versatile")` | Fast, good accuracy for structured tasks |
|
| **Entity Extraction** | `Groq("llama-3.3-70b-versatile")` | Fast, good accuracy for structured tasks |
|
||||||
| **Relation Extraction** | `OpenAI("gpt-4o")` | Best at complex relationship reasoning |
|
| **Relation Extraction** | `OpenAI("gpt-4o")` | Best at complex relationship reasoning |
|
||||||
| **Complex Analysis** | `LiteLLM("anthropic/claude-sonnet-5")` | Highest reasoning capability |
|
| **Complex Analysis** | `LiteLLM("anthropic/claude-sonnet-4-20250514")` | Highest reasoning capability |
|
||||||
| **High Volume/Cost** | `LiteLLM("deepseek/deepseek-chat")` | Lowest cost per token |
|
| **High Volume/Cost** | `LiteLLM("deepseek/deepseek-chat")` | Lowest cost per token |
|
||||||
|
|
||||||
### Error Handling
|
### Error Handling
|
||||||
@@ -441,5 +441,5 @@ extractor = NERExtractor(
|
|||||||
|
|
||||||
- [Semantic Extract](/reference/semantic_extract) — Use LLMs for NER and relation extraction.
|
- [Semantic Extract](/reference/semantic_extract) — Use LLMs for NER and relation extraction.
|
||||||
- [Agno Integration](../integrations/agno) — LLM providers in Agno multi-agent teams.
|
- [Agno Integration](../integrations/agno) — LLM providers in Agno multi-agent teams.
|
||||||
- [Reasoning](/reference/reasoning) — LLM-backed deductive and abductive reasoning.
|
- [Reasoning](reasoning) — LLM-backed deductive and abductive reasoning.
|
||||||
- [Context](/reference/context) — GraphRAG uses LLMs for reasoning over knowledge graphs.
|
- [Context](/reference/context) — GraphRAG uses LLMs for reasoning over knowledge graphs.
|
||||||
|
|||||||
@@ -495,5 +495,5 @@ The MCP server exposes three readable resources:
|
|||||||
|
|
||||||
- [Context](/reference/context) — The ContextGraph that the MCP server operates on.
|
- [Context](/reference/context) — The ContextGraph that the MCP server operates on.
|
||||||
- [Semantic Extract](/reference/semantic_extract) — NER and relation extraction powering the MCP tools.
|
- [Semantic Extract](/reference/semantic_extract) — NER and relation extraction powering the MCP tools.
|
||||||
- [Reasoning](/reference/reasoning) — Forward-chaining engine behind run_reasoning.
|
- [Reasoning](reasoning) — Forward-chaining engine behind run_reasoning.
|
||||||
- [Agno Integration](../integrations/agno) — Use Semantica inside Agno multi-agent teams.
|
- [Agno Integration](../integrations/agno) — Use Semantica inside Agno multi-agent teams.
|
||||||
|
|||||||
@@ -586,5 +586,5 @@ normalized = normalize_text("Apple Inc.", method="expand_suffixes")
|
|||||||
|
|
||||||
- [Parse](/reference/parse) — Parse documents before normalization.
|
- [Parse](/reference/parse) — Parse documents before normalization.
|
||||||
- [Split](/reference/split) — Chunk normalized text for embedding.
|
- [Split](/reference/split) — Chunk normalized text for embedding.
|
||||||
- [Deduplication](/reference/deduplication) — Resolve duplicate entities after normalization.
|
- [Deduplication](deduplication) — Resolve duplicate entities after normalization.
|
||||||
- [Pipeline](/reference/pipeline) — Include normalization as a named pipeline step.
|
- [Pipeline](pipeline) — Include normalization as a named pipeline step.
|
||||||
|
|||||||
@@ -22,7 +22,6 @@ icon: "sitemap"
|
|||||||
| `LLMOntologyGenerator` | LLM-powered ontology generation for complex domains |
|
| `LLMOntologyGenerator` | LLM-powered ontology generation for complex domains |
|
||||||
| `SHACLGenerator` | Generate SHACL shapes from an ontology or KG schema |
|
| `SHACLGenerator` | Generate SHACL shapes from an ontology or KG schema |
|
||||||
| `OntologyValidator` | Validate any graph against SHACL shapes: returns `SHACLValidationReport` |
|
| `OntologyValidator` | Validate any graph against SHACL shapes: returns `SHACLValidationReport` |
|
||||||
| `OntologyQualityGate` | Run deterministic ontology/KG quality checks for CI |
|
|
||||||
| `OWLGenerator` | Serialize ontologies to Turtle, RDF/XML, JSON-LD |
|
| `OWLGenerator` | Serialize ontologies to Turtle, RDF/XML, JSON-LD |
|
||||||
| `NamespaceManager` | IRI generation, prefix management, and namespace binding |
|
| `NamespaceManager` | IRI generation, prefix management, and namespace binding |
|
||||||
| `OntologyEvaluator` | Coverage, completeness, and granularity quality metrics |
|
| `OntologyEvaluator` | Coverage, completeness, and granularity quality metrics |
|
||||||
@@ -82,38 +81,9 @@ engine.export_owl(ontology, "ontology.ttl", format="turtle")
|
|||||||
| :------ | :----------- |
|
| :------ | :----------- |
|
||||||
| `from_data(data)` | Run the 5-stage pipeline on entity/relationship data |
|
| `from_data(data)` | Run the 5-stage pipeline on entity/relationship data |
|
||||||
| `validate_graph(kg, ontology=...)` | Check a knowledge graph against generated SHACL shapes |
|
| `validate_graph(kg, ontology=...)` | Check a knowledge graph against generated SHACL shapes |
|
||||||
| `quality_check(ontology, graph_data=...)` | Return a deterministic quality report and CI-friendly pass/fail result |
|
|
||||||
| `export_owl(ontology, path, format)` | Serialize to `"turtle"`, `"xml"`, or `"json-ld"` |
|
| `export_owl(ontology, path, format)` | Serialize to `"turtle"`, `"xml"`, or `"json-ld"` |
|
||||||
| `evaluate(ontology, kg)` | Compute coverage, completeness, and granularity metrics |
|
| `evaluate(ontology, kg)` | Compute coverage, completeness, and granularity metrics |
|
||||||
|
|
||||||
### Ontology Quality Gate
|
|
||||||
|
|
||||||
Use the quality gate before export or deployment to catch structural issues
|
|
||||||
without adding a runtime dependency:
|
|
||||||
|
|
||||||
```python
|
|
||||||
from semantica.ontology import ontology_quality_check
|
|
||||||
|
|
||||||
report = ontology_quality_check(
|
|
||||||
ontology,
|
|
||||||
graph_data=kg,
|
|
||||||
thresholds={"min_coverage": 0.8},
|
|
||||||
)
|
|
||||||
|
|
||||||
if not report.passed:
|
|
||||||
for issue in report.issues:
|
|
||||||
print(issue.code, issue.message)
|
|
||||||
```
|
|
||||||
|
|
||||||
The report checks class/property coverage, orphan schema elements, domain and
|
|
||||||
range references, and unresolved KG relationship endpoints. It includes
|
|
||||||
machine-readable issue codes, severity, counts, metrics, and threshold
|
|
||||||
failures. The first version reports findings only; it does not auto-fix data.
|
|
||||||
|
|
||||||
### Thresholds
|
|
||||||
|
|
||||||
`min_coverage` (default `0.0`) sets the minimum required `coverage` score, the average of class and property coverage from `0.0` to `1.0`; the gate fails below it. `max_errors` (default `0.0`) caps how many `error`/`critical` issues are allowed before the gate fails. `max_warnings` (default `None`) caps `warning` issues the same way, and `None` means warnings alone never fail the gate. `fail_on_warnings` is a separate parameter, not a `thresholds` key, passed to `OntologyQualityGate(...)` or `.check(...)` directly; when `True`, a single warning fails the gate regardless of `max_warnings`.
|
|
||||||
|
|
||||||
## OntologyGenerator (5-Stage Pipeline)
|
## OntologyGenerator (5-Stage Pipeline)
|
||||||
|
|
||||||
**`OntologyGenerator`** auto-generates a formal ontology from your knowledge graph entities and relationships:
|
**`OntologyGenerator`** auto-generates a formal ontology from your knowledge graph entities and relationships:
|
||||||
@@ -316,7 +286,7 @@ ontology_data = ingest_ontology("schema.jsonld") # JSON-LD
|
|||||||
Ontology versioning (`VersionManager`, `OntologyVersion`) has moved to `semantica.change_management`. Import from there: `from semantica.change_management import VersionManager`.
|
Ontology versioning (`VersionManager`, `OntologyVersion`) has moved to `semantica.change_management`. Import from there: `from semantica.change_management import VersionManager`.
|
||||||
</Note>
|
</Note>
|
||||||
|
|
||||||
- [Reasoning](/reference/reasoning) — Apply inference rules over ontology axioms.
|
- [Reasoning](reasoning) — Apply inference rules over ontology axioms.
|
||||||
- [Knowledge Graph](/reference/kg) — The graph being modeled by the ontology.
|
- [Knowledge Graph](/reference/kg) — The graph being modeled by the ontology.
|
||||||
- [Export](/reference/export) — Export ontologies as RDF, OWL, or JSON-LD.
|
- [Export](export) — Export ontologies as RDF, OWL, or JSON-LD.
|
||||||
- [Conflicts](/reference/conflicts) — Detect ontology constraint violations.
|
- [Conflicts](/reference/conflicts) — Detect ontology constraint violations.
|
||||||
|
|||||||
@@ -297,7 +297,7 @@ for source in sources:
|
|||||||
Docling is an optional dependency. If `docling` is not installed, `DoclingParser` raises an `ImportError` with installation instructions: `pip install docling`. `DocumentParser` is always available and requires no extras.
|
Docling is an optional dependency. If `docling` is not installed, `DoclingParser` raises an `ImportError` with installation instructions: `pip install docling`. `DocumentParser` is always available and requires no extras.
|
||||||
</Note>
|
</Note>
|
||||||
|
|
||||||
- [Ingest](/reference/ingest) — Load files before parsing.
|
- [Ingest](ingest) — Load files before parsing.
|
||||||
- [Split](/reference/split) — Chunk parsed text for embedding and extraction.
|
- [Split](/reference/split) — Chunk parsed text for embedding and extraction.
|
||||||
- [Docling Integration](../integrations/docling) — Full Docling integration setup guide.
|
- [Docling Integration](../integrations/docling) — Full Docling integration setup guide.
|
||||||
- [Semantic Extract](/reference/semantic_extract) — Extract entities and relations from parsed text.
|
- [Semantic Extract](/reference/semantic_extract) — Extract entities and relations from parsed text.
|
||||||
|
|||||||
@@ -588,7 +588,7 @@ StepStatus.SKIPPED # Skipped due to FailureHandler "skip" strategy
|
|||||||
</Accordion>
|
</Accordion>
|
||||||
</AccordionGroup>
|
</AccordionGroup>
|
||||||
|
|
||||||
- [Ingest](/reference/ingest) — First step in most pipelines.
|
- [Ingest](ingest) — First step in most pipelines.
|
||||||
- [Semantic Extract](/reference/semantic_extract) — Core extraction step.
|
- [Semantic Extract](/reference/semantic_extract) — Core extraction step.
|
||||||
- [Knowledge Graph](/reference/kg) — Graph construction step.
|
- [Knowledge Graph](/reference/kg) — Graph construction step.
|
||||||
- [Export](/reference/export) — Final output step.
|
- [Export](export) — Final output step.
|
||||||
|
|||||||
@@ -523,6 +523,6 @@ Provenance tracking in Semantica produces the following audit artifacts:
|
|||||||
</Note>
|
</Note>
|
||||||
|
|
||||||
- [Change Management](/reference/change_management) — Version control and snapshot audit trails.
|
- [Change Management](/reference/change_management) — Version control and snapshot audit trails.
|
||||||
- [Ingest](/reference/ingest) — Provenance begins at the ingestion stage.
|
- [Ingest](ingest) — Provenance begins at the ingestion stage.
|
||||||
- [Export](/reference/export) — Include provenance metadata in RDF exports.
|
- [Export](export) — Include provenance metadata in RDF exports.
|
||||||
- [Context](/reference/context) — Decision provenance via AgentContext.
|
- [Context](/reference/context) — Decision provenance via AgentContext.
|
||||||
|
|||||||
@@ -31,7 +31,7 @@ icon: "microchip"
|
|||||||
|
|
||||||
## Which Engine Should I Use?
|
## Which Engine Should I Use?
|
||||||
|
|
||||||
- [Reasoner](#reasoner-forward/backward-chaining) — IF/THEN rules, forward and backward chaining. **Start here**: covers 90% of use cases. No query language required.
|
- [Reasoner](#reasoner-forwardbackward-chaining) — IF/THEN rules, forward and backward chaining. **Start here**: covers 90% of use cases. No query language required.
|
||||||
- [GraphReasoner](#graphreasoner) — Natural language queries over a knowledge graph via LLM. No SPARQL or rules: just ask a question.
|
- [GraphReasoner](#graphreasoner) — Natural language queries over a knowledge graph via LLM. No SPARQL or rules: just ask a question.
|
||||||
- [DatalogReasoner](#datalogreasoner) — Recursive Horn clause rules with guaranteed termination. Use for complex multi-hop transitive rules.
|
- [DatalogReasoner](#datalogreasoner) — Recursive Horn clause rules with guaranteed termination. Use for complex multi-hop transitive rules.
|
||||||
- [ReteEngine](#reteengine) — Rete pattern matching for high-frequency inference. Use when you need to match many facts against many rules simultaneously.
|
- [ReteEngine](#reteengine) — Rete pattern matching for high-frequency inference. Use when you need to match many facts against many rules simultaneously.
|
||||||
@@ -323,7 +323,7 @@ all_facts = datalog.derive_all()
|
|||||||
|
|
||||||
# Query with variable pattern: variables start with uppercase or ?
|
# Query with variable pattern: variables start with uppercase or ?
|
||||||
results = datalog.query("ancestor(alice, ?Z)")
|
results = datalog.query("ancestor(alice, ?Z)")
|
||||||
# → a list of binding dicts: [{"Z": "bob"}, {"Z": "charlie"}, {"Z": "dave"}] (order not guaranteed)
|
# → [{"Z": "bob"}, {"Z": "charlie"}, {"Z": "dave"}]
|
||||||
|
|
||||||
# Clear and start over
|
# Clear and start over
|
||||||
datalog.clear()
|
datalog.clear()
|
||||||
@@ -483,6 +483,6 @@ step.confidence # float
|
|||||||
</Warning>
|
</Warning>
|
||||||
|
|
||||||
- [Knowledge Graph](/reference/kg) — The knowledge graph being reasoned over.
|
- [Knowledge Graph](/reference/kg) — The knowledge graph being reasoned over.
|
||||||
- [Ontology](/reference/ontology) — Ontology axioms and SHACL constraints for logical reasoning.
|
- [Ontology](ontology) — Ontology axioms and SHACL constraints for logical reasoning.
|
||||||
- [Triplet Store](/reference/triplet_store) — RDF backend for SPARQL-based reasoning.
|
- [Triplet Store](/reference/triplet_store) — RDF backend for SPARQL-based reasoning.
|
||||||
- [Context](/reference/context) — Reasoning integrated into agent decision intelligence.
|
- [Context](/reference/context) — Reasoning integrated into agent decision intelligence.
|
||||||
|
|||||||
@@ -321,7 +321,7 @@ export SEMANTICA_SEED_MERGE_STRATEGY=seed_first
|
|||||||
**Use YAML configuration for production deployments.** Hard-coding source paths in Python scripts makes environment-switching (dev → staging → prod) fragile. Declare sources in `config.yaml` under the `seed:` key and override paths with `SEMANTICA_SEED_DATA_DIR`. This way, the same code runs in every environment.
|
**Use YAML configuration for production deployments.** Hard-coding source paths in Python scripts makes environment-switching (dev → staging → prod) fragile. Declare sources in `config.yaml` under the `seed:` key and override paths with `SEMANTICA_SEED_DATA_DIR`. This way, the same code runs in every environment.
|
||||||
</Tip>
|
</Tip>
|
||||||
|
|
||||||
- [Ingest](/reference/ingest) — Load unstructured data alongside seed data.
|
- [Ingest](ingest) — Load unstructured data alongside seed data.
|
||||||
- [Knowledge Graph](/reference/kg) — The target graph that seed data populates.
|
- [Knowledge Graph](/reference/kg) — The target graph that seed data populates.
|
||||||
- [Deduplication](/reference/deduplication) — Handle duplicates during seed-extracted merge.
|
- [Deduplication](deduplication) — Handle duplicates during seed-extracted merge.
|
||||||
- [Pipeline](/reference/pipeline) — Incorporate seed loading as a named pipeline step.
|
- [Pipeline](pipeline) — Incorporate seed loading as a named pipeline step.
|
||||||
|
|||||||
@@ -191,41 +191,6 @@ trip = TripletExtractor(method=["llm", "pattern"])
|
|||||||
entities = ner.extract(text)
|
entities = ner.extract(text)
|
||||||
```
|
```
|
||||||
|
|
||||||
### NER Merge Strategies
|
|
||||||
|
|
||||||
`NERExtractor` uses `merge_strategy="fallback"` by default, so a method list remains an ordered fallback chain. To run several methods together, choose one of the explicit strategies below:
|
|
||||||
|
|
||||||
| Strategy | Behavior |
|
|
||||||
| :--- | :--- |
|
|
||||||
| `fallback` | Return the first non-empty method result. |
|
|
||||||
| `union` | Keep candidates from any method. Same-label boundary variants are aligned, while distinct labels remain available. |
|
|
||||||
| `consensus` | Require cross-method support for an offset-aligned candidate. `min_votes` defaults to `2`. |
|
|
||||||
|
|
||||||
```python
|
|
||||||
from semantica.semantic_extract import NERExtractor
|
|
||||||
|
|
||||||
ner = NERExtractor(
|
|
||||||
method=["spacy", "huggingface"],
|
|
||||||
merge_strategy="consensus",
|
|
||||||
min_votes=2,
|
|
||||||
min_agreement=0.75, # optional support-ratio requirement
|
|
||||||
method_weights={"spacy": 0.8, "huggingface": 1.0},
|
|
||||||
)
|
|
||||||
entities = ner.extract(text)
|
|
||||||
|
|
||||||
for entity in entities:
|
|
||||||
print(entity.metadata["supporting_methods"])
|
|
||||||
print(entity.metadata["vote_count"], entity.metadata["agreement"])
|
|
||||||
```
|
|
||||||
|
|
||||||
Consensus counts support against the configured eligible methods, not only methods that emitted a candidate. An empty or failed eligible method is therefore a non-supporting vote. Use `eligible_methods=[...]` to restrict the consensus denominator when the configured methods have different coverage, or use `merge_strategy="union"` for complementary rule extractors. `method_weights` only break an otherwise eligible exact-span cross-label tie; they never turn one method into multiple votes.
|
|
||||||
|
|
||||||
Each merged entity includes `supporting_methods`, `vote_count`, `eligible_method_count`, `agreement`, and per-method `method_scores` in its metadata. Consensus treats compatible label aliases such as `PER`/`PERSON` and `ORGANIZATION`/`ORG` as the same vote. It resolves a cross-label conflict only when the final spans are identical, using method weight, vote count, confidence, and a stable label order; nested entities at different spans remain available. `ml` and `spacy` are one backend for both voting and weights, so their weights are interchangeable (conflicting values are rejected). Boundary candidates are matched one-to-one only when their span IoU is at least 0.5 with every existing vote in that candidate; equal-confidence variants prefer the longer span. If a provider omits offsets, Semantica resolves its entity text against whole-word document matches before merging. This keeps repeated mentions with the same text distinct and prevents one broad span from acting as a vote for multiple mentions.
|
|
||||||
|
|
||||||
`ensemble_voting=True` is deprecated and maps to `merge_strategy="union"` during migration. Use `merge_strategy="consensus"` when method agreement is required.
|
|
||||||
|
|
||||||
Unlike `fallback`, `union` and `consensus` never inject a pattern-derived entity after the configured methods return no candidates. An empty result is therefore meaningful in those strategies.
|
|
||||||
|
|
||||||
|
|
||||||
## Quick Start
|
## Quick Start
|
||||||
|
|
||||||
@@ -448,4 +413,4 @@ triplets = trip.extract(text)
|
|||||||
- [LLM Providers](/reference/llms) — Configure which LLM is used for extraction.
|
- [LLM Providers](/reference/llms) — Configure which LLM is used for extraction.
|
||||||
- [Knowledge Graph](/reference/kg) — Build graphs from extracted entities and relationships.
|
- [Knowledge Graph](/reference/kg) — Build graphs from extracted entities and relationships.
|
||||||
- [Parse Module](/reference/parse) — Parse documents before extraction.
|
- [Parse Module](/reference/parse) — Parse documents before extraction.
|
||||||
- [Deduplication](/reference/deduplication) — Resolve duplicate entities after extraction.
|
- [Deduplication](deduplication) — Resolve duplicate entities after extraction.
|
||||||
|
|||||||
@@ -371,9 +371,9 @@ for chunk in chunks:
|
|||||||
print(f" {len(entities)} entities in chunk starting at {chunk.start_index}")
|
print(f" {len(entities)} entities in chunk starting at {chunk.start_index}")
|
||||||
```
|
```
|
||||||
|
|
||||||
For the full pipeline orchestration API, see the [Pipeline reference](/reference/pipeline).
|
For the full pipeline orchestration API, see the [Pipeline reference](pipeline).
|
||||||
|
|
||||||
- [Parse](/reference/parse) — Parse documents before chunking: produces sections and metadata.
|
- [Parse](/reference/parse) — Parse documents before chunking: produces sections and metadata.
|
||||||
- [Embeddings](/reference/embeddings) — Embed chunks for vector search and semantic chunking.
|
- [Embeddings](/reference/embeddings) — Embed chunks for vector search and semantic chunking.
|
||||||
- [Semantic Extract](/reference/semantic_extract) — Extract entities and relations from individual chunks.
|
- [Semantic Extract](/reference/semantic_extract) — Extract entities and relations from individual chunks.
|
||||||
- [Pipeline](/reference/pipeline) — Integrate splitting as a named pipeline step.
|
- [Pipeline](pipeline) — Integrate splitting as a named pipeline step.
|
||||||
|
|||||||
@@ -876,8 +876,8 @@ kg:
|
|||||||
|
|
||||||
- [Knowledge Graph Module](/reference/kg) — Core graph construction, `GraphBuilder`, analytics.
|
- [Knowledge Graph Module](/reference/kg) — Core graph construction, `GraphBuilder`, analytics.
|
||||||
- [Context Module](/reference/context) — Decision temporal windows and `find_active_nodes()`.
|
- [Context Module](/reference/context) — Decision temporal windows and `find_active_nodes()`.
|
||||||
- [Provenance](/reference/provenance) — W3C PROV-O lineage stamped alongside temporal metadata.
|
- [Provenance](provenance) — W3C PROV-O lineage stamped alongside temporal metadata.
|
||||||
- [Export](/reference/export) — OWL, Turtle, JSON-LD, and Parquet export with temporal annotations.
|
- [Export](export) — OWL, Turtle, JSON-LD, and Parquet export with temporal annotations.
|
||||||
|
|
||||||
- [Temporal Knowledge Graphs](https://github.com/semantica-agi/semantica/blob/main/cookbook/advanced/10_Temporal_Knowledge_Graphs.ipynb) — Temporal reasoning and Allen algebra · Advanced
|
- [Temporal Knowledge Graphs](https://github.com/semantica-agi/semantica/blob/main/cookbook/advanced/10_Temporal_Knowledge_Graphs.ipynb) — Temporal reasoning and Allen algebra · Advanced
|
||||||
- [Context Module](https://github.com/semantica-agi/semantica/blob/main/cookbook/introduction/19_Context_Module.ipynb) — Including temporal decision windows · Intermediate
|
- [Context Module](https://github.com/semantica-agi/semantica/blob/main/cookbook/introduction/19_Context_Module.ipynb) — Including temporal decision windows · Intermediate
|
||||||
|
|||||||
@@ -561,7 +561,7 @@ for row in result.bindings:
|
|||||||
print(row)
|
print(row)
|
||||||
```
|
```
|
||||||
|
|
||||||
- [Export](/reference/export) — Export knowledge graphs to RDF formats.
|
- [Export](export) — Export knowledge graphs to RDF formats.
|
||||||
- [Ontology](/reference/ontology) — Load OWL ontologies and store as RDF triples.
|
- [Ontology](ontology) — Load OWL ontologies and store as RDF triples.
|
||||||
- [Reasoning](/reference/reasoning) — SPARQL-based property chain inference.
|
- [Reasoning](reasoning) — SPARQL-based property chain inference.
|
||||||
- [Graph Store](/reference/graph_store) — Property graph alternative for Cypher queries.
|
- [Graph Store](/reference/graph_store) — Property graph alternative for Cypher queries.
|
||||||
|
|||||||
@@ -223,4 +223,4 @@ config = read_json_file("config.json")
|
|||||||
```
|
```
|
||||||
|
|
||||||
- [Core](/reference/core) — Framework orchestration that uses Utils internally.
|
- [Core](/reference/core) — Framework orchestration that uses Utils internally.
|
||||||
- [Pipeline](/reference/pipeline) — Uses ProgressTracker for per-step tracking.
|
- [Pipeline](pipeline) — Uses ProgressTracker for per-step tracking.
|
||||||
|
|||||||
@@ -160,7 +160,7 @@ No installation or API key required. FAISS requires `pip install faiss-cpu`.
|
|||||||
<Tab title="Pinecone">
|
<Tab title="Pinecone">
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
pip install "semantica[vectorstore-pinecone]"
|
pip install "semantica[pinecone]"
|
||||||
```
|
```
|
||||||
|
|
||||||
```python
|
```python
|
||||||
@@ -178,7 +178,7 @@ store = VectorStore(
|
|||||||
<Tab title="Weaviate">
|
<Tab title="Weaviate">
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
pip install "semantica[vectorstore-weaviate]"
|
pip install "semantica[weaviate]"
|
||||||
```
|
```
|
||||||
|
|
||||||
```python
|
```python
|
||||||
@@ -194,7 +194,7 @@ store = VectorStore(
|
|||||||
<Tab title="Qdrant">
|
<Tab title="Qdrant">
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
pip install "semantica[vectorstore-qdrant]"
|
pip install "semantica[qdrant]"
|
||||||
```
|
```
|
||||||
|
|
||||||
```python
|
```python
|
||||||
@@ -210,7 +210,7 @@ store = VectorStore(
|
|||||||
<Tab title="PgVector">
|
<Tab title="PgVector">
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
pip install "semantica[vectorstore-pgvector]"
|
pip install "semantica[pgvector]"
|
||||||
```
|
```
|
||||||
|
|
||||||
```python
|
```python
|
||||||
@@ -591,4 +591,4 @@ store.create_index(index_type="pq", metric="L2", m=8)
|
|||||||
- [Embeddings](/reference/embeddings) — Generate the vectors stored here.
|
- [Embeddings](/reference/embeddings) — Generate the vectors stored here.
|
||||||
- [Context](/reference/context) — AgentContext uses VectorStore for memory retrieval.
|
- [Context](/reference/context) — AgentContext uses VectorStore for memory retrieval.
|
||||||
- [Split](/reference/split) — Chunk documents before embedding and storing.
|
- [Split](/reference/split) — Chunk documents before embedding and storing.
|
||||||
- [Ingest](/reference/ingest) — Ingest documents before embedding and storing.
|
- [Ingest](ingest) — Ingest documents before embedding and storing.
|
||||||
|
|||||||
@@ -291,6 +291,6 @@ semantica-explorer --graph my_graph.json
|
|||||||
See the [Explorer reference](/reference/explorer) for the full feature set and REST API.
|
See the [Explorer reference](/reference/explorer) for the full feature set and REST API.
|
||||||
|
|
||||||
- [Knowledge Graph](/reference/kg) — The graph being visualized.
|
- [Knowledge Graph](/reference/kg) — The graph being visualized.
|
||||||
- [Ontology](/reference/ontology) — Visualize ontology class structure.
|
- [Ontology](ontology) — Visualize ontology class structure.
|
||||||
- [Embeddings](/reference/embeddings) — Generate the embeddings visualized here.
|
- [Embeddings](/reference/embeddings) — Generate the embeddings visualized here.
|
||||||
- [Explorer](/reference/explorer) — Full interactive Knowledge Explorer UI.
|
- [Explorer](/reference/explorer) — Full interactive Knowledge Explorer UI.
|
||||||
|
|||||||
+5
-10
@@ -236,9 +236,7 @@ def _() -> list[str]:
|
|||||||
cwd=DOCS,
|
cwd=DOCS,
|
||||||
capture_output=True,
|
capture_output=True,
|
||||||
text=True,
|
text=True,
|
||||||
encoding="utf-8",
|
timeout=300,
|
||||||
errors="replace",
|
|
||||||
timeout=600,
|
|
||||||
)
|
)
|
||||||
# Clean up zip regardless of outcome
|
# Clean up zip regardless of outcome
|
||||||
zip_path = os.path.join(DOCS, "export_ci_check.zip")
|
zip_path = os.path.join(DOCS, "export_ci_check.zip")
|
||||||
@@ -248,12 +246,9 @@ def _() -> list[str]:
|
|||||||
combined = (result.stdout or "") + (result.stderr or "")
|
combined = (result.stdout or "") + (result.stderr or "")
|
||||||
|
|
||||||
if result.returncode != 0:
|
if result.returncode != 0:
|
||||||
# On Windows, npm post-command cleanup can fail with EPERM/EBUSY on
|
# On Windows, npm cleanup raises EPERM on temp dirs — not a real
|
||||||
# temp dirs — not a real export failure. Treat as a skip rather
|
# export failure. Treat as a skip rather than a hard failure.
|
||||||
# than a hard failure, unless a real Mintlify error signature is
|
if sys.platform == "win32" and "EPERM" in combined and \
|
||||||
# present.
|
|
||||||
if sys.platform == "win32" and \
|
|
||||||
("EPERM" in combined or "EBUSY" in combined) and \
|
|
||||||
"could not be generated" not in combined:
|
"could not be generated" not in combined:
|
||||||
return [] # Windows temp-cleanup noise; real CI runs on Linux
|
return [] # Windows temp-cleanup noise; real CI runs on Linux
|
||||||
|
|
||||||
@@ -268,7 +263,7 @@ def _() -> list[str]:
|
|||||||
except FileNotFoundError:
|
except FileNotFoundError:
|
||||||
return ["npx not found — skipping Mintlify export check (Node.js required)"]
|
return ["npx not found — skipping Mintlify export check (Node.js required)"]
|
||||||
except subprocess.TimeoutExpired:
|
except subprocess.TimeoutExpired:
|
||||||
return ["mintlify export timed out after 600 s"]
|
return ["mintlify export timed out after 300 s"]
|
||||||
|
|
||||||
|
|
||||||
# ── Summary ───────────────────────────────────────────────────────────────────
|
# ── Summary ───────────────────────────────────────────────────────────────────
|
||||||
|
|||||||
Generated
-653
@@ -33,9 +33,7 @@
|
|||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@babel/core": "^7.29.6",
|
"@babel/core": "^7.29.6",
|
||||||
"@eslint/js": "^9.39.4",
|
"@eslint/js": "^9.39.4",
|
||||||
"@testing-library/react": "^16.3.3",
|
|
||||||
"@types/babel__core": "^7.20.5",
|
"@types/babel__core": "^7.20.5",
|
||||||
"@types/jsdom": "^21.1.7",
|
|
||||||
"@types/node": "^24.12.0",
|
"@types/node": "^24.12.0",
|
||||||
"@types/react": "^19.2.14",
|
"@types/react": "^19.2.14",
|
||||||
"@types/react-dom": "^19.2.3",
|
"@types/react-dom": "^19.2.3",
|
||||||
@@ -45,34 +43,12 @@
|
|||||||
"eslint-plugin-react-hooks": "^7.0.1",
|
"eslint-plugin-react-hooks": "^7.0.1",
|
||||||
"eslint-plugin-react-refresh": "^0.5.2",
|
"eslint-plugin-react-refresh": "^0.5.2",
|
||||||
"globals": "^17.4.0",
|
"globals": "^17.4.0",
|
||||||
"jsdom": "^26.1.0",
|
|
||||||
"tsx": "^4.21.0",
|
"tsx": "^4.21.0",
|
||||||
"typescript": "~5.9.3",
|
"typescript": "~5.9.3",
|
||||||
"typescript-eslint": "^8.57.0",
|
"typescript-eslint": "^8.57.0",
|
||||||
"vite": "^6.4.2"
|
"vite": "^6.4.2"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@asamuzakjp/css-color": {
|
|
||||||
"version": "3.2.0",
|
|
||||||
"resolved": "https://registry.npmmirror.com/@asamuzakjp/css-color/-/css-color-3.2.0.tgz",
|
|
||||||
"integrity": "sha512-K1A6z8tS3XsmCMM86xoWdn7Fkdn9m6RSVtocUrJYIwZnFVkng/PvkEoWtOWmP+Scc6saYWHWZYbndEEXxl24jw==",
|
|
||||||
"dev": true,
|
|
||||||
"license": "MIT",
|
|
||||||
"dependencies": {
|
|
||||||
"@csstools/css-calc": "^2.1.3",
|
|
||||||
"@csstools/css-color-parser": "^3.0.9",
|
|
||||||
"@csstools/css-parser-algorithms": "^3.0.4",
|
|
||||||
"@csstools/css-tokenizer": "^3.0.3",
|
|
||||||
"lru-cache": "^10.4.3"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/@asamuzakjp/css-color/node_modules/lru-cache": {
|
|
||||||
"version": "10.4.3",
|
|
||||||
"resolved": "https://registry.npmmirror.com/lru-cache/-/lru-cache-10.4.3.tgz",
|
|
||||||
"integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==",
|
|
||||||
"dev": true,
|
|
||||||
"license": "ISC"
|
|
||||||
},
|
|
||||||
"node_modules/@babel/code-frame": {
|
"node_modules/@babel/code-frame": {
|
||||||
"version": "7.29.0",
|
"version": "7.29.0",
|
||||||
"resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.29.0.tgz",
|
"resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.29.0.tgz",
|
||||||
@@ -364,121 +340,6 @@
|
|||||||
"node": ">=6.9.0"
|
"node": ">=6.9.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@csstools/color-helpers": {
|
|
||||||
"version": "5.1.0",
|
|
||||||
"resolved": "https://registry.npmmirror.com/@csstools/color-helpers/-/color-helpers-5.1.0.tgz",
|
|
||||||
"integrity": "sha512-S11EXWJyy0Mz5SYvRmY8nJYTFFd1LCNV+7cXyAgQtOOuzb4EsgfqDufL+9esx72/eLhsRdGZwaldu/h+E4t4BA==",
|
|
||||||
"dev": true,
|
|
||||||
"funding": [
|
|
||||||
{
|
|
||||||
"type": "github",
|
|
||||||
"url": "https://github.com/sponsors/csstools"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"type": "opencollective",
|
|
||||||
"url": "https://opencollective.com/csstools"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"license": "MIT-0",
|
|
||||||
"engines": {
|
|
||||||
"node": ">=18"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/@csstools/css-calc": {
|
|
||||||
"version": "2.1.4",
|
|
||||||
"resolved": "https://registry.npmmirror.com/@csstools/css-calc/-/css-calc-2.1.4.tgz",
|
|
||||||
"integrity": "sha512-3N8oaj+0juUw/1H3YwmDDJXCgTB1gKU6Hc/bB502u9zR0q2vd786XJH9QfrKIEgFlZmhZiq6epXl4rHqhzsIgQ==",
|
|
||||||
"dev": true,
|
|
||||||
"funding": [
|
|
||||||
{
|
|
||||||
"type": "github",
|
|
||||||
"url": "https://github.com/sponsors/csstools"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"type": "opencollective",
|
|
||||||
"url": "https://opencollective.com/csstools"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"license": "MIT",
|
|
||||||
"engines": {
|
|
||||||
"node": ">=18"
|
|
||||||
},
|
|
||||||
"peerDependencies": {
|
|
||||||
"@csstools/css-parser-algorithms": "^3.0.5",
|
|
||||||
"@csstools/css-tokenizer": "^3.0.4"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/@csstools/css-color-parser": {
|
|
||||||
"version": "3.1.0",
|
|
||||||
"resolved": "https://registry.npmmirror.com/@csstools/css-color-parser/-/css-color-parser-3.1.0.tgz",
|
|
||||||
"integrity": "sha512-nbtKwh3a6xNVIp/VRuXV64yTKnb1IjTAEEh3irzS+HkKjAOYLTGNb9pmVNntZ8iVBHcWDA2Dof0QtPgFI1BaTA==",
|
|
||||||
"dev": true,
|
|
||||||
"funding": [
|
|
||||||
{
|
|
||||||
"type": "github",
|
|
||||||
"url": "https://github.com/sponsors/csstools"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"type": "opencollective",
|
|
||||||
"url": "https://opencollective.com/csstools"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"license": "MIT",
|
|
||||||
"dependencies": {
|
|
||||||
"@csstools/color-helpers": "^5.1.0",
|
|
||||||
"@csstools/css-calc": "^2.1.4"
|
|
||||||
},
|
|
||||||
"engines": {
|
|
||||||
"node": ">=18"
|
|
||||||
},
|
|
||||||
"peerDependencies": {
|
|
||||||
"@csstools/css-parser-algorithms": "^3.0.5",
|
|
||||||
"@csstools/css-tokenizer": "^3.0.4"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/@csstools/css-parser-algorithms": {
|
|
||||||
"version": "3.0.5",
|
|
||||||
"resolved": "https://registry.npmmirror.com/@csstools/css-parser-algorithms/-/css-parser-algorithms-3.0.5.tgz",
|
|
||||||
"integrity": "sha512-DaDeUkXZKjdGhgYaHNJTV9pV7Y9B3b644jCLs9Upc3VeNGg6LWARAT6O+Q+/COo+2gg/bM5rhpMAtf70WqfBdQ==",
|
|
||||||
"dev": true,
|
|
||||||
"funding": [
|
|
||||||
{
|
|
||||||
"type": "github",
|
|
||||||
"url": "https://github.com/sponsors/csstools"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"type": "opencollective",
|
|
||||||
"url": "https://opencollective.com/csstools"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"license": "MIT",
|
|
||||||
"engines": {
|
|
||||||
"node": ">=18"
|
|
||||||
},
|
|
||||||
"peerDependencies": {
|
|
||||||
"@csstools/css-tokenizer": "^3.0.4"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/@csstools/css-tokenizer": {
|
|
||||||
"version": "3.0.4",
|
|
||||||
"resolved": "https://registry.npmmirror.com/@csstools/css-tokenizer/-/css-tokenizer-3.0.4.tgz",
|
|
||||||
"integrity": "sha512-Vd/9EVDiu6PPJt9yAh6roZP6El1xHrdvIVGjyBsHR0RYwNHgL7FJPyIIW4fANJNG6FtyZfvlRPpFI4ZM/lubvw==",
|
|
||||||
"dev": true,
|
|
||||||
"funding": [
|
|
||||||
{
|
|
||||||
"type": "github",
|
|
||||||
"url": "https://github.com/sponsors/csstools"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"type": "opencollective",
|
|
||||||
"url": "https://opencollective.com/csstools"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"license": "MIT",
|
|
||||||
"engines": {
|
|
||||||
"node": ">=18"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/@egjs/hammerjs": {
|
"node_modules/@egjs/hammerjs": {
|
||||||
"version": "2.0.17",
|
"version": "2.0.17",
|
||||||
"resolved": "https://registry.npmjs.org/@egjs/hammerjs/-/hammerjs-2.0.17.tgz",
|
"resolved": "https://registry.npmjs.org/@egjs/hammerjs/-/hammerjs-2.0.17.tgz",
|
||||||
@@ -1612,63 +1473,6 @@
|
|||||||
"react": "^18 || ^19"
|
"react": "^18 || ^19"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@testing-library/dom": {
|
|
||||||
"version": "10.4.1",
|
|
||||||
"resolved": "https://registry.npmmirror.com/@testing-library/dom/-/dom-10.4.1.tgz",
|
|
||||||
"integrity": "sha512-o4PXJQidqJl82ckFaXUeoAW+XysPLauYI43Abki5hABd853iMhitooc6znOnczgbTYmEP6U6/y1ZyKAIsvMKGg==",
|
|
||||||
"dev": true,
|
|
||||||
"license": "MIT",
|
|
||||||
"peer": true,
|
|
||||||
"dependencies": {
|
|
||||||
"@babel/code-frame": "^7.10.4",
|
|
||||||
"@babel/runtime": "^7.12.5",
|
|
||||||
"@types/aria-query": "^5.0.1",
|
|
||||||
"aria-query": "5.3.0",
|
|
||||||
"dom-accessibility-api": "^0.5.9",
|
|
||||||
"lz-string": "^1.5.0",
|
|
||||||
"picocolors": "1.1.1",
|
|
||||||
"pretty-format": "^27.0.2"
|
|
||||||
},
|
|
||||||
"engines": {
|
|
||||||
"node": ">=18"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/@testing-library/react": {
|
|
||||||
"version": "16.3.3",
|
|
||||||
"resolved": "https://registry.npmmirror.com/@testing-library/react/-/react-16.3.3.tgz",
|
|
||||||
"integrity": "sha512-Uo193NgQbPMz6lrrhtRQQFcMC6Re/ELLFbbuVL30WDlZxlpZf9/lMHTAVxPRLw1q1iu9OJmR1c2BLiENRstdBg==",
|
|
||||||
"dev": true,
|
|
||||||
"license": "MIT",
|
|
||||||
"dependencies": {
|
|
||||||
"@babel/runtime": "^7.12.5"
|
|
||||||
},
|
|
||||||
"engines": {
|
|
||||||
"node": ">=18"
|
|
||||||
},
|
|
||||||
"peerDependencies": {
|
|
||||||
"@testing-library/dom": "^10.0.0",
|
|
||||||
"@types/react": "^18.0.0 || ^19.0.0",
|
|
||||||
"@types/react-dom": "^18.0.0 || ^19.0.0",
|
|
||||||
"react": "^18.0.0 || ^19.0.0",
|
|
||||||
"react-dom": "^18.0.0 || ^19.0.0"
|
|
||||||
},
|
|
||||||
"peerDependenciesMeta": {
|
|
||||||
"@types/react": {
|
|
||||||
"optional": true
|
|
||||||
},
|
|
||||||
"@types/react-dom": {
|
|
||||||
"optional": true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/@types/aria-query": {
|
|
||||||
"version": "5.0.4",
|
|
||||||
"resolved": "https://registry.npmmirror.com/@types/aria-query/-/aria-query-5.0.4.tgz",
|
|
||||||
"integrity": "sha512-rfT93uj5s0PRL7EzccGMs3brplhcrghnDoV26NqKhCAS1hVo+WdNsPvE/yb6ilfr5hi2MEk6d5EWJTKdxg8jVw==",
|
|
||||||
"dev": true,
|
|
||||||
"license": "MIT",
|
|
||||||
"peer": true
|
|
||||||
},
|
|
||||||
"node_modules/@types/babel__core": {
|
"node_modules/@types/babel__core": {
|
||||||
"version": "7.20.5",
|
"version": "7.20.5",
|
||||||
"resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.20.5.tgz",
|
"resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.20.5.tgz",
|
||||||
@@ -1810,18 +1614,6 @@
|
|||||||
"@types/unist": "*"
|
"@types/unist": "*"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@types/jsdom": {
|
|
||||||
"version": "21.1.7",
|
|
||||||
"resolved": "https://registry.npmmirror.com/@types/jsdom/-/jsdom-21.1.7.tgz",
|
|
||||||
"integrity": "sha512-yOriVnggzrnQ3a9OKOCxaVuSug3w3/SbOj5i7VwXWZEyUNl3bLF9V3MfxGbZKuwqJOQyRfqXyROBB1CoZLFWzA==",
|
|
||||||
"dev": true,
|
|
||||||
"license": "MIT",
|
|
||||||
"dependencies": {
|
|
||||||
"@types/node": "*",
|
|
||||||
"@types/tough-cookie": "*",
|
|
||||||
"parse5": "^7.0.0"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/@types/json-schema": {
|
"node_modules/@types/json-schema": {
|
||||||
"version": "7.0.15",
|
"version": "7.0.15",
|
||||||
"resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz",
|
"resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz",
|
||||||
@@ -1873,13 +1665,6 @@
|
|||||||
"@types/react": "^19.2.0"
|
"@types/react": "^19.2.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@types/tough-cookie": {
|
|
||||||
"version": "4.0.5",
|
|
||||||
"resolved": "https://registry.npmmirror.com/@types/tough-cookie/-/tough-cookie-4.0.5.tgz",
|
|
||||||
"integrity": "sha512-/Ad8+nIOV7Rl++6f1BdKxFSMgmoqEoYbHRpPcx3JEfv8VRsQe9Z4mCXeJBzxs7mbHY/XOZZuXlRNfhpVPbs6ZA==",
|
|
||||||
"dev": true,
|
|
||||||
"license": "MIT"
|
|
||||||
},
|
|
||||||
"node_modules/@types/trusted-types": {
|
"node_modules/@types/trusted-types": {
|
||||||
"version": "2.0.7",
|
"version": "2.0.7",
|
||||||
"resolved": "https://registry.npmjs.org/@types/trusted-types/-/trusted-types-2.0.7.tgz",
|
"resolved": "https://registry.npmjs.org/@types/trusted-types/-/trusted-types-2.0.7.tgz",
|
||||||
@@ -2225,16 +2010,6 @@
|
|||||||
"acorn": "^6.0.0 || ^7.0.0 || ^8.0.0"
|
"acorn": "^6.0.0 || ^7.0.0 || ^8.0.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/agent-base": {
|
|
||||||
"version": "7.1.4",
|
|
||||||
"resolved": "https://registry.npmmirror.com/agent-base/-/agent-base-7.1.4.tgz",
|
|
||||||
"integrity": "sha512-MnA+YT8fwfJPgBx3m60MNqakm30XOkyIoH1y6huTQvC0PwZG7ki8NacLBcrPbNoo8vEZy7Jpuk7+jMO+CUovTQ==",
|
|
||||||
"dev": true,
|
|
||||||
"license": "MIT",
|
|
||||||
"engines": {
|
|
||||||
"node": ">= 14"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/ajv": {
|
"node_modules/ajv": {
|
||||||
"version": "6.15.0",
|
"version": "6.15.0",
|
||||||
"resolved": "https://registry.npmjs.org/ajv/-/ajv-6.15.0.tgz",
|
"resolved": "https://registry.npmjs.org/ajv/-/ajv-6.15.0.tgz",
|
||||||
@@ -2252,42 +2027,6 @@
|
|||||||
"url": "https://github.com/sponsors/epoberezkin"
|
"url": "https://github.com/sponsors/epoberezkin"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/ansi-regex": {
|
|
||||||
"version": "5.0.1",
|
|
||||||
"resolved": "https://registry.npmmirror.com/ansi-regex/-/ansi-regex-5.0.1.tgz",
|
|
||||||
"integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==",
|
|
||||||
"dev": true,
|
|
||||||
"license": "MIT",
|
|
||||||
"peer": true,
|
|
||||||
"engines": {
|
|
||||||
"node": ">=8"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/ansi-styles": {
|
|
||||||
"version": "5.2.0",
|
|
||||||
"resolved": "https://registry.npmmirror.com/ansi-styles/-/ansi-styles-5.2.0.tgz",
|
|
||||||
"integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==",
|
|
||||||
"dev": true,
|
|
||||||
"license": "MIT",
|
|
||||||
"peer": true,
|
|
||||||
"engines": {
|
|
||||||
"node": ">=10"
|
|
||||||
},
|
|
||||||
"funding": {
|
|
||||||
"url": "https://github.com/chalk/ansi-styles?sponsor=1"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/aria-query": {
|
|
||||||
"version": "5.3.0",
|
|
||||||
"resolved": "https://registry.npmmirror.com/aria-query/-/aria-query-5.3.0.tgz",
|
|
||||||
"integrity": "sha512-b0P0sZPKtyu8HkeRAfCq0IfURZK+SuwMjY1UXGBU27wpAiTwQAIlq56IbIO+ytk/JjS1fMR14ee5WBBfKi5J6A==",
|
|
||||||
"dev": true,
|
|
||||||
"license": "Apache-2.0",
|
|
||||||
"peer": true,
|
|
||||||
"dependencies": {
|
|
||||||
"dequal": "^2.0.3"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/attr-accept": {
|
"node_modules/attr-accept": {
|
||||||
"version": "2.2.5",
|
"version": "2.2.5",
|
||||||
"resolved": "https://registry.npmjs.org/attr-accept/-/attr-accept-2.2.5.tgz",
|
"resolved": "https://registry.npmjs.org/attr-accept/-/attr-accept-2.2.5.tgz",
|
||||||
@@ -2520,20 +2259,6 @@
|
|||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"peer": true
|
"peer": true
|
||||||
},
|
},
|
||||||
"node_modules/cssstyle": {
|
|
||||||
"version": "4.6.0",
|
|
||||||
"resolved": "https://registry.npmmirror.com/cssstyle/-/cssstyle-4.6.0.tgz",
|
|
||||||
"integrity": "sha512-2z+rWdzbbSZv6/rhtvzvqeZQHrBaqgogqt85sqFNbabZOuFbCVFb8kPeEtZjiKkbrm395irpNKiYeFeLiQnFPg==",
|
|
||||||
"dev": true,
|
|
||||||
"license": "MIT",
|
|
||||||
"dependencies": {
|
|
||||||
"@asamuzakjp/css-color": "^3.2.0",
|
|
||||||
"rrweb-cssom": "^0.8.0"
|
|
||||||
},
|
|
||||||
"engines": {
|
|
||||||
"node": ">=18"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/csstype": {
|
"node_modules/csstype": {
|
||||||
"version": "3.2.3",
|
"version": "3.2.3",
|
||||||
"resolved": "https://registry.npmjs.org/csstype/-/csstype-3.2.3.tgz",
|
"resolved": "https://registry.npmjs.org/csstype/-/csstype-3.2.3.tgz",
|
||||||
@@ -2645,20 +2370,6 @@
|
|||||||
"node": ">=12"
|
"node": ">=12"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/data-urls": {
|
|
||||||
"version": "5.0.0",
|
|
||||||
"resolved": "https://registry.npmmirror.com/data-urls/-/data-urls-5.0.0.tgz",
|
|
||||||
"integrity": "sha512-ZYP5VBHshaDAiVZxjbRVcFJpc+4xGgT0bK3vzy1HLN8jTO975HEbuYzZJcHoQEY5K1a0z8YayJkyVETa08eNTg==",
|
|
||||||
"dev": true,
|
|
||||||
"license": "MIT",
|
|
||||||
"dependencies": {
|
|
||||||
"whatwg-mimetype": "^4.0.0",
|
|
||||||
"whatwg-url": "^14.0.0"
|
|
||||||
},
|
|
||||||
"engines": {
|
|
||||||
"node": ">=18"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/debug": {
|
"node_modules/debug": {
|
||||||
"version": "4.4.3",
|
"version": "4.4.3",
|
||||||
"resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz",
|
"resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz",
|
||||||
@@ -2676,13 +2387,6 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/decimal.js": {
|
|
||||||
"version": "10.6.0",
|
|
||||||
"resolved": "https://registry.npmmirror.com/decimal.js/-/decimal.js-10.6.0.tgz",
|
|
||||||
"integrity": "sha512-YpgQiITW3JXGntzdUmyUR1V812Hn8T1YVXhCu+wO3OpS4eU9l4YdD3qjyiKdV6mvV29zapkMeD390UVEf2lkUg==",
|
|
||||||
"dev": true,
|
|
||||||
"license": "MIT"
|
|
||||||
},
|
|
||||||
"node_modules/decode-named-character-reference": {
|
"node_modules/decode-named-character-reference": {
|
||||||
"version": "1.3.0",
|
"version": "1.3.0",
|
||||||
"resolved": "https://registry.npmjs.org/decode-named-character-reference/-/decode-named-character-reference-1.3.0.tgz",
|
"resolved": "https://registry.npmjs.org/decode-named-character-reference/-/decode-named-character-reference-1.3.0.tgz",
|
||||||
@@ -2745,14 +2449,6 @@
|
|||||||
"@babel/runtime": "^7.9.2"
|
"@babel/runtime": "^7.9.2"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/dom-accessibility-api": {
|
|
||||||
"version": "0.5.16",
|
|
||||||
"resolved": "https://registry.npmmirror.com/dom-accessibility-api/-/dom-accessibility-api-0.5.16.tgz",
|
|
||||||
"integrity": "sha512-X7BJ2yElsnOJ30pZF4uIIDfBEVgF4XEBxL9Bxhy6dnrm5hkzqmsWHGTiHqRiITNhMyFLyAiWndIJP7Z1NTteDg==",
|
|
||||||
"dev": true,
|
|
||||||
"license": "MIT",
|
|
||||||
"peer": true
|
|
||||||
},
|
|
||||||
"node_modules/dompurify": {
|
"node_modules/dompurify": {
|
||||||
"version": "3.4.13",
|
"version": "3.4.13",
|
||||||
"resolved": "https://registry.npmjs.org/dompurify/-/dompurify-3.4.13.tgz",
|
"resolved": "https://registry.npmjs.org/dompurify/-/dompurify-3.4.13.tgz",
|
||||||
@@ -2770,19 +2466,6 @@
|
|||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "ISC"
|
"license": "ISC"
|
||||||
},
|
},
|
||||||
"node_modules/entities": {
|
|
||||||
"version": "6.0.1",
|
|
||||||
"resolved": "https://registry.npmmirror.com/entities/-/entities-6.0.1.tgz",
|
|
||||||
"integrity": "sha512-aN97NXWF6AWBTahfVOIrB/NShkzi5H7F9r1s9mD3cDj4Ko5f2qhhVoYMibXF7GlLveb/D2ioWay8lxI97Ven3g==",
|
|
||||||
"dev": true,
|
|
||||||
"license": "BSD-2-Clause",
|
|
||||||
"engines": {
|
|
||||||
"node": ">=0.12"
|
|
||||||
},
|
|
||||||
"funding": {
|
|
||||||
"url": "https://github.com/fb55/entities?sponsor=1"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/esbuild": {
|
"node_modules/esbuild": {
|
||||||
"version": "0.28.1",
|
"version": "0.28.1",
|
||||||
"resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.28.1.tgz",
|
"resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.28.1.tgz",
|
||||||
@@ -3375,19 +3058,6 @@
|
|||||||
"react-is": "^16.7.0"
|
"react-is": "^16.7.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/html-encoding-sniffer": {
|
|
||||||
"version": "4.0.0",
|
|
||||||
"resolved": "https://registry.npmmirror.com/html-encoding-sniffer/-/html-encoding-sniffer-4.0.0.tgz",
|
|
||||||
"integrity": "sha512-Y22oTqIU4uuPgEemfz7NDJz6OeKf12Lsu+QC+s3BVpda64lTiMYCyGwg5ki4vFxkMwQdeZDl2adZoqUgdFuTgQ==",
|
|
||||||
"dev": true,
|
|
||||||
"license": "MIT",
|
|
||||||
"dependencies": {
|
|
||||||
"whatwg-encoding": "^3.1.1"
|
|
||||||
},
|
|
||||||
"engines": {
|
|
||||||
"node": ">=18"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/html-url-attributes": {
|
"node_modules/html-url-attributes": {
|
||||||
"version": "3.0.1",
|
"version": "3.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/html-url-attributes/-/html-url-attributes-3.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/html-url-attributes/-/html-url-attributes-3.0.1.tgz",
|
||||||
@@ -3398,47 +3068,6 @@
|
|||||||
"url": "https://opencollective.com/unified"
|
"url": "https://opencollective.com/unified"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/http-proxy-agent": {
|
|
||||||
"version": "7.0.2",
|
|
||||||
"resolved": "https://registry.npmmirror.com/http-proxy-agent/-/http-proxy-agent-7.0.2.tgz",
|
|
||||||
"integrity": "sha512-T1gkAiYYDWYx3V5Bmyu7HcfcvL7mUrTWiM6yOfa3PIphViJ/gFPbvidQ+veqSOHci/PxBcDabeUNCzpOODJZig==",
|
|
||||||
"dev": true,
|
|
||||||
"license": "MIT",
|
|
||||||
"dependencies": {
|
|
||||||
"agent-base": "^7.1.0",
|
|
||||||
"debug": "^4.3.4"
|
|
||||||
},
|
|
||||||
"engines": {
|
|
||||||
"node": ">= 14"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/https-proxy-agent": {
|
|
||||||
"version": "7.0.6",
|
|
||||||
"resolved": "https://registry.npmmirror.com/https-proxy-agent/-/https-proxy-agent-7.0.6.tgz",
|
|
||||||
"integrity": "sha512-vK9P5/iUfdl95AI+JVyUuIcVtd4ofvtrOr3HNtM2yxC9bnMbEdp3x01OhQNnjb8IJYi38VlTE3mBXwcfvywuSw==",
|
|
||||||
"dev": true,
|
|
||||||
"license": "MIT",
|
|
||||||
"dependencies": {
|
|
||||||
"agent-base": "^7.1.2",
|
|
||||||
"debug": "4"
|
|
||||||
},
|
|
||||||
"engines": {
|
|
||||||
"node": ">= 14"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/iconv-lite": {
|
|
||||||
"version": "0.6.3",
|
|
||||||
"resolved": "https://registry.npmmirror.com/iconv-lite/-/iconv-lite-0.6.3.tgz",
|
|
||||||
"integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==",
|
|
||||||
"dev": true,
|
|
||||||
"license": "MIT",
|
|
||||||
"dependencies": {
|
|
||||||
"safer-buffer": ">= 2.1.2 < 3.0.0"
|
|
||||||
},
|
|
||||||
"engines": {
|
|
||||||
"node": ">=0.10.0"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/ignore": {
|
"node_modules/ignore": {
|
||||||
"version": "5.3.2",
|
"version": "5.3.2",
|
||||||
"resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz",
|
"resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz",
|
||||||
@@ -3544,13 +3173,6 @@
|
|||||||
"url": "https://github.com/sponsors/sindresorhus"
|
"url": "https://github.com/sponsors/sindresorhus"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/is-potential-custom-element-name": {
|
|
||||||
"version": "1.0.1",
|
|
||||||
"resolved": "https://registry.npmmirror.com/is-potential-custom-element-name/-/is-potential-custom-element-name-1.0.1.tgz",
|
|
||||||
"integrity": "sha512-bCYeRA2rVibKZd+s2625gGnGF/t7DSqDs4dP7CrLA1m7jKWz6pps0LpYLJN8Q64HtmPKJ1hrN3nzPNKFEKOUiQ==",
|
|
||||||
"dev": true,
|
|
||||||
"license": "MIT"
|
|
||||||
},
|
|
||||||
"node_modules/isexe": {
|
"node_modules/isexe": {
|
||||||
"version": "2.0.0",
|
"version": "2.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz",
|
||||||
@@ -3564,46 +3186,6 @@
|
|||||||
"integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==",
|
"integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==",
|
||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
"node_modules/jsdom": {
|
|
||||||
"version": "26.1.0",
|
|
||||||
"resolved": "https://registry.npmmirror.com/jsdom/-/jsdom-26.1.0.tgz",
|
|
||||||
"integrity": "sha512-Cvc9WUhxSMEo4McES3P7oK3QaXldCfNWp7pl2NNeiIFlCoLr3kfq9kb1fxftiwk1FLV7CvpvDfonxtzUDeSOPg==",
|
|
||||||
"dev": true,
|
|
||||||
"license": "MIT",
|
|
||||||
"dependencies": {
|
|
||||||
"cssstyle": "^4.2.1",
|
|
||||||
"data-urls": "^5.0.0",
|
|
||||||
"decimal.js": "^10.5.0",
|
|
||||||
"html-encoding-sniffer": "^4.0.0",
|
|
||||||
"http-proxy-agent": "^7.0.2",
|
|
||||||
"https-proxy-agent": "^7.0.6",
|
|
||||||
"is-potential-custom-element-name": "^1.0.1",
|
|
||||||
"nwsapi": "^2.2.16",
|
|
||||||
"parse5": "^7.2.1",
|
|
||||||
"rrweb-cssom": "^0.8.0",
|
|
||||||
"saxes": "^6.0.0",
|
|
||||||
"symbol-tree": "^3.2.4",
|
|
||||||
"tough-cookie": "^5.1.1",
|
|
||||||
"w3c-xmlserializer": "^5.0.0",
|
|
||||||
"webidl-conversions": "^7.0.0",
|
|
||||||
"whatwg-encoding": "^3.1.1",
|
|
||||||
"whatwg-mimetype": "^4.0.0",
|
|
||||||
"whatwg-url": "^14.1.1",
|
|
||||||
"ws": "^8.18.0",
|
|
||||||
"xml-name-validator": "^5.0.0"
|
|
||||||
},
|
|
||||||
"engines": {
|
|
||||||
"node": ">=18"
|
|
||||||
},
|
|
||||||
"peerDependencies": {
|
|
||||||
"canvas": "^3.0.0"
|
|
||||||
},
|
|
||||||
"peerDependenciesMeta": {
|
|
||||||
"canvas": {
|
|
||||||
"optional": true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/jsesc": {
|
"node_modules/jsesc": {
|
||||||
"version": "3.1.0",
|
"version": "3.1.0",
|
||||||
"resolved": "https://registry.npmjs.org/jsesc/-/jsesc-3.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/jsesc/-/jsesc-3.1.0.tgz",
|
||||||
@@ -3739,17 +3321,6 @@
|
|||||||
"react": "^16.5.1 || ^17.0.0 || ^18.0.0 || ^19.0.0"
|
"react": "^16.5.1 || ^17.0.0 || ^18.0.0 || ^19.0.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/lz-string": {
|
|
||||||
"version": "1.5.0",
|
|
||||||
"resolved": "https://registry.npmmirror.com/lz-string/-/lz-string-1.5.0.tgz",
|
|
||||||
"integrity": "sha512-h5bgJWpxJNswbU7qCrV0tIKQCaS3blPDrqKWx+QxzuzL1zGUzij9XCWLrSLsJPu5t+eWA/ycetzYAO5IOMcWAQ==",
|
|
||||||
"dev": true,
|
|
||||||
"license": "MIT",
|
|
||||||
"peer": true,
|
|
||||||
"bin": {
|
|
||||||
"lz-string": "bin/bin.js"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/markdown-table": {
|
"node_modules/markdown-table": {
|
||||||
"version": "3.0.4",
|
"version": "3.0.4",
|
||||||
"resolved": "https://registry.npmjs.org/markdown-table/-/markdown-table-3.0.4.tgz",
|
"resolved": "https://registry.npmjs.org/markdown-table/-/markdown-table-3.0.4.tgz",
|
||||||
@@ -4712,13 +4283,6 @@
|
|||||||
"node": ">=18"
|
"node": ">=18"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/nwsapi": {
|
|
||||||
"version": "2.2.27",
|
|
||||||
"resolved": "https://registry.npmmirror.com/nwsapi/-/nwsapi-2.2.27.tgz",
|
|
||||||
"integrity": "sha512-gQPNF78qebCQ6tvVFBYrvJdBNOrYZm90ZlXgpIFm06p6qHDHq/XC4TnJftN6OMbxVE0UTBAoRgcsDeJBBooITw==",
|
|
||||||
"dev": true,
|
|
||||||
"license": "MIT"
|
|
||||||
},
|
|
||||||
"node_modules/object-assign": {
|
"node_modules/object-assign": {
|
||||||
"version": "4.1.1",
|
"version": "4.1.1",
|
||||||
"resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz",
|
"resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz",
|
||||||
@@ -4818,19 +4382,6 @@
|
|||||||
"integrity": "sha512-CmBKiL6NNo/OqgmMn95Fk9Whlp2mtvIv+KNpQKN2F4SjvrEesubTRWGYSg+BnWZOnlCaSTU1sMpsBOzgbYhnsA==",
|
"integrity": "sha512-CmBKiL6NNo/OqgmMn95Fk9Whlp2mtvIv+KNpQKN2F4SjvrEesubTRWGYSg+BnWZOnlCaSTU1sMpsBOzgbYhnsA==",
|
||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
"node_modules/parse5": {
|
|
||||||
"version": "7.3.0",
|
|
||||||
"resolved": "https://registry.npmmirror.com/parse5/-/parse5-7.3.0.tgz",
|
|
||||||
"integrity": "sha512-IInvU7fabl34qmi9gY8XOVxhYyMyuH2xUNpb2q8/Y+7552KlejkRvqvD19nMoUW/uQGGbqNpA6Tufu5FL5BZgw==",
|
|
||||||
"dev": true,
|
|
||||||
"license": "MIT",
|
|
||||||
"dependencies": {
|
|
||||||
"entities": "^6.0.0"
|
|
||||||
},
|
|
||||||
"funding": {
|
|
||||||
"url": "https://github.com/inikulin/parse5?sponsor=1"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/path-exists": {
|
"node_modules/path-exists": {
|
||||||
"version": "4.0.0",
|
"version": "4.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz",
|
||||||
@@ -4954,30 +4505,6 @@
|
|||||||
"node": ">= 0.8.0"
|
"node": ">= 0.8.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/pretty-format": {
|
|
||||||
"version": "27.5.1",
|
|
||||||
"resolved": "https://registry.npmmirror.com/pretty-format/-/pretty-format-27.5.1.tgz",
|
|
||||||
"integrity": "sha512-Qb1gy5OrP5+zDf2Bvnzdl3jsTf1qXVMazbvCoKhtKqVs4/YK4ozX4gKQJJVyNe+cajNPn0KoC0MC3FUmaHWEmQ==",
|
|
||||||
"dev": true,
|
|
||||||
"license": "MIT",
|
|
||||||
"peer": true,
|
|
||||||
"dependencies": {
|
|
||||||
"ansi-regex": "^5.0.1",
|
|
||||||
"ansi-styles": "^5.0.0",
|
|
||||||
"react-is": "^17.0.1"
|
|
||||||
},
|
|
||||||
"engines": {
|
|
||||||
"node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/pretty-format/node_modules/react-is": {
|
|
||||||
"version": "17.0.2",
|
|
||||||
"resolved": "https://registry.npmmirror.com/react-is/-/react-is-17.0.2.tgz",
|
|
||||||
"integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==",
|
|
||||||
"dev": true,
|
|
||||||
"license": "MIT",
|
|
||||||
"peer": true
|
|
||||||
},
|
|
||||||
"node_modules/prop-types": {
|
"node_modules/prop-types": {
|
||||||
"version": "15.8.1",
|
"version": "15.8.1",
|
||||||
"resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz",
|
"resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz",
|
||||||
@@ -5290,33 +4817,6 @@
|
|||||||
"fsevents": "~2.3.2"
|
"fsevents": "~2.3.2"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/rrweb-cssom": {
|
|
||||||
"version": "0.8.0",
|
|
||||||
"resolved": "https://registry.npmmirror.com/rrweb-cssom/-/rrweb-cssom-0.8.0.tgz",
|
|
||||||
"integrity": "sha512-guoltQEx+9aMf2gDZ0s62EcV8lsXR+0w8915TC3ITdn2YueuNjdAYh/levpU9nFaoChh9RUS5ZdQMrKfVEN9tw==",
|
|
||||||
"dev": true,
|
|
||||||
"license": "MIT"
|
|
||||||
},
|
|
||||||
"node_modules/safer-buffer": {
|
|
||||||
"version": "2.1.2",
|
|
||||||
"resolved": "https://registry.npmmirror.com/safer-buffer/-/safer-buffer-2.1.2.tgz",
|
|
||||||
"integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==",
|
|
||||||
"dev": true,
|
|
||||||
"license": "MIT"
|
|
||||||
},
|
|
||||||
"node_modules/saxes": {
|
|
||||||
"version": "6.0.0",
|
|
||||||
"resolved": "https://registry.npmmirror.com/saxes/-/saxes-6.0.0.tgz",
|
|
||||||
"integrity": "sha512-xAg7SOnEhrm5zI3puOOKyy1OMcMlIJZYNJY7xLBwSze0UjhPLnWfj2GF2EpT0jmzaJKIWKHLsaSSajf35bcYnA==",
|
|
||||||
"dev": true,
|
|
||||||
"license": "ISC",
|
|
||||||
"dependencies": {
|
|
||||||
"xmlchars": "^2.2.0"
|
|
||||||
},
|
|
||||||
"engines": {
|
|
||||||
"node": ">=v12.22.7"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/scheduler": {
|
"node_modules/scheduler": {
|
||||||
"version": "0.27.0",
|
"version": "0.27.0",
|
||||||
"resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.27.0.tgz",
|
"resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.27.0.tgz",
|
||||||
@@ -5424,13 +4924,6 @@
|
|||||||
"inline-style-parser": "0.2.7"
|
"inline-style-parser": "0.2.7"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/symbol-tree": {
|
|
||||||
"version": "3.2.4",
|
|
||||||
"resolved": "https://registry.npmmirror.com/symbol-tree/-/symbol-tree-3.2.4.tgz",
|
|
||||||
"integrity": "sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw==",
|
|
||||||
"dev": true,
|
|
||||||
"license": "MIT"
|
|
||||||
},
|
|
||||||
"node_modules/tinyglobby": {
|
"node_modules/tinyglobby": {
|
||||||
"version": "0.2.16",
|
"version": "0.2.16",
|
||||||
"resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.16.tgz",
|
"resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.16.tgz",
|
||||||
@@ -5448,52 +4941,6 @@
|
|||||||
"url": "https://github.com/sponsors/SuperchupuDev"
|
"url": "https://github.com/sponsors/SuperchupuDev"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/tldts": {
|
|
||||||
"version": "6.1.86",
|
|
||||||
"resolved": "https://registry.npmmirror.com/tldts/-/tldts-6.1.86.tgz",
|
|
||||||
"integrity": "sha512-WMi/OQ2axVTf/ykqCQgXiIct+mSQDFdH2fkwhPwgEwvJ1kSzZRiinb0zF2Xb8u4+OqPChmyI6MEu4EezNJz+FQ==",
|
|
||||||
"dev": true,
|
|
||||||
"license": "MIT",
|
|
||||||
"dependencies": {
|
|
||||||
"tldts-core": "^6.1.86"
|
|
||||||
},
|
|
||||||
"bin": {
|
|
||||||
"tldts": "bin/cli.js"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/tldts-core": {
|
|
||||||
"version": "6.1.86",
|
|
||||||
"resolved": "https://registry.npmmirror.com/tldts-core/-/tldts-core-6.1.86.tgz",
|
|
||||||
"integrity": "sha512-Je6p7pkk+KMzMv2XXKmAE3McmolOQFdxkKw0R8EYNr7sELW46JqnNeTX8ybPiQgvg1ymCoF8LXs5fzFaZvJPTA==",
|
|
||||||
"dev": true,
|
|
||||||
"license": "MIT"
|
|
||||||
},
|
|
||||||
"node_modules/tough-cookie": {
|
|
||||||
"version": "5.1.2",
|
|
||||||
"resolved": "https://registry.npmmirror.com/tough-cookie/-/tough-cookie-5.1.2.tgz",
|
|
||||||
"integrity": "sha512-FVDYdxtnj0G6Qm/DhNPSb8Ju59ULcup3tuJxkFb5K8Bv2pUXILbf0xZWU8PX8Ov19OXljbUyveOFwRMwkXzO+A==",
|
|
||||||
"dev": true,
|
|
||||||
"license": "BSD-3-Clause",
|
|
||||||
"dependencies": {
|
|
||||||
"tldts": "^6.1.32"
|
|
||||||
},
|
|
||||||
"engines": {
|
|
||||||
"node": ">=16"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/tr46": {
|
|
||||||
"version": "5.1.1",
|
|
||||||
"resolved": "https://registry.npmmirror.com/tr46/-/tr46-5.1.1.tgz",
|
|
||||||
"integrity": "sha512-hdF5ZgjTqgAntKkklYw0R03MG2x/bSzTtkxmIRw/sTNV8YXsCJ1tfLAX23lhxhHJlEf3CRCOCGGWw3vI3GaSPw==",
|
|
||||||
"dev": true,
|
|
||||||
"license": "MIT",
|
|
||||||
"dependencies": {
|
|
||||||
"punycode": "^2.3.1"
|
|
||||||
},
|
|
||||||
"engines": {
|
|
||||||
"node": ">=18"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/trim-lines": {
|
"node_modules/trim-lines": {
|
||||||
"version": "3.0.1",
|
"version": "3.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/trim-lines/-/trim-lines-3.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/trim-lines/-/trim-lines-3.0.1.tgz",
|
||||||
@@ -5917,67 +5364,6 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/w3c-xmlserializer": {
|
|
||||||
"version": "5.0.0",
|
|
||||||
"resolved": "https://registry.npmmirror.com/w3c-xmlserializer/-/w3c-xmlserializer-5.0.0.tgz",
|
|
||||||
"integrity": "sha512-o8qghlI8NZHU1lLPrpi2+Uq7abh4GGPpYANlalzWxyWteJOCsr/P+oPBA49TOLu5FTZO4d3F9MnWJfiMo4BkmA==",
|
|
||||||
"dev": true,
|
|
||||||
"license": "MIT",
|
|
||||||
"dependencies": {
|
|
||||||
"xml-name-validator": "^5.0.0"
|
|
||||||
},
|
|
||||||
"engines": {
|
|
||||||
"node": ">=18"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/webidl-conversions": {
|
|
||||||
"version": "7.0.0",
|
|
||||||
"resolved": "https://registry.npmmirror.com/webidl-conversions/-/webidl-conversions-7.0.0.tgz",
|
|
||||||
"integrity": "sha512-VwddBukDzu71offAQR975unBIGqfKZpM+8ZX6ySk8nYhVoo5CYaZyzt3YBvYtRtO+aoGlqxPg/B87NGVZ/fu6g==",
|
|
||||||
"dev": true,
|
|
||||||
"license": "BSD-2-Clause",
|
|
||||||
"engines": {
|
|
||||||
"node": ">=12"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/whatwg-encoding": {
|
|
||||||
"version": "3.1.1",
|
|
||||||
"resolved": "https://registry.npmmirror.com/whatwg-encoding/-/whatwg-encoding-3.1.1.tgz",
|
|
||||||
"integrity": "sha512-6qN4hJdMwfYBtE3YBTTHhoeuUrDBPZmbQaxWAqSALV/MeEnR5z1xd8UKud2RAkFoPkmB+hli1TZSnyi84xz1vQ==",
|
|
||||||
"deprecated": "Use @exodus/bytes instead for a more spec-conformant and faster implementation",
|
|
||||||
"dev": true,
|
|
||||||
"license": "MIT",
|
|
||||||
"dependencies": {
|
|
||||||
"iconv-lite": "0.6.3"
|
|
||||||
},
|
|
||||||
"engines": {
|
|
||||||
"node": ">=18"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/whatwg-mimetype": {
|
|
||||||
"version": "4.0.0",
|
|
||||||
"resolved": "https://registry.npmmirror.com/whatwg-mimetype/-/whatwg-mimetype-4.0.0.tgz",
|
|
||||||
"integrity": "sha512-QaKxh0eNIi2mE9p2vEdzfagOKHCcj1pJ56EEHGQOVxp8r9/iszLUUV7v89x9O1p/T+NlTM5W7jW6+cz4Fq1YVg==",
|
|
||||||
"dev": true,
|
|
||||||
"license": "MIT",
|
|
||||||
"engines": {
|
|
||||||
"node": ">=18"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/whatwg-url": {
|
|
||||||
"version": "14.2.0",
|
|
||||||
"resolved": "https://registry.npmmirror.com/whatwg-url/-/whatwg-url-14.2.0.tgz",
|
|
||||||
"integrity": "sha512-De72GdQZzNTUBBChsXueQUnPKDkg/5A5zp7pFDuQAj5UFoENpiACU0wlCvzpAGnTkj++ihpKwKyYewn/XNUbKw==",
|
|
||||||
"dev": true,
|
|
||||||
"license": "MIT",
|
|
||||||
"dependencies": {
|
|
||||||
"tr46": "^5.1.0",
|
|
||||||
"webidl-conversions": "^7.0.0"
|
|
||||||
},
|
|
||||||
"engines": {
|
|
||||||
"node": ">=18"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/which": {
|
"node_modules/which": {
|
||||||
"version": "2.0.2",
|
"version": "2.0.2",
|
||||||
"resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz",
|
"resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz",
|
||||||
@@ -6004,45 +5390,6 @@
|
|||||||
"node": ">=0.10.0"
|
"node": ">=0.10.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/ws": {
|
|
||||||
"version": "8.21.3",
|
|
||||||
"resolved": "https://registry.npmmirror.com/ws/-/ws-8.21.3.tgz",
|
|
||||||
"integrity": "sha512-201TZ/kPWxoPr/OKWjquZR1SWKXcvxdH+e1xrx89b3YbmzLMFCLfnaG1HFIgWzJOEWZ7MvpK++odZufgYR50Rw==",
|
|
||||||
"dev": true,
|
|
||||||
"license": "MIT",
|
|
||||||
"engines": {
|
|
||||||
"node": ">=10.0.0"
|
|
||||||
},
|
|
||||||
"peerDependencies": {
|
|
||||||
"bufferutil": "^4.0.1",
|
|
||||||
"utf-8-validate": ">=5.0.2"
|
|
||||||
},
|
|
||||||
"peerDependenciesMeta": {
|
|
||||||
"bufferutil": {
|
|
||||||
"optional": true
|
|
||||||
},
|
|
||||||
"utf-8-validate": {
|
|
||||||
"optional": true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/xml-name-validator": {
|
|
||||||
"version": "5.0.0",
|
|
||||||
"resolved": "https://registry.npmmirror.com/xml-name-validator/-/xml-name-validator-5.0.0.tgz",
|
|
||||||
"integrity": "sha512-EvGK8EJ3DhaHfbRlETOWAS5pO9MZITeauHKJyb8wyajUfQUenkIg2MvLDTZ4T/TgIcm3HU0TFBgWWboAZ30UHg==",
|
|
||||||
"dev": true,
|
|
||||||
"license": "Apache-2.0",
|
|
||||||
"engines": {
|
|
||||||
"node": ">=18"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/xmlchars": {
|
|
||||||
"version": "2.2.0",
|
|
||||||
"resolved": "https://registry.npmmirror.com/xmlchars/-/xmlchars-2.2.0.tgz",
|
|
||||||
"integrity": "sha512-JZnDKK8B0RCDw84FNdDAIpZK+JuJw+s7Lz8nksI7SIuU3UXJJslUthsi+uWBUYOwPFwW7W7PRLRfUKpxjtjFCw==",
|
|
||||||
"dev": true,
|
|
||||||
"license": "MIT"
|
|
||||||
},
|
|
||||||
"node_modules/xss": {
|
"node_modules/xss": {
|
||||||
"version": "1.0.15",
|
"version": "1.0.15",
|
||||||
"resolved": "https://registry.npmjs.org/xss/-/xss-1.0.15.tgz",
|
"resolved": "https://registry.npmjs.org/xss/-/xss-1.0.15.tgz",
|
||||||
|
|||||||
@@ -9,9 +9,8 @@
|
|||||||
"lint": "eslint .",
|
"lint": "eslint .",
|
||||||
"preview": "vite preview",
|
"preview": "vite preview",
|
||||||
"test:graph-store": "node --test tests/graphStore.multi-edge.test.mjs",
|
"test:graph-store": "node --test tests/graphStore.multi-edge.test.mjs",
|
||||||
"test:graph-workspace": "node --import tsx --test tests/markdownContentViewer.test.ts tests/markdownEditorInteraction.test.tsx tests/markdownEditorState.test.ts tests/nodeMarkdownSync.test.ts tests/graphSceneState.display.test.ts tests/temporalLifecycle.test.ts tests/temporalScrubberBounds.test.ts tests/deterministicExplorerRendering.test.ts tests/explorerCapabilities.test.tsx tests/smallGraphLayout.test.ts tests/realtimeGraphAttributes.test.ts tests/ontologyEditorModel.test.ts tests/graphColorLegend.test.ts tests/ontologyUrlState.test.ts",
|
"test:graph-workspace": "node --import tsx --test tests/markdownContentViewer.test.ts tests/graphSceneState.display.test.ts tests/temporalLifecycle.test.ts tests/deterministicExplorerRendering.test.ts tests/smallGraphLayout.test.ts tests/realtimeGraphAttributes.test.ts",
|
||||||
"test:deterministic-e2e": "node --import tsx --test tests/deterministicExplorerRendering.e2e.ts",
|
"test:deterministic-e2e": "node --import tsx --test tests/deterministicExplorerRendering.e2e.ts",
|
||||||
"test:graph-legend-e2e": "node --import tsx --test tests/graphColorLegend.e2e.ts",
|
|
||||||
"test:plugin-registry": "node --import tsx --test tests/pluginRegistry.temporal.test.mjs"
|
"test:plugin-registry": "node --import tsx --test tests/pluginRegistry.temporal.test.mjs"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
@@ -40,9 +39,7 @@
|
|||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@babel/core": "^7.29.6",
|
"@babel/core": "^7.29.6",
|
||||||
"@eslint/js": "^9.39.4",
|
"@eslint/js": "^9.39.4",
|
||||||
"@testing-library/react": "^16.3.3",
|
|
||||||
"@types/babel__core": "^7.20.5",
|
"@types/babel__core": "^7.20.5",
|
||||||
"@types/jsdom": "^21.1.7",
|
|
||||||
"@types/node": "^24.12.0",
|
"@types/node": "^24.12.0",
|
||||||
"@types/react": "^19.2.14",
|
"@types/react": "^19.2.14",
|
||||||
"@types/react-dom": "^19.2.3",
|
"@types/react-dom": "^19.2.3",
|
||||||
@@ -52,7 +49,6 @@
|
|||||||
"eslint-plugin-react-hooks": "^7.0.1",
|
"eslint-plugin-react-hooks": "^7.0.1",
|
||||||
"eslint-plugin-react-refresh": "^0.5.2",
|
"eslint-plugin-react-refresh": "^0.5.2",
|
||||||
"globals": "^17.4.0",
|
"globals": "^17.4.0",
|
||||||
"jsdom": "^26.1.0",
|
|
||||||
"tsx": "^4.21.0",
|
"tsx": "^4.21.0",
|
||||||
"typescript": "~5.9.3",
|
"typescript": "~5.9.3",
|
||||||
"typescript-eslint": "^8.57.0",
|
"typescript-eslint": "^8.57.0",
|
||||||
|
|||||||
+15
-51
@@ -17,14 +17,10 @@ import {
|
|||||||
type LucideIcon,
|
type LucideIcon,
|
||||||
} from 'lucide-react';
|
} from 'lucide-react';
|
||||||
import { ErrorBoundary } from './ErrorBoundary';
|
import { ErrorBoundary } from './ErrorBoundary';
|
||||||
import { ExploreWorkspaceTabs, type ExploreView } from './ExploreWorkspaceTabs';
|
|
||||||
import { fetchAgentMemoryAvailability } from './explorerCapabilities';
|
|
||||||
import { hasOntologyUrlState } from './workspaces/OntologyWorkspace/ontologyUrlState';
|
|
||||||
|
|
||||||
const DecisionWorkspace = lazy(() => import('./workspaces/DecisionWorkspace/DecisionWorkspace').then((module) => ({ default: module.DecisionWorkspace })));
|
const DecisionWorkspace = lazy(() => import('./workspaces/DecisionWorkspace/DecisionWorkspace').then((module) => ({ default: module.DecisionWorkspace })));
|
||||||
const DiffMergeWorkspace = lazy(() => import('./workspaces/DiffMergeWorkspace/DiffMergeWorkspace').then((module) => ({ default: module.DiffMergeWorkspace })));
|
const DiffMergeWorkspace = lazy(() => import('./workspaces/DiffMergeWorkspace/DiffMergeWorkspace').then((module) => ({ default: module.DiffMergeWorkspace })));
|
||||||
const GraphWorkspace = lazy(() => import('./workspaces/GraphWorkspace/GraphWorkspace').then((module) => ({ default: module.GraphWorkspace })));
|
const GraphWorkspace = lazy(() => import('./workspaces/GraphWorkspace/GraphWorkspace').then((module) => ({ default: module.GraphWorkspace })));
|
||||||
const MemoryWorkspace = lazy(() => import('./workspaces/MemoryWorkspace').then((module) => ({ default: module.MemoryWorkspace })));
|
|
||||||
const ImportExportWorkspace = lazy(() => import('./workspaces/ImportExportWorkspace/ImportExportWorkspace').then((module) => ({ default: module.ImportExportWorkspace })));
|
const ImportExportWorkspace = lazy(() => import('./workspaces/ImportExportWorkspace/ImportExportWorkspace').then((module) => ({ default: module.ImportExportWorkspace })));
|
||||||
const LineageDiagram = lazy(() => import('./workspaces/LineageWorkspace/LineageDiagram').then((module) => ({ default: module.LineageDiagram })));
|
const LineageDiagram = lazy(() => import('./workspaces/LineageWorkspace/LineageDiagram').then((module) => ({ default: module.LineageDiagram })));
|
||||||
const ReasoningWorkspace = lazy(() => import('./workspaces/ReasoningWorkspace').then((module) => ({ default: module.ReasoningWorkspace })));
|
const ReasoningWorkspace = lazy(() => import('./workspaces/ReasoningWorkspace').then((module) => ({ default: module.ReasoningWorkspace })));
|
||||||
@@ -37,6 +33,7 @@ const OntologySummaryTab = lazy(() => import('./workspaces/ManageWorkspace/Ontol
|
|||||||
const OntologyWorkspace = lazy(() => import('./workspaces/OntologyWorkspace').then((module) => ({ default: module.OntologyWorkspace })));
|
const OntologyWorkspace = lazy(() => import('./workspaces/OntologyWorkspace').then((module) => ({ default: module.OntologyWorkspace })));
|
||||||
|
|
||||||
type WorkspaceId = 'welcome' | 'explore' | 'analyze' | 'decisions' | 'enrich' | 'manage' | 'ontology-hub';
|
type WorkspaceId = 'welcome' | 'explore' | 'analyze' | 'decisions' | 'enrich' | 'manage' | 'ontology-hub';
|
||||||
|
type ExploreView = 'graph' | 'vocabulary';
|
||||||
type AnalyzeView = 'sparql' | 'reasoning';
|
type AnalyzeView = 'sparql' | 'reasoning';
|
||||||
type EnrichView = 'import' | 'merge' | 'registry' | 'resolve';
|
type EnrichView = 'import' | 'merge' | 'registry' | 'resolve';
|
||||||
type ManageView = 'lineage' | 'kg-overview' | 'ontology';
|
type ManageView = 'lineage' | 'kg-overview' | 'ontology';
|
||||||
@@ -96,10 +93,6 @@ const navItems: NavItem[] = [
|
|||||||
{ id: 'ontology-hub', label: 'Ontology Hub', hint: 'Schema governance, registry, and vocabulary management', icon: GitMerge },
|
{ id: 'ontology-hub', label: 'Ontology Hub', hint: 'Schema governance, registry, and vocabulary management', icon: GitMerge },
|
||||||
];
|
];
|
||||||
|
|
||||||
function readInitialWorkspace(): WorkspaceId {
|
|
||||||
return hasOntologyUrlState() ? 'ontology-hub' : 'welcome';
|
|
||||||
}
|
|
||||||
|
|
||||||
const shellStyles = `
|
const shellStyles = `
|
||||||
:root {
|
:root {
|
||||||
--app-bg: #07111f;
|
--app-bg: #07111f;
|
||||||
@@ -1780,43 +1773,12 @@ function WelcomeScreen({
|
|||||||
}
|
}
|
||||||
|
|
||||||
export default function App() {
|
export default function App() {
|
||||||
const [activeWorkspace, setActiveWorkspace] = useState<WorkspaceId>(readInitialWorkspace);
|
const [activeWorkspace, setActiveWorkspace] = useState<WorkspaceId>('welcome');
|
||||||
const [exploreView, setExploreView] = useState<ExploreView>('graph');
|
const [exploreView, setExploreView] = useState<ExploreView>('graph');
|
||||||
const [analyzeView, setAnalyzeView] = useState<AnalyzeView>('reasoning');
|
const [analyzeView, setAnalyzeView] = useState<AnalyzeView>('reasoning');
|
||||||
const [enrichView, setEnrichView] = useState<EnrichView>('import');
|
const [enrichView, setEnrichView] = useState<EnrichView>('import');
|
||||||
const [manageView, setManageView] = useState<ManageView>('lineage');
|
const [manageView, setManageView] = useState<ManageView>('lineage');
|
||||||
const [graphFocusRequest, setGraphFocusRequest] = useState<{ nodeId: string; token: number } | null>(null);
|
const [graphFocusRequest, setGraphFocusRequest] = useState<{ nodeId: string; token: number } | null>(null);
|
||||||
const [exploreDraftDirty, setExploreDraftDirty] = useState(false);
|
|
||||||
const [agentMemoryAvailable, setAgentMemoryAvailable] = useState(false);
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
let active = true;
|
|
||||||
void fetchAgentMemoryAvailability().then((available) => {
|
|
||||||
if (active) setAgentMemoryAvailable(available);
|
|
||||||
});
|
|
||||||
return () => {
|
|
||||||
active = false;
|
|
||||||
};
|
|
||||||
}, []);
|
|
||||||
|
|
||||||
const confirmDiscardExploreDraft = () => (
|
|
||||||
!exploreDraftDirty
|
|
||||||
|| window.confirm("Discard the unapplied Markdown draft and leave this resource?")
|
|
||||||
);
|
|
||||||
|
|
||||||
const switchExploreView = (nextView: ExploreView) => {
|
|
||||||
if (nextView === exploreView) return;
|
|
||||||
if (!confirmDiscardExploreDraft()) return;
|
|
||||||
setExploreDraftDirty(false);
|
|
||||||
setExploreView(nextView);
|
|
||||||
};
|
|
||||||
|
|
||||||
const switchWorkspace = (nextWorkspace: WorkspaceId) => {
|
|
||||||
if (nextWorkspace === activeWorkspace) return;
|
|
||||||
if (activeWorkspace === "explore" && !confirmDiscardExploreDraft()) return;
|
|
||||||
setExploreDraftDirty(false);
|
|
||||||
setActiveWorkspace(nextWorkspace);
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
const renderWorkspace = () => {
|
const renderWorkspace = () => {
|
||||||
@@ -1849,15 +1811,18 @@ export default function App() {
|
|||||||
return (
|
return (
|
||||||
<WorkspaceShell
|
<WorkspaceShell
|
||||||
title="Explore"
|
title="Explore"
|
||||||
subtitle={exploreView === 'graph' ? undefined : exploreView === 'memories' ? "Browse and edit canonical AgentMemory documents." : "Browse the graph and switch views without leaving the workspace."}
|
subtitle={exploreView === 'graph' ? undefined : "Browse the graph and switch views without leaving the workspace."}
|
||||||
kicker={exploreView === 'graph' ? 'Graph Studio' : exploreView === 'memories' ? 'Memory Browser' : 'Vocabulary Browser'}
|
kicker={exploreView === 'graph' ? 'Graph Studio' : 'Vocabulary Browser'}
|
||||||
compact
|
compact
|
||||||
tabs={
|
tabs={
|
||||||
<ExploreWorkspaceTabs
|
<>
|
||||||
activeView={exploreView}
|
<button className="workspace-tab" data-active={exploreView === 'graph'} onClick={() => setExploreView('graph')}>
|
||||||
agentMemoryAvailable={agentMemoryAvailable}
|
Semantica Explorer
|
||||||
onSelect={switchExploreView}
|
</button>
|
||||||
/>
|
<button className="workspace-tab" data-active={exploreView === 'vocabulary'} onClick={() => setExploreView('vocabulary')}>
|
||||||
|
Vocabulary Browser
|
||||||
|
</button>
|
||||||
|
</>
|
||||||
}
|
}
|
||||||
>
|
>
|
||||||
<ErrorBoundary key={`explore-${exploreView}`}>
|
<ErrorBoundary key={`explore-${exploreView}`}>
|
||||||
@@ -1866,9 +1831,8 @@ export default function App() {
|
|||||||
<GraphWorkspace
|
<GraphWorkspace
|
||||||
externalFocusNodeId={graphFocusRequest?.nodeId}
|
externalFocusNodeId={graphFocusRequest?.nodeId}
|
||||||
externalFocusToken={graphFocusRequest?.token}
|
externalFocusToken={graphFocusRequest?.token}
|
||||||
onDirtyChange={setExploreDraftDirty}
|
|
||||||
/>
|
/>
|
||||||
) : exploreView === 'memories' ? <MemoryWorkspace onDirtyChange={setExploreDraftDirty} /> : <VocabularyWorkspace />}
|
) : <VocabularyWorkspace />}
|
||||||
</Suspense>
|
</Suspense>
|
||||||
</ErrorBoundary>
|
</ErrorBoundary>
|
||||||
</WorkspaceShell>
|
</WorkspaceShell>
|
||||||
@@ -2013,13 +1977,13 @@ export default function App() {
|
|||||||
<style>{shellStyles}</style>
|
<style>{shellStyles}</style>
|
||||||
<div className="app-shell">
|
<div className="app-shell">
|
||||||
<aside className="app-rail">
|
<aside className="app-rail">
|
||||||
<button className="brand-pill" title="Semantica Knowledge Explorer" onClick={() => switchWorkspace('welcome')} style={{ cursor: 'pointer', border: '1px solid rgba(127,208,255,0.18)' }}>SKE</button>
|
<button className="brand-pill" title="Semantica Knowledge Explorer" onClick={() => setActiveWorkspace('welcome')} style={{ cursor: 'pointer', border: '1px solid rgba(127,208,255,0.18)' }}>SKE</button>
|
||||||
{navItems.map(({ id, label, hint, icon: Icon }) => (
|
{navItems.map(({ id, label, hint, icon: Icon }) => (
|
||||||
<button
|
<button
|
||||||
key={id}
|
key={id}
|
||||||
className="nav-button"
|
className="nav-button"
|
||||||
data-active={activeWorkspace === id}
|
data-active={activeWorkspace === id}
|
||||||
onClick={() => switchWorkspace(id)}
|
onClick={() => setActiveWorkspace(id)}
|
||||||
title={hint}
|
title={hint}
|
||||||
>
|
>
|
||||||
<Icon size={20} />
|
<Icon size={20} />
|
||||||
|
|||||||
@@ -1,29 +0,0 @@
|
|||||||
export type ExploreView = 'graph' | 'memories' | 'vocabulary';
|
|
||||||
|
|
||||||
type ExploreWorkspaceTabsProps = {
|
|
||||||
activeView: ExploreView;
|
|
||||||
agentMemoryAvailable: boolean;
|
|
||||||
onSelect: (view: ExploreView) => void;
|
|
||||||
};
|
|
||||||
|
|
||||||
export function ExploreWorkspaceTabs({
|
|
||||||
activeView,
|
|
||||||
agentMemoryAvailable,
|
|
||||||
onSelect,
|
|
||||||
}: ExploreWorkspaceTabsProps) {
|
|
||||||
return (
|
|
||||||
<>
|
|
||||||
<button className="workspace-tab" data-active={activeView === 'graph'} onClick={() => onSelect('graph')}>
|
|
||||||
Semantica Explorer
|
|
||||||
</button>
|
|
||||||
{agentMemoryAvailable ? (
|
|
||||||
<button className="workspace-tab" data-active={activeView === 'memories'} onClick={() => onSelect('memories')}>
|
|
||||||
Memories
|
|
||||||
</button>
|
|
||||||
) : null}
|
|
||||||
<button className="workspace-tab" data-active={activeView === 'vocabulary'} onClick={() => onSelect('vocabulary')}>
|
|
||||||
Vocabulary Browser
|
|
||||||
</button>
|
|
||||||
</>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
@@ -1,24 +0,0 @@
|
|||||||
type Fetcher = (
|
|
||||||
input: RequestInfo | URL,
|
|
||||||
init?: RequestInit,
|
|
||||||
) => Promise<Response>;
|
|
||||||
|
|
||||||
type ExplorerInfo = {
|
|
||||||
capabilities?: {
|
|
||||||
agent_memory?: boolean;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
export async function fetchAgentMemoryAvailability(
|
|
||||||
fetcher: Fetcher = fetch,
|
|
||||||
): Promise<boolean> {
|
|
||||||
try {
|
|
||||||
const response = await fetcher('/api/info');
|
|
||||||
if (!response.ok) return false;
|
|
||||||
|
|
||||||
const info = await response.json() as ExplorerInfo;
|
|
||||||
return info.capabilities?.agent_memory === true;
|
|
||||||
} catch {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -26,8 +26,6 @@ export interface NodeAttributes {
|
|||||||
size: number;
|
size: number;
|
||||||
color: string;
|
color: string;
|
||||||
baseColor?: string;
|
baseColor?: string;
|
||||||
/** Original semantic color when a display clone bakes interaction styling into baseColor. */
|
|
||||||
semanticBaseColor?: string;
|
|
||||||
mutedColor?: string;
|
mutedColor?: string;
|
||||||
glowColor?: string;
|
glowColor?: string;
|
||||||
baseSize?: number;
|
baseSize?: number;
|
||||||
|
|||||||
@@ -15,7 +15,6 @@ export type RegistryEntryOp =
|
|||||||
| "export"
|
| "export"
|
||||||
| "merge"
|
| "merge"
|
||||||
| "add-node"
|
| "add-node"
|
||||||
| "update-node"
|
|
||||||
| "add-edge"
|
| "add-edge"
|
||||||
| "delete"
|
| "delete"
|
||||||
| "infer"
|
| "infer"
|
||||||
|
|||||||
@@ -16,7 +16,6 @@ const OP_META: Record<
|
|||||||
export: { label: "EXPORT", color: "#8fa8c6", bg: "rgba(143,168,198,0.08)", border: "rgba(143,168,198,0.18)" },
|
export: { label: "EXPORT", color: "#8fa8c6", bg: "rgba(143,168,198,0.08)", border: "rgba(143,168,198,0.18)" },
|
||||||
merge: { label: "MERGE", color: "#f2b66d", bg: "rgba(242,182,109,0.12)", border: "rgba(242,182,109,0.28)" },
|
merge: { label: "MERGE", color: "#f2b66d", bg: "rgba(242,182,109,0.12)", border: "rgba(242,182,109,0.28)" },
|
||||||
"add-node": { label: "ADD NODE", color: "#4cc38a", bg: "rgba(76,195,138,0.12)", border: "rgba(76,195,138,0.28)" },
|
"add-node": { label: "ADD NODE", color: "#4cc38a", bg: "rgba(76,195,138,0.12)", border: "rgba(76,195,138,0.28)" },
|
||||||
"update-node": { label: "UPDATE NODE", color: "#79c0ff", bg: "rgba(121,192,255,0.10)", border: "rgba(121,192,255,0.24)" },
|
|
||||||
"add-edge": { label: "ADD EDGE", color: "#4cc38a", bg: "rgba(76,195,138,0.10)", border: "rgba(76,195,138,0.22)" },
|
"add-edge": { label: "ADD EDGE", color: "#4cc38a", bg: "rgba(76,195,138,0.10)", border: "rgba(76,195,138,0.22)" },
|
||||||
delete: { label: "DELETE", color: "#ff7b72", bg: "rgba(255,123,114,0.12)", border: "rgba(255,123,114,0.28)" },
|
delete: { label: "DELETE", color: "#ff7b72", bg: "rgba(255,123,114,0.12)", border: "rgba(255,123,114,0.28)" },
|
||||||
infer: { label: "INFER", color: "#d2a8ff", bg: "rgba(210,168,255,0.12)", border: "rgba(210,168,255,0.28)" },
|
infer: { label: "INFER", color: "#d2a8ff", bg: "rgba(210,168,255,0.12)", border: "rgba(210,168,255,0.28)" },
|
||||||
@@ -24,7 +23,7 @@ const OP_META: Record<
|
|||||||
};
|
};
|
||||||
|
|
||||||
const ALL_OPS: (RegistryEntryOp | "all")[] = [
|
const ALL_OPS: (RegistryEntryOp | "all")[] = [
|
||||||
"all", "import", "export", "merge", "add-node", "update-node", "add-edge", "infer", "delete", "vocab-import",
|
"all", "import", "export", "merge", "add-node", "add-edge", "infer", "delete", "vocab-import",
|
||||||
];
|
];
|
||||||
|
|
||||||
function formatTimestamp(date: Date): string {
|
function formatTimestamp(date: Date): string {
|
||||||
|
|||||||
@@ -4,7 +4,6 @@ import { graph } from "../../store/graphStore";
|
|||||||
import { GRAPH_THEME, withAlpha } from "./graphTheme";
|
import { GRAPH_THEME, withAlpha } from "./graphTheme";
|
||||||
import type { GraphSelectedNodeKind } from "./types";
|
import type { GraphSelectedNodeKind } from "./types";
|
||||||
import { MarkdownContentViewer } from "./MarkdownContentViewer";
|
import { MarkdownContentViewer } from "./MarkdownContentViewer";
|
||||||
import type { MarkdownApplyResult } from "./markdownResourceClient";
|
|
||||||
|
|
||||||
export type LinkPrediction = {
|
export type LinkPrediction = {
|
||||||
target: string;
|
target: string;
|
||||||
@@ -45,8 +44,6 @@ export interface GraphInspectorPanelProps {
|
|||||||
pathResult: PathResponse | null;
|
pathResult: PathResponse | null;
|
||||||
onDownloadProvenance: (format: "json" | "markdown") => void;
|
onDownloadProvenance: (format: "json" | "markdown") => void;
|
||||||
onFocusNode?: (nodeId: string) => void;
|
onFocusNode?: (nodeId: string) => void;
|
||||||
onMarkdownApplied?: (result: MarkdownApplyResult) => void;
|
|
||||||
onMarkdownDirtyChange?: (dirty: boolean) => void;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const PROVENANCE_KEYS = ["source", "source_url", "pmid", "pmids", "evidence", "provenance", "confidence"] as const;
|
const PROVENANCE_KEYS = ["source", "source_url", "pmid", "pmids", "evidence", "provenance", "confidence"] as const;
|
||||||
@@ -307,8 +304,6 @@ export function GraphInspectorPanel({
|
|||||||
pathResult,
|
pathResult,
|
||||||
onDownloadProvenance,
|
onDownloadProvenance,
|
||||||
onFocusNode,
|
onFocusNode,
|
||||||
onMarkdownApplied,
|
|
||||||
onMarkdownDirtyChange,
|
|
||||||
}: GraphInspectorPanelProps) {
|
}: GraphInspectorPanelProps) {
|
||||||
if (!nodeId) {
|
if (!nodeId) {
|
||||||
return (
|
return (
|
||||||
@@ -346,7 +341,7 @@ export function GraphInspectorPanel({
|
|||||||
<div style={{ color: GRAPH_THEME.ui.text.strong, fontWeight: 600, marginBottom: 6 }}>Selected item is not directly inspectable in the current graph.</div>
|
<div style={{ color: GRAPH_THEME.ui.text.strong, fontWeight: 600, marginBottom: 6 }}>Selected item is not directly inspectable in the current graph.</div>
|
||||||
<div style={{ color: GRAPH_THEME.ui.text.body, fontSize: 13, lineHeight: 1.6 }}>
|
<div style={{ color: GRAPH_THEME.ui.text.body, fontSize: 13, lineHeight: 1.6 }}>
|
||||||
{canActivateFocused
|
{canActivateFocused
|
||||||
? "Use Focus to resolve this grouped selection to its canonical node."
|
? "Activate Focused mode to resolve this grouped selection to its canonical node."
|
||||||
: (focusedUnavailableReason ?? "Focused mode is unavailable for the current selection.")}
|
: (focusedUnavailableReason ?? "Focused mode is unavailable for the current selection.")}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -419,18 +414,19 @@ export function GraphInspectorPanel({
|
|||||||
</div>
|
</div>
|
||||||
) : null}
|
) : null}
|
||||||
|
|
||||||
{/* Canonical nodes remain editable even when their current body is empty. */}
|
{/* Content Section — only rendered when the node carries actual content.
|
||||||
<details className="node-panel-collapse" open>
|
This matches the existing inspector convention: sections that have no
|
||||||
<summary className="node-panel-summary">Content</summary>
|
data for the current node are either hidden (temporal bounds) or closed
|
||||||
<div className="node-panel-body" style={{ marginTop: 8 }}>
|
by default (Source Attribution, Properties). Always showing an open
|
||||||
<MarkdownContentViewer
|
empty panel would add noise for every relationship/predicate node. */}
|
||||||
content={nodeContent}
|
{nodeContent && (
|
||||||
resource={{ kind: "context-node", id: effectiveNodeId }}
|
<details className="node-panel-collapse" open>
|
||||||
onApplied={onMarkdownApplied}
|
<summary className="node-panel-summary">Content</summary>
|
||||||
onDirtyChange={onMarkdownDirtyChange}
|
<div className="node-panel-body" style={{ marginTop: 8 }}>
|
||||||
/>
|
<MarkdownContentViewer content={nodeContent} />
|
||||||
</div>
|
</div>
|
||||||
</details>
|
</details>
|
||||||
|
)}
|
||||||
|
|
||||||
{/* Actions */}
|
{/* Actions */}
|
||||||
<section style={sectionStyle}>
|
<section style={sectionStyle}>
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user