1. RAG(검색 증강 생성)의 기본 개념 및 활용 [0]

thumbnail RAG는 LLM이 외부 지식에 접근하여 사용자 질문에 대한 정확하고 맥락에 맞는 답변을 생성하도록 돕는 기술이다.

1.1. RAG의 단순화된 설명 [0]

  1. RAG의 필요성: LLM은 학습 데이터에 없는 질문에 대해 부정확하거나 일반적인 답변을 생성하는 환각(hallucination) 문제를 가진다. [17]
    1. 예를 들어, 회사 내부 정책 문서에 대한 질문은 LLM이 접근할 수 없는 정보이므로 정확한 답변을 기대하기 어렵다. [17]
  2. RAG의 작동 방식: 사용자가 직접 관련 문서를 찾아 프롬프트에 추가하여 LLM이 정확한 답변을 생성하도록 돕는 과정과 유사하다. [20]
    1. 검색(Retrieval): 내부 정책 문서에서 관련 정보를 찾는 과정이다. [23]
    2. 증강(Augmenting): 검색된 정보로 프롬프트를 개선하는 과정이다. [24]
    3. 생성(Generation): 증강된 프롬프트를 기반으로 LLM이 응답을 생성하는 과정이다. [25]
  3. RAG 시스템의 목표: 사용자가 직접 정보를 찾지 않고도 시스템이 관련 정보를 검색하고, 프롬프트를 증강하여 LLM이 정확한 응답을 생성하도록 하는 것이다. [30]

1.2. RAG 사용 시점 및 다른 AI 기술과의 비교 [33]

  1. RAG는 만능 해결책이 아니다: RAG는 모든 문제에 대한 해결책이 아니며, AI가 더 나은 응답을 생성하도록 돕는 여러 방법 중 하나이다. [33]
    1. 다른 방법으로는 프롬프트 엔지니어링(Prompt Engineering)과 모델 미세 조정(Fine-tuning)이 있다. [36]
  2. 사례 연구: 정책 코파일럿 챗봇 [39]
    1. 목표: 직원들이 회사 정책에 대한 질문을 할 때 정확한 답변을 제공하는 내부 챗봇을 구축하는 것이다. [42]
    2. 제한 사항: 특정 질문(예: 성과 검토, 급여 논의)에는 답변하지 않고 HR로 안내해야 한다. [46]
    3. 음성 및 스타일: CEO의 따뜻한 스코틀랜드 억양과 권위 있는 말투를 모방해야 한다. [49]
  3. 문제 해결을 위한 AI 기술 선택 [57]
    1. 제한 및 보안: 챗봇의 행동을 제어하고 민감한 정보를 다루는 데는 프롬프트 엔지니어링이 적합하다. [57]
      1. 이는 챗봇을 안전하고 전문적으로 유지하는 규칙서와 같다. [62]
    2. 음성, 스타일, 언어: CEO의 과거 연설, 이메일 등을 사용하여 모델을 미세 조정(Fine-tuning)하는 것이 적합하다. [63]
      1. 미세 조정의 한계: 정책이 자주 변경될 경우 매번 모델을 재학습해야 하며, 이는 비용이 많이 들고 느리다. [71]
      2. 사용자는 답변의 출처를 확인할 수 없고, 학습 데이터가 클수록 정확도가 낮아지며, 모델은 학습 데이터에 있는 지식만 안다. [74]
      3. 미세 조정은 의사소통 스타일과 같이 안정적이고 변하지 않는 패턴에 적합하지만, 동적인 사실 정보에는 부적합하다. [78]
    3. 가장 정확한 응답: RAG가 가장 좋은 해결책이다. [80]
      1. RAG는 쿼리 시점에 정보를 동적으로 검색하므로, 학습 시점에 정보를 검색하는 미세 조정과 다르다. [81]
      2. RAG의 핵심은 사용자 쿼리에 가장 관련성 높은 정보를 실시간으로 검색하는 것이다. [81]

2. RAG의 핵심 구성 요소: 검색, 임베딩, 벡터 데이터베이스, 청킹 [83]

