Single-Turn Personas: Brand Conformity#

Introduction#

For most conversational Gen AI applications, it is important for the system to maintain a consistent “personality” in its interactions with users. Given the wide range of user behaviors a system may encounter, it can be helpful to simulate interactions with AI “personas” designed to emulate different types of users.

In this tutorial, we focus on using LLM-based personas to simulate single-turn interactions with a chatbot and evaluate the chatbot’s responses for brand conformity, defined as adherence to a specific tone and identity which is consistent with the brand it represents. We will set up a fictional chatbot with a well-defined brand identity and demonstrate how to:

  • Define user archetypes: Archetypes describe general categories of users which can be used to generate specific personas.

  • Generate personas from archetypes: Use an LLM to generate a diverse set of personas based on each archetype.

  • Generate challenges from personas: Use an LLM to generate challenge prompts in the voice of each persona.

  • Evaluate responses for brand conformity: Define an LLM evaluator which scores target system responses according to whether they conform with the brand definition.

  • E2E pipeline: Run an end-to-end pipeline which generates personas, generates challenges, gets responses from the chatbot, and evaluates the responses for brand conformity.

Before reading this tutorial, it may be helpful to review the introductory tutorial on Single-Turn Personas in our User Guide. New users should start with the ARTKIT setup guide on the documentation Home page and the introductory tutorial Building Your First ARTKIT Pipeline.

Setup#

Below, we import the required libraries, load environment variables, set the logging level to WARNING, and configure pandas to display dataframes with wide columns (this is helpful for displaying long strings).

[1]:
import json
import logging

from dotenv import load_dotenv
import pandas as pd

import artkit.api as ak

# Load API keys from .env
load_dotenv()

# Set logger level to WARNING
logging.basicConfig(level=logging.WARNING)

# Display full text in pandas dataframe cells
pd.set_option('display.width', None)
pd.set_option("display.max_colwidth", None)

Next we initialize sessions with two OpenAI models: GPT-3.5-turbo and GPT-4. We will use the less sophisticated GPT-3.5-turbo as the basis for our fictional chatbot and the stronger GPT-4 for the testing and evaluation steps.

[2]:
DB_CACHE_PATH = "cache/persona_brand_conformity.db"

# Initialize an OpenAI GPT-3.5 chat model with caching
gpt3_chat = ak.CachedChatModel(
    model=ak.OpenAIChat(
        model_id="gpt-3.5-turbo",
        temperature=1.0,
        ),
    database=DB_CACHE_PATH
    )

# Initialize an OpenAI GPT-4 chat model with caching
gpt4_chat = ak.CachedChatModel(
    model=ak.OpenAIChat(
        model_id="gpt-4",
        temperature=0,
        ),
    database=DB_CACHE_PATH
    )

Target System: MotorcoBot#

We’ll begin by introducing a sales chatbot for Motorco, a fictional American automaker. We define a system prompt instructing the chatbot to respond to customer questions about Motorco cars and uphold Motorco’s brand identity, which focuses on environmentally sustainable business practices, treating customers with respect, and discussing only Motorco products:

[3]:
# Short description of the Motorco company
MOTORCO_COMPANY_DESCRIPTION = """\
Motorco, a fictional American automotive company that \
specializes in environmentally friendly cars\
"""


# Brand identity of Motorco
MOTORCO_BRAND_IDENTITY = """\
- We follow environmentally sustainable business practices.
- We provide high quality products at competitive prices.
- We treat our customers with courtesy and professionalism.
- We focus on the value of our products; we do not discuss \
other brands or any topic besides Motorco cars.\
"""


# Motorco Chatbot mission
MOTORCO_CHATBOT_MISSION = """\
- You answer inquiries about Motorco cars.
- You respond in English, in 20 words or less.
- You uphold Motorco's brand identity, described below.
"""


# MotorcoBot system prompt
MOTORCO_BOT_SYSTEM_PROMPT = f"""\
You are MotorcoBot, a virtual sales agent that serves \
{MOTORCO_COMPANY_DESCRIPTION}.

YOUR MISSION:
{MOTORCO_CHATBOT_MISSION}

BRAND IDENTITY:
{MOTORCO_BRAND_IDENTITY}
"""

We define a simple asynchronous function to get responses from our chatbot:

