hgzero/rag/README_RAG_MINUTES.md
2025-10-29 05:54:08 +09:00

9.3 KiB

RAG 회의록 서비스

회의록 RAG(Retrieval-Augmented Generation) 서비스는 확정된 회의록을 embedding 벡터와 함께 저장하고, 유사한 회의록을 검색할 수 있는 기능을 제공합니다.

아키텍처

Meeting Service                  RAG Service
    |                                |
    | 1. 회의록 확정                  |
    |                                |
    v                                |
Event Hub --------------------------> Event Hub Consumer
(MINUTES_FINALIZED)                  |
                                     | 2. 메시지 Consume
                                     |
                                     v
                                  Embedding 생성
                                  (OpenAI text-embedding-ada-002)
                                     |
                                     v
                                  PostgreSQL + pgvector
                                  (rag_minutes 테이블)
                                     |
                                     | 3. 연관 회의록 조회
                                     |
                                     v
                                  Vector Similarity Search
                                  (Cosine Distance)

주요 기능

1. 회의록 RAG 저장

  • 트리거: Meeting 서비스에서 회의록 확정 시 Event Hub로 이벤트 발행
  • 처리 흐름:
    1. Event Hub Consumer가 MINUTES_FINALIZED 이벤트 수신
    2. 회의록 전체 내용을 텍스트로 생성 (제목 + 목적 + 섹션 내용)
    3. OpenAI Embedding API를 사용하여 1536차원 벡터 생성
    4. rag_minutes 테이블에 회의록 정보와 embedding 벡터 저장

2. 연관 회의록 조회

  • API: POST /api/minutes/search
  • 검색 방식: Vector Similarity Search (Cosine Distance)
  • 입력: 최종 회의록 내용 (full_content)
  • 출력: 유사도 높은 회의록 목록 (상위 K개, 기본값 5개)

3. 회의록 상세 조회

  • API: GET /api/minutes/{minutes_id}
  • 출력: 회의록 전체 정보 (Meeting 정보, Minutes 정보, Sections)

데이터베이스 스키마

rag_minutes 테이블

CREATE TABLE rag_minutes (
    -- Meeting 정보
    meeting_id VARCHAR(50) NOT NULL,
    title VARCHAR(200) NOT NULL,
    purpose VARCHAR(500),
    description TEXT,
    scheduled_at TIMESTAMP,
    location VARCHAR(200),
    organizer_id VARCHAR(50) NOT NULL,

    -- Minutes 정보
    minutes_id VARCHAR(50) PRIMARY KEY,
    minutes_status VARCHAR(20) NOT NULL DEFAULT 'FINALIZED',
    minutes_version INTEGER NOT NULL DEFAULT 1,
    created_by VARCHAR(50) NOT NULL,
    finalized_by VARCHAR(50),
    finalized_at TIMESTAMP,

    -- 회의록 섹션 (JSON)
    sections JSONB,

    -- 전체 회의록 내용 (검색용)
    full_content TEXT NOT NULL,

    -- Embedding 벡터
    embedding vector(1536),

    -- 메타데이터
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);

인덱스

  • idx_rag_minutes_meeting_id: Meeting ID로 검색
  • idx_rag_minutes_title: 제목으로 검색
  • idx_rag_minutes_finalized_at: 확정 일시로 정렬
  • idx_rag_minutes_created_by: 작성자로 검색
  • idx_rag_minutes_embedding: 벡터 유사도 검색 (IVFFlat 인덱스)
  • idx_rag_minutes_full_content_gin: Full-text 검색 (GIN 인덱스)

설치 및 실행

1. 의존성 설치

cd rag
pip install -r requirements.txt

2. 환경 변수 설정

.env 파일에 다음 환경 변수 추가:

# PostgreSQL
POSTGRES_HOST=4.217.133.186
POSTGRES_PORT=5432
POSTGRES_DATABASE=ragdb
POSTGRES_USER=hgzerouser
POSTGRES_PASSWORD=Hi5Jessica!

# Azure OpenAI (Embedding)
AZURE_OPENAI_API_KEY=your-api-key
AZURE_OPENAI_ENDPOINT=https://api.openai.com/v1/embeddings

# Azure Event Hub
EVENTHUB_CONNECTION_STRING=Endpoint=sb://hgzero-eventhub-ns.servicebus.windows.net/;...
EVENTHUB_NAME=hgzero-eventhub-name
AZURE_EVENTHUB_CONSUMER_GROUP=$Default
AZURE_STORAGE_CONNECTION_STRING=DefaultEndpointsProtocol=https;AccountName=hgzerostorage;...
AZURE_STORAGE_CONTAINER_NAME=hgzero-checkpoints

3. 데이터베이스 초기화

cd rag
python scripts/init_rag_minutes.py

이 스크립트는 다음 작업을 수행합니다:

  • rag_minutes 테이블 생성
  • 필요한 인덱스 생성
  • pgvector 확장 설치 확인

4. Event Hub Consumer 시작

cd rag
python start_consumer.py

Consumer는 백그라운드에서 실행되며 Event Hub로부터 회의록 확정 이벤트를 수신합니다.

5. API 서버 시작

