edsl 0.1.14__py3-none-any.whl → 0.1.40__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 +348 -38
- edsl/BaseDiff.py +260 -0
- edsl/TemplateLoader.py +24 -0
- edsl/__init__.py +46 -10
- edsl/__version__.py +1 -0
- edsl/agents/Agent.py +842 -144
- edsl/agents/AgentList.py +521 -25
- edsl/agents/Invigilator.py +250 -374
- edsl/agents/InvigilatorBase.py +257 -0
- edsl/agents/PromptConstructor.py +272 -0
- edsl/agents/QuestionInstructionPromptBuilder.py +128 -0
- edsl/agents/QuestionTemplateReplacementsBuilder.py +137 -0
- edsl/agents/descriptors.py +43 -13
- edsl/agents/prompt_helpers.py +129 -0
- edsl/agents/question_option_processor.py +172 -0
- edsl/auto/AutoStudy.py +130 -0
- edsl/auto/StageBase.py +243 -0
- edsl/auto/StageGenerateSurvey.py +178 -0
- edsl/auto/StageLabelQuestions.py +125 -0
- edsl/auto/StagePersona.py +61 -0
- edsl/auto/StagePersonaDimensionValueRanges.py +88 -0
- edsl/auto/StagePersonaDimensionValues.py +74 -0
- edsl/auto/StagePersonaDimensions.py +69 -0
- edsl/auto/StageQuestions.py +74 -0
- edsl/auto/SurveyCreatorPipeline.py +21 -0
- edsl/auto/utilities.py +218 -0
- edsl/base/Base.py +279 -0
- edsl/config.py +121 -104
- edsl/conversation/Conversation.py +290 -0
- edsl/conversation/car_buying.py +59 -0
- edsl/conversation/chips.py +95 -0
- edsl/conversation/mug_negotiation.py +81 -0
- edsl/conversation/next_speaker_utilities.py +93 -0
- edsl/coop/CoopFunctionsMixin.py +15 -0
- edsl/coop/ExpectedParrotKeyHandler.py +125 -0
- edsl/coop/PriceFetcher.py +54 -0
- edsl/coop/__init__.py +1 -0
- edsl/coop/coop.py +1029 -134
- edsl/coop/utils.py +131 -0
- edsl/data/Cache.py +560 -89
- edsl/data/CacheEntry.py +230 -0
- edsl/data/CacheHandler.py +168 -0
- edsl/data/RemoteCacheSync.py +186 -0
- edsl/data/SQLiteDict.py +292 -0
- edsl/data/__init__.py +5 -3
- edsl/data/orm.py +6 -33
- edsl/data_transfer_models.py +74 -27
- edsl/enums.py +165 -8
- edsl/exceptions/BaseException.py +21 -0
- edsl/exceptions/__init__.py +52 -46
- edsl/exceptions/agents.py +33 -15
- edsl/exceptions/cache.py +5 -0
- edsl/exceptions/coop.py +8 -0
- edsl/exceptions/general.py +34 -0
- edsl/exceptions/inference_services.py +5 -0
- edsl/exceptions/jobs.py +15 -0
- edsl/exceptions/language_models.py +46 -1
- edsl/exceptions/questions.py +80 -5
- edsl/exceptions/results.py +16 -5
- edsl/exceptions/scenarios.py +29 -0
- edsl/exceptions/surveys.py +13 -10
- edsl/inference_services/AnthropicService.py +106 -0
- edsl/inference_services/AvailableModelCacheHandler.py +184 -0
- edsl/inference_services/AvailableModelFetcher.py +215 -0
- edsl/inference_services/AwsBedrock.py +118 -0
- edsl/inference_services/AzureAI.py +215 -0
- edsl/inference_services/DeepInfraService.py +18 -0
- edsl/inference_services/GoogleService.py +143 -0
- edsl/inference_services/GroqService.py +20 -0
- edsl/inference_services/InferenceServiceABC.py +80 -0
- edsl/inference_services/InferenceServicesCollection.py +138 -0
- edsl/inference_services/MistralAIService.py +120 -0
- edsl/inference_services/OllamaService.py +18 -0
- edsl/inference_services/OpenAIService.py +236 -0
- edsl/inference_services/PerplexityService.py +160 -0
- edsl/inference_services/ServiceAvailability.py +135 -0
- edsl/inference_services/TestService.py +90 -0
- edsl/inference_services/TogetherAIService.py +172 -0
- edsl/inference_services/data_structures.py +134 -0
- edsl/inference_services/models_available_cache.py +118 -0
- edsl/inference_services/rate_limits_cache.py +25 -0
- edsl/inference_services/registry.py +41 -0
- edsl/inference_services/write_available.py +10 -0
- edsl/jobs/AnswerQuestionFunctionConstructor.py +223 -0
- edsl/jobs/Answers.py +21 -20
- edsl/jobs/FetchInvigilator.py +47 -0
- edsl/jobs/InterviewTaskManager.py +98 -0
- edsl/jobs/InterviewsConstructor.py +50 -0
- edsl/jobs/Jobs.py +684 -204
- edsl/jobs/JobsChecks.py +172 -0
- edsl/jobs/JobsComponentConstructor.py +189 -0
- edsl/jobs/JobsPrompts.py +270 -0
- edsl/jobs/JobsRemoteInferenceHandler.py +311 -0
- edsl/jobs/JobsRemoteInferenceLogger.py +239 -0
- edsl/jobs/RequestTokenEstimator.py +30 -0
- edsl/jobs/async_interview_runner.py +138 -0
- edsl/jobs/buckets/BucketCollection.py +104 -0
- edsl/jobs/buckets/ModelBuckets.py +65 -0
- edsl/jobs/buckets/TokenBucket.py +283 -0
- 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 +392 -0
- edsl/jobs/interviews/InterviewExceptionCollection.py +99 -0
- edsl/jobs/interviews/InterviewExceptionEntry.py +186 -0
- edsl/jobs/interviews/InterviewStatistic.py +63 -0
- edsl/jobs/interviews/InterviewStatisticsCollection.py +25 -0
- edsl/jobs/interviews/InterviewStatusDictionary.py +78 -0
- edsl/jobs/interviews/InterviewStatusLog.py +92 -0
- edsl/jobs/interviews/ReportErrors.py +66 -0
- edsl/jobs/interviews/interview_status_enum.py +9 -0
- 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 -110
- edsl/jobs/runners/JobsRunnerStatus.py +298 -0
- edsl/jobs/tasks/QuestionTaskCreator.py +244 -0
- edsl/jobs/tasks/TaskCreators.py +64 -0
- edsl/jobs/tasks/TaskHistory.py +470 -0
- edsl/jobs/tasks/TaskStatusLog.py +23 -0
- edsl/jobs/tasks/task_status_enum.py +161 -0
- edsl/jobs/tokens/InterviewTokenUsage.py +27 -0
- edsl/jobs/tokens/TokenUsage.py +34 -0
- edsl/language_models/ComputeCost.py +63 -0
- edsl/language_models/LanguageModel.py +507 -386
- edsl/language_models/ModelList.py +164 -0
- edsl/language_models/PriceManager.py +127 -0
- edsl/language_models/RawResponseHandler.py +106 -0
- edsl/language_models/RegisterLanguageModelsMeta.py +184 -0
- edsl/language_models/__init__.py +1 -8
- edsl/language_models/fake_openai_call.py +15 -0
- edsl/language_models/fake_openai_service.py +61 -0
- 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 +109 -41
- edsl/language_models/utilities.py +65 -0
- edsl/notebooks/Notebook.py +263 -0
- edsl/notebooks/NotebookToLaTeX.py +142 -0
- edsl/notebooks/__init__.py +1 -0
- edsl/prompts/Prompt.py +222 -93
- edsl/prompts/__init__.py +1 -1
- edsl/questions/ExceptionExplainer.py +77 -0
- edsl/questions/HTMLQuestion.py +103 -0
- edsl/questions/QuestionBase.py +518 -0
- edsl/questions/QuestionBasePromptsMixin.py +221 -0
- edsl/questions/QuestionBudget.py +164 -67
- edsl/questions/QuestionCheckBox.py +281 -62
- edsl/questions/QuestionDict.py +343 -0
- edsl/questions/QuestionExtract.py +136 -50
- edsl/questions/QuestionFreeText.py +79 -55
- edsl/questions/QuestionFunctional.py +138 -41
- edsl/questions/QuestionList.py +184 -57
- edsl/questions/QuestionMatrix.py +265 -0
- edsl/questions/QuestionMultipleChoice.py +293 -69
- edsl/questions/QuestionNumerical.py +109 -56
- edsl/questions/QuestionRank.py +244 -49
- edsl/questions/Quick.py +41 -0
- edsl/questions/SimpleAskMixin.py +74 -0
- edsl/questions/__init__.py +9 -6
- edsl/questions/{AnswerValidatorMixin.py → answer_validator_mixin.py} +153 -38
- edsl/questions/compose_questions.py +13 -7
- edsl/questions/data_structures.py +20 -0
- edsl/questions/decorators.py +21 -0
- edsl/questions/derived/QuestionLikertFive.py +28 -26
- edsl/questions/derived/QuestionLinearScale.py +41 -28
- edsl/questions/derived/QuestionTopK.py +34 -26
- edsl/questions/derived/QuestionYesNo.py +40 -27
- edsl/questions/descriptors.py +228 -74
- edsl/questions/loop_processor.py +149 -0
- edsl/questions/prompt_templates/question_budget.jinja +13 -0
- edsl/questions/prompt_templates/question_checkbox.jinja +32 -0
- edsl/questions/prompt_templates/question_extract.jinja +11 -0
- edsl/questions/prompt_templates/question_free_text.jinja +3 -0
- edsl/questions/prompt_templates/question_linear_scale.jinja +11 -0
- edsl/questions/prompt_templates/question_list.jinja +17 -0
- edsl/questions/prompt_templates/question_multiple_choice.jinja +33 -0
- edsl/questions/prompt_templates/question_numerical.jinja +37 -0
- edsl/questions/question_base_gen_mixin.py +168 -0
- edsl/questions/question_registry.py +130 -46
- edsl/questions/register_questions_meta.py +71 -0
- edsl/questions/response_validator_abc.py +188 -0
- edsl/questions/response_validator_factory.py +34 -0
- edsl/questions/settings.py +5 -2
- edsl/questions/templates/__init__.py +0 -0
- edsl/questions/templates/budget/__init__.py +0 -0
- edsl/questions/templates/budget/answering_instructions.jinja +7 -0
- edsl/questions/templates/budget/question_presentation.jinja +7 -0
- edsl/questions/templates/checkbox/__init__.py +0 -0
- edsl/questions/templates/checkbox/answering_instructions.jinja +10 -0
- edsl/questions/templates/checkbox/question_presentation.jinja +22 -0
- edsl/questions/templates/dict/__init__.py +0 -0
- edsl/questions/templates/dict/answering_instructions.jinja +21 -0
- edsl/questions/templates/dict/question_presentation.jinja +1 -0
- edsl/questions/templates/extract/__init__.py +0 -0
- edsl/questions/templates/extract/answering_instructions.jinja +7 -0
- edsl/questions/templates/extract/question_presentation.jinja +1 -0
- edsl/questions/templates/free_text/__init__.py +0 -0
- edsl/questions/templates/free_text/answering_instructions.jinja +0 -0
- edsl/questions/templates/free_text/question_presentation.jinja +1 -0
- edsl/questions/templates/likert_five/__init__.py +0 -0
- edsl/questions/templates/likert_five/answering_instructions.jinja +10 -0
- edsl/questions/templates/likert_five/question_presentation.jinja +12 -0
- edsl/questions/templates/linear_scale/__init__.py +0 -0
- edsl/questions/templates/linear_scale/answering_instructions.jinja +5 -0
- edsl/questions/templates/linear_scale/question_presentation.jinja +5 -0
- edsl/questions/templates/list/__init__.py +0 -0
- edsl/questions/templates/list/answering_instructions.jinja +4 -0
- edsl/questions/templates/list/question_presentation.jinja +5 -0
- 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/__init__.py +0 -0
- edsl/questions/templates/multiple_choice/answering_instructions.jinja +9 -0
- edsl/questions/templates/multiple_choice/html.jinja +0 -0
- edsl/questions/templates/multiple_choice/question_presentation.jinja +12 -0
- edsl/questions/templates/numerical/__init__.py +0 -0
- edsl/questions/templates/numerical/answering_instructions.jinja +7 -0
- edsl/questions/templates/numerical/question_presentation.jinja +7 -0
- edsl/questions/templates/rank/__init__.py +0 -0
- edsl/questions/templates/rank/answering_instructions.jinja +11 -0
- edsl/questions/templates/rank/question_presentation.jinja +15 -0
- edsl/questions/templates/top_k/__init__.py +0 -0
- edsl/questions/templates/top_k/answering_instructions.jinja +8 -0
- edsl/questions/templates/top_k/question_presentation.jinja +22 -0
- edsl/questions/templates/yes_no/__init__.py +0 -0
- edsl/questions/templates/yes_no/answering_instructions.jinja +6 -0
- edsl/questions/templates/yes_no/question_presentation.jinja +12 -0
- edsl/results/CSSParameterizer.py +108 -0
- edsl/results/Dataset.py +550 -19
- edsl/results/DatasetExportMixin.py +594 -0
- edsl/results/DatasetTree.py +295 -0
- edsl/results/MarkdownToDocx.py +122 -0
- edsl/results/MarkdownToPDF.py +111 -0
- edsl/results/Result.py +477 -173
- edsl/results/Results.py +987 -269
- edsl/results/ResultsExportMixin.py +28 -125
- edsl/results/ResultsGGMixin.py +83 -15
- edsl/results/TableDisplay.py +125 -0
- edsl/results/TextEditor.py +50 -0
- edsl/results/__init__.py +1 -1
- edsl/results/file_exports.py +252 -0
- edsl/results/results_fetch_mixin.py +33 -0
- edsl/results/results_selector.py +145 -0
- edsl/results/results_tools_mixin.py +98 -0
- edsl/results/smart_objects.py +96 -0
- edsl/results/table_data_class.py +12 -0
- edsl/results/table_display.css +78 -0
- edsl/results/table_renderers.py +118 -0
- edsl/results/tree_explore.py +115 -0
- edsl/scenarios/ConstructDownloadLink.py +109 -0
- edsl/scenarios/DocumentChunker.py +102 -0
- edsl/scenarios/DocxScenario.py +16 -0
- edsl/scenarios/FileStore.py +543 -0
- edsl/scenarios/PdfExtractor.py +40 -0
- edsl/scenarios/Scenario.py +431 -62
- edsl/scenarios/ScenarioHtmlMixin.py +65 -0
- edsl/scenarios/ScenarioList.py +1415 -45
- edsl/scenarios/ScenarioListExportMixin.py +45 -0
- edsl/scenarios/ScenarioListPdfMixin.py +239 -0
- edsl/scenarios/__init__.py +2 -0
- 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 +49 -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/scenario_join.py +131 -0
- edsl/scenarios/scenario_selector.py +156 -0
- edsl/shared.py +1 -0
- edsl/study/ObjectEntry.py +173 -0
- edsl/study/ProofOfWork.py +113 -0
- edsl/study/SnapShot.py +80 -0
- edsl/study/Study.py +521 -0
- edsl/study/__init__.py +4 -0
- edsl/surveys/ConstructDAG.py +92 -0
- edsl/surveys/DAG.py +92 -11
- edsl/surveys/EditSurvey.py +221 -0
- edsl/surveys/InstructionHandler.py +100 -0
- edsl/surveys/Memory.py +9 -4
- edsl/surveys/MemoryManagement.py +72 -0
- edsl/surveys/MemoryPlan.py +156 -35
- edsl/surveys/Rule.py +221 -74
- edsl/surveys/RuleCollection.py +241 -61
- edsl/surveys/RuleManager.py +172 -0
- edsl/surveys/Simulator.py +75 -0
- edsl/surveys/Survey.py +1079 -339
- edsl/surveys/SurveyCSS.py +273 -0
- edsl/surveys/SurveyExportMixin.py +235 -40
- edsl/surveys/SurveyFlowVisualization.py +181 -0
- edsl/surveys/SurveyQualtricsImport.py +284 -0
- edsl/surveys/SurveyToApp.py +141 -0
- edsl/surveys/__init__.py +4 -2
- edsl/surveys/base.py +19 -3
- edsl/surveys/descriptors.py +17 -6
- edsl/surveys/instructions/ChangeInstruction.py +48 -0
- edsl/surveys/instructions/Instruction.py +56 -0
- edsl/surveys/instructions/InstructionCollection.py +82 -0
- edsl/surveys/instructions/__init__.py +0 -0
- edsl/templates/error_reporting/base.html +24 -0
- edsl/templates/error_reporting/exceptions_by_model.html +35 -0
- edsl/templates/error_reporting/exceptions_by_question_name.html +17 -0
- edsl/templates/error_reporting/exceptions_by_type.html +17 -0
- edsl/templates/error_reporting/interview_details.html +116 -0
- edsl/templates/error_reporting/interviews.html +19 -0
- edsl/templates/error_reporting/overview.html +5 -0
- edsl/templates/error_reporting/performance_plot.html +2 -0
- edsl/templates/error_reporting/report.css +74 -0
- edsl/templates/error_reporting/report.html +118 -0
- edsl/templates/error_reporting/report.js +25 -0
- edsl/tools/__init__.py +1 -0
- edsl/tools/clusters.py +192 -0
- edsl/tools/embeddings.py +27 -0
- edsl/tools/embeddings_plotting.py +118 -0
- edsl/tools/plotting.py +112 -0
- edsl/tools/summarize.py +18 -0
- edsl/utilities/PrettyList.py +56 -0
- edsl/utilities/SystemInfo.py +5 -0
- edsl/utilities/__init__.py +21 -20
- edsl/utilities/ast_utilities.py +3 -0
- edsl/utilities/data/Registry.py +2 -0
- edsl/utilities/decorators.py +41 -0
- edsl/utilities/gcp_bucket/__init__.py +0 -0
- edsl/utilities/gcp_bucket/cloud_storage.py +96 -0
- edsl/utilities/interface.py +310 -60
- edsl/utilities/is_notebook.py +18 -0
- edsl/utilities/is_valid_variable_name.py +11 -0
- edsl/utilities/naming_utilities.py +263 -0
- edsl/utilities/remove_edsl_version.py +24 -0
- edsl/utilities/repair_functions.py +28 -0
- edsl/utilities/restricted_python.py +70 -0
- edsl/utilities/utilities.py +203 -13
- edsl-0.1.40.dist-info/METADATA +111 -0
- edsl-0.1.40.dist-info/RECORD +362 -0
- {edsl-0.1.14.dist-info → edsl-0.1.40.dist-info}/WHEEL +1 -1
- edsl/agents/AgentListExportMixin.py +0 -24
- edsl/coop/old.py +0 -31
- edsl/data/Database.py +0 -141
- edsl/data/crud.py +0 -121
- edsl/jobs/Interview.py +0 -417
- edsl/jobs/JobsRunner.py +0 -63
- edsl/jobs/JobsRunnerStatusMixin.py +0 -115
- edsl/jobs/base.py +0 -47
- edsl/jobs/buckets.py +0 -166
- edsl/jobs/runners/JobsRunnerDryRun.py +0 -19
- edsl/jobs/runners/JobsRunnerStreaming.py +0 -54
- edsl/jobs/task_management.py +0 -218
- edsl/jobs/token_tracking.py +0 -78
- edsl/language_models/DeepInfra.py +0 -69
- edsl/language_models/OpenAI.py +0 -98
- edsl/language_models/model_interfaces/GeminiPro.py +0 -66
- edsl/language_models/model_interfaces/LanguageModelOpenAIFour.py +0 -8
- edsl/language_models/model_interfaces/LanguageModelOpenAIThreeFiveTurbo.py +0 -8
- edsl/language_models/model_interfaces/LlamaTwo13B.py +0 -21
- edsl/language_models/model_interfaces/LlamaTwo70B.py +0 -21
- edsl/language_models/model_interfaces/Mixtral8x7B.py +0 -24
- edsl/language_models/registry.py +0 -81
- edsl/language_models/schemas.py +0 -15
- edsl/language_models/unused/ReplicateBase.py +0 -83
- edsl/prompts/QuestionInstructionsBase.py +0 -6
- edsl/prompts/library/agent_instructions.py +0 -29
- edsl/prompts/library/agent_persona.py +0 -17
- edsl/prompts/library/question_budget.py +0 -26
- edsl/prompts/library/question_checkbox.py +0 -32
- edsl/prompts/library/question_extract.py +0 -19
- edsl/prompts/library/question_freetext.py +0 -14
- edsl/prompts/library/question_linear_scale.py +0 -20
- edsl/prompts/library/question_list.py +0 -22
- edsl/prompts/library/question_multiple_choice.py +0 -44
- edsl/prompts/library/question_numerical.py +0 -31
- edsl/prompts/library/question_rank.py +0 -21
- edsl/prompts/prompt_config.py +0 -33
- edsl/prompts/registry.py +0 -185
- edsl/questions/Question.py +0 -240
- edsl/report/InputOutputDataTypes.py +0 -134
- edsl/report/RegressionMixin.py +0 -28
- edsl/report/ReportOutputs.py +0 -1228
- edsl/report/ResultsFetchMixin.py +0 -106
- edsl/report/ResultsOutputMixin.py +0 -14
- edsl/report/demo.ipynb +0 -645
- edsl/results/ResultsDBMixin.py +0 -184
- edsl/surveys/SurveyFlowVisualizationMixin.py +0 -92
- edsl/trackers/Tracker.py +0 -91
- edsl/trackers/TrackerAPI.py +0 -196
- edsl/trackers/TrackerTasks.py +0 -70
- edsl/utilities/pastebin.py +0 -141
- edsl-0.1.14.dist-info/METADATA +0 -69
- edsl-0.1.14.dist-info/RECORD +0 -141
- /edsl/{language_models/model_interfaces → inference_services}/__init__.py +0 -0
- /edsl/{report/__init__.py → jobs/runners/JobsRunnerStatusData.py} +0 -0
- /edsl/{trackers/__init__.py → language_models/ServiceDataSources.py} +0 -0
- {edsl-0.1.14.dist-info → edsl-0.1.40.dist-info}/LICENSE +0 -0
edsl/data/crud.py
DELETED
@@ -1,121 +0,0 @@
|
|
1
|
-
from sqlalchemy import desc
|
2
|
-
from typing import Union
|
3
|
-
from edsl.data import Database, database, LLMOutputDataDB
|
4
|
-
from edsl.data.orm import ResultDB
|
5
|
-
|
6
|
-
|
7
|
-
class CRUDOperations:
|
8
|
-
"""
|
9
|
-
A class that implementes CRUD operations for the EDSL package.
|
10
|
-
|
11
|
-
Initalization:
|
12
|
-
- `database`: A Database object.
|
13
|
-
|
14
|
-
Methods:
|
15
|
-
- `get_LLMOutputData(model, parameters, system_prompt, prompt)`: Retrieves a cached LLM output from the database.
|
16
|
-
- `write_LLMOutputData(model, parameters, system_prompt, prompt, output)`: Writes an LLM output to the database.
|
17
|
-
"""
|
18
|
-
|
19
|
-
def __init__(self, database: Database) -> None:
|
20
|
-
self.database = database
|
21
|
-
|
22
|
-
def get_LLMOutputData(
|
23
|
-
self, model: str, parameters: str, system_prompt: str, prompt: str
|
24
|
-
) -> Union[str, None]:
|
25
|
-
"""
|
26
|
-
Retrieves a cached LLM output from the database. Arguments: in string format, the model, parameters, system_prompt, and prompt used to generate the output. Returns the output (json string) if it exists, otherwise None.
|
27
|
-
"""
|
28
|
-
with self.database.get_db() as db:
|
29
|
-
record = (
|
30
|
-
db.query(LLMOutputDataDB)
|
31
|
-
.filter_by(
|
32
|
-
prompt=prompt,
|
33
|
-
system_prompt=system_prompt,
|
34
|
-
model=model,
|
35
|
-
parameters=parameters,
|
36
|
-
)
|
37
|
-
.order_by(desc(LLMOutputDataDB.id))
|
38
|
-
.first()
|
39
|
-
)
|
40
|
-
return record.output if record else None
|
41
|
-
|
42
|
-
def write_LLMOutputData(
|
43
|
-
self, model: str, parameters: str, system_prompt: str, prompt: str, output: str
|
44
|
-
) -> None:
|
45
|
-
"""
|
46
|
-
Writes an LLM output to the database. Arguments: in string format, the model, parameters, system_prompt, prompt, and the generated output.
|
47
|
-
"""
|
48
|
-
record = LLMOutputDataDB(
|
49
|
-
model=model,
|
50
|
-
parameters=parameters,
|
51
|
-
system_prompt=system_prompt,
|
52
|
-
prompt=prompt,
|
53
|
-
output=output,
|
54
|
-
)
|
55
|
-
|
56
|
-
with self.database.get_db() as db:
|
57
|
-
db.add(record)
|
58
|
-
db.commit()
|
59
|
-
|
60
|
-
def clear_LLMOutputData(self) -> None:
|
61
|
-
"""
|
62
|
-
Clears all LLM output data from the database.
|
63
|
-
"""
|
64
|
-
with self.database.get_db() as db:
|
65
|
-
db.query(LLMOutputDataDB).delete()
|
66
|
-
db.commit()
|
67
|
-
|
68
|
-
def get_all_LLMOutputData(self) -> list:
|
69
|
-
"""
|
70
|
-
Retrieves all LLM output data from the database and returns them as a list of dictionaries.
|
71
|
-
"""
|
72
|
-
with self.database.get_db() as db:
|
73
|
-
records = db.query(LLMOutputDataDB).all()
|
74
|
-
return [
|
75
|
-
{
|
76
|
-
"id": record.id,
|
77
|
-
"model": record.model,
|
78
|
-
"parameters": record.parameters,
|
79
|
-
"system_prompt": record.system_prompt,
|
80
|
-
"prompt": record.prompt,
|
81
|
-
"output": record.output,
|
82
|
-
}
|
83
|
-
for record in records
|
84
|
-
]
|
85
|
-
|
86
|
-
def write_result(
|
87
|
-
self,
|
88
|
-
job_uuid: str,
|
89
|
-
result_uuid: str,
|
90
|
-
agent: str,
|
91
|
-
scenario: str,
|
92
|
-
model: str,
|
93
|
-
answer: str,
|
94
|
-
) -> None:
|
95
|
-
"""Writes a Result record to the database."""
|
96
|
-
record = ResultDB(
|
97
|
-
job_uuid=job_uuid,
|
98
|
-
result_uuid=result_uuid,
|
99
|
-
agent=agent,
|
100
|
-
scenario=scenario,
|
101
|
-
model=model,
|
102
|
-
answer=answer,
|
103
|
-
)
|
104
|
-
|
105
|
-
with self.database.get_db() as db:
|
106
|
-
db.add(record)
|
107
|
-
db.commit()
|
108
|
-
|
109
|
-
def read_results(self, job_uuid: str) -> list[ResultDB]:
|
110
|
-
"""Reads all Result records associated with job_uuid from the database."""
|
111
|
-
with self.database.get_db() as db:
|
112
|
-
records = (
|
113
|
-
db.query(ResultDB)
|
114
|
-
.filter_by(job_uuid=job_uuid)
|
115
|
-
.order_by(desc(ResultDB.id))
|
116
|
-
.all()
|
117
|
-
)
|
118
|
-
return records
|
119
|
-
|
120
|
-
|
121
|
-
CRUD = CRUDOperations(database)
|
edsl/jobs/Interview.py
DELETED
@@ -1,417 +0,0 @@
|
|
1
|
-
from __future__ import annotations
|
2
|
-
import asyncio
|
3
|
-
import logging
|
4
|
-
import textwrap
|
5
|
-
from collections import UserList
|
6
|
-
from typing import Any, Type, List, Generator, Callable, List
|
7
|
-
from collections import defaultdict
|
8
|
-
|
9
|
-
from edsl import CONFIG
|
10
|
-
from edsl.agents import Agent
|
11
|
-
from edsl.exceptions import InterviewErrorPriorTaskCanceled, InterviewTimeoutError
|
12
|
-
from edsl.language_models import LanguageModel
|
13
|
-
from edsl.questions import Question
|
14
|
-
from edsl.scenarios import Scenario
|
15
|
-
from edsl.surveys import Survey
|
16
|
-
from edsl.utilities.decorators import sync_wrapper
|
17
|
-
from edsl.data_transfer_models import AgentResponseDict
|
18
|
-
from edsl.jobs.Answers import Answers
|
19
|
-
|
20
|
-
from edsl.surveys.base import EndOfSurvey
|
21
|
-
|
22
|
-
from edsl.jobs.buckets import ModelBuckets
|
23
|
-
from edsl.jobs.token_tracking import TokenUsage, InterviewTokenUsage
|
24
|
-
|
25
|
-
from edsl.jobs.task_management import (
|
26
|
-
InterviewStatusDictionary,
|
27
|
-
QuestionTaskCreator,
|
28
|
-
TasksList,
|
29
|
-
)
|
30
|
-
|
31
|
-
import traceback
|
32
|
-
|
33
|
-
# create logger
|
34
|
-
logger = logging.getLogger(__name__)
|
35
|
-
logger.setLevel(logging.INFO)
|
36
|
-
logger.propagate = False
|
37
|
-
# create file handler
|
38
|
-
fh = logging.FileHandler(CONFIG.get("EDSL_LOGGING_PATH"))
|
39
|
-
fh.setLevel(logging.INFO)
|
40
|
-
# add formatter to the handlers
|
41
|
-
formatter = logging.Formatter(
|
42
|
-
"%(asctime)s - %(name)s - %(levelname)s - %(module)s:%(lineno)d - %(funcName)s - %(message)s"
|
43
|
-
)
|
44
|
-
fh.setFormatter(formatter)
|
45
|
-
# add handler to logger
|
46
|
-
logger.addHandler(fh)
|
47
|
-
|
48
|
-
# start loggin'
|
49
|
-
logger.info("Interview.py loaded")
|
50
|
-
|
51
|
-
TIMEOUT = float(CONFIG.get("API_CALL_TIMEOUT_SEC"))
|
52
|
-
|
53
|
-
|
54
|
-
class Interview:
|
55
|
-
"""
|
56
|
-
A class that has an Agent answer Survey Questions with a particular Scenario and using a LanguageModel.
|
57
|
-
"""
|
58
|
-
|
59
|
-
def __init__(
|
60
|
-
self,
|
61
|
-
agent: Agent,
|
62
|
-
survey: Survey,
|
63
|
-
scenario: Scenario,
|
64
|
-
model: Type[LanguageModel],
|
65
|
-
verbose: bool = False,
|
66
|
-
debug: bool = False,
|
67
|
-
):
|
68
|
-
self.agent = agent
|
69
|
-
self.survey = survey
|
70
|
-
self.scenario = scenario
|
71
|
-
self.model = model
|
72
|
-
self.debug = debug
|
73
|
-
self.verbose = verbose
|
74
|
-
self.answers: dict[str, str] = Answers() # will get filled in
|
75
|
-
|
76
|
-
self.dag = self.survey.dag(textify=True)
|
77
|
-
self.to_index = {
|
78
|
-
name: index for index, name in enumerate(self.survey.question_names)
|
79
|
-
}
|
80
|
-
|
81
|
-
logger.info(f"Interview instantiated")
|
82
|
-
self.task_creators = {}
|
83
|
-
|
84
|
-
@property
|
85
|
-
def token_usage(self) -> InterviewTokenUsage:
|
86
|
-
"Determins how many tokens were used for the interview."
|
87
|
-
cached_tokens = TokenUsage(from_cache=True)
|
88
|
-
new_tokens = TokenUsage(from_cache=False)
|
89
|
-
for task_creator in self.task_creators.values():
|
90
|
-
token_usage = task_creator.token_usage()
|
91
|
-
cached_tokens += token_usage["cached_tokens"]
|
92
|
-
new_tokens += token_usage["new_tokens"]
|
93
|
-
return InterviewTokenUsage(
|
94
|
-
new_token_usage=new_tokens, cached_token_usage=cached_tokens
|
95
|
-
)
|
96
|
-
|
97
|
-
@property
|
98
|
-
def interview_status(self) -> InterviewStatusDictionary:
|
99
|
-
"""Returns a dictionary mapping task status codes to counts"""
|
100
|
-
status_dict = InterviewStatusDictionary()
|
101
|
-
for task_creator in self.task_creators.values():
|
102
|
-
status_dict[task_creator.task_status] += 1
|
103
|
-
status_dict["number_from_cache"] += task_creator.from_cache
|
104
|
-
return status_dict
|
105
|
-
|
106
|
-
async def async_conduct_interview(
|
107
|
-
self,
|
108
|
-
model_buckets: ModelBuckets,
|
109
|
-
debug: bool = False,
|
110
|
-
replace_missing: bool = True,
|
111
|
-
) -> tuple["Answers", List[dict[str, Any]]]:
|
112
|
-
"""
|
113
|
-
Conducts an 'interview' asynchronously.
|
114
|
-
"""
|
115
|
-
|
116
|
-
# we create both tasks and invigilators lists.
|
117
|
-
# this is because it's easier to extract info
|
118
|
-
# we need from the invigilators list when a task fails.
|
119
|
-
# it's challenging to get info from failed asyncio tasks.
|
120
|
-
self.tasks, self.invigilators = self._build_question_tasks(
|
121
|
-
debug=debug, model_buckets=model_buckets
|
122
|
-
)
|
123
|
-
|
124
|
-
await asyncio.gather(*self.tasks, return_exceptions=not debug)
|
125
|
-
|
126
|
-
if replace_missing:
|
127
|
-
self.answers.replace_missing_answers_with_none(self.survey)
|
128
|
-
|
129
|
-
valid_results = list(self._extract_valid_results(self.tasks, self.invigilators))
|
130
|
-
|
131
|
-
return self.answers, valid_results
|
132
|
-
|
133
|
-
def _extract_valid_results(
|
134
|
-
self, tasks, invigialtors
|
135
|
-
) -> Generator["Answers", None, None]:
|
136
|
-
"""Extracts the valid results from the list of results."""
|
137
|
-
|
138
|
-
# we only need to print the warning once if a task failed.
|
139
|
-
warning_printed = False
|
140
|
-
warning_header = textwrap.dedent(
|
141
|
-
"""\
|
142
|
-
WARNING: At least one question in the survey was not answered.
|
143
|
-
"""
|
144
|
-
)
|
145
|
-
# there should be one one invigilator for each task
|
146
|
-
assert len(self.tasks) == len(self.invigilators)
|
147
|
-
|
148
|
-
for task, invigilator in zip(self.tasks, self.invigilators):
|
149
|
-
logger.info(f"Iterating through task: {task}")
|
150
|
-
if task.done():
|
151
|
-
try:
|
152
|
-
result = task.result()
|
153
|
-
except asyncio.CancelledError:
|
154
|
-
logger.info(f"Task `{task.edsl_name}` was cancelled.")
|
155
|
-
result = invigilator.get_failed_task_result()
|
156
|
-
except Exception as exception:
|
157
|
-
if not warning_printed:
|
158
|
-
warning_printed = True
|
159
|
-
print(warning_header)
|
160
|
-
|
161
|
-
error_message = f"Task `{task.edsl_name}` failed with `{exception.__class__.__name__}`:`{exception}`."
|
162
|
-
logger.error(error_message)
|
163
|
-
print(error_message)
|
164
|
-
traceback.print_exc()
|
165
|
-
# if task failed, we use the invigilator to get the failed task result
|
166
|
-
result = invigilator.get_failed_task_result()
|
167
|
-
else:
|
168
|
-
# No exception means the task completed successfully
|
169
|
-
pass
|
170
|
-
|
171
|
-
yield result
|
172
|
-
|
173
|
-
def _build_question_tasks(self, debug, model_buckets) -> List[asyncio.Task]:
|
174
|
-
"""Creates a task for each question, with dependencies on the questions that must be answered before this one can be answered."""
|
175
|
-
logger.info("Creating tasks for each question")
|
176
|
-
tasks = []
|
177
|
-
invigilators = []
|
178
|
-
for question in self.survey.questions:
|
179
|
-
# finds dependency tasks for that question
|
180
|
-
tasks_that_must_be_completed_before = (
|
181
|
-
self._get_tasks_that_must_be_completed_before(tasks, question)
|
182
|
-
)
|
183
|
-
# creates the task for that question
|
184
|
-
question_task = self._create_question_task(
|
185
|
-
question=question,
|
186
|
-
tasks_that_must_be_completed_before=tasks_that_must_be_completed_before,
|
187
|
-
model_buckets=model_buckets,
|
188
|
-
debug=debug,
|
189
|
-
)
|
190
|
-
# adds the task to the list of tasks
|
191
|
-
tasks.append(question_task)
|
192
|
-
invigilators.append(self.get_invigilator(question, debug))
|
193
|
-
return TasksList(tasks), invigilators
|
194
|
-
|
195
|
-
def _get_tasks_that_must_be_completed_before(
|
196
|
-
self, tasks, question
|
197
|
-
) -> List[asyncio.Task]:
|
198
|
-
"""Returns the tasks that must be completed before the given question can be answered.
|
199
|
-
If a question has no dependencies, this will be an empty list, [].
|
200
|
-
"""
|
201
|
-
parents_of_focal_question: List[str] = self.dag.get(question.question_name, [])
|
202
|
-
return [
|
203
|
-
tasks[self.to_index[parent_question_name]]
|
204
|
-
for parent_question_name in parents_of_focal_question
|
205
|
-
]
|
206
|
-
|
207
|
-
def _create_question_task(
|
208
|
-
self,
|
209
|
-
question: Question,
|
210
|
-
tasks_that_must_be_completed_before: List[asyncio.Task],
|
211
|
-
model_buckets: ModelBuckets,
|
212
|
-
debug,
|
213
|
-
):
|
214
|
-
"""Creates a task that depends on the passed-in dependencies that are awaited before the task is run."""
|
215
|
-
task_creator = QuestionTaskCreator(
|
216
|
-
question=question,
|
217
|
-
answer_question_func=self._answer_question_and_record_task,
|
218
|
-
token_estimator=self._get_estimated_request_tokens,
|
219
|
-
model_buckets=model_buckets,
|
220
|
-
)
|
221
|
-
[task_creator.add_dependency(x) for x in tasks_that_must_be_completed_before]
|
222
|
-
self.task_creators[question.question_name] = task_creator
|
223
|
-
return task_creator.generate_task(debug)
|
224
|
-
|
225
|
-
def async_timeout_handler(timeout):
|
226
|
-
def decorator(func):
|
227
|
-
async def wrapper(*args, **kwargs):
|
228
|
-
try:
|
229
|
-
return await asyncio.wait_for(func(*args, **kwargs), timeout)
|
230
|
-
except asyncio.TimeoutError:
|
231
|
-
raise InterviewTimeoutError(
|
232
|
-
f"Task timed out after {timeout} seconds."
|
233
|
-
)
|
234
|
-
|
235
|
-
return wrapper
|
236
|
-
|
237
|
-
return decorator
|
238
|
-
|
239
|
-
def get_invigilator(self, question, debug) -> "Invigilator":
|
240
|
-
invigilator = self.agent.create_invigilator(
|
241
|
-
question=question,
|
242
|
-
scenario=self.scenario,
|
243
|
-
model=self.model,
|
244
|
-
debug=debug,
|
245
|
-
memory_plan=self.survey.memory_plan,
|
246
|
-
current_answers=self.answers,
|
247
|
-
)
|
248
|
-
return invigilator
|
249
|
-
|
250
|
-
def _get_estimated_request_tokens(self, question) -> float:
|
251
|
-
"""Estimates the number of tokens that will be required to run the focal task."""
|
252
|
-
invigilator = self.get_invigilator(question, debug=False)
|
253
|
-
# TODO: There should be a way to get a more accurate estimate.
|
254
|
-
combined_text = ""
|
255
|
-
for prompt in invigilator.get_prompts().values():
|
256
|
-
if hasattr(prompt, "text"):
|
257
|
-
combined_text += prompt.text
|
258
|
-
elif isinstance(prompt, str):
|
259
|
-
combined_text += prompt
|
260
|
-
else:
|
261
|
-
raise ValueError(f"Prompt is of type {type(prompt)}")
|
262
|
-
return len(combined_text) / 4.0
|
263
|
-
|
264
|
-
@async_timeout_handler(TIMEOUT)
|
265
|
-
async def _answer_question_and_record_task(
|
266
|
-
self,
|
267
|
-
question,
|
268
|
-
debug,
|
269
|
-
) -> AgentResponseDict:
|
270
|
-
"""Answers a question and records the task.
|
271
|
-
This in turn calls the the passed-in agent's async_answer_question method, which returns a response dictionary.
|
272
|
-
"""
|
273
|
-
invigilator = self.get_invigilator(question, debug=debug)
|
274
|
-
response: AgentResponseDict = await invigilator.async_answer_question()
|
275
|
-
# TODO: Move this back into actual agent response dict and enforce it.
|
276
|
-
response["question_name"] = question.question_name
|
277
|
-
|
278
|
-
self.answers.add_answer(response, question)
|
279
|
-
|
280
|
-
self._cancel_skipped_questions(question)
|
281
|
-
|
282
|
-
# TODO: This should be forced to be a data-exchange model to cement attributes.
|
283
|
-
return response
|
284
|
-
|
285
|
-
def _cancel_skipped_questions(self, current_question) -> None:
|
286
|
-
"""Cancels the tasks for questions that are skipped."""
|
287
|
-
logger.info(f"Current question is {current_question.question_name}")
|
288
|
-
current_question_index = self.to_index[current_question.question_name]
|
289
|
-
next_question = self.survey.rule_collection.next_question(
|
290
|
-
q_now=current_question_index, answers=self.answers
|
291
|
-
)
|
292
|
-
next_question_index = next_question.next_q
|
293
|
-
|
294
|
-
def cancel_between(start, end):
|
295
|
-
for i in range(start, end):
|
296
|
-
logger.info(
|
297
|
-
f"Cancelling task for question {i}; {self.tasks[i].edsl_name}"
|
298
|
-
)
|
299
|
-
self.tasks[i].cancel()
|
300
|
-
skipped_question_name = self.survey.question_names[i]
|
301
|
-
logger.info(f"{skipped_question_name} skipped.")
|
302
|
-
|
303
|
-
if next_question_index == EndOfSurvey:
|
304
|
-
cancel_between(current_question_index + 1, len(self.survey.questions))
|
305
|
-
return
|
306
|
-
|
307
|
-
if next_question_index > (current_question_index + 1):
|
308
|
-
cancel_between(current_question_index + 1, next_question_index)
|
309
|
-
|
310
|
-
self.tasks.status()
|
311
|
-
|
312
|
-
#######################
|
313
|
-
# Dunder methods
|
314
|
-
#######################
|
315
|
-
def __repr__(self) -> str:
|
316
|
-
"""Returns a string representation of the Interview instance."""
|
317
|
-
return f"Interview(agent = {self.agent}, survey = {self.survey}, scenario = {self.scenario}, model = {self.model})"
|
318
|
-
|
319
|
-
|
320
|
-
# def main():
|
321
|
-
# from edsl.language_models import LanguageModelOpenAIThreeFiveTurbo
|
322
|
-
# from edsl.agents import Agent
|
323
|
-
# from edsl.surveys import Survey
|
324
|
-
# from edsl.scenarios import Scenario
|
325
|
-
# from edsl.questions import QuestionMultipleChoice
|
326
|
-
|
327
|
-
# # from edsl.jobs.Interview import Interview
|
328
|
-
|
329
|
-
# # a survey with skip logic
|
330
|
-
# q0 = QuestionMultipleChoice(
|
331
|
-
# question_text="Do you like school?",
|
332
|
-
# question_options=["yes", "no"],
|
333
|
-
# question_name="q0",
|
334
|
-
# )
|
335
|
-
# q1 = QuestionMultipleChoice(
|
336
|
-
# question_text="Why not?",
|
337
|
-
# question_options=["killer bees in cafeteria", "other"],
|
338
|
-
# question_name="q1",
|
339
|
-
# )
|
340
|
-
# q2 = QuestionMultipleChoice(
|
341
|
-
# question_text="Why?",
|
342
|
-
# question_options=["**lack*** of killer bees in cafeteria", "other"],
|
343
|
-
# question_name="q2",
|
344
|
-
# )
|
345
|
-
# s = Survey(questions=[q0, q1, q2])
|
346
|
-
# s = s.add_rule(q0, "q0 == 'yes'", q2)
|
347
|
-
|
348
|
-
# # create an interview
|
349
|
-
# a = Agent(traits=None)
|
350
|
-
|
351
|
-
# def direct_question_answering_method(self, question, scenario):
|
352
|
-
# return "yes"
|
353
|
-
|
354
|
-
# a.add_direct_question_answering_method(direct_question_answering_method)
|
355
|
-
# scenario = Scenario()
|
356
|
-
# m = LanguageModelOpenAIThreeFiveTurbo(use_cache=False)
|
357
|
-
# I = Interview(agent=a, survey=s, scenario=scenario, model=m)
|
358
|
-
|
359
|
-
# I.conduct_interview()
|
360
|
-
# # # conduct five interviews
|
361
|
-
# # for _ in range(5):
|
362
|
-
# # I.conduct_interview(debug=True)
|
363
|
-
|
364
|
-
# # # replace missing answers
|
365
|
-
# # I
|
366
|
-
# # repr(I)
|
367
|
-
# # eval(repr(I))
|
368
|
-
|
369
|
-
|
370
|
-
if __name__ == "__main__":
|
371
|
-
from edsl.language_models import LanguageModelOpenAIThreeFiveTurbo
|
372
|
-
from edsl.agents import Agent
|
373
|
-
from edsl.surveys import Survey
|
374
|
-
from edsl.scenarios import Scenario
|
375
|
-
from edsl.questions import QuestionMultipleChoice
|
376
|
-
|
377
|
-
# from edsl.jobs.Interview import Interview
|
378
|
-
|
379
|
-
# a survey with skip logic
|
380
|
-
q0 = QuestionMultipleChoice(
|
381
|
-
question_text="Do you like school?",
|
382
|
-
question_options=["yes", "no"],
|
383
|
-
question_name="q0",
|
384
|
-
)
|
385
|
-
q1 = QuestionMultipleChoice(
|
386
|
-
question_text="Why not?",
|
387
|
-
question_options=["killer bees in cafeteria", "other"],
|
388
|
-
question_name="q1",
|
389
|
-
)
|
390
|
-
q2 = QuestionMultipleChoice(
|
391
|
-
question_text="Why?",
|
392
|
-
question_options=["**lack*** of killer bees in cafeteria", "other"],
|
393
|
-
question_name="q2",
|
394
|
-
)
|
395
|
-
s = Survey(questions=[q0, q1, q2])
|
396
|
-
s = s.add_rule(q0, "q0 == 'yes'", q2)
|
397
|
-
|
398
|
-
# create an interview
|
399
|
-
a = Agent(traits=None)
|
400
|
-
|
401
|
-
def direct_question_answering_method(self, question, scenario):
|
402
|
-
return "yes"
|
403
|
-
|
404
|
-
a.add_direct_question_answering_method(direct_question_answering_method)
|
405
|
-
scenario = Scenario()
|
406
|
-
m = LanguageModelOpenAIThreeFiveTurbo(use_cache=False)
|
407
|
-
I = Interview(agent=a, survey=s, scenario=scenario, model=m)
|
408
|
-
|
409
|
-
I.conduct_interview()
|
410
|
-
# # conduct five interviews
|
411
|
-
# for _ in range(5):
|
412
|
-
# I.conduct_interview(debug=True)
|
413
|
-
|
414
|
-
# # replace missing answers
|
415
|
-
# I
|
416
|
-
# repr(I)
|
417
|
-
# eval(repr(I))
|
edsl/jobs/JobsRunner.py
DELETED
@@ -1,63 +0,0 @@
|
|
1
|
-
from __future__ import annotations
|
2
|
-
|
3
|
-
from collections import UserDict
|
4
|
-
|
5
|
-
from abc import ABC, ABCMeta, abstractmethod
|
6
|
-
from edsl.jobs import Jobs
|
7
|
-
from edsl.results import Results
|
8
|
-
|
9
|
-
|
10
|
-
class RegisterJobsRunnerMeta(ABCMeta):
|
11
|
-
"Metaclass to register output elements in a registry i.e., those that have a parent"
|
12
|
-
_registry = {} # Initialize the registry as a dictionary
|
13
|
-
|
14
|
-
def __init__(cls, name, bases, dct):
|
15
|
-
super(RegisterJobsRunnerMeta, cls).__init__(name, bases, dct)
|
16
|
-
if name != "JobsRunner":
|
17
|
-
RegisterJobsRunnerMeta._registry[name] = cls
|
18
|
-
|
19
|
-
@classmethod
|
20
|
-
def get_registered_classes(cls):
|
21
|
-
return cls._registry
|
22
|
-
|
23
|
-
@classmethod
|
24
|
-
def lookup(cls):
|
25
|
-
d = {}
|
26
|
-
for classname, cls in cls._registry.items():
|
27
|
-
if hasattr(cls, "runner_name"):
|
28
|
-
d[cls.runner_name] = cls
|
29
|
-
else:
|
30
|
-
raise Exception(
|
31
|
-
f"Class {classname} does not have a runner_name attribute"
|
32
|
-
)
|
33
|
-
return d
|
34
|
-
|
35
|
-
|
36
|
-
class JobsRunner(ABC, metaclass=RegisterJobsRunnerMeta):
|
37
|
-
"""ABC for JobRunners, which take in a job, conduct interviews, and return their results."""
|
38
|
-
|
39
|
-
def __init__(self, jobs: Jobs):
|
40
|
-
self.jobs = jobs
|
41
|
-
# create the interviews here so children can use them
|
42
|
-
self.interviews = jobs.interviews()
|
43
|
-
self.bucket_collection = jobs.bucket_collection
|
44
|
-
# self.bucket_collection = self.jobs.bucket_collection
|
45
|
-
# for model in self.jobs.models:
|
46
|
-
# self.bucket_collection.add_model(model)
|
47
|
-
|
48
|
-
@abstractmethod
|
49
|
-
def run(
|
50
|
-
self,
|
51
|
-
n: int = 1,
|
52
|
-
debug: bool = False,
|
53
|
-
verbose: bool = False,
|
54
|
-
progress_bar: bool = True,
|
55
|
-
) -> Results: # pragma: no cover
|
56
|
-
"""
|
57
|
-
Runs the job: conducts Interviews and returns their results.
|
58
|
-
- `n`: how many times to run each interview
|
59
|
-
- `debug`: prints debug messages
|
60
|
-
- `verbose`: prints messages
|
61
|
-
- `progress_bar`: shows a progress bar
|
62
|
-
"""
|
63
|
-
raise NotImplementedError
|