Recriando o gráfico de taxa de adoção da Apollo AI com GPT-5, Python e Pyodide
Recriando o gráfico de taxa de adoção da Apollo AI com GPT-5, Python e Pyodide
9 de setembro de 2025
O “Economista Chefe” da Apollo Global Management, Dr. Torsten Sløk, lançou este gráfico interessante que parece mostrar uma desaceleração nas taxas de adoção de IA entre grandes (> 250 funcionários):

Aqui está a descrição completa que acompanhou o gráfico:
O Bureau do Censo dos EUA realiza uma pesquisa quinzenal com 1,2 milhão de empresas, e uma pergunta é se uma empresa usou ferramentas de IA como aprendizado de máquina, processamento de idiomas naturais, agentes virtuais ou reconhecimento de voz para ajudar a produzir bens ou serviços nas últimas duas semanas. Dados recentes do tamanho da empresa mostram que a adoção da IA está diminuindo entre empresas com mais de 250 funcionários, veja o gráfico abaixo.
(Meu primeiro pensamento em ver esse gráfico é que espero que represente o pico das expectativas infladas levando ao calha de dissilusão No ciclo de hype do Gartner (que a Wikipedia chama de “amplamente contestada, com estudos apontando para ele ser inconsistentemente verdadeiro na melhor das hipóteses”), pois isso significa que podemos estar atingindo o fim da fase inicial do hype e indo em direção ao para o Inclinação da iluminação.)
Encontrando os dados do Censo dos EUA com pesquisa GPT-5
Esta é a primeira vez que ouvi falar do Censo dos EUA, realizando uma pesquisa quinzenal (que é uma vez a cada duas semanas) sobre a IA!
Decidi rastrear os números e ver se consegui recriar o gráfico sozinho. E como o GPT-5 é realmente bom em pesquisar agora, alimentei o seguinte prompt para ver como isso poderia fazer:
> The US Census Bureau conducts a biweekly survey of 1.2 million firms, and one question is whether a business has used AI tools such as machine learning, natural language processing, virtual agents or voice recognition to help produce goods or services in the past two weeks. Recent data by firm size shows that AI adoption has been declining among companies with more than 250 employees, see chart below.
Find me that original data
Foram necessários 1 m19 para encontrar exatamente o que eu precisava:
Aqui está a fonte original do Censo do Censo dos EUA para essa série:
- BTOs “Size de Tamanho do Emprego” Série Temporal (XLSX) – Ações quinzenais de empresas que respondem Sim Para “Nas últimas duas semanas, esse negócio usou a inteligência artificial (IA) na produção de bens ou serviços?”, Quebrada por baldes de tamanho firme (incl. Mais de 250 funcionários). Cobertura: 11 de setembro de 2023 → 24 de agosto de 2025. (Census.gov) (…)
Aquela página do censo não era de forma alguma óbvio. Felizmente, o GPT-5 me deu um dado para o arquivo “classe de tamanho de emprego”, este link aqui:

Então, baixei esse arquivo e confirmei que era realmente uma planilha contendo os dados que eu queria (entre todos os tipos de outras perguntas da pesquisa). Aqui está uma cópia de 374kb XLSX do arquivo que eu baixei.
Recriando o gráfico com intérprete de código GPT-5
Então, o que devo fazer com isso agora? Decidi ver se o GPT-5 poderia transformar a planilha de volta nesse gráfico original, usando o Python em execução em sua ferramenta de intérprete de código.
Por isso, enviei o arquivo XLSX de volta para o ChatGPT, caí em uma captura de tela do gráfico da Apollo e solicitei:
Use this data to recreate this chart using python

Eu pensei que era uma ordem bastante difícil, mas sempre vale a pena lançar grandes desafios em um LLM para aprender com o desempenho.
Isto realmente trabalhou duro nisso. Eu não fiz o tempo exatamente, mas gastou pelo menos 7 minutos “raciocinando” em 5 blocos de pensamento diferentes, intercalados com mais de uma dúzia de sessões de análise Python. Usou pandas e numpy Para explorar a planilha enviada e encontrar as figuras certas, depois tentei várias tentativas de plotar com matplotlib.
Até onde eu sei, o GPT-5 no ChatGPT agora pode alimentar os gráficos, ele cria novamente em seu próprio modelo de visão, porque parecia renderizar um gráfico quebrado (vazio) e continuar tentando fazê-lo funcionar.
Ele encontrou um dicionário de dados na última guia da planilha e usou isso para criar uma tabela de pesquisa que corresponda às letras A através G para os baldes reais do tamanho dos funcionários.
No final do processo, cuspiu este gráfico:

