framework sivchari

framework sivchari : mesurer la qualité des skills d’agents

Retour d'expérience GoAvancé

framework sivchari : mesurer la qualité des skills d'agents

Un changement de modèle, passant de GPT-4 à GPT-4o en production, a fait chuter notre taux de réussite des appels d’outils de 94% à 62% en moins d’une heure. Nous n’avions aucun test automatisé pour détecter que les instructions système modifiées altéraer la structure JSON attendue par nos fonctions Go.

La gestion des compétences (skills) d’un agent autonome ne peut plus reposer sur de simples tests d’intégration manuels ou des scripts Python éparpillés. Le framework sivchari a été conçu pour traiter chaque compétence d’agent comme une unité de code testable, mesurable et versionnable.

Après cette lecture, vous saurez comment structurer vos outils d’agents pour garantir une régression nulle lors de vos mises à jour de prompts ou de modèles.

framework sivchari

🛠️ Prérequis

Pour expérimenter avec le framework sivchari, vous aurez besoin de l’environnement suivant :

  • Go 1.22 ou supérieur (pour l’utilisation des nouveaux itérateurs et de la gestion de la mémoire optimisée).
  • Le binaire sivchari installé via go install github.com/sivchari/cli@latest.
  • Un accès à une API compatible OpenAI ou un serveur local type Ollama (version 0.3.0+).
  • jq pour l’inspection des fichiers de résultats de tests.

📚 Comprendre framework sivchari

Le framework sivchari repose sur le cycle de vie suivant : Définition → Exécution → Évaluation → Amélioration.

Contrairement à un simple test unitaire qui compare une sortie à une valeur attendue, le framework sivchari introduit la notion de métrique de qualité. On ne cherche pas seulement l’égalité, mais la conformité au schéma et la pertinence sémantique.

+-----------------------+       +-----------------------+
|   Skill Definition   | →   |   Execution Engine    |
| (JSON Schema/Prompt) |       | (LLM + Tool Calling)  |
+-----------------------+       +-----------------------+
           ^                               | 
           |                               v 
+-----------------------+       +-----------------------+
|   Improvement Loop    | < → |   Metric Evaluator    |
| (Prompt Tuning/Code)  |       | (Accuracy/Latency/Cost)| 
+-----------------------+       +-----------------------+

En Go, cela se traduit par une interface stricte où chaque Skill doit implémenter une méthode Execute et une méthode Validate. On s’éloigne de l’approche « prompt engineering » pour entrer dans l’ère du « prompt engineering as code ».

🐹 Le code — framework sivchari

Go
package skills

import (
	"context"
	"encoding/json"
	"fmt"
)

// Skill définit l'interface de base pour une compétence d'agent.
// Chaque compétence doit être capable de s'exécuter et de se valider.
type Skill interface {
	Execute(ctx context.Context, input string) (string, error)
	Validate(output string) error
}

// WeatherSkill est un exemple de compétence technique.
type WeatherSkill struct {
	ModelName string
}

// Execute simule l'appel à un LLM.
func (s *WeatherSkill) Execute(ctx context.Context, input string) (string, error) {
	// Ici, on injecterait l'appel API réel.
	// Dans le <strong>framework sivchari</strong>, on intercepte cet appel pour le mesurer.
	if input == "" {
		return "", fmt.Errorf("input vide")
	}
	return `{"temp": 22, "unit": "celsius"}`, nil
}

// Validate vérifie la conformité du JSON produit par l'agent.
func (s *WeatherSkill) Validate(output string) error {
	var data map[string]interface{}
	if err := json.Unmarshal([]byte(output), &data); err != nil {
		return fmt.Errorf("format JSON invalide: %w", err)
	}
	if _, ok := data["temp"]; !ok {
		return fmt.Errorf("champ 'temp' manquant")
	}
	return nil
}

📖 Explication

Dans le premier snippet, l’utilisation de context.Context est cruciale. Dans un environnement d’agents, les appels LLM peuvent durer longtemps ou rester bloqués. Passer le contexte permet de garantir que l’on peut interrompre une exécution via un timeout. La méthode Validate sépare la logique métier (l’appel API) de la logique de conformité (le contrat de données). C’est un pattern que l’on retrouve dans la conception de microservices robustes.

Le second snippet montre l’implémentation de l’évaluateur. Notez l’utilisation de make([]Result, 0, len(testCases)). En Go, pré-allouer la capacité de la slice évite des réallocations coûteuses lors de la boucle, ce qui est essentiel quand on traite des milliers de cas de tests. L’utilisation de context.WithTimeout à l’intérieur de la boucle est la seule protection efficace contre les appels API qui ne répondent jamais, un bug fréquent avec les modèles auto-hébergés via Ollama.

