Déploiement d'un système de réponse intelligente pour le tourisme via l'analyse sémantique et les embeddings

Fonctionnement et concepts clés

Un système d'assistance touristique intelligent repose sur deux mécanismes fondamentaux : la vectorisation du contenu et la compréhension des requêtes en langage naturel.

La technique de l'Embedding consiste à convertir une portion de texte, comme la decsription d'un site historique, en une représentation numérique continue appelée vecteur. Ce processus est analogue à attribuer une « empreinte sémantique » unique au texte. Les textes partageant des significations similaires produisent des vecteurs proches dans l'espace vectoriel. Par exemple, les descriptions de la Tour Eiffel et du Champ de Mars auront des vecteurs beaucoup plus proches que celles de la Tour Eiffel et d'un gâteau au chocolat.

Le modèle de langage gte-base-zh, entraîné sur un vaste corpus de textes chinois, excelle à générer ces embeddings en capturant avec précision les nuances et le contexte sémantiques. Son rôle dans un pipeline toruistique est double :

  1. Indexation : Transformer l'ensemble des desrciptions des sites patrimoniaux en vecteurs et les stocker pour constituer une base de connaissances consultable.
  2. Requêtage : Lorsqu'un visiteur pose une question, la convertir en vecteur, puis effectuer une recherche de similarité dans la base de connaissances vectorielle pour identifier le ou les passages les plus pertinents.

Installation et configuration de l'environnement

L'infrastructure nécessite un serveur capable de charger le modèle et d'exposer une API. Nous utiliserons le framework Xinference pour cette tâche.

La méthode recommandée consiste à déployer via un conteneur Docker pour garantir un environnement reproductible. Exécutez la commande suivante :

docker run -d \
    --name xinference-server \
    -p 9997:9997 \
    -v /chemin/vers/vos/modeles:/models \
    xprobe/xinference:latest \
    xinference-local --host 0.0.0.0 --port 9997

Assurez-vous que le chemin monté (/chemin/vers/vos/modeles) contient les fichiers du modèle gte-base-zh. Une fois le conteneur lancé, l'interface web d'administration est accessible via http://localhost:9997. Depuis cette interface, vous pouvez démarrer une instance du modèle en spécifiant son chemin interne au conteneur.

Pour vérifier le bon fonctionnement, testez la similarité sémantique entre deux phrases via l'interface de test intégrée. Des phrases sémantiquement proches devraient retourner un score élevé (proche de 1.0).

Construction d'une base de connaissances vectorielle

Le premier volet applicatif consiste à convertir les données textuelles des sites touristiques en vecteurs. Prenons un jeu de données exemple avec des sites français :

import requests
import numpy as np

# Configuration de l'appel à l'API Xinference
API_URL = "http://localhost:9997/v1/embeddings"
MODEL_ID = "gte-base-zh"

# Base de données brute des sites
points_of_interest = [
    {
        "identifier": "TourEiffel",
        "content": "La Tour Eiffel, monument emblématique de Paris construit par Gustave Eiffel pour l'Exposition universelle de 1889, s'élève à 330 mètres. Elle est la structure la plus visitée au monde."
    },
    {
        "identifier": "MontSaintMichel",
        "content": "Le Mont-Saint-Michel est une île rocheuse située en Normandie. Célèbre pour son abbaye bénédictine perchée au sommet, elle est bordée par de vastes baies aux courants puissants et changeants."
    },
    {
        "identifier": "Louvre",
        "content": "Le Musée du Louvre, ancien palais royal, est le plus grand musée d'art et d'antiquités du monde. Il abrite des œuvres capitales comme la Joconde et la Vénus de Milo."
    }
]

def fetch_vector_representation(text_input):
    """Interroge le service d'embedding pour obtenir le vecteur d'un texte."""
    payload = {
        "model": MODEL_ID,
        "input": text_input
    }
    try:
        resp = requests.post(API_URL, json=payload, timeout=30)
        resp.raise_for_status()
        response_data = resp.json()
        return response_data['data'][0]['embedding']
    except requests.RequestException as e:
        print(f"Erreur de communication avec le service: {e}")
        return None

# Construction de l'index vectoriel
vector_index = []
for site in points_of_interest:
    vector = fetch_vector_representation(site["content"])
    if vector:
        vector_index.append({
            "id": site["identifier"],
            "original_text": site["content"],
            "vector": np.array(vector)
        })
        print(f"Indexation réussie pour : {site['identifier']}")

print(f"Base vectorielle prête avec {len(vector_index)} entrées.")

Implémentation du moteur de recherche sémantique

La fonction de recherche convertit la question de l'utilisateur en vecteur, puis itère sur la base vectorielle pour calculer la similarité cosinus avec chaque entrée. Le site le plus pertinent est retourné.

def calculate_cosine_similarity(vec_a, vec_b):
    """Calcule la similarité cosinus entre deux vecteurs numpy."""
    dot_product = np.dot(vec_a, vec_b)
    magnitude_a = np.linalg.norm(vec_a)
    magnitude_b = np.linalg.norm(vec_b)
    if magnitude_a == 0 or magnitude_b == 0:
        return 0.0
    return dot_product / (magnitude_a * magnitude_b)

def search_best_match(user_query, max_results=1):
    """Recherche le site le plus similaire à la question de l'utilisateur."""
    query_vector = fetch_vector_representation(user_query)
    if query_vector is None:
        return []

    query_vec_np = np.array(query_vector)
    similarity_scores = []

    for indexed_site in vector_index:
        score = calculate_cosine_similarity(query_vec_np, indexed_site["vector"])
        similarity_scores.append((score, indexed_site))

    similarity_scores.sort(key=lambda item: item[0], reverse=True)
    return similarity_scores[:max_results]

# Exemple d'utilisation
sample_queries = [
    "Où puis-je voir une vue panoramique sur Paris?",
    "Quel musée abrite le tableau le plus célèbre du monde?",
    "Je cherche un site religieux ancien sur une île en Normandie."
]

for query in sample_queries:
    print(f"Requête utilisateur : '{query}'")
    matches = search_best_match(query)
    if matches:
        best_score, best_site = matches[0]
        print(f"-> Site le plus pertinent : {best_site['id']}")
        print(f"   Score de similarité : {best_score:.3f}")
        print(f"   Extrait de description : {best_site['original_text'][:100]}...")
    else:
        print("-> Aucun résultat pertinent trouvé.")
    print("---")

Ce prototype démontre comment un système peut interpréter des requêtes formulées de manière naturelle et libre, sans dépendre de mots-clés exacts, pour extraire des informations structurées à partir d'une base de connaissances textuelles.

Étiquettes: analyse sémantique vecteurs d'embedding modèle de langage Traitement du Langage Naturel Python

Publié le 17 juin à 20h52