edsl 0.1.39__py3-none-any.whl → 0.1.39.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 +116 -197
- edsl/__init__.py +7 -15
- edsl/__version__.py +1 -1
- edsl/agents/Agent.py +147 -351
- edsl/agents/AgentList.py +73 -211
- edsl/agents/Invigilator.py +50 -101
- edsl/agents/InvigilatorBase.py +70 -62
- edsl/agents/PromptConstructor.py +225 -143
- edsl/agents/__init__.py +1 -0
- edsl/agents/prompt_helpers.py +3 -3
- edsl/auto/AutoStudy.py +5 -18
- edsl/auto/StageBase.py +40 -53
- edsl/auto/StageQuestions.py +1 -2
- edsl/auto/utilities.py +6 -0
- edsl/config.py +2 -22
- edsl/conversation/car_buying.py +1 -2
- edsl/coop/PriceFetcher.py +1 -1
- edsl/coop/coop.py +47 -125
- edsl/coop/utils.py +14 -14
- edsl/data/Cache.py +27 -45
- edsl/data/CacheEntry.py +15 -12
- edsl/data/CacheHandler.py +12 -31
- edsl/data/RemoteCacheSync.py +46 -154
- edsl/data/__init__.py +3 -4
- edsl/data_transfer_models.py +1 -2
- edsl/enums.py +0 -27
- edsl/exceptions/__init__.py +50 -50
- edsl/exceptions/agents.py +0 -12
- edsl/exceptions/questions.py +6 -24
- edsl/exceptions/scenarios.py +0 -7
- edsl/inference_services/AnthropicService.py +19 -38
- edsl/inference_services/AwsBedrock.py +2 -0
- edsl/inference_services/AzureAI.py +2 -0
- edsl/inference_services/GoogleService.py +12 -7
- edsl/inference_services/InferenceServiceABC.py +85 -18
- edsl/inference_services/InferenceServicesCollection.py +79 -120
- edsl/inference_services/MistralAIService.py +3 -0
- edsl/inference_services/OpenAIService.py +35 -47
- edsl/inference_services/PerplexityService.py +3 -0
- edsl/inference_services/TestService.py +10 -11
- edsl/inference_services/TogetherAIService.py +3 -5
- edsl/jobs/Answers.py +14 -1
- edsl/jobs/Jobs.py +431 -356
- edsl/jobs/JobsChecks.py +10 -35
- edsl/jobs/JobsPrompts.py +4 -6
- edsl/jobs/JobsRemoteInferenceHandler.py +133 -205
- edsl/jobs/buckets/BucketCollection.py +3 -44
- edsl/jobs/buckets/TokenBucket.py +21 -53
- edsl/jobs/interviews/Interview.py +408 -143
- edsl/jobs/runners/JobsRunnerAsyncio.py +403 -88
- edsl/jobs/runners/JobsRunnerStatus.py +165 -133
- edsl/jobs/tasks/QuestionTaskCreator.py +19 -21
- edsl/jobs/tasks/TaskHistory.py +18 -38
- edsl/jobs/tasks/task_status_enum.py +2 -0
- edsl/language_models/KeyLookup.py +30 -0
- edsl/language_models/LanguageModel.py +236 -194
- edsl/language_models/ModelList.py +19 -28
- edsl/language_models/__init__.py +2 -1
- edsl/language_models/registry.py +190 -0
- edsl/language_models/repair.py +2 -2
- edsl/language_models/unused/ReplicateBase.py +83 -0
- edsl/language_models/utilities.py +4 -5
- edsl/notebooks/Notebook.py +14 -19
- edsl/prompts/Prompt.py +39 -29
- edsl/questions/{answer_validator_mixin.py → AnswerValidatorMixin.py} +2 -47
- edsl/questions/QuestionBase.py +214 -68
- edsl/questions/{question_base_gen_mixin.py → QuestionBaseGenMixin.py} +50 -57
- edsl/questions/QuestionBasePromptsMixin.py +3 -7
- edsl/questions/QuestionBudget.py +1 -1
- edsl/questions/QuestionCheckBox.py +3 -3
- edsl/questions/QuestionExtract.py +7 -5
- edsl/questions/QuestionFreeText.py +3 -2
- edsl/questions/QuestionList.py +18 -10
- edsl/questions/QuestionMultipleChoice.py +23 -67
- edsl/questions/QuestionNumerical.py +4 -2
- edsl/questions/QuestionRank.py +17 -7
- edsl/questions/{response_validator_abc.py → ResponseValidatorABC.py} +26 -40
- edsl/questions/SimpleAskMixin.py +3 -4
- edsl/questions/__init__.py +1 -2
- edsl/questions/derived/QuestionLinearScale.py +3 -6
- edsl/questions/derived/QuestionTopK.py +1 -1
- edsl/questions/descriptors.py +3 -17
- edsl/questions/question_registry.py +1 -1
- edsl/results/CSSParameterizer.py +1 -1
- edsl/results/Dataset.py +7 -170
- edsl/results/DatasetExportMixin.py +305 -168
- edsl/results/DatasetTree.py +8 -28
- edsl/results/Result.py +206 -298
- edsl/results/Results.py +131 -149
- edsl/results/ResultsDBMixin.py +238 -0
- edsl/results/ResultsExportMixin.py +0 -2
- edsl/results/{results_selector.py → Selector.py} +13 -23
- edsl/results/TableDisplay.py +171 -98
- edsl/results/__init__.py +1 -1
- edsl/scenarios/FileStore.py +239 -150
- edsl/scenarios/Scenario.py +193 -90
- edsl/scenarios/ScenarioHtmlMixin.py +3 -4
- edsl/scenarios/{scenario_join.py → ScenarioJoin.py} +6 -10
- edsl/scenarios/ScenarioList.py +244 -415
- edsl/scenarios/ScenarioListExportMixin.py +7 -0
- edsl/scenarios/ScenarioListPdfMixin.py +37 -15
- edsl/scenarios/__init__.py +2 -1
- edsl/study/ObjectEntry.py +1 -1
- edsl/study/SnapShot.py +1 -1
- edsl/study/Study.py +12 -5
- edsl/surveys/Rule.py +4 -5
- edsl/surveys/RuleCollection.py +27 -25
- edsl/surveys/Survey.py +791 -270
- edsl/surveys/SurveyCSS.py +8 -20
- edsl/surveys/{SurveyFlowVisualization.py → SurveyFlowVisualizationMixin.py} +9 -11
- edsl/surveys/__init__.py +2 -4
- edsl/surveys/descriptors.py +2 -6
- edsl/surveys/instructions/ChangeInstruction.py +2 -1
- edsl/surveys/instructions/Instruction.py +13 -4
- edsl/surveys/instructions/InstructionCollection.py +6 -11
- edsl/templates/error_reporting/interview_details.html +1 -1
- edsl/templates/error_reporting/report.html +1 -1
- edsl/tools/plotting.py +1 -1
- edsl/utilities/utilities.py +23 -35
- {edsl-0.1.39.dist-info → edsl-0.1.39.dev1.dist-info}/METADATA +10 -12
- edsl-0.1.39.dev1.dist-info/RECORD +277 -0
- {edsl-0.1.39.dist-info → edsl-0.1.39.dev1.dist-info}/WHEEL +1 -1
- edsl/agents/QuestionInstructionPromptBuilder.py +0 -128
- edsl/agents/QuestionTemplateReplacementsBuilder.py +0 -137
- edsl/agents/question_option_processor.py +0 -172
- edsl/coop/CoopFunctionsMixin.py +0 -15
- edsl/coop/ExpectedParrotKeyHandler.py +0 -125
- edsl/exceptions/inference_services.py +0 -5
- edsl/inference_services/AvailableModelCacheHandler.py +0 -184
- edsl/inference_services/AvailableModelFetcher.py +0 -215
- edsl/inference_services/ServiceAvailability.py +0 -135
- edsl/inference_services/data_structures.py +0 -134
- edsl/jobs/AnswerQuestionFunctionConstructor.py +0 -223
- edsl/jobs/FetchInvigilator.py +0 -47
- edsl/jobs/InterviewTaskManager.py +0 -98
- edsl/jobs/InterviewsConstructor.py +0 -50
- edsl/jobs/JobsComponentConstructor.py +0 -189
- edsl/jobs/JobsRemoteInferenceLogger.py +0 -239
- edsl/jobs/RequestTokenEstimator.py +0 -30
- edsl/jobs/async_interview_runner.py +0 -138
- edsl/jobs/buckets/TokenBucketAPI.py +0 -211
- edsl/jobs/buckets/TokenBucketClient.py +0 -191
- edsl/jobs/check_survey_scenario_compatibility.py +0 -85
- edsl/jobs/data_structures.py +0 -120
- edsl/jobs/decorators.py +0 -35
- edsl/jobs/jobs_status_enums.py +0 -9
- edsl/jobs/loggers/HTMLTableJobLogger.py +0 -304
- edsl/jobs/results_exceptions_handler.py +0 -98
- edsl/language_models/ComputeCost.py +0 -63
- edsl/language_models/PriceManager.py +0 -127
- edsl/language_models/RawResponseHandler.py +0 -106
- edsl/language_models/ServiceDataSources.py +0 -0
- edsl/language_models/key_management/KeyLookup.py +0 -63
- edsl/language_models/key_management/KeyLookupBuilder.py +0 -273
- edsl/language_models/key_management/KeyLookupCollection.py +0 -38
- edsl/language_models/key_management/__init__.py +0 -0
- edsl/language_models/key_management/models.py +0 -131
- edsl/language_models/model.py +0 -256
- edsl/notebooks/NotebookToLaTeX.py +0 -142
- edsl/questions/ExceptionExplainer.py +0 -77
- edsl/questions/HTMLQuestion.py +0 -103
- edsl/questions/QuestionMatrix.py +0 -265
- edsl/questions/data_structures.py +0 -20
- edsl/questions/loop_processor.py +0 -149
- edsl/questions/response_validator_factory.py +0 -34
- edsl/questions/templates/matrix/__init__.py +0 -1
- edsl/questions/templates/matrix/answering_instructions.jinja +0 -5
- edsl/questions/templates/matrix/question_presentation.jinja +0 -20
- edsl/results/MarkdownToDocx.py +0 -122
- edsl/results/MarkdownToPDF.py +0 -111
- edsl/results/TextEditor.py +0 -50
- edsl/results/file_exports.py +0 -252
- edsl/results/smart_objects.py +0 -96
- edsl/results/table_data_class.py +0 -12
- edsl/results/table_renderers.py +0 -118
- edsl/scenarios/ConstructDownloadLink.py +0 -109
- edsl/scenarios/DocumentChunker.py +0 -102
- edsl/scenarios/DocxScenario.py +0 -16
- edsl/scenarios/PdfExtractor.py +0 -40
- edsl/scenarios/directory_scanner.py +0 -96
- edsl/scenarios/file_methods.py +0 -85
- edsl/scenarios/handlers/__init__.py +0 -13
- edsl/scenarios/handlers/csv.py +0 -49
- edsl/scenarios/handlers/docx.py +0 -76
- edsl/scenarios/handlers/html.py +0 -37
- edsl/scenarios/handlers/json.py +0 -111
- edsl/scenarios/handlers/latex.py +0 -5
- edsl/scenarios/handlers/md.py +0 -51
- edsl/scenarios/handlers/pdf.py +0 -68
- edsl/scenarios/handlers/png.py +0 -39
- edsl/scenarios/handlers/pptx.py +0 -105
- edsl/scenarios/handlers/py.py +0 -294
- edsl/scenarios/handlers/sql.py +0 -313
- edsl/scenarios/handlers/sqlite.py +0 -149
- edsl/scenarios/handlers/txt.py +0 -33
- edsl/scenarios/scenario_selector.py +0 -156
- edsl/surveys/ConstructDAG.py +0 -92
- edsl/surveys/EditSurvey.py +0 -221
- edsl/surveys/InstructionHandler.py +0 -100
- edsl/surveys/MemoryManagement.py +0 -72
- edsl/surveys/RuleManager.py +0 -172
- edsl/surveys/Simulator.py +0 -75
- edsl/surveys/SurveyToApp.py +0 -141
- edsl/utilities/PrettyList.py +0 -56
- edsl/utilities/is_notebook.py +0 -18
- edsl/utilities/is_valid_variable_name.py +0 -11
- edsl/utilities/remove_edsl_version.py +0 -24
- edsl-0.1.39.dist-info/RECORD +0 -358
- /edsl/questions/{register_questions_meta.py → RegisterQuestionsMeta.py} +0 -0
- /edsl/results/{results_fetch_mixin.py → ResultsFetchMixin.py} +0 -0
- /edsl/results/{results_tools_mixin.py → ResultsToolsMixin.py} +0 -0
- {edsl-0.1.39.dist-info → edsl-0.1.39.dev1.dist-info}/LICENSE +0 -0
@@ -1,11 +1,12 @@
|
|
1
1
|
"""Mixin class for exporting results."""
|
2
2
|
|
3
|
+
import base64
|
4
|
+
import csv
|
3
5
|
import io
|
4
|
-
import
|
5
|
-
import
|
6
|
-
from typing import Optional, Tuple, Union, List
|
6
|
+
import html
|
7
|
+
from typing import Optional
|
7
8
|
|
8
|
-
from
|
9
|
+
from typing import Literal, Optional, Union, List
|
9
10
|
|
10
11
|
|
11
12
|
class DatasetExportMixin:
|
@@ -36,7 +37,7 @@ class DatasetExportMixin:
|
|
36
37
|
|
37
38
|
>>> from edsl.results import Results
|
38
39
|
>>> sorted(Results.example().select().relevant_columns(data_type = "model"))
|
39
|
-
['model.frequency_penalty',
|
40
|
+
['model.frequency_penalty', 'model.logprobs', 'model.max_tokens', 'model.model', 'model.presence_penalty', 'model.temperature', 'model.top_logprobs', 'model.top_p']
|
40
41
|
|
41
42
|
>>> Results.example().relevant_columns(data_type = "flimflam")
|
42
43
|
Traceback (most recent call last):
|
@@ -71,7 +72,7 @@ class DatasetExportMixin:
|
|
71
72
|
def num_observations(self):
|
72
73
|
"""Return the number of observations in the dataset.
|
73
74
|
|
74
|
-
>>> from edsl.results
|
75
|
+
>>> from edsl.results import Results
|
75
76
|
>>> Results.example().num_observations()
|
76
77
|
4
|
77
78
|
"""
|
@@ -143,148 +144,299 @@ class DatasetExportMixin:
|
|
143
144
|
for value in list_of_values:
|
144
145
|
print(f"{key}: {value}")
|
145
146
|
|
146
|
-
def
|
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
|
-
|
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
|
190
357
|
|
191
358
|
def to_csv(
|
192
359
|
self,
|
193
360
|
filename: Optional[str] = None,
|
194
361
|
remove_prefix: bool = False,
|
362
|
+
download_link: bool = False,
|
195
363
|
pretty_labels: Optional[dict] = None,
|
196
|
-
)
|
197
|
-
"""Export the results to a
|
198
|
-
exporter = CSVExport(
|
199
|
-
data=self,
|
200
|
-
filename=filename,
|
201
|
-
remove_prefix=remove_prefix,
|
202
|
-
pretty_labels=pretty_labels,
|
203
|
-
)
|
204
|
-
return exporter.export()
|
364
|
+
):
|
365
|
+
"""Export the results to a CSV file.
|
205
366
|
|
206
|
-
|
207
|
-
|
208
|
-
|
209
|
-
remove_prefix: bool = False,
|
210
|
-
pretty_labels: Optional[dict] = None,
|
211
|
-
sheet_name: Optional[str] = None,
|
212
|
-
) -> Optional["FileStore"]:
|
213
|
-
"""Export the results to a FileStore instance containing Excel data."""
|
214
|
-
exporter = ExcelExport(
|
215
|
-
data=self,
|
216
|
-
filename=filename,
|
217
|
-
remove_prefix=remove_prefix,
|
218
|
-
pretty_labels=pretty_labels,
|
219
|
-
sheet_name=sheet_name,
|
220
|
-
)
|
221
|
-
return exporter.export()
|
367
|
+
:param filename: The filename to save the CSV file to.
|
368
|
+
:param remove_prefix: Whether to remove the prefix from the column names.
|
369
|
+
:param download_link: Whether to display a download link in a Jupyter notebook.
|
222
370
|
|
223
|
-
|
224
|
-
"""Create a SQLite database in memory and return the connection.
|
371
|
+
Example:
|
225
372
|
|
226
|
-
|
227
|
-
|
228
|
-
|
373
|
+
>>> from edsl.results import Results
|
374
|
+
>>> r = Results.example()
|
375
|
+
>>> r.select('how_feeling').to_csv()
|
376
|
+
'answer.how_feeling\\r\\nOK\\r\\nGreat\\r\\nTerrible\\r\\nOK\\r\\n'
|
377
|
+
|
378
|
+
>>> r.select('how_feeling').to_csv(pretty_labels = {'answer.how_feeling': "How are you feeling"})
|
379
|
+
'How are you feeling\\r\\nOK\\r\\nGreat\\r\\nTerrible\\r\\nOK\\r\\n'
|
380
|
+
|
381
|
+
>>> import tempfile
|
382
|
+
>>> filename = tempfile.NamedTemporaryFile(delete=False).name
|
383
|
+
>>> r.select('how_feeling').to_csv(filename = filename)
|
384
|
+
>>> import os
|
385
|
+
>>> import csv
|
386
|
+
>>> with open(filename, newline='') as f:
|
387
|
+
... reader = csv.reader(f)
|
388
|
+
... for row in reader:
|
389
|
+
... print(row)
|
390
|
+
['answer.how_feeling']
|
391
|
+
['OK']
|
392
|
+
['Great']
|
393
|
+
['Terrible']
|
394
|
+
['OK']
|
229
395
|
|
230
|
-
Returns:
|
231
|
-
A database connection
|
232
396
|
"""
|
233
|
-
|
234
|
-
|
235
|
-
|
236
|
-
|
237
|
-
df = self.remove_prefix().to_pandas(lists_as_strings=True)
|
238
|
-
else:
|
239
|
-
df = self.to_pandas(lists_as_strings=True)
|
240
|
-
df.to_sql(
|
241
|
-
"self",
|
242
|
-
engine,
|
243
|
-
index=False,
|
244
|
-
if_exists="replace",
|
397
|
+
if pretty_labels is None:
|
398
|
+
pretty_labels = {}
|
399
|
+
header, rows = self._make_tabular(
|
400
|
+
remove_prefix=remove_prefix, pretty_labels=pretty_labels
|
245
401
|
)
|
246
|
-
return engine.connect()
|
247
402
|
|
248
|
-
|
249
|
-
|
250
|
-
|
251
|
-
|
252
|
-
|
253
|
-
|
254
|
-
|
255
|
-
|
256
|
-
|
257
|
-
|
258
|
-
|
259
|
-
|
260
|
-
|
261
|
-
|
262
|
-
|
263
|
-
|
264
|
-
|
265
|
-
|
266
|
-
|
267
|
-
|
268
|
-
|
269
|
-
DataFrame, CSV string, list, or LaTeX string depending on parameters
|
403
|
+
if filename is not None:
|
404
|
+
with open(filename, "w") as f:
|
405
|
+
writer = csv.writer(f)
|
406
|
+
writer.writerow(header)
|
407
|
+
writer.writerows(rows)
|
408
|
+
# print(f"Saved to {filename}")
|
409
|
+
else:
|
410
|
+
output = io.StringIO()
|
411
|
+
writer = csv.writer(output)
|
412
|
+
writer.writerow(header)
|
413
|
+
writer.writerows(rows)
|
414
|
+
|
415
|
+
if download_link:
|
416
|
+
from IPython.display import HTML, display
|
417
|
+
|
418
|
+
csv_file = output.getvalue()
|
419
|
+
b64 = base64.b64encode(csv_file.encode()).decode()
|
420
|
+
download_link = f'<a href="data:file/csv;base64,{b64}" download="my_data.csv">Download CSV file</a>'
|
421
|
+
display(HTML(download_link))
|
422
|
+
else:
|
423
|
+
return output.getvalue()
|
270
424
|
|
271
|
-
|
272
|
-
|
425
|
+
def download_link(self, pretty_labels: Optional[dict] = None) -> str:
|
426
|
+
"""Return a download link for the results.
|
273
427
|
|
274
|
-
|
275
|
-
df = pd.read_sql_query(query, conn)
|
428
|
+
:param pretty_labels: A dictionary of pretty labels for the columns.
|
276
429
|
|
277
|
-
|
278
|
-
|
279
|
-
|
280
|
-
|
281
|
-
|
282
|
-
|
283
|
-
df = df.set_index(df.columns[0])
|
284
|
-
df = df.transpose()
|
285
|
-
from edsl.results.Dataset import Dataset
|
430
|
+
>>> from edsl.results import Results
|
431
|
+
>>> r = Results.example()
|
432
|
+
>>> r.select('how_feeling').download_link()
|
433
|
+
'<a href="data:file/csv;base64,YW5zd2VyLmhvd19mZWVsaW5nDQpPSw0KR3JlYXQNClRlcnJpYmxlDQpPSw0K" download="my_data.csv">Download CSV file</a>'
|
434
|
+
"""
|
435
|
+
import base64
|
286
436
|
|
287
|
-
|
437
|
+
csv_string = self.to_csv(pretty_labels=pretty_labels)
|
438
|
+
b64 = base64.b64encode(csv_string.encode()).decode()
|
439
|
+
return f'<a href="data:file/csv;base64,{b64}" download="my_data.csv">Download CSV file</a>'
|
288
440
|
|
289
441
|
def to_pandas(
|
290
442
|
self, remove_prefix: bool = False, lists_as_strings=False
|
@@ -295,6 +447,19 @@ class DatasetExportMixin:
|
|
295
447
|
|
296
448
|
"""
|
297
449
|
return self._to_pandas_strings(remove_prefix)
|
450
|
+
# if lists_as_strings:
|
451
|
+
# return self._to_pandas_strings(remove_prefix=remove_prefix)
|
452
|
+
|
453
|
+
# import pandas as pd
|
454
|
+
|
455
|
+
# df = pd.DataFrame(self.data)
|
456
|
+
|
457
|
+
# if remove_prefix:
|
458
|
+
# # Optionally remove prefixes from column names
|
459
|
+
# df.columns = [col.split(".")[-1] for col in df.columns]
|
460
|
+
|
461
|
+
# df_sorted = df.sort_index(axis=1) # Sort columns alphabetically
|
462
|
+
# return df_sorted
|
298
463
|
|
299
464
|
def _to_pandas_strings(self, remove_prefix: bool = False) -> "pd.DataFrame":
|
300
465
|
"""Convert the results to a pandas DataFrame.
|
@@ -313,32 +478,12 @@ class DatasetExportMixin:
|
|
313
478
|
|
314
479
|
import pandas as pd
|
315
480
|
|
316
|
-
csv_string = self.to_csv(remove_prefix=remove_prefix)
|
481
|
+
csv_string = self.to_csv(remove_prefix=remove_prefix)
|
317
482
|
csv_buffer = io.StringIO(csv_string)
|
318
483
|
df = pd.read_csv(csv_buffer)
|
319
484
|
# df_sorted = df.sort_index(axis=1) # Sort columns alphabetically
|
320
485
|
return df
|
321
486
|
|
322
|
-
def to_polars(
|
323
|
-
self, remove_prefix: bool = False, lists_as_strings=False
|
324
|
-
) -> "pl.DataFrame":
|
325
|
-
"""Convert the results to a Polars DataFrame.
|
326
|
-
|
327
|
-
:param remove_prefix: Whether to remove the prefix from the column names.
|
328
|
-
"""
|
329
|
-
return self._to_polars_strings(remove_prefix)
|
330
|
-
|
331
|
-
def _to_polars_strings(self, remove_prefix: bool = False) -> "pl.DataFrame":
|
332
|
-
"""Convert the results to a Polars DataFrame.
|
333
|
-
|
334
|
-
:param remove_prefix: Whether to remove the prefix from the column names.
|
335
|
-
"""
|
336
|
-
import polars as pl
|
337
|
-
|
338
|
-
csv_string = self.to_csv(remove_prefix=remove_prefix).text
|
339
|
-
df = pl.read_csv(io.StringIO(csv_string))
|
340
|
-
return df
|
341
|
-
|
342
487
|
def to_scenario_list(self, remove_prefix: bool = True) -> list[dict]:
|
343
488
|
"""Convert the results to a list of dictionaries, one per scenario.
|
344
489
|
|
@@ -349,14 +494,14 @@ class DatasetExportMixin:
|
|
349
494
|
>>> r.select('how_feeling').to_scenario_list()
|
350
495
|
ScenarioList([Scenario({'how_feeling': 'OK'}), Scenario({'how_feeling': 'Great'}), Scenario({'how_feeling': 'Terrible'}), Scenario({'how_feeling': 'OK'})])
|
351
496
|
"""
|
352
|
-
from edsl
|
353
|
-
from edsl.scenarios.Scenario import Scenario
|
497
|
+
from edsl import ScenarioList, Scenario
|
354
498
|
|
355
499
|
list_of_dicts = self.to_dicts(remove_prefix=remove_prefix)
|
356
500
|
scenarios = []
|
357
501
|
for d in list_of_dicts:
|
358
502
|
scenarios.append(Scenario(d))
|
359
503
|
return ScenarioList(scenarios)
|
504
|
+
# return ScenarioList([Scenario(d) for d in list_of_dicts])
|
360
505
|
|
361
506
|
def to_agent_list(self, remove_prefix: bool = True):
|
362
507
|
"""Convert the results to a list of dictionaries, one per agent.
|
@@ -368,8 +513,7 @@ class DatasetExportMixin:
|
|
368
513
|
>>> r.select('how_feeling').to_agent_list()
|
369
514
|
AgentList([Agent(traits = {'how_feeling': 'OK'}), Agent(traits = {'how_feeling': 'Great'}), Agent(traits = {'how_feeling': 'Terrible'}), Agent(traits = {'how_feeling': 'OK'})])
|
370
515
|
"""
|
371
|
-
from edsl
|
372
|
-
from edsl.agents.AgentList import AgentList
|
516
|
+
from edsl import AgentList, Agent
|
373
517
|
|
374
518
|
list_of_dicts = self.to_dicts(remove_prefix=remove_prefix)
|
375
519
|
agents = []
|
@@ -377,11 +521,6 @@ class DatasetExportMixin:
|
|
377
521
|
if "name" in d:
|
378
522
|
d["agent_name"] = d.pop("name")
|
379
523
|
agents.append(Agent(d, name=d["agent_name"]))
|
380
|
-
if "agent_parameters" in d:
|
381
|
-
agent_parameters = d.pop("agent_parameters")
|
382
|
-
agent_name = agent_parameters.get("name", None)
|
383
|
-
instruction = agent_parameters.get("instruction", None)
|
384
|
-
agents.append(Agent(d, name=agent_name, instruction=instruction))
|
385
524
|
else:
|
386
525
|
agents.append(Agent(d))
|
387
526
|
return AgentList(agents)
|
@@ -469,9 +608,7 @@ class DatasetExportMixin:
|
|
469
608
|
new_list.append(item)
|
470
609
|
list_to_return = new_list
|
471
610
|
|
472
|
-
|
473
|
-
|
474
|
-
return PrettyList(list_to_return)
|
611
|
+
return list_to_return
|
475
612
|
|
476
613
|
def html(
|
477
614
|
self,
|
@@ -521,10 +658,8 @@ class DatasetExportMixin:
|
|
521
658
|
>>> r = Results.example()
|
522
659
|
>>> r.select('how_feeling').tally('answer.how_feeling', output = "dict")
|
523
660
|
{'OK': 2, 'Great': 1, 'Terrible': 1}
|
524
|
-
>>>
|
525
|
-
|
526
|
-
>>> r.select('how_feeling').tally('answer.how_feeling', output = "Dataset") == expected
|
527
|
-
True
|
661
|
+
>>> r.select('how_feeling').tally('answer.how_feeling', output = "Dataset")
|
662
|
+
Dataset([{'answer.how_feeling': ['OK', 'Great', 'Terrible']}, {'count': [2, 1, 1]}])
|
528
663
|
"""
|
529
664
|
from collections import Counter
|
530
665
|
|
@@ -556,6 +691,8 @@ class DatasetExportMixin:
|
|
556
691
|
if top_n is not None:
|
557
692
|
sorted_tally = dict(list(sorted_tally.items())[:top_n])
|
558
693
|
|
694
|
+
import warnings
|
695
|
+
import textwrap
|
559
696
|
from edsl.results.Dataset import Dataset
|
560
697
|
|
561
698
|
if output == "dict":
|
edsl/results/DatasetTree.py
CHANGED
@@ -1,4 +1,8 @@
|
|
1
1
|
from typing import Dict, List, Any, Optional, List
|
2
|
+
from docx import Document
|
3
|
+
from docx.shared import Inches, Pt
|
4
|
+
from docx.enum.text import WD_ALIGN_PARAGRAPH
|
5
|
+
from docx.enum.style import WD_STYLE_TYPE
|
2
6
|
|
3
7
|
|
4
8
|
def is_hashable(v):
|
@@ -94,11 +98,6 @@ class Tree:
|
|
94
98
|
if filename is None:
|
95
99
|
filename = "tree_structure.docx"
|
96
100
|
|
97
|
-
from docx import Document
|
98
|
-
from docx.shared import Inches, Pt
|
99
|
-
from docx.enum.text import WD_ALIGN_PARAGRAPH
|
100
|
-
from docx.enum.style import WD_STYLE_TYPE
|
101
|
-
|
102
101
|
doc = Document()
|
103
102
|
|
104
103
|
# Create styles for headings
|
@@ -116,29 +115,10 @@ class Tree:
|
|
116
115
|
body_style.font.size = Pt(11)
|
117
116
|
|
118
117
|
self._add_to_docx(doc, self.root, 0)
|
119
|
-
|
120
|
-
from
|
121
|
-
|
122
|
-
|
123
|
-
# Save document to bytes buffer
|
124
|
-
doc_buffer = BytesIO()
|
125
|
-
doc.save(doc_buffer)
|
126
|
-
doc_buffer.seek(0)
|
127
|
-
|
128
|
-
base64_string = base64.b64encode(doc_buffer.getvalue()).decode("utf-8")
|
129
|
-
from edsl.scenarios.FileStore import FileStore
|
130
|
-
|
131
|
-
# Create and return FileStore instance
|
132
|
-
return FileStore(
|
133
|
-
path="tree_structure.docx", # Default name
|
134
|
-
mime_type="application/vnd.openxmlformats-officedocument.wordprocessingml.document",
|
135
|
-
binary=True,
|
136
|
-
suffix="docx",
|
137
|
-
base64_string=base64_string,
|
138
|
-
)
|
139
|
-
# doc.save(filename)
|
140
|
-
# from edsl.utilities.utilities import file_notice
|
141
|
-
# file_notice(filename)
|
118
|
+
doc.save(filename)
|
119
|
+
from edsl.utilities.utilities import file_notice
|
120
|
+
|
121
|
+
file_notice(filename)
|
142
122
|
|
143
123
|
def _repr_html_(self):
|
144
124
|
"""Returns an interactive HTML representation of the tree with collapsible sections."""
|