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
@@ -0,0 +1,74 @@
|
|
1
|
+
from textwrap import dedent
|
2
|
+
from dataclasses import dataclass
|
3
|
+
|
4
|
+
from typing import List, Dict
|
5
|
+
|
6
|
+
from edsl.auto.StageBase import StageBase
|
7
|
+
from edsl.auto.StageBase import FlowDataBase
|
8
|
+
|
9
|
+
from edsl.auto.StagePersonaDimensions import StagePersonaDimensions
|
10
|
+
from edsl import Model
|
11
|
+
from edsl.questions import QuestionList, QuestionExtract
|
12
|
+
from edsl.scenarios import Scenario
|
13
|
+
|
14
|
+
from edsl.auto.utilities import gen_pipeline
|
15
|
+
|
16
|
+
|
17
|
+
class StagePersonaDimensionValues(StageBase):
|
18
|
+
input = StagePersonaDimensions.output
|
19
|
+
|
20
|
+
@dataclass
|
21
|
+
class Output(FlowDataBase):
|
22
|
+
attribute_results: List[str]
|
23
|
+
dimension_values: Dict[str, str]
|
24
|
+
persona: str
|
25
|
+
|
26
|
+
output = Output
|
27
|
+
|
28
|
+
def handle_data(self, data):
|
29
|
+
attribute_results = data.attribute_results
|
30
|
+
persona = data.persona
|
31
|
+
m = Model()
|
32
|
+
q = QuestionExtract(
|
33
|
+
question_text=dedent(
|
34
|
+
"""\
|
35
|
+
This is a persona: "{{ persona }}"
|
36
|
+
They vary on the following dimensions: "{{ attribute_results }}"
|
37
|
+
For each dimenion, what are some values that this persona might have for that dimension?
|
38
|
+
Please keep answers very short, ideally one word.
|
39
|
+
"""
|
40
|
+
),
|
41
|
+
answer_template={k: None for k in attribute_results},
|
42
|
+
question_name="dimension_values",
|
43
|
+
)
|
44
|
+
results = (
|
45
|
+
q.by(Scenario({"attribute_results": attribute_results, "persona": persona}))
|
46
|
+
.by(m)
|
47
|
+
.run()
|
48
|
+
)
|
49
|
+
results.select("attribute_results", "dimension_values").print()
|
50
|
+
return self.output(
|
51
|
+
dimension_values=results.select("dimension_values").first(),
|
52
|
+
attribute_results=attribute_results,
|
53
|
+
persona=persona,
|
54
|
+
)
|
55
|
+
|
56
|
+
|
57
|
+
if __name__ == "__main__":
|
58
|
+
from edsl.auto.StageQuestions import StageQuestions
|
59
|
+
from edsl.auto.StagePersona import StagePersona
|
60
|
+
from edsl.auto.StagePersonaDimensions import StagePersonaDimensions
|
61
|
+
|
62
|
+
pipeline = gen_pipeline(
|
63
|
+
[
|
64
|
+
StageQuestions,
|
65
|
+
StagePersona,
|
66
|
+
StagePersonaDimensions,
|
67
|
+
StagePersonaDimensionValues,
|
68
|
+
]
|
69
|
+
)
|
70
|
+
pipeline.process(
|
71
|
+
pipeline.input(
|
72
|
+
overall_question="What are some factors that could determine whether someone likes ice cream?"
|
73
|
+
)
|
74
|
+
)
|
@@ -0,0 +1,69 @@
|
|
1
|
+
from textwrap import dedent
|
2
|
+
from dataclasses import dataclass
|
3
|
+
|
4
|
+
from typing import List
|
5
|
+
|
6
|
+
from edsl.auto.StageBase import StageBase
|
7
|
+
from edsl.auto.StageBase import FlowDataBase
|
8
|
+
|
9
|
+
from edsl.auto.StagePersona import StagePersona
|
10
|
+
|
11
|
+
from edsl.questions import QuestionList
|
12
|
+
from edsl.scenarios import Scenario
|
13
|
+
from edsl import Model
|
14
|
+
|
15
|
+
from edsl.auto.utilities import gen_pipeline
|
16
|
+
|
17
|
+
|
18
|
+
class StagePersonaDimensions(StageBase):
|
19
|
+
input = StagePersona.output
|
20
|
+
|
21
|
+
@dataclass
|
22
|
+
class Output(FlowDataBase):
|
23
|
+
attribute_results: List[str]
|
24
|
+
persona: str
|
25
|
+
|
26
|
+
output = Output
|
27
|
+
|
28
|
+
def handle_data(self, data):
|
29
|
+
q_attributes = QuestionList(
|
30
|
+
question_text=dedent(
|
31
|
+
"""\
|
32
|
+
Here is a persona: "{{ persona }}"
|
33
|
+
It was construced to be someone who could answer these questions: "{{ questions }}"
|
34
|
+
|
35
|
+
We want to identify the general dimensions that make up this persona.
|
36
|
+
E.g., if the person is desribed as 'happy' then a dimenion would be 'mood'
|
37
|
+
"""
|
38
|
+
),
|
39
|
+
question_name="find_attributes",
|
40
|
+
)
|
41
|
+
m = Model()
|
42
|
+
results = (
|
43
|
+
q_attributes.by(
|
44
|
+
Scenario({"persona": data.persona, "questions": data.questions})
|
45
|
+
)
|
46
|
+
.by(m)
|
47
|
+
.run()
|
48
|
+
)
|
49
|
+
(
|
50
|
+
results.select("find_attributes").print(
|
51
|
+
pretty_labels={
|
52
|
+
"answer.find_attributes": f'Persona dimensions for: "{data.persona}"'
|
53
|
+
},
|
54
|
+
split_at_dot=False,
|
55
|
+
)
|
56
|
+
)
|
57
|
+
attribute_results = results.select("find_attributes").first()
|
58
|
+
return self.output(attribute_results=attribute_results, persona=data.persona)
|
59
|
+
|
60
|
+
|
61
|
+
if __name__ == "__main__":
|
62
|
+
from edsl.auto.StageQuestions import StageQuestions
|
63
|
+
|
64
|
+
pipeline = gen_pipeline([StageQuestions, StagePersona, StagePersonaDimensions])
|
65
|
+
pipeline.process(
|
66
|
+
pipeline.input(
|
67
|
+
overall_question="What are some factors that could determine whether someone likes ice cream?"
|
68
|
+
)
|
69
|
+
)
|
@@ -0,0 +1,74 @@
|
|
1
|
+
from dataclasses import dataclass
|
2
|
+
from typing import List
|
3
|
+
from textwrap import dedent
|
4
|
+
|
5
|
+
|
6
|
+
from edsl import Scenario
|
7
|
+
from edsl import Model
|
8
|
+
from edsl.questions.QuestionList import QuestionList
|
9
|
+
|
10
|
+
from edsl.auto.StageBase import StageBase
|
11
|
+
from edsl.auto.StageBase import FlowDataBase
|
12
|
+
|
13
|
+
from edsl.auto.utilities import gen_pipeline
|
14
|
+
|
15
|
+
|
16
|
+
class StageQuestions(StageBase):
|
17
|
+
"This stages takes as input an overall question and returns a list of questions"
|
18
|
+
|
19
|
+
@dataclass
|
20
|
+
class Input(FlowDataBase):
|
21
|
+
overall_question: str
|
22
|
+
population: str
|
23
|
+
|
24
|
+
@dataclass
|
25
|
+
class Output(FlowDataBase):
|
26
|
+
questions: List[str]
|
27
|
+
population: str
|
28
|
+
|
29
|
+
input = Input
|
30
|
+
output = Output
|
31
|
+
|
32
|
+
def handle_data(self, data):
|
33
|
+
m = Model()
|
34
|
+
overall_question = data.overall_question
|
35
|
+
population = data.population
|
36
|
+
s = Scenario({"overall_question": overall_question, "population": population})
|
37
|
+
q = QuestionList(
|
38
|
+
question_text=dedent(
|
39
|
+
"""\
|
40
|
+
Suppose I am interested in the question:
|
41
|
+
"{{ overall_question }}"
|
42
|
+
What would be some survey questions I could ask to {{ population }} that might shed light on this question?
|
43
|
+
"""
|
44
|
+
),
|
45
|
+
question_name="questions",
|
46
|
+
)
|
47
|
+
results = q.by(s).by(m).run()
|
48
|
+
(
|
49
|
+
results.select("questions").print(
|
50
|
+
pretty_labels={
|
51
|
+
"answer.questions": f'Questions for overall question: "{overall_question }"'
|
52
|
+
},
|
53
|
+
split_at_dot=False,
|
54
|
+
)
|
55
|
+
)
|
56
|
+
|
57
|
+
raw_questions = results.select("questions").first()
|
58
|
+
questions = [q.replace("'", "").replace(":", "") for q in raw_questions]
|
59
|
+
return self.Output(questions=questions, population=population)
|
60
|
+
|
61
|
+
|
62
|
+
if __name__ == "__main__":
|
63
|
+
pipeline = gen_pipeline([StageQuestions])
|
64
|
+
|
65
|
+
pipeline.process(
|
66
|
+
pipeline.input(
|
67
|
+
overall_question="What are some factors that could determine whether someone likes ice cream?",
|
68
|
+
population="Consumers",
|
69
|
+
)
|
70
|
+
)
|
71
|
+
|
72
|
+
results = StageQuestions.func(
|
73
|
+
overall_question="Why aren't my students studying more?", population="Tech"
|
74
|
+
)
|
@@ -0,0 +1,21 @@
|
|
1
|
+
import random
|
2
|
+
from typing import Dict, List, Any, TypeVar, Generator, Optional
|
3
|
+
|
4
|
+
from textwrap import dedent
|
5
|
+
|
6
|
+
# from edsl.language_models.model_interfaces.LanguageModelOpenAIFour import LanguageModelOpenAIFour
|
7
|
+
from edsl import Model
|
8
|
+
from edsl.agents.AgentList import AgentList
|
9
|
+
from edsl.results.Results import Results
|
10
|
+
from edsl import Agent
|
11
|
+
|
12
|
+
from edsl import Scenario
|
13
|
+
from edsl.surveys.Survey import Survey
|
14
|
+
|
15
|
+
from edsl.questions.QuestionMultipleChoice import QuestionMultipleChoice
|
16
|
+
from edsl.questions.QuestionFreeText import QuestionFreeText
|
17
|
+
from edsl.auto.utilities import gen_pipeline
|
18
|
+
from edsl.utilities.naming_utilities import sanitize_string
|
19
|
+
|
20
|
+
|
21
|
+
m = Model()
|
edsl/auto/utilities.py
ADDED
@@ -0,0 +1,218 @@
|
|
1
|
+
from textwrap import dedent
|
2
|
+
import random
|
3
|
+
from typing import List, TypeVar, Generator, Optional
|
4
|
+
from edsl.auto.StageBase import StageBase
|
5
|
+
from edsl.utilities.naming_utilities import sanitize_string
|
6
|
+
from edsl import Agent, Survey, Model, Cache, AgentList
|
7
|
+
from edsl import QuestionFreeText, Scenario
|
8
|
+
from edsl import QuestionMultipleChoice, Scenario, Agent, ScenarioList
|
9
|
+
|
10
|
+
StageClassType = TypeVar("StageClassType", bound=StageBase)
|
11
|
+
|
12
|
+
|
13
|
+
def gen_pipeline(stages_list: List[StageClassType]) -> StageBase:
|
14
|
+
"""Takes as input a list of Stage classes & returns a pipeline of instantiated stages.
|
15
|
+
A pipeline is a linked list of stages where each stage has a next_stage attribute.
|
16
|
+
|
17
|
+
"""
|
18
|
+
pipeline = stages_list[0]()
|
19
|
+
last_stage = pipeline
|
20
|
+
for stage in stages_list[1:]:
|
21
|
+
while last_stage.next_stage is not None: # find the end of the pipeline
|
22
|
+
last_stage = last_stage.next_stage
|
23
|
+
stage_to_add = stage()
|
24
|
+
last_stage.next_stage = stage_to_add
|
25
|
+
return pipeline
|
26
|
+
|
27
|
+
|
28
|
+
q_eligibility = QuestionMultipleChoice(
|
29
|
+
question_text=dedent(
|
30
|
+
"""\
|
31
|
+
Consider this set of question: '{{ questions }}'.
|
32
|
+
Consider this persona: '{{ persona }}'.
|
33
|
+
Would this persona be able to answer all of these questions?
|
34
|
+
"""
|
35
|
+
),
|
36
|
+
question_options=["No", "Yes"],
|
37
|
+
question_name="eligibility",
|
38
|
+
)
|
39
|
+
|
40
|
+
|
41
|
+
def agent_list_eligibility(
|
42
|
+
agent_list: AgentList,
|
43
|
+
survey: Optional[Survey] = None,
|
44
|
+
model: Optional[Model] = None,
|
45
|
+
cache: Optional[Cache] = None,
|
46
|
+
) -> List[bool]:
|
47
|
+
"""
|
48
|
+
Returns whether each agent in a list is elgible for a survey i.e., can answer every question.
|
49
|
+
|
50
|
+
>>> from edsl.language_models import LanguageModel
|
51
|
+
>>> m = LanguageModel.example(canned_response = "1", test_model = True)
|
52
|
+
>>> agent_list_eligibility(AgentList.example())
|
53
|
+
[True, True]
|
54
|
+
>>> agent_list_eligibility(AgentList.example().add_trait('persona', 2*["Cool dude"]), survey = Survey.example(), model = m)
|
55
|
+
[True, True]
|
56
|
+
"""
|
57
|
+
if survey is None:
|
58
|
+
return [True] * len(agent_list)
|
59
|
+
if "persona" not in agent_list.all_traits:
|
60
|
+
raise ValueError(
|
61
|
+
f"Each agent needs to have a persona attribute; traits are {agent_list.all_traits}"
|
62
|
+
)
|
63
|
+
sl = agent_list.select("persona").to_scenario_list()
|
64
|
+
sl.add_value("questions", [q.question_text for q in survey._questions])
|
65
|
+
results = q_eligibility.by(sl).by(model).run(cache=cache)
|
66
|
+
return [r == "Yes" for r in results.select("eligibility").to_list()]
|
67
|
+
|
68
|
+
|
69
|
+
def agent_eligibility(
|
70
|
+
agent: Agent,
|
71
|
+
survey: Survey,
|
72
|
+
model: Optional[Model] = None,
|
73
|
+
cache: Optional[Cache] = None,
|
74
|
+
) -> bool:
|
75
|
+
"""NB: This could be parallelized.
|
76
|
+
|
77
|
+
>>> from edsl.language_models import LanguageModel
|
78
|
+
>>> m = LanguageModel.example(canned_response = "1", test_model = True)
|
79
|
+
>>> agent_eligibility(agent = Agent.example().add_trait({'persona': "Persona"}), survey = Survey.example(), model = m)
|
80
|
+
True
|
81
|
+
|
82
|
+
"""
|
83
|
+
model = model or Model()
|
84
|
+
|
85
|
+
questions = [q.question_text for q in survey._questions]
|
86
|
+
persona = agent.traits["persona"]
|
87
|
+
return (
|
88
|
+
q_eligibility(model=model, questions=questions, persona=persona, cache=cache)
|
89
|
+
== "Yes"
|
90
|
+
)
|
91
|
+
|
92
|
+
|
93
|
+
def gen_agent_traits(dimension_dict: dict, seed_value: Optional[str] = None):
|
94
|
+
"""
|
95
|
+
>>> dimension_dict = {'attitude':['positive', 'negative']}
|
96
|
+
>>> ag = gen_agent_traits(dimension_dict)
|
97
|
+
>>> a = next(ag)
|
98
|
+
>>> a == {'attitude': 'positive'} or a == {'attitude': 'negative'}
|
99
|
+
True
|
100
|
+
>>> len([next(ag) for _ in range(100)])
|
101
|
+
100
|
102
|
+
"""
|
103
|
+
if seed_value is None:
|
104
|
+
seed_value = "edsl"
|
105
|
+
|
106
|
+
random.seed(seed_value)
|
107
|
+
|
108
|
+
while True:
|
109
|
+
new_agent_traits = {}
|
110
|
+
for key, list_of_values in dimension_dict.items():
|
111
|
+
new_agent_traits[key] = random.choice(list_of_values)
|
112
|
+
yield new_agent_traits
|
113
|
+
|
114
|
+
|
115
|
+
def agent_generator(
|
116
|
+
persona: str,
|
117
|
+
dimension_dict: dict,
|
118
|
+
model: Optional[Model] = None,
|
119
|
+
cache: Optional["Cache"] = None,
|
120
|
+
) -> Generator["Results", None, None]:
|
121
|
+
"""
|
122
|
+
>>> from edsl.language_models import LanguageModel
|
123
|
+
>>> m = LanguageModel.example(canned_response = "This is a cool dude.", test_model = True)
|
124
|
+
>>> ag = agent_generator(persona = "Base person", dimension_dict = {'attitude':['Positive', 'Negative']}, model = m)
|
125
|
+
>>> next(ag).select('new_agent_persona').first()
|
126
|
+
'This is a cool dude.'
|
127
|
+
>>> next(ag).select('new_agent_persona').first()
|
128
|
+
'This is a cool dude.'
|
129
|
+
"""
|
130
|
+
|
131
|
+
if model is None:
|
132
|
+
model = Model()
|
133
|
+
|
134
|
+
q = QuestionFreeText(
|
135
|
+
question_text=dedent(
|
136
|
+
"""\
|
137
|
+
Consider this persona: '{{ persona }}'.
|
138
|
+
Now imagine writing a new persona with these traits:
|
139
|
+
'{{ new_agent_traits }}'
|
140
|
+
Please write this persona as a narrative.
|
141
|
+
"""
|
142
|
+
),
|
143
|
+
question_name="new_agent_persona",
|
144
|
+
)
|
145
|
+
agent_trait_generator = gen_agent_traits(dimension_dict)
|
146
|
+
codebook = {sanitize_string(k): k for k in dimension_dict.keys()}
|
147
|
+
while True:
|
148
|
+
new_agent_traits = next(agent_trait_generator)
|
149
|
+
yield q(
|
150
|
+
persona=persona,
|
151
|
+
new_agent_traits=new_agent_traits,
|
152
|
+
codebook=codebook,
|
153
|
+
just_answer=False,
|
154
|
+
cache=cache,
|
155
|
+
model=model,
|
156
|
+
)
|
157
|
+
|
158
|
+
|
159
|
+
def create_agents(
|
160
|
+
agent_generator: Generator["Results", None, None],
|
161
|
+
survey: Optional[Survey] = None,
|
162
|
+
num_agents=11,
|
163
|
+
) -> AgentList:
|
164
|
+
"""
|
165
|
+
>>> from edsl.language_models import LanguageModel
|
166
|
+
>>> m = LanguageModel.example(canned_response = "This is a cool dude.", test_model = True)
|
167
|
+
>>> ag = agent_generator(persona = "Base person", dimension_dict = {'attitude':['Positive', 'Negative']}, model = m)
|
168
|
+
>>> new_agent_list = create_agents(agent_generator = ag)
|
169
|
+
>>> new_agent_list
|
170
|
+
|
171
|
+
"""
|
172
|
+
agent_list = AgentList([])
|
173
|
+
|
174
|
+
MAX_ITERATIONS_MULTIPLIER = 2
|
175
|
+
iterations = 0
|
176
|
+
|
177
|
+
while len(agent_list) < num_agents:
|
178
|
+
iterations += 1
|
179
|
+
candidate_agent = next(agent_generator)
|
180
|
+
codebook = candidate_agent.select("codebook").to_list()[0]
|
181
|
+
|
182
|
+
koobedoc = {v: k for k, v in codebook.items()}
|
183
|
+
persona = candidate_agent.select("new_agent_persona").to_list()[0]
|
184
|
+
traits = candidate_agent.select("new_agent_traits").to_list()[0]
|
185
|
+
new_traits = {koobedoc[key]: value for key, value in traits.items()} | {
|
186
|
+
"persona": persona
|
187
|
+
}
|
188
|
+
agent = Agent(traits=new_traits, codebook=codebook)
|
189
|
+
if survey is not None:
|
190
|
+
if agent_eligibility(agent, survey):
|
191
|
+
agent_list.append(agent)
|
192
|
+
else:
|
193
|
+
print("Agent not eligible")
|
194
|
+
else:
|
195
|
+
agent_list.append(agent)
|
196
|
+
|
197
|
+
if iterations > MAX_ITERATIONS_MULTIPLIER * num_agents:
|
198
|
+
raise Exception("Too many failures")
|
199
|
+
|
200
|
+
return agent_list
|
201
|
+
|
202
|
+
|
203
|
+
if __name__ == "__main__":
|
204
|
+
import doctest
|
205
|
+
|
206
|
+
doctest.testmod()
|
207
|
+
# from edsl.language_models import LanguageModel
|
208
|
+
|
209
|
+
# m = LanguageModel.example(canned_response="This is a cool dude.", test_model=True)
|
210
|
+
# ag = agent_generator(
|
211
|
+
# persona="Base person",
|
212
|
+
# dimension_dict={"attitude": ["Positive", "Negative"]},
|
213
|
+
# model=m,
|
214
|
+
# )
|
215
|
+
# example = [next(ag).select("new_agent_persona").first() for _ in range(10)]
|
216
|
+
# dimension_dict = {"attitude": ["positive", "negative"]}
|
217
|
+
# ag = gen_agent_traits(dimension_dict)
|
218
|
+
# example = [next(ag) for _ in range(100)]
|