edsl 0.1.47__py3-none-any.whl → 0.1.48__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/__init__.py +44 -39
- edsl/__version__.py +1 -1
- edsl/agents/__init__.py +4 -2
- edsl/agents/{Agent.py → agent.py} +442 -152
- edsl/agents/{AgentList.py → agent_list.py} +220 -162
- edsl/agents/descriptors.py +46 -7
- edsl/{exceptions/agents.py → agents/exceptions.py} +3 -12
- edsl/base/__init__.py +75 -0
- edsl/base/base_class.py +1303 -0
- edsl/base/data_transfer_models.py +114 -0
- edsl/base/enums.py +215 -0
- edsl/base.py +8 -0
- edsl/buckets/__init__.py +25 -0
- edsl/buckets/bucket_collection.py +324 -0
- edsl/buckets/model_buckets.py +206 -0
- edsl/buckets/token_bucket.py +502 -0
- edsl/{jobs/buckets/TokenBucketAPI.py → buckets/token_bucket_api.py} +1 -1
- edsl/buckets/token_bucket_client.py +509 -0
- edsl/caching/__init__.py +20 -0
- edsl/caching/cache.py +814 -0
- edsl/caching/cache_entry.py +427 -0
- edsl/{data/CacheHandler.py → caching/cache_handler.py} +14 -15
- edsl/caching/exceptions.py +24 -0
- edsl/caching/orm.py +30 -0
- edsl/{data/RemoteCacheSync.py → caching/remote_cache_sync.py} +3 -3
- edsl/caching/sql_dict.py +441 -0
- edsl/config/__init__.py +8 -0
- edsl/config/config_class.py +177 -0
- edsl/config.py +4 -176
- edsl/conversation/Conversation.py +7 -7
- edsl/conversation/car_buying.py +4 -4
- edsl/conversation/chips.py +6 -6
- edsl/coop/__init__.py +25 -2
- edsl/coop/coop.py +303 -67
- edsl/coop/{ExpectedParrotKeyHandler.py → ep_key_handling.py} +86 -10
- edsl/coop/exceptions.py +62 -0
- edsl/coop/price_fetcher.py +126 -0
- edsl/coop/utils.py +89 -24
- edsl/data_transfer_models.py +5 -72
- edsl/dataset/__init__.py +10 -0
- edsl/{results/Dataset.py → dataset/dataset.py} +116 -36
- edsl/{results/DatasetExportMixin.py → dataset/dataset_operations_mixin.py} +606 -122
- edsl/{results/DatasetTree.py → dataset/dataset_tree.py} +156 -75
- edsl/{results/TableDisplay.py → dataset/display/table_display.py} +18 -7
- edsl/{results → dataset/display}/table_renderers.py +58 -2
- edsl/{results → dataset}/file_exports.py +4 -5
- edsl/{results → dataset}/smart_objects.py +2 -2
- edsl/enums.py +5 -205
- edsl/inference_services/__init__.py +5 -0
- edsl/inference_services/{AvailableModelCacheHandler.py → available_model_cache_handler.py} +2 -3
- edsl/inference_services/{AvailableModelFetcher.py → available_model_fetcher.py} +8 -14
- edsl/inference_services/data_structures.py +3 -2
- edsl/{exceptions/inference_services.py → inference_services/exceptions.py} +1 -1
- edsl/inference_services/{InferenceServiceABC.py → inference_service_abc.py} +1 -1
- edsl/inference_services/{InferenceServicesCollection.py → inference_services_collection.py} +8 -7
- edsl/inference_services/registry.py +4 -41
- edsl/inference_services/{ServiceAvailability.py → service_availability.py} +5 -25
- edsl/inference_services/services/__init__.py +31 -0
- edsl/inference_services/{AnthropicService.py → services/anthropic_service.py} +3 -3
- edsl/inference_services/{AwsBedrock.py → services/aws_bedrock.py} +2 -2
- edsl/inference_services/{AzureAI.py → services/azure_ai.py} +2 -2
- edsl/inference_services/{DeepInfraService.py → services/deep_infra_service.py} +1 -3
- edsl/inference_services/{DeepSeekService.py → services/deep_seek_service.py} +2 -4
- edsl/inference_services/{GoogleService.py → services/google_service.py} +5 -4
- edsl/inference_services/{GroqService.py → services/groq_service.py} +1 -1
- edsl/inference_services/{MistralAIService.py → services/mistral_ai_service.py} +3 -3
- edsl/inference_services/{OllamaService.py → services/ollama_service.py} +1 -7
- edsl/inference_services/{OpenAIService.py → services/open_ai_service.py} +5 -6
- edsl/inference_services/{PerplexityService.py → services/perplexity_service.py} +3 -7
- edsl/inference_services/{TestService.py → services/test_service.py} +7 -6
- edsl/inference_services/{TogetherAIService.py → services/together_ai_service.py} +2 -6
- edsl/inference_services/{XAIService.py → services/xai_service.py} +1 -1
- edsl/inference_services/write_available.py +1 -2
- edsl/instructions/__init__.py +6 -0
- edsl/{surveys/instructions/Instruction.py → instructions/instruction.py} +11 -6
- edsl/{surveys/instructions/InstructionCollection.py → instructions/instruction_collection.py} +10 -5
- edsl/{surveys/InstructionHandler.py → instructions/instruction_handler.py} +3 -3
- edsl/{jobs/interviews → interviews}/ReportErrors.py +2 -2
- edsl/interviews/__init__.py +4 -0
- edsl/{jobs/AnswerQuestionFunctionConstructor.py → interviews/answering_function.py} +45 -18
- edsl/{jobs/interviews/InterviewExceptionEntry.py → interviews/exception_tracking.py} +107 -22
- edsl/interviews/interview.py +638 -0
- edsl/{jobs/interviews/InterviewStatusDictionary.py → interviews/interview_status_dictionary.py} +21 -12
- edsl/{jobs/interviews/InterviewStatusLog.py → interviews/interview_status_log.py} +16 -7
- edsl/{jobs/InterviewTaskManager.py → interviews/interview_task_manager.py} +12 -7
- edsl/{jobs/RequestTokenEstimator.py → interviews/request_token_estimator.py} +8 -3
- edsl/{jobs/interviews/InterviewStatistic.py → interviews/statistics.py} +36 -10
- edsl/invigilators/__init__.py +38 -0
- edsl/invigilators/invigilator_base.py +477 -0
- edsl/{agents/Invigilator.py → invigilators/invigilators.py} +263 -10
- edsl/invigilators/prompt_constructor.py +476 -0
- edsl/{agents → invigilators}/prompt_helpers.py +2 -1
- edsl/{agents/QuestionInstructionPromptBuilder.py → invigilators/question_instructions_prompt_builder.py} +18 -13
- edsl/{agents → invigilators}/question_option_processor.py +96 -21
- edsl/{agents/QuestionTemplateReplacementsBuilder.py → invigilators/question_template_replacements_builder.py} +64 -12
- edsl/jobs/__init__.py +7 -1
- edsl/jobs/async_interview_runner.py +99 -35
- edsl/jobs/check_survey_scenario_compatibility.py +7 -5
- edsl/jobs/data_structures.py +153 -22
- edsl/{exceptions/jobs.py → jobs/exceptions.py} +2 -1
- edsl/jobs/{FetchInvigilator.py → fetch_invigilator.py} +4 -4
- edsl/jobs/{loggers/HTMLTableJobLogger.py → html_table_job_logger.py} +6 -2
- edsl/jobs/{Jobs.py → jobs.py} +313 -167
- edsl/jobs/{JobsChecks.py → jobs_checks.py} +15 -7
- edsl/jobs/{JobsComponentConstructor.py → jobs_component_constructor.py} +19 -17
- edsl/jobs/{InterviewsConstructor.py → jobs_interview_constructor.py} +10 -5
- edsl/jobs/jobs_pricing_estimation.py +347 -0
- edsl/jobs/{JobsRemoteInferenceLogger.py → jobs_remote_inference_logger.py} +4 -3
- edsl/jobs/jobs_runner_asyncio.py +282 -0
- edsl/jobs/{JobsRemoteInferenceHandler.py → remote_inference.py} +19 -22
- edsl/jobs/results_exceptions_handler.py +2 -2
- edsl/key_management/__init__.py +28 -0
- edsl/key_management/key_lookup.py +161 -0
- edsl/{language_models/key_management/KeyLookupBuilder.py → key_management/key_lookup_builder.py} +118 -47
- edsl/key_management/key_lookup_collection.py +82 -0
- edsl/key_management/models.py +218 -0
- edsl/language_models/__init__.py +7 -2
- edsl/language_models/{ComputeCost.py → compute_cost.py} +18 -3
- edsl/{exceptions/language_models.py → language_models/exceptions.py} +2 -1
- edsl/language_models/language_model.py +1080 -0
- edsl/language_models/model.py +10 -25
- edsl/language_models/{ModelList.py → model_list.py} +9 -14
- edsl/language_models/{RawResponseHandler.py → raw_response_handler.py} +1 -1
- edsl/language_models/{RegisterLanguageModelsMeta.py → registry.py} +1 -1
- edsl/language_models/repair.py +4 -4
- edsl/language_models/utilities.py +4 -4
- edsl/notebooks/__init__.py +3 -1
- edsl/notebooks/{Notebook.py → notebook.py} +7 -8
- edsl/prompts/__init__.py +1 -1
- edsl/{exceptions/prompts.py → prompts/exceptions.py} +3 -1
- edsl/prompts/{Prompt.py → prompt.py} +101 -95
- edsl/questions/HTMLQuestion.py +1 -1
- edsl/questions/__init__.py +154 -25
- edsl/questions/answer_validator_mixin.py +1 -1
- edsl/questions/compose_questions.py +4 -3
- edsl/questions/derived/question_likert_five.py +166 -0
- edsl/questions/derived/{QuestionLinearScale.py → question_linear_scale.py} +4 -4
- edsl/questions/derived/{QuestionTopK.py → question_top_k.py} +4 -4
- edsl/questions/derived/{QuestionYesNo.py → question_yes_no.py} +4 -5
- edsl/questions/descriptors.py +24 -30
- edsl/questions/loop_processor.py +65 -19
- edsl/questions/question_base.py +881 -0
- edsl/questions/question_base_gen_mixin.py +15 -16
- edsl/questions/{QuestionBasePromptsMixin.py → question_base_prompts_mixin.py} +2 -2
- edsl/questions/{QuestionBudget.py → question_budget.py} +3 -4
- edsl/questions/{QuestionCheckBox.py → question_check_box.py} +16 -16
- edsl/questions/{QuestionDict.py → question_dict.py} +39 -5
- edsl/questions/{QuestionExtract.py → question_extract.py} +9 -9
- edsl/questions/question_free_text.py +282 -0
- edsl/questions/{QuestionFunctional.py → question_functional.py} +6 -5
- edsl/questions/{QuestionList.py → question_list.py} +6 -7
- edsl/questions/{QuestionMatrix.py → question_matrix.py} +6 -5
- edsl/questions/{QuestionMultipleChoice.py → question_multiple_choice.py} +126 -21
- edsl/questions/{QuestionNumerical.py → question_numerical.py} +5 -5
- edsl/questions/{QuestionRank.py → question_rank.py} +6 -6
- edsl/questions/question_registry.py +4 -9
- edsl/questions/register_questions_meta.py +8 -4
- edsl/questions/response_validator_abc.py +17 -16
- edsl/results/__init__.py +4 -1
- edsl/{exceptions/results.py → results/exceptions.py} +1 -1
- edsl/results/report.py +197 -0
- edsl/results/{Result.py → result.py} +131 -45
- edsl/results/{Results.py → results.py} +365 -220
- edsl/results/results_selector.py +344 -25
- edsl/scenarios/__init__.py +30 -3
- edsl/scenarios/{ConstructDownloadLink.py → construct_download_link.py} +7 -0
- edsl/scenarios/directory_scanner.py +156 -13
- edsl/scenarios/document_chunker.py +186 -0
- edsl/scenarios/exceptions.py +101 -0
- edsl/scenarios/file_methods.py +2 -3
- edsl/scenarios/{FileStore.py → file_store.py} +275 -189
- edsl/scenarios/handlers/__init__.py +14 -14
- edsl/scenarios/handlers/{csv.py → csv_file_store.py} +1 -2
- edsl/scenarios/handlers/{docx.py → docx_file_store.py} +8 -7
- edsl/scenarios/handlers/{html.py → html_file_store.py} +1 -2
- edsl/scenarios/handlers/{jpeg.py → jpeg_file_store.py} +1 -1
- edsl/scenarios/handlers/{json.py → json_file_store.py} +1 -1
- edsl/scenarios/handlers/latex_file_store.py +5 -0
- edsl/scenarios/handlers/{md.py → md_file_store.py} +1 -1
- edsl/scenarios/handlers/{pdf.py → pdf_file_store.py} +2 -2
- edsl/scenarios/handlers/{png.py → png_file_store.py} +1 -1
- edsl/scenarios/handlers/{pptx.py → pptx_file_store.py} +8 -7
- edsl/scenarios/handlers/{py.py → py_file_store.py} +1 -3
- edsl/scenarios/handlers/{sql.py → sql_file_store.py} +2 -1
- edsl/scenarios/handlers/{sqlite.py → sqlite_file_store.py} +2 -3
- edsl/scenarios/handlers/{txt.py → txt_file_store.py} +1 -1
- edsl/scenarios/scenario.py +928 -0
- edsl/scenarios/scenario_join.py +18 -5
- edsl/scenarios/{ScenarioList.py → scenario_list.py} +294 -106
- edsl/scenarios/{ScenarioListPdfMixin.py → scenario_list_pdf_tools.py} +16 -15
- edsl/scenarios/scenario_selector.py +5 -1
- edsl/study/ObjectEntry.py +2 -2
- edsl/study/SnapShot.py +5 -5
- edsl/study/Study.py +18 -19
- edsl/study/__init__.py +6 -4
- edsl/surveys/__init__.py +7 -4
- edsl/surveys/dag/__init__.py +2 -0
- edsl/surveys/{ConstructDAG.py → dag/construct_dag.py} +3 -3
- edsl/surveys/{DAG.py → dag/dag.py} +13 -10
- edsl/surveys/descriptors.py +1 -1
- edsl/surveys/{EditSurvey.py → edit_survey.py} +9 -9
- edsl/{exceptions/surveys.py → surveys/exceptions.py} +1 -2
- edsl/surveys/memory/__init__.py +3 -0
- edsl/surveys/{MemoryPlan.py → memory/memory_plan.py} +10 -9
- edsl/surveys/rules/__init__.py +3 -0
- edsl/surveys/{Rule.py → rules/rule.py} +103 -43
- edsl/surveys/{RuleCollection.py → rules/rule_collection.py} +21 -30
- edsl/surveys/{RuleManager.py → rules/rule_manager.py} +19 -13
- edsl/surveys/survey.py +1743 -0
- edsl/surveys/{SurveyExportMixin.py → survey_export.py} +22 -27
- edsl/surveys/{SurveyFlowVisualization.py → survey_flow_visualization.py} +11 -2
- edsl/surveys/{Simulator.py → survey_simulator.py} +10 -3
- edsl/tasks/__init__.py +32 -0
- edsl/{jobs/tasks/QuestionTaskCreator.py → tasks/question_task_creator.py} +115 -57
- edsl/tasks/task_creators.py +135 -0
- edsl/{jobs/tasks/TaskHistory.py → tasks/task_history.py} +86 -47
- edsl/{jobs/tasks → tasks}/task_status_enum.py +91 -7
- edsl/tasks/task_status_log.py +85 -0
- edsl/tokens/__init__.py +2 -0
- edsl/tokens/interview_token_usage.py +53 -0
- edsl/utilities/PrettyList.py +1 -1
- edsl/utilities/SystemInfo.py +25 -22
- edsl/utilities/__init__.py +29 -21
- edsl/utilities/gcp_bucket/__init__.py +2 -0
- edsl/utilities/gcp_bucket/cloud_storage.py +99 -96
- edsl/utilities/interface.py +44 -536
- edsl/{results/MarkdownToPDF.py → utilities/markdown_to_pdf.py} +13 -5
- edsl/utilities/repair_functions.py +1 -1
- {edsl-0.1.47.dist-info → edsl-0.1.48.dist-info}/METADATA +1 -1
- edsl-0.1.48.dist-info/RECORD +347 -0
- edsl/Base.py +0 -493
- edsl/BaseDiff.py +0 -260
- edsl/agents/InvigilatorBase.py +0 -260
- edsl/agents/PromptConstructor.py +0 -318
- edsl/coop/PriceFetcher.py +0 -54
- edsl/data/Cache.py +0 -582
- edsl/data/CacheEntry.py +0 -238
- edsl/data/SQLiteDict.py +0 -292
- edsl/data/__init__.py +0 -5
- edsl/data/orm.py +0 -10
- edsl/exceptions/cache.py +0 -5
- edsl/exceptions/coop.py +0 -14
- edsl/exceptions/data.py +0 -14
- edsl/exceptions/scenarios.py +0 -29
- edsl/jobs/Answers.py +0 -43
- edsl/jobs/JobsPrompts.py +0 -354
- edsl/jobs/buckets/BucketCollection.py +0 -134
- edsl/jobs/buckets/ModelBuckets.py +0 -65
- edsl/jobs/buckets/TokenBucket.py +0 -283
- edsl/jobs/buckets/TokenBucketClient.py +0 -191
- edsl/jobs/interviews/Interview.py +0 -395
- edsl/jobs/interviews/InterviewExceptionCollection.py +0 -99
- edsl/jobs/interviews/InterviewStatisticsCollection.py +0 -25
- edsl/jobs/runners/JobsRunnerAsyncio.py +0 -163
- edsl/jobs/runners/JobsRunnerStatusData.py +0 -0
- edsl/jobs/tasks/TaskCreators.py +0 -64
- edsl/jobs/tasks/TaskStatusLog.py +0 -23
- edsl/jobs/tokens/InterviewTokenUsage.py +0 -27
- edsl/language_models/LanguageModel.py +0 -635
- edsl/language_models/ServiceDataSources.py +0 -0
- edsl/language_models/key_management/KeyLookup.py +0 -63
- edsl/language_models/key_management/KeyLookupCollection.py +0 -38
- edsl/language_models/key_management/models.py +0 -137
- edsl/questions/QuestionBase.py +0 -544
- edsl/questions/QuestionFreeText.py +0 -130
- edsl/questions/derived/QuestionLikertFive.py +0 -76
- edsl/results/ResultsExportMixin.py +0 -45
- edsl/results/TextEditor.py +0 -50
- edsl/results/results_fetch_mixin.py +0 -33
- edsl/results/results_tools_mixin.py +0 -98
- edsl/scenarios/DocumentChunker.py +0 -104
- edsl/scenarios/Scenario.py +0 -548
- edsl/scenarios/ScenarioHtmlMixin.py +0 -65
- edsl/scenarios/ScenarioListExportMixin.py +0 -45
- edsl/scenarios/handlers/latex.py +0 -5
- edsl/shared.py +0 -1
- edsl/surveys/Survey.py +0 -1301
- edsl/surveys/SurveyQualtricsImport.py +0 -284
- edsl/surveys/SurveyToApp.py +0 -141
- edsl/surveys/instructions/__init__.py +0 -0
- edsl/tools/__init__.py +0 -1
- edsl/tools/clusters.py +0 -192
- edsl/tools/embeddings.py +0 -27
- edsl/tools/embeddings_plotting.py +0 -118
- edsl/tools/plotting.py +0 -112
- edsl/tools/summarize.py +0 -18
- edsl/utilities/data/Registry.py +0 -6
- edsl/utilities/data/__init__.py +0 -1
- edsl/utilities/data/scooter_results.json +0 -1
- edsl-0.1.47.dist-info/RECORD +0 -354
- /edsl/coop/{CoopFunctionsMixin.py → coop_functions.py} +0 -0
- /edsl/{results → dataset/display}/CSSParameterizer.py +0 -0
- /edsl/{language_models/key_management → dataset/display}/__init__.py +0 -0
- /edsl/{results → dataset/display}/table_data_class.py +0 -0
- /edsl/{results → dataset/display}/table_display.css +0 -0
- /edsl/{results/ResultsGGMixin.py → dataset/r/ggplot.py} +0 -0
- /edsl/{results → dataset}/tree_explore.py +0 -0
- /edsl/{surveys/instructions/ChangeInstruction.py → instructions/change_instruction.py} +0 -0
- /edsl/{jobs/interviews → interviews}/interview_status_enum.py +0 -0
- /edsl/jobs/{runners/JobsRunnerStatus.py → jobs_runner_status.py} +0 -0
- /edsl/language_models/{PriceManager.py → price_manager.py} +0 -0
- /edsl/language_models/{fake_openai_call.py → unused/fake_openai_call.py} +0 -0
- /edsl/language_models/{fake_openai_service.py → unused/fake_openai_service.py} +0 -0
- /edsl/notebooks/{NotebookToLaTeX.py → notebook_to_latex.py} +0 -0
- /edsl/{exceptions/questions.py → questions/exceptions.py} +0 -0
- /edsl/questions/{SimpleAskMixin.py → simple_ask_mixin.py} +0 -0
- /edsl/surveys/{Memory.py → memory/memory.py} +0 -0
- /edsl/surveys/{MemoryManagement.py → memory/memory_management.py} +0 -0
- /edsl/surveys/{SurveyCSS.py → survey_css.py} +0 -0
- /edsl/{jobs/tokens/TokenUsage.py → tokens/token_usage.py} +0 -0
- /edsl/{results/MarkdownToDocx.py → utilities/markdown_to_docx.py} +0 -0
- /edsl/{TemplateLoader.py → utilities/template_loader.py} +0 -0
- {edsl-0.1.47.dist-info → edsl-0.1.48.dist-info}/LICENSE +0 -0
- {edsl-0.1.47.dist-info → edsl-0.1.48.dist-info}/WHEEL +0 -0
@@ -4,26 +4,33 @@
|
|
4
4
|
from __future__ import annotations
|
5
5
|
import csv
|
6
6
|
import sys
|
7
|
+
import random
|
8
|
+
import logging
|
9
|
+
from collections import defaultdict
|
10
|
+
from itertools import product
|
11
|
+
|
12
|
+
|
7
13
|
from collections import UserList
|
8
14
|
from collections.abc import Iterable
|
9
|
-
|
10
15
|
from typing import Any, List, Optional, Union, TYPE_CHECKING
|
11
16
|
|
12
17
|
from simpleeval import EvalWithCompoundTypes, NameNotDefined
|
13
18
|
|
14
|
-
from
|
15
|
-
from
|
16
|
-
from
|
17
|
-
|
18
|
-
from
|
19
|
-
|
19
|
+
from ..base import Base
|
20
|
+
from ..utilities import is_notebook, remove_edsl_version, dict_hash
|
21
|
+
from ..dataset.dataset_operations_mixin import AgentListOperationsMixin
|
22
|
+
|
23
|
+
from .agent import Agent
|
24
|
+
|
25
|
+
from .exceptions import AgentListError
|
20
26
|
|
21
27
|
logger = logging.getLogger(__name__)
|
22
28
|
|
23
29
|
if TYPE_CHECKING:
|
24
|
-
from
|
25
|
-
from
|
30
|
+
from ..scenarios import ScenarioList
|
31
|
+
from ..agents import Agent
|
26
32
|
from pandas import DataFrame
|
33
|
+
from ..dataset import Dataset
|
27
34
|
|
28
35
|
|
29
36
|
def is_iterable(obj):
|
@@ -36,30 +43,66 @@ class EmptyAgentList:
|
|
36
43
|
|
37
44
|
|
38
45
|
# ResultsExportMixin,
|
39
|
-
class AgentList(UserList, Base):
|
40
|
-
"""A list of Agents.
|
46
|
+
class AgentList(UserList, Base, AgentListOperationsMixin):
|
47
|
+
"""A list of Agents with additional functionality for manipulation and analysis.
|
48
|
+
|
49
|
+
The AgentList class extends Python's UserList to provide a container for Agent objects
|
50
|
+
with methods for filtering, transforming, and analyzing collections of agents.
|
51
|
+
|
52
|
+
|
53
|
+
>>> AgentList.example().to_scenario_list()
|
54
|
+
ScenarioList([Scenario({'age': 22, 'hair': 'brown', 'height': 5.5}), Scenario({'age': 22, 'hair': 'brown', 'height': 5.5})])
|
55
|
+
|
56
|
+
>>> AgentList.example().to_dataset()
|
57
|
+
Dataset([{'age': [22, 22]}, {'hair': ['brown', 'brown']}, {'height': [5.5, 5.5]}])
|
58
|
+
|
59
|
+
>>> AgentList.example().to_pandas()
|
60
|
+
age hair height
|
61
|
+
0 22 brown 5.5
|
62
|
+
1 22 brown 5.5
|
63
|
+
|
64
|
+
|
65
|
+
"""
|
41
66
|
|
42
67
|
__documentation__ = (
|
43
68
|
"https://docs.expectedparrot.com/en/latest/agents.html#agentlist-class"
|
44
69
|
)
|
45
70
|
|
46
|
-
def __init__(self, data: Optional[list["Agent"]] = None):
|
71
|
+
def __init__(self, data: Optional[list["Agent"]] = None, codebook: Optional[dict[str, str]] = None):
|
47
72
|
"""Initialize a new AgentList.
|
48
73
|
|
49
|
-
|
74
|
+
>>> from edsl import Agent
|
75
|
+
>>> al = AgentList([Agent(traits = {'age': 22, 'hair': 'brown', 'height': 5.5}),
|
76
|
+
... Agent(traits = {'age': 22, 'hair': 'brown', 'height': 5.5})])
|
77
|
+
>>> al
|
78
|
+
AgentList([Agent(traits = {'age': 22, 'hair': 'brown', 'height': 5.5}), Agent(traits = {'age': 22, 'hair': 'brown', 'height': 5.5})])
|
79
|
+
>>> al_with_codebook = AgentList([Agent(traits = {'age': 22})], codebook={'age': 'Age in years'})
|
80
|
+
>>> al_with_codebook[0].codebook
|
81
|
+
{'age': 'Age in years'}
|
82
|
+
|
83
|
+
Args:
|
84
|
+
data: A list of Agent objects. If None, creates an empty AgentList.
|
85
|
+
codebook: Optional dictionary mapping trait names to descriptions.
|
86
|
+
If provided, will be applied to all agents in the list.
|
50
87
|
"""
|
51
88
|
if data is not None:
|
52
89
|
super().__init__(data)
|
53
90
|
else:
|
54
91
|
super().__init__()
|
92
|
+
|
93
|
+
# Apply codebook to all agents if provided
|
94
|
+
if codebook is not None:
|
95
|
+
self.set_codebook(codebook)
|
55
96
|
|
56
97
|
def shuffle(self, seed: Optional[str] = None) -> AgentList:
|
57
|
-
"""
|
98
|
+
"""Randomly shuffle the agents in place.
|
58
99
|
|
59
|
-
:
|
60
|
-
|
61
|
-
import random
|
100
|
+
Args:
|
101
|
+
seed: Optional seed for the random number generator to ensure reproducibility.
|
62
102
|
|
103
|
+
Returns:
|
104
|
+
AgentList: The shuffled AgentList (self).
|
105
|
+
"""
|
63
106
|
if seed is not None:
|
64
107
|
random.seed(seed)
|
65
108
|
random.shuffle(self.data)
|
@@ -68,64 +111,52 @@ class AgentList(UserList, Base):
|
|
68
111
|
def sample(self, n: int, seed: Optional[str] = None) -> AgentList:
|
69
112
|
"""Return a random sample of agents.
|
70
113
|
|
71
|
-
:
|
72
|
-
|
114
|
+
Args:
|
115
|
+
n: The number of agents to sample.
|
116
|
+
seed: Optional seed for the random number generator to ensure reproducibility.
|
117
|
+
|
118
|
+
Returns:
|
119
|
+
AgentList: A new AgentList containing the sampled agents.
|
73
120
|
"""
|
74
|
-
import random
|
75
121
|
|
76
122
|
if seed:
|
77
123
|
random.seed(seed)
|
78
124
|
return AgentList(random.sample(self.data, n))
|
79
125
|
|
80
|
-
def
|
81
|
-
"""
|
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.
|
126
|
+
def duplicate(self) -> AgentList:
|
127
|
+
"""Create a deep copy of the AgentList.
|
96
128
|
|
97
|
-
:
|
129
|
+
Returns:
|
130
|
+
AgentList: A new AgentList containing copies of all agents.
|
98
131
|
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
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
|
132
|
+
Examples:
|
133
|
+
>>> al = AgentList.example()
|
134
|
+
>>> al2 = al.duplicate()
|
135
|
+
>>> al2 == al
|
136
|
+
True
|
137
|
+
>>> id(al2) == id(al)
|
138
|
+
False
|
114
139
|
"""
|
115
140
|
return AgentList([a.duplicate() for a in self.data])
|
116
141
|
|
117
|
-
def rename(self, old_name, new_name) -> AgentList:
|
118
|
-
"""Rename a trait in the
|
142
|
+
def rename(self, old_name: str, new_name: str) -> AgentList:
|
143
|
+
"""Rename a trait across all agents in the list.
|
119
144
|
|
120
|
-
:
|
121
|
-
|
122
|
-
|
145
|
+
Args:
|
146
|
+
old_name: The current name of the trait.
|
147
|
+
new_name: The new name to assign to the trait.
|
123
148
|
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
149
|
+
Returns:
|
150
|
+
AgentList: A new AgentList with the renamed trait.
|
151
|
+
|
152
|
+
Examples:
|
153
|
+
>>> from edsl import Agent
|
154
|
+
>>> al = AgentList([Agent(traits = {'a': 1, 'b': 1}),
|
155
|
+
... Agent(traits = {'a': 1, 'b': 2})])
|
156
|
+
>>> al2 = al.rename('a', 'c')
|
157
|
+
>>> assert al2 == AgentList([Agent(traits = {'c': 1, 'b': 1}),
|
158
|
+
... Agent(traits = {'c': 1, 'b': 2})])
|
159
|
+
>>> assert al != al2
|
129
160
|
"""
|
130
161
|
newagents = []
|
131
162
|
for agent in self:
|
@@ -133,15 +164,21 @@ class AgentList(UserList, Base):
|
|
133
164
|
return AgentList(newagents)
|
134
165
|
|
135
166
|
def select(self, *traits) -> AgentList:
|
136
|
-
"""
|
167
|
+
"""Create a new AgentList with only the specified traits.
|
137
168
|
|
138
|
-
|
139
|
-
|
140
|
-
>>> al.select('a')
|
141
|
-
AgentList([Agent(traits = {'a': 1}), Agent(traits = {'a': 1})])
|
169
|
+
Args:
|
170
|
+
*traits: Variable number of trait names to keep.
|
142
171
|
|
143
|
-
|
172
|
+
Returns:
|
173
|
+
AgentList: A new AgentList containing agents with only the selected traits.
|
144
174
|
|
175
|
+
Examples:
|
176
|
+
>>> from edsl import Agent
|
177
|
+
>>> al = AgentList([Agent(traits = {'a': 1, 'b': 1}),
|
178
|
+
... Agent(traits = {'a': 1, 'b': 2})])
|
179
|
+
>>> al.select('a')
|
180
|
+
AgentList([Agent(traits = {'a': 1}), Agent(traits = {'a': 1})])
|
181
|
+
"""
|
145
182
|
if len(traits) == 1:
|
146
183
|
traits_to_select = [list(traits)[0]]
|
147
184
|
else:
|
@@ -150,23 +187,27 @@ class AgentList(UserList, Base):
|
|
150
187
|
return AgentList([agent.select(*traits_to_select) for agent in self.data])
|
151
188
|
|
152
189
|
def filter(self, expression: str) -> AgentList:
|
153
|
-
"""
|
154
|
-
|
190
|
+
"""Filter agents based on a boolean expression.
|
191
|
+
|
192
|
+
Args:
|
193
|
+
expression: A string containing a boolean expression to evaluate against
|
194
|
+
each agent's traits.
|
155
195
|
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
196
|
+
Returns:
|
197
|
+
AgentList: A new AgentList containing only agents that satisfy the expression.
|
198
|
+
|
199
|
+
Examples:
|
200
|
+
>>> from edsl import Agent
|
201
|
+
>>> al = AgentList([Agent(traits = {'a': 1, 'b': 1}),
|
202
|
+
... Agent(traits = {'a': 1, 'b': 2})])
|
203
|
+
>>> al.filter("b == 2")
|
204
|
+
AgentList([Agent(traits = {'a': 1, 'b': 2})])
|
160
205
|
"""
|
161
206
|
|
162
207
|
def create_evaluator(agent: "Agent"):
|
163
|
-
"""Create an evaluator for the given
|
164
|
-
The 'combined_dict' is a mapping of all values for that Result object.
|
165
|
-
"""
|
208
|
+
"""Create an evaluator for the given agent."""
|
166
209
|
return EvalWithCompoundTypes(names=agent.traits)
|
167
210
|
|
168
|
-
# iterates through all the results and evaluates the expression
|
169
|
-
|
170
211
|
try:
|
171
212
|
new_data = [
|
172
213
|
agent for agent in self.data if create_evaluator(agent).eval(expression)
|
@@ -188,7 +229,7 @@ class AgentList(UserList, Base):
|
|
188
229
|
@property
|
189
230
|
def all_traits(self) -> list[str]:
|
190
231
|
"""Return all traits in the AgentList.
|
191
|
-
>>> from edsl
|
232
|
+
>>> from edsl import Agent
|
192
233
|
>>> agent_1 = Agent(traits = {'age': 22})
|
193
234
|
>>> agent_2 = Agent(traits = {'hair': 'brown'})
|
194
235
|
>>> al = AgentList([agent_1, agent_2])
|
@@ -201,7 +242,7 @@ class AgentList(UserList, Base):
|
|
201
242
|
return list(d.keys())
|
202
243
|
|
203
244
|
@classmethod
|
204
|
-
def from_csv(cls, file_path: str, name_field: Optional[str] = None):
|
245
|
+
def from_csv(cls, file_path: str, name_field: Optional[str] = None, codebook: Optional[dict[str, str]] = None):
|
205
246
|
"""Load AgentList from a CSV file.
|
206
247
|
|
207
248
|
>>> import csv
|
@@ -216,12 +257,16 @@ class AgentList(UserList, Base):
|
|
216
257
|
>>> al = AgentList.from_csv('/tmp/agents.csv', name_field='hair')
|
217
258
|
>>> al
|
218
259
|
AgentList([Agent(name = \"""brown\""", traits = {'age': '22', 'height': '5.5'})])
|
260
|
+
>>> al = AgentList.from_csv('/tmp/agents.csv', codebook={'age': 'Age in years'})
|
261
|
+
>>> al[0].codebook
|
262
|
+
{'age': 'Age in years'}
|
219
263
|
>>> os.remove('/tmp/agents.csv')
|
220
264
|
|
221
265
|
:param file_path: The path to the CSV file.
|
222
266
|
:param name_field: The name of the field to use as the agent name.
|
267
|
+
:param codebook: Optional dictionary mapping trait names to descriptions.
|
223
268
|
"""
|
224
|
-
from
|
269
|
+
from .agent import Agent
|
225
270
|
|
226
271
|
agent_list = []
|
227
272
|
with open(file_path, "r") as f:
|
@@ -234,9 +279,9 @@ class AgentList(UserList, Base):
|
|
234
279
|
name_field = "name"
|
235
280
|
if name_field is not None:
|
236
281
|
agent_name = row.pop(name_field)
|
237
|
-
agent_list.append(Agent(traits=row, name=agent_name))
|
282
|
+
agent_list.append(Agent(traits=row, name=agent_name, codebook=codebook))
|
238
283
|
else:
|
239
|
-
agent_list.append(Agent(traits=row))
|
284
|
+
agent_list.append(Agent(traits=row, codebook=codebook))
|
240
285
|
return cls(agent_list)
|
241
286
|
|
242
287
|
def translate_traits(self, codebook: dict[str, str]):
|
@@ -258,7 +303,7 @@ class AgentList(UserList, Base):
|
|
258
303
|
"""Remove traits from the AgentList.
|
259
304
|
|
260
305
|
:param traits: The traits to remove.
|
261
|
-
>>> from edsl
|
306
|
+
>>> from edsl import Agent
|
262
307
|
>>> al = AgentList([Agent({'age': 22, 'hair': 'brown', 'height': 5.5}), Agent({'age': 22, 'hair': 'brown', 'height': 5.5})])
|
263
308
|
>>> al.remove_trait('age')
|
264
309
|
AgentList([Agent(traits = {'hair': 'brown', 'height': 5.5}), Agent(traits = {'hair': 'brown', 'height': 5.5})])
|
@@ -282,7 +327,7 @@ class AgentList(UserList, Base):
|
|
282
327
|
>>> al.add_trait('new_trait', [1, 2, 3])
|
283
328
|
Traceback (most recent call last):
|
284
329
|
...
|
285
|
-
edsl.exceptions.
|
330
|
+
edsl.agents.exceptions.AgentListError: The passed values have to be the same length as the agent list.
|
286
331
|
...
|
287
332
|
"""
|
288
333
|
if not is_iterable(values):
|
@@ -322,8 +367,6 @@ class AgentList(UserList, Base):
|
|
322
367
|
>>> hash(al)
|
323
368
|
1681154913465662422
|
324
369
|
"""
|
325
|
-
from edsl.utilities.utilities import dict_hash
|
326
|
-
|
327
370
|
return dict_hash(self.to_dict(add_edsl_version=False, sorted=True))
|
328
371
|
|
329
372
|
def to_dict(self, sorted=False, add_edsl_version=True):
|
@@ -331,7 +374,13 @@ class AgentList(UserList, Base):
|
|
331
374
|
|
332
375
|
>>> AgentList.example().to_dict(add_edsl_version=False)
|
333
376
|
{'agent_list': [{'traits': {'age': 22, 'hair': 'brown', 'height': 5.5}}, {'traits': {'age': 22, 'hair': 'brown', 'height': 5.5}}]}
|
334
|
-
|
377
|
+
>>> example_codebook = {'age': 'Age in years'}
|
378
|
+
>>> al = AgentList.example().set_codebook(example_codebook)
|
379
|
+
>>> result = al.to_dict(add_edsl_version=False)
|
380
|
+
>>> 'codebook' in result
|
381
|
+
True
|
382
|
+
>>> result['codebook'] == example_codebook
|
383
|
+
True
|
335
384
|
"""
|
336
385
|
if sorted:
|
337
386
|
data = self.data[:]
|
@@ -344,6 +393,19 @@ class AgentList(UserList, Base):
|
|
344
393
|
agent.to_dict(add_edsl_version=add_edsl_version) for agent in data
|
345
394
|
]
|
346
395
|
}
|
396
|
+
|
397
|
+
# Add codebook if all agents have the same codebook
|
398
|
+
if len(self.data) > 0:
|
399
|
+
# Get the first agent's codebook
|
400
|
+
first_codebook = self.data[0].codebook
|
401
|
+
|
402
|
+
# Check if all agents have the same codebook
|
403
|
+
all_same = all(agent.codebook == first_codebook for agent in self.data)
|
404
|
+
|
405
|
+
# Only include codebook if it's non-empty and consistent across all agents
|
406
|
+
if all_same and first_codebook:
|
407
|
+
d["codebook"] = first_codebook
|
408
|
+
|
347
409
|
if add_edsl_version:
|
348
410
|
from edsl import __version__
|
349
411
|
|
@@ -360,15 +422,15 @@ class AgentList(UserList, Base):
|
|
360
422
|
def __repr__(self):
|
361
423
|
return f"AgentList({self.data})"
|
362
424
|
|
363
|
-
def _summary(self):
|
425
|
+
def _summary(self) -> dict:
|
364
426
|
return {
|
365
427
|
"agents": len(self),
|
366
428
|
}
|
367
|
-
|
429
|
+
|
368
430
|
def set_codebook(self, codebook: dict[str, str]) -> AgentList:
|
369
431
|
"""Set the codebook for the AgentList.
|
370
432
|
|
371
|
-
>>> from edsl
|
433
|
+
>>> from edsl import Agent
|
372
434
|
>>> a = Agent(traits = {'hair': 'brown'})
|
373
435
|
>>> al = AgentList([a, a])
|
374
436
|
>>> _ = al.set_codebook({'hair': "Color of hair on driver's license"})
|
@@ -383,51 +445,13 @@ class AgentList(UserList, Base):
|
|
383
445
|
|
384
446
|
return self
|
385
447
|
|
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
448
|
|
425
449
|
def table(
|
426
450
|
self,
|
427
451
|
*fields,
|
428
452
|
tablefmt: Optional[str] = None,
|
429
453
|
pretty_labels: Optional[dict] = None,
|
430
|
-
) -> Table:
|
454
|
+
) -> "Table":
|
431
455
|
if len(self) == 0:
|
432
456
|
e = AgentListError("Cannot create a table from an empty AgentList.")
|
433
457
|
if is_notebook():
|
@@ -442,18 +466,24 @@ class AgentList(UserList, Base):
|
|
442
466
|
)
|
443
467
|
|
444
468
|
def to_dataset(self, traits_only: bool = True):
|
469
|
+
"""Convert the AgentList to a Dataset.
|
470
|
+
|
471
|
+
Args:
|
472
|
+
traits_only: If True, only include agent traits. If False, also include
|
473
|
+
agent parameters like instructions and names.
|
474
|
+
|
475
|
+
Returns:
|
476
|
+
Dataset: A dataset containing the agents' traits and optionally their parameters.
|
477
|
+
|
478
|
+
Examples:
|
479
|
+
>>> from edsl import AgentList
|
480
|
+
>>> al = AgentList.example()
|
481
|
+
>>> al.to_dataset()
|
482
|
+
Dataset([{'age': [22, 22]}, {'hair': ['brown', 'brown']}, {'height': [5.5, 5.5]}])
|
483
|
+
>>> al.to_dataset(traits_only=False) # doctest: +NORMALIZE_WHITESPACE
|
484
|
+
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}]}])
|
445
485
|
"""
|
446
|
-
|
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
|
486
|
+
from ..dataset import Dataset
|
457
487
|
|
458
488
|
agent_trait_keys = []
|
459
489
|
for agent in self:
|
@@ -472,55 +502,84 @@ class AgentList(UserList, Base):
|
|
472
502
|
)
|
473
503
|
return Dataset([{key: entry} for key, entry in data.items()])
|
474
504
|
|
475
|
-
def tree(self, node_order: Optional[List[str]] = None):
|
476
|
-
return self.to_scenario_list().tree(node_order)
|
477
|
-
|
478
505
|
@classmethod
|
479
506
|
@remove_edsl_version
|
480
507
|
def from_dict(cls, data: dict) -> "AgentList":
|
481
508
|
"""Deserialize the dictionary back to an AgentList object.
|
482
509
|
|
483
510
|
:param: data: A dictionary representing an AgentList.
|
484
|
-
|
511
|
+
|
512
|
+
>>> from edsl import Agent
|
485
513
|
>>> al = AgentList([Agent.example(), Agent.example()])
|
486
514
|
>>> al2 = AgentList.from_dict(al.to_dict())
|
487
515
|
>>> al2 == al
|
488
516
|
True
|
517
|
+
>>> example_codebook = {'age': 'Age in years'}
|
518
|
+
>>> al = AgentList([Agent.example()]).set_codebook(example_codebook)
|
519
|
+
>>> al2 = AgentList.from_dict(al.to_dict())
|
520
|
+
>>> al2[0].codebook == example_codebook
|
521
|
+
True
|
489
522
|
"""
|
490
|
-
from
|
523
|
+
from .agent import Agent
|
491
524
|
|
492
525
|
agents = [Agent.from_dict(agent_dict) for agent_dict in data["agent_list"]]
|
493
|
-
|
526
|
+
agent_list = cls(agents)
|
527
|
+
|
528
|
+
# Apply codebook if present in the dictionary
|
529
|
+
if "codebook" in data and data["codebook"]:
|
530
|
+
agent_list.set_codebook(data["codebook"])
|
531
|
+
|
532
|
+
return agent_list
|
494
533
|
|
495
534
|
@classmethod
|
496
|
-
def example(cls, randomize: bool = False) -> AgentList:
|
535
|
+
def example(cls, randomize: bool = False, codebook: Optional[dict[str, str]] = None) -> AgentList:
|
497
536
|
"""
|
498
537
|
Returns an example AgentList instance.
|
499
538
|
|
500
539
|
:param randomize: If True, uses Agent's randomize method.
|
540
|
+
:param codebook: Optional dictionary mapping trait names to descriptions.
|
541
|
+
|
542
|
+
>>> al = AgentList.example()
|
543
|
+
>>> al
|
544
|
+
AgentList([Agent(traits = {'age': 22, 'hair': 'brown', 'height': 5.5}), Agent(traits = {'age': 22, 'hair': 'brown', 'height': 5.5})])
|
545
|
+
>>> al = AgentList.example(codebook={'age': 'Age in years'})
|
546
|
+
>>> al[0].codebook
|
547
|
+
{'age': 'Age in years'}
|
501
548
|
"""
|
502
|
-
from
|
549
|
+
from .agent import Agent
|
503
550
|
|
504
|
-
|
551
|
+
agent_list = cls([Agent.example(randomize), Agent.example(randomize)])
|
552
|
+
|
553
|
+
if codebook:
|
554
|
+
agent_list.set_codebook(codebook)
|
555
|
+
|
556
|
+
return agent_list
|
505
557
|
|
506
558
|
@classmethod
|
507
|
-
def from_list(self, trait_name: str, values: List[Any]):
|
559
|
+
def from_list(self, trait_name: str, values: List[Any], codebook: Optional[dict[str, str]] = None) -> "AgentList":
|
508
560
|
"""Create an AgentList from a list of values.
|
509
561
|
|
510
562
|
:param trait_name: The name of the trait.
|
511
563
|
:param values: A list of values.
|
564
|
+
:param codebook: Optional dictionary mapping trait names to descriptions.
|
512
565
|
|
513
566
|
>>> AgentList.from_list('age', [22, 23])
|
514
567
|
AgentList([Agent(traits = {'age': 22}), Agent(traits = {'age': 23})])
|
568
|
+
>>> al = AgentList.from_list('age', [22], codebook={'age': 'Age in years'})
|
569
|
+
>>> al[0].codebook
|
570
|
+
{'age': 'Age in years'}
|
515
571
|
"""
|
516
|
-
from
|
572
|
+
from .agent import Agent
|
517
573
|
|
518
|
-
|
574
|
+
agent_list = AgentList([Agent({trait_name: value}) for value in values])
|
575
|
+
|
576
|
+
if codebook:
|
577
|
+
agent_list.set_codebook(codebook)
|
578
|
+
|
579
|
+
return agent_list
|
519
580
|
|
520
581
|
def __mul__(self, other: AgentList) -> AgentList:
|
521
582
|
"""Takes the cross product of two AgentLists."""
|
522
|
-
from itertools import product
|
523
|
-
|
524
583
|
new_sl = []
|
525
584
|
for s1, s2 in list(product(self, other)):
|
526
585
|
new_sl.append(s1 + s2)
|
@@ -531,13 +590,13 @@ class AgentList(UserList, Base):
|
|
531
590
|
|
532
591
|
>>> al = AgentList.example()
|
533
592
|
>>> print(al.code())
|
534
|
-
from edsl
|
535
|
-
from edsl
|
593
|
+
from edsl import Agent
|
594
|
+
from edsl import AgentList
|
536
595
|
agent_list = AgentList([Agent(traits = {'age': 22, 'hair': 'brown', 'height': 5.5}), Agent(traits = {'age': 22, 'hair': 'brown', 'height': 5.5})])
|
537
596
|
"""
|
538
597
|
lines = [
|
539
|
-
"from edsl
|
540
|
-
"from edsl
|
598
|
+
"from edsl import Agent",
|
599
|
+
"from edsl import AgentList",
|
541
600
|
]
|
542
601
|
lines.append(f"agent_list = AgentList({self.data})")
|
543
602
|
if string:
|
@@ -547,5 +606,4 @@ class AgentList(UserList, Base):
|
|
547
606
|
|
548
607
|
if __name__ == "__main__":
|
549
608
|
import doctest
|
550
|
-
|
551
|
-
doctest.testmod(optionflags=doctest.ELLIPSIS)
|
609
|
+
doctest.testmod(optionflags=doctest.ELLIPSIS | doctest.NORMALIZE_WHITESPACE)
|