hgzero/develop/dev/dev-ai-realtime-streaming.md
Minseo-Jo 14d03dcacf STT-AI 통합 작업 진행 중 변경사항 커밋
- AI 서비스 CORS 설정 업데이트
- 회의 진행 프로토타입 수정
- 빌드 리포트 및 로그 파일 업데이트

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-27 13:17:47 +09:00

11 KiB

실시간 AI 제안 스트리밍 개발 가이드

📋 개요

회의 진행 중 STT로 변환된 텍스트를 실시간으로 분석하여 논의사항/결정사항을 AI가 제안하는 기능

개발 일시: 2025-10-24 개발자: AI Specialist (서연) 사용 기술: Claude API, Azure Event Hub, Redis, SSE (Server-Sent Events)


🎯 구현된 기능

1. Claude API 클라이언트

  • 파일: ai/src/main/java/com/unicorn/hgzero/ai/infra/client/ClaudeApiClient.java
  • 기능:
    • Anthropic Claude API (claude-3-5-sonnet) 호출
    • 실시간 텍스트 분석하여 논의사항/결정사항 추출
    • JSON 응답 파싱 및 DTO 변환

2. Azure Event Hub Consumer

  • 파일: ai/src/main/java/com/unicorn/hgzero/ai/infra/config/EventHubConfig.java
  • 기능:
    • STT Service의 TranscriptSegmentReady 이벤트 구독
    • 실시간 음성 변환 텍스트 수신
    • SuggestionService로 전달하여 AI 분석 트리거

3. 실시간 텍스트 축적 로직

  • 파일: ai/src/main/java/com/unicorn/hgzero/ai/biz/service/SuggestionService.java
  • 메서드: processRealtimeTranscript()
  • 기능:
    • Redis Sorted Set을 이용한 슬라이딩 윈도우 (최근 5분 텍스트 유지)
    • 임계값 도달 시 자동 AI 분석 (10개 세그먼트 = 약 100-200자)

4. SSE 스트리밍

  • API: GET /api/suggestions/meetings/{meetingId}/stream
  • Controller: SuggestionController:111
  • 기능:
    • Server-Sent Events로 실시간 AI 제안사항 전송
    • 멀티캐스트 지원 (여러 클라이언트 동시 연결)
    • 자동 리소스 정리 (연결 종료 시)

🏗️ 아키텍처

[회의 진행 중]
    ↓
┌─────────────────────────────────────┐
│ 1. STT Service (Azure Speech)       │
│    - 음성 → 텍스트 실시간 변환      │
└─────────────────────────────────────┘
    ↓ Azure Event Hub
    ↓ (TranscriptSegmentReady Event)
    ↓
┌─────────────────────────────────────┐
│ 2. AI Service (Event Hub Consumer)  │
│    - 이벤트 수신                     │
│    - Redis에 텍스트 축적             │
└─────────────────────────────────────┘
    ↓
┌─────────────────────────────────────┐
│ 3. Redis (슬라이딩 윈도우)          │
│    - 최근 5분 텍스트 유지            │
│    - 임계값 체크 (10 segments)      │
└─────────────────────────────────────┘
    ↓
┌─────────────────────────────────────┐
│ 4. Claude API (Anthropic)           │
│    - 누적 텍스트 분석                │
│    - 논의사항/결정사항 추출          │
└─────────────────────────────────────┘
    ↓
┌─────────────────────────────────────┐
│ 5. SSE 스트리밍                      │
│    - 클라이언트에 실시간 전송        │
└─────────────────────────────────────┘

⚙️ 설정 방법

1. Claude API 키 발급

  1. Anthropic Console 접속
  2. API Keys → Create Key
  3. 생성된 API Key 복사

2. 환경 변수 설정

application.yml 또는 환경 변수에 추가:

# Claude API 설정
export CLAUDE_API_KEY="sk-ant-api03-..."
export CLAUDE_MODEL="claude-3-5-sonnet-20241022"
export CLAUDE_MAX_TOKENS="2000"
export CLAUDE_TEMPERATURE="0.3"

# Azure Event Hub 설정 (이미 설정됨)
export AZURE_EVENTHUB_CONNECTION_STRING="Endpoint=sb://hgzero-eventhub-ns.servicebus.windows.net/;..."
export AZURE_EVENTHUB_NAME="hgzero-eventhub-name"
export AZURE_EVENTHUB_CONSUMER_GROUP_TRANSCRIPT="ai-transcript-group"

# Redis 설정 (이미 설정됨)
export REDIS_HOST="20.249.177.114"
export REDIS_PORT="6379"
export REDIS_PASSWORD="Hi5Jessica!"
export REDIS_DATABASE="4"

3. 의존성 확인

ai/build.gradle에 이미 추가됨:

dependencies {
    // Common module
    implementation project(':common')

    // Redis
    implementation 'org.springframework.boot:spring-boot-starter-data-redis'

    // Anthropic Claude SDK
    implementation 'com.anthropic:anthropic-sdk-java:0.1.0'

    // Azure Event Hubs
    implementation "com.azure:azure-messaging-eventhubs:${azureEventHubsVersion}"
    implementation "com.azure:azure-messaging-eventhubs-checkpointstore-blob:${azureEventHubsCheckpointVersion}"

    // Spring WebFlux for SSE streaming
    implementation 'org.springframework.boot:spring-boot-starter-webflux'
}

🚀 실행 방법

1. AI Service 빌드

cd /Users/jominseo/HGZero
./gradlew :ai:build -x test

2. AI Service 실행

cd ai
./gradlew bootRun

또는 IntelliJ Run Configuration 사용

