Data Models¶
qortex uses a rich data model to capture knowledge graphs with full provenance.
Core Models¶
ConceptNode¶
A concept extracted from source material.
from qortex.core.models import ConceptNode
node = ConceptNode(
id="circuit_breaker", # Unique identifier
name="Circuit Breaker", # Human-readable name
description="Pattern that...", # Full description
domain="error_handling", # Domain it belongs to
source_id="patterns_book", # Where it came from
source_location="Chapter 3", # Optional: specific location
confidence=0.95, # Extraction confidence
properties={}, # Extensible metadata
)
| Field | Type | Required | Description |
|---|---|---|---|
id |
str | Yes | Unique identifier within the graph |
name |
str | Yes | Human-readable name |
description |
str | Yes | Full description |
domain |
str | Yes | Domain this belongs to |
source_id |
str | Yes | Source identifier for provenance |
source_location |
str | No | Location within source (chapter, page) |
confidence |
float | No | Extraction confidence (0-1), default 1.0 |
properties |
dict | No | Extensible metadata |
ConceptEdge¶
A relationship between two concepts.
from qortex.core.models import ConceptEdge, RelationType
edge = ConceptEdge(
source_id="circuit_breaker",
target_id="timeout",
relation_type=RelationType.REQUIRES,
confidence=0.9,
bidirectional=False,
properties={},
)
| Field | Type | Required | Description |
|---|---|---|---|
source_id |
str | Yes | Source concept ID |
target_id |
str | Yes | Target concept ID |
relation_type |
RelationType | Yes | Semantic relationship type |
confidence |
float | No | Edge confidence (0-1), default 1.0 |
bidirectional |
bool | No | Whether edge goes both ways |
properties |
dict | No | Extensible metadata |
RelationType¶
Semantic relationship types between concepts.
from qortex.core.models import RelationType
# Logical relationships
RelationType.CONTRADICTS # A and B are mutually exclusive
RelationType.REQUIRES # A requires B to be true/present
RelationType.REFINES # A is a more specific form of B
RelationType.IMPLEMENTS # A is a concrete implementation of B
# Compositional relationships
RelationType.PART_OF # A is a component of B
RelationType.USES # A uses/depends on B
# Similarity relationships
RelationType.SIMILAR_TO # A and B are related/analogous
RelationType.ALTERNATIVE_TO # A can substitute for B
# Epistemic relationships
RelationType.SUPPORTS # A provides evidence for B
RelationType.CHALLENGES # A provides counter-evidence for B
CodeExample¶
A code example linked to concepts and rules. Structure matches SQLAlchemy model for direct deserialization.
from qortex.core.models import CodeExample
example = CodeExample(
id="patterns:example:iterator",
code="""class Iterator:
def __iter__(self): return self
def __next__(self): raise StopIteration""",
language="python",
description="Shows the iterator protocol",
source_location="ch11:p42",
concept_ids=["patterns:Iterator", "patterns:Protocol"],
rule_ids=["patterns:rule:0"],
tags=["iterator", "design-pattern"],
is_antipattern=False,
properties={"complexity": "low"},
)
| Field | Type | Required | Description |
|---|---|---|---|
id |
str | Yes | Unique example identifier |
code |
str | Yes | The code snippet (preserves formatting) |
language |
str | Yes | Programming language |
description |
str | No | What this example demonstrates |
source_location |
str | No | Location within source (e.g., "ch11:p42") |
concept_ids |
list[str] | No | Concepts this example illustrates |
rule_ids |
list[str] | No | Rules this example demonstrates |
tags |
list[str] | No | Tags for retrieval |
is_antipattern |
bool | No | True if this is a "what not to do" example |
properties |
dict | No | Extensible metadata |
Use cases: - Few-shot prompting: Rule -> Examples -> prompt context - 2nd-order retrieval: Query -> similar code -> linked concepts -> related rules - Contrastive learning: Good example vs antipattern for the same rule
ExplicitRule¶
A rule explicitly stated in source material.
from qortex.core.models import ExplicitRule
rule = ExplicitRule(
id="rule:timeout",
text="Always configure timeouts for external calls",
domain="error_handling",
source_id="patterns_book",
concept_ids=["timeout", "circuit_breaker"],
source_location="Chapter 3, page 45",
category="architectural",
confidence=1.0,
)
| Field | Type | Required | Description |
|---|---|---|---|
id |
str | Yes | Unique rule identifier |
text |
str | Yes | The rule text |
domain |
str | Yes | Domain this belongs to |
source_id |
str | Yes | Source identifier |
concept_ids |
list[str] | No | Related concept IDs |
source_location |
str | No | Location within source |
category |
str | No | Rule category (architectural, testing, etc.) |
confidence |
float | No | Rule confidence (0-1), default 1.0 |
Rule¶
A rule as returned to consumers (includes both explicit and derived).
from qortex.core.models import Rule
rule = Rule(
id="rule:timeout",
text="Always configure timeouts",
domain="error_handling",
derivation="explicit", # or "derived"
source_concepts=["timeout"],
confidence=1.0,
relevance=0.0,
category="architectural",
metadata={}, # Template info for derived rules
)
| Field | Type | Required | Description |
|---|---|---|---|
id |
str | Yes | Unique rule identifier |
text |
str | Yes | The rule text |
domain |
str | Yes | Domain this belongs to |
derivation |
str | Yes | "explicit" or "derived" |
source_concepts |
list[str] | Yes | Concept IDs it came from |
confidence |
float | Yes | Rule confidence (0-1) |
relevance |
float | No | Relevance score from retrieval |
category |
str | No | Rule category |
metadata |
dict | No | Template info for derived rules |
Domain¶
An isolated subgraph (like a database schema).
from qortex.core.models import Domain
domain = Domain(
name="error_handling",
description="Error handling patterns and strategies",
source_ids=["patterns_book"],
concept_count=15,
edge_count=23,
rule_count=8,
)
| Field | Type | Required | Description |
|---|---|---|---|
name |
str | Yes | Domain identifier |
description |
str | No | Human-readable description |
source_ids |
list[str] | No | Sources that contributed |
concept_count |
int | No | Number of concepts |
edge_count |
int | No | Number of edges |
rule_count |
int | No | Number of rules |
created_at |
datetime | No | Creation timestamp |
updated_at |
datetime | No | Last update timestamp |
Ingestion Models¶
IngestionManifest¶
The output of an ingestor, consumed by the KG.
from qortex.core.models import IngestionManifest, SourceMetadata
manifest = IngestionManifest(
source=SourceMetadata(...),
domain="error_handling",
concepts=[...],
edges=[...],
rules=[...],
examples=[...], # Code examples linked to concepts
extraction_confidence=0.95,
warnings=["Low confidence on some extractions"],
)
This is the contract between ingestion and storage. The KG doesn't know about PDFs or Markdown - it just knows manifests.
| Field | Type | Required | Description |
|---|---|---|---|
source |
SourceMetadata | Yes | Source information |
domain |
str | Yes | Domain name |
concepts |
list[ConceptNode] | Yes | Extracted concepts |
edges |
list[ConceptEdge] | Yes | Extracted relationships |
rules |
list[ExplicitRule] | Yes | Extracted rules |
examples |
list[CodeExample] | No | Extracted code examples |
extraction_confidence |
float | No | Overall confidence |
warnings |
list[str] | No | Extraction warnings |
SourceMetadata¶
Metadata about an ingested source.
from qortex.core.models import SourceMetadata
source = SourceMetadata(
id="patterns_book",
name="Design Patterns Book",
source_type="pdf",
path_or_url="/path/to/book.pdf",
content_hash="sha256:...",
chunk_count=45,
concept_count=23,
rule_count=8,
)
Projection Models¶
EnrichedRule¶
A rule paired with its enrichment.
from qortex.projectors.models import EnrichedRule, RuleEnrichment
enriched = EnrichedRule(
rule=rule,
enrichment=RuleEnrichment(
context="When making external calls",
antipattern="No timeout limits",
rationale="Prevents cascading failures",
tags=["timeout", "resilience"],
enrichment_version=1,
enriched_at=datetime.now(timezone.utc),
enrichment_source="anthropic",
),
)
RuleEnrichment¶
Enrichment data for a rule.
from qortex.projectors.models import RuleEnrichment
enrichment = RuleEnrichment(
context="When this rule applies",
antipattern="What violating looks like",
rationale="Why this matters",
tags=["tag1", "tag2"],
enrichment_version=1,
enriched_at=datetime.now(timezone.utc),
enrichment_source="template", # or "anthropic"
source_contexts=[], # Re-enrichment history
)
ProjectionFilter¶
Filter options for rule projection.
from qortex.projectors.models import ProjectionFilter
filters = ProjectionFilter(
min_confidence=0.8,
categories=["architectural"],
exclude_derived=False,
)
Edge Rule Templates¶
qortex includes 30 templates for deriving rules from edges (3 variants x 10 relation types).
from qortex.core.templates import EdgeRuleTemplate, get_template, TEMPLATE_REGISTRY
# Get a specific template
template = get_template("requires:imperative")
# Generate rule text
text = template.render(
source_name="Circuit Breaker",
target_name="Timeout",
)
# -> "Ensure Circuit Breaker has Timeout configured"
# List all templates
for template_id in TEMPLATE_REGISTRY:
print(template_id)
Template variants:
| Variant | Style | Example |
|---|---|---|
imperative |
Direct command | "Ensure A has B" |
conditional |
When/then | "When using A, ensure B" |
warning |
Caution | "Using A without B may cause issues" |
Interop Models¶
InteropConfig¶
Configuration for the consumer interop protocol.
from qortex.interop import InteropConfig, SeedsConfig, SignalsConfig
config = InteropConfig(
seeds=SeedsConfig(
pending=Path("~/.qortex/seeds/pending"),
processed=Path("~/.qortex/seeds/processed"),
failed=Path("~/.qortex/seeds/failed"),
),
signals=SignalsConfig(
projections=Path("~/.qortex/signals/projections.jsonl"),
),
)
ProjectionEvent¶
An event in the signal log.
from qortex.interop import ProjectionEvent
event = ProjectionEvent(
event="projection_complete",
persona="error_rules",
domain="error_handling",
path="/path/to/seed.yaml",
rule_count=5,
ts="2026-02-05T12:00:00Z",
source="qortex",
source_version="0.1.0",
)
Type Hints¶
All models use Python dataclasses with full type hints:
from qortex.core.models import ConceptNode, ConceptEdge, RelationType
from typing import reveal_type
node = ConceptNode(...)
reveal_type(node.confidence) # float
reveal_type(node.properties) # dict[str, Any]
Serialization¶
Models serialize cleanly to dict/JSON:
import dataclasses
import json
node = ConceptNode(...)
node_dict = dataclasses.asdict(node)
node_json = json.dumps(node_dict)
For the universal schema format, use serialize_ruleset():
from qortex.projectors.targets._serialize import serialize_ruleset
seed = serialize_ruleset(
enriched_rules=rules,
persona_name="my_rules",
version=1,
)