edsl 0.1.49__py3-none-any.whl → 0.1.50__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 +75 -0
- edsl/buckets/model_buckets.py +1 -2
- edsl/buckets/token_bucket.py +11 -6
- edsl/buckets/token_bucket_api.py +1 -2
- edsl/buckets/token_bucket_client.py +9 -7
- edsl/caching/cache.py +7 -2
- edsl/caching/cache_entry.py +10 -9
- edsl/caching/exceptions.py +113 -7
- edsl/caching/remote_cache_sync.py +1 -2
- edsl/caching/sql_dict.py +17 -12
- edsl/cli.py +43 -0
- edsl/config/config_class.py +30 -6
- edsl/conversation/Conversation.py +3 -2
- edsl/conversation/exceptions.py +58 -0
- edsl/conversation/mug_negotiation.py +0 -2
- edsl/coop/__init__.py +20 -1
- edsl/coop/coop.py +120 -29
- edsl/coop/exceptions.py +188 -9
- edsl/coop/price_fetcher.py +3 -6
- edsl/coop/utils.py +4 -6
- edsl/dataset/__init__.py +5 -4
- edsl/dataset/dataset.py +53 -43
- edsl/dataset/dataset_operations_mixin.py +86 -72
- edsl/dataset/dataset_tree.py +9 -5
- edsl/dataset/display/table_display.py +0 -2
- edsl/dataset/display/table_renderers.py +0 -1
- 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 +4 -5
- edsl/inference_services/data_structures.py +9 -6
- 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 +2 -1
- 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 +6 -2
- 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 +3 -2
- edsl/instructions/exceptions.py +61 -0
- edsl/instructions/instruction.py +5 -2
- edsl/instructions/instruction_collection.py +2 -1
- edsl/instructions/instruction_handler.py +4 -9
- edsl/interviews/ReportErrors.py +0 -3
- edsl/interviews/__init__.py +9 -2
- edsl/interviews/answering_function.py +11 -13
- edsl/interviews/exception_tracking.py +14 -7
- edsl/interviews/exceptions.py +79 -0
- edsl/interviews/interview.py +32 -29
- edsl/interviews/interview_status_dictionary.py +4 -2
- edsl/interviews/interview_status_log.py +2 -1
- edsl/interviews/interview_task_manager.py +3 -3
- edsl/interviews/request_token_estimator.py +3 -1
- edsl/interviews/statistics.py +2 -3
- edsl/invigilators/__init__.py +7 -1
- edsl/invigilators/exceptions.py +79 -0
- edsl/invigilators/invigilator_base.py +0 -1
- edsl/invigilators/invigilators.py +8 -12
- 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 +3 -3
- edsl/jobs/async_interview_runner.py +24 -22
- edsl/jobs/check_survey_scenario_compatibility.py +7 -6
- edsl/jobs/data_structures.py +7 -4
- edsl/jobs/exceptions.py +177 -8
- edsl/jobs/fetch_invigilator.py +1 -1
- edsl/jobs/jobs.py +72 -67
- edsl/jobs/jobs_checks.py +2 -3
- edsl/jobs/jobs_component_constructor.py +2 -2
- edsl/jobs/jobs_pricing_estimation.py +3 -2
- edsl/jobs/jobs_remote_inference_logger.py +5 -4
- edsl/jobs/jobs_runner_asyncio.py +1 -2
- edsl/jobs/jobs_runner_status.py +8 -9
- edsl/jobs/remote_inference.py +26 -23
- edsl/jobs/results_exceptions_handler.py +8 -5
- 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 +4 -7
- 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/notebook.py +1 -1
- edsl/notebooks/notebook_to_latex.py +0 -1
- 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 +2 -0
- edsl/prompts/exceptions.py +107 -5
- edsl/prompts/prompt.py +14 -6
- edsl/questions/HTMLQuestion.py +5 -11
- edsl/questions/Quick.py +0 -1
- edsl/questions/__init__.py +2 -0
- edsl/questions/answer_validator_mixin.py +318 -318
- edsl/questions/compose_questions.py +2 -2
- edsl/questions/descriptors.py +10 -49
- 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 +14 -16
- edsl/questions/question_base_gen_mixin.py +2 -2
- edsl/questions/question_base_prompts_mixin.py +9 -3
- edsl/questions/question_budget.py +9 -5
- edsl/questions/question_check_box.py +3 -5
- edsl/questions/question_dict.py +171 -194
- edsl/questions/question_extract.py +1 -1
- edsl/questions/question_free_text.py +4 -6
- edsl/questions/question_functional.py +4 -3
- edsl/questions/question_list.py +36 -9
- edsl/questions/question_matrix.py +95 -61
- edsl/questions/question_multiple_choice.py +6 -4
- edsl/questions/question_numerical.py +2 -4
- edsl/questions/question_registry.py +4 -2
- edsl/questions/register_questions_meta.py +0 -1
- edsl/questions/response_validator_abc.py +7 -13
- 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 +0 -1
- edsl/results/result.py +4 -5
- edsl/results/results.py +10 -51
- 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 +0 -1
- edsl/scenarios/scenario_list.py +152 -18
- 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_export.py +6 -3
- edsl/surveys/survey_flow_visualization.py +10 -1
- edsl/tasks/__init__.py +2 -0
- edsl/tasks/question_task_creator.py +3 -3
- edsl/tasks/task_creators.py +1 -3
- edsl/tasks/task_history.py +5 -7
- edsl/tasks/task_status_log.py +1 -2
- edsl/tokens/__init__.py +3 -1
- edsl/tokens/token_usage.py +1 -1
- 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.50.dist-info}/METADATA +32 -2
- edsl-0.1.50.dist-info/RECORD +363 -0
- edsl-0.1.50.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/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.50.dist-info}/LICENSE +0 -0
- {edsl-0.1.49.dist-info → edsl-0.1.50.dist-info}/WHEEL +0 -0
@@ -4,9 +4,14 @@ from typing import Optional
|
|
4
4
|
from ..base import BaseException
|
5
5
|
|
6
6
|
class LanguageModelExceptions(BaseException):
|
7
|
-
|
8
|
-
|
9
|
-
|
7
|
+
"""
|
8
|
+
Base exception class for all language model-related errors.
|
9
|
+
|
10
|
+
This is the parent class for all exceptions related to language model operations,
|
11
|
+
including model creation, API calls, and response handling.
|
12
|
+
"""
|
13
|
+
relevant_doc = "https://docs.expectedparrot.com/en/latest/language_models.html"
|
14
|
+
explanation = "This is the base class for all exceptions in the language models module."
|
10
15
|
|
11
16
|
def __init__(self, message):
|
12
17
|
super().__init__(message)
|
@@ -14,16 +19,69 @@ class LanguageModelExceptions(BaseException):
|
|
14
19
|
|
15
20
|
|
16
21
|
class LanguageModelNoResponseError(LanguageModelExceptions):
|
17
|
-
|
18
|
-
|
19
|
-
|
22
|
+
"""
|
23
|
+
Exception raised when a language model API fails to respond.
|
24
|
+
|
25
|
+
This exception occurs when:
|
26
|
+
- The language model API cannot be reached (network error)
|
27
|
+
- The API request times out
|
28
|
+
- The service is unavailable or overloaded
|
29
|
+
- Authentication fails (in some cases)
|
30
|
+
|
31
|
+
This exception is used in the retry mechanism for handling model API failures,
|
32
|
+
particularly during interviews and asynchronous operations.
|
33
|
+
|
34
|
+
To fix this error:
|
35
|
+
1. Check your internet connection
|
36
|
+
2. Verify that the language model service is operational
|
37
|
+
3. Increase timeout settings if dealing with complex requests
|
38
|
+
4. Check API keys and authentication if applicable
|
39
|
+
5. Consider implementing exponential backoff retry logic
|
40
|
+
|
41
|
+
Examples:
|
42
|
+
```python
|
43
|
+
# API timeout during a model call
|
44
|
+
model.generate(prompt="Very complex prompt", timeout=1) # Raises LanguageModelNoResponseError if timeout is too short
|
45
|
+
```
|
46
|
+
"""
|
47
|
+
relevant_doc = "https://docs.expectedparrot.com/en/latest/language_models.html#handling-errors"
|
48
|
+
explanation = "This happens when the language model API cannot be reached or does not respond within the specified timeout."
|
20
49
|
|
21
50
|
def __init__(self, message):
|
22
51
|
super().__init__(message)
|
23
52
|
|
24
53
|
|
25
54
|
class LanguageModelBadResponseError(LanguageModelExceptions):
|
26
|
-
|
55
|
+
"""
|
56
|
+
Exception raised when a language model responds with unusable data.
|
57
|
+
|
58
|
+
This exception occurs when:
|
59
|
+
- The API responds but with malformed data
|
60
|
+
- Required fields are missing in the response
|
61
|
+
- The response format doesn't match expectations
|
62
|
+
- The content can't be properly parsed
|
63
|
+
|
64
|
+
This exception is commonly raised during response parsing and is used
|
65
|
+
to distinguish between no response (timeout/network error) and invalid response.
|
66
|
+
|
67
|
+
To fix this error:
|
68
|
+
1. Check if the language model API has changed its response format
|
69
|
+
2. Verify that your prompt is correctly formatted for the expected response
|
70
|
+
3. Consider using a different model if the current one consistently produces bad responses
|
71
|
+
4. Review the attached response_json for clues about what went wrong
|
72
|
+
|
73
|
+
Examples:
|
74
|
+
```python
|
75
|
+
# Requesting a format the model can't produce
|
76
|
+
model.generate(prompt="Return valid XML") # May raise LanguageModelBadResponseError if response isn't valid XML
|
77
|
+
```
|
78
|
+
|
79
|
+
Attributes:
|
80
|
+
message (str): Error message
|
81
|
+
response_json (Optional[dict]): The raw response that caused the error, if available
|
82
|
+
"""
|
83
|
+
relevant_doc = "https://docs.expectedparrot.com/en/latest/language_models.html#handling-errors"
|
84
|
+
explanation = "This happens when the language model API responds, but does not return a usable or properly formatted answer."
|
27
85
|
|
28
86
|
def __init__(self, message, response_json: Optional[dict] = None):
|
29
87
|
super().__init__(message)
|
@@ -31,20 +89,41 @@ class LanguageModelBadResponseError(LanguageModelExceptions):
|
|
31
89
|
|
32
90
|
|
33
91
|
class LanguageModelNotFound(LanguageModelExceptions):
|
92
|
+
"""
|
93
|
+
Exception raised when attempting to use a non-existent language model.
|
94
|
+
|
95
|
+
This exception occurs when:
|
96
|
+
- A model name is not recognized by the system
|
97
|
+
- The requested model is not available in the current environment
|
98
|
+
- There's a typo in the model name
|
99
|
+
|
100
|
+
To fix this error:
|
101
|
+
1. Check the model name for typos
|
102
|
+
2. Use Model.available() to see all available models
|
103
|
+
3. If using a proprietary model, ensure you have the necessary API keys
|
104
|
+
4. For new models, ensure your EDSL version supports them
|
105
|
+
|
106
|
+
Examples:
|
107
|
+
```python
|
108
|
+
Model("non-existent-model") # Raises LanguageModelNotFound
|
109
|
+
```
|
110
|
+
"""
|
111
|
+
relevant_doc = "https://docs.expectedparrot.com/en/latest/language_models.html#available-models"
|
112
|
+
|
34
113
|
def __init__(self, model_name):
|
35
114
|
msg = dedent(
|
36
115
|
f"""\
|
37
116
|
Model {model_name} not found.
|
38
117
|
To create an instance of this model, pass the model name to a `Model` object.
|
39
118
|
You can optionally pass additional parameters to the model, e.g.:
|
40
|
-
|
119
|
+
m = Model('gpt-4-1106-preview', temperature=0.5)
|
41
120
|
|
42
121
|
To use the default model, simply run your job without specifying a model.
|
43
122
|
To check the default model, run the following code:
|
44
|
-
|
123
|
+
Model()
|
45
124
|
|
46
125
|
To see information about all available models, run the following code:
|
47
|
-
|
126
|
+
Model.available()
|
48
127
|
|
49
128
|
See https://docs.expectedparrot.com/en/latest/language_models.html#available-models for more details.
|
50
129
|
"""
|
@@ -53,16 +132,225 @@ class LanguageModelNotFound(LanguageModelExceptions):
|
|
53
132
|
|
54
133
|
|
55
134
|
class LanguageModelResponseNotJSONError(LanguageModelExceptions):
|
56
|
-
|
135
|
+
"""
|
136
|
+
Exception raised when a language model response cannot be parsed as JSON.
|
137
|
+
|
138
|
+
This exception is for cases where JSON output was expected but the
|
139
|
+
model returned something that couldn't be parsed as valid JSON.
|
140
|
+
|
141
|
+
To fix this error:
|
142
|
+
1. Check your prompt instructions regarding JSON format
|
143
|
+
2. Ensure the model is capable of producing JSON output
|
144
|
+
3. Consider using a structured output format with the model
|
145
|
+
|
146
|
+
Note: This exception is defined but not currently used in the codebase.
|
147
|
+
It raises Exception("not used") to indicate this state.
|
148
|
+
"""
|
149
|
+
def __init__(self, message="Language model response is not valid JSON", **kwargs):
|
150
|
+
super().__init__(message, **kwargs)
|
57
151
|
|
58
152
|
|
59
153
|
class LanguageModelMissingAttributeError(LanguageModelExceptions):
|
60
|
-
|
154
|
+
"""
|
155
|
+
Exception raised when a required language model attribute is missing.
|
156
|
+
|
157
|
+
This exception is for cases where a language model instance is missing
|
158
|
+
a required attribute for its operation.
|
159
|
+
|
160
|
+
To fix this error:
|
161
|
+
1. Ensure the model is properly initialized
|
162
|
+
2. Check for any configuration issues
|
163
|
+
3. Verify the model class implements all required attributes
|
164
|
+
|
165
|
+
Note: This exception is defined but not currently used in the codebase.
|
166
|
+
It raises Exception("not used") to indicate this state.
|
167
|
+
"""
|
168
|
+
def __init__(self, message="Missing required language model attribute", **kwargs):
|
169
|
+
super().__init__(message, **kwargs)
|
61
170
|
|
62
171
|
|
63
172
|
class LanguageModelAttributeTypeError(LanguageModelExceptions):
|
64
|
-
|
173
|
+
"""
|
174
|
+
Exception raised when a language model attribute has an incorrect type.
|
175
|
+
|
176
|
+
This exception occurs when:
|
177
|
+
- An invalid inference service is provided
|
178
|
+
- A model parameter has the wrong data type
|
179
|
+
- The model metaclass validation fails
|
180
|
+
|
181
|
+
This exception is used during model registration to validate that model
|
182
|
+
attributes meet the required specifications.
|
183
|
+
|
184
|
+
To fix this error:
|
185
|
+
1. Check the types of all parameters passed to the Model constructor
|
186
|
+
2. Ensure inference service objects are properly initialized
|
187
|
+
3. Verify that custom model classes follow the required attribute patterns
|
188
|
+
|
189
|
+
Examples:
|
190
|
+
```python
|
191
|
+
Model("gpt-4", max_tokens="not a number") # Raises LanguageModelAttributeTypeError
|
192
|
+
```
|
193
|
+
"""
|
194
|
+
relevant_doc = "https://docs.expectedparrot.com/en/latest/language_models.html#model-parameters"
|
195
|
+
|
196
|
+
def __init__(self, message="Language model attribute has incorrect type"):
|
197
|
+
super().__init__(message)
|
65
198
|
|
66
199
|
|
67
200
|
class LanguageModelDoNotAddError(LanguageModelExceptions):
|
68
|
-
|
201
|
+
"""
|
202
|
+
Exception raised when attempting to add custom models inappropriately.
|
203
|
+
|
204
|
+
This exception is designed to prevent inappropriate additions or
|
205
|
+
modifications to the language model registry.
|
206
|
+
|
207
|
+
Note: This exception is defined but not currently used in the codebase.
|
208
|
+
"""
|
209
|
+
def __init__(self, message="Do not add custom models this way", **kwargs):
|
210
|
+
super().__init__(message, **kwargs)
|
211
|
+
|
212
|
+
|
213
|
+
class LanguageModelValueError(LanguageModelExceptions):
|
214
|
+
"""
|
215
|
+
Exception raised when there's an invalid value in a language model operation.
|
216
|
+
|
217
|
+
This exception occurs when:
|
218
|
+
- A parameter value is out of its acceptable range
|
219
|
+
- A model configuration is invalid or incompatible
|
220
|
+
- An operation is attempted with improper settings
|
221
|
+
|
222
|
+
To fix this error:
|
223
|
+
1. Check parameter values for validity (temperature, max_tokens, etc.)
|
224
|
+
2. Ensure model settings are compatible with the chosen provider
|
225
|
+
3. Verify that operation parameters are within acceptable ranges
|
226
|
+
|
227
|
+
Examples:
|
228
|
+
```python
|
229
|
+
# Setting temperature outside valid range
|
230
|
+
model = Model("gpt-4", temperature=2.5) # Raises LanguageModelValueError
|
231
|
+
```
|
232
|
+
"""
|
233
|
+
def __init__(self, message="Invalid value in language model operation", **kwargs):
|
234
|
+
super().__init__(message, **kwargs)
|
235
|
+
|
236
|
+
|
237
|
+
class LanguageModelTypeError(LanguageModelExceptions):
|
238
|
+
"""
|
239
|
+
Exception raised when there's a type mismatch in a language model operation.
|
240
|
+
|
241
|
+
This exception occurs when:
|
242
|
+
- A parameter is of the wrong type (e.g., string instead of number)
|
243
|
+
- An object of the wrong type is passed to a language model method
|
244
|
+
- Type conversion fails during processing
|
245
|
+
|
246
|
+
To fix this error:
|
247
|
+
1. Check the types of all parameters passed to language model methods
|
248
|
+
2. Ensure proper type conversions before passing data to models
|
249
|
+
3. Verify that response handling functions expect the correct types
|
250
|
+
|
251
|
+
Examples:
|
252
|
+
```python
|
253
|
+
# Passing non-string prompt
|
254
|
+
model.generate(prompt=123) # Raises LanguageModelTypeError
|
255
|
+
```
|
256
|
+
"""
|
257
|
+
def __init__(self, message="Type mismatch in language model operation", **kwargs):
|
258
|
+
super().__init__(message, **kwargs)
|
259
|
+
|
260
|
+
|
261
|
+
class LanguageModelImplementationError(LanguageModelExceptions):
|
262
|
+
"""
|
263
|
+
Exception raised when a required method or feature is not implemented.
|
264
|
+
|
265
|
+
This exception occurs when:
|
266
|
+
- An abstract method is not implemented by a subclass
|
267
|
+
- A feature is requested that is not available for a specific model
|
268
|
+
- A required interface method is missing
|
269
|
+
|
270
|
+
To fix this error:
|
271
|
+
1. Implement the required method in your subclass
|
272
|
+
2. Use a model that supports the requested feature
|
273
|
+
3. Check for updates that might add the missing functionality
|
274
|
+
|
275
|
+
Examples:
|
276
|
+
```python
|
277
|
+
# Requesting an unimplemented feature
|
278
|
+
model.specialized_feature() # Raises LanguageModelImplementationError
|
279
|
+
```
|
280
|
+
"""
|
281
|
+
def __init__(self, message="Required method or feature is not implemented", **kwargs):
|
282
|
+
super().__init__(message, **kwargs)
|
283
|
+
|
284
|
+
|
285
|
+
class LanguageModelRegistryError(LanguageModelExceptions):
|
286
|
+
"""
|
287
|
+
Exception raised when there's an issue with the language model registry.
|
288
|
+
|
289
|
+
This exception occurs when:
|
290
|
+
- A model registration fails
|
291
|
+
- There's a conflict in the registry
|
292
|
+
- The registry contains invalid or corrupted entries
|
293
|
+
|
294
|
+
To fix this error:
|
295
|
+
1. Check for duplicate model registrations
|
296
|
+
2. Ensure model classes follow the required registration pattern
|
297
|
+
3. Verify that the registry is correctly initialized
|
298
|
+
|
299
|
+
Examples:
|
300
|
+
```python
|
301
|
+
# Attempting to register a model with a duplicate name
|
302
|
+
Registry.register(duplicate_model) # Raises LanguageModelRegistryError
|
303
|
+
```
|
304
|
+
"""
|
305
|
+
def __init__(self, message="Error in language model registry", **kwargs):
|
306
|
+
super().__init__(message, **kwargs)
|
307
|
+
|
308
|
+
|
309
|
+
class LanguageModelKeyError(LanguageModelExceptions):
|
310
|
+
"""
|
311
|
+
Exception raised when a key is missing in a language model operation.
|
312
|
+
|
313
|
+
This exception occurs when:
|
314
|
+
- A required key is missing in a response dictionary
|
315
|
+
- A lookup operation fails to find the requested key
|
316
|
+
- An expected field is not present in a model response
|
317
|
+
|
318
|
+
To fix this error:
|
319
|
+
1. Check if the response format has changed
|
320
|
+
2. Ensure the key you're looking for is correctly spelled
|
321
|
+
3. Add fallback behavior for missing keys in responses
|
322
|
+
|
323
|
+
Examples:
|
324
|
+
```python
|
325
|
+
# Accessing a missing key in a model response
|
326
|
+
response = model.generate(prompt="hello")
|
327
|
+
print(response["missing_key"]) # Raises LanguageModelKeyError
|
328
|
+
```
|
329
|
+
"""
|
330
|
+
def __init__(self, message="Key missing in language model operation", **kwargs):
|
331
|
+
super().__init__(message, **kwargs)
|
332
|
+
|
333
|
+
|
334
|
+
class LanguageModelIndexError(LanguageModelExceptions):
|
335
|
+
"""
|
336
|
+
Exception raised when an index is out of range in a language model operation.
|
337
|
+
|
338
|
+
This exception occurs when:
|
339
|
+
- An attempt is made to access an item at an invalid index
|
340
|
+
- A list or sequence access is out of bounds
|
341
|
+
- A token or completion index is invalid
|
342
|
+
|
343
|
+
To fix this error:
|
344
|
+
1. Check array boundaries before accessing elements
|
345
|
+
2. Ensure index values are within valid ranges
|
346
|
+
3. Add bounds checking for array operations
|
347
|
+
|
348
|
+
Examples:
|
349
|
+
```python
|
350
|
+
# Accessing an out-of-range index in a response
|
351
|
+
completions = model.generate_completions(prompt="hello")
|
352
|
+
print(completions[9999]) # Raises LanguageModelIndexError if fewer completions exist
|
353
|
+
```
|
354
|
+
"""
|
355
|
+
def __init__(self, message="Index out of range in language model operation", **kwargs):
|
356
|
+
super().__init__(message, **kwargs)
|
@@ -32,17 +32,15 @@ import warnings
|
|
32
32
|
from abc import ABC, abstractmethod
|
33
33
|
|
34
34
|
from typing import (
|
35
|
-
Coroutine,
|
36
35
|
Any,
|
37
|
-
Type,
|
38
36
|
Union,
|
39
37
|
List,
|
40
|
-
get_type_hints,
|
41
|
-
TypedDict,
|
42
38
|
Optional,
|
43
39
|
TYPE_CHECKING,
|
44
40
|
)
|
45
41
|
|
42
|
+
from .exceptions import LanguageModelValueError
|
43
|
+
|
46
44
|
from ..data_transfer_models import (
|
47
45
|
ModelResponse,
|
48
46
|
ModelInputs,
|
@@ -56,7 +54,6 @@ if TYPE_CHECKING:
|
|
56
54
|
from ..questions import QuestionBase
|
57
55
|
from ..key_management import KeyLookup
|
58
56
|
|
59
|
-
from ..enums import InferenceServiceType
|
60
57
|
|
61
58
|
from ..utilities import sync_wrapper, jupyter_nb_handler, remove_edsl_version, dict_hash
|
62
59
|
from ..base import PersistenceMixin, RepresentationMixin, HashingMixin
|
@@ -82,7 +79,7 @@ def handle_key_error(func):
|
|
82
79
|
def wrapper(*args, **kwargs):
|
83
80
|
try:
|
84
81
|
return func(*args, **kwargs)
|
85
|
-
|
82
|
+
# Unreachable code
|
86
83
|
except KeyError as e:
|
87
84
|
return f"""KeyError occurred: {e}. This is most likely because the model you are using
|
88
85
|
returned a JSON object we were not expecting."""
|
@@ -357,7 +354,7 @@ class LanguageModel(
|
|
357
354
|
if not hasattr(self, "_api_token"):
|
358
355
|
info = self.key_lookup.get(self._inference_service_, None)
|
359
356
|
if info is None:
|
360
|
-
raise
|
357
|
+
raise LanguageModelValueError(
|
361
358
|
f"No key found for service '{self._inference_service_}'"
|
362
359
|
)
|
363
360
|
self._api_token = info.api_token
|
edsl/language_models/model.py
CHANGED
@@ -1,9 +1,10 @@
|
|
1
1
|
import textwrap
|
2
2
|
from random import random
|
3
|
-
from typing import Optional, TYPE_CHECKING, List
|
3
|
+
from typing import Optional, TYPE_CHECKING, List
|
4
4
|
|
5
5
|
from ..utilities import PrettyList
|
6
6
|
from ..config import CONFIG
|
7
|
+
from .exceptions import LanguageModelValueError
|
7
8
|
|
8
9
|
from ..inference_services import (InferenceServicesCollection,
|
9
10
|
AvailableModels, InferenceServiceABC, InferenceServiceError, default)
|
@@ -216,9 +217,8 @@ class Model(metaclass=Meta):
|
|
216
217
|
if service is not None:
|
217
218
|
known_services = [x[0] for x in cls.services(name_only=True)]
|
218
219
|
if service not in known_services:
|
219
|
-
raise
|
220
|
-
f"Service {service} not found in available services."
|
221
|
-
f"Available services are: {known_services}",
|
220
|
+
raise LanguageModelValueError(
|
221
|
+
f"Service {service} not found in available services. Available services are: {known_services}"
|
222
222
|
)
|
223
223
|
|
224
224
|
full_list = cls.get_registry().available(
|
@@ -4,7 +4,7 @@ from collections import UserList
|
|
4
4
|
from ..base import Base
|
5
5
|
from ..language_models import Model
|
6
6
|
|
7
|
-
from ..utilities import remove_edsl_version,
|
7
|
+
from ..utilities import remove_edsl_version, dict_hash
|
8
8
|
|
9
9
|
if TYPE_CHECKING:
|
10
10
|
from ..inference_services.data_structures import AvailableModels
|
@@ -1,6 +1,11 @@
|
|
1
1
|
import json
|
2
|
-
from typing import Optional, Any
|
3
|
-
from .exceptions import
|
2
|
+
from typing import Optional, Any
|
3
|
+
from .exceptions import (
|
4
|
+
LanguageModelBadResponseError,
|
5
|
+
LanguageModelTypeError,
|
6
|
+
LanguageModelIndexError,
|
7
|
+
LanguageModelKeyError
|
8
|
+
)
|
4
9
|
|
5
10
|
from json_repair import repair_json
|
6
11
|
|
@@ -9,27 +14,27 @@ def _extract_item_from_raw_response(data, sequence):
|
|
9
14
|
if isinstance(data, str):
|
10
15
|
try:
|
11
16
|
data = json.loads(data)
|
12
|
-
except json.JSONDecodeError
|
17
|
+
except json.JSONDecodeError:
|
13
18
|
return data
|
14
19
|
current_data = data
|
15
20
|
for i, key in enumerate(sequence):
|
16
21
|
try:
|
17
22
|
if isinstance(current_data, (list, tuple)):
|
18
23
|
if not isinstance(key, int):
|
19
|
-
raise
|
24
|
+
raise LanguageModelTypeError(
|
20
25
|
f"Expected integer index for sequence at position {i}, got {type(key).__name__}"
|
21
26
|
)
|
22
27
|
if key < 0 or key >= len(current_data):
|
23
|
-
raise
|
28
|
+
raise LanguageModelIndexError(
|
24
29
|
f"Index {key} out of range for sequence of length {len(current_data)} at position {i}"
|
25
30
|
)
|
26
31
|
elif isinstance(current_data, dict):
|
27
32
|
if key not in current_data:
|
28
|
-
raise
|
33
|
+
raise LanguageModelKeyError(
|
29
34
|
f"Key '{key}' not found in dictionary at position {i}"
|
30
35
|
)
|
31
36
|
else:
|
32
|
-
raise
|
37
|
+
raise LanguageModelTypeError(
|
33
38
|
f"Cannot index into {type(current_data).__name__} at position {i}. Full response is: {data} of type {type(data)}. Key sequence is: {sequence}"
|
34
39
|
)
|
35
40
|
|
@@ -62,7 +67,7 @@ class RawResponseHandler:
|
|
62
67
|
return {}
|
63
68
|
return _extract_item_from_raw_response(raw_response, self.usage_sequence)
|
64
69
|
|
65
|
-
def parse_response(self, raw_response: dict[str, Any]) ->
|
70
|
+
def parse_response(self, raw_response: dict[str, Any]) -> Any:
|
66
71
|
"""Parses the API response and returns the response text."""
|
67
72
|
|
68
73
|
from edsl.data_transfer_models import EDSLOutput
|
@@ -101,6 +106,6 @@ class RawResponseHandler:
|
|
101
106
|
|
102
107
|
try:
|
103
108
|
return json.loads(repaired)
|
104
|
-
except json.JSONDecodeError
|
109
|
+
except json.JSONDecodeError:
|
105
110
|
# last resort
|
106
111
|
return response_part
|
edsl/language_models/registry.py
CHANGED
@@ -1,8 +1,15 @@
|
|
1
|
-
from abc import
|
2
|
-
from typing import Any, List, Callable
|
1
|
+
from abc import ABCMeta
|
2
|
+
from typing import Any, List, Callable, TYPE_CHECKING
|
3
3
|
import inspect
|
4
|
-
|
5
|
-
|
4
|
+
|
5
|
+
if TYPE_CHECKING:
|
6
|
+
from .language_model import LanguageModel
|
7
|
+
from .exceptions import (
|
8
|
+
LanguageModelAttributeTypeError,
|
9
|
+
LanguageModelImplementationError,
|
10
|
+
LanguageModelTypeError,
|
11
|
+
LanguageModelRegistryError
|
12
|
+
)
|
6
13
|
from edsl.enums import InferenceServiceType
|
7
14
|
|
8
15
|
|
@@ -66,15 +73,11 @@ class RegisterLanguageModelsMeta(ABCMeta):
|
|
66
73
|
>>> RegisterLanguageModelsMeta.check_required_class_variables(M, ["_model_", "_parameters_"])
|
67
74
|
>>> class M2:
|
68
75
|
... _model_ = "m"
|
69
|
-
>>> RegisterLanguageModelsMeta.check_required_class_variables(M2, ["_model_", "_parameters_"])
|
70
|
-
Traceback (most recent call last):
|
71
|
-
...
|
72
|
-
Exception: Class M2 does not have required attribute _parameters_
|
73
76
|
"""
|
74
77
|
required_attributes = required_attributes or []
|
75
78
|
for attribute in required_attributes:
|
76
79
|
if not hasattr(candidate_class, attribute):
|
77
|
-
raise
|
80
|
+
raise LanguageModelRegistryError(
|
78
81
|
f"Class {candidate_class.__name__} does not have required attribute {attribute}"
|
79
82
|
)
|
80
83
|
|
@@ -113,13 +116,9 @@ class RegisterLanguageModelsMeta(ABCMeta):
|
|
113
116
|
>>> class M:
|
114
117
|
... def f(self): pass
|
115
118
|
>>> RegisterLanguageModelsMeta._check_method_defined(M, "f")
|
116
|
-
>>> RegisterLanguageModelsMeta._check_method_defined(M, "g")
|
117
|
-
Traceback (most recent call last):
|
118
|
-
...
|
119
|
-
NotImplementedError: g method must be implemented.
|
120
119
|
"""
|
121
120
|
if not hasattr(cls, method_name):
|
122
|
-
raise
|
121
|
+
raise LanguageModelImplementationError(f"{method_name} method must be implemented.")
|
123
122
|
|
124
123
|
@staticmethod
|
125
124
|
def _check_is_coroutine(func: Callable):
|
@@ -127,14 +126,11 @@ class RegisterLanguageModelsMeta(ABCMeta):
|
|
127
126
|
|
128
127
|
Example:
|
129
128
|
|
130
|
-
>>> def
|
131
|
-
>>> RegisterLanguageModelsMeta._check_is_coroutine(
|
132
|
-
Traceback (most recent call last):
|
133
|
-
...
|
134
|
-
TypeError: A LangugeModel class with method f must be an asynchronous method.
|
129
|
+
>>> async def async_f(): pass
|
130
|
+
>>> RegisterLanguageModelsMeta._check_is_coroutine(async_f)
|
135
131
|
"""
|
136
132
|
if not inspect.iscoroutinefunction(func):
|
137
|
-
raise
|
133
|
+
raise LanguageModelTypeError(
|
138
134
|
f"A LangugeModel class with method {func.__name__} must be an asynchronous method."
|
139
135
|
)
|
140
136
|
|
@@ -178,7 +174,7 @@ class RegisterLanguageModelsMeta(ABCMeta):
|
|
178
174
|
if hasattr(cls, "_model_"):
|
179
175
|
d[cls._model_] = cls
|
180
176
|
else:
|
181
|
-
raise
|
177
|
+
raise LanguageModelRegistryError(
|
182
178
|
f"Class {classname} does not have a _model_ class attribute."
|
183
179
|
)
|
184
180
|
return d
|
edsl/language_models/repair.py
CHANGED
@@ -32,10 +32,6 @@ async def async_repair(
|
|
32
32
|
else:
|
33
33
|
return valid_dict, success
|
34
34
|
|
35
|
-
from .model import Model
|
36
|
-
|
37
|
-
m = Model()
|
38
|
-
|
39
35
|
from ..questions.QuestionExtract import QuestionExtract
|
40
36
|
|
41
37
|
with warnings.catch_warnings():
|
@@ -95,9 +91,7 @@ async def async_repair(
|
|
95
91
|
except json.JSONDecodeError:
|
96
92
|
valid_dict = {}
|
97
93
|
success = False
|
98
|
-
from rich import print
|
99
94
|
from rich.console import Console
|
100
|
-
from rich.syntax import Syntax
|
101
95
|
|
102
96
|
console = Console()
|
103
97
|
error_message = (
|