edsl 0.1.27.dev2__py3-none-any.whl โ 0.1.29__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 +107 -30
- edsl/BaseDiff.py +260 -0
- edsl/__init__.py +25 -21
- edsl/__version__.py +1 -1
- edsl/agents/Agent.py +103 -46
- edsl/agents/AgentList.py +97 -13
- edsl/agents/Invigilator.py +23 -10
- edsl/agents/InvigilatorBase.py +19 -14
- edsl/agents/PromptConstructionMixin.py +342 -100
- edsl/agents/descriptors.py +5 -2
- edsl/base/Base.py +289 -0
- edsl/config.py +2 -1
- edsl/conjure/AgentConstructionMixin.py +152 -0
- edsl/conjure/Conjure.py +56 -0
- edsl/conjure/InputData.py +659 -0
- edsl/conjure/InputDataCSV.py +48 -0
- edsl/conjure/InputDataMixinQuestionStats.py +182 -0
- edsl/conjure/InputDataPyRead.py +91 -0
- edsl/conjure/InputDataSPSS.py +8 -0
- edsl/conjure/InputDataStata.py +8 -0
- edsl/conjure/QuestionOptionMixin.py +76 -0
- edsl/conjure/QuestionTypeMixin.py +23 -0
- edsl/conjure/RawQuestion.py +65 -0
- edsl/conjure/SurveyResponses.py +7 -0
- edsl/conjure/__init__.py +9 -4
- edsl/conjure/examples/placeholder.txt +0 -0
- edsl/conjure/naming_utilities.py +263 -0
- edsl/conjure/utilities.py +165 -28
- edsl/conversation/Conversation.py +238 -0
- edsl/conversation/car_buying.py +58 -0
- edsl/conversation/mug_negotiation.py +81 -0
- edsl/conversation/next_speaker_utilities.py +93 -0
- edsl/coop/coop.py +337 -121
- edsl/coop/utils.py +56 -70
- edsl/data/Cache.py +74 -22
- edsl/data/CacheHandler.py +10 -9
- edsl/data/SQLiteDict.py +11 -3
- edsl/inference_services/AnthropicService.py +1 -0
- edsl/inference_services/DeepInfraService.py +20 -13
- edsl/inference_services/GoogleService.py +7 -1
- edsl/inference_services/InferenceServicesCollection.py +33 -7
- edsl/inference_services/OpenAIService.py +17 -10
- edsl/inference_services/models_available_cache.py +69 -0
- edsl/inference_services/rate_limits_cache.py +25 -0
- edsl/inference_services/write_available.py +10 -0
- edsl/jobs/Answers.py +15 -1
- edsl/jobs/Jobs.py +322 -73
- edsl/jobs/buckets/BucketCollection.py +9 -3
- edsl/jobs/buckets/ModelBuckets.py +4 -2
- edsl/jobs/buckets/TokenBucket.py +1 -2
- edsl/jobs/interviews/Interview.py +7 -10
- edsl/jobs/interviews/InterviewStatusMixin.py +3 -3
- edsl/jobs/interviews/InterviewTaskBuildingMixin.py +39 -20
- edsl/jobs/interviews/retry_management.py +4 -4
- edsl/jobs/runners/JobsRunnerAsyncio.py +103 -65
- edsl/jobs/runners/JobsRunnerStatusData.py +3 -3
- edsl/jobs/tasks/QuestionTaskCreator.py +4 -2
- edsl/jobs/tasks/TaskHistory.py +4 -3
- edsl/language_models/LanguageModel.py +42 -55
- edsl/language_models/ModelList.py +96 -0
- edsl/language_models/registry.py +14 -0
- edsl/language_models/repair.py +97 -25
- edsl/notebooks/Notebook.py +157 -32
- edsl/prompts/Prompt.py +31 -19
- edsl/questions/QuestionBase.py +145 -23
- edsl/questions/QuestionBudget.py +5 -6
- edsl/questions/QuestionCheckBox.py +7 -3
- edsl/questions/QuestionExtract.py +5 -3
- edsl/questions/QuestionFreeText.py +3 -3
- edsl/questions/QuestionFunctional.py +0 -3
- edsl/questions/QuestionList.py +3 -4
- edsl/questions/QuestionMultipleChoice.py +16 -8
- edsl/questions/QuestionNumerical.py +4 -3
- edsl/questions/QuestionRank.py +5 -3
- edsl/questions/__init__.py +4 -3
- edsl/questions/descriptors.py +9 -4
- edsl/questions/question_registry.py +27 -31
- edsl/questions/settings.py +1 -1
- edsl/results/Dataset.py +31 -0
- edsl/results/DatasetExportMixin.py +493 -0
- edsl/results/Result.py +42 -82
- edsl/results/Results.py +178 -66
- edsl/results/ResultsDBMixin.py +10 -9
- edsl/results/ResultsExportMixin.py +23 -507
- edsl/results/ResultsGGMixin.py +3 -3
- edsl/results/ResultsToolsMixin.py +9 -9
- edsl/scenarios/FileStore.py +140 -0
- edsl/scenarios/Scenario.py +59 -6
- edsl/scenarios/ScenarioList.py +138 -52
- edsl/scenarios/ScenarioListExportMixin.py +32 -0
- edsl/scenarios/ScenarioListPdfMixin.py +2 -1
- edsl/scenarios/__init__.py +1 -0
- edsl/study/ObjectEntry.py +173 -0
- edsl/study/ProofOfWork.py +113 -0
- edsl/study/SnapShot.py +73 -0
- edsl/study/Study.py +498 -0
- edsl/study/__init__.py +4 -0
- edsl/surveys/MemoryPlan.py +11 -4
- edsl/surveys/Survey.py +124 -37
- edsl/surveys/SurveyExportMixin.py +25 -5
- edsl/surveys/SurveyFlowVisualizationMixin.py +6 -4
- edsl/tools/plotting.py +4 -2
- edsl/utilities/__init__.py +21 -20
- edsl/utilities/gcp_bucket/__init__.py +0 -0
- edsl/utilities/gcp_bucket/cloud_storage.py +96 -0
- edsl/utilities/gcp_bucket/simple_example.py +9 -0
- edsl/utilities/interface.py +90 -73
- edsl/utilities/repair_functions.py +28 -0
- edsl/utilities/utilities.py +59 -6
- {edsl-0.1.27.dev2.dist-info โ edsl-0.1.29.dist-info}/METADATA +42 -15
- edsl-0.1.29.dist-info/RECORD +203 -0
- edsl/conjure/RawResponseColumn.py +0 -327
- edsl/conjure/SurveyBuilder.py +0 -308
- edsl/conjure/SurveyBuilderCSV.py +0 -78
- edsl/conjure/SurveyBuilderSPSS.py +0 -118
- edsl/data/RemoteDict.py +0 -103
- edsl-0.1.27.dev2.dist-info/RECORD +0 -172
- {edsl-0.1.27.dev2.dist-info โ edsl-0.1.29.dist-info}/LICENSE +0 -0
- {edsl-0.1.27.dev2.dist-info โ edsl-0.1.29.dist-info}/WHEEL +0 -0
edsl/utilities/interface.py
CHANGED
@@ -1,12 +1,45 @@
|
|
1
1
|
"""A module for displaying data in various formats."""
|
2
2
|
|
3
3
|
from html import escape
|
4
|
-
from IPython.display import HTML
|
5
|
-
from IPython.display import display as ipython_diplay
|
6
4
|
|
7
|
-
|
8
|
-
|
9
|
-
from
|
5
|
+
|
6
|
+
def create_image(console, image_filename):
|
7
|
+
"""Create an image from the console output."""
|
8
|
+
font_size = 15
|
9
|
+
from PIL import Image, ImageDraw, ImageFont
|
10
|
+
|
11
|
+
text = console.export_text() # Get the console output as text.
|
12
|
+
|
13
|
+
# Create an image from the text
|
14
|
+
font_size = 15
|
15
|
+
font = ImageFont.load_default() # Use the default font to avoid file path issues.
|
16
|
+
# text_width, text_height = ImageDraw.Draw(
|
17
|
+
# Image.new("RGB", (100, 100))
|
18
|
+
# ).multiline_textsize(text, font=font)
|
19
|
+
text_width, text_height = get_multiline_textsize(text, font)
|
20
|
+
image = Image.new(
|
21
|
+
"RGB", (text_width + 20, text_height + 20), color=(255, 255, 255)
|
22
|
+
) # Add some padding
|
23
|
+
d = ImageDraw.Draw(image)
|
24
|
+
|
25
|
+
# Draw text to image
|
26
|
+
d.multiline_text((10, 10), text, font=font, fill=(0, 0, 0))
|
27
|
+
# Save the image
|
28
|
+
image.save(image_filename)
|
29
|
+
|
30
|
+
|
31
|
+
def display_table(console, table, filename):
|
32
|
+
# from rich.console import Console
|
33
|
+
# from rich.table import Table
|
34
|
+
"""Display the table using the rich library and save it to a file if a filename is provided."""
|
35
|
+
if filename is not None:
|
36
|
+
with open(filename, "w") as f:
|
37
|
+
with console.capture() as capture:
|
38
|
+
console.print(table)
|
39
|
+
f.write(capture.get())
|
40
|
+
create_image(console, filename + ".png")
|
41
|
+
else:
|
42
|
+
console.print(table)
|
10
43
|
|
11
44
|
|
12
45
|
def gen_html_sandwich(html_inner, interactive=False):
|
@@ -133,43 +166,10 @@ def get_multiline_textsize(text, font):
|
|
133
166
|
return max_width, total_height
|
134
167
|
|
135
168
|
|
136
|
-
# def create_image(console, image_filename):
|
137
|
-
# """Create an image from the console output."""
|
138
|
-
# font_size = 15
|
139
|
-
|
140
|
-
# text = console.export_text() # Get the console output as text.
|
141
|
-
|
142
|
-
# # Create an image from the text
|
143
|
-
# font_size = 15
|
144
|
-
# font = ImageFont.load_default() # Use the default font to avoid file path issues.
|
145
|
-
# # text_width, text_height = ImageDraw.Draw(
|
146
|
-
# # Image.new("RGB", (100, 100))
|
147
|
-
# # ).multiline_textsize(text, font=font)
|
148
|
-
# text_width, text_height = get_multiline_textsize(text, font)
|
149
|
-
# image = Image.new(
|
150
|
-
# "RGB", (text_width + 20, text_height + 20), color=(255, 255, 255)
|
151
|
-
# ) # Add some padding
|
152
|
-
# d = ImageDraw.Draw(image)
|
153
|
-
|
154
|
-
# # Draw text to image
|
155
|
-
# d.multiline_text((10, 10), text, font=font, fill=(0, 0, 0))
|
156
|
-
# # Save the image
|
157
|
-
# image.save(image_filename)
|
158
|
-
|
159
|
-
|
160
|
-
def display(console, table, filename):
|
161
|
-
"""Display the table using the rich library and save it to a file if a filename is provided."""
|
162
|
-
if filename is not None:
|
163
|
-
with open(filename, "w") as f:
|
164
|
-
with console.capture() as capture:
|
165
|
-
console.print(table)
|
166
|
-
f.write(capture.get())
|
167
|
-
create_image(console, filename + ".png")
|
168
|
-
else:
|
169
|
-
console.print(table)
|
170
|
-
|
171
|
-
|
172
169
|
def print_results_long(results, max_rows=None):
|
170
|
+
from rich.console import Console
|
171
|
+
from rich.table import Table
|
172
|
+
|
173
173
|
console = Console(record=True)
|
174
174
|
table = Table(show_header=True, header_style="bold magenta")
|
175
175
|
table.add_column("Result index", style="dim")
|
@@ -199,6 +199,9 @@ def print_dict_with_rich(d, key_name="Key", value_name="Value", filename=None):
|
|
199
199
|
โ c โ 3 โ
|
200
200
|
โโโโโโโดโโโโโโโโ
|
201
201
|
"""
|
202
|
+
from rich.console import Console
|
203
|
+
from rich.table import Table
|
204
|
+
|
202
205
|
console = Console(record=True)
|
203
206
|
table = Table(show_header=True, header_style="bold magenta")
|
204
207
|
table.add_column(key_name, style="dim")
|
@@ -206,7 +209,7 @@ def print_dict_with_rich(d, key_name="Key", value_name="Value", filename=None):
|
|
206
209
|
for key, value in d.items():
|
207
210
|
table.add_row(key, str(value))
|
208
211
|
console.print(table)
|
209
|
-
#
|
212
|
+
# display_table(console, table, filename)
|
210
213
|
|
211
214
|
|
212
215
|
def print_dict_as_html_table(
|
@@ -251,6 +254,9 @@ def print_dict_as_html_table(
|
|
251
254
|
|
252
255
|
|
253
256
|
def print_scenario_list(data):
|
257
|
+
from rich.console import Console
|
258
|
+
from rich.table import Table
|
259
|
+
|
254
260
|
new_data = []
|
255
261
|
for obs in data:
|
256
262
|
try:
|
@@ -300,6 +306,9 @@ def print_dataset_with_rich(data, filename=None, split_at_dot=True):
|
|
300
306
|
โ 3 โ 6 โ
|
301
307
|
โโโโโดโโโโ
|
302
308
|
"""
|
309
|
+
from rich.console import Console
|
310
|
+
from rich.table import Table
|
311
|
+
|
303
312
|
console = Console(record=True)
|
304
313
|
|
305
314
|
# Create a table object
|
@@ -321,7 +330,7 @@ def print_dataset_with_rich(data, filename=None, split_at_dot=True):
|
|
321
330
|
table.add_row(*row)
|
322
331
|
|
323
332
|
console.print(table)
|
324
|
-
#
|
333
|
+
# display_table(console, table, filename)
|
325
334
|
|
326
335
|
|
327
336
|
def create_latex_table_from_data(data, filename=None, split_at_dot=True):
|
@@ -331,15 +340,15 @@ def create_latex_table_from_data(data, filename=None, split_at_dot=True):
|
|
331
340
|
|
332
341
|
>>> data = [{"a": [1, 2, 3], "b": [4, 5, 6]}]
|
333
342
|
>>> print(create_latex_table_from_data(data))
|
334
|
-
|
335
|
-
|
336
|
-
a & b
|
337
|
-
|
338
|
-
1 & 4
|
339
|
-
2 & 5
|
340
|
-
3 & 6
|
341
|
-
|
342
|
-
|
343
|
+
\\begin{tabular}{|c|c|}
|
344
|
+
\\hline
|
345
|
+
a & b \\\\
|
346
|
+
\\hline
|
347
|
+
1 & 4 \\\\
|
348
|
+
2 & 5 \\\\
|
349
|
+
3 & 6 \\\\
|
350
|
+
\\hline
|
351
|
+
\\end{tabular}
|
343
352
|
"""
|
344
353
|
|
345
354
|
def escape_latex(s):
|
@@ -379,7 +388,7 @@ def create_latex_table_from_data(data, filename=None, split_at_dot=True):
|
|
379
388
|
num_rows = len(next(iter(data[0].values())))
|
380
389
|
|
381
390
|
# Debugging: Print the keys of the dictionaries
|
382
|
-
print("Keys in data[0]:", list(data[0].keys()))
|
391
|
+
# print("Keys in data[0]:", list(data[0].keys()))
|
383
392
|
|
384
393
|
# Add the data rows
|
385
394
|
for i in range(num_rows):
|
@@ -410,9 +419,7 @@ def create_latex_table_from_data(data, filename=None, split_at_dot=True):
|
|
410
419
|
return latex_table_str
|
411
420
|
|
412
421
|
|
413
|
-
def print_list_of_dicts_as_html_table(
|
414
|
-
data, filename=None, interactive=True, notebook=False
|
415
|
-
):
|
422
|
+
def print_list_of_dicts_as_html_table(data, interactive=True):
|
416
423
|
"""Print a list of dictionaries as an HTML table.
|
417
424
|
|
418
425
|
:param data: The list of dictionaries to print.
|
@@ -459,20 +466,7 @@ def print_list_of_dicts_as_html_table(
|
|
459
466
|
# Close the table
|
460
467
|
html_table += "</tbody>\n"
|
461
468
|
html_table += "</table>"
|
462
|
-
|
463
|
-
html = gen_html_sandwich(html_table, interactive=interactive)
|
464
|
-
|
465
|
-
# Output or save to file
|
466
|
-
if filename:
|
467
|
-
with open(filename, "w") as f:
|
468
|
-
f.write(html)
|
469
|
-
else:
|
470
|
-
# view_html(html)
|
471
|
-
if notebook:
|
472
|
-
# ipython_diplay(HTML(html))
|
473
|
-
return html
|
474
|
-
else:
|
475
|
-
print(html)
|
469
|
+
return gen_html_sandwich(html_table, interactive=interactive)
|
476
470
|
|
477
471
|
|
478
472
|
def print_list_of_dicts_as_markdown_table(data, filename=None):
|
@@ -486,7 +480,11 @@ def print_list_of_dicts_as_markdown_table(data, filename=None):
|
|
486
480
|
return
|
487
481
|
|
488
482
|
# Gather all unique headers
|
489
|
-
headers = list({key for d in data for key in d.keys()})
|
483
|
+
# headers = list({key for d in data for key in d.keys()})
|
484
|
+
headers = []
|
485
|
+
for column in data:
|
486
|
+
headers.append(list(column.keys())[0])
|
487
|
+
|
490
488
|
markdown_table = "| " + " | ".join(headers) + " |\n"
|
491
489
|
markdown_table += "|-" + "-|-".join(["" for _ in headers]) + "-|\n"
|
492
490
|
|
@@ -506,6 +504,9 @@ def print_list_of_dicts_as_markdown_table(data, filename=None):
|
|
506
504
|
|
507
505
|
def print_public_methods_with_doc(obj):
|
508
506
|
"""Print the public methods of an object along with their docstrings."""
|
507
|
+
from rich.console import Console
|
508
|
+
from rich.table import Table
|
509
|
+
|
509
510
|
console = Console()
|
510
511
|
public_methods_with_docstrings = [
|
511
512
|
(method, getattr(obj, method).__doc__)
|
@@ -527,8 +528,19 @@ def print_tally_with_rich(data, filename=None):
|
|
527
528
|
Example:
|
528
529
|
>>> data = {'a':12, 'b':14, 'c':9}
|
529
530
|
>>> print_tally_with_rich(data)
|
531
|
+
โโโโโโโโโณโโโโโโโโ
|
532
|
+
โ Value โ Count โ
|
533
|
+
โกโโโโโโโโโโโโโโโโฉ
|
534
|
+
โ a โ 12 โ
|
535
|
+
โ b โ 14 โ
|
536
|
+
โ c โ 9 โ
|
537
|
+
โโโโโโโโโดโโโโโโโโ
|
530
538
|
"""
|
531
539
|
# Initialize a console object
|
540
|
+
from rich.console import Console
|
541
|
+
from rich.table import Table
|
542
|
+
from IPython.display import display
|
543
|
+
|
532
544
|
console = Console(record=True)
|
533
545
|
|
534
546
|
# Create a new table
|
@@ -542,7 +554,9 @@ def print_tally_with_rich(data, filename=None):
|
|
542
554
|
for key, value in data.items():
|
543
555
|
table.add_row(key, str(value))
|
544
556
|
|
545
|
-
display
|
557
|
+
from IPython.display import display
|
558
|
+
|
559
|
+
display_table(console, table, filename)
|
546
560
|
|
547
561
|
|
548
562
|
def print_table_with_rich(data, filename=None):
|
@@ -565,6 +579,9 @@ def print_table_with_rich(data, filename=None):
|
|
565
579
|
โ 2 โ 9 โ 8 โ
|
566
580
|
โโโโโดโโโโดโโโโ
|
567
581
|
"""
|
582
|
+
from rich.console import Console
|
583
|
+
from rich.table import Table
|
584
|
+
|
568
585
|
# Initialize a console object - expects a list of dictionaries
|
569
586
|
console = Console(record=True)
|
570
587
|
|
@@ -584,7 +601,7 @@ def print_table_with_rich(data, filename=None):
|
|
584
601
|
for row in data:
|
585
602
|
table.add_row(*[str(value) for value in row.values()])
|
586
603
|
|
587
|
-
|
604
|
+
display_table(console, table, filename)
|
588
605
|
|
589
606
|
|
590
607
|
if __name__ == "__main__":
|
@@ -0,0 +1,28 @@
|
|
1
|
+
import json
|
2
|
+
from edsl.utilities.utilities import valid_json
|
3
|
+
|
4
|
+
|
5
|
+
def extract_json_from_string(s):
|
6
|
+
"""Extract a JSON string from a string."""
|
7
|
+
# Find the first occurrence of '{'
|
8
|
+
start_idx = s.find("{")
|
9
|
+
# Find the last occurrence of '}'
|
10
|
+
end_idx = s.rfind("}")
|
11
|
+
# If both '{' and '}' are found in the string
|
12
|
+
if start_idx != -1 and end_idx != -1 and start_idx < end_idx:
|
13
|
+
# Extract the substring from start_idx to end_idx (inclusive)
|
14
|
+
json_str = s[start_idx : end_idx + 1]
|
15
|
+
try:
|
16
|
+
return json.loads(json_str)
|
17
|
+
except json.JSONDecodeError:
|
18
|
+
raise ValueError("Invalid JSON string")
|
19
|
+
else:
|
20
|
+
raise ValueError("No JSON object found in string")
|
21
|
+
|
22
|
+
|
23
|
+
if __name__ == "__main__":
|
24
|
+
text = (
|
25
|
+
'Sure - here is some JSON { "key": "value", "number": 123, "array": [1, 2, 3] }'
|
26
|
+
)
|
27
|
+
extracted_json = extract_json_from_string(text)
|
28
|
+
d = extracted_json
|
edsl/utilities/utilities.py
CHANGED
@@ -1,5 +1,9 @@
|
|
1
1
|
"""Utility functions for working with strings, dictionaries, and files."""
|
2
2
|
|
3
|
+
from functools import wraps
|
4
|
+
import types
|
5
|
+
import time
|
6
|
+
|
3
7
|
import hashlib
|
4
8
|
import json
|
5
9
|
import keyword
|
@@ -11,13 +15,50 @@ import tempfile
|
|
11
15
|
import gzip
|
12
16
|
import webbrowser
|
13
17
|
import json
|
18
|
+
|
14
19
|
from html import escape
|
15
20
|
from typing import Callable, Union
|
16
21
|
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
22
|
+
|
23
|
+
def time_it(func):
|
24
|
+
@wraps(func)
|
25
|
+
def wrapper(*args, **kwargs):
|
26
|
+
start_time = time.time()
|
27
|
+
result = func(*args, **kwargs)
|
28
|
+
end_time = time.time()
|
29
|
+
execution_time = end_time - start_time
|
30
|
+
class_name = args[0].__class__.__name__ if args else func.__module__
|
31
|
+
print(
|
32
|
+
f"Function {class_name}.{func.__name__} took {execution_time:.4f} seconds to execute"
|
33
|
+
)
|
34
|
+
return result
|
35
|
+
|
36
|
+
return wrapper
|
37
|
+
|
38
|
+
|
39
|
+
def time_all_functions(module_or_class):
|
40
|
+
for name, obj in vars(module_or_class).items():
|
41
|
+
if isinstance(obj, types.FunctionType):
|
42
|
+
setattr(module_or_class, name, time_it(obj))
|
43
|
+
|
44
|
+
|
45
|
+
def dict_hash(data: dict):
|
46
|
+
return hash(
|
47
|
+
int(hashlib.md5(json.dumps(data, sort_keys=True).encode()).hexdigest(), 16)
|
48
|
+
)
|
49
|
+
|
50
|
+
|
51
|
+
def extract_json_from_string(text):
|
52
|
+
pattern = re.compile(r"\{.*?\}")
|
53
|
+
match = pattern.search(text)
|
54
|
+
if match:
|
55
|
+
json_data = match.group(0)
|
56
|
+
try:
|
57
|
+
json_object = json.loads(json_data)
|
58
|
+
return json_object
|
59
|
+
except json.JSONDecodeError:
|
60
|
+
return None
|
61
|
+
return None
|
21
62
|
|
22
63
|
|
23
64
|
def clean_json(bad_json_str):
|
@@ -32,6 +73,7 @@ def clean_json(bad_json_str):
|
|
32
73
|
("\t", "\\t"),
|
33
74
|
("\b", "\\b"),
|
34
75
|
("\f", "\\f"),
|
76
|
+
("[/INST]", "removed_inst"),
|
35
77
|
]
|
36
78
|
|
37
79
|
s = bad_json_str
|
@@ -46,6 +88,11 @@ def data_to_html(data, replace_new_lines=False):
|
|
46
88
|
if "edsl_class_name" in data:
|
47
89
|
_ = data.pop("edsl_class_name")
|
48
90
|
|
91
|
+
from pygments import highlight
|
92
|
+
from pygments.lexers import JsonLexer
|
93
|
+
from pygments.formatters import HtmlFormatter
|
94
|
+
from IPython.display import HTML
|
95
|
+
|
49
96
|
json_str = json.dumps(data, indent=4)
|
50
97
|
formatted_json = highlight(
|
51
98
|
json_str,
|
@@ -54,6 +101,7 @@ def data_to_html(data, replace_new_lines=False):
|
|
54
101
|
)
|
55
102
|
if replace_new_lines:
|
56
103
|
formatted_json = formatted_json.replace("\\n", "<br>")
|
104
|
+
|
57
105
|
return HTML(formatted_json).data
|
58
106
|
|
59
107
|
|
@@ -233,9 +281,14 @@ def valid_json(json_string):
|
|
233
281
|
return False
|
234
282
|
|
235
283
|
|
236
|
-
def is_valid_variable_name(name):
|
284
|
+
def is_valid_variable_name(name, allow_name=True):
|
237
285
|
"""Check if a string is a valid variable name."""
|
238
|
-
|
286
|
+
if allow_name:
|
287
|
+
return name.isidentifier() and not keyword.iskeyword(name)
|
288
|
+
else:
|
289
|
+
return (
|
290
|
+
name.isidentifier() and not keyword.iskeyword(name) and not name == "name"
|
291
|
+
)
|
239
292
|
|
240
293
|
|
241
294
|
def create_valid_var_name(s, transform_func: Callable = lambda x: x.lower()) -> str:
|
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.1
|
2
2
|
Name: edsl
|
3
|
-
Version: 0.1.
|
3
|
+
Version: 0.1.29
|
4
4
|
Summary: Create and analyze LLM-based surveys
|
5
5
|
Home-page: https://www.expectedparrot.com/
|
6
6
|
License: MIT
|
@@ -30,6 +30,7 @@ Requires-Dist: pandas (>=2.1.4,<3.0.0)
|
|
30
30
|
Requires-Dist: pydot (>=2.0.0,<3.0.0)
|
31
31
|
Requires-Dist: pygments (>=2.17.2,<3.0.0)
|
32
32
|
Requires-Dist: pymupdf (>=1.24.4,<2.0.0)
|
33
|
+
Requires-Dist: pyreadstat (>=1.2.7,<2.0.0)
|
33
34
|
Requires-Dist: python-docx (>=1.1.0,<2.0.0)
|
34
35
|
Requires-Dist: python-dotenv (>=1.0.0,<2.0.0)
|
35
36
|
Requires-Dist: restrictedpython (>=7.1,<8.0)
|
@@ -45,28 +46,54 @@ Description-Content-Type: text/markdown
|
|
45
46
|
<img src="https://github.com/expectedparrot/edsl/blob/main/static/logo.png?raw=true" alt="edsl.png" width="100"/>
|
46
47
|
</p>
|
47
48
|
|
48
|
-
The Expected Parrot Domain-Specific Language (EDSL) package lets you conduct computational social science and market research with AI. Use it to design surveys and experiments, simulate responses with large language models, and perform data labeling and other research tasks.
|
49
|
+
The Expected Parrot Domain-Specific Language (EDSL) package lets you conduct computational social science and market research with AI. Use it to design surveys and experiments, simulate responses with large language models, and perform data labeling and other research tasks. Results are formatted as specified datasets and come with built-in methods for analyzing, visualizing, and sharing.
|
49
50
|
|
50
51
|
## ๐ Links
|
51
|
-
- PyPI
|
52
|
-
- Documentation
|
53
|
-
- Getting started
|
54
|
-
- Discord
|
52
|
+
- [PyPI](https://pypi.org/project/edsl/)
|
53
|
+
- [Documentation](https://docs.expectedparrot.com)
|
54
|
+
- [Getting started](https://docs.expectedparrot.com/en/latest/starter_tutorial.html)
|
55
|
+
- [Discord](https://discord.com/invite/mxAYkjfy9m)
|
56
|
+
- [Twitter](https://x.com/ExpectedParrot)
|
57
|
+
- [LinkedIn](https://www.linkedin.com/company/expectedparrot/)
|
58
|
+
- [Blog](https://blog.expectedparrot.com)
|
55
59
|
|
60
|
+
## ๐ Hello, World!
|
61
|
+
A quick example:
|
56
62
|
|
57
|
-
|
58
|
-
|
63
|
+
```python
|
64
|
+
# Import a question type
|
65
|
+
from edsl.questions import QuestionMultipleChoice
|
59
66
|
|
67
|
+
# Construct a question using the question type template
|
68
|
+
q = QuestionMultipleChoice(
|
69
|
+
question_name="example_question",
|
70
|
+
question_text="How do you feel today?",
|
71
|
+
question_options=["Bad", "OK", "Good"]
|
72
|
+
)
|
60
73
|
|
61
|
-
|
62
|
-
|
74
|
+
# Run it with the default language model
|
75
|
+
results = q.run()
|
76
|
+
|
77
|
+
# Inspect the results in a dataset
|
78
|
+
results.select("example_question").print()
|
63
79
|
```
|
64
|
-
|
80
|
+
|
81
|
+
Output:
|
82
|
+
```python
|
83
|
+
โโโโโโโโโโโโโโโโโโโโโ
|
84
|
+
โ answer โ
|
85
|
+
โ .example_question โ
|
86
|
+
โกโโโโโโโโโโโโโโโโโโโโฉ
|
87
|
+
โ Good โ
|
88
|
+
โโโโโโโโโโโโโโโโโโโโโ
|
65
89
|
```
|
66
90
|
|
67
|
-
|
68
|
-
|
91
|
+
## ๐ป Requirements
|
92
|
+
* EDSL is compatible with Python 3.9 - 3.12.
|
93
|
+
* API keys for large language models that you want to use, stored in a `.env` file.
|
94
|
+
See instructions on [storing API keys](https://docs.expectedparrot.com/en/latest/api_keys.html).
|
69
95
|
|
70
|
-
##
|
71
|
-
|
96
|
+
## ๐ก Contributions, feature requests & bugs
|
97
|
+
Interested in contributing? Want us to add a new feature? Found a bug for us to squash?
|
98
|
+
Please send us an email at [info@expectedparrot.com](mailto:info@expectedparrot.com) or message us at our [Discord channel](https://discord.com/invite/mxAYkjfy9m).
|
72
99
|
|