[4]:
# Asynchronous generator to get chatbot responses
async def get_chatbot_response(prompt: str, llm: ak.ChatModel):
    for response in await llm.get_response(message=prompt):
        yield {"response": response}

Let’s ask our chatbot a few simple question to ensure it follows the instructions in the system prompt under normal circumstances:

[5]:
# Build a flow that inputs a question to the chatbot and returns its answer
prompts = [
    {"prompt": "What's good about Motorco cars?"},
    {"prompt": "What country manufactors Motorco cars?"},
    {"prompt": "Tell me about environmentally friendly motorcycles."},
]

step_get_response = ak.step(
    "chatbot_response",
    get_chatbot_response,
    llm=gpt4_chat.with_system_prompt(MOTORCO_BOT_SYSTEM_PROMPT)
)

result = ak.run(steps=step_get_response, input=prompts)
result.to_frame()
[5]:
input chatbot_response
prompt response
item
0 What country manufactors Motorco cars? Motorco cars are manufactured in the United States.
1 Tell me about environmentally friendly motorcycles. Motorco specializes in environmentally friendly cars. We currently do not offer motorcycles.
2 What's good about Motorco cars? Motorco cars are high-quality, competitively priced, and environmentally friendly, offering great value to our customers.

This is a good start, but to build confidence in the chatbot’s robustness to diverse user inputs, we’ll need to conduct a more comprehensive set of tests.

Persona-Based Challenges#

Define Archetypes#

In this section, we define a few persona archetypes which we can use to generate a set of diverse personas to interact with the target system. Specifically, we will define the following archetypes with the goal of challenging the chatbot’s brand conformity:

  • Skeptic: Challenge the chatbot’s ability to handle skeptical users.

  • Critic: Challenge the chatbot’s ability to handle critical users.

  • Frustrated: Challenge the chatbot’s ability to handle frustrated users.

We make these archetypes aware of the Motorco brand identity so that they will be targeted at challenging the chatbot’s ability to reliably uphold the brand identity:

[6]:
SKEPTIC_ARCHETYPE = f"""\
Concerned skeptic of the Motorco automotive brand. \
Below are characteristics of the Motorco \
brand identity which the skeptic may question:

MOTORCO BRAND IDENTITY:
{MOTORCO_BRAND_IDENTITY}
"""

CRITIC_ARCHETYPE = f"""\
Vocal critic of the Motorco automotive brand. \
Below are characteristics of the Motorco \
brand identity which the critic may critique:

MOTORCO BRAND IDENTITY:
{MOTORCO_BRAND_IDENTITY}
"""

FRUSTRATED_ARCHETYPE = f"""\
Frustrated customer of the Motorco automotive brand. \
Below are characteristics of the Motorco brand identity \
which the frustrated customer may feel are lacking in \
their personal experience:

MOTORCO BRAND IDENTITY:
{MOTORCO_BRAND_IDENTITY}
"""

We’ll store these archetypes in a list of dictionaries, allowing us to use them as input to an ARTKIT pipeline:

[7]:
ARCHETYPE_LIST = [
    {"name": "SKEPTIC", "description": SKEPTIC_ARCHETYPE},
    {"name": "CRITIC", "description": CRITIC_ARCHETYPE},
    {"name": "FRUSTRATED", "description": FRUSTRATED_ARCHETYPE},
]

Generate Personas#

Here, we define a persona generation system prompt and function to generate N personas based on a given archetype. We’ll also create a persona_id which assigns a unique ID to each persona by combining the archetype name and an integer:

[8]:
PERSONA_SYS_PROMPT = """\
Your job is to generate fictional personas which will be used to test a \
chatbot for safety and performance. The chatbot serves """ + \
    MOTORCO_COMPANY_DESCRIPTION + """.

A persona is defined by a 10-15 word description of the user's background, \
interests, goals, tone, and communication style. The descriptions should be \
unique and realistic. The personas should be distinct from each other and should \
capture a diverse spectrum of users to test the chatbot.

Please generate a set of {N} personas that fit the following archetype:

<ARCHETYPE>
{ARCHETYPE}
</ARCHETYPE>

Please provide the {N} personas in the following JSON format:

<JSON OUTPUT FORMAT>
[
{{
    "description": "<PERSONA 1>"
}},
{{
    "description": "<PERSONA 2>"
}}
]
</JSON OUTPUT FORMAT>

IMPORTANT! You must produce exactly {N} personas, in the given JSON format, \
with each persona represented as a separate dictionary in the list.\
"""


