Implement role detection service with pattern matching
- Created RoleDetector class with colon and bracket pattern extraction - Implemented role deduplication logic - Added fallback to default 'Narrator' role when no patterns found - Created /api/tts/roles endpoint using RoleDetector - Added comprehensive test suite for role detection - All tests passing (7/7) Requirements: 2.1, 2.2, 2.3, 2.4, 2.5, 2.6
This commit is contained in:
93
backend/services/role_detector.py
Normal file
93
backend/services/role_detector.py
Normal file
@@ -0,0 +1,93 @@
|
||||
"""
|
||||
Role detection service for identifying distinct speakers in text.
|
||||
"""
|
||||
import re
|
||||
from typing import List, Set, Dict
|
||||
|
||||
|
||||
class RoleDetector:
|
||||
"""
|
||||
Service for detecting distinct speaker roles in text.
|
||||
|
||||
Supports two pattern types:
|
||||
1. Colon pattern: "RoleName:" at the start of a line
|
||||
2. Bracket pattern: "[RoleName]" preceding dialogue
|
||||
"""
|
||||
|
||||
# Regex patterns for role detection
|
||||
COLON_PATTERN = r'^([A-Z][a-zA-Z\s]+?):\s'
|
||||
BRACKET_PATTERN = r'\[([A-Z][a-zA-Z\s]+?)\]'
|
||||
DEFAULT_ROLE = "Narrator"
|
||||
|
||||
def detect_roles(self, text: str) -> List[Dict[str, str]]:
|
||||
"""
|
||||
Analyzes text to identify distinct speaker roles.
|
||||
|
||||
Args:
|
||||
text: Input text to analyze
|
||||
|
||||
Returns:
|
||||
List of role dictionaries with 'id' and 'label' fields.
|
||||
Returns default "Narrator" role if no patterns found.
|
||||
"""
|
||||
if not text or not text.strip():
|
||||
return [{"id": self.DEFAULT_ROLE, "label": self.DEFAULT_ROLE}]
|
||||
|
||||
# Extract roles from both patterns
|
||||
colon_roles = self._extract_colon_pattern(text)
|
||||
bracket_roles = self._extract_bracket_pattern(text)
|
||||
|
||||
# Combine and deduplicate
|
||||
all_roles = colon_roles.union(bracket_roles)
|
||||
|
||||
# If no roles found, return default
|
||||
if not all_roles:
|
||||
return [{"id": self.DEFAULT_ROLE, "label": self.DEFAULT_ROLE}]
|
||||
|
||||
# Convert to role dictionaries and sort for consistent ordering
|
||||
role_list = [
|
||||
{"id": role.strip(), "label": role.strip()}
|
||||
for role in sorted(all_roles)
|
||||
]
|
||||
|
||||
return role_list
|
||||
|
||||
def _extract_colon_pattern(self, text: str) -> Set[str]:
|
||||
"""
|
||||
Extracts roles from "RoleName:" pattern at line starts.
|
||||
|
||||
Args:
|
||||
text: Input text to analyze
|
||||
|
||||
Returns:
|
||||
Set of role names found
|
||||
"""
|
||||
roles = set()
|
||||
pattern = re.compile(self.COLON_PATTERN, re.MULTILINE)
|
||||
|
||||
for match in pattern.finditer(text):
|
||||
role_name = match.group(1).strip()
|
||||
if role_name:
|
||||
roles.add(role_name)
|
||||
|
||||
return roles
|
||||
|
||||
def _extract_bracket_pattern(self, text: str) -> Set[str]:
|
||||
"""
|
||||
Extracts roles from "[RoleName]" pattern.
|
||||
|
||||
Args:
|
||||
text: Input text to analyze
|
||||
|
||||
Returns:
|
||||
Set of role names found
|
||||
"""
|
||||
roles = set()
|
||||
pattern = re.compile(self.BRACKET_PATTERN)
|
||||
|
||||
for match in pattern.finditer(text):
|
||||
role_name = match.group(1).strip()
|
||||
if role_name:
|
||||
roles.add(role_name)
|
||||
|
||||
return roles
|
||||
Reference in New Issue
Block a user