symbolicai 1.0.0__py3-none-any.whl → 1.1.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.
Files changed (127) hide show
  1. symai/__init__.py +198 -134
  2. symai/backend/base.py +51 -51
  3. symai/backend/engines/drawing/engine_bfl.py +33 -33
  4. symai/backend/engines/drawing/engine_gpt_image.py +4 -10
  5. symai/backend/engines/embedding/engine_llama_cpp.py +50 -35
  6. symai/backend/engines/embedding/engine_openai.py +22 -16
  7. symai/backend/engines/execute/engine_python.py +16 -16
  8. symai/backend/engines/files/engine_io.py +51 -49
  9. symai/backend/engines/imagecaptioning/engine_blip2.py +27 -23
  10. symai/backend/engines/imagecaptioning/engine_llavacpp_client.py +53 -46
  11. symai/backend/engines/index/engine_pinecone.py +116 -88
  12. symai/backend/engines/index/engine_qdrant.py +1011 -0
  13. symai/backend/engines/index/engine_vectordb.py +78 -52
  14. symai/backend/engines/lean/engine_lean4.py +65 -25
  15. symai/backend/engines/neurosymbolic/__init__.py +28 -28
  16. symai/backend/engines/neurosymbolic/engine_anthropic_claudeX_chat.py +137 -135
  17. symai/backend/engines/neurosymbolic/engine_anthropic_claudeX_reasoning.py +145 -152
  18. symai/backend/engines/neurosymbolic/engine_cerebras.py +328 -0
  19. symai/backend/engines/neurosymbolic/engine_deepseekX_reasoning.py +75 -49
  20. symai/backend/engines/neurosymbolic/engine_google_geminiX_reasoning.py +199 -155
  21. symai/backend/engines/neurosymbolic/engine_groq.py +106 -72
  22. symai/backend/engines/neurosymbolic/engine_huggingface.py +100 -67
  23. symai/backend/engines/neurosymbolic/engine_llama_cpp.py +121 -93
  24. symai/backend/engines/neurosymbolic/engine_openai_gptX_chat.py +213 -132
  25. symai/backend/engines/neurosymbolic/engine_openai_gptX_reasoning.py +180 -137
  26. symai/backend/engines/ocr/engine_apilayer.py +18 -20
  27. symai/backend/engines/output/engine_stdout.py +9 -9
  28. symai/backend/engines/{webscraping → scrape}/engine_requests.py +25 -11
  29. symai/backend/engines/search/engine_openai.py +95 -83
  30. symai/backend/engines/search/engine_parallel.py +665 -0
  31. symai/backend/engines/search/engine_perplexity.py +40 -41
  32. symai/backend/engines/search/engine_serpapi.py +33 -28
  33. symai/backend/engines/speech_to_text/engine_local_whisper.py +37 -27
  34. symai/backend/engines/symbolic/engine_wolframalpha.py +14 -8
  35. symai/backend/engines/text_to_speech/engine_openai.py +15 -19
  36. symai/backend/engines/text_vision/engine_clip.py +34 -28
  37. symai/backend/engines/userinput/engine_console.py +3 -4
  38. symai/backend/mixin/anthropic.py +48 -40
  39. symai/backend/mixin/deepseek.py +4 -5
  40. symai/backend/mixin/google.py +5 -4
  41. symai/backend/mixin/groq.py +2 -4
  42. symai/backend/mixin/openai.py +132 -110
  43. symai/backend/settings.py +14 -14
  44. symai/chat.py +164 -94
  45. symai/collect/dynamic.py +13 -11
  46. symai/collect/pipeline.py +39 -31
  47. symai/collect/stats.py +109 -69
  48. symai/components.py +556 -238
  49. symai/constraints.py +14 -5
  50. symai/core.py +1495 -1210
  51. symai/core_ext.py +55 -50
  52. symai/endpoints/api.py +113 -58
  53. symai/extended/api_builder.py +22 -17
  54. symai/extended/arxiv_pdf_parser.py +13 -5
  55. symai/extended/bibtex_parser.py +8 -4
  56. symai/extended/conversation.py +88 -69
  57. symai/extended/document.py +40 -27
  58. symai/extended/file_merger.py +45 -7
  59. symai/extended/graph.py +38 -24
  60. symai/extended/html_style_template.py +17 -11
  61. symai/extended/interfaces/blip_2.py +1 -1
  62. symai/extended/interfaces/clip.py +4 -2
  63. symai/extended/interfaces/console.py +5 -3
  64. symai/extended/interfaces/dall_e.py +3 -1
  65. symai/extended/interfaces/file.py +2 -0
  66. symai/extended/interfaces/flux.py +3 -1
  67. symai/extended/interfaces/gpt_image.py +15 -6
  68. symai/extended/interfaces/input.py +2 -1
  69. symai/extended/interfaces/llava.py +1 -1
  70. symai/extended/interfaces/{naive_webscraping.py → naive_scrape.py} +3 -2
  71. symai/extended/interfaces/naive_vectordb.py +2 -2
  72. symai/extended/interfaces/ocr.py +4 -2
  73. symai/extended/interfaces/openai_search.py +2 -0
  74. symai/extended/interfaces/parallel.py +30 -0
  75. symai/extended/interfaces/perplexity.py +2 -0
  76. symai/extended/interfaces/pinecone.py +6 -4
  77. symai/extended/interfaces/python.py +2 -0
  78. symai/extended/interfaces/serpapi.py +2 -0
  79. symai/extended/interfaces/terminal.py +0 -1
  80. symai/extended/interfaces/tts.py +2 -1
  81. symai/extended/interfaces/whisper.py +2 -1
  82. symai/extended/interfaces/wolframalpha.py +1 -0
  83. symai/extended/metrics/__init__.py +1 -1
  84. symai/extended/metrics/similarity.py +5 -2
  85. symai/extended/os_command.py +31 -22
  86. symai/extended/packages/symdev.py +39 -34
  87. symai/extended/packages/sympkg.py +30 -27
  88. symai/extended/packages/symrun.py +46 -35
  89. symai/extended/repo_cloner.py +10 -9
  90. symai/extended/seo_query_optimizer.py +15 -12
  91. symai/extended/solver.py +104 -76
  92. symai/extended/summarizer.py +8 -7
  93. symai/extended/taypan_interpreter.py +10 -9
  94. symai/extended/vectordb.py +28 -15
  95. symai/formatter/formatter.py +39 -31
  96. symai/formatter/regex.py +46 -44
  97. symai/functional.py +184 -86
  98. symai/imports.py +85 -51
  99. symai/interfaces.py +1 -1
  100. symai/memory.py +33 -24
  101. symai/menu/screen.py +28 -19
  102. symai/misc/console.py +27 -27
  103. symai/misc/loader.py +4 -3
  104. symai/models/base.py +147 -76
  105. symai/models/errors.py +1 -1
  106. symai/ops/__init__.py +1 -1
  107. symai/ops/measures.py +17 -14
  108. symai/ops/primitives.py +933 -635
  109. symai/post_processors.py +28 -24
  110. symai/pre_processors.py +58 -52
  111. symai/processor.py +15 -9
  112. symai/prompts.py +714 -649
  113. symai/server/huggingface_server.py +115 -32
  114. symai/server/llama_cpp_server.py +14 -6
  115. symai/server/qdrant_server.py +206 -0
  116. symai/shell.py +98 -39
  117. symai/shellsv.py +307 -223
  118. symai/strategy.py +135 -81
  119. symai/symbol.py +276 -225
  120. symai/utils.py +62 -46
  121. {symbolicai-1.0.0.dist-info → symbolicai-1.1.0.dist-info}/METADATA +19 -9
  122. symbolicai-1.1.0.dist-info/RECORD +168 -0
  123. symbolicai-1.0.0.dist-info/RECORD +0 -163
  124. {symbolicai-1.0.0.dist-info → symbolicai-1.1.0.dist-info}/WHEEL +0 -0
  125. {symbolicai-1.0.0.dist-info → symbolicai-1.1.0.dist-info}/entry_points.txt +0 -0
  126. {symbolicai-1.0.0.dist-info → symbolicai-1.1.0.dist-info}/licenses/LICENSE +0 -0
  127. {symbolicai-1.0.0.dist-info → symbolicai-1.1.0.dist-info}/top_level.txt +0 -0
symai/collect/stats.py CHANGED
@@ -12,13 +12,13 @@ from ..ops.primitives import OperatorPrimitives
12
12
  from ..symbol import Symbol
13
13
  from ..utils import UserMessage
14
14
 
15
- SPECIAL_CONSTANT = '__aggregate_'
16
- EXCLUDE_LIST = ['_ipython_canary_method_should_not_exist_', '__custom_documentations__']
15
+ SPECIAL_CONSTANT = "__aggregate_"
16
+ EXCLUDE_LIST = ["_ipython_canary_method_should_not_exist_", "__custom_documentations__"]
17
17
 
18
18
 
19
19
  def _normalize_name(name: str) -> str:
20
20
  # Replace any character that is not a letter or a number with an underscore
21
- normalized_name = re.sub(r'[^a-zA-Z0-9]', '_', name)
21
+ normalized_name = re.sub(r"[^a-zA-Z0-9]", "_", name)
22
22
  return normalized_name.lower()
23
23
 
24
24
 
@@ -29,29 +29,33 @@ class AggregatorJSONEncoder(JSONEncoder):
29
29
  # drop active from state
30
30
  if isinstance(obj, Aggregator):
31
31
  state = obj.__dict__.copy()
32
- state.pop('_raise_error', None)
33
- state.pop('_active', None)
34
- state.pop('_finalized', None)
35
- state.pop('_map', None)
32
+ state.pop("_raise_error", None)
33
+ state.pop("_active", None)
34
+ state.pop("_finalized", None)
35
+ state.pop("_map", None)
36
36
  # drop everything that starts with SPECIAL_CONSTANT
