edsl 0.1.37.dev5__py3-none-any.whl → 0.1.38__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 (86) hide show
  1. edsl/Base.py +63 -34
  2. edsl/BaseDiff.py +7 -7
  3. edsl/__init__.py +2 -1
  4. edsl/__version__.py +1 -1
  5. edsl/agents/Agent.py +23 -11
  6. edsl/agents/AgentList.py +86 -23
  7. edsl/agents/Invigilator.py +18 -7
  8. edsl/agents/InvigilatorBase.py +0 -19
  9. edsl/agents/PromptConstructor.py +5 -4
  10. edsl/auto/SurveyCreatorPipeline.py +1 -1
  11. edsl/auto/utilities.py +1 -1
  12. edsl/base/Base.py +3 -13
  13. edsl/config.py +8 -0
  14. edsl/coop/coop.py +89 -19
  15. edsl/data/Cache.py +45 -17
  16. edsl/data/CacheEntry.py +8 -3
  17. edsl/data/RemoteCacheSync.py +0 -19
  18. edsl/enums.py +2 -0
  19. edsl/exceptions/agents.py +4 -0
  20. edsl/exceptions/cache.py +5 -0
  21. edsl/inference_services/GoogleService.py +7 -15
  22. edsl/inference_services/PerplexityService.py +163 -0
  23. edsl/inference_services/registry.py +2 -0
  24. edsl/jobs/Jobs.py +110 -559
  25. edsl/jobs/JobsChecks.py +147 -0
  26. edsl/jobs/JobsPrompts.py +268 -0
  27. edsl/jobs/JobsRemoteInferenceHandler.py +239 -0
  28. edsl/jobs/buckets/TokenBucket.py +3 -0
  29. edsl/jobs/interviews/Interview.py +7 -7
  30. edsl/jobs/runners/JobsRunnerAsyncio.py +156 -28
  31. edsl/jobs/runners/JobsRunnerStatus.py +194 -196
  32. edsl/jobs/tasks/TaskHistory.py +27 -19
  33. edsl/language_models/LanguageModel.py +52 -90
  34. edsl/language_models/ModelList.py +67 -14
  35. edsl/language_models/registry.py +57 -4
  36. edsl/notebooks/Notebook.py +7 -8
  37. edsl/prompts/Prompt.py +8 -3
  38. edsl/questions/QuestionBase.py +38 -30
  39. edsl/questions/QuestionBaseGenMixin.py +1 -1
  40. edsl/questions/QuestionBasePromptsMixin.py +0 -17
  41. edsl/questions/QuestionExtract.py +3 -4
  42. edsl/questions/QuestionFunctional.py +10 -3
  43. edsl/questions/derived/QuestionTopK.py +2 -0
  44. edsl/questions/question_registry.py +36 -6
  45. edsl/results/CSSParameterizer.py +108 -0
  46. edsl/results/Dataset.py +146 -15
  47. edsl/results/DatasetExportMixin.py +231 -217
  48. edsl/results/DatasetTree.py +134 -4
  49. edsl/results/Result.py +31 -16
  50. edsl/results/Results.py +159 -65
  51. edsl/results/TableDisplay.py +198 -0
  52. edsl/results/table_display.css +78 -0
  53. edsl/scenarios/FileStore.py +187 -13
  54. edsl/scenarios/Scenario.py +73 -18
  55. edsl/scenarios/ScenarioJoin.py +127 -0
  56. edsl/scenarios/ScenarioList.py +251 -76
  57. edsl/surveys/MemoryPlan.py +1 -1
  58. edsl/surveys/Rule.py +1 -5
  59. edsl/surveys/RuleCollection.py +1 -1
  60. edsl/surveys/Survey.py +25 -19
  61. edsl/surveys/SurveyFlowVisualizationMixin.py +67 -9
  62. edsl/surveys/instructions/ChangeInstruction.py +9 -7
  63. edsl/surveys/instructions/Instruction.py +21 -7
  64. edsl/templates/error_reporting/interview_details.html +3 -3
  65. edsl/templates/error_reporting/interviews.html +18 -9
  66. edsl/{conjure → utilities}/naming_utilities.py +1 -1
  67. edsl/utilities/utilities.py +15 -0
  68. {edsl-0.1.37.dev5.dist-info → edsl-0.1.38.dist-info}/METADATA +2 -1
  69. {edsl-0.1.37.dev5.dist-info → edsl-0.1.38.dist-info}/RECORD +71 -77
  70. edsl/conjure/AgentConstructionMixin.py +0 -160
  71. edsl/conjure/Conjure.py +0 -62
  72. edsl/conjure/InputData.py +0 -659
  73. edsl/conjure/InputDataCSV.py +0 -48
  74. edsl/conjure/InputDataMixinQuestionStats.py +0 -182
  75. edsl/conjure/InputDataPyRead.py +0 -91
  76. edsl/conjure/InputDataSPSS.py +0 -8
  77. edsl/conjure/InputDataStata.py +0 -8
  78. edsl/conjure/QuestionOptionMixin.py +0 -76
  79. edsl/conjure/QuestionTypeMixin.py +0 -23
  80. edsl/conjure/RawQuestion.py +0 -65
  81. edsl/conjure/SurveyResponses.py +0 -7
  82. edsl/conjure/__init__.py +0 -9
  83. edsl/conjure/examples/placeholder.txt +0 -0
  84. edsl/conjure/utilities.py +0 -201
  85. {edsl-0.1.37.dev5.dist-info → edsl-0.1.38.dist-info}/LICENSE +0 -0
  86. {edsl-0.1.37.dev5.dist-info → edsl-0.1.38.dist-info}/WHEEL +0 -0
