import { ChatOpenAI } from '@langchain/openai'; import { SystemMessage, HumanMessage } from '@langchain/core/messages'; import { RunnableConfig } from '@langchain/core/runnables'; import { EvaluationState } from '../state'; /** * Node responsible for generating the final mastery report at the end of the session. */ export const reportAnalyzerNode = async ( state: EvaluationState, config?: RunnableConfig, ): Promise> => { const { model } = (config?.configurable as any) || {}; const { scores, messages } = state; const questionList = state.questions || []; console.log('[AnalyzerNode] Entering node...', { numScores: Object.keys(scores || {}).length, numMessages: messages?.length, scores, }); if (!model) { throw new Error('Missing model in node configuration'); } const scoreSummary = Object.entries(scores) .map(([qId, score]) => { const displayId = isNaN(parseInt(qId)) ? qId : (parseInt(qId) + 1).toString(); return `Question ${displayId}: Score ${score}/10`; }) .join('\n'); const dimensionSummary = questionList.reduce((acc: Record, q: any) => { const dim = q.dimension || 'workCapability'; const score = scores[q.id] || 0; if (!acc[dim]) acc[dim] = []; acc[dim].push(score); return acc; }, {}); const dimensionAvg = Object.entries(dimensionSummary).map(([dim, arr]: [string, any]) => { const avg = arr.reduce((a: number, b: number) => a + b, 0) / arr.length; return `${dim}: ${avg.toFixed(1)}/10`; }).join('\n'); const isZh = state.language === 'zh'; const isJa = state.language === 'ja'; const systemPromptZh = `你是一位客观且严谨的高级教育顾问。 请审查以下评估结果,并为员工提供一份严谨的掌握程度报告。 重要提示: 1. **你必须使用以下语言生成报告:中文 (Simplified Chinese)**。 2. **严禁夹杂日文**。即使对话记录中包含日文,报告内容也必须全中文。 3. 报告的第一行必须严格遵守此格式:"LEVEL: [Novice/Proficient/Advanced/Expert]"。 4. **等级判定必须遵循以下分数阈值**: - 总体平均分 >= 9 → Expert(专家) - 总体平均分 >= 7 → Advanced(高级) - 已通过(有有效回答且得分 > 0)→ Proficient(熟练) - 未通过(无有效回答或得分为 0)→ Novice(新手) 即使得分很高,也要确保等级与上述阈值匹配。不要随意提高或降低等级。 5. 不要虚构或幻想优点(如"潜力"或"好奇心"),如果用户明确表示"不知道"或未提供实质内容。 6. 专注于对话记录中已证明的事实。 各维度得分: ${dimensionAvg} 问题与得分: ${scoreSummary} 对话记录: ${messages .filter((m: any) => m._getType() !== 'system') .map((m: any) => `${m.role || m._getType()}: ${m.content}`) .join('\n')} 报告结构: 1. 总体级别(已在顶部指定) 2. 各维度得分分析(提示词、LLM、IDE、开发范式、工作能力) 3. 薄弱环节识别 4. 针对性改进建议 5. 推荐的学习路径。`; const systemPromptJa = `あなたは客観的で厳格なシニア教育コンサルタントです。 以下の評価結果をレビューし、従業員に対して厳格な習熟度レポートを提供してください。 重要事項: 1. **レポートは必ず次の言語で生成してください:日本語**。 2. **中国語を混ぜないでください**。会話ログに中国語が含まれていても、レポートの内容はすべて日本語で記述してください。 3. レポートの最初の行は, 必ず次の形式に従ってください:"LEVEL: [Novice/Proficient/Advanced/Expert]"。 4. 客観的であること。ユーザーが有効な回答を提供しなかった場合、またはスコアが 0 の場合、'Novice' と判定し、習熟度が証明されていないことを明示してください。 5. **レベル判定は以下のスコアしきい値に従うこと**: - 平均スコア >= 9 → Expert - 平均スコア >= 7 → Advanced - 合格(有効な回答がありスコア > 0)→ Proficient - 不合格(有効な回答なし、またはスコア 0)→ Novice 6. ユーザーが「わからない」と言ったり、内容を提供しなかった場合に、長所(「ポテンシャル」や「好奇心」など)を捏造しないでください。 7. 会話ログで証明された事実に集中してください。 各ディメンションスコア: ${dimensionAvg} 質問とスコア: ${scoreSummary} 会話ログ: ${messages .filter((m: any) => m._getType() !== 'system') .map((m: any) => `${m.role || m._getType()}: ${m.content}`) .join('\n')} レポート構成: 1. 総合レベル(一番上に指定済み) 2. 各ディメンション分析(提示詞、LLM、IDE、開発範式、工作能力) 3. 薄弱环节识别 4. 推奨される学習パス。`; const systemPromptEn = `You are an objective and critical seniority education consultant. Review the following assessment results and provide a rigorous mastery report for the employee. IMPORTANT: 1. **You MUST generate the report strictly in English.** 2. START the report with exactly this format: "LEVEL: [Novice/Proficient/Advanced/Expert]" on the first line. 3. Be OBJECTIVE. If the user provided no valid answers or scores are 0, you MUST identify them as 'Novice' and explicitly state they have NOT demonstrated mastery. 4. **Level assignment MUST follow these score thresholds**: - Average score >= 9 → Expert - Average score >= 7 → Advanced - Passed (has valid answers with score > 0) → Proficient - Not passed (no valid answers or score is 0) → Novice 5. DO NOT invent or hallucinate strengths (like 'potential' or 'curiosity') if the user explicitly said "I don't know" or provided no content. 6. Focus on what was PROVEN in the conversation logs. DIMENSION SCORES: ${dimensionAvg} QUESTIONS AND SCORES: ${scoreSummary} CONVERSATION LOGS: ${messages .filter((m: any) => m._getType() !== 'system') .map((m: any) => `${m.role || m._getType()}: ${m.content}`) .join('\n')} REPORT STRUCTURE: 1. Overall Level (Already specified at top) 2. Dimension Analysis (Prompt, LLM, IDE, DevPattern, WorkCapability) 3. Weak Areas Identification 4. Targeted Learning Recommendations.`; const systemPrompt = isZh ? systemPromptZh : isJa ? systemPromptJa : systemPromptEn; const humanMsg = isZh ? '生成最终掌握程度报告。' : isJa ? '最終的な習熟度レポートを生成してください。' : 'Generate the final mastery report.'; const response = await model.invoke([ new SystemMessage(systemPrompt), new HumanMessage(humanMsg), ]); console.log( '[AnalyzerNode] Report generated successfully. Length:', response.content?.toString().length, ); return { report: response.content as string, }; };