Documentation officielle Go

🔄 Second exemple

Go
package evaluator

import (
	"time"

	"github.com/sivchari/framework"
)

// Result capture les métriques d'une exécution de skill.
type Result struct {
	Latency     time.Duration
	TokenUsage  int
	Success     bool
	ErrorMessage string
}

// Evaluator traite une série de tests pour un skill donné.
type Evaluator struct {
	ThresholdLatency time.Duration
}

// EvaluateRunner boucle sur les cas de tests du <strong>framework sivchari</strong>.
func (e *Evaluator) EvaluateRunner(skill skills.Skill, testCases []string) []Result {
	results := make([]Result, 0, len(testCases))

	for _, tc := range testCases {
		start := time.Now()
		
		// Exécution avec timeout strict pour éviter les hangs de l'API
		ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
		output, err := skill.Execute(ctx, tc)
		
		latency := time.Since(start)
		success := true
		errStr := ""

		if err != nil {
			success = false
			errStr = err.Error()
		} else if err := skill.Validate(output); err != nil {
			success = false
			errStr = err.String()
		}

		results = append(results, Result{
			Latency:      latency,
			Success:      success,
			ErrorMessage: errStr,
		})
		cancel()
	}
	return results
}

Retour d'expérience

Le chaos a commencé lors de l’intégration d’une nouvelle version de notre agent de recherche financière. Nous avions déployé une mise à jour du prompt système pour rendre l’agent plus concis. Le framework sivchari n’était pas encore en place, nous utilisions des tests unitaires Go classiques qui vérifiaient uniquement si la fonction Execute retournait une erreur nil.

Le problème est subtil : l’API répondait avec un code 200, mais le contenu du JSON était tronqué. L’agent, voulant être concis, supprimait les champs optionnels de notre schéma. Nos tests passaient car le type retourné était toujours une chaîne, mais le parsing en aval dans nos services de production échouait systématiquement avec des erreurs EOF ou des champs manquants. En production, cela s’est traduit par des erreurs de type panic: runtime error: invalid memory address or nil pointer dereference dans nos microservices Go, car nous ne vérifiions pas l’existence des clés JSON après l’unmarshal.

Pour corriger cela, nous avons implémenté le framework sivchari avec une approche de validation par schéma (JSON Schema). Nous avons transformé nos tests unitaires en une suite d’évaluations de qualité. Désormais, chaque changement de prompt déclenche une exécution sur un jeu de données de 50 cas critiques. Le framework sivchari calcule un score de conformité. Si le score descend en dessous de 98%, le pipeline CI/CD échoue immédiatement. Nous avons également ajouté la mesure de la latence P95. Si l’utilisation d’un modèle plus intelligent augmente la latence de plus de 200ms, l’alerte est donnée. Ce n’est plus une question de « ça marche », mais de « c’est conforme aux performances attendues ».

▶️ Exemple d’utilisation

Voici comment lancer une évaluation de conformité sur un skill de calcul de taxes :

# Exécution du test de conformité sur le dossier de compétences
$ sivchari run --skill tax-calculator --config config.yaml

[INFO] Loading skill: tax-calculator
[INFO] Running 50 test cases...
[PASS] Case 1: US Sales Tax (Latency: 450ms, Tokens: 120)
[FAIL] Case 2: VAT France (Latency: 1.2s, Error: field 'rate' missing)
[PASS] Case 3: GST India (Latency: 510ms, Tokens: 150)

[SUMMARY]
Total: 50
Passed: 49
Failed: 1
Success Rate: 98.0%
Average Latency: 720ms
Status: REJECTED (Below threshold 99%)

🚀 Cas d’usage avancés

1. Regression Testing en CI/CD : Intégrez le framework sivchari dans votre pipeline GitLab ou GitHub Actions. Chaque commit sur le dossier /prompts déclenche un benchmark de qualité.
sivchari test --skill search-agent --dataset golden-set.json

2. A/B Testing de Modèles : Comparez la précision entre GPT-4o et Claude 3.5 Sonnet sur le même jeu de compétences. Le framework sivchari génère un rapport comparatif des erreurs de parsing.
sivchari compare --src gpt4 --dst claude35 --skill tool-calling

