# Agent Immobilier — Guide de mise en place

Agent d'analyse immobilière combinant un **agent ReAct LLM** (GPT-4o) et un moteur
d'estimation géographique sans LLM. Couvre le Nord (59) et la Haute-Garonne (31).

---

## Démarrage rapide

```bash
# 1. Dépendances
python -m venv .venv && source .venv/bin/activate   # Windows : .venv\Scripts\activate
pip install -r requirements.txt

# 2. Environnement
cp .env.example .env
# → Éditer .env et renseigner OPENAI_API_KEY

# 3. Lancer l'API (la base de données est initialisée automatiquement)
uvicorn api:app --host 0.0.0.0 --port 8000 --reload
```

Ouvrir <http://localhost:8000/docs> pour l'interface interactive.
Ouvrir <http://localhost:8000/map> pour la carte IRIS interactive.

---

## Prérequis

| Outil | Version minimum | Rôle |
|---|---|---|
| Python | 3.11 | Runtime principal |
| pip | 23+ | Gestionnaire de paquets |
| Docker | 24+ | Langfuse (optionnel) |
| Clé OpenAI | — | Modèles GPT-4o / GPT-4o-mini |

---

## Installation

### 1. Environnement virtuel et dépendances

```bash
python -m venv .venv

# macOS / Linux
source .venv/bin/activate

# Windows (PowerShell)
.venv\Scripts\Activate.ps1

pip install -r requirements.txt
```

### 2. Variables d'environnement

```bash
cp .env.example .env
```

Éditer `.env` :

```dotenv
# Obligatoire
OPENAI_API_KEY=sk-proj-...

# Optionnel — authentification sur /ask et /analysis
# API_KEY=votre-cle-secrete

# Optionnel — observabilité Langfuse (voir § Langfuse)
# LANGFUSE_PUBLIC_KEY=pk-lf-...
# LANGFUSE_SECRET_KEY=sk-lf-...
# LANGFUSE_HOST=http://localhost:3000
```

---

## Fichiers de données

### Structure attendue

```
data/
├── immobilier.db                    ← SQLite (généré au démarrage)
├── Base_OP_2025_Nationale.csv       ← Observatoire des Loyers 2025 — Toulouse
├── DSV.csv                          ← DVF 2025, Haute-Garonne (31), séparateur |
├── 2021/59.csv                      ← DVF géocodé Nord (59)
├── 2022/59.csv
├── 2023/59.csv
├── 2024/59.csv
├── 2025/59.csv
└── 2026/
    ├── iris_nord.geojson            ← Polygones IRIS du Nord — 1 345 quartiers
    ├── iris_prix.json               ← Prix moyen/m² par IRIS (build_iris_data.py)
    ├── iris_securite.json           ← Score de dangerosité par IRIS (build_iris_data.py)
    └── securite_nord_complet.xlsx   ← Scores de délinquance par commune
```

### Fichiers inclus dans le dépôt

- `data/Base_OP_2025_Nationale.csv` — loyers Toulouse
- `data/DSV.csv` — transactions DVF Haute-Garonne 2025
- `data/20{21..25}/59.csv` — DVF géocodé Nord (2021–2025)
- `data/2026/iris_nord.geojson` — polygones IRIS (cache IGN)
- `data/2026/iris_prix.json`, `iris_securite.json` — données pré-calculées
- `data/2026/securite_nord_complet.xlsx` — scores commune

### Fichier généré automatiquement

`data/immobilier.db` est créé et initialisé au premier démarrage de l'API ou du CLI.
Il n'est pas suivi par git (voir `.gitignore`).

---

## Scripts de reconstruction des données

À n'exécuter qu'une seule fois (ou pour mettre à jour les données DVF).
Les fichiers de données pré-calculés sont déjà présents dans le dépôt.

### Ordre recommandé

```bash
# 1. Scores de sécurité par commune (produit securite_nord_complet.xlsx)
python build_securite_nord.py

# 2. Scores IRIS + carte des prix (produit iris_prix.json et iris_securite.json)
#    Télécharge iris_nord.geojson depuis l'IGN Géoplateforme si absent (~150 Mo)
python build_iris_data.py

# 3. Table mutations + table prix_evolution_iris dans immobilier.db
#    Jointure spatiale sur ~163 000 transactions — durée : 5 à 15 min
python build_mutations_iris.py

# 4. Table prix_evolution par commune dans immobilier.db (métropole lilloise)
python build_prix_evolution.py
```

> **Note** : `build_iris_data.py` requiert un accès Internet pour télécharger les
> polygones IRIS depuis l'IGN Géoplateforme (uniquement si `data/2026/iris_nord.geojson`
> est absent).

---

## Lancer l'application

### Mode API (recommandé)

```bash
uvicorn api:app --host 0.0.0.0 --port 8000 --reload
```

| URL | Description |
|---|---|
| <http://localhost:8000/docs> | Documentation interactive (Swagger UI) |
| <http://localhost:8000/dashboard> | Dashboard de monitoring |
| <http://localhost:8000/map> | Carte IRIS interactive (Nord 59) |
| <http://localhost:8000/health> | État du service |
| <http://localhost:8000/metrics> | Métriques de performance |

