Score artwork comments with local signatures plus Together AI, and optionally require Turnstile before posting.
67 lines
2.3 KiB
PHP
67 lines
2.3 KiB
PHP
<?php
|
|
|
|
use App\Services\Moderation\TogetherCommentSpamClassifier;
|
|
use Illuminate\Support\Facades\Http;
|
|
use Tests\TestCase;
|
|
|
|
uses(TestCase::class);
|
|
|
|
beforeEach(function (): void {
|
|
config([
|
|
'comment_spam.ai.api_key' => 'test-key',
|
|
'comment_spam.ai.base_url' => 'https://api.together.test/v1',
|
|
'comment_spam.ai.model' => 'meta-llama/Llama-3.2-3B-Instruct-Turbo',
|
|
]);
|
|
});
|
|
|
|
it('classifies using the strict Together JSON contract', function (string $model): void {
|
|
config(['comment_spam.ai.model' => $model]);
|
|
Http::fake([
|
|
'https://api.together.test/*' => Http::response([
|
|
'choices' => [['message' => ['content' => '{"spam":true,"confidence":0.95,"reason":"Unsolicited promotion."}']]],
|
|
]),
|
|
]);
|
|
|
|
$result = app(TogetherCommentSpamClassifier::class)->classify('Buy now at example.test');
|
|
|
|
expect($result->spam)->toBeTrue()
|
|
->and($result->confidence)->toBe(0.95)
|
|
->and($result->provider)->toBe('together')
|
|
->and($result->model)->toBe($model);
|
|
})->with([
|
|
'Llama' => ['meta-llama/Llama-3.2-3B-Instruct-Turbo'],
|
|
'Bonsai' => ['Prism-ML/Ternary-Bonsai-27B'],
|
|
]);
|
|
|
|
it('rejects an unsupported configured model before making an HTTP request', function (): void {
|
|
config(['comment_spam.ai.model' => 'some/unsupported-model']);
|
|
Http::fake();
|
|
|
|
expect(fn () => app(TogetherCommentSpamClassifier::class)->classify('hello'))
|
|
->toThrow(RuntimeException::class, 'Unsupported Together AI comment spam model.');
|
|
|
|
Http::assertNothingSent();
|
|
});
|
|
|
|
it('rejects malformed or out of range classifier output', function (array $json): void {
|
|
Http::fake([
|
|
'https://api.together.test/*' => Http::response([
|
|
'choices' => [['message' => ['content' => json_encode($json)]]],
|
|
]),
|
|
]);
|
|
|
|
expect(fn () => app(TogetherCommentSpamClassifier::class)->classify('hello'))
|
|
->toThrow(RuntimeException::class);
|
|
})->with([
|
|
[['spam' => 'true', 'confidence' => 0.9, 'reason' => 'bad type']],
|
|
[['spam' => true, 'confidence' => 1.1, 'reason' => 'out of range']],
|
|
[['spam' => true, 'confidence' => 0.9]],
|
|
]);
|
|
|
|
it('fails closed when Together is not configured', function (): void {
|
|
config(['comment_spam.ai.api_key' => '']);
|
|
|
|
expect(fn () => app(TogetherCommentSpamClassifier::class)->classify('hello'))
|
|
->toThrow(RuntimeException::class);
|
|
});
|