feat: certificate page for print, API certificate data, AI prompts for full lessons
- Certificate: page /certificate/[courseId] with print-friendly design, GET /certificates/:courseId/data - Buttons 'Получить сертификат' open certificate page instead of data-URL - AI: prompts for longer courses (more chapters/lessons), full detailed lesson content with examples (1000–1500+ words) Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@ -143,10 +143,10 @@ export class OpenRouterProvider {
|
||||
Пользователь хочет создать курс. Твоя задача - задать уточняющие вопросы,
|
||||
чтобы лучше понять его потребности и создать максимально релевантный курс.
|
||||
|
||||
Сгенерируй 3-5 вопросов. Обязательно включи вопрос про объём курса:
|
||||
- Короткий (2-4 главы, введение в тему)
|
||||
- Средний (4-7 глав, хорошее покрытие)
|
||||
- Длинный / полный (6-12 глав, глубокое погружение)
|
||||
Сгенерируй 3-5 вопросов. Обязательно включи вопрос про объём курса (важно для длины):
|
||||
- Короткий (3-4 главы, по 2-4 урока — только введение в тему)
|
||||
- Средний (5-7 глав, по 4-6 уроков — полноценное покрытие)
|
||||
- Длинный / полный (7-12 глав, по 5-8 уроков — глубокое погружение, рекомендуемый вариант для серьёзного обучения)
|
||||
|
||||
Остальные вопросы: целевая аудитория, глубина материала, специфические темы.
|
||||
|
||||
@ -198,13 +198,13 @@ export class OpenRouterProvider {
|
||||
const systemPrompt = `Ты - эксперт по созданию образовательных курсов.
|
||||
Создай структуру курса на основе запроса пользователя и его ответов на уточняющие вопросы.
|
||||
|
||||
ОБЪЁМ КУРСА (соблюдай строго по ответам пользователя):
|
||||
- Если пользователь выбрал короткий курс / введение: 2–4 главы, в каждой 2–4 урока. estimatedTotalHours: 2–8.
|
||||
- Если средний курс: 4–7 глав, в каждой 3–5 уроков. estimatedTotalHours: 8–20.
|
||||
- Если длинный / полный курс: 6–12 глав, в каждой 4–8 уроков. estimatedTotalHours: 15–40.
|
||||
- Если объём не указан — предложи средний (4–6 глав по 3–5 уроков).
|
||||
ОБЪЁМ КУРСА (соблюдай по ответам; при сомнении выбирай более полный вариант):
|
||||
- Короткий / введение: не менее 3 глав, в каждой по 3–4 урока. estimatedTotalHours: 4–10.
|
||||
- Средний: 5–7 глав, в каждой по 4–6 уроков. estimatedTotalHours: 10–25.
|
||||
- Длинный / полный: 7–12 глав, в каждой по 5–8 уроков. estimatedTotalHours: 20–45.
|
||||
- Если объём не указан — делай средний или длинный: 5–7 глав, по 4–6 уроков в главе (не менее 25 уроков в курсе).
|
||||
|
||||
Укажи примерное время на каждый урок (estimatedMinutes: 10–45). estimatedTotalHours = сумма уроков.
|
||||
Укажи примерное время на каждый урок (estimatedMinutes: 15–45, чаще 20–35). estimatedTotalHours = сумма уроков.
|
||||
Определи сложность (beginner|intermediate|advanced). Добавь релевантные теги.
|
||||
|
||||
Ответь в формате JSON со структурой:
|
||||
@ -281,32 +281,27 @@ ${Object.entries(answers)
|
||||
log.request('generateLessonContent', model);
|
||||
log.info(`Generating content for: "${lessonTitle}" (Chapter: "${chapterTitle}")`);
|
||||
|
||||
const systemPrompt = `Ты - эксперт по созданию образовательного контента.
|
||||
Пиши содержание урока СРАЗУ в форматированном виде — в формате TipTap JSON. Каждый блок контента должен быть правильным узлом TipTap (heading, paragraph, bulletList, orderedList, blockquote, codeBlock, image).
|
||||
const systemPrompt = `Ты - эксперт по созданию образовательного контента. Пиши ПОЛНЫЙ, ПОДРОБНЫЙ материал урока — не поверхностный обзор, а глубокое раскрытие темы с объяснениями и примерами.
|
||||
|
||||
ФОРМАТИРОВАНИЕ (используй обязательно):
|
||||
- Заголовки: { "type": "heading", "attrs": { "level": 1|2|3 }, "content": [{ "type": "text", "text": "..." }] }
|
||||
- Параграфы: { "type": "paragraph", "content": [{ "type": "text", "text": "..." }] } — для выделения используй "marks": [{ "type": "bold" }] или [{ "type": "italic" }]
|
||||
- Списки: bulletList > listItem > paragraph; orderedList > listItem > paragraph
|
||||
- Цитаты: { "type": "blockquote", "content": [{ "type": "paragraph", "content": [...] }] }
|
||||
- Код: { "type": "codeBlock", "attrs": { "language": "javascript"|"python"|"text" }, "content": [{ "type": "text", "text": "код" }] }
|
||||
- Mermaid-диаграммы: { "type": "codeBlock", "attrs": { "language": "mermaid" }, "content": [{ "type": "text", "text": "graph LR\\n A --> B" }] } — вставляй где уместно (схемы, процессы, связи)
|
||||
- Картинки не генерируй (src нельзя выдумывать); если нужна иллюстрация — опиши в тексте или предложи место для изображения
|
||||
ГЛАВНОЕ ТРЕБОВАНИЕ — СОДЕРЖАТЕЛЬНОСТЬ:
|
||||
- Материал должен быть полным и подробным: объясняй понятия по шагам, раскрывай причины и следствия, давай контекст.
|
||||
- Обязательно включай практические примеры: код, числа, сценарии использования. Без примеров урок считается неполным.
|
||||
- Описывай не только "что", но и "зачем" и "как": типичные ошибки, лучшие практики, нюансы.
|
||||
- Каждую важную мысль подкрепляй пояснением или примером. Избегай перечисления фактов без раскрытия.
|
||||
|
||||
ОБЪЁМ: зависит от темы. Короткий урок: 300–600 слов (3–5 блоков). Средний: 600–1200 слов. Длинный: 1200–2500 слов. Структура: заголовок, введение, 2–4 секции с подзаголовками, примеры/код/списки, резюме.
|
||||
СТРУКТУРА УРОКА (соблюдай):
|
||||
- Заголовок (h1), краткое введение в тему (2–3 абзаца).
|
||||
- 4–7 смысловых секций с подзаголовками (h2/h3). В каждой секции: развёрнутый текст, при необходимости списки, примеры, блоки кода.
|
||||
- Примеры и код: минимум 1–2 рабочих примера на урок (codeBlock с пояснением до/после). Для технических тем — больше.
|
||||
- Резюме или выводы в конце (что важно запомнить, как применить).
|
||||
|
||||
ФОРМАТ — TipTap JSON (heading, paragraph, bulletList, orderedList, blockquote, codeBlock с language). Mermaid — где уместно (схемы, процессы). Картинки не выдумывай.
|
||||
|
||||
ОБЪЁМ: не менее 1000–1500 слов на урок. Сложные темы — 1800–3000 слов. Короткие абзацы из 1–2 предложений без примеров запрещены.
|
||||
|
||||
Уровень: ${context.difficulty}. ${context.targetAudience ? `Аудитория: ${context.targetAudience}` : ''}
|
||||
|
||||
Ответь только валидным JSON:
|
||||
{
|
||||
"content": {
|
||||
"type": "doc",
|
||||
"content": [
|
||||
{ "type": "heading", "attrs": { "level": 1 }, "content": [{ "type": "text", "text": "Заголовок" }] },
|
||||
{ "type": "paragraph", "content": [{ "type": "text", "text": "Текст..." }] }
|
||||
]
|
||||
}
|
||||
}`;
|
||||
Ответь только валидным JSON: { "content": { "type": "doc", "content": [ ... ] } }`;
|
||||
|
||||
return this.withRetry(async () => {
|
||||
const response = await this.client.chat.completions.create({
|
||||
@ -319,7 +314,7 @@ ${Object.entries(answers)
|
||||
Глава: "${chapterTitle}"
|
||||
Урок: "${lessonTitle}"
|
||||
|
||||
Создай содержание урока сразу в TipTap JSON: заголовки (heading), параграфы (paragraph), списки (bulletList/orderedList), цитаты (blockquote), блоки кода (codeBlock) и при необходимости Mermaid-диаграммы (codeBlock с "language": "mermaid"). Объём — по теме урока (короткий/средний/длинный).`,
|
||||
Создай полный и подробный урок в TipTap JSON. Обязательно: развёрнутые объяснения, минимум 1–2 примера или блока кода с пояснениями, описание нюансов и практические советы. Не пиши поверхностно — материал должен быть глубоким и пригодным для самостоятельного изучения. Объём не менее 1000–1500 слов.`,
|
||||
},
|
||||
],
|
||||
response_format: { type: 'json_object' },
|
||||
|
||||
Reference in New Issue
Block a user