edsl 0.1.50__py3-none-any.whl → 0.1.52__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.
Files changed (119) hide show
  1. edsl/__init__.py +45 -34
  2. edsl/__version__.py +1 -1
  3. edsl/base/base_exception.py +2 -2
  4. edsl/buckets/bucket_collection.py +1 -1
  5. edsl/buckets/exceptions.py +32 -0
  6. edsl/buckets/token_bucket_api.py +26 -10
  7. edsl/caching/cache.py +5 -2
  8. edsl/caching/remote_cache_sync.py +5 -5
  9. edsl/caching/sql_dict.py +12 -11
  10. edsl/config/__init__.py +1 -1
  11. edsl/config/config_class.py +4 -2
  12. edsl/conversation/Conversation.py +9 -5
  13. edsl/conversation/car_buying.py +1 -3
  14. edsl/conversation/mug_negotiation.py +2 -6
  15. edsl/coop/__init__.py +11 -8
  16. edsl/coop/coop.py +15 -13
  17. edsl/coop/coop_functions.py +1 -1
  18. edsl/coop/ep_key_handling.py +1 -1
  19. edsl/coop/price_fetcher.py +2 -2
  20. edsl/coop/utils.py +2 -2
  21. edsl/dataset/dataset.py +144 -63
  22. edsl/dataset/dataset_operations_mixin.py +14 -6
  23. edsl/dataset/dataset_tree.py +3 -3
  24. edsl/dataset/display/table_renderers.py +6 -3
  25. edsl/dataset/file_exports.py +4 -4
  26. edsl/dataset/r/ggplot.py +3 -3
  27. edsl/inference_services/available_model_fetcher.py +2 -2
  28. edsl/inference_services/data_structures.py +5 -5
  29. edsl/inference_services/inference_service_abc.py +1 -1
  30. edsl/inference_services/inference_services_collection.py +1 -1
  31. edsl/inference_services/service_availability.py +3 -3
  32. edsl/inference_services/services/azure_ai.py +3 -3
  33. edsl/inference_services/services/google_service.py +1 -1
  34. edsl/inference_services/services/test_service.py +1 -1
  35. edsl/instructions/change_instruction.py +5 -4
  36. edsl/instructions/instruction.py +1 -0
  37. edsl/instructions/instruction_collection.py +5 -4
  38. edsl/instructions/instruction_handler.py +10 -8
  39. edsl/interviews/answering_function.py +20 -21
  40. edsl/interviews/exception_tracking.py +3 -2
  41. edsl/interviews/interview.py +1 -1
  42. edsl/interviews/interview_status_dictionary.py +1 -1
  43. edsl/interviews/interview_task_manager.py +7 -4
  44. edsl/interviews/request_token_estimator.py +3 -2
  45. edsl/interviews/statistics.py +2 -2
  46. edsl/invigilators/invigilators.py +34 -6
  47. edsl/jobs/__init__.py +39 -2
  48. edsl/jobs/async_interview_runner.py +1 -1
  49. edsl/jobs/check_survey_scenario_compatibility.py +5 -5
  50. edsl/jobs/data_structures.py +2 -2
  51. edsl/jobs/html_table_job_logger.py +494 -257
  52. edsl/jobs/jobs.py +2 -2
  53. edsl/jobs/jobs_checks.py +5 -5
  54. edsl/jobs/jobs_component_constructor.py +2 -2
  55. edsl/jobs/jobs_pricing_estimation.py +1 -1
  56. edsl/jobs/jobs_runner_asyncio.py +2 -2
  57. edsl/jobs/jobs_status_enums.py +1 -0
  58. edsl/jobs/remote_inference.py +47 -13
  59. edsl/jobs/results_exceptions_handler.py +2 -2
  60. edsl/language_models/language_model.py +151 -145
  61. edsl/notebooks/__init__.py +24 -1
  62. edsl/notebooks/exceptions.py +82 -0
  63. edsl/notebooks/notebook.py +7 -3
  64. edsl/notebooks/notebook_to_latex.py +1 -1
  65. edsl/prompts/__init__.py +23 -2
  66. edsl/prompts/prompt.py +1 -1
  67. edsl/questions/__init__.py +4 -4
  68. edsl/questions/answer_validator_mixin.py +0 -5
  69. edsl/questions/compose_questions.py +2 -2
  70. edsl/questions/descriptors.py +1 -1
  71. edsl/questions/question_base.py +32 -3
  72. edsl/questions/question_base_prompts_mixin.py +4 -4
  73. edsl/questions/question_budget.py +503 -102
  74. edsl/questions/question_check_box.py +658 -156
  75. edsl/questions/question_dict.py +176 -2
  76. edsl/questions/question_extract.py +401 -61
  77. edsl/questions/question_free_text.py +77 -9
  78. edsl/questions/question_functional.py +118 -9
  79. edsl/questions/{derived/question_likert_five.py → question_likert_five.py} +2 -2
  80. edsl/questions/{derived/question_linear_scale.py → question_linear_scale.py} +3 -4
  81. edsl/questions/question_list.py +246 -26
  82. edsl/questions/question_matrix.py +586 -73
  83. edsl/questions/question_multiple_choice.py +213 -47
  84. edsl/questions/question_numerical.py +360 -29
  85. edsl/questions/question_rank.py +401 -124
  86. edsl/questions/question_registry.py +3 -3
  87. edsl/questions/{derived/question_top_k.py → question_top_k.py} +3 -3
  88. edsl/questions/{derived/question_yes_no.py → question_yes_no.py} +3 -4
  89. edsl/questions/register_questions_meta.py +2 -1
  90. edsl/questions/response_validator_abc.py +6 -2
  91. edsl/questions/response_validator_factory.py +10 -12
  92. edsl/results/report.py +1 -1
  93. edsl/results/result.py +7 -4
  94. edsl/results/results.py +500 -271
  95. edsl/results/results_selector.py +2 -2
  96. edsl/scenarios/construct_download_link.py +3 -3
  97. edsl/scenarios/scenario.py +1 -2
  98. edsl/scenarios/scenario_list.py +41 -23
  99. edsl/surveys/survey_css.py +3 -3
  100. edsl/surveys/survey_simulator.py +2 -1
  101. edsl/tasks/__init__.py +22 -2
  102. edsl/tasks/exceptions.py +72 -0
  103. edsl/tasks/task_history.py +48 -11
  104. edsl/templates/error_reporting/base.html +37 -4
  105. edsl/templates/error_reporting/exceptions_table.html +105 -33
  106. edsl/templates/error_reporting/interview_details.html +130 -126
  107. edsl/templates/error_reporting/overview.html +21 -25
  108. edsl/templates/error_reporting/report.css +215 -46
  109. edsl/templates/error_reporting/report.js +122 -20
  110. edsl/tokens/__init__.py +27 -1
  111. edsl/tokens/exceptions.py +37 -0
  112. edsl/tokens/interview_token_usage.py +3 -2
  113. edsl/tokens/token_usage.py +4 -3
  114. {edsl-0.1.50.dist-info → edsl-0.1.52.dist-info}/METADATA +1 -1
  115. {edsl-0.1.50.dist-info → edsl-0.1.52.dist-info}/RECORD +118 -116
  116. edsl/questions/derived/__init__.py +0 -0
  117. {edsl-0.1.50.dist-info → edsl-0.1.52.dist-info}/LICENSE +0 -0
  118. {edsl-0.1.50.dist-info → edsl-0.1.52.dist-info}/WHEEL +0 -0
  119. {edsl-0.1.50.dist-info → edsl-0.1.52.dist-info}/entry_points.txt +0 -0
