edsl 0.1.14__py3-none-any.whl → 0.1.40__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- edsl/Base.py +348 -38
- edsl/BaseDiff.py +260 -0
- edsl/TemplateLoader.py +24 -0
- edsl/__init__.py +46 -10
- edsl/__version__.py +1 -0
- edsl/agents/Agent.py +842 -144
- edsl/agents/AgentList.py +521 -25
- edsl/agents/Invigilator.py +250 -374
- edsl/agents/InvigilatorBase.py +257 -0
- edsl/agents/PromptConstructor.py +272 -0
- edsl/agents/QuestionInstructionPromptBuilder.py +128 -0
- edsl/agents/QuestionTemplateReplacementsBuilder.py +137 -0
- edsl/agents/descriptors.py +43 -13
- edsl/agents/prompt_helpers.py +129 -0
- edsl/agents/question_option_processor.py +172 -0
- edsl/auto/AutoStudy.py +130 -0
- edsl/auto/StageBase.py +243 -0
- edsl/auto/StageGenerateSurvey.py +178 -0
- edsl/auto/StageLabelQuestions.py +125 -0
- edsl/auto/StagePersona.py +61 -0
- edsl/auto/StagePersonaDimensionValueRanges.py +88 -0
- edsl/auto/StagePersonaDimensionValues.py +74 -0
- edsl/auto/StagePersonaDimensions.py +69 -0
- edsl/auto/StageQuestions.py +74 -0
- edsl/auto/SurveyCreatorPipeline.py +21 -0
- edsl/auto/utilities.py +218 -0
- edsl/base/Base.py +279 -0
- edsl/config.py +121 -104
- edsl/conversation/Conversation.py +290 -0
- edsl/conversation/car_buying.py +59 -0
- edsl/conversation/chips.py +95 -0
- edsl/conversation/mug_negotiation.py +81 -0
- edsl/conversation/next_speaker_utilities.py +93 -0
- edsl/coop/CoopFunctionsMixin.py +15 -0
- edsl/coop/ExpectedParrotKeyHandler.py +125 -0
- edsl/coop/PriceFetcher.py +54 -0
- edsl/coop/__init__.py +1 -0
- edsl/coop/coop.py +1029 -134
- edsl/coop/utils.py +131 -0
- edsl/data/Cache.py +560 -89
- edsl/data/CacheEntry.py +230 -0
- edsl/data/CacheHandler.py +168 -0
- edsl/data/RemoteCacheSync.py +186 -0
- edsl/data/SQLiteDict.py +292 -0
- edsl/data/__init__.py +5 -3
- edsl/data/orm.py +6 -33
- edsl/data_transfer_models.py +74 -27
- edsl/enums.py +165 -8
- edsl/exceptions/BaseException.py +21 -0
- edsl/exceptions/__init__.py +52 -46
- edsl/exceptions/agents.py +33 -15
- edsl/exceptions/cache.py +5 -0
- edsl/exceptions/coop.py +8 -0
- edsl/exceptions/general.py +34 -0
- edsl/exceptions/inference_services.py +5 -0
- edsl/exceptions/jobs.py +15 -0
- edsl/exceptions/language_models.py +46 -1
- edsl/exceptions/questions.py +80 -5
- edsl/exceptions/results.py +16 -5
- edsl/exceptions/scenarios.py +29 -0
- edsl/exceptions/surveys.py +13 -10
- edsl/inference_services/AnthropicService.py +106 -0
- edsl/inference_services/AvailableModelCacheHandler.py +184 -0
- edsl/inference_services/AvailableModelFetcher.py +215 -0
- edsl/inference_services/AwsBedrock.py +118 -0
- edsl/inference_services/AzureAI.py +215 -0
- edsl/inference_services/DeepInfraService.py +18 -0
- edsl/inference_services/GoogleService.py +143 -0
- edsl/inference_services/GroqService.py +20 -0
- edsl/inference_services/InferenceServiceABC.py +80 -0
- edsl/inference_services/InferenceServicesCollection.py +138 -0
- edsl/inference_services/MistralAIService.py +120 -0
- edsl/inference_services/OllamaService.py +18 -0
- edsl/inference_services/OpenAIService.py +236 -0
- edsl/inference_services/PerplexityService.py +160 -0
- edsl/inference_services/ServiceAvailability.py +135 -0
- edsl/inference_services/TestService.py +90 -0
- edsl/inference_services/TogetherAIService.py +172 -0
- edsl/inference_services/data_structures.py +134 -0
- edsl/inference_services/models_available_cache.py +118 -0
- edsl/inference_services/rate_limits_cache.py +25 -0
- edsl/inference_services/registry.py +41 -0
- edsl/inference_services/write_available.py +10 -0
- edsl/jobs/AnswerQuestionFunctionConstructor.py +223 -0
- edsl/jobs/Answers.py +21 -20
- edsl/jobs/FetchInvigilator.py +47 -0
- edsl/jobs/InterviewTaskManager.py +98 -0
- edsl/jobs/InterviewsConstructor.py +50 -0
- edsl/jobs/Jobs.py +684 -204
- edsl/jobs/JobsChecks.py +172 -0
- edsl/jobs/JobsComponentConstructor.py +189 -0
- edsl/jobs/JobsPrompts.py +270 -0
- edsl/jobs/JobsRemoteInferenceHandler.py +311 -0
- edsl/jobs/JobsRemoteInferenceLogger.py +239 -0
- edsl/jobs/RequestTokenEstimator.py +30 -0
- edsl/jobs/async_interview_runner.py +138 -0
- edsl/jobs/buckets/BucketCollection.py +104 -0
- edsl/jobs/buckets/ModelBuckets.py +65 -0
- edsl/jobs/buckets/TokenBucket.py +283 -0
- edsl/jobs/buckets/TokenBucketAPI.py +211 -0
- edsl/jobs/buckets/TokenBucketClient.py +191 -0
- edsl/jobs/check_survey_scenario_compatibility.py +85 -0
- edsl/jobs/data_structures.py +120 -0
- edsl/jobs/decorators.py +35 -0
- edsl/jobs/interviews/Interview.py +392 -0
- edsl/jobs/interviews/InterviewExceptionCollection.py +99 -0
- edsl/jobs/interviews/InterviewExceptionEntry.py +186 -0
- edsl/jobs/interviews/InterviewStatistic.py +63 -0
- edsl/jobs/interviews/InterviewStatisticsCollection.py +25 -0
- edsl/jobs/interviews/InterviewStatusDictionary.py +78 -0
- edsl/jobs/interviews/InterviewStatusLog.py +92 -0
- edsl/jobs/interviews/ReportErrors.py +66 -0
- edsl/jobs/interviews/interview_status_enum.py +9 -0
- edsl/jobs/jobs_status_enums.py +9 -0
- edsl/jobs/loggers/HTMLTableJobLogger.py +304 -0
- edsl/jobs/results_exceptions_handler.py +98 -0
- edsl/jobs/runners/JobsRunnerAsyncio.py +151 -110
- edsl/jobs/runners/JobsRunnerStatus.py +298 -0
- edsl/jobs/tasks/QuestionTaskCreator.py +244 -0
- edsl/jobs/tasks/TaskCreators.py +64 -0
- edsl/jobs/tasks/TaskHistory.py +470 -0
- edsl/jobs/tasks/TaskStatusLog.py +23 -0
- edsl/jobs/tasks/task_status_enum.py +161 -0
- edsl/jobs/tokens/InterviewTokenUsage.py +27 -0
- edsl/jobs/tokens/TokenUsage.py +34 -0
- edsl/language_models/ComputeCost.py +63 -0
- edsl/language_models/LanguageModel.py +507 -386
- edsl/language_models/ModelList.py +164 -0
- edsl/language_models/PriceManager.py +127 -0
- edsl/language_models/RawResponseHandler.py +106 -0
- edsl/language_models/RegisterLanguageModelsMeta.py +184 -0
- edsl/language_models/__init__.py +1 -8
- edsl/language_models/fake_openai_call.py +15 -0
- edsl/language_models/fake_openai_service.py +61 -0
- edsl/language_models/key_management/KeyLookup.py +63 -0
- edsl/language_models/key_management/KeyLookupBuilder.py +273 -0
- edsl/language_models/key_management/KeyLookupCollection.py +38 -0
- edsl/language_models/key_management/__init__.py +0 -0
- edsl/language_models/key_management/models.py +131 -0
- edsl/language_models/model.py +256 -0
- edsl/language_models/repair.py +109 -41
- edsl/language_models/utilities.py +65 -0
- edsl/notebooks/Notebook.py +263 -0
- edsl/notebooks/NotebookToLaTeX.py +142 -0
- edsl/notebooks/__init__.py +1 -0
- edsl/prompts/Prompt.py +222 -93
- edsl/prompts/__init__.py +1 -1
- edsl/questions/ExceptionExplainer.py +77 -0
- edsl/questions/HTMLQuestion.py +103 -0
- edsl/questions/QuestionBase.py +518 -0
- edsl/questions/QuestionBasePromptsMixin.py +221 -0
- edsl/questions/QuestionBudget.py +164 -67
- edsl/questions/QuestionCheckBox.py +281 -62
- edsl/questions/QuestionDict.py +343 -0
- edsl/questions/QuestionExtract.py +136 -50
- edsl/questions/QuestionFreeText.py +79 -55
- edsl/questions/QuestionFunctional.py +138 -41
- edsl/questions/QuestionList.py +184 -57
- edsl/questions/QuestionMatrix.py +265 -0
- edsl/questions/QuestionMultipleChoice.py +293 -69
- edsl/questions/QuestionNumerical.py +109 -56
- edsl/questions/QuestionRank.py +244 -49
- edsl/questions/Quick.py +41 -0
- edsl/questions/SimpleAskMixin.py +74 -0
- edsl/questions/__init__.py +9 -6
- edsl/questions/{AnswerValidatorMixin.py → answer_validator_mixin.py} +153 -38
- edsl/questions/compose_questions.py +13 -7
- edsl/questions/data_structures.py +20 -0
- edsl/questions/decorators.py +21 -0
- edsl/questions/derived/QuestionLikertFive.py +28 -26
- edsl/questions/derived/QuestionLinearScale.py +41 -28
- edsl/questions/derived/QuestionTopK.py +34 -26
- edsl/questions/derived/QuestionYesNo.py +40 -27
- edsl/questions/descriptors.py +228 -74
- edsl/questions/loop_processor.py +149 -0
- edsl/questions/prompt_templates/question_budget.jinja +13 -0
- edsl/questions/prompt_templates/question_checkbox.jinja +32 -0
- edsl/questions/prompt_templates/question_extract.jinja +11 -0
- edsl/questions/prompt_templates/question_free_text.jinja +3 -0
- edsl/questions/prompt_templates/question_linear_scale.jinja +11 -0
- edsl/questions/prompt_templates/question_list.jinja +17 -0
- edsl/questions/prompt_templates/question_multiple_choice.jinja +33 -0
- edsl/questions/prompt_templates/question_numerical.jinja +37 -0
- edsl/questions/question_base_gen_mixin.py +168 -0
- edsl/questions/question_registry.py +130 -46
- edsl/questions/register_questions_meta.py +71 -0
- edsl/questions/response_validator_abc.py +188 -0
- edsl/questions/response_validator_factory.py +34 -0
- edsl/questions/settings.py +5 -2
- edsl/questions/templates/__init__.py +0 -0
- edsl/questions/templates/budget/__init__.py +0 -0
- edsl/questions/templates/budget/answering_instructions.jinja +7 -0
- edsl/questions/templates/budget/question_presentation.jinja +7 -0
- edsl/questions/templates/checkbox/__init__.py +0 -0
- edsl/questions/templates/checkbox/answering_instructions.jinja +10 -0
- edsl/questions/templates/checkbox/question_presentation.jinja +22 -0
- edsl/questions/templates/dict/__init__.py +0 -0
- edsl/questions/templates/dict/answering_instructions.jinja +21 -0
- edsl/questions/templates/dict/question_presentation.jinja +1 -0
- edsl/questions/templates/extract/__init__.py +0 -0
- edsl/questions/templates/extract/answering_instructions.jinja +7 -0
- edsl/questions/templates/extract/question_presentation.jinja +1 -0
- edsl/questions/templates/free_text/__init__.py +0 -0
- edsl/questions/templates/free_text/answering_instructions.jinja +0 -0
- edsl/questions/templates/free_text/question_presentation.jinja +1 -0
- edsl/questions/templates/likert_five/__init__.py +0 -0
- edsl/questions/templates/likert_five/answering_instructions.jinja +10 -0
- edsl/questions/templates/likert_five/question_presentation.jinja +12 -0
- edsl/questions/templates/linear_scale/__init__.py +0 -0
- edsl/questions/templates/linear_scale/answering_instructions.jinja +5 -0
- edsl/questions/templates/linear_scale/question_presentation.jinja +5 -0
- edsl/questions/templates/list/__init__.py +0 -0
- edsl/questions/templates/list/answering_instructions.jinja +4 -0
- edsl/questions/templates/list/question_presentation.jinja +5 -0
- edsl/questions/templates/matrix/__init__.py +1 -0
- edsl/questions/templates/matrix/answering_instructions.jinja +5 -0
- edsl/questions/templates/matrix/question_presentation.jinja +20 -0
- edsl/questions/templates/multiple_choice/__init__.py +0 -0
- edsl/questions/templates/multiple_choice/answering_instructions.jinja +9 -0
- edsl/questions/templates/multiple_choice/html.jinja +0 -0
- edsl/questions/templates/multiple_choice/question_presentation.jinja +12 -0
- edsl/questions/templates/numerical/__init__.py +0 -0
- edsl/questions/templates/numerical/answering_instructions.jinja +7 -0
- edsl/questions/templates/numerical/question_presentation.jinja +7 -0
- edsl/questions/templates/rank/__init__.py +0 -0
- edsl/questions/templates/rank/answering_instructions.jinja +11 -0
- edsl/questions/templates/rank/question_presentation.jinja +15 -0
- edsl/questions/templates/top_k/__init__.py +0 -0
- edsl/questions/templates/top_k/answering_instructions.jinja +8 -0
- edsl/questions/templates/top_k/question_presentation.jinja +22 -0
- edsl/questions/templates/yes_no/__init__.py +0 -0
- edsl/questions/templates/yes_no/answering_instructions.jinja +6 -0
- edsl/questions/templates/yes_no/question_presentation.jinja +12 -0
- edsl/results/CSSParameterizer.py +108 -0
- edsl/results/Dataset.py +550 -19
- edsl/results/DatasetExportMixin.py +594 -0
- edsl/results/DatasetTree.py +295 -0
- edsl/results/MarkdownToDocx.py +122 -0
- edsl/results/MarkdownToPDF.py +111 -0
- edsl/results/Result.py +477 -173
- edsl/results/Results.py +987 -269
- edsl/results/ResultsExportMixin.py +28 -125
- edsl/results/ResultsGGMixin.py +83 -15
- edsl/results/TableDisplay.py +125 -0
- edsl/results/TextEditor.py +50 -0
- edsl/results/__init__.py +1 -1
- edsl/results/file_exports.py +252 -0
- edsl/results/results_fetch_mixin.py +33 -0
- edsl/results/results_selector.py +145 -0
- edsl/results/results_tools_mixin.py +98 -0
- edsl/results/smart_objects.py +96 -0
- edsl/results/table_data_class.py +12 -0
- edsl/results/table_display.css +78 -0
- edsl/results/table_renderers.py +118 -0
- edsl/results/tree_explore.py +115 -0
- edsl/scenarios/ConstructDownloadLink.py +109 -0
- edsl/scenarios/DocumentChunker.py +102 -0
- edsl/scenarios/DocxScenario.py +16 -0
- edsl/scenarios/FileStore.py +543 -0
- edsl/scenarios/PdfExtractor.py +40 -0
- edsl/scenarios/Scenario.py +431 -62
- edsl/scenarios/ScenarioHtmlMixin.py +65 -0
- edsl/scenarios/ScenarioList.py +1415 -45
- edsl/scenarios/ScenarioListExportMixin.py +45 -0
- edsl/scenarios/ScenarioListPdfMixin.py +239 -0
- edsl/scenarios/__init__.py +2 -0
- edsl/scenarios/directory_scanner.py +96 -0
- edsl/scenarios/file_methods.py +85 -0
- edsl/scenarios/handlers/__init__.py +13 -0
- edsl/scenarios/handlers/csv.py +49 -0
- edsl/scenarios/handlers/docx.py +76 -0
- edsl/scenarios/handlers/html.py +37 -0
- edsl/scenarios/handlers/json.py +111 -0
- edsl/scenarios/handlers/latex.py +5 -0
- edsl/scenarios/handlers/md.py +51 -0
- edsl/scenarios/handlers/pdf.py +68 -0
- edsl/scenarios/handlers/png.py +39 -0
- edsl/scenarios/handlers/pptx.py +105 -0
- edsl/scenarios/handlers/py.py +294 -0
- edsl/scenarios/handlers/sql.py +313 -0
- edsl/scenarios/handlers/sqlite.py +149 -0
- edsl/scenarios/handlers/txt.py +33 -0
- edsl/scenarios/scenario_join.py +131 -0
- edsl/scenarios/scenario_selector.py +156 -0
- edsl/shared.py +1 -0
- edsl/study/ObjectEntry.py +173 -0
- edsl/study/ProofOfWork.py +113 -0
- edsl/study/SnapShot.py +80 -0
- edsl/study/Study.py +521 -0
- edsl/study/__init__.py +4 -0
- edsl/surveys/ConstructDAG.py +92 -0
- edsl/surveys/DAG.py +92 -11
- edsl/surveys/EditSurvey.py +221 -0
- edsl/surveys/InstructionHandler.py +100 -0
- edsl/surveys/Memory.py +9 -4
- edsl/surveys/MemoryManagement.py +72 -0
- edsl/surveys/MemoryPlan.py +156 -35
- edsl/surveys/Rule.py +221 -74
- edsl/surveys/RuleCollection.py +241 -61
- edsl/surveys/RuleManager.py +172 -0
- edsl/surveys/Simulator.py +75 -0
- edsl/surveys/Survey.py +1079 -339
- edsl/surveys/SurveyCSS.py +273 -0
- edsl/surveys/SurveyExportMixin.py +235 -40
- edsl/surveys/SurveyFlowVisualization.py +181 -0
- edsl/surveys/SurveyQualtricsImport.py +284 -0
- edsl/surveys/SurveyToApp.py +141 -0
- edsl/surveys/__init__.py +4 -2
- edsl/surveys/base.py +19 -3
- edsl/surveys/descriptors.py +17 -6
- edsl/surveys/instructions/ChangeInstruction.py +48 -0
- edsl/surveys/instructions/Instruction.py +56 -0
- edsl/surveys/instructions/InstructionCollection.py +82 -0
- edsl/surveys/instructions/__init__.py +0 -0
- edsl/templates/error_reporting/base.html +24 -0
- edsl/templates/error_reporting/exceptions_by_model.html +35 -0
- edsl/templates/error_reporting/exceptions_by_question_name.html +17 -0
- edsl/templates/error_reporting/exceptions_by_type.html +17 -0
- edsl/templates/error_reporting/interview_details.html +116 -0
- edsl/templates/error_reporting/interviews.html +19 -0
- edsl/templates/error_reporting/overview.html +5 -0
- edsl/templates/error_reporting/performance_plot.html +2 -0
- edsl/templates/error_reporting/report.css +74 -0
- edsl/templates/error_reporting/report.html +118 -0
- edsl/templates/error_reporting/report.js +25 -0
- edsl/tools/__init__.py +1 -0
- edsl/tools/clusters.py +192 -0
- edsl/tools/embeddings.py +27 -0
- edsl/tools/embeddings_plotting.py +118 -0
- edsl/tools/plotting.py +112 -0
- edsl/tools/summarize.py +18 -0
- edsl/utilities/PrettyList.py +56 -0
- edsl/utilities/SystemInfo.py +5 -0
- edsl/utilities/__init__.py +21 -20
- edsl/utilities/ast_utilities.py +3 -0
- edsl/utilities/data/Registry.py +2 -0
- edsl/utilities/decorators.py +41 -0
- edsl/utilities/gcp_bucket/__init__.py +0 -0
- edsl/utilities/gcp_bucket/cloud_storage.py +96 -0
- edsl/utilities/interface.py +310 -60
- edsl/utilities/is_notebook.py +18 -0
- edsl/utilities/is_valid_variable_name.py +11 -0
- edsl/utilities/naming_utilities.py +263 -0
- edsl/utilities/remove_edsl_version.py +24 -0
- edsl/utilities/repair_functions.py +28 -0
- edsl/utilities/restricted_python.py +70 -0
- edsl/utilities/utilities.py +203 -13
- edsl-0.1.40.dist-info/METADATA +111 -0
- edsl-0.1.40.dist-info/RECORD +362 -0
- {edsl-0.1.14.dist-info → edsl-0.1.40.dist-info}/WHEEL +1 -1
- edsl/agents/AgentListExportMixin.py +0 -24
- edsl/coop/old.py +0 -31
- edsl/data/Database.py +0 -141
- edsl/data/crud.py +0 -121
- edsl/jobs/Interview.py +0 -417
- edsl/jobs/JobsRunner.py +0 -63
- edsl/jobs/JobsRunnerStatusMixin.py +0 -115
- edsl/jobs/base.py +0 -47
- edsl/jobs/buckets.py +0 -166
- edsl/jobs/runners/JobsRunnerDryRun.py +0 -19
- edsl/jobs/runners/JobsRunnerStreaming.py +0 -54
- edsl/jobs/task_management.py +0 -218
- edsl/jobs/token_tracking.py +0 -78
- edsl/language_models/DeepInfra.py +0 -69
- edsl/language_models/OpenAI.py +0 -98
- edsl/language_models/model_interfaces/GeminiPro.py +0 -66
- edsl/language_models/model_interfaces/LanguageModelOpenAIFour.py +0 -8
- edsl/language_models/model_interfaces/LanguageModelOpenAIThreeFiveTurbo.py +0 -8
- edsl/language_models/model_interfaces/LlamaTwo13B.py +0 -21
- edsl/language_models/model_interfaces/LlamaTwo70B.py +0 -21
- edsl/language_models/model_interfaces/Mixtral8x7B.py +0 -24
- edsl/language_models/registry.py +0 -81
- edsl/language_models/schemas.py +0 -15
- edsl/language_models/unused/ReplicateBase.py +0 -83
- edsl/prompts/QuestionInstructionsBase.py +0 -6
- edsl/prompts/library/agent_instructions.py +0 -29
- edsl/prompts/library/agent_persona.py +0 -17
- edsl/prompts/library/question_budget.py +0 -26
- edsl/prompts/library/question_checkbox.py +0 -32
- edsl/prompts/library/question_extract.py +0 -19
- edsl/prompts/library/question_freetext.py +0 -14
- edsl/prompts/library/question_linear_scale.py +0 -20
- edsl/prompts/library/question_list.py +0 -22
- edsl/prompts/library/question_multiple_choice.py +0 -44
- edsl/prompts/library/question_numerical.py +0 -31
- edsl/prompts/library/question_rank.py +0 -21
- edsl/prompts/prompt_config.py +0 -33
- edsl/prompts/registry.py +0 -185
- edsl/questions/Question.py +0 -240
- edsl/report/InputOutputDataTypes.py +0 -134
- edsl/report/RegressionMixin.py +0 -28
- edsl/report/ReportOutputs.py +0 -1228
- edsl/report/ResultsFetchMixin.py +0 -106
- edsl/report/ResultsOutputMixin.py +0 -14
- edsl/report/demo.ipynb +0 -645
- edsl/results/ResultsDBMixin.py +0 -184
- edsl/surveys/SurveyFlowVisualizationMixin.py +0 -92
- edsl/trackers/Tracker.py +0 -91
- edsl/trackers/TrackerAPI.py +0 -196
- edsl/trackers/TrackerTasks.py +0 -70
- edsl/utilities/pastebin.py +0 -141
- edsl-0.1.14.dist-info/METADATA +0 -69
- edsl-0.1.14.dist-info/RECORD +0 -141
- /edsl/{language_models/model_interfaces → inference_services}/__init__.py +0 -0
- /edsl/{report/__init__.py → jobs/runners/JobsRunnerStatusData.py} +0 -0
- /edsl/{trackers/__init__.py → language_models/ServiceDataSources.py} +0 -0
- {edsl-0.1.14.dist-info → edsl-0.1.40.dist-info}/LICENSE +0 -0
edsl/agents/AgentList.py
CHANGED
@@ -1,55 +1,551 @@
|
|
1
|
+
"""A list of Agents
|
2
|
+
"""
|
3
|
+
|
1
4
|
from __future__ import annotations
|
2
|
-
import
|
5
|
+
import csv
|
6
|
+
import sys
|
3
7
|
from collections import UserList
|
4
|
-
from
|
8
|
+
from collections.abc import Iterable
|
9
|
+
|
10
|
+
from typing import Any, List, Optional, Union, TYPE_CHECKING
|
5
11
|
|
6
|
-
from
|
7
|
-
from rich.table import Table
|
12
|
+
from simpleeval import EvalWithCompoundTypes, NameNotDefined
|
8
13
|
|
9
|
-
from edsl.agents import Agent
|
10
|
-
from edsl.agents.AgentListExportMixin import AgentListExportMixin
|
11
14
|
from edsl.Base import Base
|
15
|
+
from edsl.utilities.remove_edsl_version import remove_edsl_version
|
16
|
+
from edsl.exceptions.agents import AgentListError
|
17
|
+
from edsl.utilities.is_notebook import is_notebook
|
18
|
+
from edsl.results.ResultsExportMixin import ResultsExportMixin
|
19
|
+
import logging
|
20
|
+
|
21
|
+
logger = logging.getLogger(__name__)
|
22
|
+
|
23
|
+
if TYPE_CHECKING:
|
24
|
+
from edsl.scenarios.ScenarioList import ScenarioList
|
25
|
+
from edsl.agents.Agent import Agent
|
26
|
+
from pandas import DataFrame
|
27
|
+
|
28
|
+
|
29
|
+
def is_iterable(obj):
|
30
|
+
return isinstance(obj, Iterable)
|
31
|
+
|
12
32
|
|
33
|
+
class EmptyAgentList:
|
34
|
+
def __repr__(self):
|
35
|
+
return "Empty AgentList"
|
13
36
|
|
14
|
-
|
15
|
-
|
37
|
+
|
38
|
+
# ResultsExportMixin,
|
39
|
+
class AgentList(UserList, Base):
|
40
|
+
"""A list of Agents."""
|
41
|
+
|
42
|
+
__documentation__ = (
|
43
|
+
"https://docs.expectedparrot.com/en/latest/agents.html#agentlist-class"
|
44
|
+
)
|
45
|
+
|
46
|
+
def __init__(self, data: Optional[list["Agent"]] = None):
|
47
|
+
"""Initialize a new AgentList.
|
48
|
+
|
49
|
+
:param data: A list of Agents.
|
50
|
+
"""
|
16
51
|
if data is not None:
|
17
52
|
super().__init__(data)
|
18
53
|
else:
|
19
54
|
super().__init__()
|
20
55
|
|
21
|
-
def
|
22
|
-
|
56
|
+
def shuffle(self, seed: Optional[str] = None) -> AgentList:
|
57
|
+
"""Shuffle the AgentList.
|
58
|
+
|
59
|
+
:param seed: The seed for the random number generator.
|
60
|
+
"""
|
61
|
+
import random
|
62
|
+
|
63
|
+
if seed is not None:
|
64
|
+
random.seed(seed)
|
65
|
+
random.shuffle(self.data)
|
66
|
+
return self
|
67
|
+
|
68
|
+
def sample(self, n: int, seed: Optional[str] = None) -> AgentList:
|
69
|
+
"""Return a random sample of agents.
|
70
|
+
|
71
|
+
:param n: The number of agents to sample.
|
72
|
+
:param seed: The seed for the random number generator.
|
73
|
+
"""
|
74
|
+
import random
|
75
|
+
|
76
|
+
if seed:
|
77
|
+
random.seed(seed)
|
78
|
+
return AgentList(random.sample(self.data, n))
|
79
|
+
|
80
|
+
def to_pandas(self) -> "DataFrame":
|
81
|
+
"""Return a pandas DataFrame.
|
82
|
+
|
83
|
+
>>> from edsl.agents.Agent import Agent
|
84
|
+
>>> al = AgentList([Agent(traits = {'age': 22, 'hair': 'brown', 'height': 5.5}), Agent(traits = {'age': 22, 'hair': 'brown', 'height': 5.5})])
|
85
|
+
>>> al.to_pandas()
|
86
|
+
age hair height
|
87
|
+
0 22 brown 5.5
|
88
|
+
1 22 brown 5.5
|
89
|
+
"""
|
90
|
+
return self.to_scenario_list().to_pandas()
|
91
|
+
|
92
|
+
def tally(
|
93
|
+
self, *fields: Optional[str], top_n: Optional[int] = None, output="Dataset"
|
94
|
+
) -> Union[dict, "Dataset"]:
|
95
|
+
"""Tally the values of a field or perform a cross-tab of multiple fields.
|
96
|
+
|
97
|
+
:param fields: The field(s) to tally, multiple fields for cross-tabulation.
|
98
|
+
|
99
|
+
>>> al = AgentList.example()
|
100
|
+
>>> al.tally('age')
|
101
|
+
Dataset([{'age': [22]}, {'count': [2]}])
|
102
|
+
"""
|
103
|
+
return self.to_scenario_list().tally(*fields, top_n=top_n, output=output)
|
104
|
+
|
105
|
+
def duplicate(self):
|
106
|
+
"""Duplicate the AgentList.
|
107
|
+
|
108
|
+
>>> al = AgentList.example()
|
109
|
+
>>> al2 = al.duplicate()
|
110
|
+
>>> al2 == al
|
111
|
+
True
|
112
|
+
>>> id(al2) == id(al)
|
113
|
+
False
|
114
|
+
"""
|
115
|
+
return AgentList([a.duplicate() for a in self.data])
|
116
|
+
|
117
|
+
def rename(self, old_name, new_name) -> AgentList:
|
118
|
+
"""Rename a trait in the AgentList.
|
119
|
+
|
120
|
+
:param old_name: The old name of the trait.
|
121
|
+
:param new_name: The new name of the trait.
|
122
|
+
:param inplace: Whether to rename the trait in place.
|
123
|
+
|
124
|
+
>>> from edsl.agents.Agent import Agent
|
125
|
+
>>> al = AgentList([Agent(traits = {'a': 1, 'b': 1}), Agent(traits = {'a': 1, 'b': 2})])
|
126
|
+
>>> al2 = al.rename('a', 'c')
|
127
|
+
>>> assert al2 == AgentList([Agent(traits = {'c': 1, 'b': 1}), Agent(traits = {'c': 1, 'b': 2})])
|
128
|
+
>>> assert al != al2
|
129
|
+
"""
|
130
|
+
newagents = []
|
131
|
+
for agent in self:
|
132
|
+
newagents.append(agent.rename(old_name, new_name))
|
133
|
+
return AgentList(newagents)
|
134
|
+
|
135
|
+
def select(self, *traits) -> AgentList:
|
136
|
+
"""Selects agents with only the references traits.
|
137
|
+
|
138
|
+
>>> from edsl.agents.Agent import Agent
|
139
|
+
>>> al = AgentList([Agent(traits = {'a': 1, 'b': 1}), Agent(traits = {'a': 1, 'b': 2})])
|
140
|
+
>>> al.select('a')
|
141
|
+
AgentList([Agent(traits = {'a': 1}), Agent(traits = {'a': 1})])
|
142
|
+
|
143
|
+
"""
|
144
|
+
|
145
|
+
if len(traits) == 1:
|
146
|
+
traits_to_select = [list(traits)[0]]
|
147
|
+
else:
|
148
|
+
traits_to_select = list(traits)
|
149
|
+
|
150
|
+
return AgentList([agent.select(*traits_to_select) for agent in self.data])
|
151
|
+
|
152
|
+
def filter(self, expression: str) -> AgentList:
|
153
|
+
"""
|
154
|
+
Filter a list of agents based on an expression.
|
155
|
+
|
156
|
+
>>> from edsl.agents.Agent import Agent
|
157
|
+
>>> al = AgentList([Agent(traits = {'a': 1, 'b': 1}), Agent(traits = {'a': 1, 'b': 2})])
|
158
|
+
>>> al.filter("b == 2")
|
159
|
+
AgentList([Agent(traits = {'a': 1, 'b': 2})])
|
160
|
+
"""
|
161
|
+
|
162
|
+
def create_evaluator(agent: "Agent"):
|
163
|
+
"""Create an evaluator for the given result.
|
164
|
+
The 'combined_dict' is a mapping of all values for that Result object.
|
165
|
+
"""
|
166
|
+
return EvalWithCompoundTypes(names=agent.traits)
|
167
|
+
|
168
|
+
# iterates through all the results and evaluates the expression
|
169
|
+
|
170
|
+
try:
|
171
|
+
new_data = [
|
172
|
+
agent for agent in self.data if create_evaluator(agent).eval(expression)
|
173
|
+
]
|
174
|
+
except NameNotDefined as e:
|
175
|
+
e = AgentListError(f"'{expression}' is not a valid expression.")
|
176
|
+
if is_notebook():
|
177
|
+
print(e, file=sys.stderr)
|
178
|
+
else:
|
179
|
+
raise e
|
180
|
+
|
181
|
+
return EmptyAgentList()
|
182
|
+
|
183
|
+
if len(new_data) == 0:
|
184
|
+
return EmptyAgentList()
|
185
|
+
|
186
|
+
return AgentList(new_data)
|
187
|
+
|
188
|
+
@property
|
189
|
+
def all_traits(self) -> list[str]:
|
190
|
+
"""Return all traits in the AgentList.
|
191
|
+
>>> from edsl.agents.Agent import Agent
|
192
|
+
>>> agent_1 = Agent(traits = {'age': 22})
|
193
|
+
>>> agent_2 = Agent(traits = {'hair': 'brown'})
|
194
|
+
>>> al = AgentList([agent_1, agent_2])
|
195
|
+
>>> al.all_traits
|
196
|
+
['age', 'hair']
|
197
|
+
"""
|
198
|
+
d = {}
|
199
|
+
for agent in self:
|
200
|
+
d.update(agent.traits)
|
201
|
+
return list(d.keys())
|
202
|
+
|
203
|
+
@classmethod
|
204
|
+
def from_csv(cls, file_path: str, name_field: Optional[str] = None):
|
205
|
+
"""Load AgentList from a CSV file.
|
206
|
+
|
207
|
+
>>> import csv
|
208
|
+
>>> import os
|
209
|
+
>>> with open('/tmp/agents.csv', 'w') as f:
|
210
|
+
... writer = csv.writer(f)
|
211
|
+
... _ = writer.writerow(['age', 'hair', 'height'])
|
212
|
+
... _ = writer.writerow([22, 'brown', 5.5])
|
213
|
+
>>> al = AgentList.from_csv('/tmp/agents.csv')
|
214
|
+
>>> al
|
215
|
+
AgentList([Agent(traits = {'age': '22', 'hair': 'brown', 'height': '5.5'})])
|
216
|
+
>>> al = AgentList.from_csv('/tmp/agents.csv', name_field='hair')
|
217
|
+
>>> al
|
218
|
+
AgentList([Agent(name = \"""brown\""", traits = {'age': '22', 'height': '5.5'})])
|
219
|
+
>>> os.remove('/tmp/agents.csv')
|
220
|
+
|
221
|
+
:param file_path: The path to the CSV file.
|
222
|
+
:param name_field: The name of the field to use as the agent name.
|
223
|
+
"""
|
224
|
+
from edsl.agents.Agent import Agent
|
225
|
+
|
226
|
+
agent_list = []
|
227
|
+
with open(file_path, "r") as f:
|
228
|
+
reader = csv.DictReader(f)
|
229
|
+
for row in reader:
|
230
|
+
if "name" in row:
|
231
|
+
import warnings
|
232
|
+
|
233
|
+
warnings.warn("Using 'name' field in the CSV for the Agent name")
|
234
|
+
name_field = "name"
|
235
|
+
if name_field is not None:
|
236
|
+
agent_name = row.pop(name_field)
|
237
|
+
agent_list.append(Agent(traits=row, name=agent_name))
|
238
|
+
else:
|
239
|
+
agent_list.append(Agent(traits=row))
|
240
|
+
return cls(agent_list)
|
241
|
+
|
242
|
+
def translate_traits(self, codebook: dict[str, str]):
|
243
|
+
"""Translate traits to a new codebook.
|
244
|
+
|
245
|
+
:param codebook: The new codebook.
|
246
|
+
|
247
|
+
>>> al = AgentList.example()
|
248
|
+
>>> codebook = {'hair': {'brown':'Secret word for green'}}
|
249
|
+
>>> al.translate_traits(codebook)
|
250
|
+
AgentList([Agent(traits = {'age': 22, 'hair': 'Secret word for green', 'height': 5.5}), Agent(traits = {'age': 22, 'hair': 'Secret word for green', 'height': 5.5})])
|
251
|
+
"""
|
252
|
+
new_agents = []
|
253
|
+
for agent in self.data:
|
254
|
+
new_agents.append(agent.translate_traits(codebook))
|
255
|
+
return AgentList(new_agents)
|
256
|
+
|
257
|
+
def remove_trait(self, trait: str):
|
258
|
+
"""Remove traits from the AgentList.
|
259
|
+
|
260
|
+
:param traits: The traits to remove.
|
261
|
+
>>> from edsl.agents.Agent import Agent
|
262
|
+
>>> al = AgentList([Agent({'age': 22, 'hair': 'brown', 'height': 5.5}), Agent({'age': 22, 'hair': 'brown', 'height': 5.5})])
|
263
|
+
>>> al.remove_trait('age')
|
264
|
+
AgentList([Agent(traits = {'hair': 'brown', 'height': 5.5}), Agent(traits = {'hair': 'brown', 'height': 5.5})])
|
265
|
+
"""
|
266
|
+
agents = []
|
267
|
+
new_al = self.duplicate()
|
268
|
+
for agent in new_al.data:
|
269
|
+
agents.append(agent.remove_trait(trait))
|
270
|
+
return AgentList(agents)
|
23
271
|
|
24
|
-
def
|
25
|
-
|
272
|
+
def add_trait(self, trait: str, values: List[Any]) -> AgentList:
|
273
|
+
"""Adds a new trait to every agent, with values taken from values.
|
274
|
+
|
275
|
+
:param trait: The name of the trait.
|
276
|
+
:param values: The valeues(s) of the trait. If a single value is passed, it is used for all agents.
|
277
|
+
|
278
|
+
>>> al = AgentList.example()
|
279
|
+
>>> new_al = al.add_trait('new_trait', 1)
|
280
|
+
>>> new_al.select('new_trait').to_scenario_list().to_list()
|
281
|
+
[1, 1]
|
282
|
+
>>> al.add_trait('new_trait', [1, 2, 3])
|
283
|
+
Traceback (most recent call last):
|
284
|
+
...
|
285
|
+
edsl.exceptions.agents.AgentListError: The passed values have to be the same length as the agent list.
|
286
|
+
...
|
287
|
+
"""
|
288
|
+
if not is_iterable(values):
|
289
|
+
new_agents = []
|
290
|
+
value = values
|
291
|
+
for agent in self.data:
|
292
|
+
new_agents.append(agent.add_trait(trait, value))
|
293
|
+
return AgentList(new_agents)
|
294
|
+
|
295
|
+
if len(values) != len(self):
|
296
|
+
e = AgentListError(
|
297
|
+
"The passed values have to be the same length as the agent list."
|
298
|
+
)
|
299
|
+
if is_notebook():
|
300
|
+
print(e, file=sys.stderr)
|
301
|
+
else:
|
302
|
+
raise e
|
303
|
+
new_agents = []
|
304
|
+
for agent, value in zip(self.data, values):
|
305
|
+
new_agents.append(agent.add_trait(trait, value))
|
306
|
+
return AgentList(new_agents)
|
307
|
+
|
308
|
+
@staticmethod
|
309
|
+
def get_codebook(file_path: str):
|
310
|
+
"""Return the codebook for a CSV file.
|
311
|
+
|
312
|
+
:param file_path: The path to the CSV file.
|
313
|
+
"""
|
314
|
+
with open(file_path, "r") as f:
|
315
|
+
reader = csv.DictReader(f)
|
316
|
+
return {field: None for field in reader.fieldnames}
|
317
|
+
|
318
|
+
def __hash__(self) -> int:
|
319
|
+
"""Return the hash of the AgentList.
|
320
|
+
|
321
|
+
>>> al = AgentList.example()
|
322
|
+
>>> hash(al)
|
323
|
+
1681154913465662422
|
324
|
+
"""
|
325
|
+
from edsl.utilities.utilities import dict_hash
|
326
|
+
|
327
|
+
return dict_hash(self.to_dict(add_edsl_version=False, sorted=True))
|
328
|
+
|
329
|
+
def to_dict(self, sorted=False, add_edsl_version=True):
|
330
|
+
"""Serialize the AgentList to a dictionary.
|
331
|
+
|
332
|
+
>>> AgentList.example().to_dict(add_edsl_version=False)
|
333
|
+
{'agent_list': [{'traits': {'age': 22, 'hair': 'brown', 'height': 5.5}}, {'traits': {'age': 22, 'hair': 'brown', 'height': 5.5}}]}
|
334
|
+
|
335
|
+
"""
|
336
|
+
if sorted:
|
337
|
+
data = self.data[:]
|
338
|
+
data.sort(key=lambda x: hash(x))
|
339
|
+
else:
|
340
|
+
data = self.data
|
341
|
+
|
342
|
+
d = {
|
343
|
+
"agent_list": [
|
344
|
+
agent.to_dict(add_edsl_version=add_edsl_version) for agent in data
|
345
|
+
]
|
346
|
+
}
|
347
|
+
if add_edsl_version:
|
348
|
+
from edsl import __version__
|
349
|
+
|
350
|
+
d["edsl_version"] = __version__
|
351
|
+
d["edsl_class_name"] = "AgentList"
|
352
|
+
|
353
|
+
return d
|
354
|
+
|
355
|
+
def __eq__(self, other: AgentList) -> bool:
|
356
|
+
return self.to_dict(sorted=True, add_edsl_version=False) == other.to_dict(
|
357
|
+
sorted=True, add_edsl_version=False
|
358
|
+
)
|
359
|
+
|
360
|
+
def __repr__(self):
|
361
|
+
return f"AgentList({self.data})"
|
362
|
+
|
363
|
+
def _summary(self):
|
364
|
+
return {
|
365
|
+
"agents": len(self),
|
366
|
+
}
|
367
|
+
|
368
|
+
def set_codebook(self, codebook: dict[str, str]) -> AgentList:
|
369
|
+
"""Set the codebook for the AgentList.
|
370
|
+
|
371
|
+
>>> from edsl.agents.Agent import Agent
|
372
|
+
>>> a = Agent(traits = {'hair': 'brown'})
|
373
|
+
>>> al = AgentList([a, a])
|
374
|
+
>>> _ = al.set_codebook({'hair': "Color of hair on driver's license"})
|
375
|
+
>>> al[0].codebook
|
376
|
+
{'hair': "Color of hair on driver's license"}
|
377
|
+
|
378
|
+
|
379
|
+
:param codebook: The codebook.
|
380
|
+
"""
|
381
|
+
for agent in self.data:
|
382
|
+
agent.codebook = codebook
|
383
|
+
|
384
|
+
return self
|
385
|
+
|
386
|
+
def to_csv(self, file_path: str):
|
387
|
+
"""Save the AgentList to a CSV file.
|
388
|
+
|
389
|
+
:param file_path: The path to the CSV file.
|
390
|
+
"""
|
391
|
+
self.to_scenario_list().to_csv(file_path)
|
392
|
+
|
393
|
+
def to_list(self, include_agent_name=False) -> list[tuple]:
|
394
|
+
"""Return a list of tuples."""
|
395
|
+
return self.to_scenario_list(include_agent_name).to_list()
|
396
|
+
|
397
|
+
def to_scenario_list(
|
398
|
+
self, include_agent_name: bool = False, include_instruction: bool = False
|
399
|
+
) -> ScenarioList:
|
400
|
+
"""Converts the agent to a scenario list."""
|
401
|
+
from edsl.scenarios.ScenarioList import ScenarioList
|
402
|
+
from edsl.scenarios.Scenario import Scenario
|
403
|
+
|
404
|
+
# raise NotImplementedError("This method is not implemented yet.")
|
405
|
+
|
406
|
+
scenario_list = ScenarioList()
|
407
|
+
for agent in self.data:
|
408
|
+
d = agent.traits
|
409
|
+
if include_agent_name:
|
410
|
+
d["agent_name"] = agent.name
|
411
|
+
if include_instruction:
|
412
|
+
d["instruction"] = agent.instruction
|
413
|
+
scenario_list.append(Scenario(d))
|
414
|
+
return scenario_list
|
415
|
+
|
416
|
+
# if include_agent_name:
|
417
|
+
# return ScenarioList(
|
418
|
+
# [
|
419
|
+
# Scenario(agent.traits | {"agent_name": agent.name} | })
|
420
|
+
# for agent in self.data
|
421
|
+
# ]
|
422
|
+
# )
|
423
|
+
# return ScenarioList([Scenario(agent.traits) for agent in self.data])
|
424
|
+
|
425
|
+
def table(
|
426
|
+
self,
|
427
|
+
*fields,
|
428
|
+
tablefmt: Optional[str] = None,
|
429
|
+
pretty_labels: Optional[dict] = None,
|
430
|
+
) -> Table:
|
431
|
+
if len(self) == 0:
|
432
|
+
e = AgentListError("Cannot create a table from an empty AgentList.")
|
433
|
+
if is_notebook():
|
434
|
+
print(e, file=sys.stderr)
|
435
|
+
return None
|
436
|
+
else:
|
437
|
+
raise e
|
438
|
+
return (
|
439
|
+
self.to_scenario_list()
|
440
|
+
.to_dataset()
|
441
|
+
.table(*fields, tablefmt=tablefmt, pretty_labels=pretty_labels)
|
442
|
+
)
|
443
|
+
|
444
|
+
def to_dataset(self, traits_only: bool = True):
|
445
|
+
"""
|
446
|
+
Convert the AgentList to a Dataset.
|
447
|
+
|
448
|
+
>>> from edsl.agents.AgentList import AgentList
|
449
|
+
>>> al = AgentList.example()
|
450
|
+
>>> al.to_dataset()
|
451
|
+
Dataset([{'age': [22, 22]}, {'hair': ['brown', 'brown']}, {'height': [5.5, 5.5]}])
|
452
|
+
>>> al.to_dataset(traits_only = False)
|
453
|
+
Dataset([{'age': [22, 22]}, {'hair': ['brown', 'brown']}, {'height': [5.5, 5.5]}, {'agent_parameters': [{'instruction': 'You are answering questions as if you were a human. Do not break character.', 'agent_name': None}, {'instruction': 'You are answering questions as if you were a human. Do not break character.', 'agent_name': None}]}])
|
454
|
+
"""
|
455
|
+
from edsl.results.Dataset import Dataset
|
456
|
+
from collections import defaultdict
|
457
|
+
|
458
|
+
agent_trait_keys = []
|
459
|
+
for agent in self:
|
460
|
+
agent_keys = list(agent.traits.keys())
|
461
|
+
for key in agent_keys:
|
462
|
+
if key not in agent_trait_keys:
|
463
|
+
agent_trait_keys.append(key)
|
464
|
+
|
465
|
+
data = defaultdict(list)
|
466
|
+
for agent in self:
|
467
|
+
for trait_key in agent_trait_keys:
|
468
|
+
data[trait_key].append(agent.traits.get(trait_key, None))
|
469
|
+
if not traits_only:
|
470
|
+
data["agent_parameters"].append(
|
471
|
+
{"instruction": agent.instruction, "agent_name": agent.name}
|
472
|
+
)
|
473
|
+
return Dataset([{key: entry} for key, entry in data.items()])
|
474
|
+
|
475
|
+
def tree(self, node_order: Optional[List[str]] = None):
|
476
|
+
return self.to_scenario_list().tree(node_order)
|
26
477
|
|
27
478
|
@classmethod
|
479
|
+
@remove_edsl_version
|
28
480
|
def from_dict(cls, data: dict) -> "AgentList":
|
29
|
-
"""
|
481
|
+
"""Deserialize the dictionary back to an AgentList object.
|
482
|
+
|
483
|
+
:param: data: A dictionary representing an AgentList.
|
484
|
+
>>> from edsl.agents.Agent import Agent
|
485
|
+
>>> al = AgentList([Agent.example(), Agent.example()])
|
486
|
+
>>> al2 = AgentList.from_dict(al.to_dict())
|
487
|
+
>>> al2 == al
|
488
|
+
True
|
489
|
+
"""
|
490
|
+
from edsl.agents.Agent import Agent
|
491
|
+
|
30
492
|
agents = [Agent.from_dict(agent_dict) for agent_dict in data["agent_list"]]
|
31
493
|
return cls(agents)
|
32
494
|
|
33
495
|
@classmethod
|
34
|
-
def example(cls):
|
35
|
-
|
496
|
+
def example(cls, randomize: bool = False) -> AgentList:
|
497
|
+
"""
|
498
|
+
Returns an example AgentList instance.
|
36
499
|
|
37
|
-
|
500
|
+
:param randomize: If True, uses Agent's randomize method.
|
501
|
+
"""
|
502
|
+
from edsl.agents.Agent import Agent
|
503
|
+
|
504
|
+
return cls([Agent.example(randomize), Agent.example(randomize)])
|
505
|
+
|
506
|
+
@classmethod
|
507
|
+
def from_list(self, trait_name: str, values: List[Any]):
|
508
|
+
"""Create an AgentList from a list of values.
|
509
|
+
|
510
|
+
:param trait_name: The name of the trait.
|
511
|
+
:param values: A list of values.
|
512
|
+
|
513
|
+
>>> AgentList.from_list('age', [22, 23])
|
514
|
+
AgentList([Agent(traits = {'age': 22}), Agent(traits = {'age': 23})])
|
515
|
+
"""
|
516
|
+
from edsl.agents.Agent import Agent
|
517
|
+
|
518
|
+
return AgentList([Agent({trait_name: value}) for value in values])
|
519
|
+
|
520
|
+
def __mul__(self, other: AgentList) -> AgentList:
|
521
|
+
"""Takes the cross product of two AgentLists."""
|
522
|
+
from itertools import product
|
523
|
+
|
524
|
+
new_sl = []
|
525
|
+
for s1, s2 in list(product(self, other)):
|
526
|
+
new_sl.append(s1 + s2)
|
527
|
+
return AgentList(new_sl)
|
528
|
+
|
529
|
+
def code(self, string=True) -> Union[str, list[str]]:
|
530
|
+
"""Return code to construct an AgentList.
|
531
|
+
|
532
|
+
>>> al = AgentList.example()
|
533
|
+
>>> print(al.code())
|
534
|
+
from edsl.agents.Agent import Agent
|
535
|
+
from edsl.agents.AgentList import AgentList
|
536
|
+
agent_list = AgentList([Agent(traits = {'age': 22, 'hair': 'brown', 'height': 5.5}), Agent(traits = {'age': 22, 'hair': 'brown', 'height': 5.5})])
|
537
|
+
"""
|
38
538
|
lines = [
|
39
539
|
"from edsl.agents.Agent import Agent",
|
40
540
|
"from edsl.agents.AgentList import AgentList",
|
41
541
|
]
|
42
542
|
lines.append(f"agent_list = AgentList({self.data})")
|
543
|
+
if string:
|
544
|
+
return "\n".join(lines)
|
43
545
|
return lines
|
44
546
|
|
45
|
-
def rich_print(self):
|
46
|
-
"""Displays an object as a table."""
|
47
|
-
table = Table(title="AgentList")
|
48
|
-
table.add_column("Agents", style="bold")
|
49
|
-
for agent in self.data:
|
50
|
-
table.add_row(agent.rich_print())
|
51
|
-
return table
|
52
|
-
|
53
547
|
|
54
548
|
if __name__ == "__main__":
|
55
|
-
|
549
|
+
import doctest
|
550
|
+
|
551
|
+
doctest.testmod(optionflags=doctest.ELLIPSIS)
|