# 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 테이블

```sql
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. 의존성 설치

```bash
cd rag
pip install -r requirements.txt
```

### 2. 환경 변수 설정

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

```bash
# 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. 데이터베이스 초기화

```bash
cd rag
python scripts/init_rag_minutes.py
```

이 스크립트는 다음 작업을 수행합니다:
- `rag_minutes` 테이블 생성
- 필요한 인덱스 생성
- pgvector 확장 설치 확인

### 4. Event Hub Consumer 시작

```bash
cd rag
python start_consumer.py
```

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

### 5. API 서버 시작

```bash
cd rag/src
python -m api.main
```

또는:

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

## API 사용 예시

### 1. 연관 회의록 검색

**요청**:

```bash
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
  }'
```

**응답**:

```json
[
  {
    "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. 회의록 상세 조회

**요청**:

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

**응답**:

```json
{
  "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. 통계 조회

**요청**:

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

**응답**:

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

## Event Hub 메시지 형식

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

```json
{
  "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**: 유사도 측정에 최적화된 거리 메트릭

### 2. Full-text Search

- **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 연결 실패

```bash
# 연결 문자열 확인
echo $EVENTHUB_CONNECTION_STRING

# Event Hub 상태 확인 (Azure Portal)
```

### 2. Embedding 생성 실패

```bash
# OpenAI API 키 확인
echo $AZURE_OPENAI_API_KEY

# API 할당량 확인 (OpenAI Dashboard)
```

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

```bash
# 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. **배치 처리**: 대량의 과거 회의록 일괄 처리

## 참고 자료

- [pgvector](https://github.com/pgvector/pgvector): PostgreSQL의 Vector 확장
- [Azure Event Hubs](https://docs.microsoft.com/azure/event-hubs/): Azure Event Hubs 문서
- [OpenAI Embeddings](https://platform.openai.com/docs/guides/embeddings): OpenAI Embedding API 가이드
