hgzero/design/구현방안-맥락기반용어설명.md
hiondal 34dbe84151 맥락기반용어설명 구현방안 작성 완료
- 전체 팀원 토의를 통한 하이브리드형(단계별 확장) 최적안 도출
- 데이터 수집/정제/벡터라이징 전략 수립
- Claude API 호출 구조 설계 (프롬프트, JSON 요청/응답)
- Phase 1-3 단계별 구현 로드맵 (2주/4주/6주)
- 성능 목표: 응답시간 5초→3초→2초, 정확도 70%→85%→90%
- 비용 최적화: Redis 캐싱으로 60% 절감 ($45→$18/월)
- 기술 스택: OpenAI Embedding + Pinecone + Claude 3.5 + Redis
- 하이브리드 검색: 벡터 70% + 키워드 30%
- 품질 검증 기준 및 운영 모니터링 전략 포함

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-20 16:56:51 +09:00

30 KiB
Raw Blame History

맥락기반 용어설명 구현방안

문서 정보

  • 작성일: 2025-01-20
  • 작성자: AI Specialist 박서연, Backend Developer 이준호/이동욱, Architect 홍길동
  • 버전: 2.0 (하이브리드형 - 단계별 확장 방식)
  • 상태: 최종 승인

목차

  1. 개요
  2. 아키텍처 설계
  3. 데이터 수집 및 정제
  4. 벡터라이징 전략
  5. Claude API 호출 구조
  6. 단계별 구현 로드맵
  7. 성능 및 비용 최적화
  8. 품질 검증 기준
  9. 운영 및 모니터링

개요

목적

회의록 작성자가 업무 지식이 없어도, AI가 맥락에 맞는 실용적인 용어 설명을 자동으로 제공하여 정확한 회의록 작성을 지원합니다.

핵심 차별화 포인트

  • 단순 용어 정의 (Wikipedia 스타일)
  • 조직 내 실제 사용 맥락 제공
  • 관련 회의록 및 프로젝트 연결
  • 과거 논의 요약 (언제, 누가, 어떻게 사용했는지)

관련 유저스토리

  • UFR-RAG-010: 전문용어 자동 감지
  • UFR-RAG-020: 맥락 기반 용어 설명 생성

아키텍처 설계

전체 아키텍처 (최종 목표)

┌─────────────────────────────────────────────────────────┐
│                    회의록 작성 중                        │
│                (전문용어 "RAG" 감지)                     │
└──────────────────┬──────────────────────────────────────┘
                   │
                   ▼
┌─────────────────────────────────────────────────────────┐
│              RAG 서비스 (Node.js)                       │
│  ┌───────────────────────────────────────────────────┐ │
│  │ 1. 용어 감지 엔진                                 │ │
│  │    - 용어 사전 매칭 (Trie 자료구조)             │ │
│  │    - 신뢰도 계산 (0-100%)                        │ │
│  └───────────────────────────────────────────────────┘ │
│  ┌───────────────────────────────────────────────────┐ │
│  │ 2. Redis 캐시 조회                                │ │
│  │    Key: term:{용어명}:{회의ID}                    │ │
│  │    TTL: 자주 쓰이는 용어 7일, 드문 용어 1일       │ │
│  └───────────────────────────────────────────────────┘ │
│         ▼ (캐시 미스)                                   │
│  ┌───────────────────────────────────────────────────┐ │
│  │ 3. 벡터 검색 (Pinecone)                           │ │
│  │    - Query Embedding (OpenAI text-embedding-3)    │ │
│  │    - 하이브리드 검색 (벡터 + 키워드)              │ │
│  │    - Top 5 관련 문서 추출                         │ │
│  └───────────────────────────────────────────────────┘ │
│         ▼                                               │
│  ┌───────────────────────────────────────────────────┐ │
│  │ 4. Claude API 호출                                │ │
│  │    - 프롬프트: System + User + Few-shot           │ │
│  │    - 응답: JSON {definition, context, related}    │ │
│  └───────────────────────────────────────────────────┘ │
│         ▼                                               │
│  ┌───────────────────────────────────────────────────┐ │
│  │ 5. 응답 캐싱 (Redis)                              │ │
│  │    - 다음 요청 시 즉시 반환                       │ │
│  └───────────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────┘
                   │
                   ▼
