edsl 0.1.49__py3-none-any.whl → 0.1.51__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 +124 -53
- edsl/__version__.py +1 -1
- edsl/agents/agent.py +21 -21
- edsl/agents/agent_list.py +2 -5
- edsl/agents/exceptions.py +119 -5
- edsl/base/__init__.py +10 -35
- edsl/base/base_class.py +71 -36
- edsl/base/base_exception.py +204 -0
- edsl/base/data_transfer_models.py +1 -1
- edsl/base/exceptions.py +94 -0
- edsl/buckets/__init__.py +15 -1
- edsl/buckets/bucket_collection.py +3 -4
- edsl/buckets/exceptions.py +107 -0
- edsl/buckets/model_buckets.py +1 -2
- edsl/buckets/token_bucket.py +11 -6
- edsl/buckets/token_bucket_api.py +27 -12
- edsl/buckets/token_bucket_client.py +9 -7
- edsl/caching/cache.py +12 -4
- edsl/caching/cache_entry.py +10 -9
- edsl/caching/exceptions.py +113 -7
- edsl/caching/remote_cache_sync.py +6 -7
- edsl/caching/sql_dict.py +20 -14
- edsl/cli.py +43 -0
- edsl/config/__init__.py +1 -1
- edsl/config/config_class.py +32 -6
- edsl/conversation/Conversation.py +8 -4
- edsl/conversation/car_buying.py +1 -3
- edsl/conversation/exceptions.py +58 -0
- edsl/conversation/mug_negotiation.py +2 -8
- edsl/coop/__init__.py +28 -6
- edsl/coop/coop.py +120 -29
- edsl/coop/coop_functions.py +1 -1
- edsl/coop/ep_key_handling.py +1 -1
- edsl/coop/exceptions.py +188 -9
- edsl/coop/price_fetcher.py +5 -8
- edsl/coop/utils.py +4 -6
- edsl/dataset/__init__.py +5 -4
- edsl/dataset/dataset.py +177 -86
- edsl/dataset/dataset_operations_mixin.py +98 -76
- edsl/dataset/dataset_tree.py +11 -7
- edsl/dataset/display/table_display.py +0 -2
- edsl/dataset/display/table_renderers.py +6 -4
- edsl/dataset/exceptions.py +125 -0
- edsl/dataset/file_exports.py +18 -11
- edsl/dataset/r/ggplot.py +13 -6
- edsl/display/__init__.py +27 -0
- edsl/display/core.py +147 -0
- edsl/display/plugin.py +189 -0
- edsl/display/utils.py +52 -0
- edsl/inference_services/__init__.py +9 -1
- edsl/inference_services/available_model_cache_handler.py +1 -1
- edsl/inference_services/available_model_fetcher.py +5 -6
- edsl/inference_services/data_structures.py +10 -7
- edsl/inference_services/exceptions.py +132 -1
- edsl/inference_services/inference_service_abc.py +2 -2
- edsl/inference_services/inference_services_collection.py +2 -6
- edsl/inference_services/registry.py +4 -3
- edsl/inference_services/service_availability.py +4 -3
- edsl/inference_services/services/anthropic_service.py +4 -1
- edsl/inference_services/services/aws_bedrock.py +13 -12
- edsl/inference_services/services/azure_ai.py +12 -10
- edsl/inference_services/services/deep_infra_service.py +1 -4
- edsl/inference_services/services/deep_seek_service.py +1 -5
- edsl/inference_services/services/google_service.py +7 -3
- edsl/inference_services/services/groq_service.py +1 -1
- edsl/inference_services/services/mistral_ai_service.py +4 -2
- edsl/inference_services/services/ollama_service.py +1 -1
- edsl/inference_services/services/open_ai_service.py +7 -5
- edsl/inference_services/services/perplexity_service.py +6 -2
- edsl/inference_services/services/test_service.py +8 -7
- edsl/inference_services/services/together_ai_service.py +2 -3
- edsl/inference_services/services/xai_service.py +1 -1
- edsl/instructions/__init__.py +1 -1
- edsl/instructions/change_instruction.py +7 -5
- edsl/instructions/exceptions.py +61 -0
- edsl/instructions/instruction.py +6 -2
- edsl/instructions/instruction_collection.py +6 -4
- edsl/instructions/instruction_handler.py +12 -15
- edsl/interviews/ReportErrors.py +0 -3
- edsl/interviews/__init__.py +9 -2
- edsl/interviews/answering_function.py +11 -13
- edsl/interviews/exception_tracking.py +15 -8
- edsl/interviews/exceptions.py +79 -0
- edsl/interviews/interview.py +33 -30
- edsl/interviews/interview_status_dictionary.py +4 -2
- edsl/interviews/interview_status_log.py +2 -1
- edsl/interviews/interview_task_manager.py +5 -5
- edsl/interviews/request_token_estimator.py +5 -2
- edsl/interviews/statistics.py +3 -4
- edsl/invigilators/__init__.py +7 -1
- edsl/invigilators/exceptions.py +79 -0
- edsl/invigilators/invigilator_base.py +0 -1
- edsl/invigilators/invigilators.py +9 -13
- edsl/invigilators/prompt_constructor.py +1 -5
- edsl/invigilators/prompt_helpers.py +8 -4
- edsl/invigilators/question_instructions_prompt_builder.py +1 -1
- edsl/invigilators/question_option_processor.py +9 -5
- edsl/invigilators/question_template_replacements_builder.py +3 -2
- edsl/jobs/__init__.py +42 -5
- edsl/jobs/async_interview_runner.py +25 -23
- edsl/jobs/check_survey_scenario_compatibility.py +11 -10
- edsl/jobs/data_structures.py +8 -5
- edsl/jobs/exceptions.py +177 -8
- edsl/jobs/fetch_invigilator.py +1 -1
- edsl/jobs/jobs.py +74 -69
- edsl/jobs/jobs_checks.py +6 -7
- edsl/jobs/jobs_component_constructor.py +4 -4
- edsl/jobs/jobs_pricing_estimation.py +4 -3
- edsl/jobs/jobs_remote_inference_logger.py +5 -4
- edsl/jobs/jobs_runner_asyncio.py +3 -4
- edsl/jobs/jobs_runner_status.py +8 -9
- edsl/jobs/remote_inference.py +27 -24
- edsl/jobs/results_exceptions_handler.py +10 -7
- edsl/key_management/__init__.py +3 -1
- edsl/key_management/exceptions.py +62 -0
- edsl/key_management/key_lookup.py +1 -1
- edsl/key_management/key_lookup_builder.py +37 -14
- edsl/key_management/key_lookup_collection.py +2 -0
- edsl/language_models/__init__.py +1 -1
- edsl/language_models/exceptions.py +302 -14
- edsl/language_models/language_model.py +9 -8
- edsl/language_models/model.py +4 -4
- edsl/language_models/model_list.py +1 -1
- edsl/language_models/price_manager.py +1 -1
- edsl/language_models/raw_response_handler.py +14 -9
- edsl/language_models/registry.py +17 -21
- edsl/language_models/repair.py +0 -6
- edsl/language_models/unused/fake_openai_service.py +0 -1
- edsl/load_plugins.py +69 -0
- edsl/logger.py +146 -0
- edsl/notebooks/__init__.py +24 -1
- edsl/notebooks/exceptions.py +82 -0
- edsl/notebooks/notebook.py +7 -3
- edsl/notebooks/notebook_to_latex.py +1 -2
- edsl/plugins/__init__.py +63 -0
- edsl/plugins/built_in/export_example.py +50 -0
- edsl/plugins/built_in/pig_latin.py +67 -0
- edsl/plugins/cli.py +372 -0
- edsl/plugins/cli_typer.py +283 -0
- edsl/plugins/exceptions.py +31 -0
- edsl/plugins/hookspec.py +51 -0
- edsl/plugins/plugin_host.py +128 -0
- edsl/plugins/plugin_manager.py +633 -0
- edsl/plugins/plugins_registry.py +168 -0
- edsl/prompts/__init__.py +24 -1
- edsl/prompts/exceptions.py +107 -5
- edsl/prompts/prompt.py +15 -7
- edsl/questions/HTMLQuestion.py +5 -11
- edsl/questions/Quick.py +0 -1
- edsl/questions/__init__.py +6 -4
- edsl/questions/answer_validator_mixin.py +318 -323
- edsl/questions/compose_questions.py +3 -3
- edsl/questions/descriptors.py +11 -50
- edsl/questions/exceptions.py +278 -22
- edsl/questions/loop_processor.py +7 -5
- edsl/questions/prompt_templates/question_list.jinja +3 -0
- edsl/questions/question_base.py +46 -19
- edsl/questions/question_base_gen_mixin.py +2 -2
- edsl/questions/question_base_prompts_mixin.py +13 -7
- edsl/questions/question_budget.py +503 -98
- edsl/questions/question_check_box.py +660 -160
- edsl/questions/question_dict.py +345 -194
- edsl/questions/question_extract.py +401 -61
- edsl/questions/question_free_text.py +80 -14
- edsl/questions/question_functional.py +119 -9
- edsl/questions/{derived/question_likert_five.py → question_likert_five.py} +2 -2
- edsl/questions/{derived/question_linear_scale.py → question_linear_scale.py} +3 -4
- edsl/questions/question_list.py +275 -28
- edsl/questions/question_matrix.py +643 -96
- edsl/questions/question_multiple_choice.py +219 -51
- edsl/questions/question_numerical.py +361 -32
- edsl/questions/question_rank.py +401 -124
- edsl/questions/question_registry.py +7 -5
- edsl/questions/{derived/question_top_k.py → question_top_k.py} +3 -3
- edsl/questions/{derived/question_yes_no.py → question_yes_no.py} +3 -4
- edsl/questions/register_questions_meta.py +2 -2
- edsl/questions/response_validator_abc.py +13 -15
- edsl/questions/response_validator_factory.py +10 -12
- edsl/questions/templates/dict/answering_instructions.jinja +1 -0
- edsl/questions/templates/rank/question_presentation.jinja +1 -1
- edsl/results/__init__.py +1 -1
- edsl/results/exceptions.py +141 -7
- edsl/results/report.py +1 -2
- edsl/results/result.py +11 -9
- edsl/results/results.py +480 -321
- edsl/results/results_selector.py +8 -4
- edsl/scenarios/PdfExtractor.py +2 -2
- edsl/scenarios/construct_download_link.py +69 -35
- edsl/scenarios/directory_scanner.py +33 -14
- edsl/scenarios/document_chunker.py +1 -1
- edsl/scenarios/exceptions.py +238 -14
- edsl/scenarios/file_methods.py +1 -1
- edsl/scenarios/file_store.py +7 -3
- edsl/scenarios/handlers/__init__.py +17 -0
- edsl/scenarios/handlers/docx_file_store.py +0 -5
- edsl/scenarios/handlers/pdf_file_store.py +0 -1
- edsl/scenarios/handlers/pptx_file_store.py +0 -5
- edsl/scenarios/handlers/py_file_store.py +0 -1
- edsl/scenarios/handlers/sql_file_store.py +1 -4
- edsl/scenarios/handlers/sqlite_file_store.py +0 -1
- edsl/scenarios/handlers/txt_file_store.py +1 -1
- edsl/scenarios/scenario.py +1 -3
- edsl/scenarios/scenario_list.py +179 -27
- edsl/scenarios/scenario_list_pdf_tools.py +1 -0
- edsl/scenarios/scenario_selector.py +0 -1
- edsl/surveys/__init__.py +3 -4
- edsl/surveys/dag/__init__.py +4 -2
- edsl/surveys/descriptors.py +1 -1
- edsl/surveys/edit_survey.py +1 -0
- edsl/surveys/exceptions.py +165 -9
- edsl/surveys/memory/__init__.py +5 -3
- edsl/surveys/memory/memory_management.py +1 -0
- edsl/surveys/memory/memory_plan.py +6 -15
- edsl/surveys/rules/__init__.py +5 -3
- edsl/surveys/rules/rule.py +1 -2
- edsl/surveys/rules/rule_collection.py +1 -1
- edsl/surveys/survey.py +12 -24
- edsl/surveys/survey_css.py +3 -3
- edsl/surveys/survey_export.py +6 -3
- edsl/surveys/survey_flow_visualization.py +10 -1
- edsl/surveys/survey_simulator.py +2 -1
- edsl/tasks/__init__.py +23 -1
- edsl/tasks/exceptions.py +72 -0
- edsl/tasks/question_task_creator.py +3 -3
- edsl/tasks/task_creators.py +1 -3
- edsl/tasks/task_history.py +8 -10
- edsl/tasks/task_status_log.py +1 -2
- edsl/tokens/__init__.py +29 -1
- edsl/tokens/exceptions.py +37 -0
- edsl/tokens/interview_token_usage.py +3 -2
- edsl/tokens/token_usage.py +4 -3
- edsl/utilities/__init__.py +21 -1
- edsl/utilities/decorators.py +1 -2
- edsl/utilities/markdown_to_docx.py +2 -2
- edsl/utilities/markdown_to_pdf.py +1 -1
- edsl/utilities/repair_functions.py +0 -1
- edsl/utilities/restricted_python.py +0 -1
- edsl/utilities/template_loader.py +2 -3
- edsl/utilities/utilities.py +8 -29
- {edsl-0.1.49.dist-info → edsl-0.1.51.dist-info}/METADATA +32 -2
- edsl-0.1.51.dist-info/RECORD +365 -0
- edsl-0.1.51.dist-info/entry_points.txt +3 -0
- edsl/dataset/smart_objects.py +0 -96
- edsl/exceptions/BaseException.py +0 -21
- edsl/exceptions/__init__.py +0 -54
- edsl/exceptions/configuration.py +0 -16
- edsl/exceptions/general.py +0 -34
- edsl/questions/derived/__init__.py +0 -0
- edsl/study/ObjectEntry.py +0 -173
- edsl/study/ProofOfWork.py +0 -113
- edsl/study/SnapShot.py +0 -80
- edsl/study/Study.py +0 -520
- edsl/study/__init__.py +0 -6
- edsl/utilities/interface.py +0 -135
- edsl-0.1.49.dist-info/RECORD +0 -347
- {edsl-0.1.49.dist-info → edsl-0.1.51.dist-info}/LICENSE +0 -0
- {edsl-0.1.49.dist-info → edsl-0.1.51.dist-info}/WHEEL +0 -0
@@ -8,6 +8,7 @@ if TYPE_CHECKING:
|
|
8
8
|
from ...surveys import Survey
|
9
9
|
from ...prompts import Prompt
|
10
10
|
from ..dag import DAG
|
11
|
+
from ...questions.question_base import QuestionBase
|
11
12
|
|
12
13
|
class MemoryPlan(UserDict):
|
13
14
|
"""A survey has a memory plan that specifies what the agent should remember when answering a question.
|
@@ -103,23 +104,13 @@ class MemoryPlan(UserDict):
|
|
103
104
|
:param focal_question: The current question being answered.
|
104
105
|
:param prior_question: The question that was answered before the focal question that should be remembered.
|
105
106
|
|
106
|
-
|
107
|
-
|
108
|
-
Traceback (most recent call last):
|
109
|
-
...
|
110
|
-
ValueError: q1 must come before q0.
|
107
|
+
# Prior question must come before focal question
|
108
|
+
# Example: adding "q0", "q1" would raise ValueError as q1 comes after q0
|
111
109
|
|
112
|
-
|
113
|
-
|
114
|
-
Traceback (most recent call last):
|
115
|
-
...
|
116
|
-
ValueError: crap is not in the survey. Current names are ['q0', 'q1', 'q2']
|
110
|
+
# Question names must exist in the survey
|
111
|
+
# Example: using a non-existent question name "crap" would raise ValueError
|
117
112
|
|
118
|
-
|
119
|
-
>>> mp.add_single_memory("crap", "q0")
|
120
|
-
Traceback (most recent call last):
|
121
|
-
...
|
122
|
-
ValueError: crap is not in the survey. Current names are ['q0', 'q1', 'q2']
|
113
|
+
# Similarly, focal question must also exist in the survey
|
123
114
|
"""
|
124
115
|
self._check_valid_question_name(focal_question)
|
125
116
|
self._check_valid_question_name(prior_question)
|
edsl/surveys/rules/__init__.py
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
-
from .rule import Rule
|
2
|
-
from .rule_manager import RuleManager
|
3
|
-
from .rule_collection import RuleCollection
|
1
|
+
from .rule import Rule # noqa: F401
|
2
|
+
from .rule_manager import RuleManager # noqa: F401
|
3
|
+
from .rule_collection import RuleCollection # noqa: F401
|
4
|
+
|
5
|
+
__all__ = []
|
edsl/surveys/rules/rule.py
CHANGED
@@ -19,7 +19,7 @@ with a low (-1) priority.
|
|
19
19
|
|
20
20
|
import ast
|
21
21
|
import random
|
22
|
-
from typing import Any, Union
|
22
|
+
from typing import Any, Union
|
23
23
|
from collections import defaultdict
|
24
24
|
|
25
25
|
|
@@ -27,7 +27,6 @@ from collections import defaultdict
|
|
27
27
|
from simpleeval import EvalWithCompoundTypes
|
28
28
|
|
29
29
|
from ..exceptions import SurveyError
|
30
|
-
|
31
30
|
from ..exceptions import (
|
32
31
|
SurveyRuleCannotEvaluateError,
|
33
32
|
SurveyRuleRefersToFutureStateError,
|
edsl/surveys/survey.py
CHANGED
@@ -25,10 +25,8 @@ from typing import (
|
|
25
25
|
TYPE_CHECKING,
|
26
26
|
Dict,
|
27
27
|
Tuple,
|
28
|
-
Set,
|
29
|
-
Type,
|
30
28
|
)
|
31
|
-
from typing_extensions import Literal
|
29
|
+
from typing_extensions import Literal
|
32
30
|
from ..base import Base
|
33
31
|
from ..agents import Agent
|
34
32
|
from ..scenarios import Scenario
|
@@ -45,7 +43,6 @@ if TYPE_CHECKING:
|
|
45
43
|
from ..scenarios import ScenarioList
|
46
44
|
from ..buckets.bucket_collection import BucketCollection
|
47
45
|
from ..key_management.key_lookup import KeyLookup
|
48
|
-
from .memory import Memory
|
49
46
|
|
50
47
|
# Define types for documentation purpose only
|
51
48
|
VisibilityType = Literal["unlisted", "public", "private"]
|
@@ -243,6 +240,14 @@ class Survey(Base):
|
|
243
240
|
|
244
241
|
self._exporter = SurveyExport(self)
|
245
242
|
|
243
|
+
|
244
|
+
# In survey.py
|
245
|
+
@property
|
246
|
+
def ep(self):
|
247
|
+
"""Return plugin host for this survey."""
|
248
|
+
from ..plugins.plugin_host import PluginHost
|
249
|
+
return PluginHost(self)
|
250
|
+
|
246
251
|
def question_names_valid(self) -> bool:
|
247
252
|
"""Check if the question names are valid."""
|
248
253
|
return all(q.is_valid_question_name() for q in self.questions)
|
@@ -350,11 +355,7 @@ class Survey(Base):
|
|
350
355
|
|
351
356
|
This doesnt' work with questions that don't exist:
|
352
357
|
|
353
|
-
|
354
|
-
Traceback (most recent call last):
|
355
|
-
...
|
356
|
-
edsl.surveys.exceptions.SurveyError: Question name poop not found in survey. The current question names are {'q0': 0, 'q1': 1, 'q2': 2}.
|
357
|
-
...
|
358
|
+
# Example with a non-existent question name would raise SurveyError
|
358
359
|
"""
|
359
360
|
if q is EndOfSurvey:
|
360
361
|
return EndOfSurvey
|
@@ -609,11 +610,6 @@ class Survey(Base):
|
|
609
610
|
>>> s1 = Survey.example()
|
610
611
|
>>> from edsl import QuestionFreeText
|
611
612
|
>>> s2 = Survey([QuestionFreeText(question_text="What is your name?", question_name="yo")])
|
612
|
-
>>> s3 = s1 + s2
|
613
|
-
Traceback (most recent call last):
|
614
|
-
...
|
615
|
-
edsl.surveys.exceptions.SurveyCreationError: ...
|
616
|
-
...
|
617
613
|
>>> s3 = s1.clear_non_default_rules() + s2
|
618
614
|
>>> len(s3.questions)
|
619
615
|
4
|
@@ -676,11 +672,7 @@ class Survey(Base):
|
|
676
672
|
>>> q = QuestionMultipleChoice(question_text = "Do you like school?", question_options=["yes", "no"], question_name="q0")
|
677
673
|
>>> s = Survey().add_question(q)
|
678
674
|
|
679
|
-
|
680
|
-
Traceback (most recent call last):
|
681
|
-
...
|
682
|
-
edsl.surveys.exceptions.SurveyCreationError: Question name 'q0' already exists in survey. Existing names are ['q0'].
|
683
|
-
...
|
675
|
+
# Adding a question with a duplicate name would raise SurveyCreationError
|
684
676
|
"""
|
685
677
|
return EditSurvey(self).add_question(question, index)
|
686
678
|
|
@@ -972,11 +964,7 @@ class Survey(Base):
|
|
972
964
|
>>> s.next_question("q0", {"q0.answer": "no"}).question_name
|
973
965
|
'q1'
|
974
966
|
|
975
|
-
|
976
|
-
Traceback (most recent call last):
|
977
|
-
...
|
978
|
-
edsl.surveys.exceptions.SurveyCreationError: The expression contains '<>', which is not allowed. You probably mean '!='.
|
979
|
-
...
|
967
|
+
# Using invalid operators like '<>' would raise SurveyCreationError
|
980
968
|
"""
|
981
969
|
return RuleManager(self).add_stop_rule(question, expression)
|
982
970
|
|
edsl/surveys/survey_css.py
CHANGED
@@ -1,5 +1,5 @@
|
|
1
1
|
from typing import Optional
|
2
|
-
from
|
2
|
+
from ..utilities.remove_edsl_version import remove_edsl_version
|
3
3
|
|
4
4
|
|
5
5
|
class CSSRuleMeta(type):
|
@@ -73,7 +73,7 @@ class CSSRule(metaclass=CSSRuleMeta):
|
|
73
73
|
d = {"selector": self.selector, "properties": self.properties}
|
74
74
|
|
75
75
|
if add_esl_version:
|
76
|
-
from
|
76
|
+
from .. import __version__
|
77
77
|
|
78
78
|
d["edsl_version"] = __version__
|
79
79
|
d["edsl_class_name"] = self.__class__.__name__
|
@@ -233,7 +233,7 @@ class SurveyCSS:
|
|
233
233
|
"""
|
234
234
|
d = {"rules": [rule.to_dict() for rule in self.rules.values()]}
|
235
235
|
if add_edsl_version:
|
236
|
-
from
|
236
|
+
from .. import __version__
|
237
237
|
|
238
238
|
d["edsl_version"] = __version__
|
239
239
|
d["edsl_class_name"] = self.__class__.__name__
|
edsl/surveys/survey_export.py
CHANGED
@@ -1,12 +1,16 @@
|
|
1
1
|
"""A class for exporting surveys to different formats."""
|
2
2
|
|
3
|
-
from typing import Union, Optional
|
3
|
+
from typing import Union, Optional, TYPE_CHECKING
|
4
4
|
|
5
5
|
import subprocess
|
6
6
|
import platform
|
7
7
|
import os
|
8
8
|
import tempfile
|
9
9
|
|
10
|
+
if TYPE_CHECKING:
|
11
|
+
from docx import Document
|
12
|
+
from ..scenarios import ScenarioList
|
13
|
+
|
10
14
|
|
11
15
|
def open_docx(file_path):
|
12
16
|
"""
|
@@ -61,7 +65,7 @@ class SurveyExport:
|
|
61
65
|
|
62
66
|
doc = Document()
|
63
67
|
doc.add_heading("EDSL Survey")
|
64
|
-
doc.add_paragraph(
|
68
|
+
doc.add_paragraph("\n")
|
65
69
|
for index, question in enumerate(self.survey._questions):
|
66
70
|
h = doc.add_paragraph() # Add question as a paragraph
|
67
71
|
h.add_run(f"Question {index + 1} ({question.question_name})").bold = True
|
@@ -176,7 +180,6 @@ class SurveyExport:
|
|
176
180
|
include_question_name=False,
|
177
181
|
):
|
178
182
|
from IPython.display import display, HTML
|
179
|
-
import tempfile
|
180
183
|
import os
|
181
184
|
from edsl.utilities.utilities import is_notebook
|
182
185
|
|
@@ -1,10 +1,19 @@
|
|
1
1
|
"""A mixin for visualizing the flow of a survey with parameter nodes."""
|
2
2
|
|
3
|
-
from typing import Optional
|
3
|
+
from typing import Optional
|
4
4
|
from edsl.surveys.base import RulePriority, EndOfSurvey
|
5
5
|
import tempfile
|
6
6
|
|
7
7
|
|
8
|
+
# Import types for annotations
|
9
|
+
from typing import TYPE_CHECKING
|
10
|
+
|
11
|
+
if TYPE_CHECKING:
|
12
|
+
from ..surveys.survey import Survey
|
13
|
+
from ..scenarios import Scenario
|
14
|
+
from ..agents import Agent
|
15
|
+
|
16
|
+
|
8
17
|
class SurveyFlowVisualization:
|
9
18
|
"""A mixin for visualizing the flow of a survey with parameter visualization."""
|
10
19
|
|
edsl/surveys/survey_simulator.py
CHANGED
@@ -58,7 +58,8 @@ class Simulator:
|
|
58
58
|
|
59
59
|
if num_passes > 100:
|
60
60
|
print("Too many passes.")
|
61
|
-
|
61
|
+
from .exceptions import SurveyError
|
62
|
+
raise SurveyError("Too many passes.")
|
62
63
|
return self.survey.answers
|
63
64
|
|
64
65
|
def create_agent(self) -> "Agent":
|
edsl/tasks/__init__.py
CHANGED
@@ -26,7 +26,29 @@ For most users, this module works behind the scenes, but understanding it can
|
|
26
26
|
be helpful when debugging or optimizing complex EDSL workflows.
|
27
27
|
"""
|
28
28
|
|
29
|
+
__all__ = [
|
30
|
+
'TaskHistory',
|
31
|
+
'QuestionTaskCreator',
|
32
|
+
'TaskCreators',
|
33
|
+
'TaskStatus',
|
34
|
+
'TaskStatusDescriptor',
|
35
|
+
'TaskError',
|
36
|
+
'TaskStatusError',
|
37
|
+
'TaskExecutionError',
|
38
|
+
'TaskDependencyError',
|
39
|
+
'TaskResourceError',
|
40
|
+
'TaskHistoryError'
|
41
|
+
]
|
42
|
+
|
29
43
|
from .task_history import TaskHistory
|
30
44
|
from .question_task_creator import QuestionTaskCreator
|
31
45
|
from .task_creators import TaskCreators
|
32
|
-
from .task_status_enum import TaskStatus, TaskStatusDescriptor
|
46
|
+
from .task_status_enum import TaskStatus, TaskStatusDescriptor
|
47
|
+
from .exceptions import (
|
48
|
+
TaskError,
|
49
|
+
TaskStatusError,
|
50
|
+
TaskExecutionError,
|
51
|
+
TaskDependencyError,
|
52
|
+
TaskResourceError,
|
53
|
+
TaskHistoryError
|
54
|
+
)
|
edsl/tasks/exceptions.py
ADDED
@@ -0,0 +1,72 @@
|
|
1
|
+
"""
|
2
|
+
This module defines the exception hierarchy for the tasks module.
|
3
|
+
|
4
|
+
All exceptions related to task creation, execution, and management are defined here.
|
5
|
+
These exceptions provide detailed error information for debugging and error reporting.
|
6
|
+
"""
|
7
|
+
|
8
|
+
from ..base import BaseException
|
9
|
+
|
10
|
+
|
11
|
+
class TaskError(BaseException):
|
12
|
+
"""
|
13
|
+
Base exception for all tasks-related errors.
|
14
|
+
|
15
|
+
This is the parent class for all exceptions raised within the tasks module.
|
16
|
+
It inherits from BaseException to ensure proper error tracking and reporting.
|
17
|
+
"""
|
18
|
+
pass
|
19
|
+
|
20
|
+
|
21
|
+
class TaskStatusError(TaskError):
|
22
|
+
"""
|
23
|
+
Raised when a task encounters an invalid status transition.
|
24
|
+
|
25
|
+
This exception is raised when a task attempts to transition to an invalid state
|
26
|
+
based on its current state, such as trying to set a completed task to running.
|
27
|
+
|
28
|
+
Attributes:
|
29
|
+
current_status: The current status of the task
|
30
|
+
attempted_status: The status that could not be set
|
31
|
+
"""
|
32
|
+
pass
|
33
|
+
|
34
|
+
|
35
|
+
class TaskExecutionError(TaskError):
|
36
|
+
"""
|
37
|
+
Raised when a task encounters an error during execution.
|
38
|
+
|
39
|
+
This is a general exception for errors that occur while a task is running,
|
40
|
+
not specific to dependency resolution or resource allocation.
|
41
|
+
"""
|
42
|
+
pass
|
43
|
+
|
44
|
+
|
45
|
+
class TaskDependencyError(TaskError):
|
46
|
+
"""
|
47
|
+
Raised when there is an issue with task dependencies.
|
48
|
+
|
49
|
+
This exception is raised for dependency-related issues, such as circular
|
50
|
+
dependencies or errors in dependent tasks.
|
51
|
+
"""
|
52
|
+
pass
|
53
|
+
|
54
|
+
|
55
|
+
class TaskResourceError(TaskError):
|
56
|
+
"""
|
57
|
+
Raised when a task cannot acquire necessary resources.
|
58
|
+
|
59
|
+
This exception is used when a task cannot obtain required resources
|
60
|
+
such as tokens or request capacity, beyond normal waiting situations.
|
61
|
+
"""
|
62
|
+
pass
|
63
|
+
|
64
|
+
|
65
|
+
class TaskHistoryError(TaskError):
|
66
|
+
"""
|
67
|
+
Raised for errors related to task history operations.
|
68
|
+
|
69
|
+
This exception covers issues with recording, accessing, or analyzing
|
70
|
+
task execution history and logs.
|
71
|
+
"""
|
72
|
+
pass
|
@@ -8,7 +8,7 @@ execution unit in EDSL's task system.
|
|
8
8
|
"""
|
9
9
|
|
10
10
|
import asyncio
|
11
|
-
from typing import Callable,
|
11
|
+
from typing import Callable, Optional, TYPE_CHECKING
|
12
12
|
from collections import UserList, UserDict
|
13
13
|
|
14
14
|
from ..jobs.exceptions import InterviewErrorPriorTaskCanceled
|
@@ -170,12 +170,12 @@ class QuestionTaskCreator(UserList):
|
|
170
170
|
"""
|
171
171
|
|
172
172
|
requested_tokens = self.estimated_tokens()
|
173
|
-
if (
|
173
|
+
if (self.tokens_bucket.wait_time(requested_tokens)) > 0:
|
174
174
|
self.task_status = TaskStatus.WAITING_FOR_TOKEN_CAPACITY
|
175
175
|
|
176
176
|
await self.tokens_bucket.get_tokens(requested_tokens)
|
177
177
|
|
178
|
-
if
|
178
|
+
if self.model_buckets.requests_bucket.wait_time(1) > 0:
|
179
179
|
self.waiting = True # do we need this?
|
180
180
|
self.task_status = TaskStatus.WAITING_FOR_REQUEST_CAPACITY
|
181
181
|
|
edsl/tasks/task_creators.py
CHANGED
@@ -6,15 +6,13 @@ for executing a single question within an interview. It aggregates status and to
|
|
6
6
|
information across all tasks, providing a complete view of interview execution.
|
7
7
|
"""
|
8
8
|
|
9
|
-
from typing import
|
9
|
+
from typing import List, TYPE_CHECKING
|
10
10
|
from collections import UserDict
|
11
11
|
|
12
12
|
if TYPE_CHECKING:
|
13
|
-
from ..tokens import TokenUsage
|
14
13
|
from ..tokens import InterviewTokenUsage
|
15
14
|
from ..interviews import InterviewStatusDictionary
|
16
15
|
from .task_status_log import TaskStatusLog
|
17
|
-
from .question_task_creator import QuestionTaskCreator
|
18
16
|
|
19
17
|
class TaskCreators(UserDict):
|
20
18
|
"""
|
edsl/tasks/task_history.py
CHANGED
@@ -7,7 +7,10 @@ visualization and reporting to help users understand task execution patterns and
|
|
7
7
|
issues.
|
8
8
|
"""
|
9
9
|
|
10
|
-
from typing import List, Optional,
|
10
|
+
from typing import List, Optional, TYPE_CHECKING
|
11
|
+
|
12
|
+
if TYPE_CHECKING:
|
13
|
+
from ..interviews import Interview
|
11
14
|
from io import BytesIO
|
12
15
|
import base64
|
13
16
|
import os
|
@@ -89,12 +92,10 @@ class TaskHistory(RepresentationMixin):
|
|
89
92
|
@classmethod
|
90
93
|
def example(cls):
|
91
94
|
""" """
|
92
|
-
from ..interviews import Interview
|
93
95
|
from ..jobs import Jobs
|
94
96
|
|
95
97
|
j = Jobs.example(throw_exception_probability=1, test_model=True)
|
96
98
|
|
97
|
-
from edsl.config import CONFIG
|
98
99
|
|
99
100
|
results = j.run(
|
100
101
|
print_exceptions=False,
|
@@ -145,7 +146,7 @@ class TaskHistory(RepresentationMixin):
|
|
145
146
|
"include_traceback": self.include_traceback,
|
146
147
|
}
|
147
148
|
if add_edsl_version:
|
148
|
-
from
|
149
|
+
from .. import __version__
|
149
150
|
|
150
151
|
d["edsl_version"] = __version__
|
151
152
|
d["edsl_class_name"] = "TaskHistory"
|
@@ -404,8 +405,8 @@ class TaskHistory(RepresentationMixin):
|
|
404
405
|
|
405
406
|
models_used = set([i.model.model for index, i in self._interviews.items()])
|
406
407
|
|
407
|
-
from jinja2 import Environment
|
408
|
-
from
|
408
|
+
from jinja2 import Environment
|
409
|
+
from ..utilities import TemplateLoader
|
409
410
|
|
410
411
|
env = Environment(loader=TemplateLoader("edsl", "templates/error_reporting"))
|
411
412
|
|
@@ -463,9 +464,8 @@ class TaskHistory(RepresentationMixin):
|
|
463
464
|
- Exception details, status transitions, and timing are all included
|
464
465
|
"""
|
465
466
|
from IPython.display import display, HTML
|
466
|
-
import tempfile
|
467
467
|
import os
|
468
|
-
from
|
468
|
+
from ..utilities.utilities import is_notebook
|
469
469
|
|
470
470
|
output = self.generate_html_report(css)
|
471
471
|
|
@@ -509,8 +509,6 @@ class TaskHistory(RepresentationMixin):
|
|
509
509
|
"""Create a notebook with the HTML content embedded in the first cell, then delete the cell content while keeping the output."""
|
510
510
|
from nbformat import v4 as nbf
|
511
511
|
from nbconvert.preprocessors import ExecutePreprocessor
|
512
|
-
import nbformat
|
513
|
-
import os
|
514
512
|
|
515
513
|
# Use the existing html method to generate the HTML content
|
516
514
|
output_html = self.generate_html_report(css=None)
|
edsl/tasks/task_status_log.py
CHANGED
@@ -7,9 +7,8 @@ execution, including timing, state transitions, and status at any point in time.
|
|
7
7
|
"""
|
8
8
|
|
9
9
|
from collections import UserList
|
10
|
-
from typing import List, Optional, Union
|
11
10
|
|
12
|
-
from .task_status_enum import TaskStatus
|
11
|
+
from .task_status_enum import TaskStatus
|
13
12
|
|
14
13
|
|
15
14
|
class TaskStatusLog(UserList):
|
edsl/tokens/__init__.py
CHANGED
@@ -1,2 +1,30 @@
|
|
1
|
+
"""
|
2
|
+
The tokens module provides functionality for tracking and analyzing token usage in EDSL.
|
3
|
+
|
4
|
+
This module implements classes for tracking and reporting token usage across various
|
5
|
+
components of EDSL, particularly for language model calls. It supports aggregation,
|
6
|
+
cost calculation, and reporting of token usage metrics.
|
7
|
+
|
8
|
+
Key components:
|
9
|
+
1. TokenUsage - Tracks prompt and completion tokens for a single operation
|
10
|
+
2. InterviewTokenUsage - Aggregates token usage across an entire interview
|
11
|
+
3. Exception classes for handling token-related errors
|
12
|
+
|
13
|
+
The token tracking system helps with:
|
14
|
+
- Cost estimation and billing
|
15
|
+
- Resource utilization analysis
|
16
|
+
- Cache effectiveness measurement
|
17
|
+
- API quota management
|
18
|
+
"""
|
19
|
+
|
1
20
|
from .token_usage import TokenUsage
|
2
|
-
from .interview_token_usage import InterviewTokenUsage
|
21
|
+
from .interview_token_usage import InterviewTokenUsage
|
22
|
+
from .exceptions import TokenError, TokenUsageError, TokenCostError
|
23
|
+
|
24
|
+
__all__ = [
|
25
|
+
"TokenUsage",
|
26
|
+
"InterviewTokenUsage",
|
27
|
+
"TokenError",
|
28
|
+
"TokenUsageError",
|
29
|
+
"TokenCostError"
|
30
|
+
]
|
@@ -0,0 +1,37 @@
|
|
1
|
+
"""
|
2
|
+
This module defines the exception hierarchy for the tokens module.
|
3
|
+
|
4
|
+
All exceptions related to token usage tracking and cost calculations are defined here.
|
5
|
+
"""
|
6
|
+
|
7
|
+
from ..base import BaseException
|
8
|
+
|
9
|
+
|
10
|
+
class TokenError(BaseException):
|
11
|
+
"""
|
12
|
+
Base exception for all token-related errors.
|
13
|
+
|
14
|
+
This is the parent class for all exceptions raised within the tokens module.
|
15
|
+
It inherits from BaseException to ensure proper error tracking and reporting.
|
16
|
+
"""
|
17
|
+
pass
|
18
|
+
|
19
|
+
|
20
|
+
class TokenUsageError(TokenError):
|
21
|
+
"""
|
22
|
+
Raised when there is an error in token usage operations.
|
23
|
+
|
24
|
+
This exception is raised for issues related to token usage tracking,
|
25
|
+
such as invalid token counts or incompatible token usage types.
|
26
|
+
"""
|
27
|
+
pass
|
28
|
+
|
29
|
+
|
30
|
+
class TokenCostError(TokenError):
|
31
|
+
"""
|
32
|
+
Raised when there is an error in token cost calculations.
|
33
|
+
|
34
|
+
This exception is used for issues with cost calculations, such as
|
35
|
+
missing or invalid pricing information.
|
36
|
+
"""
|
37
|
+
pass
|
@@ -1,7 +1,8 @@
|
|
1
1
|
from typing import Optional
|
2
2
|
|
3
3
|
from .token_usage import TokenUsage
|
4
|
-
from
|
4
|
+
from ..enums import TokenPricing
|
5
|
+
from .exceptions import TokenUsageError
|
5
6
|
|
6
7
|
class InterviewTokenUsage:
|
7
8
|
"""A class to represent the token usage of an interview."""
|
@@ -24,7 +25,7 @@ class InterviewTokenUsage:
|
|
24
25
|
>>> usage3 = usage1 + usage2
|
25
26
|
"""
|
26
27
|
if not isinstance(other, InterviewTokenUsage):
|
27
|
-
raise
|
28
|
+
raise TokenUsageError(f"Can't add {type(other)} to InterviewTokenSummary")
|
28
29
|
return InterviewTokenUsage(
|
29
30
|
new_token_usage=self.new_token_usage + other.new_token_usage,
|
30
31
|
cached_token_usage=self.cached_token_usage + other.cached_token_usage,
|
edsl/tokens/token_usage.py
CHANGED
@@ -1,4 +1,5 @@
|
|
1
|
-
from
|
1
|
+
from ..enums import TokenPricing
|
2
|
+
from .exceptions import TokenUsageError, TokenCostError
|
2
3
|
|
3
4
|
|
4
5
|
class TokenUsage:
|
@@ -15,9 +16,9 @@ class TokenUsage:
|
|
15
16
|
|
16
17
|
def __add__(self, other):
|
17
18
|
if not isinstance(other, TokenUsage):
|
18
|
-
raise
|
19
|
+
raise TokenUsageError(f"Can't add {type(other)} to InterviewTokenUsage")
|
19
20
|
if self.from_cache != other.from_cache:
|
20
|
-
raise
|
21
|
+
raise TokenUsageError("Can't add token usages from different sources")
|
21
22
|
return TokenUsage(
|
22
23
|
from_cache=self.from_cache,
|
23
24
|
prompt_tokens=self.prompt_tokens + other.prompt_tokens,
|
edsl/utilities/__init__.py
CHANGED
@@ -26,5 +26,25 @@ from .is_valid_variable_name import is_valid_variable_name
|
|
26
26
|
from .naming_utilities import sanitize_string
|
27
27
|
|
28
28
|
# Interface module - note: print_results_long is imported directly in results.py
|
29
|
-
|
29
|
+
|
30
|
+
__all__ = [
|
31
|
+
"TemplateLoader",
|
32
|
+
"PrettyList",
|
33
|
+
"create_restricted_function",
|
34
|
+
"remove_edsl_version",
|
35
|
+
"extract_variable_names",
|
36
|
+
"clean_json",
|
37
|
+
"dict_hash",
|
38
|
+
"hash_value",
|
39
|
+
"repair_json",
|
40
|
+
"create_valid_var_name",
|
41
|
+
"random_string",
|
42
|
+
"shorten_string",
|
43
|
+
"is_gzipped",
|
44
|
+
"sync_wrapper",
|
45
|
+
"jupyter_nb_handler",
|
46
|
+
"is_notebook",
|
47
|
+
"is_valid_variable_name",
|
48
|
+
"sanitize_string"
|
49
|
+
]
|
30
50
|
|
edsl/utilities/decorators.py
CHANGED
@@ -69,7 +69,7 @@ class MarkdownToDocx:
|
|
69
69
|
|
70
70
|
try:
|
71
71
|
# Run pandoc command
|
72
|
-
|
72
|
+
subprocess.run(
|
73
73
|
cmd,
|
74
74
|
input=self.markdown_content,
|
75
75
|
text=True,
|
@@ -115,7 +115,7 @@ class MarkdownToDocx:
|
|
115
115
|
cmd = ["pandoc", "--print-default-data-file", "reference.docx"]
|
116
116
|
|
117
117
|
with open(output_path, "wb") as f:
|
118
|
-
|
118
|
+
subprocess.run(cmd, stdout=f, check=True)
|
119
119
|
return True
|
120
120
|
except subprocess.CalledProcessError as e:
|
121
121
|
print(f"Error creating template: {e.stderr}")
|