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
@@ -1,9 +1,8 @@
|
|
1
1
|
from __future__ import annotations
|
2
2
|
from typing import Optional
|
3
|
-
from
|
4
|
-
from
|
5
|
-
|
6
|
-
from ..decorators import inject_exception
|
3
|
+
from .descriptors import QuestionOptionsDescriptor
|
4
|
+
from .question_multiple_choice import QuestionMultipleChoice
|
5
|
+
from .decorators import inject_exception
|
7
6
|
|
8
7
|
|
9
8
|
class QuestionYesNo(QuestionMultipleChoice):
|
@@ -2,7 +2,6 @@ from __future__ import annotations
|
|
2
2
|
from abc import ABCMeta
|
3
3
|
import inspect
|
4
4
|
|
5
|
-
from ..enums import QuestionType
|
6
5
|
from .exceptions import QuestionMissingTypeError, QuestionBadTypeError
|
7
6
|
|
8
7
|
class RegisterQuestionsMeta(ABCMeta):
|
@@ -63,7 +62,8 @@ class RegisterQuestionsMeta(ABCMeta):
|
|
63
62
|
if hasattr(cls, "question_type"):
|
64
63
|
d[cls.question_type] = cls
|
65
64
|
else:
|
66
|
-
|
65
|
+
from .exceptions import QuestionMissingTypeError
|
66
|
+
raise QuestionMissingTypeError(
|
67
67
|
f"Class {classname} does not have a question_type class attribute"
|
68
68
|
)
|
69
69
|
return d
|
@@ -1,7 +1,7 @@
|
|
1
|
-
from abc import ABC
|
2
|
-
from typing import Optional,
|
1
|
+
from abc import ABC
|
2
|
+
from typing import Optional, List, TYPE_CHECKING
|
3
3
|
|
4
|
-
from pydantic import BaseModel,
|
4
|
+
from pydantic import BaseModel, ValidationError
|
5
5
|
|
6
6
|
from .exceptions import QuestionAnswerValidationError
|
7
7
|
from .ExceptionExplainer import ExceptionExplainer
|
@@ -22,7 +22,8 @@ class ResponseValidatorABC(ABC):
|
|
22
22
|
required_class_vars = ["required_params", "valid_examples", "invalid_examples"]
|
23
23
|
for var in required_class_vars:
|
24
24
|
if not hasattr(cls, var):
|
25
|
-
|
25
|
+
from .exceptions import QuestionValueError
|
26
|
+
raise QuestionValueError(f"Class {cls.__name__} must have a '{var}' attribute.")
|
26
27
|
|
27
28
|
def __init__(
|
28
29
|
self,
|
@@ -41,7 +42,8 @@ class ResponseValidatorABC(ABC):
|
|
41
42
|
param for param in self.required_params if param not in kwargs
|
42
43
|
]
|
43
44
|
if missing_params:
|
44
|
-
|
45
|
+
from .exceptions import QuestionValueError
|
46
|
+
raise QuestionValueError(
|
45
47
|
f"Missing required parameters: {', '.join(missing_params)}"
|
46
48
|
)
|
47
49
|
|
@@ -75,8 +77,12 @@ class ResponseValidatorABC(ABC):
|
|
75
77
|
ConstrainedNumericResponse(answer=42, comment=None, generated_tokens=None)
|
76
78
|
"""
|
77
79
|
try:
|
78
|
-
|
79
|
-
|
80
|
+
# Use model_validate instead of direct instantiation
|
81
|
+
return self.response_model.model_validate(data)
|
82
|
+
except (ValidationError, QuestionAnswerValidationError) as e:
|
83
|
+
# Pass through QuestionAnswerValidationError or convert ValidationError
|
84
|
+
if isinstance(e, QuestionAnswerValidationError):
|
85
|
+
raise
|
80
86
|
raise QuestionAnswerValidationError(
|
81
87
|
message=str(e), pydantic_error=e, data=data, model=self.response_model
|
82
88
|
)
|
@@ -98,20 +104,12 @@ class ResponseValidatorABC(ABC):
|
|
98
104
|
{'answer': 42, 'comment': None, 'generated_tokens': None}
|
99
105
|
>>> rv.max_value
|
100
106
|
86.7
|
101
|
-
>>> rv.validate({"answer": "120"})
|
102
|
-
Traceback (most recent call last):
|
103
|
-
...
|
104
|
-
edsl.questions.exceptions.QuestionAnswerValidationError:...
|
105
107
|
>>> from edsl import QuestionNumerical
|
106
108
|
>>> q = QuestionNumerical.example()
|
107
109
|
>>> q.permissive = True
|
108
110
|
>>> rv = q.response_validator
|
109
111
|
>>> rv.validate({"answer": "120"})
|
110
112
|
{'answer': 120, 'comment': None, 'generated_tokens': None}
|
111
|
-
>>> rv.validate({"answer": "poo"})
|
112
|
-
Traceback (most recent call last):
|
113
|
-
...
|
114
|
-
edsl.questions.exceptions.QuestionAnswerValidationError:...
|
115
113
|
"""
|
116
114
|
proposed_edsl_answer_dict = self._preprocess(raw_edsl_answer_dict)
|
117
115
|
try:
|
@@ -1,5 +1,6 @@
|
|
1
|
-
from
|
2
|
-
from
|
1
|
+
from typing import Type, List
|
2
|
+
from .data_structures import BaseModel
|
3
|
+
from .response_validator_abc import ResponseValidatorABC
|
3
4
|
|
4
5
|
|
5
6
|
class ResponseValidatorFactory:
|
@@ -9,7 +10,7 @@ class ResponseValidatorFactory:
|
|
9
10
|
self.question = question
|
10
11
|
|
11
12
|
@property
|
12
|
-
def response_model(self) ->
|
13
|
+
def response_model(self) -> Type["BaseModel"]:
|
13
14
|
if self.question._response_model is not None:
|
14
15
|
return self.question._response_model
|
15
16
|
else:
|
@@ -18,17 +19,14 @@ class ResponseValidatorFactory:
|
|
18
19
|
@property
|
19
20
|
def response_validator(self) -> "ResponseValidatorABC":
|
20
21
|
"""Return the response validator."""
|
21
|
-
params =
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
| {"exception_to_throw": getattr(self.question, "exception_to_throw", None)}
|
27
|
-
| {"override_answer": getattr(self.question, "override_answer", None)}
|
28
|
-
)
|
22
|
+
params = {}
|
23
|
+
params.update({"response_model": self.question.response_model})
|
24
|
+
params.update({k: getattr(self.question, k) for k in self.validator_parameters})
|
25
|
+
params.update({"exception_to_throw": getattr(self.question, "exception_to_throw", None)})
|
26
|
+
params.update({"override_answer": getattr(self.question, "override_answer", None)})
|
29
27
|
return self.question.response_validator_class(**params)
|
30
28
|
|
31
29
|
@property
|
32
|
-
def validator_parameters(self) ->
|
30
|
+
def validator_parameters(self) -> List[str]:
|
33
31
|
"""Return the parameters required for the response validator."""
|
34
32
|
return self.question.response_validator_class.required_params
|
edsl/results/__init__.py
CHANGED
edsl/results/exceptions.py
CHANGED
@@ -2,28 +2,162 @@
|
|
2
2
|
from ..base import BaseException
|
3
3
|
|
4
4
|
class ResultsError(BaseException):
|
5
|
-
|
5
|
+
"""
|
6
|
+
Base exception class for all results-related errors.
|
7
|
+
|
8
|
+
This is the parent class for all exceptions related to Results objects
|
9
|
+
operations, including data manipulation, selection, and filtering.
|
10
|
+
|
11
|
+
This exception is raised in the following cases:
|
12
|
+
- When trying to add two Results objects with different surveys or created columns
|
13
|
+
- When trying to sample more items than available
|
14
|
+
- When Survey is not defined when accessing answer_keys
|
15
|
+
- When fetching remote Results fails
|
16
|
+
- When inappropriate model types are used with Results methods
|
17
|
+
"""
|
18
|
+
relevant_doc = "https://docs.expectedparrot.com/en/latest/results.html"
|
6
19
|
|
7
20
|
|
8
21
|
class ResultsDeserializationError(ResultsError):
|
9
|
-
|
22
|
+
"""
|
23
|
+
Exception raised when Results object deserialization fails.
|
24
|
+
|
25
|
+
This exception occurs when a Results object cannot be properly reconstructed
|
26
|
+
from its serialized representation, typically during from_dict() operations.
|
27
|
+
|
28
|
+
Reasons this might occur:
|
29
|
+
- Missing required fields in the serialized data
|
30
|
+
- Corrupted serialized data
|
31
|
+
- Version incompatibility between serialized data and current code
|
32
|
+
|
33
|
+
To fix this error:
|
34
|
+
1. Check that the serialized data is complete and uncorrupted
|
35
|
+
2. Ensure you're using a compatible version of EDSL to deserialize the data
|
36
|
+
3. If the issue persists, you may need to recreate the results from raw data
|
37
|
+
|
38
|
+
Examples:
|
39
|
+
```python
|
40
|
+
Results.from_dict(incomplete_or_corrupted_data) # Raises ResultsDeserializationError
|
41
|
+
```
|
42
|
+
"""
|
43
|
+
relevant_doc = "https://docs.expectedparrot.com/en/latest/results.html#saving-and-loading-results"
|
10
44
|
|
11
45
|
|
12
46
|
class ResultsBadMutationstringError(ResultsError):
|
13
|
-
|
47
|
+
"""
|
48
|
+
Exception raised when an invalid mutation string is provided.
|
49
|
+
|
50
|
+
This exception occurs when the mutation string doesn't follow the required format,
|
51
|
+
which should be 'column_name = expression' where expression is a valid Python
|
52
|
+
expression that can reference other columns.
|
53
|
+
|
54
|
+
To fix this error:
|
55
|
+
1. Ensure your mutation string contains an equals sign
|
56
|
+
2. Check that the left side is a valid column name
|
57
|
+
3. Verify the right side is a valid Python expression
|
58
|
+
|
59
|
+
Examples:
|
60
|
+
```python
|
61
|
+
results.mutate("invalid_mutation_no_equals") # Raises ResultsBadMutationstringError
|
62
|
+
results.mutate("column_name == value") # Raises ResultsBadMutationstringError (should use single =)
|
63
|
+
```
|
64
|
+
"""
|
65
|
+
relevant_doc = "https://docs.expectedparrot.com/en/latest/results.html#creating-new-columns"
|
14
66
|
|
15
67
|
|
16
68
|
class ResultsColumnNotFoundError(ResultsError):
|
17
|
-
|
69
|
+
"""
|
70
|
+
Exception raised when attempting to access a non-existent column.
|
71
|
+
|
72
|
+
This exception occurs when trying to access, filter, or perform operations
|
73
|
+
on a column that doesn't exist in the Results object.
|
74
|
+
|
75
|
+
To fix this error:
|
76
|
+
1. Check for typos in the column name
|
77
|
+
2. Verify the column exists using results.columns() or results.df.columns
|
78
|
+
3. If the column is dynamic, ensure it has been created with mutate() first
|
79
|
+
|
80
|
+
The error message typically includes suggestions for similar column names
|
81
|
+
that do exist, which can help identify typos.
|
82
|
+
|
83
|
+
Examples:
|
84
|
+
```python
|
85
|
+
results.table(keys=["non_existent_column"]) # Raises ResultsColumnNotFoundError
|
86
|
+
results.select("typo_in_column_name") # Raises ResultsColumnNotFoundError
|
87
|
+
```
|
88
|
+
"""
|
89
|
+
relevant_doc = "https://docs.expectedparrot.com/en/latest/results.html#selecting-columns"
|
18
90
|
|
19
91
|
|
20
92
|
class ResultsInvalidNameError(ResultsError):
|
21
|
-
|
93
|
+
"""
|
94
|
+
Exception raised when an invalid column name is provided.
|
95
|
+
|
96
|
+
This exception occurs when:
|
97
|
+
- The provided name is not a valid Python identifier
|
98
|
+
- The name conflicts with reserved names or methods
|
99
|
+
- The name contains invalid characters or starts with a number
|
100
|
+
|
101
|
+
To fix this error:
|
102
|
+
1. Use names that follow Python variable naming rules
|
103
|
+
2. Avoid using reserved words or existing method names
|
104
|
+
3. Use only letters, numbers, and underscores (not starting with a number)
|
105
|
+
|
106
|
+
Examples:
|
107
|
+
```python
|
108
|
+
results.mutate("123invalid = 1") # Raises ResultsInvalidNameError (starts with number)
|
109
|
+
results.mutate("invalid-name = 1") # Raises ResultsInvalidNameError (contains hyphen)
|
110
|
+
results.mutate("filter = 1") # Raises ResultsInvalidNameError (reserved method name)
|
111
|
+
```
|
112
|
+
"""
|
113
|
+
relevant_doc = "https://docs.expectedparrot.com/en/latest/results.html#creating-new-columns"
|
22
114
|
|
23
115
|
|
24
116
|
class ResultsMutateError(ResultsError):
|
25
|
-
|
117
|
+
"""
|
118
|
+
Exception raised when a mutation operation fails.
|
119
|
+
|
120
|
+
This exception occurs when an error happens during the execution of a mutation
|
121
|
+
expression, such as:
|
122
|
+
- Syntax errors in the expression
|
123
|
+
- Reference to non-existent columns
|
124
|
+
- Type errors in operations (e.g., adding a string to a number)
|
125
|
+
|
126
|
+
To fix this error:
|
127
|
+
1. Check the expression syntax
|
128
|
+
2. Verify all columns referenced in the expression exist
|
129
|
+
3. Ensure type compatibility in operations
|
130
|
+
4. Test the expression with simple cases first
|
131
|
+
|
132
|
+
Examples:
|
133
|
+
```python
|
134
|
+
results.mutate("new_col = old_col + 'text'") # Raises ResultsMutateError if old_col contains numbers
|
135
|
+
results.mutate("new_col = undefined_col + 1") # Raises ResultsMutateError if undefined_col doesn't exist
|
136
|
+
```
|
137
|
+
"""
|
138
|
+
relevant_doc = "https://docs.expectedparrot.com/en/latest/results.html#creating-new-columns"
|
26
139
|
|
27
140
|
|
28
141
|
class ResultsFilterError(ResultsError):
|
29
|
-
|
142
|
+
"""
|
143
|
+
Exception raised when a filter operation fails.
|
144
|
+
|
145
|
+
This exception occurs when there's an error in the filter expression, such as:
|
146
|
+
- Using single equals (=) instead of double equals (==) for comparison
|
147
|
+
- Syntax errors in the filter expression
|
148
|
+
- Reference to non-existent columns
|
149
|
+
- Type errors in comparisons
|
150
|
+
|
151
|
+
To fix this error:
|
152
|
+
1. Use == (double equals) for equality comparisons, not = (single equals)
|
153
|
+
2. Check the filter expression syntax
|
154
|
+
3. Verify all columns referenced in the expression exist
|
155
|
+
4. Ensure type compatibility in comparisons
|
156
|
+
|
157
|
+
Examples:
|
158
|
+
```python
|
159
|
+
results.filter("column = value") # Raises ResultsFilterError (use == instead)
|
160
|
+
results.filter("column == undefined_var") # Raises ResultsFilterError if undefined_var isn't defined
|
161
|
+
```
|
162
|
+
"""
|
163
|
+
relevant_doc = "https://docs.expectedparrot.com/en/latest/results.html#filtering-results"
|
edsl/results/report.py
CHANGED
@@ -1,6 +1,5 @@
|
|
1
1
|
import jinja2
|
2
2
|
import textwrap
|
3
|
-
import warnings
|
4
3
|
|
5
4
|
class Report:
|
6
5
|
"""
|
@@ -174,7 +173,7 @@ class Report:
|
|
174
173
|
|
175
174
|
if __name__ == "__main__":
|
176
175
|
# Suppose you have an existing Dataset
|
177
|
-
from
|
176
|
+
from .. import Results
|
178
177
|
ds = Results.example().select("how_feeling", "how_feeling_yesterday")
|
179
178
|
|
180
179
|
# Provide a custom template string
|
edsl/results/result.py
CHANGED
@@ -23,7 +23,7 @@ maintaining a rich object model.
|
|
23
23
|
from __future__ import annotations
|
24
24
|
import inspect
|
25
25
|
from collections import UserDict
|
26
|
-
from typing import Any,
|
26
|
+
from typing import Any, Callable, Optional, TYPE_CHECKING, Union
|
27
27
|
|
28
28
|
from ..base import Base
|
29
29
|
from ..utilities import remove_edsl_version
|
@@ -35,7 +35,6 @@ if TYPE_CHECKING:
|
|
35
35
|
from ..agents import Agent
|
36
36
|
from ..scenarios import Scenario
|
37
37
|
from ..language_models import LanguageModel
|
38
|
-
from ..prompts import Prompt
|
39
38
|
from ..surveys import Survey
|
40
39
|
|
41
40
|
QuestionName = str
|
@@ -259,15 +258,17 @@ class Result(Base, UserDict):
|
|
259
258
|
|
260
259
|
def check_expression(self, expression: str) -> None:
|
261
260
|
for key in self.problem_keys:
|
262
|
-
if key in expression and
|
263
|
-
|
264
|
-
|
261
|
+
if key in expression and key + "." not in expression:
|
262
|
+
from .exceptions import ResultsColumnNotFoundError
|
263
|
+
raise ResultsColumnNotFoundError(
|
264
|
+
f"Key by itself {key} is problematic. Use the full key {key + '.' + key} name instead."
|
265
265
|
)
|
266
266
|
return None
|
267
267
|
|
268
268
|
def code(self):
|
269
269
|
"""Return a string of code that can be used to recreate the Result object."""
|
270
|
-
|
270
|
+
from .exceptions import ResultsError
|
271
|
+
raise ResultsError("The code() method is not implemented for Result objects")
|
271
272
|
|
272
273
|
@property
|
273
274
|
def problem_keys(self) -> list[str]:
|
@@ -307,7 +308,7 @@ class Result(Base, UserDict):
|
|
307
308
|
return self._combined_dict
|
308
309
|
|
309
310
|
@property
|
310
|
-
def
|
311
|
+
def get_problem_keys(self) -> list[str]:
|
311
312
|
"""Return a list of keys that are problematic."""
|
312
313
|
if self._combined_dict is None or self._problem_keys is None:
|
313
314
|
self._compute_combined_dict_and_problem_keys()
|
@@ -568,7 +569,8 @@ class Result(Base, UserDict):
|
|
568
569
|
elif v.default is not v.empty:
|
569
570
|
params[k] = v.default
|
570
571
|
else:
|
571
|
-
|
572
|
+
from .exceptions import ResultsError
|
573
|
+
raise ResultsError(f"Parameter {k} not found in Result object")
|
572
574
|
return scoring_function(**params)
|
573
575
|
|
574
576
|
@classmethod
|
@@ -579,7 +581,7 @@ class Result(Base, UserDict):
|
|
579
581
|
|
580
582
|
def get_question_results(
|
581
583
|
model_response_objects,
|
582
|
-
) -> dict[str,
|
584
|
+
) -> dict[str, Any]:
|
583
585
|
"""Maps the question name to the EDSLResultObjectInput."""
|
584
586
|
question_results = {}
|
585
587
|
for result in model_response_objects:
|