Files
YG-Datasets/easy-dataset-main/app/api/projects/[projectId]/blind-test-tasks/[taskId]/vote/route.js

155 lines
4.2 KiB
JavaScript

import { NextResponse } from 'next/server';
import { db } from '@/lib/db/index';
/**
* Submit vote result
* vote: 'left' | 'right' | 'both_good' | 'both_bad'
* Results are stored in EvalResults table
*/
export async function POST(request, { params }) {
try {
const { projectId, taskId } = params;
const { vote, questionId, isSwapped, leftAnswer, rightAnswer } = await request.json();
// Validate vote option
const validVotes = ['left', 'right', 'both_good', 'both_bad'];
if (!validVotes.includes(vote)) {
return NextResponse.json({ code: 400, error: 'Invalid vote option' }, { status: 400 });
}
if (!questionId) {
return NextResponse.json({ code: 400, error: 'Question ID is required' }, { status: 400 });
}
const task = await db.task.findFirst({
where: {
id: taskId,
projectId,
taskType: 'blind-test'
}
});
if (!task) {
return NextResponse.json({ code: 404, error: 'Task not found' }, { status: 404 });
}
if (task.status !== 0) {
return NextResponse.json({ code: 400, error: 'Task has ended' }, { status: 400 });
}
// Parse task details
let detail = {};
try {
detail = task.detail ? JSON.parse(task.detail) : {};
} catch (e) {
console.error('Failed to parse task detail:', e);
}
// Calculate scores
// isSwapped: true means left is model B and right is model A
// isSwapped: false means left is model A and right is model B
let modelAScore = 0;
let modelBScore = 0;
if (vote === 'left') {
if (isSwapped) {
modelBScore = 1; // Left is B
} else {
modelAScore = 1; // Left is A
}
} else if (vote === 'right') {
if (isSwapped) {
modelAScore = 1; // Right is A
} else {
modelBScore = 1; // Right is B
}
} else if (vote === 'both_good') {
modelAScore = 0.5;
modelBScore = 0.5;
}
// both_bad: both scores remain 0
// Store result in EvalResults table
const evalResult = await db.evalResults.create({
data: {
projectId,
taskId,
evalDatasetId: questionId,
modelAnswer: JSON.stringify({
leftAnswer: leftAnswer || '',
rightAnswer: rightAnswer || ''
}),
score: modelAScore, // Store modelA score for sorting/aggregation
isCorrect: false, // Not applicable for blind-test
judgeResponse: JSON.stringify({
vote,
isSwapped,
modelAScore,
modelBScore
}),
duration: 0,
status: 0
}
});
// Update task progress
const evalDatasetIds = detail.evalDatasetIds || [];
const newCurrentIndex = (detail.currentIndex || 0) + 1;
const isCompleted = newCurrentIndex >= evalDatasetIds.length;
const updatedDetail = {
...detail,
currentIndex: newCurrentIndex
};
await db.task.update({
where: { id: taskId },
data: {
detail: JSON.stringify(updatedDetail),
completedCount: newCurrentIndex,
status: isCompleted ? 1 : 0, // 1-completed, 0-running
endTime: isCompleted ? new Date() : null
}
});
// Calculate current total scores from EvalResults
const allResults = await db.evalResults.findMany({
where: { taskId },
select: { judgeResponse: true }
});
let totalModelAScore = 0;
let totalModelBScore = 0;
for (const r of allResults) {
try {
const judge = JSON.parse(r.judgeResponse || '{}');
totalModelAScore += judge.modelAScore || 0;
totalModelBScore += judge.modelBScore || 0;
} catch (e) {
// Ignore parse errors
}
}
return NextResponse.json({
code: 0,
data: {
success: true,
isCompleted,
currentIndex: newCurrentIndex,
totalCount: evalDatasetIds.length,
scores: {
modelA: totalModelAScore,
modelB: totalModelBScore
}
},
message: isCompleted ? 'Blind-test task completed' : 'Vote recorded'
});
} catch (error) {
console.error('Failed to submit vote result:', error);
return NextResponse.json(
{ code: 500, error: 'Failed to submit vote result', message: error.message },
{ status: 500 }
);
}
}