@@ -1,25 +1,127 @@
1
- document.addEventListener('DOMContentLoaded', function() {
2
- const collapsibleSections = document.querySelectorAll('.exception-detail, .raw-model-response');
3
-
4
- collapsibleSections.forEach(section => {
5
- const header = section.querySelector('.exception-header, .response-header');
6
- const content = section.querySelector('.exception-content, .response-content');
7
- const toggleBtn = section.querySelector('.toggle-btn');
1
+ // Toggle functionality for exception details
2
+ function toggleExceptionDetail(header) {
3
+ const detail = header.closest('.exception-detail');
4
+ const content = detail.querySelector('.exception-content');
5
+ const expanded = header.getAttribute('aria-expanded') === 'true';
6
+
7
+ if (expanded) {
8
+ content.classList.remove('expanded');
9
+ header.setAttribute('aria-expanded', 'false');
10
+ } else {
11
+ content.classList.add('expanded');
12
+ header.setAttribute('aria-expanded', 'true');
13
+ }
14
+ }
8
15
 
9
- header.addEventListener('click', function() {
10
- content.classList.toggle('show');
11
- toggleBtn.classList.toggle('rotated');
16
+ // Copy code functionality
17
+ function copyCode(button) {
18
+ console.log("Copy button clicked");
19
+
20
+ // Find the code block - look for pre/code elements after the button's parent
21
+ const section = button.closest('div');
22
+ const codeBlock = section.nextElementSibling;
23
+
24
+ if (codeBlock) {
25
+ // Get the text content
26
+ let textToCopy = '';
27
+ if (codeBlock.tagName === 'PRE') {
28
+ textToCopy = codeBlock.textContent || '';
29
+ } else if (codeBlock.tagName === 'TEXTAREA') {
30
+ textToCopy = codeBlock.value || '';
31
+ }
32
+
33
+ // Use clipboard API if available, fallback to execCommand
34
+ if (navigator.clipboard && navigator.clipboard.writeText) {
35
+ navigator.clipboard.writeText(textToCopy)
36
+ .then(() => {
37
+ console.log("Text copied to clipboard successfully");
38
+ showCopiedFeedback(button);
39
+ })
40
+ .catch(err => {
41
+ console.error("Failed to copy text: ", err);
42
+ fallbackCopy(textToCopy, button);
12
43
  });
13
- });
14
-
15
- });
44
+ } else {
45
+ fallbackCopy(textToCopy, button);
46
+ }
47
+ } else {
48
+ console.error("Code block not found");
49
+ }
50
+ }
16
51
 
17
- function copyCode() {
18
- const textarea = document.getElementById('codeToCopy');
19
- textarea.select();
20
- textarea.setSelectionRange(0, 99999); // For mobile devices
21
- document.execCommand("copy");
52
+ // Fallback copy method using document.execCommand
53
+ function fallbackCopy(text, button) {
54
+ // Create temporary textarea
55
+ const textarea = document.createElement('textarea');
56
+ textarea.value = text;
57
+ textarea.style.position = 'fixed'; // Avoid scrolling to bottom
58
+ document.body.appendChild(textarea);
59
+ textarea.select();
60
+
61
+ try {
62
+ const successful = document.execCommand('copy');
63
+ if (successful) {
64
+ console.log("Fallback copy successful");
65
+ showCopiedFeedback(button);
66
+ } else {
67
+ console.error("Fallback copy failed");
68
+ }
69
+ } catch (err) {
70
+ console.error("Fallback copy error:", err);
71
+ }
72
+
73
+ document.body.removeChild(textarea);
74
+ }
22
75
 
23
- // Optionally, you can display an alert or change the button text to indicate success
24
- alert("Code copied to clipboard!");
76
+ // Show copied feedback on button
77
+ function showCopiedFeedback(button) {
78
+ const originalText = button.textContent;
79
+ button.textContent = 'Copied!';
80
+ button.disabled = true;
81
+
82
+ setTimeout(() => {
83
+ button.textContent = originalText;
84
+ button.disabled = false;
85
+ }, 2000);
25
86
  }
87
+
88
+ // Initialize all headers on page load
89
+ document.addEventListener('DOMContentLoaded', function() {
90
+ console.log("DOM loaded, initializing exception toggles");
91
+
92
+ // Set initial states for all exception contents
93
+ const exceptionContents = document.querySelectorAll('.exception-content');
94
+ console.log(`Found ${exceptionContents.length} exception contents`);
95
+
96
+ exceptionContents.forEach(content => {
97
+ content.classList.remove('expanded');
98
+ });
99
+
100
+ // Set aria attributes on headers and add click events
101
+ const exceptionHeaders = document.querySelectorAll('.exception-header');
102
+ console.log(`Found ${exceptionHeaders.length} exception headers`);
103
+
104
+ exceptionHeaders.forEach(header => {
105
+ header.setAttribute('aria-expanded', 'false');
106
+
107
+ // Add click listener
108
+ header.addEventListener('click', function(e) {
109
+ console.log("Header clicked, toggling exception detail");
110
+ toggleExceptionDetail(this);
111
+ });
112
+ });
113
+
114
+ // Set up copy buttons
115
+ const copyButtons = document.querySelectorAll('.copy-button');
116
+ console.log(`Found ${copyButtons.length} copy buttons`);
117
+
118
+ copyButtons.forEach(button => {
119
+ // Add click listener
120
+ button.addEventListener('click', function(e) {
121
+ console.log("Copy button clicked");
122
+ e.preventDefault();
123
+ e.stopPropagation();
124
+ copyCode(this);
125
+ });
126
+ });
127
+ });
edsl/tokens/__init__.py CHANGED
@@ -1,4 +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
21
  from .interview_token_usage import InterviewTokenUsage
22
+ from .exceptions import TokenError, TokenUsageError, TokenCostError
3
23
 
4
- __all__ = ["TokenUsage", "InterviewTokenUsage"]
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 edsl.enums import TokenPricing
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 ValueError(f"Can't add {type(other)} to InterviewTokenSummary")
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,
@@ -1,4 +1,5 @@
1
- from edsl.enums import TokenPricing
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 ValueError(f"Can't add {type(other)} to InterviewTokenUsage")
19
+ raise TokenUsageError(f"Can't add {type(other)} to InterviewTokenUsage")
19
20
  if self.from_cache != other.from_cache:
20
- raise ValueError("Can't add token usages from different sources")
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,
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: edsl
3
- Version: 0.1.50
3
+ Version: 0.1.52
4
4
  Summary: Create and analyze LLM-based surveys
5
5
  Home-page: https://www.expectedparrot.com/
6
6
  License: MIT