옵티마이저: 어떤 걸 고를까

옵티마이저: 어떤 걸 골라야 하나요?

이 페이지가 왜 필요한가요?

DSPy에는 옵티마이저(텔레프롬프터)가 열두 개나 있어요. 그래서 DSPy에서 가장 많이 묻는 질문이 "그럼 뭘 써야 하나요?"예요. 이 페이지는 그 선택을 위한 가이드예요. 각 옵티마이저가 무엇을 튜닝하고, 컴파일 시점에 무엇이 필요한지, 비용이 얼마나 드는지, 그리고 언제 다른 옵티마이저보다 나은지 정리해요.

프로그램과 메트릭이 준비됐고, 무엇을 컴파일할지 정하려는 시점에 읽으면 좋아요. 개별 옵티마이저의 심화 페이지들(GEPA, BootstrapFewShot 계열, BootstrapFinetune)은 이 페이지와 나란히 두는 구성이에요.

설계 결정

1. 모든 옵티마이저는 명령어·데모·가중치 중 하나 이상을 튜닝해요

이 세 개의 손잡이(노브)가 DSPy가 노출하는 모든 탐색 공간을 덮어요. 명령어(instruction) 는 각 predictor 시그니처의 자연어 docstring이고, 데모(demo) 는 호출 시점에 각 predictor가 보는 컨텍스트 내 예시이며, 가중치(weight) 는 LM이 튜닝 가능할 때의 모델 파라미터예요. 각 옵티마이저는 이 중 하나나 둘을 골라 나머지는 건드리지 않아요. 아래 API 워크스루는 이 손잡이 기준으로 그룹을 나눠요.

2. .compile()은 새 복사본을 반환해요 — 원본 student는 바뀌지 않아요

모든 옵티마이저가 먼저 하는 일은 student.reset_copy()예요. 이건 딥카피인데, 상속된 _compiled 플래그까지 함께 비워요. 컴파일된 프로그램이 반환되고, 여러분이 넘긴 원본은 그대로 남아요. 같은 student에 서로 다른 옵티마이저·데이터셋·예산으로 .compile()을 다시 실행하고, 실행 간 상태 누수를 걱정하지 않고 결과를 비교할 수 있어요.

3. _compiled=True 플래그는 이후 옵티마이저가 서브모듈을 건드리지 않게 해줘요

.compile()이 성공하면 옵티마이저는 반환된 모듈에 _compiled = True를 설정해요. 이 컴파일된 모듈을 더 큰 프로그램 안에 넣고 바깥 모듈에 두 번째 옵티마이저를 돌리면, named_parameters()가 안쪽 컴파일된 모듈을 건너뛰어요. 그래서 안쪽 predictor들은 첫 옵티마이저가 남긴 그대로 유지되요. 이 플래그가 "안쪽 최적화 → 바깥에 임베드 → 바깥 최적화"를 가능하게 해요.

4. 모든 옵티마이저는 metric을 받지만, 요구하는 메트릭 형태는 달라요

모든 옵티마이저는 예시당 숫자 점수를 읽어요. 대부분은 단순한 float나 boolean이면 충분해요. 하지만 GEPA는 자연어 비평을 제안에 흘려보내기 때문에 Prediction(score, feedback)을 추가로 필요로 해요. 옵티마이저에 맞지 않는 메트릭 형태를 고르는 게 가장 흔한 설정 실수예요. 의심되면 해당 옵티마이저 페이지를 확인하세요.

5. predictor별 Prediction(score, feedback)을 읽는 건 GEPA뿐이에요

다른 명령어 옵티마이저(COPRO, MIPROv2)는 메트릭을 블랙박스 스칼라로 취급해요. 후보 A가 후보 B보다 높은 점수를 받았는지 정도만 알아요. 반면 GEPA는 각 메트릭 호출에서 feedback을 읽어 다음 명령어 제안에 반영해요. 같은 의미이지만 반대로, 피드백이 풍부한 메트릭이 없다면 같은 예산에서 GEPA보다 COPRO나 MIPROv2가 나은 성과를 낼 수도 있어요.

6. 프롬프트 전용 옵티마이저는 어떤 LM이든 동작하고, 미세조정 옵티마이저는 튜닝 가능한 모델이 필요해요

BootstrapFewShot, COPRO, MIPROv2, GEPA 등 대부분은 프롬프트와 데모를 바꿔요. LM은 그대로이므로 폐쇄형(closed-source) 프로바이더도 쓸 수 있어요. 반면 BootstrapFinetune은 새 모델 가중치를 쓰기 때문에 미세조정 API를 노출하는 LM(로컬 트레이너, 오픈소스 모델, OpenAI 미세조정 엔드포인트 같은 프로바이더)이 필요해요. 이 차이가 여러분에게 어떤 옵티마이저가 가능한지를 가르는 기준이에요.

7. 데모 튜닝은 과적합되기 쉽고, 명령어 튜닝은 일반화되기 쉬워요

50개 훈련 예시에서 학습한 데모 셋은 그 특정 trainset을 설명해요. 그 예시들과 닮지 않은 입력은 혜택을 못 볼 수 있어요. 반면 명령어 재작성은 예시 위의 수준에서 패턴을 잡아내서 전이되기 쉬워요. 보편 법칙은 아니지만, 검증 셋이 작거나 편향돼 있다면 명령어 최적화 쪽으로 기우는 게 유용한 기본값이에요.

8. 대부분의 팀은 프롬프트 전용으로 시작하다가, 그것이 정체되면 미세조정으로 넘어가요

프롬프트 전용 최적화는 LM 토큰이 들어요. 미세조정은 LM 토큰 + 훈련 연산 + 새 가중치 배포 비용. GEPA나 MIPROv2 위의 미세조정의 한계적 향상은 보통 작고 때로는 음수인 반면, 한계 비용은 훨씬 커요. 미세조정은 첫 지렛대가 아니라 마지막 지렛대로 취급하세요.

9. "한 번 컴파일, 저장, 재로드" 루프가 옵티마이저 비용을 분산시켜요

.compile()은 비싸요. GEPA와 MIPROv2는 단일 실행에 수백 달러를 LM 호출로 쓸 수 있어요. 하지만 결과물은 이동 가능한 아티팩트(program.save(path))이고, 그걸로 추론하는 건 저렴해요. 프로그램 버전당 한 번 컴파일하고 저장된 아티팩트를 여러 번 서빙할 때 경제성이 성립해요.

10. LM 기반 자동 선택은 없어요 — 여러분이 고르는 거예요

DSPy는 태스크나 LM을 내성적으로 살펴 옵티마이저를 골라주지 않아요. MIPROv2와 GEPA의 auto 손잡이는 옵티마이저 내부의 예산만 제어하지, 어느 옵티마이저를 쓸지는 제어하지 않아요. 이 페이지 맨 아래의 선택 치트시트가 가장 추천 엔진에 가까운 자료예요.

2축 결정

두 질문이 후보를 빠르게 줄여줘요.

병목은 명령어, 데모, 아니면 가중치인가요? 프롬프트 문구가 틀렸다면 명령어 옵티마이저(COPRO, GEPA, MIPROv2)가 도와줘요. 모델이 형식과 스타일을 고정할 예시가 필요하다면 데모 옵티마이저(BootstrapFewShot, BootstrapRS)가 도와줘요. 모델 자체가 한계이고 미세조정이 가능하다면 가중치 튜닝(BootstrapFinetune)이 지렛대예요.

연산 예산은 얼마인가요? 제로 설정 베이스라인(LabeledFewShot, BootstrapFewShot)은 거의 비용이 안 들어요. 탐색 기반 옵티마이저(BootstrapRS, MIPROv2, GEPA)는 실제 비용이 들어요. 결합 옵티마이저(BetterTogether)는 둘 다 내요.

API 워크스루

각 옵티마이저가 무엇을 튜닝하는지 기준으로 그룹을 나눴어요.

여기서 시작

두 줄짜리 베이스라인이에요. 더 무거운 걸 만지기 전에 이 중 하나를 먼저 써보세요.

dspy.LabeledFewShot(k=16).compile() 동안 LM 호출이 없어요. trainset에서 최대 k개 예시(sample=False면 결정적, 기본은 무작위)를 샘플링해 각 predictor의 demo로 붙여요. 정직한 베이스라인으로 쓰세요. LabeledFewShot만으로 목표에 도달한다면 더 무거운 최적화는 낭비예요.

