# License: Apache-2.0 License # Created by: Patrick Lumbantobing, VertoX-AI # Copyright (c) 2026 VertoX-AI. All rights reserved. # # This work is licensed under the Apache-2.0 License. # To view a copy of this license, visit # https://www.apache.org/licenses/LICENSE-2.0 """Extract exactly the six contract boundary fields from validated alignments.""" from __future__ import annotations from dataclasses import dataclass from speech_text_data_aligners.core.errors import AlignmentValidationError from speech_text_data_aligners.core.models import AlignmentRequest, AlignmentResult from speech_text_data_aligners.core.validation import validate_alignment_result BOUNDARY_COLUMNS = ( "first_word_text", "first_word_start_s", "first_word_end_s", "last_word_text", "last_word_start_s", "last_word_end_s", ) @dataclass(frozen=True, slots=True) class BoundaryFields: """Hold original-facing first/last lexical surfaces and acoustic boundaries. Parameters ---------- first_word_text: Original surface of the first lexical word. first_word_start_s: Acoustic start of the first lexical word. first_word_end_s: Acoustic end of the first lexical word. last_word_text: Original surface of the last lexical word. last_word_start_s: Acoustic start of the last lexical word. last_word_end_s: Acoustic end of the last lexical word. """ first_word_text: str first_word_start_s: float first_word_end_s: float last_word_text: str last_word_start_s: float last_word_end_s: float def as_dict(self) -> dict[str, str | float]: """Return fields in the exact output-schema insertion order. Returns: A new ordered dictionary with the six contract column names. """ return { "first_word_text": self.first_word_text, "first_word_start_s": self.first_word_start_s, "first_word_end_s": self.first_word_end_s, "last_word_text": self.last_word_text, "last_word_start_s": self.last_word_start_s, "last_word_end_s": self.last_word_end_s, } def extract_boundary_fields( request: AlignmentRequest, result: AlignmentResult, ) -> BoundaryFields: """Validate a result and select its first/last lexical alignments. A one-word utterance intentionally uses the same record for both endpoints. Parameters ---------- request: Authoritative request used for semantic validation. result: Candidate complete result. Returns ------- Exactly six backend-neutral boundary values using original word surfaces. Raises ------ AlignmentValidationError: If validation fails or no aligned words exist. TranscriptError: If the authoritative transcript has no lexical words. """ validated = validate_alignment_result(request, result) if not validated.words: raise AlignmentValidationError("cannot extract boundaries from no words") first = validated.words[0] last = validated.words[-1] return BoundaryFields( first_word_text=first.lexical_word.text, first_word_start_s=first.start_s, first_word_end_s=first.end_s, last_word_text=last.lexical_word.text, last_word_start_s=last.start_s, last_word_end_s=last.end_s, )