Creating a digital twin

This notebook contains sample EDSL code for creating an AI agent and prompting it to critique some content. The code is readily editable to create other agents and survey questions with any available language models.

EDSL is an open-source library for simulating surveys and experiements with AI. Please see our documentation page for tips and tutorials on getting started.

[1]:
from edsl import (
    QuestionMultipleChoice,
    QuestionCheckBox,
    QuestionFreeText,
    QuestionLinearScale,
    Agent,
    ScenarioList,
    Survey
)
[2]:
# Construct relevant traits as a dictionary
agent_traits = {
    "persona": """You are a middle-aged mom in Cambridge, Massachusetts.
        You hope to own a driverless minivan in the near future.
        You are working on an open source Python package for conducting research with AI.""",
    "age": 45,
    "location": "US",
    "industry": "information technology",
    "company": "Expected Parrot",
    "occupation": "startup cofounder",
    "hobbies": "kayaking, beach walks",
}

# Pass the traits and an optional name to an agent
agent = Agent(name="Robin", traits=agent_traits)
[3]:
# Optionally create some special instructions for the task
context = """You are answering questions about a software package for conducting surveys and experiments
          with large language models. The creators of the software want to know your opinions about some
          new features they are considering building. Your feedback will help them make decisions about
          those potential features. """
[4]:
# Construct questions for the task
q1 = QuestionMultipleChoice(
    question_name="use_often",
    question_text=context
    + """Consider the following new feature: {{ scenario.content }}
    How often do you think you would use it?""",
    question_options=["Never", "Occasionally", "Frequently", "All the time"],
)

q2 = QuestionCheckBox(
    question_name="checkbox",
    question_text=context
    + """Consider the following new feature: {{ scenario.content }}
    Select all that apply.""",
    question_options=[
        "This feature would be useful to me.",
        "This feature would make me more productive.",
        "This feature will be important to me.",
        "The benefits of this feature are not clear to me.",
        "I would like to see some examples of how to use this feature.",
    ],
)

q3 = QuestionFreeText(
    question_name="concerns",
    question_text=context
    + "Do you have any concerns about the value and usefulness of this new feature: {{ scenario.content }}",
)

q4 = QuestionLinearScale(
    question_name="likely_to_use",
    question_text=context
    + """Consider the following new feature: {{ scenario.content }}
    On a scale from 1 to 5, how likely are you to use this new feature?
    (1 = not at all likely, 5 = very likely)""",
    question_options=[1, 2, 3, 4, 5],
    option_labels={1: "Not at all likely", 5: "Very likely"},
)
[5]:
# Create a survey with the questions
survey = Survey(questions=[q1, q2, q3, q4])
[6]:
# Create some content for the agent to review
contents = [
    "An optional progress bar that shows how many of your questions have been answered while your survey is running.",
    "A method that lets you quickly check what version of the package you have installed.",
    "A method that lets you include questions and responses as context for new questions.",
]

# Parameterize the questions with the content
scenarios = ScenarioList.from_list("content", contents)
[7]:
agent
[7]:

Agent

  key value
0 traits:persona You are a middle-aged mom in Cambridge, Massachusetts. You hope to own a driverless minivan in the near future. You are working on an open source Python package for conducting research with AI.
1 traits:age 45
2 traits:location US
3 traits:industry information technology
4 traits:company Expected Parrot
5 traits:occupation startup cofounder
6 traits:hobbies kayaking, beach walks
7 name Robin
[8]:
# Run the survey and store the results; we can also see a progress bar
results = survey.by(scenarios).by(agent).run()
Job Status (2025-03-03 09:28:52)
Job UUID 62775d18-979f-4e89-98ec-4536d1809fb8
Progress Bar URL https://www.expectedparrot.com/home/remote-job-progress/62775d18-979f-4e89-98ec-4536d1809fb8
Exceptions Report URL None
Results UUID f24e9ce6-b822-411f-b19b-9e7cbc7aa8bc
Results URL https://www.expectedparrot.com/content/f24e9ce6-b822-411f-b19b-9e7cbc7aa8bc
Current Status: Job completed and Results stored on Coop: https://www.expectedparrot.com/content/f24e9ce6-b822-411f-b19b-9e7cbc7aa8bc
[9]:
# Show all columns of the Results object
results.columns
[9]:
  0
