Decisions API
La Decisions API permet à un modèle de prendre des décisions typées sur un contenu au lieu de générer du texte. Vous fournissez le contenu à évaluer et un ensemble de questions, et le modèle renvoie une réponse structurée pour chacune : la probabilité d’un oui ou d’un non, un choix unique parmi une liste d’options, ou une note sur une échelle graduée, accompagnés des probabilités de chaque option et d’une valeur de confiance.
L’API est conçue pour la classification, le routage, la modération, la notation, le filtrage et tout autre cas où votre code doit bifurquer directement selon le résultat. Le modèle ne peut répondre qu’avec les options et les niveaux que vous définissez, jamais en dehors ; il n’y a donc aucun texte libre à analyser.
Lors de la première utilisation d’un modèle de décision, il est recommandé de consulter d’abord le guide d’utilisation de Jev, qui couvre le démarrage rapide, la conception des questions, l’interprétation des résultats et des exemples de scénarios. Cette page constitue la référence au niveau des champs.
Endpoints
Les trois endpoints servent les mêmes modèles avec la même tarification ; seuls les formats de requête et de réponse diffèrent. Choisissez celui qui correspond à votre client :
L’authentification fonctionne comme pour les autres endpoints : Authorization: Bearer <votre OFOXAI_API_KEY>. Seules les requêtes sans streaming sont prises en charge ; chaque requête renvoie toutes les réponses de façon synchrone.
Modèles disponibles
La liste complète des modèles compatibles avec cette API figure sur la page des modèles . Un appel avec un modèle de chat ordinaire (par exemple openai/gpt-4o) renvoie endpoint_not_supported.
Format unifié : /v1/decisions
Paramètres de la requête
Format d’entrée
input accepte trois formes :
- Texte : une chaîne unique.
"input": "Customer message: I was charged twice, nobody has answered my two emails, and I need a refund today." - Données structurées : un objet JSON, transmis tel quel au modèle. Les questions peuvent faire référence aux noms de champs entre backticks, par exemple
`message`."input": { "ticket_id": 4812, "message": "I was charged twice.", "plan": "pro" } - Tableau de messages :
[{ "role", "content" }], oùcontentest une chaîne ou une liste de blocs de contenu. Seuls les blocsinput_textetinput_imagesont pris en charge. Les images ne fonctionnent qu’avec les modèles capables de les lire. Jev ne lit pas les images ; en envoyer une renvoie 400.
Objet question
Exemples de requête
cURL
curl https://api.ofox.ai/v1/decisions \
-H "Authorization: Bearer $OFOX_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "typesafe/jev-latest",
"input": "Customer message: I was charged twice, nobody has answered my two emails, and I need a refund today.",
"questions": [
{ "type": "predicate", "name": "is_frustrated", "instructions": "Is the customer frustrated?" },
{
"type": "choice",
"name": "category",
"instructions": "Which category does this ticket belong to?",
"choices": [
{ "value": "billing", "description": "Charges and refunds" },
{ "value": "bug", "description": "Product issue" },
{ "value": "other", "description": "Other" }
]
},
{
"type": "score",
"name": "urgency",
"instructions": "How quickly does a human need to respond?",
"levels": [
{ "label": "low", "description": "Within a week is fine" },
{ "label": "medium", "description": "Should respond soon" },
{ "label": "high", "description": "Must respond today" }
]
}
]
}'Format de la réponse
{
"model": "typesafe/jev-latest",
"answers": [
{ "type": "predicate", "name": "is_frustrated", "probability": 0.97 },
{
"type": "choice",
"name": "category",
"choice": "billing",
"confidence": 1,
"probabilities": [
{ "value": "billing", "probability": 1 },
{ "value": "bug", "probability": 0 },
{ "value": "other", "probability": 0 }
]
},
{
"type": "score",
"name": "urgency",
"score": 2,
"confidence": 1,
"legend": { "0": "low: Within a week is fine", "1": "medium: Should respond soon", "2": "high: Must respond today" },
"probabilities": [
{ "value": 0, "label": "low", "probability": 0 },
{ "value": 1, "label": "medium", "probability": 0 },
{ "value": 2, "label": "high", "probability": 1 }
]
}
],
"usage": { "prompt_tokens": 407, "completion_tokens": 72, "total_tokens": 479 }
}answers correspond un à un à questions, dans le même ordre. Champs de chaque type de réponse :
Format natif TypeSafe : /typesafe/v1/systemone
Les formats de requête et de réponse sont identiques à ceux de l’API officielle TypeSafe : vous pouvez utiliser directement le SDK TypeSafe ou migrer du code existant. Par rapport au format unifié, les différences sont les suivantes :
curl https://api.ofox.ai/typesafe/v1/systemone \
-H "Authorization: Bearer $OFOX_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "jev-latest",
"state": "Help! My payouts have been failing for 3 days.",
"questions": {
"is_urgent": { "type": "noul", "instructions": "Does this convey urgency?" },
"department": {
"type": "choice",
"instructions": "Which team should handle this?",
"criteria": {
"billing": "Payments, invoicing, refunds",
"technical": "Bugs, outages, integrations",
"sales": "Pricing, upgrades"
}
},
"frustration": {
"type": "score",
"instructions": "How frustrated is the customer?",
"criteria": ["Calm", "Frustrated", "Very angry"]
}
}
}'{
"model": "typesafe/jev-latest",
"answers": {
"is_urgent": { "type": "noul", "noul": 0.95 },
"department": {
"type": "choice",
"choice": "billing",
"confidence": 0.85,
"probabilities": { "billing": 0.9, "technical": 0.1, "sales": 0 }
},
"frustration": {
"type": "score",
"score": 1.03,
"confidence": 0.95,
"legend": { "0": "Calm", "1": "Frustrated", "2": "Very angry" },
"probabilities": { "0": 0, "1": 0.97, "2": 0.03 }
}
},
"usage": { "input_tokens": 399, "output_tokens": 73 }
}Intégration SDK
SDK OpenAI
Le SDK officiel d’OpenAI fournit client.decisions.create(). Faites pointer base_url vers https://api.ofox.ai/v1 et utilisez le format unifié pour le corps de la requête. Un exemple figure dans l’onglet Python ci-dessus. Il faut une version du SDK incluant la Decisions API (testé avec openai Python 3.31.0).
SDK TypeSafe
Avec le SDK officiel TypeSafe, définissez base_url sur https://api.ofox.ai/typesafe et remplacez api_key par votre clé API OfoxAI. Le reste du code reste inchangé :
Python
# pip install typesafe-sdk
import os
from typesafe_sdk import TypeSafeClient, Noul, Choice, Score
with TypeSafeClient(base_url="https://api.ofox.ai/typesafe", api_key=os.environ["OFOX_API_KEY"]) as client:
r = client.system_one(
model="jev-latest",
state={"message": "I was charged twice, nobody has answered my two emails, and I need a refund today."},
questions={
"urgent": Noul(instructions="Is the customer asking for this to be handled today?"),
"dept": Choice(
instructions="Which team should handle this?",
criteria={"billing": "Charges, invoices, refunds", "technical": "Bugs, integrations", "sales": "Pricing, upgrades"},
),
"anger": Score(instructions="How upset is the customer?", criteria=["Calm", "Upset but polite", "Very angry"]),
},
)
print(r.nouls["urgent"].noul) # 0.98
print(r.choices["dept"].choice) # billing
print(r.scores["anger"].score) # 1.56Probabilité et confiance
- La probabilité répond à la question « quelle est la réponse » :
probabilityetprobabilitiessont les probabilités calibrées du modèle pour chaque réponse possible. - La confiance répond à la question « peut-on se fier à cette décision » :
confidenceest dérivée de la distribution de probabilités et augmente à mesure que la distribution est concentrée. Si deux options sont chacune à 0.5,choiceen renvoie tout de même une, maisconfidencesera faible.
Une pratique courante consiste à définir un seuil dans le code : agir automatiquement lorsque la confiance est élevée, et transmettre à un humain ou à un modèle plus puissant pour vérification lorsqu’elle est faible.
Facturation
La facturation se fait au token ; les tarifs figurent sur la page du modèle . typesafe/jev-latest ne facture que les tokens d’entrée ; la sortie n’est pas facturée (completion_tokens / output_tokens sont tout de même renvoyés).
Toutes les questions d’une requête partagent la même entrée : regrouper plusieurs questions dans une seule requête est donc nettement moins coûteux et plus rapide que de les répartir sur des appels distincts.
Limites
Erreurs courantes
Pour les autres erreurs générales, consultez Gestion des erreurs.