Skip to content

GENAI · FULL STACK

A call auditor that listens, scores and flags what breaks the rules

A full-stack app for reviewing recorded calls. Upload a file or record in the browser, and it returns a transcript, sentiment, emotion, toxicity, intent and a 0 to 100 compliance score, then checks your own rules and can send alerts and scheduled reports.

An example: the mel spectrogram of a synthesized two-voice support call, its first transcript line, a keyword rule flagging a refund promise, and a 0 to 100 compliance score gauge.

THE GAP

Checking a call against policy means listening to the whole thing.

Most of a compliance review is listening: what was said, whether anyone got abusive, whether a required phrase was said or a banned one slipped out. It is slow, and the result depends on who is listening.

I wanted to see how much of that first pass a chain of open models could handle, and to turn the rules into something a team writes down once and a system checks every time.

01

Slow to review

Listening happens in real time, so review time grows with every call you record.

02

Rules on paper

A policy written in a document cannot flag anything. Someone has to apply it, call by call.

03

Findings stall

Even when a problem is found, someone still has to write it up and tell the right people.

WHAT IT DOES

A first pass on every call, with the rules written down.

A FastAPI backend transcribes the call with Whisper, runs it through a chain of open models, checks it against rules stored in the database, and saves the result to SQLite. A React and TypeScript front end shows the score, transcript and timelines, with logins, roles, teams, comments and tags so several reviewers can work on the same calls. Alerts, webhooks, emails and scheduled reports carry the findings to people who are not looking at the screen.

Transcript and signals

Whisper transcribes and detects language. Open models score sentiment, emotion and toxicity, classify intent zero-shot, pull topics and summarize.

A 0 to 100 score

Emotion and toxicity combine into a 0 to 100 compliance score. Below 70 raises a warning, below 50 a critical alert.

Your own rules

Regex, keyword, sentiment, emotion, toxicity and score-threshold rules live in the database, each with a severity, and can be tested first.

Findings that travel

Alerts can fire webhooks and emails. Daily, weekly or monthly reports go out by email, with PDF, CSV and JSON exports.

HOW IT WORKS

What happens to one call

  1. 1

    Upload

    Drop in an audio file or record straight from the browser microphone.

  2. 2

    Transcribe

    Whisper, small model by default, transcribes the call and detects its language.

  3. 3

    Analyze

    Open models score sentiment, emotion and toxicity, then add intent, topics, summary and action items.

  4. 4

    Explain

    SHAP highlights which words pushed the toxicity score up.

  5. 5

    Check rules

    Your stored rules and the default thresholds run against the transcript and scores.

  6. 6

    Notify

    Alerts trigger any configured webhooks and emails, and the analysis is saved.

  7. 7

    Review

    Reviewers see the score, transcript and timeline, then comment, tag, compare or export.

SYSTEM DESIGN

One endpoint, many small models

A single FastAPI endpoint runs every analysis in sequence on the uploaded file. Each step is wrapped on its own, so one failing model leaves a gap in the report instead of failing the whole request.

RESULTS

What is in the repo

0 to 100

compliance score per call, with warning and critical alerts below 70 and 50

7

rule types a team can define, from regex and keywords to score thresholds

64

API routes, from analysis to users, teams, webhooks and schedules

14

pages in the React and TypeScript front end

This is an application, not a benchmark: the repo has no accuracy measurements, so these are counts from the code.

WHAT IT TAUGHT ME

Where the feature list got ahead of the code

Looking back at the code, the feature list got ahead of it in places. The speaker turns are a placeholder: the audio is cut into two-second windows and each window is labeled by its spectral centroid, which is not real diarization. The sentiment model returns LABEL_0 to LABEL_2, but the score's weight table expects NEGATIVE, NEUTRAL and POSITIVE, so sentiment never moves the score. And custom rules are Python expressions run through eval, on routes that need no login, which is fine on a laptop and nowhere else. The next version needs a real diarization model, a tested label map, and rules that cannot run code.

BUILT WITH

  • FastAPI
  • Whisper
  • Transformers
  • Detoxify
  • SHAP
  • scikit-learn
  • SQLAlchemy
  • SQLite
  • APScheduler
  • React
  • TypeScript
  • Tailwind CSS
  • Recharts

Like what you see?

Thanks for reading. There's more where this came from.