edsl/Base.py CHANGED
@@ -9,37 +9,46 @@ from uuid import UUID
9
9
 
10
10
  # from edsl.utilities.MethodSuggesterMixin import MethodSuggesterMixin
11
11
 
12
+ from edsl.utilities.utilities import is_notebook
13
+
12
14
 
13
15
  class RichPrintingMixin:
14
- """Mixin for rich printing and persistence of objects."""
16
+ pass
15
17
 
16
- def _for_console(self):
17
- """Return a string representation of the object for console printing."""
18
- from rich.console import Console
18
+ # def print(self):
19
+ # print(self)
19
20
 
20
- with io.StringIO() as buf:
21
- console = Console(file=buf, record=True)
22
- table = self.rich_print()
23
- console.print(table)
24
- return console.export_text()
25
21
 
26
- def __str__(self):
27
- """Return a string representation of the object for console printing."""
28
- return self._for_console()
22
+ # """Mixin for rich printing and persistence of objects."""
29
23
 
30
- def print(self):
31
- """Print the object to the console."""
32
- from edsl.utilities.utilities import is_notebook
24
+ # def _for_console(self):
25
+ # """Return a string representation of the object for console printing."""
26
+ # from rich.console import Console
33
27
 
34
- if is_notebook():
35
- from IPython.display import display
28
+ # with io.StringIO() as buf:
29
+ # console = Console(file=buf, record=True)
30
+ # table = self.rich_print()
31
+ # console.print(table)
32
+ # return console.export_text()
36
33
 
37
- display(self.rich_print())
38
- else:
39
- from rich.console import Console
34
+ # def __str__(self):
35
+ # """Return a string representation of the object for console printing."""
36
+ # # return self._for_console()
37
+ # return self.__repr__()
38
+
39
+ # def print(self):
40
+ # """Print the object to the console."""
41
+ # from edsl.utilities.utilities import is_notebook
42
+
43
+ # if is_notebook():
44
+ # from IPython.display import display
40
45
 
41
- console = Console()
42
- console.print(self.rich_print())
46
+ # display(self.rich_print())
47
+ # else:
48
+ # from rich.console import Console
49
+
50
+ # console = Console()
51
+ # console.print(self.rich_print())
43
52
 
