Home » AI » Comment créer un analyste financier IA privé en local ?

Comment créer un analyste financier IA privé en local ?

Construire un analyste financier IA privé en local repose sur un pipeline de prétraitement CSV robuste, des modèles ML légers (scikit‑learn) et un LLM local (ex. Ollama / llama.cpp) pour synthèses en langage naturel, garantissant confidentialité et contrôle (sources : pandas, scikit‑learn, Ollama).

Quelle architecture privilégier pour un analyste financier IA privé

Une architecture modulaire exécutée 100 % en local, composée d’une UI (Streamlit), d’un module de prétraitement, d’un module ML (classification + anomalie), d’un module de visualisation (Plotly) et d’une couche LLM locale (Ollama ou inference locale) est la meilleure approche.

Cette solution garantit confidentialité des données financières, traçabilité et contrôle des dépendances. Chaque module porte une responsabilité unique et le flux de données suit une chaîne claire : import CSV → prétraitement → modèles ML (classification, détection d’anomalies) → visualisations → synthèse en langage naturel via LLM local.

  • app.py : Point d’entrée Streamlit. Gère upload CSV, appels aux modules et orchestration. Sortie : tableau interactif, graphiques, résumé LLM.
  • preprocessing.py : Nettoyage, normalisation, feature engineering. Entrée : CSV brut. Sortie : DataFrame sérialisable (JSON/feather) prêt pour ML.
  • ml_models.py : Entraînement et inférence des modèles de classification et d’anomalie (IsolationForest, RandomForest). Entrée : features, labels optionnels. Sortie : prédictions, scores, artefacts sauvegardés (joblib).
  • visualizations.py : Fonctions Plotly produisant figures (séries temporelles, heatmaps). Entrée : DataFrame + sorties ML. Sortie : objets Plotly intégrés dans Streamlit.
  • llm_integration.py : Wrapper pour Ollama / llama.cpp / Transformers en local. Transforme métriques et insights en prompts structurés, retourne synthèse NLG.
  • config.py : Paramètres centralisés (seuils, chemins, modèles). Entrée : variables d’environnement ou fichier .env. Sortie : constantes pour l’app.
  • sample_data/ : Jeux d’exemples et tests unitaires pour CI.

Séparer interfaces et logique, appliquer inversion de dépendances (modules importent des contrats, pas l’implémentation), et normaliser les contrats d’entrée/sortie en JSON facilite tests et maintenabilité.

Choix technologiques :

  • Pandas : ETL fiable (Python 3.10+ requis).
  • Scikit‑learn : Modèles classiques, CPU-friendly.
  • Joblib : Persistance des modèles.
  • Streamlit : UI légère pour Data Apps.
  • Plotly : Visualisations interactives.
  • Ollama / llama.cpp / Hugging Face Transformers : LLM locaux. Ollama/llama.cpp acceptent CPU; Hugging Face permet GPU pour modèles >7B; choix dépend de la taille du modèle (2-7B utile en CPU, >13B recommandé GPU).

Diagramme flux :

  • CSV Upload → preprocessing.py → ml_models.py → visualizations.py → llm_integration.py → app.py affiche synthèse.
app.py Orchestration Streamlit CSV, JSON UI, Figures, Texte
preprocessing.py Nettoyage & features CSV DataFrame JSON
ml_models.py Train / Inférence Features Predictions, joblib
visualizations.py Figures Plotly Data + preds Objets Plotly
llm_integration.py NLG local Métriques JSON Texte synthèse
Module Points d’attention Complexité
preprocessing.py Gestion des valeurs manquantes et contraintes comptables Facile
ml_models.py Choix de features, overfitting, sauvegarde des artefacts Moyen
visualizations.py Performances interactives pour grands jeux Facile
llm_integration.py Prompt engineering local, limites mémoire modèle Difficile
app.py Orchestration et gestion d’erreurs utilisateur Moyen

Comment construire un pipeline robuste de prétraitement de CSV bancaires

Un pipeline qui détecte automatiquement les colonnes, normalise les formats et produit un schéma standardisé est indispensable pour des relevés bancaires hétérogènes.

Stratégie de détection des colonnes.

  • Définition d’un dictionnaire de motifs pour identifier les colonnes les plus fréquentes.
  • Utilisation d’expressions régulières et d’heuristiques (priorité sur les correspondances exactes, fallback par similarité de nom).
  • Gestion des ambiguités par score et heuristique de contexte (présence simultanée de « debit »/ »credit », position relative des colonnes).
COLUMN_PATTERNS = {
    r'(?i)date|transaction_date|dt': 'date',
    r'(?i)description|libellé|motif': 'description',
    r'(?i)amount|montant|valeur': 'amount',
    r'(?i)debit|prelevement|deb': 'debit',
    r'(?i)credit|creditment|crd': 'credit',
    r'(?i)currency|devise|eur|usd': 'currency'
}

Fonction Python de détection et normalisation.

import re
import pandas as pd

def detect_column_mapping(df):
    mapping = {}
    cols = list(df.columns)
    for col in cols:
        found = None
        for pattern, role in COLUMN_PATTERNS.items():
            if re.search(pattern, col):
                found = role
                break
        if found:
            mapping.setdefault(found, []).append(col)
    return mapping

def normalize_amounts(df, mapping):
    df2 = df.copy()
    # Cas séparés débit/crédit
    if 'amount' in mapping:
        amt_col = mapping['amount'][0]
        df2['amount'] = df2[amt_col].astype(str)
    else:
        deb = mapping.get('debit', [])
        cred = mapping.get('credit', [])
        if deb and cred:
            df2['amount'] = df2[deb[0]].fillna('0').astype(str).str.replace(',','.')
            df2['amount'] = pd.to_numeric(df2['amount'], errors='coerce') * -1
            cr = pd.to_numeric(df2[cred[0]].fillna(0).astype(str).str.replace(',','.'), errors='coerce')
            df2['amount'] = df2['amount'].fillna(0) + cr.fillna(0)
        else:
            # Tentative de conversion directe
            possible = (mapping.get('amount') or cols)[0]
            s = df2[possible].astype(str).str.replace(r'[^\d\-,\.\s]', '', regex=True)
            s = s.str.replace(r'\s', '', regex=True).str.replace(',', '.')
            df2['amount'] = pd.to_numeric(s, errors='coerce')

Traitement des cas réels et snippets.

  • Formats de date variés : Utiliser pandas.to_datetime(df[‘date’], dayfirst=True, errors=’coerce’).
  • Séparateurs décimaux et milliers : Prétraiter par replace pour normaliser espace et virgule, puis pd.to_numeric.
  • Devises multiples : Extraire avec regex r'([A-Z]{3})’ puis normaliser via taux ou champ currency.
  • Colonnes manquantes : Compléter par règles (amount = credit-debit) et logger anomalies.
  • Transactions en double : Détecter par groupby([‘date’,’amount’,’description’]).size() et garder le plus récent.
  • Libellés multi‑ligne : Remplacer ‘\\n’ par ‘ ‘ et normaliser espaces.

Tests et validation.

  • Fournir jeux sample_data/ couvrant cas: séparateurs, devises, formats date.
  • Assertions de schéma: colonnes [‘date’,’description’,’amount’,’currency’] présentes et types valides.
  • Vérifier idempotence: réappliquer la normalisation doit donner le même résultat.
  • Logger anomalies: lignes non converties, montants NaN, devises inconnues.
# Mini-box: normalisation finale
df['date'] = pd.to_datetime(df['date'], dayfirst=True, errors='coerce')
df['description'] = df['description'].astype(str).str.replace(r'\s+', ' ', regex=True).str.strip()
df['amount'] = pd.to_numeric(df['amount'], errors='coerce')
Étape Sortie attendue Règle de gestion
Détection colonnes mapping dict Regex + score + fallback manuel
Nettoyage montants Colonne amount numérique Débits négatifs, crédits positifs
Normalisation dates Date ISO dayfirst=True, fallback parsing
Validation Schéma validé Assertions + log anomalies

Quels modèles ML pour classer les transactions et détecter les anomalies

Pour petits jeux de données, combiner un classifieur léger (LogisticRegression ou RandomForest) pour catégorisation et un détecteur non supervisé (IsolationForest ou LocalOutlierFactor) pour anomalies fonctionne bien.

Je fournis ici une méthode pragmatique, code opérable et règles simples pour industrialiser rapidement un analyste financier IA local.

1) Pipeline d’ingénierie des features.

Voici les features essentielles :

  • Montant : Valeur brute de la transaction en devise principale.
  • Montant absolu : Utile pour homogénéiser dépenses/remboursements.
  • Signe : Débit/Crédit encodé en binaire ou catégorie.
  • Jour de la semaine : Capture de patterns hebdomadaires.
  • Période du mois : Début/milieu/fin pour salaires et prélèvements.
  • Description (texte) : TF‑IDF ou embedding léger pour capter mots-clés.
  • Merchant : Encodage fréquentiel ou target‑encoding si assez de données.
  • Fréquence par compte : Nombre de transactions similaires sur fenêtre glissante.

2) Exemples de code sklearn.

# Classification pipeline avec LogisticRegression
import joblib
import pandas as pd
from sklearn.compose import ColumnTransformer
from sklearn.feature_extraction.text import TfidfVectorizer
from sklearn.preprocessing import StandardScaler, OneHotEncoder
from sklearn.linear_model import LogisticRegression
from sklearn.model_selection import cross_val_score
from sklearn.pipeline import Pipeline

# Colonnes
num_cols = ['amount','abs_amount','frequency']
cat_cols = ['sign','merchant']
text_col = 'description'

# Pipeline
num_pipe = Pipeline([('scaler', StandardScaler())])
cat_pipe = Pipeline([('ohe', OneHotEncoder(handle_unknown='ignore'))])
text_pipe = Pipeline([('tfidf', TfidfVectorizer(max_features=1000))])

pre = ColumnTransformer([
    ('num', num_pipe, num_cols),
    ('cat', cat_pipe, cat_cols),
    ('text', text_pipe, text_col)
])

clf = Pipeline([('pre', pre), ('lr', LogisticRegression(max_iter=1000))])

# Entraînement et validation croisée
# X, y doivent être définis (pandas DataFrame/Series)
scores = cross_val_score(clf, X, y, cv=5, scoring='f1_macro')
clf.fit(X, y)
joblib.dump(clf, 'clf_joblib.pkl')
# Chargement
clf_loaded = joblib.load('clf_joblib.pkl')
preds = clf_loaded.predict(X_test)
# Détection d'anomalies avec IsolationForest
from sklearn.ensemble import IsolationForest
iso = IsolationForest(contamination=0.01, random_state=42)
# Utiliser uniquement features numériques et encodées
features = pre.fit_transform(X)  # ou construire un pipeline dédié
iso.fit(features)
scores = iso.decision_function(features)  # plus bas = plus anormal
anoms = iso.predict(features)  # -1 anomalie, 1 normal
joblib.dump(iso, 'iso_joblib.pkl')

3) Stratégies pour petits jeux de données.

Je recommande :

  • Augmentation faible : Synthèse de descriptions par règles ou paraphrases contrôlées.
  • Cross‑validation K‑Fold : Maximiser usage des labels disponibles.
  • Règles heuristiques : Renforcer labels fragiles (vendor matches, montants récurrents).
  • Seuils adaptatifs : Ajuster contamination d’IsolationForest par période.
  • Calibration : Appliquer Platt scaling via CalibratedClassifierCV si probabilités nécessaires.

4) Métriques et réentraînement incrémental.

Surveiller précision, rappel et F1 pour la catégorisation, et taux de faux positifs (FPR) pour anomalies.

Capturer corrections utilisateur et réentraîner périodiquement : conserver un buffer de corrections, lancer un réentraînement batch hebdo ou utiliser modèles supportant partial_fit (SGDClassifier) pour mises à jour rapides.

Modèle Complexité Besoin en données Latence Robustesse aux outliers
LogisticRegression Faible Faible‑Moyen Très faible Moyenne
RandomForest Moyenne Moyen Moyenne Bonne (mais sensibles aux noise)
IsolationForest Faible Faible Très faible Excellente pour anomalies
LocalOutlierFactor Moyenne Moyen Variable (voisinage) Bonne mais sensible au choix de k

Comment intégrer un LLM local et une interface interactive en gardant la confidentialité

Intégrer un LLM local (Ollama, llama.cpp ou inference locale via Hugging Face) via une API locale et conserver toute la chaîne de données en local permet d’obtenir des insights en langage naturel sans exposer les données.

1) Options techniques pour LLM local et exigences matérielles.

  • Ollama : Solution simple pour déployer et exposer un modèle local via un serveur HTTP; recommandé pour prototypage rapide.
  • llama.cpp : Moteur d’inférence optimisé CPU (format GGML). GGML signifie une représentation quantifiée optimisée pour CPU.
  • Hugging Face Transformers : Flexibilité GPU/CPU, meilleure pour modèles >13B et pipelines personnalisés.
  • Exigences approximatives : Modèles 7B utilisables sur CPU en GGML (8–16 Go de RAM selon quantification). Modèles >13B préférables sur GPU (16–48 Go VRAM) pour latences acceptables.

2) Architecture d’intégration et template de prompt.

  • Architecture : Wrapper REST local (Ollama server ou petit FastAPI/Flask) appelé depuis Streamlit pour l’interface interactive.
  • Template de prompt : Résumer dépenses, détecter anomalies, générer recommandations actionnables.
Prompt Template:
Vous êtes un analyste financier. Résumez les dépenses mensuelles: {monthly_summary}.
Listez les 10 principaux marchands: {top_10_merchants}.
Signalez anomalies détectées: {anomalies_detected}.
Fournissez 3 recommandations actionnables, priorité et estimation d'impact en euros.

3) Privacy : anonymisation et règles minimales de contexte.

  • Remplacer IBAN/PAN par tokens (ex: IBAN_XXXX), supprimer noms clients si non nécessaires.
  • Appliquer règles minimales de contexte : n’envoyer que les agrégats nécessaires (somme, moyenne, top N) plutôt que les transactions brutes.

4) UX : visualisations liées à la génération LLM.

  • Lier Plotly : Sélection d’une période dans Plotly déclenche recalcul des features puis nouveau prompt.
  • Latence : Afficher spinner et utiliser streaming si le serveur le supporte pour rendre la génération progressive.
  • Export : Générer rapports PDF/Markdown localement via wkhtmltopdf ou nbconvert.

5) Exemples de code et limites.

# Exemple HTTP Ollama (curl)
curl -s -X POST "http://localhost:11434/api/generate" -H "Content-Type: application/json" \
-d '{"model":"ggml-model","prompt":"..."}'
# Exemple transformers (pseudo)
from transformers import pipeline
nlp = pipeline("text-generation", model="local-model")
res = nlp(prompt, max_length=512)

Limites : Coût mémoire élevé pour modèles >13B, latence variable en CPU, nécessité d’évaluer hallucinations via jeux de tests et règles de validation.

Option Avantages Contraintes matérielles Cas d’usage
Ollama Déploiement simple, API HTTP CPU/GPU selon modèle Prototype, équipes internes
llama.cpp (GGML) Fonctionne sur CPU, économique 8–16 Go RAM pour 7B Déploiement edge, faible coût
Hugging Face Flexibilité GPU, écosystème riche 16–48 Go VRAM pour >13B Production, modèles grands

Prêt à lancer votre analyste financier IA local ?

Un analyste financier IA privé en local est réalisable en combinant un pipeline de prétraitement robuste, des modèles ML adaptés aux petits jeux de données et un LLM exécuté localement pour synthèses en langage naturel. Ce design garantit confidentialité, contrôle et réactivité : vous conservez vos données, obtenez des insights actionnables et une solution modulaire évolutive. Le bénéfice pour vous : des analyses rapides, privées et explicables, directement sur votre machine.

FAQ

Comment garantir que mes relevés bancaires ne quittent jamais ma machine ?
Exécutez tous les composants (prétraitement, ML, LLM) localement et évitez les services cloud. Utilisez des solutions locales comme Ollama, llama.cpp ou Transformers en local, conservez les fichiers CSV sur disque chiffré et limitez tout appel réseau sortant. Assurez des audits de dépendances et de ports ouverts.
Comment gérer l’hétérogénéité des fichiers CSV bancaires ?
Utilisez un détecteur de colonnes basé sur des motifs regex (COLUMN_PATTERNS) pour mapper dynamiquement les noms vers un schéma standard. Normalisez dates, décimales, devises et combinez debit/credit en une colonne ‘amount’ signée. Testez avec jeux d’exemples variés et logguez les fichiers non conformes.
Quels modèles choisir pour classer et détecter anomalies avec peu de données ?
Pour la classification, des modèles légers comme LogisticRegression ou RandomForest fonctionnent bien. Pour anomalies, IsolationForest ou LocalOutlierFactor sont adaptés. Renforcez les features (TF‑IDF sur description, features temporelles) et surveillez precision/recall et taux de faux positifs.
Comment intégrer un LLM sans exposer de données sensibles ?
Hébergez le LLM localement et appliquez une étape de redaction/anonymisation avant de construire le prompt (masquer IBAN, numéros de carte, noms). Envoyez uniquement les agrégats ou transactions sélectionnées nécessaires à l’explication et conservez les logs localement.
Quelles contraintes matérielles pour un LLM local ?
Les modèles 7B peuvent tourner en mode GGML/llama.cpp sur CPU avec latences acceptables; les modèles >13B demandent GPU (16+ GB VRAM recommandé). Ollama simplifie le déploiement local mais évaluez l’empreinte mémoire et la latence selon vos besoins.

 

 

A propos de l’auteur

Franck Scandolera — expert & formateur en Tracking avancé server‑side, Analytics Engineering, Automatisation No/Low Code (n8n) et intégration de l’IA en entreprise. Responsable de l’agence webAnalyste et de l’organisme de formation Formations Analytics. Références : Logis Hôtel, Yelloh Village, BazarChic, Fédération Française de Football, Texdecor. Dispo pour aider les entreprises => contactez moi.

Retour en haut
BeGenAI