> ## Documentation Index
> Fetch the complete documentation index at: https://docs.expectedparrot.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Run your first survey

> Construct and run a small EDSL survey, inspect its responses, and extend it to AI or human studies.

This tutorial takes you from a single feedback question to classifying several messages and exporting the answers. You will see how questions, scenarios, models, and results fit together. It begins with a fixed local test response, then shows how to choose a language model for the same workflow.

## Install EDSL

Follow [Installation](https://docs.expectedparrot.com/en/latest/installation.md) for supported Python versions and environment setup:

```bash theme={null}
pip install edsl
```

Run the code in a notebook or Python script. The [CLI Guide](https://docs.expectedparrot.com/en/latest/cli.md) provides an equivalent command line workflow.

## Construct a survey and run a local test

The example asks for a service improvement and uses a test model configured to return a fixed answer. You can run it immediately without an account or model credentials.

```python theme={null}
from edsl import Cache, Model, QuestionFreeText, Survey

question = QuestionFreeText(
    question_name="feedback",
    question_text="What would improve this service?",
)
survey = Survey([question])
model = Model("test", canned_response="Make the export button easier to find.")
job = survey.by(model)
results = job.run(
    cache=Cache(),
    disable_remote_inference=True,
    disable_remote_cache=True,
    progress_bar=False,
)
# In a notebook, leave this as the last expression to display the table.
# In a script: results.select("answer.feedback").print()
# For a Python list: results.select("answer.feedback").to_list()
results.select("answer.feedback")
```

The displayed table contains one `answer.feedback` value: “Make the export button easier to find.”

The `Survey` defines the questions, the `Model` supplies an execution configuration, `by()` creates a job, and `run()` returns a Results object. `select()` extracts a Dataset with the requested answer column. This fixed response tests the workflow; it is not a research observation.

## Vary inputs with scenarios

Replace the single free-text task with a classification question applied to several feedback records. Construction alone makes no model calls:

```python theme={null}
from edsl import QuestionMultipleChoice, Scenario, ScenarioList, Survey

question = QuestionMultipleChoice(
    question_name="sentiment",
    question_text="Classify the sentiment of this feedback: {{ scenario.feedback }}",
    question_options=["Positive", "Neutral", "Negative"],
)
feedback = ScenarioList([
    Scenario({"record_id": "f1", "feedback": "The setup was easy."}),
    Scenario({"record_id": "f2", "feedback": "I couldn't find the export button."}),
    Scenario({"record_id": "f3", "feedback": "It worked as expected."}),
])
job = question.by(feedback)
# by(): one interview per input, with the same answer.sentiment column.
# loop(): three distinct questions in one survey, with the text substituted now.
variants = question.loop(feedback)
variant_survey = Survey(variants)
```

`job` contains three interviews, one for each feedback record. `variant_survey` demonstrates the alternative of constructing multiple distinct questions within one survey; see [Scenarios](https://docs.expectedparrot.com/en/latest/scenarios.md) for when to use each approach.

## Log in to Expected Parrot

To use Expected Parrot's model access from a notebook, run:

```python theme={null}
from edsl import login

login()
```

Follow the sign-in link in the cell output. EDSL retrieves and stores your API key automatically. For login options or direct provider access, see [Model access and API keys](https://docs.expectedparrot.com/en/latest/api_keys.md).

## Choose a language model

Inspect the current model catalog with `Model.available()` or `ep models --text`. Select a model appropriate for the task and review [costs](https://docs.expectedparrot.com/en/latest/costs.md).

Calling `Model()` without a name selects your configured default model. You can inspect its name and parameters:

```python theme={null}
from edsl import Model

model = Model()
{"model": model.model, "parameters": model.parameters}
# In a script, wrap this expression in print() to display it.
```

To choose a specific model instead, pass its name to `Model()` and its provider's service name as `service_name`. Replace both placeholders below with the corresponding identifiers from the catalog:

```python theme={null}
model = Model("MODEL_NAME", service_name="SERVICE_NAME")
```

Model names and availability change, so use the current catalog values. You can also pass parameters supported by your chosen model as keyword arguments; see [Language models](https://docs.expectedparrot.com/en/latest/language_models.md) for configuration details.

Once you have chosen either the default or a specific model, apply it to the job and run the survey. This makes model calls and may incur usage costs:

```python theme={null}
results = job.by(model).run()
```

Expected output is three completed interview records, each with an `answer.sentiment` value from the allowed options. Actual labels depend on the model and inputs; inspect errors and completion counts before analysis.

## Inspect and export responses

```python theme={null}
table = results.select("scenario.record_id", "scenario.feedback", "answer.sentiment")
# Display in a notebook: put table on the last line of a cell.
# Display in a script: table.print()
# Convert to pandas when you need DataFrame operations.
frame = table.to_pandas()
table.to_csv("feedback_labels.csv")
```

Keep the record identifier beside each answer so you can join classifications to source data or human labels. See [Results](https://docs.expectedparrot.com/en/latest/results.md) and [Dataset](https://docs.expectedparrot.com/en/latest/dataset.md) for filtering, comparison, and export.

## Extend the study

* [Survey logic and piping](https://docs.expectedparrot.com/en/latest/guides/survey_logic.md): branch on answers and supply previous responses as context.
* [Creating and varying agents](https://docs.expectedparrot.com/en/latest/agents.md): specify controlled respondent profiles.
* [Model comparisons](https://docs.expectedparrot.com/en/latest/guides/model_comparisons.md): apply different models to matched inputs.
* [Human studies](https://docs.expectedparrot.com/en/latest/guides/human_studies.md): publish a survey and collect responses from people.
* [Saving and sharing objects](https://docs.expectedparrot.com/en/latest/guides/saving_objects.md): preserve a reusable study specification and outputs.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.