Implemented support for the seriatim JSON schema for input transcripts

This commit is contained in:
2026-04-27 22:11:19 -05:00
parent b9eef0043b
commit 8cab965abf
2 changed files with 81 additions and 4 deletions

View File

@@ -8,7 +8,7 @@ from .errors import AuditaValidationError
class TranscriptSegment(BaseModel):
model_config = ConfigDict(extra="forbid")
model_config = ConfigDict(extra="ignore")
id: int = Field(ge=1)
speaker: StrictStr
@@ -50,7 +50,7 @@ class TranscriptSegment(BaseModel):
class SourceTranscriptSegment(BaseModel):
model_config = ConfigDict(extra="forbid")
model_config = ConfigDict(extra="ignore")
id: Optional[int] = Field(default=None, ge=1)
speaker: StrictStr
@@ -146,8 +146,9 @@ def validate_transcript_data(
data: Any,
require_sequential_ids: bool = True,
) -> List[TranscriptSegment]:
data = _extract_transcript_segments(data)
if not isinstance(data, list):
raise AuditaValidationError("Transcript must be a JSON array.")
raise AuditaValidationError("Transcript must be a JSON array or an object with a segments array.")
if not data:
raise AuditaValidationError("Transcript must contain at least one segment.")
try:
@@ -160,8 +161,9 @@ def validate_transcript_data(
def validate_source_transcript_data(data: Any) -> List[SourceTranscriptSegment]:
data = _extract_transcript_segments(data)
if not isinstance(data, list):
raise AuditaValidationError("Transcript must be a JSON array.")
raise AuditaValidationError("Transcript must be a JSON array or an object with a segments array.")
if not data:
raise AuditaValidationError("Transcript must contain at least one segment.")
try:
@@ -215,6 +217,12 @@ def source_transcript_to_json(segments: List[SourceTranscriptSegment]) -> str:
return json.dumps(payload, ensure_ascii=False, indent=2) + "\n"
def _extract_transcript_segments(data: Any) -> Any:
if isinstance(data, dict) and "segments" in data:
return data["segments"]
return data
def _validate_sequential_ids(transcript: List[TranscriptSegment]) -> None:
ids = [segment.id for segment in transcript]
expected = list(range(1, len(transcript) + 1))

View File

@@ -0,0 +1,69 @@
from audita.core.schemas import parse_source_transcript_json, parse_transcript_json
SERIATIM_TRANSCRIPT = """
{
"metadata": {
"application": "seriatim",
"version": "dev",
"input_reader": "json-files",
"input_files": ["eric.json", "mike.json"],
"preprocessing_modules": ["validate-raw", "normalize-speakers", "trim-text"],
"postprocessing_modules": ["detect-overlaps", "resolve-overlaps", "backchannel"],
"output_modules": ["json"]
},
"segments": [
{
"id": 1,
"source": "eric.json",
"source_segment_index": 0,
"speaker": "Eric Rakestraw",
"start": 1.25,
"end": 3.5,
"text": "Hello there.",
"overlap_group_id": 1
},
{
"id": 2,
"source": "eric.json",
"source_ref": "word-run:1:1:1",
"derived_from": ["eric.json#0"],
"speaker": "Eric Rakestraw",
"start": 4.0,
"end": 4.5,
"text": "Resolved word run",
"categories": ["backchannel"]
}
],
"overlap_groups": [
{
"id": 1,
"start": 1.25,
"end": 4.0,
"segments": ["eric.json#0", "mike.json#0"],
"speakers": ["Eric Rakestraw", "Mike Brown"],
"class": "unknown",
"resolution": "unresolved"
}
]
}
"""
def test_parse_source_transcript_json_accepts_seriatim_transcript_object():
segments = parse_source_transcript_json(SERIATIM_TRANSCRIPT)
assert len(segments) == 2
assert segments[0].id == 1
assert segments[0].speaker == "Eric Rakestraw"
assert segments[0].start == 1.25
assert segments[0].end == 3.5
assert segments[0].text == "Hello there."
assert segments[1].text == "Resolved word run"
def test_parse_transcript_json_accepts_seriatim_transcript_object_and_ignores_unused_fields():
segments = parse_transcript_json(SERIATIM_TRANSCRIPT)
assert [segment.id for segment in segments] == [1, 2]
assert [segment.text for segment in segments] == ["Hello there.", "Resolved word run"]