LangChain 챗봇3장 · LangChain 기본 구조와 LCEL10 / 21← 이전목차다음 →MetaContents

3장. LangChain 기본 구조와 LCEL

다양한 프롬프트 1: 역할·형식·제약 지시

꽃집에 꽃다발을 주문할 때 "꽃다발 하나요"라고만 하면 꽃집 주인의 취향대로 나옵니다. "어머니 생신 선물이에요(누구를 위해), 손에 들기 좋은 작은 크기로요(어떤 꼴로), 백합은 빼 주세요(하지 말 것)"라고 하면 원하는 꽃다발에 훨씬 가까워집니다. 프롬프트도 같습니다. 질문만 던지는 것보다 역할, 형식, 제약을 적어 주면 답이 원하는 꼴에 가까워집니다.

역할, 형식, 제약의 세 가지 지시를 나란히 놓고 예를 붙인 비교 그림

세 상자가 시스템 메시지에 적는 세 가지 지시입니다. 역할은 "누구로서 답하나", 형식은 "어떤 꼴로 답하나", 제약은 "하지 말 것과 경계"입니다. 상자 아래 줄이 이 장에서 쓰는 예입니다. 여기서 "어머니 생신 선물"이 역할, "작은 크기"가 형식, "백합은 빼고"가 제약입니다. 비유와 다른 점은, 꽃집 주인은 지시를 어기면 다시 만들어 주지만 모델은 지시를 가끔 어기므로 우리가 결과를 확인해야 한다는 것입니다.

세 가지 지시

지시묻는 것예없으면
역할(role)누구로서 답하나너는 구름다리여행의 친절한 상담원이다아무에게나 하는 일반적인 답
형식(format)어떤 꼴로 답하나글머리표(-) 세 줄 이내길이와 꼴이 그때그때 다르다
제약(constraint)하지 말 것, 모를 때가격은 지어내지 않는다. 모르면 상담원 연결그럴듯한 숫자를 지어낼 수 있다

constraint 는 "제한, 묶어 두는 것"이라는 뜻입니다. 세 지시는 모두 시스템 메시지에 적고, 손님의 질문은 human 줄에 따로 둡니다.

짧은 예시

세 지시를 변수로 따로 적어 두고 이어 붙여 시스템 메시지를 만듭니다. 지시를 따로 두면 하나만 바꿔 가며 견주기 쉽습니다.

Python
from langchain_core.prompts import ChatPromptTemplate

ROLE = "너는 구름다리여행의 친절한 상담원이다."
FORMAT = "답은 글머리표(-) 세 줄 이내로 쓴다."
LIMIT = "모르는 것은 '상담원에게 연결해 드릴게요'라고 답하고, 가격은 지어내지 않는다."

# 세 지시를 줄바꿈으로 이어 시스템 메시지 하나로 만든다
prompt = ChatPromptTemplate.from_messages([("system", "\n".join([ROLE, FORMAT, LIMIT])), ("human", "{question}")])

messages = prompt.invoke({"question": "제주도 3박 4일 얼마예요?"}).to_messages()
print(messages[0].content)
print("---")
print(messages[1].content)
출력
너는 구름다리여행의 친절한 상담원이다.
답은 글머리표(-) 세 줄 이내로 쓴다.
모르는 것은 '상담원에게 연결해 드릴게요'라고 답하고, 가격은 지어내지 않는다.
---
제주도 3박 4일 얼마예요?

손님은 가격을 물었지만 FAQ 에는 가격이 없습니다. 제약 지시가 없으면 모델이 그럴듯한 금액을 지어낼 수 있습니다. 1장의 "환각과 지식 마감일" 절에서 본 처방 "모르면 모른다고 답하라"를 시스템 메시지에 넣은 것입니다. 실습 4에서 지시가 있을 때와 없을 때 답의 꼴을 견줍니다.

코드가 의미하는 것

이 코드는 꽃다발 주문서에 "누구를 위해, 어떤 꼴로, 무엇은 빼고"를 한 줄씩 적어 넣는 일을 흉내 낸 것입니다. 지시 셋을 따로 적고, 이어 붙여 시스템 메시지로 만들고, 손님 질문은 다른 줄에 넣습니다.

코드하는 일챗봇에서 뜻하는 것
ROLE, FORMAT, LIMIT역할, 형식, 제약 지시를 변수 셋에 따로 둔다챗봇의 성격, 답의 꼴, 하지 말 것을 나눠 두면 하나만 바꿔 가며 견주기 쉽습니다
"\n".join([ROLE, FORMAT, LIMIT])세 지시를 줄바꿈으로 이어 글 하나로 만든다세 지시가 시스템 메시지 하나에 들어갑니다
("human", "{question}")손님 질문을 human 줄에 따로 둔다손님 글이 규칙과 섞이지 않게 합니다
messages[0].content, messages[1].content채운 두 메시지의 글을 꺼낸다모델에게 가는 규칙과 질문을 따로 확인합니다

결과에서 읽을 것은 두 가지입니다.

  • 시스템 메시지가 지시 세 줄입니다. --- 위의 세 줄이 역할, 형식, 제약 차례로 들어갔습니다.
  • 손님 질문은 따로 갑니다. --- 아래의 가격 질문은 human 메시지에 있습니다. 이 질문에 제약 지시가 어떻게 작동하는지는 실습 4에서 봅니다.

주의할 점

  • 지시는 "~하지 마라"보다 "~한다"로 적는 편이 잘 지켜집니다. "길게 쓰지 마라" 대신 "세 줄 이내로 쓴다"처럼 무엇을 할지 적습니다.
  • 지시가 서로 부딪치지 않게 합니다. "자세히 설명한다"와 "세 줄 이내로 쓴다"를 함께 적으면 모델이 어느 쪽을 따를지 그때그때 달라집니다.
← 이전 절3장 · 파이프로 잇기와 데이터가 바뀌는 모습다음 절 →3장 · 다양한 프롬프트 2: 퓨샷과 단계별 지시