대화 히스토리 관리하기

대화 히스토리 관리하기 (Managing conversation history)

챗봇 같은 AI 애플리케이션을 만들 때 대화 히스토리를 유지하는 것은 기본적인 기능입니다. DSPy는 dspy.Module 안에서 대화 히스토리를 자동 관리하지 않지만, dspy.History 유틸리티를 제공해 대화 히스토리를 효과적으로 관리하게 도와줍니다.

출처: 문서

본문

dspy.History 로 대화 히스토리 관리하기

dspy.History 클래스는 입력 필드 타입으로 쓸 수 있고, 대화 히스토리를 저장하는 messages: list[dict[str, Any]] 속성을 지닙니다. 이 리스트의 각 항목은 당신의 시그니처에 정의된 필드에 대응하는 키를 가진 사전입니다. 아래 예시를 보세요:

import dspy
import os

os.environ["OPENAI_API_KEY"] = "{your_openai_api_key}"

dspy.configure(lm=dspy.LM("openai/gpt-4o-mini"))

class QA(dspy.Signature):
    question: str = dspy.InputField()
    history: dspy.History = dspy.InputField()
    answer: str = dspy.OutputField()

predict = dspy.Predict(QA)
history = dspy.History(messages=[])

while True:
    question = input("Type your question, end conversation by typing 'finish': ")
    if question == "finish":
        break
    outputs = predict(question=question, history=history)
    print(f"\n{outputs.answer}\n")
    history.messages.append({"question": question, **outputs})

dspy.inspect_history()

대화 히스토리를 쓸 때 두 가지 핵심 단계가 있어요:

  • 시그니처에 dspy.History 타입의 필드를 포함합니다.
  • 런타임에 history 인스턴스를 유지하고, 새 대화 턴을 그것에 추가합니다. 각 항목은 관련된 모든 입력·출력 필드 정보를 포함해야 합니다.

실행 예시는 이렇게 생겼습니다:

Type your question, end conversation by typing 'finish': do you know the competition between pytorch and tensorflow?

Yes, there is a notable competition between PyTorch and TensorFlow, which are two of the most popular deep learning frameworks. ...

Type your question, end conversation by typing 'finish': which one won the battle? just tell me the result, don't include any reasoning, thanks!

There is no definitive winner; both PyTorch and TensorFlow are widely used and have their own strengths.
Type your question, end conversation by typing 'finish': finish

각 사용자 입력과 어시스턴트 응답이 히스토리에 추가되어, 모델이 턴을 넘어 맥락을 유지하게 되는 것을 볼 수 있어요.

언어 모델에게 실제로 보내는 프롬프트는 dspy.inspect_history 출력에서 보이듯 다중 턴 메시지입니다. 각 대화 턴이 사용자 메시지 뒤에 어시스턴트 메시지로 표현됩니다.

Few-shot 예시에서의 히스토리

히스토리가 입력 필드로 나열되었음에도(시스템 메시지의 "2. history (History):") 프롬프트의 입력 필드 섹션에 나타나지 않는다는 점을 눈치챘을 거예요. 이것은 의도적입니다. 대화 히스토리를 포함하는 few-shot 예시를 포맷할 때 DSPy는 히스토리를 여러 턴으로 확장하지 않습니다. 대신 OpenAI 표준 형식과의 호환성을 위해 각 few-shot 예시를 단일 턴으로 표현합니다.

예를 들어:

import dspy

dspy.configure(lm=dspy.LM("openai/gpt-4o-mini"))


class QA(dspy.Signature):
    question: str = dspy.InputField()
    history: dspy.History = dspy.InputField()
    answer: str = dspy.OutputField()


predict = dspy.Predict(QA)
history = dspy.History(messages=[])

predict.demos.append(
    dspy.Example(
        question="What is the capital of France?",
        history=dspy.History(
            messages=[{"question": "What is the capital of Germany?", "answer": "The capital of Germany is Berlin."}]
        ),
        answer="The capital of France is Paris.",
    )
)

predict(question="What is the capital of America?", history=dspy.History(messages=[]))
dspy.inspect_history()

보시다시피, few-shot 예시는 대화 히스토리를 여러 턴으로 확장하지 않고 자기 섹션 안의 JSON 데이터로 표현합니다:

[[ ## history ## ]]
{"messages": [{"question": "What is the capital of Germany?", "answer": "The capital of Germany is Berlin."}]}

이 접근은 표준 프롬프트 형식과의 호환성을 보장하면서도, 모델에게 관련된 대화 맥락을 제공합니다.

더 알아보기 (Learn more)