omni-ai-eval

Par exploreomni · omni-agent-skills

Évaluez la précision de génération de requêtes d'Omni AI en exécutant des prompts de test via l'Omni CLI, en comparant le JSON de requête généré aux résultats attendus, et en calculant un score de précision. Utilisez cette skill chaque fois que quelqu'un souhaite évaluer Omni AI, benchmarker Blobby, exécuter des tests de régression, comparer des sorties AI entre branches ou configurations, tester des variations de prompt, mesurer la qualité de l'AI, réaliser des A/B tests sur des changements de modèle, évaluer l'impact de modifications de contexte, ou toute variante de « run evals », « test Blobby », « benchmark query generation », « compare AI results », « regression test », « how accurate is the AI » ou « measure the impact of my changes ».

npx skills add https://github.com/exploreomni/omni-agent-skills --skill omni-ai-eval

Omni Eval

Exécutez des evals sur les APIs de génération de requêtes IA d'Omni — soumettez des prompts de test, capturez le JSON de requête généré, comparez-le avec les résultats attendus et évaluez la précision selon plusieurs dimensions.

Conseil : Utilisez omni-ai-optimizer pour améliorer les scores après avoir identifié des défaillances, et omni-model-explorer pour découvrir les topics et champs disponibles pour construire des cas d'eval.

Prérequis

# Vérifiez que l'Omni CLI est installé — sinon, demandez à l'utilisateur de l'installer
# Voir : https://github.com/exploreomni/cli#readme
command -v omni >/dev/null || echo "ERROR: Omni CLI is not installed."
# Affichage des profils disponibles et sélection du profil approprié
omni config show
# S'il existe plusieurs profils, demandez à l'utilisateur lequel utiliser, puis changez :
omni config use <profile-name>

Vous avez aussi besoin d'un ID de modèle et d'un ensemble d'eval — un fichier de cas de test avec des prompts et des structures de requête attendues. Consultez le Guide de Conception d'Eval pour les meilleures pratiques de construction d'ensembles d'eval.

Découverte des Commandes

omni ai --help    # Opérations IA (generate-query, jobs, pick-topic)

Conseil : Utilisez -o json pour forcer une sortie structurée pour l'analyse programmatique, ou -o human pour des tableaux lisibles. Par défaut, auto (humain dans un TTY, JSON lors du pipe).

Format d'Entrée d'Eval

Chaque cas d'eval associe un prompt en langage naturel à la structure de requête attendue. JSONL (un objet JSON par ligne) fonctionne bien pour les exécutions en masse :

{"id": "rev-by-month", "prompt": "Show me revenue by month", "modelId": "your-model-id", "expected": {"topic": "order_items", "fields": ["order_items.created_at[month]", "order_items.total_revenue"], "filters": {}, "sorts": [{"column_name": "order_items.created_at[month]", "sort_descending": false}]}, "tags": ["time-series"]}
{"id": "top-customers", "prompt": "Top 10 customers by spend", "modelId": "your-model-id", "expected": {"topic": "order_items", "fields": ["users.name", "order_items.total_revenue"], "filters": {}, "sorts": [{"column_name": "order_items.total_revenue", "sort_descending": true}]}, "tags": ["top-n"]}
Champ Requis Description
id Oui Identifiant unique du cas d'eval
prompt Oui Question en langage naturel à envoyer à l'IA
modelId Oui UUID du modèle cible
expected Oui Objet avec topic, fields, filters, sorts
branchId Non Branche à tester
currentTopicName Non Limiter à un topic spécifique
tags Non Tableau de tags pour filtrer/regrouper les résultats

Note : JSONL est montré ici, mais n'importe quel format structuré fonctionne — CSV, tableaux JSON, YAML — tant que vous pouvez itérer sur les cas et extraire ces champs.

Exécution des Evals : Chemin Rapide (API Generate Query)

Le endpoint synchrone generate-query est le moyen le plus rapide d'évaluer la génération de requêtes. Passez --run-query false pour obtenir uniquement le JSON de requête généré sans l'exécuter contre la base de données.

Appel Eval Unique

omni ai generate-query your-model-id "Show me revenue by month" --run-query false

Structure de Réponse

{
  "query": {
    "fields": ["order_items.created_at[month]", "order_items.total_revenue"],
    "table": "order_items",
    "filters": {},
    "sorts": [{"column_name": "order_items.created_at[month]", "sort_descending": false}],
    "limit": 500
  },
  "topic": "order_items",
  "error": null
}

Paramètres de Requête

Arg/Flag Requis Description
<model-id> Oui UUID du modèle Omni (arg positionnel)
<prompt> Oui Question en langage naturel (arg positionnel)
--run-query Non Définir à false pour ignorer l'exécution de la requête (plus rapide, par défaut true)
--branch-id Non UUID de branche pour les tests spécifiques à une branche
--current-topic-name Non Limiter la sélection du topic à un topic spécifique

Boucle Batch (bash)

while IFS= read -r line; do
  id=$(echo "$line" | jq -r '.id')
  prompt=$(echo "$line" | jq -r '.prompt')
  model_id=$(echo "$line" | jq -r '.modelId')
  branch_id=$(echo "$line" | jq -r '.branchId // empty')

  branch_flag=""
  if [ -n "$branch_id" ]; then
    branch_flag="--branch-id $branch_id"
  fi

  result=$(omni ai generate-query "$model_id" "$prompt" --run-query false $branch_flag --compact)

  echo "{\"id\": \"$id\", \"generated\": $result}" >> eval_results.jsonl
done < eval_cases.jsonl

Exécution des Evals : Chemin Agentic (API AI Jobs)

Utilisez l'API asynchrone AI Jobs lorsque vous voulez tester le workflow agentic complet — analyse multi-étapes, tool use et sélection de topic comme Blobby le ferait en production.

Soumettre un Job

omni ai job-submit your-model-id "Show me revenue by month"

Réponse :

{
  "jobId": "job-uuid",
  "conversationId": "conv-uuid",
  "omniChatUrl": "https://yourorg.omniapp.co/chat/..."
}

Attendre la Complétion

omni ai job-status <jobId>

Progression du statut : QUEUEDEXECUTINGCOMPLETE (ou FAILED). Interrogez avec backoff exponentiel (par exemple, 2s, 4s, 8s) jusqu'à ce que le state soit terminal.

Obtenir le Résultat

omni ai job-result <jobId>

Le résultat contient un tableau actions. Cherchez les actions avec type: "generate_query" pour extraire le JSON de requête :

{
  "actions": [
    {
      "type": "generate_query",
      "message": "Querying revenue by month...",
      "result": {
        "queryName": "Revenue by Month",
        "query": { "fields": [...], "table": "...", "filters": {...} },
        "status": "success",
        "totalRowCount": 12
      }
    }
  ],
  "topic": "order_items",
  "resultSummary": "Here are the monthly revenue figures..."
}

Quand Utiliser Quel Chemin

Critère Generate Query (Rapide) AI Jobs (Agentic)
Vitesse Synchrone, rapide Async, plus lent
Volume Exécutions haute volume Volume plus faible
Portée Génération de requête seulement Workflow agent complet
Cas d'usage Précision des champs/filtres Comportement bout en bout
Multi-étapes Requête unique Peut générer plusieurs requêtes

Test de Sélection de Topic

Évaluez la sélection de topic indépendamment avec le endpoint pick-topic :

omni ai pick-topic your-model-id "How many users signed up last month?"

Réponse :

{
  "topicId": "users"
}

Cela vous permet d'évaluer la précision de la sélection de topic comme dimension séparée — utile lorsque la sélection de topic est un point faible connu.

Scoring : Comparaison Structurelle de Requête

Comparez le JSON de requête généré contre la requête attendue selon quatre dimensions :

Dimension Méthode de Comparaison Scoring
topic Correspondance exacte de chaîne réussi/échoué
fields Comparaison d'ensemble (indépendante de l'ordre) réussi/échoué + score de similarité
filters Correspondance clé-valeur (clé présente + valeur correspond) réussi/échoué par clé de filtre
sorts Comparaison d'ordre de tableau réussi/échoué

Exemple de Logique de Comparaison (TypeScript)

function scoreEval(expected: any, generated: any) {
  // Topic: exact match
  const topicPass = generated.topic === expected.topic;

  // Fields: set comparison (order-independent)
  const expectedFields = new Set(expected.fields);
  const generatedFields = new Set(generated.query.fields);
  const missing = [...expectedFields].filter(f => !generatedFields.has(f));
  const extra = [...generatedFields].filter(f => !expectedFields.has(f));
  const fieldsPass = missing.length === 0 && extra.length === 0;

  // Filters: key-value match
  const expectedFilters = expected.filters || {};
  const generatedFilters = generated.query.filters || {};
  const missingKeys = Object.keys(expectedFilters).filter(k => !(k in generatedFilters));
  const wrongValues = Object.keys(expectedFilters)
    .filter(k => k in generatedFilters && generatedFilters[k] !== expectedFilters[k]);
  const filtersPass = missingKeys.length === 0 && wrongValues.length === 0;

  // Sorts: ordered comparison
  const sortsPass = JSON.stringify(expected.sorts || []) ===
    JSON.stringify(generated.query.sorts || []);

  return {
    topic: topicPass,
    fields: { pass: fieldsPass, missing, extra },
    filters: { pass: filtersPass, missingKeys, wrongValues },
    sorts: sortsPass,
    allPass: topicPass && fieldsPass && filtersPass && sortsPass,
  };
}

Scoring Agrégé

Calculez les taux de réussite sur tous les cas d'eval :

Eval Results: 47/50 passed (94,0%)
  Topic:   49/50 (98,0%)
  Fields:  47/50 (94,0%)
  Filters: 48/50 (96,0%)
  Sorts:   50/50 (100,0%)

Les taux par dimension aident à identifier où la précision est la plus faible — si la précision du topic est élevée mais celle des filtres est basse, concentrez les améliorations de ai_context sur les orientations liées aux filtres.

Comparaison A/B

Exécutez la même suite d'eval avec une variable modifiée pour mesurer l'impact. C'est le workflow central pour comprendre si une modification améliore ou dégrade la précision de l'IA.

Variables Courantes à Comparer

  • Branches de modèle — passez différentes valeurs --branch-id pour tester les changements de contexte sur une branche avant de fusionner
  • Portée du topic--current-topic-name "orders" vs omis (auto-sélection)
  • Changements de contexte de modèleai_context, sample_queries, descriptions de champs (appliquez via omni-model-builder sur une branche, puis évaluez contre cette branche)
  • Formulation du prompt — même requête attendue, texte de prompt différent
  • Configuration de l'IA — type de modèle, niveau de réflexion ou autres paramètres IA

Workflow

  1. Exécutez la suite d'eval avec configuration A → enregistrez sous results_a.jsonl
  2. Exécutez la suite d'eval avec configuration B → enregistrez sous results_b.jsonl
  3. Évaluez les deux ensembles de résultats
  4. Comparez côte à côte, en vérifiant les régressions

Exemple de Sortie de Comparaison

A/B Comparison: main vs branch/new-context
                      A (main)    B (new-context)    Delta
Overall pass rate:    88,0%       94,0%              +6,0%
Topic accuracy:       96,0%       98,0%              +2,0%
Field accuracy:       90,0%       94,0%              +4,0%
Filter accuracy:      88,0%       96,0%              +8,0%

Regressions (passed in A, failed in B):
  - rev-by-quarter: fields missing order_items.total_revenue

Improvements (failed in A, passed in B):
  - customer-count: topic now correctly selects users
  - top-products: filters now include status=complete

Important : Vérifiez toujours les régressions, pas seulement l'amélioration globale. Une amélioration nette qui casse des cas précédemment corrects peut indiquer un conflit de ai_context.

Snapshot de l'État du Modèle

Avant d'exécuter les evals, faites un snapshot de la définition du modèle pour que les résultats soient reproductibles :

# Enregistrer le modèle YAML
omni models yaml-get <modelId> --compact > model_snapshot_$(date +%Y%m%d).json

# Valider l'intégrité du modèle
omni models validate <modelId>

Versionnez votre ensemble d'eval à côté des snapshots de modèle pour pouvoir tracer quel état de modèle a produit quels scores.

Problèmes Connus & Pièges

  • La comparaison de filtres peut être complexe — Omni supporte les expressions de filtre riches ("last 7 days", "between 10 and 100", "not null"). La comparaison structurelle ci-dessus utilise la correspondance exacte de chaîne sur les valeurs de filtre. Si l'IA produit des expressions sémantiquement équivalentes mais syntaxiquement différentes, vous pouvez voir des faux négatifs. Envisagez de normaliser les motifs courants ou d'utiliser un seuil Jaccard.
  • AI Jobs sont asynchrones — interrogez avec backoff exponentiel. N'inondez pas le endpoint de statut.
  • Rate limiting — pour les exécutions d'eval haute volume, ajoutez un petit délai entre les appels ou regroupez les requêtes.
  • Le champ limit peut varier — l'IA peut choisir des limites différentes de celles attendues. Envisagez d'exclure limit de la comparaison stricte si ce n'est pas critique pour votre eval.
  • table vs topic — la réponse generate-query retourne topic comme champ de niveau supérieur et table à l'intérieur de l'objet query. Ils correspondent généralement mais ne sont pas toujours identiques. Comparez contre le topic de niveau supérieur.

Référence Documentation

Skills Connexes

  • omni-query — exécuter des requêtes golden pour valider les résultats attendus
  • omni-model-explorer — découvrir les topics et champs pour construire des cas d'eval
  • omni-ai-optimizer — améliorer la précision de l'IA selon les résultats d'eval
  • omni-model-builder — appliquer les changements de contexte sur les branches avant les tests A/B

Skills similaires