Spaces:
Sleeping
Sleeping
Update app.py
Browse files
app.py
CHANGED
|
@@ -766,49 +766,75 @@ def handle_get_speaking_sentence(data):
|
|
| 766 |
Frame 5: Return a sentence for the user to repeat aloud.
|
| 767 |
The reference_text field is ready to pass directly to assess_pronunciation.
|
| 768 |
|
| 769 |
-
Emit: { "grammar_rule": "copula", "
|
| 770 |
Response: { "grammar_rule", "sentence": {korean, english, difficulty},
|
| 771 |
"sentence_index", "total_sentences",
|
| 772 |
"instruction", "reference_text" }
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 773 |
"""
|
| 774 |
grammar_rule = (data or {}).get("grammar_rule", "")
|
| 775 |
-
difficulty
|
| 776 |
exclude_ids = set(str(i) for i in (data or {}).get("exclude_ids", []))
|
|
|
|
| 777 |
if not grammar_rule:
|
| 778 |
emit('speaking_sentence', {"error": "grammar_rule is required"})
|
| 779 |
return
|
| 780 |
|
| 781 |
-
logger.info(f"🗣️ Speaking sentence: rule={grammar_rule}
|
| 782 |
-
|
|
|
|
|
|
|
|
|
|
| 783 |
|
| 784 |
if not sentences:
|
|
|
|
| 785 |
examples = get_example_sentences(grammar_rule)
|
| 786 |
if examples:
|
| 787 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 788 |
emit('speaking_sentence', {
|
| 789 |
-
"grammar_rule":
|
| 790 |
-
"sentence":
|
| 791 |
-
"sentence_index":
|
| 792 |
-
"
|
| 793 |
-
"
|
|
|
|
| 794 |
})
|
| 795 |
return
|
| 796 |
emit('speaking_sentence', {"error": f"No speaking sentences for rule: {grammar_rule}"})
|
| 797 |
return
|
| 798 |
|
| 799 |
-
|
| 800 |
available = [(i, s) for i, s in enumerate(sentences) if str(i) not in exclude_ids]
|
| 801 |
if not available:
|
|
|
|
| 802 |
available = list(enumerate(sentences))
|
|
|
|
|
|
|
| 803 |
idx, sentence = random.choice(available)
|
|
|
|
|
|
|
| 804 |
|
| 805 |
emit('speaking_sentence', {
|
| 806 |
-
"grammar_rule":
|
| 807 |
-
"sentence":
|
| 808 |
-
"sentence_index":
|
| 809 |
"total_sentences": len(sentences),
|
| 810 |
-
"instruction":
|
| 811 |
-
"reference_text":
|
| 812 |
})
|
| 813 |
|
| 814 |
|
|
|
|
| 766 |
Frame 5: Return a sentence for the user to repeat aloud.
|
| 767 |
The reference_text field is ready to pass directly to assess_pronunciation.
|
| 768 |
|
| 769 |
+
Emit: { "grammar_rule": "copula", "exclude_ids": ["0", "2"] }
|
| 770 |
Response: { "grammar_rule", "sentence": {korean, english, difficulty},
|
| 771 |
"sentence_index", "total_sentences",
|
| 772 |
"instruction", "reference_text" }
|
| 773 |
+
|
| 774 |
+
NOTE: difficulty is intentionally NOT used as a filter here.
|
| 775 |
+
All sentences for the rule are pooled and sorted by difficulty ascending,
|
| 776 |
+
so easier sentences come first naturally. Filtering by difficulty caused
|
| 777 |
+
the pool to collapse to 1-2 sentences, making repeats unavoidable.
|
| 778 |
+
Use exclude_ids to track which sentences have been shown this session.
|
| 779 |
+
The server cycles back to the full pool once all sentences are excluded.
|
| 780 |
"""
|
| 781 |
grammar_rule = (data or {}).get("grammar_rule", "")
|
| 782 |
+
# difficulty param accepted but NOT used as a hard filter — see docstring
|
| 783 |
exclude_ids = set(str(i) for i in (data or {}).get("exclude_ids", []))
|
| 784 |
+
|
| 785 |
if not grammar_rule:
|
| 786 |
emit('speaking_sentence', {"error": "grammar_rule is required"})
|
| 787 |
return
|
| 788 |
|
| 789 |
+
logger.info(f"🗣️ Speaking sentence: rule={grammar_rule} exclude={sorted(exclude_ids)}")
|
| 790 |
+
|
| 791 |
+
# Always fetch full pool — sorted by difficulty so easier sentences come first
|
| 792 |
+
sentences = get_speaking_sentences(grammar_rule, difficulty=None)
|
| 793 |
+
sentences = sorted(sentences, key=lambda s: s.get("difficulty", 1))
|
| 794 |
|
| 795 |
if not sentences:
|
| 796 |
+
# Last-resort fallback: use example sentences
|
| 797 |
examples = get_example_sentences(grammar_rule)
|
| 798 |
if examples:
|
| 799 |
+
# Cycle through examples using exclude_ids too
|
| 800 |
+
available_ex = [(i, ex) for i, ex in enumerate(examples)
|
| 801 |
+
if f"ex_{i}" not in exclude_ids]
|
| 802 |
+
if not available_ex:
|
| 803 |
+
available_ex = list(enumerate(examples))
|
| 804 |
+
import random
|
| 805 |
+
ex_idx, ex = random.choice(available_ex)
|
| 806 |
+
first = ex["positive"]
|
| 807 |
+
logger.warning(f"⚠️ No speaking sentences for {grammar_rule} — using example fallback ex_{ex_idx}")
|
| 808 |
emit('speaking_sentence', {
|
| 809 |
+
"grammar_rule": grammar_rule,
|
| 810 |
+
"sentence": {"korean": first["korean"], "english": first["english"], "difficulty": 1},
|
| 811 |
+
"sentence_index": f"ex_{ex_idx}",
|
| 812 |
+
"total_sentences": len(examples),
|
| 813 |
+
"instruction": "듣고 따라 말해 보세요! Listen and repeat.",
|
| 814 |
+
"reference_text": first["korean"],
|
| 815 |
})
|
| 816 |
return
|
| 817 |
emit('speaking_sentence', {"error": f"No speaking sentences for rule: {grammar_rule}"})
|
| 818 |
return
|
| 819 |
|
| 820 |
+
# Select next unshown sentence; wrap around once all are exhausted
|
| 821 |
available = [(i, s) for i, s in enumerate(sentences) if str(i) not in exclude_ids]
|
| 822 |
if not available:
|
| 823 |
+
logger.info(f"🗣️ All {len(sentences)} sentences shown — cycling back to start")
|
| 824 |
available = list(enumerate(sentences))
|
| 825 |
+
|
| 826 |
+
import random
|
| 827 |
idx, sentence = random.choice(available)
|
| 828 |
+
logger.info(f"🗣️ Serving sentence_index={idx} '{sentence['korean'][:20]}...' "
|
| 829 |
+
f"(pool={len(sentences)}, available={len(available)})")
|
| 830 |
|
| 831 |
emit('speaking_sentence', {
|
| 832 |
+
"grammar_rule": grammar_rule,
|
| 833 |
+
"sentence": sentence,
|
| 834 |
+
"sentence_index": str(idx),
|
| 835 |
"total_sentences": len(sentences),
|
| 836 |
+
"instruction": "듣고 따라 말해 보세요! Listen and repeat.",
|
| 837 |
+
"reference_text": sentence["korean"],
|
| 838 |
})
|
| 839 |
|
| 840 |
|