Évaluations en ligne AI Config
Attachez des judges aux variations AI Config pour un scoring automatique de la qualité en utilisant la méthodologie LLM-as-a-judge. Les judges évaluent les réponses et retournent des scores entre 0,0 et 1,0.
Conditions préalables
- Compte LaunchDarkly avec AI Configs activé
- Token d'accès API avec permissions d'écriture
- AI Config existant avec variations (utilisez la skill
aiconfig-create) - Pour l'enregistrement automatique des métriques et l'API consolidée des résultats de judge : Python AI SDK v0.18.0+ ou Node.js AI SDK v0.17.0+
Détection de la clé API
- Vérifier les variables d'environnement -
LAUNCHDARKLY_API_KEY,LAUNCHDARKLY_API_TOKEN,LD_API_KEY - Vérifier la configuration MCP - Claude :
~/.claude/config.json->mcpServers.launchdarkly.env.LAUNCHDARKLY_API_KEY - Demander à l'utilisateur - Seulement si la détection échoue
Concepts clés
Que sont les judges ?
Les judges sont des AI Configs spécialisés en mode judge qui évaluent les réponses d'autres AI Configs. Ils utilisent un LLM pour scorer les outputs et retourner des résultats structurés :
{
"score": 0.85,
"reasoning": "Answered correctly with one minor omission"
}
Judges intégrés
LaunchDarkly fournit trois judges préconfigurés :
| Judge | Clé métrique | Mesure |
|---|---|---|
| Accuracy | $ld:ai:judge:accuracy |
Exactitude et fondement de la réponse |
| Relevance | $ld:ai:judge:relevance |
Pertinence par rapport à la demande utilisateur |
| Toxicity | $ld:ai:judge:toxicity |
Formulation nuisible ou dangereuse (inférieur = plus sûr) |
Mode Completion uniquement
Les judges ne peuvent être attachés que aux AI Configs en mode completion dans l'interface utilisateur. Pour le mode agent ou les pipelines personnalisés, utilisez l'évaluation programmatique via le SDK.
Restrictions
- Impossible d'attacher des judges à des judges (pas de récursion)
- Impossible d'attacher plusieurs judges avec la même clé métrique à une même variation
- Impossible de voir/modifier les paramètres du modèle ou les tools sur les variations judge
Workflow
Étape 1 : Créer des judges personnalisés (optionnel)
Pour une évaluation spécifique au domaine, créez des AI Configs judge :
# Create judge config
curl -X POST "https://app.launchdarkly.com/api/v2/projects/{projectKey}/ai-configs" \
-H "Authorization: {api_token}" \
-H "Content-Type: application/json" \
-H "LD-API-Version: beta" \
-d '{
"key": "security-judge",
"name": "Security Judge",
"mode": "judge",
"evaluationMetricKey": "security",
"isInverted": false
}'
Note : Définissez
isInverted: truepour les métriques comme toxicity où 0,0 est préférable.
Puis ajoutez une variation avec le prompt d'évaluation :
curl -X POST "https://app.launchdarkly.com/api/v2/projects/{projectKey}/ai-configs/security-judge/variations" \
-H "Authorization: {api_token}" \
-H "Content-Type: application/json" \
-H "LD-API-Version: beta" \
-d '{
"key": "default",
"name": "Default",
"messages": [
{
"role": "system",
"content": "You are a security auditor. Score from 0.0 to 1.0:\n- 1.0: No security issues\n- 0.7-0.9: Minor issues\n- 0.4-0.6: Moderate issues\n- 0.1-0.3: Serious vulnerabilities\n- 0.0: Critical vulnerabilities\n\nCheck for: SQL injection, XSS, hardcoded secrets, command injection."
}
],
"modelConfigKey": "OpenAI.gpt-4o-mini",
"model": {
"parameters": {
"temperature": 0.3
}
}
}'
Étape 2 : Attacher les judges aux variations
Utilisez l'endpoint PATCH de variation :
curl -X PATCH "https://app.launchdarkly.com/api/v2/projects/{projectKey}/ai-configs/{configKey}/variations/{variationKey}" \
-H "Authorization: {api_token}" \
-H "Content-Type: application/json" \
-H "LD-API-Version: beta" \
-d '{
"judgeConfiguration": {
"judges": [
{"judgeConfigKey": "security-judge", "samplingRate": 1.0},
{"judgeConfigKey": "api-contract-judge", "samplingRate": 0.5}
]
}
}'
Important : Le tableau
judgesremplace tous les attachements de judges existants. Un tableau vide supprime tous les judges.
Étape 3 : Définir le fallthrough sur les judges
Chaque AI Config judge doit avoir son fallthrough défini à la variation activée. Les AI Configs utilisent par défaut la variation « disabled » (index 0).
Note :
turnTargetingOnne fonctionne pas pour les AI Configs. UtilisezupdateFallthroughVariationOrRolloutà la place.
# First get the variation ID for "Default" from GET targeting response
curl -X PATCH "https://app.launchdarkly.com/api/v2/projects/{projectKey}/ai-configs/security-judge/targeting" \
-H "Authorization: {api_token}" \
-H "Content-Type: application/json; domain-model=launchdarkly.semanticpatch" \
-H "LD-API-Version: beta" \
-d '{
"environmentKey": "production",
"instructions": [{
"kind": "updateFallthroughVariationOrRollout",
"variationId": "your-default-variation-uuid"
}]
}'
Implémentation Python
import requests
import os
from typing import Optional
class AIConfigJudges:
"""Manager for AI Config judge attachments"""
def __init__(self, api_token: str, project_key: str):
self.api_token = api_token
self.project_key = project_key
self.base_url = "https://app.launchdarkly.com/api/v2"
self.headers = {
"Authorization": api_token,
"Content-Type": "application/json",
"LD-API-Version": "beta"
}
def attach_judges(self, config_key: str, variation_key: str,
judges: list[dict]) -> dict:
"""
Attach judges to a variation.
Args:
config_key: AI Config key
variation_key: Variation key
judges: List of {"judgeConfigKey": str, "samplingRate": float}
"""
url = f"{self.base_url}/projects/{self.project_key}/ai-configs/{config_key}/variations/{variation_key}"
response = requests.patch(url, headers=self.headers, json={
"judgeConfiguration": {"judges": judges}
})
if response.status_code == 200:
print(f"[OK] Attached {len(judges)} judges to {config_key}/{variation_key}")
return response.json()
print(f"[ERROR] {response.status_code}: {response.text}")
return {}
def create_judge(self, key: str, name: str, metric_key: str,
system_prompt: str, model: str = "OpenAI.gpt-4o-mini",
is_inverted: bool = False) -> dict:
"""
Create a judge AI Config.
Args:
key: Judge config key
name: Display name
metric_key: Metric key for scoring (appears as $ld:ai:judge:{metric_key})
system_prompt: Evaluation instructions
is_inverted: True if lower scores are better (e.g., toxicity)
"""
# Create config
config_url = f"{self.base_url}/projects/{self.project_key}/ai-configs"
response = requests.post(config_url, headers=self.headers, json={
"key": key,
"name": name,
"mode": "judge",
"evaluationMetricKey": metric_key,
"isInverted": is_inverted
})
if response.status_code not in [200, 201]:
print(f"[ERROR] Creating config: {response.text}")
return {}
# Create variation
var_url = f"{self.base_url}/projects/{self.project_key}/ai-configs/{key}/variations"
response = requests.post(var_url, headers=self.headers, json={
"key": "default",
"name": "Default",
"messages": [{"role": "system", "content": system_prompt}],
"modelConfigKey": model,
"model": {"parameters": {"temperature": 0.3}}
})
if response.status_code in [200, 201]:
print(f"[OK] Created judge: {key}")
return response.json()
print(f"[ERROR] Creating variation: {response.text}")
return {}
def set_fallthrough(self, config_key: str, environment: str,
variation_key: str = "default") -> bool:
"""
Set fallthrough to enable a judge config.
Note: turnTargetingOn doesn't work for AI Configs. Instead, set the
fallthrough from disabled (index 0) to the enabled variation.
"""
# Get variation ID
url = f"{self.base_url}/projects/{self.project_key}/ai-configs/{config_key}/targeting"
response = requests.get(url, headers=self.headers)
if response.status_code != 200:
print(f"[ERROR] {response.status_code}: {response.text}")
return False
targeting = response.json()
variation_id = None
for var in targeting.get("variations", []):
if var.get("key") == variation_key or var.get("name") == variation_key:
variation_id = var.get("_id")
break
if not variation_id:
print(f"[ERROR] Variation '{variation_key}' not found")
return False
# Set fallthrough
response = requests.patch(url, headers={
**self.headers,
"Content-Type": "application/json; domain-model=launchdarkly.semanticpatch"
}, json={
"environmentKey": environment,
"instructions": [{
"kind": "updateFallthroughVariationOrRollout",
"variationId": variation_id
}]
})
if response.status_code == 200:
print(f"[OK] Fallthrough set for {config_key}")
return True
print(f"[ERROR] {response.status_code}: {response.text}")
return False
SDK : Évaluation automatique
Quand vous utilisez create_chat() + invoke(), les judges attachés évaluent automatiquement :
import os
import json
import asyncio
import ldclient
from ldclient import Context
from ldclient.config import Config
from ldai import LDAIClient, AICompletionConfigDefault
sdk_key = os.getenv('LAUNCHDARKLY_SDK_KEY')
ai_config_key = os.getenv('LAUNCHDARKLY_AI_CONFIG_KEY', 'sample-ai-config')
async def async_main():
ldclient.set_config(Config(sdk_key))
aiclient = LDAIClient(ldclient.get())
context = (
Context.builder('example-user-key')
.kind('user')
.name('Sandy')
.build()
)
default_value = AICompletionConfigDefault(enabled=False)
# create_chat() initializes with judges from AI Config
chat = await aiclient.create_chat(ai_config_key, context, default_value, {})
if not chat:
print(f"AI chat configuration not enabled for: {ai_config_key}")
return
user_input = 'How can LaunchDarkly help me?'
# invoke() automatically evaluates with attached judges
chat_response = await chat.invoke(user_input)
print("Response:", chat_response.message.content)
# Await evaluation results
if chat_response.evaluations and len(chat_response.evaluations) > 0:
eval_results = await asyncio.gather(*chat_response.evaluations)
results_to_display = [
result.to_dict() if result is not None else "not evaluated"
for result in eval_results
]
print("Judge results:")
print(json.dumps(results_to_display, indent=2, default=str))
# Always flush events before closing — trailing events are at risk of being
# lost otherwise, in short-lived scripts and long-running services alike.
ldclient.get().flush()
ldclient.get().close()
SDK : Évaluation directe par judge
Pour le mode agent ou les pipelines personnalisés, évaluez directement les paires input/output :
import os
import json
import asyncio
import ldclient
from ldclient import Context
from ldclient.config import Config
from ldai import LDAIClient, AICompletionConfigDefault
sdk_key = os.getenv('LAUNCHDARKLY_SDK_KEY')
judge_key = os.getenv('LAUNCHDARKLY_AI_JUDGE_KEY', 'sample-ai-judge-accuracy')
async def async_main():
ldclient.set_config(Config(sdk_key))
aiclient = LDAIClient(ldclient.get())
context = (
Context.builder('example-user-key')
.kind('user')
.name('Sandy')
.build()
)
judge_default_value = AICompletionConfigDefault(enabled=False)
# Get judge configuration from LaunchDarkly
judge = await aiclient.create_judge(judge_key, context, judge_default_value)
if not judge:
print(f"AI judge configuration not enabled for key: {judge_key}")
return
input_text = 'You are a helpful assistant. How can you help me?'
output_text = 'I can answer any question you have.'
# Evaluate the input/output pair — always returns a JudgeResult in v0.18.0+
judge_result = await judge.evaluate(input_text, output_text)
if not judge_result.sampled:
print("Judge evaluation was skipped (sample rate or configuration issue)")
return
# Track the consolidated result on the AI Config tracker if needed:
# tracker = ai_config.create_tracker()
# tracker.track_judge_result(judge_result)
print("Judge Result:")
print(json.dumps(judge_result.to_dict(), default=str))
# Always flush events before closing — trailing events are at risk of being
# lost otherwise, in short-lived scripts and long-running services alike.
ldclient.get().flush()
ldclient.get().close()
Note : L'évaluation directe n'enregistre pas automatiquement les métriques. Obtenez un tracker via
ai_config.create_tracker()/aiConfig.createTracker!()et appeleztracker.track_judge_result(result)/tracker.trackJudgeResult(result)pour enregistrer les scores de l'AI Config que vous évaluez. (Cela consolide la paire antérieuretrack_eval_scores+track_judge_responsequi a été supprimée en Python v0.18.0 / Node v0.17.0.)
Taux d'échantillonnage
Chaque réponse évaluée envoie une demande supplémentaire à votre fournisseur de modèle, augmentant l'utilisation de tokens et les coûts. Commencez par un pourcentage d'échantillonnage inférieur et augmentez-le uniquement si vous avez besoin de plus de couverture d'évaluation.
Vous pouvez ajuster les taux d'échantillonnage à tout moment dans la section Judges d'une variation, ou désactiver un judge en définissant son échantillonnage à 0 %.
Affichage des résultats
- Accédez à AI Configs > sélectionnez votre config
- Cliquez sur l'onglet Monitoring
- Sélectionnez Evaluator metrics dans le menu déroulant
- Consultez les scores par variation et plage de temps
Les résultats apparaissent dans 1-2 minutes suivant l'évaluation.
Utilisation dans les guardrails et expériences
Les métriques d'évaluation s'intègrent avec :
- Guarded rollouts : Mettre en pause/annuler quand les scores chutent sous un seuil
- Expériences : Comparer les variations en utilisant les métriques d'évaluation comme objectifs
Gestion des erreurs
| Statut | Cause | Solution |
|---|---|---|
| 404 | Config/variation non trouvé | Vérifiez l'existence des clés |
| 400 | Configuration judge invalide | Vérifiez que judgeConfigKey existe |
| 403 | Permissions insuffisantes | Vérifiez les permissions du token API |
| 422 | Clé métrique dupliquée | Impossible d'attacher plusieurs judges avec la même clé métrique |
Prochaines étapes
Après avoir attaché les judges :
- Définir le fallthrough sur les configs judge à une variation activée (requis)
- Surveiller les résultats dans l'onglet Monitoring
- Ajuster l'échantillonnage selon vos besoins de coût/couverture
- Configurer des guarded rollouts pour la détection automatique des régressions
Skills associées
aiconfig-create- Créer des AI Configs et des judgesaiconfig-targeting- Configurer les règles de targetingaiconfig-variations- Gérer les variations
Références
Exemples Python SDK :
- direct_judge_example.py - Évaluer les paires input/output directement
- chat_judge_example.py - Évaluation automatique avec create_chat/invoke
Exemples Node.js SDK :
- judge-evaluation - Évaluation directe et automatique basée sur le chat