ワンクリックで
surveys
Complete reference for EDSL survey construction: question types, Jinja2 templating, skip/navigation rules, and memory modes.
Codex または Claude でインストール この Prompt をコピーして Codex、Claude、または他のアシスタントに貼り付けると、Skill ページを確認してインストールできます。
メニュー
Complete reference for EDSL survey construction: question types, Jinja2 templating, skip/navigation rules, and memory modes.
Codex または Claude でインストール この Prompt をコピーして Codex、Claude、または他のアシスタントに貼り付けると、Skill ページを確認してインストールできます。
SOC 職業分類に基づく
Patterns for creating EDSL AgentLists from various sources: lists, CSV, Excel, DataFrame, and programmatic combinations.
Saving EDSL objects locally and publishing them to Coop (Expected Parrot's servers).
Templates for the standard EDSL study files: survey, scenarios, agents, models, and create_results.py.
Error logging protocol using append-only JSONL format (errors.jsonl).
Developer tool: find the most recent errors.jsonl from an agent run, diagnose root causes, and interactively patch the agent's instruction files to prevent recurrence.
Using FileStore to wrap files (images, PDFs, data) for use in EDSL survey scenarios.
| name | surveys |
| description | Complete reference for EDSL survey construction: question types, Jinja2 templating, skip/navigation rules, and memory modes. |
Consolidated reference for building surveys with EDSL: question types, Jinja2 templating, skip/navigation rules, memory modes, helper utilities, and visualization.
from edsl import Survey, QuestionFreeText, QuestionMultipleChoice
q1 = QuestionFreeText(
question_name="name",
question_text="What is your name?"
)
q2 = QuestionMultipleChoice(
question_name="color",
question_text="What is your favorite color?",
question_options=["Red", "Blue", "Green", "Yellow"]
)
q3 = QuestionFreeText(
question_name="why_color",
question_text="Why do you like that color?"
)
survey = Survey([q1, q2, q3])
Survey is immutable - each operation returns a new Survey instance:
survey = Survey()
survey = survey.add_question(QuestionFreeText(
question_name="q1",
question_text="First question?"
))
survey = survey.add_question(QuestionFreeText(
question_name="q2",
question_text="Second question?"
))
# Add at specific index
survey = survey.add_question(new_question, index=1)
Instructions are displayed to respondents between questions:
from edsl import Survey, Instruction
instruction = Instruction(
text="Please answer the following questions honestly.",
name="intro"
)
survey = survey.add_instruction(instruction)
survey = survey.add_instruction(
Instruction(text="Now for some demographic questions...")
)
IMPORTANT:
Instructiontext is NOT checked for scenario field references. If your scenarios have fields that must be used, reference them in a question'squestion_text, not in an Instruction. EDSL'sJobsCompatibilityErroronly looks at question text.
All questions require question_name (a valid Python identifier) and question_text.
To see the question types available:
from edsl import Question
Question.available()
Open-ended text responses without constraints.
from edsl import QuestionFreeText
q = QuestionFreeText(
question_name="feedback",
question_text="What do you think about our service?"
)
Single selection from a predefined list of options.
from edsl import QuestionMultipleChoice
q = QuestionMultipleChoice(
question_name="color",
question_text="What is your favorite color?",
question_options=["Red", "Blue", "Green", "Yellow"]
)
Multiple selections from a predefined list (checkbox-style).
from edsl import QuestionCheckBox
q = QuestionCheckBox(
question_name="features",
question_text="Which features do you use? (Select all that apply)",
question_options=["Feature A", "Feature B", "Feature C", "Feature D"],
min_selections=1,
max_selections=3
)
Numeric responses with optional min/max bounds.
from edsl import QuestionNumerical
q = QuestionNumerical(
question_name="age",
question_text="How old are you?",
min_value=0,
max_value=120
)
Simple binary yes/no question (derived from MultipleChoice).
from edsl import QuestionYesNo
q = QuestionYesNo(
question_name="consent",
question_text="Do you agree to participate in this survey?"
)
# Options are automatically ["Yes", "No"]
Linear scale with customizable range and endpoint labels.
from edsl import QuestionLinearScale
q = QuestionLinearScale(
question_name="satisfaction",
question_text="How satisfied are you with our service?",
question_options=[1, 2, 3, 4, 5],
option_labels={1: "Very Unsatisfied", 5: "Very Satisfied"}
)
Standard 5-point Likert scale (agree/disagree).
from edsl import QuestionLikertFive
q = QuestionLikertFive(
question_name="statement_agree",
question_text="I find the product easy to use."
)
# Options: Strongly disagree, Disagree, Neutral, Agree, Strongly agree
Response as a list of items.
from edsl import QuestionList
q = QuestionList(
question_name="top_movies",
question_text="List your top 3 favorite movies.",
max_list_items=3
)
Ranking/ordering items by preference.
from edsl import QuestionRank
q = QuestionRank(
question_name="priority",
question_text="Rank these features by importance (1 = most important):",
question_options=["Speed", "Security", "Price", "Support"],
num_selections=4
)
Grid-based responses with rows (items) and columns (options).
from edsl import QuestionMatrix
q = QuestionMatrix(
question_name="product_ratings",
question_text="Rate each product on the following attributes:",
question_items=["Product A", "Product B", "Product C"],
question_options=["Poor", "Fair", "Good", "Excellent"],
)
Allocating a fixed budget across multiple options.
from edsl import QuestionBudget
q = QuestionBudget(
question_name="time_allocation",
question_text="How would you allocate 100 hours across these activities?",
question_options=["Work", "Exercise", "Leisure", "Sleep"],
budget_sum=100
)
Response as key-value pairs (structured data).
from edsl import QuestionDict
q = QuestionDict(
question_name="contact_info",
question_text="Provide your contact information:",
answer_keys=["name", "email", "phone"]
)
Extracting specific information from text.
from edsl import QuestionExtract
q = QuestionExtract(
question_name="entities",
question_text="Extract all company names from the following text: {{ text }}",
answer_template={"companies": "List of company names"}
)
BM25-powered search through large option sets.
from edsl import QuestionDropdown
q = QuestionDropdown(
question_name="country",
question_text="Select your country:",
question_options=["Afghanistan", "Albania", ..., "Zimbabwe"]
)
Multiple choice with an "Other" option for custom responses.
from edsl import QuestionMultipleChoiceWithOther
q = QuestionMultipleChoiceWithOther(
question_name="source",
question_text="How did you hear about us?",
question_options=["Google", "Friend", "Advertisement"],
other_option_label="Other (please specify)"
)
Checkbox with an "Other" option for custom responses.
from edsl import QuestionCheckboxWithOther
q = QuestionCheckboxWithOther(
question_name="interests",
question_text="What are your interests?",
question_options=["Sports", "Music", "Reading"],
other_option_label="Other"
)
Select top K items from a list.
from edsl import QuestionTopK
q = QuestionTopK(
question_name="favorites",
question_text="Select your top 3 favorite items:",
question_options=["A", "B", "C", "D", "E"],
k=3
)
Python function-based question (not sent to LLM - computed locally).
from edsl import QuestionFunctional
def compute_sum(scenario, agent):
numbers = scenario.get("numbers", [])
return sum(numbers)
q = QuestionFunctional(
question_name="total",
question_text="Calculate the sum",
func=compute_sum
)
Use custom Pydantic models as response schemas.
from edsl import QuestionPydantic
from pydantic import BaseModel
class PersonInfo(BaseModel):
name: str
age: int
occupation: str
q = QuestionPydantic(
question_name="person",
question_text="Describe a person:",
pydantic_model=PersonInfo
)
Responses with markdown formatting.
from edsl import QuestionMarkdown
q = QuestionMarkdown(
question_name="formatted_response",
question_text="Write a formatted response with headers and lists."
)
All questions support these common parameters:
| Parameter | Description |
|---|---|
question_name | Unique identifier (valid Python identifier) |
question_text | The question text (supports Jinja2 templating) |
answering_instructions | Optional custom instructions for the LLM |
question_presentation | Optional custom presentation template |
| Type | Use Case | Key Parameter |
|---|---|---|
QuestionFreeText | Open-ended responses | - |
QuestionMultipleChoice | Single selection | question_options |
QuestionCheckBox | Multiple selections | question_options |
QuestionNumerical | Numbers | min_value, max_value |
QuestionYesNo | Binary yes/no | - |
QuestionLinearScale | Numeric scale | question_options, option_labels |
QuestionLikertFive | 5-point agree/disagree | - |
QuestionList | List of items | max_list_items |
QuestionRank | Ordering | question_options, num_selections |
QuestionMatrix | Grid/table | question_items, question_options |
QuestionBudget | Budget allocation | question_options, budget_sum |
QuestionDict | Key-value pairs | answer_keys |
QuestionExtract | Extract from text | answer_template |
QuestionDropdown | Large option sets | question_options |
EDSL uses Jinja2 templating to create dynamic questions. Template variables are enclosed in {{ }} and are rendered at runtime.
from edsl import QuestionFreeText, Scenario
q = QuestionFreeText(
question_name="opinion",
question_text="What do you think about {{ scenario.fruit }}?"
)
scenarios = [
Scenario({"fruit": "apples"}),
Scenario({"fruit": "oranges"}),
]
results = q.by(scenarios).run()
from edsl import QuestionFreeText, Agent
q = QuestionFreeText(
question_name="perspective",
question_text="As a {{ agent.occupation }}, what do you think about remote work?"
)
agent = Agent(traits={"occupation": "software engineer", "age": 35})
results = q.by(agent).run()
Reference previous answers within a survey:
q1 = QuestionFreeText(
question_name="name",
question_text="What is your name?"
)
q2 = QuestionFreeText(
question_name="greeting",
question_text="Hello {{ name.answer }}! How are you today?"
)
survey = Survey([q1, q2])
q = QuestionMultipleChoice(
question_name="preference",
question_text="Which {{ scenario.category }} do you prefer?",
question_options=[
"{{ scenario.option_a }}",
"{{ scenario.option_b }}",
"{{ scenario.option_c }}"
]
)
| Variable | Access Pattern | Example |
|---|---|---|
| Scenario value | {{ scenario.key }} | {{ scenario.fruit }} |
| Agent trait | {{ agent.trait }} | {{ agent.occupation }} |
| Prior answer | {{ question_name.answer }} | {{ q1.answer }} |
Rules define conditional navigation through surveys using Jinja2 template expressions.
survey = survey.add_skip_rule(
"pet_name",
"{{ has_pet.answer }} == 'No'"
)
survey = (survey
.add_rule("preference", "{{ preference.answer }} == 'A'", "section_a")
.add_rule("preference", "{{ preference.answer }} == 'B'", "section_b"))
survey = survey.add_stop_rule(
"eligibility",
"{{ eligibility.answer }} == 'No'"
)
from edsl.surveys.navigation_markers import EndOfSurvey
survey = survey.add_rule("screening", "{{ screening.answer }} == 'disqualified'", EndOfSurvey)
"{{ question_name.answer }} == 'value'"
"{{ age.answer }} > 18"
"{{ q1.answer }} == 'yes' and {{ q2.answer }} != 'no'"
| Task | Method |
|---|---|
| Add skip rule | survey.add_skip_rule(question, expression) |
| Add navigation rule | survey.add_rule(question, expression, next_question) |
| Add stop rule | survey.add_stop_rule(question, expression) |
| Set priority | survey.add_rule(q, expr, next_q, priority=1) |
| View rules | survey.show_rules() |
| Jump to end | survey.add_rule(q, expr, EndOfSurvey) |
Memory controls which previous question-answer pairs an agent sees when answering each question.
| Mode | Method | Use Case |
|---|---|---|
| No Memory | (default) | Independent questions |
| Full Memory | survey.set_full_memory_mode() | Conversational surveys |
| Lagged Memory | survey.set_lagged_memory(lags=N) | Recent context only |
| Targeted Memory | survey.add_targeted_memory(focal, prior) | Precise control |
| Memory Collection | survey.add_memory_collection(focal, [priors]) | Multiple targeted |
from edsl.surveys.survey_helpers.matrix_combiner import combine_multiple_choice_to_matrix
new_survey = combine_multiple_choice_to_matrix(
survey=survey,
question_names=["trust_freelancer", "trust_ai", "trust_agency"],
matrix_question_name="trust_matrix"
)
Survey methods can be chained since each returns a new Survey:
survey = (Survey([q1, q2, q3])
.add_rule("q1", "{{ q1.answer }} == 'skip'", "q3")
.add_skip_rule("q2", "{{ q1.answer }} == 'skip'")
.add_question(q4))
| Task | Method |
|---|---|
| Create survey | Survey([q1, q2, q3]) |
| Add question | survey.add_question(q, index=None) |
| Add instruction | survey.add_instruction(inst) |
| Get question | survey.get("question_name") |
| List questions | survey.questions |
| Question names | survey.question_names |
| Number of questions | len(survey) |