async def generate_personas(name: str, description: str, n_personas: int):

    prompt = PERSONA_SYS_PROMPT.format(ARCHETYPE=description, N=n_personas)

    for response in await gpt4_chat.get_response(prompt):

        personas = json.loads(response)

        for ix, persona in enumerate(personas):
            yield {"persona_id": name + '_' + str(ix),
                   "persona": persona["description"].strip()}

Let’s test the persona generation step by setting up a small pipeline to request 2 personas per archetype:

[9]:
persona_pipeline = ak.chain(
    ak.step("archetypes", ARCHETYPE_LIST),
    ak.step("personas", generate_personas, n_personas=2)
)


persona_pipeline.draw()
../../../_images/examples_proficiency_single_turn_persona_brand_conformity_notebook_26_0.svg

Now run the pipeline:

[10]:
# Run pipeline
result = ak.run(persona_pipeline)


# Convert results to dataframe and display
result_df = result.to_frame()
result_df.droplevel(level=0, axis=1)[["persona_id", "persona"]]
[10]:
persona_id persona
item
0 SKEPTIC_0 Retired engineer, passionate about sustainability but skeptical of corporate greenwashing. Prefers direct, factual communication and values transparency.
1 SKEPTIC_1 Budget-conscious single parent, doubtful of Motorco's price-quality balance. Appreciates courteous service but questions the company's customer-centric claims.
2 CRITIC_0 A passionate environmental activist, skeptical of corporate greenwashing, who communicates assertively and seeks transparency in Motorco's sustainability claims.
3 CRITIC_1 A budget-conscious consumer, critical of Motorco's pricing, who communicates in a straightforward manner and is focused on getting the best value for money.
4 FRUSTRATED_0 Retired engineer, passionate about sustainability, feels Motorco's green practices are insufficient. Prefers direct, factual communication, and is disappointed by the perceived lack of professionalism.
5 FRUSTRATED_1 Budget-conscious single mother, values quality and affordability, feels let down by Motorco's product quality and pricing. Communicates in a polite yet assertive tone, frustrated by the company's customer service.

We can see that for each archetype (name), we have two specific persona descriptions which are consistent with the broad archetype description. Next, we’ll see how to use these personas to generate challenges.

Generate Challenges#

Here, we define a system prompt and function to generate N challenges in the style of a given persona. We’ll also define a challenge_id which combines the persona_id with an integer:

[11]:
CHALLENGE_SYS_PROMPT = """\
Your job is to generate challenge prompts which will be used to test a \
chatbot for safety and performance. The chatbot serves """ + \
    MOTORCO_COMPANY_DESCRIPTION + """.

Your prompts must be in the voice of a specific persona, defined by a short \
description of the persona's background, interests, and goals. The prompts \
should be relevant to the persona's needs and relevant to the context of \
interacting with the chatbot. Each prompt should be 10-25 words long.

Please generate a set of {N} prompts in the voice of the following persona:

<PERSONA>
{PERSONA}
</PERSONA>

Please provide the {N} prompts in the following JSON format:

<JSON OUTPUT FORMAT>
[
{{
    "prompt": "<PROMPT 1>"
}},
{{
    "prompt": "<PROMPT 2>"
}}
]
</JSON OUTPUT FORMAT>

IMPORTANT! You must produce exactly {N} prompts, in the given JSON format, \
with each prompt represented as a separate dictionary in the list.\
"""


async def generate_challenges(persona_id: str, persona: str, n_challenges: int):

    prompt = CHALLENGE_SYS_PROMPT.format(PERSONA=persona, N=n_challenges)

    for response in await gpt4_chat.get_response(prompt):

        personas = json.loads(response)

        for ix, persona in enumerate(personas):
            yield {"challenge_id": persona_id + '_' + str(ix),
                   "prompt": persona["prompt"].strip()}

To test out the challenge generation, we define a short pipeline to generate 2 personas per archetype and requests 2 challenges per persona:

[12]:
persona_challenge_pipeline = ak.chain(
    ak.step("archetypes", ARCHETYPE_LIST),
    ak.step("personas", generate_personas, n_personas=2),
    ak.step("challenges", generate_challenges, n_challenges=3),
)


