symbolicai 0.21.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 (134) hide show
  1. symai/__init__.py +269 -173
  2. symai/backend/base.py +123 -110
  3. symai/backend/engines/drawing/engine_bfl.py +45 -44
  4. symai/backend/engines/drawing/engine_gpt_image.py +112 -97
  5. symai/backend/engines/embedding/engine_llama_cpp.py +63 -52
  6. symai/backend/engines/embedding/engine_openai.py +25 -21
  7. symai/backend/engines/execute/engine_python.py +19 -18
  8. symai/backend/engines/files/engine_io.py +104 -95
  9. symai/backend/engines/imagecaptioning/engine_blip2.py +28 -24
  10. symai/backend/engines/imagecaptioning/engine_llavacpp_client.py +102 -79
  11. symai/backend/engines/index/engine_pinecone.py +124 -97
  12. symai/backend/engines/index/engine_qdrant.py +1011 -0
  13. symai/backend/engines/index/engine_vectordb.py +84 -56
  14. symai/backend/engines/lean/engine_lean4.py +96 -52
  15. symai/backend/engines/neurosymbolic/__init__.py +41 -13
  16. symai/backend/engines/neurosymbolic/engine_anthropic_claudeX_chat.py +330 -248
  17. symai/backend/engines/neurosymbolic/engine_anthropic_claudeX_reasoning.py +329 -264
  18. symai/backend/engines/neurosymbolic/engine_cerebras.py +328 -0
  19. symai/backend/engines/neurosymbolic/engine_deepseekX_reasoning.py +118 -88
  20. symai/backend/engines/neurosymbolic/engine_google_geminiX_reasoning.py +344 -299
  21. symai/backend/engines/neurosymbolic/engine_groq.py +173 -115
  22. symai/backend/engines/neurosymbolic/engine_huggingface.py +114 -84
  23. symai/backend/engines/neurosymbolic/engine_llama_cpp.py +144 -118
  24. symai/backend/engines/neurosymbolic/engine_openai_gptX_chat.py +415 -307
  25. symai/backend/engines/neurosymbolic/engine_openai_gptX_reasoning.py +394 -231
  26. symai/backend/engines/ocr/engine_apilayer.py +23 -27
  27. symai/backend/engines/output/engine_stdout.py +10 -13
  28. symai/backend/engines/{webscraping → scrape}/engine_requests.py +101 -54
  29. symai/backend/engines/search/engine_openai.py +100 -88
  30. symai/backend/engines/search/engine_parallel.py +665 -0
  31. symai/backend/engines/search/engine_perplexity.py +44 -45
  32. symai/backend/engines/search/engine_serpapi.py +37 -34
  33. symai/backend/engines/speech_to_text/engine_local_whisper.py +54 -51
  34. symai/backend/engines/symbolic/engine_wolframalpha.py +15 -9
  35. symai/backend/engines/text_to_speech/engine_openai.py +20 -26
  36. symai/backend/engines/text_vision/engine_clip.py +39 -37
  37. symai/backend/engines/userinput/engine_console.py +5 -6
  38. symai/backend/mixin/__init__.py +13 -0
  39. symai/backend/mixin/anthropic.py +48 -38
  40. symai/backend/mixin/deepseek.py +6 -5
  41. symai/backend/mixin/google.py +7 -4
  42. symai/backend/mixin/groq.py +2 -4
  43. symai/backend/mixin/openai.py +140 -110
  44. symai/backend/settings.py +87 -20
  45. symai/chat.py +216 -123
  46. symai/collect/__init__.py +7 -1
  47. symai/collect/dynamic.py +80 -70
  48. symai/collect/pipeline.py +67 -51
  49. symai/collect/stats.py +161 -109
  50. symai/components.py +707 -360
  51. symai/constraints.py +24 -12
  52. symai/core.py +1857 -1233
  53. symai/core_ext.py +83 -80
  54. symai/endpoints/api.py +166 -104
  55. symai/extended/.DS_Store +0 -0
  56. symai/extended/__init__.py +46 -12
  57. symai/extended/api_builder.py +29 -21
  58. symai/extended/arxiv_pdf_parser.py +23 -14
  59. symai/extended/bibtex_parser.py +9 -6
  60. symai/extended/conversation.py +156 -126
  61. symai/extended/document.py +50 -30
  62. symai/extended/file_merger.py +57 -14
  63. symai/extended/graph.py +51 -32
  64. symai/extended/html_style_template.py +18 -14
  65. symai/extended/interfaces/blip_2.py +2 -3
  66. symai/extended/interfaces/clip.py +4 -3
  67. symai/extended/interfaces/console.py +9 -1
  68. symai/extended/interfaces/dall_e.py +4 -2
  69. symai/extended/interfaces/file.py +2 -0
  70. symai/extended/interfaces/flux.py +4 -2
  71. symai/extended/interfaces/gpt_image.py +16 -7
  72. symai/extended/interfaces/input.py +2 -1
  73. symai/extended/interfaces/llava.py +1 -2
  74. symai/extended/interfaces/{naive_webscraping.py → naive_scrape.py} +4 -3
  75. symai/extended/interfaces/naive_vectordb.py +9 -10
  76. symai/extended/interfaces/ocr.py +5 -3
  77. symai/extended/interfaces/openai_search.py +2 -0
  78. symai/extended/interfaces/parallel.py +30 -0
  79. symai/extended/interfaces/perplexity.py +2 -0
  80. symai/extended/interfaces/pinecone.py +12 -9
  81. symai/extended/interfaces/python.py +2 -0
  82. symai/extended/interfaces/serpapi.py +3 -1
  83. symai/extended/interfaces/terminal.py +2 -4
  84. symai/extended/interfaces/tts.py +3 -2
  85. symai/extended/interfaces/whisper.py +3 -2
  86. symai/extended/interfaces/wolframalpha.py +2 -1
  87. symai/extended/metrics/__init__.py +11 -1
  88. symai/extended/metrics/similarity.py +14 -13
  89. symai/extended/os_command.py +39 -29
  90. symai/extended/packages/__init__.py +29 -3
  91. symai/extended/packages/symdev.py +51 -43
  92. symai/extended/packages/sympkg.py +41 -35
  93. symai/extended/packages/symrun.py +63 -50
  94. symai/extended/repo_cloner.py +14 -12
  95. symai/extended/seo_query_optimizer.py +15 -13
  96. symai/extended/solver.py +116 -91
  97. symai/extended/summarizer.py +12 -10
  98. symai/extended/taypan_interpreter.py +17 -18
  99. symai/extended/vectordb.py +122 -92
  100. symai/formatter/__init__.py +9 -1
  101. symai/formatter/formatter.py +51 -47
  102. symai/formatter/regex.py +70 -69
  103. symai/functional.py +325 -176
  104. symai/imports.py +190 -147
  105. symai/interfaces.py +57 -28
  106. symai/memory.py +45 -35
  107. symai/menu/screen.py +28 -19
  108. symai/misc/console.py +66 -56
  109. symai/misc/loader.py +8 -5
  110. symai/models/__init__.py +17 -1
  111. symai/models/base.py +395 -236
  112. symai/models/errors.py +1 -2
  113. symai/ops/__init__.py +32 -22
  114. symai/ops/measures.py +24 -25
  115. symai/ops/primitives.py +1149 -731
  116. symai/post_processors.py +58 -50
  117. symai/pre_processors.py +86 -82
  118. symai/processor.py +21 -13
  119. symai/prompts.py +764 -685
  120. symai/server/huggingface_server.py +135 -49
  121. symai/server/llama_cpp_server.py +21 -11
  122. symai/server/qdrant_server.py +206 -0
  123. symai/shell.py +100 -42
  124. symai/shellsv.py +700 -492
  125. symai/strategy.py +630 -346
  126. symai/symbol.py +368 -322
  127. symai/utils.py +100 -78
  128. {symbolicai-0.21.0.dist-info → symbolicai-1.1.0.dist-info}/METADATA +22 -10
  129. symbolicai-1.1.0.dist-info/RECORD +168 -0
  130. symbolicai-0.21.0.dist-info/RECORD +0 -162
  131. {symbolicai-0.21.0.dist-info → symbolicai-1.1.0.dist-info}/WHEEL +0 -0
  132. {symbolicai-0.21.0.dist-info → symbolicai-1.1.0.dist-info}/entry_points.txt +0 -0
  133. {symbolicai-0.21.0.dist-info → symbolicai-1.1.0.dist-info}/licenses/LICENSE +0 -0
  134. {symbolicai-0.21.0.dist-info → symbolicai-1.1.0.dist-info}/top_level.txt +0 -0
