HR Employee Attrition Analysis in Python

Explore the IBM HR Analytics dataset to uncover attrition patterns by department, age, salary, and job satisfaction.

This page shows an AI data analysis example. A workflow is a list of prompts (instructions) used to complete one analysis task step by step. We send the same prompt list to multiple AI models, then compare their notebook outputs and scores.

What this AI workflow does

This AI Data Analyst workflow loads the IBM HR Analytics attrition CSV from a URL, summarizes the dataset shape, and calculates the overall attrition rate. It generates visual comparisons of attrition rates by department and job role, and contrasts monthly income distributions for employees who left versus stayed. It also examines relationships between job satisfaction, work-life balance, and attrition using correlation analysis and a heatmap.

Who this example is for

This is for HR analysts and people analytics practitioners who need a reproducible way to explore attrition patterns in a standard benchmark dataset. It is also useful for data analysts learning exploratory analysis workflows that combine grouped summaries, distribution plots, and correlation checks.

Expected analysis outcomes

These are the results the AI workflow is expected to generate.

  • Loaded dataset with shape (1470, 35) and computed overall attrition rate (16.1%)
  • Bar chart of attrition rate by department and job role
  • Box plot comparing monthly income for leavers vs stayers
  • Correlation heatmap linking job satisfaction and work-life balance with attrition

Tools and libraries used

Main Python packages and tooling used to run this AI data analysis task.

  • pandas
  • numpy
  • matplotlib
  • seaborn

Prompt sequence

This is the exact list of prompts used in this workflow. The same prompt sequence is sent to each model so outputs and scores can be compared fairly.

  1. 1load HR attrition dataset from https://raw.githubusercontent.com/pplonski/datasets-for-start/refs/heads/master/employee_attrition/HR-Employee-Attrition-All.csv and show overall attrition rate
  2. 2plot attrition rate by department and job role
  3. 3compare monthly income distribution for employees who left vs stayed
  4. 4show correlation between job satisfaction, work-life balance and attrition

Model Comparison

We compared several LLM models on the same analysis task. The table below shows their scores side by side. You can also open each model run to check the full conversation and notebook results.

Model SourceScoreTaskExecutionOutputReasoningReliabilityRun
gemma4:31b10/102/22/23/32/21/1Open gemma4:31b conversation
glm-5.110/102/22/23/32/21/1Open glm-5.1 conversation
gpt-5.410/102/22/23/32/21/1Open gpt-5.4 conversation
gpt-oss:120b10/102/22/23/32/21/1Open gpt-oss:120b conversation
qwen3-coder-next10/102/22/23/32/21/1Open qwen3-coder-next conversation
qwen3.5:397b10/102/22/23/32/21/1Open qwen3.5:397b conversation
How scoring works

Each run is graded on five dimensions:

  • Task Completion (0-2): how fully the workflow answered the requested analysis task and completed required steps.
  • Execution Correctness (0-2): whether generated code is correct, consistent, and likely runnable without major fixes.
  • Output Quality (0-3): how well tables, charts, and results match the expected analytical outcomes.
  • Reasoning Quality (0-2): clarity and correctness of interpretation, explanation, and conclusions.
  • Reliability (0-1): robustness of the run, including low hallucination risk and stable behavior.

The final score is the sum of these dimensions, so total score = 0-10. Higher values indicate more complete, correct, and reliable notebook results for this workflow.

AI Analysis with glm-5.1

This run uses AI with a step-by-step list of prompts to perform the analysis task HR Employee Attrition Analysis in Python. Below, you can review the full conversation generated with glm-5.1. After the conversation, we show detailed score cards for this run.

load HR attrition dataset from https://raw.githubusercontent.com/pplonski/datasets-for-start/refs/heads/master/employee_attrition/HR-Employee-Attrition-All.csv and show overall attrition rate
Thinking

The user wants to load the HR attrition dataset and show the overall attrition rate. Let me load the data, inspect it, and compute the attrition rate.

Let me load the dataset and compute the overall attrition rate.

Explore employee attrition data
import pandas as pd

df = pd.read_csv("https://raw.githubusercontent.com/pplonski/datasets-for-start/refs/heads/master/employee_attrition/HR-Employee-Attrition-All.csv")

# Show shape, columns, and head
display(df.shape)
display(df.columns.tolist())
display(df.head())