┌─────────────────────────────────────────────────────────┐
│            사용자에게 설명 표시                          │
│  - 간단한 정의 (1-2문장)                                │
│  - 맥락 기반 설명                                        │
│  - 관련 회의록 링크 (최대 3개)                          │
│  - 과거 사용 사례                                        │
└─────────────────────────────────────────────────────────┘

기술 스택

계층 기술 선택 이유
임베딩 모델 OpenAI text-embedding-3-large 높은 정확도 (1536 차원), 안정적 API
벡터 DB Pinecone 관리형 서비스, 빠른 검색, Kubernetes 호환
LLM Claude 3.5 Sonnet 긴 컨텍스트, 한국어 성능 우수, JSON 응답 안정적
캐시 Redis 빠른 응답, TTL 지원, 분산 캐시 가능
메시지 큐 RabbitMQ 배치 작업 비동기 처리
오케스트레이션 Kubernetes 스케일링, 배포 자동화

데이터 수집 및 정제

1. 데이터 수집 범위

Phase 1 (2주): 회의록만

회의록 DB (Meeting 서비스)
  ├─ meeting_id
  ├─ title
  ├─ content (Markdown)
  ├─ participants
  ├─ date
  └─ project_id

Phase 2 (4주): 위키 추가

사내 위키 (Confluence, Notion 등)
  ├─ page_id
  ├─ title
  ├─ content
  ├─ author
  ├─ last_updated
  └─ tags

Phase 3 (6주): 프로젝트 문서 + 이메일

프로젝트 문서 (Google Drive, SharePoint)
  ├─ doc_id
  ├─ title
  ├─ content
  ├─ project_id
  └─ created_at

이메일 (Outlook, Gmail)
  ├─ email_id
  ├─ subject
  ├─ body (HTML → Plain Text 변환)
  ├─ sender
  └─ date

2. 데이터 정제 파이프라인

graph LR
    A[원본 수집] --> B[전처리]
    B --> C[메타데이터 추가]
    C --> D[벡터화]
    D --> E[Pinecone 저장]

    B --> B1[불용어 제거]
    B --> B2[토큰화]
    B --> B3[정규화]

    C --> C1[날짜]
    C --> C2[참석자/작성자]
    C --> C3[프로젝트]
    C --> C4[부서]

전처리 상세

1) 불용어 제거

STOPWORDS = [
    '그', '저', '것', '수', '등', '들', '및', '때문', '위해', '통해',
    '하지만', '그러나', '따라서', '또한', '즉', '예를 들어'
]

def remove_stopwords(text):
    tokens = text.split()
    return ' '.join([t for t in tokens if t not in STOPWORDS])

2) 토큰화 (한국어)

from konlpy.tag import Okt

okt = Okt()

def tokenize_korean(text):
    return okt.morphs(text, stem=True)

3) 정규화

import re

def normalize(text):
    # 이메일 제거
    text = re.sub(r'\S+@\S+', '[EMAIL]', text)
    # URL 제거
    text = re.sub(r'http\S+', '[URL]', text)
    # 특수문자 제거 (단, -_ 유지)
    text = re.sub(r'[^\w\s-_]', '', text)
    # 공백 정리
    text = re.sub(r'\s+', ' ', text)
    return text.strip()

3. 메타데이터 설계

{
  "id": "doc_12345",
  "content": "RAG 시스템은 Retrieval-Augmented Generation의 약자로...",
  "metadata": {
    "source": "meeting",  // meeting | wiki | doc | email
    "title": "프로젝트 회의",
    "date": "2025-01-20T14:00:00Z",
    "participants": ["김민준", "박서연", "이준호"],
    "project_id": "proj_001",
    "project_name": "회의록 시스템",
    "department": "개발팀",
    "tags": ["RAG", "AI", "회의록"],
    "language": "ko"
  }
}

벡터라이징 전략

1. Chunking 전략

목표: 회의록/문서를 의미 있는 단위로 분할하여 검색 정확도 향상

def chunk_text(text, chunk_size=500, overlap=50):
    """
    텍스트를 chunk로 분할

    Args:
        text: 원본 텍스트
        chunk_size: 청크 크기 (토큰 수)
        overlap: 청크 간 중복 크기

    Returns:
        List[str]: 청크 리스트
    """
    tokens = tokenize_korean(text)
    chunks = []

    for i in range(0, len(tokens), chunk_size - overlap):
        chunk = tokens[i:i + chunk_size]
        chunks.append(' '.join(chunk))

    return chunks