À primeira vista, pensei que o havia acertado … mas depois comparei o gráfico mais de perto com o original da Apollo e vi algumas discrepâncias definitivas. O gráfico do GPT-5 atingiu o pico de 14,5%, mas o valor mais alto no Apollo’s foi mais de 13,5%. O gráfico do GPT-5 era mais espesso-e mais interessante incluiu um aumento claro no último ponto de dados em que a Apollo havia tendência para baixo.
Decidi que era hora de olhar para os dados reais. Abri a planilha em números, encontrei as colunas de perguntas da IA e as revisei manualmente. Eles pareciam corresponder aos resultados do gráfico do GPT-5-por que a diferença para a de Apollo?
Então notei um detalhe crucial no gráfico da Apollo que eu havia saído da minha captura de tela original!
NOTA: Os dados são a média móvel de seis pesquisas.
Então eu disse ao chatgpt:
Do the first question, plot it as a six survey rolling average
Fiz a primeira pergunta, porque havia dois que eram relevantes na planilha da pesquisa.
- Nas últimas duas semanas, esse negócio usou a inteligência artificial (IA) na produção de bens ou serviços? (Exemplos de IA: aprendizado de máquina, processamento de linguagem natural, agentes virtuais, reconhecimento de voz etc.)
- Nos seis meses seguintes, você acha que esse negócio usará a inteligência artificial (AI) na produção de bens ou serviços? (Exemplos de IA: aprendizado de máquina, processamento de linguagem natural, agentes virtuais, reconhecimento de voz etc.)
Ele se afastou por mais um pouco, adicionou este código ao script:
# Compute 6-survey rolling average (biweekly cadence → ~12 weeks) rolled = wide.rolling(window=6, min_periods=6).mean()
E exibi este gráfico (depois que eu disse para consertar a falha no título):

Eu acho que fez isso! Esta é uma combinação muito sólida para o original da Apollo, recriada usando matplotlib e pandas dos mesmos dados de origem subjacente do censo dos EUA.
Aqui está o código Python completo que escreveu, o que eu acho bastante legível (tanto quanto o código dos pandas pode ser):
import pandas as pd import matplotlib.pyplot as plt from matplotlib.ticker import PercentFormatter path = "/mnt/data/Employment Size Class.xlsx" resp = pd.read_excel(path, sheet_name="Response Estimates") dates = pd.read_excel(path, sheet_name="Collection and Reference Dates") is_current = resp("Question").astype(str).str.strip().str.startswith("In the last two weeks") ai_yes = resp(is_current & resp("Answer").astype(str).str.strip().str.lower().eq("yes")).copy() code_to_bucket = {"A":"1-4","B":"5-9","C":"10-19","D":"20-49","E":"50-99","F":"100-249","G":"250 or more employees"} ai_yes("Bucket") = ai_yes("Empsize").map(code_to_bucket) period_cols = (c for c in ai_yes.columns if str(c).isdigit() and len(str(c))==6) long = ai_yes.melt(id_vars=("Bucket"), value_vars=period_cols, var_name="Smpdt", value_name="value") dates("Smpdt") = dates("Smpdt").astype(str) long("Smpdt") = long("Smpdt").astype(str) merged = long.merge(dates(("Smpdt","Ref End")), on="Smpdt", how="left") merged("date") = pd.to_datetime(merged("Ref End"), errors="coerce") merged("value") = pd.to_numeric(long("value").astype(str).str.replace("%","",regex=False).str.strip(), errors="coerce") order = ("250 or more employees","100-249","50-99","20-49","10-19","5-9","1-4") wide = merged.pivot_table(index="date", columns="Bucket", values="value", aggfunc="mean").sort_index() wide = wide((c for c in order if c in wide.columns)) rolled = wide.rolling(window=6, min_periods=6).mean() start, end = pd.Timestamp("2023-11-01"), pd.Timestamp("2025-08-31") rolled_win = rolled.loc((rolled.index >= start) & (rolled.index <= end)) fig, ax = plt.subplots(figsize=(12, 6)) for col in order: if col in rolled_win.columns: ax.plot(rolled_win.index, rolled_win(col), label=col, linewidth=2) ax.set_title("AI adoption (last two weeks) — 6‑survey rolling average", pad=16) ax.yaxis.set_major_formatter(PercentFormatter(100)) ax.set_ylabel("%") ax.set_xlabel("") ax.grid(True, alpha=0.25, linestyle="--") ax.legend(title=None, loc="upper left", ncols=2, frameon=False) plt.tight_layout() png_path = "/mnt/data/ai_adoption_rolling6_by_firm_size.png" svg_path = "/mnt/data/ai_adoption_rolling6_by_firm_size.svg" plt.savefig(png_path, dpi=200, bbox_inches="tight") plt.savefig(svg_path, bbox_inches="tight")
Gosto de como gerou uma versão SVG do gráfico sem que eu o pedisse.
Você pode acessar a transcrição do ChatGPT para ver detalhes completos de tudo o que fez.
Renderização que traçará o lado do cliente usando Pyodide
Eu tive mais um desafio para experimentar. Eu poderia renderizar o mesmo gráfico inteiramente no navegador usando pyodide, que pode executar pandas e matplotlib?
Iniciei uma nova sessão ChatGPT GPT-5 e solicitei:
Build a canvas that loads Pyodide and uses it to render an example bar chart with pandas and matplotlib and then displays that on the page
Meu objetivo aqui era simplesmente ver se eu conseguia uma prova de conceito de um gráfico renderizado, idealmente usando o recurso de tela do ChatGPT. O Canvas é a versão do Claude de Artefatos de Claude, que permite que o modelo escreva e execute HTML e JavaScript diretamente na interface ChatGPT.
Funcionou! Aqui está a transcrição e aqui está o que me criou, exportado para minhas ferramentas.simonwillison.net Github Pages Site (código -fonte aqui).

Agora provei para mim mesmo que posso renderizar esses gráficos de Python diretamente no navegador. Próximo passo: recrie o gráfico da Apollo.
Eu sabia que precisaria de uma maneira de carregar a planilha que estava habilitada para CORS. Eu carreguei minha cópia para o meu /static/cors-allow/2025/... Diretório (configurado no S3 para servir os cabeçalhos do CORS), colados no código de consumo acabado de antecipadamente e disse ao ChatGPT:
Now update it to have less explanatory text and a less exciting design (black on white is fine) and run the equivalent of this:(… colado no código Python de anteriores …)
Load the XLSX sheet from https://static.simonwillison.net/static/cors-allow/2025/Employment-Size-Class-Sep-2025.xlsx
Não funcionou bem – eu recebi um erro sobre openpyxl que eu pesquisei manualmente a correção e solicitou:
Use await micropip.install("openpyxl") to install openpyxl - instead of using loadPackage
Eu tive que colar em outra mensagem de erro:
zipfile.BadZipFile: File is not a zip file
Então um sobre um SyntaxError: unmatched ')' e a TypeError: Legend.__init__() got an unexpected keyword argument 'ncols'-Capitando e colando mensagens de erro continua sendo uma parte frustrante, mas necessária do loop codificador de vibração.
… Mas com essas correções no lugar, o código resultante funcionou! Visite Tools.simonwillison.net/ai-adoption para ver o resultado final:

Aqui está o código para essa página, 170 linhas all-in de HTML, CSS, JavaScript e Python.
O que eu aprendi com isso
Essa foi outra daquelas investigações inspiradas em curiosidade que se transformaram em um conjunto de lições úteis.
- O GPT-5 é ótimo em rastrear dados do censo dos EUA, por mais difícil que seja o site deles para entender se você não trabalhar com seus dados com frequência
- Ele pode fazer um bom trabalho de transformar dados + uma captura de tela de um gráfico em uma recriação desse gráfico usando o intérprete de código, pandas e matplotlib
- A execução do Python + Matplotlib em um navegador via Pyodide é muito fácil e leva apenas algumas dezenas de linhas de código
- Buscar uma folha XLSX em Pyodide é apenas uma pequena etapa extra usando
pyfetcheopenpyxl:import micropip await micropip.install("openpyxl") from pyodide.http import pyfetch resp_fetch = await pyfetch(URL) wb_bytes = await resp_fetch.bytes() xf = pd.ExcelFile(io.BytesIO(wb_bytes), engine='openpyxl')
- Outro padrão novo para mim: você pode renderizar uma imagem ao DOM do código de pyodide como este:
from js import document document.getElementById('plot').src = 'data:image/png;base64,' + img_b64
Definitivamente estarei usando essas técnicas novamente no futuro.
Atualizar: Por coincidência, Claude lançou seu próprio equivalente atualizado ao intérprete de código ChatGPT no final do dia em que publiquei essa história, então publiquei o mesmo experimento de recreação de gráficos contra o Claude Sonnet 4 para ver como ele comparou.