thumbnail RAG 시스템은 문서 청킹, 임베딩, 벡터 데이터베이스를 활용하여 사용자의 질문에 가장 관련성 높은 정보를 검색하고, 이를 LLM에 전달하여 정확하고 맥락에 맞는 답변을 생성한다.

2.1. 검색(Retrieval)의 이해: 키워드 검색과 의미론적 검색 [83]

  1. 검색의 중요성: 수백, 수천 개의 정책 문서 중에서 사용자 질문과 관련된 문서를 찾는 과정이다. [87]
  2. 키워드 검색(Keyword Search) [89]
    1. 작동 방식: 사용자 질문에서 키워드를 식별하고, 문서 내에서 해당 키워드를 정확히 일치시켜 검색한다. [89]
      1. 예를 들어, "reimbursement"와 "home office"라는 키워드를 사용하여 문서를 검색한다. [90]
    2. 한계: 정확히 일치하는 키워드가 없으면 검색에 실패한다. [93]
      1. 예를 들어, "reimbursement" 대신 "allowance"를 사용하거나 "home office" 대신 "work from home"을 사용하면 관련 문서를 찾지 못할 수 있다. [185]
    3. 인기 있는 기술: TF(Term Frequency) 및 BM25(Best Match 25)와 같은 기술이 사용된다. [103]
      1. TF-IDF: 문서 내 단어의 중요도를 측정하여 점수를 부여한다. [115]
      2. BM25: TF-IDF와 유사하지만, 단어가 모든 문서에 존재할 경우 관련성이 낮다고 판단하여 0점을 부여하는 등 더 엄격하게 점수를 할당한다. [125]
  3. 의미론적 검색(Semantic Search) [182]
    1. 필요성: 키워드 검색의 한계를 극복하기 위해 단어의 의미를 기반으로 문서를 검색한다. [190]
    2. 작동 방식: 검색 쿼리와 모든 문서를 수학적 벡터(embeddings)로 변환한다. [195]
      1. 의미가 유사한 문서들은 이 고차원 공간에서 서로 가깝게 위치한다. [197]
      2. 두 텍스트 조각의 유사성은 벡터 간의 거리를 계산하여 측정한다. [200]
      3. 예를 들어, "reimbursement"와 "allowance"는 다른 단어이지만, 의미가 유사하므로 벡터 공간에서 가깝게 위치한다. [202]

2.2. 임베딩 모델(Embedding Models) [204]

  1. 임베딩 모델의 역할: 텍스트를 의미를 나타내는 숫자로 변환하는 모델이다. [224]
    1. 예를 들어, "dogs are allowed in the office"라는 문장은 벡터(숫자 배열)로 변환된다. [225]
    2. 각 숫자는 모델이 언어 패턴을 학습하여 얻은 지식을 나타낸다. [229]
  2. 모델 예시: all-MiniLM-L6-V2 [208]
    1. 이 모델은 문장과 단락을 384차원 밀집 벡터 공간에 매핑하며, 클러스터링 및 의미론적 검색에 사용될 수 있다. [209]
    2. 2,200만 개의 매개변수를 가진 모델이다. [210]
  3. 매개변수(Parameters)의 의미: 모델의 "두뇌 능력"을 반영하며, AI의 메모리에 저장된 학습된 지식을 나타낸다. [211]
    1. GPT-3.5(1,750억 개) 및 GPT-4(1조 8천억 개)와 비교하면 all-MiniLM 모델(2,200만 개)은 매우 작다. [217]
    2. all-MiniLM 모델은 크기가 90MB로 로컬에서 사용 가능하며 임베딩 모델로 적합하다. [220]
    3. GPT 모델은 텍스트 생성 및 추론에 사용된다. [222]
  4. 벡터 유사성 계산: 벡터 간의 거리를 측정하여 유사성을 판단한다. [239]
    1. 384차원과 같은 고차원 공간에서는 내적(dot product)을 사용하여 유사성을 계산한다. [245]
    2. 내적은 벡터의 값을 곱하고 더한 후 정규화하여 0과 1 사이의 유사성 점수를 반환한다. [255]
    3. 1에 가까울수록 유사하고, 1에서 멀어질수록 유사하지 않다. [266]
  5. 임베딩 모델의 종류: sentence transformers는 로컬에서 실행되는 무료 모델이며, OpenAI의 임베딩과 같은 API 모델은 외부 서버에서 실행되며 유료이다. [299]

