Skip to content

Commit 4f2477b

Browse files
committed
overhaul
1 parent 33c27c1 commit 4f2477b

73 files changed

Lines changed: 987 additions & 314 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

DATASET.md

Lines changed: 101 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,101 @@
1+
# InsightBench Dataset Schema
2+
3+
This document describes the structure and conventions of the InsightBench dataset.
4+
5+
## Overview
6+
7+
InsightBench contains **97 flags** (analytical tasks) with a total of **409 ground-truth insights** for evaluating data analytics agents. Each flag consists of:
8+
- A CSV dataset (simulated ServiceNow data)
9+
- A Jupyter notebook with ground-truth analysis code and insights
10+
- A JSON metadata file used by the evaluation framework
11+
12+
## JSON Schema
13+
14+
Each `flag-{N}.json` file has this structure:
15+
16+
```json
17+
{
18+
"dataset_csv_path": "data/notebooks/csvs/flag-{N}.csv",
19+
"user_dataset_csv_path": "data/notebooks/csvs/flag-{N}-sysuser.csv | null",
20+
"metadata": {
21+
"goal": "Analytical goal description",
22+
"role": "Analyst role (e.g., 'L2 Support Agent')",
23+
"category": "One of the canonical categories",
24+
"dataset_description": "Description of the dataset fields",
25+
"header": "Task title",
26+
"difficulty": 1-4 (optional, null if not assigned)
27+
},
28+
"insight_list": [
29+
{
30+
"data_type": "descriptive | diagnostic | predictive | ...",
31+
"insight": "The key finding (ground truth)",
32+
"insight_value": { ... },
33+
"plot": { ... },
34+
"question": "The analytical question",
35+
"actionable_insight": "Recommended action",
36+
"code": "Python analysis code"
37+
}
38+
],
39+
"insights": ["insight text 1", "insight text 2", ...],
40+
"summary": "Summary of all findings"
41+
}
42+
```
43+
44+
## Categories
45+
46+
| Category | Count | Description |
47+
|----------|-------|-------------|
48+
| Incident Management | 31 | ServiceNow incident analysis |
49+
| Finance Management | 28 | Expense and financial analysis |
50+
| Goal Management | 20 | Organizational goal tracking |
51+
| User Management | 8 | HR and personnel analysis |
52+
| Asset Management | 6 | IT asset management |
53+
| Asset Management & User Management | 2 | Cross-domain analysis |
54+
| Finance Management & User Management | 2 | Cross-domain analysis |
55+
56+
## Data Types (Insight Classification)
57+
58+
| Type | Count | Description |
59+
|------|-------|-------------|
60+
| descriptive | 188 | What happened? Distribution, averages, totals |
61+
| diagnostic | 108 | Why did it happen? Correlations, root cause |
62+
| comparative | 33 | How do groups differ? Cross-group analysis |
63+
| predictive | 22 | What will happen? Trends, forecasts |
64+
| analytical | 23 | Deep analysis of patterns and relationships |
65+
| time_series | 17 | Temporal patterns and trends |
66+
| correlative | 6 | Statistical correlations |
67+
| trend diagnosis | 4 | Trend identification and analysis |
68+
| frequency | 4 | Frequency and count analysis |
69+
| distribution | 2 | Distribution shape analysis |
70+
| prescriptive | 1 | What should be done? Recommendations |
71+
| categorical | 1 | Categorical data analysis |
72+
73+
## Adversarial Flags (80-87)
74+
75+
Flags 80-87 are **deliberately adversarial** test cases. Their CSVs intentionally lack the columns required by the analysis. The ground-truth insights are error messages like "There was no column X to conduct any analysis."
76+
77+
These flags test whether data analytics agents:
78+
1. Correctly identify when required data is unavailable
79+
2. Report the limitation instead of hallucinating insights
80+
3. Do not fabricate analysis results
81+
82+
## Difficulty Levels
83+
84+
Difficulty is assigned to 12 flags (from notebook metadata):
85+
86+
| Level | Flags |
87+
|-------|-------|
88+
| 1 | 12, 59 |
89+
| 2 | 3, 49 |
90+
| 3 | 2, 48 |
91+
| 4 | 1, 47, 94, 95, 96, 97 |
92+
93+
## Evaluation
94+
95+
The evaluation framework uses the `insights` array (list of insight text strings) for scoring via ROUGE-1 or G-EVAL. The `insight_list` provides the full structured ground truth.
96+
97+
Benchmark tiers:
98+
- `"toy"`: flags 1-5 (5 flags)
99+
- `"standard"`: flags 1-30 (30 flags)
100+
- `"full"`: flags 1-97 excluding duplicates (97 flags)
101+

