edsl 0.1.46__py3-none-any.whl → 0.1.47__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/Base.py +86 -19
- edsl/__version__.py +1 -1
- edsl/coop/coop.py +134 -53
- edsl/data/Cache.py +2 -0
- edsl/data/CacheEntry.py +10 -2
- edsl/inference_services/PerplexityService.py +9 -5
- edsl/jobs/Jobs.py +20 -0
- edsl/jobs/JobsComponentConstructor.py +2 -1
- edsl/language_models/LanguageModel.py +6 -6
- edsl/questions/QuestionBase.py +5 -0
- edsl/questions/question_registry.py +6 -7
- edsl/results/DatasetExportMixin.py +99 -2
- edsl/results/Results.py +59 -0
- edsl/scenarios/FileStore.py +112 -7
- edsl/scenarios/ScenarioList.py +130 -0
- edsl/study/Study.py +2 -2
- edsl/surveys/Survey.py +15 -20
- {edsl-0.1.46.dist-info → edsl-0.1.47.dist-info}/METADATA +3 -2
- {edsl-0.1.46.dist-info → edsl-0.1.47.dist-info}/RECORD +21 -33
- edsl/auto/AutoStudy.py +0 -130
- edsl/auto/StageBase.py +0 -243
- edsl/auto/StageGenerateSurvey.py +0 -178
- edsl/auto/StageLabelQuestions.py +0 -125
- edsl/auto/StagePersona.py +0 -61
- edsl/auto/StagePersonaDimensionValueRanges.py +0 -88
- edsl/auto/StagePersonaDimensionValues.py +0 -74
- edsl/auto/StagePersonaDimensions.py +0 -69
- edsl/auto/StageQuestions.py +0 -74
- edsl/auto/SurveyCreatorPipeline.py +0 -21
- edsl/auto/utilities.py +0 -218
- edsl/base/Base.py +0 -279
- {edsl-0.1.46.dist-info → edsl-0.1.47.dist-info}/LICENSE +0 -0
- {edsl-0.1.46.dist-info → edsl-0.1.47.dist-info}/WHEEL +0 -0
edsl/Base.py
CHANGED
@@ -65,13 +65,11 @@ class PersistenceMixin:
|
|
65
65
|
def pull(
|
66
66
|
cls,
|
67
67
|
url_or_uuid: Optional[Union[str, UUID]] = None,
|
68
|
-
# expected_parrot_url: Optional[str] = None,
|
69
68
|
):
|
70
69
|
"""Pull the object from coop.
|
71
70
|
|
72
71
|
Args:
|
73
72
|
url_or_uuid: Either a UUID string or a URL pointing to the object
|
74
|
-
expected_parrot_url: Optional URL for the Parrot server
|
75
73
|
"""
|
76
74
|
from edsl.coop import Coop
|
77
75
|
from edsl.coop.utils import ObjectRegistry
|
@@ -79,36 +77,27 @@ class PersistenceMixin:
|
|
79
77
|
object_type = ObjectRegistry.get_object_type_by_edsl_class(cls)
|
80
78
|
coop = Coop()
|
81
79
|
|
82
|
-
|
83
|
-
if "www" in url_or_uuid:
|
84
|
-
url_or_uuid = url_or_uuid.replace("www", "api")
|
85
|
-
if url_or_uuid and (
|
86
|
-
"http://" in str(url_or_uuid) or "https://" in str(url_or_uuid)
|
87
|
-
):
|
88
|
-
return coop.get(url=url_or_uuid, expected_object_type=object_type)
|
89
|
-
else:
|
90
|
-
return coop.get(uuid=url_or_uuid, expected_object_type=object_type)
|
80
|
+
return coop.get(url_or_uuid, expected_object_type=object_type)
|
91
81
|
|
92
82
|
@classmethod
|
93
|
-
def delete(cls,
|
83
|
+
def delete(cls, url_or_uuid: Union[str, UUID]) -> None:
|
94
84
|
"""Delete the object from coop."""
|
95
85
|
from edsl.coop import Coop
|
96
86
|
|
97
87
|
coop = Coop()
|
98
|
-
|
88
|
+
|
89
|
+
return coop.delete(url_or_uuid)
|
99
90
|
|
100
91
|
@classmethod
|
101
|
-
def
|
92
|
+
def patch_cls(
|
102
93
|
cls,
|
103
|
-
|
104
|
-
url: Optional[str] = None,
|
94
|
+
url_or_uuid: Union[str, UUID],
|
105
95
|
description: Optional[str] = None,
|
106
|
-
alias: Optional[str] = None,
|
107
96
|
value: Optional[Any] = None,
|
108
97
|
visibility: Optional[str] = None,
|
109
98
|
):
|
110
99
|
"""
|
111
|
-
Patch an uploaded
|
100
|
+
Patch an uploaded object's attributes (class method version).
|
112
101
|
- `description` changes the description of the object on Coop
|
113
102
|
- `value` changes the value of the object on Coop. **has to be an EDSL object**
|
114
103
|
- `visibility` changes the visibility of the object on Coop
|
@@ -116,7 +105,85 @@ class PersistenceMixin:
|
|
116
105
|
from edsl.coop import Coop
|
117
106
|
|
118
107
|
coop = Coop()
|
119
|
-
|
108
|
+
|
109
|
+
return coop.patch(
|
110
|
+
url_or_uuid=url_or_uuid,
|
111
|
+
description=description,
|
112
|
+
value=value,
|
113
|
+
visibility=visibility,
|
114
|
+
)
|
115
|
+
|
116
|
+
class ClassOrInstanceMethod:
|
117
|
+
"""Descriptor that allows a method to be called as both a class method and an instance method."""
|
118
|
+
|
119
|
+
def __init__(self, func):
|
120
|
+
self.func = func
|
121
|
+
|
122
|
+
def __get__(self, obj, objtype=None):
|
123
|
+
if obj is None:
|
124
|
+
# Called as a class method
|
125
|
+
def wrapper(*args, **kwargs):
|
126
|
+
return self.func(objtype, *args, **kwargs)
|
127
|
+
|
128
|
+
return wrapper
|
129
|
+
else:
|
130
|
+
# Called as an instance method
|
131
|
+
def wrapper(*args, **kwargs):
|
132
|
+
return self.func(obj, *args, **kwargs)
|
133
|
+
|
134
|
+
return wrapper
|
135
|
+
|
136
|
+
@ClassOrInstanceMethod
|
137
|
+
def patch(
|
138
|
+
self_or_cls,
|
139
|
+
url_or_uuid: Union[str, UUID],
|
140
|
+
description: Optional[str] = None,
|
141
|
+
value: Optional[Any] = None,
|
142
|
+
visibility: Optional[str] = None,
|
143
|
+
):
|
144
|
+
"""
|
145
|
+
Patch an uploaded object's attributes.
|
146
|
+
|
147
|
+
When called as a class method:
|
148
|
+
- Requires explicit `value` parameter
|
149
|
+
|
150
|
+
When called as an instance method:
|
151
|
+
- Uses the instance itself as the `value` parameter
|
152
|
+
|
153
|
+
Parameters:
|
154
|
+
- `id_or_url`: ID or URL of the object to patch
|
155
|
+
- `description`: changes the description of the object on Coop
|
156
|
+
- `value`: changes the value of the object on Coop (required for class method)
|
157
|
+
- `visibility`: changes the visibility of the object on Coop
|
158
|
+
"""
|
159
|
+
|
160
|
+
# Check if this is being called as a class method
|
161
|
+
if isinstance(self_or_cls, type):
|
162
|
+
# This is a class method call
|
163
|
+
cls = self_or_cls
|
164
|
+
return cls.patch_cls(
|
165
|
+
url_or_uuid=url_or_uuid,
|
166
|
+
description=description,
|
167
|
+
value=value,
|
168
|
+
visibility=visibility,
|
169
|
+
)
|
170
|
+
else:
|
171
|
+
# This is an instance method call
|
172
|
+
instance = self_or_cls
|
173
|
+
cls_type = instance.__class__
|
174
|
+
|
175
|
+
# Use the instance as the value if not explicitly provided
|
176
|
+
if value is None:
|
177
|
+
value = instance
|
178
|
+
else:
|
179
|
+
pass
|
180
|
+
|
181
|
+
return cls_type.patch_cls(
|
182
|
+
url_or_uuid=url_or_uuid,
|
183
|
+
description=description,
|
184
|
+
value=value,
|
185
|
+
visibility=visibility,
|
186
|
+
)
|
120
187
|
|
121
188
|
@classmethod
|
122
189
|
def search(cls, query):
|
edsl/__version__.py
CHANGED
@@ -1 +1 @@
|
|
1
|
-
__version__ = "0.1.
|
1
|
+
__version__ = "0.1.47"
|
edsl/coop/coop.py
CHANGED
@@ -287,19 +287,25 @@ class Coop(CoopFunctionsMixin):
|
|
287
287
|
if value is None:
|
288
288
|
return "null"
|
289
289
|
|
290
|
+
@staticmethod
|
291
|
+
def _is_url(url_or_uuid: Union[str, UUID]) -> bool:
|
292
|
+
return "http://" in str(url_or_uuid) or "https://" in str(url_or_uuid)
|
293
|
+
|
290
294
|
def _resolve_uuid_or_alias(
|
291
|
-
self,
|
295
|
+
self, url_or_uuid: Union[str, UUID]
|
292
296
|
) -> tuple[Optional[str], Optional[str], Optional[str]]:
|
293
297
|
"""
|
294
298
|
Resolve the uuid or alias information from a uuid or a url.
|
295
299
|
Returns a tuple of (uuid, owner_username, alias)
|
296
|
-
- For content
|
297
|
-
- For content
|
300
|
+
- For content/uuid URLs: returns (uuid, None, None)
|
301
|
+
- For content/username/alias URLs: returns (None, username, alias)
|
298
302
|
"""
|
299
|
-
if not
|
303
|
+
if not url_or_uuid:
|
300
304
|
raise CoopNoUUIDError("No uuid or url provided for the object.")
|
301
305
|
|
302
|
-
if
|
306
|
+
if self._is_url(url_or_uuid):
|
307
|
+
url = str(url_or_uuid)
|
308
|
+
|
303
309
|
parts = (
|
304
310
|
url.replace("http://", "")
|
305
311
|
.replace("https://", "")
|
@@ -326,7 +332,8 @@ class Coop(CoopFunctionsMixin):
|
|
326
332
|
f"Invalid URL format. The URL must end with /content/<uuid> or /content/<username>/<alias>: {url}"
|
327
333
|
)
|
328
334
|
|
329
|
-
|
335
|
+
uuid = str(url_or_uuid)
|
336
|
+
return uuid, None, None
|
330
337
|
|
331
338
|
@property
|
332
339
|
def edsl_settings(self) -> dict:
|
@@ -348,6 +355,15 @@ class Coop(CoopFunctionsMixin):
|
|
348
355
|
################
|
349
356
|
# Objects
|
350
357
|
################
|
358
|
+
def _get_alias_url(self, owner_username: str, alias: str) -> Union[str, None]:
|
359
|
+
"""
|
360
|
+
Get the URL of an object by its owner username and alias.
|
361
|
+
"""
|
362
|
+
if owner_username and alias:
|
363
|
+
return f"{self.url}/content/{owner_username}/{alias}"
|
364
|
+
else:
|
365
|
+
return None
|
366
|
+
|
351
367
|
def create(
|
352
368
|
self,
|
353
369
|
object: EDSLObject,
|
@@ -368,7 +384,9 @@ class Coop(CoopFunctionsMixin):
|
|
368
384
|
"json_string": json.dumps(
|
369
385
|
object.to_dict(),
|
370
386
|
default=self._json_handle_none,
|
371
|
-
)
|
387
|
+
)
|
388
|
+
if object_type != "scenario"
|
389
|
+
else "",
|
372
390
|
"object_type": object_type,
|
373
391
|
"visibility": visibility,
|
374
392
|
"version": self._edsl_version,
|
@@ -376,19 +394,38 @@ class Coop(CoopFunctionsMixin):
|
|
376
394
|
)
|
377
395
|
self._resolve_server_response(response)
|
378
396
|
response_json = response.json()
|
397
|
+
|
398
|
+
if object_type == "scenario":
|
399
|
+
json_data = json.dumps(
|
400
|
+
object.to_dict(),
|
401
|
+
default=self._json_handle_none,
|
402
|
+
)
|
403
|
+
headers = {"Content-Type": "application/json"}
|
404
|
+
if response_json.get("upload_signed_url"):
|
405
|
+
signed_url = response_json.get("upload_signed_url")
|
406
|
+
else:
|
407
|
+
raise Exception("No signed url provided received")
|
408
|
+
|
409
|
+
response = requests.put(
|
410
|
+
signed_url, data=json_data.encode(), headers=headers
|
411
|
+
)
|
412
|
+
owner_username = response_json.get("owner_username")
|
413
|
+
object_alias = response_json.get("alias")
|
414
|
+
|
379
415
|
return {
|
380
416
|
"description": response_json.get("description"),
|
381
417
|
"object_type": object_type,
|
382
418
|
"url": f"{self.url}/content/{response_json.get('uuid')}",
|
419
|
+
"alias_url": self._get_alias_url(owner_username, object_alias),
|
383
420
|
"uuid": response_json.get("uuid"),
|
384
421
|
"version": self._edsl_version,
|
385
422
|
"visibility": response_json.get("visibility"),
|
423
|
+
"upload_signed_url": response_json.get("upload_signed_url", None),
|
386
424
|
}
|
387
425
|
|
388
426
|
def get(
|
389
427
|
self,
|
390
|
-
|
391
|
-
url: str = None,
|
428
|
+
url_or_uuid: Union[str, UUID],
|
392
429
|
expected_object_type: Optional[ObjectType] = None,
|
393
430
|
) -> EDSLObject:
|
394
431
|
"""
|
@@ -396,13 +433,13 @@ class Coop(CoopFunctionsMixin):
|
|
396
433
|
- If the object's visibility is private, the user must be the owner.
|
397
434
|
- Optionally, check if the retrieved object is of a certain type.
|
398
435
|
|
399
|
-
:param
|
400
|
-
|
401
|
-
:param expected_object_type:
|
436
|
+
:param url_or_uuid: The UUID or URL of the object.
|
437
|
+
URLs can be in the form content/uuid or content/username/alias.
|
438
|
+
:param expected_object_type: The expected type of the object.
|
402
439
|
|
403
440
|
:return: the object instance.
|
404
441
|
"""
|
405
|
-
obj_uuid, owner_username, alias = self._resolve_uuid_or_alias(
|
442
|
+
obj_uuid, owner_username, alias = self._resolve_uuid_or_alias(url_or_uuid)
|
406
443
|
|
407
444
|
if obj_uuid:
|
408
445
|
response = self._send_server_request(
|
@@ -419,6 +456,10 @@ class Coop(CoopFunctionsMixin):
|
|
419
456
|
|
420
457
|
self._resolve_server_response(response)
|
421
458
|
json_string = response.json().get("json_string")
|
459
|
+
if "load_from:" in json_string[0:12]:
|
460
|
+
load_link = json_string.split("load_from:")[1]
|
461
|
+
object_data = requests.get(load_link)
|
462
|
+
json_string = object_data.text
|
422
463
|
object_type = response.json().get("object_type")
|
423
464
|
if expected_object_type and object_type != expected_object_type:
|
424
465
|
raise Exception(f"Expected {expected_object_type=} but got {object_type=}")
|
@@ -437,28 +478,51 @@ class Coop(CoopFunctionsMixin):
|
|
437
478
|
params={"type": object_type},
|
438
479
|
)
|
439
480
|
self._resolve_server_response(response)
|
440
|
-
objects = [
|
441
|
-
|
442
|
-
|
481
|
+
objects = []
|
482
|
+
for o in response.json():
|
483
|
+
json_string = o.get("json_string")
|
484
|
+
## check if load from bucket needed.
|
485
|
+
if "load_from:" in json_string[0:12]:
|
486
|
+
load_link = json_string.split("load_from:")[1]
|
487
|
+
object_data = requests.get(load_link)
|
488
|
+
json_string = object_data.text
|
489
|
+
|
490
|
+
json_string = json.loads(json_string)
|
491
|
+
object = {
|
492
|
+
"object": edsl_class.from_dict(json_string),
|
443
493
|
"uuid": o.get("uuid"),
|
444
494
|
"version": o.get("version"),
|
445
495
|
"description": o.get("description"),
|
446
496
|
"visibility": o.get("visibility"),
|
447
497
|
"url": f"{self.url}/content/{o.get('uuid')}",
|
498
|
+
"alias_url": self._get_alias_url(
|
499
|
+
o.get("owner_username"), o.get("alias")
|
500
|
+
),
|
448
501
|
}
|
449
|
-
|
450
|
-
|
502
|
+
objects.append(object)
|
503
|
+
|
451
504
|
return objects
|
452
505
|
|
453
|
-
def delete(self,
|
506
|
+
def delete(self, url_or_uuid: Union[str, UUID]) -> dict:
|
454
507
|
"""
|
455
508
|
Delete an object from the server.
|
509
|
+
|
510
|
+
:param url_or_uuid: The UUID or URL of the object.
|
511
|
+
URLs can be in the form content/uuid or content/username/alias.
|
456
512
|
"""
|
457
|
-
obj_uuid,
|
513
|
+
obj_uuid, owner_username, alias = self._resolve_uuid_or_alias(url_or_uuid)
|
514
|
+
|
515
|
+
if obj_uuid:
|
516
|
+
uri = "api/v0/object"
|
517
|
+
params = {"uuid": obj_uuid}
|
518
|
+
else:
|
519
|
+
uri = "api/v0/object/alias"
|
520
|
+
params = {"owner_username": owner_username, "alias": alias}
|
521
|
+
|
458
522
|
response = self._send_server_request(
|
459
|
-
uri=
|
523
|
+
uri=uri,
|
460
524
|
method="DELETE",
|
461
|
-
params=
|
525
|
+
params=params,
|
462
526
|
)
|
463
527
|
|
464
528
|
self._resolve_server_response(response)
|
@@ -466,8 +530,7 @@ class Coop(CoopFunctionsMixin):
|
|
466
530
|
|
467
531
|
def patch(
|
468
532
|
self,
|
469
|
-
|
470
|
-
url: str = None,
|
533
|
+
url_or_uuid: Union[str, UUID],
|
471
534
|
description: Optional[str] = None,
|
472
535
|
alias: Optional[str] = None,
|
473
536
|
value: Optional[EDSLObject] = None,
|
@@ -475,15 +538,35 @@ class Coop(CoopFunctionsMixin):
|
|
475
538
|
) -> dict:
|
476
539
|
"""
|
477
540
|
Change the attributes of an uploaded object
|
478
|
-
|
479
|
-
|
480
|
-
|
541
|
+
|
542
|
+
:param url_or_uuid: The UUID or URL of the object.
|
543
|
+
URLs can be in the form content/uuid or content/username/alias.
|
544
|
+
:param description: Optional new description
|
545
|
+
:param alias: Optional new alias
|
546
|
+
:param value: Optional new object value
|
547
|
+
:param visibility: Optional new visibility setting
|
548
|
+
"""
|
549
|
+
if (
|
550
|
+
description is None
|
551
|
+
and visibility is None
|
552
|
+
and value is None
|
553
|
+
and alias is None
|
554
|
+
):
|
481
555
|
raise Exception("Nothing to patch.")
|
482
|
-
|
556
|
+
|
557
|
+
obj_uuid, owner_username, obj_alias = self._resolve_uuid_or_alias(url_or_uuid)
|
558
|
+
|
559
|
+
if obj_uuid:
|
560
|
+
uri = "api/v0/object"
|
561
|
+
params = {"uuid": obj_uuid}
|
562
|
+
else:
|
563
|
+
uri = "api/v0/object/alias"
|
564
|
+
params = {"owner_username": owner_username, "alias": obj_alias}
|
565
|
+
|
483
566
|
response = self._send_server_request(
|
484
|
-
uri=
|
567
|
+
uri=uri,
|
485
568
|
method="PATCH",
|
486
|
-
params=
|
569
|
+
params=params,
|
487
570
|
payload={
|
488
571
|
"description": description,
|
489
572
|
"alias": alias,
|
@@ -1187,27 +1270,25 @@ def main():
|
|
1187
1270
|
##############
|
1188
1271
|
# .. create and manipulate an object through the Coop client
|
1189
1272
|
response = coop.create(QuestionMultipleChoice.example())
|
1190
|
-
coop.get(
|
1191
|
-
coop.get(
|
1192
|
-
coop.get(
|
1273
|
+
coop.get(response.get("uuid"))
|
1274
|
+
coop.get(response.get("uuid"), expected_object_type="question")
|
1275
|
+
coop.get(response.get("url"))
|
1193
1276
|
coop.create(QuestionMultipleChoice.example())
|
1194
1277
|
coop.get_all("question")
|
1195
|
-
coop.patch(
|
1196
|
-
coop.patch(
|
1197
|
-
coop.patch(
|
1198
|
-
# coop.patch(
|
1199
|
-
coop.get(
|
1200
|
-
coop.delete(
|
1278
|
+
coop.patch(response.get("uuid"), visibility="private")
|
1279
|
+
coop.patch(response.get("uuid"), description="hey")
|
1280
|
+
coop.patch(response.get("uuid"), value=QuestionFreeText.example())
|
1281
|
+
# coop.patch(response.get("uuid"), value=Survey.example()) - should throw error
|
1282
|
+
coop.get(response.get("uuid"))
|
1283
|
+
coop.delete(response.get("uuid"))
|
1201
1284
|
|
1202
1285
|
# .. create and manipulate an object through the class
|
1203
1286
|
response = QuestionMultipleChoice.example().push()
|
1204
|
-
QuestionMultipleChoice.pull(
|
1205
|
-
QuestionMultipleChoice.pull(
|
1206
|
-
QuestionMultipleChoice.patch(
|
1207
|
-
QuestionMultipleChoice.patch(
|
1208
|
-
QuestionMultipleChoice.patch(
|
1209
|
-
uuid=response.get("uuid"), value=QuestionFreeText.example()
|
1210
|
-
)
|
1287
|
+
QuestionMultipleChoice.pull(response.get("uuid"))
|
1288
|
+
QuestionMultipleChoice.pull(response.get("url"))
|
1289
|
+
QuestionMultipleChoice.patch(response.get("uuid"), visibility="private")
|
1290
|
+
QuestionMultipleChoice.patch(response.get("uuid"), description="hey")
|
1291
|
+
QuestionMultipleChoice.patch(response.get("uuid"), value=QuestionFreeText.example())
|
1211
1292
|
QuestionMultipleChoice.pull(response.get("uuid"))
|
1212
1293
|
QuestionMultipleChoice.delete(response.get("uuid"))
|
1213
1294
|
|
@@ -1230,7 +1311,7 @@ def main():
|
|
1230
1311
|
# 1. Delete existing objects
|
1231
1312
|
existing_objects = coop.get_all(object_type)
|
1232
1313
|
for item in existing_objects:
|
1233
|
-
coop.delete(
|
1314
|
+
coop.delete(item.get("uuid"))
|
1234
1315
|
# 2. Create new objects
|
1235
1316
|
example = cls.example()
|
1236
1317
|
response_1 = coop.create(example)
|
@@ -1244,21 +1325,21 @@ def main():
|
|
1244
1325
|
assert len(objects) == 4
|
1245
1326
|
# 4. Try to retrieve an item that does not exist
|
1246
1327
|
try:
|
1247
|
-
coop.get(
|
1328
|
+
coop.get(uuid4())
|
1248
1329
|
except Exception as e:
|
1249
1330
|
print(e)
|
1250
1331
|
# 5. Try to retrieve all test objects by their uuids
|
1251
1332
|
for response in [response_1, response_2, response_3, response_4]:
|
1252
|
-
coop.get(
|
1333
|
+
coop.get(response.get("uuid"))
|
1253
1334
|
# 6. Change visibility of all objects
|
1254
1335
|
for item in objects:
|
1255
|
-
coop.patch(
|
1336
|
+
coop.patch(item.get("uuid"), visibility="private")
|
1256
1337
|
# 6. Change description of all objects
|
1257
1338
|
for item in objects:
|
1258
|
-
coop.patch(
|
1339
|
+
coop.patch(item.get("uuid"), description="hey")
|
1259
1340
|
# 7. Delete all objects
|
1260
1341
|
for item in objects:
|
1261
|
-
coop.delete(
|
1342
|
+
coop.delete(item.get("uuid"))
|
1262
1343
|
assert len(coop.get_all(object_type)) == 0
|
1263
1344
|
|
1264
1345
|
##############
|
@@ -1291,4 +1372,4 @@ def main():
|
|
1291
1372
|
coop.remote_inference_cost(job)
|
1292
1373
|
job_coop_object = coop.remote_inference_create(job)
|
1293
1374
|
job_coop_results = coop.remote_inference_get(job_coop_object.get("uuid"))
|
1294
|
-
coop.get(
|
1375
|
+
coop.get(job_coop_results.get("results_uuid"))
|
edsl/data/Cache.py
CHANGED
@@ -173,6 +173,7 @@ class Cache(Base):
|
|
173
173
|
user_prompt: str,
|
174
174
|
response: dict,
|
175
175
|
iteration: int,
|
176
|
+
service: str,
|
176
177
|
) -> str:
|
177
178
|
"""
|
178
179
|
Add a new key-value pair to the cache.
|
@@ -204,6 +205,7 @@ class Cache(Base):
|
|
204
205
|
user_prompt=user_prompt,
|
205
206
|
output=json.dumps(response),
|
206
207
|
iteration=iteration,
|
208
|
+
service=service,
|
207
209
|
)
|
208
210
|
key = entry.key
|
209
211
|
self.new_entries[key] = entry
|
edsl/data/CacheEntry.py
CHANGED
@@ -16,7 +16,7 @@ class CacheEntry(RepresentationMixin):
|
|
16
16
|
"""
|
17
17
|
|
18
18
|
key_fields = ["model", "parameters", "system_prompt", "user_prompt", "iteration"]
|
19
|
-
all_fields = key_fields + ["timestamp", "output"]
|
19
|
+
all_fields = key_fields + ["timestamp", "output", "service"]
|
20
20
|
|
21
21
|
def __init__(
|
22
22
|
self,
|
@@ -28,6 +28,7 @@ class CacheEntry(RepresentationMixin):
|
|
28
28
|
iteration: Optional[int] = None,
|
29
29
|
output: str,
|
30
30
|
timestamp: Optional[int] = None,
|
31
|
+
service: Optional[str] = None,
|
31
32
|
):
|
32
33
|
self.model = model
|
33
34
|
self.parameters = parameters
|
@@ -38,6 +39,7 @@ class CacheEntry(RepresentationMixin):
|
|
38
39
|
self.timestamp = timestamp or int(
|
39
40
|
datetime.datetime.now(datetime.timezone.utc).timestamp()
|
40
41
|
)
|
42
|
+
self.service = service
|
41
43
|
self._check_types()
|
42
44
|
|
43
45
|
def _check_types(self):
|
@@ -59,6 +61,8 @@ class CacheEntry(RepresentationMixin):
|
|
59
61
|
# TODO: should probably be float
|
60
62
|
if not isinstance(self.timestamp, int):
|
61
63
|
raise TypeError(f"`timestamp` should be an integer")
|
64
|
+
if self.service is not None and not isinstance(self.service, str):
|
65
|
+
raise TypeError("`service` should be either a string or None")
|
62
66
|
|
63
67
|
@classmethod
|
64
68
|
def gen_key(
|
@@ -94,6 +98,7 @@ class CacheEntry(RepresentationMixin):
|
|
94
98
|
"output": self.output,
|
95
99
|
"iteration": self.iteration,
|
96
100
|
"timestamp": self.timestamp,
|
101
|
+
"service": self.service,
|
97
102
|
}
|
98
103
|
# if add_edsl_version:
|
99
104
|
# from edsl import __version__
|
@@ -144,7 +149,8 @@ class CacheEntry(RepresentationMixin):
|
|
144
149
|
f"user_prompt={repr(self.user_prompt)}, "
|
145
150
|
f"output={repr(self.output)}, "
|
146
151
|
f"iteration={self.iteration}, "
|
147
|
-
f"timestamp={self.timestamp}
|
152
|
+
f"timestamp={self.timestamp}, "
|
153
|
+
f"service={repr(self.service)})"
|
148
154
|
)
|
149
155
|
|
150
156
|
@classmethod
|
@@ -164,6 +170,7 @@ class CacheEntry(RepresentationMixin):
|
|
164
170
|
output="The fox says 'hello'",
|
165
171
|
iteration=1,
|
166
172
|
timestamp=int(datetime.datetime.now(datetime.timezone.utc).timestamp()),
|
173
|
+
service="openai",
|
167
174
|
)
|
168
175
|
|
169
176
|
@classmethod
|
@@ -184,6 +191,7 @@ class CacheEntry(RepresentationMixin):
|
|
184
191
|
input = cls.example().to_dict()
|
185
192
|
_ = input.pop("timestamp")
|
186
193
|
_ = input.pop("output")
|
194
|
+
_ = input.pop("service")
|
187
195
|
return input
|
188
196
|
|
189
197
|
@classmethod
|
@@ -29,9 +29,12 @@ class PerplexityService(OpenAIService):
|
|
29
29
|
@classmethod
|
30
30
|
def available(cls) -> List[str]:
|
31
31
|
return [
|
32
|
-
"
|
33
|
-
"
|
34
|
-
"
|
32
|
+
"sonar-deep-research",
|
33
|
+
"sonar-reasoning-pro",
|
34
|
+
"sonar-reasoning",
|
35
|
+
"sonar-pro",
|
36
|
+
"sonar",
|
37
|
+
"r1-1776",
|
35
38
|
]
|
36
39
|
|
37
40
|
@classmethod
|
@@ -65,10 +68,10 @@ class PerplexityService(OpenAIService):
|
|
65
68
|
}
|
66
69
|
|
67
70
|
def sync_client(self):
|
68
|
-
return cls.sync_client()
|
71
|
+
return cls.sync_client(api_key=self.api_token)
|
69
72
|
|
70
73
|
def async_client(self):
|
71
|
-
return cls.async_client()
|
74
|
+
return cls.async_client(api_key=self.api_token)
|
72
75
|
|
73
76
|
@classmethod
|
74
77
|
def available(cls) -> list[str]:
|
@@ -149,6 +152,7 @@ class PerplexityService(OpenAIService):
|
|
149
152
|
# "logprobs": self.logprobs,
|
150
153
|
# "top_logprobs": self.top_logprobs if self.logprobs else None,
|
151
154
|
}
|
155
|
+
print("calling the model", flush=True)
|
152
156
|
try:
|
153
157
|
response = await client.chat.completions.create(**params)
|
154
158
|
except Exception as e:
|
edsl/jobs/Jobs.py
CHANGED
@@ -119,6 +119,19 @@ class Jobs(Base):
|
|
119
119
|
:param agents: a list of agents
|
120
120
|
:param models: a list of models
|
121
121
|
:param scenarios: a list of scenarios
|
122
|
+
|
123
|
+
|
124
|
+
>>> from edsl.surveys.Survey import Survey
|
125
|
+
>>> from edsl.questions.QuestionFreeText import QuestionFreeText
|
126
|
+
>>> q = QuestionFreeText(question_name="name", question_text="What is your name?")
|
127
|
+
>>> s = Survey(questions=[q])
|
128
|
+
>>> j = Jobs(survey = s)
|
129
|
+
>>> q = QuestionFreeText(question_name="{{ bad_name }}", question_text="What is your name?")
|
130
|
+
>>> s = Survey(questions=[q])
|
131
|
+
>>> j = Jobs(survey = s)
|
132
|
+
Traceback (most recent call last):
|
133
|
+
...
|
134
|
+
ValueError: At least some question names are not valid: ['{{ bad_name }}']
|
122
135
|
"""
|
123
136
|
self.run_config = RunConfig(
|
124
137
|
environment=RunEnvironment(), parameters=RunParameters()
|
@@ -129,6 +142,13 @@ class Jobs(Base):
|
|
129
142
|
self.scenarios: ScenarioList = scenarios
|
130
143
|
self.models: ModelList = models
|
131
144
|
|
145
|
+
try:
|
146
|
+
assert self.survey.question_names_valid()
|
147
|
+
except Exception as e:
|
148
|
+
invalid_question_names = [q.question_name for q in self.survey.questions if not q.is_valid_question_name()]
|
149
|
+
raise ValueError(f"At least some question names are not valid: {invalid_question_names}")
|
150
|
+
|
151
|
+
|
132
152
|
def add_running_env(self, running_env: RunEnvironment):
|
133
153
|
self.run_config.add_environment(running_env)
|
134
154
|
return self
|
@@ -153,7 +153,8 @@ class JobsComponentConstructor:
|
|
153
153
|
For example, if the user passes in 3 agents,
|
154
154
|
and there are 2 existing agents, this will create 6 new agents
|
155
155
|
>>> from edsl.jobs import Jobs
|
156
|
-
>>>
|
156
|
+
>>> from edsl.surveys.Survey import Survey
|
157
|
+
>>> JobsComponentConstructor(Jobs(survey = Survey.example()))._merge_objects([1,2,3], [4,5,6])
|
157
158
|
[5, 6, 7, 6, 7, 8, 7, 8, 9]
|
158
159
|
"""
|
159
160
|
new_objects = JobsComponentConstructor._get_empty_container_object(
|