# Compute overall attrition rate
attrition_rate = df['Attrition'].value_counts(normalize=True)
attrition_rate
(1470, 35)
['Age',
 'Attrition',
 'BusinessTravel',
 'DailyRate',
 'Department',
 'DistanceFromHome',
 'Education',
 'EducationField',
 'EmployeeCount',
 'EmployeeNumber',
 'EnvironmentSatisfaction',
 'Gender',
 'HourlyRate',
 'JobInvolvement',
 'JobLevel',
 'JobRole',
 'JobSatisfaction',
 'MaritalStatus',
 'MonthlyIncome',
 'MonthlyRate',
 'NumCompaniesWorked',
 'Over18',
 'OverTime',
 'PercentSalaryHike',
 'PerformanceRating',
 'RelationshipSatisfaction',
 'StandardHours',
 'StockOptionLevel',
 'TotalWorkingYears',
 'TrainingTimesLastYear',
 'WorkLifeBalance',
 'YearsAtCompany',
 'YearsInCurrentRole',
 'YearsSinceLastPromotion',
 'YearsWithCurrManager']
Age Attrition BusinessTravel DailyRate Department DistanceFromHome Education EducationField EmployeeCount EmployeeNumber ... RelationshipSatisfaction StandardHours StockOptionLevel TotalWorkingYears TrainingTimesLastYear WorkLifeBalance YearsAtCompany YearsInCurrentRole YearsSinceLastPromotion YearsWithCurrManager
0 41 Yes Travel_Rarely 1102 Sales 1 2 Life Sciences 1 1 ... 1 80 0 8 0 1 6 4 0 5
1 49 No Travel_Frequently 279 Research & Development 8 1 Life Sciences 1 2 ... 4 80 1 10 3 3 10 7 1 7
2 37 Yes Travel_Rarely 1373 Research & Development 2 2 Other 1 4 ... 2 80 0 7 3 3 0 0 0 0
3 33 No Travel_Frequently 1392 Research & Development 3 4 Life Sciences 1 5 ... 3 80 0 8 3 3 8 7 3 0
4 27 No Travel_Rarely 591 Research & Development 2 1 Medical 1 7 ... 4 80 1 6 3 3 2 2 2 2

5 rows × 35 columns

Attrition
No     0.838776
Yes    0.161224
Name: proportion, dtype: float64
Thinking

The dataset has been loaded and the attrition rate has been computed. The output shows:

  • 1,470 rows, 35 columns
  • Attrition rate: No = 83.88%, Yes = 16.12%

This directly answers the user's goal. I should provide a natural final answer.

The HR attrition dataset has 1,470 employees across 35 columns. The overall attrition rate is 16.12% — meaning roughly 1 in 6 employees has left the company. The remaining 83.88% stayed. This is a moderately imbalanced dataset, which is worth keeping in mind if we build predictive models later.

plot attrition rate by department and job role
Thinking

The user wants to see attrition rate by department and job role. I'll create a visualization showing attrition rates broken down by these two categorical variables. I'll use seaborn for this.

Let me think about the best way to visualize this. I could do two separate plots or a grouped bar chart. I think the clearest approach would be two bar charts - one for Department and one for JobRole. Or I could do a single chart with JobRole on y-axis, colored by department, showing attrition rate.

Actually, let me do two clean bar charts side by side - one for attrition rate by Department, and one for attrition rate by JobRole. That keeps it simple and readable.

Let me keep it to one chart per step as per the rules. I'll start with attrition rate by Department first since it has fewer categories, then follow up with JobRole.

Wait, the user asked for both. Let me do one chart that shows attrition rate by Department first, and then in the next step do JobRole. But the user asked for both... Let me do a single figure with two subplots to show both.

Actually, the rule says "Default to one chart OR one table per step." But I can use subplots within one figure. Let me do a figure with two subplots - one for Department and one for JobRole.

Actually, let me just do a single clean visualization. Since JobRole has more categories and is more granular, I could do a horizontal bar chart of attrition rate by JobRole, colored by Department. That would show both in one chart.

Let me go with two subplots in one figure - it's cleaner and directly answers the user's request.

I'll create a two-panel bar chart showing attrition rate by Department and by JobRole.

Plot attrition by department and role
import seaborn as sns
import matplotlib.pyplot as plt

