edsl 0.1.38.dev2__py3-none-any.whl → 0.1.38.dev4__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 +60 -31
- edsl/__version__.py +1 -1
- edsl/agents/Agent.py +18 -9
- edsl/agents/AgentList.py +59 -8
- edsl/agents/Invigilator.py +18 -7
- edsl/agents/InvigilatorBase.py +0 -19
- edsl/agents/PromptConstructor.py +5 -4
- edsl/config.py +8 -0
- edsl/coop/coop.py +74 -7
- edsl/data/Cache.py +27 -2
- edsl/data/CacheEntry.py +8 -3
- edsl/data/RemoteCacheSync.py +0 -19
- edsl/enums.py +2 -0
- edsl/inference_services/GoogleService.py +7 -15
- edsl/inference_services/PerplexityService.py +163 -0
- edsl/inference_services/registry.py +2 -0
- edsl/jobs/Jobs.py +88 -548
- edsl/jobs/JobsChecks.py +147 -0
- edsl/jobs/JobsPrompts.py +268 -0
- edsl/jobs/JobsRemoteInferenceHandler.py +239 -0
- edsl/jobs/interviews/Interview.py +11 -11
- edsl/jobs/runners/JobsRunnerAsyncio.py +140 -35
- edsl/jobs/runners/JobsRunnerStatus.py +0 -2
- edsl/jobs/tasks/TaskHistory.py +15 -16
- edsl/language_models/LanguageModel.py +44 -84
- edsl/language_models/ModelList.py +47 -1
- edsl/language_models/registry.py +57 -4
- edsl/prompts/Prompt.py +8 -3
- edsl/questions/QuestionBase.py +20 -16
- edsl/questions/QuestionExtract.py +3 -4
- edsl/questions/question_registry.py +36 -6
- edsl/results/CSSParameterizer.py +108 -0
- edsl/results/Dataset.py +146 -15
- edsl/results/DatasetExportMixin.py +231 -217
- edsl/results/DatasetTree.py +134 -4
- edsl/results/Result.py +18 -9
- edsl/results/Results.py +145 -51
- edsl/results/TableDisplay.py +198 -0
- edsl/results/table_display.css +78 -0
- edsl/scenarios/FileStore.py +187 -13
- edsl/scenarios/Scenario.py +61 -4
- edsl/scenarios/ScenarioJoin.py +127 -0
- edsl/scenarios/ScenarioList.py +237 -62
- edsl/surveys/Survey.py +16 -2
- edsl/surveys/SurveyFlowVisualizationMixin.py +67 -9
- edsl/surveys/instructions/Instruction.py +12 -0
- edsl/templates/error_reporting/interview_details.html +3 -3
- edsl/templates/error_reporting/interviews.html +18 -9
- edsl/utilities/utilities.py +15 -0
- {edsl-0.1.38.dev2.dist-info → edsl-0.1.38.dev4.dist-info}/METADATA +2 -1
- {edsl-0.1.38.dev2.dist-info → edsl-0.1.38.dev4.dist-info}/RECORD +53 -45
- {edsl-0.1.38.dev2.dist-info → edsl-0.1.38.dev4.dist-info}/LICENSE +0 -0
- {edsl-0.1.38.dev2.dist-info → edsl-0.1.38.dev4.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
|
-
def print(
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
) -> Union[None, str, "Results"]:
|
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,6 +405,7 @@ class DatasetExportMixin:
|
|
405
405
|
writer = csv.writer(f)
|
406
406
|
writer.writerow(header)
|
407
407
|
writer.writerows(rows)
|
408
|
+
# print(f"Saved to {filename}")
|
408
409
|
else:
|
409
410
|
output = io.StringIO()
|
410
411
|
writer = csv.writer(output)
|
@@ -515,7 +516,14 @@ class DatasetExportMixin:
|
|
515
516
|
from edsl import AgentList, Agent
|
516
517
|
|
517
518
|
list_of_dicts = self.to_dicts(remove_prefix=remove_prefix)
|
518
|
-
|
519
|
+
agents = []
|
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)
|
519
527
|
|
520
528
|
def to_dicts(self, remove_prefix: bool = True) -> list[dict]:
|
521
529
|
"""Convert the results to a list of dictionaries.
|
@@ -651,9 +659,7 @@ class DatasetExportMixin:
|
|
651
659
|
>>> r.select('how_feeling').tally('answer.how_feeling', output = "dict")
|
652
660
|
{'OK': 2, 'Great': 1, 'Terrible': 1}
|
653
661
|
>>> r.select('how_feeling').tally('answer.how_feeling', output = "Dataset")
|
654
|
-
Dataset([{'
|
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}
|
662
|
+
Dataset([{'answer.how_feeling': ['OK', 'Great', 'Terrible']}, {'count': [2, 1, 1]}])
|
657
663
|
"""
|
658
664
|
from collections import Counter
|
659
665
|
|
@@ -664,8 +670,6 @@ class DatasetExportMixin:
|
|
664
670
|
column.split(".")[-1] for column in self.relevant_columns()
|
665
671
|
]
|
666
672
|
|
667
|
-
# breakpoint()
|
668
|
-
|
669
673
|
if not all(
|
670
674
|
f in self.relevant_columns() or f in relevant_columns_without_prefix
|
671
675
|
for f in fields
|
@@ -703,12 +707,22 @@ class DatasetExportMixin:
|
|
703
707
|
)
|
704
708
|
return sorted_tally
|
705
709
|
elif output == "Dataset":
|
706
|
-
|
710
|
+
dataset = Dataset(
|
707
711
|
[
|
708
712
|
{"value": list(sorted_tally.keys())},
|
709
713
|
{"count": list(sorted_tally.values())},
|
710
714
|
]
|
711
715
|
)
|
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()
|
712
726
|
|
713
727
|
|
714
728
|
if __name__ == "__main__":
|