79 خطوط
4.5 KiB
PHP
79 خطوط
4.5 KiB
PHP
<?php
|
|
|
|
namespace App\Modules\AI\Infrastructure;
|
|
|
|
use App\Modules\AI\Domain\AiProvider;
|
|
use Illuminate\Support\Str;
|
|
|
|
final class LocalStructuringProvider implements AiProvider
|
|
{
|
|
public function id(): string
|
|
{
|
|
return 'local-structuring-v1';
|
|
}
|
|
|
|
public function external(): bool
|
|
{
|
|
return false;
|
|
}
|
|
|
|
public function chat(string $prompt, ?string $systemPrompt = null): string
|
|
{
|
|
return trim(preg_replace('/\s+/u', ' ', strip_tags($prompt)) ?? '');
|
|
}
|
|
|
|
public function structure(array $fragments, array $options): array
|
|
{
|
|
$language = $options['language'] ?? 'fa';
|
|
$topic = trim((string) ($options['topic'] ?? ''));
|
|
$title = $topic !== '' ? $topic : trim((string) ($fragments[0]['heading'] ?? ''));
|
|
if ($title === '') {
|
|
$title = $language === 'en' ? 'Imported learning draft' : 'پیشنویس محتوای واردشده';
|
|
}
|
|
$lessonCount = max(1, min(12, (int) ($options['lessonCount'] ?? count($fragments) ?: 1)));
|
|
$selected = array_slice($fragments, 0, $lessonCount);
|
|
if ($selected === []) {
|
|
$selected = [['id' => 'generated', 'locator' => null, 'heading' => $title, 'content' => (string) ($options['objective'] ?? $topic)]];
|
|
}
|
|
$lessons = array_map(function (array $fragment, int $index) use ($language): array {
|
|
$heading = trim((string) ($fragment['heading'] ?? ''));
|
|
$content = trim($fragment['content']);
|
|
|
|
return [
|
|
'title' => $heading !== '' ? Str::limit($heading, 150, '') : ($language === 'en' ? 'Lesson '.($index + 1) : 'درس '.($index + 1)),
|
|
'summary' => Str::limit($content, 500),
|
|
'sourceFragmentIds' => [$fragment['id']],
|
|
'blocks' => $content === '' ? [] : [['type' => 'text', 'schemaVersion' => 1, 'data' => ['html' => '<p>'.nl2br(e($content)).'</p>']]],
|
|
];
|
|
}, $selected, array_keys($selected));
|
|
|
|
return [
|
|
'schemaVersion' => 1,
|
|
'providerDisclosure' => 'Deterministic local structuring; no external generative model was used.',
|
|
'title' => $title,
|
|
'description' => (string) ($options['objective'] ?? ($language === 'en' ? 'Draft generated from the supplied source for Designer review.' : 'پیشنویس تولیدشده از منبع ورودی برای بازبینی طراح.')),
|
|
'settings' => collect($options)->only(['audience', 'objective', 'duration', 'difficulty', 'language', 'tone', 'assessmentLevel', 'interactionDensity'])->all(),
|
|
'modules' => [['title' => $language === 'en' ? 'Core content' : 'محتوای اصلی', 'lessons' => $lessons]],
|
|
];
|
|
}
|
|
|
|
public function assist(string $operation, string $content, array $context): array
|
|
{
|
|
$plain = trim(preg_replace('/\s+/u', ' ', strip_tags($content)) ?? '');
|
|
$result = match ($operation) {
|
|
'generate_lesson' => ['title' => Str::limit($plain, 80), 'outline' => ['مقدمه', 'نکات کلیدی', 'تمرین کاربردی'], 'draft' => $plain],
|
|
'generate_quiz' => ['prompt' => 'کدام گزینه با محتوای درس سازگار است؟', 'options' => [Str::limit($plain, 120), 'گزینه نیازمند بازبینی طراح'], 'answerIndex' => 0],
|
|
'rewrite' => $plain,
|
|
'shorten' => Str::limit($plain, max(120, (int) floor(mb_strlen($plain) * 0.6))),
|
|
'simplify' => preg_replace('/[؛:]/u', '.', $plain) ?? $plain,
|
|
'split_lesson' => collect(preg_split('/(?<=[.!؟])\s+/u', $plain) ?: [])->chunk(3)->map(fn ($chunk) => $chunk->implode(' '))->values()->all(),
|
|
'generate_examples' => ['اصل یا مفهوم: '.Str::limit($plain, 180), 'مثال کاربردی باید توسط طراح با زمینه سازمان تکمیل شود.'],
|
|
'add_interaction' => ['type' => 'flashcard', 'front' => Str::limit($plain, 180), 'back' => 'پاسخ باید توسط طراح تأیید شود.'],
|
|
'audit_course', 'check_objectives', 'check_assessment_alignment' => ['summary' => 'Local structural audit completed.', 'issues' => $plain === '' ? ['Content is empty.'] : [], 'requiresDesignerReview' => true],
|
|
default => $plain,
|
|
};
|
|
|
|
return ['schemaVersion' => 1, 'operation' => $operation, 'proposal' => $result, 'context' => collect($context)->only(['entityType', 'entityId'])->all(), 'providerDisclosure' => 'Local deterministic assistant; review before accepting.'];
|
|
}
|
|
}
|