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
- Utiliser la recherche hybride pour la meilleure pertinence en combinant vectorielle et mot-clé
- Activer le classement sémantique pour les requêtes en langage naturel
- Indexer par lots de 100 à 1 000 documents pour l'efficacité
- Utiliser des filtres pour affiner les résultats avant le classement
- Configurer les dimensions vectorielles pour correspondre à votre modèle d'embedding
- Utiliser l'algorithme HNSW pour la recherche vectorielle à grande échelle
- 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) ouANSWER_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
- Utiliser les variables d'environnement pour les endpoints, clés et noms de déploiement
- Préférer
DefaultAzureCredentialaux clés API pour la production - Utiliser
SearchIndexingBufferedSenderpour les chargements par lots (gère le batching et les retentatives) - Toujours définir la configuration sémantique pour les index de récupération agentique
- Utiliser
create_or_update_indexpour la création d'index idempotente - 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}")