1414import com .stackup .stackup .session .application .dto .GenerateQuestionsPayload ;
1515import com .stackup .stackup .session .application .dto .GenerateQuestionsPayload .DocumentContext ;
1616import com .stackup .stackup .session .application .event .SessionCreatedEvent ;
17+ import com .stackup .stackup .session .domain .InterviewSessionRepository ;
18+ import com .stackup .stackup .session .domain .SessionQuestionPoolRepository ;
1719import java .io .IOException ;
1820import java .io .InputStream ;
1921import java .nio .charset .StandardCharsets ;
2224import lombok .RequiredArgsConstructor ;
2325import org .slf4j .Logger ;
2426import org .slf4j .LoggerFactory ;
27+ import org .springframework .beans .factory .annotation .Value ;
28+ import org .springframework .data .domain .PageRequest ;
2529import org .springframework .stereotype .Component ;
2630import org .springframework .transaction .annotation .Propagation ;
2731import org .springframework .transaction .annotation .Transactional ;
@@ -44,28 +48,53 @@ public class SessionQuestionsRequester {
4448 private final RabbitMqProperties properties ;
4549 private final AnalyzedDocumentRepository documentRepository ;
4650 private final ObjectStorageClient storage ;
51+ private final InterviewSessionRepository sessionRepository ;
52+ private final SessionQuestionPoolRepository questionPoolRepository ;
53+
54+ // 최근 몇 개 세션까지 거슬러 중복 질문을 회피할지. 0 이면 비활성.
55+ @ Value ("${interview.question-dedup.recent-sessions:3}" )
56+ private int recentSessionCount ;
57+ // AI 에 넘길 과거 질문 최대 개수 (envelope 비대화 방지).
58+ @ Value ("${interview.question-dedup.max-questions:30}" )
59+ private int maxRecentQuestions ;
4760
4861 @ Transactional (propagation = Propagation .NOT_SUPPORTED )
4962 @ TransactionalEventListener (phase = TransactionPhase .AFTER_COMMIT )
5063 public void onSessionCreated (SessionCreatedEvent event ) {
5164 List <DocumentContext > documents = buildDocumentContexts (event .contextDocumentIds ());
5265 int generalCount = event .generalQuestionCount () != null
5366 ? event .generalQuestionCount () : DEFAULT_GENERAL_QUESTION_COUNT ;
67+ List <String > recentQuestions = recentQuestions (event .userId (), event .sessionId ());
5468 GenerateQuestionsPayload payload = new GenerateQuestionsPayload (
5569 event .sessionId (),
5670 event .mode (),
5771 event .jobCategory (),
5872 documents ,
5973 generalCount ,
60- event .maxQuestions ()
74+ event .maxQuestions (),
75+ recentQuestions
6176 );
6277 publisher .publishToAi (
6378 properties .routingKeys ().generateQuestions (),
6479 payload ,
6580 new MessageContext (event .userId (), event .sessionId (), null , null )
6681 );
67- log .info ("generate.questions published. sessionId={}, doc_count={}, general_count={}, max={}" ,
68- event .sessionId (), documents .size (), generalCount , event .maxQuestions ());
82+ log .info ("generate.questions published. sessionId={}, doc_count={}, general_count={}, max={}, recent_q={}" ,
83+ event .sessionId (), documents .size (), generalCount , event .maxQuestions (), recentQuestions .size ());
84+ }
85+
86+ // 같은 유저의 최근 N개 세션에서 출제된 질문을 모아 AI 의 중복 회피용으로 전달.
87+ private List <String > recentQuestions (Long userId , Long currentSessionId ) {
88+ if (recentSessionCount <= 0 || maxRecentQuestions <= 0 ) {
89+ return List .of ();
90+ }
91+ List <Long > sessionIds = sessionRepository .findRecentSessionIds (
92+ userId , currentSessionId , PageRequest .of (0 , recentSessionCount ));
93+ if (sessionIds .isEmpty ()) {
94+ return List .of ();
95+ }
96+ return questionPoolRepository .findRecentQuestions (
97+ sessionIds , PageRequest .of (0 , maxRecentQuestions ));
6998 }
7099
71100 private List <DocumentContext > buildDocumentContexts (List <Long > documentIds ) {
0 commit comments