44
53
 
45
54
  class PersistenceMixin:
@@ -201,7 +210,7 @@ class DiffMethodsMixin:
201
210
 
202
211
 
203
212
  class Base(
204
- RichPrintingMixin,
213
+ # RichPrintingMixin,
205
214
  PersistenceMixin,
206
215
  DiffMethodsMixin,
207
216
  ABC,
@@ -209,16 +218,36 @@ class Base(
209
218
  ):
210
219
  """Base class for all classes in the package."""
211
220
 
212
- # def __getitem__(self, key):
213
- # return getattr(self, key)
221
+ def json(self):
222
+ return json.loads(json.dumps(self.to_dict(add_edsl_version=False)))
223
+
224
+ def print(self, **kwargs):
225
+ if "format" in kwargs:
226
+ if kwargs["format"] not in ["html", "markdown", "rich", "latex"]:
227
+ raise ValueError(f"Format '{kwargs['format']}' not supported.")
214
228
 
215
- # @abstractmethod
216
- # def _repr_html_(self) -> str:
217
- # raise NotImplementedError("This method is not implemented yet.")
229
+ if hasattr(self, "table"):
230
+ return self.table()
231
+ else:
232
+ return self
218
233
 
219
- # @abstractmethod
220
- # def _repr_(self) -> str:
221
- # raise NotImplementedError("This method is not implemented yet.")
234
+ def __str__(self):
235
+ return self.__repr__()
236
+
237
+ def summary(self, format="table"):
238
+ from edsl import Scenario
239
+
240
+ d = self._summary()
241
+ if format == "table":
242
+ return Scenario(d).table()
243
+ if format == "dict":
244
+ return d
245
+ if format == "json":
246
+ return Scenario(d).json()
247
+ if format == "yaml":
248
+ return Scenario(d).yaml()
249
+ if format == "html":
250
+ return Scenario(d).table(tablefmt="html")
222
251
 
223
252
  def keys(self):
224
253
  """Return the keys of the object."""
@@ -256,10 +285,10 @@ class Base(
256
285
 
257
286
  if not isinstance(other, self.__class__):
258
287
  return False
259
- if "sort" in inspect.signature(self._to_dict).parameters:
260
- return self._to_dict(sort=True) == other._to_dict(sort=True)
288
+ if "sort" in inspect.signature(self.to_dict).parameters:
289
+ return self.to_dict(sort=True) == other.to_dict(sort=True)
261
290
  else:
262
- return self._to_dict() == other._to_dict()
291
+ return self.to_dict() == other.to_dict()
263
292
 
264
293
  @abstractmethod
265
294
  def example():
edsl/BaseDiff.py CHANGED
@@ -25,7 +25,7 @@ class DummyObject:
25
25
  def __init__(self, object_dict):
26
26
  self.object_dict = object_dict
27
27
 
28
- def _to_dict(self):
28
+ def to_dict(self):
29
29
  return self.object_dict
30
30
 
31
31
 
@@ -38,12 +38,12 @@ class BaseDiff:
38
38
  self.obj1 = obj1
39
39
  self.obj2 = obj2
40
40
 
41
- if "sort" in inspect.signature(obj1._to_dict).parameters:
42
- self._dict1 = obj1._to_dict(sort=True)
43
- self._dict2 = obj2._to_dict(sort=True)
41
+ if "sort" in inspect.signature(obj1.to_dict).parameters:
42
+ self._dict1 = obj1.to_dict(sort=True)
43
+ self._dict2 = obj2.to_dict(sort=True)
44
44
  else:
45
- self._dict1 = obj1._to_dict()
46
- self._dict2 = obj2._to_dict()
45
+ self._dict1 = obj1.to_dict()
46
+ self._dict2 = obj2.to_dict()
47
47
  self._obj_class = type(obj1)
48
48
 
49
49
  self.added = added
@@ -139,7 +139,7 @@ class BaseDiff:
139
139
  def apply(self, obj: Any):
140
140
  """Apply the diff to the object."""
141
141
 
142
- new_obj_dict = obj._to_dict()
142
+ new_obj_dict = obj.to_dict()
143
143
  for k, v in self.added.items():
144
144
  new_obj_dict[k] = v
145
145
  for k in self.removed.keys():
edsl/__init__.py CHANGED
@@ -41,7 +41,8 @@ from edsl.shared import shared_globals
41
41
  from edsl.jobs.Jobs import Jobs
42
42
  from edsl.notebooks.Notebook import Notebook
43
43
  from edsl.study.Study import Study
44
- from edsl.conjure.Conjure import Conjure
44
+
45
+ # from edsl.conjure.Conjure import Conjure
45
46
  from edsl.coop.coop import Coop
46
47
 
47
48
  from edsl.surveys.instructions.Instruction import Instruction
edsl/__version__.py CHANGED
@@ -1 +1 @@
1
- __version__ = "0.1.37.dev5"
1
+ __version__ = "0.1.38"
edsl/agents/Agent.py CHANGED
@@ -243,6 +243,15 @@ class Agent(Base):
243
243
  else:
244
244
  return self._traits
245
245
 
246
+ def _repr_html_(self):
247
+ # d = self.to_dict(add_edsl_version=False)
248
+ d = self.traits
249
+ data = [[k, v] for k, v in d.items()]
250
+ from tabulate import tabulate
251
+
252
+ table = str(tabulate(data, headers=["keys", "values"], tablefmt="html"))
253
+ return f"<pre>{table}</pre>"
254
+
246
255
  def rename(
247
256
  self, old_name_or_dict: Union[str, dict], new_name: Optional[str] = None
248
257
  ) -> Agent:
@@ -631,10 +640,10 @@ class Agent(Base):
631
640
  ]
632
641
  return f"{class_name}({', '.join(items)})"
633
642
 
634
- def _repr_html_(self):
635
- from edsl.utilities.utilities import data_to_html
643
+ # def _repr_html_(self):
644
+ # from edsl.utilities.utilities import data_to_html
636
645
 
637
- return data_to_html(self.to_dict())
646
+ # return data_to_html(self.to_dict())
638
647
 
639
648
  #######################
640
649
  # SERIALIZATION METHODS
@@ -694,14 +703,10 @@ class Agent(Base):
694
703
  def __hash__(self) -> int:
695
704
  from edsl.utilities.utilities import dict_hash
696
705
 
697
- return dict_hash(self._to_dict())
706
+ return dict_hash(self.to_dict(add_edsl_version=False))
698
707
 
699
- def _to_dict(self) -> dict[str, Union[dict, bool]]:
700
- """Serialize to a dictionary without EDSL info"""
701
- return self.data
702
-
703
- @add_edsl_version
704
- def to_dict(self) -> dict[str, Union[dict, bool]]:
708
+ # @add_edsl_version
709
+ def to_dict(self, add_edsl_version=True) -> dict[str, Union[dict, bool]]:
705
710
  """Serialize to a dictionary with EDSL info.
706
711
 
707
712
  Example usage:
@@ -710,7 +715,14 @@ class Agent(Base):
710
715
  >>> a.to_dict()
711
716
  {'name': 'Steve', 'traits': {'age': 10, 'hair': 'brown', 'height': 5.5}, 'edsl_version': '...', 'edsl_class_name': 'Agent'}
712
717
  """
713
- return self._to_dict()
718
+ d = copy.deepcopy(self.data)
719
+ if add_edsl_version:
720
+ from edsl import __version__
721
+
722
+ d["edsl_version"] = __version__
723
+ d["edsl_class_name"] = self.__class__.__name__
724
+
725
+ return d
714
726
 
715
727
  @classmethod
716
728
  @remove_edsl_version
edsl/agents/AgentList.py CHANGED
@@ -14,7 +14,7 @@ from __future__ import annotations
14
14
  import csv
15
15
  import json
16
16
  from collections import UserList
17
- from typing import Any, List, Optional, Union
17
+ from typing import Any, List, Optional, Union, TYPE_CHECKING
18
18
  from rich import print_json
19
19
  from rich.table import Table
20
20
  from simpleeval import EvalWithCompoundTypes
@@ -23,6 +23,11 @@ from edsl.utilities.decorators import add_edsl_version, remove_edsl_version
23
23
 
24
24
  from collections.abc import Iterable
25
25
 
26
+ from edsl.exceptions.agents import AgentListError
27
+
28
+ if TYPE_CHECKING:
29
+ from edsl.scenarios.ScenarioList import ScenarioList
30
+
26
31
 
27
32
  def is_iterable(obj):
28
33
  return isinstance(obj, Iterable)
@@ -31,6 +36,10 @@ def is_iterable(obj):
31
36
  class AgentList(UserList, Base):
32
37
  """A list of Agents."""
33
38
 
39
+ __documentation__ = (
40
+ "https://docs.expectedparrot.com/en/latest/agents.html#agentlist-class"
41
+ )
42
+
34
43
  def __init__(self, data: Optional[list["Agent"]] = None):
35
44
  """Initialize a new AgentList.
36
45
 
@@ -52,7 +61,7 @@ class AgentList(UserList, Base):
52
61
  random.shuffle(self.data)
53
62
  return self
54
63
 
55
- def sample(self, n: int, seed="edsl") -> AgentList:
64
+ def sample(self, n: int, seed: Optional[str] = None) -> AgentList:
56
65
  """Return a random sample of agents.
57
66
 
58
67
  :param n: The number of agents to sample.
@@ -60,9 +69,17 @@ class AgentList(UserList, Base):
60
69
  """
61
70
  import random
62
71
 
63
- random.seed(seed)
72
+ if seed:
73
+ random.seed(seed)
64
74
  return AgentList(random.sample(self.data, n))
65
75
 
76
+ def to_pandas(self):
77
+ """Return a pandas DataFrame."""
78
+ return self.to_scenario_list().to_pandas()
79
+
80
+ def tally(self):
81
+ return self.to_scenario_list().tally()
82
+
66
83
  def rename(self, old_name, new_name):
67
84
  """Rename a trait in the AgentList.
68
85
 
@@ -113,7 +130,7 @@ class AgentList(UserList, Base):
113
130
  ]
