edtech / apps /api /src /utils /metrics.ts
CognxSafeTrack
chore: finalize Sprint P2 & P3 optimizations, baseline prisma migrations, and update technical audit docs
cfbb685
import levenshtein from 'fast-levenshtein';
/**
* Word Error Rate (WER) calculation using Levenshtein distance at word level.
*/
export const calculateWER = (reference: string, hypothesis: string): number => {
const clean = (str: string) => str.toLowerCase().replace(/[.,/#!$%^&*;:{}=\-_`~()]/g, "").split(/\s+/).filter(w => w);
const refWords = clean(reference);
const hypWords = clean(hypothesis);
if (refWords.length === 0) return hypWords.length > 0 ? 1 : 0;
const wordMap = new Map<string, string>();
let charCode = 0xE000;
const getChar = (word: string) => {
if (!wordMap.has(word)) wordMap.set(word, String.fromCharCode(charCode++));
return wordMap.get(word)!;
};
const refChars = refWords.map(getChar).join('');
const hypChars = hypWords.map(getChar).join('');
return levenshtein.get(refChars, hypChars) / refWords.length;
};
/**
* Standard error formatter for catch blocks.
*/
export const formatError = (err: unknown): string => {
if (err instanceof Error) return err.message;
return String(err);
};