edsl 0.1.29__py3-none-any.whl → 0.1.29.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 +18 -18
- edsl/__init__.py +23 -23
- edsl/__version__.py +1 -1
- edsl/agents/Agent.py +41 -77
- edsl/agents/AgentList.py +9 -19
- edsl/agents/Invigilator.py +1 -19
- edsl/agents/InvigilatorBase.py +10 -15
- edsl/agents/PromptConstructionMixin.py +100 -342
- edsl/agents/descriptors.py +1 -2
- edsl/config.py +1 -2
- edsl/conjure/InputData.py +8 -39
- edsl/coop/coop.py +150 -187
- edsl/coop/utils.py +75 -43
- edsl/data/Cache.py +5 -19
- edsl/data/SQLiteDict.py +3 -11
- edsl/jobs/Answers.py +1 -15
- edsl/jobs/Jobs.py +46 -90
- edsl/jobs/buckets/ModelBuckets.py +2 -4
- edsl/jobs/buckets/TokenBucket.py +2 -1
- edsl/jobs/interviews/Interview.py +9 -3
- edsl/jobs/interviews/InterviewStatusMixin.py +3 -3
- edsl/jobs/interviews/InterviewTaskBuildingMixin.py +10 -15
- edsl/jobs/runners/JobsRunnerAsyncio.py +25 -21
- edsl/jobs/tasks/TaskHistory.py +3 -4
- edsl/language_models/LanguageModel.py +11 -5
- edsl/language_models/ModelList.py +1 -1
- edsl/language_models/repair.py +7 -8
- edsl/notebooks/Notebook.py +3 -40
- edsl/prompts/Prompt.py +19 -31
- edsl/questions/QuestionBase.py +13 -38
- edsl/questions/QuestionBudget.py +6 -5
- edsl/questions/QuestionCheckBox.py +3 -7
- edsl/questions/QuestionExtract.py +3 -5
- edsl/questions/QuestionFreeText.py +3 -3
- edsl/questions/QuestionFunctional.py +3 -0
- edsl/questions/QuestionList.py +4 -3
- edsl/questions/QuestionMultipleChoice.py +8 -16
- edsl/questions/QuestionNumerical.py +3 -4
- edsl/questions/QuestionRank.py +3 -5
- edsl/questions/__init__.py +3 -4
- edsl/questions/descriptors.py +2 -4
- edsl/questions/question_registry.py +31 -20
- edsl/questions/settings.py +1 -1
- edsl/results/Dataset.py +0 -31
- edsl/results/Result.py +74 -22
- edsl/results/Results.py +47 -97
- edsl/results/ResultsDBMixin.py +3 -7
- edsl/results/ResultsExportMixin.py +537 -22
- edsl/results/ResultsGGMixin.py +3 -3
- edsl/results/ResultsToolsMixin.py +5 -5
- edsl/scenarios/Scenario.py +6 -5
- edsl/scenarios/ScenarioList.py +11 -34
- edsl/scenarios/ScenarioListPdfMixin.py +1 -2
- edsl/scenarios/__init__.py +0 -1
- edsl/study/Study.py +9 -3
- edsl/surveys/MemoryPlan.py +4 -11
- edsl/surveys/Survey.py +7 -46
- edsl/surveys/SurveyExportMixin.py +2 -4
- edsl/surveys/SurveyFlowVisualizationMixin.py +4 -6
- edsl/tools/plotting.py +2 -4
- edsl/utilities/__init__.py +21 -21
- edsl/utilities/interface.py +45 -66
- edsl/utilities/utilities.py +13 -11
- {edsl-0.1.29.dist-info → edsl-0.1.29.dev2.dist-info}/METADATA +10 -11
- {edsl-0.1.29.dist-info → edsl-0.1.29.dev2.dist-info}/RECORD +68 -71
- edsl-0.1.29.dev2.dist-info/entry_points.txt +3 -0
- edsl/base/Base.py +0 -289
- edsl/results/DatasetExportMixin.py +0 -493
- edsl/scenarios/FileStore.py +0 -140
- edsl/scenarios/ScenarioListExportMixin.py +0 -32
- {edsl-0.1.29.dist-info → edsl-0.1.29.dev2.dist-info}/LICENSE +0 -0
- {edsl-0.1.29.dist-info → edsl-0.1.29.dev2.dist-info}/WHEEL +0 -0
edsl/results/Results.py
CHANGED
@@ -5,10 +5,16 @@ It is not typically instantiated directly, but is returned by the run method of
|
|
5
5
|
|
6
6
|
from __future__ import annotations
|
7
7
|
import json
|
8
|
+
import hashlib
|
8
9
|
import random
|
9
10
|
from collections import UserList, defaultdict
|
10
11
|
from typing import Optional, Callable, Any, Type, Union, List
|
11
12
|
|
13
|
+
from pygments import highlight
|
14
|
+
from pygments.lexers import JsonLexer
|
15
|
+
from pygments.formatters import HtmlFormatter
|
16
|
+
from IPython.display import HTML
|
17
|
+
|
12
18
|
from simpleeval import EvalWithCompoundTypes
|
13
19
|
|
14
20
|
from edsl.exceptions.results import (
|
@@ -18,17 +24,29 @@ from edsl.exceptions.results import (
|
|
18
24
|
ResultsMutateError,
|
19
25
|
ResultsFilterError,
|
20
26
|
)
|
21
|
-
|
27
|
+
from edsl.agents import Agent, AgentList
|
28
|
+
from edsl.language_models.LanguageModel import LanguageModel
|
29
|
+
from edsl.results.Dataset import Dataset
|
30
|
+
from edsl.results.Result import Result
|
22
31
|
from edsl.results.ResultsExportMixin import ResultsExportMixin
|
32
|
+
from edsl.scenarios import Scenario
|
33
|
+
|
34
|
+
# from edsl.scenarios.ScenarioList import ScenarioList
|
35
|
+
from edsl.surveys import Survey
|
36
|
+
from edsl.data.Cache import Cache
|
37
|
+
from edsl.utilities import (
|
38
|
+
is_valid_variable_name,
|
39
|
+
shorten_string,
|
40
|
+
)
|
41
|
+
from edsl.utilities.decorators import add_edsl_version, remove_edsl_version
|
42
|
+
from edsl.utilities.utilities import dict_hash
|
23
43
|
from edsl.results.ResultsToolsMixin import ResultsToolsMixin
|
44
|
+
|
24
45
|
from edsl.results.ResultsDBMixin import ResultsDBMixin
|
25
46
|
from edsl.results.ResultsGGMixin import ResultsGGMixin
|
26
|
-
from edsl.results.ResultsFetchMixin import ResultsFetchMixin
|
27
|
-
|
28
|
-
from edsl.utilities.decorators import add_edsl_version, remove_edsl_version
|
29
|
-
from edsl.utilities.utilities import dict_hash
|
30
47
|
|
31
48
|
from edsl.Base import Base
|
49
|
+
from edsl.results.ResultsFetchMixin import ResultsFetchMixin
|
32
50
|
|
33
51
|
|
34
52
|
class Mixins(
|
@@ -38,22 +56,7 @@ class Mixins(
|
|
38
56
|
ResultsGGMixin,
|
39
57
|
ResultsToolsMixin,
|
40
58
|
):
|
41
|
-
|
42
|
-
"""Print the results in long format.
|
43
|
-
|
44
|
-
>>> from edsl.results import Results
|
45
|
-
>>> r = Results.example()
|
46
|
-
>>> r.select('how_feeling').print_long(max_rows = 2)
|
47
|
-
┏━━━━━━━━━━━━━━┳━━━━━━━━━━━━━┳━━━━━━━┓
|
48
|
-
┃ Result index ┃ Key ┃ Value ┃
|
49
|
-
┡━━━━━━━━━━━━━━╇━━━━━━━━━━━━━╇━━━━━━━┩
|
50
|
-
│ 0 │ how_feeling │ OK │
|
51
|
-
│ 1 │ how_feeling │ Great │
|
52
|
-
└──────────────┴─────────────┴───────┘
|
53
|
-
"""
|
54
|
-
from edsl.utilities.interface import print_results_long
|
55
|
-
|
56
|
-
print_results_long(self, max_rows=max_rows)
|
59
|
+
pass
|
57
60
|
|
58
61
|
|
59
62
|
class Results(UserList, Mixins, Base):
|
@@ -81,10 +84,10 @@ class Results(UserList, Mixins, Base):
|
|
81
84
|
|
82
85
|
def __init__(
|
83
86
|
self,
|
84
|
-
survey: Optional[
|
85
|
-
data: Optional[list[
|
87
|
+
survey: Optional[Survey] = None,
|
88
|
+
data: Optional[list[Result]] = None,
|
86
89
|
created_columns: Optional[list[str]] = None,
|
87
|
-
cache: Optional[
|
90
|
+
cache: Optional[Cache] = None,
|
88
91
|
job_uuid: Optional[str] = None,
|
89
92
|
total_results: Optional[int] = None,
|
90
93
|
):
|
@@ -97,8 +100,6 @@ class Results(UserList, Mixins, Base):
|
|
97
100
|
:param total_results: An integer representing the total number of results.
|
98
101
|
"""
|
99
102
|
super().__init__(data)
|
100
|
-
from edsl.data.Cache import Cache
|
101
|
-
|
102
103
|
self.survey = survey
|
103
104
|
self.created_columns = created_columns or []
|
104
105
|
self._job_uuid = job_uuid
|
@@ -124,10 +125,6 @@ class Results(UserList, Mixins, Base):
|
|
124
125
|
raise TypeError("Invalid argument type")
|
125
126
|
|
126
127
|
def _update_results(self) -> None:
|
127
|
-
from edsl import Agent, Scenario
|
128
|
-
from edsl.language_models import LanguageModel
|
129
|
-
from edsl.results import Result
|
130
|
-
|
131
128
|
if self._job_uuid and len(self.data) < self._total_results:
|
132
129
|
results = [
|
133
130
|
Result(
|
@@ -168,16 +165,16 @@ class Results(UserList, Mixins, Base):
|
|
168
165
|
)
|
169
166
|
|
170
167
|
def __repr__(self) -> str:
|
171
|
-
return f"Results(data = {self.data}, survey = {repr(self.survey)}, created_columns = {self.created_columns})"
|
168
|
+
# return f"Results(data = {self.data}, survey = {repr(self.survey)}, created_columns = {self.created_columns})"
|
169
|
+
return f"""Results object
|
170
|
+
Size: {len(self.data)}.
|
171
|
+
Survey questions: {[q.question_name for q in self.survey.questions]}.
|
172
|
+
Created columns: {self.created_columns}
|
173
|
+
Hash: {hash(self)}
|
174
|
+
"""
|
172
175
|
|
173
176
|
def _repr_html_(self) -> str:
|
174
|
-
from IPython.display import HTML
|
175
|
-
|
176
177
|
json_str = json.dumps(self.to_dict()["data"], indent=4)
|
177
|
-
from pygments import highlight
|
178
|
-
from pygments.lexers import JsonLexer
|
179
|
-
from pygments.formatters import HtmlFormatter
|
180
|
-
|
181
178
|
formatted_json = highlight(
|
182
179
|
json_str,
|
183
180
|
JsonLexer(),
|
@@ -186,8 +183,6 @@ class Results(UserList, Mixins, Base):
|
|
186
183
|
return HTML(formatted_json).data
|
187
184
|
|
188
185
|
def _to_dict(self, sort=False):
|
189
|
-
from edsl.data.Cache import Cache
|
190
|
-
|
191
186
|
if sort:
|
192
187
|
data = sorted([result for result in self.data], key=lambda x: hash(x))
|
193
188
|
else:
|
@@ -237,31 +232,6 @@ class Results(UserList, Mixins, Base):
|
|
237
232
|
def hashes(self) -> set:
|
238
233
|
return set(hash(result) for result in self.data)
|
239
234
|
|
240
|
-
def sample(self, n: int) -> "Results":
|
241
|
-
"""Return a random sample of the results.
|
242
|
-
|
243
|
-
:param n: The number of samples to return.
|
244
|
-
|
245
|
-
>>> from edsl.results import Results
|
246
|
-
>>> r = Results.example()
|
247
|
-
>>> len(r.sample(2))
|
248
|
-
2
|
249
|
-
"""
|
250
|
-
indices = None
|
251
|
-
|
252
|
-
for entry in self:
|
253
|
-
key, values = list(entry.items())[0]
|
254
|
-
if indices is None: # gets the indices for the first time
|
255
|
-
indices = list(range(len(values)))
|
256
|
-
sampled_indices = random.sample(indices, n)
|
257
|
-
if n > len(indices):
|
258
|
-
raise ValueError(
|
259
|
-
f"Cannot sample {n} items from a list of length {len(indices)}."
|
260
|
-
)
|
261
|
-
entry[key] = [values[i] for i in sampled_indices]
|
262
|
-
|
263
|
-
return self
|
264
|
-
|
265
235
|
@classmethod
|
266
236
|
@remove_edsl_version
|
267
237
|
def from_dict(cls, data: dict[str, Any]) -> Results:
|
@@ -277,20 +247,12 @@ class Results(UserList, Mixins, Base):
|
|
277
247
|
>>> r == r2
|
278
248
|
True
|
279
249
|
"""
|
280
|
-
|
281
|
-
|
282
|
-
|
283
|
-
|
284
|
-
|
285
|
-
|
286
|
-
data=[Result.from_dict(r) for r in data["data"]],
|
287
|
-
created_columns=data.get("created_columns", None),
|
288
|
-
cache=(
|
289
|
-
Cache.from_dict(data.get("cache")) if "cache" in data else Cache()
|
290
|
-
),
|
291
|
-
)
|
292
|
-
except Exception as e:
|
293
|
-
breakpoint()
|
250
|
+
results = cls(
|
251
|
+
survey=Survey.from_dict(data["survey"]),
|
252
|
+
data=[Result.from_dict(r) for r in data["data"]],
|
253
|
+
created_columns=data.get("created_columns", None),
|
254
|
+
cache=Cache.from_dict(data.get("cache")) if "cache" in data else Cache(),
|
255
|
+
)
|
294
256
|
return results
|
295
257
|
|
296
258
|
######################
|
@@ -357,8 +319,6 @@ class Results(UserList, Mixins, Base):
|
|
357
319
|
>>> r.answer_keys
|
358
320
|
{'how_feeling': 'How are you this {{ period }}?', 'how_feeling_yesterday': 'How were you feeling yesterday {{ period }}?'}
|
359
321
|
"""
|
360
|
-
from edsl.utilities.utilities import shorten_string
|
361
|
-
|
362
322
|
if not self.survey:
|
363
323
|
raise Exception("Survey is not defined so no answer keys are available.")
|
364
324
|
|
@@ -373,7 +333,7 @@ class Results(UserList, Mixins, Base):
|
|
373
333
|
return sorted_dict
|
374
334
|
|
375
335
|
@property
|
376
|
-
def agents(self) ->
|
336
|
+
def agents(self) -> AgentList:
|
377
337
|
"""Return a list of all of the agents in the Results.
|
378
338
|
|
379
339
|
Example:
|
@@ -382,12 +342,10 @@ class Results(UserList, Mixins, Base):
|
|
382
342
|
>>> r.agents
|
383
343
|
AgentList([Agent(traits = {'status': 'Joyful'}), Agent(traits = {'status': 'Joyful'}), Agent(traits = {'status': 'Sad'}), Agent(traits = {'status': 'Sad'})])
|
384
344
|
"""
|
385
|
-
from edsl import AgentList
|
386
|
-
|
387
345
|
return AgentList([r.agent for r in self.data])
|
388
346
|
|
389
347
|
@property
|
390
|
-
def models(self) -> list[Type[
|
348
|
+
def models(self) -> list[Type[LanguageModel]]:
|
391
349
|
"""Return a list of all of the models in the Results.
|
392
350
|
|
393
351
|
Example:
|
@@ -509,7 +467,7 @@ class Results(UserList, Mixins, Base):
|
|
509
467
|
)
|
510
468
|
return data_type, key
|
511
469
|
|
512
|
-
def first(self) ->
|
470
|
+
def first(self) -> Result:
|
513
471
|
"""Return the first observation in the results.
|
514
472
|
|
515
473
|
Example:
|
@@ -627,8 +585,6 @@ class Results(UserList, Mixins, Base):
|
|
627
585
|
)
|
628
586
|
raw_var_name, expression = new_var_string.split("=", 1)
|
629
587
|
var_name = raw_var_name.strip()
|
630
|
-
from edsl.utilities.utilities import is_valid_variable_name
|
631
|
-
|
632
588
|
if not is_valid_variable_name(var_name):
|
633
589
|
raise ResultsInvalidNameError(f"{var_name} is not a valid variable name.")
|
634
590
|
|
@@ -640,7 +596,7 @@ class Results(UserList, Mixins, Base):
|
|
640
596
|
names=result.combined_dict, functions=functions_dict
|
641
597
|
)
|
642
598
|
|
643
|
-
def new_result(old_result:
|
599
|
+
def new_result(old_result: Result, var_name: str) -> Result:
|
644
600
|
evaluator = create_evaluator(old_result)
|
645
601
|
value = evaluator.eval(expression)
|
646
602
|
new_result = old_result.copy()
|
@@ -730,7 +686,7 @@ class Results(UserList, Mixins, Base):
|
|
730
686
|
|
731
687
|
return Results(survey=self.survey, data=new_data, created_columns=None)
|
732
688
|
|
733
|
-
def select(self, *columns: Union[str, list[str]]) ->
|
689
|
+
def select(self, *columns: Union[str, list[str]]) -> Dataset:
|
734
690
|
"""
|
735
691
|
Select data from the results and format it.
|
736
692
|
|
@@ -742,7 +698,6 @@ class Results(UserList, Mixins, Base):
|
|
742
698
|
>>> results.select('how_feeling')
|
743
699
|
Dataset([{'answer.how_feeling': ['OK', 'Great', 'Terrible', 'OK']}])
|
744
700
|
"""
|
745
|
-
|
746
701
|
if len(self) == 0:
|
747
702
|
raise Exception("No data to select from---the Results object is empty.")
|
748
703
|
|
@@ -799,16 +754,12 @@ class Results(UserList, Mixins, Base):
|
|
799
754
|
return items_in_order.index(single_key)
|
800
755
|
|
801
756
|
sorted(new_data, key=sort_by_key_order)
|
802
|
-
from edsl.results.Dataset import Dataset
|
803
757
|
|
804
758
|
return Dataset(new_data)
|
805
759
|
|
806
760
|
def sort_by(self, *columns: str, reverse: bool = False) -> Results:
|
807
761
|
import warnings
|
808
|
-
|
809
|
-
warnings.warn(
|
810
|
-
"sort_by is deprecated. Use order_by instead.", DeprecationWarning
|
811
|
-
)
|
762
|
+
warnings.warn("sort_by is deprecated. Use order_by instead.", DeprecationWarning)
|
812
763
|
return self.order_by(*columns, reverse=reverse)
|
813
764
|
|
814
765
|
def order_by(self, *columns: str, reverse: bool = False) -> Results:
|
@@ -849,7 +800,6 @@ class Results(UserList, Mixins, Base):
|
|
849
800
|
│ Great │
|
850
801
|
└──────────────┘
|
851
802
|
"""
|
852
|
-
|
853
803
|
def to_numeric_if_possible(v):
|
854
804
|
try:
|
855
805
|
return float(v)
|
@@ -958,7 +908,7 @@ class Results(UserList, Mixins, Base):
|
|
958
908
|
|
959
909
|
:param debug: if False, uses actual API calls
|
960
910
|
"""
|
961
|
-
from edsl.jobs
|
911
|
+
from edsl.jobs import Jobs
|
962
912
|
from edsl.data.Cache import Cache
|
963
913
|
|
964
914
|
c = Cache()
|
edsl/results/ResultsDBMixin.py
CHANGED
@@ -1,6 +1,8 @@
|
|
1
1
|
"""Mixin for working with SQLite respresentation of a 'Results' object."""
|
2
2
|
|
3
|
+
import pandas as pd
|
3
4
|
import sqlite3
|
5
|
+
from sqlalchemy import create_engine
|
4
6
|
from enum import Enum
|
5
7
|
from typing import Literal, Union, Optional
|
6
8
|
|
@@ -90,8 +92,6 @@ class ResultsDBMixin:
|
|
90
92
|
conn.commit()
|
91
93
|
return conn
|
92
94
|
elif shape == SQLDataShape.WIDE:
|
93
|
-
from sqlalchemy import create_engine
|
94
|
-
|
95
95
|
engine = create_engine("sqlite:///:memory:")
|
96
96
|
df = self.to_pandas(remove_prefix=remove_prefix)
|
97
97
|
df.to_sql("self", engine, index=False, if_exists="replace")
|
@@ -121,7 +121,7 @@ class ResultsDBMixin:
|
|
121
121
|
to_list=False,
|
122
122
|
to_latex=False,
|
123
123
|
filename: Optional[str] = None,
|
124
|
-
) -> Union[
|
124
|
+
) -> Union[pd.DataFrame, str]:
|
125
125
|
"""Execute a SQL query and return the results as a DataFrame.
|
126
126
|
|
127
127
|
:param query: The SQL query to execute
|
@@ -151,8 +151,6 @@ class ResultsDBMixin:
|
|
151
151
|
2 Terrible
|
152
152
|
3 OK
|
153
153
|
"""
|
154
|
-
import pandas as pd
|
155
|
-
|
156
154
|
shape_enum = self._get_shape_enum(shape)
|
157
155
|
|
158
156
|
conn = self._db(shape=shape_enum, remove_prefix=remove_prefix)
|
@@ -207,8 +205,6 @@ class ResultsDBMixin:
|
|
207
205
|
...
|
208
206
|
<BLANKLINE>
|
209
207
|
"""
|
210
|
-
import pandas as pd
|
211
|
-
|
212
208
|
shape_enum = self._get_shape_enum(shape)
|
213
209
|
conn = self._db(shape=shape_enum, remove_prefix=remove_prefix)
|
214
210
|
|