edsl 0.1.44__py3-none-any.whl → 0.1.46__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 +7 -3
- edsl/__version__.py +1 -1
- edsl/agents/InvigilatorBase.py +3 -1
- edsl/agents/PromptConstructor.py +66 -91
- edsl/agents/QuestionInstructionPromptBuilder.py +160 -79
- edsl/agents/QuestionTemplateReplacementsBuilder.py +80 -17
- edsl/agents/question_option_processor.py +15 -6
- edsl/coop/CoopFunctionsMixin.py +3 -4
- edsl/coop/coop.py +171 -96
- edsl/data/RemoteCacheSync.py +10 -9
- edsl/enums.py +3 -3
- edsl/inference_services/AnthropicService.py +11 -9
- edsl/inference_services/AvailableModelFetcher.py +2 -0
- edsl/inference_services/AwsBedrock.py +1 -2
- edsl/inference_services/AzureAI.py +12 -9
- edsl/inference_services/GoogleService.py +9 -4
- edsl/inference_services/InferenceServicesCollection.py +2 -2
- edsl/inference_services/MistralAIService.py +1 -2
- edsl/inference_services/OpenAIService.py +9 -4
- edsl/inference_services/PerplexityService.py +2 -1
- edsl/inference_services/{GrokService.py → XAIService.py} +2 -2
- edsl/inference_services/registry.py +2 -2
- edsl/jobs/AnswerQuestionFunctionConstructor.py +12 -1
- edsl/jobs/Jobs.py +24 -17
- edsl/jobs/JobsChecks.py +10 -13
- edsl/jobs/JobsPrompts.py +49 -26
- edsl/jobs/JobsRemoteInferenceHandler.py +4 -5
- edsl/jobs/async_interview_runner.py +3 -1
- edsl/jobs/check_survey_scenario_compatibility.py +5 -5
- edsl/jobs/data_structures.py +3 -0
- edsl/jobs/interviews/Interview.py +6 -3
- edsl/jobs/interviews/InterviewExceptionEntry.py +12 -0
- edsl/jobs/tasks/TaskHistory.py +1 -1
- edsl/language_models/LanguageModel.py +6 -3
- edsl/language_models/PriceManager.py +45 -5
- edsl/language_models/model.py +47 -26
- edsl/questions/QuestionBase.py +21 -0
- edsl/questions/QuestionBasePromptsMixin.py +103 -0
- edsl/questions/QuestionFreeText.py +22 -5
- edsl/questions/descriptors.py +4 -0
- edsl/questions/question_base_gen_mixin.py +96 -29
- edsl/results/Dataset.py +65 -0
- edsl/results/DatasetExportMixin.py +320 -32
- edsl/results/Result.py +27 -0
- edsl/results/Results.py +22 -2
- edsl/results/ResultsGGMixin.py +7 -3
- edsl/scenarios/DocumentChunker.py +2 -0
- edsl/scenarios/FileStore.py +10 -0
- edsl/scenarios/PdfExtractor.py +21 -1
- edsl/scenarios/Scenario.py +25 -9
- edsl/scenarios/ScenarioList.py +226 -24
- edsl/scenarios/handlers/__init__.py +1 -0
- edsl/scenarios/handlers/docx.py +5 -1
- edsl/scenarios/handlers/jpeg.py +39 -0
- edsl/surveys/Survey.py +5 -4
- edsl/surveys/SurveyFlowVisualization.py +91 -43
- edsl/templates/error_reporting/exceptions_table.html +7 -8
- edsl/templates/error_reporting/interview_details.html +1 -1
- edsl/templates/error_reporting/interviews.html +0 -1
- edsl/templates/error_reporting/overview.html +2 -7
- edsl/templates/error_reporting/performance_plot.html +1 -1
- edsl/templates/error_reporting/report.css +1 -1
- edsl/utilities/PrettyList.py +14 -0
- edsl-0.1.46.dist-info/METADATA +246 -0
- {edsl-0.1.44.dist-info → edsl-0.1.46.dist-info}/RECORD +67 -66
- edsl-0.1.44.dist-info/METADATA +0 -110
- {edsl-0.1.44.dist-info → edsl-0.1.46.dist-info}/LICENSE +0 -0
- {edsl-0.1.44.dist-info → edsl-0.1.46.dist-info}/WHEEL +0 -0
@@ -8,51 +8,113 @@ import tempfile
|
|
8
8
|
class SurveyFlowVisualization:
|
9
9
|
"""A mixin for visualizing the flow of a survey with parameter visualization."""
|
10
10
|
|
11
|
-
def __init__(self, survey: "Survey"):
|
11
|
+
def __init__(self, survey: "Survey", scenario: Optional["Scenario"] = None, agent: Optional["Agent"] = None):
|
12
12
|
self.survey = survey
|
13
|
+
self.scenario = scenario or {}
|
14
|
+
self.agent = agent
|
15
|
+
#from edsl import Scenario
|
16
|
+
#self.scenario = Scenario({'hello': 'world'})
|
13
17
|
|
14
18
|
def show_flow(self, filename: Optional[str] = None):
|
15
19
|
"""Create an image showing the flow of users through the survey and question parameters."""
|
16
20
|
# Create a graph object
|
17
21
|
import pydot
|
18
22
|
|
19
|
-
|
23
|
+
FONT_SIZE = "10"
|
20
24
|
|
21
|
-
|
25
|
+
graph = pydot.Dot(graph_type="digraph", fontsize=FONT_SIZE)
|
26
|
+
|
27
|
+
# First collect all unique parameters and different types of references
|
22
28
|
params_and_refs = set()
|
23
29
|
param_to_questions = {} # Keep track of which questions use each parameter
|
24
|
-
|
30
|
+
reference_types = {} # Dictionary to store different types of references
|
31
|
+
reference_colors = {
|
32
|
+
'answer': 'purple',
|
33
|
+
'question_text': 'red',
|
34
|
+
'question_options': 'orange',
|
35
|
+
'comment': 'blue',
|
36
|
+
'default': "grey"
|
37
|
+
}
|
25
38
|
|
26
39
|
# First pass: collect parameters and their question associations
|
27
40
|
for index, question in enumerate(self.survey.questions):
|
28
|
-
# Add the main question node
|
29
41
|
question_node = pydot.Node(
|
30
|
-
f"Q{index}", label=f"{question.question_name}", shape="ellipse"
|
42
|
+
f"Q{index}", label=f"{question.question_name}", shape="ellipse", fontsize=FONT_SIZE
|
31
43
|
)
|
32
44
|
graph.add_node(question_node)
|
33
45
|
|
34
|
-
if hasattr(question, "
|
35
|
-
for param in question.
|
36
|
-
|
37
|
-
|
38
|
-
|
46
|
+
if hasattr(question, "detailed_parameters"):
|
47
|
+
for param in question.detailed_parameters:
|
48
|
+
if "agent." in param:
|
49
|
+
# Handle agent trait references
|
50
|
+
trait_name = param.replace("agent.", "")
|
51
|
+
params_and_refs.add(param)
|
52
|
+
if param not in param_to_questions:
|
53
|
+
param_to_questions[param] = []
|
54
|
+
param_to_questions[param].append(index)
|
55
|
+
elif "." in param:
|
56
|
+
source_q, ref_type = param.split(".", 1)
|
57
|
+
if ref_type not in reference_types:
|
58
|
+
reference_types[ref_type] = set()
|
59
|
+
reference_types[ref_type].add((source_q, index))
|
39
60
|
else:
|
40
61
|
params_and_refs.add(param)
|
41
62
|
if param not in param_to_questions:
|
42
63
|
param_to_questions[param] = []
|
43
64
|
param_to_questions[param].append(index)
|
44
65
|
|
66
|
+
# Add edges for all reference types
|
67
|
+
for ref_type, references in reference_types.items():
|
68
|
+
color = reference_colors.get(ref_type, reference_colors['default'])
|
69
|
+
for source_q_name, target_q_index in references:
|
70
|
+
# Find the source question index by name
|
71
|
+
try:
|
72
|
+
source_q_index = next(
|
73
|
+
i
|
74
|
+
for i, q in enumerate(self.survey.questions)
|
75
|
+
if q.question_name == source_q_name
|
76
|
+
)
|
77
|
+
except StopIteration:
|
78
|
+
print(f"Source question {source_q_name} not found in survey.")
|
79
|
+
continue
|
80
|
+
|
81
|
+
ref_edge = pydot.Edge(
|
82
|
+
f"Q{source_q_index}",
|
83
|
+
f"Q{target_q_index}",
|
84
|
+
style="dashed",
|
85
|
+
color=color,
|
86
|
+
label=f".{ref_type}",
|
87
|
+
fontcolor=color,
|
88
|
+
fontname="Courier",
|
89
|
+
fontsize=FONT_SIZE
|
90
|
+
)
|
91
|
+
graph.add_edge(ref_edge)
|
92
|
+
|
45
93
|
# Create parameter nodes and connect them to questions
|
46
94
|
for param in params_and_refs:
|
47
95
|
param_node_name = f"param_{param}"
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
96
|
+
node_attrs = {
|
97
|
+
"label": f"{{{{ {param} }}}}",
|
98
|
+
"shape": "box",
|
99
|
+
"style": "filled",
|
100
|
+
"fillcolor": "lightgrey",
|
101
|
+
"fontsize": FONT_SIZE,
|
102
|
+
}
|
103
|
+
|
104
|
+
# Special handling for agent traits
|
105
|
+
if param.startswith("agent."):
|
106
|
+
node_attrs.update({
|
107
|
+
"fillcolor": "lightpink",
|
108
|
+
"label": f"Agent Trait\n{{{{ {param} }}}}"
|
109
|
+
})
|
110
|
+
# Check if parameter exists in scenario
|
111
|
+
elif self.scenario and param in self.scenario:
|
112
|
+
node_attrs.update({
|
113
|
+
"fillcolor": "lightgreen",
|
114
|
+
"label": f"Scenario\n{{{{ {param} }}}}"
|
115
|
+
})
|
116
|
+
|
117
|
+
param_node = pydot.Node(param_node_name, **node_attrs)
|
56
118
|
graph.add_node(param_node)
|
57
119
|
|
58
120
|
# Connect this parameter to all questions that use it
|
@@ -61,39 +123,22 @@ class SurveyFlowVisualization:
|
|
61
123
|
param_node_name,
|
62
124
|
f"Q{q_index}",
|
63
125
|
style="dotted",
|
64
|
-
color="grey",
|
65
126
|
arrowsize="0.5",
|
127
|
+
fontsize=FONT_SIZE,
|
66
128
|
)
|
67
129
|
graph.add_edge(param_edge)
|
68
130
|
|
69
|
-
# Add edges for answer references
|
70
|
-
for source_q_name, target_q_index in answer_refs:
|
71
|
-
# Find the source question index by name
|
72
|
-
source_q_index = next(
|
73
|
-
i
|
74
|
-
for i, q in enumerate(self.survey.questions)
|
75
|
-
if q.question_name == source_q_name
|
76
|
-
)
|
77
|
-
ref_edge = pydot.Edge(
|
78
|
-
f"Q{source_q_index}",
|
79
|
-
f"Q{target_q_index}",
|
80
|
-
style="dashed",
|
81
|
-
color="purple",
|
82
|
-
label="answer reference",
|
83
|
-
)
|
84
|
-
graph.add_edge(ref_edge)
|
85
|
-
|
86
131
|
# Add an "EndOfSurvey" node
|
87
132
|
graph.add_node(
|
88
|
-
pydot.Node("EndOfSurvey", label="End of Survey", shape="rectangle")
|
133
|
+
pydot.Node("EndOfSurvey", label="End of Survey", shape="rectangle", fontsize=FONT_SIZE, style="filled", fillcolor="lightgrey")
|
89
134
|
)
|
90
135
|
|
91
136
|
# Add edges for normal flow through the survey
|
92
137
|
num_questions = len(self.survey.questions)
|
93
138
|
for index in range(num_questions - 1):
|
94
|
-
graph.add_edge(pydot.Edge(f"Q{index}", f"Q{index+1}"))
|
139
|
+
graph.add_edge(pydot.Edge(f"Q{index}", f"Q{index+1}", fontsize=FONT_SIZE))
|
95
140
|
|
96
|
-
graph.add_edge(pydot.Edge(f"Q{num_questions-1}", "EndOfSurvey"))
|
141
|
+
graph.add_edge(pydot.Edge(f"Q{num_questions-1}", "EndOfSurvey", fontsize=FONT_SIZE))
|
97
142
|
|
98
143
|
relevant_rules = [
|
99
144
|
rule
|
@@ -109,7 +154,7 @@ class SurveyFlowVisualization:
|
|
109
154
|
"purple",
|
110
155
|
"brown",
|
111
156
|
"cyan",
|
112
|
-
"
|
157
|
+
"darkgreen",
|
113
158
|
]
|
114
159
|
rule_colors = {
|
115
160
|
rule: colors[i % len(colors)] for i, rule in enumerate(relevant_rules)
|
@@ -133,6 +178,8 @@ class SurveyFlowVisualization:
|
|
133
178
|
fontcolor=color,
|
134
179
|
tailport="n",
|
135
180
|
headport="n",
|
181
|
+
fontname="Courier",
|
182
|
+
fontsize=FONT_SIZE,
|
136
183
|
)
|
137
184
|
else:
|
138
185
|
edge = pydot.Edge(
|
@@ -141,6 +188,8 @@ class SurveyFlowVisualization:
|
|
141
188
|
label=edge_label,
|
142
189
|
color=color,
|
143
190
|
fontcolor=color,
|
191
|
+
fontname="Courier",
|
192
|
+
fontsize=FONT_SIZE,
|
144
193
|
)
|
145
194
|
|
146
195
|
graph.add_edge(edge)
|
@@ -156,9 +205,8 @@ class SurveyFlowVisualization:
|
|
156
205
|
except FileNotFoundError:
|
157
206
|
print(
|
158
207
|
"""File not found. Most likely it's because you don't have graphviz installed. Please install it and try again.
|
159
|
-
|
208
|
+
On Ubuntu, you can install it by running:
|
160
209
|
$ sudo apt-get install graphviz
|
161
|
-
on Ubuntu.
|
162
210
|
"""
|
163
211
|
)
|
164
212
|
from edsl.utilities.is_notebook import is_notebook
|
@@ -7,11 +7,11 @@
|
|
7
7
|
<table border="1">
|
8
8
|
<thead>
|
9
9
|
<tr>
|
10
|
-
<th>Exception Type</th>
|
11
|
-
<th>Service</th>
|
12
|
-
<th>Model</th>
|
13
|
-
<th>Question Name</th>
|
14
|
-
<th>Total</th>
|
10
|
+
<th style="text-align: left">Exception Type</th>
|
11
|
+
<th style="text-align: left">Service</th>
|
12
|
+
<th style="text-align: left">Model</th>
|
13
|
+
<th style="text-align: left">Question Name</th>
|
14
|
+
<th style="text-align: left">Total</th>
|
15
15
|
</tr>
|
16
16
|
</thead>
|
17
17
|
<tbody>
|
@@ -27,9 +27,8 @@
|
|
27
27
|
</tbody>
|
28
28
|
</table>
|
29
29
|
<p>
|
30
|
-
|
31
|
-
You can modify the maximum number of attempts for failed API calls in `edsl/config.py`.
|
30
|
+
Note: You may encounter repeated exceptions where retries were attempted.
|
32
31
|
</p>
|
33
32
|
<p>
|
34
|
-
|
33
|
+
See details about each exception, including code for reproducing it (click to expand).
|
35
34
|
</p>
|
@@ -4,16 +4,11 @@
|
|
4
4
|
}
|
5
5
|
</style>
|
6
6
|
|
7
|
-
<
|
7
|
+
<h3>Exceptions Report</h3>
|
8
8
|
<p>
|
9
9
|
This report summarizes exceptions encountered in the job that was run.
|
10
10
|
</p>
|
11
|
-
<p>
|
12
|
-
For advice on dealing with exceptions, please see the EDSL <a href="https://docs.expectedparrot.com/en/latest/exceptions.html">documentation</a> page. <br>
|
13
|
-
You can also post a question at the Expected Parrot <a href="https://discord.com/invite/mxAYkjfy9m">Discord channel</a>, open an issue on <a href="https://github.com/expectedparrot/edsl">GitHub</a>, or send an email to <a href="mailto:info@expectedparrot.com">info@expectedparrot.com</a>.
|
14
|
-
</p>
|
15
11
|
|
16
|
-
<h2>Overview</h2>
|
17
12
|
<table border="1">
|
18
13
|
<tbody>
|
19
14
|
<tr>
|
@@ -27,5 +22,5 @@
|
|
27
22
|
</tbody>
|
28
23
|
</table>
|
29
24
|
<p>
|
30
|
-
An
|
25
|
+
An interview is the result of one survey, taken by one agent, with one model and one scenario (if any).
|
31
26
|
</p>
|
@@ -1,2 +1,2 @@
|
|
1
|
-
<h2>Performance Plot</h2>
|
1
|
+
<!-- <h2>Performance Plot</h2> -->
|
2
2
|
{{ performance_plot_html }}
|
edsl/utilities/PrettyList.py
CHANGED
@@ -1,12 +1,26 @@
|
|
1
1
|
from collections import UserList
|
2
2
|
from edsl.results.Dataset import Dataset
|
3
3
|
|
4
|
+
class Markkdown:
|
5
|
+
|
6
|
+
def __init__(self, text: str):
|
7
|
+
self.text = text
|
8
|
+
|
9
|
+
def __str__(self):
|
10
|
+
return self.text
|
11
|
+
|
12
|
+
def _repr_markdown_(self):
|
13
|
+
return self.text
|
4
14
|
|
5
15
|
class PrettyList(UserList):
|
6
16
|
def __init__(self, data=None, columns=None):
|
7
17
|
super().__init__(data)
|
8
18
|
self.columns = columns
|
9
19
|
|
20
|
+
def to_markdown(self):
|
21
|
+
text = "".join([str(row) for row in self])
|
22
|
+
return Markkdown(text)
|
23
|
+
|
10
24
|
def _repr_html_(self):
|
11
25
|
if isinstance(self[0], list) or isinstance(self[0], tuple):
|
12
26
|
num_cols = len(self[0])
|
@@ -0,0 +1,246 @@
|
|
1
|
+
Metadata-Version: 2.1
|
2
|
+
Name: edsl
|
3
|
+
Version: 0.1.46
|
4
|
+
Summary: Create and analyze LLM-based surveys
|
5
|
+
Home-page: https://www.expectedparrot.com/
|
6
|
+
License: MIT
|
7
|
+
Keywords: LLM,social science,surveys,user research
|
8
|
+
Author: John Horton
|
9
|
+
Author-email: info@expectedparrot.com
|
10
|
+
Requires-Python: >=3.9.1,<3.13
|
11
|
+
Classifier: License :: OSI Approved :: MIT License
|
12
|
+
Classifier: Programming Language :: Python :: 3
|
13
|
+
Classifier: Programming Language :: Python :: 3.10
|
14
|
+
Classifier: Programming Language :: Python :: 3.11
|
15
|
+
Classifier: Programming Language :: Python :: 3.12
|
16
|
+
Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
|
17
|
+
Classifier: Topic :: Software Development :: Libraries :: Application Frameworks
|
18
|
+
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
19
|
+
Requires-Dist: aiohttp (>=3.9.1,<4.0.0)
|
20
|
+
Requires-Dist: anthropic (>=0.45.0,<0.46.0)
|
21
|
+
Requires-Dist: azure-ai-inference (>=1.0.0b3,<2.0.0)
|
22
|
+
Requires-Dist: black[jupyter] (>=24.4.2,<25.0.0)
|
23
|
+
Requires-Dist: boto3 (>=1.34.161,<2.0.0)
|
24
|
+
Requires-Dist: google-generativeai (>=0.8.2,<0.9.0)
|
25
|
+
Requires-Dist: groq (>=0.9.0,<0.10.0)
|
26
|
+
Requires-Dist: jinja2 (>=3.1.2,<4.0.0)
|
27
|
+
Requires-Dist: json-repair (>=0.28.4,<0.29.0)
|
28
|
+
Requires-Dist: jupyter (>=1.0.0,<2.0.0)
|
29
|
+
Requires-Dist: markdown2 (>=2.4.11,<3.0.0)
|
30
|
+
Requires-Dist: matplotlib (>=3.8,<3.9)
|
31
|
+
Requires-Dist: mistralai (>=1.0.2,<2.0.0)
|
32
|
+
Requires-Dist: nest-asyncio (>=1.5.9,<2.0.0)
|
33
|
+
Requires-Dist: numpy (>=1.22,<2.0)
|
34
|
+
Requires-Dist: openai (>=1.4.0,<2.0.0)
|
35
|
+
Requires-Dist: openpyxl (>=3.1.5,<4.0.0)
|
36
|
+
Requires-Dist: pandas (>=2.1.4,<3.0.0)
|
37
|
+
Requires-Dist: platformdirs (>=4.3.6,<5.0.0)
|
38
|
+
Requires-Dist: pydot (>=2.0.0,<3.0.0)
|
39
|
+
Requires-Dist: pygments (>=2.17.2,<3.0.0)
|
40
|
+
Requires-Dist: pypdf2 (>=3.0.1,<4.0.0)
|
41
|
+
Requires-Dist: pyreadstat (>=1.2.7,<2.0.0)
|
42
|
+
Requires-Dist: python-docx (>=1.1.0,<2.0.0)
|
43
|
+
Requires-Dist: python-dotenv (>=1.0.0,<2.0.0)
|
44
|
+
Requires-Dist: python-pptx (>=1.0.2,<2.0.0)
|
45
|
+
Requires-Dist: restrictedpython (>=7.1,<8.0)
|
46
|
+
Requires-Dist: rich (>=13.7.0,<14.0.0)
|
47
|
+
Requires-Dist: setuptools (<72.0)
|
48
|
+
Requires-Dist: simpleeval (>=0.9.13,<0.10.0)
|
49
|
+
Requires-Dist: sqlalchemy (>=2.0.23,<3.0.0)
|
50
|
+
Requires-Dist: tabulate (>=0.9.0,<0.10.0)
|
51
|
+
Requires-Dist: tenacity (>=8.2.3,<9.0.0)
|
52
|
+
Requires-Dist: urllib3 (>=1.25.4,<1.27)
|
53
|
+
Project-URL: Documentation, https://docs.expectedparrot.com
|
54
|
+
Description-Content-Type: text/markdown
|
55
|
+
|
56
|
+
# Expected Parrot Domain-Specific Language (EDSL)
|
57
|
+
|
58
|
+
The Expected Parrot Domain-Specific Language (EDSL) package makes it easy to conduct computational social science and market research with AI. Use it to design surveys and experiments, collect responses from humans and large language models, and perform data labeling and many other research tasks. Results are formatted as specified datasets and come with built-in methods for analyzing, visualizing and sharing.
|
59
|
+
|
60
|
+
<p align="right">
|
61
|
+
<img src="https://github.com/expectedparrot/edsl/blob/main/static/logo.png?raw=true" alt="edsl.png" width="100"/>
|
62
|
+
</p>
|
63
|
+
|
64
|
+
## Features
|
65
|
+
|
66
|
+
**Declarative design**:
|
67
|
+
Specified <a href="https://docs.expectedparrot.con/en/latest/questions.html" target="_blank" rel="noopener noreferrer">question types</a> ensure consistent results without requiring a JSON schema (<a href="https://www.expectedparrot.com/content/2a848a0e-f9de-46bc-98d0-a13b9a1caf11" target="_blank" rel="noopener noreferrer">view at Coop</a>):
|
68
|
+
|
69
|
+
```python
|
70
|
+
from edsl import QuestionMultipleChoice
|
71
|
+
|
72
|
+
q = QuestionMultipleChoice(
|
73
|
+
question_name = "example",
|
74
|
+
question_text = "How do you feel today?",
|
75
|
+
question_options = ["Bad", "OK", "Good"]
|
76
|
+
)
|
77
|
+
|
78
|
+
results = q.run()
|
79
|
+
|
80
|
+
results.select("example")
|
81
|
+
```
|
82
|
+
|
83
|
+
> | answer.example |
|
84
|
+
> |-----------------|
|
85
|
+
> | Good |
|
86
|
+
|
87
|
+
<br>
|
88
|
+
|
89
|
+
**Parameterized prompts**:
|
90
|
+
Easily parameterize and control prompts with "<a href="https://docs.expectedparrot.com/en/latest/scenarios.html" target="_blank" rel="noopener noreferrer">scenarios</a>" of data automatically imported from many sources (CSV, PDF, PNG, etc.)(<a href="https://www.expectedparrot.com/content/7bb9ec2e-827b-4867-ac02-33163df1a1d1" target="_blank" rel="noopener noreferrer">view at Coop</a>):
|
91
|
+
|
92
|
+
```python
|
93
|
+
from edsl import ScenarioList, QuestionLinearScale
|
94
|
+
|
95
|
+
q = QuestionLinearScale(
|
96
|
+
question_name = "example",
|
97
|
+
question_text = "How much do you enjoy {{ activity }}?",
|
98
|
+
question_options = [1,2,3,4,5,],
|
99
|
+
option_labels = {1:"Not at all", 5:"Very much"}
|
100
|
+
)
|
101
|
+
|
102
|
+
sl = ScenarioList.from_list("activity", ["coding", "sleeping"])
|
103
|
+
|
104
|
+
results = q.by(sl).run()
|
105
|
+
|
106
|
+
results.select("activity", "example")
|
107
|
+
```
|
108
|
+
|
109
|
+
> | scenario.activity | answer.example |
|
110
|
+
> |--------------------|-----------------|
|
111
|
+
> | Coding | 5 |
|
112
|
+
> | Sleeping | 5 |
|
113
|
+
|
114
|
+
<br>
|
115
|
+
|
116
|
+
**Design AI agent personas to answer questions**:
|
117
|
+
Construct agents with relevant traits to provide diverse responses to your surveys (<a href="https://www.expectedparrot.com/content/b639a2d7-4ae6-48fe-8b9e-58350fab93de" target="_blank" rel="noopener noreferrer">view at Coop</a>)
|
118
|
+
|
119
|
+
```python
|
120
|
+
from edsl import Agent, AgentList, QuestionList
|
121
|
+
|
122
|
+
al = AgentList(Agent(traits = {"persona":p}) for p in ["botanist", "detective"])
|
123
|
+
|
124
|
+
q = QuestionList(
|
125
|
+
question_name = "example",
|
126
|
+
question_text = "What are your favorite colors?",
|
127
|
+
max_list_items = 3
|
128
|
+
)
|
129
|
+
|
130
|
+
results = q.by(al).run()
|
131
|
+
|
132
|
+
results.select("persona", "example")
|
133
|
+
```
|
134
|
+
|
135
|
+
> | agent.persona | answer.example |
|
136
|
+
> |----------------|---------------------------------------------|
|
137
|
+
> | botanist | ['Green', 'Earthy Brown', 'Sunset Orange'] |
|
138
|
+
> | detective | ['Gray', 'Black', 'Navy Blye'] |
|
139
|
+
|
140
|
+
<br>
|
141
|
+
|
142
|
+
**Simplified access to LLMs**:
|
143
|
+
Choose whether to use your own keys for LLMs, or access all <a href="https://www.expectedparrot.com/getting-started/coop-pricing" target="_blank" rel="noopener noreferrer">available models</a> with an Expected Parrot API key. Run surveys with many models at once and compare responses at a convenient inferface (<a href="https://www.expectedparrot.com/content/044465f0-b87f-430d-a3b9-4fd3b8560299" target="_blank" rel="noopener noreferrer">view at Coop</a>)
|
144
|
+
|
145
|
+
```python
|
146
|
+
from edsl import Model, ModelList, QuestionFreeText
|
147
|
+
|
148
|
+
ml = ModelList(Model(m) for m in ["gpt-4o", "gemini-1.5-flash"])
|
149
|
+
|
150
|
+
q = QuestionFreeText(
|
151
|
+
question_name = "example",
|
152
|
+
question_text = "What is your top tip for using LLMs to answer surveys?"
|
153
|
+
)
|
154
|
+
|
155
|
+
results = q.by(ml).run()
|
156
|
+
|
157
|
+
results.select("model", "example")
|
158
|
+
```
|
159
|
+
|
160
|
+
> | model.model | answer.example |
|
161
|
+
> |--------------------|-------------------------------------------------------------------------------------------------|
|
162
|
+
> | gpt-4o | When using large language models (LLMs) to answer surveys, my top tip is to ensure that the ... |
|
163
|
+
> | gemini-1.5-flash | My top tip for using LLMs to answer surveys is to **treat the LLM as a sophisticated brainst... |
|
164
|
+
|
165
|
+
<br>
|
166
|
+
|
167
|
+
**Piping & skip-logic**:
|
168
|
+
Build rich data labeling flows with features for piping answers and adding survey logic such as skip and stop rules (<a href="https://www.expectedparrot.com/content/b8afe09d-49bf-4c05-b753-d7b0ae782eb3" target="_blank" rel="noopener noreferrer">view at Coop</a>):
|
169
|
+
|
170
|
+
```python
|
171
|
+
from edsl import QuestionMultipleChoice, QuestionFreeText, Survey
|
172
|
+
|
173
|
+
q1 = QuestionMultipleChoice(
|
174
|
+
question_name = "color",
|
175
|
+
question_text = "What is your favorite primary color?",
|
176
|
+
question_options = ["red", "yellow", "blue"]
|
177
|
+
)
|
178
|
+
|
179
|
+
q2 = QuestionFreeText(
|
180
|
+
question_name = "flower",
|
181
|
+
question_text = "Name a flower that is {{ color.answer }}."
|
182
|
+
)
|
183
|
+
|
184
|
+
survey = Survey(questions = [q1, q2])
|
185
|
+
|
186
|
+
results = survey.run()
|
187
|
+
|
188
|
+
results.select("color", "flower")
|
189
|
+
```
|
190
|
+
|
191
|
+
> | answer.color | answer.flower |
|
192
|
+
> |---------------|-----------------------------------------------------------------------------------|
|
193
|
+
> | blue | A commonly known blue flower is the bluebell. Another example is the cornflower. |
|
194
|
+
|
195
|
+
<br>
|
196
|
+
|
197
|
+
**Caching**:
|
198
|
+
API calls to LLMs are cached automatically, allowing you to retrieve responses to questions that have already been run and reproduce experiments at no cost. Learn more about how the <a href="https://docs.expectedparrot.com/en/latest/remote_caching.html" target="_blank" rel="noopener noreferrer">universal remote cache</a> works.
|
199
|
+
|
200
|
+
**Flexibility**:
|
201
|
+
Choose whether to run surveys on your own computer or at the Expected Parrot server.
|
202
|
+
|
203
|
+
**Tools for collaboration**:
|
204
|
+
Easily share workflows and projects privately or publicly at Coop: an integrated platform for AI-based research. Your account comes with free credits for running surveys, and lets you securely share keys, track expenses and usage for your team.
|
205
|
+
|
206
|
+
**Built-in tools for analyis**:
|
207
|
+
Analyze results as specified datasets from your account or workspace. Easily import data to use with your surveys and export results.
|
208
|
+
|
209
|
+
## Getting started
|
210
|
+
|
211
|
+
1. Run `pip install edsl` to install the package.
|
212
|
+
|
213
|
+
2. <a href="https://www.expectedparrot.com/login" target="_blank" rel="noopener noreferrer">Create an account</a> to run surveys at the Expected Parrot server and access a <a href="https://docs.expectedparrot.com/en/latest/remote_caching.html" target="_blank" rel="noopener noreferrer">universal remote cache</a> of stored responses for reproducing results.
|
214
|
+
|
215
|
+
3. Choose whether to use your own keys for language models or get an Expected Parrot key to access all available models at once. Securely <a href="https://docs.expectedparrot.com/en/latest/api_keys.html" target="_blank" rel="noopener noreferrer">manage keys</a>, share expenses and track usage for your team from your account.
|
216
|
+
|
217
|
+
4. Run the <a href="https://docs.expectedparrot.com/en/latest/starter_tutorial.html" target="_blank" rel="noopener noreferrer">starter tutorial</a> and explore other demo notebooks.
|
218
|
+
|
219
|
+
5. Share workflows and survey results at <a href="https://www.expectedparrot.com/content/explore" target="_blank" rel="noopener noreferrer">Coop</a>
|
220
|
+
|
221
|
+
6. Join our <a href="https://discord.com/invite/mxAYkjfy9m" target="_blank" rel="noopener noreferrer">Discord</a> for updates and discussions! Request new features!
|
222
|
+
|
223
|
+
## Code & Docs
|
224
|
+
- <a href="https://pypi.org/project/edsl/" target="_blank" rel="noopener noreferrer">PyPI</a>
|
225
|
+
- <a href="https://github.com/expectedparrot/edsl" target="_blank" rel="noopener noreferrer">GitHub</a>
|
226
|
+
- <a href="https://docs.expectedparrot.com" target="_blank" rel="noopener noreferrer">Documentation</a>
|
227
|
+
|
228
|
+
## Requirements
|
229
|
+
- Python 3.9 - 3.12
|
230
|
+
- API keys for language models. You can use your own keys or an Expected Parrot key that provides access to all available models.
|
231
|
+
See instructions on <a href="https://docs.expectedparrot.com/en/latest/api_keys.html" target="_blank" rel="noopener noreferrer">managing keys</a> and <a href="https://www.expectedparrot.com/getting-started/coop-pricing" target="_blank" rel="noopener noreferrer">model pricing and performance</a> information.
|
232
|
+
|
233
|
+
## Coop
|
234
|
+
An integrated platform for running experiments, sharing workflows and launching hybrid human/AI surveys.
|
235
|
+
- <a href="https://www.expectedparrot.com/login" target="_blank" rel="noopener noreferrer">Login / Signup</a>
|
236
|
+
- <a href="https://www.expectedparrot.com/content/explore" target="_blank" rel="noopener noreferrer">Explore</a>
|
237
|
+
|
238
|
+
## Community
|
239
|
+
- <a href="https://discord.com/invite/mxAYkjfy9m" target="_blank" rel="noopener noreferrer">Discord</a>
|
240
|
+
- <a href="https://x.com/ExpectedParrot" target="_blank" rel="noopener noreferrer">Twitter</a>
|
241
|
+
- <a href="https://www.linkedin.com/company/expectedparrot/" target="_blank" rel="noopener noreferrer">LinkedIn</a>
|
242
|
+
- <a href="https://blog.expectedparrot.com" target="_blank" rel="noopener noreferrer">Blog</a>
|
243
|
+
|
244
|
+
## Contact
|
245
|
+
- <a href="mailto:info@expectedparrot.com" target="_blank" rel="noopener noreferrer">Email</a>
|
246
|
+
|