Como criar um analista de dados de IA totalmente local com OpenClaw e Ollama

Como criar um analista de dados de IA totalmente local com OpenClaw e Ollama
Neste tutorial, você vai montar um analista de dados de IA 100% local, capaz de:
ler arquivos CSV, Excel e JSON;
analisar métricas e tendências sem enviar dados para a nuvem;
gerar um gráfico automaticamente;
criar um relatório em Markdown com insights;
usar o OpenClaw como camada de orquestração e o Ollama como modelo local.
O objetivo é construir uma base sólida, compreensível tanto para quem está começando quanto para quem já trabalha com dados, automação ou IA local.
O que você vai construir
Ao final, você terá um projeto local com esta lógica:
Você fornece um arquivo de dados.
O OpenClaw recebe o comando do usuário e dispara o fluxo.
Um script Python faz a leitura do dataset, encontra colunas relevantes, cria visualizações e monta um relatório.
O Ollama entra como motor local de raciocínio e resumo.
Todos os arquivos são gerados no seu computador, sem depender de APIs externas.
Arquivos de saída esperados
trend_chart.png— gráfico gerado automaticamente;analysis_report.md— relatório com KPIs, observações e resumo;tool_trace.json— trilha de execução para auditoria.
Arquitetura do projeto
ComponenteFunçãoOpenClawRecebe o pedido, organiza a execução e chama as ferramentas locais.OllamaExecuta o modelo de linguagem localmente, sem enviar prompts para a nuvem.PythonLê, processa e resume os dados; também gera gráficos e relatórios.Pandas + MatplotlibTratamento tabular e visualização de dados.
Em termos simples: OpenClaw pensa a execução do fluxo, Ollama responde localmente e Python faz o trabalho analítico.
Ferramentas necessárias e links oficiais
Abaixo estão os links oficiais das ferramentas mencionadas neste tutorial:
OpenClaw: Agente local que orquestra o fluxo - https://openclaw.ai/
Documentação OpenClaw: Instalação e configuração - https://docs.openclaw.ai/
Ollama: Execução local de modelos - https://ollama.com/download
Biblioteca de modelos Ollama: Escolha e download de modelos - https://ollama.com/library
Modelo Qwen3: Modelo local sugerido neste tutorial - https://ollama.com/library/qwen3
Node.js Runtime: exigido pelo OpenClaw - https://nodejs.org/en/download
Python: Motor do script analítico - https://www.python.org/downloads/
Requisitos mínimos recomendados
Sistema operacional: Windows, macOS ou Linux;
Windows: prefira WSL2 para ter menos atrito com OpenClaw;
Node.js: versão 24 LTS de preferência;
Python: 3.11 ou superior;
Espaço em disco: pelo menos alguns GB livres para modelos e ambiente virtual;
Memória: quanto maior o modelo, maior a necessidade de RAM/VRAM.
Para começar com bom equilíbrio entre qualidade e consumo de recursos, este tutorial usa o modelo qwen3:8b.
Etapa 1: instalar o Python
Baixe e instale o Python pela página oficial:
https://www.python.org/downloads/
No Windows, marque a opção Add Python to PATH durante a instalação.
Como verificar
python --versionou, em alguns sistemas:
python3 --versionEtapa 2: instalar o Node.js
O OpenClaw precisa do Node.js. Baixe a versão LTS oficial:
https://nodejs.org/en/download
Como verificar
node --version npm --versionEtapa 3: instalar o Ollama
Baixe o instalador oficial do Ollama:
Depois, confira se tudo está funcionando:
ollama --versionInicie o serviço do Ollama
Em muitos sistemas, basta abrir o Ollama. Se quiser iniciar via terminal:
ollama serveSe o serviço estiver ativo, a API local ficará disponível em:
http://localhost:11434Etapa 4: baixar um modelo local
Agora vamos baixar um modelo que servirá como “cérebro” do seu analista local.
ollama pull qwen3:8bDepois, confira os modelos instalados:
ollama listPágina oficial do modelo: https://ollama.com/library/qwen3
Etapa 5: instalar o OpenClaw
Você pode usar o instalador oficial.
macOS / Linux / WSL2
curl -fsSL https://openclaw.ai/install.sh | bashWindows PowerShell
iwr -useb https://openclaw.ai/install.ps1 | iexDepois, rode o onboarding:
openclaw onboard --install-daemonVerificação
openclaw doctor openclaw gateway statusDurante o onboarding, escolha a opção de usar Ollama local como provider principal.
Etapa 6: criar a estrutura do projeto
Crie uma pasta para o seu analista local:
mkdir local-data-analyst cd local-data-analystEstrutura sugerida:
local-data-analyst/ ├── data/ ├── docs/ ├── output/ ├── requirements.txt ├── main.py └── SKILL.mdEtapa 7: criar o ambiente Python
macOS / Linux / WSL2
python3 -m venv .venv source .venv/bin/activateWindows PowerShell
python -m venv .venv .venv\Scripts\Activate.ps1Arquivo requirements.txt
pandas matplotlib openpyxl tabulateInstalar dependências
pip install -r requirements.txtEtapa 8: criar o motor de análise em Python
Agora vem a parte central do projeto: o script que vai abrir o dataset, encontrar tendências, gerar um gráfico e montar um relatório.
Arquivo main.py
import argparse import json from pathlib import Path from urllib import request import pandas as pd import matplotlib.pyplot as plt def log_event(events, stage, action, detail): events.append({ "stage": stage, "action": action, "detail": detail }) def load_tabular_data(data_path: Path, events): ext = data_path.suffix.lower() if ext == ".csv": df = pd.read_csv(data_path) elif ext in {".tsv", ".tab"}: df = pd.read_csv(data_path, sep="\\t") elif ext in {".json", ".jsonl"}: try: df = pd.read_json(data_path) except ValueError: df = pd.read_json(data_path, lines=True) elif ext in {".xlsx", ".xls"}: df = pd.read_excel(data_path) else: raise ValueError(f"Formato não suportado: {ext}") log_event(events, "fs", "read", f"Arquivo carregado: {data_path.name}") return df def read_context_docs(docs_dir: Path, events): texts = [] if not docs_dir.exists(): return "" for file in docs_dir.iterdir(): if file.is_file() and file.suffix.lower() in {".txt", ".md"}: texts.append(f"## {file.name}\\n" + file.read_text(encoding="utf-8", errors="ignore")) log_event(events, "docs", "read", f"Documento lido: {file.name}") return "\\n\\n".join(texts).strip() def infer_date_column(df: pd.DataFrame): for col in df.columns: converted = pd.to_datetime(df[col], errors="coerce") if converted.notna().sum() >= max(3, len(df) // 3): return col, converted return None, None def infer_numeric_column(df: pd.DataFrame): numeric_cols = df.select_dtypes(include="number").columns.tolist() return numeric_cols[0] if numeric_cols else None def build_chart(df: pd.DataFrame, x_col: str, y_col: str, output_file: Path, events): plt.figure(figsize=(12, 6)) x_is_date = False converted = pd.to_datetime(df[x_col], errors="coerce") if converted.notna().sum() >= max(3, len(df) // 3): temp = df.copy() temp[x_col] = converted temp = temp.dropna(subset=[x_col, y_col]) grouped = temp.groupby(temp[x_col].dt.to_period("M"))[y_col].sum().reset_index() grouped[x_col] = grouped[x_col].astype(str) plt.plot(grouped[x_col], grouped[y_col], marker="o") x_is_date = True else: temp = df[[x_col, y_col]].dropna().groupby(x_col)[y_col].sum().reset_index() temp = temp.sort_values(y_col, ascending=False).head(15) plt.bar(temp[x_col].astype(str), temp[y_col]) plt.title(f"Tendência de {y_col} por {x_col}") plt.xlabel(x_col) plt.ylabel(y_col) plt.xticks(rotation=45, ha="right") plt.tight_layout() plt.savefig(output_file, dpi=150) plt.close() if x_is_date: log_event(events, "chart", "create", f"Gráfico temporal salvo em {output_file.name}") else: log_event(events, "chart", "create", f"Gráfico categórico salvo em {output_file.name}") def ollama_generate(model: str, prompt: str): url = "http://localhost:11434/api/generate" payload = json.dumps({ "model": model, "prompt": prompt, "stream": False }).encode("utf-8") req = request.Request( url, data=payload, headers={"Content-Type": "application/json"} ) with request.urlopen(req, timeout=120) as resp: body = json.loads(resp.read().decode("utf-8")) return str(body.get("response", "")).strip() def main(): parser = argparse.ArgumentParser() parser.add_argument("--docs-dir", required=True) parser.add_argument("--data-file", required=True) parser.add_argument("--output-dir", required=True) parser.add_argument("--prompt", required=True) parser.add_argument("--use-ollama", action="store_true") parser.add_argument("--model", default="qwen3:8b") parser.add_argument("--x-column", default="") parser.add_argument("--y-column", default="") args = parser.parse_args() events = [] data_file = Path(args.data_file) docs_dir = Path(args.docs_dir) output_dir = Path(args.output_dir) output_dir.mkdir(parents=True, exist_ok=True) df = load_tabular_data(data_file, events) docs_text = read_context_docs(docs_dir, events) x_col = args.x_column.strip() y_col = args.y_column.strip() if not y_col: y_col = infer_numeric_column(df) if not x_col: inferred_date_col, _ = infer_date_column(df) x_col = inferred_date_col or (df.columns[0] if len(df.columns) else "") if not x_col or not y_col: raise ValueError("Não foi possível inferir colunas suficientes para análise. Informe --x-column e --y-column manualmente.") chart_file = output_dir / "trend_chart.png" build_chart(df, x_col, y_col, chart_file, events) total_rows = len(df) total_cols = len(df.columns) null_count = int(df.isna().sum().sum()) sample = df.head(10).to_markdown(index=False) base_report = f\"\"\"# Relatório de Análise ## Resumo técnico - Arquivo analisado: {data_file.name} - Total de linhas: {total_rows} - Total de colunas: {total_cols} - Total de valores nulos: {null_count} - Coluna usada como eixo X: {x_col} - Coluna usada como eixo Y: {y_col} ## Prévia dos dados {sample} ## Estatísticas descritivas {df.describe(include="all").transpose().fillna("").to_markdown()} ## Observações iniciais - O gráfico principal foi salvo como `trend_chart.png`. - O rastreamento desta execução foi salvo como `tool_trace.json`. \"\"\" final_report = base_report if args.use_ollama: prompt = f\"\"\"Você é um analista de dados local. Com base no dataset abaixo, escreva: 1. um resumo executivo em português do Brasil; 2. três insights relevantes; 3. dois possíveis próximos passos de negócio. Pedido do usuário: {args.prompt} Contexto adicional: {docs_text[:5000] if docs_text else "Nenhum documento adicional fornecido."} Relatório técnico inicial: {base_report[:12000]} \"\"\" summary = ollama_generate(args.model, prompt) final_report += "\\n\\n## Interpretação gerada pelo modelo\\n" + summary log_event(events, "llm", "generate", f"Resumo gerado com o modelo {args.model}") report_file = output_dir / "analysis_report.md" report_file.write_text(final_report, encoding="utf-8") log_event(events, "report", "write", f"Relatório salvo em {report_file.name}") trace_file = output_dir / "tool_trace.json" trace_file.write_text(json.dumps(events, ensure_ascii=False, indent=2), encoding="utf-8") print("Análise concluída com sucesso.") print(f"Gráfico: {chart_file}") print(f"Relatório: {report_file}") print(f"Trace: {trace_file}") if __name__ == "__main__": main()Etapa 9: criar a skill do OpenClaw
Agora vamos ensinar o OpenClaw a disparar esse fluxo com um único comando.
Arquivo SKILL.md
Substitua /CAMINHO/ABSOLUTO/DO/PROJETO pelo caminho real da sua pasta.
--- name: local-data-analyst description: Analista de dados local com OpenClaw + Ollama, gerando gráfico, relatório e trilha de execução. user-invocable: true command-dispatch: tool command-tool: exec command-arg-mode: raw --- Use esta skill como: /local-data-analyst <comando bruto> Template obrigatório: python3 /CAMINHO/ABSOLUTO/DO/PROJETO/main.py --docs-dir /CAMINHO/ABSOLUTO/DO/PROJETO/docs --data-file /CAMINHO/ABSOLUTO/DO/PROJETO/data/SEU_ARQUIVO.csv --output-dir /CAMINHO/ABSOLUTO/DO/PROJETO/output --prompt "Descreva tendências, alertas e oportunidades" --use-ollama --model qwen3:8b Saídas esperadas: - trend_chart.png - analysis_report.md - tool_trace.jsonEssa skill cria um atalho operacional: em vez de você executar o script manualmente toda vez, o OpenClaw passa a orquestrar o fluxo.
Etapa 10: configurar o OpenClaw para usar o Ollama local
A forma mais simples é deixar o OpenClaw descobrir automaticamente os modelos do Ollama local.
macOS / Linux / WSL2
export OLLAMA_API_KEY="ollama-local"Windows PowerShell
$env:OLLAMA_API_KEY="ollama-local"Depois, escolha o modelo padrão:
openclaw models list openclaw models set ollama/qwen3:8bSe quiser manter isso isolado por projeto, você também pode criar um arquivo de configuração local.
Exemplo de openclaw.local.json
{ "agents": { "defaults": { "model": { "primary": "ollama/qwen3:8b" } } } }Se usar esse arquivo, aponte a variável de ambiente:
macOS / Linux / WSL2
export OPENCLAW_CONFIG_PATH="$PWD/openclaw.local.json"Windows PowerShell
$env:OPENCLAW_CONFIG_PATH="$PWD\openclaw.local.json"Etapa 11: preparar seus dados
Coloque seu dataset dentro da pasta data.
Exemplo:
data/ └── vendas.csvVocê também pode colocar arquivos de contexto em docs, por exemplo:
docs/ ├── objetivo.md └── contexto.txtExemplos de contexto útil:
metas de faturamento;
explicação das colunas do dataset;
contexto comercial da empresa;
hipóteses que você deseja validar.
Etapa 12: iniciar o sistema
Terminal 1 — iniciar o Ollama
ollama serveTerminal 2 — iniciar o gateway do OpenClaw
openclaw gateway --forceTerminal 3 — disparar a análise
Exemplo de chamada manual:
openclaw agent --local --message '/local-data-analyst python3 /CAMINHO/ABSOLUTO/DO/PROJETO/main.py --docs-dir /CAMINHO/ABSOLUTO/DO/PROJETO/docs --data-file /CAMINHO/ABSOLUTO/DO/PROJETO/data/vendas.csv --output-dir /CAMINHO/ABSOLUTO/DO/PROJETO/output --prompt "Analise faturamento, sazonalidade, sinais de crescimento, anomalias e oportunidades" --use-ollama --model qwen3:8b'Se tudo correr bem, o OpenClaw vai acionar o script e gerar estes arquivos:
output/trend_chart.pngoutput/analysis_report.mdoutput/tool_trace.json
Como ler o resultado
trend_chart.png
É o gráfico principal da análise. Dependendo do seu dataset, ele pode representar:
evolução temporal;
comparação por categoria;
distribuição resumida por agrupamento.
analysis_report.md
Esse é o arquivo mais importante para o usuário final. Ele traz:
informações básicas sobre o dataset;
estatísticas descritivas;
resumo interpretativo gerado pelo modelo local;
insights e próximos passos.
tool_trace.json
Serve para auditoria e troubleshooting. Você consegue ver quais etapas rodaram e em que ordem.
Boas práticas para um analista de dados local de verdade
use nomes de colunas claros, como
data,faturamento,categoria,quantidade;sempre documente o objetivo da análise em um arquivo
.mddentro da pastadocs;mantenha um dataset de teste pequeno para validar o fluxo antes de rodar em bases grandes;
salve saídas versionadas em pastas separadas quando quiser comparar resultados;
evite ativar recursos em nuvem se sua prioridade for privacidade total.
Limitações desta primeira versão
o script acima foi pensado para dados tabulares simples;
o suporte a documentos de contexto está focado em
.txte.md;gráficos mais sofisticados podem exigir lógica específica por tipo de dataset;
modelos maiores podem exigir mais memória e mais tempo de resposta.
Ainda assim, esta base já é excelente para criar um analista de dados privado, auditável e executável localmente.
Expansões recomendadas para a próxima versão
Adicionar leitura de PDF com uma biblioteca dedicada.
Criar uma interface web local para upload de arquivos.
Salvar relatórios também em HTML e PDF.
Criar skills separadas por tipo de análise:
análise de vendas;
análise financeira;
análise de estoque;
análise de churn ou recorrência.
Acoplar consultas SQL locais ou arquivos Parquet.
Problemas comuns e como resolver
O OpenClaw não encontra o Ollama
Confirme se o serviço está rodando:
ollama serveDepois teste a API local:
curl http://localhost:11434/api/tagsO modelo não aparece na lista
Baixe novamente:
ollama pull qwen3:8b ollama listO Python não consegue abrir o Excel
Instale a dependência:
pip install openpyxlO script não identificou corretamente as colunas
Informe manualmente:
--x-column data --y-column faturamentoO Windows está dando mais erro do que deveria
Considere rodar todo o fluxo dentro do WSL2.
Conclusão
Com OpenClaw e Ollama, você pode montar um analista de dados de IA que funciona de forma totalmente local, sem depender de APIs pagas e sem expor dados sensíveis para terceiros.
Esse tipo de arquitetura é especialmente útil para empresas, times internos, dados confidenciais e experimentos em ambientes controlados.
Mais do que um simples chatbot, você passa a ter um fluxo analítico automatizado, auditável e extensível.