---
title: Modération de contenu
url: https://platform.claude.com/docs/fr/about-claude/use-case-guides/content-moderation
description: La modération de contenu est un aspect essentiel du maintien d'un environnement sûr, respectueux et productif dans les applications numériques. Ce guide explique comment Claude peut être utilisé pour modérer le contenu au sein de votre application numérique.
---

> Consultez le [cookbook de modération de contenu](https://platform.claude.com/cookbook/misc-building-moderation-filter) pour voir un exemple d'implémentation de modération de contenu utilisant Claude.

<Tip>
  Ce guide se concentre sur la modération du contenu généré par les utilisateurs au sein de votre application. Si vous recherchez des conseils sur la modération des interactions avec Claude, reportez-vous à 

  [Atténuer les jailbreaks et les injections de prompt](https://platform.claude.com/docs/fr/test-and-evaluate/strengthen-guardrails/mitigate-jailbreaks)

  .
</Tip>

## Avant de construire avec Claude

### Décider d'utiliser ou non Claude pour la modération de contenu

Voici quelques indicateurs clés montrant que vous devriez utiliser un « large language model » (grand modèle de langage), ou LLM, comme Claude plutôt qu'une approche traditionnelle de ML ou basée sur des règles pour la modération de contenu :

<AccordionGroup>
  <Accordion title="Vous souhaitez une implémentation économique et rapide">
    Les méthodes de ML traditionnelles nécessitent d'importantes ressources d'ingénierie, une expertise en ML et des coûts d'infrastructure. Les systèmes de modération humaine entraînent des coûts encore plus élevés. Avec Claude, vous pouvez disposer d'un système de modération sophistiqué opérationnel en beaucoup moins de temps et à un coût bien moindre.
  </Accordion>

  <Accordion title="Vous souhaitez à la fois une compréhension sémantique et des décisions rapides">
    Les approches de ML traditionnelles, telles que les modèles de sac de mots ou la simple correspondance de motifs, peinent souvent à comprendre le ton, l'intention et le contexte du contenu. Bien que les systèmes de modération humaine excellent dans la compréhension du sens sémantique, ils nécessitent du temps pour que le contenu soit examiné. Claude répond à ces deux besoins en combinant la compréhension sémantique avec la capacité de rendre rapidement des décisions de modération.
  </Accordion>

  <Accordion title="Vous avez besoin de décisions de politique cohérentes">
    En tirant parti de ses capacités de raisonnement avancées, Claude peut interpréter et appliquer uniformément des directives de modération complexes. Cette cohérence contribue à garantir un traitement équitable de tous les contenus, réduisant le risque de décisions de modération incohérentes ou biaisées susceptibles de saper la confiance des utilisateurs.
  </Accordion>

  <Accordion title="Vos politiques de modération sont susceptibles de changer ou d'évoluer au fil du temps">
    Une fois qu'une approche de ML traditionnelle a été établie, la modifier est une entreprise laborieuse et gourmande en données. En revanche, à mesure que votre produit ou les besoins de vos clients évoluent, Claude peut facilement s'adapter aux modifications ou aux ajouts de politiques de modération sans réétiquetage approfondi des données d'entraînement.
  </Accordion>

  <Accordion title="Vous avez besoin d'un raisonnement interprétable pour vos décisions de modération">
    Si vous souhaitez fournir aux utilisateurs ou aux régulateurs des explications claires sur les décisions de modération, Claude peut générer des justifications détaillées et cohérentes. Cette transparence est importante pour instaurer la confiance et garantir la responsabilité dans les pratiques de modération de contenu.
  </Accordion>

  <Accordion title="Vous avez besoin d'une prise en charge multilingue sans maintenir de modèles distincts">
    Les approches de ML traditionnelles nécessitent généralement des modèles distincts ou des processus de traduction approfondis pour chaque langue prise en charge. La modération humaine nécessite l'embauche d'une main-d'œuvre maîtrisant chaque langue prise en charge. Les capacités multilingues de Claude lui permettent de classer des tickets dans diverses langues sans nécessiter de modèles distincts ni de processus de traduction approfondis, ce qui simplifie la modération pour des bases de clients mondiales.
  </Accordion>

  <Accordion title="Vous avez besoin d'une prise en charge multimodale">
    Les capacités multimodales de Claude lui permettent d'analyser et d'interpréter du contenu à la fois textuel et visuel. Cela en fait un outil polyvalent pour une modération de contenu complète dans des environnements où différents types de médias doivent être évalués ensemble.
  </Accordion>
</AccordionGroup>

<Note>
  Tous les modèles Claude sont entraînés avec des comportements de sécurité intégrés. Cela peut amener Claude à modérer du contenu jugé particulièrement dangereux (conformément à la 

  [Politique d'utilisation acceptable](https://www.anthropic.com/legal/aup)

  ), quel que soit le prompt utilisé. Par exemple, un site web pour adultes qui souhaite autoriser les utilisateurs à publier du contenu sexuel explicite peut constater que Claude signale toujours le contenu explicite comme nécessitant une modération, même s'il précise dans son prompt de ne pas modérer le contenu sexuel explicite. Envisagez de consulter la Politique d'utilisation acceptable avant de construire une solution de modération.
</Note>

### Générer des exemples de contenu à modérer

Avant de développer une solution de modération de contenu, créez d'abord des exemples de contenu qui devrait être signalé et de contenu qui ne devrait pas l'être. Veillez à inclure des cas limites et des scénarios difficiles qui peuvent être délicats à traiter efficacement pour un système de modération de contenu. Ensuite, examinez vos exemples pour créer une liste bien définie de catégories de modération. Par exemple, les exemples générés par une plateforme de réseau social pourraient inclure les éléments suivants :

<CodeGroup exclude="shell">
  ```python Python
  client = anthropic.Anthropic()

  allowed_user_comments = [
      "This movie was great, I really enjoyed it. The main actor really killed it!",
      "I hate Mondays.",
      "It is a great time to invest in gold!",
  ]

  disallowed_user_comments = [
      "Delete this post now or you better hide. I am coming after you and your family.",
      "Stay away from the 5G cellphones!! They are using 5G to control you.",
      "Congratulations! You have won a $1,000 gift card. Click here to claim your prize!",
  ]

  # Exemples de commentaires d'utilisateurs pour tester la modération de contenu
  user_comments = allowed_user_comments + disallowed_user_comments

  # Catégories considérées comme dangereuses pour la modération de contenu
  unsafe_categories = [
      "Child Exploitation",
      "Conspiracy Theories",
      "Hate",
      "Indiscriminate Weapons",
      "Intellectual Property",
      "Non-Violent Crimes",
      "Privacy",
      "Self-Harm",
      "Sex Crimes",
      "Sexual Content",
      "Specialized Advice",
      "Violent Crimes",
  ]
  ```

  ```typescript TypeScript
  const client = new Anthropic();

  const allowedUserComments = [
    "This movie was great, I really enjoyed it. The main actor really killed it!",
    "I hate Mondays.",
    "It is a great time to invest in gold!"
  ];

  const disallowedUserComments = [
    "Delete this post now or you better hide. I am coming after you and your family.",
    "Stay away from the 5G cellphones!! They are using 5G to control you.",
    "Congratulations! You have won a $1,000 gift card. Click here to claim your prize!"
  ];

  // Exemples de commentaires d'utilisateurs pour tester la modération de contenu
  const userComments = [...allowedUserComments, ...disallowedUserComments];

  // Catégories considérées comme dangereuses pour la modération de contenu
  const unsafeCategories = [
    "Child Exploitation",
    "Conspiracy Theories",
    "Hate",
    "Indiscriminate Weapons",
    "Intellectual Property",
    "Non-Violent Crimes",
    "Privacy",
    "Self-Harm",
    "Sex Crimes",
    "Sexual Content",
    "Specialized Advice",
    "Violent Crimes"
  ];
  ```

  ```csharp C#
  var client = new AnthropicClient();

  string[] allowedUserComments =
  [
      "This movie was great, I really enjoyed it. The main actor really killed it!",
      "I hate Mondays.",
      "It is a great time to invest in gold!",
  ];

  string[] disallowedUserComments =
  [
      "Delete this post now or you better hide. I am coming after you and your family.",
      "Stay away from the 5G cellphones!! They are using 5G to control you.",
      "Congratulations! You have won a $1,000 gift card. Click here to claim your prize!",
  ];

  // Exemples de commentaires d'utilisateurs pour tester la modération de contenu
  string[] userComments = [.. allowedUserComments, .. disallowedUserComments];

  // Catégories considérées comme dangereuses pour la modération de contenu
  string[] unsafeCategories =
  [
      "Child Exploitation",
      "Conspiracy Theories",
      "Hate",
      "Indiscriminate Weapons",
      "Intellectual Property",
      "Non-Violent Crimes",
      "Privacy",
      "Self-Harm",
      "Sex Crimes",
      "Sexual Content",
      "Specialized Advice",
      "Violent Crimes",
  ];
  ```

  ```go Go
  var client = anthropic.NewClient()

  var allowedUserComments = []string{
  	"This movie was great, I really enjoyed it. The main actor really killed it!",
  	"I hate Mondays.",
  	"It is a great time to invest in gold!",
  }

  var disallowedUserComments = []string{
  	"Delete this post now or you better hide. I am coming after you and your family.",
  	"Stay away from the 5G cellphones!! They are using 5G to control you.",
  	"Congratulations! You have won a $1,000 gift card. Click here to claim your prize!",
  }

  // Exemples de commentaires d'utilisateurs pour tester la modération de contenu
  var userComments = slices.Concat(allowedUserComments, disallowedUserComments)

  // Catégories considérées comme dangereuses pour la modération de contenu
  var unsafeCategories = []string{
  	"Child Exploitation",
  	"Conspiracy Theories",
  	"Hate",
  	"Indiscriminate Weapons",
  	"Intellectual Property",
  	"Non-Violent Crimes",
  	"Privacy",
  	"Self-Harm",
  	"Sex Crimes",
  	"Sexual Content",
  	"Specialized Advice",
  	"Violent Crimes",
  }
  ```

  ```java Java
  final AnthropicClient client = AnthropicOkHttpClient.fromEnv();

  final List<String> allowedUserComments = List.of(
          "This movie was great, I really enjoyed it. The main actor really killed it!",
          "I hate Mondays.",
          "It is a great time to invest in gold!");

  final List<String> disallowedUserComments = List.of(
          "Delete this post now or you better hide. I am coming after you and your family.",
          "Stay away from the 5G cellphones!! They are using 5G to control you.",
          "Congratulations! You have won a $1,000 gift card. Click here to claim your prize!");

  // Exemples de commentaires d'utilisateurs pour tester la modération de contenu
  final List<String> userComments =
          Stream.concat(allowedUserComments.stream(), disallowedUserComments.stream()).toList();

  // Catégories considérées comme dangereuses pour la modération de contenu
  final List<String> unsafeCategories = List.of(
          "Child Exploitation",
          "Conspiracy Theories",
          "Hate",
          "Indiscriminate Weapons",
          "Intellectual Property",
          "Non-Violent Crimes",
          "Privacy",
          "Self-Harm",
          "Sex Crimes",
          "Sexual Content",
          "Specialized Advice",
          "Violent Crimes");
  ```

  ```php PHP
  $client = new Client();

  $allowedUserComments = [
      'This movie was great, I really enjoyed it. The main actor really killed it!',
      'I hate Mondays.',
      'It is a great time to invest in gold!',
  ];

  $disallowedUserComments = [
      'Delete this post now or you better hide. I am coming after you and your family.',
      'Stay away from the 5G cellphones!! They are using 5G to control you.',
      'Congratulations! You have won a $1,000 gift card. Click here to claim your prize!',
  ];

  // Exemples de commentaires d'utilisateurs pour tester la modération de contenu
  $userComments = [...$allowedUserComments, ...$disallowedUserComments];

  // Catégories considérées comme dangereuses pour la modération de contenu
  $unsafeCategories = [
      'Child Exploitation',
      'Conspiracy Theories',
      'Hate',
      'Indiscriminate Weapons',
      'Intellectual Property',
      'Non-Violent Crimes',
      'Privacy',
      'Self-Harm',
      'Sex Crimes',
      'Sexual Content',
      'Specialized Advice',
      'Violent Crimes',
  ];
  ```

  ```ruby Ruby
  CLIENT = Anthropic::Client.new

  ALLOWED_USER_COMMENTS = [
    "This movie was great, I really enjoyed it. The main actor really killed it!",
    "I hate Mondays.",
    "It is a great time to invest in gold!"
  ]

  DISALLOWED_USER_COMMENTS = [
    "Delete this post now or you better hide. I am coming after you and your family.",
    "Stay away from the 5G cellphones!! They are using 5G to control you.",
    "Congratulations! You have won a $1,000 gift card. Click here to claim your prize!"
  ]

  # Exemples de commentaires d'utilisateurs pour tester la modération de contenu
  USER_COMMENTS = ALLOWED_USER_COMMENTS + DISALLOWED_USER_COMMENTS

  # Catégories considérées comme dangereuses pour la modération de contenu
  UNSAFE_CATEGORIES = [
    "Child Exploitation",
    "Conspiracy Theories",
    "Hate",
    "Indiscriminate Weapons",
    "Intellectual Property",
    "Non-Violent Crimes",
    "Privacy",
    "Self-Harm",
    "Sex Crimes",
    "Sexual Content",
    "Specialized Advice",
    "Violent Crimes"
  ]
  ```
</CodeGroup>

Modérer efficacement ces exemples nécessite une compréhension nuancée du langage. Dans le commentaire `This movie was great, I really enjoyed it. The main actor really killed it!`, le système de modération de contenu doit reconnaître que « killed it » est une métaphore, et non l'indication d'une violence réelle. À l'inverse, malgré l'absence de mentions explicites de violence, le commentaire `Delete this post now or you better hide. I am coming after you and your family.` devrait être signalé par le système de modération de contenu.

Les catégories non sûres peuvent être personnalisées pour répondre à vos besoins spécifiques. Par exemple, si vous souhaitez empêcher les mineurs de créer du contenu sur votre site web, vous pourriez ajouter « Underage Posting » aux catégories.

***

## Comment modérer du contenu avec Claude

### Sélectionner le bon modèle Claude

Lors de la sélection d'un modèle, il est important de tenir compte de la taille de vos données. Si les coûts sont une préoccupation, un modèle plus petit tel que Claude Haiku 5.5 est un excellent choix en raison de son rapport coût-efficacité. Voici une estimation du coût de la modération de texte pour une plateforme de réseau social qui reçoit un milliard de publications par mois :

* **Taille du contenu**

  * Publications par mois : 1 Md
  * Caractères par publication : 100
  * Total de caractères : 100 Md

* **Tokens estimés**

  * Tokens d'entrée : 28,6 Md (en supposant 1 token pour 3,5 caractères)
  * Pourcentage de messages signalés : 3 %
  * Tokens de sortie par message signalé : 50
  * Total de tokens de sortie : 1,5 Md

* **Coût estimé avec Claude Haiku 5.5**

  * Coût des tokens d'entrée : 28 600 MTok \* 0,10 $ / MTok = 2 860 $ USD
  * Coût des tokens de sortie : 1 500 MTok \* 0,50 $ / MTok = 750 $ USD
  * Coût mensuel : 2 860 $ + 750 $ = 3 610 $ USD

* **Coût estimé avec Claude Opus 5**

  * Coût des tokens d'entrée : 28 600 MTok \* 5,00 $ / MTok = 143 000 $ USD
  * Coût des tokens de sortie : 1 500 MTok \* 25,00 $ / MTok = 37 500 $ USD
  * Coût mensuel : 143 000 $ + 37 500 $ = 180 500 $ USD

* **Coût estimé avec Claude Opus 4.8**

  * Coût des tokens d'entrée : 28 600 MTok \* 5,00 $ / MTok = 143 000 $ USD
  * Coût des tokens de sortie : 1 500 MTok \* 25,00 $ / MTok = 37 500 $ USD
  * Coût mensuel : 143 000 $ + 37 500 $ = 180 500 $ USD

<Tip>
  Les coûts réels peuvent différer de ces estimations. Ces estimations sont basées sur le prompt présenté dans la section sur le 

  [traitement par lots](https://platform.claude.com/docs/fr/about-claude/use-case-guides/content-moderation#consider-batch-processing)

  . Les tokens de sortie peuvent être réduits davantage en supprimant le champ 

  `explanation`

   de la réponse.
</Tip>

### Construire un prompt solide

Pour utiliser Claude pour la modération de contenu, Claude doit comprendre les exigences de modération de votre application. Commencez par rédiger un prompt qui vous permet de définir vos besoins en matière de modération :

<CodeGroup exclude="shell">
  ```python Python
  def moderate_message(message, unsafe_categories):
      # Convertir les catégories dangereuses en chaîne, avec chaque catégorie sur une nouvelle ligne
      unsafe_category_str = "\n".join(unsafe_categories)

      # Construire le prompt pour Claude, incluant le message et les catégories dangereuses
      assessment_prompt = f"""
      Determine whether the following message warrants moderation,
      based on the unsafe categories outlined below.

      Message:
      <message>{message}</message>

      Unsafe Categories:
      <categories>
      {unsafe_category_str}
      </categories>

      Respond with ONLY a JSON object, using the format below:
      {{
      "violation": <Boolean field denoting whether the message should be moderated>,
      "categories": [Comma-separated list of violated categories],
      "explanation": [Optional. Only include if there is a violation.]
      }}
  Do not include markdown formatting or code fences in your response."""

      # Envoyer la requête à Claude pour la modération de contenu
      response = client.messages.create(
          model="claude-haiku-4-5-20251001",  # Using the Haiku model for lower costs
          max_tokens=200,
          messages=[{"role": "user", "content": assessment_prompt}],
      )

      # Analyser la réponse JSON de Claude
      text_block = next(block for block in response.content if block.type == "text")
      assessment = json.loads(text_block.text)

      # Extraire le statut de violation de l'évaluation
      contains_violation = assessment["violation"]

      # S'il y a une violation, récupérer les catégories et l'explication ; sinon, utiliser des valeurs vides par défaut
      violated_categories = assessment.get("categories", []) if contains_violation else []
      explanation = assessment.get("explanation") if contains_violation else None

      return contains_violation, violated_categories, explanation


  # Traiter chaque commentaire et afficher les résultats
  for comment in user_comments:
      print(f"\nComment: {comment}")
      violation, violated_categories, explanation = moderate_message(
          comment, unsafe_categories
      )

      if violation:
          print(f"Violated Categories: {', '.join(violated_categories)}")
          print(f"Explanation: {explanation}")
      else:
          print("No issues detected.")
  ```

  ```typescript TypeScript
  // Structure de l'évaluation JSON renvoyée par Claude
  interface ModerationAssessment {
    violation: boolean;
    categories?: string[];
    explanation?: string;
  }

  async function moderateMessage(
    message: string,
    unsafeCategories: string[]
  ): Promise<{ violation: boolean; violatedCategories: string[]; explanation?: string }> {
    // Convertir les catégories dangereuses en chaîne, avec chaque catégorie sur une nouvelle ligne
    const unsafeCategoryStr = unsafeCategories.join("\n");

    // Construire le prompt pour Claude, incluant le message et les catégories dangereuses
    const assessmentPrompt = `
      Determine whether the following message warrants moderation,
      based on the unsafe categories outlined below.

      Message:
      <message>${message}</message>

      Unsafe Categories:
      <categories>
      ${unsafeCategoryStr}
      </categories>

      Respond with ONLY a JSON object, using the format below:
      {
      "violation": <Boolean field denoting whether the message should be moderated>,
      "categories": [Comma-separated list of violated categories],
      "explanation": [Optional. Only include if there is a violation.]
      }
  Do not include markdown formatting or code fences in your response.`;

    // Envoyer la requête à Claude pour la modération de contenu
    const response = await client.messages.create({
      model: "claude-haiku-4-5-20251001", // Using the Haiku model for lower costs
      max_tokens: 200,
      messages: [{ role: "user", content: assessmentPrompt }]
    });

    // Analyser la réponse JSON de Claude
    const textBlock = response.content.find((block) => block.type === "text");
    if (!textBlock) {
      throw new Error("Expected a text block in the response");
    }
    const assessment: ModerationAssessment = JSON.parse(textBlock.text);

    // Extraire le statut de violation de l'évaluation
    const containsViolation = assessment.violation;

    // S'il y a une violation, récupérer les catégories et l'explication ; sinon, utiliser des valeurs vides par défaut
    const violatedCategories = containsViolation ? (assessment.categories ?? []) : [];
    const explanation = containsViolation ? assessment.explanation : undefined;

    return { violation: containsViolation, violatedCategories, explanation };
  }

  // Traiter chaque commentaire et afficher les résultats
  for (const comment of userComments) {
    console.log(`\nComment: ${comment}`);
    const { violation, violatedCategories, explanation } = await moderateMessage(
      comment,
      unsafeCategories
    );

    if (violation) {
      console.log(`Violated Categories: ${violatedCategories.join(", ")}`);
      console.log(`Explanation: ${explanation}`);
    } else {
      console.log("No issues detected.");
    }
  }
  ```

  ```csharp C#
  async Task<(bool ContainsViolation, List<string> ViolatedCategories, string? Explanation)> ModerateMessage(
      string message,
      IReadOnlyList<string> categories
  )
  {
      // Convertir les catégories dangereuses en chaîne, avec chaque catégorie sur une nouvelle ligne
      var unsafeCategoryText = string.Join("\n", categories);

      // Construire le prompt pour Claude, incluant le message et les catégories dangereuses
      var assessmentPrompt = $$"""

      Determine whether the following message warrants moderation,
      based on the unsafe categories outlined below.

      Message:
      <message>{{message}}</message>

      Unsafe Categories:
      <categories>
      {{unsafeCategoryText}}
      </categories>

      Respond with ONLY a JSON object, using the format below:
      {
      "violation": <Boolean field denoting whether the message should be moderated>,
      "categories": [Comma-separated list of violated categories],
      "explanation": [Optional. Only include if there is a violation.]
      }
  Do not include markdown formatting or code fences in your response.
  """;

      // Envoyer la requête à Claude pour la modération de contenu
      var response = await client.Messages.Create(
          new()
          {
              Model = Model.ClaudeHaiku4_5_20251001, // Using the Haiku model for lower costs
              MaxTokens = 200,
              Messages = [new() { Role = Role.User, Content = assessmentPrompt }],
          }
      );

      // Restreindre le premier bloc de contenu à un bloc de texte, puis analyser la réponse JSON de Claude
      if (!response.Content[0].TryPickText(out var textBlock))
      {
          throw new InvalidOperationException("Expected a text response from Claude.");
      }
      var assessment = JsonNode.Parse(textBlock.Text)!;

      // Extraire le statut de violation de l'évaluation
      var containsViolation = assessment["violation"]!.GetValue<bool>();

      // S'il y a une violation, obtenir les catégories et l'explication ; sinon, utiliser des valeurs par défaut vides
      List<string> violatedCategories = containsViolation
          ? assessment["categories"]?.AsArray().Select(category => category!.GetValue<string>()).ToList() ?? []
          : [];
      var explanation = containsViolation ? assessment["explanation"]?.GetValue<string>() : null;

      return (containsViolation, violatedCategories, explanation);
  }

  // Traiter chaque commentaire et afficher les résultats
  foreach (var comment in userComments)
  {
      Console.WriteLine($"\nComment: {comment}");
      var (violation, violatedCategories, explanation) = await ModerateMessage(comment, unsafeCategories);

      if (violation)
      {
          Console.WriteLine($"Violated Categories: {string.Join(", ", violatedCategories)}");
          Console.WriteLine($"Explanation: {explanation}");
      }
      else
      {
          Console.WriteLine("No issues detected.");
      }
  }
  ```

  ```go Go
  func moderateMessage(message string, unsafeCategories []string) (bool, []string, string) {
  	// Convertir les catégories dangereuses en une chaîne, avec chaque catégorie sur une nouvelle ligne
  	unsafeCategoryStr := strings.Join(unsafeCategories, "\n")

  	// Construire le prompt pour Claude, incluant le message et les catégories dangereuses
  	assessmentPrompt := fmt.Sprintf(`
      Determine whether the following message warrants moderation,
      based on the unsafe categories outlined below.

      Message:
      <message>%s</message>

      Unsafe Categories:
      <categories>
      %s
      </categories>

      Respond with ONLY a JSON object, using the format below:
      {
      "violation": <Boolean field denoting whether the message should be moderated>,
      "categories": [Comma-separated list of violated categories],
      "explanation": [Optional. Only include if there is a violation.]
      }
  Do not include markdown formatting or code fences in your response.`, message, unsafeCategoryStr)

  	// Envoyer la requête à Claude pour la modération de contenu
  	response, err := client.Messages.New(context.Background(), anthropic.MessageNewParams{
  		Model:     anthropic.ModelClaudeHaiku4_5_20251001, // Using the Haiku model for lower costs
  		MaxTokens: 200,
  		Messages: []anthropic.MessageParam{
  			anthropic.NewUserMessage(anthropic.NewTextBlock(assessmentPrompt)),
  		},
  	})
  	if err != nil {
  		log.Fatal(err)
  	}

  	// Restreindre le premier bloc de contenu à un bloc de texte avant de lire son texte
  	textBlock, ok := response.Content[0].AsAny().(anthropic.TextBlock)
  	if !ok {
  		log.Fatalf("expected a text block, got %q", response.Content[0].Type)
  	}

  	// Analyser la réponse JSON de Claude
  	var assessment struct {
  		Violation   bool     `json:"violation"`
  		Categories  []string `json:"categories"`
  		Explanation string   `json:"explanation"`
  	}
  	if err := json.Unmarshal([]byte(textBlock.Text), &assessment); err != nil {
  		log.Fatal(err)
  	}

  	// S'il y a une violation, retourner les catégories et l'explication ; sinon, utiliser des valeurs par défaut vides
  	if !assessment.Violation {
  		return false, nil, ""
  	}
  	return true, assessment.Categories, assessment.Explanation
  }

  // moderateAllComments traite chaque commentaire et affiche les résultats.
  func moderateAllComments() {
  	for _, comment := range userComments {
  		fmt.Printf("\nComment: %s\n", comment)
  		violation, violatedCategories, explanation := moderateMessage(comment, unsafeCategories)

  		if violation {
  			fmt.Printf("Violated Categories: %s\n", strings.Join(violatedCategories, ", "))
  			fmt.Printf("Explanation: %s\n", explanation)
  		} else {
  			fmt.Println("No issues detected.")
  		}
  	}
  }
  ```

  ```java Java
  record ModerationResult(boolean violation, List<String> violatedCategories, String explanation) {}

  ModerationResult moderateMessage(String message, List<String> unsafeCategories)
          throws JsonProcessingException {
      // Convertir les catégories dangereuses en chaîne, avec chaque catégorie sur une nouvelle ligne
      String unsafeCategoryStr = String.join("\n", unsafeCategories);

      // Construire le prompt pour Claude, incluant le message et les catégories dangereuses
      String assessmentPrompt = """

              Determine whether the following message warrants moderation,
              based on the unsafe categories outlined below.

              Message:
              <message>%s</message>

              Unsafe Categories:
              <categories>
              %s
              </categories>

              Respond with ONLY a JSON object, using the format below:
              {
              "violation": <Boolean field denoting whether the message should be moderated>,
              "categories": [Comma-separated list of violated categories],
              "explanation": [Optional. Only include if there is a violation.]
              }
          Do not include markdown formatting or code fences in your response."""
              .formatted(message, unsafeCategoryStr);

      // Envoyer la requête à Claude pour la modération de contenu
      Message response = client.messages().create(MessageCreateParams.builder()
              .model(Model.CLAUDE_HAIKU_4_5_20251001) // Using the Haiku model for lower costs
              .maxTokens(200)
              .addUserMessage(assessmentPrompt)
              .build());

      // Analyser la réponse JSON de Claude
      String assessmentJson = response.content().stream()
              .flatMap(contentBlock -> contentBlock.text().stream())
              .findFirst()
              .orElseThrow()
              .text();
      ObjectMapper mapper = new ObjectMapper();
      JsonNode assessment = mapper.readTree(assessmentJson);

      // Extraire le statut de violation de l'évaluation
      boolean containsViolation = assessment.required("violation").asBoolean();

      // S'il y a une violation, obtenir les catégories et l'explication ; sinon, utiliser des valeurs par défaut vides
      List<String> violatedCategories = containsViolation && assessment.has("categories")
              ? mapper.convertValue(assessment.get("categories"), new TypeReference<List<String>>() {})
              : List.of();
      String explanation = containsViolation && assessment.hasNonNull("explanation")
              ? assessment.get("explanation").asText()
              : null;

      return new ModerationResult(containsViolation, violatedCategories, explanation);
  }

  // Traiter chaque commentaire et afficher les résultats
  void printModerationResults() throws JsonProcessingException {
      for (String comment : userComments) {
          IO.println("\nComment: " + comment);
          ModerationResult result = moderateMessage(comment, unsafeCategories);

          if (result.violation()) {
              IO.println("Violated Categories: " + String.join(", ", result.violatedCategories()));
              IO.println("Explanation: " + result.explanation());
          } else {
              IO.println("No issues detected.");
          }
      }
  }
  ```

  ```php PHP
  $moderateMessage = function (string $message, array $unsafeCategories) use ($client): array {
      // Convertir les catégories dangereuses en chaîne, avec chaque catégorie sur une nouvelle ligne
      $unsafeCategoryStr = implode("\n", $unsafeCategories);

      // Construire le prompt pour Claude, incluant le message et les catégories dangereuses
      $assessmentPrompt = <<<PROMPT

          Determine whether the following message warrants moderation,
          based on the unsafe categories outlined below.

          Message:
          <message>{$message}</message>

          Unsafe Categories:
          <categories>
          {$unsafeCategoryStr}
          </categories>

          Respond with ONLY a JSON object, using the format below:
          {
          "violation": <Boolean field denoting whether the message should be moderated>,
          "categories": [Comma-separated list of violated categories],
          "explanation": [Optional. Only include if there is a violation.]
          }
      Do not include markdown formatting or code fences in your response.
      PROMPT;

      // Envoyer la requête à Claude pour la modération de contenu
      $response = $client->messages->create(
          model: 'claude-haiku-4-5-20251001', // Using the Haiku model for lower costs
          maxTokens: 200,
          messages: [['role' => 'user', 'content' => $assessmentPrompt]],
      );

      // Analyser la réponse JSON de Claude. Le SDK décode chaque bloc de contenu
      // dans sa classe concrète, donc trouver le TextBlock avant de lire le texte.
      $textBlock = array_find($response->content, fn ($block) => $block instanceof \Anthropic\Messages\TextBlock)
          ?? throw new \RuntimeException('Expected a text block in the response.');
      $assessment = json_decode($textBlock->text, associative: true, flags: JSON_THROW_ON_ERROR);

      // Extraire le statut de violation de l'évaluation
      $containsViolation = $assessment['violation'];

      // S'il y a une violation, récupérer les catégories et l'explication ; sinon, utiliser des valeurs vides par défaut
      $violatedCategories = $containsViolation ? ($assessment['categories'] ?? []) : [];
      $explanation = $containsViolation ? ($assessment['explanation'] ?? null) : null;

      return [$containsViolation, $violatedCategories, $explanation];
  };

  // Traiter chaque commentaire et afficher les résultats
  foreach ($userComments as $comment) {
      echo "\nComment: {$comment}\n";
      [$violation, $violatedCategories, $explanation] = $moderateMessage($comment, $unsafeCategories);

      if ($violation) {
          echo 'Violated Categories: ' . implode(', ', $violatedCategories) . "\n";
          echo "Explanation: {$explanation}\n";
      } else {
          echo "No issues detected.\n";
      }
  }
  ```

  ```ruby Ruby
  def moderate_message(message, unsafe_categories)
    # Convertir les catégories dangereuses en chaîne, avec chaque catégorie sur une nouvelle ligne
    unsafe_category_str = unsafe_categories.join("\n")

    # Construire le prompt pour Claude, incluant le message et les catégories dangereuses
    assessment_prompt = <<~PROMPT.chomp

          Determine whether the following message warrants moderation,
          based on the unsafe categories outlined below.

          Message:
          <message>#{message}</message>

          Unsafe Categories:
          <categories>
          #{unsafe_category_str}
          </categories>

          Respond with ONLY a JSON object, using the format below:
          {
          "violation": <Boolean field denoting whether the message should be moderated>,
          "categories": [Comma-separated list of violated categories],
          "explanation": [Optional. Only include if there is a violation.]
          }
      Do not include markdown formatting or code fences in your response.
    PROMPT

    # Envoyer la requête à Claude pour la modération de contenu
    response = CLIENT.messages.create(
      model: "claude-haiku-4-5-20251001", # Using the Haiku model for lower costs
      max_tokens: 200,
      messages: [{role: :user, content: assessment_prompt}]
    )

    # Analyser la réponse JSON de Claude
    text_block = response.content.find { it.type == :text }
    assessment = JSON.parse(text_block.text)

    # Extraire le statut de violation de l'évaluation
    contains_violation = assessment["violation"]

    # S'il y a une violation, récupérer les catégories et l'explication ; sinon, utiliser des valeurs par défaut vides
    violated_categories = contains_violation ? assessment.fetch("categories", []) : []
    explanation = contains_violation ? assessment["explanation"] : nil

    [contains_violation, violated_categories, explanation]
  end


  # Traiter chaque commentaire et afficher les résultats
  USER_COMMENTS.each do |comment|
    puts "\nComment: #{comment}"
    violation, violated_categories, explanation = moderate_message(comment, UNSAFE_CATEGORIES)

    if violation
      puts "Violated Categories: #{violated_categories.join(", ")}"
      puts "Explanation: #{explanation}"
    else
      puts "No issues detected."
    end
  end
  ```
</CodeGroup>

Dans cet exemple, la fonction `moderate_message` contient un prompt d'évaluation qui inclut les catégories de contenu non sûr et le message à évaluer. Le prompt demande à Claude d'évaluer si le message doit être modéré, en fonction des catégories non sûres que vous avez définies précédemment.

L'évaluation du modèle est ensuite analysée pour déterminer s'il y a une violation. En cas de violation, Claude renvoie également une liste des catégories enfreintes ainsi qu'une explication des raisons pour lesquelles le message n'est pas sûr.

### Évaluer votre prompt

La modération de contenu est un problème de classification. Vous pouvez donc utiliser les mêmes techniques décrites dans le [cookbook de classification](https://platform.claude.com/cookbook/capabilities-classification-guide) pour déterminer la précision de votre système de modération de contenu.

Une considération supplémentaire est qu'au lieu de traiter la modération de contenu comme un problème de classification binaire, vous pouvez créer plusieurs catégories pour représenter différents niveaux de risque. La création de plusieurs niveaux de risque vous permet d'ajuster l'agressivité de votre modération. Par exemple, vous pourriez vouloir bloquer automatiquement les requêtes d'utilisateurs jugées à haut risque, tandis que les utilisateurs ayant de nombreuses requêtes à risque moyen sont signalés pour un examen humain.

<CodeGroup exclude="shell">
  ```python Python
  def assess_risk_level(message, unsafe_categories):
      # Convertir les catégories dangereuses en chaîne, avec chaque catégorie sur une nouvelle ligne
      unsafe_category_str = "\n".join(unsafe_categories)

      # Construire le prompt pour Claude, incluant le message, les catégories dangereuses et les définitions des niveaux de risque
      assessment_prompt = f"""
      Assess the risk level of the following message,
      based on the unsafe categories listed below.

  Message:
  <message>{message}</message>

  Unsafe Categories:
  <categories>
  {unsafe_category_str}
  </categories>

  Assign a risk level based on your confidence that the user's message should be moderated
  based on the defined unsafe categories:

  0 - No risk
  1 - Low risk
  2 - Medium risk
  3 - High risk

  Respond with ONLY a JSON object, using the format below:
  {{
    "risk_level": <Numerical field denoting the risk level>,
    "categories": [Comma-separated list of violated categories],
    "explanation": <Optional. Only include if risk level is greater than 0>
  }}
  Do not include markdown formatting or code fences in your response."""

      # Envoyer la requête à Claude pour l'évaluation du risque
      response = client.messages.create(
          model="claude-haiku-4-5-20251001",  # Using the Haiku model for lower costs
          max_tokens=200,
          messages=[{"role": "user", "content": assessment_prompt}],
      )

      # Analyser la réponse JSON de Claude
      text_block = next(block for block in response.content if block.type == "text")
      assessment = json.loads(text_block.text)

      # Extraire le niveau de risque, les catégories violées et l'explication de l'évaluation
      risk_level = assessment["risk_level"]
      violated_categories = assessment["categories"]
      explanation = assessment.get("explanation")

      return risk_level, violated_categories, explanation


  # Traiter chaque commentaire et afficher les résultats
  for comment in user_comments:
      print(f"\nComment: {comment}")
      risk_level, violated_categories, explanation = assess_risk_level(
          comment, unsafe_categories
      )

      print(f"Risk Level: {risk_level}")
      if violated_categories:
          print(f"Violated Categories: {', '.join(violated_categories)}")
      if explanation:
          print(f"Explanation: {explanation}")
  ```

  ```typescript TypeScript
  // Structure de l'évaluation de risque JSON renvoyée par Claude
  interface RiskAssessment {
    risk_level: number;
    categories: string[];
    explanation?: string;
  }

  async function assessRiskLevel(
    message: string,
    unsafeCategories: string[]
  ): Promise<{ riskLevel: number; violatedCategories: string[]; explanation?: string }> {
    // Convertir les catégories dangereuses en chaîne, avec chaque catégorie sur une nouvelle ligne
    const unsafeCategoryStr = unsafeCategories.join("\n");

    // Construire le prompt pour Claude, incluant le message, les catégories dangereuses et les définitions des niveaux de risque
    const assessmentPrompt = `
      Assess the risk level of the following message,
      based on the unsafe categories listed below.

  Message:
  <message>${message}</message>

  Unsafe Categories:
  <categories>
  ${unsafeCategoryStr}
  </categories>

  Assign a risk level based on your confidence that the user's message should be moderated
  based on the defined unsafe categories:

  0 - No risk
  1 - Low risk
  2 - Medium risk
  3 - High risk

  Respond with ONLY a JSON object, using the format below:
  {
    "risk_level": <Numerical field denoting the risk level>,
    "categories": [Comma-separated list of violated categories],
    "explanation": <Optional. Only include if risk level is greater than 0>
  }
  Do not include markdown formatting or code fences in your response.`;

    // Envoyer la requête à Claude pour l'évaluation du risque
    const response = await client.messages.create({
      model: "claude-haiku-4-5-20251001", // Using the Haiku model for lower costs
      max_tokens: 200,
      messages: [{ role: "user", content: assessmentPrompt }]
    });

    // Analyser la réponse JSON de Claude
    const textBlock = response.content.find((block) => block.type === "text");
    if (!textBlock) {
      throw new Error("Expected a text block in the response");
    }
    const assessment: RiskAssessment = JSON.parse(textBlock.text);

    // Extraire le niveau de risque, les catégories violées et l'explication de l'évaluation
    const { risk_level: riskLevel, categories: violatedCategories, explanation } = assessment;

    return { riskLevel, violatedCategories, explanation };
  }

  // Traiter chaque commentaire et afficher les résultats
  for (const comment of userComments) {
    console.log(`\nComment: ${comment}`);
    const { riskLevel, violatedCategories, explanation } = await assessRiskLevel(
      comment,
      unsafeCategories
    );

    console.log(`Risk Level: ${riskLevel}`);
    if (violatedCategories.length > 0) {
      console.log(`Violated Categories: ${violatedCategories.join(", ")}`);
    }
    if (explanation) {
      console.log(`Explanation: ${explanation}`);
    }
  }
  ```

  ```csharp C#
  async Task<(int RiskLevel, List<string> ViolatedCategories, string? Explanation)> AssessRiskLevel(
      string message,
      IReadOnlyList<string> categories
  )
  {
      // Convertir les catégories dangereuses en chaîne, avec chaque catégorie sur une nouvelle ligne
      var unsafeCategoryText = string.Join("\n", categories);

      // Construire le prompt pour Claude, incluant le message, les catégories dangereuses et les définitions des niveaux de risque
      var assessmentPrompt = $$"""

      Assess the risk level of the following message,
      based on the unsafe categories listed below.

  Message:
  <message>{{message}}</message>

  Unsafe Categories:
  <categories>
  {{unsafeCategoryText}}
  </categories>

  Assign a risk level based on your confidence that the user's message should be moderated
  based on the defined unsafe categories:

  0 - No risk
  1 - Low risk
  2 - Medium risk
  3 - High risk

  Respond with ONLY a JSON object, using the format below:
  {
    "risk_level": <Numerical field denoting the risk level>,
    "categories": [Comma-separated list of violated categories],
    "explanation": <Optional. Only include if risk level is greater than 0>
  }
  Do not include markdown formatting or code fences in your response.
  """;

      // Envoyer la requête à Claude pour l'évaluation des risques
      var response = await client.Messages.Create(
          new()
          {
              Model = Model.ClaudeHaiku4_5_20251001, // Using the Haiku model for lower costs
              MaxTokens = 200,
              Messages = [new() { Role = Role.User, Content = assessmentPrompt }],
          }
      );

      // Restreindre le premier bloc de contenu à un bloc de texte, puis analyser la réponse JSON de Claude
      if (!response.Content[0].TryPickText(out var textBlock))
      {
          throw new InvalidOperationException("Expected a text response from Claude.");
      }
      var assessment = JsonNode.Parse(textBlock.Text)!;

      // Extraire le niveau de risque, les catégories violées et l'explication de l'évaluation
      var riskLevel = assessment["risk_level"]!.GetValue<int>();
      var violatedCategories = assessment["categories"]!
          .AsArray()
          .Select(category => category!.GetValue<string>())
          .ToList();
      var explanation = assessment["explanation"]?.GetValue<string>();

      return (riskLevel, violatedCategories, explanation);
  }

  // Traiter chaque commentaire et afficher les résultats
  foreach (var comment in userComments)
  {
      Console.WriteLine($"\nComment: {comment}");
      var (riskLevel, violatedCategories, explanation) = await AssessRiskLevel(comment, unsafeCategories);

      Console.WriteLine($"Risk Level: {riskLevel}");
      if (violatedCategories.Count > 0)
      {
          Console.WriteLine($"Violated Categories: {string.Join(", ", violatedCategories)}");
      }
      if (!string.IsNullOrEmpty(explanation))
      {
          Console.WriteLine($"Explanation: {explanation}");
      }
  }
  ```

  ```go Go
  func assessRiskLevel(message string, unsafeCategories []string) (int, []string, string) {
  	// Convertir les catégories dangereuses en une chaîne, avec chaque catégorie sur une nouvelle ligne
  	unsafeCategoryStr := strings.Join(unsafeCategories, "\n")

  	// Construire le prompt pour Claude, incluant le message, les catégories dangereuses et les définitions des niveaux de risque
  	assessmentPrompt := fmt.Sprintf(`
      Assess the risk level of the following message,
      based on the unsafe categories listed below.

  Message:
  <message>%s</message>

  Unsafe Categories:
  <categories>
  %s
  </categories>

  Assign a risk level based on your confidence that the user's message should be moderated
  based on the defined unsafe categories:

  0 - No risk
  1 - Low risk
  2 - Medium risk
  3 - High risk

  Respond with ONLY a JSON object, using the format below:
  {
    "risk_level": <Numerical field denoting the risk level>,
    "categories": [Comma-separated list of violated categories],
    "explanation": <Optional. Only include if risk level is greater than 0>
  }
  Do not include markdown formatting or code fences in your response.`, message, unsafeCategoryStr)

  	// Envoyer la requête à Claude pour l'évaluation du risque
  	response, err := client.Messages.New(context.Background(), anthropic.MessageNewParams{
  		Model:     anthropic.ModelClaudeHaiku4_5_20251001, // Using the Haiku model for lower costs
  		MaxTokens: 200,
  		Messages: []anthropic.MessageParam{
  			anthropic.NewUserMessage(anthropic.NewTextBlock(assessmentPrompt)),
  		},
  	})
  	if err != nil {
  		log.Fatal(err)
  	}

  	// Restreindre le premier bloc de contenu à un bloc de texte avant de lire son texte
  	textBlock, ok := response.Content[0].AsAny().(anthropic.TextBlock)
  	if !ok {
  		log.Fatalf("expected a text block, got %q", response.Content[0].Type)
  	}

  	// Analyser la réponse JSON de Claude
  	var assessment struct {
  		RiskLevel   int      `json:"risk_level"`
  		Categories  []string `json:"categories"`
  		Explanation string   `json:"explanation"`
  	}
  	if err := json.Unmarshal([]byte(textBlock.Text), &assessment); err != nil {
  		log.Fatal(err)
  	}

  	// Retourner le niveau de risque, les catégories violées et l'explication issus de l'évaluation
  	return assessment.RiskLevel, assessment.Categories, assessment.Explanation
  }

  // assessAllRiskLevels traite chaque commentaire et affiche les résultats.
  func assessAllRiskLevels() {
  	for _, comment := range userComments {
  		fmt.Printf("\nComment: %s\n", comment)
  		riskLevel, violatedCategories, explanation := assessRiskLevel(comment, unsafeCategories)

  		fmt.Printf("Risk Level: %d\n", riskLevel)
  		if len(violatedCategories) > 0 {
  			fmt.Printf("Violated Categories: %s\n", strings.Join(violatedCategories, ", "))
  		}
  		if explanation != "" {
  			fmt.Printf("Explanation: %s\n", explanation)
  		}
  	}
  }
  ```

  ```java Java
  record RiskAssessment(int riskLevel, List<String> violatedCategories, String explanation) {}

  RiskAssessment assessRiskLevel(String message, List<String> unsafeCategories)
          throws JsonProcessingException {
      // Convertir les catégories dangereuses en chaîne, avec chaque catégorie sur une nouvelle ligne
      String unsafeCategoryStr = String.join("\n", unsafeCategories);

      // Construire le prompt pour Claude, incluant le message, les catégories dangereuses et les définitions des niveaux de risque
      String assessmentPrompt = """

              Assess the risk level of the following message,
              based on the unsafe categories listed below.

          Message:
          <message>%s</message>

          Unsafe Categories:
          <categories>
          %s
          </categories>

          Assign a risk level based on your confidence that the user's message should be moderated
          based on the defined unsafe categories:

          0 - No risk
          1 - Low risk
          2 - Medium risk
          3 - High risk

          Respond with ONLY a JSON object, using the format below:
          {
            "risk_level": <Numerical field denoting the risk level>,
            "categories": [Comma-separated list of violated categories],
            "explanation": <Optional. Only include if risk level is greater than 0>
          }
          Do not include markdown formatting or code fences in your response."""
              .formatted(message, unsafeCategoryStr);

      // Envoyer la requête à Claude pour l'évaluation du risque
      Message response = client.messages().create(MessageCreateParams.builder()
              .model(Model.CLAUDE_HAIKU_4_5_20251001) // Using the Haiku model for lower costs
              .maxTokens(200)
              .addUserMessage(assessmentPrompt)
              .build());

      // Analyser la réponse JSON de Claude
      String assessmentJson = response.content().stream()
              .flatMap(contentBlock -> contentBlock.text().stream())
              .findFirst()
              .orElseThrow()
              .text();
      ObjectMapper mapper = new ObjectMapper();
      JsonNode assessment = mapper.readTree(assessmentJson);

      // Extraire le niveau de risque, les catégories violées et l'explication de l'évaluation
      int riskLevel = assessment.required("risk_level").asInt();
      JsonNode categoriesNode = assessment.required("categories");
      List<String> violatedCategories = categoriesNode.isNull()
              ? List.of()
              : mapper.convertValue(categoriesNode, new TypeReference<List<String>>() {});
      String explanation = assessment.hasNonNull("explanation")
              ? assessment.get("explanation").asText()
              : null;

      return new RiskAssessment(riskLevel, violatedCategories, explanation);
  }

  // Traiter chaque commentaire et afficher les résultats
  void printRiskLevels() throws JsonProcessingException {
      for (String comment : userComments) {
          IO.println("\nComment: " + comment);
          RiskAssessment assessment = assessRiskLevel(comment, unsafeCategories);

          IO.println("Risk Level: " + assessment.riskLevel());
          if (!assessment.violatedCategories().isEmpty()) {
              IO.println("Violated Categories: " + String.join(", ", assessment.violatedCategories()));
          }
          if (assessment.explanation() != null && !assessment.explanation().isEmpty()) {
              IO.println("Explanation: " + assessment.explanation());
          }
      }
  }
  ```

  ```php PHP
  $assessRiskLevel = function (string $message, array $unsafeCategories) use ($client): array {
      // Convertir les catégories dangereuses en chaîne, avec chaque catégorie sur une nouvelle ligne
      $unsafeCategoryStr = implode("\n", $unsafeCategories);

      // Construire le prompt pour Claude, incluant le message, les catégories dangereuses et les définitions des niveaux de risque
      $assessmentPrompt = <<<PROMPT

          Assess the risk level of the following message,
          based on the unsafe categories listed below.

      Message:
      <message>{$message}</message>

      Unsafe Categories:
      <categories>
      {$unsafeCategoryStr}
      </categories>

      Assign a risk level based on your confidence that the user's message should be moderated
      based on the defined unsafe categories:

      0 - No risk
      1 - Low risk
      2 - Medium risk
      3 - High risk

      Respond with ONLY a JSON object, using the format below:
      {
        "risk_level": <Numerical field denoting the risk level>,
        "categories": [Comma-separated list of violated categories],
        "explanation": <Optional. Only include if risk level is greater than 0>
      }
      Do not include markdown formatting or code fences in your response.
      PROMPT;

      // Envoyer la requête à Claude pour l'évaluation des risques
      $response = $client->messages->create(
          model: 'claude-haiku-4-5-20251001', // Using the Haiku model for lower costs
          maxTokens: 200,
          messages: [['role' => 'user', 'content' => $assessmentPrompt]],
      );

      // Analyser la réponse JSON de Claude. Le SDK décode chaque bloc de contenu
      // dans sa classe concrète, donc trouver le TextBlock avant de lire le texte.
      $textBlock = array_find($response->content, fn ($block) => $block instanceof \Anthropic\Messages\TextBlock)
          ?? throw new \RuntimeException('Expected a text block in the response.');
      $assessment = json_decode($textBlock->text, associative: true, flags: JSON_THROW_ON_ERROR);

      // Extraire le niveau de risque, les catégories violées et l'explication de l'évaluation
      $riskLevel = $assessment['risk_level'];
      $violatedCategories = $assessment['categories'];
      $explanation = $assessment['explanation'] ?? null;

      return [$riskLevel, $violatedCategories, $explanation];
  };

  // Traiter chaque commentaire et afficher les résultats
  foreach ($userComments as $comment) {
      echo "\nComment: {$comment}\n";
      [$riskLevel, $violatedCategories, $explanation] = $assessRiskLevel($comment, $unsafeCategories);

      echo "Risk Level: {$riskLevel}\n";
      if ($violatedCategories) {
          echo 'Violated Categories: ' . implode(', ', $violatedCategories) . "\n";
      }
      if ($explanation) {
          echo "Explanation: {$explanation}\n";
      }
  }
  ```

  ```ruby Ruby
  def assess_risk_level(message, unsafe_categories)
    # Convertir les catégories dangereuses en chaîne, avec chaque catégorie sur une nouvelle ligne
    unsafe_category_str = unsafe_categories.join("\n")

    # Construire le prompt pour Claude, incluant le message, les catégories dangereuses et les définitions des niveaux de risque
    assessment_prompt = <<~PROMPT.chomp

          Assess the risk level of the following message,
          based on the unsafe categories listed below.

      Message:
      <message>#{message}</message>

      Unsafe Categories:
      <categories>
      #{unsafe_category_str}
      </categories>

      Assign a risk level based on your confidence that the user's message should be moderated
      based on the defined unsafe categories:

      0 - No risk
      1 - Low risk
      2 - Medium risk
      3 - High risk

      Respond with ONLY a JSON object, using the format below:
      {
        "risk_level": <Numerical field denoting the risk level>,
        "categories": [Comma-separated list of violated categories],
        "explanation": <Optional. Only include if risk level is greater than 0>
      }
      Do not include markdown formatting or code fences in your response.
    PROMPT

    # Envoyer la requête à Claude pour l'évaluation du risque
    response = CLIENT.messages.create(
      model: "claude-haiku-4-5-20251001", # Using the Haiku model for lower costs
      max_tokens: 200,
      messages: [{role: :user, content: assessment_prompt}]
    )

    # Analyser la réponse JSON de Claude
    text_block = response.content.find { it.type == :text }
    assessment = JSON.parse(text_block.text)

    # Extraire le niveau de risque, les catégories violées et l'explication de l'évaluation
    risk_level = assessment["risk_level"]
    violated_categories = assessment["categories"]
    explanation = assessment["explanation"]

    [risk_level, violated_categories, explanation]
  end


  # Traiter chaque commentaire et afficher les résultats
  USER_COMMENTS.each do |comment|
    puts "\nComment: #{comment}"
    risk_level, violated_categories, explanation = assess_risk_level(comment, UNSAFE_CATEGORIES)

    puts "Risk Level: #{risk_level}"
    puts "Violated Categories: #{violated_categories.join(", ")}" if violated_categories&.any?
    puts "Explanation: #{explanation}" if explanation
  end
  ```
</CodeGroup>

Ce code implémente une fonction `assess_risk_level` qui utilise Claude pour évaluer le niveau de risque d'un message. La fonction accepte en entrée un message et les catégories non sûres.

Au sein de la fonction, un prompt est généré pour Claude, comprenant le message à évaluer, les catégories non sûres et des instructions spécifiques pour évaluer le niveau de risque. Le prompt demande à Claude de répondre avec un objet JSON qui inclut le niveau de risque, les catégories enfreintes et une explication facultative.

Cette approche permet une modération de contenu flexible en attribuant des niveaux de risque. Elle peut être intégrée de manière transparente dans un système plus vaste pour automatiser le filtrage de contenu ou signaler des commentaires pour un examen humain en fonction de leur niveau de risque évalué. Par exemple, lors de l'exécution de ce code, le commentaire `Delete this post now or you better hide. I am coming after you and your family.` est identifié comme à haut risque en raison de sa menace dangereuse. À l'inverse, le commentaire `Stay away from the 5G cellphones!! They are using 5G to control you.` est classé comme à risque moyen.

### Déployer votre prompt

Une fois que vous êtes confiant dans la qualité de votre solution, il est temps de la déployer en production. Voici quelques bonnes pratiques à suivre lors de l'utilisation de la modération de contenu en production :

1. **Fournir un retour clair aux utilisateurs :** Lorsque la saisie d'un utilisateur est bloquée ou qu'une réponse est signalée en raison de la modération de contenu, fournissez un retour informatif et constructif pour aider les utilisateurs à comprendre pourquoi leur message a été signalé et comment ils peuvent le reformuler de manière appropriée. Dans les exemples de code précédents, cela se fait via le champ `explanation` de la réponse de Claude.

2. **Analyser le contenu modéré :** Suivez les types de contenu signalés par votre système de modération afin d'identifier les tendances et les axes d'amélioration potentiels.

3. **Évaluer et améliorer en continu :** Évaluez régulièrement les performances de votre système de modération de contenu à l'aide de métriques telles que le suivi de la précision et du rappel. Utilisez ces données pour affiner de manière itérative vos prompts de modération, vos mots-clés et vos critères d'évaluation.

***

## Améliorer les performances

Dans des scénarios complexes, il peut être utile d'envisager des stratégies supplémentaires pour améliorer les performances au-delà des [techniques de prompt engineering](https://platform.claude.com/docs/fr/build-with-claude/prompt-engineering/overview) standard. Voici quelques stratégies avancées :

### Définir les sujets et fournir des exemples

En plus de lister les catégories non sûres dans le prompt, des améliorations supplémentaires peuvent être apportées en fournissant des définitions et des expressions liées à chaque catégorie.

<CodeGroup exclude="shell">
  ```python Python
  # Catégories considérées comme dangereuses pour la modération de contenu, avec leurs définitions
  unsafe_category_definitions = {
      "Child Exploitation": "Content that depicts child nudity or that enables, encourages, excuses, or depicts the sexual abuse of children.",
      "Conspiracy Theories": """Content that promotes or endorses unfounded, false, or misleading theories about events, situations, or individuals,
          which can incite harm or undermine public trust in institutions or facts.""",
      "Hate": """Content that is hateful toward people on the basis of their protected characteristics
          (race, color, ethnicity, national origin, disability, religious affiliation, caste, sexual orientation, sex, gender identity and serious disease),
          or content that perpetuates negative stereotypes.""",
      "Indiscriminate Weapons": "Content that enables the creation of weapons of mass destruction.",
      "Intellectual Property": "Content that violates the intellectual property rights of third parties.",
      "Non-Violent Crimes": "Content that enables, encourages, or excuses the commission of non-violent crimes.",
      "Privacy": "Content that contains sensitive, personal information about private individuals.",
      "Self-Harm": "Content that enables, encourages, or excuses acts of intentional self-harm.",
      "Sex Crimes": "Content that enables, encourages, or excuses the commission of sex crimes.",
      "Sexual Content": "Content that contains erotic descriptions or explicit depictions of sex acts.",
      "Specialized Advice": """Content that contains financial, medical, or legal advice.
          Financial advice includes guidance on investments, stocks, bonds, or any financial planning.""",
      "Violent Crimes": "Content that enables, encourages, or excuses the commission of violent crimes.",
  }


  def moderate_message_with_definitions(message, unsafe_category_definitions):
      # Formater la chaîne des catégories dangereuses, avec chaque catégorie et sa définition sur une nouvelle ligne
      unsafe_category_str = "\n".join(
          f"{category}: {definition}"
          for category, definition in unsafe_category_definitions.items()
      )

      # Construire le prompt pour Claude, incluant le message et les catégories dangereuses
      assessment_prompt = f"""Determine whether the following message warrants moderation, based on the unsafe categories outlined below.

  Message:
  <message>{message}</message>

  Unsafe Categories and Their Definitions:
  <categories>
  {unsafe_category_str}
  </categories>

  It's important that you remember all unsafe categories and their definitions.

  Respond with ONLY a JSON object, using the format below:
  {{
    "violation": <Boolean field denoting whether the message should be moderated>,
    "categories": [Comma-separated list of violated categories],
    "explanation": [Optional. Only include if there is a violation.]
  }}
  Do not include markdown formatting or code fences in your response."""

      # Envoyer la requête à Claude pour la modération de contenu
      response = client.messages.create(
          model="claude-haiku-4-5-20251001",  # Using the Haiku model for lower costs
          max_tokens=200,
          messages=[{"role": "user", "content": assessment_prompt}],
      )

      # Analyser la réponse JSON de Claude
      text_block = next(block for block in response.content if block.type == "text")
      assessment = json.loads(text_block.text)

      # Extraire le statut de violation de l'évaluation
      contains_violation = assessment["violation"]

      # S'il y a une violation, récupérer les catégories et l'explication ; sinon, utiliser des valeurs vides par défaut
      violated_categories = assessment.get("categories", []) if contains_violation else []
      explanation = assessment.get("explanation") if contains_violation else None

      return contains_violation, violated_categories, explanation


  # Traiter chaque commentaire et afficher les résultats
  for comment in user_comments:
      print(f"\nComment: {comment}")
      violation, violated_categories, explanation = moderate_message_with_definitions(
          comment, unsafe_category_definitions
      )

      if violation:
          print(f"Violated Categories: {', '.join(violated_categories)}")
          print(f"Explanation: {explanation}")
      else:
          print("No issues detected.")
  ```

  ```typescript TypeScript
  // Structure de l'évaluation JSON renvoyée par Claude
  interface DefinitionBasedAssessment {
    violation: boolean;
    categories?: string[];
    explanation?: string;
  }

  // Catégories considérées comme dangereuses pour la modération de contenu, avec leurs définitions
  // (les clés d'objet conservent l'ordre d'insertion, donc les catégories s'affichent dans cet ordre)
  const unsafeCategoryDefinitions: Record<string, string> = {
    "Child Exploitation":
      "Content that depicts child nudity or that enables, encourages, excuses, or depicts the sexual abuse of children.",
    "Conspiracy Theories": `Content that promotes or endorses unfounded, false, or misleading theories about events, situations, or individuals,
          which can incite harm or undermine public trust in institutions or facts.`,
    Hate: `Content that is hateful toward people on the basis of their protected characteristics
          (race, color, ethnicity, national origin, disability, religious affiliation, caste, sexual orientation, sex, gender identity and serious disease),
          or content that perpetuates negative stereotypes.`,
    "Indiscriminate Weapons":
      "Content that enables the creation of weapons of mass destruction.",
    "Intellectual Property":
      "Content that violates the intellectual property rights of third parties.",
    "Non-Violent Crimes":
      "Content that enables, encourages, or excuses the commission of non-violent crimes.",
    Privacy: "Content that contains sensitive, personal information about private individuals.",
    "Self-Harm": "Content that enables, encourages, or excuses acts of intentional self-harm.",
    "Sex Crimes": "Content that enables, encourages, or excuses the commission of sex crimes.",
    "Sexual Content":
      "Content that contains erotic descriptions or explicit depictions of sex acts.",
    "Specialized Advice": `Content that contains financial, medical, or legal advice.
          Financial advice includes guidance on investments, stocks, bonds, or any financial planning.`,
    "Violent Crimes":
      "Content that enables, encourages, or excuses the commission of violent crimes."
  };

  async function moderateMessageWithDefinitions(
    message: string,
    unsafeCategoryDefinitions: Record<string, string>
  ): Promise<{ violation: boolean; violatedCategories: string[]; explanation?: string }> {
    // Formater la chaîne des catégories dangereuses, avec chaque catégorie et sa définition sur une nouvelle ligne
    const unsafeCategoryStr = Object.entries(unsafeCategoryDefinitions)
      .map(([category, definition]) => `${category}: ${definition}`)
      .join("\n");

    // Construire le prompt pour Claude, incluant le message et les catégories dangereuses
    const assessmentPrompt = `Determine whether the following message warrants moderation, based on the unsafe categories outlined below.

  Message:
  <message>${message}</message>

  Unsafe Categories and Their Definitions:
  <categories>
  ${unsafeCategoryStr}
  </categories>

  It's important that you remember all unsafe categories and their definitions.

  Respond with ONLY a JSON object, using the format below:
  {
    "violation": <Boolean field denoting whether the message should be moderated>,
    "categories": [Comma-separated list of violated categories],
    "explanation": [Optional. Only include if there is a violation.]
  }
  Do not include markdown formatting or code fences in your response.`;

    // Envoyer la requête à Claude pour la modération de contenu
    const response = await client.messages.create({
      model: "claude-haiku-4-5-20251001", // Using the Haiku model for lower costs
      max_tokens: 200,
      messages: [{ role: "user", content: assessmentPrompt }]
    });

    // Analyser la réponse JSON de Claude
    const textBlock = response.content.find((block) => block.type === "text");
    if (!textBlock) {
      throw new Error("Expected a text block in the response");
    }
    const assessment: DefinitionBasedAssessment = JSON.parse(textBlock.text);

    // Extraire le statut de violation de l'évaluation
    const containsViolation = assessment.violation;

    // S'il y a une violation, récupérer les catégories et l'explication ; sinon, utiliser des valeurs vides par défaut
    const violatedCategories = containsViolation ? (assessment.categories ?? []) : [];
    const explanation = containsViolation ? assessment.explanation : undefined;

    return { violation: containsViolation, violatedCategories, explanation };
  }

  // Traiter chaque commentaire et afficher les résultats
  for (const comment of userComments) {
    console.log(`\nComment: ${comment}`);
    const { violation, violatedCategories, explanation } = await moderateMessageWithDefinitions(
      comment,
      unsafeCategoryDefinitions
    );

    if (violation) {
      console.log(`Violated Categories: ${violatedCategories.join(", ")}`);
      console.log(`Explanation: ${explanation}`);
    } else {
      console.log("No issues detected.");
    }
  }
  ```

  ```csharp C#
  // Catégories considérées comme dangereuses pour la modération de contenu, avec leurs définitions.
  // Les entrées restent dans l'ordre d'insertion, donc le prompt généré liste les catégories
  // exactement dans cet ordre.
  (string Category, string Definition)[] unsafeCategoryDefinitions =
  [
      (
          "Child Exploitation",
          "Content that depicts child nudity or that enables, encourages, excuses, or depicts the sexual abuse of children."
      ),
      (
          "Conspiracy Theories",
          """
          Content that promotes or endorses unfounded, false, or misleading theories about events, situations, or individuals,
                  which can incite harm or undermine public trust in institutions or facts.
          """
      ),
      (
          "Hate",
          """
          Content that is hateful toward people on the basis of their protected characteristics
                  (race, color, ethnicity, national origin, disability, religious affiliation, caste, sexual orientation, sex, gender identity and serious disease),
                  or content that perpetuates negative stereotypes.
          """
      ),
      ("Indiscriminate Weapons", "Content that enables the creation of weapons of mass destruction."),
      ("Intellectual Property", "Content that violates the intellectual property rights of third parties."),
      ("Non-Violent Crimes", "Content that enables, encourages, or excuses the commission of non-violent crimes."),
      ("Privacy", "Content that contains sensitive, personal information about private individuals."),
      ("Self-Harm", "Content that enables, encourages, or excuses acts of intentional self-harm."),
      ("Sex Crimes", "Content that enables, encourages, or excuses the commission of sex crimes."),
      ("Sexual Content", "Content that contains erotic descriptions or explicit depictions of sex acts."),
      (
          "Specialized Advice",
          """
          Content that contains financial, medical, or legal advice.
                  Financial advice includes guidance on investments, stocks, bonds, or any financial planning.
          """
      ),
      ("Violent Crimes", "Content that enables, encourages, or excuses the commission of violent crimes."),
  ];


  async Task<(bool ContainsViolation, List<string> ViolatedCategories, string? Explanation)> ModerateMessageWithDefinitions(
      string message,
      IReadOnlyList<(string Category, string Definition)> categoryDefinitions
  )
  {
      // Formater la chaîne des catégories dangereuses, avec chaque catégorie et sa définition sur une nouvelle ligne
      var unsafeCategoryText = string.Join(
          "\n",
          categoryDefinitions.Select(entry => $"{entry.Category}: {entry.Definition}")
      );

      // Construire le prompt pour Claude, incluant le message et les catégories dangereuses
      var assessmentPrompt = $$"""
  Determine whether the following message warrants moderation, based on the unsafe categories outlined below.

  Message:
  <message>{{message}}</message>

  Unsafe Categories and Their Definitions:
  <categories>
  {{unsafeCategoryText}}
  </categories>

  It's important that you remember all unsafe categories and their definitions.

  Respond with ONLY a JSON object, using the format below:
  {
    "violation": <Boolean field denoting whether the message should be moderated>,
    "categories": [Comma-separated list of violated categories],
    "explanation": [Optional. Only include if there is a violation.]
  }
  Do not include markdown formatting or code fences in your response.
  """;

      // Envoyer la requête à Claude pour la modération de contenu
      var response = await client.Messages.Create(
          new()
          {
              Model = Model.ClaudeHaiku4_5_20251001, // Using the Haiku model for lower costs
              MaxTokens = 200,
              Messages = [new() { Role = Role.User, Content = assessmentPrompt }],
          }
      );

      // Restreindre le premier bloc de contenu à un bloc de texte, puis analyser la réponse JSON de Claude
      if (!response.Content[0].TryPickText(out var textBlock))
      {
          throw new InvalidOperationException("Expected a text response from Claude.");
      }
      var assessment = JsonNode.Parse(textBlock.Text)!;

      // Extraire le statut de violation de l'évaluation
      var containsViolation = assessment["violation"]!.GetValue<bool>();

      // S'il y a une violation, obtenir les catégories et l'explication ; sinon, utiliser des valeurs par défaut vides
      List<string> violatedCategories = containsViolation
          ? assessment["categories"]?.AsArray().Select(category => category!.GetValue<string>()).ToList() ?? []
          : [];
      var explanation = containsViolation ? assessment["explanation"]?.GetValue<string>() : null;

      return (containsViolation, violatedCategories, explanation);
  }

  // Traiter chaque commentaire et afficher les résultats
  foreach (var comment in userComments)
  {
      Console.WriteLine($"\nComment: {comment}");
      var (violation, violatedCategories, explanation) = await ModerateMessageWithDefinitions(
          comment,
          unsafeCategoryDefinitions
      );

      if (violation)
      {
          Console.WriteLine($"Violated Categories: {string.Join(", ", violatedCategories)}");
          Console.WriteLine($"Explanation: {explanation}");
      }
      else
      {
          Console.WriteLine("No issues detected.");
      }
  }
  ```

  ```go Go
  // Catégories considérées comme dangereuses pour la modération de contenu, avec leurs définitions.
  // Un slice de paires catégorie/définition (plutôt qu'une map) garde l'ordre de rendu
  // stable ; les maps Go itèrent dans un ordre aléatoire.
  type categoryDefinition struct {
  	category   string
  	definition string
  }

  var unsafeCategoryDefinitions = []categoryDefinition{
  	{"Child Exploitation", "Content that depicts child nudity or that enables, encourages, excuses, or depicts the sexual abuse of children."},
  	{"Conspiracy Theories", `Content that promotes or endorses unfounded, false, or misleading theories about events, situations, or individuals,
          which can incite harm or undermine public trust in institutions or facts.`},
  	{"Hate", `Content that is hateful toward people on the basis of their protected characteristics
          (race, color, ethnicity, national origin, disability, religious affiliation, caste, sexual orientation, sex, gender identity and serious disease),
          or content that perpetuates negative stereotypes.`},
  	{"Indiscriminate Weapons", "Content that enables the creation of weapons of mass destruction."},
  	{"Intellectual Property", "Content that violates the intellectual property rights of third parties."},
  	{"Non-Violent Crimes", "Content that enables, encourages, or excuses the commission of non-violent crimes."},
  	{"Privacy", "Content that contains sensitive, personal information about private individuals."},
  	{"Self-Harm", "Content that enables, encourages, or excuses acts of intentional self-harm."},
  	{"Sex Crimes", "Content that enables, encourages, or excuses the commission of sex crimes."},
  	{"Sexual Content", "Content that contains erotic descriptions or explicit depictions of sex acts."},
  	{"Specialized Advice", `Content that contains financial, medical, or legal advice.
          Financial advice includes guidance on investments, stocks, bonds, or any financial planning.`},
  	{"Violent Crimes", "Content that enables, encourages, or excuses the commission of violent crimes."},
  }

  func moderateMessageWithDefinitions(message string, unsafeCategoryDefinitions []categoryDefinition) (bool, []string, string) {
  	// Formater la chaîne des catégories dangereuses, avec chaque catégorie et sa définition sur une nouvelle ligne
  	categoryLines := make([]string, len(unsafeCategoryDefinitions))
  	for i, entry := range unsafeCategoryDefinitions {
  		categoryLines[i] = fmt.Sprintf("%s: %s", entry.category, entry.definition)
  	}
  	unsafeCategoryStr := strings.Join(categoryLines, "\n")

  	// Construire le prompt pour Claude, incluant le message et les catégories dangereuses
  	assessmentPrompt := fmt.Sprintf(`Determine whether the following message warrants moderation, based on the unsafe categories outlined below.

  Message:
  <message>%s</message>

  Unsafe Categories and Their Definitions:
  <categories>
  %s
  </categories>

  It's important that you remember all unsafe categories and their definitions.

  Respond with ONLY a JSON object, using the format below:
  {
    "violation": <Boolean field denoting whether the message should be moderated>,
    "categories": [Comma-separated list of violated categories],
    "explanation": [Optional. Only include if there is a violation.]
  }
  Do not include markdown formatting or code fences in your response.`, message, unsafeCategoryStr)

  	// Envoyer la requête à Claude pour la modération de contenu
  	response, err := client.Messages.New(context.Background(), anthropic.MessageNewParams{
  		Model:     anthropic.ModelClaudeHaiku4_5_20251001, // Using the Haiku model for lower costs
  		MaxTokens: 200,
  		Messages: []anthropic.MessageParam{
  			anthropic.NewUserMessage(anthropic.NewTextBlock(assessmentPrompt)),
  		},
  	})
  	if err != nil {
  		log.Fatal(err)
  	}

  	// Restreindre le premier bloc de contenu à un bloc de texte avant de lire son texte
  	textBlock, ok := response.Content[0].AsAny().(anthropic.TextBlock)
  	if !ok {
  		log.Fatalf("expected a text block, got %q", response.Content[0].Type)
  	}

  	// Analyser la réponse JSON de Claude
  	var assessment struct {
  		Violation   bool     `json:"violation"`
  		Categories  []string `json:"categories"`
  		Explanation string   `json:"explanation"`
  	}
  	if err := json.Unmarshal([]byte(textBlock.Text), &assessment); err != nil {
  		log.Fatal(err)
  	}

  	// S'il y a une violation, retourner les catégories et l'explication ; sinon, utiliser des valeurs par défaut vides
  	if !assessment.Violation {
  		return false, nil, ""
  	}
  	return true, assessment.Categories, assessment.Explanation
  }

  // moderateAllCommentsWithDefinitions traite chaque commentaire et affiche les résultats.
  func moderateAllCommentsWithDefinitions() {
  	for _, comment := range userComments {
  		fmt.Printf("\nComment: %s\n", comment)
  		violation, violatedCategories, explanation := moderateMessageWithDefinitions(comment, unsafeCategoryDefinitions)

  		if violation {
  			fmt.Printf("Violated Categories: %s\n", strings.Join(violatedCategories, ", "))
  			fmt.Printf("Explanation: %s\n", explanation)
  		} else {
  			fmt.Println("No issues detected.")
  		}
  	}
  }
  ```

  ```java Java
  // Catégories considérées comme dangereuses pour la modération de contenu, avec leurs définitions
  record CategoryDefinition(String category, String definition) {}

  final List<CategoryDefinition> unsafeCategoryDefinitions = List.of(
          new CategoryDefinition(
                  "Child Exploitation",
                  "Content that depicts child nudity or that enables, encourages, excuses, or depicts the sexual abuse of children."),
          new CategoryDefinition(
                  "Conspiracy Theories",
                  """
                  Content that promotes or endorses unfounded, false, or misleading theories about events, situations, or individuals,
                          which can incite harm or undermine public trust in institutions or facts."""),
          new CategoryDefinition(
                  "Hate",
                  """
                  Content that is hateful toward people on the basis of their protected characteristics
                          (race, color, ethnicity, national origin, disability, religious affiliation, caste, sexual orientation, sex, gender identity and serious disease),
                          or content that perpetuates negative stereotypes."""),
          new CategoryDefinition(
                  "Indiscriminate Weapons",
                  "Content that enables the creation of weapons of mass destruction."),
          new CategoryDefinition(
                  "Intellectual Property",
                  "Content that violates the intellectual property rights of third parties."),
          new CategoryDefinition(
                  "Non-Violent Crimes",
                  "Content that enables, encourages, or excuses the commission of non-violent crimes."),
          new CategoryDefinition(
                  "Privacy",
                  "Content that contains sensitive, personal information about private individuals."),
          new CategoryDefinition(
                  "Self-Harm",
                  "Content that enables, encourages, or excuses acts of intentional self-harm."),
          new CategoryDefinition(
                  "Sex Crimes",
                  "Content that enables, encourages, or excuses the commission of sex crimes."),
          new CategoryDefinition(
                  "Sexual Content",
                  "Content that contains erotic descriptions or explicit depictions of sex acts."),
          new CategoryDefinition(
                  "Specialized Advice",
                  """
                  Content that contains financial, medical, or legal advice.
                          Financial advice includes guidance on investments, stocks, bonds, or any financial planning."""),
          new CategoryDefinition(
                  "Violent Crimes",
                  "Content that enables, encourages, or excuses the commission of violent crimes."));

  record ModerationDecision(boolean violation, List<String> violatedCategories, String explanation) {}

  ModerationDecision moderateMessageWithDefinitions(
          String message, List<CategoryDefinition> unsafeCategoryDefinitions)
          throws JsonProcessingException {
      // Formater la chaîne des catégories dangereuses, avec chaque catégorie et sa définition sur une nouvelle ligne
      String unsafeCategoryStr = unsafeCategoryDefinitions.stream()
              .map(categoryDefinition ->
                      categoryDefinition.category() + ": " + categoryDefinition.definition())
              .collect(Collectors.joining("\n"));

      // Construire le prompt pour Claude, incluant le message et les catégories dangereuses
      String assessmentPrompt = """
          Determine whether the following message warrants moderation, based on the unsafe categories outlined below.

          Message:
          <message>%s</message>

          Unsafe Categories and Their Definitions:
          <categories>
          %s
          </categories>

          It's important that you remember all unsafe categories and their definitions.

          Respond with ONLY a JSON object, using the format below:
          {
            "violation": <Boolean field denoting whether the message should be moderated>,
            "categories": [Comma-separated list of violated categories],
            "explanation": [Optional. Only include if there is a violation.]
          }
          Do not include markdown formatting or code fences in your response."""
              .formatted(message, unsafeCategoryStr);

      // Envoyer la requête à Claude pour la modération de contenu
      Message response = client.messages().create(MessageCreateParams.builder()
              .model(Model.CLAUDE_HAIKU_4_5_20251001) // Using the Haiku model for lower costs
              .maxTokens(200)
              .addUserMessage(assessmentPrompt)
              .build());

      // Analyser la réponse JSON de Claude
      String assessmentJson = response.content().stream()
              .flatMap(contentBlock -> contentBlock.text().stream())
              .findFirst()
              .orElseThrow()
              .text();
      ObjectMapper mapper = new ObjectMapper();
      JsonNode assessment = mapper.readTree(assessmentJson);

      // Extraire le statut de violation de l'évaluation
      boolean containsViolation = assessment.required("violation").asBoolean();

      // S'il y a une violation, obtenir les catégories et l'explication ; sinon, utiliser des valeurs par défaut vides
      List<String> violatedCategories = containsViolation && assessment.has("categories")
              ? mapper.convertValue(assessment.get("categories"), new TypeReference<List<String>>() {})
              : List.of();
      String explanation = containsViolation && assessment.hasNonNull("explanation")
              ? assessment.get("explanation").asText()
              : null;

      return new ModerationDecision(containsViolation, violatedCategories, explanation);
  }

  // Traiter chaque commentaire et afficher les résultats
  void printModerationResultsWithDefinitions() throws JsonProcessingException {
      for (String comment : userComments) {
          IO.println("\nComment: " + comment);
          ModerationDecision result = moderateMessageWithDefinitions(comment, unsafeCategoryDefinitions);

          if (result.violation()) {
              IO.println("Violated Categories: " + String.join(", ", result.violatedCategories()));
              IO.println("Explanation: " + result.explanation());
          } else {
              IO.println("No issues detected.");
          }
      }
  }
  ```

  ```php PHP
  // Catégories considérées comme dangereuses pour la modération de contenu, avec leurs définitions
  $unsafeCategoryDefinitions = [
      'Child Exploitation' => 'Content that depicts child nudity or that enables, encourages, excuses, or depicts the sexual abuse of children.',
      'Conspiracy Theories' => 'Content that promotes or endorses unfounded, false, or misleading theories about events, situations, or individuals,
          which can incite harm or undermine public trust in institutions or facts.',
      'Hate' => 'Content that is hateful toward people on the basis of their protected characteristics
          (race, color, ethnicity, national origin, disability, religious affiliation, caste, sexual orientation, sex, gender identity and serious disease),
          or content that perpetuates negative stereotypes.',
      'Indiscriminate Weapons' => 'Content that enables the creation of weapons of mass destruction.',
      'Intellectual Property' => 'Content that violates the intellectual property rights of third parties.',
      'Non-Violent Crimes' => 'Content that enables, encourages, or excuses the commission of non-violent crimes.',
      'Privacy' => 'Content that contains sensitive, personal information about private individuals.',
      'Self-Harm' => 'Content that enables, encourages, or excuses acts of intentional self-harm.',
      'Sex Crimes' => 'Content that enables, encourages, or excuses the commission of sex crimes.',
      'Sexual Content' => 'Content that contains erotic descriptions or explicit depictions of sex acts.',
      'Specialized Advice' => 'Content that contains financial, medical, or legal advice.
          Financial advice includes guidance on investments, stocks, bonds, or any financial planning.',
      'Violent Crimes' => 'Content that enables, encourages, or excuses the commission of violent crimes.',
  ];

  $moderateMessageWithDefinitions = function (string $message, array $unsafeCategoryDefinitions) use ($client): array {
      // Formater la chaîne des catégories dangereuses, avec chaque catégorie et sa définition sur une nouvelle ligne
      $categoryLines = [];
      foreach ($unsafeCategoryDefinitions as $category => $definition) {
          $categoryLines[] = "{$category}: {$definition}";
      }
      $unsafeCategoryStr = implode("\n", $categoryLines);

      // Construire le prompt pour Claude, incluant le message et les catégories dangereuses
      $assessmentPrompt = <<<PROMPT
      Determine whether the following message warrants moderation, based on the unsafe categories outlined below.

      Message:
      <message>{$message}</message>

      Unsafe Categories and Their Definitions:
      <categories>
      {$unsafeCategoryStr}
      </categories>

      It's important that you remember all unsafe categories and their definitions.

      Respond with ONLY a JSON object, using the format below:
      {
        "violation": <Boolean field denoting whether the message should be moderated>,
        "categories": [Comma-separated list of violated categories],
        "explanation": [Optional. Only include if there is a violation.]
      }
      Do not include markdown formatting or code fences in your response.
      PROMPT;

      // Envoyer la requête à Claude pour la modération de contenu
      $response = $client->messages->create(
          model: 'claude-haiku-4-5-20251001', // Using the Haiku model for lower costs
          maxTokens: 200,
          messages: [['role' => 'user', 'content' => $assessmentPrompt]],
      );

      // Analyser la réponse JSON de Claude. Le SDK décode chaque bloc de contenu
      // dans sa classe concrète, donc trouver le TextBlock avant de lire le texte.
      $textBlock = array_find($response->content, fn ($block) => $block instanceof \Anthropic\Messages\TextBlock)
          ?? throw new \RuntimeException('Expected a text block in the response.');
      $assessment = json_decode($textBlock->text, associative: true, flags: JSON_THROW_ON_ERROR);

      // Extraire le statut de violation de l'évaluation
      $containsViolation = $assessment['violation'];

      // S'il y a une violation, récupérer les catégories et l'explication ; sinon, utiliser des valeurs vides par défaut
      $violatedCategories = $containsViolation ? ($assessment['categories'] ?? []) : [];
      $explanation = $containsViolation ? ($assessment['explanation'] ?? null) : null;

      return [$containsViolation, $violatedCategories, $explanation];
  };

  // Traiter chaque commentaire et afficher les résultats
  foreach ($userComments as $comment) {
      echo "\nComment: {$comment}\n";
      [$violation, $violatedCategories, $explanation] = $moderateMessageWithDefinitions($comment, $unsafeCategoryDefinitions);

      if ($violation) {
          echo 'Violated Categories: ' . implode(', ', $violatedCategories) . "\n";
          echo "Explanation: {$explanation}\n";
      } else {
          echo "No issues detected.\n";
      }
  }
  ```

  ```ruby Ruby
  # Catégories considérées comme dangereuses pour la modération de contenu, avec leurs définitions
  UNSAFE_CATEGORY_DEFINITIONS = {
    "Child Exploitation" => "Content that depicts child nudity or that enables, encourages, excuses, or depicts the sexual abuse of children.",
    "Conspiracy Theories" => "Content that promotes or endorses unfounded, false, or misleading theories about events, situations, or individuals,
          which can incite harm or undermine public trust in institutions or facts.",
    "Hate" => "Content that is hateful toward people on the basis of their protected characteristics
          (race, color, ethnicity, national origin, disability, religious affiliation, caste, sexual orientation, sex, gender identity and serious disease),
          or content that perpetuates negative stereotypes.",
    "Indiscriminate Weapons" => "Content that enables the creation of weapons of mass destruction.",
    "Intellectual Property" => "Content that violates the intellectual property rights of third parties.",
    "Non-Violent Crimes" => "Content that enables, encourages, or excuses the commission of non-violent crimes.",
    "Privacy" => "Content that contains sensitive, personal information about private individuals.",
    "Self-Harm" => "Content that enables, encourages, or excuses acts of intentional self-harm.",
    "Sex Crimes" => "Content that enables, encourages, or excuses the commission of sex crimes.",
    "Sexual Content" => "Content that contains erotic descriptions or explicit depictions of sex acts.",
    "Specialized Advice" => "Content that contains financial, medical, or legal advice.
          Financial advice includes guidance on investments, stocks, bonds, or any financial planning.",
    "Violent Crimes" => "Content that enables, encourages, or excuses the commission of violent crimes."
  }


  def moderate_message_with_definitions(message, unsafe_category_definitions)
    # Formater la chaîne des catégories dangereuses, avec chaque catégorie et sa définition sur une nouvelle ligne
    unsafe_category_str = unsafe_category_definitions
      .map { |category, definition| "#{category}: #{definition}" }
      .join("\n")

    # Construire le prompt pour Claude, incluant le message et les catégories dangereuses
    assessment_prompt = <<~PROMPT.chomp
      Determine whether the following message warrants moderation, based on the unsafe categories outlined below.

      Message:
      <message>#{message}</message>

      Unsafe Categories and Their Definitions:
      <categories>
      #{unsafe_category_str}
      </categories>

      It's important that you remember all unsafe categories and their definitions.

      Respond with ONLY a JSON object, using the format below:
      {
        "violation": <Boolean field denoting whether the message should be moderated>,
        "categories": [Comma-separated list of violated categories],
        "explanation": [Optional. Only include if there is a violation.]
      }
      Do not include markdown formatting or code fences in your response.
    PROMPT

    # Envoyer la requête à Claude pour la modération de contenu
    response = CLIENT.messages.create(
      model: "claude-haiku-4-5-20251001", # Using the Haiku model for lower costs
      max_tokens: 200,
      messages: [{role: :user, content: assessment_prompt}]
    )

    # Analyser la réponse JSON de Claude
    text_block = response.content.find { it.type == :text }
    assessment = JSON.parse(text_block.text)

    # Extraire le statut de violation de l'évaluation
    contains_violation = assessment["violation"]

    # S'il y a une violation, récupérer les catégories et l'explication ; sinon, utiliser des valeurs par défaut vides
    violated_categories = contains_violation ? assessment.fetch("categories", []) : []
    explanation = contains_violation ? assessment["explanation"] : nil

    [contains_violation, violated_categories, explanation]
  end


  # Traiter chaque commentaire et afficher les résultats
  USER_COMMENTS.each do |comment|
    puts "\nComment: #{comment}"
    violation, violated_categories, explanation = moderate_message_with_definitions(comment, UNSAFE_CATEGORY_DEFINITIONS)

    if violation
      puts "Violated Categories: #{violated_categories.join(", ")}"
      puts "Explanation: #{explanation}"
    else
      puts "No issues detected."
    end
  end
  ```
</CodeGroup>

La fonction `moderate_message_with_definitions` étend la fonction `moderate_message` précédente en permettant d'associer chaque catégorie non sûre à une définition détaillée. Cela se fait dans le code en remplaçant la collection `unsafe_categories` de la fonction d'origine par un mappage `unsafe_category_definitions`. Ce mappage associe chaque catégorie non sûre à sa définition correspondante. Les noms des catégories et leurs définitions sont tous deux inclus dans le prompt.

Notamment, la définition de la catégorie `Specialized Advice` précise désormais les types de conseils financiers qui doivent être interdits. En conséquence, le commentaire `It is a great time to invest in gold!`, qui passait auparavant l'évaluation `moderate_message`, déclenche désormais une violation.

### Envisager le traitement par lots

Pour réduire les coûts dans les situations où la modération en temps réel n'est pas nécessaire, envisagez de modérer les messages par lots. Incluez plusieurs messages dans le contexte du prompt et demandez à Claude d'évaluer quels messages doivent être modérés.

<CodeGroup exclude="shell">
  ```python Python
  def batch_moderate_messages(messages, unsafe_categories):
      # Convertir les catégories dangereuses en chaîne, avec chaque catégorie sur une nouvelle ligne
      unsafe_category_str = "\n".join(unsafe_categories)

      # Formater la chaîne des messages, chaque message étant encadré de balises de type XML et doté d'un ID
      messages_str = "\n".join(
          [f"<message id={idx}>{msg}</message>" for idx, msg in enumerate(messages)]
      )

      # Construire le prompt pour Claude, incluant les messages et les catégories dangereuses
      assessment_prompt = f"""Determine the messages to moderate, based on the unsafe categories outlined below.

  Messages:
  <messages>
  {messages_str}
  </messages>

  Unsafe Categories:
  <categories>
  {unsafe_category_str}
  </categories>

  Respond with ONLY a JSON object, using the format below:
  {{
    "violations": [
      {{
        "id": <message id>,
        "categories": [list of violated categories],
        "explanation": <Explanation of why there's a violation>
      }}
    ]
  }}

  Important Notes:
  - Remember to analyze every message for a violation.
  - Select any number of violations that reasonably apply.
  - Do not include markdown formatting or code fences in your response."""

      # Envoyer la requête à Claude pour la modération de contenu
      response = client.messages.create(
          model="claude-haiku-4-5-20251001",  # Using the Haiku model for lower costs
          max_tokens=2048,  # Increased max token count to handle batches
          messages=[{"role": "user", "content": assessment_prompt}],
      )

      # Analyser la réponse JSON de Claude
      text_block = next(block for block in response.content if block.type == "text")
      assessment = json.loads(text_block.text)
      return assessment


  # Traiter le lot de commentaires et obtenir la réponse
  response_obj = batch_moderate_messages(user_comments, unsafe_categories)

  # Afficher les résultats pour chaque violation détectée
  for violation in response_obj["violations"]:
      print(f"""Comment: {user_comments[violation["id"]]}
  Violated Categories: {", ".join(violation["categories"])}
  Explanation: {violation["explanation"]}
  """)
  ```

  ```typescript TypeScript
  // Structure de l'évaluation par lots JSON renvoyée par Claude
  interface BatchAssessment {
    violations: {
      id: number;
      categories: string[];
      explanation: string;
    }[];
  }

  async function batchModerateMessages(
    messages: string[],
    unsafeCategories: string[]
  ): Promise<BatchAssessment> {
    // Convertir les catégories dangereuses en chaîne, avec chaque catégorie sur une nouvelle ligne
    const unsafeCategoryStr = unsafeCategories.join("\n");

    // Formater la chaîne des messages, chaque message étant encadré de balises de type XML et doté d'un ID
    const messagesStr = messages
      .map((msg, idx) => `<message id=${idx}>${msg}</message>`)
      .join("\n");

    // Construire le prompt pour Claude, incluant les messages et les catégories dangereuses
    const assessmentPrompt = `Determine the messages to moderate, based on the unsafe categories outlined below.

  Messages:
  <messages>
  ${messagesStr}
  </messages>

  Unsafe Categories:
  <categories>
  ${unsafeCategoryStr}
  </categories>

  Respond with ONLY a JSON object, using the format below:
  {
    "violations": [
      {
        "id": <message id>,
        "categories": [list of violated categories],
        "explanation": <Explanation of why there's a violation>
      }
    ]
  }

  Important Notes:
  - Remember to analyze every message for a violation.
  - Select any number of violations that reasonably apply.
  - Do not include markdown formatting or code fences in your response.`;

    // Envoyer la requête à Claude pour la modération de contenu
    const response = await client.messages.create({
      model: "claude-haiku-4-5-20251001", // Using the Haiku model for lower costs
      max_tokens: 2048, // Increased max token count to handle batches
      messages: [{ role: "user", content: assessmentPrompt }]
    });

    // Analyser la réponse JSON de Claude
    const textBlock = response.content.find((block) => block.type === "text");
    if (!textBlock) {
      throw new Error("Expected a text block in the response");
    }
    const assessment: BatchAssessment = JSON.parse(textBlock.text);
    return assessment;
  }

  // Traiter le lot de commentaires et obtenir la réponse
  const batchAssessment = await batchModerateMessages(userComments, unsafeCategories);

  // Afficher les résultats pour chaque violation détectée
  for (const violation of batchAssessment.violations) {
    console.log(`Comment: ${userComments[violation.id]}
  Violated Categories: ${violation.categories.join(", ")}
  Explanation: ${violation.explanation}
  `);
  }
  ```

  ```csharp C#
  async Task<JsonNode> BatchModerateMessages(IReadOnlyList<string> messages, IReadOnlyList<string> categories)
  {
      // Convertir les catégories dangereuses en chaîne, avec chaque catégorie sur une nouvelle ligne
      var unsafeCategoryText = string.Join("\n", categories);

      // Formater la chaîne des messages, chaque message étant encadré de balises de type XML et doté d'un ID
      var messagesText = string.Join(
          "\n",
          messages.Select((message, index) => $"<message id={index}>{message}</message>")
      );

      // Construire le prompt pour Claude, incluant les messages et les catégories dangereuses
      var assessmentPrompt = $$"""
  Determine the messages to moderate, based on the unsafe categories outlined below.

  Messages:
  <messages>
  {{messagesText}}
  </messages>

  Unsafe Categories:
  <categories>
  {{unsafeCategoryText}}
  </categories>

  Respond with ONLY a JSON object, using the format below:
  {
    "violations": [
      {
        "id": <message id>,
        "categories": [list of violated categories],
        "explanation": <Explanation of why there's a violation>
      }
    ]
  }

  Important Notes:
  - Remember to analyze every message for a violation.
  - Select any number of violations that reasonably apply.
  - Do not include markdown formatting or code fences in your response.
  """;

      // Envoyer la requête à Claude pour la modération de contenu
      var response = await client.Messages.Create(
          new()
          {
              Model = Model.ClaudeHaiku4_5_20251001, // Using the Haiku model for lower costs
              MaxTokens = 2048, // Increased max token count to handle batches
              Messages = [new() { Role = Role.User, Content = assessmentPrompt }],
          }
      );

      // Restreindre le premier bloc de contenu à un bloc de texte, puis analyser la réponse JSON de Claude
      if (!response.Content[0].TryPickText(out var textBlock))
      {
          throw new InvalidOperationException("Expected a text response from Claude.");
      }
      return JsonNode.Parse(textBlock.Text)!;
  }

  // Traiter le lot de commentaires et obtenir la réponse
  var moderationResults = await BatchModerateMessages(userComments, unsafeCategories);

  // Afficher les résultats pour chaque violation détectée
  foreach (var violation in moderationResults["violations"]!.AsArray())
  {
      var flaggedComment = userComments[violation!["id"]!.GetValue<int>()];
      var violatedCategories = string.Join(
          ", ",
          violation["categories"]!.AsArray().Select(category => category!.GetValue<string>())
      );
      var explanation = violation["explanation"]!.GetValue<string>();

      Console.WriteLine($"""
          Comment: {flaggedComment}
          Violated Categories: {violatedCategories}
          Explanation: {explanation}

          """);
  }
  ```

  ```go Go
  // batchViolation est une entrée du tableau « violations » de Claude : l'index du
  // message fautif, plus les catégories qu'il a violées et la raison.
  type batchViolation struct {
  	ID          int      `json:"id"`
  	Categories  []string `json:"categories"`
  	Explanation string   `json:"explanation"`
  }

  func batchModerateMessages(messages []string, unsafeCategories []string) []batchViolation {
  	// Convertir les catégories dangereuses en une chaîne, avec chaque catégorie sur une nouvelle ligne
  	unsafeCategoryStr := strings.Join(unsafeCategories, "\n")

  	// Formater la chaîne des messages, avec chaque message entouré de balises de type XML et doté d'un ID
  	messageLines := make([]string, len(messages))
  	for i, message := range messages {
  		messageLines[i] = fmt.Sprintf("<message id=%d>%s</message>", i, message)
  	}
  	messagesStr := strings.Join(messageLines, "\n")

  	// Construire le prompt pour Claude, incluant les messages et les catégories dangereuses
  	assessmentPrompt := fmt.Sprintf(`Determine the messages to moderate, based on the unsafe categories outlined below.

  Messages:
  <messages>
  %s
  </messages>

  Unsafe Categories:
  <categories>
  %s
  </categories>

  Respond with ONLY a JSON object, using the format below:
  {
    "violations": [
      {
        "id": <message id>,
        "categories": [list of violated categories],
        "explanation": <Explanation of why there's a violation>
      }
    ]
  }

  Important Notes:
  - Remember to analyze every message for a violation.
  - Select any number of violations that reasonably apply.
  - Do not include markdown formatting or code fences in your response.`, messagesStr, unsafeCategoryStr)

  	// Envoyer la requête à Claude pour la modération de contenu
  	response, err := client.Messages.New(context.Background(), anthropic.MessageNewParams{
  		Model:     anthropic.ModelClaudeHaiku4_5_20251001, // Using the Haiku model for lower costs
  		MaxTokens: 2048,                                   // Increased max token count to handle batches
  		Messages: []anthropic.MessageParam{
  			anthropic.NewUserMessage(anthropic.NewTextBlock(assessmentPrompt)),
  		},
  	})
  	if err != nil {
  		log.Fatal(err)
  	}

  	// Restreindre le premier bloc de contenu à un bloc de texte avant de lire son texte
  	textBlock, ok := response.Content[0].AsAny().(anthropic.TextBlock)
  	if !ok {
  		log.Fatalf("expected a text block, got %q", response.Content[0].Type)
  	}

  	// Analyser la réponse JSON de Claude
  	var assessment struct {
  		Violations []batchViolation `json:"violations"`
  	}
  	if err := json.Unmarshal([]byte(textBlock.Text), &assessment); err != nil {
  		log.Fatal(err)
  	}
  	return assessment.Violations
  }

  // moderateAllCommentsAsBatch modère le lot entier de commentaires en une seule
  // requête et affiche les résultats pour chaque violation détectée.
  func moderateAllCommentsAsBatch() {
  	// Traiter le lot de commentaires et obtenir la réponse
  	violations := batchModerateMessages(userComments, unsafeCategories)

  	// Afficher les résultats pour chaque violation détectée
  	for _, violation := range violations {
  		fmt.Printf(`Comment: %s
  Violated Categories: %s
  Explanation: %s

  `, userComments[violation.ID], strings.Join(violation.Categories, ", "), violation.Explanation)
  	}
  }
  ```

  ```java Java
  JsonNode batchModerateMessages(List<String> messages, List<String> unsafeCategories)
          throws JsonProcessingException {
      // Convertir les catégories dangereuses en chaîne, avec chaque catégorie sur une nouvelle ligne
      String unsafeCategoryStr = String.join("\n", unsafeCategories);

      // Formater la chaîne des messages, chaque message étant encadré de balises de type XML et doté d'un ID
      String messagesStr = IntStream.range(0, messages.size())
              .mapToObj(idx -> "<message id=%d>%s</message>".formatted(idx, messages.get(idx)))
              .collect(Collectors.joining("\n"));

      // Construire le prompt pour Claude, incluant les messages et les catégories dangereuses
      String assessmentPrompt = """
          Determine the messages to moderate, based on the unsafe categories outlined below.

          Messages:
          <messages>
          %s
          </messages>

          Unsafe Categories:
          <categories>
          %s
          </categories>

          Respond with ONLY a JSON object, using the format below:
          {
            "violations": [
              {
                "id": <message id>,
                "categories": [list of violated categories],
                "explanation": <Explanation of why there's a violation>
              }
            ]
          }

          Important Notes:
          - Remember to analyze every message for a violation.
          - Select any number of violations that reasonably apply.
          - Do not include markdown formatting or code fences in your response."""
              .formatted(messagesStr, unsafeCategoryStr);

      // Envoyer la requête à Claude pour la modération de contenu
      Message response = client.messages().create(MessageCreateParams.builder()
              .model(Model.CLAUDE_HAIKU_4_5_20251001) // Using the Haiku model for lower costs
              .maxTokens(2048) // Increased max token count to handle batches
              .addUserMessage(assessmentPrompt)
              .build());

      // Analyser la réponse JSON de Claude
      String assessmentJson = response.content().stream()
              .flatMap(contentBlock -> contentBlock.text().stream())
              .findFirst()
              .orElseThrow()
              .text();
      return new ObjectMapper().readTree(assessmentJson);
  }

  // Traiter le lot de commentaires et afficher les résultats pour chaque violation détectée
  void printBatchViolations() throws JsonProcessingException {
      JsonNode response = batchModerateMessages(userComments, unsafeCategories);

      ObjectMapper mapper = new ObjectMapper();
      for (JsonNode violation : response.required("violations")) {
          List<String> violatedCategories =
                  mapper.convertValue(violation.required("categories"), new TypeReference<List<String>>() {});
          IO.println("""
                  Comment: %s
                  Violated Categories: %s
                  Explanation: %s
                  """.formatted(
                          userComments.get(violation.required("id").asInt()),
                          String.join(", ", violatedCategories),
                          violation.required("explanation").asText()));
      }
  }
  ```

  ```php PHP
  $batchModerateMessages = function (array $messages, array $unsafeCategories) use ($client): array {
      // Convertir les catégories dangereuses en chaîne, avec chaque catégorie sur une nouvelle ligne
      $unsafeCategoryStr = implode("\n", $unsafeCategories);

      // Formater la chaîne des messages, chaque message étant encadré de balises de type XML et doté d'un ID
      $messageLines = [];
      foreach ($messages as $idx => $msg) {
          $messageLines[] = "<message id={$idx}>{$msg}</message>";
      }
      $messagesStr = implode("\n", $messageLines);

      // Construire le prompt pour Claude, incluant les messages et les catégories dangereuses
      $assessmentPrompt = <<<PROMPT
      Determine the messages to moderate, based on the unsafe categories outlined below.

      Messages:
      <messages>
      {$messagesStr}
      </messages>

      Unsafe Categories:
      <categories>
      {$unsafeCategoryStr}
      </categories>

      Respond with ONLY a JSON object, using the format below:
      {
        "violations": [
          {
            "id": <message id>,
            "categories": [list of violated categories],
            "explanation": <Explanation of why there's a violation>
          }
        ]
      }

      Important Notes:
      - Remember to analyze every message for a violation.
      - Select any number of violations that reasonably apply.
      - Do not include markdown formatting or code fences in your response.
      PROMPT;

      // Envoyer la requête à Claude pour la modération de contenu
      $response = $client->messages->create(
          model: 'claude-haiku-4-5-20251001', // Using the Haiku model for lower costs
          maxTokens: 2048, // Increased max token count to handle batches
          messages: [['role' => 'user', 'content' => $assessmentPrompt]],
      );

      // Analyser la réponse JSON de Claude. Le SDK décode chaque bloc de contenu
      // dans sa classe concrète, donc trouver le TextBlock avant de lire le texte.
      $textBlock = array_find($response->content, fn ($block) => $block instanceof \Anthropic\Messages\TextBlock)
          ?? throw new \RuntimeException('Expected a text block in the response.');

      return json_decode($textBlock->text, associative: true, flags: JSON_THROW_ON_ERROR);
  };

  // Traiter le lot de commentaires et obtenir la réponse
  $responseObj = $batchModerateMessages($userComments, $unsafeCategories);

  // Afficher les résultats pour chaque violation détectée
  foreach ($responseObj['violations'] as $violation) {
      echo "Comment: {$userComments[$violation['id']]}\n";
      echo 'Violated Categories: ' . implode(', ', $violation['categories']) . "\n";
      echo "Explanation: {$violation['explanation']}\n\n";
  }
  ```

  ```ruby Ruby
  def batch_moderate_messages(messages, unsafe_categories)
    # Convertir les catégories dangereuses en chaîne, avec chaque catégorie sur une nouvelle ligne
    unsafe_category_str = unsafe_categories.join("\n")

    # Formater la chaîne des messages, chaque message étant encadré de balises de type XML et doté d'un ID
    messages_str = messages
      .map.with_index { |message, index| "<message id=#{index}>#{message}</message>" }
      .join("\n")

    # Construire le prompt pour Claude, incluant les messages et les catégories dangereuses
    assessment_prompt = <<~PROMPT.chomp
      Determine the messages to moderate, based on the unsafe categories outlined below.

      Messages:
      <messages>
      #{messages_str}
      </messages>

      Unsafe Categories:
      <categories>
      #{unsafe_category_str}
      </categories>

      Respond with ONLY a JSON object, using the format below:
      {
        "violations": [
          {
            "id": <message id>,
            "categories": [list of violated categories],
            "explanation": <Explanation of why there's a violation>
          }
        ]
      }

      Important Notes:
      - Remember to analyze every message for a violation.
      - Select any number of violations that reasonably apply.
      - Do not include markdown formatting or code fences in your response.
    PROMPT

    # Envoyer la requête à Claude pour la modération de contenu
    response = CLIENT.messages.create(
      model: "claude-haiku-4-5-20251001", # Using the Haiku model for lower costs
      max_tokens: 2048, # Increased max token count to handle batches
      messages: [{role: :user, content: assessment_prompt}]
    )

    # Analyser la réponse JSON de Claude
    text_block = response.content.find { it.type == :text }
    JSON.parse(text_block.text)
  end


  # Traiter le lot de commentaires et obtenir la réponse
  response_obj = batch_moderate_messages(USER_COMMENTS, UNSAFE_CATEGORIES)

  # Afficher les résultats pour chaque violation détectée
  response_obj["violations"].each do |violation|
    puts <<~RESULT
      Comment: #{USER_COMMENTS[violation["id"]]}
      Violated Categories: #{violation["categories"].join(", ")}
      Explanation: #{violation["explanation"]}

    RESULT
  end
  ```
</CodeGroup>

Dans cet exemple, la fonction `batch_moderate_messages` gère la modération d'un lot entier de messages avec un seul appel à l'API Claude. À l'intérieur de la fonction, un prompt est créé qui inclut la liste des messages à évaluer et les catégories de contenu non sûr. Le prompt demande à Claude de renvoyer un objet JSON listant tous les messages qui contiennent des violations. Chaque message de la réponse est identifié par son `id`, qui correspond à la position du message dans le lot. Gardez à l'esprit que trouver la taille de lot optimale pour vos besoins spécifiques peut nécessiter quelques expérimentations. Bien que des tailles de lot plus importantes puissent réduire les coûts, elles peuvent également entraîner une légère baisse de qualité. De plus, vous devrez peut-être augmenter le paramètre `max_tokens` dans l'appel à l'API Claude pour permettre des réponses plus longues. Pour plus de détails sur le nombre maximal de tokens que le modèle choisi peut produire, reportez-vous au [tableau de comparaison des modèles](https://platform.claude.com/docs/fr/models/overview#latest-models-comparison).

<CardGroup cols={2}>
  <Card title="Cookbook de modération de contenu" icon="link" href="https://platform.claude.com/cookbook/misc-building-moderation-filter">
    Consultez un exemple de code entièrement implémenté montrant comment utiliser Claude pour la modération de contenu.
  </Card>

  <Card title="Atténuer les jailbreaks" icon="link" href="https://platform.claude.com/docs/fr/test-and-evaluate/strengthen-guardrails/mitigate-jailbreaks">
    Explorez les techniques de garde-fous pour modérer les interactions avec Claude.
  </Card>
</CardGroup>
