symbolicai 1.6.0__py3-none-any.whl → 1.7.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 CHANGED
@@ -31,7 +31,7 @@ os.environ["TOKENIZERS_PARALLELISM"] = "false"
31
31
  # Create singleton instance
32
32
  config_manager = settings.SymAIConfig()
33
33
 
34
- SYMAI_VERSION = "1.6.0"
34
+ SYMAI_VERSION = "1.7.0"
35
35
  __version__ = SYMAI_VERSION
36
36
  __root_dir__ = config_manager.config_dir
37
37
 
@@ -64,6 +64,7 @@ class ClaudeXChatEngine(Engine, AnthropicMixin):
64
64
  and "4-0" not in self.config.get("NEUROSYMBOLIC_ENGINE_MODEL")
65
65
  and "4-1" not in self.config.get("NEUROSYMBOLIC_ENGINE_MODEL")
66
66
  and "4-5" not in self.config.get("NEUROSYMBOLIC_ENGINE_MODEL")
67
+ and "4-6" not in self.config.get("NEUROSYMBOLIC_ENGINE_MODEL")
67
68
  )
68
69
  ):
69
70
  return "neurosymbolic"
@@ -66,6 +66,7 @@ class ClaudeXReasoningEngine(Engine, AnthropicMixin):
66
66
  or "4-0" in self.config.get("NEUROSYMBOLIC_ENGINE_MODEL")
67
67
  or "4-1" in self.config.get("NEUROSYMBOLIC_ENGINE_MODEL")
68
68
  or "4-5" in self.config.get("NEUROSYMBOLIC_ENGINE_MODEL")
69
+ or "4-6" in self.config.get("NEUROSYMBOLIC_ENGINE_MODEL")
69
70
  )
70
71
  ):
71
72
  return "neurosymbolic"
@@ -348,9 +349,48 @@ class ClaudeXReasoningEngine(Engine, AnthropicMixin):
348
349
 
349
350
  return {"role": "user", "content": user_text}
350
351
 
352
+ def _build_output_config(self, response_format):
353
+ if response_format is None:
354
+ return NOT_GIVEN
355
+
356
+ if response_format["type"] == "json_schema":
357
+ schema = response_format.get("schema")
358
+ if schema is None and response_format.get("json_schema") is not None:
359
+ schema = response_format["json_schema"].get("schema", response_format["json_schema"])
360
+ if schema is None:
361
+ return NOT_GIVEN
362
+ return {"format": {"type": "json_schema", "schema": schema}}
363
+
364
+ if response_format["type"] == "json_object":
365
+ schema = response_format.get("schema")
366
+ if schema is None:
367
+ return NOT_GIVEN
368
+ return {"format": {"type": "json_schema", "schema": schema}}
369
+
370
+ return NOT_GIVEN
371
+
351
372
  def _prepare_request_payload(self, argument):
352
373
  kwargs = argument.kwargs
353
374
  model = kwargs.get("model", self.model)
375
+ long_context_1m = bool(kwargs.get("long_context_1m", False))
376
+ use_long_context_1m = long_context_1m and self.supports_long_context_1m(model)
377
+ effective_context_tokens = self.api_max_context_tokens(model=model)
378
+ if effective_context_tokens is None:
379
+ effective_context_tokens = 200_000
380
+ if use_long_context_1m:
381
+ effective_context_tokens = self.api_max_context_tokens(
382
+ long_context_1m=True, model=model
383
+ )
384
+ if long_context_1m and not use_long_context_1m:
385
+ UserMessage(
386
+ "long_context_1m is only supported for claude-opus-4-6 and claude-sonnet-4-5; "
387
+ f"falling back to {effective_context_tokens} token context."
388
+ )
389
+
390
+ extra_headers = None
391
+ if use_long_context_1m:
392
+ extra_headers = {"anthropic-beta": self.long_context_beta_header()}
393
+
354
394
  stop = kwargs.get("stop", NOT_GIVEN)
355
395
  temperature = kwargs.get("temperature", 1)
356
396
  thinking_arg = kwargs.get("thinking", NOT_GIVEN)
@@ -368,6 +408,8 @@ class ClaudeXReasoningEngine(Engine, AnthropicMixin):
368
408
  tool_choice = kwargs.get("tool_choice", NOT_GIVEN)
