Syntactic and Semantic Modes of the Symbol Class in SymbolicAI
The Symbol class operates in two distinct modes—syntactic (raw Python data processing) and semantic (LLM-driven neuro-symbolic reasoning)—controlled by an internal __semantic__ flag that determines whether operations execute locally or route through the language model engine.
The dual-mode architecture in the extensityai/symbolicai repository allows developers to fluidly switch between deterministic Python execution and AI-augmented symbolic reasoning. Understanding these syntactic and semantic modes is essential for effectively leveraging the library's neuro-symbolic capabilities.
Understanding Syntactic vs Semantic Modes
The Symbol class distinguishes between two operational states through an internal boolean flag:
-
Syntactic mode (
__semantic__ = False): The instance behaves as ordinary Python data. Arithmetic operators, string methods, and logical operations execute directly on the raw value without LLM invocation. This mode is ideal for pure data manipulation, performance-critical paths, or when deterministic behavior is required. -
Semantic mode (
__semantic__ = True): The instance becomes a prompt-driven, neuro-symbolic entity. Operations are routed through the configured LLM engine, enabling natural language understanding, contextual reasoning, and AI-augmented transformations. For example, the bitwise negation operator (~) sends a prompt to the LLM to semantically negate a statement rather than performing bitwise inversion.
How the Modes Are Implemented
The mode switching mechanism is implemented across three core components: the constructor flag logic in Symbol.__new__, the casting primitives in symai/ops/primitives.py, and the public property interface.
Flag Creation in __new__
In symai/symbol.py, the Symbol class sets the __semantic__ flag during instance construction. When semantic=True is passed to the constructor and mixin primitives are enabled, the flag is activated:
# symai/symbol.py (line ~395)
if use_mixin and standard_primitives and semantic:
obj.__semantic__ = True # Activates semantic mode
By default, Symbol instances are created in syntactic mode (__semantic__ is not set or is False).
Mode Conversion with .syn and .sem
The CastingPrimitives mixin (registered in symai/ops/primitives.py) provides two properties for runtime mode switching:
# symai/ops/primitives.py (lines ~1314-1332)
@property
def syn(self) -> "Symbol":
"""Return a syntactic (non-semantic) view of this Symbol."""
if not getattr(self, "__semantic__", False):
return self
return self._to_type(self.value, semantic=False)
@property
def sem(self) -> "Symbol":
"""Return a semantic view of this Symbol."""
if getattr(self, "__semantic__", False):
return self
return self._to_type(self.value, semantic=True)
The .syn property returns a syntactic view by creating a new Symbol with semantic=False, while .sem creates a semantic view with semantic=True. These properties enable fluid mode switching without manual flag manipulation.
Practical Code Examples
Default Syntactic Behavior
Creating a Symbol without the semantic flag produces a syntactic instance suitable for standard Python operations:
from symai import Symbol
s = Symbol(42) # Syntactic mode
print(s.__semantic__) # False
print(s + Symbol(8)) # 50 (arithmetic on raw values)
Creating a Semantic Symbol
Pass semantic=True to enable LLM-driven operations:
from symai import Symbol
s_sem = Symbol("What is the capital of France?", semantic=True)
print(s_sem.__semantic__) # True
# The ~ operator invokes the LLM for semantic negation
negated = ~s_sem
print(negated) # "Paris is not the capital of France."
Switching Modes with Properties
Use .sem and .syn to convert between modes dynamically:
from symai import Symbol
s = Symbol("apple") # Syntactic
print(s.__semantic__) # False
# Switch to semantic for LLM processing
s_sem = s.sem
print(s_sem.__semantic__) # True
# Process semantically, then revert to syntactic
result = s_sem.upper() # May use LLM for contextual upper-casing
s_back = result.syn
print(s_back.__semantic__) # False
print(s_back + Symbol(" pie")) # "apple pie" (syntactic concatenation)
Summary
- The
Symbolclass implements a dual-mode architecture through the__semantic__flag, distinguishing between syntactic (raw Python data) and semantic (LLM-driven) operations. - Syntactic mode is the default state where operators execute locally on raw values, providing deterministic performance without LLM overhead.
- Semantic mode activates neuro-symbolic capabilities, routing operations through the configured LLM engine for natural language reasoning and AI-augmented transformations.
- Mode switching is achieved through the
.semand.synproperties defined insymai/ops/primitives.py, or by passingsemantic=Trueduring construction insymai/symbol.py.
Frequently Asked Questions
How do I check if a Symbol instance is in semantic mode?
Inspect the __semantic__ attribute directly. If the attribute is True, the instance operates in semantic mode; otherwise, it is in syntactic mode:
sym = Symbol("test", semantic=True)
print(sym.__semantic__) # True
Can I switch a Symbol from semantic to syntactic mode without creating a new instance?
The .syn property returns a syntactic view, which may be the same instance if already syntactic, or a new Symbol with semantic=False if converting from semantic mode. The original instance remains unchanged; mode conversion creates a new view rather than mutating the existing object.
What happens to operators like + or ~ when a Symbol is in semantic mode?
In syntactic mode, + performs standard arithmetic or string concatenation on the raw value. In semantic mode, operators are overloaded to route through the LLM engine. For example, the bitwise negation operator ~ sends a prompt to the LLM to semantically negate the statement rather than performing bitwise inversion on the value.
Is there a performance difference between syntactic and semantic modes?
Yes. Syntactic mode executes native Python operations with minimal overhead, suitable for performance-critical paths. Semantic mode incurs latency from LLM API calls or local model inference, making it appropriate for complex reasoning tasks where AI augmentation justifies the computational cost.
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 →