본문 바로가기
공부방/Python & AI

[AI] ChatPromptTemplate

by 래채 2025. 10. 12.

ChatPromptTemplate은 LangChain에서 채팅 기반 언어 모델을 위한 프롬프트를 구조화하고 관리하는 핵심 클래스입니다.

🎯 주요 특징

  1. 메시지 기반 구조: system, human, ai 등 역할별 메시지를 구조화
  2. 변수 템플릿: 동적으로 값을 주입할 수 있는 플레이스홀더 제공
  3. 재사용성: 한 번 정의한 템플릿을 여러 번 사용 가능
  4. 타입 안정성: 명확한 메시지 역할 구분

💡 주요 메서드

  • from_messages(): 메시지 리스트로부터 템플릿 생성
  • format_messages(): 변수를 주입하여 최종 메시지 생성
  • invoke(): 변수를 주입하고 포맷된 메시지 반환

📌 핵심 포인트 정리

1️⃣ 메시지 역할 구분

  • ("system", ...): AI의 역할과 행동 정의
  • ("human", ...): 사용자 입력
  • ("ai", ...): AI 응답 (Few-shot 예제용)

2️⃣ 변수 주입

python
{variable_name}  # 중괄호로 변수 표시

3️⃣ MessagesPlaceholder

대화 히스토리나 동적 메시지 리스트를 삽입할 때 필수!

4️⃣ 실전 활용 패턴

 
python
# 기본 패턴
template | llm | output_parser

# 체인 구성
chain = prompt_template | llm
response = chain.invoke({"variable": "value"})

🎯 언제 사용하면 좋을까?

프롬프트 재사용이 필요할 때
대화 맥락 유지가 중요할 때
역할 기반 시스템 구축 시
RAG, 에이전트 등 복잡한 파이프라인

 

- 샘플 코드!

from langchain_core.prompts import ChatPromptTemplate, MessagesPlaceholder
from langchain_core.messages import SystemMessage, HumanMessage, AIMessage

# ============================================================
# 사례 1: 기본 사용법 - 간단한 질의응답
# ============================================================
print("=" * 60)
print("사례 1: 기본 사용법")
print("=" * 60)

# 템플릿 정의
basic_template = ChatPromptTemplate.from_messages([
    ("system", "당신은 {role}입니다. 항상 {tone} 톤으로 답변하세요."),
    ("human", "{question}")
])

# 템플릿 사용
formatted_messages = basic_template.format_messages(
    role="친절한 AI 어시스턴트",
    tone="공손하고 따뜻한",
    question="파이썬에서 리스트와 튜플의 차이는 뭔가요?"
)

for msg in formatted_messages:
    print(f"{msg.__class__.__name__}: {msg.content}\n")


# ============================================================
# 사례 2: Few-shot Learning - 예제 기반 학습
# ============================================================
print("=" * 60)
print("사례 2: Few-shot Learning")
print("=" * 60)

few_shot_template = ChatPromptTemplate.from_messages([
    ("system", "당신은 감정 분석 전문가입니다. 주어진 텍스트의 감정을 분석하세요."),
    ("human", "오늘 승진했어요!"),
    ("ai", "긍정적 (기쁨, 성취감)"),
    ("human", "비가 와서 우울해..."),
    ("ai", "부정적 (슬픔, 우울)"),
    ("human", "{user_text}")
])

formatted = few_shot_template.format_messages(
    user_text="새로운 프로젝트가 시작되네요."
)

for msg in formatted:
    print(f"{msg.__class__.__name__}: {msg.content}\n")


# ============================================================
# 사례 3: MessagesPlaceholder - 대화 히스토리 포함
# ============================================================
print("=" * 60)
print("사례 3: 대화 히스토리 포함")
print("=" * 60)

conversation_template = ChatPromptTemplate.from_messages([
    ("system", "당신은 사용자의 대화 맥락을 이해하는 AI입니다."),
    MessagesPlaceholder(variable_name="chat_history"),
    ("human", "{current_input}")
])

# 이전 대화 히스토리
chat_history = [
    HumanMessage(content="내 이름은 철수야"),
    AIMessage(content="안녕하세요, 철수님! 만나서 반갑습니다."),
    HumanMessage(content="나는 개발자야"),
    AIMessage(content="멋지네요! 어떤 분야의 개발을 하시나요?")
]

formatted = conversation_template.format_messages(
    chat_history=chat_history,
    current_input="내 직업이 뭐였지?"
)

for msg in formatted:
    print(f"{msg.__class__.__name__}: {msg.content}\n")


# ============================================================
# 사례 4: 다국어 번역 시스템
# ============================================================
print("=" * 60)
print("사례 4: 다국어 번역")
print("=" * 60)