114
131
  except Exception as e:
115
132
  print(f"Exception:{e}")
116
- raise Exception(f"Error in filter. Exception:{e}")
133
+ raise AgentListError(f"Error in filter. Exception:{e}")
117
134
 
118
135
  return AgentList(new_data)
119
136
 
@@ -199,7 +216,8 @@ class AgentList(UserList, Base):
199
216
  >>> al.add_trait('new_trait', [1, 2, 3])
200
217
  Traceback (most recent call last):
201
218
  ...
202
- ValueError: The passed values have to be the same length as the agent list.
219
+ edsl.exceptions.agents.AgentListError: The passed values have to be the same length as the agent list.
220
+ ...
203
221
  """
204
222
  if not is_iterable(values):
205
223
  value = values
@@ -208,7 +226,7 @@ class AgentList(UserList, Base):
208
226
  return self
209
227
 
210
228
  if len(values) != len(self):
211
- raise ValueError(
229
+ raise AgentListError(
212
230
  "The passed values have to be the same length as the agent list."
213
231
  )
214
232
  for agent, value in zip(self.data, values):
@@ -228,47 +246,89 @@ class AgentList(UserList, Base):
228
246
  def __hash__(self) -> int:
229
247
  from edsl.utilities.utilities import dict_hash
230
248
 
231
- data = self.to_dict()
232
- # data['agent_list'] = sorted(data['agent_list'], key=lambda x: dict_hash(x)
233
- return dict_hash(self._to_dict(sorted=True))
249
+ return dict_hash(self.to_dict(add_edsl_version=False, sorted=True))
234
250
 
235
- def _to_dict(self, sorted=False):
251
+ def to_dict(self, sorted=False, add_edsl_version=True):
252
+ """Serialize the AgentList to a dictionary."""
236
253
  if sorted:
237
254
  data = self.data[:]
238
255
  data.sort(key=lambda x: hash(x))
239
256
  else:
240
257
  data = self.data
241
258
 
242
- return {"agent_list": [agent.to_dict() for agent in data]}
259
+ d = {
260
+ "agent_list": [
261
+ agent.to_dict(add_edsl_version=add_edsl_version) for agent in data
262
+ ]
263
+ }
264
+ if add_edsl_version:
265
+ from edsl import __version__
243
266
 
244
- def __eq__(self, other: AgentList) -> bool:
245
- return self._to_dict(sorted=True) == other._to_dict(sorted=True)
267
+ d["edsl_version"] = __version__
268
+ d["edsl_class_name"] = "AgentList"
246
269
 
247
- @add_edsl_version
248
- def to_dict(self):
249
- """Return dictionary of AgentList to serialization."""
250
- return self._to_dict()
270
+ return d
271
+
272
+ def __eq__(self, other: AgentList) -> bool:
273
+ return self.to_dict(sorted=True, add_edsl_version=False) == other.to_dict(
274
+ sorted=True, add_edsl_version=False
275
+ )
251
276
 
252
277
  def __repr__(self):
253
278
  return f"AgentList({self.data})"
254
279
 
255
- def print(self, format: Optional[str] = None):
256
- """Print the AgentList."""
257
- print_json(json.dumps(self._to_dict()))
280
+ def _summary(self):
281
+ return {
282
+ "EDSL Class": "AgentList",
283
+ "Number of agents": len(self),
284
+ "Agent trait fields": self.all_traits,
285
+ }
258
286
 
259
287
  def _repr_html_(self):
260
288
  """Return an HTML representation of the AgentList."""
261
- from edsl.utilities.utilities import data_to_html
289
+ footer = f"<a href={self.__documentation__}>(docs)</a>"
290
+ return str(self.summary(format="html")) + footer
291
+
292
+ def to_csv(self, file_path: str):
293
+ """Save the AgentList to a CSV file.
262
294
 
