edsl 0.1.47__py3-none-any.whl → 0.1.48__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- edsl/__init__.py +44 -39
- edsl/__version__.py +1 -1
- edsl/agents/__init__.py +4 -2
- edsl/agents/{Agent.py → agent.py} +442 -152
- edsl/agents/{AgentList.py → agent_list.py} +220 -162
- edsl/agents/descriptors.py +46 -7
- edsl/{exceptions/agents.py → agents/exceptions.py} +3 -12
- edsl/base/__init__.py +75 -0
- edsl/base/base_class.py +1303 -0
- edsl/base/data_transfer_models.py +114 -0
- edsl/base/enums.py +215 -0
- edsl/base.py +8 -0
- edsl/buckets/__init__.py +25 -0
- edsl/buckets/bucket_collection.py +324 -0
- edsl/buckets/model_buckets.py +206 -0
- edsl/buckets/token_bucket.py +502 -0
- edsl/{jobs/buckets/TokenBucketAPI.py → buckets/token_bucket_api.py} +1 -1
- edsl/buckets/token_bucket_client.py +509 -0
- edsl/caching/__init__.py +20 -0
- edsl/caching/cache.py +814 -0
- edsl/caching/cache_entry.py +427 -0
- edsl/{data/CacheHandler.py → caching/cache_handler.py} +14 -15
- edsl/caching/exceptions.py +24 -0
- edsl/caching/orm.py +30 -0
- edsl/{data/RemoteCacheSync.py → caching/remote_cache_sync.py} +3 -3
- edsl/caching/sql_dict.py +441 -0
- edsl/config/__init__.py +8 -0
- edsl/config/config_class.py +177 -0
- edsl/config.py +4 -176
- edsl/conversation/Conversation.py +7 -7
- edsl/conversation/car_buying.py +4 -4
- edsl/conversation/chips.py +6 -6
- edsl/coop/__init__.py +25 -2
- edsl/coop/coop.py +303 -67
- edsl/coop/{ExpectedParrotKeyHandler.py → ep_key_handling.py} +86 -10
- edsl/coop/exceptions.py +62 -0
- edsl/coop/price_fetcher.py +126 -0
- edsl/coop/utils.py +89 -24
- edsl/data_transfer_models.py +5 -72
- edsl/dataset/__init__.py +10 -0
- edsl/{results/Dataset.py → dataset/dataset.py} +116 -36
- edsl/{results/DatasetExportMixin.py → dataset/dataset_operations_mixin.py} +606 -122
- edsl/{results/DatasetTree.py → dataset/dataset_tree.py} +156 -75
- edsl/{results/TableDisplay.py → dataset/display/table_display.py} +18 -7
- edsl/{results → dataset/display}/table_renderers.py +58 -2
- edsl/{results → dataset}/file_exports.py +4 -5
- edsl/{results → dataset}/smart_objects.py +2 -2
- edsl/enums.py +5 -205
- edsl/inference_services/__init__.py +5 -0
- edsl/inference_services/{AvailableModelCacheHandler.py → available_model_cache_handler.py} +2 -3
- edsl/inference_services/{AvailableModelFetcher.py → available_model_fetcher.py} +8 -14
- edsl/inference_services/data_structures.py +3 -2
- edsl/{exceptions/inference_services.py → inference_services/exceptions.py} +1 -1
- edsl/inference_services/{InferenceServiceABC.py → inference_service_abc.py} +1 -1
- edsl/inference_services/{InferenceServicesCollection.py → inference_services_collection.py} +8 -7
- edsl/inference_services/registry.py +4 -41
- edsl/inference_services/{ServiceAvailability.py → service_availability.py} +5 -25
- edsl/inference_services/services/__init__.py +31 -0
- edsl/inference_services/{AnthropicService.py → services/anthropic_service.py} +3 -3
- edsl/inference_services/{AwsBedrock.py → services/aws_bedrock.py} +2 -2
- edsl/inference_services/{AzureAI.py → services/azure_ai.py} +2 -2
- edsl/inference_services/{DeepInfraService.py → services/deep_infra_service.py} +1 -3
- edsl/inference_services/{DeepSeekService.py → services/deep_seek_service.py} +2 -4
- edsl/inference_services/{GoogleService.py → services/google_service.py} +5 -4
- edsl/inference_services/{GroqService.py → services/groq_service.py} +1 -1
- edsl/inference_services/{MistralAIService.py → services/mistral_ai_service.py} +3 -3
- edsl/inference_services/{OllamaService.py → services/ollama_service.py} +1 -7
- edsl/inference_services/{OpenAIService.py → services/open_ai_service.py} +5 -6
- edsl/inference_services/{PerplexityService.py → services/perplexity_service.py} +3 -7
- edsl/inference_services/{TestService.py → services/test_service.py} +7 -6
- edsl/inference_services/{TogetherAIService.py → services/together_ai_service.py} +2 -6
- edsl/inference_services/{XAIService.py → services/xai_service.py} +1 -1
- edsl/inference_services/write_available.py +1 -2
- edsl/instructions/__init__.py +6 -0
- edsl/{surveys/instructions/Instruction.py → instructions/instruction.py} +11 -6
- edsl/{surveys/instructions/InstructionCollection.py → instructions/instruction_collection.py} +10 -5
- edsl/{surveys/InstructionHandler.py → instructions/instruction_handler.py} +3 -3
- edsl/{jobs/interviews → interviews}/ReportErrors.py +2 -2
- edsl/interviews/__init__.py +4 -0
- edsl/{jobs/AnswerQuestionFunctionConstructor.py → interviews/answering_function.py} +45 -18
- edsl/{jobs/interviews/InterviewExceptionEntry.py → interviews/exception_tracking.py} +107 -22
- edsl/interviews/interview.py +638 -0
- edsl/{jobs/interviews/InterviewStatusDictionary.py → interviews/interview_status_dictionary.py} +21 -12
- edsl/{jobs/interviews/InterviewStatusLog.py → interviews/interview_status_log.py} +16 -7
- edsl/{jobs/InterviewTaskManager.py → interviews/interview_task_manager.py} +12 -7
- edsl/{jobs/RequestTokenEstimator.py → interviews/request_token_estimator.py} +8 -3
- edsl/{jobs/interviews/InterviewStatistic.py → interviews/statistics.py} +36 -10
- edsl/invigilators/__init__.py +38 -0
- edsl/invigilators/invigilator_base.py +477 -0
- edsl/{agents/Invigilator.py → invigilators/invigilators.py} +263 -10
- edsl/invigilators/prompt_constructor.py +476 -0
- edsl/{agents → invigilators}/prompt_helpers.py +2 -1
- edsl/{agents/QuestionInstructionPromptBuilder.py → invigilators/question_instructions_prompt_builder.py} +18 -13
- edsl/{agents → invigilators}/question_option_processor.py +96 -21
- edsl/{agents/QuestionTemplateReplacementsBuilder.py → invigilators/question_template_replacements_builder.py} +64 -12
- edsl/jobs/__init__.py +7 -1
- edsl/jobs/async_interview_runner.py +99 -35
- edsl/jobs/check_survey_scenario_compatibility.py +7 -5
- edsl/jobs/data_structures.py +153 -22
- edsl/{exceptions/jobs.py → jobs/exceptions.py} +2 -1
- edsl/jobs/{FetchInvigilator.py → fetch_invigilator.py} +4 -4
- edsl/jobs/{loggers/HTMLTableJobLogger.py → html_table_job_logger.py} +6 -2
- edsl/jobs/{Jobs.py → jobs.py} +313 -167
- edsl/jobs/{JobsChecks.py → jobs_checks.py} +15 -7
- edsl/jobs/{JobsComponentConstructor.py → jobs_component_constructor.py} +19 -17
- edsl/jobs/{InterviewsConstructor.py → jobs_interview_constructor.py} +10 -5
- edsl/jobs/jobs_pricing_estimation.py +347 -0
- edsl/jobs/{JobsRemoteInferenceLogger.py → jobs_remote_inference_logger.py} +4 -3
- edsl/jobs/jobs_runner_asyncio.py +282 -0
- edsl/jobs/{JobsRemoteInferenceHandler.py → remote_inference.py} +19 -22
- edsl/jobs/results_exceptions_handler.py +2 -2
- edsl/key_management/__init__.py +28 -0
- edsl/key_management/key_lookup.py +161 -0
- edsl/{language_models/key_management/KeyLookupBuilder.py → key_management/key_lookup_builder.py} +118 -47
- edsl/key_management/key_lookup_collection.py +82 -0
- edsl/key_management/models.py +218 -0
- edsl/language_models/__init__.py +7 -2
- edsl/language_models/{ComputeCost.py → compute_cost.py} +18 -3
- edsl/{exceptions/language_models.py → language_models/exceptions.py} +2 -1
- edsl/language_models/language_model.py +1080 -0
- edsl/language_models/model.py +10 -25
- edsl/language_models/{ModelList.py → model_list.py} +9 -14
- edsl/language_models/{RawResponseHandler.py → raw_response_handler.py} +1 -1
- edsl/language_models/{RegisterLanguageModelsMeta.py → registry.py} +1 -1
- edsl/language_models/repair.py +4 -4
- edsl/language_models/utilities.py +4 -4
- edsl/notebooks/__init__.py +3 -1
- edsl/notebooks/{Notebook.py → notebook.py} +7 -8
- edsl/prompts/__init__.py +1 -1
- edsl/{exceptions/prompts.py → prompts/exceptions.py} +3 -1
- edsl/prompts/{Prompt.py → prompt.py} +101 -95
- edsl/questions/HTMLQuestion.py +1 -1
- edsl/questions/__init__.py +154 -25
- edsl/questions/answer_validator_mixin.py +1 -1
- edsl/questions/compose_questions.py +4 -3
- edsl/questions/derived/question_likert_five.py +166 -0
- edsl/questions/derived/{QuestionLinearScale.py → question_linear_scale.py} +4 -4
- edsl/questions/derived/{QuestionTopK.py → question_top_k.py} +4 -4
- edsl/questions/derived/{QuestionYesNo.py → question_yes_no.py} +4 -5
- edsl/questions/descriptors.py +24 -30
- edsl/questions/loop_processor.py +65 -19
- edsl/questions/question_base.py +881 -0
- edsl/questions/question_base_gen_mixin.py +15 -16
- edsl/questions/{QuestionBasePromptsMixin.py → question_base_prompts_mixin.py} +2 -2
- edsl/questions/{QuestionBudget.py → question_budget.py} +3 -4
- edsl/questions/{QuestionCheckBox.py → question_check_box.py} +16 -16
- edsl/questions/{QuestionDict.py → question_dict.py} +39 -5
- edsl/questions/{QuestionExtract.py → question_extract.py} +9 -9
- edsl/questions/question_free_text.py +282 -0
- edsl/questions/{QuestionFunctional.py → question_functional.py} +6 -5
- edsl/questions/{QuestionList.py → question_list.py} +6 -7
- edsl/questions/{QuestionMatrix.py → question_matrix.py} +6 -5
- edsl/questions/{QuestionMultipleChoice.py → question_multiple_choice.py} +126 -21
- edsl/questions/{QuestionNumerical.py → question_numerical.py} +5 -5
- edsl/questions/{QuestionRank.py → question_rank.py} +6 -6
- edsl/questions/question_registry.py +4 -9
- edsl/questions/register_questions_meta.py +8 -4
- edsl/questions/response_validator_abc.py +17 -16
- edsl/results/__init__.py +4 -1
- edsl/{exceptions/results.py → results/exceptions.py} +1 -1
- edsl/results/report.py +197 -0
- edsl/results/{Result.py → result.py} +131 -45
- edsl/results/{Results.py → results.py} +365 -220
- edsl/results/results_selector.py +344 -25
- edsl/scenarios/__init__.py +30 -3
- edsl/scenarios/{ConstructDownloadLink.py → construct_download_link.py} +7 -0
- edsl/scenarios/directory_scanner.py +156 -13
- edsl/scenarios/document_chunker.py +186 -0
- edsl/scenarios/exceptions.py +101 -0
- edsl/scenarios/file_methods.py +2 -3
- edsl/scenarios/{FileStore.py → file_store.py} +275 -189
- edsl/scenarios/handlers/__init__.py +14 -14
- edsl/scenarios/handlers/{csv.py → csv_file_store.py} +1 -2
- edsl/scenarios/handlers/{docx.py → docx_file_store.py} +8 -7
- edsl/scenarios/handlers/{html.py → html_file_store.py} +1 -2
- edsl/scenarios/handlers/{jpeg.py → jpeg_file_store.py} +1 -1
- edsl/scenarios/handlers/{json.py → json_file_store.py} +1 -1
- edsl/scenarios/handlers/latex_file_store.py +5 -0
- edsl/scenarios/handlers/{md.py → md_file_store.py} +1 -1
- edsl/scenarios/handlers/{pdf.py → pdf_file_store.py} +2 -2
- edsl/scenarios/handlers/{png.py → png_file_store.py} +1 -1
- edsl/scenarios/handlers/{pptx.py → pptx_file_store.py} +8 -7
- edsl/scenarios/handlers/{py.py → py_file_store.py} +1 -3
- edsl/scenarios/handlers/{sql.py → sql_file_store.py} +2 -1
- edsl/scenarios/handlers/{sqlite.py → sqlite_file_store.py} +2 -3
- edsl/scenarios/handlers/{txt.py → txt_file_store.py} +1 -1
- edsl/scenarios/scenario.py +928 -0
- edsl/scenarios/scenario_join.py +18 -5
- edsl/scenarios/{ScenarioList.py → scenario_list.py} +294 -106
- edsl/scenarios/{ScenarioListPdfMixin.py → scenario_list_pdf_tools.py} +16 -15
- edsl/scenarios/scenario_selector.py +5 -1
- edsl/study/ObjectEntry.py +2 -2
- edsl/study/SnapShot.py +5 -5
- edsl/study/Study.py +18 -19
- edsl/study/__init__.py +6 -4
- edsl/surveys/__init__.py +7 -4
- edsl/surveys/dag/__init__.py +2 -0
- edsl/surveys/{ConstructDAG.py → dag/construct_dag.py} +3 -3
- edsl/surveys/{DAG.py → dag/dag.py} +13 -10
- edsl/surveys/descriptors.py +1 -1
- edsl/surveys/{EditSurvey.py → edit_survey.py} +9 -9
- edsl/{exceptions/surveys.py → surveys/exceptions.py} +1 -2
- edsl/surveys/memory/__init__.py +3 -0
- edsl/surveys/{MemoryPlan.py → memory/memory_plan.py} +10 -9
- edsl/surveys/rules/__init__.py +3 -0
- edsl/surveys/{Rule.py → rules/rule.py} +103 -43
- edsl/surveys/{RuleCollection.py → rules/rule_collection.py} +21 -30
- edsl/surveys/{RuleManager.py → rules/rule_manager.py} +19 -13
- edsl/surveys/survey.py +1743 -0
- edsl/surveys/{SurveyExportMixin.py → survey_export.py} +22 -27
- edsl/surveys/{SurveyFlowVisualization.py → survey_flow_visualization.py} +11 -2
- edsl/surveys/{Simulator.py → survey_simulator.py} +10 -3
- edsl/tasks/__init__.py +32 -0
- edsl/{jobs/tasks/QuestionTaskCreator.py → tasks/question_task_creator.py} +115 -57
- edsl/tasks/task_creators.py +135 -0
- edsl/{jobs/tasks/TaskHistory.py → tasks/task_history.py} +86 -47
- edsl/{jobs/tasks → tasks}/task_status_enum.py +91 -7
- edsl/tasks/task_status_log.py +85 -0
- edsl/tokens/__init__.py +2 -0
- edsl/tokens/interview_token_usage.py +53 -0
- edsl/utilities/PrettyList.py +1 -1
- edsl/utilities/SystemInfo.py +25 -22
- edsl/utilities/__init__.py +29 -21
- edsl/utilities/gcp_bucket/__init__.py +2 -0
- edsl/utilities/gcp_bucket/cloud_storage.py +99 -96
- edsl/utilities/interface.py +44 -536
- edsl/{results/MarkdownToPDF.py → utilities/markdown_to_pdf.py} +13 -5
- edsl/utilities/repair_functions.py +1 -1
- {edsl-0.1.47.dist-info → edsl-0.1.48.dist-info}/METADATA +1 -1
- edsl-0.1.48.dist-info/RECORD +347 -0
- edsl/Base.py +0 -493
- edsl/BaseDiff.py +0 -260
- edsl/agents/InvigilatorBase.py +0 -260
- edsl/agents/PromptConstructor.py +0 -318
- edsl/coop/PriceFetcher.py +0 -54
- edsl/data/Cache.py +0 -582
- edsl/data/CacheEntry.py +0 -238
- edsl/data/SQLiteDict.py +0 -292
- edsl/data/__init__.py +0 -5
- edsl/data/orm.py +0 -10
- edsl/exceptions/cache.py +0 -5
- edsl/exceptions/coop.py +0 -14
- edsl/exceptions/data.py +0 -14
- edsl/exceptions/scenarios.py +0 -29
- edsl/jobs/Answers.py +0 -43
- edsl/jobs/JobsPrompts.py +0 -354
- edsl/jobs/buckets/BucketCollection.py +0 -134
- edsl/jobs/buckets/ModelBuckets.py +0 -65
- edsl/jobs/buckets/TokenBucket.py +0 -283
- edsl/jobs/buckets/TokenBucketClient.py +0 -191
- edsl/jobs/interviews/Interview.py +0 -395
- edsl/jobs/interviews/InterviewExceptionCollection.py +0 -99
- edsl/jobs/interviews/InterviewStatisticsCollection.py +0 -25
- edsl/jobs/runners/JobsRunnerAsyncio.py +0 -163
- edsl/jobs/runners/JobsRunnerStatusData.py +0 -0
- edsl/jobs/tasks/TaskCreators.py +0 -64
- edsl/jobs/tasks/TaskStatusLog.py +0 -23
- edsl/jobs/tokens/InterviewTokenUsage.py +0 -27
- edsl/language_models/LanguageModel.py +0 -635
- edsl/language_models/ServiceDataSources.py +0 -0
- edsl/language_models/key_management/KeyLookup.py +0 -63
- edsl/language_models/key_management/KeyLookupCollection.py +0 -38
- edsl/language_models/key_management/models.py +0 -137
- edsl/questions/QuestionBase.py +0 -544
- edsl/questions/QuestionFreeText.py +0 -130
- edsl/questions/derived/QuestionLikertFive.py +0 -76
- edsl/results/ResultsExportMixin.py +0 -45
- edsl/results/TextEditor.py +0 -50
- edsl/results/results_fetch_mixin.py +0 -33
- edsl/results/results_tools_mixin.py +0 -98
- edsl/scenarios/DocumentChunker.py +0 -104
- edsl/scenarios/Scenario.py +0 -548
- edsl/scenarios/ScenarioHtmlMixin.py +0 -65
- edsl/scenarios/ScenarioListExportMixin.py +0 -45
- edsl/scenarios/handlers/latex.py +0 -5
- edsl/shared.py +0 -1
- edsl/surveys/Survey.py +0 -1301
- edsl/surveys/SurveyQualtricsImport.py +0 -284
- edsl/surveys/SurveyToApp.py +0 -141
- edsl/surveys/instructions/__init__.py +0 -0
- edsl/tools/__init__.py +0 -1
- edsl/tools/clusters.py +0 -192
- edsl/tools/embeddings.py +0 -27
- edsl/tools/embeddings_plotting.py +0 -118
- edsl/tools/plotting.py +0 -112
- edsl/tools/summarize.py +0 -18
- edsl/utilities/data/Registry.py +0 -6
- edsl/utilities/data/__init__.py +0 -1
- edsl/utilities/data/scooter_results.json +0 -1
- edsl-0.1.47.dist-info/RECORD +0 -354
- /edsl/coop/{CoopFunctionsMixin.py → coop_functions.py} +0 -0
- /edsl/{results → dataset/display}/CSSParameterizer.py +0 -0
- /edsl/{language_models/key_management → dataset/display}/__init__.py +0 -0
- /edsl/{results → dataset/display}/table_data_class.py +0 -0
- /edsl/{results → dataset/display}/table_display.css +0 -0
- /edsl/{results/ResultsGGMixin.py → dataset/r/ggplot.py} +0 -0
- /edsl/{results → dataset}/tree_explore.py +0 -0
- /edsl/{surveys/instructions/ChangeInstruction.py → instructions/change_instruction.py} +0 -0
- /edsl/{jobs/interviews → interviews}/interview_status_enum.py +0 -0
- /edsl/jobs/{runners/JobsRunnerStatus.py → jobs_runner_status.py} +0 -0
- /edsl/language_models/{PriceManager.py → price_manager.py} +0 -0
- /edsl/language_models/{fake_openai_call.py → unused/fake_openai_call.py} +0 -0
- /edsl/language_models/{fake_openai_service.py → unused/fake_openai_service.py} +0 -0
- /edsl/notebooks/{NotebookToLaTeX.py → notebook_to_latex.py} +0 -0
- /edsl/{exceptions/questions.py → questions/exceptions.py} +0 -0
- /edsl/questions/{SimpleAskMixin.py → simple_ask_mixin.py} +0 -0
- /edsl/surveys/{Memory.py → memory/memory.py} +0 -0
- /edsl/surveys/{MemoryManagement.py → memory/memory_management.py} +0 -0
- /edsl/surveys/{SurveyCSS.py → survey_css.py} +0 -0
- /edsl/{jobs/tokens/TokenUsage.py → tokens/token_usage.py} +0 -0
- /edsl/{results/MarkdownToDocx.py → utilities/markdown_to_docx.py} +0 -0
- /edsl/{TemplateLoader.py → utilities/template_loader.py} +0 -0
- {edsl-0.1.47.dist-info → edsl-0.1.48.dist-info}/LICENSE +0 -0
- {edsl-0.1.47.dist-info → edsl-0.1.48.dist-info}/WHEEL +0 -0
@@ -1,26 +1,26 @@
|
|
1
1
|
import copy
|
2
2
|
import asyncio
|
3
3
|
|
4
|
-
from typing import Union, Type, Callable, TYPE_CHECKING
|
4
|
+
from typing import Union, Type, Callable, TYPE_CHECKING, Any
|
5
5
|
|
6
6
|
if TYPE_CHECKING:
|
7
|
-
from
|
8
|
-
from
|
9
|
-
from
|
7
|
+
from ..questions import QuestionBase
|
8
|
+
from .interview import Interview
|
9
|
+
from ..key_management import KeyLookup
|
10
10
|
|
11
|
-
from
|
12
|
-
from
|
11
|
+
from ..surveys.base import EndOfSurvey
|
12
|
+
from ..tasks import TaskStatus
|
13
13
|
|
14
|
-
from
|
15
|
-
from
|
16
|
-
from
|
17
|
-
from
|
14
|
+
from ..jobs.fetch_invigilator import FetchInvigilator
|
15
|
+
from ..language_models.exceptions import LanguageModelNoResponseError
|
16
|
+
from ..questions.exceptions import QuestionAnswerValidationError
|
17
|
+
from ..data_transfer_models import AgentResponseDict, EDSLResultObjectInput, Answers
|
18
18
|
|
19
|
-
from
|
19
|
+
from .exception_tracking import InterviewExceptionEntry
|
20
20
|
|
21
21
|
|
22
22
|
class RetryConfig:
|
23
|
-
from
|
23
|
+
from ..config import CONFIG
|
24
24
|
|
25
25
|
EDSL_BACKOFF_START_SEC = float(CONFIG.get("EDSL_BACKOFF_START_SEC"))
|
26
26
|
EDSL_BACKOFF_MAX_SEC = float(CONFIG.get("EDSL_BACKOFF_MAX_SEC"))
|
@@ -46,17 +46,45 @@ class SkipHandler:
|
|
46
46
|
| self.interview.agent["traits"]
|
47
47
|
)
|
48
48
|
return self.skip_function(current_question_index, combined_answers)
|
49
|
+
|
50
|
+
def _current_info_env(self) -> dict[str, Any]:
|
51
|
+
"""
|
52
|
+
- The current answers are "generated_tokens" and "comment"
|
53
|
+
- The scenario should have "scenario." added to the keys
|
54
|
+
- The agent traits should have "agent." added to the keys
|
55
|
+
"""
|
56
|
+
# Process answers dictionary
|
57
|
+
processed_answers = {}
|
58
|
+
for key, value in self.interview.answers.items():
|
59
|
+
if key.endswith("_generated_tokens"):
|
60
|
+
base_name = key.replace("_generated_tokens", "")
|
61
|
+
processed_answers[f"{base_name}.generated_tokens"] = value
|
62
|
+
elif key.endswith("_comment"):
|
63
|
+
base_name = key.replace("_comment", "")
|
64
|
+
processed_answers[f"{base_name}.comment"] = value
|
65
|
+
else:
|
66
|
+
# Regular answer
|
67
|
+
processed_answers[f"{key}.answer"] = value
|
68
|
+
|
69
|
+
# Process scenario dictionary
|
70
|
+
processed_scenario = {f"scenario.{k}": v for k, v in self.interview.scenario.items()}
|
71
|
+
|
72
|
+
# Process agent traits
|
73
|
+
processed_agent = {f"agent.{k}": v for k, v in self.interview.agent["traits"].items()}
|
74
|
+
|
75
|
+
return processed_answers | processed_scenario | processed_agent
|
49
76
|
|
50
77
|
def cancel_skipped_questions(self, current_question: "QuestionBase") -> None:
|
51
78
|
"""Cancel the tasks for questions that should be skipped."""
|
52
79
|
current_question_index: int = self.interview.to_index[
|
53
80
|
current_question.question_name
|
54
81
|
]
|
55
|
-
answers = (
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
82
|
+
answers = self._current_info_env()
|
83
|
+
# answers = (
|
84
|
+
# self.interview.answers
|
85
|
+
# | self.interview.scenario
|
86
|
+
# | self.interview.agent["traits"]
|
87
|
+
# )
|
60
88
|
|
61
89
|
# Get the index of the next question, which could also be the end of the survey
|
62
90
|
next_question: Union[int, EndOfSurvey] = (
|
@@ -111,7 +139,6 @@ class AnswerQuestionFunctionConstructor:
|
|
111
139
|
):
|
112
140
|
"""Handle an exception that occurred while answering a question."""
|
113
141
|
|
114
|
-
from edsl.jobs.interviews.InterviewExceptionEntry import InterviewExceptionEntry
|
115
142
|
|
116
143
|
answers = copy.copy(
|
117
144
|
self.interview.answers
|
@@ -1,7 +1,9 @@
|
|
1
|
+
from collections import UserDict
|
1
2
|
import traceback
|
2
3
|
import datetime
|
3
|
-
|
4
|
+
import json
|
4
5
|
|
6
|
+
from ..invigilators import InvigilatorBase
|
5
7
|
|
6
8
|
class InterviewExceptionEntry:
|
7
9
|
"""Class to record an exception that occurred during the interview."""
|
@@ -16,33 +18,33 @@ class InterviewExceptionEntry:
|
|
16
18
|
):
|
17
19
|
self.time = datetime.datetime.now().isoformat()
|
18
20
|
self.exception = exception
|
19
|
-
# self.failed_question = failed_question
|
20
21
|
self.invigilator = invigilator
|
21
22
|
self.traceback_format = traceback_format
|
22
23
|
self.answers = answers
|
23
24
|
|
24
|
-
# breakpoint()
|
25
|
-
|
26
25
|
@property
|
27
|
-
def question_type(self):
|
28
|
-
|
26
|
+
def question_type(self) -> str:
|
27
|
+
"""Return the type of the question that failed."""
|
29
28
|
return self.invigilator.question.question_type
|
30
29
|
|
31
30
|
@property
|
32
|
-
def name(self):
|
31
|
+
def name(self) -> str:
|
32
|
+
"""Return the name of the exception."""
|
33
33
|
return repr(self.exception)
|
34
34
|
|
35
35
|
@property
|
36
|
-
def rendered_prompts(self):
|
36
|
+
def rendered_prompts(self) -> str:
|
37
|
+
"""Return the rendered prompts."""
|
37
38
|
return self.invigilator.get_prompts()
|
38
39
|
|
39
40
|
@property
|
40
|
-
def key_sequence(self):
|
41
|
+
def key_sequence(self) -> tuple[str, ...]:
|
42
|
+
"""Return the key sequence."""
|
41
43
|
return self.invigilator.model.key_sequence
|
42
44
|
|
43
45
|
@property
|
44
|
-
def generated_token_string(self):
|
45
|
-
|
46
|
+
def generated_token_string(self) -> str:
|
47
|
+
"""Return the generated token string."""
|
46
48
|
if self.invigilator.raw_model_response is None:
|
47
49
|
return "No raw model response available."
|
48
50
|
else:
|
@@ -51,9 +53,8 @@ class InterviewExceptionEntry:
|
|
51
53
|
)
|
52
54
|
|
53
55
|
@property
|
54
|
-
def raw_model_response(self):
|
55
|
-
|
56
|
-
|
56
|
+
def raw_model_response(self) -> dict:
|
57
|
+
"""Return the raw model response."""
|
57
58
|
if self.invigilator.raw_model_response is None:
|
58
59
|
return "No raw model response available."
|
59
60
|
return json.dumps(self.invigilator.raw_model_response, indent=2)
|
@@ -64,8 +65,12 @@ class InterviewExceptionEntry:
|
|
64
65
|
|
65
66
|
@classmethod
|
66
67
|
def example(cls):
|
67
|
-
|
68
|
-
|
68
|
+
"""Return an example InterviewExceptionEntry.
|
69
|
+
|
70
|
+
>>> entry = InterviewExceptionEntry.example()
|
71
|
+
"""
|
72
|
+
from ..questions import QuestionFreeText
|
73
|
+
from ..language_models import LanguageModel
|
69
74
|
|
70
75
|
m = LanguageModel.example(test_model=True)
|
71
76
|
q = QuestionFreeText.example(exception_to_throw=ValueError)
|
@@ -80,9 +85,11 @@ class InterviewExceptionEntry:
|
|
80
85
|
|
81
86
|
@property
|
82
87
|
def code_to_reproduce(self):
|
88
|
+
"""Return the code to reproduce the exception."""
|
83
89
|
return self.code(run=False)
|
84
90
|
|
85
91
|
def code(self, run=True):
|
92
|
+
"""Return the code to reproduce the exception."""
|
86
93
|
lines = []
|
87
94
|
lines.append("from edsl import Question, Model, Scenario, Agent")
|
88
95
|
|
@@ -101,7 +108,7 @@ class InterviewExceptionEntry:
|
|
101
108
|
return code_str
|
102
109
|
|
103
110
|
@property
|
104
|
-
def traceback(self):
|
111
|
+
def traceback(self) -> str:
|
105
112
|
"""Return the exception as HTML."""
|
106
113
|
if self.traceback_format == "html":
|
107
114
|
return self.html_traceback
|
@@ -109,7 +116,7 @@ class InterviewExceptionEntry:
|
|
109
116
|
return self.text_traceback
|
110
117
|
|
111
118
|
@property
|
112
|
-
def text_traceback(self):
|
119
|
+
def text_traceback(self) -> str:
|
113
120
|
"""
|
114
121
|
>>> entry = InterviewExceptionEntry.example()
|
115
122
|
>>> entry.text_traceback
|
@@ -120,7 +127,7 @@ class InterviewExceptionEntry:
|
|
120
127
|
return tb_str
|
121
128
|
|
122
129
|
@property
|
123
|
-
def html_traceback(self):
|
130
|
+
def html_traceback(self) -> str:
|
124
131
|
from rich.console import Console
|
125
132
|
from rich.table import Table
|
126
133
|
from rich.traceback import Traceback
|
@@ -142,6 +149,11 @@ class InterviewExceptionEntry:
|
|
142
149
|
|
143
150
|
@staticmethod
|
144
151
|
def serialize_exception(exception: Exception) -> dict:
|
152
|
+
"""Serialize an exception to a dictionary.
|
153
|
+
|
154
|
+
>>> entry = InterviewExceptionEntry.example()
|
155
|
+
>>> _ = entry.serialize_exception(entry.exception)
|
156
|
+
"""
|
145
157
|
return {
|
146
158
|
"type": type(exception).__name__,
|
147
159
|
"message": str(exception),
|
@@ -154,6 +166,11 @@ class InterviewExceptionEntry:
|
|
154
166
|
|
155
167
|
@staticmethod
|
156
168
|
def deserialize_exception(data: dict) -> Exception:
|
169
|
+
"""Deserialize an exception from a dictionary.
|
170
|
+
|
171
|
+
>>> entry = InterviewExceptionEntry.example()
|
172
|
+
>>> _ = entry.deserialize_exception(entry.to_dict()["exception"])
|
173
|
+
"""
|
157
174
|
try:
|
158
175
|
exception_class = globals()[data["type"]]
|
159
176
|
except KeyError:
|
@@ -166,8 +183,7 @@ class InterviewExceptionEntry:
|
|
166
183
|
>>> entry = InterviewExceptionEntry.example()
|
167
184
|
>>> _ = entry.to_dict()
|
168
185
|
"""
|
169
|
-
import
|
170
|
-
from edsl.exceptions.questions import QuestionAnswerValidationError
|
186
|
+
from ..questions.exceptions import QuestionAnswerValidationError
|
171
187
|
|
172
188
|
invigilator = (
|
173
189
|
self.invigilator.to_dict() if self.invigilator is not None else None
|
@@ -192,7 +208,7 @@ class InterviewExceptionEntry:
|
|
192
208
|
@classmethod
|
193
209
|
def from_dict(cls, data: dict) -> "InterviewExceptionEntry":
|
194
210
|
"""Create an InterviewExceptionEntry from a dictionary."""
|
195
|
-
from
|
211
|
+
from ..invigilators import InvigilatorAI
|
196
212
|
|
197
213
|
exception = cls.deserialize_exception(data["exception"])
|
198
214
|
if data["invigilator"] is None:
|
@@ -202,6 +218,75 @@ class InterviewExceptionEntry:
|
|
202
218
|
return cls(exception=exception, invigilator=invigilator)
|
203
219
|
|
204
220
|
|
221
|
+
|
222
|
+
class InterviewExceptionCollection(UserDict):
|
223
|
+
"""A collection of exceptions that occurred during the interview."""
|
224
|
+
|
225
|
+
def __init__(self):
|
226
|
+
"""Initialize the InterviewExceptionCollection."""
|
227
|
+
super().__init__()
|
228
|
+
self.fixed = set()
|
229
|
+
|
230
|
+
def unfixed_exceptions(self) -> list:
|
231
|
+
"""Return a list of unfixed exceptions."""
|
232
|
+
return {k: v for k, v in self.data.items() if k not in self.fixed}
|
233
|
+
|
234
|
+
def num_unfixed(self) -> int:
|
235
|
+
"""Return a list of unfixed questions."""
|
236
|
+
return len([k for k in self.data.keys() if k not in self.fixed])
|
237
|
+
|
238
|
+
def record_fixed_question(self, question_name: str) -> None:
|
239
|
+
"""Record that a question has been fixed."""
|
240
|
+
self.fixed.add(question_name)
|
241
|
+
|
242
|
+
def add(self, question_name: str, entry: InterviewExceptionEntry) -> None:
|
243
|
+
"""Add an exception entry to the collection."""
|
244
|
+
question_name = question_name
|
245
|
+
if question_name not in self.data:
|
246
|
+
self.data[question_name] = []
|
247
|
+
self.data[question_name].append(entry)
|
248
|
+
|
249
|
+
def to_dict(self, include_traceback=True) -> dict:
|
250
|
+
"""Return the collection of exceptions as a dictionary."""
|
251
|
+
newdata = {k: [e.to_dict() for e in v] for k, v in self.data.items()}
|
252
|
+
return newdata
|
253
|
+
|
254
|
+
@classmethod
|
255
|
+
def from_dict(cls, data: dict) -> "InterviewExceptionCollection":
|
256
|
+
"""Create an InterviewExceptionCollection from a dictionary."""
|
257
|
+
collection = cls()
|
258
|
+
for question_name, entries in data.items():
|
259
|
+
for entry in entries:
|
260
|
+
collection.add(question_name, InterviewExceptionEntry.from_dict(entry))
|
261
|
+
return collection
|
262
|
+
|
263
|
+
def _repr_html_(self) -> str:
|
264
|
+
from ..utilities.utilities import data_to_html
|
265
|
+
|
266
|
+
return data_to_html(self.to_dict(include_traceback=True))
|
267
|
+
|
268
|
+
def ascii_table(self, traceback: bool = False) -> None:
|
269
|
+
"""Print the collection of exceptions as an ASCII table."""
|
270
|
+
headers = ["Question name", "Exception", "Time", "Traceback"]
|
271
|
+
from tabulate import tabulate
|
272
|
+
|
273
|
+
data = []
|
274
|
+
for question, exceptions in self.data.items():
|
275
|
+
for exception in exceptions:
|
276
|
+
if traceback:
|
277
|
+
row = [
|
278
|
+
question,
|
279
|
+
exception["exception"],
|
280
|
+
exception["time"],
|
281
|
+
exception["traceback"],
|
282
|
+
]
|
283
|
+
else:
|
284
|
+
row = [question, exception["exception"], exception["time"]]
|
285
|
+
data.append(row)
|
286
|
+
|
287
|
+
print(tabulate(data, headers=headers, tablefmt="grid"))
|
288
|
+
|
289
|
+
|
205
290
|
if __name__ == "__main__":
|
206
291
|
import doctest
|
207
292
|
|