import { prisma } from './prisma'; import { calculateWER } from '../utils/metrics'; import { normalizeWolof } from '../scripts/normalizeWolof'; export class TrainingService { static async getPendingAudios(page: number, limit: number) { const [pending, total] = await Promise.all([ prisma.trainingData.findMany({ where: { status: 'PENDING' }, orderBy: { createdAt: 'desc' }, skip: (page - 1) * limit, take: limit, }), prisma.trainingData.count({ where: { status: 'PENDING' } }) ]); return { pending, total, page, limit }; } static async submitCorrection(id: string | undefined, audioUrl: string, transcription: string, manualCorrection: string) { const normResult = normalizeWolof(transcription); const rawWER = calculateWER(manualCorrection, transcription); const normalizedWER = calculateWER(manualCorrection, normResult.normalizedText); // Analyze missing words const manualWords = manualCorrection.toLowerCase().replace(/[.,/#!$%^&*;:{}=\-_`~()]/g, "").split(/\s+/).filter(w => w); const normWords = normResult.normalizedText.toLowerCase().replace(/[.,/#!$%^&*;:{}=\-_`~()]/g, "").split(/\s+/).filter((w: string) => w); const missingWords = Array.from(new Set(manualWords.filter((w: string) => !normWords.includes(w)))); const data = await prisma.trainingData.upsert({ where: { id: id || '00000000-0000-0000-0000-000000000000' }, update: { manualCorrection, rawWER, normalizedWER, status: 'REVIEWED' }, create: { audioUrl, transcription, manualCorrection, rawWER, normalizedWER, status: 'REVIEWED' } }); return { data, missingWords, rawWER, normalizedWER }; } static async createTrainingRecord(audioUrl: string, transcription: string) { return prisma.trainingData.create({ data: { audioUrl, transcription: transcription || '', status: 'PENDING' } }); } }