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.
- edsl/__init__.py +8 -1
- edsl/__init__original.py +134 -0
- edsl/__version__.py +1 -1
- edsl/agents/agent.py +29 -0
- edsl/agents/agent_list.py +36 -1
- edsl/base/base_class.py +281 -151
- edsl/buckets/__init__.py +8 -3
- edsl/buckets/bucket_collection.py +9 -3
- edsl/buckets/model_buckets.py +4 -2
- edsl/buckets/token_bucket.py +2 -2
- edsl/buckets/token_bucket_client.py +5 -3
- edsl/caching/cache.py +131 -62
- edsl/caching/cache_entry.py +70 -58
- edsl/caching/sql_dict.py +17 -0
- edsl/cli.py +99 -0
- edsl/config/config_class.py +16 -0
- edsl/conversation/__init__.py +31 -0
- edsl/coop/coop.py +276 -242
- edsl/coop/coop_jobs_objects.py +59 -0
- edsl/coop/coop_objects.py +29 -0
- edsl/coop/coop_regular_objects.py +26 -0
- edsl/coop/utils.py +24 -19
- edsl/dataset/dataset.py +338 -101
- edsl/db_list/sqlite_list.py +349 -0
- edsl/inference_services/__init__.py +40 -5
- edsl/inference_services/exceptions.py +11 -0
- edsl/inference_services/services/anthropic_service.py +5 -2
- edsl/inference_services/services/aws_bedrock.py +6 -2
- edsl/inference_services/services/azure_ai.py +6 -2
- edsl/inference_services/services/google_service.py +3 -2
- edsl/inference_services/services/mistral_ai_service.py +6 -2
- edsl/inference_services/services/open_ai_service.py +6 -2
- edsl/inference_services/services/perplexity_service.py +6 -2
- edsl/inference_services/services/test_service.py +94 -5
- edsl/interviews/answering_function.py +167 -59
- edsl/interviews/interview.py +124 -72
- edsl/interviews/interview_task_manager.py +10 -0
- edsl/invigilators/invigilators.py +9 -0
- edsl/jobs/async_interview_runner.py +146 -104
- edsl/jobs/data_structures.py +6 -4
- edsl/jobs/decorators.py +61 -0
- edsl/jobs/fetch_invigilator.py +61 -18
- edsl/jobs/html_table_job_logger.py +14 -2
- edsl/jobs/jobs.py +180 -104
- edsl/jobs/jobs_component_constructor.py +2 -2
- edsl/jobs/jobs_interview_constructor.py +2 -0
- edsl/jobs/jobs_remote_inference_logger.py +4 -0
- edsl/jobs/jobs_runner_status.py +30 -25
- edsl/jobs/progress_bar_manager.py +79 -0
- edsl/jobs/remote_inference.py +35 -1
- edsl/key_management/key_lookup_builder.py +6 -1
- edsl/language_models/language_model.py +86 -6
- edsl/language_models/model.py +10 -3
- edsl/language_models/price_manager.py +45 -75
- edsl/language_models/registry.py +5 -0
- edsl/notebooks/notebook.py +77 -10
- edsl/questions/VALIDATION_README.md +134 -0
- edsl/questions/__init__.py +24 -1
- edsl/questions/exceptions.py +21 -0
- edsl/questions/question_dict.py +201 -16
- edsl/questions/question_multiple_choice_with_other.py +624 -0
- edsl/questions/question_registry.py +2 -1
- edsl/questions/templates/multiple_choice_with_other/__init__.py +0 -0
- edsl/questions/templates/multiple_choice_with_other/answering_instructions.jinja +15 -0
- edsl/questions/templates/multiple_choice_with_other/question_presentation.jinja +17 -0
- edsl/questions/validation_analysis.py +185 -0
- edsl/questions/validation_cli.py +131 -0
- edsl/questions/validation_html_report.py +404 -0
- edsl/questions/validation_logger.py +136 -0
- edsl/results/result.py +63 -16
- edsl/results/results.py +702 -171
- edsl/scenarios/construct_download_link.py +16 -3
- edsl/scenarios/directory_scanner.py +226 -226
- edsl/scenarios/file_methods.py +5 -0
- edsl/scenarios/file_store.py +117 -6
- edsl/scenarios/handlers/__init__.py +5 -1
- edsl/scenarios/handlers/mp4_file_store.py +104 -0
- edsl/scenarios/handlers/webm_file_store.py +104 -0
- edsl/scenarios/scenario.py +120 -101
- edsl/scenarios/scenario_list.py +800 -727
- edsl/scenarios/scenario_list_gc_test.py +146 -0
- edsl/scenarios/scenario_list_memory_test.py +214 -0
- edsl/scenarios/scenario_list_source_refactor.md +35 -0
- edsl/scenarios/scenario_selector.py +5 -4
- edsl/scenarios/scenario_source.py +1990 -0
- edsl/scenarios/tests/test_scenario_list_sources.py +52 -0
- edsl/surveys/survey.py +22 -0
- edsl/tasks/__init__.py +4 -2
- edsl/tasks/task_history.py +198 -36
- edsl/tests/scenarios/test_ScenarioSource.py +51 -0
- edsl/tests/scenarios/test_scenario_list_sources.py +51 -0
- edsl/utilities/__init__.py +2 -1
- edsl/utilities/decorators.py +121 -0
- edsl/utilities/memory_debugger.py +1010 -0
- {edsl-0.1.54.dist-info → edsl-0.1.55.dist-info}/METADATA +51 -76
- {edsl-0.1.54.dist-info → edsl-0.1.55.dist-info}/RECORD +99 -75
- edsl/jobs/jobs_runner_asyncio.py +0 -281
- edsl/language_models/unused/fake_openai_service.py +0 -60
- {edsl-0.1.54.dist-info → edsl-0.1.55.dist-info}/LICENSE +0 -0
- {edsl-0.1.54.dist-info → edsl-0.1.55.dist-info}/WHEEL +0 -0
- {edsl-0.1.54.dist-info → edsl-0.1.55.dist-info}/entry_points.txt +0 -0
edsl/caching/cache_entry.py
CHANGED
@@ -21,12 +21,12 @@ from .exceptions import CacheError
|
|
21
21
|
class CacheEntry(RepresentationMixin):
|
22
22
|
"""
|
23
23
|
Represents a single cached language model response with associated metadata.
|
24
|
-
|
24
|
+
|
25
25
|
CacheEntry objects store language model responses along with the prompts and
|
26
26
|
parameters that generated them. Each entry is uniquely identified by a hash
|
27
|
-
of its key fields (model, parameters, prompts, and iteration), making it
|
27
|
+
of its key fields (model, parameters, prompts, and iteration), making it
|
28
28
|
possible to efficiently retrieve cached responses for identical inputs.
|
29
|
-
|
29
|
+
|
30
30
|
Attributes:
|
31
31
|
model (str): The language model identifier (e.g., "gpt-3.5-turbo")
|
32
32
|
parameters (dict): Model parameters used for generation (e.g., temperature)
|
@@ -37,14 +37,14 @@ class CacheEntry(RepresentationMixin):
|
|
37
37
|
with the same prompts (defaults to 0)
|
38
38
|
timestamp (int): Unix timestamp when the entry was created
|
39
39
|
service (str, optional): The service provider for the model (e.g., "openai")
|
40
|
-
|
40
|
+
|
41
41
|
Class Attributes:
|
42
42
|
key_fields (List[str]): Fields used to generate the unique hash key
|
43
43
|
all_fields (List[str]): All fields stored in the cache entry
|
44
44
|
"""
|
45
45
|
|
46
46
|
key_fields = ["model", "parameters", "system_prompt", "user_prompt", "iteration"]
|
47
|
-
all_fields = key_fields + ["timestamp", "output", "service"]
|
47
|
+
all_fields = key_fields + ["timestamp", "output", "service", "validated"]
|
48
48
|
|
49
49
|
def __init__(
|
50
50
|
self,
|
@@ -57,6 +57,7 @@ class CacheEntry(RepresentationMixin):
|
|
57
57
|
output: str,
|
58
58
|
timestamp: Optional[int] = None,
|
59
59
|
service: Optional[str] = None,
|
60
|
+
validated: bool = False,
|
60
61
|
):
|
61
62
|
self.model = model
|
62
63
|
self.parameters = parameters
|
@@ -68,16 +69,17 @@ class CacheEntry(RepresentationMixin):
|
|
68
69
|
datetime.datetime.now(datetime.timezone.utc).timestamp()
|
69
70
|
)
|
70
71
|
self.service = service
|
72
|
+
self.validated = validated
|
71
73
|
self._check_types()
|
72
74
|
|
73
75
|
def _check_types(self) -> None:
|
74
76
|
"""
|
75
77
|
Validates that all attributes have the correct types.
|
76
|
-
|
78
|
+
|
77
79
|
This method is called during initialization to ensure that all
|
78
80
|
attributes have the expected types, raising TypeError exceptions
|
79
81
|
with descriptive messages when validation fails.
|
80
|
-
|
82
|
+
|
81
83
|
Raises:
|
82
84
|
TypeError: If any attribute has an incorrect type
|
83
85
|
"""
|
@@ -98,31 +100,38 @@ class CacheEntry(RepresentationMixin):
|
|
98
100
|
raise CacheError("`timestamp` should be an integer")
|
99
101
|
if self.service is not None and not isinstance(self.service, str):
|
100
102
|
raise CacheError("`service` should be either a string or None")
|
103
|
+
if not isinstance(self.validated, bool):
|
104
|
+
raise CacheError("`validated` should be a boolean")
|
101
105
|
|
102
106
|
@classmethod
|
103
107
|
def gen_key(
|
104
|
-
cls,
|
105
|
-
|
108
|
+
cls,
|
109
|
+
*,
|
110
|
+
model: str,
|
111
|
+
parameters: Dict[str, Any],
|
112
|
+
system_prompt: str,
|
113
|
+
user_prompt: str,
|
114
|
+
iteration: int,
|
106
115
|
) -> str:
|
107
116
|
"""
|
108
117
|
Generates a unique key hash for the cache entry based on input parameters.
|
109
|
-
|
118
|
+
|
110
119
|
This method creates a deterministic hash key by concatenating the model name,
|
111
120
|
parameters (sorted to ensure consistency), system prompt, user prompt, and
|
112
121
|
iteration number. The hash enables efficient lookup of cache entries with
|
113
122
|
identical inputs.
|
114
|
-
|
123
|
+
|
115
124
|
Args:
|
116
125
|
model: The language model identifier
|
117
126
|
parameters: Dictionary of model parameters (will be sorted for consistency)
|
118
127
|
system_prompt: The system prompt provided to the model
|
119
128
|
user_prompt: The user prompt provided to the model
|
120
129
|
iteration: Iteration number for this combination of inputs
|
121
|
-
|
130
|
+
|
122
131
|
Returns:
|
123
132
|
A hex-encoded MD5 hash string that uniquely identifies this combination
|
124
133
|
of inputs
|
125
|
-
|
134
|
+
|
126
135
|
Note:
|
127
136
|
- The hash treats single and double quotes as equivalent
|
128
137
|
- Parameters are sorted to ensure consistent hashing regardless of order
|
@@ -134,11 +143,11 @@ class CacheEntry(RepresentationMixin):
|
|
134
143
|
def key(self) -> str:
|
135
144
|
"""
|
136
145
|
Returns the unique hash key for this cache entry.
|
137
|
-
|
146
|
+
|
138
147
|
This property extracts the key fields from the instance and generates
|
139
148
|
a hash key using the gen_key classmethod. The key uniquely identifies
|
140
149
|
this combination of model, parameters, prompts, and iteration.
|
141
|
-
|
150
|
+
|
142
151
|
Returns:
|
143
152
|
A hex-encoded MD5 hash string that uniquely identifies this cache entry
|
144
153
|
"""
|
@@ -148,17 +157,17 @@ class CacheEntry(RepresentationMixin):
|
|
148
157
|
def to_dict(self, add_edsl_version: bool = True) -> Dict[str, Any]:
|
149
158
|
"""
|
150
159
|
Converts the cache entry to a dictionary representation.
|
151
|
-
|
160
|
+
|
152
161
|
This method creates a dictionary containing all fields of the cache entry,
|
153
162
|
making it suitable for serialization or storage.
|
154
|
-
|
163
|
+
|
155
164
|
Args:
|
156
165
|
add_edsl_version: If True, adds EDSL version information to the dict
|
157
166
|
(Currently disabled pending implementation)
|
158
|
-
|
167
|
+
|
159
168
|
Returns:
|
160
169
|
A dictionary representation of the cache entry with all fields
|
161
|
-
|
170
|
+
|
162
171
|
Note:
|
163
172
|
The edsl_version feature is currently disabled in the implementation
|
164
173
|
"""
|
@@ -171,6 +180,7 @@ class CacheEntry(RepresentationMixin):
|
|
171
180
|
"iteration": self.iteration,
|
172
181
|
"timestamp": self.timestamp,
|
173
182
|
"service": self.service,
|
183
|
+
"validated": self.validated,
|
174
184
|
}
|
175
185
|
# Feature for adding version information (currently disabled)
|
176
186
|
# if add_edsl_version:
|
@@ -182,9 +192,9 @@ class CacheEntry(RepresentationMixin):
|
|
182
192
|
def keys(self) -> List[str]:
|
183
193
|
"""
|
184
194
|
Returns a list of field names in this cache entry.
|
185
|
-
|
195
|
+
|
186
196
|
This method enables dict-like access to cache entry field names.
|
187
|
-
|
197
|
+
|
188
198
|
Returns:
|
189
199
|
List of field names from the dictionary representation
|
190
200
|
"""
|
@@ -193,9 +203,9 @@ class CacheEntry(RepresentationMixin):
|
|
193
203
|
def values(self) -> List[Any]:
|
194
204
|
"""
|
195
205
|
Returns a list of values for all fields in this cache entry.
|
196
|
-
|
206
|
+
|
197
207
|
This method enables dict-like access to cache entry values.
|
198
|
-
|
208
|
+
|
199
209
|
Returns:
|
200
210
|
List of values from the dictionary representation
|
201
211
|
"""
|
@@ -204,16 +214,16 @@ class CacheEntry(RepresentationMixin):
|
|
204
214
|
def __getitem__(self, key: str) -> Any:
|
205
215
|
"""
|
206
216
|
Enables dictionary-style access to cache entry attributes.
|
207
|
-
|
217
|
+
|
208
218
|
This method allows accessing cache entry attributes using dictionary
|
209
219
|
syntax (e.g., entry["model"] instead of entry.model).
|
210
|
-
|
220
|
+
|
211
221
|
Args:
|
212
222
|
key: The name of the attribute to access
|
213
|
-
|
223
|
+
|
214
224
|
Returns:
|
215
225
|
The value of the specified attribute
|
216
|
-
|
226
|
+
|
217
227
|
Raises:
|
218
228
|
AttributeError: If the specified attribute doesn't exist
|
219
229
|
"""
|
@@ -223,17 +233,17 @@ class CacheEntry(RepresentationMixin):
|
|
223
233
|
def from_dict(cls, data: Dict[str, Any]) -> CacheEntry:
|
224
234
|
"""
|
225
235
|
Creates a CacheEntry object from a dictionary representation.
|
226
|
-
|
236
|
+
|
227
237
|
This factory method enables reconstruction of CacheEntry objects
|
228
238
|
from serialized dictionary representations, such as those produced
|
229
239
|
by the to_dict method.
|
230
|
-
|
240
|
+
|
231
241
|
Args:
|
232
242
|
data: Dictionary containing required CacheEntry fields
|
233
|
-
|
243
|
+
|
234
244
|
Returns:
|
235
245
|
A new CacheEntry instance with fields populated from the dictionary
|
236
|
-
|
246
|
+
|
237
247
|
Raises:
|
238
248
|
TypeError: If data contains fields with incorrect types
|
239
249
|
KeyError: If required fields are missing from data
|
@@ -243,18 +253,18 @@ class CacheEntry(RepresentationMixin):
|
|
243
253
|
def __eq__(self, other: Any) -> bool:
|
244
254
|
"""
|
245
255
|
Compares this cache entry with another for equality.
|
246
|
-
|
256
|
+
|
247
257
|
This method checks if all fields except timestamp are equal between
|
248
|
-
this cache entry and another. The timestamp is excluded from the
|
258
|
+
this cache entry and another. The timestamp is excluded from the
|
249
259
|
comparison because it's typically not relevant for determining if
|
250
260
|
two entries represent the same cached response.
|
251
|
-
|
261
|
+
|
252
262
|
Args:
|
253
263
|
other: Another object to compare with this cache entry
|
254
|
-
|
264
|
+
|
255
265
|
Returns:
|
256
266
|
True if all fields except timestamp are equal, False otherwise
|
257
|
-
|
267
|
+
|
258
268
|
Note:
|
259
269
|
Returns False if other is not a CacheEntry instance
|
260
270
|
"""
|
@@ -268,11 +278,11 @@ class CacheEntry(RepresentationMixin):
|
|
268
278
|
def __repr__(self) -> str:
|
269
279
|
"""
|
270
280
|
Returns a string representation of this cache entry.
|
271
|
-
|
281
|
+
|
272
282
|
This method creates a string representation that displays all fields
|
273
283
|
of the cache entry in a format that can be evaluated to recreate
|
274
284
|
the object.
|
275
|
-
|
285
|
+
|
276
286
|
Returns:
|
277
287
|
A string representation that can be passed to eval() to recreate
|
278
288
|
this cache entry
|
@@ -285,24 +295,25 @@ class CacheEntry(RepresentationMixin):
|
|
285
295
|
f"output={repr(self.output)}, "
|
286
296
|
f"iteration={self.iteration}, "
|
287
297
|
f"timestamp={self.timestamp}, "
|
288
|
-
f"service={repr(self.service)}
|
298
|
+
f"service={repr(self.service)}, "
|
299
|
+
f"validated={self.validated})"
|
289
300
|
)
|
290
301
|
|
291
302
|
@classmethod
|
292
303
|
def example(cls, randomize: bool = False) -> CacheEntry:
|
293
304
|
"""
|
294
305
|
Creates an example CacheEntry instance for testing and demonstration.
|
295
|
-
|
306
|
+
|
296
307
|
This factory method generates a pre-populated CacheEntry with example
|
297
308
|
values, useful for testing, documentation, and examples.
|
298
|
-
|
309
|
+
|
299
310
|
Args:
|
300
311
|
randomize: If True, adds a random UUID to the system prompt to make
|
301
312
|
the entry unique and generate a different hash key
|
302
|
-
|
313
|
+
|
303
314
|
Returns:
|
304
315
|
A fully populated example CacheEntry instance
|
305
|
-
|
316
|
+
|
306
317
|
Example:
|
307
318
|
>>> entry = CacheEntry.example()
|
308
319
|
>>> isinstance(entry, CacheEntry)
|
@@ -320,20 +331,21 @@ class CacheEntry(RepresentationMixin):
|
|
320
331
|
iteration=1,
|
321
332
|
timestamp=int(datetime.datetime.now(datetime.timezone.utc).timestamp()),
|
322
333
|
service="openai",
|
334
|
+
validated=True,
|
323
335
|
)
|
324
336
|
|
325
337
|
@classmethod
|
326
338
|
def example_dict(cls) -> Dict[str, CacheEntry]:
|
327
339
|
"""
|
328
340
|
Creates an example dictionary mapping a key to a CacheEntry.
|
329
|
-
|
341
|
+
|
330
342
|
This method demonstrates how CacheEntry objects are typically stored
|
331
343
|
in a cache, with their hash keys as dictionary keys.
|
332
|
-
|
344
|
+
|
333
345
|
Returns:
|
334
346
|
A dictionary with a single entry mapping the example entry's key
|
335
347
|
to the example entry
|
336
|
-
|
348
|
+
|
337
349
|
Note:
|
338
350
|
This is particularly useful for testing and demonstrating the
|
339
351
|
Cache class functionality
|
@@ -345,13 +357,13 @@ class CacheEntry(RepresentationMixin):
|
|
345
357
|
def fetch_input_example(cls) -> Dict[str, Any]:
|
346
358
|
"""
|
347
359
|
Creates an example input dictionary for a 'fetch' operation.
|
348
|
-
|
360
|
+
|
349
361
|
This method generates a dictionary containing the fields needed to
|
350
362
|
look up a cache entry (everything except the response/output fields).
|
351
|
-
|
363
|
+
|
352
364
|
Returns:
|
353
365
|
A dictionary with fields needed to generate a cache key for lookup
|
354
|
-
|
366
|
+
|
355
367
|
Note:
|
356
368
|
This is used by the Cache class to demonstrate fetch operations
|
357
369
|
"""
|
@@ -365,14 +377,14 @@ class CacheEntry(RepresentationMixin):
|
|
365
377
|
def store_input_example(cls) -> Dict[str, Any]:
|
366
378
|
"""
|
367
379
|
Creates an example input dictionary for a 'store' operation.
|
368
|
-
|
380
|
+
|
369
381
|
This method generates a dictionary containing the fields needed to
|
370
382
|
store a new cache entry, with 'output' renamed to 'response' to match
|
371
383
|
the API of the Cache.store method.
|
372
|
-
|
384
|
+
|
373
385
|
Returns:
|
374
386
|
A dictionary with fields needed to store a new cache entry
|
375
|
-
|
387
|
+
|
376
388
|
Note:
|
377
389
|
This is used by the Cache class to demonstrate store operations
|
378
390
|
"""
|
@@ -385,11 +397,11 @@ class CacheEntry(RepresentationMixin):
|
|
385
397
|
def main() -> None:
|
386
398
|
"""
|
387
399
|
Demonstration of CacheEntry functionality for interactive testing.
|
388
|
-
|
400
|
+
|
389
401
|
This function demonstrates the key features of the CacheEntry class,
|
390
402
|
including creating entries, calculating hash keys, converting to/from
|
391
403
|
dictionaries, and comparing entries.
|
392
|
-
|
404
|
+
|
393
405
|
Note:
|
394
406
|
This function is intended to be run in an interactive Python session
|
395
407
|
for exploration and testing, not as part of normal code execution.
|
@@ -402,20 +414,20 @@ def main() -> None:
|
|
402
414
|
|
403
415
|
# Demonstrate key generation
|
404
416
|
print(f"Cache key: {cache_entry.key}")
|
405
|
-
|
417
|
+
|
406
418
|
# Demonstrate serialization and deserialization
|
407
419
|
entry_dict = cache_entry.to_dict()
|
408
420
|
print(f"Dictionary representation: {entry_dict}")
|
409
421
|
reconstructed = CacheEntry.from_dict(entry_dict)
|
410
422
|
print(f"Reconstructed from dict: {reconstructed}")
|
411
|
-
|
423
|
+
|
412
424
|
# Demonstrate equality comparisons
|
413
425
|
print(f"Same content equals: {cache_entry == CacheEntry.example()}")
|
414
426
|
print(f"Same key equals: {cache_entry.key == CacheEntry.example().key}")
|
415
|
-
|
427
|
+
|
416
428
|
# Demonstrate repr evaluation
|
417
429
|
print(f"Repr can be evaluated: {eval(repr(cache_entry)) == cache_entry}")
|
418
|
-
|
430
|
+
|
419
431
|
# Demonstrate utility methods
|
420
432
|
print(f"Example dict: {CacheEntry.example_dict()}")
|
421
433
|
print(f"Fetch input example: {CacheEntry.fetch_input_example()}")
|
edsl/caching/sql_dict.py
CHANGED
@@ -363,6 +363,23 @@ class SQLiteDict:
|
|
363
363
|
|
364
364
|
def __repr__(self) -> str:
|
365
365
|
return f"{self.__class__.__name__}(db_path={self.db_path!r})"
|
366
|
+
|
367
|
+
def close(self):
|
368
|
+
"""Close database connections and clean up resources.
|
369
|
+
|
370
|
+
This method properly disposes of the SQLAlchemy engine,
|
371
|
+
closing all connections in the pool to prevent memory leaks.
|
372
|
+
"""
|
373
|
+
if hasattr(self, 'engine') and self.engine:
|
374
|
+
self.engine.dispose()
|
375
|
+
|
376
|
+
def __del__(self):
|
377
|
+
"""Destructor for proper resource cleanup.
|
378
|
+
|
379
|
+
Ensures SQLAlchemy connections are properly closed when the
|
380
|
+
object is garbage collected.
|
381
|
+
"""
|
382
|
+
self.close()
|
366
383
|
|
367
384
|
@classmethod
|
368
385
|
def example(cls) -> SQLiteDict:
|
edsl/cli.py
CHANGED
@@ -6,6 +6,8 @@ This module provides the main entry point for the EDSL command-line tool.
|
|
6
6
|
|
7
7
|
import sys
|
8
8
|
import typer
|
9
|
+
import json
|
10
|
+
from pathlib import Path
|
9
11
|
from typing import Optional
|
10
12
|
from rich.console import Console
|
11
13
|
from importlib import metadata
|
@@ -20,6 +22,103 @@ from .plugins.cli_typer import app as plugins_app
|
|
20
22
|
# Add the plugins subcommand
|
21
23
|
app.add_typer(plugins_app, name="plugins")
|
22
24
|
|
25
|
+
# Create the validation app
|
26
|
+
validation_app = typer.Typer(help="Manage EDSL validation failures")
|
27
|
+
app.add_typer(validation_app, name="validation")
|
28
|
+
|
29
|
+
@validation_app.command("logs")
|
30
|
+
def list_validation_logs(
|
31
|
+
count: int = typer.Option(10, "--count", "-n", help="Number of logs to show"),
|
32
|
+
question_type: Optional[str] = typer.Option(None, "--type", "-t", help="Filter by question type"),
|
33
|
+
output: Optional[Path] = typer.Option(None, "--output", "-o", help="Output file path"),
|
34
|
+
):
|
35
|
+
"""List validation failure logs."""
|
36
|
+
from .questions.validation_logger import get_validation_failure_logs
|
37
|
+
|
38
|
+
logs = get_validation_failure_logs(n=count)
|
39
|
+
|
40
|
+
# Filter by question type if provided
|
41
|
+
if question_type:
|
42
|
+
logs = [log for log in logs if log.get("question_type") == question_type]
|
43
|
+
|
44
|
+
if output:
|
45
|
+
with open(output, "w") as f:
|
46
|
+
json.dump(logs, f, indent=2)
|
47
|
+
console.print(f"[green]Logs written to {output}[/green]")
|
48
|
+
else:
|
49
|
+
console.print_json(json.dumps(logs, indent=2))
|
50
|
+
|
51
|
+
@validation_app.command("clear")
|
52
|
+
def clear_validation_logs():
|
53
|
+
"""Clear validation failure logs."""
|
54
|
+
from .questions.validation_logger import clear_validation_logs
|
55
|
+
|
56
|
+
clear_validation_logs()
|
57
|
+
console.print("[green]Validation logs cleared.[/green]")
|
58
|
+
|
59
|
+
@validation_app.command("stats")
|
60
|
+
def validation_stats(
|
61
|
+
output: Optional[Path] = typer.Option(None, "--output", "-o", help="Output file path"),
|
62
|
+
):
|
63
|
+
"""Show validation failure statistics."""
|
64
|
+
from .questions.validation_analysis import get_validation_failure_stats
|
65
|
+
|
66
|
+
stats = get_validation_failure_stats()
|
67
|
+
|
68
|
+
if output:
|
69
|
+
with open(output, "w") as f:
|
70
|
+
json.dump(stats, f, indent=2)
|
71
|
+
console.print(f"[green]Stats written to {output}[/green]")
|
72
|
+
else:
|
73
|
+
console.print_json(json.dumps(stats, indent=2))
|
74
|
+
|
75
|
+
@validation_app.command("suggest")
|
76
|
+
def suggest_improvements(
|
77
|
+
question_type: Optional[str] = typer.Option(None, "--type", "-t", help="Filter by question type"),
|
78
|
+
output: Optional[Path] = typer.Option(None, "--output", "-o", help="Output file path"),
|
79
|
+
):
|
80
|
+
"""Suggest improvements for fix methods."""
|
81
|
+
from .questions.validation_analysis import suggest_fix_improvements
|
82
|
+
|
83
|
+
suggestions = suggest_fix_improvements(question_type=question_type)
|
84
|
+
|
85
|
+
if output:
|
86
|
+
with open(output, "w") as f:
|
87
|
+
json.dump(suggestions, f, indent=2)
|
88
|
+
console.print(f"[green]Suggestions written to {output}[/green]")
|
89
|
+
else:
|
90
|
+
console.print_json(json.dumps(suggestions, indent=2))
|
91
|
+
|
92
|
+
@validation_app.command("report")
|
93
|
+
def generate_report(
|
94
|
+
output: Optional[Path] = typer.Option(None, "--output", "-o", help="Output file path"),
|
95
|
+
):
|
96
|
+
"""Generate a comprehensive validation report."""
|
97
|
+
from .questions.validation_analysis import export_improvements_report
|
98
|
+
|
99
|
+
report_path = export_improvements_report(output_path=output)
|
100
|
+
console.print(f"[green]Report generated at: {report_path}[/green]")
|
101
|
+
|
102
|
+
@validation_app.command("html-report")
|
103
|
+
def generate_html_report(
|
104
|
+
output: Optional[Path] = typer.Option(None, "--output", "-o", help="Output file path"),
|
105
|
+
open_browser: bool = typer.Option(True, "--open/--no-open", help="Open the report in a browser"),
|
106
|
+
):
|
107
|
+
"""Generate an HTML validation report and optionally open it in a browser."""
|
108
|
+
from .questions.validation_html_report import generate_html_report
|
109
|
+
import webbrowser
|
110
|
+
|
111
|
+
report_path = generate_html_report(output_path=output)
|
112
|
+
console.print(f"[green]HTML report generated at: {report_path}[/green]")
|
113
|
+
|
114
|
+
if open_browser:
|
115
|
+
try:
|
116
|
+
webbrowser.open(f"file://{report_path}")
|
117
|
+
console.print("[green]Opened report in browser[/green]")
|
118
|
+
except Exception as e:
|
119
|
+
console.print(f"[yellow]Could not open browser: {e}[/yellow]")
|
120
|
+
console.print(f"[yellow]Report is available at: {report_path}[/yellow]")
|
121
|
+
|
23
122
|
@app.callback()
|
24
123
|
def callback():
|
25
124
|
"""
|
edsl/config/config_class.py
CHANGED
@@ -58,6 +58,10 @@ CONFIG_MAP = {
|
|
58
58
|
"default": "True",
|
59
59
|
"info": "This config var determines whether to fetch prices for tokens used in remote inference",
|
60
60
|
},
|
61
|
+
"EDSL_LOG_DIR": {
|
62
|
+
"default": str(os.path.join(platformdirs.user_data_dir('edsl'), 'logs')),
|
63
|
+
"info": "This config var determines the directory where logs are stored.",
|
64
|
+
},
|
61
65
|
"EDSL_LOG_LEVEL": {
|
62
66
|
"default": "ERROR",
|
63
67
|
"info": "This config var determines the logging level for the EDSL package (DEBUG, INFO, WARNING, ERROR, CRITICAL).",
|
@@ -90,6 +94,18 @@ CONFIG_MAP = {
|
|
90
94
|
"default": "None",
|
91
95
|
"info": "This config var holds the URL of the remote token bucket server.",
|
92
96
|
},
|
97
|
+
"EDSL_SQLLIST_MEMORY_THRESHOLD": {
|
98
|
+
"default": "10", # Change to a very low threshold (10 bytes) to test SQLite offloading
|
99
|
+
"info": "This config var determines the memory threshold in bytes before SQLList offloads data to SQLite.",
|
100
|
+
},
|
101
|
+
"EDSL_SQLLIST_DB_PATH": {
|
102
|
+
"default": f"sqlite:///{os.path.join(platformdirs.user_cache_dir('edsl'), 'sql_list_data.db')}",
|
103
|
+
"info": "This config var determines the default database path for SQLList instances.",
|
104
|
+
},
|
105
|
+
"EDSL_RESULTS_MEMORY_THRESHOLD": {
|
106
|
+
"default": "10", # Change to a very low threshold (10 bytes) to test SQLite offloading
|
107
|
+
"info": "This config var determines the memory threshold in bytes before Results' SQLList offloads data to SQLite.",
|
108
|
+
},
|
93
109
|
}
|
94
110
|
|
95
111
|
|
@@ -0,0 +1,31 @@
|
|
1
|
+
"""
|
2
|
+
The conversation module provides tools for simulating conversations between agents.
|
3
|
+
|
4
|
+
It includes classes for managing dialogues, tracking statements, and controlling
|
5
|
+
conversation flow between multiple participants.
|
6
|
+
"""
|
7
|
+
|
8
|
+
from .Conversation import Conversation, ConversationList, AgentStatement, AgentStatements
|
9
|
+
from .exceptions import ConversationError, ConversationValueError, ConversationStateError
|
10
|
+
from .next_speaker_utilities import (
|
11
|
+
default_turn_taking_generator,
|
12
|
+
turn_taking_generator_with_focal_speaker,
|
13
|
+
random_turn_taking_generator,
|
14
|
+
random_inclusive_generator,
|
15
|
+
speaker_closure,
|
16
|
+
)
|
17
|
+
|
18
|
+
__all__ = [
|
19
|
+
"Conversation",
|
20
|
+
"ConversationList",
|
21
|
+
"AgentStatement",
|
22
|
+
"AgentStatements",
|
23
|
+
"ConversationError",
|
24
|
+
"ConversationValueError",
|
25
|
+
"ConversationStateError",
|
26
|
+
"default_turn_taking_generator",
|
27
|
+
"turn_taking_generator_with_focal_speaker",
|
28
|
+
"random_turn_taking_generator",
|
29
|
+
"random_inclusive_generator",
|
30
|
+
"speaker_closure",
|
31
|
+
]
|