프롬프트 템플릿을 활용한 대형 언어 모델과의 효과적인 상호 작용 방법과 파이썬 실습 예제

GoGoComputer·2024년 10월 2일
0

LangChain Basics

목록 보기
6/40

이 강의는 대형 언어 모델(LLM)과의 상호 작용에서 프롬프트 템플릿이 왜 중요한지, 그리고 어떻게 사용하는지에 대해 다루고 있습니다. 특히 LangChain 라이브러리와 OpenAI의 모델을 활용하는 방법을 예시로 설명하겠습니다.


1. 프롬프트 템플릿이란 무엇인가요?

프롬프트 템플릿은 LLM에 변수를 전달할 때 더 체계적이고 유연한 방법을 제공합니다. 기존에는 문자열 또는 문자열 목록을 사용하고, 파이썬의 f-문자열이나 format() 메서드를 이용해 변수를 직접 삽입하곤 했습니다. 하지만 이 방법은 코드가 복잡해지고 유지보수가 어려워질 수 있습니다.

프롬프트 템플릿을 사용하면 변수를 템플릿 내에 명시적으로 정의하고, 나중에 값을 전달하여 프롬프트를 생성할 수 있습니다. 이는 코드의 가독성과 재사용성을 높여주며, 특히 복잡한 프롬프트를 다룰 때 유용합니다.


2. 텍스트 완성 모델을 위한 프롬프트 템플릿 만들기

2.1 기본적인 LLM 호출 방법

먼저, LLM을 사용하여 간단한 사실을 출력하는 예시를 보겠습니다.

from langchain.llms import OpenAI

llm = OpenAI(temperature=0.9)
text = "화성에 대한 사실을 말해줘"
print(llm(text))

이 코드는 OpenAI의 LLM을 사용하여 "화성에 대한 사실을 말해줘"라는 프롬프트에 대한 응답을 출력합니다.

2.2 f-문자열을 이용한 변수 삽입

만약 다른 행성에 대한 사실을 알고 싶다면, f-문자열을 사용하여 코드를 수정할 수 있습니다.

planet = "금성"
text = f"{planet}에 대한 사실을 말해줘"
print(llm(text))

하지만 이 방법은 코드의 재사용성이 떨어지고, 변수 관리가 어려울 수 있습니다.

2.3 프롬프트 템플릿으로 개선하기

프롬프트 템플릿을 사용하면 이러한 문제를 해결할 수 있습니다.

from langchain.prompts import PromptTemplate

prompt = PromptTemplate(
    input_variables=["planet"],
    template="{planet}에 대한 사실을 말해줘"
)

formatted_prompt = prompt.format(planet="금성")
print(llm(formatted_prompt))

여기서 PromptTemplate을 사용하여 planet이라는 입력 변수를 정의하고, 나중에 format() 메서드를 통해 값을 전달합니다.

2.4 여러 입력 변수를 가진 템플릿 만들기

프롬프트 템플릿은 여러 입력 변수를 가질 수도 있습니다.

prompt = PromptTemplate(
    input_variables=["topic", "grade_level"],
    template="{grade_level} 수준에서 {topic}에 대한 사실을 말해줘"
)

formatted_prompt = prompt.format(topic="바다", grade_level="대학")
print(llm(formatted_prompt))

이렇게 하면 보다 복잡한 프롬프트를 유연하게 생성할 수 있습니다.


3. 채팅 모델을 위한 프롬프트 템플릿 만들기

이제 채팅 모델에서 프롬프트 템플릿을 사용하는 방법을 알아보겠습니다. 채팅 모델은 시스템 메시지, 사용자 메시지, AI 메시지 등의 다양한 메시지 유형을 다루기 때문에, 프롬프트 템플릿이 더욱 유용합니다.

3.1 필요한 모듈 가져오기

from langchain.prompts import (
    ChatPromptTemplate,
    SystemMessagePromptTemplate,
    HumanMessagePromptTemplate
)
from langchain.schema import AIMessage, HumanMessage, SystemMessage

3.2 시스템 메시지 템플릿 만들기

예를 들어, 요리 조언을 해주는 AI 어시스턴트를 만들고 싶다고 가정해봅시다.

system_template = (
    "당신은 {dietary_preference} 식단에 전문적인 요리 어시스턴트입니다. "
    "{cooking_time} 안에 만들 수 있는 요리를 추천해주세요."
)

system_message_prompt = SystemMessagePromptTemplate.from_template(system_template)

여기서 dietary_preferencecooking_time이라는 입력 변수를 정의했습니다.

3.3 사용자 메시지 템플릿 만들기

사용자의 요청을 받을 템플릿을 만듭니다.

human_template = "{user_request}"

human_message_prompt = HumanMessagePromptTemplate.from_template(human_template)

user_request라는 입력 변수를 사용하여 사용자의 요청을 받습니다.

3.4 채팅 프롬프트 템플릿 조합하기

이제 시스템 메시지와 사용자 메시지를 조합하여 채팅 프롬프트 템플릿을 만듭니다.

chat_prompt = ChatPromptTemplate.from_messages([system_message_prompt, human_message_prompt])