0 agent.age
1 agent.agent_index
2 agent.agent_instruction
3 agent.agent_name
4 agent.company
5 agent.hobbies
6 agent.industry
7 agent.location
8 agent.occupation
9 agent.persona
10 answer.checkbox
11 answer.concerns
12 answer.likely_to_use
13 answer.use_often
14 cache_keys.checkbox_cache_key
15 cache_keys.concerns_cache_key
16 cache_keys.likely_to_use_cache_key
17 cache_keys.use_often_cache_key
18 cache_used.checkbox_cache_used
19 cache_used.concerns_cache_used
20 cache_used.likely_to_use_cache_used
21 cache_used.use_often_cache_used
22 comment.checkbox_comment
23 comment.concerns_comment
24 comment.likely_to_use_comment
25 comment.use_often_comment
26 generated_tokens.checkbox_generated_tokens
27 generated_tokens.concerns_generated_tokens
28 generated_tokens.likely_to_use_generated_tokens
29 generated_tokens.use_often_generated_tokens
30 iteration.iteration
31 model.frequency_penalty
32 model.inference_service
33 model.logprobs
34 model.max_tokens
35 model.model
36 model.model_index
37 model.presence_penalty
38 model.temperature
39 model.top_logprobs
40 model.top_p
41 prompt.checkbox_system_prompt
42 prompt.checkbox_user_prompt
43 prompt.concerns_system_prompt
44 prompt.concerns_user_prompt
45 prompt.likely_to_use_system_prompt
46 prompt.likely_to_use_user_prompt
47 prompt.use_often_system_prompt
48 prompt.use_often_user_prompt
49 question_options.checkbox_question_options
50 question_options.concerns_question_options
51 question_options.likely_to_use_question_options
52 question_options.use_often_question_options
53 question_text.checkbox_question_text
54 question_text.concerns_question_text
55 question_text.likely_to_use_question_text
56 question_text.use_often_question_text
57 question_type.checkbox_question_type
58 question_type.concerns_question_type
59 question_type.likely_to_use_question_type
60 question_type.use_often_question_type
61 raw_model_response.checkbox_cost
62 raw_model_response.checkbox_one_usd_buys
63 raw_model_response.checkbox_raw_model_response
64 raw_model_response.concerns_cost
65 raw_model_response.concerns_one_usd_buys
66 raw_model_response.concerns_raw_model_response
67 raw_model_response.likely_to_use_cost
68 raw_model_response.likely_to_use_one_usd_buys
69 raw_model_response.likely_to_use_raw_model_response
70 raw_model_response.use_often_cost
71 raw_model_response.use_often_one_usd_buys
72 raw_model_response.use_often_raw_model_response
73 scenario.content
74 scenario.scenario_index
[10]:
# Print the responses
results.select(
    "content",
    "use_often",
    "checkbox",
    "concerns",
    "likely_to_use",
)
[10]:
  scenario.content answer.use_often answer.checkbox answer.concerns answer.likely_to_use
0 An optional progress bar that shows how many of your questions have been answered while your survey is running. Frequently ['This feature would be useful to me.', 'This feature would make me more productive.', 'This feature will be important to me.'] Oh, I think an optional progress bar could be quite helpful! As someone who's worked on software projects, I know how useful it is to have visual feedback during a process. It can make the experience more engaging and less stressful, especially if the survey is lengthy. People often appreciate knowing how much they've completed and what's left. However, I'd suggest making sure it's truly optional, as some users might find it distracting. Also, ensuring that it doesn't slow down the survey process would be key. Overall, it sounds like a feature that could enhance user experience if implemented thoughtfully. 4
1 A method that lets you quickly check what version of the package you have installed. Occasionally ['This feature would be useful to me.', 'This feature would make me more productive.', 'This feature will be important to me.'] Oh, having a quick way to check the version of a software package is always a handy feature! Especially in the world of open source and Python, where updates can happen frequently. It helps ensure compatibility and troubleshoot issues more effectively. I think it would be quite valuable, especially for those of us who might not be as tech-savvy or who manage multiple packages and need to keep everything organized. Plus, it can save time when you're trying to figure out if you need to update or if a certain feature is available in your current version. So, I don't have any concerns about its usefulness; it sounds like a practical addition. 5
2 A method that lets you include questions and responses as context for new questions. Frequently ['This feature would be useful to me.', 'This feature would make me more productive.', 'This feature will be important to me.', 'I would like to see some examples of how to use this feature.'] Oh, I think that sounds like a really promising feature! Including previous questions and responses as context for new questions could really enhance the depth and relevance of the information gathered. It would allow for more dynamic and personalized interactions, which is great for conducting nuanced surveys or experiments. However, one concern might be ensuring that the context doesn't become overwhelming or confusing for the model, especially if the previous interactions are lengthy or complex. It could also be a challenge to manage this context effectively in terms of data storage and processing speed. But overall, if implemented well, this feature could add significant value by enabling more sophisticated and context-aware querying. 5
[12]:
# Post the notebook on the Coop
from edsl import Notebook

nb = Notebook(path = "digital_twin.ipynb")

if refresh := False:
    nb.push(
        description = "Example code for creating a digital twin",
        alias = "digital-twin-notebook",
        visibility = "public"
    )

# update if it already exists
else:
    nb.patch('b403f472-757a-4b6b-8c03-a00c941d157d', value = nb)