-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathassessment-generation-improved.js
More file actions
135 lines (116 loc) · 4.51 KB
/
assessment-generation-improved.js
File metadata and controls
135 lines (116 loc) · 4.51 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
// ============================================================
// IMPROVED ASSESSMENT GENERATION ERROR HANDLING
// Replace the handleGenerateAssessment function in simpatico-ats.js
// with this version that has better JSON parsing & validation
// ============================================================
async function handleGenerateAssessment(request, env, ctx) {
requireRole(ctx, 'hr', 'admin', 'superadmin');
const body = await request.json().catch(() => ({}));
const { job_title, department, tech_stack, culture, difficulty, question_count = 5 } = body;
if (!job_title) {
return apiResponse(
{ error: 'job_title is required' },
HTTP.UNPROCESSABLE,
{ code: 'VALIDATION_ERROR' }
);
}
try {
// Build detailed prompt for AI
const prompt = `Design a highly specific, proctored assessment quiz for a ${difficulty || 'mid-level'} ${job_title}${department ? ` in ${department}` : ''}${tech_stack ? ` specializing in ${tech_stack}` : ''}.
Generate ${question_count} technical questions that:
1. Accurately assess core competencies for this role
2. Include both multiple-choice (MCQ) and short-answer types
3. Have clear correct answers and grading rubrics for AI evaluation
4. Test real-world problem-solving, not just theory
${culture ? `Company culture: ${culture}. Incorporate questions that assess alignment with our values.` : ''}
CRITICAL: Return ONLY valid JSON (no markdown, no code blocks) in this exact format:
{
"assessment_title": "string",
"questions": [
{
"id": "q1",
"type": "mcq",
"question": "string",
"options": ["A", "B", "C", "D"],
"correct_answer": "A",
"scoring_rubric": "How to grade this question"
}
]
}`;
const aiResponse = await env.AI.run('@cf/meta/llama-3.1-8b-instruct', {
messages: [{ role: 'user', content: prompt }],
max_tokens: 2000
});
if (!aiResponse?.response) {
throw new Error('AI returned empty response');
}
// Parse AI response - remove markdown code blocks if present
let responseText = aiResponse.response.trim();
responseText = responseText
.replace(/^```json\n?/, '')
.replace(/\n?```$/, '')
.replace(/^```\n?/, '')
.trim();
// Attempt to parse JSON
let assessment;
try {
assessment = JSON.parse(responseText);
} catch (parseError) {
console.error('[assessment] JSON parse failed:', {
error: parseError.message,
rawResponse: responseText.substring(0, 200)
});
throw new Error(`AI returned invalid JSON: ${parseError.message}. Please try again.`);
}
// Validate assessment structure
if (!assessment.assessment_title || typeof assessment.assessment_title !== 'string') {
throw new Error('Assessment missing or invalid title field');
}
if (!Array.isArray(assessment.questions) || assessment.questions.length === 0) {
throw new Error(`Assessment has no questions (got ${assessment.questions?.length || 0}). AI may not have generated properly.`);
}
// Validate each question
assessment.questions.forEach((q, idx) => {
if (!q.question || !q.type) {
throw new Error(`Question ${idx + 1} missing required fields (question, type)`);
}
if (q.type === 'mcq' && (!Array.isArray(q.options) || q.options.length === 0)) {
throw new Error(`MCQ question ${idx + 1} has no options`);
}
if (!q.correct_answer) {
throw new Error(`Question ${idx + 1} missing correct_answer`);
}
});
return apiResponse({
assessment,
generated_at: new Date().toISOString(),
question_count: assessment.questions.length
});
} catch (error) {
console.error('[assessment] Generation error:', {
job_title,
error: error.message,
timestamp: new Date().toISOString()
});
// Distinguish between validation, AI, and system errors
if (error.message.includes('JSON')) {
return apiResponse(
{ error: `Assessment generation failed: ${error.message}` },
HTTP.SERVER_ERROR,
{ code: 'AI_PARSE_ERROR', retryable: true }
);
}
if (error.message.includes('missing') || error.message.includes('invalid')) {
return apiResponse(
{ error: `Invalid assessment structure: ${error.message}` },
HTTP.SERVER_ERROR,
{ code: 'ASSESSMENT_VALIDATION_ERROR', retryable: true }
);
}
return apiResponse(
{ error: error.message || 'Assessment generation failed' },
HTTP.SERVER_ERROR,
{ code: 'AI_SERVICE_ERROR' }
);
}
}