Comment appeler Jev sur AiHubMix : un tutoriel de classification structurée

AIHubMix5 min de lecture
Comment appeler Jev sur AiHubMix : un tutoriel de classification structurée

Réponse courte : jev-1.13 ne génère pas de texte. Vous envoyez en POST un texte accompagné d'un ensemble de questions nommées à https://aihubmix.com/v1/systemone, et vous recevez en retour des réponses typées, indexées par les noms de vos questions : une catégorie, un score ou une probabilité. Rien à analyser. Vous trouverez ci-dessous une requête fonctionnelle, le format complet de la réponse et l'erreur de conception qui réduira discrètement votre précision.

À quoi sert Jev

Utilisez-le lorsque vous avez besoin d'un jugement, et non d'un paragraphe : orienter un ticket de support, évaluer la gravité, signaler l'urgence, filtrer du contenu. La page du modèle l'indique clairement : « Pas de génération de texte, rien à analyser ».

Utilisez plutôt un modèle de chat classique si vous avez besoin d'explications, de résumés ou de tout résultat en texte libre. Jev ne peut pas produire ces éléments.

Avant de commencer

  • [ ] Python 3 installé (la bibliothèque standard suffit)
  • [ ] Un compte AiHubMix et une clé API
  • [ ] Clé exportée sous AIHUBMIX_API_KEY, jamais codée en dur dans le source

Vous n'avez pas besoin du SDK OpenAI, de LangChain ni du paquet requests.

Étape 1 — Connaître le point de terminaison

POST https://aihubmix.com/v1/systemone
Authorization: Bearer YOUR_KEY
Content-Type: application/json

Il s'agit d'une route spécifique au modèle, et non /v1/chat/completions. Les clients compatibles OpenAI ne peuvent pas l'appeler. Utilisez du HTTP simple.

Étape 2 — Choisir vos types de questions

Il en existe trois, que vous pouvez combiner librement dans une même requête :

TypeUtilisationVous fournissez
choiceChoix d'une catégoriecriteria sous forme de dictionnaire : libellé → définition
scoreÉvaluation sur une échelle ordonnéecriteria sous forme de liste, du plus bas au plus haut
noulUn jugement oui/nonrien de plus que instructions

Étape 3 — Construire la requête

state est le texte à évaluer. questions contient des clés que vous choisissez ; la réponse utilise les mêmes noms.

payload = {
    "model": "jev-1.13",
    "state": "Hi, I have been trying to connect my Stripe account for 3 days "
             "and it keeps failing. I am losing sales. Please help ASAP.",
    "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",
            },
        },
        "frustration": {
            "type": "score",
            "instructions": "How frustrated the customer appears",
            "criteria": [
                "Calm, just stating facts",
                "Frustrated but civil",
                "Very angry, strong language",
            ],
        },
        "is_urgent": {
            "type": "noul",
            "instructions": "The message conveys urgency or time-sensitivity",
        },
    },
}

Étape 4 — Envoyer la requête avec la bibliothèque standard

import json, os, urllib.error, urllib.request

def ask(payload):
    req = urllib.request.Request(
        "https://aihubmix.com/v1/systemone",
        data=json.dumps(payload).encode(),
        headers={"Authorization": "Bearer " + os.environ["AIHUBMIX_API_KEY"],
                 "Content-Type": "application/json"},
        method="POST",
    )
    try:
        with urllib.request.urlopen(req, timeout=60) as r:
            return json.loads(r.read())
    except urllib.error.HTTPError as e:
        raise SystemExit(f"HTTP {e.code}: {e.read().decode(errors='replace')[:500]}")

Gardez la construction de la requête à l'intérieur d'une fonction. Si vous construisez et envoyez au niveau du module, l'importation du fichier relance l'appel et consomme des jetons.

Étape 5 — Lire les réponses

Chaque réponse stocke sa valeur sous une clé correspondant à son type, donc un seul accesseur couvre les trois :

data = ask(payload)
for name, ans in data["answers"].items():
    kind = ans["type"]
    print(name, kind, ans[kind], ans.get("confidence"))
print("usage:", data.get("usage"))

Sortie vérifiée :

department   choice  billing   0.51
frustration  score   1         1
is_urgent    noul    1         None
usage: {'input_tokens': 424, 'output_tokens': 73}

Étape 6 — Comprendre l'enveloppe complète

La boucle d'affichage masque des champs utiles. Le JSON brut d'une réponse de type score :

{
  "type": "score",
  "score": 1,
  "legend": {"0": "Calm, just stating facts", "1": "Frustrated but civil", "2": "Very angry, strong language"},
  "probabilities": {"0": 0, "1": 1, "2": 0},
  "confidence": 1
}
  • legend fait correspondre l'indice à votre propre formulation : l'entier est auto-descriptif, vous n'avez donc besoin d'aucune table de correspondance dans votre code.
  • probabilities donne la distribution complète, utile pour détecter une égalité quasi parfaite.
  • noul ne comporte pas de champ confidence. Sa probabilité constitue le signal.

Le niveau supérieur renvoie aussi usage, id, provider (TypeSafe) et la version du backend résolue typesafe/jev-1.13-20260917.

L'erreur qui coûte de la précision

Dans la requête ci-dessus, department a renvoyé billing avec une confiance de 0.51. En répétant exactement la même requête, le même libellé est revenu avec 0.38 — la réponse était stable, mais la certitude annoncée ne l'était pas.

La cause se trouve dans les critères, et non dans le modèle. billing correspond à « Problèmes de paiement ou d'abonnement » et technical à « Bugs ou problèmes d'intégration ». Une intégration Stripe qui continue d'échouer correspond réellement aux deux. Le modèle signalait une ambiguïté inscrite dans le schéma lui-même.

Deux règles avant la production :

  1. Rédigez des critères choice mutuellement exclusifs. Si un humain hésiterait entre deux libellés, le modèle hésitera aussi.
  2. Définissez un seuil de confiance et dirigez les résultats à faible confiance vers une file de traitement humaine plutôt que de les accepter comme décisions. Un modèle qui reconnaît son incertitude est plus précieux qu'un modèle qui la dissimule.

Liste de contrôle avant lancement

  • [ ] Clé chargée depuis l'environnement ou depuis un fichier aux droits 600 ignoré par votre VCS
  • [ ] Critères choice revus pour détecter les recoupements
  • [ ] Seuil de confiance défini, avec une solution de repli en dessous
  • [ ] Réponses noul traitées séparément — elles ne comportent pas de confidence
  • [ ] Questions inutilisées supprimées (3 questions coûtent 424 jetons d'entrée ; 2 en coûtent 355)
  • [ ] Réponses non 2xx journalisées avec le corps brut

FAQ

Puis-je utiliser le SDK OpenAI ? Non. /v1/systemone n'est pas une route compatible OpenAI.

Jev peut-il renvoyer une phrase ou un résumé ? Non. Il répond uniquement aux questions typées que vous définissez.

Combien de questions par requête ? Les tests vérifiés en ont utilisé deux et trois. Chaque question ajoute des jetons en entrée et en sortie ; n'incluez donc que celles sur lesquelles vous agirez.

Existe-t-il un alias de version ? La page du modèle liste un alias jev-latest à côté de jev-1.13. Fixez la version explicite si la reproductibilité compte.

Quel est le coût ? La page du modèle publie $0.0462 / M de jetons en entrée et $0 / M de jetons en sortie. Ce sont des chiffres du fournisseur : vérifiez les tarifs en vigueur avant de budgétiser.

Quelle est la taille de la fenêtre de contexte ? La page du modèle est incohérente : 64K dans son en-tête, 32K dans le tableau des fournisseurs. Vérifiez avec votre entrée la plus longue avant de vous fier à l'une ou l'autre valeur.

Portée de ce guide

Tout ce qui précède a été vérifié à l'aide de trois appels réels sur une seule entrée. Il ne couvre ni la latence, ni le traitement par lots, ni le débit, ni le comportement sur des entrées différentes de l'exemple. La dérive de confiance est une observation reproduite, non un taux d'erreur mesuré : reproduisez-la sur vos propres données avant de fixer un seuil.

Démarrer sur AiHubMix

jev-1.13 est disponible via AiHubMix, et la page du modèle contient tout ce à quoi ce tutoriel renvoie : le point de terminaison /v1/systemone, les trois types de questions avec leurs formats de criteria, l'ensemble des champs de réponse, et la tarification publiée de $0.0462 / M de jetons en entrée et $0 / M de jetons en sortie. L'alias jev-latest pointe vers la version la plus récente, il reste donc à jour au fil des évolutions.

Commencez ici : https://aihubmix.com/model/jev-latest

Prochaines étapes :

  1. Créez un compte AiHubMix et générez une clé API
  2. Copiez la requête de l'étape 3 et la fonction ask() de l'étape 4
  3. Remplacez state par un enregistrement réel de votre propre file
  4. Comparez le résultat avec la manière dont vous classez cet enregistrement aujourd'hui

Si ce guide vous a été utile, abonnez-vous pour recevoir les prochains articles sur les modèles à sortie structurée et les pipelines de classification.

Une seule passerelle vers plusieurs fournisseurs d’IA. Conçue pour la production.

Découvrir AIHubMix