edsl 0.1.37.dev4__tar.gz → 0.1.37.dev6__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.37.dev4 → edsl-0.1.37.dev6}/PKG-INFO +1 -1
- edsl-0.1.37.dev6/edsl/__version__.py +1 -0
- {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/agents/Agent.py +86 -35
- {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/agents/AgentList.py +5 -0
- {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/agents/InvigilatorBase.py +2 -23
- {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/agents/PromptConstructor.py +147 -106
- {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/agents/descriptors.py +17 -4
- {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/config.py +1 -1
- {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/conjure/AgentConstructionMixin.py +11 -3
- {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/conversation/Conversation.py +66 -14
- edsl-0.1.37.dev6/edsl/conversation/chips.py +95 -0
- {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/coop/coop.py +134 -3
- {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/data/Cache.py +1 -1
- edsl-0.1.37.dev6/edsl/exceptions/BaseException.py +21 -0
- {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/exceptions/__init__.py +7 -3
- edsl-0.1.37.dev6/edsl/exceptions/agents.py +38 -0
- edsl-0.1.37.dev6/edsl/exceptions/results.py +29 -0
- edsl-0.1.37.dev6/edsl/exceptions/scenarios.py +22 -0
- edsl-0.1.37.dev6/edsl/exceptions/surveys.py +37 -0
- {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/inference_services/InferenceServicesCollection.py +32 -9
- {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/jobs/Jobs.py +265 -53
- {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/jobs/interviews/InterviewExceptionEntry.py +5 -1
- {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/jobs/tasks/TaskHistory.py +1 -0
- edsl-0.1.37.dev6/edsl/language_models/KeyLookup.py +30 -0
- {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/language_models/LanguageModel.py +47 -59
- {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/language_models/__init__.py +1 -0
- {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/prompts/Prompt.py +8 -4
- {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/questions/QuestionBase.py +53 -13
- {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/questions/QuestionBasePromptsMixin.py +1 -33
- {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/questions/QuestionFunctional.py +2 -2
- {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/questions/descriptors.py +23 -28
- {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/results/DatasetExportMixin.py +25 -1
- {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/results/Result.py +16 -1
- {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/results/Results.py +31 -120
- {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/results/ResultsDBMixin.py +1 -1
- {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/results/Selector.py +18 -1
- {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/scenarios/Scenario.py +48 -12
- {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/scenarios/ScenarioHtmlMixin.py +7 -2
- {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/scenarios/ScenarioList.py +12 -1
- {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/surveys/Rule.py +10 -4
- {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/surveys/Survey.py +100 -77
- {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/utilities/utilities.py +18 -0
- {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/pyproject.toml +1 -1
- edsl-0.1.37.dev4/edsl/__version__.py +0 -1
- edsl-0.1.37.dev4/edsl/exceptions/agents.py +0 -40
- edsl-0.1.37.dev4/edsl/exceptions/results.py +0 -26
- edsl-0.1.37.dev4/edsl/exceptions/surveys.py +0 -34
- {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/LICENSE +0 -0
- {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/README.md +0 -0
- {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/Base.py +0 -0
- {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/BaseDiff.py +0 -0
- {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/TemplateLoader.py +0 -0
- {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/__init__.py +0 -0
- {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/agents/Invigilator.py +0 -0
- {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/agents/__init__.py +0 -0
- {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/agents/prompt_helpers.py +0 -0
- {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/auto/AutoStudy.py +0 -0
- {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/auto/StageBase.py +0 -0
- {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/auto/StageGenerateSurvey.py +0 -0
- {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/auto/StageLabelQuestions.py +0 -0
- {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/auto/StagePersona.py +0 -0
- {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/auto/StagePersonaDimensionValueRanges.py +0 -0
- {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/auto/StagePersonaDimensionValues.py +0 -0
- {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/auto/StagePersonaDimensions.py +0 -0
- {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/auto/StageQuestions.py +0 -0
- {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/auto/SurveyCreatorPipeline.py +0 -0
- {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/auto/utilities.py +0 -0
- {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/base/Base.py +0 -0
- {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/conjure/Conjure.py +0 -0
- {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/conjure/InputData.py +0 -0
- {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/conjure/InputDataCSV.py +0 -0
- {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/conjure/InputDataMixinQuestionStats.py +0 -0
- {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/conjure/InputDataPyRead.py +0 -0
- {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/conjure/InputDataSPSS.py +0 -0
- {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/conjure/InputDataStata.py +0 -0
- {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/conjure/QuestionOptionMixin.py +0 -0
- {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/conjure/QuestionTypeMixin.py +0 -0
- {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/conjure/RawQuestion.py +0 -0
- {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/conjure/SurveyResponses.py +0 -0
- {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/conjure/__init__.py +0 -0
- {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/conjure/examples/placeholder.txt +0 -0
- {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/conjure/naming_utilities.py +0 -0
- {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/conjure/utilities.py +0 -0
- {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/conversation/car_buying.py +0 -0
- {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/conversation/mug_negotiation.py +0 -0
- {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/conversation/next_speaker_utilities.py +0 -0
- {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/coop/PriceFetcher.py +0 -0
- {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/coop/__init__.py +0 -0
- {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/coop/utils.py +0 -0
- {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/data/CacheEntry.py +0 -0
- {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/data/CacheHandler.py +0 -0
- {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/data/RemoteCacheSync.py +0 -0
- {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/data/SQLiteDict.py +0 -0
- {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/data/__init__.py +0 -0
- {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/data/orm.py +0 -0
- {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/data_transfer_models.py +0 -0
- {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/enums.py +0 -0
- {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/exceptions/configuration.py +0 -0
- {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/exceptions/coop.py +0 -0
- {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/exceptions/data.py +0 -0
- {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/exceptions/general.py +0 -0
- {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/exceptions/jobs.py +0 -0
- {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/exceptions/language_models.py +0 -0
- {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/exceptions/prompts.py +0 -0
- {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/exceptions/questions.py +0 -0
- {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/inference_services/AnthropicService.py +0 -0
- {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/inference_services/AwsBedrock.py +0 -0
- {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/inference_services/AzureAI.py +0 -0
- {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/inference_services/DeepInfraService.py +0 -0
- {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/inference_services/GoogleService.py +0 -0
- {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/inference_services/GroqService.py +0 -0
- {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/inference_services/InferenceServiceABC.py +0 -0
- {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/inference_services/MistralAIService.py +0 -0
- {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/inference_services/OllamaService.py +0 -0
- {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/inference_services/OpenAIService.py +0 -0
- {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/inference_services/TestService.py +0 -0
- {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/inference_services/TogetherAIService.py +0 -0
- {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/inference_services/__init__.py +0 -0
- {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/inference_services/models_available_cache.py +0 -0
- {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/inference_services/rate_limits_cache.py +0 -0
- {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/inference_services/registry.py +0 -0
- {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/inference_services/write_available.py +0 -0
- {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/jobs/Answers.py +0 -0
- {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/jobs/__init__.py +0 -0
- {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/jobs/buckets/BucketCollection.py +0 -0
- {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/jobs/buckets/ModelBuckets.py +0 -0
- {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/jobs/buckets/TokenBucket.py +0 -0
- {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/jobs/interviews/Interview.py +0 -0
- {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/jobs/interviews/InterviewExceptionCollection.py +0 -0
- {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/jobs/interviews/InterviewStatistic.py +0 -0
- {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/jobs/interviews/InterviewStatisticsCollection.py +0 -0
- {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/jobs/interviews/InterviewStatusDictionary.py +0 -0
- {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/jobs/interviews/InterviewStatusLog.py +0 -0
- {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/jobs/interviews/ReportErrors.py +0 -0
- {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/jobs/interviews/interview_status_enum.py +0 -0
- {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/jobs/runners/JobsRunnerAsyncio.py +0 -0
- {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/jobs/runners/JobsRunnerStatus.py +0 -0
- {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/jobs/runners/JobsRunnerStatusData.py +0 -0
- {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/jobs/tasks/QuestionTaskCreator.py +0 -0
- {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/jobs/tasks/TaskCreators.py +0 -0
- {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/jobs/tasks/TaskStatusLog.py +0 -0
- {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/jobs/tasks/task_status_enum.py +0 -0
- {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/jobs/tokens/InterviewTokenUsage.py +0 -0
- {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/jobs/tokens/TokenUsage.py +0 -0
- {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/language_models/ModelList.py +0 -0
- {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/language_models/RegisterLanguageModelsMeta.py +0 -0
- {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/language_models/fake_openai_call.py +0 -0
- {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/language_models/fake_openai_service.py +0 -0
- {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/language_models/registry.py +0 -0
- {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/language_models/repair.py +0 -0
- {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/language_models/unused/ReplicateBase.py +0 -0
- {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/language_models/utilities.py +0 -0
- {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/notebooks/Notebook.py +0 -0
- {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/notebooks/__init__.py +0 -0
- {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/prompts/__init__.py +0 -0
- {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/questions/AnswerValidatorMixin.py +0 -0
- {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/questions/QuestionBaseGenMixin.py +0 -0
- {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/questions/QuestionBudget.py +0 -0
- {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/questions/QuestionCheckBox.py +0 -0
- {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/questions/QuestionExtract.py +0 -0
- {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/questions/QuestionFreeText.py +0 -0
- {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/questions/QuestionList.py +0 -0
- {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/questions/QuestionMultipleChoice.py +0 -0
- {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/questions/QuestionNumerical.py +0 -0
- {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/questions/QuestionRank.py +0 -0
- {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/questions/Quick.py +0 -0
- {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/questions/RegisterQuestionsMeta.py +0 -0
- {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/questions/ResponseValidatorABC.py +0 -0
- {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/questions/SimpleAskMixin.py +0 -0
- {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/questions/__init__.py +0 -0
- {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/questions/compose_questions.py +0 -0
- {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/questions/decorators.py +0 -0
- {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/questions/derived/QuestionLikertFive.py +0 -0
- {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/questions/derived/QuestionLinearScale.py +0 -0
- {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/questions/derived/QuestionTopK.py +0 -0
- {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/questions/derived/QuestionYesNo.py +0 -0
- {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/questions/derived/__init__.py +0 -0
- {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/questions/prompt_templates/question_budget.jinja +0 -0
- {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/questions/prompt_templates/question_checkbox.jinja +0 -0
- {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/questions/prompt_templates/question_extract.jinja +0 -0
- {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/questions/prompt_templates/question_free_text.jinja +0 -0
- {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/questions/prompt_templates/question_linear_scale.jinja +0 -0
- {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/questions/prompt_templates/question_list.jinja +0 -0
- {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/questions/prompt_templates/question_multiple_choice.jinja +0 -0
- {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/questions/prompt_templates/question_numerical.jinja +0 -0
- {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/questions/question_registry.py +0 -0
- {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/questions/settings.py +0 -0
- {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/questions/templates/__init__.py +0 -0
- {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/questions/templates/__pycache__/__init__.cpython-312.pyc +0 -0
- {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/questions/templates/budget/__init__.py +0 -0
- {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/questions/templates/budget/__pycache__/__init__.cpython-312.pyc +0 -0
- {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/questions/templates/budget/answering_instructions.jinja +0 -0
- {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/questions/templates/budget/question_presentation.jinja +0 -0
- {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/questions/templates/checkbox/__init__.py +0 -0
- {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/questions/templates/checkbox/__pycache__/__init__.cpython-312.pyc +0 -0
- {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/questions/templates/checkbox/answering_instructions.jinja +0 -0
- {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/questions/templates/checkbox/question_presentation.jinja +0 -0
- {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/questions/templates/extract/__init__.py +0 -0
- {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/questions/templates/extract/__pycache__/__init__.cpython-312.pyc +0 -0
- {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/questions/templates/extract/answering_instructions.jinja +0 -0
- {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/questions/templates/extract/question_presentation.jinja +0 -0
- {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/questions/templates/free_text/__init__.py +0 -0
- {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/questions/templates/free_text/__pycache__/__init__.cpython-312.pyc +0 -0
- {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/questions/templates/free_text/answering_instructions.jinja +0 -0
- {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/questions/templates/free_text/question_presentation.jinja +0 -0
- {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/questions/templates/likert_five/__init__.py +0 -0
- {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/questions/templates/likert_five/__pycache__/__init__.cpython-312.pyc +0 -0
- {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/questions/templates/likert_five/answering_instructions.jinja +0 -0
- {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/questions/templates/likert_five/question_presentation.jinja +0 -0
- {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/questions/templates/linear_scale/__init__.py +0 -0
- {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/questions/templates/linear_scale/__pycache__/__init__.cpython-312.pyc +0 -0
- {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/questions/templates/linear_scale/answering_instructions.jinja +0 -0
- {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/questions/templates/linear_scale/question_presentation.jinja +0 -0
- {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/questions/templates/list/__init__.py +0 -0
- {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/questions/templates/list/__pycache__/__init__.cpython-312.pyc +0 -0
- {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/questions/templates/list/answering_instructions.jinja +0 -0
- {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/questions/templates/list/question_presentation.jinja +0 -0
- {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/questions/templates/multiple_choice/__init__.py +0 -0
- {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/questions/templates/multiple_choice/__pycache__/__init__.cpython-312.pyc +0 -0
- {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/questions/templates/multiple_choice/answering_instructions.jinja +0 -0
- {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/questions/templates/multiple_choice/html.jinja +0 -0
- {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/questions/templates/multiple_choice/question_presentation.jinja +0 -0
- {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/questions/templates/numerical/__init__.py +0 -0
- {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/questions/templates/numerical/__pycache__/__init__.cpython-312.pyc +0 -0
- {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/questions/templates/numerical/answering_instructions.jinja +0 -0
- {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/questions/templates/numerical/question_presentation.jinja +0 -0
- {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/questions/templates/rank/__init__.py +0 -0
- {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/questions/templates/rank/__pycache__/__init__.cpython-312.pyc +0 -0
- {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/questions/templates/rank/answering_instructions.jinja +0 -0
- {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/questions/templates/rank/question_presentation.jinja +0 -0
- {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/questions/templates/top_k/__init__.py +0 -0
- {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/questions/templates/top_k/__pycache__/__init__.cpython-312.pyc +0 -0
- {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/questions/templates/top_k/answering_instructions.jinja +0 -0
- {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/questions/templates/top_k/question_presentation.jinja +0 -0
- {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/questions/templates/yes_no/__init__.py +0 -0
- {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/questions/templates/yes_no/__pycache__/__init__.cpython-312.pyc +0 -0
- {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/questions/templates/yes_no/answering_instructions.jinja +0 -0
- {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/questions/templates/yes_no/question_presentation.jinja +0 -0
- {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/results/Dataset.py +0 -0
- {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/results/DatasetTree.py +0 -0
- {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/results/ResultsExportMixin.py +0 -0
- {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/results/ResultsFetchMixin.py +0 -0
- {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/results/ResultsGGMixin.py +0 -0
- {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/results/ResultsToolsMixin.py +0 -0
- {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/results/__init__.py +0 -0
- {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/results/tree_explore.py +0 -0
- {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/scenarios/FileStore.py +0 -0
- {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/scenarios/ScenarioListExportMixin.py +0 -0
- {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/scenarios/ScenarioListPdfMixin.py +0 -0
- {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/scenarios/__init__.py +0 -0
- {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/shared.py +0 -0
- {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/study/ObjectEntry.py +0 -0
- {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/study/ProofOfWork.py +0 -0
- {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/study/SnapShot.py +0 -0
- {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/study/Study.py +0 -0
- {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/study/__init__.py +0 -0
- {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/surveys/DAG.py +0 -0
- {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/surveys/Memory.py +0 -0
- {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/surveys/MemoryPlan.py +0 -0
- {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/surveys/RuleCollection.py +0 -0
- {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/surveys/SurveyCSS.py +0 -0
- {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/surveys/SurveyExportMixin.py +0 -0
- {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/surveys/SurveyFlowVisualizationMixin.py +0 -0
- {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/surveys/SurveyQualtricsImport.py +0 -0
- {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/surveys/__init__.py +0 -0
- {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/surveys/base.py +0 -0
- {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/surveys/descriptors.py +0 -0
- {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/surveys/instructions/ChangeInstruction.py +0 -0
- {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/surveys/instructions/Instruction.py +0 -0
- {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/surveys/instructions/InstructionCollection.py +0 -0
- {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/surveys/instructions/__init__.py +0 -0
- {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/templates/error_reporting/base.html +0 -0
- {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/templates/error_reporting/exceptions_by_model.html +0 -0
- {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/templates/error_reporting/exceptions_by_question_name.html +0 -0
- {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/templates/error_reporting/exceptions_by_type.html +0 -0
- {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/templates/error_reporting/interview_details.html +0 -0
- {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/templates/error_reporting/interviews.html +0 -0
- {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/templates/error_reporting/overview.html +0 -0
- {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/templates/error_reporting/performance_plot.html +0 -0
- {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/templates/error_reporting/report.css +0 -0
- {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/templates/error_reporting/report.html +0 -0
- {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/templates/error_reporting/report.js +0 -0
- {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/tools/__init__.py +0 -0
- {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/tools/clusters.py +0 -0
- {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/tools/embeddings.py +0 -0
- {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/tools/embeddings_plotting.py +0 -0
- {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/tools/plotting.py +0 -0
- {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/tools/summarize.py +0 -0
- {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/utilities/SystemInfo.py +0 -0
- {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/utilities/__init__.py +0 -0
- {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/utilities/ast_utilities.py +0 -0
- {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/utilities/data/Registry.py +0 -0
- {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/utilities/data/__init__.py +0 -0
- {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/utilities/data/scooter_results.json +0 -0
- {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/utilities/decorators.py +0 -0
- {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/utilities/gcp_bucket/__init__.py +0 -0
- {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/utilities/gcp_bucket/cloud_storage.py +0 -0
- {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/utilities/interface.py +0 -0
- {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/utilities/repair_functions.py +0 -0
- {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/utilities/restricted_python.py +0 -0
@@ -0,0 +1 @@
|
|
1
|
+
__version__ = "0.1.37.dev6"
|
@@ -4,14 +4,23 @@ from __future__ import annotations
|
|
4
4
|
import copy
|
5
5
|
import inspect
|
6
6
|
import types
|
7
|
-
from typing import Callable, Optional, Union, Any
|
7
|
+
from typing import Callable, Optional, Union, Any, TYPE_CHECKING
|
8
|
+
|
9
|
+
if TYPE_CHECKING:
|
10
|
+
from edsl import Cache, Survey, Scenario
|
11
|
+
from edsl.language_models import LanguageModel
|
12
|
+
from edsl.surveys.MemoryPlan import MemoryPlan
|
13
|
+
from edsl.questions import QuestionBase
|
14
|
+
from edsl.agents.Invigilator import InvigilatorBase
|
15
|
+
|
8
16
|
from uuid import uuid4
|
9
|
-
from edsl.Base import Base
|
10
17
|
|
18
|
+
from edsl.Base import Base
|
11
19
|
from edsl.prompts import Prompt
|
12
20
|
from edsl.exceptions import QuestionScenarioRenderError
|
13
21
|
|
14
22
|
from edsl.exceptions.agents import (
|
23
|
+
AgentErrors,
|
15
24
|
AgentCombinationError,
|
16
25
|
AgentDirectAnswerFunctionError,
|
17
26
|
AgentDynamicTraitsFunctionError,
|
@@ -33,7 +42,9 @@ from edsl.utilities.restricted_python import create_restricted_function
|
|
33
42
|
|
34
43
|
|
35
44
|
class Agent(Base):
|
36
|
-
"""An
|
45
|
+
"""An class representing an agent that can answer questions."""
|
46
|
+
|
47
|
+
__doc__ = "https://docs.expectedparrot.com/en/latest/agents.html"
|
37
48
|
|
38
49
|
default_instruction = """You are answering questions as if you were a human. Do not break character."""
|
39
50
|
|
@@ -148,9 +159,10 @@ class Agent(Base):
|
|
148
159
|
self.current_question = None
|
149
160
|
|
150
161
|
if traits_presentation_template is not None:
|
162
|
+
self._traits_presentation_template = traits_presentation_template
|
151
163
|
self.traits_presentation_template = traits_presentation_template
|
152
164
|
else:
|
153
|
-
self.traits_presentation_template = "
|
165
|
+
self.traits_presentation_template = "Your traits: {{traits}}"
|
154
166
|
|
155
167
|
@property
|
156
168
|
def agent_persona(self) -> Prompt:
|
@@ -181,13 +193,23 @@ class Agent(Base):
|
|
181
193
|
"""Check whether dynamic trait function is valid.
|
182
194
|
|
183
195
|
This checks whether the dynamic traits function is valid.
|
196
|
+
|
197
|
+
>>> def f(question): return {"age": 10, "hair": "brown", "height": 5.5}
|
198
|
+
>>> a = Agent(dynamic_traits_function = f)
|
199
|
+
>>> a._check_dynamic_traits_function()
|
200
|
+
|
201
|
+
>>> def g(question, poo): return {"age": 10, "hair": "brown", "height": 5.5}
|
202
|
+
>>> a = Agent(dynamic_traits_function = g)
|
203
|
+
Traceback (most recent call last):
|
204
|
+
...
|
205
|
+
edsl.exceptions.agents.AgentDynamicTraitsFunctionError: ...
|
184
206
|
"""
|
185
207
|
if self.has_dynamic_traits_function:
|
186
208
|
sig = inspect.signature(self.dynamic_traits_function)
|
187
209
|
if "question" in sig.parameters:
|
188
210
|
if len(sig.parameters) > 1:
|
189
211
|
raise AgentDynamicTraitsFunctionError(
|
190
|
-
f"The dynamic traits function {self.dynamic_traits_function} has too many parameters. It should only have one parameter: 'question'."
|
212
|
+
message=f"The dynamic traits function {self.dynamic_traits_function} has too many parameters. It should only have one parameter: 'question'."
|
191
213
|
)
|
192
214
|
else:
|
193
215
|
if len(sig.parameters) > 0:
|
@@ -221,7 +243,38 @@ class Agent(Base):
|
|
221
243
|
else:
|
222
244
|
return self._traits
|
223
245
|
|
224
|
-
def rename(
|
246
|
+
def rename(
|
247
|
+
self, old_name_or_dict: Union[str, dict], new_name: Optional[str] = None
|
248
|
+
) -> Agent:
|
249
|
+
"""Rename a trait.
|
250
|
+
|
251
|
+
Example usage:
|
252
|
+
|
253
|
+
>>> a = Agent(traits = {"age": 10, "hair": "brown", "height": 5.5})
|
254
|
+
>>> a.rename("age", "years") == Agent(traits = {'years': 10, 'hair': 'brown', 'height': 5.5})
|
255
|
+
True
|
256
|
+
|
257
|
+
>>> a.rename({'years': 'smage'})
|
258
|
+
Agent(traits = {'hair': 'brown', 'height': 5.5, 'smage': 10})
|
259
|
+
|
260
|
+
"""
|
261
|
+
if isinstance(old_name_or_dict, dict) and new_name is None:
|
262
|
+
for old_name, new_name in old_name_or_dict.items():
|
263
|
+
self = self._rename(old_name, new_name)
|
264
|
+
return self
|
265
|
+
|
266
|
+
if isinstance(old_name_or_dict, dict) and new_name:
|
267
|
+
raise AgentErrors(
|
268
|
+
f"You passed a dict: {old_name_or_dict} and a new name: {new_name}. You should pass only a dict."
|
269
|
+
)
|
270
|
+
|
271
|
+
if isinstance(old_name_or_dict, str):
|
272
|
+
self._rename(old_name_or_dict, new_name)
|
273
|
+
return self
|
274
|
+
|
275
|
+
raise AgentErrors("Something is not right with Agent renaming")
|
276
|
+
|
277
|
+
def _rename(self, old_name: str, new_name: str) -> Agent:
|
225
278
|
"""Rename a trait.
|
226
279
|
|
227
280
|
Example usage:
|
@@ -267,8 +320,11 @@ class Agent(Base):
|
|
267
320
|
translate_response: bool = False,
|
268
321
|
) -> None:
|
269
322
|
"""Add a method to the agent that can answer a particular question type.
|
323
|
+
https://docs.expectedparrot.com/en/latest/agents.html#agent-direct-answering-methods
|
270
324
|
|
271
325
|
:param method: A method that can answer a question directly.
|
326
|
+
:param validate_response: Whether to validate the response.
|
327
|
+
:param translate_response: Whether to translate the response.
|
272
328
|
|
273
329
|
Example usage:
|
274
330
|
|
@@ -304,10 +360,10 @@ class Agent(Base):
|
|
304
360
|
question: "QuestionBase",
|
305
361
|
cache: "Cache",
|
306
362
|
survey: Optional["Survey"] = None,
|
307
|
-
scenario: Optional[Scenario] = None,
|
308
|
-
model: Optional[LanguageModel] = None,
|
363
|
+
scenario: Optional["Scenario"] = None,
|
364
|
+
model: Optional["LanguageModel"] = None,
|
309
365
|
debug: bool = False,
|
310
|
-
memory_plan: Optional[MemoryPlan] = None,
|
366
|
+
memory_plan: Optional["MemoryPlan"] = None,
|
311
367
|
current_answers: Optional[dict] = None,
|
312
368
|
iteration: int = 1,
|
313
369
|
sidecar_model=None,
|
@@ -354,13 +410,13 @@ class Agent(Base):
|
|
354
410
|
async def async_answer_question(
|
355
411
|
self,
|
356
412
|
*,
|
357
|
-
question:
|
358
|
-
cache:
|
359
|
-
scenario: Optional[
|
360
|
-
survey: Optional[
|
361
|
-
model: Optional[
|
413
|
+
question: QuestionBase,
|
414
|
+
cache: Cache,
|
415
|
+
scenario: Optional[Scenario] = None,
|
416
|
+
survey: Optional[Survey] = None,
|
417
|
+
model: Optional[LanguageModel] = None,
|
362
418
|
debug: bool = False,
|
363
|
-
memory_plan: Optional[
|
419
|
+
memory_plan: Optional[MemoryPlan] = None,
|
364
420
|
current_answers: Optional[dict] = None,
|
365
421
|
iteration: int = 0,
|
366
422
|
) -> AgentResponseDict:
|
@@ -404,13 +460,13 @@ class Agent(Base):
|
|
404
460
|
|
405
461
|
def _create_invigilator(
|
406
462
|
self,
|
407
|
-
question:
|
408
|
-
cache: Optional[
|
409
|
-
scenario: Optional[
|
410
|
-
model: Optional[
|
411
|
-
survey: Optional[
|
463
|
+
question: QuestionBase,
|
464
|
+
cache: Optional[Cache] = None,
|
465
|
+
scenario: Optional[Scenario] = None,
|
466
|
+
model: Optional[LanguageModel] = None,
|
467
|
+
survey: Optional[Survey] = None,
|
412
468
|
debug: bool = False,
|
413
|
-
memory_plan: Optional[
|
469
|
+
memory_plan: Optional[MemoryPlan] = None,
|
414
470
|
current_answers: Optional[dict] = None,
|
415
471
|
iteration: int = 0,
|
416
472
|
sidecar_model=None,
|
@@ -493,9 +549,6 @@ class Agent(Base):
|
|
493
549
|
|
494
550
|
return Agent(traits={trait: self.traits[trait] for trait in traits_to_select})
|
495
551
|
|
496
|
-
################
|
497
|
-
# Dunder Methods
|
498
|
-
################
|
499
552
|
def __add__(self, other_agent: Optional[Agent] = None) -> Agent:
|
500
553
|
"""
|
501
554
|
Combine two agents by joining their traits.
|
@@ -512,6 +565,7 @@ class Agent(Base):
|
|
512
565
|
Traceback (most recent call last):
|
513
566
|
...
|
514
567
|
edsl.exceptions.agents.AgentCombinationError: The agents have overlapping traits: {'age'}.
|
568
|
+
...
|
515
569
|
"""
|
516
570
|
if other_agent is None:
|
517
571
|
return self
|
@@ -540,12 +594,12 @@ class Agent(Base):
|
|
540
594
|
|
541
595
|
def __getattr__(self, name):
|
542
596
|
# This will be called only if 'name' is not found in the usual places
|
543
|
-
# breakpoint()
|
544
597
|
if name == "has_dynamic_traits_function":
|
545
598
|
return self.has_dynamic_traits_function
|
546
599
|
|
547
600
|
if name in self._traits:
|
548
601
|
return self._traits[name]
|
602
|
+
|
549
603
|
raise AttributeError(
|
550
604
|
f"'{type(self).__name__}' object has no attribute '{name}'"
|
551
605
|
)
|
@@ -598,6 +652,7 @@ class Agent(Base):
|
|
598
652
|
for k, v in self.__dict__.items()
|
599
653
|
if k.startswith("_")
|
600
654
|
}
|
655
|
+
|
601
656
|
if hasattr(self, "set_instructions"):
|
602
657
|
if not self.set_instructions:
|
603
658
|
raw_data.pop("instruction")
|
@@ -622,8 +677,6 @@ class Agent(Base):
|
|
622
677
|
"answer_question_directly", None
|
623
678
|
) # in case answer_question_directly will appear with _ in self.__dict__
|
624
679
|
answer_question_directly_func = self.answer_question_directly
|
625
|
-
# print(answer_question_directly_func)
|
626
|
-
# print(type(answer_question_directly_func), flush=True)
|
627
680
|
|
628
681
|
if (
|
629
682
|
answer_question_directly_func
|
@@ -644,12 +697,12 @@ class Agent(Base):
|
|
644
697
|
return dict_hash(self._to_dict())
|
645
698
|
|
646
699
|
def _to_dict(self) -> dict[str, Union[dict, bool]]:
|
647
|
-
"""Serialize to a dictionary
|
700
|
+
"""Serialize to a dictionary without EDSL info"""
|
648
701
|
return self.data
|
649
702
|
|
650
703
|
@add_edsl_version
|
651
704
|
def to_dict(self) -> dict[str, Union[dict, bool]]:
|
652
|
-
"""Serialize to a dictionary.
|
705
|
+
"""Serialize to a dictionary with EDSL info.
|
653
706
|
|
654
707
|
Example usage:
|
655
708
|
|
@@ -672,10 +725,6 @@ class Agent(Base):
|
|
672
725
|
"""
|
673
726
|
return cls(**agent_dict)
|
674
727
|
|
675
|
-
################
|
676
|
-
# DISPLAY Methods
|
677
|
-
################
|
678
|
-
|
679
728
|
def _table(self) -> tuple[dict, list]:
|
680
729
|
"""Prepare generic table data."""
|
681
730
|
table_data = []
|
@@ -691,14 +740,16 @@ class Agent(Base):
|
|
691
740
|
return self
|
692
741
|
|
693
742
|
if isinstance(trait_name_or_dict, dict) and value:
|
694
|
-
raise
|
743
|
+
raise AgentErrors(
|
744
|
+
f"You passed a dict: {trait_name_or_dict} and a value: {value}. You should pass only a dict."
|
745
|
+
)
|
695
746
|
|
696
747
|
if isinstance(trait_name_or_dict, str):
|
697
748
|
trait = trait_name_or_dict
|
698
749
|
self.traits[trait] = value
|
699
750
|
return self
|
700
751
|
|
701
|
-
raise
|
752
|
+
raise AgentErrors("Something is not right with adding a trait to an Agent")
|
702
753
|
|
703
754
|
def remove_trait(self, trait: str) -> Agent:
|
704
755
|
"""Remove a trait from the agent.
|
@@ -151,6 +151,11 @@ class AgentList(UserList, Base):
|
|
151
151
|
with open(file_path, "r") as f:
|
152
152
|
reader = csv.DictReader(f)
|
153
153
|
for row in reader:
|
154
|
+
if "name" in row:
|
155
|
+
import warnings
|
156
|
+
|
157
|
+
warnings.warn("Using 'name' field in the CSV for the Agent name")
|
158
|
+
name_field = "name"
|
154
159
|
if name_field is not None:
|
155
160
|
agent_name = row.pop(name_field)
|
156
161
|
agent_list.append(Agent(traits=row, name=agent_name))
|
@@ -236,24 +236,6 @@ class InvigilatorBase(ABC):
|
|
236
236
|
from edsl import Model
|
237
237
|
|
238
238
|
model = Model("test", canned_response="SPAM!")
|
239
|
-
# class TestLanguageModelGood(LanguageModel):
|
240
|
-
# """A test language model."""
|
241
|
-
|
242
|
-
# _model_ = "test"
|
243
|
-
# _parameters_ = {"temperature": 0.5}
|
244
|
-
# _inference_service_ = InferenceServiceType.TEST.value
|
245
|
-
|
246
|
-
# async def async_execute_model_call(
|
247
|
-
# self, user_prompt: str, system_prompt: str
|
248
|
-
# ) -> dict[str, Any]:
|
249
|
-
# await asyncio.sleep(0.1)
|
250
|
-
# if hasattr(self, "throw_an_exception"):
|
251
|
-
# raise Exception("Error!")
|
252
|
-
# return {"message": """{"answer": "SPAM!"}"""}
|
253
|
-
|
254
|
-
# def parse_response(self, raw_response: dict[str, Any]) -> str:
|
255
|
-
# """Parse the response from the model."""
|
256
|
-
# return raw_response["message"]
|
257
239
|
|
258
240
|
if throw_an_exception:
|
259
241
|
model.throw_an_exception = True
|
@@ -263,11 +245,8 @@ class InvigilatorBase(ABC):
|
|
263
245
|
|
264
246
|
if not survey:
|
265
247
|
survey = Survey.example()
|
266
|
-
|
267
|
-
|
268
|
-
# survey._questions[0].question_name = question.question_name
|
269
|
-
# survey.add_question(question)
|
270
|
-
if question:
|
248
|
+
|
249
|
+
if question not in survey.questions and question is not None:
|
271
250
|
survey.add_question(question)
|
272
251
|
|
273
252
|
question = question or survey.questions[0]
|
@@ -7,6 +7,23 @@ from edsl.prompts.Prompt import Prompt
|
|
7
7
|
from edsl.agents.prompt_helpers import PromptPlan
|
8
8
|
|
9
9
|
|
10
|
+
class PlaceholderAnswer:
|
11
|
+
"""A placeholder answer for when a question is not yet answered."""
|
12
|
+
|
13
|
+
def __init__(self):
|
14
|
+
self.answer = "N/A"
|
15
|
+
self.comment = "Will be populated by prior answer"
|
16
|
+
|
17
|
+
def __getitem__(self, index):
|
18
|
+
return ""
|
19
|
+
|
20
|
+
def __str__(self):
|
21
|
+
return "<<PlaceholderAnswer>>"
|
22
|
+
|
23
|
+
def __repr__(self):
|
24
|
+
return "<<PlaceholderAnswer>>"
|
25
|
+
|
26
|
+
|
10
27
|
def get_jinja2_variables(template_str: str) -> Set[str]:
|
11
28
|
"""
|
12
29
|
Extracts all variable names from a Jinja2 template using Jinja2's built-in parsing.
|
@@ -88,15 +105,20 @@ class PromptConstructor:
|
|
88
105
|
return self.agent.prompt()
|
89
106
|
|
90
107
|
def prior_answers_dict(self) -> dict:
|
108
|
+
# this is all questions
|
91
109
|
d = self.survey.question_names_to_questions()
|
92
110
|
# This attaches the answer to the question
|
93
|
-
for question
|
94
|
-
if question in
|
95
|
-
d[question].answer =
|
111
|
+
for question in d:
|
112
|
+
if question in self.current_answers:
|
113
|
+
d[question].answer = self.current_answers[question]
|
96
114
|
else:
|
97
|
-
|
98
|
-
|
99
|
-
|
115
|
+
d[question].answer = PlaceholderAnswer()
|
116
|
+
|
117
|
+
# if (new_question := question.split("_comment")[0]) in d:
|
118
|
+
# d[new_question].comment = answer
|
119
|
+
# d[question].answer = PlaceholderAnswer()
|
120
|
+
|
121
|
+
# breakpoint()
|
100
122
|
return d
|
101
123
|
|
102
124
|
@property
|
@@ -109,6 +131,123 @@ class PromptConstructor:
|
|
109
131
|
question_file_keys.append(var)
|
110
132
|
return question_file_keys
|
111
133
|
|
134
|
+
def build_replacement_dict(self, question_data: dict):
|
135
|
+
"""
|
136
|
+
Builds a dictionary of replacement values by combining multiple data sources.
|
137
|
+
"""
|
138
|
+
# File references dictionary
|
139
|
+
file_refs = {key: f"<see file {key}>" for key in self.scenario_file_keys}
|
140
|
+
|
141
|
+
# Scenario items excluding file keys
|
142
|
+
scenario_items = {
|
143
|
+
k: v for k, v in self.scenario.items() if k not in self.scenario_file_keys
|
144
|
+
}
|
145
|
+
|
146
|
+
# Question settings with defaults
|
147
|
+
question_settings = {
|
148
|
+
"use_code": getattr(self.question, "_use_code", True),
|
149
|
+
"include_comment": getattr(self.question, "_include_comment", False),
|
150
|
+
}
|
151
|
+
|
152
|
+
# Combine all dictionaries using dict.update() for clarity
|
153
|
+
replacement_dict = {}
|
154
|
+
for d in [
|
155
|
+
file_refs,
|
156
|
+
question_data,
|
157
|
+
scenario_items,
|
158
|
+
self.prior_answers_dict(),
|
159
|
+
{"agent": self.agent},
|
160
|
+
question_settings,
|
161
|
+
]:
|
162
|
+
replacement_dict.update(d)
|
163
|
+
|
164
|
+
return replacement_dict
|
165
|
+
|
166
|
+
def _get_question_options(self, question_data):
|
167
|
+
question_options_entry = question_data.get("question_options", None)
|
168
|
+
question_options = question_options_entry
|
169
|
+
|
170
|
+
placeholder = ["<< Option 1 - Placholder >>", "<< Option 2 - Placholder >>"]
|
171
|
+
|
172
|
+
if isinstance(question_options_entry, str):
|
173
|
+
env = Environment()
|
174
|
+
parsed_content = env.parse(question_options_entry)
|
175
|
+
question_option_key = list(meta.find_undeclared_variables(parsed_content))[
|
176
|
+
0
|
177
|
+
]
|
178
|
+
if isinstance(self.scenario.get(question_option_key), list):
|
179
|
+
question_options = self.scenario.get(question_option_key)
|
180
|
+
|
181
|
+
# might be getting it from the prior answers
|
182
|
+
if self.prior_answers_dict().get(question_option_key) is not None:
|
183
|
+
prior_question = self.prior_answers_dict().get(question_option_key)
|
184
|
+
if hasattr(prior_question, "answer"):
|
185
|
+
if isinstance(prior_question.answer, list):
|
186
|
+
question_options = prior_question.answer
|
187
|
+
else:
|
188
|
+
question_options = placeholder
|
189
|
+
else:
|
190
|
+
question_options = placeholder
|
191
|
+
|
192
|
+
return question_options
|
193
|
+
|
194
|
+
def build_question_instructions_prompt(self):
|
195
|
+
"""Buils the question instructions prompt."""
|
196
|
+
|
197
|
+
question_prompt = Prompt(self.question.get_instructions(model=self.model.model))
|
198
|
+
|
199
|
+
# Get the data for the question - this is a dictionary of the question data
|
200
|
+
# e.g., {'question_text': 'Do you like school?', 'question_name': 'q0', 'question_options': ['yes', 'no']}
|
201
|
+
question_data = self.question.data.copy()
|
202
|
+
|
203
|
+
if "question_options" in question_data:
|
204
|
+
question_options = self._get_question_options(question_data)
|
205
|
+
question_data["question_options"] = question_options
|
206
|
+
|
207
|
+
# check to see if the question_options is actually a string
|
208
|
+
# This is used when the user is using the question_options as a variable from a scenario
|
209
|
+
# if "question_options" in question_data:
|
210
|
+
replacement_dict = self.build_replacement_dict(question_data)
|
211
|
+
rendered_instructions = question_prompt.render(replacement_dict)
|
212
|
+
|
213
|
+
# is there anything left to render?
|
214
|
+
undefined_template_variables = (
|
215
|
+
rendered_instructions.undefined_template_variables({})
|
216
|
+
)
|
217
|
+
|
218
|
+
# Check if it's the name of a question in the survey
|
219
|
+
for question_name in self.survey.question_names:
|
220
|
+
if question_name in undefined_template_variables:
|
221
|
+
print(
|
222
|
+
"Question name found in undefined_template_variables: ",
|
223
|
+
question_name,
|
224
|
+
)
|
225
|
+
|
226
|
+
if undefined_template_variables:
|
227
|
+
msg = f"Question instructions still has variables: {undefined_template_variables}."
|
228
|
+
import warnings
|
229
|
+
|
230
|
+
warnings.warn(msg)
|
231
|
+
# raise QuestionScenarioRenderError(
|
232
|
+
# f"Question instructions still has variables: {undefined_template_variables}."
|
233
|
+
# )
|
234
|
+
|
235
|
+
# Check if question has instructions - these are instructions in a Survey that can apply to multiple follow-on questions
|
236
|
+
relevant_instructions = self.survey.relevant_instructions(
|
237
|
+
self.question.question_name
|
238
|
+
)
|
239
|
+
|
240
|
+
if relevant_instructions != []:
|
241
|
+
# preamble_text = Prompt(
|
242
|
+
# text="You were given the following instructions: "
|
243
|
+
# )
|
244
|
+
preamble_text = Prompt(text="")
|
245
|
+
for instruction in relevant_instructions:
|
246
|
+
preamble_text += instruction.text
|
247
|
+
rendered_instructions = preamble_text + rendered_instructions
|
248
|
+
|
249
|
+
return rendered_instructions
|
250
|
+
|
112
251
|
@property
|
113
252
|
def question_instructions_prompt(self) -> Prompt:
|
114
253
|
"""
|
@@ -118,109 +257,11 @@ class PromptConstructor:
|
|
118
257
|
Prompt(text=\"""...
|
119
258
|
...
|
120
259
|
"""
|
121
|
-
# The user might have passed a custom prompt, which would be stored in _question_instructions_prompt
|
122
260
|
if not hasattr(self, "_question_instructions_prompt"):
|
123
|
-
|
124
|
-
|
125
|
-
self.question.get_instructions(model=self.model.model)
|
261
|
+
self._question_instructions_prompt = (
|
262
|
+
self.build_question_instructions_prompt()
|
126
263
|
)
|
127
264
|
|
128
|
-
# Get the data for the question - this is a dictionary of the question data
|
129
|
-
# e.g., {'question_text': 'Do you like school?', 'question_name': 'q0', 'question_options': ['yes', 'no']}
|
130
|
-
question_data = self.question.data.copy()
|
131
|
-
|
132
|
-
# check to see if the question_options is actually a string
|
133
|
-
# This is used when the user is using the question_options as a variable from a scenario
|
134
|
-
# if "question_options" in question_data:
|
135
|
-
if isinstance(self.question.data.get("question_options", None), str):
|
136
|
-
env = Environment()
|
137
|
-
parsed_content = env.parse(self.question.data["question_options"])
|
138
|
-
question_option_key = list(
|
139
|
-
meta.find_undeclared_variables(parsed_content)
|
140
|
-
)[0]
|
141
|
-
|
142
|
-
# look to see if the question_option_key is in the scenario
|
143
|
-
if isinstance(
|
144
|
-
question_options := self.scenario.get(question_option_key), list
|
145
|
-
):
|
146
|
-
question_data["question_options"] = question_options
|
147
|
-
self.question.question_options = question_options
|
148
|
-
|
149
|
-
# might be getting it from the prior answers
|
150
|
-
if self.prior_answers_dict().get(question_option_key) is not None:
|
151
|
-
prior_question = self.prior_answers_dict().get(question_option_key)
|
152
|
-
if hasattr(prior_question, "answer"):
|
153
|
-
if isinstance(prior_question.answer, list):
|
154
|
-
question_data["question_options"] = prior_question.answer
|
155
|
-
self.question.question_options = prior_question.answer
|
156
|
-
else:
|
157
|
-
placeholder_options = [
|
158
|
-
"N/A",
|
159
|
-
"Will be populated by prior answer",
|
160
|
-
"These are placeholder options",
|
161
|
-
]
|
162
|
-
question_data["question_options"] = placeholder_options
|
163
|
-
self.question.question_options = placeholder_options
|
164
|
-
|
165
|
-
replacement_dict = (
|
166
|
-
{key: f"<see file {key}>" for key in self.scenario_file_keys}
|
167
|
-
| question_data
|
168
|
-
| {
|
169
|
-
k: v
|
170
|
-
for k, v in self.scenario.items()
|
171
|
-
if k not in self.scenario_file_keys
|
172
|
-
} # don't include images in the replacement dict
|
173
|
-
| self.prior_answers_dict()
|
174
|
-
| {"agent": self.agent}
|
175
|
-
| {
|
176
|
-
"use_code": getattr(self.question, "_use_code", True),
|
177
|
-
"include_comment": getattr(
|
178
|
-
self.question, "_include_comment", False
|
179
|
-
),
|
180
|
-
}
|
181
|
-
)
|
182
|
-
|
183
|
-
rendered_instructions = question_prompt.render(replacement_dict)
|
184
|
-
|
185
|
-
# is there anything left to render?
|
186
|
-
undefined_template_variables = (
|
187
|
-
rendered_instructions.undefined_template_variables({})
|
188
|
-
)
|
189
|
-
|
190
|
-
# Check if it's the name of a question in the survey
|
191
|
-
for question_name in self.survey.question_names:
|
192
|
-
if question_name in undefined_template_variables:
|
193
|
-
print(
|
194
|
-
"Question name found in undefined_template_variables: ",
|
195
|
-
question_name,
|
196
|
-
)
|
197
|
-
|
198
|
-
if undefined_template_variables:
|
199
|
-
msg = f"Question instructions still has variables: {undefined_template_variables}."
|
200
|
-
import warnings
|
201
|
-
|
202
|
-
warnings.warn(msg)
|
203
|
-
# raise QuestionScenarioRenderError(
|
204
|
-
# f"Question instructions still has variables: {undefined_template_variables}."
|
205
|
-
# )
|
206
|
-
|
207
|
-
####################################
|
208
|
-
# Check if question has instructions - these are instructions in a Survey that can apply to multiple follow-on questions
|
209
|
-
####################################
|
210
|
-
relevant_instructions = self.survey.relevant_instructions(
|
211
|
-
self.question.question_name
|
212
|
-
)
|
213
|
-
|
214
|
-
if relevant_instructions != []:
|
215
|
-
# preamble_text = Prompt(
|
216
|
-
# text="You were given the following instructions: "
|
217
|
-
# )
|
218
|
-
preamble_text = Prompt(text="")
|
219
|
-
for instruction in relevant_instructions:
|
220
|
-
preamble_text += instruction.text
|
221
|
-
rendered_instructions = preamble_text + rendered_instructions
|
222
|
-
|
223
|
-
self._question_instructions_prompt = rendered_instructions
|
224
265
|
return self._question_instructions_prompt
|
225
266
|
|
226
267
|
@property
|
@@ -4,6 +4,20 @@ from typing import Dict
|
|
4
4
|
from edsl.exceptions.agents import AgentNameError, AgentTraitKeyError
|
5
5
|
|
6
6
|
|
7
|
+
def convert_agent_name(x):
|
8
|
+
# potentially a numpy int64
|
9
|
+
import numpy as np
|
10
|
+
|
11
|
+
if isinstance(x, np.int64):
|
12
|
+
return int(x)
|
13
|
+
elif x is None:
|
14
|
+
return None
|
15
|
+
elif isinstance(x, int):
|
16
|
+
return x
|
17
|
+
else:
|
18
|
+
return str(x)
|
19
|
+
|
20
|
+
|
7
21
|
class NameDescriptor:
|
8
22
|
"""ABC for something."""
|
9
23
|
|
@@ -13,7 +27,7 @@ class NameDescriptor:
|
|
13
27
|
|
14
28
|
def __set__(self, instance, name: str) -> None:
|
15
29
|
"""Set the value of the attribute."""
|
16
|
-
instance.__dict__[self.name] = name
|
30
|
+
instance.__dict__[self.name] = convert_agent_name(name)
|
17
31
|
|
18
32
|
def __set_name__(self, owner, name: str) -> None:
|
19
33
|
"""Set the name of the attribute."""
|
@@ -34,9 +48,8 @@ class TraitsDescriptor:
|
|
34
48
|
for key, value in traits_dict.items():
|
35
49
|
if key == "name":
|
36
50
|
raise AgentNameError(
|
37
|
-
"
|
38
|
-
Agent(name="my_agent", traits={"trait1": "value1", "trait2": "value2"})
|
39
|
-
"""
|
51
|
+
"Trait keys cannot be 'name'. Instead, use the 'name' attribute directly e.g.,\n"
|
52
|
+
'Agent(name="my_agent", traits={"trait1": "value1", "trait2": "value2"})'
|
40
53
|
)
|
41
54
|
|
42
55
|
if not is_valid_variable_name(key):
|
@@ -58,7 +58,7 @@ CONFIG_MAP = {
|
|
58
58
|
"info": "This config var holds the maximum number of tokens per minute for all models. Model-specific values provided in env vars such as EDSL_SERVICE_TPM_OPENAI will override this value for the corresponding model.",
|
59
59
|
},
|
60
60
|
"EXPECTED_PARROT_URL": {
|
61
|
-
"default": "https://
|
61
|
+
"default": "https://api.expectedparrot.com",
|
62
62
|
"info": "This config var holds the URL of the Expected Parrot API.",
|
63
63
|
},
|
64
64
|
}
|