시그니처 확장하기: 입력 추가와 타입 지정
시그니처 확장하기: 입력 추가와 타입 지정 (Expanding your signature)
시그니처는 필드를 추가할수록 점점 더 유연한 작업 정의가 돼요. 이 강의에서는 입력·출력을 늘리고, 필드에 타입을 지정하면서 프로그램을 더 정밀하게 다듬는 방법을 배워볼게요.
출처: 문서
본문
입력·출력 추가하기
시그니처 문자열에 필드를 추가하는 것은 필드 이름을 쉼표로 구분하기만 하면 돼요. 예를 들어 프로그램을 업데이트해서 location 과 mood 두 개의 입력을 받게 해 볼게요:
haiku_bot = dspy.Predict("location, mood -> haiku")
result = haiku_bot(location="a quiet library", mood="mysterious")
print(result.haiku)
이것은 다음과 같이 나옵니다:
Books whisper in hush
Ink curls in soft dim corners
Night reads in quiet
추가 출력을 정의하는 것도 똑같이 동작해요:
haiku_bot = dspy.Predict("location, mood -> haiku, haiku_title")
result = haiku_bot(location="a quiet library", mood="mysterious")
print(result.haiku_title)
print("- - -")
print(result.haiku)
결과:
Where the Pages Breath
- - -
Books whisper in hush
Ink curls in soft dim corners
Night reads in quiet
필드 이름을 신중하게 지어 시그니처 다듬기
우리가 고르는 필드 이름은 단지 우리가 읽기 편하라고 있는 게 아니에요. 전통적인 프로그래밍에서 변수 이름이 순수한 식별자일 뿐인 것과 달리, LM도 그 이름을 읽고 각 입력·출력이 무엇을 뜻하는지 유추하는 데 사용합니다.
"location, mood -> haiku" 대신 "a, b -> c" 를 쓰면 LM은 길을 잃어요. 직접 시험해 볼게요:
haiku_bot = dspy.Predict("a, b -> c")
result = haiku_bot(a="a quiet library", b="mysterious")
print(result.c)
이 코드는 다음과 같이 만들어 냅니다:
In the quiet library, a mysterious presence seemed to linger between the shelves, as if it had been waiting for someone to notice.
우리 모델은 하이쿠를 원한다는 걸 모르니 그냥 추측만 할 뿐이에요.
이름 짓기는 DSPy에서 가장 싼 최적화입니다. request 라는 필드보다 research_request 라는 필드가 다른 변경 없이도 더 나은 완성 결과를 만들어 냅니다. 시그니처는 편집하기 쉬우니 그 장점을 적극 활용하세요.
필드에 타입을 지정하면 더 신뢰할 수 있는 프로그램이 됩니다
name: type 형식으로 필드에 타입(typing) 을 지정하면 작업에 더 많은 구체성을 더할 수 있어요. 예를 들어 "location, mood, contains_pun: bool -> haiku" 시그니처는 우리 시(詩)에 말장난(pun)을 포함할지를 나타내는 불리언을 받습니다:
haiku_bot = dspy.Predict("location, mood, contains_pun: bool -> haiku")
result = haiku_bot(location="a quiet library", mood="mysterious", contains_pun=True)
print(result.haiku)
결과:
Dusty hush of books
Spine turns to hush of riddles
Novel jokes echo
인라인 타입은 DSPy가 LM의 출력을 우리가 요청한 타입으로 강제 변환(coerce) 하도록 지시하고, 변환이 불가능할 때는 명확한 경고를 표시하게 해 줍니다. 이렇게 하면 프롬프트만 쓰는 시스템이 숨겨 왔던 한 부류의 조용한 실패를 잡아낼 수 있어요.
타입은 자연어보다 코드로 표현하기 쉬운 구조적 세부 정보를 전달할 수 있게도 해 줍니다. 더 풍부한 타입 — 예를 들어 Pydantic 모델, TypedDict, dataclasses 같은 것들 — 은 LM이 작업을 제대로 완료하도록 돕는 많은 세부 정보를 담을 수 있어요.
이것은 특히 출력 필드에 타입을 지정할 때 유용합니다. 예를 들어 프로그램을 수정해 하이쿠를 여러 개 생성하도록 하려면 출력 필드 이름을 복수형으로 만들고 list[str] 로 타입을 지정할 수 있어요:
haiku_bot = dspy.Predict("location, mood -> haikus:list[str]")
result = haiku_bot(location="a sunny beach", mood="relaxed")
print(f"Generated {len(result.haikus)} haikus, here's the first:")
print(result.haikus[0])
결과:
Generated 3 haikus, here's the first:
Sun on sandy toes,
waves breathe slow, worries drift away—
soft light, easy air.
프로그램에 필드가 여럿 쌓이거나 더 세밀한 지시문을 추가하고 싶어지면, 이제 클래스 기반 시그니처(class-based signature) 로 전환할 때가 된 거예요.
다음: 클래스 기반 시그니처 →