BioPlayground

🧬
목록으로

RAG와 문맥 확장 — 실험실 논문 창고를 LLM의 두뇌에 얹기

왜 LLM은 우리 실험실 내부 자료를 모르는가. 임베딩 검색·chunking·hybrid search·reranking으로 외부 지식을 LLM에 주입하는 RAG 아키텍처를 원리부터 실무까지.

입문
|
22
|
검증 완료 (2026-07)
진행률0/15 (0%)

RAG와 문맥 확장 — 실험실 논문 창고를 LLM의 두뇌에 얹기

이 토픽을 마치면

편 #7에서 만든 논문 요약 어시스턴트에는 근본적 한계가 있습니다. 모델은 우리 실험실 내부 자료를 모릅니다. 여러분이 지난 5년간 발표한 논문 30편, 실험실 위키의 프로토콜 200개, 학회 발표 슬라이드 100개, 이 자료들이 LLM의 훈련 데이터에 들어 있을 리 없습니다.

이 편에서 다룰 RAG(Retrieval-Augmented Generation, 검색 증강 생성) 는 이 문제를 해결하는 아키텍처입니다. 외부 지식 창고를 만들고, LLM이 필요할 때마다 관련 부분을 검색해 문맥에 주입해서 답하도록. 편 #5의 임베딩과 편 #6의 어텐션이 실무에서 어떻게 재활용되는지 볼 수 있는 자연스러운 지점.


LLM 지식의 두 자리

편 #1에서 LLM을 "확률 기계"로 이해했고, 편 #5·6에서 이 기계가 파라미터 수백억 개에 훈련 데이터의 통계적 패턴을 압축해 저장한다는 것을 봤습니다. 그런데 이 지식이 살고 있는 자리를 좀 더 정밀하게 보면 두 곳입니다.

첫째 자리 — 파라미터. 훈련 과정에서 학습된 것들. GPT-4가 "미토콘드리아는 세포의 발전소"라는 문장을 만들 수 있는 것은 훈련 데이터에서 이런 문장이 반복 노출되어 파라미터에 흔적이 남았기 때문. 이 지식은 모델 자체에 붙박이로 들어 있고, 문맥과 무관하게 참조됩니다.

둘째 자리 — 문맥 창(context window). 매 호출마다 프롬프트에 담기는 정보. 편 #7의 few-shot 예시, 지도교수 이름, 검토 중인 논문 텍스트 등. 이 지식은 어텐션을 통해서만 참조됩니다. 모델이 다음 어절을 예측할 때 어텐션이 문맥의 관련 부분에 주목하고, 그 정보가 답변에 반영.

두 자리의 특성이 완전히 다릅니다.

파라미터문맥 창
저장 위치모델 가중치프롬프트
갱신 방법재훈련 (수 주~수 개월)매 호출 (즉시)
용량사실상 무제한 (수백억 파라미터)유한 (128K~1M 토큰)
검증불투명투명 (프롬프트 확인 가능)
개인 정보위험 (훈련에 넣으면 모든 사용자에게 노출)안전 (호출당 격리)

우리 실험실 논문 30편을 LLM이 참조하게 하려면 두 옵션이 있습니다.

  • 옵션 A: 이 논문들로 LLM을 재훈련·파인튜닝. 파라미터 자리에 지식을 심음.
  • 옵션 B: 매 호출마다 관련 논문을 문맥 창에 붙여 넣기.

옵션 A는 수십 GB의 GPU와 수 주의 훈련 시간이 필요. 게다가 새 논문이 추가될 때마다 재훈련해야 함. 옵션 B는 갱신이 즉시 가능하고 훈련 없음. 실무는 대부분 옵션 B 계열.

문제는 옵션 B의 실행 방법. 논문 30편을 통째로 문맥에 넣으면 200K 토큰을 훨씬 넘어갑니다. 게다가 100편·1000편으로 늘어나면 어떤 200K 문맥 모델도 못 담습니다.

여기서 RAG의 아이디어. 필요한 부분만 찾아서 넣기. 매 질문에 대해 관련 논문 몇 편·몇 문단만 검색해서 문맥에 주입.


RAG 파이프라인의 뼈대

RAG의 전체 흐름.

text
[준비 단계 - 한 번만]
논문 30편, 프로토콜 200개, 슬라이드 100개
   ↓
Chunking (문단·섹션 단위로 쪼갬)
   ↓