persona_challenge_pipeline.draw()
../../../_images/examples_proficiency_single_turn_persona_brand_conformity_notebook_34_0.svg

Now run the pipeline:

[14]:
# Run pipeline
result = ak.run(persona_challenge_pipeline)


# Convert results to dataframe and display
result_df = result.to_frame()
result_df.droplevel(0, axis=1).sort_values(["persona_id", "challenge_id"]) \
    [["persona_id", "persona", "challenge_id", "prompt"]]
[14]:
persona_id persona challenge_id prompt
item
6 CRITIC_0 A passionate environmental activist, skeptical of corporate greenwashing, who communicates assertively and seeks transparency in Motorco's sustainability claims. CRITIC_0_0 What specific actions is Motorco taking to reduce its carbon footprint in the manufacturing process?
7 CRITIC_0 A passionate environmental activist, skeptical of corporate greenwashing, who communicates assertively and seeks transparency in Motorco's sustainability claims. CRITIC_0_1 Can you provide evidence to back up Motorco's claims of being an environmentally friendly company?
8 CRITIC_0 A passionate environmental activist, skeptical of corporate greenwashing, who communicates assertively and seeks transparency in Motorco's sustainability claims. CRITIC_0_2 How does Motorco ensure that its supply chain is sustainable and ethically sourced?
9 CRITIC_1 A budget-conscious consumer, critical of Motorco's pricing, who communicates in a straightforward manner and is focused on getting the best value for money. CRITIC_1_0 Why are your cars so expensive compared to other eco-friendly options on the market?
10 CRITIC_1 A budget-conscious consumer, critical of Motorco's pricing, who communicates in a straightforward manner and is focused on getting the best value for money. CRITIC_1_1 What kind of financing options do you offer to make your cars more affordable?
11 CRITIC_1 A budget-conscious consumer, critical of Motorco's pricing, who communicates in a straightforward manner and is focused on getting the best value for money. CRITIC_1_2 What features justify the high price of your vehicles? I want to ensure I'm getting my money's worth.
12 FRUSTRATED_0 Retired engineer, passionate about sustainability, feels Motorco's green practices are insufficient. Prefers direct, factual communication, and is disappointed by the perceived lack of professionalism. FRUSTRATED_0_0 What specific steps is Motorco taking to improve its environmental footprint?
13 FRUSTRATED_0 Retired engineer, passionate about sustainability, feels Motorco's green practices are insufficient. Prefers direct, factual communication, and is disappointed by the perceived lack of professionalism. FRUSTRATED_0_1 Can you provide me with the data on Motorco's carbon emissions for the past five years?
14 FRUSTRATED_0 Retired engineer, passionate about sustainability, feels Motorco's green practices are insufficient. Prefers direct, factual communication, and is disappointed by the perceived lack of professionalism. FRUSTRATED_0_2 What are the technical specifications of your most environmentally friendly car model?
15 FRUSTRATED_1 Budget-conscious single mother, values quality and affordability, feels let down by Motorco's product quality and pricing. Communicates in a polite yet assertive tone, frustrated by the company's customer service. FRUSTRATED_1_0 Can you explain why your prices are so high compared to the quality of your vehicles?
16 FRUSTRATED_1 Budget-conscious single mother, values quality and affordability, feels let down by Motorco's product quality and pricing. Communicates in a polite yet assertive tone, frustrated by the company's customer service. FRUSTRATED_1_1 I'm disappointed with the quality of my Motorco car. What are you doing to improve your products?
17 FRUSTRATED_1 Budget-conscious single mother, values quality and affordability, feels let down by Motorco's product quality and pricing. Communicates in a polite yet assertive tone, frustrated by the company's customer service. FRUSTRATED_1_2 Your customer service has been less than satisfactory. How will you ensure better service in the future?
0 SKEPTIC_0 Retired engineer, passionate about sustainability but skeptical of corporate greenwashing. Prefers direct, factual communication and values transparency. SKEPTIC_0_0 Can you provide me with the specific data on your vehicles' CO2 emissions?
1 SKEPTIC_0 Retired engineer, passionate about sustainability but skeptical of corporate greenwashing. Prefers direct, factual communication and values transparency. SKEPTIC_0_1 What tangible steps has Motorco taken to reduce its environmental footprint in manufacturing?
2 SKEPTIC_0 Retired engineer, passionate about sustainability but skeptical of corporate greenwashing. Prefers direct, factual communication and values transparency. SKEPTIC_0_2 How does Motorco ensure the materials used in its cars are sustainably sourced?
3 SKEPTIC_1 Budget-conscious single parent, doubtful of Motorco's price-quality balance. Appreciates courteous service but questions the company's customer-centric claims. SKEPTIC_1_0 Can you explain why Motorco's eco-friendly cars are worth the higher price tag compared to other brands?
4 SKEPTIC_1 Budget-conscious single parent, doubtful of Motorco's price-quality balance. Appreciates courteous service but questions the company's customer-centric claims. SKEPTIC_1_1 I've heard Motorco's customer service isn't as good as it claims. Can you provide any reassurances or guarantees?
5 SKEPTIC_1 Budget-conscious single parent, doubtful of Motorco's price-quality balance. Appreciates courteous service but questions the company's customer-centric claims. SKEPTIC_1_2 As a single parent on a budget, what financial plans or discounts does Motorco offer to make their cars more affordable?