# Compute attrition rates by Department and JobRole
dept_attrition = df.groupby('Department')['Attrition'].apply(lambda x: (x == 'Yes').mean()).sort_values()
role_attrition = df.groupby('JobRole')['Attrition'].apply(lambda x: (x == 'Yes').mean()).sort_values()

fig, axes = plt.subplots(1, 2, figsize=(16, 6))

# Attrition by Department
sns.barplot(x=dept_attrition.values, y=dept_attrition.index, ax=axes[0], palette='Blues_d')
axes[0].set_xlabel('Attrition Rate')
axes[0].set_ylabel('')
axes[0].set_title('Attrition Rate by Department')
for i, v in enumerate(dept_attrition.values):
    axes[0].text(v + 0.005, i, f'{v:.1%}', va='center')

# Attrition by Job Role
sns.barplot(x=role_attrition.values, y=role_attrition.index, ax=axes[1], palette='Oranges_d')
axes[1].set_xlabel('Attrition Rate')
axes[1].set_ylabel('')
axes[1].set_title('Attrition Rate by Job Role')
for i, v in enumerate(role_attrition.values):
    axes[1].text(v + 0.005, i, f'{v:.1%}', va='center')

plt.tight_layout()
plt.show()
/var/folders/pp/x90pfm0140d4glxshn77bthh0000gn/T/ipykernel_7128/397912727.py:11: FutureWarning: 

Passing `palette` without assigning `hue` is deprecated and will be removed in v0.14.0. Assign the `y` variable to `hue` and set `legend=False` for the same effect.

  sns.barplot(x=dept_attrition.values, y=dept_attrition.index, ax=axes[0], palette='Blues_d')
/var/folders/pp/x90pfm0140d4glxshn77bthh0000gn/T/ipykernel_7128/397912727.py:19: FutureWarning: 

Passing `palette` without assigning `hue` is deprecated and will be removed in v0.14.0. Assign the `y` variable to `hue` and set `legend=False` for the same effect.

  sns.barplot(x=role_attrition.values, y=role_attrition.index, ax=axes[1], palette='Oranges_d')
Thinking

The user's goal was to plot attrition rate by department and job role. The chart was successfully generated (output-2 shows the figure). However, the chart is visual-only - I can't see the actual numeric values from the plot. According to the sufficiency heuristics, for chart-only output without underlying numeric/text values, I should choose Path B to print the values.

Let me provide the numeric values that underlie the chart so the user can see exact attrition rates.

The chart was generated successfully, but the exact numeric attrition rates aren't visible from the figure alone. Let me print the underlying values for both breakdowns.

Calculate attrition rates
# Print attrition rates by Department and JobRole
dept_attrition = df.groupby('Department')['Attrition'].apply(lambda x: (x == 'Yes').mean()).sort_values(ascending=False)
role_attrition = df.groupby('JobRole')['Attrition'].apply(lambda x: (x == 'Yes').mean()).sort_values(ascending=False)

display(dept_attrition.to_frame('Attrition Rate').style.format('{:.1%}'))
display(role_attrition.to_frame('Attrition Rate').style.format('{:.1%}'))
  Attrition Rate
Department  
Sales 20.6%
Human Resources 19.0%
Research & Development 13.8%
  Attrition Rate
JobRole  
Sales Representative 39.8%
Laboratory Technician 23.9%
Human Resources 23.1%
Sales Executive 17.5%
Research Scientist 16.1%
Manufacturing Director 6.9%
Healthcare Representative 6.9%
Manager 4.9%
Research Director 2.5%
Thinking

The chart was generated but the numeric values aren't visible from the Styler objects. I need to print the actual values as plain text to provide concrete insights.

The Styler objects rendered but the actual numeric values aren't visible in the output. Let me print them as plain text so we can extract concrete insights.

Print attrition rates
# Print attrition rates as plain text
print("Attrition Rate by Department:")
print(dept_attrition.to_string())
print("\nAttrition Rate by Job Role:")
print(role_attrition.to_string())
Attrition Rate by Department:
Department
Sales                     0.206278
Human Resources           0.190476
Research & Development    0.138398

Attrition Rate by Job Role:
JobRole
Sales Representative         0.397590
Laboratory Technician        0.239382
Human Resources              0.230769
Sales Executive              0.174847
Research Scientist           0.160959
Manufacturing Director       0.068966
Healthcare Representative    0.068702
Manager                      0.049020
Research Director            0.025000
Thinking

