jaclang 0.7.7__py3-none-any.whl → 0.7.9__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.
Potentially problematic release.
This version of jaclang might be problematic. Click here for more details.
- jaclang/compiler/__init__.py +11 -12
- jaclang/compiler/absyntree.py +1 -1
- jaclang/compiler/passes/main/type_check_pass.py +19 -1
- jaclang/compiler/passes/tool/tests/test_unparse_validate.py +1 -1
- jaclang/compiler/passes/utils/mypy_ast_build.py +1 -8
- jaclang/langserve/engine.py +17 -8
- jaclang/langserve/server.py +12 -17
- jaclang/plugin/default.py +3 -69
- jaclang/py.typed +0 -0
- jaclang/tests/test_language.py +0 -100
- {jaclang-0.7.7.dist-info → jaclang-0.7.9.dist-info}/METADATA +1 -1
- {jaclang-0.7.7.dist-info → jaclang-0.7.9.dist-info}/RECORD +14 -20
- jaclang/core/aott.py +0 -314
- jaclang/tests/fixtures/math_question.jpg +0 -0
- jaclang/tests/fixtures/with_llm_function.jac +0 -33
- jaclang/tests/fixtures/with_llm_lower.jac +0 -45
- jaclang/tests/fixtures/with_llm_method.jac +0 -51
- jaclang/tests/fixtures/with_llm_type.jac +0 -52
- jaclang/tests/fixtures/with_llm_vision.jac +0 -25
- {jaclang-0.7.7.dist-info → jaclang-0.7.9.dist-info}/WHEEL +0 -0
- {jaclang-0.7.7.dist-info → jaclang-0.7.9.dist-info}/entry_points.txt +0 -0
jaclang/compiler/__init__.py
CHANGED
|
@@ -6,12 +6,12 @@ import os
|
|
|
6
6
|
import shutil
|
|
7
7
|
import sys
|
|
8
8
|
|
|
9
|
+
from jaclang.utils.helpers import auto_generate_refs
|
|
10
|
+
from jaclang.vendor.lark.tools import standalone
|
|
11
|
+
|
|
9
12
|
|
|
10
13
|
def generate_static_parser(force: bool = False) -> None:
|
|
11
14
|
"""Generate static parser."""
|
|
12
|
-
from jaclang.utils.helpers import auto_generate_refs
|
|
13
|
-
from jaclang.vendor.lark.tools import standalone
|
|
14
|
-
|
|
15
15
|
cur_dir = os.path.dirname(__file__)
|
|
16
16
|
if force or not os.path.exists(os.path.join(cur_dir, "generated", "jac_parser.py")):
|
|
17
17
|
if os.path.exists(os.path.join(cur_dir, "generated")):
|
|
@@ -27,25 +27,24 @@ def generate_static_parser(force: bool = False) -> None:
|
|
|
27
27
|
os.path.join(cur_dir, "generated", "jac_parser.py"),
|
|
28
28
|
"-c",
|
|
29
29
|
]
|
|
30
|
-
standalone.main()
|
|
30
|
+
standalone.main()
|
|
31
31
|
sys.argv = save_argv
|
|
32
32
|
try:
|
|
33
33
|
auto_generate_refs()
|
|
34
34
|
except Exception as e:
|
|
35
|
-
|
|
35
|
+
logging.error(f"Error generating reference files: {e}")
|
|
36
36
|
|
|
37
37
|
|
|
38
38
|
generate_static_parser()
|
|
39
39
|
try:
|
|
40
|
-
from jaclang.compiler.generated import jac_parser as jac_lark
|
|
41
|
-
|
|
42
|
-
jac_lark.logger.setLevel(logging.DEBUG)
|
|
43
|
-
except AttributeError:
|
|
40
|
+
from jaclang.compiler.generated import jac_parser as jac_lark
|
|
41
|
+
except ModuleNotFoundError:
|
|
44
42
|
generate_static_parser(force=True)
|
|
45
|
-
from jaclang.compiler.generated import jac_parser as jac_lark
|
|
43
|
+
from jaclang.compiler.generated import jac_parser as jac_lark
|
|
44
|
+
|
|
45
|
+
jac_lark.logger.setLevel(logging.DEBUG)
|
|
46
|
+
contextlib.suppress(ModuleNotFoundError)
|
|
46
47
|
|
|
47
|
-
jac_lark.logger.setLevel(logging.DEBUG)
|
|
48
|
-
contextlib.suppress(AttributeError)
|
|
49
48
|
TOKEN_MAP = {
|
|
50
49
|
x.name: x.pattern.value
|
|
51
50
|
for x in jac_lark.Lark_StandAlone().parser.lexer_conf.terminals
|
jaclang/compiler/absyntree.py
CHANGED
|
@@ -676,7 +676,7 @@ class Module(AstDocNode):
|
|
|
676
676
|
if self.doc:
|
|
677
677
|
new_kid.append(self.doc)
|
|
678
678
|
new_kid.extend(self.body)
|
|
679
|
-
self.set_kids(nodes=new_kid)
|
|
679
|
+
self.set_kids(nodes=new_kid if len(new_kid) else [EmptyToken()])
|
|
680
680
|
return res
|
|
681
681
|
|
|
682
682
|
def unparse(self) -> str:
|
|
@@ -8,6 +8,7 @@ import os
|
|
|
8
8
|
import pathlib
|
|
9
9
|
import sys
|
|
10
10
|
|
|
11
|
+
# import jaclang
|
|
11
12
|
import jaclang.compiler.absyntree as ast
|
|
12
13
|
import jaclang.compiler.passes.utils.mypy_ast_build as myab
|
|
13
14
|
from jaclang.compiler.constant import Constants as Con
|
|
@@ -93,12 +94,29 @@ class JacTypeCheckPass(Pass):
|
|
|
93
94
|
mypy_graph[module.name] = st
|
|
94
95
|
new_modules.append(st)
|
|
95
96
|
|
|
97
|
+
# def get_stub(mod: str) -> myab.BuildSource:
|
|
98
|
+
# """Get stub file path."""
|
|
99
|
+
# return myab.BuildSource(
|
|
100
|
+
# path=str(
|
|
101
|
+
# pathlib.Path(os.path.dirname(jaclang.__file__)).parent
|
|
102
|
+
# / "stubs"
|
|
103
|
+
# / "jaclang"
|
|
104
|
+
# / "plugin"
|
|
105
|
+
# / f"{mod}.pyi"
|
|
106
|
+
# ),
|
|
107
|
+
# module=f"jaclang.plugin.{mod}",
|
|
108
|
+
# )
|
|
109
|
+
|
|
96
110
|
graph = myab.load_graph(
|
|
97
111
|
[
|
|
98
112
|
myab.BuildSource(
|
|
99
113
|
path=str(self.__path / "typeshed" / "stdlib" / "builtins.pyi"),
|
|
100
114
|
module="builtins",
|
|
101
|
-
)
|
|
115
|
+
),
|
|
116
|
+
# get_stub("default"),
|
|
117
|
+
# get_stub("feature"),
|
|
118
|
+
# get_stub("spec"),
|
|
119
|
+
# get_stub("builtin"),
|
|
102
120
|
],
|
|
103
121
|
manager,
|
|
104
122
|
old_graph=mypy_graph,
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
import ast as ast3
|
|
4
4
|
from difflib import unified_diff
|
|
5
5
|
|
|
6
|
-
|
|
6
|
+
|
|
7
7
|
from jaclang.compiler.compile import jac_file_to_pass, jac_str_to_pass
|
|
8
8
|
from jaclang.compiler.passes.main import PyastGenPass
|
|
9
9
|
from jaclang.compiler.passes.main.schedules import py_code_gen as without_format
|
|
@@ -4,14 +4,12 @@ from __future__ import annotations
|
|
|
4
4
|
|
|
5
5
|
import ast
|
|
6
6
|
import os
|
|
7
|
-
import pathlib
|
|
8
7
|
|
|
9
|
-
import jaclang
|
|
10
8
|
from jaclang.compiler.absyntree import AstNode
|
|
11
9
|
from jaclang.compiler.passes import Pass
|
|
12
10
|
from jaclang.compiler.passes.main.fuse_typeinfo_pass import (
|
|
13
11
|
FuseTypeInfoPass,
|
|
14
|
-
)
|
|
12
|
+
)
|
|
15
13
|
|
|
16
14
|
import mypy.build as myb
|
|
17
15
|
import mypy.checkexpr as mycke
|
|
@@ -31,11 +29,6 @@ from mypy.options import Options
|
|
|
31
29
|
from mypy.semanal_main import semantic_analysis_for_scc
|
|
32
30
|
|
|
33
31
|
|
|
34
|
-
os.environ["MYPYPATH"] = str(
|
|
35
|
-
pathlib.Path(os.path.dirname(jaclang.__file__)).parent / "stubs"
|
|
36
|
-
)
|
|
37
|
-
|
|
38
|
-
|
|
39
32
|
mypy_to_jac_node_map: dict[
|
|
40
33
|
tuple[int, int | None, int | None, int | None], list[AstNode]
|
|
41
34
|
] = {}
|
jaclang/langserve/engine.py
CHANGED
|
@@ -2,7 +2,9 @@
|
|
|
2
2
|
|
|
3
3
|
from __future__ import annotations
|
|
4
4
|
|
|
5
|
+
import asyncio
|
|
5
6
|
import logging
|
|
7
|
+
from concurrent.futures import ThreadPoolExecutor
|
|
6
8
|
from enum import IntEnum
|
|
7
9
|
from typing import Optional
|
|
8
10
|
|
|
@@ -126,8 +128,9 @@ class JacLangServer(LanguageServer):
|
|
|
126
128
|
"""Initialize workspace."""
|
|
127
129
|
super().__init__("jac-lsp", "v0.1")
|
|
128
130
|
self.modules: dict[str, ModuleInfo] = {}
|
|
131
|
+
self.executor = ThreadPoolExecutor()
|
|
129
132
|
|
|
130
|
-
def push_diagnostics(self, file_path: str) -> None:
|
|
133
|
+
async def push_diagnostics(self, file_path: str) -> None:
|
|
131
134
|
"""Push diagnostics for a file."""
|
|
132
135
|
if file_path in self.modules:
|
|
133
136
|
self.publish_diagnostics(
|
|
@@ -230,17 +233,23 @@ class JacLangServer(LanguageServer):
|
|
|
230
233
|
self.update_modules(file_path, build, ALev.TYPE)
|
|
231
234
|
return len(self.modules[file_path].errors) == 0
|
|
232
235
|
|
|
233
|
-
def analyze_and_publish(self, uri: str, level: int = 2) -> None:
|
|
236
|
+
async def analyze_and_publish(self, uri: str, level: int = 2) -> None:
|
|
234
237
|
"""Analyze and publish diagnostics."""
|
|
235
238
|
self.log_py(f"Analyzing {uri}...")
|
|
236
|
-
success =
|
|
237
|
-
|
|
239
|
+
success = await asyncio.get_event_loop().run_in_executor(
|
|
240
|
+
self.executor, self.quick_check, uri
|
|
241
|
+
)
|
|
242
|
+
await self.push_diagnostics(uri)
|
|
238
243
|
if success and level > 0:
|
|
239
|
-
success =
|
|
240
|
-
|
|
244
|
+
success = await asyncio.get_event_loop().run_in_executor(
|
|
245
|
+
self.executor, self.deep_check, uri
|
|
246
|
+
)
|
|
247
|
+
await self.push_diagnostics(uri)
|
|
241
248
|
if level > 1:
|
|
242
|
-
|
|
243
|
-
|
|
249
|
+
await asyncio.get_event_loop().run_in_executor(
|
|
250
|
+
self.executor, self.type_check, uri
|
|
251
|
+
)
|
|
252
|
+
await self.push_diagnostics(uri)
|
|
244
253
|
|
|
245
254
|
def get_completion(
|
|
246
255
|
self, file_path: str, position: lspt.Position
|
jaclang/langserve/server.py
CHANGED
|
@@ -18,21 +18,24 @@ server = JacLangServer()
|
|
|
18
18
|
|
|
19
19
|
@server.feature(lspt.TEXT_DOCUMENT_DID_OPEN)
|
|
20
20
|
@server.feature(lspt.TEXT_DOCUMENT_DID_SAVE)
|
|
21
|
-
def did_open(ls: JacLangServer, params: lspt.DidOpenTextDocumentParams) -> None:
|
|
21
|
+
async def did_open(ls: JacLangServer, params: lspt.DidOpenTextDocumentParams) -> None:
|
|
22
22
|
"""Check syntax on change."""
|
|
23
|
-
ls.analyze_and_publish(params.text_document.uri)
|
|
24
|
-
# token_params = lspt.SemanticTokensParams(
|
|
25
|
-
# text_document=lspt.TextDocumentIdentifier(uri=params.text_document.uri)
|
|
26
|
-
# )
|
|
27
|
-
# tokens = semantic_tokens_full(ls, token_params)
|
|
28
|
-
# ls.send_notification("textDocument/publishSemanticTokens", tokens)
|
|
23
|
+
await ls.analyze_and_publish(params.text_document.uri)
|
|
29
24
|
|
|
30
25
|
|
|
31
26
|
@server.feature(lspt.TEXT_DOCUMENT_DID_CHANGE)
|
|
32
|
-
@debounce(0.
|
|
27
|
+
@debounce(0.3)
|
|
33
28
|
async def did_change(ls: JacLangServer, params: lspt.DidOpenTextDocumentParams) -> None:
|
|
34
29
|
"""Check syntax on change."""
|
|
35
|
-
ls.analyze_and_publish(params.text_document.uri, level=
|
|
30
|
+
await ls.analyze_and_publish(params.text_document.uri, level=1)
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
@server.feature(lspt.TEXT_DOCUMENT_FORMATTING)
|
|
34
|
+
def formatting(
|
|
35
|
+
ls: JacLangServer, params: lspt.DocumentFormattingParams
|
|
36
|
+
) -> list[lspt.TextEdit]:
|
|
37
|
+
"""Format the given document."""
|
|
38
|
+
return ls.formatted_jac(params.text_document.uri)
|
|
36
39
|
|
|
37
40
|
|
|
38
41
|
@server.feature(
|
|
@@ -86,14 +89,6 @@ def completion(ls: JacLangServer, params: lspt.CompletionParams) -> lspt.Complet
|
|
|
86
89
|
return ls.get_completion(params.text_document.uri, params.position)
|
|
87
90
|
|
|
88
91
|
|
|
89
|
-
@server.feature(lspt.TEXT_DOCUMENT_FORMATTING)
|
|
90
|
-
def formatting(
|
|
91
|
-
ls: JacLangServer, params: lspt.DocumentFormattingParams
|
|
92
|
-
) -> list[lspt.TextEdit]:
|
|
93
|
-
"""Format the given document."""
|
|
94
|
-
return ls.formatted_jac(params.text_document.uri)
|
|
95
|
-
|
|
96
|
-
|
|
97
92
|
@server.feature(lspt.TEXT_DOCUMENT_HOVER, lspt.HoverOptions(work_done_progress=True))
|
|
98
93
|
def hover(
|
|
99
94
|
ls: JacLangServer, params: lspt.TextDocumentPositionParams
|
jaclang/plugin/default.py
CHANGED
|
@@ -15,13 +15,6 @@ from typing import Any, Callable, Optional, Type, Union
|
|
|
15
15
|
from jaclang.compiler.absyntree import Module
|
|
16
16
|
from jaclang.compiler.constant import EdgeDir, colors
|
|
17
17
|
from jaclang.compiler.semtable import SemInfo, SemRegistry, SemScope
|
|
18
|
-
from jaclang.core.aott import (
|
|
19
|
-
aott_raise,
|
|
20
|
-
extract_non_primary_type,
|
|
21
|
-
get_all_type_explanations,
|
|
22
|
-
get_info_types,
|
|
23
|
-
get_input_information,
|
|
24
|
-
)
|
|
25
18
|
from jaclang.core.constructs import (
|
|
26
19
|
Architype,
|
|
27
20
|
DSFunc,
|
|
@@ -616,7 +609,7 @@ class JacFeatureDefaults:
|
|
|
616
609
|
)
|
|
617
610
|
if isinstance(attr_sem_info, SemInfo) and isinstance(attr_scope, SemScope):
|
|
618
611
|
return attr_sem_info.semstr, attr_scope.as_type_str
|
|
619
|
-
return "", ""
|
|
612
|
+
return "", ""
|
|
620
613
|
|
|
621
614
|
@staticmethod
|
|
622
615
|
@hookimpl
|
|
@@ -632,68 +625,9 @@ class JacFeatureDefaults:
|
|
|
632
625
|
action: str,
|
|
633
626
|
) -> Any: # noqa: ANN401
|
|
634
627
|
"""Jac's with_llm feature."""
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
os.path.dirname(file_loc),
|
|
638
|
-
"__jac_gen__",
|
|
639
|
-
os.path.basename(file_loc).replace(".jac", ".registry.pkl"),
|
|
640
|
-
),
|
|
641
|
-
"rb",
|
|
642
|
-
) as f:
|
|
643
|
-
mod_registry = pickle.load(f)
|
|
644
|
-
|
|
645
|
-
outputs = outputs[0] if isinstance(outputs, list) else outputs
|
|
646
|
-
_scope = SemScope.get_scope_from_str(scope)
|
|
647
|
-
assert _scope is not None
|
|
648
|
-
|
|
649
|
-
method = model_params.pop("method") if "method" in model_params else "Normal"
|
|
650
|
-
available_methods = model.MTLLM_METHOD_PROMPTS.keys()
|
|
651
|
-
assert (
|
|
652
|
-
method in available_methods
|
|
653
|
-
), f"Invalid method: {method}. Select from {available_methods}"
|
|
654
|
-
|
|
655
|
-
context = (
|
|
656
|
-
"\n".join(model_params.pop("context")) if "context" in model_params else ""
|
|
657
|
-
)
|
|
658
|
-
|
|
659
|
-
type_collector: list = []
|
|
660
|
-
incl_info = [x for x in incl_info if not isinstance(x[1], type)]
|
|
661
|
-
information, collected_types = get_info_types(_scope, mod_registry, incl_info)
|
|
662
|
-
type_collector.extend(collected_types)
|
|
663
|
-
|
|
664
|
-
inputs_information = get_input_information(inputs, type_collector)
|
|
665
|
-
|
|
666
|
-
output_information = f"{outputs[0]} ({outputs[1]})".strip()
|
|
667
|
-
type_collector.extend(extract_non_primary_type(outputs[1]))
|
|
668
|
-
output_type_explanations = "\n".join(
|
|
669
|
-
list(
|
|
670
|
-
get_all_type_explanations(
|
|
671
|
-
extract_non_primary_type(outputs[1]), mod_registry
|
|
672
|
-
).values()
|
|
673
|
-
)
|
|
674
|
-
)
|
|
675
|
-
|
|
676
|
-
type_explanations_list = list(
|
|
677
|
-
get_all_type_explanations(type_collector, mod_registry).values()
|
|
678
|
-
)
|
|
679
|
-
type_explanations = "\n".join(type_explanations_list)
|
|
680
|
-
|
|
681
|
-
meaning_out = aott_raise(
|
|
682
|
-
model=model,
|
|
683
|
-
information=information,
|
|
684
|
-
inputs_information=inputs_information,
|
|
685
|
-
output_information=output_information,
|
|
686
|
-
type_explanations=type_explanations,
|
|
687
|
-
action=action,
|
|
688
|
-
context=context,
|
|
689
|
-
method=method,
|
|
690
|
-
tools=[],
|
|
691
|
-
model_params=model_params,
|
|
692
|
-
)
|
|
693
|
-
output = model.resolve_output(
|
|
694
|
-
meaning_out, outputs[0], outputs[1], output_type_explanations
|
|
628
|
+
raise ImportError(
|
|
629
|
+
"mtllm is not installed. Please install it with `pip install mtllm`."
|
|
695
630
|
)
|
|
696
|
-
return output
|
|
697
631
|
|
|
698
632
|
|
|
699
633
|
class JacBuiltin:
|
jaclang/py.typed
ADDED
|
File without changes
|
jaclang/tests/test_language.py
CHANGED
|
@@ -112,106 +112,6 @@ class JacLanguageTests(TestCase):
|
|
|
112
112
|
"{'a': 'apple', 'b': 'ball', 'c': 'cat', 'd': 'dog', 'e': 'elephant'}\n",
|
|
113
113
|
)
|
|
114
114
|
|
|
115
|
-
# TODO: Move these tests to mtllm repo
|
|
116
|
-
# def test_with_llm_function(self) -> None:
|
|
117
|
-
# """Parse micro jac file."""
|
|
118
|
-
# captured_output = io.StringIO()
|
|
119
|
-
# sys.stdout = captured_output
|
|
120
|
-
# jac_import("with_llm_function", base_path=self.fixture_abs_path("./"))
|
|
121
|
-
# sys.stdout = sys.__stdout__
|
|
122
|
-
# stdout_value = captured_output.getvalue()
|
|
123
|
-
# self.assertIn("{'temperature': 0.7}", stdout_value)
|
|
124
|
-
# self.assertIn("Emoji Representation (str)", stdout_value)
|
|
125
|
-
# self.assertIn('Text Input (input) (str) = "Lets move to paris"', stdout_value)
|
|
126
|
-
# self.assertIn(
|
|
127
|
-
# ' = [{"input": "I love tp drink pina coladas"',
|
|
128
|
-
# stdout_value,
|
|
129
|
-
# )
|
|
130
|
-
|
|
131
|
-
# def test_with_llm_method(self) -> None:
|
|
132
|
-
# """Parse micro jac file."""
|
|
133
|
-
# captured_output = io.StringIO()
|
|
134
|
-
# sys.stdout = captured_output
|
|
135
|
-
# jac_import("with_llm_method", base_path=self.fixture_abs_path("./"))
|
|
136
|
-
# sys.stdout = sys.__stdout__
|
|
137
|
-
# stdout_value = captured_output.getvalue()
|
|
138
|
-
# self.assertIn("[Reasoning] <Reason>", stdout_value)
|
|
139
|
-
# self.assertIn("(Enum) eg:- Personality.EXTROVERT ->", stdout_value)
|
|
140
|
-
# self.assertIn(
|
|
141
|
-
# "Personality Index of a Person (PersonalityIndex) (class) eg:- "
|
|
142
|
-
# "PersonalityIndex(index=int) -> Personality Index (index) (int)",
|
|
143
|
-
# stdout_value,
|
|
144
|
-
# )
|
|
145
|
-
# self.assertIn(
|
|
146
|
-
# "Personality of the Person (dict[Personality,PersonalityIndex])",
|
|
147
|
-
# stdout_value,
|
|
148
|
-
# )
|
|
149
|
-
# self.assertIn(
|
|
150
|
-
# 'Diary Entries (diary_entries) (list[str]) = ["I won noble prize in '
|
|
151
|
-
# 'Physics", "I am popular for my theory of relativity"]',
|
|
152
|
-
# stdout_value,
|
|
153
|
-
# )
|
|
154
|
-
|
|
155
|
-
# def test_with_llm_lower(self) -> None:
|
|
156
|
-
# """Parse micro jac file."""
|
|
157
|
-
# captured_output = io.StringIO()
|
|
158
|
-
# sys.stdout = captured_output
|
|
159
|
-
# jac_import("with_llm_lower", base_path=self.fixture_abs_path("./"))
|
|
160
|
-
# sys.stdout = sys.__stdout__
|
|
161
|
-
# stdout_value = captured_output.getvalue()
|
|
162
|
-
# self.assertIn("[Reasoning] <Reason>", stdout_value)
|
|
163
|
-
# self.assertIn(
|
|
164
|
-
# 'Name of the Person (name) (str) = "Oppenheimer"',
|
|
165
|
-
# stdout_value,
|
|
166
|
-
# )
|
|
167
|
-
# self.assertIn(
|
|
168
|
-
# "Person (Person) (obj) eg:- Person(full_name=str, yod=int, personality"
|
|
169
|
-
# "=Personality) -> Fullname of the Person (full_name) (str), Year of Death"
|
|
170
|
-
# " (yod) (int), Personality of the Person (personality) (Personality)",
|
|
171
|
-
# stdout_value,
|
|
172
|
-
# )
|
|
173
|
-
# self.assertIn(
|
|
174
|
-
# "J. Robert Oppenheimer was a Introvert person who died in 1967",
|
|
175
|
-
# stdout_value,
|
|
176
|
-
# )
|
|
177
|
-
|
|
178
|
-
# def test_with_llm_type(self) -> None:
|
|
179
|
-
# """Parse micro jac file."""
|
|
180
|
-
# captured_output = io.StringIO()
|
|
181
|
-
# sys.stdout = captured_output
|
|
182
|
-
# jac_import("with_llm_type", base_path=self.fixture_abs_path("./"))
|
|
183
|
-
# sys.stdout = sys.__stdout__
|
|
184
|
-
# stdout_value = captured_output.getvalue()
|
|
185
|
-
# self.assertIn("14/03/1879", stdout_value)
|
|
186
|
-
# self.assertNotIn(
|
|
187
|
-
# 'University (University) (obj) = type(__module__="with_llm_type", __doc__=None, '
|
|
188
|
-
# "_jac_entry_funcs_`=[`], _jac_exit_funcs_=[], __init__=function(__wrapped__=function()))",
|
|
189
|
-
# stdout_value,
|
|
190
|
-
# )
|
|
191
|
-
# desired_output_count = stdout_value.count(
|
|
192
|
-
# "Person(name='Jason Mars', dob='1994-01-01', age=30)"
|
|
193
|
-
# )
|
|
194
|
-
# self.assertEqual(desired_output_count, 2)
|
|
195
|
-
|
|
196
|
-
# def test_with_llm_vision(self) -> None:
|
|
197
|
-
# """Test MTLLLM Vision Implementation."""
|
|
198
|
-
# try:
|
|
199
|
-
# captured_output = io.StringIO()
|
|
200
|
-
# sys.stdout = captured_output
|
|
201
|
-
# jac_import("with_llm_vision", base_path=self.fixture_abs_path("./"))
|
|
202
|
-
# sys.stdout = sys.__stdout__
|
|
203
|
-
# stdout_value = captured_output.getvalue()
|
|
204
|
-
# self.assertIn(
|
|
205
|
-
# "{'type': 'text', 'text': '\\n[System Prompt]\\n", stdout_value[:500]
|
|
206
|
-
# )
|
|
207
|
-
# self.assertNotIn(
|
|
208
|
-
# " {'type': 'text', 'text': 'Image of the Question (question_img) (Image) = '}, "
|
|
209
|
-
# "{'type': 'image_url', 'image_url': {'url': 'data:image/jpeg;base64,/9j/4AAQSkZJRgABAQAAAQAB",
|
|
210
|
-
# stdout_value[:500],
|
|
211
|
-
# )
|
|
212
|
-
# except Exception:
|
|
213
|
-
# self.skipTest("This test requires Pillow to be installed.")
|
|
214
|
-
|
|
215
115
|
def test_ignore(self) -> None:
|
|
216
116
|
"""Parse micro jac file."""
|
|
217
117
|
Jac.get_root()._jac_.edges.clear()
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: jaclang
|
|
3
|
-
Version: 0.7.
|
|
3
|
+
Version: 0.7.9
|
|
4
4
|
Summary: Jac is a unique and powerful programming language that runs on top of Python, offering an unprecedented level of intelligence and intuitive understanding.
|
|
5
5
|
Home-page: https://jaseci.org
|
|
6
6
|
License: MIT
|
|
@@ -5,8 +5,8 @@ jaclang/cli/cli.md,sha256=4BPJGdcyvs_rXgd_DPEGjkKSGe5ureXXYaQsf-_z_LU,5939
|
|
|
5
5
|
jaclang/cli/cli.py,sha256=8CbN_oqMhZ71AJhgA9J0Q551GMO3ey273dgaFPckLyI,13582
|
|
6
6
|
jaclang/cli/cmdreg.py,sha256=u0jAd6A8czt7tBgPBBKBhYAG4By1FrjEGaTU2XFKeYs,8372
|
|
7
7
|
jaclang/compiler/.gitignore,sha256=n1k2_xXTorp9PY8hhYM4psHircn-NMaFx95bSgDKopo,10
|
|
8
|
-
jaclang/compiler/__init__.py,sha256=
|
|
9
|
-
jaclang/compiler/absyntree.py,sha256=
|
|
8
|
+
jaclang/compiler/__init__.py,sha256=P8h-q53h-MTK8Wmvpb7sP5R6Ojz94Y2F9nqMwIUt0d4,3064
|
|
9
|
+
jaclang/compiler/absyntree.py,sha256=Xwkd3sxRmjWobNZEO-UNDmDfSC0wA0ihN-FSRXrZ-1Q,134545
|
|
10
10
|
jaclang/compiler/codeloc.py,sha256=YhJcHjhMCOT6mV1qLehwriuFgW0H2-ntq68k_r8yBs4,2800
|
|
11
11
|
jaclang/compiler/compile.py,sha256=0d8p4i2LXg2RCu1XfWx_Jq_dx7pK2Zn2VIj-apvX_nI,3389
|
|
12
12
|
jaclang/compiler/constant.py,sha256=n4KaEkvnb9-KVJJVvxiWimhjbrOiknBvLHAVDBFbF7Y,8991
|
|
@@ -62,7 +62,7 @@ jaclang/compiler/passes/main/tests/test_sub_node_pass.py,sha256=I8m2SM2Z-OJkRG3C
|
|
|
62
62
|
jaclang/compiler/passes/main/tests/test_sym_tab_build_pass.py,sha256=85mUM6mYYLCrQ9AivBIbreG7CgdsJH2zrNOqdcpnwBo,730
|
|
63
63
|
jaclang/compiler/passes/main/tests/test_type_check_pass.py,sha256=v2_KmcyX1_fOpReRKM0mUnlFXKVPRvFCMR3Mw9ftytI,2265
|
|
64
64
|
jaclang/compiler/passes/main/tests/test_typeinfo_pass.py,sha256=ehC0_giLg7NwB7fR10nW5Te8mZ76qmUFxkK1bEjtmrw,129
|
|
65
|
-
jaclang/compiler/passes/main/type_check_pass.py,sha256=
|
|
65
|
+
jaclang/compiler/passes/main/type_check_pass.py,sha256=TyVC3jmuxMvG8Fo4TbceMnRSgZxX98m65cfMh10C5O8,4073
|
|
66
66
|
jaclang/compiler/passes/tool/__init__.py,sha256=xekCOXysHIcthWm8NRmQoA1Ah1XV8vFbkfeHphJtUdc,223
|
|
67
67
|
jaclang/compiler/passes/tool/fuse_comments_pass.py,sha256=N9a84qArNuTXX1iaXsBzqcufx6A3zYq2p-1ieH6FmHc,3133
|
|
68
68
|
jaclang/compiler/passes/tool/jac_formatter_pass.py,sha256=yqq2OOSs2tlDKUnPe0GS3NAZh8F5fquA5ZTYw44QX08,87356
|
|
@@ -100,10 +100,10 @@ jaclang/compiler/passes/tool/tests/fixtures/simple_walk.jac,sha256=6jwYKXxJ1B4Vf
|
|
|
100
100
|
jaclang/compiler/passes/tool/tests/fixtures/simple_walk_fmt.jac,sha256=6jwYKXxJ1B4VfYDFlQhStN3_QX7dDXzC2gI6U9-KhZM,806
|
|
101
101
|
jaclang/compiler/passes/tool/tests/test_fuse_comments_pass.py,sha256=ZeWHsm7VIyyS8KKpoB2SdlHM4jF22fMfSrfTfxt2MQw,398
|
|
102
102
|
jaclang/compiler/passes/tool/tests/test_jac_format_pass.py,sha256=AKGBEz02bS9REJuryZlPvY2avE_XWqKV8sRrnh5hu2g,6101
|
|
103
|
-
jaclang/compiler/passes/tool/tests/test_unparse_validate.py,sha256=
|
|
103
|
+
jaclang/compiler/passes/tool/tests/test_unparse_validate.py,sha256=HtaIGwLoY2yz1T3nkI9SFjMEnY_st7cnUcz6hmguR6I,2728
|
|
104
104
|
jaclang/compiler/passes/transform.py,sha256=GEHK3zFWrEjbAQ3mIl3D59jBuIrA8DRbw9t_IlUqg3M,2297
|
|
105
105
|
jaclang/compiler/passes/utils/__init__.py,sha256=UsI5rUopTUiStAzup4kbPwIwrnC5ofCrqWBCBbM2-k4,35
|
|
106
|
-
jaclang/compiler/passes/utils/mypy_ast_build.py,sha256=
|
|
106
|
+
jaclang/compiler/passes/utils/mypy_ast_build.py,sha256=aPvvdGSwbOGHYiK5kY665bqtfjj7s2YfTONV4EuLai8,26162
|
|
107
107
|
jaclang/compiler/semtable.py,sha256=tW0vY1N377w_WgKalqXe2VR8FJDwd9CpI6jDJi1jhEU,4152
|
|
108
108
|
jaclang/compiler/symtable.py,sha256=oYdYS1PUnNCGPPZsZZOduiDtTYyLVd6tXWAoUyCupUc,9275
|
|
109
109
|
jaclang/compiler/tests/__init__.py,sha256=qiXa5UNRBanGOcplFKTT9a_9GEyiv7goq1OzuCjDCFE,27
|
|
@@ -118,7 +118,6 @@ jaclang/compiler/tests/fixtures/stuff.jac,sha256=qOq6WOwhlprMmJpiqQudgqnr4qTd9uh
|
|
|
118
118
|
jaclang/compiler/tests/test_importer.py,sha256=JNmte5FsHhnng9jzw7N5BenflAFCasuhezN1sytDVyg,1739
|
|
119
119
|
jaclang/compiler/tests/test_parser.py,sha256=Sj9Kz1FghESaPpyx_kEvScs4xvz-vgEdH8yyQJ0iB7M,4820
|
|
120
120
|
jaclang/core/__init__.py,sha256=jDDYBCV82qPhmcDVk3NIvHbhng0ebSrXD3xrojg0-eo,34
|
|
121
|
-
jaclang/core/aott.py,sha256=W-hvfwDxwu1S3jFTWADWNob0-JnYbywdbUklkXIAOUA,11367
|
|
122
121
|
jaclang/core/architype.py,sha256=qBH0W-ALxmK6DALc4_S7gx-3R7C_6o-PGKb3f4RbWbE,16781
|
|
123
122
|
jaclang/core/constructs.py,sha256=ogWc95DEZxQWoxqsfbRrcmt9ldGDqW7zQVu3DWuIAKs,848
|
|
124
123
|
jaclang/core/context.py,sha256=AxGsra9EqokVdOhwIxR9RuAcnm0HmobUnMBezUBY1_s,4774
|
|
@@ -127,8 +126,8 @@ jaclang/core/memory.py,sha256=7QukfL6wDBXrdpRn01yu4RMNkmIMNqFiKrI0zfpGSy4,2947
|
|
|
127
126
|
jaclang/core/test.py,sha256=HRCl3cf0uPTe58Kcx_sBUb6ow8J53rnmpFOhA7g9oAA,2851
|
|
128
127
|
jaclang/core/utils.py,sha256=uzEsRSuNSMMo7dlvCozGv0TnpUmHEjGNzUTZt1Df2gQ,7741
|
|
129
128
|
jaclang/langserve/__init__.py,sha256=3qbnivBBcLZCfmDYRMIeKkG08Lx7XQsJJg-qG8TU8yc,51
|
|
130
|
-
jaclang/langserve/engine.py,sha256=
|
|
131
|
-
jaclang/langserve/server.py,sha256=
|
|
129
|
+
jaclang/langserve/engine.py,sha256=ntvJB2silUagQZFLOahyXqh0Ef7E3uiMsE14PzunFOU,16708
|
|
130
|
+
jaclang/langserve/server.py,sha256=4WrJXEVYWEcTjXlNoRx0patf34tjPXENKg35ofSYhtI,4121
|
|
132
131
|
jaclang/langserve/tests/__init__.py,sha256=iDM47k6c3vahaWhwxpbkdEOshbmX-Zl5x669VONjS2I,23
|
|
133
132
|
jaclang/langserve/tests/defaults.py,sha256=8UWHuCHY-WatPcWFhyX9-4KLuJgODTlLNj0wNnKomIM,7608
|
|
134
133
|
jaclang/langserve/tests/fixtures/base_module_structure.jac,sha256=gtU3Uq0gsJy6G8Dg4IWiL-YSk_LVFAYK4mVEPt5rGpE,515
|
|
@@ -152,7 +151,7 @@ jaclang/langserve/tests/test_server.py,sha256=Bmllojot7c40rq0mDMOAiOyowY0-ECh_qA
|
|
|
152
151
|
jaclang/langserve/utils.py,sha256=JS_XxDAtqTO4r0wSQjxgGqHwx9xTN_JZpNI1YP-kgbY,9868
|
|
153
152
|
jaclang/plugin/__init__.py,sha256=5t2krHKt_44PrCTGojzxEimxpNHYVQcn89jAiCSXE_k,165
|
|
154
153
|
jaclang/plugin/builtin.py,sha256=MEMPUnj_rlwcCNmUkfH5S8iazMnQ6fpp6tls4fh5z7k,1188
|
|
155
|
-
jaclang/plugin/default.py,sha256=
|
|
154
|
+
jaclang/plugin/default.py,sha256=PBRhDnMChwLbV-Mzuy5Uss1ziRZ3UNCnGfOb1D6fOP4,23533
|
|
156
155
|
jaclang/plugin/feature.py,sha256=fhyQRNYOkcXlYn1ObFPqdOHPhtC_lGQfgd7RD2ooLUY,9792
|
|
157
156
|
jaclang/plugin/spec.py,sha256=CMu6rzi94eIZaqsFz3NIbN3upJgGneb4FE_7Rly7slE,8893
|
|
158
157
|
jaclang/plugin/tests/__init__.py,sha256=rn_tNG8jCHWwBc_rx4yFkGc4N1GISb7aPuTFVRTvrTk,38
|
|
@@ -162,6 +161,7 @@ jaclang/plugin/tests/fixtures/simple_node_connection.jac,sha256=KdbpACWtnj92TqQq
|
|
|
162
161
|
jaclang/plugin/tests/fixtures/simple_persistent.jac,sha256=o0TZTOJEZjFW8A2IGY8ICBZEBZzHhqha0xQFFBK_DSI,624
|
|
163
162
|
jaclang/plugin/tests/test_features.py,sha256=p0N5inZn92Cj0eqslmDR0-q6pVG8hkcQfA6CuQcfP3Y,2352
|
|
164
163
|
jaclang/plugin/tests/test_jaseci.py,sha256=XcVL-FOZMTsjJEZqCa-rcYyEPl1dxdFFu9vhvm8kUaI,7956
|
|
164
|
+
jaclang/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
165
165
|
jaclang/settings.py,sha256=7rKy_kQkWjciwBoWHoJVYrK0nxLwaG54FFvFLOGGggk,3375
|
|
166
166
|
jaclang/tests/fixtures/abc.jac,sha256=AWzRxTBjvQwoLSOakjn0kKXWqKvDaUYGc1zmBk1Nd5c,1770
|
|
167
167
|
jaclang/tests/fixtures/access_checker.jac,sha256=6Inm14cZsyMfezFRs2zfnQEZSE_JRxVvytcZbox7BNw,375
|
|
@@ -213,7 +213,6 @@ jaclang/tests/fixtures/inherit_check.jac,sha256=FQlbCavN4ryt3mmD6ei1MIt1jMgZ8_Nc
|
|
|
213
213
|
jaclang/tests/fixtures/jacsamp.jac,sha256=VUHUn-RvHzTA4v0KNIFuciocqAHsgQp9tfsEvh5WHlE,96
|
|
214
214
|
jaclang/tests/fixtures/jp_importer.jac,sha256=Mfn62rwYk8CANIkCoMf5UFt4SKl042jaU0CHnj-Soiw,414
|
|
215
215
|
jaclang/tests/fixtures/lambda.jac,sha256=nU4HbPrBdYe6NegJq4LueequaiLCe3KWyTAbL__ibG0,113
|
|
216
|
-
jaclang/tests/fixtures/math_question.jpg,sha256=YYLzFuCZRmhEcyTNKy-HzOaka4ZSswHExA3a6UMD18E,152545
|
|
217
216
|
jaclang/tests/fixtures/maxfail_run_test.jac,sha256=JSGAM4wXnu5kP5aczcHNDlnn017yZpinRApetQSPhtE,196
|
|
218
217
|
jaclang/tests/fixtures/mtest.impl.jac,sha256=wYsT4feH2JgxxgN217dgbDWooSmD8HBSlzUwJ4jAa8g,76
|
|
219
218
|
jaclang/tests/fixtures/mtest.jac,sha256=i7aQpJuUw4YMXgJOvGn_lRx-TruJdqBClioPKGUd4mw,67
|
|
@@ -243,14 +242,9 @@ jaclang/tests/fixtures/tuplytuples.jac,sha256=6qiXn5OV_qn4cqKwROjJ1VuBAh0nbUGpp-
|
|
|
243
242
|
jaclang/tests/fixtures/type_info.jac,sha256=4Cw31ef5gny6IS0kLzgeSO-7ArEH1HgFFFip1BGQhZM,316
|
|
244
243
|
jaclang/tests/fixtures/walker_override.jac,sha256=Ok58ZAgxuV6aECNxYrjbbyAWSiqIbnly3N3O6cD563o,271
|
|
245
244
|
jaclang/tests/fixtures/with_context.jac,sha256=cDA_4YWe5UVmQRgcpktzkZ_zsswQpV_T2Otf_rFnPy8,466
|
|
246
|
-
jaclang/tests/fixtures/with_llm_function.jac,sha256=Tt5C9rmAtHPGMVWx9A6M9iYLasPZVBecM_bzK_5btz8,797
|
|
247
|
-
jaclang/tests/fixtures/with_llm_lower.jac,sha256=G-aq6uQnRfcnXvv9Jan_WO7X1o0xU_FCKTzk007aXsQ,1871
|
|
248
|
-
jaclang/tests/fixtures/with_llm_method.jac,sha256=_la52GnLVXE5wnF3t8ZaL_72ojXHpzeYLlL-4zUOdM8,1413
|
|
249
|
-
jaclang/tests/fixtures/with_llm_type.jac,sha256=IXXgOaLPz90IbU8az9FqxmzKW9m08t3cq3146QWkXoA,1771
|
|
250
|
-
jaclang/tests/fixtures/with_llm_vision.jac,sha256=2UC_i1ufnXk9uhj4ruEaR_6romR_r2CVN3YwMLDdgGY,672
|
|
251
245
|
jaclang/tests/test_bugs.py,sha256=tBPsIlSPqZDIz4QaScNRT-WdGIdJ0uU-aRBWq1XUZ6o,555
|
|
252
246
|
jaclang/tests/test_cli.py,sha256=tnqdx8W5jTlsDJYR3713EikJqCbcgWEknEwuRHByvWk,8703
|
|
253
|
-
jaclang/tests/test_language.py,sha256=
|
|
247
|
+
jaclang/tests/test_language.py,sha256=T0DqM3aFjJ5_0oWqKhEkOyY1eruv-uGRgWkjWWcngXE,34671
|
|
254
248
|
jaclang/tests/test_man_code.py,sha256=Kq93zg3hEfiouvpWvmfCgR6lDT5RKDp28k5ZaWe1Xeg,4519
|
|
255
249
|
jaclang/tests/test_reference.py,sha256=FoZQS-U9teiag8mAmX5X6ak4fuCOv00mvOyqJ44Zkc8,3379
|
|
256
250
|
jaclang/tests/test_settings.py,sha256=TIX5uiu8H9IpZN2__uFiclcdCpBpPpcAwtlEHyFC4kk,1999
|
|
@@ -1484,7 +1478,7 @@ jaclang/vendor/typing_extensions-4.12.2.dist-info/METADATA,sha256=BeUQIa8cnYbrjW
|
|
|
1484
1478
|
jaclang/vendor/typing_extensions-4.12.2.dist-info/RECORD,sha256=XS4fBVrPI7kaNZ56Ggl2RGa76jySWLqTzcrUpZIQTVM,418
|
|
1485
1479
|
jaclang/vendor/typing_extensions-4.12.2.dist-info/WHEEL,sha256=EZbGkh7Ie4PoZfRQ8I0ZuP9VklN_TvcZ6DSE5Uar4z4,81
|
|
1486
1480
|
jaclang/vendor/typing_extensions.py,sha256=gwekpyG9DVG3lxWKX4ni8u7nk3We5slG98mA9F3DJQw,134451
|
|
1487
|
-
jaclang-0.7.
|
|
1488
|
-
jaclang-0.7.
|
|
1489
|
-
jaclang-0.7.
|
|
1490
|
-
jaclang-0.7.
|
|
1481
|
+
jaclang-0.7.9.dist-info/METADATA,sha256=uil9KBvccbzWC-m1gQEOrUjkRXcGBRyIctKEbLvQgGY,4807
|
|
1482
|
+
jaclang-0.7.9.dist-info/WHEEL,sha256=sP946D7jFCHeNz5Iq4fL4Lu-PrWrFsgfLXbbkciIZwg,88
|
|
1483
|
+
jaclang-0.7.9.dist-info/entry_points.txt,sha256=8sMi4Tvi9f8tQDN2QAXsSA2icO27zQ4GgEdph6bNEZM,49
|
|
1484
|
+
jaclang-0.7.9.dist-info/RECORD,,
|
jaclang/core/aott.py
DELETED
|
@@ -1,314 +0,0 @@
|
|
|
1
|
-
"""
|
|
2
|
-
AOTT: Automated Operational Type Transformation.
|
|
3
|
-
|
|
4
|
-
This has all the necessary functions to perform the AOTT operations.
|
|
5
|
-
"""
|
|
6
|
-
|
|
7
|
-
import base64
|
|
8
|
-
import logging
|
|
9
|
-
import re
|
|
10
|
-
from enum import Enum
|
|
11
|
-
from io import BytesIO
|
|
12
|
-
from typing import Any
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
try:
|
|
16
|
-
from PIL import Image
|
|
17
|
-
except ImportError:
|
|
18
|
-
Image = None
|
|
19
|
-
|
|
20
|
-
from jaclang.compiler.semtable import SemInfo, SemRegistry, SemScope
|
|
21
|
-
|
|
22
|
-
try:
|
|
23
|
-
from mtllm.llms import BaseLLM
|
|
24
|
-
except ImportError:
|
|
25
|
-
BaseLLM = None
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
IMG_FORMATS = ["PngImageFile", "JpegImageFile"]
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
def aott_raise(
|
|
32
|
-
model: BaseLLM, # type: ignore
|
|
33
|
-
information: str,
|
|
34
|
-
inputs_information: str | list[dict],
|
|
35
|
-
output_information: str,
|
|
36
|
-
type_explanations: str,
|
|
37
|
-
action: str,
|
|
38
|
-
context: str,
|
|
39
|
-
method: str,
|
|
40
|
-
tools: list["Tool"],
|
|
41
|
-
model_params: dict,
|
|
42
|
-
) -> str:
|
|
43
|
-
"""AOTT Raise uses the information (Meanings types values) provided to generate a prompt(meaning in)."""
|
|
44
|
-
system_prompt = model.MTLLM_SYSTEM_PROMPT
|
|
45
|
-
meaning_in: str | list[dict]
|
|
46
|
-
if method != "ReAct":
|
|
47
|
-
method_prompt = model.MTLLM_METHOD_PROMPTS[method]
|
|
48
|
-
if isinstance(inputs_information, str):
|
|
49
|
-
mtllm_prompt = model.MTLLM_PROMPT.format(
|
|
50
|
-
information=information,
|
|
51
|
-
inputs_information=inputs_information,
|
|
52
|
-
output_information=output_information,
|
|
53
|
-
type_explanations=type_explanations,
|
|
54
|
-
action=action,
|
|
55
|
-
context=context,
|
|
56
|
-
).strip()
|
|
57
|
-
meaning_in = f"{system_prompt}\n{mtllm_prompt}\n{method_prompt}".strip()
|
|
58
|
-
else:
|
|
59
|
-
upper_half = model.MTLLM_PROMPT.split("{inputs_information}")[0]
|
|
60
|
-
lower_half = model.MTLLM_PROMPT.split("{inputs_information}")[1]
|
|
61
|
-
upper_half = upper_half.format(
|
|
62
|
-
information=information,
|
|
63
|
-
context=context,
|
|
64
|
-
)
|
|
65
|
-
lower_half = lower_half.format(
|
|
66
|
-
output_information=output_information,
|
|
67
|
-
type_explanations=type_explanations,
|
|
68
|
-
action=action,
|
|
69
|
-
)
|
|
70
|
-
meaning_in = (
|
|
71
|
-
[
|
|
72
|
-
{"type": "text", "text": system_prompt},
|
|
73
|
-
{"type": "text", "text": upper_half},
|
|
74
|
-
]
|
|
75
|
-
+ inputs_information
|
|
76
|
-
+ [
|
|
77
|
-
{"type": "text", "text": lower_half},
|
|
78
|
-
{"type": "text", "text": method_prompt},
|
|
79
|
-
]
|
|
80
|
-
)
|
|
81
|
-
return model(meaning_in, **model_params)
|
|
82
|
-
else:
|
|
83
|
-
assert tools, "Tools must be provided for the ReAct method."
|
|
84
|
-
# TODO: Implement ReAct method
|
|
85
|
-
return ""
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
def get_info_types(
|
|
89
|
-
scope: SemScope, mod_registry: SemRegistry, incl_info: list[tuple[str, str]]
|
|
90
|
-
) -> tuple[str, list[str]]:
|
|
91
|
-
"""Filter the registry data based on the scope and return the info string."""
|
|
92
|
-
collected_types = []
|
|
93
|
-
avail_scopes = []
|
|
94
|
-
while True:
|
|
95
|
-
avail_scopes.append(str(scope))
|
|
96
|
-
if not scope.parent:
|
|
97
|
-
break
|
|
98
|
-
scope = scope.parent
|
|
99
|
-
|
|
100
|
-
filtered_registry = SemRegistry()
|
|
101
|
-
for _scope, sem_info_list in mod_registry.registry.items():
|
|
102
|
-
if str(_scope) in avail_scopes:
|
|
103
|
-
filtered_registry.registry[_scope] = sem_info_list
|
|
104
|
-
|
|
105
|
-
info_str = []
|
|
106
|
-
for incl in incl_info:
|
|
107
|
-
_, sem_info = filtered_registry.lookup(name=incl[0])
|
|
108
|
-
if sem_info and isinstance(sem_info, SemInfo):
|
|
109
|
-
(
|
|
110
|
-
collected_types.extend(extract_non_primary_type(sem_info.type))
|
|
111
|
-
if sem_info.type
|
|
112
|
-
else None
|
|
113
|
-
)
|
|
114
|
-
info_str.append(
|
|
115
|
-
f"{sem_info.semstr} ({sem_info.name}) ({sem_info.type}) = {get_object_string(incl[1])}".strip()
|
|
116
|
-
)
|
|
117
|
-
return ("\n".join(info_str), collected_types)
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
def get_object_string(obj: Any) -> Any: # noqa: ANN401
|
|
121
|
-
"""Get the string representation of the input object."""
|
|
122
|
-
if isinstance(obj, str):
|
|
123
|
-
return f'"{obj}"'
|
|
124
|
-
elif isinstance(obj, (int, float, bool)):
|
|
125
|
-
return str(obj)
|
|
126
|
-
elif isinstance(obj, list):
|
|
127
|
-
return "[" + ", ".join(get_object_string(item) for item in obj) + "]"
|
|
128
|
-
elif isinstance(obj, tuple):
|
|
129
|
-
return "(" + ", ".join(get_object_string(item) for item in obj) + ")"
|
|
130
|
-
elif isinstance(obj, dict):
|
|
131
|
-
return (
|
|
132
|
-
"{"
|
|
133
|
-
+ ", ".join(
|
|
134
|
-
f"{get_object_string(key)}: {get_object_string(value)}"
|
|
135
|
-
for key, value in obj.items()
|
|
136
|
-
)
|
|
137
|
-
+ "}"
|
|
138
|
-
)
|
|
139
|
-
elif isinstance(obj, Enum):
|
|
140
|
-
return f"{obj.__class__.__name__}.{obj.name}"
|
|
141
|
-
elif hasattr(obj, "__dict__"):
|
|
142
|
-
args = ", ".join(
|
|
143
|
-
f"{key}={get_object_string(value)}"
|
|
144
|
-
for key, value in vars(obj).items()
|
|
145
|
-
if key != "_jac_"
|
|
146
|
-
)
|
|
147
|
-
return f"{obj.__class__.__name__}({args})"
|
|
148
|
-
else:
|
|
149
|
-
return str(obj)
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
def get_all_type_explanations(type_list: list, mod_registry: SemRegistry) -> dict:
|
|
153
|
-
"""Get all type explanations from the input type list."""
|
|
154
|
-
collected_type_explanations = {}
|
|
155
|
-
for type_item in type_list:
|
|
156
|
-
type_explanation_str, nested_types = get_type_explanation(
|
|
157
|
-
type_item, mod_registry
|
|
158
|
-
)
|
|
159
|
-
if type_explanation_str is not None:
|
|
160
|
-
if type_item not in collected_type_explanations:
|
|
161
|
-
collected_type_explanations[type_item] = type_explanation_str
|
|
162
|
-
if nested_types:
|
|
163
|
-
nested_collected_type_explanations = get_all_type_explanations(
|
|
164
|
-
list(nested_types), mod_registry
|
|
165
|
-
)
|
|
166
|
-
for k, v in nested_collected_type_explanations.items():
|
|
167
|
-
if k not in collected_type_explanations:
|
|
168
|
-
collected_type_explanations[k] = v
|
|
169
|
-
return collected_type_explanations
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
def get_type_explanation(
|
|
173
|
-
type_str: str, mod_registry: SemRegistry
|
|
174
|
-
) -> tuple[str | None, set[str] | None]:
|
|
175
|
-
"""Get the type explanation of the input type string."""
|
|
176
|
-
scope, sem_info = mod_registry.lookup(name=type_str)
|
|
177
|
-
if isinstance(sem_info, SemInfo) and sem_info.type:
|
|
178
|
-
sem_info_scope = SemScope(sem_info.name, sem_info.type, scope)
|
|
179
|
-
_, type_info = mod_registry.lookup(scope=sem_info_scope)
|
|
180
|
-
type_info_str = []
|
|
181
|
-
type_info_types = []
|
|
182
|
-
type_example = [f"{sem_info.name}("]
|
|
183
|
-
if sem_info.type == "Enum" and isinstance(type_info, list):
|
|
184
|
-
for enum_item in type_info:
|
|
185
|
-
type_info_str.append(
|
|
186
|
-
f"{enum_item.semstr} ({enum_item.name}) (EnumItem)".strip()
|
|
187
|
-
)
|
|
188
|
-
type_example[0] = type_example[0].replace("(", f".{enum_item.name}")
|
|
189
|
-
elif sem_info.type in ["obj", "class", "node", "edge"] and isinstance(
|
|
190
|
-
type_info, list
|
|
191
|
-
):
|
|
192
|
-
for arch_item in type_info:
|
|
193
|
-
if arch_item.type in ["obj", "class", "node", "edge"]:
|
|
194
|
-
continue
|
|
195
|
-
type_info_str.append(
|
|
196
|
-
f"{arch_item.semstr} ({arch_item.name}) ({arch_item.type})".strip()
|
|
197
|
-
)
|
|
198
|
-
type_example.append(f"{arch_item.name}={arch_item.type}, ")
|
|
199
|
-
if arch_item.type and extract_non_primary_type(arch_item.type):
|
|
200
|
-
type_info_types.extend(extract_non_primary_type(arch_item.type))
|
|
201
|
-
if len(type_example) > 1:
|
|
202
|
-
type_example[-1] = type_example[-1].replace(", ", ")")
|
|
203
|
-
else:
|
|
204
|
-
type_example.append(")")
|
|
205
|
-
return (
|
|
206
|
-
f"{sem_info.semstr} ({sem_info.name}) ({sem_info.type}) eg:- {''.join(type_example)} -> {', '.join(type_info_str)}".strip(), # noqa: E501
|
|
207
|
-
set(type_info_types),
|
|
208
|
-
)
|
|
209
|
-
return None, None
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
def extract_non_primary_type(type_str: str) -> list:
|
|
213
|
-
"""Extract non-primary types from the type string."""
|
|
214
|
-
if not type_str:
|
|
215
|
-
return []
|
|
216
|
-
pattern = r"(?:\[|,\s*|\|)([a-zA-Z_][a-zA-Z0-9_]*)|([a-zA-Z_][a-zA-Z0-9_]*)"
|
|
217
|
-
matches = re.findall(pattern, type_str)
|
|
218
|
-
primary_types = [
|
|
219
|
-
"str",
|
|
220
|
-
"int",
|
|
221
|
-
"float",
|
|
222
|
-
"bool",
|
|
223
|
-
"list",
|
|
224
|
-
"dict",
|
|
225
|
-
"tuple",
|
|
226
|
-
"set",
|
|
227
|
-
"Any",
|
|
228
|
-
"None",
|
|
229
|
-
]
|
|
230
|
-
non_primary_types = [m for t in matches for m in t if m and m not in primary_types]
|
|
231
|
-
return non_primary_types
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
def get_type_annotation(data: Any) -> str: # noqa: ANN401
|
|
235
|
-
"""Get the type annotation of the input data."""
|
|
236
|
-
if isinstance(data, dict):
|
|
237
|
-
class_name = next(
|
|
238
|
-
(value.__class__.__name__ for value in data.values() if value is not None),
|
|
239
|
-
None,
|
|
240
|
-
)
|
|
241
|
-
if class_name:
|
|
242
|
-
return f"dict[str, {class_name}]"
|
|
243
|
-
else:
|
|
244
|
-
return "dict[str, Any]"
|
|
245
|
-
else:
|
|
246
|
-
return str(type(data).__name__)
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
class Tool:
|
|
250
|
-
"""Tool class for the AOTT operations."""
|
|
251
|
-
|
|
252
|
-
def __init__(self) -> None:
|
|
253
|
-
"""Initialize the Tool class."""
|
|
254
|
-
# TODO: Implement the Tool class
|
|
255
|
-
pass
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
def get_input_information(
|
|
259
|
-
inputs: list[tuple[str, str, str, Any]], type_collector: list
|
|
260
|
-
) -> str | list[dict]:
|
|
261
|
-
"""
|
|
262
|
-
Get the input information for the AOTT operation.
|
|
263
|
-
|
|
264
|
-
Returns:
|
|
265
|
-
str | list[dict]: If the input does not contain images, returns a string with the input information.
|
|
266
|
-
If the input contains images, returns a list of dictionaries representing the input information,
|
|
267
|
-
where each dictionary contains either text or image_url.
|
|
268
|
-
|
|
269
|
-
"""
|
|
270
|
-
contains_imgs = any(get_type_annotation(i[3]) in IMG_FORMATS for i in inputs)
|
|
271
|
-
if not contains_imgs:
|
|
272
|
-
inputs_information_list = []
|
|
273
|
-
for i in inputs:
|
|
274
|
-
typ_anno = get_type_annotation(i[3])
|
|
275
|
-
type_collector.extend(extract_non_primary_type(typ_anno))
|
|
276
|
-
inputs_information_list.append(
|
|
277
|
-
f"{i[0] if i[0] else ''} ({i[2]}) ({typ_anno}) = {get_object_string(i[3])}".strip()
|
|
278
|
-
)
|
|
279
|
-
return "\n".join(inputs_information_list)
|
|
280
|
-
else:
|
|
281
|
-
inputs_information_dict_list: list[dict] = []
|
|
282
|
-
for i in inputs:
|
|
283
|
-
if get_type_annotation(i[3]) in IMG_FORMATS:
|
|
284
|
-
img_base64 = image_to_base64(i[3])
|
|
285
|
-
image_repr: list[dict] = [
|
|
286
|
-
{
|
|
287
|
-
"type": "text",
|
|
288
|
-
"text": f"{i[0] if i[0] else ''} ({i[2]}) (Image) = ".strip(),
|
|
289
|
-
},
|
|
290
|
-
{"type": "image_url", "image_url": {"url": img_base64}},
|
|
291
|
-
]
|
|
292
|
-
inputs_information_dict_list.extend(image_repr)
|
|
293
|
-
continue
|
|
294
|
-
typ_anno = get_type_annotation(i[3])
|
|
295
|
-
type_collector.extend(extract_non_primary_type(typ_anno))
|
|
296
|
-
inputs_information_dict_list.append(
|
|
297
|
-
{
|
|
298
|
-
"type": "text",
|
|
299
|
-
"text": f"{i[0] if i[0] else ''} ({i[2]}) ({typ_anno}) = {get_object_string(i[3])}".strip(),
|
|
300
|
-
}
|
|
301
|
-
)
|
|
302
|
-
return inputs_information_dict_list
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
def image_to_base64(image: Image) -> str: # type: ignore
|
|
306
|
-
"""Convert an image to base64 expected by OpenAI."""
|
|
307
|
-
if not Image:
|
|
308
|
-
log = logging.getLogger(__name__)
|
|
309
|
-
log.error("Pillow is not installed. Please install Pillow to use images.")
|
|
310
|
-
return ""
|
|
311
|
-
img_format = image.format
|
|
312
|
-
with BytesIO() as buffer:
|
|
313
|
-
image.save(buffer, format=img_format, quality=100)
|
|
314
|
-
return f"data:image/{img_format.lower()};base64,{base64.b64encode(buffer.getvalue()).decode()}"
|
|
Binary file
|
|
@@ -1,33 +0,0 @@
|
|
|
1
|
-
import:py from mtllm.llms, BaseLLM;
|
|
2
|
-
|
|
3
|
-
obj model:BaseLLM: {
|
|
4
|
-
can init {
|
|
5
|
-
self.verbose = False;
|
|
6
|
-
self.max_tries = 1;
|
|
7
|
-
}
|
|
8
|
-
can __infer__(meaning_in: str, **kwargs: dict) {
|
|
9
|
-
print(kwargs);
|
|
10
|
-
print(meaning_in);
|
|
11
|
-
return "[Output] Something";
|
|
12
|
-
}
|
|
13
|
-
}
|
|
14
|
-
glob llm = model();
|
|
15
|
-
|
|
16
|
-
glob emoji_examples: 'Examples of Text to Emoji': list[dict[str, str]] = [
|
|
17
|
-
{
|
|
18
|
-
"input": "I love tp drink pina coladas",
|
|
19
|
-
"output": "👤 ❤️ 🥤 🍍🥥"
|
|
20
|
-
},
|
|
21
|
-
{
|
|
22
|
-
"input": "Mime Person",
|
|
23
|
-
"output": "👤🤲🚷"
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
];
|
|
27
|
-
|
|
28
|
-
can 'Get Emoji Representation'
|
|
29
|
-
get_emoji(input: 'Text Input': str) -> 'Emoji Representation': str by llm(temperature=0.7, incl_info=(emoji_examples),excl_info=());
|
|
30
|
-
|
|
31
|
-
with entry {
|
|
32
|
-
print(get_emoji('Lets move to paris'));
|
|
33
|
-
}
|
|
@@ -1,45 +0,0 @@
|
|
|
1
|
-
import:py from mtllm.llms, BaseLLM;
|
|
2
|
-
|
|
3
|
-
obj model:BaseLLM: {
|
|
4
|
-
can init {
|
|
5
|
-
self.verbose = False;
|
|
6
|
-
self.max_tries = 1;
|
|
7
|
-
}
|
|
8
|
-
can __infer__(meaning_in: str, **kwargs: dict) {
|
|
9
|
-
print(meaning_in);
|
|
10
|
-
return '[Reasoning] J. Robert Oppenheimer, also known as the "father of the atomic bomb," was a brilliant '
|
|
11
|
-
'theoretical physicist and the director of the Manhattan Project during World War II. He played a crucial '
|
|
12
|
-
'role in developing the first nuclear weapons. However, after witnessing the devastation caused by the '
|
|
13
|
-
'atomic bombs dropped on Hiroshima and Nagasaki, he expressed deep regret and became an advocate for nuclear '
|
|
14
|
-
'disarmament. While he was an exceptional scientist, he was also known for his introspective and philosophical '
|
|
15
|
-
'nature, which suggests an introverted personality.\n'
|
|
16
|
-
'[Output] Person(full_name="J. Robert Oppenheimer", yod=1967, personality=Personality.INTROVERT)';
|
|
17
|
-
}
|
|
18
|
-
}
|
|
19
|
-
glob llm = model();
|
|
20
|
-
|
|
21
|
-
enum 'Personality of the Person'
|
|
22
|
-
Personality {
|
|
23
|
-
INTROVERT: 'Person who is shy and reticent' = "Introvert",
|
|
24
|
-
EXTROVERT: 'Person who is outgoing and socially confident' = "Extrovert"
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
obj 'Person'
|
|
28
|
-
Person {
|
|
29
|
-
has full_name: 'Fullname of the Person': str,
|
|
30
|
-
yod: 'Year of Death': int,
|
|
31
|
-
personality: 'Personality of the Person': Personality;
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
glob personality_examples: 'Personality Information of Famous People': dict[str, Personality] = {
|
|
35
|
-
'Albert Einstein': Personality.INTROVERT,
|
|
36
|
-
'Barack Obama': Personality.EXTROVERT
|
|
37
|
-
};
|
|
38
|
-
|
|
39
|
-
can 'Get Person Information use common knowledge'
|
|
40
|
-
get_person_info(name: 'Name of the Person': str) -> 'Person': Person by llm(method="Reason");
|
|
41
|
-
|
|
42
|
-
with entry {
|
|
43
|
-
person_obj = get_person_info('Oppenheimer');
|
|
44
|
-
print(f"{person_obj.full_name} was a {person_obj.personality.value} person who died in {person_obj.yod}");
|
|
45
|
-
}
|
|
@@ -1,51 +0,0 @@
|
|
|
1
|
-
import:py from mtllm.llms, BaseLLM;
|
|
2
|
-
|
|
3
|
-
obj model:BaseLLM: {
|
|
4
|
-
can init {
|
|
5
|
-
self.verbose = False;
|
|
6
|
-
self.max_tries = 1;
|
|
7
|
-
}
|
|
8
|
-
can __infer__(meaning_in: str, **kwargs: dict) {
|
|
9
|
-
print(meaning_in);
|
|
10
|
-
return "[Output] Something";
|
|
11
|
-
}
|
|
12
|
-
}
|
|
13
|
-
glob llm = model();
|
|
14
|
-
|
|
15
|
-
class 'Personality Index of a Person'
|
|
16
|
-
PersonalityIndex {
|
|
17
|
-
has index: 'Personality Index': int;
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
enum 'Personality of the Person'
|
|
21
|
-
Personality {
|
|
22
|
-
INTROVERT: 'Person who is shy and reticent',
|
|
23
|
-
EXTROVERT: 'Person who is outgoing and socially confident'
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
glob personality_examples: 'Personality Information of Famous People': dict[str, Personality|None] = {
|
|
27
|
-
'Albert Einstein': Personality.INTROVERT,
|
|
28
|
-
'Barack Obama': Personality.EXTROVERT
|
|
29
|
-
};
|
|
30
|
-
|
|
31
|
-
obj 'Person'
|
|
32
|
-
Person {
|
|
33
|
-
has name: 'Name of the Person': str,
|
|
34
|
-
age: 'Age of the Person': int;
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
obj 'main object '
|
|
38
|
-
outer{
|
|
39
|
-
obj 'inner object'
|
|
40
|
-
inner {
|
|
41
|
-
has diary_entries :'Diary Entries': list[str];
|
|
42
|
-
can 'Get Personality of the Person'
|
|
43
|
-
get_personality (person: 'Person Object': list[Person]) -> 'Personality of the Person': dict[Personality, PersonalityIndex] by llm(method="Reason", incl_info=(personality_examples, self.diary_entries));
|
|
44
|
-
}
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
with entry{
|
|
48
|
-
obj1=outer.inner(["I won noble prize in Physics", "I am popular for my theory of relativity"]);
|
|
49
|
-
pp=Person('Albert Einstein', 76);
|
|
50
|
-
print(obj1.get_personality(pp));
|
|
51
|
-
}
|
|
@@ -1,52 +0,0 @@
|
|
|
1
|
-
import:py from mtllm.llms, BaseLLM;
|
|
2
|
-
|
|
3
|
-
obj model:BaseLLM: {
|
|
4
|
-
can init(output_str: str) {
|
|
5
|
-
self.verbose = False;
|
|
6
|
-
self.max_tries = 1;
|
|
7
|
-
self.output_str = output_str;
|
|
8
|
-
}
|
|
9
|
-
can __infer__(meaning_in: str, **kwargs: dict) {
|
|
10
|
-
print("Meaning in: ", meaning_in);
|
|
11
|
-
return f"[Output] {self.output_str}";
|
|
12
|
-
}
|
|
13
|
-
}
|
|
14
|
-
glob llm1 = model(output_str="Person(name='Albert Einstein', dob='14/03/1879', age=76)");
|
|
15
|
-
|
|
16
|
-
obj 'Person'
|
|
17
|
-
Person {
|
|
18
|
-
has name: 'Name of the Person': str,
|
|
19
|
-
dob: 'Date of Birth': str,
|
|
20
|
-
age: 'Age of the Person': int;
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
with entry {
|
|
24
|
-
einstein: 'Einstein Object': Person = Person(name="Albert Einstein" by llm1());
|
|
25
|
-
print(einstein.dob); #14/03/1879
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
glob llm2 = model(output_str="University.Department(name='Computer Science', head=Person(name='Jason Mars', dob='1994-01-01', age=30))");
|
|
29
|
-
|
|
30
|
-
obj 'University'
|
|
31
|
-
University {
|
|
32
|
-
has name: 'Name of the University': str,
|
|
33
|
-
location: 'Location of the University': str,
|
|
34
|
-
departments: 'Departments in the University': list[self.Department] = [];
|
|
35
|
-
|
|
36
|
-
obj 'Department'
|
|
37
|
-
Department {
|
|
38
|
-
has name: 'Name of the Department': str,
|
|
39
|
-
head: 'Head of the Department': Person;
|
|
40
|
-
}
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
with entry {
|
|
44
|
-
umich: 'Univeristy of Michigan': University = University(name="University of Michigan", location="Ann Arbor, Michigan");
|
|
45
|
-
cs_department: 'Computer Science Department': University.Department = University.Department(
|
|
46
|
-
name="Computer Science" by llm2(incl_info=(umich))
|
|
47
|
-
);
|
|
48
|
-
print(cs_department.head); # Person(name='Jason Mars', dob='1994-01-01', age=30)
|
|
49
|
-
|
|
50
|
-
umich.departments.append(umich.Department(name="Computer Science" by llm2()));
|
|
51
|
-
print(umich.departments[0].head); # Person(name='Jason Mars', dob='1994-01-01', age=30)
|
|
52
|
-
}
|
|
@@ -1,25 +0,0 @@
|
|
|
1
|
-
import:py from mtllm.llms, BaseLLM;
|
|
2
|
-
import:py from PIL, Image;
|
|
3
|
-
import:py os;
|
|
4
|
-
|
|
5
|
-
obj model:BaseLLM: {
|
|
6
|
-
can init {
|
|
7
|
-
self.verbose = False;
|
|
8
|
-
self.max_tries = 1;
|
|
9
|
-
}
|
|
10
|
-
can __infer__(meaning_in: str, **kwargs: dict) {
|
|
11
|
-
print(kwargs);
|
|
12
|
-
print(meaning_in);
|
|
13
|
-
return "[Output] Something";
|
|
14
|
-
}
|
|
15
|
-
}
|
|
16
|
-
glob llm = model();
|
|
17
|
-
|
|
18
|
-
can 'Solve the Given Math Question'
|
|
19
|
-
solve_math_question(question_img: 'Image of the Question': Image) -> 'Answer to the Question': str
|
|
20
|
-
by llm(method="Chain-of-Thoughts");
|
|
21
|
-
|
|
22
|
-
with entry {
|
|
23
|
-
question_img = Image.open(os.path.join(os.path.dirname(__file__), 'math_question.jpg'));
|
|
24
|
-
print(solve_math_question(question_img));
|
|
25
|
-
}
|
|
File without changes
|
|
File without changes
|