RAG 튜토리얼

RAG 튜토리얼 (Tutorial: Retrieval-Augmented Generation)

DSPy에서 검색 증강 생성(Retrieval-Augmented Generation, RAG) 의 유·무에 따른 기본 질의응답의 빠른 예시를 살펴봅니다. 구체적으로는 Linux나 iPhone 앱 같은 Tech 질문에 답하는 시스템을 만듭니다.

출처: 문서

본문

최신 DSPy를 pip install -U dspy 로 설치하고 따라와 주세요. 개념적 개요가 필요하다면 이 최근 강의가 좋은 출발점입니다. pip install datasets 도 실행해야 합니다. 이 튜토리얼은 dspy.Embedder 와 dspy.retrievers.Embeddings 를 쓰는데, numpy가 필요하므로 pip install dspy[numpy] 도 실행하세요.

DSPy 환경 구성

모듈에서 OpenAI gpt-4o-mini 를 사용한다고 DSPy에 알립니다. 인증은 OPENAI_API_KEY 에서 찾아봅니다. 다른 공급자나 로컬 모델로 쉽게 바꿀 수 있습니다.

권장: MLflow Tracing 설정(튜토리얼 내 네 단계 안내).

import dspy

lm = dspy.LM('openai/gpt-4o-mini')
dspy.configure(lm=lm)

가장 단순한 모듈은 dspy.Predict 입니다. DSPy Signature 즉 구조화 입출력 스키마를 받아 지정한 동작의 호출 가능한 함수를 반환합니다.

qa = dspy.Predict('question: str -> response: str')
response = qa(question="what are high memory and low memory on linux?")
print(response.response)

시그니처에서 지정한 변수 이름이 입력·출력 인자 이름과 역할을 정의한 것을 주목하세요. dspy.inspect_history(n=1) 로 DSPy가 보낸 프롬프트를 확인할 수 있습니다.

DSPy는 다양한 내장 모듈(dspy.ChainOfThought, dspy.ProgramOfThought, dspy.ReAct)을 가지며, 이들은 기본 dspy.Predict 와 상호 교환 가능합니다. 같은 시그니처를 받고 일반적인 프롬프트 기법·추론 시점 전략을 적용합니다. 예를 들어 dspy.ChainOfThought 는 시그니처가 요청한 출력 전에 LM에서 reasoning 을 이끌어내는 쉬운 방법입니다.

예시 다루기와 평가

RAG-QA Arena "Tech" 데이터셋에서 StackExchange 기반 질문과 정답 세트를 내려받습니다. 간단한 dict를 dspy.Example 리스트로 만듭니다. dspy.Example 을 만들 때 .with_inputs("field1", ...) 로 어떤 필드가 입력인지 지정하고, 나머지는 레이블·메타데이터로 취급됩니다.

data = [dspy.Example(**d).with_inputs('question') for d in data]

메트릭으로 dspy.evaluate.SemanticF1 을 씁니다. 이것은 실제로 우리가 쓰는 LM을 사용하는 매우 단순한 DSPy 모듈로 구현된 의미적 F1 메트릭입니다. dspy.Evaluate 로 병렬 평가를 실행할 수 있습니다.

evaluate = dspy.Evaluate(devset=devset, metric=metric, num_threads=24, ...)

기본 RAG

RAG 검색용 코퍼스 데이터를 내려받습니다. 더 빠르고 값싸게 돌리려고 코퍼스를 28,000 문서로 다운샘플링했습니다.

시스템의 retriever 설정

dspy.Embedder 와 임베딩을 사용해 retriever를 구성합니다.

첫 RAG 모듈 만들기

dspy.Module 로 검색과 답변 생성을 조합합니다. forward 는 질문을 받아 관련 문단을 검색해 컨텍스트를 만들고, ChainOfThought 로 답을 생성합니다.

class RAG(dspy.Module):
    def __init__(self, k=3):
        super().__init__()
        self.retrieve = dspy.Retrieve(k=k)
        self.generate_answer = dspy.ChainOfThought("context, question -> answer")

    def forward(self, question):
        context = self.retrieve(question).passages
        return self.generate_answer(context=context, question=question)

DSPy 최적화기로 RAG 프롬프트 개선

dspy.GEPA 같은 최적화기로 메트릭에 맞춰 RAG 프로그램을 컴파일하면 더 높은 품질의 프롬프트를 얻어 점수를 더 끌어올립니다.

비용 주시

작은 LM과 최적화를 결합해 정확도를 높이면서 비용을 낮출 수 있습니다.

저장과 불러오기

최적화된 프로그램을 저장하고 다시 불러올 수 있습니다(MLflow에도 저장·로드 가능).

다음은?

Multi-Hop RAG나 RAG를 에이전트로 같은 심화 튜토리얼로 나아가세요.

더 알아보기 (Learn more)