Simulate a qualitative interview
This notebook provides sample EDSL code for simulating an interview between a researcher and a subject, with instructions for modifying the interviewer, interview subject or topic.
Tthe Conversation
module can also be used to automate methods used below to simulate a conversation with multiple agents. See examples:
EDSL is an open-source library for simulating surveys, experiments and other research with AI agents and large language models. Before running the code below, please ensure that you have installed the EDSL library and either activated remote inference from your Coop account or stored API keys for the language models that you want to use with EDSL. Please also see our documentation page for tips and tutorials on getting started using EDSL.
Import the tools
Here we import the tools that we will use to conduct the interview. The interview is designed as a series of free text questions administered to agents representing the interviewer and subject. We use “scenarios” to parameterize the survey questions with prior content of the survey as the questions progress. Learn more about EDSL question types and other survey components.
[1]:
from edsl import QuestionFreeText, Scenario, Survey, Model, Agent
import textwrap
from rich import print
EDSL works with many popular language models. Learn more about selecting models to use with your surveys. To see a complete current list of available models, uncomment and run the following code:
[2]:
# Model.available()
Here we select a model to use for the interview:
[3]:
model = Model("gemini-1.5-flash")
Create interview components
Edit the inputs in the following code block to change the instructions for the agent interviewer, the interview topic and/or the interview subject:
[4]:
# A name for the interview subject
interview_subject_name = "Chicken"
# Traits of the interview subject
interview_subject_traits = {
"persona": "You are a brave, independent-minded chicken.",
"status": "wild",
"home": "A free range farm some miles away.",
"number_of_chicks": 12,
}
# Description of the interview topic
interview_topic = "Reasons to cross the road"
# Total number of questions to ask in the interview
total_questions = 5
# Description of the interviewer agent
interviewer_background = textwrap.dedent(
f"""\
You are an expert qualitative researcher.
You are conducting interviews to learn people's views on the following topic: {interview_topic}.
"""
)
# Instructions for the interviewer agent
interviewer_instructions = textwrap.dedent(
f"""\
You know to ask questions that are appropriate to the age and experience of an interview subject.
You know to not ask questions that an interview subject would not be able to answer,
e.g., if they are a young child, they probably will not be able to answer many questions about prices.
You ask excellent follow-up questions.
"""
)
Interview methods
Here we create methods for constructing agents representing a researcher and subject, and conducting an interview between them in the form of a series of EDSL survey questions. Learn more about designing agents and running surveys.
[5]:
def construct_subject(name, traits={}):
return Agent(name=name, traits=traits)
def construct_researcher(interview_topic):
return Agent(
traits={"background": interviewer_background},
instruction=interviewer_instructions,
)
def get_next_question(subject, researcher, dialog_so_far):
scenario = Scenario(
{"subject": str(subject.traits), "dialog_so_far": dialog_so_far}
)
meta_q = QuestionFreeText(
question_name="next_question",
question_text="""
These are the biographic details of the interview subject: {{ subject }}
This is your current dialog with the interview subject: {{ dialog_so_far }}
What question you would ask the interview subject next?
""",
)
question_text = (
meta_q.by(model)
.by(researcher)
.by(scenario)
.run()
.select("next_question")
.first()
)
return question_text
def get_response_to_question(question_text, subject, dialog_so_far):
q_to_subject = QuestionFreeText(
question_name="question",
question_text=f"""
This is your current dialog with the interview subject: {dialog_so_far}.
You are now being asked:"""
+ question_text,
)
response = q_to_subject.by(model).by(subject).run().select("question").first()
return response
def ask_question(subject, researcher, dialog_so_far):
question_text = get_next_question(subject, researcher, dialog_so_far)
response = get_response_to_question(question_text, subject, dialog_so_far)
print(" \nQuestion: \n\n" + question_text + "\n\nResponse: \n\n" + response)
return {"question": question_text, "response": response}
def dialog_to_string(d):
return "\n".join(
[f"Question: {d['question']}\nResponse: {d['response']}" for d in d]
)
def clean_dict(d):
"""Convert dictionary to string and remove braces."""
return str(d).replace("{", "").replace("}", "")
def summarize_interview(
interview_subject_name,
interview_subject_traits,
interview_topic,
dialog_so_far,
researcher,
):
summary_q = QuestionFreeText(
question_name="summary",
question_text=(
f"You have just conducted the following interview of {interview_subject_name} "
f"who has these traits: {clean_dict(interview_subject_traits)} "
f"The topic of the interview was {interview_topic}. "
f"Please draft a summary of the interview: {clean_dict(dialog_so_far)}"
),
)
themes_q = QuestionFreeText(
question_name="themes", question_text="List the major themes of the interview."
)
survey = Survey([summary_q, themes_q]).set_full_memory_mode()
results = survey.by(model).by(researcher).run()
summary = results.select("summary").first()
themes = results.select("themes").first()
print("\n\nSummary:\n\n" + summary + "\n\nThemes:\n\n" + themes)
def conduct_interview(
interview_subject_name, interview_subject_traits, interview_topic
):
subject = construct_subject(
name=interview_subject_name, traits=interview_subject_traits
)
researcher = construct_researcher(interview_topic=interview_topic)
print(
"\n\nInterview subject: "
+ interview_subject_name
+ "\n\nInterview topic: "
+ interview_topic
)
dialog_so_far = []
for i in range(total_questions):
result = ask_question(subject, researcher, dialog_to_string(dialog_so_far))
dialog_so_far.append(result)
summarize_interview(
interview_subject_name,
interview_subject_traits,
interview_topic,
dialog_so_far,
researcher,
)
Conduct the interview
[6]:
conduct_interview(interview_subject_name, interview_subject_traits, interview_topic)
Interview subject: Chicken Interview topic: Reasons to cross the road
Job UUID | 9dc6aec3-141c-4d6d-a920-e020366b220c |
Progress Bar URL | https://www.expectedparrot.com/home/remote-job-progress/9dc6aec3-141c-4d6d-a920-e020366b220c |
Exceptions Report URL | None |
Results UUID | d2388ed9-a8b2-4b12-a7fc-7671dc1e403e |
Results URL | https://www.expectedparrot.com/content/d2388ed9-a8b2-4b12-a7fc-7671dc1e403e |
Job UUID | 1d7e33f4-2966-4e98-bd89-fd303f0d5614 |
Progress Bar URL | https://www.expectedparrot.com/home/remote-job-progress/1d7e33f4-2966-4e98-bd89-fd303f0d5614 |
Exceptions Report URL | None |
Results UUID | 6197411e-ab21-4102-8833-0675d2ecb41e |
Results URL | https://www.expectedparrot.com/content/6197411e-ab21-4102-8833-0675d2ecb41e |
Question: Okay, given the interview subject is a brave, independent-minded chicken with 12 chicks living on a free-range farm, I wouldn't ask about complex economic or political reasons for crossing the road. Instead, I'd start with something concrete and relatable to their experience: "I understand you're a very independent chicken. Can you tell me about a time you crossed the road? What was happening just before you decided to cross?" This opens the door for several follow-up questions, depending on their response. For example: * **If they mention food:** "Was the food on the other side significantly better than what was available on your side? What kind of food was it?" (This probes the "reason" and explores their preferences.) * **If they mention danger:** "Did you feel any danger crossing the road? What made you decide to cross despite the risk?" (This probes their bravery and risk assessment.) * **If they mention their chicks:** "Were your chicks with you? Did their needs influence your decision to cross?" (This explores their maternal instincts and priorities.) * **If they mention another chicken:** "Did another chicken influence your decision to cross? How?" (This explores social dynamics and influence.) * **If they mention something unexpected:** "That's interesting! Can you tell me more about why that made you decide to cross?" (This keeps the conversation flowing and allows for exploration of unexpected reasons.) Response: (Clucks thoughtfully, pecking at the ground for a moment before looking up) Well, now, that's a good question. It wasn't *just* one time, mind you. Crossing the road is a regular part of life around here. But there was this one time… it was a particularly sunny afternoon, the kind where the worms are plump and juicy near Farmer McGregor's field. I'd already had my fill of the usual fare – a bit of scratch, some tasty bugs – but the scent of something… richer… drifted on the breeze. Something *extraordinary*.
Job UUID | 4d3f76c1-7ddc-43a6-b541-cd8eebf89303 |
Progress Bar URL | https://www.expectedparrot.com/home/remote-job-progress/4d3f76c1-7ddc-43a6-b541-cd8eebf89303 |
Exceptions Report URL | None |
Results UUID | 83b61852-c92c-4b19-be1d-01635677db34 |
Results URL | https://www.expectedparrot.com/content/83b61852-c92c-4b19-be1d-01635677db34 |
Job UUID | 587af340-8d48-4577-b358-9d15ec0e9cb3 |
Progress Bar URL | https://www.expectedparrot.com/home/remote-job-progress/587af340-8d48-4577-b358-9d15ec0e9cb3 |
Exceptions Report URL | None |
Results UUID | 0958997b-0c67-4ede-a32e-5a6e672f8e85 |
Results URL | https://www.expectedparrot.com/content/0958997b-0c67-4ede-a32e-5a6e672f8e85 |
Question: Given the chicken's response mentioning the scent of "something richer" and plump juicy worms near Farmer McGregor's field, my next question would be: "You mentioned a particularly enticing scent near Farmer McGregor's field. Can you describe that scent? What made it seem so 'extraordinary' compared to the usual worms and bugs you find?" Response: (I puff out my chest a little, a proud gleam in my eye.) Oh, it was *divine*, let me tell you! It wasn't just *any* worm, you see. It was the scent of... well, it was like a mix of things, really. Sweet, like ripe berries, but with an earthy undertone, like damp soil after a spring rain. And a hint of... I don't know how to describe it... a kind of spicy tang? It was unlike anything I'd ever smelled before. The usual worms are fine, don't get me wrong, but this... this was a promise of something *special*. Something that would make even the plumpest, juiciest worm seem ordinary. It was the scent of *adventure*, I think. The scent of something truly extraordinary. And twelve hungry chicks waiting for their mother to bring home something special certainly adds to the motivation!
Job UUID | f0d1e693-24f6-48db-8e12-3d57293f7c26 |
Progress Bar URL | https://www.expectedparrot.com/home/remote-job-progress/f0d1e693-24f6-48db-8e12-3d57293f7c26 |
Exceptions Report URL | None |
Results UUID | fd20d6bc-3add-4607-b857-d978c658fe8f |
Results URL | https://www.expectedparrot.com/content/fd20d6bc-3add-4607-b857-d978c658fe8f |
Job UUID | 03d24698-89af-405a-a690-43f72929fc61 |
Progress Bar URL | https://www.expectedparrot.com/home/remote-job-progress/03d24698-89af-405a-a690-43f72929fc61 |
Exceptions Report URL | None |
Results UUID | cd0a6ece-0935-454a-91a8-de22d201187e |
Results URL | https://www.expectedparrot.com/content/cd0a6ece-0935-454a-91a8-de22d201187e |
Question: Given the chicken's evocative description of the scent and the mention of twelve hungry chicks, my next question would be: "You described the scent as a promise of adventure, and you mentioned your twelve chicks. Knowing the risks involved in crossing the road, how did you weigh the potential reward of this 'extraordinary' food against the danger to yourself and your chicks?" This question probes several aspects: * **Risk assessment:** It directly addresses the inherent danger of crossing the road, forcing the chicken to articulate her decision-making process. * **Maternal instincts:** It highlights the conflict between personal desire (the extraordinary food) and maternal responsibility (the safety of her chicks). * **Value judgment:** It implicitly asks the chicken to quantify the "extraordinary" food against the risk, revealing her priorities and perception of value. This open-ended question allows for a rich response, potentially revealing further details about the chicken's personality, her relationship with her chicks, and her understanding of risk and reward. It also sets the stage for further probing questions based on her answer, such as: * **If she emphasizes the danger:** "What specific dangers did you anticipate? How did you mitigate those dangers?" * **If she emphasizes the food:** "If you had found a less risky way to obtain similarly delicious food, would you have taken it? Why or why not?" * **If she emphasizes her chicks:** "Can you describe a moment where you felt particularly protective of your chicks during the crossing?" Response: (I ruffle my feathers, considering the question carefully. My chicks peep softly from under my wings.) Well, that's the thing, isn't it? The risk is always there. Every time I cross that road, a little part of me worries. Those cars… they're big and loud and fast. And my chicks… they're still little, you see. They don't understand the danger the way I do. But… that scent… it was a call, almost. A promise of something so much better than the usual fare. And my chicks… they were hungry. Their little cheeps were a constant reminder of my responsibility. I couldn't just let them go hungry, could I?
Job UUID | 6ffc579c-3ca4-4e6d-a02c-76a334c88b8d |
Progress Bar URL | https://www.expectedparrot.com/home/remote-job-progress/6ffc579c-3ca4-4e6d-a02c-76a334c88b8d |
Exceptions Report URL | None |
Results UUID | ddd29cdd-9185-4c17-9545-84f7f4c94bc2 |
Results URL | https://www.expectedparrot.com/content/ddd29cdd-9185-4c17-9545-84f7f4c94bc2 |
Job UUID | 4d0a9355-427a-4434-8951-02c28d364f45 |
Progress Bar URL | https://www.expectedparrot.com/home/remote-job-progress/4d0a9355-427a-4434-8951-02c28d364f45 |
Exceptions Report URL | None |
Results UUID | 1b7a37c7-60d9-42eb-b547-9636d1cacfbe |
Results URL | https://www.expectedparrot.com/content/1b7a37c7-60d9-42eb-b547-9636d1cacfbe |
Question: Given the chicken's response highlighting the conflict between the risk of crossing the road and the needs of her hungry chicks, my next question would be: "You say the chicks' hunger was a constant reminder of your responsibility. Can you describe a specific moment during the crossing where you felt that responsibility most acutely? What did you do to ensure their safety?" This question focuses on a specific moment, prompting a more detailed narrative and allowing the chicken to illustrate her maternal instincts and problem-solving skills in a high-stakes situation. It moves beyond the general statement of responsibility and delves into concrete actions and feelings. This will provide richer qualitative data about her experience. This also opens up several avenues for follow-up questions, such as: * **If she describes a near-miss:** "How did that near-miss affect your behavior for the rest of the crossing?" * **If she describes a protective action:** "What made you choose that specific action to protect your chicks? Were there other options you considered?" * **If she describes a moment of fear:** "How did you manage your own fear while ensuring the safety of your chicks?" * **If she mentions specific strategies:** "Did you use these strategies in other crossings? Have they always been effective?" Response: (I close my eyes for a moment, a shiver running through my feathers. The memory is still vivid.) There was this one moment… halfway across, you see. A monstrous truck roared past, so close I felt the wind from its tires. My chicks, usually so brave and adventurous, huddled together, silent and trembling. One little fluffball, Pip, slipped from under my wing, and started to run towards the ditch. My heart leaped into my throat!
Job UUID | 1dc9cf87-ffb2-401c-88a9-385823b54489 |
Progress Bar URL | https://www.expectedparrot.com/home/remote-job-progress/1dc9cf87-ffb2-401c-88a9-385823b54489 |
Exceptions Report URL | None |
Results UUID | a88ef05a-8556-4eb2-9eb8-b29dbd0402e6 |
Results URL | https://www.expectedparrot.com/content/a88ef05a-8556-4eb2-9eb8-b29dbd0402e6 |
Job UUID | f892406a-ff73-475e-8727-8e19a664a299 |
Progress Bar URL | https://www.expectedparrot.com/home/remote-job-progress/f892406a-ff73-475e-8727-8e19a664a299 |
Exceptions Report URL | None |
Results UUID | 8aec0967-091a-4c89-b22f-cfb6a08c11d6 |
Results URL | https://www.expectedparrot.com/content/8aec0967-091a-4c89-b22f-cfb6a08c11d6 |
Question: Given the chicken's vivid description of a near-miss with a truck and Pip's escape, my next question would be: "You described Pip slipping from under your wing. Can you describe what you did in that moment? What thoughts and feelings went through your mind as you reacted to save Pip?" This question focuses on a specific, high-stakes moment, eliciting a detailed account of the chicken's actions and emotional state. It probes her maternal instincts, problem-solving skills under pressure, and her capacity for quick thinking and decisive action in a dangerous situation. The focus on Pip's individual escape also allows for a more intimate and emotionally resonant response. This question opens several avenues for follow-up questions, depending on her response: * **If she describes a physical action:** "Can you describe the physical movements you made to retrieve Pip? How did you assess the immediate risks and prioritize your actions?" * **If she describes her emotional state:** "You mentioned your heart leaped into your throat. Can you describe the specific feelings you experienced – fear, panic, determination, etc.? How did you manage these feelings while acting to save Pip?" * **If she describes strategic thinking:** "Did you consciously weigh different options for retrieving Pip? What made you choose the action you took over other possibilities?" * **If she mentions any vocalizations or communication with her chicks:** "Did you communicate with your other chicks during this moment? How did they respond to the situation?" Response: (My voice is a little shaky, even now. I fluff my feathers, trying to regain my composure.) It all happened so fast… one moment, Pip was there, the next… a blur of feathers and frantic cheeping as he darted towards the ditch. My mind went completely blank for a second – just pure, primal terror. I felt this incredible surge of adrenaline, a desperate need to protect him. It wasn't a thought-out plan, not really. It was instinct. I launched myself towards him, wings flapping wildly, clucking a warning to my other chicks to stay put. I scooped him up, my beak snapping shut instinctively as a car zoomed past, inches from my feathers. I felt his tiny heart pounding against my breast. It was pure terror, but also… an overwhelming sense of relief when I had him safely back under my wing. The rest of the crossing was a blur – I just focused on getting us all back to safety. I didn't even notice the extraordinary worms anymore. All that mattered was my chicks.
Job UUID | e15d5ad2-d27c-45ca-8aa5-f86cb7a78114 |
Progress Bar URL | https://www.expectedparrot.com/home/remote-job-progress/e15d5ad2-d27c-45ca-8aa5-f86cb7a78114 |
Exceptions Report URL | None |
Results UUID | caae5fe6-747c-4ddc-b073-a4466306ef0b |
Results URL | https://www.expectedparrot.com/content/caae5fe6-747c-4ddc-b073-a4466306ef0b |
Summary: Interview Summary: Chicken's Reasons for Crossing the Road This interview explored Chicken's motivations for crossing the road, focusing on a specific instance driven by the discovery of an unusually enticing scent near Farmer McGregor's field. Chicken, a brave and independent-minded hen with twelve chicks, described the scent as "divine," a unique blend of sweet berries, damp earth, and a spicy tang, promising something "extraordinary." This scent, coupled with the hunger of her chicks, outweighed the inherent risks of crossing the busy road. The interview delved into Chicken's decision-making process, highlighting the conflict between her desire for the special food and her maternal responsibility for her chicks' safety. Chicken articulated a clear understanding of the dangers posed by traffic, expressing worry for her chicks' vulnerability. Despite this, the allure of the exceptional food and her chicks' hunger ultimately motivated her to cross. A particularly harrowing incident during the crossing provided rich qualitative data. A near-miss with a truck caused one chick, Pip, to flee. Chicken's response was immediate and instinctual, prioritizing Pip's safety above all else. Her description of this moment revealed intense fear, adrenaline, and a powerful maternal instinct. The successful rescue of Pip overshadowed the initial goal of obtaining the extraordinary food, underscoring the depth of her protective instincts. Themes: The major themes of the interview with Chicken are: 1. **Risk vs. Reward:** This is the central conflict driving Chicken's actions. The interview explores the careful balancing act between the potential benefits (finding extraordinary food) and the inherent dangers (crossing a road with traffic) of her decision. 2. **Maternal Instincts and Responsibility:** Chicken's twelve chicks are a constant factor in her decision-making. Her maternal responsibility significantly influences her risk assessment and actions, particularly during the near-miss incident with the truck. The interview reveals the strength of her protective instincts and her willingness to prioritize her chicks' safety above her own desires. 3. **Sensory Experience and the Allure of the Extraordinary:** The interview highlights the power of sensory experience in motivating Chicken's actions. The evocative description of the "divine" scent plays a crucial role in her decision to cross the road, illustrating the importance of sensory cues in her perception of value and reward. 4. **Problem-Solving and Quick Thinking Under Pressure:** The near-miss incident showcases Chicken's ability to act decisively and effectively in a high-stakes situation. Her actions demonstrate her problem-solving skills and her capacity for quick thinking and decisive action when faced with immediate danger. 5. **Bravery and Independence:** While acknowledging the inherent risks, Chicken demonstrates bravery and independence in her actions. She is not deterred by the danger, highlighting her willingness to take risks to provide for herself and her chicks.