edsl 0.1.41__py3-none-any.whl → 0.1.42__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/__version__.py +1 -1
- edsl/agents/Invigilator.py +3 -2
- edsl/agents/InvigilatorBase.py +2 -1
- edsl/agents/QuestionTemplateReplacementsBuilder.py +7 -2
- edsl/coop/coop.py +32 -0
- edsl/enums.py +3 -0
- edsl/exceptions/jobs.py +1 -9
- edsl/exceptions/language_models.py +8 -4
- edsl/exceptions/questions.py +8 -11
- edsl/inference_services/DeepSeekService.py +18 -0
- edsl/inference_services/registry.py +2 -0
- edsl/jobs/Jobs.py +18 -11
- edsl/jobs/JobsPrompts.py +11 -1
- edsl/jobs/JobsRemoteInferenceHandler.py +1 -0
- edsl/jobs/JobsRemoteInferenceLogger.py +1 -1
- edsl/jobs/interviews/Interview.py +1 -1
- edsl/jobs/loggers/HTMLTableJobLogger.py +6 -1
- edsl/jobs/results_exceptions_handler.py +2 -7
- edsl/jobs/tasks/TaskHistory.py +49 -17
- edsl/language_models/LanguageModel.py +7 -4
- edsl/language_models/ModelList.py +1 -1
- edsl/language_models/model.py +49 -0
- edsl/questions/descriptors.py +5 -5
- edsl/results/Result.py +9 -3
- edsl/results/Results.py +1 -1
- edsl/scenarios/PdfExtractor.py +3 -6
- edsl/scenarios/Scenario.py +2 -1
- edsl/surveys/Survey.py +1 -1
- edsl/templates/error_reporting/base.html +2 -4
- edsl/templates/error_reporting/exceptions_table.html +35 -0
- edsl/templates/error_reporting/interview_details.html +67 -53
- edsl/templates/error_reporting/interviews.html +4 -17
- edsl/templates/error_reporting/overview.html +31 -5
- edsl/templates/error_reporting/performance_plot.html +1 -1
- {edsl-0.1.41.dist-info → edsl-0.1.42.dist-info}/METADATA +2 -2
- {edsl-0.1.41.dist-info → edsl-0.1.42.dist-info}/RECORD +38 -36
- {edsl-0.1.41.dist-info → edsl-0.1.42.dist-info}/LICENSE +0 -0
- {edsl-0.1.41.dist-info → edsl-0.1.42.dist-info}/WHEEL +0 -0
edsl/questions/descriptors.py
CHANGED
@@ -302,10 +302,10 @@ class QuestionOptionsDescriptor(BaseDescriptor):
|
|
302
302
|
raise QuestionCreationValidationError(
|
303
303
|
f"Question options must be a list (got {value})."
|
304
304
|
)
|
305
|
-
if len(value) > Settings.MAX_NUM_OPTIONS:
|
306
|
-
|
307
|
-
|
308
|
-
|
305
|
+
# if len(value) > Settings.MAX_NUM_OPTIONS:
|
306
|
+
# raise QuestionCreationValidationError(
|
307
|
+
# f"Too many question options (got {value})."
|
308
|
+
# )
|
309
309
|
if len(value) < Settings.MIN_NUM_OPTIONS:
|
310
310
|
raise QuestionCreationValidationError(
|
311
311
|
f"Too few question options (got {value})."
|
@@ -408,7 +408,7 @@ class QuestionTextDescriptor(BaseDescriptor):
|
|
408
408
|
# Automatically replace single braces with double braces
|
409
409
|
# This is here because if the user is using an f-string, the double brace will get converted to a single brace.
|
410
410
|
# This undoes that.
|
411
|
-
value = re.sub(r"\{([^\{\}]+)\}", r"{{\1}}", value)
|
411
|
+
# value = re.sub(r"\{([^\{\}]+)\}", r"{{\1}}", value)
|
412
412
|
return value
|
413
413
|
|
414
414
|
# iterate through all doubles braces and check if they are valid python identifiers
|
edsl/results/Result.py
CHANGED
@@ -78,7 +78,6 @@ class Result(Base, UserDict):
|
|
78
78
|
self.question_to_attributes = (
|
79
79
|
question_to_attributes or self._create_question_to_attributes(survey)
|
80
80
|
)
|
81
|
-
|
82
81
|
data = {
|
83
82
|
"agent": agent,
|
84
83
|
"scenario": scenario,
|
@@ -87,7 +86,7 @@ class Result(Base, UserDict):
|
|
87
86
|
"answer": answer,
|
88
87
|
"prompt": prompt or {},
|
89
88
|
"raw_model_response": raw_model_response or {},
|
90
|
-
"question_to_attributes": question_to_attributes,
|
89
|
+
"question_to_attributes": self.question_to_attributes,
|
91
90
|
"generated_tokens": generated_tokens or {},
|
92
91
|
"comments_dict": comments_dict or {},
|
93
92
|
"cache_used_dict": cache_used_dict or {},
|
@@ -154,7 +153,9 @@ class Result(Base, UserDict):
|
|
154
153
|
@staticmethod
|
155
154
|
def _create_model_sub_dict(model) -> dict:
|
156
155
|
return {
|
157
|
-
"model": model.parameters
|
156
|
+
"model": model.parameters
|
157
|
+
| {"model": model.model}
|
158
|
+
| {"inference_service": model._inference_service_},
|
158
159
|
}
|
159
160
|
|
160
161
|
@staticmethod
|
@@ -365,6 +366,10 @@ class Result(Base, UserDict):
|
|
365
366
|
else prompt_obj.to_dict()
|
366
367
|
)
|
367
368
|
d[key] = new_prompt_dict
|
369
|
+
|
370
|
+
if self.indices is not None:
|
371
|
+
d["indices"] = self.indices
|
372
|
+
|
368
373
|
if add_edsl_version:
|
369
374
|
from edsl import __version__
|
370
375
|
|
@@ -414,6 +419,7 @@ class Result(Base, UserDict):
|
|
414
419
|
comments_dict=json_dict.get("comments_dict", {}),
|
415
420
|
cache_used_dict=json_dict.get("cache_used_dict", {}),
|
416
421
|
cache_keys=json_dict.get("cache_keys", {}),
|
422
|
+
indices = json_dict.get("indices", None)
|
417
423
|
)
|
418
424
|
return result
|
419
425
|
|
edsl/results/Results.py
CHANGED
@@ -647,7 +647,7 @@ class Results(UserList, Mixins, Base):
|
|
647
647
|
|
648
648
|
>>> r = Results.example()
|
649
649
|
>>> r.model_keys
|
650
|
-
['frequency_penalty', 'logprobs', 'max_tokens', 'model', 'model_index', 'presence_penalty', 'temperature', 'top_logprobs', 'top_p']
|
650
|
+
['frequency_penalty', 'inference_service', 'logprobs', 'max_tokens', 'model', 'model_index', 'presence_penalty', 'temperature', 'top_logprobs', 'top_p']
|
651
651
|
"""
|
652
652
|
return sorted(self._data_type_to_keys["model"])
|
653
653
|
|
edsl/scenarios/PdfExtractor.py
CHANGED
@@ -2,14 +2,11 @@ import os
|
|
2
2
|
|
3
3
|
|
4
4
|
class PdfExtractor:
|
5
|
-
def __init__(self, pdf_path: str
|
5
|
+
def __init__(self, pdf_path: str):
|
6
6
|
self.pdf_path = pdf_path
|
7
|
-
self.constructor = parent_object.__class__
|
7
|
+
#self.constructor = parent_object.__class__
|
8
8
|
|
9
|
-
def
|
10
|
-
return self.constructor(self._get_pdf_dict())
|
11
|
-
|
12
|
-
def _get_pdf_dict(self) -> dict:
|
9
|
+
def get_pdf_dict(self) -> dict:
|
13
10
|
# Ensure the file exists
|
14
11
|
import fitz
|
15
12
|
|
edsl/scenarios/Scenario.py
CHANGED
@@ -358,7 +358,8 @@ class Scenario(Base, UserDict, ScenarioHtmlMixin):
|
|
358
358
|
def from_pdf(cls, pdf_path: str):
|
359
359
|
from edsl.scenarios.PdfExtractor import PdfExtractor
|
360
360
|
|
361
|
-
|
361
|
+
extractor = PdfExtractor(pdf_path)
|
362
|
+
return Scenario(extractor.get_pdf_dict())
|
362
363
|
|
363
364
|
@classmethod
|
364
365
|
def from_docx(cls, docx_path: str) -> "Scenario":
|
edsl/surveys/Survey.py
CHANGED
@@ -3,7 +3,7 @@
|
|
3
3
|
<head>
|
4
4
|
<meta charset="UTF-8">
|
5
5
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
6
|
-
<title>
|
6
|
+
<title>Exceptions Report</title>
|
7
7
|
<style>
|
8
8
|
{{ css }}
|
9
9
|
</style>
|
@@ -15,9 +15,7 @@
|
|
15
15
|
</head>
|
16
16
|
<body>
|
17
17
|
{% include 'overview.html' %}
|
18
|
-
{% include '
|
19
|
-
{% include 'exceptions_by_model.html' %}
|
20
|
-
{% include 'exceptions_by_question_name.html' %}
|
18
|
+
{% include 'exceptions_table.html' %}
|
21
19
|
{% include 'interviews.html' %}
|
22
20
|
{% include 'performance_plot.html' %}
|
23
21
|
</body>
|
@@ -0,0 +1,35 @@
|
|
1
|
+
<style>
|
2
|
+
th, td {
|
3
|
+
padding: 0 10px; /* This applies the padding uniformly to all td elements */
|
4
|
+
}
|
5
|
+
</style>
|
6
|
+
|
7
|
+
<table border="1">
|
8
|
+
<thead>
|
9
|
+
<tr>
|
10
|
+
<th>Exception Type</th>
|
11
|
+
<th>Service</th>
|
12
|
+
<th>Model</th>
|
13
|
+
<th>Question Name</th>
|
14
|
+
<th>Total</th>
|
15
|
+
</tr>
|
16
|
+
</thead>
|
17
|
+
<tbody>
|
18
|
+
{% for (exception_type, service, model, question_name), count in exceptions_table.items() %}
|
19
|
+
<tr>
|
20
|
+
<td>{{ exception_type }}</td>
|
21
|
+
<td>{{ service }}</td>
|
22
|
+
<td>{{ model }}</td>
|
23
|
+
<td>{{ question_name }}</td>
|
24
|
+
<td>{{ count }}</td>
|
25
|
+
</tr>
|
26
|
+
{% endfor %}
|
27
|
+
</tbody>
|
28
|
+
</table>
|
29
|
+
<p>
|
30
|
+
<i>Note:</i> You may encounter repeated exceptions where retries were attempted.
|
31
|
+
You can modify the maximum number of attempts for failed API calls in `edsl/config.py`.
|
32
|
+
</p>
|
33
|
+
<p>
|
34
|
+
Click to expand the details below for information about each exception, including code for reproducing it.
|
35
|
+
</p>
|
@@ -1,43 +1,67 @@
|
|
1
|
-
<
|
2
|
-
|
1
|
+
<style>
|
2
|
+
td {
|
3
|
+
padding: 0 10px; /* This applies the padding uniformly to all td elements */
|
4
|
+
}
|
5
|
+
.toggle-btn {
|
6
|
+
background-color: #4CAF50;
|
7
|
+
color: white;
|
8
|
+
border: none;
|
9
|
+
padding: 10px 20px;
|
10
|
+
text-align: center;
|
11
|
+
text-decoration: none;
|
12
|
+
display: inline-block;
|
13
|
+
font-size: 16px;
|
14
|
+
margin: 4px 2px;
|
15
|
+
cursor: pointer;
|
16
|
+
border-radius: 8px;
|
17
|
+
white-space: nowrap;
|
18
|
+
}
|
19
|
+
.toggle-btn span.collapse {
|
20
|
+
display: none;
|
21
|
+
}
|
22
|
+
.exception-content {
|
23
|
+
max-width: 100%; /* Adjust this value based on your layout */
|
24
|
+
overflow-x: auto; /* Enables horizontal scrolling */
|
25
|
+
}
|
26
|
+
</style>
|
3
27
|
|
4
|
-
<
|
28
|
+
<div class="question">question_name: {{ question }}</div>
|
5
29
|
|
6
30
|
{% for exception_message in exceptions %}
|
7
31
|
<div class="exception-detail">
|
8
|
-
|
32
|
+
<div class="exception-header">
|
9
33
|
<span class="exception-exception">Exception: {{ exception_message.name }}</span>
|
10
|
-
<button class="toggle-btn"
|
11
|
-
|
12
|
-
|
34
|
+
<button id="toggleBtn" class="toggle-btn" onclick="toggleButton(this)" aria-expanded="false">
|
35
|
+
<span class="expand"> ▼ </span>
|
36
|
+
</button>
|
37
|
+
</div>
|
38
|
+
<div class="exception-content">
|
13
39
|
<table border="1">
|
14
|
-
<tr>
|
15
|
-
<th>Key</th>
|
16
|
-
<th>Value</th>
|
17
|
-
</tr>
|
18
40
|
<tr>
|
19
41
|
<td>Interview ID (index in results)</td>
|
20
42
|
<td>{{ index }}</td>
|
21
43
|
</tr>
|
22
44
|
<tr>
|
23
|
-
<td>Question name
|
45
|
+
<td>Question name</td>
|
24
46
|
<td>{{ question }}</td>
|
25
47
|
</tr>
|
26
|
-
|
27
48
|
<tr>
|
28
|
-
<td>Question type
|
49
|
+
<td>Question type</td>
|
29
50
|
<td>{{ exception_message.question_type }}</td>
|
30
51
|
</tr>
|
31
|
-
|
32
52
|
<tr>
|
33
53
|
<td>Human-readable question</td>
|
34
54
|
<td>{{ interview.survey._get_question_by_name(question).html(
|
35
55
|
scenario = interview.scenario,
|
36
56
|
agent = interview.agent,
|
37
|
-
answers = exception_message.answers
|
38
|
-
|
57
|
+
answers = exception_message.answers
|
58
|
+
)
|
39
59
|
}}</td>
|
40
60
|
</tr>
|
61
|
+
<tr>
|
62
|
+
<td>User Prompt</td>
|
63
|
+
<td><pre>{{ exception_message.rendered_prompts['user_prompt'] }}</pre></td>
|
64
|
+
</tr>
|
41
65
|
<tr>
|
42
66
|
<td>Scenario</td>
|
43
67
|
<td>{{ interview.scenario.__repr__() }}</td>
|
@@ -47,24 +71,20 @@
|
|
47
71
|
<td>{{ interview.agent.__repr__() }}</td>
|
48
72
|
</tr>
|
49
73
|
<tr>
|
50
|
-
<td>
|
51
|
-
<td>{{
|
74
|
+
<td>System Prompt</td>
|
75
|
+
<td><pre>{{ exception_message.rendered_prompts['system_prompt'] }}</pre></td>
|
52
76
|
</tr>
|
53
77
|
<tr>
|
54
78
|
<td>Inference service</td>
|
55
79
|
<td>{{ interview.model._inference_service_ }}</td>
|
56
80
|
</tr>
|
57
81
|
<tr>
|
58
|
-
<td>Model
|
59
|
-
<td>{{ interview.model.
|
60
|
-
</tr>
|
61
|
-
<tr>
|
62
|
-
<td>User Prompt</td>
|
63
|
-
<td><pre>{{ exception_message.rendered_prompts['user_prompt'] }}</pre></td>
|
82
|
+
<td>Model name</td>
|
83
|
+
<td>{{ interview.model.model }}</td>
|
64
84
|
</tr>
|
65
85
|
<tr>
|
66
|
-
<td>
|
67
|
-
<td
|
86
|
+
<td>Model parameters</td>
|
87
|
+
<td>{{ interview.model.__repr__() }}</td>
|
68
88
|
</tr>
|
69
89
|
<tr>
|
70
90
|
<td>Raw model response</td>
|
@@ -77,7 +97,7 @@
|
|
77
97
|
</td>
|
78
98
|
</tr>
|
79
99
|
<tr>
|
80
|
-
<td>Code to
|
100
|
+
<td>Code likely to reproduce the error</td>
|
81
101
|
<td>
|
82
102
|
<textarea id="codeToCopy" rows="10" cols="90">{{ exception_message.code_to_reproduce }}</textarea>
|
83
103
|
<button onclick="copyCode()">Copy</button>
|
@@ -85,32 +105,26 @@
|
|
85
105
|
</tr>
|
86
106
|
|
87
107
|
</table>
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
</
|
105
|
-
|
106
|
-
|
107
|
-
<div class="exception-time">Time: {{ exception_message.time }}</div>
|
108
|
-
<div class="exception-traceback">Traceback:
|
109
|
-
<text>
|
110
|
-
<pre>{{ exception_message.traceback }}</pre>
|
111
|
-
</text>
|
112
|
-
</div>
|
108
|
+
|
109
|
+
{% if exception_message.exception.__class__.__name__ == 'QuestionAnswerValidationError' %}
|
110
|
+
<h3>Answer validation details</h3>
|
111
|
+
<table border="1">
|
112
|
+
{% for field, (open_tag, close_tag, value) in exception_message.exception.to_html_dict().items() %}
|
113
|
+
<tr>
|
114
|
+
<td>{{ field }}</td>
|
115
|
+
<td><{{ open_tag }}> {{ value | escape }} <{{ close_tag }}></td>
|
116
|
+
</tr>
|
117
|
+
{% endfor %}
|
118
|
+
</table>
|
119
|
+
{% endif %}
|
120
|
+
<br><br>
|
121
|
+
<div class="exception-time">Time: {{ exception_message.time }}</div>
|
122
|
+
<div class="exception-traceback">Traceback:
|
123
|
+
<text>
|
124
|
+
<pre>{{ exception_message.traceback }}</pre>
|
125
|
+
</text>
|
113
126
|
</div>
|
114
127
|
</div>
|
128
|
+
</div>
|
115
129
|
|
116
130
|
{% endfor %}
|
@@ -1,19 +1,6 @@
|
|
1
|
-
|
2
|
-
{% if interviews|length > max_interviews %}
|
3
|
-
<h1>Only showing the first {{ max_interviews }} interviews with errors</h1>
|
4
|
-
{% else %}
|
5
|
-
<h1>Showing all interviews</h1>
|
6
|
-
{% endif %}
|
7
|
-
|
1
|
+
<h2>Exceptions Details</h2>
|
8
2
|
{% for index, interview in interviews.items() %}
|
9
|
-
{%
|
10
|
-
{%
|
11
|
-
|
12
|
-
Model: {{ interview.model.model }}
|
13
|
-
<h1>Failing questions</h1>
|
14
|
-
{% endif %}
|
15
|
-
{% for question, exceptions in interview.exceptions.items() %}
|
16
|
-
{% include 'interview_details.html' %}
|
17
|
-
{% endfor %}
|
18
|
-
{% endif %}
|
3
|
+
{% for question, exceptions in interview.exceptions.items() %}
|
4
|
+
{% include 'interview_details.html' %}
|
5
|
+
{% endfor %}
|
19
6
|
{% endfor %}
|
@@ -1,5 +1,31 @@
|
|
1
|
-
<
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
1
|
+
<style>
|
2
|
+
td {
|
3
|
+
padding: 0 10px; /* This applies the padding uniformly to all td elements */
|
4
|
+
}
|
5
|
+
</style>
|
6
|
+
|
7
|
+
<h1>Exceptions Report</h1>
|
8
|
+
<p>
|
9
|
+
This report summarizes exceptions encountered in the job that was run.
|
10
|
+
</p>
|
11
|
+
<p>
|
12
|
+
For advice on dealing with exceptions, please see the EDSL <a href="https://docs.expectedparrot.com/en/latest/exceptions.html">documentation</a> page. <br>
|
13
|
+
You can also post a question at the Expected Parrot <a href="https://discord.com/invite/mxAYkjfy9m">Discord channel</a>, open an issue on <a href="https://github.com/expectedparrot/edsl">GitHub</a>, or send an email to <a href="mailto:info@expectedparrot.com">info@expectedparrot.com</a>.
|
14
|
+
</p>
|
15
|
+
|
16
|
+
<h2>Overview</h2>
|
17
|
+
<table border="1">
|
18
|
+
<tbody>
|
19
|
+
<tr>
|
20
|
+
<td>Total interviews</td>
|
21
|
+
<td>{{ interviews|length }}</td>
|
22
|
+
</tr>
|
23
|
+
<tr>
|
24
|
+
<td>Interviews with exceptions</td>
|
25
|
+
<td>{{ num_exceptions }}</td>
|
26
|
+
</tr>
|
27
|
+
</tbody>
|
28
|
+
</table>
|
29
|
+
<p>
|
30
|
+
An "interview" is the result of one survey, taken by one agent, with one model and one scenario (if any).
|
31
|
+
</p>
|
@@ -1,2 +1,2 @@
|
|
1
|
-
<
|
1
|
+
<h2>Performance Plot</h2>
|
2
2
|
{{ performance_plot_html }}
|
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.1
|
2
2
|
Name: edsl
|
3
|
-
Version: 0.1.
|
3
|
+
Version: 0.1.42
|
4
4
|
Summary: Create and analyze LLM-based surveys
|
5
5
|
Home-page: https://www.expectedparrot.com/
|
6
6
|
License: MIT
|
@@ -107,5 +107,5 @@ See instructions on [storing API keys](https://docs.expectedparrot.com/en/latest
|
|
107
107
|
|
108
108
|
## 💡 Contributions, feature requests & bugs
|
109
109
|
Interested in contributing? Want us to add a new feature? Found a bug for us to squash?
|
110
|
-
Please send us an email at [info@expectedparrot.com](mailto:info@expectedparrot.com) or message us at our [Discord channel](https://discord.com/invite/mxAYkjfy9m)
|
110
|
+
Please send us an email at [info@expectedparrot.com](mailto:info@expectedparrot.com) or message us at our [Discord channel](https://discord.com/invite/mxAYkjfy9m)..
|
111
111
|
|