37
37
  for key in list(state.keys()):
38
- if (not key.startswith(SPECIAL_CONSTANT) and key != '_value') or \
39
- (key == '_value' and obj._value == []) or \
40
- key.replace(SPECIAL_CONSTANT, '') in EXCLUDE_LIST:
38
+ if (
39
+ (not key.startswith(SPECIAL_CONSTANT) and key != "_value")
40
+ or (key == "_value" and obj._value == [])
41
+ or key.replace(SPECIAL_CONSTANT, "") in EXCLUDE_LIST
42
+ ):
41
43
  state.pop(key, None)
42
44
  return state
43
45
  return obj.__dict__
44
46
 
45
47
 
46
48
  class Aggregator(Symbol):
47
- def __init__(self,
48
- value: Union["Aggregator", Symbol] | None = None,
49
- path: str | None = None,
50
- active: bool = True,
51
- raise_error: bool = False,
52
- *args, **kwargs):
53
- super().__init__(*args,
54
- **kwargs)
49
+ def __init__(
50
+ self,
51
+ value: Union["Aggregator", Symbol] | None = None,
52
+ path: str | None = None,
53
+ active: bool = True,
54
+ raise_error: bool = False,
55
+ *args,
56
+ **kwargs,
57
+ ):
58
+ super().__init__(*args, **kwargs)
55
59
  # disable nesy engine to avoid side effects
56
60
  self.__disable_nesy_engine__ = True
57
61
  if value is not None and isinstance(value, Symbol):
@@ -64,29 +68,38 @@ class Aggregator(Symbol):
64
68
  elif not isinstance(self._value, (list, tuple)):
65
69
  self._value = [self._value]
66
70
  elif value is not None:
67
- UserMessage(f'Aggregator object must be of type Aggregator or Symbol! Got: {type(value)}', raise_with=Exception)
71
+ UserMessage(
72
+ f"Aggregator object must be of type Aggregator or Symbol! Got: {type(value)}",
73
+ raise_with=Exception,
74
+ )
68
75
  else:
69
76
  self._value = []
70
- self._raise_error = raise_error
71
- self._active = active
77
+ self._raise_error = raise_error
78
+ self._active = active
72
79
  self._finalized = False
