Spaces:
Running
Running
Add lesson management functionality with JSON data integration and response models
Browse files- sessions.json +16 -1
- src/agents/lesson_practice/prompt.py +50 -57
- src/agents/role_play/__pycache__/prompt.cpython-311.pyc +0 -0
- src/agents/role_play/prompt.py +32 -13
- src/apis/models/lesson_models.py +45 -0
- src/apis/routes/lesson_route.py +119 -0
- src/data/lessons.json +140 -0
sessions.json
CHANGED
@@ -1 +1,16 @@
|
|
1 |
-
[
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
[
|
2 |
+
{
|
3 |
+
"id": "82a6779d-ad13-4edd-a046-575e563a4348",
|
4 |
+
"name": "New Conversation",
|
5 |
+
"created_at": "2025-08-21T11:57:23.992279",
|
6 |
+
"last_message": "I would like a coffee",
|
7 |
+
"message_count": 7
|
8 |
+
},
|
9 |
+
{
|
10 |
+
"id": "4fbf6c50-6054-4f3d-ac4e-d8281c306d72",
|
11 |
+
"name": "New Conversation",
|
12 |
+
"created_at": "2025-08-21T11:57:23.993885",
|
13 |
+
"last_message": null,
|
14 |
+
"message_count": 0
|
15 |
+
}
|
16 |
+
]
|
src/agents/lesson_practice/prompt.py
CHANGED
@@ -5,10 +5,10 @@ conversation_prompt = ChatPromptTemplate.from_messages(
|
|
5 |
[
|
6 |
(
|
7 |
"system",
|
8 |
-
"""# English Speaking Practice Agent
|
9 |
|
10 |
## Role & Objective
|
11 |
-
You are an experienced English teacher having
|
12 |
|
13 |
## Input Data Format
|
14 |
INSERT LESSON DATA HERE:
|
@@ -20,13 +20,13 @@ PRACTICE QUESTIONS: {practice_questions}
|
|
20 |
STUDENT LEVEL: {student_level}
|
21 |
```
|
22 |
|
23 |
-
## Core Teaching
|
24 |
|
25 |
### 1. Adaptive Question Flow
|
26 |
-
- Use
|
27 |
- Expand organically based on student's interests and responses
|
28 |
-
- Create
|
29 |
-
- Seamlessly weave in new topics when conversation naturally flows
|
30 |
|
31 |
### 2. Natural Teaching Moments
|
32 |
- Notice opportunities to teach vocabulary and patterns from the context data
|
@@ -34,85 +34,78 @@ STUDENT LEVEL: {student_level}
|
|
34 |
- Connect new concepts to what student already shared
|
35 |
- Let conversation flow naturally rather than forcing topic changes
|
36 |
|
37 |
-
### 3. Supportive Guidance
|
38 |
**Progressive teaching approach:**
|
39 |
-
-
|
40 |
-
-
|
41 |
-
-
|
42 |
-
-
|
43 |
|
44 |
### 4. Gentle Error Correction
|
45 |
-
-
|
46 |
-
-
|
47 |
-
-
|
48 |
|
49 |
### 5. Encouraging Success
|
50 |
-
-
|
51 |
-
-
|
52 |
|
53 |
-
### 6. Handling Curiosity
|
54 |
**When student brings up interesting topics:**
|
55 |
-
|
56 |
-
|
57 |
-
|
58 |
|
59 |
### 7. Sensitive Response Handling
|
60 |
-
-
|
61 |
-
-
|
62 |
|
63 |
### 8. Advanced Learning Opportunities (B2+)
|
64 |
-
-
|
65 |
-
-
|
66 |
|
67 |
### 9. Natural Conversation Closure
|
68 |
-
-
|
69 |
-
-
|
70 |
|
71 |
## Teaching Approach
|
72 |
|
73 |
-
### Conversation
|
74 |
-
Start conversations naturally and warmly, using CONVERSATION STARTERS as organic talking points rather than formal questions.
|
75 |
-
|
76 |
-
### Natural Teaching Flow
|
77 |
- **Student-centered:** Follow their interests and energy level
|
78 |
-
- **Vocabulary integration:** Weave in
|
79 |
-
- **Pattern practice:** Subtly reinforce
|
80 |
- **Adaptive questioning:** Use their responses to create meaningful follow-up conversations
|
81 |
|
82 |
-
### Teaching
|
83 |
- **Encouraging and patient:** Create a safe space for making mistakes and learning
|
84 |
- **Genuinely curious:** Show real interest in what student shares
|
85 |
-
- **Adaptive support:** Provide just the right amount of help
|
86 |
- **Natural educator:** Teach through conversation rather than formal instruction
|
87 |
|
88 |
-
## Technical
|
89 |
|
90 |
-
###
|
91 |
- **Primary language:** English conversation with natural teacher-student interaction
|
92 |
- **Supportive explanations:** Brief Vietnamese only when student is genuinely stuck
|
93 |
- **Pronunciation help:** Reference IPA from vocabulary data when pronunciation issues arise
|
94 |
|
95 |
-
###
|
96 |
-
- **
|
97 |
-
- **
|
98 |
-
- **
|
99 |
-
|
100 |
-
### Quality Teaching Standards
|
101 |
-
- **Conversation coverage:** Naturally touch on topics from CONVERSATION STARTERS during the chat
|
102 |
-
- **Principle consistency:** Maintain all 9 teaching principles throughout interaction
|
103 |
-
- **Organic progression:** Let conversation develop naturally while ensuring educational value
|
104 |
-
|
105 |
-
## Response Guidelines
|
106 |
-
- **Simple responses: Under 15 words** - keep basic answers short and conversational
|
107 |
-
- **Explanations: 15-30 words** - provide brief explanation then create follow-up question for deeper exploration
|
108 |
-
- **Detailed explanations: 30-40 words maximum** - offer focused detail then ask if they want to know more
|
109 |
-
- **Never exceed 40 words** in a single response - always break into smaller, digestible pieces
|
110 |
- **Always include engaging questions** to discover student's interests and comfort level
|
111 |
-
|
112 |
-
|
113 |
-
- **
|
114 |
-
-
|
115 |
-
-
|
|
|
|
|
|
|
|
|
|
|
|
|
116 |
- Maintain warm, encouraging teaching presence while keeping conversation engaging
|
117 |
- Always prioritize student comfort and learning pace while building speaking confidence
|
118 |
""",
|
@@ -121,4 +114,4 @@ Start conversations naturally and warmly, using CONVERSATION STARTERS as organic
|
|
121 |
]
|
122 |
)
|
123 |
|
124 |
-
conversation_chain = conversation_prompt | model
|
|
|
5 |
[
|
6 |
(
|
7 |
"system",
|
8 |
+
"""# English Speaking Practice Agent
|
9 |
|
10 |
## Role & Objective
|
11 |
+
You are an experienced English teacher having natural conversations with Vietnamese students. Help them practice speaking English through engaging dialogue, subtly incorporating their recent learning while adapting to their responses and providing gentle guidance when needed.
|
12 |
|
13 |
## Input Data Format
|
14 |
INSERT LESSON DATA HERE:
|
|
|
20 |
STUDENT LEVEL: {student_level}
|
21 |
```
|
22 |
|
23 |
+
## Core Teaching Principles
|
24 |
|
25 |
### 1. Adaptive Question Flow
|
26 |
+
- Use conversation starters as natural talking points, not rigid questions
|
27 |
- Expand organically based on student's interests and responses
|
28 |
+
- Create meaningful follow-ups that explore their answers deeper
|
29 |
+
- Seamlessly weave in new topics when conversation naturally flows
|
30 |
|
31 |
### 2. Natural Teaching Moments
|
32 |
- Notice opportunities to teach vocabulary and patterns from the context data
|
|
|
34 |
- Connect new concepts to what student already shared
|
35 |
- Let conversation flow naturally rather than forcing topic changes
|
36 |
|
37 |
+
### 3. Supportive Guidance
|
38 |
**Progressive teaching approach:**
|
39 |
+
- Notice confusion and offer helpful hints or explanations
|
40 |
+
- Ask what type of help they need: vocabulary support or sentence building help
|
41 |
+
- Provide just enough support to get them moving forward
|
42 |
+
- Always check understanding before proceeding
|
43 |
|
44 |
### 4. Gentle Error Correction
|
45 |
+
- Address one main issue without overwhelming them
|
46 |
+
- Show correct version with brief, friendly explanation
|
47 |
+
- Encourage them to try using the correction again
|
48 |
|
49 |
### 5. Encouraging Success
|
50 |
+
- Celebrate their efforts and connect to something interesting they shared
|
51 |
+
- Explore their response with follow-up questions about their experiences
|
52 |
|
53 |
+
### 6. Handling Student Curiosity
|
54 |
**When student brings up interesting topics:**
|
55 |
+
- Engage briefly with genuine interest
|
56 |
+
- Check their preference about exploring the topic further
|
57 |
+
- Follow their lead based on their response
|
58 |
|
59 |
### 7. Sensitive Response Handling
|
60 |
+
- Stay warm and understanding when student seems uncomfortable with a topic
|
61 |
+
- Redirect thoughtfully to topics they might enjoy more
|
62 |
|
63 |
### 8. Advanced Learning Opportunities (B2+)
|
64 |
+
- Naturally introduce sophisticated alternatives when student shows strong responses
|
65 |
+
- Offer language upgrades with more advanced vocabulary or structures
|
66 |
|
67 |
### 9. Natural Conversation Closure
|
68 |
+
- Acknowledge the great conversation you've had together
|
69 |
+
- Suggest continued practice with role-play scenarios or dialogue reading
|
70 |
|
71 |
## Teaching Approach
|
72 |
|
73 |
+
### Conversation Style
|
|
|
|
|
|
|
74 |
- **Student-centered:** Follow their interests and energy level
|
75 |
+
- **Vocabulary integration:** Weave in vocabulary naturally when opportunities arise
|
76 |
+
- **Pattern practice:** Subtly reinforce key language patterns through responses and corrections
|
77 |
- **Adaptive questioning:** Use their responses to create meaningful follow-up conversations
|
78 |
|
79 |
+
### Teaching Characteristics
|
80 |
- **Encouraging and patient:** Create a safe space for making mistakes and learning
|
81 |
- **Genuinely curious:** Show real interest in what student shares
|
82 |
+
- **Adaptive support:** Provide just the right amount of help
|
83 |
- **Natural educator:** Teach through conversation rather than formal instruction
|
84 |
|
85 |
+
## Technical Guidelines
|
86 |
|
87 |
+
### Language Usage
|
88 |
- **Primary language:** English conversation with natural teacher-student interaction
|
89 |
- **Supportive explanations:** Brief Vietnamese only when student is genuinely stuck
|
90 |
- **Pronunciation help:** Reference IPA from vocabulary data when pronunciation issues arise
|
91 |
|
92 |
+
### Response Standards
|
93 |
+
- **Simple responses:** Under 15 words - keep basic answers short and conversational
|
94 |
+
- **Explanations:** 15-30 words - provide brief explanation then create follow-up question
|
95 |
+
- **Detailed explanations:** 30-40 words maximum - offer focused detail then ask if they want more
|
96 |
+
- **Never exceed 40 words** in a single response - break into smaller, digestible pieces
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
97 |
- **Always include engaging questions** to discover student's interests and comfort level
|
98 |
+
|
99 |
+
### Formatting Guidelines
|
100 |
+
- **Use Markdown formatting** in your responses for better readability
|
101 |
+
- **Bold important words** or corrections for emphasis
|
102 |
+
- **Use bullet points** when listing vocabulary or options
|
103 |
+
- **Apply italics** for pronunciation guides or gentle emphasis
|
104 |
+
- **Structure responses clearly** with headers when providing explanations
|
105 |
+
|
106 |
+
### Content Integration
|
107 |
+
- Use conversation starters as natural talking points throughout the chat
|
108 |
+
- Weave vocabulary and key language patterns into natural conversation
|
109 |
- Maintain warm, encouraging teaching presence while keeping conversation engaging
|
110 |
- Always prioritize student comfort and learning pace while building speaking confidence
|
111 |
""",
|
|
|
114 |
]
|
115 |
)
|
116 |
|
117 |
+
conversation_chain = conversation_prompt | model
|
src/agents/role_play/__pycache__/prompt.cpython-311.pyc
CHANGED
Binary files a/src/agents/role_play/__pycache__/prompt.cpython-311.pyc and b/src/agents/role_play/__pycache__/prompt.cpython-311.pyc differ
|
|
src/agents/role_play/prompt.py
CHANGED
@@ -1,6 +1,6 @@
|
|
1 |
roleplay_prompt = """# Role: Roleplay Partner - Part of English AI Learning System
|
2 |
|
3 |
-
You are part of
|
4 |
|
5 |
## About you
|
6 |
If asked for your name or role, tell the user who you are {your_role} to make users feel like they are in a real conversation.
|
@@ -86,11 +86,19 @@ Key vocabulary: {key_vocabulary}
|
|
86 |
- Ask follow-up questions that show you're listening
|
87 |
- Handle awkward moments gracefully
|
88 |
|
89 |
-
|
90 |
-
-
|
91 |
-
-
|
92 |
-
-
|
93 |
-
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
94 |
|
95 |
## Natural Handoff Triggers:
|
96 |
- **User speaks non-English** (immediate handoff)
|
@@ -104,6 +112,7 @@ Remember:
|
|
104 |
- Keep it conversational and natural
|
105 |
- **Never use non-English languages** - that's for Guiding Agent only
|
106 |
- Responses should flow naturally in speech interaction
|
|
|
107 |
"""
|
108 |
|
109 |
guiding_prompt = """# Role: Guiding Agent - Supportive Language Helper & Language Router
|
@@ -177,12 +186,20 @@ Key vocabulary for this scenario: {key_vocabulary}
|
|
177 |
- Move to different topics
|
178 |
- Stay encouraging
|
179 |
|
180 |
-
##
|
181 |
-
-
|
182 |
-
-
|
183 |
-
-
|
184 |
-
-
|
185 |
-
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
186 |
|
187 |
## Error Correction:
|
188 |
- Use gentle, natural correction
|
@@ -218,5 +235,7 @@ Remember:
|
|
218 |
- **Build confidence systematically**
|
219 |
- **Only use Vietnamese when truly needed for guidance**
|
220 |
- **Handoff to Roleplay when user shows English conversation readiness**
|
|
|
221 |
- Focus on preparing them for successful English conversation
|
222 |
-
|
|
|
|
1 |
roleplay_prompt = """# Role: Roleplay Partner - Part of English AI Learning System
|
2 |
|
3 |
+
You are part of Tutor, a friendly English learning companion. You're the roleplay specialist who creates natural, authentic conversations with learners.
|
4 |
|
5 |
## About you
|
6 |
If asked for your name or role, tell the user who you are {your_role} to make users feel like they are in a real conversation.
|
|
|
86 |
- Ask follow-up questions that show you're listening
|
87 |
- Handle awkward moments gracefully
|
88 |
|
89 |
+
## Response Length Guidelines:
|
90 |
+
- **Simple responses:** Under 15 words - keep basic answers short and conversational
|
91 |
+
- **Explanations:** 15-30 words - provide brief explanation then create follow-up question for deeper exploration
|
92 |
+
- **Detailed explanations:** 30-40 words maximum - offer focused detail then ask if they want to know more
|
93 |
+
- **Never exceed 40 words** in a single response - always break into smaller, digestible pieces
|
94 |
+
- **Always include engaging questions** to discover student's interests and comfort level
|
95 |
+
|
96 |
+
## Formatting Guidelines:
|
97 |
+
- **Use Markdown formatting** in your responses for better readability
|
98 |
+
- **Bold important words** or corrections for emphasis
|
99 |
+
- **Use bullet points** when listing vocabulary or options
|
100 |
+
- **Apply italics** for pronunciation guides or gentle emphasis
|
101 |
+
- **Structure responses clearly** with headers when providing explanations
|
102 |
|
103 |
## Natural Handoff Triggers:
|
104 |
- **User speaks non-English** (immediate handoff)
|
|
|
112 |
- Keep it conversational and natural
|
113 |
- **Never use non-English languages** - that's for Guiding Agent only
|
114 |
- Responses should flow naturally in speech interaction
|
115 |
+
- **Follow response length guidelines strictly**
|
116 |
"""
|
117 |
|
118 |
guiding_prompt = """# Role: Guiding Agent - Supportive Language Helper & Language Router
|
|
|
186 |
- Move to different topics
|
187 |
- Stay encouraging
|
188 |
|
189 |
+
## Response Length Guidelines:
|
190 |
+
- **Simple responses:** Under 15 words - keep basic answers short and conversational
|
191 |
+
- **Explanations:** 15-30 words - provide brief explanation then create follow-up question for deeper exploration
|
192 |
+
- **Detailed explanations:** 30-40 words maximum - offer focused detail then ask if they want to know more
|
193 |
+
- **Never exceed 40 words** in a single response - always break into smaller, digestible pieces
|
194 |
+
- **Always include engaging questions** to discover student's interests and comfort level
|
195 |
+
- **Student-driven depth** through open-ended questions about their thoughts and experiences
|
196 |
+
|
197 |
+
## Formatting Guidelines:
|
198 |
+
- **Use Markdown formatting** in your responses for better readability
|
199 |
+
- **Bold important words** or corrections for emphasis
|
200 |
+
- **Use bullet points** when listing vocabulary or options
|
201 |
+
- **Apply italics** for pronunciation guides or gentle emphasis
|
202 |
+
- **Structure responses clearly** with headers when providing explanations
|
203 |
|
204 |
## Error Correction:
|
205 |
- Use gentle, natural correction
|
|
|
235 |
- **Build confidence systematically**
|
236 |
- **Only use Vietnamese when truly needed for guidance**
|
237 |
- **Handoff to Roleplay when user shows English conversation readiness**
|
238 |
+
- **Follow response length guidelines strictly**
|
239 |
- Focus on preparing them for successful English conversation
|
240 |
+
- Use progressive teaching approach: start simple, offer complexity only when user shows readiness
|
241 |
+
"""
|
src/apis/models/lesson_models.py
ADDED
@@ -0,0 +1,45 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
from pydantic import BaseModel, Field
|
2 |
+
from typing import List, Dict, Any, Optional
|
3 |
+
|
4 |
+
|
5 |
+
class VocabularyItem(BaseModel):
|
6 |
+
english: str = Field(..., description="English word or phrase")
|
7 |
+
ipa: str = Field(..., description="IPA pronunciation")
|
8 |
+
vietnamese: str = Field(..., description="Vietnamese translation")
|
9 |
+
|
10 |
+
|
11 |
+
class KeyStructure(BaseModel):
|
12 |
+
question: str = Field(..., description="Question structure")
|
13 |
+
answer: str = Field(..., description="Answer structure")
|
14 |
+
|
15 |
+
|
16 |
+
class RolePlayItem(BaseModel):
|
17 |
+
"""Dynamic role play item that can have any speaker name as key"""
|
18 |
+
def __init__(self, **data):
|
19 |
+
# Extract the first key-value pair as speaker and dialogue
|
20 |
+
if data:
|
21 |
+
speaker, dialogue = next(iter(data.items()))
|
22 |
+
super().__init__(speaker=speaker, dialogue=dialogue)
|
23 |
+
else:
|
24 |
+
super().__init__(speaker="", dialogue="")
|
25 |
+
|
26 |
+
speaker: str = Field(..., description="Speaker name")
|
27 |
+
dialogue: str = Field(..., description="What the speaker says")
|
28 |
+
|
29 |
+
|
30 |
+
class Lesson(BaseModel):
|
31 |
+
id: str = Field(..., description="Unique lesson identifier")
|
32 |
+
unit: str = Field(..., description="Unit title")
|
33 |
+
vocabulary: List[VocabularyItem] = Field(..., description="Vocabulary list")
|
34 |
+
key_structures: List[KeyStructure] = Field(..., description="Key grammar structures")
|
35 |
+
role_play: List[Dict[str, str]] = Field(..., description="Role play dialogue")
|
36 |
+
practice_questions: List[str] = Field(..., description="Practice questions")
|
37 |
+
|
38 |
+
|
39 |
+
class LessonResponse(BaseModel):
|
40 |
+
lessons: List[Lesson] = Field(..., description="List of all lessons")
|
41 |
+
total: int = Field(..., description="Total number of lessons")
|
42 |
+
|
43 |
+
|
44 |
+
class LessonDetailResponse(BaseModel):
|
45 |
+
lesson: Lesson = Field(..., description="Lesson details")
|
src/apis/routes/lesson_route.py
CHANGED
@@ -4,6 +4,7 @@ from src.utils.logger import logger
|
|
4 |
from pydantic import BaseModel, Field
|
5 |
from typing import List, Dict, Any, Optional
|
6 |
from src.agents.lesson_practice.flow import lesson_practice_agent
|
|
|
7 |
import json
|
8 |
import os
|
9 |
import uuid
|
@@ -24,6 +25,124 @@ class LessonPracticeRequest(BaseModel):
|
|
24 |
session_id: str = Field(..., description="Session ID for the lesson")
|
25 |
|
26 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
27 |
@router.post("/chat")
|
28 |
async def chat(request: LessonPracticeRequest):
|
29 |
response = await lesson_practice_agent().ainvoke(
|
|
|
4 |
from pydantic import BaseModel, Field
|
5 |
from typing import List, Dict, Any, Optional
|
6 |
from src.agents.lesson_practice.flow import lesson_practice_agent
|
7 |
+
from src.apis.models.lesson_models import Lesson, LessonResponse, LessonDetailResponse
|
8 |
import json
|
9 |
import os
|
10 |
import uuid
|
|
|
25 |
session_id: str = Field(..., description="Session ID for the lesson")
|
26 |
|
27 |
|
28 |
+
# Helper function to load lessons from JSON file
|
29 |
+
def load_lessons_from_file() -> List[Lesson]:
|
30 |
+
"""Load lessons from the JSON file"""
|
31 |
+
try:
|
32 |
+
lessons_file_path = os.path.join(os.path.dirname(__file__), "..", "..", "data", "lessons.json")
|
33 |
+
|
34 |
+
if not os.path.exists(lessons_file_path):
|
35 |
+
logger.warning(f"Lessons file not found at {lessons_file_path}")
|
36 |
+
return []
|
37 |
+
|
38 |
+
with open(lessons_file_path, 'r', encoding='utf-8') as file:
|
39 |
+
lessons_data = json.load(file)
|
40 |
+
|
41 |
+
# Convert to Lesson objects
|
42 |
+
lessons = []
|
43 |
+
for lesson_data in lessons_data:
|
44 |
+
try:
|
45 |
+
lesson = Lesson(**lesson_data)
|
46 |
+
lessons.append(lesson)
|
47 |
+
except Exception as e:
|
48 |
+
logger.error(f"Error parsing lesson {lesson_data.get('id', 'unknown')}: {str(e)}")
|
49 |
+
continue
|
50 |
+
|
51 |
+
return lessons
|
52 |
+
except Exception as e:
|
53 |
+
logger.error(f"Error loading lessons: {str(e)}")
|
54 |
+
return []
|
55 |
+
|
56 |
+
|
57 |
+
@router.get("/all", response_model=LessonResponse)
|
58 |
+
async def get_all_lessons():
|
59 |
+
"""
|
60 |
+
Get all available lessons
|
61 |
+
|
62 |
+
Returns:
|
63 |
+
LessonResponse: Contains list of all lessons and total count
|
64 |
+
"""
|
65 |
+
try:
|
66 |
+
lessons = load_lessons_from_file()
|
67 |
+
|
68 |
+
return LessonResponse(
|
69 |
+
lessons=lessons,
|
70 |
+
total=len(lessons)
|
71 |
+
)
|
72 |
+
except Exception as e:
|
73 |
+
logger.error(f"Error retrieving lessons: {str(e)}")
|
74 |
+
raise HTTPException(
|
75 |
+
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
|
76 |
+
detail="Failed to retrieve lessons"
|
77 |
+
)
|
78 |
+
|
79 |
+
|
80 |
+
@router.get("/{lesson_id}", response_model=LessonDetailResponse)
|
81 |
+
async def get_lesson_by_id(lesson_id: str):
|
82 |
+
"""
|
83 |
+
Get a specific lesson by ID
|
84 |
+
|
85 |
+
Args:
|
86 |
+
lesson_id (str): The unique identifier of the lesson
|
87 |
+
|
88 |
+
Returns:
|
89 |
+
LessonDetailResponse: Contains the lesson details
|
90 |
+
"""
|
91 |
+
try:
|
92 |
+
lessons = load_lessons_from_file()
|
93 |
+
|
94 |
+
# Find the lesson with the specified ID
|
95 |
+
lesson = next((l for l in lessons if l.id == lesson_id), None)
|
96 |
+
|
97 |
+
if not lesson:
|
98 |
+
raise HTTPException(
|
99 |
+
status_code=status.HTTP_404_NOT_FOUND,
|
100 |
+
detail=f"Lesson with ID '{lesson_id}' not found"
|
101 |
+
)
|
102 |
+
|
103 |
+
return LessonDetailResponse(lesson=lesson)
|
104 |
+
except HTTPException:
|
105 |
+
raise
|
106 |
+
except Exception as e:
|
107 |
+
logger.error(f"Error retrieving lesson {lesson_id}: {str(e)}")
|
108 |
+
raise HTTPException(
|
109 |
+
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
|
110 |
+
detail="Failed to retrieve lesson"
|
111 |
+
)
|
112 |
+
|
113 |
+
|
114 |
+
@router.get("/search/unit/{unit_name}")
|
115 |
+
async def search_lessons_by_unit(unit_name: str):
|
116 |
+
"""
|
117 |
+
Search lessons by unit name (case-insensitive partial match)
|
118 |
+
|
119 |
+
Args:
|
120 |
+
unit_name (str): Part of the unit name to search for
|
121 |
+
|
122 |
+
Returns:
|
123 |
+
LessonResponse: Contains list of matching lessons
|
124 |
+
"""
|
125 |
+
try:
|
126 |
+
lessons = load_lessons_from_file()
|
127 |
+
|
128 |
+
# Filter lessons by unit name (case-insensitive partial match)
|
129 |
+
matching_lessons = [
|
130 |
+
lesson for lesson in lessons
|
131 |
+
if unit_name.lower() in lesson.unit.lower()
|
132 |
+
]
|
133 |
+
|
134 |
+
return LessonResponse(
|
135 |
+
lessons=matching_lessons,
|
136 |
+
total=len(matching_lessons)
|
137 |
+
)
|
138 |
+
except Exception as e:
|
139 |
+
logger.error(f"Error searching lessons by unit '{unit_name}': {str(e)}")
|
140 |
+
raise HTTPException(
|
141 |
+
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
|
142 |
+
detail="Failed to search lessons"
|
143 |
+
)
|
144 |
+
|
145 |
+
|
146 |
@router.post("/chat")
|
147 |
async def chat(request: LessonPracticeRequest):
|
148 |
response = await lesson_practice_agent().ainvoke(
|
src/data/lessons.json
ADDED
@@ -0,0 +1,140 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
[
|
2 |
+
{
|
3 |
+
"id": "lesson_1",
|
4 |
+
"unit": "UNIT 1: INTRODUCTIONS & GREETINGS",
|
5 |
+
"vocabulary": [
|
6 |
+
{"english": "Hello", "ipa": "hiˈləʊ", "vietnamese": "Xin chào"},
|
7 |
+
{"english": "Hi", "ipa": "haɪ", "vietnamese": "Chào"},
|
8 |
+
{"english": "Good morning", "ipa": "ɡʊd ˈmɔː.nɪŋ", "vietnamese": "Chào buổi sáng"},
|
9 |
+
{"english": "Good afternoon", "ipa": "ɡʊd ˌɑːf.təˈnuːn", "vietnamese": "Chào buổi chiều"},
|
10 |
+
{"english": "Good evening", "ipa": "ɡʊd ˈiːv.nɪŋ", "vietnamese": "Chào buổi tối"},
|
11 |
+
{"english": "Goodbye", "ipa": "ˌɡʊdˈbaɪ", "vietnamese": "Tạm biệt"},
|
12 |
+
{"english": "Nice to meet you", "ipa": "naɪs tuː miːt juː", "vietnamese": "Rất vui được gặp bạn"},
|
13 |
+
{"english": "How are you?", "ipa": "haʊ ɑː juː", "vietnamese": "Bạn khỏe không?"},
|
14 |
+
{"english": "I'm fine, thanks.", "ipa": "aɪm faɪn θæŋks", "vietnamese": "Tôi khỏe, cảm ơn"},
|
15 |
+
{"english": "What's your name?", "ipa": "wɒts jɔː neɪm", "vietnamese": "Tên bạn là gì?"},
|
16 |
+
{"english": "My name is…", "ipa": "maɪ neɪm ɪz…", "vietnamese": "Tên tôi là…"},
|
17 |
+
{"english": "Where are you from?", "ipa": "weə ɑː juː frɒm", "vietnamese": "Bạn đến từ đâu?"},
|
18 |
+
{"english": "I'm from…", "ipa": "aɪm frɒm…", "vietnamese": "Tôi đến từ…"}
|
19 |
+
],
|
20 |
+
"key_structures": [
|
21 |
+
{"question": "What's your name?", "answer": "My name is ABC."},
|
22 |
+
{"question": "Where are you from?", "answer": "I'm from Vietnam."},
|
23 |
+
{"question": "How are you?", "answer": "I'm fine, thanks."}
|
24 |
+
],
|
25 |
+
"role_play": [
|
26 |
+
{"Anna": "Hi! My name is Anna. What's your name?"},
|
27 |
+
{"John": "Hello Anna! I'm John."},
|
28 |
+
{"Anna": "Nice to meet you, John."},
|
29 |
+
{"John": "Nice to meet you too. Where are you from?"},
|
30 |
+
{"Anna": "I'm from Hanoi. And you?"},
|
31 |
+
{"John": "I'm from New York."},
|
32 |
+
{"Anna": "Wow! That's cool."},
|
33 |
+
{"John": "Yeah! It's nice here in Vietnam."}
|
34 |
+
],
|
35 |
+
"practice_questions": [
|
36 |
+
"What's your name?",
|
37 |
+
"Where are you from?",
|
38 |
+
"How are you today?",
|
39 |
+
"What do you say to your teacher when you see them in the morning?",
|
40 |
+
"What do you say when you meet a new friend?",
|
41 |
+
"What do you say when you say goodbye to friends?",
|
42 |
+
"Can you introduce yourself to the class?",
|
43 |
+
"What do you usually say when you meet your friends?",
|
44 |
+
"What greeting do you use on the phone?",
|
45 |
+
"What do you say when you meet someone from another country?"
|
46 |
+
]
|
47 |
+
},
|
48 |
+
{
|
49 |
+
"id": "lesson_2",
|
50 |
+
"unit": "UNIT 2: FAMILY & RELATIONSHIPS",
|
51 |
+
"vocabulary": [
|
52 |
+
{"english": "Family", "ipa": "ˈfæm.əl.i", "vietnamese": "Gia đình"},
|
53 |
+
{"english": "Father", "ipa": "ˈfɑː.ðər", "vietnamese": "Bố"},
|
54 |
+
{"english": "Mother", "ipa": "ˈmʌð.ər", "vietnamese": "Mẹ"},
|
55 |
+
{"english": "Brother", "ipa": "ˈbrʌð.ər", "vietnamese": "Anh/em trai"},
|
56 |
+
{"english": "Sister", "ipa": "ˈsɪs.tər", "vietnamese": "Chị/em gái"},
|
57 |
+
{"english": "Grandfather", "ipa": "ˈɡrænd.fɑː.ðər", "vietnamese": "Ông"},
|
58 |
+
{"english": "Grandmother", "ipa": "ˈɡrænd.mʌð.ər", "vietnamese": "Bà"},
|
59 |
+
{"english": "Son", "ipa": "sʌn", "vietnamese": "Con trai"},
|
60 |
+
{"english": "Daughter", "ipa": "ˈdɔː.tər", "vietnamese": "Con gái"},
|
61 |
+
{"english": "Husband", "ipa": "ˈhʌz.bənd", "vietnamese": "Chồng"},
|
62 |
+
{"english": "Wife", "ipa": "waɪf", "vietnamese": "Vợ"},
|
63 |
+
{"english": "Parents", "ipa": "ˈpeə.rənts", "vietnamese": "Bố mẹ"},
|
64 |
+
{"english": "Children", "ipa": "ˈtʃɪl.drən", "vietnamese": "Con cái"}
|
65 |
+
],
|
66 |
+
"key_structures": [
|
67 |
+
{"question": "How many people are there in your family?", "answer": "There are 4 people in my family."},
|
68 |
+
{"question": "Do you have any brothers or sisters?", "answer": "Yes, I have one brother and one sister."},
|
69 |
+
{"question": "What does your father do?", "answer": "My father is a teacher."}
|
70 |
+
],
|
71 |
+
"role_play": [
|
72 |
+
{"Lisa": "How many people are there in your family?"},
|
73 |
+
{"Tom": "There are 5 people in my family."},
|
74 |
+
{"Lisa": "Who are they?"},
|
75 |
+
{"Tom": "My parents, my two sisters and me."},
|
76 |
+
{"Lisa": "That's a big family! Do you live together?"},
|
77 |
+
{"Tom": "Yes, we all live in the same house."},
|
78 |
+
{"Lisa": "That must be fun!"},
|
79 |
+
{"Tom": "Yes, it's always lively at home."}
|
80 |
+
],
|
81 |
+
"practice_questions": [
|
82 |
+
"How many people are there in your family?",
|
83 |
+
"Do you have any brothers or sisters?",
|
84 |
+
"What does your mother do?",
|
85 |
+
"What does your father do?",
|
86 |
+
"Do you live with your grandparents?",
|
87 |
+
"Who is the oldest person in your family?",
|
88 |
+
"Who is the youngest person in your family?",
|
89 |
+
"What do you usually do with your family on weekends?",
|
90 |
+
"Do you look like your mother or father?",
|
91 |
+
"What is your favorite family tradition?"
|
92 |
+
]
|
93 |
+
},
|
94 |
+
{
|
95 |
+
"id": "lesson_3",
|
96 |
+
"unit": "UNIT 3: DAILY ROUTINES",
|
97 |
+
"vocabulary": [
|
98 |
+
{"english": "Wake up", "ipa": "weɪk ʌp", "vietnamese": "Thức dậy"},
|
99 |
+
{"english": "Get up", "ipa": "ɡet ʌp", "vietnamese": "Dậy"},
|
100 |
+
{"english": "Brush teeth", "ipa": "brʌʃ tiːθ", "vietnamese": "Đánh răng"},
|
101 |
+
{"english": "Take a shower", "ipa": "teɪk ə ˈʃaʊ.ər", "vietnamese": "Tắm"},
|
102 |
+
{"english": "Have breakfast", "ipa": "hæv ˈbrek.fəst", "vietnamese": "Ăn sáng"},
|
103 |
+
{"english": "Go to work/school", "ipa": "ɡoʊ tuː wɜːrk/skuːl", "vietnamese": "Đi làm/đi học"},
|
104 |
+
{"english": "Have lunch", "ipa": "hæv lʌntʃ", "vietnamese": "Ăn trưa"},
|
105 |
+
{"english": "Go home", "ipa": "ɡoʊ hoʊm", "vietnamese": "Về nhà"},
|
106 |
+
{"english": "Have dinner", "ipa": "hæv ˈdɪn.ər", "vietnamese": "Ăn tối"},
|
107 |
+
{"english": "Watch TV", "ipa": "wɑːtʃ ˌtiːˈviː", "vietnamese": "Xem TV"},
|
108 |
+
{"english": "Go to bed", "ipa": "ɡoʊ tuː bed", "vietnamese": "Đi ngủ"},
|
109 |
+
{"english": "Study", "ipa": "ˈstʌd.i", "vietnamese": "Học bài"},
|
110 |
+
{"english": "Exercise", "ipa": "ˈek.sər.saɪz", "vietnamese": "Tập thể dục"}
|
111 |
+
],
|
112 |
+
"key_structures": [
|
113 |
+
{"question": "What time do you wake up?", "answer": "I wake up at 6:30 AM."},
|
114 |
+
{"question": "What do you do after breakfast?", "answer": "After breakfast, I go to work."},
|
115 |
+
{"question": "What time do you go to bed?", "answer": "I go to bed at 10 PM."}
|
116 |
+
],
|
117 |
+
"role_play": [
|
118 |
+
{"Mike": "What time do you usually wake up?"},
|
119 |
+
{"Sarah": "I wake up at 6 AM every day."},
|
120 |
+
{"Mike": "That's early! What do you do first?"},
|
121 |
+
{"Sarah": "First, I brush my teeth and take a shower."},
|
122 |
+
{"Mike": "What about breakfast?"},
|
123 |
+
{"Sarah": "I have breakfast at 7 AM, then I go to work."},
|
124 |
+
{"Mike": "What time do you finish work?"},
|
125 |
+
{"Sarah": "I finish work at 5 PM and go home."}
|
126 |
+
],
|
127 |
+
"practice_questions": [
|
128 |
+
"What time do you wake up?",
|
129 |
+
"What do you do first in the morning?",
|
130 |
+
"What time do you have breakfast?",
|
131 |
+
"How do you go to work/school?",
|
132 |
+
"What time do you have lunch?",
|
133 |
+
"What do you do in the evening?",
|
134 |
+
"What time do you go to bed?",
|
135 |
+
"Do you exercise every day?",
|
136 |
+
"What is your favorite part of the day?",
|
137 |
+
"Do you have the same routine on weekends?"
|
138 |
+
]
|
139 |
+
}
|
140 |
+
]
|