How to Debug Issues in Semantica AGI: A Complete Troubleshooting Guide
Semantica AGI exposes a comprehensive logging framework centered in semantica/utils/logging.py that serves as the primary entry point for troubleshooting, allowing developers to configure granular log levels, capture performance metrics, and structure error reports across the entire stack.
Effective debugging in Semantica AGI requires understanding its hierarchical logging system, which routes diagnostics from worker processes, vector stores, and multi-agent coordination layers through a unified pipeline. By leveraging the utilities defined in the semantica-agi/semantica repository, you can isolate failures without modifying core logic.
Core Logging Architecture
Initialization and Configuration
The debugging lifecycle begins at the application entry point. In semantica/worker.py, the process immediately invokes setup_logging() at lines 15-16 to establish the root logger before any other imports occur. This ensures that all subsequent components—from vector-store backends to visualization modules—inherit the same configuration.
Default behavior is governed by DEFAULT_CONFIG in semantica/utils/constants.py (lines 95-101), which sets the baseline to INFO level and attaches a RotatingFileHandler writing to semantica.log. You can override these defaults at runtime by passing arguments to setup_logging(level="DEBUG", file="custom.log"), which clears existing handlers via root_logger.handlers.clear() before applying new settings. As implemented in semantica/utils/logging.py (lines 32-34), the root logger’s propagate flag is explicitly set to False to prevent duplicate messages from reaching Python’s global root logger.
Namespaced Logger Hierarchy
The framework creates isolated channels for different subsystems using get_logger(name), defined at lines 57-65 of semantica/utils/logging.py. This function returns a logger named semantica.<name>, allowing you to target specific domains like vector_store, performance, error, or quality. By adjusting individual logger levels, you can silence noisy modules while maintaining verbose output for the component under investigation.
Step-by-Step Debugging Workflow
Step 1: Configure Global Debug Logging
Raise the verbosity across the entire application either by setting the environment variable LOGGING_LEVEL=DEBUG or by programmatically calling setup_logging(level="DEBUG") before importing other Semantica modules. This elevates the root logger’s level, causing all child loggers to inherit the new threshold and emit granular diagnostic data.
from semantica.utils import setup_logging, get_logger
# Turn on verbose debugging and write to a dedicated file
logger = setup_logging(level="DEBUG", file="debug.log")
app_logger = get_logger(__name__) # namespaced under semantica.__name__
app_logger.debug("Debugging session initialized")
Step 2: Enable File Persistence
To retain logs beyond the console session, specify a file path when configuring the logger. The framework automatically instantiates a RotatingFileHandler that manages log rotation, preventing disk space exhaustion during extended debug sessions. This persistent output is essential for post-mortem analysis of failures that crash the worker process.
Step 3: Isolate Subsystem Issues
Avoid console noise by targeting specific components. Obtain a subsystem-specific logger via get_logger("vector_store") or get_logger("visualization"), then adjust its level independently using logger.setLevel(logging.DEBUG). This fine-grained approach allows you to debug the vector-store backend without being overwhelmed by unrelated messages from the layout algorithms or MCP session layers.
Step 4: Instrument Performance-Critical Code
Identify bottlenecks using the @log_execution_time decorator (lines 50-58) or the log_performance() helper (lines 78-86), both defined in semantica/utils/logging.py. These utilities automatically capture execution duration and optional metrics like memory usage and cache hit rates.
from semantica.utils import log_execution_time, log_performance
import time
@log_execution_time
def heavy_computation(data):
# … intensive work …
return result
# Or manually log performance
start = time.time()
result = heavy_computation(my_data)
log_performance("heavy_computation", time.time() - start,
memory_usage=200 * 1024 * 1024, cache_hit=False)
Step 5: Capture Structured Exceptions
Replace standard try/except blocks with log_error() (lines 30-38) to capture full stack traces alongside contextual data. This function stores supplementary information in the log record’s extra dictionary, making it searchable in aggregation tools like ELK or Loki.
from semantica.utils import log_error, get_logger
logger = get_logger("my_module")
try:
risky_operation()
except Exception as exc:
log_error(exc,
context={"operation": "risky_operation", "input": payload},
include_traceback=True,
level="ERROR",
escalate=True) # will also log a CRITICAL entry
Step 6: Detect Data Quality Degradation
Monitor model output health using log_data_quality() (lines 84-92), which emits structured log lines containing quality scores. When a score falls below a configurable threshold, the utility automatically raises a warning, helping you catch silent degradation in AGI pipelines before it impacts downstream tasks.
Step 7: Analyze Logs and Verify with Tests
Inspect the generated logs using tail -f debug.log or load them into a centralized viewer. Search for timestamps, specific logger names (e.g., semantica.vector_store), or severity levels (ERROR, WARNING). For reproducible debugging, run the test suite with pytest -vv; the integrated logging fixtures capture debug output for each test, providing internal state visibility during CI failures.
Common Pitfalls and Solutions
- Multiple initialization calls: Invoking
setup_logging()repeatedly overwrites earlier handler configurations. Ensure the function is called exactly once, typically insemantica/worker.py, to maintain consistent output. - Handler duplication: While the implementation clears existing handlers before adding new ones, bypassing
setup_logging()to manually attach handlers can cause duplicate entries. Always use the provided utility to manage handler lifecycle. - Propagation side effects: Because the root logger has
propagate=False, messages will not bubble up to Python’s default root logger. This prevents double-logging but means you must rely on Semantica’s configured handlers for output capture.
Summary
- Initialize logging via
setup_logging()early in the application lifecycle, as demonstrated insemantica/worker.py, to ensure allcomponents route through the same hierarchy. - Configure verbose output by setting
level="DEBUG"or theLOGGING_LEVELenvironment variable to capture detailed subsystem behavior. - Use
get_logger(name)to obtain namespaced loggers that allow fine-grained control over specific components without console noise. - Instrument performance-critical paths with
@log_execution_timeorlog_performance()to identify bottlenecks through automatic timing and memory metrics. - Capture actionable error context using
log_error()with structured data and traceback inclusion for root-cause analysis in production environments. - Monitor model health with
log_data_quality()to detect silent degradation in AGI outputs via configurable threshold warnings.
Frequently Asked Questions
How do I enable debug logging without modifying source code?
Set the LOGGING_LEVEL environment variable to DEBUG before launching the worker process. The framework reads this during initialization in semantica/worker.py, configuring the root logger and all child loggers to emit verbose diagnostic information without requiring code changes.
Why are my log entries appearing twice in the console?
Duplicate entries typically occur when setup_logging() is invoked multiple times or when custom handlers are added manually without clearing previous ones. The implementation in semantica/utils/logging.py explicitly calls root_logger.handlers.clear() to prevent this, so ensure you are not bypassing the standard initialization.
How can I debug performance issues in a specific module?
Target the subsystem by obtaining its namespaced logger via get_logger("vector_store") (or the appropriate module name) and enabling debug-level output specifically for that logger. For granular timing data, apply the @log_execution_time decorator to expensive functions or call log_performance() manually with custom metrics like memory usage and cache hit rates to pinpoint exact bottlenecks.
Where are the default logging settings defined?
Default configurations reside in the DEFAULT_CONFIG dictionary within semantica/utils/constants.py (lines 95-101), which specifies an INFO logging level and a rotating file handler writing to semantica.log. These defaults are loaded by setup_logging() in semantica/utils/logging.py and can be overridden at runtime via arguments or environment variables.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →