enterprise-audio-intelligence / scripts /validate_audio_pipeline.py
Akbub's picture
deploy: Nexus AI v0.2.0 - SAP C4C Lead Creation UI included in fresh frontend build
d1f3f31
Raw
History Blame Contribute Delete
3.79 kB
from __future__ import annotations
import argparse
import json
import sys
import time
import asyncio
from pathlib import Path
PROJECT_ROOT = Path(__file__).resolve().parents[1]
if str(PROJECT_ROOT) not in sys.path:
sys.path.insert(0, str(PROJECT_ROOT))
from src.api.server import analyze_text_payload
from src.aspect_sentiment.audio import WhisperTranscriber
from src.aspect_sentiment.behavioral_signals import detect_signals
from src.aspect_sentiment.diarization import diarize_audio_segments
REQUIRED_TERMS = ["laptop", "60000", "dell", "lenovo"]
def validate_audio(audio_path: Path, min_confidence: float, min_turns: int) -> tuple[dict, list[str]]:
transcriber = WhisperTranscriber()
transcription = transcriber.transcribe(audio_path)
diarization = diarize_audio_segments(audio_path, transcription.segments)
result = asyncio.run(analyze_text_payload(
transcription.text,
source_name=audio_path.name,
source_type="audio",
language=transcription.language,
transcription_confidence=transcription.confidence,
whisper_model=transcriber.model_size,
diarization=diarization,
start_time=time.perf_counter(),
))
customer_text = result.get("customerTranscript", "")
agent_text = result.get("agentTranscript", "")
transcript_lower = transcription.text.lower().replace(",", "")
signals = detect_signals(customer_text, result.get("rawFeatures", []))
failures: list[str] = []
if transcription.confidence is None or transcription.confidence < min_confidence:
failures.append(f"transcription confidence below threshold: {transcription.confidence}")
if len(diarization.turns) < min_turns:
failures.append(f"too few diarized turns: {len(diarization.turns)}")
if not customer_text.strip():
failures.append("missing customer transcript")
if not agent_text.strip():
failures.append("missing agent transcript")
for term in REQUIRED_TERMS:
if term not in transcript_lower:
failures.append(f"required transcript term missing: {term}")
if "asked_for_whatsapp" in signals.get("detected_positive", []):
failures.append("false WhatsApp behavioral signal detected")
if result.get("conversionScore", {}).get("label") not in {"warm", "hot", "cold"}:
failures.append("conversion label is invalid")
summary = {
"audio": str(audio_path),
"whisperModel": transcriber.model_size,
"language": transcription.language,
"confidence": transcription.confidence,
"durationSeconds": transcription.duration_seconds,
"segmentCount": len(transcription.segments),
"diarizationProvider": diarization.provider,
"turnCount": len(diarization.turns),
"customerWordCount": len(customer_text.split()),
"agentWordCount": len(agent_text.split()),
"conversion": result.get("conversionScore", {}),
"behavioralSignals": signals,
"failures": failures,
}
return summary, failures
def main() -> int:
parser = argparse.ArgumentParser(description="Run a production smoke test for the audio pipeline.")
parser.add_argument("--audio", type=Path, default=Path("audio/conv_001.wav"))
parser.add_argument("--min-confidence", type=float, default=0.60)
parser.add_argument("--min-turns", type=int, default=8)
args = parser.parse_args()
if not args.audio.exists():
print(json.dumps({"failures": [f"audio file not found: {args.audio}"]}, indent=2))
return 2
summary, failures = validate_audio(args.audio, args.min_confidence, args.min_turns)
print(json.dumps(summary, indent=2, ensure_ascii=True))
return 1 if failures else 0
if __name__ == "__main__":
sys.exit(main())