369
409
  metadata_anthropic = kwargs.get("metadata", NOT_GIVEN)
370
410
  max_tokens = kwargs.get("max_tokens", self.max_response_tokens)
411
+ response_format = kwargs.get("response_format", argument.prop.response_format)
412
+ output_config = self._build_output_config(response_format)
371
413
 
372
414
  if stop != NOT_GIVEN and not isinstance(stop, list):
373
415
  stop = [stop]
@@ -377,7 +419,7 @@ class ClaudeXReasoningEngine(Engine, AnthropicMixin):
377
419
  if stop != NOT_GIVEN:
378
420
  stop = [r"{s}" for s in stop]
379
421
 
380
- return {
422
+ payload = {
381
423
  "model": model,
382
424
  "max_tokens": max_tokens,
383
425
  "stop_sequences": stop,
@@ -389,7 +431,12 @@ class ClaudeXReasoningEngine(Engine, AnthropicMixin):
389
431
  "metadata": metadata_anthropic,
390
432
  "tools": tools,
391
433
  "tool_choice": tool_choice,
434
+ "output_config": output_config,
392
435
  }
436
+ if extra_headers is not None:
437
+ payload["extra_headers"] = extra_headers
438
+
439
+ return payload
393
440
 
394
441
  def _collect_response(self, res):
395
442
  if isinstance(res, list):
@@ -16,6 +16,7 @@ logging.getLogger("requests").setLevel(logging.ERROR)
16
16
  logging.getLogger("urllib").setLevel(logging.ERROR)
17
17
  logging.getLogger("httpx").setLevel(logging.ERROR)
18
18
  logging.getLogger("httpcore").setLevel(logging.ERROR)
19
+ logging.getLogger("hpack").setLevel(logging.ERROR)
19
20
 
20
21
 
21
22
  _NON_VERBOSE_OUTPUT = (
@@ -10,6 +10,7 @@ SUPPORTED_CHAT_MODELS = [
10
10
  "claude-3-haiku-20240307",
11
11
  ]
12
12
  SUPPORTED_REASONING_MODELS = [
13
+ "claude-opus-4-6",
13
14
  "claude-opus-4-5",
14
15
  "claude-opus-4-1",
15
16
  "claude-opus-4-0",
@@ -19,29 +20,49 @@ SUPPORTED_REASONING_MODELS = [
19
20
  "claude-sonnet-4-5",
20
21
  ]
21
22
 
23
+ LONG_CONTEXT_1M_TOKENS = 1_000_000
24
+ LONG_CONTEXT_1M_BETA_HEADER = "context-1m-2025-08-07"
25
+ LONG_CONTEXT_1M_MODELS = {
26
+ "claude-opus-4-6",
27
+ "claude-sonnet-4-5",
28
+ }
29
+
22
30
 
23
31
  class AnthropicMixin:
24
- def api_max_context_tokens(self):
32
+ def supports_long_context_1m(self, model: str) -> bool:
33
+ return model in LONG_CONTEXT_1M_MODELS
34
+
35
+ def long_context_beta_header(self) -> str:
36
+ return LONG_CONTEXT_1M_BETA_HEADER
37
+
38
+ def api_max_context_tokens(self, long_context_1m: bool = False, model: str | None = None):
39
+ selected_model = self.model if model is None else model
40
+ if long_context_1m and self.supports_long_context_1m(selected_model):
41
+ return LONG_CONTEXT_1M_TOKENS
25
42
  if (
26
- self.model == "claude-opus-4-5"
27
- or self.model == "claude-opus-4-1"
28
- or self.model == "claude-opus-4-0"
29
- or self.model == "claude-sonnet-4-0"
30
- or self.model == "claude-3-7-sonnet-latest"
31
- or self.model == "claude-haiku-4-5"
32
- or self.model == "claude-sonnet-4-5"
33
- or self.model == "claude-3-5-sonnet-latest"
34
- or self.model == "claude-3-5-sonnet-20241022"
35
- or self.model == "claude-3-5-sonnet-20240620"
36
- or self.model == "claude-3-opus-latest"
37
- or self.model == "claude-3-opus-20240229"
38
- or self.model == "claude-3-sonnet-20240229"
39
- or self.model == "claude-3-haiku-20240307"
43
+ selected_model == "claude-opus-4-6"
44
+ or selected_model == "claude-opus-4-5"
45
+ or selected_model == "claude-opus-4-1"
46
+ or selected_model == "claude-opus-4-0"
47
+ or selected_model == "claude-sonnet-4-0"
48
+ or selected_model == "claude-3-7-sonnet-latest"
49
+ or selected_model == "claude-haiku-4-5"
50
+ or selected_model == "claude-sonnet-4-5"
51
+ or selected_model == "claude-3-5-sonnet-latest"
52
+ or selected_model == "claude-3-5-sonnet-20241022"
53
+ or selected_model == "claude-3-5-sonnet-20240620"
54
+ or selected_model == "claude-3-opus-latest"
55
+ or selected_model == "claude-3-opus-20240229"
56
+ or selected_model == "claude-3-sonnet-20240229"
57
+ or selected_model == "claude-3-haiku-20240307"
40
58
  ):
41
59
  return 200_000
42
60
  return None
43
61
 
44
62
  def api_max_response_tokens(self):
63
+ if self.model == "claude-opus-4-6":
64
+ return 128_000
65
+
45
66
  if (
46
67
  self.model == "claude-opus-4-5"
47
68
  or self.model == "claude-sonnet-4-0"
@@ -61,7 +82,7 @@ class AnthropicMixin:
61
82
  if (
62
83
  self.model == "claude-3-5-sonnet-20240620"
63
84
  or self.model == "claude-3-opus-latest"
64
- or self.model == "clade-3-opus-20240229"
85
+ or self.model == "claude-3-opus-20240229"
65
86
  or self.model == "claude-3-sonnet-20240229"
66
87
  or self.model == "claude-3-haiku-20240307"
67
88
  ):
symai/strategy.py CHANGED
@@ -3,9 +3,11 @@ import logging
3
3
  import time
4
4
  from collections import defaultdict
5
5
  from collections.abc import Callable
6
+ from contextlib import nullcontext
6
7
  from typing import Any, ClassVar
7
8
 
8
9
  import numpy as np
10
+ from anthropic import transform_schema
9
11
  from beartype import beartype
10
12
  from loguru import logger
11
13
  from pydantic import BaseModel, ValidationError
@@ -14,7 +16,9 @@ from rich.markup import escape
14
16
  from rich.panel import Panel
15
17
  from rich.table import Table
16
18
 
19
+ from .backend.settings import SYMAI_CONFIG
17
20
  from .components import Function
21
+ from .context import CURRENT_ENGINE_VAR
18
22
  from .models import LLMDataModel, TypeValidationError, build_dynamic_llm_datamodel
19
23
  from .symbol import Expression
20
24
  from .utils import UserMessage
@@ -182,6 +186,7 @@ class TypeValidationFunction(ValidationFunction):
182
186
  self.output_data_model = None
183
187
  self.accumulate_errors = accumulate_errors
184
188
  self.verbose = verbose
189
+ self.dynamic_engine = self.retry_params.get("dynamic_engine")
185
190
 
186
191
  def register_expected_data_model(
187
192
  self, data_model: LLMDataModel, attach_to: str, override: bool = False
@@ -361,7 +366,8 @@ Important guidelines:
361
366
  if self.verbose:
362
367
  self.display_panel(self.remedy_function.dynamic_context, title="New Context")
363
368
 
364
- json_str = self.remedy_function(seed=remedy_seeds[attempt_index], **kwargs).value
369
+ with (self.dynamic_engine if self.dynamic_engine is not None else nullcontext()):
370
+ json_str = self.remedy_function(seed=remedy_seeds[attempt_index], **kwargs).value
365
371
  logger.info("Applied remedy function with updated context!")
366
372
  return json_str
367
373
 
@@ -418,17 +424,51 @@ Important guidelines:
418
424
  violations=errors,
419
425
  )
420
426
 
427
+ def _build_response_format(self, kwargs: dict) -> dict:
428
+ response_format = kwargs.get("response_format")
429
+ if response_format is None:
430
+ response_format = {"type": "json_object"}
431
+ # Resolve the effective model from the most specific runtime source first.
432
+ # This keeps contracts working when engines are swapped dynamically and no static
433
+ # model is registered in config.
434
+ selected_model = kwargs.get("model")
435
+ if selected_model is None:
436
+ active_engine = CURRENT_ENGINE_VAR.get()
437
+ if active_engine is not None:
438
+ selected_model = getattr(active_engine, "model", None)
439
+ if selected_model is None:
440
+ selected_model = SYMAI_CONFIG.get("NEUROSYMBOLIC_ENGINE_MODEL", "")
441
+
442
+ if "claude-opus" not in selected_model:
443
+ return response_format
444
+
445
+ if response_format.get("type") != "json_object":
446
+ return response_format
447
+
448
+ # At the contract layer, `json_object` stays the generic trigger for structured output.
449
+ # Opus requires a concrete JSON Schema payload, so we derive it from the output model.
450
+ return {"type": "json_schema", "schema": transform_schema(self.output_data_model)}
451
+
421
452
  def forward(
422
453
  self, prompt: str, f_semantic_conditions: list[Callable] | None = None, *args, **kwargs
423
454
  ):
424
455
  self._ensure_output_model()
425
456
  validation_context = kwargs.pop("validation_context", {})
426
- kwargs["response_format"] = {"type": "json_object"}
457
+ kwargs["response_format"] = self._build_response_format(kwargs)
427
458
  logger.info("Initializing validation…")
428
459
  self._display_verbose_panels(prompt)
429
460
 
430
461
  context = self.zero_shot_prompt(prompt=prompt)
431
- json_str = super().forward(context, *args, **kwargs).value
462
+
463
+ # Zero-shot attempt; fall back to dynamic engine on failure
464
+ try:
465
+ json_str = super().forward(context, *args, **kwargs).value
466
+ except Exception:
467
+ if self.dynamic_engine is None:
468
+ raise
469
+ logger.info("Zero-shot failed; retrying with dynamic engine…")
470
+ with self.dynamic_engine:
471
+ json_str = super().forward(context, *args, **kwargs).value
432
472
 
433
473
  remedy_seeds = self.prepare_seeds(self.retry_params["tries"] + 1, **kwargs)
434
474
  logger.info(f"Prepared {len(remedy_seeds)} remedy seeds for validation attempts…")
@@ -468,7 +508,7 @@ class contract:
468
508
  post_remedy: bool = False,
469
509
  accumulate_errors: bool = False,
470
510
  verbose: bool = False,
471
- remedy_retry_params: dict[str, int | float | bool] = _default_remedy_retry_params,
511
+ remedy_retry_params: dict[str, Any] = _default_remedy_retry_params,
472
512
  ):
473
513
  """
474
514
  A contract class decorator inspired by DbC principles. It ensures that the function's input and output
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: symbolicai
3
- Version: 1.6.0
3
+ Version: 1.7.0
4
4
  Summary: A Neurosymbolic Perspective on Large Language Models
5
5
  Author-email: Marius-Constantin Dinu <marius@extensity.ai>, Leoveanu-Condrei Claudiu <leo@extensity.ai>
6
6
  License: BSD 3-Clause License
@@ -52,7 +52,7 @@ Requires-Dist: tqdm>=4.66.3
52
52
  Requires-Dist: python-box>=7.1.1
53
53
  Requires-Dist: pandas>=2.2.2
54
54
  Requires-Dist: scikit-learn>=1.5.0
55
- Requires-Dist: torch>=2.2.2
55
+ Requires-Dist: torch<2.10.0
56
56
  Requires-Dist: torchaudio>=2.2.2
57
57
  Requires-Dist: torchvision>=0.17.2
58
58
  Requires-Dist: PyYAML>=6.0.1
@@ -1,5 +1,5 @@
1
1
  symai/TERMS_OF_SERVICE.md,sha256=HN42UXVI_wAVDHjMShzy_k7xAsbjXaATNeMKcIte_eg,91409
2
- symai/__init__.py,sha256=P9fADfIIeSF_rI1YQUhBHQIMieDgvLt-QM4KvOKtvt4,15612
2
+ symai/__init__.py,sha256=j5bwtmnvxtMH6h5LsdMB5hgynMwXRVH5tWJ5rp49Am0,15612
3
3
  symai/chat.py,sha256=DCEbmZ96wv-eitAVt6-oF6PT3JM3cT59Iy3r2Hucd_M,14100
4
4
  symai/components.py,sha256=SsGl8Cs-AQcPZjFyTv4IB3ATz8evRiVwTBH7k2umVSo,75391
5
5
  symai/constraints.py,sha256=ljjB9p0qK4DrDl_u5G_Y-Y6WAH5ZHANIqLLxRtwcORs,1980
@@ -17,7 +17,7 @@ symai/processor.py,sha256=FsR7rIjm6NlestgX3dVOLtvQJcGNpJaogtPyi3I1PR4,1648
17
17
  symai/prompts.py,sha256=cF3FauHfl0ZiBW-6DEE50wx_elNN7PBTbbmlVCr7nzQ,93743
18
18
  symai/shell.py,sha256=iEQ-dGGPSm7ZDaaC3I7RwnzgA8X9yHBzPD0TouBk3AU,6487
19
19
  symai/shellsv.py,sha256=rdKwBRqTT0k81LgMi0qshD4z8ucYL5iDCN4MOCgvEa8,39581
20
- symai/strategy.py,sha256=BQTXRnBv57fYO47A--WA6KK1oqGmf9Aijm0p4a_vvqY,45004
20
+ symai/strategy.py,sha256=8-BlvTQ-o1XlVbHiu5LE7wtYRyqwAJPv3qgN6UHnuN0,46932
21
21
  symai/symbol.py,sha256=s5CYwP5SGcRUzZ7TlakZFpKBX_Q0mwPQKRbv4pC3sxM,40443
22
22
  symai/symsh.md,sha256=QwY_-fX0Ge7Aazul0xde2DuF2FZLw_elxrkXR3kuKDQ,1245
23
23
  symai/utils.py,sha256=m4iQzxclkPAUSDderTO_OK2fKznJ69pLfbBcTYq4p70,10824
@@ -39,9 +39,9 @@ symai/backend/engines/index/engine_qdrant.py,sha256=U9p0kzYvHE4DjFgxnvnG_8xfEoP_
39
39
  symai/backend/engines/index/engine_vectordb.py,sha256=xXU8QaC2BX9O4dDjDCVYgWO4PxQMpmNlhtal6UVtV0o,8541
40
40
  symai/backend/engines/lean/engine_lean4.py,sha256=ln5nbQn5szq8nRulbREPLCPQ5bwjM_A5XAGMkfzPdT8,10102
41
41
  symai/backend/engines/neurosymbolic/__init__.py,sha256=zEjkuxtzBQdxx-b1aXzooCatA43Rrlo9jAyZZfRYNzM,2608
42
- symai/backend/engines/neurosymbolic/engine_anthropic_claudeX_chat.py,sha256=WyuskobMjf9ynxRWUnXk55DUMUN7qv7jT1nbZP3Bx9o,21054
43
- symai/backend/engines/neurosymbolic/engine_anthropic_claudeX_reasoning.py,sha256=thEPDh8H-5XrsADF0mVTWB6m_dJgKeTT49HvyCGJcQM,21291
44
- symai/backend/engines/neurosymbolic/engine_cerebras.py,sha256=ki84Qh7hdxaKn--UgMMUvAEoqJos7VeKtkka6XpHI3g,13336
42
+ symai/backend/engines/neurosymbolic/engine_anthropic_claudeX_chat.py,sha256=Y5AOCmJgL51QgrVbezSd0pe8GgMYNCuWWDIDES1_eaM,21133
43
+ symai/backend/engines/neurosymbolic/engine_anthropic_claudeX_reasoning.py,sha256=PaIN_C6xMhAUw51vGkI774q-PMnq30mofWsOtwYrIc8,23393
44
+ symai/backend/engines/neurosymbolic/engine_cerebras.py,sha256=zFnKKd_9iEL2S-4hKFMG4vPAK-fkSOkaUMJlZ5EvoF4,13387
45
45
  symai/backend/engines/neurosymbolic/engine_deepseekX_reasoning.py,sha256=_k0hy5dUxkbNP9vgF4R780A6THtjfcCJ_xUnkPvPRNw,9299
46
46
  symai/backend/engines/neurosymbolic/engine_google_geminiX_reasoning.py,sha256=pvsUNtWYwvFXt8EEy5ed0V4xE4EE0IZ4f7Uw5jV3OF0,28333
47
47
  symai/backend/engines/neurosymbolic/engine_groq.py,sha256=pliezi4X1LP-XdnJirjlI2nCXC8S2pex8fZalNlkKWw,13122
@@ -66,7 +66,7 @@ symai/backend/engines/text_to_speech/engine_openai.py,sha256=AtY0mDvIM_yZQ6AgYNX
66
66
  symai/backend/engines/text_vision/engine_clip.py,sha256=hU9vsHtKPpQYEoESyjuGXOzMhUNhvspYMCNkCAqn2x8,3648
67
67
  symai/backend/engines/userinput/engine_console.py,sha256=fDO6PRQI3NYZ_nHVXDFIsS9cFDRv3aTOfv8h5a360jc,743
68
68
  symai/backend/mixin/__init__.py,sha256=LMeNSxy0Uwn3CSSImgGcRal7JpZqIxP9I1lw0C4sLJ0,1539
69
- symai/backend/mixin/anthropic.py,sha256=GdHimGqiJcA21Jo797ZEeFzotRpCOJdBJQIChl_6NJI,2403
69
+ symai/backend/mixin/anthropic.py,sha256=b06RGsEa_lvn1VBKRtLt1BPROCnR6g_lPO0BQtU2s0o,3213
70
70
  symai/backend/mixin/cerebras.py,sha256=MEc9vQ6G4KWWrt0NFjdt2y0rojhtBidwa_n4M8Z5EKI,215
71
71
  symai/backend/mixin/deepseek.py,sha256=7TnyqXQb2t6r6-hzOClPzxfO2d7TShYC989Lmn_YTzM,414
72
72
  symai/backend/mixin/google.py,sha256=N1xxrrTcQkcKJtdPbRorev6dfJ1F65I5XavrGR06GN4,494
@@ -143,9 +143,9 @@ symai/server/__init__.py,sha256=AbpHGcgLb-kRsJGnwFEktk7uzpZOCcBY74-YBdrKVGs,1
143
143
  symai/server/huggingface_server.py,sha256=wSAVqFiKQsCu5UB2YYVpxJBhJ7GgQBBfePxNi265yP8,9039
144
144
  symai/server/llama_cpp_server.py,sha256=-WPTNB2cbnwtnpES4AtPM__MCasDKl83jr94JGS9tmI,2144
145
145
  symai/server/qdrant_server.py,sha256=l4r4rz29c7cO1dapXO0LQ4sHW4WF44keuz7j8v5azMc,9854
146
- symbolicai-1.6.0.dist-info/licenses/LICENSE,sha256=9vRFudlJ1ghVfra5lcCUIYQCqnZSYcBLjLHbGRsrQCs,1505
147
- symbolicai-1.6.0.dist-info/METADATA,sha256=efGH2KBd8r1A30XkrgOgIHHF3tg8KwgPFG_TtgOtOCc,22946
148
- symbolicai-1.6.0.dist-info/WHEEL,sha256=wUyA8OaulRlbfwMtmQsvNngGrxQHAvkKcvRmdizlJi0,92
149
- symbolicai-1.6.0.dist-info/entry_points.txt,sha256=JV5sdydIfUZdDF6QBEQHiZHod6XNPjCjpWQrXh7gTAw,261
150
- symbolicai-1.6.0.dist-info/top_level.txt,sha256=bOoIDfpDIvCQtQgXcwVKJvxAKwsxpxo2IL4z92rNJjw,6
151
- symbolicai-1.6.0.dist-info/RECORD,,
146
+ symbolicai-1.7.0.dist-info/licenses/LICENSE,sha256=9vRFudlJ1ghVfra5lcCUIYQCqnZSYcBLjLHbGRsrQCs,1505
147
+ symbolicai-1.7.0.dist-info/METADATA,sha256=leIkcs9g6yfwn3e7qqRGnZHUL_Co6M9G5W9YddvE1QM,22946
148
+ symbolicai-1.7.0.dist-info/WHEEL,sha256=wUyA8OaulRlbfwMtmQsvNngGrxQHAvkKcvRmdizlJi0,92
149
+ symbolicai-1.7.0.dist-info/entry_points.txt,sha256=JV5sdydIfUZdDF6QBEQHiZHod6XNPjCjpWQrXh7gTAw,261
150
+ symbolicai-1.7.0.dist-info/top_level.txt,sha256=bOoIDfpDIvCQtQgXcwVKJvxAKwsxpxo2IL4z92rNJjw,6
151
+ symbolicai-1.7.0.dist-info/RECORD,,