faq-backend-api / README_api.md
Loren's picture
First commit
b36f0fe
|
Raw History Blame Contribute Delete
7.18 kB
---
title: API FAQ - Embeddings Multilingues
description: API FastAPI pour répondre à des questions via recherche de similarité sur une base FAQ avec embeddings multilingues
sdk: docker
---
# API FAQ - Embeddings Multilingues
API FastAPI permettant de répondre à des questions en cherchant la réponse la plus similaire dans une base FAQ via recherche d'embeddings multilingues.
## Caractéristiques
- 🌍 **Multilingue** : Utilise le modèle `intfloat/multilingual-e5-small` pour supporter plusieurs langues
- 🚀 **Rapide** : Recherche par similarité cosinus via ChromaDB
- 📊 **Seuil configurable** : Filtrage des réponses selon un seuil de confiance
- 📝 **Type-safe** : Utilise Pydantic pour la validation des données
- 📚 **Documentation interactive** : Swagger UI intégrée via `/docs`
## Architecture
```
app.py # Point d'entrée FastAPI
├── models.py # Modèles Pydantic (QuestionInput, AnswerOutput)
├── config.py # Configuration centralisée
├── faq_loader.py # Chargement de la FAQ au format JSON
├── embeddings.py # Gestion ChromaDB + modèle transformers
└── data/
└── faq.json # Exemple de base FAQ (intentions, formulations, réponses)
```
## Installation locale
### Prérequis
- Python 3.8+
- pip ou conda
### Étapes
1. **Cloner le repository** (ou télécharger les fichiers)
```bash
git clone <url>
cd faq-backend-api
```
2. **Créer un environnement virtuel** (recommandé)
```bash
python -m venv venv
# Windows
venv\Scripts\activate
# Linux/Mac
source venv/bin/activate
```
3. **Installer les dépendances**
```bash
pip install -r requirements.txt
```
4. **Configurer les variables d'environnement** (optionnel)
```bash
cp .env.example .env
# Éditer .env si nécessaire
```
5. **Lancer l'application**
```bash
uvicorn app:app --reload
```
L'API sera accessible à `http://localhost:8000`
## Utilisation
### Endpoint principal : POST `/ask`
Poser une question et obtenir la réponse la plus similaire
**Requête :**
```json
{
"question": "Est-ce que c’est gratuit ?"
}
```
**Réponse :**
```json
{
"question": "Est-ce que c’est gratuit ?",
"formulation": "Est-ce que c’est gratuit ?",
"answer": "Oui. L’adhésion et la participation aux projets de l'association sont gratuites. Il n’y a ni frais de formation ni cotisation obligatoire pour contribuer aux projets.",
"theme": "est_ce_que_c_est_gratuit",
"similarity_score": 0.95,
"confidence": true
}
```
**Champs de réponse :**
- `question` : Question posée
- `formulation` : Formulation de la FAQ qui correspond le mieux à la question
- `answer` : Réponse trouvée dans la FAQ
- `theme` : Intention de la FAQ (`intent_key`)
- `similarity_score` : Score de similarité cosinus [0, 1]
- `confidence` : `true` si le score ≥ seuil de confiance, `false` sinon
### Endpoint santé : GET `/health`
Vérifier l'état du service et le nombre de FAQs indexées
**Réponse :**
```json
{
"status": "ok",
"faq_count": 474
}
```
### Documentation interactive : GET `/docs`
Accéder à la documentation Swagger UI interactive :
```
http://localhost:8000/docs
```
## Tests
### Avec curl
```bash
# Test question connue
curl -X POST "http://localhost:8000/ask" \
-H "Content-Type: application/json" \
-d '{"question": "Est-ce que c’est gratuit ?"}'
# Test question inconnue
curl -X POST "http://localhost:8000/ask" \
-H "Content-Type: application/json" \
-d '{"question": "Comment faire des crêpes ?"}'
# Health check
curl "http://localhost:8000/health"
```
### Avec Python
```python
import requests
url = "http://localhost:8000/ask"
response = requests.post(url, json={"question": "Est-ce que c’est gratuit ?"})
print(response.json())
```
### Avec Postman ou Insomnia
Importer la collection depuis `/docs` ou créer manuellement une requête POST vers `/ask`
## Configuration
### Variables d'environnement
Créer un fichier `.env` (voir `.env.example`) pour configurer :
```env
# Modèle d'embedding
MODEL_NAME=intfloat/multilingual-e5-small
# Seuil de confiance [0.0, 1.0]
# 0.5 par défaut
SIMILARITY_THRESHOLD=0.5
```
### Fichiers de données
Le fichier d'exemple `data/faq.json` illustre le format attendu (chemin défini par `FAQ_JSON_PATH` dans `config.py`). Il contient une liste `intents` ; chaque intent activé (`enabled: true`) comporte :
- `intent_key` : identifiant de l'intention (renvoyé comme `theme`)
- `canonical_question` et `utterances` : formulations de la question
- `response` : réponse associée
Les FAQs sont chargées et indexées au démarrage de l'application.
## Hugging Face
L'API est déployée sur Hugging Face Spaces (runtime Docker) : **https://loren-faq-backend-api.hf.space**
| Ressource | URL |
|---|---|
| Swagger UI | https://loren-faq-backend-api.hf.space/docs |
| Question (POST) | https://loren-faq-backend-api.hf.space/ask |
| Santé | https://loren-faq-backend-api.hf.space/health |
| Configuration | https://loren-faq-backend-api.hf.space/config |
Exemple :
```bash
curl -X POST "https://loren-faq-backend-api.hf.space/ask" -H "Content-Type: application/json" -d '{"question": "Comment je deviens membre ?"}'
```
### Configuration
Dans l'interface du Space, "Settings" → "Variables and secrets" permet de définir les variables d'environnement (ex : `SIMILARITY_THRESHOLD=0.6`). Les logs de build et d'exécution sont consultables depuis l'onglet "Logs".
### Démarrage
Le démarrage (~30-60s) comprend :
1. Installation des dépendances
2. Téléchargement des modèles (embeddings et cross-encoder)
3. Chargement de la FAQ
4. Génération des embeddings
Après une période d'inactivité, le Space peut être mis en veille : la première requête peut alors prendre quelques dizaines de secondes.
## Architecture ChromaDB
### EphemeralClient (Option utilisée)
Les embeddings sont chargés en mémoire au démarrage et recalculés à chaque redémarrage :
**Avantages :**
- ✓ Plus rapide (pas d'I/O disque)
- ✓ Pas de dépendance de persistance
- ✓ Idéal pour HF Spaces (ressources limitées)
**Inconvénients :**
- Les embeddings sont recalculés à chaque déploiement (~30s)
### PersistentClient (Alternative)
Si vous préférez persister les embeddings sur disque, remplacer `EphemeralClient` par `PersistentClient` dans `embeddings.py`.
## Considérations de performance
- **Modèle** : `multilingual-e5-small` (~50MB)
- **Threshold** : Augmenter pour être plus strict, réduire pour plus de matches
- **Top-k** : 3 par défaut (`TOP_K` dans `config.py`) : nombre maximum de thèmes distincts retenus comme candidats (`list_candidates`). Peut être surchargé par requête via le champ `top_k` de `/ask`
## Logs
Les logs sont affichés au démarrage et en temps réel :
- 🚀 Démarrage
- 📚 Chargement FAQ
- ✓ Application prête
- 📝 Questions reçues
- ✓/❌ Réponses trouvées