janus-llm 4.2.0__py3-none-any.whl → 4.3.5__py3-none-any.whl
Sign up to get free protection for your applications and to get access to all the features.
- janus/__init__.py +1 -1
- janus/__main__.py +1 -1
- janus/_tests/evaluator_tests/EvalReadMe.md +85 -0
- janus/_tests/evaluator_tests/incose_tests/incose_large_test.json +39 -0
- janus/_tests/evaluator_tests/incose_tests/incose_small_test.json +17 -0
- janus/_tests/evaluator_tests/inline_comment_tests/mumps_inline_comment_test.m +71 -0
- janus/_tests/test_cli.py +3 -2
- janus/cli/aggregate.py +135 -0
- janus/cli/cli.py +111 -0
- janus/cli/constants.py +43 -0
- janus/cli/database.py +289 -0
- janus/cli/diagram.py +178 -0
- janus/cli/document.py +174 -0
- janus/cli/embedding.py +122 -0
- janus/cli/llm.py +187 -0
- janus/cli/partition.py +125 -0
- janus/cli/self_eval.py +149 -0
- janus/cli/translate.py +183 -0
- janus/converter/__init__.py +1 -1
- janus/converter/_tests/test_translate.py +2 -0
- janus/converter/converter.py +129 -92
- janus/converter/document.py +21 -14
- janus/converter/evaluate.py +237 -4
- janus/converter/translate.py +3 -3
- janus/embedding/collections.py +1 -1
- janus/language/alc/_tests/alc.asm +3779 -0
- janus/language/alc/_tests/test_alc.py +1 -1
- janus/language/alc/alc.py +9 -4
- janus/language/binary/_tests/hello.bin +0 -0
- janus/language/block.py +47 -12
- janus/language/file.py +1 -1
- janus/language/mumps/_tests/mumps.m +235 -0
- janus/language/splitter.py +31 -23
- janus/language/treesitter/_tests/languages/fortran.f90 +416 -0
- janus/language/treesitter/_tests/languages/ibmhlasm.asm +16 -0
- janus/language/treesitter/_tests/languages/matlab.m +225 -0
- janus/language/treesitter/treesitter.py +9 -1
- janus/llm/models_info.py +26 -13
- janus/metrics/_tests/asm_test_file.asm +10 -0
- janus/metrics/_tests/mumps_test_file.m +6 -0
- janus/metrics/_tests/test_treesitter_metrics.py +1 -1
- janus/metrics/prompts/clarity.txt +8 -0
- janus/metrics/prompts/completeness.txt +16 -0
- janus/metrics/prompts/faithfulness.txt +10 -0
- janus/metrics/prompts/hallucination.txt +16 -0
- janus/metrics/prompts/quality.txt +8 -0
- janus/metrics/prompts/readability.txt +16 -0
- janus/metrics/prompts/usefulness.txt +16 -0
- janus/parsers/code_parser.py +4 -4
- janus/parsers/doc_parser.py +12 -9
- janus/parsers/eval_parsers/incose_parser.py +134 -0
- janus/parsers/eval_parsers/inline_comment_parser.py +112 -0
- janus/parsers/parser.py +7 -0
- janus/parsers/partition_parser.py +47 -13
- janus/parsers/reqs_parser.py +8 -5
- janus/parsers/uml.py +5 -4
- janus/prompts/prompt.py +2 -2
- janus/prompts/templates/README.md +30 -0
- janus/prompts/templates/basic_aggregation/human.txt +6 -0
- janus/prompts/templates/basic_aggregation/system.txt +1 -0
- janus/prompts/templates/basic_refinement/human.txt +14 -0
- janus/prompts/templates/basic_refinement/system.txt +1 -0
- janus/prompts/templates/diagram/human.txt +9 -0
- janus/prompts/templates/diagram/system.txt +1 -0
- janus/prompts/templates/diagram_with_documentation/human.txt +15 -0
- janus/prompts/templates/diagram_with_documentation/system.txt +1 -0
- janus/prompts/templates/document/human.txt +10 -0
- janus/prompts/templates/document/system.txt +1 -0
- janus/prompts/templates/document_cloze/human.txt +11 -0
- janus/prompts/templates/document_cloze/system.txt +1 -0
- janus/prompts/templates/document_cloze/variables.json +4 -0
- janus/prompts/templates/document_cloze/variables_asm.json +4 -0
- janus/prompts/templates/document_inline/human.txt +13 -0
- janus/prompts/templates/eval_prompts/incose/human.txt +32 -0
- janus/prompts/templates/eval_prompts/incose/system.txt +1 -0
- janus/prompts/templates/eval_prompts/incose/variables.json +3 -0
- janus/prompts/templates/eval_prompts/inline_comments/human.txt +49 -0
- janus/prompts/templates/eval_prompts/inline_comments/system.txt +1 -0
- janus/prompts/templates/eval_prompts/inline_comments/variables.json +3 -0
- janus/prompts/templates/micromanaged_mumps_v1.0/human.txt +23 -0
- janus/prompts/templates/micromanaged_mumps_v1.0/system.txt +3 -0
- janus/prompts/templates/micromanaged_mumps_v2.0/human.txt +28 -0
- janus/prompts/templates/micromanaged_mumps_v2.0/system.txt +3 -0
- janus/prompts/templates/micromanaged_mumps_v2.1/human.txt +29 -0
- janus/prompts/templates/micromanaged_mumps_v2.1/system.txt +3 -0
- janus/prompts/templates/multidocument/human.txt +15 -0
- janus/prompts/templates/multidocument/system.txt +1 -0
- janus/prompts/templates/partition/human.txt +22 -0
- janus/prompts/templates/partition/system.txt +1 -0
- janus/prompts/templates/partition/variables.json +4 -0
- janus/prompts/templates/pseudocode/human.txt +7 -0
- janus/prompts/templates/pseudocode/system.txt +7 -0
- janus/prompts/templates/refinement/fix_exceptions/human.txt +19 -0
- janus/prompts/templates/refinement/fix_exceptions/system.txt +1 -0
- janus/prompts/templates/refinement/format/code_format/human.txt +12 -0
- janus/prompts/templates/refinement/format/code_format/system.txt +1 -0
- janus/prompts/templates/refinement/format/requirements_format/human.txt +14 -0
- janus/prompts/templates/refinement/format/requirements_format/system.txt +1 -0
- janus/prompts/templates/refinement/hallucination/human.txt +13 -0
- janus/prompts/templates/refinement/hallucination/system.txt +1 -0
- janus/prompts/templates/refinement/reflection/human.txt +15 -0
- janus/prompts/templates/refinement/reflection/incose/human.txt +26 -0
- janus/prompts/templates/refinement/reflection/incose/system.txt +1 -0
- janus/prompts/templates/refinement/reflection/incose_deduplicate/human.txt +16 -0
- janus/prompts/templates/refinement/reflection/incose_deduplicate/system.txt +1 -0
- janus/prompts/templates/refinement/reflection/system.txt +1 -0
- janus/prompts/templates/refinement/revision/human.txt +16 -0
- janus/prompts/templates/refinement/revision/incose/human.txt +16 -0
- janus/prompts/templates/refinement/revision/incose/system.txt +1 -0
- janus/prompts/templates/refinement/revision/incose_deduplicate/human.txt +17 -0
- janus/prompts/templates/refinement/revision/incose_deduplicate/system.txt +1 -0
- janus/prompts/templates/refinement/revision/system.txt +1 -0
- janus/prompts/templates/refinement/uml/alc_fix_variables/human.txt +15 -0
- janus/prompts/templates/refinement/uml/alc_fix_variables/system.txt +2 -0
- janus/prompts/templates/refinement/uml/fix_connections/human.txt +15 -0
- janus/prompts/templates/refinement/uml/fix_connections/system.txt +2 -0
- janus/prompts/templates/requirements/human.txt +13 -0
- janus/prompts/templates/requirements/system.txt +2 -0
- janus/prompts/templates/retrieval/language_docs/human.txt +10 -0
- janus/prompts/templates/retrieval/language_docs/system.txt +1 -0
- janus/prompts/templates/simple/human.txt +16 -0
- janus/prompts/templates/simple/system.txt +3 -0
- janus/refiners/format.py +49 -0
- janus/refiners/refiner.py +143 -4
- janus/utils/enums.py +140 -111
- janus/utils/logger.py +2 -0
- {janus_llm-4.2.0.dist-info → janus_llm-4.3.5.dist-info}/METADATA +7 -7
- janus_llm-4.3.5.dist-info/RECORD +210 -0
- {janus_llm-4.2.0.dist-info → janus_llm-4.3.5.dist-info}/WHEEL +1 -1
- janus_llm-4.3.5.dist-info/entry_points.txt +3 -0
- janus/cli.py +0 -1343
- janus_llm-4.2.0.dist-info/RECORD +0 -113
- janus_llm-4.2.0.dist-info/entry_points.txt +0 -3
- {janus_llm-4.2.0.dist-info → janus_llm-4.3.5.dist-info}/LICENSE +0 -0
janus/converter/evaluate.py
CHANGED
@@ -1,15 +1,248 @@
|
|
1
|
+
import json
|
2
|
+
import re
|
3
|
+
from copy import deepcopy
|
4
|
+
|
5
|
+
from langchain_core.runnables import Runnable, RunnableLambda, RunnableParallel
|
6
|
+
|
1
7
|
from janus.converter.converter import Converter
|
8
|
+
from janus.language.block import TranslatedCodeBlock
|
2
9
|
from janus.language.combine import JsonCombiner
|
3
|
-
from janus.parsers.
|
10
|
+
from janus.parsers.eval_parsers.incose_parser import IncoseParser
|
11
|
+
from janus.parsers.eval_parsers.inline_comment_parser import InlineCommentParser
|
12
|
+
from janus.parsers.parser import JanusParserException
|
4
13
|
from janus.utils.logger import create_logger
|
5
14
|
|
6
15
|
log = create_logger(__name__)
|
7
16
|
|
8
17
|
|
9
18
|
class Evaluator(Converter):
|
10
|
-
|
19
|
+
"""Evaluator
|
20
|
+
|
21
|
+
A class that performs an LLM self evaluation"
|
22
|
+
"on an input target, with an associated prompt.
|
23
|
+
|
24
|
+
Current valid evaluation types:
|
25
|
+
['incose', 'comments']
|
26
|
+
|
27
|
+
"""
|
28
|
+
|
29
|
+
def __init__(self, **kwargs) -> None:
|
30
|
+
"""Initialize the Evaluator class
|
31
|
+
|
32
|
+
Arguments:
|
33
|
+
model: The LLM to use for translation. If an OpenAI model, the
|
34
|
+
`OPENAI_API_KEY` environment variable must be set.
|
35
|
+
model_arguments: Additional arguments to pass to the LLM constructor.
|
36
|
+
max_prompts: The maximum number of prompts to try before giving up.
|
37
|
+
"""
|
11
38
|
super().__init__(**kwargs)
|
12
|
-
self.set_prompt("evaluate")
|
13
39
|
self._combiner = JsonCombiner()
|
14
|
-
self._parser = EvaluationParser()
|
15
40
|
self._load_parameters()
|
41
|
+
|
42
|
+
|
43
|
+
class RequirementEvaluator(Evaluator):
|
44
|
+
"""INCOSE Requirement Evaluator
|
45
|
+
|
46
|
+
A class that performs an LLM self evaluation on an input target,
|
47
|
+
with an associated prompt.
|
48
|
+
|
49
|
+
The evaluation prompts are for Incose Evaluations
|
50
|
+
|
51
|
+
"""
|
52
|
+
|
53
|
+
def __init__(self, eval_items_per_request: int | None = None, **kwargs) -> None:
|
54
|
+
"""Initialize the Evaluator class
|
55
|
+
|
56
|
+
Arguments:
|
57
|
+
model: The LLM to use for translation. If an OpenAI model, the
|
58
|
+
`OPENAI_API_KEY` environment variable must be set.
|
59
|
+
model_arguments: Additional arguments to pass to the LLM constructor.
|
60
|
+
max_prompts: The maximum number of prompts to try before giving up.
|
61
|
+
"""
|
62
|
+
super().__init__(**kwargs)
|
63
|
+
self.eval_items_per_request = eval_items_per_request
|
64
|
+
self._parser = IncoseParser()
|
65
|
+
self.set_prompt("eval_prompts/incose")
|
66
|
+
|
67
|
+
def _input_runnable(self) -> Runnable:
|
68
|
+
def _get_code(json_text: str) -> str:
|
69
|
+
return json.loads(json_text)["code"]
|
70
|
+
|
71
|
+
def _get_reqs(json_text: str) -> str:
|
72
|
+
return json.dumps(json.loads(json_text)["requirements"])
|
73
|
+
|
74
|
+
return RunnableLambda(self._parser.parse_input) | RunnableParallel(
|
75
|
+
SOURCE_CODE=_get_code,
|
76
|
+
REQUIREMENTS=_get_reqs,
|
77
|
+
context=self._retriever,
|
78
|
+
)
|
79
|
+
|
80
|
+
def _add_translation(self, block: TranslatedCodeBlock):
|
81
|
+
if block.translated:
|
82
|
+
return
|
83
|
+
|
84
|
+
if block.original.text is None:
|
85
|
+
block.translated = True
|
86
|
+
return
|
87
|
+
|
88
|
+
if self.eval_items_per_request is None:
|
89
|
+
return super()._add_translation(block)
|
90
|
+
|
91
|
+
input_obj = json.loads(block.original.text)
|
92
|
+
requirements = input_obj.get("requirements", [])
|
93
|
+
|
94
|
+
if not requirements:
|
95
|
+
log.debug(f"[{block.name}] Skipping empty block")
|
96
|
+
block.translated = True
|
97
|
+
block.text = None
|
98
|
+
block.complete = True
|
99
|
+
return
|
100
|
+
|
101
|
+
# For some reason requirements objects are in nested lists?
|
102
|
+
while isinstance(requirements[0], list):
|
103
|
+
requirements = [r for lst in requirements for r in lst]
|
104
|
+
|
105
|
+
if len(requirements) <= self.eval_items_per_request:
|
106
|
+
input_obj["requirements"] = requirements
|
107
|
+
block.original.text = json.dumps(input_obj)
|
108
|
+
return super()._add_translation(block)
|
109
|
+
|
110
|
+
block.processing_time = 0
|
111
|
+
block.cost = 0
|
112
|
+
obj = {}
|
113
|
+
for i in range(0, len(requirements), self.eval_items_per_request):
|
114
|
+
# Build a new TranslatedBlock using the new working text
|
115
|
+
working_requirements = requirements[i : i + self.eval_items_per_request]
|
116
|
+
working_copy = deepcopy(block.original)
|
117
|
+
working_obj = json.loads(working_copy.text) # type: ignore
|
118
|
+
working_obj["requirements"] = working_requirements
|
119
|
+
working_copy.text = json.dumps(working_obj)
|
120
|
+
working_block = TranslatedCodeBlock(working_copy, self._target_language)
|
121
|
+
|
122
|
+
# Run the LLM on the working text
|
123
|
+
try:
|
124
|
+
super()._add_translation(working_block)
|
125
|
+
except JanusParserException as e:
|
126
|
+
block.text += "\n==============\n" + working_block.text
|
127
|
+
block.tokens = self._llm.get_num_tokens(block.text)
|
128
|
+
raise e
|
129
|
+
finally:
|
130
|
+
# Update metadata to include for all runs
|
131
|
+
block.num_requests += working_block.num_requests
|
132
|
+
block.cost += working_block.cost
|
133
|
+
block.processing_time += working_block.processing_time
|
134
|
+
block.request_input_tokens += working_block.request_input_tokens
|
135
|
+
block.request_output_tokens += working_block.request_output_tokens
|
136
|
+
|
137
|
+
# Update the output text to merge this section's output in
|
138
|
+
obj.update(json.loads(working_block.text))
|
139
|
+
# intermediate result of block,
|
140
|
+
# will be overwritten if file completes successfully
|
141
|
+
block.text = json.dumps(obj)
|
142
|
+
|
143
|
+
block.text = json.dumps(obj)
|
144
|
+
block.tokens = self._llm.get_num_tokens(block.text)
|
145
|
+
block.translated = True
|
146
|
+
|
147
|
+
log.debug(
|
148
|
+
f"[{block.name}] Output code:\n{json.dumps(json.loads(block.text), indent=2)}"
|
149
|
+
)
|
150
|
+
|
151
|
+
|
152
|
+
class InlineCommentEvaluator(Evaluator):
|
153
|
+
"""Inline Comment Evaluator
|
154
|
+
|
155
|
+
A class that performs an LLM self evaluation on inline comments,
|
156
|
+
with an associated prompt.
|
157
|
+
"""
|
158
|
+
|
159
|
+
def __init__(self, eval_items_per_request: int | None = None, **kwargs) -> None:
|
160
|
+
"""Initialize the Evaluator class
|
161
|
+
|
162
|
+
Arguments:
|
163
|
+
model: The LLM to use for translation. If an OpenAI model, the
|
164
|
+
`OPENAI_API_KEY` environment variable must be set.
|
165
|
+
model_arguments: Additional arguments to pass to the LLM constructor.
|
166
|
+
max_prompts: The maximum number of prompts to try before giving up.
|
167
|
+
"""
|
168
|
+
super().__init__(**kwargs)
|
169
|
+
self._combiner = JsonCombiner()
|
170
|
+
self._load_parameters()
|
171
|
+
self._parser = InlineCommentParser()
|
172
|
+
self.set_prompt("eval_prompts/inline_comments")
|
173
|
+
self.eval_items_per_request = eval_items_per_request
|
174
|
+
|
175
|
+
def _add_translation(self, block: TranslatedCodeBlock):
|
176
|
+
if block.translated:
|
177
|
+
return
|
178
|
+
|
179
|
+
if block.original.text is None:
|
180
|
+
block.translated = True
|
181
|
+
return
|
182
|
+
|
183
|
+
if self.eval_items_per_request is None:
|
184
|
+
return super()._add_translation(block)
|
185
|
+
|
186
|
+
comment_pattern = r"<(?:INLINE|BLOCK)_COMMENT \w{8}>.*$"
|
187
|
+
comments = list(
|
188
|
+
re.finditer(comment_pattern, block.original.text, flags=re.MULTILINE)
|
189
|
+
)
|
190
|
+
|
191
|
+
if not comments:
|
192
|
+
log.info(f"[{block.name}] Skipping commentless block")
|
193
|
+
block.translated = True
|
194
|
+
block.text = None
|
195
|
+
block.complete = True
|
196
|
+
return
|
197
|
+
|
198
|
+
if len(comments) <= self.eval_items_per_request:
|
199
|
+
return super()._add_translation(block)
|
200
|
+
|
201
|
+
comment_group_indices = list(range(0, len(comments), self.eval_items_per_request))
|
202
|
+
log.debug(
|
203
|
+
f"[{block.name}] Block contains more than {self.eval_items_per_request}"
|
204
|
+
f" comments, splitting {len(comments)} comments into"
|
205
|
+
f" {len(comment_group_indices)} groups"
|
206
|
+
)
|
207
|
+
|
208
|
+
block.processing_time = 0
|
209
|
+
block.cost = 0
|
210
|
+
block.retries = 0
|
211
|
+
obj = {}
|
212
|
+
for i in range(0, len(comments), self.eval_items_per_request):
|
213
|
+
# Split the text into the section containing comments of interest,
|
214
|
+
# all the text prior to those comments, and all the text after them
|
215
|
+
working_comments = comments[i : i + self.eval_items_per_request]
|
216
|
+
start_idx = working_comments[0].start()
|
217
|
+
end_idx = working_comments[-1].end()
|
218
|
+
prefix = block.original.text[:start_idx]
|
219
|
+
keeper = block.original.text[start_idx:end_idx]
|
220
|
+
suffix = block.original.text[end_idx:]
|
221
|
+
|
222
|
+
# Strip all comment placeholders outside of the section of interest
|
223
|
+
prefix = re.sub(comment_pattern, "", prefix, flags=re.MULTILINE)
|
224
|
+
suffix = re.sub(comment_pattern, "", suffix, flags=re.MULTILINE)
|
225
|
+
|
226
|
+
# Build a new TranslatedBlock using the new working text
|
227
|
+
working_copy = deepcopy(block.original)
|
228
|
+
working_copy.text = prefix + keeper + suffix
|
229
|
+
working_block = TranslatedCodeBlock(working_copy, self._target_language)
|
230
|
+
|
231
|
+
# Run the LLM on the working text
|
232
|
+
super()._add_translation(working_block)
|
233
|
+
|
234
|
+
# Update metadata to include for all runs
|
235
|
+
block.retries += working_block.retries
|
236
|
+
block.cost += working_block.cost
|
237
|
+
block.processing_time += working_block.processing_time
|
238
|
+
|
239
|
+
# Update the output text to merge this section's output in
|
240
|
+
obj.update(json.loads(working_block.text))
|
241
|
+
|
242
|
+
block.text = json.dumps(obj)
|
243
|
+
block.tokens = self._llm.get_num_tokens(block.text)
|
244
|
+
block.translated = True
|
245
|
+
|
246
|
+
log.debug(
|
247
|
+
f"[{block.name}] Output code:\n{json.dumps(json.loads(block.text), indent=2)}"
|
248
|
+
)
|
janus/converter/translate.py
CHANGED
@@ -21,8 +21,7 @@ class Translator(Converter):
|
|
21
21
|
|
22
22
|
Arguments:
|
23
23
|
model: The LLM to use for translation. If an OpenAI model, the
|
24
|
-
`OPENAI_API_KEY` environment variable must be set
|
25
|
-
`OPENAI_ORG_ID` environment variable should be set if needed.
|
24
|
+
`OPENAI_API_KEY` environment variable must be set.
|
26
25
|
model_arguments: Additional arguments to pass to the LLM constructor.
|
27
26
|
source_language: The source programming language.
|
28
27
|
target_language: The target programming language.
|
@@ -67,7 +66,8 @@ class Translator(Converter):
|
|
67
66
|
)
|
68
67
|
self._target_language = target_language
|
69
68
|
self._target_version = target_version
|
70
|
-
|
69
|
+
# Taking the first suffix as the default for output files
|
70
|
+
self._target_suffix = f".{LANGUAGES[target_language]['suffixes'][0]}"
|
71
71
|
|
72
72
|
@run_if_changed(
|
73
73
|
"_prompt_template_name",
|
janus/embedding/collections.py
CHANGED
@@ -87,7 +87,7 @@ class Collections:
|
|
87
87
|
"""Get the Chroma collections.
|
88
88
|
|
89
89
|
Returns:
|
90
|
-
The Chroma collections. Raises
|
90
|
+
The Chroma collections. Raises InvalidCollectionException if not found.
|
91
91
|
"""
|
92
92
|
if isinstance(name, str):
|
93
93
|
return [self._client.get_collection(name)]
|