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
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.
⭐ Analytics engineer, Data Analyst et Automatisation IA indépendant ⭐
- Ref clients : Logis Hôtel, Yelloh Village, BazarChic, Fédération Football Français, Texdecor…
Mon terrain de jeu :
- Data Analyst & Analytics engineering : tracking avancé (GTM server, e-commerce, CAPI, RGPD), entrepôt de données (BigQuery, Snowflake, PostgreSQL, ClickHouse), modèles (Airflow, dbt, Dataform), dashboards décisionnels (Looker, Power BI, Metabase, SQL, Python).
- Automatisation IA des taches Data, Marketing, RH, compta etc : conception de workflows intelligents robustes (n8n, App Script, scraping) connectés aux API de vos outils et LLM (OpenAI, Mistral, Claude…).
- Engineering IA pour créer des applications et agent IA sur mesure : intégration de LLM (OpenAI, Mistral…), RAG, assistants métier, génération de documents complexes, APIs, backends Node.js/Python.






