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.
- edsl/Base.py +15 -11
- edsl/__version__.py +1 -1
- edsl/agents/Invigilator.py +22 -3
- edsl/agents/PromptConstructor.py +79 -183
- edsl/agents/prompt_helpers.py +129 -0
- edsl/coop/coop.py +3 -2
- edsl/data_transfer_models.py +0 -1
- edsl/inference_services/AnthropicService.py +5 -2
- edsl/inference_services/AwsBedrock.py +5 -2
- edsl/inference_services/AzureAI.py +5 -2
- edsl/inference_services/GoogleService.py +108 -33
- edsl/inference_services/MistralAIService.py +5 -2
- edsl/inference_services/OpenAIService.py +3 -2
- edsl/inference_services/TestService.py +11 -2
- edsl/inference_services/TogetherAIService.py +1 -1
- edsl/jobs/interviews/Interview.py +19 -9
- edsl/jobs/runners/JobsRunnerAsyncio.py +37 -16
- edsl/jobs/runners/JobsRunnerStatus.py +4 -3
- edsl/jobs/tasks/QuestionTaskCreator.py +1 -13
- edsl/language_models/LanguageModel.py +12 -9
- edsl/language_models/utilities.py +3 -2
- edsl/questions/QuestionBase.py +11 -2
- edsl/questions/QuestionBaseGenMixin.py +28 -0
- edsl/questions/QuestionCheckBox.py +1 -1
- edsl/questions/QuestionMultipleChoice.py +5 -1
- edsl/questions/ResponseValidatorABC.py +5 -1
- edsl/questions/descriptors.py +12 -11
- edsl/questions/templates/yes_no/answering_instructions.jinja +2 -2
- edsl/scenarios/FileStore.py +159 -71
- edsl/scenarios/Scenario.py +23 -49
- edsl/scenarios/ScenarioList.py +6 -2
- edsl/surveys/DAG.py +62 -0
- edsl/surveys/MemoryPlan.py +26 -0
- edsl/surveys/Rule.py +24 -0
- edsl/surveys/RuleCollection.py +36 -2
- edsl/surveys/Survey.py +182 -10
- {edsl-0.1.33.dev3.dist-info → edsl-0.1.34.dev1.dist-info}/METADATA +2 -1
- {edsl-0.1.33.dev3.dist-info → edsl-0.1.34.dev1.dist-info}/RECORD +40 -40
- edsl/scenarios/ScenarioImageMixin.py +0 -100
- {edsl-0.1.33.dev3.dist-info → edsl-0.1.34.dev1.dist-info}/LICENSE +0 -0
- {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
|
|
edsl/surveys/RuleCollection.py
CHANGED
@@ -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=
|
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=
|
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
|
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
|
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.
|
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.
|
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=
|
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=
|
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=
|
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=
|
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=
|
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=
|
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=
|
71
|
-
edsl/inference_services/AwsBedrock.py,sha256=
|
72
|
-
edsl/inference_services/AzureAI.py,sha256=
|
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=
|
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=
|
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=
|
81
|
-
edsl/inference_services/TestService.py,sha256
|
82
|
-
edsl/inference_services/TogetherAIService.py,sha256=
|
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=
|
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=
|
106
|
-
edsl/jobs/runners/JobsRunnerStatus.py,sha256=
|
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=
|
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=
|
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=
|
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=
|
146
|
-
edsl/questions/QuestionBaseGenMixin.py,sha256=
|
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=
|
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=
|
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=
|
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=
|
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=
|
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=
|
232
|
-
edsl/scenarios/Scenario.py,sha256=
|
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/
|
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=
|
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=
|
248
|
-
edsl/surveys/Rule.py,sha256=
|
249
|
-
edsl/surveys/RuleCollection.py,sha256=
|
250
|
-
edsl/surveys/Survey.py,sha256=
|
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.
|
293
|
-
edsl-0.1.
|
294
|
-
edsl-0.1.
|
295
|
-
edsl-0.1.
|
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)
|
File without changes
|