Skip to content

Feature/sprint3 feedback rag#38

Merged
i3months merged 5 commits into
devfrom
feature/sprint3-feedback-rag
May 31, 2026
Merged

Feature/sprint3 feedback rag#38
i3months merged 5 commits into
devfrom
feature/sprint3-feedback-rag

Conversation

@i3months

Copy link
Copy Markdown
Member

Summary

Sprint 3 — 종합 피드백(US-24) + RAG 검색 활성화 + 음성 면접 풀스택 구현

주요 변경

  • Core /api/internal/embeddings/search (pgvector cosine topK)
  • 음성 답변 풀스택 (multipart 업로드 → analyze.voice → STT/분석 → callback.voice
    → AnswerSubmittedEvent → 기존 followup 흐름 재사용)
  • AI voice/stt 추상화 + Mock / OpenAI Whisper / Deepgram 3종 provider
  • WPM, 한국어 간투어, silence, 발음 정확도(confidence/logprob 기반) 분석

i3months added 5 commits May 30, 2026 16:55
Sprint 3 백엔드/AI 본 구현. US-24 (종합 피드백) + RAG 검색 활성화.

## 메시징 인프라
- ai.generate.feedback / core.callback.feedback 큐 + DLQ 추가
  (infra/rabbitmq/definitions.json, RabbitMqConfig, RabbitMqProperties, application.yml)

## Core 피드백 도메인
- SessionEndedEvent (USER_REQUEST | MAX_QUESTIONS_REACHED)
  - SessionService.end + QuestionsCallbackService.applyFollowup 자동 종료 시 발화
- SessionFeedbackRequester @TransactionalEventListener(AFTER_COMMIT, REQUIRES_NEW)
  → 메시지 시퀀스 + 컨텍스트 문서 ID 수집 → generate.feedback 발행
- FeedbackCallbackService + Handler — session_feedbacks INSERT + SSE FEEDBACK_READY
  멱등: processed_messages + session_feedbacks UNIQUE(session_id)
- GET /api/sessions/{id}/feedback (SessionFeedbackQueryService)
- SessionFeedback.of() factory + JdbcType JSON 매핑

## Core embeddings search API
- POST /api/internal/embeddings/search (X-Internal-API-Key)
- JdbcDocumentEmbeddingRepository.search() — pgvector cosine `<=>` topK 검색
  documentIds 필터 옵션, NamedParameterJdbcTemplate IN 절 동적 바인딩

## AI 서버
- generate.feedback consumer (LangChain Pro 모델, FeedbackResult Pydantic)
- 프롬프트: 시퀀스 흐름 우선, 4점 + 강점/약점/개선 키워드
- RAG: 마지막 INTERVIEWEE 답변을 쿼리로 임베딩 → Core search → topK 청크 주입
- CoreClient.search_embeddings() — 실패 시 빈 리스트 (RAG 보강용, fatal 아님)

## 테스트
- FeedbackCallbackServiceTest (Mockito): apply, 중복 messageId skip, 기존 feedback skip
- SessionFeedbackRequesterTest: publish 호출, 기존 feedback 시 skip
- AI test_feedback_consumer.py: 생성+발행, RAG 호출, 멱등 skip
- 백엔드 + AI 전 테스트 통과 (BUILD SUCCESSFUL, 132 passed)

## Sprint 4 분리
- 음성 모듈 (Whisper STT, WPM/filler/silence) — Phase 2
- WebSocket — Phase 1 in-memory SSE 단일화 유지
ai/CLAUDE.md §8 의 Phase 2 음성 모듈 본 구현. 텍스트 면접의 답변 흐름과 동일한
이벤트 모델 위에 음성 답변을 1급 시민으로 추가.

## 메시징 인프라
- ai.analyze.voice / core.callback.voice 큐 + DLQ + 라우팅 키
  (infra/rabbitmq/definitions.json, RabbitMqProperties, application.yml, RabbitMqConfig)

## Core 음성 답변 흐름
- POST /api/sessions/{id}/messages/voice (multipart/form-data, Idempotency-Key)
  - InterviewMessage placeholder INSERT (content="(transcribing)", status=CREATED)
  - S3 PUT (`interview/voice/raw/{sid}/{mid}.{ext}`)
  - analyze.voice 발행 (envelope: 메시지 id, S3 key, 직전 질문 hint, interview type 등)
- VoiceCallbackHandler/Service — callback.voice 수신
  - completeWithTranscript(content) + markStatus(COMPLETED)
  - MessageVoiceAnalysis INSERT (wpm/silence/filler/accuracy)
  - SSE SESSION_MESSAGE transcribed 알림
  - AnswerSubmittedEvent 발화 → 기존 SessionFollowupRequester 재사용 (텍스트와 동일 follow-up)
