edsl 0.1.33__py3-none-any.whl → 0.1.33.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 +3 -9
- edsl/__init__.py +3 -8
- edsl/__version__.py +1 -1
- edsl/agents/Agent.py +8 -40
- edsl/agents/AgentList.py +0 -43
- edsl/agents/Invigilator.py +219 -135
- edsl/agents/InvigilatorBase.py +59 -148
- edsl/agents/{PromptConstructor.py → PromptConstructionMixin.py} +89 -138
- edsl/agents/__init__.py +0 -1
- edsl/config.py +56 -47
- edsl/coop/coop.py +7 -50
- edsl/data/Cache.py +1 -35
- edsl/data_transfer_models.py +38 -73
- edsl/enums.py +0 -4
- edsl/exceptions/language_models.py +1 -25
- edsl/exceptions/questions.py +5 -62
- edsl/exceptions/results.py +0 -4
- edsl/inference_services/AnthropicService.py +11 -13
- edsl/inference_services/AwsBedrock.py +17 -19
- edsl/inference_services/AzureAI.py +20 -37
- edsl/inference_services/GoogleService.py +12 -16
- edsl/inference_services/GroqService.py +0 -2
- edsl/inference_services/InferenceServiceABC.py +3 -58
- edsl/inference_services/OpenAIService.py +54 -48
- edsl/inference_services/models_available_cache.py +6 -0
- edsl/inference_services/registry.py +0 -6
- edsl/jobs/Answers.py +12 -10
- edsl/jobs/Jobs.py +21 -36
- edsl/jobs/buckets/BucketCollection.py +15 -24
- edsl/jobs/buckets/TokenBucket.py +14 -93
- edsl/jobs/interviews/Interview.py +78 -366
- edsl/jobs/interviews/InterviewExceptionEntry.py +19 -85
- edsl/jobs/interviews/InterviewTaskBuildingMixin.py +286 -0
- edsl/jobs/interviews/{InterviewExceptionCollection.py → interview_exception_tracking.py} +68 -14
- edsl/jobs/interviews/retry_management.py +37 -0
- edsl/jobs/runners/JobsRunnerAsyncio.py +175 -146
- edsl/jobs/runners/JobsRunnerStatusMixin.py +333 -0
- edsl/jobs/tasks/QuestionTaskCreator.py +23 -30
- edsl/jobs/tasks/TaskHistory.py +213 -148
- edsl/language_models/LanguageModel.py +156 -261
- edsl/language_models/ModelList.py +2 -2
- edsl/language_models/RegisterLanguageModelsMeta.py +29 -14
- edsl/language_models/registry.py +6 -23
- edsl/language_models/repair.py +19 -0
- edsl/prompts/Prompt.py +2 -52
- edsl/questions/AnswerValidatorMixin.py +26 -23
- edsl/questions/QuestionBase.py +249 -329
- edsl/questions/QuestionBudget.py +41 -99
- edsl/questions/QuestionCheckBox.py +35 -227
- edsl/questions/QuestionExtract.py +27 -98
- edsl/questions/QuestionFreeText.py +29 -52
- edsl/questions/QuestionFunctional.py +0 -7
- edsl/questions/QuestionList.py +22 -141
- edsl/questions/QuestionMultipleChoice.py +65 -159
- edsl/questions/QuestionNumerical.py +46 -88
- edsl/questions/QuestionRank.py +24 -182
- edsl/questions/RegisterQuestionsMeta.py +12 -31
- edsl/questions/__init__.py +4 -3
- edsl/questions/derived/QuestionLikertFive.py +5 -10
- edsl/questions/derived/QuestionLinearScale.py +2 -15
- edsl/questions/derived/QuestionTopK.py +1 -10
- edsl/questions/derived/QuestionYesNo.py +3 -24
- edsl/questions/descriptors.py +7 -43
- edsl/questions/question_registry.py +2 -6
- edsl/results/Dataset.py +0 -20
- edsl/results/DatasetExportMixin.py +48 -46
- edsl/results/Result.py +5 -32
- edsl/results/Results.py +46 -135
- edsl/results/ResultsDBMixin.py +3 -3
- edsl/scenarios/FileStore.py +10 -71
- edsl/scenarios/Scenario.py +25 -96
- edsl/scenarios/ScenarioImageMixin.py +2 -2
- edsl/scenarios/ScenarioList.py +39 -361
- edsl/scenarios/ScenarioListExportMixin.py +0 -9
- edsl/scenarios/ScenarioListPdfMixin.py +4 -150
- edsl/study/SnapShot.py +1 -8
- edsl/study/Study.py +0 -32
- edsl/surveys/Rule.py +1 -10
- edsl/surveys/RuleCollection.py +5 -21
- edsl/surveys/Survey.py +310 -636
- edsl/surveys/SurveyExportMixin.py +9 -71
- edsl/surveys/SurveyFlowVisualizationMixin.py +1 -2
- edsl/surveys/SurveyQualtricsImport.py +4 -75
- edsl/utilities/gcp_bucket/simple_example.py +9 -0
- edsl/utilities/utilities.py +1 -9
- {edsl-0.1.33.dist-info → edsl-0.1.33.dev1.dist-info}/METADATA +2 -5
- edsl-0.1.33.dev1.dist-info/RECORD +209 -0
- edsl/TemplateLoader.py +0 -24
- edsl/auto/AutoStudy.py +0 -117
- edsl/auto/StageBase.py +0 -230
- edsl/auto/StageGenerateSurvey.py +0 -178
- edsl/auto/StageLabelQuestions.py +0 -125
- edsl/auto/StagePersona.py +0 -61
- edsl/auto/StagePersonaDimensionValueRanges.py +0 -88
- edsl/auto/StagePersonaDimensionValues.py +0 -74
- edsl/auto/StagePersonaDimensions.py +0 -69
- edsl/auto/StageQuestions.py +0 -73
- edsl/auto/SurveyCreatorPipeline.py +0 -21
- edsl/auto/utilities.py +0 -224
- edsl/coop/PriceFetcher.py +0 -58
- edsl/inference_services/MistralAIService.py +0 -120
- edsl/inference_services/TestService.py +0 -80
- edsl/inference_services/TogetherAIService.py +0 -170
- edsl/jobs/FailedQuestion.py +0 -78
- edsl/jobs/runners/JobsRunnerStatus.py +0 -331
- edsl/language_models/fake_openai_call.py +0 -15
- edsl/language_models/fake_openai_service.py +0 -61
- edsl/language_models/utilities.py +0 -61
- edsl/questions/QuestionBaseGenMixin.py +0 -133
- edsl/questions/QuestionBasePromptsMixin.py +0 -266
- edsl/questions/Quick.py +0 -41
- edsl/questions/ResponseValidatorABC.py +0 -170
- edsl/questions/decorators.py +0 -21
- edsl/questions/prompt_templates/question_budget.jinja +0 -13
- edsl/questions/prompt_templates/question_checkbox.jinja +0 -32
- edsl/questions/prompt_templates/question_extract.jinja +0 -11
- edsl/questions/prompt_templates/question_free_text.jinja +0 -3
- edsl/questions/prompt_templates/question_linear_scale.jinja +0 -11
- edsl/questions/prompt_templates/question_list.jinja +0 -17
- edsl/questions/prompt_templates/question_multiple_choice.jinja +0 -33
- edsl/questions/prompt_templates/question_numerical.jinja +0 -37
- edsl/questions/templates/__init__.py +0 -0
- edsl/questions/templates/budget/__init__.py +0 -0
- edsl/questions/templates/budget/answering_instructions.jinja +0 -7
- edsl/questions/templates/budget/question_presentation.jinja +0 -7
- edsl/questions/templates/checkbox/__init__.py +0 -0
- edsl/questions/templates/checkbox/answering_instructions.jinja +0 -10
- edsl/questions/templates/checkbox/question_presentation.jinja +0 -22
- edsl/questions/templates/extract/__init__.py +0 -0
- edsl/questions/templates/extract/answering_instructions.jinja +0 -7
- edsl/questions/templates/extract/question_presentation.jinja +0 -1
- edsl/questions/templates/free_text/__init__.py +0 -0
- edsl/questions/templates/free_text/answering_instructions.jinja +0 -0
- edsl/questions/templates/free_text/question_presentation.jinja +0 -1
- edsl/questions/templates/likert_five/__init__.py +0 -0
- edsl/questions/templates/likert_five/answering_instructions.jinja +0 -10
- edsl/questions/templates/likert_five/question_presentation.jinja +0 -12
- edsl/questions/templates/linear_scale/__init__.py +0 -0
- edsl/questions/templates/linear_scale/answering_instructions.jinja +0 -5
- edsl/questions/templates/linear_scale/question_presentation.jinja +0 -5
- edsl/questions/templates/list/__init__.py +0 -0
- edsl/questions/templates/list/answering_instructions.jinja +0 -4
- edsl/questions/templates/list/question_presentation.jinja +0 -5
- edsl/questions/templates/multiple_choice/__init__.py +0 -0
- edsl/questions/templates/multiple_choice/answering_instructions.jinja +0 -9
- edsl/questions/templates/multiple_choice/html.jinja +0 -0
- edsl/questions/templates/multiple_choice/question_presentation.jinja +0 -12
- edsl/questions/templates/numerical/__init__.py +0 -0
- edsl/questions/templates/numerical/answering_instructions.jinja +0 -8
- edsl/questions/templates/numerical/question_presentation.jinja +0 -7
- edsl/questions/templates/rank/__init__.py +0 -0
- edsl/questions/templates/rank/answering_instructions.jinja +0 -11
- edsl/questions/templates/rank/question_presentation.jinja +0 -15
- edsl/questions/templates/top_k/__init__.py +0 -0
- edsl/questions/templates/top_k/answering_instructions.jinja +0 -8
- edsl/questions/templates/top_k/question_presentation.jinja +0 -22
- edsl/questions/templates/yes_no/__init__.py +0 -0
- edsl/questions/templates/yes_no/answering_instructions.jinja +0 -6
- edsl/questions/templates/yes_no/question_presentation.jinja +0 -12
- edsl/results/DatasetTree.py +0 -145
- edsl/results/Selector.py +0 -118
- edsl/results/tree_explore.py +0 -115
- edsl/surveys/instructions/ChangeInstruction.py +0 -47
- edsl/surveys/instructions/Instruction.py +0 -34
- edsl/surveys/instructions/InstructionCollection.py +0 -77
- edsl/surveys/instructions/__init__.py +0 -0
- edsl/templates/error_reporting/base.html +0 -24
- edsl/templates/error_reporting/exceptions_by_model.html +0 -35
- edsl/templates/error_reporting/exceptions_by_question_name.html +0 -17
- edsl/templates/error_reporting/exceptions_by_type.html +0 -17
- edsl/templates/error_reporting/interview_details.html +0 -116
- edsl/templates/error_reporting/interviews.html +0 -10
- edsl/templates/error_reporting/overview.html +0 -5
- edsl/templates/error_reporting/performance_plot.html +0 -2
- edsl/templates/error_reporting/report.css +0 -74
- edsl/templates/error_reporting/report.html +0 -118
- edsl/templates/error_reporting/report.js +0 -25
- edsl-0.1.33.dist-info/RECORD +0 -295
- {edsl-0.1.33.dist-info → edsl-0.1.33.dev1.dist-info}/LICENSE +0 -0
- {edsl-0.1.33.dist-info → edsl-0.1.33.dev1.dist-info}/WHEEL +0 -0
@@ -1,74 +0,0 @@
|
|
1
|
-
from textwrap import dedent
|
2
|
-
from dataclasses import dataclass
|
3
|
-
|
4
|
-
from typing import List, Dict
|
5
|
-
|
6
|
-
from edsl.auto.StageBase import StageBase
|
7
|
-
from edsl.auto.StageBase import FlowDataBase
|
8
|
-
|
9
|
-
from edsl.auto.StagePersonaDimensions import StagePersonaDimensions
|
10
|
-
from edsl import Model
|
11
|
-
from edsl.questions import QuestionList, QuestionExtract
|
12
|
-
from edsl.scenarios import Scenario
|
13
|
-
|
14
|
-
from edsl.auto.utilities import gen_pipeline
|
15
|
-
|
16
|
-
|
17
|
-
class StagePersonaDimensionValues(StageBase):
|
18
|
-
input = StagePersonaDimensions.output
|
19
|
-
|
20
|
-
@dataclass
|
21
|
-
class Output(FlowDataBase):
|
22
|
-
attribute_results: List[str]
|
23
|
-
dimension_values: Dict[str, str]
|
24
|
-
persona: str
|
25
|
-
|
26
|
-
output = Output
|
27
|
-
|
28
|
-
def handle_data(self, data):
|
29
|
-
attribute_results = data.attribute_results
|
30
|
-
persona = data.persona
|
31
|
-
m = Model()
|
32
|
-
q = QuestionExtract(
|
33
|
-
question_text=dedent(
|
34
|
-
"""\
|
35
|
-
This is a persona: "{{ persona }}"
|
36
|
-
They vary on the following dimensions: "{{ attribute_results }}"
|
37
|
-
For each dimenion, what are some values that this persona might have for that dimension?
|
38
|
-
Please keep answers very short, ideally one word.
|
39
|
-
"""
|
40
|
-
),
|
41
|
-
answer_template={k: None for k in attribute_results},
|
42
|
-
question_name="dimension_values",
|
43
|
-
)
|
44
|
-
results = (
|
45
|
-
q.by(Scenario({"attribute_results": attribute_results, "persona": persona}))
|
46
|
-
.by(m)
|
47
|
-
.run()
|
48
|
-
)
|
49
|
-
results.select("attribute_results", "dimension_values").print()
|
50
|
-
return self.output(
|
51
|
-
dimension_values=results.select("dimension_values").first(),
|
52
|
-
attribute_results=attribute_results,
|
53
|
-
persona=persona,
|
54
|
-
)
|
55
|
-
|
56
|
-
|
57
|
-
if __name__ == "__main__":
|
58
|
-
from edsl.auto.StageQuestions import StageQuestions
|
59
|
-
from edsl.auto.StagePersona import StagePersona
|
60
|
-
from edsl.auto.StagePersonaDimensions import StagePersonaDimensions
|
61
|
-
|
62
|
-
pipeline = gen_pipeline(
|
63
|
-
[
|
64
|
-
StageQuestions,
|
65
|
-
StagePersona,
|
66
|
-
StagePersonaDimensions,
|
67
|
-
StagePersonaDimensionValues,
|
68
|
-
]
|
69
|
-
)
|
70
|
-
pipeline.process(
|
71
|
-
pipeline.input(
|
72
|
-
overall_question="What are some factors that could determine whether someone likes ice cream?"
|
73
|
-
)
|
74
|
-
)
|
@@ -1,69 +0,0 @@
|
|
1
|
-
from textwrap import dedent
|
2
|
-
from dataclasses import dataclass
|
3
|
-
|
4
|
-
from typing import List
|
5
|
-
|
6
|
-
from edsl.auto.StageBase import StageBase
|
7
|
-
from edsl.auto.StageBase import FlowDataBase
|
8
|
-
|
9
|
-
from edsl.auto.StagePersona import StagePersona
|
10
|
-
|
11
|
-
from edsl.questions import QuestionList
|
12
|
-
from edsl.scenarios import Scenario
|
13
|
-
from edsl import Model
|
14
|
-
|
15
|
-
from edsl.auto.utilities import gen_pipeline
|
16
|
-
|
17
|
-
|
18
|
-
class StagePersonaDimensions(StageBase):
|
19
|
-
input = StagePersona.output
|
20
|
-
|
21
|
-
@dataclass
|
22
|
-
class Output(FlowDataBase):
|
23
|
-
attribute_results: List[str]
|
24
|
-
persona: str
|
25
|
-
|
26
|
-
output = Output
|
27
|
-
|
28
|
-
def handle_data(self, data):
|
29
|
-
q_attributes = QuestionList(
|
30
|
-
question_text=dedent(
|
31
|
-
"""\
|
32
|
-
Here is a persona: "{{ persona }}"
|
33
|
-
It was construced to be someone who could answer these questions: "{{ questions }}"
|
34
|
-
|
35
|
-
We want to identify the general dimensions that make up this persona.
|
36
|
-
E.g., if the person is desribed as 'happy' then a dimenion would be 'mood'
|
37
|
-
"""
|
38
|
-
),
|
39
|
-
question_name="find_attributes",
|
40
|
-
)
|
41
|
-
m = Model()
|
42
|
-
results = (
|
43
|
-
q_attributes.by(
|
44
|
-
Scenario({"persona": data.persona, "questions": data.questions})
|
45
|
-
)
|
46
|
-
.by(m)
|
47
|
-
.run()
|
48
|
-
)
|
49
|
-
(
|
50
|
-
results.select("find_attributes").print(
|
51
|
-
pretty_labels={
|
52
|
-
"answer.find_attributes": f'Persona dimensions for: "{data.persona}"'
|
53
|
-
},
|
54
|
-
split_at_dot=False,
|
55
|
-
)
|
56
|
-
)
|
57
|
-
attribute_results = results.select("find_attributes").first()
|
58
|
-
return self.output(attribute_results=attribute_results, persona=data.persona)
|
59
|
-
|
60
|
-
|
61
|
-
if __name__ == "__main__":
|
62
|
-
from edsl.auto.StageQuestions import StageQuestions
|
63
|
-
|
64
|
-
pipeline = gen_pipeline([StageQuestions, StagePersona, StagePersonaDimensions])
|
65
|
-
pipeline.process(
|
66
|
-
pipeline.input(
|
67
|
-
overall_question="What are some factors that could determine whether someone likes ice cream?"
|
68
|
-
)
|
69
|
-
)
|
edsl/auto/StageQuestions.py
DELETED
@@ -1,73 +0,0 @@
|
|
1
|
-
from dataclasses import dataclass
|
2
|
-
from typing import List
|
3
|
-
from textwrap import dedent
|
4
|
-
|
5
|
-
|
6
|
-
from edsl import Scenario
|
7
|
-
from edsl import Model
|
8
|
-
from edsl.questions.QuestionList import QuestionList
|
9
|
-
|
10
|
-
from edsl.auto.StageBase import StageBase
|
11
|
-
from edsl.auto.StageBase import FlowDataBase
|
12
|
-
|
13
|
-
from edsl.auto.utilities import gen_pipeline
|
14
|
-
|
15
|
-
|
16
|
-
class StageQuestions(StageBase):
|
17
|
-
"This stages takes as input an overall question and returns a list of questions"
|
18
|
-
|
19
|
-
@dataclass
|
20
|
-
class Input(FlowDataBase):
|
21
|
-
overall_question: str
|
22
|
-
population: str
|
23
|
-
|
24
|
-
@dataclass
|
25
|
-
class Output(FlowDataBase):
|
26
|
-
questions: List[str]
|
27
|
-
population: str
|
28
|
-
|
29
|
-
input = Input
|
30
|
-
output = Output
|
31
|
-
|
32
|
-
def handle_data(self, data):
|
33
|
-
m = Model()
|
34
|
-
overall_question = data.overall_question
|
35
|
-
population = data.population
|
36
|
-
s = Scenario({"overall_question": overall_question, "population": population})
|
37
|
-
q = QuestionList(
|
38
|
-
question_text=dedent(
|
39
|
-
"""\
|
40
|
-
Suppose I am interested in the question:
|
41
|
-
"{{ overall_question }}"
|
42
|
-
What would be some survey questions I could ask to {{ population }} that might shed light on this question?
|
43
|
-
"""
|
44
|
-
),
|
45
|
-
question_name="questions",
|
46
|
-
)
|
47
|
-
results = q.by(s).by(m).run()
|
48
|
-
(
|
49
|
-
results.select("questions").print(
|
50
|
-
pretty_labels={
|
51
|
-
"answer.questions": f'Questions for overall question: "{overall_question }"'
|
52
|
-
},
|
53
|
-
split_at_dot=False,
|
54
|
-
)
|
55
|
-
)
|
56
|
-
|
57
|
-
raw_questions = results.select("questions").first()
|
58
|
-
questions = [q.replace("'", "").replace(":", "") for q in raw_questions]
|
59
|
-
return self.Output(questions=questions, population=population)
|
60
|
-
|
61
|
-
|
62
|
-
if __name__ == "__main__":
|
63
|
-
pipeline = gen_pipeline([StageQuestions])
|
64
|
-
|
65
|
-
pipeline.process(
|
66
|
-
pipeline.input(
|
67
|
-
overall_question="What are some factors that could determine whether someone likes ice cream?",
|
68
|
-
population="Consumers",
|
69
|
-
)
|
70
|
-
)
|
71
|
-
StageQuestions.func(
|
72
|
-
overall_question="Why aren't my students studying more?", population="Tech"
|
73
|
-
)
|
@@ -1,21 +0,0 @@
|
|
1
|
-
import random
|
2
|
-
from typing import Dict, List, Any, TypeVar, Generator, Optional
|
3
|
-
|
4
|
-
from textwrap import dedent
|
5
|
-
|
6
|
-
# from edsl.language_models.model_interfaces.LanguageModelOpenAIFour import LanguageModelOpenAIFour
|
7
|
-
from edsl import Model
|
8
|
-
from edsl.agents.AgentList import AgentList
|
9
|
-
from edsl.results.Results import Results
|
10
|
-
from edsl import Agent
|
11
|
-
|
12
|
-
from edsl import Scenario
|
13
|
-
from edsl.surveys.Survey import Survey
|
14
|
-
|
15
|
-
from edsl.questions.QuestionMultipleChoice import QuestionMultipleChoice
|
16
|
-
from edsl.questions.QuestionFreeText import QuestionFreeText
|
17
|
-
from edsl.auto.utilities import gen_pipeline
|
18
|
-
from edsl.conjure.naming_utilities import sanitize_string
|
19
|
-
|
20
|
-
|
21
|
-
m = Model()
|
edsl/auto/utilities.py
DELETED
@@ -1,224 +0,0 @@
|
|
1
|
-
from textwrap import dedent
|
2
|
-
import random
|
3
|
-
from typing import List, TypeVar, Generator, Optional
|
4
|
-
from edsl.auto.StageBase import StageBase
|
5
|
-
from edsl.conjure.naming_utilities import sanitize_string
|
6
|
-
from edsl import Agent, Survey, Model, Cache, AgentList
|
7
|
-
from edsl import QuestionFreeText, Scenario
|
8
|
-
from edsl import QuestionMultipleChoice, Scenario, Agent, ScenarioList
|
9
|
-
|
10
|
-
StageClassType = TypeVar("StageClassType", bound=StageBase)
|
11
|
-
|
12
|
-
|
13
|
-
def gen_pipeline(stages_list: List[StageClassType]) -> StageBase:
|
14
|
-
"""Takes as input a list of Stage classes & returns a pipeline of instantiated stages.
|
15
|
-
A pipeline is a linked list of stages where each stage has a next_stage attribute.
|
16
|
-
|
17
|
-
"""
|
18
|
-
pipeline = stages_list[0]()
|
19
|
-
last_stage = pipeline
|
20
|
-
for stage in stages_list[1:]:
|
21
|
-
while last_stage.next_stage is not None: # find the end of the pipeline
|
22
|
-
last_stage = last_stage.next_stage
|
23
|
-
stage_to_add = stage()
|
24
|
-
last_stage.next_stage = stage_to_add
|
25
|
-
return pipeline
|
26
|
-
|
27
|
-
|
28
|
-
q_eligibility = QuestionMultipleChoice(
|
29
|
-
question_text=dedent(
|
30
|
-
"""\
|
31
|
-
Consider this set of question: '{{ questions }}'.
|
32
|
-
Consider this persona: '{{ persona }}'.
|
33
|
-
Would this persona be able to answer all of these questions?
|
34
|
-
"""
|
35
|
-
),
|
36
|
-
question_options=["No", "Yes"],
|
37
|
-
question_name="eligibility",
|
38
|
-
)
|
39
|
-
|
40
|
-
|
41
|
-
def agent_list_eligibility(
|
42
|
-
agent_list: AgentList,
|
43
|
-
survey: Optional[Survey] = None,
|
44
|
-
model: Optional[Model] = None,
|
45
|
-
cache: Optional[Cache] = None,
|
46
|
-
) -> List[bool]:
|
47
|
-
"""
|
48
|
-
Returns whether each agent in a list is elgible for a survey i.e., can answer every question.
|
49
|
-
|
50
|
-
>>> from edsl.language_models import LanguageModel
|
51
|
-
>>> m = LanguageModel.example(canned_response = "1", test_model = True)
|
52
|
-
>>> agent_list_eligibility(AgentList.example())
|
53
|
-
[True, True]
|
54
|
-
>>> agent_list_eligibility(AgentList.example().add_trait('persona', 2*["Cool dude"]), survey = Survey.example(), model = m)
|
55
|
-
[True, True]
|
56
|
-
"""
|
57
|
-
if survey is None:
|
58
|
-
return [True] * len(agent_list)
|
59
|
-
if "persona" not in agent_list.all_traits:
|
60
|
-
raise ValueError(
|
61
|
-
f"Each agent needs to have a persona attribute; traits are {agent_list.all_traits}"
|
62
|
-
)
|
63
|
-
sl = agent_list.select("persona").to_scenario_list()
|
64
|
-
sl.add_value("questions", [q.question_text for q in survey._questions])
|
65
|
-
results = q_eligibility.by(sl).by(model).run(cache=cache)
|
66
|
-
return [r == "Yes" for r in results.select("eligibility").to_list()]
|
67
|
-
|
68
|
-
|
69
|
-
def agent_eligibility(
|
70
|
-
agent: Agent,
|
71
|
-
survey: Survey,
|
72
|
-
model: Optional[Model] = None,
|
73
|
-
cache: Optional[Cache] = None,
|
74
|
-
) -> bool:
|
75
|
-
"""NB: This could be parallelized.
|
76
|
-
|
77
|
-
>>> from edsl.language_models import LanguageModel
|
78
|
-
>>> m = LanguageModel.example(canned_response = "1", test_model = True)
|
79
|
-
>>> agent_eligibility(agent = Agent.example().add_trait({'persona': "Persona"}), survey = Survey.example(), model = m)
|
80
|
-
True
|
81
|
-
|
82
|
-
"""
|
83
|
-
model = model or Model()
|
84
|
-
|
85
|
-
questions = [q.question_text for q in survey._questions]
|
86
|
-
persona = agent.traits["persona"]
|
87
|
-
return (
|
88
|
-
q_eligibility(model=model, questions=questions, persona=persona, cache=cache)
|
89
|
-
== "Yes"
|
90
|
-
)
|
91
|
-
# results = (
|
92
|
-
# q.by(model)
|
93
|
-
# .by(Scenario({"questions": questions, "persona": persona}))
|
94
|
-
# .run(cache=cache)
|
95
|
-
# )
|
96
|
-
# return results.select("eligibility").first() == "Yes"
|
97
|
-
|
98
|
-
|
99
|
-
def gen_agent_traits(dimension_dict: dict, seed_value: Optional[str] = None):
|
100
|
-
"""
|
101
|
-
>>> dimension_dict = {'attitude':['positive', 'negative']}
|
102
|
-
>>> ag = gen_agent_traits(dimension_dict)
|
103
|
-
>>> a = next(ag)
|
104
|
-
>>> a == {'attitude': 'positive'} or a == {'attitude': 'negative'}
|
105
|
-
True
|
106
|
-
>>> len([next(ag) for _ in range(100)])
|
107
|
-
100
|
108
|
-
"""
|
109
|
-
if seed_value is None:
|
110
|
-
seed_value = "edsl"
|
111
|
-
|
112
|
-
random.seed(seed_value)
|
113
|
-
|
114
|
-
while True:
|
115
|
-
new_agent_traits = {}
|
116
|
-
for key, list_of_values in dimension_dict.items():
|
117
|
-
new_agent_traits[key] = random.choice(list_of_values)
|
118
|
-
yield new_agent_traits
|
119
|
-
|
120
|
-
|
121
|
-
def agent_generator(
|
122
|
-
persona: str,
|
123
|
-
dimension_dict: dict,
|
124
|
-
model: Optional[Model] = None,
|
125
|
-
cache: Optional["Cache"] = None,
|
126
|
-
) -> Generator["Results", None, None]:
|
127
|
-
"""
|
128
|
-
>>> from edsl.language_models import LanguageModel
|
129
|
-
>>> m = LanguageModel.example(canned_response = "This is a cool dude.", test_model = True)
|
130
|
-
>>> ag = agent_generator(persona = "Base person", dimension_dict = {'attitude':['Positive', 'Negative']}, model = m)
|
131
|
-
>>> next(ag).select('new_agent_persona').first()
|
132
|
-
'This is a cool dude.'
|
133
|
-
>>> next(ag).select('new_agent_persona').first()
|
134
|
-
'This is a cool dude.'
|
135
|
-
"""
|
136
|
-
|
137
|
-
if model is None:
|
138
|
-
model = Model()
|
139
|
-
|
140
|
-
q = QuestionFreeText(
|
141
|
-
question_text=dedent(
|
142
|
-
"""\
|
143
|
-
Consider this persona: '{{ persona }}'.
|
144
|
-
Now imagine writing a new persona with these traits:
|
145
|
-
'{{ new_agent_traits }}'
|
146
|
-
Please write this persona as a narrative.
|
147
|
-
"""
|
148
|
-
),
|
149
|
-
question_name="new_agent_persona",
|
150
|
-
)
|
151
|
-
agent_trait_generator = gen_agent_traits(dimension_dict)
|
152
|
-
codebook = {sanitize_string(k): k for k in dimension_dict.keys()}
|
153
|
-
while True:
|
154
|
-
new_agent_traits = next(agent_trait_generator)
|
155
|
-
yield q(
|
156
|
-
persona=persona,
|
157
|
-
new_agent_traits=new_agent_traits,
|
158
|
-
codebook=codebook,
|
159
|
-
just_answer=False,
|
160
|
-
cache=cache,
|
161
|
-
model=model,
|
162
|
-
)
|
163
|
-
|
164
|
-
|
165
|
-
def create_agents(
|
166
|
-
agent_generator: Generator["Results", None, None],
|
167
|
-
survey: Optional[Survey] = None,
|
168
|
-
num_agents=11,
|
169
|
-
) -> AgentList:
|
170
|
-
"""
|
171
|
-
>>> from edsl.language_models import LanguageModel
|
172
|
-
>>> m = LanguageModel.example(canned_response = "This is a cool dude.", test_model = True)
|
173
|
-
>>> ag = agent_generator(persona = "Base person", dimension_dict = {'attitude':['Positive', 'Negative']}, model = m)
|
174
|
-
>>> new_agent_list = create_agents(agent_generator = ag)
|
175
|
-
>>> new_agent_list
|
176
|
-
|
177
|
-
"""
|
178
|
-
agent_list = AgentList([])
|
179
|
-
|
180
|
-
MAX_ITERATIONS_MULTIPLIER = 2
|
181
|
-
iterations = 0
|
182
|
-
|
183
|
-
while len(agent_list) < num_agents:
|
184
|
-
iterations += 1
|
185
|
-
candidate_agent = next(agent_generator)
|
186
|
-
codebook = candidate_agent.select("codebook").to_list()[0]
|
187
|
-
|
188
|
-
koobedoc = {v: k for k, v in codebook.items()}
|
189
|
-
persona = candidate_agent.select("new_agent_persona").to_list()[0]
|
190
|
-
traits = candidate_agent.select("new_agent_traits").to_list()[0]
|
191
|
-
new_traits = {koobedoc[key]: value for key, value in traits.items()} | {
|
192
|
-
"persona": persona
|
193
|
-
}
|
194
|
-
agent = Agent(traits=new_traits, codebook=codebook)
|
195
|
-
if survey is not None:
|
196
|
-
if agent_eligibility(agent, survey):
|
197
|
-
agent_list.append(agent)
|
198
|
-
else:
|
199
|
-
print("Agent not eligible")
|
200
|
-
else:
|
201
|
-
agent_list.append(agent)
|
202
|
-
|
203
|
-
if iterations > MAX_ITERATIONS_MULTIPLIER * num_agents:
|
204
|
-
raise Exception("Too many failures")
|
205
|
-
|
206
|
-
return agent_list
|
207
|
-
|
208
|
-
|
209
|
-
if __name__ == "__main__":
|
210
|
-
import doctest
|
211
|
-
|
212
|
-
doctest.testmod()
|
213
|
-
# from edsl.language_models import LanguageModel
|
214
|
-
|
215
|
-
# m = LanguageModel.example(canned_response="This is a cool dude.", test_model=True)
|
216
|
-
# ag = agent_generator(
|
217
|
-
# persona="Base person",
|
218
|
-
# dimension_dict={"attitude": ["Positive", "Negative"]},
|
219
|
-
# model=m,
|
220
|
-
# )
|
221
|
-
# example = [next(ag).select("new_agent_persona").first() for _ in range(10)]
|
222
|
-
# dimension_dict = {"attitude": ["positive", "negative"]}
|
223
|
-
# ag = gen_agent_traits(dimension_dict)
|
224
|
-
# example = [next(ag) for _ in range(100)]
|
edsl/coop/PriceFetcher.py
DELETED
@@ -1,58 +0,0 @@
|
|
1
|
-
import requests
|
2
|
-
import csv
|
3
|
-
from io import StringIO
|
4
|
-
|
5
|
-
|
6
|
-
class PriceFetcher:
|
7
|
-
_instance = None
|
8
|
-
|
9
|
-
def __new__(cls):
|
10
|
-
if cls._instance is None:
|
11
|
-
cls._instance = super(PriceFetcher, cls).__new__(cls)
|
12
|
-
cls._instance._cached_prices = None
|
13
|
-
return cls._instance
|
14
|
-
|
15
|
-
def fetch_prices(self):
|
16
|
-
if self._cached_prices is not None:
|
17
|
-
return self._cached_prices
|
18
|
-
|
19
|
-
import requests
|
20
|
-
import csv
|
21
|
-
from io import StringIO
|
22
|
-
|
23
|
-
sheet_id = "1SAO3Bhntefl0XQHJv27rMxpvu6uzKDWNXFHRa7jrUDs"
|
24
|
-
|
25
|
-
# Construct the URL to fetch the CSV
|
26
|
-
url = f"https://docs.google.com/spreadsheets/d/{sheet_id}/export?format=csv"
|
27
|
-
|
28
|
-
try:
|
29
|
-
# Fetch the CSV data
|
30
|
-
response = requests.get(url)
|
31
|
-
response.raise_for_status() # Raise an exception for bad responses
|
32
|
-
|
33
|
-
# Parse the CSV data
|
34
|
-
csv_data = StringIO(response.text)
|
35
|
-
reader = csv.reader(csv_data)
|
36
|
-
|
37
|
-
# Convert to list of dictionaries
|
38
|
-
headers = next(reader)
|
39
|
-
data = [dict(zip(headers, row)) for row in reader]
|
40
|
-
|
41
|
-
# self._cached_prices = data
|
42
|
-
# return data
|
43
|
-
price_lookup = {}
|
44
|
-
for entry in data:
|
45
|
-
service = entry.get("service", None)
|
46
|
-
model = entry.get("model", None)
|
47
|
-
if service and model:
|
48
|
-
token_type = entry.get("token_type", None)
|
49
|
-
if (service, model) in price_lookup:
|
50
|
-
price_lookup[(service, model)].update({token_type: entry})
|
51
|
-
else:
|
52
|
-
price_lookup[(service, model)] = {token_type: entry}
|
53
|
-
self._cached_prices = price_lookup
|
54
|
-
return self._cached_prices
|
55
|
-
|
56
|
-
except requests.RequestException as e:
|
57
|
-
# print(f"An error occurred: {e}")
|
58
|
-
return {}
|
@@ -1,120 +0,0 @@
|
|
1
|
-
import os
|
2
|
-
from typing import Any, List
|
3
|
-
from edsl.inference_services.InferenceServiceABC import InferenceServiceABC
|
4
|
-
from edsl.language_models.LanguageModel import LanguageModel
|
5
|
-
import asyncio
|
6
|
-
from mistralai import Mistral
|
7
|
-
|
8
|
-
from edsl.exceptions.language_models import LanguageModelBadResponseError
|
9
|
-
|
10
|
-
|
11
|
-
class MistralAIService(InferenceServiceABC):
|
12
|
-
"""Mistral AI service class."""
|
13
|
-
|
14
|
-
key_sequence = ["choices", 0, "message", "content"]
|
15
|
-
usage_sequence = ["usage"]
|
16
|
-
|
17
|
-
_inference_service_ = "mistral"
|
18
|
-
_env_key_name_ = "MISTRAL_API_KEY" # Environment variable for Mistral API key
|
19
|
-
input_token_name = "prompt_tokens"
|
20
|
-
output_token_name = "completion_tokens"
|
21
|
-
|
22
|
-
_sync_client_instance = None
|
23
|
-
_async_client_instance = None
|
24
|
-
|
25
|
-
_sync_client = Mistral
|
26
|
-
_async_client = Mistral
|
27
|
-
|
28
|
-
_models_list_cache: List[str] = []
|
29
|
-
model_exclude_list = []
|
30
|
-
|
31
|
-
def __init_subclass__(cls, **kwargs):
|
32
|
-
super().__init_subclass__(**kwargs)
|
33
|
-
# so subclasses have to create their own instances of the clients
|
34
|
-
cls._sync_client_instance = None
|
35
|
-
cls._async_client_instance = None
|
36
|
-
|
37
|
-
@classmethod
|
38
|
-
def sync_client(cls):
|
39
|
-
if cls._sync_client_instance is None:
|
40
|
-
cls._sync_client_instance = cls._sync_client(
|
41
|
-
api_key=os.getenv(cls._env_key_name_)
|
42
|
-
)
|
43
|
-
return cls._sync_client_instance
|
44
|
-
|
45
|
-
@classmethod
|
46
|
-
def async_client(cls):
|
47
|
-
if cls._async_client_instance is None:
|
48
|
-
cls._async_client_instance = cls._async_client(
|
49
|
-
api_key=os.getenv(cls._env_key_name_)
|
50
|
-
)
|
51
|
-
return cls._async_client_instance
|
52
|
-
|
53
|
-
@classmethod
|
54
|
-
def available(cls) -> list[str]:
|
55
|
-
if not cls._models_list_cache:
|
56
|
-
cls._models_list_cache = [
|
57
|
-
m.id for m in cls.sync_client().models.list().data
|
58
|
-
]
|
59
|
-
|
60
|
-
return cls._models_list_cache
|
61
|
-
|
62
|
-
@classmethod
|
63
|
-
def create_model(
|
64
|
-
cls, model_name: str = "mistral", model_class_name=None
|
65
|
-
) -> LanguageModel:
|
66
|
-
if model_class_name is None:
|
67
|
-
model_class_name = cls.to_class_name(model_name)
|
68
|
-
|
69
|
-
class LLM(LanguageModel):
|
70
|
-
"""
|
71
|
-
Child class of LanguageModel for interacting with Mistral models.
|
72
|
-
"""
|
73
|
-
|
74
|
-
key_sequence = cls.key_sequence
|
75
|
-
usage_sequence = cls.usage_sequence
|
76
|
-
|
77
|
-
input_token_name = cls.input_token_name
|
78
|
-
output_token_name = cls.output_token_name
|
79
|
-
|
80
|
-
_inference_service_ = cls._inference_service_
|
81
|
-
_model_ = model_name
|
82
|
-
_parameters_ = {
|
83
|
-
"temperature": 0.5,
|
84
|
-
"max_tokens": 512,
|
85
|
-
"top_p": 0.9,
|
86
|
-
}
|
87
|
-
|
88
|
-
_tpm = cls.get_tpm(cls)
|
89
|
-
_rpm = cls.get_rpm(cls)
|
90
|
-
|
91
|
-
def sync_client(self):
|
92
|
-
return cls.sync_client()
|
93
|
-
|
94
|
-
def async_client(self):
|
95
|
-
return cls.async_client()
|
96
|
-
|
97
|
-
async def async_execute_model_call(
|
98
|
-
self, user_prompt: str, system_prompt: str = ""
|
99
|
-
) -> dict[str, Any]:
|
100
|
-
"""Calls the Mistral API and returns the API response."""
|
101
|
-
s = self.async_client()
|
102
|
-
|
103
|
-
try:
|
104
|
-
res = await s.chat.complete_async(
|
105
|
-
model=model_name,
|
106
|
-
messages=[
|
107
|
-
{
|
108
|
-
"content": user_prompt,
|
109
|
-
"role": "user",
|
110
|
-
},
|
111
|
-
],
|
112
|
-
)
|
113
|
-
except Exception as e:
|
114
|
-
raise LanguageModelBadResponseError(f"Error with Mistral API: {e}")
|
115
|
-
|
116
|
-
return res.model_dump()
|
117
|
-
|
118
|
-
LLM.__name__ = model_class_name
|
119
|
-
|
120
|
-
return LLM
|