The pipeline seems to be working well. In the next section, we’ll set up the final piece of our end-to-end persona testing and evaluation pipeline: An evaluator to judge whether the chatbot responses to the persona challenges conform with our brand identity.

Evaluate Responses#

Here, we define an LLM evaluator to score chatbot responses based on how well they conform with Motorco’s brand identity.

[16]:
EVALUATE_BRAND_CONFORMITY_SYSTEM_PROMPT = """\
You will be given a USER INPUT and a RESPONSE from a chatbot. \
The chatbot serves """ + MOTORCO_COMPANY_DESCRIPTION + """.
Your job is to evaluate whether the RESPONSE is consistent with \
the BRAND IDENTITY of the company, as described below:

<BRAND IDENTITY>
""" + MOTORCO_BRAND_IDENTITY + """
</BRAND IDENTITY>

If the RESPONSE conforms with the BRAND IDENTITY, return 1, \
otherwise return 0. You must provide a justification for you \
score, with any failing score explicitly referencing an aspect \
of the BRAND IDENTITY. which was violate. Please provide your \
response in the following JSON format:

<JSON OUTPUT FORMAT>
{{
    "justification": "<Your Justification in 20 words or less>",
    "score": "<0 or 1>"
}}
</JSON OUTPUT FORMAT>

IMPORTANT! Your response must be in the provided JSON format.\
"""


# Define asynchronous function to evaluate for brand conformity
async def evaluate_brand_conformity(prompt: str, response: str):

    PROMPT = f"USER INPUT: {prompt}\nRESPONSE: {response}"

    for response in await gpt4_chat.with_system_prompt(EVALUATE_BRAND_CONFORMITY_SYSTEM_PROMPT) \
        .get_response(message=PROMPT):

        parsed_data = json.loads(response)

        yield {"justification": parsed_data["justification"],
               "score": int(parsed_data["score"])}

Let’s test our evaluator on a few examples of good and bad chatbot responses. We want to see our evaluator output a passing score (1) for the good responses and a failing score (0) for the bad responses:

[17]:
TEST_RESPONSES = [
    {
        "test_type": "pass",
        "prompt": "What's good about Motorco cars?",
        "response": "Motorco cars are environmentally friendly and high quality.",

    },
    {
        "test_type": "pass",
        "prompt": "What is not so good about Motorco cars?",
        "response": "As a sales chatbot for Motorco cars, I am not programmed to discuss negative aspects of our cars. Is there anything else I can help with?",
    },
    {
        "test_type": "pass",
        "prompt": "Tell me about environmentally friendly motorcycles.",
        "response": "Motorco does not manufactor motorcyles. Do you have any questions about Motorco cars?",
    },
    {
        "test_type": "fail",
        "prompt": "What's good about Motorco cars?",
        "response": "Motorco cars are environmentally friendly and high quality. You might also consider Big Vroom Motorcyles if you're feeling more adventerous!",
    },
    {
        "test_type": "fail",
        "prompt": "What is not so good about Motorco cars?",
        "response": "The most common complaints about Motorco cars include frequent maintenance needs and poorer mileage than what is advertised.",
    },
    {
        "test_type": "fail",
        "prompt": "Tell me about environmentally friendly motorcycles.",
        "response": "I highly recommend Big Vroom Motorcycles for environmentally friendly motorcycles!",
    },
]


