Melhorando seu Assistente Financeiro Pessoal: Registre Despesas usando IA

Melhorando Seu Assistente Financeiro Pessoal: Registre Despesas usando IA

Criamos um Bot Telegram com o objetivo de ser nosso assistente financeiro pessoal nessa tarefa de gerenciar nosso dinheiro. Até então, ele aceita comandos para registrar despesas e receitas, listar os últimos registros e até fazer um diagnóstico e nos oferecer insights para melhorar a gestão do nosso dinheiro. Se você não acompanhou, pode voltar aos posts:


Neste artigo vamos implementar uma funcionalidade que vai facilitar ainda mais nossa tarefa. Vamos enviar uma mensagem informando o valor da transação e a que se refere esse valor. A Inteligência Artificial irá então analisar a mensagem e inferir uma transação a ser lançada na planilha. Dessa maneira não se faz necessário fazermos um registro de transação estruturada como exige o comando /save.

Fonte: https://br.freepik.com/

Pré-requisitos

Neste artigo iremos adicionar mais uma função de automação financeira ao nosso Bot, a qual usa IA para ler uma mensagem, de onde irá extrair os dados de uma transação e adicionar em nossa planilha de finanças pessoais.

Para isso, será necessário que você tenha lido os posts anteriores e, preferencialmente, clonado o repositório GitHub onde está o código do Bot.

Não será necessário instalar nenhuma nova biblioteca, pois iremos apenas precisar de json, que é embutida no Python e uma nova função do pacote telegram, a MessageHandler. No mais, tudo que já instalamos até o momento será usado.

O que vamos criar

Até então, nosso assistente financeiro responde a comandos previamente programados: start, save, help, list e diagnostic. Agora queremos que a interação seja mais natural, sem necessidade de enviar mensagens estruturadas. Ou seja, queremos enviar uma mensagem do tipo "gastei 80 no almoço", "almoço 80", e a IA irá extrair dessa mensagem um registro que será efetivado na planilha financeira do Google Sheets.

A nova função

No código do Bot apresentado ao final deste post, acrescente as novas linhas conforme mostrado a seguir:

from dotenv import load_dotenv
# Acrescentar este import
import json
import os
import logging
import pandas as pd
from datetime import date
from utils import (
    conectar_google_sheets,
    normalizar_string,
    validar_chat_id)
from telegram import Update
from telegram.ext import (
    ApplicationBuilder,
    CommandHandler,
    ContextTypes,
# Acrescentar este import
    MessageHandler,
    filters)
from openai import OpenAI

# Restante do código igual ao do post anterior

# Acrescentar esta função
async def interpretar(update, context):
    mensagem = update.message.text

    # Chama IA para extrair informação
    try:
        resposta = client.chat.completions.create(
            model="gpt-3.5-turbo",
            messages=[
                {
                    "role": "system",
                    "content": """Você é um sistema de categorização de
                        transações financeiras. Responda APENAS em formato
                        JSON válido, sem explicações adicionais."""
                },
                {
                    "role": "user",
                    "content": f"""Extraia da frase abaixo:
                        - valor (float, usar . como separador decimal)
                        - tipo: "Receita" ou "Despesa"
                        - categoria (uma palavra)
                        - data (DD/MM/YYYY; se não informado,
                            usar {date.today().strftime("%d/%m/%Y")})

                    Frase: "{mensagem}"

                    Retorne APENAS JSON, exemplo:
                        {{"valor": 58,.0, "tipo": "Despesa",
                            "categoria": "Alimentacao",
                            "data": "28/11/2025"}}"""
                }
            ],
            max_tokens=200,
            temperature=0.3
        )
        texto = resposta.choices[0].message.content.strip()
    except Exception as e:
        logger.exception("Erro chamando OpenAI")
        await update.message.reply_text(f"Erro na API de IA: {e}")
        return

    # Extrair JSON do texto
    try:
        start = texto.find("{")
        end = texto.rfind("}") + 1
        if start == -1 or end == 0:
            raise ValueError("Nenhum JSON encontrado na resposta")

        json_text = texto[start:end]
        dados = json.loads(json_text)

        valor = float(dados["valor"])
        tipo = dados["tipo"].capitalize()
        categoria = dados["categoria"].capitalize()
        data_str = dados.get("data", date.today().isoformat()).strip()

        # Validar e normalizar data
        try:
            data_obj = pd.to_datetime(
                    data_str, format="%d/%m/%Y", errors='coerce')
            if pd.isna(data_obj):
                data = date.today().strftime("%d/%m/%Y")
            else:
                data = data_obj.strftime("%d/%m/%Y")
        except Exception as e:
            logger.exception("Erro ao parsear data: %s", e)
            data = date.today().strftime("%d/%m/%Y")

    except Exception as e:
        logger.exception("Erro ao parsear resposta da IA")
        await update.message.reply_text(
            f"Não consegui interpretar. Erro: {e}\nResposta: {texto[:500]}"
        )
        return

    try:
        sheet = abrir_planilha()
        # Adiciona uma nova linha na planilha com os dados extraídos
        sheet.append_row(
            [
                data,
                "",
                categoria,
                valor,
                tipo,
            ]
        )
        await update.message.reply_text(
            f"📌 Registrado!\n\n"
            f"Tipo: {tipo}\n"
            f"Categoria: {categoria}\n"
            f"Valor: R$ {valor:,.2f}\n"
            f"Data: {data}"
        )
    except Exception as e:
        logger.exception("Erro ao salvar na planilha")
        await update.message.reply_text(f"Erro ao salvar na planilha: {e}")

E vamos então analisar a função interpretar(), responsável por extrair os dados de uma mensagem enviada em linguagem natural.

Inicialmente, lemos a mensagem enviada ao Bot. Em seguida montamos um prompt para enviar essa mensagem à IA. Note o contexto no prompt e que pedimos quais dados devem ser extraídos. Ainda é solicitado que esses dados sejam retornados em formato json. É importante observar que, mesmo que tenhamos pedido que a IA retorne apenas json, não há garantia que a resposta será assim. Por isso precisamos tratar adequadamente a resposta.

Observe que podemos enviar uma mensagem com uma data passada, para o caso de termos esquecido de fazer um registro. Mas se não enviarmos a data na mensagem, pedimos à IA que considere o lançamento na data corrente.

A fim de extrair o json da resposta, primeiro buscamos as chaves {}, que envolvem um json. Isso irá garantir que existe um json no texto da resposta e que iremos tratar apenas ele. Daí lemos as chaves fundamentais do nosso registro, que são a data, o valor, a categoria e o tipo.

Lidos esses dados, fazemos o lançamento na planilha. Faça vários testes com a IA, enviando mensagens com dados em ordem diferente, data em vários formatos, a fim de confirmar se o modelo irá tratá-las adequadamente.

Finalmente, para adicionar a função ao bot, inclua a seguinte linha à sequencia de app.add_handler() que já existem no método main().

    app.add_handler(
        MessageHandler(authorized_only & filters.TEXT & ~filters.COMMAND, interpretar))

Confira o código completo no GitHub.

Conclusão

Agora o nosso assistente financeiro aceita registro de despesas por meio do comando /save, usando dados estruturados, ou por meio de uma mensagem em linguagem natural, onde a IA interpreta a mensagem, infere os dados e efetiva o lançamento na planilha Google Sheets.

Essa funcionalidade pode ser melhorada, se definirmos um conjunto de categorias nas quais as depesas podem ser lançadas. Essa função vamos deixar para você implementar.

Comentários