import uuid
|
from typing import AsyncIterator
|
|
from app.services.scene_engine import GENERIC_GREETING
|
|
|
class DialogueService:
|
def create_dialogue_id(self) -> str:
|
return str(uuid.uuid4())
|
|
async def stream_dialogue(
|
self,
|
dialogue_id: str,
|
user_text: str | None = None,
|
scene_prompt: str | None = None,
|
difficulty: str = "A2",
|
) -> AsyncIterator[dict]:
|
opening = scene_prompt or GENERIC_GREETING
|
chunks = [
|
{
|
"dialogue_id": dialogue_id,
|
"text": opening,
|
"audio_url": None,
|
"intent_type": "greeting",
|
"difficulty_level": difficulty,
|
}
|
]
|
|
if user_text:
|
feedback = self._evaluate_response(user_text)
|
chunks.append(
|
{
|
"dialogue_id": dialogue_id,
|
"text": feedback["text"],
|
"audio_url": None,
|
"intent_type": feedback["intent_type"],
|
"difficulty_level": difficulty,
|
}
|
)
|
if feedback["follow_up"]:
|
chunks.append(
|
{
|
"dialogue_id": dialogue_id,
|
"text": feedback["follow_up"],
|
"audio_url": None,
|
"intent_type": "question",
|
"difficulty_level": difficulty,
|
}
|
)
|
|
for chunk in chunks:
|
yield chunk
|
|
def _evaluate_response(self, text: str) -> dict:
|
normalized = text.strip()
|
if not normalized:
|
return {
|
"text": "I didn't catch that. Could you try again?",
|
"intent_type": "correction",
|
"follow_up": "Please repeat your answer slowly.",
|
}
|
|
if normalized[0].islower():
|
return {
|
"text": f'Good try! Remember to capitalize: "{normalized[0].upper()}{normalized[1:]}"',
|
"intent_type": "correction",
|
"follow_up": "Can you say the full sentence again?",
|
}
|
|
if not normalized.endswith((".", "!", "?")):
|
return {
|
"text": "Nice answer! Don't forget punctuation at the end.",
|
"intent_type": "praise",
|
"follow_up": "Tell me one more detail about it.",
|
}
|
|
return {
|
"text": "Great job! Your sentence looks correct.",
|
"intent_type": "praise",
|
"follow_up": "What would you do differently next time?",
|
}
|