Implemented support for the seriatim JSON schema for input transcripts
This commit is contained in:
@@ -8,7 +8,7 @@ from .errors import AuditaValidationError
|
|||||||
|
|
||||||
|
|
||||||
class TranscriptSegment(BaseModel):
|
class TranscriptSegment(BaseModel):
|
||||||
model_config = ConfigDict(extra="forbid")
|
model_config = ConfigDict(extra="ignore")
|
||||||
|
|
||||||
id: int = Field(ge=1)
|
id: int = Field(ge=1)
|
||||||
speaker: StrictStr
|
speaker: StrictStr
|
||||||
@@ -50,7 +50,7 @@ class TranscriptSegment(BaseModel):
|
|||||||
|
|
||||||
|
|
||||||
class SourceTranscriptSegment(BaseModel):
|
class SourceTranscriptSegment(BaseModel):
|
||||||
model_config = ConfigDict(extra="forbid")
|
model_config = ConfigDict(extra="ignore")
|
||||||
|
|
||||||
id: Optional[int] = Field(default=None, ge=1)
|
id: Optional[int] = Field(default=None, ge=1)
|
||||||
speaker: StrictStr
|
speaker: StrictStr
|
||||||
@@ -146,8 +146,9 @@ def validate_transcript_data(
|
|||||||
data: Any,
|
data: Any,
|
||||||
require_sequential_ids: bool = True,
|
require_sequential_ids: bool = True,
|
||||||
) -> List[TranscriptSegment]:
|
) -> List[TranscriptSegment]:
|
||||||
|
data = _extract_transcript_segments(data)
|
||||||
if not isinstance(data, list):
|
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:
|
if not data:
|
||||||
raise AuditaValidationError("Transcript must contain at least one segment.")
|
raise AuditaValidationError("Transcript must contain at least one segment.")
|
||||||
try:
|
try:
|
||||||
@@ -160,8 +161,9 @@ def validate_transcript_data(
|
|||||||
|
|
||||||
|
|
||||||
def validate_source_transcript_data(data: Any) -> List[SourceTranscriptSegment]:
|
def validate_source_transcript_data(data: Any) -> List[SourceTranscriptSegment]:
|
||||||
|
data = _extract_transcript_segments(data)
|
||||||
if not isinstance(data, list):
|
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:
|
if not data:
|
||||||
raise AuditaValidationError("Transcript must contain at least one segment.")
|
raise AuditaValidationError("Transcript must contain at least one segment.")
|
||||||
try:
|
try:
|
||||||
@@ -215,6 +217,12 @@ def source_transcript_to_json(segments: List[SourceTranscriptSegment]) -> str:
|
|||||||
return json.dumps(payload, ensure_ascii=False, indent=2) + "\n"
|
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:
|
def _validate_sequential_ids(transcript: List[TranscriptSegment]) -> None:
|
||||||
ids = [segment.id for segment in transcript]
|
ids = [segment.id for segment in transcript]
|
||||||
expected = list(range(1, len(transcript) + 1))
|
expected = list(range(1, len(transcript) + 1))
|
||||||
|
|||||||
69
tests/test_new_transcript_schema.py
Normal file
69
tests/test_new_transcript_schema.py
Normal 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"]
|
||||||
Reference in New Issue
Block a user