3. 클라이언트 테스트 (회의진행.html)

// SSE 연결
const meetingId = "MTG-2025-001";
const eventSource = new EventSource(`/api/suggestions/meetings/${meetingId}/stream`);

// AI 제안사항 수신
eventSource.addEventListener('ai-suggestion', (event) => {
  const suggestion = JSON.parse(event.data);
  console.log('실시간 AI 제안:', suggestion);

  // 논의사항 UI 업데이트
  suggestion.discussionTopics.forEach(topic => {
    addDiscussionToUI(topic);
  });

  // 결정사항 UI 업데이트
  suggestion.decisions.forEach(decision => {
    addDecisionToUI(decision);
  });
});

// 에러 처리
eventSource.onerror = (error) => {
  console.error('SSE 연결 오류:', error);
  eventSource.close();
};

// 회의 종료 시 연결 종료
function endMeeting() {
  eventSource.close();
}

📊 데이터 흐름

Event Hub 이벤트 구조

{
  "recordingId": "REC-20250123-001",
  "meetingId": "MTG-2025-001",
  "transcriptId": "TRS-SEG-001",
  "text": "안녕하세요, 오늘 회의를 시작하겠습니다.",
  "timestamp": 1234567890,
  "confidence": 0.92,
  "eventTime": "2025-01-23T10:30:00Z"
}

Claude API 응답 구조

{
  "discussions": [
    {
      "topic": "보안 요구사항 검토",
      "reason": "안건에 포함되어 있으나 아직 논의되지 않음",
      "priority": "HIGH"
    }
  ],
  "decisions": [
    {
      "content": "React로 프론트엔드 개발",
      "confidence": 0.9,
      "extractedFrom": "프론트엔드는 React로 개발하기로 했습니다"
    }
  ]
}

SSE 스트리밍 응답

event: ai-suggestion
id: 12345
data: {"discussionTopics":[...],"decisions":[...]}

event: ai-suggestion
id: 12346
data: {"discussionTopics":[...],"decisions":[...]}

🔧 주요 설정값

설정 설명
MIN_SEGMENTS_FOR_ANALYSIS 10 AI 분석 시작 임계값 (세그먼트 수)
TEXT_RETENTION_MS 300000 (5분) Redis 텍스트 보관 기간
CLAUDE_MODEL claude-3-5-sonnet-20241022 사용 Claude 모델
CLAUDE_MAX_TOKENS 2000 최대 응답 토큰 수
CLAUDE_TEMPERATURE 0.3 창의성 수준 (0-1)

🐛 트러블슈팅

1. Event Hub 연결 실패

증상: Event Hub Processor 시작 실패 로그

해결:

# 연결 문자열 확인
echo $AZURE_EVENTHUB_CONNECTION_STRING

# Consumer Group 확인
echo $AZURE_EVENTHUB_CONSUMER_GROUP_TRANSCRIPT

2. Claude API 호출 실패

증상: Claude API 호출 실패 로그

해결:

# API 키 확인
echo $CLAUDE_API_KEY

# 네트워크 연결 확인
curl -X POST https://api.anthropic.com/v1/messages \
  -H "x-api-key: $CLAUDE_API_KEY" \
  -H "anthropic-version: 2023-06-01" \
  -H "content-type: application/json"

3. Redis 연결 실패

증상: Unable to connect to Redis 로그

해결:

# Redis 연결 테스트
redis-cli -h $REDIS_HOST -p $REDIS_PORT -a $REDIS_PASSWORD ping

# 응답: PONG

4. SSE 스트림 끊김

증상: 클라이언트에서 연결이 자주 끊김

해결:

// 자동 재연결 로직 추가
function connectSSE(meetingId) {
  const eventSource = new EventSource(`/api/suggestions/meetings/${meetingId}/stream`);

  eventSource.onerror = (error) => {
    console.error('SSE 연결 오류, 5초 후 재연결...');
    eventSource.close();
    setTimeout(() => connectSSE(meetingId), 5000);
  };

  return eventSource;
}

📈 성능 최적화

1. Redis 메모리 관리

  • 슬라이딩 윈도우로 최근 5분만 유지
  • 회의 종료 시 자동 삭제
  • TTL 설정 고려 (향후 추가)

2. Claude API 호출 최적화

  • 임계값 도달 시에만 호출 (불필요한 호출 방지)
  • 비동기 처리로 응답 대기 시간 최소화
  • 에러 발생 시 빈 응답 반환 (서비스 중단 방지)

3. SSE 연결 관리

  • 멀티캐스트로 여러 클라이언트 동시 지원
  • 연결 종료 시 자동 리소스 정리
  • Backpressure 버퍼링으로 과부하 방지

🔜 향후 개발 계획

Phase 2: AI 정확도 향상

  • 회의 안건 기반 맥락 분석
  • 과거 회의록 참조 (RAG)
  • 조직별 용어 사전 통합

Phase 3: 성능 개선

  • Redis TTL 자동 설정
  • Claude API 캐싱 전략
  • 배치 분석 옵션 추가

Phase 4: 모니터링

  • AI 제안 정확도 측정
  • 응답 시간 메트릭 수집
  • 사용량 대시보드 구축

📚 참고 자료


체크리스트

  • Claude API 클라이언트 구현
  • Azure Event Hub Consumer 구현
  • Redis 슬라이딩 윈도우 구현
  • SSE 스트리밍 구현
  • SuggestionService 통합
  • Claude API 키 발급 및 설정
  • 통합 테스트 (STT → AI → SSE)
  • 프론트엔드 연동 테스트

개발 완료: 2025-10-24 다음 단계: Claude API 키 발급 및 통합 테스트