각 조각의 임베딩 계산 (편 #5의 임베딩 모델)
   ↓
벡터 데이터베이스에 저장 (임베딩 + 원문)

[질의 단계 - 매 호출]
유저 질문: "CRISPR 편집 효율이 낮았던 case가 실험실에 있었나?"
   ↓
질문 임베딩 계산 (같은 임베딩 모델)
   ↓
벡터 DB에서 코사인 유사도로 상위 K개 조각 검색
   ↓
검색된 조각들을 프롬프트에 붙여넣기
   ↓
LLM 호출 → 답변 생성

세 개의 부품이 필요합니다: 임베딩 모델, 벡터 DB, LLM. 앞의 두 부품이 검색을, 마지막이 생성을 담당. Retrieval + Generation의 조합이 이름 그대로 RAG.

바이오 유비 — 세포 신호 통합의 재활용. 편 #6에서 어텐션을 "세포가 주변 정보 중 관련된 것에 주목하는 원리"로 봤습니다. RAG는 이 원리를 한 층 확장한 것. 세포(LLM)가 참조 가능한 이웃 세포(문맥)를 동적으로 늘리는 시스템을 얹은 셈. 어텐션이 문맥 안 정보에 주목하는 원리라면, RAG는 그 문맥 자체를 매번 재구성하는 원리.


Chunking — 조각의 크기가 검색 품질을 좌우한다

문서를 통째로 임베딩하면 임베딩 하나에 너무 많은 의미가 뭉쳐서 검색 정확도가 떨어집니다. 반대로 어절 단위로 쪼개면 문맥이 부족해서 임베딩이 무의미해집니다. 적절한 조각 크기가 필요합니다.

일반적 지침.

  • 조각 크기: 200800 토큰 (대략 2001000 단어)
  • 조각 사이 오버랩 10~20% (경계에서 정보 소실 방지)
  • 문단·섹션 경계에서 쪼갬 (강제로 어절 중간에서 자르지 말 것)

Recursive Character Splitter (LangChain·LlamaIndex 표준). 큰 구분자(문단 경계)로 먼저 쪼개고, 조각이 너무 크면 다음 구분자(문장 경계)로, 더 작은 단위로 재귀적으로.

python
splitter = RecursiveCharacterTextSplitter(
chunk_size=500,
chunk_overlap=50,
separators=["\n\n", "\n", ". ", " ", ""]
)
chunks = splitter.split_text(paper.text)

바이오 도메인 특화 chunking.

  • 논문: 초록·서론·방법·결과·논의 섹션을 각각 별도 조각으로. 섹션 헤더를 조각 앞에 붙임(맥락 보존).
  • 프로토콜: 각 단계를 별도 조각으로. 시약 목록은 하나의 조각으로.
  • 슬라이드: 슬라이드 한 장 = 한 조각. 발표자 노트가 있으면 함께.
  • 표·그림: 캡션을 조각의 헤더로 사용. 표 데이터는 CSV나 markdown 표 형태로 유지.

메타데이터 부착. 각 조각에 원본 논문 정보(저자·연도·저널·DOI)를 메타데이터로 저장. 나중에 답변에 출처 표시할 때 사용.


임베딩 검색 — 편 #5의 벡터 공간 재활용

편 #5에서 이야기한 임베딩 공간이 여기서 재등장합니다. 이번에는 어절이 아니라 문서 조각 전체의 임베딩. 이걸 문서 임베딩(document embedding) 또는 문장 임베딩(sentence embedding) 이라 부릅니다.

임베딩 모델. 조각을 넣으면 벡터(대개 512~4096차원)를 뱉는 신경망. 훈련 방식은 "의미적으로 유사한 조각의 벡터는 가깝게, 다른 조각의 벡터는 멀게".

주요 임베딩 모델.

  • OpenAI text-embedding-3: 실무 표준 중 하나. small(1536차원)과 large(3072차원). API 호출.
  • Cohere embed v3: 다국어 강함, 저지연.
  • Voyage AI: 최근 벤치마크 상위.
  • Sentence-BERT 계열: 오픈소스. all-MiniLM-L6-v2(384차원), all-mpnet-base-v2(768차원) 등.
  • BGE·E5 계열: 오픈소스 최상위권. 다국어 지원 좋음.

바이오 도메인 특화. 일반 임베딩 모델은 바이오 용어(유전자명·단백질명·약어)에 상대적으로 약합니다. 필요하면.

  • BioBERT·PubMedBERT: PubMed로 사전훈련된 BERT 계열. Sentence embedding으로 파인튜닝 가능.
  • SPECTER: 논문 인용 관계로 훈련된 학술 임베딩.
  • 자체 파인튜닝: 실험실 자료로 sentence-transformers 파인튜닝. 최고 성능이지만 데이터·훈련 필요.

코사인 유사도(cosine similarity) 로 두 벡터의 유사도를 측정.

text
similarity(u, v) = ⟨u, v⟩ / (||u|| · ||v||)

두 벡터의 방향이 같으면 1, 무관하면 0, 반대면 -1. 임베딩은 대개 정규화되어(norm 1) 저장해서 코사인 유사도가 그냥 내적. 편 #6 어텐션 스코어의 축약 형태.

검색 절차.

  1. 질문을 임베딩 모델에 넣어 질문 벡터 q.
  2. 벡터 DB의 모든 조각 벡터와 q 사이의 코사인 유사도 계산.
  3. 상위 K개(예: K=10) 조각 반환.

수만~수백만 조각을 매 질의마다 순회하면 느리기 때문에 근사 최근접 검색(Approximate Nearest Neighbor, ANN) 인덱스를 씀. HNSW(Hierarchical Navigable Small World) 가 표준. 부록 A.7 참조.


Vector Database — 임베딩을 얹어두는 창고

벡터 DB. 임베딩 + 메타데이터를 저장하고, 유사도 검색을 빠르게 처리하는 인프라. 주요 선택지.

  • Chroma: 오픈소스, 로컬·경량. 시작하기 좋음.
  • Qdrant: 오픈소스, 프로덕션급. 셀프 호스팅·클라우드 모두 지원.
  • Weaviate: 오픈소스, 스키마 강력, GraphQL 인터페이스.
  • Pinecone: 매니지드 서비스, 유료. 사용 편함.
  • pgvector: PostgreSQL 확장. 기존 SQL 인프라 활용.
  • Milvus: 대규모, 엔터프라이즈급.

실무 규모 감. 논문 30편(각 20 조각)이면 600 벡터. Chroma로 로컬에서 충분. 논문 10만편(200만 조각)이면 Qdrant·Pinecone 같은 프로덕션급. 우선 Chroma로 시작해서 규모 따라 이전.

저장 형태. 각 벡터마다:

json
{
  "id": "paper_2023_smith_chunk_3",
  "vector": [0.024, -0.113, ..., 0.087],  // 1536차원 float
  "content": "In this study, we investigated CRISPR editing efficiency in HEK293T cells...",
  "metadata": {
    "paper_id": "2023_Smith_Nature",
    "section": "Results",
    "authors": ["Smith J", "Lee H"],
    "year": 2023,
    "doi": "10.1038/..."
  }
}

Dense + Sparse — Hybrid Search의 힘

임베딩 검색(dense retrieval)의 약점. 정확한 단어 매칭에 약합니다. 질문에 "TP53"이라는 유전자명이 있고 문서에도 "TP53"이 있어도, 임베딩 공간에서는 다른 유전자명과 섞여 있을 수 있음. 유전자명·약물명·화학식·수식 같은 정확한 식별자는 dense 검색이 놓치기 쉬움.

이 약점을 보완하는 게 sparse retrieval. 전통적 정보검색 방법.

BM25 (Best Matching 25). 20년 넘게 검색 엔진의 표준. 단어 빈도·문서 길이·역문서 빈도로 관련도를 계산. 정확한 단어 매칭에 강함.

Hybrid Search. Dense와 Sparse 결과를 결합.

  • 각 방식으로 상위 K개씩 검색.
  • 두 결과의 순위를 Reciprocal Rank Fusion(RRF) 로 결합.
text
RRF_score(doc) = Σ_i 1 / (k + rank_i(doc))

k = 60 기본값. 각 방식에서 순위가 높으면 점수 상승.

실무 지침. 도메인이 전문 용어·식별자가 많은 경우(바이오·의약·법률·특허) hybrid가 dense 단독보다 상당한 개선. 검색 성능 벤치마크에서 대개 hybrid가 우세.

최근 트렌드. ColBERT·SPLADE 같은 학습된 sparse 임베딩이 등장. Dense와 sparse의 장점을 하나의 모델에서 결합. 최신 벤치마크 상위.


Reranking — 마지막 필터의 힘

임베딩 검색은 빠르지만 정확도가 완벽하지 않습니다. 상위 10개 검색 결과 중 몇 개는 실제로 관련 없을 수 있음.

Reranker (재순위 지정 모델). 검색된 K개 후보를 더 정확한 모델로 재평가. Cross-encoder 방식이 표준.

Bi-encoder vs Cross-encoder.

  • Bi-encoder (임베딩 검색): 질문과 문서를 각각 임베딩으로 변환 후 유사도. 빠르지만 두 텍스트의 상호작용은 유사도 하나로 압축.
  • Cross-encoder (reranker): 질문과 문서를 함께 트랜스포머에 넣어 관련도 점수를 직접 계산. 정확하지만 느림.

Cross-encoder는 두 텍스트의 모든 어절 쌍 사이 어텐션(편 #6)을 계산하기 때문에 훨씬 세밀한 판단이 가능. 대가로 계산량이 커서 모든 문서를 다 못 함. 먼저 임베딩으로 100개 추리고, 그중 상위 10개를 cross-encoder로 재정렬하는 2단계 파이프라인이 표준.

주요 reranker.

  • Cohere Rerank v3: 매니지드 API.
  • BGE-Reranker: 오픈소스, 다국어.
  • Voyage Rerank: 벤치마크 상위.

효과. 임베딩 top-10만 쓸 때 정답률 60% → reranker 얹으면 80%로 개선되는 것이 흔한 경험.


RAG의 한계 — 어디에서 실패하는가

RAG가 만능은 아닙니다. 실무에서 자주 마주치는 실패 유형.

한계 1: 검색이 실패하면 답이 실패. 벡터 DB에 답의 근거가 있어도 검색이 못 찾으면 LLM이 참조할 수 없습니다. Chunking이 나쁘거나, 임베딩 모델이 도메인에 약하거나, 질문이 검색 시스템에 맞지 않는 표현이면 실패. → 질문 재작성(query rewriting)·멀티 쿼리 검색 등 대응.

한계 2: 결합 추론이 어려움. 답이 여러 문서에 걸쳐 있고 통합이 필요한 경우. 예: "우리 실험실이 지난 5년간 사용한 세포주 목록"은 30편 논문의 방법 섹션을 모두 참조해서 정리해야 함. 각 문서만 보고는 답 불가. → agentic RAG·multi-hop retrieval 등 대응.

한계 3: 인용 정확성. LLM이 검색된 문서에서 답을 만든다고 해도, 문서에 없는 내용을 지어낼 수 있음(hallucination, 편 #11). 검색 결과가 있어도 완전 방어는 아님. → 명시적 인용 요청, 출처 강제 표시.

한계 4: 부정형 질문. "우리 실험실이 안 다룬 세포주는?"처럼 부재를 물으면 RAG가 어려움. 검색으로 없는 것을 찾을 수 없기 때문. → 반전 질문 재작성.

한계 5: 최신 정보 vs 검색 창고 갱신 지연. 벡터 DB가 실시간이 아니면 최신 정보 놓침. → 증분 업데이트, real-time indexing.


Long-Context 시대의 RAG — 여전히 필요한가

2024~2025년에 등장한 100만 토큰 문맥 모델(Gemini 1.5·Claude 3.5·GPT-4.1 등)이 논쟁을 일으켰습니다. "이제 문맥이 이렇게 큰데 RAG가 필요한가?" 라는 물음.

RAG 여전히 필요한 이유.

  • 비용. 매 호출마다 1M 토큰을 넣으면 요금·지연이 폭발. RAG는 K개 조각(~10K 토큰)만 넣어 훨씬 저렴·빠름.
  • 정확도. 100만 토큰 문맥에서도 모델이 "lost in the middle" 문제를 보임. 중간 위치의 정보를 놓침. RAG로 관련 부분만 압축해 넣으면 오히려 정확도 상승.
  • 확장성. 1M 토큰도 1000편 논문이 안 됨. 실무 규모는 계속 그 이상.
  • 감사·투명성. 어떤 문서가 답에 사용되었는지 추적 가능. 규제 산업에 필수.

Long-context의 유용성. 전체 문맥이 실제로 필요한 특정 작업(예: 한 논문 전체 심층 분석)에는 long-context가 이김. RAG와 long-context는 대체가 아니라 역할 분담.

하이브리드 아키텍처. 실무에서 RAG로 관련 100~1000 조각을 뽑고, 이걸 long-context에 밀어넣는 방식이 흔함. RAG의 검색력과 long-context의 결합력을 함께.


바이오 응용 시나리오

시나리오 1 — 실험실 논문·프로토콜 지식 챗봇

여러분의 실험실 이 30편 논문 + 200개 프로토콜 + 지도교수의 강의노트를 RAG로 인덱싱. Slack 봇이나 웹 UI로 질문 가능.

python
# 준비 (한 번)
from langchain.text_splitter import RecursiveCharacterTextSplitter
from langchain_community.vectorstores import Chroma
from langchain_openai import OpenAIEmbeddings
splitter = RecursiveCharacterTextSplitter(chunk_size=500, chunk_overlap=50)
docs = load_lab_documents() # papers, protocols, notes
chunks = splitter.split_documents(docs)
embeddings = OpenAIEmbeddings(model="text-embedding-3-large")
vectorstore = Chroma.from_documents(chunks, embeddings, persist_directory="./lab_db")
# 질의 (매 호출)
def ask_lab(question):
docs = vectorstore.similarity_search(question, k=10)
context = "\n\n".join([d.page_content for d in docs])
prompt = f"""당신은 우리 실험실의 자료를 참조해 답하는 조수입니다.
아래 자료를 근거로 질문에 답하고, 답변 뒤에 각 근거의 출처를 [저자, 연도, 섹션]으로 표기하세요.
자료에 없는 정보는 "우리 실험실 자료에서 확인 안 됨"으로 답하세요.
자료:
{context}
질문: {question}
답변:"""
return llm(prompt, temperature=0)
# 사용
ask_lab("CRISPR 편집 효율이 20% 이하였던 case가 있었나?")

시스템 프롬프트로 출처 표시 강제 + 자료 밖 정보 거절. 편 #7의 프롬프트 규칙과 결합.

시나리오 2 — 임상 시험 문헌 검색 어시스턴트

특정 질환·치료법의 임상 시험 결과를 종합 검색.

  • 데이터 소스: ClinicalTrials.gov, PubMed, 학회 초록.
  • Chunking: 각 시험을 하나의 문서로. 초록·프로토콜·결과를 별도 조각.
  • Hybrid search: 약물명·유전자명은 BM25가 강해서 hybrid 필수.
  • Reranker: 임상 관련도 판정 정확도가 답변 품질 좌우.
  • Metadata filter: "Phase 3", "2020년 이후", "adult only" 같은 필터를 벡터 검색과 결합.

이런 어시스턴트가 요즘 CRO·병원 리서치팀에서 실무 배치되고 있음.

시나리오 3 — 유전자·단백질 지식 QA

BioBERT 임베딩 + UniProt·Ensembl 데이터로 유전자 QA 시스템.

  • 유전자 하나의 UniProt 페이지를 여러 조각으로 (function, structure, disease, PTM 등)
  • 도메인 특화 임베딩(BioBERT) 사용
  • 사용자 질문: "TP53과 상호작용하는 kinase는?" → 관련 조각 검색 → LLM이 요약

이 계열이 최근 상용 바이오 툴(Elicit·Consensus 등)의 뿌리 기술.


핵심 정리

  • LLM 지식이 사는 두 자리: 파라미터(붙박이·재훈련 필요)와 문맥 창(즉시·유한).
  • RAG는 외부 지식을 문맥에 동적으로 주입하는 아키텍처. 검색 + 생성 조합.
  • 파이프라인: chunking → 임베딩 → 벡터 DB → 검색 → 프롬프트 주입 → LLM.
  • Chunking은 200800 토큰 + 1020% 오버랩. 섹션 경계 존중.
  • 임베딩 검색은 편 #5 임베딩 공간의 자연스러운 확장. 코사인 유사도.
  • Vector DB — 시작은 Chroma, 규모 시엔 Qdrant·Pinecone.
  • Hybrid search (dense + BM25)로 정확한 식별자 매칭 보강. RRF로 결합.
  • Reranker (cross-encoder)로 최종 정확도 향상. 2단계 파이프라인.
  • 한계: 검색 실패, 결합 추론, 인용 오류, 부정형 질문.
  • Long-context 시대에도 RAG는 유효. 비용·정확도(lost in the middle)·확장성 이유.

다음 개념


📐 부록 — 전문가를 위한 수학 공식

난이도: 매우 어려움 (Very Hard) 대상: 정보검색·확률·최적화 배경이 있는 독자

A.1 코사인 유사도와 내적

두 벡터 u, v ∈ ℝ^d:

text
cos_sim(u, v) = ⟨u, v⟩ / (||u||_2 · ||v||_2)

정규화된 벡터(||u||_2 = 1)라면 코사인 유사도 = 내적:

text
cos_sim(u, v) = ⟨u, v⟩ = Σ_i u_i v_i

편 #6 어텐션 스코어와의 관계. 어텐션의 ⟨Q_i, K_j⟩도 같은 내적 형태. RAG의 검색이 어텐션의 첫 스코어 계산과 개념적으로 동형.

A.2 임베딩 모델 훈련의 대조 학습

Sentence-BERT 계열이 채택. 유사한 쌍은 가깝게, 다른 쌍은 멀게.

Triplet Loss:

text
L = max(0, ||f(a) - f(p)||^2 - ||f(a) - f(n)||^2 + margin)

a: 앵커, p: 긍정(유사), n: 부정(무관). margin(예: 0.5)만큼 부정이 더 멀어지도록.

InfoNCE Loss (SimCLR 계열, 실무 표준):

text
L = -log[ exp(sim(f(a), f(p)) / τ) / Σ_k exp(sim(f(a), f(k)) / τ) ]

τ: temperature. 미니배치 안 다른 예시들이 자동 부정 예시로 사용.

A.3 BM25 수식

문서 D, 질의 Q = {q_1, ..., q_n}:

text
BM25(D, Q) = Σ_i IDF(q_i) · TF(q_i, D) · (k_1 + 1) / (TF(q_i, D) + k_1 · (1 - b + b · |D| / avgdl))
  • IDF(q_i) = log((N - n_i + 0.5) / (n_i + 0.5) + 1). N: 전체 문서 수, n_i: q_i 포함 문서 수.
  • TF(q_i, D): 문서 D에서 q_i의 빈도.
  • avgdl: 평균 문서 길이.
  • 파라미터: k_1 = 1.2~2.0, b = 0.75.

직관. 자주 나오는 단어는 IDF가 낮아 가중치 낮음. 문서에서 자주 반복되면 TF 높음. 문서가 길수록 정규화. 검색 엔진의 30년 표준.

A.4 Reciprocal Rank Fusion (RRF)

여러 검색 방식의 순위를 결합:

text
RRF_score(d) = Σ_{r ∈ R} 1 / (k + rank_r(d))
  • R: 검색 방식 집합 (예: dense, sparse).
  • rank_r(d): 방식 r에서 문서 d의 순위 (1이 최상).
  • k = 60 (경험적 기본값).

장점: 각 방식의 절대 점수가 아니라 순위만 사용. 스케일 차이 무시 가능.

A.5 Cross-Encoder Rerank 수식

Cross-encoder 입력:

text
[CLS] question [SEP] document [SEP]

이 전체 시퀀스에 대해 트랜스포머(BERT/RoBERTa 계열)가 어텐션 계산. [CLS] 토큰의 최종 표현이 선형 층을 통과해 관련도 점수:

text
score = W · h_{CLS} + b

계산 비용. Bi-encoder는 두 인코더 독립 계산이라 K개 문서 검색 시 2K 인코더 통과. Cross-encoder는 각 (Q, D) 쌍마다 인코더 통과라 K번 통과이지만 K가 많으면 훨씬 느림.

실무: bi-encoder로 100개 → cross-encoder로 top-10 파이프라인.

A.6 HNSW 인덱스

Hierarchical Navigable Small World. 근사 최근접 검색의 오늘 표준.

구조: 다층 그래프. 상위 층은 sparse(적은 노드·긴 간선), 하위 층은 dense(많은 노드·짧은 간선). 검색 시 상위 층에서 대략 방향 잡고 하위 층에서 정밀 탐색.

시간 복잡도: O(log N) — 정확 검색 O(N)에 비해 매우 빠름.

정확도: 파라미터(M, ef_construction, ef_search)에 따라 조정. 대개 recall 95%+ 유지 가능.

메모리: 벡터 자체 + 그래프 구조. 그래프 오버헤드 대략 벡터 크기의 1~2배.

A.7 Query Rewriting 기법

HyDE (Hypothetical Document Embeddings):

  1. 질문을 LLM에 넣어 "가상의 답변 문서"를 먼저 생성.
  2. 이 가상 답변을 임베딩해서 검색.

이유. 질문과 답변은 표현 방식이 다르지만, 답변과 답변은 표현이 유사. 가상 답변으로 검색하면 실제 답이 포함된 문서와 매칭 잘 됨.

Multi-Query:

  1. LLM으로 질문을 여러 가지로 다시 씀(다른 표현·다른 각도).
  2. 각 쿼리로 검색 후 결과 합침.

A.8 Long-Context의 "Lost in the Middle" 현상

Liu et al. (2023) 관찰. LLM이 긴 문맥의 처음과 끝에 있는 정보를 잘 찾고, 중간의 정보를 놓치는 경향.

정확도 곡선. 문맥 위치를 x축, 정답률을 y축으로 그리면 U자형. 시작·끝 90%, 중간 60% 수준.

대응:

  • 중요 정보를 문맥 시작이나 끝에 배치.
  • Reranker로 상위 조각을 문맥 시작에 배치.
  • Long-context 대신 RAG로 관련 부분만 압축.

A.9 RAG의 확률적 정식화

질문 q, 답 a, 문서 조각 d.

Naive Bayes 관점:

text
P(a | q) = Σ_d P(a | q, d) · P(d | q)
  • P(d | q): 검색 확률 (임베딩 유사도).
  • P(a | q, d): 문서 주어진 답변 확률 (LLM).

Fusion-in-Decoder (FiD). 검색된 K개 문서를 각각 독립 인코딩 후 디코더에서 결합. RETRO·Atlas 계열이 이 접근.

Retrieval-Augmented Language Model (RALM). 모델 파라미터 자체에 검색을 통합. RETRO·REALM. 매 훈련 스텝에 검색 참조.

A.10 RAG 성능 지표

Retrieval 단계:

  • Recall@K: 정답이 상위 K에 포함된 비율.
  • Precision@K: 상위 K 중 실제 관련된 비율.
  • MRR (Mean Reciprocal Rank): 정답 순위의 역수의 평균.
  • NDCG (Normalized Discounted Cumulative Gain): 순위 가중 관련도.

Generation 단계:

  • Faithfulness: 답이 검색된 문서에 근거하는가.
  • Answer Relevancy: 답이 질문에 관련되는가.
  • Context Precision·Recall: 검색 문맥이 답에 필요한 정보를 포함하는가.

. RAGAS·TruLens 같은 프레임워크가 이런 지표를 자동 측정.


참고 자료

본 편의 콘텐츠·시나리오·비유·수치는 모두 BioPlayground 자체 개발이며, 아래는 개념 학습에 도움이 되는 외부 참고 자료입니다.

  • RAG 원 논문: Lewis et al., "Retrieval-Augmented Generation for Knowledge-Intensive NLP Tasks" (NeurIPS 2020)
  • Dense Passage Retrieval: Karpukhin et al., "Dense Passage Retrieval for Open-Domain Question Answering" (EMNLP 2020)
  • BM25: Robertson & Zaragoza, "The Probabilistic Relevance Framework: BM25 and Beyond" (2009)
  • Sentence-BERT: Reimers & Gurevych, "Sentence-BERT: Sentence Embeddings using Siamese BERT-Networks" (EMNLP 2019)
  • HNSW: Malkov & Yashunin, "Efficient and robust approximate nearest neighbor search using Hierarchical Navigable Small World graphs" (TPAMI 2020)
  • Lost in the Middle: Liu et al., "Lost in the Middle: How Language Models Use Long Contexts" (TACL 2023)
  • HyDE: Gao et al., "Precise Zero-Shot Dense Retrieval without Relevance Labels" (ACL 2023)
  • Fusion-in-Decoder: Izacard & Grave, "Leveraging Passage Retrieval with Generative Models" (EACL 2021)
  • RETRO: Borgeaud et al., "Improving language models by retrieving from trillions of tokens" (ICML 2022)
  • BioBERT: Lee et al., "BioBERT: a pre-trained biomedical language representation model" (Bioinformatics 2020)
  • LangChain 문서: python.langchain.com
  • LlamaIndex 문서: docs.llamaindex.ai
  • Anthropic Contextual Retrieval: anthropic.com/news/contextual-retrieval

편 #8로 외부 지식을 LLM에 얹는 방법을 배웠습니다. 편 #9에서는 LLM이 스스로 도구(검색·계산·API 호출)를 부리는 에이전트 패턴을 다룹니다.