import hashlib
|
import random
|
from typing import Any
|
|
from app.config import settings
|
|
SCENE_CATALOG = [
|
("home_bedroom", "居家-卧室", "Let's talk about your morning routine."),
|
("home_kitchen", "居家-厨房", "What would you like to cook today?"),
|
("home_study", "居家-书房", "Shall we review your vocabulary?"),
|
("school", "校内", "How was your class today?"),
|
("commute", "通勤", "What do you see on your way?"),
|
("exercise", "运动", "How do you stay active?"),
|
("dining", "用餐", "What are you having for dinner?"),
|
]
|
|
GENERIC_GREETING = "Hello! How can I help you practice English today?"
|
|
|
class SceneEngine:
|
def __init__(self, threshold: float | None = None) -> None:
|
self.threshold = threshold or settings.scene_confidence_threshold
|
|
def _derive_seed(self, device_id: str, timestamp: int, hints: dict[str, Any]) -> int:
|
raw = f"{device_id}:{timestamp}:{hints.get('mode', '')}"
|
return int(hashlib.md5(raw.encode()).hexdigest()[:8], 16)
|
|
def analyze(
|
self,
|
device_id: str,
|
timestamp: int,
|
context_hints: dict[str, Any] | None = None,
|
) -> dict[str, Any]:
|
hints = context_hints or {}
|
rng = random.Random(self._derive_seed(device_id, timestamp, hints))
|
|
if hints.get("scene"):
|
scene_key = hints["scene"]
|
match = next((s for s in SCENE_CATALOG if s[0] == scene_key), None)
|
if match:
|
confidence = float(hints.get("confidence", 0.85))
|
return self._build_result(match, confidence)
|
|
idx = rng.randint(0, len(SCENE_CATALOG) - 1)
|
confidence = round(rng.uniform(0.55, 0.95), 2)
|
return self._build_result(SCENE_CATALOG[idx], confidence)
|
|
def _build_result(self, scene: tuple[str, str, str], confidence: float) -> dict[str, Any]:
|
scene_key, scene_label, prompt = scene
|
use_generic = confidence < self.threshold
|
return {
|
"scene": scene_label,
|
"scene_key": scene_key,
|
"confidence": confidence,
|
"greeting_strategy": "generic" if use_generic else "contextual",
|
"suggested_intent": GENERIC_GREETING if use_generic else prompt,
|
}
|