3.5 입력 변수 확인하기

프롬프트 템플릿에서 필요한 입력 변수를 확인할 수 있습니다.

print(chat_prompt.input_variables)
# 출력: ['dietary_preference', 'cooking_time', 'user_request']

3.6 프롬프트 포맷팅 및 모델 호출

이제 실제 값을 전달하여 프롬프트를 생성하고, 모델에 전달할 수 있습니다.

formatted_prompt = chat_prompt.format_prompt(
    dietary_preference="채식",
    cooking_time="30분",
    user_request="간단한 저녁 요리 추천해주세요."
)

messages = formatted_prompt.to_messages()
response = llm(messages)
print(response.content)

4. 요약 및 정리

오늘은 프롬프트 템플릿을 사용하여 LLM과 상호 작용하는 방법에 대해 알아보았습니다.

  • 프롬프트 템플릿의 장점: 변수 관리가 용이하고, 코드의 재사용성과 가독성을 높여줍니다.
  • 텍스트 완성 모델에서의 사용: PromptTemplate을 사용하여 입력 변수를 정의하고, format() 메서드로 값을 전달합니다.
  • 채팅 모델에서의 사용: 시스템 메시지와 사용자 메시지를 위한 템플릿을 만들고, 이를 조합하여 ChatPromptTemplate을 생성합니다.
  • 입력 변수 관리: input_variables를 통해 필요한 입력 변수를 쉽게 파악할 수 있습니다.

프롬프트 템플릿은 복잡한 프롬프트를 관리하고, 다양한 상황에 유연하게 대응할 수 있도록 도와주는 강력한 도구입니다. 앞으로 LLM을 활용한 애플리케이션을 개발하실 때 큰 도움이 될 것입니다.


추가 팁

  • 저장 및 재사용: 프롬프트 템플릿을 파일로 저장하고 나중에 불러올 수 있습니다. 이는 팀 작업이나 프로젝트 규모가 커질 때 유용합니다.
  • 복잡한 프롬프트 구성: 프롬프트 템플릿은 중첩되거나 다른 템플릿과 조합될 수 있어, 매우 복잡한 프롬프트도 관리할 수 있습니다.
  • 디버깅 용이성: 입력 변수를 명시적으로 관리하기 때문에, 예상치 못한 오류를 줄이고 디버깅을 쉽게 할 수 있습니다.

이상으로 프롬프트 템플릿에 대한 자세한 설명을 마치겠습니다. 도움이 되셨길 바랍니다!

실습

위의 내용을 바탕으로, 작동 가능한 파이썬 코드를 작성해드리겠습니다. 이 코드는 OpenAI API 키를 .env 파일로부터 불러오며, langchain 라이브러리를 사용하여 프롬프트 템플릿을 활용하는 예시를 보여줍니다.

먼저 필요한 라이브러리를 설치해야 합니다:

pip install openai langchain python-dotenv

.env 파일에 OpenAI API 키를 다음과 같이 설정해 주세요:

OPENAI_API_KEY=your-api-key-here

이제 코드를 살펴보겠습니다.

import os
from dotenv import load_dotenv

# .env 파일에서 API 키를 불러옵니다.
load_dotenv()
openai_api_key = os.getenv("OPENAI_API_KEY")

# 필요한 모듈을 임포트합니다.
from langchain.llms import OpenAI
from langchain.chat_models import ChatOpenAI
from langchain.prompts import (
    PromptTemplate,
    ChatPromptTemplate,
    SystemMessagePromptTemplate,
    HumanMessagePromptTemplate
)
from langchain.schema import AIMessage, HumanMessage, SystemMessage

# 텍스트 완성 모델을 초기화합니다.
llm = OpenAI(temperature=0.9, openai_api_key=openai_api_key)

# 채팅 모델을 초기화합니다.
chat_model = ChatOpenAI(temperature=0.9, openai_api_key=openai_api_key)

# --- 1. 텍스트 완성 모델에서 프롬프트 템플릿 사용 ---

# 1.1 단일 입력 변수를 가진 프롬프트 템플릿 생성
single_input_prompt = PromptTemplate(
    input_variables=["planet"],
    template="{planet}에 대한 사실을 말해줘"
)

# 프롬프트를 포맷하고 모델에 전달합니다.
formatted_prompt = single_input_prompt.format(planet="금성")
print("금성에 대한 사실:")
print(llm(formatted_prompt))
print("-" * 50)

# 1.2 여러 입력 변수를 가진 프롬프트 템플릿 생성
multi_input_prompt = PromptTemplate(
    input_variables=["topic", "grade_level"],
    template="{grade_level} 수준에서 {topic}에 대한 사실을 말해줘"
)

# 프롬프트를 포맷하고 모델에 전달합니다.
formatted_prompt = multi_input_prompt.format(topic="바다", grade_level="고등학교")
print("고등학교 수준에서 바다에 대한 사실:")
print(llm(formatted_prompt))
print("-" * 50)

# --- 2. 채팅 모델에서 프롬프트 템플릿 사용 ---

