DSPy에서의 최적화

DSPy에서의 최적화

시스템을 하나 만들고, 그걸 평가할 방법까지 갖췄다면 이제 마지막 단계가 남아요. 바로 DSPy 옵티마이저로 프로그램 안의 프롬프트나 가중치를 튜닝하는 거죠. 그런데 그 전에, 데이터 수집의 범위를 조금 넓혀둘 필요가 있어요. 지금까지 탐색할 때 써온 개발 셋(development set)에 더해, 훈련 셋(training set)보류된 테스트 셋(held-out test set) 을 따로 쌓아두는 겁니다.

훈련 셋(과 그 부분집합인 검증 셋)은 사실 30개 예시만 있어도 꽤 큰 효과를 볼 수 있어요. 그래도 가능하다면 최소 300개를 목표로 잡는 편이 좋아요. 옵티마이저에 따라 trainset만 받는 것도 있고, trainsetvalset 둘 다 요구하는 것도 있어요.

여기서 재미있는 점이 하나 있어요. 대부분의 프롬프트 옵티마이저에 데이터를 나눌 때는, 딥러닝에서 흔히 쓰던 방식과 거꾸로 된 비율을 권장해요. 훈련에 20%, 검증에 80%를 주는 거예요. 프롬프트 기반 옵티마이저가 작은 훈련 셋에 과적합되기 쉬워서, 검증을 안정적으로 하려면 오히려 검증 셋을 크게 잡는 게 낫기 때문이에요. 반면 dspy.GEPA 같은 옵티마이저는 좀 더 표준적인 ML 관례를 따라요. 훈련 셋을 최대한 키우고, 검증 셋은 다운스트림 태스크(테스트 셋)의 분포를 반영할 만큼만 유지하는 식이죠.

첫 몇 번의 최적화를 돌리고 나면, 크게 두 갈래로 나뉘게 돼요. 모든 게 만족스럽거나, 아니면 꽤 진전이 있긴 한데 최종 프로그램이나 메트릭이 마음에 안 드는 경우죠. 후자라면 1단계(Programming in DSPy)로 돌아가 핵심 질문들을 다시 점검해 봐요.

  • 태스크 정의가 제대로 됐나요?
  • 문제를 풀 데이터를 더 모아야(또는 온라인에서 찾아야) 하나요?
  • 메트릭을 바꿔볼까요?
  • 더 정교한 옵티마이저를 써볼까요?
  • DSPy Assertions 같은 고급 기능도 고려해야 하나요?
  • 그리고 어쩌면 가장 중요하게, 프로그램 자체에 단계나 복잡성을 더 추가하고 싶진 않나요?
  • 옵티마이저 여러 개를 순서대로 써볼까요?

반복적인 개발이 핵심이에요. DSPy는 그걸 점진적으로 할 수 있는 조각들, 즉 데이터·프로그램 구조·메트릭·최적화 단계를 각각 반복할 수 있는 재료를 줘요. 복잡한 LM 프로그램을 최적화하는 건 아주 새로운 패러다임이라서, 무엇을 하는 게 옳은지에 대한 기준도 아직 만들어지고 있는 중이에요(이 글을 쓸 당시엔 DSPy에만 있었는데, 지금은 수많은 DSPy 확장 프레임워크가 생겨서 그 말은 더 이상 사실이 아니네요). 도움이 필요하면 커뮤니티 Discord 서버도 마련돼 있어요.