README.md

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,9 @@ Insight-Bench is a benchmark dataset designed to evaluate end-to-end data analyt
1010

1111
## Data
1212

13-
All groundtruth notebooks are in `data/notebooks`.
13+
The benchmark contains **97 flags** (analytical tasks) with **409 ground-truth insights** across 7 categories: Incident Management, Finance Management, Goal Management, User Management, Asset Management, and two cross-domain categories. Flags 80-87 are adversarial test cases that evaluate whether agents correctly identify when required data columns are unavailable.
14+
15+
All ground-truth notebooks are in `data/notebooks`. See [DATASET.md](DATASET.md) for full schema documentation.
1416

1517
An example notebook can be found here: `data/notebooks/flag-1.ipynb`
1618

data/notebooks/flag-1.json

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,17 +4,18 @@
44
"metadata": {
55
"goal": "Find the discrepancy and imbalance in distribution of incidents assigned across categories",
66
"role": "L2 Support Agent",
7-
"category": "Incidents Management",
7+
"category": "Incident Management",
88
"dataset_description": "The dataset comprises 500 entries simulating ServiceNow incidents table, detailing various attributes such as category, state, open and close dates, involved personnel, and incident specifics like location, description, and priority. It captures incident management activities with fields like 'opened_at', 'closed_at', 'assigned_to', 'short_description', and 'priority', reflecting the operational handling and urgency of issues across different locations and categories.",
9-
"header": "Hardware Incident Dataset (Flag 1)"
9+
"header": "Hardware Incident Dataset (Flag 1)",
10+
"difficulty": 4
1011
},
1112
"insight_list": [
1213
{
1314
"data_type": "descriptive",
1415
"insight": "hardware incidents is significantly higher than others",
1516
"insight_value": {
1617
"x_val": "Hardware",
17-
"y_val": 335
18+
"y_val": 336
1819
},
1920
"plot": {
2021
"plot_type": "histogram",
@@ -168,7 +169,8 @@
168169
"plot description": "The line plot displays the trend of incidents across different categories over time. Each line represents a category and the height of the line corresponds to the number of incidents in that category at a given time. The 'Hardware' category does not show any significant increasing trend. It is relatively stable and has a higher count than other categories."
169170
},
170171
"question": "Is there a pattern or trend over time in the distribution of incidents across categories?",
171-
"code": "# Convert 'opened_at' to datetime\ndf['opened_at'] = pd.to_datetime(df['opened_at'])\n\n# Resample the data by month and category, and count the number of incidents\ndf_resampled = df.groupby([pd.Grouper(key='opened_at', freq='M'), 'category']).size().unstack()\n\n# Plot the resampled data\nplot = df_resampled.plot(kind='line')\n\n# Set plot title\nplt.title('Incidents Over Time by Category')\n\n# Set x-axis label\nplt.xlabel('Time')\n\n# Set y-axis label\nplt.ylabel('Number of Incidents')\n\n# Display the figure\nplt.show()"
172+
"code": "# Convert 'opened_at' to datetime\ndf['opened_at'] = pd.to_datetime(df['opened_at'])\n\n# Resample the data by month and category, and count the number of incidents\ndf_resampled = df.groupby([pd.Grouper(key='opened_at', freq='M'), 'category']).size().unstack()\n\n# Plot the resampled data\nplot = df_resampled.plot(kind='line')\n\n# Set plot title\nplt.title('Incidents Over Time by Category')\n\n# Set x-axis label\nplt.xlabel('Time')\n\n# Set y-axis label\nplt.ylabel('Number of Incidents')\n\n# Display the figure\nplt.show()",
173+
"actionable_insight": ""
172174
},
173175
{
174176
"data_type": "diagnostic",

data/notebooks/flag-10.json

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,8 @@
7777
},
7878
"question": "Is the increase in ttr uniform across all categories of incidents or is it more pronounced in a specific category?",
7979
"actionable_insight": "The uniform increase in TTR across all categories suggests that the issue is not specific to any particular category. This could indicate a systemic issue in the incident management process. It would be beneficial to investigate the overall process and identify areas for improvement to reduce the TTR.",
80-
"code": "# Group by category and opened_at date, then calculate average ttr\ncategory_ttr_trend = df.groupby(['category', df['opened_at'].dt.date])['ttr_days'].mean().reset_index()\n\n# Plot the trend for each category\nfig, ax = plt.subplots(figsize=(10,6))\n\nfor category in category_ttr_trend['category'].unique():\n ax.plot(category_ttr_trend[category_ttr_trend['category'] == category]['opened_at'], \n category_ttr_trend[category_ttr_trend['category'] == category]['ttr_days'], \n label=category)\n\nplt.title('Trend of TTR Across Categories Over Time')\nplt.xlabel('Opened At')\nplt.ylabel('Average TTR (Days)')\nplt.legend(loc='best')\nplt.grid(True)\nplt.show()"
80+
"code": "# Group by category and opened_at date, then calculate average ttr\ncategory_ttr_trend = df.groupby(['category', df['opened_at'].dt.date])['ttr_days'].mean().reset_index()\n\n# Plot the trend for each category\nfig, ax = plt.subplots(figsize=(10,6))\n\nfor category in category_ttr_trend['category'].unique():\n ax.plot(category_ttr_trend[category_ttr_trend['category'] == category]['opened_at'], \n category_ttr_trend[category_ttr_trend['category'] == category]['ttr_days'], \n label=category)\n\nplt.title('Trend of TTR Across Categories Over Time')\nplt.xlabel('Opened At')\nplt.ylabel('Average TTR (Days)')\nplt.legend(loc='best')\nplt.grid(True)\nplt.show()",
81+
"insight_value": {}
8182
},
8283
{
8384
"data_type": "descriptive",
@@ -97,7 +98,8 @@
9798
},
9899
"question": "Are there any trends in the productivity of the human agents over time? For instance, is there a decrease in the number of incidents resolved per agent over time?",
99100
"actionable_insight": "The uniform productivity across all agents suggests that the workload is evenly distributed and all agents are equally productive. This is a positive indicator of good workload management. However, it would still be beneficial to continually monitor agent productivity and workload to ensure this balance is maintained.",
100-
"code": "agent_incident_count = df.groupby('assigned_to')['number'].count()\n\n# Plot the histogram\nagent_incident_count.plot(kind='bar', figsize=(10,6))\n\nplt.title('Number of Incidents Resolved Per Agent')\nplt.xlabel('Agent')\nplt.ylabel('Number of Incidents Resolved')\nplt.grid(True)\nplt.xticks(rotation=45)\nplt.show()"
101+
"code": "agent_incident_count = df.groupby('assigned_to')['number'].count()\n\n# Plot the histogram\nagent_incident_count.plot(kind='bar', figsize=(10,6))\n\nplt.title('Number of Incidents Resolved Per Agent')\nplt.xlabel('Agent')\nplt.ylabel('Number of Incidents Resolved')\nplt.grid(True)\nplt.xticks(rotation=45)\nplt.show()",
102+
"insight_value": {}
101103
}
102104
],
103105
"insights": [

data/notebooks/flag-100.json

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,10 @@
44
"metadata": {
55
"goal": "Find the discrepancy and imbalance in distribution of incidents assigned across categories",
66
"role": "L2 Support Agent",
7-
"category": "Incidents Management",
7+
"category": "Incident Management",
88
"dataset_description": "The dataset comprises 500 entries simulating ServiceNow incidents table, detailing various attributes such as category, state, open and close dates, involved personnel, and incident specifics like location, description, and priority. It captures incident management activities with fields like 'opened_at', 'closed_at', 'assigned_to', 'short_description', and 'priority', reflecting the operational handling and urgency of issues across different locations and categories.",
9-
"header": "Hardware Incident Dataset (Flag 100)"
9+
"header": "Hardware Incident Dataset (Flag 100)",
10+
"difficulty": 4
1011
},
1112
"insight_list": [
1213
{
@@ -73,7 +74,7 @@
7374
},
7475
{
7576
"data_type": "diagnostic",
76-
"insight": "There are specific mentions of printers in the incident descriptions.",
77+
"insight": "There are no specific mentions of the word 'Printer' in the incident descriptions.",
7778
"insight_value": {
7879
"x_val": "Printer",
7980
"y_val": 0
@@ -162,18 +163,22 @@
162163
"plot description": "The line plot displays the trend of incidents across different categories over time. Each line represents a category and the height of the line corresponds to the number of incidents in that category at a given time. The 'Hardware' category does not show any significant increasing trend. It is relatively stable and has a higher count than other categories."
163164
},
164165
"question": "Is there a pattern or trend over time in the distribution of incidents across categories?",
165-
"code": "# Convert 'opened_at' to datetime\ndf['opened_at'] = pd.to_datetime(df['opened_at'])\n\n# Resample the data by month and category, and count the number of incidents\ndf_resampled = df.groupby([pd.Grouper(key='opened_at', freq='M'), 'category']).size().unstack()\n\n# Plot the resampled data\nplot = df_resampled.plot(kind='line')\n\n# Set plot title\nplt.title('Incidents Over Time by Category')\n\n# Set x-axis label\nplt.xlabel('Time')\n\n# Set y-axis label\nplt.ylabel('Number of Incidents')\n\n# Display the figure\nplt.show()"
166+
"code": "# Convert 'opened_at' to datetime\ndf['opened_at'] = pd.to_datetime(df['opened_at'])\n\n# Resample the data by month and category, and count the number of incidents\ndf_resampled = df.groupby([pd.Grouper(key='opened_at', freq='M'), 'category']).size().unstack()\n\n# Plot the resampled data\nplot = df_resampled.plot(kind='line')\n\n# Set plot title\nplt.title('Incidents Over Time by Category')\n\n# Set x-axis label\nplt.xlabel('Time')\n\n# Set y-axis label\nplt.ylabel('Number of Incidents')\n\n# Display the figure\nplt.show()",
167+
"actionable_insight": ""
166168
},
167169
{
168170
"insight": "",
169171
"question": "What are the most effective resolution methods for different types of incidents?",
170-
"code": "import pandas as pd\nfrom matplotlib import pyplot as plt\n\ndf = pd.read_csv('csvs/flag-100.csv')\n\n# Analyze resolution methods\nresolution_counts = df['resolution_method'].value_counts()\nmost_common_method = resolution_counts.index[0]\nleast_common_method = resolution_counts.index[-1]\n\nresolution_by_category = df.groupby('category')['resolution_method'].agg(lambda x: x.value_counts().index[0])\n\n# Plotting code\nplt.figure(figsize=(12, 6))\nresolution_counts.plot(kind='bar')\nplt.title('Frequency of Resolution Methods')\nplt.xlabel('Resolution Method')\nplt.ylabel('Number of Incidents')\nplt.xticks(rotation=45, ha='right')\nplt.tight_layout()\n\n# Save the plot\nplt.show()\nplt.close()"
172+
"code": "import pandas as pd\nfrom matplotlib import pyplot as plt\n\ndf = pd.read_csv('csvs/flag-100.csv')\n\n# Analyze resolution methods\nresolution_counts = df['resolution_method'].value_counts()\nmost_common_method = resolution_counts.index[0]\nleast_common_method = resolution_counts.index[-1]\n\nresolution_by_category = df.groupby('category')['resolution_method'].agg(lambda x: x.value_counts().index[0])\n\n# Plotting code\nplt.figure(figsize=(12, 6))\nresolution_counts.plot(kind='bar')\nplt.title('Frequency of Resolution Methods')\nplt.xlabel('Resolution Method')\nplt.ylabel('Number of Incidents')\nplt.xticks(rotation=45, ha='right')\nplt.tight_layout()\n\n# Save the plot\nplt.show()\nplt.close()",
173+
"insight_value": {},
174+
"actionable_insight": "",
175+
"data_type": "descriptive"
171176
}
172177
],
173178
"insights": [
174179
"The incidents are equally distributed across all categories.",
175180
"There are no specific issues mentioned in the incident descriptions for each category.",
176-
"There are specific mentions of printers in the incident descriptions.",
181+
"There are no specific mentions of the word 'Printer' in the incident descriptions.",
177182
"There is no specific location where hardware incidents are concentrated.",
178183
"There is no significant increasing trend in the 'Hardware' or any other category.",
179184
""

data/notebooks/flag-12.json

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,10 @@
44
"metadata": {
55
"goal": "Find the discrepancy and imbalance in incidents assigned",
66
"role": "L1 Agent",
7-
"category": "Incidents Management",
7+
"category": "Incident Management",
88
"dataset_description": "The dataset comprises 500 entries simulating ServiceNow incidents table, detailing various attributes such as category, state, open and close dates, involved personnel, and incident specifics like description, and priority. It captures incident management activities with fields like 'opened_at', 'closed_at', 'assigned_to', 'short_description', and 'priority', reflecting the operational handling and urgency of issues across different locations and categories.",
9-
"header": "Hardware Incident Easy Dataset (Flag 12)"
9+
"header": "Hardware Incident Easy Dataset (Flag 12)",
10+
"difficulty": 1
1011
},
1112
"insight_list": [
1213
{
@@ -116,7 +117,8 @@
116117
"plot description": "The line plot displays the trend of incidents across different categories over time. Each line represents a category and the height of the line corresponds to the number of incidents in that category at a given time. The 'Hardware' category shows a significant increasing trend."
117118
},
118119
"question": "Is there a pattern or trend over time in the distribution of incidents across categories?",
119-
"code": "# Convert 'opened_at' to datetime\ndf['opened_at'] = pd.to_datetime(df['opened_at'])\n\n# Resample the data by month and category, and count the number of incidents\ndf_resampled = df.groupby([pd.Grouper(key='opened_at', freq='M'), 'category']).size().unstack()\n\n# Plot the resampled data\nplot = df_resampled.plot(kind='line')\n\n# Set plot title\nplt.title('Incidents Over Time by Category')\n\n# Set x-axis label\nplt.xlabel('Time')\n\n# Set y-axis label\nplt.ylabel('Number of Incidents')\n\n# Display the figure\nplt.show()"
120+
"code": "# Convert 'opened_at' to datetime\ndf['opened_at'] = pd.to_datetime(df['opened_at'])\n\n# Resample the data by month and category, and count the number of incidents\ndf_resampled = df.groupby([pd.Grouper(key='opened_at', freq='M'), 'category']).size().unstack()\n\n# Plot the resampled data\nplot = df_resampled.plot(kind='line')\n\n# Set plot title\nplt.title('Incidents Over Time by Category')\n\n# Set x-axis label\nplt.xlabel('Time')\n\n# Set y-axis label\nplt.ylabel('Number of Incidents')\n\n# Display the figure\nplt.show()",
121+
"actionable_insight": ""
120122
}
121123
],
122124
"insights": [

0 commit comments

Comments
 (0)