2.3. 벡터 데이터베이스(Vector Databases) [366]

  1. 벡터 데이터베이스의 필요성: 수백, 수천 개의 대규모 문서에서 효율적으로 관련 정보를 검색하기 위해 필요하다. [367]
    1. 모든 쿼리 임베딩을 저장된 모든 임베딩과 비교하는 것은 비효율적이다. [372]
    2. 벡터 데이터베이스는 스마트한 색인 알고리즘을 사용하여 관련 결과를 즉시 검색하고, 효율적이며 확장 가능하다. [378]
  2. 색인(Indexing): 벡터를 미리 조직화하여 "이웃"으로 그룹화한다. [382]
    1. 예를 들어, 동물 정책, 건강 혜택, 원격 근무 정책을 각각 그룹화하여 검색 범위를 좁힌다. [384]
  3. 인기 있는 색인 알고리즘: [387]
    1. HNSW(Hierarchical Navigable Small World): 가장 널리 사용되는 알고리즘으로, 각 벡터를 가장 유사한 이웃과 연결하는 그래프 구조를 생성한다. 빠르고 정확하다. [388]
    2. IVF(Inverted File) 및 LSH(Locally Sensitive Hashing)도 다른 예시이다. [391]
  4. 인기 있는 벡터 DB 구현: [392]
    1. Chroma: 오픈 소스이며 Python 친화적이어서 학습에 적합하다. 무료로 로컬에 설치하여 실험할 수 있다. [397]
    2. Pinecone: 관리형 서비스로, 인프라를 직접 관리할 필요가 없다. 대기업에서 프로덕션에 사용되며, 사용량에 따라 비용을 지불한다. [400]
    3. VV8: GraphQL API를 제공하는 또 다른 옵션이다. [404]
    4. 학습 및 실험에는 Chroma를 사용하고, 프로덕션 환경에서는 Pinecone과 같은 서비스를 사용하는 것이 좋다. [406]
  5. ChromaDB 사용 예시: [407]
    1. ChromaDB 라이브러리를 설치하고, 클라이언트에 연결하여 policies라는 컬렉션을 생성한다. [407]
    2. collection.add 명령을 사용하여 정책 문서를 컬렉션에 추가하면, 텍스트가 384차원 벡터로 변환되어 HNSW 색인 구조에 저장된다. [412]
    3. collection.query 메서드를 사용하여 쿼리 문자열을 전달하여 검색한다. [415]
    4. 지속성(Persistence): 기본적으로 ChromaDB는 메모리에 데이터를 저장하므로 프로그램이 종료되면 데이터가 손실된다. [417]
      1. 데이터를 영구적으로 저장하려면 chromadb.PersistentClient()를 사용하여 데이터베이스 파일을 저장할 경로를 지정해야 한다. [420]
    5. 임베딩 모델 변경: 기본적으로 all-MiniLM 모델을 사용하지만, embedding_function 매개변수를 사용하여 OpenAI의 임베딩 모델이나 사용자 정의 임베딩 함수를 사용할 수 있다. [423]

2.4. 청킹(Chunking) [476]

  1. 청킹의 필요성: 대규모 문서를 벡터 데이터베이스에 추가할 때 발생하는 정확성 문제(precision problem)를 해결하기 위해 필요하다. [476]
    1. 예를 들어, 50페이지짜리 직원 핸드북 전체를 단일 항목으로 추가하면, 사용자가 특정 정책을 물었을 때 핸드북 전체를 반환하여 관련 없는 정보에 압도될 수 있다. [480]
  2. 청킹의 이점: 문서를 작고 집중된 조각으로 나누어 사용자가 필요한 특정 정책 섹션만 얻을 수 있도록 한다. [484]
  3. 청킹 전략: [490]
    1. 고정 크기 청크(Fixed-size chunks): 각 청크에 500자씩 할당하는 간단하고 신뢰할 수 있는 방법이다. [491]
      1. 문제점: 문장 중간에 분할될 경우 의미가 손상될 수 있다. [493]
      2. 해결책: 오버랩(Overlap): 청크 사이에 50자 정도의 오버랩을 추가하여 문맥을 보존한다. [496]
    2. 문장 기반 청킹(Sentence-based chunking): 각 문장을 별도의 청크로 분할한다. [500]
    3. 단락 기반 청킹(Paragraph-based chunking): 각 단락을 단일 청크로 만든다. [500]
  4. 청킹의 균형: [502]
    1. 청크가 너무 작으면: 문맥이 손실되고, 정보가 단편화되어 이해도가 낮아진다. [503]
    2. 청크가 너무 크면: 정확도가 떨어지고, 관련 없는 내용이 많아 검색이 비효율적이며, 결과가 압도적일 수 있다. [507]
  5. 효과적인 청킹을 위한 핵심 원칙: [521]
    1. 크기 가이드라인: 200~500자 범위가 문맥과 위치의 균형을 맞추는 데 좋다. [522]
      1. 연속성을 유지하기 위해 50~100자의 오버랩을 추가한다. [523]
      2. 기술 문서와 일반 정책은 다른 청크 크기가 필요할 수 있다. [524]
    2. 경계 규칙: 문법적 무결성을 유지하기 위해 항상 문장 경계에서 분할한다. [525]
      1. 단어 중간에 끊는 것을 피하고, 단락을 보존하여 논리적 구조를 유지한다. [526]
    3. 테스트: 실제 쿼리를 테스트하여 청크가 질문에 실제로 답변하는지 확인한다. [527]
      1. 오버랩이 의미를 보존하는지 확인하고, 검색 결과를 모니터링하여 청크 크기를 조정해야 하는지 확인한다. [528]

3. RAG 시스템 구축 및 운영 [578]

thumbnail

RAG 시스템은 문서 청킹, 임베딩, 벡터 데이터베이스를 통합하여 사용자 쿼리에 대한 정확한 응답을 생성하며, 캐싱, 모니터링, 오류 처리 기술을 통해 프로덕션 환경에서 안정적으로 운영된다.

3.1. RAG 아키텍처 구축 [578]

  1. RAG 파이프라인: 사용자가 질문하기 전에 문서 로딩, 청킹, 임베딩 생성, 벡터 DB 저장 등의 전처리 작업을 수행한다. [584]
    1. 단계: 정책 문서를 가져와 500자 청크(50자 오버랩)로 분할한다. [589]
    2. OpenAI의 임베딩 모델을 사용하여 임베딩으로 변환한다. [589]
    3. 벡터 DB에 로드한다. [589]
  2. 쿼리 처리: 쿼리가 들어오면 RAG 파이프라인에서 필요한 문서 청크를 검색한다. [590]
  3. 응답 생성: 검색된 문서 청크와 사용자 쿼리를 증강하여 LLM에 전송하고 응답을 생성한다. [591]