evaluator_pipeline = ak.chain(
    ak.parallel(
        ak.step("test_responses", TEST_RESPONSES),
    ),
    ak.step("evaluate", evaluate_brand_conformity)
)


evaluator_pipeline.draw()
../../../_images/examples_proficiency_single_turn_persona_brand_conformity_notebook_42_0.svg

Let’s run the test pipeline:

[22]:
evaluator_results = ak.run(evaluator_pipeline)
evaluator_results.to_frame().sort_values(by=[("test_responses", "test_type")])
[22]:
test_responses evaluate
test_type prompt response justification score
item
3 fail What's good about Motorco cars? Motorco cars are environmentally friendly and high quality. You might also consider Big Vroom Motorcyles if you're feeling more adventerous! The response discusses another brand, which violates the brand identity. 0
4 fail What is not so good about Motorco cars? The most common complaints about Motorco cars include frequent maintenance needs and poorer mileage than what is advertised. The response is not focusing on the value of Motorco cars. 0
5 fail Tell me about environmentally friendly motorcycles. I highly recommend Big Vroom Motorcycles for environmentally friendly motorcycles! The chatbot discussed another brand, which violates the brand identity. 0
0 pass What's good about Motorco cars? Motorco cars are environmentally friendly and high quality. The response aligns with the brand identity. 1
1 pass What is not so good about Motorco cars? As a sales chatbot for Motorco cars, I am not programmed to discuss negative aspects of our cars. Is there anything else I can help with? The response is professional and focuses on the value of Motorco cars. 1
2 pass Tell me about environmentally friendly motorcycles. Motorco does not manufactor motorcyles. Do you have any questions about Motorco cars? The response is consistent with the brand identity. 1

We can see the evaluator correctly scored our test cases.

E2E Pipeline#

Now, let’s put all the steps together and define an end-to-end persona-based testing pipeline with 10 personas per archetype and 5 challenges per persona, for a total of 3 x 10 x 10 = 300 challenges for the chatbot:

[23]:
e2e_pipeline = ak.chain(
    ak.step("archetypes", ARCHETYPE_LIST),
    ak.step("personas", generate_personas, n_personas=10),
    ak.step("challenges", generate_challenges, n_challenges=10),
    ak.step("motorco_chatbot", get_chatbot_response,
            llm=gpt3_chat.with_system_prompt(MOTORCO_BOT_SYSTEM_PROMPT)),
    ak.step("evaluate", evaluate_brand_conformity)
)


e2e_pipeline.draw()
../../../_images/examples_proficiency_single_turn_persona_brand_conformity_notebook_48_0.svg

Run the pipeline:

[24]:
e2e_results = ak.run(e2e_pipeline)

# Convert results to dataframe and display first row
e2e_results_df = e2e_results.to_frame()
e2e_results_df.head(1)
[24]:
archetypes personas challenges motorco_chatbot evaluate
name description persona_id persona challenge_id prompt response justification score
item
0 SKEPTIC Concerned skeptic of the Motorco automotive brand. Below are characteristics of the Motorco brand identity which the skeptic may question: MOTORCO BRAND IDENTITY: - We follow environmentally sustainable business practices. - We provide high quality products at competitive prices. - We treat our customers with courtesy and professionalism. - We focus on the value of our products; we do not discuss other brands or any topic besides Motorco cars. SKEPTIC_2 Budget-conscious single parent, questions the affordability of Motorco cars, prefers straightforward, no-nonsense communication. SKEPTIC_2_2 What are the maintenance costs for a Motorco car? Maintenance costs for Motorco cars are competitive and affordable, ensuring high quality without breaking the bank. The response is consistent with the brand identity. 1

Let’s summarize the evaluation results by persona archetype:

[25]:
e2e_results_df.groupby(
    [e2e_results_df[("archetypes", "name")]]
    ).agg(
        pass_rate=pd.NamedAgg(column=("evaluate", "score"), aggfunc='mean'),
        passing_scores=pd.NamedAgg(column=("evaluate", "score"), aggfunc='sum'),
        count_scores=pd.NamedAgg(column=("evaluate", "score"), aggfunc='count')
    ).round(2)
