Accueil / Articles

Migrez les démos de vecteurs Redis vers un index partagé Azure AI Search

Déplacer la recherche vectorielle LangGraph des démos Redis vers un index partagé Azure AI Search : déclarer le schéma, filtrer par session, supprimer via une requête, laisser les autres utilisateurs.

Éditeur : REACTAPP.TOP6 min de lecture1396 mots

Sources: From Redis to Azure AI Search: The Full Migration

Pourquoi Redis n’a pas été la solution finale

La recherche vectorielle locale avec Redis est parfaite pour les démonstrations sur ordinateur portable. Les environnements partagés, la recherche garantie par des SLA et l’authentification native d’Azure incitent les équipes à opter pour Azure AI Search. Cette migration conserve le pipeline LangGraph tout en remplaçant le backend vectoriel.

La recherche IA traditionnelle versus ce modèle

La recherche par mots-clés classique classe les résultats en fonction de la superposition lexicale. La solution migrée stocke des embeddings à côté du texte et effectue des recherches en fonction de la similarité sémantique, éventuellement combinée à des filtres. Azure AI Search devient ainsi le système géré pour ces vecteurs.

La seule décision qui a dû changer : index partagé ou index par session

Les démos Redis créent souvent un index jetable par session. Azure AI Search privilégie un index partagé avec un champ de filtre par session (ou locataire). Supprimer tout l’index pour « vider une session » est l’outil inadapté ; la suppression par filtre est la méthode correcte.

uv add langgraph langchain-core langchain-openai langchain-text-splitters \
       azure-ai-documentintelligence azure-core \
       langchain-redis redisvl \
       python-dotenv
def get_vector_store() -> AzureSearch:
    global _vector_store
    if _vector_store is None:
        _vector_store = AzureSearch(
            azure_search_endpoint=config.AZURE_SEARCH_ENDPOINT,
            azure_search_key=config.AZURE_SEARCH_API_KEY,
            index_name=config.AZURE_SEARCH_INDEX_NAME,
            embedding_function=embeddings,
            fields=_FIELDS,
            vector_search_dimensions=config.EMBEDDING_DIMENSIONS,
        )
    return _vector_store
_FIELDS = [
    SimpleField(name="id", type=SearchFieldDataType.String, key=True, filterable=True),
    SearchableField(name="content", type=SearchFieldDataType.String),
    SearchField(
        name="content_vector",
        type="Collection(Edm.Single)",
        searchable=True,
        vector_search_dimensions=config.EMBEDDING_DIMENSIONS,
        vector_search_profile_name="myHnswProfile",
    ),
    SearchableField(name="metadata", type=SearchFieldDataType.String),
    SimpleField(name="session_id", type=SearchFieldDataType.String, filterable=True),
    SimpleField(name="file_name", type=SearchFieldDataType.String, filterable=True),
    SimpleField(name="chunk_index", type=SearchFieldDataType.Int32, filterable=True, sortable=True),
]
state["retrieved"] = vs.similarity_search(
    state["query"],
    k=config.TOP_K,
    filters=f"session_id eq '{state['session_id']}'",
)
def clear_session(session_id: str) -> None:
    vs = get_vector_store()
    results = vs.client.search(
        search_text="*",
        filter=f"session_id eq '{session_id}'",
        select=["id"],
    )
    ids = [r["id"] for r in results]
    if ids:
        vs.delete(ids=ids)
az search service create \
  --name "$SEARCH_SERVICE_NAME" \
  --resource-group "$RESOURCE_GROUP" \
  --location "$LOCATION" \
  --sku basic \
  --partition-count 1 \
  --replica-count 1

SEARCH_ADMIN_KEY=$(az search admin-key show \
  --resource-group "$RESOURCE_GROUP" \
  --service-name "$SEARCH_SERVICE_NAME" \
  --query primaryKey -o tsv)
AZURE_OPENAI_ENDPOINT=https://aif-cus-aisearchegs-dev-01.cognitiveservices.azure.com/
AZURE_OPENAI_API_KEY=<<redacted>>
# AZURE_OPENAI_API_VERSION = os.environ.get("AZURE_OPENAI_API_VERSION", "2024-10-21")
AZURE_OPENAI_EMBEDDING_DEPLOYMENT=text-embedding-3-small
AZURE_OPENAI_CHAT_DEPLOYMENT="gpt-5-mini"
# --- Azure Document Intelligence (used for all file text extraction) ---
DOCUMENTINTELLIGENCE_ENDPOINT=https://adi-cus-aisearchegs-dev-01.cognitiveservices.azure.com/
DOCUMENTINTELLIGENCE_KEY=<<redacted>>
AZURE_SEARCH_ENDPOINT=https://ais-cus-aisearchegs-dev-01.search.windows.net
AZURE_SEARCH_API_KEY=<<redacted>>
AZURE_SEARCH_INDEX_NAME=chat-file-search-index
azure.core.exceptions.HttpResponseError: The vector field 'content_vector'
must have the properties 'dimensions' and 'vectorSearchConfiguration' set.
TypeError: Object of type float32 is not JSON serializable
from azure.search.documents._utils.model_base import SdkJSONEncoder
_original_default = SdkJSONEncoder.default

