어댑터: 시그니처가 프롬프트가 되는 법

어댑터: 시그니처가 프롬프트가 되는 법 (Adapters: how signatures become prompts)

어댑터(adapter)는 Signature 와 LM 사이의 계층입니다. 시그니처의 지시문·필드·데모를 채팅 메시지로 포맷하고, 호출을 보내며, LM의 응답을 타입이 지정된 Python 값으로 다시 파싱합니다. 서로 다른 어댑터는 서로 다른 프롬프트 모양 — 채팅 마커, JSON, XML, 또는 2단계 추출 — 을 쓰므로, 같은 Signature가 포맷 강도가 크게 다른 모델들에서 실행될 수 있습니다.

출처: 문서

본문

프롬프트가 와이어에서 어떻게 보이는지, 왜 타입 필드가 한 방식으로 파싱되고 다른 방식으로는 안 되는지, [[ ## field_name ## ]] 마커가 어디서 나오는지, 또는 ChatAdapter가 잘못 작동할 때 어떤 어댑터로 전환할지 알고 싶을 때 이 문서를 읽으세요.

설계 결정

1. 어댑터는 플러그 가능(pluggable)하다

같은 Signature, 다른 프롬프트 모양, Signature 변경 없음. LM은 무엇을 읽고 만들기를 선호하는지가 크게 다릅니다. 마커로 지시문-따르기에 훈련된 모델은 ChatAdapter의 [[ ## field ## ]] 형식을 좋아하고, 네이티브 구조화 출력 모드가 있는 모델은 JSONAdapter에서 최선을 내며, 형식을 불안정하게 만드는 추론 모델은 TwoStepAdapter를 원합니다. 이 결정을 하나의 인터페이스 뒤에 두면 Signatures·모듈·최적화기가 어떤 LM 계열을 상대하는지 알 필요가 없습니다.

2. ChatAdapter가 기본값이다

텍스트 전용, 모델 중립, [[ ## field ## ]] 마커 사용. JSON 모드, 함수 호출, 네이티브 구조화 출력 같은 특별한 LM 기능이 필요 없습니다. 그 폭이 기본값인 이유예요. 또한 안전망을 포함합니다. 정규식 파서가 실패하면 자동으로 JSONAdapter로 폴백합니다(use_json_adapter_fallback=False 로 토글).

3. 모든 어댑터는 고정된 수명주기를 따른다

preprocess → format → LM 호출 → postprocess → parse. 이 다섯 단계를 따라가면서 어떤 어댑터든 디버깅할 수 있어요. preprocess는 네이티브 LM 기능(함수 호출, 추론)을 위해 시그니처를 적응시키고, format은 메시지를 만들며, parse는 응답을 시그니처 필드로 다시 파싱합니다.

4. 타입은 어댑터 계층에서 강제 변환된다

시그니처는 주석만 선언하고, 파싱과 타입 강제 변환은 어댑터에서 일어납니다. dspy/adapters/utils.py::parse_value 는 json_repair → ast.literal_eval → TypeAdapter(annotation) 순으로 시도합니다. 상세는 시그니처 심층 탐구를 참고하세요.

5. 도구는 텍스트 또는 네이티브 함수 호출로 전송된다

어댑터는 도구 스키마를 텍스트로 렌더링할지 Tool.format_as_litellm_function_call() 로 공급자 네이티브 형식으로 보낼지 결정합니다. JSONAdapter 는 기본적으로 네이티브 함수 호출을 활성화하고, ChatAdapter 는 use_native_function_calling=True 로 명시 설정해야 합니다. 상세는 도구와 MCP를 참고하세요.

주요 어댑터

  • dspy.ChatAdapter — 기본값. [[ ## field ## ]] 마커로 구조화된 채팅 메시지.
  • dspy.JSONAdapter — 출력을 JSON으로 강제. 네이티브 함수 호출 기본 활성.
  • dspy.XMLAdapter — XML 태그 구조.
  • dspy.TwoStepAdapter — 추출을 두 단계로 나눠 다루는 2단계 추출 접근.

활성 어댑터는 dspy.context(adapter=...) 로 바꿔 켤 수 있습니다:

adapter = dspy.ChatAdapter(use_native_function_calling=True)
with dspy.context(adapter=adapter):
    result = agent(question="...")

더 알아보기 (Learn more)