edsl 0.1.54__py3-none-any.whl → 0.1.55__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 (101) hide show
  1. edsl/__init__.py +8 -1
  2. edsl/__init__original.py +134 -0
  3. edsl/__version__.py +1 -1
  4. edsl/agents/agent.py +29 -0
  5. edsl/agents/agent_list.py +36 -1
  6. edsl/base/base_class.py +281 -151
  7. edsl/buckets/__init__.py +8 -3
  8. edsl/buckets/bucket_collection.py +9 -3
  9. edsl/buckets/model_buckets.py +4 -2
  10. edsl/buckets/token_bucket.py +2 -2
  11. edsl/buckets/token_bucket_client.py +5 -3
  12. edsl/caching/cache.py +131 -62
  13. edsl/caching/cache_entry.py +70 -58
  14. edsl/caching/sql_dict.py +17 -0
  15. edsl/cli.py +99 -0
  16. edsl/config/config_class.py +16 -0
  17. edsl/conversation/__init__.py +31 -0
  18. edsl/coop/coop.py +276 -242
  19. edsl/coop/coop_jobs_objects.py +59 -0
  20. edsl/coop/coop_objects.py +29 -0
  21. edsl/coop/coop_regular_objects.py +26 -0
  22. edsl/coop/utils.py +24 -19
  23. edsl/dataset/dataset.py +338 -101
  24. edsl/db_list/sqlite_list.py +349 -0
  25. edsl/inference_services/__init__.py +40 -5
  26. edsl/inference_services/exceptions.py +11 -0
  27. edsl/inference_services/services/anthropic_service.py +5 -2
  28. edsl/inference_services/services/aws_bedrock.py +6 -2
  29. edsl/inference_services/services/azure_ai.py +6 -2
  30. edsl/inference_services/services/google_service.py +3 -2
  31. edsl/inference_services/services/mistral_ai_service.py +6 -2
  32. edsl/inference_services/services/open_ai_service.py +6 -2
  33. edsl/inference_services/services/perplexity_service.py +6 -2
  34. edsl/inference_services/services/test_service.py +94 -5
  35. edsl/interviews/answering_function.py +167 -59
  36. edsl/interviews/interview.py +124 -72
  37. edsl/interviews/interview_task_manager.py +10 -0
  38. edsl/invigilators/invigilators.py +9 -0
  39. edsl/jobs/async_interview_runner.py +146 -104
  40. edsl/jobs/data_structures.py +6 -4
  41. edsl/jobs/decorators.py +61 -0
  42. edsl/jobs/fetch_invigilator.py +61 -18
  43. edsl/jobs/html_table_job_logger.py +14 -2
  44. edsl/jobs/jobs.py +180 -104
  45. edsl/jobs/jobs_component_constructor.py +2 -2
  46. edsl/jobs/jobs_interview_constructor.py +2 -0
  47. edsl/jobs/jobs_remote_inference_logger.py +4 -0
  48. edsl/jobs/jobs_runner_status.py +30 -25
  49. edsl/jobs/progress_bar_manager.py +79 -0
  50. edsl/jobs/remote_inference.py +35 -1
  51. edsl/key_management/key_lookup_builder.py +6 -1
  52. edsl/language_models/language_model.py +86 -6
  53. edsl/language_models/model.py +10 -3
  54. edsl/language_models/price_manager.py +45 -75
  55. edsl/language_models/registry.py +5 -0
  56. edsl/notebooks/notebook.py +77 -10
  57. edsl/questions/VALIDATION_README.md +134 -0
  58. edsl/questions/__init__.py +24 -1
  59. edsl/questions/exceptions.py +21 -0
  60. edsl/questions/question_dict.py +201 -16
  61. edsl/questions/question_multiple_choice_with_other.py +624 -0
  62. edsl/questions/question_registry.py +2 -1
  63. edsl/questions/templates/multiple_choice_with_other/__init__.py +0 -0
  64. edsl/questions/templates/multiple_choice_with_other/answering_instructions.jinja +15 -0
  65. edsl/questions/templates/multiple_choice_with_other/question_presentation.jinja +17 -0
  66. edsl/questions/validation_analysis.py +185 -0
  67. edsl/questions/validation_cli.py +131 -0
  68. edsl/questions/validation_html_report.py +404 -0
  69. edsl/questions/validation_logger.py +136 -0
  70. edsl/results/result.py +63 -16
  71. edsl/results/results.py +702 -171
  72. edsl/scenarios/construct_download_link.py +16 -3
  73. edsl/scenarios/directory_scanner.py +226 -226
  74. edsl/scenarios/file_methods.py +5 -0
  75. edsl/scenarios/file_store.py +117 -6
  76. edsl/scenarios/handlers/__init__.py +5 -1
  77. edsl/scenarios/handlers/mp4_file_store.py +104 -0
  78. edsl/scenarios/handlers/webm_file_store.py +104 -0
  79. edsl/scenarios/scenario.py +120 -101
  80. edsl/scenarios/scenario_list.py +800 -727
  81. edsl/scenarios/scenario_list_gc_test.py +146 -0
  82. edsl/scenarios/scenario_list_memory_test.py +214 -0
  83. edsl/scenarios/scenario_list_source_refactor.md +35 -0
  84. edsl/scenarios/scenario_selector.py +5 -4
  85. edsl/scenarios/scenario_source.py +1990 -0
  86. edsl/scenarios/tests/test_scenario_list_sources.py +52 -0
  87. edsl/surveys/survey.py +22 -0
  88. edsl/tasks/__init__.py +4 -2
  89. edsl/tasks/task_history.py +198 -36
  90. edsl/tests/scenarios/test_ScenarioSource.py +51 -0
  91. edsl/tests/scenarios/test_scenario_list_sources.py +51 -0
  92. edsl/utilities/__init__.py +2 -1
  93. edsl/utilities/decorators.py +121 -0
  94. edsl/utilities/memory_debugger.py +1010 -0
  95. {edsl-0.1.54.dist-info → edsl-0.1.55.dist-info}/METADATA +51 -76
  96. {edsl-0.1.54.dist-info → edsl-0.1.55.dist-info}/RECORD +99 -75
  97. edsl/jobs/jobs_runner_asyncio.py +0 -281
  98. edsl/language_models/unused/fake_openai_service.py +0 -60
  99. {edsl-0.1.54.dist-info → edsl-0.1.55.dist-info}/LICENSE +0 -0
  100. {edsl-0.1.54.dist-info → edsl-0.1.55.dist-info}/WHEEL +0 -0
  101. {edsl-0.1.54.dist-info → edsl-0.1.55.dist-info}/entry_points.txt +0 -0
