edsl 0.1.46__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 +430 -113
- 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/dataset/dataset_operations_mixin.py +1492 -0
- 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} +12 -12
- 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} +321 -155
- edsl/jobs/{JobsChecks.py → jobs_checks.py} +15 -7
- edsl/jobs/{JobsComponentConstructor.py → jobs_component_constructor.py} +20 -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 +10 -16
- 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} +420 -216
- 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/file_store.py +755 -0
- 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} +424 -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 +20 -21
- 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.46.dist-info → edsl-0.1.48.dist-info}/METADATA +3 -2
- edsl-0.1.48.dist-info/RECORD +347 -0
- edsl/Base.py +0 -426
- edsl/BaseDiff.py +0 -260
- edsl/agents/InvigilatorBase.py +0 -260
- edsl/agents/PromptConstructor.py +0 -318
- edsl/auto/AutoStudy.py +0 -130
- edsl/auto/StageBase.py +0 -243
- edsl/auto/StageGenerateSurvey.py +0 -178
- edsl/auto/StageLabelQuestions.py +0 -125
- edsl/auto/StagePersona.py +0 -61
- edsl/auto/StagePersonaDimensionValueRanges.py +0 -88
- edsl/auto/StagePersonaDimensionValues.py +0 -74
- edsl/auto/StagePersonaDimensions.py +0 -69
- edsl/auto/StageQuestions.py +0 -74
- edsl/auto/SurveyCreatorPipeline.py +0 -21
- edsl/auto/utilities.py +0 -218
- edsl/base/Base.py +0 -279
- edsl/coop/PriceFetcher.py +0 -54
- edsl/data/Cache.py +0 -580
- edsl/data/CacheEntry.py +0 -230
- 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 -539
- edsl/questions/QuestionFreeText.py +0 -130
- edsl/questions/derived/QuestionLikertFive.py +0 -76
- edsl/results/DatasetExportMixin.py +0 -911
- 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/FileStore.py +0 -564
- 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 -1306
- 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.46.dist-info/RECORD +0 -366
- /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.46.dist-info → edsl-0.1.48.dist-info}/LICENSE +0 -0
- {edsl-0.1.46.dist-info → edsl-0.1.48.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
|
38
|
+
|
39
|
+
from ..buckets import BucketCollection
|
40
|
+
from ..scenarios import Scenario, ScenarioList
|
41
|
+
from ..surveys import Survey
|
42
|
+
from ..interviews import Interview
|
17
43
|
|
18
|
-
from
|
19
|
-
from
|
20
|
-
from
|
21
|
-
from
|
22
|
-
from
|
23
|
-
from edsl.data.RemoteCacheSync import RemoteCacheSync
|
24
|
-
from edsl.exceptions.coop import CoopServerResponseError
|
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,16 +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
|
-
|
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
|
122
195
|
"""
|
123
196
|
self.run_config = RunConfig(
|
124
197
|
environment=RunEnvironment(), parameters=RunParameters()
|
@@ -129,6 +202,15 @@ class Jobs(Base):
|
|
129
202
|
self.scenarios: ScenarioList = scenarios
|
130
203
|
self.models: ModelList = models
|
131
204
|
|
205
|
+
self._where_clauses = []
|
206
|
+
|
207
|
+
try:
|
208
|
+
assert self.survey.question_names_valid()
|
209
|
+
except Exception as e:
|
210
|
+
invalid_question_names = [q.question_name for q in self.survey.questions if not q.is_valid_question_name()]
|
211
|
+
raise ValueError(f"At least some question names are not valid: {invalid_question_names}")
|
212
|
+
|
213
|
+
|
132
214
|
def add_running_env(self, running_env: RunEnvironment):
|
133
215
|
self.run_config.add_environment(running_env)
|
134
216
|
return self
|
@@ -142,7 +224,7 @@ class Jobs(Base):
|
|
142
224
|
self.run_config.add_cache(cache)
|
143
225
|
return self
|
144
226
|
|
145
|
-
def using_bucket_collection(self, bucket_collection: BucketCollection) -> Jobs:
|
227
|
+
def using_bucket_collection(self, bucket_collection: 'BucketCollection') -> Jobs:
|
146
228
|
"""
|
147
229
|
Add a BucketCollection to the job.
|
148
230
|
|
@@ -151,7 +233,7 @@ class Jobs(Base):
|
|
151
233
|
self.run_config.add_bucket_collection(bucket_collection)
|
152
234
|
return self
|
153
235
|
|
154
|
-
def using_key_lookup(self, key_lookup: KeyLookup) -> Jobs:
|
236
|
+
def using_key_lookup(self, key_lookup: 'KeyLookup') -> Jobs:
|
155
237
|
"""
|
156
238
|
Add a KeyLookup to the job.
|
157
239
|
|
@@ -166,8 +248,8 @@ class Jobs(Base):
|
|
166
248
|
|
167
249
|
:param obj: the object to add
|
168
250
|
"""
|
169
|
-
from
|
170
|
-
from
|
251
|
+
from ..caching import Cache
|
252
|
+
from ..key_management import KeyLookup
|
171
253
|
|
172
254
|
if isinstance(obj, Cache):
|
173
255
|
self.using_cache(obj)
|
@@ -183,7 +265,7 @@ class Jobs(Base):
|
|
183
265
|
|
184
266
|
@models.setter
|
185
267
|
def models(self, value):
|
186
|
-
from
|
268
|
+
from ..language_models import ModelList
|
187
269
|
|
188
270
|
if value:
|
189
271
|
if not isinstance(value, ModelList):
|
@@ -205,7 +287,7 @@ class Jobs(Base):
|
|
205
287
|
|
206
288
|
@agents.setter
|
207
289
|
def agents(self, value):
|
208
|
-
from
|
290
|
+
from ..agents import AgentList
|
209
291
|
|
210
292
|
if value:
|
211
293
|
if not isinstance(value, AgentList):
|
@@ -215,14 +297,23 @@ class Jobs(Base):
|
|
215
297
|
else:
|
216
298
|
self._agents = AgentList([])
|
217
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
|
+
|
218
309
|
@property
|
219
310
|
def scenarios(self):
|
220
311
|
return self._scenarios
|
221
312
|
|
222
313
|
@scenarios.setter
|
223
314
|
def scenarios(self, value):
|
224
|
-
from
|
225
|
-
from
|
315
|
+
from ..scenarios import ScenarioList
|
316
|
+
from ..dataset import Dataset
|
226
317
|
|
227
318
|
if value:
|
228
319
|
if isinstance(
|
@@ -240,40 +331,58 @@ class Jobs(Base):
|
|
240
331
|
def by(
|
241
332
|
self,
|
242
333
|
*args: Union[
|
243
|
-
Agent,
|
244
|
-
Scenario,
|
245
|
-
LanguageModel,
|
334
|
+
"Agent",
|
335
|
+
"Scenario",
|
336
|
+
"LanguageModel",
|
246
337
|
Sequence[Union["Agent", "Scenario", "LanguageModel"]],
|
247
338
|
],
|
248
|
-
) -> Jobs:
|
249
|
-
"""
|
250
|
-
Add
|
251
|
-
|
252
|
-
|
253
|
-
|
254
|
-
|
255
|
-
|
256
|
-
|
257
|
-
|
258
|
-
|
259
|
-
|
260
|
-
|
261
|
-
|
262
|
-
|
263
|
-
|
264
|
-
|
265
|
-
|
266
|
-
|
267
|
-
|
268
|
-
|
269
|
-
|
339
|
+
) -> "Jobs":
|
340
|
+
"""
|
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
|
+
|
270
375
|
Notes:
|
271
|
-
|
272
|
-
|
273
|
-
|
274
|
-
|
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).
|
275
384
|
"""
|
276
|
-
from
|
385
|
+
from .jobs_component_constructor import JobsComponentConstructor
|
277
386
|
|
278
387
|
return JobsComponentConstructor(self).by(*args)
|
279
388
|
|
@@ -285,7 +394,7 @@ class Jobs(Base):
|
|
285
394
|
>>> Jobs.example().prompts()
|
286
395
|
Dataset(...)
|
287
396
|
"""
|
288
|
-
return JobsPrompts(self).prompts(iterations=iterations)
|
397
|
+
return JobsPrompts.from_jobs(self).prompts(iterations=iterations)
|
289
398
|
|
290
399
|
def show_prompts(self, all: bool = False) -> None:
|
291
400
|
"""Print the prompts."""
|
@@ -328,7 +437,7 @@ class Jobs(Base):
|
|
328
437
|
def estimate_job_cost_from_external_prices(
|
329
438
|
self, price_lookup: dict, iterations: int = 1
|
330
439
|
) -> dict:
|
331
|
-
return JobsPrompts(self).estimate_job_cost_from_external_prices(
|
440
|
+
return JobsPrompts.from_jobs(self).estimate_job_cost_from_external_prices(
|
332
441
|
price_lookup, iterations
|
333
442
|
)
|
334
443
|
|
@@ -340,9 +449,9 @@ class Jobs(Base):
|
|
340
449
|
return job_results.compute_job_cost()
|
341
450
|
|
342
451
|
def replace_missing_objects(self) -> None:
|
343
|
-
from
|
344
|
-
from
|
345
|
-
from
|
452
|
+
from ..agents import Agent
|
453
|
+
from ..language_models.model import Model
|
454
|
+
from ..scenarios import Scenario
|
346
455
|
|
347
456
|
self.agents = self.agents or [Agent()]
|
348
457
|
self.models = self.models or [Model()]
|
@@ -357,7 +466,7 @@ class Jobs(Base):
|
|
357
466
|
with us filling in defaults.
|
358
467
|
|
359
468
|
"""
|
360
|
-
from
|
469
|
+
from .jobs_interview_constructor import InterviewsConstructor
|
361
470
|
|
362
471
|
self.replace_missing_objects()
|
363
472
|
yield from InterviewsConstructor(
|
@@ -365,8 +474,12 @@ class Jobs(Base):
|
|
365
474
|
).create_interviews()
|
366
475
|
|
367
476
|
def show_flow(self, filename: Optional[str] = None) -> None:
|
368
|
-
"""Show the flow of the survey.
|
369
|
-
|
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
|
370
483
|
if self.scenarios:
|
371
484
|
scenario = self.scenarios[0]
|
372
485
|
else:
|
@@ -442,7 +555,7 @@ class Jobs(Base):
|
|
442
555
|
846655441787442972
|
443
556
|
|
444
557
|
"""
|
445
|
-
from
|
558
|
+
from ..utilities import dict_hash
|
446
559
|
|
447
560
|
return dict_hash(self.to_dict(add_edsl_version=False))
|
448
561
|
|
@@ -450,8 +563,6 @@ class Jobs(Base):
|
|
450
563
|
"""Check if a Job is verbose. If so, print the message."""
|
451
564
|
if self.run_config.parameters.verbose:
|
452
565
|
print(message)
|
453
|
-
# if hasattr(self, "verbose") and self.verbose:
|
454
|
-
# print(message)
|
455
566
|
|
456
567
|
def all_question_parameters(self) -> set:
|
457
568
|
"""Return all the fields in the questions in the survey.
|
@@ -468,7 +579,7 @@ class Jobs(Base):
|
|
468
579
|
return False
|
469
580
|
if not self.run_config.parameters.disable_remote_cache:
|
470
581
|
try:
|
471
|
-
from
|
582
|
+
from ..coop import Coop
|
472
583
|
|
473
584
|
user_edsl_settings = Coop().edsl_settings
|
474
585
|
return user_edsl_settings.get("remote_caching", False)
|
@@ -493,9 +604,7 @@ class Jobs(Base):
|
|
493
604
|
)
|
494
605
|
return job_info
|
495
606
|
|
496
|
-
def _create_remote_inference_handler(self) -> JobsRemoteInferenceHandler:
|
497
|
-
from edsl.jobs.JobsRemoteInferenceHandler import JobsRemoteInferenceHandler
|
498
|
-
|
607
|
+
def _create_remote_inference_handler(self) -> 'JobsRemoteInferenceHandler':
|
499
608
|
return JobsRemoteInferenceHandler(
|
500
609
|
self, verbose=self.run_config.parameters.verbose
|
501
610
|
)
|
@@ -504,8 +613,7 @@ class Jobs(Base):
|
|
504
613
|
self,
|
505
614
|
config: RunConfig,
|
506
615
|
) -> Union["Results", None]:
|
507
|
-
from
|
508
|
-
from edsl.jobs.JobsRemoteInferenceHandler import RemoteJobInfo
|
616
|
+
from .remote_inference import RemoteJobInfo
|
509
617
|
|
510
618
|
background = config.parameters.background
|
511
619
|
|
@@ -513,7 +621,7 @@ class Jobs(Base):
|
|
513
621
|
if jh.use_remote_inference(self.run_config.parameters.disable_remote_inference):
|
514
622
|
job_info: RemoteJobInfo = self._start_remote_inference_job(jh)
|
515
623
|
if background:
|
516
|
-
from edsl.results
|
624
|
+
from edsl.results import Results
|
517
625
|
|
518
626
|
results = Results.from_job_info(job_info)
|
519
627
|
return results
|
@@ -540,9 +648,9 @@ class Jobs(Base):
|
|
540
648
|
async def _execute_with_remote_cache(self, run_job_async: bool) -> Results:
|
541
649
|
use_remote_cache = self.use_remote_cache()
|
542
650
|
|
543
|
-
from
|
544
|
-
from
|
545
|
-
from
|
651
|
+
from ..coop import Coop
|
652
|
+
from .jobs_runner_asyncio import JobsRunnerAsyncio
|
653
|
+
from ..caching import Cache
|
546
654
|
|
547
655
|
assert isinstance(self.run_config.environment.cache, Cache)
|
548
656
|
|
@@ -589,12 +697,12 @@ class Jobs(Base):
|
|
589
697
|
self.run_config.environment.cache is None
|
590
698
|
or self.run_config.environment.cache is True
|
591
699
|
):
|
592
|
-
from
|
700
|
+
from ..caching import CacheHandler
|
593
701
|
|
594
702
|
self.run_config.environment.cache = CacheHandler().get_cache()
|
595
703
|
|
596
704
|
if self.run_config.environment.cache is False:
|
597
|
-
from
|
705
|
+
from ..caching import Cache
|
598
706
|
|
599
707
|
self.run_config.environment.cache = Cache(immediate_write=False)
|
600
708
|
|
@@ -622,21 +730,50 @@ class Jobs(Base):
|
|
622
730
|
@with_config
|
623
731
|
def run(self, *, config: RunConfig) -> "Results":
|
624
732
|
"""
|
625
|
-
Runs the
|
626
|
-
|
627
|
-
|
628
|
-
|
629
|
-
|
630
|
-
|
631
|
-
:
|
632
|
-
|
633
|
-
|
634
|
-
|
635
|
-
|
636
|
-
|
637
|
-
|
638
|
-
|
639
|
-
|
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
|
+
...
|
640
777
|
"""
|
641
778
|
potentially_completed_results = self._run(config)
|
642
779
|
|
@@ -648,21 +785,50 @@ class Jobs(Base):
|
|
648
785
|
@with_config
|
649
786
|
async def run_async(self, *, config: RunConfig) -> "Results":
|
650
787
|
"""
|
651
|
-
|
652
|
-
|
653
|
-
|
654
|
-
|
655
|
-
|
656
|
-
|
657
|
-
:
|
658
|
-
|
659
|
-
|
660
|
-
|
661
|
-
|
662
|
-
|
663
|
-
|
664
|
-
|
665
|
-
|
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
|
666
832
|
"""
|
667
833
|
self._run(config)
|
668
834
|
|
@@ -726,10 +892,10 @@ class Jobs(Base):
|
|
726
892
|
@remove_edsl_version
|
727
893
|
def from_dict(cls, data: dict) -> Jobs:
|
728
894
|
"""Creates a Jobs instance from a dictionary."""
|
729
|
-
from
|
730
|
-
from
|
731
|
-
from
|
732
|
-
from
|
895
|
+
from ..surveys import Survey
|
896
|
+
from ..agents import Agent
|
897
|
+
from ..language_models import LanguageModel
|
898
|
+
from ..scenarios import Scenario
|
733
899
|
|
734
900
|
return cls(
|
735
901
|
survey=Survey.from_dict(data["survey"]),
|
@@ -767,14 +933,14 @@ class Jobs(Base):
|
|
767
933
|
"""
|
768
934
|
import random
|
769
935
|
from uuid import uuid4
|
770
|
-
from
|
771
|
-
from
|
772
|
-
from
|
936
|
+
from ..questions import QuestionMultipleChoice
|
937
|
+
from ..agents import Agent
|
938
|
+
from ..scenarios import Scenario
|
773
939
|
|
774
940
|
addition = "" if not randomize else str(uuid4())
|
775
941
|
|
776
942
|
if test_model:
|
777
|
-
from
|
943
|
+
from ..language_models import LanguageModel
|
778
944
|
|
779
945
|
m = LanguageModel.example(test_model=True)
|
780
946
|
|
@@ -815,8 +981,8 @@ class Jobs(Base):
|
|
815
981
|
question_options=["Good", "Great", "OK", "Terrible"],
|
816
982
|
question_name="how_feeling_yesterday",
|
817
983
|
)
|
818
|
-
from
|
819
|
-
from
|
984
|
+
from ..surveys import Survey
|
985
|
+
from ..scenarios import ScenarioList
|
820
986
|
|
821
987
|
base_survey = Survey(questions=[q1, q2])
|
822
988
|
|
@@ -840,8 +1006,8 @@ class Jobs(Base):
|
|
840
1006
|
|
841
1007
|
def main():
|
842
1008
|
"""Run the module's doctests."""
|
843
|
-
from
|
844
|
-
from
|
1009
|
+
from .jobs import Jobs
|
1010
|
+
from ..caching import Cache
|
845
1011
|
|
846
1012
|
job = Jobs.example()
|
847
1013
|
len(job) == 4
|