clip-box — où se trouve-t-il dans cette image ?
C'est la porte d'entrée "où est X". L'implémentation réside dans
decision-model : le même client répond à bool, choice, score et box,
et clip-box est un point d'entrée léger qui maintient ce vocabulaire
routable et peut pointer vers une couche d'adaptation autonome lorsqu'un
autre modèle occupe l'emplacement de décision.
clip-box --image scene.png --target "le carré rouge" # couche d'adaptation sur :8083
clip-box --image scene.png --target "le carré rouge" --port 8761 # couche d'adaptation autonome
decision-model box --image scene.png --target "le carré rouge" # même chose
h2o-lightning est un modèle de décision de 4B : il répond à des questions
typées avec des probabilités et ne génère jamais de prose. Sa question box
renvoie un rectangle au lieu d'une étiquette, et trois nombres qui comptent
plus que le rectangle :
| champ | signification |
|---|---|
box | left, top, right, bottom en fractions de l'image, à partir du coin supérieur gauche |
confidence | P(IoU ≥ 0.5) — une lecture de décision sur l'image avec la boîte dessinée dessus, pas un nombre que le modèle raconte |
present | P(la cible est visible quoi qu'il arrive) — une lecture séparée sur l'image non modifiée |
found | si une boîte a été produite ; un échec renvoie l'image entière avec une confiance de 0 |
Verrouillez sur present, pas sur found. Si on demande un vélo bleu dans une scène
qui n'en a pas, le modèle renvoie une boîte d'apparence confiante autour d'autre chose avec
found: true et present: 0.111. present est ce qui dit non.
Utilisation
# démarrer l'API (les questions box sont activées ; le port avant du slot est :8083)
h2o-serve --port 8083 # CPU, Q8_0
h2o-serve --backend vulkan # GPU AMD : construit le backend Vulkan épinglé une fois
h2o-serve --status
h2o-serve --stop
# demander
clip-box --image scene.png --target "le carré rouge"
# ACCEPT box=(0.247, 0.247) -> (0.753, 0.753) confidence=0.651 present=0.885
clip-box --image scene.png --target "le vélo bleu" # absent -> quitte avec 2
clip-box --image receipt.png --target "le montant total" # confidence 0.163 < 0.30 -> rejeté
clip-box --image scene.png --target "le carré rouge" --json --crop /tmp/square.png
--json renvoie accepted, reason, box, pixels (calculés à partir de la
taille réelle de l'image), confidence, present, found et le model qui a
répondu. Le code de sortie 0 accepte, 2 rejette, 1 est une erreur de requête.
--min-present (par défaut 0.5) et --min-confidence (par défaut 0.30) configurent les
seuils ; les deux sont également des variables d'environnement (BOX_MIN_PRESENT,
BOX_MIN_CONFIDENCE). --crop écrit la boîte acceptée ; il nécessite Pillow.
Capacité, pas hypothèse
box est une fonctionnalité d'adaptation, pas une fonctionnalité de protocole : le propre
/v1/systemone de llama.cpp n'accepte que choice, score et noul. Le slot de décision
alterne entre cinq candidats, donc :
decision-model caps
# model /models/h2o-lightning-4b-Q4_K_M.gguf
# slot :8083 (box sur :8083)
# primitives bool, choice, score, box
Si l'occupant n'est pas h2o, caps n'affiche pas box et box refuse avec le
nom du modèle servi — au lieu d'envoyer une question à laquelle ce point de terminaison ne
peut pas répondre.
Pour quoi il est réellement bon
Mesuré sur ce poste de travail (Q8_0, backend CPU), scènes synthétiques avec vérité connue :
| cible | IoU | confidence | present |
|---|---|---|---|
| carré rouge, 512×512 centré | 0.976 | 0.651 | 0.885 |
| rectangle rouge, 512×1024 haut | 0.877 | 0.669 | 0.897 |
| rectangle rouge, 1024×512 large | 0.848 | 0.722 | 0.895 |
| petit carré rouge dans une scène encombrée | 0.603 | 0.359 | 0.896 |
| "le vélo bleu" (absent) | — | 0.188 | 0.111 |
| "le montant total" sur un reçu | raté (boîte en dessous du total) | 0.144 | 0.899 |
Objets saillants, icônes, formes, images simples : bon, le rapport hauteur/largeur est
traité correctement. Texte petit dense sur un reçu : il rate, et sa faible confiance le
dit. Pour une valeur sur un reçu, recadrez avec le voisinage du total ou utilisez la
question choice de l'API de décision ("quel est le TOTAL ? sous-total/total/taxe"), qui
s'est correctement notée sur la même image.
Le piège que cette habileté existe pour absorber
Pillow. La couche d'adaptation dessine la boîte avant la lecture de l'étroitesse et
renvoie None sur ImportError, donc un Python sans Pillow répond à chaque boîte avec
confidence: 0.0. h2o-serve construit son propre environnement virtuel et vérifie
l'import.
Fichiers
| chemin | rôle |
|---|---|
scripts/clip_box.py | point d'entrée — transfère --port/--host, délègue à decision-model box |
../hardware/decision-model/scripts/decision_model.py | le client : une question box, deux seuils, recadrage, codes de sortie |
../hardware/decision-model/scripts/h2o_serve.py | le lanceur : amorçage épinglé par hachage, environnement virtuel sécurisé pour Pillow, backend CPU/CUDA/Vulkan, --status, --stop |
L'état réside dans ~/.cache/h2o_lightning_gguf (poids + backend épinglé) et
~/.local/share/h2o-lightning/venv. Rien en dehors de ces deux chemins n'est touché.
Notes de protocole
- Le
box.modede la couche d'adaptation est icigenerate: une génération contrainte dans la conventionbbox_2dde Qwen (0–1000, x en premier), analysée et limitée.edges/hybridnécessitent un modèle entraîné sur les lectures de bords ; gardezgenerateavec cette version. confidenceest une probabilité avec sa propre température,1.0jusqu'à ce qu'elle soit ajustée, donc elle est conservatrice : une boîte quasi parfaite sur un grand carré donne 0.65, pas 0.95.- Une image par requête par défaut ; la couche d'adaptation accepte jusqu'à 8 avec
images:et le backend est démarré avec--image-max-tokens 1024. - Le côté décision du même serveur répond à
choice/noul/scoresur le texte et les images via/v1/systemone; pour des décisions calibrées sur le texte, préférezpplx-decider(Indice de décision 60.06 contre 51.38 ici). Utilisez ce modèle pour la géométrie, pas pour le routage.