첫 번째 DSPy 프로그램 작성하기

첫 번째 DSPy 프로그램 작성하기 (Writing our first DSPy program)

이번 강의에서는 하이쿠 생성 프로그램을 만들 거예요. 각 섹션마다 프로그램을 확장해 가면서 DSPy의 새로운 개념과 기능을 하나씩 소개할게요. 먼저 프로그램의 가장 간단한 버전을 작성해서 실행해 본 뒤, DSPy가 뒤에서 실제로 하는 일을 차근차근 살펴볼게요.

출처: 문서

본문

haiku_signature = "subject -> haiku"
haiku_generator = dspy.Predict(haiku_signature)

result = haiku_generator(subject="computer science")
print(result.haiku)

첫 번째 줄은 우리의 Signature (시그니처) 를 지정해요. Signature는 DSPy의 핵심 개념으로, 우리가 하려는 작업을 정의하는 방법이에요. 프로그래밍의 함수 시그니처와 비슷하게, DSPy Signature는 함수가 받아들이는 입력과 반환하는 출력을 기술합니다.

DSPy Signature를 정의하는 가장 간단한 방법은 "inputs -> outputs" 형태의 문자열을 쓰는 거예요. 우리 경우에는 subject를 제공하고 haiku를 돌려받고 싶습니다.

언어 모델로 프로그래밍하기 때문에 변수 이름이 중요해요. 변수 이름은 프로그램의 인터페이스를 정의하는 동시에 모델에게 우리의 의도를 알려 주는 힌트가 됩니다. haiku를 limerick으로 바꾸면 모델이 그 신호를 알아차리고 대신 limerick(라임을 맞춘 짧은 시)을 만듭니다. 또한 프로그램의 출력도 result.haiku 대신 result.limerick으로 접근할 수 있게 돼요.

Predict 모듈

Signature를 호출 가능한 함수로 바꾸려면 dspy.Predict 를 사용합니다. Predict는 일종의 DSPy Module 이에요. Signature가 무엇을 원하는지 지정한다면, Module은 어떻게 그 목표를 달성할지를 정의합니다. Module은 호출 시점의 전략을 구현하고 제어 흐름, 도구 등을 관리해요.

Predict는 가장 기초적인(foundational) Module입니다. dspy.Predict(haiku_signature) 를 호출하면 어떤 일이 일어나는지 볼게요:

  1. "subject -> haiku" 문자열이 Signature 클래스로 파싱되고, 입출력 필드는 기본적으로 str 타입이 돼요.
  2. Signature 인스턴스를 위한 기본 지시 문자열(instruction) 이 생성돼요. 이 경우에는 "Given the fields subject, produce the fields haiku." 입니다.
  3. 이 Signature로 Predict 모듈이 인스턴스화됩니다.

이제 haiku_generator는 호출 가능해졌어요. haiku_generator(subject="computer science") 를 호출하면 다음 과정이 시작됩니다:

  1. DSPy 설정을 확인해서 LM이 구성되어 있는지 검사합니다.
  2. Adapter를 사용해 Signature와 그 입력을 LM이 소비할 수 있는 메시지로 렌더링해요. 기본값은 ChatAdapter이지만, JSON, XML 등 다양한 변형이 있어 특정 LM에 맞춰 메시지를 포맷할 수 있습니다.
  3. ChatAdapter가 프롬프트를 구성하는데, 여기에는 Signature 지시문, 입력·출력을 설명하는 필드 스키마, 포맷 지침, 그리고 제공된 입력(이 경우 "computer science")이 포함돼요.
  4. 메시지를 LM으로 보냅니다. 캐싱이 기본적으로 활성화되어 있어 동일한 호출은 캐시된 응답을 반환해요.
  5. 응답이 반환되면 ChatAdapter가 이를 파싱해 출력 필드를 추출합니다.
  6. Predict 모듈은 접근 가능한 출력 필드를 가진 Prediction 객체를 반환해요. result.haiku 를 호출하면 생성된 하이쿠가 나옵니다.
  7. 이 호출은 LM 히스토리에 기록되는데, 나중에 dspy.inspect_history() 로 확인할 수 있어요.

print(result.haiku) 를 실행하면 다음과 같이 나옵니다:

Silent code unfolds
Logic threads through hidden paths
Bugs bloom, then resolve

불과 네 줄로 소프트웨어처럼 읽히고 함수처럼 동작하는 AI 기반 프로그램을 만들었어요.

DSPy가 만든 프롬프트 들여다보기

DSPy는 프롬프트 작성과 템플릿 작업을 전부 관리해 줍니다. dspy.inspect_history(n=1) 을 호출하면 우리 프로그램이 만든 포맷된 프롬프트와 lm이 반환한 문자열을 확인할 수 있어요.

먼저 DSPy가 시스템 지시문을 생성했어요:

Your input fields are:
1. `subject` (str):
Your output fields are:
1. `haiku` (str):
All interactions will be structured in the following way, with the appropriate values filled in.

[[ ## subject ## ]]
{subject}

[[ ## haiku ## ]]
{haiku}

[[ ## completed ## ]]
In adhering to this structure, your objective is: 
    Given the fields `subject`, produce the fields `haiku`.

이 대괄호와 해시 스타일은 기본 ChatAdapter가 프롬프트를 구조화하는 방식으로, 입력과 섹션을 구분 지어 줍니다.

다음으로, 어댑터가 우리 입력을 유저 메시지로 템플릿 처리했어요:

[[ ## subject ## ]]
computer science

Respond with the corresponding output fields, starting with the field `[[ ## haiku ## ]]`, and then ending with the marker for `[[ ## completed ## ]]`.

DSPy는 이 둘을 모두 lm에 보냈고, lm은 다음과 같은 응답을 만들었습니다:

[[ ## haiku ## ]]
Silent code unfolds
Logic threads through hidden paths
Bugs bloom, then resolve

[[ ## completed ## ]]

DSPy에서는 시그니처를 조합하면 메시지는 알아서 작성됩니다.

다음: 시그니처 확장하기 →

더 알아보기 (Learn more)