feat(ai): AiService (Anthropic adapter), GenerateSlug action
Implement AI domain with Anthropic API integration for slug generation. Adds GenerateSlug action for URL-to-slug transformation and GenerateAbVariants for A/B test variants. Includes test coverage for GenerateSlug action with mocked AiService. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>main
parent
79da7502cd
commit
c193e482ac
|
|
@ -0,0 +1,26 @@
|
|||
<?php
|
||||
|
||||
namespace App\Domains\Ai\Actions;
|
||||
|
||||
use App\Domains\Ai\Services\AiService;
|
||||
|
||||
class GenerateAbVariants
|
||||
{
|
||||
public function __construct(private AiService $ai) {}
|
||||
|
||||
public function handle(string $targetUrl, int $count = 3): array
|
||||
{
|
||||
$prompt = "Generate {$count} A/B test URL slug variants (3-8 chars each, lowercase, hyphens only, comma-separated) for: {$targetUrl}. Reply with ONLY the comma-separated slugs.";
|
||||
|
||||
$result = $this->ai->complete($prompt);
|
||||
|
||||
if (empty($result)) {
|
||||
return [];
|
||||
}
|
||||
|
||||
return array_map(
|
||||
fn($s) => preg_replace('/[^a-z0-9-]/', '', strtolower(trim($s))),
|
||||
explode(',', $result)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,19 @@
|
|||
<?php
|
||||
|
||||
namespace App\Domains\Ai\Actions;
|
||||
|
||||
use App\Domains\Ai\Services\AiService;
|
||||
|
||||
class GenerateSlug
|
||||
{
|
||||
public function __construct(private AiService $ai) {}
|
||||
|
||||
public function handle(string $targetUrl): string
|
||||
{
|
||||
$prompt = "Generate a short, memorable URL slug (3-8 chars, lowercase, hyphens only) for this URL: {$targetUrl}. Reply with ONLY the slug, no explanation.";
|
||||
|
||||
$slug = $this->ai->complete($prompt);
|
||||
|
||||
return preg_replace('/[^a-z0-9-]/', '', strtolower($slug));
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,29 @@
|
|||
<?php
|
||||
|
||||
namespace App\Domains\Ai\Services;
|
||||
|
||||
use Illuminate\Support\Facades\Http;
|
||||
|
||||
class AiService
|
||||
{
|
||||
public function complete(string $prompt, string $model = 'claude-sonnet-4-6'): string
|
||||
{
|
||||
$apiKey = config('services.anthropic.api_key');
|
||||
|
||||
if (! $apiKey) {
|
||||
return '';
|
||||
}
|
||||
|
||||
$response = Http::withHeaders([
|
||||
'x-api-key' => $apiKey,
|
||||
'anthropic-version' => '2023-06-01',
|
||||
'content-type' => 'application/json',
|
||||
])->post('https://api.anthropic.com/v1/messages', [
|
||||
'model' => $model,
|
||||
'max_tokens' => 256,
|
||||
'messages' => [['role' => 'user', 'content' => $prompt]],
|
||||
]);
|
||||
|
||||
return trim($response->json('content.0.text') ?? '');
|
||||
}
|
||||
}
|
||||
|
|
@ -35,4 +35,8 @@ return [
|
|||
],
|
||||
],
|
||||
|
||||
'anthropic' => [
|
||||
'api_key' => env('ANTHROPIC_API_KEY'),
|
||||
],
|
||||
|
||||
];
|
||||
|
|
|
|||
|
|
@ -0,0 +1,16 @@
|
|||
<?php
|
||||
|
||||
use App\Domains\Ai\Actions\GenerateSlug;
|
||||
use App\Domains\Ai\Services\AiService;
|
||||
|
||||
it('generates slug from URL via AI service', function () {
|
||||
$mockAi = Mockery::mock(AiService::class);
|
||||
$mockAi->shouldReceive('complete')
|
||||
->once()
|
||||
->andReturn('best-promo');
|
||||
|
||||
$action = new GenerateSlug($mockAi);
|
||||
$slug = $action->handle('https://example.com/summer-sale-2026');
|
||||
|
||||
expect($slug)->toBe('best-promo');
|
||||
});
|
||||
Loading…
Reference in New Issue