방법 1 from-template() 메소드 사용해 PromptTemplate 객체 생성
치환될 변수를 {}로 묶어서 템플릿 정의=
from langchain_core.prompts import PromptTemplate
# template 정의. {country}는 변수로, 이후에 값이 들어갈 자리를 의미
template = "{country}의 수도는 어디인가요?"
# from_template 메소드를 이용하여 PromptTemplate 객체 생성
prompt = PromptTemplate.from_template(template)
prompt
PromptTemplate(input_variables=['country'], input_types={}, partial_variables={}, template='{country}의 수도는 어디인가요?')
변수 대한민국으로 넣어보기
prompt.format
# format으로 변수 입력하고 prompt 출력시 제대로 나옴
prompt = prompt.format(country="대한민국")
prompt
'대한민국의 수도는 어디인가요?'
다시 보면!##
template 만들고
prompt 만들고
chain 만들어서 invoke (딕셔너리형태가 정석인데 변수가 1개면 key값만 입력 가능)
# template 정의
template = "{country}의 수도는 어디인가요?"
# from_template 메소드를 이용하여 PromptTemplate 객체 생성
prompt = PromptTemplate.from_template(template)
# chain 생성
chain = prompt | llm
# country 변수에 입력된 값이 자동으로 치환되어 수행됨
# 아래처럼 딕셔너리 형식이 정석임
# chain.invoke({"country":"대한민국"}).content
chain.invoke("대한민국").content
'대한민국의 수도는 서울입니다.'
방법 2 PromptTemplate 객체 생성과 prompt 동시에 생성
유효성 검사를 위해 input_variables를 명시적으로 지정
# template 정의
template = "{country}의 수도는 어디인가요?"
# PromptTemplate 객체를 활용하여 prompt_template 생성
# 여태까지랑 다른 방식
# 직관적인 스타일
prompt = PromptTemplate(
template=template,
input_variables=["country"],
)
prompt
PromptTemplate(input_variables=['country'], input_types={}, partial_variables={}, template='{country}의 수도는 어디인가요?')
# prompt 생성
prompt.format(country="대한민국")
'대한민국의 수도는 어디인가요?'
partial_variables
변수 2개 이상
country2 미국임
# template 정의
# partial_variables 입력받아야 할 변수가 2개 이상일 때 중간과정에서 변수가 확정될 때
template = "{country1}과 {country2}의 수도는 각각 어디인가요?"
# PromptTemplate 객체를 활용하여 prompt_template 생성
prompt = PromptTemplate(
template=template,
input_variables=["country1"],
partial_variables={
"country2": "미국" # dictionary 형태로 partial_variables를 전달
},
)
prompt
PromptTemplate(input_variables=['country1'], input_types={}, partial_variables={'country2': '미국'}, template='{country1}과 {country2}의 수도는 각각 어디인가요?')
country1에 대한민국 넣어서
prompt 확인하면 대한민국, 미국 뜸
prompt.format(country1="대한민국")
'대한민국과 미국의 수도는 각각 어디인가요?'
partial_variables
partial : 함수를 부분적으로 사용
아래 예시는 항상 공통된 방식으로 가져오고 싶은 변수가 있음
ex) 날짜, 시간
결괏값이 function -> 아직 호출되지 않은 것임
get today 함수가 있고 오늘 날짜 알아서 받아올 것이고
n도 아직 안 들어가서 호출 안됨
# 매개변수 받을 필요 없음
# strtime 아니고 strftime임!
def get_today():
return datetime.now().strftime("%B %d")
prompt = PromptTemplate(
template="오늘의 날짜는 {today}입니다. 오늘이 생일인 유명인 {n}명을을 나열해 주세요. 생년월일을 표기해주세요.",
input_variables=["n"],
partial_variables={
"today": get_today
},
)
prompt
PromptTemplate(input_variables=['n'], input_types={}, partial_variables={'today': <function get_today at 0x000001E6FD260040>}, template='오늘의 날짜는 {today}입니다. 오늘이 생일인 유명인 {n}명을을 나열해 주세요. 생년월일을 표기해주세요.')
prompt 3으로 format
prompt.format(n=3)
'오늘의 날짜는 January 26입니다. 오늘이 생일인 유명인 3명을을 나열해 주세요. 생년월일을 표기해주세요.'
chain 생성 후 invoke 실행
# chain 을 생성합니다.
chain = prompt | ChatOpenAI(model_name="gpt-4o", temperature=0)
# chain 을 실행 후 결과를 확인합니다.
#
print(chain.invoke(3).content)
파일로 template 읽어오기
파일이 길어지면? 파일로 불러올 수 있음
파일형식 : yaml
인코딩 설정 해야지 오류 안 뜸
예시 1
# 프롬프트가 길어진다면? 파일로 불러오기
from langchain_core.prompts import load_prompt
prompt = load_prompt("prompts/fruit_color.yaml", encoding="utf-8")
prompt
PromptTemplate(input_variables=['fruit'], input_types={}, partial_variables={}, template='{fruit}의 색깔이 뭐야?')
예시 2
# 조금 더 긴 prompt
# encoding="utf-8" 이거 넣어줘야 함
prompt2 = load_prompt("prompts/capital.yaml", encoding="utf-8")
print(prompt2.format(country="대한민국"))
대한민국의 수도에 대해서 알려주세요.
수도의 특징을 다음의 양식에 맞게 정리해 주세요.
300자 내외로 작성해 주세요.
한글로 작성해 주세요.
----
[양식]
1. 면적
2. 인구
3. 역사적 장소
4. 특산품
#Answer:
ChatPromptTemplate
대화형식으로 프롬프트 주입
튜플 형식(role, message) 구성
system
human : 사용자의 입력값
ai : 출력값
# PromptTemplate이 아닌 Chat이 붙어있음
# 메세지에 HumanMessagePromptTemplate로 한 번 감싸져짐
from langchain_core.prompts import ChatPromptTemplate
chat_prompt = ChatPromptTemplate.from_template("{country}의 수도는 어디인가요?")
chat_prompt
ChatPromptTemplate(input_variables=['country'], input_types={}, partial_variables={}, messages=[HumanMessagePromptTemplate(prompt=PromptTemplate(input_variables=['country'], input_types={}, partial_variables={}, template='{country}의 수도는 어디인가요?'), additional_kwargs={})])
Human
# content가 아니라 Human으로 나옴
# role과 메세지가 있음
# human 우리가 입력한 입력값
# 답변 ai의 답변 메세지
chat_prompt.format(country="대한민국")
'Human: 대한민국의 수도는 어디인가요?'
from_message에서 튜플로 넣는데 한 번 대괄호로 묶어야 함
template은 from_message()
messages 생성은 format_messages()
from langchain_core.prompts import ChatPromptTemplate
# 메세지는 tuple 형식임
# role은 system, human, ai 중 하나 넣어야 함
chat_template = ChatPromptTemplate.from_messages(
[
# role, message
("system", "당신은 친절한 AI 어시스턴트입니다. 당신의 이름은 {name} 입니다."),
("human", "반가워요!"),
("ai", "안녕하세요! 무엇을 도와드릴까요?"),
("human", "{user_input}"),
]
)
# 챗 message 를 생성합니다.
messages = chat_template.format_messages(
name="테디", user_input="당신의 이름은 무엇입니까?"
)
messages
[SystemMessage(content='당신은 친절한 AI 어시스턴트입니다. 당신의 이름은 테디 입니다.', additional_kwargs={}, response_metadata={}),
HumanMessage(content='반가워요!', additional_kwargs={}, response_metadata={}),
AIMessage(content='안녕하세요! 무엇을 도와드릴까요?', additional_kwargs={}, response_metadata={}),
HumanMessage(content='당신의 이름은 무엇입니까?', additional_kwargs={}, response_metadata={})]
llm.invoke(messages).content
'제 이름은 테디입니다. 어떻게 도와드릴까요?'
따란
# 뒤에 outputparser를 넣으면 text를 받을 수 있음
chain = chat_template | llm
# 이름을 Teddy로 넣음
# 이전에는 하나의 질문인데
# 대화형 형식의 프롬프트 만들고 human의 role이 있고 변수가 있고 이를 채우면 답변을 해줌
chain.invoke({"name": "Teddy", "user_input": "당신의 이름은 무엇입니까?"}).content
'제 이름은 Teddy입니다. 저를 통해 궁금한 것이 있거나 도움이 필요하신 경우 언제든지 말씀해주세요!'
정리 : PromptTemplate과 달리 ChatPromptTemplate은 대화형 형식이고, system과 role이 있어서
chat에 최적화됨
MessagePlaceholder
:채워지지 않은 것
:나중에 채워질 곳을 일단 잡아두고 있는 것
:ex 대화 내용을 기록할 때 사용함
: 쌓인 대화를 중간에 input으로 넣어야 하는데 대화가 아직 확정이 안 됨 -> history 변수에 넣음
from langchain_core.output_parsers import StrOutputParser
from langchain_core.prompts import ChatPromptTemplate, MessagesPlaceholder
chat_prompt = ChatPromptTemplate.from_messages(
[
(
"system",
"당신은 요약 전문 AI 어시스턴트입니다. 당신의 임무는 주요 키워드로 대화를 요약하는 것입니다.",
),
MessagesPlaceholder(variable_name="conversation"),
("human", "지금까지의 대화를 {word_count} 단어로 요약합니다."),
]
)
chat_prompt
나중에 사용하는 경우
formatted_chate_prompt 확인
# format으로 채운 것은 word count랑 conversation으로 input variable만 채움
# 아래 코드에서 formatted_chat_prompt 변수로 지정하지 않으면 아직 invoke할 수 없는 것이고 걍 format만 한 것임
formatted_chat_prompt = chat_prompt.format(
word_count=5,
conversation=[
("human", "안녕하세요! 저는 오늘 새로 입사한 테디 입니다. 만나서 반갑습니다."),
("ai", "반가워요! 앞으로 잘 부탁 드립니다."),
],
)
print(formatted_chat_prompt)
# format으로 채운 것은 word count랑 conversation으로 input variable만 채움
# 아래 코드에서 formatted_chat_prompt 변수로 지정하지 않으면 아직 invoke할 수 없는 것이고 걍 format만 한 것임
formatted_chat_prompt = chat_prompt.format(
word_count=5,
conversation=[
("human", "안녕하세요! 저는 오늘 새로 입사한 테디 입니다. 만나서 반갑습니다."),
("ai", "반가워요! 앞으로 잘 부탁 드립니다."),
],
)
print(formatted_chat_prompt)
chain 생성 후 invoke
근데 결과가 잘 안 나옴;
word count 에 맞게 output이 안 나옴.............
# chain 생성
chain = chat_prompt | llm | StrOutputParser()
# chain 실행 및 결과확인
chain.invoke(
{
"word_count": 5,
"conversation": [
(
"human",
"안녕하세요! 저는 오늘 새로 입사한 테디 입니다. 만나서 반갑습니다.",
),
("ai", "반가워요! 앞으로 잘 부탁 드립니다."),
],
}
)
'새로 입사한 테디, 반가워요!'
'랭체인' 카테고리의 다른 글
0201 강의 Part.2 Ch.3 RAG, 프로젝트 Develope (0) | 2025.01.27 |
---|---|
0201 강의 Part 2 - Ch1 Prompt [FewShotTemplate, suffix, example selector, FewShotChatMessagePromptTemplate, LangChainHub] (0) | 2025.01.27 |
강의 Ch.4 11~13 파일 05-Runnable (0) | 2025.01.18 |
강의 Ch4.08~10, 파일 04-LCEL-Advanced : LCEL 인터페이스, batch, async 비동기, parallel 병렬성 (1) | 2025.01.18 |
강의 Ch4.03~07, 파일 03-LCEL : 멀티모달 모델, 프롬프트 템플릿, 변형 (0) | 2025.01.17 |