AgentSkillsCN

edsl-survey-helpers

支持对问题进行重命名,将多项选择题组合成矩阵,并自动生成后续问题。

SKILL.md
--- frontmatter
name: edsl-survey-helpers
description: Question renaming, combining MC questions into matrices, and auto-generating follow-up questions
allowed-tools: Read, Glob, Bash(python:*)

Survey Helper Utilities

Advanced utilities for manipulating surveys.

Question Renaming

Rename a question and automatically update ALL references throughout the survey:

python
from edsl import Survey

survey = Survey([q1, q2, q3])
survey = survey.add_rule("q1", "{{ q1.answer }} == 'yes'", "q2")

# Rename q1 to "intro_question"
# All rules, memory, piping references are updated automatically
new_survey = survey.with_renamed_question("q1", "intro_question")

# Now the rule expression is: "{{ intro_question.answer }} == 'yes'"

What gets updated:

  • Question name in the question object
  • Rule expressions (both q1.answer and {{ q1.answer }} formats)
  • Memory plan (focal and prior question names)
  • Piping references in question text ({{ q1.answer }} becomes {{ intro_question.answer }})
  • Piping in question options
  • Instruction text references
  • Question groups

Matrix Combiner

Combine multiple multiple-choice questions with the same options into a single matrix question:

python
from edsl import Survey, QuestionMultipleChoice
from edsl.surveys.survey_helpers.matrix_combiner import combine_multiple_choice_to_matrix

# Questions with same options
q1 = QuestionMultipleChoice(
    question_name="trust_freelancer",
    question_text="How much would you trust: A freelancer without AI",
    question_options=["High", "Medium", "Low"]
)
q2 = QuestionMultipleChoice(
    question_name="trust_ai",
    question_text="How much would you trust: A freelancer with AI",
    question_options=["High", "Medium", "Low"]
)
q3 = QuestionMultipleChoice(
    question_name="trust_agency",
    question_text="How much would you trust: An agency",
    question_options=["High", "Medium", "Low"]
)

survey = Survey([q1, q2, q3])

# Combine into matrix - auto-infers question text from common prefix
new_survey = combine_multiple_choice_to_matrix(
    survey=survey,
    question_names=["trust_freelancer", "trust_ai", "trust_agency"],
    matrix_question_name="trust_matrix"
)
# Creates QuestionMatrix with:
# - question_text: "How much would you trust"
# - question_items: ["A freelancer without AI", "A freelancer with AI", "An agency"]
# - question_options: ["High", "Medium", "Low"]

With Explicit Text

python
new_survey = combine_multiple_choice_to_matrix(
    survey=survey,
    question_names=["satisfaction_work", "satisfaction_pay"],
    matrix_question_name="satisfaction_matrix",
    matrix_question_text="How satisfied are you with each aspect?",
    remove_original_questions=True,  # Default: removes originals
    index=0  # Position in survey (default: end)
)

Requirements

  • All questions must be QuestionMultipleChoice
  • All questions must have identical question_options

Follow-up Questions

Auto-generate conditional follow-up questions for each option in a multiple choice question:

python
from edsl import Survey, QuestionMultipleChoice, QuestionFreeText

# Main question
q_restaurant = QuestionMultipleChoice(
    question_name="restaurants",
    question_text="Which restaurant do you prefer?",
    question_options=["Italian", "Chinese", "Mexican"]
)

# Follow-up template - uses {{ restaurants.answer }} placeholder
q_followup = QuestionFreeText(
    question_name="why_restaurant",
    question_text="Why do you like {{ restaurants.answer }}?"
)

# Create survey and add follow-ups
survey = Survey([q_restaurant])
survey = survey.add_followup_questions("restaurants", q_followup)

# Creates 4 questions total:
# 1. restaurants (original)
# 2. why_restaurant_restaurants_0 ("Why do you like Italian?")
# 3. why_restaurant_restaurants_1 ("Why do you like Chinese?")
# 4. why_restaurant_restaurants_2 ("Why do you like Mexican?")

# Each follow-up has skip logic:
# - why_restaurant_restaurants_0 skipped unless answer == "Italian"
# - why_restaurant_restaurants_1 skipped unless answer == "Chinese"
# - etc.

How It Works

  1. Creates one follow-up question per option
  2. Substitutes {{ question_name.answer }} with each option value
  3. Adds skip logic so each follow-up only appears for its option
  4. Maintains proper survey flow

CSS Styling (for HTML Export)

Customize CSS for HTML survey rendering:

python
from edsl.surveys.survey_helpers.survey_css import SurveyCSS, CSSRule

# Create custom styles
css = SurveyCSS()
css.update_style("survey_container", "width", "100%")
css.update_style("survey_container", "max-width", "800px")
css.update_style("question_text", "font-size", "20px")
css.update_style("question_text", "font-weight", "bold")

# Remove a style
css.remove_style("survey_container", "max-width")

# Generate CSS string
css_string = css.generate_css()
print(css_string)

# Get default styles
default_css = SurveyCSS.default_style()

Default CSS Selectors

SelectorPurpose
survey_containerMain survey wrapper
survey_questionIndividual question container
question_textQuestion text styling
question_optionsOptions list styling
question_options liIndividual option items

Delete Questions

python
# Delete a question by name
survey = survey.delete_question("question_name")

# Delete by index
survey = survey.delete_question(survey.questions[2])

Move Questions

python
# Move question to new position
survey = survey.move_question("question_name", new_index=0)

Quick Reference

TaskMethod
Rename questionsurvey.with_renamed_question(old, new)
Combine to matrixcombine_multiple_choice_to_matrix(survey, names, new_name)
Add follow-upssurvey.add_followup_questions(ref_q, template)
Delete questionsurvey.delete_question(name)
Move questionsurvey.move_question(name, new_index)
Custom CSSSurveyCSS().update_style(selector, prop, value)