본문 바로가기
Natural Language Processing

[SeSac] LangChain 2 - 프롬프트 (Prompt)

by 자몽먹은토끼 2024. 7. 14.
728x90
반응형

프롬프트 (Prompt)

: 언어모델의 입력으로 사용되는, 질문이나 요청 형태의 지시문

> 틀을 미리 잘 만들어놓으면, 재사용이 가능하고 수정해서 사용하기 편리하다.

 

 

프롬프트 템플릿 (Prompt Template)

 

: 하나의 문장이나 간단한 명령을 입력하여 동일하게 하나의 문장 혹은 간단한 응답을 출력할 때 사용

최종적으로 출력은 문자열 형태를 띈다. 파이썬 문자열 포맷팅을 사용하여 동적으로 특정한 위치에 입력값을 포함시킬 수 있다.

 

from langchain_core.prompts import PromptTemplate

# 'name'과 'age'라는 두 개의 변수를 사용하는 프롬프트 템플릿을 정의
template_text = "안녕하세요, 제 이름은 {name}이고, 나이는 {age}살입니다."

# PromptTemplate 인스턴스를 생성
prompt_template = PromptTemplate.from_template(template_text)

# 템플릿에 값을 채워서 프롬프트를 완성
filled_prompt = prompt_template.format(name="홍길동", age=30)

filled_prompt
# '안녕하세요, 제 이름은 홍길동이고, 나이는 30살입니다.'

> 두개의 변수를 포맷팅

 

 

template_text = "안녕하세요, 제 이름은 {name}이고, 나이는 {age}살입니다."
prompt_template = PromptTemplate.from_template(template_text)

# 문자열 템플릿 결합 (PromptTemplate + PromptTemplate + 문자열)
combined_prompt = (
              prompt_template
              + PromptTemplate.from_template("\n\n아버지를 아버지라 부를 수 없습니다.")
              + "\n\n{language}로 번역해주세요."
)
     
combined_prompt.format(name="홍길동", age=30, language="영어")

combined_prompt
# '안녕하세요, 제 이름은 홍길동이고, 나이는 30살입니다.\n\n아버지를 아버지라 부를 수 없습니다.\n\n영어로 번역해주세요.'

> 템플릿과 템플릿 간의 결합 및 템플릿과 문자열간의 결합

 

그럼 이 완성된 프롬프트를 LLM모델에 전달하고 Outputparser를 거치면 다음과 같다.

from langchain_openai import ChatOpenAI
from langchain_core.output_parsers import StrOutputParser

llm = ChatOpenAI(model="gpt-3.5-turbo-0125")
chain = combined_prompt | llm | StrOutputParser()
chain.invoke({"age":30, "language":"영어", "name":"홍길동"})
# chain.invoke()

# 'Hello, my name is Hong Gildong and I am 30 years old.\n\nI cannot call my father "father."'

 

또 한가지 의문 ❗

어차피 앞에서 변수들을 모두 formatting 했는데 invoke함수에서 재차 format할 필요가 있을까?

임의로 작성한 저 주석으로 사용하면 오류가 나나?

→ 오류가 나는지는 모르겠으나 invoke함수를 이용해서 입력값을 주는건, 랭체인의 재사용성을 위함이다. 😮

→ 만약 invoke함수에 포맷팅을 재정의 하고싶지 않다면, chain.invoke(combined_prompt) 를 넣어주면 된다 🪄

안된다면, 다른 변수에 포맷한 값을 저장하고 그 변수를 invoke함수내에 넣어주면 된다 🪄🪄

 

 

 

 

 

 

챗 프롬프트 템플릿 (Chat Prompt Template)

 

: 대화형 상황에서 여러 개의 메세지(문장/문자열)를 리스트형태로 만들어 LLM모델에 전달

출력은 하나의 출력을 갖는다. 여러 메세지를 원소로 갖는 리스트 입력에서, 각 메세지는 역할(role)과 내용(content)으로 구성된다.

보통 챗봇형태의 개발에 사용된다.

 

Message 유형
  • SystemMessage : 시스템의 기능을 설명. LLM 및 전체 AI 시스템의 역할이나 배경을 지정. role= 'system'
  • HumanMessage : 사용자의 질문을 나타냄. role= 'user'
  • AIMessage : AI 모델의 응답을 제공, 모델의 출력을 제공
  • FunctionMessage : 특정 함수 호출의 결과를 나타냄
  • ToolMessage : 도구 호출의 결과를 나타냄

 

- 첫 번째 버전

# 2-튜플 형태의 메시지 목록으로 프롬프트 생성 (type, content)

from langchain_core.prompts import ChatPromptTemplate

chat_prompt = ChatPromptTemplate.from_messages([
    ("system", "이 시스템은 천문학 질문에 답변할 수 있습니다."),
    ("user", "{user_input}"),
])

messages = chat_prompt.format_messages(user_input="태양계에서 가장 큰 행성은 무엇인가요?")
messages
# [SystemMessage(content='이 시스템은 천문학 질문에 답변할 수 있습니다.'),
#  HumanMessage(content='태양계에서 가장 큰 행성은 무엇인가요?')]

> role과 content를 쌍으로 하여 튜플 형태의 메세지목록으로 프롬프트를 생성한다.

(랭체인을 연결하는 과정은 동일하다. chain연결 코드와 invoke함수 코드만 넣으면 끝)

 

 

- 두 번째 버전

# MessagePromptTemplate 활용

from langchain_core.prompts import SystemMessagePromptTemplate,  HumanMessagePromptTemplate

chat_prompt = ChatPromptTemplate.from_messages(
    [
        SystemMessagePromptTemplate.from_template("이 시스템은 천문학 질문에 답변할 수 있습니다."),
        HumanMessagePromptTemplate.from_template("{user_input}"),
    ]
)

messages = chat_prompt.format_messages(user_input="태양계에서 가장 큰 행성은 무엇인가요?")
messages
# [SystemMessage(content='이 시스템은 천문학 질문에 답변할 수 있습니다.'),
#  HumanMessage(content='태양계에서 가장 큰 행성은 무엇인가요?')]

> 이 버전은 systemmessageprompttemplate과 humanmessageprompttemplate 라이브러리를 사용하여 프롬프트를 생성하는 방법이다.

 

728x90
반응형