feat: Add AiLessonEnhancerService to automatically generate NotebookLM-style cheat sheets and quizzes
This commit is contained in:
@@ -0,0 +1,102 @@
|
||||
<?php
|
||||
|
||||
namespace App\Services;
|
||||
|
||||
use App\Core\Database;
|
||||
use App\Core\Env;
|
||||
|
||||
class AiLessonEnhancerService
|
||||
{
|
||||
/**
|
||||
* Extracts the lively script, cheat sheet, and Socratic quiz using Gemini.
|
||||
*/
|
||||
public static function enhanceLesson(int $lessonId): bool
|
||||
{
|
||||
$lesson = Database::selectOne(
|
||||
"SELECT l.*, c.subject_id FROM lessons l JOIN courses c ON l.course_id = c.id WHERE l.id = ?",
|
||||
[$lessonId]
|
||||
);
|
||||
|
||||
if (!$lesson || empty($lesson['markdown_content'])) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$prompt = self::buildPrompt($lesson['title'], $lesson['markdown_content']);
|
||||
$result = self::callGemini($prompt);
|
||||
|
||||
if (!$result) return false;
|
||||
|
||||
// Save to Database
|
||||
Database::execute(
|
||||
"UPDATE lessons SET cheat_sheet_markdown = ?, socratic_quiz_json = ? WHERE id = ?",
|
||||
[
|
||||
$result['cheat_sheet'] ?? null,
|
||||
json_encode($result['socratic_quiz'] ?? []),
|
||||
$lessonId
|
||||
]
|
||||
);
|
||||
|
||||
// Return true if successful
|
||||
return true;
|
||||
}
|
||||
|
||||
private static function buildPrompt(string $title, string $content): string
|
||||
{
|
||||
return "أنت خبير تعليمي وصانع محتوى محترف (تعمل بآلية مشابهة لـ Google NotebookLM).
|
||||
بناءً على نص الدرس التالي، قم بتوليد حزمة تعليمية متكاملة بصيغة JSON فقط.
|
||||
|
||||
أريد الإجابة بصيغة JSON صارمة تحتوي على المفاتيح التالية:
|
||||
{
|
||||
\"video_script\": \"سيناريو حواري حيوي للمعلم يشرح الدرس بحماس مع التوجيهات البصرية.\",
|
||||
\"cheat_sheet\": \"ملخص الدرس بخطوات سريعة ومبسطة جداً (بصيغة Markdown).\",
|
||||
\"socratic_quiz\": {
|
||||
\"question\": \"سؤال ذكي متعدد الخيارات\",
|
||||
\"options\": [\"خيار A\", \"خيار B\", \"خيار C\", \"خيار D\"],
|
||||
\"correct_answer\": \"النص الدقيق للخيار الصحيح\",
|
||||
\"explanation\": \"تفسير سبب صحة هذا الخيار\"
|
||||
}
|
||||
}
|
||||
|
||||
عنوان الدرس: {$title}
|
||||
محتوى الدرس: {$content}";
|
||||
}
|
||||
|
||||
private static function callGemini(string $prompt): ?array
|
||||
{
|
||||
$apiKey = Env::get('GEMINI_API_KEY');
|
||||
if (!$apiKey) {
|
||||
$keys = explode(',', getenv('GEMINI_API_KEY'));
|
||||
$apiKey = trim($keys[0] ?? '');
|
||||
}
|
||||
if (!$apiKey) return null;
|
||||
|
||||
$model = Env::get('GEMINI_MODEL') ?: 'gemini-1.5-flash';
|
||||
$url = "https://generativelanguage.googleapis.com/v1beta/models/{$model}:generateContent?key={$apiKey}";
|
||||
|
||||
$payload = [
|
||||
'contents' => [['parts' => [['text' => $prompt]]]],
|
||||
'generationConfig' => ['responseMimeType' => 'application/json', 'temperature' => 0.7]
|
||||
];
|
||||
|
||||
$ch = curl_init($url);
|
||||
curl_setopt_array($ch, [
|
||||
CURLOPT_POST => true,
|
||||
CURLOPT_POSTFIELDS => json_encode($payload),
|
||||
CURLOPT_HTTPHEADER => ['Content-Type: application/json'],
|
||||
CURLOPT_RETURNTRANSFER => true,
|
||||
CURLOPT_TIMEOUT => 60
|
||||
]);
|
||||
$res = curl_exec($ch);
|
||||
curl_close($ch);
|
||||
|
||||
if (!$res) return null;
|
||||
|
||||
$json = json_decode($res, true);
|
||||
$text = $json['candidates'][0]['content']['parts'][0]['text'] ?? '';
|
||||
|
||||
$text = preg_replace('/^```json\s*/i', '', $text);
|
||||
$text = preg_replace('/```\s*$/i', '', $text);
|
||||
|
||||
return json_decode(trim($text), true);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user