IModerationService

This commit is contained in:
Paul Schneider 2026-05-30 18:20:17 +01:00
commit 1aafb7cc7d
10 changed files with 162 additions and 10 deletions

View file

@ -0,0 +1,90 @@
using Yavsc.Moderation;
using Yavsc.Abstract.Interfaces;
using Anthropic.SDK;
using Anthropic.SDK.Messaging;
using Anthropic.SDK.Constants;
using Anthropic.SDK.Models;
using Newtonsoft.Json;
using Microsoft.Extensions.Configuration;
using System.Text.Json;
public class ClaudeModerationService : IModerationService
{
private readonly AnthropicClient _client;
private readonly float _autoApproveThreshold;
private readonly float _autoRejectThreshold;
public ClaudeModerationService(
AnthropicClient client,
IConfiguration config)
{
_client = client;
_autoApproveThreshold = config.GetValue<float>(
"Moderation:AutoApproveThreshold", 0.7f);
_autoRejectThreshold = config.GetValue<float>(
"Moderation:AutoRejectThreshold", 0.9f);
}
public async Task<ModerationResult> ModerateAsync(string content, string context)
{
var prompt = $$"""
Tu es un modérateur pour une plateforme de mise en relation prestataires/clients.
Contexte : {{context}}
Contenu à modérer : {{content}}
Réponds UNIQUEMENT en JSON :
{
"action": "approved" | "rejected" | "needs_review",
"reason": "explication courte",
"confidence": 0.0 à 1.0
}
""";
var response = await _client.Messages.GetClaudeMessageAsync(
new MessageParameters
{
Model = AnthropicModels.Claude45Haiku, // Haiku : rapide et économique
MaxTokens = 256,
Messages = [new Message(RoleType.User, prompt)]
});
var text = response.Content
.OfType<TextContent>()
.FirstOrDefault()?.Text ?? string.Empty;
return ParseResult(text);
}
private ModerationResult ParseResult(string json)
{
try
{
var doc = JsonDocument.Parse(json);
var root = doc.RootElement;
var actionStr = root.GetProperty("action").GetString();
var reason = root.GetProperty("reason").GetString() ?? string.Empty;
var confidence = root.GetProperty("confidence").GetSingle();
var action = actionStr switch
{
"approved" => confidence >= _autoApproveThreshold
? ModerationAction.Approved
: ModerationAction.NeedsReview,
"rejected" => confidence >= _autoRejectThreshold
? ModerationAction.Rejected
: ModerationAction.NeedsReview,
"needs_review" => ModerationAction.NeedsReview,
_ => ModerationAction.NeedsReview
};
return new ModerationResult(action, reason, confidence);
}
catch
{
return new ModerationResult(
ModerationAction.NeedsReview,
"Erreur de parsing de la réponse",
0f);
}
}
}

View file

@ -0,0 +1,11 @@
using Yavsc.Abstract.Interfaces;
using Yavsc.Moderation;
public class MockModerationService : IModerationService
{
public Task<ModerationResult> ModerateAsync(string content, string context)
=> Task.FromResult(new ModerationResult(
ModerationAction.Approved,
"Mock modération — API non configurée",
1.0f));
}

View file

@ -8,6 +8,7 @@
<RepositoryUrl>https://github.com/pazof/yavsc</RepositoryUrl>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Anthropic.SDK" />
<PackageReference Include="HigginsSoft.IdentityServer8.EntityFramework" />
<PackageReference Include="Magick.NET-Q8-AnyCPU" />
<PackageReference Include="Npgsql.EntityFrameworkCore.PostgreSQL" />