@@ -1,30 +1,38 @@
1
- import os
1
+ from collections.abc import Callable
2
2
  from pathlib import Path
3
- from typing import Callable, List, Optional, Union
3
+ from typing import TYPE_CHECKING, Union
4
4
 
5
5
  from ..components import FileReader, Indexer
6
6
  from ..formatter import ParagraphFormatter
7
7
  from ..symbol import Expression, Symbol
8
+ from ..utils import UserMessage
9
+
10
+ if TYPE_CHECKING:
11
+ from ..backend.engines.files.engine_io import TextContainer
12
+
13
+ _DEFAULT_PARAGRAPH_FORMATTER = ParagraphFormatter()
8
14
 
9
15
 
10
16
  class DocumentRetriever(Expression):
11
17
  def __init__(
12
- self,
13
- source: Optional[str] = None,
14
- *,
15
- index_name: str = Indexer.DEFAULT,
16
- top_k: int = 5,
17
- max_depth: int = 1,
18
- formatter: Callable = ParagraphFormatter(),
19
- overwrite: bool = False,
20
- with_metadata: bool = False,
21
- raw_result: Optional[bool] = False,
22
- new_dim: Optional[int] = None,
23
- **kwargs
24
- ):
18
+ self,
19
+ source: str | None = None,
20
+ *,
21
+ index_name: str = Indexer.DEFAULT,
22
+ top_k: int = 5,
23
+ max_depth: int = 1,
24
+ formatter: Callable = _DEFAULT_PARAGRAPH_FORMATTER,
25
+ overwrite: bool = False,
26
+ with_metadata: bool = False,
27
+ raw_result: bool | None = False,
28
+ new_dim: int | None = None,
29
+ **kwargs,
30
+ ):
25
31
  super().__init__(**kwargs)
26
- self.indexer = Indexer(index_name=index_name, top_k=top_k, formatter=formatter, auto_add=False, new_dim=new_dim)
27
- self.reader = FileReader(with_metadata=with_metadata)
32
+ self.indexer = Indexer(
33
+ index_name=index_name, top_k=top_k, formatter=formatter, auto_add=False, new_dim=new_dim
34
+ )
35
+ self.reader = FileReader(with_metadata=with_metadata)
28
36
  self.new_dim = new_dim
29
37
 
30
38
  if overwrite:
@@ -33,34 +41,43 @@ class DocumentRetriever(Expression):
33
41
  # we insert the text into the index if (1) index does not exist and (2) there's a specific source
34
42
  if source is not None and not self.indexer.exists():
35
43
  self.indexer.register()
36
- text = self.parse_source(source, with_metadata=with_metadata, max_depth=max_depth, **kwargs)
44
+ text = self.parse_source(
45
+ source, with_metadata=with_metadata, max_depth=max_depth, **kwargs
46
+ )
37
47
  self.index = self.indexer(data=text, raw_result=raw_result, **kwargs)
38
48
  else:
39
49
  # we don't insert the text at initialization since the index already exists and there's no specific source
40
50
  self.index = self.indexer(raw_result=raw_result, **kwargs)
41
51
 
42
52
  def forward(
43
- self,
44
- query: Symbol,
45
- raw_result: Optional[bool] = False,
46
- ) -> Symbol:
53
+ self,
54
+ query: Symbol,
55
+ raw_result: bool | None = False,
56
+ ) -> Symbol:
47
57
  return self.index(
48
- query,
49
- raw_result=raw_result,
50
- )
58
+ query,
59
+ raw_result=raw_result,
60
+ )
51
61
 
52
- def insert(self, source: Union[str, Path], **kwargs):
62
+ def insert(self, source: str | Path, **kwargs):
53
63
  # dynamically insert data into the index given a session
54
64
  # the data can be:
55
65
  # - a string (e.g. something that the user wants to insert)
56
66
  # - a file path (e.g. a new file that the user wants to insert)
57
67
  # - a directory path (e.g. a new directory that the user wants to insert)
58
- text = self.parse_source(source, with_metadata=kwargs.get('with_metadata', False), max_depth=kwargs.get('max_depth', 1), **kwargs)
59
- #NOTE: Do we need `new_dim` here?
68
+ text = self.parse_source(
69
+ source,
70
+ with_metadata=kwargs.get("with_metadata", False),
71
+ max_depth=kwargs.get("max_depth", 1),
72
+ **kwargs,
73
+ )
74
+ # NOTE: Do we need `new_dim` here?
60
75
  self.add(text, index_name=self.indexer.index_name, **kwargs)
61
76
  self.config(None, save=True, index_name=self.indexer.index_name, **kwargs)
62
77
 
63
- def parse_source(self, source: str, with_metadata: bool, max_depth: int, **kwargs) -> List[Union[str, 'TextContainer']]:
78
+ def parse_source(
79
+ self, source: str, with_metadata: bool, max_depth: int, **kwargs
80
+ ) -> list[Union[str, "TextContainer"]]:
64
81
  maybe_path = Path(source)
65
82
  if isinstance(source, str) and not (maybe_path.is_file() or maybe_path.is_dir()):
66
83
  return Symbol(source).zip(new_dim=self.new_dim)
@@ -69,4 +86,7 @@ class DocumentRetriever(Expression):
69
86
  return self.reader(files, with_metadata=with_metadata, **kwargs)
70
87
  if maybe_path.is_file():
71
88
  return self.reader(source, with_metadata=with_metadata, **kwargs)
72
- raise ValueError(f"Invalid source: {source}; must be a file, directory, or string")
89
+ UserMessage(
90
+ f"Invalid source: {source}; must be a file, directory, or string", raise_with=ValueError
91
+ )
92
+ return []
@@ -1,10 +1,10 @@
1
1
  import os
2
+ from pathlib import Path
2
3
 
3
4
  from tqdm import tqdm
4
- from typing import List
5
5
 
6
- from ..symbol import Expression, Symbol
7
6
  from ..components import FileReader
7
+ from ..symbol import Expression, Symbol
8
8
 
9
9
 
10
10
  class FileMerger(Expression):
@@ -12,8 +12,48 @@ class FileMerger(Expression):
12
12
  Class to merge contents of multiple files into one, specified by their file endings and root path.
13
13
  Files specified in the exclude list will not be included.
14
14
  """
15
- def __init__(self, file_endings: List[str] = ['.py', '.md', '.txt', '.sh', '.pdf', '.json', '.yaml', '.java', '.cpp', '.hpp', '.c', '.h', '.js', '.css', '.html', '.xml', '.csv', '.tsv', '.yml', '.rst', '.ipynb', '.tex', '.bib'],
16
- file_excludes: List[str] = ['__init__.py', '__pycache__', 'LICENSE', 'requirements.txt', 'environment.yaml', '.git'], **kwargs):
15
+
16
+ def __init__(
17
+ self,
18
+ file_endings: list[str] | None = None,
19
+ file_excludes: list[str] | None = None,
20
+ **kwargs,
21
+ ):
22
+ if file_excludes is None:
23
+ file_excludes = [
24
+ "__init__.py",
25
+ "__pycache__",
26
+ "LICENSE",
27
+ "requirements.txt",
28
+ "environment.yaml",
29
+ ".git",
30
+ ]
31
+ if file_endings is None:
32
+ file_endings = [
33
+ ".py",
34
+ ".md",
35
+ ".txt",
36
+ ".sh",
37
+ ".pdf",
38
+ ".json",
39
+ ".yaml",
40
+ ".java",
41
+ ".cpp",
42
+ ".hpp",
43
+ ".c",
44
+ ".h",
45
+ ".js",
46
+ ".css",
47
+ ".html",
48
+ ".xml",
49
+ ".csv",
50
+ ".tsv",
51
+ ".yml",
52
+ ".rst",
53
+ ".ipynb",
54
+ ".tex",
55
+ ".bib",
56
+ ]
17
57
  super().__init__(**kwargs)
18
58
  self.file_endings = file_endings
19
59
  self.file_excludes = file_excludes
@@ -31,29 +71,32 @@ class FileMerger(Expression):
31
71
 
32
72
  # Implement recursive file search
33
73
  # use tqdm for progress bar and description
34
- tqdm_desc = f"Reading file: ..."
74
+ tqdm_desc = "Reading file: ..."
35
75
  # use os.walk to recursively search for files in the root path
36
76
  progress = tqdm(os.walk(root_path), desc=tqdm_desc)
37
77
 
38
- for root, dirs, files in progress:
78
+ for root, _dirs, files in progress:
39
79
  for file in files:
40
- file_path = os.path.join(root, file)
80
+ file_path = Path(root) / file
81
+ file_path_str = file_path.as_posix()
41
82
  # Exclude files with the specified names in the path
42
- if any(exclude in file_path for exclude in self.file_excludes):
83
+ if any(exclude in file_path_str for exclude in self.file_excludes):
43
84
  continue
44
85
 
45
86
  # Look only for files with the specified endings
46
87
  if file.endswith(tuple(self.file_endings)):
47
88
  # Read in the file using the FileReader
48
- file_content = self.reader(file_path, **kwargs).value
89
+ file_content = self.reader(file_path_str, **kwargs).value
49
90
 
50
91
  # escape file name spaces
51
- file_path = file_path.replace(" ", "\\ ")
92
+ file_path_escaped = file_path_str.replace(" ", "\\ ")
52
93
 
53
94
  # Append start and end markers for each file
54
- file_content = f"# ----[FILE_START]<PART1/1>{file_path}[FILE_CONTENT]:\n" + \
55
- file_content + \
56
- f"\n# ----[FILE_END]{file_path}\n"
95
+ file_content = (
96
+ f"# ----[FILE_START]<PART1/1>{file_path_escaped}[FILE_CONTENT]:\n"
97
+ + file_content
98
+ + f"\n# ----[FILE_END]{file_path_escaped}\n"
99
+ )
57
100
 
58
101
  # Merge the file contents
59
102
  merged_file += file_content
@@ -63,4 +106,4 @@ class FileMerger(Expression):
63
106
  progress.set_description(tqdm_desc)
64
107
 
65
108
  # Return the merged file as a Symbol
66
- return self._to_symbol(merged_file)
109
+ return self._to_symbol(merged_file)
symai/extended/graph.py CHANGED
@@ -1,5 +1,5 @@
1
+ from collections.abc import Callable
1
2
  from multiprocessing import Pool
2
- from typing import Callable
3
3
 
4
4
  from .. import core
5
5
  from ..formatter import SentenceFormatter
@@ -7,6 +7,9 @@ from ..post_processors import StripPostProcessor
7
7
  from ..pre_processors import PreProcessor
8
8
  from ..prompts import Prompt
9
9
  from ..symbol import Expression, Symbol
10
+ from ..utils import UserMessage
11
+
12
+ _DEFAULT_SENTENCE_FORMATTER = SentenceFormatter()
10
13
 
11
14
  GRAPH_DESCRIPTION = """[Description]
12
15
  Build source-target relationship pairs for named entities based for the [DATA] section. The [DATA] section contains one sentence.
@@ -18,7 +21,7 @@ If more than one entity pair is extracted from the same sentence, then the CSV f
18
21
 
19
22
  class GraphPreProcessor(PreProcessor):
20
23
  def __call__(self, argument):
21
- return '$> {} =>'.format(str(argument.args[0]))
24
+ return f"$> {argument.args[0]!s} =>"
22
25
 
23
26
 
24
27
  class Graph(Expression):
@@ -26,51 +29,66 @@ class Graph(Expression):
26
29
  def static_context(self) -> str:
27
30
  return GRAPH_DESCRIPTION
28
31
 
29
- def __init__(self, formatter: Callable = SentenceFormatter(), n_workers: int = 1, verbose: bool = False, **kwargs):
32
+ def __init__(
33
+ self,
34
+ formatter: Callable = _DEFAULT_SENTENCE_FORMATTER,
35
+ n_workers: int = 1,
36
+ verbose: bool = False,
37
+ **kwargs,
38
+ ):
30
39
  super().__init__(**kwargs)
31
- self.formatter = formatter
32
- self.n_workers = n_workers
40
+ self.formatter = formatter
41
+ self.n_workers = n_workers
33
42
  self.sym_return_type = Graph
34
- self.verbose = verbose
43
+ self.verbose = verbose
35
44
 
36
- def process_symbol(self, s, *args, **kwargs):
37
- res = ''
45
+ def process_symbol(self, s, *_args, **kwargs):
46
+ res = ""
38
47
 
39
- @core.few_shot(prompt="Extract relationships between entities:\n",
40
- examples=Prompt([
41
- '$> John has a dog. =>John, dog, 1 EOF',
42
- '$> Karl has two sons. =>Karl, sons, 2 EOF',
43
- '$> Similarly, the term general linguistics is used to distinguish core linguistics from other types of study =>general linguistics, core linguistics, 1 EOF',
44
- '$> X has Y and Z has Y =>X, Y, 1\nZ, Y, 1 EOF',
45
- ]),
46
- pre_processors=[GraphPreProcessor()],
47
- post_processors=[StripPostProcessor()],
48
- stop=['EOF'], **kwargs)
48
+ @core.few_shot(
49
+ prompt="Extract relationships between entities:\n",
50
+ examples=Prompt(
51
+ [
52
+ "$> John has a dog. =>John, dog, 1 EOF",
53
+ "$> Karl has two sons. =>Karl, sons, 2 EOF",
54
+ "$> Similarly, the term general linguistics is used to distinguish core linguistics from other types of study =>general linguistics, core linguistics, 1 EOF",
55
+ "$> X has Y and Z has Y =>X, Y, 1\nZ, Y, 1 EOF",
56
+ ]
57
+ ),
58
+ pre_processors=[GraphPreProcessor()],
59
+ post_processors=[StripPostProcessor()],
60
+ stop=["EOF"],
61
+ **kwargs,
62
+ )
49
63
  def _func(_, text) -> str:
50
64
  pass
51
65
 
52
66
  if len(str(s)) > 0:
53
- if self.verbose: print(s)
67
+ if self.verbose:
68
+ UserMessage(str(s))
54
69
  r = _func(self, s)
55
70
  rec = str(r)
56
- lines = rec.split('\n')
57
- for l in lines:
58
- l = l.strip()
59
- if len(l) > 0:
60
- csv = l.split(',')
71
+ lines = rec.split("\n")
72
+ for line in lines:
73
+ stripped_line = line.strip()
74
+ if len(stripped_line) > 0:
75
+ csv = stripped_line.split(",")
61
76
  try:
62
- if len(csv) == 3 and \
63
- csv[0].strip() != '' and \
64
- csv[1].strip() != '' and \
65
- int(csv[2].strip()) > 0:
66
- res += l + '\n'
77
+ if (
78
+ len(csv) == 3
79
+ and csv[0].strip() != ""
80
+ and csv[1].strip() != ""
81
+ and int(csv[2].strip()) > 0
82
+ ):
83
+ res += stripped_line + "\n"
67
84
  except Exception as e:
68
- if self.verbose: print(e)
85
+ if self.verbose:
86
+ UserMessage(str(e))
69
87
  pass
70
88
  return res
71
89
 
72
- def forward(self, sym: Symbol, **kwargs) -> Symbol:
73
- res = 'source,target,value\n'
90
+ def forward(self, sym: Symbol, **_kwargs) -> Symbol:
91
+ res = "source,target,value\n"
74
92
  sym_list = self.formatter(sym).value
75
93
  if self.n_workers == 1:
76
94
  for s in sym_list:
@@ -83,3 +101,4 @@ class Graph(Expression):
83
101
  return res
84
102
 
85
103
 
104
+ _DEFAULT_SENTENCE_FORMATTER = SentenceFormatter()
@@ -61,13 +61,15 @@ class HtmlStyleTemplate(Expression):
61
61
  super().__init__(**kwargs)
62
62
  self.html_template_seq = Template()
63
63
  self.html_template_seq.template_ = HEADER_STYLE_DESCRIPTION