263
- return data_to_html(self.to_dict()["agent_list"])
295
+ :param file_path: The path to the CSV file.
296
+ """
297
+ self.to_scenario_list().to_csv(file_path)
264
298
 
265
- def to_scenario_list(self) -> "ScenarioList":
299
+ def to_list(self, include_agent_name=False) -> list[tuple]:
300
+ """Return a list of tuples."""
301
+ return self.to_scenario_list(include_agent_name).to_list()
302
+
303
+ def to_scenario_list(self, include_agent_name=False) -> ScenarioList:
266
304
  """Return a list of scenarios."""
267
305
  from edsl.scenarios.ScenarioList import ScenarioList
268
306
  from edsl.scenarios.Scenario import Scenario
269
307
 
308
+ if include_agent_name:
309
+ return ScenarioList(
310
+ [
311
+ Scenario(agent.traits | {"agent_name": agent.name})
312
+ for agent in self.data
313
+ ]
314
+ )
270
315
  return ScenarioList([Scenario(agent.traits) for agent in self.data])
271
316
 
317
+ def table(
318
+ self,
319
+ *fields,
320
+ tablefmt: Optional[str] = None,
321
+ pretty_labels: Optional[dict] = None,
322
+ ) -> Table:
323
+ return (
324
+ self.to_scenario_list()
325
+ .to_dataset()
326
+ .table(*fields, tablefmt=tablefmt, pretty_labels=pretty_labels)
327
+ )
328
+
329
+ def tree(self, node_order: Optional[List[str]] = None):
330
+ return self.to_scenario_list().tree(node_order)
331
+
272
332
  @classmethod
273
333
  @remove_edsl_version
274
334
  def from_dict(cls, data: dict) -> "AgentList":
@@ -303,6 +363,9 @@ class AgentList(UserList, Base):
303
363
 
304
364
  :param trait_name: The name of the trait.
305
365
  :param values: A list of values.
366
+
367
+ >>> AgentList.from_list('age', [22, 23])
368
+ AgentList([Agent(traits = {'age': 22}), Agent(traits = {'age': 23})])
306
369
  """
