langfun 0.0.2.dev20240429__py3-none-any.whl → 0.1.2.dev202501140804__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.
- langfun/__init__.py +20 -2
- langfun/core/__init__.py +16 -5
- langfun/core/agentic/__init__.py +30 -0
- langfun/core/agentic/action.py +854 -0
- langfun/core/agentic/action_eval.py +150 -0
- langfun/core/agentic/action_eval_test.py +109 -0
- langfun/core/agentic/action_test.py +136 -0
- langfun/core/coding/python/__init__.py +5 -11
- langfun/core/coding/python/correction.py +37 -21
- langfun/core/coding/python/correction_test.py +29 -3
- langfun/core/coding/python/execution.py +40 -216
- langfun/core/coding/python/execution_test.py +29 -89
- langfun/core/coding/python/generation.py +21 -11
- langfun/core/coding/python/generation_test.py +2 -2
- langfun/core/coding/python/parsing.py +108 -193
- langfun/core/coding/python/parsing_test.py +2 -105
- langfun/core/component.py +63 -2
- langfun/core/component_test.py +53 -0
- langfun/core/concurrent.py +414 -117
- langfun/core/concurrent_test.py +111 -24
- langfun/core/console.py +18 -5
- langfun/core/console_test.py +17 -0
- langfun/core/eval/__init__.py +16 -1
- langfun/core/eval/base.py +622 -174
- langfun/core/eval/base_test.py +200 -54
- langfun/core/eval/matching.py +63 -76
- langfun/core/eval/matching_test.py +17 -8
- langfun/core/eval/patching.py +130 -0
- langfun/core/eval/patching_test.py +170 -0
- langfun/core/eval/scoring.py +26 -26
- langfun/core/eval/scoring_test.py +19 -2
- langfun/core/eval/v2/__init__.py +42 -0
- langfun/core/eval/v2/checkpointing.py +380 -0
- langfun/core/eval/v2/checkpointing_test.py +228 -0
- langfun/core/eval/v2/eval_test_helper.py +136 -0
- langfun/core/eval/v2/evaluation.py +725 -0
- langfun/core/eval/v2/evaluation_test.py +180 -0
- langfun/core/eval/v2/example.py +305 -0
- langfun/core/eval/v2/example_test.py +128 -0
- langfun/core/eval/v2/experiment.py +1048 -0
- langfun/core/eval/v2/experiment_test.py +433 -0
- langfun/core/eval/v2/metric_values.py +156 -0
- langfun/core/eval/v2/metric_values_test.py +80 -0
- langfun/core/eval/v2/metrics.py +357 -0
- langfun/core/eval/v2/metrics_test.py +203 -0
- langfun/core/eval/v2/progress.py +348 -0
- langfun/core/eval/v2/progress_test.py +82 -0
- langfun/core/eval/v2/progress_tracking.py +210 -0
- langfun/core/eval/v2/progress_tracking_test.py +66 -0
- langfun/core/eval/v2/reporting.py +270 -0
- langfun/core/eval/v2/reporting_test.py +158 -0
- langfun/core/eval/v2/runners.py +488 -0
- langfun/core/eval/v2/runners_test.py +334 -0
- langfun/core/langfunc.py +4 -17
- langfun/core/langfunc_test.py +22 -6
- langfun/core/language_model.py +577 -39
- langfun/core/language_model_test.py +470 -56
- langfun/core/llms/__init__.py +87 -16
- langfun/core/llms/anthropic.py +312 -87
- langfun/core/llms/anthropic_test.py +71 -3
- langfun/core/llms/cache/base.py +21 -2
- langfun/core/llms/cache/in_memory.py +13 -0
- langfun/core/llms/cache/in_memory_test.py +53 -2
- langfun/core/llms/compositional.py +101 -0
- langfun/core/llms/compositional_test.py +73 -0
- langfun/core/llms/deepseek.py +117 -0
- langfun/core/llms/deepseek_test.py +61 -0
- langfun/core/llms/fake.py +11 -7
- langfun/core/llms/fake_test.py +14 -0
- langfun/core/llms/gemini.py +507 -0
- langfun/core/llms/gemini_test.py +195 -0
- langfun/core/llms/google_genai.py +62 -218
- langfun/core/llms/google_genai_test.py +9 -202
- langfun/core/llms/groq.py +160 -144
- langfun/core/llms/groq_test.py +31 -137
- langfun/core/llms/llama_cpp.py +15 -42
- langfun/core/llms/llama_cpp_test.py +4 -30
- langfun/core/llms/openai.py +395 -203
- langfun/core/llms/openai_compatible.py +179 -0
- langfun/core/llms/openai_compatible_test.py +495 -0
- langfun/core/llms/openai_test.py +30 -395
- langfun/core/llms/rest.py +113 -0
- langfun/core/llms/rest_test.py +111 -0
- langfun/core/llms/vertexai.py +192 -0
- langfun/core/llms/vertexai_test.py +52 -0
- langfun/core/logging.py +284 -0
- langfun/core/logging_test.py +125 -0
- langfun/core/message.py +319 -9
- langfun/core/message_test.py +190 -13
- langfun/core/modalities/__init__.py +6 -2
- langfun/core/modalities/audio.py +30 -0
- langfun/core/modalities/audio_test.py +63 -0
- langfun/core/modalities/image.py +39 -20
- langfun/core/modalities/image_test.py +52 -9
- langfun/core/modalities/mime.py +206 -29
- langfun/core/modalities/mime_test.py +90 -9
- langfun/core/modalities/ms_office.py +117 -0
- langfun/core/modalities/ms_office_test.py +389 -0
- langfun/core/modalities/pdf.py +22 -0
- langfun/core/modalities/pdf_test.py +57 -0
- langfun/core/modalities/video.py +9 -26
- langfun/core/modalities/video_test.py +3 -3
- langfun/core/modality.py +26 -3
- langfun/core/modality_test.py +2 -2
- langfun/core/sampling.py +11 -11
- langfun/core/structured/__init__.py +12 -16
- langfun/core/structured/completion.py +32 -5
- langfun/core/structured/completion_test.py +7 -6
- langfun/core/structured/description.py +2 -2
- langfun/core/structured/description_test.py +3 -3
- langfun/core/structured/function_generation.py +60 -27
- langfun/core/structured/function_generation_test.py +72 -2
- langfun/core/structured/mapping.py +97 -47
- langfun/core/structured/mapping_test.py +90 -2
- langfun/core/structured/parsing.py +33 -21
- langfun/core/structured/parsing_test.py +53 -9
- langfun/core/structured/querying.py +746 -0
- langfun/core/structured/{prompting_test.py → querying_test.py} +469 -51
- langfun/core/structured/schema.py +204 -97
- langfun/core/structured/schema_generation.py +1 -1
- langfun/core/structured/schema_test.py +130 -29
- langfun/core/structured/scoring.py +125 -19
- langfun/core/structured/scoring_test.py +30 -0
- langfun/core/structured/tokenization.py +64 -0
- langfun/core/structured/tokenization_test.py +48 -0
- langfun/core/template.py +115 -1
- langfun/core/template_test.py +71 -1
- langfun/core/templates/conversation.py +9 -0
- langfun/core/templates/conversation_test.py +4 -3
- langfun/core/templates/selfplay_test.py +10 -2
- langfun-0.1.2.dev202501140804.dist-info/METADATA +225 -0
- langfun-0.1.2.dev202501140804.dist-info/RECORD +153 -0
- {langfun-0.0.2.dev20240429.dist-info → langfun-0.1.2.dev202501140804.dist-info}/WHEEL +1 -1
- langfun/core/coding/python/errors.py +0 -108
- langfun/core/coding/python/errors_test.py +0 -99
- langfun/core/coding/python/permissions.py +0 -90
- langfun/core/coding/python/permissions_test.py +0 -86
- langfun/core/structured/prompting.py +0 -238
- langfun/core/text_formatting.py +0 -162
- langfun/core/text_formatting_test.py +0 -47
- langfun-0.0.2.dev20240429.dist-info/METADATA +0 -100
- langfun-0.0.2.dev20240429.dist-info/RECORD +0 -108
- {langfun-0.0.2.dev20240429.dist-info → langfun-0.1.2.dev202501140804.dist-info}/LICENSE +0 -0
- {langfun-0.0.2.dev20240429.dist-info → langfun-0.1.2.dev202501140804.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,270 @@
|
|
1
|
+
# Copyright 2024 The Langfun Authors
|
2
|
+
#
|
3
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
4
|
+
# you may not use this file except in compliance with the License.
|
5
|
+
# You may obtain a copy of the License at
|
6
|
+
#
|
7
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
8
|
+
#
|
9
|
+
# Unless required by applicable law or agreed to in writing, software
|
10
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
11
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
12
|
+
# See the License for the specific language governing permissions and
|
13
|
+
# limitations under the License.
|
14
|
+
"""Reporting evaluation results."""
|
15
|
+
|
16
|
+
import threading
|
17
|
+
import time
|
18
|
+
import traceback
|
19
|
+
from typing import Annotated
|
20
|
+
|
21
|
+
from langfun.core.eval.v2 import example as example_lib
|
22
|
+
from langfun.core.eval.v2 import experiment as experiment_lib
|
23
|
+
import pyglove as pg
|
24
|
+
|
25
|
+
Runner = experiment_lib.Runner
|
26
|
+
Experiment = experiment_lib.Experiment
|
27
|
+
Example = example_lib.Example
|
28
|
+
|
29
|
+
|
30
|
+
_SUMMARY_FILE = 'summary.html'
|
31
|
+
_EVALULATION_DETAIL_FILE = 'index.html'
|
32
|
+
|
33
|
+
|
34
|
+
class HtmlReporter(experiment_lib.Plugin):
|
35
|
+
"""Plugin for periodically generating HTML reports for the experiment."""
|
36
|
+
|
37
|
+
summary_interval: Annotated[
|
38
|
+
int,
|
39
|
+
'The interval of writing summary in seconds.'
|
40
|
+
] = 60
|
41
|
+
|
42
|
+
experiment_report_interval: Annotated[
|
43
|
+
int,
|
44
|
+
'The interval of writing report for inidividual experiments in seconds.'
|
45
|
+
] = 120
|
46
|
+
|
47
|
+
def _on_bound(self):
|
48
|
+
super()._on_bound()
|
49
|
+
self._last_summary_time = 0
|
50
|
+
self._last_experiment_report_time = {}
|
51
|
+
self._update_thread = None
|
52
|
+
self._stop_update = False
|
53
|
+
self._stop_update_experiment_ids = set()
|
54
|
+
self._summary_lock = None
|
55
|
+
self._experiment_index_lock = None
|
56
|
+
|
57
|
+
def on_run_start(
|
58
|
+
self,
|
59
|
+
runner: Runner,
|
60
|
+
root: Experiment
|
61
|
+
) -> None:
|
62
|
+
self._maybe_update_summary(runner)
|
63
|
+
self._last_experiment_report_time = {leaf.id: 0 for leaf in root.leaf_nodes}
|
64
|
+
self._stop_update = False
|
65
|
+
self._stop_update_experiment_ids = set()
|
66
|
+
self._summary_lock = threading.Lock()
|
67
|
+
self._experiment_index_lock = {
|
68
|
+
leaf.id: threading.Lock() for leaf in root.leaf_nodes
|
69
|
+
}
|
70
|
+
self._update_thread = threading.Thread(
|
71
|
+
target=self._update_thread_func, args=(runner,)
|
72
|
+
)
|
73
|
+
self._update_thread.start()
|
74
|
+
|
75
|
+
def on_run_complete(
|
76
|
+
self,
|
77
|
+
runner: Runner,
|
78
|
+
root: Experiment
|
79
|
+
) -> None:
|
80
|
+
self._stop_update = True
|
81
|
+
self._maybe_update_summary(runner, force=True)
|
82
|
+
|
83
|
+
def on_run_abort(
|
84
|
+
self,
|
85
|
+
runner: Runner,
|
86
|
+
root: Experiment,
|
87
|
+
error: BaseException
|
88
|
+
) -> None:
|
89
|
+
self._stop_update = True
|
90
|
+
self._maybe_update_summary(runner, force=True)
|
91
|
+
|
92
|
+
def _update_thread_func(self, runner: Runner):
|
93
|
+
while not self._stop_update:
|
94
|
+
self._maybe_update_summary(runner, background=False)
|
95
|
+
for leaf in runner.current_run.experiment.leaf_nodes:
|
96
|
+
if leaf.id in self._stop_update_experiment_ids:
|
97
|
+
continue
|
98
|
+
self._maybe_update_experiment_html(runner, leaf, background=False)
|
99
|
+
if leaf.progress.is_stopped:
|
100
|
+
self._stop_update_experiment_ids.add(leaf.id)
|
101
|
+
time.sleep(5)
|
102
|
+
|
103
|
+
def on_experiment_start(
|
104
|
+
self,
|
105
|
+
runner: Runner,
|
106
|
+
experiment: Experiment
|
107
|
+
) -> None:
|
108
|
+
if experiment.is_leaf:
|
109
|
+
self._maybe_update_experiment_html(runner, experiment)
|
110
|
+
|
111
|
+
def on_experiment_complete(
|
112
|
+
self, runner: Runner, experiment: Experiment
|
113
|
+
):
|
114
|
+
if experiment.is_leaf:
|
115
|
+
self._maybe_update_experiment_html(runner, experiment, force=True)
|
116
|
+
|
117
|
+
def on_experiment_abort(
|
118
|
+
self,
|
119
|
+
runner: Runner,
|
120
|
+
experiment: Experiment,
|
121
|
+
error: BaseException
|
122
|
+
) -> None:
|
123
|
+
del error
|
124
|
+
assert experiment.is_leaf
|
125
|
+
self._maybe_update_experiment_html(runner, experiment, force=True)
|
126
|
+
|
127
|
+
def on_example_complete(
|
128
|
+
self, runner: Runner, experiment: Experiment, example: Example
|
129
|
+
):
|
130
|
+
self._save_example_html(runner, experiment, example)
|
131
|
+
self._maybe_update_experiment_html(runner, experiment)
|
132
|
+
self._maybe_update_summary(runner)
|
133
|
+
|
134
|
+
def _maybe_update_summary(
|
135
|
+
self,
|
136
|
+
runner: Runner,
|
137
|
+
background: bool = True,
|
138
|
+
force: bool = False) -> None:
|
139
|
+
"""Maybe update the summary of current run."""
|
140
|
+
run = runner.current_run
|
141
|
+
def _summary():
|
142
|
+
html = run.experiment.to_html(
|
143
|
+
collapse_level=None,
|
144
|
+
extra_flags=dict(
|
145
|
+
current_run=run, interactive=False, card_view=True,
|
146
|
+
)
|
147
|
+
)
|
148
|
+
with self._summary_lock:
|
149
|
+
html.save(
|
150
|
+
run.output_path_for(run.experiment, _SUMMARY_FILE)
|
151
|
+
)
|
152
|
+
|
153
|
+
if force or (time.time() - self._last_summary_time > self.summary_interval):
|
154
|
+
self._last_summary_time = time.time()
|
155
|
+
if background:
|
156
|
+
runner.background_run(_summary)
|
157
|
+
else:
|
158
|
+
_summary()
|
159
|
+
|
160
|
+
def _maybe_update_experiment_html(
|
161
|
+
self,
|
162
|
+
runner: Runner,
|
163
|
+
experiment: Experiment,
|
164
|
+
force: bool = False,
|
165
|
+
background: bool = True,
|
166
|
+
) -> None:
|
167
|
+
def _save():
|
168
|
+
index_html_path = runner.current_run.output_path_for(
|
169
|
+
experiment, _EVALULATION_DETAIL_FILE
|
170
|
+
)
|
171
|
+
try:
|
172
|
+
with pg.timeit() as t:
|
173
|
+
html = experiment.to_html(
|
174
|
+
collapse_level=None,
|
175
|
+
extra_flags=dict(
|
176
|
+
current_run=runner.current_run,
|
177
|
+
interactive=False,
|
178
|
+
card_view=False,
|
179
|
+
),
|
180
|
+
)
|
181
|
+
with self._experiment_index_lock[experiment.id]:
|
182
|
+
html.save(index_html_path)
|
183
|
+
experiment.info(
|
184
|
+
f'Updated {index_html_path!r} in {t.elapse:.2f} seconds.',
|
185
|
+
)
|
186
|
+
except BaseException as e: # pylint: disable=broad-except
|
187
|
+
experiment.error(
|
188
|
+
f'Failed to generate {index_html_path!r}. '
|
189
|
+
f'Error: {e}, Stacktrace: \n{traceback.format_exc()}.',
|
190
|
+
)
|
191
|
+
raise e
|
192
|
+
|
193
|
+
if force or (
|
194
|
+
time.time() - self._last_experiment_report_time[experiment.id]
|
195
|
+
> self.experiment_report_interval
|
196
|
+
):
|
197
|
+
self._last_experiment_report_time[experiment.id] = time.time()
|
198
|
+
if background:
|
199
|
+
runner.background_run(_save)
|
200
|
+
else:
|
201
|
+
_save()
|
202
|
+
|
203
|
+
def _save_example_html(
|
204
|
+
self, runner: Runner, experiment: Experiment, example: Example
|
205
|
+
) -> None:
|
206
|
+
"""Saves the example in HTML format."""
|
207
|
+
current_run = runner.current_run
|
208
|
+
def _generate():
|
209
|
+
try:
|
210
|
+
with pg.timeit() as t:
|
211
|
+
html = example.to_html(
|
212
|
+
collapse_level=None,
|
213
|
+
enable_summary_tooltip=False,
|
214
|
+
extra_flags=dict(
|
215
|
+
# For properly rendering the next link.
|
216
|
+
num_examples=getattr(experiment, 'num_examples', None)
|
217
|
+
),
|
218
|
+
)
|
219
|
+
html.save(
|
220
|
+
runner.current_run.output_path_for(
|
221
|
+
experiment, f'{example.id}.html'
|
222
|
+
)
|
223
|
+
)
|
224
|
+
experiment.info(
|
225
|
+
f'\'{example.id}.html\' generated in {t.elapse:.2f} seconds. '
|
226
|
+
)
|
227
|
+
except BaseException as e: # pylint: disable=broad-except
|
228
|
+
experiment.error(
|
229
|
+
f'Failed to generate \'{example.id}.html\'. '
|
230
|
+
f'Error: {e}, Stacktrace: \n{traceback.format_exc()}.',
|
231
|
+
)
|
232
|
+
raise e
|
233
|
+
|
234
|
+
def _copy():
|
235
|
+
src_file = current_run.input_path_for(experiment, f'{example.id}.html')
|
236
|
+
dest_file = current_run.output_path_for(experiment, f'{example.id}.html')
|
237
|
+
|
238
|
+
if src_file == dest_file:
|
239
|
+
return
|
240
|
+
|
241
|
+
if not pg.io.path_exists(src_file):
|
242
|
+
experiment.warning(
|
243
|
+
f'Skip copying \'{example.id}.html\' as '
|
244
|
+
f'{src_file!r} does not exist.'
|
245
|
+
)
|
246
|
+
return
|
247
|
+
|
248
|
+
try:
|
249
|
+
with pg.timeit() as t, pg.io.open(src_file, 'r') as src:
|
250
|
+
content = src.read()
|
251
|
+
with pg.io.open(dest_file, 'w') as dest:
|
252
|
+
dest.write(content)
|
253
|
+
experiment.info(
|
254
|
+
f'\'{example.id}.html\' copied in {t.elapse:.2f} seconds.'
|
255
|
+
)
|
256
|
+
except BaseException as e: # pylint: disable=broad-except
|
257
|
+
experiment.error(
|
258
|
+
f'Failed to copy {src_file!r} to {dest_file!r}. Error: {e}.'
|
259
|
+
)
|
260
|
+
raise e
|
261
|
+
|
262
|
+
generate_example_html = current_run.generate_example_html
|
263
|
+
if (generate_example_html == 'all'
|
264
|
+
or (generate_example_html == 'new' and example.newly_processed)
|
265
|
+
or (isinstance(generate_example_html, list)
|
266
|
+
and example.id in generate_example_html)):
|
267
|
+
op = _generate
|
268
|
+
else:
|
269
|
+
op = _copy
|
270
|
+
runner.background_run(op)
|
@@ -0,0 +1,158 @@
|
|
1
|
+
# Copyright 2024 The Langfun Authors
|
2
|
+
#
|
3
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
4
|
+
# you may not use this file except in compliance with the License.
|
5
|
+
# You may obtain a copy of the License at
|
6
|
+
#
|
7
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
8
|
+
#
|
9
|
+
# Unless required by applicable law or agreed to in writing, software
|
10
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
11
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
12
|
+
# See the License for the specific language governing permissions and
|
13
|
+
# limitations under the License.
|
14
|
+
import os
|
15
|
+
import tempfile
|
16
|
+
import unittest
|
17
|
+
|
18
|
+
from langfun.core.eval.v2 import checkpointing
|
19
|
+
from langfun.core.eval.v2 import eval_test_helper
|
20
|
+
from langfun.core.eval.v2 import reporting
|
21
|
+
from langfun.core.eval.v2 import runners as runners_lib # pylint: disable=unused-import
|
22
|
+
import pyglove as pg
|
23
|
+
|
24
|
+
|
25
|
+
class ReportingTest(unittest.TestCase):
|
26
|
+
|
27
|
+
def test_reporting(self):
|
28
|
+
root_dir = os.path.join(tempfile.gettempdir(), 'test_reporting')
|
29
|
+
experiment = eval_test_helper.test_experiment()
|
30
|
+
checkpointer = checkpointing.BulkCheckpointer('checkpoint.jsonl')
|
31
|
+
reporter = reporting.HtmlReporter()
|
32
|
+
run = experiment.run(root_dir, 'new', plugins=[checkpointer, reporter])
|
33
|
+
self.assertTrue(
|
34
|
+
pg.io.path_exists(run.output_path_for(experiment, 'summary.html'))
|
35
|
+
)
|
36
|
+
for leaf in experiment.leaf_nodes:
|
37
|
+
self.assertTrue(
|
38
|
+
pg.io.path_exists(run.output_path_for(leaf, 'index.html'))
|
39
|
+
)
|
40
|
+
for i in range(leaf.num_examples):
|
41
|
+
self.assertTrue(
|
42
|
+
pg.io.path_exists(run.output_path_for(leaf, f'{i + 1}.html'))
|
43
|
+
)
|
44
|
+
found_generation_log = False
|
45
|
+
for log_entry in leaf._log_entries:
|
46
|
+
if 'generated in' in log_entry.message:
|
47
|
+
found_generation_log = True
|
48
|
+
break
|
49
|
+
self.assertTrue(found_generation_log)
|
50
|
+
|
51
|
+
# Test warm start.
|
52
|
+
root_dir = os.path.join(tempfile.gettempdir(), 'test_reporting2')
|
53
|
+
experiment = eval_test_helper.test_experiment()
|
54
|
+
run = experiment.run(
|
55
|
+
root_dir, 'new', plugins=[checkpointer, reporter],
|
56
|
+
warm_start_from=run.output_root
|
57
|
+
)
|
58
|
+
self.assertTrue(
|
59
|
+
pg.io.path_exists(run.output_path_for(experiment, 'summary.html'))
|
60
|
+
)
|
61
|
+
for leaf in experiment.leaf_nodes:
|
62
|
+
self.assertTrue(
|
63
|
+
pg.io.path_exists(run.output_path_for(leaf, 'index.html'))
|
64
|
+
)
|
65
|
+
for i in range(leaf.num_examples):
|
66
|
+
self.assertTrue(
|
67
|
+
pg.io.path_exists(run.output_path_for(leaf, f'{i + 1}.html'))
|
68
|
+
)
|
69
|
+
found_copy_log = False
|
70
|
+
for log_entry in leaf._log_entries:
|
71
|
+
if 'copied in' in log_entry.message:
|
72
|
+
found_copy_log = True
|
73
|
+
break
|
74
|
+
self.assertTrue(found_copy_log)
|
75
|
+
|
76
|
+
def test_index_html_generation_error(self):
|
77
|
+
root_dir = os.path.join(
|
78
|
+
tempfile.gettempdir(),
|
79
|
+
'test_reporting_with_index_html_generation_error'
|
80
|
+
)
|
81
|
+
experiment = (eval_test_helper
|
82
|
+
.test_experiment_with_index_html_generation_error())
|
83
|
+
reporter = reporting.HtmlReporter()
|
84
|
+
run = experiment.run(root_dir, 'new', plugins=[reporter])
|
85
|
+
self.assertFalse(
|
86
|
+
pg.io.path_exists(run.output_path_for(experiment, 'summary.html'))
|
87
|
+
)
|
88
|
+
for leaf in experiment.leaf_nodes:
|
89
|
+
self.assertFalse(
|
90
|
+
pg.io.path_exists(run.output_path_for(leaf, 'index.html'))
|
91
|
+
)
|
92
|
+
found_error_log = False
|
93
|
+
for log_entry in experiment._log_entries:
|
94
|
+
if log_entry.message.startswith('Failed to generate'):
|
95
|
+
found_error_log = True
|
96
|
+
break
|
97
|
+
self.assertTrue(found_error_log)
|
98
|
+
|
99
|
+
def test_example_html_generation_error(self):
|
100
|
+
root_dir = os.path.join(
|
101
|
+
tempfile.gettempdir(),
|
102
|
+
'test_reporting_with_example_html_generation_error'
|
103
|
+
)
|
104
|
+
experiment = (eval_test_helper
|
105
|
+
.test_experiment_with_example_html_generation_error())
|
106
|
+
checkpointer = checkpointing.BulkCheckpointer('checkpoint.jsonl')
|
107
|
+
reporter = reporting.HtmlReporter()
|
108
|
+
run = experiment.run(root_dir, 'new', plugins=[checkpointer, reporter])
|
109
|
+
self.assertTrue(
|
110
|
+
pg.io.path_exists(run.output_path_for(experiment, 'summary.html'))
|
111
|
+
)
|
112
|
+
for leaf in experiment.leaf_nodes:
|
113
|
+
self.assertTrue(
|
114
|
+
pg.io.path_exists(run.output_path_for(leaf, 'index.html'))
|
115
|
+
)
|
116
|
+
for i in range(leaf.num_examples):
|
117
|
+
self.assertFalse(
|
118
|
+
pg.io.path_exists(run.output_path_for(leaf, f'{i + 1}.html'))
|
119
|
+
)
|
120
|
+
found_error_log = False
|
121
|
+
for log_entry in experiment._log_entries:
|
122
|
+
if log_entry.message.startswith('Failed to generate'):
|
123
|
+
found_error_log = True
|
124
|
+
break
|
125
|
+
self.assertTrue(found_error_log)
|
126
|
+
|
127
|
+
# Test warm start.
|
128
|
+
root_dir = os.path.join(
|
129
|
+
tempfile.gettempdir(),
|
130
|
+
'test_reporting_with_example_html_generation_error2'
|
131
|
+
)
|
132
|
+
experiment = (eval_test_helper
|
133
|
+
.test_experiment_with_example_html_generation_error())
|
134
|
+
run = experiment.run(
|
135
|
+
root_dir, 'new', plugins=[checkpointer, reporter],
|
136
|
+
warm_start_from=run.output_root
|
137
|
+
)
|
138
|
+
self.assertTrue(
|
139
|
+
pg.io.path_exists(run.output_path_for(experiment, 'summary.html'))
|
140
|
+
)
|
141
|
+
for leaf in experiment.leaf_nodes:
|
142
|
+
self.assertTrue(
|
143
|
+
pg.io.path_exists(run.output_path_for(leaf, 'index.html'))
|
144
|
+
)
|
145
|
+
for i in range(leaf.num_examples):
|
146
|
+
self.assertFalse(
|
147
|
+
pg.io.path_exists(run.output_path_for(leaf, f'{i + 1}.html'))
|
148
|
+
)
|
149
|
+
found_error_log = False
|
150
|
+
for log_entry in experiment._log_entries:
|
151
|
+
if log_entry.message.startswith('Skip copying'):
|
152
|
+
found_error_log = True
|
153
|
+
break
|
154
|
+
self.assertTrue(found_error_log)
|
155
|
+
|
156
|
+
|
157
|
+
if __name__ == '__main__':
|
158
|
+
unittest.main()
|