translation_template = ChatPromptTemplate.from_messages([
    ("system", """당신은 전문 번역가입니다.
원문: {source_lang}
목표: {target_lang}
번역 스타일: {style}"""),
    ("human", "{text}")
])

formatted = translation_template.format_messages(
    source_lang="한국어",
    target_lang="영어",
    style="비즈니스 공식 문서",
    text="안녕하세요, 귀사의 제안서를 검토했습니다."
)

for msg in formatted:
    print(f"{msg.__class__.__name__}: {msg.content}\n")


# ============================================================
# 사례 5: RAG (Retrieval-Augmented Generation) 패턴
# ============================================================
print("=" * 60)
print("사례 5: RAG 패턴")
print("=" * 60)

rag_template = ChatPromptTemplate.from_messages([
    ("system", """당신은 문서 기반 질의응답 시스템입니다.
주어진 컨텍스트만을 사용하여 답변하세요.

컨텍스트:
{context}

답변 규칙:
1. 컨텍스트에 없는 정보는 "해당 정보가 없습니다"라고 답변
2. 출처를 명시할 것
3. 간결하고 정확하게 답변"""),
    ("human", "{question}")
])

context = """
[문서 1] LangChain은 LLM 애플리케이션 개발 프레임워크입니다.
[문서 2] ChatPromptTemplate은 프롬프트를 구조화하는 도구입니다.
[문서 3] 2023년에 출시되었으며, 파이썬과 TypeScript를 지원합니다.
"""

formatted = rag_template.format_messages(
    context=context,
    question="LangChain은 언제 출시되었나요?"
)

for msg in formatted:
    print(f"{msg.__class__.__name__}: {msg.content}\n")


# ============================================================
# 사례 6: 코드 리뷰 시스템
# ============================================================
print("=" * 60)
print("사례 6: 코드 리뷰")
print("=" * 60)

code_review_template = ChatPromptTemplate.from_messages([
    ("system", """당신은 {language} 전문 코드 리뷰어입니다.

리뷰 기준:
- 코드 품질: {focus_areas}
- 심각도: {severity_level}

리뷰 형식:
1. 전반적 평가
2. 개선 필요 사항
3. 긍정적 측면
4. 제안사항"""),
    ("human", "다음 코드를 리뷰해주세요:\n\n{code}")
])

sample_code = """
def calculate_average(numbers):
    total = 0
    for num in numbers:
        total = total + num
    return total / len(numbers)
"""

formatted = code_review_template.format_messages(
    language="Python",
    focus_areas="성능, 가독성, 예외 처리",
    severity_level="상세",
    code=sample_code
)

for msg in formatted:
    print(f"{msg.__class__.__name__}: {msg.content}\n")


# ============================================================
# 사례 7: 동적 역할 부여 (Role-based)
# ============================================================
print("=" * 60)
print("사례 7: 동적 역할 부여")
print("=" * 60)

role_template = ChatPromptTemplate.from_messages([
    ("system", """역할: {role}
전문 분야: {expertise}
성격: {personality}
제약 조건: {constraints}"""),
    ("human", "{task}")
])

# 예시 1: 창의적 작가
formatted1 = role_template.format_messages(
    role="창의적인 소설가",
    expertise="SF, 판타지",
    personality="상상력이 풍부하고 비유적 표현을 좋아함",
    constraints="1000자 이내, 청소년 독자 대상",
    task="우주 정거장에서의 하루를 묘사해주세요"
)

print("--- 작가 역할 ---")
for msg in formatted1:
    print(f"{msg.__class__.__name__}: {msg.content}\n")

# 예시 2: 데이터 분석가
formatted2 = role_template.format_messages(
    role="데이터 분석 전문가",
    expertise="통계, 시각화, Python",
    personality="논리적이고 근거 기반 의사결정",
    constraints="코드는 pandas와 matplotlib 사용",
    task="월별 매출 데이터 분석 방법을 제안해주세요"
)

print("\n--- 분석가 역할 ---")
for msg in formatted2:
    print(f"{msg.__class__.__name__}: {msg.content}\n")


# ============================================================
# 사례 8: 템플릿 체이닝 - 다단계 처리
# ============================================================
print("=" * 60)
print("사례 8: 다단계 프롬프트 (요약 → 분석)")
print("=" * 60)

# 1단계: 요약
summary_template = ChatPromptTemplate.from_messages([
    ("system", "긴 텍스트를 3문장으로 요약하세요."),
    ("human", "{long_text}")
])

# 2단계: 분석
analysis_template = ChatPromptTemplate.from_messages([
    ("system", "요약된 내용을 바탕으로 핵심 키워드 5개를 추출하세요."),
    ("human", "요약: {summary}")
])

