Replaced the stub LLM-based validator class with two real LLM-based validator implementations

This commit is contained in:
2026-04-24 11:52:22 -05:00
parent bca2152971
commit 34b3c09e43
14 changed files with 918 additions and 99 deletions

View File

@@ -1,8 +1,9 @@
from audita.core.config import AuditaConfig
from audita.core.errors import AuditaLLMError
from audita.core.schemas import parse_glossary_yaml, parse_transcript_json
from audita.framework.models import CorrectionProposal, ModuleContext, ModuleRunSpec
from audita.framework.runner import PipelineRunner
from audita.validators import ProtectedGlossaryTermsValidator
from audita.validators import MeaningReversalValidator, ProtectedGlossaryTermsValidator, SpokenFormPlausibilityValidator
from audita.validators.base import ValidationContext, ValidationDecision, ValidationResult
@@ -34,6 +35,25 @@ class RecordingLLMValidator(RecordingValidator):
execution_kind = "llm"
class FakeStructuredLLMClient:
def __init__(self, responses):
self._responses = list(responses)
self.calls = []
def run_structured(self, *, stage_name, messages, response_model, config):
self.calls.append(
{
"stage_name": stage_name,
"messages": list(messages),
"response_model": response_model,
}
)
if not self._responses:
raise AuditaLLMError("FakeStructuredLLMClient received more calls than expected.")
payload = self._responses.pop(0)
return response_model.model_validate(payload)
class RecordingModule:
replacement_policy = "require_unique"
@@ -227,6 +247,89 @@ def test_pipeline_runner_supports_deterministic_and_llm_validators_in_one_chain(
]
def test_pipeline_runner_supports_real_llm_validators_in_one_chain(tmp_path):
transcript = parse_transcript_json(
"""
[
{"id": 1, "speaker": "A", "start": 0.0, "end": 1.0, "text": "There were gestures at the dam."}
]
"""
)
glossary = parse_glossary_yaml(
"""
glossary:
- name: "Jesters"
category: faction
summary: "The Jesters are a faction."
"""
)
module = RecordingModule(
"mixed_real",
[
CorrectionProposal(
proposal_index=0,
module_instance="mixed_real",
module_key="glossary",
id=1,
original_text="gestures",
corrected_text="Jesters",
confidence=0.9,
)
],
[
ProtectedGlossaryTermsValidator("protected_glossary_guard"),
SpokenFormPlausibilityValidator("spoken_form_plausibility_review"),
MeaningReversalValidator("meaning_reversal_review"),
],
[],
)
llm_client = FakeStructuredLLMClient(
[
{
"validations": [
{
"correction_index": 0,
"approved": True,
"confidence": 0.95,
"reason": "Likely phonetic mistranscription in context.",
}
]
},
{
"validations": [
{
"correction_index": 0,
"approved": True,
"confidence": 0.98,
"reason": "Does not reverse the segment meaning.",
}
]
},
]
)
runner = PipelineRunner()
result = runner.run(
transcript=transcript,
glossary=glossary,
module_specs=[ModuleRunSpec(instance_name="mixed_real", module_key="glossary", module=module)],
config=AuditaConfig.from_sources(env={"OPENROUTER_API_KEY": "test-key"}),
run_dir=tmp_path / "run",
llm_client=llm_client,
)
assert result.transcript[0].text == "There were Jesters at the dam."
assert [report.execution_kind for report in result.module_reports[0].validators] == [
"deterministic",
"llm",
"llm",
]
assert [call["stage_name"] for call in llm_client.calls] == [
"mixed_real:spoken_form_plausibility_review",
"mixed_real:meaning_reversal_review",
]
def test_pipeline_runner_uses_real_protected_glossary_validator(tmp_path):
transcript = parse_transcript_json(
"""