# 2.1 시스템 메시지 템플릿 생성
system_template = (
    "당신은 {dietary_preference} 식단에 전문적인 요리 어시스턴트입니다. "
    "{cooking_time} 안에 만들 수 있는 요리를 추천해주세요."
)
system_message_prompt = SystemMessagePromptTemplate.from_template(system_template)

# 2.2 사용자 메시지 템플릿 생성
human_template = "{user_request}"
human_message_prompt = HumanMessagePromptTemplate.from_template(human_template)

# 2.3 채팅 프롬프트 템플릿 생성
chat_prompt = ChatPromptTemplate.from_messages([system_message_prompt, human_message_prompt])

# 2.4 필요한 입력 변수 확인
print("필요한 입력 변수:", chat_prompt.input_variables)
print("-" * 50)

# 2.5 프롬프트를 포맷하고 모델에 전달
formatted_prompt = chat_prompt.format_prompt(
    dietary_preference="채식",
    cooking_time="30분",
    user_request="간단한 저녁 요리 추천해주세요."
)

# 메시지로 변환
messages = formatted_prompt.to_messages()

# 모델에 메시지 전달하고 응답 출력
response = chat_model(messages)
print("AI 어시스턴트의 추천:")
print(response.content)

코드 설명

  • 환경 변수 로드: .env 파일에서 OPENAI_API_KEY를 불러옵니다.
  • 모델 초기화: OpenAIChatOpenAI를 사용하여 텍스트 완성 모델과 채팅 모델을 초기화합니다.
  • 프롬프트 템플릿 생성:
    • 텍스트 완성 모델용 PromptTemplate을 생성하여 단일 및 다중 입력 변수를 활용합니다.
    • 채팅 모델용 SystemMessagePromptTemplateHumanMessagePromptTemplate을 생성합니다.
  • 프롬프트 포맷팅 및 모델 호출:
    • format() 또는 format_prompt() 메서드를 사용하여 실제 값을 입력 변수에 전달합니다.
    • 텍스트 완성 모델에는 포맷된 문자열을 직접 전달하고, 채팅 모델에는 메시지 객체 목록을 전달합니다.

출력 예시

프로그램을 실행하면 다음과 같은 결과를 얻을 수 있습니다.

금성에 대한 사실:
금성은 태양계에서 두 번째 행성이며, 지구와 가장 비슷한 크기와 질량을 가지고 있습니다. 하지만 두꺼운 이산화탄소 대기로 인해 극심한 온실 효과가 발생하여 표면 온도가 평균 464°C에 달합니다. 또한, 금성은 자전 방향이 다른 행성과 반대이며, 자전 주기가 매우 길어 하루가 243 지구일에 해당합니다.
--------------------------------------------------
고등학교 수준에서 바다에 대한 사실:
바다는 지구 표면의 약 71%를 차지하는 거대한 소금물의 집합체로, 태평양, 대서양, 인도양, 남극해, 북극해의 다섯 개의 주요 해양으로 구성되어 있습니다. 바다는 지구의 기후 조절, 탄소 순환, 생물 다양성 유지 등 중요한 역할을 하며, 다양한 해양 생물과 생태계를 포함하고 있습니다.
--------------------------------------------------
필요한 입력 변수: ['dietary_preference', 'cooking_time', 'user_request']
--------------------------------------------------
AI 어시스턴트의 추천:
채식주의자를 위한 30분 이내에 만들 수 있는 간단한 저녁 요리로 '채소 스터프드 파프리카'를 추천합니다.

**재료:**
- 빨간 파프리카 2개
- 양파 1/2개
- 버섯 100g
- 호박 1/2개
- 방울토마토 6개
- 올리브유 2큰술
- 소금과 후추 약간
- 토마토 소스 1/2컵
- 모짜렐라 치즈 (선택사항)

**조리 방법:**
1. 오븐을 180도로 예열합니다.
2. 파프리카는 윗부분을 잘라 씨를 제거합니다.
3. 양파, 버섯, 호박, 방울토마토를 작게 썰어 올리브유에 볶습니다. 소금과 후추로 간을 합니다.
4. 볶은 야채를 파프리카에 채웁니다.
5. 위에 토마토 소스를 뿌리고, 모짜렐라 치즈를 올립니다.
6. 예열된 오븐에서 20분간 구워줍니다.

간단하면서도 영양가 높은 채식 요리입니다. 즐거운 식사 되세요!

추가 정보

  • 환경 설정: .env 파일은 코드와 동일한 디렉토리에 위치해야 합니다.
  • 온도 파라미터: temperature=0.9로 설정하여 생성되는 텍스트의 창의성을 높였습니다.
  • 입력 변수 관리: 프롬프트 템플릿에서 필요한 입력 변수를 input_variables로 쉽게 확인할 수 있습니다.

참고 사항

  • OpenAI의 정책에 따라, 생성되는 텍스트는 항상 동일하지 않을 수 있습니다.
  • 실제로 실행할 때는 자신의 OpenAI API 키를 사용해야 합니다.

이렇게 프롬프트 템플릿을 활용하여 OpenAI의 LLM과 상호 작용하는 방법을 보여드렸습니다. 이 코드가 도움이 되길 바랍니다!

profile
IT를 좋아합니다.

0개의 댓글