edsl 0.1.30__py3-none-any.whl → 0.1.30.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/__version__.py +1 -1
- edsl/agents/Agent.py +6 -8
- edsl/agents/AgentList.py +19 -9
- edsl/agents/Invigilator.py +5 -4
- edsl/conversation/car_buying.py +1 -1
- edsl/data/Cache.py +16 -25
- edsl/data/CacheEntry.py +7 -6
- edsl/data_transfer_models.py +0 -4
- edsl/jobs/Jobs.py +2 -17
- edsl/jobs/buckets/ModelBuckets.py +0 -10
- edsl/jobs/buckets/TokenBucket.py +3 -31
- edsl/jobs/interviews/Interview.py +73 -99
- edsl/jobs/interviews/InterviewTaskBuildingMixin.py +19 -9
- edsl/jobs/runners/JobsRunnerAsyncio.py +0 -4
- edsl/jobs/tasks/QuestionTaskCreator.py +6 -10
- edsl/language_models/LanguageModel.py +6 -12
- edsl/notebooks/Notebook.py +9 -9
- edsl/questions/QuestionFreeText.py +2 -4
- edsl/questions/QuestionFunctional.py +2 -34
- edsl/questions/QuestionMultipleChoice.py +8 -57
- edsl/questions/descriptors.py +2 -42
- edsl/results/DatasetExportMixin.py +5 -84
- edsl/results/Result.py +5 -53
- edsl/results/Results.py +30 -70
- edsl/scenarios/FileStore.py +4 -163
- edsl/scenarios/Scenario.py +19 -12
- edsl/scenarios/ScenarioList.py +6 -8
- edsl/study/Study.py +7 -5
- edsl/surveys/Survey.py +12 -44
- {edsl-0.1.30.dist-info → edsl-0.1.30.dev1.dist-info}/METADATA +1 -1
- {edsl-0.1.30.dist-info → edsl-0.1.30.dev1.dist-info}/RECORD +33 -33
- {edsl-0.1.30.dist-info → edsl-0.1.30.dev1.dist-info}/WHEEL +1 -1
- {edsl-0.1.30.dist-info → edsl-0.1.30.dev1.dist-info}/LICENSE +0 -0
edsl/results/Result.py
CHANGED
@@ -126,9 +126,6 @@ class Result(Base, UserDict):
|
|
126
126
|
self.survey = survey
|
127
127
|
self.question_to_attributes = question_to_attributes
|
128
128
|
|
129
|
-
self._combined_dict = None
|
130
|
-
self._problem_keys = None
|
131
|
-
|
132
129
|
###############
|
133
130
|
# Used in Results
|
134
131
|
###############
|
@@ -167,64 +164,25 @@ class Result(Base, UserDict):
|
|
167
164
|
"answer": self.answer,
|
168
165
|
"prompt": self.prompt,
|
169
166
|
"raw_model_response": self.raw_model_response,
|
170
|
-
|
167
|
+
"iteration": {"iteration": self.iteration},
|
171
168
|
"question_text": question_text_dict,
|
172
169
|
"question_options": question_options_dict,
|
173
170
|
"question_type": question_type_dict,
|
174
171
|
"comment": comments_dict,
|
175
172
|
}
|
176
173
|
|
177
|
-
def check_expression(self, expression) -> None:
|
178
|
-
for key in self.problem_keys:
|
179
|
-
if key in expression and not key + "." in expression:
|
180
|
-
raise ValueError(
|
181
|
-
f"Key by iself {key} is problematic. Use the full key {key + '.' + key} name instead."
|
182
|
-
)
|
183
|
-
return None
|
184
|
-
|
185
174
|
def code(self):
|
186
175
|
"""Return a string of code that can be used to recreate the Result object."""
|
187
176
|
raise NotImplementedError
|
188
177
|
|
189
178
|
@property
|
190
|
-
def
|
191
|
-
"""Return a
|
192
|
-
return self._problem_keys
|
193
|
-
|
194
|
-
def _compute_combined_dict_and_problem_keys(self) -> None:
|
179
|
+
def combined_dict(self) -> dict[str, Any]:
|
180
|
+
"""Return a dictionary that includes all sub_dicts, but also puts the key-value pairs in each sub_dict as a key_value pair in the combined dictionary."""
|
195
181
|
combined = {}
|
196
|
-
problem_keys = []
|
197
182
|
for key, sub_dict in self.sub_dicts.items():
|
198
183
|
combined.update(sub_dict)
|
199
|
-
# in some cases, the sub_dict might have keys that conflict with the main dict
|
200
|
-
if key in combined:
|
201
|
-
# The key is already in the combined dict
|
202
|
-
problem_keys = problem_keys + [key]
|
203
|
-
|
204
184
|
combined.update({key: sub_dict})
|
205
|
-
|
206
|
-
# dot notation to access the subdicts.
|
207
|
-
self._combined_dict = combined
|
208
|
-
self._problem_keys = problem_keys
|
209
|
-
|
210
|
-
@property
|
211
|
-
def combined_dict(self) -> dict[str, Any]:
|
212
|
-
"""Return a dictionary that includes all sub_dicts, but also puts the key-value pairs in each sub_dict as a key_value pair in the combined dictionary.
|
213
|
-
|
214
|
-
>>> r = Result.example()
|
215
|
-
>>> r.combined_dict['how_feeling']
|
216
|
-
'OK'
|
217
|
-
"""
|
218
|
-
if self._combined_dict is None or self._problem_keys is None:
|
219
|
-
self._compute_combined_dict_and_problem_keys()
|
220
|
-
return self._combined_dict
|
221
|
-
|
222
|
-
@property
|
223
|
-
def problem_keys(self):
|
224
|
-
"""Return a list of keys that are problematic."""
|
225
|
-
if self._combined_dict is None or self._problem_keys is None:
|
226
|
-
self._compute_combined_dict_and_problem_keys()
|
227
|
-
return self._problem_keys
|
185
|
+
return combined
|
228
186
|
|
229
187
|
def get_value(self, data_type: str, key: str) -> Any:
|
230
188
|
"""Return the value for a given data type and key.
|
@@ -268,13 +226,7 @@ class Result(Base, UserDict):
|
|
268
226
|
return Result.from_dict(self.to_dict())
|
269
227
|
|
270
228
|
def __eq__(self, other) -> bool:
|
271
|
-
"""Return True if the Result object is equal to another Result object.
|
272
|
-
|
273
|
-
>>> r = Result.example()
|
274
|
-
>>> r == r
|
275
|
-
True
|
276
|
-
|
277
|
-
"""
|
229
|
+
"""Return True if the Result object is equal to another Result object."""
|
278
230
|
return self.to_dict() == other.to_dict()
|
279
231
|
|
280
232
|
###############
|
edsl/results/Results.py
CHANGED
@@ -290,8 +290,7 @@ class Results(UserList, Mixins, Base):
|
|
290
290
|
),
|
291
291
|
)
|
292
292
|
except Exception as e:
|
293
|
-
|
294
|
-
# breakpoint()
|
293
|
+
breakpoint()
|
295
294
|
return results
|
296
295
|
|
297
296
|
######################
|
@@ -604,38 +603,6 @@ class Results(UserList, Mixins, Base):
|
|
604
603
|
self = self.add_column(key, values)
|
605
604
|
return self
|
606
605
|
|
607
|
-
@staticmethod
|
608
|
-
def _create_evaluator(
|
609
|
-
result: Result, functions_dict: Optional[dict] = None
|
610
|
-
) -> EvalWithCompoundTypes:
|
611
|
-
"""Create an evaluator for the expression.
|
612
|
-
|
613
|
-
>>> from unittest.mock import Mock
|
614
|
-
>>> result = Mock()
|
615
|
-
>>> result.combined_dict = {'how_feeling': 'OK'}
|
616
|
-
|
617
|
-
>>> evaluator = Results._create_evaluator(result = result, functions_dict = {})
|
618
|
-
>>> evaluator.eval("how_feeling == 'OK'")
|
619
|
-
True
|
620
|
-
|
621
|
-
>>> result.combined_dict = {'answer': {'how_feeling': 'OK'}}
|
622
|
-
>>> evaluator = Results._create_evaluator(result = result, functions_dict = {})
|
623
|
-
>>> evaluator.eval("answer.how_feeling== 'OK'")
|
624
|
-
True
|
625
|
-
|
626
|
-
Note that you need to refer to the answer dictionary in the expression.
|
627
|
-
|
628
|
-
>>> evaluator.eval("how_feeling== 'OK'")
|
629
|
-
Traceback (most recent call last):
|
630
|
-
...
|
631
|
-
simpleeval.NameNotDefined: 'how_feeling' is not defined for expression 'how_feeling== 'OK''
|
632
|
-
"""
|
633
|
-
if functions_dict is None:
|
634
|
-
functions_dict = {}
|
635
|
-
return EvalWithCompoundTypes(
|
636
|
-
names=result.combined_dict, functions=functions_dict
|
637
|
-
)
|
638
|
-
|
639
606
|
def mutate(
|
640
607
|
self, new_var_string: str, functions_dict: Optional[dict] = None
|
641
608
|
) -> Results:
|
@@ -668,8 +635,13 @@ class Results(UserList, Mixins, Base):
|
|
668
635
|
# create the evaluator
|
669
636
|
functions_dict = functions_dict or {}
|
670
637
|
|
638
|
+
def create_evaluator(result: Result) -> EvalWithCompoundTypes:
|
639
|
+
return EvalWithCompoundTypes(
|
640
|
+
names=result.combined_dict, functions=functions_dict
|
641
|
+
)
|
642
|
+
|
671
643
|
def new_result(old_result: "Result", var_name: str) -> "Result":
|
672
|
-
evaluator =
|
644
|
+
evaluator = create_evaluator(old_result)
|
673
645
|
value = evaluator.eval(expression)
|
674
646
|
new_result = old_result.copy()
|
675
647
|
new_result["answer"][var_name] = value
|
@@ -769,9 +741,6 @@ class Results(UserList, Mixins, Base):
|
|
769
741
|
>>> results = Results.example()
|
770
742
|
>>> results.select('how_feeling')
|
771
743
|
Dataset([{'answer.how_feeling': ['OK', 'Great', 'Terrible', 'OK']}])
|
772
|
-
|
773
|
-
>>> results.select('how_feeling', 'model', 'how_feeling')
|
774
|
-
Dataset([{'answer.how_feeling': ['OK', 'Great', 'Terrible', 'OK']}, {'model.model': ['gpt-4-1106-preview', 'gpt-4-1106-preview', 'gpt-4-1106-preview', 'gpt-4-1106-preview']}, {'answer.how_feeling': ['OK', 'Great', 'Terrible', 'OK']}])
|
775
744
|
"""
|
776
745
|
|
777
746
|
if len(self) == 0:
|
@@ -829,19 +798,10 @@ class Results(UserList, Mixins, Base):
|
|
829
798
|
# Return the index of this key in the list_of_keys
|
830
799
|
return items_in_order.index(single_key)
|
831
800
|
|
832
|
-
|
801
|
+
sorted(new_data, key=sort_by_key_order)
|
833
802
|
from edsl.results.Dataset import Dataset
|
834
803
|
|
835
|
-
|
836
|
-
|
837
|
-
# WORKS but slow
|
838
|
-
for key in items_in_order:
|
839
|
-
for d in new_data:
|
840
|
-
if key in d:
|
841
|
-
sorted_new_data.append(d)
|
842
|
-
break
|
843
|
-
|
844
|
-
return Dataset(sorted_new_data)
|
804
|
+
return Dataset(new_data)
|
845
805
|
|
846
806
|
def sort_by(self, *columns: str, reverse: bool = False) -> Results:
|
847
807
|
import warnings
|
@@ -956,29 +916,29 @@ class Results(UserList, Mixins, Base):
|
|
956
916
|
"You must use '==' instead of '=' in the filter expression."
|
957
917
|
)
|
958
918
|
|
919
|
+
def create_evaluator(result):
|
920
|
+
"""Create an evaluator for the given result.
|
921
|
+
The 'combined_dict' is a mapping of all values for that Result object.
|
922
|
+
"""
|
923
|
+
return EvalWithCompoundTypes(names=result.combined_dict)
|
924
|
+
|
959
925
|
try:
|
960
926
|
# iterates through all the results and evaluates the expression
|
961
|
-
new_data = [
|
962
|
-
|
963
|
-
|
964
|
-
result.
|
965
|
-
|
966
|
-
new_data.append(result)
|
967
|
-
|
968
|
-
except ValueError as e:
|
969
|
-
raise ResultsFilterError(
|
970
|
-
f"Error in filter. Exception:{e}",
|
971
|
-
f"The expression you provided was: {expression}",
|
972
|
-
"See https://docs.expectedparrot.com/en/latest/results.html#filtering-results for more details.",
|
973
|
-
)
|
927
|
+
new_data = [
|
928
|
+
result
|
929
|
+
for result in self.data
|
930
|
+
if create_evaluator(result).eval(expression)
|
931
|
+
]
|
974
932
|
except Exception as e:
|
975
933
|
raise ResultsFilterError(
|
976
|
-
f"""Error in filter. Exception:{e}.
|
977
|
-
|
978
|
-
|
979
|
-
|
980
|
-
|
981
|
-
|
934
|
+
f"""Error in filter. Exception:{e}.
|
935
|
+
The expression you provided was: {expression}.
|
936
|
+
Please make sure that the expression is a valid Python expression that evaluates to a boolean.
|
937
|
+
For example, 'how_feeling == "Great"' is a valid expression, as is 'how_feeling in ["Great", "Terrible"]'.
|
938
|
+
However, 'how_feeling = "Great"' is not a valid expression.
|
939
|
+
|
940
|
+
See https://docs.expectedparrot.com/en/latest/results.html#filtering-results for more details.
|
941
|
+
"""
|
982
942
|
)
|
983
943
|
|
984
944
|
if len(new_data) == 0:
|
@@ -989,7 +949,7 @@ class Results(UserList, Mixins, Base):
|
|
989
949
|
return Results(survey=self.survey, data=new_data, created_columns=None)
|
990
950
|
|
991
951
|
@classmethod
|
992
|
-
def example(cls, debug: bool = False
|
952
|
+
def example(cls, debug: bool = False) -> Results:
|
993
953
|
"""Return an example `Results` object.
|
994
954
|
|
995
955
|
Example usage:
|
@@ -1002,7 +962,7 @@ class Results(UserList, Mixins, Base):
|
|
1002
962
|
from edsl.data.Cache import Cache
|
1003
963
|
|
1004
964
|
c = Cache()
|
1005
|
-
job = Jobs.example(
|
965
|
+
job = Jobs.example()
|
1006
966
|
results = job.run(cache=c, debug=debug)
|
1007
967
|
return results
|
1008
968
|
|
edsl/scenarios/FileStore.py
CHANGED
@@ -32,9 +32,6 @@ class FileStore(Scenario):
|
|
32
32
|
def from_dict(cls, d):
|
33
33
|
return cls(d["filename"], d["binary"], d["suffix"], d["base64_string"])
|
34
34
|
|
35
|
-
def __repr__(self):
|
36
|
-
return f"FileStore(filename='{self.filename}', binary='{self.binary}', 'suffix'={self.suffix})"
|
37
|
-
|
38
35
|
def encode_file_to_base64_string(self, file_path):
|
39
36
|
try:
|
40
37
|
# Attempt to open the file in text mode
|
@@ -100,14 +97,8 @@ class FileStore(Scenario):
|
|
100
97
|
file_like_object = self.base64_to_text_file(self["base64_string"])
|
101
98
|
|
102
99
|
# Create a named temporary file
|
103
|
-
|
104
|
-
temp_file
|
105
|
-
|
106
|
-
if self.binary:
|
107
|
-
temp_file.write(file_like_object.read())
|
108
|
-
else:
|
109
|
-
temp_file.write(file_like_object.read())
|
110
|
-
|
100
|
+
temp_file = tempfile.NamedTemporaryFile(delete=False, suffix=suffix)
|
101
|
+
temp_file.write(file_like_object.read())
|
111
102
|
temp_file.close()
|
112
103
|
|
113
104
|
return temp_file.name
|
@@ -129,149 +120,11 @@ class CSVFileStore(FileStore):
|
|
129
120
|
def __init__(self, filename):
|
130
121
|
super().__init__(filename, suffix=".csv")
|
131
122
|
|
132
|
-
@classmethod
|
133
|
-
def example(cls):
|
134
|
-
from edsl.results.Results import Results
|
135
|
-
|
136
|
-
r = Results.example()
|
137
|
-
import tempfile
|
138
|
-
|
139
|
-
with tempfile.NamedTemporaryFile(suffix=".csv", delete=False) as f:
|
140
|
-
r.to_csv(filename=f.name)
|
141
|
-
return cls(f.name)
|
142
|
-
|
143
|
-
def view(self):
|
144
|
-
import pandas as pd
|
145
|
-
|
146
|
-
return pd.read_csv(self.to_tempfile())
|
147
|
-
|
148
123
|
|
149
124
|
class PDFFileStore(FileStore):
|
150
125
|
def __init__(self, filename):
|
151
126
|
super().__init__(filename, suffix=".pdf")
|
152
127
|
|
153
|
-
def view(self):
|
154
|
-
pdf_path = self.to_tempfile()
|
155
|
-
print(f"PDF path: {pdf_path}") # Print the path to ensure it exists
|
156
|
-
import os
|
157
|
-
import subprocess
|
158
|
-
|
159
|
-
if os.path.exists(pdf_path):
|
160
|
-
try:
|
161
|
-
if os.name == "posix":
|
162
|
-
# for cool kids
|
163
|
-
subprocess.run(["open", pdf_path], check=True) # macOS
|
164
|
-
elif os.name == "nt":
|
165
|
-
os.startfile(pdf_path) # Windows
|
166
|
-
else:
|
167
|
-
subprocess.run(["xdg-open", pdf_path], check=True) # Linux
|
168
|
-
except Exception as e:
|
169
|
-
print(f"Error opening PDF: {e}")
|
170
|
-
else:
|
171
|
-
print("PDF file was not created successfully.")
|
172
|
-
|
173
|
-
@classmethod
|
174
|
-
def example(cls):
|
175
|
-
import textwrap
|
176
|
-
|
177
|
-
pdf_string = textwrap.dedent(
|
178
|
-
"""\
|
179
|
-
%PDF-1.4
|
180
|
-
1 0 obj
|
181
|
-
<< /Type /Catalog /Pages 2 0 R >>
|
182
|
-
endobj
|
183
|
-
2 0 obj
|
184
|
-
<< /Type /Pages /Kids [3 0 R] /Count 1 >>
|
185
|
-
endobj
|
186
|
-
3 0 obj
|
187
|
-
<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Contents 4 0 R >>
|
188
|
-
endobj
|
189
|
-
4 0 obj
|
190
|
-
<< /Length 44 >>
|
191
|
-
stream
|
192
|
-
BT
|
193
|
-
/F1 24 Tf
|
194
|
-
100 700 Td
|
195
|
-
(Hello, World!) Tj
|
196
|
-
ET
|
197
|
-
endstream
|
198
|
-
endobj
|
199
|
-
5 0 obj
|
200
|
-
<< /Type /Font /Subtype /Type1 /BaseFont /Helvetica >>
|
201
|
-
endobj
|
202
|
-
6 0 obj
|
203
|
-
<< /ProcSet [/PDF /Text] /Font << /F1 5 0 R >> >>
|
204
|
-
endobj
|
205
|
-
xref
|
206
|
-
0 7
|
207
|
-
0000000000 65535 f
|
208
|
-
0000000010 00000 n
|
209
|
-
0000000053 00000 n
|
210
|
-
0000000100 00000 n
|
211
|
-
0000000173 00000 n
|
212
|
-
0000000232 00000 n
|
213
|
-
0000000272 00000 n
|
214
|
-
trailer
|
215
|
-
<< /Size 7 /Root 1 0 R >>
|
216
|
-
startxref
|
217
|
-
318
|
218
|
-
%%EOF"""
|
219
|
-
)
|
220
|
-
import tempfile
|
221
|
-
|
222
|
-
with tempfile.NamedTemporaryFile(suffix=".pdf", delete=False) as f:
|
223
|
-
f.write(pdf_string.encode())
|
224
|
-
return cls(f.name)
|
225
|
-
|
226
|
-
|
227
|
-
class PNGFileStore(FileStore):
|
228
|
-
def __init__(self, filename):
|
229
|
-
super().__init__(filename, suffix=".png")
|
230
|
-
|
231
|
-
@classmethod
|
232
|
-
def example(cls):
|
233
|
-
import textwrap
|
234
|
-
|
235
|
-
png_string = textwrap.dedent(
|
236
|
-
"""\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x01\x00\x00\x00\x01\x00\x08\x06\x00\x00\x00\x1f\x15\xc4\x89\x00\x00\x00\x0cIDAT\x08\xd7c\x00\x01"""
|
237
|
-
)
|
238
|
-
import tempfile
|
239
|
-
|
240
|
-
with tempfile.NamedTemporaryFile(suffix=".png", delete=False) as f:
|
241
|
-
f.write(png_string.encode())
|
242
|
-
return cls(f.name)
|
243
|
-
|
244
|
-
def view(self):
|
245
|
-
import matplotlib.pyplot as plt
|
246
|
-
import matplotlib.image as mpimg
|
247
|
-
|
248
|
-
img = mpimg.imread(self.to_tempfile())
|
249
|
-
plt.imshow(img)
|
250
|
-
plt.show()
|
251
|
-
|
252
|
-
|
253
|
-
class SQLiteFileStore(FileStore):
|
254
|
-
def __init__(self, filename):
|
255
|
-
super().__init__(filename, suffix=".sqlite")
|
256
|
-
|
257
|
-
@classmethod
|
258
|
-
def example(cls):
|
259
|
-
import sqlite3
|
260
|
-
import tempfile
|
261
|
-
|
262
|
-
with tempfile.NamedTemporaryFile(suffix=".sqlite", delete=False) as f:
|
263
|
-
conn = sqlite3.connect(f.name)
|
264
|
-
c = conn.cursor()
|
265
|
-
c.execute("""CREATE TABLE stocks (date text)""")
|
266
|
-
conn.commit()
|
267
|
-
|
268
|
-
def view(self):
|
269
|
-
import subprocess
|
270
|
-
import os
|
271
|
-
|
272
|
-
sqlite_path = self.to_tempfile()
|
273
|
-
os.system(f"sqlite3 {sqlite_path}")
|
274
|
-
|
275
128
|
|
276
129
|
if __name__ == "__main__":
|
277
130
|
# file_path = "../conjure/examples/Ex11-2.sav"
|
@@ -279,21 +132,9 @@ if __name__ == "__main__":
|
|
279
132
|
# info = fs.push()
|
280
133
|
# print(info)
|
281
134
|
|
282
|
-
# fs = CSVFileStore.example()
|
283
|
-
# fs.to_tempfile()
|
284
|
-
# print(fs.view())
|
285
|
-
|
286
|
-
# fs = PDFFileStore.example()
|
287
|
-
# fs.view()
|
288
|
-
|
289
|
-
# fs = PDFFileStore("paper.pdf")
|
290
|
-
# fs.view()
|
291
135
|
# from edsl import Conjure
|
292
136
|
|
293
|
-
fs = PNGFileStore("robot.png")
|
294
|
-
fs.view()
|
295
|
-
|
296
137
|
# c = Conjure(datafile_name=fs.to_tempfile())
|
297
|
-
|
138
|
+
f = PDFFileStore("paper.pdf")
|
298
139
|
# print(f.to_tempfile())
|
299
|
-
|
140
|
+
f.push()
|
edsl/scenarios/Scenario.py
CHANGED
@@ -1,17 +1,21 @@
|
|
1
1
|
"""A Scenario is a dictionary with a key/value to parameterize a question."""
|
2
2
|
|
3
|
-
|
3
|
+
import time
|
4
4
|
import copy
|
5
|
+
from collections import UserDict
|
6
|
+
from typing import Union, List, Optional, Generator
|
5
7
|
import base64
|
6
8
|
import hashlib
|
7
9
|
import os
|
8
|
-
|
9
|
-
from typing import Union, List, Optional, Generator
|
10
|
-
from uuid import uuid4
|
10
|
+
|
11
11
|
from edsl.Base import Base
|
12
12
|
from edsl.scenarios.ScenarioImageMixin import ScenarioImageMixin
|
13
13
|
from edsl.scenarios.ScenarioHtmlMixin import ScenarioHtmlMixin
|
14
|
-
|
14
|
+
|
15
|
+
from edsl.utilities.decorators import (
|
16
|
+
add_edsl_version,
|
17
|
+
remove_edsl_version,
|
18
|
+
)
|
15
19
|
|
16
20
|
|
17
21
|
class Scenario(Base, UserDict, ScenarioImageMixin, ScenarioHtmlMixin):
|
@@ -24,7 +28,9 @@ class Scenario(Base, UserDict, ScenarioImageMixin, ScenarioHtmlMixin):
|
|
24
28
|
|
25
29
|
:param data: A dictionary of keys/values for parameterizing questions.
|
26
30
|
"""
|
27
|
-
|
31
|
+
if data is None:
|
32
|
+
data = {}
|
33
|
+
self.data = data
|
28
34
|
self.name = name
|
29
35
|
|
30
36
|
def replicate(self, n: int) -> "ScenarioList":
|
@@ -409,16 +415,17 @@ class Scenario(Base, UserDict, ScenarioImageMixin, ScenarioHtmlMixin):
|
|
409
415
|
return table
|
410
416
|
|
411
417
|
@classmethod
|
412
|
-
def example(cls
|
413
|
-
"""
|
414
|
-
|
418
|
+
def example(cls) -> "Scenario":
|
419
|
+
"""Return an example scenario.
|
420
|
+
|
421
|
+
Example:
|
415
422
|
|
416
|
-
|
423
|
+
>>> Scenario.example()
|
424
|
+
Scenario({'persona': 'A reseacher studying whether LLMs can be used to generate surveys.'})
|
417
425
|
"""
|
418
|
-
addition = "" if not randomize else str(uuid4())
|
419
426
|
return cls(
|
420
427
|
{
|
421
|
-
"persona":
|
428
|
+
"persona": "A reseacher studying whether LLMs can be used to generate surveys."
|
422
429
|
}
|
423
430
|
)
|
424
431
|
|
edsl/scenarios/ScenarioList.py
CHANGED
@@ -5,8 +5,10 @@ import csv
|
|
5
5
|
import random
|
6
6
|
from collections import UserList, Counter
|
7
7
|
from collections.abc import Iterable
|
8
|
-
from simpleeval import EvalWithCompoundTypes
|
9
8
|
from typing import Any, Optional, Union, List
|
9
|
+
|
10
|
+
from simpleeval import EvalWithCompoundTypes
|
11
|
+
|
10
12
|
from edsl.Base import Base
|
11
13
|
from edsl.utilities.decorators import add_edsl_version, remove_edsl_version
|
12
14
|
from edsl.scenarios.Scenario import Scenario
|
@@ -440,13 +442,9 @@ class ScenarioList(Base, UserList, ScenarioListMixin):
|
|
440
442
|
return lines
|
441
443
|
|
442
444
|
@classmethod
|
443
|
-
def example(cls
|
444
|
-
"""
|
445
|
-
|
446
|
-
|
447
|
-
:params randomize: If True, use Scenario's randomize method to randomize the values.
|
448
|
-
"""
|
449
|
-
return cls([Scenario.example(randomize), Scenario.example(randomize)])
|
445
|
+
def example(cls) -> ScenarioList:
|
446
|
+
"""Return an example of the `ScenarioList`."""
|
447
|
+
return cls([Scenario.example(), Scenario.example()])
|
450
448
|
|
451
449
|
def rich_print(self) -> None:
|
452
450
|
"""Display an object as a table."""
|
edsl/study/Study.py
CHANGED
@@ -6,12 +6,14 @@ import platform
|
|
6
6
|
import socket
|
7
7
|
from datetime import datetime
|
8
8
|
from typing import Dict, Optional, Union
|
9
|
-
from uuid import UUID, uuid4
|
10
9
|
from edsl import Cache, set_session_cache, unset_session_cache
|
11
10
|
from edsl.utilities.utilities import dict_hash
|
12
11
|
from edsl.study.ObjectEntry import ObjectEntry
|
13
12
|
from edsl.study.ProofOfWork import ProofOfWork
|
14
13
|
from edsl.study.SnapShot import SnapShot
|
14
|
+
from uuid import UUID
|
15
|
+
|
16
|
+
# from edsl.Base import Base
|
15
17
|
|
16
18
|
|
17
19
|
class Study:
|
@@ -400,14 +402,14 @@ class Study:
|
|
400
402
|
return diff
|
401
403
|
|
402
404
|
@classmethod
|
403
|
-
def example(cls, verbose=False
|
405
|
+
def example(cls, verbose=False):
|
404
406
|
import tempfile
|
405
407
|
|
406
408
|
study_file = tempfile.NamedTemporaryFile()
|
407
409
|
with cls(filename=study_file.name, verbose=verbose) as study:
|
408
410
|
from edsl import QuestionFreeText
|
409
411
|
|
410
|
-
q = QuestionFreeText.example(
|
412
|
+
q = QuestionFreeText.example()
|
411
413
|
return study
|
412
414
|
|
413
415
|
@classmethod
|
@@ -461,13 +463,13 @@ class Study:
|
|
461
463
|
else:
|
462
464
|
self.objects[oe.hash] = oe
|
463
465
|
|
464
|
-
def push(self) ->
|
466
|
+
def push(self, refresh=False) -> None:
|
465
467
|
"""Push the objects to coop."""
|
466
468
|
|
467
469
|
from edsl import Coop
|
468
470
|
|
469
471
|
coop = Coop()
|
470
|
-
|
472
|
+
coop.create(self, description=self.description)
|
471
473
|
|
472
474
|
@classmethod
|
473
475
|
def pull(cls, uuid: Optional[Union[str, UUID]] = None, url: Optional[str] = None):
|