### Mode CLI

```bash
python main.py
```

Saisir les questions au clavier, ou déposer un fichier `.m4a` dans le dossier
du projet pour une transcription automatique via Whisper.

---

## Endpoints API

### `POST /ask`

Question en langage naturel → agent ReAct (GPT-4o).

```bash
curl -X POST http://localhost:8000/ask \
  -H "Content-Type: application/json" \
  -d '{"question": "Quel est le prix au m² à Lille pour un appartement ?"}'
```

### `POST /analysis`

Estimation de prix sans LLM (algorithme géographique DVF).

```bash
curl -X POST http://localhost:8000/analysis \
  -H "Content-Type: application/json" \
  -d '{
    "adresse": "7 avenue nelson mandela",
    "code_postal": 59290,
    "ville": "wasquehal",
    "surface_m2": 65.0,
    "type_bien": "appartement",
    "statut": "medium",
    "orientation": "sud",
    "taille_terrain": 0.0
  }'
```

### Authentification (optionnelle)

Si `API_KEY` est défini dans `.env`, ajouter le header sur `/ask` et `/analysis` :

```bash
-H "X-API-Key: votre-cle-secrete"
```

---

## Tests

```bash
# Tests unitaires uniquement (aucun token consommé)
pytest

# Inclure les tests d'intégration LLM (consomme des tokens OpenAI)
pytest --run-integration

# Un test spécifique
pytest tests/test_integration.py::test_classifier_analyse -v -m integration
```

Les tests d'intégration sont désactivés par défaut et requièrent `--run-integration`.
Les seuils de qualité LLM sont définis dans `tests/test_qualite.py` (score ≥ 3.0/5).

---

## Observabilité — Langfuse (optionnel)

Langfuse trace toutes les questions, sélections d'outils et scores de qualité LLM.

### Démarrer le stack

```bash
docker compose -f docker-compose__662__0.yml up -d
```

Attendre ~30 secondes, puis ouvrir <http://localhost:3000>.

| Champ | Valeur |
|---|---|
| Email | `formateur@ajc.fr` |
| Mot de passe | `formation2026` |

### Connecter l'agent

Décommenter dans `.env` :

```dotenv
LANGFUSE_PUBLIC_KEY=pk-lf-formation
LANGFUSE_SECRET_KEY=sk-lf-formation
LANGFUSE_HOST=http://localhost:3000
```

Redémarrer le serveur. Les traces apparaissent dans le projet **Agents IA**.

### Arrêter le stack

```bash
docker compose -f docker-compose__662__0.yml down       # conserve les données
docker compose -f docker-compose__662__0.yml down -v    # supprime tout
```

---

## Docker (déploiement)

```bash
# Build
docker build -t agent-immobilier .

# Run
docker run -p 8000:8000 \
  -e OPENAI_API_KEY=sk-proj-... \
  -v $(pwd)/data:/app/data \
  agent-immobilier
```

Monter `data/` en volume pour conserver la base SQLite entre les redémarrages
et éviter de rebaker les fichiers CSV dans l'image.

---

## Architecture résumée

```
Requête utilisateur
       │
       ▼
valider_input()          ← core/security.py  (injection, SQL, longueur)
       │
       ▼
classifier_question()    ← core/llm.py       (GPT-4o-mini)
       │
  ┌────┴──────────────┐
  │                   │
analyse            conversation / hors_scope
  │
  ▼
react_loop()            ← agent/react.py     (max 3 itérations)
  ├── choisir_outil()   ← GPT-4o-mini (orchestrateur)
  ├── exécuter outil    ← tools/
  └── appeler_llm()     ← GPT-4o (réponse finale)
       │
       ▼
memory.store()          ← agent/memory.py    (deque, max 10 messages)
```

### Tables SQLite (`data/immobilier.db`)

| Table | Source | Peuplée par |
|---|---|---|
| `mutations` | DVF 2021–2025, Nord (59), avec IRIS | `build_mutations_iris.py` |
| `prix_evolution_iris` | Prix médian par IRIS / type / année | `build_mutations_iris.py` |
| `prix_evolution` | Prix médian par commune / type / année | `build_prix_evolution.py` |
| `loyers` | Observatoire des Loyers 2025, Toulouse | `setup_db()` au démarrage |

---

## Dépannage

**`ModuleNotFoundError: No module named 'shapely'`**
→ `pip install -r requirements.txt` dans l'environnement virtuel actif.

**`OPENAI_API_KEY` non trouvée**
→ Vérifier que `.env` existe et que la variable est renseignée (pas de guillemets autour de la valeur).

**`Table 'mutations' créée vide`** (warning au démarrage)
→ Normal si `build_mutations_iris.py` n'a pas encore été exécuté. Les fonctionnalités
IRIS et carte des prix ne seront pas disponibles. Exécuter le script (~10 min).

**`iris_nord.geojson` absent**
→ `python build_iris_data.py` le télécharge automatiquement depuis l'IGN Géoplateforme.
Requiert un accès Internet.

**Erreur au démarrage Docker : fichiers CSV manquants**
→ Monter le dossier `data/` en volume : `-v $(pwd)/data:/app/data`.
