CognxSafeTrack
feat: backlog P0→P3 — toast system, payments, tenant isolation, feedback handler, i18n parity
6dd9bad | 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' | |
| } | |
| }); | |
| } | |
| } | |