O DeepSeek V3.2 Speciale é um modelo de raciocínio de alta computação ajustado para fluxos de trabalho complexos e aprimorados por ferramentas. Em vez de só responder perguntas direto, ele foi feito pra planejar, raciocinar e coordenar ferramentas pra construir sistemas de análise de agentes.
Neste tutorial, vamos usar o DeepSeek V3.2 Speciale para criar um Agente Analista de Dados de IA que fica em cima de qualquer CSV. O fluxo é assim:
O usuário envia um arquivo CSV e faz uma pergunta em linguagem natural.
Um agente planejador converte a pergunta em um plano de análise JSON estruturado
Depois, algumas ferramentas Python executam o plano e geram tabelas/gráficos.
Finalmente, um agente explicativo transforma os números brutos em um resumo de insights.
No final, você vai ter um aplicativo Streamlit com planos bem claros e etapas de análise que dá pra repetir. Se você quiser saber mais sobre agentes de IA, recomendo dar uma olhada no programa de habilidades Fundamentos de Agentes de IA.
O que é o DeepSeek V3.2 Speciale?
O DeepSeek V3.2 Speciale é a versão com alta capacidade de computação e reforçada por aprendizado de reforço da família DeepSeek V3.2, projetada especialmente para raciocínio profundo, em vez de conversas casuais.
Ele leva o desempenho a um nível que chega a competir com modelos como o Gemini 3 Pro em tarefas complexas e até conseguiu medalhas de ouro em benchmarks como IMO, CMO, ICPC World Finals e IOI 2025.
O DeepSeek V3.2 Speciale é otimizado para:
Matemática avançada, lógica e raciocínio em várias etapas
Ele também dá suporte a fluxos de trabalho agênicos, nos quais o modelo planeja ações em vez de responder de uma só vez.
Assim como seus concorrentes, ele também suporta saídas estruturadas de contexto longo com raciocínio do tipo cadeia de pensamentos.
A V3.2 Speciale só dá suporte ao modo de pensamento e, por enquanto, não dá suporte à chamada de ferramentas pela API oficial. Não dá pra só mexer no temperature e achar que vai ter um JSON limpo logo de cara. O modelo Speciale vai pensar bastante e, muitas vezes, vai misturar seu raciocínio com a resposta final.
DeepSeek-V3.2-Projeto de exemplo especial: Agente Analista de Dados de IA
Nesta seção, vamos implementar um Agente Analista de Dados de IA com um modelo DeepSeek V3.2 Speciale integrado a um aplicativo Streamlit. Em resumo, eis o que o aplicativo final faz:
Carregue qualquer arquivo CSV. Você pode encontrar bons exemplos no Kaggle (como previsão de vendas, que usei nesta demonstração).
O aplicativo detecta automaticamente as colunas de data e adiciona campos auxiliares de ano, mês e ano_mês.
Você digita uma pergunta e o DeepSeek V3.2 Speciale age como um Agente Planejador que responde com um plano JSON:
quais colunas agrupar
quais métricas agregar
filtros opcionais (por exemplo, “Ano == 2019”)
se deve desenhar um gráfico de barras, gráfico de linhas ou gráfico circular
Um Data Worker Python puro executa o plano com pandas.
Um gerador de gráficos cria gráficos de barras/linhas/circulares com matplotlib e seaborn.
Um Agente Explicador resume o resultado em linguagem simples e destaca as principais conclusões.
Vamos construir passo a passo.
Passo 1: Pré-requisitos
Primeiro, instale as dependências principais e pegue uma chave API da plataforma API do DeepSeek:
Vamos usar algumas bibliotecas principais, como streamlit, para alimentar a interface interativa do aplicativo web, pandas para carregar e manipular dados CSV, matplotlib e seaborn para criar gráficos e visualizações. A biblioteca python-dotenv é usada para carregar variáveis de ambiente a partir de um arquivo .env, e o OpenAI como cliente para se comunicar com a API compatível com OpenAI do DeepSeek.
Depois, entre na plataforma da API DeepSeek, vá até a aba Chaves da API e clique em Criar uma nova chave da API.
Por fim, dá um nome à tua chave e copia a chave gerada.
Defina sua chave API DeepSeek como uma variável de ambiente:
Com as dependências instaladas, o próximo passo é colocá-las no nosso script e conectar o cliente DeepSeek que vai alimentar nossos agentes planejadores e explicadores.
import io
import json
import os
import re
from datetime import datetime
import matplotlib.pyplot as plt
import pandas as pd
import seaborn as sns
import streamlit as st
from dotenv import load_dotenv
from openai import OpenAI
plt.style.use('seaborn-v0_8-darkgrid')
sns.set_palette("husl")
load_dotenv()
DEEPSEEK_API_KEY = os.getenv("DEEPSEEK_API_KEY")ifnot DEEPSEEK_API_KEY:raise RuntimeError("Please set DEEPSEEK_API_KEY env variable.")
DEEPSEEK_BASE_URL = os.getenv("DEEPSEEK_BASE_URL","https://api.deepseek.com/v3.2_speciale_expires_on_20251215",)
client = OpenAI(
api_key=DEEPSEEK_API_KEY,
base_url=DEEPSEEK_BASE_URL,)Tecnologia
O bloco de código acima faz três coisas. Ele importa nossas bibliotecas principais, aplica um estilo de plotagem e carrega variáveis de ambiente de .env. Em seguida, ele lê DEEPSEEK_API_KEY, valida e constrói um cliente OpenAI apontado para o endpoint temporário V3.2 Speciale do DeepSeek, para que todas as chamadas LLM subsequentes passem pelo modelo correto.
Observe que o DeepSeek V3.2 Speciale está atualmente sendo servido a partir de um endpoint temporário que expira em 15 de dezembro de 2025. Depois disso, o URL de implantação pode mudar, mas o nome do modelo continuará sendo deepseek-reasoner. Para saber os pontos finais mais recentes e detalhes de uso, dá uma olhada na documentação oficial do DeepSeek.
Com o cliente configurado, vamos definir nossos dois agentes: um para planejar a análise e outro para explicar os resultados.
Passo 3: Agente Planejador
Com o cliente instalado, podemos criar o Planner Agent, que decide quais análises serão executadas com os dados. Em vez de deixar o modelo mexer diretamente no DataFrame, pedimos pra ele criar um plano JSON estruturado que nosso “trabalhador de dados” Python possa executar com segurança.
O planejador vê uma descrição em texto do conjunto de dados junto com a pergunta do usuário e retorna um objeto JSON descrevendo a operação, colunas agrupadas, filtros, métrica e tipo de gráfico.
defcall_planner_llm(schema_text:str, question:str)->tuple[dict,str]:
system_prompt ="""
You are a data analysis planner. Convert user questions into JSON plans.
JSON Structure (REQUIRED):
{
"operation": "group_by_summary",
"group_by": ["column_name"],
"filters": [],
"target_column": "column_to_analyze",
"metric": "sum",
"need_chart": true,
"chart_type": "bar"
}
Fields:
- operation: Always use "group_by_summary" (most flexible)
- group_by: Columns to group by (e.g., ["Product Name"] or ["Category", "Region"])
- filters: Optional filters, e.g., [{"column": "Year", "op": "==", "value": "2023"}]
- target_column: Column to aggregate (must exist in schema!)
- metric: One of: sum, mean, count, max, min
- need_chart: true (always show chart)
- chart_type: bar, line, or pie
Quick Rules:
- Use ONLY columns from the provided schema
- For "this year", look for year columns or use the latest year in data
- For "top N", use appropriate group_by and metric
- For comparisons, use filters to split groups
Think briefly, then output the complete JSON.
""".strip()
messages =[{"role":"system","content": system_prompt},{"role":"user","content":f"Dataset:\n{schema_text}\n\nQuestion:\n{question}\n\nReminder: After analyzing, output the complete JSON plan.",},]
resp = client.chat.completions.create(
model="deepseek-reasoner",
messages=messages,
max_tokens=8192,)
message = resp.choices[0].message
content = message.content or""
content = content.strip()
reasoning_content =getattr(message,'reasoning_content',None)or""
finish_reason = resp.choices[0].finish_reason
defextract_json_from_text(text:str)->dict|None:ifnot text:returnNonetry:return json.loads(text)except json.JSONDecodeError:pass
code_block_match = re.search(r'```(?:json)?\s*(\{[\s\S]*?\})\s*```', text, re.DOTALL)if code_block_match:try:return json.loads(code_block_match.group(1))except json.JSONDecodeError:passdeffind_all_json_objects(s):
objects =[]
depth =0
start_idx =None
in_string =False
escape_next =Falsefor i, char inenumerate(s):if escape_next:
escape_next =Falsecontinueif char =='\\':
escape_next =Truecontinueif char =='"'andnot in_string:
in_string =Trueelif char =='"'and in_string:
in_string =Falseelifnot in_string:if char =='{':if depth ==0:
start_idx = i
depth +=1elif char =='}':
depth -=1if depth ==0and start_idx isnotNone:
objects.append(s[start_idx:i+1])
start_idx =Nonereturn objects
for candidate in find_all_json_objects(text):try:
parsed = json.loads(candidate)ifisinstance(parsed,dict)andany(k in parsed for k in['operation','target_column','metric','group_by']):return parsed
except json.JSONDecodeError:continuefor i inrange(len(text)):if text[i]=='{':
decoder = json.JSONDecoder()try:
parsed, _ = decoder.raw_decode(text[i:])ifisinstance(parsed,dict)andany(k in parsed for k in['operation','target_column','metric','group_by']):return parsed
except json.JSONDecodeError:continuereturnNoneif reasoning_content:
plan = extract_json_from_text(reasoning_content)if plan isnotNone:return plan, reasoning_content
plan = extract_json_from_text(content)if plan isnotNone:return plan, reasoning_content
error_msg =(f"Planner returned non-JSON content.\n"f"Finish reason: {finish_reason}\n"f"Content received: {repr(content[:500])if content else'(empty)'}\n"f"Reasoning content length: {len(reasoning_content)if reasoning_content else0}\n"f"Reasoning content sample: {reasoning_content[:500]if reasoning_content else'(none)'}")if finish_reason =="length":
error_msg +="\n\nNote: Response was truncated due to token limit. The model didn't finish generating the JSON."raise ValueError(error_msg)Tecnologia
Primeiro, o system_prompt define o contrato para o Planner Agent, que transforma a pergunta do usuário em um plano JSON e especifica exatamente quais campos esperamos, como uma lista de colunas group_by, filters opcionais, um target_column, um metric e um chart_type.
Também adicionamos algumas heurísticas (como lidar com “este ano” ou “top N”) para que o modelo se comporte mais como um analista de dados júnior do que como um chatbot genérico.
Depois, criamos a mensagem do sistema que traz as instruções e junta duas coisas: uma descrição textual do esquema do conjunto de dados (nomes das colunas, tipos de dados, linhas de amostra) e a pergunta do usuário. Isso dá ao modelo contexto suficiente para escolher nomes de colunas válidos e uma agregação sensata para a pergunta que está sendo feita.
O DeepSeek V3.2 Speciale é então chamado através de client.chat.completions.create(). Como esse é um modelo de raciocínio, ele pode gerar dois canais de saída: uma sequência de caracteres visível e uma sequência interna de caracteres reasoning_content, onde geralmente fica a maior parte do “pensamento” e a resposta final. A gente pega os dois da resposta e fica de olho no finish_reason pra poder ver se tem algum truncamento.
O trabalho pesado rola dentro de uma função chamad extract_json_from_text(). Como os modelos de raciocínio nem sempre devolvem JSON limpo, a gente coloca isso em um markdown. Para deixar o planejador mais robusto, essa função auxiliar tenta várias estratégias em sequência:
Primeiro, ele tenta analisar toda a string com json.loads
Depois, ele procura por delimitadores de código JSON e analisa o conteúdo dentro deles.
Por fim, ele procura blocos equilibrados usando uma pequena rotina de correspondência de chaves e usa um decodificador JSON bruto.
Para cada candidato, só aceita objetos que pareçam um plano válido, ou seja, eles precisam ter pelo menos um dos campos operation, target_column, metric ou group_by.
Por fim, conectamos tudo aplicando uma função de extract_json_from_text() e a reasoning_content.
Juntas, essas peças transformam qualquer pergunta em linguagem natural e instantâneo de esquema em um plano de análise estruturado.
Passo 4: Agente explicador
Depois que o Data Worker faz a análise com o Pandas, mandamos a tabela de resultados junto com o plano JSON de volta para o DeepSeek e transformamos tudo em um resumo com insights concretos.
defcall_explainer_llm(question:str, plan:dict, result_summary:list)->tuple[str,str]:
system_prompt ="""
You are a senior data analyst explaining insights to business stakeholders.
The user asked a question about their CSV data.
Another agent already designed an analysis plan and we executed it in Python.
You will now explain the results in clear, engaging, non-technical language.
Requirements:
- Start with a direct 1-2 sentence answer to their question
- Use bullet points (3-5 points) to highlight key insights, trends, or comparisons
- Include specific numbers and percentages where relevant
- Use business-friendly language (avoid technical jargon like "aggregation", "groupby")
- If the data shows interesting patterns, point them out
- End with a brief recommendation or next step if appropriate
Keep it concise and actionable.
""".strip()
limited_summary = result_summary[:20]iflen(result_summary)>20else result_summary
user_content =f"""
User question:
{question}
Analysis performed:
{json.dumps(plan, indent=2)}
Results (top rows):
{json.dumps(limited_summary, indent=2)}
Total rows in result: {len(result_summary)}
""".strip()
messages =[{"role":"system","content": system_prompt},{"role":"user","content": user_content},]
resp = client.chat.completions.create(
model="deepseek-reasoner",
messages=messages,
max_tokens=2048,)
message = resp.choices[0].message
content = message.content or""
content = content.strip()
reasoning_content =getattr(message,'reasoning_content',None)or""ifnot content:if reasoning_content:
content = reasoning_content.strip()return(content if content else"Unable to generate explanation from the model response.",
reasoning_content)Tecnologia
O agente explicador começa definindo o system_prompt, que diz ao DeepSeek para agir como um analista de dados sênior conversando com os stakeholders do negócio. A gente especifica exatamente como a gente quer que a resposta seja, junto com outras dicas para escrever a resposta.
Depois, a gente prepara um user_content, que dá ao modelo todo o contexto que ele precisa. Passamos a pergunta original, o plano de análise JSON (para que ele saiba quais cálculos foram executados) e o número total de linhas.
Depois, montamos a lista de mensagens e chamamos o DeepSeek V3.2 Speciale pelo client.chat.completions.create(). Assim como no planejador, o modelo pode retornar texto tanto em content quanto em reasoning_content, então adicionamos ambos e voltamos para reasoning_content se content estiver vazio.
Por fim, a função retorna uma tupla que inclui tanto a explicação quanto a string de raciocínio bruto que aparece no expansor.
Com esse Agente Explicador instalado, o ciclo está completo:
O Agente Planejador decide o que calcular,
O Data Worker faz o plano com pandas e matplotlib, e
O Explainer Agent transforma os números em insights úteis.
Passo 5: Funções auxiliares
Antes de deixarmos o DeepSeek planejar qualquer coisa, precisamos descrever os dados de forma clara e torná-los fáceis de analisar. Isso é feito usando um monte de funções auxiliares.
Etapa 5.1 Planejador de esquema
O Planner Agent não consegue ver seu DataFrame diretamente, então a gente manda um resumo textual compacto do conjunto de dados.
Esse auxiliar faz um loop em todas as colunas. Também inclui alguns exemplos de valores para coisas como nomes de produtos, regiões ou categorias. F
Por fim, ele adiciona uma pequena tabela de marcação das primeiras linhas, para que o modelo tenha exemplos concretos para raciocinar.
Essa sequência de caracteres do esquema é como o planejador vê seus dados, permitindo que ele escolha nomes de colunas e agrupamentos válidos.
Etapa 5.2 Pré-processamento automático de datas
A gente detecta automaticamente as colunas de data e adiciona campos auxiliares como _year e _year_month, o que facilita para o DeepSeek responder a perguntas como “no ano passado” ou “por mês”.
defpreprocess_dates(df: pd.DataFrame)-> pd.DataFrame:
df = df.copy()
date_columns =[]for col in df.columns:if pd.api.types.is_datetime64_any_dtype(df[col]):
date_columns.append(col)continueifany(x in col.lower()for x in['date','time','day']):try:
df[col]= pd.to_datetime(df[col], errors='coerce')if df[col].notna().sum()>0:
date_columns.append(col)except:passfor col in date_columns:if col in df.columns and pd.api.types.is_datetime64_any_dtype(df[col]):
df[f'{col}_year']= df[col].dt.year
df[f'{col}_month']= df[col].dt.month
df[f'{col}_year_month']= df[col].dt.to_period('M').astype(str)return dfTecnologia
Primeiro, a gente dá uma olhada nas colunas e, se uma coluna já for datetime ou o nome dela der a entender que é uma data (tipo order_date ou day), a gente tenta analisá-la com pd.to_datetime. Para cada coluna de data, criamos recursos como _year, _month e _year_month.
Esse pré-processamento significa que o planejador pode consultar com segurança as colunas year e year_month sem que você precise criar manualmente recursos de tempo para cada conjunto de dados.
Passo 5.3 Aplicação do filtro
O planejador pode adicionar filtros de linha simples ao plano, e esse auxiliar transforma esses filtros em filtros pandas.
defapply_filters(df: pd.DataFrame, filters:list)-> pd.DataFrame:ifnot filters:return df
filtered = df.copy()for f in filters:
col = f.get("column")
op = f.get("op")
val = f.get("value")if col notin filtered.columns:continuetry:
val_cast = pd.to_numeric(val)except Exception:
val_cast = val
if op =="==":
filtered = filtered[filtered[col]== val_cast]elif op =="!=":
filtered = filtered[filtered[col]!= val_cast]elif op ==">":
filtered = filtered[filtered[col]> val_cast]elif op =="<":
filtered = filtered[filtered[col]< val_cast]elif op ==">=":
filtered = filtered[filtered[col]>= val_cast]elif op =="<=":
filtered = filtered[filtered[col]<= val_cast]elif op =="contains":
filtered = filtered[filtered[col].astype(str).str.contains(str(val_cast),case=False, na=False)]return filteredTecnologia
Para cada filtro, a gente verifica se a coluna existe e, se possível, transforma o valor em um número. Depois, faz a comparação certa. Todos os filtros são aplicados um atrás do outro, então você pode juntar condições como “Região contém Oeste” e “Ano >= 2021”.
Essa função é o que conecta as restrições de linguagem natural do plano aos subconjuntos de linhas.
Passo 5.4: Plano de análise
Agora vamos implementar o Data Worker, que é uma camada fina que lê o plano JSON e executa as agregações pandas correspondentes.
Começamos desmembrando o plano com operação, coluna de destino, colunas de agrupamento, filtros e parâmetros métricos. T
Então, os filtros são aplicados através da função ` apply_filters() `. Se o plano fizer referência a uma coluna inválida, voltaremos a retornar uma pré-visualização simples.
Caso contrário, para operações suportadas, agregamos toda a tabela ou executamos um agrupamento seguido de operações como soma, média, contagem, máximo ou mínimo, e classificamos o resultado pela coluna de métrica.
Esse é o ponto principal da camada de ferramentas: o LLM decide o que calcular, e essa função decide como fazer isso de forma segura com o pandas.
Passo 5.5: Gerador de gráficos
Por fim, transformamos a tabela resultante em um gráfico que combina com o plano chart_type, para que tenhamos números e recursos visuais na saída.
Lemos chart_type, group_by e target_column a partir do plano e criamos uma figura Matplotlib. A função generate_chart() acima retorna um buffer PNG na memória que o aplicativo Streamlit exibe ao lado das principais métricas.
Com essas funções auxiliares em funcionamento, o resto do sistema fica bem mais simples. O Planner usa get_schema_description para projetar a análise, o Data Worker usa as funções preprocess_dates(), apply_filters() e run_analysis_plan() para processar os números, e a função generate_chart() transforma a tabela final em um gráfico.
Passo 6: Interface do usuário Streamlit
Agora que temos as funções planejador, trabalhador de dados, explicador e auxiliar em funcionamento, podemos reunir tudo em um aplicativo Streamlit.
st.set_page_config(
page_title="AI Data Analyst Agent",
page_icon="📊",
layout="wide",
initial_sidebar_state="expanded")
st.markdown("""
<style>
.main-header {
font-weight: 700;
text-align: center;
}
.sub-header {
text-align: center;
}
.metric-card {
background-
border-radius: 0.5rem;
border-left: 4px solid #1f77b4;
}
.insight-box {
background-
border-radius: 0.5rem;
border-left: 4px solid #2ecc71;
}
</style>
""", unsafe_allow_html=True)
st.markdown("<h1 class='main-header'>AI Data Analyst Agent</h1>", unsafe_allow_html=True)
uploaded_file = st.file_uploader("Upload CSV file",type=["csv"],help="Upload any CSV file to get started")if uploaded_file isnotNone:try:
df = pd.read_csv(uploaded_file)
df = preprocess_dates(df)except Exception as e:
st.error(f"Error loading CSV: {e}")
st.stop()with st.expander("Preview Data", expanded=False):
col1, col2, col3 = st.columns(3)
col1.metric("Total Rows",f"{len(df):,}")
col2.metric("Total Columns",len(df.columns))
col3.metric("Memory Usage",f"{df.memory_usage(deep=True).sum()/1024**2:.1f} MB")
st.dataframe(df.head(100), width='stretch', height=300)
st.markdown("**Numeric Columns Summary:**")
numeric_cols = df.select_dtypes(include=['number']).columns
iflen(numeric_cols)>0:
st.dataframe(df[numeric_cols].describe(), width='stretch')
st.markdown("---")
col1, col2 = st.columns([4,1])with col1:
question = st.text_input(" Ask a question about your data",
placeholder="e.g., Which product category had the highest sales last year?",
label_visibility="collapsed")with col2:
analyze_button = st.button("Analyze",type="primary", width='stretch')if analyze_button and question.strip():with st.spinner("Analyzing data..."):
schema_text = get_schema_description(df)try:
plan, planner_reasoning = call_planner_llm(schema_text, question)except Exception as e:
st.error(f" Planner agent failed: {e}")
st.stop()with st.expander(" Analysis Plan", expanded=False):
col1, col2 = st.columns(2)with col1:
st.json(plan)with col2:if planner_reasoning:
st.markdown("**AI Reasoning Process:**")
st.text_area("Planner Reasoning", planner_reasoning[:1000]+"..."iflen(planner_reasoning)>1000else planner_reasoning,
height=200, label_visibility="collapsed")try:
result_df = run_analysis_plan(df, plan)except Exception as e:
st.error(f" Error running analysis: {e}")
st.info(" Tip: Try rephrasing your question or be more specific about the columns you want to analyze.")
st.stop()
st.markdown("---")
st.markdown("## Results")
chart_buf = generate_chart(result_df, plan)if chart_buf isnotNone:
col1, col2 = st.columns([2,1])with col1:
st.image(chart_buf)with col2:
st.markdown("### Key Metrics")
target_col = plan.get("target_column")if target_col in result_df.columns:
st.metric("Total",f"{result_df[target_col].sum():,.2f}")
st.metric("Average",f"{result_df[target_col].mean():,.2f}")
st.metric("Max",f"{result_df[target_col].max():,.2f}")
st.metric("Min",f"{result_df[target_col].min():,.2f}")else:
st.info("Chart generation skipped (not applicable for this query)")with st.expander("Results Table", expanded=True):
st.dataframe(result_df, width='stretch', height=400)
csv_data = result_df.to_csv(index=False)
st.download_button(
label="Download Results as CSV",
data=csv_data,
file_name=f"analysis_results_{datetime.now().strftime('%Y%m%d_%H%M%S')}.csv",
mime="text/csv")with st.spinner("Generating insights..."):
result_df_serializable = result_df.copy()for col in result_df_serializable.columns:if pd.api.types.is_datetime64_any_dtype(result_df_serializable[col]):
result_df_serializable[col]= result_df_serializable[col].astype(str)elif pd.api.types.is_period_dtype(result_df_serializable[col]):
result_df_serializable[col]= result_df_serializable[col].astype(str)
result_summary = result_df_serializable.to_dict(orient="records")
explanation, explainer_reasoning = call_explainer_llm(
question=question,
plan=plan,
result_summary=result_summary,)
st.markdown("---")
st.markdown("## AI Insights")
st.markdown(f'<div class="insight-box">{explanation}</div>', unsafe_allow_html=True)if explainer_reasoning:with st.expander(" AI Reasoning Process", expanded=False):
st.text_area("Explainer Reasoning", explainer_reasoning[:1500]+"..."iflen(explainer_reasoning)>1500else explainer_reasoning,
height=300, label_visibility="collapsed")Tecnologia
Na parte superior, a gente configura a página com st.set_page_config e CSS para estilizar o painel. Primeiro, o usuário faz o upload de um CSV, que a gente carrega em um DataFrame, passa por um preprocess_dates e mostra dentro de um expansorde dadosPreview Data com contagem de linhas/colunas, uso de memória e um resumo rápido.
Nos bastidores, criamos um esquema com a função get_schema_description(), chamamos call_planner_llm para obter um plano JSON e mostramos tanto o plano quanto o raciocínio do modelo em um expansor. O Data Worker então executa o plano com o pandas, e a seçãoResultados do mostra um gráfico do generate_chart junto com as principais métricas.
Por fim, chamamos call_explainer_llm com a pergunta, o plano e o resumo dos resultados para gerar uma explicação para o caixa AI Insights , com um Expansor do Processo de Raciocínio da IA para quem quiser dar uma olhada nos bastidores.
No vídeo abaixo, você pode ver uma versão resumida do fluxo de trabalho em ação:
Conclusão
Neste tutorial, criamos um aplicativo Streamlit que pega qualquer CSV, descreve-o para o modelo, pede ao modelo DeepSeek V3.2 Speciale para criar um plano de análise JSON, executa esse plano com pandas, visualiza a saída com Matplotlib/Seaborn e, em seguida, transforma os resultados em insights fáceis de entender.
A partir daqui, você pode estender a mesma arquitetura para warehouse SQL, arquivos Parquet ou até mesmo uma pilha BI completa. Simples, troque o carregador CSV por um conector de banco de dados, adicione novas operações ou conecte outros modelos de raciocínio.
Perguntas frequentes sobre o DeepSeek V3.2 Speciale
Posso usar um modelo diferente em vez do DeepSeek V3.2 Speciale?⌄
A arquitetura é independente do modelo, desde que ele siga as instruções e gere JSON estruturado. Você pode trocar por qualquer modelo compatível com OpenAI, basta atualizar o nome base_url e model no cliente.
Que tipo de perguntas esse Agente Analista de Dados de IA lida melhor?⌄
A configuração atual é mais forte para análises descritivas, como resumos agrupados, comparações, filtros básicos e agregações simples. Não é feito pra consultas SQL aleatórias, mas dá pra estender o esquema JSON e o run_analysis_plan() pra dar suporte a operações mais complexas.
Qual é o tamanho máximo que meu CSV pode ter antes de travar?⌄
O que limita não é só o modelo, mas também os pandas e a memória. O aplicativo vai lidar com conjuntos de dados pequenos a médios, dependendo do seu hardware. Se você estiver trabalhando com tabelas muito grandes, considere reduzir a resolução, pré-agregar ou trocar a camada CSV/pandas por um banco de dados.
É seguro usar isso com dados confidenciais?⌄
Por padrão, todos os dados que você carrega são enviados para a API do DeepSeek quando você descreve o esquema e os resultados para o modelo. Para conjuntos de dados sensíveis ou regulamentados, você deve tentar tornar as colunas anônimas, evitar enviar valores brutos além do necessário e hospedar um modelo de raciocínio compatível localmente.
Por que não perguntar diretamente à modelo em vez de usar vários agentes?⌄
Você pode mandar o CSV bruto direto pro modelo, mas perde a capacidade de reproduzir e controlar. Ao dividir o fluxo de trabalho em um Planejador (plano JSON), Trabalhador de Dados (execução pandas) e Explicador (insights em linguagem natural), cada etapa fica transparente, fácil de depurar e auditar.
Sou Especialista Google Developers em ML (Gen AI), tricampeã no Kaggle e Embaixadora Women Techmakers, com mais de três anos de experiência na área de tecnologia. Cofundei uma startup de saúde em 2020 e atualmente faço um mestrado em ciência da computação na Georgia Tech, com foco em aprendizado de máquina.
Aprenda habilidades essenciais de analista de dados, tanto técnicas quanto interpessoais, desde programação em Python até comunicação eficaz, para avançar em sua carreira.
O DeepSeek-Coder-V2 é um modelo de linguagem de código de código aberto que rivaliza com o desempenho do GPT-4, Gemini 1.5 Pro, Claude 3 Opus, Llama 3 70B ou Codestral.
Saiba como realizar a validação de dados e modelos para garantir um desempenho robusto de machine learning usando nosso guia passo a passo para automatizar testes com o DeepChecks.
Uma visão geral abrangente da API Assistants com nosso artigo, que oferece uma análise aprofundada de seus recursos, usos no setor, orientação de configuração e práticas recomendadas para maximizar seu potencial em vários aplicativos de negócios.
Este tutorial sobre o Streamlit foi criado para ajudar cientistas de dados ou engenheiros de aprendizado de máquina que não são desenvolvedores da Web e não estão interessados em passar semanas aprendendo a usar essas estruturas para criar aplicativos da Web.
O DeepSeek V3.2 Speciale é um modelo de raciocínio de alta computação ajustado para fluxos de trabalho complexos e aprimorados por ferramentas. Em vez de só responder perguntas direto, ele foi feito pra planejar, raciocinar e coordenar ferramentas pra construir sistemas de análise de agentes.
Neste tutorial, vamos usar o DeepSeek V3.2 Speciale para criar um Agente Analista de Dados de IA que fica em cima de qualquer CSV. O fluxo é assim:
No final, você vai ter um aplicativo Streamlit com planos bem claros e etapas de análise que dá pra repetir. Se você quiser saber mais sobre agentes de IA, recomendo dar uma olhada no programa de habilidades Fundamentos de Agentes de IA.
O que é o DeepSeek V3.2 Speciale?
O DeepSeek V3.2 Speciale é a versão com alta capacidade de computação e reforçada por aprendizado de reforço da família DeepSeek V3.2, projetada especialmente para raciocínio profundo, em vez de conversas casuais.
Ele leva o desempenho a um nível que chega a competir com modelos como o Gemini 3 Pro em tarefas complexas e até conseguiu medalhas de ouro em benchmarks como IMO, CMO, ICPC World Finals e IOI 2025.
O DeepSeek V3.2 Speciale é otimizado para:
A V3.2 Speciale só dá suporte ao modo de pensamento e, por enquanto, não dá suporte à chamada de ferramentas pela API oficial. Não dá pra só mexer no
temperaturee achar que vai ter um JSON limpo logo de cara. O modelo Speciale vai pensar bastante e, muitas vezes, vai misturar seu raciocínio com a resposta final.DeepSeek-V3.2-Projeto de exemplo especial: Agente Analista de Dados de IA
Nesta seção, vamos implementar um Agente Analista de Dados de IA com um modelo DeepSeek V3.2 Speciale integrado a um aplicativo Streamlit. Em resumo, eis o que o aplicativo final faz:
Vamos construir passo a passo.
Passo 1: Pré-requisitos
Primeiro, instale as dependências principais e pegue uma chave API da plataforma API do DeepSeek:
Vamos usar algumas bibliotecas principais, como streamlit, para alimentar a interface interativa do aplicativo web, pandas para carregar e manipular dados CSV, matplotlib e seaborn para criar gráficos e visualizações. A biblioteca python-dotenv é usada para carregar variáveis de ambiente a partir de um arquivo .env, e o OpenAI como cliente para se comunicar com a API compatível com OpenAI do DeepSeek.
Depois, entre na plataforma da API DeepSeek, vá até a aba Chaves da API e clique em Criar uma nova chave da API.
Por fim, dá um nome à tua chave e copia a chave gerada.
Defina sua chave API DeepSeek como uma variável de ambiente:
Agora nosso ambiente está pronto.
Passo 2: Importações e cliente DeepSeek
Com as dependências instaladas, o próximo passo é colocá-las no nosso script e conectar o cliente DeepSeek que vai alimentar nossos agentes planejadores e explicadores.
O bloco de código acima faz três coisas. Ele importa nossas bibliotecas principais, aplica um estilo de plotagem e carrega variáveis de ambiente de
.env. Em seguida, ele lêDEEPSEEK_API_KEY, valida e constrói um cliente OpenAI apontado para o endpoint temporário V3.2 Speciale do DeepSeek, para que todas as chamadas LLM subsequentes passem pelo modelo correto.Observe que o DeepSeek V3.2 Speciale está atualmente sendo servido a partir de um endpoint temporário que expira em 15 de dezembro de 2025. Depois disso, o URL de implantação pode mudar, mas o nome do modelo continuará sendo
deepseek-reasoner. Para saber os pontos finais mais recentes e detalhes de uso, dá uma olhada na documentação oficial do DeepSeek.Com o cliente configurado, vamos definir nossos dois agentes: um para planejar a análise e outro para explicar os resultados.
Passo 3: Agente Planejador
Com o cliente instalado, podemos criar o Planner Agent, que decide quais análises serão executadas com os dados. Em vez de deixar o modelo mexer diretamente no DataFrame, pedimos pra ele criar um plano JSON estruturado que nosso “trabalhador de dados” Python possa executar com segurança.
O planejador vê uma descrição em texto do conjunto de dados junto com a pergunta do usuário e retorna um objeto JSON descrevendo a operação, colunas agrupadas, filtros, métrica e tipo de gráfico.
Primeiro, o
system_promptdefine o contrato para o Planner Agent, que transforma a pergunta do usuário em um plano JSON e especifica exatamente quais campos esperamos, como uma lista de colunasgroup_by,filtersopcionais, umtarget_column, ummetrice umchart_type.Também adicionamos algumas heurísticas (como lidar com “este ano” ou “top N”) para que o modelo se comporte mais como um analista de dados júnior do que como um chatbot genérico.
Depois, criamos a mensagem do sistema que traz as instruções e junta duas coisas: uma descrição textual do esquema do conjunto de dados (nomes das colunas, tipos de dados, linhas de amostra) e a pergunta do usuário. Isso dá ao modelo contexto suficiente para escolher nomes de colunas válidos e uma agregação sensata para a pergunta que está sendo feita.
O DeepSeek V3.2 Speciale é então chamado através de
client.chat.completions.create(). Como esse é um modelo de raciocínio, ele pode gerar dois canais de saída: uma sequência de caracteres visível e uma sequência interna de caracteresreasoning_content, onde geralmente fica a maior parte do “pensamento” e a resposta final. A gente pega os dois da resposta e fica de olho nofinish_reasonpra poder ver se tem algum truncamento.O trabalho pesado rola dentro de uma função chamad
extract_json_from_text(). Como os modelos de raciocínio nem sempre devolvem JSON limpo, a gente coloca isso em um markdown. Para deixar o planejador mais robusto, essa função auxiliar tenta várias estratégias em sequência:json.loadsPara cada candidato, só aceita objetos que pareçam um plano válido, ou seja, eles precisam ter pelo menos um dos campos
operation,target_column,metricougroup_by.Por fim, conectamos tudo aplicando uma função de
extract_json_from_text()e areasoning_content.Juntas, essas peças transformam qualquer pergunta em linguagem natural e instantâneo de esquema em um plano de análise estruturado.
Passo 4: Agente explicador
Depois que o Data Worker faz a análise com o Pandas, mandamos a tabela de resultados junto com o plano JSON de volta para o DeepSeek e transformamos tudo em um resumo com insights concretos.
O agente explicador começa definindo o
system_prompt, que diz ao DeepSeek para agir como um analista de dados sênior conversando com os stakeholders do negócio. A gente especifica exatamente como a gente quer que a resposta seja, junto com outras dicas para escrever a resposta.Depois, a gente prepara um
user_content, que dá ao modelo todo o contexto que ele precisa. Passamos a pergunta original, o plano de análise JSON (para que ele saiba quais cálculos foram executados) e o número total de linhas.Depois, montamos a lista de mensagens e chamamos o DeepSeek V3.2 Speciale pelo
client.chat.completions.create(). Assim como no planejador, o modelo pode retornar texto tanto emcontentquanto emreasoning_content, então adicionamos ambos e voltamos parareasoning_contentsecontentestiver vazio.Por fim, a função retorna uma tupla que inclui tanto a explicação quanto a string de raciocínio bruto que aparece no expansor.
Com esse Agente Explicador instalado, o ciclo está completo:
Passo 5: Funções auxiliares
Antes de deixarmos o DeepSeek planejar qualquer coisa, precisamos descrever os dados de forma clara e torná-los fáceis de analisar. Isso é feito usando um monte de funções auxiliares.
Etapa 5.1 Planejador de esquema
O Planner Agent não consegue ver seu DataFrame diretamente, então a gente manda um resumo textual compacto do conjunto de dados.
Esse auxiliar faz um loop em todas as colunas. Também inclui alguns exemplos de valores para coisas como nomes de produtos, regiões ou categorias. F
Por fim, ele adiciona uma pequena tabela de marcação das primeiras linhas, para que o modelo tenha exemplos concretos para raciocinar.
Essa sequência de caracteres do esquema é como o planejador vê seus dados, permitindo que ele escolha nomes de colunas e agrupamentos válidos.
Etapa 5.2 Pré-processamento automático de datas
A gente detecta automaticamente as colunas de data e adiciona campos auxiliares como
_yeare_year_month, o que facilita para o DeepSeek responder a perguntas como “no ano passado” ou “por mês”.Primeiro, a gente dá uma olhada nas colunas e, se uma coluna já for datetime ou o nome dela der a entender que é uma data (tipo
order_dateouday), a gente tenta analisá-la compd.to_datetime. Para cada coluna de data, criamos recursos como_year,_monthe_year_month.Esse pré-processamento significa que o planejador pode consultar com segurança as colunas
yeareyear_monthsem que você precise criar manualmente recursos de tempo para cada conjunto de dados.Passo 5.3 Aplicação do filtro
O planejador pode adicionar filtros de linha simples ao plano, e esse auxiliar transforma esses filtros em filtros pandas.
Para cada filtro, a gente verifica se a coluna existe e, se possível, transforma o valor em um número. Depois, faz a comparação certa. Todos os filtros são aplicados um atrás do outro, então você pode juntar condições como “Região contém Oeste” e “Ano >= 2021”.
Essa função é o que conecta as restrições de linguagem natural do plano aos subconjuntos de linhas.
Passo 5.4: Plano de análise
Agora vamos implementar o Data Worker, que é uma camada fina que lê o plano JSON e executa as agregações pandas correspondentes.
Começamos desmembrando o plano com operação, coluna de destino, colunas de agrupamento, filtros e parâmetros métricos. T
Então, os filtros são aplicados através da função `
apply_filters()`. Se o plano fizer referência a uma coluna inválida, voltaremos a retornar uma pré-visualização simples.Caso contrário, para operações suportadas, agregamos toda a tabela ou executamos um agrupamento seguido de operações como soma, média, contagem, máximo ou mínimo, e classificamos o resultado pela coluna de métrica.
Esse é o ponto principal da camada de ferramentas: o LLM decide o que calcular, e essa função decide como fazer isso de forma segura com o pandas.
Passo 5.5: Gerador de gráficos
Por fim, transformamos a tabela resultante em um gráfico que combina com o plano
chart_type, para que tenhamos números e recursos visuais na saída.Lemos
chart_type,group_byetarget_columna partir do plano e criamos uma figura Matplotlib. A funçãogenerate_chart()acima retorna um buffer PNG na memória que o aplicativo Streamlit exibe ao lado das principais métricas.Com essas funções auxiliares em funcionamento, o resto do sistema fica bem mais simples. O Planner usa
get_schema_descriptionpara projetar a análise, o Data Worker usa as funçõespreprocess_dates(),apply_filters()erun_analysis_plan()para processar os números, e a funçãogenerate_chart()transforma a tabela final em um gráfico.Passo 6: Interface do usuário Streamlit
Agora que temos as funções planejador, trabalhador de dados, explicador e auxiliar em funcionamento, podemos reunir tudo em um aplicativo Streamlit.
Na parte superior, a gente configura a página com
st.set_page_confige CSS para estilizar o painel. Primeiro, o usuário faz o upload de um CSV, que a gente carrega em um DataFrame, passa por umpreprocess_datese mostra dentro de um expansorde dados Preview Data com contagem de linhas/colunas, uso de memória e um resumo rápido.Nos bastidores, criamos um esquema com a função
get_schema_description(), chamamoscall_planner_llmpara obter um plano JSON e mostramos tanto o plano quanto o raciocínio do modelo em um expansor. O Data Worker então executa o plano com o pandas, e a seçãoResultados do mostra um gráfico dogenerate_chartjunto com as principais métricas.Por fim, chamamos
call_explainer_llmcom a pergunta, o plano e o resumo dos resultados para gerar uma explicação para o caixa AI Insights , com um Expansor do Processo de Raciocínio da IA para quem quiser dar uma olhada nos bastidores.Salve tudo como
app.pye execute:No vídeo abaixo, você pode ver uma versão resumida do fluxo de trabalho em ação: