feat: add getting ralated document in realtime

This commit is contained in:
djeon
2025-10-30 13:42:11 +09:00
parent f133faa509
commit 9580de9c82
7 changed files with 204 additions and 4 deletions
+108 -2
View File
@@ -130,7 +130,7 @@ class EventHubConsumer:
await self._process_minutes_event(event_data)
elif event_type == "SegmentCreated":
# 세그먼트 생성 이벤트 - 용어검색 실행
# 세그먼트 생성 이벤트 - 용어검색 및 연관 회의록 검색 실행
await self._process_segment_event(event_data)
# Checkpoint 업데이트
@@ -294,7 +294,8 @@ class EventHubConsumer:
# 7. SSE를 통해 결과 전송
# Event Hub 메시지에서 sessionId 추출 (여러 필드 확인)
session_id = event_data.get("sessionId") or event_data.get("session_id") or event_data.get("meetingId") or meeting_id
session_id = event_data.get("sessionId")
# session_id = event_data.get("sessionId") or event_data.get("session_id") or event_data.get("meetingId") or meeting_id
logger.info(f"SSE 전송 시도: sessionId={session_id}, meetingId={meeting_id}")
@@ -337,9 +338,114 @@ class EventHubConsumer:
else:
logger.warning("이벤트 데이터에 sessionId가 없어 SSE 전송을 건너뜁니다")
# 8. 연관 회의록 검색 및 SSE 전송
await self._search_and_send_related_minutes(text, session_id, segment_id, meeting_id)
except Exception as e:
logger.error(f"세그먼트 이벤트 처리 실패: {str(e)}", exc_info=True)
async def _search_and_send_related_minutes(
self,
text: str,
session_id: Optional[str],
segment_id: str,
meeting_id: str
):
"""
연관 회의록 검색 및 SSE 전송
Args:
text: 세그먼트 텍스트
session_id: 세션 ID
segment_id: 세그먼트 ID
meeting_id: 회의 ID
"""
try:
# RAG Minutes DB가 없으면 스킵
if not self.rag_minutes_db:
logger.debug("RAG Minutes DB가 설정되지 않아 연관 회의록 검색을 스킵합니다")
return
if not text:
logger.warning(f"세그먼트 {segment_id}에 텍스트가 없어 연관 회의록 검색을 스킵합니다")
return
logger.info(f"세그먼트 연관 회의록 검색 시작: {segment_id} (회의: {meeting_id})")
logger.info(f"검색 텍스트: {text[:100]}...")
# 1. 텍스트를 임베딩으로 변환
query_embedding = self.embedding_gen.generate_embedding(text)
logger.info(f"임베딩 생성 완료: {len(query_embedding)}차원")
# 2. 연관 회의록 검색 설정
config = self.config.get("rag_minutes", {})
search_config = config.get("search", {})
top_k = search_config.get("top_k", 5)
similarity_threshold = search_config.get("similarity_threshold", 0.7)
# 3. 벡터 유사도 검색
results = self.rag_minutes_db.search_by_vector(
query_embedding=query_embedding,
top_k=top_k,
similarity_threshold=similarity_threshold
)
# 4. 검색 결과 로깅
if results:
logger.info(f"세그먼트 {segment_id} 연관 회의록 검색 완료: {len(results)}개 발견")
for idx, result in enumerate(results, 1):
minutes = result["minutes"]
score = result["similarity_score"]
logger.info(
f" [{idx}] {minutes.title} "
f"(회의 ID: {minutes.meeting_id}, 유사도: {score:.3f})"
)
else:
logger.info(f"세그먼트 {segment_id}에서 연관 회의록을 찾지 못했습니다")
# 5. SSE를 통해 결과 전송
if session_id:
from ..services.sse_manager import sse_manager
# 회의록 정보를 직렬화 가능한 형태로 변환
minutes_data = []
for result in results:
minutes = result["minutes"]
minutes_data.append({
"minutes_id": minutes.minutes_id,
"meeting_id": minutes.meeting_id,
"title": minutes.title,
"purpose": minutes.purpose,
"scheduled_at": minutes.scheduled_at,
"location": minutes.location,
"finalized_at": minutes.finalized_at,
"similarity_score": result["similarity_score"]
})
# SSE로 전송
success = await sse_manager.send_to_session(
session_id=session_id,
data={
"segment_id": segment_id,
"meeting_id": meeting_id,
"text": text[:100], # 텍스트 일부만 전송
"related_minutes": minutes_data,
"total_count": len(minutes_data)
},
event_type="related_minutes_result"
)
if success:
logger.info(f"연관 회의록 검색 결과를 SSE로 전송 완료: {session_id}")
else:
logger.warning(f"SSE 전송 실패 (세션 미연결): {session_id}")
else:
logger.warning("세션 ID가 없어 연관 회의록 SSE 전송을 건너뜁니다")
except Exception as e:
logger.error(f"연관 회의록 검색 및 전송 실패: {str(e)}", exc_info=True)
def _convert_datetime_array_to_string(self, value: Union[str, List, None]) -> Optional[str]:
"""
Java LocalDateTime 배열을 ISO 8601 문자열로 변환