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.
Files changed (72) hide show
  1. edsl/Base.py +18 -18
  2. edsl/__init__.py +23 -23
  3. edsl/__version__.py +1 -1
  4. edsl/agents/Agent.py +41 -77
  5. edsl/agents/AgentList.py +9 -19
  6. edsl/agents/Invigilator.py +1 -19
  7. edsl/agents/InvigilatorBase.py +10 -15
  8. edsl/agents/PromptConstructionMixin.py +100 -342
  9. edsl/agents/descriptors.py +1 -2
  10. edsl/config.py +1 -2
  11. edsl/conjure/InputData.py +8 -39
  12. edsl/coop/coop.py +150 -187
  13. edsl/coop/utils.py +75 -43
  14. edsl/data/Cache.py +5 -19
  15. edsl/data/SQLiteDict.py +3 -11
  16. edsl/jobs/Answers.py +1 -15
  17. edsl/jobs/Jobs.py +46 -90
  18. edsl/jobs/buckets/ModelBuckets.py +2 -4
  19. edsl/jobs/buckets/TokenBucket.py +2 -1
  20. edsl/jobs/interviews/Interview.py +9 -3
  21. edsl/jobs/interviews/InterviewStatusMixin.py +3 -3
  22. edsl/jobs/interviews/InterviewTaskBuildingMixin.py +10 -15
  23. edsl/jobs/runners/JobsRunnerAsyncio.py +25 -21
  24. edsl/jobs/tasks/TaskHistory.py +3 -4
  25. edsl/language_models/LanguageModel.py +11 -5
  26. edsl/language_models/ModelList.py +1 -1
  27. edsl/language_models/repair.py +7 -8
  28. edsl/notebooks/Notebook.py +3 -40
  29. edsl/prompts/Prompt.py +19 -31
  30. edsl/questions/QuestionBase.py +13 -38
  31. edsl/questions/QuestionBudget.py +6 -5
  32. edsl/questions/QuestionCheckBox.py +3 -7
  33. edsl/questions/QuestionExtract.py +3 -5
  34. edsl/questions/QuestionFreeText.py +3 -3
  35. edsl/questions/QuestionFunctional.py +3 -0
  36. edsl/questions/QuestionList.py +4 -3
  37. edsl/questions/QuestionMultipleChoice.py +8 -16
  38. edsl/questions/QuestionNumerical.py +3 -4
  39. edsl/questions/QuestionRank.py +3 -5
  40. edsl/questions/__init__.py +3 -4
  41. edsl/questions/descriptors.py +2 -4
  42. edsl/questions/question_registry.py +31 -20
  43. edsl/questions/settings.py +1 -1
  44. edsl/results/Dataset.py +0 -31
  45. edsl/results/Result.py +74 -22
  46. edsl/results/Results.py +47 -97
  47. edsl/results/ResultsDBMixin.py +3 -7
  48. edsl/results/ResultsExportMixin.py +537 -22
  49. edsl/results/ResultsGGMixin.py +3 -3
  50. edsl/results/ResultsToolsMixin.py +5 -5
  51. edsl/scenarios/Scenario.py +6 -5
  52. edsl/scenarios/ScenarioList.py +11 -34
  53. edsl/scenarios/ScenarioListPdfMixin.py +1 -2
  54. edsl/scenarios/__init__.py +0 -1
  55. edsl/study/Study.py +9 -3
  56. edsl/surveys/MemoryPlan.py +4 -11
  57. edsl/surveys/Survey.py +7 -46
  58. edsl/surveys/SurveyExportMixin.py +2 -4
  59. edsl/surveys/SurveyFlowVisualizationMixin.py +4 -6
  60. edsl/tools/plotting.py +2 -4
  61. edsl/utilities/__init__.py +21 -21
  62. edsl/utilities/interface.py +45 -66
  63. edsl/utilities/utilities.py +13 -11
  64. {edsl-0.1.29.dist-info → edsl-0.1.29.dev2.dist-info}/METADATA +10 -11
  65. {edsl-0.1.29.dist-info → edsl-0.1.29.dev2.dist-info}/RECORD +68 -71
  66. edsl-0.1.29.dev2.dist-info/entry_points.txt +3 -0
  67. edsl/base/Base.py +0 -289
  68. edsl/results/DatasetExportMixin.py +0 -493
  69. edsl/scenarios/FileStore.py +0 -140
  70. edsl/scenarios/ScenarioListExportMixin.py +0 -32
  71. {edsl-0.1.29.dist-info → edsl-0.1.29.dev2.dist-info}/LICENSE +0 -0
  72. {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
- def print_long(self, max_rows=None) -> None:
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["Survey"] = None,
85
- data: Optional[list["Result"]] = None,
87
+ survey: Optional[Survey] = None,
88
+ data: Optional[list[Result]] = None,
86
89
  created_columns: Optional[list[str]] = None,
87
- cache: Optional["Cache"] = None,
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
- from edsl import Survey, Cache
281
- from edsl.results.Result import Result
282
-
283
- try:
284
- results = cls(
285
- survey=Survey.from_dict(data["survey"]),
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) -> "AgentList":
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["LanguageModel"]]:
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) -> "Result":
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: "Result", var_name: str) -> "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]]) -> "Dataset":
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.Jobs import Jobs
911
+ from edsl.jobs import Jobs
962
912
  from edsl.data.Cache import Cache
963
913
 
964
914
  c = Cache()
@@ -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["pd.DataFrame", str]:
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