datacrew-ai / app.py
Gleison's picture
Fix: Use Groq API via HTTP requests instead of Python client
5e9d068
Raw
History Blame Contribute Delete
16.1 kB
"""
DataCrew AI - Interface Gradio para Hugging Face Spaces
Análise Inteligente de Dados com IA
Desenvolvido por: Gleison Leoni
"""
import gradio as gr
import pandas as pd
import os
import requests
import json
import plotly.express as px
import plotly.graph_objects as go
# API Key Groq (será configurada pelo usuário)
groq_api_key = None
def initialize_groq(api_key):
"""Inicializa/valida a API key do Groq"""
global groq_api_key
if not api_key or not api_key.startswith('gsk_'):
return "❌ API Key inválida! Deve começar com 'gsk_'"
try:
# Testar a API key com uma chamada simples
headers = {
"Authorization": f"Bearer {api_key}",
"Content-Type": "application/json"
}
response = requests.post(
"https://api.groq.com/openai/v1/chat/completions",
headers=headers,
json={
"model": "llama-3.3-70b-versatile",
"messages": [{"role": "user", "content": "test"}],
"max_tokens": 5
},
timeout=10
)
if response.status_code == 200:
groq_api_key = api_key
return "✅ API Key configurada com sucesso!"
elif response.status_code == 401:
return "❌ API Key inválida ou expirada"
else:
return f"❌ Erro: {response.status_code} - {response.text[:100]}"
except requests.exceptions.Timeout:
return "❌ Timeout - Verifique sua conexão"
except Exception as e:
return f"❌ Erro ao validar API Key: {str(e)}"
def analyze_csv(file):
"""Analisa o arquivo CSV e retorna estatísticas"""
if file is None:
return "⚠️ Por favor, faça upload de um arquivo CSV primeiro.", None
try:
# Ler CSV
df = pd.read_csv(file.name)
# Análise básica
analysis = f"""
📊 **Análise Automática do Dataset**
**Dimensões:**
- Linhas: {len(df):,}
- Colunas: {len(df.columns)}
- Tamanho: {df.memory_usage(deep=True).sum() / 1024:.2f} KB
**Colunas ({len(df.columns)}):**
{chr(10).join([f"• {col} ({df[col].dtype})" for col in df.columns])}
**Valores Ausentes:**
{df.isnull().sum().to_string() if df.isnull().sum().sum() > 0 else "✅ Nenhum valor ausente"}
**Duplicatas:**
{"✅ Nenhuma duplicata encontrada" if df.duplicated().sum() == 0 else f"⚠️ {df.duplicated().sum()} linhas duplicadas"}
**Primeiras 10 Linhas:**
"""
# Retornar análise + preview dos dados
return analysis, df.head(10)
except Exception as e:
return f"❌ Erro ao analisar CSV: {str(e)}", None
def get_statistics(file):
"""Retorna estatísticas descritivas"""
if file is None:
return "⚠️ Faça upload de um CSV primeiro."
try:
df = pd.read_csv(file.name)
# Estatísticas numéricas
numeric_cols = df.select_dtypes(include=['number']).columns
if len(numeric_cols) == 0:
return "⚠️ Nenhuma coluna numérica encontrada no dataset."
stats = f"""
📈 **Estatísticas Descritivas**
**Colunas Numéricas: {len(numeric_cols)}**
"""
for col in numeric_cols:
stats += f"""
**{col}:**
- Média: {df[col].mean():.2f}
- Mediana: {df[col].median():.2f}
- Desvio Padrão: {df[col].std():.2f}
- Mínimo: {df[col].min():.2f}
- Máximo: {df[col].max():.2f}
- Q1 (25%): {df[col].quantile(0.25):.2f}
- Q3 (75%): {df[col].quantile(0.75):.2f}
"""
return stats
except Exception as e:
return f"❌ Erro: {str(e)}"
def create_visualization(file, chart_type, x_col, y_col):
"""Cria visualizações com Plotly"""
if file is None:
return None, "⚠️ Faça upload de um CSV primeiro."
try:
df = pd.read_csv(file.name)
if x_col not in df.columns:
return None, f"❌ Coluna '{x_col}' não encontrada no dataset.\n\nColunas disponíveis: {', '.join(df.columns)}"
# Criar gráfico baseado no tipo
if chart_type == "Histograma":
fig = px.histogram(df, x=x_col, title=f"Distribuição de {x_col}",
color_discrete_sequence=['#3B82F6'])
elif chart_type == "Gráfico de Barras":
value_counts = df[x_col].value_counts().head(20)
fig = px.bar(x=value_counts.index, y=value_counts.values,
labels={'x': x_col, 'y': 'Contagem'},
title=f"Contagem de {x_col}",
color_discrete_sequence=['#8B5CF6'])
elif chart_type == "Scatter Plot":
if y_col and y_col in df.columns:
fig = px.scatter(df, x=x_col, y=y_col,
title=f"{x_col} vs {y_col}",
color_discrete_sequence=['#EC4899'])
else:
return None, "❌ Para Scatter Plot, selecione duas colunas numéricas."
elif chart_type == "Box Plot":
fig = px.box(df, y=x_col, title=f"Box Plot de {x_col}",
color_discrete_sequence=['#10B981'])
elif chart_type == "Matriz de Correlação":
numeric_df = df.select_dtypes(include=['number'])
if len(numeric_df.columns) < 2:
return None, "❌ Necessário pelo menos 2 colunas numéricas para matriz de correlação."
corr = numeric_df.corr()
fig = px.imshow(corr, text_auto=True, aspect="auto",
title="Matriz de Correlação",
color_continuous_scale='RdBu_r')
else:
return None, "❌ Tipo de gráfico não reconhecido."
fig.update_layout(
template="plotly_white",
height=500,
font=dict(size=12)
)
return fig, f"✅ Gráfico '{chart_type}' gerado com sucesso!"
except Exception as e:
return None, f"❌ Erro ao criar visualização: {str(e)}"
def ask_question(file, question, api_key):
"""Responde perguntas usando Groq via API HTTP"""
global groq_api_key
if not api_key:
return "⚠️ Por favor, configure sua API Key do Groq primeiro na seção acima."
if file is None:
return "⚠️ Faça upload de um CSV primeiro."
if not question:
return "⚠️ Digite uma pergunta."
try:
# Atualizar API key se mudou
if api_key != groq_api_key:
result = initialize_groq(api_key)
if "❌" in result:
return result
# Ler dados
df = pd.read_csv(file.name)
# Preparar contexto
context = f"""
Você é um analista de dados especializado. Responda a pergunta do usuário sobre este dataset de forma clara e objetiva.
**Dataset:** {os.path.basename(file.name)}
**Dimensões:** {len(df)} linhas × {len(df.columns)} colunas
**Colunas e Tipos:**
{chr(10).join([f"- {col}: {df[col].dtype} ({df[col].nunique()} valores únicos)" for col in df.columns])}
**Amostra dos dados (5 primeiras linhas):**
{df.head(5).to_string()}
**Estatísticas das colunas numéricas:**
{df.describe().to_string()}
**Pergunta do usuário:** {question}
Instruções para resposta:
- Seja claro e objetivo
- Use markdown para formatação
- Destaque insights importantes com **negrito**
- Se relevante, mencione números e estatísticas
- Responda em português brasileiro
"""
# Chamar API Groq via HTTP
headers = {
"Authorization": f"Bearer {groq_api_key}",
"Content-Type": "application/json"
}
payload = {
"model": "llama-3.3-70b-versatile",
"messages": [
{"role": "system", "content": "Você é um assistente especializado em análise de dados. Forneça respostas claras, objetivas e baseadas em dados."},
{"role": "user", "content": context}
],
"temperature": 0.7,
"max_tokens": 2000
}
response = requests.post(
"https://api.groq.com/openai/v1/chat/completions",
headers=headers,
json=payload,
timeout=30
)
if response.status_code == 200:
answer = response.json()['choices'][0]['message']['content']
return f"🤖 **Resposta da IA:**\n\n{answer}"
else:
return f"❌ Erro na API Groq ({response.status_code}): {response.text[:200]}"
except requests.exceptions.Timeout:
return "❌ Timeout - A IA demorou muito para responder. Tente novamente."
except Exception as e:
return f"❌ Erro ao processar pergunta: {str(e)}\n\nVerifique se sua API Key está correta."
# ============================================================================
# Interface Gradio
# ============================================================================
with gr.Blocks(
theme=gr.themes.Soft(
primary_hue="blue",
secondary_hue="purple",
),
title="DataCrew AI - Análise Inteligente de Dados",
css="""
.gradio-container {
font-family: 'Inter', sans-serif;
}
"""
) as demo:
# Header
gr.Markdown("""
# 🧠 DataCrew AI
### Análise Inteligente de Dados com Inteligência Artificial
**Desenvolvido por:** Gleison Leoni | **Tecnologia:** Groq (LLaMA 3.3) + Pandas + Plotly
Faça upload de um arquivo CSV e converse com seus dados usando IA de última geração!
""")
gr.Markdown("---")
# API Key
gr.Markdown("### 🔑 Configuração")
gr.Markdown("Obtenha sua chave gratuita em: [console.groq.com](https://console.groq.com)")
with gr.Row():
api_key_input = gr.Textbox(
label="API Key do Groq",
placeholder="gsk_...",
type="password",
scale=3
)
api_status = gr.Textbox(label="Status", interactive=False, scale=1)
api_key_input.change(
fn=initialize_groq,
inputs=[api_key_input],
outputs=[api_status]
)
gr.Markdown("---")
# Upload de arquivo
gr.Markdown("### 📁 Upload do Dataset")
file_input = gr.File(
label="Arraste seu arquivo CSV aqui ou clique para fazer upload",
file_types=[".csv"],
type="filepath"
)
gr.Markdown("---")
# Tabs
with gr.Tabs():
# Tab 1: Análise Automática
with gr.Tab("📊 Análise Automática"):
gr.Markdown("""
Clique no botão abaixo para obter uma análise completa do seu dataset:
- Dimensões (linhas e colunas)
- Tipos de dados
- Valores ausentes e duplicatas
- Preview dos dados
""")
analyze_btn = gr.Button("🔍 Analisar Dataset", variant="primary", size="lg")
with gr.Row():
analysis_output = gr.Markdown(label="Análise")
with gr.Row():
data_preview = gr.DataFrame(label="Preview dos Dados (10 primeiras linhas)")
analyze_btn.click(
fn=analyze_csv,
inputs=[file_input],
outputs=[analysis_output, data_preview]
)
# Tab 2: Estatísticas
with gr.Tab("📈 Estatísticas Descritivas"):
gr.Markdown("""
Obtenha estatísticas detalhadas das colunas numéricas:
- Média, mediana, desvio padrão
- Valores mínimo e máximo
- Quartis (25%, 75%)
""")
stats_btn = gr.Button("📊 Calcular Estatísticas", variant="primary", size="lg")
stats_output = gr.Markdown(label="Estatísticas")
stats_btn.click(
fn=get_statistics,
inputs=[file_input],
outputs=[stats_output]
)
# Tab 3: Visualizações
with gr.Tab("📉 Gráficos e Visualizações"):
gr.Markdown("""
Crie gráficos interativos dos seus dados:
1. Escolha o tipo de gráfico
2. Digite o nome da coluna (exatamente como aparece no CSV)
3. Clique em "Gerar Gráfico"
""")
with gr.Row():
chart_type = gr.Dropdown(
choices=[
"Histograma",
"Gráfico de Barras",
"Scatter Plot",
"Box Plot",
"Matriz de Correlação"
],
label="Tipo de Gráfico",
value="Histograma"
)
with gr.Row():
x_column = gr.Textbox(
label="Coluna X",
placeholder="Digite o nome exato da coluna",
info="Para Histograma, Barras e Box Plot"
)
y_column = gr.Textbox(
label="Coluna Y (opcional)",
placeholder="Apenas para Scatter Plot",
info="Segunda coluna para comparação"
)
create_chart_btn = gr.Button("📊 Gerar Gráfico", variant="primary", size="lg")
chart_status = gr.Textbox(label="Status", interactive=False)
with gr.Row():
chart_output = gr.Plot(label="Gráfico Interativo")
create_chart_btn.click(
fn=create_visualization,
inputs=[file_input, chart_type, x_column, y_column],
outputs=[chart_output, chart_status]
)
# Tab 4: Chat com IA
with gr.Tab("💬 Chat com IA"):
gr.Markdown("""
### Faça perguntas sobre seus dados em linguagem natural!
A IA (LLaMA 3.3 70B via Groq) irá analisar seus dados e responder suas perguntas de forma inteligente.
**💡 Exemplos de perguntas:**
- "Quais são as principais estatísticas deste dataset?"
- "Qual coluna tem mais valores ausentes?"
- "Identifique possíveis outliers nos dados"
- "Mostre insights sobre correlações entre variáveis"
- "Faça uma análise exploratória completa"
- "Sugira próximos passos para análise"
""")
question_input = gr.Textbox(
label="❓ Sua Pergunta",
placeholder="Digite sua pergunta sobre os dados...",
lines=3
)
ask_btn = gr.Button("🤖 Perguntar à IA", variant="primary", size="lg")
answer_output = gr.Markdown(label="Resposta da IA")
# Exemplos de perguntas
gr.Examples(
examples=[
"Quais são as 5 principais estatísticas deste dataset?",
"Identifique outliers nas colunas numéricas",
"Mostre correlações entre as variáveis",
"Faça uma análise exploratória completa dos dados",
],
inputs=question_input,
label="Clique em um exemplo para testar:"
)
ask_btn.click(
fn=ask_question,
inputs=[file_input, question_input, api_key_input],
outputs=[answer_output]
)
# Footer
gr.Markdown("""
---
### 📚 Sobre este Projeto
**DataCrew AI** é uma plataforma de análise inteligente de dados desenvolvida como parte do curso de Inteligência Artificial.
**Tecnologias:**
- 🤖 Groq (LLaMA 3.3 70B) - Processamento de linguagem natural
- 🐼 Pandas - Manipulação de dados
- 📊 Plotly - Visualizações interativas
- 🎨 Gradio - Interface web
**Desenvolvedor:** Gleison Leoni
**Código Fonte:** [GitHub](https://github.com/gleison-leoni/datacrew-ai)
""")
# ============================================================================
# Executar
# ============================================================================
if __name__ == "__main__":
demo.launch()