Scenario holds the inputs to a question: text, numbers, experimental conditions, or files such as PDFs, images, video, and audio. Give each input a name and refer to it in the question with {{ scenario.name }}. A ScenarioList supplies multiple sets of inputs so you can ask the same questions about each one.
Put the material being evaluated in a scenario; put simulated respondent characteristics in an Agent.
Keep the question fixed and vary the data
The example asks the same sentiment question about three feedback messages. Each scenario provides the message and a record identifier; the question supplies the shared Positive, Neutral, and Negative categories. It prepares the tasks without generating answers:record_id is retained in results even though it is not inserted into the question text. Use stable identifiers to join predictions with source data and human annotations.
Crossing inputs versus creating question variants
question.by(feedback) asks the same question in separate interviews for each scenario. The answer column remains answer.sentiment, and scenario values identify the input row.
question.loop(feedback) returns separate question objects with scenario values substituted into their text. Placing those questions in a survey creates multiple answer columns in each interview. Choose this when respondents should see several fixed versions within one survey. It is not a substitute for assigning treatments between respondents.
Controlled experiments
Cross scenario conditions with agent profiles and models using successiveby() calls. EDSL runs every combination: two treatments, four profiles, and three models produce 24 interviews per iteration. Human participant assignment is configured separately when publishing the survey.
Use Experimental conditions to retain condition labels and Human studies for scenario assignment in hosted surveys.
Data and files
A scenario can hold extracted text or a complete file. For a complete file, EDSL uses a FileStore to carry its contents. Reference the file’s scenario field in every question that should receive it.
The examples below use local filenames; replace them with your files. Loading them constructs EDSL objects locally. Calling
run() sends the referenced content to your selected model. Use notebook login or provider credentials to configure access.
For attachments, select a model that accepts that media type. Replace MODEL_NAME and SERVICE_NAME with current identifiers from Language models. Model.check_working_models(works_with_images=True) helps find image-capable models; that filter does not establish PDF, video, or audio support.
Images
Create an image scenario, reference itsimage field, and ask a question:
image_name="image" sets the field used in the question. Without it, from_image() uses the filename before its first dot. The filename field above is ordinary metadata retained in the results.
If you already have a FileStore, use Scenario({"image": file}) or file.to_scenario(key_name="image"). This is also how you attach an image retrieved from Expected Parrot or returned by image generation.
PDF attachments
Attach the whole PDF when the question should use its text, charts, images, and layout together. Select a model with PDF input support:PDF text
ScenarioList.from_source("pdf", ...) extracts text into one scenario per page. Each row has filename, page, and text; page numbers start at 1. Text extraction uses PyMuPDF (python -m pip install pymupdf).
Scenario.from_pdf() returns filename and text. These text workflows can use a text model. For scanned pages or questions about visual layout, use a PDF attachment or page images.
PDF page images
Render each PDF page as an image when you want to ask about diagrams, layout, or scanned content page by page. This conversion usespdf2image and its system dependency Poppler.
content. It contains the image data even after the converter’s temporary files are cleaned up. To save a page image yourself, use page_images[0]["content"].write("page-1.jpg").
Scenario.from_pdf_to_image("report.pdf") is an alternative that returns one Scenario with separate attachment fields page_0, page_1, and so on. Reference the particular page fields you want the question to receive, as in the multiple-attachment example.
Video
Use a video file as a scenario input and refer to it in the question. This example uses EDSL’sgoogle service; choose a current model that supports video input and replace GOOGLE_MODEL_NAME:
Audio
Audio uses the same attachment pattern. For example, transcribe an MP3 using a Google model with audio input support:A collection of files
Create one scenario per file to apply the same questions across a collection. For example, reuse the image question and model from Images with a directory of PNGs:file and includes metadata such as file_name and file_path. Renaming file to image matches the field referenced by image_question. Change the pattern and question to work with PDFs, videos, or audio files instead. Use metadata=False if you only want the attachment field.
Multiple attachments in one scenario
Put several files in the same Scenario when the model should compare them in one response. Reference each attachment explicitly:Common methods
This constructs four conditions without running a model:
Clean and transform rows
ScenarioList transformations let you prepare inputs before building a job. The following operates entirely on local data:
For a single Scenario, use
select(), drop(), rename({"old": "new"}), and replace_value("field", value) to transform the mapping. scenario.replicate(n) returns a ScenarioList of copies.
Join, reshape, and summarize
Useleft_join(other, by="record_id"), inner_join(...), or right_join(...) for matching records by a key, rather than times() for all combinations. Check key uniqueness and resulting row counts when joining.
to_agent_list() converts rows to respondent profiles; to_dataset() returns a table. Use to_dicts() for ordinary row dictionaries and to_list() after selecting the fields you need. For pandas, Polars, CSV, and Excel outputs, see table conversions.
scenarios.embed("text", model=embedding_model, cache=embedding_cache) adds vectors for a text field. See text embeddings for model selection, caching, and a local example.