long_article = """
LangChain은 대규모 언어 모델(LLM)을 활용한 애플리케이션 개발을 위한 
프레임워크입니다. 이 프레임워크는 프롬프트 관리, 체인 구성, 
메모리 관리 등 다양한 기능을 제공합니다. 특히 ChatPromptTemplate은 
구조화된 프롬프트를 쉽게 만들 수 있게 해주며, 재사용성과 유지보수성을 
크게 향상시킵니다. 개발자들은 이를 통해 복잡한 대화형 AI 시스템을 
효율적으로 구축할 수 있습니다.
"""

# 1단계 실행
step1 = summary_template.format_messages(long_text=long_article)
print("--- 1단계: 요약 프롬프트 ---")
for msg in step1:
    print(f"{msg.__class__.__name__}: {msg.content}\n")

# 2단계 실행 (가상의 요약 결과 사용)
mock_summary = "LangChain은 LLM 앱 개발 프레임워크다. ChatPromptTemplate로 구조화된 프롬프트를 만든다. 재사용성과 유지보수성이 우수하다."
step2 = analysis_template.format_messages(summary=mock_summary)
print("--- 2단계: 분석 프롬프트 ---")
for msg in step2:
    print(f"{msg.__class__.__name__}: {msg.content}\n")


# ============================================================
# 사례 9: 부분 프롬프트 (Partial Prompts)
# ============================================================
print("=" * 60)
print("사례 9: 부분 프롬프트")
print("=" * 60)

from datetime import datetime

# 날짜를 반환하는 함수
def get_current_date():
    return datetime.now().strftime("%Y-%m-%d %H:%M:%S")

# partial 사용
partial_template = ChatPromptTemplate.from_messages([
    ("system", "현재 시각: {current_time}\n당신은 {role}입니다."),
    ("human", "{question}")
])

# current_time을 미리 고정
partial_prompt = partial_template.partial(current_time=get_current_date())

# 나머지 변수만 채우기
formatted = partial_prompt.format_messages(
    role="시간 관리 코치",
    question="오늘 할 일을 어떻게 정리하면 좋을까요?"
)

for msg in formatted:
    print(f"{msg.__class__.__name__}: {msg.content}\n")


# ============================================================
# 사례 10: 실전 활용 - LLM과 함께 사용
# ============================================================
print("=" * 60)
print("사례 10: 실전 통합 예제 (LLM 호출 구조)")
print("=" * 60)

# 실제 LLM 체인 구조 (의사코드)
integration_template = ChatPromptTemplate.from_messages([
    ("system", "당신은 {domain} 전문가입니다."),
    MessagesPlaceholder(variable_name="history", optional=True),
    ("human", "{input}")
])

print("템플릿 구조:")
print(integration_template)
print("\n사용 예시:")
print("""
# LangChain의 실제 사용 패턴
from langchain_openai import ChatOpenAI

# LLM 초기화
llm = ChatOpenAI(model="gpt-4", temperature=0.7)

# 체인 생성
chain = integration_template | llm

# 실행
response = chain.invoke({
    "domain": "파이썬 개발",
    "history": [
        HumanMessage(content="Flask와 FastAPI 중 뭐가 좋나요?"),
        AIMessage(content="프로젝트 규모와 요구사항에 따라 다릅니다...")
    ],
    "input": "비동기 처리가 필요하면 어떤 걸 써야 하나요?"
})

print(response.content)
""")


# ============================================================
# 보너스: 템플릿 검증 및 디버깅 팁
# ============================================================
print("=" * 60)
print("보너스: 템플릿 디버깅")
print("=" * 60)

debug_template = ChatPromptTemplate.from_messages([
    ("system", "당신은 {role}입니다."),
    ("human", "{question}")
])

# 템플릿 정보 확인
print("템플릿에 필요한 변수:", debug_template.input_variables)
print("템플릿 구조:\n", debug_template.pretty_repr())

# 잘못된 변수 사용 시 에러 방지
try:
    # 필수 변수 누락
    debug_template.format_messages(role="개발자")
except KeyError as e:
    print(f"\n에러 발생: {e}")
    print("누락된 변수를 확인하세요!")

print("\n" + "=" * 60)
print("모든 예제 완료!")
print("=" * 60)

 

chatprompt_examples.py
0.01MB

 

with Claude

'공부방 > Python & AI' 카테고리의 다른 글

[AI] ChatPromptTemplate.from_messages  (0) 2025.10.13
[Python] Sequence  (0) 2025.10.12
[AI] add_messages  (0) 2025.10.12
[Python] Annotated  (0) 2025.10.12
[AI] MessagesPlaceholder  (0) 2025.10.12