3.2. 프로덕션 환경에서의 RAG: 캐싱, 모니터링, 오류 처리 [616]

  1. 캐싱(Caching) [619]
    1. 문제점: RAG 시스템은 임베딩 생성, 벡터 DB 검색, LLM API 호출 등 여러 비용이 많이 드는 작업을 포함하므로 느리다. [620]
    2. 해결책: 캐싱은 비용이 많이 드는 작업의 결과를 저장하고 재사용하여 성능을 향상시킨다. [624]
    3. 캐싱 유형: [631]
      1. 쿼리 캐시(Query cache): 완전한 질문-답변 쌍을 저장하여 자주 묻는 질문에 즉시 응답한다. [633]
      2. 임베딩 캐시(Embedding cache): 텍스트에 대해 계산된 벡터를 저장하여 임베딩 생성 비용을 줄인다. [636]
      3. 벡터 검색 캐시(Vector search cache): 데이터베이스 쿼리 결과를 저장하여 유사한 쿼리가 동일한 결과를 반환할 때 유용하다. [639]
      4. LLM 응답 캐시(LLM response cache): 생성된 답변을 저장한다. LLM 호출은 파이프라인에서 가장 느린 부분이므로 가장 가치 있는 캐싱이다. [642]
    4. 구현: Redis와 같은 캐싱 도구를 사용하여 쿼리와 컨텍스트를 해싱하여 고유한 캐시 키를 생성한다. [645]
      1. 캐시에서 응답을 먼저 확인하고, 없으면 RAG 파이프라인으로 응답을 생성한 후 만료 시간(TTL)과 함께 캐시에 저장한다. [650]
      2. TTL은 성능 이점을 얻을 만큼 충분히 길지만, 데이터가 오래되지 않을 만큼 짧아야 한다. [653]
  2. 모니터링(Monitoring) [658]
    1. 필요성: RAG 시스템의 성능을 이해하고 문제가 발생했을 때 파악하기 위해 모든 것을 모니터링해야 한다. [658]
    2. 주요 지표: [660]
      1. 응답 시간(Response time): 질문에 답변하는 속도이다. [660]
      2. 처리량(Throughput): 초당 처리하는 쿼리 수이다. [660]
      3. 오류율(Error rate): 요청 실패율이다. [660]
      4. 검색 품질(Retrieval quality): 반환된 청크가 사용자 질문과 얼마나 관련성이 높은지 측정한다. [661]
      5. 임베딩 성능(Embedding performance): 벡터 생성에 걸리는 시간을 추적한다. [662]
      6. 청킹 효율성(Chunking efficiency): 문서 분할이 얼마나 잘 이루어지는지 모니터링한다. [663]
    3. 경고 임계값 설정: 문제가 발생했을 때 즉시 알 수 있도록 현실적인 임계값을 설정한다. [664]
  3. 오류 처리(Error Handling) [669]
    1. 목표: 프로덕션 환경에서 벡터 데이터베이스 다운, LLM 서비스 중단, 네트워크 시간 초과 등 문제가 발생하더라도 시스템이 정상적으로 작동하도록 점진적 성능 저하(graceful degradation)를 목표로 한다. [669]
    2. 계단식 대체 전략(Cascading fallback strategy): [673]
      1. 전체 RAG 파이프라인이 실패하면 키워드 검색을 시도한다. [674]
      2. 키워드 검색도 실패하면 검색된 청크를 직접 반환한다. [675]
      3. 이마저도 실패하면 간단한 텍스트 매칭을 사용한다. [676]
      4. 최후의 수단으로 유용한 오류 메시지를 반환한다. [677]
    3. 회로 차단기 패턴(Circuit Breaker Pattern): 서비스가 복구되었는지 주기적으로 테스트하여 정상 작동으로 복귀한다. [679]

3.3. 프로덕션 RAG 시스템 아키텍처 [682]

  1. 계층화된 아키텍처: Kubernetes에서 실행되는 완전한 프로덕션 RAG 시스템은 데이터 계층, RAG 파이프라인 계층, 애플리케이션 계층, 모니터링 스택으로 구성된다. [685]
    1. 데이터 계층(Data layer): 벡터를 위한 ChromaDB, 캐싱을 위한 Redis, 메타데이터를 위한 PostgreSQL 등 모든 스토리지 시스템을 포함한다. [688]
    2. RAG 파이프라인 계층(RAG pipeline layer): 쿼리 처리, 청킹, 임베딩, 생성, 검색, 증강 등 핵심 RAG 기능을 마이크로서비스로 분할하여 포함한다. [690]
      1. 각 서비스는 수요에 따라 독립적으로 확장할 수 있다. [692]
    3. 애플리케이션 계층(Application layer): 웹 UI, 모바일 앱 백엔드, 관리 인터페이스 등 사용자 대면 서비스를 포함한다. [693]
    4. 모니터링 스택(Monitoring stack): 메트릭을 위한 Prometheus, 대시보드를 위한 Grafana, 추적을 위한 Jaeger, 로깅을 위한 ELK 스택을 포함한다. [696]
  2. 이점: 이러한 계층화된 아키텍처는 관심사를 명확하게 분리하여 수천 명의 동시 사용자를 처리하면서 높은 가용성과 성능을 유지할 수 있다. [697]