edsl 0.1.39.dev3__py3-none-any.whl → 0.1.39.dev4__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 +413 -332
- edsl/BaseDiff.py +260 -260
- edsl/TemplateLoader.py +24 -24
- edsl/__init__.py +57 -49
- edsl/__version__.py +1 -1
- edsl/agents/Agent.py +1071 -867
- edsl/agents/AgentList.py +551 -413
- edsl/agents/Invigilator.py +284 -233
- edsl/agents/InvigilatorBase.py +257 -270
- edsl/agents/PromptConstructor.py +272 -354
- edsl/agents/QuestionInstructionPromptBuilder.py +128 -0
- edsl/agents/QuestionTemplateReplacementsBuilder.py +137 -0
- edsl/agents/__init__.py +2 -3
- edsl/agents/descriptors.py +99 -99
- edsl/agents/prompt_helpers.py +129 -129
- edsl/agents/question_option_processor.py +172 -0
- edsl/auto/AutoStudy.py +130 -117
- edsl/auto/StageBase.py +243 -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 +74 -73
- edsl/auto/SurveyCreatorPipeline.py +21 -21
- edsl/auto/utilities.py +218 -224
- edsl/base/Base.py +279 -279
- edsl/config.py +177 -157
- edsl/conversation/Conversation.py +290 -290
- edsl/conversation/car_buying.py +59 -58
- edsl/conversation/chips.py +95 -95
- edsl/conversation/mug_negotiation.py +81 -81
- edsl/conversation/next_speaker_utilities.py +93 -93
- edsl/coop/CoopFunctionsMixin.py +15 -0
- edsl/coop/ExpectedParrotKeyHandler.py +125 -0
- edsl/coop/PriceFetcher.py +54 -54
- edsl/coop/__init__.py +2 -2
- edsl/coop/coop.py +1106 -1028
- edsl/coop/utils.py +131 -131
- edsl/data/Cache.py +573 -555
- edsl/data/CacheEntry.py +230 -233
- edsl/data/CacheHandler.py +168 -149
- edsl/data/RemoteCacheSync.py +186 -78
- edsl/data/SQLiteDict.py +292 -292
- edsl/data/__init__.py +5 -4
- edsl/data/hack.py +10 -0
- edsl/data/orm.py +10 -10
- edsl/data_transfer_models.py +74 -73
- edsl/enums.py +202 -175
- edsl/exceptions/BaseException.py +21 -21
- edsl/exceptions/__init__.py +54 -54
- edsl/exceptions/agents.py +54 -42
- 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/inference_services.py +5 -0
- edsl/exceptions/jobs.py +33 -33
- edsl/exceptions/language_models.py +63 -63
- edsl/exceptions/prompts.py +15 -15
- edsl/exceptions/questions.py +109 -91
- edsl/exceptions/results.py +29 -29
- edsl/exceptions/scenarios.py +29 -22
- edsl/exceptions/surveys.py +37 -37
- edsl/inference_services/AnthropicService.py +106 -87
- edsl/inference_services/AvailableModelCacheHandler.py +184 -0
- edsl/inference_services/AvailableModelFetcher.py +215 -0
- edsl/inference_services/AwsBedrock.py +118 -120
- edsl/inference_services/AzureAI.py +215 -217
- edsl/inference_services/DeepInfraService.py +18 -18
- edsl/inference_services/GoogleService.py +143 -148
- edsl/inference_services/GroqService.py +20 -20
- edsl/inference_services/InferenceServiceABC.py +80 -147
- edsl/inference_services/InferenceServicesCollection.py +138 -97
- edsl/inference_services/MistralAIService.py +120 -123
- edsl/inference_services/OllamaService.py +18 -18
- edsl/inference_services/OpenAIService.py +236 -224
- edsl/inference_services/PerplexityService.py +160 -163
- edsl/inference_services/ServiceAvailability.py +135 -0
- edsl/inference_services/TestService.py +90 -89
- edsl/inference_services/TogetherAIService.py +172 -170
- edsl/inference_services/data_structures.py +134 -0
- 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/AnswerQuestionFunctionConstructor.py +223 -0
- edsl/jobs/Answers.py +43 -56
- edsl/jobs/FetchInvigilator.py +47 -0
- edsl/jobs/InterviewTaskManager.py +98 -0
- edsl/jobs/InterviewsConstructor.py +50 -0
- edsl/jobs/Jobs.py +823 -898
- edsl/jobs/JobsChecks.py +172 -147
- edsl/jobs/JobsComponentConstructor.py +189 -0
- edsl/jobs/JobsPrompts.py +270 -268
- edsl/jobs/JobsRemoteInferenceHandler.py +311 -239
- edsl/jobs/JobsRemoteInferenceLogger.py +239 -0
- edsl/jobs/RequestTokenEstimator.py +30 -0
- edsl/jobs/__init__.py +1 -1
- edsl/jobs/async_interview_runner.py +138 -0
- edsl/jobs/buckets/BucketCollection.py +104 -63
- edsl/jobs/buckets/ModelBuckets.py +65 -65
- edsl/jobs/buckets/TokenBucket.py +283 -251
- edsl/jobs/buckets/TokenBucketAPI.py +211 -0
- edsl/jobs/buckets/TokenBucketClient.py +191 -0
- edsl/jobs/check_survey_scenario_compatibility.py +85 -0
- edsl/jobs/data_structures.py +120 -0
- edsl/jobs/decorators.py +35 -0
- edsl/jobs/interviews/Interview.py +396 -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/jobs_status_enums.py +9 -0
- edsl/jobs/loggers/HTMLTableJobLogger.py +304 -0
- edsl/jobs/results_exceptions_handler.py +98 -0
- edsl/jobs/runners/JobsRunnerAsyncio.py +151 -466
- edsl/jobs/runners/JobsRunnerStatus.py +297 -330
- edsl/jobs/tasks/QuestionTaskCreator.py +244 -242
- edsl/jobs/tasks/TaskCreators.py +64 -64
- edsl/jobs/tasks/TaskHistory.py +470 -450
- edsl/jobs/tasks/TaskStatusLog.py +23 -23
- edsl/jobs/tasks/task_status_enum.py +161 -163
- edsl/jobs/tokens/InterviewTokenUsage.py +27 -27
- edsl/jobs/tokens/TokenUsage.py +34 -34
- edsl/language_models/ComputeCost.py +63 -0
- edsl/language_models/LanguageModel.py +626 -668
- edsl/language_models/ModelList.py +164 -155
- edsl/language_models/PriceManager.py +127 -0
- edsl/language_models/RawResponseHandler.py +106 -0
- edsl/language_models/RegisterLanguageModelsMeta.py +184 -184
- edsl/language_models/ServiceDataSources.py +0 -0
- edsl/language_models/__init__.py +2 -3
- edsl/language_models/fake_openai_call.py +15 -15
- edsl/language_models/fake_openai_service.py +61 -61
- edsl/language_models/key_management/KeyLookup.py +63 -0
- edsl/language_models/key_management/KeyLookupBuilder.py +273 -0
- edsl/language_models/key_management/KeyLookupCollection.py +38 -0
- edsl/language_models/key_management/__init__.py +0 -0
- edsl/language_models/key_management/models.py +131 -0
- edsl/language_models/model.py +256 -0
- edsl/language_models/repair.py +156 -156
- edsl/language_models/utilities.py +65 -64
- edsl/notebooks/Notebook.py +263 -258
- edsl/notebooks/NotebookToLaTeX.py +142 -0
- edsl/notebooks/__init__.py +1 -1
- edsl/prompts/Prompt.py +352 -362
- edsl/prompts/__init__.py +2 -2
- edsl/questions/ExceptionExplainer.py +77 -0
- edsl/questions/HTMLQuestion.py +103 -0
- edsl/questions/QuestionBase.py +518 -664
- edsl/questions/QuestionBasePromptsMixin.py +221 -217
- edsl/questions/QuestionBudget.py +227 -227
- edsl/questions/QuestionCheckBox.py +359 -359
- edsl/questions/QuestionExtract.py +180 -182
- edsl/questions/QuestionFreeText.py +113 -114
- edsl/questions/QuestionFunctional.py +166 -166
- edsl/questions/QuestionList.py +223 -231
- edsl/questions/QuestionMatrix.py +265 -0
- edsl/questions/QuestionMultipleChoice.py +330 -286
- edsl/questions/QuestionNumerical.py +151 -153
- edsl/questions/QuestionRank.py +314 -324
- edsl/questions/Quick.py +41 -41
- edsl/questions/SimpleAskMixin.py +74 -73
- edsl/questions/__init__.py +27 -26
- edsl/questions/{AnswerValidatorMixin.py → answer_validator_mixin.py} +334 -289
- edsl/questions/compose_questions.py +98 -98
- edsl/questions/data_structures.py +20 -0
- edsl/questions/decorators.py +21 -21
- edsl/questions/derived/QuestionLikertFive.py +76 -76
- edsl/questions/derived/QuestionLinearScale.py +90 -87
- edsl/questions/derived/QuestionTopK.py +93 -93
- edsl/questions/derived/QuestionYesNo.py +82 -82
- edsl/questions/descriptors.py +427 -413
- edsl/questions/loop_processor.py +149 -0
- 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/{QuestionBaseGenMixin.py → question_base_gen_mixin.py} +168 -161
- edsl/questions/question_registry.py +177 -177
- edsl/questions/{RegisterQuestionsMeta.py → register_questions_meta.py} +71 -71
- edsl/questions/{ResponseValidatorABC.py → response_validator_abc.py} +188 -174
- edsl/questions/response_validator_factory.py +34 -0
- 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/matrix/__init__.py +1 -0
- edsl/questions/templates/matrix/answering_instructions.jinja +5 -0
- edsl/questions/templates/matrix/question_presentation.jinja +20 -0
- 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 +587 -424
- edsl/results/DatasetExportMixin.py +594 -731
- edsl/results/DatasetTree.py +295 -275
- edsl/results/MarkdownToDocx.py +122 -0
- edsl/results/MarkdownToPDF.py +111 -0
- edsl/results/Result.py +557 -465
- edsl/results/Results.py +1183 -1165
- edsl/results/ResultsExportMixin.py +45 -43
- edsl/results/ResultsGGMixin.py +121 -121
- edsl/results/TableDisplay.py +125 -198
- edsl/results/TextEditor.py +50 -0
- edsl/results/__init__.py +2 -2
- edsl/results/file_exports.py +252 -0
- edsl/results/{ResultsFetchMixin.py → results_fetch_mixin.py} +33 -33
- edsl/results/{Selector.py → results_selector.py} +145 -135
- edsl/results/{ResultsToolsMixin.py → results_tools_mixin.py} +98 -98
- edsl/results/smart_objects.py +96 -0
- edsl/results/table_data_class.py +12 -0
- edsl/results/table_display.css +77 -77
- edsl/results/table_renderers.py +118 -0
- edsl/results/tree_explore.py +115 -115
- edsl/scenarios/ConstructDownloadLink.py +109 -0
- edsl/scenarios/DocumentChunker.py +102 -0
- edsl/scenarios/DocxScenario.py +16 -0
- edsl/scenarios/FileStore.py +511 -632
- edsl/scenarios/PdfExtractor.py +40 -0
- edsl/scenarios/Scenario.py +498 -601
- edsl/scenarios/ScenarioHtmlMixin.py +65 -64
- edsl/scenarios/ScenarioList.py +1458 -1287
- edsl/scenarios/ScenarioListExportMixin.py +45 -52
- edsl/scenarios/ScenarioListPdfMixin.py +239 -261
- edsl/scenarios/__init__.py +3 -4
- edsl/scenarios/directory_scanner.py +96 -0
- edsl/scenarios/file_methods.py +85 -0
- edsl/scenarios/handlers/__init__.py +13 -0
- edsl/scenarios/handlers/csv.py +38 -0
- edsl/scenarios/handlers/docx.py +76 -0
- edsl/scenarios/handlers/html.py +37 -0
- edsl/scenarios/handlers/json.py +111 -0
- edsl/scenarios/handlers/latex.py +5 -0
- edsl/scenarios/handlers/md.py +51 -0
- edsl/scenarios/handlers/pdf.py +68 -0
- edsl/scenarios/handlers/png.py +39 -0
- edsl/scenarios/handlers/pptx.py +105 -0
- edsl/scenarios/handlers/py.py +294 -0
- edsl/scenarios/handlers/sql.py +313 -0
- edsl/scenarios/handlers/sqlite.py +149 -0
- edsl/scenarios/handlers/txt.py +33 -0
- edsl/scenarios/{ScenarioJoin.py → scenario_join.py} +131 -127
- edsl/scenarios/scenario_selector.py +156 -0
- 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 +521 -528
- edsl/study/__init__.py +4 -4
- edsl/surveys/ConstructDAG.py +92 -0
- edsl/surveys/DAG.py +148 -148
- edsl/surveys/EditSurvey.py +221 -0
- edsl/surveys/InstructionHandler.py +100 -0
- edsl/surveys/Memory.py +31 -31
- edsl/surveys/MemoryManagement.py +72 -0
- edsl/surveys/MemoryPlan.py +244 -244
- edsl/surveys/Rule.py +327 -326
- edsl/surveys/RuleCollection.py +385 -387
- edsl/surveys/RuleManager.py +172 -0
- edsl/surveys/Simulator.py +75 -0
- edsl/surveys/Survey.py +1280 -1801
- edsl/surveys/SurveyCSS.py +273 -261
- edsl/surveys/SurveyExportMixin.py +259 -259
- edsl/surveys/{SurveyFlowVisualizationMixin.py → SurveyFlowVisualization.py} +181 -179
- edsl/surveys/SurveyQualtricsImport.py +284 -284
- edsl/surveys/SurveyToApp.py +141 -0
- edsl/surveys/__init__.py +5 -3
- edsl/surveys/base.py +53 -53
- edsl/surveys/descriptors.py +60 -56
- edsl/surveys/instructions/ChangeInstruction.py +48 -49
- edsl/surveys/instructions/Instruction.py +56 -65
- edsl/surveys/instructions/InstructionCollection.py +82 -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 -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/test_h +1 -0
- 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/PrettyList.py +56 -0
- 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/gcp_bucket/example.py +50 -0
- edsl/utilities/interface.py +627 -627
- edsl/utilities/is_notebook.py +18 -0
- edsl/utilities/is_valid_variable_name.py +11 -0
- edsl/utilities/naming_utilities.py +263 -263
- edsl/utilities/remove_edsl_version.py +24 -0
- edsl/utilities/repair_functions.py +28 -28
- edsl/utilities/restricted_python.py +70 -70
- edsl/utilities/utilities.py +436 -424
- {edsl-0.1.39.dev3.dist-info → edsl-0.1.39.dev4.dist-info}/LICENSE +21 -21
- {edsl-0.1.39.dev3.dist-info → edsl-0.1.39.dev4.dist-info}/METADATA +13 -11
- edsl-0.1.39.dev4.dist-info/RECORD +361 -0
- edsl/language_models/KeyLookup.py +0 -30
- edsl/language_models/registry.py +0 -190
- edsl/language_models/unused/ReplicateBase.py +0 -83
- edsl/results/ResultsDBMixin.py +0 -238
- edsl-0.1.39.dev3.dist-info/RECORD +0 -277
- {edsl-0.1.39.dev3.dist-info → edsl-0.1.39.dev4.dist-info}/WHEEL +0 -0
@@ -0,0 +1,141 @@
|
|
1
|
+
from fastapi import FastAPI
|
2
|
+
from pydantic import BaseModel, create_model
|
3
|
+
from typing import Callable, Optional, Type, Dict, Any, List, Union
|
4
|
+
|
5
|
+
|
6
|
+
class SurveyToApp:
|
7
|
+
def __init__(self, survey):
|
8
|
+
self.survey = survey
|
9
|
+
self.app = FastAPI()
|
10
|
+
|
11
|
+
def parameters(self):
|
12
|
+
return self.survey.parameters
|
13
|
+
|
14
|
+
def create_input(self) -> Type[BaseModel]:
|
15
|
+
"""
|
16
|
+
Creates a Pydantic model based on the survey parameters.
|
17
|
+
Returns:
|
18
|
+
Type[BaseModel]: A dynamically created Pydantic model class
|
19
|
+
"""
|
20
|
+
# Get parameters from survey - now calling the method
|
21
|
+
params = self.parameters()
|
22
|
+
|
23
|
+
# Create field definitions dictionary
|
24
|
+
fields: Dict[str, Any] = {}
|
25
|
+
|
26
|
+
# Since params is a set, we'll handle each parameter directly
|
27
|
+
# Assuming each parameter in the set has the necessary attributes
|
28
|
+
for param in params:
|
29
|
+
# You might need to adjust these based on the actual parameter object structure
|
30
|
+
param_name = getattr(param, "name", str(param))
|
31
|
+
param_type = getattr(param, "type", "string")
|
32
|
+
is_required = getattr(param, "required", True)
|
33
|
+
|
34
|
+
# Map survey parameter types to Python types
|
35
|
+
type_mapping = {
|
36
|
+
"string": str,
|
37
|
+
"integer": int,
|
38
|
+
"float": float,
|
39
|
+
"boolean": bool,
|
40
|
+
"array": List,
|
41
|
+
# Add more type mappings as needed
|
42
|
+
}
|
43
|
+
|
44
|
+
# Get the Python type from mapping
|
45
|
+
python_type = type_mapping.get(param_type, str)
|
46
|
+
|
47
|
+
if is_required:
|
48
|
+
fields[param_name] = (python_type, ...)
|
49
|
+
else:
|
50
|
+
fields[param_name] = (Optional[python_type], None)
|
51
|
+
|
52
|
+
# Add the template variable 'name' that's used in the question text
|
53
|
+
fields["name"] = (str, ...)
|
54
|
+
|
55
|
+
# Create and return the Pydantic model
|
56
|
+
model_name = f"{self.survey.__class__.__name__}Model"
|
57
|
+
return create_model(model_name, **fields)
|
58
|
+
|
59
|
+
def create_route(self) -> Callable:
|
60
|
+
"""
|
61
|
+
Creates a FastAPI route handler for the survey.
|
62
|
+
Returns:
|
63
|
+
Callable: A route handler function
|
64
|
+
"""
|
65
|
+
input_model = self.create_input()
|
66
|
+
|
67
|
+
async def route_handler(input_data: input_model):
|
68
|
+
"""
|
69
|
+
Handles the API route by processing the input data through the survey.
|
70
|
+
Args:
|
71
|
+
input_data: The validated input data matching the created Pydantic model
|
72
|
+
Returns:
|
73
|
+
dict: The processed survey results
|
74
|
+
"""
|
75
|
+
# Convert Pydantic model to dict
|
76
|
+
data = input_data.dict()
|
77
|
+
print(data)
|
78
|
+
from edsl.scenarios.Scenario import Scenario
|
79
|
+
|
80
|
+
# Process the data through the survey
|
81
|
+
try:
|
82
|
+
s = Scenario(data)
|
83
|
+
results = self.survey.by(s).run()
|
84
|
+
return {
|
85
|
+
"status": "success",
|
86
|
+
"data": results.select("answer.*").to_scenario_list().to_dict(),
|
87
|
+
}
|
88
|
+
except Exception as e:
|
89
|
+
return {"status": "error", "message": str(e)}
|
90
|
+
|
91
|
+
return route_handler
|
92
|
+
|
93
|
+
def add_to_app(
|
94
|
+
self, app: FastAPI, path: str = "/survey", methods: List[str] = ["POST", "GET"]
|
95
|
+
):
|
96
|
+
"""
|
97
|
+
Adds the survey route to a FastAPI application.
|
98
|
+
Args:
|
99
|
+
app (FastAPI): The FastAPI application instance
|
100
|
+
path (str): The API endpoint path
|
101
|
+
methods (List[str]): HTTP methods to support
|
102
|
+
"""
|
103
|
+
route_handler = self.create_route()
|
104
|
+
input_model = self.create_input()
|
105
|
+
|
106
|
+
app.add_api_route(
|
107
|
+
path, route_handler, methods=methods, response_model=Dict[str, Any]
|
108
|
+
)
|
109
|
+
|
110
|
+
def create_app(self, path: str = "/survey", methods: List[str] = ["POST", "GET"]):
|
111
|
+
"""
|
112
|
+
Creates a FastAPI application with the survey route.
|
113
|
+
Args:
|
114
|
+
path (str): The API endpoint path
|
115
|
+
methods (List[str]): HTTP methods to support
|
116
|
+
Returns:
|
117
|
+
FastAPI: The FastAPI application instance
|
118
|
+
"""
|
119
|
+
app = FastAPI()
|
120
|
+
self.add_to_app(app, path=path, methods=methods)
|
121
|
+
return app
|
122
|
+
|
123
|
+
|
124
|
+
from edsl import QuestionFreeText, QuestionList
|
125
|
+
|
126
|
+
# q = QuestionFreeText(
|
127
|
+
# question_name="name_gender",
|
128
|
+
# question_text="Is this customarily a boy's name or a girl's name: {{ name}}",
|
129
|
+
# )
|
130
|
+
|
131
|
+
q = QuestionList(
|
132
|
+
question_name="examples",
|
133
|
+
question_text="Give me {{ num }} examples of {{ thing }}",
|
134
|
+
)
|
135
|
+
|
136
|
+
survey_app = SurveyToApp(q.to_survey())
|
137
|
+
|
138
|
+
if __name__ == "__main__":
|
139
|
+
import uvicorn
|
140
|
+
|
141
|
+
uvicorn.run(survey_app.create_app(path="/examples"), host="127.0.0.1", port=8000)
|
edsl/surveys/__init__.py
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
-
from edsl.surveys.Survey import Survey
|
2
|
-
from edsl.surveys.
|
3
|
-
|
1
|
+
from edsl.surveys.Survey import Survey
|
2
|
+
from edsl.surveys.instructions.Instruction import Instruction
|
3
|
+
|
4
|
+
# from edsl.surveys.Rule import Rule
|
5
|
+
# from edsl.surveys.RuleCollection import RuleCollection
|
edsl/surveys/base.py
CHANGED
@@ -1,53 +1,53 @@
|
|
1
|
-
"""Base classes and enumerations for the surveyor package."""
|
2
|
-
|
3
|
-
from enum import Enum
|
4
|
-
|
5
|
-
|
6
|
-
class RulePriority(Enum):
|
7
|
-
"""Enumeration of the priority of a rule."""
|
8
|
-
|
9
|
-
DEFAULT = -1
|
10
|
-
|
11
|
-
|
12
|
-
class EndOfSurveyParent:
|
13
|
-
"""A named object that represents the end of the survey."""
|
14
|
-
|
15
|
-
pass
|
16
|
-
|
17
|
-
def __repr__(self):
|
18
|
-
"""Return a string representation of the object."""
|
19
|
-
return "EndOfSurvey"
|
20
|
-
|
21
|
-
def __str__(self):
|
22
|
-
"""Return a string representation of the object."""
|
23
|
-
return "EndOfSurvey"
|
24
|
-
|
25
|
-
def __bool__(self):
|
26
|
-
"""Return False."""
|
27
|
-
return False
|
28
|
-
|
29
|
-
def __add__(self, other):
|
30
|
-
"""Add the object to another object.
|
31
|
-
|
32
|
-
Example:
|
33
|
-
>>> e = EndOfSurveyParent()
|
34
|
-
>>> e + 1
|
35
|
-
EndOfSurvey
|
36
|
-
"""
|
37
|
-
return self
|
38
|
-
|
39
|
-
def __deepcopy__(self, memo):
|
40
|
-
# Return the same instance when deepcopy is called
|
41
|
-
return self
|
42
|
-
|
43
|
-
def __radd__(self, other):
|
44
|
-
"""Add the object to another object.
|
45
|
-
|
46
|
-
Example:
|
47
|
-
>>> 1 + EndOfSurveyParent()
|
48
|
-
EndOfSurvey
|
49
|
-
"""
|
50
|
-
return self
|
51
|
-
|
52
|
-
|
53
|
-
EndOfSurvey = EndOfSurveyParent()
|
1
|
+
"""Base classes and enumerations for the surveyor package."""
|
2
|
+
|
3
|
+
from enum import Enum
|
4
|
+
|
5
|
+
|
6
|
+
class RulePriority(Enum):
|
7
|
+
"""Enumeration of the priority of a rule."""
|
8
|
+
|
9
|
+
DEFAULT = -1
|
10
|
+
|
11
|
+
|
12
|
+
class EndOfSurveyParent:
|
13
|
+
"""A named object that represents the end of the survey."""
|
14
|
+
|
15
|
+
pass
|
16
|
+
|
17
|
+
def __repr__(self):
|
18
|
+
"""Return a string representation of the object."""
|
19
|
+
return "EndOfSurvey"
|
20
|
+
|
21
|
+
def __str__(self):
|
22
|
+
"""Return a string representation of the object."""
|
23
|
+
return "EndOfSurvey"
|
24
|
+
|
25
|
+
def __bool__(self):
|
26
|
+
"""Return False."""
|
27
|
+
return False
|
28
|
+
|
29
|
+
def __add__(self, other):
|
30
|
+
"""Add the object to another object.
|
31
|
+
|
32
|
+
Example:
|
33
|
+
>>> e = EndOfSurveyParent()
|
34
|
+
>>> e + 1
|
35
|
+
EndOfSurvey
|
36
|
+
"""
|
37
|
+
return self
|
38
|
+
|
39
|
+
def __deepcopy__(self, memo):
|
40
|
+
# Return the same instance when deepcopy is called
|
41
|
+
return self
|
42
|
+
|
43
|
+
def __radd__(self, other):
|
44
|
+
"""Add the object to another object.
|
45
|
+
|
46
|
+
Example:
|
47
|
+
>>> 1 + EndOfSurveyParent()
|
48
|
+
EndOfSurvey
|
49
|
+
"""
|
50
|
+
return self
|
51
|
+
|
52
|
+
|
53
|
+
EndOfSurvey = EndOfSurveyParent()
|
edsl/surveys/descriptors.py
CHANGED
@@ -1,56 +1,60 @@
|
|
1
|
-
"""This module contains the descriptors for the classes in the edsl package."""
|
2
|
-
|
3
|
-
from abc import ABC, abstractmethod
|
4
|
-
from typing import Any
|
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
|
-
|
1
|
+
"""This module contains the descriptors for the classes in the edsl package."""
|
2
|
+
|
3
|
+
from abc import ABC, abstractmethod
|
4
|
+
from typing import Any, TYPE_CHECKING
|
5
|
+
|
6
|
+
if TYPE_CHECKING:
|
7
|
+
from edsl.questions.QuestionBase import QuestionBase
|
8
|
+
|
9
|
+
|
10
|
+
class BaseDescriptor(ABC):
|
11
|
+
"""ABC for something."""
|
12
|
+
|
13
|
+
@abstractmethod
|
14
|
+
def validate(self, value: Any) -> None:
|
15
|
+
"""Validate the value. If it is invalid, raise an exception. If it is valid, do nothing."""
|
16
|
+
pass
|
17
|
+
|
18
|
+
def __get__(self, instance, owner):
|
19
|
+
"""Get the value of the attribute."""
|
20
|
+
return instance.__dict__[self.name]
|
21
|
+
|
22
|
+
def __set__(self, instance, value: Any) -> None:
|
23
|
+
"""Set the value of the attribute."""
|
24
|
+
self.validate(value, instance)
|
25
|
+
instance.__dict__[self.name] = value
|
26
|
+
|
27
|
+
def __set_name__(self, owner, name: str) -> None:
|
28
|
+
"""Set the name of the attribute."""
|
29
|
+
self.name = "_" + name
|
30
|
+
|
31
|
+
|
32
|
+
class QuestionsDescriptor(BaseDescriptor):
|
33
|
+
"""Descriptor for questions."""
|
34
|
+
|
35
|
+
def __get__(self, instance, owner):
|
36
|
+
"""Get the value of the attribute."""
|
37
|
+
return instance.__dict__[self.name]
|
38
|
+
|
39
|
+
def validate(self, value: Any, instance) -> None:
|
40
|
+
"""Validate the value. If it is invalid, raise an exception. If it is valid, do nothing."""
|
41
|
+
from edsl.questions.QuestionBase import QuestionBase
|
42
|
+
|
43
|
+
if not isinstance(value, list):
|
44
|
+
raise TypeError("Questions must be a list.")
|
45
|
+
if not all(isinstance(question, QuestionBase) for question in value):
|
46
|
+
raise TypeError("Questions must be a list of Question objects.")
|
47
|
+
question_names = [question.question_name for question in value]
|
48
|
+
if len(question_names) != len(set(question_names)):
|
49
|
+
raise ValueError("Question names must be unique.")
|
50
|
+
|
51
|
+
def __set__(self, instance, value: Any) -> None:
|
52
|
+
"""Set the value of the attribute."""
|
53
|
+
self.validate(value, instance)
|
54
|
+
instance.__dict__[self.name] = []
|
55
|
+
for question in value:
|
56
|
+
instance.add_question(question)
|
57
|
+
|
58
|
+
def __set_name__(self, owner, name: str) -> None:
|
59
|
+
"""Set the name of the attribute."""
|
60
|
+
self.name = "_" + name
|
@@ -1,49 +1,48 @@
|
|
1
|
-
from typing import List, Optional
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
self.
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
"
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
d["
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
@
|
47
|
-
|
48
|
-
|
49
|
-
return cls(data["keep"], data["drop"])
|
1
|
+
from typing import List, Optional
|
2
|
+
from edsl.utilities.remove_edsl_version import remove_edsl_version
|
3
|
+
|
4
|
+
|
5
|
+
class ChangeInstruction:
|
6
|
+
def __init__(
|
7
|
+
self,
|
8
|
+
keep: Optional[List[str]] = None,
|
9
|
+
drop: Optional[List[str]] = None,
|
10
|
+
):
|
11
|
+
if keep is None and drop is None:
|
12
|
+
raise ValueError("Keep and drop cannot both be None")
|
13
|
+
|
14
|
+
self.keep = keep or []
|
15
|
+
self.drop = drop or []
|
16
|
+
|
17
|
+
def include_instruction(self, instruction_name) -> bool:
|
18
|
+
return (instruction_name in self.keep) or (not instruction_name in self.drop)
|
19
|
+
|
20
|
+
def add_name(self, index) -> None:
|
21
|
+
self.name = "change_instruction_{}".format(index)
|
22
|
+
|
23
|
+
def __str__(self):
|
24
|
+
return self.text
|
25
|
+
|
26
|
+
def to_dict(self, add_edsl_version=True):
|
27
|
+
d = {
|
28
|
+
"keep": self.keep,
|
29
|
+
"drop": self.drop,
|
30
|
+
}
|
31
|
+
if add_edsl_version:
|
32
|
+
from edsl import __version__
|
33
|
+
|
34
|
+
d["edsl_version"] = __version__
|
35
|
+
d["edsl_class_name"] = "ChangeInstruction"
|
36
|
+
|
37
|
+
return d
|
38
|
+
|
39
|
+
def __hash__(self) -> int:
|
40
|
+
"""Return a hash of the question."""
|
41
|
+
from edsl.utilities.utilities import dict_hash
|
42
|
+
|
43
|
+
return dict_hash(self.to_dict(add_edsl_version=False))
|
44
|
+
|
45
|
+
@classmethod
|
46
|
+
@remove_edsl_version
|
47
|
+
def from_dict(cls, data):
|
48
|
+
return cls(data["keep"], data["drop"])
|
@@ -1,65 +1,56 @@
|
|
1
|
-
from typing import Union, Optional, List, Generator, Dict
|
2
|
-
from edsl.
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
self.
|
12
|
-
self.
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
def
|
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
|
-
|
57
|
-
|
58
|
-
@classmethod
|
59
|
-
@remove_edsl_version
|
60
|
-
def from_dict(cls, data):
|
61
|
-
return cls(
|
62
|
-
data["name"],
|
63
|
-
data["text"],
|
64
|
-
data.get("preamble", "You were given the following instructions:"),
|
65
|
-
)
|
1
|
+
from typing import Union, Optional, List, Generator, Dict
|
2
|
+
from edsl.utilities.remove_edsl_version import remove_edsl_version
|
3
|
+
from edsl.Base import RepresentationMixin
|
4
|
+
|
5
|
+
|
6
|
+
class Instruction(RepresentationMixin):
|
7
|
+
def __init__(
|
8
|
+
self, name, text, preamble="You were given the following instructions:"
|
9
|
+
):
|
10
|
+
self.name = name
|
11
|
+
self.text = text
|
12
|
+
self.preamble = preamble
|
13
|
+
|
14
|
+
def __str__(self):
|
15
|
+
return self.text
|
16
|
+
|
17
|
+
def __repr__(self):
|
18
|
+
return """Instruction(name="{}", text="{}")""".format(self.name, self.text)
|
19
|
+
|
20
|
+
@classmethod
|
21
|
+
def example(cls) -> "Instruction":
|
22
|
+
return cls(name="example", text="This is an example instruction.")
|
23
|
+
|
24
|
+
def to_dict(self, add_edsl_version=True):
|
25
|
+
d = {
|
26
|
+
"name": self.name,
|
27
|
+
"text": self.text,
|
28
|
+
"edsl_class_name": "Instruction",
|
29
|
+
"preamble": self.preamble,
|
30
|
+
}
|
31
|
+
if add_edsl_version:
|
32
|
+
from edsl import __version__
|
33
|
+
|
34
|
+
d["edsl_version"] = __version__
|
35
|
+
d["edsl_class_name"] = "Instruction"
|
36
|
+
return d
|
37
|
+
|
38
|
+
def add_question(self, question) -> "Survey":
|
39
|
+
from edsl.surveys.Survey import Survey
|
40
|
+
|
41
|
+
return Survey([self, question])
|
42
|
+
|
43
|
+
def __hash__(self) -> int:
|
44
|
+
"""Return a hash of the question."""
|
45
|
+
from edsl.utilities.utilities import dict_hash
|
46
|
+
|
47
|
+
return dict_hash(self.to_dict(add_edsl_version=False))
|
48
|
+
|
49
|
+
@classmethod
|
50
|
+
@remove_edsl_version
|
51
|
+
def from_dict(cls, data):
|
52
|
+
return cls(
|
53
|
+
data["name"],
|
54
|
+
data["text"],
|
55
|
+
data.get("preamble", "You were given the following instructions:"),
|
56
|
+
)
|