Spaces:
Paused
Paused
multi photos - in process
Browse files- .gitattributes +35 -0
- .gitignore +2 -2
- README.md +0 -0
- TASKS.md +34 -6
- app/.gradio/certificate.pem +31 -0
- app/__init__.py +0 -0
- app/drawings.py +108 -0
- app/knowledge_base/LP_shots.py +243 -0
- app/knowledge_base/Methods.md +113 -0
- app/knowledge_base/check_list.md +41 -0
- app/knowledge_base/inspire.md +9 -0
- app/knowledge_base/lesson_frameworks.md +1 -0
- app/knowledge_base/test.md +23 -0
- app/knowledge_base/test_samples/PPP_Spotlight 5_1.md +166 -0
- app/knowledge_base/test_samples/lesson_plan_20250426200232.docx +0 -0
- app/knowledge_base/test_samples/lesson_plan_20250426215122.docx +0 -0
- app/knowledge_base/test_samples/lesson_plan_20250426220824.docx +0 -0
- app/knowledge_base/textbooks.py +79 -0
- app/knowledge_base/tips.md +173 -0
- app/main.py +486 -0
- app/prompt_builder/__init__.py +0 -0
- app/prompt_builder/methodology.py +18 -0
- app/prompt_builder/prompt.py +257 -0
- app/prompt_builder/prompt_sketches.md +284 -0
- app/quotes.py +118 -0
- app/styles.css +69 -0
- app/test_502.py +23 -0
- app/test_gradio.py +486 -0
- app/test_gradio_test.py +527 -0
- docs/architecture.md +61 -0
- docs/notes.md +69 -0
- requirements.txt +8 -0
.gitattributes
ADDED
|
@@ -0,0 +1,35 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
*.7z filter=lfs diff=lfs merge=lfs -text
|
| 2 |
+
*.arrow filter=lfs diff=lfs merge=lfs -text
|
| 3 |
+
*.bin filter=lfs diff=lfs merge=lfs -text
|
| 4 |
+
*.bz2 filter=lfs diff=lfs merge=lfs -text
|
| 5 |
+
*.ckpt filter=lfs diff=lfs merge=lfs -text
|
| 6 |
+
*.ftz filter=lfs diff=lfs merge=lfs -text
|
| 7 |
+
*.gz filter=lfs diff=lfs merge=lfs -text
|
| 8 |
+
*.h5 filter=lfs diff=lfs merge=lfs -text
|
| 9 |
+
*.joblib filter=lfs diff=lfs merge=lfs -text
|
| 10 |
+
*.lfs.* filter=lfs diff=lfs merge=lfs -text
|
| 11 |
+
*.mlmodel filter=lfs diff=lfs merge=lfs -text
|
| 12 |
+
*.model filter=lfs diff=lfs merge=lfs -text
|
| 13 |
+
*.msgpack filter=lfs diff=lfs merge=lfs -text
|
| 14 |
+
*.npy filter=lfs diff=lfs merge=lfs -text
|
| 15 |
+
*.npz filter=lfs diff=lfs merge=lfs -text
|
| 16 |
+
*.onnx filter=lfs diff=lfs merge=lfs -text
|
| 17 |
+
*.ot filter=lfs diff=lfs merge=lfs -text
|
| 18 |
+
*.parquet filter=lfs diff=lfs merge=lfs -text
|
| 19 |
+
*.pb filter=lfs diff=lfs merge=lfs -text
|
| 20 |
+
*.pickle filter=lfs diff=lfs merge=lfs -text
|
| 21 |
+
*.pkl filter=lfs diff=lfs merge=lfs -text
|
| 22 |
+
*.pt filter=lfs diff=lfs merge=lfs -text
|
| 23 |
+
*.pth filter=lfs diff=lfs merge=lfs -text
|
| 24 |
+
*.rar filter=lfs diff=lfs merge=lfs -text
|
| 25 |
+
*.safetensors filter=lfs diff=lfs merge=lfs -text
|
| 26 |
+
saved_model/**/* filter=lfs diff=lfs merge=lfs -text
|
| 27 |
+
*.tar.* filter=lfs diff=lfs merge=lfs -text
|
| 28 |
+
*.tar filter=lfs diff=lfs merge=lfs -text
|
| 29 |
+
*.tflite filter=lfs diff=lfs merge=lfs -text
|
| 30 |
+
*.tgz filter=lfs diff=lfs merge=lfs -text
|
| 31 |
+
*.wasm filter=lfs diff=lfs merge=lfs -text
|
| 32 |
+
*.xz filter=lfs diff=lfs merge=lfs -text
|
| 33 |
+
*.zip filter=lfs diff=lfs merge=lfs -text
|
| 34 |
+
*.zst filter=lfs diff=lfs merge=lfs -text
|
| 35 |
+
*tfevents* filter=lfs diff=lfs merge=lfs -text
|
.gitignore
CHANGED
|
@@ -4,8 +4,8 @@
|
|
| 4 |
|
| 5 |
#bot/config.py
|
| 6 |
.env
|
| 7 |
-
|
| 8 |
-
|
| 9 |
__pycache__/
|
| 10 |
.idea/
|
| 11 |
.idea/workspace.xml
|
|
|
|
| 4 |
|
| 5 |
#bot/config.py
|
| 6 |
.env
|
| 7 |
+
Materials/
|
| 8 |
+
dev/
|
| 9 |
__pycache__/
|
| 10 |
.idea/
|
| 11 |
.idea/workspace.xml
|
README.md
CHANGED
|
Binary files a/README.md and b/README.md differ
|
|
|
TASKS.md
CHANGED
|
@@ -18,23 +18,51 @@
|
|
| 18 |
[ ] загрузка нескольких страниц учебника
|
| 19 |
[ ] интеграция настроек
|
| 20 |
[ ] мотивационный блок в приложении - напр. цитата из педагогики, мотивационная, каждый раз новая
|
|
|
|
|
|
|
|
|
|
| 21 |
|
|
|
|
|
|
|
|
|
|
| 22 |
|
|
|
|
|
|
|
| 23 |
|
|
|
|
| 24 |
## in progress
|
| 25 |
-
[ ]
|
| 26 |
-
[ ]
|
|
|
|
|
|
|
|
|
|
|
|
|
| 27 |
|
| 28 |
-
[ ] проверка Responses API - web_search, vision
|
| 29 |
|
| 30 |
## done
|
| 31 |
[x] базовая проверка LP через LLM -- фото страницы Spotlight 6 + gpt4o = успешно
|
| 32 |
[x] проверка Responses API - работа с БЗ -- работает успешно через официальный openai ResponsesAPI ()
|
| 33 |
[x] UI приложения базово - Layout, набор регуляторов
|
| 34 |
-
|
| 35 |
-
|
|
|
|
|
|
|
|
|
|
| 36 |
|
| 37 |
Нужен ли поиск по web?
|
| 38 |
Да, если это подкрепляет vision
|
| 39 |
Нужен ли поиск по БЗ?
|
| 40 |
-
Да, если нужны коллекции материалов
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 18 |
[ ] загрузка нескольких страниц учебника
|
| 19 |
[ ] интеграция настроек
|
| 20 |
[ ] мотивационный блок в приложении - напр. цитата из педагогики, мотивационная, каждый раз новая
|
| 21 |
+
[ ] ФГОСи методреки как гайдлайн (интересная проверка как будет выстроен урок по ним)
|
| 22 |
+
[ ] версия - без материала. Полностью с нуля по web search составленный урок
|
| 23 |
+
[ ] построение портрета ученика - по региону, описанию школы
|
| 24 |
|
| 25 |
+
[ ] сравнить gpt-4.1 и o4-mini
|
| 26 |
+
[ ] вынести в промпте в отдельный блок рекомендации по занятияю и classroom management (по запросу - дополнительная опция)
|
| 27 |
+
[ ] генерация частей урока - захотел переделал вступление, и каждое задание - отдельно
|
| 28 |
|
| 29 |
+
[ ] можно превратить в интерактивный обучающий курс. Где части плана объясняются, поясняется методика, даются ссылки на видео с уроками и тд. Вдохновение: https://maxenglishcorner.com/lessons/teaching-ideas/teaching-ideas-7-lesson-planning-ppp-model/
|
| 30 |
+
[ ] эту идею описать в портфолио как продолжение MVP
|
| 31 |
|
| 32 |
+
[ ]
|
| 33 |
## in progress
|
| 34 |
+
[ ] интерфейс, аналогичный logoKonspekt
|
| 35 |
+
[ ] автозаполнение поля Учебник (по словарю)
|
| 36 |
+
[ ] закомментить параметры, которые не будут в релизе - прописать к ним логику развития
|
| 37 |
+
[ ] 2-3 страницы в input
|
| 38 |
+
[ ] web search
|
| 39 |
+
|
| 40 |
|
|
|
|
| 41 |
|
| 42 |
## done
|
| 43 |
[x] базовая проверка LP через LLM -- фото страницы Spotlight 6 + gpt4o = успешно
|
| 44 |
[x] проверка Responses API - работа с БЗ -- работает успешно через официальный openai ResponsesAPI ()
|
| 45 |
[x] UI приложения базово - Layout, набор регуляторов
|
| 46 |
+
[x] проверка Responses API - web_search, vision
|
| 47 |
+
[x] базовый MVP: загрузка > url > LLM1 > настройки > LLM2 > план урока и возможность скачать. Streamlit
|
| 48 |
+
[x] проверка различных основных учебников
|
| 49 |
+
[x] промпт для методики PPP - динамический
|
| 50 |
+
[x] параметры корректно передаются в промпт динамически
|
| 51 |
|
| 52 |
Нужен ли поиск по web?
|
| 53 |
Да, если это подкрепляет vision
|
| 54 |
Нужен ли поиск по БЗ?
|
| 55 |
+
Да, если нужны коллекции материалов
|
| 56 |
+
|
| 57 |
+
Название учебника (+edition) + Номер страниц учебника:
|
| 58 |
+
+ web search:
|
| 59 |
+
поиск аудио к конкретным учебникам (если в открытом доступе)
|
| 60 |
+
|
| 61 |
+
Описания методик
|
| 62 |
+
|
| 63 |
+
Примеры хороших планов ESL
|
| 64 |
+
|
| 65 |
+
LLM + web_search + инструкция: найди дополнительный материал в соответствии с общим контекстом урока:
|
| 66 |
+
Интеграция релевантных материалов в план
|
| 67 |
+
|
| 68 |
+
LLM + file_search: интеграция в план занятий из базы
|
app/.gradio/certificate.pem
ADDED
|
@@ -0,0 +1,31 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
-----BEGIN CERTIFICATE-----
|
| 2 |
+
MIIFazCCA1OgAwIBAgIRAIIQz7DSQONZRGPgu2OCiwAwDQYJKoZIhvcNAQELBQAw
|
| 3 |
+
TzELMAkGA1UEBhMCVVMxKTAnBgNVBAoTIEludGVybmV0IFNlY3VyaXR5IFJlc2Vh
|
| 4 |
+
cmNoIEdyb3VwMRUwEwYDVQQDEwxJU1JHIFJvb3QgWDEwHhcNMTUwNjA0MTEwNDM4
|
| 5 |
+
WhcNMzUwNjA0MTEwNDM4WjBPMQswCQYDVQQGEwJVUzEpMCcGA1UEChMgSW50ZXJu
|
| 6 |
+
ZXQgU2VjdXJpdHkgUmVzZWFyY2ggR3JvdXAxFTATBgNVBAMTDElTUkcgUm9vdCBY
|
| 7 |
+
MTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAK3oJHP0FDfzm54rVygc
|
| 8 |
+
h77ct984kIxuPOZXoHj3dcKi/vVqbvYATyjb3miGbESTtrFj/RQSa78f0uoxmyF+
|
| 9 |
+
0TM8ukj13Xnfs7j/EvEhmkvBioZxaUpmZmyPfjxwv60pIgbz5MDmgK7iS4+3mX6U
|
| 10 |
+
A5/TR5d8mUgjU+g4rk8Kb4Mu0UlXjIB0ttov0DiNewNwIRt18jA8+o+u3dpjq+sW
|
| 11 |
+
T8KOEUt+zwvo/7V3LvSye0rgTBIlDHCNAymg4VMk7BPZ7hm/ELNKjD+Jo2FR3qyH
|
| 12 |
+
B5T0Y3HsLuJvW5iB4YlcNHlsdu87kGJ55tukmi8mxdAQ4Q7e2RCOFvu396j3x+UC
|
| 13 |
+
B5iPNgiV5+I3lg02dZ77DnKxHZu8A/lJBdiB3QW0KtZB6awBdpUKD9jf1b0SHzUv
|
| 14 |
+
KBds0pjBqAlkd25HN7rOrFleaJ1/ctaJxQZBKT5ZPt0m9STJEadao0xAH0ahmbWn
|
| 15 |
+
OlFuhjuefXKnEgV4We0+UXgVCwOPjdAvBbI+e0ocS3MFEvzG6uBQE3xDk3SzynTn
|
| 16 |
+
jh8BCNAw1FtxNrQHusEwMFxIt4I7mKZ9YIqioymCzLq9gwQbooMDQaHWBfEbwrbw
|
| 17 |
+
qHyGO0aoSCqI3Haadr8faqU9GY/rOPNk3sgrDQoo//fb4hVC1CLQJ13hef4Y53CI
|
| 18 |
+
rU7m2Ys6xt0nUW7/vGT1M0NPAgMBAAGjQjBAMA4GA1UdDwEB/wQEAwIBBjAPBgNV
|
| 19 |
+
HRMBAf8EBTADAQH/MB0GA1UdDgQWBBR5tFnme7bl5AFzgAiIyBpY9umbbjANBgkq
|
| 20 |
+
hkiG9w0BAQsFAAOCAgEAVR9YqbyyqFDQDLHYGmkgJykIrGF1XIpu+ILlaS/V9lZL
|
| 21 |
+
ubhzEFnTIZd+50xx+7LSYK05qAvqFyFWhfFQDlnrzuBZ6brJFe+GnY+EgPbk6ZGQ
|
| 22 |
+
3BebYhtF8GaV0nxvwuo77x/Py9auJ/GpsMiu/X1+mvoiBOv/2X/qkSsisRcOj/KK
|
| 23 |
+
NFtY2PwByVS5uCbMiogziUwthDyC3+6WVwW6LLv3xLfHTjuCvjHIInNzktHCgKQ5
|
| 24 |
+
ORAzI4JMPJ+GslWYHb4phowim57iaztXOoJwTdwJx4nLCgdNbOhdjsnvzqvHu7Ur
|
| 25 |
+
TkXWStAmzOVyyghqpZXjFaH3pO3JLF+l+/+sKAIuvtd7u+Nxe5AW0wdeRlN8NwdC
|
| 26 |
+
jNPElpzVmbUq4JUagEiuTDkHzsxHpFKVK7q4+63SM1N95R1NbdWhscdCb+ZAJzVc
|
| 27 |
+
oyi3B43njTOQ5yOf+1CceWxG1bQVs5ZufpsMljq4Ui0/1lvh+wjChP4kqKOJ2qxq
|
| 28 |
+
4RgqsahDYVvTH9w7jXbyLeiNdd8XM2w9U/t7y0Ff/9yi0GE44Za4rF2LN9d11TPA
|
| 29 |
+
mRGunUHBcnWEvgJBQl9nJEiU0Zsnvgc/ubhPgXRR4Xq37Z0j4r7g1SgEEzwxA57d
|
| 30 |
+
emyPxgcYxn/eR44/KJ4EBs+lVDR3veyJm+kXQ99b21/+jh5Xos1AnX5iItreGCc=
|
| 31 |
+
-----END CERTIFICATE-----
|
app/__init__.py
ADDED
|
File without changes
|
app/drawings.py
ADDED
|
@@ -0,0 +1,108 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
drawings = [
|
| 2 |
+
# 1. Доска с началом урока
|
| 3 |
+
r"""
|
| 4 |
+
_________________________________
|
| 5 |
+
| |
|
| 6 |
+
| W E L C O M E ! |
|
| 7 |
+
| |
|
| 8 |
+
| Today's Plan: |
|
| 9 |
+
| • Warm-up: [_____] |
|
| 10 |
+
| • New words: [_____] |
|
| 11 |
+
| • Game: [_____] |
|
| 12 |
+
| • Project: [_____] |
|
| 13 |
+
| |
|
| 14 |
+
| \ |
|
| 15 |
+
| \ (^_^) |
|
| 16 |
+
| `--|_|--' |
|
| 17 |
+
| / \ |
|
| 18 |
+
|_________________________________|
|
| 19 |
+
""",
|
| 20 |
+
|
| 21 |
+
# 3. Работа в группах
|
| 22 |
+
r"""
|
| 23 |
+
.─────────────────.
|
| 24 |
+
| _____ _____ |
|
| 25 |
+
| / \/ \ |
|
| 26 |
+
| | o || o | |
|
| 27 |
+
| \____/\_____/ |
|
| 28 |
+
| |
|
| 29 |
+
| "Let's share!" |
|
| 30 |
+
| /\ /\ |
|
| 31 |
+
| / \_____/ \ |
|
| 32 |
+
| | GROUP 1 | |
|
| 33 |
+
'─────────────────'
|
| 34 |
+
""",
|
| 35 |
+
|
| 36 |
+
# 4. Обсуждение
|
| 37 |
+
r"""
|
| 38 |
+
_______________________
|
| 39 |
+
/ \
|
| 40 |
+
| ? ? ? |
|
| 41 |
+
| / \ / \ / \ |
|
| 42 |
+
| |
|
| 43 |
+
| IDEA STORM |
|
| 44 |
+
| |
|
| 45 |
+
| o o o |
|
| 46 |
+
| <|> <|> <|> |
|
| 47 |
+
| /\ /\ /\ |
|
| 48 |
+
\_________________________/
|
| 49 |
+
""",
|
| 50 |
+
|
| 51 |
+
# 5. Активное занятие
|
| 52 |
+
r"""
|
| 53 |
+
╔═════════════════════╗
|
| 54 |
+
║ RUN AND FIND! ║
|
| 55 |
+
╠═════════════════════╣
|
| 56 |
+
║ ║
|
| 57 |
+
║ (\_/) (•.•) ║
|
| 58 |
+
║ / >☆< \ / > < \ ║
|
| 59 |
+
║ ║
|
| 60 |
+
║ "I found yellow!" ║
|
| 61 |
+
║ ║
|
| 62 |
+
╚═════════════════════╝
|
| 63 |
+
""",
|
| 64 |
+
|
| 65 |
+
# 6. Творческий проект
|
| 66 |
+
r"""
|
| 67 |
+
.-------------------.
|
| 68 |
+
| ___ |
|
| 69 |
+
| / \ ✏️ |
|
| 70 |
+
| | | ___ |
|
| 71 |
+
| \___/ / \ |
|
| 72 |
+
| | ||
|
| 73 |
+
| OUR \___/ |
|
| 74 |
+
| POSTER! |
|
| 75 |
+
| \_____/ |
|
| 76 |
+
| | | |
|
| 77 |
+
'-------------------'
|
| 78 |
+
""",
|
| 79 |
+
|
| 80 |
+
# 7. Время вопросов
|
| 81 |
+
r"""
|
| 82 |
+
________________________
|
| 83 |
+
| |
|
| 84 |
+
| ? ? |
|
| 85 |
+
| / \ / \ |
|
| 86 |
+
| |
|
| 87 |
+
| "But why...?" |
|
| 88 |
+
| \ |
|
| 89 |
+
| \ (。◕‿◕。) |
|
| 90 |
+
| \____________|
|
| 91 |
+
| |
|
| 92 |
+
|________________________|
|
| 93 |
+
""",
|
| 94 |
+
|
| 95 |
+
# 8. Успех
|
| 96 |
+
r"""
|
| 97 |
+
╭───────────────────╮
|
| 98 |
+
│ │
|
| 99 |
+
│ ★ ★ ★ ★ ★ │
|
| 100 |
+
│ │
|
| 101 |
+
│ WE DID IT! │
|
| 102 |
+
│ \ │
|
| 103 |
+
│ \ \(^o^)/ │
|
| 104 |
+
│ __\________ │
|
| 105 |
+
│ │
|
| 106 |
+
╰───────────────────╯
|
| 107 |
+
"""
|
| 108 |
+
]
|
app/knowledge_base/LP_shots.py
ADDED
|
@@ -0,0 +1,243 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
LP_PPP_1 = f"""
|
| 2 |
+
CLASS - - - Intermediate level, 4 students
|
| 3 |
+
THEME FOR CLASS - - - Pollution
|
| 4 |
+
TARGET LANGUAGE (TL) - - - 1st and 2nd conditonals
|
| 5 |
+
OBJECTIVE FOR CLASS - - - By the end of the class the students should be able to know the difference between
|
| 6 |
+
first and second conditionals and be able to use both forms while speaking about pollution.
|
| 7 |
+
MATERIALS - - -
|
| 8 |
+
● 3 pictures to be used in the CONTEXT stage (from Pixabay)
|
| 9 |
+
●Handout 1 - Reading: Article about air pollution plus corresponding reading exercises
|
| 10 |
+
citation: (This article was written by Katy Daigle and has been adapted from
|
| 11 |
+
https://www.sciencenewsforstudents.org/article/air-pollution-shortening-lives-worldwide)
|
| 12 |
+
●Handout 2 - Worksheet for PRACTICE activities with summary reference chart at top of page
|
| 13 |
+
|
| 14 |
+
---
|
| 15 |
+
1. CONTEXT or WARMER/THEME
|
| 16 |
+
|
| 17 |
+
OBJECTIVE(S)
|
| 18 |
+
●To get the students speaking and communicating a little in English.
|
| 19 |
+
●To orientate students to begin thinking of different kinds of pollution. There are three
|
| 20 |
+
pictures (one each of air, land and water pollution).
|
| 21 |
+
|
| 22 |
+
MATERIALS
|
| 23 |
+
3 pictures from Pixabay
|
| 24 |
+
(different kinds of pollution: air, land & water)
|
| 25 |
+
Students are placed into pairs (more intimate groups this way, and more students will be speaking) and given 3
|
| 26 |
+
pictures. Together they have to
|
| 27 |
+
1) Describe each picture individually
|
| 28 |
+
2) Decide what all three pictures have in common
|
| 29 |
+
Teacher monitors and helps out a little if there are problems with vocabulary
|
| 30 |
+
After the pair-work the teacher asks the students to say what they came up with
|
| 31 |
+
|
| 32 |
+
|
| 33 |
+
2. INTRODUCTION
|
| 34 |
+
|
| 35 |
+
OBJECTIVE(S)
|
| 36 |
+
● To pre-teach some vocabulary found in the reading (ex: lifespan)
|
| 37 |
+
●To orientate students to some of the content (concepts) in the article
|
| 38 |
+
|
| 39 |
+
MATERIALS
|
| 40 |
+
none, other than the whiteboard
|
| 41 |
+
|
| 42 |
+
|
| 43 |
+
●Elicit the meaning of ‘lifespan’ from the class
|
| 44 |
+
●Ask the students to answer the question written on the board:
|
| 45 |
+
What are some common causes for shorter life spans in some countries? (for example diet, pollution and cancer)
|
| 46 |
+
|
| 47 |
+
|
| 48 |
+
3. INPUT TASK 1: READING FOR GIST
|
| 49 |
+
|
| 50 |
+
OBJECTIVE(S)
|
| 51 |
+
● To have the students get a general idea of what the text is about
|
| 52 |
+
without getting bogged down with unfamiliar vocabulary or some unclear parts or ideas
|
| 53 |
+
MATERIALS Handout 1 with article and two sets of questions. One set is for
|
| 54 |
+
this task where the students have to decide which of the three given titles is most suitable
|
| 55 |
+
●The students are given a handout which contains both the article to read and two sets of questions. The students are
|
| 56 |
+
asked to fold their papers so they could focus completely on that first task (and not reading ahead to see what is next on
|
| 57 |
+
the handout).
|
| 58 |
+
●Students understand the task before they begin reading and are given only one minute to decide which title would be
|
| 59 |
+
best for the article.
|
| 60 |
+
●After one minute students are asked not only for their answer, but also why the other options were not correct or
|
| 61 |
+
suitable.
|
| 62 |
+
|
| 63 |
+
|
| 64 |
+
4. INPUT TASK 2: READING FOR DETAILS
|
| 65 |
+
|
| 66 |
+
OBJECTIVE(S) ●
|
| 67 |
+
To have the students get a better idea of what the text is about
|
| 68 |
+
by quickly scanning it for specific information
|
| 69 |
+
MATERIALS Handout 1 with article and two sets of questions. This task is the
|
| 70 |
+
second set of 3 questions found at the bottom of the article
|
| 71 |
+
|
| 72 |
+
● Students are told to look at Section 2 on their handout
|
| 73 |
+
●We go over the questions so the students understand what they have to read for
|
| 74 |
+
●Students work out the answers individually but can check with other students
|
| 75 |
+
●The answers are elicited and explained.
|
| 76 |
+
|
| 77 |
+
5. PRESENTATION
|
| 78 |
+
|
| 79 |
+
OBJECTIVE(S)
|
| 80 |
+
● To familiarize the students with how the first and second
|
| 81 |
+
conditionals are formed and to know what situations are appropriate to use which one
|
| 82 |
+
MATERIALS
|
| 83 |
+
The form, concepts and examples are written on the board
|
| 84 |
+
|
| 85 |
+
●Ask the students what they know about the grammatical structure of conditionals.
|
| 86 |
+
●Focus on what they know about the first and second conditionals and write the information on the board in a clear and
|
| 87 |
+
organized way (which resembles the chart in Handout 2.
|
| 88 |
+
●Review the key points by asking different students comprehension check questions to see what they understand and
|
| 89 |
+
how well they are retaining the key information.
|
| 90 |
+
|
| 91 |
+
6. PRACTICE 1 CORRECT SENTENCES
|
| 92 |
+
|
| 93 |
+
OBJECTIVE(S) ● To test for level of understanding as students apply some of the
|
| 94 |
+
recently reviewed key concepts by correcting 4 sentences with errors emphasizing those
|
| 95 |
+
points.
|
| 96 |
+
MATERIALS Handout 2 with a chart for reference of key idea (#1) and the task
|
| 97 |
+
of correcting the four sentences (#2)
|
| 98 |
+
|
| 99 |
+
●Point out the 4 sentences in Section 2 and tell the students to correct them.
|
| 100 |
+
●Monitor the students while they are working to see what they find difficult.
|
| 101 |
+
●Elicit the answers and their explanations / Also deal with their doubts as we go over their answers.
|
| 102 |
+
●Review the key points before going on to Practice 2
|
| 103 |
+
|
| 104 |
+
7a. PRACTICE 2a WRITE & USE QUESTIONS 1-ST CONDITIONAL
|
| 105 |
+
|
| 106 |
+
OBJECTIVE(S)
|
| 107 |
+
● To have the students come up with their own sentences using the
|
| 108 |
+
first conditional structure for an appropriate situation, matching the form with the function
|
| 109 |
+
● To have the students become familiar with incorporating the TL into their speaking
|
| 110 |
+
MATERIALS
|
| 111 |
+
Handout 2 Section #3
|
| 112 |
+
●Focus on only the first conditional as the TL (target language) and elicit the key points to orientate the students.
|
| 113 |
+
●Students look at Section #3 on Handout 2 and teacher elicits different possible questions they could ask in that form.
|
| 114 |
+
●Students individually write first conditional questions to ask a partner in the class. Teacher monitors and helps.
|
| 115 |
+
●Model the coming speaking application by having one student ask another his/her question and the partner replies.
|
| 116 |
+
Encourage them to explore a little further by changing it into a ‘mini one-minute conversation’ through asking followup questions and volunteering comments or details.
|
| 117 |
+
●Place students in pairs and have them take turns with their questions which lead them to their mini conversations.
|
| 118 |
+
●Give some feedback when they are finished, looking both at the target language used and their development of the
|
| 119 |
+
mini conversations.
|
| 120 |
+
|
| 121 |
+
7b. PRACTICE 2b WRITE & USE QUESTIONS 2ND CONDITIONAL
|
| 122 |
+
|
| 123 |
+
OBJECTIVE(S)
|
| 124 |
+
● To have the students come up with their own sentences using the
|
| 125 |
+
second conditional structure for an appropriate situation, matching the form with the
|
| 126 |
+
function
|
| 127 |
+
● To have the students become familiar with incorporating the TL into their speaking
|
| 128 |
+
MATERIALS Handout 2 Section #4
|
| 129 |
+
●Focus on only the second conditional and elicit the key points to orientate the students.
|
| 130 |
+
●Basically the same procedure as the previous exercise, but now for Section 4 and focusing on the second conditional.
|
| 131 |
+
|
| 132 |
+
7c. PRACTICE 3 PREPARE FOR DISCUSSION
|
| 133 |
+
|
| 134 |
+
OBJECTIVE(S)
|
| 135 |
+
● To help students prepare for coming discussion
|
| 136 |
+
MATERIALS Handout 2 Section #5
|
| 137 |
+
Some prompts in Section #6 they can use in their conversation
|
| 138 |
+
●Tell the students that soon they will have a discussion about the theme of air pollution. They are to talk about how
|
| 139 |
+
bad it is and what can be done about it. Elicit some possible sentences/questions for the two conditionals as examples.
|
| 140 |
+
●Students each write one first conditional sentence or question and another one in the second conditional that they
|
| 141 |
+
might use in that discussion.
|
| 142 |
+
●Teacher monitors and helps.
|
| 143 |
+
●Because there are only four students, place them all in the same group and tell them they are enjoying a cup of coffee
|
| 144 |
+
together. They are to imagine that the conversation has turned to air pollution and without referring to their notes, they
|
| 145 |
+
talk about how bad the situation is and speculate what could be done about it, using occasionally, if it’s appropriate, the
|
| 146 |
+
first or second conditional. The main focus is to have a conversation and that they should explore the theme.
|
| 147 |
+
●Go over the expressions in Section #6 that they can use while speaking and write them on the board as prompts
|
| 148 |
+
●Teacher listens and steps in, if necessary, to guide and encourage the students to explore the theme in their
|
| 149 |
+
conversation.
|
| 150 |
+
●Give some feedback when they are finished, looking both at the target language used and their development of the
|
| 151 |
+
discussion.
|
| 152 |
+
|
| 153 |
+
|
| 154 |
+
8. PRODUCTION
|
| 155 |
+
|
| 156 |
+
OBJECTIVE(S)
|
| 157 |
+
● To use the two conditionals in a Production speaking activity
|
| 158 |
+
MATERIALS
|
| 159 |
+
none
|
| 160 |
+
|
| 161 |
+
●Tell the students they are going to have one more conversation using the first and second conditional. This time it
|
| 162 |
+
will be about land and water pollution or pollution in general.
|
| 163 |
+
●Tell them they can think for a couple of minutes about what they may say or ask about that theme. Remind them of
|
| 164 |
+
some of the things that came up in the previous speaking activity. Also tell them that the teacher will not be
|
| 165 |
+
participating; that it will be just their conversation.
|
| 166 |
+
●Students speak for about 5 minutes.
|
| 167 |
+
●Give some feedback when they are finished, looking both at the target language used and their development of the
|
| 168 |
+
discussion.
|
| 169 |
+
"""
|
| 170 |
+
|
| 171 |
+
LP_PPP_2 = f"""
|
| 172 |
+
1 OBJECTIVES
|
| 173 |
+
By the end of the class the students should be able to use the past continuous while engaging in a conversation about what they did last weekend
|
| 174 |
+
|
| 175 |
+
2 CONTEXT
|
| 176 |
+
●Show some pictures of people doing fun or relaxing things and students describe them (learning the relevant vocabulary such as the action verbs – reading a book, playing tennis, etc)
|
| 177 |
+
●Then the students ask the teacher questions to find out what s/he did last weekend or typically does on the weekend. (It’s fine if the students don’t use the past continuous and they shouldn’t be expected to if they haven’t been taught it yet. In fact, the past continuous isn’t part of the lesson plan until later in the Presentation stage).
|
| 178 |
+
|
| 179 |
+
3 INPUT TASK 1: READING FOR GIST
|
| 180 |
+
Best title
|
| 181 |
+
●Write on the board 3 titles and tell the students they have to decide which one (A, B or C) is the most suitable for the reading.
|
| 182 |
+
●Give the students the reading and 60 seconds to complete the task.
|
| 183 |
+
●Ask the students to say their choice(s) and say why. When all the choices have been gone over, tell them the correct answer.
|
| 184 |
+
|
| 185 |
+
4 INPUT TASK 2: READING FOR SPECIFIC INFORMATION
|
| 186 |
+
●Give the students a handout with six sentences. All six sentences reflect what happened in the text they just read, but each sentence has one mistake. Students are asked to look at the example of the first sentence and make similar corrections for the remaining five. NOTE: These mistakes reflect understanding the contents of the text, NOT any grammar errors. Ex: Julie went to the market on Saturday. Friday
|
| 187 |
+
●Students complete task individually, compare answers with another student, then go over their answers as a class.
|
| 188 |
+
© maxenglishcorner.com 2020 PPP lesson planning example 2
|
| 189 |
+
|
| 190 |
+
5 PRESENTATION 1
|
| 191 |
+
PAST CONTINUOUS: Form & Ongoing Action in Past
|
| 192 |
+
●Write on the board two sentences found in the first paragraph of the text. Ex: There was a lot of traffic. Lots of people were going to the beach.
|
| 193 |
+
●Elicit the names of the two verb forms and write them above the examples.
|
| 194 |
+
●Elicit the structure of each. (regular verb in past simple form = verb + ED) (past continuous verb has 2 parts: be auxiliary in past + verb in ING form) ●Elicit how to create the negative forms and write those sentences on the board ●Elicit how to create a WH question (and answer) ●Elicit how to create a YES/NO question (and positive & negative answer) ●Elicit when to use the past continuous. (Focus on Concepts 1 & 2 but accept others) These concepts are explained in Part D of The PPP Model Explained and refer to particular situations that would be appropriate for using the past continuous. You want the students to understand that they can use the past continuous form when describing a general situation happening in the past (ex: It was raining yesterday), or when a particular action lasted for a period of time and you want to bring attention to that (ex: It was raining all night).
|
| 195 |
+
●Before continuing on to the Practice tasks, ask different students comprehension check questions, testing them on what they understand of what has been presented so far.
|
| 196 |
+
6 PRACTICE set 1
|
| 197 |
+
PRACTICE 1-1
|
| 198 |
+
●Give students worksheet. Explain exercise 1-1: There are 5 gap-fill sentences to complete, writing the past continuous form with the provided prompts. Ex: She __________ football yesterday. (not play) (She wasn’t playing football yesterday.)
|
| 199 |
+
●Students do it individually, check in pairs, then go over answers with class
|
| 200 |
+
PRACTICE 1-2
|
| 201 |
+
●Exercise 2 on worksheet. Students invent answers to respond to WH and Yes/No questions. Ex: What were they doing? __________ (They were sleeping. – for example) Was he studying? (+) __________ OR (-) __________ (Yes, he was. OR No, he wasn’t.) ●Model one or two examples first.
|
| 202 |
+
●As above, students do it individually, check in pairs, then the answers are gone over
|
| 203 |
+
PRACTICE 1-3
|
| 204 |
+
Have the students ask you past continuous questions about your last weekend. Encourage both WH & Yes/No questions. Allow other questions too, like past simple and present simple, and if they make mistakes, guide them by eliciting the right form of question to ask or the key elements which would help them decide which form to use.
|
| 205 |
+
7 PRESENTATION 2
|
| 206 |
+
PAST CONTINUOUS: Action happening at a specific time in the past
|
| 207 |
+
●Write on the board the following question and answer: What were you doing at ten o’clock last night? I was watching TV.
|
| 208 |
+
●Elicit if the action was for a duration (ex: for 3 hours) (No), a description in general (ex: the sun was shining) (No) or for an action happening (in progress) at a specific time in the past (Yes!)
|
| 209 |
+
© maxenglishcorner.com 2020 PPP lesson planning example 2
|
| 210 |
+
●Point out that this is a different function (situation to use the verb tense). Ask students if there are any changes to the form in the question or answer. (No)
|
| 211 |
+
●Draw a time line (see Concept #5) As in Presentation 1, the past continuous can be used in different situations. In this case it is for a continuous action happening at a certain point in time in the past.
|
| 212 |
+
●Elicit or provide more WH questions: - - What were you watching on TV (at that time)? - - Who were you watching TV with (at that time)? - - What were you doing at 11:00 last night?
|
| 213 |
+
●And elicit some Yes/No questions:
|
| 214 |
+
- - Were you watching TV at 10:30? (Yes, I was. // No, I wasn’t.) - - Were you eating at 6:15?
|
| 215 |
+
8 PRACTICE set 2
|
| 216 |
+
PRACTICE 2-1
|
| 217 |
+
●Students write questions to ask partner about last night (with specific times). If students seem to be able to handle it, ask them to write two WH questions and two Yes/No questions. If not, do 3 WH questions only. ●Teacher monitors and helps/guides when necessary.
|
| 218 |
+
PRACTICE 2-2
|
| 219 |
+
●Students are placed into pairs. One student is to ask a WH question, and the other answers it. Model first with two students so they are clear on the task instructions. Then students carry out the task and the teacher monitors. ●In the same pairs, students change roles.
|
| 220 |
+
PRACTICE 2-3
|
| 221 |
+
●If only WH questions were done previously, then repeat tasks 2-1 and 2-2 but for Yes/No questions this time.
|
| 222 |
+
9 PRESENTATION 3
|
| 223 |
+
Focus on enriching the students’ approach to speaking
|
| 224 |
+
●Teacher goes into ‘hot seat’ role where students have to ask WH and Yes/No questions about what s/he was doing yesterday. ●Teacher points out that simply asking a list of unrelated questions soon exhausts the activity. The students can enrich their speaking by 1) asking follow-up questions – not all of which have to be in the past continuous form (ex: Do you do that every night?) 2) making comments – (ex: That’s interesting. Me too. I was doing that too.) 3) volunteering information about themselves – I don’t like to watch TV. I prefer to do other things in my free time…..) ●Teacher chooses one student to be in the hot seat and the class asks that person about her/his day yesterday. The teacher encourages follow-up questions, comments from the class, as well as volunteering information about themselves.
|
| 225 |
+
© maxenglishcorner.com 2020 PPP lesson planning example 2 10 PRACTICE set 3
|
| 226 |
+
PRACTICE 3-1
|
| 227 |
+
●Students are divided into groups of 3 or 4, one person in each group is in the hot seat, and they ask and speak about yesterday. (Some questions and sentences are in the past continuous, but many aren’t.) Teacher monitors. ●After a few minutes the teacher tells the students to select a new person for the hot seat. Teacher monitors.
|
| 228 |
+
After a few more minutes teacher stops activity and addresses class, offering a little feedback (such as encouragement, advice and eliciting corrections to some mistakes).
|
| 229 |
+
PRACTICE 3-2 Dress Rehearsal for Production Speaking Activity
|
| 230 |
+
●Students stay in the same groups. Rather than focusing on just one person who is in a hot seat role, tell them to imagine they are having a coffee together and a short conversation about what they did yesterday. Encourage the people to all participate, volunteer information, make comments and ask questions, including follow-up questions.
|
| 231 |
+
●Teacher monitors and prompts them as the students attempt to have a conversation for five minutes.
|
| 232 |
+
●At the end of the activity, teacher gives some feedback such as tips, recognition of what they were doing well, some corrections on mistakes made when using the past simple or continuous, and more encouragement for everyone to participate in the conversation.
|
| 233 |
+
11 PRODUCTION
|
| 234 |
+
●The teacher changes the groups so there are new members in each group.
|
| 235 |
+
●The students are told to do the same thing as before, only now the theme of their conversation is to talk about last weekend. They can find out how their weekends were similar or different, and if the weekend was unusual or like every other weekend.
|
| 236 |
+
●This time the teacher does not intervene and s/he tells them so. They will have up to 5 minutes to speak about the theme and the teacher will not be participating or helping in any way. It is up to them to maintain the conversation.
|
| 237 |
+
●The students engage in their conversations the best they can.
|
| 238 |
+
12 FEEDBACK
|
| 239 |
+
●As with the dress rehearsal, the teacher gives feedback in the form of corrections, tips and reminders, and pointing out what the students did well.
|
| 240 |
+
HOMEWORK
|
| 241 |
+
●The students have to write 150 words about what they did last weekend, including at least one example of the past continuous for Concept 1* and at least one example of Concept 5*.
|
| 242 |
+
*NOTE: ‘Concept 1’ and ‘Concept 5’ are not the official names or numbers of these referenced situations. They were only used for the purposes of this article and can be seen as they were presented in The PPP Model Explained, Section D. They could very easily be called Situation 1 and Situation 2 or any other title that the teacher may prefer to use.
|
| 243 |
+
"""
|
app/knowledge_base/Methods.md
ADDED
|
@@ -0,0 +1,113 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
1. Логика построения урока: цепочка решений
|
| 2 |
+
Диагностика входных данных
|
| 3 |
+
|
| 4 |
+
Учитель отмечает: учебник, страница, тема, уровень, возраст, цель (в широком смысле).
|
| 5 |
+
|
| 6 |
+
LLM сканирует страницу, извлекает явные элементы (лексика в рамке, заголовки, упражнения) и составляет первичный список «возможного целевого языка» (слов, структур, функций).
|
| 7 |
+
|
| 8 |
+
Выбор целевого языка (teacher-in-the-loop)
|
| 9 |
+
|
| 10 |
+
LLM выдаёт 2–3 кандидатуры “target language” (например, “Present Perfect for life experiences”, “Vocabulary: holiday activities”), на основе чего есть на странице.
|
| 11 |
+
|
| 12 |
+
Учитель подтверждает или уточняет (дописывает свой вариант).
|
| 13 |
+
|
| 14 |
+
Построение плана по фазам PPP
|
| 15 |
+
|
| 16 |
+
Presentation: LLM предлагает контекст-активность, опираясь на выбранный target language.
|
| 17 |
+
|
| 18 |
+
Practice: LLM генерирует контролируемые упражнения по выбранному языку.
|
| 19 |
+
|
| 20 |
+
Production: LLM предлагает коммуникативное задание, где ученики применяют язык.
|
| 21 |
+
|
| 22 |
+
Учитель верифицирует и дорабатывает
|
| 23 |
+
|
| 24 |
+
Промпт закладывает, что LLM после генерации каждого этапа спрашивает: “Нужны ли дополнительные опоры (чек-лист, подсказки)?”
|
| 25 |
+
|
| 26 |
+
Учитель вносит правки, модель «догружает» до финальной версии.
|
| 27 |
+
|
| 28 |
+
|
| 29 |
+
|
| 30 |
+
|
| 31 |
+
|
| 32 |
+
|
| 33 |
+
|
| 34 |
+
|
| 35 |
+
|
| 36 |
+
|
| 37 |
+
Метод PPP даёт прочный каркас, а гибкость в упражнениях позволяет адаптировать урок под возраст и уровень учеников.
|
| 38 |
+
|
| 39 |
+
|
| 40 |
+
Методика | Суть | Когда применять
|
| 41 |
+
PPP (Presentation-Practice-Production) | Чёткая трёхступенчатая структура: презентация языка → контролируемая практика → свободное применение. | Уровни A1–B1, акцент на грамматике/лексике, нуждается в высокой структурированности урока .
|
| 42 |
+
TTT (Test-Teach-Test) | Сначала диагностическое задание (тест), затем целевое обучение, затем повторный тест. | Подготовка к экзаменам (IELTS, TOEFL), уровни B1+, когда важно оценить и проработать пробелы .
|
| 43 |
+
ESA (Engage-Study-Activate) | Гибкая чередующаяся модель: вовлечение → изучение → активизация. | Когда нужна вариативность, интеграция коммуникативных задач и языкового разборе; подходит для всех уровней .
|
| 44 |
+
TBL (Task-Based Learning) | Урок строится вокруг смысловой задачи; языковой фокус после выполнения. | Коммуникативная практика, survival-skills, взрослые/подростки B1+; длительные проекты .
|
| 45 |
+
TPR (Total Physical Response) | Физические действия в ответ на языковые команды. | Младшие школьники, A1–A2, ввод глагольной лексики, сниженная тревожность .
|
| 46 |
+
PBL (Project-Based Learning) | Долгосрочные проекты по проблемному вопросу. | Школьный возраст, смешанные уровни, междисциплинарные темы, развивает крит. мышление и навыки 21 века .
|
| 47 |
+
CLIL (Content and Language Integrated Learning) | Изучение предмета (науки, истории) через ИЯ. | Когда цель — одновременно развивать предметные и языковые компетенции; старшие классы .
|
| 48 |
+
Лексический подход | Фокус на лексических «чанках» (collocations), а не на грамматике. | Расширение говорения и понимания «нативных» фраз, уровни B1+ .
|
| 49 |
+
Грамматико-переводной (GTM) | Изучение грамматических правил + перевод. | Академические группы, старшие подростки/студенты, чтение литературы .
|
| 50 |
+
Прямой метод | Полное погружение: только ИЯ, индуктивное изучение грамматики. | Низкие-средние уровни, малые группы, когда цель — устная беглость .
|
| 51 |
+
Аудиолингвальный (ALM) | Повторение, имитация, структурные упражнения. | Быстрая отработка структур, курсы в языковых лабораториях, уровни A1–B1 .
|
| 52 |
+
|
| 53 |
+
|
| 54 |
+
Параметр | Рекомендации по выбору методики
|
| 55 |
+
CEFR-уровень | A1–A2: PPP, TPR, ALM; B1–B2: ESA, TBL, Лексический; B2–C1: CLIL, TBL, GTM (для чтения) .
|
| 56 |
+
Возраст | Дети (6–10): TPR, ESA; Подростки (11–17): PPP, ESA, PBL; Взрослые: TBL, CLIL, GTM .
|
| 57 |
+
Количество учеников | Индивидуально/малые группы: Direct Method, ALM, TTT; Большие группы: ESA, PPP, TBL .
|
| 58 |
+
Тема и цель | Грамматика/лексика: PPP, ALM; Коммуникация: ESA, TBL; Проект/исследование: PBL, CLIL .
|
| 59 |
+
Длительность | 30–45 мин: PPP, TPR; 60–90 мин: ESA, TBL; более 1 урока: PBL, CLIL .
|
| 60 |
+
Оборудование | Минимум (доска, карточки): PPP, Direct; Tech-rich (видео, интернет): ESA, CLIL, PBL .
|
| 61 |
+
Доп. сведения от учителя | Экзаменационная цель → TTT; Особенности учеников (интересы) → ESA, PBL .
|
| 62 |
+
|
| 63 |
+
|
| 64 |
+
Гибкость vs. структура
|
| 65 |
+
|
| 66 |
+
Укажите, где методика должна быть жёстко соблюдена (этапы PPP) и где возможна вариативность (ESA-фазы, творческие задания).
|
| 67 |
+
|
| 68 |
+
Примеры
|
| 69 |
+
|
| 70 |
+
Приведите 1–2 коротких образца активности (не целый план), чтобы задать тон (например, «групповое задание: спланировать…»).
|
| 71 |
+
|
| 72 |
+
Критерии качества
|
| 73 |
+
|
| 74 |
+
Опишите, на что обратить внимание: достижение цели, интересность, соответствие уровню, баланс навыков.
|
| 75 |
+
|
| 76 |
+
Творческий простор
|
| 77 |
+
|
| 78 |
+
Добавьте фразу: «Предлагай нестандартные идеи, но обосновывай их ссылкой на методику».
|
| 79 |
+
|
| 80 |
+
Итого, для надёжного промпта достаточно:
|
| 81 |
+
|
| 82 |
+
кратких описаний методик (экстракты),
|
| 83 |
+
|
| 84 |
+
чёткого перечисления ваших параметров,
|
| 85 |
+
|
| 86 |
+
примеров активностей,
|
| 87 |
+
|
| 88 |
+
критериев оценки.
|
| 89 |
+
|
| 90 |
+
|
| 91 |
+
|
| 92 |
+
|
| 93 |
+
Класс цели | Подкласс / тип | Пример формулировки цели | Когда актуально
|
| 94 |
+
1. Навыковые (Skills) Macmillan Education ELT
|
| 95 |
+
| • Чтение (Reading) | «Уметь находить в тексте информацию по конкретному вопросу» | Подготовка к экзаменам, работа с аутентичными текстами
|
| 96 |
+
| • Аудирование (Listening) | «Понимать основную идею аудиозаписи на бытовую тему» | Уроки восприятия речи, фильмы, аудиоматериалы
|
| 97 |
+
| • Говорение (Speaking) | «Свободно рассказать о своём вчерашнем дне» | Коммуникативные уроки, ролевые игры
|
| 98 |
+
| • Письмо (Writing) | «Написать письмо–запрос на английском языке» | Деловой английский, подготовка к письменным заданиям
|
| 99 |
+
2. Языковые (Language)
|
| 100 |
+
| • Лексика (Vocabulary) | «Выучить 15 новых слов по теме “Путешествия”» | Уроки лексического развития
|
| 101 |
+
| • Грамматика (Grammar) | «Освоить Past Perfect для описания завершённых действий» | Фокусные грамматические занятия
|
| 102 |
+
| • Функциональный язык (Functions) | «Уметь просить и давать указания (imperatives)» | Диалоговые ситуации, телефонирование
|
| 103 |
+
| • Произношение (Pronunciation) | «Отрабатывать звуки /θ/ и /ð/ в словах и предложениях» | Фонетические тренировки
|
| 104 |
+
3. Стратегии (Strategies)
|
| 105 |
+
| • Learning strategies | «Научиться конспектировать аудиотекст» | Развитие автономии, подготовка к академическим целям
|
| 106 |
+
| • Reading strategies | «Использовать сканирование (skimming) для общей идеи» | Работа с большим объемом текста
|
| 107 |
+
4. Коммуникативные (Communicative)
|
| 108 |
+
| • Fluency vs Accuracy | «Развить беглость речи при рассказе истории» | Свободное общение, дискуссии
|
| 109 |
+
| • Interaction skills | «Уметь поддержать беседу в паре по заданной теме» | Парная/групповая работа
|
| 110 |
+
5. Междисциплинарные / жизненные (Life & 21st-C)
|
| 111 |
+
| • Critical thinking | «Анализировать и критиковать аргументы в тексте» | Старшие классы, CLIL-проекты
|
| 112 |
+
| • Collaboration skills | «Совместно спланировать школьное мероприятие» | Проектная работа (PBL)
|
| 113 |
+
| • Cultural awareness | «Понимать различия в межкультурном общении» | CLIL, межкультурные обмены
|
app/knowledge_base/check_list.md
ADDED
|
@@ -0,0 +1,41 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
📋 ЧЕК-ЛИСТ: Как выбрать Target Language для урока
|
| 2 |
+
По материалу страницы
|
| 3 |
+
|
| 4 |
+
Есть ли выделенные слова, грамматические конструкции, выражения?
|
| 5 |
+
|
| 6 |
+
Присутствуют ли готовые списки лексики, примеры диалогов, грамматические таблицы?
|
| 7 |
+
|
| 8 |
+
По теме урока
|
| 9 |
+
|
| 10 |
+
Какие языковые средства необходимы, чтобы говорить на заданную тему?
|
| 11 |
+
|
| 12 |
+
Какие ключевые слова или фразы необходимы для выполнения основной задачи урока?
|
| 13 |
+
|
| 14 |
+
По цели занятия
|
| 15 |
+
|
| 16 |
+
Требуется развитие навыков речи, слушания, чтения, письма?
|
| 17 |
+
|
| 18 |
+
Какая языковая поддержка нужна для достижения цели?
|
| 19 |
+
|
| 20 |
+
По возрасту и уровню учащихся
|
| 21 |
+
|
| 22 |
+
Возраст: Нужно ли упростить язык для младших/младших подростков?
|
| 23 |
+
|
| 24 |
+
Уровень:
|
| 25 |
+
|
| 26 |
+
A1–A2 → простые слова, базовые структуры (3–5 единиц)
|
| 27 |
+
|
| 28 |
+
B1–B2 → более сложные выражения, фразовые глаголы, конструкции (5–7 единиц)
|
| 29 |
+
|
| 30 |
+
C1–C2 → идиомы, формулы дискурса, редкие слова (7–9 единиц)
|
| 31 |
+
|
| 32 |
+
По типу языка
|
| 33 |
+
|
| 34 |
+
Лексика, грамматика, функциональный язык, произношение, идиомы, фразовые глаголы.
|
| 35 |
+
|
| 36 |
+
Иногда комбинация (например: модальные глаголы + фразы для просьб).
|
| 37 |
+
|
| 38 |
+
По практическому применению
|
| 39 |
+
|
| 40 |
+
Какие языковые единицы учащиеся реально смогут использовать в финальной части (Production)?
|
| 41 |
+
|
app/knowledge_base/inspire.md
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
The theories behind it, the materials and activities that become part of it, the suggestions and the models one can follow, all have to deal with the inevitable:
|
| 2 |
+
that it is only a plan and whatever shape it takes, it is to be used in the classroom.
|
| 3 |
+
|
| 4 |
+
|
| 5 |
+
Креативные варианты:
|
| 6 |
+
|
| 7 |
+
«Создайте мем с фразой из текста и обсудите её значение».
|
| 8 |
+
|
| 9 |
+
«Найдите «странное» предложение в тексте и объясните, почему оно выделяется».
|
app/knowledge_base/lesson_frameworks.md
ADDED
|
@@ -0,0 +1 @@
|
|
|
|
|
|
|
| 1 |
+
ва ва
|
app/knowledge_base/test.md
ADDED
|
@@ -0,0 +1,23 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
|
| 2 |
+
Фрагмент:
|
| 3 |
+
"Упражнение 1b (стр. 8) – табличка «What information is on each card?»
|
| 4 |
+
– Ученики в тетрадях отмечают крестиком (X), какую информацию (full name, expiry date и т.д.) они видят на каждой карте."
|
| 5 |
+
|
| 6 |
+
Комментарий:
|
| 7 |
+
Хорошо бы в плане сделать набросок таблички в плане, чтобы учитель сразу понимал, как это организовать
|
| 8 |
+
|
| 9 |
+
В промпт:
|
| 10 |
+
Используй в плане условные визуальные схемы при необходимости.
|
| 11 |
+
Например, если нужно что-то нарисовать на доске или какую-то таблицу вынести в тетрадь - приведи общий (для понимания сути) набросок в плане
|
| 12 |
+
|
| 13 |
+
Проверка:
|
| 14 |
+
|
| 15 |
+
|
| 16 |
+
|
| 17 |
+
|
| 18 |
+
2. Проведите тестирование
|
| 19 |
+
Сравните качество планов уроков:
|
| 20 |
+
|
| 21 |
+
С указанным учебником.
|
| 22 |
+
|
| 23 |
+
Без него (когда модель определяет его сама).
|
app/knowledge_base/test_samples/PPP_Spotlight 5_1.md
ADDED
|
@@ -0,0 +1,166 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
user
|
| 2 |
+
Ты — опытый ESL-методист. Ты помогаешь учителям составлять грамотные и интересные планы занятий.
|
| 3 |
+
Разработай план урока на материале загруженной страницы учебника. Максимально опирайся на этот материал.
|
| 4 |
+
Перед тем как генерировать план, обдумай этапы урока по методологии PPP (Presentation-Practice-Production). с учетом всех вводных параметров занятия.
|
| 5 |
+
Будь гибким: адаптируй идеи под реальный контекст занятия, проявляй педагогическое чутьё, не копируй механически структуру. Главная цель — сделать урок живым и полезным!
|
| 6 |
+
На всех этапах урока используй материал страницы как основной источник. Указывай номера упражнений в плане.
|
| 7 |
+
|
| 8 |
+
Параметры занятия:
|
| 9 |
+
- УМК: попробуй определи визуально через логотипы, заголовки, структуру
|
| 10 |
+
- Уровень УМК по CEFR: определи по сложности текста/упражнений или по названию учебника
|
| 11 |
+
- Тема: выяви через ключевые слова/изображения на странице
|
| 12 |
+
- Цель: сформулируй как 'К концу урока ученики смогут...'
|
| 13 |
+
- Продолжительность: 60 мин
|
| 14 |
+
- Количество учеников: 10 чел
|
| 15 |
+
- Возраст: 11-12 лет (учти: дети: фокус на играх, движении, визуалах, коротких активностях)
|
| 16 |
+
- Методология занятия: PPP (Presentation-Practice-Production)
|
| 17 |
+
- Целевой язык: определи самостоятельно по загруженной странице,
|
| 18 |
+
- Дополнительная информация от учителя: не указано
|
| 19 |
+
- Оборудование/инвентарь: стандартный класс + проектор
|
| 20 |
+
- Необходимость домашнего задания: не требуется
|
| 21 |
+
|
| 22 |
+
|
| 23 |
+
|
| 24 |
+
[МЕТОДИКА PPP]
|
| 25 |
+
📝 Чек-лист перед генерацией этапов урока:
|
| 26 |
+
Кто мои ученики? (Возраст, уровень CEFR, сильные/слабые стороны)
|
| 27 |
+
Что за материал на странице? (Лексика, грамматика, темы — что важно освоить?)
|
| 28 |
+
Какая цель урока? (Что ученики должны уметь делать к концу?)
|
| 29 |
+
Какая активность наиболее естественна для этого контекста? (Диалог, игра, проект, обсуждение?)
|
| 30 |
+
Какой тип упражнений соответствует целям? (Контролируемые / полуконтролируемые / свободная практика?)
|
| 31 |
+
Нужно ли предусмотреть поддержку слабых учеников? (Подсказки, шаблоны, парная работа)
|
| 32 |
+
Как я дам обратную связь после практики? (Похвала + 1–2 рекомендации для улучшения)
|
| 33 |
+
|
| 34 |
+
Перед разработкой этапа задай себе краткий вопросник (чек-лист выше), чтобы лучше почувствовать уровень учеников, специфику материала и выбрать подходящие активности.
|
| 35 |
+
Ориентируйся на содержание страницы, параметры урока и свое "учительское чутье".
|
| 36 |
+
|
| 37 |
+
Presentation (20–25% времени) — Выбери главный target language (лексика или структура) по материалу страницы. — Введите новое языковое содержимое через три канала: понимание (meaning), форма (form), произношение (pronunciation). — Определите количество новых языковых единиц в зависимости от уровня CEFR и возраста учащихся, чтобы обеспечить оптимальное усвоение материала. — Предусмотри, где эти единицы будут представлены письменно (доска, раздатки, заметки). — Дополни план идеями для активации внимания: короткий диалог, обсуждение картинки, мини-видео.
|
| 38 |
+
Этап 2: Practice (30–40% времени занятия)
|
| 39 |
+
|
| 40 |
+
Построй этап на базе target language, выбранного на предыдущей фазе.
|
| 41 |
+
Используй материал страницы учебника как основу для упражнений (переформатируй задания при необходимости, но сохраняй их смысл и структуру).
|
| 42 |
+
|
| 43 |
+
Организуй 2–3 упражнения, начиная с полностью контролируемых к более свободным:
|
| 44 |
+
Controlled Practice:
|
| 45 |
+
— drills (substitution, transformation, repetition);
|
| 46 |
+
— sentence formation exercises;
|
| 47 |
+
— simple gap-fills, где нет вариативности в ответах.
|
| 48 |
+
|
| 49 |
+
Semi-controlled Practice:
|
| 50 |
+
— gap-fills с выбором из нескольких возможных ответов;
|
| 51 |
+
— matching (словосочетание–перевод, начало–конец предложения);
|
| 52 |
+
— guided sentence or dialogue completion.
|
| 53 |
+
|
| 54 |
+
Цель этапа: закрепить понимание значения, формы и произношения целевого языка.
|
| 55 |
+
Подбирай тип упражнений, учитывая возраст, уровень CEFR, продолжительность урока и количество учеников (пары, мини-группы и т.д.).
|
| 56 |
+
Продумай, как предоставить минимальный фидбэк (например, общее исправление ошибок после каждого упражнения).
|
| 57 |
+
|
| 58 |
+
Этап 3: Production (25–35% времени занятия)
|
| 59 |
+
|
| 60 |
+
Построй задание на свободное использование target language.
|
| 61 |
+
Используй материал страницы как отправную точку для ситуации, но адаптируй или дополни её, чтобы задание требовало активного создания речи учениками.
|
| 62 |
+
Возможные типы заданий:
|
| 63 |
+
- Ролевые игры (role plays): в парах, мини-группах;
|
| 64 |
+
- Мини-проекты: например, создать постер, сценарий, презентацию;
|
| 65 |
+
- Обсуждения и дебаты;
|
| 66 |
+
- Симуляции реальных ситуаций;
|
| 67 |
+
- Storytelling (рассказывание истории, дополнение истории по картинкам);
|
| 68 |
+
- Игры на использование языка (интервью, "Find someone who...", викторины).
|
| 69 |
+
|
| 70 |
+
Обязательно оставь место для устной обратной связи после задания:
|
| 71 |
+
- Сначала позитив: что получилось хорошо;
|
| 72 |
+
- Потом мягкие рекомендации: 2–3 главных направления для улучшения (аккуратность, использование новых выражений, беглость).
|
| 73 |
+
Подбирай активность с учётом возраста, уровня и характера группы (например, подростки предпочитают соревновательные задания, взрослые — практические кейсы).
|
| 74 |
+
|
| 75 |
+
** Корректировки длительности этапов для разных уровней**:
|
| 76 |
+
Начинающие (A1-A2):
|
| 77 |
+
• Увеличить Practice до 45-50% (больше повторений и структурированных упражнений).
|
| 78 |
+
• Сократить Production до 20% (менее сложные задания).
|
| 79 |
+
|
| 80 |
+
Продвинутые (B2-C1):
|
| 81 |
+
• Сократить Presentation до 15% (быстрый ввод материала).
|
| 82 |
+
• Увеличить Production до 35-40% (больше дискуссий/кейсов).
|
| 83 |
+
|
| 84 |
+
|
| 85 |
+
|
| 86 |
+
#######################
|
| 87 |
+
|
| 88 |
+
|
| 89 |
+
План урока «Who are you?» (УМК: предп. «English World» Starter, стр. 8)
|
| 90 |
+
Уровень CEFR: A1
|
| 91 |
+
Тема: Формы удостоверений личности и личные данные
|
| 92 |
+
Цель: К концу урока ученики смогут узнать и назвать четыре вида карт: identity card, driving licence, credit card, membership card;
|
| 93 |
+
задавать и отвечать на вопросы о личных данных: name, address, postcode, telephone number;
|
| 94 |
+
уметь произносить и писать своё имя и адрес по буквам. Возраст: 11–12 лет Продолжительность: 60 мин Класс: 10 человек Оборудование: проектор, доска, маркеры, распечатанные карточки (А, B, C, D) и бланки «VIDEOWORLD» для практики, карточки-анкеты для ролевой игры. Домашнее задание: не задаётся
|
| 95 |
+
|
| 96 |
+
Подготовительный чек-лист (для себя, учитель):
|
| 97 |
+
• Ученики A1, 11–12 лет, нуждаются в большом количестве визуальной поддержки, движениях и парной работе. • Материал: лексика (4 типа карт), функциональный язык (запрос личных данных, правописание по буквам), восприятие на слух и чтение диалога. • Основная цель – научить узнавать карты и заполнять анкету, задавая и отвечая на вопросы. • Поддержка слабых: раздатки с подсказками (список слов, таблица букв).
|
| 98 |
+
Этап 1. Presentation (12 мин, 20%)
|
| 99 |
+
1.1. Введение темы (2 мин)
|
| 100 |
+
– Показать на проекторе четыре картинки карточек (A–D).
|
| 101 |
+
– Вопрос к классу: What are these? (слайд/доска)
|
| 102 |
+
– Ученики называют то, что понимают; записать ключевые слова на доске: identity card, driving licence, credit card, membership card.
|
| 103 |
+
|
| 104 |
+
1.2. Meaning–Form–Pronunciation (10 мин)
|
| 105 |
+
a) Meaning
|
| 106 |
+
– Картинки по очереди: учитель показывает Identity card – What is this? – обозначает функцию (to prove who you are).
|
| 107 |
+
– Аналогично с driving licence (to drive), credit card (to pay), membership card (to enter a club).
|
| 108 |
+
b) Form
|
| 109 |
+
– На доске выписать каждое словосочетание, подчеркнуть раздельность слов и правописание.
|
| 110 |
+
– Попросить учеников прочитать по цепочке (substitution drill): “This is a …”
|
| 111 |
+
c) Pronunciation
|
| 112 |
+
– Чак-репит (choral drilling) с акцентом на /aɪˌden.tɪ.ti kɑːd/, /draɪ.vɪŋ ˈlaɪ.səns/, /ˈkre.dɪt kɑːd/, /ˈmem.bə.ʃɪp kɑːd/.
|
| 113 |
+
– Индивидуальные повторы для слабых (teacher monitors).
|
| 114 |
+
|
| 115 |
+
Доп. функционал: фраза «How do you spell that?»
|
| 116 |
+
– Учитель моделирует мини-диалог с учеником у доски, спрашивает имя и просит написать по буквам.
|
| 117 |
+
|
| 118 |
+
|
| 119 |
+
Этап 2. Practice (25 мин, 40%)
|
| 120 |
+
2.1. Controlled Practice (10 мин)
|
| 121 |
+
Упражнение 1a (стр. 8):
|
| 122 |
+
– В парах ученики смотрят на карточки A–D и подписывают их тип (credit card, driving licence, identity card, sports/membership card).
|
| 123 |
+
– Проверка хором, учитель исправляет.
|
| 124 |
+
|
| 125 |
+
Упражнение 1b (стр. 8) – табличка «What information is on each card?»
|
| 126 |
+
– Ученики в тетрадях отмечают крестиком (X), какую информацию (full name, expiry date и т.д.) они видят на каждой карте.
|
| 127 |
+
– Короткий общий разбор (teacher elicits ответы).
|
| 128 |
+
|
| 129 |
+
2.2. Semi-controlled Practice (15 мин)
|
| 130 |
+
Упражнение 2b (стр. 8) – заполнение Membership Card (VIDEOWORLD)
|
| 131 |
+
– Раздать карточки-анкету и текст диалога (сокращённо).
|
| 132 |
+
– В парах один читает реплики Penny, другой – Jane; заполняют поля Name, Surname, Address, Postcode, Phone Number, Membership Number.
|
| 133 |
+
– После – сравнение в группах, учитель вешает заполненный бланк на доску и сверяет.
|
| 134 |
+
|
| 135 |
+
Упражнение 3 (стр. 8) – What are these numbers?
|
| 136 |
+
– Индивидуально: ученики подписывают к цифрам (1–10; 2–7125 9990; 3–SW1 4TA).
|
| 137 |
+
– Обсуждение в парах, общий фидбэк.
|
| 138 |
+
|
| 139 |
+
Этап 3. Production (18 мин, 30%)
|
| 140 |
+
Ролевая игра «Join the club»
|
| 141 |
+
3.1. Подготовка (3 мин)
|
| 142 |
+
– Раздать каждому ученику карточку-анкету (аналог видеомира) с незаполненными полями.
|
| 143 |
+
– Разделить класс на тройки: receptionist + 2 new members.
|
| 144 |
+
|
| 145 |
+
3.2. Ролевая игра (10 мин)
|
| 146 |
+
– Receptionist задаёт вопросы:
|
| 147 |
+
– What’s your name? How do you spell that?
|
| 148 |
+
– Where do you live? What’s your postcode?
|
| 149 |
+
– What’s your telephone number?
|
| 150 |
+
– Новые члены отвечают и заполняют анкету.
|
| 151 |
+
– Меняются ролями, переходят к следующему партнёру.
|
| 152 |
+
|
| 153 |
+
3.3. Отзыв и коррекция (5 мин)
|
| 154 |
+
– Собрать 2–3 пары к доске, попросить кратко провести интервью и показать заполненные анкеты.
|
| 155 |
+
– Позитивная обратная связь:
|
| 156 |
+
– «Great pronunciation of postcode!»
|
| 157 |
+
– «Well done using full sentences!»
|
| 158 |
+
– Рекомендации:
|
| 159 |
+
– «Don’t forget to spell your surname slower.»
|
| 160 |
+
– «Use the phrase “I live at…” for address.»
|
| 161 |
+
|
| 162 |
+
Итого:
|
| 163 |
+
Presentation 12 мин (20%)
|
| 164 |
+
Practice 25 мин (40%)
|
| 165 |
+
Production 18 мин (30%)
|
| 166 |
+
Оставшиеся 5 мин – организационные моменты, переходы, быстрый чектест на доске: “Match the word to the picture” для закрепления.
|
app/knowledge_base/test_samples/lesson_plan_20250426200232.docx
ADDED
|
Binary file (39.5 kB). View file
|
|
|
app/knowledge_base/test_samples/lesson_plan_20250426215122.docx
ADDED
|
Binary file (40.1 kB). View file
|
|
|
app/knowledge_base/test_samples/lesson_plan_20250426220824.docx
ADDED
|
Binary file (39.4 kB). View file
|
|
|
app/knowledge_base/textbooks.py
ADDED
|
@@ -0,0 +1,79 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Список учебников для автоподстановки (серия + уровень)
|
| 2 |
+
TEXTBOOKS = [
|
| 3 |
+
# Spotlight
|
| 4 |
+
"Spotlight Starter", "Spotlight 2", "Spotlight 3", "Spotlight 4",
|
| 5 |
+
"Spotlight 5", "Spotlight 6", "Spotlight 7", "Spotlight 8",
|
| 6 |
+
"Spotlight 9", "Spotlight 10", "Spotlight 11",
|
| 7 |
+
|
| 8 |
+
# English File
|
| 9 |
+
"English File Beginner", "English File Elementary", "English File Pre-Intermediate",
|
| 10 |
+
"English File Intermediate", "English File Upper-Intermediate", "English File Advanced",
|
| 11 |
+
|
| 12 |
+
# Headway
|
| 13 |
+
"Headway Beginner", "Headway Elementary", "Headway Pre-Intermediate",
|
| 14 |
+
"Headway Intermediate", "Headway Upper-Intermediate", "Headway Advanced",
|
| 15 |
+
|
| 16 |
+
# Solutions
|
| 17 |
+
"Solutions Elementary", "Solutions Pre-Intermediate", "Solutions Intermediate",
|
| 18 |
+
"Solutions Upper-Intermediate", "Solutions Advanced",
|
| 19 |
+
|
| 20 |
+
# Grammar in Use
|
| 21 |
+
"Basic Grammar in Use", "English Grammar in Use", "Advanced Grammar in Use",
|
| 22 |
+
|
| 23 |
+
# Starlight
|
| 24 |
+
"Starlight 2", "Starlight 3", "Starlight 4", "Starlight 5",
|
| 25 |
+
"Starlight 6", "Starlight 7", "Starlight 8", "Starlight 9",
|
| 26 |
+
"Starlight 10", "Starlight 11",
|
| 27 |
+
|
| 28 |
+
# Другие популярные
|
| 29 |
+
"Family and Friends Starter", "Family and Friends 1", "Family and Friends 2",
|
| 30 |
+
"Family and Friends 3", "Family and Friends 4", "Family and Friends 5",
|
| 31 |
+
"Family and Friends 6",
|
| 32 |
+
"Cutting Edge Starter", "Cutting Edge Elementary", "Cutting Edge Pre-Intermediate",
|
| 33 |
+
"Cutting Edge Intermediate", "Cutting Edge Upper-Intermediate", "Cutting Edge Advanced",
|
| 34 |
+
"Round-Up Starter", "Round-Up 1", "Round-Up 2", "Round-Up 3",
|
| 35 |
+
"Round-Up 4", "Round-Up 5", "Round-Up 6",
|
| 36 |
+
|
| 37 |
+
# Для взрослых (General English)
|
| 38 |
+
"Global Beginner", "Global Elementary", "Global Pre-Intermediate",
|
| 39 |
+
"Global Intermediate", "Global Upper-Intermediate", "Global Advanced",
|
| 40 |
+
|
| 41 |
+
"New English File Beginner", "New English File Elementary", "New English File Pre-Intermediate",
|
| 42 |
+
"New English File Intermediate", "New English File Upper-Intermediate", "New English File Advanced",
|
| 43 |
+
|
| 44 |
+
"Navigate A1", "Navigate A2", "Navigate B1", "Navigate B1+", "Navigate B2", "Navigate C1",
|
| 45 |
+
|
| 46 |
+
"Innovations Beginner", "Innovations Elementary", "Innovations Pre-Intermediate",
|
| 47 |
+
"Innovations Intermediate", "Innovations Upper-Intermediate", "Innovations Advanced",
|
| 48 |
+
|
| 49 |
+
"Speakout Starter", "Speakout Elementary", "Speakout Pre-Intermediate",
|
| 50 |
+
"Speakout Intermediate", "Speakout Upper-Intermediate", "Speakout Advanced",
|
| 51 |
+
|
| 52 |
+
# Бизнес-английский
|
| 53 |
+
"Market Leader Beginner", "Market Leader Elementary", "Market Leader Pre-Intermediate",
|
| 54 |
+
"Market Leader Intermediate", "Market Leader Upper-Intermediate", "Market Leader Advanced",
|
| 55 |
+
|
| 56 |
+
"Business Result Starter", "Business Result Elementary", "Business Result Pre-Intermediate",
|
| 57 |
+
"Business Result Intermediate", "Business Result Upper-Intermediate", "Business Result Advanced",
|
| 58 |
+
|
| 59 |
+
# Экзаменационные курсы
|
| 60 |
+
"Complete IELTS Bands 4-5", "Complete IELTS Bands 5-6.5", "Complete IELTS Bands 6.5-7.5",
|
| 61 |
+
"Objective First", "Objective Advanced", "Objective Proficiency",
|
| 62 |
+
"Ready for IELTS", "Ready for Advanced", "Ready for Proficiency",
|
| 63 |
+
|
| 64 |
+
# Для академических целей
|
| 65 |
+
"Academic Vocabulary in Use", "Grammar for Academic Purposes",
|
| 66 |
+
"Oxford EAP Beginner", "Oxford EAP Elementary", "Oxford EAP Pre-Intermediate",
|
| 67 |
+
"Oxford EAP Intermediate", "Oxford EAP Upper-Intermediate", "Oxford EAP Advanced",
|
| 68 |
+
|
| 69 |
+
# Специализированные
|
| 70 |
+
"English for Medicine", "English for IT", "English for Engineers",
|
| 71 |
+
"Legal English", "Financial English", "English for Tourism",
|
| 72 |
+
|
| 73 |
+
# Детские курсы (добавлено для полноты)
|
| 74 |
+
"Academy Stars Starter", "Academy Stars 1", "Academy Stars 2",
|
| 75 |
+
"Academy Stars 3", "Academy Stars 4", "Academy Stars 5", "Academy Stars 6",
|
| 76 |
+
|
| 77 |
+
"Guess What! 1", "Guess What! 2", "Guess What! 3", "Guess What! 4",
|
| 78 |
+
|
| 79 |
+
]
|
app/knowledge_base/tips.md
ADDED
|
@@ -0,0 +1,173 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
ИДЕИ:
|
| 2 |
+
Вынести рекомендации по занятию и рефлексию в отдельный блок четко
|
| 3 |
+
Структура и форматирование - четко
|
| 4 |
+
|
| 5 |
+
|
| 6 |
+
|
| 7 |
+
|
| 8 |
+
|
| 9 |
+
PPP
|
| 10 |
+
|
| 11 |
+
Важные нюансы:
|
| 12 |
+
Гибкость:
|
| 13 |
+
|
| 14 |
+
Если студенты не усвоили материал на Practice, сократите Production и добавьте упражнение.
|
| 15 |
+
|
| 16 |
+
Для уроков с грамматикой увеличьте Presentation на 5-10%.
|
| 17 |
+
|
| 18 |
+
Домашнее задание:
|
| 19 |
+
|
| 20 |
+
Не включается в тайминг. Дается в конце Production (2-3 минуты на объяснение).
|
| 21 |
+
|
| 22 |
+
Обратная связь:
|
| 23 |
+
|
| 24 |
+
Часть Production (последние 3-5 минут).
|
| 25 |
+
|
| 26 |
+
|
| 27 |
+
1. **Presentation (20-25% времени занятия)**
|
| 28 |
+
- Введите ЦЕЛЕВЫЙ ЯЗЫК (минимум 5 языковых единиц) через контекст: короткий диалог, картинку или видео, фокусируясь на значении → форме → произношении
|
| 29 |
+
- Используй визуалы или реальные объекты, чтобы зацепить внимание и активировать схемы учащихся.
|
| 30 |
+
|
| 31 |
+
2. **Practice (30-40% времени занятия)**
|
| 32 |
+
- Два–три контролируемых упражнения: drills (substitution, transformation), gap-fills, matching.
|
| 33 |
+
- Немедленно корректируй ошибки вежливо, поддерживая мотивацию
|
| 34 |
+
|
| 35 |
+
3. **Production (25-35% времени занятия)**
|
| 36 |
+
- Ролевые игры или мини-проект, где ученики свободно используют выученный язык (диалог, обсуждение)
|
| 37 |
+
- Фидбэк после: отметь сильные стороны, затем укажи 2–3 точки для улучшения
|
| 38 |
+
|
| 39 |
+
|
| 40 |
+
Возраст учащихся также влияет на восприятие нового материала:
|
| 41 |
+
|
| 42 |
+
Дети (6–12 лет): Предпочтительны визуальные и игровые методы подачи материала.
|
| 43 |
+
|
| 44 |
+
Подростки (13–17 лет): Эффективны групповые проекты и обсуждения актуальных тем.
|
| 45 |
+
|
| 46 |
+
Взрослые: Целесообразно использовать профессиональные контексты и дискуссии.
|
| 47 |
+
|
| 48 |
+
|
| 49 |
+
Что может считаться target language (целевым языком) на уроке английского:
|
| 50 |
+
|
| 51 |
+
|
| 52 |
+
Категория Примеры
|
| 53 |
+
Лексика (vocabulary) Тематические слова и выражения: еда, путешествия, эмоции
|
| 54 |
+
Грамматика (grammar) Времена, модальные глаголы, условные предложения, артикли
|
| 55 |
+
Функциональный язык (functional language) Фразы для общения: просьбы, советы, приглашения, извинения
|
| 56 |
+
Фразовые глаголы (phrasal verbs) Turn up, break down, look after
|
| 57 |
+
Идиомы (idioms) "Break the ice", "Hit the books"
|
| 58 |
+
Произношение (pronunciation features) Интонация вопросов, соединение слов (linking sounds), ударение
|
| 59 |
+
Орфография (spelling patterns) Правила написания: окончания -ing, суффиксы и префиксы
|
| 60 |
+
Синтаксис (syntax) Порядок слов в вопросах, порядок прилагательных
|
| 61 |
+
Функции дискурса (discourse markers) Well, actually, you know, I mean...
|
| 62 |
+
Социальные формы речи (register) Формальный/неформальный стиль общения
|
| 63 |
+
|
| 64 |
+
|
| 65 |
+
|
| 66 |
+
1. Контролируемые упражнения (Controlled Practice)
|
| 67 |
+
Фокус на точности, минимум свободы.
|
| 68 |
+
|
| 69 |
+
Тип упражнения Описание Источник
|
| 70 |
+
Repetition drills Хоровое или индивидуальное повторение целевых фраз/звуков.
|
| 71 |
+
Substitution drills Замена одной части фразы другой (e.g., “I like tea” → “She likes coffee”).
|
| 72 |
+
Transformation drills Преобразование предложений (утвердит. → вопросит.).
|
| 73 |
+
Gap-fill (cloze) exercises Заполнение пропусков в тексте или диалоге.
|
| 74 |
+
Matching activities Сопоставление слов с определениями, картинок с предложениями.
|
| 75 |
+
Multiple-choice questions Выбор правильного варианта из нескольких.
|
| 76 |
+
True/False (Correct/Incorrect) Оценка утверждений как верных/неверных.
|
| 77 |
+
Sentence completion Дописать конец предложения по образцу.
|
| 78 |
+
Dictation Прослушивание и письменная запись целевых фраз/предложений.
|
| 79 |
+
Sentence jumbles Распутать перемешанные слова в предложение.
|
| 80 |
+
Error correction tasks Найти и исправить ошибки в примерах.
|
| 81 |
+
Controlled dialogues Чтение/роль по готовому сценарию с жёсткими подсказками.
|
| 82 |
+
|
| 83 |
+
|
| 84 |
+
2. Полу-контролируемые упражнения (Semi-controlled Practice)
|
| 85 |
+
Введение элемента свободы, но с опорой на целевой язык.
|
| 86 |
+
|
| 87 |
+
Тип упражнения Описание Источник
|
| 88 |
+
Pair Q&A Пары задают друг другу вопросы по шаблону (info-gap).
|
| 89 |
+
Brainstorming Генерация идей/слов по теме, опора на целевой язык.
|
| 90 |
+
Fill-in-the-blank dialogues Заполнение пропусков в диалоге, затем разыгрывание его.
|
| 91 |
+
Story-telling with pictures Составление рассказа по серии картинок, с включением ЦЯ.
|
| 92 |
+
Rank & Share Ранжирование элементов по критериям, обсуждение в парах/группах.
|
| 93 |
+
Find someone who… (info-gap) Опрос одноклассников по списку вопросов, отчёт о результатах.
|
| 94 |
+
Vocab Taboo Объяснение слова, не называя его, остальные угадывают.
|
| 95 |
+
Speak-to-Draw Инструкции с предлогами: один описывает, другой рисует.
|
| 96 |
+
Interview role-play Создание вопросов-интервью и инсценировка.
|
| 97 |
+
Directed paired conversation Парная беседа по заданным вопросам без дальнейших подсказок.
|
| 98 |
+
Story completion Продолжить начало рассказа, данное учителем или в тексте.
|
| 99 |
+
Information gap maps/charts Заполнение таблиц/карт данными, обмен информацией в парах.
|
| 100 |
+
|
| 101 |
+
|
| 102 |
+
3. Переходное (linking) упражнение к Production
|
| 103 |
+
Готовит к свободному применению, смешивая контролируемые и свободные элементы.
|
| 104 |
+
|
| 105 |
+
Тип упражнения Описание Источник
|
| 106 |
+
Semi-scripted role-play Диалог с частичными подсказками, затем свободное продолжение.
|
| 107 |
+
Information-gap mini-project Сбор информации в парах/группах и представление результатов (карточки, плакаты).
|
| 108 |
+
Guided discussion Обсуждение вопросов со списком ключевых фраз, затем открытый обмен мнениями.
|
| 109 |
+
Sentence-prompt stories Закончить историю, начатую учителем, по опорным фразам.
|
| 110 |
+
|
| 111 |
+
|
| 112 |
+
3. Production (25–35% времени)
|
| 113 |
+
Цель: предоставить ученикам возможность свободно применять target language в реалистичной коммуникативной задаче
|
| 114 |
+
barefootteflteacher.com
|
| 115 |
+
.
|
| 116 |
+
|
| 117 |
+
Что включить в план
|
| 118 |
+
Задача с реальным смыслом: выберите активность, где результат важен (мини-проект, презентация, интервью)
|
| 119 |
+
TESOL Pop
|
| 120 |
+
.
|
| 121 |
+
|
| 122 |
+
Фиксация продукта: предусмотреть запись (доска, тетради, совместный файл) итоговых высказываний или артефактов
|
| 123 |
+
Go Overseas
|
| 124 |
+
.
|
| 125 |
+
|
| 126 |
+
Групповая динамика: парная или групповая работа с минимальными подсказками по форме
|
| 127 |
+
TeachingEnglish
|
| 128 |
+
.
|
| 129 |
+
|
| 130 |
+
Обратная связь: этап peer-review или teacher feedback — сначала положительное, затем 2–3 совета по улучшению
|
| 131 |
+
barefootteflteacher.com
|
| 132 |
+
.
|
| 133 |
+
|
| 134 |
+
Дифференциация: для смешанных уровней предложить базовый и продвинутый варианты задачи
|
| 135 |
+
barefootteflteacher.com
|
| 136 |
+
.
|
| 137 |
+
|
| 138 |
+
Типы Production-активностей
|
| 139 |
+
Модель может выбирать из следующих вариантов в зависимости от параметров урока:
|
| 140 |
+
|
| 141 |
+
|
| 142 |
+
Тип активности Описание
|
| 143 |
+
Ролевые игры (Role-play) Ситуации из реальной жизни (покупка, интервью)
|
| 144 |
+
Дискуссии (Discussion) Групповые дебаты или круглые столы
|
| 145 |
+
Мини-проекты (Mini-projects) Совместное создание плаката, видео или презентации
|
| 146 |
+
Интервью (Interview) Ученики берут друг у друга интервью по теме
|
| 147 |
+
Storytelling Рассказ истории на основе картинок или подсказок
|
| 148 |
+
Problem-solving tasks Решение кейсовых задач, планирование мероприятия
|
| 149 |
+
Peer teaching Ученики обучают друг друга элементам target language
|
| 150 |
+
|
| 151 |
+
|
| 152 |
+
Действуй в рамках методологии, но мысли широко и оставайся гибким, предлагай творческие варианты, соответстующие контексту занятия.
|
| 153 |
+
Действуй творчески, не фанатично: опирайся на заданные параметры (тема, уровень, возраст, инвентарь) и используй «учительское чутьё» при выборе задач, сохраняя свободу внутри методической структуры .
|
| 154 |
+
|
| 155 |
+
Пример мини-шаблона (пример few-shot):
|
| 156 |
+
— Presentation: ввести Past Continuous через картинку и вопрос “What were they doing?”
|
| 157 |
+
— Practice: 2 упражнения: gap-fills (5 предлож.), substitution drill (3 примера).
|
| 158 |
+
— Production: ролевой диалог “рассказать о выходных”; 5 мин свободной беседы.
|
| 159 |
+
— Feedback: praise + 2 рекомендац.
|
| 160 |
+
|
| 161 |
+
📝 Чек-лист перед генерацией этапов урока:
|
| 162 |
+
Кто мои ученики? (Возраст, уровень CEFR, сильные/слабые стороны)
|
| 163 |
+
Что за материал на странице? (Лексика, грамматика, темы — что важно освоить?)
|
| 164 |
+
Какая цель урока? (Что ученики должны уметь делать к концу?)
|
| 165 |
+
Какая активность наиболее естественна для этого контекста? (Диалог, игра, проект, обсуждение?)
|
| 166 |
+
Какой тип упражнений соответствует целям? (Контролируемые / полуконтролируемые / свободная практика?)
|
| 167 |
+
Нужно ли предусмотреть поддержку слабых учеников? (Подсказки, шаблоны, парная работа)
|
| 168 |
+
Как я дам обратную связь после практики? (Похвала + 1–2 рекомендации для улучшения)
|
| 169 |
+
|
| 170 |
+
|
| 171 |
+
|
| 172 |
+
Поддерживай тёплый, естественный тон плана. Если в материале заметен интересный или забавный момент, можешь кратко его отметить — но главное внимание уделяй целям урока и развитию учеников.
|
| 173 |
+
|
app/main.py
CHANGED
|
@@ -0,0 +1,486 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import os
|
| 2 |
+
import logging
|
| 3 |
+
import tempfile
|
| 4 |
+
from datetime import datetime
|
| 5 |
+
from dotenv import load_dotenv
|
| 6 |
+
from openai import OpenAI
|
| 7 |
+
import gradio as gr
|
| 8 |
+
from docx import Document
|
| 9 |
+
import requests
|
| 10 |
+
from typing import Optional
|
| 11 |
+
|
| 12 |
+
import random
|
| 13 |
+
from app.quotes import quotes
|
| 14 |
+
from app.drawings import drawings
|
| 15 |
+
from app.knowledge_base.textbooks import TEXTBOOKS
|
| 16 |
+
# --- Настройка ---
|
| 17 |
+
logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s')
|
| 18 |
+
load_dotenv()
|
| 19 |
+
api_key = os.getenv("API_KEY_openai")
|
| 20 |
+
client = OpenAI(api_key=api_key) if api_key else None
|
| 21 |
+
VS_ID = os.getenv("VECTOR_STORE_ID", "") # vector store for file_search if needed
|
| 22 |
+
|
| 23 |
+
# --- Утилиты ---
|
| 24 |
+
def upload_to_catbox(file_bytes: bytes) -> str:
|
| 25 |
+
"""Загружает файл на catbox.moe и возвращает URL"""
|
| 26 |
+
try:
|
| 27 |
+
response = requests.post(
|
| 28 |
+
"https://catbox.moe/user/api.php",
|
| 29 |
+
files={"fileToUpload": file_bytes},
|
| 30 |
+
data={"reqtype": "fileupload"},
|
| 31 |
+
timeout=10
|
| 32 |
+
)
|
| 33 |
+
response.raise_for_status()
|
| 34 |
+
return response.text.strip()
|
| 35 |
+
except Exception as e:
|
| 36 |
+
logging.error(f"Ошибка загрузки изображения: {e}")
|
| 37 |
+
raise gr.Error("Не удалось загрузить изображение")
|
| 38 |
+
|
| 39 |
+
|
| 40 |
+
def generate_docx(text: str) -> str:
|
| 41 |
+
"""Сохраняет текст в .docx и возвращает путь"""
|
| 42 |
+
doc = Document()
|
| 43 |
+
for line in text.split("\n"):
|
| 44 |
+
doc.add_paragraph(line)
|
| 45 |
+
tmp = tempfile.gettempdir()
|
| 46 |
+
path = os.path.join(tmp, f"lesson_plan_{datetime.now().strftime('%Y%m%d%H%M%S')}.docx")
|
| 47 |
+
doc.save(path)
|
| 48 |
+
return path
|
| 49 |
+
|
| 50 |
+
# названия textbooks для автозаполнения поля Учебник
|
| 51 |
+
import json
|
| 52 |
+
|
| 53 |
+
## Сохраняем отзыв через POST в google-таблицу
|
| 54 |
+
GOOGLE_SHEET_URL = os.getenv("FEEDBACK_GS_URL")
|
| 55 |
+
|
| 56 |
+
def save_feedback(comment, rate):
|
| 57 |
+
payload = {
|
| 58 |
+
"comment": comment,
|
| 59 |
+
"rate": rate
|
| 60 |
+
}
|
| 61 |
+
try:
|
| 62 |
+
requests.post(GOOGLE_SHEET_URL, json=payload, timeout=3)
|
| 63 |
+
except Exception as e:
|
| 64 |
+
print(f"Ошибка при отправке отзыва: {e}")
|
| 65 |
+
|
| 66 |
+
### ОСНОВНАЯ ФУНКЦИЯ ГЕНЕРАЦИИ
|
| 67 |
+
def generate_lesson_plan(
|
| 68 |
+
image_path: Optional[str],
|
| 69 |
+
textbook: str,
|
| 70 |
+
cefr: str,
|
| 71 |
+
topic: str,
|
| 72 |
+
goal: str,
|
| 73 |
+
format_type: str,
|
| 74 |
+
num_students: int,
|
| 75 |
+
age: str,
|
| 76 |
+
adults: bool,
|
| 77 |
+
level_match: int,
|
| 78 |
+
duration: int,
|
| 79 |
+
inventory: str,
|
| 80 |
+
extra_info: str,
|
| 81 |
+
methodology: str,
|
| 82 |
+
target_language: str,
|
| 83 |
+
hw_required: bool,
|
| 84 |
+
web_search: bool
|
| 85 |
+
# repetition: bool,
|
| 86 |
+
# application: bool,
|
| 87 |
+
# analysis: bool,
|
| 88 |
+
# creativity: bool
|
| 89 |
+
) -> str:
|
| 90 |
+
|
| 91 |
+
# Валидация API клиента
|
| 92 |
+
if not client:
|
| 93 |
+
raise gr.Error("API ключ не настроен")
|
| 94 |
+
# Проверка наличия изображения
|
| 95 |
+
if not image_path:
|
| 96 |
+
return "❗ Загрузите фото страницы учебника для генерации урока"
|
| 97 |
+
|
| 98 |
+
# Загружаем изображение и получаем URL
|
| 99 |
+
try:
|
| 100 |
+
with open(image_path, "rb") as f:
|
| 101 |
+
image_url = upload_to_catbox(f.read())
|
| 102 |
+
except Exception as e:
|
| 103 |
+
logging.error(f"Image upload error: {e}")
|
| 104 |
+
raise gr.Error("Не удалось загрузить изображение")
|
| 105 |
+
|
| 106 |
+
# Собираем текстовый prompt
|
| 107 |
+
lesson_params = {
|
| 108 |
+
'methodology': methodology,
|
| 109 |
+
'target_language': target_language, # для PPP
|
| 110 |
+
'textbook': textbook,
|
| 111 |
+
'cefr': cefr,
|
| 112 |
+
'topic': topic,
|
| 113 |
+
'goal': goal,
|
| 114 |
+
'num_students': num_students,
|
| 115 |
+
'age': 'Взрослые' if adults else age,
|
| 116 |
+
'level_match': level_match,
|
| 117 |
+
'duration': duration,
|
| 118 |
+
'inventory': inventory,
|
| 119 |
+
'hw_required': hw_required,
|
| 120 |
+
'extra_info': extra_info
|
| 121 |
+
}
|
| 122 |
+
|
| 123 |
+
# Получаем готовый промпт
|
| 124 |
+
from app.prompt_builder.prompt import build_prompt
|
| 125 |
+
full_prompt = build_prompt(lesson_params)
|
| 126 |
+
|
| 127 |
+
# Собираем входные данные согласно API
|
| 128 |
+
input_content = [
|
| 129 |
+
{
|
| 130 |
+
"type": "input_text",
|
| 131 |
+
"text": full_prompt
|
| 132 |
+
},
|
| 133 |
+
{
|
| 134 |
+
"type": "input_image",
|
| 135 |
+
"image_url": image_url,
|
| 136 |
+
"detail": "high"
|
| 137 |
+
}
|
| 138 |
+
]
|
| 139 |
+
|
| 140 |
+
# Опции инструментов
|
| 141 |
+
tools = []
|
| 142 |
+
tool_choice = None
|
| 143 |
+
if web_search:
|
| 144 |
+
tools.append({
|
| 145 |
+
"type": "web_search_preview",
|
| 146 |
+
"search_context_size": "medium",
|
| 147 |
+
"user_location": {"type": "approximate", "country": "RU"}
|
| 148 |
+
})
|
| 149 |
+
tool_choice = {"type": "web_search_preview"}
|
| 150 |
+
|
| 151 |
+
# Вызов LLM
|
| 152 |
+
try:
|
| 153 |
+
response = client.responses.create(
|
| 154 |
+
input=[{"role": "user", "content": input_content}],
|
| 155 |
+
model="o4-mini", # gpt-4o-mini gpt-4.1
|
| 156 |
+
tools=tools or None,
|
| 157 |
+
tool_choice=tool_choice,
|
| 158 |
+
max_output_tokens=8192,
|
| 159 |
+
reasoning= {"effort":"medium"},
|
| 160 |
+
stream=False
|
| 161 |
+
)
|
| 162 |
+
return response.output_text
|
| 163 |
+
|
| 164 |
+
except Exception as e:
|
| 165 |
+
logging.error(f"Generation error: {e}")
|
| 166 |
+
raise gr.Error(f"Ошибка генерации: {e}")
|
| 167 |
+
|
| 168 |
+
|
| 169 |
+
|
| 170 |
+
########## ИНТЕРФЕЙС
|
| 171 |
+
# Случайный рисунок в блокноте
|
| 172 |
+
drawing = random.choice(drawings)
|
| 173 |
+
# Текст с подсказкой и рисунком в блокноте
|
| 174 |
+
hint_text = f"""Здесь появится план занятия — заполните вводные и нажмите кнопку **Создать план**<br>
|
| 175 |
+
Создание может занять до 1 минуты
|
| 176 |
+
<pre>
|
| 177 |
+
{drawing}
|
| 178 |
+
</pre>
|
| 179 |
+
"""
|
| 180 |
+
|
| 181 |
+
#ТЕМА И СТИЛИ
|
| 182 |
+
### css привязывать именно так
|
| 183 |
+
#theme='earneleh/paris'
|
| 184 |
+
theme = gr.themes.Base(
|
| 185 |
+
secondary_hue="rose",
|
| 186 |
+
neutral_hue="stone",
|
| 187 |
+
).set(
|
| 188 |
+
body_background_fill='*primary_50',
|
| 189 |
+
body_text_color='*primary_900',
|
| 190 |
+
body_text_size='*text_lg',
|
| 191 |
+
body_text_color_subdued='*primary_700',
|
| 192 |
+
body_text_weight='600',
|
| 193 |
+
)
|
| 194 |
+
css_path = os.path.join(os.path.dirname(__file__), "styles.css")
|
| 195 |
+
|
| 196 |
+
# ИНТЕРФЕЙС
|
| 197 |
+
with gr.Blocks(theme=theme, css_paths=css_path) as app:
|
| 198 |
+
advanced_settings_visible = gr.State(value=False) # Импортируем gr.State для хранения состояния
|
| 199 |
+
feedback_visible = gr.State(False) # Хранит, открыт ли блок отзыва
|
| 200 |
+
|
| 201 |
+
gr.Markdown("# План урока английского языка", elem_classes=["main-title"])
|
| 202 |
+
quote_box = gr.Markdown(random.choice(quotes), elem_classes=["quote-block"])
|
| 203 |
+
with gr.Row():
|
| 204 |
+
with gr.Column(elem_classes=["left-col"], scale=1):
|
| 205 |
+
image = gr.Image(
|
| 206 |
+
label="Фото страницы учебника*",
|
| 207 |
+
type="filepath",
|
| 208 |
+
height=0, # Автоматическая высота
|
| 209 |
+
container=False # Не растягивать контейнер
|
| 210 |
+
)
|
| 211 |
+
|
| 212 |
+
# Блок 1: Учебник
|
| 213 |
+
with gr.Column(variant="panel"):
|
| 214 |
+
gr.Markdown("### 📚 Учебник", elem_classes=["block-title"])
|
| 215 |
+
textbook = gr.Textbox(label="Название учебника", placeholder="напр. English File Beginner", elem_id="textbook_input")
|
| 216 |
+
|
| 217 |
+
cefr = gr.Dropdown(label="Уровень", choices=["", "A1", "A2", "B1", "B2", "C1", "C2"],
|
| 218 |
+
value="", info="Выберите уровень")
|
| 219 |
+
# Блок 2: Класс
|
| 220 |
+
with gr.Column(variant="panel"):
|
| 221 |
+
gr.Markdown("### 👥 Класс", elem_classes=["block-title"])
|
| 222 |
+
format_type = gr.Radio(label="Формат занятия", choices=["Индивидуальное", "Групповое"],
|
| 223 |
+
value="Групповое")
|
| 224 |
+
|
| 225 |
+
with gr.Group(visible=True) as group_settings:
|
| 226 |
+
num_students = gr.Slider(label="Количество учеников", minimum=1, maximum=40,
|
| 227 |
+
value=10, step=1, info="Для групповых занятий")
|
| 228 |
+
|
| 229 |
+
with gr.Group() as age_group:
|
| 230 |
+
age = gr.Textbox(label="Возраст", placeholder="напр. 10–11", interactive=True)
|
| 231 |
+
adults = gr.Checkbox(label="Взрослые")
|
| 232 |
+
|
| 233 |
+
level_match = gr.Dropdown(label = "Уровень учеников относительно учебника",
|
| 234 |
+
choices = ["ниже", "на уровне", "выше", "mixed"], value = "на уровне")
|
| 235 |
+
|
| 236 |
+
# Блок 3: Занятие
|
| 237 |
+
with gr.Column(variant="panel"):
|
| 238 |
+
gr.Markdown("### 📄 Занятие", elem_classes=["block-title"])
|
| 239 |
+
topic = gr.Textbox(label="Тема", placeholder="напр. Daily routines")
|
| 240 |
+
goal = gr.Textbox(label="Цель", placeholder="К концу урока ученики смогут...")
|
| 241 |
+
duration = gr.Slider(label="Длительность (мин)", minimum=30, maximum=180, value=60, step=5)
|
| 242 |
+
inventory = gr.Textbox(label="Инвентарь", placeholder="по умолчанию - доска и проектор")
|
| 243 |
+
extra_info = gr.Textbox(label="Допонительная информация", placeholder="Класс весёлый и взвинченный после физкультуры")
|
| 244 |
+
|
| 245 |
+
# Блок 4: Методика
|
| 246 |
+
with gr.Column(variant="panel"):
|
| 247 |
+
gr.Markdown("### 🎓 Методика", elem_classes=["block-title"])
|
| 248 |
+
methodology = gr.Dropdown(label="Методика преподавания",
|
| 249 |
+
choices=["PPP (Presentation-Practice-Production)",
|
| 250 |
+
"TTT (Test-Teach-Test)"],
|
| 251 |
+
value="PPP (Presentation-Practice-Production)")
|
| 252 |
+
target_language = gr.Textbox(
|
| 253 |
+
label="Target language",
|
| 254 |
+
placeholder="Например: 'I have been to...' 'How long have you...?' (Present Perfect experience)",
|
| 255 |
+
visible=True # По умолчанию видно, так как PPP выбран
|
| 256 |
+
)
|
| 257 |
+
|
| 258 |
+
# advanced_btn = gr.Button(value="➕ Продвинутые настройки (в разработке", size="sm")
|
| 259 |
+
#
|
| 260 |
+
# # Блок продвинутых настроек, изначально скрыт
|
| 261 |
+
# with gr.Column(visible=False) as advanced_block:
|
| 262 |
+
# gr.Markdown("**💡 Уровни задач (таксономия):**")
|
| 263 |
+
# repetition = gr.Checkbox(label="Повторение")
|
| 264 |
+
# application = gr.Checkbox(label="Применение")
|
| 265 |
+
# analysis = gr.Checkbox(label="Анализ")
|
| 266 |
+
# creativity = gr.Checkbox(label="Творчество")
|
| 267 |
+
|
| 268 |
+
hw_required = gr.Checkbox(label="Домашнее задание")
|
| 269 |
+
web_search = gr.Checkbox(label="Доп. материалы из интернета")
|
| 270 |
+
|
| 271 |
+
btn = gr.Button("Создать план", variant="primary", size="lg")
|
| 272 |
+
|
| 273 |
+
# Правая колонка — результат (output)
|
| 274 |
+
with gr.Column(elem_classes=["right-col"], scale=2):
|
| 275 |
+
# Общий блок-панель для правой колонки
|
| 276 |
+
with gr.Column(variant="panel"): # <<< Главная панель
|
| 277 |
+
gr.Markdown("### План урока", elem_classes=["block-title"]) # Заголовок ВНУТРИ панели
|
| 278 |
+
# Блок с выводом плана
|
| 279 |
+
output = gr.Markdown(
|
| 280 |
+
hint_text,
|
| 281 |
+
elem_id="plan-output"
|
| 282 |
+
)
|
| 283 |
+
# Кнопка скачивания (оставляем внутри панели)
|
| 284 |
+
download_btn = gr.DownloadButton(
|
| 285 |
+
label="⬇️ Скачать .docx",
|
| 286 |
+
visible=False
|
| 287 |
+
)
|
| 288 |
+
# Кнопка "Помогите нам стать лучше"
|
| 289 |
+
feedback_btn = gr.Button("💬 Помогите нам стать лучше", elem_classes=["feedback-button"])
|
| 290 |
+
|
| 291 |
+
# Скрытый блок с обратной связью
|
| 292 |
+
with gr.Column(visible=False) as feedback_block:
|
| 293 |
+
gr.Markdown("_Спасибо, что попробовали! Как вам?_\n_Ваши наблюдения и замечания помогают нам расти._")
|
| 294 |
+
|
| 295 |
+
|
| 296 |
+
def toggle_feedback_block(current_visible):
|
| 297 |
+
return (
|
| 298 |
+
gr.update(visible=not current_visible), # показать/скрыть блок
|
| 299 |
+
not current_visible, # обновить состояние
|
| 300 |
+
gr.update(visible=False) # скрыть благодарность при открытии/закрытии
|
| 301 |
+
)
|
| 302 |
+
feedback_text = gr.Textbox(
|
| 303 |
+
label="Ваше наблюдение или комментарий",
|
| 304 |
+
placeholder="Например: 'Для 3 лет лексика подбирается неправильно — какая там 'машина', максимум - 'би-би'",
|
| 305 |
+
lines=4
|
| 306 |
+
)
|
| 307 |
+
|
| 308 |
+
rating = gr.Radio(
|
| 309 |
+
choices=["1", "2", "3", "4", "5"],
|
| 310 |
+
label="Оценка"
|
| 311 |
+
)
|
| 312 |
+
|
| 313 |
+
send_feedback = gr.Button("📩 Отправить отзыв")
|
| 314 |
+
|
| 315 |
+
feedback_confirmation = gr.Markdown(
|
| 316 |
+
visible=False,
|
| 317 |
+
elem_classes=["feedback-confirmation"]
|
| 318 |
+
)
|
| 319 |
+
|
| 320 |
+
# <-- Блок благодарности — ВНЕ feedback_block, но СРАЗУ ПОСЛЕ
|
| 321 |
+
with gr.Column(visible=False) as feedback_confirmation:
|
| 322 |
+
gr.Markdown("✅ Спасибо! Ваш комментарий передан и, возможно, уже сегодня ассистент станет полезнее :)")
|
| 323 |
+
|
| 324 |
+
# Остальное
|
| 325 |
+
gr.Markdown(
|
| 326 |
+
"""
|
| 327 |
+
🙌 Если вас заинтересовал проект, мы приглашаем
|
| 328 |
+
👉 [присоединиться к Telegram-группе](https://t.me/+yN9BSJ1DJxxjZmJi)
|
| 329 |
+
"""
|
| 330 |
+
)
|
| 331 |
+
|
| 332 |
+
### --- Логика интерфейса ---
|
| 333 |
+
## Доп. настройки
|
| 334 |
+
# def toggle_advanced_settings(visible):
|
| 335 |
+
# return gr.update(visible=not visible), not visible
|
| 336 |
+
|
| 337 |
+
# advanced_btn.click(
|
| 338 |
+
# fn=toggle_advanced_settings,
|
| 339 |
+
# inputs=[advanced_settings_visible],
|
| 340 |
+
# outputs=[advanced_block, advanced_settings_visible]
|
| 341 |
+
# )
|
| 342 |
+
|
| 343 |
+
# Формат занятия - видимость поля если выбрано групповое
|
| 344 |
+
def toggle_format(selected_format):
|
| 345 |
+
return gr.update(visible=selected_format == "Групповое")
|
| 346 |
+
format_type.change(fn=toggle_format, inputs=format_type, outputs=group_settings)
|
| 347 |
+
|
| 348 |
+
# Возраст - деактивация поля если нажато "Взрослые"
|
| 349 |
+
def toggle_age(adult_checked):
|
| 350 |
+
return gr.update(interactive=not adult_checked)
|
| 351 |
+
adults.change(fn=toggle_age, inputs=adults, outputs=age)
|
| 352 |
+
|
| 353 |
+
# Функция для переключения видимости Target language
|
| 354 |
+
def toggle_target_language(methodology_value):
|
| 355 |
+
return gr.update(visible=methodology_value == "PPP (Presentation-Practice-Production)")
|
| 356 |
+
methodology.change(fn=toggle_target_language, inputs=methodology, outputs=target_language)
|
| 357 |
+
|
| 358 |
+
# JS для автодополнения
|
| 359 |
+
app.load(
|
| 360 |
+
None,
|
| 361 |
+
None,
|
| 362 |
+
js=f"""
|
| 363 |
+
const textbooks = {TEXTBOOKS};
|
| 364 |
+
|
| 365 |
+
function setupAutocomplete() {{
|
| 366 |
+
const input = document.getElementById('textbook_input');
|
| 367 |
+
if (!input) return;
|
| 368 |
+
|
| 369 |
+
const datalist = document.createElement('datalist');
|
| 370 |
+
datalist.id = 'textbook_suggestions';
|
| 371 |
+
|
| 372 |
+
textbooks.forEach(book => {{
|
| 373 |
+
const option = document.createElement('option');
|
| 374 |
+
option.value = book;
|
| 375 |
+
datalist.appendChild(option);
|
| 376 |
+
}});
|
| 377 |
+
|
| 378 |
+
input.setAttribute('list', datalist.id);
|
| 379 |
+
document.body.appendChild(datalist);
|
| 380 |
+
}}
|
| 381 |
+
|
| 382 |
+
// Запускаем после загрузки
|
| 383 |
+
if (document.readyState === 'complete') {{
|
| 384 |
+
setupAutocomplete();
|
| 385 |
+
}} else {{
|
| 386 |
+
document.addEventListener('DOMContentLoaded', setupAutocomplete);
|
| 387 |
+
}}
|
| 388 |
+
"""
|
| 389 |
+
)
|
| 390 |
+
### СПИСОК ВСЕХ ПАРАМЕТРОВ ИНТЕРФЕЙСА
|
| 391 |
+
all_inputs = [
|
| 392 |
+
image, # Gradio компонент, соответствует image_path в функциях
|
| 393 |
+
textbook,
|
| 394 |
+
cefr,
|
| 395 |
+
topic,
|
| 396 |
+
goal,
|
| 397 |
+
format_type,
|
| 398 |
+
num_students,
|
| 399 |
+
age,
|
| 400 |
+
adults,
|
| 401 |
+
level_match,
|
| 402 |
+
duration,
|
| 403 |
+
inventory,
|
| 404 |
+
extra_info,
|
| 405 |
+
methodology,
|
| 406 |
+
target_language,
|
| 407 |
+
hw_required,
|
| 408 |
+
web_search
|
| 409 |
+
# repetition,
|
| 410 |
+
# application,
|
| 411 |
+
# analysis,
|
| 412 |
+
# creativity
|
| 413 |
+
]
|
| 414 |
+
|
| 415 |
+
# Коллбек генерации
|
| 416 |
+
def on_generate(
|
| 417 |
+
image_path: Optional[str], # Переименовано из image
|
| 418 |
+
textbook: str,
|
| 419 |
+
cefr: str,
|
| 420 |
+
topic: str,
|
| 421 |
+
goal: str,
|
| 422 |
+
format_type: str,
|
| 423 |
+
num_students: int,
|
| 424 |
+
age: str,
|
| 425 |
+
adults: bool,
|
| 426 |
+
level_match: int,
|
| 427 |
+
duration: int,
|
| 428 |
+
inventory: str,
|
| 429 |
+
extra_info: str,
|
| 430 |
+
methodology: str,
|
| 431 |
+
target_language: str,
|
| 432 |
+
hw_required: bool,
|
| 433 |
+
web_search: bool
|
| 434 |
+
# repetition: bool,
|
| 435 |
+
# application: bool,
|
| 436 |
+
# analysis: bool,
|
| 437 |
+
# creativity: bool
|
| 438 |
+
):
|
| 439 |
+
# Проверка обязательных полей
|
| 440 |
+
if not image_path or (not adults and not age):
|
| 441 |
+
return gr.update(value="❗ Заполните обязательные поля (отмечены *)"), gr.update(visible=False)
|
| 442 |
+
|
| 443 |
+
# Собираем все аргументы в словарь
|
| 444 |
+
kwargs = locals()
|
| 445 |
+
|
| 446 |
+
# Генерация плана
|
| 447 |
+
text = generate_lesson_plan(**kwargs)
|
| 448 |
+
|
| 449 |
+
# Создание DOCX
|
| 450 |
+
docx_path = generate_docx(text) if not text.startswith("❗") else None
|
| 451 |
+
return gr.update(value=text), gr.update(visible=bool(docx_path), value=docx_path)
|
| 452 |
+
|
| 453 |
+
btn.click(
|
| 454 |
+
fn=on_generate,
|
| 455 |
+
inputs=all_inputs,
|
| 456 |
+
outputs=[output, download_btn]
|
| 457 |
+
)
|
| 458 |
+
|
| 459 |
+
# Логика: показать форму по нажатию на кнопку
|
| 460 |
+
feedback_btn.click(
|
| 461 |
+
fn=toggle_feedback_block,
|
| 462 |
+
inputs=[feedback_visible],
|
| 463 |
+
outputs=[feedback_block, feedback_visible, feedback_confirmation]
|
| 464 |
+
)
|
| 465 |
+
|
| 466 |
+
# Логика отправки обратной связи
|
| 467 |
+
def send_feedback_fn(comment, rate):
|
| 468 |
+
save_feedback(comment, rate) # Сохраняем отзыв
|
| 469 |
+
return (
|
| 470 |
+
gr.update(visible=False), # свернуть форму
|
| 471 |
+
False, # сбросить состояние
|
| 472 |
+
gr.update(
|
| 473 |
+
value="✅ Спасибо! Ваш комментарий передан, и, возможно, уже сегодня ассистент станет полезнее :)",
|
| 474 |
+
visible=True
|
| 475 |
+
)
|
| 476 |
+
)
|
| 477 |
+
|
| 478 |
+
send_feedback.click(
|
| 479 |
+
fn=send_feedback_fn,
|
| 480 |
+
inputs=[feedback_text, rating],
|
| 481 |
+
outputs=[feedback_block, feedback_visible, feedback_confirmation]
|
| 482 |
+
)
|
| 483 |
+
|
| 484 |
+
|
| 485 |
+
if __name__ == "__main__":
|
| 486 |
+
app.launch()
|
app/prompt_builder/__init__.py
ADDED
|
File without changes
|
app/prompt_builder/methodology.py
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
METHODOLOGY_DATA = {
|
| 2 |
+
"PPP": {
|
| 3 |
+
"structure": "3 этапа: Presentation → Practice → Production",
|
| 4 |
+
"key_points": [
|
| 5 |
+
"Четкое разделение этапов",
|
| 6 |
+
"Контролируемая практика перед свободным использованием",
|
| 7 |
+
"Пример: Демонстрация диалога → Упражнения на подстановку → Ролевая игра"
|
| 8 |
+
]
|
| 9 |
+
},
|
| 10 |
+
"TTT": {
|
| 11 |
+
"structure": "Test → Teach → Test",
|
| 12 |
+
"key_points": [
|
| 13 |
+
"Диагностика текущего уровня перед обучением",
|
| 14 |
+
"Фокус на пробелах в знаниях",
|
| 15 |
+
"Пример: Предварительный квиз → Объяснение проблемных мест → Финальное задание"
|
| 16 |
+
]
|
| 17 |
+
}
|
| 18 |
+
}
|
app/prompt_builder/prompt.py
ADDED
|
@@ -0,0 +1,257 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
def build_prompt(params):
|
| 2 |
+
# с обработкой пустых значений
|
| 3 |
+
def clean_value(value, default):
|
| 4 |
+
if value is None:
|
| 5 |
+
return default
|
| 6 |
+
if isinstance(value, str) and value.strip() == '':
|
| 7 |
+
return default
|
| 8 |
+
return value
|
| 9 |
+
|
| 10 |
+
# Создаем базовый промпт как список строк
|
| 11 |
+
prompt_base = [
|
| 12 |
+
f"""
|
| 13 |
+
Ты — опытный ESL-методист. Ты помогаешь учителям составлять грамотные и интересные планы занятий.
|
| 14 |
+
Разработай план урока на материале загруженной страницы учебника. Максимально опирайся на этот материал.
|
| 15 |
+
Перед тем как генерировать план, обдумай этапы урока по методологии {params['methodology']} с учетом всех вводных параметров занятия.
|
| 16 |
+
Будь гибким: адаптируй идеи под реальный контекст занятия, проявляй педагогическое чутьё, не копируй механически структуру. Главная цель — сделать урок живым и полезным!
|
| 17 |
+
На всех этапах урока используй материал страницы как основной источник. Указывай номера упражнений в плане.
|
| 18 |
+
Используй в плане условные визуальные схемы при необходимости - например, если нужно что-то нарисовать на доске или какую-то таблицу вынести в тетрадь - приведи общий (для понимания сути) набросок в плане.
|
| 19 |
+
|
| 20 |
+
Параметры занятия:
|
| 21 |
+
- УМК: {clean_value(params.get('textbook'), "попробуй определи визуально через логотипы, заголовки, структуру")}
|
| 22 |
+
- Уровень УМК по CEFR: {clean_value(params.get('cefr'), "определи по сложности текста/упражнений или по названию учебника")}
|
| 23 |
+
- Тема: {clean_value(params.get('topic'), "выяви через ключевые слова/изображения на странице")}
|
| 24 |
+
- Цель: {clean_value(params.get('goal'), "сформулируй сам 'К концу урока ученики смогут...'")}
|
| 25 |
+
- Возраст: {params['age']} лет (учти: {_get_age_group_comment(params['age'])})
|
| 26 |
+
- Продолжительность: {params['duration']} мин
|
| 27 |
+
- Количество учеников: {params['num_students']} чел
|
| 28 |
+
- Методология занятия: {params['methodology']}
|
| 29 |
+
- Соответствие класса (ученика) уровню учебника: {params['level_match']} ({_get_level_match_comment(params['level_match'])})
|
| 30 |
+
- Target language: {params.get('target_language') or 'определи самостоятельно по загруженной странице'}
|
| 31 |
+
- Оборудование/инвентарь: {params.get('inventory') or "стандартный класс + проектор"}
|
| 32 |
+
|
| 33 |
+
"""
|
| 34 |
+
]
|
| 35 |
+
|
| 36 |
+
# Добавляем дополнительную информацию ТОЛЬКО если она есть
|
| 37 |
+
if params.get('extra_info'):
|
| 38 |
+
prompt_base.append(f"- Дополнительная информация от учителя: {params['extra_info']}\n")
|
| 39 |
+
if params.get('hw_required'):
|
| 40 |
+
prompt_base.append("- Разработай домашнее задание, логично вытекающее из урока\n")
|
| 41 |
+
|
| 42 |
+
# Объединяем все части в одну строку
|
| 43 |
+
base_prompt = "".join(prompt_base)
|
| 44 |
+
|
| 45 |
+
# Добавляем советы по методике
|
| 46 |
+
methodology_advice = METHODOLOGY_TIPS.get(params['methodology'], "")
|
| 47 |
+
|
| 48 |
+
return base_prompt + methodology_advice
|
| 49 |
+
|
| 50 |
+
|
| 51 |
+
def is_empty_or_whitespace(text):
|
| 52 |
+
"""Проверяет, является ли текст пустым или содержит только пробельные символы"""
|
| 53 |
+
return text is None or (isinstance(text, str) and text.strip() == '')
|
| 54 |
+
|
| 55 |
+
def _get_level_match_comment(level):
|
| 56 |
+
comments = {
|
| 57 |
+
'ниже': "материал проще уровня учеников - добавь усложнённые элементы",
|
| 58 |
+
'на уровне': "материал соответствует уровню учеников",
|
| 59 |
+
'выше': "материал сложнее уровня учеников - предусмотри дополнительные объяснения",
|
| 60 |
+
'mixed': "в группе разные уровни - подготовь дифференцированные задания"
|
| 61 |
+
}
|
| 62 |
+
return comments.get(level, "учти соответствие уровня материала и учеников")
|
| 63 |
+
|
| 64 |
+
def _get_age_group_comment(age):
|
| 65 |
+
try:
|
| 66 |
+
# Преобразуем в строку на случай, если возраст пришёл как число
|
| 67 |
+
age_str = str(age).strip()
|
| 68 |
+
|
| 69 |
+
# Удаляем все нецифровые символы, кроме разделителей (пробел, дефис, запятая)
|
| 70 |
+
cleaned = ''.join(c if c.isdigit() or c in ' -,' else ' ' for c in age_str)
|
| 71 |
+
|
| 72 |
+
# Разбиваем по возможным разделителям
|
| 73 |
+
for separator in ['-', ' ', ',']:
|
| 74 |
+
if separator in cleaned:
|
| 75 |
+
age_parts = cleaned.split(separator)
|
| 76 |
+
# Берём первый попавшийся числовой элемент
|
| 77 |
+
for part in age_parts:
|
| 78 |
+
if part.strip().isdigit():
|
| 79 |
+
age_int = int(part.strip())
|
| 80 |
+
break
|
| 81 |
+
break
|
| 82 |
+
else:
|
| 83 |
+
# Если не нашли разделителей - пробуем преобразовать целиком
|
| 84 |
+
age_int = int(cleaned) if cleaned.isdigit() else 0
|
| 85 |
+
|
| 86 |
+
# Определяем возрастную группу
|
| 87 |
+
if 6 <= age_int <= 12:
|
| 88 |
+
return "дети: фокус на играх, движении, визуалах, коротких активностях"
|
| 89 |
+
elif 13 <= age_int <= 17:
|
| 90 |
+
return "подростки: актуальные темы (напр. соцсети, игры), групповые проекты, элемент соревнования"
|
| 91 |
+
elif age_int > 17:
|
| 92 |
+
return "взрослые: кейсы из реальной жизни, профессиональные контексты, дискуссии"
|
| 93 |
+
else:
|
| 94 |
+
return "дошкольники: игровое обучение, максимальная наглядность, частая смена деятельности"
|
| 95 |
+
|
| 96 |
+
except (ValueError, AttributeError, TypeError):
|
| 97 |
+
return "учти возрастные особенности группы"
|
| 98 |
+
|
| 99 |
+
|
| 100 |
+
|
| 101 |
+
METHODOLOGY_TIPS = {
|
| 102 |
+
"PPP (Presentation-Practice-Production)": """
|
| 103 |
+
[МЕТОДИКА PPP]
|
| 104 |
+
|
| 105 |
+
Быстрый чек‑лист перед каждым этапом:
|
| 106 |
+
|
| 107 |
+
Кто мои ученики? (возраст, уровень CEFR)
|
| 108 |
+
Какие части страницы взять за основу урока? (тексты, задания, изображения)
|
| 109 |
+
Какая цель урока? (что ученики должны уметь к концу)
|
| 110 |
+
Какие упражнения подойдут? (контролируемые/полуконтролируемые/свободные)
|
| 111 |
+
Как поддержать слабых учеников? (подсказки, шаблоны, парная работа)
|
| 112 |
+
|
| 113 |
+
Перед каждым этапом прогоняй чек‑лист, ориентируйся на страницу, параметры урока и свое учительское чутье.
|
| 114 |
+
|
| 115 |
+
Этап 1: Presentation (20–25% времени)
|
| 116 |
+
|
| 117 |
+
1) Contextualisation (5–7 мин)
|
| 118 |
+
— Придумай живую ситуацию (вопрос, загадку, картинку, мини-историю), связанную с темой страницы.
|
| 119 |
+
— Ситуация должна логично вести к нужным языковым элементам.
|
| 120 |
+
— Через эту ситуацию естественно выведи target language (лексика, грамматика, выражения).
|
| 121 |
+
|
| 122 |
+
Контекст не должен быть искусственным: старайся строить ситуацию так, чтобы все target language звучали там естественно и логично.
|
| 123 |
+
Если надо, немного адаптируй формулировки LT для лучшего встраивания.
|
| 124 |
+
|
| 125 |
+
2) Target Language Discovery
|
| 126 |
+
— Помоги ученикам самим «заметить» и «вывести» target language через вопросы (eliciting).
|
| 127 |
+
— Затем закрепи его по методу COW:
|
| 128 |
+
• Concept: объяснение смысла через примеры и вопросы.
|
| 129 |
+
• Oral: устная практика (с акцентом на важные для произношения моменты).
|
| 130 |
+
• Written: письменная фиксация (укажи, где будет письменная фиксация - доска/слайды/раздатки etc).
|
| 131 |
+
|
| 132 |
+
Параметры объема TL:
|
| 133 |
+
• A1–A2 (6–12 лет): 3–5 единиц
|
| 134 |
+
• A2–B1 (13–17 лет): 5–7 единиц
|
| 135 |
+
• B2+: 7–10 единиц
|
| 136 |
+
|
| 137 |
+
|
| 138 |
+
Справка:
|
| 139 |
+
Виды target language:
|
| 140 |
+
Лексика (vocabulary) Тематические слова и выражения: еда, путешествия, эмоции etc.
|
| 141 |
+
Грамматика (grammar) Времена, модальные глаголы, условные предложения, артикли etc.
|
| 142 |
+
Функциональный язык (functional language) Фразы для общения: просьбы, советы, приглашения, извинения etc.
|
| 143 |
+
Фразовые глаголы (phrasal verbs) Turn up, break down, look after etc.
|
| 144 |
+
Идиомы (idioms) "Break the ice", "Hit the books" etc.
|
| 145 |
+
Произношение (pronunciation features) Интонация вопросов, соединение слов (linking sounds), ударение etc.
|
| 146 |
+
Орфография (spelling patterns) Правила написания: окончания -ing, суффиксы и префиксы etc.
|
| 147 |
+
Синтаксис (syntax) Порядок слов в вопросах, порядок прилагательных etc.
|
| 148 |
+
Функции дискурса (discourse markers) Well, actually, you know, I mean... etc.
|
| 149 |
+
Социальные формы речи (register) Формальный/неформальный стиль общения etc.
|
| 150 |
+
|
| 151 |
+
|
| 152 |
+
Этап 2: Practice (30–40% времени занятия)
|
| 153 |
+
Цель этапа: помочь ученикам отработать target language под контролем учителя, чтобы укрепить понимание формы и значения.
|
| 154 |
+
Построй этап на базе target language, выбранного на предыдущей фазе.
|
| 155 |
+
Используй материал страницы учебника как основу для упражнений (переформатируй задания при необходимости, но сохраняй их смысл и структуру).
|
| 156 |
+
|
| 157 |
+
Организуй 2–3 контролируемых или полуконтролируемых упражнения.
|
| 158 |
+
|
| 159 |
+
Если у тебя есть пространство для маневра, начни с упражнений с высокой степенью контроля (чтобы ученики не допускали ошибок).
|
| 160 |
+
Постепенно ослабляй контроль, подводя к этапу Production.
|
| 161 |
+
|
| 162 |
+
Подбирая тип упражнений, учитывая возраст, уровень CEFR, продолжительность урока и количество учеников (пары, мини-группы и т.д.).
|
| 163 |
+
Продумай, как предоставить минимальный фидбэк (например, общее исправление ошибок после каждого упражнения).
|
| 164 |
+
|
| 165 |
+
Справка:
|
| 166 |
+
Неполный список возможных типов упражнений для этапа Practice:
|
| 167 |
+
Controlled drills - Substitution, transformation, repetition drills.
|
| 168 |
+
Gap-fills - Вставка пропущенных слов, структур или фраз.
|
| 169 |
+
Matching - Соотнесение вопросов и ответов, слов и определений.
|
| 170 |
+
Sentence completion - Завершение предложений целевыми структурами.
|
| 171 |
+
Reordering Перестановка - элементов для создания правильных предложений.
|
| 172 |
+
Controlled dialogues - Диалоги с частично заданной структурой.
|
| 173 |
+
Information gap activities - (контролируемые) Обмен недостающей информацией по чётким правилам.
|
| 174 |
+
|
| 175 |
+
|
| 176 |
+
Этап 3: Production (25–35% времени занятия)
|
| 177 |
+
Цель этапа: Дать ученикам возможность свободно и творчески использовать target language в реальной коммуникации.
|
| 178 |
+
Построй задание на свободное использование target language.
|
| 179 |
+
Используй материал страницы как отправную точку для ситуации, но адаптируй или дополни её, чтобы задание требовало активного создания речи учениками.
|
| 180 |
+
|
| 181 |
+
Справка:
|
| 182 |
+
Возможные типы заданий (можешь использовать и другие варианты по своему усмотрению):
|
| 183 |
+
|
| 184 |
+
Role-play | Разыгрывание реальных ситуаций.
|
| 185 |
+
Discussion / Debate | Обсуждение темы урока.
|
| 186 |
+
Mini-project | Создание плаката, презентации, мини-видео.
|
| 187 |
+
Interview | Ученики задают друг другу вопросы.
|
| 188 |
+
Storytelling | Придумывание и рассказывание историй.
|
| 189 |
+
Problem-solving task | Решение задач и кейсов.
|
| 190 |
+
Peer teaching | Объяснение новой лексики друг другу.
|
| 191 |
+
Игры на использование языка | "Find someone who...", викторины и т.д.
|
| 192 |
+
|
| 193 |
+
Подбирай активность с учётом возраста, уровня и характера группы (например, подростки предпочитают соревновательные задания, взрослые — практические кейсы).
|
| 194 |
+
|
| 195 |
+
** Корректировки длительности этапов для разных уровней**:
|
| 196 |
+
Начинающие (A1-A2):
|
| 197 |
+
• Увеличить Practice до 45-50% (больше повторений и структурированных упражнений).
|
| 198 |
+
• Сократить Production до 20% (менее сложные задания).
|
| 199 |
+
|
| 200 |
+
Продвинутые (B2-C1):
|
| 201 |
+
• Сократить Presentation до 15% (быстрый ввод материала).
|
| 202 |
+
• Увеличить Production до 35-40% (больше дискуссий/кейсов).
|
| 203 |
+
|
| 204 |
+
""",
|
| 205 |
+
|
| 206 |
+
"TTT (Test-Teach-Test)": """
|
| 207 |
+
[МЕТОДИКА TTT]
|
| 208 |
+
Обязательные этапы:
|
| 209 |
+
1. Test (10 мин): Диагностический тест
|
| 210 |
+
2. Teach (15 мин): Объяснение проблемных мест
|
| 211 |
+
3. Test (20 мин): Применение в новой ситуации
|
| 212 |
+
Пример: предтест на времена → объяснение Past Perfect → кейсы
|
| 213 |
+
"""
|
| 214 |
+
}
|
| 215 |
+
|
| 216 |
+
|
| 217 |
+
|
| 218 |
+
|
| 219 |
+
# Этап 1 :Presentation (20–25% времени)
|
| 220 |
+
# — Выбери главный target language (лексика или структура) по материалу страницы.
|
| 221 |
+
# - Придумай общий контекст для всех target language (д
|
| 222 |
+
# Начни урок с некоего интересного объекта, вопроса, иллюстрации, короткого видео, загадки или чего угодно еще, чтобы заинтриговать учеников и задать контекст.
|
| 223 |
+
# — Введи target language по методике: понимание (concept), звуковая форма (oral), письменная форма (written).
|
| 224 |
+
# — Определите количество новых языковых единиц в зависимости от уровня CEFR и возраста учащихся, чтобы обеспечить оптимальное усвоение материала.
|
| 225 |
+
# — Предусмотри, где эти единицы будут представлены письменно (доска, раздатки, заметки).
|
| 226 |
+
# — Дополни план идеями для активации внимания: короткий диалог, обсуждение картинки, мини-видео.
|
| 227 |
+
|
| 228 |
+
|
| 229 |
+
EXTRA_CASES = f"""
|
| 230 |
+
Особые указания:
|
| 231 |
+
Если учебник и возраст явно конфликтуют (напр., медицинский английский для детей 6 лет):
|
| 232 |
+
- Предупреди: "Материал требует адаптации. Предлагаю упрощённый вариант: [идея]"
|
| 233 |
+
- Сохрани 2-3 ключевых элемента страницы, но измени контекст
|
| 234 |
+
Пример:
|
| 235 |
+
Текст про хирургию → "Лечим плюшевых зверей: bandage, medicine, hurt"
|
| 236 |
+
|
| 237 |
+
1. Всегда сохраняй структуру выбранной методики, но меняй:
|
| 238 |
+
- Тип активностей (игры ↔ кейсы)
|
| 239 |
+
- Длительность этапов (дети: чаще сменяй задания)
|
| 240 |
+
- Степень автономии (подростки: больше групповой работы)
|
| 241 |
+
|
| 242 |
+
2. Если учебник явно не подходит по возрасту:
|
| 243 |
+
- Шаг 1: Выдели ключевые элементы страницы (текст/упражнения/картинки)
|
| 244 |
+
- Шаг 2: Переупакуй их в подходящий формат:
|
| 245 |
+
Пример:
|
| 246 |
+
Учебник для взрослых → урок для детей 10 лет:
|
| 247 |
+
• Текст о бизнесе → "Создай магазин мечты"
|
| 248 |
+
• Сложные термины → "Придумай смешные названия для товаров"
|
| 249 |
+
• Графики → "Нарисуй идеальный график каникул"
|
| 250 |
+
|
| 251 |
+
3. Дифференциация внутри группы:
|
| 252 |
+
- Для mixed ages: предложи 2 варианта одного задания
|
| 253 |
+
Пример:
|
| 254 |
+
"Basic: Используй слова из рамки. Advanced: Добавь 3 прилагательных"
|
| 255 |
+
"""
|
| 256 |
+
|
| 257 |
+
|
app/prompt_builder/prompt_sketches.md
ADDED
|
@@ -0,0 +1,284 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
def build_prompt(params):
|
| 2 |
+
base_prompt = f"""
|
| 3 |
+
Ты — опытный ESL-методист. Помоги учителю создать структурированный и увлекательный план урока,
|
| 4 |
+
максимально используя материалы загруженной страницы учебника. Действуй строго в рамках методологии {params['methodology']},
|
| 5 |
+
но предлагай неочевидные идеи там, где это уместно.
|
| 6 |
+
|
| 7 |
+
Параметры занятия:
|
| 8 |
+
- УМК: {params.get('textbook') or "анализируй визуально: логотипы, заголовки, структуру"}
|
| 9 |
+
- Уровень CEFR: {params.get('cefr') or "определи по: длине предложений, сложности лексики, грамматическим структурам"}
|
| 10 |
+
- Тема: {params.get('topic') or "выяви через ключевые слова/изображения на странице"}
|
| 11 |
+
- Цель: {params.get('goal') or "сформулируй как 'К концу урока ученики смогут...' + действие с целевым языком"}
|
| 12 |
+
- Длительность: {params['duration']} мин
|
| 13 |
+
- Возраст: {params['age']}
|
| 14 |
+
- Инвентарь: {params.get('inventory') or "стандартный класс + проектор"}
|
| 15 |
+
- ДЗ: {'Обязательно' if params['hw_required'] else 'Не требуется'}
|
| 16 |
+
|
| 17 |
+
Особые требования:
|
| 18 |
+
"""
|
| 19 |
+
|
| 20 |
+
methodology_advice = METHODOLOGY_TIPS.get(params['methodology'], "")
|
| 21 |
+
return base_prompt + methodology_advice
|
| 22 |
+
|
| 23 |
+
METHODOLOGY_TIPS = {
|
| 24 |
+
"PPP (Presentation-Practice-Production)": """
|
| 25 |
+
[ДЕТАЛЬНАЯ ИНСТРУКЦИЯ ДЛЯ PPP]
|
| 26 |
+
|
| 27 |
+
1. PRESENTATION (20-25% времени)
|
| 28 |
+
✔ Обязательно:
|
| 29 |
+
- Используй 1-2 элемента со страницы как контекст (диалог/текст/картинки)
|
| 30 |
+
- Выдели 5-7 языковых единиц (подсвети рамкой/цветом на странице)
|
| 31 |
+
- Включи работу с формой: таблица на доске с примерами из материалов
|
| 32 |
+
✨ Креатив:
|
| 33 |
+
- "Создайте мем с фразой из текста"
|
| 34 |
+
- "Найдите самое странное предложение и объясните его"
|
| 35 |
+
|
| 36 |
+
2. PRACTICE (30-45% времени)
|
| 37 |
+
✔ Обязательно:
|
| 38 |
+
- 2 базовых упражнения ИЗ УЧЕБНИКА (gap-fill/matching/transformation)
|
| 39 |
+
- 1 активность с адаптацией материала (примеры ↓)
|
| 40 |
+
🎯 Дифференциация:
|
| 41 |
+
- Начинающие: добавь шаблоны/опции выбора
|
| 42 |
+
- Продвинутые: "Дополните предложения деталями"
|
| 43 |
+
🔥 Альтернативы:
|
| 44 |
+
- "Grammar Auction" с предложениями из текста
|
| 45 |
+
- "Find Someone Who..." с целевой лексикой
|
| 46 |
+
|
| 47 |
+
3. PRODUCTION (25-35% времени)
|
| 48 |
+
✔ Обязательно:
|
| 49 |
+
- Реальная коммуникация (не механические упражнения)
|
| 50 |
+
- Минимум 5 случаев использования целевого языка
|
| 51 |
+
💡 Идеи:
|
| 52 |
+
- "Снимите 30-секундный TikTok-обзор текста"
|
| 53 |
+
- Ролевая игра "Интервью с персонажем учебника"
|
| 54 |
+
|
| 55 |
+
4. ДОПОЛНИТЕЛЬНО
|
| 56 |
+
⏱ Тайминг-подсказки:
|
| 57 |
+
- На 60 мин: P(15) → Pr(25) → Pd(20)
|
| 58 |
+
- На 90 мин: P(20) → Pr(35) → Pd(30)
|
| 59 |
+
📝 ДЗ (если нужно):
|
| 60 |
+
- "Напишите альтернативный финал истории с 8 целевыми словами"
|
| 61 |
+
- "Создайте диалог-продолжение упражнения 5B"
|
| 62 |
+
|
| 63 |
+
❗ Важно:
|
| 64 |
+
- 70% контента должно быть с загруженной страницы
|
| 65 |
+
- Для детей добавь движение/игры
|
| 66 |
+
- Для взрослых — кейсы/дискуссии
|
| 67 |
+
""",
|
| 68 |
+
|
| 69 |
+
"TTT (Test-Teach-Test)": """
|
| 70 |
+
[МЕТОДИКА TTT]
|
| 71 |
+
... (оставьте ваш текущий контент)
|
| 72 |
+
"""
|
| 73 |
+
}
|
| 74 |
+
|
| 75 |
+
|
| 76 |
+
|
| 77 |
+
|
| 78 |
+
|
| 79 |
+
“Цель урока:
|
| 80 |
+
– Навыковая: Speaking (рассказать о своём опыте);
|
| 81 |
+
– Языковая: Grammar (Present Perfect для выражения жизненного опыта);
|
| 82 |
+
– Коммуникативная: Fluency (свободный диалог в парах);
|
| 83 |
+
– Жизненная: Collaboration (спланировать совместную поездку).”
|
| 84 |
+
|
| 85 |
+
METHODOLOGY_TIPS = {
|
| 86 |
+
"PPP (Presentation-Practice-Production)": """
|
| 87 |
+
[МЕТОДИКА PPP - ДЕТАЛЬНАЯ ИНСТРУКЦИЯ]
|
| 88 |
+
|
| 89 |
+
АНАЛИЗ МАТЕРИАЛА УЧЕБНИКА:
|
| 90 |
+
1. Определи ключевой языковой фокус (лексика/грамматика) из текста и упражнений
|
| 91 |
+
2. Выдели 5-7 целевых слов/фраз или 1 грамматическую структуру
|
| 92 |
+
3. Найди подходящий контекст (диалог, текст, картинки) для презентации
|
| 93 |
+
|
| 94 |
+
ПЛАН УРОКА:
|
| 95 |
+
|
| 96 |
+
=== PRESENTATION (20-25% времени) ===
|
| 97 |
+
Цель: Ввести язык в осмысленном контексте
|
| 98 |
+
• Используй материалы со страницы:
|
| 99 |
+
- Если есть диалог: "Прочитайте/прослушайте диалог из упр. X. Вопрос: What's the main problem?"
|
| 100 |
+
- Если текст: "Найдите 3 слова, описывающие [тему]"
|
| 101 |
+
- Если картинки: "Опишите фото из учебника. What do you see?"
|
| 102 |
+
• Явно выдели целевой язык:
|
| 103 |
+
- Создай таблицу на доске с примерами из учебника
|
| 104 |
+
- Сфокусируйся на: форме, значении, произношении
|
| 105 |
+
- Используй элиситацию: "What words describe [topic]?" → дополняй ответы
|
| 106 |
+
|
| 107 |
+
=== PRACTICE (30-40% времени) ===
|
| 108 |
+
Цель: Контролируемое применение языка
|
| 109 |
+
• Адаптируй упражнения со страницы:
|
| 110 |
+
- Упражнения на подстановку (gap-fills) → "Выполните упр. 3A индивидуально"
|
| 111 |
+
- Трансформации (rewriting) → "Измените предложения, как в примере из упр. 5B"
|
| 112 |
+
- Мини-диалоги → "В парах разыграйте диалог, заменив выделенные фразы"
|
| 113 |
+
• Прогрессия сложности:
|
| 114 |
+
1. Полностью контролируемые задания (из учебника)
|
| 115 |
+
2. Полу-контролируемые (частично измененные примеры)
|
| 116 |
+
3. Подготовка к Production (например, "Составьте 3 вопроса для партнера")
|
| 117 |
+
|
| 118 |
+
=== PRODUCTION (25-30% времени) ===
|
| 119 |
+
Цель: Свободное использование языка
|
| 120 |
+
• Создай коммуникативную активность на основе материалов:
|
| 121 |
+
- Ролевые игры: "Student A: Tourist (use phrases from p.X), Student B: Guide"
|
| 122 |
+
- Творческие задания: "Напишите email, используя 5 слов с доски"
|
| 123 |
+
- Обсуждения: "В группах решите: What's the best solution for [problem from text]?"
|
| 124 |
+
• Критерии:
|
| 125 |
+
- Минимум 5-7 реплик/предложений с целевым языком
|
| 126 |
+
- Минимальное вмешательство учителя
|
| 127 |
+
- Реальный обмен информацией (не механическое повторение)
|
| 128 |
+
|
| 129 |
+
ДОПОЛНИТЕЛЬНО:
|
| 130 |
+
• Дифференциация:
|
| 131 |
+
- Для сильных: "Добавьте 2 своих примера"
|
| 132 |
+
- Для слабых: "Используйте шаблон из рамки"
|
| 133 |
+
• Обратная связь:
|
| 134 |
+
- Исправь 2-3 типичные ошибки после Production
|
| 135 |
+
- Похвали успешное использование языка
|
| 136 |
+
• Домашнее задание (если требуется):
|
| 137 |
+
- Свяжи с уроком: "Напишите диалог, развивающий историю из учебника"
|
| 138 |
+
|
| 139 |
+
ПРИМЕР ДЛЯ СТРАНИЦЫ С ТЕМОЙ "TRAVEL":
|
| 140 |
+
1. Presentation: Карта из учебника → "Какие места вы узнаёте? What can you do there?" → введение фраз (book a ticket, pack luggage)
|
| 141 |
+
2. Practice: Упр. на заполнение пропусков в диалоге аэропорта → преобразование утверждений в вопросы
|
| 142 |
+
3. Production: Ролевая игра "Lost luggage" с использованием 5 фраз с урока
|
| 143 |
+
""",
|
| 144 |
+
}
|
| 145 |
+
|
| 146 |
+
|
| 147 |
+
|
| 148 |
+
|
| 149 |
+
|
| 150 |
+
|
| 151 |
+
|
| 152 |
+
|
| 153 |
+
|
| 154 |
+
|
| 155 |
+
|
| 156 |
+
промпт должен явно указать модели:
|
| 157 |
+
|
| 158 |
+
Анализировать визуальный контент,
|
| 159 |
+
|
| 160 |
+
Извлекать из него ключевые элементы для PPP,
|
| 161 |
+
|
| 162 |
+
Строить план урока на основе распознанного материала.
|
| 163 |
+
|
| 164 |
+
Вот как будет выглядеть финальный промпт:
|
| 165 |
+
|
| 166 |
+
Промпт для генерации PPP-плана на основе фото страницы учебника
|
| 167 |
+
Role: Ты — AI-ассистент для учителей английского, экспертно владеющий методологие�� PPP.
|
| 168 |
+
Goal: Создать структурированный план урока, строго соответствующий материалам на загруженной странице учебника.
|
| 169 |
+
|
| 170 |
+
Шаг 1: Анализ страницы учебника
|
| 171 |
+
(Эти инструкции получает модель, но не пользователь)
|
| 172 |
+
|
| 173 |
+
Определи:
|
| 174 |
+
|
| 175 |
+
Тема урока (напр., "Travel", "Food", "Past Continuous").
|
| 176 |
+
|
| 177 |
+
CEFR уровень (A1, B2 и т.д.) — по сложности текста/упражнений.
|
| 178 |
+
|
| 179 |
+
Целевой язык:
|
| 180 |
+
|
| 181 |
+
Лексика (минимум 5 ключевых слов/фраз из текста/заданий).
|
| 182 |
+
|
| 183 |
+
Грамматика (напр., Present Perfect, модальные глаголы).
|
| 184 |
+
|
| 185 |
+
Тип заданий на странице (gap-fill, диалоги, чтение).
|
| 186 |
+
|
| 187 |
+
Если данные неясны:
|
| 188 |
+
|
| 189 |
+
Спроси: «На странице нет явной темы. Уточните: это урок по грамматике (какой?) или лексике (какой теме?)».
|
| 190 |
+
|
| 191 |
+
Если фото размыто/нечитаемо: «Не удалось распознать текст. Загрузите более четкое фото или укажите тему вручную».
|
| 192 |
+
|
| 193 |
+
Шаг 2: Генерация PPP-плана
|
| 194 |
+
Инструкции для модели:
|
| 195 |
+
Используй только материалы с загруженной страницы. Если учитель ввел параметры (тема, уровень), проверь их соответствие контенту учебника.
|
| 196 |
+
|
| 197 |
+
1. Presentation (20-25% времени)
|
| 198 |
+
Контекст:
|
| 199 |
+
|
| 200 |
+
«Используй изображения/заголовки с фото страницы для ввода в тему. Пример:
|
| 201 |
+
|
| 202 |
+
Если на странице есть картинки с людьми в аэропорту: «Покажите фото из учебника. Спросите: ‘What do you see? Have you ever been in this situation?’».
|
| 203 |
+
|
| 204 |
+
Если текст — диалог: «Проиграйте аудио/прочитайте диалог. Задайте вопрос: ‘What’s the main problem?»».
|
| 205 |
+
|
| 206 |
+
Целевой язык:
|
| 207 |
+
|
| 208 |
+
«Выдели из текста/упражнений:
|
| 209 |
+
|
| 210 |
+
Лексика: 5-7 ключевых слов (напр., из заголовка или выделенных в учебнике).
|
| 211 |
+
|
| 212 |
+
Грамматика: конструкция, которая повторяется (напр., условные предложения).
|
| 213 |
+
|
| 214 |
+
Как презентовать:
|
| 215 |
+
|
| 216 |
+
Создай таблицу на доске с примерами из текста.
|
| 217 |
+
|
| 218 |
+
Используй упражнение №X с фото страницы для элиситации (напр., gap-fill с пропущенными глаголами).
|
| 219 |
+
|
| 220 |
+
2. Practice (30-40% времени)
|
| 221 |
+
Задания:
|
| 222 |
+
|
| 223 |
+
«Адаптируй упражнения с фото страницы:
|
| 224 |
+
|
| 225 |
+
Если есть matching (сопоставление): «Раздайте карточки из упр. 3. В парах сопоставьте слова с определениями».
|
| 226 |
+
|
| 227 |
+
Если есть ролевая игра: «Разыграйте диалог из учебника, заменив выделенные фразы на свои».
|
| 228 |
+
|
| 229 |
+
Дифференциация:
|
| 230 |
+
|
| 231 |
+
Для mixed уровней: «Advanced: добавьте 2 своих примера. Beginners: используйте словарь со стр. X».
|
| 232 |
+
|
| 233 |
+
3. Production (25-30% времени)
|
| 234 |
+
Активность:
|
| 235 |
+
|
| 236 |
+
«Создай задание, расширяющее тему учебника. Примеры:
|
| 237 |
+
|
| 238 |
+
Если на странице текст про путешествия: «Смоделируйте ситуацию: вы в аэропорту. Разработайте диалог ‘Lost Luggage’ с 5 фразами из урока».
|
| 239 |
+
|
| 240 |
+
Если грамматика: Past Continuous: «Напишите историю ‘What Were You Doing When…?’ используя 4 примера из учебника».
|
| 241 |
+
|
| 242 |
+
4. Homework & Feedback
|
| 243 |
+
ДЗ: Если на странице есть письменное задание (напр., «Write an email»), используй его. Если нет: «Напишите 10 предложений, используя слова из таблицы на доске».
|
| 244 |
+
|
| 245 |
+
Коррекция: «Выберите 2 частые ошибки из Production. Напишите, как исправить (напр., неправильный порядок слов в Present Perfect)».
|
| 246 |
+
|
| 247 |
+
Пример работы промпта
|
| 248 |
+
Фото страницы: Учебник "English File Pre-Intermediate", стр. 78 — текст про экологию, упражнения на Present Perfect, слова: recycle, pollution, environment.
|
| 249 |
+
Параметры учителя: Длительность — 45 мин, возраст — подростки 14 лет.
|
| 250 |
+
|
| 251 |
+
Сгенерированный план:
|
| 252 |
+
|
| 253 |
+
Presentation (10 мин):
|
| 254 |
+
|
| 255 |
+
Обсуждение картинки с загрязненным парком из учебника: «What’s wrong here? What would you do?».
|
| 256 |
+
|
| 257 |
+
Выписать на доску слова: recycle, pollution, environment. Добавить примеры из текста.
|
| 258 |
+
|
| 259 |
+
Хоровая отработка произношения.
|
| 260 |
+
|
| 261 |
+
Practice (20 мин):
|
| 262 |
+
|
| 263 |
+
Упр. 2A (gap-fill с Present Perfect): «Сделайте индивидуально, потом проверка в парах».
|
| 264 |
+
|
| 265 |
+
Ролевая игра: «Student A: Environmental activist. Student B: Mayor. Discuss solutions (use 3 words from the board)».
|
| 266 |
+
|
| 267 |
+
Production (15 мин):
|
| 268 |
+
|
| 269 |
+
Проект: «Создайте плакат ‘Save Our Park’ с 5 советами на основе урока (используйте Present Perfect: ‘We have recycled...’)».
|
| 270 |
+
|
| 271 |
+
ДЗ: «Напишите письмо мэру с 3 предложениями из вашего плаката».
|
| 272 |
+
|
| 273 |
+
Критические моменты для промпта:
|
| 274 |
+
Жесткая привязка к контенту учебника:
|
| 275 |
+
|
| 276 |
+
«Не придумывай слова/грамматику — бери только с фото страницы».
|
| 277 |
+
|
| 278 |
+
Проверка на противоречия:
|
| 279 |
+
|
| 280 |
+
«Если учитель указал тему ‘Food’, а на странице текст про спорт — предупреди: ‘Тема урока не совпадает с учебником. Использовать спортивную лексику?’».
|
| 281 |
+
|
| 282 |
+
Работа с визуалом:
|
| 283 |
+
|
| 284 |
+
«Если на странице есть схемы/таблицы — используй их для наглядности в Presentation».
|
app/quotes.py
ADDED
|
@@ -0,0 +1,118 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
|
| 2 |
+
quotes = [
|
| 3 |
+
"<em>«Хороший план — это гибкая структура, готовая к импровизации»</em><br>",
|
| 4 |
+
"<em>«Ошибки ученика — это дорожки к его пониманию, а не провалы»</em><br>",
|
| 5 |
+
"<em>«Обратная связь должна быть 'зеленой' — отмечай сильные стороны прежде, чем указывать на слабые»</em><br>",
|
| 6 |
+
"<em>«Каждый этап урока — это возможность для ученика стать активным соавтором обучения»</em><br>",
|
| 7 |
+
"<em>«Контекст важнее слова: учи не словам, а ситуациям их использования»</em><br>",
|
| 8 |
+
"<em>«Scaffolding — это временные колёсики, которые мы убираем, когда ученики готовы ехать сами»</em><br>",
|
| 9 |
+
"<em>«Коммуникация важнее совершенства формы»</em><br>",
|
| 10 |
+
"<em>«Ваш план урока — как волшебный амулет, который защитит вас от того, чтобы быть съеденным заживо»</em><br>Скотт Торнбери",
|
| 11 |
+
"<em>«Каждый урок — это маленький эксперимент, а не экзамен»</em><br>",
|
| 12 |
+
"<em>«Самый ценный ресурс урока — внимание учителя к человеку, а не к программе»</em><br>",
|
| 13 |
+
"<em>«Учитель — не носитель знаний, он — архитектор обучающего пространства»</em><br>",
|
| 14 |
+
"<em>«Concept checking — это не тест, а приглашение к диалогу»</em><br>",
|
| 15 |
+
"<em>«<em>«Человеческие существа всегда учились методом проб и ошибок, и изучение нового языка не исключение»</em><br>Джим Скривенер",
|
| 16 |
+
"<em>«Задача учителя — создать потребность в языке, а не навязать материал»</em><br>",
|
| 17 |
+
"<em>«Настоящее планирование освобождает учителя учителя на занятии - слушать, отмечать, реагировать (философия ELT)",
|
| 18 |
+
"<em>«Рефлексия учителя — мощнейший инструмент профессионального роста»</em><br>",
|
| 19 |
+
"<em>«Уроки — это лаборатория: экспериментируй, наблюдай, делай выводы»</em><br>",
|
| 20 |
+
"<em>«Материалы — лишь топливо; подлинный двигатель урока — взаимодействие»</em><br>",
|
| 21 |
+
"<em>«Персонализация отвлечёт от учебника, но приведёт к истинному усвоению»</em><br>",
|
| 22 |
+
"<em>«Урок без элемента игры — как картина без цвета»</em><br>",
|
| 23 |
+
"<em>«Комбинируя структуры и свободу, мы создаём условия для открытия нового»</em><br>",
|
| 24 |
+
"<em>«План занятия — это обещание, которое ты даёшь своим ученикам.»</em><br>",
|
| 25 |
+
"<em>«Образовательная цель оживает только в момент, когда ученики её делают своей.»</em><br>"
|
| 26 |
+
]
|
| 27 |
+
|
| 28 |
+
|
| 29 |
+
|
| 30 |
+
|
| 31 |
+
#
|
| 32 |
+
#
|
| 33 |
+
# quotes = [
|
| 34 |
+
#
|
| 35 |
+
# "<em>«»</em><br>
|
| 36 |
+
# "<em>«»</em><br>
|
| 37 |
+
#
|
| 38 |
+
#
|
| 39 |
+
# «Один из величайших врагов успешного преподавания — это скука учеников.»
|
| 40 |
+
# — Джереми Хармер
|
| 41 |
+
#
|
| 42 |
+
# «Преподавание — это живое, творческое, личное, межличностное искусство.»
|
| 43 |
+
# — Джим Скривенер
|
| 44 |
+
#
|
| 45 |
+
# ваш план урока — как волшебный амулет, который защитит вас от того, чтобы быть съеденным заживо.
|
| 46 |
+
# — Скотт Торнбери
|
| 47 |
+
#
|
| 48 |
+
#
|
| 49 |
+
# «Забудьте о методологии. Ученикам просто нужно больше практики.»
|
| 50 |
+
# — Джим Скривенер
|
| 51 |
+
#
|
| 52 |
+
# «Человеческие существа всегда учились методом проб и ошибок, и изучение нового языка не исключение.»
|
| 53 |
+
# — Джим Скривенер
|
| 54 |
+
#
|
| 55 |
+
# More Than English
|
| 56 |
+
# "A lesson plan is not a script. It is a map drawn with care, so we can wander with freedom."
|
| 57 |
+
# — inspired
|
| 58 |
+
# by
|
| 59 |
+
# Scott
|
| 60 |
+
# Thornbury
|
| 61 |
+
#
|
| 62 |
+
# "True planning liberates the teacher: the mind is free to listen, to notice, to respond."
|
| 63 |
+
# — Anonymous(inspired
|
| 64 |
+
# by
|
| 65 |
+
# ELT
|
| 66 |
+
# teaching
|
| 67 |
+
# philosophy)
|
| 68 |
+
#
|
| 69 |
+
# "When we plan with the learner in mind, the lesson becomes a journey, not a checklist."
|
| 70 |
+
# — based
|
| 71 |
+
# on
|
| 72 |
+
# ideas
|
| 73 |
+
# by
|
| 74 |
+
# Penny
|
| 75 |
+
# Ur
|
| 76 |
+
#
|
| 77 |
+
# "Good teaching is prepared spontaneity. Planning gives wings to presence."
|
| 78 |
+
# — inspired
|
| 79 |
+
# by
|
| 80 |
+
# Jim
|
| 81 |
+
# Scrivener
|
| 82 |
+
#
|
| 83 |
+
# "Language teaching is not about control. It is about building spaces where real communication can happen."
|
| 84 |
+
# — reflections
|
| 85 |
+
# on
|
| 86 |
+
# Communicative
|
| 87 |
+
# Language
|
| 88 |
+
# Teaching(CLT)
|
| 89 |
+
#
|
| 90 |
+
# "The art of teaching is not filling time. It is filling hearts."
|
| 91 |
+
# — Anonymous
|
| 92 |
+
#
|
| 93 |
+
# "We plan not because we mistrust the learner, but because we trust the encounter."
|
| 94 |
+
# — A
|
| 95 |
+
# thought
|
| 96 |
+
# from the CELTA
|
| 97 |
+
# world
|
| 98 |
+
#
|
| 99 |
+
# «Ошибки — это дыхание обучения. Если их нет, ученик задохнулся.»
|
| 100 |
+
# — Переосмысление подхода к ошибкам в Communicative Methodology
|
| 101 |
+
#
|
| 102 |
+
# «Учитель не держит знания в руках. Он строит мосты через незнание.»
|
| 103 |
+
# — Переосмысление роли учителя в Humanistic Teaching
|
| 104 |
+
#
|
| 105 |
+
# «Хорошая обратная связь — это не красная ручка, а зелёная кисть.»
|
| 106 |
+
# — Философия positive feedback, CELTA
|
| 107 |
+
#
|
| 108 |
+
#
|
| 109 |
+
# «Мы не обучаем языку. Мы создаём пространство, в котором язык рождается.»
|
| 110 |
+
# — Jim Scrivener, свободная интерпретация идей Demand High Teaching
|
| 111 |
+
#
|
| 112 |
+
# "A teacher without a plan is like a ship without a sail; a teacher chained to a plan is like a ship in a bottle."
|
| 113 |
+
# — based
|
| 114 |
+
# on
|
| 115 |
+
# ELT
|
| 116 |
+
# training
|
| 117 |
+
# aphorisms
|
| 118 |
+
# # Зарубежные
|
app/styles.css
ADDED
|
@@ -0,0 +1,69 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
/* Основной фон */
|
| 2 |
+
/*.gradio-container {
|
| 3 |
+
background-color: #fef3c7;
|
| 4 |
+
} */
|
| 5 |
+
|
| 6 |
+
/* Заголовок */
|
| 7 |
+
/* .main-title h2 { */
|
| 8 |
+
text-align: left;
|
| 9 |
+
font-size: 2rem;
|
| 10 |
+
margin: 0; /* Убираем отступы вокруг заголовка */
|
| 11 |
+
/*color: #003366;*/
|
| 12 |
+
margin-bottom: -5px; !important /* Убираем отступ снизу заголовка */
|
| 13 |
+
padding: 0;
|
| 14 |
+
}
|
| 15 |
+
|
| 16 |
+
|
| 17 |
+
/* Цитата */
|
| 18 |
+
.quote-block {
|
| 19 |
+
text-align: left;
|
| 20 |
+
/*font-style: italic;*/
|
| 21 |
+
padding: 0;
|
| 22 |
+
margin: -1px 0 0 0; /* верхний небольшой отступ, снизу чуть больше */
|
| 23 |
+
/*max-width: 30em;*/ /* ограничиваем ширину, чтобы не тянулась на всю строку */
|
| 24 |
+
line-height: 1.4em;
|
| 25 |
+
}
|
| 26 |
+
|
| 27 |
+
|
| 28 |
+
/* .left-col { */
|
| 29 |
+
/* background-color: #CDE8FA; /* более тёмный голубой */
|
| 30 |
+
/* padding: 20px; */
|
| 31 |
+
/* Можно и цвет текста подкорректировать */
|
| 32 |
+
/* color: #003366; */
|
| 33 |
+
/* } */
|
| 34 |
+
|
| 35 |
+
.right-col {
|
| 36 |
+
background-color: #F0FAFF; /* посветлее */
|
| 37 |
+
padding: 0px;
|
| 38 |
+
color: #fef3c7;
|
| 39 |
+
}
|
| 40 |
+
|
| 41 |
+
/* Поле для конспекта */
|
| 42 |
+
#plan-output {
|
| 43 |
+
border: 2px dashed #bbb;
|
| 44 |
+
border-radius: 12px;
|
| 45 |
+
background-color: ##f5f5f5;
|
| 46 |
+
padding: 20px;
|
| 47 |
+
min-height: 1050px;
|
| 48 |
+
font-style: italic;
|
| 49 |
+
color: #555;
|
| 50 |
+
box-shadow: 0 2px 6px rgba(0,0,0,0.05);
|
| 51 |
+
}
|
| 52 |
+
|
| 53 |
+
/*#f5f5f5*/
|
| 54 |
+
|
| 55 |
+
/* Стилизуем заголовок аккордеона (самую "кнопку") */
|
| 56 |
+
.feedback-button {
|
| 57 |
+
font-weight: bold;
|
| 58 |
+
text-align: center;
|
| 59 |
+
background-color: #f1f1f1;
|
| 60 |
+
padding: 12px 18px;
|
| 61 |
+
border-radius: 10px;
|
| 62 |
+
margin-top: 12px;
|
| 63 |
+
}
|
| 64 |
+
|
| 65 |
+
.feedback-confirmation {
|
| 66 |
+
display: block !important;
|
| 67 |
+
margin-top: 10px;
|
| 68 |
+
color: green;
|
| 69 |
+
}
|
app/test_502.py
ADDED
|
@@ -0,0 +1,23 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import gradio as gr
|
| 2 |
+
|
| 3 |
+
def greet(name):
|
| 4 |
+
return f"Привет, {name}!"
|
| 5 |
+
|
| 6 |
+
demo = gr.Interface(
|
| 7 |
+
fn=greet,
|
| 8 |
+
inputs=gr.Textbox(label="Введите ваше имя"),
|
| 9 |
+
outputs=gr.Textbox(label="Приветствие")
|
| 10 |
+
)
|
| 11 |
+
|
| 12 |
+
if __name__ == "__main__":
|
| 13 |
+
# Отключаем проверку localhost и пробуем разные порты
|
| 14 |
+
try:
|
| 15 |
+
demo.launch(
|
| 16 |
+
server_port=7860,
|
| 17 |
+
prevent_thread_lock=True, # Не блокировать основной поток
|
| 18 |
+
show_error=True, # Показывать детальные ошибки
|
| 19 |
+
inbrowser=True # Автоматически открывать браузер
|
| 20 |
+
)
|
| 21 |
+
input("Нажмите Enter чтобы остановить сервер...") # Держим сервер активным
|
| 22 |
+
except Exception as e:
|
| 23 |
+
print(f"Ошибка: {e}")
|
app/test_gradio.py
ADDED
|
@@ -0,0 +1,486 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import os
|
| 2 |
+
import logging
|
| 3 |
+
import tempfile
|
| 4 |
+
from datetime import datetime
|
| 5 |
+
from dotenv import load_dotenv
|
| 6 |
+
from openai import OpenAI
|
| 7 |
+
import gradio as gr
|
| 8 |
+
from docx import Document
|
| 9 |
+
import requests
|
| 10 |
+
from typing import Optional
|
| 11 |
+
|
| 12 |
+
import random
|
| 13 |
+
from app.quotes import quotes
|
| 14 |
+
from app.drawings import drawings
|
| 15 |
+
from app.knowledge_base.textbooks import TEXTBOOKS
|
| 16 |
+
# --- Настройка ---
|
| 17 |
+
logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s')
|
| 18 |
+
load_dotenv()
|
| 19 |
+
api_key = os.getenv("API_KEY_openai")
|
| 20 |
+
client = OpenAI(api_key=api_key) if api_key else None
|
| 21 |
+
VS_ID = os.getenv("VECTOR_STORE_ID", "") # vector store for file_search if needed
|
| 22 |
+
|
| 23 |
+
# --- Утилиты ---
|
| 24 |
+
def upload_to_catbox(file_bytes: bytes) -> str:
|
| 25 |
+
"""Загружает файл на catbox.moe и возвращает URL"""
|
| 26 |
+
try:
|
| 27 |
+
response = requests.post(
|
| 28 |
+
"https://catbox.moe/user/api.php",
|
| 29 |
+
files={"fileToUpload": file_bytes},
|
| 30 |
+
data={"reqtype": "fileupload"},
|
| 31 |
+
timeout=10
|
| 32 |
+
)
|
| 33 |
+
response.raise_for_status()
|
| 34 |
+
return response.text.strip()
|
| 35 |
+
except Exception as e:
|
| 36 |
+
logging.error(f"Ошибка загрузки изображения: {e}")
|
| 37 |
+
raise gr.Error("Не удалось загрузить изображение")
|
| 38 |
+
|
| 39 |
+
|
| 40 |
+
def generate_docx(text: str) -> str:
|
| 41 |
+
"""Сохраняет текст в .docx и возвращает путь"""
|
| 42 |
+
doc = Document()
|
| 43 |
+
for line in text.split("\n"):
|
| 44 |
+
doc.add_paragraph(line)
|
| 45 |
+
tmp = tempfile.gettempdir()
|
| 46 |
+
path = os.path.join(tmp, f"lesson_plan_{datetime.now().strftime('%Y%m%d%H%M%S')}.docx")
|
| 47 |
+
doc.save(path)
|
| 48 |
+
return path
|
| 49 |
+
|
| 50 |
+
# названия textbooks для автозаполнения поля Учебник
|
| 51 |
+
import json
|
| 52 |
+
|
| 53 |
+
## Сохраняем отзыв через POST в google-таблицу
|
| 54 |
+
GOOGLE_SHEET_URL = os.getenv("FEEDBACK_GS_URL")
|
| 55 |
+
|
| 56 |
+
def save_feedback(comment, rate):
|
| 57 |
+
payload = {
|
| 58 |
+
"comment": comment,
|
| 59 |
+
"rate": rate
|
| 60 |
+
}
|
| 61 |
+
try:
|
| 62 |
+
requests.post(GOOGLE_SHEET_URL, json=payload, timeout=3)
|
| 63 |
+
except Exception as e:
|
| 64 |
+
print(f"Ошибка при отправке отзыва: {e}")
|
| 65 |
+
|
| 66 |
+
### ОСНОВНАЯ ФУНКЦИЯ ГЕНЕРАЦИИ
|
| 67 |
+
def generate_lesson_plan(
|
| 68 |
+
image_path: Optional[str],
|
| 69 |
+
textbook: str,
|
| 70 |
+
cefr: str,
|
| 71 |
+
topic: str,
|
| 72 |
+
goal: str,
|
| 73 |
+
format_type: str,
|
| 74 |
+
num_students: int,
|
| 75 |
+
age: str,
|
| 76 |
+
adults: bool,
|
| 77 |
+
level_match: int,
|
| 78 |
+
duration: int,
|
| 79 |
+
inventory: str,
|
| 80 |
+
extra_info: str,
|
| 81 |
+
methodology: str,
|
| 82 |
+
target_language: str,
|
| 83 |
+
hw_required: bool,
|
| 84 |
+
web_search: bool
|
| 85 |
+
# repetition: bool,
|
| 86 |
+
# application: bool,
|
| 87 |
+
# analysis: bool,
|
| 88 |
+
# creativity: bool
|
| 89 |
+
) -> str:
|
| 90 |
+
|
| 91 |
+
# Валидация API клиента
|
| 92 |
+
if not client:
|
| 93 |
+
raise gr.Error("API ключ не настроен")
|
| 94 |
+
# Проверка наличия изображения
|
| 95 |
+
if not image_path:
|
| 96 |
+
return "❗ Загрузите фото страницы учебника для генерации урока"
|
| 97 |
+
|
| 98 |
+
# Загружаем изображение и получаем URL
|
| 99 |
+
try:
|
| 100 |
+
with open(image_path, "rb") as f:
|
| 101 |
+
image_url = upload_to_catbox(f.read())
|
| 102 |
+
except Exception as e:
|
| 103 |
+
logging.error(f"Image upload error: {e}")
|
| 104 |
+
raise gr.Error("Не удалось загрузить изображение")
|
| 105 |
+
|
| 106 |
+
# Собираем текстовый prompt
|
| 107 |
+
lesson_params = {
|
| 108 |
+
'methodology': methodology,
|
| 109 |
+
'target_language': target_language, # для PPP
|
| 110 |
+
'textbook': textbook,
|
| 111 |
+
'cefr': cefr,
|
| 112 |
+
'topic': topic,
|
| 113 |
+
'goal': goal,
|
| 114 |
+
'num_students': num_students,
|
| 115 |
+
'age': 'Взрослые' if adults else age,
|
| 116 |
+
'level_match': level_match,
|
| 117 |
+
'duration': duration,
|
| 118 |
+
'inventory': inventory,
|
| 119 |
+
'hw_required': hw_required,
|
| 120 |
+
'extra_info': extra_info
|
| 121 |
+
}
|
| 122 |
+
|
| 123 |
+
# Получаем готовый промпт
|
| 124 |
+
from app.prompt_builder.prompt import build_prompt
|
| 125 |
+
full_prompt = build_prompt(lesson_params)
|
| 126 |
+
|
| 127 |
+
# Собираем входные данные согласно API
|
| 128 |
+
input_content = [
|
| 129 |
+
{
|
| 130 |
+
"type": "input_text",
|
| 131 |
+
"text": full_prompt
|
| 132 |
+
},
|
| 133 |
+
{
|
| 134 |
+
"type": "input_image",
|
| 135 |
+
"image_url": image_url,
|
| 136 |
+
"detail": "high"
|
| 137 |
+
}
|
| 138 |
+
]
|
| 139 |
+
|
| 140 |
+
# Опции инструментов
|
| 141 |
+
tools = []
|
| 142 |
+
tool_choice = None
|
| 143 |
+
if web_search:
|
| 144 |
+
tools.append({
|
| 145 |
+
"type": "web_search_preview",
|
| 146 |
+
"search_context_size": "medium",
|
| 147 |
+
"user_location": {"type": "approximate", "country": "RU"}
|
| 148 |
+
})
|
| 149 |
+
tool_choice = {"type": "web_search_preview"}
|
| 150 |
+
|
| 151 |
+
# Вызов LLM
|
| 152 |
+
try:
|
| 153 |
+
response = client.responses.create(
|
| 154 |
+
input=[{"role": "user", "content": input_content}],
|
| 155 |
+
model="o4-mini", # gpt-4o-mini gpt-4.1
|
| 156 |
+
tools=tools or None,
|
| 157 |
+
tool_choice=tool_choice,
|
| 158 |
+
max_output_tokens=8192,
|
| 159 |
+
reasoning= {"effort":"medium"},
|
| 160 |
+
stream=False
|
| 161 |
+
)
|
| 162 |
+
return response.output_text
|
| 163 |
+
|
| 164 |
+
except Exception as e:
|
| 165 |
+
logging.error(f"Generation error: {e}")
|
| 166 |
+
raise gr.Error(f"Ошибка генерации: {e}")
|
| 167 |
+
|
| 168 |
+
|
| 169 |
+
|
| 170 |
+
########## ИНТЕРФЕЙС
|
| 171 |
+
# Случайный рисунок в блокноте
|
| 172 |
+
drawing = random.choice(drawings)
|
| 173 |
+
# Текст с подсказкой и рисунком в блокноте
|
| 174 |
+
hint_text = f"""Здесь появится план занятия — заполните вводные и нажмите кнопку **Создать план**<br>
|
| 175 |
+
Создание может занять до 1 минуты
|
| 176 |
+
<pre>
|
| 177 |
+
{drawing}
|
| 178 |
+
</pre>
|
| 179 |
+
"""
|
| 180 |
+
|
| 181 |
+
#ТЕМА И СТИЛИ
|
| 182 |
+
### css привязывать именно так
|
| 183 |
+
#theme='earneleh/paris'
|
| 184 |
+
theme = gr.themes.Base(
|
| 185 |
+
secondary_hue="rose",
|
| 186 |
+
neutral_hue="stone",
|
| 187 |
+
).set(
|
| 188 |
+
body_background_fill='*primary_50',
|
| 189 |
+
body_text_color='*primary_900',
|
| 190 |
+
body_text_size='*text_lg',
|
| 191 |
+
body_text_color_subdued='*primary_700',
|
| 192 |
+
body_text_weight='600',
|
| 193 |
+
)
|
| 194 |
+
css_path = os.path.join(os.path.dirname(__file__), "styles.css")
|
| 195 |
+
|
| 196 |
+
# ИНТЕРФЕЙС
|
| 197 |
+
with gr.Blocks(theme=theme, css_paths=css_path) as app:
|
| 198 |
+
advanced_settings_visible = gr.State(value=False) # Импортируем gr.State для хранения состояния
|
| 199 |
+
feedback_visible = gr.State(False) # Хранит, открыт ли блок отзыва
|
| 200 |
+
|
| 201 |
+
gr.Markdown("# План урока английского языка", elem_classes=["main-title"])
|
| 202 |
+
quote_box = gr.Markdown(random.choice(quotes), elem_classes=["quote-block"])
|
| 203 |
+
with gr.Row():
|
| 204 |
+
with gr.Column(elem_classes=["left-col"], scale=1):
|
| 205 |
+
image = gr.Image(
|
| 206 |
+
label="Фото страницы учебника*",
|
| 207 |
+
type="filepath",
|
| 208 |
+
height=0, # Автоматическая высота
|
| 209 |
+
container=False # Не растягивать контейнер
|
| 210 |
+
)
|
| 211 |
+
|
| 212 |
+
# Блок 1: Учебник
|
| 213 |
+
with gr.Column(variant="panel"):
|
| 214 |
+
gr.Markdown("### 📚 Учебник", elem_classes=["block-title"])
|
| 215 |
+
textbook = gr.Textbox(label="Название учебника", placeholder="напр. English File Beginner", elem_id="textbook_input")
|
| 216 |
+
|
| 217 |
+
cefr = gr.Dropdown(label="Уровень", choices=["", "A1", "A2", "B1", "B2", "C1", "C2"],
|
| 218 |
+
value="", info="Выберите уровень")
|
| 219 |
+
# Блок 2: Класс
|
| 220 |
+
with gr.Column(variant="panel"):
|
| 221 |
+
gr.Markdown("### 👥 Класс", elem_classes=["block-title"])
|
| 222 |
+
format_type = gr.Radio(label="Формат занятия", choices=["Индивидуальное", "Групповое"],
|
| 223 |
+
value="Групповое")
|
| 224 |
+
|
| 225 |
+
with gr.Group(visible=True) as group_settings:
|
| 226 |
+
num_students = gr.Slider(label="Количество учеников", minimum=1, maximum=40,
|
| 227 |
+
value=10, step=1, info="Для групповых занятий")
|
| 228 |
+
|
| 229 |
+
with gr.Group() as age_group:
|
| 230 |
+
age = gr.Textbox(label="Возраст", placeholder="напр. 10–11", interactive=True)
|
| 231 |
+
adults = gr.Checkbox(label="Взрослые")
|
| 232 |
+
|
| 233 |
+
level_match = gr.Dropdown(label = "Уровень учеников относительно учебника",
|
| 234 |
+
choices = ["ниже", "на уровне", "выше", "mixed"], value = "на уровне")
|
| 235 |
+
|
| 236 |
+
# Блок 3: Занятие
|
| 237 |
+
with gr.Column(variant="panel"):
|
| 238 |
+
gr.Markdown("### 📄 Занятие", elem_classes=["block-title"])
|
| 239 |
+
topic = gr.Textbox(label="Тема", placeholder="напр. Daily routines")
|
| 240 |
+
goal = gr.Textbox(label="Цель", placeholder="К концу урока ученики смогут...")
|
| 241 |
+
duration = gr.Slider(label="Длительность (мин)", minimum=30, maximum=180, value=60, step=5)
|
| 242 |
+
inventory = gr.Textbox(label="Инвентарь", placeholder="по умолчанию - доска и проектор")
|
| 243 |
+
extra_info = gr.Textbox(label="Допонительная информация", placeholder="Класс весёлый и взвинченный после физкультуры")
|
| 244 |
+
|
| 245 |
+
# Блок 4: Методика
|
| 246 |
+
with gr.Column(variant="panel"):
|
| 247 |
+
gr.Markdown("### 🎓 Методика", elem_classes=["block-title"])
|
| 248 |
+
methodology = gr.Dropdown(label="Методика преподавания",
|
| 249 |
+
choices=["PPP (Presentation-Practice-Production)",
|
| 250 |
+
"TTT (Test-Teach-Test)"],
|
| 251 |
+
value="PPP (Presentation-Practice-Production)")
|
| 252 |
+
target_language = gr.Textbox(
|
| 253 |
+
label="Target language",
|
| 254 |
+
placeholder="Например: 'I have been to...' 'How long have you...?' (Present Perfect experience)",
|
| 255 |
+
visible=True # По умолчанию видно, так как PPP выбран
|
| 256 |
+
)
|
| 257 |
+
|
| 258 |
+
# advanced_btn = gr.Button(value="➕ Продвинутые настройки (в разработке", size="sm")
|
| 259 |
+
#
|
| 260 |
+
# # Блок продвинутых настроек, изначально скрыт
|
| 261 |
+
# with gr.Column(visible=False) as advanced_block:
|
| 262 |
+
# gr.Markdown("**💡 Уровни задач (таксономия):**")
|
| 263 |
+
# repetition = gr.Checkbox(label="Повторение")
|
| 264 |
+
# application = gr.Checkbox(label="Применение")
|
| 265 |
+
# analysis = gr.Checkbox(label="Анализ")
|
| 266 |
+
# creativity = gr.Checkbox(label="Творчество")
|
| 267 |
+
|
| 268 |
+
hw_required = gr.Checkbox(label="Домашнее задание")
|
| 269 |
+
web_search = gr.Checkbox(label="Доп. материалы из интернета")
|
| 270 |
+
|
| 271 |
+
btn = gr.Button("Создать план", variant="primary", size="lg")
|
| 272 |
+
|
| 273 |
+
# Правая колонка — результат (output)
|
| 274 |
+
with gr.Column(elem_classes=["right-col"], scale=2):
|
| 275 |
+
# Общий блок-панель для правой колонки
|
| 276 |
+
with gr.Column(variant="panel"): # <<< Главная панель
|
| 277 |
+
gr.Markdown("### План урока", elem_classes=["block-title"]) # Заголовок ВНУТРИ панели
|
| 278 |
+
# Блок с выводом плана
|
| 279 |
+
output = gr.Markdown(
|
| 280 |
+
hint_text,
|
| 281 |
+
elem_id="plan-output"
|
| 282 |
+
)
|
| 283 |
+
# Кнопка скачивания (оставляем внутри панели)
|
| 284 |
+
download_btn = gr.DownloadButton(
|
| 285 |
+
label="⬇️ Скачать .docx",
|
| 286 |
+
visible=False
|
| 287 |
+
)
|
| 288 |
+
# Кнопка "Помогите нам стать лучше"
|
| 289 |
+
feedback_btn = gr.Button("💬 Помогите нам стать лучше", elem_classes=["feedback-button"])
|
| 290 |
+
|
| 291 |
+
# Скрытый блок с обратной связью
|
| 292 |
+
with gr.Column(visible=False) as feedback_block:
|
| 293 |
+
gr.Markdown("_Спасибо, что попробовали! Как вам?_\n_Ваши наблюдения и замечания помогают нам расти._")
|
| 294 |
+
|
| 295 |
+
|
| 296 |
+
def toggle_feedback_block(current_visible):
|
| 297 |
+
return (
|
| 298 |
+
gr.update(visible=not current_visible), # показать/скрыть блок
|
| 299 |
+
not current_visible, # обновить состояние
|
| 300 |
+
gr.update(visible=False) # скрыть благодарность при открытии/закрытии
|
| 301 |
+
)
|
| 302 |
+
feedback_text = gr.Textbox(
|
| 303 |
+
label="Ваше наблюдение или комментарий",
|
| 304 |
+
placeholder="Например: 'Для 3 лет лексика подбирается неправильно — какая там 'машина', максимум - 'би-би'",
|
| 305 |
+
lines=4
|
| 306 |
+
)
|
| 307 |
+
|
| 308 |
+
rating = gr.Radio(
|
| 309 |
+
choices=["1", "2", "3", "4", "5"],
|
| 310 |
+
label="Оценка"
|
| 311 |
+
)
|
| 312 |
+
|
| 313 |
+
send_feedback = gr.Button("📩 Отправить отзыв")
|
| 314 |
+
|
| 315 |
+
feedback_confirmation = gr.Markdown(
|
| 316 |
+
visible=False,
|
| 317 |
+
elem_classes=["feedback-confirmation"]
|
| 318 |
+
)
|
| 319 |
+
|
| 320 |
+
# <-- Блок благодарности — ВНЕ feedback_block, но СРАЗУ ПОСЛЕ
|
| 321 |
+
with gr.Column(visible=False) as feedback_confirmation:
|
| 322 |
+
gr.Markdown("✅ Спасибо! Ваш комментарий передан и, возможно, уже сегодня ассистент станет полезнее :)")
|
| 323 |
+
|
| 324 |
+
# Остальное
|
| 325 |
+
gr.Markdown(
|
| 326 |
+
"""
|
| 327 |
+
🙌 Если вас заинтересовал проект, мы приглашаем
|
| 328 |
+
👉 [присоединиться к Telegram-группе](https://t.me/+yN9BSJ1DJxxjZmJi)
|
| 329 |
+
"""
|
| 330 |
+
)
|
| 331 |
+
|
| 332 |
+
### --- Логика интерфейса ---
|
| 333 |
+
## Доп. настройки
|
| 334 |
+
# def toggle_advanced_settings(visible):
|
| 335 |
+
# return gr.update(visible=not visible), not visible
|
| 336 |
+
|
| 337 |
+
# advanced_btn.click(
|
| 338 |
+
# fn=toggle_advanced_settings,
|
| 339 |
+
# inputs=[advanced_settings_visible],
|
| 340 |
+
# outputs=[advanced_block, advanced_settings_visible]
|
| 341 |
+
# )
|
| 342 |
+
|
| 343 |
+
# Формат занятия - видимость поля если выбрано групповое
|
| 344 |
+
def toggle_format(selected_format):
|
| 345 |
+
return gr.update(visible=selected_format == "Групповое")
|
| 346 |
+
format_type.change(fn=toggle_format, inputs=format_type, outputs=group_settings)
|
| 347 |
+
|
| 348 |
+
# Возраст - деактивация поля если нажато "Взрослые"
|
| 349 |
+
def toggle_age(adult_checked):
|
| 350 |
+
return gr.update(interactive=not adult_checked)
|
| 351 |
+
adults.change(fn=toggle_age, inputs=adults, outputs=age)
|
| 352 |
+
|
| 353 |
+
# Функция для переключения видимости Target language
|
| 354 |
+
def toggle_target_language(methodology_value):
|
| 355 |
+
return gr.update(visible=methodology_value == "PPP (Presentation-Practice-Production)")
|
| 356 |
+
methodology.change(fn=toggle_target_language, inputs=methodology, outputs=target_language)
|
| 357 |
+
|
| 358 |
+
# JS для автодополнения
|
| 359 |
+
app.load(
|
| 360 |
+
None,
|
| 361 |
+
None,
|
| 362 |
+
js=f"""
|
| 363 |
+
const textbooks = {TEXTBOOKS};
|
| 364 |
+
|
| 365 |
+
function setupAutocomplete() {{
|
| 366 |
+
const input = document.getElementById('textbook_input');
|
| 367 |
+
if (!input) return;
|
| 368 |
+
|
| 369 |
+
const datalist = document.createElement('datalist');
|
| 370 |
+
datalist.id = 'textbook_suggestions';
|
| 371 |
+
|
| 372 |
+
textbooks.forEach(book => {{
|
| 373 |
+
const option = document.createElement('option');
|
| 374 |
+
option.value = book;
|
| 375 |
+
datalist.appendChild(option);
|
| 376 |
+
}});
|
| 377 |
+
|
| 378 |
+
input.setAttribute('list', datalist.id);
|
| 379 |
+
document.body.appendChild(datalist);
|
| 380 |
+
}}
|
| 381 |
+
|
| 382 |
+
// Запускаем после загрузки
|
| 383 |
+
if (document.readyState === 'complete') {{
|
| 384 |
+
setupAutocomplete();
|
| 385 |
+
}} else {{
|
| 386 |
+
document.addEventListener('DOMContentLoaded', setupAutocomplete);
|
| 387 |
+
}}
|
| 388 |
+
"""
|
| 389 |
+
)
|
| 390 |
+
### СПИСОК ВСЕХ ПАРАМЕТРОВ ИНТЕРФЕЙСА
|
| 391 |
+
all_inputs = [
|
| 392 |
+
image, # Gradio компонент, соответствует image_path в функциях
|
| 393 |
+
textbook,
|
| 394 |
+
cefr,
|
| 395 |
+
topic,
|
| 396 |
+
goal,
|
| 397 |
+
format_type,
|
| 398 |
+
num_students,
|
| 399 |
+
age,
|
| 400 |
+
adults,
|
| 401 |
+
level_match,
|
| 402 |
+
duration,
|
| 403 |
+
inventory,
|
| 404 |
+
extra_info,
|
| 405 |
+
methodology,
|
| 406 |
+
target_language,
|
| 407 |
+
hw_required,
|
| 408 |
+
web_search
|
| 409 |
+
# repetition,
|
| 410 |
+
# application,
|
| 411 |
+
# analysis,
|
| 412 |
+
# creativity
|
| 413 |
+
]
|
| 414 |
+
|
| 415 |
+
# Коллбек генерации
|
| 416 |
+
def on_generate(
|
| 417 |
+
image_path: Optional[str], # Переименовано из image
|
| 418 |
+
textbook: str,
|
| 419 |
+
cefr: str,
|
| 420 |
+
topic: str,
|
| 421 |
+
goal: str,
|
| 422 |
+
format_type: str,
|
| 423 |
+
num_students: int,
|
| 424 |
+
age: str,
|
| 425 |
+
adults: bool,
|
| 426 |
+
level_match: int,
|
| 427 |
+
duration: int,
|
| 428 |
+
inventory: str,
|
| 429 |
+
extra_info: str,
|
| 430 |
+
methodology: str,
|
| 431 |
+
target_language: str,
|
| 432 |
+
hw_required: bool,
|
| 433 |
+
web_search: bool
|
| 434 |
+
# repetition: bool,
|
| 435 |
+
# application: bool,
|
| 436 |
+
# analysis: bool,
|
| 437 |
+
# creativity: bool
|
| 438 |
+
):
|
| 439 |
+
# Проверка обязательных полей
|
| 440 |
+
if not image_path or (not adults and not age):
|
| 441 |
+
return gr.update(value="❗ Заполните обязательные поля (отмечены *)"), gr.update(visible=False)
|
| 442 |
+
|
| 443 |
+
# Собираем все аргументы в словарь
|
| 444 |
+
kwargs = locals()
|
| 445 |
+
|
| 446 |
+
# Генерация плана
|
| 447 |
+
text = generate_lesson_plan(**kwargs)
|
| 448 |
+
|
| 449 |
+
# Создание DOCX
|
| 450 |
+
docx_path = generate_docx(text) if not text.startswith("❗") else None
|
| 451 |
+
return gr.update(value=text), gr.update(visible=bool(docx_path), value=docx_path)
|
| 452 |
+
|
| 453 |
+
btn.click(
|
| 454 |
+
fn=on_generate,
|
| 455 |
+
inputs=all_inputs,
|
| 456 |
+
outputs=[output, download_btn]
|
| 457 |
+
)
|
| 458 |
+
|
| 459 |
+
# Логика: показать форму по нажатию на кнопку
|
| 460 |
+
feedback_btn.click(
|
| 461 |
+
fn=toggle_feedback_block,
|
| 462 |
+
inputs=[feedback_visible],
|
| 463 |
+
outputs=[feedback_block, feedback_visible, feedback_confirmation]
|
| 464 |
+
)
|
| 465 |
+
|
| 466 |
+
# Логика отправки обратной связи
|
| 467 |
+
def send_feedback_fn(comment, rate):
|
| 468 |
+
save_feedback(comment, rate) # Сохраняем отзыв
|
| 469 |
+
return (
|
| 470 |
+
gr.update(visible=False), # свернуть форму
|
| 471 |
+
False, # сбросить состояние
|
| 472 |
+
gr.update(
|
| 473 |
+
value="✅ Спасибо! Ваш комментарий передан, и, возможно, уже сегодня ассистент станет полезнее :)",
|
| 474 |
+
visible=True
|
| 475 |
+
)
|
| 476 |
+
)
|
| 477 |
+
|
| 478 |
+
send_feedback.click(
|
| 479 |
+
fn=send_feedback_fn,
|
| 480 |
+
inputs=[feedback_text, rating],
|
| 481 |
+
outputs=[feedback_block, feedback_visible, feedback_confirmation]
|
| 482 |
+
)
|
| 483 |
+
|
| 484 |
+
|
| 485 |
+
if __name__ == "__main__":
|
| 486 |
+
app.launch()
|
app/test_gradio_test.py
ADDED
|
@@ -0,0 +1,527 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import os
|
| 2 |
+
import logging
|
| 3 |
+
import tempfile
|
| 4 |
+
from datetime import datetime
|
| 5 |
+
from dotenv import load_dotenv
|
| 6 |
+
from openai import OpenAI
|
| 7 |
+
import gradio as gr
|
| 8 |
+
from docx import Document
|
| 9 |
+
import requests
|
| 10 |
+
from typing import Optional
|
| 11 |
+
|
| 12 |
+
import random
|
| 13 |
+
from app.quotes import quotes
|
| 14 |
+
from app.drawings import drawings
|
| 15 |
+
from app.knowledge_base.textbooks import TEXTBOOKS
|
| 16 |
+
# --- Настройка ---
|
| 17 |
+
logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s')
|
| 18 |
+
load_dotenv()
|
| 19 |
+
api_key = os.getenv("API_KEY_openai")
|
| 20 |
+
client = OpenAI(api_key=api_key) if api_key else None
|
| 21 |
+
VS_ID = os.getenv("VECTOR_STORE_ID", "") # vector store for file_search if needed
|
| 22 |
+
|
| 23 |
+
# --- Утилиты ---
|
| 24 |
+
def upload_to_catbox(file_bytes: bytes) -> str:
|
| 25 |
+
"""Загружает файл на catbox.moe и возвращает URL"""
|
| 26 |
+
try:
|
| 27 |
+
response = requests.post(
|
| 28 |
+
"https://catbox.moe/user/api.php",
|
| 29 |
+
files={"fileToUpload": file_bytes},
|
| 30 |
+
data={"reqtype": "fileupload"},
|
| 31 |
+
timeout=10
|
| 32 |
+
)
|
| 33 |
+
response.raise_for_status()
|
| 34 |
+
return response.text.strip()
|
| 35 |
+
except Exception as e:
|
| 36 |
+
logging.error(f"Ошибка загрузки изображения: {e}")
|
| 37 |
+
raise gr.Error("Не удалось загрузить изображение")
|
| 38 |
+
|
| 39 |
+
|
| 40 |
+
def generate_docx(text: str) -> str:
|
| 41 |
+
"""Сохраняет текст в .docx и возвращает путь"""
|
| 42 |
+
doc = Document()
|
| 43 |
+
for line in text.split("\n"):
|
| 44 |
+
doc.add_paragraph(line)
|
| 45 |
+
tmp = tempfile.gettempdir()
|
| 46 |
+
path = os.path.join(tmp, f"lesson_plan_{datetime.now().strftime('%Y%m%d%H%M%S')}.docx")
|
| 47 |
+
doc.save(path)
|
| 48 |
+
return path
|
| 49 |
+
|
| 50 |
+
# названия textbooks для автозаполнения поля Учебник
|
| 51 |
+
import json
|
| 52 |
+
|
| 53 |
+
## Сохраняем отзыв через POST в google-таблицу
|
| 54 |
+
GOOGLE_SHEET_URL = os.getenv("FEEDBACK_GS_URL")
|
| 55 |
+
|
| 56 |
+
def save_feedback(comment, rate):
|
| 57 |
+
payload = {
|
| 58 |
+
"comment": comment,
|
| 59 |
+
"rate": rate
|
| 60 |
+
}
|
| 61 |
+
try:
|
| 62 |
+
requests.post(GOOGLE_SHEET_URL, json=payload, timeout=3)
|
| 63 |
+
except Exception as e:
|
| 64 |
+
print(f"Ошибка при отправке отзыва: {e}")
|
| 65 |
+
|
| 66 |
+
### ОСНОВНАЯ ФУНКЦИЯ ГЕНЕРАЦИИ
|
| 67 |
+
def generate_lesson_plan(
|
| 68 |
+
main_image_path: Optional[str],
|
| 69 |
+
extra_images: Optional[list[str]],
|
| 70 |
+
textbook: str,
|
| 71 |
+
cefr: str,
|
| 72 |
+
topic: str,
|
| 73 |
+
goal: str,
|
| 74 |
+
format_type: str,
|
| 75 |
+
num_students: int,
|
| 76 |
+
age: str,
|
| 77 |
+
adults: bool,
|
| 78 |
+
level_match: int,
|
| 79 |
+
duration: int,
|
| 80 |
+
inventory: str,
|
| 81 |
+
extra_info: str,
|
| 82 |
+
methodology: str,
|
| 83 |
+
target_language: str,
|
| 84 |
+
hw_required: bool,
|
| 85 |
+
web_search: bool
|
| 86 |
+
# repetition: bool,
|
| 87 |
+
# application: bool,
|
| 88 |
+
# analysis: bool,
|
| 89 |
+
# creativity: bool
|
| 90 |
+
) -> str:
|
| 91 |
+
|
| 92 |
+
# Валидация
|
| 93 |
+
if not main_image_path:
|
| 94 |
+
return "❗ Загрузите хотя бы главную страницу"
|
| 95 |
+
|
| 96 |
+
# Собираем все пути изображений
|
| 97 |
+
image_paths = [main_image_path]
|
| 98 |
+
if extra_images:
|
| 99 |
+
if len(extra_images) > 2:
|
| 100 |
+
return "❗ Максимум 2 дополнительные страницы"
|
| 101 |
+
image_paths.extend(extra_images)
|
| 102 |
+
|
| 103 |
+
# Валидация API клиента
|
| 104 |
+
if not client:
|
| 105 |
+
raise gr.Error("API ключ не настроен")
|
| 106 |
+
# Проверка наличия изображения
|
| 107 |
+
if not image_path:
|
| 108 |
+
return "❗ Загрузите фото страницы учебника для генерации урока"
|
| 109 |
+
|
| 110 |
+
# Загружаем изображение и получаем URL
|
| 111 |
+
try:
|
| 112 |
+
with open(image_path, "rb") as f:
|
| 113 |
+
image_url = upload_to_catbox(f.read())
|
| 114 |
+
except Exception as e:
|
| 115 |
+
logging.error(f"Image upload error: {e}")
|
| 116 |
+
raise gr.Error("Не удалось загрузить изображение")
|
| 117 |
+
|
| 118 |
+
# Собираем текстовый prompt
|
| 119 |
+
lesson_params = {
|
| 120 |
+
'methodology': methodology,
|
| 121 |
+
'target_language': target_language, # для PPP
|
| 122 |
+
'textbook': textbook,
|
| 123 |
+
'cefr': cefr,
|
| 124 |
+
'topic': topic,
|
| 125 |
+
'goal': goal,
|
| 126 |
+
'num_students': num_students,
|
| 127 |
+
'age': 'Взрослые' if adults else age,
|
| 128 |
+
'level_match': level_match,
|
| 129 |
+
'duration': duration,
|
| 130 |
+
'inventory': inventory,
|
| 131 |
+
'hw_required': hw_required,
|
| 132 |
+
'extra_info': extra_info
|
| 133 |
+
}
|
| 134 |
+
|
| 135 |
+
# Получаем готовый промпт
|
| 136 |
+
from app.prompt_builder.prompt import build_prompt
|
| 137 |
+
full_prompt = build_prompt(lesson_params)
|
| 138 |
+
|
| 139 |
+
# Собираем входные данные согласно API
|
| 140 |
+
input_content = [
|
| 141 |
+
{
|
| 142 |
+
"type": "input_text",
|
| 143 |
+
"text": full_prompt
|
| 144 |
+
},
|
| 145 |
+
{
|
| 146 |
+
"type": "input_image",
|
| 147 |
+
"image_url": image_url,
|
| 148 |
+
"detail": "high"
|
| 149 |
+
}
|
| 150 |
+
]
|
| 151 |
+
|
| 152 |
+
# Опции инстр��ментов
|
| 153 |
+
tools = []
|
| 154 |
+
tool_choice = None
|
| 155 |
+
if web_search:
|
| 156 |
+
tools.append({
|
| 157 |
+
"type": "web_search_preview",
|
| 158 |
+
"search_context_size": "medium",
|
| 159 |
+
"user_location": {"type": "approximate", "country": "RU"}
|
| 160 |
+
})
|
| 161 |
+
tool_choice = {"type": "web_search_preview"}
|
| 162 |
+
|
| 163 |
+
# Вызов LLM
|
| 164 |
+
try:
|
| 165 |
+
response = client.responses.create(
|
| 166 |
+
input=[{"role": "user", "content": input_content}],
|
| 167 |
+
model="o4-mini", # gpt-4o-mini gpt-4.1
|
| 168 |
+
tools=tools or None,
|
| 169 |
+
tool_choice=tool_choice,
|
| 170 |
+
max_output_tokens=8192,
|
| 171 |
+
reasoning= {"effort":"medium"},
|
| 172 |
+
stream=False
|
| 173 |
+
)
|
| 174 |
+
return response.output_text
|
| 175 |
+
|
| 176 |
+
except Exception as e:
|
| 177 |
+
logging.error(f"Generation error: {e}")
|
| 178 |
+
raise gr.Error(f"Ошибка генерации: {e}")
|
| 179 |
+
|
| 180 |
+
|
| 181 |
+
|
| 182 |
+
########## ИНТЕРФЕЙС
|
| 183 |
+
# Случайный рисунок в блокноте
|
| 184 |
+
drawing = random.choice(drawings)
|
| 185 |
+
# Текст с подсказкой и рисунком в блокноте
|
| 186 |
+
hint_text = f"""Здесь появится план занятия — заполните вводные и нажмите кнопку **Создать план**<br>
|
| 187 |
+
Создание может занять до 1 минуты
|
| 188 |
+
<pre>
|
| 189 |
+
{drawing}
|
| 190 |
+
</pre>
|
| 191 |
+
"""
|
| 192 |
+
|
| 193 |
+
#ТЕМА И СТИЛИ
|
| 194 |
+
### css привязывать именно так
|
| 195 |
+
#theme='earneleh/paris'
|
| 196 |
+
theme = gr.themes.Base(
|
| 197 |
+
secondary_hue="rose",
|
| 198 |
+
neutral_hue="stone",
|
| 199 |
+
).set(
|
| 200 |
+
body_background_fill='*primary_50',
|
| 201 |
+
body_text_color='*primary_900',
|
| 202 |
+
body_text_size='*text_lg',
|
| 203 |
+
body_text_color_subdued='*primary_700',
|
| 204 |
+
body_text_weight='600',
|
| 205 |
+
)
|
| 206 |
+
css_path = os.path.join(os.path.dirname(__file__), "styles.css")
|
| 207 |
+
|
| 208 |
+
# ИНТЕРФЕЙС
|
| 209 |
+
with gr.Blocks(theme=theme, css_paths=css_path) as app:
|
| 210 |
+
advanced_settings_visible = gr.State(value=False) # Импортируем gr.State для хранения состояния
|
| 211 |
+
feedback_visible = gr.State(False) # Хранит, открыт ли блок отзыва
|
| 212 |
+
|
| 213 |
+
gr.Markdown("# План урока английского языка", elem_classes=["main-title"])
|
| 214 |
+
quote_box = gr.Markdown(random.choice(quotes), elem_classes=["quote-block"])
|
| 215 |
+
with gr.Row():
|
| 216 |
+
with gr.Column(variant="panel"):
|
| 217 |
+
# Основной загрузчик (с камерой)
|
| 218 |
+
main_image = gr.Image(
|
| 219 |
+
label="Главная страница учебника*",
|
| 220 |
+
type="filepath",
|
| 221 |
+
source="upload", # разрешаем и загрузку, и камеру
|
| 222 |
+
tool=None, # или "editor" если нужно редактирование
|
| 223 |
+
height=300
|
| 224 |
+
)
|
| 225 |
+
|
| 226 |
+
# Дополнительные страницы (до 2х)
|
| 227 |
+
extra_images = gr.File(
|
| 228 |
+
label="Дополнительные страницы (макс. 2)",
|
| 229 |
+
file_types=["image"],
|
| 230 |
+
file_count="multiple",
|
| 231 |
+
height=100,
|
| 232 |
+
visible=False # по умолчанию скрыт
|
| 233 |
+
)
|
| 234 |
+
|
| 235 |
+
# Переключатель
|
| 236 |
+
show_extra = gr.Checkbox(
|
| 237 |
+
label="Добавить страницы (разворот)",
|
| 238 |
+
value=False
|
| 239 |
+
)
|
| 240 |
+
|
| 241 |
+
# Блок 1: Учебник
|
| 242 |
+
with gr.Column(variant="panel"):
|
| 243 |
+
gr.Markdown("### 📚 Учебник", elem_classes=["block-title"])
|
| 244 |
+
textbook = gr.Textbox(label="Название учебника", placeholder="напр. English File Beginner", elem_id="textbook_input")
|
| 245 |
+
|
| 246 |
+
cefr = gr.Dropdown(label="Уровень", choices=["", "A1", "A2", "B1", "B2", "C1", "C2"],
|
| 247 |
+
value="", info="Выберите уровень")
|
| 248 |
+
# Блок 2: Класс
|
| 249 |
+
with gr.Column(variant="panel"):
|
| 250 |
+
gr.Markdown("### 👥 Класс", elem_classes=["block-title"])
|
| 251 |
+
format_type = gr.Radio(label="Формат занятия", choices=["Индивидуальное", "Групповое"],
|
| 252 |
+
value="Групповое")
|
| 253 |
+
|
| 254 |
+
with gr.Group(visible=True) as group_settings:
|
| 255 |
+
num_students = gr.Slider(label="Количество учеников", minimum=1, maximum=40,
|
| 256 |
+
value=10, step=1, info="Для групповых занятий")
|
| 257 |
+
|
| 258 |
+
with gr.Group() as age_group:
|
| 259 |
+
age = gr.Textbox(label="Возраст", placeholder="напр. 10–11", interactive=True)
|
| 260 |
+
adults = gr.Checkbox(label="Взрослые")
|
| 261 |
+
|
| 262 |
+
level_match = gr.Dropdown(label = "Уровень учеников относительно учебника",
|
| 263 |
+
choices = ["ниже", "на уровне", "выше", "mixed"], value = "на уровне")
|
| 264 |
+
|
| 265 |
+
# Блок 3: ��анятие
|
| 266 |
+
with gr.Column(variant="panel"):
|
| 267 |
+
gr.Markdown("### 📄 Занятие", elem_classes=["block-title"])
|
| 268 |
+
topic = gr.Textbox(label="Тема", placeholder="напр. Daily routines")
|
| 269 |
+
goal = gr.Textbox(label="Цель", placeholder="К концу урока ученики смогут...")
|
| 270 |
+
duration = gr.Slider(label="Длительность (мин)", minimum=30, maximum=180, value=60, step=5)
|
| 271 |
+
inventory = gr.Textbox(label="Инвентарь", placeholder="по умолчанию - доска и проектор")
|
| 272 |
+
extra_info = gr.Textbox(label="Допонительная информация", placeholder="Класс весёлый и взвинченный после физкультуры")
|
| 273 |
+
|
| 274 |
+
# Блок 4: Методика
|
| 275 |
+
with gr.Column(variant="panel"):
|
| 276 |
+
gr.Markdown("### 🎓 Методика", elem_classes=["block-title"])
|
| 277 |
+
methodology = gr.Dropdown(label="Методика преподавания",
|
| 278 |
+
choices=["PPP (Presentation-Practice-Production)",
|
| 279 |
+
"TTT (Test-Teach-Test)"],
|
| 280 |
+
value="PPP (Presentation-Practice-Production)")
|
| 281 |
+
target_language = gr.Textbox(
|
| 282 |
+
label="Target language",
|
| 283 |
+
placeholder="Например: 'I have been to...' 'How long have you...?' (Present Perfect experience)",
|
| 284 |
+
visible=True # По умолчанию видно, так как PPP выбран
|
| 285 |
+
)
|
| 286 |
+
|
| 287 |
+
# advanced_btn = gr.Button(value="➕ Продвинутые настройки (в разработке", size="sm")
|
| 288 |
+
#
|
| 289 |
+
# # Блок продвинутых настроек, изначально скрыт
|
| 290 |
+
# with gr.Column(visible=False) as advanced_block:
|
| 291 |
+
# gr.Markdown("**💡 Уровни задач (таксономия):**")
|
| 292 |
+
# repetition = gr.Checkbox(label="Повторение")
|
| 293 |
+
# application = gr.Checkbox(label="Применение")
|
| 294 |
+
# analysis = gr.Checkbox(label="Анализ")
|
| 295 |
+
# creativity = gr.Checkbox(label="Творчество")
|
| 296 |
+
|
| 297 |
+
hw_required = gr.Checkbox(label="Домашнее задание")
|
| 298 |
+
web_search = gr.Checkbox(label="Доп. материалы из интернета")
|
| 299 |
+
|
| 300 |
+
btn = gr.Button("Создать план", variant="primary", size="lg")
|
| 301 |
+
|
| 302 |
+
# Правая колонка — результат (output)
|
| 303 |
+
with gr.Column(elem_classes=["right-col"], scale=2):
|
| 304 |
+
# Общий блок-панель для правой колонки
|
| 305 |
+
with gr.Column(variant="panel"): # <<< Главная панель
|
| 306 |
+
gr.Markdown("### План урока", elem_classes=["block-title"]) # Заголовок ВНУТРИ панели
|
| 307 |
+
# Блок с выводом плана
|
| 308 |
+
output = gr.Markdown(
|
| 309 |
+
hint_text,
|
| 310 |
+
elem_id="plan-output"
|
| 311 |
+
)
|
| 312 |
+
# Кнопка скачивания (оставляем внутри панели)
|
| 313 |
+
download_btn = gr.DownloadButton(
|
| 314 |
+
label="⬇️ Скачать .docx",
|
| 315 |
+
visible=False
|
| 316 |
+
)
|
| 317 |
+
# Кнопка "Помогите нам стать лучше"
|
| 318 |
+
feedback_btn = gr.Button("💬 Помогите нам стать лучше", elem_classes=["feedback-button"])
|
| 319 |
+
|
| 320 |
+
# Скрытый блок с обратной связью
|
| 321 |
+
with gr.Column(visible=False) as feedback_block:
|
| 322 |
+
gr.Markdown("_Спасибо, что попробовали! Как вам?_\n_Ваши наблюдения и замечания помогают нам расти._")
|
| 323 |
+
|
| 324 |
+
|
| 325 |
+
def toggle_feedback_block(current_visible):
|
| 326 |
+
return (
|
| 327 |
+
gr.update(visible=not current_visible), # показать/скрыть блок
|
| 328 |
+
not current_visible, # обновить состояние
|
| 329 |
+
gr.update(visible=False) # скрыть благодарность при открытии/закрытии
|
| 330 |
+
)
|
| 331 |
+
feedback_text = gr.Textbox(
|
| 332 |
+
label="Ваше наблюдение или комментарий",
|
| 333 |
+
placeholder="Например: 'Для 3 лет лексика подбирается неправильно — какая там 'машина', максимум - 'би-би'",
|
| 334 |
+
lines=4
|
| 335 |
+
)
|
| 336 |
+
|
| 337 |
+
rating = gr.Radio(
|
| 338 |
+
choices=["1", "2", "3", "4", "5"],
|
| 339 |
+
label="Оценка"
|
| 340 |
+
)
|
| 341 |
+
|
| 342 |
+
send_feedback = gr.Button("📩 Отправить отзыв")
|
| 343 |
+
|
| 344 |
+
feedback_confirmation = gr.Markdown(
|
| 345 |
+
visible=False,
|
| 346 |
+
elem_classes=["feedback-confirmation"]
|
| 347 |
+
)
|
| 348 |
+
|
| 349 |
+
# <-- Блок благодарности — ВНЕ feedback_block, но СРАЗУ ПОСЛЕ
|
| 350 |
+
with gr.Column(visible=False) as feedback_confirmation:
|
| 351 |
+
gr.Markdown("✅ Спасибо! Ваш комментарий передан и, возможно, уже сегодня ассистент станет полезнее :)")
|
| 352 |
+
|
| 353 |
+
# Остальное
|
| 354 |
+
gr.Markdown(
|
| 355 |
+
"""
|
| 356 |
+
🙌 Если вас заинтересовал проект, мы приглашаем
|
| 357 |
+
👉 [присоединиться к Telegram-группе](https://t.me/+yN9BSJ1DJxxjZmJi)
|
| 358 |
+
"""
|
| 359 |
+
)
|
| 360 |
+
|
| 361 |
+
### --- Логика интерфейса ---
|
| 362 |
+
|
| 363 |
+
# Показываем/скрываем блок загрузки доп. изображений
|
| 364 |
+
def toggle_extra_images(show: bool):
|
| 365 |
+
return gr.update(visible=show)
|
| 366 |
+
|
| 367 |
+
|
| 368 |
+
show_extra.change(
|
| 369 |
+
fn=toggle_extra_images,
|
| 370 |
+
inputs=show_extra,
|
| 371 |
+
outputs=extra_images
|
| 372 |
+
)
|
| 373 |
+
|
| 374 |
+
## Доп. настройки
|
| 375 |
+
# def toggle_advanced_settings(visible):
|
| 376 |
+
# return gr.update(visible=not visible), not visible
|
| 377 |
+
|
| 378 |
+
# advanced_btn.click(
|
| 379 |
+
# fn=toggle_advanced_settings,
|
| 380 |
+
# inputs=[advanced_settings_visible],
|
| 381 |
+
# outputs=[advanced_block, advanced_settings_visible]
|
| 382 |
+
# )
|
| 383 |
+
|
| 384 |
+
# Формат занятия - видимость поля если выбрано групповое
|
| 385 |
+
def toggle_format(selected_format):
|
| 386 |
+
return gr.update(visible=selected_format == "Групповое")
|
| 387 |
+
format_type.change(fn=toggle_format, inputs=format_type, outputs=group_settings)
|
| 388 |
+
|
| 389 |
+
# Возраст - деактивация поля если нажато "Взрослые"
|
| 390 |
+
def toggle_age(adult_checked):
|
| 391 |
+
return gr.update(interactive=not adult_checked)
|
| 392 |
+
adults.change(fn=toggle_age, inputs=adults, outputs=age)
|
| 393 |
+
|
| 394 |
+
# Функция для переключения видимости Target language
|
| 395 |
+
def toggle_target_language(methodology_value):
|
| 396 |
+
return gr.update(visible=methodology_value == "PPP (Presentation-Practice-Production)")
|
| 397 |
+
methodology.change(fn=toggle_target_language, inputs=methodology, outputs=target_language)
|
| 398 |
+
|
| 399 |
+
# JS для автодополнения
|
| 400 |
+
app.load(
|
| 401 |
+
None,
|
| 402 |
+
None,
|
| 403 |
+
js=f"""
|
| 404 |
+
const textbooks = {TEXTBOOKS};
|
| 405 |
+
|
| 406 |
+
function setupAutocomplete() {{
|
| 407 |
+
const input = document.getElementById('textbook_input');
|
| 408 |
+
if (!input) return;
|
| 409 |
+
|
| 410 |
+
const datalist = document.createElement('datalist');
|
| 411 |
+
datalist.id = 'textbook_suggestions';
|
| 412 |
+
|
| 413 |
+
textbooks.forEach(book => {{
|
| 414 |
+
const option = document.createElement('option');
|
| 415 |
+
option.value = book;
|
| 416 |
+
datalist.appendChild(option);
|
| 417 |
+
}});
|
| 418 |
+
|
| 419 |
+
input.setAttribute('list', datalist.id);
|
| 420 |
+
document.body.appendChild(datalist);
|
| 421 |
+
}}
|
| 422 |
+
|
| 423 |
+
// Запускаем после загрузки
|
| 424 |
+
if (document.readyState === 'complete') {{
|
| 425 |
+
setupAutocomplete();
|
| 426 |
+
}} else {{
|
| 427 |
+
document.addEventListener('DOMContentLoaded', setupAutocomplete);
|
| 428 |
+
}}
|
| 429 |
+
"""
|
| 430 |
+
)
|
| 431 |
+
### СПИСОК ВСЕХ ПАРАМЕТРОВ ИНТЕРФЕЙСА
|
| 432 |
+
all_inputs = [
|
| 433 |
+
image, # Gradio компонент, соответствует image_path в функциях
|
| 434 |
+
textbook,
|
| 435 |
+
cefr,
|
| 436 |
+
topic,
|
| 437 |
+
goal,
|
| 438 |
+
format_type,
|
| 439 |
+
num_students,
|
| 440 |
+
age,
|
| 441 |
+
adults,
|
| 442 |
+
level_match,
|
| 443 |
+
duration,
|
| 444 |
+
inventory,
|
| 445 |
+
extra_info,
|
| 446 |
+
methodology,
|
| 447 |
+
target_language,
|
| 448 |
+
hw_required,
|
| 449 |
+
web_search
|
| 450 |
+
# repetition,
|
| 451 |
+
# application,
|
| 452 |
+
# analysis,
|
| 453 |
+
# creativity
|
| 454 |
+
]
|
| 455 |
+
|
| 456 |
+
# Коллбек генерации
|
| 457 |
+
def on_generate(
|
| 458 |
+
image_path: Optional[str], # Переименовано из image
|
| 459 |
+
textbook: str,
|
| 460 |
+
cefr: str,
|
| 461 |
+
topic: str,
|
| 462 |
+
goal: str,
|
| 463 |
+
format_type: str,
|
| 464 |
+
num_students: int,
|
| 465 |
+
age: str,
|
| 466 |
+
adults: bool,
|
| 467 |
+
level_match: int,
|
| 468 |
+
duration: int,
|
| 469 |
+
inventory: str,
|
| 470 |
+
extra_info: str,
|
| 471 |
+
methodology: str,
|
| 472 |
+
target_language: str,
|
| 473 |
+
hw_required: bool,
|
| 474 |
+
web_search: bool
|
| 475 |
+
# repetition: bool,
|
| 476 |
+
# application: bool,
|
| 477 |
+
# analysis: bool,
|
| 478 |
+
# creativity: bool
|
| 479 |
+
):
|
| 480 |
+
# Проверка обязательных полей
|
| 481 |
+
if not image_path or (not adults and not age):
|
| 482 |
+
return gr.update(value="❗ Заполните обязательные поля (отмечены *)"), gr.update(visible=False)
|
| 483 |
+
|
| 484 |
+
# Собираем все аргументы в словарь
|
| 485 |
+
kwargs = locals()
|
| 486 |
+
|
| 487 |
+
# Генерация плана
|
| 488 |
+
text = generate_lesson_plan(**kwargs)
|
| 489 |
+
|
| 490 |
+
# Создание DOCX
|
| 491 |
+
docx_path = generate_docx(text) if not text.startswith("❗") else None
|
| 492 |
+
return gr.update(value=text), gr.update(visible=bool(docx_path), value=docx_path)
|
| 493 |
+
|
| 494 |
+
btn.click(
|
| 495 |
+
fn=on_generate,
|
| 496 |
+
inputs=[main_image, extra_images, all_inputs],
|
| 497 |
+
outputs=[output, download_btn]
|
| 498 |
+
)
|
| 499 |
+
|
| 500 |
+
# Логика: показать форму по нажатию на кнопку
|
| 501 |
+
feedback_btn.click(
|
| 502 |
+
fn=toggle_feedback_block,
|
| 503 |
+
inputs=[feedback_visible],
|
| 504 |
+
outputs=[feedback_block, feedback_visible, feedback_confirmation]
|
| 505 |
+
)
|
| 506 |
+
|
| 507 |
+
# Логика отправки обратной связи
|
| 508 |
+
def send_feedback_fn(comment, rate):
|
| 509 |
+
save_feedback(comment, rate) # Сохраняем отзыв
|
| 510 |
+
return (
|
| 511 |
+
gr.update(visible=False), # свернуть форму
|
| 512 |
+
False, # сбросить состояние
|
| 513 |
+
gr.update(
|
| 514 |
+
value="✅ Спасибо! Ваш комментарий передан, и, возможно, уже сегодня ассистент станет полезнее :)",
|
| 515 |
+
visible=True
|
| 516 |
+
)
|
| 517 |
+
)
|
| 518 |
+
|
| 519 |
+
send_feedback.click(
|
| 520 |
+
fn=send_feedback_fn,
|
| 521 |
+
inputs=[feedback_text, rating],
|
| 522 |
+
outputs=[feedback_block, feedback_visible, feedback_confirmation]
|
| 523 |
+
)
|
| 524 |
+
|
| 525 |
+
|
| 526 |
+
if __name__ == "__main__":
|
| 527 |
+
app.launch()
|
docs/architecture.md
CHANGED
|
@@ -1,3 +1,55 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
мне нужно сделать простое приложение по генерации планов уроков на базе предоставленной фотографии страницы учебника.
|
| 2 |
Для интерфейса используем streamlit. Логика такая - экран делится не левую и правую части. В левой части область загрузки
|
| 3 |
фотографии страницы учебника + поля заполнения и настройки (они появляются после успешной загрузки).
|
|
@@ -16,6 +68,15 @@
|
|
| 16 |
Длительное хранение загруженных изображений не требуется, поэтому решение tmpfiles.org подходит.
|
| 17 |
|
| 18 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 19 |
Structured Outputs через response_format с JSON Schema , так как:
|
| 20 |
|
| 21 |
|
|
|
|
| 1 |
+
Я разрабатываю AI-ассистента для учителей английского. Туда загружаешь фото страниц учебника, а также задаешь параметры.
|
| 2 |
+
На выходе получаешь план урока. Фото считывается через vision. Везде используется API openai, эндпоинт responses (2025 год,
|
| 3 |
+
это самый актуальный эндпоинт). Интерфейс реализуется на Gradio. Vision работает через загрузку в него временного url
|
| 4 |
+
изображения страницы учебника. Блоки параметров: 1) Занятия - тема, основная цель, название учебника, уровень учебника
|
| 5 |
+
(по CEFR, выпадающий список) 2) Методика (выпадающий список, там PPP, TTT и другие актуальные подходы и методики ESL - 5 разных).
|
| 6 |
+
Занятие: кол-во учеников (ползунок от 2 до 40 и чекбокс "индивидуальное занятие", нажатие которого деактивирует ползунок),
|
| 7 |
+
время занятия (ползунок от 20 до 120 минут), возраст (свободное поле с placeholder "напр. 10-11", и чекбокс "врослые",
|
| 8 |
+
нажатие которого деактивирует свободное поле с возрастом), соответствие класса уровню - ползунок с 3 позициями mixed ability
|
| 9 |
+
(предложи варианты, ведь бывает что учебник ниже уровня большинства, бывает наоборот ниже, бывает что в примерно в уровень,
|
| 10 |
+
бывает полный mixed ability). Дальше - ччекбокс наличия домашнего задания, под ним - чекбокс доп. материалов из интернета.
|
| 11 |
+
Обязательные поля должны быть заполнены для активации генерции, иначе при нажатии кнопки создания урока на месте плана урока
|
| 12 |
+
возникает сообщение о необходимости заполнить обязательные поля. Оформлен интерфейс в 2 колонки - левая с настройками (1/3 ширины),
|
| 13 |
+
правая с планом урока (2/3 ширины). Я тебе вышлю имеющуюся у меня заготовку - здесь корректна инициализация клиента, правильные
|
| 14 |
+
названия эндпоинтов и моделей. Но здесь практически всё пока не то, что нужно - image_url сейчас подключается по условию, но оно
|
| 15 |
+
должно всегда попадать в LLM для генерации и другое. Прежде чем начнем писать код, проговори всё, и задай если нужно вопросы. Код не пиши.
|
| 16 |
+
|
| 17 |
+
На вопросы: 1. методики - давай пока оставим эти 2 - PPP и TTT. По умолчанию - PPP, так что поле необязательное (значение по умолчанию уже есть) 2.метки для уровня:
|
| 18 |
+
“below”, “on-level”, “above”, “mixed” 3. Да, правильно 4. Если фото не загружено - урок не генерируется (это ключевая функция ассистента - создавать урок по загруженной странице)
|
| 19 |
+
5. Формат вывода - markdown внутри правого поля внутри Gradio - ок, но docx-экспорт через кнопку должен тоже быть (так же, как в приложении из примера) 6.
|
| 20 |
+
6. Заглушка web search - она не возвращает ничего, в prompt можно ее добавить при условии нажатия чекбокса как "используется web search
|
| 21 |
+
7. (пусть модель просто видит эту строчку если чекбокс нажат, а если отжат - там ничего) 7. Достаточно слайдера, о котором говорили выше.
|
| 22 |
+
8. Что еще забыли -- параметры тема и цель занятия. Тема необязательная, цель - тоже необязательная. Все настройки делим на блоки (аналогично тому
|
| 23 |
+
9. как в приложении примере есть блоки "ребенок" и "занятие"). В начале - блок "занятие" (учебник, уровень, тема, цель"), затем - ��ласс (кол-во детей
|
| 24 |
+
10. (обязательное поле), возраст (обязательно), соответствие уровню учебника. Потом чекбоксы - наличие ДЗ и доп. материалы из интернета. Во всех полях
|
| 25 |
+
11. со свободным ответом должны быть плейсхолдеры с релевантным текстом-подсказкой
|
| 26 |
+
|
| 27 |
+
|
| 28 |
+
|
| 29 |
+
|
| 30 |
+
|
| 31 |
+
Собираем все параметры в all_inputs (это список Gradio-компонентов).
|
| 32 |
+
|
| 33 |
+
Передаём их в on_generate через inputs=all_inputs.
|
| 34 |
+
|
| 35 |
+
Внутри on_generate используем locals(), чтобы автоматически получить словарь всех аргументов.
|
| 36 |
+
|
| 37 |
+
Распаковываем их в generate_lesson_plan(**kwargs).
|
| 38 |
+
|
| 39 |
+
|
| 40 |
+
|
| 41 |
+
|
| 42 |
+
|
| 43 |
+
|
| 44 |
+
|
| 45 |
+
|
| 46 |
+
|
| 47 |
+
|
| 48 |
+
|
| 49 |
+
|
| 50 |
+
|
| 51 |
+
|
| 52 |
+
|
| 53 |
мне нужно сделать простое приложение по генерации планов уроков на базе предоставленной фотографии страницы учебника.
|
| 54 |
Для интерфейса используем streamlit. Логика такая - экран делится не левую и правую части. В левой части область загрузки
|
| 55 |
фотографии страницы учебника + поля заполнения и настройки (они появляются после успешной загрузки).
|
|
|
|
| 68 |
Длительное хранение загруженных изображений не требуется, поэтому решение tmpfiles.org подходит.
|
| 69 |
|
| 70 |
|
| 71 |
+
|
| 72 |
+
Upload Image → (if auto_detect) → Vision API → Update Textbook Field → Show Form
|
| 73 |
+
↘ (else) → Show Form Immediately
|
| 74 |
+
|
| 75 |
+
uploaded_image → upload_to_catbox() → public_url → передача в OpenAI
|
| 76 |
+
|
| 77 |
+
|
| 78 |
+
|
| 79 |
+
|
| 80 |
Structured Outputs через response_format с JSON Schema , так как:
|
| 81 |
|
| 82 |
|
docs/notes.md
ADDED
|
@@ -0,0 +1,69 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
Сложности двух аспектов:
|
| 2 |
+
Технические и архитектурные (
|
| 3 |
+
Как сделать ссылку при file search называемой и кликабельной? через временные ссылки, s3 хранилище
|
| 4 |
+
А если сделать стриминг ответа (чтобы построчно выводил), то эта логика ломается - как в этом случае добавить ссылки?
|
| 5 |
+
Как добиться от file search лучшего обобщения материала, если он заточен под retrieval? Модели с reasoning + большее значение max_num_results
|
| 6 |
+
Как деплоить MVP? Мое решение - HF Spaces + Gradio. Бесплатно, нативно, итеративно.
|
| 7 |
+
|
| 8 |
+
Как дать такой UX чтобы заинтересованные результатом пользователи перешли в телеграм-группу тестировки? Сделать кнопку отзыва и перехода в группу после того, как генерация вызвана?
|
| 9 |
+
А ведь заинтересованный пользователь захочет скачать план занятия, значит под этой кнопкой скачивания мы и добавим кнопку "помочь проекту", внутри которого - блок отзыва + переход в тг-группу
|
| 10 |
+
Результат: конверсия около 50% (количество срабатываний генерации (по логам openai / количество вступлений в тг-группу))
|
| 11 |
+
|
| 12 |
+
|
| 13 |
+
Как достать номер страницы при file search? Reasoning
|
| 14 |
+
|
| 15 |
+
Как тестировать на баги? Начни с самых нетипичных случаев поведения - они часто случатся, и ты потеряешь клиентов
|
| 16 |
+
Ты должен четко понимать ценность продукта
|
| 17 |
+
Если базовой ценности нет, то все остальное вокруг - пустая трата времени (ну или изучение новых навыков для другого проекта, имеющего ценность)
|
| 18 |
+
Ценность может быть определена только клиентом.
|
| 19 |
+
Поэтому наиболее ценный продукт - там где я и разработчик и клиент.
|
| 20 |
+
Проверим эту гипотезу на TeacherAss
|
| 21 |
+
|
| 22 |
+
|
| 23 |
+
В Конспекте Логопеда провал как раз в том, что я не смог контролировать ценность. Там нужно привлечение экспертной среды, которая будет всем - глазами, ушами, чутьем этого ассистента.
|
| 24 |
+
|
| 25 |
+
Обнаружено:
|
| 26 |
+
- Общие указания не работают. Если хочешь конкретно-заточенный воспроизводимый результат, нужно конкретно затачивать и смотреть что воспроизводится.
|
| 27 |
+
- Без экспертности (внутренней или внешней) продукт не построить
|
| 28 |
+
- ИИ напрямую не дает такую экспертность т.к. является живым носителем потребности - нужны живые люди - их боли, жалобы и прочее
|
| 29 |
+
- В проекте использовал свою боль - люблю делать хорошие уроки, всё по ESL, PPP там, TTT, через контекст, но не хватало времени.
|
| 30 |
+
Нужно чтобы кто-то очень чутко помогал мне, вдохновлял меня, чтобы я занимался не поиском материала, а творческой приятной деятельностью планирования,
|
| 31 |
+
которое и является сутью моей работы.
|
| 32 |
+
И ведь все классные методики давно известны, верно? Но их надо "прожить" через себя, впитать.
|
| 33 |
+
- А если ты начинающий, то ты можешь готовиться часами, всё выверяя. И это правильно.
|
| 34 |
+
но асситент сделает этот процесс приятным
|
| 35 |
+
|
| 36 |
+
|
| 37 |
+
|
| 38 |
+
TeacherAss:
|
| 39 |
+
Каеие методические указания дать? Насколько детально?
|
| 40 |
+
Какую методологию выбрать при каких параметрах? Например, если фокус на Reading? Vocabulary? И т.п.
|
| 41 |
+
|
| 42 |
+
|
| 43 |
+
|
| 44 |
+
-- ЛогоКонспект
|
| 45 |
+
Чего на самом деле хотят клиенты-логопеды? Им нужен рабочий конспект для каких целей? Они часто говорят что он "не по стандарту",
|
| 46 |
+
те конспекты они используют возможно для некой отчетности. Нужно четко разграничивать для чего испольщовать конспект - чтобы сделать лучше занятие или для снятия рутины с отчетности.
|
| 47 |
+
Здесь сразу разделение на государственные и частные практики.
|
| 48 |
+
|
| 49 |
+
----
|
| 50 |
+
Может быть много разных характеристик:
|
| 51 |
+
Шкала творчества урока (от сухого до безумного)
|
| 52 |
+
Шкала энергичности класса (тихий - значит надо вывести из себя/стоящий на ушах - надо успокоить)
|
| 53 |
+
Рекомендации для учителя по classroom management - Как опция
|
| 54 |
+
|
| 55 |
+
|
| 56 |
+
ИДЕИ ДЛЯ РАЗВИТИЯ:
|
| 57 |
+
* генерация частей урока - захотел переделал вступление, и каждое задание - отдельно
|
| 58 |
+
То есть сделать такой конструктор занятия. С элементами.
|
| 59 |
+
Это требует четкой полноценной базы знаний. Какая методика с каким уровнем лучше, с каким возрастом. И так далее.
|
| 60 |
+
|
| 61 |
+
* Функционал для онлайн - уроков: здесь акцент на презентации, интерактиве, электронных материалах и активностях (напр. Кахут)
|
| 62 |
+
|
| 63 |
+
Для тестирования огромное поле:
|
| 64 |
+
Какие методики лучше работают с какими параметрами - возраст, учебник (напр. можно ли выстроить PBL на материале spotlight) и т.п.
|
| 65 |
+
|
| 66 |
+
|
| 67 |
+
Чтобы разработать AI-помощника который будет методично создавать планы уроков, например, необходимо:
|
| 68 |
+
быть методистом
|
| 69 |
+
Если 1 человек объединяет эти навык, это хорошо, но команда все равно нужна по разным направлениям. И методисты, и разработчики и UX/FB
|
requirements.txt
ADDED
|
@@ -0,0 +1,8 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
python-dotenv
|
| 2 |
+
python-docx
|
| 3 |
+
openai
|
| 4 |
+
gradio
|
| 5 |
+
requests
|
| 6 |
+
pillow
|
| 7 |
+
|
| 8 |
+
|