edsl 0.1.47__py3-none-any.whl → 0.1.49__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 +311 -75
- 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.49.dist-info}/METADATA +1 -1
- edsl-0.1.49.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.49.dist-info}/LICENSE +0 -0
- {edsl-0.1.47.dist-info → edsl-0.1.49.dist-info}/WHEEL +0 -0
edsl/jobs/{Jobs.py → jobs.py}
RENAMED
@@ -1,7 +1,26 @@
|
|
1
|
-
|
1
|
+
"""
|
2
|
+
The Jobs module is the core orchestration component of the EDSL framework.
|
3
|
+
|
4
|
+
It provides functionality to define, configure, and execute computational jobs that
|
5
|
+
involve multiple agents, scenarios, models, and a survey. Jobs are the primary way
|
6
|
+
that users run large-scale experiments or simulations in EDSL.
|
7
|
+
|
8
|
+
The Jobs class handles:
|
9
|
+
1. Organizing all components (agents, scenarios, models, survey)
|
10
|
+
2. Configuring execution parameters
|
11
|
+
3. Managing resources like caches and API keys
|
12
|
+
4. Running interviews in parallel
|
13
|
+
5. Collecting and structuring results
|
14
|
+
|
15
|
+
This module is designed to be used by both application developers and researchers
|
16
|
+
who need to run complex simulations with language models.
|
17
|
+
"""
|
2
18
|
from __future__ import annotations
|
3
19
|
import asyncio
|
4
20
|
from inspect import signature
|
21
|
+
from typing import Optional, Union, TypeVar, Callable, cast
|
22
|
+
from functools import wraps
|
23
|
+
|
5
24
|
from typing import (
|
6
25
|
Literal,
|
7
26
|
Optional,
|
@@ -13,38 +32,36 @@ from typing import (
|
|
13
32
|
Tuple,
|
14
33
|
)
|
15
34
|
|
16
|
-
from
|
35
|
+
from ..base import Base
|
36
|
+
from ..utilities import remove_edsl_version
|
37
|
+
from ..coop import CoopServerResponseError
|
17
38
|
|
18
|
-
from
|
19
|
-
from
|
20
|
-
from
|
21
|
-
from
|
22
|
-
|
23
|
-
from
|
24
|
-
from
|
39
|
+
from ..buckets import BucketCollection
|
40
|
+
from ..scenarios import Scenario, ScenarioList
|
41
|
+
from ..surveys import Survey
|
42
|
+
from ..interviews import Interview
|
43
|
+
|
44
|
+
from .jobs_pricing_estimation import JobsPrompts
|
45
|
+
from .remote_inference import JobsRemoteInferenceHandler
|
46
|
+
from .jobs_checks import JobsChecks
|
47
|
+
from .data_structures import RunEnvironment, RunParameters, RunConfig
|
48
|
+
from .check_survey_scenario_compatibility import CheckSurveyScenarioCompatibility
|
25
49
|
|
26
|
-
from edsl.jobs.JobsChecks import JobsChecks
|
27
|
-
from edsl.jobs.data_structures import RunEnvironment, RunParameters, RunConfig
|
28
50
|
|
29
51
|
if TYPE_CHECKING:
|
30
|
-
from
|
31
|
-
from
|
32
|
-
from
|
33
|
-
from
|
34
|
-
from
|
35
|
-
from
|
36
|
-
from
|
37
|
-
from
|
38
|
-
from
|
39
|
-
from
|
40
|
-
from edsl.language_models.key_management.KeyLookup import KeyLookup
|
41
|
-
from edsl.jobs.JobsRemoteInferenceHandler import JobsRemoteInferenceHandler
|
52
|
+
from ..agents import Agent
|
53
|
+
from ..agents import AgentList
|
54
|
+
from ..language_models import LanguageModel
|
55
|
+
from ..scenarios import Scenario, ScenarioList
|
56
|
+
from ..surveys import Survey
|
57
|
+
from ..results import Results
|
58
|
+
from ..dataset import Dataset
|
59
|
+
from ..language_models import ModelList
|
60
|
+
from ..caching import Cache
|
61
|
+
from ..key_management import KeyLookup
|
42
62
|
|
43
63
|
VisibilityType = Literal["private", "public", "unlisted"]
|
44
64
|
|
45
|
-
from dataclasses import dataclass
|
46
|
-
from typing import Optional, Union, TypeVar, Callable, cast
|
47
|
-
from functools import wraps
|
48
65
|
|
49
66
|
try:
|
50
67
|
from typing import ParamSpec
|
@@ -56,13 +73,32 @@ P = ParamSpec("P")
|
|
56
73
|
T = TypeVar("T")
|
57
74
|
|
58
75
|
|
59
|
-
from edsl.jobs.check_survey_scenario_compatibility import (
|
60
|
-
CheckSurveyScenarioCompatibility,
|
61
|
-
)
|
62
76
|
|
63
77
|
|
64
78
|
def with_config(f: Callable[P, T]) -> Callable[P, T]:
|
65
|
-
"
|
79
|
+
"""
|
80
|
+
Decorator that processes function parameters to match the RunConfig dataclass structure.
|
81
|
+
|
82
|
+
This decorator is used primarily with the run() and run_async() methods to provide
|
83
|
+
a consistent interface for job configuration while maintaining a clean API.
|
84
|
+
|
85
|
+
The decorator:
|
86
|
+
1. Extracts environment-related parameters into a RunEnvironment instance
|
87
|
+
2. Extracts execution-related parameters into a RunParameters instance
|
88
|
+
3. Combines both into a single RunConfig object
|
89
|
+
4. Passes this RunConfig to the decorated function as a keyword argument
|
90
|
+
|
91
|
+
Parameters:
|
92
|
+
f (Callable): The function to decorate, typically run() or run_async()
|
93
|
+
|
94
|
+
Returns:
|
95
|
+
Callable: A wrapped function that accepts all RunConfig parameters directly
|
96
|
+
|
97
|
+
Example:
|
98
|
+
@with_config
|
99
|
+
def run(self, *, config: RunConfig) -> Results:
|
100
|
+
# Function can now access config.parameters and config.environment
|
101
|
+
"""
|
66
102
|
parameter_fields = {
|
67
103
|
name: field.default
|
68
104
|
for name, field in RunParameters.__dataclass_fields__.items()
|
@@ -84,24 +120,33 @@ def with_config(f: Callable[P, T]) -> Callable[P, T]:
|
|
84
120
|
config = RunConfig(environment=environment, parameters=parameters)
|
85
121
|
return f(*args, config=config)
|
86
122
|
|
87
|
-
# Update the wrapper's signature to include all RunConfig parameters
|
88
|
-
# old_sig = signature(f)
|
89
|
-
# wrapper.__signature__ = old_sig.replace(
|
90
|
-
# parameters=list(old_sig.parameters.values())[:-1]
|
91
|
-
# + [
|
92
|
-
# old_sig.parameters["config"].replace(
|
93
|
-
# default=parameter_fields[name], name=name
|
94
|
-
# )
|
95
|
-
# for name in combined
|
96
|
-
# ]
|
97
|
-
# )
|
98
|
-
|
99
123
|
return cast(Callable[P, T], wrapper)
|
100
124
|
|
101
125
|
|
102
126
|
class Jobs(Base):
|
103
127
|
"""
|
104
|
-
A collection of agents, scenarios
|
128
|
+
A collection of agents, scenarios, models, and a survey that orchestrates interviews.
|
129
|
+
|
130
|
+
The Jobs class is the central component for running large-scale experiments or simulations
|
131
|
+
in EDSL. It manages the execution of interviews where agents interact with surveys through
|
132
|
+
language models, possibly in different scenarios.
|
133
|
+
|
134
|
+
Key responsibilities:
|
135
|
+
1. Managing collections of agents, scenarios, and models
|
136
|
+
2. Configuring execution parameters (caching, API keys, etc.)
|
137
|
+
3. Managing parallel execution of interviews
|
138
|
+
4. Handling remote cache and inference capabilities
|
139
|
+
5. Collecting and organizing results
|
140
|
+
|
141
|
+
A typical workflow involves:
|
142
|
+
1. Creating a survey with questions
|
143
|
+
2. Creating a Jobs instance with that survey
|
144
|
+
3. Adding agents, scenarios, and models using the `by()` method
|
145
|
+
4. Running the job with `run()` or `run_async()`
|
146
|
+
5. Analyzing the results
|
147
|
+
|
148
|
+
Jobs implements a fluent interface pattern, where methods return self to allow
|
149
|
+
method chaining for concise, readable configuration.
|
105
150
|
"""
|
106
151
|
|
107
152
|
__documentation__ = "https://docs.expectedparrot.com/en/latest/jobs.html"
|
@@ -109,29 +154,44 @@ class Jobs(Base):
|
|
109
154
|
def __init__(
|
110
155
|
self,
|
111
156
|
survey: "Survey",
|
112
|
-
agents: Optional[Union[list[Agent], AgentList]] = None,
|
113
|
-
models: Optional[Union[ModelList, list[LanguageModel]]] = None,
|
114
|
-
scenarios: Optional[Union[ScenarioList, list[Scenario]]] = None,
|
157
|
+
agents: Optional[Union[list["Agent"], "AgentList"]] = None,
|
158
|
+
models: Optional[Union["ModelList", list["LanguageModel"]]] = None,
|
159
|
+
scenarios: Optional[Union["ScenarioList", list["Scenario"]]] = None,
|
115
160
|
):
|
116
|
-
"""Initialize a Jobs instance.
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
161
|
+
"""Initialize a Jobs instance with a survey and optional components.
|
162
|
+
|
163
|
+
The Jobs constructor requires a survey and optionally accepts collections of
|
164
|
+
agents, models, and scenarios. If any of these optional components are not provided,
|
165
|
+
they can be added later using the `by()` method or will be automatically populated
|
166
|
+
with defaults when the job is run.
|
167
|
+
|
168
|
+
Parameters:
|
169
|
+
survey (Survey): The survey containing questions to be used in the job
|
170
|
+
agents (Union[list[Agent], AgentList], optional): The agents that will take the survey
|
171
|
+
models (Union[ModelList, list[LanguageModel]], optional): The language models to use
|
172
|
+
scenarios (Union[ScenarioList, list[Scenario]], optional): The scenarios to run
|
173
|
+
|
174
|
+
Raises:
|
175
|
+
ValueError: If the survey contains questions with invalid names
|
176
|
+
(e.g., names containing template variables)
|
177
|
+
|
178
|
+
Examples:
|
179
|
+
>>> from edsl.surveys import Survey
|
180
|
+
>>> from edsl.questions import QuestionFreeText
|
181
|
+
>>> q = QuestionFreeText(question_name="name", question_text="What is your name?")
|
182
|
+
>>> s = Survey(questions=[q])
|
183
|
+
>>> j = Jobs(survey = s)
|
184
|
+
>>> q = QuestionFreeText(question_name="{{ bad_name }}", question_text="What is your name?")
|
185
|
+
>>> s = Survey(questions=[q])
|
186
|
+
>>> j = Jobs(survey = s)
|
187
|
+
Traceback (most recent call last):
|
188
|
+
...
|
189
|
+
ValueError: At least some question names are not valid: ['{{ bad_name }}']
|
190
|
+
|
191
|
+
Notes:
|
192
|
+
- The survey's questions must have valid names without templating variables
|
193
|
+
- If agents, models, or scenarios are not provided, defaults will be used when running
|
194
|
+
- Upon initialization, a RunConfig is created with default environment and parameters
|
135
195
|
"""
|
136
196
|
self.run_config = RunConfig(
|
137
197
|
environment=RunEnvironment(), parameters=RunParameters()
|
@@ -142,6 +202,8 @@ class Jobs(Base):
|
|
142
202
|
self.scenarios: ScenarioList = scenarios
|
143
203
|
self.models: ModelList = models
|
144
204
|
|
205
|
+
self._where_clauses = []
|
206
|
+
|
145
207
|
try:
|
146
208
|
assert self.survey.question_names_valid()
|
147
209
|
except Exception as e:
|
@@ -162,7 +224,7 @@ class Jobs(Base):
|
|
162
224
|
self.run_config.add_cache(cache)
|
163
225
|
return self
|
164
226
|
|
165
|
-
def using_bucket_collection(self, bucket_collection: BucketCollection) -> Jobs:
|
227
|
+
def using_bucket_collection(self, bucket_collection: 'BucketCollection') -> Jobs:
|
166
228
|
"""
|
167
229
|
Add a BucketCollection to the job.
|
168
230
|
|
@@ -171,7 +233,7 @@ class Jobs(Base):
|
|
171
233
|
self.run_config.add_bucket_collection(bucket_collection)
|
172
234
|
return self
|
173
235
|
|
174
|
-
def using_key_lookup(self, key_lookup: KeyLookup) -> Jobs:
|
236
|
+
def using_key_lookup(self, key_lookup: 'KeyLookup') -> Jobs:
|
175
237
|
"""
|
176
238
|
Add a KeyLookup to the job.
|
177
239
|
|
@@ -186,8 +248,8 @@ class Jobs(Base):
|
|
186
248
|
|
187
249
|
:param obj: the object to add
|
188
250
|
"""
|
189
|
-
from
|
190
|
-
from
|
251
|
+
from ..caching import Cache
|
252
|
+
from ..key_management import KeyLookup
|
191
253
|
|
192
254
|
if isinstance(obj, Cache):
|
193
255
|
self.using_cache(obj)
|
@@ -203,7 +265,7 @@ class Jobs(Base):
|
|
203
265
|
|
204
266
|
@models.setter
|
205
267
|
def models(self, value):
|
206
|
-
from
|
268
|
+
from ..language_models import ModelList
|
207
269
|
|
208
270
|
if value:
|
209
271
|
if not isinstance(value, ModelList):
|
@@ -225,7 +287,7 @@ class Jobs(Base):
|
|
225
287
|
|
226
288
|
@agents.setter
|
227
289
|
def agents(self, value):
|
228
|
-
from
|
290
|
+
from ..agents import AgentList
|
229
291
|
|
230
292
|
if value:
|
231
293
|
if not isinstance(value, AgentList):
|
@@ -235,14 +297,23 @@ class Jobs(Base):
|
|
235
297
|
else:
|
236
298
|
self._agents = AgentList([])
|
237
299
|
|
300
|
+
def where(self, expression: str) -> Jobs:
|
301
|
+
"""
|
302
|
+
Filter the agents, scenarios, and models based on a condition.
|
303
|
+
|
304
|
+
:param expression: a condition to filter the agents, scenarios, and models
|
305
|
+
"""
|
306
|
+
self._where_clauses.append(expression)
|
307
|
+
return self
|
308
|
+
|
238
309
|
@property
|
239
310
|
def scenarios(self):
|
240
311
|
return self._scenarios
|
241
312
|
|
242
313
|
@scenarios.setter
|
243
314
|
def scenarios(self, value):
|
244
|
-
from
|
245
|
-
from
|
315
|
+
from ..scenarios import ScenarioList
|
316
|
+
from ..dataset import Dataset
|
246
317
|
|
247
318
|
if value:
|
248
319
|
if isinstance(
|
@@ -260,40 +331,58 @@ class Jobs(Base):
|
|
260
331
|
def by(
|
261
332
|
self,
|
262
333
|
*args: Union[
|
263
|
-
Agent,
|
264
|
-
Scenario,
|
265
|
-
LanguageModel,
|
334
|
+
"Agent",
|
335
|
+
"Scenario",
|
336
|
+
"LanguageModel",
|
266
337
|
Sequence[Union["Agent", "Scenario", "LanguageModel"]],
|
267
338
|
],
|
268
|
-
) -> Jobs:
|
339
|
+
) -> "Jobs":
|
269
340
|
"""
|
270
|
-
Add
|
271
|
-
|
272
|
-
|
273
|
-
|
274
|
-
|
275
|
-
|
276
|
-
|
277
|
-
|
278
|
-
|
279
|
-
|
280
|
-
|
281
|
-
|
282
|
-
|
283
|
-
|
284
|
-
|
285
|
-
|
286
|
-
|
287
|
-
|
288
|
-
|
289
|
-
|
341
|
+
Add agents, scenarios, and language models to a job using a fluent interface.
|
342
|
+
|
343
|
+
This method is the primary way to configure a Jobs instance with components.
|
344
|
+
It intelligently handles different types of objects and collections, making
|
345
|
+
it easy to build complex job configurations with a concise syntax.
|
346
|
+
|
347
|
+
Parameters:
|
348
|
+
*args: Objects or sequences of objects to add to the job.
|
349
|
+
Supported types are Agent, Scenario, LanguageModel, and sequences of these.
|
350
|
+
|
351
|
+
Returns:
|
352
|
+
Jobs: The Jobs instance (self) for method chaining
|
353
|
+
|
354
|
+
Examples:
|
355
|
+
>>> from edsl.surveys import Survey
|
356
|
+
>>> from edsl.questions import QuestionFreeText
|
357
|
+
>>> q = QuestionFreeText(question_name="name", question_text="What is your name?")
|
358
|
+
>>> j = Jobs(survey = Survey(questions=[q]))
|
359
|
+
>>> j
|
360
|
+
Jobs(survey=Survey(...), agents=AgentList([]), models=ModelList([]), scenarios=ScenarioList([]))
|
361
|
+
>>> from edsl.agents import Agent; a = Agent(traits = {"status": "Sad"})
|
362
|
+
>>> j.by(a).agents
|
363
|
+
AgentList([Agent(traits = {'status': 'Sad'})])
|
364
|
+
|
365
|
+
# Adding multiple components at once
|
366
|
+
>>> from edsl.language_models import Model
|
367
|
+
>>> from edsl.scenarios import Scenario
|
368
|
+
>>> j = Jobs.example()
|
369
|
+
>>> _ = j.by(Agent(traits={"mood": "happy"})).by(Model(temperature=0.7)).by(Scenario({"time": "morning"}))
|
370
|
+
|
371
|
+
# Adding a sequence of the same type
|
372
|
+
>>> agents = [Agent(traits={"age": i}) for i in range(5)]
|
373
|
+
>>> _ = j.by(agents)
|
374
|
+
|
290
375
|
Notes:
|
291
|
-
|
292
|
-
|
293
|
-
|
294
|
-
|
376
|
+
- All objects must implement 'get_value', 'set_value', and '__add__' methods
|
377
|
+
- Agent traits: When adding agents with traits to existing agents, the traits are
|
378
|
+
combined. Avoid overlapping trait names to prevent unexpected behavior.
|
379
|
+
- Scenario traits: When adding scenarios with traits to existing scenarios, new
|
380
|
+
traits overwrite existing ones with the same name.
|
381
|
+
- Models: New models with the same attributes will override existing models.
|
382
|
+
- The method detects object types automatically and routes them to the appropriate
|
383
|
+
collection (agents, scenarios, or models).
|
295
384
|
"""
|
296
|
-
from
|
385
|
+
from .jobs_component_constructor import JobsComponentConstructor
|
297
386
|
|
298
387
|
return JobsComponentConstructor(self).by(*args)
|
299
388
|
|
@@ -305,7 +394,7 @@ class Jobs(Base):
|
|
305
394
|
>>> Jobs.example().prompts()
|
306
395
|
Dataset(...)
|
307
396
|
"""
|
308
|
-
return JobsPrompts(self).prompts(iterations=iterations)
|
397
|
+
return JobsPrompts.from_jobs(self).prompts(iterations=iterations)
|
309
398
|
|
310
399
|
def show_prompts(self, all: bool = False) -> None:
|
311
400
|
"""Print the prompts."""
|
@@ -348,7 +437,7 @@ class Jobs(Base):
|
|
348
437
|
def estimate_job_cost_from_external_prices(
|
349
438
|
self, price_lookup: dict, iterations: int = 1
|
350
439
|
) -> dict:
|
351
|
-
return JobsPrompts(self).estimate_job_cost_from_external_prices(
|
440
|
+
return JobsPrompts.from_jobs(self).estimate_job_cost_from_external_prices(
|
352
441
|
price_lookup, iterations
|
353
442
|
)
|
354
443
|
|
@@ -360,9 +449,9 @@ class Jobs(Base):
|
|
360
449
|
return job_results.compute_job_cost()
|
361
450
|
|
362
451
|
def replace_missing_objects(self) -> None:
|
363
|
-
from
|
364
|
-
from
|
365
|
-
from
|
452
|
+
from ..agents import Agent
|
453
|
+
from ..language_models.model import Model
|
454
|
+
from ..scenarios import Scenario
|
366
455
|
|
367
456
|
self.agents = self.agents or [Agent()]
|
368
457
|
self.models = self.models or [Model()]
|
@@ -377,7 +466,7 @@ class Jobs(Base):
|
|
377
466
|
with us filling in defaults.
|
378
467
|
|
379
468
|
"""
|
380
|
-
from
|
469
|
+
from .jobs_interview_constructor import InterviewsConstructor
|
381
470
|
|
382
471
|
self.replace_missing_objects()
|
383
472
|
yield from InterviewsConstructor(
|
@@ -385,8 +474,12 @@ class Jobs(Base):
|
|
385
474
|
).create_interviews()
|
386
475
|
|
387
476
|
def show_flow(self, filename: Optional[str] = None) -> None:
|
388
|
-
"""Show the flow of the survey.
|
389
|
-
|
477
|
+
"""Show the flow of the survey.
|
478
|
+
|
479
|
+
>>> from edsl.jobs import Jobs
|
480
|
+
>>> Jobs.example().show_flow()
|
481
|
+
"""
|
482
|
+
from ..surveys import SurveyFlowVisualization
|
390
483
|
if self.scenarios:
|
391
484
|
scenario = self.scenarios[0]
|
392
485
|
else:
|
@@ -462,7 +555,7 @@ class Jobs(Base):
|
|
462
555
|
846655441787442972
|
463
556
|
|
464
557
|
"""
|
465
|
-
from
|
558
|
+
from ..utilities import dict_hash
|
466
559
|
|
467
560
|
return dict_hash(self.to_dict(add_edsl_version=False))
|
468
561
|
|
@@ -470,8 +563,6 @@ class Jobs(Base):
|
|
470
563
|
"""Check if a Job is verbose. If so, print the message."""
|
471
564
|
if self.run_config.parameters.verbose:
|
472
565
|
print(message)
|
473
|
-
# if hasattr(self, "verbose") and self.verbose:
|
474
|
-
# print(message)
|
475
566
|
|
476
567
|
def all_question_parameters(self) -> set:
|
477
568
|
"""Return all the fields in the questions in the survey.
|
@@ -488,7 +579,7 @@ class Jobs(Base):
|
|
488
579
|
return False
|
489
580
|
if not self.run_config.parameters.disable_remote_cache:
|
490
581
|
try:
|
491
|
-
from
|
582
|
+
from ..coop import Coop
|
492
583
|
|
493
584
|
user_edsl_settings = Coop().edsl_settings
|
494
585
|
return user_edsl_settings.get("remote_caching", False)
|
@@ -513,9 +604,7 @@ class Jobs(Base):
|
|
513
604
|
)
|
514
605
|
return job_info
|
515
606
|
|
516
|
-
def _create_remote_inference_handler(self) -> JobsRemoteInferenceHandler:
|
517
|
-
from edsl.jobs.JobsRemoteInferenceHandler import JobsRemoteInferenceHandler
|
518
|
-
|
607
|
+
def _create_remote_inference_handler(self) -> 'JobsRemoteInferenceHandler':
|
519
608
|
return JobsRemoteInferenceHandler(
|
520
609
|
self, verbose=self.run_config.parameters.verbose
|
521
610
|
)
|
@@ -524,8 +613,7 @@ class Jobs(Base):
|
|
524
613
|
self,
|
525
614
|
config: RunConfig,
|
526
615
|
) -> Union["Results", None]:
|
527
|
-
from
|
528
|
-
from edsl.jobs.JobsRemoteInferenceHandler import RemoteJobInfo
|
616
|
+
from .remote_inference import RemoteJobInfo
|
529
617
|
|
530
618
|
background = config.parameters.background
|
531
619
|
|
@@ -533,7 +621,7 @@ class Jobs(Base):
|
|
533
621
|
if jh.use_remote_inference(self.run_config.parameters.disable_remote_inference):
|
534
622
|
job_info: RemoteJobInfo = self._start_remote_inference_job(jh)
|
535
623
|
if background:
|
536
|
-
from edsl.results
|
624
|
+
from edsl.results import Results
|
537
625
|
|
538
626
|
results = Results.from_job_info(job_info)
|
539
627
|
return results
|
@@ -560,9 +648,9 @@ class Jobs(Base):
|
|
560
648
|
async def _execute_with_remote_cache(self, run_job_async: bool) -> Results:
|
561
649
|
use_remote_cache = self.use_remote_cache()
|
562
650
|
|
563
|
-
from
|
564
|
-
from
|
565
|
-
from
|
651
|
+
from ..coop import Coop
|
652
|
+
from .jobs_runner_asyncio import JobsRunnerAsyncio
|
653
|
+
from ..caching import Cache
|
566
654
|
|
567
655
|
assert isinstance(self.run_config.environment.cache, Cache)
|
568
656
|
|
@@ -609,12 +697,12 @@ class Jobs(Base):
|
|
609
697
|
self.run_config.environment.cache is None
|
610
698
|
or self.run_config.environment.cache is True
|
611
699
|
):
|
612
|
-
from
|
700
|
+
from ..caching import CacheHandler
|
613
701
|
|
614
702
|
self.run_config.environment.cache = CacheHandler().get_cache()
|
615
703
|
|
616
704
|
if self.run_config.environment.cache is False:
|
617
|
-
from
|
705
|
+
from ..caching import Cache
|
618
706
|
|
619
707
|
self.run_config.environment.cache = Cache(immediate_write=False)
|
620
708
|
|
@@ -642,21 +730,50 @@ class Jobs(Base):
|
|
642
730
|
@with_config
|
643
731
|
def run(self, *, config: RunConfig) -> "Results":
|
644
732
|
"""
|
645
|
-
Runs the
|
646
|
-
|
647
|
-
|
648
|
-
|
649
|
-
|
650
|
-
|
651
|
-
:
|
652
|
-
|
653
|
-
|
654
|
-
|
655
|
-
|
656
|
-
|
657
|
-
|
658
|
-
|
659
|
-
|
733
|
+
Runs the job by conducting interviews and returns their results.
|
734
|
+
|
735
|
+
This is the main entry point for executing a job. It processes all interviews
|
736
|
+
(combinations of agents, scenarios, and models) and returns a Results object
|
737
|
+
containing all responses and metadata.
|
738
|
+
|
739
|
+
Parameters:
|
740
|
+
n (int): Number of iterations to run each interview (default: 1)
|
741
|
+
progress_bar (bool): Whether to show a progress bar (default: False)
|
742
|
+
stop_on_exception (bool): Whether to stop the job if an exception is raised (default: False)
|
743
|
+
check_api_keys (bool): Whether to verify API keys before running (default: False)
|
744
|
+
verbose (bool): Whether to print extra messages during execution (default: True)
|
745
|
+
print_exceptions (bool): Whether to print exceptions as they occur (default: True)
|
746
|
+
remote_cache_description (str, optional): Description for entries in the remote cache
|
747
|
+
remote_inference_description (str, optional): Description for the remote inference job
|
748
|
+
remote_inference_results_visibility (VisibilityType): Visibility of results on Coop ("private", "public", "unlisted")
|
749
|
+
disable_remote_cache (bool): Whether to disable the remote cache (default: False)
|
750
|
+
disable_remote_inference (bool): Whether to disable remote inference (default: False)
|
751
|
+
fresh (bool): Whether to ignore cache and force new results (default: False)
|
752
|
+
skip_retry (bool): Whether to skip retrying failed interviews (default: False)
|
753
|
+
raise_validation_errors (bool): Whether to raise validation errors (default: False)
|
754
|
+
background (bool): Whether to run in background mode (default: False)
|
755
|
+
job_uuid (str, optional): UUID for the job, used for tracking
|
756
|
+
cache (Cache, optional): Cache object to store results
|
757
|
+
bucket_collection (BucketCollection, optional): Object to track API calls
|
758
|
+
key_lookup (KeyLookup, optional): Object to manage API keys
|
759
|
+
|
760
|
+
Returns:
|
761
|
+
Results: A Results object containing all responses and metadata
|
762
|
+
|
763
|
+
Notes:
|
764
|
+
- This method will first try to use remote inference if available
|
765
|
+
- If remote inference is not available, it will run locally
|
766
|
+
- For long-running jobs, consider using progress_bar=True
|
767
|
+
- For maximum performance, ensure appropriate caching is configured
|
768
|
+
|
769
|
+
Example:
|
770
|
+
>>> from edsl.jobs import Jobs
|
771
|
+
>>> from edsl.caching import Cache
|
772
|
+
>>> job = Jobs.example()
|
773
|
+
>>> from edsl import Model
|
774
|
+
>>> m = Model('test')
|
775
|
+
>>> results = job.by(m).run(cache=Cache(), progress_bar=False, n=2, disable_remote_inference=True)
|
776
|
+
...
|
660
777
|
"""
|
661
778
|
potentially_completed_results = self._run(config)
|
662
779
|
|
@@ -668,21 +785,50 @@ class Jobs(Base):
|
|
668
785
|
@with_config
|
669
786
|
async def run_async(self, *, config: RunConfig) -> "Results":
|
670
787
|
"""
|
671
|
-
|
672
|
-
|
673
|
-
|
674
|
-
|
675
|
-
|
676
|
-
|
677
|
-
:
|
678
|
-
|
679
|
-
|
680
|
-
|
681
|
-
|
682
|
-
|
683
|
-
|
684
|
-
|
685
|
-
|
788
|
+
Asynchronously runs the job by conducting interviews and returns their results.
|
789
|
+
|
790
|
+
This method is the asynchronous version of `run()`. It has the same functionality and
|
791
|
+
parameters but can be awaited in an async context for better integration with
|
792
|
+
asynchronous code.
|
793
|
+
|
794
|
+
Parameters:
|
795
|
+
n (int): Number of iterations to run each interview (default: 1)
|
796
|
+
progress_bar (bool): Whether to show a progress bar (default: False)
|
797
|
+
stop_on_exception (bool): Whether to stop the job if an exception is raised (default: False)
|
798
|
+
check_api_keys (bool): Whether to verify API keys before running (default: False)
|
799
|
+
verbose (bool): Whether to print extra messages during execution (default: True)
|
800
|
+
print_exceptions (bool): Whether to print exceptions as they occur (default: True)
|
801
|
+
remote_cache_description (str, optional): Description for entries in the remote cache
|
802
|
+
remote_inference_description (str, optional): Description for the remote inference job
|
803
|
+
remote_inference_results_visibility (VisibilityType): Visibility of results on Coop ("private", "public", "unlisted")
|
804
|
+
disable_remote_cache (bool): Whether to disable the remote cache (default: False)
|
805
|
+
disable_remote_inference (bool): Whether to disable remote inference (default: False)
|
806
|
+
fresh (bool): Whether to ignore cache and force new results (default: False)
|
807
|
+
skip_retry (bool): Whether to skip retrying failed interviews (default: False)
|
808
|
+
raise_validation_errors (bool): Whether to raise validation errors (default: False)
|
809
|
+
background (bool): Whether to run in background mode (default: False)
|
810
|
+
job_uuid (str, optional): UUID for the job, used for tracking
|
811
|
+
cache (Cache, optional): Cache object to store results
|
812
|
+
bucket_collection (BucketCollection, optional): Object to track API calls
|
813
|
+
key_lookup (KeyLookup, optional): Object to manage API keys
|
814
|
+
|
815
|
+
Returns:
|
816
|
+
Results: A Results object containing all responses and metadata
|
817
|
+
|
818
|
+
Notes:
|
819
|
+
- This method should be used in async contexts (e.g., with `await`)
|
820
|
+
- For non-async contexts, use the `run()` method instead
|
821
|
+
- This method is particularly useful in notebook environments or async applications
|
822
|
+
|
823
|
+
Example:
|
824
|
+
>>> import asyncio
|
825
|
+
>>> from edsl.jobs import Jobs
|
826
|
+
>>> from edsl.caching import Cache
|
827
|
+
>>> job = Jobs.example()
|
828
|
+
>>> # In an async context
|
829
|
+
>>> async def run_job():
|
830
|
+
... results = await job.run_async(cache=Cache(), progress_bar=True)
|
831
|
+
... return results
|
686
832
|
"""
|
687
833
|
self._run(config)
|
688
834
|
|
@@ -746,10 +892,10 @@ class Jobs(Base):
|
|
746
892
|
@remove_edsl_version
|
747
893
|
def from_dict(cls, data: dict) -> Jobs:
|
748
894
|
"""Creates a Jobs instance from a dictionary."""
|
749
|
-
from
|
750
|
-
from
|
751
|
-
from
|
752
|
-
from
|
895
|
+
from ..surveys import Survey
|
896
|
+
from ..agents import Agent
|
897
|
+
from ..language_models import LanguageModel
|
898
|
+
from ..scenarios import Scenario
|
753
899
|
|
754
900
|
return cls(
|
755
901
|
survey=Survey.from_dict(data["survey"]),
|
@@ -787,14 +933,14 @@ class Jobs(Base):
|
|
787
933
|
"""
|
788
934
|
import random
|
789
935
|
from uuid import uuid4
|
790
|
-
from
|
791
|
-
from
|
792
|
-
from
|
936
|
+
from ..questions import QuestionMultipleChoice
|
937
|
+
from ..agents import Agent
|
938
|
+
from ..scenarios import Scenario
|
793
939
|
|
794
940
|
addition = "" if not randomize else str(uuid4())
|
795
941
|
|
796
942
|
if test_model:
|
797
|
-
from
|
943
|
+
from ..language_models import LanguageModel
|
798
944
|
|
799
945
|
m = LanguageModel.example(test_model=True)
|
800
946
|
|
@@ -835,8 +981,8 @@ class Jobs(Base):
|
|
835
981
|
question_options=["Good", "Great", "OK", "Terrible"],
|
836
982
|
question_name="how_feeling_yesterday",
|
837
983
|
)
|
838
|
-
from
|
839
|
-
from
|
984
|
+
from ..surveys import Survey
|
985
|
+
from ..scenarios import ScenarioList
|
840
986
|
|
841
987
|
base_survey = Survey(questions=[q1, q2])
|
842
988
|
|
@@ -860,8 +1006,8 @@ class Jobs(Base):
|
|
860
1006
|
|
861
1007
|
def main():
|
862
1008
|
"""Run the module's doctests."""
|
863
|
-
from
|
864
|
-
from
|
1009
|
+
from .jobs import Jobs
|
1010
|
+
from ..caching import Cache
|
865
1011
|
|
866
1012
|
job = Jobs.example()
|
867
1013
|
len(job) == 4
|