IModerationService
This commit is contained in:
parent
069b9df478
commit
1aafb7cc7d
10 changed files with 162 additions and 10 deletions
12
.env.sample
12
.env.sample
|
|
@ -4,6 +4,14 @@ POSTGRES_PORT=5432
|
|||
POSTGRES_DB=yavsc
|
||||
POSTGRES_USER=yavsc
|
||||
POSTGRES_PASSWORD=lame-YAVSC_CONNECTION_PASSWORD
|
||||
DESTDIR=/srv/www/yavsc
|
||||
|
||||
ASPNETCORE_ConnectionStrings__YavscConnection=Server=$POSTGRES_HOST;Port=$POSTGRES_PORT;Database=$POSTGRES_DB;Username=$POSTGRES_USER;Password=$POSTGRES_PASSWORD;
|
||||
|
||||
ANTHROPIC_API_KEY=<votre-clé-api-anthropic>
|
||||
MODERATION_AUTO_REJECT_THRESHOLD=0.9
|
||||
MODERATION_AUTO_APPROVE_THRESHOLD=0.7
|
||||
# Limite par appel
|
||||
ANTHROPIC_MAX_TOKENS=256 # la modération n'a pas besoin de plus
|
||||
|
||||
# Choisis le bon modèle selon l'usage
|
||||
# - Modération : claude-haiku-4-5 (rapide, pas cher)
|
||||
# - Aide rédaction devis : claude-sonnet-4-6 (meilleur équilibre)
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@
|
|||
<ManagePackageVersionsCentrally>true</ManagePackageVersionsCentrally>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<PackageVersion Include="Anthropic.SDK" Version="5.10.0" />
|
||||
<PackageVersion Include="AsciiDocSharp" Version="0.2.0" />
|
||||
<PackageVersion Include="AsciiDocSharp.Converters.Html" Version="0.2.0" />
|
||||
<PackageVersion Include="Avalonia" Version="12.0.4" />
|
||||
|
|
@ -63,10 +64,10 @@
|
|||
<PackageVersion Include="Selenium.WebDriver" Version="4.44.0" />
|
||||
<PackageVersion Include="Serilog.AspNetCore" Version="10.0.0" />
|
||||
<PackageVersion Include="SixLabors.ImageSharp" Version="4.0.0" />
|
||||
<PackageVersion Include="Swashbuckle.AspNetCore" Version="10.1.7" />
|
||||
<PackageVersion Include="Swashbuckle.AspNetCore" Version="10.2.0" />
|
||||
<PackageVersion Include="System.Security.Cryptography.Pkcs" Version="10.0.8" />
|
||||
<PackageVersion Include="xunit" Version="2.9.3" />
|
||||
<PackageVersion Include="xunit.runner.visualstudio" Version="3.1.5" />
|
||||
<PackageVersion Include="Yavsc.Abstract" Version="1.0.6-rc18" />
|
||||
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
8
src/Yavsc.Abstract/Interfaces/IModerationService.cs
Normal file
8
src/Yavsc.Abstract/Interfaces/IModerationService.cs
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
using Yavsc.Moderation;
|
||||
|
||||
namespace Yavsc.Abstract.Interfaces;
|
||||
|
||||
public interface IModerationService
|
||||
{
|
||||
Task<ModerationResult> ModerateAsync(string content, string context);
|
||||
}
|
||||
3
src/Yavsc.Abstract/Moderation/ModerationAction.cs
Normal file
3
src/Yavsc.Abstract/Moderation/ModerationAction.cs
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
namespace Yavsc.Moderation;
|
||||
|
||||
public enum ModerationAction { Approved, Rejected, NeedsReview }
|
||||
7
src/Yavsc.Abstract/Moderation/ModerationResult.cs
Normal file
7
src/Yavsc.Abstract/Moderation/ModerationResult.cs
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
namespace Yavsc.Moderation;
|
||||
|
||||
public record ModerationResult(
|
||||
ModerationAction Action,
|
||||
string Reason,
|
||||
float ConfidenceScore
|
||||
);
|
||||
|
|
@ -1,5 +1,7 @@
|
|||
|
||||
using Anthropic.SDK;
|
||||
using Microsoft.AspNetCore;
|
||||
using Yavsc.Abstract.Interfaces;
|
||||
using Yavsc.Extensions;
|
||||
|
||||
namespace Yavsc
|
||||
|
|
@ -10,11 +12,28 @@ namespace Yavsc
|
|||
{
|
||||
var builder = WebApplication.CreateBuilder(args);
|
||||
|
||||
// Anthropic client
|
||||
builder.Services.AddSingleton<AnthropicClient>(_ =>
|
||||
new AnthropicClient(
|
||||
new APIAuthentication(
|
||||
builder.Configuration["ANTHROPIC_API_KEY"]
|
||||
?? throw new InvalidOperationException("ANTHROPIC_API_KEY manquante")
|
||||
)
|
||||
)
|
||||
);
|
||||
|
||||
// Service de modération
|
||||
if (builder.Environment.IsDevelopment())
|
||||
builder.Services.AddScoped<IModerationService, MockModerationService>();
|
||||
else
|
||||
builder.Services.AddScoped<IModerationService, ClaudeModerationService>();
|
||||
|
||||
builder.Configuration
|
||||
.AddJsonFile("appsettings.json")
|
||||
.AddJsonFile($"appsettings.{builder.Environment.EnvironmentName}.json", optional: true)
|
||||
.AddEnvironmentVariables()
|
||||
.Build();
|
||||
|
||||
var app = await builder.ConfigureWebAppServices().ConfigurePipeline();
|
||||
app.Run();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -77,5 +77,9 @@
|
|||
},
|
||||
"Kyc": {
|
||||
"HmacSecret": "*** via dotnet user-secrets ou variable d'environnement ***"
|
||||
},
|
||||
"Moderation": {
|
||||
"AutoApproveThreshold": 0.7,
|
||||
"AutoRejectThreshold": 0.9
|
||||
}
|
||||
}
|
||||
|
|
|
|||
90
src/Yavsc.Server/Services/ClaudeModerationService.cs
Normal file
90
src/Yavsc.Server/Services/ClaudeModerationService.cs
Normal 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
11
src/Yavsc.Server/Services/MockModerationService.cs
Normal file
11
src/Yavsc.Server/Services/MockModerationService.cs
Normal 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));
|
||||
}
|
||||
|
|
@ -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" />
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue