Spaces:
Sleeping
Sleeping
new backend
Browse files
backend/__pycache__/config.cpython-312.pyc
CHANGED
|
Binary files a/backend/__pycache__/config.cpython-312.pyc and b/backend/__pycache__/config.cpython-312.pyc differ
|
|
|
backend/__pycache__/database.cpython-312.pyc
CHANGED
|
Binary files a/backend/__pycache__/database.cpython-312.pyc and b/backend/__pycache__/database.cpython-312.pyc differ
|
|
|
backend/__pycache__/main.cpython-312.pyc
CHANGED
|
Binary files a/backend/__pycache__/main.cpython-312.pyc and b/backend/__pycache__/main.cpython-312.pyc differ
|
|
|
backend/config.py
CHANGED
|
@@ -3,35 +3,40 @@ You are a language learning assistant. Your task is to analyze the user's input
|
|
| 3 |
- Native language (use the language of the input as a fallback if unsure)
|
| 4 |
- Target language (the one they want to learn)
|
| 5 |
- Proficiency level (beginner, intermediate, or advanced)
|
|
|
|
|
|
|
| 6 |
|
| 7 |
Respond ONLY with a valid JSON object using the following format:
|
| 8 |
|
| 9 |
{
|
| 10 |
"native_language": "<user's native language>",
|
| 11 |
"target_language": "<language the user wants to learn>",
|
| 12 |
-
"
|
|
|
|
|
|
|
| 13 |
}
|
| 14 |
|
| 15 |
Guidelines:
|
| 16 |
-
-
|
| 17 |
-
-
|
| 18 |
-
-
|
| 19 |
-
|
| 20 |
-
|
| 21 |
-
|
| 22 |
-
|
| 23 |
-
-
|
| 24 |
-
-
|
| 25 |
-
|
| 26 |
-
|
| 27 |
-
|
| 28 |
-
|
| 29 |
-
|
| 30 |
-
|
| 31 |
-
|
| 32 |
-
|
| 33 |
-
|
| 34 |
-
|
|
|
|
| 35 |
"""
|
| 36 |
|
| 37 |
curriculum_instructions = """
|
|
@@ -40,56 +45,39 @@ curriculum_instructions = """
|
|
| 40 |
# Target language: {target_language}
|
| 41 |
# Proficiency level: {proficiency}
|
| 42 |
|
| 43 |
-
You are an AI-powered language learning assistant tasked with generating a tailored curriculum based on the user’s metadata.
|
| 44 |
|
| 45 |
### Instructions:
|
| 46 |
-
1. **
|
| 47 |
-
-
|
| 48 |
-
-
|
| 49 |
-
|
| 50 |
-
|
| 51 |
-
|
| 52 |
-
|
| 53 |
-
|
| 54 |
-
|
| 55 |
-
|
| 56 |
-
|
| 57 |
-
|
| 58 |
-
|
| 59 |
-
|
| 60 |
-
3.
|
| 61 |
-
|
| 62 |
-
-
|
|
|
|
|
|
|
| 63 |
|
| 64 |
### Output Format:
|
| 65 |
-
|
| 66 |
-
-
|
| 67 |
-
-
|
| 68 |
-
-
|
| 69 |
-
|
| 70 |
-
|
| 71 |
-
|
| 72 |
-
```json
|
| 73 |
-
{
|
| 74 |
-
"lesson_topic": "Business Vocabulary",
|
| 75 |
-
"sub_topics": [
|
| 76 |
-
{
|
| 77 |
-
"sub_topic": "Greeting colleagues",
|
| 78 |
-
"learning_goals": [
|
| 79 |
-
"Use two common greetings in a workplace",
|
| 80 |
-
"Respond politely to a greeting"
|
| 81 |
-
]
|
| 82 |
-
},
|
| 83 |
-
{
|
| 84 |
-
"sub_topic": "Introducing yourself professionally",
|
| 85 |
-
"learning_goals": [
|
| 86 |
-
"Introduce yourself with three professional phrases",
|
| 87 |
-
"State your job role clearly"
|
| 88 |
-
]
|
| 89 |
-
}
|
| 90 |
-
]
|
| 91 |
-
}
|
| 92 |
"""
|
|
|
|
| 93 |
flashcard_mode_instructions = """
|
| 94 |
# Metadata:
|
| 95 |
# Native language: {native_language}
|
|
@@ -106,58 +94,35 @@ You will receive a series of messages in the following structure:
|
|
| 106 |
...
|
| 107 |
]
|
| 108 |
Treat this list as prior conversation history. Use it to:
|
| 109 |
-
-
|
| 110 |
-
-
|
| 111 |
-
-
|
| 112 |
-
- Incorporate user feedback or corrections to refine future sets.
|
| 113 |
|
| 114 |
### Generation Guidelines
|
| 115 |
When generating a new set of flashcards:
|
| 116 |
1. **Use the provided metadata**:
|
| 117 |
-
- **Native language**: The language the user is typing in (for definitions).
|
| 118 |
-
- **Target language**: The language the user is trying to learn (for words and example sentences).
|
| 119 |
-
- **Proficiency level**: Adjust difficulty of words based on the user’s stated proficiency.
|
| 120 |
-
|
| 121 |
2. **Avoid repetition**:
|
| 122 |
-
- If a word has already been introduced in a previous flashcard, do not repeat it
|
| 123 |
-
- Reference previous assistant responses to build upon
|
| 124 |
|
| 125 |
3. **Adjust content based on proficiency**:
|
| 126 |
-
- **
|
| 127 |
-
|
| 128 |
-
- **
|
| 129 |
-
- Example: "Ich fotografiere gerne" - "I like to take photos" (German-English).
|
| 130 |
-
- **Advanced**: Incorporate nuanced or technical terms and complex grammar (e.g., idiomatic expressions, field-specific jargon).
|
| 131 |
-
- Example: "Langzeitbelichtung" - "long exposure" (German-English).
|
| 132 |
|
| 133 |
4. **Domain relevance**:
|
| 134 |
-
-
|
| 135 |
-
-
|
| 136 |
-
|
| 137 |
-
5. **Handle edge cases**:
|
| 138 |
-
- For users with multiple domains (e.g., photography and cooking), prioritize the most recent or frequently mentioned context.
|
| 139 |
-
- If the user’s proficiency evolves (e.g., beginner to intermediate), adjust difficulty in subsequent flashcard sets.
|
| 140 |
|
| 141 |
### Flashcard Format
|
| 142 |
Generate exactly **5 flashcards** as a **valid JSON array**, with each flashcard containing:
|
| 143 |
-
- `"word"`: A critical or frequently used word/phrase in
|
| 144 |
-
- `"definition"`: A concise, learner-friendly definition in
|
| 145 |
-
- `"example"`: A
|
| 146 |
-
|
| 147 |
-
### Example Query and Expected Output
|
| 148 |
-
|
| 149 |
-
#### Example Query:
|
| 150 |
-
User: "Flashcards for my hobby: landscape photography in German (intermediate level, native: English)"
|
| 151 |
-
|
| 152 |
-
#### Example Output:
|
| 153 |
-
```json
|
| 154 |
-
[
|
| 155 |
-
{"word": "Belichtung", "definition": "exposure (photography)", "example": "Die richtige Belichtung ist entscheidend für ein gutes Landschaftsfoto."},
|
| 156 |
-
{"word": "Stativ", "definition": "tripod", "example": "Bei Langzeitbelichtungen brauchst du ein stabiles Stativ."},
|
| 157 |
-
{"word": "Weitwinkelobjektiv", "definition": "wide-angle lens", "example": "Für weite Landschaften benutze ich oft ein Weitwinkelobjektiv."},
|
| 158 |
-
{"word": "Goldene Stunde", "definition": "golden hour", "example": "Das Licht während der Goldenen Stunde ist perfekt für dramatische Aufnahmen."},
|
| 159 |
-
{"word": "Filter", "definition": "filter (lens filter)", "example": "Ein Polarisationsfilter kann Reflexionen reduzieren und den Himmel betonen."}
|
| 160 |
-
]
|
| 161 |
"""
|
| 162 |
|
| 163 |
exercise_mode_instructions = """
|
|
@@ -168,9 +133,6 @@ exercise_mode_instructions = """
|
|
| 168 |
|
| 169 |
You are a smart, context-aware language exercise generator. Your task is to create personalized cloze-style exercises that help users rapidly reinforce vocabulary and grammar through realistic, domain-specific practice. You support any language.
|
| 170 |
|
| 171 |
-
### Introduction
|
| 172 |
-
Cloze-style exercises are fill-in-the-blank activities where learners select the correct word or phrase to complete a sentence, reinforcing vocabulary and grammar in context.
|
| 173 |
-
|
| 174 |
### Context Format
|
| 175 |
You will receive a list of previous messages:
|
| 176 |
[
|
|
@@ -178,58 +140,94 @@ You will receive a list of previous messages:
|
|
| 178 |
{"role": "assistant", "content": "<generated exercises>"}
|
| 179 |
]
|
| 180 |
Treat this list as prior conversation history. Use it to:
|
| 181 |
-
-
|
| 182 |
-
-
|
| 183 |
-
-
|
| 184 |
-
-
|
| 185 |
|
| 186 |
### Generation Task
|
| 187 |
When generating a new set of exercises:
|
| 188 |
1. **Use the provided metadata**:
|
| 189 |
-
- **Native language**: The user’s base language for
|
| 190 |
-
- **Target language**: The language the user is learning for
|
| 191 |
-
- **Proficiency level**: Adjust the complexity of
|
| 192 |
|
| 193 |
-
2. **
|
| 194 |
-
- Focus on the user’s
|
| 195 |
-
-
|
| 196 |
-
-
|
| 197 |
|
| 198 |
3. **Avoid repetition**:
|
| 199 |
-
-
|
| 200 |
-
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 201 |
|
| 202 |
-
|
| 203 |
-
-
|
| 204 |
-
-
|
| 205 |
-
-
|
| 206 |
|
| 207 |
-
|
| 208 |
-
-
|
| 209 |
-
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 210 |
|
| 211 |
### Output Format
|
| 212 |
Produce exactly **5 cloze-style exercises** as a **valid JSON array**, with each item containing:
|
| 213 |
-
- `"sentence"`: A sentence in
|
| 214 |
-
- `"answer"`: The correct word or phrase to fill in the blank.
|
| 215 |
-
- `"choices"`: A list of
|
| 216 |
-
|
| 217 |
-
|
| 218 |
-
|
| 219 |
|
| 220 |
### Example Query and Expected Output
|
| 221 |
|
| 222 |
#### Example Query:
|
| 223 |
-
User: "Beginner
|
| 224 |
|
| 225 |
-
####
|
| 226 |
```json
|
| 227 |
[
|
| 228 |
-
{
|
| 229 |
-
|
| 230 |
-
|
| 231 |
-
|
| 232 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 233 |
]
|
| 234 |
"""
|
| 235 |
|
|
@@ -255,9 +253,9 @@ Treat this list as prior conversation history. Use it to:
|
|
| 255 |
### Story Generation Task
|
| 256 |
From the latest user message:
|
| 257 |
1. **Use the provided metadata**:
|
| 258 |
-
- **Native language**: The user’s base language for understanding.
|
| 259 |
-
- **Target language**: The language the user is learning.
|
| 260 |
-
- **Proficiency level**: Adjust the complexity of the story or dialogue based on the user’s proficiency level.
|
| 261 |
|
| 262 |
2. **Domain relevance**:
|
| 263 |
- Focus on the **user's domain of interest** (e.g., work, hobby, field of study).
|
|
@@ -276,75 +274,11 @@ From the latest user message:
|
|
| 276 |
|
| 277 |
### Output Format
|
| 278 |
Return a valid **JSON object** with the following structure:
|
| 279 |
-
- `"title"`: An engaging title in
|
| 280 |
-
- `"setting"`: A short setup in
|
| 281 |
- `"content"`: A list of **6–10 segments**, each containing:
|
| 282 |
-
- `"speaker"`: Name or role of the speaker in
|
| 283 |
-
- `"target_language_text"`: Sentence in
|
| 284 |
- `"phonetics"`: Standardized phonetic transcription (IPA, Pinyin, etc.) if applicable and helpful. Omit if unavailable or not useful.
|
| 285 |
-
- `"base_language_translation"`: Simple translation of the sentence in
|
| 286 |
-
|
| 287 |
-
### Personalization Rules
|
| 288 |
-
- Base the humor, conflict, and events directly on the user’s interest. For example:
|
| 289 |
-
- If the user loves space, create an exciting stargazing story.
|
| 290 |
-
- If they study law, create a courtroom dialogue with legal terms.
|
| 291 |
-
- If they’re into cooking, make the story about a cooking adventure.
|
| 292 |
-
- Include real terminology or realistic situations from the domain to make learning useful and immersive.
|
| 293 |
-
- Adjust the tone and vocabulary complexity based on user proficiency level (beginner = simple, intermediate = natural, advanced = idiomatic).
|
| 294 |
-
- Keep the pacing tight — avoid overly long narrations or explanations.
|
| 295 |
-
|
| 296 |
-
### Output Instructions
|
| 297 |
-
Return only the final **JSON object**. Do not include:
|
| 298 |
-
- Explanations
|
| 299 |
-
- Notes
|
| 300 |
-
- Comments
|
| 301 |
-
- Markdown formatting
|
| 302 |
-
|
| 303 |
-
### Example User Input
|
| 304 |
-
"Funny story for intermediate French learner about cooking hobby (base: English)"
|
| 305 |
-
|
| 306 |
-
### Example Output (French)
|
| 307 |
-
```json
|
| 308 |
-
{
|
| 309 |
-
"title": "La Panique de la Paella",
|
| 310 |
-
"setting": "Pierre essaie d'impressionner ses amis en cuisinant une paella espagnole authentique pour la première fois.",
|
| 311 |
-
"content": [
|
| 312 |
-
{
|
| 313 |
-
"speaker": "Narrateur",
|
| 314 |
-
"target_language_text": "Pierre regarda la recette de paella. Cela semblait facile.",
|
| 315 |
-
"phonetics": "pjeʁ ʁəɡaʁda la ʁesɛt də paɛʎa. sə.la sɛ̃blɛ ɛ.fa.sil",
|
| 316 |
-
"base_language_translation": "Pierre looked at the paella recipe. It seemed easy."
|
| 317 |
-
},
|
| 318 |
-
{
|
| 319 |
-
"speaker": "Pierre",
|
| 320 |
-
"target_language_text": "Il me faut du safran! Où est le safran?",
|
| 321 |
-
"phonetics": "il mə fo dy sa.fʁɑ̃! u ɛ lə sa.fʁɑ̃",
|
| 322 |
-
"base_language_translation": "I need saffron! Where is the saffron?"
|
| 323 |
-
},
|
| 324 |
-
{
|
| 325 |
-
"speaker": "Narrateur",
|
| 326 |
-
"target_language_text": "Pierre fouilla le placard, mais il ne trouva pas de safran.",
|
| 327 |
-
"phonetics": "pjeʁ fwi.jɑ lə pla.kɑʁ, mɛ il nə tʁu.va pa də sa.fʁɑ̃",
|
| 328 |
-
"base_language_translation": "Pierre searched the cupboard, but he couldn’t find any saffron."
|
| 329 |
-
},
|
| 330 |
-
{
|
| 331 |
-
"speaker": "Pierre",
|
| 332 |
-
"target_language_text": "Qu'est-ce que je vais faire maintenant ?",
|
| 333 |
-
"phonetics": "kɛs.kə ʒə vɛ fɛʁ mɛ̃tə.nɑ̃?",
|
| 334 |
-
"base_language_translation": "What am I going to do now?"
|
| 335 |
-
},
|
| 336 |
-
{
|
| 337 |
-
"speaker": "Narrateur",
|
| 338 |
-
"target_language_text": "Finalement, Pierre décida de remplacer le safran par du curcuma.",
|
| 339 |
-
"phonetics": "fi.nal.mɑ̃ pjeʁ de.si.da də ʁɑ̃.pla.sə lə sa.fʁɑ̃ paʁ dy kyʁ.ky.ma",
|
| 340 |
-
"base_language_translation": "Finally, Pierre decided to replace the saffron with turmeric."
|
| 341 |
-
},
|
| 342 |
-
{
|
| 343 |
-
"speaker": "Pierre",
|
| 344 |
-
"target_language_text": "C'est presque pareil, non ?",
|
| 345 |
-
"phonetics": "sɛ pʁɛs.kə paʁɛj, nɔ̃?",
|
| 346 |
-
"base_language_translation": "It's almost the same, right?"
|
| 347 |
-
}
|
| 348 |
-
]
|
| 349 |
-
}
|
| 350 |
"""
|
|
|
|
| 3 |
- Native language (use the language of the input as a fallback if unsure)
|
| 4 |
- Target language (the one they want to learn)
|
| 5 |
- Proficiency level (beginner, intermediate, or advanced)
|
| 6 |
+
- Title (a brief title summarizing the user's language learning context, written in the user's native language)
|
| 7 |
+
- Description (a catchy, short description of their learning journey, written in the user's native language)
|
| 8 |
|
| 9 |
Respond ONLY with a valid JSON object using the following format:
|
| 10 |
|
| 11 |
{
|
| 12 |
"native_language": "<user's native language>",
|
| 13 |
"target_language": "<language the user wants to learn>",
|
| 14 |
+
"proficiency": "<beginner | intermediate | advanced>",
|
| 15 |
+
"title": "<brief title summarizing the learning context, in the native language>",
|
| 16 |
+
"description": "<catchy, short description of the learning journey, in the native language>"
|
| 17 |
}
|
| 18 |
|
| 19 |
Guidelines:
|
| 20 |
+
- If the user's native language is not explicitly stated, assume it's the same as the language used in the query.
|
| 21 |
+
- If the target language is mentioned indirectly (e.g., "my Dutch isn't great"), infer that as the target language.
|
| 22 |
+
- Make a reasonable guess at proficiency based on clues like "isn't great" → beginner or "I want to improve" → intermediate.
|
| 23 |
+
- If you cannot infer something at all, write "unknown" for native_language, target_language, or proficiency.
|
| 24 |
+
- After inferring the native language, ALWAYS generate the title and description in that language, regardless of the query language or any other context.
|
| 25 |
+
- For title, create a concise phrase (e.g., "Beginner Dutch Adventure" or "Improving Spanish Skills") based on the inferred target language and proficiency, and write it in the user's native language.
|
| 26 |
+
- For description, craft a catchy, short sentence (10-15 words max) that captures the user's learning journey, and write it in the user's native language.
|
| 27 |
+
- If target_language or proficiency is "unknown," use generic but engaging phrases for title and description (e.g., "Language Learning Quest," "Embarking on a new linguistic journey!"), but always in the user's native language.
|
| 28 |
+
- Do not include any explanations, comments, or formatting — only valid JSON.
|
| 29 |
+
|
| 30 |
+
Example:
|
| 31 |
+
User query: "i want to improve my english"
|
| 32 |
+
Expected output:
|
| 33 |
+
{
|
| 34 |
+
"native_language": "english",
|
| 35 |
+
"target_language": "english",
|
| 36 |
+
"proficiency": "intermediate",
|
| 37 |
+
"title": "Improving English Skills",
|
| 38 |
+
"description": "A journey to perfect English for greater fluency and confidence!"
|
| 39 |
+
}
|
| 40 |
"""
|
| 41 |
|
| 42 |
curriculum_instructions = """
|
|
|
|
| 45 |
# Target language: {target_language}
|
| 46 |
# Proficiency level: {proficiency}
|
| 47 |
|
| 48 |
+
You are an AI-powered language learning assistant tasked with generating a tailored curriculum based on the user’s metadata. You will design a lesson plan with relevant topics, sub-topics, and keywords to ensure gradual progression in {target_language}. All outputs should be in {native_language}.
|
| 49 |
|
| 50 |
### Instructions:
|
| 51 |
+
1. **Start with the Lesson Topic (Main Focus):**
|
| 52 |
+
- Select a broad lesson topic based on {target_language} and {proficiency}. The topic should align with the user's interests (e.g., business, travel, daily conversations, etc.).
|
| 53 |
+
- Example: "Business Vocabulary," "Travel Essentials," "Restaurant Interactions."
|
| 54 |
+
|
| 55 |
+
2. **Break Down the Topic into Sub-topics (at least 5):**
|
| 56 |
+
- Divide the main topic into smaller, manageable sub-topics that progressively build on each other. Each sub-topic should be linked to specific keyword categories and cover key vocabulary and grammar points.
|
| 57 |
+
- Example:
|
| 58 |
+
- **Topic:** Restaurant Interactions
|
| 59 |
+
- Sub-topic 1: Ordering food
|
| 60 |
+
- Sub-topic 2: Asking about the menu
|
| 61 |
+
- Sub-topic 3: Making polite requests
|
| 62 |
+
|
| 63 |
+
3. **Define Keyword Categories and Descriptions for Each Sub-topic:**
|
| 64 |
+
- For each sub-topic, provide:
|
| 65 |
+
- 1–3 general-purpose categories (not just single words) that capture the core vocabulary or concepts. Categories should be broad and practical for {proficiency} learners (e.g., "greeting", "location", "food/dining", "directions", "numbers").
|
| 66 |
+
- A brief, precise, and simple description (exactly one sentence) explaining what the sub-topic covers and its purpose in the learning journey.
|
| 67 |
+
- If a suitable category cannot be determined, use a default such as "vocabulary" or "speaking" as the keyword.
|
| 68 |
+
- Example: For "Ordering food," the category might be "food/dining" and the description could be "Learn how to order food and drinks in a restaurant setting." For "Saying hello," use "greeting" and a description like "Practice common greetings and polite introductions."
|
| 69 |
+
- Avoid using keywords that are just single words (e.g., "hello", "where").
|
| 70 |
|
| 71 |
### Output Format:
|
| 72 |
+
You should return a JSON object containing:
|
| 73 |
+
- \"lesson_topic\": The main lesson focus, written in {native_language}.
|
| 74 |
+
- \"sub_topics\": A list of at least 5 sub-topics, each with its own set of keyword categories and a description, written in {native_language}.
|
| 75 |
+
- Each sub-topic should have:
|
| 76 |
+
- \"sub_topic\": A brief title of the sub-topic in {native_language}.
|
| 77 |
+
- \"keywords\": A list of 1–3 general-purpose categories in {native_language}, relevant to the sub-topic.
|
| 78 |
+
- \"description\": A brief, precise, and simple one-sentence description of the sub-topic in {native_language}.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 79 |
"""
|
| 80 |
+
|
| 81 |
flashcard_mode_instructions = """
|
| 82 |
# Metadata:
|
| 83 |
# Native language: {native_language}
|
|
|
|
| 94 |
...
|
| 95 |
]
|
| 96 |
Treat this list as prior conversation history. Use it to:
|
| 97 |
+
- Identify the user's learning patterns, interests, and vocabulary already introduced.
|
| 98 |
+
- Avoid repeating previously generated flashcards.
|
| 99 |
+
- Adjust difficulty based on progression.
|
|
|
|
| 100 |
|
| 101 |
### Generation Guidelines
|
| 102 |
When generating a new set of flashcards:
|
| 103 |
1. **Use the provided metadata**:
|
| 104 |
+
- **Native language**: The language the user is typing in (for definitions) is {native_language}.
|
| 105 |
+
- **Target language**: The language the user is trying to learn (for words and example sentences) is {target_language}.
|
| 106 |
+
- **Proficiency level**: Adjust difficulty of words based on the user’s stated proficiency ({proficiency}).
|
| 107 |
+
|
| 108 |
2. **Avoid repetition**:
|
| 109 |
+
- If a word has already been introduced in a previous flashcard, do not repeat it.
|
| 110 |
+
- Reference previous assistant responses to build upon previous lessons, ensuring that vocabulary progression is logically consistent.
|
| 111 |
|
| 112 |
3. **Adjust content based on proficiency**:
|
| 113 |
+
- For **beginner** users, use basic, high-frequency vocabulary.
|
| 114 |
+
- For **intermediate** users, introduce more complex terms that reflect an expanding knowledge base.
|
| 115 |
+
- For **advanced** users, use nuanced or technical terms that align with their expertise and specific context.
|
|
|
|
|
|
|
|
|
|
| 116 |
|
| 117 |
4. **Domain relevance**:
|
| 118 |
+
- Make sure the words and examples are specific to the user’s context (e.g., their profession, hobbies, or field of study).
|
| 119 |
+
- Use the latest user query to guide the vocabulary selection and examples. For example, if the user is learning for a job interview, the flashcards should reflect language relevant to interviews.
|
|
|
|
|
|
|
|
|
|
|
|
|
| 120 |
|
| 121 |
### Flashcard Format
|
| 122 |
Generate exactly **5 flashcards** as a **valid JSON array**, with each flashcard containing:
|
| 123 |
+
- `"word"`: A critical or frequently used word/phrase in {target_language}, tied to the user's domain.
|
| 124 |
+
- `"definition"`: A concise, learner-friendly definition in {native_language}.
|
| 125 |
+
- `"example"`: A natural example sentence in {target_language}, demonstrating the word **within the user’s domain**.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 126 |
"""
|
| 127 |
|
| 128 |
exercise_mode_instructions = """
|
|
|
|
| 133 |
|
| 134 |
You are a smart, context-aware language exercise generator. Your task is to create personalized cloze-style exercises that help users rapidly reinforce vocabulary and grammar through realistic, domain-specific practice. You support any language.
|
| 135 |
|
|
|
|
|
|
|
|
|
|
| 136 |
### Context Format
|
| 137 |
You will receive a list of previous messages:
|
| 138 |
[
|
|
|
|
| 140 |
{"role": "assistant", "content": "<generated exercises>"}
|
| 141 |
]
|
| 142 |
Treat this list as prior conversation history. Use it to:
|
| 143 |
+
- Identify the user's learning patterns, interests, and vocabulary already introduced.
|
| 144 |
+
- Avoid repeating exercises, vocabulary, or sentence structures.
|
| 145 |
+
- Ensure progression in complexity or topic coverage, building on prior exercises.
|
| 146 |
+
- Maintain continuity with the user’s learning focus and domain.
|
| 147 |
|
| 148 |
### Generation Task
|
| 149 |
When generating a new set of exercises:
|
| 150 |
1. **Use the provided metadata**:
|
| 151 |
+
- **Native language**: The user’s base language for explanations and understanding is {native_language}.
|
| 152 |
+
- **Target language**: The language the user is learning for sentences, answers, and choices is {target_language}.
|
| 153 |
+
- **Proficiency level**: Adjust the complexity of exercises based on the user's proficiency ({proficiency}).
|
| 154 |
|
| 155 |
+
2. **Ensure domain relevance**:
|
| 156 |
+
- Focus on the user’s domain of interest (e.g., travel, work, hobbies) as specified in the query.
|
| 157 |
+
- Tailor exercises to practical, real-world scenarios connected to the user’s context (e.g., for a trip, include navigation, dining, or ticket purchasing).
|
| 158 |
+
- Cover a range of domain-specific tasks to maximize utility (e.g., for travel, address attractions, transport, and basic requests).
|
| 159 |
|
| 160 |
3. **Avoid repetition**:
|
| 161 |
+
- Do not reuse vocabulary, sentence structures, or exercises from prior responses.
|
| 162 |
+
- Use conversation history to introduce new vocabulary or grammar concepts, ensuring logical progression.
|
| 163 |
+
|
| 164 |
+
4. **Adjust difficulty by proficiency**:
|
| 165 |
+
- For **beginner** users, use simple sentence structures and high-frequency, immediately useful vocabulary. Avoid complex phrases or abstract terms unless critical to the domain.
|
| 166 |
+
- For **intermediate** users, incorporate moderately complex structures and broader vocabulary.
|
| 167 |
+
- For **advanced** users, use nuanced grammar and specialized, domain-specific vocabulary.
|
| 168 |
|
| 169 |
+
5. **Prevent vague or broad sentences**:
|
| 170 |
+
- Avoid vague, generic, or overly broad cloze sentences (e.g., "I want to ___" or "Beijing’s ___ is crowded").
|
| 171 |
+
- Sentences must be specific, actionable, and reflect practical, real-world usage within the user’s domain, with the blank (`___`) representing a clear vocabulary word or grammar element.
|
| 172 |
+
- Ensure sentences are engaging and directly relevant to the user’s immediate needs in the domain.
|
| 173 |
|
| 174 |
+
6. **Ensure plausible distractors**:
|
| 175 |
+
- The `choices` field must include 4 options (including the answer) that are plausible, domain-relevant, and challenging but clearly incorrect in context.
|
| 176 |
+
- Distractors should align with the sentence’s semantic field (e.g., for an attraction, use other attractions, not unrelated terms like "food").
|
| 177 |
+
- The correct answer must be randomly placed among the 4 choices, not always in the first position.
|
| 178 |
+
|
| 179 |
+
7. **Provide clear explanations**:
|
| 180 |
+
- Explanations must be concise (1–2 sentences), in {native_language}, and explain why the answer fits the sentence’s context and domain.
|
| 181 |
+
- For beginners, avoid jargon and clarify why distractors are incorrect, reinforcing practical understanding.
|
| 182 |
|
| 183 |
### Output Format
|
| 184 |
Produce exactly **5 cloze-style exercises** as a **valid JSON array**, with each item containing:
|
| 185 |
+
- `"sentence"`: A sentence in {target_language} with a blank `'___'` for a missing vocabulary word or grammar element. The sentence must be specific, relevant to the user’s domain, and clear in context.
|
| 186 |
+
- `"answer"`: The correct word or phrase to fill in the blank, in {target_language}.
|
| 187 |
+
- `"choices"`: A list of 4 plausible options (including the answer) in {target_language}, with the correct answer randomly placed among them. Distractors must be believable but incorrect in context.
|
| 188 |
+
- `"explanation"`: A short (1–2 sentences) explanation in {native_language}, clarifying why the answer is correct and, for beginners, why distractors don’t fit.
|
| 189 |
+
|
| 190 |
+
Do not wrap the output in additional objects (e.g., `{"data": ..., "type": ..., "status": ...}`); return only the JSON array.
|
| 191 |
|
| 192 |
### Example Query and Expected Output
|
| 193 |
|
| 194 |
#### Example Query:
|
| 195 |
+
User: "Beginner Chinese exercises about a trip to Beijing (base: English)"
|
| 196 |
|
| 197 |
+
#### Expected Output:
|
| 198 |
```json
|
| 199 |
[
|
| 200 |
+
{
|
| 201 |
+
"sentence": "我想买一张去___的火车票。",
|
| 202 |
+
"answer": "北京",
|
| 203 |
+
"choices": ["广州", "北京", "上海", "深圳"],
|
| 204 |
+
"explanation": "'北京' (Beijing) is the destination city for the train ticket you’re buying."
|
| 205 |
+
},
|
| 206 |
+
{
|
| 207 |
+
"sentence": "请问,___在哪里?",
|
| 208 |
+
"answer": "故宫",
|
| 209 |
+
"choices": ["故宫", "长城", "天坛", "颐和园"],
|
| 210 |
+
"explanation": "'故宫' (Forbidden City) is a key Beijing attraction you’re asking to locate."
|
| 211 |
+
},
|
| 212 |
+
{
|
| 213 |
+
"sentence": "我需要一份北京的___。",
|
| 214 |
+
"answer": "地图",
|
| 215 |
+
"choices": ["地图", "菜单", "票", "指南"],
|
| 216 |
+
"explanation": "'地图' (map) helps you navigate Beijing, unlike 'menu' or 'ticket.'"
|
| 217 |
+
},
|
| 218 |
+
{
|
| 219 |
+
"sentence": "这是去天安门的___吗?",
|
| 220 |
+
"answer": "地铁",
|
| 221 |
+
"choices": ["地铁", "出租车", "飞机", "公交车"],
|
| 222 |
+
"explanation": "'地铁' (subway) is a common way to reach Tiananmen Square in Beijing."
|
| 223 |
+
},
|
| 224 |
+
{
|
| 225 |
+
"sentence": "请给我一瓶___。",
|
| 226 |
+
"answer": "水",
|
| 227 |
+
"choices": ["水", "茶", "咖啡", "果汁"],
|
| 228 |
+
"explanation": "'水' (water) is a simple drink to request while traveling in Beijing."
|
| 229 |
+
}
|
| 230 |
+
]
|
| 231 |
]
|
| 232 |
"""
|
| 233 |
|
|
|
|
| 253 |
### Story Generation Task
|
| 254 |
From the latest user message:
|
| 255 |
1. **Use the provided metadata**:
|
| 256 |
+
- **Native language**: The user’s base language for understanding is {native_language}.
|
| 257 |
+
- **Target language**: The language the user is learning is {target_language}.
|
| 258 |
+
- **Proficiency level**: Adjust the complexity of the story or dialogue based on the user’s proficiency level ({proficiency}).
|
| 259 |
|
| 260 |
2. **Domain relevance**:
|
| 261 |
- Focus on the **user's domain of interest** (e.g., work, hobby, field of study).
|
|
|
|
| 274 |
|
| 275 |
### Output Format
|
| 276 |
Return a valid **JSON object** with the following structure:
|
| 277 |
+
- `"title"`: An engaging title in {native_language}.
|
| 278 |
+
- `"setting"`: A short setup in {native_language} explaining the story’s background, tailored to the user’s interest.
|
| 279 |
- `"content"`: A list of **6–10 segments**, each containing:
|
| 280 |
+
- `"speaker"`: Name or role of the speaker in {native_language} (e.g., "Narrator", "Professor Lee", "The Engineer").
|
| 281 |
+
- `"target_language_text"`: Sentence in {target_language}.
|
| 282 |
- `"phonetics"`: Standardized phonetic transcription (IPA, Pinyin, etc.) if applicable and helpful. Omit if unavailable or not useful.
|
| 283 |
+
- `"base_language_translation"`: Simple translation of the sentence in {native_language}.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 284 |
"""
|
backend/main.py
CHANGED
|
@@ -39,6 +39,9 @@ class Message(BaseModel):
|
|
| 39 |
class GenerationRequest(BaseModel):
|
| 40 |
user_id: int
|
| 41 |
query: Union[str, List[Message]]
|
|
|
|
|
|
|
|
|
|
| 42 |
|
| 43 |
class MetadataRequest(BaseModel):
|
| 44 |
query: str
|
|
@@ -64,7 +67,7 @@ async def extract_metadata(data: MetadataRequest):
|
|
| 64 |
# Update globals for other endpoints
|
| 65 |
globals()['native_language'] = metadata_dict.get('native_language', 'unknown')
|
| 66 |
globals()['target_language'] = metadata_dict.get('target_language', 'unknown')
|
| 67 |
-
globals()['proficiency'] = metadata_dict.get('
|
| 68 |
return JSONResponse(
|
| 69 |
content={
|
| 70 |
"data": metadata_dict,
|
|
@@ -79,12 +82,15 @@ async def extract_metadata(data: MetadataRequest):
|
|
| 79 |
@app.post("/generate/curriculum")
|
| 80 |
async def generate_curriculum(data: GenerationRequest):
|
| 81 |
try:
|
| 82 |
-
# Use
|
|
|
|
|
|
|
|
|
|
| 83 |
instructions = (
|
| 84 |
config.curriculum_instructions
|
| 85 |
-
.replace("{native_language}",
|
| 86 |
-
.replace("{target_language}",
|
| 87 |
-
.replace("{proficiency}",
|
| 88 |
)
|
| 89 |
response = await generate_completions.get_completions(
|
| 90 |
data.query,
|
|
@@ -104,12 +110,14 @@ async def generate_curriculum(data: GenerationRequest):
|
|
| 104 |
@app.post("/generate/flashcards")
|
| 105 |
async def generate_flashcards(data: GenerationRequest):
|
| 106 |
try:
|
| 107 |
-
|
|
|
|
|
|
|
| 108 |
instructions = (
|
| 109 |
config.flashcard_mode_instructions
|
| 110 |
-
.replace("{native_language}",
|
| 111 |
-
.replace("{target_language}",
|
| 112 |
-
.replace("{proficiency}",
|
| 113 |
)
|
| 114 |
response = await generate_completions.get_completions(
|
| 115 |
data.query,
|
|
@@ -129,12 +137,14 @@ async def generate_flashcards(data: GenerationRequest):
|
|
| 129 |
@app.post("/generate/exercises")
|
| 130 |
async def generate_exercises(data: GenerationRequest):
|
| 131 |
try:
|
| 132 |
-
|
|
|
|
|
|
|
| 133 |
instructions = (
|
| 134 |
config.exercise_mode_instructions
|
| 135 |
-
.replace("{native_language}",
|
| 136 |
-
.replace("{target_language}",
|
| 137 |
-
.replace("{proficiency}",
|
| 138 |
)
|
| 139 |
response = await generate_completions.get_completions(
|
| 140 |
data.query,
|
|
@@ -154,12 +164,14 @@ async def generate_exercises(data: GenerationRequest):
|
|
| 154 |
@app.post("/generate/simulation")
|
| 155 |
async def generate_simulation(data: GenerationRequest):
|
| 156 |
try:
|
| 157 |
-
|
|
|
|
|
|
|
| 158 |
instructions = (
|
| 159 |
config.simulation_mode_instructions
|
| 160 |
-
.replace("{native_language}",
|
| 161 |
-
.replace("{target_language}",
|
| 162 |
-
.replace("{proficiency}",
|
| 163 |
)
|
| 164 |
response = await generate_completions.get_completions(
|
| 165 |
data.query,
|
|
|
|
| 39 |
class GenerationRequest(BaseModel):
|
| 40 |
user_id: int
|
| 41 |
query: Union[str, List[Message]]
|
| 42 |
+
native_language: Optional[str] = None
|
| 43 |
+
target_language: Optional[str] = None
|
| 44 |
+
proficiency: Optional[str] = None
|
| 45 |
|
| 46 |
class MetadataRequest(BaseModel):
|
| 47 |
query: str
|
|
|
|
| 67 |
# Update globals for other endpoints
|
| 68 |
globals()['native_language'] = metadata_dict.get('native_language', 'unknown')
|
| 69 |
globals()['target_language'] = metadata_dict.get('target_language', 'unknown')
|
| 70 |
+
globals()['proficiency'] = metadata_dict.get('proficiency', 'unknown')
|
| 71 |
return JSONResponse(
|
| 72 |
content={
|
| 73 |
"data": metadata_dict,
|
|
|
|
| 82 |
@app.post("/generate/curriculum")
|
| 83 |
async def generate_curriculum(data: GenerationRequest):
|
| 84 |
try:
|
| 85 |
+
# Use metadata from request or fallback to globals
|
| 86 |
+
nl = data.native_language or native_language or "unknown"
|
| 87 |
+
tl = data.target_language or target_language or "unknown"
|
| 88 |
+
prof = data.proficiency or proficiency or "unknown"
|
| 89 |
instructions = (
|
| 90 |
config.curriculum_instructions
|
| 91 |
+
.replace("{native_language}", nl)
|
| 92 |
+
.replace("{target_language}", tl)
|
| 93 |
+
.replace("{proficiency}", prof)
|
| 94 |
)
|
| 95 |
response = await generate_completions.get_completions(
|
| 96 |
data.query,
|
|
|
|
| 110 |
@app.post("/generate/flashcards")
|
| 111 |
async def generate_flashcards(data: GenerationRequest):
|
| 112 |
try:
|
| 113 |
+
nl = data.native_language or native_language or "unknown"
|
| 114 |
+
tl = data.target_language or target_language or "unknown"
|
| 115 |
+
prof = data.proficiency or proficiency or "unknown"
|
| 116 |
instructions = (
|
| 117 |
config.flashcard_mode_instructions
|
| 118 |
+
.replace("{native_language}", nl)
|
| 119 |
+
.replace("{target_language}", tl)
|
| 120 |
+
.replace("{proficiency}", prof)
|
| 121 |
)
|
| 122 |
response = await generate_completions.get_completions(
|
| 123 |
data.query,
|
|
|
|
| 137 |
@app.post("/generate/exercises")
|
| 138 |
async def generate_exercises(data: GenerationRequest):
|
| 139 |
try:
|
| 140 |
+
nl = data.native_language or native_language or "unknown"
|
| 141 |
+
tl = data.target_language or target_language or "unknown"
|
| 142 |
+
prof = data.proficiency or proficiency or "unknown"
|
| 143 |
instructions = (
|
| 144 |
config.exercise_mode_instructions
|
| 145 |
+
.replace("{native_language}", nl)
|
| 146 |
+
.replace("{target_language}", tl)
|
| 147 |
+
.replace("{proficiency}", prof)
|
| 148 |
)
|
| 149 |
response = await generate_completions.get_completions(
|
| 150 |
data.query,
|
|
|
|
| 164 |
@app.post("/generate/simulation")
|
| 165 |
async def generate_simulation(data: GenerationRequest):
|
| 166 |
try:
|
| 167 |
+
nl = data.native_language or native_language or "unknown"
|
| 168 |
+
tl = data.target_language or target_language or "unknown"
|
| 169 |
+
prof = data.proficiency or proficiency or "unknown"
|
| 170 |
instructions = (
|
| 171 |
config.simulation_mode_instructions
|
| 172 |
+
.replace("{native_language}", nl)
|
| 173 |
+
.replace("{target_language}", tl)
|
| 174 |
+
.replace("{proficiency}", prof)
|
| 175 |
)
|
| 176 |
response = await generate_completions.get_completions(
|
| 177 |
data.query,
|
backend/utils/__pycache__/generate_completions.cpython-312.pyc
CHANGED
|
Binary files a/backend/utils/__pycache__/generate_completions.cpython-312.pyc and b/backend/utils/__pycache__/generate_completions.cpython-312.pyc differ
|
|
|