Analisar um Excel ou CSV com uma IA locale
Analisar um Excel ou CSV com uma IA local não exige confiar as somas ao modelo. Este guia divide o trabalho: o pandas lê o arquivo e calcula, um segundo script reconta por outro caminho e, em seguida, um modelo servido pelo Ollama comenta resultados já verificados. O código completo é fornecido para um CSV, com as alterações necessárias para uma pasta de trabalho do Excel. Uma seção indica com precisão o que foi verificado na prática e o que não foi.
#Analisar um Excel ou CSV com uma IA local: quem calcula, quem interpreta
Colar uma tabela em uma conversa é tentador: a resposta vem em frases, com totais que parecem corretos. Mas um LLM gera texto plausível e não executa nenhum cálculo quando escreve um total. Nada na resposta dele distingue um número certo de um número errado. E quanto mais longo o arquivo, maior o risco de ele exceder o contexto do modelo, às vezes sem uma mensagem clara.
A divisão proposta aqui é simples: tudo o que pode ser recalculado de forma idêntica fica a cargo de uma ferramenta determinística. O mesmo arquivo e o mesmo script dão o mesmo resultado, e esse resultado pode ser verificado. O modelo fica com o que sabe fazer: colocar resultados em palavras, apontar o que merece atenção e propor perguntas.
- Ler e validar: pandas
- Colunas presentes, células vazias, valores numéricos, datas no formato esperado. O script para em vez de tentar adivinhar.
- Calcular: pandas
- Totais e participações por categoria, gravados em um arquivo faits.json.
- Verificar: somente Python
- Um segundo script relê o arquivo de origem sem pandas e reconta. Qualquer divergência bloqueia a continuação.
- Interpretar: o modelo local
- Ele recebe apenas o faits.json, não as linhas do arquivo, e redige um comentário sem escrever ele mesmo um único número.
- Decidir: você
- Um total comprova uma soma, não uma causa. O comentário do modelo continua sendo uma pista a ser examinada.
#Diferença em relação ao tutorial de text-to-SQL
Aproveite a nossa experiência e um percurso guiado para criar o seu assistente local e usar a sua IA no dia a dia.
- Espaço online vitalício
- PDF + arquivos
- Reembolsado em 30 dias
O QuelLLM já oferece um tutorial de text-to-SQL local. Os dois guias impedem que o LLM invente resultados, mas não atribuem a ele o mesmo papel. A escolha depende principalmente da sua necessidade: fazer perguntas variadas ou refazer um cálculo conhecido.
- Text-to-SQL: papel do modelo
- Ele escreve a consulta a partir de uma pergunta em francês. Em seguida, o banco de dados executa esse código gerado, daí a necessidade de um papel somente leitura e de uma validação do SQL.
- Este guia: papel do modelo
- Ele não escreve nenhum código e não executa nada. Você escreve o cálculo uma vez e, depois, o modelo comenta o resultado.
- Text-to-SQL: quando escolher
- Dados em PostgreSQL ou MySQL e perguntas que mudam com frequência.
- Este guia: quando escolhê-lo
- Uma exportação ou uma pasta de trabalho, com um cálculo recorrente: balanço mensal, detalhamento por categoria, acompanhamento de despesas.
- Limite deste guia
- Uma nova pergunta exige modificar o script. Esse é o preço de um cálculo revisado e reproduzível.
#Pré-requisitos e arquivo de exemplo
- Ollama
- O serviço deve responder em http://localhost:11434. O guia de instalação está listado no fim da página.
- Python
- Um ambiente virtual com Python 3.11 ou mais recente para o pandas 3.
- Um modelo
- O exemplo usa o qwen3.5:9b, cerca de 6,6 GB em Q4, um tamanho que cabe em uma RTX 3060 12GB. Ele reutiliza o modelo do guia sobre saídas estruturadas; a qualidade dos comentários dele sobre dados tabulares não foi avaliada aqui.
- Um arquivo fictício
- Comece com o pequeno arquivo abaixo. Você pode conferir os totais dele de cabeça, o que permite ver se a configuração funciona antes de usar dados reais.
Esse é o formato encontrado com frequência em uma exportação francesa: ponto e vírgula entre as colunas, vírgula para os decimais, data em dia/mês/ano. Verifique o seu em um editor de texto, não no Excel, que reformata a exibição.
#Etapa 1: calcular com o pandas
O script descreve explicitamente o formato do arquivo e prefere parar a produzir um total duvidoso. A documentação do pandas consultada em 03/11/2026 (versão 3.1.0) descreve os parâmetros usados: sep para o delimitador, decimal para os dados europeus e on_bad_lines, cujo valor padrão “error” gera um erro em uma linha malformada.
Duas escolhas merecem uma explicação. Primeiro, keep_default_na=False: a lista padrão do pandas trata, entre outros, NA, N/A e null como valores ausentes. Ora, uma categoria “NA” lida como ausente poderia desaparecer de um agrupamento sem nenhum alerta. Depois, as duplicatas são contadas, mas não removidas: duas compras idênticas no mesmo dia podem ser legítimas, e essa decisão cabe a você.
Para o arquivo de exemplo, o resultado pode ser calculado à mão: A = 100 + 25 = 125, B = 50, ou seja, uma soma de 175. Sua saída deve corresponder aos valores a seguir.
#Etapa 2: recontar por outro caminho
Um cálculo determinístico pode estar errado de forma perfeitamente reproduzível: separador incorreto, coluna mal lida, filtro esquecido. Por isso, este segundo script não confia no pandas: ele relê o arquivo de origem com os módulos padrão csv e decimal, reconta e depois compara. Trata-se de uma verificação de leitura e de soma. Ela não diz se o cálculo escolhido responde à sua pergunta.
Encadeie as etapas com &&: se uma falhar, a seguinte não começa. Assim, o modelo nunca verá resultados rejeitados pela verificação.
#Etapa 3: pedir ao modelo que interprete os resultados
O modelo recebe o conteúdo de faits.json e responde de acordo com um esquema JSON, com o parâmetro format do Ollama explicado no guia sobre saídas estruturadas. Esse esquema define a forma da resposta, não sua exatidão. A proteção útil está em outro lugar: o modelo vê os valores para poder compará-los, mas deve citá-los pela chave. A função remplir rejeita qualquer número escrito diretamente, bem como qualquer chave inventada.
Essa proteção não cobre tudo. Ela não detecta um número escrito por extenso (“três vezes mais”), nem uma conclusão falsa construída com valores corretos, por exemplo, uma causa apresentada como comprovada. Ela bloqueia números copiados ou inventados, mas a revisão humana continua necessária. Se uma resposta for rejeitada, não a corrija manualmente: execute novamente ou reformule a instrução e mantenha um registro da rejeição.
Enviar apenas agregados também reduz o que o modelo pode ler: nem nomes de clientes, nem texto livre vindo das linhas. No entanto, os rótulos de categorias continuam sendo transmitidos e podem conter texto malicioso se o arquivo vier de fora. Aqui, o modelo não tem nenhuma ferramenta e só pode produzir texto, o que limita os danos possíveis sem eliminar o risco.
#Etapa 4: analisar um Excel, o que muda
Para uma pasta de trabalho .xlsx, apenas a leitura muda em calculs.py: read_excel substitui read_csv, e os parâmetros sep, decimal, encoding e on_bad_lines desaparecem. Este bloco não foi executado em um arquivo Excel: teste-o primeiro em uma pequena pasta de trabalho cujos totais você conheça.
- Motor
- Na documentação 3.1.0, o openpyxl continua sendo usado por padrão para .xlsx, mas essa escolha está anunciada para mudar para o calamine em uma versão futura. Especificá-lo evita trocar de mecanismo sem perceber durante uma atualização.
- Feuille
- O valor padrão de sheet_name é 0, ou seja, a primeira planilha. Com None ou uma lista, read_excel retorna um dicionário de tabelas, e não uma só: nesse caso, o script acima precisaria ser adaptado.
- Cabeçalho
- O script pressupõe os nomes das colunas na primeira linha. Se houver um título antes da tabela, use o parâmetro header ou, melhor ainda, limpe uma cópia da pasta de trabalho.
- Dates
- Se a coluna contiver datas reais do Excel, o formato dia/mês/ano do script não necessariamente se aplica a elas. Verifique date_min e date_max no faits.json.
- Linhas de total
- Uma linha “Total” no fim da planilha seria contada como uma categoria e dobraria a soma. Nesse caso, ela aparece como chave no faits.json: revise essa lista.
A verificação da etapa 2 lê um CSV. Para mantê-la, exporte a planilha pelo Excel (Salvar como, formato CSV UTF-8) e execute python controle.py export.csv. A exportação passa pelo Excel, e não pelo mecanismo de leitura do pandas: é outro caminho de leitura, e as diferenças são justamente o que se procura. Verifique o delimitador: o script espera um ponto e vírgula. Um valor exportado com seu formato de exibição, como “1 250,00 €”, fará a verificação falhar em vez de passar despercebido: remova esse formato na cópia a ser exportada. Um formato arredondado na exibição também pode criar uma diferença, a ser tratada da mesma maneira.
#O que foi verificado e o que não foi
Em 30/10/2026, um CSV fictício foi lido e agregado com o pandas 3.0.2; a verificação resultou em A=125 e B=50. Essa é a única evidência prática deste guia. O arquivo de exemplo acima reutiliza esses totais para manter a legibilidade, sem que isso comprove o funcionamento dos scripts publicados.
- Verificado
- Leitura e agregação de um CSV fictício com pandas 3.0.2, totais A=125 e B=50 (30/10/2026).
- Revisado, não executado
- Parâmetros de read_csv e read_excel, na documentação do pandas 3.1.0 consultada em 03/11/2026. Ela é mais recente que a versão do teste: confira a sua versão com pip show pandas.
- Não verificado
- Execução completa de calculs.py, controle.py e interpreter.py na forma publicada, e valores de faits.json na saída: os valores indicados foram calculados à mão.
- Não verificado
- Qualquer chamada a um LLM: qualidade dos comentários, cumprimento da instrução, frequência das rejeições. Por isso, nenhum exemplo de resposta é apresentado.
- Não verificado
- Qualquer leitura de um arquivo Excel, incluindo fórmulas e exportação para CSV.
Nenhuma duração, nenhuma taxa de erro e nenhuma comparação de modelos aparecem aqui, por falta de medição. Trate estes scripts como uma base a ser testada no arquivo fictício antes de usar seus dados. O teste útil também consiste em provocar falhas: altere um valor no faits.json e a verificação deve recusar o resultado; forneça para preenchimento um texto contendo um número e a resposta deve ser rejeitada.
#Solução de problemas
- “A coluna montant contém algo além de números”
- Ainda resta um símbolo monetário, um texto ou um separador de milhar. Se o arquivo usar separador de milhar, adicione o parâmetro thousands a read_csv com o caractere correto. Nos arquivos franceses, costuma ser um espaço não separável, invisível a olho nu. Depois, a verificação também precisará remover esse mesmo caractere antes de Decimal.
- Apenas uma coluna lida, ou colunas ausentes
- O delimitador não é o correto. Abra o arquivo em um editor de texto e ajuste sep em calculs.py e delimiter em controle.py.
- UnicodeDecodeError
- O arquivo não está em UTF-8. Uma exportação antiga do Windows costuma estar em cp1252: altere encoding nos dois scripts e depois verifique os acentos nos nomes das categorias.
- Erro no formato de data
- Uma data não segue o formato dia/mês/ano. Corrija o dado ou ajuste format. Evite uma conversão permissiva, que pode mascarar uma inversão entre dia e mês.
- Participações incoerentes
- Com reembolsos ou valores negativos, uma participação percentual pode passar de 100 ou perder o sentido. O script não sinaliza isso: nesse caso, retire essas participações do faits.json.
- Resposta rejeitada em todas as tentativas
- O modelo copia os valores apesar da instrução. Reformule-a ou experimente outro modelo, sem remover a proteção.
- “Connection refused” no lado de Ollama
- O serviço não foi iniciado. Verifique com ollama list e o endereço http://localhost:11434.
#Para se aprofundar
Estes guias complementam a montagem: o text-to-SQL se seus dados estiverem em um banco de dados, as saídas estruturadas para o parâmetro format e os riscos ligados a instruções ocultas em arquivos vindos de fora.
Um comentário, um erro ou uma observação? Avise-nos; isso ajuda a melhorar o guia para todos.