edsl 0.1.33__py3-none-any.whl → 0.1.33.dev1__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.
- edsl/Base.py +3 -9
- edsl/__init__.py +3 -8
- edsl/__version__.py +1 -1
- edsl/agents/Agent.py +8 -40
- edsl/agents/AgentList.py +0 -43
- edsl/agents/Invigilator.py +219 -135
- edsl/agents/InvigilatorBase.py +59 -148
- edsl/agents/{PromptConstructor.py → PromptConstructionMixin.py} +89 -138
- edsl/agents/__init__.py +0 -1
- edsl/config.py +56 -47
- edsl/coop/coop.py +7 -50
- edsl/data/Cache.py +1 -35
- edsl/data_transfer_models.py +38 -73
- edsl/enums.py +0 -4
- edsl/exceptions/language_models.py +1 -25
- edsl/exceptions/questions.py +5 -62
- edsl/exceptions/results.py +0 -4
- edsl/inference_services/AnthropicService.py +11 -13
- edsl/inference_services/AwsBedrock.py +17 -19
- edsl/inference_services/AzureAI.py +20 -37
- edsl/inference_services/GoogleService.py +12 -16
- edsl/inference_services/GroqService.py +0 -2
- edsl/inference_services/InferenceServiceABC.py +3 -58
- edsl/inference_services/OpenAIService.py +54 -48
- edsl/inference_services/models_available_cache.py +6 -0
- edsl/inference_services/registry.py +0 -6
- edsl/jobs/Answers.py +12 -10
- edsl/jobs/Jobs.py +21 -36
- edsl/jobs/buckets/BucketCollection.py +15 -24
- edsl/jobs/buckets/TokenBucket.py +14 -93
- edsl/jobs/interviews/Interview.py +78 -366
- edsl/jobs/interviews/InterviewExceptionEntry.py +19 -85
- edsl/jobs/interviews/InterviewTaskBuildingMixin.py +286 -0
- edsl/jobs/interviews/{InterviewExceptionCollection.py → interview_exception_tracking.py} +68 -14
- edsl/jobs/interviews/retry_management.py +37 -0
- edsl/jobs/runners/JobsRunnerAsyncio.py +175 -146
- edsl/jobs/runners/JobsRunnerStatusMixin.py +333 -0
- edsl/jobs/tasks/QuestionTaskCreator.py +23 -30
- edsl/jobs/tasks/TaskHistory.py +213 -148
- edsl/language_models/LanguageModel.py +156 -261
- edsl/language_models/ModelList.py +2 -2
- edsl/language_models/RegisterLanguageModelsMeta.py +29 -14
- edsl/language_models/registry.py +6 -23
- edsl/language_models/repair.py +19 -0
- edsl/prompts/Prompt.py +2 -52
- edsl/questions/AnswerValidatorMixin.py +26 -23
- edsl/questions/QuestionBase.py +249 -329
- edsl/questions/QuestionBudget.py +41 -99
- edsl/questions/QuestionCheckBox.py +35 -227
- edsl/questions/QuestionExtract.py +27 -98
- edsl/questions/QuestionFreeText.py +29 -52
- edsl/questions/QuestionFunctional.py +0 -7
- edsl/questions/QuestionList.py +22 -141
- edsl/questions/QuestionMultipleChoice.py +65 -159
- edsl/questions/QuestionNumerical.py +46 -88
- edsl/questions/QuestionRank.py +24 -182
- edsl/questions/RegisterQuestionsMeta.py +12 -31
- edsl/questions/__init__.py +4 -3
- edsl/questions/derived/QuestionLikertFive.py +5 -10
- edsl/questions/derived/QuestionLinearScale.py +2 -15
- edsl/questions/derived/QuestionTopK.py +1 -10
- edsl/questions/derived/QuestionYesNo.py +3 -24
- edsl/questions/descriptors.py +7 -43
- edsl/questions/question_registry.py +2 -6
- edsl/results/Dataset.py +0 -20
- edsl/results/DatasetExportMixin.py +48 -46
- edsl/results/Result.py +5 -32
- edsl/results/Results.py +46 -135
- edsl/results/ResultsDBMixin.py +3 -3
- edsl/scenarios/FileStore.py +10 -71
- edsl/scenarios/Scenario.py +25 -96
- edsl/scenarios/ScenarioImageMixin.py +2 -2
- edsl/scenarios/ScenarioList.py +39 -361
- edsl/scenarios/ScenarioListExportMixin.py +0 -9
- edsl/scenarios/ScenarioListPdfMixin.py +4 -150
- edsl/study/SnapShot.py +1 -8
- edsl/study/Study.py +0 -32
- edsl/surveys/Rule.py +1 -10
- edsl/surveys/RuleCollection.py +5 -21
- edsl/surveys/Survey.py +310 -636
- edsl/surveys/SurveyExportMixin.py +9 -71
- edsl/surveys/SurveyFlowVisualizationMixin.py +1 -2
- edsl/surveys/SurveyQualtricsImport.py +4 -75
- edsl/utilities/gcp_bucket/simple_example.py +9 -0
- edsl/utilities/utilities.py +1 -9
- {edsl-0.1.33.dist-info → edsl-0.1.33.dev1.dist-info}/METADATA +2 -5
- edsl-0.1.33.dev1.dist-info/RECORD +209 -0
- edsl/TemplateLoader.py +0 -24
- edsl/auto/AutoStudy.py +0 -117
- edsl/auto/StageBase.py +0 -230
- edsl/auto/StageGenerateSurvey.py +0 -178
- edsl/auto/StageLabelQuestions.py +0 -125
- edsl/auto/StagePersona.py +0 -61
- edsl/auto/StagePersonaDimensionValueRanges.py +0 -88
- edsl/auto/StagePersonaDimensionValues.py +0 -74
- edsl/auto/StagePersonaDimensions.py +0 -69
- edsl/auto/StageQuestions.py +0 -73
- edsl/auto/SurveyCreatorPipeline.py +0 -21
- edsl/auto/utilities.py +0 -224
- edsl/coop/PriceFetcher.py +0 -58
- edsl/inference_services/MistralAIService.py +0 -120
- edsl/inference_services/TestService.py +0 -80
- edsl/inference_services/TogetherAIService.py +0 -170
- edsl/jobs/FailedQuestion.py +0 -78
- edsl/jobs/runners/JobsRunnerStatus.py +0 -331
- edsl/language_models/fake_openai_call.py +0 -15
- edsl/language_models/fake_openai_service.py +0 -61
- edsl/language_models/utilities.py +0 -61
- edsl/questions/QuestionBaseGenMixin.py +0 -133
- edsl/questions/QuestionBasePromptsMixin.py +0 -266
- edsl/questions/Quick.py +0 -41
- edsl/questions/ResponseValidatorABC.py +0 -170
- edsl/questions/decorators.py +0 -21
- edsl/questions/prompt_templates/question_budget.jinja +0 -13
- edsl/questions/prompt_templates/question_checkbox.jinja +0 -32
- edsl/questions/prompt_templates/question_extract.jinja +0 -11
- edsl/questions/prompt_templates/question_free_text.jinja +0 -3
- edsl/questions/prompt_templates/question_linear_scale.jinja +0 -11
- edsl/questions/prompt_templates/question_list.jinja +0 -17
- edsl/questions/prompt_templates/question_multiple_choice.jinja +0 -33
- edsl/questions/prompt_templates/question_numerical.jinja +0 -37
- edsl/questions/templates/__init__.py +0 -0
- edsl/questions/templates/budget/__init__.py +0 -0
- edsl/questions/templates/budget/answering_instructions.jinja +0 -7
- edsl/questions/templates/budget/question_presentation.jinja +0 -7
- edsl/questions/templates/checkbox/__init__.py +0 -0
- edsl/questions/templates/checkbox/answering_instructions.jinja +0 -10
- edsl/questions/templates/checkbox/question_presentation.jinja +0 -22
- edsl/questions/templates/extract/__init__.py +0 -0
- edsl/questions/templates/extract/answering_instructions.jinja +0 -7
- edsl/questions/templates/extract/question_presentation.jinja +0 -1
- edsl/questions/templates/free_text/__init__.py +0 -0
- edsl/questions/templates/free_text/answering_instructions.jinja +0 -0
- edsl/questions/templates/free_text/question_presentation.jinja +0 -1
- edsl/questions/templates/likert_five/__init__.py +0 -0
- edsl/questions/templates/likert_five/answering_instructions.jinja +0 -10
- edsl/questions/templates/likert_five/question_presentation.jinja +0 -12
- edsl/questions/templates/linear_scale/__init__.py +0 -0
- edsl/questions/templates/linear_scale/answering_instructions.jinja +0 -5
- edsl/questions/templates/linear_scale/question_presentation.jinja +0 -5
- edsl/questions/templates/list/__init__.py +0 -0
- edsl/questions/templates/list/answering_instructions.jinja +0 -4
- edsl/questions/templates/list/question_presentation.jinja +0 -5
- edsl/questions/templates/multiple_choice/__init__.py +0 -0
- edsl/questions/templates/multiple_choice/answering_instructions.jinja +0 -9
- edsl/questions/templates/multiple_choice/html.jinja +0 -0
- edsl/questions/templates/multiple_choice/question_presentation.jinja +0 -12
- edsl/questions/templates/numerical/__init__.py +0 -0
- edsl/questions/templates/numerical/answering_instructions.jinja +0 -8
- edsl/questions/templates/numerical/question_presentation.jinja +0 -7
- edsl/questions/templates/rank/__init__.py +0 -0
- edsl/questions/templates/rank/answering_instructions.jinja +0 -11
- edsl/questions/templates/rank/question_presentation.jinja +0 -15
- edsl/questions/templates/top_k/__init__.py +0 -0
- edsl/questions/templates/top_k/answering_instructions.jinja +0 -8
- edsl/questions/templates/top_k/question_presentation.jinja +0 -22
- edsl/questions/templates/yes_no/__init__.py +0 -0
- edsl/questions/templates/yes_no/answering_instructions.jinja +0 -6
- edsl/questions/templates/yes_no/question_presentation.jinja +0 -12
- edsl/results/DatasetTree.py +0 -145
- edsl/results/Selector.py +0 -118
- edsl/results/tree_explore.py +0 -115
- edsl/surveys/instructions/ChangeInstruction.py +0 -47
- edsl/surveys/instructions/Instruction.py +0 -34
- edsl/surveys/instructions/InstructionCollection.py +0 -77
- edsl/surveys/instructions/__init__.py +0 -0
- edsl/templates/error_reporting/base.html +0 -24
- edsl/templates/error_reporting/exceptions_by_model.html +0 -35
- edsl/templates/error_reporting/exceptions_by_question_name.html +0 -17
- edsl/templates/error_reporting/exceptions_by_type.html +0 -17
- edsl/templates/error_reporting/interview_details.html +0 -116
- edsl/templates/error_reporting/interviews.html +0 -10
- edsl/templates/error_reporting/overview.html +0 -5
- edsl/templates/error_reporting/performance_plot.html +0 -2
- edsl/templates/error_reporting/report.css +0 -74
- edsl/templates/error_reporting/report.html +0 -118
- edsl/templates/error_reporting/report.js +0 -25
- edsl-0.1.33.dist-info/RECORD +0 -295
- {edsl-0.1.33.dist-info → edsl-0.1.33.dev1.dist-info}/LICENSE +0 -0
- {edsl-0.1.33.dist-info → edsl-0.1.33.dev1.dist-info}/WHEEL +0 -0
edsl/jobs/tasks/TaskHistory.py
CHANGED
@@ -1,10 +1,7 @@
|
|
1
|
+
from edsl.jobs.tasks.task_status_enum import TaskStatus
|
1
2
|
from typing import List, Optional
|
2
3
|
from io import BytesIO
|
3
|
-
import webbrowser
|
4
|
-
import os
|
5
4
|
import base64
|
6
|
-
from importlib import resources
|
7
|
-
from edsl.jobs.tasks.task_status_enum import TaskStatus
|
8
5
|
|
9
6
|
|
10
7
|
class TaskHistory:
|
@@ -33,12 +30,7 @@ class TaskHistory:
|
|
33
30
|
|
34
31
|
from edsl.config import CONFIG
|
35
32
|
|
36
|
-
results = j.run(
|
37
|
-
print_exceptions=False,
|
38
|
-
skip_retry=True,
|
39
|
-
cache=False,
|
40
|
-
raise_validation_errors=True,
|
41
|
-
)
|
33
|
+
results = j.run(print_exceptions=False, skip_retry=True, cache=False)
|
42
34
|
|
43
35
|
return cls(results.task_history.total_interviews)
|
44
36
|
|
@@ -50,18 +42,6 @@ class TaskHistory:
|
|
50
42
|
"""
|
51
43
|
return [i.exceptions for k, i in self._interviews.items() if i.exceptions != {}]
|
52
44
|
|
53
|
-
@property
|
54
|
-
def unfixed_exceptions(self):
|
55
|
-
"""
|
56
|
-
>>> len(TaskHistory.example().unfixed_exceptions)
|
57
|
-
4
|
58
|
-
"""
|
59
|
-
return [
|
60
|
-
i.exceptions
|
61
|
-
for k, i in self._interviews.items()
|
62
|
-
if i.exceptions.num_unfixed() > 0
|
63
|
-
]
|
64
|
-
|
65
45
|
@property
|
66
46
|
def indices(self):
|
67
47
|
return [k for k, i in self._interviews.items() if i.exceptions != {}]
|
@@ -90,11 +70,6 @@ class TaskHistory:
|
|
90
70
|
"""
|
91
71
|
return len(self.exceptions) > 0
|
92
72
|
|
93
|
-
@property
|
94
|
-
def has_unfixed_exceptions(self) -> bool:
|
95
|
-
"""Return True if there are any exceptions."""
|
96
|
-
return len(self.unfixed_exceptions) > 0
|
97
|
-
|
98
73
|
def _repr_html_(self):
|
99
74
|
"""Return an HTML representation of the TaskHistory."""
|
100
75
|
from edsl.utilities.utilities import data_to_html
|
@@ -213,14 +188,58 @@ class TaskHistory:
|
|
213
188
|
plt.show()
|
214
189
|
|
215
190
|
def css(self):
|
216
|
-
|
217
|
-
|
218
|
-
|
191
|
+
return """
|
192
|
+
body {
|
193
|
+
font-family: Arial, sans-serif;
|
194
|
+
line-height: 1.6;
|
195
|
+
background-color: #f9f9f9;
|
196
|
+
color: #333;
|
197
|
+
margin: 20px;
|
198
|
+
}
|
199
|
+
|
200
|
+
.interview {
|
201
|
+
font-size: 1.5em;
|
202
|
+
margin-bottom: 10px;
|
203
|
+
padding: 10px;
|
204
|
+
background-color: #e3f2fd;
|
205
|
+
border-left: 5px solid #2196f3;
|
206
|
+
}
|
207
|
+
|
208
|
+
.question {
|
209
|
+
font-size: 1.2em;
|
210
|
+
margin-bottom: 10px;
|
211
|
+
padding: 10px;
|
212
|
+
background-color: #fff9c4;
|
213
|
+
border-left: 5px solid #ffeb3b;
|
214
|
+
}
|
215
|
+
|
216
|
+
.exception-detail {
|
217
|
+
margin-bottom: 10px;
|
218
|
+
padding: 10px;
|
219
|
+
background-color: #ffebee;
|
220
|
+
border-left: 5px solid #f44336;
|
221
|
+
}
|
222
|
+
|
223
|
+
.question-detail {
|
224
|
+
border: 3px solid black; /* Adjust the thickness by changing the number */
|
225
|
+
padding: 10px; /* Optional: Adds some padding inside the border */
|
226
|
+
}
|
219
227
|
|
220
|
-
|
221
|
-
|
222
|
-
|
223
|
-
|
228
|
+
.exception-detail div {
|
229
|
+
margin-bottom: 5px;
|
230
|
+
}
|
231
|
+
|
232
|
+
.exception-exception {
|
233
|
+
font-weight: bold;
|
234
|
+
color: #d32f2f;
|
235
|
+
}
|
236
|
+
|
237
|
+
.exception-time,
|
238
|
+
.exception-traceback {
|
239
|
+
font-style: italic;
|
240
|
+
color: #555;
|
241
|
+
}
|
242
|
+
"""
|
224
243
|
|
225
244
|
@property
|
226
245
|
def exceptions_by_type(self) -> dict:
|
@@ -229,136 +248,206 @@ class TaskHistory:
|
|
229
248
|
for interview in self.total_interviews:
|
230
249
|
for question_name, exceptions in interview.exceptions.items():
|
231
250
|
for exception in exceptions:
|
232
|
-
exception_type = exception
|
233
|
-
# exception_type = exception["exception"]
|
234
|
-
# breakpoint()
|
251
|
+
exception_type = exception["exception"]
|
235
252
|
if exception_type in exceptions_by_type:
|
236
253
|
exceptions_by_type[exception_type] += 1
|
237
254
|
else:
|
238
255
|
exceptions_by_type[exception_type] = 1
|
239
256
|
return exceptions_by_type
|
240
257
|
|
241
|
-
@property
|
242
|
-
def exceptions_by_service(self) -> dict:
|
243
|
-
"""Return a dictionary of exceptions tallied by service."""
|
244
|
-
exceptions_by_service = {}
|
245
|
-
for interview in self.total_interviews:
|
246
|
-
service = interview.model._inference_service_
|
247
|
-
if service not in exceptions_by_service:
|
248
|
-
exceptions_by_service[service] = 0
|
249
|
-
if interview.exceptions != {}:
|
250
|
-
exceptions_by_service[service] += len(interview.exceptions)
|
251
|
-
return exceptions_by_service
|
252
|
-
|
253
258
|
@property
|
254
259
|
def exceptions_by_question_name(self) -> dict:
|
255
260
|
"""Return a dictionary of exceptions tallied by question name."""
|
256
261
|
exceptions_by_question_name = {}
|
257
262
|
for interview in self.total_interviews:
|
258
263
|
for question_name, exceptions in interview.exceptions.items():
|
259
|
-
|
260
|
-
question_name
|
261
|
-
)
|
262
|
-
# breakpoint()
|
263
|
-
if (question_name, question_type) not in exceptions_by_question_name:
|
264
|
-
exceptions_by_question_name[(question_name, question_type)] = 0
|
265
|
-
exceptions_by_question_name[(question_name, question_type)] += len(
|
266
|
-
exceptions
|
267
|
-
)
|
264
|
+
if question_name not in exceptions_by_question_name:
|
265
|
+
exceptions_by_question_name[question_name] = 0
|
266
|
+
exceptions_by_question_name[question_name] += len(exceptions)
|
268
267
|
|
269
268
|
for question in self.total_interviews[0].survey.questions:
|
270
|
-
if
|
271
|
-
question.question_name
|
272
|
-
|
273
|
-
) not in exceptions_by_question_name:
|
274
|
-
exceptions_by_question_name[
|
275
|
-
(question.question_name, question.question_type)
|
276
|
-
] = 0
|
277
|
-
|
278
|
-
sorted_exceptions_by_question_name = {
|
279
|
-
k: v
|
280
|
-
for k, v in sorted(
|
281
|
-
exceptions_by_question_name.items(),
|
282
|
-
key=lambda item: item[1],
|
283
|
-
reverse=True,
|
284
|
-
)
|
285
|
-
}
|
286
|
-
return sorted_exceptions_by_question_name
|
269
|
+
if question.question_name not in exceptions_by_question_name:
|
270
|
+
exceptions_by_question_name[question.question_name] = 0
|
271
|
+
return exceptions_by_question_name
|
287
272
|
|
288
273
|
@property
|
289
274
|
def exceptions_by_model(self) -> dict:
|
290
275
|
"""Return a dictionary of exceptions tallied by model and question name."""
|
291
276
|
exceptions_by_model = {}
|
292
277
|
for interview in self.total_interviews:
|
293
|
-
model = interview.model
|
294
|
-
|
295
|
-
|
296
|
-
exceptions_by_model[(service, model)] = 0
|
278
|
+
model = interview.model
|
279
|
+
if model not in exceptions_by_model:
|
280
|
+
exceptions_by_model[model.model] = 0
|
297
281
|
if interview.exceptions != {}:
|
298
|
-
exceptions_by_model[
|
299
|
-
|
300
|
-
|
301
|
-
|
302
|
-
|
303
|
-
|
304
|
-
|
305
|
-
|
306
|
-
|
307
|
-
|
282
|
+
exceptions_by_model[model.model] += len(interview.exceptions)
|
283
|
+
return exceptions_by_model
|
284
|
+
|
285
|
+
def html(
|
286
|
+
self,
|
287
|
+
filename: Optional[str] = None,
|
288
|
+
return_link=False,
|
289
|
+
css=None,
|
290
|
+
cta="Open Report in New Tab",
|
291
|
+
):
|
292
|
+
"""Return an HTML report."""
|
293
|
+
|
294
|
+
from IPython.display import display, HTML
|
295
|
+
import tempfile
|
296
|
+
import os
|
297
|
+
from edsl.utilities.utilities import is_notebook
|
298
|
+
from jinja2 import Template
|
308
299
|
|
309
|
-
def generate_html_report(self, css: Optional[str]):
|
310
300
|
performance_plot_html = self.plot(num_periods=100, get_embedded_html=True)
|
311
301
|
|
312
302
|
if css is None:
|
313
303
|
css = self.css()
|
314
304
|
|
315
|
-
models_used = set([i.model
|
316
|
-
|
317
|
-
from jinja2 import Environment, FileSystemLoader
|
318
|
-
from edsl.TemplateLoader import TemplateLoader
|
305
|
+
models_used = set([i.model for index, i in self._interviews.items()])
|
319
306
|
|
320
|
-
|
307
|
+
template = Template(
|
308
|
+
"""
|
309
|
+
<!DOCTYPE html>
|
310
|
+
<html lang="en">
|
311
|
+
<head>
|
312
|
+
<meta charset="UTF-8">
|
313
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
314
|
+
<title>Exception Details</title>
|
315
|
+
<style>
|
316
|
+
{{ css }}
|
317
|
+
</style>
|
318
|
+
</head>
|
319
|
+
<body>
|
320
|
+
<h1>Overview</h1>
|
321
|
+
<p>There were {{ interviews|length }} total interviews. The number of interviews with exceptions was {{ num_exceptions }}.</p>
|
322
|
+
<p>The models used were: {{ models_used }}.</p>
|
323
|
+
<p>For documentation on dealing with exceptions on Expected Parrot,
|
324
|
+
see <a href="https://docs.expectedparrot.com/en/latest/exceptions.html">here</a>.</p>
|
325
|
+
|
326
|
+
<h2>Exceptions by Type</h2>
|
327
|
+
<table>
|
328
|
+
<thead>
|
329
|
+
<tr>
|
330
|
+
<th>Exception Type</th>
|
331
|
+
<th>Number</th>
|
332
|
+
</tr>
|
333
|
+
</thead>
|
334
|
+
<tbody>
|
335
|
+
{% for exception_type, exceptions in exceptions_by_type.items() %}
|
336
|
+
<tr>
|
337
|
+
<td>{{ exception_type }}</td>
|
338
|
+
<td>{{ exceptions }}</td>
|
339
|
+
</tr>
|
340
|
+
{% endfor %}
|
341
|
+
</tbody>
|
342
|
+
</table>
|
343
|
+
|
344
|
+
|
345
|
+
<h2>Exceptions by Model</h2>
|
346
|
+
<table>
|
347
|
+
<thead>
|
348
|
+
<tr>
|
349
|
+
<th>Model</th>
|
350
|
+
<th>Number</th>
|
351
|
+
</tr>
|
352
|
+
</thead>
|
353
|
+
<tbody>
|
354
|
+
{% for model, exceptions in exceptions_by_model.items() %}
|
355
|
+
<tr>
|
356
|
+
<td>{{ model }}</td>
|
357
|
+
<td>{{ exceptions }}</td>
|
358
|
+
</tr>
|
359
|
+
{% endfor %}
|
360
|
+
</tbody>
|
361
|
+
</table>
|
362
|
+
|
363
|
+
|
364
|
+
<h2>Exceptions by Question Name</h2>
|
365
|
+
<table>
|
366
|
+
<thead>
|
367
|
+
<tr>
|
368
|
+
<th>Question Name</th>
|
369
|
+
<th>Number of Exceptions</th>
|
370
|
+
</tr>
|
371
|
+
</thead>
|
372
|
+
<tbody>
|
373
|
+
{% for question_name, exception_count in exceptions_by_question_name.items() %}
|
374
|
+
<tr>
|
375
|
+
<td>{{ question_name }}</td>
|
376
|
+
<td>{{ exception_count }}</td>
|
377
|
+
</tr>
|
378
|
+
{% endfor %}
|
379
|
+
</tbody>
|
380
|
+
</table>
|
381
|
+
|
382
|
+
|
383
|
+
{% for index, interview in interviews.items() %}
|
384
|
+
{% if interview.exceptions != {} %}
|
385
|
+
<div class="interview">Interview: {{ index }} </div>
|
386
|
+
<h1>Failing questions</h1>
|
387
|
+
{% endif %}
|
388
|
+
{% for question, exceptions in interview.exceptions.items() %}
|
389
|
+
<div class="question">question_name: {{ question }}</div>
|
390
|
+
|
391
|
+
<h2>Question</h2>
|
392
|
+
<div class="question-detail">
|
393
|
+
{{ interview.survey.get_question(question).html(interview.scenario,interview.agent) }}
|
394
|
+
</div>
|
395
|
+
|
396
|
+
<h2>Scenario</h2>
|
397
|
+
<div class="scenario">
|
398
|
+
{{ interview.scenario._repr_html_() }}
|
399
|
+
</div>
|
400
|
+
|
401
|
+
<h2>Agent</h2>
|
402
|
+
<div class="agent">
|
403
|
+
{{ interview.agent._repr_html_() }}
|
404
|
+
</div>
|
405
|
+
|
406
|
+
<h2>Model</h2>
|
407
|
+
<div class="model">
|
408
|
+
{{ interview.model._repr_html_() }}
|
409
|
+
</div>
|
410
|
+
|
411
|
+
<h2>Exception details</h2>
|
412
|
+
|
413
|
+
{% for exception_message in exceptions %}
|
414
|
+
<div class="exception-detail">
|
415
|
+
<div class="exception-exception">Exception: {{ exception_message.exception }}</div>
|
416
|
+
<div class="exception-time">Time: {{ exception_message.time }}</div>
|
417
|
+
<div class="exception-traceback">Traceback: <pre>{{ exception_message.traceback }} </pre></div>
|
418
|
+
</div>
|
419
|
+
{% endfor %}
|
420
|
+
{% endfor %}
|
421
|
+
{% endfor %}
|
422
|
+
|
423
|
+
<h1>Performance Plot</h1>
|
424
|
+
{{ performance_plot_html }}
|
425
|
+
</body>
|
426
|
+
</html>
|
427
|
+
"""
|
428
|
+
)
|
321
429
|
|
322
|
-
#
|
323
|
-
template = env.get_template("base.html")
|
324
|
-
# rendered_template = template.render(your_data=your_data)
|
430
|
+
# breakpoint()
|
325
431
|
|
326
432
|
# Render the template with data
|
327
433
|
output = template.render(
|
328
434
|
interviews=self._interviews,
|
329
435
|
css=css,
|
330
|
-
javascript=self.javascript(),
|
331
436
|
num_exceptions=len(self.exceptions),
|
332
437
|
performance_plot_html=performance_plot_html,
|
333
438
|
exceptions_by_type=self.exceptions_by_type,
|
334
439
|
exceptions_by_question_name=self.exceptions_by_question_name,
|
335
440
|
exceptions_by_model=self.exceptions_by_model,
|
336
|
-
exceptions_by_service=self.exceptions_by_service,
|
337
441
|
models_used=models_used,
|
338
442
|
)
|
339
|
-
return output
|
340
|
-
|
341
|
-
def html(
|
342
|
-
self,
|
343
|
-
filename: Optional[str] = None,
|
344
|
-
return_link=False,
|
345
|
-
css=None,
|
346
|
-
cta="Open Report in New Tab",
|
347
|
-
open_in_browser=True,
|
348
|
-
):
|
349
|
-
"""Return an HTML report."""
|
350
|
-
|
351
|
-
from IPython.display import display, HTML
|
352
|
-
import tempfile
|
353
|
-
import os
|
354
|
-
from edsl.utilities.utilities import is_notebook
|
355
|
-
|
356
|
-
output = self.generate_html_report(css)
|
357
443
|
|
358
444
|
# Save the rendered output to a file
|
359
445
|
with open("output.html", "w") as f:
|
360
446
|
f.write(output)
|
361
447
|
|
448
|
+
if css is None:
|
449
|
+
css = self.css()
|
450
|
+
|
362
451
|
if filename is None:
|
363
452
|
current_directory = os.getcwd()
|
364
453
|
filename = tempfile.NamedTemporaryFile(
|
@@ -367,7 +456,10 @@ class TaskHistory:
|
|
367
456
|
|
368
457
|
with open(filename, "w") as f:
|
369
458
|
with open(filename, "w") as f:
|
459
|
+
# f.write(html_header)
|
460
|
+
# f.write(self._repr_html_())
|
370
461
|
f.write(output)
|
462
|
+
# f.write(html_footer)
|
371
463
|
|
372
464
|
if is_notebook():
|
373
465
|
import html
|
@@ -380,44 +472,17 @@ class TaskHistory:
|
|
380
472
|
<iframe srcdoc="{ escaped_output }" style="width: 800px; height: 600px;"></iframe>
|
381
473
|
"""
|
382
474
|
display(HTML(iframe))
|
475
|
+
# display(HTML(output))
|
383
476
|
else:
|
384
477
|
print(f"Exception report saved to {filename}")
|
478
|
+
import webbrowser
|
479
|
+
import os
|
385
480
|
|
386
|
-
if open_in_browser:
|
387
481
|
webbrowser.open(f"file://{os.path.abspath(filename)}")
|
388
482
|
|
389
483
|
if return_link:
|
390
484
|
return filename
|
391
485
|
|
392
|
-
def notebook(self):
|
393
|
-
"""Create a notebook with the HTML content embedded in the first cell, then delete the cell content while keeping the output."""
|
394
|
-
from nbformat import v4 as nbf
|
395
|
-
from nbconvert.preprocessors import ExecutePreprocessor
|
396
|
-
import nbformat
|
397
|
-
import os
|
398
|
-
|
399
|
-
# Use the existing html method to generate the HTML content
|
400
|
-
output_html = self.generate_html_report(css=None)
|
401
|
-
nb = nbf.new_notebook()
|
402
|
-
|
403
|
-
# Add a code cell that renders the HTML content
|
404
|
-
code_cell = nbf.new_code_cell(
|
405
|
-
f"""
|
406
|
-
from IPython.display import HTML, display
|
407
|
-
display(HTML('''{output_html}'''))
|
408
|
-
"""
|
409
|
-
)
|
410
|
-
nb.cells.append(code_cell)
|
411
|
-
|
412
|
-
# Execute the notebook
|
413
|
-
ep = ExecutePreprocessor(timeout=600, kernel_name="python3")
|
414
|
-
ep.preprocess(nb, {"metadata": {"path": os.getcwd()}})
|
415
|
-
|
416
|
-
# After execution, clear the cell's source code
|
417
|
-
nb.cells[0].source = ""
|
418
|
-
|
419
|
-
return nb
|
420
|
-
|
421
486
|
|
422
487
|
if __name__ == "__main__":
|
423
488
|
import doctest
|