본문 바로가기

AI·LLM 엔지니어링

〈LangChain 기반 RAG 시스템 구축〉 6편: RAG 파이프라인 속도 최적화 & 캐싱 전략 편

반응형

 

🔥 LangChain 기반 RAG 시스템 구축

6편. RAG 파이프라인 속도 최적화 & 캐싱 전략 편

(LangChain + vLLM + 벡터DB 기반 실전 튜닝 가이드)

RAG 시스템은 기능을 만드는 것보다
속도를 안정적으로 유지하며 운영하는 것이 훨씬 어렵다.

검색 지연, 임베딩 지연, LLM 응답 지연…
이 중 어느 하나만 느려져도 전체 API 성능이 무너진다.

이번 편에서는 실제로 기업 환경에서 사용하는 속도 최적화 기법 + 캐싱 전략을 모두 소개한다.


📌 1. RAG 속도 최적화는 왜 중요한가?

RAG는 요청 1건 처리에 다음 단계가 모두 필요하다.

  1. 검색(벡터DB)
  2. 재검색(Reranking 등)
  3. 컨텍스트 생성
  4. LLM 응답 생성
  5. 후처리

각 단계에서 몇 ms씩 누적되면 API 전반이 1~2초씩 느려질 수 있다.

RAG 시스템 튜닝의 목표는 단 하나:

평균 응답 시간을 1초 이하로 유지하기


📌 2. 전체 속도 병목 구조 보기

아래는 일반적인 RAG 병목 포인트다.

유저 질문
 → 텍스트 전처리 (5~10ms)
 → 벡터 검색 (20~150ms)
 → 재검색/Rerank (20~200ms)
 → 프롬프트 구성 (5~20ms)
 → LLM 응답 생성 (300~1500ms)
 → 출력 후처리 (5~20ms)

이 중 벡터 검색, Rerank, LLM 생성이 가장 큰 병목이다.


📌 3. 벡터 검색 속도 최적화 전략

3.1. 벡터DB 파라미터 튜닝

✓ Chroma / FAISS / Milvus 공통 전략

  • search_k는 너무 크게 하지 않는다.
  • k는 3~5 정도로 유지한다.
  • HNSW 기반이라면 ef_search 값을 조절한다. → 기본값보다 1.2~1.5배만 증가.

3.2. GPU 검색 사용 (추천)

Milvus, Qdrant, FAISS 모두 GPU 검색을 제공한다.
CPU 대비 5~20배 빨라지기도 한다.

예시:

# FAISS GPU Index
import faiss
res = faiss.StandardGpuResources()
gpu_index = faiss.index_cpu_to_gpu(res, 0, cpu_index)

3.3. Chunk 크기 조정으로 검색 횟수 감소

청크가 너무 잘게 쪼개지면 검색해야 할 데이터 수가 많아져 속도가 느려진다.

  • Chunk: 600~1200 tokens 권장
  • Overlap: 100~200 tokens

📌 4. 재검색(Reranking) 최적화

Reranker로 cross-encoder를 사용하면 정확도는 올라가지만 속도는 크게 떨어진다.

✓ 최적 조합

  • 검색: Dense Vector(속도 빠름)
  • 재검색: MonoT5 / Cohere Rerank(선택)
  • LLM으로 재정렬하는 방식(cheap LLM rerank)도 실무에서 많이 사용

✓ LLM 기반 re-rank 예시

prompt = f"""
아래 문서들을 질문과 관련도 높은 순으로 정렬해주세요.

질문: {query}
문서:
{documents}
"""
llm.invoke(prompt)

가벼운 모델(3B ~ 7B GGUF)로만 돌리면 충분히 빠르다.


📌 5. LLM 응답 속도 최적화(vLLM 중심)

vLLM은 RAG 서비스의 응답 속도를 크게 개선해주는 핵심 엔진이다.

5.1. vLLM 속도를 좌우하는 요소