Chunking 전략 비교

방식 크기 Overlap 장점 단점
고정 크기 500 토큰 50 토큰 단순, 빠름 문맥 끊김 가능
문단 기반 가변 0 자연스러운 구분 크기 불균등
문장 기반 가변 1 문장 의미 보존 너무 작을 수 있음
하이브리드 500 토큰 50 토큰 + 문단 경계 균형잡힘 복잡함

선택: 하이브리드 방식 (Phase 2 이후 적용)

2. Embedding 생성

import openai

def generate_embedding(text, model="text-embedding-3-large"):
    """
    OpenAI API로 임베딩 생성

    Returns:
        List[float]: 1536 차원 벡터
    """
    response = openai.embeddings.create(
        input=text,
        model=model
    )
    return response.data[0].embedding

비용 계산:

  • text-embedding-3-large: $0.00013 / 1K tokens
  • 예상 월 비용: 500 회의록 × 2K tokens × $0.00013 = $0.13

3. Pinecone 저장

import pinecone

# 초기화
pinecone.init(api_key="YOUR_API_KEY", environment="us-west1-gcp")
index = pinecone.Index("meeting-rag")

def upsert_to_pinecone(doc_id, embedding, metadata):
    """
    Pinecone에 벡터 저장
    """
    index.upsert(vectors=[{
        "id": doc_id,
        "values": embedding,
        "metadata": metadata
    }])

Pinecone 설정:

  • Index: meeting-rag
  • Dimension: 1536
  • Metric: cosine
  • Replicas: 1 (Phase 1), 2 (Phase 3, HA)
  • Pods: p1.x1 (Phase 1), p1.x2 (Phase 2+)

Claude API 호출 구조

1. 프롬프트 설계

System Prompt

당신은 조직 내 전문용어를 쉽게 설명하는 전문가입니다.
- 사내 회의록, 위키, 프로젝트 문서를 기반으로 실용적인 설명을 제공합니다.
- 단순 정의가 아닌, 조직에서 실제로 어떻게 사용되는지 맥락을 포함합니다.
- 과거 논의 내용을 요약하여 제공합니다.

응답 형식은 반드시 JSON으로 작성하세요:
{
  "definition": "간단한 정의 (1-2문장)",
  "context": "이 회의에서의 의미 (맥락 기반 설명)",
  "usage_examples": ["실제 사용 사례 1", "사용 사례 2"],
  "related_projects": ["관련 프로젝트 1", "프로젝트 2"],
  "past_discussions": [
    {"date": "2025-01-15", "meeting": "프로젝트 회의", "summary": "RAG 시스템 도입 결정"}
  ],
  "references": ["doc_id_1", "doc_id_2", "doc_id_3"]
}

User Prompt (Few-shot Learning)

아래는 검색된 관련 문서들입니다:

---
문서 1 (회의록, 2025-01-15):
제목: 프로젝트 회의
내용: RAG 시스템을 도입하기로 결정했습니다. Retrieval-Augmented Generation은 문서 검색과 생성을 결합한 AI 기술입니다...

문서 2 (위키, 2025-01-10):
제목: AI 기술 가이드
내용: RAG는 벡터 DB를 활용하여 관련 문서를 찾고, LLM이 이를 기반으로 답변을 생성하는 방식입니다...

문서 3 (프로젝트 문서, 2025-01-05):
제목: 회의록 시스템 설계서
내용: 맥락 기반 용어 설명 기능에 RAG 시스템을 적용합니다...
---

현재 회의 맥락:
- 회의: "주간 스크럼"
- 날짜: 2025-01-20
- 참석자: 김민준, 박서연, 이준호
- 프로젝트: "회의록 시스템"

용어: "RAG"

위 정보를 바탕으로 "RAG"에 대한 설명을 JSON 형식으로 작성해주세요.

예시:
{
  "definition": "Retrieval-Augmented Generation의 약자로, 문서 검색과 AI 생성을 결합한 기술입니다.",
  "context": "우리 팀은 회의록 시스템에 RAG를 적용하여 과거 회의록과 사내 문서를 검색하고, 맥락에 맞는 용어 설명을 자동 생성합니다.",
  "usage_examples": [
    "회의 중 전문용어가 나오면 RAG 시스템이 관련 문서를 찾아 설명을 제공합니다",
    "신입사원도 업무 지식 없이 정확한 회의록을 작성할 수 있습니다"
  ],
  "related_projects": ["회의록 시스템", "AI 자동화 프로젝트"],
  "past_discussions": [
    {"date": "2025-01-15", "meeting": "프로젝트 회의", "summary": "RAG 시스템 도입 결정"},
    {"date": "2025-01-10", "meeting": "기술 세미나", "summary": "RAG 아키텍처 소개"}
  ],
  "references": ["doc_12345", "doc_12346", "doc_12347"]
}

2. API 호출 코드

import Anthropic from '@anthropic-ai/sdk';

const anthropic = new Anthropic({
  apiKey: process.env.CLAUDE_API_KEY,
});

interface TermExplanation {
  definition: string;
  context: string;
  usage_examples: string[];
  related_projects: string[];
  past_discussions: Array<{
    date: string;
    meeting: string;
    summary: string;
  }>;
  references: string[];
}

async function explainTerm(
  term: string,
  relatedDocs: any[],
  meetingContext: any
): Promise<TermExplanation> {

  const systemPrompt = `당신은 조직 내 전문용어를 쉽게 설명하는 전문가입니다...`;

  const userPrompt = buildUserPrompt(term, relatedDocs, meetingContext);

  const response = await anthropic.messages.create({
    model: 'claude-3-5-sonnet-20241022',
    max_tokens: 2000,
    temperature: 0.3,  // 일관된 응답을 위해 낮은 temperature
    system: systemPrompt,
    messages: [
      {
        role: 'user',
        content: userPrompt
      }
    ]
  });

  // JSON 파싱
  const content = response.content[0].text;
  const jsonMatch = content.match(/\{[\s\S]*\}/);

  if (!jsonMatch) {
    throw new Error('Invalid JSON response from Claude');
  }

  return JSON.parse(jsonMatch[0]);
}

function buildUserPrompt(term: string, docs: any[], context: any): string {
  const docsSummary = docs.map((doc, idx) => {
    return `문서 ${idx + 1} (${doc.metadata.source}, ${doc.metadata.date}):
제목: ${doc.metadata.title}
내용: ${doc.content.substring(0, 500)}...`;
  }).join('\n\n');

  return `아래는 검색된 관련 문서들입니다:

---
${docsSummary}
---

현재 회의 맥락:
- 회의: "${context.meeting_title}"
- 날짜: ${context.date}
- 참석자: ${context.participants.join(', ')}
- 프로젝트: "${context.project_name}"

용어: "${term}"

위 정보를 바탕으로 "${term}"에 대한 설명을 JSON 형식으로 작성해주세요.

예시:
{
  "definition": "...",
  "context": "...",
  ...
}`;
}

3. API 요청/응답 예시

요청 (Request)

{
  "model": "claude-3-5-sonnet-20241022",
  "max_tokens": 2000,
  "temperature": 0.3,
  "system": "당신은 조직 내 전문용어를 쉽게 설명하는 전문가입니다...",
  "messages": [
    {
      "role": "user",
      "content": "아래는 검색된 관련 문서들입니다...\n용어: \"RAG\""
    }
  ]
}

응답 (Response)

{
  "id": "msg_01ABC123",
  "type": "message",
  "role": "assistant",
  "content": [
    {
      "type": "text",
      "text": "{\n  \"definition\": \"Retrieval-Augmented Generation의 약자로, 문서 검색과 AI 생성을 결합한 기술입니다.\",\n  \"context\": \"우리 팀은 회의록 시스템에 RAG를 적용하여 과거 회의록과 사내 문서를 검색하고, 맥락에 맞는 용어 설명을 자동 생성합니다.\",\n  \"usage_examples\": [\n    \"회의 중 전문용어가 나오면 RAG 시스템이 관련 문서를 찾아 설명을 제공합니다\",\n    \"신입사원도 업무 지식 없이 정확한 회의록을 작성할 수 있습니다\"\n  ],\n  \"related_projects\": [\"회의록 시스템\", \"AI 자동화 프로젝트\"],\n  \"past_discussions\": [\n    {\"date\": \"2025-01-15\", \"meeting\": \"프로젝트 회의\", \"summary\": \"RAG 시스템 도입 결정\"},\n    {\"date\": \"2025-01-10\", \"meeting\": \"기술 세미나\", \"summary\": \"RAG 아키텍처 소개\"}\n  ],\n  \"references\": [\"doc_12345\", \"doc_12346\", \"doc_12347\"]\n}"
    }
  ],
  "model": "claude-3-5-sonnet-20241022",
  "stop_reason": "end_turn",
  "usage": {
    "input_tokens": 1250,
    "output_tokens": 320
  }
}

단계별 구현 로드맵

Phase 1: 기본 기능 (2주)

목표: 회의록 기반 최소 기능 구현 및 사용자 테스트

구현 범위

  • 회의록 DB 연동
  • 용어 감지 엔진 (Trie 자료구조)
  • OpenAI Embedding API 연동
  • Pinecone 벡터 검색
  • Claude API 호출 (기본 프롬프트)
  • UI: 점선 밑줄 하이라이트, 바텀 시트 툴팁

성능 목표

  • 응답 시간: 5초 이내
  • 용어 감지 정확도: 70% 이상
  • 관련 문서 정확도: 60% 이상

제약 사항

  • 캐시 없음 (모든 요청 실시간 처리)
  • 회의록만 검색 (위키, 문서, 이메일 미포함)

배포 전략

  • Beta 테스트: 20명 (개발팀 10명, 기획팀 5명, 경영지원팀 5명)
  • 피드백 수집: Google Forms 설문 + 주간 인터뷰

Phase 2: 성능 개선 (4주)

목표: 캐시 도입 + 위키 추가 + 하이브리드 검색

구현 범위

  • Redis 캐시 레이어
    • TTL: 자주 쓰이는 용어 7일, 드문 용어 1일
    • Cache Warming: 상위 50개 용어 사전 캐싱
  • 사내 위키 연동 (Confluence, Notion)
  • 하이브리드 검색 (벡터 + 키워드)
    • 벡터 유사도: 70% 가중치
    • 키워드 매칭: 30% 가중치
  • 프롬프트 최적화 (Few-shot learning)

성능 목표

  • 응답 시간: 3초 이내 (캐시 히트 시 0.5초)
  • 용어 감지 정확도: 85% 이상
  • 관련 문서 정확도: 75% 이상
  • 캐시 히트율: 60% 이상

배포 전략

  • Beta 테스트 확대: 50명
  • A/B 테스트: 캐시 vs 캐시 없음, 하이브리드 vs 벡터 단독

Phase 3: 고도화 (6주)

목표: 전체 데이터 통합 + 시맨틱 필터링 + 부서별 커스터마이징

구현 범위

  • 프로젝트 문서 연동 (Google Drive, SharePoint)
  • 이메일 연동 (Outlook, Gmail)
  • 시맨틱 필터링
    • 부서별 용어 우선순위
    • 프로젝트별 문맥 가중치
  • 2단계 캐싱
    • L1: Redis (Hot data, TTL 7일)
    • L2: CDN (Static explanations, TTL 30일)
  • 용어 추천 시스템
    • "이 용어를 사전에 추가할까요?" 제안

성능 목표

  • 응답 시간: 2초 이내 (캐시 히트 시 0.3초)
  • 용어 감지 정확도: 90% 이상
  • 관련 문서 정확도: 80% 이상
  • 캐시 히트율: 80% 이상

배포 전략

  • 전사 배포 (200명+)
  • 부서별 용어 사전 큐레이션 워크숍

성능 및 비용 최적화

1. 캐싱 전략

Redis 캐시 구조

Key: term:{term_name}:{meeting_id}
Value: JSON (TermExplanation)
TTL:
  - 자주 쓰이는 용어 (요청 >10회/월): 7일
  - 드문 용어 (요청 <10회/월): 1일

Cache Warming

# 매일 새벽 2시 실행
def cache_warming():
    # 상위 50개 빈도 높은 용어
    top_terms = get_top_terms(limit=50)

    for term in top_terms:
        # 최근 회의 맥락으로 미리 캐싱
        recent_meetings = get_recent_meetings(limit=5)
        for meeting in recent_meetings:
            explanation = explain_term(term, meeting)
            cache_key = f"term:{term}:{meeting.id}"
            redis.setex(cache_key, ttl=7*24*3600, value=json.dumps(explanation))

2. 하이브리드 검색

def hybrid_search(query, top_k=5):
    """
    벡터 검색 + 키워드 검색 결합
    """
    # 1. 벡터 검색 (70% 가중치)
    query_embedding = generate_embedding(query)
    vector_results = pinecone_index.query(
        vector=query_embedding,
        top_k=top_k * 2,  # 2배수 조회
        include_metadata=True
    )

    # 2. 키워드 검색 (30% 가중치)
    keyword_results = elasticsearch.search(
        index="meetings",
        body={
            "query": {
                "multi_match": {
                    "query": query,
                    "fields": ["title^3", "content", "tags^2"]
                }
            }
        },
        size=top_k * 2
    )

    # 3. 점수 결합 (Normalized)
    combined_scores = {}

    for match in vector_results.matches:
        combined_scores[match.id] = match.score * 0.7

    for hit in keyword_results['hits']['hits']:
        doc_id = hit['_id']
        if doc_id in combined_scores:
            combined_scores[doc_id] += hit['_score'] * 0.3
        else:
            combined_scores[doc_id] = hit['_score'] * 0.3

    # 4. 상위 k개 반환
    sorted_results = sorted(combined_scores.items(), key=lambda x: x[1], reverse=True)
    return sorted_results[:top_k]

3. Claude API 비용 절감

비용 구조

Claude 3.5 Sonnet:
- Input: $3 / 1M tokens
- Output: $15 / 1M tokens

월 예상 비용 (500 회의록, 평균 10회 용어 설명):
- 총 요청: 5,000회
- 평균 Input: 1,500 tokens/요청
- 평균 Output: 300 tokens/요청

비용 = (5000 * 1500 * $3 / 1M) + (5000 * 300 * $15 / 1M)
     = $22.5 + $22.5
     = $45/월

캐시 적용 시 (60% 히트율):
     = $45 * 0.4 = $18/월

Rate Limiting

import { RateLimiter } from 'limiter';

const limiter = new RateLimiter({
  tokensPerInterval: 60,  // 분당 60회
  interval: 'minute'
});

async function callClaudeWithRateLimit(prompt: string) {
  await limiter.removeTokens(1);
  return await anthropic.messages.create({...});
}

품질 검증 기준

1. 자동 검증

용어 감지 정확도

def calculate_term_detection_accuracy():
    """
    테스트 세트: 100개 회의록, 200개 용어
    """
    test_data = load_test_data("term_detection_test.json")

    correct = 0
    total = len(test_data)

    for sample in test_data:
        detected_terms = detect_terms(sample.content)
        expected_terms = sample.expected_terms

        # F1 Score 계산
        precision = len(set(detected_terms) & set(expected_terms)) / len(detected_terms)
        recall = len(set(detected_terms) & set(expected_terms)) / len(expected_terms)
        f1 = 2 * (precision * recall) / (precision + recall)

        correct += f1

    return (correct / total) * 100

설명 품질 평가

def evaluate_explanation_quality():
    """
    사람 평가 + 자동 평가 결합
    """
    test_cases = load_test_cases("explanation_quality.json")

    scores = []

    for case in test_cases:
        explanation = explain_term(case.term, case.context)

        # 자동 평가 (1-5점)
        auto_score = 0

        # 1) 정의 포함 여부 (1점)
        if len(explanation.definition) > 10:
            auto_score += 1

        # 2) 맥락 설명 포함 여부 (1점)
        if len(explanation.context) > 20:
            auto_score += 1

        # 3) 사용 사례 포함 여부 (1점)
        if len(explanation.usage_examples) >= 1:
            auto_score += 1

        # 4) 관련 문서 연결 여부 (1점)
        if len(explanation.references) >= 1:
            auto_score += 1

        # 5) 과거 논의 포함 여부 (1점)
        if len(explanation.past_discussions) >= 1:
            auto_score += 1

        scores.append(auto_score)

    return sum(scores) / len(scores)

2. 사람 평가

평가 기준

항목 배점 기준
정확성 30점 용어 정의가 정확한가?
맥락 적합성 30점 현재 회의 맥락과 관련성이 높은가?
실용성 20점 실제 업무에 도움이 되는가?
가독성 10점 이해하기 쉬운가?
완성도 10점 관련 문서, 과거 논의 포함 여부

평가 프로세스

  1. 매 Sprint 종료 시 20개 샘플 평가
  2. 평가자: Beta 테스터 10명 (무작위 선정)
  3. 목표 점수: 80점 이상

