L'API Document QnA
Mis à jour le 29 juillet 2026
Interroger vos documents en langage naturel
Document QnA associe l’OCR à un LLM Mistral pour vous laisser poser des questions directement sur le contenu de vos documents. Là où il fallait parcourir cinquante pages pour retrouver une clause ou un chiffre, vous formulez la question et lisez la réponse. En interne, le service enchaîne deux étapes — l’OCR extrait le texte, la structure et le formatage du document, puis un modèle de chat Mistral analyse le contenu extrait pour répondre. Cette combinaison reste transparente pour vous : un seul appel API suffit.
Un endpoint différent de l’OCR
C’est le point qui déroute au premier essai. L’OCR pur passe par client.ocr.process ; le QnA, lui, emprunte l’endpoint Chat standard client.chat.complete, avec un message dont le contenu mélange un bloc de texte et un bloc de type document_url. Autrement dit, le document devient une pièce jointe de votre question, au même titre qu’une image dans un échange multimodal.
import os
from mistralai import Mistral
client = Mistral(api_key=os.environ["MISTRAL_API_KEY"])
# Question sur un document public
response = client.chat.complete(
model="mistral-small-latest",
messages=[
{
"role": "user",
"content": [
{
"type": "text",
"text": "Quel est le chiffre d'affaires total mentionné ?"
},
{
"type": "document_url",
"document_url": "https://exemple.com/rapport-annuel.pdf"
}
]
}
]
)
print(response.choices[0].message.content)
Trois façons de transmettre le document
L’URL publique est la voie la plus directe, adaptée aux documents déjà accessibles en ligne — une publication scientifique, un rapport institutionnel, un PDF hébergé sur votre site.
messages = [
{
"role": "user",
"content": [
{"type": "text", "text": "Résume les points principaux."},
{
"type": "document_url",
"document_url": "https://arxiv.org/pdf/1805.04770"
}
]
}
]
response = client.chat.complete(
model="mistral-small-latest",
messages=messages
)
Vos fichiers locaux, eux, passent en base64. C’est le mode par défaut dès que le document est confidentiel ou stocké derrière votre pare-feu : rien n’a besoin d’être publié sur le web pour être interrogé.
import base64
with open("contrat.pdf", "rb") as f:
doc_base64 = base64.b64encode(f.read()).decode("utf-8")
messages = [
{
"role": "user",
"content": [
{
"type": "text",
"text": "Quelles sont les clauses de résiliation ?"
},
{
"type": "document_base64",
"document_base64": doc_base64
}
]
}
]
response = client.chat.complete(
model="mistral-small-latest",
messages=messages
)
Troisième voie enfin, celle des fichiers déjà transmis via l’API Files : vous uploadez une fois avec purpose="ocr", puis vous référencez l’identifiant obtenu autant de fois que nécessaire. Sur un document que vous comptez interroger à plusieurs reprises, cela évite de retransmettre plusieurs mégaoctets à chaque question.
uploaded = client.files.upload(
file=open("rapport.pdf", "rb"),
purpose="ocr"
)
messages = [
{
"role": "user",
"content": [
{"type": "text", "text": "Quel est le budget prévu ?"},
{"type": "file_id", "file_id": uploaded.id}
]
}
]
response = client.chat.complete(
model="mistral-small-latest",
messages=messages
)
Quel modèle de chat pour quelle question
Le paramètre model reste le vôtre, et il pèse à la fois sur la qualité des réponses et sur la facture.
| Modèle | Profil | Quand le choisir |
|---|---|---|
mistral-small-latest | Rapide et économique | Suffisant pour la plupart des questions |
mistral-medium-latest | Bon compromis | Vitesse et précision équilibrées |
mistral-large-latest | Plus précis | Analyses complexes et raisonnement |
Le choix dépend de la complexité de vos questions et de votre budget : une extraction de montant sur une facture ne réclame pas le même modèle qu’une comparaison de régimes de responsabilité entre deux contrats.
Enchaîner les questions
Rien ne vous oblige à tout demander d’un coup. Vous transmettez le document dans le premier message, ajoutez la réponse du modèle à l’historique, puis posez votre question de suivi en texte seul : le contexte du document reste dans la conversation. C’est la manière naturelle d’explorer un rapport — un résumé d’abord, puis un approfondissement sur le point qui vous intéresse.
historique = [
{
"role": "user",
"content": [
{"type": "text", "text": "Résume ce document en 3 points."},
{
"type": "document_url",
"document_url": "https://exemple.com/rapport.pdf"
}
]
}
]
# Premier appel
response = client.chat.complete(
model="mistral-small-latest",
messages=historique
)
# Ajout de la réponse à l'historique
historique.append({
"role": "assistant",
"content": response.choices[0].message.content
})
# Question de suivi
historique.append({
"role": "user",
"content": "Détaille le deuxième point."
})
response = client.chat.complete(
model="mistral-small-latest",
messages=historique
)
print(response.choices[0].message.content)
Ce que le QnA ne fera pas pour vous
Quatre limites méritent d’être connues avant de bâtir un service dessus. La taille d’abord : 50 Mo par fichier et 1 000 pages au maximum, ce qui exclut les archives volumineuses sans découpage préalable. Le coût ensuite, car les documents longs consomment beaucoup de tokens d’entrée à chaque question posée. L’absence de mémoire persistante impose de reconstituer l’historique vous-même, chaque appel étant indépendant en dehors d’une conversation multi-tours. Le point le plus délicat reste le dernier : le LLM interprète autant qu’il extrait, ce qui peut introduire des erreurs sur les chiffres précis. Pour un montant qui partira en comptabilité, préférez une annotation structurée ; réservez le QnA à la compréhension et à la synthèse.
Points clés à retenir
- Document QnA utilise l’endpoint Chat avec un contenu de type
document_urloudocument_base64 - Le workflow interne est OCR puis LLM, mais un seul appel suffit
- Trois méthodes d’envoi : URL, base64, fichier uploadé
- Les conversations multi-tours permettent des analyses approfondies
- Choisissez le modèle de chat selon la complexité de vos questions