307
370
  from edsl.agents.Agent import Agent
308
371
 
@@ -45,6 +45,10 @@ class InvigilatorAI(InvigilatorBase):
45
45
 
46
46
  params.update({"iteration": self.iteration, "cache": self.cache})
47
47
 
48
+ params.update({"invigilator": self})
49
+ # if hasattr(self.question, "answer_template"):
50
+ # breakpoint()
51
+
48
52
  agent_response_dict: AgentResponseDict = await self.model.async_get_response(
49
53
  **params
50
54
  )
@@ -83,19 +87,26 @@ class InvigilatorAI(InvigilatorBase):
83
87
  exception_occurred = None
84
88
  validated = False
85
89
  try:
86
- # if the question has jinja parameters, it might be easier to make a new question
87
- # with those all filled in & then validate that
88
- # breakpoint()
90
+ # if the question has jinja parameters, it is easier to make a new question with the parameters
89
91
  if self.question.parameters:
90
92
  prior_answers_dict = self.prompt_constructor.prior_answers_dict()
93
+
94
+ # question options have be treated differently because of dynamic question
95
+ # this logic is all in the prompt constructor
96
+ if "question_options" in self.question.data:
97
+ new_question_options = (
98
+ self.prompt_constructor._get_question_options(
99
+ self.question.data
100
+ )
101
+ )
102
+ if new_question_options != self.question.data["question_options"]:
103
+ # I don't love this direct writing but it seems to work
104
+ self.question.question_options = new_question_options
105
+
91
106
  question_with_validators = self.question.render(
92
107
  self.scenario | prior_answers_dict
93
108
  )
