symbolicai 0.20.2__py3-none-any.whl → 1.0.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- symai/__init__.py +96 -64
- symai/backend/base.py +93 -80
- symai/backend/engines/drawing/engine_bfl.py +12 -11
- symai/backend/engines/drawing/engine_gpt_image.py +108 -87
- symai/backend/engines/embedding/engine_llama_cpp.py +25 -28
- symai/backend/engines/embedding/engine_openai.py +3 -5
- symai/backend/engines/execute/engine_python.py +6 -5
- symai/backend/engines/files/engine_io.py +74 -67
- symai/backend/engines/imagecaptioning/engine_blip2.py +3 -3
- symai/backend/engines/imagecaptioning/engine_llavacpp_client.py +54 -38
- symai/backend/engines/index/engine_pinecone.py +23 -24
- symai/backend/engines/index/engine_vectordb.py +16 -14
- symai/backend/engines/lean/engine_lean4.py +38 -34
- symai/backend/engines/neurosymbolic/__init__.py +41 -13
- symai/backend/engines/neurosymbolic/engine_anthropic_claudeX_chat.py +262 -182
- symai/backend/engines/neurosymbolic/engine_anthropic_claudeX_reasoning.py +263 -191
- symai/backend/engines/neurosymbolic/engine_deepseekX_reasoning.py +53 -49
- symai/backend/engines/neurosymbolic/engine_google_geminiX_reasoning.py +212 -211
- symai/backend/engines/neurosymbolic/engine_groq.py +87 -63
- symai/backend/engines/neurosymbolic/engine_huggingface.py +21 -24
- symai/backend/engines/neurosymbolic/engine_llama_cpp.py +117 -48
- symai/backend/engines/neurosymbolic/engine_openai_gptX_chat.py +256 -229
- symai/backend/engines/neurosymbolic/engine_openai_gptX_reasoning.py +270 -150
- symai/backend/engines/ocr/engine_apilayer.py +6 -8
- symai/backend/engines/output/engine_stdout.py +1 -4
- symai/backend/engines/search/engine_openai.py +7 -7
- symai/backend/engines/search/engine_perplexity.py +5 -5
- symai/backend/engines/search/engine_serpapi.py +12 -14
- symai/backend/engines/speech_to_text/engine_local_whisper.py +20 -27
- symai/backend/engines/symbolic/engine_wolframalpha.py +3 -3
- symai/backend/engines/text_to_speech/engine_openai.py +5 -7
- symai/backend/engines/text_vision/engine_clip.py +7 -11
- symai/backend/engines/userinput/engine_console.py +3 -3
- symai/backend/engines/webscraping/engine_requests.py +81 -48
- symai/backend/mixin/__init__.py +13 -0
- symai/backend/mixin/anthropic.py +4 -2
- symai/backend/mixin/deepseek.py +2 -0
- symai/backend/mixin/google.py +2 -0
- symai/backend/mixin/openai.py +11 -3
- symai/backend/settings.py +83 -16
- symai/chat.py +101 -78
- symai/collect/__init__.py +7 -1
- symai/collect/dynamic.py +77 -69
- symai/collect/pipeline.py +35 -27
- symai/collect/stats.py +75 -63
- symai/components.py +198 -169
- symai/constraints.py +15 -12
- symai/core.py +698 -359
- symai/core_ext.py +32 -34
- symai/endpoints/api.py +80 -73
- symai/extended/.DS_Store +0 -0
- symai/extended/__init__.py +46 -12
- symai/extended/api_builder.py +11 -8
- symai/extended/arxiv_pdf_parser.py +13 -12
- symai/extended/bibtex_parser.py +2 -3
- symai/extended/conversation.py +101 -90
- symai/extended/document.py +17 -10
- symai/extended/file_merger.py +18 -13
- symai/extended/graph.py +18 -13
- symai/extended/html_style_template.py +2 -4
- symai/extended/interfaces/blip_2.py +1 -2
- symai/extended/interfaces/clip.py +1 -2
- symai/extended/interfaces/console.py +7 -1
- symai/extended/interfaces/dall_e.py +1 -1
- symai/extended/interfaces/flux.py +1 -1
- symai/extended/interfaces/gpt_image.py +1 -1
- symai/extended/interfaces/input.py +1 -1
- symai/extended/interfaces/llava.py +0 -1
- symai/extended/interfaces/naive_vectordb.py +7 -8
- symai/extended/interfaces/naive_webscraping.py +1 -1
- symai/extended/interfaces/ocr.py +1 -1
- symai/extended/interfaces/pinecone.py +6 -5
- symai/extended/interfaces/serpapi.py +1 -1
- symai/extended/interfaces/terminal.py +2 -3
- symai/extended/interfaces/tts.py +1 -1
- symai/extended/interfaces/whisper.py +1 -1
- symai/extended/interfaces/wolframalpha.py +1 -1
- symai/extended/metrics/__init__.py +11 -1
- symai/extended/metrics/similarity.py +11 -13
- symai/extended/os_command.py +17 -16
- symai/extended/packages/__init__.py +29 -3
- symai/extended/packages/symdev.py +19 -16
- symai/extended/packages/sympkg.py +12 -9
- symai/extended/packages/symrun.py +21 -19
- symai/extended/repo_cloner.py +11 -10
- symai/extended/seo_query_optimizer.py +1 -2
- symai/extended/solver.py +20 -23
- symai/extended/summarizer.py +4 -3
- symai/extended/taypan_interpreter.py +10 -12
- symai/extended/vectordb.py +99 -82
- symai/formatter/__init__.py +9 -1
- symai/formatter/formatter.py +12 -16
- symai/formatter/regex.py +62 -63
- symai/functional.py +176 -122
- symai/imports.py +136 -127
- symai/interfaces.py +56 -27
- symai/memory.py +14 -13
- symai/misc/console.py +49 -39
- symai/misc/loader.py +5 -3
- symai/models/__init__.py +17 -1
- symai/models/base.py +269 -181
- symai/models/errors.py +0 -1
- symai/ops/__init__.py +32 -22
- symai/ops/measures.py +11 -15
- symai/ops/primitives.py +348 -228
- symai/post_processors.py +32 -28
- symai/pre_processors.py +39 -41
- symai/processor.py +6 -4
- symai/prompts.py +59 -45
- symai/server/huggingface_server.py +23 -20
- symai/server/llama_cpp_server.py +7 -5
- symai/shell.py +3 -4
- symai/shellsv.py +499 -375
- symai/strategy.py +517 -287
- symai/symbol.py +111 -116
- symai/utils.py +42 -36
- {symbolicai-0.20.2.dist-info → symbolicai-1.0.0.dist-info}/METADATA +4 -2
- symbolicai-1.0.0.dist-info/RECORD +163 -0
- symbolicai-0.20.2.dist-info/RECORD +0 -162
- {symbolicai-0.20.2.dist-info → symbolicai-1.0.0.dist-info}/WHEEL +0 -0
- {symbolicai-0.20.2.dist-info → symbolicai-1.0.0.dist-info}/entry_points.txt +0 -0
- {symbolicai-0.20.2.dist-info → symbolicai-1.0.0.dist-info}/licenses/LICENSE +0 -0
- {symbolicai-0.20.2.dist-info → symbolicai-1.0.0.dist-info}/top_level.txt +0 -0
symai/symbol.py
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import copy
|
|
2
2
|
import html
|
|
3
3
|
import json
|
|
4
|
+
from collections.abc import Callable, Iterator
|
|
4
5
|
from json import JSONEncoder
|
|
5
|
-
from typing import
|
|
6
|
-
Tuple, Type, TypeVar)
|
|
6
|
+
from typing import Any, ClassVar
|
|
7
7
|
|
|
8
8
|
import numpy as np
|
|
9
9
|
from box import Box
|
|
@@ -11,8 +11,6 @@ from box import Box
|
|
|
11
11
|
from . import core
|
|
12
12
|
from .ops import SYMBOL_PRIMITIVES
|
|
13
13
|
|
|
14
|
-
T = TypeVar('T')
|
|
15
|
-
|
|
16
14
|
|
|
17
15
|
class SymbolEncoder(JSONEncoder):
|
|
18
16
|
def default(self, o):
|
|
@@ -30,7 +28,7 @@ class SymbolEncoder(JSONEncoder):
|
|
|
30
28
|
return JSONEncoder.default(self, o)
|
|
31
29
|
|
|
32
30
|
|
|
33
|
-
class Metadata
|
|
31
|
+
class Metadata:
|
|
34
32
|
# create a method that allow to dynamically assign a attribute if not in __dict__
|
|
35
33
|
# example: metadata = Metadata()
|
|
36
34
|
# metadata.some_new_attribute = 'some_value'
|
|
@@ -111,7 +109,7 @@ class Metadata(object):
|
|
|
111
109
|
_val = ''
|
|
112
110
|
if self.value is not None:
|
|
113
111
|
_val += str(self.value)
|
|
114
|
-
return _val + f"Properties({
|
|
112
|
+
return _val + f"Properties({ {k: str(v) for k, v in self.__dict__.items() if not k.startswith('_')}!s})"
|
|
115
113
|
|
|
116
114
|
def __repr__(self) -> str:
|
|
117
115
|
'''
|
|
@@ -128,7 +126,7 @@ class Metadata(object):
|
|
|
128
126
|
|
|
129
127
|
|
|
130
128
|
class Linker(Metadata):
|
|
131
|
-
def keys(self) ->
|
|
129
|
+
def keys(self) -> list[str]:
|
|
132
130
|
'''
|
|
133
131
|
Get all keys of the linker.
|
|
134
132
|
|
|
@@ -137,7 +135,7 @@ class Linker(Metadata):
|
|
|
137
135
|
'''
|
|
138
136
|
return list(self.results.keys())
|
|
139
137
|
|
|
140
|
-
def values(self) ->
|
|
138
|
+
def values(self) -> list[Any]:
|
|
141
139
|
'''
|
|
142
140
|
Get all values of the linker.
|
|
143
141
|
|
|
@@ -160,15 +158,19 @@ class Linker(Metadata):
|
|
|
160
158
|
'''
|
|
161
159
|
# search all results and return the first one that matches the name
|
|
162
160
|
res = []
|
|
161
|
+
def match_(key, search_name):
|
|
162
|
+
if strict:
|
|
163
|
+
return str(search_name) == str(key)
|
|
164
|
+
return str(search_name).lower() in str(key).lower()
|
|
165
|
+
|
|
163
166
|
for k in list(self.results.keys()):
|
|
164
|
-
match_ = lambda k, name: str(name).lower() in str(k).lower() if not strict else str(name) == str(k)
|
|
165
167
|
if match_(k, name):
|
|
166
168
|
res.append(self.results[k])
|
|
167
169
|
if single:
|
|
168
170
|
assert len(res) == 1, f'Found {len(res)} results for name {name}. Expected 1.'
|
|
169
171
|
if len(res) == 0:
|
|
170
172
|
return None
|
|
171
|
-
|
|
173
|
+
if len(res) == 1:
|
|
172
174
|
return res[0]
|
|
173
175
|
return res
|
|
174
176
|
|
|
@@ -207,15 +209,16 @@ class SymbolMeta(type):
|
|
|
207
209
|
return cls
|
|
208
210
|
|
|
209
211
|
|
|
210
|
-
class Symbol(
|
|
211
|
-
_mixin
|
|
212
|
-
_primitives
|
|
213
|
-
_metadata
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
212
|
+
class Symbol(metaclass=SymbolMeta):
|
|
213
|
+
_mixin: ClassVar[bool] = True
|
|
214
|
+
_primitives: ClassVar[dict[str, type]] = SYMBOL_PRIMITIVES
|
|
215
|
+
_metadata: ClassVar[Metadata] = Metadata()
|
|
216
|
+
_metadata_primitives: ClassVar[dict[str, Callable]] = {}
|
|
217
|
+
_metadata._primitives = _metadata_primitives
|
|
218
|
+
_dynamic_context: ClassVar[dict[str, list[str]]] = {}
|
|
219
|
+
_RESERVED_PROPERTIES: ClassVar[set[str]] = {'graph', 'linker', 'parent', 'children', 'metadata', 'value', 'root', 'nodes', 'edges', 'global_context', 'static_context', 'dynamic_context', 'shape'}
|
|
217
220
|
|
|
218
|
-
def __init__(self, *value, static_context:
|
|
221
|
+
def __init__(self, *value, static_context: str | None = '', dynamic_context: str | None = None, **kwargs) -> None:
|
|
219
222
|
'''
|
|
220
223
|
Initialize a Symbol instance with a specified value. Unwraps nested symbols.
|
|
221
224
|
|
|
@@ -252,11 +255,11 @@ class Symbol(Generic[T], metaclass=SymbolMeta):
|
|
|
252
255
|
'''
|
|
253
256
|
def _func(k, v):
|
|
254
257
|
# check if property is of type Symbol and not private and a class variable (not a function)
|
|
255
|
-
if isinstance(v, Symbol) and not k.startswith('_') and
|
|
258
|
+
if isinstance(v, Symbol) and not k.startswith('_') and v is not self:
|
|
256
259
|
v._parent = self
|
|
257
260
|
self._children.append(v)
|
|
258
261
|
# else if iterable, check if it contains symbols
|
|
259
|
-
elif
|
|
262
|
+
elif isinstance(v, (list, tuple)) and not k.startswith('_'):
|
|
260
263
|
for i in v:
|
|
261
264
|
_func(k, i)
|
|
262
265
|
|
|
@@ -267,45 +270,33 @@ class Symbol(Generic[T], metaclass=SymbolMeta):
|
|
|
267
270
|
def _unwrap_symbols_args(self, *args, nested: bool = False) -> Any:
|
|
268
271
|
if len(args) == 0:
|
|
269
272
|
return None
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
# if the value is a primitive, store it as is
|
|
276
|
-
if isinstance(value, str) or isinstance(value, int) or isinstance(value, float) or isinstance(value, bool):
|
|
277
|
-
pass
|
|
278
|
-
|
|
279
|
-
# if the value is a symbol, unwrap it
|
|
280
|
-
elif isinstance(value, Symbol):
|
|
281
|
-
# if not nested, copy the symbol's value, metadata, parent, and children
|
|
282
|
-
if not nested:
|
|
283
|
-
self._metadata = value.metadata
|
|
284
|
-
self._static_context = value.static_context
|
|
285
|
-
self._kwargs = value._kwargs
|
|
286
|
-
# unwrap the symbol's value
|
|
287
|
-
value = value.value
|
|
288
|
-
|
|
289
|
-
# if the value is a list, tuple, dict, or set, unwrap all nested symbols
|
|
290
|
-
elif isinstance(value, list) or isinstance(value, dict) or \
|
|
291
|
-
isinstance(value, set) or isinstance(value, tuple):
|
|
292
|
-
|
|
293
|
-
if isinstance(value, list):
|
|
294
|
-
value = [self._unwrap_symbols_args(v, nested=True) for v in value]
|
|
295
|
-
|
|
296
|
-
elif isinstance(value, dict):
|
|
297
|
-
value = {self._unwrap_symbols_args(k, nested=True): self._unwrap_symbols_args(v, nested=True) for k, v in value.items()}
|
|
298
|
-
|
|
299
|
-
elif isinstance(value, set):
|
|
300
|
-
value = {self._unwrap_symbols_args(v, nested=True) for v in value}
|
|
301
|
-
|
|
302
|
-
elif isinstance(value, tuple):
|
|
303
|
-
value = tuple([self._unwrap_symbols_args(v, nested=True) for v in value])
|
|
273
|
+
if len(args) == 1:
|
|
274
|
+
return self._unwrap_single_symbol_arg(args[0], nested=nested)
|
|
275
|
+
if len(args) > 1:
|
|
276
|
+
return [self._unwrap_symbols_args(a, nested=True) if isinstance(a, Symbol) else a for a in args]
|
|
277
|
+
return None
|
|
304
278
|
|
|
279
|
+
def _unwrap_single_symbol_arg(self, value: Any, *, nested: bool) -> Any:
|
|
280
|
+
if isinstance(value, (str, int, float, bool)):
|
|
305
281
|
return value
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
282
|
+
if isinstance(value, Symbol):
|
|
283
|
+
if not nested:
|
|
284
|
+
self._metadata = value.metadata
|
|
285
|
+
self._static_context = value.static_context
|
|
286
|
+
self._kwargs = value._kwargs
|
|
287
|
+
return value.value
|
|
288
|
+
if isinstance(value, list):
|
|
289
|
+
return [self._unwrap_symbols_args(v, nested=True) for v in value]
|
|
290
|
+
if isinstance(value, dict):
|
|
291
|
+
return {
|
|
292
|
+
self._unwrap_symbols_args(k, nested=True): self._unwrap_symbols_args(v, nested=True)
|
|
293
|
+
for k, v in value.items()
|
|
294
|
+
}
|
|
295
|
+
if isinstance(value, set):
|
|
296
|
+
return {self._unwrap_symbols_args(v, nested=True) for v in value}
|
|
297
|
+
if isinstance(value, tuple):
|
|
298
|
+
return tuple(self._unwrap_symbols_args(v, nested=True) for v in value)
|
|
299
|
+
return value
|
|
309
300
|
|
|
310
301
|
def _construct_dependency_graph(self, *value):
|
|
311
302
|
'''
|
|
@@ -316,16 +307,16 @@ class Symbol(Generic[T], metaclass=SymbolMeta):
|
|
|
316
307
|
'''
|
|
317
308
|
# for each value
|
|
318
309
|
for v in value:
|
|
319
|
-
if isinstance(v, Symbol) and
|
|
310
|
+
if isinstance(v, Symbol) and v is not self:
|
|
320
311
|
# new instance becomes child of previous instance
|
|
321
312
|
v._parent = self
|
|
322
313
|
# add new instance to children of previous instance
|
|
323
314
|
self._children.append(v)
|
|
324
315
|
|
|
325
|
-
def __new__(cls, *
|
|
326
|
-
mixin:
|
|
327
|
-
primitives:
|
|
328
|
-
callables:
|
|
316
|
+
def __new__(cls, *_args,
|
|
317
|
+
mixin: bool | None = None,
|
|
318
|
+
primitives: list[type] | None = None,
|
|
319
|
+
callables: list[tuple[str, Callable]] | None = None,
|
|
329
320
|
semantic: bool = False,
|
|
330
321
|
**kwargs) -> "Symbol":
|
|
331
322
|
'''
|
|
@@ -348,10 +339,11 @@ class Symbol(Generic[T], metaclass=SymbolMeta):
|
|
|
348
339
|
if not isinstance(primitives, list):
|
|
349
340
|
primitives = [primitives]
|
|
350
341
|
# Initialize instance as a combination of Symbol and the mixin primitive types
|
|
342
|
+
target_cls = cls
|
|
351
343
|
if use_mixin:
|
|
352
344
|
# create a new cls type that inherits from Symbol and the mixin primitive types
|
|
353
|
-
|
|
354
|
-
obj = super().__new__(
|
|
345
|
+
target_cls = SymbolMeta(cls.__name__, (cls, *tuple(primitives)), {})
|
|
346
|
+
obj = super().__new__(target_cls)
|
|
355
347
|
# store to inherit when creating new instances
|
|
356
348
|
obj._kwargs = {
|
|
357
349
|
'mixin': use_mixin,
|
|
@@ -361,10 +353,9 @@ class Symbol(Generic[T], metaclass=SymbolMeta):
|
|
|
361
353
|
**kwargs
|
|
362
354
|
}
|
|
363
355
|
# configure standard primitives
|
|
364
|
-
if use_mixin and standard_primitives:
|
|
356
|
+
if use_mixin and standard_primitives and semantic:
|
|
365
357
|
# allow to iterate over iterables for neuro-symbolic values
|
|
366
|
-
|
|
367
|
-
obj.__semantic__ = True
|
|
358
|
+
obj.__semantic__ = True
|
|
368
359
|
# If metatype has additional runtime primitives, add them to the instance
|
|
369
360
|
if Symbol._metadata._primitives is not None:
|
|
370
361
|
for prim_name in list(Symbol._metadata._primitives.keys()):
|
|
@@ -411,7 +402,8 @@ class Symbol(Generic[T], metaclass=SymbolMeta):
|
|
|
411
402
|
value = self.value if self.value is not None else None
|
|
412
403
|
if isinstance(value, Exception):
|
|
413
404
|
raise value
|
|
414
|
-
|
|
405
|
+
msg = f"<class '{self.__class__.__name__}'> or nested value of {type(value)!s} have no attribute '{name}'"
|
|
406
|
+
raise AttributeError(msg)
|
|
415
407
|
except AttributeError as ex:
|
|
416
408
|
# if has attribute and is public function
|
|
417
409
|
if hasattr(self.value, name) and not name.startswith('_'):
|
|
@@ -440,7 +432,7 @@ class Symbol(Generic[T], metaclass=SymbolMeta):
|
|
|
440
432
|
return memoryview(self.embedding)
|
|
441
433
|
|
|
442
434
|
@staticmethod
|
|
443
|
-
def symbols(*values) ->
|
|
435
|
+
def symbols(*values) -> list["Symbol"]:
|
|
444
436
|
'''
|
|
445
437
|
Create a list of Symbol instances from a list of values.
|
|
446
438
|
|
|
@@ -458,7 +450,7 @@ class Symbol(Generic[T], metaclass=SymbolMeta):
|
|
|
458
450
|
It returns a tuple that contains:
|
|
459
451
|
- A callable object that when called produces a new object (e.g., the class of the object)
|
|
460
452
|
- A tuple of arguments for the callable object
|
|
461
|
-
- Optionally, the state which will be passed to the object
|
|
453
|
+
- Optionally, the state which will be passed to the object's `__setstate__` method
|
|
462
454
|
|
|
463
455
|
Returns:
|
|
464
456
|
tuple: A tuple containing the callable object, the arguments for the callable object, and the state of the object.
|
|
@@ -476,7 +468,7 @@ class Symbol(Generic[T], metaclass=SymbolMeta):
|
|
|
476
468
|
# The __reduce__ method returns:
|
|
477
469
|
# - A callable object that when called produces a new object (e.g., the class of the object)
|
|
478
470
|
# - A tuple of arguments for the callable object
|
|
479
|
-
# - Optionally, the state which will be passed to the object
|
|
471
|
+
# - Optionally, the state which will be passed to the object's `__setstate__` method
|
|
480
472
|
return (self._reconstruct_class, (base_cls, self._mixin, primitives), state)
|
|
481
473
|
|
|
482
474
|
def __reduce_ex__(self, protocol):
|
|
@@ -500,12 +492,11 @@ class Symbol(Generic[T], metaclass=SymbolMeta):
|
|
|
500
492
|
# Convert primitive info tuples back to types
|
|
501
493
|
primitives = [primitive for primitive, name in primitives_info]
|
|
502
494
|
# Create new cls with UnifiedMeta metaclass
|
|
503
|
-
cls
|
|
504
|
-
|
|
505
|
-
return obj
|
|
495
|
+
cls = SymbolMeta(base_cls.__name__, (base_cls, *tuple(primitives)), {})
|
|
496
|
+
return cls()
|
|
506
497
|
return base_cls()
|
|
507
498
|
|
|
508
|
-
def __getstate__(self) ->
|
|
499
|
+
def __getstate__(self) -> dict[str, Any]:
|
|
509
500
|
'''
|
|
510
501
|
Get the state of the symbol for serialization.
|
|
511
502
|
|
|
@@ -532,7 +523,7 @@ class Symbol(Generic[T], metaclass=SymbolMeta):
|
|
|
532
523
|
self._parent = None
|
|
533
524
|
self._children = []
|
|
534
525
|
|
|
535
|
-
def json(self) ->
|
|
526
|
+
def json(self) -> dict[str, Any]:
|
|
536
527
|
'''
|
|
537
528
|
Get the json-serializable dictionary representation of the Symbol instance.
|
|
538
529
|
|
|
@@ -568,8 +559,7 @@ class Symbol(Generic[T], metaclass=SymbolMeta):
|
|
|
568
559
|
return value
|
|
569
560
|
# inherit kwargs for new symbol instance
|
|
570
561
|
kwargs = {**self._kwargs, **kwargs}
|
|
571
|
-
|
|
572
|
-
return sym
|
|
562
|
+
return type_(value, **kwargs)
|
|
573
563
|
|
|
574
564
|
def _to_type(self, value: Any, **kwargs) -> "Symbol":
|
|
575
565
|
'''
|
|
@@ -586,8 +576,7 @@ class Symbol(Generic[T], metaclass=SymbolMeta):
|
|
|
586
576
|
return value
|
|
587
577
|
# inherit kwargs for new symbol instance
|
|
588
578
|
kwargs = {**self._kwargs, **kwargs}
|
|
589
|
-
|
|
590
|
-
return sym
|
|
579
|
+
return type_(value, **kwargs)
|
|
591
580
|
|
|
592
581
|
@property
|
|
593
582
|
def _symbol_type(self) -> "Symbol":
|
|
@@ -609,7 +598,7 @@ class Symbol(Generic[T], metaclass=SymbolMeta):
|
|
|
609
598
|
return str(self.value).__hash__()
|
|
610
599
|
|
|
611
600
|
@property
|
|
612
|
-
def metadata(self) ->
|
|
601
|
+
def metadata(self) -> dict[str, Any]:
|
|
613
602
|
'''
|
|
614
603
|
Get the metadata associated with the symbol.
|
|
615
604
|
|
|
@@ -692,7 +681,7 @@ class Symbol(Generic[T], metaclass=SymbolMeta):
|
|
|
692
681
|
return root
|
|
693
682
|
|
|
694
683
|
@property
|
|
695
|
-
def nodes(self) ->
|
|
684
|
+
def nodes(self) -> list["Symbol"]:
|
|
696
685
|
'''
|
|
697
686
|
Get all nodes descending recursively from the symbol.
|
|
698
687
|
|
|
@@ -709,7 +698,7 @@ class Symbol(Generic[T], metaclass=SymbolMeta):
|
|
|
709
698
|
return nodes
|
|
710
699
|
|
|
711
700
|
@property
|
|
712
|
-
def edges(self) ->
|
|
701
|
+
def edges(self) -> list[tuple]:
|
|
713
702
|
'''
|
|
714
703
|
Get all edges descending recursively from the symbol.
|
|
715
704
|
|
|
@@ -726,7 +715,7 @@ class Symbol(Generic[T], metaclass=SymbolMeta):
|
|
|
726
715
|
return edges
|
|
727
716
|
|
|
728
717
|
@property
|
|
729
|
-
def graph(self) -> (
|
|
718
|
+
def graph(self) -> (list["Symbol"], list[tuple]):
|
|
730
719
|
'''
|
|
731
720
|
Get the graph representation of the symbol.
|
|
732
721
|
|
|
@@ -736,7 +725,7 @@ class Symbol(Generic[T], metaclass=SymbolMeta):
|
|
|
736
725
|
return self.nodes, self.edges
|
|
737
726
|
|
|
738
727
|
@property
|
|
739
|
-
def linker(self) ->
|
|
728
|
+
def linker(self) -> list["Symbol"]:
|
|
740
729
|
'''
|
|
741
730
|
Returns the link object metadata by descending recursively from the root of the symbol to the root_link object.
|
|
742
731
|
|
|
@@ -756,7 +745,7 @@ class Symbol(Generic[T], metaclass=SymbolMeta):
|
|
|
756
745
|
return self._parent
|
|
757
746
|
|
|
758
747
|
@property
|
|
759
|
-
def children(self) ->
|
|
748
|
+
def children(self) -> list["Symbol"]:
|
|
760
749
|
'''
|
|
761
750
|
Get the children of the symbol.
|
|
762
751
|
|
|
@@ -765,7 +754,7 @@ class Symbol(Generic[T], metaclass=SymbolMeta):
|
|
|
765
754
|
'''
|
|
766
755
|
return self._children
|
|
767
756
|
|
|
768
|
-
def _root_link(self, sym: Any, **
|
|
757
|
+
def _root_link(self, sym: Any, **_kwargs) -> Any:
|
|
769
758
|
'''
|
|
770
759
|
Call the forward method and assign the result to the graph value attribute.
|
|
771
760
|
|
|
@@ -777,7 +766,7 @@ class Symbol(Generic[T], metaclass=SymbolMeta):
|
|
|
777
766
|
Any: The result of the forward method.
|
|
778
767
|
'''
|
|
779
768
|
# transport results to the root node for global access
|
|
780
|
-
if
|
|
769
|
+
if self is not self.root and not self.metadata.detach:
|
|
781
770
|
ref = self.root.metadata
|
|
782
771
|
if ref.root_link is None:
|
|
783
772
|
ref.root_link = Linker()
|
|
@@ -788,12 +777,12 @@ class Symbol(Generic[T], metaclass=SymbolMeta):
|
|
|
788
777
|
prev = list(ref.root_link.results.values())[-1] # get previous result
|
|
789
778
|
# create new symbol to avoid circular references
|
|
790
779
|
res_ = Symbol(sym)
|
|
791
|
-
if prev is not None and
|
|
780
|
+
if prev is not None and prev is not res_.root:
|
|
792
781
|
prev.children.append(res_.root)
|
|
793
782
|
res_.root._parent = prev
|
|
794
783
|
ref.root_link.results[self.__repr__()] = res_
|
|
795
784
|
|
|
796
|
-
def adapt(self, context: str, types:
|
|
785
|
+
def adapt(self, context: str, types: list[type] | None = None) -> None:
|
|
797
786
|
'''
|
|
798
787
|
Update the dynamic context with a given runtime context.
|
|
799
788
|
|
|
@@ -802,34 +791,38 @@ class Symbol(Generic[T], metaclass=SymbolMeta):
|
|
|
802
791
|
type (Type): The type used to update the dynamic context
|
|
803
792
|
|
|
804
793
|
'''
|
|
794
|
+
if types is None:
|
|
795
|
+
types = []
|
|
805
796
|
if not isinstance(types, list):
|
|
806
797
|
types = [types]
|
|
807
798
|
if len(types) == 0:
|
|
808
799
|
types = [type(self)]
|
|
809
800
|
|
|
810
801
|
for type_ in types:
|
|
811
|
-
|
|
812
|
-
if
|
|
813
|
-
Symbol._dynamic_context[
|
|
802
|
+
type_key = str(type_)
|
|
803
|
+
if type_key not in Symbol._dynamic_context:
|
|
804
|
+
Symbol._dynamic_context[type_key] = []
|
|
814
805
|
|
|
815
|
-
Symbol._dynamic_context[
|
|
806
|
+
Symbol._dynamic_context[type_key].append(str(context))
|
|
816
807
|
|
|
817
|
-
def clear(self, types:
|
|
808
|
+
def clear(self, types: list[type] | None = None) -> None:
|
|
818
809
|
'''
|
|
819
810
|
Clear the dynamic context associated with this symbol type.
|
|
820
811
|
'''
|
|
812
|
+
if types is None:
|
|
813
|
+
types = []
|
|
821
814
|
if not isinstance(types, list):
|
|
822
815
|
types = [types]
|
|
823
816
|
if len(types) == 0:
|
|
824
817
|
types = [type(self)]
|
|
825
818
|
|
|
826
819
|
for type_ in types:
|
|
827
|
-
|
|
828
|
-
if
|
|
829
|
-
Symbol._dynamic_context[
|
|
820
|
+
type_key = str(type_)
|
|
821
|
+
if type_key not in Symbol._dynamic_context:
|
|
822
|
+
Symbol._dynamic_context[type_key] = []
|
|
830
823
|
return
|
|
831
824
|
|
|
832
|
-
Symbol._dynamic_context[
|
|
825
|
+
Symbol._dynamic_context[type_key].clear()
|
|
833
826
|
|
|
834
827
|
def __len__(self) -> int:
|
|
835
828
|
'''
|
|
@@ -859,14 +852,13 @@ class Symbol(Generic[T], metaclass=SymbolMeta):
|
|
|
859
852
|
'''
|
|
860
853
|
if self.value is None:
|
|
861
854
|
return ''
|
|
862
|
-
|
|
855
|
+
if isinstance(self.value, (list, np.ndarray, tuple)):
|
|
863
856
|
return str([str(v) for v in self.value])
|
|
864
|
-
|
|
857
|
+
if isinstance(self.value, dict):
|
|
865
858
|
return str({k: str(v) for k, v in self.value.items()})
|
|
866
|
-
|
|
859
|
+
if isinstance(self.value, set):
|
|
867
860
|
return str({str(v) for v in self.value})
|
|
868
|
-
|
|
869
|
-
return str(self.value)
|
|
861
|
+
return str(self.value)
|
|
870
862
|
|
|
871
863
|
def __repr__(self, simplified: bool = False) -> str:
|
|
872
864
|
'''
|
|
@@ -901,7 +893,7 @@ class Symbol(Generic[T], metaclass=SymbolMeta):
|
|
|
901
893
|
Returns:
|
|
902
894
|
Iterator: An iterator for the Symbol's value.
|
|
903
895
|
'''
|
|
904
|
-
if isinstance(self.value, list
|
|
896
|
+
if isinstance(self.value, (list, tuple, np.ndarray)):
|
|
905
897
|
return iter(self.value)
|
|
906
898
|
|
|
907
899
|
return self.list('item').value.__iter__()
|
|
@@ -960,8 +952,8 @@ class Symbol(Generic[T], metaclass=SymbolMeta):
|
|
|
960
952
|
# TODO: Workaround for Python bug to enable runtime assignment of lambda function to new Symbol objects.
|
|
961
953
|
# Currently creating multiple lambda functions within class __new__ definition only links last lambda function to all new Symbol attribute assignments.
|
|
962
954
|
# Need to contact Python developers to fix this bug.
|
|
963
|
-
class Call
|
|
964
|
-
def __new__(
|
|
955
|
+
class Call:
|
|
956
|
+
def __new__(cls, name, callable: Callable) -> Any:
|
|
965
957
|
'''
|
|
966
958
|
Prepare a callable for use in a Symbol instance.
|
|
967
959
|
|
|
@@ -976,8 +968,8 @@ class Call(object):
|
|
|
976
968
|
return (name, _func)
|
|
977
969
|
|
|
978
970
|
|
|
979
|
-
class GlobalSymbolPrimitive
|
|
980
|
-
def __new__(
|
|
971
|
+
class GlobalSymbolPrimitive:
|
|
972
|
+
def __new__(cls, name, callable: Callable) -> Any:
|
|
981
973
|
'''
|
|
982
974
|
Prepare a callable for use in a Symbol instance.
|
|
983
975
|
|
|
@@ -1060,7 +1052,7 @@ class Expression(Symbol):
|
|
|
1060
1052
|
return json.dumps(self, cls=ExpressionEncoder)
|
|
1061
1053
|
|
|
1062
1054
|
@property
|
|
1063
|
-
def sym_return_type(self) ->
|
|
1055
|
+
def sym_return_type(self) -> type:
|
|
1064
1056
|
'''
|
|
1065
1057
|
Returns the casting type of this expression.
|
|
1066
1058
|
|
|
@@ -1070,7 +1062,7 @@ class Expression(Symbol):
|
|
|
1070
1062
|
return self._sym_return_type
|
|
1071
1063
|
|
|
1072
1064
|
@sym_return_type.setter
|
|
1073
|
-
def sym_return_type(self, type:
|
|
1065
|
+
def sym_return_type(self, type: type) -> None:
|
|
1074
1066
|
'''
|
|
1075
1067
|
Sets the casting type of this expression.
|
|
1076
1068
|
|
|
@@ -1090,10 +1082,10 @@ class Expression(Symbol):
|
|
|
1090
1082
|
Returns:
|
|
1091
1083
|
Symbol: The evaluated result of the implemented forward method.
|
|
1092
1084
|
'''
|
|
1093
|
-
raise NotImplementedError
|
|
1085
|
+
raise NotImplementedError
|
|
1094
1086
|
|
|
1095
1087
|
@staticmethod
|
|
1096
|
-
def command(engines:
|
|
1088
|
+
def command(engines: list[str] | None = None, **kwargs) -> 'Symbol':
|
|
1097
1089
|
'''
|
|
1098
1090
|
Execute command(s) on engines.
|
|
1099
1091
|
|
|
@@ -1104,13 +1096,16 @@ class Expression(Symbol):
|
|
|
1104
1096
|
Returns:
|
|
1105
1097
|
Symbol: An Expression object representing the command execution result.
|
|
1106
1098
|
'''
|
|
1099
|
+
if engines is None:
|
|
1100
|
+
engines = ['all']
|
|
1101
|
+
|
|
1107
1102
|
@core.command(engines=engines, **kwargs)
|
|
1108
1103
|
def _func(_):
|
|
1109
1104
|
pass
|
|
1110
1105
|
return Expression(_func(Expression()))
|
|
1111
1106
|
|
|
1112
1107
|
@staticmethod
|
|
1113
|
-
def register(engines:
|
|
1108
|
+
def register(engines: dict[str, Any], **kwargs) -> 'Symbol':
|
|
1114
1109
|
'''
|
|
1115
1110
|
Configure multiple engines.
|
|
1116
1111
|
|
|
@@ -1154,7 +1149,7 @@ class Expression(Symbol):
|
|
|
1154
1149
|
|
|
1155
1150
|
|
|
1156
1151
|
class Result(Expression):
|
|
1157
|
-
def __init__(self, value = None, *
|
|
1152
|
+
def __init__(self, value = None, *_args, **kwargs):
|
|
1158
1153
|
'''
|
|
1159
1154
|
Create a Result object that stores the results operations, including the raw result, value and metadata, if any.
|
|
1160
1155
|
|
|
@@ -1169,7 +1164,7 @@ class Result(Expression):
|
|
|
1169
1164
|
try:
|
|
1170
1165
|
# try to make the values easily accessible
|
|
1171
1166
|
self.raw = Box(value)
|
|
1172
|
-
except:
|
|
1167
|
+
except Exception:
|
|
1173
1168
|
# otherwise, store the unprocessed view
|
|
1174
1169
|
self.raw = value
|
|
1175
1170
|
|