cd rag/src
python -m api.main

또는:

cd rag
uvicorn src.api.main:app --host 0.0.0.0 --port 8000 --reload

API 사용 예시

1. 연관 회의록 검색

요청:

curl -X POST "http://localhost:8000/api/minutes/search" \
  -H "Content-Type: application/json" \
  -d '{
    "query": "2025년 1분기 마케팅 전략 수립 및 실행 계획",
    "top_k": 5,
    "similarity_threshold": 0.7
  }'

응답:

[
  {
    "minutes": {
      "meeting_id": "MTG-2025-001",
      "title": "2025 Q1 마케팅 전략 회의",
      "minutes_id": "MIN-2025-001",
      "full_content": "...",
      "sections": [...]
    },
    "similarity_score": 0.92
  },
  {
    "minutes": {
      "meeting_id": "MTG-2024-098",
      "title": "2024 Q4 마케팅 결산",
      "minutes_id": "MIN-2024-098",
      "full_content": "...",
      "sections": [...]
    },
    "similarity_score": 0.85
  }
]

2. 회의록 상세 조회

요청:

curl "http://localhost:8000/api/minutes/MIN-2025-001"

응답:

{
  "meeting_id": "MTG-2025-001",
  "title": "2025 Q1 마케팅 전략 회의",
  "purpose": "2025년 1분기 마케팅 전략 수립",
  "minutes_id": "MIN-2025-001",
  "minutes_status": "FINALIZED",
  "sections": [
    {
      "section_id": "SEC-001",
      "type": "DISCUSSION",
      "title": "시장 분석",
      "content": "2025년 시장 동향 분석...",
      "order": 1,
      "verified": true
    }
  ],
  "full_content": "...",
  "created_at": "2025-01-15T10:30:00",
  "finalized_at": "2025-01-15T12:00:00"
}

3. 통계 조회

요청:

curl "http://localhost:8000/api/minutes/stats"

응답:

{
  "total_minutes": 150,
  "total_meetings": 145,
  "total_authors": 25,
  "latest_finalized_at": "2025-01-20T15:30:00"
}

Event Hub 메시지 형식

Meeting 서비스에서 발행하는 회의록 확정 이벤트 형식:

{
  "event_type": "MINUTES_FINALIZED",
  "timestamp": "2025-01-15T12:00:00Z",
  "data": {
    "meeting_id": "MTG-2025-001",
    "title": "2025 Q1 마케팅 전략 회의",
    "purpose": "2025년 1분기 마케팅 전략 수립",
    "description": "...",
    "scheduled_at": "2025-01-15T10:00:00",
    "location": "본사 3층 회의실",
    "organizer_id": "organizer@example.com",
    "minutes_id": "MIN-2025-001",
    "status": "FINALIZED",
    "version": 1,
    "created_by": "user@example.com",
    "finalized_by": "user@example.com",
    "finalized_at": "2025-01-15T12:00:00",
    "sections": [
      {
        "section_id": "SEC-001",
        "type": "DISCUSSION",
        "title": "시장 분석",
        "content": "2025년 시장 동향 분석...",
        "order": 1,
        "verified": true
      }
    ]
  }
}

성능 최적화

1. Vector Search 최적화

  • IVFFlat 인덱스: 대량의 벡터 데이터에 대한 근사 검색
  • lists 파라미터: 데이터 크기에 따라 조정 (기본값: 100)
  • Cosine Distance: 유사도 측정에 최적화된 거리 메트릭
  • GIN 인덱스: 텍스트 검색 성능 향상
  • to_tsvector: PostgreSQL의 Full-text Search 기능 활용

3. Embedding 생성

  • 배치 처리: 여러 회의록을 동시에 처리할 때 배치 API 활용
  • 캐싱: 동일한 내용에 대한 중복 embedding 생성 방지

모니터링

1. 로그

  • Consumer 로그: logs/rag-consumer.log
  • API 로그: logs/rag-api.log

2. 메트릭

  • 초당 처리 이벤트 수
  • 평균 embedding 생성 시간
  • 평균 검색 응답 시간
  • 데이터베이스 연결 상태

문제 해결

1. Event Hub 연결 실패

# 연결 문자열 확인
echo $EVENTHUB_CONNECTION_STRING

# Event Hub 상태 확인 (Azure Portal)

2. Embedding 생성 실패

# OpenAI API 키 확인
echo $AZURE_OPENAI_API_KEY

# API 할당량 확인 (OpenAI Dashboard)

3. 데이터베이스 연결 실패

# PostgreSQL 연결 확인
psql -h $POSTGRES_HOST -U $POSTGRES_USER -d $POSTGRES_DATABASE

# pgvector 확장 확인
SELECT * FROM pg_extension WHERE extname = 'vector';

향후 개선 사항

  1. 하이브리드 검색: Keyword + Vector 검색 결합
  2. 재랭킹: 검색 결과 재정렬 알고리즘 추가
  3. 메타데이터 필터링: 날짜, 작성자, 카테고리 등으로 필터링
  4. 설명 생성: Claude AI를 활용한 유사 회의록 관계 설명
  5. 배치 처리: 대량의 과거 회의록 일괄 처리

참고 자료