dspy.BootstrapFewShot(metric=None, metric_threshold=None, teacher_settings=None, max_bootstrapped_demos=4, max_labeled_demos=16, max_rounds=1) — 프로그램(또는 제공한 teacher)을 훈련 예시에 실행하고, 각 완성을 메트릭으로 채점한 뒤 메트릭을 통과한 trace를 demo로 남겨요. 결합된 셋은 각 predictor마다 최대 max_bootstrapped_demos개의 부트스트랩 trace와 최대 max_labeled_demos개의 원시 라벨 예시를 섞어요. 메트릭이 신뢰할 만하면 거의 항상 zero-shot을 이겨요. 안전한 첫 시도예요.

데모 셋에서 탐색

한 번의 부트스트랩 통과로 부족할 때.

dspy.BootstrapFewShotWithRandomSearch(metric, max_bootstrapped_demos=4, max_labeled_demos=16, max_rounds=1, num_candidate_programs=16, num_threads=None, stop_at_score=None)dspy.BootstrapRS로도 불려요. BootstrapFewShot을 서로 다른 무작위 시드로 num_candidate_programs회 실행하고, 각 후보를 valset에서 평가해 가장 높은 점수 하나를 반환해요. 무작위성은 어느 trace가 먼저 부트스트랩되느냐에서 와요. 서로 다른 시드가 서로 다른 데모 부분집합을 발견하죠. stop_at_score는 후보가 목표를 넘으면 일찍 멈춰요.

dspy.KNNFewShot(k, trainset, vectorizer, **bootstrap_kwargs) — 데모가 컴파일 시점이 아니라 추론 시점에 골라져요. 생성 시 trainset을 vectorizer로 임베딩해 캐시해요. 매 호출마다 입력을 임베딩하고, 가장 가까운 k개 훈련 예시를 검색해 그 단일 호출의 데모로 써요. 입력 분포 전반에 일반화되는 단일 데모 셋이 없을 때 이 간접성이 가치가 있어요.

명령어 최적화

예시가 아니라 프롬프트 문구가 발목을 잡을 때.

dspy.COPRO(prompt_model=None, metric=None, breadth=10, depth=3, init_temperature=1.4, track_stats=False) — 폭 우선 제안자예요. depth개의 각 레벨에서 prompt_model로 predictor마다 breadth개의 후보 명령어를 생성하고, trainset으로 채점한 뒤 최고를 유지해요. 총 LM 비용은 대략 breadth × depth × num_predictors예요. 가볍고, 데모가 이미 강한데 문구만 고치면 될 때 특히 좋아요.

dspy.GEPA(metric, auto=None, max_full_evals=None, max_metric_calls=None, reflection_lm=None, skip_perfect_score=True, instruction_proposer=None, use_merge=True, num_threads=None) — 반성(reflection)이 이끄는 진화적 명령어 탐색이에요. GEPA는 프로그램 개체군을 유지하고, 각각을 trainset에서 실행하며, 메트릭의 predictor별 feedback을 읽고, reflection_lm으로 그 피드백을 반영한 편집을 제안해요. 파레토 최적해에서 최고 후보를 반환해요. 강한 reflection LM과 피드백 형태의 메트릭이 있을 때 프롬프트 전용 최적화에서 두드러져요. 자세한 메커니즘은 GEPA 심화를 보세요.

명령어와 데모를 함께 최적화

dspy.MIPROv2(metric, prompt_model=None, task_model=None, teacher_settings=None, max_bootstrapped_demos=4, max_labeled_demos=4, auto="light", num_candidates=None, num_threads=None, init_temperature=1.0, track_stats=True) — 명령어+데모 결합 공간에 대한 베이지안 최적화 탐색이에요. prompt_model(종종 더 강한 LM)이 명령어를 제안하고, task_model(여러분의 student)이 프로그램을 실행해요. auto("light" / "medium" / "heavy")는 제안과 평가 양쪽의 예산으로 환산돼요. 명령어와 데모를 함께 튜닝해야 할 때 최신 기법(state of the art)이에요.

dspy.SIMBA(metric, bsize=32, num_candidates=6, max_steps=8, max_demos=4, prompt_model=None, teacher_settings=None, num_threads=None) — 미니배치 SGD 풍의 탐색이에요. 각 스텝이 bsize 미니배치를 샘플링하고, 최악 점수 예시를 찾아 prompt_model이 자연어 규칙(명령어 패치)이나 새 데모를 제안해 그 예시를 다뤄요. 미니배치 중심이라 SIMBA는 반응적이에요. 각 스텝이 평균이 아니라 현재의 약점을 겨냥하죠.

