edsl 0.1.33.dev3__py3-none-any.whl → 0.1.34.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.
Files changed (41) hide show
  1. edsl/Base.py +15 -11
  2. edsl/__version__.py +1 -1
  3. edsl/agents/Invigilator.py +22 -3
  4. edsl/agents/PromptConstructor.py +79 -183
  5. edsl/agents/prompt_helpers.py +129 -0
  6. edsl/coop/coop.py +3 -2
  7. edsl/data_transfer_models.py +0 -1
  8. edsl/inference_services/AnthropicService.py +5 -2
  9. edsl/inference_services/AwsBedrock.py +5 -2
  10. edsl/inference_services/AzureAI.py +5 -2
  11. edsl/inference_services/GoogleService.py +108 -33
  12. edsl/inference_services/MistralAIService.py +5 -2
  13. edsl/inference_services/OpenAIService.py +3 -2
  14. edsl/inference_services/TestService.py +11 -2
  15. edsl/inference_services/TogetherAIService.py +1 -1
  16. edsl/jobs/interviews/Interview.py +19 -9
  17. edsl/jobs/runners/JobsRunnerAsyncio.py +37 -16
  18. edsl/jobs/runners/JobsRunnerStatus.py +4 -3
  19. edsl/jobs/tasks/QuestionTaskCreator.py +1 -13
  20. edsl/language_models/LanguageModel.py +12 -9
  21. edsl/language_models/utilities.py +3 -2
  22. edsl/questions/QuestionBase.py +11 -2
  23. edsl/questions/QuestionBaseGenMixin.py +28 -0
  24. edsl/questions/QuestionCheckBox.py +1 -1
  25. edsl/questions/QuestionMultipleChoice.py +5 -1
  26. edsl/questions/ResponseValidatorABC.py +5 -1
  27. edsl/questions/descriptors.py +12 -11
  28. edsl/questions/templates/yes_no/answering_instructions.jinja +2 -2
  29. edsl/scenarios/FileStore.py +159 -71
  30. edsl/scenarios/Scenario.py +23 -49
  31. edsl/scenarios/ScenarioList.py +6 -2
  32. edsl/surveys/DAG.py +62 -0
  33. edsl/surveys/MemoryPlan.py +26 -0
  34. edsl/surveys/Rule.py +24 -0
  35. edsl/surveys/RuleCollection.py +36 -2
  36. edsl/surveys/Survey.py +182 -10
  37. {edsl-0.1.33.dev3.dist-info → edsl-0.1.34.dev1.dist-info}/METADATA +2 -1
  38. {edsl-0.1.33.dev3.dist-info → edsl-0.1.34.dev1.dist-info}/RECORD +40 -40
  39. edsl/scenarios/ScenarioImageMixin.py +0 -100
  40. {edsl-0.1.33.dev3.dist-info → edsl-0.1.34.dev1.dist-info}/LICENSE +0 -0
  41. {edsl-0.1.33.dev3.dist-info → edsl-0.1.34.dev1.dist-info}/WHEEL +0 -0
edsl/surveys/Rule.py CHANGED
@@ -38,9 +38,29 @@ from edsl.utilities.ast_utilities import extract_variable_names
38
38
  from edsl.utilities.decorators import add_edsl_version, remove_edsl_version
39
39
 
40
40
 
41
+ class QuestionIndex:
42
+ def __set_name__(self, owner, name):
43
+ self.name = f"_{name}"
44
+
45
+ def __get__(self, obj, objtype=None):
46
+ return getattr(obj, self.name)
47
+
48
+ def __set__(self, obj, value):
49
+ if not isinstance(value, (int, EndOfSurvey.__class__)):
50
+ raise ValueError(f"{self.name} must be an integer or EndOfSurvey")
51
+ if self.name == "_next_q" and isinstance(value, int):
52
+ current_q = getattr(obj, "_current_q")
53
+ if value <= current_q:
54
+ raise ValueError("next_q must be greater than current_q")
55
+ setattr(obj, self.name, value)
56
+
57
+
41
58
  class Rule:
42
59
  """The Rule class defines a "rule" for determining the next question presented to an agent."""
43
60
 
61
+ current_q = QuestionIndex()
62
+ next_q = QuestionIndex()
63
+
44
64
  # Not implemented but nice to have:
45
65
  # We could potentially use the question pydantic models to check for rule conflicts, as
46
66
  # they define the potential trees through a survey.
@@ -75,6 +95,10 @@ class Rule:
75
95
  self.priority = priority
76
96
  self.before_rule = before_rule
77
97
 
98
+ if not self.next_q == EndOfSurvey:
99
+ if self.next_q <= self.current_q:
100
+ raise SurveyRuleSendsYouBackwardsError
101
+
78
102
  if not self.next_q == EndOfSurvey and self.current_q > self.next_q:
79
103
  raise SurveyRuleSendsYouBackwardsError
80
104
 
@@ -120,13 +120,13 @@ class RuleCollection(UserList):
120
120
  :param answers: The answers to the survey questions.
121
121
 
122
122
  >>> rule_collection = RuleCollection()
123
- >>> r = Rule(current_q=1, expression="True", next_q=1, priority=1, question_name_to_index={}, before_rule = True)
123
+ >>> r = Rule(current_q=1, expression="True", next_q=2, priority=1, question_name_to_index={}, before_rule = True)
124
124
  >>> rule_collection.add_rule(r)
125
125
  >>> rule_collection.skip_question_before_running(1, {})
126
126
  True
127
127
 
128
128
  >>> rule_collection = RuleCollection()
129
- >>> r = Rule(current_q=1, expression="False", next_q=1, priority=1, question_name_to_index={}, before_rule = True)
129
+ >>> r = Rule(current_q=1, expression="False", next_q=2, priority=1, question_name_to_index={}, before_rule = True)
130
130
  >>> rule_collection.add_rule(r)
131
131
  >>> rule_collection.skip_question_before_running(1, {})
132
132
  False
@@ -321,6 +321,40 @@ class RuleCollection(UserList):
321
321
 
322
322
  return DAG(dict(sorted(children_to_parents.items())))
323
323
 
324
+ def detect_cycles(self):
325
+ """
326
+ Detect cycles in the survey rules using depth-first search.
327
+
328
+ :return: A list of cycles if any are found, otherwise an empty list.
329
+ """
330
+ dag = self.dag
331
+ visited = set()
332
+ path = []
333
+ cycles = []
334
+
335
+ def dfs(node):
336
+ if node in path:
337
+ cycle = path[path.index(node) :]
338
+ cycles.append(cycle + [node])
339
+ return
340
+
341
+ if node in visited:
342
+ return
343
+
344
+ visited.add(node)
345
+ path.append(node)
346
+
347
+ for child in dag.get(node, []):
348
+ dfs(child)
349
+
350
+ path.pop()
351
+
352
+ for node in dag:
353
+ if node not in visited:
354
+ dfs(node)
355
+
356
+ return cycles
357
+
324
358
  @classmethod