64
- self.html_stream = Stream(
65
- self.html_template_seq
64
+ self.html_stream = Stream(self.html_template_seq)
65
+ self.style_template = Style(
66
+ description=HTML_STREAM_STYLE_DESCRIPTION,
67
+ libraries=[
68
+ "https://cdn.jsdelivr.net/npm/bootstrap@5.2.3/dist/css/bootstrap.min.css",
69
+ "https://cdn.jsdelivr.net/npm/bootstrap@5.2.3/dist/js/bootstrap.bundle.min.js",
70
+ "https://ajax.googleapis.com/ajax/libs/jquery/3.6.1/jquery.min.js",
71
+ ],
66
72
  )
67
- self.style_template = Style(description=HTML_STREAM_STYLE_DESCRIPTION,
68
- libraries=['https://cdn.jsdelivr.net/npm/bootstrap@5.2.3/dist/css/bootstrap.min.css',
69
- 'https://cdn.jsdelivr.net/npm/bootstrap@5.2.3/dist/js/bootstrap.bundle.min.js',
70
- 'https://ajax.googleapis.com/ajax/libs/jquery/3.6.1/jquery.min.js'])
71
73
 
72
74
  def forward(self, sym: Symbol, **kwargs) -> Symbol:
73
75
  """The `render` method takes a `Symbol` as an argument and returns a `Symbol` containing the rendered news.
@@ -76,13 +78,15 @@ class HtmlStyleTemplate(Expression):
76
78
  These strings are combined into a single `Symbol` object which is then clustered.
77
79
  Finally, the `render` method applies the `html_template` to the clustered `Symbol` and returns the result.
78
80
  """
79
- if type(sym) != Symbol:
81
+ if not isinstance(sym, Symbol):
80
82
  sym = Symbol(sym)
81
83
  html_data = list(self.html_stream(sym, **kwargs))
82
- style_data = [str(self.style_template(html,
83
- template=HTML_TEMPLATE_STYLE,
84
- placeholder='{{placeholder}}',
85
- **kwargs)) for html in html_data]
86
- res = '\n'.join(style_data)
87
- res = Symbol(res)
88
- return res
84
+ style_data = [
85
+ str(
86
+ self.style_template(
87
+ html, template=HTML_TEMPLATE_STYLE, placeholder="{{placeholder}}", **kwargs
88
+ )
89
+ )
90
+ for html in html_data
91
+ ]
92
+ return Symbol("\n".join(style_data))
@@ -1,5 +1,3 @@
1
- from typing import List
2
-
3
1
  from ... import core
4
2
  from ...symbol import Expression
5
3
 
@@ -9,8 +7,9 @@ class blip_2(Expression):
9
7
  super().__init__(*args, **kwargs)
10
8
  self.name = self.__class__.__name__
11
9
 
12
- def __call__(self, image: str = None, query: str = None, **kwargs) -> "blip_2":
10
+ def __call__(self, image: str | None = None, query: str | None = None, **kwargs) -> "blip_2":
13
11
  @core.caption(image=image, prompt=query, **kwargs)
14
12
  def _func(_) -> str:
15
13
  pass
14
+
16
15
  return self.sym_return_type(_func(self))
@@ -1,5 +1,3 @@
1
- from typing import List, Union
2
-
3
1
  import numpy as np
4
2
 
5
3
  from ... import core
@@ -11,8 +9,11 @@ class clip(Expression):
11
9
  super().__init__(*args, **kwargs)
12
10
  self.name = self.__class__.__name__
13
11
 
14
- def __call__(self, image: str | bytes = None, text: List[str] = None, **kwargs) -> "clip":
12
+ def __call__(
13
+ self, image: str | bytes | None = None, text: list[str] | None = None, **kwargs
14
+ ) -> "clip":
15
15
  @core.text_vision(image=image, text=text, **kwargs)
16
16
  def _func(_) -> np.ndarray:
17
17
  pass
18
+
18
19
  return self.sym_return_type(_func(self))
@@ -1,5 +1,6 @@
1
1
  from ... import core
2
2
  from ...symbol import Expression
3
+ from ...utils import UserMessage
3
4
 
4
5
 
5
6
  class console(Expression):
@@ -8,8 +9,15 @@ class console(Expression):
8
9
  self.name = self.__class__.__name__
9
10
 
10
11
  def __call__(self, *args, **kwargs) -> "console":
11
- kwargs['handler'] = lambda x: print(*x['args'])
12
+ def _handler(payload):
13
+ args_ = payload.get("args", ())
14
+ message = " ".join(str(arg) for arg in args_)
15
+ UserMessage(message)
16
+
17
+ kwargs["handler"] = _handler
18
+
12
19
  @core.output(**kwargs)
13
20
  def _func(_, *args):
14
21
  pass
22
+
15
23
  return self.sym_return_type(_func(self, *args))
@@ -1,6 +1,6 @@
1
1
  from ... import core
2
- from ...symbol import Expression, Symbol
3
2
  from ...backend.engines.drawing.engine_gpt_image import GPTImageResult
3
+ from ...symbol import Expression, Symbol
4
4
 
5
5
 
6
6
  class dall_e(Expression):
@@ -8,9 +8,11 @@ class dall_e(Expression):
8
8
  super().__init__(*args, **kwargs)
9
9
  self.name = self.__class__.__name__
10
10
 
11
- def __call__(self, sym: Symbol, operation: str = 'create', **kwargs) -> GPTImageResult:
11
+ def __call__(self, sym: Symbol, operation: str = "create", **kwargs) -> GPTImageResult:
12
12
  sym = self._to_symbol(sym)
13
+
13
14
  @core.draw(operation=operation, **kwargs)
14
15
  def _func(_) -> GPTImageResult:
15
16
  pass
17
+
16
18
  return _func(sym)
@@ -9,7 +9,9 @@ class file(Expression):
9
9
 
10
10
  def __call__(self, path: Symbol, **kwargs) -> "file":
11
11
  path = self._to_symbol(path)
12
+
12
13
  @core.opening(path=path.value, **kwargs)
13
14
  def _func(_) -> str:
14
15
  pass
16
+
15
17
  return self.sym_return_type(_func(self))
@@ -1,6 +1,6 @@
1
1
  from ... import core
2
- from ...symbol import Expression, Symbol
3
2
  from ...backend.engines.drawing.engine_bfl import FluxResult
3
+ from ...symbol import Expression
4
4
 
5
5
 
6
6
  class flux(Expression):
@@ -8,9 +8,11 @@ class flux(Expression):
8
8
  super().__init__(*args, **kwargs)
9
9
  self.name = self.__class__.__name__
10
10
 
11
- def __call__(self, prompt: str, operation: str = 'create', **kwargs) -> FluxResult:
11
+ def __call__(self, prompt: str, operation: str = "create", **kwargs) -> FluxResult:
12
12
  prompt = self._to_symbol(prompt)
13
+
13
14
  @core.draw(operation=operation, **kwargs)
14
15
  def _func(_) -> FluxResult:
15
16
  pass
17
+
16
18
  return _func(prompt)
@@ -1,6 +1,6 @@
1
1
  from ... import core
2
2
  from ...backend.engines.drawing.engine_gpt_image import GPTImageResult
3
- from ...symbol import Expression, Symbol
3
+ from ...symbol import Expression
4
4
 
5
5
 
6
6
  class gpt_image(Expression):
@@ -8,9 +8,18 @@ class gpt_image(Expression):
8
8
  super().__init__(*args, **kwargs)
9
9
  self.name = self.__class__.__name__
10
10
 
11
- def __call__(self, prompt: str | None = None, operation: str = 'create', engine: str | None = None, model: str | None = None, **kwargs) -> GPTImageResult:
12
- prompt = self._to_symbol(prompt)
13
- @core.draw(engine=engine or "drawing", operation=operation, model=model, **kwargs)
14
- def _func(_) -> GPTImageResult:
15
- pass
16
- return _func(prompt)
11
+ def __call__(
12
+ self,
13
+ prompt: str | None = None,
14
+ operation: str = "create",
15
+ engine: str | None = None,
16
+ model: str | None = None,
17
+ **kwargs,
18
+ ) -> GPTImageResult:
19
+ prompt = self._to_symbol(prompt)
20
+
21
+ @core.draw(engine=engine or "drawing", operation=operation, model=model, **kwargs)
22
+ def _func(_) -> GPTImageResult:
23
+ pass
24
+
25
+ return _func(prompt)
@@ -2,7 +2,7 @@ from ... import core
2
2
  from ...symbol import Expression
3
3
 
4
4
 
5
- class input(Expression):
5
+ class input(Expression): # noqa
6
6
  def __init__(self, *args, **kwargs):
7
7
  super().__init__(*args, **kwargs)
8
8
  self.name = self.__class__.__name__
@@ -11,4 +11,5 @@ class input(Expression):
11
11
  @core.userinput(**kwargs)
12
12
  def _func(_, message) -> str:
13
13
  pass
14
+
14
15
  return self.sym_return_type(_func(self, message))
@@ -1,5 +1,3 @@
1
- from typing import List
2
-
3
1
  from ... import core
4
2
  from ...symbol import Expression
5
3
 
@@ -13,4 +11,5 @@ class llava(Expression):
13
11
  @core.caption(image=image, prompt=query, **kwargs)
14
12
  def _func(_) -> str:
15
13
  pass
14
+
16
15
  return self.sym_return_type(_func(self))
@@ -1,17 +1,18 @@
1
1
  from ... import core
2
- from ...backend.engines.webscraping.engine_requests import RequestsResult
2
+ from ...backend.engines.scrape.engine_requests import RequestsResult
3
3
  from ...symbol import Expression
4
4
 
5
5
 
6
- class naive_webscraping(Expression):
6
+ class naive_scrape(Expression):
7
7
  def __init__(self, *args, **kwargs):
8
8
  super().__init__(*args, **kwargs)
9
9
  self.name = self.__class__.__name__
10
10
 
11
11
  def __call__(self, url: str, **kwargs) -> RequestsResult:
12
12
  @core.scrape(url=url, **kwargs)
13
- def _func(_, *args, **inner_kwargs) -> RequestsResult:
13
+ def _func(_, *_args, **_inner_kwargs) -> RequestsResult:
14
14
  # The fallback path may inject debugging kwargs like `error`/`stack_trace`;
15
15
  # accept and ignore them so EngineRepository can surface structured failures.
16
16
  return None
17
+
17
18
  return _func(self)
@@ -1,12 +1,10 @@
1
- from ... import core
2
- from ...backend.engines.index.engine_vectordb import (VectorDBIndexEngine,
3
- VectorDBResult)
1
+ from ...backend.engines.index.engine_vectordb import VectorDBIndexEngine, VectorDBResult
4
2
  from ...symbol import Expression
5
- from ...utils import CustomUserWarning
3
+ from ...utils import UserMessage
6
4
 
7
5
 
8
6
  class naive_vectordb(Expression):
9
- def __init__(self, index_name = VectorDBIndexEngine._default_index_name, *args, **kwargs):
7
+ def __init__(self, index_name=VectorDBIndexEngine._default_index_name, *args, **kwargs):
10
8
  super().__init__(*args, **kwargs)
11
9
  self.index_name = index_name
12
10
  self.name = self.__class__.__name__
@@ -17,7 +15,7 @@ class naive_vectordb(Expression):
17
15
  operation: str = "search",
18
16
  index_name: str | None = None,
19
17
  storage_file: str | None = None,
20
- **kwargs
18
+ **kwargs,
21
19
  ) -> VectorDBResult:
22
20
  index = self.index_name if index_name is None else index_name
23
21
  if operation == "search":
@@ -26,10 +24,11 @@ class naive_vectordb(Expression):
26
24
  if isinstance(query, list):
27
25
  for q in query:
28
26
  self.add(doc=[q], index_name=index, **kwargs)
29
- return
27
+ return None
30
28
  self.add(doc=[query], index_name=index, **kwargs)
31
- return
29
+ return None
32
30
  if operation == "config":
33
31
  self.config(path=query, index_name=index, storage_file=storage_file, **kwargs)
34
- return
35
- CustomUserWarning(f"Operation not supported: {operation}", raise_with=NotImplementedError)
32
+ return None
33
+ UserMessage(f"Operation not supported: {operation}", raise_with=NotImplementedError)
34
+ return None