Implement support for segments with an optional categories key

This commit is contained in:
2026-04-28 22:41:16 -05:00
parent 177e45f1fd
commit db6004fadc
10 changed files with 115 additions and 9 deletions

View File

@@ -25,3 +25,19 @@ def test_chunk_transcript_batches_sections_by_token_limit():
assert len(sections) == 2
assert [segment.segment.id for segment in sections[0].segments] == [1, 2]
assert [segment.segment.id for segment in sections[1].segments] == [3]
def test_chunk_transcript_prompt_payload_includes_categories_when_present():
transcript = parse_transcript_json(
"""
[
{"id": 1, "speaker": "A", "start": 0.0, "end": 1.0, "text": "one", "categories": ["intro", "aside"]}
]
"""
)
sections = chunk_transcript(transcript, max_section_tokens=8, estimator=FakeEstimator())
assert sections[0].prompt_payload() == [
{"id": 1, "original_text": "one", "categories": ["intro", "aside"]}
]

View File

@@ -120,8 +120,8 @@ def test_spoken_form_plausibility_validator_approves_plausible_and_rejects_impla
transcript = parse_transcript_json(
"""
[
{"id": 1, "speaker": "A", "start": 0.0, "end": 1.0, "text": "There were gestures at the temple."},
{"id": 2, "speaker": "A", "start": 1.0, "end": 2.0, "text": "Lyra moved first."}
{"id": 1, "speaker": "A", "start": 0.0, "end": 1.0, "text": "There were gestures at the temple.", "categories": ["narration"]},
{"id": 2, "speaker": "A", "start": 1.0, "end": 2.0, "text": "Lyra moved first.", "categories": ["combat"]}
]
"""
)
@@ -176,6 +176,7 @@ def test_spoken_form_plausibility_validator_approves_plausible_and_rejects_impla
]
prompt_text = client.calls[0]["messages"][1]["content"]
assert '"original_segment_text"' in prompt_text
assert '"categories"' in prompt_text
assert "There were Jesters at the temple." in prompt_text
assert "Lyra moved first." in prompt_text

View File

@@ -46,9 +46,9 @@ def _transcript():
return parse_source_transcript_json(
"""
[
{"speaker": "Eric", "start": 0.0, "end": 1.0, "text": "Hello."},
{"speaker": "Eric", "start": 1.5, "end": 2.0, "text": "Again."},
{"speaker": "Mike", "start": 10.0, "end": 11.0, "text": "Done."}
{"speaker": "Eric", "start": 0.0, "end": 1.0, "text": "Hello.", "categories": ["intro"]},
{"speaker": "Eric", "start": 1.5, "end": 2.0, "text": "Again.", "categories": ["intro", "aside"]},
{"speaker": "Mike", "start": 10.0, "end": 11.0, "text": "Done.", "categories": ["response"]}
]
"""
)
@@ -74,6 +74,8 @@ def test_process_transcript_runs_noop_framework(tmp_path):
assert [segment.id for segment in revised] == [1, 2]
assert revised[0].text == "Hello. Again."
assert revised[1].text == "Done."
assert revised[0].categories == ["intro", "aside"]
assert revised[1].categories == ["response"]
assert [call["stage_name"] for call in llm_client.calls] == [
"glossary_1:proposal",
"homophones:proposal",
@@ -186,6 +188,30 @@ def test_external_report_can_be_written(tmp_path):
assert payload["totals"]["applied_change_count"] == 0
def test_process_transcript_preserves_categories_in_llm_prompt_payloads(tmp_path):
llm_client = FakeStructuredLLMClient(
[
{"corrections": []},
{"corrections": []},
{"corrections": []},
{"corrections": []},
{"corrections": []},
]
)
process_transcript(
_transcript(),
_glossary(),
AuditaConfig.from_sources(env={}, overrides=None),
llm_client=llm_client,
)
proposal_prompt = llm_client.calls[0]["messages"][1]["content"]
assert '"categories": [' in proposal_prompt
assert '"intro"' in proposal_prompt
assert '"aside"' in proposal_prompt
def test_default_module_specs_expose_final_validator_order():
specs = default_module_specs()

View File

@@ -1,4 +1,6 @@
from audita.core.schemas import parse_source_transcript_json, parse_transcript_json
import json
from audita.core.schemas import parse_source_transcript_json, parse_transcript_json, transcript_to_json
SERIATIM_TRANSCRIPT = """
@@ -60,6 +62,8 @@ def test_parse_source_transcript_json_accepts_seriatim_transcript_object():
assert segments[0].end == 3.5
assert segments[0].text == "Hello there."
assert segments[1].text == "Resolved word run"
assert segments[0].categories is None
assert segments[1].categories == ["backchannel"]
def test_parse_transcript_json_accepts_seriatim_transcript_object_and_ignores_unused_fields():
@@ -67,3 +71,14 @@ def test_parse_transcript_json_accepts_seriatim_transcript_object_and_ignores_un
assert [segment.id for segment in segments] == [1, 2]
assert [segment.text for segment in segments] == ["Hello there.", "Resolved word run"]
assert segments[0].categories is None
assert segments[1].categories == ["backchannel"]
def test_transcript_to_json_emits_categories_only_when_present():
segments = parse_transcript_json(SERIATIM_TRANSCRIPT)
payload = json.loads(transcript_to_json(segments))
assert "categories" not in payload[0]
assert payload[1]["categories"] == ["backchannel"]