73
- self._map = None
74
- self._path = path
75
-
76
- def __new__(cls, *args,
77
- mixin: bool | None = None,
78
- primitives: list[type] | None = None, # only inherit arithmetic primitives
79
- callables: list[tuple[str, Callable]] | None = None,
80
- semantic: bool = False,
81
- **kwargs) -> "Symbol":
80
+ self._map = None
81
+ self._path = path
82
+
83
+ def __new__(
84
+ cls,
85
+ *args,
86
+ mixin: bool | None = None,
87
+ primitives: list[type] | None = None, # only inherit arithmetic primitives
88
+ callables: list[tuple[str, Callable]] | None = None,
89
+ semantic: bool = False,
90
+ **kwargs,
91
+ ) -> "Symbol":
82
92
  if primitives is None:
83
93
  primitives = [OperatorPrimitives]
84
- return super().__new__(cls, *args,
85
- mixin=mixin,
86
- primitives=primitives,
87
- callables=callables,
88
- semantic=semantic,
89
- **kwargs)
94
+ return super().__new__(
95
+ cls,
96
+ *args,
97
+ mixin=mixin,
98
+ primitives=primitives,
99
+ callables=callables,
100
+ semantic=semantic,
101
+ **kwargs,
102
+ )
90
103
 
91
104
  def __getattr__(self, name):
92
105
  # replace name special characters and spaces with underscores
@@ -98,12 +111,14 @@ class Aggregator(Symbol):
98
111
  self._children.append(aggregator)
99
112
  # create a new aggregate aggregator
100
113
  # named {SPECIAL_CONSTANT}{name} for automatic aggregation
101
- self.__dict__[f'{SPECIAL_CONSTANT}{name}'] = aggregator
114
+ self.__dict__[f"{SPECIAL_CONSTANT}{name}"] = aggregator
102
115
  # add also a property with the same name but without the SPECIAL_CONSTANT prefix as a shortcut
103
- self.__dict__[name] = self.__dict__[f'{SPECIAL_CONSTANT}{name}']
116
+ self.__dict__[name] = self.__dict__[f"{SPECIAL_CONSTANT}{name}"]
104
117
  return self.__dict__.get(name)
105
118
  if not self._active and name not in self.__dict__:
106
- UserMessage(f'Aggregator object is frozen! No attribute {name} found!', raise_with=Exception)
119
+ UserMessage(
120
+ f"Aggregator object is frozen! No attribute {name} found!", raise_with=Exception
121
+ )
107
122
  return self.__dict__.get(name)
108
123
 
109
124
  def __setattr__(self, name, value):
@@ -134,10 +149,10 @@ class Aggregator(Symbol):
134
149
  def __setstate__(self, state):
135
150
  # replace name special characters and spaces with underscores
136
151
  # drop active from state
137
- state.pop('_raise_error', None)
138
- state.pop('_active', None)
139
- state.pop('_finalized', None)
140
- state.pop('_map', None)
152
+ state.pop("_raise_error", None)
153
+ state.pop("_active", None)
154
+ state.pop("_finalized", None)
155
+ state.pop("_map", None)
141
156
  return super().__setstate__(state)
142
157
 
143
158
  @staticmethod
@@ -151,19 +166,19 @@ class Aggregator(Symbol):
151
166
  obj._path = attr_key
152
167
  attr_value = Aggregator._reconstruct(attr_value, parent=parent, strict=strict)
153
168
  if attr_key.startswith(SPECIAL_CONSTANT):
154
- attr_key = attr_key.replace(SPECIAL_CONSTANT, '')
155
- if attr_key == '_value':
169
+ attr_key = attr_key.replace(SPECIAL_CONSTANT, "")
170
+ if attr_key == "_value":
156
171
  try:
157
172
  attr_value = np.asarray(attr_value, dtype=np.float32)
158
173
  except Exception as e:
159
174
  if strict:
160
- msg = f'Could not set value of Aggregator object: {obj.path}! ERROR: {e}'
175
+ msg = f"Could not set value of Aggregator object: {obj.path}! ERROR: {e}"
161
176
  UserMessage(msg)
