EXEMPLE - Audit FinOps Complet
Rapport d'Audit - Système RAG Production
Généré: 2025-01-15T10:30:00 Repo: /mon/projet/rag_api Modèle: gemma4
Synthèse Exécutive
Situation actuelle
- Coût estimé: €820/mois
- Fournisseurs: Ollama (local), SentenceTransformers (embeddings)
- Modèles actifs: Mistral 7B, neural-chat
- Volumétrie: ~5000 requêtes/jour, croissance 20%/mois
Opportunité
- Économie réaliste: €250-350/mois (30-42%)
- Effort: 2-3 semaines implémentation
- Risque qualité: Faible (SLA qualité maintenue >95%)
3 Actions prioritaires
- Reranking RAG → €150/mois, 2 jours, risque faible
- Filtrage métadonnées → €100/mois, 1 jour, risque faible
- Quantization Mistral → €80/mois, 3 jours, risque moyen
Timeline recommandée
- Semaine 1: Quick wins (reranking + filtrage) = €250/mois gain
- Semaine 2-3: Quantization & monitoring = €80/mois supplémentaires
Phase 1 - Découverte
Fichiers & Structure
rag_api/
├── app.py (FastAPI, 280 lignes)
├── indexing/
│ ├── embeddings.py (SentenceTransformers, 150 lignes)
│ ├── chunking.py (80 lignes)
│ └── storage.py (Chroma, 120 lignes)
├── retrieval/
│ ├── search.py (BM25, vector, 200 lignes)
│ └── reranker.py (stub, non implémenté, 30 lignes)
├── llm/
│ ├── inference.py (Ollama wrapper, 180 lignes)
│ └── prompts.py (system prompt, 1500 chars)
├── docker-compose.yml (Ollama, Chroma, Redis)
└── .env (clés API, endpoints)
Python: 28 fichiers (1200 LOC total)
YAML: 4 fichiers (docker-compose, k8s stubs)
Docker: 1 Dockerfile + docker-compose
Appels IA détectés
1. Ollama Inference
- Fichier:
llm/inference.py(ligne 45, 67) - Provider: Ollama
- Modèles: mistral:7b-instruct, neural-chat:7b-v3
- Max tokens: 2048 (max_output=1024)
- Température: 0.5 (default), 0.2 (recherche)
- Contexte: system_prompt (1500 chars) + documents (variable)
- Fréquence: Toutes les 5000 requêtes/jour
- Détail:
def generate(query, context, model="mistral"):
response = ollama.generate( model=model, prompt=f"{SYSTEM_PROMPT}\n\nContext:
{context}\n\nQuery: {query}", stream=False,
temperature=0.5, top_p=0.9, top_k=40, num_ctx=2048, #
context window num_predict=1024 )
2. SentenceTransformers Embeddings
- Fichier:
indexing/embeddings.py(ligne 20) - Model: all-MiniLM-L6-v2 (22M params, ~384 dims)
- Fréquence: Indexation hebdomadaire (300 docs = 300 embeddings)
- Détail:
embedder = SentenceTransformer('all-MiniLM-L6-v2')embeddings =
embedder.encode(documents, batch_size=32) # GPU
Infrastructure
Docker containers (docker-compose):
✓ ollama (image: ollama/ollama:latest)
- Port: 11434
- Volume: /root/.ollama (25GB)
- GPU: NVIDIA A10 (24GB)
✓ chroma (image: chromadb/chroma:latest)
- Port: 8000
- Volume: chroma_data
✓ redis (image: redis:latest)
- Port: 6379
- Cache query_embeddings
✗ Kubernetes: Non utilisé (prêt pour scaling)
GPU: NVIDIA A10 (24GB VRAM)
- Ollama: ~12GB Mistral loaded
- SentenceTransformers: ~2GB during indexing
- Headroom: 10GB
Configuration
.env:
OLLAMA_URL=http://localhost:11434
OLLAMA_MODEL=mistral:7b-instruct
EMBEDDING_MODEL=all-MiniLM-L6-v2
CHROMA_HOST=localhost
REDIS_HOST=localhost
BATCH_SIZE=32
TOP_K=10 # RAG top docs
MAX_CONTEXT_LENGTH=2000
Logs & Observabilité
Logs détectés:
✓ app.log (FastAPI uvicorn, 2.5MB, 1 week data)
- Requests: 35000/week
- Errors: 0.2%
- P95 latency: 350ms
✓ inference.log (Ollama calls, 500KB)
- Calls: 5000/day (avg)
- Fail rate: <0.1%
✗ Métriques Prometheus: Absent
✗ Monitoring GPU: Absent (ajou
ter!)
Hypothèses de volumétrie
| Métrique | Valeur | Confiance | Source |
|---|---|---|---|
| Requêtes/jour | 5000 | Haut | Logs app.log |
| Requêtes/mois | ~150k | Haut | Extrapolation |
| Avg docs retrieved | 10 | Moyen | Code top_k=10 |
| Avg doc size | 200 tokens | Moyen | Estimation |
| Indexation/mois | 1 (weekly) | Haut | Schedule |
Phase 2 - Baseline
Décomposition par poste
A) Tokens Entrée (RAG + system prompt)
Par requête:
- System prompt: 450 tokens
- RAG documents (10 × 200): 2000 tokens
- Query: 50 tokens
= 2500 tokens/requête (total)
Mensuel:
- 150k requêtes × 2500 tokens = 375M tokens/mois
- À $0.001/1M tokens = €375/mois
Hypothèses:
- SentenceTransformers gratuit (local)
- Coûts = GPU amortis (A10: €200/mois)
- Réalité: €200/mois (GPU) + €375/mois tokens = €575/mois
B) Tokens Sortie
Par requête:
- Avg output: 200 tokens
Mensuel:
- 150k requêtes × 200 tokens = 30M tokens/mois
- Ollama local: €0 (coût GPU amorti)
- Real cost: inclus GPU (€200/mois shared)
C) Infrastructure
GPU A10 (24GB): €250/mois cloud
- Utilisé: Ollama + SentenceTransformers
- Utilisation: 45% (temps moyen)
- Amortissement: €250/mois
Chroma vector DB: €0 (local)
Redis cache: €0 (local)
Network/Bandwidth: ~€20/mois
D) Embeddings
Indexation hebdomadaire:
- 300 docs × 384 dims = 86KB vectorial data
- Coût: GPU (amortis dans A10)
Récapitulatif coûts
| Poste | Estimation | Confiance |
|---|---|---|
| GPU (Ollama + embeddings) | €200/mois | Moyen |
| Tokens entrée | €375/mois | Moyen |
| Tokens sortie | €0 (amortis) | Moyen |
| Infrastructure (réseau, storage) | €20/mois | Faible |
| Buffer (10% imprévu) | €82/mois | Faible |
| TOTAL | €677/mois | - |
Note de confiance: Moyen. Manquent logs détaillés Ollama (tokens réels vs estimés).
Recommandation Phase 2
Instrumentation prioritaire:
# Ajouter loggingTokens réels:
response = ollama.generate(...)
print(f"Prompt tokens: {response['prompt_eval_count']}")
print(f"Response tokens: {response['eval_count']}")
# Puis stocker en Prometheus pour baseline rigide
Phase 3 - Pareto 20/80
Identification des 80%
Classement par coût:
1. GPU infrastructure: €200/mois (30%)
- Non optimizable facilement
- Mais: quantization réduira utilisation
2. Tokens entrée (contexte RAG): €375/mois (55%)
- ⭐ TOP LEVIER - Concentrer efforts ici
- Cause: top_k=10 docs × 200 tokens chaque
- Optimisations: reranking (5 docs) = -50% tokens
3. Autres (réseau, buffer): €102/mois (15%)
- Ignorable pour ROI
Recommandation Phase 3
Focus absolu:
- Réduire tokens d'entrée (€375/mois = 55%)
- Reranking: -50% = €187/mois
- Filtrage métadonnées: -20% = €75/mois
- Historique élagué: -10% = €37/mois
- Total potentiel: €299/mois (44%)
Phase 4 - Quantification par levier
Levier 1: RAG Reranking
Description:
Ajouter CrossEncoder pour reranking des top_k résultats.
Stratégie: Récupérer 10 docs (BM25), rerank avec CE, envoyer 5 meilleurs.
Implémentation:
from sentence_transformers import CrossEncoder
reranker = CrossEncoder('cross-encoder/ms-marco-TinyBERT-L-2-v2')
def reranked_retrieval(query, all_docs):
scores = reranker.predict([[query, doc] for doc in all_docs[:10]])
return [doc for _, doc in sorted(zip(scores, all_docs[:10]), reverse=True)][:5]
Gains estimés:
- Tokens entrée réduits: 10 docs → 5 docs = -50% tokens RAG
- Entrée baseline: 2000 tokens, reranking: 1000 tokens = -1000 tokens/requête
- Mensuel: 150k requêtes × 1000 tokens = -150M tokens = -€150/mois
Effort:
- Intégration: 2 jours
- Testing (100 queries manuellement): 1 jour
- Deployment: 0.5 jour
= 3.5 jours total
Risque qualité:
- Risk: Perte de documents pertinents (top 5 vs top 10)
- Mitigation: Tester precision@5 vs baseline recall@10
- Acceptable: Si F1 ≥ 0.95
Risque latence:
- CrossEncoder ajout: ~50ms par requête
- Baseline P95: 350ms → peut devenir 400ms
- Acceptable si SLA < 500ms
Confiance: MOYEN
- Bien étudié (cross-encoder works well)
- Risque quality: mitigation clear
- Latence impact: mesurable
Gain/effort/risque: ⭐⭐⭐⭐⭐ (QUICK WIN)
Levier 2: Filtrage métadonnées
Description:
Ajouter filtres métadonnées (source, date, topic) avant retrieval.
Réduit documents inutiles.
Implémentation:
# Actuellement: all_docs = vector_db.search(query, top_k=10)
# Après: all_docs = vector_db.search(query, top_k=10,
# where={"source": "current_year"})
Gains estimés:
- Filtrage divise résultats × 0.8 (20% excluded) = -200 tokens/requête
- Mensuel: 150k × 200 tokens = -€100/mois
Effort:
- Schema modification: 1 jour
- Deployment: 0.5 jour
= 1.5 jours
Risque: TRÈS FAIBLE
- Filtrage appliqué en DB, pas en LLM
- Facile à revert si problème
Confiance: HAUT
Gain/effort/risque: ⭐⭐⭐⭐⭐ (QUICK WIN)
Levier 3: Quantization Mistral
Description:
Quantize Mistral 7B INT8 ou GPTQ (baisse VRAM, slightly slower).
Implémentation:
ollama pull mistral:7b-instruct-q8 # au lieu de full F32
Gains estimés:
- VRAM reduction: 12GB → 5GB
- GPU utilization: 45% → 30%
- Power draw: 150W → 100W
- Cost impact: Indirect (less peak power, possibility sous-utilisation)
- Gain: ~€50/mois (meilleure utilisation multi-models)
Latence impact:
- Inference: ~10-15% slower
- Baseline 150ms → 165ms = acceptable
Effort:
- Model switch: 0.5 day
- Testing qualité: 2 days
- Deployment: 0.5 day
= 3 days
Risque qualité:
- INT8 quantization tested widely
- Risk: 1-2% accuracy loss (acceptable)
- Mitigation: Full test on 500 queries
Confiance: MOYEN
- Technique proven
- But quality impact hard to predict exactly
Gain/effort/risque: ⭐⭐⭐⭐☆ (POTENTIAL)
Levier 4: System Prompt Optimization
Description:
Réduire system prompt 1500 chars → 800 chars (garder essentiel).
Current prompt (1500 chars):
"Tu es un assistant RAG. Tu dois répondre à la question basée
sur le contexte fourni. Si le contexte ne contient pas la réponse,
dis 'Je ne sais pas'. Réponds en français. Sois précis et concis.
N'hallucine pas. Cite tes sources. Ne fais pas de suppositions.
Utilise les documents fournis uniquement. Merci."
Optimized (800 chars):
"Réponds basé sur le contexte. Si absent, dis 'Je ne sais pas'.
Sois concis. Cite sources."
Gains estimés:
- Prompt reduction: 450 tokens → 200 tokens = -250 tokens/requête
- Mensuel: 150k × 250 = -€125/mois
Risque qualité:
- HAUT: Instructions moins détaillées
- Risk: Perte de structure (hallucinations augmentées)
- Conclusion: REJECT ce levier (qualité trop importante)
Confiance: FAIBLE
Gain/effort/risque: ⭐⭐☆☆☆ (SKIP - RISQUE QUALITÉ TROP HAUT)
Tableau résumé Phase 4
| Levier | Gain €/mois | % | Effort (j) | Risque | Confiance |
|---|---|---|---|---|---|
| Reranking | €150 | 22% | 3.5 | Faible | Moyen |
| Filtrage métadonnées | €100 | 15% | 1.5 | Très faible | Haut |
| Quantization | €50 | 7% | 3 | Moyen | Moyen |
| System prompt (skip) | €125 | 18% | 2 | ÉLEVÉ | Faible |
| TOTAL EXPLOITABLE | €300 | 44% | 8 | - | - |
Phase 5 - Priorisation
Matrice Impact/Effort
EFFORT (jours)
^
5|
4| ❌ System Prompt ⭐ Quantization
3| (risque élevé) (moyen)
2|
1| ⭐⭐ Filtrage
0| métadonnées
+--|---|---|---|----> GAIN (€/mois)
0 50 100 150 200
⭐⭐ Reranking
Catégorisation
Quick Wins (semaine 1-2)
✅ Filtrage métadonnées
- Gain: €100/mois
- Effort: 1.5 jours
- Risque: Très faible
- Ratio: €66/jour
✅ Reranking RAG
- Gain: €150/mois
- Effort: 3.5 jours
- Risque: Faible
- Ratio: €43/jour
Subtotal: €250/mois (5 jours)
Chantiers (semaine 3+)
⭐ Quantization
- Gain: €50/mois
- Effort: 3 jours
- Risque: Moyen
- Ratio: €17/jour
- Dépend de: Performance tests
Subtotal: €50/mois (3 jours)
À abandonner
❌ System Prompt Optimization
- Risque qualité: TROP HAUT
- Déj compensé par reranking
- SKIP
Plan d'action séquencé
SEMAINE 1: Filtrage + prep Reranking
[Day 1-2] Filtrage métadonnées
☐ Audit schema Chroma
☐ Ajouter filtres (source, date)
☐ Tests unitaires
☐ Deploy staging
[Day 3-5] Reranking development
☐ Setup CrossEncoder model
☐ Intégration retrieval.py
☐ Unit tests
☐ Deploy staging
SEMAINE 2: Testing + Production
[Day 6-7] Full testing
☐ Test filtrage sur 100 requêtes
☐ Test reranking qualité vs baseline
☐ Latency benchmark (P95, P99)
☐ Go/No-go decision
[Day 8-10] Production deployment
☐ Canary deploy (10% traffic)
☐ Monitor 2 days
☐ Full rollout
☐ Post-implementation validation
SEMAINE 3+: Quantization (optionnel)
[Day 11-13] Quantization testing
☐ Download mistral:q8
☐ Quality eval (500 queries)
☐ Latency benchmark
☐ Decision
[Day 14-16] Production
☐ Deploy if validated
☐ Monitor gains
Critères de validation avant/après
FILTRAGE MÉTADONNÉES:
Before:
- Docs returned: 10
- Tokens/requête: 2000
- Success rate: 97%
After:
- Docs returned: 8 (expected)
- Tokens/requête: 1600
- Success rate: ≥96% (target: no degradation >1%)
Gate: Si success_rate < 96% → ROLLBACK
RERANKING:
Before:
- Top-5 overlap with humans: 80% (F1 score)
- Latency P95: 350ms
- Success rate: 97%
After:
- Top-5 overlap: ≥75% (target: <5% loss)
- Latency P95: ≤400ms (target: <50ms increase)
- Success rate: ≥96%
Gate: Si F1 < 0.75 ou latency > 450ms → ROLLBACK
QUANTIZATION:
Before:
- BLEU score on 100 test queries: 0.82
- Latency P95: 350ms
After:
- BLEU score: ≥0.81 (target: <1% loss)
- Latency P95: ≤380ms (target: <10% increase)
Gate: Si BLEU < 0.81 → revert to F32
Phase 6 - Livrable Final
Synthèse exécutive (pour direction)
AUDIT FINOPS - SYSTÈME RAG
Rapport directif pour C-Level
Situation:
- Coût mensuel: €677/mois
- Fournisseur: Ollama local + GPU cloud
- Charge: 5000 req/jour, croissance 20%/mois
Opportunité:
- Économie identifiée: €250-300/mois (37-44%)
- Timeline implémentation: 2-3 semaines
- Risque qualité: Faible (SLA quality maintained >95%)
- ROI: Payback en ~1 mois
Recommandations:
1. ✅ Reranking RAG (€150/mois, 3.5j, low risk) → ASAP
2. ✅ Filtrage métadonnées (€100/mois, 1.5j, v.low risk) → ASAP
3. ⭐ Quantization (€50/mois, 3j, med risk) → Après testing
Approval:
[ ] Approuver implémentation semaine 1-2
[ ] Prevoir ressources: 1 dev fulltime (2 weeks)
[ ] Budget monitoring: Mesure gains m+1
Plan d'action détaillé
OBJECTIF: Réduire coûts OpEx de €250/mois tout en préservant qualité
SEMAINE 1-2: QUICK WINS (€250/mois gain)
├─ Filtrage métadonnées (€100/mois)
│ ├─ Effort: 1.5j
│ ├─ Risque: Très faible
│ └─ Actions:
│ 1. Audit schema Chroma (30min)
│ 2. Ajouter filtres source/date (4h)
│ 3. Tests + deploy staging (4h)
│ 4. Prod deploy (2h)
│
└─ Reranking RAG (€150/mois)
├─ Effort: 3.5j
├─ Risque: Faible
└─ Actions:
1. Setup CrossEncoder (4h)
2. Intégration retrieval.py (6h)
3. Quality testing (8h, 100 queries manual eval)
4. Latency benchmark (4h)
5. Staging deploy + monitor (4h)
6. Prod deploy (2h)
SEMAINE 3+: CHANTIERS OPTIONNELS (€50/mois additionnel)
└─ Quantization Mistral INT8 (€50/mois)
├─ Effort: 3j (si approved)
├─ Risque: Moyen
└─ Actions:
1. Download mistral:q8 (1h)
2. Quality eval (16h, 500 queries)
3. Latency impact analysis (4h)
4. Decision gate (pass/fail)
5. Deploy if approved (2h)
VALIDATION:
- Pre-implementation baseline: Run validate_finops.py baseline
- Post-implementation (day 14): Run validate_finops.py measure
- Comparison: Attendez €250/mois économies + qualité préservée
Risques et contingencies
RISQUE 1: Reranking dégradé qualité
├─ Probabilité: Basse (technique proven)
├─ Impact: Élevé (user satisfaction)
└─ Mitigation:
- Tester sur 100 queries avant prod
- Métriques claires (F1 ≥ 0.75)
- Rollback plan: 1h si nécessaire
RISQUE 2: Latence augmente > SLA (500ms)
├─ Probabilité: Moyenne (CrossEncoder + Retrieval)
├─ Impact: Moyen (user experience)
└─ Mitigation:
- Benchmark avant prod
- Target P95 ≤ 400ms
- Cache CrossEncoder scores si nécessaire
RISQUE 3: Filtrage exclut requêtes valides
├─ Probabilité: Basse (métadonnées bien structurées)
├─ Impact: Moyen (edge cases)
└─ Mitigation:
- Audit filtres sur 50 queries
- Fallback: full search si score trop bas
- Success rate ≥ 96%
MITIGATION GLOBALE:
- Staging deployment 48h avant prod
- Canary deploy (10% traffic) day 1
- Monitoring continu (Prometheus metrics)
- Incident runbook prêt
- Rollback plan < 1h pour chaque composant
Métriques post-implémentation
À MESURER (Daily for week 1-4 post-implementation):
Tokens & Costs:
☐ Tokens d'entrée moyenne: baseline 2500 → target 1600
☐ Estimation coût mensuel: baseline €677 → target €400
Quality:
☐ Success rate: baseline 97% → target ≥96%
☐ F1 score (reranking): baseline — → target ≥0.75
☐ BLEU score (quantization): baseline 0.82 → target ≥0.81
Performance:
☐ Latency P50: baseline 150ms → target ≤170ms
☐ Latency P95: baseline 350ms → target ≤420ms
☐ GPU utilization: baseline 45% → target 35% (quantization)
Business:
☐ Monthly cost: baseline €677 → target €400-427
☐ Savings realized: target €250-277/month
☐ User satisfaction: baseline 4.2/5 → target ≥4.0/5
DECISION GATES:
- Day 7: Success rate ≥95%? → Continue, else rollback
- Day 14: Latency P95 ≤450ms? → Continue, else tune
- Day 30: Cost ≤€450/month? → Declare success, else iterate
Timeline et dépendances
┌─────────────────────────────────────────────────┐
│ PHASE 1: APPROVALS (Day -2 to 0) │
│ ├─ Technical review passed ✓ │
│ └─ Management approval │
└─────────────────────────────────────────────────┘
↓
┌─────────────────────────────────────────────────┐
│ PHASE 2: QUICK WINS (Week 1-2, Day 1-10) │
│ ├─ Filtrage métadonnées (Day 1-2) [▓▓░] │
│ ├─ Reranking development (Day 2-5) [▓▓▓░] │
│ ├─ Full testing (Day 6-7) [▓▓░░] │
│ └─ Production deploy (Day 8-10) [▓░░░] │
│ │
│ Expected gain: €250/month │
└─────────────────────────────────────────────────┘
↓
┌─────────────────────────────────────────────────┐
│ PHASE 3: VALIDATION & MONITORING (Week 3-4) │
│ ├─ Daily metrics collection [░░░░░] │
│ ├─ Decision point: Go for Quantization? Day 14 │
│ └─ Prepare next optimization if approved │
└─────────────────────────────────────────────────┘
↓
┌─────────────────────────────────────────────────┐
│ PHASE 4: QUANTIZATION (Optional, Week 3+) │
│ ├─ If approved: Test & deploy (3 days) │
│ └─ Additional gain: €50/month │
└─────────────────────────────────────────────────┘
Checklist finale
Avant déploiement:
[ ] Direction approval signée
[ ] Technical review complétée
[ ] Staging tests passés (F1 ≥0.75, latency ≤400ms)
[ ] Monitoring setup (Prometheus, Grafana)
[ ] Incident runbook prêt
[ ] Rollback procedure testé
[ ] Team training complétée
Week 1-2 (Implementation):
[ ] Filtrage métadonnées deployed + monitored
[ ] Reranking tested & deployed
[ ] Canary deployment (10% traffic) stable
[ ] Full rollout prepared
Week 3-4 (Validation):
[ ] Cost reduction ≥€200/month (target €250)
[ ] Quality metrics ≥96% (success rate)
[ ] User satisfaction maintained (≥4.0/5)
[ ] Performance SLA met (P95 ≤420ms)
[ ] No critical incidents
Post-validation:
[ ] Decision: quantization yes/no
[ ] Quarterly re-audit scheduled (Q2 2025)
[ ] Architecture docs updated
[ ] Cost controls implemented (budget alerts)
Document: Exemple - Audit FinOps Complet Généré: 2025-01-15 Status: EXEMPLE À titre informatif Prochaine révision: Q2 2025 (3 mois)
Pierre Erol GIRAUDY — Expert IA Souveraine & Gouvernance. Créateur du framework UGAIA/AFEES©. Auteur : Gouvernance et Audit de l’Intelligence Artificielle et ses Outils — 3ᵉ éd. 2026.
UGAIA© · AFEES© · Andorra · Avril 2026 · www.UGAIA.eu

Aucun commentaire:
Enregistrer un commentaire