def _numpy_safe_default(self, o):
    if isinstance(o, np.floating):
        return float(o)
    if isinstance(o, np.integer):
        return int(o)
    return _original_default(self, o)

SdkJSONEncoder.default = _numpy_safe_default
uv run python -m aisearchmanualvectorization.main \
  --session demo1 \
  --files ./source/sample_bank_statement.pdf ./source/sample_loan_agreement.pdf
uv run python -m aisearchmanualvectorization.main \
  --session demo1 \
  --query "What's the overdraft protection fee?"

A: The overdraft protection transfer fee is $10.00 per occurrence.

Sources:
  - sample_bank_statement.pdf (chunk 7): Overdraft Protection...
  - sample_bank_statement.pdf (chunk 8): Interest Rate & Annual Percentage Yield...
  - sample_bank_statement.pdf (chunk 9): Monthly Maintenance Fee...
  - sample_bank_statement.pdf (chunk 3): <td>-$10.44</td> <td>$8,096.52</td>...

Étape par étape : qu’a changé dans le code

get_vector_store() — plus limité à une session

Il renvoie maintenant un client lié au nom d’un index partagé. L’isolation des sessions passe par des filtres de métadonnées, et non par des indexes distincts.

Le schéma des champs — déclaré explicitement

Les dimensions vectorielles, les champs de contenu et les IDs de session filtrables doivent être définis à l’avance. Les valeurs par défaut utilisées auparavant avec Redis ne correspondent pas aux types de champs d’Azure AI Search.

retrieve_node — un filtre en chaîne de caractères plutôt qu’un objet filtrant

Utilisez session_id eq '…' (ou le filtre OData équivalent) afin que les données d’un utilisateur ne se retrouvent pas dans les résultats d’un autre.

clear_session() — suppression par requête, pas par suppression de l’index

Effectuez une suppression filtrée en fonction de la clé de session. La création répétée d’index pour chaque session dépassera les limites du service et ralentira les démarrages initiaux.

Liste de vérification pour la migration

  • Adaptez la dimension d’incorporation au champ vectoriel de l’index
  • Ne ré-incorporez que si le modèle d’incorporation a changé ; sinon, mettez à jour simplement les données existantes
  • Faites fonctionner simultanément Redis et Azure AI Search sur des questions de référence avant le passage au nouveau système
  • Déplacez les secrets dans Key Vault ou une identité gérée chaque fois que c’est possible
  • Mettez à jour les documents de procédure : éliminez les hypothèses du type « un redémarrage de docker pour Redis efface l’état »

Résultats et compromis

Azure AI Search intègre une scalabilité gérée, des outils de portail et un système RBAC. Il ajoute également un délai de provisionnement ainsi qu’une contrainte liée à la conception des index partagés. Pour le graphe de questions-réponses en PDF, le graphe des nœuds est resté stable ; seuls l’adaptateur de stockage et le cycle de vie des sessions ont changé.

Conclusion

Considérez Redis comme des roues d’apprentissage et Azure AI Search comme des pneus routiers. Maintenez l’isolation des sessions dans les filtres, déclarez explicitement le schéma et supprimez les données via des requêtes. L’orchestration LangGraph ne devrait presque pas s’en apercevoir ; si c’est le cas, l’abstraction était trop perméable.

Conseil pour la migration : laissez Redis en mode lecture seule pendant une semaine tandis qu’Azure AI Search gère le trafic de production, en comparant les 3 meilleures réponses sur l’ensemble de questions de référence. Si le taux de correspondance diminue, examinez d’abord les clauses de filtre et les noms des champs avant de blâmer le modèle d’incorporation. La plupart des régressions lors de ce type de migration sont dues à des erreurs dans les filtres, et non à des problèmes mathématiques liés aux vecteurs.

Conseil pour la migration : maintenez Redis en mode lecture seule pendant une semaine tandis qu’Azure AI Search gère le trafic de production, en comparant la superposition des 3 meilleures réponses sur l’ensemble de questions de référence. Si cette superposition diminue, examinez les clauses de filtrage et les noms des champs avant d’accuser le modèle d’incorporation. La plupart des dégradations lors de ce type de migration sont dues à des erreurs de filtrage, et non à des problèmes de mathématiques vectorielles.

