autoace-audio-evaluator / tests /test_batch.py
mritunjayk-ops's picture
Add LLM emotion classifier, result summary, and honest docs
f94ee13
Raw
History Blame Contribute Delete
3.4 kB
import csv
import hashlib
import json
import math
import struct
import wave
from autoace_audio.batch import ManifestEntry, parse_manifest_for_inference, process_batch
from autoace_audio.pipeline import prepare_audio
def write_wav(path, frequency=440, duration=0.15, sample_rate=16_000):
with wave.open(str(path), "wb") as output:
output.setnchannels(1)
output.setsampwidth(2)
output.setframerate(sample_rate)
frames = bytearray()
for index in range(int(duration * sample_rate)):
sample = int(8_000 * math.sin(2 * math.pi * frequency * index / sample_rate))
frames.extend(struct.pack("<h", sample))
output.writeframes(frames)
def write_manifest(path, label_value):
with path.open("w", encoding="utf-8", newline="") as stream:
writer = csv.DictWriter(stream, fieldnames=("name", "result_json"))
writer.writeheader()
writer.writerow({"name": "call.wav", "result_json": label_value})
def test_batch_isolates_file_failures_and_continues(tmp_path):
write_wav(tmp_path / "first.wav", 440)
(tmp_path / "broken.mp3").write_bytes(b"not audio")
write_wav(tmp_path / "third.wav", 660)
entries = (
ManifestEntry("first.wav"),
ManifestEntry("broken.mp3"),
ManifestEntry("third.wav"),
)
report = process_batch(entries, tmp_path, prepare_audio)
assert [item.status for item in report.items] == ["ok", "error", "ok"]
assert report.success_count == 2
assert report.failure_count == 1
assert report.items[1].failure is not None
assert report.items[1].failure.code == "audio_decode_failed"
assert str(tmp_path) not in report.items[1].failure.message
def test_missing_file_is_an_isolated_error(tmp_path):
write_wav(tmp_path / "present.wav")
entries = (ManifestEntry("missing.wav"), ManifestEntry("present.wav"))
report = process_batch(entries, tmp_path, lambda path: path.name)
assert [item.status for item in report.items] == ["error", "ok"]
assert report.items[0].failure.code == "missing_file"
def test_inference_results_do_not_change_when_labels_are_removed_or_altered(tmp_path):
audio = tmp_path / "call.wav"
write_wav(audio)
empty_manifest = tmp_path / "empty.csv"
altered_manifest = tmp_path / "altered.csv"
write_manifest(empty_manifest, "")
write_manifest(
altered_manifest,
json.dumps(
{
"emotional_tone": "distressed",
"emotional_intensity": "high",
"background_noise_present": True,
"background_noise_type": "television",
"background_noise_severity": "high",
"audio_quality": "severely_impaired",
"speaker_overlap_present": True,
"long_silence_present": True,
"confidence": 1.0,
}
),
)
def inference_stub(path):
return hashlib.sha256(path.read_bytes()).hexdigest()
without_labels = process_batch(
parse_manifest_for_inference(empty_manifest), tmp_path, inference_stub
)
with_altered_labels = process_batch(
parse_manifest_for_inference(altered_manifest), tmp_path, inference_stub
)
assert without_labels.items == with_altered_labels.items
assert not hasattr(parse_manifest_for_inference(altered_manifest)[0], "result_json")