Ajouter des documents à une collection
Sur cette page
Leçon corrigée le 2 novembre 2026 d’après le code du SDK
xai-sdk1.21.0 et la documentation de xAI : les appelsawaitexigent le client asynchroneAsyncClient, le statut d’indexation se compare à la constantecollections_pb2.DOCUMENT_STATUS_PROCESSED(et non à une chaîne, ce qui faisait tourner la boucle sans fin), et l’ingestion en masse passe parupload_document, qui enchaîne les deux étapes en un appel — l’ancien exemple téléversait chaque fichier deux fois, dont une par une méthode inexistante. Sources : Collections via l’API · xai-sdk-python.
Pourquoi l’ajout se fait en deux temps
On s’attend à pouvoir déposer un PDF directement dans une collection, comme on glisse un fichier dans un dossier. Ce n’est pas ainsi que fonctionne l’API xAI : le document passe d’abord par la Files API, qui le stocke et lui attribue un file_id, puis par la Management API, qui rattache cet identifiant à la collection. Deux appels, deux clés, deux étapes.
Cette dissociation a une conséquence directe et très utile : le fichier existe une seule fois côté stockage, mais peut être rattaché à autant de collections que nécessaire. Le même rapport technique alimente la base de l’équipe produit et celle du support sans être uploadé deux fois, sans consommer deux fois du quota, et sans risquer de diverger entre deux copies.
Étape 1 : déposer le fichier
Rien de nouveau ici, c’est l’endpoint que vous maîtrisez depuis la première leçon :
curl -X POST https://api.x.ai/v1/files \
-H "Authorization: Bearer $XAI_API_KEY" \
-F "[email protected]" \
-F "purpose=assistants"
Récupérez le file_id de la réponse : il est le pivot de l’étape suivante.
Étape 2 : rattacher à la collection
L’ajout prend la forme d’un POST sur une URL qui combine les deux identifiants, celui de la collection et celui du fichier, et n’exige aucun corps de requête :
curl -X POST https://management-api.x.ai/v1/collections/col_xyz789/documents/file_abc123 \
-H "Authorization: Bearer $XAI_MANAGEMENT_API_KEY"
Dès cet appel accepté, xAI démarre l’indexation du contenu. Le document traverse alors plusieurs états de traitement avant d’être réellement disponible pour la recherche.
Attendre que l’indexation soit terminée
C’est le piège classique du premier pipeline : la requête d’ajout renvoie un succès, on enchaîne aussitôt sur une recherche, et la collection répond qu’elle ne trouve rien. Le document existe, mais il n’est pas encore indexé. Le statut à attendre est DOCUMENT_STATUS_PROCESSED, et le SDK permet de boucler proprement dessus :
import asyncio
import os
from xai_sdk import AsyncClient
from xai_sdk.proto import collections_pb2
client = AsyncClient(
api_key=os.getenv("XAI_API_KEY"),
management_api_key=os.getenv("XAI_MANAGEMENT_API_KEY"),
)
async def attendre_indexation(file_id, collection_id):
doc = await client.collections.get_document(file_id, collection_id)
while doc.status != collections_pb2.DOCUMENT_STATUS_PROCESSED:
if doc.status == collections_pb2.DOCUMENT_STATUS_FAILED:
raise RuntimeError(f"Indexation échouée : {doc.error_message}")
await asyncio.sleep(3)
doc = await client.collections.get_document(file_id, collection_id)
print("Document indexé et prêt pour la recherche")
asyncio.run(attendre_indexation("file_abc123", "col_xyz789"))
Le délai dépend directement du volume : un PDF de quelques pages est indexé en quelques secondes, tandis qu’un document de 100 MB peut demander plusieurs minutes. Dans une ingestion nocturne, cette boucle avec une pause de trois secondes suffit ; dans une interface où l’utilisateur dépose un fichier et attend, prévoyez un retour visuel plutôt qu’un écran figé.
Retirer un document sans le perdre
Détacher un fichier d’une collection est une opération distincte de sa suppression :
curl -X DELETE \
https://management-api.x.ai/v1/collections/col_xyz789/documents/file_abc123 \
-H "Authorization: Bearer $XAI_MANAGEMENT_API_KEY"
Le fichier disparaît de l’index de cette collection mais reste disponible via la Files API, et peut être rattaché ailleurs. C’est exactement ce qu’il faut faire lorsqu’une fiche produit devient obsolète pour le support tout en gardant sa valeur d’archive : vous la sortez de la base opérationnelle sans détruire le document.
Alimenter une collection en masse
Quand il s’agit d’initialiser une base à partir d’un dossier entier, la boucle s’écrit une fois et resservira longtemps :
import asyncio
import os
from pathlib import Path
from xai_sdk import AsyncClient
client = AsyncClient(
api_key=os.getenv("XAI_API_KEY"),
management_api_key=os.getenv("XAI_MANAGEMENT_API_KEY"),
)
fichiers = [
"docs/guide-installation.pdf",
"docs/reference-api.pdf",
"docs/faq.md",
"docs/changelog.txt",
]
async def alimenter(collection_id):
for chemin in map(Path, fichiers):
# Étapes 1 et 2 en un seul appel : upload par la Files API, puis rattachement
await client.collections.upload_document(
collection_id=collection_id,
name=chemin.name,
data=chemin.read_bytes(),
)
print(f"Ajouté : {chemin}")
asyncio.run(alimenter("col_xyz789"))
Remarquez le mélange de formats dans la liste — PDF, Markdown, texte brut cohabitent sans difficulté dans une même collection, ce qui vous évite d’uniformiser vos sources avant l’ingestion.
Deux clés, deux périmètres
Ce processus mobilise deux identifiants d’accès qu’il ne faut pas confondre : la clé API standard (XAI_API_KEY) pour l’upload de l’étape 1, la clé Management (XAI_MANAGEMENT_API_KEY) pour le rattachement de l’étape 2. Le SDK les reçoit toutes deux à la création du client, et upload_document s’en sert l’une après l’autre. Vérifiez que cette dernière porte bien la permission AddFileToCollection : sans elle, votre upload réussira, votre ajout échouera avec une erreur 403, et vous accumulerez des fichiers correctement stockés mais absents de toute collection.
Points clés à retenir
- L’ajout à une collection se fait en deux étapes : upload puis ajout
- Un fichier peut appartenir à plusieurs collections simultanément
- Le document doit atteindre le statut
DOCUMENT_STATUS_PROCESSEDavant d’être recherchable - La suppression d’un document d’une collection ne supprime pas le fichier sous-jacent
- Deux clés API distinctes sont nécessaires : standard pour l’upload, Management pour la collection