- 에러 코드 도착 시 message FAILED 마킹 + SSE 알림 (followup 미발화)
- 멱등: processed_messages + message_voice_analyses UNIQUE(message_id)
- 입력 검증: 25MB 캡, audio/webm·ogg·mp3·m4a·wav 화이트리스트

## AI 음성 모듈 신설 (`ai/src/ai_server/voice/`)
- stt/base.py — SttProvider Protocol + TranscriptionResult/Segment + SttError
- stt/openai_whisper.py — OpenAI `/audio/transcriptions` 직접 호출
  (Mindlogic 게이트웨이가 STT 미지원이라 우회. response_format=verbose_json 으로
  segment timestamps + logprob 회수)
- stt/mock.py — 더미 transcript (OPENAI_API_KEY 미발급 시 fallback)
- stt/factory.py — STT_PROVIDER 토글 + 키 누락 시 mock fallback
- analysis/metrics.py — WPM(어절/분), 한국어 간투어(`(?:음+|어+|그+|아+)`),
  silence(앞/뒤 패딩 + segment 갭 합산), 발음 정확도(exp(avg_logprob) 평균)
- messaging/consumers/voice_consumer.py — S3 GET → STT → 분석 → callback.voice 발행
  - 실패 분기: AUDIO_FETCH_FAILED / STT_AUTH_FAILED / TRANSCRIPTION_FAILED 등 코드 회신

## 환경변수 카탈로그
- STT_PROVIDER, OPENAI_API_KEY, OPENAI_BASE_URL, WHISPER_MODEL, WHISPER_LANGUAGE
  (.env.example × 2, docker-compose.yml ai 서비스 매핑)

## 테스트
- AI 단위: test_voice_metrics.py (4) + test_voice_consumer.py (4)
- Backend 단위: VoiceCallbackServiceTest (3)
- 전체: backend BUILD SUCCESSFUL, AI 140 passed
- ArchUnit `entities_do_not_have_public_setters` 통과 — `attachAudio`,
  `completeWithTranscript` 등 도메인 의미 메서드만 추가

## Sprint 4 후속 (별도 PR)
- WebSocket(RT3) 실시간 음성 청크 스트리밍 — 현재는 multipart 한 번에 업로드 MVP
- TTS provider
신규 큐(ai.generate.feedback, ai.analyze.voice 등) 는 운영 RabbitMQ 에 아직 없고
Spring RabbitMqConfig 가 부팅 시점에 declare 한다. AI runner.py 는 passive=true 로
큐 검색이라 큐 없으면 NOT_FOUND 로 즉시 종료.

ai 의 depends_on 에 backend healthcheck 를 추가해 backend 가 큐 declare 마친 뒤
ai 가 시작하도록 순서 보장. 첫 배포 race 차단.
GitHub Repository Secret 에 OPENAI_API_KEY 가 등록돼 있어도 워크플로 매핑이 없으면
운영 .env 에 박히지 않아 STT 가 mock 으로 fallback. 매핑 + upsert 추가.

키가 실제 주입된 경우(secret 값 비어있지 않음)에만 STT_PROVIDER=openai_whisper 로
자동 전환. 누락 또는 빈 값이면 .env.example default(mock) 유지 — 안전한 fallback.
Deepgram (한국어 정확도 우선, $200 신규 크레딧) STT 추가. OpenAI Whisper API
유료 대비 비용 부담 ↓, 정확도 ≈ (model=whisper-large 사용 시).

## AI
- voice/stt/deepgram.py — POST /v1/listen, utterances 우선 + alternative fallback,
  confidence → logprob 변환으로 기존 metrics.pronunciation_accuracy 그대로 호환
- factory.py — STT_PROVIDER=auto 시 deepgram > openai_whisper > mock 자동 선택,
  명시 provider 의 키 누락 시 안전한 mock fallback
- settings — deepgram_* 5종 + stt_provider Literal 에 auto/deepgram 추가
- 단위 테스트 4개 (성공/utterance 없음/auth 실패/5xx) — 총 144 passed

## 운영 자동 주입
- .env.example × 2, docker-compose.yml ai 서비스 환경변수 매핑
- deploy-app.yml: DEEPGRAM_API_KEY GitHub Secret 매핑 + upsert_env
- STT_PROVIDER 는 키 1개라도 있으면 자동 'auto' (factory 가 우선순위로 결정)

OPENAI_API_KEY 가 없어도 DEEPGRAM_API_KEY 만 있으면 Deepgram 으로 STT 동작.
둘 다 없으면 mock 유지 (안전한 fallback).
@vercel

vercel Bot commented May 31, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
stackup Ready Ready Preview, Comment May 31, 2026 1:40pm

@i3months i3months merged commit 39c505c into dev May 31, 2026
3 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant