mirror of
https://github.com/semantica-agi/semantica.git
synced 2026-09-04 04:01:07 +00:00
Compare commits
12
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
98900af751 | ||
|
|
8bceff105c | ||
|
|
f45499b5a7 | ||
|
|
b574e2e6b4 | ||
|
|
c04adcd1a9 | ||
|
|
a85cf913a5 | ||
|
|
6ba433fea0 | ||
|
|
f6a0e4a32e | ||
|
|
111bcf997e | ||
|
|
6a07ad29be | ||
|
|
064f0eccad | ||
|
|
afec253451 |
@@ -28,7 +28,13 @@
|
||||
|
||||
[](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://docs.getsemantica.ai/) [](https://discord.gg/sV34vps5hH) [](https://x.com/BuildSemantica) [](https://www.youtube.com/watch?v=QfnNZg4-dZA) [](CHANGELOG.md)
|
||||
[](https://getsemantica.ai/)
|
||||
[](https://docs.getsemantica.ai/)
|
||||
[](https://discord.gg/sV34vps5hH)
|
||||
[](https://x.com/BuildSemantica)
|
||||
|
||||
[](https://www.youtube.com/watch?v=QfnNZg4-dZA)
|
||||
|
||||
|
||||
```bash
|
||||
pip install semantica
|
||||
|
||||
@@ -195,7 +195,7 @@ apt29_intel = context.retrieve(
|
||||
```python
|
||||
from semantica.llms import LiteLLM
|
||||
|
||||
llm = LiteLLM(model="anthropic/claude-sonnet-4-20250514")
|
||||
llm = LiteLLM(model="anthropic/claude-sonnet-5")
|
||||
|
||||
result = context.query_with_reasoning(
|
||||
"What are APT29's known TTPs against healthcare infrastructure, "
|
||||
@@ -281,7 +281,7 @@ context.store(
|
||||
link_entities=True,
|
||||
)
|
||||
|
||||
llm = LiteLLM(model="anthropic/claude-sonnet-4-20250514")
|
||||
llm = LiteLLM(model="anthropic/claude-sonnet-5")
|
||||
result = context.query_with_reasoning(
|
||||
"Trace the C2 infrastructure chain for APT29 operations targeting "
|
||||
"ITAR-controlled contractors in 2025. Include IP ranges, ASNs, and TTPs.",
|
||||
@@ -351,7 +351,7 @@ Parent: wmiprvse.exe
|
||||
Sigma match: T1053.005 Scheduled Task/Job
|
||||
"""
|
||||
|
||||
llm = LiteLLM(model="anthropic/claude-sonnet-4-20250514")
|
||||
llm = LiteLLM(model="anthropic/claude-sonnet-5")
|
||||
triage = soc_context.query_with_reasoning(
|
||||
"Triage this SIEM alert and identify the correct response runbook:\n{}".format(alert_text),
|
||||
llm_provider=llm,
|
||||
@@ -425,7 +425,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.
|
||||
"""
|
||||
|
||||
llm = LiteLLM(model="anthropic/claude-sonnet-4-20250514")
|
||||
llm = LiteLLM(model="anthropic/claude-sonnet-5")
|
||||
answer = clinical_context.query_with_reasoning(
|
||||
"What is the evidence-based warfarin bridging protocol for this patient "
|
||||
"given CKD and amiodarone interaction risk?\n\n{}".format(patient_context),
|
||||
@@ -495,7 +495,7 @@ compliance_context.store(
|
||||
extract_relationships=True,
|
||||
)
|
||||
|
||||
llm = LiteLLM(model="anthropic/claude-sonnet-4-20250514")
|
||||
llm = LiteLLM(model="anthropic/claude-sonnet-5")
|
||||
answer = compliance_context.query_with_reasoning(
|
||||
"Under Basel III CRE20, what are the RWA calculation requirements for "
|
||||
"commercial real estate exposures with LTV > 80%? "
|
||||
|
||||
@@ -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 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.
|
||||
`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.
|
||||
|
||||
```python
|
||||
from semantica.llms import LiteLLM
|
||||
|
||||
# Anthropic Claude — highest accuracy for complex reasoning
|
||||
llm = LiteLLM(model="anthropic/claude-sonnet-4-20250514")
|
||||
llm = LiteLLM(model="anthropic/claude-sonnet-5")
|
||||
# Reads ANTHROPIC_API_KEY from environment
|
||||
|
||||
# Azure OpenAI — compliance and data-residency requirements
|
||||
llm = LiteLLM(model="azure/gpt-4o", api_key="YOUR_AZURE_KEY")
|
||||
|
||||
# AWS Bedrock — existing cloud agreement, no new vendor
|
||||
llm = LiteLLM(model="bedrock/anthropic.claude-3-5-sonnet-20241022-v2:0")
|
||||
llm = LiteLLM(model="bedrock/anthropic.claude-sonnet-4-5-20250929-v1:0")
|
||||
|
||||
# Google Vertex AI
|
||||
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
|
||||
|
||||
PROVIDER_MAP = {
|
||||
"prod": "anthropic/claude-sonnet-4-20250514",
|
||||
"prod": "anthropic/claude-sonnet-5",
|
||||
"staging": "openai/gpt-4o-mini",
|
||||
"local": "ollama/llama3.2",
|
||||
"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
|
||||
if fast_result["confidence"] < 0.85:
|
||||
deep_llm = LiteLLM(model="anthropic/claude-sonnet-4-20250514")
|
||||
deep_llm = LiteLLM(model="anthropic/claude-sonnet-5")
|
||||
deep_result = context.query_with_reasoning(
|
||||
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
|
||||
if triage["confidence"] < 0.88:
|
||||
deep_llm = LiteLLM(model="anthropic/claude-sonnet-4-20250514")
|
||||
deep_llm = LiteLLM(model="anthropic/claude-sonnet-5")
|
||||
deep = context.query_with_reasoning(
|
||||
"Full MITRE ATT&CK analysis of this alert: identify the attack chain, "
|
||||
"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)
|
||||
|
||||
# Report synthesis with Claude — switch to azure/gpt-4o for HIPAA by changing one string
|
||||
report_llm = LiteLLM(model="anthropic/claude-sonnet-4-20250514")
|
||||
report_llm = LiteLLM(model="anthropic/claude-sonnet-5")
|
||||
# For HIPAA-constrained Azure deployment:
|
||||
# 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
|
||||
gpt4o = OpenAI(model="gpt-4o", api_key="YOUR_OAI_KEY")
|
||||
claude = LiteLLM(model="anthropic/claude-sonnet-4-20250514")
|
||||
claude = LiteLLM(model="anthropic/claude-sonnet-5")
|
||||
|
||||
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)
|
||||
|
||||
@@ -197,7 +197,7 @@ reasoning_agent.load("./pipeline/enriched_intel/")
|
||||
# All memories, graph nodes, and vector embeddings from both ingestion agents are now available.
|
||||
|
||||
# Use a high-capability model for the synthesis step
|
||||
llm = LiteLLM(model="anthropic/claude-sonnet-4-20250514")
|
||||
llm = LiteLLM(model="anthropic/claude-sonnet-5")
|
||||
|
||||
synthesis = reasoning_agent.query_with_reasoning(
|
||||
"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 ---
|
||||
if triage["confidence"] < 0.90:
|
||||
deep_llm = LiteLLM(model="anthropic/claude-sonnet-4-20250514")
|
||||
deep_llm = LiteLLM(model="anthropic/claude-sonnet-5")
|
||||
|
||||
investigation = tier2.query_with_reasoning(
|
||||
"Full MITRE ATT&CK analysis of incident {}. "
|
||||
@@ -533,7 +533,7 @@ t1.start(); t2.start()
|
||||
t1.join(); t2.join()
|
||||
|
||||
# Chief agent synthesizes across literature and experimental data
|
||||
llm = LiteLLM(model="anthropic/claude-sonnet-4-20250514")
|
||||
llm = LiteLLM(model="anthropic/claude-sonnet-5")
|
||||
|
||||
synthesis = chief.query_with_reasoning(
|
||||
"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()
|
||||
|
||||
app_id = "LOAN-2025-88421"
|
||||
llm = LiteLLM(model="anthropic/claude-sonnet-4-20250514")
|
||||
llm = LiteLLM(model="anthropic/claude-sonnet-5")
|
||||
|
||||
# --- Risk Desk: PD/LGD/EL analysis ---
|
||||
risk_desk.store(
|
||||
|
||||
@@ -477,7 +477,7 @@ regs = [
|
||||
]
|
||||
|
||||
# Use an LLM to extract the conceptual model from regulatory prose
|
||||
llm_gen = LLMOntologyGenerator(provider="anthropic", model="claude-sonnet-4-20250514")
|
||||
llm_gen = LLMOntologyGenerator(provider="anthropic", model="claude-sonnet-5")
|
||||
ontology = llm_gen.generate_ontology_from_text(
|
||||
"\n\n".join(r.text[:8000] for r in regs) # token-safe excerpt per document
|
||||
)
|
||||
|
||||
@@ -127,7 +127,7 @@ engine = ExecutionEngine(max_workers=4, retry_on_failure=True)
|
||||
result = engine.execute_pipeline(pipeline)
|
||||
|
||||
print(f"Success: {result.success}")
|
||||
print(f"Output: {result.output}") # {"node_count": 312, "edge_count": 847}
|
||||
print(f"Output: {result.output}") # the final step's return value, e.g. {"node_count": ..., "edge_count": ...}
|
||||
print(f"Duration: {result.metrics['execution_time']:.2f}s")
|
||||
print(f"Steps completed: {result.metrics['steps_executed']}")
|
||||
```
|
||||
@@ -197,7 +197,9 @@ engine = ExecutionEngine(
|
||||
max_workers = 4,
|
||||
retry_on_failure = True,
|
||||
)
|
||||
# The engine uses handler.get_retry_policy(step.step_type) when a step fails
|
||||
# ExecutionEngine builds its own FailureHandler; replace it with the configured one
|
||||
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:
|
||||
|
||||
@@ -100,14 +100,15 @@ ner = NamedEntityRecognizer(
|
||||
methods=["llm", "ml", "pattern"],
|
||||
confidence_threshold=0.75,
|
||||
provider="anthropic",
|
||||
llm_model="claude-sonnet-4-6",
|
||||
llm_model="claude-sonnet-5",
|
||||
)
|
||||
entities = ner.extract_entities(report)
|
||||
|
||||
for e in entities:
|
||||
print("[{:>5.2f}] {:15s} {}".format(e.confidence, e.label, e.text))
|
||||
|
||||
# Expected output (abbreviated):
|
||||
# Illustrative output — exact labels and scores depend on the method and model.
|
||||
# Abbreviated:
|
||||
# [ 0.94] THREAT_ACTOR GAMMA-7
|
||||
# [ 0.91] THREAT_ACTOR DELTA-3
|
||||
# [ 0.97] MALWARE HAMMERTOSS
|
||||
@@ -262,16 +263,18 @@ from semantica.semantic_extract import TripletExtractor
|
||||
tri = TripletExtractor(
|
||||
method="llm",
|
||||
provider="anthropic",
|
||||
llm_model="claude-sonnet-4-6",
|
||||
llm_model="claude-sonnet-5",
|
||||
include_temporal=True, # attach time context to triplets when available
|
||||
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
|
||||
# uses them to constrain and validate what it produces
|
||||
# uses them to constrain what it produces
|
||||
triplets = tri.extract_triplets(report, entities, relations)
|
||||
|
||||
# Filter malformed triplets before serialisation
|
||||
# (extract_triplets validates automatically unless validate=False, as above)
|
||||
valid = tri.validate_triplets(triplets)
|
||||
print("Valid: {}/{}".format(len(valid), len(triplets)))
|
||||
|
||||
@@ -320,7 +323,7 @@ def ingest_intel_report(
|
||||
methods=[method, "pattern"],
|
||||
confidence_threshold=0.70,
|
||||
provider="anthropic",
|
||||
llm_model="claude-sonnet-4-6",
|
||||
llm_model="claude-sonnet-5",
|
||||
)
|
||||
entities = ner.extract_entities(text)
|
||||
classified = ner.classify_entities(entities)
|
||||
@@ -335,7 +338,7 @@ def ingest_intel_report(
|
||||
relation_types=["deployed", "targets", "exploits", "operates_from", "provided_to"],
|
||||
confidence_threshold=0.65,
|
||||
provider="anthropic",
|
||||
llm_model="claude-sonnet-4-6",
|
||||
llm_model="claude-sonnet-5",
|
||||
)
|
||||
relations = rel.extract_relations(text, entities)
|
||||
|
||||
@@ -347,9 +350,10 @@ def ingest_intel_report(
|
||||
tri = TripletExtractor(
|
||||
method=method,
|
||||
provider="anthropic",
|
||||
llm_model="claude-sonnet-4-6",
|
||||
llm_model="claude-sonnet-5",
|
||||
include_temporal=True,
|
||||
include_provenance=True,
|
||||
validate=False, # keep raw triplets so the summary can report rejections
|
||||
)
|
||||
triplets = tri.extract_triplets(text, entities, relations)
|
||||
valid = tri.validate_triplets(triplets)
|
||||
@@ -377,6 +381,7 @@ def ingest_intel_report(
|
||||
"coref_chains": len(chains),
|
||||
"relations": len(relations),
|
||||
"events": len(events),
|
||||
"triplets_total": len(triplets),
|
||||
"triplets_valid": len(valid),
|
||||
"graph_nodes": graph_stats.get("graph_nodes", 0),
|
||||
"graph_edges": graph_stats.get("graph_edges", 0),
|
||||
@@ -402,7 +407,7 @@ for text, doc_id in reports:
|
||||
summary["relations"],
|
||||
summary["events"],
|
||||
summary["triplets_valid"],
|
||||
len(summary["rdf_turtle"]),
|
||||
summary["triplets_total"],
|
||||
))
|
||||
```
|
||||
|
||||
@@ -421,7 +426,7 @@ ner = NamedEntityRecognizer(
|
||||
methods=["llm", "pattern"],
|
||||
confidence_threshold=0.75,
|
||||
provider="anthropic",
|
||||
llm_model="claude-sonnet-4-6",
|
||||
llm_model="claude-sonnet-5",
|
||||
)
|
||||
entities = ner.extract_entities(fintel_text)
|
||||
grouped = ner.classify_entities(entities)
|
||||
@@ -438,14 +443,14 @@ rel = RelationExtractor(
|
||||
relation_types=["operates_from", "deployed", "targets", "exploits"],
|
||||
confidence_threshold=0.70,
|
||||
provider="anthropic",
|
||||
llm_model="claude-sonnet-4-6",
|
||||
llm_model="claude-sonnet-5",
|
||||
)
|
||||
relations = rel.extract_relations(fintel_text, entities)
|
||||
|
||||
tri = TripletExtractor(
|
||||
method="llm",
|
||||
provider="anthropic",
|
||||
llm_model="claude-sonnet-4-6",
|
||||
llm_model="claude-sonnet-5",
|
||||
include_temporal=True,
|
||||
include_provenance=True,
|
||||
)
|
||||
@@ -544,14 +549,14 @@ rel = RelationExtractor(
|
||||
relation_types=["treats", "causes_adverse_event", "has_efficacy", "evaluated_in"],
|
||||
confidence_threshold=0.65,
|
||||
provider="anthropic",
|
||||
llm_model="claude-sonnet-4-6",
|
||||
llm_model="claude-sonnet-5",
|
||||
)
|
||||
relations = rel.extract_relations(paper, entities)
|
||||
|
||||
tri = TripletExtractor(
|
||||
method="llm",
|
||||
provider="anthropic",
|
||||
llm_model="claude-sonnet-4-6",
|
||||
llm_model="claude-sonnet-5",
|
||||
triplet_types=["treats", "has_efficacy", "causes_adverse_event"],
|
||||
include_temporal=True,
|
||||
include_provenance=True,
|
||||
@@ -595,7 +600,7 @@ ner = NamedEntityRecognizer(
|
||||
methods=["llm", "ml", "pattern"],
|
||||
confidence_threshold=0.70,
|
||||
provider="anthropic",
|
||||
llm_model="claude-sonnet-4-6",
|
||||
llm_model="claude-sonnet-5",
|
||||
)
|
||||
entities = ner.extract_entities(credit_memo)
|
||||
grouped = ner.classify_entities(entities)
|
||||
@@ -612,14 +617,14 @@ rel = RelationExtractor(
|
||||
relation_types=["guaranteed_by", "secured_by", "classified_as", "exposed_to"],
|
||||
confidence_threshold=0.65,
|
||||
provider="anthropic",
|
||||
llm_model="claude-sonnet-4-6",
|
||||
llm_model="claude-sonnet-5",
|
||||
)
|
||||
relations = rel.extract_relations(credit_memo, entities)
|
||||
|
||||
tri = TripletExtractor(
|
||||
method="llm",
|
||||
provider="anthropic",
|
||||
llm_model="claude-sonnet-4-6",
|
||||
llm_model="claude-sonnet-5",
|
||||
include_temporal=True,
|
||||
include_provenance=True,
|
||||
)
|
||||
|
||||
@@ -12,13 +12,13 @@ icon: "link"
|
||||
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
|
||||
|
||||
- **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`.
|
||||
- **SemanticaKGTool** / **SemanticaDecisionTool** — `BaseTool` subclasses: `semantica_query_graph` and `semantica_query_decisions` for LangGraph / tool-calling agents.
|
||||
- **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`.
|
||||
- **SemanticaKGTool** / **SemanticaDecisionTool** (`BaseTool` subclasses): `semantica_query_graph` and `semantica_query_decisions` for LangGraph / tool-calling agents.
|
||||
|
||||
## Component Details
|
||||
|
||||
|
||||
+163
-122
@@ -28,7 +28,9 @@ Semantica is organized into **27 modules** across six logical layers. Each modul
|
||||
|
||||
### Ingest
|
||||
|
||||
Loads data from files, web, databases, and streams into a unified `SourceDocument` format.
|
||||
Loads data from files, web, databases, and streams. Each ingestor returns its own
|
||||
result type (`FileIngestor` → `FileObject`, `WebIngestor` → `WebContent`, …);
|
||||
document-oriented ones expose a `.text` payload and `.metadata`.
|
||||
|
||||
```python
|
||||
from semantica.ingest import FileIngestor, WebIngestor, ParquetIngestor, XMLIngestor, DatabricksIngestor
|
||||
@@ -37,7 +39,7 @@ from semantica.ingest import FileIngestor, WebIngestor, ParquetIngestor, XMLInge
|
||||
ingestor = FileIngestor()
|
||||
documents = ingestor.ingest_directory("data/")
|
||||
|
||||
# Web crawl
|
||||
# Web page: returns a WebContent with .text, .title, .links, .metadata
|
||||
web_ingestor = WebIngestor()
|
||||
page = web_ingestor.ingest_url("https://example.com")
|
||||
|
||||
@@ -67,13 +69,13 @@ Extracts structured text and layout metadata from raw documents.
|
||||
```python
|
||||
from semantica.parse import DocumentParser, DoclingParser
|
||||
|
||||
# Standard parser: all common formats
|
||||
# Standard parser: all common formats. parse() takes a path, returns a dict
|
||||
parser = DocumentParser()
|
||||
parsed = parser.parse_document("document.pdf")
|
||||
parsed = parser.parse("document.pdf") # {"full_text": ..., "metadata": ..., ...}
|
||||
|
||||
# Advanced parser: multi-column PDFs, merged-cell tables, OCR
|
||||
parser = DoclingParser(extract_tables=True, extract_images=True, output_format="markdown")
|
||||
parsed = parser.parse("data/annual_report.pdf")
|
||||
# Advanced parser (pip install semantica[parse-docling]): tables, OCR, layout
|
||||
parser = DoclingParser(export_format="markdown", enable_ocr=True)
|
||||
parsed = parser.parse("data/annual_report.pdf") # dict with full_text, tables, pages
|
||||
```
|
||||
|
||||
**Available parsers:** `DocumentParser`, `DoclingParser`, `CodeParser`, `CSVParser`, `DocxParser`, `EmailParser`, `ExcelParser`, `HTMLParser`, `ImageParser`, `JSONParser`, `MCPParser`, `MediaParser`, `PDFParser`, `PPTXParser`, `StructuredDataParser`, `WebParser`, `XMLParser`
|
||||
@@ -85,11 +87,12 @@ Chunks text for embedding and RAG pipelines with awareness of semantic boundarie
|
||||
```python
|
||||
from semantica.split import TextSplitter
|
||||
|
||||
splitter = TextSplitter(method="semantic_transformer")
|
||||
chunks = splitter.split(text, chunk_size=1000, chunk_overlap=200)
|
||||
# chunk_size / chunk_overlap are constructor arguments
|
||||
splitter = TextSplitter(method="semantic_transformer", chunk_size=1000, chunk_overlap=200)
|
||||
chunks = splitter.split(text)
|
||||
```
|
||||
|
||||
**Chunking strategies:** `recursive`, `semantic_transformer`, `entity_aware`, `relation_aware`, `sliding_window`, `structural`
|
||||
**Chunking methods:** `recursive`, `token`, `sentence`, `paragraph`, `semantic_transformer`, `entity_aware`, `relation_aware`, `graph_based`, `ontology_aware`, `hierarchical`, `community_detection`, `centrality_based`, `llm`
|
||||
|
||||
### Normalize
|
||||
|
||||
@@ -115,17 +118,18 @@ Named entity recognition, relation extraction, and triplet generation.
|
||||
```python
|
||||
from semantica.semantic_extract import NERExtractor, RelationExtractor, TripletExtractor
|
||||
|
||||
ner = NERExtractor(method="llm", llm_provider=llm)
|
||||
entities = ner.extract("Apple Inc. was founded by Steve Jobs.")
|
||||
# LLM method: provider + llm_model select the backend; the API key comes from the env
|
||||
ner = NERExtractor(method="llm", provider="groq", llm_model="llama-3.3-70b-versatile")
|
||||
entities = ner.extract("Apple Inc. was founded by Steve Jobs.") # list[Entity]
|
||||
|
||||
rel = RelationExtractor(method="llm", llm_provider=llm)
|
||||
relationships = rel.extract(text, entities=entities)
|
||||
rel = RelationExtractor(method="llm", provider="groq", llm_model="llama-3.3-70b-versatile")
|
||||
relationships = rel.extract(text, entities=entities) # list[Relation]
|
||||
|
||||
trip = TripletExtractor(method="llm", llm_provider=llm)
|
||||
triplets = trip.extract(text)
|
||||
trip = TripletExtractor(method="pattern")
|
||||
triplets = trip.extract(text) # list[Triplet]
|
||||
```
|
||||
|
||||
**Extraction methods:** `"pattern"` (no API key), `"ml"` (local model), `"llm"` (any of the 8 supported providers)
|
||||
**Extraction methods:** `"pattern"` (no API key), `"ml"` (local spaCy model), `"llm"` (any of the 9 supported providers)
|
||||
|
||||
**Additional extractors:** `CoreferenceResolver`, `EventDetector`, `SemanticAnalyzer`, `SemanticNetworkExtractor`
|
||||
|
||||
@@ -137,17 +141,17 @@ Graph construction, graph algorithms, temporal model, and distance intelligence.
|
||||
from semantica.kg import GraphBuilder, GraphAnalyzer, TemporalGraphQuery, SimilarityCalculator
|
||||
from datetime import datetime
|
||||
|
||||
# Build
|
||||
# Build: build() takes a {"entities": ..., "relationships": ...} dict
|
||||
builder = GraphBuilder(merge_entities=True)
|
||||
kg = builder.build(entities=entities, relationships=relationships)
|
||||
kg = builder.build({"entities": entities, "relationships": relationships})
|
||||
|
||||
# Temporal graphs (v0.4.0)
|
||||
query_engine = TemporalGraphQuery(enable_temporal_reasoning=True)
|
||||
snapshot = query_engine.query_at_time(kg, query="", at_time=datetime(2021, 6, 15))
|
||||
|
||||
# Semantic similarity (v0.5.0)
|
||||
calc = SimilarityCalculator()
|
||||
scores = calc.calculate_similarity(entity_a, entity_b)
|
||||
# Semantic similarity (v0.5.0): operates on embedding vectors
|
||||
calc = SimilarityCalculator(method="cosine")
|
||||
score = calc.cosine_similarity(vec_a, vec_b)
|
||||
```
|
||||
|
||||
**Graph algorithms available:** centrality calculation, community detection, connectivity analysis, entity resolution, link prediction, path finding, similarity calculation
|
||||
@@ -175,19 +179,23 @@ Derives new facts from existing knowledge using multiple inference strategies.
|
||||
```python
|
||||
from semantica.reasoning import Reasoner, DatalogReasoner
|
||||
|
||||
# Rule-based reasoning
|
||||
# Forward chaining: facts and rules as predicate(args) / IF-THEN strings
|
||||
engine = Reasoner()
|
||||
engine.apply_transitivity("located_in")
|
||||
engine.apply_symmetry("knows")
|
||||
result = engine.infer()
|
||||
engine.add_fact("Manager(Alice)")
|
||||
engine.add_rule("IF Manager(?x) THEN HasAuthority(?x)")
|
||||
results = engine.forward_chain() # list[InferenceResult] with .conclusion, .rule_used
|
||||
|
||||
# Datalog: recursive Horn clause rules (v0.4.0)
|
||||
datalog = DatalogEngine()
|
||||
datalog = DatalogReasoner()
|
||||
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).")
|
||||
results = datalog.query("ancestor(alice, ?)")
|
||||
datalog.derive_all()
|
||||
results = datalog.query("ancestor(tom, ?Z)") # [{"Z": "bob"}, {"Z": "ann"}], order not guaranteed
|
||||
```
|
||||
|
||||
**Engines:** forward chaining, Rete network, deductive, abductive, SPARQL, Datalog: all produce explainable inference paths
|
||||
**Engines:** `Reasoner` (forward/backward chaining), `ReteEngine`, `SPARQLReasoner`, `DatalogReasoner`, `TemporalReasoningEngine`, `GraphReasoner` (LLM)
|
||||
|
||||
|
||||
## Storage
|
||||
@@ -199,9 +207,9 @@ Generates and manages vector embeddings for semantic similarity.
|
||||
```python
|
||||
from semantica.embeddings import EmbeddingGenerator
|
||||
|
||||
generator = EmbeddingGenerator(model="sentence-transformers")
|
||||
embeddings = generator.generate(["text1", "text2"])
|
||||
similarity = generator.similarity(embeddings[0], embeddings[1])
|
||||
generator = EmbeddingGenerator()
|
||||
embeddings = generator.generate_embeddings(["text1", "text2"]) # np.ndarray
|
||||
similarity = generator.compare_embeddings(embeddings[0], embeddings[1])
|
||||
```
|
||||
|
||||
**Supported models:** Sentence-Transformers, FastEmbed, OpenAI, BGE
|
||||
@@ -215,12 +223,18 @@ Multi-backend vector database with hybrid search support.
|
||||
```python
|
||||
from semantica.vector_store import VectorStore
|
||||
|
||||
store = VectorStore(backend="faiss", dimension=768)
|
||||
store.add_vectors(embeddings, ids)
|
||||
results = store.search(query_vector, top_k=10)
|
||||
store = VectorStore(backend="faiss", dimension=768)
|
||||
|
||||
# Raw vectors
|
||||
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, in-memory
|
||||
**Backends:** FAISS, Pinecone, Weaviate, Qdrant, Milvus, PgVector, SQLite, in-memory
|
||||
|
||||
**Search modes:** semantic top-k, hybrid (vector + keyword), metadata-filtered
|
||||
|
||||
@@ -232,8 +246,8 @@ Connects to graph databases for persistent, query-able storage.
|
||||
from semantica.graph_store import GraphStore
|
||||
|
||||
store = GraphStore(backend="neo4j")
|
||||
store.add_nodes(entities)
|
||||
store.add_edges(relationships)
|
||||
store.add_nodes([{"id": "acme", "type": "Organization", "properties": {"name": "Acme"}}])
|
||||
store.add_edges([{"source": "alice", "target": "acme", "type": "works_for"}])
|
||||
results = store.query("MATCH (n)-[r]->(m) RETURN n, r, m")
|
||||
```
|
||||
|
||||
@@ -246,9 +260,9 @@ RDF triple-based storage with SPARQL query support.
|
||||
```python
|
||||
from semantica.triplet_store import TripletStore
|
||||
|
||||
store = TripletStore(backend="blazegraph")
|
||||
store.add_triplets(subject, predicate, obj)
|
||||
results = store.sparql("SELECT ?s ?p ?o WHERE { ?s ?p ?o }")
|
||||
store = TripletStore(backend="oxigraph")
|
||||
store.add_triplets(triplets) # list of Triplet objects (or add_triplet for one)
|
||||
results = store.execute_query("SELECT ?s ?p ?o WHERE { ?s ?p ?o }")
|
||||
```
|
||||
|
||||
**Backends:** Oxigraph (embedded), Blazegraph, Apache Jena, RDF4J
|
||||
@@ -261,15 +275,18 @@ results = store.sparql("SELECT ?s ?p ?o WHERE { ?s ?p ?o }")
|
||||
Detects, scores, and merges duplicate entities across sources.
|
||||
|
||||
```python
|
||||
from semantica.deduplication import EntityResolver
|
||||
from semantica.deduplication import DuplicateDetector, EntityMerger
|
||||
|
||||
resolver = EntityResolver()
|
||||
merged = resolver.resolve(entities, strategy="semantic_v2")
|
||||
detector = DuplicateDetector(similarity_threshold=0.85)
|
||||
candidates = detector.detect_duplicates(entities)
|
||||
|
||||
merger = EntityMerger()
|
||||
operations = merger.merge_duplicates(entities, strategy="keep_most_complete")
|
||||
```
|
||||
|
||||
**v2 strategies** (`blocking_v2`, `hybrid_v2`, `semantic_v2`) are up to 7x faster than v1.
|
||||
**v2 candidate-generation modes** (`blocking_v2`, `hybrid_v2`, `semantic_v2`) are up to 7x faster than v1.
|
||||
|
||||
**Components:** `EntityResolver`, `DuplicateDetector`, `EntityMerger`, `SimilarityCalculator`, `ClusterBuilder`
|
||||
**Components:** `DuplicateDetector`, `EntityMerger`, `ClusterBuilder`, `MergeStrategyManager`
|
||||
|
||||
**`DuplicateDetector` options:** `max_results`, `top_k_per_entity`, `min_similarity`, `sort_by`
|
||||
|
||||
@@ -278,14 +295,13 @@ merged = resolver.resolve(entities, strategy="semantic_v2")
|
||||
Detects and resolves fact conflicts across overlapping knowledge sources.
|
||||
|
||||
```python
|
||||
from semantica.conflicts import ConflictDetector
|
||||
from semantica.conflicts import ConflictDetector, ConflictResolver
|
||||
|
||||
detector = ConflictDetector()
|
||||
conflicts = detector.detect_conflicts(kg)
|
||||
resolved = detector.resolve(conflicts, strategy="most_recent")
|
||||
conflicts = ConflictDetector().detect_conflicts(entities) # list of entity dicts
|
||||
resolved = ConflictResolver().resolve_conflicts(conflicts, strategy="most_recent")
|
||||
```
|
||||
|
||||
**Detection types:** value conflicts, type conflicts, temporal conflicts, logical conflicts
|
||||
**Detection types:** value conflicts, type conflicts, relationship conflicts, temporal conflicts, logical conflicts
|
||||
|
||||
**Resolution strategies:** prefer most recent, prefer most reliable source, majority vote, flag for manual review
|
||||
|
||||
@@ -298,6 +314,7 @@ Agent context graphs, decision tracking, causal chains, and precedent search.
|
||||
|
||||
```python
|
||||
from semantica.context import AgentContext, ContextGraph
|
||||
from semantica.vector_store import VectorStore
|
||||
|
||||
context = AgentContext(
|
||||
vector_store=VectorStore(backend="faiss", dimension=768),
|
||||
@@ -328,7 +345,7 @@ W3C PROV-O compliant lineage tracking across all modules.
|
||||
from semantica.provenance import ProvenanceManager
|
||||
|
||||
manager = ProvenanceManager()
|
||||
manager.track_entity("entity_1", "document.pdf", "person")
|
||||
manager.track_entity("entity_1", source="document.pdf", metadata={"type": "person"})
|
||||
lineage = manager.get_lineage("entity_1")
|
||||
```
|
||||
|
||||
@@ -364,8 +381,8 @@ RDFExporter().export(graph, file_path="graph.ttl", format="turtle")
|
||||
# Analytics
|
||||
ParquetExporter().export(graph, file_path="output/graph.parquet")
|
||||
|
||||
# ArangoDB
|
||||
aql = ArangoAQLExporter().export(graph)
|
||||
# ArangoDB: writes AQL INSERT statements to the given path
|
||||
ArangoAQLExporter().export(graph, file_path="graph.aql")
|
||||
```
|
||||
|
||||
**Export formats:** RDF (Turtle, JSON-LD, N-Triples, XML), Parquet, ArangoDB AQL, CSV, OWL, Arrow, LPG, YAML, distance matrices
|
||||
@@ -390,16 +407,24 @@ viz.visualize_network(graph, output="html", file_path="graph.html")
|
||||
Pipeline DSL with parallel workers, retry policies, and failure handling.
|
||||
|
||||
```python
|
||||
from semantica.pipeline import Pipeline
|
||||
from semantica.pipeline import PipelineBuilder, ExecutionEngine
|
||||
from semantica.ingest import FileIngestor
|
||||
from semantica.semantic_extract import NERExtractor
|
||||
|
||||
pipeline = Pipeline()
|
||||
pipeline.add_step("ingest", FileIngestor())
|
||||
pipeline.add_step("extract", NERExtractor())
|
||||
pipeline.add_step("build", GraphBuilder())
|
||||
result = pipeline.run("data/")
|
||||
builder = PipelineBuilder()
|
||||
|
||||
# Each step type dispatches to a handler you register (or supply explicitly)
|
||||
builder.register_step_handler("ingest", lambda data, **c: FileIngestor().ingest(c["source"]))
|
||||
builder.register_step_handler("extract", lambda docs, **c: NERExtractor(method="pattern").extract(docs[0].text))
|
||||
|
||||
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:** `Pipeline`, `PipelineBuilder`, `ExecutionEngine`, `FailureHandler`, `PipelineValidator`, `ParallelismManager`, `ResourceScheduler`
|
||||
**Components:** `PipelineBuilder`, `Pipeline`, `ExecutionEngine`, `FailureHandler`, `PipelineValidator`, `ParallelismManager`, `ResourceScheduler`
|
||||
|
||||
### Explorer
|
||||
|
||||
@@ -428,7 +453,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"))
|
||||
```
|
||||
|
||||
**Supported providers:** OpenAI, Anthropic, Google Gemini, Groq, Ollama, DeepSeek, Novita AI, LiteLLM (20+ models via one interface)
|
||||
**Supported providers:** OpenAI, Anthropic, Google Gemini, Groq, Ollama, DeepSeek, Novita AI, HuggingFace, plus LiteLLM (100+ models via one interface)
|
||||
|
||||
### MCP Server
|
||||
|
||||
@@ -445,44 +470,43 @@ python -m semantica.mcp_server
|
||||
Bootstrap knowledge graphs from verified structured sources: fixed-point reference data, controlled vocabularies, and domain anchors.
|
||||
|
||||
```python
|
||||
from semantica.seed import SeedManager
|
||||
from semantica.seed import SeedDataManager
|
||||
|
||||
seed = SeedManager()
|
||||
seed.populate(kg, dataset="companies", count=100)
|
||||
seed = SeedDataManager()
|
||||
|
||||
# Load domain seeds from file or built-in datasets
|
||||
seed.load_from_file("seed_data/industries.json")
|
||||
seed.inject(kg) # merges seed nodes without duplicating existing entities
|
||||
# Load trusted reference data from CSV / JSON / a database / an API
|
||||
seed_data = seed.load_from_csv("seed_data/industries.csv", entity_type="Industry")
|
||||
|
||||
# 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.
|
||||
|
||||
### Evals
|
||||
|
||||
Evaluation framework for measuring KG quality, extraction accuracy, and pipeline performance.
|
||||
Scores decision-intelligence outputs (decision records, audit trails, reasoning
|
||||
text) with a registry of deterministic and model-backed evaluators plus a small
|
||||
run harness.
|
||||
|
||||
```python
|
||||
from semantica.evals import KGEvaluator, ExtractionEvaluator, PipelineEvaluator, RegressionTracker
|
||||
from semantica.evals import evaluate, list_evaluators
|
||||
|
||||
# KG quality
|
||||
report = KGEvaluator().evaluate(kg, ontology=ontology)
|
||||
print(f"Completeness: {report.completeness:.2%} Consistency: {report.consistency:.2%}")
|
||||
list_evaluators()
|
||||
# ['decision_scores', 'exact_match', 'keyword_check', 'length_range',
|
||||
# 'levenshtein', 'llm_as_judge', 'numeric_range', 'regex_match', 'rouge',
|
||||
# 'temporal_range']
|
||||
|
||||
# Extraction accuracy
|
||||
report = ExtractionEvaluator().evaluate_ner(predictions=extracted, gold_standard=annotated)
|
||||
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")
|
||||
cases = [("apple", "aple"), ("night", "nacht")]
|
||||
summary = evaluate(cases, evaluators=["levenshtein"])
|
||||
print(summary.total, summary.passed, summary.pass_rate)
|
||||
```
|
||||
|
||||
**Components:** `KGEvaluator`, `ExtractionEvaluator`, `PipelineEvaluator`, `RegressionTracker`
|
||||
**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).
|
||||
|
||||
### Core
|
||||
|
||||
@@ -491,20 +515,20 @@ Base classes, shared data models, and the plugin registry used across all module
|
||||
```python
|
||||
from semantica.core import Semantica, PluginRegistry, ConfigManager
|
||||
|
||||
# Top-level orchestrator
|
||||
sem = Semantica(config_path="config.yaml")
|
||||
# ConfigManager loads a Config; Config.get() does dotted lookups
|
||||
config = ConfigManager().load_from_file("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()
|
||||
|
||||
# Plugin registry: register custom components
|
||||
# Plugin registry: register custom components under a name
|
||||
registry = PluginRegistry()
|
||||
registry.register("my_ingestor", MyCustomIngestor)
|
||||
|
||||
# Config management
|
||||
config = ConfigManager(config_path="config.yaml")
|
||||
batch = config.get("processing.batch_size", default=32)
|
||||
registry.register_plugin("my_ingestor", MyCustomIngestor, version="1.0.0")
|
||||
```
|
||||
|
||||
**Components:** `Semantica`, `PluginRegistry`, `ConfigManager`, `LifecycleManager`, `HealthMonitor`, `Config`
|
||||
**Components:** `Semantica`, `PluginRegistry`, `ConfigManager`, `Config`, `LifecycleManager`, `HealthStatus`, `MethodRegistry`
|
||||
|
||||
### Utils
|
||||
|
||||
@@ -532,11 +556,13 @@ from semantica.semantic_extract import NERExtractor, RelationExtractor
|
||||
from semantica.kg import GraphBuilder
|
||||
|
||||
sources = FileIngestor().ingest("data/")
|
||||
parsed = DocumentParser().parse(sources[0])
|
||||
entities = NERExtractor(method="llm", llm_provider=llm).extract(parsed)
|
||||
relationships = RelationExtractor(method="llm", llm_provider=llm).extract(parsed, entities=entities)
|
||||
text = DocumentParser().parse(sources[0].path)["full_text"]
|
||||
ner = NERExtractor(method="llm", provider="groq", llm_model="llama-3.3-70b-versatile")
|
||||
rel = RelationExtractor(method="llm", provider="groq", llm_model="llama-3.3-70b-versatile")
|
||||
entities = ner.extract(text)
|
||||
relationships = rel.extract(text, entities=entities)
|
||||
graph = GraphBuilder(merge_entities=True).build(
|
||||
entities=entities, relationships=relationships
|
||||
{"entities": entities, "relationships": relationships}
|
||||
)
|
||||
```
|
||||
|
||||
@@ -555,16 +581,20 @@ from semantica.vector_store import VectorStore
|
||||
context = AgentContext(
|
||||
vector_store=VectorStore(backend="faiss", dimension=768),
|
||||
knowledge_graph=ContextGraph(advanced_analytics=True),
|
||||
graph_expansion=True,
|
||||
)
|
||||
context.load_graph("company_kg.json")
|
||||
|
||||
result = context.query(
|
||||
# store() extracts entities and populates the graph + vector index
|
||||
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?",
|
||||
mode="graphrag",
|
||||
reasoning=True,
|
||||
use_graph=True,
|
||||
expand_graph=True,
|
||||
)
|
||||
for claim in result.claims:
|
||||
print(f"{claim.text} → {claim.source_node}")
|
||||
for r in results:
|
||||
print(f"[{r['score']:.3f}] {r['content']} (source: {r['source']})")
|
||||
```
|
||||
|
||||
**Best for:** question-answering systems, RAG with source attribution, research assistants
|
||||
@@ -606,18 +636,22 @@ precedents = context.find_precedents("model selection", limit=5)
|
||||
|
||||
```python
|
||||
from semantica.ingest import FileIngestor
|
||||
from semantica.parse import DocumentParser
|
||||
from semantica.semantic_extract import NERExtractor
|
||||
from semantica.kg import GraphBuilder
|
||||
from semantica.provenance import ProvenanceManager
|
||||
from semantica.export import RDFExporter
|
||||
|
||||
sources = FileIngestor().ingest("records/")
|
||||
entities = NERExtractor(method="llm", llm_provider=llm).extract(sources)
|
||||
graph = GraphBuilder(merge_entities=True).build(entities=entities, relationships=[])
|
||||
prov = ProvenanceManager()
|
||||
lineage = prov.get_entity_lineage("entity_id")
|
||||
ner = NERExtractor(method="llm", provider="groq", llm_model="llama-3.3-70b-versatile")
|
||||
entities = ner.extract(DocumentParser().parse(sources[0].path)["full_text"])
|
||||
graph = GraphBuilder(merge_entities=True).build({"entities": entities, "relationships": []})
|
||||
|
||||
RDFExporter(include_provenance=True).export(graph, file_path="audit.ttl", format="turtle")
|
||||
prov = ProvenanceManager()
|
||||
prov.track_entity("entity_id", source="records/filing.pdf", metadata={"extractor": "llm"})
|
||||
lineage = prov.get_lineage("entity_id")
|
||||
|
||||
RDFExporter().export(graph, file_path="audit.ttl", format="turtle")
|
||||
```
|
||||
|
||||
**Best for:** HIPAA, SOX, GDPR, FDA 21 CFR Part 11 deployments
|
||||
@@ -632,18 +666,25 @@ RDFExporter(include_provenance=True).export(graph, file_path="audit.ttl", format
|
||||
from semantica.ingest import WebIngestor
|
||||
from semantica.normalize import TextNormalizer
|
||||
from semantica.semantic_extract import NERExtractor, RelationExtractor
|
||||
from semantica.graph_store import Neo4jStore
|
||||
from semantica.graph_store import GraphStore
|
||||
from semantica.kg import GraphBuilder
|
||||
|
||||
pages = WebIngestor(max_depth=2).ingest("https://example.com")
|
||||
ingestor = WebIngestor()
|
||||
normalizer = TextNormalizer()
|
||||
store = Neo4jStore(uri="bolt://localhost:7687", user="neo4j", password="password")
|
||||
ner = NERExtractor(method="pattern")
|
||||
rel = RelationExtractor(method="pattern")
|
||||
|
||||
for page in pages:
|
||||
# The generic GraphStore wrapper exposes the add_nodes/add_edges interface
|
||||
# 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)
|
||||
entities = NERExtractor().extract(text)
|
||||
relationships = RelationExtractor().extract(text, entities=entities)
|
||||
store.add_nodes(entities)
|
||||
store.add_edges(relationships)
|
||||
entities = ner.extract(text)
|
||||
relationships = rel.extract(text, entities=entities)
|
||||
builder.build({"entities": entities, "relationships": relationships})
|
||||
```
|
||||
|
||||
**Best for:** competitive intelligence, news monitoring, research aggregation
|
||||
@@ -692,8 +733,8 @@ versioner.create_snapshot(kg, "2024-Q1", author="user@example.com", description=
|
||||
| [vector_store](/reference/vector_store) | Vector database | `VectorStore` |
|
||||
| [graph_store](/reference/graph_store) | Graph database | `GraphStore` |
|
||||
| [triplet_store](/reference/triplet_store) | RDF triple store | `TripletStore` |
|
||||
| [deduplication](/reference/deduplication) | Entity resolution | `EntityResolver`, `DuplicateDetector`, `ClusterBuilder`, `MergeStrategyManager` |
|
||||
| [conflicts](/reference/conflicts) | Conflict resolution | `ConflictDetector` |
|
||||
| [deduplication](/reference/deduplication) | Entity resolution | `DuplicateDetector`, `EntityMerger`, `ClusterBuilder`, `MergeStrategyManager` |
|
||||
| [conflicts](/reference/conflicts) | Conflict resolution | `ConflictDetector`, `ConflictResolver`, `SourceTracker` |
|
||||
| [context](/reference/context) | Agent context & decisions | `AgentContext`, `ContextGraph` |
|
||||
| [provenance](/reference/provenance) | W3C PROV-O lineage | `ProvenanceManager` |
|
||||
| [change_management](/reference/change_management) | Version control | `TemporalVersionManager` |
|
||||
@@ -703,8 +744,8 @@ versioner.create_snapshot(kg, "2024-Q1", author="user@example.com", description=
|
||||
| [explorer](/reference/explorer) | Knowledge Explorer UI | `semantica-explorer --graph <file>` |
|
||||
| [llms](/reference/llms) | LLM providers | `Groq`, `OpenAI`, `create_provider` |
|
||||
| [mcp_server](/reference/mcp_server) | MCP stdio server | `python -m semantica.mcp_server` |
|
||||
| [seed](/reference/seed) | KG bootstrapping from structured sources | `SeedManager` |
|
||||
| [evals](/reference/evals) | Quality evaluation | `KGEvaluator`, `ExtractionEvaluator`, `PipelineEvaluator`, `RegressionTracker` |
|
||||
| [seed](/reference/seed) | KG bootstrapping from structured sources | `SeedDataManager` |
|
||||
| [evals](/reference/evals) | Decision-intelligence evaluation | `evaluate`, `list_evaluators`, `EvalSummary` |
|
||||
| [core](/reference/core) | Base classes & registry | `Semantica`, `ConfigManager`, `PluginRegistry`, `LifecycleManager` |
|
||||
| [utils](/reference/utils) | Shared utilities | `helpers`, `validators` |
|
||||
|
||||
|
||||
@@ -129,7 +129,7 @@ from semantica.llms import Groq, OpenAI, LiteLLM, HuggingFaceLLM
|
||||
from semantica.llms import LiteLLM
|
||||
|
||||
llm = LiteLLM(
|
||||
model="anthropic/claude-sonnet-4-20250514",
|
||||
model="anthropic/claude-sonnet-5",
|
||||
api_key=os.getenv("ANTHROPIC_API_KEY"),
|
||||
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
|
||||
providers = {
|
||||
"fast": LiteLLM(model="groq/llama-3.1-8b-instant", api_key=os.getenv("GROQ_API_KEY")),
|
||||
"smart": LiteLLM(model="anthropic/claude-sonnet-4-20250514", api_key=os.getenv("ANTHROPIC_API_KEY"))
|
||||
"smart": LiteLLM(model="anthropic/claude-sonnet-5", api_key=os.getenv("ANTHROPIC_API_KEY"))
|
||||
}
|
||||
```
|
||||
|
||||
@@ -252,7 +252,7 @@ from semantica.llms import LiteLLM
|
||||
# pip install "semantica[llm-litellm]"
|
||||
|
||||
# Anthropic Claude
|
||||
llm = LiteLLM(model="anthropic/claude-opus-4-5", api_key=os.getenv("ANTHROPIC_API_KEY"))
|
||||
llm = LiteLLM(model="anthropic/claude-opus-4-7", api_key=os.getenv("ANTHROPIC_API_KEY"))
|
||||
|
||||
# Google Gemini
|
||||
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"))
|
||||
|
||||
# AWS Bedrock
|
||||
llm = LiteLLM(model="bedrock/anthropic.claude-3-5-sonnet-20241022-v2:0")
|
||||
llm = LiteLLM(model="bedrock/anthropic.claude-sonnet-4-5-20250929-v1:0")
|
||||
|
||||
# Novita AI
|
||||
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>")
|
||||
providers = {
|
||||
"Anthropic": LiteLLM(model="anthropic/claude-opus-4-5", api_key=os.getenv("ANTHROPIC_API_KEY")),
|
||||
"Anthropic": LiteLLM(model="anthropic/claude-opus-4-7", api_key=os.getenv("ANTHROPIC_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"),
|
||||
"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")),
|
||||
"Bedrock": LiteLLM(model="bedrock/anthropic.claude-3-5-sonnet-20241022-v2:0"),
|
||||
"Bedrock": LiteLLM(model="bedrock/anthropic.claude-sonnet-4-5-20250929-v1:0"),
|
||||
"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")),
|
||||
}
|
||||
@@ -416,7 +416,7 @@ for text in texts:
|
||||
| :---------- | :--------------------------- | :----------- |
|
||||
| **Entity Extraction** | `Groq("llama-3.3-70b-versatile")` | Fast, good accuracy for structured tasks |
|
||||
| **Relation Extraction** | `OpenAI("gpt-4o")` | Best at complex relationship reasoning |
|
||||
| **Complex Analysis** | `LiteLLM("anthropic/claude-sonnet-4-20250514")` | Highest reasoning capability |
|
||||
| **Complex Analysis** | `LiteLLM("anthropic/claude-sonnet-5")` | Highest reasoning capability |
|
||||
| **High Volume/Cost** | `LiteLLM("deepseek/deepseek-chat")` | Lowest cost per token |
|
||||
|
||||
### Error Handling
|
||||
|
||||
@@ -323,7 +323,7 @@ all_facts = datalog.derive_all()
|
||||
|
||||
# Query with variable pattern: variables start with uppercase or ?
|
||||
results = datalog.query("ancestor(alice, ?Z)")
|
||||
# → [{"Z": "bob"}, {"Z": "charlie"}, {"Z": "dave"}]
|
||||
# → a list of binding dicts: [{"Z": "bob"}, {"Z": "charlie"}, {"Z": "dave"}] (order not guaranteed)
|
||||
|
||||
# Clear and start over
|
||||
datalog.clear()
|
||||
|
||||
+36
-7
@@ -47,7 +47,11 @@ dependencies = [
|
||||
"numpy>=2.0.2",
|
||||
"pandas>=1.3.0",
|
||||
"scipy>=1.13.1",
|
||||
"scikit-learn>=1.7.2",
|
||||
# scikit-learn dropped Python 3.9 support at 1.7.0 (requires_python >=3.10),
|
||||
# so an unqualified >=1.7.2 floor is unsatisfiable on 3.9. Cap 3.9 to the
|
||||
# last 3.9-compatible release line; 3.10+ is left unconstrained.
|
||||
"scikit-learn>=1.6.1,<1.7.0; python_version < '3.10'",
|
||||
"scikit-learn>=1.7.2; python_version >= '3.10'",
|
||||
"umap-learn>=0.5.12",
|
||||
# thinc (spacy's core dep) dropped Python 3.9 wheels at 8.3.10, and later
|
||||
# spacy patch releases (3.8.8+) require thinc>=8.3.9-only-on-3.10+ ranges,
|
||||
@@ -66,24 +70,49 @@ dependencies = [
|
||||
"seaborn>=0.13.2",
|
||||
"plotly>=6.8.0",
|
||||
"ipywidgets>=8.0.0",
|
||||
"requests>=2.34.2",
|
||||
# requests dropped Python 3.9 support at 2.33.0 (requires_python >=3.10),
|
||||
# so an unqualified >=2.34.2 floor is unsatisfiable on 3.9. Cap 3.9 to the
|
||||
# last 3.9-compatible release; 3.10+ is left unconstrained.
|
||||
"requests>=2.32.5,<2.33.0; python_version < '3.10'",
|
||||
"requests>=2.34.2; python_version >= '3.10'",
|
||||
"GitPython>=3.1.58",
|
||||
"chardet>=7.4.3",
|
||||
# chardet dropped Python 3.9 support at 6.0.0 (requires_python >=3.10), so
|
||||
# an unqualified >=7.4.3 floor is unsatisfiable on 3.9. Cap 3.9 to the last
|
||||
# 3.9-compatible release; 3.10+ is left unconstrained.
|
||||
"chardet>=5.2.0,<6.0.0; python_version < '3.10'",
|
||||
"chardet>=7.4.3; python_version >= '3.10'",
|
||||
"protobuf>=5.29.1,<8.0",
|
||||
"grpcio>=1.81.1",
|
||||
# grpcio dropped Python 3.9 support at 1.81.0 (requires_python >=3.10), so
|
||||
# an unqualified >=1.81.1 floor is unsatisfiable on 3.9. Cap 3.9 to the last
|
||||
# 3.9-compatible release; 3.10+ is left unconstrained.
|
||||
"grpcio>=1.80.0,<1.81.0; python_version < '3.10'",
|
||||
"grpcio>=1.81.1; python_version >= '3.10'",
|
||||
"beautifulsoup4>=4.15.0",
|
||||
"lxml>=6.1.1",
|
||||
"python-docx>=1.2.0",
|
||||
"openpyxl>=3.1.5",
|
||||
"pillow>=12.2.0",
|
||||
# pillow dropped Python 3.9 support at 12.0.0 (requires_python >=3.10), so
|
||||
# an unqualified >=12.2.0 floor is unsatisfiable on 3.9. Cap 3.9 to the last
|
||||
# 3.9-compatible release; 3.10+ is left unconstrained.
|
||||
"pillow>=11.3.0,<12.0.0; python_version < '3.10'",
|
||||
"pillow>=12.2.0; python_version >= '3.10'",
|
||||
"librosa>=0.9.0",
|
||||
"opencv-python>=4.13.0.92",
|
||||
"faiss-cpu>=1.7.0",
|
||||
"fastembed>=0.2.0",
|
||||
"onnxruntime>=1.20.1",
|
||||
# onnxruntime stopped shipping cp39 wheels at 1.20.0 (its PyPI metadata
|
||||
# still claims requires_python >=3.9, but no matching wheel exists), so an
|
||||
# unqualified >=1.20.1 floor is unsatisfiable on 3.9. Cap 3.9 to the last
|
||||
# release with a cp39 wheel; 3.10+ is left unconstrained.
|
||||
"onnxruntime>=1.19.2,<1.20.0; python_version < '3.10'",
|
||||
"onnxruntime>=1.20.1; python_version >= '3.10'",
|
||||
"tokenizers>=0.15.0",
|
||||
"pydantic>=2.13.4",
|
||||
"click>=8.4.2",
|
||||
# click dropped Python 3.9 support at 8.2.0 (requires_python >=3.10), so an
|
||||
# unqualified >=8.4.2 floor is unsatisfiable on 3.9. Cap 3.9 to the last
|
||||
# 3.9-compatible release; 3.10+ is left unconstrained.
|
||||
"click>=8.1.8,<8.2.0; python_version < '3.10'",
|
||||
"click>=8.4.2; python_version >= '3.10'",
|
||||
"rich>=12.5.0",
|
||||
"tqdm>=4.68.3",
|
||||
"pyyaml>=6.0",
|
||||
|
||||
@@ -35,7 +35,7 @@ Example Usage:
|
||||
>>> llm = LiteLLM(model="openai/gpt-4o", api_key="your-key")
|
||||
>>> response = llm.generate("Hello, world!")
|
||||
>>> # Or use other providers via LiteLLM
|
||||
>>> llm = LiteLLM(model="anthropic/claude-sonnet-4-20250514")
|
||||
>>> llm = LiteLLM(model="anthropic/claude-sonnet-5")
|
||||
>>> response = llm.generate("Hello, world!")
|
||||
>>>
|
||||
>>> # Anthropic provider
|
||||
|
||||
@@ -31,7 +31,7 @@ class LiteLLM:
|
||||
Provides unified interface to 100+ LLM providers through LiteLLM library.
|
||||
Supports providers like OpenAI, Anthropic, Groq, Azure, Bedrock, Vertex AI, etc.
|
||||
|
||||
Model format: "provider/model-name" (e.g., "openai/gpt-4o", "anthropic/claude-sonnet-4-20250514", "groq/llama-3.1-8b-instant")
|
||||
Model format: "provider/model-name" (e.g., "openai/gpt-4o", "anthropic/claude-sonnet-5", "groq/llama-3.1-8b-instant")
|
||||
|
||||
Example:
|
||||
>>> from semantica.llms import LiteLLM
|
||||
@@ -39,7 +39,7 @@ class LiteLLM:
|
||||
>>> response = llm.generate("What is AI?")
|
||||
>>>
|
||||
>>> # Use with different providers
|
||||
>>> llm = LiteLLM(model="anthropic/claude-sonnet-4-20250514")
|
||||
>>> llm = LiteLLM(model="anthropic/claude-sonnet-5")
|
||||
>>> response = llm.generate("Hello!")
|
||||
"""
|
||||
|
||||
@@ -54,7 +54,7 @@ class LiteLLM:
|
||||
|
||||
Args:
|
||||
model: Model identifier in format "provider/model-name"
|
||||
Examples: "openai/gpt-4o", "anthropic/claude-sonnet-4-20250514",
|
||||
Examples: "openai/gpt-4o", "anthropic/claude-sonnet-5",
|
||||
"groq/llama-3.1-8b-instant", "azure/gpt-4", etc.
|
||||
api_key: API key (optional, can use environment variables)
|
||||
**kwargs: Additional LiteLLM options (temperature, max_tokens, etc.)
|
||||
|
||||
Reference in New Issue
Block a user