Спринт 4: AI-помощник на базе DeepSeek

- Страница /settings: ввод и проверка API ключа DeepSeek
- POST /api/llm/generate — генерация вопросов по названию теста
- POST /api/llm/improve — улучшение формулировки вопроса + ответов (модал с галочками)
- POST /api/llm/distractors — генерация дистракторов
- POST /api/llm/review — рецензия теста + кнопка «Предложить вариант»
- POST /api/llm/improve_all — улучшение всего теста с постатейным сравнением
- Миграция 004: таблица settings (key-value)
- Шапка приложения с навигацией на /settings

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Aleksey Razorvin
2026-03-21 15:11:49 +05:00
parent c1a38bfef8
commit 9a0b3ba92c
19 changed files with 1485 additions and 43 deletions
+22 -15
View File
@@ -102,34 +102,41 @@
---
## Спринт 4 — AI-помощник (DeepSeek)
## Спринт 4 — AI-помощник (DeepSeek)
**Результат:** При создании и редактировании теста доступен AI-ассистент на базе DeepSeek. Ключ API настраивается через страницу настроек.
**Статус:** Завершён и протестирован вручную в браузере.
### Страница настроек (`/settings`)
- [ ] Модель БД: `Setting` (key-value, ключ `deepseek_api_key`)
- [ ] Миграция `004`
- [ ] API: `GET /api/settings/{key}`, `PUT /api/settings/{key}`
- [ ] API: `POST /api/llm/check` — проверить подключение (тестовый запрос к DeepSeek)
- [ ] Фронт: страница `/settings` — поле для ввода ключа + кнопка «Проверить подключение»
- [x] Модель БД: `Setting` (key-value, ключ `deepseek_api_key`)
- [x] Миграция `004`
- [x] API: `GET /api/settings/{key}`, `PUT /api/settings/{key}`
- [x] API: `POST /api/llm/check` — проверить подключение (тестовый запрос к DeepSeek)
- [x] Фронт: страница `/settings` — поле для ввода ключа + кнопка «Проверить подключение»
### AI-функции в форме создания/редактирования теста
- [ ] API: `POST /api/llm/generate` — сгенерировать вопросы и ответы по теме
- [ ] API: `POST /api/llm/improve` — улучшить формулировку вопроса
- [ ] API: `POST /api/llm/distractors` — добавить варианты-дистракторы к вопросу
- [ ] API: `POST /api/llm/review` — проверить качество всего теста
- [x] API: `POST /api/llm/generate` — сгенерировать вопросы и ответы по теме
- [x] API: `POST /api/llm/improve` — улучшить формулировку вопроса
- [x] API: `POST /api/llm/distractors` — добавить варианты-дистракторы к вопросу
- [x] API: `POST /api/llm/review` — проверить качество всего теста
### Интеграция в UI
- [ ] Кнопка «Сгенерировать с AI» на странице создания теста — вводишь тему, получаешь готовый набор вопросов
- [ ] Кнопка «✨» рядом с каждым вопросомулучшить формулировку
- [ ] Кнопка «+ Дистракторы» рядом с каждым вопросом — дополнить неправильные варианты
- [ ] Кнопка «Проверить тест» — AI анализирует весь тест и выдаёт рекомендации
- [ ] Ссылка на страницу `/settings` в шапке приложения
- [x] Кнопка «Сгенерировать с AI» над списком вопросов — ввод темы → превью → «Применить все вопросы»
- [x] Кнопка «Улучшить» в шапке каждого вопросазаменяет формулировку AI-версией
- [x] Кнопка «Дистракторы» в шапке каждого вопроса — добавляет 3 новых неправильных варианта
- [x] Кнопка «Проверить тест» — AI анализирует весь тест и выдаёт рекомендации в модале
- [x] Ссылка «Настройки» в шапке приложения (новый Layout с AppHeader)
### Технические детали
- DeepSeek API совместим с форматом OpenAI — используем библиотеку `openai` с `base_url=https://api.deepseek.com`
- Модель: `deepseek-chat`
- Ключ хранится в таблице `settings`, передаётся из бэкенда — фронт ключ не видит
- `response_format={"type": "json_object"}` для generate, distractors, improve, improve_all — гарантирует структурированный ответ
### Доработки после тестирования
- [x] «Сгенерировать с AI»: убран вопрос про тему — используется название теста; кнопка задизаблена пока название не заполнено
- [x] «Улучшить»: открывает модал с постатейным сравнением (вопрос + каждый ответ) и галочками вместо прямой замены
- [x] «Проверить тест»: добавлена кнопка «Предложить вариант» — вызывает `POST /api/llm/improve_all`, показывает сравнение всего теста с галочками
---
+101
View File
@@ -0,0 +1,101 @@
# ШАГ 011 — Спринт 4: AI-помощник (DeepSeek)
**Дата:** 2026-03-21
**Контекст:** Мастер-класс по разработке системы тестирования сотрудников клиники.
---
## Запрос
> запускам спринт 4
---
## Реализовано
Интеграция с DeepSeek LLM при создании и редактировании тестов. Страница настроек для управления API ключом.
---
## Новые файлы
```
backend/app/models/setting.py ← модель Setting (key-value)
backend/app/schemas/setting.py ← SettingOut, SettingUpdate
backend/app/services/__init__.py ← пакет services
backend/app/services/llm.py ← DeepSeek клиент (все 4 функции)
backend/app/api/settings.py ← GET/PUT /api/settings/{key}
backend/app/api/llm.py ← POST /api/llm/check|generate|improve|distractors|review
backend/alembic/versions/004_settings.py ← миграция: таблица settings
frontend/src/api/settings.ts ← API клиент настроек
frontend/src/api/llm.ts ← API клиент LLM
frontend/src/pages/Settings/index.tsx ← страница /settings
```
## Изменённые файлы
```
backend/app/main.py ← зарегистрированы роутеры settings и llm
backend/alembic/env.py ← импорт модели setting
backend/requirements.txt ← добавлен openai==1.57.0
frontend/src/components/TestForm/index.tsx ← добавлены AI-кнопки
frontend/src/App.tsx ← Layout с шапкой, роут /settings
```
---
## API эндпоинты (новые)
| Метод | URL | Описание |
|-------|-----|----------|
| GET | `/api/settings/{key}` | Получить значение настройки |
| PUT | `/api/settings/{key}` | Сохранить значение настройки |
| POST | `/api/llm/check` | Проверить подключение к DeepSeek |
| POST | `/api/llm/generate` | Сгенерировать вопросы по теме |
| POST | `/api/llm/improve` | Улучшить формулировку вопроса |
| POST | `/api/llm/distractors` | Сгенерировать дистракторы |
| POST | `/api/llm/review` | Проверить качество всего теста |
---
## Схема БД (новое)
```
settings
key VARCHAR(100) PK
value TEXT nullable
updated_at TIMESTAMP auto-updated
```
---
## AI-функции в форме теста
| Кнопка | Расположение | Действие |
|--------|-------------|---------|
| «Сгенерировать с AI» | Над списком вопросов | Открывает модал → ввод темы → превью → «Применить все вопросы» |
| «Проверить тест» | Над списком вопросов | Открывает модал с рекомендациями AI по всему тесту |
| «Улучшить» | В шапке каждого вопроса | Заменяет текст вопроса улучшенной AI-формулировкой |
| «Дистракторы» | В шапке каждого вопроса | Добавляет 3 новых неправильных варианта к вопросу |
---
## Технические детали
- DeepSeek API совместим с OpenAI SDK: `AsyncOpenAI(base_url="https://api.deepseek.com")`
- Модель: `deepseek-chat`
- `response_format={"type": "json_object"}` для generate и distractors — гарантирует JSON-ответ
- API ключ хранится в таблице `settings` с ключом `deepseek_api_key`; фронт ключ не видит
- Шапка приложения: новый `Layout` с `AppHeader` — ссылка «Настройки» в правом углу
---
## Следующие шаги
- [x] Спринт 1: Инфраструктура + Создание тестов
- [x] Спринт 2: Прохождение теста + результат
- [x] Спринт 3: Редактирование + версионность
- [x] Спринт 4: AI-помощник (DeepSeek)
- [ ] Спринт 5: Трекер результатов
- [ ] Спринт 6: Авторизация и роли
- [ ] Спринт 7: Уведомления в MAX
+78
View File
@@ -0,0 +1,78 @@
# ШАГ 012 — Спринт 4: Доработки после тестирования
**Дата:** 2026-03-21
**Контекст:** Мастер-класс по разработке системы тестирования сотрудников клиники.
---
## Запрос (серия правок после тестирования)
> 1. «Сгенерировать с AI» не должен спрашивать тему — использовать название теста
> 2. «Улучшить» должен показывать сравнение старого и нового с галочками, а не затирать текст
> 3. «Проверить тест» → добавить кнопку «Предложить вариант» с полным сравнением всего теста
---
## Доработки
### 1. Кнопка «Сгенерировать с AI»
**Было:** при нажатии открывался модал с полем ввода темы.
**Стало:**
- Кнопка задизаблена, пока не заполнено поле «Название теста» (`shouldUpdate` на поле `title`)
- При нажатии сразу берёт название теста как тему и запускает генерацию
- Открывается модал с анимацией загрузки → превью вопросов → «Применить» / «Сгенерировать заново»
### 2. Кнопка «Улучшить» в карточке вопроса
**Было:** заменяла текст вопроса новой формулировкой без предупреждения.
**Стало:**
- Открывается модал с двумя колонками: текущая формулировка и предложение AI
- Изменения разбиты на позиции: текст вопроса + каждый вариант ответа отдельно
- Чекбокс «Применить» у каждой позиции
- Кнопка «Применить выбранные» — применяет только отмеченные пункты
**Изменения в бэкенде:**
- `improve_question(db, question, answers)` — теперь принимает список ответов и возвращает JSON `{question, answers[]}`
- `POST /api/llm/improve``ImproveRequest` добавлено поле `answers`, `ImproveResponse` теперь `{improved_question, improved_answers[]}`
### 3. Кнопка «Предложить вариант» в модале «Проверить тест»
**Новая кнопка** появляется после получения рекомендаций AI.
**Поведение:**
- При нажатии вызывает новый `POST /api/llm/improve_all`
- Модал переключается в режим сравнения: весь тест постранично
- Для каждого вопроса: текущий vs AI-предложение + чекбокс
- Для каждого варианта ответа: текущий vs AI-предложение + чекбокс
- Правильные ответы помечены `(правильный ✓)`
- Кнопки: «Применить выбранные» / «← К рекомендациям» / «Закрыть»
**Новые файлы/функции бэкенда:**
- `improve_all(db, title, questions)` в `services/llm.py`
- `POST /api/llm/improve_all` в `api/llm.py`
---
## Изменённые файлы
```
backend/app/services/llm.py ← improve_question принимает answers; новая функция improve_all
backend/app/api/llm.py ← обновлён ImproveRequest/ImproveResponse; новый /improve_all
frontend/src/api/llm.ts ← обновлена сигнатура improve; новый метод improveAll
frontend/src/components/TestForm/ ← все три доработки UI
```
---
## Следующие шаги
- [x] Спринт 1: Инфраструктура + Создание тестов
- [x] Спринт 2: Прохождение теста + результат
- [x] Спринт 3: Редактирование + версионность
- [x] Спринт 4: AI-помощник (DeepSeek)
- [ ] Спринт 5: Трекер результатов
- [ ] Спринт 6: Авторизация и роли
- [ ] Спринт 7: Уведомления в MAX