162
177
  raise Exception(msg) from e
163
178
  obj.__setattr__(attr_key, attr_value)
164
179
 
165
180
  @staticmethod
166
- def _reconstruct(dictionary, parent = None, strict: bool = True):
181
+ def _reconstruct(dictionary, parent=None, strict: bool = True):
167
182
  obj = Aggregator()
168
183
  obj._parent = parent
169
184
  if parent is not None:
@@ -172,12 +187,12 @@ class Aggregator(Symbol):
172
187
  return obj
173
188
 
174
189
  def __str__(self) -> str:
175
- '''
190
+ """
176
191
  Get the string representation of the Symbol object.
177
192
 
178
193
  Returns:
179
194
  str: The string representation of the Symbol object.
180
- '''
195
+ """
181
196
  return str(self.entries)
182
197
 
183
198
  def _to_symbol(self, other) -> Symbol:
@@ -189,13 +204,13 @@ class Aggregator(Symbol):
189
204
 
190
205
  @property
191
206
  def path(self) -> str:
192
- path = ''
193
- obj = self
207
+ path = ""
208
+ obj = self
194
209
  while obj is not None:
195
210
  if obj._path is not None:
196
- path = obj._path.replace(SPECIAL_CONSTANT, '') + '.' + path
211
+ path = obj._path.replace(SPECIAL_CONSTANT, "") + "." + path
197
212
  obj = obj._parent
198
- return path[:-1] # remove last dot
213
+ return path[:-1] # remove last dot
199
214
 
200
215
  def __or__(self, other: Any) -> Any:
201
216
  self.add(other)
@@ -233,7 +248,9 @@ class Aggregator(Symbol):
233
248
  def _set_map_recursively(self, map):
234
249
  self._map = map
235
250
  for key, value in self.__dict__.items():
236
- if isinstance(value, Aggregator) and (not key.startswith('_') or key.startswith(SPECIAL_CONSTANT)):
251
+ if isinstance(value, Aggregator) and (
252
+ not key.startswith("_") or key.startswith(SPECIAL_CONSTANT)
253
+ ):
237
254
  value.map = map
238
255
 
239
256
  def shape(self):
@@ -245,7 +262,7 @@ class Aggregator(Symbol):
245
262
  return json.dumps(self, cls=AggregatorJSONEncoder)
246
263
 
247
264
  def save(self, path: str):
248
- with Path(path).open('w') as f:
265
+ with Path(path).open("w") as f:
249
266
  json.dump(self, f, cls=AggregatorJSONEncoder)
250
267
 
251
268
  @staticmethod
@@ -260,7 +277,7 @@ class Aggregator(Symbol):
260
277
  def add(self, entries):
261
278
  # Add entries to the aggregator
262
279
  if not self.active and self._finalized:
263
- UserMessage('Aggregator object is frozen!', raise_with=Exception)
280
+ UserMessage("Aggregator object is frozen!", raise_with=Exception)
264
281
  return
265
282
  try:
266
283
  processed_entries = self._prepare_entries(entries)
@@ -269,15 +286,29 @@ class Aggregator(Symbol):
269
286
  processed_entries = self._squeeze_entries(processed_entries)
270
287
  self.entries.append(processed_entries)
271
288
  except Exception as e:
272
- msg = f'Could not add entries to Aggregator object! Please verify type or original error: {e}'
289
+ msg = f"Could not add entries to Aggregator object! Please verify type or original error: {e}"
273
290
  if self._raise_error:
274
291
  UserMessage(msg)
275
292
  raise Exception(msg) from e
276
293
  UserMessage(msg)
277
294
 
278
295
  def _prepare_entries(self, entries):
279
- valid_types = (tuple, list, np.float32, np.float64, np.ndarray, torch.Tensor, int, float, bool, str, Symbol)
280
- assert isinstance(entries, valid_types), f'Entries must be a tuple, list, numpy array, torch tensor, integer, float, boolean, string, or Symbol! Got: {type(entries)}'
296
+ valid_types = (
297
+ tuple,
298
+ list,
299
+ np.float32,
300
+ np.float64,
301
+ np.ndarray,
302
+ torch.Tensor,
303
+ int,
304
+ float,
305
+ bool,
306
+ str,
307
+ Symbol,
308
+ )
309
+ assert isinstance(entries, valid_types), (
310
+ f"Entries must be a tuple, list, numpy array, torch tensor, integer, float, boolean, string, or Symbol! Got: {type(entries)}"
311
+ )
281
312
  if isinstance(entries, torch.Tensor):
282
313
  return entries.detach().cpu().numpy().astype(np.float32)
283
314
  if isinstance(entries, (tuple, list)):
@@ -302,8 +333,11 @@ class Aggregator(Symbol):
302
333
 
303
334
  def keys(self):
304
335
  # Get all key names of items that have the SPECIAL_CONSTANT prefix
305
- return [key.replace(SPECIAL_CONSTANT, '') for key in self.__dict__ if not key.startswith('_') and \
306
- key.replace(SPECIAL_CONSTANT, '') not in EXCLUDE_LIST]
336
+ return [
337
+ key.replace(SPECIAL_CONSTANT, "")
338
+ for key in self.__dict__
339
+ if not key.startswith("_") and key.replace(SPECIAL_CONSTANT, "") not in EXCLUDE_LIST
340
+ ]
307
341
 
308
342
  @property
309
343
  def active(self):
@@ -313,7 +347,7 @@ class Aggregator(Symbol):
313
347
  @active.setter
314
348
  def active(self, value):
315
349
  # Set the active status of the aggregator
316
- assert isinstance(value, bool), f'Active status must be a boolean! Got: {type(value)}'
350
+ assert isinstance(value, bool), f"Active status must be a boolean! Got: {type(value)}"
317
351
  self._active = value
318
352
 
319
353
  @property
@@ -324,25 +358,31 @@ class Aggregator(Symbol):
324
358
  @finalized.setter
325
359
  def finalized(self, value):
326
360
  # Set the finalized status of the aggregator
327
- assert isinstance(value, bool), f'Finalized status must be a boolean! Got: {type(value)}'
361
+ assert isinstance(value, bool), f"Finalized status must be a boolean! Got: {type(value)}"
328
362
  self._finalized = value
329
363
 
330
364
  def finalize(self):
331
365
  # Finalizes the dynamic creation of the aggregators and freezes the object to prevent further changes
332
- self._active = False
333
- self._finalized = True
366
+ self._active = False
367
+ self._finalized = True
368
+
334
369
  def raise_exception(name, value):
335
- if name == 'map':
370
+ if name == "map":
336
371
  self.__setattr__(name, value)
337
372
  else:
338
- UserMessage('Aggregator object is frozen!', raise_with=Exception)
373
+ UserMessage("Aggregator object is frozen!", raise_with=Exception)
374
+
339
375
  self.__setattr__ = raise_exception
376
+
340
377
  def get_attribute(*args, **kwargs):
341
378
  return self.__dict__.get(*args, **kwargs)
379
+
342
380
  self.__getattr__ = get_attribute
343
381
  # Do the same recursively for all properties of type Aggregator
344
382
  for key, value in self.__dict__.items():
345
- if isinstance(value, Aggregator) and (not key.startswith('_') or key.startswith(SPECIAL_CONSTANT)):
383
+ if isinstance(value, Aggregator) and (
384
+ not key.startswith("_") or key.startswith(SPECIAL_CONSTANT)
385
+ ):
346
386
  value.finalize()
347
387
 
348
388
  def get(self, *args, **kwargs):
@@ -354,7 +394,7 @@ class Aggregator(Symbol):
354
394
  def clear(self):
355
395
  # Clear the entries of the aggregator
356
396
  if self._finalized:
357
- UserMessage('Aggregator object is frozen!', raise_with=Exception)
397
+ UserMessage("Aggregator object is frozen!", raise_with=Exception)
358
398
  self._value = []
359
399
 
360
400
  def sum(self, axis=0):