Conseil pour la migration : maintenez Redis en mode lecture seule pendant une semaine tandis qu’Azure AI Search gère le trafic de production, en comparant la superposition des 3 meilleures réponses sur l’ensemble de questions de référence. Si cette superposition diminue, examinez les clauses de filtrage et les noms des champs avant d’accuser le modèle d’incorporation. La plupart des dégradations lors de ce type de migration sont dues à des erreurs de filtrage, et non à des problèmes de mathématiques vectorielles.

Conseil pour la migration : maintenez Redis en mode lecture seule pendant une semaine tandis qu’Azure AI Search gère le trafic de production, en comparant la superposition des 3 meilleures réponses sur l’ensemble de questions de référence. Si cette superposition diminue, examinez les clauses de filtrage et les noms de champs avant d’accuser le modèle d’incorporation. La plupart des dégradations lors de ce type de migration sont dues à des erreurs de filtrage, et non à des problèmes de mathématiques vectorielles.

Conseil pour la migration : maintenez Redis en mode lecture seule pendant une semaine tandis qu’Azure AI Search gère le trafic de production, en comparant la superposition des 3 meilleures réponses sur l’ensemble de questions de référence. Si cette superposition diminue, examinez les clauses de filtrage et les noms de champs avant d’accuser le modèle d’incorporation. La plupart des dégradations lors de ce type de migration sont dues à des erreurs de filtrage, et non à des problèmes de mathématiques vectorielles.

Conseil pour la migration : maintenez Redis en mode lecture seule pendant une semaine tandis qu’Azure AI Search gère le trafic de production, en comparant la superposition des 3 meilleures réponses sur l’ensemble de questions de référence. Si cette superposition diminue, examinez les clauses de filtrage et les noms des champs avant d’accuser le modèle d’incorporation. La plupart des dégradations lors de ce type de migration sont dues à des erreurs de filtrage, et non à des problèmes de mathématiques vectorielles.

Conseil pour la migration : maintenez Redis en mode lecture seule pendant une semaine tandis qu’Azure AI Search gère le trafic de production, en comparant la superposition des 3 meilleures réponses sur l’ensemble de questions de référence. Si cette superposition diminue, examinez les clauses de filtrage et les noms des champs avant d’accuser le modèle d’incorporation. La plupart des dégradations lors de ce type de migration sont dues à des erreurs de filtrage, et non à des problèmes de mathématiques vectorielles.

Conseil pour la migration : maintenez Redis en mode lecture seule pendant une semaine tandis qu’Azure AI Search gère le trafic de production, en comparant la superposition des 3 meilleures réponses sur l’ensemble de questions de référence. Si cette superposition diminue, examinez les clauses de filtrage et les noms des champs avant d’accuser le modèle d’incorporation. La plupart des dégradations lors de ce type de migration sont dues à des erreurs de filtrage, et non à des problèmes de mathématiques vectorielles.

Conseil pour la migration : maintenez Redis en mode lecture seule pendant une semaine tandis qu’Azure AI Search gère le trafic de production, en comparant la superposition des 3 meilleures réponses sur l’ensemble de questions de référence. Si cette superposition diminue, examinez les clauses de filtrage et les noms des champs avant d’accuser le modèle d’incorporation. La plupart des dégradations lors de ce type de migration sont dues à des erreurs de filtrage, et non à des problèmes de mathématiques vectorielles.

Conseil pour la migration : maintenez Redis en mode lecture seule pendant une semaine tandis qu’Azure AI Search gère le trafic de production, en comparant la superposition des 3 meilleures réponses sur l’ensemble de questions de référence. Si cette superposition diminue, examinez les clauses de filtrage et les noms de champs avant d’accuser le modèle d’incorporation. La plupart des dégradations lors de ce type de migration sont dues à des erreurs de filtrage, et non à des problèmes de mathématiques vectorielles.

Conseil pour la migration : maintenez Redis en mode lecture seule pendant une semaine tandis qu’Azure AI Search gère le trafic de production, en comparant la superposition des 3 meilleures réponses sur l’ensemble de questions de référence. Si cette superposition diminue, examinez les clauses de filtrage et les noms de champs avant d’accuser le modèle d’incorporation. La plupart des dégradations lors de ce type de migration sont dues à des erreurs de filtrage, et non à des problèmes de mathématiques vectorielles.

Le schéma de la discipline est important à deux reprises : une fois lors de la création de l’index Azure AI Search, et à nouveau lorsque le modèle d’incorporation est mis à jour. Les incohérences de dimensions provoquent des erreurs visibles ; les incohérences dans les champs filtrables se manifestent discrètement sous forme de ensembles de résultats vides. Ajoutez une assertion au démarrage qui lit la définition de l’index et compare les dimensions vectorielles ainsi que les noms des champs de session avec la configuration en cours d’exécution.