azure-search-documents-py

npx skills add https://github.com/microsoft/skills --skill azure-search-documents-py

Azure AI Search SDK pour Python

Recherche full-text, vectorielle et hybride avec capacités d'enrichissement IA.

Installation

pip install azure-search-documents

Variables d'environnement

AZURE_SEARCH_ENDPOINT=https://<service-name>.search.windows.net  # Requis pour toutes les méthodes d'authentification
AZURE_SEARCH_API_KEY=<your-api-key>  # Requis uniquement pour l'authentification AzureKeyCredential
AZURE_SEARCH_INDEX_NAME=<your-index-name>  # Requis pour toutes les méthodes d'authentification

Authentification

Clé API

from azure.search.documents import SearchClient
from azure.core.credentials import AzureKeyCredential

client = SearchClient(
    endpoint=os.environ["AZURE_SEARCH_ENDPOINT"],
    index_name=os.environ["AZURE_SEARCH_INDEX_NAME"],
    credential=AzureKeyCredential(os.environ["AZURE_SEARCH_API_KEY"])
)

Entra ID (Recommandé)

from azure.search.documents import SearchClient
from azure.identity import DefaultAzureCredential

client = SearchClient(
    endpoint=os.environ["AZURE_SEARCH_ENDPOINT"],
    index_name=os.environ["AZURE_SEARCH_INDEX_NAME"],
    credential=DefaultAzureCredential()
)

Types de client

Client Objectif
SearchClient Opérations de recherche et de documents
SearchIndexClient Gestion des index, cartes de synonymes
SearchIndexerClient Indexeurs, sources de données, skillsets

Créer un index avec champ vectoriel

from azure.search.documents.indexes import SearchIndexClient
from azure.search.documents.indexes.models import (
    SearchIndex,
    SearchField,
    SearchFieldDataType,
    VectorSearch,
    HnswAlgorithmConfiguration,
    VectorSearchProfile,
    SearchableField,
    SimpleField
)

index_client = SearchIndexClient(endpoint, AzureKeyCredential(key))

fields = [
    SimpleField(name="id", type=SearchFieldDataType.String, key=True),
    SearchableField(name="title", type=SearchFieldDataType.String),
    SearchableField(name="content", type=SearchFieldDataType.String),
    SearchField(
        name="content_vector",
        type=SearchFieldDataType.Collection(SearchFieldDataType.Single),
        searchable=True,
        vector_search_dimensions=1536,
        vector_search_profile_name="my-vector-profile"
    )
]

vector_search = VectorSearch(
    algorithms=[
        HnswAlgorithmConfiguration(name="my-hnsw")
    ],
    profiles=[
        VectorSearchProfile(
            name="my-vector-profile",
            algorithm_configuration_name="my-hnsw"
        )
    ]
)

index = SearchIndex(
    name="my-index",
    fields=fields,
    vector_search=vector_search
)

index_client.create_or_update_index(index)

Charger des documents

from azure.search.documents import SearchClient

client = SearchClient(endpoint, "my-index", AzureKeyCredential(key))

documents = [
    {
        "id": "1",
        "title": "Azure AI Search",
        "content": "Full-text and vector search service",
        "content_vector": [0.1, 0.2, ...]  # 1536 dimensions
    }
]

result = client.upload_documents(documents)
print(f"Uploaded {len(result)} documents")

Recherche par mot-clé

results = client.search(
    search_text="azure search",
    select=["id", "title", "content"],
    top=10
)

for result in results:
    print(f"{result['title']}: {result['@search.score']}")

Recherche vectorielle

from azure.search.documents.models import VectorizedQuery

# Votre embedding de requête (1536 dimensions)
query_vector = get_embedding("semantic search capabilities")

vector_query = VectorizedQuery(
    vector=query_vector,
    k_nearest_neighbors=10,
    fields="content_vector"
)

results = client.search(
    vector_queries=[vector_query],
    select=["id", "title", "content"]
)

for result in results:
    print(f"{result['title']}: {result['@search.score']}")

Recherche hybride (vectorielle + mot-clé)

from azure.search.documents.models import VectorizedQuery

vector_query = VectorizedQuery(
    vector=query_vector,
    k_nearest_neighbors=10,
    fields="content_vector"
)

results = client.search(
    search_text="azure search",
    vector_queries=[vector_query],
    select=["id", "title", "content"],
    top=10
)

Classement sémantique

from azure.search.documents.models import QueryType

results = client.search(
    search_text="what is azure search",
    query_type=QueryType.SEMANTIC,
    semantic_configuration_name="my-semantic-config",
    select=["id", "title", "content"],
    top=10
)

for result in results:
    print(f"{result['title']}")
    if result.get("@search.captions"):
        print(f"  Caption: {result['@search.captions'][0].text}")

Filtres

results = client.search(
    search_text="*",
    filter="category eq 'Technology' and rating gt 4",
    order_by=["rating desc"],
    select=["id", "title", "category", "rating"]
)

Facettes

results = client.search(
    search_text="*",
    facets=["category,count:10", "rating"],
    top=0  # Only get facets, no documents
)

for facet_name, facet_values in results.get_facets().items():
    print(f"{facet_name}:")
    for facet in facet_values:
        print(f"  {facet['value']}: {facet['count']}")

Saisie semi-automatique et suggestions

# Saisie semi-automatique
results = client.autocomplete(
    search_text="sea",
    suggester_name="my-suggester",
    mode="twoTerms"
)

# Suggestions
results = client.suggest(
    search_text="sea",
    suggester_name="my-suggester",
    select=["title"]
)

Indexeur avec skillset

from azure.search.documents.indexes import SearchIndexerClient
from azure.search.documents.indexes.models import (
    SearchIndexer,
    SearchIndexerDataSourceConnection,
    SearchIndexerSkillset,
    EntityRecognitionSkill,
    InputFieldMappingEntry,
    OutputFieldMappingEntry
)

indexer_client = SearchIndexerClient(endpoint, AzureKeyCredential(key))

# Créer la source de données
data_source = SearchIndexerDataSourceConnection(
    name="my-datasource",
    type="azureblob",
    connection_string=connection_string,
    container={"name": "documents"}
)
indexer_client.create_or_update_data_source_connection(data_source)

# Créer le skillset
skillset = SearchIndexerSkillset(
    name="my-skillset",
    skills=[
        EntityRecognitionSkill(
            inputs=[InputFieldMappingEntry(name="text", source="/document/content")],
            outputs=[OutputFieldMappingEntry(name="organizations", target_name="organizations")]
        )
    ]
)
indexer_client.create_or_update_skillset(skillset)

# Créer l'indexeur
indexer = SearchIndexer(
    name="my-indexer",
    data_source_name="my-datasource",
    target_index_name="my-index",
    skillset_name="my-skillset"
)
indexer_client.create_or_update_indexer(indexer)

Bonnes pratiques

  1. Utiliser la recherche hybride pour la meilleure pertinence en combinant vectorielle et mot-clé
  2. Activer le classement sémantique pour les requêtes en langage naturel
  3. Indexer par lots de 100 à 1 000 documents pour l'efficacité
  4. Utiliser des filtres pour affiner les résultats avant le classement
  5. Configurer les dimensions vectorielles pour correspondre à votre modèle d'embedding
  6. Utiliser l'algorithme HNSW pour la recherche vectorielle à grande échelle
  7. Créer les suggesteurs au moment de la création de l'index (impossible à ajouter après)

Fichiers de référence

Fichier Contenu
references/vector-search.md Configuration HNSW, vectorisation intégrée, requêtes multi-vecteurs
references/semantic-ranking.md Configuration sémantique, légendes, réponses, modèles hybrides
scripts/setup_vector_index.py Script CLI pour créer un index de recherche avec vecteurs

Modèles supplémentaires Azure AI Search

SDK Python Azure AI Search

Écrivez du code Python clean et idiomatique pour Azure AI Search en utilisant azure-search-documents.

Installation

pip install azure-search-documents azure-identity

Variables d'environnement

AZURE_SEARCH_ENDPOINT=https://<search-service>.search.windows.net  # Requis pour toutes les méthodes d'authentification
AZURE_SEARCH_INDEX_NAME=<index-name>  # Requis pour toutes les méthodes d'authentification
# Pour l'authentification par clé API (non recommandée pour la production)
AZURE_SEARCH_API_KEY=<api-key>  # Requis uniquement pour l'authentification AzureKeyCredential
AZURE_TOKEN_CREDENTIALS=prod # Requis uniquement si DefaultAzureCredential est utilisé en production

Authentification

DefaultAzureCredential (préféré) :

from azure.identity import DefaultAzureCredential, ManagedIdentityCredential
from azure.search.documents import SearchClient

# Dev local : DefaultAzureCredential. Production : définir AZURE_TOKEN_CREDENTIALS=prod ou AZURE_TOKEN_CREDENTIALS=<specific_credential>
credential = DefaultAzureCredential(require_envvar=True)
# Ou utiliser une authentification spécifique directement en production :
# Voir https://learn.microsoft.com/python/api/overview/azure/identity-readme?view=azure-python#credential-classes
# credential = ManagedIdentityCredential()
client = SearchClient(endpoint, index_name, credential)

Clé API :

from azure.core.credentials import AzureKeyCredential
from azure.search.documents import SearchClient

client = SearchClient(endpoint, index_name, AzureKeyCredential(api_key))

Sélection du client

Client Objectif
SearchClient Interroger les index, charger/mettre à jour/supprimer des documents
SearchIndexClient Créer/gérer les index, sources de connaissances, bases de connaissances
SearchIndexerClient Gérer les indexeurs, skillsets, sources de données
KnowledgeBaseRetrievalClient Récupération agentique avec Q&A basée sur LLM

Modèle de création d'index

