feat(chart): enterprise agent adoption surveys

This commit is contained in:
Orchestrator
2026-06-04 17:53:47 -05:00
committed by marsultor
parent d84d0655ee
commit 4ed57f7dd4

View File

@@ -0,0 +1,184 @@
"""Agent Adoption Survey Comparison Chart
Grouped horizontal bar chart comparing key enterprise AI adoption metrics
across three major 2025 surveys: LangChain, McKinsey, and PwC.
"""
import matplotlib
matplotlib.use("Agg")
# Patch matplotlib Path.__deepcopy__ to break Python 3.14 recursion loop
try:
from matplotlib.path import Path
_original_path_deepcopy = Path.__deepcopy__
def _safe_path_deepcopy(self, memo):
if id(self) in memo:
return memo[id(self)]
memo[id(self)] = self
return self
Path.__deepcopy__ = _safe_path_deepcopy
except Exception:
pass
import matplotlib.pyplot as plt
import matplotlib.colors as mcolors
import matplotlib.patches as mpatches
from src.data.agent_adoption import agent_survey_data
from src.utils.styling import (
get_theme, EXPORT_DPI, AGENT_GROWTH, GRAY_DARK, BLACK, WHITE, GRAY_LIGHT,
)
def _shade(base_hex: str, factor: float) -> str:
"""Lighten or darken a hex color by a given factor (01)."""
r, g, b = mcolors.to_rgb(base_hex)
# Blend toward white to lighten
r2 = r + (1.0 - r) * factor
g2 = g + (1.0 - g) * factor
b2 = b + (1.0 - b) * factor
return mcolors.to_hex((r2, g2, b2))
def plot_agent_adoption() -> str:
"""Generate grouped horizontal bar chart of survey comparisons."""
plt.rcParams.update(get_theme())
fig, ax = plt.subplots(figsize=(14, 8))
# ------------------------------------------------------------------
# Data
# ------------------------------------------------------------------
lc = agent_survey_data["langchain_2025"]
mc = agent_survey_data["mckinsey_2025"]
pc = agent_survey_data["pwc_2025"]
# Each row is a comparable category; values are [LangChain, McKinsey, PwC]
# Where a survey has no direct comparable metric, we use None.
categories = [
"Production\nDeployment",
"Overall\nAI Adoption",
"Budget\nIncrease",
"Scaling\nAgentic AI",
"Productivity\nValue",
]
# Values mapped to closest comparable metrics
values = [
# Production / Deployment
[lc["production"], None, pc["ai_agents_already_adopted"]],
# Overall AI Adoption / Maturity
[lc["observability_implemented"], mc["overall_ai_adoption"], None],
# Budget / Investment Intent
[lc["multi_model_deployments"], None, pc["plan_increase_ai_budgets"]],
# Scaling / Experimentation
[None, mc["agentic_ai_scaling"], None],
# Measurable Value / Productivity
[None, None, pc["measurable_productivity_value"]],
]
# Survey identifiers
surveys = [
"LangChain\n(n=1,340)",
"McKinsey\n(n=1,993)",
"PwC\n(n=308)",
]
# Colors: base AGENT_GROWTH with increasing lightness
colors = [
AGENT_GROWTH, # LangChain — full purple
_shade(AGENT_GROWTH, 0.25), # McKinsey — lighter
_shade(AGENT_GROWTH, 0.50), # PwC — lightest
]
# ------------------------------------------------------------------
# Plotting
# ------------------------------------------------------------------
n_cats = len(categories)
bar_height = 0.22
x_positions = [0, 1, 2] # offset within each group
y_positions = []
for i in range(n_cats):
base_y = i * 3 # three bars per category
y_positions.append([base_y + off for off in [0.0, 0.22, 0.44]])
# Plot bars
for row_idx, (cat, row_vals) in enumerate(zip(categories, values)):
for col_idx, val in enumerate(row_vals):
if val is None:
continue
y = y_positions[row_idx][col_idx]
ax.barh(y, val, height=bar_height,
color=colors[col_idx],
edgecolor=WHITE, linewidth=0.8,
label=surveys[col_idx] if row_idx == 0 else None)
# Value label on bar
ax.text(val + 1.0, y, f"{val:.1f}%",
va="center", fontsize=9, color=GRAY_DARK,
fontweight="bold")
# Y-axis: category labels centered on each group
group_centers = [i * 3 + 0.22 for i in range(n_cats)]
ax.set_yticks(group_centers)
ax.set_yticklabels(categories, fontsize=11, fontweight="bold")
# Inset legend-like labels inside each group
legend_y_offset = 0.55
for col_idx in range(3):
ax.text(-0.5, group_centers[0] + legend_y_offset - col_idx * 0.22,
surveys[col_idx], fontsize=8, color=colors[col_idx],
ha="left", va="center", fontweight="bold")
# Axis config
ax.set_xlim(0, 105)
ax.set_xlabel("Percentage (%)", fontsize=11, color=GRAY_DARK)
ax.set_xticks(range(0, 106, 10))
ax.tick_params(axis="x", labelsize=9)
# Grid
ax.xaxis.grid(True, alpha=0.3, color=GRAY_LIGHT)
ax.yaxis.grid(False)
# Spine cleanup
ax.spines["top"].set_visible(False)
ax.spines["right"].set_visible(False)
ax.spines["left"].set_color("#cccccc")
ax.spines["bottom"].set_color("#cccccc")
# Title
ax.set_title(
"Enterprise Agent Adoption — Survey Comparison",
fontsize=18, fontweight="bold", pad=16, color=BLACK,
)
ax.text(
0.5, -0.18,
"LangChain (n=1,340) | McKinsey (n=1,993) | PwC (n=308)",
transform=ax.transAxes,
fontsize=11, color=GRAY_DARK, ha="center",
)
# Legend
handles = []
for col_idx in range(3):
handles.append(
mpatches.Rectangle((0, 0), 1, 1, color=colors[col_idx], alpha=1)
)
ax.legend(handles, surveys, loc="lower right", fontsize=9,
frameon=True, edgecolor="#cccccc")
# Adjust layout
fig.subplots_adjust(left=0.28, right=0.95, top=0.85, bottom=0.10)
# Save
out_path = "output/charts/10_agent_adoption.png"
fig.savefig(out_path, dpi=EXPORT_DPI,
facecolor=fig.get_facecolor(), edgecolor="none")
plt.close(fig)
return out_path
def main():
path = plot_agent_adoption()
print(f"Chart saved: {path}")
if __name__ == "__main__":
main()