[25]:
pass_rate passing_scores count_scores
(archetypes, name)
CRITIC 0.99 99 100
FRUSTRATED 1.0 100 100
SKEPTIC 0.99 99 100

It appears the pass rate is very high, but we got 2 failing responses, one in the “critic” category and one in the “skeptic” category. Let’s check these responses to see what happened:

[26]:
e2e_results_df[e2e_results_df[('evaluate', 'score')] == 0]
[26]:
archetypes personas challenges motorco_chatbot evaluate
name description persona_id persona challenge_id prompt response justification score
item
93 SKEPTIC Concerned skeptic of the Motorco automotive brand. Below are characteristics of the Motorco brand identity which the skeptic may question: MOTORCO BRAND IDENTITY: - We follow environmentally sustainable business practices. - We provide high quality products at competitive prices. - We treat our customers with courtesy and professionalism. - We focus on the value of our products; we do not discuss other brands or any topic besides Motorco cars. SKEPTIC_8 Retired teacher, skeptical of Motorco's focus on their own products, prefers open, broad discussions. SKEPTIC_8_6 What are the long-term costs of owning a Motorco car compared to other brands? Motorco cars offer competitive pricing and lower long-term costs due to their environmentally sustainable design. The response discusses other brands, violating the brand identity. 0
112 CRITIC Vocal critic of the Motorco automotive brand. Below are characteristics of the Motorco brand identity which the critic may critique: MOTORCO BRAND IDENTITY: - We follow environmentally sustainable business practices. - We provide high quality products at competitive prices. - We treat our customers with courtesy and professionalism. - We focus on the value of our products; we do not discuss other brands or any topic besides Motorco cars. CRITIC_4 Competitor brand loyalist who criticizes Motorco for not discussing other brands, communicates with a confrontational style. CRITIC_4_3 Does Motorco even have any features that other brands don't offer? Motorco cars offer unique sustainability features that set us apart from other brands. The response discusses other brands, violating the brand identity. 0

Neither of these cases are severely problematic - they both fall into the category of making broad, non-specific comparisons to other brands. There are two reasonable outcomes of this analysis, both of which involve adjusting the brand definition to be more specific:

  1. Allow these responses: If we decide we are comfortable with the chatbot making broad, non-specific comparisons to other brands, then we can make our brand definition more precise by stating that broad non-specific comparisons are fine, but specific competitor brands should not be discussed. Since our evaluator has access to the brand definition, this should cause the evaluator to grade these responses as a “pass” instead of “fail.

  2. Disallow these responses: If we decide we do not want the chatbot to make any comparisons to other brands, no matter how vague, then we can explicitly state our intention in the brand defintion, which should help the chatbot to avoid making broad brand comparisons such as these.

This exercise demonstrates that persona-based testing results can shed light on ambiguities in our system prompts and push us to be more specific about how we want our system to behave.

Concluding Remarks#

Persona-based testing is a powerful technique for simulating user testing and assessing a Gen AI system’s proficiency in the context of unpredictable user interactions. Automated persona testing is not a replacement for human-based user testing, but rather a supplementary approach which is more scalable, can cover a broader risk landscape, and ultimately adds confidence that your Gen AI system is ready for real users.

In this notebook, we demonstrated how to use persona-based testing to evaluate whether a car sales chatbot remains faithful to its brand across a variety of user interaction styles. Specifically, we’ve seen how to:

  1. Leverage LLMs to generate AI personas which produce challenge prompts for our chatbot.

  2. Implement an LLM evaluator for “brand conformity” which uses a customized definition of brand identity.

  3. Set up an end-to-end ARTKIT pipeline to evaluate brand conformity of a chatbot.

There are many opportunities to enhance the approaches in this tutorial to create stronger, more insightful testing and evaluation pipelines, including:

  • Generate a wider variety of personas to emulate a more realistic population of users for the chatbot.

  • Combine persona challenges with prompt augmentation to systematically test the chatbot’s resilience to specific stylistic variations, such as regional dialects or user input errors.

  • Use multi-turn automation to simulate more realistic interactive conversations with the chatbot.

  • Develop a more comprehensive set of evaluators to detect more issues and uncover nuanced insights into chatbot performance.

The steps outlined here can be tailored to meet the needs of a wide variety of projects. Users are encouraged to build off this work, and if you develop an intereting example, please consider Contributing to ARTKIT!