Ciblage des AI Configs
Configurez les règles de ciblage pour les AI Configs afin de contrôler quelles variations sont servies selon différents contextes. Fonctionne de la même manière en mode completion et en mode agent.
Prérequis
- Compte LaunchDarkly avec AI Configs activé
- Token d'accès API avec permissions d'écriture
- Clé de projet et clé d'environnement
- AI Config existant avec des variations (utilisez la skill
aiconfig-create)
Détection de clé API
- Vérifier les variables d'environnement -
LAUNCHDARKLY_API_KEY,LAUNCHDARKLY_API_TOKEN,LD_API_KEY - Vérifier la config MCP - Claude:
~/.claude/config.json->mcpServers.launchdarkly.env.LAUNCHDARKLY_API_KEY - Demander à l'utilisateur - Uniquement si la détection échoue
Concepts clés
Ordre d'évaluation
Les règles de ciblage s'évaluent dans cet ordre (même que les feature flags) :
- Cibles individuelles - Clés de contexte spécifiques (priorité maximale)
- Règles de segment - Segments prédéfinis
- Règles personnalisées - Conditions basées sur des attributs (évaluées dans l'ordre)
- Règle par défaut - Repli pour tous les autres
- Variation désactivée - Quand le ciblage est désactivé
API Semantic Patch
Le ciblage des AI Configs utilise les instructions semantic patch :
PATCH /api/v2/projects/{projectKey}/ai-configs/{configKey}/targeting
Content-Type: application/json; domain-model=launchdarkly.semanticpatch
Concepts clés
- variationId : UUIDs, pas des clés. Récupérez toujours le ciblage d'abord pour obtenir les IDs.
- Poids : Millièmes (50000 = 50%, 100000 = 100%)
- Logique de clauses : Plusieurs clauses = ET, plusieurs valeurs = OU
- Attributs nulls : Les règles avec attributs null/manquants sont ignorées
Workflow
Étape 1 : Obtenir le ciblage (avec IDs de variations)
curl -X GET "https://app.launchdarkly.com/api/v2/projects/{projectKey}/ai-configs/{configKey}/targeting" \
-H "Authorization: {api_token}" \
-H "LD-API-Version: beta"
La réponse inclut un tableau variations avec _id (UUID) pour chaque variation.
Étape 2 : Modifier la règle par défaut
Modifiez la règle par défaut pour servir la variation que vous avez créée.
Important : L'instruction
turnTargetingOnne fonctionne pas pour les AI Configs. UtilisezupdateFallthroughVariationOrRolloutà la place.
# D'abord, récupérez les IDs de variations de la réponse de l'Étape 1
# Ensuite, définissez le repli vers la variation activée (ex : variation "Default")
curl -X PATCH "https://app.launchdarkly.com/api/v2/projects/{projectKey}/ai-configs/{configKey}/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-enabled-variation-uuid"
}]
}'
Étape 3 : Ajouter des règles de ciblage
Règle basée sur les attributs :
curl -X PATCH "https://app.launchdarkly.com/api/v2/projects/{projectKey}/ai-configs/{configKey}/targeting" \
-H "Authorization: {api_token}" \
-H "Content-Type: application/json; domain-model=launchdarkly.semanticpatch" \
-H "LD-API-Version: beta" \
-d '{
"environmentKey": "production",
"instructions": [{
"kind": "addRule",
"clauses": [{
"contextKind": "user",
"attribute": "selectedModel",
"op": "contains",
"values": ["sonnet"],
"negate": false
}],
"variation": 0
}]
}'
Déploiement progressif en pourcentage :
curl -X PATCH "..." \
-d '{
"environmentKey": "production",
"instructions": [{
"kind": "addRule",
"clauses": [{
"contextKind": "user",
"attribute": "tier",
"op": "in",
"values": ["premium"],
"negate": false
}],
"percentageRolloutConfig": {
"contextKind": "user",
"bucketBy": "key",
"variations": [
{"variation": 0, "weight": 60000},
{"variation": 1, "weight": 40000}
]
}
}]
}'
Définir le repli (règle par défaut) :
curl -X PATCH "..." \
-d '{
"environmentKey": "production",
"instructions": [{
"kind": "updateFallthroughVariationOrRollout",
"variationId": "fallback-variation-uuid"
}]
}'
Implémentation Python
import requests
import os
from typing import Dict, List, Optional
class AIConfigTargeting:
"""Manager for AI Config targeting rules"""
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"
def get_targeting(self, config_key: str) -> Optional[Dict]:
"""Get current targeting with variation IDs."""
url = f"{self.base_url}/projects/{self.project_key}/ai-configs/{config_key}/targeting"
response = requests.get(url, headers={
"Authorization": self.api_token,
"LD-API-Version": "beta"
})
if response.status_code == 200:
return response.json()
print(f"[ERROR] {response.status_code}: {response.text}")
return None
def get_variation_id(self, config_key: str, variation_key: str) -> Optional[str]:
"""Look up variation UUID from key or name."""
targeting = self.get_targeting(config_key)
if targeting:
for var in targeting.get("variations", []):
if var.get("key") == variation_key or var.get("name") == variation_key:
return var.get("_id")
return None
def update_targeting(self, config_key: str, environment: str,
instructions: List[Dict], comment: str = "") -> Optional[Dict]:
"""Send semantic patch instructions."""
url = f"{self.base_url}/projects/{self.project_key}/ai-configs/{config_key}/targeting"
payload = {"environmentKey": environment, "instructions": instructions}
if comment:
payload["comment"] = comment
response = requests.patch(url, headers={
"Authorization": self.api_token,
"Content-Type": "application/json; domain-model=launchdarkly.semanticpatch",
"LD-API-Version": "beta"
}, json=payload)
if response.status_code == 200:
return response.json()
print(f"[ERROR] {response.status_code}: {response.text}")
return None
def enable_config(self, config_key: str, environment: str,
variation_key: str = "default") -> bool:
"""
Enable an AI Config by setting fallthrough to an enabled variation.
Note: turnTargetingOn doesn't work for AI Configs. Instead, set the
fallthrough from the disabled variation (index 0) to an enabled one.
"""
variation_id = self.get_variation_id(config_key, variation_key)
if not variation_id:
print(f"[ERROR] Variation '{variation_key}' not found")
return False
return self.set_fallthrough(config_key, environment, variation_id)
def add_rule(self, config_key: str, environment: str,
clauses: List[Dict], variation: int,
description: str = "") -> bool:
"""Add targeting rule serving a specific variation index."""
instruction = {
"kind": "addRule",
"clauses": clauses,
"variation": variation
}
if description:
instruction["description"] = description
result = self.update_targeting(config_key, environment,
[instruction], f"Add rule: {description}")
if result:
print(f"[OK] Rule added")
return True
return False
def add_rollout_rule(self, config_key: str, environment: str,
clauses: List[Dict],
weights: List[Dict],
bucket_by: str = "key") -> bool:
"""
Add percentage rollout rule.
weights: [{"variation": 0, "weight": 50000}, {"variation": 1, "weight": 50000}]
"""
result = self.update_targeting(config_key, environment, [{
"kind": "addRule",
"clauses": clauses,
"percentageRolloutConfig": {
"contextKind": "user",
"bucketBy": bucket_by,
"variations": weights
}
}], "Add percentage rollout")
if result:
print(f"[OK] Rollout rule added")
return True
return False
def set_fallthrough(self, config_key: str, environment: str,
variation_id: str) -> bool:
"""Set default (fallthrough) variation by UUID."""
result = self.update_targeting(config_key, environment, [{
"kind": "updateFallthroughVariationOrRollout",
"variationId": variation_id
}], "Set fallthrough")
if result:
print(f"[OK] Fallthrough set")
return True
return False
def target_individuals(self, config_key: str, environment: str,
context_keys: List[str], variation: int,
context_kind: str = "user") -> bool:
"""Target specific context keys."""
result = self.update_targeting(config_key, environment, [{
"kind": "addTargets",
"variation": variation,
"contextKind": context_kind,
"values": context_keys
}], f"Target {len(context_keys)} individuals")
if result:
print(f"[OK] Individual targets added")
return True
return False
def target_segment(self, config_key: str, environment: str,
segment_keys: List[str], variation: int) -> bool:
"""Target a segment."""
result = self.update_targeting(config_key, environment, [{
"kind": "addRule",
"clauses": [{
"attribute": "segmentMatch",
"contextKind": "", # Leave blank for segments
"op": "segmentMatch",
"values": segment_keys,
"negate": False
}],
"variation": variation
}], f"Target segments: {segment_keys}")
if result:
print(f"[OK] Segment targeting added")
return True
return False
def clear_rules(self, config_key: str, environment: str) -> bool:
"""Remove all targeting rules."""
result = self.update_targeting(config_key, environment,
[{"kind": "replaceRules", "rules": []}], "Clear all rules")
if result:
print(f"[OK] All rules cleared")
return True
return False
Référence des instructions
Note :
turnTargetingOnetturnTargetingOffne fonctionnent pas pour les AI Configs. Les AI Configs ont le ciblage activé par défaut. Pour « activer » une config, définissez le repli vers une variation activée en utilisantupdateFallthroughVariationOrRollout.
Règles
| Kind | Description |
|---|---|
addRule |
Ajouter une règle avec clauses et variation/déploiement |
removeRule |
Supprimer par ruleId |
replaceRules |
Remplacer toutes les règles |
reorderRules |
Modifier l'ordre d'évaluation |
updateRuleVariationOrRollout |
Mettre à jour ce qu'une règle sert |
Repli
| Kind | Description |
|---|---|
updateFallthroughVariationOrRollout |
Définir la variation ou le déploiement par défaut |
Cibles individuelles
| Kind | Description |
|---|---|
addTargets |
Cibler des clés de contexte spécifiques |
removeTargets |
Supprimer des cibles spécifiques |
replaceTargets |
Remplacer toutes les cibles |
Référence des opérateurs
| Operator | Description | Exemple |
|---|---|---|
in |
Valeur dans une liste | ["premium", "enterprise"] |
contains |
La chaîne contient | ["sonnet"] |
startsWith |
Préfixe de chaîne | ["user-"] |
endsWith |
Suffixe de chaîne | [".edu"] |
matches |
Correspondance regex | ["^user-\\d+$"] |
greaterThan / lessThan |
Comparaison numérique | [100] |
before / after |
Comparaison de date | ["2024-12-31T00:00:00Z"] |
semVerEqual / semVerGreaterThan |
Comparaison de version | ["2.0.0"] |
segmentMatch |
Appartenance au segment | ["beta-testers"] |
Structure de clause
{
"contextKind": "user",
"attribute": "email",
"op": "endsWith",
"values": [".edu"],
"negate": false
}
- Plusieurs clauses = ET (toutes doivent correspondre)
- Plusieurs valeurs = OU (une quelconque peut correspondre)
negate: trueinverse l'opérateur
Types de déploiement
Déploiement progressif manuel en pourcentage
{
"percentageRolloutConfig": {
"contextKind": "user",
"bucketBy": "key",
"variations": [
{"variation": 0, "weight": 50000},
{"variation": 1, "weight": 50000}
]
}
}
Déploiement progressif
{
"progressiveRolloutConfig": {
"contextKind": "user",
"controlVariation": 1,
"endVariation": 0,
"steps": [
{"rolloutWeight": 1000, "duration": {"quantity": 4, "unit": "hour"}},
{"rolloutWeight": 5000, "duration": {"quantity": 4, "unit": "hour"}},
{"rolloutWeight": 10000, "duration": {"quantity": 4, "unit": "hour"}}
]
}
}
Déploiement sécurisé
{
"guardedRolloutConfig": {
"randomizationUnit": "user",
"stages": [
{"rolloutWeight": 1000, "monitoringWindowMilliseconds": 17280000},
{"rolloutWeight": 5000, "monitoringWindowMilliseconds": 17280000}
],
"metrics": [{
"metricKey": "error-rate",
"onRegression": {"rollback": true},
"regressionThreshold": 0.01
}]
}
}
Motifs courants
Routage de modèle par attribut
# Router selon l'attribut de contexte selectedModel
targeting.add_rule(
config_key="model-selector",
environment="production",
clauses=[{
"contextKind": "user",
"attribute": "selectedModel",
"op": "contains",
"values": ["sonnet"],
"negate": False
}],
variation=0, # Index de variation Sonnet
description="Route sonnet requests"
)
Variation basée sur le tier
targeting.add_rule(
config_key="chat-assistant",
environment="production",
clauses=[{
"contextKind": "user",
"attribute": "tier",
"op": "in",
"values": ["premium", "enterprise"],
"negate": False
}],
variation=0 # Variation de modèle premium
)
Ciblage de segment
targeting.target_segment(
config_key="chat-assistant",
environment="production",
segment_keys=["beta-testers"],
variation=1 # Variation expérimentale
)
Gestion des erreurs
| Status | Cause | Solution |
|---|---|---|
| 400 | Semantic patch invalide | Vérifiez le format des instructions, les ops doivent être en minuscules |
| 403 | Permissions insuffisantes | Vérifiez le token API |
| 404 | Config non trouvée | Vérifiez projectKey et configKey |
| 422 | Variation invalide | Utilisez l'index (0, 1, 2...) ou l'UUID de la réponse de ciblage |
Étapes suivantes
Après la configuration du ciblage :
- Fournir l'URL de la config :
https://app.launchdarkly.com/projects/{projectKey}/ai-configs/{configKey} - Surveiller les performances avec
aiconfig-ai-metrics - Attacher des juges avec
aiconfig-online-evals - Configurer des déploiements sécurisés pour la détection automatique de régression
Skills connexes
aiconfig-create- Créer des AI Configs avec variationsaiconfig-variations- Gérer les variationsaiconfig-online-evals- Attacher des jugesaiconfig-segments- Créer des segments pour le ciblage