edsl 0.1.50__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/__version__.py +1 -1
- edsl/base/base_exception.py +2 -2
- edsl/buckets/bucket_collection.py +1 -1
- edsl/buckets/exceptions.py +32 -0
- edsl/buckets/token_bucket_api.py +26 -10
- edsl/caching/cache.py +5 -2
- edsl/caching/remote_cache_sync.py +5 -5
- edsl/caching/sql_dict.py +12 -11
- edsl/config/__init__.py +1 -1
- edsl/config/config_class.py +4 -2
- edsl/conversation/Conversation.py +7 -4
- edsl/conversation/car_buying.py +1 -3
- edsl/conversation/mug_negotiation.py +2 -6
- edsl/coop/__init__.py +11 -8
- edsl/coop/coop.py +13 -13
- edsl/coop/coop_functions.py +1 -1
- edsl/coop/ep_key_handling.py +1 -1
- edsl/coop/price_fetcher.py +2 -2
- edsl/coop/utils.py +2 -2
- edsl/dataset/dataset.py +144 -63
- edsl/dataset/dataset_operations_mixin.py +14 -6
- edsl/dataset/dataset_tree.py +3 -3
- edsl/dataset/display/table_renderers.py +6 -3
- edsl/dataset/file_exports.py +4 -4
- edsl/dataset/r/ggplot.py +3 -3
- edsl/inference_services/available_model_fetcher.py +2 -2
- edsl/inference_services/data_structures.py +5 -5
- edsl/inference_services/inference_service_abc.py +1 -1
- edsl/inference_services/inference_services_collection.py +1 -1
- edsl/inference_services/service_availability.py +3 -3
- edsl/inference_services/services/azure_ai.py +3 -3
- edsl/inference_services/services/google_service.py +1 -1
- edsl/inference_services/services/test_service.py +1 -1
- edsl/instructions/change_instruction.py +5 -4
- edsl/instructions/instruction.py +1 -0
- edsl/instructions/instruction_collection.py +5 -4
- edsl/instructions/instruction_handler.py +10 -8
- edsl/interviews/exception_tracking.py +1 -1
- edsl/interviews/interview.py +1 -1
- edsl/interviews/interview_status_dictionary.py +1 -1
- edsl/interviews/interview_task_manager.py +2 -2
- edsl/interviews/request_token_estimator.py +3 -2
- edsl/interviews/statistics.py +2 -2
- edsl/invigilators/invigilators.py +2 -2
- edsl/jobs/__init__.py +39 -2
- edsl/jobs/async_interview_runner.py +1 -1
- edsl/jobs/check_survey_scenario_compatibility.py +5 -5
- edsl/jobs/data_structures.py +2 -2
- edsl/jobs/jobs.py +2 -2
- edsl/jobs/jobs_checks.py +5 -5
- edsl/jobs/jobs_component_constructor.py +2 -2
- edsl/jobs/jobs_pricing_estimation.py +1 -1
- edsl/jobs/jobs_runner_asyncio.py +2 -2
- edsl/jobs/remote_inference.py +1 -1
- edsl/jobs/results_exceptions_handler.py +2 -2
- edsl/language_models/language_model.py +5 -1
- 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 -1
- edsl/prompts/__init__.py +23 -2
- edsl/prompts/prompt.py +1 -1
- edsl/questions/__init__.py +4 -4
- edsl/questions/answer_validator_mixin.py +0 -5
- edsl/questions/compose_questions.py +2 -2
- edsl/questions/descriptors.py +1 -1
- edsl/questions/question_base.py +32 -3
- edsl/questions/question_base_prompts_mixin.py +4 -4
- edsl/questions/question_budget.py +503 -102
- edsl/questions/question_check_box.py +658 -156
- edsl/questions/question_dict.py +176 -2
- edsl/questions/question_extract.py +401 -61
- edsl/questions/question_free_text.py +77 -9
- edsl/questions/question_functional.py +118 -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 +246 -26
- edsl/questions/question_matrix.py +586 -73
- edsl/questions/question_multiple_choice.py +213 -47
- edsl/questions/question_numerical.py +360 -29
- edsl/questions/question_rank.py +401 -124
- edsl/questions/question_registry.py +3 -3
- 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 -1
- edsl/questions/response_validator_abc.py +6 -2
- edsl/questions/response_validator_factory.py +10 -12
- edsl/results/report.py +1 -1
- edsl/results/result.py +7 -4
- edsl/results/results.py +471 -271
- edsl/results/results_selector.py +2 -2
- edsl/scenarios/construct_download_link.py +3 -3
- edsl/scenarios/scenario.py +1 -2
- edsl/scenarios/scenario_list.py +41 -23
- edsl/surveys/survey_css.py +3 -3
- edsl/surveys/survey_simulator.py +2 -1
- edsl/tasks/__init__.py +22 -2
- edsl/tasks/exceptions.py +72 -0
- edsl/tasks/task_history.py +3 -3
- edsl/tokens/__init__.py +27 -1
- edsl/tokens/exceptions.py +37 -0
- edsl/tokens/interview_token_usage.py +3 -2
- edsl/tokens/token_usage.py +4 -3
- {edsl-0.1.50.dist-info → edsl-0.1.51.dist-info}/METADATA +1 -1
- {edsl-0.1.50.dist-info → edsl-0.1.51.dist-info}/RECORD +108 -106
- edsl/questions/derived/__init__.py +0 -0
- {edsl-0.1.50.dist-info → edsl-0.1.51.dist-info}/LICENSE +0 -0
- {edsl-0.1.50.dist-info → edsl-0.1.51.dist-info}/WHEEL +0 -0
- {edsl-0.1.50.dist-info → edsl-0.1.51.dist-info}/entry_points.txt +0 -0
edsl/questions/__init__.py
CHANGED
@@ -120,10 +120,10 @@ from .question_budget import QuestionBudget
|
|
120
120
|
from .question_rank import QuestionRank
|
121
121
|
|
122
122
|
# Questions derived from core questions
|
123
|
-
from .
|
124
|
-
from .
|
125
|
-
from .
|
126
|
-
from .
|
123
|
+
from .question_likert_five import QuestionLikertFive
|
124
|
+
from .question_linear_scale import QuestionLinearScale
|
125
|
+
from .question_yes_no import QuestionYesNo
|
126
|
+
from .question_top_k import QuestionTopK
|
127
127
|
|
128
128
|
from .exceptions import QuestionScenarioRenderError
|
129
129
|
|
@@ -3,6 +3,7 @@
|
|
3
3
|
from .question_functional import QuestionFunctional
|
4
4
|
from .question_base import QuestionBase
|
5
5
|
from ..scenarios import Scenario
|
6
|
+
from .exceptions import QuestionValueError
|
6
7
|
|
7
8
|
|
8
9
|
def compose_questions(
|
@@ -19,7 +20,6 @@ def compose_questions(
|
|
19
20
|
if question_name is None:
|
20
21
|
question_name = f"{q1.question_name}_{q2.question_name}"
|
21
22
|
if q1.question_name not in q2.question_text:
|
22
|
-
from .exceptions import QuestionValueError
|
23
23
|
raise QuestionValueError(
|
24
24
|
f"q2 requires a field not present in q1's answer. "
|
25
25
|
f"q1: {q1.question_name}, q2: {q2.question_name}"
|
@@ -30,7 +30,7 @@ def compose_questions(
|
|
30
30
|
) -> QuestionFunctional:
|
31
31
|
"""Return the answer to the second question given the answer to the first question."""
|
32
32
|
# get the answer to the first question
|
33
|
-
from
|
33
|
+
from ..agents.agent import Agent
|
34
34
|
|
35
35
|
first_answer = (
|
36
36
|
q1.by(scenario)
|
edsl/questions/descriptors.py
CHANGED
@@ -230,7 +230,7 @@ class QuestionNameDescriptor(BaseDescriptor):
|
|
230
230
|
|
231
231
|
def validate(self, value, instance):
|
232
232
|
"""Validate the value is a valid variable name."""
|
233
|
-
from
|
233
|
+
from ..utilities.utilities import is_valid_variable_name
|
234
234
|
|
235
235
|
if "{{" in value and "}}" in value:
|
236
236
|
# they're trying to use a dynamic question name - let's let this play out
|
edsl/questions/question_base.py
CHANGED
@@ -271,8 +271,25 @@ class QuestionBase(
|
|
271
271
|
"""
|
272
272
|
if not hasattr(self, "_fake_data_factory"):
|
273
273
|
from polyfactory.factories.pydantic_factory import ModelFactory
|
274
|
-
|
275
|
-
|
274
|
+
from random import randint, uniform
|
275
|
+
|
276
|
+
class FakeData(ModelFactory[self.response_model]):
|
277
|
+
# Add customization for specific question types
|
278
|
+
if hasattr(self, 'question_type') and self.question_type == 'numerical':
|
279
|
+
@classmethod
|
280
|
+
def build_answer(cls):
|
281
|
+
min_val = getattr(self, 'min_value', None)
|
282
|
+
max_val = getattr(self, 'max_value', None)
|
283
|
+
|
284
|
+
# Default values if none provided
|
285
|
+
min_val = 0 if min_val is None else min_val
|
286
|
+
max_val = 100 if max_val is None else max_val
|
287
|
+
|
288
|
+
# Ensure values are within bounds
|
289
|
+
if isinstance(min_val, int) and isinstance(max_val, int):
|
290
|
+
return randint(min_val, max_val)
|
291
|
+
else:
|
292
|
+
return uniform(min_val, max_val)
|
276
293
|
|
277
294
|
self._fake_data_factory = FakeData
|
278
295
|
return self._fake_data_factory
|
@@ -358,7 +375,19 @@ class QuestionBase(
|
|
358
375
|
>>> Q.example()._validate_answer({'answer': 'Hello', 'generated_tokens': 'Hello'})
|
359
376
|
{'answer': 'Hello', 'generated_tokens': 'Hello'}
|
360
377
|
"""
|
361
|
-
|
378
|
+
try:
|
379
|
+
return self.response_validator.validate(answer, replacement_dict)
|
380
|
+
except Exception as e:
|
381
|
+
# Ensure all validation errors are raised as QuestionAnswerValidationError
|
382
|
+
from .exceptions import QuestionAnswerValidationError
|
383
|
+
if not isinstance(e, QuestionAnswerValidationError):
|
384
|
+
raise QuestionAnswerValidationError(
|
385
|
+
message=f"Invalid response: {e}",
|
386
|
+
data=answer,
|
387
|
+
model=getattr(self, 'response_model', None),
|
388
|
+
pydantic_error=e if hasattr(e, 'errors') else None
|
389
|
+
) from e
|
390
|
+
raise
|
362
391
|
|
363
392
|
@property
|
364
393
|
def name(self) -> str:
|
@@ -74,7 +74,7 @@ class QuestionBasePromptsMixin:
|
|
74
74
|
>>> q.get_instructions(model = "gpt3")
|
75
75
|
Prompt(text=\"""{{question_text}}. Answer in valid JSON like so {'answer': 'comment: <>}\""")
|
76
76
|
"""
|
77
|
-
from
|
77
|
+
from ..language_models.model import Model
|
78
78
|
|
79
79
|
if not hasattr(self, "_model_instructions"):
|
80
80
|
self._model_instructions = {}
|
@@ -125,7 +125,7 @@ class QuestionBasePromptsMixin:
|
|
125
125
|
template_text = template_manager.get_template(
|
126
126
|
cls.question_type, "answering_instructions.jinja"
|
127
127
|
)
|
128
|
-
from
|
128
|
+
from ..prompts import Prompt
|
129
129
|
|
130
130
|
return Prompt(text=template_text)
|
131
131
|
|
@@ -134,7 +134,7 @@ class QuestionBasePromptsMixin:
|
|
134
134
|
template_text = template_manager.get_template(
|
135
135
|
cls.question_type, "question_presentation.jinja"
|
136
136
|
)
|
137
|
-
from
|
137
|
+
from ..prompts import Prompt
|
138
138
|
|
139
139
|
return Prompt(text=template_text)
|
140
140
|
|
@@ -190,7 +190,7 @@ class QuestionBasePromptsMixin:
|
|
190
190
|
@property
|
191
191
|
def new_default_instructions(self) -> "Prompt":
|
192
192
|
"This is set up as a property because there are mutable question values that determine how it is rendered."
|
193
|
-
from
|
193
|
+
from ..prompts import Prompt
|
194
194
|
|
195
195
|
return Prompt(self.question_presentation) + Prompt(self.answering_instructions)
|
196
196
|
|