from azure.search.documents.indexes import SearchIndexClient
from azure.search.documents.indexes.models import (
    SearchIndex, SearchField, VectorSearch, VectorSearchProfile,
    HnswAlgorithmConfiguration, AzureOpenAIVectorizer,
    AzureOpenAIVectorizerParameters, SemanticSearch,
    SemanticConfiguration, SemanticPrioritizedFields, SemanticField
)

index = SearchIndex(
    name=index_name,
    fields=[
        SearchField(name="id", type="Edm.String", key=True),
        SearchField(name="content", type="Edm.String", searchable=True),
        SearchField(name="embedding", type="Collection(Edm.Single)",
                   vector_search_dimensions=3072,
                   vector_search_profile_name="vector-profile"),
    ],
    vector_search=VectorSearch(
        profiles=[VectorSearchProfile(
            name="vector-profile",
            algorithm_configuration_name="hnsw-algo",
            vectorizer_name="openai-vectorizer"
        )],
        algorithms=[HnswAlgorithmConfiguration(name="hnsw-algo")],
        vectorizers=[AzureOpenAIVectorizer(
            vectorizer_name="openai-vectorizer",
            parameters=AzureOpenAIVectorizerParameters(
                resource_url=aoai_endpoint,
                deployment_name=embedding_deployment,
                model_name=embedding_model
            )
        )]
    ),
    semantic_search=SemanticSearch(
        default_configuration_name="semantic-config",
        configurations=[SemanticConfiguration(
            name="semantic-config",
            prioritized_fields=SemanticPrioritizedFields(
                content_fields=[SemanticField(field_name="content")]
            )
        )]
    )
)

index_client = SearchIndexClient(endpoint, credential)
index_client.create_or_update_index(index)

Opérations sur les documents

from azure.search.documents import SearchIndexingBufferedSender

# Chargement par lots avec batching automatique
with SearchIndexingBufferedSender(endpoint, index_name, credential) as sender:
    sender.upload_documents(documents)

# Opérations directes via SearchClient
search_client = SearchClient(endpoint, index_name, credential)
search_client.upload_documents(documents)      # Ajouter nouveaux
search_client.merge_documents(documents)       # Mettre à jour existants
search_client.merge_or_upload_documents(documents)  # Upsert
search_client.delete_documents(documents)      # Supprimer

Modèles de recherche

# Recherche basique
results = search_client.search(search_text="query")

# Recherche vectorielle
from azure.search.documents.models import VectorizedQuery

results = search_client.search(
    search_text=None,
    vector_queries=[VectorizedQuery(
        vector=embedding,
        k_nearest_neighbors=5,
        fields="embedding"
    )]
)

# Recherche hybride (vectorielle + mot-clé)
results = search_client.search(
    search_text="query",
    vector_queries=[VectorizedQuery(vector=embedding, k_nearest_neighbors=5, fields="embedding")],
    query_type="semantic",
    semantic_configuration_name="semantic-config"
)

# Avec filtres
results = search_client.search(
    search_text="query",
    filter="category eq 'technology'",
    select=["id", "title", "content"],
    top=10
)

Récupération agentique (bases de connaissances)

Pour Q&A basée sur LLM avec synthèse de réponses, voir references/agentic-retrieval.md.

Concepts clés :

  • Source de connaissances : Pointe vers un index de recherche
  • Base de connaissances : Enveloppe les sources de connaissances + LLM pour la planification et la synthèse de requêtes
  • Modes de sortie : EXTRACTIVE_DATA (extraits bruts) ou ANSWER_SYNTHESIS (réponses générées par LLM)

Modèle asynchrone

from azure.search.documents.aio import SearchClient

async with SearchClient(endpoint, index_name, credential) as client:
    results = await client.search(search_text="query")
    async for result in results:
        print(result["title"])

Bonnes pratiques

  1. Utiliser les variables d'environnement pour les endpoints, clés et noms de déploiement
  2. Préférer DefaultAzureCredential aux clés API pour la production
  3. Utiliser SearchIndexingBufferedSender pour les chargements par lots (gère le batching et les retentatives)
  4. Toujours définir la configuration sémantique pour les index de récupération agentique
  5. Utiliser create_or_update_index pour la création d'index idempotente
  6. Fermer les clients avec des gestionnaires de contexte ou un appel explicite à close()

Référence des types de champ

Type EDM Python Remarques
Edm.String str Texte consultable
Edm.Int32 int Entier
Edm.Int64 int Long entier
Edm.Double float Nombre flottant
Edm.Boolean bool Vrai/Faux
Edm.DateTimeOffset datetime ISO 8601
Collection(Edm.Single) List[float] Embeddings vectoriels
Collection(Edm.String) List[str] Tableaux de chaînes

Gestion des erreurs

from azure.core.exceptions import (
    HttpResponseError,
    ResourceNotFoundError,
    ResourceExistsError
)

try:
    result = search_client.get_document(key="123")
except ResourceNotFoundError:
    print("Document not found")
except HttpResponseError as e:
    print(f"Search error: {e.message}")

Skills similaires