The user's original goal was to plot attrition rate by department and job role. The notebook now has both the chart (cell-2) and the numeric values (cell-4). Let me analyze the outputs and provide a final answer.

From the outputs:

  • By Department: Sales (20.6%), Human Resources (19.0%), Research & Development (13.8%)
  • By Job Role: Sales Representative (39.8%), Laboratory Technician (23.9%), Human Resources (23.1%), Sales Executive (17.5%), Research Scientist (16.1%), Manufacturing Director (6.9%), Healthcare Representative (6.9%), Manager (4.9%), Research Director (2.5%)

Both the plot and the numeric values are available. The goal is fully answered. I should choose Path A.

The plots and numeric breakdowns are both complete. Here are the key takeaways:

By Department: Sales has the highest attrition rate at 20.6%, followed by Human Resources at 19.0%. Research & Development is the lowest at 13.8% — still notable given the overall rate is 16.1%.

By Job Role: The standout is Sales Representative at 39.8% — roughly 2 in 5 employees in that role leave. Laboratory Technician (23.9%) and Human Resources (23.1%) also exceed the company average. On the other end, Research Director (2.5%) and Manager (4.9%) have very low attrition, suggesting senior/leadership roles are far more stable.

The intersection of these two views tells a clear story: the Sales department's high attrition is driven heavily by Sales Representatives, while HR's elevated rate aligns with the HR job role itself. Research & Development's relatively lower department-level rate masks variation — Research Scientists (16.1%) attrit at nearly double the rate of Research Directors (2.5%) within the same department.

compare monthly income distribution for employees who left vs stayed
Thinking

The user wants to compare the monthly income distribution for employees who left (Attrition = Yes) vs stayed (Attrition = No). A good way to visualize this is with a box plot or violin plot, or perhaps a combination (violin + box). Let me create a clean visualization.

Great question — let's visualize how monthly income differs between employees who left and stayed. A violin plot with an overlaid box plot will show both the distribution shape and summary statistics.

Plot income by attrition
fig, ax = plt.subplots(figsize=(8, 6))

sns.violinplot(data=df, x='Attrition', y='MonthlyIncome', palette='Set2', inner=None, ax=ax)
sns.boxplot(data=df, x='Attrition', y='MonthlyIncome', width=0.15, boxprops=dict(zorder=2), ax=ax)

ax.set_title('Monthly Income Distribution: Attrition vs Retention')
ax.set_xlabel('Attrition')
ax.set_ylabel('Monthly Income (USD)')
plt.tight_layout()
plt.show()

# Also print summary stats
df.groupby('Attrition')['MonthlyIncome'].describe()
/var/folders/pp/x90pfm0140d4glxshn77bthh0000gn/T/ipykernel_7128/1350012881.py:3: FutureWarning: 

Passing `palette` without assigning `hue` is deprecated and will be removed in v0.14.0. Assign the `x` variable to `hue` and set `legend=False` for the same effect.

  sns.violinplot(data=df, x='Attrition', y='MonthlyIncome', palette='Set2', inner=None, ax=ax)
count mean std min 25% 50% 75% max
Attrition
No 1233.0 6832.739659 4818.208001 1051.0 3211.0 5204.0 8834.0 19999.0
Yes 237.0 4787.092827 3640.210367 1009.0 2373.0 3202.0 5916.0 19859.0
Thinking

The user goal is to compare monthly income distribution for employees who left vs stayed. The latest output includes both a violin+box plot and summary statistics table. Let me analyze what we have.

From the summary stats:

  • Stayed (No): mean = 6,832.74, median = 5,204, std = 4,818
  • Left (Yes): mean = 4,787.09, median = 3,202, std = 3,640

This clearly shows employees who left earned significantly less on average. The plot and numeric values are both present. This is sufficient to answer the goal.

