""" 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