시그니처 확장하기: 입력·출력 더하고 타입 붙이기

시그니처 확장하기: 입력·출력 더하고 타입 붙이기

시그니처는 콤마로 필드 이름을 구분하기만 하면 얼마든지 확장할 수 있어요. 입력과 출력을 여럿 추가하고, name: type 형식으로 타입을 붙이면 작업의 범위가 훨씬 구체적이고 안정적으로 바뀝니다. 이 페이지는 그 확장 방법을 순서대로 다룹니다.

출처: 공식문서

입력·출력 추가하기

시그니처 문자열에 필드를 더하는 건 필드 이름을 콤마로 구분하기만 하면 돼요. 두 개의 입력 locationmood를 받도록 프로그램을 바꿔 볼게요.

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 형식으로 필드에 타입을 지정하면 작업에 더 구체성을 더할 수 있어요. 예를 들어 "location, mood, contains_pun: bool -> haiku" 시그니처는 시에 말장난(pun)을 넣을지 여부를 나타내는 boolean을 받습니다.

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의 출력을 우리가 요청한 타입으로 강제 변환(코어스)하게 하고, 변환할 수 없을 때 명확한 경고를 표면화해요. 이는 프롬프트만 쓰는 시스템이 숨겨 두는 조용한 실패의 한 부류를 잡아내지요.

타입은 또 자연어보다 코드로 표현하기 쉬운 구조적 세부사항을 전달할 수 있게 해요. 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.

프로그램이 필드를 여럿 쌓기 시작하거나 뉘앙스가 있는 지시를 추가하고 싶다면, 이쯤에서 클래스 기반 시그니처로 올라갈 때입니다.

더 알아보기 (Learn more)