325
359
  def example(cls):
326
360
  """Create an example RuleCollection object."""
edsl/surveys/Survey.py CHANGED
@@ -22,6 +22,10 @@ from edsl.utilities.decorators import add_edsl_version, remove_edsl_version
22
22
 
23
23
  from edsl.agents.Agent import Agent
24
24
 
25
+ from edsl.surveys.instructions.InstructionCollection import InstructionCollection
26
+ from edsl.surveys.instructions.Instruction import Instruction
27
+ from edsl.surveys.instructions.ChangeInstruction import ChangeInstruction
28
+
25
29
 
26
30
  class ValidatedString(str):
27
31
  def __new__(cls, content):
@@ -32,13 +36,6 @@ class ValidatedString(str):
32
36
  return super().__new__(cls, content)
33
37
 
34
38
 
35
- # from edsl.surveys.Instruction import Instruction
36
- # from edsl.surveys.Instruction import ChangeInstruction
37
- from edsl.surveys.instructions.InstructionCollection import InstructionCollection
38
- from edsl.surveys.instructions.Instruction import Instruction
39
- from edsl.surveys.instructions.ChangeInstruction import ChangeInstruction
40
-
41
-
42
39
  class Survey(SurveyExportMixin, SurveyFlowVisualizationMixin, Base):
43
40
  """A collection of questions that supports skip logic."""
44
41
 
@@ -289,16 +286,52 @@ class Survey(SurveyExportMixin, SurveyFlowVisualizationMixin, Base):
289
286
 
290
287
  # region: Simulation methods
291
288
 
289
+ @classmethod
290
+ def random_survey(self):
291
+ """Create a random survey."""
292
+ from edsl.questions import QuestionMultipleChoice, QuestionFreeText
293
+ from random import choice
294
+
295
+ num_questions = 10
296
+ questions = []
297
+ for i in range(num_questions):
298
+ if choice([True, False]):
299
+ q = QuestionMultipleChoice(
300
+ question_text="nothing",
301
+ question_name="q_" + str(i),
302
+ question_options=list(range(3)),
303
+ )
304
+ questions.append(q)
305
+ else:
306
+ questions.append(
307
+ QuestionFreeText(
308
+ question_text="nothing", question_name="q_" + str(i)
309
+ )
310
+ )
311
+ s = Survey(questions)
312
+ start_index = choice(range(num_questions - 1))
313
+ end_index = choice(range(start_index + 1, 10))
314
+ s = s.add_rule(f"q_{start_index}", "True", f"q_{end_index}")
315
+ question_to_delete = choice(range(num_questions))
316
+ s.delete_question(f"q_{question_to_delete}")
317
+ return s
318
+
292
319
  def simulate(self) -> dict:
293
320
  """Simulate the survey and return the answers."""
294
321
  i = self.gen_path_through_survey()
295
322
  q = next(i)
323
+ num_passes = 0
296
324
  while True:
325
+ num_passes += 1
297
326
  try:
298
327
  answer = q._simulate_answer()
299
328
  q = i.send({q.question_name: answer["answer"]})
300
329
  except StopIteration:
301
330
  break
331
+
332
+ if num_passes > 100:
333
+ print("Too many passes.")
334
+ raise Exception("Too many passes.")
302
335
  return self.answers
303
336
 
304
337
  def create_agent(self) -> "Agent":
@@ -573,7 +606,110 @@ class Survey(SurveyExportMixin, SurveyFlowVisualizationMixin, Base):
573
606
 
574
607
  return Survey(questions=self.questions + other.questions)
575
608
 
576
- def add_question(self, question: QuestionBase) -> Survey:
609
+ def move_question(self, identifier: Union[str, int], new_index: int):
610
+ if isinstance(identifier, str):
611
+ if identifier not in self.question_names:
612
+ raise ValueError(
613
+ f"Question name '{identifier}' does not exist in the survey."
614
+ )
615
+ index = self.question_name_to_index[identifier]
616
+ elif isinstance(identifier, int):
617
+ if identifier < 0 or identifier >= len(self.questions):
618
+ raise ValueError(f"Index {identifier} is out of range.")
619
+ index = identifier
620
+ else:
621
+ raise TypeError(
622
+ "Identifier must be either a string (question name) or an integer (question index)."
623
+ )
624
+
625
+ moving_question = self._questions[index]
626
+
627
+ new_survey = self.delete_question(index)
628
+ new_survey.add_question(moving_question, new_index)
629
+ return new_survey
630
+
631
+ def delete_question(self, identifier: Union[str, int]) -> Survey:
632
+ """
633
+ Delete a question from the survey.
634
+
635
+ :param identifier: The name or index of the question to delete.
636
+ :return: The updated Survey object.
637
+
638
+ >>> from edsl import QuestionMultipleChoice, Survey
639
+ >>> q1 = QuestionMultipleChoice(question_text="Q1", question_options=["A", "B"], question_name="q1")
640
+ >>> q2 = QuestionMultipleChoice(question_text="Q2", question_options=["C", "D"], question_name="q2")
641
+ >>> s = Survey().add_question(q1).add_question(q2)
642
+ >>> _ = s.delete_question("q1")
643
+ >>> len(s.questions)
644
+ 1
645
+ >>> _ = s.delete_question(0)
646
+ >>> len(s.questions)
647
+ 0
648
+ """
649
+ if isinstance(identifier, str):
650
+ if identifier not in self.question_names:
651
+ raise ValueError(
652
+ f"Question name '{identifier}' does not exist in the survey."
653
+ )
654
+ index = self.question_name_to_index[identifier]
655
+ elif isinstance(identifier, int):
656
+ if identifier < 0 or identifier >= len(self.questions):
657
+ raise ValueError(f"Index {identifier} is out of range.")
658
+ index = identifier
659
+ else:
660
+ raise TypeError(
661
+ "Identifier must be either a string (question name) or an integer (question index)."
662
+ )
663
+
664
+ # Remove the question
665
+ deleted_question = self._questions.pop(index)
666
+ del self.pseudo_indices[deleted_question.question_name]
667
+ # del self.question_name_to_index[deleted_question.question_name]
668
+
669
+ # Update indices
670
+ for question_name, old_index in self.pseudo_indices.items():
671
+ if old_index > index:
672
+ self.pseudo_indices[question_name] = old_index - 1
673
+
674
+ # for question_name, old_index in self.question_name_to_index.items():
675
+ # if old_index > index:
676
+ # self.question_name_to_index[question_name] = old_index - 1
677
+
678
+ # Update rules
679
+ new_rule_collection = RuleCollection()
680
+ for rule in self.rule_collection:
681
+ if rule.current_q == index:
682
+ continue # Remove rules associated with the deleted question
683
+ if rule.current_q > index:
684
+ rule.current_q -= 1
685
+ if rule.next_q > index:
686
+ rule.next_q -= 1
687
+
688
+ if rule.next_q == index:
689
+ if index == len(self.questions):
690
+ rule.next_q = EndOfSurvey
691
+ else:
692
+ rule.next_q = index
693
+ # rule.next_q = min(index, len(self.questions) - 1)
694
+ # continue
695
+
696
+ # if rule.next_q == index:
697
+ # rule.next_q = min(
698
+ # rule.next_q, len(self.questions) - 1
699
+ # ) # Adjust to last question if necessary
700
+
701
+ new_rule_collection.add_rule(rule)
702
+ self.rule_collection = new_rule_collection
703
+
704
+ # Update memory plan if it exists
705
+ if hasattr(self, "memory_plan"):
706
+ self.memory_plan.remove_question(deleted_question.question_name)
707
+
708
+ return self
709
+
710
+ def add_question(
711
+ self, question: QuestionBase, index: Optional[int] = None
712
+ ) -> Survey:
577
713
  """
578
714
  Add a question to survey.
579
715
 
@@ -596,15 +732,51 @@ class Survey(SurveyExportMixin, SurveyFlowVisualizationMixin, Base):
596
732
  raise SurveyCreationError(
597
733
  f"""Question name '{question.question_name}' already exists in survey. Existing names are {self.question_names}."""
598
734
  )
599
- index = len(self.questions)
735
+ if index is None:
736
+ index = len(self.questions)
737
+
738
+ if index > len(self.questions):
739
+ raise ValueError(
740
+ f"Index {index} is greater than the number of questions in the survey."
741
+ )
742
+ if index < 0:
743
+ raise ValueError(f"Index {index} is less than 0.")
744
+
745
+ interior_insertion = index != len(self.questions)
746
+
747
+ # index = len(self.questions)
600
748
  # TODO: This is a bit ugly because the user
601
749
  # doesn't "know" about _questions - it's generated by the
602
750
  # descriptor.
603
- self._questions.append(question)
751
+ self._questions.insert(index, question)
752
+
753
+ if interior_insertion:
754
+ for question_name, old_index in self.pseudo_indices.items():
755
+ if old_index >= index:
756
+ self.pseudo_indices[question_name] = old_index + 1
604
757
 
605
758
  self.pseudo_indices[question.question_name] = index
606
759
 
760
+ ## Re-do question_name to index - this is done automatically
761
+ # for question_name, old_index in self.question_name_to_index.items():
762
+ # if old_index >= index:
763
+ # self.question_name_to_index[question_name] = old_index + 1
764
+
765
+ ## Need to re-do the rule collection and the indices of the questions
766
+
767
+ ## If a rule is before the insertion index and next_q is also before the insertion index, no change needed.
768
+ ## If the rule is before the insertion index but next_q is after the insertion index, increment the next_q by 1
769
+ ## If the rule is after the insertion index, increment the current_q by 1 and the next_q by 1
770
+
607
771
  # using index + 1 presumes there is a next question
772
+ if interior_insertion:
773
+ for rule in self.rule_collection:
774
+ if rule.current_q >= index:
775
+ rule.current_q += 1
776
+ if rule.next_q >= index:
777
+ rule.next_q += 1
778
+
779
+ # add a new rule
608
780
  self.rule_collection.add_rule(
609
781
  Rule(
610
782
  current_q=index,
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: edsl
3
- Version: 0.1.33.dev3
3
+ Version: 0.1.34.dev1
4
4
  Summary: Create and analyze LLM-based surveys
5
5
  Home-page: https://www.expectedparrot.com/
6
6
  License: MIT
@@ -21,6 +21,7 @@ Requires-Dist: anthropic (>=0.23.1,<0.24.0)
21
21
  Requires-Dist: azure-ai-inference (>=1.0.0b3,<2.0.0)
22
22
  Requires-Dist: black[jupyter] (>=24.4.2,<25.0.0)
23
23
  Requires-Dist: boto3 (>=1.34.161,<2.0.0)
24
+ Requires-Dist: google-generativeai (>=0.8.2,<0.9.0)
24
25
  Requires-Dist: groq (>=0.9.0,<0.10.0)
25
26
  Requires-Dist: jinja2 (>=3.1.2,<4.0.0)
26
27
  Requires-Dist: json-repair (>=0.28.4,<0.29.0)
@@ -1,15 +1,16 @@
1
- edsl/Base.py,sha256=8T9p-MMUACtgEi6MQY0XvSI_wRToQlMob42E31FCgdg,9124
1
+ edsl/Base.py,sha256=wdFpHWlQlGNL4XfOmYA0AK9YupMDxK3G7mDHCQp60o4,9295
2
2
  edsl/BaseDiff.py,sha256=RoVEh52UJs22yMa7k7jv8se01G62jJNWnBzaZngo-Ug,8260
3
3
  edsl/TemplateLoader.py,sha256=sDBlSMt7EfOduM7w3h6v03gvh_Rzn9hVrlS-iLSQdZA,849
4
4
  edsl/__init__.py,sha256=UZcx9RHSi3Dslh2lWvCOeppdMW9Xzw_YLs-kFaNW1MU,1770
5
- edsl/__version__.py,sha256=ZNenyV-pawXAWnSfwnFv6zGQe_a7xJ6k-kujFJCD97E,28
5
+ edsl/__version__.py,sha256=XhBgcCdTjSpYn65HiKUqna67rnO8Ic__tIbjoMBXW6g,28
6
6
  edsl/agents/Agent.py,sha256=ww6DK177eHQUlYkzgnt1b-MBDKXCdhVx3HezAZZ7TKk,28473
7
7
  edsl/agents/AgentList.py,sha256=qo8VK3Ov0YOSbsBcHmlwLZBH81CcDfy5IEcx9AVH78M,10963
8
- edsl/agents/Invigilator.py,sha256=Of6R2zWoEzx-_NxQG1G7qNbNt4leb544kRBidSjeIJE,8126
8
+ edsl/agents/Invigilator.py,sha256=6xd4sJ6Jzxld8LZDWZuSCZLL_MfaSux4LJCAm_RLEOM,9077
9
9
  edsl/agents/InvigilatorBase.py,sha256=qIdAiriXAbnJH_SN9w2UAXHcDgQvk8Ar3QerKFjtPwM,10341
10
- edsl/agents/PromptConstructor.py,sha256=VOxZsILgC60zOxK4kEauO6XKCz3tyM0ddxND5o1QDN8,18533
10
+ edsl/agents/PromptConstructor.py,sha256=BmScHm5y67vnPKMgo-Diq4p_nyVf_G7MB9IHFY7rml8,14599
11
11
  edsl/agents/__init__.py,sha256=B1dWfV4QWOo8cc2KeuetdFGeNhZ8XHc0Q8YhQW9k7BE,136
12
12
  edsl/agents/descriptors.py,sha256=m8ND3-2-JbgNX1HGakBNLIeemwsgYa1mQxYO9GW33hw,2934
13
+ edsl/agents/prompt_helpers.py,sha256=rHUxM_F0kCOkJmnhCyK-amFKViAYvpRRLD8LHFLGqQw,5023
13
14
  edsl/auto/AutoStudy.py,sha256=yNnhfJPO6oxbgVaYbRftJa8DluKhajfgLCh9o9E3YmU,3843
14
15
  edsl/auto/StageBase.py,sha256=6Ve0cMmc-wdK7tgk7_cOopnvvggEOSkNWfLLWXny7QU,7933
15
16
  edsl/auto/StageGenerateSurvey.py,sha256=_lC1-hhFjqd6md1-RE9uEOPtZp7dZHxJn0ERpszSfow,7394
@@ -45,7 +46,7 @@ edsl/conversation/mug_negotiation.py,sha256=mjvAqErD4AjN3G2za2c-X-3axOShW-zAJUei
45
46
  edsl/conversation/next_speaker_utilities.py,sha256=bqr5JglCd6bdLc9IZ5zGOAsmN2F4ERiubSMYvZIG7qk,3629
46
47
  edsl/coop/PriceFetcher.py,sha256=7q8r1FqE9ap1CMi6WiE_pZQhYxEqG9_tgPgGxLQYVX8,1894
47
48
  edsl/coop/__init__.py,sha256=4iZCwJSzJVyjBYk8ggGxY2kZjq9dXVT1jhyPDNyew4I,115
48
- edsl/coop/coop.py,sha256=nXb5JHuqfEQTnUEgS0NHv3E5MYpuA9U972FDzdgTm1g,28456
49
+ edsl/coop/coop.py,sha256=_wdT6Z-fFYGtAWLn1e98Vv8hgwhdJM2vH_2G-J2ugiI,28547
49
50
  edsl/coop/utils.py,sha256=UZwljKYW_Yjw7RYcjOg3SW7fn1pyHQfJ1fM48TBNoss,3601
50
51
  edsl/data/Cache.py,sha256=jDt0LoZjLpGnM8-CraQEcsQaVg--U3BiBR1zHj0nDn8,16536
51
52
  edsl/data/CacheEntry.py,sha256=_5UiFaJQu_U-Z1_lEPt-h6Gaidp2Eunk02wOd3Ni3MQ,7252
@@ -53,7 +54,7 @@ edsl/data/CacheHandler.py,sha256=DxbfeT2nZGRu8yQkbWr2tyEnhNiClevMsd5KZMCq2f0,479
53
54
  edsl/data/SQLiteDict.py,sha256=V5Nfnxctgh4Iblqcw1KmbnkjtfmWrrombROSQ3mvg6A,8979
54
55
  edsl/data/__init__.py,sha256=KBNGGEuGHq--D-TlpAQmvv_If906dJc1Gsy028zOx78,170
55
56
  edsl/data/orm.py,sha256=Jz6rvw5SrlxwysTL0QI9r68EflKxeEBmf6j6himHDS8,238
56
- edsl/data_transfer_models.py,sha256=ibey234Y8Y34TCoadh7MVlx_RHLmAYvhO5LsTReRl4E,1952
57
+ edsl/data_transfer_models.py,sha256=9LsvZNMvyEEkF-DIcEUA9iomFbxG7E6nRUqsbHoB03k,1951
57
58
  edsl/enums.py,sha256=Z6nhaP8p3z0UJSfsCGb6VQUtGUKw3AK6yC0UDwOi05c,5247
58
59
  edsl/exceptions/__init__.py,sha256=HVg-U-rJ0fRoG9Rws6gnK5S9B68SkPWDPsoD6KpMZ-A,1370
59
60
  edsl/exceptions/agents.py,sha256=3SORFwFbMGrF6-vAL2GrKEVdPcXo7md_k2oYufnVXHA,673
@@ -67,19 +68,19 @@ edsl/exceptions/prompts.py,sha256=vD_reI-RVKWYHYozenEmhmB7Rb1sIiXghgNUtbVGBUo,24
67
68
  edsl/exceptions/questions.py,sha256=ItTXeJEN2TDBL0LLWy37RFX3QG5iUoZa9HzUOs5Ney4,2509
68
69
  edsl/exceptions/results.py,sha256=EkjowYF_7tvDQU0SlyHRiETq-MzZcxALMn0CyaSk2M0,386
69
70
  edsl/exceptions/surveys.py,sha256=lADtr-tvPmUYSfRy3TdkTV5SzZfShlMgCzm-ZGYRlGk,557
70
- edsl/inference_services/AnthropicService.py,sha256=OV6miOC8mzPmalNouTmzk7eqqzUUHteLf5qZ-yWRBXA,2808
71
- edsl/inference_services/AwsBedrock.py,sha256=Tf_g4vNDJXDWpYOmUxGrMRfoqN5bUJRf2NZCBucmb4U,3813
72
- edsl/inference_services/AzureAI.py,sha256=1o257vsZLDTvJ5VnL65gE2qpFg4lzP835E3SySFTGcA,8776
71
+ edsl/inference_services/AnthropicService.py,sha256=6kE8miYIsCZ6B-da4LMHE3tUkyNAsMZcNF8JWKLRKkg,2917
72
+ edsl/inference_services/AwsBedrock.py,sha256=tVsKrw7LHoqc-zDaLew0ufwEMYP_OzkCzsc4zZuXdEk,3926
73
+ edsl/inference_services/AzureAI.py,sha256=Xd3r4Y5OQReW-hG67ymK3LSDLiHj5hMFuvGEz5DI3lY,8889
73
74
  edsl/inference_services/DeepInfraService.py,sha256=fWlH5sCNxf8eHPHxPPxJMEVWpCM9sDenkC8IZYqtXfA,515
74
- edsl/inference_services/GoogleService.py,sha256=2OKQmV2SB5pWgK3YBBuAyRrOInPArMirmfM9ihnUNq8,2903
75
+ edsl/inference_services/GoogleService.py,sha256=CeyQ2Db_cCFOIVvetSwsFLqenJFrg4EGoRYwIe7-7-U,5422
75
76
  edsl/inference_services/GroqService.py,sha256=eDMq8d7YAlJ2689ywaoaPGvMgFfOiX1KYlF_vr97N6I,510
76
77
  edsl/inference_services/InferenceServiceABC.py,sha256=rXqorwbKqzlwui2cxum8_TRrBcfOkgB9s0xULHYGQ1Y,3709
77
78
  edsl/inference_services/InferenceServicesCollection.py,sha256=EDyxnoSjGXhWob_ost7U8WUYjn1jgL_noB0-VlXBnOo,2810
78
- edsl/inference_services/MistralAIService.py,sha256=MIdvroQcfMJLx5wOXItLZpie-MXid4pvIYV9y4xLOWY,3771
79
+ edsl/inference_services/MistralAIService.py,sha256=7mUsBEZdEWIjfh4qMNemTT2xYMq7k0yuMLGtDTdfp4Y,3878
79
80
  edsl/inference_services/OllamaService.py,sha256=oro9CRl8IUE2Ro-zE69Cr4Zaf6Gdw29XW5CFU-46E0k,498
80
- edsl/inference_services/OpenAIService.py,sha256=Io84AC-_QGRze1PbllaoYI2li00YMtONhfluK8f_po0,7179
81
- edsl/inference_services/TestService.py,sha256=Y9dBFE35Y089I3E4LXqG2RdccD4IP2eFG49EoHQ9b5g,2600
82
- edsl/inference_services/TogetherAIService.py,sha256=DIyYs2OoUi44xynwezT4EscOPL0ySl8_f3og5stOkQw,6291
81
+ edsl/inference_services/OpenAIService.py,sha256=2rGW0iGD_hnM1NHBJQCDI59Ti-9wFQu7gh8hDB95Cr4,7264
82
+ edsl/inference_services/TestService.py,sha256=-jTXkl_qLt1k8gJjRb0SMgTb9EY-XMTP-ZUL9AJcUCA,3009
83
+ edsl/inference_services/TogetherAIService.py,sha256=p_31ccrfN25kZF2xlAlUkb7w1EL4lGjmkSv-5qZ7TtY,6301
83
84
  edsl/inference_services/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
84
85
  edsl/inference_services/models_available_cache.py,sha256=HtGNaYgrxY2oPy-QruKhjj6LUzhGNqBhLHFWMoMi1E4,3312
85
86
  edsl/inference_services/rate_limits_cache.py,sha256=HYslviz7mxF9U4CUTPAkoyBsiXjSju-YCp4HHir6e34,1398
@@ -92,7 +93,7 @@ edsl/jobs/__init__.py,sha256=aKuAyd_GoalGj-k7djOoVwEbFUE2XLPlikXaA1_8yAg,32
92
93
  edsl/jobs/buckets/BucketCollection.py,sha256=11CRisE1WAPcAlI3YJK3DVvu0AqSvv8KskXo4Q1waSk,2286
93
94
  edsl/jobs/buckets/ModelBuckets.py,sha256=hxw_tzc0V42CiB7mh5jIxlgwDVJ-zFZhlLtKrHEg8ho,2419
94
95
  edsl/jobs/buckets/TokenBucket.py,sha256=7fG4omzTcj5xC2iJLO9bfBkdAGs6Y3weXzlA3BgPr0E,9090
95
- edsl/jobs/interviews/Interview.py,sha256=OsIcz6wmVmkoJNnA8PN8tCD1DKq-HwLmSwo5UUkyvbU,23264
96
+ edsl/jobs/interviews/Interview.py,sha256=Vt5-6zNazBnp8EZRTA552hy3MyaFxMPkLGgAaIhikzI,23774
96
97
  edsl/jobs/interviews/InterviewExceptionCollection.py,sha256=Ez8BCZUD3odqoY9h-gzYKKM8yaHynQ-eYw2uMDh7t98,3279
97
98
  edsl/jobs/interviews/InterviewExceptionEntry.py,sha256=BGGjj0sb1wJJ0QmYklt1DyEYKD8mUGygllGfN2WXKbY,4903
98
99
  edsl/jobs/interviews/InterviewStatistic.py,sha256=hY5d2EkIJ96NilPpZAvZZzZoxLXM7ss3xx5MIcKtTPs,1856
@@ -102,10 +103,10 @@ edsl/jobs/interviews/InterviewStatusLog.py,sha256=6u0F8gf5tha39VQL-IK_QPkCsQAYVO
102
103
  edsl/jobs/interviews/InterviewStatusMixin.py,sha256=VV0Pel-crUsLoGpTifeIIkXsLGj0bfuO--UtpRnH-dU,1251
103
104
  edsl/jobs/interviews/ReportErrors.py,sha256=RSzDU2rWwtjfztj7sqaMab0quCiY-X2bG3AEOxhTim8,1745
104
105
  edsl/jobs/interviews/interview_status_enum.py,sha256=KJ-1yLAHdX-p8TiFnM0M3v1tnBwkq4aMCuBX6-ytrI8,229
105
- edsl/jobs/runners/JobsRunnerAsyncio.py,sha256=QBmZvjsQ5XdR3HuI_-D4qzQbO9x5KE2QBaBvGMM49SU,12092
106
- edsl/jobs/runners/JobsRunnerStatus.py,sha256=Rhy3Jfa0VK9QqtwtVzX5sF-9Zyg139OeuM-r4psl2UM,12054
106
+ edsl/jobs/runners/JobsRunnerAsyncio.py,sha256=CxO93PO7UGtr9yzrIWDlBjHdq1uAaKoaevsJsYV_3zA,12856
107
+ edsl/jobs/runners/JobsRunnerStatus.py,sha256=4eCh9sRpswGdKeSMW9pCGCAjJZa-OrWUPI7tsxIy_g4,12112
107
108
  edsl/jobs/runners/JobsRunnerStatusData.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
108
- edsl/jobs/tasks/QuestionTaskCreator.py,sha256=8d-rduM4i2Zpd66_NeMkHvkQLhV7SQjLIks2A_nKRoM,10655
109
+ edsl/jobs/tasks/QuestionTaskCreator.py,sha256=f26rokFVXVdyKR2M8of_jlZqP6TPcTAINk9tEvb35pw,10122
109
110
  edsl/jobs/tasks/TaskCreators.py,sha256=XqAbNU33378Z4PQncokbfJwnKt3KHR9aqa5fKYRDpfg,2694
110
111
  edsl/jobs/tasks/TaskHistory.py,sha256=xRSo22ipyUSJ15w_k2Jc3dZ04VLwft8zfvm3smAIYrA,14227
111
112
  edsl/jobs/tasks/TaskStatusLog.py,sha256=bqH36a32F12fjX-M-4lNOhHaK2-WLFzKE-r0PxZPRjI,546
@@ -113,7 +114,7 @@ edsl/jobs/tasks/task_management.py,sha256=KMToZuXzMlnHRHUF_VHL0-lHMTGhklf2GHVuwE
113
114
  edsl/jobs/tasks/task_status_enum.py,sha256=DOyrz61YlIS8R1W7izJNphcLrJ7I_ReUlfdRmk23h0Q,5333
114
115
  edsl/jobs/tokens/InterviewTokenUsage.py,sha256=u_6-IHpGFwZ6qMEXr24-jyLVUSSp4dSs_4iAZsBv7O4,1100
115
116
  edsl/jobs/tokens/TokenUsage.py,sha256=odj2-wDNEbHl9noyFAQ0DSKV0D9cv3aDOpmXufKZ8O4,1323
116
- edsl/language_models/LanguageModel.py,sha256=r80s-9P7icYDz7yABCdfl78vTv-SDF1qlWCJHXb9RiU,25102
117
+ edsl/language_models/LanguageModel.py,sha256=_f3Gv-1n4ttKWs7aSJG13xRklzxL-wOAn2Gl1jrWh5M,25193
117
118
  edsl/language_models/ModelList.py,sha256=GhjRV7y1jRvP_Yjgwv6fxksTVb8sFPBiiRRfdqW-hgg,2852
118
119
  edsl/language_models/RegisterLanguageModelsMeta.py,sha256=eMtBSAnlRnC4c-0_o2QkSNyzv-uAce4BEGMXq2PLj2E,7523
119
120
  edsl/language_models/__init__.py,sha256=bvY7Gy6VkX1gSbNkRbGPS-M1kUnb0EohL0FSagaEaTs,109
@@ -122,7 +123,7 @@ edsl/language_models/fake_openai_service.py,sha256=2AAsAinELbMZRqiepwBkWhWcLuMe5
122
123
  edsl/language_models/registry.py,sha256=hfOlKbTkXrXGpZHQQPKE9uyyUCgOxoUyyIaKL2kf53U,4369
123
124
  edsl/language_models/repair.py,sha256=d0i2S3kJfX7JtuCYhlIyT0QP8hcZkRPLanC09lOW_xo,5353
124
125
  edsl/language_models/unused/ReplicateBase.py,sha256=J1oqf7mEyyKhRwNUomnptVqAsVFYCbS3iTW0EXpKtXo,3331
125
- edsl/language_models/utilities.py,sha256=iPnzYfN-Qxc-iYmwf-JPA0zr6ZGnRDHmudI_y4OSRdk,2187
126
+ edsl/language_models/utilities.py,sha256=ZEwldu1n4M0YRxcQ1s5q6SOkgc7ld4SLuFMq6hjiHIk,2256
126
127
  edsl/notebooks/Notebook.py,sha256=xi9xkxmkQ6-DwhqbjjMLpYKB0VJV20AtwEonJ6mnqjo,7739
127
128
  edsl/notebooks/__init__.py,sha256=VNUA3nNq04slWNbYaNrzOhQJu3AZANpvBniyCJSzJ7U,45
128
129
  edsl/prompts/Prompt.py,sha256=KsIz0tZnIqZlnbzNWO57C3MwJ0OCcUrZPmu7DBApc4s,11887
@@ -142,21 +143,21 @@ edsl/prompts/library/question_rank.py,sha256=WDgXyph0EKWJrSgsW2eqcx3xdU-WA1LEvB2
142
143
  edsl/prompts/prompt_config.py,sha256=O3Y5EvBsCeKs9m9IjXiRXOcHWlWvQV0yqsNb2oSR1ow,974
143
144
  edsl/prompts/registry.py,sha256=XOsqGsvNOmIG83jqoszqI72yNZkkszKR4FrEhwSzj_Q,8093
144
145
  edsl/questions/AnswerValidatorMixin.py,sha256=t_ABep50KP02GSc48Y8VAEjp35drVOngfrWXU5aVhgk,11505
145
- edsl/questions/QuestionBase.py,sha256=5l6Mze61IidmKzXGN5TD-O-fQ5gcOVBUiZNGWigEiX0,20877
146
- edsl/questions/QuestionBaseGenMixin.py,sha256=v5oquCGPDKklLTlMStrnqeTU5PaFFl98tFkZJCQmLEo,5006
146
+ edsl/questions/QuestionBase.py,sha256=NY1M1QT3v2ToZJMbzsER4zejOPmczPzxEA_LKmdbsPk,21153
147
+ edsl/questions/QuestionBaseGenMixin.py,sha256=CPxjWZjrxuSO8YWelz6dbp7fm788gN7-T8z7jXStboQ,6017
147
148
  edsl/questions/QuestionBasePromptsMixin.py,sha256=Km1P6PpkVJ9O3dS8pJZHNJ6aQABhYGLwdef4Z2vSrqk,9516
148
149
  edsl/questions/QuestionBudget.py,sha256=TJgPsyqafJdJw5if0zVxh7zHloourINUqUWfWIlRq9Y,8131
149
- edsl/questions/QuestionCheckBox.py,sha256=TJjmrjbRYmRX4ZNoGpkgLdasWcWavl9uvJDV6AZ5fz0,12835
150
+ edsl/questions/QuestionCheckBox.py,sha256=wC_doEdNZi4y8Uz-tXZyQ2GYS5wQKOWhbVUnyVLoACU,12840
150
151
  edsl/questions/QuestionExtract.py,sha256=PlXwMeZgPAFBXIHSXpFMYTToag-HwA9C7u6-Z3bQMek,6103
151
152
  edsl/questions/QuestionFreeText.py,sha256=uXJxrrAGCq0-J6WpO6TBNFBNOC2ztoEVa-2UMXuwlak,3384
152
153
  edsl/questions/QuestionFunctional.py,sha256=yZQFLQAxfNsAIETffFoBr-Ltb2oFPeywu-nhm9qjYRc,5133
153
154
  edsl/questions/QuestionList.py,sha256=vs2AE8OnbwVsly-sorb9dfIibdF1BpOaCRYyvwXYSzY,7209
154
- edsl/questions/QuestionMultipleChoice.py,sha256=oLEQqLpSho1c3AgQacbUXvMEddUKZEM5pMULH54eXP8,10074
155
+ edsl/questions/QuestionMultipleChoice.py,sha256=SrvT8vS9KOCBogcABOFBhO1gb5Lr0vvmOfoxUkSw-h0,10294
155
156
  edsl/questions/QuestionNumerical.py,sha256=_jMZ28DZHYAv_g3Y3vCnmzerMs995on0Ng6j4pDcfHo,4959
156
157
  edsl/questions/QuestionRank.py,sha256=kYHTYXU88X2Uv-zeCiI9w5aEFYTxvg2p7DoGaaER4ik,11596
157
158
  edsl/questions/Quick.py,sha256=h6h4fEvIkLIFJX2JiqfOUEXzku9azWxEpI5o2A4RmVs,1731
158
159
  edsl/questions/RegisterQuestionsMeta.py,sha256=2h_9iZt3cjr_7JRmveTqbmEBBCvjtefMDfhM7Pgd_zg,2598
159
- edsl/questions/ResponseValidatorABC.py,sha256=TN0AMbPo2mc4_XP0r6BY-5YBZ0ZEyvInHFgMp4citbY,6033
160
+ edsl/questions/ResponseValidatorABC.py,sha256=94l_-d380quOwYZyBUl7Bdunxapc9Bi51_Y-TFDl7ZU,6097
160
161
  edsl/questions/SimpleAskMixin.py,sha256=YRLiHA6TPMKyLWvdAi7Mfnxcqtw7Kem6tH28YNb8n4U,2227
161
162
  edsl/questions/__init__.py,sha256=PYChrB0dHhHAKsL3QUqYa3_ZBgxHmR9bs67pUE9h0Eg,1161
162
163
  edsl/questions/compose_questions.py,sha256=ZcLkwNaofk-o0-skGXEDGZAj6DumOhVhyIUjqEnKrbg,3380
@@ -166,7 +167,7 @@ edsl/questions/derived/QuestionLinearScale.py,sha256=tj_RszK9WumaKRVMS1Fy63-Q6ip
166
167
  edsl/questions/derived/QuestionTopK.py,sha256=HT8NlbT8YBTmVNVPVIP1EyqGsiN3bu4SbFp29CVT0a4,3212
167
168
  edsl/questions/derived/QuestionYesNo.py,sha256=KWJyaXSNPNxELtK0nWvIqNtpAF05MMAC0ILUjxXkVwo,2735
168
169
  edsl/questions/derived/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
169
- edsl/questions/descriptors.py,sha256=48Hin8AEZVRltIV37TjGtKI0xyoD0C0pjK51UVkJnxA,16365
170
+ edsl/questions/descriptors.py,sha256=10zWqaYeRjlc5jTCHFoa0SLZ-myEfZiO42HFoS5_KbE,16407
170
171
  edsl/questions/prompt_templates/question_budget.jinja,sha256=-ekZYCa_KRc-xLcpf3j-YmXV0WSyIK_laOp2x3li-tA,737
171
172
  edsl/questions/prompt_templates/question_checkbox.jinja,sha256=V-Dn2VJhfXyIILWIhMviTfQ5WuXh1YZerwicaA6Okzc,1136
172
173
  edsl/questions/prompt_templates/question_extract.jinja,sha256=27b8iMJaA2h5UOrHPMiBCapMnJou4vSkZzkZndK2s1U,343
@@ -213,7 +214,7 @@ edsl/questions/templates/top_k/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5
213
214
  edsl/questions/templates/top_k/answering_instructions.jinja,sha256=2V38SJZ0Y1E70mHm0HJUzGKregiSlEqVYIcqbncxh5c,266
214
215
  edsl/questions/templates/top_k/question_presentation.jinja,sha256=2u8XIkFPWzOuhbeoIvYBm6zUWnTHF66cGJXIznxVobw,807
215
216
  edsl/questions/templates/yes_no/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
216
- edsl/questions/templates/yes_no/answering_instructions.jinja,sha256=aJVZ_SDdN4SkcHr4KtPU9YwCKZLL1_XtUVqEjiRyn0o,171
217
+ edsl/questions/templates/yes_no/answering_instructions.jinja,sha256=UAcssfcYeW8zytmPOVJOVQEdwdvlRspE8WnatYvreJQ,172
217
218
  edsl/questions/templates/yes_no/question_presentation.jinja,sha256=hoEVj4GQD3EYnR2AStXkMFOJeqISNoEVzBd8-cx2yWg,273
218
219
  edsl/results/Dataset.py,sha256=XeCWNcni1rde9iVzmC1WTIne2cip4-f2gQL5iaJfXNw,9202
219
220
  edsl/results/DatasetExportMixin.py,sha256=-YR-UeuIW_8u0a8HnQ9R6V41DxCq22_AlsD48fXv0sw,25890
@@ -228,11 +229,10 @@ edsl/results/ResultsToolsMixin.py,sha256=mseEFxJCf9sjXdIxpjITt_UZBwdXxw2o2VLg5jM
228
229
  edsl/results/Selector.py,sha256=4AsFD71FKTFY1a0_AImsYWcYKx-RXPG6RgwsAvuNW3k,4403
229
230
  edsl/results/__init__.py,sha256=2YcyiVtXi-3vIV0ZzOy1PqBLm2gaziufJVi4fdNrAt8,80
230
231
  edsl/results/tree_explore.py,sha256=hQjiO4E71rIOPDgEHgK8T8ukxqoNdgX_tvyiDlG4_9U,4624
231
- edsl/scenarios/FileStore.py,sha256=87WVSU-MFRj2iPAH9-ffvYiD3ycSqxhumhCGcY7IJes,10391
232
- edsl/scenarios/Scenario.py,sha256=UdfmjJpm2cTLNza7EhYZtIhEtMO20ZzUD5mQOv_X0lI,17543
232
+ edsl/scenarios/FileStore.py,sha256=mk8jVl2vvP31ufWPruS5ULT4TmbmMWd7NgQbtRIrJE0,13934
233
+ edsl/scenarios/Scenario.py,sha256=ZG1x4_MmWP9j0gakLwsxOZ7ESMy3ifwBMhgQlHvsYo8,16809
233
234
  edsl/scenarios/ScenarioHtmlMixin.py,sha256=EmugmbPJYW5eZS30rM6pDMDQD9yrrvHjmgZWB1qBfq4,1882
234
- edsl/scenarios/ScenarioImageMixin.py,sha256=EpUoFa5gFrB8NlLB9m8dX2uEQfGd9KVFXT9ynyVx6XA,3468
235
- edsl/scenarios/ScenarioList.py,sha256=2sTTV4i0XTijItuODNhIBbC2mVwpREY2LMct73UALOE,40506
235
+ edsl/scenarios/ScenarioList.py,sha256=v5zmM3AOxbVFN9kez6h8GVbFFAxDlykycXqREDc2h8c,40622
236
236
  edsl/scenarios/ScenarioListExportMixin.py,sha256=wfffY9xy_1QyIM-1xnisr64izSLjmyuotUYY5iDLodc,1681
237
237
  edsl/scenarios/ScenarioListPdfMixin.py,sha256=z_H2sZn5SCSq6nRLSU5jefaOlh4sqJLyOY_Ld0XCR18,8332
238
238
  edsl/scenarios/__init__.py,sha256=KRwZCLf2R0qyJvv1NGbd8M51Bt6Ia6Iylg-Xq_2Fa6M,98
@@ -242,12 +242,12 @@ edsl/study/ProofOfWork.py,sha256=FaqYtLgeiTEQXWKukPgPUTWMcIN5t1FR7h7Re8QEtgc,343
242
242
  edsl/study/SnapShot.py,sha256=BY9NP_HRTuOSvCncuE-q5OwMcTEtnBS8bFn_PhF7OcU,2678
243
243
  edsl/study/Study.py,sha256=Ytm15XIWgT716scM3HKFSfdBHxRwX6mfMn3l8dgdY1c,18462
244
244
  edsl/study/__init__.py,sha256=YAvPLTPG3hK_eN9Ar3d1_d-E3laXpSya879A25-JAxU,170
245
- edsl/surveys/DAG.py,sha256=ozQuHo9ZQ8Eet5nDXtp7rFpiSocvvfxIHtyTnztvodg,2380
245
+ edsl/surveys/DAG.py,sha256=dnIbrfJ_lQ3QEKjpyuo1I6b0kcnW2KMMyPir0A6J4XM,4235
246
246
  edsl/surveys/Memory.py,sha256=-ikOtkkQldGB_BkPCW3o7AYwV5B_pIwlREw7aVCSHaQ,1113
247
- edsl/surveys/MemoryPlan.py,sha256=BeLuqS5Q8G2jSluHYFCAxVmj7cNPK-rDQ3mUsuDjikQ,7979
248
- edsl/surveys/Rule.py,sha256=BWWz3IYN10t2TAO1uch2p9DQM13kPozCJr-ywZN0_LU,11399
249
- edsl/surveys/RuleCollection.py,sha256=amnyDclcBoaoSVgZ33Okx_GOli3mw5QCkvDmisrMvxg,14091
250
- edsl/surveys/Survey.py,sha256=yBYvCUllH0fxR2F_SxKH8EACPsfZhUT-UeOA9ZJigoA,65263
247
+ edsl/surveys/MemoryPlan.py,sha256=VESoPM0C_4LUngkskE51rOca_4vbXC2yjfwrBXtHfHA,9029
248
+ edsl/surveys/Rule.py,sha256=RlERae5n5jFTnEp597UF50YGXtywECU1nulYdsSlfh0,12223
249
+ edsl/surveys/RuleCollection.py,sha256=VBx9-OuBBFIJlRYfpbWIjMVFSA5iMwTzdx5yl8giQA8,14871
250
+ edsl/surveys/Survey.py,sha256=EYXkA0CzgpTIlwnVG21NQgBUo-vMRZhXrkP2sbT5hq4,72125
251
251
  edsl/surveys/SurveyCSS.py,sha256=NjJezs2sTlgFprN6IukjGKwNYmNdXnLjzV2w5K4z4RI,8415
252
252
  edsl/surveys/SurveyExportMixin.py,sha256=Kvkd2ku2Kemsn2Nw-Yt8GTnGFcUqfEiKznmisAeO7ck,8339
253
253
  edsl/surveys/SurveyFlowVisualizationMixin.py,sha256=dEG_f-L0ZAyWU5Ta584IX5GZurjVt1tbIISo5z61Jvg,4004
@@ -289,7 +289,7 @@ edsl/utilities/interface.py,sha256=AaKpWiwWBwP2swNXmnFlIf3ZFsjfsR5bjXQAW47tD-8,1
289
289
  edsl/utilities/repair_functions.py,sha256=tftmklAqam6LOQQu_-9U44N-llycffhW8LfO63vBmNw,929
290
290
  edsl/utilities/restricted_python.py,sha256=5-_zUhrNbos7pLhDl9nr8d24auRlquR6w-vKkmNjPiA,2060
291
291
  edsl/utilities/utilities.py,sha256=gqMtWWNEZkWLiRR9vHW-VRNy2bStEPlJ-I2aK9CwFiQ,11367
292
- edsl-0.1.33.dev3.dist-info/LICENSE,sha256=_qszBDs8KHShVYcYzdMz3HNMtH-fKN_p5zjoVAVumFc,1111
293
- edsl-0.1.33.dev3.dist-info/METADATA,sha256=HQjufTZnJ8VDOZPYZOxdtYOTXvBu_AojIE1Q1iB1beI,4424
294
- edsl-0.1.33.dev3.dist-info/WHEEL,sha256=sP946D7jFCHeNz5Iq4fL4Lu-PrWrFsgfLXbbkciIZwg,88
295
- edsl-0.1.33.dev3.dist-info/RECORD,,
292
+ edsl-0.1.34.dev1.dist-info/LICENSE,sha256=_qszBDs8KHShVYcYzdMz3HNMtH-fKN_p5zjoVAVumFc,1111
293
+ edsl-0.1.34.dev1.dist-info/METADATA,sha256=S-k9GEY61HYIUZ60rtZxkPBP0g9V2lb6YfG70P41PFk,4476
294
+ edsl-0.1.34.dev1.dist-info/WHEEL,sha256=sP946D7jFCHeNz5Iq4fL4Lu-PrWrFsgfLXbbkciIZwg,88
295
+ edsl-0.1.34.dev1.dist-info/RECORD,,
@@ -1,100 +0,0 @@
1
- import base64
2
- import os
3
- import requests
4
- import tempfile
5
- import mimetypes
6
- from urllib.parse import urlparse
7
-
8
-
9
- class ScenarioImageMixin:
10
- def add_image(self, image_path: str):
11
- """Add an image to a scenario.
12
-
13
- >>> from edsl.scenarios.Scenario import Scenario
14
- >>> s = Scenario({"food": "wood chips"})
15
- >>> s.add_image(Scenario.example_image())
16
- Scenario({'food': 'wood chips', 'logo': ...})
17
- """
18
- new_scenario = self.from_image(image_path)
19
- return self + new_scenario
20
-
21
- @staticmethod
22
- def example_image():
23
- """Return an example image path."""
24
- import os
25
-
26
- base_path = os.path.dirname(os.path.abspath(__file__))
27
- return os.path.join(base_path, "../../static/logo.png")
28
-
29
- @classmethod
30
- def from_image(cls, image_path: str) -> "Scenario":
31
- """Creates a scenario with a base64 encoding of an image.
32
-
33
- >>> from edsl.scenarios.Scenario import Scenario
34
- >>> s = Scenario.from_image(Scenario.example_image())
35
- >>> s
36
- Scenario({'logo': ...})
37
- """
38
-
39
- if image_path.startswith("http://") or image_path.startswith("https://"):
40
- return cls._from_url_image(image_path)
41
- else:
42
- return cls._from_filepath_image(image_path)
43
-
44
- @classmethod
45
- def _from_url_image(cls, image_url: str) -> "Scenario":
46
- """Handles downloading and encoding an image from a URL."""
47
- response = requests.get(image_url)
48
- if response.status_code == 200:
49
- # Try to extract the file extension from the URL
50
- parsed_url = urlparse(image_url)
51
- file_name = parsed_url.path.split("/")[-1]
52
- file_extension = file_name.split(".")[-1] if "." in file_name else None
53
-
54
- # If the file extension is not found in the URL, use the content type
55
- if not file_extension:
56
- content_type = response.headers.get("Content-Type")
57
- file_extension = mimetypes.guess_extension(content_type)
58
-
59
- # If still no file extension, use a generic binary extension
60
- if not file_extension:
61
- file_extension = ".bin"
62
-
63
- # Create a temporary file with the appropriate extension
64
- with tempfile.NamedTemporaryFile(
65
- delete=False, suffix=file_extension
66
- ) as temp_file:
67
- # Write the image content to the temporary file
68
- temp_file.write(response.content)
69
- temp_file_name = temp_file.name
70
- else:
71
- raise ValueError("Failed to download the image.")
72
-
73
- scenario = cls._from_filepath_image(temp_file_name)
74
- os.remove(temp_file_name)
75
- return scenario
76
-
77
- @classmethod
78
- def _from_filepath_image(cls, image_path: str) -> "Scenario":
79
- """Handles encoding an image from a local file path."""
80
- with open(image_path, "rb") as image_file:
81
- s = cls(
82
- {
83
- "file_path": image_path,
84
- "encoded_image": base64.b64encode(image_file.read()).decode(
85
- "utf-8"
86
- ),
87
- }
88
- )
89
- s._has_image = True
90
- return s
91
-
92
- def __repr__(self):
93
- return f"Scenario({self.data})"
94
-
95
-
96
- if __name__ == "__main__":
97
- import doctest
98
- from edsl.scenarios.Scenario import Scenario
99
-
100
- doctest.testmod(extraglobs={"Scenario": Scenario}, optionflags=doctest.ELLIPSIS)