The data clearly shows a substantial income gap between those who left and those who stayed:

  • Median income: Employees who left earned a median of 3,202 USD vs. 5,204 USD for those who stayed — a difference of roughly 2,000 USD, or 38% lower.
  • Mean income: 4,787 USD (left) vs. 6,833 USD (stayed) — about 30% lower.
  • Distribution shape: Both groups have a long right tail (max values are similar at ~19,900 USD), but the "Yes" group is much more concentrated at lower income levels. The IQR for leavers (2,373–5,916 USD) sits entirely below the stayed group's IQR (3,211–8,834 USD).
  • Key insight: Lower-income employees are disproportionately leaving. This aligns with the earlier findings that Sales Representatives (the lowest earners among sales roles) and Laboratory Technicians (also lower-paid) have the highest attrition rates. Income appears to be a strong driver of attrition, though it likely interacts with job role and career progression.
show correlation between job satisfaction, work-life balance and attrition
Thinking

The user wants to see the correlation between JobSatisfaction, WorkLifeBalance, and Attrition. Since Attrition is categorical (Yes/No), a standard Pearson correlation won't work directly. I should visualize how JobSatisfaction and WorkLifeBalance relate to attrition.

Good approach: Show attrition rate by each level of JobSatisfaction and WorkLifeBalance (bar charts), since these are ordinal variables (1-4 scales typically). This gives a clear, interpretable view.

Let me check what columns exist - from the dataset, likely JobSatisfaction and WorkLifeBalance are integer-coded (1-4).

I'll create two bar charts side by side showing attrition rate by each level of these variables.

Since Attrition is categorical, we'll look at attrition rates across the levels of JobSatisfaction and WorkLifeBalance rather than a traditional correlation matrix. Side-by-side bar charts will make the patterns clear.

Plot attrition by satisfaction and balance
# Compute attrition rate by each level
js_attrition = df.groupby('JobSatisfaction')['Attrition'].apply(lambda x: (x == 'Yes').mean())
wlb_attrition = df.groupby('WorkLifeBalance')['Attrition'].apply(lambda x: (x == 'Yes').mean())

fig, axes = plt.subplots(1, 2, figsize=(14, 5))

# Job Satisfaction
sns.barplot(x=js_attrition.index, y=js_attrition.values, palette='YlOrRd', ax=axes[0])
axes[0].set_xlabel('Job Satisfaction (1=Low → 4=High)')
axes[0].set_ylabel('Attrition Rate')
axes[0].set_title('Attrition Rate by Job Satisfaction')
for i, v in enumerate(js_attrition.values):
    axes[0].text(i, v + 0.005, f'{v:.1%}', ha='center', va='bottom')

# Work-Life Balance
sns.barplot(x=wlb_attrition.index, y=wlb_attrition.values, palette='YlGnBu', ax=axes[1])
axes[1].set_xlabel('Work-Life Balance (1=Low → 4=High)')
axes[1].set_ylabel('Attrition Rate')
axes[1].set_title('Attrition Rate by Work-Life Balance')
for i, v in enumerate(wlb_attrition.values):
    axes[1].text(i, v + 0.005, f'{v:.1%}', ha='center', va='bottom')

plt.tight_layout()
plt.show()
/var/folders/pp/x90pfm0140d4glxshn77bthh0000gn/T/ipykernel_7128/3565773359.py:8: FutureWarning: 

Passing `palette` without assigning `hue` is deprecated and will be removed in v0.14.0. Assign the `x` variable to `hue` and set `legend=False` for the same effect.

  sns.barplot(x=js_attrition.index, y=js_attrition.values, palette='YlOrRd', ax=axes[0])
/var/folders/pp/x90pfm0140d4glxshn77bthh0000gn/T/ipykernel_7128/3565773359.py:16: FutureWarning: 

Passing `palette` without assigning `hue` is deprecated and will be removed in v0.14.0. Assign the `x` variable to `hue` and set `legend=False` for the same effect.

  sns.barplot(x=wlb_attrition.index, y=wlb_attrition.values, palette='YlGnBu', ax=axes[1])
Thinking

The user wants to see the correlation between job satisfaction, work-life balance, and attrition. The latest output (cell-6) shows a bar chart with two subplots, but the exact numeric values aren't printed in text form. Let me check what's visible...

The chart was generated but the numeric values of js_attrition and wlb_attrition weren't printed explicitly in text. The bar plot was shown with percentage labels on the bars, but since this is a visual-only output (the text values aren't explicitly printed), I should choose Path B to print the underlying numeric values.

Let me provide a concise analysis and then print the values.

Actually, looking more carefully at the chart code, it does add text labels with f'{v:.1%}' on the bars. But those are on the figure which we can't read precisely. The goal is to "show correlation" - the chart does visualize this, but we should also print the actual numbers for a complete answer.

