edsl 0.1.37.dev6__py3-none-any.whl → 0.1.38__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- edsl/Base.py +332 -303
- edsl/BaseDiff.py +260 -260
- edsl/TemplateLoader.py +24 -24
- edsl/__init__.py +49 -48
- edsl/__version__.py +1 -1
- edsl/agents/Agent.py +867 -855
- edsl/agents/AgentList.py +413 -350
- edsl/agents/Invigilator.py +233 -222
- edsl/agents/InvigilatorBase.py +265 -284
- edsl/agents/PromptConstructor.py +354 -353
- edsl/agents/__init__.py +3 -3
- edsl/agents/descriptors.py +99 -99
- edsl/agents/prompt_helpers.py +129 -129
- edsl/auto/AutoStudy.py +117 -117
- edsl/auto/StageBase.py +230 -230
- edsl/auto/StageGenerateSurvey.py +178 -178
- edsl/auto/StageLabelQuestions.py +125 -125
- edsl/auto/StagePersona.py +61 -61
- edsl/auto/StagePersonaDimensionValueRanges.py +88 -88
- edsl/auto/StagePersonaDimensionValues.py +74 -74
- edsl/auto/StagePersonaDimensions.py +69 -69
- edsl/auto/StageQuestions.py +73 -73
- edsl/auto/SurveyCreatorPipeline.py +21 -21
- edsl/auto/utilities.py +224 -224
- edsl/base/Base.py +279 -289
- edsl/config.py +157 -149
- edsl/conversation/Conversation.py +290 -290
- edsl/conversation/car_buying.py +58 -58
- edsl/conversation/chips.py +95 -95
- edsl/conversation/mug_negotiation.py +81 -81
- edsl/conversation/next_speaker_utilities.py +93 -93
- edsl/coop/PriceFetcher.py +54 -54
- edsl/coop/__init__.py +2 -2
- edsl/coop/coop.py +1028 -958
- edsl/coop/utils.py +131 -131
- edsl/data/Cache.py +555 -527
- edsl/data/CacheEntry.py +233 -228
- edsl/data/CacheHandler.py +149 -149
- edsl/data/RemoteCacheSync.py +78 -97
- edsl/data/SQLiteDict.py +292 -292
- edsl/data/__init__.py +4 -4
- edsl/data/orm.py +10 -10
- edsl/data_transfer_models.py +73 -73
- edsl/enums.py +175 -173
- edsl/exceptions/BaseException.py +21 -21
- edsl/exceptions/__init__.py +54 -54
- edsl/exceptions/agents.py +42 -38
- edsl/exceptions/cache.py +5 -0
- edsl/exceptions/configuration.py +16 -16
- edsl/exceptions/coop.py +10 -10
- edsl/exceptions/data.py +14 -14
- edsl/exceptions/general.py +34 -34
- edsl/exceptions/jobs.py +33 -33
- edsl/exceptions/language_models.py +63 -63
- edsl/exceptions/prompts.py +15 -15
- edsl/exceptions/questions.py +91 -91
- edsl/exceptions/results.py +29 -29
- edsl/exceptions/scenarios.py +22 -22
- edsl/exceptions/surveys.py +37 -37
- edsl/inference_services/AnthropicService.py +87 -87
- edsl/inference_services/AwsBedrock.py +120 -120
- edsl/inference_services/AzureAI.py +217 -217
- edsl/inference_services/DeepInfraService.py +18 -18
- edsl/inference_services/GoogleService.py +148 -156
- edsl/inference_services/GroqService.py +20 -20
- edsl/inference_services/InferenceServiceABC.py +147 -147
- edsl/inference_services/InferenceServicesCollection.py +97 -97
- edsl/inference_services/MistralAIService.py +123 -123
- edsl/inference_services/OllamaService.py +18 -18
- edsl/inference_services/OpenAIService.py +224 -224
- edsl/inference_services/PerplexityService.py +163 -0
- edsl/inference_services/TestService.py +89 -89
- edsl/inference_services/TogetherAIService.py +170 -170
- edsl/inference_services/models_available_cache.py +118 -118
- edsl/inference_services/rate_limits_cache.py +25 -25
- edsl/inference_services/registry.py +41 -39
- edsl/inference_services/write_available.py +10 -10
- edsl/jobs/Answers.py +56 -56
- edsl/jobs/Jobs.py +898 -1347
- edsl/jobs/JobsChecks.py +147 -0
- edsl/jobs/JobsPrompts.py +268 -0
- edsl/jobs/JobsRemoteInferenceHandler.py +239 -0
- edsl/jobs/__init__.py +1 -1
- edsl/jobs/buckets/BucketCollection.py +63 -63
- edsl/jobs/buckets/ModelBuckets.py +65 -65
- edsl/jobs/buckets/TokenBucket.py +251 -248
- edsl/jobs/interviews/Interview.py +661 -661
- edsl/jobs/interviews/InterviewExceptionCollection.py +99 -99
- edsl/jobs/interviews/InterviewExceptionEntry.py +186 -186
- edsl/jobs/interviews/InterviewStatistic.py +63 -63
- edsl/jobs/interviews/InterviewStatisticsCollection.py +25 -25
- edsl/jobs/interviews/InterviewStatusDictionary.py +78 -78
- edsl/jobs/interviews/InterviewStatusLog.py +92 -92
- edsl/jobs/interviews/ReportErrors.py +66 -66
- edsl/jobs/interviews/interview_status_enum.py +9 -9
- edsl/jobs/runners/JobsRunnerAsyncio.py +466 -338
- edsl/jobs/runners/JobsRunnerStatus.py +330 -332
- edsl/jobs/tasks/QuestionTaskCreator.py +242 -242
- edsl/jobs/tasks/TaskCreators.py +64 -64
- edsl/jobs/tasks/TaskHistory.py +450 -442
- edsl/jobs/tasks/TaskStatusLog.py +23 -23
- edsl/jobs/tasks/task_status_enum.py +163 -163
- edsl/jobs/tokens/InterviewTokenUsage.py +27 -27
- edsl/jobs/tokens/TokenUsage.py +34 -34
- edsl/language_models/KeyLookup.py +30 -30
- edsl/language_models/LanguageModel.py +668 -706
- edsl/language_models/ModelList.py +155 -102
- edsl/language_models/RegisterLanguageModelsMeta.py +184 -184
- edsl/language_models/__init__.py +3 -3
- edsl/language_models/fake_openai_call.py +15 -15
- edsl/language_models/fake_openai_service.py +61 -61
- edsl/language_models/registry.py +190 -137
- edsl/language_models/repair.py +156 -156
- edsl/language_models/unused/ReplicateBase.py +83 -83
- edsl/language_models/utilities.py +64 -64
- edsl/notebooks/Notebook.py +258 -259
- edsl/notebooks/__init__.py +1 -1
- edsl/prompts/Prompt.py +362 -357
- edsl/prompts/__init__.py +2 -2
- edsl/questions/AnswerValidatorMixin.py +289 -289
- edsl/questions/QuestionBase.py +664 -656
- edsl/questions/QuestionBaseGenMixin.py +161 -161
- edsl/questions/QuestionBasePromptsMixin.py +217 -234
- edsl/questions/QuestionBudget.py +227 -227
- edsl/questions/QuestionCheckBox.py +359 -359
- edsl/questions/QuestionExtract.py +182 -183
- edsl/questions/QuestionFreeText.py +114 -114
- edsl/questions/QuestionFunctional.py +166 -159
- edsl/questions/QuestionList.py +231 -231
- edsl/questions/QuestionMultipleChoice.py +286 -286
- edsl/questions/QuestionNumerical.py +153 -153
- edsl/questions/QuestionRank.py +324 -324
- edsl/questions/Quick.py +41 -41
- edsl/questions/RegisterQuestionsMeta.py +71 -71
- edsl/questions/ResponseValidatorABC.py +174 -174
- edsl/questions/SimpleAskMixin.py +73 -73
- edsl/questions/__init__.py +26 -26
- edsl/questions/compose_questions.py +98 -98
- edsl/questions/decorators.py +21 -21
- edsl/questions/derived/QuestionLikertFive.py +76 -76
- edsl/questions/derived/QuestionLinearScale.py +87 -87
- edsl/questions/derived/QuestionTopK.py +93 -91
- edsl/questions/derived/QuestionYesNo.py +82 -82
- edsl/questions/descriptors.py +413 -413
- edsl/questions/prompt_templates/question_budget.jinja +13 -13
- edsl/questions/prompt_templates/question_checkbox.jinja +32 -32
- edsl/questions/prompt_templates/question_extract.jinja +11 -11
- edsl/questions/prompt_templates/question_free_text.jinja +3 -3
- edsl/questions/prompt_templates/question_linear_scale.jinja +11 -11
- edsl/questions/prompt_templates/question_list.jinja +17 -17
- edsl/questions/prompt_templates/question_multiple_choice.jinja +33 -33
- edsl/questions/prompt_templates/question_numerical.jinja +36 -36
- edsl/questions/question_registry.py +177 -147
- edsl/questions/settings.py +12 -12
- edsl/questions/templates/budget/answering_instructions.jinja +7 -7
- edsl/questions/templates/budget/question_presentation.jinja +7 -7
- edsl/questions/templates/checkbox/answering_instructions.jinja +10 -10
- edsl/questions/templates/checkbox/question_presentation.jinja +22 -22
- edsl/questions/templates/extract/answering_instructions.jinja +7 -7
- edsl/questions/templates/likert_five/answering_instructions.jinja +10 -10
- edsl/questions/templates/likert_five/question_presentation.jinja +11 -11
- edsl/questions/templates/linear_scale/answering_instructions.jinja +5 -5
- edsl/questions/templates/linear_scale/question_presentation.jinja +5 -5
- edsl/questions/templates/list/answering_instructions.jinja +3 -3
- edsl/questions/templates/list/question_presentation.jinja +5 -5
- edsl/questions/templates/multiple_choice/answering_instructions.jinja +9 -9
- edsl/questions/templates/multiple_choice/question_presentation.jinja +11 -11
- edsl/questions/templates/numerical/answering_instructions.jinja +6 -6
- edsl/questions/templates/numerical/question_presentation.jinja +6 -6
- edsl/questions/templates/rank/answering_instructions.jinja +11 -11
- edsl/questions/templates/rank/question_presentation.jinja +15 -15
- edsl/questions/templates/top_k/answering_instructions.jinja +8 -8
- edsl/questions/templates/top_k/question_presentation.jinja +22 -22
- edsl/questions/templates/yes_no/answering_instructions.jinja +6 -6
- edsl/questions/templates/yes_no/question_presentation.jinja +11 -11
- edsl/results/CSSParameterizer.py +108 -0
- edsl/results/Dataset.py +424 -293
- edsl/results/DatasetExportMixin.py +731 -717
- edsl/results/DatasetTree.py +275 -145
- edsl/results/Result.py +465 -450
- edsl/results/Results.py +1165 -1071
- edsl/results/ResultsDBMixin.py +238 -238
- edsl/results/ResultsExportMixin.py +43 -43
- edsl/results/ResultsFetchMixin.py +33 -33
- edsl/results/ResultsGGMixin.py +121 -121
- edsl/results/ResultsToolsMixin.py +98 -98
- edsl/results/Selector.py +135 -135
- edsl/results/TableDisplay.py +198 -0
- edsl/results/__init__.py +2 -2
- edsl/results/table_display.css +78 -0
- edsl/results/tree_explore.py +115 -115
- edsl/scenarios/FileStore.py +632 -458
- edsl/scenarios/Scenario.py +601 -546
- edsl/scenarios/ScenarioHtmlMixin.py +64 -64
- edsl/scenarios/ScenarioJoin.py +127 -0
- edsl/scenarios/ScenarioList.py +1287 -1112
- edsl/scenarios/ScenarioListExportMixin.py +52 -52
- edsl/scenarios/ScenarioListPdfMixin.py +261 -261
- edsl/scenarios/__init__.py +4 -4
- edsl/shared.py +1 -1
- edsl/study/ObjectEntry.py +173 -173
- edsl/study/ProofOfWork.py +113 -113
- edsl/study/SnapShot.py +80 -80
- edsl/study/Study.py +528 -528
- edsl/study/__init__.py +4 -4
- edsl/surveys/DAG.py +148 -148
- edsl/surveys/Memory.py +31 -31
- edsl/surveys/MemoryPlan.py +244 -244
- edsl/surveys/Rule.py +326 -330
- edsl/surveys/RuleCollection.py +387 -387
- edsl/surveys/Survey.py +1801 -1795
- edsl/surveys/SurveyCSS.py +261 -261
- edsl/surveys/SurveyExportMixin.py +259 -259
- edsl/surveys/SurveyFlowVisualizationMixin.py +179 -121
- edsl/surveys/SurveyQualtricsImport.py +284 -284
- edsl/surveys/__init__.py +3 -3
- edsl/surveys/base.py +53 -53
- edsl/surveys/descriptors.py +56 -56
- edsl/surveys/instructions/ChangeInstruction.py +49 -47
- edsl/surveys/instructions/Instruction.py +65 -51
- edsl/surveys/instructions/InstructionCollection.py +77 -77
- edsl/templates/error_reporting/base.html +23 -23
- edsl/templates/error_reporting/exceptions_by_model.html +34 -34
- edsl/templates/error_reporting/exceptions_by_question_name.html +16 -16
- edsl/templates/error_reporting/exceptions_by_type.html +16 -16
- edsl/templates/error_reporting/interview_details.html +115 -115
- edsl/templates/error_reporting/interviews.html +19 -10
- edsl/templates/error_reporting/overview.html +4 -4
- edsl/templates/error_reporting/performance_plot.html +1 -1
- edsl/templates/error_reporting/report.css +73 -73
- edsl/templates/error_reporting/report.html +117 -117
- edsl/templates/error_reporting/report.js +25 -25
- edsl/tools/__init__.py +1 -1
- edsl/tools/clusters.py +192 -192
- edsl/tools/embeddings.py +27 -27
- edsl/tools/embeddings_plotting.py +118 -118
- edsl/tools/plotting.py +112 -112
- edsl/tools/summarize.py +18 -18
- edsl/utilities/SystemInfo.py +28 -28
- edsl/utilities/__init__.py +22 -22
- edsl/utilities/ast_utilities.py +25 -25
- edsl/utilities/data/Registry.py +6 -6
- edsl/utilities/data/__init__.py +1 -1
- edsl/utilities/data/scooter_results.json +1 -1
- edsl/utilities/decorators.py +77 -77
- edsl/utilities/gcp_bucket/cloud_storage.py +96 -96
- edsl/utilities/interface.py +627 -627
- edsl/{conjure → utilities}/naming_utilities.py +263 -263
- edsl/utilities/repair_functions.py +28 -28
- edsl/utilities/restricted_python.py +70 -70
- edsl/utilities/utilities.py +424 -409
- {edsl-0.1.37.dev6.dist-info → edsl-0.1.38.dist-info}/LICENSE +21 -21
- {edsl-0.1.37.dev6.dist-info → edsl-0.1.38.dist-info}/METADATA +2 -1
- edsl-0.1.38.dist-info/RECORD +277 -0
- edsl/conjure/AgentConstructionMixin.py +0 -160
- edsl/conjure/Conjure.py +0 -62
- edsl/conjure/InputData.py +0 -659
- edsl/conjure/InputDataCSV.py +0 -48
- edsl/conjure/InputDataMixinQuestionStats.py +0 -182
- edsl/conjure/InputDataPyRead.py +0 -91
- edsl/conjure/InputDataSPSS.py +0 -8
- edsl/conjure/InputDataStata.py +0 -8
- edsl/conjure/QuestionOptionMixin.py +0 -76
- edsl/conjure/QuestionTypeMixin.py +0 -23
- edsl/conjure/RawQuestion.py +0 -65
- edsl/conjure/SurveyResponses.py +0 -7
- edsl/conjure/__init__.py +0 -9
- edsl/conjure/examples/placeholder.txt +0 -0
- edsl/conjure/utilities.py +0 -201
- edsl-0.1.37.dev6.dist-info/RECORD +0 -283
- {edsl-0.1.37.dev6.dist-info → edsl-0.1.38.dist-info}/WHEEL +0 -0
edsl/agents/InvigilatorBase.py
CHANGED
@@ -1,284 +1,265 @@
|
|
1
|
-
from abc import ABC, abstractmethod
|
2
|
-
import asyncio
|
3
|
-
from typing import Coroutine, Dict, Any, Optional
|
4
|
-
|
5
|
-
from edsl.prompts.Prompt import Prompt
|
6
|
-
from edsl.utilities.decorators import jupyter_nb_handler
|
7
|
-
from edsl.data_transfer_models import AgentResponseDict
|
8
|
-
|
9
|
-
from edsl.data.Cache import Cache
|
10
|
-
|
11
|
-
from edsl.questions.QuestionBase import QuestionBase
|
12
|
-
from edsl.scenarios.Scenario import Scenario
|
13
|
-
from edsl.surveys.MemoryPlan import MemoryPlan
|
14
|
-
from edsl.language_models.LanguageModel import LanguageModel
|
15
|
-
|
16
|
-
from edsl.data_transfer_models import EDSLResultObjectInput
|
17
|
-
from edsl.agents.PromptConstructor import PromptConstructor
|
18
|
-
|
19
|
-
from edsl.agents.prompt_helpers import PromptPlan
|
20
|
-
|
21
|
-
|
22
|
-
class InvigilatorBase(ABC):
|
23
|
-
"""An invigiator (someone who administers an exam) is a class that is responsible for administering a question to an agent.
|
24
|
-
|
25
|
-
>>> InvigilatorBase.example().answer_question()
|
26
|
-
{'message': [{'text': 'SPAM!'}], 'usage': {'prompt_tokens': 1, 'completion_tokens': 1}}
|
27
|
-
|
28
|
-
>>> InvigilatorBase.example().get_failed_task_result(failure_reason="Failed to get response").comment
|
29
|
-
'Failed to get response'
|
30
|
-
|
31
|
-
This returns an empty prompt because there is no memory the agent needs to have at q0.
|
32
|
-
|
33
|
-
|
34
|
-
"""
|
35
|
-
|
36
|
-
def __init__(
|
37
|
-
self,
|
38
|
-
agent: "Agent",
|
39
|
-
question: QuestionBase,
|
40
|
-
scenario: Scenario,
|
41
|
-
model: LanguageModel,
|
42
|
-
memory_plan: MemoryPlan,
|
43
|
-
current_answers: dict,
|
44
|
-
survey: Optional["Survey"],
|
45
|
-
cache: Optional[Cache] = None,
|
46
|
-
iteration: Optional[int] = 1,
|
47
|
-
additional_prompt_data: Optional[dict] = None,
|
48
|
-
sidecar_model: Optional[LanguageModel] = None,
|
49
|
-
raise_validation_errors: Optional[bool] = True,
|
50
|
-
prompt_plan: Optional["PromptPlan"] = None,
|
51
|
-
):
|
52
|
-
"""Initialize a new Invigilator."""
|
53
|
-
self.agent = agent
|
54
|
-
self.question = question
|
55
|
-
self.scenario = scenario
|
56
|
-
self.model = model
|
57
|
-
self.memory_plan = memory_plan
|
58
|
-
self.current_answers = current_answers or {}
|
59
|
-
self.iteration = iteration
|
60
|
-
self.additional_prompt_data = additional_prompt_data
|
61
|
-
self.cache = cache
|
62
|
-
self.sidecar_model = sidecar_model
|
63
|
-
self.survey = survey
|
64
|
-
self.raise_validation_errors = raise_validation_errors
|
65
|
-
if prompt_plan is None:
|
66
|
-
self.prompt_plan = PromptPlan()
|
67
|
-
else:
|
68
|
-
self.prompt_plan = prompt_plan
|
69
|
-
|
70
|
-
self.raw_model_response = (
|
71
|
-
None # placeholder for the raw response from the model
|
72
|
-
)
|
73
|
-
|
74
|
-
@property
|
75
|
-
def prompt_constructor(self) -> PromptConstructor:
|
76
|
-
"""Return the prompt constructor."""
|
77
|
-
return PromptConstructor(self, prompt_plan=self.prompt_plan)
|
78
|
-
|
79
|
-
def to_dict(self):
|
80
|
-
attributes = [
|
81
|
-
"agent",
|
82
|
-
"question",
|
83
|
-
"scenario",
|
84
|
-
"model",
|
85
|
-
"memory_plan",
|
86
|
-
"current_answers",
|
87
|
-
"iteration",
|
88
|
-
"additional_prompt_data",
|
89
|
-
"cache",
|
90
|
-
"sidecar_model",
|
91
|
-
"survey",
|
92
|
-
]
|
93
|
-
|
94
|
-
def serialize_attribute(attr):
|
95
|
-
value = getattr(self, attr)
|
96
|
-
if value is None:
|
97
|
-
return None
|
98
|
-
if hasattr(value, "to_dict"):
|
99
|
-
return value.to_dict()
|
100
|
-
if isinstance(value, (int, float, str, bool, dict, list)):
|
101
|
-
return value
|
102
|
-
return str(value)
|
103
|
-
|
104
|
-
return {attr: serialize_attribute(attr) for attr in attributes}
|
105
|
-
|
106
|
-
@classmethod
|
107
|
-
def from_dict(cls, data):
|
108
|
-
from edsl.agents.Agent import Agent
|
109
|
-
from edsl.questions import QuestionBase
|
110
|
-
from edsl.scenarios.Scenario import Scenario
|
111
|
-
from edsl.surveys.MemoryPlan import MemoryPlan
|
112
|
-
from edsl.language_models.LanguageModel import LanguageModel
|
113
|
-
from edsl.surveys.Survey import Survey
|
114
|
-
|
115
|
-
agent = Agent.from_dict(data["agent"])
|
116
|
-
question = QuestionBase.from_dict(data["question"])
|
117
|
-
scenario = Scenario.from_dict(data["scenario"])
|
118
|
-
model = LanguageModel.from_dict(data["model"])
|
119
|
-
memory_plan = MemoryPlan.from_dict(data["memory_plan"])
|
120
|
-
survey = Survey.from_dict(data["survey"])
|
121
|
-
current_answers = data["current_answers"]
|
122
|
-
iteration = data["iteration"]
|
123
|
-
additional_prompt_data = data["additional_prompt_data"]
|
124
|
-
cache = Cache.from_dict(data["cache"])
|
125
|
-
|
126
|
-
if data["sidecar_model"] is None:
|
127
|
-
sidecar_model = None
|
128
|
-
else:
|
129
|
-
sidecar_model = LanguageModel.from_dict(data["sidecar_model"])
|
130
|
-
|
131
|
-
return cls(
|
132
|
-
agent=agent,
|
133
|
-
question=question,
|
134
|
-
scenario=scenario,
|
135
|
-
model=model,
|
136
|
-
memory_plan=memory_plan,
|
137
|
-
current_answers=current_answers,
|
138
|
-
survey=survey,
|
139
|
-
iteration=iteration,
|
140
|
-
additional_prompt_data=additional_prompt_data,
|
141
|
-
cache=cache,
|
142
|
-
sidecar_model=sidecar_model,
|
143
|
-
)
|
144
|
-
|
145
|
-
def __repr__(self) -> str:
|
146
|
-
"""Return a string representation of the Invigilator.
|
147
|
-
|
148
|
-
>>> InvigilatorBase.example().__repr__()
|
149
|
-
'InvigilatorExample(...)'
|
150
|
-
|
151
|
-
"""
|
152
|
-
return f"{self.__class__.__name__}(agent={repr(self.agent)}, question={repr(self.question)}, scneario={repr(self.scenario)}, model={repr(self.model)}, memory_plan={repr(self.memory_plan)}, current_answers={repr(self.current_answers)}, iteration{repr(self.iteration)}, additional_prompt_data={repr(self.additional_prompt_data)}, cache={repr(self.cache)}, sidecarmodel={repr(self.sidecar_model)})"
|
153
|
-
|
154
|
-
def get_failed_task_result(self, failure_reason) -> EDSLResultObjectInput:
|
155
|
-
"""Return an AgentResponseDict used in case the question-asking fails.
|
156
|
-
|
157
|
-
Possible reasons include:
|
158
|
-
- Legimately skipped because of skip logic
|
159
|
-
- Failed to get response from the model
|
160
|
-
|
161
|
-
"""
|
162
|
-
data = {
|
163
|
-
"answer": None,
|
164
|
-
"generated_tokens": None,
|
165
|
-
"comment": failure_reason,
|
166
|
-
"question_name": self.question.question_name,
|
167
|
-
"prompts": self.get_prompts(),
|
168
|
-
"cached_response": None,
|
169
|
-
"raw_model_response": None,
|
170
|
-
"cache_used": None,
|
171
|
-
"cache_key": None,
|
172
|
-
}
|
173
|
-
return EDSLResultObjectInput(**data)
|
174
|
-
|
175
|
-
|
176
|
-
|
177
|
-
|
178
|
-
|
179
|
-
|
180
|
-
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
|
186
|
-
|
187
|
-
|
188
|
-
|
189
|
-
|
190
|
-
|
191
|
-
|
192
|
-
|
193
|
-
|
194
|
-
|
195
|
-
|
196
|
-
|
197
|
-
return
|
198
|
-
|
199
|
-
|
200
|
-
|
201
|
-
|
202
|
-
|
203
|
-
|
204
|
-
|
205
|
-
|
206
|
-
|
207
|
-
|
208
|
-
|
209
|
-
|
210
|
-
|
211
|
-
|
212
|
-
|
213
|
-
|
214
|
-
|
215
|
-
|
216
|
-
|
217
|
-
|
218
|
-
|
219
|
-
|
220
|
-
|
221
|
-
|
222
|
-
|
223
|
-
|
224
|
-
|
225
|
-
|
226
|
-
|
227
|
-
|
228
|
-
|
229
|
-
|
230
|
-
|
231
|
-
|
232
|
-
|
233
|
-
|
234
|
-
|
235
|
-
|
236
|
-
from edsl import
|
237
|
-
|
238
|
-
|
239
|
-
|
240
|
-
|
241
|
-
|
242
|
-
|
243
|
-
|
244
|
-
|
245
|
-
|
246
|
-
|
247
|
-
|
248
|
-
|
249
|
-
|
250
|
-
|
251
|
-
|
252
|
-
|
253
|
-
|
254
|
-
|
255
|
-
|
256
|
-
|
257
|
-
|
258
|
-
|
259
|
-
|
260
|
-
|
261
|
-
|
262
|
-
|
263
|
-
|
264
|
-
|
265
|
-
|
266
|
-
return await self.model.async_execute_model_call(
|
267
|
-
user_prompt="Hello", system_prompt="Hi"
|
268
|
-
)
|
269
|
-
|
270
|
-
return InvigilatorExample(
|
271
|
-
agent=agent,
|
272
|
-
question=question,
|
273
|
-
scenario=scenario,
|
274
|
-
survey=survey,
|
275
|
-
model=model,
|
276
|
-
memory_plan=memory_plan,
|
277
|
-
current_answers=current_answers,
|
278
|
-
)
|
279
|
-
|
280
|
-
|
281
|
-
if __name__ == "__main__":
|
282
|
-
import doctest
|
283
|
-
|
284
|
-
doctest.testmod(optionflags=doctest.ELLIPSIS)
|
1
|
+
from abc import ABC, abstractmethod
|
2
|
+
import asyncio
|
3
|
+
from typing import Coroutine, Dict, Any, Optional
|
4
|
+
|
5
|
+
from edsl.prompts.Prompt import Prompt
|
6
|
+
from edsl.utilities.decorators import jupyter_nb_handler
|
7
|
+
from edsl.data_transfer_models import AgentResponseDict
|
8
|
+
|
9
|
+
from edsl.data.Cache import Cache
|
10
|
+
|
11
|
+
from edsl.questions.QuestionBase import QuestionBase
|
12
|
+
from edsl.scenarios.Scenario import Scenario
|
13
|
+
from edsl.surveys.MemoryPlan import MemoryPlan
|
14
|
+
from edsl.language_models.LanguageModel import LanguageModel
|
15
|
+
|
16
|
+
from edsl.data_transfer_models import EDSLResultObjectInput
|
17
|
+
from edsl.agents.PromptConstructor import PromptConstructor
|
18
|
+
|
19
|
+
from edsl.agents.prompt_helpers import PromptPlan
|
20
|
+
|
21
|
+
|
22
|
+
class InvigilatorBase(ABC):
|
23
|
+
"""An invigiator (someone who administers an exam) is a class that is responsible for administering a question to an agent.
|
24
|
+
|
25
|
+
>>> InvigilatorBase.example().answer_question()
|
26
|
+
{'message': [{'text': 'SPAM!'}], 'usage': {'prompt_tokens': 1, 'completion_tokens': 1}}
|
27
|
+
|
28
|
+
>>> InvigilatorBase.example().get_failed_task_result(failure_reason="Failed to get response").comment
|
29
|
+
'Failed to get response'
|
30
|
+
|
31
|
+
This returns an empty prompt because there is no memory the agent needs to have at q0.
|
32
|
+
|
33
|
+
|
34
|
+
"""
|
35
|
+
|
36
|
+
def __init__(
|
37
|
+
self,
|
38
|
+
agent: "Agent",
|
39
|
+
question: QuestionBase,
|
40
|
+
scenario: Scenario,
|
41
|
+
model: LanguageModel,
|
42
|
+
memory_plan: MemoryPlan,
|
43
|
+
current_answers: dict,
|
44
|
+
survey: Optional["Survey"],
|
45
|
+
cache: Optional[Cache] = None,
|
46
|
+
iteration: Optional[int] = 1,
|
47
|
+
additional_prompt_data: Optional[dict] = None,
|
48
|
+
sidecar_model: Optional[LanguageModel] = None,
|
49
|
+
raise_validation_errors: Optional[bool] = True,
|
50
|
+
prompt_plan: Optional["PromptPlan"] = None,
|
51
|
+
):
|
52
|
+
"""Initialize a new Invigilator."""
|
53
|
+
self.agent = agent
|
54
|
+
self.question = question
|
55
|
+
self.scenario = scenario
|
56
|
+
self.model = model
|
57
|
+
self.memory_plan = memory_plan
|
58
|
+
self.current_answers = current_answers or {}
|
59
|
+
self.iteration = iteration
|
60
|
+
self.additional_prompt_data = additional_prompt_data
|
61
|
+
self.cache = cache
|
62
|
+
self.sidecar_model = sidecar_model
|
63
|
+
self.survey = survey
|
64
|
+
self.raise_validation_errors = raise_validation_errors
|
65
|
+
if prompt_plan is None:
|
66
|
+
self.prompt_plan = PromptPlan()
|
67
|
+
else:
|
68
|
+
self.prompt_plan = prompt_plan
|
69
|
+
|
70
|
+
self.raw_model_response = (
|
71
|
+
None # placeholder for the raw response from the model
|
72
|
+
)
|
73
|
+
|
74
|
+
@property
|
75
|
+
def prompt_constructor(self) -> PromptConstructor:
|
76
|
+
"""Return the prompt constructor."""
|
77
|
+
return PromptConstructor(self, prompt_plan=self.prompt_plan)
|
78
|
+
|
79
|
+
def to_dict(self):
|
80
|
+
attributes = [
|
81
|
+
"agent",
|
82
|
+
"question",
|
83
|
+
"scenario",
|
84
|
+
"model",
|
85
|
+
"memory_plan",
|
86
|
+
"current_answers",
|
87
|
+
"iteration",
|
88
|
+
"additional_prompt_data",
|
89
|
+
"cache",
|
90
|
+
"sidecar_model",
|
91
|
+
"survey",
|
92
|
+
]
|
93
|
+
|
94
|
+
def serialize_attribute(attr):
|
95
|
+
value = getattr(self, attr)
|
96
|
+
if value is None:
|
97
|
+
return None
|
98
|
+
if hasattr(value, "to_dict"):
|
99
|
+
return value.to_dict()
|
100
|
+
if isinstance(value, (int, float, str, bool, dict, list)):
|
101
|
+
return value
|
102
|
+
return str(value)
|
103
|
+
|
104
|
+
return {attr: serialize_attribute(attr) for attr in attributes}
|
105
|
+
|
106
|
+
@classmethod
|
107
|
+
def from_dict(cls, data):
|
108
|
+
from edsl.agents.Agent import Agent
|
109
|
+
from edsl.questions import QuestionBase
|
110
|
+
from edsl.scenarios.Scenario import Scenario
|
111
|
+
from edsl.surveys.MemoryPlan import MemoryPlan
|
112
|
+
from edsl.language_models.LanguageModel import LanguageModel
|
113
|
+
from edsl.surveys.Survey import Survey
|
114
|
+
|
115
|
+
agent = Agent.from_dict(data["agent"])
|
116
|
+
question = QuestionBase.from_dict(data["question"])
|
117
|
+
scenario = Scenario.from_dict(data["scenario"])
|
118
|
+
model = LanguageModel.from_dict(data["model"])
|
119
|
+
memory_plan = MemoryPlan.from_dict(data["memory_plan"])
|
120
|
+
survey = Survey.from_dict(data["survey"])
|
121
|
+
current_answers = data["current_answers"]
|
122
|
+
iteration = data["iteration"]
|
123
|
+
additional_prompt_data = data["additional_prompt_data"]
|
124
|
+
cache = Cache.from_dict(data["cache"])
|
125
|
+
|
126
|
+
if data["sidecar_model"] is None:
|
127
|
+
sidecar_model = None
|
128
|
+
else:
|
129
|
+
sidecar_model = LanguageModel.from_dict(data["sidecar_model"])
|
130
|
+
|
131
|
+
return cls(
|
132
|
+
agent=agent,
|
133
|
+
question=question,
|
134
|
+
scenario=scenario,
|
135
|
+
model=model,
|
136
|
+
memory_plan=memory_plan,
|
137
|
+
current_answers=current_answers,
|
138
|
+
survey=survey,
|
139
|
+
iteration=iteration,
|
140
|
+
additional_prompt_data=additional_prompt_data,
|
141
|
+
cache=cache,
|
142
|
+
sidecar_model=sidecar_model,
|
143
|
+
)
|
144
|
+
|
145
|
+
def __repr__(self) -> str:
|
146
|
+
"""Return a string representation of the Invigilator.
|
147
|
+
|
148
|
+
>>> InvigilatorBase.example().__repr__()
|
149
|
+
'InvigilatorExample(...)'
|
150
|
+
|
151
|
+
"""
|
152
|
+
return f"{self.__class__.__name__}(agent={repr(self.agent)}, question={repr(self.question)}, scneario={repr(self.scenario)}, model={repr(self.model)}, memory_plan={repr(self.memory_plan)}, current_answers={repr(self.current_answers)}, iteration{repr(self.iteration)}, additional_prompt_data={repr(self.additional_prompt_data)}, cache={repr(self.cache)}, sidecarmodel={repr(self.sidecar_model)})"
|
153
|
+
|
154
|
+
def get_failed_task_result(self, failure_reason) -> EDSLResultObjectInput:
|
155
|
+
"""Return an AgentResponseDict used in case the question-asking fails.
|
156
|
+
|
157
|
+
Possible reasons include:
|
158
|
+
- Legimately skipped because of skip logic
|
159
|
+
- Failed to get response from the model
|
160
|
+
|
161
|
+
"""
|
162
|
+
data = {
|
163
|
+
"answer": None,
|
164
|
+
"generated_tokens": None,
|
165
|
+
"comment": failure_reason,
|
166
|
+
"question_name": self.question.question_name,
|
167
|
+
"prompts": self.get_prompts(),
|
168
|
+
"cached_response": None,
|
169
|
+
"raw_model_response": None,
|
170
|
+
"cache_used": None,
|
171
|
+
"cache_key": None,
|
172
|
+
}
|
173
|
+
return EDSLResultObjectInput(**data)
|
174
|
+
|
175
|
+
def get_prompts(self) -> Dict[str, Prompt]:
|
176
|
+
"""Return the prompt used."""
|
177
|
+
|
178
|
+
return {
|
179
|
+
"user_prompt": Prompt("NA"),
|
180
|
+
"system_prompt": Prompt("NA"),
|
181
|
+
}
|
182
|
+
|
183
|
+
@abstractmethod
|
184
|
+
async def async_answer_question(self):
|
185
|
+
"""Asnwer a question."""
|
186
|
+
pass
|
187
|
+
|
188
|
+
@jupyter_nb_handler
|
189
|
+
def answer_question(self) -> Coroutine:
|
190
|
+
"""Return a function that gets the answers to the question."""
|
191
|
+
|
192
|
+
async def main():
|
193
|
+
"""Return the answer to the question."""
|
194
|
+
results = await asyncio.gather(self.async_answer_question())
|
195
|
+
return results[0] # Since there's only one task, return its result
|
196
|
+
|
197
|
+
return main()
|
198
|
+
|
199
|
+
@classmethod
|
200
|
+
def example(
|
201
|
+
cls, throw_an_exception=False, question=None, scenario=None, survey=None
|
202
|
+
) -> "InvigilatorBase":
|
203
|
+
"""Return an example invigilator.
|
204
|
+
|
205
|
+
>>> InvigilatorBase.example()
|
206
|
+
InvigilatorExample(...)
|
207
|
+
|
208
|
+
"""
|
209
|
+
from edsl.agents.Agent import Agent
|
210
|
+
from edsl.questions import QuestionMultipleChoice
|
211
|
+
from edsl.scenarios.Scenario import Scenario
|
212
|
+
from edsl.language_models import LanguageModel
|
213
|
+
from edsl.surveys.MemoryPlan import MemoryPlan
|
214
|
+
|
215
|
+
from edsl.enums import InferenceServiceType
|
216
|
+
|
217
|
+
from edsl import Model
|
218
|
+
|
219
|
+
model = Model("test", canned_response="SPAM!")
|
220
|
+
|
221
|
+
if throw_an_exception:
|
222
|
+
model.throw_an_exception = True
|
223
|
+
agent = Agent.example()
|
224
|
+
# question = QuestionMultipleChoice.example()
|
225
|
+
from edsl.surveys import Survey
|
226
|
+
|
227
|
+
if not survey:
|
228
|
+
survey = Survey.example()
|
229
|
+
|
230
|
+
if question not in survey.questions and question is not None:
|
231
|
+
survey.add_question(question)
|
232
|
+
|
233
|
+
question = question or survey.questions[0]
|
234
|
+
scenario = scenario or Scenario.example()
|
235
|
+
# memory_plan = None #memory_plan = MemoryPlan()
|
236
|
+
from edsl import Survey
|
237
|
+
|
238
|
+
memory_plan = MemoryPlan(survey=survey)
|
239
|
+
current_answers = None
|
240
|
+
from edsl.agents.PromptConstructor import PromptConstructor
|
241
|
+
|
242
|
+
class InvigilatorExample(InvigilatorBase):
|
243
|
+
"""An example invigilator."""
|
244
|
+
|
245
|
+
async def async_answer_question(self):
|
246
|
+
"""Answer a question."""
|
247
|
+
return await self.model.async_execute_model_call(
|
248
|
+
user_prompt="Hello", system_prompt="Hi"
|
249
|
+
)
|
250
|
+
|
251
|
+
return InvigilatorExample(
|
252
|
+
agent=agent,
|
253
|
+
question=question,
|
254
|
+
scenario=scenario,
|
255
|
+
survey=survey,
|
256
|
+
model=model,
|
257
|
+
memory_plan=memory_plan,
|
258
|
+
current_answers=current_answers,
|
259
|
+
)
|
260
|
+
|
261
|
+
|
262
|
+
if __name__ == "__main__":
|
263
|
+
import doctest
|
264
|
+
|
265
|
+
doctest.testmod(optionflags=doctest.ELLIPSIS)
|