--- title: "Core Module" description: "Framework orchestration, lifecycle management, configuration, and plugin system." icon: "gear" --- `semantica.core` is the coordination layer for the framework. For most tasks you should use individual modules directly (`semantica.ingest`, `semantica.kg`, etc.). Reach for Core when you need application-level lifecycle management, centralized configuration, or a plugin registry. ## What You Get Orchestration class for coordinating complex multi-module workflows and full KG construction pipelines. Unified config loading, merging, and validation with environment variable overrides. Startup/shutdown hooks with priority ordering and component health monitoring. Dynamic plugin discovery, registration, loading, and unloading. Register and dispatch custom orchestration methods by name. Live configuration state — dot-notation access, update, validate, and serialize. **Use individual modules directly** for the vast majority of use cases. Use the `Semantica` orchestration class only when you need application-level lifecycle management or a plugin system. ## Quick Start ```python from semantica.core import ConfigManager manager = ConfigManager() config = manager.load_from_file("config.yaml") # Override one key at runtime config.set("processing.batch_size", 64) ``` ```python from semantica.core import Semantica framework = Semantica(config=config) framework.initialize() status = framework.get_status() print(f"State: {status['state']}") # → "READY" ``` ```python result = framework.build_knowledge_base( sources=["doc1.pdf", "doc2.docx"], embeddings=True, graph=True, ) ``` ```python # Always shut down in a finally block try: result = framework.build_knowledge_base(sources) finally: framework.shutdown(graceful=True) ``` ## Semantica (Orchestration) High-level entry point that coordinates the full KG construction pipeline: ```python from semantica.core import Semantica, ConfigManager config_manager = ConfigManager() config = config_manager.load_from_file("config.yaml") framework = Semantica(config=config) framework.initialize() try: result = framework.build_knowledge_base( sources=["doc1.pdf", "doc2.docx"], embeddings=True, graph=True, ) status = framework.get_status() print(f"State: {status['state']}") finally: framework.shutdown(graceful=True) ``` | Method | Description | | ------ | ----------- | | `initialize()` | Initialize all framework components | | `build_knowledge_base(sources, **kwargs)` | Orchestrate full KG construction pipeline | | `run_pipeline(pipeline, data)` | Execute an existing `Pipeline` instance | | `get_status()` | Return system health and current state | | `shutdown(graceful=True)` | Graceful shutdown — waits for in-flight operations | ## ConfigManager Centralized config loading with deep-merge and environment variable overrides: ```python from semantica.core import ConfigManager manager = ConfigManager() config = manager.load_from_file("config.yaml") # Merge base config with environment-specific overrides merged = manager.merge_configs( manager.load_from_file("base.yaml"), manager.load_from_file("prod.yaml"), ) # Nested dot-notation access batch_size = config.get("processing.batch_size", default=16) config.set("processing.batch_size", 64) config.update({"quality": {"min_confidence": 0.75}}, merge=True) config.validate() config_dict = config.to_dict() ``` ### Config Section Reference | Section | Key Fields | Description | | ------- | ---------- | ----------- | | `llm_provider` | `name`, `model`, `api_key`, `base_url` | LLM used for extraction and reasoning | | `embedding_model` | `provider`, `model`, `dimension`, `device` | Embedding provider and model | | `vector_store` | `backend`, `dimension`, `index_type` | Vector storage backend | | `graph_db` | `backend`, `uri`, `user`, `password` | Graph database connection | | `processing` | `batch_size`, `max_workers`, `chunk_size` | Parallelism and batching | | `pipeline` | `retry_max`, `backoff`, `failure_strategy` | Pipeline retry and failure policy | | `logging` | `level`, `format`, `file` | Logging configuration | | `quality` | `min_confidence`, `dedup_threshold` | Quality thresholds | | `security` | `redact_pii`, `allowed_domains` | Security and compliance settings | | `custom` | any key | User-defined extension settings | ### Environment Variable Overrides Any config key can be overridden with a `SEMANTICA_` prefix using double underscores for nesting: ```bash export SEMANTICA_PROCESSING__BATCH_SIZE=64 export SEMANTICA_LLM_PROVIDER__MODEL=gpt-4o export SEMANTICA_LOGGING__LEVEL=DEBUG export SEMANTICA_QUALITY__MIN_CONFIDENCE=0.8 ``` ## LifecycleManager Manages framework state with a defined state machine and ordered startup/shutdown hooks: ```python from semantica.core import LifecycleManager manager = LifecycleManager() def init_db(): print("Initializing database...") def cleanup_db(): print("Closing database connections...") # Lower priority values run first during startup # Higher priority values run first during shutdown manager.register_startup_hook(init_db, priority=10) manager.register_shutdown_hook(cleanup_db, priority=10) manager.startup() # Component health monitoring class DatabaseComponent: def health_check(self): return {"healthy": True, "message": "Connected"} manager.register_component("database", DatabaseComponent()) summary = manager.get_health_summary() # → {"database": {"healthy": True, "message": "Connected"}, ...} manager.shutdown(graceful=True) ``` ## PluginRegistry Register custom components that participate in the full pipeline: ```python from semantica.core import PluginRegistry class MyPlugin: def initialize(self): print("Plugin initialized") def execute(self, data): return {"processed": True} registry = PluginRegistry(plugin_paths=["./plugins"]) registry.register_plugin( "my_plugin", MyPlugin, version="1.0.0", description="Custom domain extractor", author="team@example.com", capabilities=["extract"], ) plugin = registry.load_plugin("my_plugin", api_key="xxx") result = plugin.execute("sample data") # Inspect registered plugins for info in registry.list_plugins(): print(f"{info['name']} v{info['version']} — {info['description']}") # Unload when done registry.unload_plugin("my_plugin") ``` ## MethodRegistry Register custom orchestration methods and dispatch them by name: ```python from semantica.core import method_registry def fast_kb_builder(sources, **kwargs): # Custom logic — skip embeddings for speed ... method_registry.register("knowledge_base", "fast", fast_kb_builder) from semantica.core.methods import build_knowledge_base result = build_knowledge_base(sources=["doc.pdf"], method="fast") ``` ## Schemas ```python from semantica.core import SystemState SystemState.UNINITIALIZED # → startup() → SystemState.INITIALIZING # → hooks complete → SystemState.READY # → first operation → SystemState.RUNNING # → shutdown() → SystemState.STOPPING # → hooks complete → SystemState.STOPPED # Any unhandled exception during startup/shutdown → SystemState.ERROR ``` Check current state at any time: ```python state = manager.get_state() if manager.is_ready(): result = framework.build_knowledge_base(sources) ``` ```python @dataclass class HealthStatus: component: str # component name healthy: bool # True = operational message: str # human-readable status timestamp: datetime # time of last check details: Dict[str, Any] # component-specific diagnostics ``` ```python health = manager.health_check() for name, status in health.items(): icon = "✓" if status.healthy else "✗" print(f"{icon} {name}: {status.message}") ``` ```python @dataclass class PluginInfo: name: str version: str plugin_class: Type description: str author: str dependencies: List[str] # pip package names required capabilities: List[str] # e.g. ["ingest", "extract"] metadata: Dict[str, Any] @dataclass class LoadedPlugin: info: PluginInfo instance: Any # the live plugin object config: Dict[str, Any] # config passed at load time loaded_at: datetime ``` ```python registry = PluginRegistry() registry.register_plugin("my_plugin", MyPlugin, version="1.0.0") if registry.is_plugin_loaded("my_plugin"): plugin = registry.get_loaded_plugin("my_plugin") else: plugin = registry.load_plugin("my_plugin") details = registry.get_plugin_info("my_plugin") ``` ## Complete Configuration Example ```yaml # config.yaml llm_provider: name: groq model: llama-3.3-70b-versatile api_key: ${GROQ_API_KEY} embedding_model: provider: sentence-transformers model: all-mpnet-base-v2 dimension: 768 device: cpu # "cpu" | "cuda" | "mps" vector_store: backend: faiss dimension: 768 index_type: hnsw # "flat" | "ivf" | "hnsw" | "pq" graph_db: backend: neo4j uri: bolt://localhost:7687 user: neo4j password: ${NEO4J_PASSWORD} processing: batch_size: 32 max_workers: 4 chunk_size: 512 pipeline: retry_max: 3 backoff: exponential # "fixed" | "linear" | "exponential" failure_strategy: skip # "skip" | "stop" | "retry" quality: min_confidence: 0.7 dedup_threshold: 0.85 logging: level: INFO # DEBUG | INFO | WARNING | ERROR format: "%(asctime)s %(name)s %(levelname)s %(message)s" ``` Load and use: ```python from semantica.core import ConfigManager, Semantica manager = ConfigManager() config = manager.load_from_file("config.yaml") config.set("processing.batch_size", 64) # runtime override framework = Semantica(config=config) framework.initialize() result = framework.build_knowledge_base(["doc1.pdf", "doc2.docx"]) framework.shutdown() ``` ## Tips and Common Pitfalls **Use individual modules directly unless you need application lifecycle management.** `Semantica` orchestrates the full pipeline, but for simple scripts and notebooks, using `FileIngestor`, `NERExtractor`, and `GraphBuilder` directly is clearer and more debuggable. **Always call `framework.shutdown(graceful=True)` in a `finally` block.** Without graceful shutdown, in-flight pipeline steps may leave partial writes in your vector store or graph database. Wrapping in `try/finally` guarantees cleanup even on exceptions. **Use `ConfigManager.merge_configs()` for environment-specific overrides.** Keep a `base.yaml` with default settings and a `prod.yaml` with overrides. Merge them at startup rather than maintaining separate copies — this prevents configuration drift between environments. **Environment variable overrides use double underscores for nesting.** `SEMANTICA_PROCESSING__BATCH_SIZE=64` sets `processing.batch_size` — the double underscore (`__`) represents a nesting level. A single underscore is reserved for multi-word keys within the same level. **Register startup hooks with explicit priorities.** `register_startup_hook(fn, priority=10)` — lower numbers run first. If your database hook (priority 10) must run before your cache hook (priority 20), those numbers guarantee the order. Without explicit priorities, execution order is undefined. **Check `manager.is_ready()` before running pipelines.** If `Semantica.initialize()` failed partway through (e.g., a database connection refused), the state transitions to `ERROR` rather than `READY`. Always check before submitting work to avoid errors that are hard to trace. Pipeline execution and step orchestration. Shared utilities used by Core internally. Learn the basics before using Core. Configure LLM providers via ConfigManager.