✓ 모델 크기

  • 7B → 가장 빠르며 실무에서 충분히 사용
  • 13B → 정확도·속도 균형
  • 70B → 분석성 답변 필요 시 사용, but 캐싱 필수

✓ GPU VRAM

  • VRAM이 부족하면 속도가 급격히 느려진다
  • 16GB VRAM → 7B
  • 24GB VRAM → 7B, 13B
  • 80GB VRAM (H100) → 70B

5.2. vLLM 실행 최적화

python -m vllm.entrypoints.api_server \
  --model ./model.gguf \
  --tensor-parallel-size 1 \
  --max-num-batched-tokens 4096 \
  --gpu-memory-utilization 0.9 \
  --disable-log-requests \
  --trust-remote-code

주요 파라미터

  • max-num-batched-tokens: batch 크기 증가 → 처리량 향상
  • gpu-memory-utilization: VRAM 최대 활용
  • disable-log-requests: I/O 병목 제거

📌 6. 캐싱 전략 (속도 향상 핵심)

RAG 성능 최적화에서 캐싱은 필수다.

6.1. 3단계 캐싱 구조

1. 임베딩 캐시
2. 검색 결과 캐시
3. LLM 응답 캐시

① 임베딩 캐시(Embedding Cache)

OpenAI/로컬 임베딩 호출 비용 절감

예시:

from langchain.embeddings import CacheBackedEmbeddings

embed = CacheBackedEmbeddings(
    underlying_embeddings=embedding_model,
    cache=LocalFileStore("./embed_cache")
)

② 검색 결과 캐시(Search Cache)

같은 질문 반복 요청 시 검색을 건너뛰게 한다.

Redis 기반 예:

redis.set(query_hash, search_results)

③ LLM 응답 캐시(Generation Cache)

FAQ 기반 서비스에서 효과 극대화.

  • Redis / SQLite / DuckDB 모두 가능
  • key: 질문 + 검색 문서 해시
  • value: LLM 응답 결과

📌 7. 프롬프트 최적화로 속도 개선

프롬프트가 길면 LLM context length가 커져 속도가 느려진다.

실무 팁

  • 문서 3~5개만 넣기
  • system prompt는 2~3줄로 최소화
  • 예시(Few-shot)는 길게 넣지 말기
  • 불필요한 설명 제거

프롬프트 예시:

주어진 문서를 기반으로 질문에 정확하게 답하세요.
문서에 없는 내용은 추론하지 말고 "문서에 정보가 없습니다"라고 말하세요.

📌 8. 전체 RAG 속도 개선 실전 아키텍처

유저 요청
 → Redis 캐시 확인
 → 검색 (GPU)
 → Rerank (7B LLM)
 → 프롬프트 구성 최적화
 → vLLM 응답 (Batching)
 → 결과 반환 + 응답 캐싱

기업 환경에서 실제로 가장 많이 사용하는 구조다.


⭐ 실전 팁 3개

① Chunk 크기 조절이 성능 최적화의 첫 단계

청크가 너무 많으면 검색이 느려지고, 너무 크면 정확도가 떨어진다.

② 벡터 검색과 LLM 응답 모두 캐싱할 것

FAQ가 많거나 질문 패턴이 반복되는 서비스에서는 2~5배 빨라진다.

③ vLLM은 GPU VRAM 활용도를 0.9까지 올려도 안정적

성능이 눈에 띄게 개선된다.


🎯 다음편 예고

6편에서는 RAG 시스템의 핵심인 속도 최적화 & 캐싱 전략을 완전 정리했다.
이제 성능, 비용, 안정성 면에서 “운영 가능한 RAG 시스템”을 만들 수 있다.

다음 편에서는:

📌 7편. RAG 장애 대응, 로그 분석, 관찰성(O11y) 구축 편
으로 이어진다.


🔖 추천 태그

RAG, LLM, LangChain,
vLLM, RAG속도최적화, 캐싱전략,
벡터DB, Redis, FAISS,
GPU서빙, AI엔지니어링, 검색최적화,
LLM튜닝, 실무AI, RAG운영

반응형