운영 및 모니터링

1. 성능 메트릭

Prometheus 메트릭

import { Counter, Histogram, Gauge } from 'prom-client';

// 요청 수
const requestCounter = new Counter({
  name: 'rag_requests_total',
  help: 'Total number of RAG requests',
  labelNames: ['status', 'cache_hit']
});

// 응답 시간
const responseTimeHistogram = new Histogram({
  name: 'rag_response_time_seconds',
  help: 'RAG response time in seconds',
  buckets: [0.5, 1, 2, 3, 5]
});

// 캐시 히트율
const cacheHitRate = new Gauge({
  name: 'rag_cache_hit_rate',
  help: 'Cache hit rate percentage'
});

// Claude API 비용
const apiCostCounter = new Counter({
  name: 'claude_api_cost_usd',
  help: 'Estimated Claude API cost in USD'
});

Grafana 대시보드

┌────────────────────────────────────────────┐
│  RAG 시스템 성능 모니터링                  │
├────────────────────────────────────────────┤
│  [ 실시간 요청 수 ]  [ 평균 응답 시간 ]   │
│      125 req/min          2.3s            │
├────────────────────────────────────────────┤
│  [ 캐시 히트율 ]      [ Claude API 비용 ]  │
│      65%                  $18/월           │
├────────────────────────────────────────────┤
│  [ 용어 감지 정확도 ]  [ 설명 품질 점수 ] │
│      88%                   85/100          │
└────────────────────────────────────────────┘

2. 알림 설정

Alertmanager 규칙

groups:
  - name: rag_alerts
    rules:
      - alert: HighResponseTime
        expr: rag_response_time_seconds > 5
        for: 5m
        labels:
          severity: warning
        annotations:
          summary: "RAG 응답 시간 초과 (>5초)"

      - alert: LowCacheHitRate
        expr: rag_cache_hit_rate < 50
        for: 10m
        labels:
          severity: info
        annotations:
          summary: "캐시 히트율 낮음 (<50%)"

      - alert: ClaudeAPIError
        expr: increase(rag_requests_total{status="error"}[5m]) > 10
        labels:
          severity: critical
        annotations:
          summary: "Claude API 오류 급증"

3. 로깅 전략

import winston from 'winston';

const logger = winston.createLogger({
  level: 'info',
  format: winston.format.json(),
  transports: [
    new winston.transports.File({ filename: 'rag-error.log', level: 'error' }),
    new winston.transports.File({ filename: 'rag-combined.log' })
  ]
});

// 로그 예시
logger.info('Term explanation generated', {
  term: 'RAG',
  meeting_id: 'meeting_12345',
  response_time_ms: 2300,
  cache_hit: false,
  related_docs_count: 5,
  claude_tokens: { input: 1500, output: 320 }
});

부록

A. API 명세서

POST /api/rag/explain

요청:

{
  "term": "RAG",
  "meeting_id": "meeting_12345",
  "context": {
    "meeting_title": "주간 스크럼",
    "date": "2025-01-20T14:00:00Z",
    "participants": ["김민준", "박서연"],
    "project_name": "회의록 시스템"
  }
}

응답:

{
  "term": "RAG",
  "explanation": {
    "definition": "Retrieval-Augmented Generation의 약자로...",
    "context": "우리 팀은 회의록 시스템에 RAG를 적용하여...",
    "usage_examples": ["..."],
    "related_projects": ["..."],
    "past_discussions": [...],
    "references": ["doc_12345"]
  },
  "metadata": {
    "response_time_ms": 2300,
    "cache_hit": false,
    "related_docs_count": 5,
    "confidence_score": 0.92
  }
}

B. 배치 작업 스케줄

작업 주기 시간 설명
회의록 벡터화 실시간 - 회의 종료 후 즉시
위키 동기화 매일 새벽 2시 Confluence API 호출
캐시 워밍 매일 새벽 3시 상위 50개 용어 캐싱
용어 사전 갱신 주간 일요일 새벽 1시 신규 용어 자동 추가
성능 리포트 생성 주간 월요일 오전 9시 주간 성능 분석

변경 이력

버전 날짜 변경 내용 작성자
1.0 2025-01-20 초기 구현방안 작성 박서연, 이준호, 홍길동
2.0 2025-01-20 하이브리드형 로드맵으로 최종 승인 전체 팀

문서 끝