edsl 0.1.39.dev2__py3-none-any.whl → 0.1.39.dev3__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 -385
- edsl/BaseDiff.py +260 -260
- edsl/TemplateLoader.py +24 -24
- edsl/__init__.py +49 -57
- edsl/__version__.py +1 -1
- edsl/agents/Agent.py +867 -1079
- edsl/agents/AgentList.py +413 -551
- edsl/agents/Invigilator.py +233 -285
- edsl/agents/InvigilatorBase.py +270 -254
- edsl/agents/PromptConstructor.py +354 -252
- edsl/agents/__init__.py +3 -2
- 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 -279
- edsl/config.py +157 -177
- edsl/conversation/Conversation.py +290 -290
- edsl/conversation/car_buying.py +58 -59
- 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 -1090
- edsl/coop/utils.py +131 -131
- edsl/data/Cache.py +555 -562
- edsl/data/CacheEntry.py +233 -230
- edsl/data/CacheHandler.py +149 -170
- edsl/data/RemoteCacheSync.py +78 -78
- edsl/data/SQLiteDict.py +292 -292
- edsl/data/__init__.py +4 -5
- edsl/data/orm.py +10 -10
- edsl/data_transfer_models.py +73 -74
- edsl/enums.py +175 -195
- edsl/exceptions/BaseException.py +21 -21
- edsl/exceptions/__init__.py +54 -54
- edsl/exceptions/agents.py +42 -54
- edsl/exceptions/cache.py +5 -5
- 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 -109
- edsl/exceptions/results.py +29 -29
- edsl/exceptions/scenarios.py +22 -29
- edsl/exceptions/surveys.py +37 -37
- edsl/inference_services/AnthropicService.py +87 -84
- edsl/inference_services/AwsBedrock.py +120 -118
- edsl/inference_services/AzureAI.py +217 -215
- edsl/inference_services/DeepInfraService.py +18 -18
- edsl/inference_services/GoogleService.py +148 -139
- edsl/inference_services/GroqService.py +20 -20
- edsl/inference_services/InferenceServiceABC.py +147 -80
- edsl/inference_services/InferenceServicesCollection.py +97 -122
- edsl/inference_services/MistralAIService.py +123 -120
- edsl/inference_services/OllamaService.py +18 -18
- edsl/inference_services/OpenAIService.py +224 -221
- edsl/inference_services/PerplexityService.py +163 -160
- edsl/inference_services/TestService.py +89 -92
- 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 -41
- edsl/inference_services/write_available.py +10 -10
- edsl/jobs/Answers.py +56 -43
- edsl/jobs/Jobs.py +898 -757
- edsl/jobs/JobsChecks.py +147 -172
- edsl/jobs/JobsPrompts.py +268 -270
- edsl/jobs/JobsRemoteInferenceHandler.py +239 -287
- edsl/jobs/__init__.py +1 -1
- edsl/jobs/buckets/BucketCollection.py +63 -104
- edsl/jobs/buckets/ModelBuckets.py +65 -65
- edsl/jobs/buckets/TokenBucket.py +251 -283
- edsl/jobs/interviews/Interview.py +661 -358
- 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 -421
- edsl/jobs/runners/JobsRunnerStatus.py +330 -330
- edsl/jobs/tasks/QuestionTaskCreator.py +242 -244
- edsl/jobs/tasks/TaskCreators.py +64 -64
- edsl/jobs/tasks/TaskHistory.py +450 -449
- edsl/jobs/tasks/TaskStatusLog.py +23 -23
- edsl/jobs/tasks/task_status_enum.py +163 -161
- edsl/jobs/tokens/InterviewTokenUsage.py +27 -27
- edsl/jobs/tokens/TokenUsage.py +34 -34
- edsl/language_models/KeyLookup.py +30 -0
- edsl/language_models/LanguageModel.py +668 -571
- edsl/language_models/ModelList.py +155 -153
- edsl/language_models/RegisterLanguageModelsMeta.py +184 -184
- edsl/language_models/__init__.py +3 -2
- edsl/language_models/fake_openai_call.py +15 -15
- edsl/language_models/fake_openai_service.py +61 -61
- edsl/language_models/registry.py +190 -180
- edsl/language_models/repair.py +156 -156
- edsl/language_models/unused/ReplicateBase.py +83 -0
- edsl/language_models/utilities.py +64 -65
- edsl/notebooks/Notebook.py +258 -263
- edsl/notebooks/__init__.py +1 -1
- edsl/prompts/Prompt.py +362 -352
- edsl/prompts/__init__.py +2 -2
- edsl/questions/AnswerValidatorMixin.py +289 -334
- edsl/questions/QuestionBase.py +664 -509
- edsl/questions/QuestionBaseGenMixin.py +161 -165
- edsl/questions/QuestionBasePromptsMixin.py +217 -221
- edsl/questions/QuestionBudget.py +227 -227
- edsl/questions/QuestionCheckBox.py +359 -359
- edsl/questions/QuestionExtract.py +182 -182
- edsl/questions/QuestionFreeText.py +114 -113
- edsl/questions/QuestionFunctional.py +166 -166
- edsl/questions/QuestionList.py +231 -229
- edsl/questions/QuestionMultipleChoice.py +286 -330
- edsl/questions/QuestionNumerical.py +153 -151
- edsl/questions/QuestionRank.py +324 -314
- edsl/questions/Quick.py +41 -41
- edsl/questions/RegisterQuestionsMeta.py +71 -71
- edsl/questions/ResponseValidatorABC.py +174 -200
- edsl/questions/SimpleAskMixin.py +73 -74
- edsl/questions/__init__.py +26 -27
- 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 -90
- edsl/questions/derived/QuestionTopK.py +93 -93
- edsl/questions/derived/QuestionYesNo.py +82 -82
- edsl/questions/descriptors.py +413 -427
- 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 -177
- 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 -108
- edsl/results/Dataset.py +424 -587
- edsl/results/DatasetExportMixin.py +731 -653
- edsl/results/DatasetTree.py +275 -295
- edsl/results/Result.py +465 -451
- edsl/results/Results.py +1165 -1172
- edsl/results/ResultsDBMixin.py +238 -0
- edsl/results/ResultsExportMixin.py +43 -45
- edsl/results/ResultsFetchMixin.py +33 -33
- edsl/results/ResultsGGMixin.py +121 -121
- edsl/results/ResultsToolsMixin.py +98 -98
- edsl/results/Selector.py +135 -145
- edsl/results/TableDisplay.py +198 -125
- edsl/results/__init__.py +2 -2
- edsl/results/table_display.css +77 -77
- edsl/results/tree_explore.py +115 -115
- edsl/scenarios/FileStore.py +632 -511
- edsl/scenarios/Scenario.py +601 -498
- edsl/scenarios/ScenarioHtmlMixin.py +64 -65
- edsl/scenarios/ScenarioJoin.py +127 -131
- edsl/scenarios/ScenarioList.py +1287 -1430
- edsl/scenarios/ScenarioListExportMixin.py +52 -45
- edsl/scenarios/ScenarioListPdfMixin.py +261 -239
- edsl/scenarios/__init__.py +4 -3
- 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 -521
- 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 -327
- edsl/surveys/RuleCollection.py +387 -385
- edsl/surveys/Survey.py +1801 -1229
- edsl/surveys/SurveyCSS.py +261 -273
- edsl/surveys/SurveyExportMixin.py +259 -259
- edsl/surveys/{SurveyFlowVisualization.py → SurveyFlowVisualizationMixin.py} +179 -181
- edsl/surveys/SurveyQualtricsImport.py +284 -284
- edsl/surveys/__init__.py +3 -5
- edsl/surveys/base.py +53 -53
- edsl/surveys/descriptors.py +56 -60
- edsl/surveys/instructions/ChangeInstruction.py +49 -48
- edsl/surveys/instructions/Instruction.py +65 -56
- edsl/surveys/instructions/InstructionCollection.py +77 -82
- 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 -19
- 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/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 -436
- {edsl-0.1.39.dev2.dist-info → edsl-0.1.39.dev3.dist-info}/LICENSE +21 -21
- {edsl-0.1.39.dev2.dist-info → edsl-0.1.39.dev3.dist-info}/METADATA +10 -12
- edsl-0.1.39.dev3.dist-info/RECORD +277 -0
- edsl/agents/QuestionInstructionPromptBuilder.py +0 -128
- edsl/agents/QuestionOptionProcessor.py +0 -172
- edsl/agents/QuestionTemplateReplacementsBuilder.py +0 -137
- edsl/coop/CoopFunctionsMixin.py +0 -15
- edsl/coop/ExpectedParrotKeyHandler.py +0 -125
- edsl/exceptions/inference_services.py +0 -5
- edsl/inference_services/AvailableModelCacheHandler.py +0 -184
- edsl/inference_services/AvailableModelFetcher.py +0 -209
- edsl/inference_services/ServiceAvailability.py +0 -135
- edsl/inference_services/data_structures.py +0 -62
- edsl/jobs/AnswerQuestionFunctionConstructor.py +0 -188
- edsl/jobs/FetchInvigilator.py +0 -40
- edsl/jobs/InterviewTaskManager.py +0 -98
- edsl/jobs/InterviewsConstructor.py +0 -48
- edsl/jobs/JobsComponentConstructor.py +0 -189
- edsl/jobs/JobsRemoteInferenceLogger.py +0 -239
- edsl/jobs/RequestTokenEstimator.py +0 -30
- edsl/jobs/buckets/TokenBucketAPI.py +0 -211
- edsl/jobs/buckets/TokenBucketClient.py +0 -191
- edsl/jobs/decorators.py +0 -35
- edsl/jobs/jobs_status_enums.py +0 -9
- edsl/jobs/loggers/HTMLTableJobLogger.py +0 -304
- edsl/language_models/ComputeCost.py +0 -63
- edsl/language_models/PriceManager.py +0 -127
- edsl/language_models/RawResponseHandler.py +0 -106
- edsl/language_models/ServiceDataSources.py +0 -0
- edsl/language_models/key_management/KeyLookup.py +0 -63
- edsl/language_models/key_management/KeyLookupBuilder.py +0 -273
- edsl/language_models/key_management/KeyLookupCollection.py +0 -38
- edsl/language_models/key_management/__init__.py +0 -0
- edsl/language_models/key_management/models.py +0 -131
- edsl/notebooks/NotebookToLaTeX.py +0 -142
- edsl/questions/ExceptionExplainer.py +0 -77
- edsl/questions/HTMLQuestion.py +0 -103
- edsl/questions/LoopProcessor.py +0 -149
- edsl/questions/QuestionMatrix.py +0 -265
- edsl/questions/ResponseValidatorFactory.py +0 -28
- edsl/questions/templates/matrix/__init__.py +0 -1
- edsl/questions/templates/matrix/answering_instructions.jinja +0 -5
- edsl/questions/templates/matrix/question_presentation.jinja +0 -20
- edsl/results/MarkdownToDocx.py +0 -122
- edsl/results/MarkdownToPDF.py +0 -111
- edsl/results/TextEditor.py +0 -50
- edsl/results/smart_objects.py +0 -96
- edsl/results/table_data_class.py +0 -12
- edsl/results/table_renderers.py +0 -118
- edsl/scenarios/ConstructDownloadLink.py +0 -109
- edsl/scenarios/DirectoryScanner.py +0 -96
- edsl/scenarios/DocumentChunker.py +0 -102
- edsl/scenarios/DocxScenario.py +0 -16
- edsl/scenarios/PdfExtractor.py +0 -40
- edsl/scenarios/ScenarioSelector.py +0 -156
- edsl/scenarios/file_methods.py +0 -85
- edsl/scenarios/handlers/__init__.py +0 -13
- edsl/scenarios/handlers/csv.py +0 -38
- edsl/scenarios/handlers/docx.py +0 -76
- edsl/scenarios/handlers/html.py +0 -37
- edsl/scenarios/handlers/json.py +0 -111
- edsl/scenarios/handlers/latex.py +0 -5
- edsl/scenarios/handlers/md.py +0 -51
- edsl/scenarios/handlers/pdf.py +0 -68
- edsl/scenarios/handlers/png.py +0 -39
- edsl/scenarios/handlers/pptx.py +0 -105
- edsl/scenarios/handlers/py.py +0 -294
- edsl/scenarios/handlers/sql.py +0 -313
- edsl/scenarios/handlers/sqlite.py +0 -149
- edsl/scenarios/handlers/txt.py +0 -33
- edsl/surveys/ConstructDAG.py +0 -92
- edsl/surveys/EditSurvey.py +0 -221
- edsl/surveys/InstructionHandler.py +0 -100
- edsl/surveys/MemoryManagement.py +0 -72
- edsl/surveys/RuleManager.py +0 -172
- edsl/surveys/Simulator.py +0 -75
- edsl/surveys/SurveyToApp.py +0 -141
- edsl/utilities/PrettyList.py +0 -56
- edsl/utilities/is_notebook.py +0 -18
- edsl/utilities/is_valid_variable_name.py +0 -11
- edsl/utilities/remove_edsl_version.py +0 -24
- edsl-0.1.39.dev2.dist-info/RECORD +0 -352
- {edsl-0.1.39.dev2.dist-info → edsl-0.1.39.dev3.dist-info}/WHEEL +0 -0
edsl/questions/SimpleAskMixin.py
CHANGED
@@ -1,74 +1,73 @@
|
|
1
|
-
import
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
console
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
return format_output(response)
|
1
|
+
from rich.table import Table
|
2
|
+
from rich.console import Console
|
3
|
+
import math
|
4
|
+
|
5
|
+
|
6
|
+
def logprob_to_prob(logprob):
|
7
|
+
if logprob is None:
|
8
|
+
return None
|
9
|
+
return math.exp(logprob)
|
10
|
+
|
11
|
+
|
12
|
+
def format_output(data):
|
13
|
+
content = data["choices"][0]["logprobs"]["content"]
|
14
|
+
table = Table(show_header=True, header_style="bold magenta")
|
15
|
+
|
16
|
+
# First pass to determine the maximum number of top tokens
|
17
|
+
max_tokens = max(len(item["top_logprobs"]) for item in content)
|
18
|
+
|
19
|
+
# Set up the table columns
|
20
|
+
table.add_column("Token", style="bold")
|
21
|
+
for i in range(max_tokens):
|
22
|
+
table.add_column(f"Top Token {i+1}")
|
23
|
+
|
24
|
+
for item in content:
|
25
|
+
token = item["token"].strip()
|
26
|
+
top_tokens = [
|
27
|
+
(top["token"].strip(), logprob_to_prob(top.get("logprob")))
|
28
|
+
for top in item["top_logprobs"]
|
29
|
+
]
|
30
|
+
|
31
|
+
# Row data starts with the main token
|
32
|
+
row = [token]
|
33
|
+
|
34
|
+
# Add each top token with coloring based on probability
|
35
|
+
for token, probability in top_tokens:
|
36
|
+
if probability is not None:
|
37
|
+
# Assign color based on probability value
|
38
|
+
if probability > 0.5:
|
39
|
+
color = "green"
|
40
|
+
elif probability > 0.2:
|
41
|
+
color = "yellow"
|
42
|
+
else:
|
43
|
+
color = "red"
|
44
|
+
formatted_token = f"[{color}]{token} ({probability:.2f})[/]"
|
45
|
+
else:
|
46
|
+
formatted_token = f"{token} (N/A)"
|
47
|
+
row.append(formatted_token)
|
48
|
+
|
49
|
+
# Ensure row has enough columns
|
50
|
+
while len(row) < max_tokens + 1:
|
51
|
+
row.append("")
|
52
|
+
|
53
|
+
table.add_row(*row)
|
54
|
+
|
55
|
+
console = Console()
|
56
|
+
console.print(table)
|
57
|
+
|
58
|
+
|
59
|
+
class SimpleAskMixin:
|
60
|
+
# def simple_ask(self, question: QuestionBase, system_prompt = "You are a helpful agent pretending to be a human.", top_logprobs = 2):
|
61
|
+
|
62
|
+
def simple_ask(
|
63
|
+
self,
|
64
|
+
model=None,
|
65
|
+
system_prompt="You are a helpful agent pretending to be a human. Do not break character",
|
66
|
+
top_logprobs=4,
|
67
|
+
):
|
68
|
+
from edsl import Model
|
69
|
+
|
70
|
+
if model is None:
|
71
|
+
model = Model()
|
72
|
+
response = model.simple_ask(self, system_prompt, top_logprobs)
|
73
|
+
return format_output(response)
|
edsl/questions/__init__.py
CHANGED
@@ -1,27 +1,26 @@
|
|
1
|
-
# Schemas
|
2
|
-
from edsl.questions.settings import Settings
|
3
|
-
from edsl.questions.RegisterQuestionsMeta import RegisterQuestionsMeta
|
4
|
-
|
5
|
-
# Base Class
|
6
|
-
from edsl.questions.QuestionBase import QuestionBase
|
7
|
-
|
8
|
-
# Core Questions
|
9
|
-
from edsl.questions.QuestionCheckBox import QuestionCheckBox
|
10
|
-
from edsl.questions.QuestionExtract import QuestionExtract
|
11
|
-
from edsl.questions.QuestionFreeText import QuestionFreeText
|
12
|
-
from edsl.questions.QuestionFunctional import QuestionFunctional
|
13
|
-
from edsl.questions.QuestionList import QuestionList
|
14
|
-
from edsl.questions.
|
15
|
-
from edsl.questions.
|
16
|
-
from edsl.questions.
|
17
|
-
from edsl.questions.
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
from edsl.questions.derived.
|
22
|
-
from edsl.questions.derived.
|
23
|
-
from edsl.questions.derived.
|
24
|
-
|
25
|
-
|
26
|
-
#
|
27
|
-
# from edsl.questions.compose_questions import compose_questions
|
1
|
+
# Schemas
|
2
|
+
from edsl.questions.settings import Settings
|
3
|
+
from edsl.questions.RegisterQuestionsMeta import RegisterQuestionsMeta
|
4
|
+
|
5
|
+
# Base Class
|
6
|
+
from edsl.questions.QuestionBase import QuestionBase
|
7
|
+
|
8
|
+
# Core Questions
|
9
|
+
from edsl.questions.QuestionCheckBox import QuestionCheckBox
|
10
|
+
from edsl.questions.QuestionExtract import QuestionExtract
|
11
|
+
from edsl.questions.QuestionFreeText import QuestionFreeText
|
12
|
+
from edsl.questions.QuestionFunctional import QuestionFunctional
|
13
|
+
from edsl.questions.QuestionList import QuestionList
|
14
|
+
from edsl.questions.QuestionMultipleChoice import QuestionMultipleChoice
|
15
|
+
from edsl.questions.QuestionNumerical import QuestionNumerical
|
16
|
+
from edsl.questions.QuestionBudget import QuestionBudget
|
17
|
+
from edsl.questions.QuestionRank import QuestionRank
|
18
|
+
|
19
|
+
# # # Questions derived from core questions
|
20
|
+
from edsl.questions.derived.QuestionLikertFive import QuestionLikertFive
|
21
|
+
from edsl.questions.derived.QuestionLinearScale import QuestionLinearScale
|
22
|
+
from edsl.questions.derived.QuestionYesNo import QuestionYesNo
|
23
|
+
from edsl.questions.derived.QuestionTopK import QuestionTopK
|
24
|
+
|
25
|
+
# # Compose Questions
|
26
|
+
# from edsl.questions.compose_questions import compose_questions
|
@@ -1,98 +1,98 @@
|
|
1
|
-
"""Compose two questions where the answer to q1 is used as an input to q2."""
|
2
|
-
|
3
|
-
from edsl.questions import QuestionFunctional
|
4
|
-
from edsl.questions.QuestionBase import QuestionBase
|
5
|
-
from edsl.scenarios.Scenario import Scenario
|
6
|
-
|
7
|
-
|
8
|
-
def compose_questions(
|
9
|
-
q1: QuestionBase, q2: QuestionBase, question_name: str = None
|
10
|
-
) -> QuestionFunctional:
|
11
|
-
"""
|
12
|
-
Compose two questions where the answer to q1 is used as an input to q2.
|
13
|
-
|
14
|
-
The resulting question is a question that can be used like other questions.
|
15
|
-
Note that the same result can also be achieved in other ways:
|
16
|
-
- Using the `add_targeted_memory(q2, q1)` method in Survey
|
17
|
-
- Using the __add__ method in Question
|
18
|
-
"""
|
19
|
-
if question_name is None:
|
20
|
-
question_name = f"{q1.question_name}_{q2.question_name}"
|
21
|
-
if q1.question_name not in q2.question_text:
|
22
|
-
raise ValueError(
|
23
|
-
f"q2 requires a field not present in q1's answer. "
|
24
|
-
f"q1: {q1.question_name}, q2: {q2.question_name}"
|
25
|
-
)
|
26
|
-
|
27
|
-
def combo(
|
28
|
-
scenario: Scenario, agent_traits: dict[str, str] = None
|
29
|
-
) -> QuestionFunctional:
|
30
|
-
"""Return the answer to the second question given the answer to the first question."""
|
31
|
-
# get the answer to the first question
|
32
|
-
from edsl.agents.Agent import Agent
|
33
|
-
|
34
|
-
first_answer = (
|
35
|
-
q1.by(scenario)
|
36
|
-
.by(Agent(traits=agent_traits))
|
37
|
-
.run()
|
38
|
-
.select(q1.question_name)[0]
|
39
|
-
)
|
40
|
-
# update the scenario with the answer to the first question
|
41
|
-
scenario.update({q1.question_name: first_answer})
|
42
|
-
# get the answer to the second question
|
43
|
-
second_answer = (
|
44
|
-
q2.by(scenario)
|
45
|
-
.by(Agent(traits=agent_traits))
|
46
|
-
.run()
|
47
|
-
.select(q2.question_name)[0]
|
48
|
-
)
|
49
|
-
return second_answer
|
50
|
-
|
51
|
-
return QuestionFunctional(
|
52
|
-
question_name=question_name, question_text="functional", func=combo
|
53
|
-
)
|
54
|
-
|
55
|
-
|
56
|
-
# UNCOMMENT BELOW TO SEE HOW THIS WORKS
|
57
|
-
|
58
|
-
# if __name__ == "__main__":
|
59
|
-
# from edsl.questions import QuestionFreeText, QuestionFunctional
|
60
|
-
# from edsl.questions.compose_questions import compose_questions
|
61
|
-
# from edsl.scenarios.Scenario import Scenario
|
62
|
-
|
63
|
-
# q1 = QuestionFreeText(
|
64
|
-
# question_text="What is the capital of {{country}}", question_name="capital"
|
65
|
-
# )
|
66
|
-
# q2 = QuestionFreeText(
|
67
|
-
# question_text="What is the population of {{capital}}",
|
68
|
-
# question_name="population",
|
69
|
-
# )
|
70
|
-
# q3 = compose_questions(q1, q2)
|
71
|
-
|
72
|
-
# jobs = q3.by(
|
73
|
-
# Scenario({"country": "France"}),
|
74
|
-
# Scenario({"country": "Germany"}),
|
75
|
-
# Scenario({"country": "Greece"}),
|
76
|
-
# )
|
77
|
-
|
78
|
-
# print("Without an agent persona")
|
79
|
-
# results1 = jobs.run()
|
80
|
-
|
81
|
-
# print("Adding an agent persona")
|
82
|
-
# results2 = jobs.by(
|
83
|
-
# Agent(traits={"name": "Bob, who always mentions his travel agency."})
|
84
|
-
# ).run()
|
85
|
-
# results2.select("capital_population").table()
|
86
|
-
|
87
|
-
# q1 = QuestionFreeText(
|
88
|
-
# question_text="What is the capital of {{country}}", question_name="capital"
|
89
|
-
# )
|
90
|
-
# q2 = QuestionFreeText(
|
91
|
-
# question_text="Is this {{population}} large?", question_name="population"
|
92
|
-
# )
|
93
|
-
# q3 = compose_questions(q1, q2)
|
94
|
-
# print("Should throw an exception:")
|
95
|
-
# try:
|
96
|
-
# q3.by(Scenario({"country": "France"})).run()
|
97
|
-
# except ValueError as e:
|
98
|
-
# print(e)
|
1
|
+
"""Compose two questions where the answer to q1 is used as an input to q2."""
|
2
|
+
|
3
|
+
from edsl.questions import QuestionFunctional
|
4
|
+
from edsl.questions.QuestionBase import QuestionBase
|
5
|
+
from edsl.scenarios.Scenario import Scenario
|
6
|
+
|
7
|
+
|
8
|
+
def compose_questions(
|
9
|
+
q1: QuestionBase, q2: QuestionBase, question_name: str = None
|
10
|
+
) -> QuestionFunctional:
|
11
|
+
"""
|
12
|
+
Compose two questions where the answer to q1 is used as an input to q2.
|
13
|
+
|
14
|
+
The resulting question is a question that can be used like other questions.
|
15
|
+
Note that the same result can also be achieved in other ways:
|
16
|
+
- Using the `add_targeted_memory(q2, q1)` method in Survey
|
17
|
+
- Using the __add__ method in Question
|
18
|
+
"""
|
19
|
+
if question_name is None:
|
20
|
+
question_name = f"{q1.question_name}_{q2.question_name}"
|
21
|
+
if q1.question_name not in q2.question_text:
|
22
|
+
raise ValueError(
|
23
|
+
f"q2 requires a field not present in q1's answer. "
|
24
|
+
f"q1: {q1.question_name}, q2: {q2.question_name}"
|
25
|
+
)
|
26
|
+
|
27
|
+
def combo(
|
28
|
+
scenario: Scenario, agent_traits: dict[str, str] = None
|
29
|
+
) -> QuestionFunctional:
|
30
|
+
"""Return the answer to the second question given the answer to the first question."""
|
31
|
+
# get the answer to the first question
|
32
|
+
from edsl.agents.Agent import Agent
|
33
|
+
|
34
|
+
first_answer = (
|
35
|
+
q1.by(scenario)
|
36
|
+
.by(Agent(traits=agent_traits))
|
37
|
+
.run()
|
38
|
+
.select(q1.question_name)[0]
|
39
|
+
)
|
40
|
+
# update the scenario with the answer to the first question
|
41
|
+
scenario.update({q1.question_name: first_answer})
|
42
|
+
# get the answer to the second question
|
43
|
+
second_answer = (
|
44
|
+
q2.by(scenario)
|
45
|
+
.by(Agent(traits=agent_traits))
|
46
|
+
.run()
|
47
|
+
.select(q2.question_name)[0]
|
48
|
+
)
|
49
|
+
return second_answer
|
50
|
+
|
51
|
+
return QuestionFunctional(
|
52
|
+
question_name=question_name, question_text="functional", func=combo
|
53
|
+
)
|
54
|
+
|
55
|
+
|
56
|
+
# UNCOMMENT BELOW TO SEE HOW THIS WORKS
|
57
|
+
|
58
|
+
# if __name__ == "__main__":
|
59
|
+
# from edsl.questions import QuestionFreeText, QuestionFunctional
|
60
|
+
# from edsl.questions.compose_questions import compose_questions
|
61
|
+
# from edsl.scenarios.Scenario import Scenario
|
62
|
+
|
63
|
+
# q1 = QuestionFreeText(
|
64
|
+
# question_text="What is the capital of {{country}}", question_name="capital"
|
65
|
+
# )
|
66
|
+
# q2 = QuestionFreeText(
|
67
|
+
# question_text="What is the population of {{capital}}",
|
68
|
+
# question_name="population",
|
69
|
+
# )
|
70
|
+
# q3 = compose_questions(q1, q2)
|
71
|
+
|
72
|
+
# jobs = q3.by(
|
73
|
+
# Scenario({"country": "France"}),
|
74
|
+
# Scenario({"country": "Germany"}),
|
75
|
+
# Scenario({"country": "Greece"}),
|
76
|
+
# )
|
77
|
+
|
78
|
+
# print("Without an agent persona")
|
79
|
+
# results1 = jobs.run()
|
80
|
+
|
81
|
+
# print("Adding an agent persona")
|
82
|
+
# results2 = jobs.by(
|
83
|
+
# Agent(traits={"name": "Bob, who always mentions his travel agency."})
|
84
|
+
# ).run()
|
85
|
+
# results2.select("capital_population").table()
|
86
|
+
|
87
|
+
# q1 = QuestionFreeText(
|
88
|
+
# question_text="What is the capital of {{country}}", question_name="capital"
|
89
|
+
# )
|
90
|
+
# q2 = QuestionFreeText(
|
91
|
+
# question_text="Is this {{population}} large?", question_name="population"
|
92
|
+
# )
|
93
|
+
# q3 = compose_questions(q1, q2)
|
94
|
+
# print("Should throw an exception:")
|
95
|
+
# try:
|
96
|
+
# q3.by(Scenario({"country": "France"})).run()
|
97
|
+
# except ValueError as e:
|
98
|
+
# print(e)
|
edsl/questions/decorators.py
CHANGED
@@ -1,21 +1,21 @@
|
|
1
|
-
from typing import Optional, Callable, TypeVar
|
2
|
-
|
3
|
-
T = TypeVar("T")
|
4
|
-
|
5
|
-
|
6
|
-
def inject_exception(func: Callable[..., T]) -> Callable[..., T]:
|
7
|
-
def wrapper(
|
8
|
-
cls,
|
9
|
-
exception_to_throw: Optional[Exception] = None,
|
10
|
-
override_answer: Optional[dict] = None,
|
11
|
-
*args,
|
12
|
-
**kwargs
|
13
|
-
) -> T:
|
14
|
-
base_instance = func(cls, *args, **kwargs)
|
15
|
-
if exception_to_throw:
|
16
|
-
base_instance.exception_to_throw = exception_to_throw
|
17
|
-
if override_answer:
|
18
|
-
base_instance.override_answer = override_answer
|
19
|
-
return base_instance
|
20
|
-
|
21
|
-
return wrapper
|
1
|
+
from typing import Optional, Callable, TypeVar
|
2
|
+
|
3
|
+
T = TypeVar("T")
|
4
|
+
|
5
|
+
|
6
|
+
def inject_exception(func: Callable[..., T]) -> Callable[..., T]:
|
7
|
+
def wrapper(
|
8
|
+
cls,
|
9
|
+
exception_to_throw: Optional[Exception] = None,
|
10
|
+
override_answer: Optional[dict] = None,
|
11
|
+
*args,
|
12
|
+
**kwargs
|
13
|
+
) -> T:
|
14
|
+
base_instance = func(cls, *args, **kwargs)
|
15
|
+
if exception_to_throw:
|
16
|
+
base_instance.exception_to_throw = exception_to_throw
|
17
|
+
if override_answer:
|
18
|
+
base_instance.override_answer = override_answer
|
19
|
+
return base_instance
|
20
|
+
|
21
|
+
return wrapper
|
@@ -1,76 +1,76 @@
|
|
1
|
-
from __future__ import annotations
|
2
|
-
from typing import Optional
|
3
|
-
from edsl.questions.QuestionMultipleChoice import QuestionMultipleChoice
|
4
|
-
|
5
|
-
from edsl.questions.decorators import inject_exception
|
6
|
-
|
7
|
-
|
8
|
-
class QuestionLikertFive(QuestionMultipleChoice):
|
9
|
-
"""This question prompts the agent to respond to a statement on a 5-point Likert scale."""
|
10
|
-
|
11
|
-
question_type = "likert_five"
|
12
|
-
likert_options: list[str] = [
|
13
|
-
"Strongly disagree",
|
14
|
-
"Disagree",
|
15
|
-
"Neutral",
|
16
|
-
"Agree",
|
17
|
-
"Strongly agree",
|
18
|
-
]
|
19
|
-
|
20
|
-
def __init__(
|
21
|
-
self,
|
22
|
-
question_name: str,
|
23
|
-
question_text: str,
|
24
|
-
question_options: Optional[list[str]] = likert_options,
|
25
|
-
answering_instructions: Optional[str] = None,
|
26
|
-
question_presentation: Optional[str] = None,
|
27
|
-
include_comment: bool = True,
|
28
|
-
):
|
29
|
-
"""Initialize the question.
|
30
|
-
|
31
|
-
:param question_name: The name of the question.
|
32
|
-
:param question_text: The text of the question.
|
33
|
-
:param question_options: The options the respondent should select from (list of strings). If not provided, the default Likert options are used (['Strongly disagree', 'Disagree', 'Neutral', 'Agree', 'Strongly agree']). To view them, run `QuestionLikertFive.likert_options`.
|
34
|
-
"""
|
35
|
-
super().__init__(
|
36
|
-
question_name=question_name,
|
37
|
-
question_text=question_text,
|
38
|
-
question_options=question_options,
|
39
|
-
use_code=False,
|
40
|
-
include_comment=include_comment,
|
41
|
-
answering_instructions=answering_instructions,
|
42
|
-
question_presentation=question_presentation,
|
43
|
-
)
|
44
|
-
|
45
|
-
@classmethod
|
46
|
-
@inject_exception
|
47
|
-
def example(cls) -> QuestionLikertFive:
|
48
|
-
"""Return an example question."""
|
49
|
-
return cls(
|
50
|
-
question_name="happy_raining",
|
51
|
-
question_text="I'm only happy when it rains.",
|
52
|
-
)
|
53
|
-
|
54
|
-
|
55
|
-
def main():
|
56
|
-
"""Test QuestionLikertFive."""
|
57
|
-
from edsl.questions.derived.QuestionLikertFive import QuestionLikertFive
|
58
|
-
|
59
|
-
q = QuestionLikertFive.example()
|
60
|
-
q.question_text
|
61
|
-
q.question_options
|
62
|
-
q.question_name
|
63
|
-
# validate an answer
|
64
|
-
q._validate_answer({"answer": 0, "comment": "I like custard"})
|
65
|
-
# translate answer code
|
66
|
-
q._translate_answer_code_to_answer(0, {})
|
67
|
-
q._simulate_answer()
|
68
|
-
q._simulate_answer(human_readable=False)
|
69
|
-
q._validate_answer(q._simulate_answer(human_readable=False))
|
70
|
-
# serialization (inherits from Question)
|
71
|
-
q.to_dict()
|
72
|
-
assert q.from_dict(q.to_dict()) == q
|
73
|
-
|
74
|
-
import doctest
|
75
|
-
|
76
|
-
doctest.testmod(optionflags=doctest.ELLIPSIS)
|
1
|
+
from __future__ import annotations
|
2
|
+
from typing import Optional
|
3
|
+
from edsl.questions.QuestionMultipleChoice import QuestionMultipleChoice
|
4
|
+
|
5
|
+
from edsl.questions.decorators import inject_exception
|
6
|
+
|
7
|
+
|
8
|
+
class QuestionLikertFive(QuestionMultipleChoice):
|
9
|
+
"""This question prompts the agent to respond to a statement on a 5-point Likert scale."""
|
10
|
+
|
11
|
+
question_type = "likert_five"
|
12
|
+
likert_options: list[str] = [
|
13
|
+
"Strongly disagree",
|
14
|
+
"Disagree",
|
15
|
+
"Neutral",
|
16
|
+
"Agree",
|
17
|
+
"Strongly agree",
|
18
|
+
]
|
19
|
+
|
20
|
+
def __init__(
|
21
|
+
self,
|
22
|
+
question_name: str,
|
23
|
+
question_text: str,
|
24
|
+
question_options: Optional[list[str]] = likert_options,
|
25
|
+
answering_instructions: Optional[str] = None,
|
26
|
+
question_presentation: Optional[str] = None,
|
27
|
+
include_comment: bool = True,
|
28
|
+
):
|
29
|
+
"""Initialize the question.
|
30
|
+
|
31
|
+
:param question_name: The name of the question.
|
32
|
+
:param question_text: The text of the question.
|
33
|
+
:param question_options: The options the respondent should select from (list of strings). If not provided, the default Likert options are used (['Strongly disagree', 'Disagree', 'Neutral', 'Agree', 'Strongly agree']). To view them, run `QuestionLikertFive.likert_options`.
|
34
|
+
"""
|
35
|
+
super().__init__(
|
36
|
+
question_name=question_name,
|
37
|
+
question_text=question_text,
|
38
|
+
question_options=question_options,
|
39
|
+
use_code=False,
|
40
|
+
include_comment=include_comment,
|
41
|
+
answering_instructions=answering_instructions,
|
42
|
+
question_presentation=question_presentation,
|
43
|
+
)
|
44
|
+
|
45
|
+
@classmethod
|
46
|
+
@inject_exception
|
47
|
+
def example(cls) -> QuestionLikertFive:
|
48
|
+
"""Return an example question."""
|
49
|
+
return cls(
|
50
|
+
question_name="happy_raining",
|
51
|
+
question_text="I'm only happy when it rains.",
|
52
|
+
)
|
53
|
+
|
54
|
+
|
55
|
+
def main():
|
56
|
+
"""Test QuestionLikertFive."""
|
57
|
+
from edsl.questions.derived.QuestionLikertFive import QuestionLikertFive
|
58
|
+
|
59
|
+
q = QuestionLikertFive.example()
|
60
|
+
q.question_text
|
61
|
+
q.question_options
|
62
|
+
q.question_name
|
63
|
+
# validate an answer
|
64
|
+
q._validate_answer({"answer": 0, "comment": "I like custard"})
|
65
|
+
# translate answer code
|
66
|
+
q._translate_answer_code_to_answer(0, {})
|
67
|
+
q._simulate_answer()
|
68
|
+
q._simulate_answer(human_readable=False)
|
69
|
+
q._validate_answer(q._simulate_answer(human_readable=False))
|
70
|
+
# serialization (inherits from Question)
|
71
|
+
q.to_dict()
|
72
|
+
assert q.from_dict(q.to_dict()) == q
|
73
|
+
|
74
|
+
import doctest
|
75
|
+
|
76
|
+
doctest.testmod(optionflags=doctest.ELLIPSIS)
|