mirror of
https://github.com/hwanny1128/HGZero.git
synced 2025-12-06 11:26:25 +00:00
376 lines
9.3 KiB
Markdown
376 lines
9.3 KiB
Markdown
# 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 가이드
|