jaclang 0.7.1__py3-none-any.whl → 0.7.5__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 +2 -2
- jaclang/compiler/absyntree.py +378 -277
- jaclang/compiler/codeloc.py +2 -2
- jaclang/compiler/constant.py +2 -0
- jaclang/compiler/jac.lark +25 -19
- jaclang/compiler/parser.py +115 -92
- jaclang/compiler/passes/main/access_modifier_pass.py +15 -9
- jaclang/compiler/passes/main/def_impl_match_pass.py +29 -11
- jaclang/compiler/passes/main/def_use_pass.py +48 -17
- jaclang/compiler/passes/main/fuse_typeinfo_pass.py +49 -30
- jaclang/compiler/passes/main/import_pass.py +12 -7
- jaclang/compiler/passes/main/pyast_gen_pass.py +110 -47
- jaclang/compiler/passes/main/pyast_load_pass.py +49 -13
- jaclang/compiler/passes/main/pyjac_ast_link_pass.py +25 -11
- jaclang/compiler/passes/main/pyout_pass.py +3 -1
- jaclang/compiler/passes/main/registry_pass.py +6 -6
- jaclang/compiler/passes/main/sym_tab_build_pass.py +30 -72
- jaclang/compiler/passes/main/tests/test_decl_def_match_pass.py +21 -4
- jaclang/compiler/passes/main/tests/test_def_use_pass.py +5 -10
- jaclang/compiler/passes/main/tests/test_import_pass.py +8 -0
- jaclang/compiler/passes/main/tests/test_type_check_pass.py +1 -1
- jaclang/compiler/passes/main/type_check_pass.py +2 -1
- jaclang/compiler/passes/tool/jac_formatter_pass.py +44 -11
- jaclang/compiler/passes/tool/tests/fixtures/corelib.jac +16 -0
- jaclang/compiler/passes/tool/tests/fixtures/corelib_fmt.jac +16 -0
- jaclang/compiler/passes/tool/tests/fixtures/doc_string.jac +15 -0
- jaclang/compiler/passes/tool/tests/test_jac_format_pass.py +7 -5
- jaclang/compiler/passes/tool/tests/test_unparse_validate.py +1 -2
- jaclang/compiler/passes/transform.py +2 -4
- jaclang/{core/registry.py → compiler/semtable.py} +1 -3
- jaclang/compiler/symtable.py +39 -31
- jaclang/compiler/tests/test_parser.py +2 -2
- jaclang/core/aott.py +112 -16
- jaclang/core/{construct.py → architype.py} +44 -93
- jaclang/core/constructs.py +44 -0
- jaclang/core/context.py +157 -0
- jaclang/core/importer.py +18 -9
- jaclang/core/llms/anthropic.py +31 -2
- jaclang/core/llms/base.py +3 -3
- jaclang/core/llms/groq.py +4 -1
- jaclang/core/llms/huggingface.py +4 -1
- jaclang/core/llms/ollama.py +4 -1
- jaclang/core/llms/openai.py +6 -2
- jaclang/core/llms/togetherai.py +4 -1
- jaclang/core/memory.py +53 -2
- jaclang/core/test.py +90 -0
- jaclang/core/utils.py +2 -2
- jaclang/langserve/engine.py +119 -122
- jaclang/langserve/server.py +27 -5
- jaclang/langserve/tests/fixtures/circle.jac +16 -12
- jaclang/langserve/tests/fixtures/circle_err.jac +3 -3
- jaclang/langserve/tests/fixtures/circle_pure.impl.jac +8 -4
- jaclang/langserve/tests/fixtures/circle_pure.jac +2 -2
- jaclang/langserve/tests/test_server.py +114 -0
- jaclang/langserve/utils.py +104 -10
- jaclang/plugin/builtin.py +1 -1
- jaclang/plugin/default.py +46 -90
- jaclang/plugin/feature.py +32 -16
- jaclang/plugin/spec.py +17 -19
- jaclang/plugin/tests/test_features.py +0 -33
- jaclang/settings.py +4 -0
- jaclang/tests/fixtures/abc.jac +16 -12
- jaclang/tests/fixtures/byllmissue.jac +12 -0
- jaclang/tests/fixtures/edgetypetest.jac +16 -0
- jaclang/tests/fixtures/hash_init_check.jac +17 -0
- jaclang/tests/fixtures/impl_match_confused.impl.jac +1 -0
- jaclang/tests/fixtures/impl_match_confused.jac +5 -0
- jaclang/tests/fixtures/math_question.jpg +0 -0
- jaclang/tests/fixtures/maxfail_run_test.jac +17 -5
- jaclang/tests/fixtures/nosigself.jac +19 -0
- jaclang/tests/fixtures/run_test.jac +17 -5
- jaclang/tests/fixtures/walker_override.jac +21 -0
- jaclang/tests/fixtures/with_llm_vision.jac +25 -0
- jaclang/tests/test_bugs.py +19 -0
- jaclang/tests/test_cli.py +1 -1
- jaclang/tests/test_language.py +116 -11
- jaclang/tests/test_reference.py +1 -1
- jaclang/utils/lang_tools.py +5 -4
- jaclang/utils/test.py +2 -1
- jaclang/utils/treeprinter.py +35 -4
- {jaclang-0.7.1.dist-info → jaclang-0.7.5.dist-info}/METADATA +3 -2
- {jaclang-0.7.1.dist-info → jaclang-0.7.5.dist-info}/RECORD +84 -71
- jaclang/core/shelve_storage.py +0 -55
- {jaclang-0.7.1.dist-info → jaclang-0.7.5.dist-info}/WHEEL +0 -0
- {jaclang-0.7.1.dist-info → jaclang-0.7.5.dist-info}/entry_points.txt +0 -0
jaclang/core/context.py
ADDED
|
@@ -0,0 +1,157 @@
|
|
|
1
|
+
"""Core constructs for Jac Language."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
import unittest
|
|
6
|
+
from contextvars import ContextVar
|
|
7
|
+
from typing import Callable, Optional
|
|
8
|
+
from uuid import UUID
|
|
9
|
+
|
|
10
|
+
from .architype import Architype, Root
|
|
11
|
+
from .memory import Memory, ShelveStorage
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
class ExecutionContext:
|
|
15
|
+
"""Default Execution Context implementation."""
|
|
16
|
+
|
|
17
|
+
mem: Optional[Memory]
|
|
18
|
+
root: Optional[Root]
|
|
19
|
+
|
|
20
|
+
def __init__(self) -> None:
|
|
21
|
+
"""Create execution context."""
|
|
22
|
+
super().__init__()
|
|
23
|
+
self.mem = ShelveStorage()
|
|
24
|
+
self.root = None
|
|
25
|
+
|
|
26
|
+
def init_memory(self, session: str = "") -> None:
|
|
27
|
+
"""Initialize memory."""
|
|
28
|
+
if session:
|
|
29
|
+
self.mem = ShelveStorage(session)
|
|
30
|
+
else:
|
|
31
|
+
self.mem = Memory()
|
|
32
|
+
|
|
33
|
+
def get_root(self) -> Root:
|
|
34
|
+
"""Get the root object."""
|
|
35
|
+
if self.mem is None:
|
|
36
|
+
raise ValueError("Memory not initialized")
|
|
37
|
+
|
|
38
|
+
if not self.root:
|
|
39
|
+
root = self.mem.get_obj(UUID(int=0))
|
|
40
|
+
if root is None:
|
|
41
|
+
self.root = Root()
|
|
42
|
+
self.mem.save_obj(self.root, persistent=self.root._jac_.persistent)
|
|
43
|
+
elif not isinstance(root, Root):
|
|
44
|
+
raise ValueError(f"Invalid root object: {root}")
|
|
45
|
+
else:
|
|
46
|
+
self.root = root
|
|
47
|
+
return self.root
|
|
48
|
+
|
|
49
|
+
def get_obj(self, obj_id: UUID) -> Architype | None:
|
|
50
|
+
"""Get object from memory."""
|
|
51
|
+
if self.mem is None:
|
|
52
|
+
raise ValueError("Memory not initialized")
|
|
53
|
+
|
|
54
|
+
return self.mem.get_obj(obj_id)
|
|
55
|
+
|
|
56
|
+
def save_obj(self, item: Architype, persistent: bool) -> None:
|
|
57
|
+
"""Save object to memory."""
|
|
58
|
+
if self.mem is None:
|
|
59
|
+
raise ValueError("Memory not initialized")
|
|
60
|
+
|
|
61
|
+
self.mem.save_obj(item, persistent)
|
|
62
|
+
|
|
63
|
+
def reset(self) -> None:
|
|
64
|
+
"""Reset the execution context."""
|
|
65
|
+
if self.mem:
|
|
66
|
+
self.mem.close()
|
|
67
|
+
self.mem = None
|
|
68
|
+
self.root = None
|
|
69
|
+
|
|
70
|
+
|
|
71
|
+
exec_context: ContextVar[ExecutionContext | None] = ContextVar(
|
|
72
|
+
"ExecutionContext", default=None
|
|
73
|
+
)
|
|
74
|
+
|
|
75
|
+
|
|
76
|
+
class JacTestResult(unittest.TextTestResult):
|
|
77
|
+
"""Jac test result class."""
|
|
78
|
+
|
|
79
|
+
def __init__(
|
|
80
|
+
self,
|
|
81
|
+
stream, # noqa
|
|
82
|
+
descriptions, # noqa
|
|
83
|
+
verbosity: int,
|
|
84
|
+
max_failures: Optional[int] = None,
|
|
85
|
+
) -> None:
|
|
86
|
+
"""Initialize FailFastTestResult object."""
|
|
87
|
+
super().__init__(stream, descriptions, verbosity) # noqa
|
|
88
|
+
self.failures_count = JacTestCheck.failcount
|
|
89
|
+
self.max_failures = max_failures
|
|
90
|
+
|
|
91
|
+
def addFailure(self, test, err) -> None: # noqa
|
|
92
|
+
"""Count failures and stop."""
|
|
93
|
+
super().addFailure(test, err)
|
|
94
|
+
self.failures_count += 1
|
|
95
|
+
if self.max_failures is not None and self.failures_count >= self.max_failures:
|
|
96
|
+
self.stop()
|
|
97
|
+
|
|
98
|
+
def stop(self) -> None:
|
|
99
|
+
"""Stop the test execution."""
|
|
100
|
+
self.shouldStop = True
|
|
101
|
+
|
|
102
|
+
|
|
103
|
+
class JacTextTestRunner(unittest.TextTestRunner):
|
|
104
|
+
"""Jac test runner class."""
|
|
105
|
+
|
|
106
|
+
def __init__(self, max_failures: Optional[int] = None, **kwargs) -> None: # noqa
|
|
107
|
+
"""Initialize JacTextTestRunner object."""
|
|
108
|
+
self.max_failures = max_failures
|
|
109
|
+
super().__init__(**kwargs)
|
|
110
|
+
|
|
111
|
+
def _makeResult(self) -> JacTestResult: # noqa
|
|
112
|
+
"""Override the method to return an instance of JacTestResult."""
|
|
113
|
+
return JacTestResult(
|
|
114
|
+
self.stream,
|
|
115
|
+
self.descriptions,
|
|
116
|
+
self.verbosity,
|
|
117
|
+
max_failures=self.max_failures,
|
|
118
|
+
)
|
|
119
|
+
|
|
120
|
+
|
|
121
|
+
class JacTestCheck:
|
|
122
|
+
"""Jac Testing and Checking."""
|
|
123
|
+
|
|
124
|
+
test_case = unittest.TestCase()
|
|
125
|
+
test_suite = unittest.TestSuite()
|
|
126
|
+
breaker = False
|
|
127
|
+
failcount = 0
|
|
128
|
+
|
|
129
|
+
@staticmethod
|
|
130
|
+
def reset() -> None:
|
|
131
|
+
"""Clear the test suite."""
|
|
132
|
+
JacTestCheck.test_case = unittest.TestCase()
|
|
133
|
+
JacTestCheck.test_suite = unittest.TestSuite()
|
|
134
|
+
|
|
135
|
+
@staticmethod
|
|
136
|
+
def run_test(xit: bool, maxfail: int | None, verbose: bool) -> None:
|
|
137
|
+
"""Run the test suite."""
|
|
138
|
+
verb = 2 if verbose else 1
|
|
139
|
+
runner = JacTextTestRunner(max_failures=maxfail, failfast=xit, verbosity=verb)
|
|
140
|
+
result = runner.run(JacTestCheck.test_suite)
|
|
141
|
+
if result.wasSuccessful():
|
|
142
|
+
print("Passed successfully.")
|
|
143
|
+
else:
|
|
144
|
+
fails = len(result.failures)
|
|
145
|
+
JacTestCheck.failcount += fails
|
|
146
|
+
JacTestCheck.breaker = (
|
|
147
|
+
(JacTestCheck.failcount >= maxfail) if maxfail else True
|
|
148
|
+
)
|
|
149
|
+
|
|
150
|
+
@staticmethod
|
|
151
|
+
def add_test(test_fun: Callable) -> None:
|
|
152
|
+
"""Create a new test."""
|
|
153
|
+
JacTestCheck.test_suite.addTest(unittest.FunctionTestCase(test_fun))
|
|
154
|
+
|
|
155
|
+
def __getattr__(self, name: str) -> object:
|
|
156
|
+
"""Make convenient check.Equal(...) etc."""
|
|
157
|
+
return getattr(JacTestCheck.test_case, name)
|
jaclang/core/importer.py
CHANGED
|
@@ -11,7 +11,6 @@ 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
13
|
from jaclang.core.utils import sys_path_context
|
|
14
|
-
from jaclang.utils.log import logging
|
|
15
14
|
|
|
16
15
|
|
|
17
16
|
def jac_importer(
|
|
@@ -21,7 +20,7 @@ def jac_importer(
|
|
|
21
20
|
cachable: bool = True,
|
|
22
21
|
mdl_alias: Optional[str] = None,
|
|
23
22
|
override_name: Optional[str] = None,
|
|
24
|
-
mod_bundle: Optional[Module] = None,
|
|
23
|
+
mod_bundle: Optional[Module | str] = None,
|
|
25
24
|
lng: Optional[str] = "jac",
|
|
26
25
|
items: Optional[dict[str, Union[str, bool]]] = None,
|
|
27
26
|
) -> Optional[types.ModuleType]:
|
|
@@ -41,6 +40,14 @@ def jac_importer(
|
|
|
41
40
|
elif not override_name and not package_path and module_name in sys.modules:
|
|
42
41
|
return sys.modules[module_name]
|
|
43
42
|
|
|
43
|
+
valid_mod_bundle = (
|
|
44
|
+
sys.modules[mod_bundle].__jac_mod_bundle__
|
|
45
|
+
if isinstance(mod_bundle, str)
|
|
46
|
+
and mod_bundle in sys.modules
|
|
47
|
+
and "__jac_mod_bundle__" in sys.modules[mod_bundle].__dict__
|
|
48
|
+
else mod_bundle
|
|
49
|
+
)
|
|
50
|
+
|
|
44
51
|
caller_dir = get_caller_dir(target, base_path, dir_path)
|
|
45
52
|
full_target = path.normpath(path.join(caller_dir, file_name))
|
|
46
53
|
|
|
@@ -51,10 +58,10 @@ def jac_importer(
|
|
|
51
58
|
else:
|
|
52
59
|
module_name = override_name if override_name else module_name
|
|
53
60
|
module = create_jac_py_module(
|
|
54
|
-
|
|
61
|
+
valid_mod_bundle, module_name, package_path, full_target
|
|
55
62
|
)
|
|
56
|
-
if
|
|
57
|
-
codeobj =
|
|
63
|
+
if valid_mod_bundle:
|
|
64
|
+
codeobj = valid_mod_bundle.mod_deps[full_target].gen.py_bytecode
|
|
58
65
|
codeobj = marshal.loads(codeobj) if isinstance(codeobj, bytes) else None
|
|
59
66
|
else:
|
|
60
67
|
gen_dir = path.join(caller_dir, Con.JAC_GEN_DIR)
|
|
@@ -69,9 +76,8 @@ def jac_importer(
|
|
|
69
76
|
else:
|
|
70
77
|
result = compile_jac(full_target, cache_result=cachable)
|
|
71
78
|
if result.errors_had or not result.ir.gen.py_bytecode:
|
|
72
|
-
for e in result.errors_had:
|
|
73
|
-
|
|
74
|
-
logging.error(e)
|
|
79
|
+
# for e in result.errors_had:
|
|
80
|
+
# print(e)
|
|
75
81
|
return None
|
|
76
82
|
else:
|
|
77
83
|
codeobj = marshal.loads(result.ir.gen.py_bytecode)
|
|
@@ -84,7 +90,10 @@ def jac_importer(
|
|
|
84
90
|
|
|
85
91
|
|
|
86
92
|
def create_jac_py_module(
|
|
87
|
-
mod_bundle: Optional[Module
|
|
93
|
+
mod_bundle: Optional[Module | str],
|
|
94
|
+
module_name: str,
|
|
95
|
+
package_path: str,
|
|
96
|
+
full_target: str,
|
|
88
97
|
) -> types.ModuleType:
|
|
89
98
|
"""Create a module."""
|
|
90
99
|
module = types.ModuleType(module_name)
|
jaclang/core/llms/anthropic.py
CHANGED
|
@@ -45,12 +45,41 @@ class Anthropic(BaseLLM):
|
|
|
45
45
|
self.client = anthropic.Anthropic()
|
|
46
46
|
self.verbose = verbose
|
|
47
47
|
self.max_tries = max_tries
|
|
48
|
-
self.model_name = kwargs.get("model_name", "claude-3-sonnet-20240229")
|
|
48
|
+
self.model_name = str(kwargs.get("model_name", "claude-3-sonnet-20240229"))
|
|
49
49
|
self.temperature = kwargs.get("temperature", 0.7)
|
|
50
50
|
self.max_tokens = kwargs.get("max_tokens", 1024)
|
|
51
51
|
|
|
52
|
-
def __infer__(self, meaning_in: str, **kwargs: dict) -> str:
|
|
52
|
+
def __infer__(self, meaning_in: str | list[dict], **kwargs: dict) -> str:
|
|
53
53
|
"""Infer a response from the input meaning."""
|
|
54
|
+
if not isinstance(meaning_in, str):
|
|
55
|
+
assert self.model_name.startswith(
|
|
56
|
+
("claude-3-opus", "claude-3-sonnet", "claude-3-haiku")
|
|
57
|
+
), f"Model {self.model_name} is not multimodal, use a multimodal model instead."
|
|
58
|
+
|
|
59
|
+
import re
|
|
60
|
+
|
|
61
|
+
formatted_meaning_in = []
|
|
62
|
+
for item in meaning_in:
|
|
63
|
+
if item["type"] == "image_url":
|
|
64
|
+
# "data:image/jpeg;base64,base64_string"
|
|
65
|
+
img_match = re.match(
|
|
66
|
+
r"data:(image/[a-zA-Z]*);base64,(.*)", item["source"]
|
|
67
|
+
)
|
|
68
|
+
if img_match:
|
|
69
|
+
media_type, base64_string = img_match.groups()
|
|
70
|
+
formatted_meaning_in.append(
|
|
71
|
+
{
|
|
72
|
+
"type": "image",
|
|
73
|
+
"source": {
|
|
74
|
+
"type": "base64",
|
|
75
|
+
"media_type": media_type,
|
|
76
|
+
"data": base64_string,
|
|
77
|
+
},
|
|
78
|
+
}
|
|
79
|
+
)
|
|
80
|
+
continue
|
|
81
|
+
formatted_meaning_in.append(item)
|
|
82
|
+
meaning_in = formatted_meaning_in
|
|
54
83
|
messages = [{"role": "user", "content": meaning_in}]
|
|
55
84
|
output = self.client.messages.create(
|
|
56
85
|
model=kwargs.get("model_name", self.model_name),
|
jaclang/core/llms/base.py
CHANGED
|
@@ -112,11 +112,11 @@ class BaseLLM:
|
|
|
112
112
|
self.max_tries = max_tries
|
|
113
113
|
raise NotImplementedError
|
|
114
114
|
|
|
115
|
-
def __infer__(self, meaning_in: str, **kwargs: dict) -> str:
|
|
115
|
+
def __infer__(self, meaning_in: str | list[dict], **kwargs: dict) -> str:
|
|
116
116
|
"""Infer a response from the input meaning."""
|
|
117
117
|
raise NotImplementedError
|
|
118
118
|
|
|
119
|
-
def __call__(self, input_text: str, **kwargs: dict) -> str:
|
|
119
|
+
def __call__(self, input_text: str | list[dict], **kwargs: dict) -> str:
|
|
120
120
|
"""Infer a response from the input text."""
|
|
121
121
|
if self.verbose:
|
|
122
122
|
logger.info(f"Meaning In\n{input_text}")
|
|
@@ -131,7 +131,7 @@ class BaseLLM:
|
|
|
131
131
|
) -> str:
|
|
132
132
|
"""Resolve the output string to return the reasoning and output."""
|
|
133
133
|
if self.verbose:
|
|
134
|
-
logger.
|
|
134
|
+
logger.info(f"Meaning Out\n{meaning_out}")
|
|
135
135
|
output_match = re.search(r"\[Output\](.*)", meaning_out)
|
|
136
136
|
output = output_match.group(1).strip() if output_match else None
|
|
137
137
|
if not output_match:
|
jaclang/core/llms/groq.py
CHANGED
|
@@ -49,8 +49,11 @@ class Groq(BaseLLM):
|
|
|
49
49
|
self.temperature = kwargs.get("temperature", 0.7)
|
|
50
50
|
self.max_tokens = kwargs.get("max_tokens", 1024)
|
|
51
51
|
|
|
52
|
-
def __infer__(self, meaning_in: str, **kwargs: dict) -> str:
|
|
52
|
+
def __infer__(self, meaning_in: str | list[dict], **kwargs: dict) -> str:
|
|
53
53
|
"""Infer a response from the input meaning."""
|
|
54
|
+
assert isinstance(
|
|
55
|
+
meaning_in, str
|
|
56
|
+
), "Currently Multimodal models are not supported. Please provide a string input."
|
|
54
57
|
messages = [{"role": "user", "content": meaning_in}]
|
|
55
58
|
model_params = {
|
|
56
59
|
k: v
|
jaclang/core/llms/huggingface.py
CHANGED
|
@@ -61,8 +61,11 @@ class Huggingface(BaseLLM):
|
|
|
61
61
|
self.temperature = kwargs.get("temperature", 0.7)
|
|
62
62
|
self.max_tokens = kwargs.get("max_new_tokens", 1024)
|
|
63
63
|
|
|
64
|
-
def __infer__(self, meaning_in: str, **kwargs: dict) -> str:
|
|
64
|
+
def __infer__(self, meaning_in: str | list[dict], **kwargs: dict) -> str:
|
|
65
65
|
"""Infer a response from the input meaning."""
|
|
66
|
+
assert isinstance(
|
|
67
|
+
meaning_in, str
|
|
68
|
+
), "Currently Multimodal models are not supported. Please provide a string input."
|
|
66
69
|
messages = [{"role": "user", "content": meaning_in}]
|
|
67
70
|
output = self.pipe(
|
|
68
71
|
messages,
|
jaclang/core/llms/ollama.py
CHANGED
|
@@ -51,8 +51,11 @@ class Ollama(BaseLLM):
|
|
|
51
51
|
k: v for k, v in kwargs.items() if k not in ["model_name", "host"]
|
|
52
52
|
}
|
|
53
53
|
|
|
54
|
-
def __infer__(self, meaning_in: str, **kwargs: dict) -> str:
|
|
54
|
+
def __infer__(self, meaning_in: str | list[dict], **kwargs: dict) -> str:
|
|
55
55
|
"""Infer a response from the input meaning."""
|
|
56
|
+
assert isinstance(
|
|
57
|
+
meaning_in, str
|
|
58
|
+
), "Currently Multimodal models are not supported. Please provide a string input."
|
|
56
59
|
model = str(kwargs.get("model_name", self.model_name))
|
|
57
60
|
if not self.check_model(model):
|
|
58
61
|
self.download_model(model)
|
jaclang/core/llms/openai.py
CHANGED
|
@@ -45,12 +45,16 @@ class OpenAI(BaseLLM):
|
|
|
45
45
|
self.client = openai.OpenAI()
|
|
46
46
|
self.verbose = verbose
|
|
47
47
|
self.max_tries = max_tries
|
|
48
|
-
self.model_name = kwargs.get("model_name", "gpt-3.5-turbo")
|
|
48
|
+
self.model_name = str(kwargs.get("model_name", "gpt-3.5-turbo"))
|
|
49
49
|
self.temperature = kwargs.get("temperature", 0.7)
|
|
50
50
|
self.max_tokens = kwargs.get("max_tokens", 1024)
|
|
51
51
|
|
|
52
|
-
def __infer__(self, meaning_in: str, **kwargs: dict) -> str:
|
|
52
|
+
def __infer__(self, meaning_in: str | list[dict], **kwargs: dict) -> str:
|
|
53
53
|
"""Infer a response from the input meaning."""
|
|
54
|
+
if not isinstance(meaning_in, str):
|
|
55
|
+
assert self.model_name.startswith(
|
|
56
|
+
("gpt-4o", "gpt-4-turbo")
|
|
57
|
+
), f"Model {self.model_name} is not multimodal, use a multimodal model instead."
|
|
54
58
|
messages = [{"role": "user", "content": meaning_in}]
|
|
55
59
|
output = self.client.chat.completions.create(
|
|
56
60
|
model=kwargs.get("model_name", self.model_name),
|
jaclang/core/llms/togetherai.py
CHANGED
|
@@ -48,8 +48,11 @@ class TogetherAI(BaseLLM):
|
|
|
48
48
|
self.temperature = kwargs.get("temperature", 0.7)
|
|
49
49
|
self.max_tokens = kwargs.get("max_tokens", 1024)
|
|
50
50
|
|
|
51
|
-
def __infer__(self, meaning_in: str, **kwargs: dict) -> str:
|
|
51
|
+
def __infer__(self, meaning_in: str | list[dict], **kwargs: dict) -> str:
|
|
52
52
|
"""Infer a response from the input meaning."""
|
|
53
|
+
assert isinstance(
|
|
54
|
+
meaning_in, str
|
|
55
|
+
), "Currently Multimodal models are not supported. Please provide a string input."
|
|
53
56
|
messages = [{"role": "user", "content": meaning_in}]
|
|
54
57
|
output = self.client.chat.completions.create(
|
|
55
58
|
model=kwargs.get("model_name", self.model_name),
|
jaclang/core/memory.py
CHANGED
|
@@ -1,8 +1,11 @@
|
|
|
1
|
-
"""
|
|
1
|
+
"""Core constructs for Jac Language."""
|
|
2
2
|
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
import shelve
|
|
3
6
|
from uuid import UUID
|
|
4
7
|
|
|
5
|
-
from
|
|
8
|
+
from .architype import Architype
|
|
6
9
|
|
|
7
10
|
|
|
8
11
|
class Memory:
|
|
@@ -46,3 +49,51 @@ class Memory:
|
|
|
46
49
|
def close(self) -> None:
|
|
47
50
|
"""Close any connection, if applicable."""
|
|
48
51
|
self.mem.clear()
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
class ShelveStorage(Memory):
|
|
55
|
+
"""Shelve storage for jaclang runtime object."""
|
|
56
|
+
|
|
57
|
+
storage: shelve.Shelf | None = None
|
|
58
|
+
|
|
59
|
+
def __init__(self, session: str = "") -> None:
|
|
60
|
+
"""Init shelve storage."""
|
|
61
|
+
super().__init__()
|
|
62
|
+
if session:
|
|
63
|
+
self.connect(session)
|
|
64
|
+
|
|
65
|
+
def get_obj_from_store(self, obj_id: UUID) -> Architype | None:
|
|
66
|
+
"""Get object from the underlying store."""
|
|
67
|
+
obj = super().get_obj_from_store(obj_id)
|
|
68
|
+
if obj is None and self.storage:
|
|
69
|
+
obj = self.storage.get(str(obj_id))
|
|
70
|
+
if obj is not None:
|
|
71
|
+
self.mem[obj_id] = obj
|
|
72
|
+
|
|
73
|
+
return obj
|
|
74
|
+
|
|
75
|
+
def has_obj_in_store(self, obj_id: UUID | str) -> bool:
|
|
76
|
+
"""Check if the object exists in the underlying store."""
|
|
77
|
+
return obj_id in self.mem or (
|
|
78
|
+
str(obj_id) in self.storage if self.storage else False
|
|
79
|
+
)
|
|
80
|
+
|
|
81
|
+
def commit(self) -> None:
|
|
82
|
+
"""Commit changes to persistent storage."""
|
|
83
|
+
if self.storage is not None:
|
|
84
|
+
for obj_id, obj in self.save_obj_list.items():
|
|
85
|
+
self.storage[str(obj_id)] = obj
|
|
86
|
+
self.save_obj_list.clear()
|
|
87
|
+
|
|
88
|
+
def connect(self, session: str) -> None:
|
|
89
|
+
"""Connect to storage."""
|
|
90
|
+
self.session = session
|
|
91
|
+
self.storage = shelve.open(session)
|
|
92
|
+
|
|
93
|
+
def close(self) -> None:
|
|
94
|
+
"""Close the storage."""
|
|
95
|
+
super().close()
|
|
96
|
+
self.commit()
|
|
97
|
+
if self.storage:
|
|
98
|
+
self.storage.close()
|
|
99
|
+
self.storage = None
|
jaclang/core/test.py
ADDED
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
"""Core constructs for Jac Language."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
import unittest
|
|
6
|
+
from typing import Callable, Optional
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
class JacTestResult(unittest.TextTestResult):
|
|
10
|
+
"""Jac test result class."""
|
|
11
|
+
|
|
12
|
+
def __init__(
|
|
13
|
+
self,
|
|
14
|
+
stream, # noqa
|
|
15
|
+
descriptions, # noqa
|
|
16
|
+
verbosity: int,
|
|
17
|
+
max_failures: Optional[int] = None,
|
|
18
|
+
) -> None:
|
|
19
|
+
"""Initialize FailFastTestResult object."""
|
|
20
|
+
super().__init__(stream, descriptions, verbosity) # noqa
|
|
21
|
+
self.failures_count = JacTestCheck.failcount
|
|
22
|
+
self.max_failures = max_failures
|
|
23
|
+
|
|
24
|
+
def addFailure(self, test, err) -> None: # noqa
|
|
25
|
+
"""Count failures and stop."""
|
|
26
|
+
super().addFailure(test, err)
|
|
27
|
+
self.failures_count += 1
|
|
28
|
+
if self.max_failures is not None and self.failures_count >= self.max_failures:
|
|
29
|
+
self.stop()
|
|
30
|
+
|
|
31
|
+
def stop(self) -> None:
|
|
32
|
+
"""Stop the test execution."""
|
|
33
|
+
self.shouldStop = True
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
class JacTextTestRunner(unittest.TextTestRunner):
|
|
37
|
+
"""Jac test runner class."""
|
|
38
|
+
|
|
39
|
+
def __init__(self, max_failures: Optional[int] = None, **kwargs) -> None: # noqa
|
|
40
|
+
"""Initialize JacTextTestRunner object."""
|
|
41
|
+
self.max_failures = max_failures
|
|
42
|
+
super().__init__(**kwargs)
|
|
43
|
+
|
|
44
|
+
def _makeResult(self) -> JacTestResult: # noqa
|
|
45
|
+
"""Override the method to return an instance of JacTestResult."""
|
|
46
|
+
return JacTestResult(
|
|
47
|
+
self.stream,
|
|
48
|
+
self.descriptions,
|
|
49
|
+
self.verbosity,
|
|
50
|
+
max_failures=self.max_failures,
|
|
51
|
+
)
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
class JacTestCheck:
|
|
55
|
+
"""Jac Testing and Checking."""
|
|
56
|
+
|
|
57
|
+
test_case = unittest.TestCase()
|
|
58
|
+
test_suite = unittest.TestSuite()
|
|
59
|
+
breaker = False
|
|
60
|
+
failcount = 0
|
|
61
|
+
|
|
62
|
+
@staticmethod
|
|
63
|
+
def reset() -> None:
|
|
64
|
+
"""Clear the test suite."""
|
|
65
|
+
JacTestCheck.test_case = unittest.TestCase()
|
|
66
|
+
JacTestCheck.test_suite = unittest.TestSuite()
|
|
67
|
+
|
|
68
|
+
@staticmethod
|
|
69
|
+
def run_test(xit: bool, maxfail: int | None, verbose: bool) -> None:
|
|
70
|
+
"""Run the test suite."""
|
|
71
|
+
verb = 2 if verbose else 1
|
|
72
|
+
runner = JacTextTestRunner(max_failures=maxfail, failfast=xit, verbosity=verb)
|
|
73
|
+
result = runner.run(JacTestCheck.test_suite)
|
|
74
|
+
if result.wasSuccessful():
|
|
75
|
+
print("Passed successfully.")
|
|
76
|
+
else:
|
|
77
|
+
fails = len(result.failures)
|
|
78
|
+
JacTestCheck.failcount += fails
|
|
79
|
+
JacTestCheck.breaker = (
|
|
80
|
+
(JacTestCheck.failcount >= maxfail) if maxfail else True
|
|
81
|
+
)
|
|
82
|
+
|
|
83
|
+
@staticmethod
|
|
84
|
+
def add_test(test_fun: Callable) -> None:
|
|
85
|
+
"""Create a new test."""
|
|
86
|
+
JacTestCheck.test_suite.addTest(unittest.FunctionTestCase(test_fun))
|
|
87
|
+
|
|
88
|
+
def __getattr__(self, name: str) -> object:
|
|
89
|
+
"""Make convenient check.Equal(...) etc."""
|
|
90
|
+
return getattr(JacTestCheck.test_case, name)
|
jaclang/core/utils.py
CHANGED
|
@@ -8,10 +8,10 @@ from contextlib import contextmanager
|
|
|
8
8
|
from typing import Callable, Iterator, TYPE_CHECKING
|
|
9
9
|
|
|
10
10
|
import jaclang.compiler.absyntree as ast
|
|
11
|
-
from jaclang.
|
|
11
|
+
from jaclang.compiler.semtable import SemScope
|
|
12
12
|
|
|
13
13
|
if TYPE_CHECKING:
|
|
14
|
-
from jaclang.core.
|
|
14
|
+
from jaclang.core.constructs import NodeAnchor, NodeArchitype
|
|
15
15
|
|
|
16
16
|
|
|
17
17
|
@contextmanager
|