edsl 0.1.30.dev4__tar.gz → 0.1.31__tar.gz
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-0.1.30.dev4 → edsl-0.1.31}/PKG-INFO +4 -2
- edsl-0.1.31/edsl/__version__.py +1 -0
- {edsl-0.1.30.dev4 → edsl-0.1.31}/edsl/agents/Invigilator.py +7 -2
- {edsl-0.1.30.dev4 → edsl-0.1.31}/edsl/agents/PromptConstructionMixin.py +18 -1
- {edsl-0.1.30.dev4 → edsl-0.1.31}/edsl/config.py +4 -0
- {edsl-0.1.30.dev4 → edsl-0.1.31}/edsl/conjure/Conjure.py +6 -0
- {edsl-0.1.30.dev4 → edsl-0.1.31}/edsl/coop/coop.py +4 -0
- {edsl-0.1.30.dev4 → edsl-0.1.31}/edsl/coop/utils.py +9 -1
- {edsl-0.1.30.dev4 → edsl-0.1.31}/edsl/data/CacheHandler.py +3 -4
- {edsl-0.1.30.dev4 → edsl-0.1.31}/edsl/enums.py +2 -0
- edsl-0.1.31/edsl/inference_services/DeepInfraService.py +18 -0
- edsl-0.1.31/edsl/inference_services/GroqService.py +18 -0
- {edsl-0.1.30.dev4 → edsl-0.1.31}/edsl/inference_services/InferenceServicesCollection.py +13 -5
- {edsl-0.1.30.dev4 → edsl-0.1.31}/edsl/inference_services/OpenAIService.py +64 -21
- {edsl-0.1.30.dev4 → edsl-0.1.31}/edsl/inference_services/registry.py +2 -1
- {edsl-0.1.30.dev4 → edsl-0.1.31}/edsl/jobs/Jobs.py +80 -33
- {edsl-0.1.30.dev4 → edsl-0.1.31}/edsl/jobs/buckets/TokenBucket.py +24 -5
- {edsl-0.1.30.dev4 → edsl-0.1.31}/edsl/jobs/interviews/Interview.py +122 -75
- edsl-0.1.31/edsl/jobs/interviews/InterviewExceptionEntry.py +101 -0
- {edsl-0.1.30.dev4 → edsl-0.1.31}/edsl/jobs/interviews/InterviewTaskBuildingMixin.py +58 -52
- {edsl-0.1.30.dev4 → edsl-0.1.31}/edsl/jobs/interviews/interview_exception_tracking.py +68 -10
- {edsl-0.1.30.dev4 → edsl-0.1.31}/edsl/jobs/runners/JobsRunnerAsyncio.py +112 -81
- edsl-0.1.31/edsl/jobs/runners/JobsRunnerStatusMixin.py +333 -0
- {edsl-0.1.30.dev4 → edsl-0.1.31}/edsl/jobs/tasks/QuestionTaskCreator.py +1 -5
- {edsl-0.1.30.dev4 → edsl-0.1.31}/edsl/jobs/tasks/TaskCreators.py +8 -2
- {edsl-0.1.30.dev4 → edsl-0.1.31}/edsl/jobs/tasks/TaskHistory.py +145 -1
- {edsl-0.1.30.dev4 → edsl-0.1.31}/edsl/language_models/LanguageModel.py +135 -75
- {edsl-0.1.30.dev4 → edsl-0.1.31}/edsl/language_models/ModelList.py +8 -2
- {edsl-0.1.30.dev4 → edsl-0.1.31}/edsl/language_models/registry.py +16 -0
- {edsl-0.1.30.dev4 → edsl-0.1.31}/edsl/questions/QuestionFunctional.py +34 -2
- {edsl-0.1.30.dev4 → edsl-0.1.31}/edsl/questions/QuestionMultipleChoice.py +58 -8
- {edsl-0.1.30.dev4 → edsl-0.1.31}/edsl/questions/QuestionNumerical.py +0 -1
- {edsl-0.1.30.dev4 → edsl-0.1.31}/edsl/questions/descriptors.py +42 -2
- {edsl-0.1.30.dev4 → edsl-0.1.31}/edsl/results/DatasetExportMixin.py +258 -75
- {edsl-0.1.30.dev4 → edsl-0.1.31}/edsl/results/Result.py +53 -5
- {edsl-0.1.30.dev4 → edsl-0.1.31}/edsl/results/Results.py +66 -27
- {edsl-0.1.30.dev4 → edsl-0.1.31}/edsl/results/ResultsToolsMixin.py +1 -1
- {edsl-0.1.30.dev4 → edsl-0.1.31}/edsl/scenarios/Scenario.py +14 -0
- {edsl-0.1.30.dev4 → edsl-0.1.31}/edsl/scenarios/ScenarioList.py +59 -21
- {edsl-0.1.30.dev4 → edsl-0.1.31}/edsl/scenarios/ScenarioListExportMixin.py +16 -5
- {edsl-0.1.30.dev4 → edsl-0.1.31}/edsl/scenarios/ScenarioListPdfMixin.py +3 -0
- {edsl-0.1.30.dev4 → edsl-0.1.31}/edsl/study/Study.py +2 -2
- {edsl-0.1.30.dev4 → edsl-0.1.31}/edsl/surveys/Survey.py +35 -1
- edsl-0.1.31/edsl/utilities/gcp_bucket/__init__.py +0 -0
- {edsl-0.1.30.dev4 → edsl-0.1.31}/pyproject.toml +22 -19
- edsl-0.1.30.dev4/edsl/__version__.py +0 -1
- edsl-0.1.30.dev4/edsl/inference_services/DeepInfraService.py +0 -103
- edsl-0.1.30.dev4/edsl/jobs/runners/JobsRunnerStatusData.py +0 -237
- edsl-0.1.30.dev4/edsl/jobs/runners/JobsRunnerStatusMixin.py +0 -77
- {edsl-0.1.30.dev4 → edsl-0.1.31}/LICENSE +0 -0
- {edsl-0.1.30.dev4 → edsl-0.1.31}/README.md +0 -0
- {edsl-0.1.30.dev4 → edsl-0.1.31}/edsl/Base.py +0 -0
- {edsl-0.1.30.dev4 → edsl-0.1.31}/edsl/BaseDiff.py +0 -0
- {edsl-0.1.30.dev4 → edsl-0.1.31}/edsl/__init__.py +0 -0
- {edsl-0.1.30.dev4 → edsl-0.1.31}/edsl/agents/Agent.py +0 -0
- {edsl-0.1.30.dev4 → edsl-0.1.31}/edsl/agents/AgentList.py +0 -0
- {edsl-0.1.30.dev4 → edsl-0.1.31}/edsl/agents/InvigilatorBase.py +0 -0
- {edsl-0.1.30.dev4 → edsl-0.1.31}/edsl/agents/__init__.py +0 -0
- {edsl-0.1.30.dev4 → edsl-0.1.31}/edsl/agents/descriptors.py +0 -0
- {edsl-0.1.30.dev4 → edsl-0.1.31}/edsl/base/Base.py +0 -0
- {edsl-0.1.30.dev4 → edsl-0.1.31}/edsl/conjure/AgentConstructionMixin.py +0 -0
- {edsl-0.1.30.dev4 → edsl-0.1.31}/edsl/conjure/InputData.py +0 -0
- {edsl-0.1.30.dev4 → edsl-0.1.31}/edsl/conjure/InputDataCSV.py +0 -0
- {edsl-0.1.30.dev4 → edsl-0.1.31}/edsl/conjure/InputDataMixinQuestionStats.py +0 -0
- {edsl-0.1.30.dev4 → edsl-0.1.31}/edsl/conjure/InputDataPyRead.py +0 -0
- {edsl-0.1.30.dev4 → edsl-0.1.31}/edsl/conjure/InputDataSPSS.py +0 -0
- {edsl-0.1.30.dev4 → edsl-0.1.31}/edsl/conjure/InputDataStata.py +0 -0
- {edsl-0.1.30.dev4 → edsl-0.1.31}/edsl/conjure/QuestionOptionMixin.py +0 -0
- {edsl-0.1.30.dev4 → edsl-0.1.31}/edsl/conjure/QuestionTypeMixin.py +0 -0
- {edsl-0.1.30.dev4 → edsl-0.1.31}/edsl/conjure/RawQuestion.py +0 -0
- {edsl-0.1.30.dev4 → edsl-0.1.31}/edsl/conjure/SurveyResponses.py +0 -0
- {edsl-0.1.30.dev4 → edsl-0.1.31}/edsl/conjure/__init__.py +0 -0
- {edsl-0.1.30.dev4 → edsl-0.1.31}/edsl/conjure/examples/placeholder.txt +0 -0
- {edsl-0.1.30.dev4 → edsl-0.1.31}/edsl/conjure/naming_utilities.py +0 -0
- {edsl-0.1.30.dev4 → edsl-0.1.31}/edsl/conjure/utilities.py +0 -0
- {edsl-0.1.30.dev4 → edsl-0.1.31}/edsl/conversation/Conversation.py +0 -0
- {edsl-0.1.30.dev4 → edsl-0.1.31}/edsl/conversation/car_buying.py +0 -0
- {edsl-0.1.30.dev4 → edsl-0.1.31}/edsl/conversation/mug_negotiation.py +0 -0
- {edsl-0.1.30.dev4 → edsl-0.1.31}/edsl/conversation/next_speaker_utilities.py +0 -0
- {edsl-0.1.30.dev4 → edsl-0.1.31}/edsl/coop/__init__.py +0 -0
- {edsl-0.1.30.dev4 → edsl-0.1.31}/edsl/data/Cache.py +0 -0
- {edsl-0.1.30.dev4 → edsl-0.1.31}/edsl/data/CacheEntry.py +0 -0
- {edsl-0.1.30.dev4 → edsl-0.1.31}/edsl/data/SQLiteDict.py +0 -0
- {edsl-0.1.30.dev4 → edsl-0.1.31}/edsl/data/__init__.py +0 -0
- {edsl-0.1.30.dev4 → edsl-0.1.31}/edsl/data/orm.py +0 -0
- {edsl-0.1.30.dev4 → edsl-0.1.31}/edsl/data_transfer_models.py +0 -0
- {edsl-0.1.30.dev4 → edsl-0.1.31}/edsl/exceptions/__init__.py +0 -0
- {edsl-0.1.30.dev4 → edsl-0.1.31}/edsl/exceptions/agents.py +0 -0
- {edsl-0.1.30.dev4 → edsl-0.1.31}/edsl/exceptions/configuration.py +0 -0
- {edsl-0.1.30.dev4 → edsl-0.1.31}/edsl/exceptions/coop.py +0 -0
- {edsl-0.1.30.dev4 → edsl-0.1.31}/edsl/exceptions/data.py +0 -0
- {edsl-0.1.30.dev4 → edsl-0.1.31}/edsl/exceptions/general.py +0 -0
- {edsl-0.1.30.dev4 → edsl-0.1.31}/edsl/exceptions/jobs.py +0 -0
- {edsl-0.1.30.dev4 → edsl-0.1.31}/edsl/exceptions/language_models.py +0 -0
- {edsl-0.1.30.dev4 → edsl-0.1.31}/edsl/exceptions/prompts.py +0 -0
- {edsl-0.1.30.dev4 → edsl-0.1.31}/edsl/exceptions/questions.py +0 -0
- {edsl-0.1.30.dev4 → edsl-0.1.31}/edsl/exceptions/results.py +0 -0
- {edsl-0.1.30.dev4 → edsl-0.1.31}/edsl/exceptions/surveys.py +0 -0
- {edsl-0.1.30.dev4 → edsl-0.1.31}/edsl/inference_services/AnthropicService.py +0 -0
- {edsl-0.1.30.dev4 → edsl-0.1.31}/edsl/inference_services/GoogleService.py +0 -0
- {edsl-0.1.30.dev4 → edsl-0.1.31}/edsl/inference_services/InferenceServiceABC.py +0 -0
- {edsl-0.1.30.dev4 → edsl-0.1.31}/edsl/inference_services/__init__.py +0 -0
- {edsl-0.1.30.dev4 → edsl-0.1.31}/edsl/inference_services/models_available_cache.py +0 -0
- {edsl-0.1.30.dev4 → edsl-0.1.31}/edsl/inference_services/rate_limits_cache.py +0 -0
- {edsl-0.1.30.dev4 → edsl-0.1.31}/edsl/inference_services/write_available.py +0 -0
- {edsl-0.1.30.dev4 → edsl-0.1.31}/edsl/jobs/Answers.py +0 -0
- {edsl-0.1.30.dev4 → edsl-0.1.31}/edsl/jobs/__init__.py +0 -0
- {edsl-0.1.30.dev4 → edsl-0.1.31}/edsl/jobs/buckets/BucketCollection.py +0 -0
- {edsl-0.1.30.dev4 → edsl-0.1.31}/edsl/jobs/buckets/ModelBuckets.py +0 -0
- {edsl-0.1.30.dev4 → edsl-0.1.31}/edsl/jobs/interviews/InterviewStatistic.py +0 -0
- {edsl-0.1.30.dev4 → edsl-0.1.31}/edsl/jobs/interviews/InterviewStatisticsCollection.py +0 -0
- {edsl-0.1.30.dev4 → edsl-0.1.31}/edsl/jobs/interviews/InterviewStatusDictionary.py +0 -0
- {edsl-0.1.30.dev4 → edsl-0.1.31}/edsl/jobs/interviews/InterviewStatusLog.py +0 -0
- {edsl-0.1.30.dev4 → edsl-0.1.31}/edsl/jobs/interviews/InterviewStatusMixin.py +0 -0
- {edsl-0.1.30.dev4 → edsl-0.1.31}/edsl/jobs/interviews/ReportErrors.py +0 -0
- {edsl-0.1.30.dev4 → edsl-0.1.31}/edsl/jobs/interviews/interview_status_enum.py +0 -0
- {edsl-0.1.30.dev4 → edsl-0.1.31}/edsl/jobs/interviews/retry_management.py +0 -0
- /edsl-0.1.30.dev4/edsl/questions/derived/__init__.py → /edsl-0.1.31/edsl/jobs/runners/JobsRunnerStatusData.py +0 -0
- {edsl-0.1.30.dev4 → edsl-0.1.31}/edsl/jobs/tasks/TaskStatusLog.py +0 -0
- {edsl-0.1.30.dev4 → edsl-0.1.31}/edsl/jobs/tasks/task_management.py +0 -0
- {edsl-0.1.30.dev4 → edsl-0.1.31}/edsl/jobs/tasks/task_status_enum.py +0 -0
- {edsl-0.1.30.dev4 → edsl-0.1.31}/edsl/jobs/tokens/InterviewTokenUsage.py +0 -0
- {edsl-0.1.30.dev4 → edsl-0.1.31}/edsl/jobs/tokens/TokenUsage.py +0 -0
- {edsl-0.1.30.dev4 → edsl-0.1.31}/edsl/language_models/RegisterLanguageModelsMeta.py +0 -0
- {edsl-0.1.30.dev4 → edsl-0.1.31}/edsl/language_models/__init__.py +0 -0
- {edsl-0.1.30.dev4 → edsl-0.1.31}/edsl/language_models/repair.py +0 -0
- {edsl-0.1.30.dev4 → edsl-0.1.31}/edsl/language_models/unused/ReplicateBase.py +0 -0
- {edsl-0.1.30.dev4 → edsl-0.1.31}/edsl/notebooks/Notebook.py +0 -0
- {edsl-0.1.30.dev4 → edsl-0.1.31}/edsl/notebooks/__init__.py +0 -0
- {edsl-0.1.30.dev4 → edsl-0.1.31}/edsl/prompts/Prompt.py +0 -0
- {edsl-0.1.30.dev4 → edsl-0.1.31}/edsl/prompts/QuestionInstructionsBase.py +0 -0
- {edsl-0.1.30.dev4 → edsl-0.1.31}/edsl/prompts/__init__.py +0 -0
- {edsl-0.1.30.dev4 → edsl-0.1.31}/edsl/prompts/library/agent_instructions.py +0 -0
- {edsl-0.1.30.dev4 → edsl-0.1.31}/edsl/prompts/library/agent_persona.py +0 -0
- {edsl-0.1.30.dev4 → edsl-0.1.31}/edsl/prompts/library/question_budget.py +0 -0
- {edsl-0.1.30.dev4 → edsl-0.1.31}/edsl/prompts/library/question_checkbox.py +0 -0
- {edsl-0.1.30.dev4 → edsl-0.1.31}/edsl/prompts/library/question_extract.py +0 -0
- {edsl-0.1.30.dev4 → edsl-0.1.31}/edsl/prompts/library/question_freetext.py +0 -0
- {edsl-0.1.30.dev4 → edsl-0.1.31}/edsl/prompts/library/question_linear_scale.py +0 -0
- {edsl-0.1.30.dev4 → edsl-0.1.31}/edsl/prompts/library/question_list.py +0 -0
- {edsl-0.1.30.dev4 → edsl-0.1.31}/edsl/prompts/library/question_multiple_choice.py +0 -0
- {edsl-0.1.30.dev4 → edsl-0.1.31}/edsl/prompts/library/question_numerical.py +0 -0
- {edsl-0.1.30.dev4 → edsl-0.1.31}/edsl/prompts/library/question_rank.py +0 -0
- {edsl-0.1.30.dev4 → edsl-0.1.31}/edsl/prompts/prompt_config.py +0 -0
- {edsl-0.1.30.dev4 → edsl-0.1.31}/edsl/prompts/registry.py +0 -0
- {edsl-0.1.30.dev4 → edsl-0.1.31}/edsl/questions/AnswerValidatorMixin.py +0 -0
- {edsl-0.1.30.dev4 → edsl-0.1.31}/edsl/questions/QuestionBase.py +0 -0
- {edsl-0.1.30.dev4 → edsl-0.1.31}/edsl/questions/QuestionBudget.py +0 -0
- {edsl-0.1.30.dev4 → edsl-0.1.31}/edsl/questions/QuestionCheckBox.py +0 -0
- {edsl-0.1.30.dev4 → edsl-0.1.31}/edsl/questions/QuestionExtract.py +0 -0
- {edsl-0.1.30.dev4 → edsl-0.1.31}/edsl/questions/QuestionFreeText.py +0 -0
- {edsl-0.1.30.dev4 → edsl-0.1.31}/edsl/questions/QuestionList.py +0 -0
- {edsl-0.1.30.dev4 → edsl-0.1.31}/edsl/questions/QuestionRank.py +0 -0
- {edsl-0.1.30.dev4 → edsl-0.1.31}/edsl/questions/RegisterQuestionsMeta.py +0 -0
- {edsl-0.1.30.dev4 → edsl-0.1.31}/edsl/questions/SimpleAskMixin.py +0 -0
- {edsl-0.1.30.dev4 → edsl-0.1.31}/edsl/questions/__init__.py +0 -0
- {edsl-0.1.30.dev4 → edsl-0.1.31}/edsl/questions/compose_questions.py +0 -0
- {edsl-0.1.30.dev4 → edsl-0.1.31}/edsl/questions/derived/QuestionLikertFive.py +0 -0
- {edsl-0.1.30.dev4 → edsl-0.1.31}/edsl/questions/derived/QuestionLinearScale.py +0 -0
- {edsl-0.1.30.dev4 → edsl-0.1.31}/edsl/questions/derived/QuestionTopK.py +0 -0
- {edsl-0.1.30.dev4 → edsl-0.1.31}/edsl/questions/derived/QuestionYesNo.py +0 -0
- {edsl-0.1.30.dev4/edsl/utilities/gcp_bucket → edsl-0.1.31/edsl/questions/derived}/__init__.py +0 -0
- {edsl-0.1.30.dev4 → edsl-0.1.31}/edsl/questions/question_registry.py +0 -0
- {edsl-0.1.30.dev4 → edsl-0.1.31}/edsl/questions/settings.py +0 -0
- {edsl-0.1.30.dev4 → edsl-0.1.31}/edsl/results/Dataset.py +0 -0
- {edsl-0.1.30.dev4 → edsl-0.1.31}/edsl/results/ResultsDBMixin.py +0 -0
- {edsl-0.1.30.dev4 → edsl-0.1.31}/edsl/results/ResultsExportMixin.py +0 -0
- {edsl-0.1.30.dev4 → edsl-0.1.31}/edsl/results/ResultsFetchMixin.py +0 -0
- {edsl-0.1.30.dev4 → edsl-0.1.31}/edsl/results/ResultsGGMixin.py +0 -0
- {edsl-0.1.30.dev4 → edsl-0.1.31}/edsl/results/__init__.py +0 -0
- {edsl-0.1.30.dev4 → edsl-0.1.31}/edsl/scenarios/FileStore.py +0 -0
- {edsl-0.1.30.dev4 → edsl-0.1.31}/edsl/scenarios/ScenarioHtmlMixin.py +0 -0
- {edsl-0.1.30.dev4 → edsl-0.1.31}/edsl/scenarios/ScenarioImageMixin.py +0 -0
- {edsl-0.1.30.dev4 → edsl-0.1.31}/edsl/scenarios/__init__.py +0 -0
- {edsl-0.1.30.dev4 → edsl-0.1.31}/edsl/shared.py +0 -0
- {edsl-0.1.30.dev4 → edsl-0.1.31}/edsl/study/ObjectEntry.py +0 -0
- {edsl-0.1.30.dev4 → edsl-0.1.31}/edsl/study/ProofOfWork.py +0 -0
- {edsl-0.1.30.dev4 → edsl-0.1.31}/edsl/study/SnapShot.py +0 -0
- {edsl-0.1.30.dev4 → edsl-0.1.31}/edsl/study/__init__.py +0 -0
- {edsl-0.1.30.dev4 → edsl-0.1.31}/edsl/surveys/DAG.py +0 -0
- {edsl-0.1.30.dev4 → edsl-0.1.31}/edsl/surveys/Memory.py +0 -0
- {edsl-0.1.30.dev4 → edsl-0.1.31}/edsl/surveys/MemoryPlan.py +0 -0
- {edsl-0.1.30.dev4 → edsl-0.1.31}/edsl/surveys/Rule.py +0 -0
- {edsl-0.1.30.dev4 → edsl-0.1.31}/edsl/surveys/RuleCollection.py +0 -0
- {edsl-0.1.30.dev4 → edsl-0.1.31}/edsl/surveys/SurveyCSS.py +0 -0
- {edsl-0.1.30.dev4 → edsl-0.1.31}/edsl/surveys/SurveyExportMixin.py +0 -0
- {edsl-0.1.30.dev4 → edsl-0.1.31}/edsl/surveys/SurveyFlowVisualizationMixin.py +0 -0
- {edsl-0.1.30.dev4 → edsl-0.1.31}/edsl/surveys/__init__.py +0 -0
- {edsl-0.1.30.dev4 → edsl-0.1.31}/edsl/surveys/base.py +0 -0
- {edsl-0.1.30.dev4 → edsl-0.1.31}/edsl/surveys/descriptors.py +0 -0
- {edsl-0.1.30.dev4 → edsl-0.1.31}/edsl/tools/__init__.py +0 -0
- {edsl-0.1.30.dev4 → edsl-0.1.31}/edsl/tools/clusters.py +0 -0
- {edsl-0.1.30.dev4 → edsl-0.1.31}/edsl/tools/embeddings.py +0 -0
- {edsl-0.1.30.dev4 → edsl-0.1.31}/edsl/tools/embeddings_plotting.py +0 -0
- {edsl-0.1.30.dev4 → edsl-0.1.31}/edsl/tools/plotting.py +0 -0
- {edsl-0.1.30.dev4 → edsl-0.1.31}/edsl/tools/summarize.py +0 -0
- {edsl-0.1.30.dev4 → edsl-0.1.31}/edsl/utilities/SystemInfo.py +0 -0
- {edsl-0.1.30.dev4 → edsl-0.1.31}/edsl/utilities/__init__.py +0 -0
- {edsl-0.1.30.dev4 → edsl-0.1.31}/edsl/utilities/ast_utilities.py +0 -0
- {edsl-0.1.30.dev4 → edsl-0.1.31}/edsl/utilities/data/Registry.py +0 -0
- {edsl-0.1.30.dev4 → edsl-0.1.31}/edsl/utilities/data/__init__.py +0 -0
- {edsl-0.1.30.dev4 → edsl-0.1.31}/edsl/utilities/data/scooter_results.json +0 -0
- {edsl-0.1.30.dev4 → edsl-0.1.31}/edsl/utilities/decorators.py +0 -0
- {edsl-0.1.30.dev4 → edsl-0.1.31}/edsl/utilities/gcp_bucket/cloud_storage.py +0 -0
- {edsl-0.1.30.dev4 → edsl-0.1.31}/edsl/utilities/gcp_bucket/simple_example.py +0 -0
- {edsl-0.1.30.dev4 → edsl-0.1.31}/edsl/utilities/interface.py +0 -0
- {edsl-0.1.30.dev4 → edsl-0.1.31}/edsl/utilities/repair_functions.py +0 -0
- {edsl-0.1.30.dev4 → edsl-0.1.31}/edsl/utilities/restricted_python.py +0 -0
- {edsl-0.1.30.dev4 → edsl-0.1.31}/edsl/utilities/utilities.py +0 -0
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.1
|
2
2
|
Name: edsl
|
3
|
-
Version: 0.1.
|
3
|
+
Version: 0.1.31
|
4
4
|
Summary: Create and analyze LLM-based surveys
|
5
5
|
Home-page: https://www.expectedparrot.com/
|
6
6
|
License: MIT
|
@@ -19,10 +19,11 @@ Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
19
19
|
Requires-Dist: aiohttp (>=3.9.1,<4.0.0)
|
20
20
|
Requires-Dist: anthropic (>=0.23.1,<0.24.0)
|
21
21
|
Requires-Dist: black[jupyter] (>=24.4.2,<25.0.0)
|
22
|
+
Requires-Dist: groq (>=0.9.0,<0.10.0)
|
22
23
|
Requires-Dist: jinja2 (>=3.1.2,<4.0.0)
|
23
24
|
Requires-Dist: jupyter (>=1.0.0,<2.0.0)
|
24
25
|
Requires-Dist: markdown2 (>=2.4.11,<3.0.0)
|
25
|
-
Requires-Dist: matplotlib (>=3.8
|
26
|
+
Requires-Dist: matplotlib (>=3.8,<3.9)
|
26
27
|
Requires-Dist: nest-asyncio (>=1.5.9,<2.0.0)
|
27
28
|
Requires-Dist: numpy (>=1.22,<2.0)
|
28
29
|
Requires-Dist: openai (>=1.4.0,<2.0.0)
|
@@ -35,6 +36,7 @@ Requires-Dist: python-docx (>=1.1.0,<2.0.0)
|
|
35
36
|
Requires-Dist: python-dotenv (>=1.0.0,<2.0.0)
|
36
37
|
Requires-Dist: restrictedpython (>=7.1,<8.0)
|
37
38
|
Requires-Dist: rich (>=13.7.0,<14.0.0)
|
39
|
+
Requires-Dist: setuptools (<72.0)
|
38
40
|
Requires-Dist: simpleeval (>=0.9.13,<0.10.0)
|
39
41
|
Requires-Dist: sqlalchemy (>=2.0.23,<3.0.0)
|
40
42
|
Requires-Dist: tenacity (>=8.2.3,<9.0.0)
|
@@ -0,0 +1 @@
|
|
1
|
+
__version__ = "0.1.31"
|
@@ -18,7 +18,12 @@ class InvigilatorAI(PromptConstructorMixin, InvigilatorBase):
|
|
18
18
|
"""An invigilator that uses an AI model to answer questions."""
|
19
19
|
|
20
20
|
async def async_answer_question(self) -> AgentResponseDict:
|
21
|
-
"""Answer a question using the AI model.
|
21
|
+
"""Answer a question using the AI model.
|
22
|
+
|
23
|
+
>>> i = InvigilatorAI.example()
|
24
|
+
>>> i.answer_question()
|
25
|
+
{'message': '{"answer": "SPAM!"}'}
|
26
|
+
"""
|
22
27
|
params = self.get_prompts() | {"iteration": self.iteration}
|
23
28
|
raw_response = await self.async_get_response(**params)
|
24
29
|
data = {
|
@@ -29,6 +34,7 @@ class InvigilatorAI(PromptConstructorMixin, InvigilatorBase):
|
|
29
34
|
"raw_model_response": raw_response["raw_model_response"],
|
30
35
|
}
|
31
36
|
response = self._format_raw_response(**data)
|
37
|
+
# breakpoint()
|
32
38
|
return AgentResponseDict(**response)
|
33
39
|
|
34
40
|
async def async_get_response(
|
@@ -97,7 +103,6 @@ class InvigilatorAI(PromptConstructorMixin, InvigilatorBase):
|
|
97
103
|
answer = question._translate_answer_code_to_answer(
|
98
104
|
response["answer"], combined_dict
|
99
105
|
)
|
100
|
-
# breakpoint()
|
101
106
|
data = {
|
102
107
|
"answer": answer,
|
103
108
|
"comment": response.get(
|
@@ -275,8 +275,25 @@ class PromptConstructorMixin:
|
|
275
275
|
if (new_question := question.split("_comment")[0]) in d:
|
276
276
|
d[new_question].comment = answer
|
277
277
|
|
278
|
+
question_data = self.question.data.copy()
|
279
|
+
|
280
|
+
# check to see if the questio_options is actuall a string
|
281
|
+
if "question_options" in question_data:
|
282
|
+
if isinstance(self.question.data["question_options"], str):
|
283
|
+
from jinja2 import Environment, meta
|
284
|
+
|
285
|
+
env = Environment()
|
286
|
+
parsed_content = env.parse(self.question.data["question_options"])
|
287
|
+
question_option_key = list(
|
288
|
+
meta.find_undeclared_variables(parsed_content)
|
289
|
+
)[0]
|
290
|
+
question_data["question_options"] = self.scenario.get(
|
291
|
+
question_option_key
|
292
|
+
)
|
293
|
+
|
294
|
+
# breakpoint()
|
278
295
|
rendered_instructions = question_prompt.render(
|
279
|
-
|
296
|
+
question_data | self.scenario | d | {"agent": self.agent}
|
280
297
|
)
|
281
298
|
|
282
299
|
undefined_template_variables = (
|
@@ -65,6 +65,10 @@ CONFIG_MAP = {
|
|
65
65
|
# "default": None,
|
66
66
|
# "info": "This env var holds your Anthropic API key (https://www.anthropic.com/).",
|
67
67
|
# },
|
68
|
+
# "GROQ_API_KEY": {
|
69
|
+
# "default": None,
|
70
|
+
# "info": "This env var holds your GROQ API key (https://console.groq.com/login).",
|
71
|
+
# },
|
68
72
|
}
|
69
73
|
|
70
74
|
|
@@ -35,6 +35,12 @@ class Conjure:
|
|
35
35
|
# The __init__ method in Conjure won't be called because __new__ returns a different class instance.
|
36
36
|
pass
|
37
37
|
|
38
|
+
@classmethod
|
39
|
+
def example(cls):
|
40
|
+
from edsl.conjure.InputData import InputDataABC
|
41
|
+
|
42
|
+
return InputDataABC.example()
|
43
|
+
|
38
44
|
|
39
45
|
if __name__ == "__main__":
|
40
46
|
pass
|
@@ -465,6 +465,7 @@ class Coop:
|
|
465
465
|
description: Optional[str] = None,
|
466
466
|
status: RemoteJobStatus = "queued",
|
467
467
|
visibility: Optional[VisibilityType] = "unlisted",
|
468
|
+
iterations: Optional[int] = 1,
|
468
469
|
) -> dict:
|
469
470
|
"""
|
470
471
|
Send a remote inference job to the server.
|
@@ -473,6 +474,7 @@ class Coop:
|
|
473
474
|
:param optional description: A description for this entry in the remote cache.
|
474
475
|
:param status: The status of the job. Should be 'queued', unless you are debugging.
|
475
476
|
:param visibility: The visibility of the cache entry.
|
477
|
+
:param iterations: The number of times to run each interview.
|
476
478
|
|
477
479
|
>>> job = Jobs.example()
|
478
480
|
>>> coop.remote_inference_create(job=job, description="My job")
|
@@ -488,6 +490,7 @@ class Coop:
|
|
488
490
|
),
|
489
491
|
"description": description,
|
490
492
|
"status": status,
|
493
|
+
"iterations": iterations,
|
491
494
|
"visibility": visibility,
|
492
495
|
"version": self._edsl_version,
|
493
496
|
},
|
@@ -498,6 +501,7 @@ class Coop:
|
|
498
501
|
"uuid": response_json.get("jobs_uuid"),
|
499
502
|
"description": response_json.get("description"),
|
500
503
|
"status": response_json.get("status"),
|
504
|
+
"iterations": response_json.get("iterations"),
|
501
505
|
"visibility": response_json.get("visibility"),
|
502
506
|
"version": self._edsl_version,
|
503
507
|
}
|
@@ -2,6 +2,7 @@ from edsl import (
|
|
2
2
|
Agent,
|
3
3
|
AgentList,
|
4
4
|
Cache,
|
5
|
+
ModelList,
|
5
6
|
Notebook,
|
6
7
|
Results,
|
7
8
|
Scenario,
|
@@ -9,6 +10,7 @@ from edsl import (
|
|
9
10
|
Survey,
|
10
11
|
Study,
|
11
12
|
)
|
13
|
+
from edsl.language_models import LanguageModel
|
12
14
|
from edsl.questions import QuestionBase
|
13
15
|
from typing import Literal, Optional, Type, Union
|
14
16
|
|
@@ -16,6 +18,8 @@ EDSLObject = Union[
|
|
16
18
|
Agent,
|
17
19
|
AgentList,
|
18
20
|
Cache,
|
21
|
+
LanguageModel,
|
22
|
+
ModelList,
|
19
23
|
Notebook,
|
20
24
|
Type[QuestionBase],
|
21
25
|
Results,
|
@@ -29,6 +33,8 @@ ObjectType = Literal[
|
|
29
33
|
"agent",
|
30
34
|
"agent_list",
|
31
35
|
"cache",
|
36
|
+
"model",
|
37
|
+
"model_list",
|
32
38
|
"notebook",
|
33
39
|
"question",
|
34
40
|
"results",
|
@@ -62,8 +68,10 @@ class ObjectRegistry:
|
|
62
68
|
{"object_type": "agent", "edsl_class": Agent},
|
63
69
|
{"object_type": "agent_list", "edsl_class": AgentList},
|
64
70
|
{"object_type": "cache", "edsl_class": Cache},
|
65
|
-
{"object_type": "
|
71
|
+
{"object_type": "model", "edsl_class": LanguageModel},
|
72
|
+
{"object_type": "model_list", "edsl_class": ModelList},
|
66
73
|
{"object_type": "notebook", "edsl_class": Notebook},
|
74
|
+
{"object_type": "question", "edsl_class": QuestionBase},
|
67
75
|
{"object_type": "results", "edsl_class": Results},
|
68
76
|
{"object_type": "scenario", "edsl_class": Scenario},
|
69
77
|
{"object_type": "scenario_list", "edsl_class": ScenarioList},
|
@@ -41,7 +41,7 @@ class CacheHandler:
|
|
41
41
|
old_data = self.from_old_sqlite_cache()
|
42
42
|
self.cache.add_from_dict(old_data)
|
43
43
|
|
44
|
-
def create_cache_directory(self) -> None:
|
44
|
+
def create_cache_directory(self, notify = False) -> None:
|
45
45
|
"""
|
46
46
|
Create the cache directory if one is required and it does not exist.
|
47
47
|
"""
|
@@ -49,9 +49,8 @@ class CacheHandler:
|
|
49
49
|
dir_path = os.path.dirname(path)
|
50
50
|
if dir_path and not os.path.exists(dir_path):
|
51
51
|
os.makedirs(dir_path)
|
52
|
-
|
53
|
-
|
54
|
-
warnings.warn(f"Created cache directory: {dir_path}")
|
52
|
+
if notify:
|
53
|
+
print(f"Created cache directory: {dir_path}")
|
55
54
|
|
56
55
|
def gen_cache(self) -> Cache:
|
57
56
|
"""
|
@@ -59,6 +59,7 @@ class InferenceServiceType(EnumWithChecks):
|
|
59
59
|
GOOGLE = "google"
|
60
60
|
TEST = "test"
|
61
61
|
ANTHROPIC = "anthropic"
|
62
|
+
GROQ = "groq"
|
62
63
|
|
63
64
|
|
64
65
|
service_to_api_keyname = {
|
@@ -69,6 +70,7 @@ service_to_api_keyname = {
|
|
69
70
|
InferenceServiceType.GOOGLE.value: "GOOGLE_API_KEY",
|
70
71
|
InferenceServiceType.TEST.value: "TBD",
|
71
72
|
InferenceServiceType.ANTHROPIC.value: "ANTHROPIC_API_KEY",
|
73
|
+
InferenceServiceType.GROQ.value: "GROQ_API_KEY",
|
72
74
|
}
|
73
75
|
|
74
76
|
|
@@ -0,0 +1,18 @@
|
|
1
|
+
import aiohttp
|
2
|
+
import json
|
3
|
+
import requests
|
4
|
+
from typing import Any, List
|
5
|
+
|
6
|
+
# from edsl.inference_services.InferenceServiceABC import InferenceServiceABC
|
7
|
+
from edsl.language_models import LanguageModel
|
8
|
+
|
9
|
+
from edsl.inference_services.OpenAIService import OpenAIService
|
10
|
+
|
11
|
+
|
12
|
+
class DeepInfraService(OpenAIService):
|
13
|
+
"""DeepInfra service class."""
|
14
|
+
|
15
|
+
_inference_service_ = "deep_infra"
|
16
|
+
_env_key_name_ = "DEEP_INFRA_API_KEY"
|
17
|
+
_base_url_ = "https://api.deepinfra.com/v1/openai"
|
18
|
+
_models_list_cache: List[str] = []
|
@@ -0,0 +1,18 @@
|
|
1
|
+
from typing import Any, List
|
2
|
+
from edsl.inference_services.OpenAIService import OpenAIService
|
3
|
+
|
4
|
+
import groq
|
5
|
+
|
6
|
+
|
7
|
+
class GroqService(OpenAIService):
|
8
|
+
"""DeepInfra service class."""
|
9
|
+
|
10
|
+
_inference_service_ = "groq"
|
11
|
+
_env_key_name_ = "GROQ_API_KEY"
|
12
|
+
|
13
|
+
_sync_client_ = groq.Groq
|
14
|
+
_async_client_ = groq.AsyncGroq
|
15
|
+
|
16
|
+
# _base_url_ = "https://api.deepinfra.com/v1/openai"
|
17
|
+
_base_url_ = None
|
18
|
+
_models_list_cache: List[str] = []
|
@@ -15,15 +15,19 @@ class InferenceServicesCollection:
|
|
15
15
|
cls.added_models[service_name].append(model_name)
|
16
16
|
|
17
17
|
@staticmethod
|
18
|
-
def _get_service_available(service) -> list[str]:
|
18
|
+
def _get_service_available(service, warn: bool = False) -> list[str]:
|
19
19
|
from_api = True
|
20
20
|
try:
|
21
21
|
service_models = service.available()
|
22
22
|
except Exception as e:
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
23
|
+
if warn:
|
24
|
+
warnings.warn(
|
25
|
+
f"""Error getting models for {service._inference_service_}.
|
26
|
+
Check that you have properly stored your Expected Parrot API key and activated remote inference, or stored your own API keys for the language models that you want to use.
|
27
|
+
See https://docs.expectedparrot.com/en/latest/api_keys.html for instructions on storing API keys.
|
28
|
+
Relying on cache.""",
|
29
|
+
UserWarning,
|
30
|
+
)
|
27
31
|
from edsl.inference_services.models_available_cache import models_available
|
28
32
|
|
29
33
|
service_models = models_available.get(service._inference_service_, [])
|
@@ -57,4 +61,8 @@ class InferenceServicesCollection:
|
|
57
61
|
if service_name is None or service_name == service._inference_service_:
|
58
62
|
return service.create_model(model_name)
|
59
63
|
|
64
|
+
# if model_name == "test":
|
65
|
+
# from edsl.language_models import LanguageModel
|
66
|
+
# return LanguageModel(test = True)
|
67
|
+
|
60
68
|
raise Exception(f"Model {model_name} not found in any of the services")
|
@@ -1,6 +1,9 @@
|
|
1
1
|
from typing import Any, List
|
2
2
|
import re
|
3
|
-
|
3
|
+
import os
|
4
|
+
|
5
|
+
# from openai import AsyncOpenAI
|
6
|
+
import openai
|
4
7
|
|
5
8
|
from edsl.inference_services.InferenceServiceABC import InferenceServiceABC
|
6
9
|
from edsl.language_models import LanguageModel
|
@@ -12,6 +15,22 @@ class OpenAIService(InferenceServiceABC):
|
|
12
15
|
|
13
16
|
_inference_service_ = "openai"
|
14
17
|
_env_key_name_ = "OPENAI_API_KEY"
|
18
|
+
_base_url_ = None
|
19
|
+
|
20
|
+
_sync_client_ = openai.OpenAI
|
21
|
+
_async_client_ = openai.AsyncOpenAI
|
22
|
+
|
23
|
+
@classmethod
|
24
|
+
def sync_client(cls):
|
25
|
+
return cls._sync_client_(
|
26
|
+
api_key=os.getenv(cls._env_key_name_), base_url=cls._base_url_
|
27
|
+
)
|
28
|
+
|
29
|
+
@classmethod
|
30
|
+
def async_client(cls):
|
31
|
+
return cls._async_client_(
|
32
|
+
api_key=os.getenv(cls._env_key_name_), base_url=cls._base_url_
|
33
|
+
)
|
15
34
|
|
16
35
|
# TODO: Make this a coop call
|
17
36
|
model_exclude_list = [
|
@@ -31,16 +50,24 @@ class OpenAIService(InferenceServiceABC):
|
|
31
50
|
]
|
32
51
|
_models_list_cache: List[str] = []
|
33
52
|
|
53
|
+
@classmethod
|
54
|
+
def get_model_list(cls):
|
55
|
+
raw_list = cls.sync_client().models.list()
|
56
|
+
if hasattr(raw_list, "data"):
|
57
|
+
return raw_list.data
|
58
|
+
else:
|
59
|
+
return raw_list
|
60
|
+
|
34
61
|
@classmethod
|
35
62
|
def available(cls) -> List[str]:
|
36
|
-
from openai import OpenAI
|
63
|
+
# from openai import OpenAI
|
37
64
|
|
38
65
|
if not cls._models_list_cache:
|
39
66
|
try:
|
40
|
-
client = OpenAI()
|
67
|
+
# client = OpenAI(api_key = os.getenv(cls._env_key_name_), base_url = cls._base_url_)
|
41
68
|
cls._models_list_cache = [
|
42
69
|
m.id
|
43
|
-
for m in
|
70
|
+
for m in cls.get_model_list()
|
44
71
|
if m.id not in cls.model_exclude_list
|
45
72
|
]
|
46
73
|
except Exception as e:
|
@@ -78,15 +105,24 @@ class OpenAIService(InferenceServiceABC):
|
|
78
105
|
"top_logprobs": 3,
|
79
106
|
}
|
80
107
|
|
108
|
+
def sync_client(self):
|
109
|
+
return cls.sync_client()
|
110
|
+
|
111
|
+
def async_client(self):
|
112
|
+
return cls.async_client()
|
113
|
+
|
81
114
|
@classmethod
|
82
115
|
def available(cls) -> list[str]:
|
83
|
-
|
84
|
-
|
116
|
+
# import openai
|
117
|
+
# client = openai.OpenAI(api_key = os.getenv(cls._env_key_name_), base_url = cls._base_url_)
|
118
|
+
# return client.models.list()
|
119
|
+
return cls.sync_client().models.list()
|
85
120
|
|
86
121
|
def get_headers(self) -> dict[str, Any]:
|
87
|
-
from openai import OpenAI
|
122
|
+
# from openai import OpenAI
|
88
123
|
|
89
|
-
client = OpenAI()
|
124
|
+
# client = OpenAI(api_key = os.getenv(cls._env_key_name_), base_url = cls._base_url_)
|
125
|
+
client = self.sync_client()
|
90
126
|
response = client.chat.completions.with_raw_response.create(
|
91
127
|
messages=[
|
92
128
|
{
|
@@ -124,8 +160,8 @@ class OpenAIService(InferenceServiceABC):
|
|
124
160
|
encoded_image=None,
|
125
161
|
) -> dict[str, Any]:
|
126
162
|
"""Calls the OpenAI API and returns the API response."""
|
127
|
-
content = [{"type": "text", "text": user_prompt}]
|
128
163
|
if encoded_image:
|
164
|
+
content = [{"type": "text", "text": user_prompt}]
|
129
165
|
content.append(
|
130
166
|
{
|
131
167
|
"type": "image_url",
|
@@ -134,21 +170,28 @@ class OpenAIService(InferenceServiceABC):
|
|
134
170
|
},
|
135
171
|
}
|
136
172
|
)
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
173
|
+
else:
|
174
|
+
content = user_prompt
|
175
|
+
# self.client = AsyncOpenAI(
|
176
|
+
# api_key = os.getenv(cls._env_key_name_),
|
177
|
+
# base_url = cls._base_url_
|
178
|
+
# )
|
179
|
+
client = self.async_client()
|
180
|
+
params = {
|
181
|
+
"model": self.model,
|
182
|
+
"messages": [
|
141
183
|
{"role": "system", "content": system_prompt},
|
142
184
|
{"role": "user", "content": content},
|
143
185
|
],
|
144
|
-
temperature
|
145
|
-
max_tokens
|
146
|
-
top_p
|
147
|
-
frequency_penalty
|
148
|
-
presence_penalty
|
149
|
-
logprobs
|
150
|
-
top_logprobs
|
151
|
-
|
186
|
+
"temperature": self.temperature,
|
187
|
+
"max_tokens": self.max_tokens,
|
188
|
+
"top_p": self.top_p,
|
189
|
+
"frequency_penalty": self.frequency_penalty,
|
190
|
+
"presence_penalty": self.presence_penalty,
|
191
|
+
"logprobs": self.logprobs,
|
192
|
+
"top_logprobs": self.top_logprobs if self.logprobs else None,
|
193
|
+
}
|
194
|
+
response = await client.chat.completions.create(**params)
|
152
195
|
return response.model_dump()
|
153
196
|
|
154
197
|
@staticmethod
|
@@ -6,7 +6,8 @@ from edsl.inference_services.OpenAIService import OpenAIService
|
|
6
6
|
from edsl.inference_services.AnthropicService import AnthropicService
|
7
7
|
from edsl.inference_services.DeepInfraService import DeepInfraService
|
8
8
|
from edsl.inference_services.GoogleService import GoogleService
|
9
|
+
from edsl.inference_services.GroqService import GroqService
|
9
10
|
|
10
11
|
default = InferenceServicesCollection(
|
11
|
-
[OpenAIService, AnthropicService, DeepInfraService, GoogleService]
|
12
|
+
[OpenAIService, AnthropicService, DeepInfraService, GoogleService, GroqService]
|
12
13
|
)
|
@@ -3,9 +3,7 @@ from __future__ import annotations
|
|
3
3
|
import warnings
|
4
4
|
from itertools import product
|
5
5
|
from typing import Optional, Union, Sequence, Generator
|
6
|
-
|
7
6
|
from edsl.Base import Base
|
8
|
-
|
9
7
|
from edsl.exceptions import MissingAPIKeyError
|
10
8
|
from edsl.jobs.buckets.BucketCollection import BucketCollection
|
11
9
|
from edsl.jobs.interviews.Interview import Interview
|
@@ -321,7 +319,11 @@ class Jobs(Base):
|
|
321
319
|
self.scenarios = self.scenarios or [Scenario()]
|
322
320
|
for agent, scenario, model in product(self.agents, self.scenarios, self.models):
|
323
321
|
yield Interview(
|
324
|
-
survey=self.survey,
|
322
|
+
survey=self.survey,
|
323
|
+
agent=agent,
|
324
|
+
scenario=scenario,
|
325
|
+
model=model,
|
326
|
+
skip_retry=self.skip_retry,
|
325
327
|
)
|
326
328
|
|
327
329
|
def create_bucket_collection(self) -> BucketCollection:
|
@@ -411,6 +413,12 @@ class Jobs(Base):
|
|
411
413
|
if warn:
|
412
414
|
warnings.warn(message)
|
413
415
|
|
416
|
+
@property
|
417
|
+
def skip_retry(self):
|
418
|
+
if not hasattr(self, "_skip_retry"):
|
419
|
+
return False
|
420
|
+
return self._skip_retry
|
421
|
+
|
414
422
|
def run(
|
415
423
|
self,
|
416
424
|
n: int = 1,
|
@@ -425,6 +433,7 @@ class Jobs(Base):
|
|
425
433
|
print_exceptions=True,
|
426
434
|
remote_cache_description: Optional[str] = None,
|
427
435
|
remote_inference_description: Optional[str] = None,
|
436
|
+
skip_retry: bool = False,
|
428
437
|
) -> Results:
|
429
438
|
"""
|
430
439
|
Runs the Job: conducts Interviews and returns their results.
|
@@ -443,6 +452,7 @@ class Jobs(Base):
|
|
443
452
|
from edsl.coop.coop import Coop
|
444
453
|
|
445
454
|
self._check_parameters()
|
455
|
+
self._skip_retry = skip_retry
|
446
456
|
|
447
457
|
if batch_mode is not None:
|
448
458
|
raise NotImplementedError(
|
@@ -461,12 +471,11 @@ class Jobs(Base):
|
|
461
471
|
remote_inference = False
|
462
472
|
|
463
473
|
if remote_inference:
|
464
|
-
|
465
|
-
from
|
466
|
-
from edsl.
|
467
|
-
|
468
|
-
|
469
|
-
from edsl.surveys.Survey import Survey
|
474
|
+
import time
|
475
|
+
from datetime import datetime
|
476
|
+
from edsl.config import CONFIG
|
477
|
+
|
478
|
+
expected_parrot_url = CONFIG.get("EXPECTED_PARROT_URL")
|
470
479
|
|
471
480
|
self._output("Remote inference activated. Sending job to server...")
|
472
481
|
if remote_cache:
|
@@ -474,33 +483,60 @@ class Jobs(Base):
|
|
474
483
|
"Remote caching activated. The remote cache will be used for this job."
|
475
484
|
)
|
476
485
|
|
477
|
-
|
486
|
+
remote_job_creation_data = coop.remote_inference_create(
|
478
487
|
self,
|
479
488
|
description=remote_inference_description,
|
480
489
|
status="queued",
|
490
|
+
iterations=n,
|
481
491
|
)
|
482
|
-
|
483
|
-
|
484
|
-
|
485
|
-
|
486
|
-
|
487
|
-
|
488
|
-
|
489
|
-
|
490
|
-
|
491
|
-
|
492
|
-
|
492
|
+
time_queued = datetime.now().strftime("%m/%d/%Y %I:%M:%S %p")
|
493
|
+
job_uuid = remote_job_creation_data.get("uuid")
|
494
|
+
print(f"Remote inference started (Job uuid={job_uuid}).")
|
495
|
+
# print(f"Job queued at {time_queued}.")
|
496
|
+
job_in_queue = True
|
497
|
+
while job_in_queue:
|
498
|
+
remote_job_data = coop.remote_inference_get(job_uuid)
|
499
|
+
status = remote_job_data.get("status")
|
500
|
+
if status == "cancelled":
|
501
|
+
print("\r" + " " * 80 + "\r", end="")
|
502
|
+
print("Job cancelled by the user.")
|
503
|
+
print(
|
504
|
+
f"See {expected_parrot_url}/home/remote-inference for more details."
|
493
505
|
)
|
494
|
-
|
495
|
-
|
496
|
-
|
497
|
-
|
498
|
-
|
499
|
-
|
500
|
-
|
501
|
-
|
506
|
+
return None
|
507
|
+
elif status == "failed":
|
508
|
+
print("\r" + " " * 80 + "\r", end="")
|
509
|
+
print("Job failed.")
|
510
|
+
print(
|
511
|
+
f"See {expected_parrot_url}/home/remote-inference for more details."
|
512
|
+
)
|
513
|
+
return None
|
514
|
+
elif status == "completed":
|
515
|
+
results_uuid = remote_job_data.get("results_uuid")
|
516
|
+
results = coop.get(results_uuid, expected_object_type="results")
|
517
|
+
print("\r" + " " * 80 + "\r", end="")
|
518
|
+
print(
|
519
|
+
f"Job completed and Results stored on Coop (Results uuid={results_uuid})."
|
520
|
+
)
|
521
|
+
return results
|
522
|
+
else:
|
523
|
+
duration = 10 if len(self) < 10 else 60
|
524
|
+
time_checked = datetime.now().strftime("%Y-%m-%d %I:%M:%S %p")
|
525
|
+
frames = ["⠋", "⠙", "⠹", "⠸", "⠼", "⠴", "⠦", "⠧", "⠇", "⠏"]
|
526
|
+
start_time = time.time()
|
527
|
+
i = 0
|
528
|
+
while time.time() - start_time < duration:
|
529
|
+
print(
|
530
|
+
f"\r{frames[i % len(frames)]} Job status: {status} - last update: {time_checked}",
|
531
|
+
end="",
|
532
|
+
flush=True,
|
533
|
+
)
|
534
|
+
time.sleep(0.1)
|
535
|
+
i += 1
|
502
536
|
else:
|
503
537
|
if check_api_keys:
|
538
|
+
from edsl import Model
|
539
|
+
|
504
540
|
for model in self.models + [Model()]:
|
505
541
|
if not model.has_valid_api_key():
|
506
542
|
raise MissingAPIKeyError(
|
@@ -606,9 +642,9 @@ class Jobs(Base):
|
|
606
642
|
results = JobsRunnerAsyncio(self).run(*args, **kwargs)
|
607
643
|
return results
|
608
644
|
|
609
|
-
async def run_async(self, cache=None, **kwargs):
|
645
|
+
async def run_async(self, cache=None, n=1, **kwargs):
|
610
646
|
"""Run the job asynchronously."""
|
611
|
-
results = await JobsRunnerAsyncio(self).run_async(cache=cache, **kwargs)
|
647
|
+
results = await JobsRunnerAsyncio(self).run_async(cache=cache, n=n, **kwargs)
|
612
648
|
return results
|
613
649
|
|
614
650
|
def all_question_parameters(self):
|
@@ -688,7 +724,10 @@ class Jobs(Base):
|
|
688
724
|
#######################
|
689
725
|
@classmethod
|
690
726
|
def example(
|
691
|
-
cls,
|
727
|
+
cls,
|
728
|
+
throw_exception_probability: int = 0,
|
729
|
+
randomize: bool = False,
|
730
|
+
test_model=False,
|
692
731
|
) -> Jobs:
|
693
732
|
"""Return an example Jobs instance.
|
694
733
|
|
@@ -706,6 +745,11 @@ class Jobs(Base):
|
|
706
745
|
|
707
746
|
addition = "" if not randomize else str(uuid4())
|
708
747
|
|
748
|
+
if test_model:
|
749
|
+
from edsl.language_models import LanguageModel
|
750
|
+
|
751
|
+
m = LanguageModel.example(test_model=True)
|
752
|
+
|
709
753
|
# (status, question, period)
|
710
754
|
agent_answers = {
|
711
755
|
("Joyful", "how_feeling", "morning"): "OK",
|
@@ -753,7 +797,10 @@ class Jobs(Base):
|
|
753
797
|
Scenario({"period": "afternoon"}),
|
754
798
|
]
|
755
799
|
)
|
756
|
-
|
800
|
+
if test_model:
|
801
|
+
job = base_survey.by(m).by(scenario_list).by(joy_agent, sad_agent)
|
802
|
+
else:
|
803
|
+
job = base_survey.by(scenario_list).by(joy_agent, sad_agent)
|
757
804
|
|
758
805
|
return job
|
759
806
|
|