Primitives (Questions)
Les trois types de question TypeSafe (Choice, Score, Noul), les réponses typées qu’ils renvoient, comment choisir entre eux et comment en poser plusieurs d’un coup.
Les primitives de TypeSafe sont les petits blocs typés que tu composes dans le code. Ils vont par paires : une question définit un jugement qu’un modèle System One doit porter sur un état, et sa réponse est la valeur typée qui revient. Tu composes les réponses dans ton code pour prendre des décisions. Il existe trois types de question, chacun renvoyant une forme de réponse différente.
| Type | À quoi il répond | Renvoie |
|---|---|---|
| Choice | Laquelle de ces options ? | choice, probabilities, confidence |
| Score | Quel niveau ? | score, legend, probabilities, confidence |
| Noul | Est-ce vrai ? | noul (de 0 à 1) |
Tu peux poser une seule question ou en envoyer plusieurs ensemble. Chaque question d’une requête voit le même état, est évaluée indépendamment et renvoie une réponse typée sous l’ID que tu as choisi.
Demande un jugement immédiat par question
Les modèles System One sont conçus pour des jugements rapides et ciblés. Demande un jugement qu’une personne compétente porte en une seconde avec le bon contexte. « Ce message transmet-il une urgence ? » est une bonne question. « Analyse ce message et détermine la meilleure marche à suivre » n’en est pas une. Cela demande un raisonnement lent, et c’est le signe qu’il faut découper la tâche en petites questions et composer les réponses dans le code.
Si le jugement que tu veux dépend de plusieurs facteurs indépendants, interroge chaque facteur séparément et combine les réponses avec ta propre logique. Au lieu de « note ce pitch de startup », demande la taille du marché, la faisabilité technique et la différenciation, puis pondère-les dans le code selon leur importance relative. Quand les priorités changent, modifie la valeur des pondérations plutôt que de réécrire un prompt. Poser plusieurs questions ensemble montre comment faire.
Définis une question
Chaque question a un ID, un type et des instructions. Les questions Choice et Score prennent aussi des criteria, qui définissent les options d’une question Choice ou les niveaux d’un Score. Les questions Noul acceptent des criteria comme clarification facultative de ce que signifient oui et non.
- ID. La clé que tu choisis, comme
refund_requested. Elle identifie la réponse renvoyée. type. L’un dechoice,scoreounoul.instructions. La question que tu poses sur l’état. C’est là que va ta logique d’évaluation. Écris-la comme une question claire et précise, ou comme une affirmation que le modèle doit juger. Une chaîne suffit pour la plupart des questions. Elle peut aussi être un objet ou un tableau, ce qui place la question dans un champ et les données auxquelles elle se réfère dans d’autres ; voir Utiliser une structure dans les questions.criteria. Les réponses possibles : une association d’options pour une question Choice, une liste ordonnée de niveaux pour un Score, et une description facultative de oui et non pour un Noul. La page de chaque type de question détaille sa forme.
Cette question demande si un client a réclamé un remboursement :
from typesafe_sdk import Noul
questions = {
"refund_requested": Noul(
instructions="Does the customer request a refund?",
),
}
Choisis un type de question
Choisis le type qui correspond à la forme de la réponse dont tu as besoin.
-
Choice convient quand la réponse est l’une d’un ensemble connu d’options sans ordre entre elles : router un ticket vers un service, classer un type de document, détecter un langage de programmation. Donne la liste complète des options, et ajoute une option
otherounone of the abovequand la liste risque de ne pas couvrir toutes les entrées. -
Score convient quand la réponse se situe sur un spectre et que tu peux décrire ce que signifie chaque point de ce spectre : gravité d’un bug, frustration d’un client, niveau de compétence. Les niveaux sont à toi de les définir, et le modèle renvoie une position le long de ceux-ci.
-
Noul convient à une question oui/non nette où la probabilité elle-même est le signal utile : ce message contient-il des informations personnelles identifiables, le client demande-t-il un remboursement, le CV mentionne-t-il des systèmes distribués.
Si deux types semblent convenir, privilégie celui dont la réponse permet à ton code d’agir directement. Un Choice entre refund, rebook et information correspond directement à trois chemins de code. Un Score de frustration du client correspond à un seuil. Un Noul correspond à un if.
Ce qui revient
Les réponses sont aussi des primitives. Chaque type de question renvoie une valeur typée que ton code peut comparer, soumettre à un seuil, trier, passer à de la logique supplémentaire ou placer dans l’état d’une requête suivante (voir Dépendance entre questions).
| Type | Champs de la réponse | Comment la lire |
|---|---|---|
| Choice | choice, probabilities, confidence |
choice est l’option sélectionnée. probabilities est la distribution sur toutes les options. confidence résume à quel point cette distribution est pointue. |
| Score | score, legend, probabilities, confidence |
score est une position le long de tes niveaux, et peut tomber entre deux d’entre eux. legend reprend les niveaux par numéro. probabilities est la distribution sur les niveaux. |
| Noul | noul |
La probabilité que la réponse soit oui. Proche de 1, c’est un oui franc ; proche de 0, un non franc ; proche de 0.5, une incertitude. Noul n’a pas de confidence distincte. |
Deux propriétés de ces réponses les rendent composables :
- Chaque réponse est contrainte aux options que tu as fournies. Le modèle renvoie une distribution de probabilité sur tes options ou niveaux, jamais une valeur en dehors. Ton code n’a jamais à extraire une valeur d’un texte généré.
- Chaque réponse est indépendante. La réponse d’une question n’est pas un contexte caché pour une autre. Tu peux ajouter ou retirer des questions sans changer les résultats des autres.
Confiance explique comment confidence est dérivée des probabilities et comment l’utiliser pour décider quand agir automatiquement et quand escalader vers une personne.
Cibler des champs précis
Le contenu évalué, l’état, est souvent un objet JSON composé de plusieurs parties : une conversation, un enregistrement, une politique. Quand une question porte sur l’une de ces parties, nomme-la dans les instructions avec un chemin à points et indices vers sa clé, accents graves compris. Le modèle sait alors quelle partie de l’état juger.
Reprends la conversation de support de la page État :
{
"ticket": {
"subject": "Duplicate charge",
"messages": [
{"from": "customer", "text": "I was charged twice for order A-104. Please refund the duplicate."},
{"from": "support", "text": "We are checking the charges."}
]
},
"order": {
"id": "A-104",
"charges": [
{"amount_usd": 49, "status": "captured"},
{"amount_usd": 49, "status": "captured"}
]
},
"refund_policy": "Duplicate charges are eligible for a refund."
}
Ces deux questions ciblent, par chemin, le message du client, la politique et les frais :
questions = {
"refund_requested": {
"type": "noul",
"instructions": "Does `ticket.messages[0].text` request a refund?",
},
"policy_supports_refund": {
"type": "noul",
"instructions": (
"Does `refund_policy` support the refund requested "
"in `ticket.messages[0].text`, given `order.charges`?"
),
},
}
Des chemins explicites indiquent clairement quelles parties d’un état structuré doivent éclairer chaque jugement. Voir État pour savoir comment structurer l’entrée.
Poser plusieurs questions ensemble
Envoie en une seule requête toutes les questions qui utilisent le même état. Tu peux mélanger librement les types de question. Les modèles System One évaluent en parallèle chaque question d’une requête. Ajouter des questions ne change presque pas le temps de réponse et ne coûte que les jetons des questions supplémentaires, qui sont bon marché. Poser une question dont tu n’auras peut-être pas besoin est presque gratuit.
Cette requête classe un message client, vérifie l’urgence et note la frustration, le tout d’un coup :
{
"state": "Our API integration started returning 500 errors on every request about 20 minutes ago, and we can't process any customer orders until this is fixed.",
"questions": {
"department": {
"type": "choice",
"instructions": "Which team should handle this",
"criteria": {
"billing": "Payment or subscription issues",
"technical": "Bugs or integration problems",
"sales": "Pricing or account questions"
}
},
"is_urgent": {
"type": "noul",
"instructions": "The message conveys urgency or time-sensitivity"
},
"frustration": {
"type": "score",
"instructions": "How frustrated the customer appears",
"criteria": [
"Calm, just stating facts",
"Frustrated but civil",
"Very angry, strong language"
]
}
}
}Nos SDK clients fournissent des questions et des réponses typées. En Python, passe un dictionnaire questions d’objets Choice, Noul et Score à client.system_one(...). Cette requête envoie un ticket et une politique de remboursement une seule fois et obtient une réponse typée pour chaque question :
from typesafe_sdk import Choice, Noul, Score, TypeSafeClient
state = {
"ticket_message": "My flight was cancelled. Can I get a refund?",
"refund_policy": "Cancelled flights are eligible for a full refund.",
}
with TypeSafeClient() as client:
response = client.system_one(
state=state,
questions={
"refund_requested": Noul(
instructions="Does `ticket_message` request a refund?",
),
"request_type": Choice(
instructions="What is the main request in `ticket_message`?",
criteria={
"refund": "The customer wants money returned.",
"rebooking": "The customer wants a replacement flight.",
"information": "The customer is asking for information only.",
},
),
"frustration": Score(
instructions="How frustrated does the customer appear in `ticket_message`?",
criteria=[
"Calm and neutral.",
"Concerned but civil.",
"Very angry or using strong language.",
],
),
},
)
print(response.answers["refund_requested"].noul)
print(response.answers["request_type"].choice)
print(response.answers["frustration"].score)
Voir les SDK clients pour l’installation et l’usage dans ton langage.
Pose des questions spéculatives
Pose toutes les questions dont ton code pourrait avoir besoin, y compris celles dont la réponse n’importe que pour certaines entrées, et laisse le code décider quelles réponses utiliser. Si un ticket s’avère ne pas être un rapport de bug, ignore la réponse de gravité. Nous appelons cela le motif Fan-out spéculatif. Le cookbook sur les questions en parallèle montre que regrouper 13 questions dans un seul appel coûte 11,5x moins cher et va 9,6x plus vite que 13 appels séparés, sans changement dans les réponses.
Divise un jugement complexe en plusieurs questions
Un jugement qui dépend de plusieurs choses gagne à être découpé en une question par chose. Combine les réponses dans ton code, en donnant à chacune une pondération selon son importance relative. Les pondérations sont les tiennes. Quand le résultat combiné ne correspond pas à ce que déciderait ton équipe, modifie-les dans le code et relance. Ajouter des questions ne change presque pas le temps de réponse, car elles s’exécutent en parallèle au sein d’une même requête. Le découpage coûte quelques jetons de question en plus.
Par exemple, la priorité d’un ticket peut se construire à partir de trois questions Score : la gravité du bug, la frustration du client et la quantité d’informations que le rapport donne à un ingénieur. La page Score déroule cette requête et le code qui normalise et pondère les réponses dans Diviser un jugement complexe en plusieurs Scores. Cette technique s’appelle le motif Notation composite.
Dépendance entre questions
Les questions d’une même requête sont indépendantes : une réponse ne devient pas un contexte pour une autre question. Si un jugement ultérieur dépend d’une réponse antérieure, fais une seconde requête dans le code. La dépendance est réelle seulement quand ton code ne peut pas construire la seconde requête avant d’avoir la première réponse : il a besoin de la réponse pour récupérer plus de données pour l’état, pour décider de quoi l’état est fait, ou pour choisir les options de la question suivante. Sinon, pose les questions ensemble et combine leurs réponses dans le code.
Deux requêtes sont l’exception, pas la règle. Si les questions de la seconde requête auraient pu être posées contre l’état d’origine, pose-les dans la première requête et laisse le code ignorer celles dont il n’a pas besoin. Trois cookbooks font une seconde requête pour une vraie raison. Suggestion de skill classe 182 skills en une seule requête, puis récupère le texte complet des trois meilleurs et les juge de nouveau face à ces meilleures preuves. Récupération de structure demande si chaque saut de ligne a coupé une phrase, fusionne les lignes en blocs à partir de ces réponses, puis classe les blocs, qui n’existaient pas avant que la première requête ait répondu. Classification hiérarchique utilise chaque réponse de Choice pour décider quelles options la requête suivante propose.
Voir Comment construire avec TypeSafe pour savoir comment découper un flux de travail en jugements ciblés.
Étapes suivantes
Choice
Choisis une option dans une liste fixe.
Score
Note l’état selon des niveaux ordonnés.
Noul
Obtiens la probabilité qu’une affirmation soit vraie.
Pour voir comment ils se composent en architectures système, direction Motifs.