Enhance test submission feature by adding optional hiddenInstructions field for temporary instructions during LLM checks; update API, UI components, and types to support this functionality, improving task evaluation for teachers and challenge authors.
This commit is contained in:
+13
-11
@@ -4,7 +4,7 @@
|
|||||||
|
|
||||||
Содержит два блока изменений:
|
Содержит два блока изменений:
|
||||||
- **Управление видимостью цепочек заданий** (поле `isActive` и новый админский эндпоинт).
|
- **Управление видимостью цепочек заданий** (поле `isActive` и новый админский эндпоинт).
|
||||||
- **Тестовая проверка решения задания админом** (флаг `isTest` в `/submit`).
|
- **Тестовая проверка решения задания админом** (флаг `isTest` и опциональные `hiddenInstructions` в `/submit`).
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
@@ -158,14 +158,15 @@
|
|||||||
|
|
||||||
#### `POST /api/challenge/submit`
|
#### `POST /api/challenge/submit`
|
||||||
|
|
||||||
К существующему API добавлен новый опциональный флаг в теле запроса:
|
К существующему API добавлены новые опциональные поля в теле запроса:
|
||||||
|
|
||||||
```json
|
```json
|
||||||
{
|
{
|
||||||
"userId": "...",
|
"userId": "...",
|
||||||
"taskId": "...",
|
"taskId": "...",
|
||||||
"result": "...",
|
"result": "...",
|
||||||
"isTest": true // НОВОЕ: опциональный флаг
|
"isTest": true, // НОВОЕ: флаг тестового режима
|
||||||
|
"hiddenInstructions": "..." // НОВОЕ: опциональные инструкции для проверки
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
@@ -183,8 +184,9 @@
|
|||||||
- Доступен только для ролей `teacher` / `challenge-author` (проверка через `isTeacher(req, true)`).
|
- Доступен только для ролей `teacher` / `challenge-author` (проверка через `isTeacher(req, true)`).
|
||||||
- **Не создаётся** запись `ChallengeSubmission`.
|
- **Не создаётся** запись `ChallengeSubmission`.
|
||||||
- **Не используется** очередь проверки.
|
- **Не используется** очередь проверки.
|
||||||
- Проверяется только существование задания (`taskId`), пользователь по `userId` в этом режиме **не ищется и не нужен**.
|
- Проверяется только существование задания (`taskId`), пользователь по `userId` в этом режиме **не ищется и не нужен** (но поле всё ещё формально обязательно по схеме).
|
||||||
- Сразу вызывается LLM и возвращается результат проверки.
|
- Если переданы `hiddenInstructions`, они используются **вместо** `task.hiddenInstructions` при формировании промпта для LLM.
|
||||||
|
- Никакие изменения инструкций, переданные через `hiddenInstructions`, **не сохраняются** в базу — это чисто временная инструкция для одной тестовой проверки.
|
||||||
|
|
||||||
**Пример запроса (тестовый режим):**
|
**Пример запроса (тестовый режим):**
|
||||||
|
|
||||||
@@ -197,12 +199,11 @@ Authorization: Bearer <keycloak_token_teacher_or_author>
|
|||||||
"userId": "any-or-dummy-id",
|
"userId": "any-or-dummy-id",
|
||||||
"taskId": "507f1f77bcf86cd799439012",
|
"taskId": "507f1f77bcf86cd799439012",
|
||||||
"result": "function solve() { ... }",
|
"result": "function solve() { ... }",
|
||||||
"isTest": true
|
"isTest": true,
|
||||||
|
"hiddenInstructions": "ВРЕМЕННЫЕ инструкции для проверки, не сохраняются"
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
> `userId` формально обязателен по схеме, но в тестовом режиме не используется на бэке. Можно передавать любой корректный ObjectId.
|
|
||||||
|
|
||||||
**Пример ответа (тестовый режим):**
|
**Пример ответа (тестовый режим):**
|
||||||
|
|
||||||
```json
|
```json
|
||||||
@@ -222,12 +223,13 @@ Authorization: Bearer <keycloak_token_teacher_or_author>
|
|||||||
|
|
||||||
- **Где использовать тестовый режим**:
|
- **Где использовать тестовый режим**:
|
||||||
- только в админских/преподавательских интерфейсах (например, экран настройки задания или предпросмотр проверки);
|
- только в админских/преподавательских интерфейсах (например, экран настройки задания или предпросмотр проверки);
|
||||||
- использовать флаг `isTest: true`, когда нужно получить мгновенный ответ от LLM без записи в историю.
|
- использовать флаг `isTest: true`, когда нужно получить мгновенный ответ от LLM без записи в историю;
|
||||||
|
- при наличии UI-редактора скрытых инструкций использовать `hiddenInstructions` для передачи временного варианта, не сохраняя его.
|
||||||
- **Где НЕ использовать**:
|
- **Где НЕ использовать**:
|
||||||
- в пользовательском флоу сдачи заданий студентами — там должен использоваться обычный режим **без** `isTest`.
|
- в пользовательском флоу сдачи заданий студентами — там должен использоваться обычный режим **без** `isTest`.
|
||||||
- **UI-ожидания**:
|
- **UI-ожидания**:
|
||||||
- показывать администратору статус (`accepted` / `needs_revision`) и `feedback`;
|
- показывать администратору статус (`accepted` / `needs_revision`) и `feedback`;
|
||||||
- явно обозначить в интерфейсе, что это «тестовая проверка» и она **не попадает в статистику / попытки**.
|
- явно обозначить в интерфейсе, что это «тестовая проверка» и она **не попадает в статистику / попытки**, а переданные `hiddenInstructions` не сохраняются.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
@@ -238,4 +240,4 @@ Authorization: Bearer <keycloak_token_teacher_or_author>
|
|||||||
- админский список: `GET /api/challenge/chains/admin` → все цепочки + управление `isActive` через `POST/PUT /chain`.
|
- админский список: `GET /api/challenge/chains/admin` → все цепочки + управление `isActive` через `POST/PUT /chain`.
|
||||||
- Для отправки решений:
|
- Для отправки решений:
|
||||||
- обычный режим без `isTest` — всё как раньше (очередь, попытки, статистика);
|
- обычный режим без `isTest` — всё как раньше (очередь, попытки, статистика);
|
||||||
- тестовый режим с `isTest: true` — только для `teacher/challenge-author`, без записи прогресса, сразу возвращает результат проверки.
|
- тестовый режим с `isTest: true` + опциональные `hiddenInstructions` — только для `teacher/challenge-author`, без записи прогресса, сразу возвращает результат проверки с учётом временных инструкций.
|
||||||
@@ -147,7 +147,7 @@ export const api = createApi({
|
|||||||
|
|
||||||
// Test submission (LLM check without creating a real submission)
|
// Test submission (LLM check without creating a real submission)
|
||||||
testSubmission: builder.mutation<TestSubmissionResult, SubmitRequest>({
|
testSubmission: builder.mutation<TestSubmissionResult, SubmitRequest>({
|
||||||
query: ({ userId, taskId, result, isTest = true }) => ({
|
query: ({ userId, taskId, result, isTest = true, hiddenInstructions }) => ({
|
||||||
url: '/challenge/submit',
|
url: '/challenge/submit',
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
body: {
|
body: {
|
||||||
@@ -155,6 +155,7 @@ export const api = createApi({
|
|||||||
taskId,
|
taskId,
|
||||||
result,
|
result,
|
||||||
isTest,
|
isTest,
|
||||||
|
hiddenInstructions,
|
||||||
},
|
},
|
||||||
}),
|
}),
|
||||||
transformResponse: (response: APIResponse<TestSubmissionResult>) => response.data,
|
transformResponse: (response: APIResponse<TestSubmissionResult>) => response.data,
|
||||||
|
|||||||
@@ -136,6 +136,7 @@ export const TaskFormPage: React.FC = () => {
|
|||||||
taskId: task.id,
|
taskId: task.id,
|
||||||
result: testAnswer.trim(),
|
result: testAnswer.trim(),
|
||||||
isTest: true,
|
isTest: true,
|
||||||
|
hiddenInstructions: hiddenInstructions.trim() || undefined,
|
||||||
}).unwrap()
|
}).unwrap()
|
||||||
|
|
||||||
setTestStatus(result.status)
|
setTestStatus(result.status)
|
||||||
|
|||||||
@@ -234,6 +234,8 @@ export interface SubmitRequest {
|
|||||||
result: string
|
result: string
|
||||||
// Флаг тестового режима: проверка без создания Submission и очереди
|
// Флаг тестового режима: проверка без создания Submission и очереди
|
||||||
isTest?: boolean
|
isTest?: boolean
|
||||||
|
// Временные скрытые инструкции для тестовой проверки (не сохраняются в задачу)
|
||||||
|
hiddenInstructions?: string
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface TestSubmissionResult {
|
export interface TestSubmissionResult {
|
||||||
|
|||||||
Reference in New Issue
Block a user