dspy.InferRules(num_candidates=10, num_rules=10, num_threads=None, **bootstrap_kwargs)BootstrapFewShot을 확장해요. 데모를 부트스트랩한 뒤 teacher LM에 그 데모를 읽고 num_rules개의 일반 규칙을 추출하게 하고, 그 규칙을 predictor의 명령어에 덧붙여요. 규칙은 해석 가능해서 읽고 유지할지 결정할 수 있어요. 예시로부터 그냥 추론하기보다 명시적으로 규칙으로 표현하고 싶은 패턴이 있을 때 유용해요.

가중치 미세조정

dspy.BootstrapFinetune(metric=None, multitask=True, train_kwargs=None, adapter=None, exclude_demos=False, num_threads=None)BootstrapFewShot처럼 성공 trace를 부트스트랩한 뒤 그걸 훈련 데이터로 써서 student LM을 미세조정해요. .finetune() 메서드가 있는 LM이 필요해요. Together AI 같은 오픈소스 LM 프로바이더, OpenAI 미세조정 API, 또는 로컬 트레이너요. multitask=True는 모든 predictor에 걸쳐 하나의 모델을, False는 predictor별로 별도 모델을 훈련해요.

옵티마이저 합성

dspy.BetterTogether(metric, **optimizers) — 문자열("p -> w -> p")로 지정한 순서, 즉 프롬프트 최적화 → 가중치 튜닝 → 다시 프롬프트 최적화를 실행하는 메타 옵티마이저예요. optimizers kwargs가 문자를 옵티마이저 인스턴스(p=GEPA(...), w=BootstrapFinetune(...))에 매핑해요. 기본은 pBootstrapRS, wBootstrapFinetune이에요. 프롬프트 전용과 가중치 전용을 둘 다 시도했는데 합성이 될 것 같을 때 써요.

dspy.Ensemble(reduce_fn=None, size=None, deterministic=False) — 흔한 의미의 옵티마이저는 아니에요. 이미 컴파일된 프로그램들을 하나로 합쳐요. .compile(programs)는 각 입력을 모든 프로그램에 병렬로 통과시키고 reduce_fn(커스텀 함수, 기본은 dspy.majority를 통한 다수결 투표)으로 줄이는 모듈을 반환해요. 여러 옵티마이저 실행이 각각 훌륭한 후보를 만들고, 추론 시점에 결합하고 싶을 때 유용해요.

특수 목적

dspy.AvatarOptimizer(metric, max_iters=10, lower_bound=0, upper_bound=1, max_positive_inputs=10, max_negative_inputs=10, optimize_for="max") — 에이전트형 프로그램용이에요. trainset을 메트릭 기준으로 높은 점수(긍정)와 낮은 점수(부정) 예시로 나눠요. 매 반복마다 LM으로 긍정·부정 예시를 읽고 그 차이를 설명하는 명령어 편집을 제안한 뒤 새 명령어를 평가해요. 메트릭이 깔끔한 합격/불합격이고 해석 가능한 에이전트 명령어가 필요할 때 틈새로 유용해요.

선택 치트시트

상황 시도
막 시작, 뭐가 도움이 될지 모름 BootstrapFewShot
데모가 시도마다 품질이 들쭉날쭉 BootstrapFewShotWithRandomSearch
큰 trainset, 입력마다 다른 데모 필요 KNNFewShot
명령어가 틀려 보이고 데모는 괜찮음 COPRO 또는 GEPA
둘 다 약하고 예산 있음 MIPROv2 또는 GEPA
실패 사례가 이름 붙일 만한 패턴을 공유 SIMBA 또는 InferRules
프롬프트 전용이 정체됐고 모델을 튜닝 가능 BootstrapFinetune
프롬프트+가중치 튜닝을 결합하고 싶음 BetterTogether
결합할 유능한 프로그램이 여러 개 Ensemble
에이전트 / 도구 사용 태스크 AvatarOptimizer 또는 GEPA

관련 링크

  • 메트릭과 평가 — 모든 옵티마이저가 거기 정의된 메트릭에 대해 컴파일하고, GEPA가 기대하는 Prediction(score, feedback) 형태도 거기 문서화돼요.
  • GEPA 심화 — 위 옵티마이저의 심화 편이에요.
  • BootstrapFewShot 계열BootstrapFewShot와 그 무작위 탐색 변형들의 심화 편이에요.
  • BootstrapFinetune 미세조정 — 가중치 튜닝 심화 편이에요.