edsl 0.1.38__py3-none-any.whl → 0.1.38.dev2__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 +31 -60
- edsl/__version__.py +1 -1
- edsl/agents/Agent.py +9 -18
- edsl/agents/AgentList.py +8 -59
- edsl/agents/Invigilator.py +7 -18
- edsl/agents/InvigilatorBase.py +19 -0
- edsl/agents/PromptConstructor.py +4 -5
- edsl/config.py +0 -8
- edsl/coop/coop.py +7 -74
- edsl/data/Cache.py +2 -27
- edsl/data/CacheEntry.py +3 -8
- edsl/data/RemoteCacheSync.py +19 -0
- edsl/enums.py +0 -2
- edsl/inference_services/GoogleService.py +15 -7
- edsl/inference_services/registry.py +0 -2
- edsl/jobs/Jobs.py +548 -88
- edsl/jobs/interviews/Interview.py +11 -11
- edsl/jobs/runners/JobsRunnerAsyncio.py +35 -140
- edsl/jobs/runners/JobsRunnerStatus.py +2 -0
- edsl/jobs/tasks/TaskHistory.py +16 -15
- edsl/language_models/LanguageModel.py +84 -44
- edsl/language_models/ModelList.py +1 -47
- edsl/language_models/registry.py +4 -57
- edsl/prompts/Prompt.py +3 -8
- edsl/questions/QuestionBase.py +16 -20
- edsl/questions/QuestionExtract.py +4 -3
- edsl/questions/question_registry.py +6 -36
- edsl/results/Dataset.py +15 -146
- edsl/results/DatasetExportMixin.py +217 -231
- edsl/results/DatasetTree.py +4 -134
- edsl/results/Result.py +9 -18
- edsl/results/Results.py +51 -145
- edsl/scenarios/FileStore.py +13 -187
- edsl/scenarios/Scenario.py +4 -61
- edsl/scenarios/ScenarioList.py +62 -237
- edsl/surveys/Survey.py +2 -16
- edsl/surveys/SurveyFlowVisualizationMixin.py +9 -67
- edsl/surveys/instructions/Instruction.py +0 -12
- edsl/templates/error_reporting/interview_details.html +3 -3
- edsl/templates/error_reporting/interviews.html +9 -18
- edsl/utilities/utilities.py +0 -15
- {edsl-0.1.38.dist-info → edsl-0.1.38.dev2.dist-info}/METADATA +1 -2
- {edsl-0.1.38.dist-info → edsl-0.1.38.dev2.dist-info}/RECORD +45 -53
- edsl/inference_services/PerplexityService.py +0 -163
- edsl/jobs/JobsChecks.py +0 -147
- edsl/jobs/JobsPrompts.py +0 -268
- edsl/jobs/JobsRemoteInferenceHandler.py +0 -239
- edsl/results/CSSParameterizer.py +0 -108
- edsl/results/TableDisplay.py +0 -198
- edsl/results/table_display.css +0 -78
- edsl/scenarios/ScenarioJoin.py +0 -127
- {edsl-0.1.38.dist-info → edsl-0.1.38.dev2.dist-info}/LICENSE +0 -0
- {edsl-0.1.38.dist-info → edsl-0.1.38.dev2.dist-info}/WHEEL +0 -0
@@ -144,216 +144,216 @@ class DatasetExportMixin:
|
|
144
144
|
for value in list_of_values:
|
145
145
|
print(f"{key}: {value}")
|
146
146
|
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
-
|
177
|
-
|
178
|
-
|
179
|
-
|
180
|
-
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
|
186
|
-
|
187
|
-
|
188
|
-
|
189
|
-
|
190
|
-
|
191
|
-
|
192
|
-
|
193
|
-
|
194
|
-
|
195
|
-
|
196
|
-
|
197
|
-
|
198
|
-
|
199
|
-
|
200
|
-
|
201
|
-
|
202
|
-
|
203
|
-
|
204
|
-
|
205
|
-
|
206
|
-
|
207
|
-
|
208
|
-
|
209
|
-
|
210
|
-
|
211
|
-
|
212
|
-
|
213
|
-
|
214
|
-
|
215
|
-
|
216
|
-
|
217
|
-
|
218
|
-
|
219
|
-
|
220
|
-
|
221
|
-
|
222
|
-
|
223
|
-
|
224
|
-
|
225
|
-
|
226
|
-
|
227
|
-
|
228
|
-
|
229
|
-
|
230
|
-
|
231
|
-
|
232
|
-
|
233
|
-
|
234
|
-
|
235
|
-
|
236
|
-
|
237
|
-
|
238
|
-
|
239
|
-
|
240
|
-
|
241
|
-
|
242
|
-
|
243
|
-
|
244
|
-
|
245
|
-
|
246
|
-
|
247
|
-
|
248
|
-
|
249
|
-
|
250
|
-
|
251
|
-
|
252
|
-
|
253
|
-
|
254
|
-
|
255
|
-
|
256
|
-
|
257
|
-
|
258
|
-
|
259
|
-
|
260
|
-
|
261
|
-
|
262
|
-
|
263
|
-
|
264
|
-
|
265
|
-
|
266
|
-
|
267
|
-
|
268
|
-
|
269
|
-
|
270
|
-
|
271
|
-
|
272
|
-
|
273
|
-
|
274
|
-
|
275
|
-
|
276
|
-
|
277
|
-
|
278
|
-
|
279
|
-
|
280
|
-
|
281
|
-
|
282
|
-
|
283
|
-
|
284
|
-
|
285
|
-
|
286
|
-
|
287
|
-
|
288
|
-
|
289
|
-
|
290
|
-
|
291
|
-
|
292
|
-
|
293
|
-
|
294
|
-
|
295
|
-
|
296
|
-
|
297
|
-
|
298
|
-
|
299
|
-
|
300
|
-
|
301
|
-
|
302
|
-
|
303
|
-
|
304
|
-
|
305
|
-
|
306
|
-
|
307
|
-
|
308
|
-
|
309
|
-
|
310
|
-
|
311
|
-
|
312
|
-
|
313
|
-
|
314
|
-
|
315
|
-
|
316
|
-
|
317
|
-
|
318
|
-
|
319
|
-
|
320
|
-
|
321
|
-
|
322
|
-
|
323
|
-
|
324
|
-
|
325
|
-
|
326
|
-
|
327
|
-
|
328
|
-
|
329
|
-
|
330
|
-
|
331
|
-
|
332
|
-
|
333
|
-
|
334
|
-
|
335
|
-
|
336
|
-
|
337
|
-
|
338
|
-
|
339
|
-
|
340
|
-
|
341
|
-
|
342
|
-
|
343
|
-
|
344
|
-
|
345
|
-
|
346
|
-
|
347
|
-
|
348
|
-
|
349
|
-
|
350
|
-
|
351
|
-
|
352
|
-
|
353
|
-
|
354
|
-
|
355
|
-
|
356
|
-
|
147
|
+
def print(
|
148
|
+
self,
|
149
|
+
pretty_labels: Optional[dict] = None,
|
150
|
+
filename: Optional[str] = None,
|
151
|
+
format: Optional[Literal["rich", "html", "markdown", "latex"]] = None,
|
152
|
+
interactive: bool = False,
|
153
|
+
split_at_dot: bool = True,
|
154
|
+
max_rows=None,
|
155
|
+
tee=False,
|
156
|
+
iframe=False,
|
157
|
+
iframe_height: int = 200,
|
158
|
+
iframe_width: int = 600,
|
159
|
+
web=False,
|
160
|
+
return_string: bool = False,
|
161
|
+
) -> Union[None, str, "Results"]:
|
162
|
+
"""Print the results in a pretty format.
|
163
|
+
|
164
|
+
:param pretty_labels: A dictionary of pretty labels for the columns.
|
165
|
+
:param filename: The filename to save the results to.
|
166
|
+
:param format: The format to print the results in. Options are 'rich', 'html', 'markdown', or 'latex'.
|
167
|
+
:param interactive: Whether to print the results interactively in a Jupyter notebook.
|
168
|
+
:param split_at_dot: Whether to split the column names at the last dot w/ a newline.
|
169
|
+
:param max_rows: The maximum number of rows to print.
|
170
|
+
:param tee: Whether to return the dataset.
|
171
|
+
:param iframe: Whether to display the table in an iframe.
|
172
|
+
:param iframe_height: The height of the iframe.
|
173
|
+
:param iframe_width: The width of the iframe.
|
174
|
+
:param web: Whether to display the table in a web browser.
|
175
|
+
:param return_string: Whether to return the output as a string instead of printing.
|
176
|
+
|
177
|
+
:return: None if tee is False and return_string is False, the dataset if tee is True, or a string if return_string is True.
|
178
|
+
|
179
|
+
Example: Print in rich format at the terminal
|
180
|
+
|
181
|
+
>>> from edsl.results import Results
|
182
|
+
>>> r = Results.example()
|
183
|
+
>>> r.select('how_feeling').print(format = "rich")
|
184
|
+
┏━━━━━━━━━━━━━━┓
|
185
|
+
┃ answer ┃
|
186
|
+
┃ .how_feeling ┃
|
187
|
+
┡━━━━━━━━━━━━━━┩
|
188
|
+
│ OK │
|
189
|
+
├──────────────┤
|
190
|
+
│ Great │
|
191
|
+
├──────────────┤
|
192
|
+
│ Terrible │
|
193
|
+
├──────────────┤
|
194
|
+
│ OK │
|
195
|
+
└──────────────┘
|
196
|
+
|
197
|
+
>>> r = Results.example()
|
198
|
+
>>> r2 = r.select("how_feeling").print(format = "rich", tee = True, max_rows = 2)
|
199
|
+
┏━━━━━━━━━━━━━━┓
|
200
|
+
┃ answer ┃
|
201
|
+
┃ .how_feeling ┃
|
202
|
+
┡━━━━━━━━━━━━━━┩
|
203
|
+
│ OK │
|
204
|
+
├──────────────┤
|
205
|
+
│ Great │
|
206
|
+
└──────────────┘
|
207
|
+
>>> r2
|
208
|
+
Dataset([{'answer.how_feeling': ['OK', 'Great', 'Terrible', 'OK']}])
|
209
|
+
|
210
|
+
>>> r.select('how_feeling').print(format = "rich", max_rows = 2)
|
211
|
+
┏━━━━━━━━━━━━━━┓
|
212
|
+
┃ answer ┃
|
213
|
+
┃ .how_feeling ┃
|
214
|
+
┡━━━━━━━━━━━━━━┩
|
215
|
+
│ OK │
|
216
|
+
├──────────────┤
|
217
|
+
│ Great │
|
218
|
+
└──────────────┘
|
219
|
+
|
220
|
+
>>> r.select('how_feeling').print(format = "rich", split_at_dot = False)
|
221
|
+
┏━━━━━━━━━━━━━━━━━━━━┓
|
222
|
+
┃ answer.how_feeling ┃
|
223
|
+
┡━━━━━━━━━━━━━━━━━━━━┩
|
224
|
+
│ OK │
|
225
|
+
├────────────────────┤
|
226
|
+
│ Great │
|
227
|
+
├────────────────────┤
|
228
|
+
│ Terrible │
|
229
|
+
├────────────────────┤
|
230
|
+
│ OK │
|
231
|
+
└────────────────────┘
|
232
|
+
|
233
|
+
Example: using the pretty_labels parameter
|
234
|
+
|
235
|
+
>>> r.select('how_feeling').print(format="rich", pretty_labels = {'answer.how_feeling': "How are you feeling"})
|
236
|
+
┏━━━━━━━━━━━━━━━━━━━━━┓
|
237
|
+
┃ How are you feeling ┃
|
238
|
+
┡━━━━━━━━━━━━━━━━━━━━━┩
|
239
|
+
│ OK │
|
240
|
+
├─────────────────────┤
|
241
|
+
│ Great │
|
242
|
+
├─────────────────────┤
|
243
|
+
│ Terrible │
|
244
|
+
├─────────────────────┤
|
245
|
+
│ OK │
|
246
|
+
└─────────────────────┘
|
247
|
+
|
248
|
+
Example: printing in markdown format
|
249
|
+
|
250
|
+
>>> r.select('how_feeling').print(format='markdown')
|
251
|
+
| answer.how_feeling |
|
252
|
+
|--|
|
253
|
+
| OK |
|
254
|
+
| Great |
|
255
|
+
| Terrible |
|
256
|
+
| OK |
|
257
|
+
...
|
258
|
+
|
259
|
+
>>> r.select('how_feeling').print(format='latex')
|
260
|
+
\\begin{tabular}{l}
|
261
|
+
...
|
262
|
+
\\end{tabular}
|
263
|
+
<BLANKLINE>
|
264
|
+
"""
|
265
|
+
from IPython.display import HTML, display
|
266
|
+
from edsl.utilities.utilities import is_notebook
|
267
|
+
import io
|
268
|
+
import sys
|
269
|
+
|
270
|
+
def _determine_format(format):
|
271
|
+
if format is None:
|
272
|
+
if is_notebook():
|
273
|
+
format = "html"
|
274
|
+
else:
|
275
|
+
format = "rich"
|
276
|
+
if format not in ["rich", "html", "markdown", "latex"]:
|
277
|
+
raise ValueError(
|
278
|
+
"format must be one of 'rich', 'html', 'markdown', or 'latex'."
|
279
|
+
)
|
280
|
+
|
281
|
+
return format
|
282
|
+
|
283
|
+
format = _determine_format(format)
|
284
|
+
|
285
|
+
if pretty_labels is None:
|
286
|
+
pretty_labels = {}
|
287
|
+
|
288
|
+
if pretty_labels != {}: # only split at dot if there are no pretty labels
|
289
|
+
split_at_dot = False
|
290
|
+
|
291
|
+
def _create_data():
|
292
|
+
for index, entry in enumerate(self):
|
293
|
+
key, list_of_values = list(entry.items())[0]
|
294
|
+
yield {pretty_labels.get(key, key): list_of_values[:max_rows]}
|
295
|
+
|
296
|
+
new_data = list(_create_data())
|
297
|
+
|
298
|
+
# Capture output if return_string is True
|
299
|
+
if return_string:
|
300
|
+
old_stdout = sys.stdout
|
301
|
+
sys.stdout = io.StringIO()
|
302
|
+
|
303
|
+
output = None
|
304
|
+
|
305
|
+
if format == "rich":
|
306
|
+
from edsl.utilities.interface import print_dataset_with_rich
|
307
|
+
|
308
|
+
output = print_dataset_with_rich(
|
309
|
+
new_data, filename=filename, split_at_dot=split_at_dot
|
310
|
+
)
|
311
|
+
elif format == "markdown":
|
312
|
+
from edsl.utilities.interface import print_list_of_dicts_as_markdown_table
|
313
|
+
|
314
|
+
output = print_list_of_dicts_as_markdown_table(new_data, filename=filename)
|
315
|
+
elif format == "latex":
|
316
|
+
df = self.to_pandas()
|
317
|
+
df.columns = [col.replace("_", " ") for col in df.columns]
|
318
|
+
latex_string = df.to_latex(index=False)
|
319
|
+
|
320
|
+
if filename is not None:
|
321
|
+
with open(filename, "w") as f:
|
322
|
+
f.write(latex_string)
|
323
|
+
else:
|
324
|
+
print(latex_string)
|
325
|
+
output = latex_string
|
326
|
+
elif format == "html":
|
327
|
+
from edsl.utilities.interface import print_list_of_dicts_as_html_table
|
328
|
+
|
329
|
+
html_source = print_list_of_dicts_as_html_table(
|
330
|
+
new_data, interactive=interactive
|
331
|
+
)
|
332
|
+
|
333
|
+
if iframe:
|
334
|
+
iframe = f""""
|
335
|
+
<iframe srcdoc="{ html.escape(html_source) }" style="width: {iframe_width}px; height: {iframe_height}px;"></iframe>
|
336
|
+
"""
|
337
|
+
display(HTML(iframe))
|
338
|
+
elif is_notebook():
|
339
|
+
display(HTML(html_source))
|
340
|
+
else:
|
341
|
+
from edsl.utilities.interface import view_html
|
342
|
+
|
343
|
+
view_html(html_source)
|
344
|
+
|
345
|
+
output = html_source
|
346
|
+
|
347
|
+
# Restore stdout and get captured output if return_string is True
|
348
|
+
if return_string:
|
349
|
+
captured_output = sys.stdout.getvalue()
|
350
|
+
sys.stdout = old_stdout
|
351
|
+
return captured_output or output
|
352
|
+
|
353
|
+
if tee:
|
354
|
+
return self
|
355
|
+
|
356
|
+
return None
|
357
357
|
|
358
358
|
def to_csv(
|
359
359
|
self,
|
@@ -405,7 +405,6 @@ class DatasetExportMixin:
|
|
405
405
|
writer = csv.writer(f)
|
406
406
|
writer.writerow(header)
|
407
407
|
writer.writerows(rows)
|
408
|
-
# print(f"Saved to {filename}")
|
409
408
|
else:
|
410
409
|
output = io.StringIO()
|
411
410
|
writer = csv.writer(output)
|
@@ -516,14 +515,7 @@ class DatasetExportMixin:
|
|
516
515
|
from edsl import AgentList, Agent
|
517
516
|
|
518
517
|
list_of_dicts = self.to_dicts(remove_prefix=remove_prefix)
|
519
|
-
|
520
|
-
for d in list_of_dicts:
|
521
|
-
if "name" in d:
|
522
|
-
d["agent_name"] = d.pop("name")
|
523
|
-
agents.append(Agent(d, name=d["agent_name"]))
|
524
|
-
else:
|
525
|
-
agents.append(Agent(d))
|
526
|
-
return AgentList(agents)
|
518
|
+
return AgentList([Agent(d) for d in list_of_dicts])
|
527
519
|
|
528
520
|
def to_dicts(self, remove_prefix: bool = True) -> list[dict]:
|
529
521
|
"""Convert the results to a list of dictionaries.
|
@@ -659,7 +651,9 @@ class DatasetExportMixin:
|
|
659
651
|
>>> r.select('how_feeling').tally('answer.how_feeling', output = "dict")
|
660
652
|
{'OK': 2, 'Great': 1, 'Terrible': 1}
|
661
653
|
>>> r.select('how_feeling').tally('answer.how_feeling', output = "Dataset")
|
662
|
-
Dataset([{'
|
654
|
+
Dataset([{'value': ['OK', 'Great', 'Terrible']}, {'count': [2, 1, 1]}])
|
655
|
+
>>> r.select('how_feeling', 'period').tally('how_feeling', 'period', output = "dict")
|
656
|
+
{('OK', 'morning'): 1, ('Great', 'afternoon'): 1, ('Terrible', 'morning'): 1, ('OK', 'afternoon'): 1}
|
663
657
|
"""
|
664
658
|
from collections import Counter
|
665
659
|
|
@@ -670,6 +664,8 @@ class DatasetExportMixin:
|
|
670
664
|
column.split(".")[-1] for column in self.relevant_columns()
|
671
665
|
]
|
672
666
|
|
667
|
+
# breakpoint()
|
668
|
+
|
673
669
|
if not all(
|
674
670
|
f in self.relevant_columns() or f in relevant_columns_without_prefix
|
675
671
|
for f in fields
|
@@ -707,22 +703,12 @@ class DatasetExportMixin:
|
|
707
703
|
)
|
708
704
|
return sorted_tally
|
709
705
|
elif output == "Dataset":
|
710
|
-
|
706
|
+
return Dataset(
|
711
707
|
[
|
712
708
|
{"value": list(sorted_tally.keys())},
|
713
709
|
{"count": list(sorted_tally.values())},
|
714
710
|
]
|
715
711
|
)
|
716
|
-
# return dataset
|
717
|
-
sl = dataset.to_scenario_list().unpack(
|
718
|
-
"value",
|
719
|
-
new_names=[fields] if isinstance(fields, str) else fields,
|
720
|
-
keep_original=False,
|
721
|
-
)
|
722
|
-
keys = list(sl[0].keys())
|
723
|
-
keys.remove("count")
|
724
|
-
keys.append("count")
|
725
|
-
return sl.reorder_keys(keys).to_dataset()
|
726
712
|
|
727
713
|
|
728
714
|
if __name__ == "__main__":
|