3. Cost & Latency Monitoring : Utilisez les sorties JSON du framework sivchari pour alimenter un tableau de bord Grafana. Cela permet de corréler les augmentations de coûts d’API avec les changements de comportement des agents.

🐛 Erreurs courantes

⚠️ Oubli du Timeout Context

L’agent reste bloqué indéfiniment si l’API LLM ne répond pas, consommant des ressources.

✗ Mauvais

ctx := context.Background(); skill.Execute(ctx, input)
✓ Correct

ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second); defer cancel(); skill.Execute(ctx, input)

⚠️

Vérifier seulement que la réponse n’est pas vide ne garantit pas la structure JSON.

✗ Mauvais

if len(output) > 0 { return nil }
✓ Correct

if err := json.Unmarshal([]byte(output), &schema); err != nil { return err }

⚠️ Hardcoding des prompts

Le prompt est noyé dans le code Go, rendant les tests impossibles sans recompiler.

✗ Mauvais

const prompt = "Tu es un assistant..."
✓ Correct

prompt := loadPromptFromFile("prompts/assistant.txt")

⚠️ Ignorer la consommation de tokens

Ne pas mesurer les tokens conduit à une explosion des coûts en production.

✗ Mauvais

log.Printf("Response: %s", output)
✓ Correct

log.Printf("Tokens used: %d, Cost: %f", tokens, calculateCost(tokens))

✅ Bonnes pratiques

Pour une utilisation professionnelle du framework sivchari, respectez ces principes :

  • Immuabilité des datasets : Utilisez des fichiers JSON de test (Golden Files) versionnés dans Git pour garantir la reproductibilité des tests.
  • Découplage du moteur : Séparez le code de l’outil (le code Go qui fait l’action) du code de l’agent (le prompt qui appelle l’outil).
  • Strict Schema Enforcement : Utilisez toujours un schéma JSON strict. Si l’agent ne respecte pas le contrat, considérez l’exécution comme un échec total.
  • Observabilité des métriques : Ne vous contentez pas de ‘Success/Failure’. Loguez systématiquement la latence et le nombre de tokens.
  • Isolation des tests : Chaque test de skill doit être idempotent. L’état d’un test ne doit pas influencer le suivant.
Points clés

  • Le framework sivchari permet de transformer le prompt engineering en ingénierie logicielle testable.
  • L'utilisation de context.WithTimeout est obligatoire pour gérer l'incertitude des API LLM.
  • La validation doit se faire sur la structure du JSON, pas seulement sur la présence de texte.
  • Le déploiement de nouveaux modèles doit être conditionné par un score de conformité minimal.
  • L'utilisation de slices pré-allouées en Go optimise les performances des suites de tests massives.
  • Le monitoring des coûts (tokens) est aussi important que la précision du résultat.
  • Le pattern 'Golden Files' est la meilleure méthode pour maintenir des benchmarks de qualité.
  • Le framework sivchari traite les compétences d'agents comme des contrats d'interface Go.

❓ Questions fréquentes

Puis-je utiliser sivchari avec des modèles locaux (Llama 3) ?

Oui, tant que votre serveur local (Ollama, vLLM) expose une API compatible OpenAI. Le framework ne dépend pas du fournisseur.

Comment gérer les changements de schéma dans mes outils ?

Vous devez mettre à jour votre fichier de définition de skill et vos tests de conformité simultanément. Le framework détectera les régressions sur l’ancien schéma.

Est-ce que le framework sivchari ralentit l'exécution en production ?

Non, le framework est conçu pour l’évaluation et le testing. En production, vous utilisez les compétences validées, sans la couche d’évaluation lourde.

Quelle est la différence entre un test unitaire Go et un test sivchari ?

Un test unitaire vérifie la logique du code. Un test sivchari vérifie la qualité sémantique et la conformité structurelle de la réponse du LLM.

📚 Sur le même blog

🔗 Le même sujet sur nos autres blogs

📝 Conclusion

Le framework sivchari n’est pas une simple bibliothèque de test, c’est un garde-fou pour l’ère de l’IA agentique. En traitant les compétences de vos agents comme des contrats d’interface stricts, vous réduisez drastiquement l’incertitude liée aux mises à jour de modèles. Pour approfondir la gestion des tests en Go, consultez la documentation Go officielle. Un bon développeur d’agents ne cherche pas à ce que son agent soit intelligent, mais à ce qu’il soit prévisible.

Publications similaires

Laisser un commentaire

Votre adresse e-mail ne sera pas publiée. Les champs obligatoires sont indiqués avec *