16 KiB
Challenge Service - Руководство для преподавателей
Специальное руководство для пользователей с ролью teacher в Keycloak.
Требования
Для создания и редактирования заданий и цепочек необходимо:
- Быть авторизованным через Keycloak
- Иметь роль
teacherв клиентеjournal
Особенности для преподавателей
1. Скрытые инструкции для LLM
При создании заданий вы можете добавить скрытые инструкции (hiddenInstructions), которые:
- ✅ Видны только преподавателям
- ✅ Передаются в LLM при проверке
- ❌ Не видны студентам
- ❌ Не отображаются в интерфейсе студента
Примеры использования
Пример 1: Контроль сложности
{
"title": "Реализовать сортировку",
"description": "Напишите функцию для сортировки массива чисел",
"hiddenInstructions": "Проверь, чтобы сложность алгоритма была не хуже O(n log n). Не принимай bubble sort или простые O(n²) решения."
}
Пример 2: Специфичные требования
{
"title": "REST API endpoint",
"description": "Создайте endpoint для получения списка пользователей",
"hiddenInstructions": "Обязательно должна быть пагинация, обработка ошибок и валидация параметров. Если чего-то не хватает - укажи в feedback."
}
Пример 3: Стиль кода
{
"title": "Компонент React",
"description": "Создайте компонент для отображения карточки товара",
"hiddenInstructions": "Проверь использование TypeScript, правильное применение хуков, и соблюдение best practices React. Код должен быть чистым и читаемым."
}
Пример 4: Тонкая настройка проверки
{
"title": "SQL запрос",
"description": "Напишите запрос для выборки активных пользователей",
"hiddenInstructions": "Даже если запрос работает, но неоптимален (например, использует SELECT *), укажи на это в feedback и попроси оптимизировать."
}
2. Создание задания через API
С помощью Keycloak токена
// Получение токена (пример для frontend)
const keycloakToken = keycloak.token // из keycloak-js
// Создание задания
async function createTask(title: string, description: string, hiddenInstructions: string) {
const response = await fetch('http://localhost:8082/api/challenge/task', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Authorization': `Bearer ${keycloakToken}`
},
body: JSON.stringify({
title,
description,
hiddenInstructions
})
})
return response.json()
}
С помощью curl
# Получить токен от Keycloak
TOKEN="your_keycloak_token"
# Создать задание
curl -X POST http://localhost:8082/api/challenge/task \
-H "Content-Type: application/json" \
-H "Authorization: Bearer $TOKEN" \
-d '{
"title": "Написать функцию",
"description": "# Задание\n\nНапишите функцию для...",
"hiddenInstructions": "Проверь производительность и обработку ошибок"
}'
3. UI компоненты для преподавателей
TaskForm с скрытыми инструкциями
import { useState } from 'react'
import ReactMarkdown from 'react-markdown'
interface TaskFormProps {
onSubmit: (task: { title: string; description: string; hiddenInstructions: string }) => void
}
export function TeacherTaskForm({ onSubmit }: TaskFormProps) {
const [title, setTitle] = useState('')
const [description, setDescription] = useState('')
const [hiddenInstructions, setHiddenInstructions] = useState('')
const [showPreview, setShowPreview] = useState(false)
const handleSubmit = (e: React.FormEvent) => {
e.preventDefault()
onSubmit({ title, description, hiddenInstructions })
}
return (
<form onSubmit={handleSubmit}>
<div className="form-group">
<label>Заголовок задания</label>
<input
type="text"
value={title}
onChange={(e) => setTitle(e.target.value)}
required
maxLength={255}
/>
</div>
<div className="form-group">
<label>Описание (Markdown)</label>
<div className="tabs">
<button type="button" onClick={() => setShowPreview(false)}>Редактор</button>
<button type="button" onClick={() => setShowPreview(true)}>Превью</button>
</div>
{showPreview ? (
<div className="markdown-preview">
<ReactMarkdown>{description}</ReactMarkdown>
</div>
) : (
<textarea
value={description}
onChange={(e) => setDescription(e.target.value)}
required
rows={15}
placeholder="# Заголовок\n\nОписание задания..."
/>
)}
</div>
<div className="form-group highlight">
<label>
🔒 Скрытые инструкции для LLM
<span className="info-tooltip">
Эти инструкции увидит только LLM при проверке.
Студенты их не увидят.
</span>
</label>
<textarea
value={hiddenInstructions}
onChange={(e) => setHiddenInstructions(e.target.value)}
rows={5}
placeholder="Дополнительные требования к проверке..."
/>
</div>
<button type="submit">Создать задание</button>
</form>
)
}
TaskCard с индикацией скрытых инструкций
interface TaskCardProps {
task: ChallengeTask
isTeacher: boolean
}
export function TaskCard({ task, isTeacher }: TaskCardProps) {
return (
<div className="task-card">
<h3>{task.title}</h3>
<div className="task-description">
<ReactMarkdown>{task.description}</ReactMarkdown>
</div>
{isTeacher && task.hiddenInstructions && (
<div className="hidden-instructions-indicator">
<span className="lock-icon">🔒</span>
<span>Содержит скрытые инструкции для LLM</span>
</div>
)}
{isTeacher && task.creator && (
<div className="task-meta">
<span>Создал: {task.creator.preferred_username}</span>
</div>
)}
</div>
)
}
4. Настройка Keycloak
Добавление роли teacher
- Войдите в админ панель Keycloak
- Выберите realm (например,
bro-jsилиitpark) - Перейдите в Clients →
journal - Перейдите на вкладку Roles
- Добавьте роль
teacher, если её нет - Назначьте роль нужным пользователям через Users → [пользователь] → Role Mappings
5. Best Practices
✅ Хорошие скрытые инструкции
"Проверь, что функция обрабатывает edge cases: пустой массив,
один элемент, отрицательные числа. Если что-то упущено - укажи."
"Код должен следовать принципу DRY. Если есть дублирование -
отправь на доработку с рекомендацией."
"Обязательна обработка ошибок. Если try-catch отсутствует или
неполный - укажи в feedback."
❌ Плохие скрытые инструкции
"Проверь" // Слишком общее
"Это задание должно быть правильным" // Бессмысленное
"Не принимай, если не идеально" // Слишком строгое, непонятное
6. Просмотр скрытых инструкций
Скрытые инструкции доступны только при запросе с токеном teacher:
// Получить задание (с токеном teacher)
async function getTaskAsTeacher(taskId: string) {
const response = await fetch(`http://localhost:8082/api/challenge/task/${taskId}`, {
headers: {
'Authorization': `Bearer ${keycloakToken}`
}
})
const { data } = await response.json()
// data.hiddenInstructions будет доступно
console.log('Hidden instructions:', data.hiddenInstructions)
}
// Получить задание (без токена или с обычным пользователем)
async function getTaskAsStudent(taskId: string) {
const response = await fetch(`http://localhost:8082/api/challenge/task/${taskId}`)
const { data } = await response.json()
// data.hiddenInstructions будет undefined
console.log('Hidden instructions:', data.hiddenInstructions) // undefined
}
7. Редактирование существующих заданий
async function updateTask(
taskId: string,
updates: {
title?: string
description?: string
hiddenInstructions?: string
}
) {
const response = await fetch(`http://localhost:8082/api/challenge/task/${taskId}`, {
method: 'PUT',
headers: {
'Content-Type': 'application/json',
'Authorization': `Bearer ${keycloakToken}`
},
body: JSON.stringify(updates)
})
return response.json()
}
// Пример использования
updateTask('507f1f77bcf86cd799439011', {
hiddenInstructions: 'Обновленные требования к проверке'
})
8. Мониторинг эффективности инструкций
Отслеживайте, как скрытые инструкции влияют на результаты:
interface InstructionEffectiveness {
taskId: string
taskTitle: string
hasHiddenInstructions: boolean
acceptanceRate: number // % принятых с первой попытки
averageFeedbackQuality: number // оценка качества feedback
}
// Анализ эффективности
async function analyzeInstructionsEffectiveness() {
const tasks = await fetchAllTasks()
const stats = await fetchSystemStats()
return tasks.map(task => ({
taskId: task.id,
taskTitle: task.title,
hasHiddenInstructions: !!task.hiddenInstructions,
acceptanceRate: calculateAcceptanceRate(task.id, stats),
averageFeedbackQuality: calculateFeedbackQuality(task.id, stats)
}))
}
9. Шаблоны скрытых инструкций
Для программирования
Проверь:
1. Корректность алгоритма
2. Обработку edge cases
3. Сложность алгоритма (должна быть оптимальной)
4. Читаемость кода
5. Наличие комментариев в сложных местах
Для веб-разработки
Проверь:
1. Соответствие HTML семантике
2. Доступность (accessibility)
3. Responsive design
4. Производительность
5. Best practices для используемого фреймворка
Для баз данных
Проверь:
1. Правильность SQL синтаксиса
2. Оптимальность запроса
3. Использование индексов
4. Защиту от SQL injection
5. Читаемость запроса
10. FAQ
Q: Что если я не добавлю скрытые инструкции?
A: Задание будет работать нормально. LLM проверит решение на основе только видимого описания.
Q: Могут ли студенты как-то увидеть скрытые инструкции?
A: Нет, сервер автоматически фильтрует это поле при запросах без роли teacher.
Q: Можно ли изменить скрытые инструкции после создания?
A: Да, используйте PUT /api/challenge/task/:taskId с новым значением hiddenInstructions.
Q: Влияют ли скрытые инструкции на все проверки?
A: Да, каждая проверка использует актуальные hiddenInstructions из задания.
Q: Можно ли использовать Markdown в скрытых инструкциях?
A: Можно, но это обычный текст. Markdown не рендерится, так как инструкции идут прямо в LLM.
Примеры реальных сценариев
Сценарий 1: Курс по алгоритмам
{
"title": "Реализовать бинарный поиск",
"description": "Напишите функцию binarySearch(arr, target), которая ищет элемент в отсортированном массиве",
"hiddenInstructions": "Проверь сложность - должна быть O(log n). Если используется линейный поиск или неоптимальный алгоритм - отклони с объяснением. Также проверь обработку случаев, когда элемент не найден."
}
Сценарий 2: Курс по React
{
"title": "Форма регистрации",
"description": "Создайте компонент формы регистрации с полями email и пароль",
"hiddenInstructions": "Обязательна валидация на стороне клиента, использование controlled components, и правильное управление state. Если используются uncontrolled components или нет валидации - отправь на доработку."
}
Сценарий 3: Курс по безопасности
{
"title": "Безопасный API endpoint",
"description": "Создайте endpoint для аутентификации пользователя",
"hiddenInstructions": "Критически важно: пароли должны хешироваться, должна быть защита от SQL injection, rate limiting. Если что-то из этого отсутствует - обязательно отклони и подробно объясни риски безопасности."
}
Используйте скрытые инструкции разумно для повышения качества автоматической проверки! 🎓