feat: implement QuestionBank CRUD with pagination and template query
- Add pagination support to findAll (page, limit query params) - Add findByTemplateId method to service - Add GET /by-template/:templateId endpoint to controller - Service already includes CRUD for QuestionBank and QuestionBankItem
This commit is contained in:
@@ -0,0 +1,99 @@
|
||||
import { AIMessage } from '@langchain/core/messages';
|
||||
import { RunnableConfig } from '@langchain/core/runnables';
|
||||
import { EvaluationState } from '../state';
|
||||
|
||||
/**
|
||||
* Node responsible for presenting the current question or follow-up to the user.
|
||||
*/
|
||||
export const interviewerNode = async (
|
||||
state: EvaluationState,
|
||||
config?: RunnableConfig,
|
||||
): Promise<Partial<EvaluationState>> => {
|
||||
const { questions, currentQuestionIndex, shouldFollowUp, messages } = state;
|
||||
|
||||
console.log('[InterviewerNode] Entering node...', {
|
||||
numQuestions: questions?.length,
|
||||
currentIndex: currentQuestionIndex,
|
||||
shouldFollowUp,
|
||||
numMessages: messages?.length,
|
||||
});
|
||||
|
||||
if (!questions || questions.length === 0) {
|
||||
const isZh = state.language === 'zh';
|
||||
const isJa = state.language === 'ja';
|
||||
const msg = isZh
|
||||
? '很抱歉,我无法为此会话生成任何问题。'
|
||||
: isJa
|
||||
? '申し訳ありませんが、このセッションの問題を生成できませんでした。'
|
||||
: "I'm sorry, I couldn't generate any questions for this session.";
|
||||
return {
|
||||
messages: [new AIMessage(msg)],
|
||||
};
|
||||
}
|
||||
|
||||
const currentQuestion = questions[currentQuestionIndex];
|
||||
|
||||
// If it's a follow-up, we add a prefix to the label later.
|
||||
// If we've run out of questions and no follow-up requested, we shouldn't be here, but let's be safe.
|
||||
if (currentQuestionIndex >= questions.length) {
|
||||
return { shouldFollowUp: false };
|
||||
}
|
||||
|
||||
const isZh = state.language === 'zh';
|
||||
const isJa = state.language === 'ja';
|
||||
|
||||
let prompt = '';
|
||||
|
||||
if (
|
||||
shouldFollowUp &&
|
||||
state.feedbackHistory &&
|
||||
state.feedbackHistory.length > 0
|
||||
) {
|
||||
// Construct a follow-up prompt based on last feedback
|
||||
const lastFeedbackMsg =
|
||||
state.feedbackHistory[state.feedbackHistory.length - 1];
|
||||
const feedbackText = lastFeedbackMsg.content.toString();
|
||||
|
||||
// Extract the "Feedback: ..." part if possible, otherwise use whole text
|
||||
const feedbackMatch = feedbackText.match(
|
||||
/(?:Feedback|反馈|フィードバック): ([\s\S]*)/i,
|
||||
);
|
||||
const specificFeedback = feedbackMatch
|
||||
? feedbackMatch[1].trim()
|
||||
: feedbackText;
|
||||
|
||||
const followUpLabel = isZh
|
||||
? '补充追问'
|
||||
: isJa
|
||||
? '追加の質問'
|
||||
: 'Follow-up Clarification';
|
||||
const followUpInstruction = isZh
|
||||
? '根据以上反馈,请补充更具体的信息:'
|
||||
: isJa
|
||||
? '上記のフィードバックに基づき、より具体的な情報を追加してください:'
|
||||
: 'Based on the feedback above, please provide more specific details:';
|
||||
|
||||
prompt = `${followUpLabel}\n\n${specificFeedback}\n\n${followUpInstruction}`;
|
||||
} else {
|
||||
// Standard question presentation
|
||||
const label = isZh
|
||||
? `问题 ${currentQuestionIndex + 1}`
|
||||
: isJa
|
||||
? `質問 ${currentQuestionIndex + 1}`
|
||||
: `Question ${currentQuestionIndex + 1}`;
|
||||
|
||||
const instruction = isZh
|
||||
? '请提供您的回答。'
|
||||
: isJa
|
||||
? '回答を入力してください。'
|
||||
: 'Please provide your answer.';
|
||||
|
||||
prompt = `${label}: ${currentQuestion.questionText}\n\n${instruction}`;
|
||||
}
|
||||
|
||||
console.log('[InterviewerNode] Returning question:', { currentQuestionIndex, questionText: currentQuestion?.questionText });
|
||||
return {
|
||||
messages: [new AIMessage(prompt)],
|
||||
shouldFollowUp: false,
|
||||
};
|
||||
};
|
||||
Reference in New Issue
Block a user