DSPy: 취약한 프롬프트 엔지니어링을 컴파일된 LLM 파이프라인으로 대체하기
금융 AI 파이프라인을 생각할 때마다 항상 같은 벽에 부딪히곤 합니다. 테스트 사례에서는 훌륭하게 작동하는 것을 만들 수 있지만, 벤더가 송장 형식을 바꾸거나 새로운 거래 유형이 나타나면 조용히 무너지는 것을 보게 됩니다. 이러한 취약함은 거의 항상 프롬프트, 즉 아무도 건드리고 싶어 하지 않는 수작업으로 작성된 문자열에 있습니다. 스탠포드의 Khattab 등이 소개하고 ICLR 2024에서 발표된 DSPy는 회계 업무 자동화를 시도하는 사람이라면 반드시 주목해야 할, LLM 파이프라인을 구축하는 근본적으로 다른 방식을 제안합니다.
논문 요약
DSPy: Compiling Declarative Language Model Calls into Self-Improving Pipelines (Khattab, Singhvi, Maheshwari 등, ICLR 2024)는 LLM 파이프라인 구축을 프롬프트 엔지니어링 문제가 아닌 프로그래밍 문제로 재정의합니다. 핵심적인 관찰은 현대적인 LLM 애플리케이션이 일반적으로 파이썬 제어 흐름과 결합된 하드코딩된 프롬프트 문자열 — 저자들이 "프롬프트 템플릿"이라 부르는 것 — 의 집합으로 구축된다는 점입니다. 모델이 바뀌거나 작업 분포가 변하면 누군가 그 문자열들을 일일이 손으로 다시 써야 합니다.
DSPy는 프롬프트 템플릿을 *시그니처(signatures)*와 *모듈(modules)*이라는 두 가지 추상화로 대체합니다. 시그니처는 LM 호출이 수행해야 할 작업을 타입화된 선언적 명세로 나타낸 것으로, question -> answer와 같이 간결하게 작성하거나 파이썬 클래스에 명시적인 필드 설명을 포함하여 작성할 수 있습니다. 모듈은 시그니처를 ChainOfThought, ReAct, ProgramOfThought, MultiChainComparison 등과 같은 추론 전략으로 감쌉니다. 결정적인 추가 요소는 컴파일러(논문에서는 텔레프롬프터라고 함)로, DSPy 프로그램, 소규모 레이블링된 데이터셋, 검증 메트릭을 입력받아 퓨샷(few-shot) 시연 사례를 자동으로 생성하고 그중에서 선택하여 해당 메트릭에 최적화된 프롬프트를 생성합니다. 컴파일러는 모든 중간 단계의 레이블을 필요로 하지 않습니다. 레이블이 없는 입력에 대해 티처(teacher) 프로그램을 실행하고 올바른 최종 결과가 나온 트레이스(trace)를 필터링하여 시연 사례를 부트스트랩할 수 있습니다.
핵심 아이디어
- 시그니처는 의도와 구현을 분리합니다.
question, context -> answer라고 작성하는 것만으로 DSPy는 기본 LM 호출을 어떻게 구성, 호출 및 최적화할지 알 수 있습니다. 개발자는 프롬프트 문자열을 전혀 작성하지 않습니다. - 컴파일은 메트릭 기반의 부트스트래핑입니다.
BootstrapFewShot옵티마이저는 훈련 입력에 대해 프로그램을 실행하고, 파이프라인이 성공한 입출력 트레이스를 수집하여 이를 시연 사례로 사용합니다. 중간 추론 단계에 대한 인간의 어노테이션은 필요하지 않습니다. - 컴파일러는 소형 모델의 잠재력을 끌어냅니다. GSM8K(수학 문장제 문제)에서 기본 Llama2-13b는 제로샷 프롬프팅으로 9.4%를 기록했습니다. 리플렉션(reflection) 및 앙상블 모듈을 사용한 DSPy 컴파일 후에는 46.9%에 도달했습니다. 복잡한 추론에는 부적합하다고 여겨졌던 T5-Large(파라미터 7억 7천만 개)는 단 200개의 레이블링된 예시만으로 HotPotQA에서 39.3%의 정답 일치율을 달성했습니다.
- 전문가의 프롬프트가 한계치가 아닙니다. GSM8K에서 기본 퓨샷 프롬프팅을 사용하는 GPT-3.5는 25.2%에 도달합니다. 전문가가 작성한 생각의 사슬(Chain-of-Thought)은 이를 약 72~73%까지 끌어올립니다. DSPy의 컴파일된 리플렉션 및 앙상블 파이프라인은 인간이 프롬프트를 작성하지 않고도 이를 81.6%까지 밀어붙입니다.
- 프로그램은 조합 가능합니다. DSPy의 멀티홉 검색 QA 파이프라인은 약 12줄의 파이썬 코드입니다. 저자들은 랭체인(LangChain)에서 이와 동일한 기능을 하려면 1,000자가 넘는 수작업 프롬프트 문자열 50개가 포함된 다고 언급합니다.
- 세 단계의 컴파일 과정. 옵티마이저는 후보 생성(트레이스 부트스트래핑), 파라미터 최적화(하이퍼파라미터에 대한 랜덤 서치 또는 Optuna), 고차 최적화(앙상블, 동적 제어 흐름) 순으로 작동합니다.
장점과 한계점
실험 결과는 실질적이고 상당합니다. 단 몇 개의 레이블링된 훈련 예시만 사용하여 Llama2-13b로 GSM8K에서 9.4%에서 46.9%로 향상된 것은 점진적인 개선이 아닙니다. 이는 이전에는 GPT-4가 필요했던 작업에 작고 저렴한 모델을 사용할 수 있게 만드는 수준의 차이입니다. 아키텍처 또한 정말 우아합니다. 시그니처는 읽기 쉽고, 모듈은 조합 가능하며, 추상화는 시연된 작업들에 대해 정보 누출(leaky abstraction) 없이 잘 작동합니다.
한계점도 분명하지만, 논문에서는 별도의 섹션에서 이를 다루지 않습니다. 가장 중요한 점은 컴파일러가 여러분의 메트릭만큼만 유능하다는 것입니다. 검증 메트릭이 부정확하거나 실제 작업 품질과 일치하지 않는다면(실무에서 매우 흔한 경우임), 옵티마이저는 여러분이 실제로 중요하게 생각하는 부분에서는 실패하면서 메트릭만 극대화하는 영리한 방법들을 찾아낼 것입니다. 회계와 같은 구조화된 도메인에서는 "전표의 대차가 맞음"과 같은 메트릭을 정의할 수 있지만, 대차가 맞는 전표라도 계정 과목이 완전히 틀릴 수 있습니다. 저자들도 이 문제가 존재한다는 것을 알고 있지만, 이를 개발자의 책임으로 남겨둡니다.
두 번째 한계는 컴파일에 여전히 어느 정도의 레이블링된 데이터가 필요하다는 점입니다. 논문에서는 BootstrapFewShot을 사용하여 단 10개의 예시만으로도 가능하며, 입력값만 필요하고 중간 단계 레이블은 필요 없다고 주장합니다. 이는 최선의 경우에는 사실이지만, 실제로는 시작 프로그램이 훈련 예시를 하나도 해결하지 못할 때 부트스트래핑의 신뢰도가 떨어집니다. 금융 에이전트 파이프라인의 기준 정확도가 거의 0에 가깝다면(새로운 것을 구축할 때 흔히 발생함), 컴파일 과정은 헛바퀴를 돌 수 있습니다.
세 번째이자 더 미묘한 점은 DSPy가 프롬프트와 시연 사례를 최적화하지만, 프로그램 구조 자체를 최적화하지는 않는다는 것입니다. 작업에 근본적으로 잘못된 방식으로 모듈을 연결했다면 컴파일러는 도움이 되지 않습니다. 프로그램 설계는 여전히 개발자의 몫입니다.
금융 AI를 위한 가치
프롬프트의 취약성 문제는 실제 운영 환경에 금융 AI 에이전트를 배치하는 데 있어 아마도 가장 큰 실질적인 장애물일 것입니다. 거래 내역을 계정 과목에 매칭하여 분류하는 파이프라인은 가맹점 데이터 형식이 바뀌거나, 새로운 지출 카테고리가 나타나거나, 계정 체계(Chart of Accounts)가 업데이트될 때마다 성능이 저하될 것입니다. DSPy를 사용하면 작업을 추상적으로 정의하고(transaction_description, chart_of_accounts -> account_code, confidence), 분포가 바뀔 때마다 컴파일러가 최적의 시연 사례를 찾아내도록 할 수 있습니다.
특히 Beancount의 경우, 세 개의 연결된 DSPy 모듈로 구성된 파이프라인을 상상해 볼 수 있습니다. 하나는 원시 은행 내역에서 구조화된 거래 데이터를 추출하고, 하나는 장부의 기존 계정 체계에서 가장 잘 맞는 계정을 조회하며, 마지막 하나는 결과 전표가 복식 부기 제약 조건을 준수하는지 검증하는 모듈입니다. 각 모듈은 고유한 시그니처를 가지며, 전체 프로그램은 회계적 정확성과 형식 준수를 모두 확인하는 메트릭에 따라 컴파일됩니다. 메트릭 품질 문제는 여기서 가장 뼈아프게 다가올 것입니다. 대차 불일치뿐만 아니라 잘못된 계정 과목까지 잡아내는 메트릭이 필요하기 때문입니다. 하지만 이는 해결 가능한 엔지니어링 문제 프로젝트입니다.
더 깊은 함의는 DSPy가 업무의 중심을 "더 나은 프롬프트 작성"에서 "더 나은 메트릭 작성 및 소규모 레이블링 데이터셋 수집"으로 옮긴다는 점입니다. 이는 규제, 계정 체계 구조, 거래 형식이 시간이 지남에 따라 변하는 실제 금융 시스템에 있어 훨씬 더 지속 가능한 엔지니어링 관행입니다.
더 읽어볼 거리
- OPRO: Large Language Models as Optimizers (Yang 등, arXiv:2309.03409) — 반복적인 LM 생성 정제를 통한 프롬프트 최적화에 대한 Google DeepMind의 접근 방식. DSPy의 부트스트래핑 접근 방식에 대한 유용한 대조점입니다.
- TextGrad: Automatic "Differentiation" via Text (Yuksekgonul 등, arXiv:2406.07496) — 최적화를 메 트릭 기반 부트스트래핑이 아닌 텍스트 피드백을 통한 역전파로 프레임화함. DSPy의 방식이 약한 코딩 및 과학적 작업에서 강력한 결과를 보여줍니다.
- DSPy Assertions: Computational Constraints for Self-Refining Language Model Pipelines (Singhvi 등, arXiv:2312.13382) — DSPy 프로그램에 하드 및 소프트 제약 조건을 추가하여 출력이 도메인 규칙을 위반할 때 파이프라인이 스스로 수정할 수 있도록 함. 회계 불변성(invariants)을 강제하는 것과 직접적으로 관련이 있습니다.