94
109
  question_with_validators.use_code = self.question.use_code
95
- # if question_with_validators.parameters:
96
- # raise ValueError(
97
- # f"The question still has parameters after rendering: {question_with_validators}"
98
- # )
99
110
  else:
100
111
  question_with_validators = self.question
101
112
 
@@ -172,25 +172,6 @@ class InvigilatorBase(ABC):
172
172
  }
173
173
  return EDSLResultObjectInput(**data)
174
174
 
175
- # breakpoint()
176
- # if hasattr(self, "augmented_model_response"):
177
- # import json
178
-
179
- # generated_tokens = json.loads(self.augmented_model_response)["answer"][
180
- # "generated_tokens"
181
- # ]
182
- # else:
183
- # generated_tokens = "Filled in by InvigilatorBase.get_failed_task_result"
184
- # agent_response_dict = AgentResponseDict(
185
- # answer=None,
186
- # comment="Failed to get usable response",
187
- # generated_tokens=generated_tokens,
188
- # question_name=self.question.question_name,
189
- # prompts=self.get_prompts(),
190
- # )
191
- # # breakpoint()
192
- # return agent_response_dict
193
-
194
175
  def get_prompts(self) -> Dict[str, Prompt]:
195
176
  """Return the prompt used."""
196
177
 
@@ -169,6 +169,8 @@ class PromptConstructor:
169
169
 
170
170
  placeholder = ["<< Option 1 - Placholder >>", "<< Option 2 - Placholder >>"]
171
171
 
172
+ # print("Question options entry: ", question_options_entry)
173
+
172
174
  if isinstance(question_options_entry, str):
173
175
  env = Environment()
174
176
  parsed_content = env.parse(question_options_entry)
