jaclang 0.5.18__py3-none-any.whl → 0.6.1__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/cli/cli.py +94 -5
- jaclang/cli/cmdreg.py +18 -6
- jaclang/compiler/__init__.py +12 -5
- jaclang/compiler/absyntree.py +4 -5
- jaclang/compiler/generated/jac_parser.py +2 -2
- jaclang/compiler/jac.lark +2 -2
- jaclang/compiler/parser.py +48 -8
- jaclang/compiler/passes/main/__init__.py +3 -2
- jaclang/compiler/passes/main/access_modifier_pass.py +173 -0
- jaclang/compiler/passes/main/def_impl_match_pass.py +4 -1
- jaclang/compiler/passes/main/fuse_typeinfo_pass.py +10 -7
- jaclang/compiler/passes/main/import_pass.py +70 -40
- jaclang/compiler/passes/main/pyast_gen_pass.py +47 -83
- jaclang/compiler/passes/main/pyast_load_pass.py +136 -73
- jaclang/compiler/passes/main/pyjac_ast_link_pass.py +218 -0
- jaclang/compiler/passes/main/pyout_pass.py +14 -13
- jaclang/compiler/passes/main/registry_pass.py +8 -3
- jaclang/compiler/passes/main/schedules.py +7 -3
- jaclang/compiler/passes/main/sym_tab_build_pass.py +32 -29
- jaclang/compiler/passes/main/tests/test_import_pass.py +13 -2
- jaclang/compiler/passes/tool/jac_formatter_pass.py +83 -21
- jaclang/compiler/passes/tool/tests/test_jac_format_pass.py +11 -4
- jaclang/compiler/passes/transform.py +2 -0
- jaclang/compiler/symtable.py +10 -3
- jaclang/compiler/tests/test_importer.py +9 -0
- jaclang/compiler/workspace.py +17 -5
- jaclang/core/aott.py +43 -63
- jaclang/core/construct.py +157 -21
- jaclang/core/importer.py +77 -65
- jaclang/core/llms/__init__.py +20 -0
- jaclang/core/llms/anthropic.py +61 -0
- jaclang/core/llms/base.py +206 -0
- jaclang/core/llms/groq.py +67 -0
- jaclang/core/llms/huggingface.py +73 -0
- jaclang/core/llms/ollama.py +78 -0
- jaclang/core/llms/openai.py +61 -0
- jaclang/core/llms/togetherai.py +60 -0
- jaclang/core/llms/utils.py +9 -0
- jaclang/core/memory.py +48 -0
- jaclang/core/shelve_storage.py +55 -0
- jaclang/core/utils.py +16 -1
- jaclang/plugin/__init__.py +1 -2
- jaclang/plugin/builtin.py +1 -1
- jaclang/plugin/default.py +134 -18
- jaclang/plugin/feature.py +35 -13
- jaclang/plugin/spec.py +52 -10
- jaclang/plugin/tests/test_jaseci.py +219 -0
- jaclang/settings.py +1 -1
- jaclang/utils/helpers.py +6 -2
- jaclang/utils/treeprinter.py +14 -6
- jaclang-0.6.1.dist-info/METADATA +17 -0
- {jaclang-0.5.18.dist-info → jaclang-0.6.1.dist-info}/RECORD +55 -42
- jaclang/core/llms.py +0 -111
- jaclang-0.5.18.dist-info/METADATA +0 -7
- {jaclang-0.5.18.dist-info → jaclang-0.6.1.dist-info}/WHEEL +0 -0
- {jaclang-0.5.18.dist-info → jaclang-0.6.1.dist-info}/entry_points.txt +0 -0
- {jaclang-0.5.18.dist-info → jaclang-0.6.1.dist-info}/top_level.txt +0 -0
jaclang/core/aott.py
CHANGED
|
@@ -8,78 +8,40 @@ import re
|
|
|
8
8
|
from enum import Enum
|
|
9
9
|
from typing import Any
|
|
10
10
|
|
|
11
|
+
from jaclang.core.llms.base import BaseLLM
|
|
11
12
|
from jaclang.core.registry import SemInfo, SemRegistry, SemScope
|
|
12
13
|
|
|
13
14
|
|
|
14
|
-
PROMPT_TEMPLATE = """
|
|
15
|
-
[System Prompt]
|
|
16
|
-
This is an operation you must perform and return the output values. Neither, the methodology, extra sentences nor the code are not needed.
|
|
17
|
-
Input/Type formatting: Explanation of the Input (variable_name) (type) = value
|
|
18
|
-
|
|
19
|
-
[Information]
|
|
20
|
-
{information}
|
|
21
|
-
|
|
22
|
-
[Inputs Information]
|
|
23
|
-
{inputs_information}
|
|
24
|
-
|
|
25
|
-
[Output Information]
|
|
26
|
-
{output_information}
|
|
27
|
-
|
|
28
|
-
[Type Explanations]
|
|
29
|
-
{type_explanations}
|
|
30
|
-
|
|
31
|
-
[Action]
|
|
32
|
-
{action}
|
|
33
|
-
|
|
34
|
-
{reason_suffix}
|
|
35
|
-
""" # noqa E501
|
|
36
|
-
|
|
37
|
-
WITH_REASON_SUFFIX = """
|
|
38
|
-
Reason and return the output result(s) only, adhering to the provided Type in the following format
|
|
39
|
-
|
|
40
|
-
[Reasoning] <Reason>
|
|
41
|
-
[Output] <Result>
|
|
42
|
-
"""
|
|
43
|
-
|
|
44
|
-
WITHOUT_REASON_SUFFIX = """Generate and return the output result(s) only, adhering to the provided Type in the following format
|
|
45
|
-
|
|
46
|
-
[Output] <result>
|
|
47
|
-
""" # noqa E501
|
|
48
|
-
|
|
49
|
-
|
|
50
15
|
def aott_raise(
|
|
16
|
+
model: BaseLLM,
|
|
51
17
|
information: str,
|
|
52
18
|
inputs_information: str,
|
|
53
19
|
output_information: str,
|
|
54
20
|
type_explanations: str,
|
|
55
21
|
action: str,
|
|
56
|
-
|
|
22
|
+
context: str,
|
|
23
|
+
method: str,
|
|
24
|
+
tools: list["Tool"],
|
|
25
|
+
model_params: dict,
|
|
57
26
|
) -> str:
|
|
58
27
|
"""AOTT Raise uses the information (Meanings types values) provided to generate a prompt(meaning in)."""
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
output_match = re.search(r"\[Output\](.*)", s)
|
|
73
|
-
|
|
74
|
-
if reasoning_match and output_match:
|
|
75
|
-
reasoning = reasoning_match.group(1)
|
|
76
|
-
output = output_match.group(1)
|
|
77
|
-
return (reasoning.strip(), output.strip())
|
|
78
|
-
elif output_match:
|
|
79
|
-
output = output_match.group(1)
|
|
80
|
-
return (None, output.strip())
|
|
28
|
+
if method != "ReAct":
|
|
29
|
+
system_prompt = model.MTLLM_SYSTEM_PROMPT
|
|
30
|
+
mtllm_prompt = model.MTLLM_PROMPT.format(
|
|
31
|
+
information=information,
|
|
32
|
+
inputs_information=inputs_information,
|
|
33
|
+
output_information=output_information,
|
|
34
|
+
type_explanations=type_explanations,
|
|
35
|
+
action=action,
|
|
36
|
+
context=context,
|
|
37
|
+
)
|
|
38
|
+
method_prompt = model.MTLLM_METHOD_PROMPTS[method]
|
|
39
|
+
meaning_in = f"{system_prompt}\n{mtllm_prompt}\n{method_prompt}"
|
|
40
|
+
return model(meaning_in, **model_params)
|
|
81
41
|
else:
|
|
82
|
-
|
|
42
|
+
assert tools, "Tools must be provided for the ReAct method."
|
|
43
|
+
# TODO: Implement ReAct method
|
|
44
|
+
return ""
|
|
83
45
|
|
|
84
46
|
|
|
85
47
|
def get_info_types(
|
|
@@ -176,22 +138,31 @@ def get_type_explanation(
|
|
|
176
138
|
_, type_info = mod_registry.lookup(scope=sem_info_scope)
|
|
177
139
|
type_info_str = []
|
|
178
140
|
type_info_types = []
|
|
141
|
+
type_example = [f"{sem_info.name}("]
|
|
179
142
|
if sem_info.type == "Enum" and isinstance(type_info, list):
|
|
180
143
|
for enum_item in type_info:
|
|
181
144
|
type_info_str.append(
|
|
182
|
-
f"{enum_item.semstr} (
|
|
145
|
+
f"{enum_item.semstr} ({enum_item.name}) (EnumItem)"
|
|
183
146
|
)
|
|
147
|
+
type_example[0] = type_example[0].replace("(", f".{enum_item.name}")
|
|
184
148
|
elif sem_info.type in ["obj", "class", "node", "edge"] and isinstance(
|
|
185
149
|
type_info, list
|
|
186
150
|
):
|
|
187
151
|
for arch_item in type_info:
|
|
152
|
+
if arch_item.type in ["obj", "class", "node", "edge"]:
|
|
153
|
+
continue
|
|
188
154
|
type_info_str.append(
|
|
189
|
-
f"{arch_item.semstr} ({arch_item.
|
|
155
|
+
f"{arch_item.semstr} ({arch_item.name}) ({arch_item.type})"
|
|
190
156
|
)
|
|
157
|
+
type_example.append(f"{arch_item.name}={arch_item.type}, ")
|
|
191
158
|
if arch_item.type and extract_non_primary_type(arch_item.type):
|
|
192
159
|
type_info_types.extend(extract_non_primary_type(arch_item.type))
|
|
160
|
+
if len(type_example) > 1:
|
|
161
|
+
type_example[-1] = type_example[-1].replace(", ", ")")
|
|
162
|
+
else:
|
|
163
|
+
type_example.append(")")
|
|
193
164
|
return (
|
|
194
|
-
f"{sem_info.semstr} ({sem_info.
|
|
165
|
+
f"{sem_info.semstr} ({sem_info.name}) ({sem_info.type}) eg:- {''.join(type_example)} -> {', '.join(type_info_str)}", # noqa: E501
|
|
195
166
|
set(type_info_types),
|
|
196
167
|
)
|
|
197
168
|
return None, None
|
|
@@ -232,3 +203,12 @@ def get_type_annotation(data: Any) -> str: # noqa: ANN401
|
|
|
232
203
|
return "dict[str, Any]"
|
|
233
204
|
else:
|
|
234
205
|
return str(type(data).__name__)
|
|
206
|
+
|
|
207
|
+
|
|
208
|
+
class Tool:
|
|
209
|
+
"""Tool class for the AOTT operations."""
|
|
210
|
+
|
|
211
|
+
def __init__(self) -> None:
|
|
212
|
+
"""Initialize the Tool class."""
|
|
213
|
+
# TODO: Implement the Tool class
|
|
214
|
+
pass
|
jaclang/core/construct.py
CHANGED
|
@@ -2,15 +2,15 @@
|
|
|
2
2
|
|
|
3
3
|
from __future__ import annotations
|
|
4
4
|
|
|
5
|
-
# import shelve
|
|
6
|
-
import types
|
|
7
5
|
import unittest
|
|
8
6
|
from dataclasses import dataclass, field
|
|
9
|
-
from typing import
|
|
10
|
-
|
|
7
|
+
from typing import Callable, Optional
|
|
8
|
+
from uuid import UUID, uuid4
|
|
11
9
|
|
|
12
10
|
from jaclang.compiler.constant import EdgeDir
|
|
13
11
|
from jaclang.core.utils import collect_node_connections
|
|
12
|
+
from jaclang.plugin.feature import JacFeature as Jac
|
|
13
|
+
from jaclang.plugin.spec import DSFunc
|
|
14
14
|
|
|
15
15
|
|
|
16
16
|
@dataclass(eq=False)
|
|
@@ -18,6 +18,7 @@ class ElementAnchor:
|
|
|
18
18
|
"""Element Anchor."""
|
|
19
19
|
|
|
20
20
|
obj: Architype
|
|
21
|
+
id: UUID = field(default_factory=uuid4)
|
|
21
22
|
|
|
22
23
|
|
|
23
24
|
@dataclass(eq=False)
|
|
@@ -35,6 +36,37 @@ class NodeAnchor(ObjectAnchor):
|
|
|
35
36
|
|
|
36
37
|
obj: NodeArchitype
|
|
37
38
|
edges: list[EdgeArchitype] = field(default_factory=lambda: [])
|
|
39
|
+
edge_ids: list[UUID] = field(default_factory=lambda: [])
|
|
40
|
+
persistent: bool = False
|
|
41
|
+
|
|
42
|
+
def __getstate__(self) -> dict:
|
|
43
|
+
"""Override getstate for pickle and shelve."""
|
|
44
|
+
state = self.__dict__.copy()
|
|
45
|
+
state.pop("obj")
|
|
46
|
+
if self.edges and "edges" in state:
|
|
47
|
+
edges = state.pop("edges")
|
|
48
|
+
state["edge_ids"] = [e._jac_.id for e in edges]
|
|
49
|
+
|
|
50
|
+
return state
|
|
51
|
+
|
|
52
|
+
def __setstate__(self, state: dict) -> None:
|
|
53
|
+
"""Override setstate for pickle and shelve."""
|
|
54
|
+
self.__dict__.update(state)
|
|
55
|
+
if "edge_ids" in state:
|
|
56
|
+
self.edge_ids = state.pop("edge_ids")
|
|
57
|
+
|
|
58
|
+
def populate_edges(self) -> None:
|
|
59
|
+
"""Populate edges from edge ids."""
|
|
60
|
+
if len(self.edges) == 0 and len(self.edge_ids) > 0:
|
|
61
|
+
for e_id in self.edge_ids:
|
|
62
|
+
edge = Jac.context().get_obj(e_id)
|
|
63
|
+
if edge is None:
|
|
64
|
+
raise ValueError(f"Edge with id {e_id} not found.")
|
|
65
|
+
elif not isinstance(edge, EdgeArchitype):
|
|
66
|
+
raise ValueError(f"Object with id {e_id} is not an edge.")
|
|
67
|
+
else:
|
|
68
|
+
self.edges.append(edge)
|
|
69
|
+
self.edge_ids.clear()
|
|
38
70
|
|
|
39
71
|
def connect_node(self, nd: NodeArchitype, edg: EdgeArchitype) -> NodeArchitype:
|
|
40
72
|
"""Connect a node with given edge."""
|
|
@@ -48,6 +80,8 @@ class NodeAnchor(ObjectAnchor):
|
|
|
48
80
|
target_obj: Optional[list[NodeArchitype]],
|
|
49
81
|
) -> list[EdgeArchitype]:
|
|
50
82
|
"""Get edges connected to this node."""
|
|
83
|
+
self.populate_edges()
|
|
84
|
+
|
|
51
85
|
edge_list: list[EdgeArchitype] = [*self.edges]
|
|
52
86
|
ret_edges: list[EdgeArchitype] = []
|
|
53
87
|
edge_list = filter_func(edge_list) if filter_func else edge_list
|
|
@@ -76,6 +110,9 @@ class NodeAnchor(ObjectAnchor):
|
|
|
76
110
|
target_obj: Optional[list[NodeArchitype]],
|
|
77
111
|
) -> list[NodeArchitype]:
|
|
78
112
|
"""Get set of nodes connected to this node."""
|
|
113
|
+
self.populate_edges()
|
|
114
|
+
for edge in self.edges:
|
|
115
|
+
edge.populate_nodes()
|
|
79
116
|
edge_list: list[EdgeArchitype] = [*self.edges]
|
|
80
117
|
node_list: list[NodeArchitype] = []
|
|
81
118
|
edge_list = filter_func(edge_list) if filter_func else edge_list
|
|
@@ -126,7 +163,29 @@ class EdgeAnchor(ObjectAnchor):
|
|
|
126
163
|
obj: EdgeArchitype
|
|
127
164
|
source: Optional[NodeArchitype] = None
|
|
128
165
|
target: Optional[NodeArchitype] = None
|
|
166
|
+
source_id: Optional[UUID] = None
|
|
167
|
+
target_id: Optional[UUID] = None
|
|
129
168
|
is_undirected: bool = False
|
|
169
|
+
persistent: bool = False
|
|
170
|
+
|
|
171
|
+
def __getstate__(self) -> dict:
|
|
172
|
+
"""Override getstate for pickle and shelve."""
|
|
173
|
+
state = self.__dict__.copy()
|
|
174
|
+
state.pop("obj")
|
|
175
|
+
|
|
176
|
+
if self.source:
|
|
177
|
+
state["source_id"] = self.source._jac_.id
|
|
178
|
+
state.pop("source")
|
|
179
|
+
|
|
180
|
+
if self.target:
|
|
181
|
+
state["target_id"] = self.target._jac_.id
|
|
182
|
+
state.pop("target")
|
|
183
|
+
|
|
184
|
+
return state
|
|
185
|
+
|
|
186
|
+
def __setstate__(self, state: dict) -> None:
|
|
187
|
+
"""Override setstate for pickle and shelve."""
|
|
188
|
+
self.__dict__.update(state)
|
|
130
189
|
|
|
131
190
|
def attach(
|
|
132
191
|
self, src: NodeArchitype, trg: NodeArchitype, is_undirected: bool = False
|
|
@@ -268,26 +327,113 @@ class Architype:
|
|
|
268
327
|
"""Create default architype."""
|
|
269
328
|
self._jac_: ObjectAnchor = ObjectAnchor(obj=self)
|
|
270
329
|
|
|
330
|
+
def __hash__(self) -> int:
|
|
331
|
+
"""Override hash for architype."""
|
|
332
|
+
return hash(self._jac_.id)
|
|
333
|
+
|
|
334
|
+
def __eq__(self, other: object) -> bool:
|
|
335
|
+
"""Override equality for architype."""
|
|
336
|
+
if not isinstance(other, Architype):
|
|
337
|
+
return False
|
|
338
|
+
else:
|
|
339
|
+
return self._jac_.id == other._jac_.id
|
|
340
|
+
|
|
341
|
+
def __repr__(self) -> str:
|
|
342
|
+
"""Override repr for architype."""
|
|
343
|
+
return f"{self.__class__.__name__}"
|
|
344
|
+
|
|
345
|
+
def __getstate__(self) -> dict:
|
|
346
|
+
"""Override getstate for pickle and shelve."""
|
|
347
|
+
raise NotImplementedError
|
|
348
|
+
|
|
271
349
|
|
|
272
350
|
class NodeArchitype(Architype):
|
|
273
351
|
"""Node Architype Protocol."""
|
|
274
352
|
|
|
353
|
+
_jac_: NodeAnchor
|
|
354
|
+
|
|
275
355
|
def __init__(self) -> None:
|
|
276
356
|
"""Create node architype."""
|
|
277
357
|
self._jac_: NodeAnchor = NodeAnchor(obj=self)
|
|
358
|
+
Jac.context().save_obj(self, persistent=self._jac_.persistent)
|
|
359
|
+
|
|
360
|
+
def save(self) -> None:
|
|
361
|
+
"""Save the node to the memory/storage hierarchy."""
|
|
362
|
+
self._jac_.persistent = True
|
|
363
|
+
Jac.context().save_obj(self, persistent=True)
|
|
364
|
+
|
|
365
|
+
def __getstate__(self) -> dict:
|
|
366
|
+
"""Override getstate for pickle and shelve."""
|
|
367
|
+
state = self.__dict__.copy()
|
|
368
|
+
state["_jac_"] = self._jac_.__getstate__()
|
|
369
|
+
return state
|
|
370
|
+
|
|
371
|
+
def __setstate__(self, state: dict) -> None:
|
|
372
|
+
"""Override setstate for pickle and shelve."""
|
|
373
|
+
self.__dict__.update(state)
|
|
374
|
+
self._jac_ = NodeAnchor(obj=self)
|
|
375
|
+
self._jac_.__setstate__(state["_jac_"])
|
|
278
376
|
|
|
279
377
|
|
|
280
378
|
class EdgeArchitype(Architype):
|
|
281
379
|
"""Edge Architype Protocol."""
|
|
282
380
|
|
|
381
|
+
_jac_: EdgeAnchor
|
|
382
|
+
persistent: bool = False
|
|
383
|
+
|
|
283
384
|
def __init__(self) -> None:
|
|
284
385
|
"""Create edge architype."""
|
|
285
386
|
self._jac_: EdgeAnchor = EdgeAnchor(obj=self)
|
|
387
|
+
Jac.context().save_obj(self, persistent=self.persistent)
|
|
388
|
+
|
|
389
|
+
def save(self) -> None:
|
|
390
|
+
"""Save the edge to the memory/storage hierarchy."""
|
|
391
|
+
self.persistent = True
|
|
392
|
+
Jac.context().save_obj(self, persistent=True)
|
|
393
|
+
|
|
394
|
+
def __getstate__(self) -> dict:
|
|
395
|
+
"""Override getstate for pickle and shelve."""
|
|
396
|
+
state = self.__dict__.copy()
|
|
397
|
+
state["_jac_"] = self._jac_.__getstate__()
|
|
398
|
+
return state
|
|
399
|
+
|
|
400
|
+
def __setstate__(self, state: dict) -> None:
|
|
401
|
+
"""Override setstate for pickle and shelve."""
|
|
402
|
+
self.__dict__.update(state)
|
|
403
|
+
self._jac_ = EdgeAnchor(obj=self)
|
|
404
|
+
self._jac_.__setstate__(state["_jac_"])
|
|
405
|
+
|
|
406
|
+
def populate_nodes(self) -> None:
|
|
407
|
+
"""Populate nodes for the edges from node ids."""
|
|
408
|
+
if self._jac_.source_id:
|
|
409
|
+
obj = Jac.context().get_obj(self._jac_.source_id)
|
|
410
|
+
if obj is None:
|
|
411
|
+
raise ValueError(f"Node with id {self._jac_.source_id} not found.")
|
|
412
|
+
elif not isinstance(obj, NodeArchitype):
|
|
413
|
+
raise ValueError(
|
|
414
|
+
f"Object with id {self._jac_.source_id} is not a node."
|
|
415
|
+
)
|
|
416
|
+
else:
|
|
417
|
+
self._jac_.source = obj
|
|
418
|
+
self._jac_.source_id = None
|
|
419
|
+
if self._jac_.target_id:
|
|
420
|
+
obj = Jac.context().get_obj(self._jac_.target_id)
|
|
421
|
+
if obj is None:
|
|
422
|
+
raise ValueError(f"Node with id {self._jac_.target_id} not found.")
|
|
423
|
+
elif not isinstance(obj, NodeArchitype):
|
|
424
|
+
raise ValueError(
|
|
425
|
+
f"Object with id {self._jac_.target_id} is not a node."
|
|
426
|
+
)
|
|
427
|
+
else:
|
|
428
|
+
self._jac_.target = obj
|
|
429
|
+
self._jac_.target_id = None
|
|
286
430
|
|
|
287
431
|
|
|
288
432
|
class WalkerArchitype(Architype):
|
|
289
433
|
"""Walker Architype Protocol."""
|
|
290
434
|
|
|
435
|
+
_jac_: WalkerAnchor
|
|
436
|
+
|
|
291
437
|
def __init__(self) -> None:
|
|
292
438
|
"""Create walker architype."""
|
|
293
439
|
self._jac_: WalkerAnchor = WalkerAnchor(obj=self)
|
|
@@ -301,6 +447,12 @@ class Root(NodeArchitype):
|
|
|
301
447
|
reachable_nodes: list[NodeArchitype] = []
|
|
302
448
|
connections: set[tuple[NodeArchitype, NodeArchitype, EdgeArchitype]] = set()
|
|
303
449
|
|
|
450
|
+
def __init__(self) -> None:
|
|
451
|
+
"""Create root node."""
|
|
452
|
+
super().__init__()
|
|
453
|
+
self._jac_.id = UUID(int=0)
|
|
454
|
+
self._jac_.persistent = True
|
|
455
|
+
|
|
304
456
|
def reset(self) -> None:
|
|
305
457
|
"""Reset the root."""
|
|
306
458
|
self.reachable_nodes = []
|
|
@@ -315,19 +467,6 @@ class GenericEdge(EdgeArchitype):
|
|
|
315
467
|
_jac_exit_funcs_ = []
|
|
316
468
|
|
|
317
469
|
|
|
318
|
-
@dataclass(eq=False)
|
|
319
|
-
class DSFunc:
|
|
320
|
-
"""Data Spatial Function."""
|
|
321
|
-
|
|
322
|
-
name: str
|
|
323
|
-
trigger: type | types.UnionType | tuple[type | types.UnionType, ...] | None
|
|
324
|
-
func: Callable[[Any, Any], Any] | None = None
|
|
325
|
-
|
|
326
|
-
def resolve(self, cls: type) -> None:
|
|
327
|
-
"""Resolve the function."""
|
|
328
|
-
self.func = getattr(cls, self.name)
|
|
329
|
-
|
|
330
|
-
|
|
331
470
|
class JacTestResult(unittest.TextTestResult):
|
|
332
471
|
"""Jac test result class."""
|
|
333
472
|
|
|
@@ -407,9 +546,6 @@ class JacTestCheck:
|
|
|
407
546
|
"""Create a new test."""
|
|
408
547
|
JacTestCheck.test_suite.addTest(unittest.FunctionTestCase(test_fun))
|
|
409
548
|
|
|
410
|
-
def __getattr__(self, name: str) ->
|
|
549
|
+
def __getattr__(self, name: str) -> object:
|
|
411
550
|
"""Make convenient check.Equal(...) etc."""
|
|
412
551
|
return getattr(JacTestCheck.test_case, name)
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
root = Root()
|
jaclang/core/importer.py
CHANGED
|
@@ -10,6 +10,7 @@ from typing import Optional, Union
|
|
|
10
10
|
from jaclang.compiler.absyntree import Module
|
|
11
11
|
from jaclang.compiler.compile import compile_jac
|
|
12
12
|
from jaclang.compiler.constant import Constants as Con
|
|
13
|
+
from jaclang.core.utils import sys_path_context
|
|
13
14
|
from jaclang.utils.log import logging
|
|
14
15
|
|
|
15
16
|
|
|
@@ -21,56 +22,41 @@ def jac_importer(
|
|
|
21
22
|
mdl_alias: Optional[str] = None,
|
|
22
23
|
override_name: Optional[str] = None,
|
|
23
24
|
mod_bundle: Optional[Module] = None,
|
|
24
|
-
lng: Optional[str] =
|
|
25
|
+
lng: Optional[str] = "jac",
|
|
25
26
|
items: Optional[dict[str, Union[str, bool]]] = None,
|
|
26
27
|
) -> Optional[types.ModuleType]:
|
|
27
28
|
"""Core Import Process."""
|
|
28
|
-
dir_path, file_name = (
|
|
29
|
-
path.
|
|
30
|
-
if lng == "py"
|
|
31
|
-
else path.split(path.join(*(target.split("."))) + ".jac")
|
|
29
|
+
dir_path, file_name = path.split(
|
|
30
|
+
path.join(*(target.split("."))) + (".jac" if lng == "jac" else ".py")
|
|
32
31
|
)
|
|
33
32
|
module_name = path.splitext(file_name)[0]
|
|
34
33
|
package_path = dir_path.replace(path.sep, ".")
|
|
35
34
|
|
|
36
|
-
if
|
|
35
|
+
if (
|
|
36
|
+
not override_name
|
|
37
|
+
and package_path
|
|
38
|
+
and f"{package_path}.{module_name}" in sys.modules
|
|
39
|
+
):
|
|
37
40
|
return sys.modules[f"{package_path}.{module_name}"]
|
|
38
|
-
elif not package_path and module_name in sys.modules
|
|
41
|
+
elif not override_name and not package_path and module_name in sys.modules:
|
|
39
42
|
return sys.modules[module_name]
|
|
40
43
|
|
|
41
|
-
caller_dir =
|
|
42
|
-
if not caller_dir:
|
|
43
|
-
caller_dir = getcwd()
|
|
44
|
-
chomp_target = target
|
|
45
|
-
if chomp_target.startswith("."):
|
|
46
|
-
chomp_target = chomp_target[1:]
|
|
47
|
-
while chomp_target.startswith("."):
|
|
48
|
-
caller_dir = path.dirname(caller_dir)
|
|
49
|
-
chomp_target = chomp_target[1:]
|
|
50
|
-
caller_dir = path.join(caller_dir, dir_path)
|
|
51
|
-
|
|
44
|
+
caller_dir = get_caller_dir(target, base_path, dir_path)
|
|
52
45
|
full_target = path.normpath(path.join(caller_dir, file_name))
|
|
53
|
-
path_added = False
|
|
54
|
-
if caller_dir not in sys.path:
|
|
55
|
-
sys.path.append(caller_dir)
|
|
56
|
-
path_added = True
|
|
57
46
|
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
47
|
+
if lng == "py":
|
|
48
|
+
module = py_import(
|
|
49
|
+
target=target, items=items, absorb=absorb, mdl_alias=mdl_alias
|
|
50
|
+
)
|
|
51
|
+
else:
|
|
52
|
+
module_name = override_name if override_name else module_name
|
|
53
|
+
module = create_jac_py_module(
|
|
54
|
+
mod_bundle, module_name, package_path, full_target
|
|
55
|
+
)
|
|
64
56
|
if mod_bundle:
|
|
65
|
-
codeobj =
|
|
66
|
-
|
|
67
|
-
if full_target == mod_bundle.loc.mod_path
|
|
68
|
-
else mod_bundle.mod_deps[full_target].gen.py_bytecode
|
|
69
|
-
)
|
|
70
|
-
if isinstance(codeobj, bytes):
|
|
71
|
-
codeobj = marshal.loads(codeobj)
|
|
57
|
+
codeobj = mod_bundle.mod_deps[full_target].gen.py_bytecode
|
|
58
|
+
codeobj = marshal.loads(codeobj) if isinstance(codeobj, bytes) else None
|
|
72
59
|
else:
|
|
73
|
-
|
|
74
60
|
gen_dir = path.join(caller_dir, Con.JAC_GEN_DIR)
|
|
75
61
|
pyc_file_path = path.join(gen_dir, module_name + ".jbc")
|
|
76
62
|
if (
|
|
@@ -89,46 +75,60 @@ def jac_importer(
|
|
|
89
75
|
return None
|
|
90
76
|
else:
|
|
91
77
|
codeobj = marshal.loads(result.ir.gen.py_bytecode)
|
|
92
|
-
|
|
93
|
-
if package_path:
|
|
94
|
-
parts = package_path.split(".")
|
|
95
|
-
for i in range(len(parts)):
|
|
96
|
-
package_name = ".".join(parts[: i + 1])
|
|
97
|
-
if package_name not in sys.modules:
|
|
98
|
-
sys.modules[package_name] = types.ModuleType(package_name)
|
|
99
|
-
|
|
100
|
-
setattr(sys.modules[package_path], module_name, module)
|
|
101
|
-
sys.modules[f"{package_path}.{module_name}"] = module
|
|
102
|
-
sys.modules[module_name] = module
|
|
103
|
-
|
|
104
78
|
if not codeobj:
|
|
105
79
|
raise ImportError(f"No bytecode found for {full_target}")
|
|
106
|
-
|
|
80
|
+
with sys_path_context(caller_dir):
|
|
81
|
+
exec(codeobj, module.__dict__)
|
|
107
82
|
|
|
108
|
-
|
|
109
|
-
py_import(target=target, items=items, absorb=absorb, mdl_alias=mdl_alias)
|
|
110
|
-
if lng == "py" or lng == "jac"
|
|
111
|
-
else None
|
|
112
|
-
)
|
|
83
|
+
return module
|
|
113
84
|
|
|
114
|
-
if path_added:
|
|
115
|
-
sys.path.remove(caller_dir)
|
|
116
85
|
|
|
86
|
+
def create_jac_py_module(
|
|
87
|
+
mod_bundle: Optional[Module], module_name: str, package_path: str, full_target: str
|
|
88
|
+
) -> types.ModuleType:
|
|
89
|
+
"""Create a module."""
|
|
90
|
+
module = types.ModuleType(module_name)
|
|
91
|
+
module.__file__ = full_target
|
|
92
|
+
module.__name__ = module_name
|
|
93
|
+
module.__dict__["__jac_mod_bundle__"] = mod_bundle
|
|
94
|
+
if package_path:
|
|
95
|
+
parts = package_path.split(".")
|
|
96
|
+
for i in range(len(parts)):
|
|
97
|
+
package_name = ".".join(parts[: i + 1])
|
|
98
|
+
if package_name not in sys.modules:
|
|
99
|
+
sys.modules[package_name] = types.ModuleType(package_name)
|
|
100
|
+
|
|
101
|
+
setattr(sys.modules[package_path], module_name, module)
|
|
102
|
+
sys.modules[f"{package_path}.{module_name}"] = module
|
|
103
|
+
sys.modules[module_name] = module
|
|
117
104
|
return module
|
|
118
105
|
|
|
119
106
|
|
|
107
|
+
def get_caller_dir(target: str, base_path: str, dir_path: str) -> str:
|
|
108
|
+
"""Get the directory of the caller."""
|
|
109
|
+
caller_dir = base_path if path.isdir(base_path) else path.dirname(base_path)
|
|
110
|
+
caller_dir = caller_dir if caller_dir else getcwd()
|
|
111
|
+
chomp_target = target
|
|
112
|
+
if chomp_target.startswith("."):
|
|
113
|
+
chomp_target = chomp_target[1:]
|
|
114
|
+
while chomp_target.startswith("."):
|
|
115
|
+
caller_dir = path.dirname(caller_dir)
|
|
116
|
+
chomp_target = chomp_target[1:]
|
|
117
|
+
caller_dir = path.join(caller_dir, dir_path)
|
|
118
|
+
return caller_dir
|
|
119
|
+
|
|
120
|
+
|
|
120
121
|
def py_import(
|
|
121
122
|
target: str,
|
|
122
123
|
items: Optional[dict[str, Union[str, bool]]] = None,
|
|
123
124
|
absorb: bool = False,
|
|
124
125
|
mdl_alias: Optional[str] = None,
|
|
125
|
-
) ->
|
|
126
|
+
) -> types.ModuleType:
|
|
126
127
|
"""Import a Python module."""
|
|
127
128
|
try:
|
|
128
129
|
target = target.lstrip(".") if target.startswith("..") else target
|
|
129
|
-
imported_module = importlib.import_module(target)
|
|
130
|
+
imported_module = importlib.import_module(name=target)
|
|
130
131
|
main_module = __import__("__main__")
|
|
131
|
-
# importer = importlib.import_module(caller)
|
|
132
132
|
if absorb:
|
|
133
133
|
for name in dir(imported_module):
|
|
134
134
|
if not name.startswith("_"):
|
|
@@ -136,11 +136,21 @@ def py_import(
|
|
|
136
136
|
|
|
137
137
|
elif items:
|
|
138
138
|
for name, alias in items.items():
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
139
|
+
try:
|
|
140
|
+
setattr(
|
|
141
|
+
main_module,
|
|
142
|
+
alias if isinstance(alias, str) else name,
|
|
143
|
+
getattr(imported_module, name),
|
|
144
|
+
)
|
|
145
|
+
except AttributeError as e:
|
|
146
|
+
if hasattr(imported_module, "__path__"):
|
|
147
|
+
setattr(
|
|
148
|
+
main_module,
|
|
149
|
+
alias if isinstance(alias, str) else name,
|
|
150
|
+
importlib.import_module(f"{target}.{name}"),
|
|
151
|
+
)
|
|
152
|
+
else:
|
|
153
|
+
raise e
|
|
144
154
|
|
|
145
155
|
else:
|
|
146
156
|
setattr(
|
|
@@ -148,5 +158,7 @@ def py_import(
|
|
|
148
158
|
mdl_alias if isinstance(mdl_alias, str) else target,
|
|
149
159
|
imported_module,
|
|
150
160
|
)
|
|
151
|
-
|
|
161
|
+
return imported_module
|
|
162
|
+
except ImportError as e:
|
|
152
163
|
print(f"Failed to import module {target}")
|
|
164
|
+
raise e
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
"""LLM implementations for MTLLM."""
|
|
2
|
+
|
|
3
|
+
from .anthropic import Anthropic
|
|
4
|
+
from .base import BaseLLM
|
|
5
|
+
from .groq import Groq
|
|
6
|
+
from .huggingface import Huggingface
|
|
7
|
+
from .ollama import Ollama
|
|
8
|
+
from .openai import OpenAI
|
|
9
|
+
from .togetherai import TogetherAI
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
__all__ = [
|
|
13
|
+
"Anthropic",
|
|
14
|
+
"Ollama",
|
|
15
|
+
"Huggingface",
|
|
16
|
+
"Groq",
|
|
17
|
+
"BaseLLM",
|
|
18
|
+
"OpenAI",
|
|
19
|
+
"TogetherAI",
|
|
20
|
+
]
|