@@ -1,6 +1,14 @@
1
1
  import functools
2
2
  import asyncio
3
3
  import nest_asyncio
4
+ import os
5
+ import gc
6
+ import time
7
+ import json
8
+ import psutil
9
+ import tracemalloc
10
+ from datetime import datetime
11
+ from pathlib import Path
4
12
  from edsl import __version__ as edsl_version
5
13
 
6
14
  nest_asyncio.apply()
@@ -74,3 +82,116 @@ def sync_wrapper(async_func):
74
82
  return asyncio.run(async_func(*args, **kwargs))
75
83
 
76
84
  return wrapper
85
+
86
+
87
+ def memory_profile(func):
88
+ """
89
+ Decorator to profile memory usage of a function.
90
+
91
+ Only activates if the EDSL_MEMORY_PROFILE environment variable is set to 'true'
92
+ or if the function name is included in the EDSL_MEMORY_PROFILE_FUNCTIONS
93
+ environment variable (comma-separated list of function names).
94
+
95
+ Example:
96
+ EDSL_MEMORY_PROFILE=true python your_script.py
97
+ EDSL_MEMORY_PROFILE_FUNCTIONS=filter,duplicate python your_script.py
98
+ """
99
+ @functools.wraps(func)
100
+ def wrapper(*args, **kwargs):
101
+ # Check if memory profiling is enabled
102
+ profile_env = os.environ.get('EDSL_MEMORY_PROFILE', '').lower() == 'true'
103
+ profile_functions = os.environ.get('EDSL_MEMORY_PROFILE_FUNCTIONS', '')
104
+ profile_func_list = [f.strip() for f in profile_functions.split(',') if f.strip()]
105
+
106
+ # Determine if this function should be profiled
107
+ should_profile = profile_env or func.__name__ in profile_func_list
108
+
109
+ if not should_profile:
110
+ # Normal execution if profiling is disabled
111
+ return func(*args, **kwargs)
112
+
113
+ # Begin memory profiling
114
+ # Force garbage collection before measuring
115
+ gc.collect()
116
+ gc.collect()
117
+
118
+ # Get process for memory measurements
119
+ process = psutil.Process(os.getpid())
120
+
121
+ # Start memory tracking
122
+ tracemalloc.start()
123
+
124
+ # Record starting memory
125
+ memory_before = process.memory_info().rss / (1024 * 1024) # MB
126
+ snapshot1 = tracemalloc.take_snapshot()
127
+ start_time = time.time()
128
+
129
+ # Execute the function
130
+ result = func(*args, **kwargs)
131
+
132
+ # Record ending stats
133
+ end_time = time.time()
134
+ snapshot2 = tracemalloc.take_snapshot()
135
+ memory_after = process.memory_info().rss / (1024 * 1024) # MB
136
+
137
+ # Calculate differences
138
+ execution_time = end_time - start_time
139
+ memory_diff = memory_after - memory_before
140
+
141
+ # Get top memory differences
142
+ top_stats = snapshot2.compare_to(snapshot1, 'lineno')
143
+
144
+ # Prepare stats for report and JSON
145
+ timestamp = datetime.now().strftime('%Y-%m-%d %H:%M:%S')
146
+ stats = {
147
+ "timestamp": timestamp,
148
+ "function": func.__qualname__,
149
+ "execution_time_seconds": execution_time,
150
+ "memory_before_mb": memory_before,
151
+ "memory_after_mb": memory_after,
152
+ "memory_diff_mb": memory_diff,
153
+ "top_allocations": [
154
+ {
155
+ "file": stat.traceback.format()[0],
156
+ "size_kb": stat.size_diff / 1024
157
+ } for stat in top_stats[:10]
158
+ ]
159
+ }
160
+
161
+ # Generate console report
162
+ print("\n" + "="*60)
163
+ print(f"MEMORY PROFILE REPORT - {func.__name__}")
164
+ print("="*60)
165
+ print(f"Timestamp: {timestamp}")
166
+ print(f"Function: {func.__qualname__}")
167
+ print("-"*60)
168
+ print(f"Execution time: {execution_time:.4f} seconds")
169
+ print(f"Memory before: {memory_before:.2f} MB")
170
+ print(f"Memory after: {memory_after:.2f} MB")
171
+ print(f"Memory difference: {memory_diff:.2f} MB")
172
+ print("-"*60)
173
+ print("Top 10 memory allocations by line:")
174
+ for stat in top_stats[:10]:
175
+ print(f"{stat.traceback.format()[0]} - {stat.size_diff / 1024:.2f} KB")
176
+ print("="*60)
177
+
178
+ # Save report to file if EDSL_MEMORY_PROFILE_SAVE is true
179
+ if os.environ.get('EDSL_MEMORY_PROFILE_SAVE', '').lower() == 'true':
180
+ report_dir = Path("./benchmark_logs/memory_reports")
181
+ report_dir.mkdir(parents=True, exist_ok=True)
182
+
183
+ # Create filename with timestamp and function name
184
+ timestamp_file = datetime.now().strftime('%Y%m%d_%H%M%S')
185
+ report_path = report_dir / f"{func.__name__}_{timestamp_file}.json"
186
+
187
+ with open(report_path, 'w') as f:
188
+ json.dump(stats, f, indent=2)
189
+
190
+ print(f"Memory profile report saved to: {report_path}")
191
+
192
+ # Stop memory tracking
193
+ tracemalloc.stop()
194
+
195
+ return result
196
+
197
+ return wrapper