@@ -200,13 +202,12 @@ class PromptConstructor:
200
202
  # e.g., {'question_text': 'Do you like school?', 'question_name': 'q0', 'question_options': ['yes', 'no']}
201
203
  question_data = self.question.data.copy()
202
204
 
203
- if "question_options" in question_data:
205
+ if (
206
+ "question_options" in question_data
207
+ ): # is this a question with question options?
204
208
  question_options = self._get_question_options(question_data)
205
209
  question_data["question_options"] = question_options
206
210
 
207
- # check to see if the question_options is actually a string
208
- # This is used when the user is using the question_options as a variable from a scenario
209
- # if "question_options" in question_data:
210
211
  replacement_dict = self.build_replacement_dict(question_data)
211
212
  rendered_instructions = question_prompt.render(replacement_dict)
212
213
 
@@ -15,7 +15,7 @@ from edsl.surveys.Survey import Survey
15
15
  from edsl.questions.QuestionMultipleChoice import QuestionMultipleChoice
16
16
  from edsl.questions.QuestionFreeText import QuestionFreeText
17
17
  from edsl.auto.utilities import gen_pipeline
18
- from edsl.conjure.naming_utilities import sanitize_string
18
+ from edsl.utilities.naming_utilities import sanitize_string
19
19
 
20
20
 
21
21
  m = Model()
edsl/auto/utilities.py CHANGED
@@ -2,7 +2,7 @@ from textwrap import dedent
2
2
  import random
3
3
  from typing import List, TypeVar, Generator, Optional
4
4
  from edsl.auto.StageBase import StageBase
5
- from edsl.conjure.naming_utilities import sanitize_string
5
+ from edsl.utilities.naming_utilities import sanitize_string
6
6
  from edsl import Agent, Survey, Model, Cache, AgentList
7
7
  from edsl import QuestionFreeText, Scenario
8
8
  from edsl import QuestionMultipleChoice, Scenario, Agent, ScenarioList
edsl/base/Base.py CHANGED
@@ -229,26 +229,16 @@ class Base(
229
229
 
230
230
  return data_to_html(self.to_dict())
231
231
 
232
- # def html(self):
233
- # html_string = self._repr_html_()
234
- # import tempfile
235
- # import webbrowser
236
-
237
- # with tempfile.NamedTemporaryFile("w", delete=False, suffix=".html") as f:
238
- # # print("Writing HTML to", f.name)
239
- # f.write(html_string)
240
- # webbrowser.open(f.name)
241
-
242
232
  def __eq__(self, other):
243
233
  """Return whether two objects are equal."""
244
234
  import inspect
245
235
 
246
236
  if not isinstance(other, self.__class__):
247
237
  return False
248
- if "sort" in inspect.signature(self._to_dict).parameters:
249
- return self._to_dict(sort=True) == other._to_dict(sort=True)
238
+ if "sort" in inspect.signature(self.to_dict).parameters:
239
+ return self.to_dict(sort=True) == other.to_dict(sort=True)
250
240
  else:
251
- return self._to_dict() == other._to_dict()
241
+ return self.to_dict() == other.to_dict()
252
242
 
253
243
  @abstractmethod
254
244
  def example():
edsl/config.py CHANGED
@@ -61,6 +61,14 @@ CONFIG_MAP = {
61
61
  "default": "https://www.expectedparrot.com",
62
62
  "info": "This config var holds the URL of the Expected Parrot API.",
63
63
  },
64
+ "EDSL_MAX_CONCURRENT_TASKS": {
65
+ "default": "500",
66
+ "info": "This config var determines the maximum number of concurrent tasks that can be run by the async job-runner",
67
+ },
68
+ "EDSL_OPEN_EXCEPTION_REPORT_URL": {
69
+ "default": "False",
70
+ "info": "This config var determines whether to open the exception report URL in the browser",
71
+ },
64
72
  }
65
73
 
66
74