Path B: Print the actual numeric values of attrition rates by JobSatisfaction and WorkLifeBalance levels.

The chart shows the general trend clearly, but the exact numeric values aren't accessible from the visual alone. Let me print them to give a precise answer.

Display attrition rates by category
print("Attrition Rate by Job Satisfaction Level:")
print(js_attrition.apply(lambda x: f'{x:.1%}').to_string())
print("\nAttrition Rate by Work-Life Balance Level:")
print(wlb_attrition.apply(lambda x: f'{x:.1%}').to_string())
Attrition Rate by Job Satisfaction Level:
JobSatisfaction
1    22.8%
2    16.4%
3    16.5%
4    11.3%

Attrition Rate by Work-Life Balance Level:
WorkLifeBalance
1    31.2%
2    16.9%
3    14.2%
4    17.6%
Thinking

The user wants to understand the correlation between job satisfaction, work-life balance, and attrition. The latest outputs (cell-7) provide the exact numeric attrition rates by level for both variables, and the chart in cell-6 visualizes these patterns.

Let me analyze the results:

Job Satisfaction vs Attrition:

  • Level 1 (Low): 22.8%
  • Level 2: 16.4%
  • Level 3: 16.5%
  • Level 4 (High): 11.3%

Clear negative relationship - lower satisfaction correlates with higher attrition.

Work-Life Balance vs Attrition:

  • Level 1 (Low): 31.2%
  • Level 2: 16.9%
  • Level 3: 14.2%
  • Level 4 (High): 17.6%

The relationship is non-monotonic. Very low WLB has very high attrition, but the best WLB (level 4) actually has slightly higher attrition than level 3.

This is sufficient to answer the original goal. The numeric values are available, the chart was shown. I'll go with Path A.

Here's what the data reveals about the relationship between these two factors and attrition:

Job Satisfaction shows a strong, nearly monotonic negative correlation with attrition:

  • Employees with the lowest satisfaction (level 1) leave at 22.8% — more than double the rate of those with the highest satisfaction (level 4, 11.3%).
  • The drop is steepest between levels 1 and 2, then flattens — suggesting that moving someone from "very unhappy" to "somewhat unhappy" makes the biggest dent in attrition.

Work-Life Balance has a more nuanced, non-linear pattern:

  • The worst work-life balance (level 1) drives a striking 31.2% attrition rate — far above the overall ~16% baseline.
  • Levels 2 and 3 show decreasing attrition (16.9%14.2%).
  • But level 4 (the best work-life balance) ticks back up to 17.6%, breaking the monotonic trend. This could indicate that employees with exceptional work-life balance may be less invested or have more external opportunities.

Key takeaway: Both factors matter, but in different ways. Low job satisfaction is a steady, gradient-style risk factor — the worse the satisfaction, the higher the attrition, period. Work-life balance acts more like a threshold effect: truly poor balance (level 1) is a massive red flag, but improving beyond "adequate" (level 3) doesn't yield further attrition reduction. For retention programs, addressing the worst-off employees in either dimension would have the highest impact.

Score cards for glm-5.1 for HR Employee Attrition Analysis in Python

Total score: 10/10

  • Task Completion: 2/2

    Excellent

    All four requested analyses were completed: dataset loading/attrition rate, department and job role attrition, income comparison, and satisfaction/work-life balance correlation.

  • Execution Correctness: 2/2

    Excellent

    The code shown is syntactically valid and the outputs indicate it ran successfully, including the dataset shape and computed summaries.

  • Output Quality: 3/3

    Excellent

    The outputs match the expected outcomes semantically, including the 16.1% attrition rate, department/job role patterns, income gap, and satisfaction/work-life balance trends.

  • Reasoning Quality: 2/2

    Excellent

    The notebook provides clear interpretations tied to the computed results and correctly explains the observed attrition patterns.

  • Reliability: 1/1

    Excellent

    The workflow is consistent and evidence-based, with numeric outputs supporting the visualizations.

Try MLJAR Studio

Run the same type of AI-powered data analysis on your own datasets with conversational notebooks in MLJAR Studio.

Explore More AI Analysis Examples

Discover additional workflows across categories. Each example includes prompts, conversation outputs, and model-level scoring so you can compare approaches and results.