[논문 리뷰] DSPy: Compiling Declarative Language Model Calls into Self-Improving Pipelines

smj·2026년 3월 31일

review

목록 보기
15/30

한줄 요약: 프롬프트 엔지니어링을 수작업에서 프로그래밍으로 전환 — LM 호출을 선언적으로 정의하고 컴파일러가 자동으로 프롬프트/파인튜닝을 최적화한다.

항목내용
저자Omar Khattab, Arnav Singhvi, Paridhi Maheshwari, Zhiyuan Zhang, Keshav Santhanam, Sri Vardhamanan, Saiful Haq, Ashutosh Sharma, Thomas T. Joshi, Hanna Moazam, Heather Miller, Matei Zaharia, Christopher Potts
소속Stanford University
발표ICLR 2024
링크arxiv.org/abs/2310.03714
키워드Prompt Optimization, Compiler, Declarative Programming, LM Pipeline

1. 문제 정의

현재 LLM 애플리케이션 개발의 문제:

전형적인 RAG 파이프라인의 프롬프트:
  "You are a helpful assistant. Given the context below, answer the question.
   Be concise. If you don't know, say 'I don't know'.
   Context: {context}
   Question: {question}
   Answer:"

문제점:
  1. 취약성: 단어 하나 바꾸면 성능 급변 ("Be concise" 제거 → 성능 10% 하락)
  2. 모델 종속: GPT-4에서 튜닝한 프롬프트가 Llama에서는 작동 안 함
  3. 파이프라인 복잡도: RAG = 검색 + 재랭킹 + 생성, 각 단계마다 프롬프트 튜닝 필요
  4. 비체계적: 프롬프트 변경의 전체 파이프라인 영향을 예측 불가

핵심 제안: 프롬프트를 직접 쓰는 대신, 무엇을 할지(what)를 선언하고 어떻게 할지(how)는 컴파일러에 맡긴다.


2. 제안 방법

Signature: 입출력 선언

# 기존: 장황한 프롬프트 직접 작성
prompt = "Given a question, search for relevant passages and provide a concise answer..."

# DSPy: 입출력만 선언
class GenerateAnswer(dspy.Signature):
    """Answer questions with short factoid answers."""
    context = dspy.InputField(desc="relevant passages")
    question = dspy.InputField()
    answer = dspy.OutputField(desc="often between 1 and 5 words")

Module: 재사용 가능한 LM 호출 패턴

# 내장 모듈
dspy.Predict(signature)      # 기본 LM 호출
dspy.ChainOfThought(sig)     # 자동으로 "reasoning" 단계 추가
dspy.ReAct(sig, tools=[...]) # ReAct 패턴 자동 구현
dspy.Retrieve(k=3)           # 검색 모듈

# RAG 파이프라인 정의
class RAG(dspy.Module):
    def __init__(self):
        self.retrieve = dspy.Retrieve(k=3)
        self.generate = dspy.ChainOfThought(GenerateAnswer)

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

Teleprompter (Optimizer): 자동 최적화

컴파일 과정:
  1. 학습 데이터 (질문, 정답) 쌍 준비
  2. Teleprompter가 자동으로:
     - Few-shot 예시 선택 (BootstrapFewShot)
     - 또는 instruction 최적화 (COPRO, MIPRO)
     - 또는 파인튜닝 데이터 생성 (BootstrapFinetune)
  3. 각 모듈의 프롬프트를 독립적으로 최적화
  4. 전체 파이프라인의 end-to-end 메트릭 기반 평가

teleprompter = BootstrapFewShotWithRandomSearch(
    metric=answer_exact_match,
    max_bootstrapped_demos=4,
    num_candidate_programs=16
)
compiled_rag = teleprompter.compile(RAG(), trainset=trainset)

핵심 철학: 분리

개발자가 정의하는 것:     컴파일러가 결정하는 것:
  - 입출력 스키마          - 프롬프트 텍스트
  - 모듈 구조              - Few-shot 예시 선택
  - 평가 메트릭            - Instruction 문구
  - 파이프라인 흐름         - 파인튜닝 여부/데이터

→ "무엇(what)"과 "어떻게(how)"의 분리
→ 모델을 바꿔도 re-compile만 하면 됨

3. 실험 결과

3.1 GSM8K (수학 추론)

방법정확도
표준 프롬프트33.8%
수작업 CoT 프롬프트44.2%
DSPy BootstrapFewShot49.1%
DSPy MIPRO52.7%

3.2 HotPotQA (멀티홉 QA)

방법F1 Score
표준 RAG36.2
수작업 최적화 RAG41.5
DSPy compiled RAG51.3
DSPy compiled Baleen57.0

→ 수작업 프롬프트 대비 15-20%p 향상 — 자동 최적화가 사람보다 우수

3.3 모델 전환 시 강건성

GPT-3.5에서 최적화한 프롬프트를 Llama-2-13B에 적용:
  수작업 프롬프트: 성능 -23% 하락
  DSPy re-compile: 성능 -3% 하락

→ 모델 전환 시 re-compile만으로 적응

4. 한계점

  • 학습 데이터 필요: 최소 수십 개의 (입력, 정답) 쌍이 필요 → 완전한 zero-shot 시나리오에는 부적합
  • 컴파일 비용: BootstrapFewShot은 수백 번의 LM 호출 필요 → MIPRO는 수천 번
  • 디버깅 어려움: 컴파일러가 생성한 프롬프트가 왜 효과적인지 해석이 어려움
  • 메트릭 정의의 어려움: 좋은 메트릭을 정의하는 것 자체가 도메인 지식 필요
  • 복잡한 파이프라인에서의 최적화: 5단계 이상 파이프라인에서 각 단계의 최적화가 서로 간섭할 수 있음
  • 커뮤니티 성숙도: 빠르게 발전 중이나 API 변경이 잦아 프로덕션 안정성 우려

5. 의의와 영향

  • "프롬프트 엔지니어링 → 프롬프트 프로그래밍" 패러다임 전환의 선두주자
  • LLM 애플리케이션을 소프트웨어 공학적으로 다루는 프레임워크 — 테스트, 최적화, 재현 가능
  • 모델 독립적 개발: 코드 변경 없이 GPT-4 → Llama → Mistral 전환 가능
  • Stanford NLP 그룹(ColBERT, Alpaca의 저자들)의 집대성
  • LangChain/LlamaIndex와 다른 철학: 체이닝(how) 대신 선언(what)에 집중

6. 💬 리뷰어 코멘트

DSPy의 핵심 통찰은 "프롬프트는 코드가 아니라 설정(config)이어야 한다"는 것이다. 현재 대부분의 LLM 애플리케이션에서 프롬프트는 하드코딩된 문자열이고, 모델이나 태스크가 바뀌면 사람이 다시 튜닝해야 한다. DSPy는 이를 컴파일러에 위임함으로써, 프롬프트를 "최적화 가능한 파라미터"로 취급한다.

실전에서의 주의점: DSPy는 명확한 평가 메트릭이 있는 태스크에서 강력하다 (QA, 분류, 추출). 하지만 "좋은 글쓰기"처럼 메트릭 정의가 모호한 태스크에서는 컴파일러의 효과가 제한적이다.

LangChain이 "LLM 호출을 쉽게 체이닝"하는 도구라면, DSPy는 "LLM 호출을 자동으로 최적화"하는 도구다. 이 둘은 경쟁보다 상보적이며, 장기적으로 DSPy의 선언적 접근이 더 확장 가능해 보인다.


관련 논문: ColBERT, ARES, Demonstrate-Search-Predict, Self-Instruct

0개의 댓글