목차
- 오늘 강의 개요
- 환경 설정 & 라이브러리 import
- 프롬프트의 4가지 구성 요소
- build_prompt 함수 - 구조적 프롬프트 생성기
- 역할 부여 (Role-Based Prompting)
- RoleBasedAssistant 클래스 - 역할 기반 대화 관리
- 실습: 다중 전문가 의사결정 시스템
- Chain-of-Thought (CoT) 프롬프팅
- build_step_prompt 함수 - 단계별 처리기
- 실습: 이메일 작성 자동화
- 출력 형식 지정 팁
- 핵심 개념 총정리
- 자주 나오는 실수/주의사항
1. 오늘 강의 개요
오늘 강의는 LLM이 더 정확하고 일관된 결과를 내도록 프롬프트를 설계하는 “프롬프트 엔지니어링” 기법을 심화 학습하는 날이다.
핵심 키워드: 구조화, 역할 부여, 단계별 사고(CoT)
전체 학습 흐름
1
2
3
4
5
6
7
8
9
10
11
| 나쁜 프롬프트 → 좋은 프롬프트의 차이점 확인
↓
프롬프트 4대 구성요소 학습 (지시/컨텍스트/입력/출력형식)
↓
역할 부여 기법 (SystemMessage 활용)
↓
대화 히스토리 관리 (RoleBasedAssistant 클래스)
↓
Chain-of-Thought (단계별 추론 강제)
↓
실전 응용: 이메일 자동 작성, 다중 전문가 토론
|
LLM의 출력 품질은 프롬프트 품질에 직접 비례한다. 같은 LLM이라도 프롬프트를 어떻게 짜느냐에 따라 결과가 크게 달라진다.
2. 환경 설정 & 라이브러리 import
코드
1
2
3
4
5
6
7
8
9
10
11
12
| import os
from dotenv import load_dotenv
import pandas as pd
import json
import time
from langchain_openai import ChatOpenAI
from langchain_core.messages import HumanMessage, SystemMessage, AIMessage
load_dotenv()
llm = ChatOpenAI(model="gpt-4o-mini")
|
각 모듈 역할
- ChatOpenAI : LLM 인스턴스 생성 (gpt-4o-mini 모델)
- HumanMessage : 사용자 발화 메시지 객체
- SystemMessage : 시스템(역할/지시) 메시지 객체
- AIMessage : AI 응답 메시지 객체 (few-shot 예시에 활용)
- load_dotenv() : .env 파일에서 OPENAI_API_KEY 로드
messages 리스트에 [SystemMessage, HumanMessage, AIMessage, …] 를 순서대로 담아서 llm.invoke(messages)로 전달하면 멀티턴 대화가 가능하다
3. 프롬프트의 4가지 구성 요소
LLM에게 보내는 프롬프트는 아래 4가지 요소로 구성하면 품질이 크게 향상된다.
4가지 구성 요소
1
2
3
4
| [지시] : LLM이 수행해야 할 작업 (동사로 명확하게)
[컨텍스트]: 배경 정보, 상황 설명 (LLM이 맥락을 이해하도록)
[입력] : 처리할 실제 데이터 또는 질문
[출력형식]: 원하는 출력 형태 지정 (json, 표, 문장 수, 형식)
|
나쁜 프롬프트 vs 좋은 프롬프트 비교
1
2
3
4
5
6
7
8
9
10
11
| # 나쁜 프롬프트 - 너무 모호함
bad_prompt = 'AI에 대해 알려줘'
# → LLM이 어디서부터 어디까지, 얼만큼, 누구에게 설명해야 할지 모름
# 좋은 프롬프트 - 4가지 요소 포함
good_prompt = f"""
[지시] 아래 주제에 대해 {user_input}을 작성해주세요
[컨텍스트] 기업 신입사원 대상 AI 교육 자료입니다
[입력] 대규모 언어모델(LLM)의 작동원리
[출력 형식] 3문장 이내로, 비유를 하나 포함하세요
"""
|
명확한 프롬프트 = 랜덤성이 줄어든다 LLM이 학습한 데이터에서 어떤 방향으로 답을 생성할지 범위가 좁아지기 때문
출력 제약 조건 가이드
- 수량 지정 : “정확히 3문장”, “5개의 불릿포인트”
- 대상 지정 : “프로그래밍 비전공자 대상”
- 제외 조건 : “코드 예시 없이”, “기술 용어 제외”
- 품질 기준 : “각 항목은 실제 사례 포함”
4. build_prompt 함수 - 구조적 프롬프트 생성기
4가지 구성 요소를 파라미터로 받아 완성된 프롬프트 문자열을 반환하는 함수.
코드
1
2
3
4
5
6
7
8
9
10
11
| def build_prompt(instructions, context="", input_data="", output_format=""):
parts = []
parts.append(f"[지시] {instructions}")
if context:
parts.append(f"[컨텍스트] {context}")
if input_data:
parts.append(f"[입력] {input_data}")
if output_format:
parts.append(f"[출력 형식] {output_format}")
return '\n'.join(parts)
|
context, input_data, output_format은 선택 항목이다 (없으면 생략됨) instructions만 필수 파라미터
사용 예시 - 감정 분석
1
2
3
4
5
6
| prompt = build_prompt(
instructions = '다음 텍스트의 감정을 분석하세요',
context = '고객 리뷰 분석 시스템입니다',
input_data = '배송은 빨랐는데 포장이 엉망이네요',
output_format= '감정 : [긍정/부정/혼합], 이유 : [한 줄 설명]'
)
|
생성된 프롬프트 (출력)
1
2
3
4
| [지시] 다음 텍스트의 감정을 분석하세요
[컨텍스트] 고객 리뷰 분석 시스템입니다
[입력] 배송은 빨랐는데 포장이 엉망이네요
[출력 형식] 감정 : [긍정/부정/혼합], 이유 : [한 줄 설명]
|
LLM 응답 예시
1
2
| 감정 : 혼합, 이유 : 배송이 빨랐다는 긍정적인 요소가 있지만,
포장이 엉망이라는 부정적인 요소가 함께 언급됨.
|
실습: 뉴스 기사 요약기
1
2
3
4
5
6
7
8
9
10
11
12
13
| news_text = """
지난 20일 중국 선전시에서 열린 '화웨이 중국 파트너 콘퍼런스 2026'에서 ...
아틀라스 350은 화웨이가 미국과 그 우방국인 한국·대만 등의 해외 공급망에
의존하지 않고 자체적으로 개발한 부품으로만 구성된 100% 중국산 추론용 AI 가속기다.
"""
prompt = build_prompt(
instructions = '뉴스 기사를 요약해주세요',
context = '뉴스 요약 서비스입니다',
input_data = news_text,
output_format= '제목 : ...\n요약 : (2문장)\n키워드 : [키워드1, 키워드2, 키워드3]'
)
llm.invoke([HumanMessage(content=prompt)])
|
LLM 응답 예시: 제목 : 화웨이, 100% 중국산 AI 가속기 ‘아틀라스 350’ 공개 요약 : 화웨이가 자체 개발한 AI 가속기 아틀라스 350을 선보이며 엔비디아 저사양 GPU보다 성능이 3배 뛰어나다고 강조했다. 키워드 : 화웨이, AI 가속기, 자주성
5. 역할 부여 (Role-Based Prompting)
SystemMessage를 이용해 LLM에게 특정 페르소나(역할)를 부여하는 기법. 같은 질문이라도 역할에 따라 전혀 다른 관점의 답변이 나온다.
기본 구조
1
2
| [SystemMessage] - 역할/페르소나 지정 (대화 전체에 유지됨)
[HumanMessage] - 실제 질문
|
역할 비교 실험
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
| question = "블록체인 기술이 금융 산업에 미치는 영향은?"
roles = {
"투자 전문가": "당신은 월스트리트에서 20년 경력의 투자 전문가입니다. "
"항상 투자 관점에서 생각하고, 구체적인 사례를 알려주세요",
"기술 개발자": "당신은 블록체인 코어 개발자입니다. 기술적 관점에서 설명하세요",
"규제 전문가": "당신은 금융감독원 출신 규제 전문가입니다. "
"법적/제도적 관점에서 설명해주세요."
}
for role_name, role_msg in roles.items():
print(f"roles : {role_name}")
result = llm.invoke([
SystemMessage(content=role_msg),
HumanMessage(content=question)
]).content
print(f"response : {result[:200]}")
print()
|
역할별 응답 차이
1
2
3
| 투자 전문가 → 거래 비용 절감, 암호화폐 사례, 투자 기회
기술 개발자 → 기술적 구현, 분산원장 원리
규제 전문가 → 법적 리스크, 제도적 과제
|
SystemMessage는 전체 대화의 “규칙서” 역할을 한다 HumanMessage가 여러 번 이어져도 SystemMessage의 역할은 계속 유지된다
6. RoleBasedAssistant 클래스 - 역할 기반 대화 관리
단순 일회성 역할 부여를 넘어, 대화 히스토리를 관리하며 멀티턴 대화를 지원하는 클래스.
코드
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
| class RoleBasedAssistant:
def __init__(self, role_name, system_prompt):
self.role_name = role_name
self.system_prompt = system_prompt
self.history = [SystemMessage(content=system_prompt)]
def ask(self, question):
self.history.append(HumanMessage(content=question))
response = llm.invoke(self.history)
answer = response.content
self.history.append(AIMessage(content=answer))
return answer
def reset(self):
self.history = [SystemMessage(content=self.system_prompt)]
|
구조 도식
1
2
3
4
5
6
7
8
9
10
11
| __init__()
└─ history = [SystemMessage(system_prompt)]
ask(question)
├─ history에 HumanMessage 추가
├─ llm.invoke(history) 호출
├─ AIMessage를 history에 추가
└─ 답변 반환
reset()
└─ history를 초기 상태로 초기화
|
history 리스트에 대화가 누적되므로 이전 문맥을 기억한 채로 대화를 이어갈 수 있다 reset()을 호출하면 대화 이력이 초기화되어 새 대화를 시작한다
사용 예시 - 코드 리뷰어
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
| reviewer = RoleBasedAssistant(
role_name = "시니어 코드 리뷰어",
system_prompt= """당신은 10년 경력의 Python 개발자이자 코드 리뷰어입니다.
규칙:
- 코드의 장단점을 균형있게 평가해주세요
- 개선 제안은 항상 코드 예시와 함께 주세요
- 주니어 개발자를 격려하는 톤을 유지해주세요
"""
)
sample_code = """
def calc(x):
r = []
for i in x:
if i > 0:
r.append(i*2)
return r
"""
reviewer.ask(f"이 코드를 리뷰해주세요:\n{sample_code}")
|
리뷰어 응답 예시
1
2
3
4
5
6
7
8
9
10
11
12
| 장점:
1. 명확한 목적: 양수를 찾아 두 배로 곱하는 로직이 직관적
2. 간결한 논리: for 루프와 if 조건문이 명확
단점:
1. 함수 이름이 모호: calc → positive_double 등으로 명확히
2. 리스트 컴프리헨션 활용 가능
3. 타입 힌트 없음
개선 코드:
def double_positives(numbers: list[int]) -> list[int]:
return [n * 2 for n in numbers if n > 0]
|
7. 실습: 다중 전문가 의사결정 시스템
RoleBasedAssistant를 여러 개 생성하고, 별도의 “사회자” assistant가 의견을 종합하는 패턴.
전체 흐름
1
2
3
4
5
6
7
8
9
| 질문 입력
↓
CEO assistant.ask(질문) → CEO 관점 의견
CTO assistant.ask(질문) → CTO 관점 의견
CFO assistant.ask(질문) → CFO 관점 의견
↓
세 의견을 하나의 문자열로 합치기
↓
moderator(사회자) assistant.ask(합친 의견) → 종합 요약
|
코드
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
| experts = [
RoleBasedAssistant(
role_name = "CEO",
system_prompt= "당신은 디지털 혁신을 추구하는 CEO입니다. "
"시장 기회와 경쟁 우위 관점에서 판단하세요. 3문장으로만 얘기하세요."
),
RoleBasedAssistant(
role_name = "CTO",
system_prompt= "당신은 현실적인 CTO입니다. "
"기술 구현 가능성, 인프라, 인력 관점에서 판단하세요. 3문장으로만 얘기하세요."
),
RoleBasedAssistant(
role_name = "CFO",
system_prompt= "당신은 보수적인 CFO입니다. "
"ROI, 비용, 재무 리스크 관점에서 판단하세요. 3문장으로만 얘기하세요."
)
]
question = "우리 회사에 AI를 도입해야 할까요"
opinion = []
for expert in experts:
answer = expert.ask(question)
opinion.append(f"\n {expert.role_name}\n {answer}")
print(f"\n {expert.role_name}")
print(f" {answer}\n")
# 사회자가 의견 종합
moderator = RoleBasedAssistant(
role_name = "사회자",
system_prompt= "당신은 경영 회의 사회자입니다. "
"여러 전문가 의견을 객관적으로 종합해서 핵심 합의점을 도출해주세요. 3문장으로만 얘기하세요."
)
summary_input = "다음 전문가 의견을 종합 정리하세요:\n\n" + "\n\n".join(opinion)
moderator.ask(summary_input)
|
실행 결과 예시
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
| CEO
네, AI 도입은 비용 절감과 효율성 향상의 기회를 제공할 수 있습니다.
경쟁사들이 이미 AI를 활용하고 있기 때문에 긴급히 필요합니다.
AI를 통해 고객 맞춤형 서비스를 강화하면 충성도를 높일 수 있습니다.
CTO
AI 도입은 특정 업무의 효율성을 높이고 데이터 기반 의사결정을 지원합니다.
기술 구현 가능성 평가와 필요 인력 확보가 선행되어야 합니다.
CFO
ROI 분석이 먼저이며, 초기 투자 비용과 운영 비용을 신중히 고려해야 합니다.
사회자 종합:
AI 도입은 경쟁력 강화와 효율성 향상에 도움이 되지만,
명확한 목표 설정과 예산 배정이 필수적입니다.
단계적 접근으로 재무 리스크를 최소화하며 지속 가능성을 확보해야 합니다.
|
이 패턴은 LLM에게 다양한 시각으로 문제를 분석하게 만드는 강력한 기법이다 각 역할에 “3문장으로만” 같은 출력 제약을 주면 답변이 더 집중된다
8. Chain-of-Thought (CoT) 프롬프팅
LLM이 복잡한 문제를 풀 때 단계별로 추론 과정을 거치도록 강제하는 기법.
핵심 아이디어
1
2
3
4
5
6
7
| 단순 프롬프트:
"이 데이터를 분석하고 인사이트를 제공하세요"
→ LLM이 즉흥적으로 답변 생성 (논리 비약 발생 가능)
CoT 프롬프트:
"1단계: 데이터 정리 → 2단계: 추세 분석 → 3단계: 이상점 식별 → ..."
→ LLM이 단계별로 사고하며 더 정확한 결과 도출
|
단순 프롬프트 vs CoT 프롬프트 비교
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
| task_data = "2026년 우리 회사 매출 : Q1 50억, Q2 65억, Q3 45억, Q4 80억"
# 단순 프롬프트
single_prompt = f"다음 데이터를 분석하고 인사이트를 제공하세요 : {task_data}"
llm.invoke([HumanMessage(content=single_prompt)]).content
# → 그냥 나열식으로 분석, 계산 오류 가능성 있음
# CoT 프롬프트 - 단계별 사고 강제
step_prompt = f"""다음 매출 데이터를 아래 단계에 따라 분석하세요.
데이터 : {task_data}
1단계 - 데이터 정리 : 분기별 매출을 표로 정리하세요
2단계 - 추세 분석 : 전분기 대비 증감률을 계산하세요
3단계 - 이상점 식별 : 눈에 띄는 변동이 있는 분기를 찾으세요
4단계 - 원인 추정 : 이상점의 가능한 원인을 2가지씩 제시하세요
5단계 - 제안 : 다음 분기 전략을 1가지 제안하세요
각 단계의 결과를 명확히 구분하여 출력하세요"""
|
CoT 응답 예시
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
| ### 1단계 - 데이터 정리
| 분기 | 매출 (억 원) |
|------|-------------|
| Q1 | 50 |
| Q2 | 65 |
| Q3 | 45 |
| Q4 | 80 |
### 2단계 - 추세 분석
Q1→Q2: +30% (증가)
Q2→Q3: -30.77% (감소, 이상점!)
Q3→Q4: +77.78% (대폭 증가)
### 3단계 - 이상점 식별
Q3 매출이 전분기 대비 30%이상 급감
### 4단계 - 원인 추정
Q3 감소 원인:
- 계절성 요인 (여름 비수기)
- 대형 거래처와의 계약 지연 또는 해지
### 5단계 - 제안
Q3 비수기 대비 사전 계약 확보 전략 필요
|
CoT 기법은 수학 계산, 논리 추론, 단계별 의사결정 등에서 특히 효과적이다 LLM은 단계를 나누면 더 신중하게 생각하게 된다 (Reasoning 모델의 원리와 유사)
9. build_step_prompt 함수 - 단계별 처리기
CoT 프롬프트를 재사용 가능한 형태로 만든 함수.
코드
1
2
3
4
5
6
7
8
9
10
11
12
| def build_step_prompt(task, data, steps):
prompt_parts = [
f"작업: {task}",
f"\n데이터:\n{data}",
"\n아래 단계를 순서대로 수행하세요:\n"
]
for i, step in enumerate(steps, 1):
prompt_parts.append(f"{i}단계 - {step['name']}: {step['instruction']}")
prompt_parts.append("\n각 단계의 결과를 '## N단계' 형식으로 구분하여 출력하세요")
return '\n'.join(prompt_parts)
|
steps 파라미터 구조
1
2
3
4
| steps = [
{"name": "단계 이름", "instruction": "이 단계에서 수행할 구체적 지시"},
...
]
|
사용 예시 - 고객 리뷰 심층 분석
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
| review = "배송은 정말 빨랐어요! 그런데 상품 색상이 사진과 좀 달라서 실망했습니다."
steps = [
{"name": "감정 식별", "instruction": "리뷰에서 긍정, 부정 감정을 각각 추리세요"},
{"name": "주제 분류", "instruction": "언급된 주제(배송, 품질, 가격 등)를 분류하세요"},
{"name": "점수 산정", "instruction": "각 주제별 만족도를 1~5점으로 평가하세요"},
{"name": "종합 판단", "instruction": "전체 만족도와 재구매 가능성을 판단하세요"},
]
prompt = build_step_prompt(
task = "고객 리뷰 심층 분석",
data = review,
steps = steps
)
print(prompt)
|
생성된 프롬프트 (출력)
1
2
3
4
5
6
7
8
9
10
11
12
13
| 작업: 고객 리뷰 심층 분석
데이터:
배송은 정말 빨랐어요! 그런데 상품 색상이 사진과 좀 달라서 실망했습니다.
아래 단계를 순서대로 수행하세요:
1단계 - 감정 식별: 리뷰에서 긍정, 부정 감정을 각각 추리세요
2단계 - 주제 분류: 언급된 주제(배송, 품질, 가격 등)를 분류하세요
3단계 - 점수 산정: 각 주제별 만족도를 1~5점으로 평가하세요
4단계 - 종합 판단: 전체 만족도와 재구매 가능성을 판단하세요
각 단계의 결과를 '## N단계' 형식으로 구분하여 출력하세요
|
LLM 응답 예시
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
| ## 1단계 - 감정 식별
- 긍정 감정: "배송은 정말 빨랐어요!"
- 부정 감정: "상품 색상이 사진과 좀 달라서 실망했습니다."
## 2단계 - 주제 분류
- 배송
- 품질
## 3단계 - 점수 산정
- 배송: 5점
- 품질: 2점
## 4단계 - 종합 판단
- 전체 만족도: 3.5점
- 재구매 가능성: 낮음
|
10. 실습: 이메일 작성 자동화
build_step_prompt를 활용해서 상황에 맞는 비즈니스 이메일을 단계별로 작성하는 실습.
이메일 작성 단계 정의
1
2
3
4
5
6
7
| email_steps = [
{'name': '상황 분석', 'instruction': '발신자, 수신자, 상황의 긴급도, 이메일의 목적을 파악하세요'},
{'name': '핵심 메시지 도출', 'instruction': '이메일에서 전달할 핵심 메시지를 한 문장으로 정리하세요'},
{'name': '이메일 구조 설계', 'instruction': '인사->본론->요청사항->마무리 구조를 설계하세요'},
{'name': '본문 작성', 'instruction': '위 구조에 따라 완성된 이메일을 작성하세요. 공손하지만 명확한 톤을 유지하세요'},
{'name': '최종 검토', 'instruction': '작성된 이메일의 톤, 오타, 논리 흐름을 검토하고 최종본을 출력하세요'},
]
|
예시 1: 프로젝트 지연 알림 이메일
1
2
3
4
5
6
7
8
| situation1 = "프로젝트 납기일이 2주 지연될 예정, 이를 클라이언트에게 알려야 합니다. 원인은 외부 API 연동 이슈입니다"
prompt1 = build_step_prompt(
task = "비즈니스 이메일 작성",
data = situation1,
steps = email_steps
)
print(llm.invoke([HumanMessage(content=prompt1)]).content)
|
응답 예시 (최종 이메일 본문)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
| 제목: 프로젝트 납기일 지연 안내
안녕하세요 [클라이언트 이름]님,
저희는 [프로젝트 이름]의 진행 상황에 대해 말씀드릴 사항이 있어 연락드립니다.
현재 진행 중인 프로젝트의 납기일이 외부 API 연동 이슈로 인해 2주 지연될 예정입니다.
저희 팀은 이 문제를 해결하기 위해 최선을 다하고 있으며,
빠른 시일 내에 정상적인 일정을 회복할 수 있도록 노력하겠습니다.
불편을 드려서 대단히 죄송합니다. 궁금한 사항이 있으시면 언제든지 연락해 주세요.
감사합니다.
[발신자 이름]
|
예시 2: 신규 파트너십 제안 이메일
1
2
3
4
5
6
7
8
| situation2 = "대기업 데이터 팀장에게 협업을 제안하는 메일을 보내려 합니다"
prompt2 = build_step_prompt(
task = "비즈니스 이메일 작성",
data = situation2,
steps = email_steps
)
print(llm.invoke([HumanMessage(content=prompt2)]).content)
|
두 이메일 비교 포인트
1
2
| 상황1 (지연 안림) : 사과 → 원인 설명 → 향후 계획 → 연락처
상황2 (협업 제안) : 자기소개 → 협업 가치 → 구체적 제안 → 미팅 요청
|
build_step_prompt는 “작업 유형”과 “상황 데이터”만 바꿔도 다양한 문서를 자동 생성할 수 있다 이메일 외에도 기획서, 보고서, 계약서 초안 등에 응용 가능
11. 출력 형식 지정 팁
LLM이 원하는 형식으로 정확히 출력하도록 유도하는 방법.
출력 형식 종류
1
2
3
4
5
| json : 구조화된 데이터 추출, API 연동에 활용
table : 마크다운 표 형식, 비교/정리에 유용
yaml : 설정 파일 형태
xml : 레거시 시스템 연동
불릿포인트 : 목록 형태의 답변
|
출력 형식 지정 방법
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
| # 방법 1: 직접 형식 제시
output_format = '감정 : [긍정/부정/혼합], 이유 : [한 줄 설명]'
# 방법 2: json 템플릿 제시
output_format = """
{
"sentiment" : "긍정/부정/혼합",
"score" : "1~5점수",
"pros" : ["장점1"],
"cons" : ["단점1"]
}
"""
# 방법 3: 단계 번호 부여
output_format = "각 단계의 결과를 '## N단계' 형식으로 구분하여 출력하세요"
|
LLM 평가 기준 개념
1
2
3
4
5
6
| 답변 성능 측정 예시:
정답 : "I go to school"
모델 출력 : "I go school"
→ 단어 수준에서는 거의 맞지만 문법적으로 틀림
→ 출력 형식이 정확히 맞아야 파싱이 가능하므로 형식 준수가 중요
|
부정 제약보다 긍정 제약이 효과적이다 “거짓말로 지어내지 마세요” → “사실만 그대로 얘기하세요” “주관적 의견 말고” → “객관적 사실만”
12. 핵심 개념 총정리
오늘 배운 기법 정리
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
| 1. 구조적 프롬프트 (build_prompt)
- 지시/컨텍스트/입력/출력형식 4요소 분리
- 명확한 제약 조건 부여
2. 역할 부여 (SystemMessage)
- 페르소나를 통한 관점 고정
- 대화 전체에 걸쳐 역할 유지
3. 대화 히스토리 관리 (RoleBasedAssistant)
- history 리스트에 누적
- HumanMessage / AIMessage 쌍으로 관리
- reset()으로 초기화
4. Chain-of-Thought (build_step_prompt)
- 단계별 사고 강제
- 복잡한 태스크를 작은 단위로 분해
- 각 단계 결과를 명확히 구분하여 출력
|
언제 어떤 기법을 쓸까
1
2
3
4
5
| 단순 Q&A → 기본 프롬프트 + 출력 형식 지정
전문적 관점 필요 → 역할 부여 (SystemMessage)
멀티턴 대화 필요 → RoleBasedAssistant (history 유지)
복잡한 분석/계산 → Chain-of-Thought (단계별)
다양한 관점 비교 → 다중 Expert + Moderator 패턴
|
13. 자주 나오는 실수/주의사항
주의사항
- 모호한 프롬프트 금지
- “AI에 대해 알려줘” 대신 대상/분량/형식을 명확히 지정
- LLM이 무엇을 원하는지 추측하게 만들지 말 것
- 역할을 시스템 프롬프트에 지정할 것
- HumanMessage에 역할 넣으면 대화 흐름이 중간에 깨질 수 있음
- 역할은 반드시 SystemMessage에 지정
- CoT 단계 수는 적절하게
- 너무 많은 단계는 오히려 LLM이 혼란스러워함
- 3~5단계가 적당, 각 단계를 명확하게 분리
- 부정 제약보다 긍정 제약
- “~하지 마세요” → “~하세요”로 바꿔서 표현
- LLM은 긍정적 지시에 더 잘 반응함
- 출력 형식은 예시와 함께
- “json으로 출력하세요” 보다 실제 json 구조를 템플릿으로 제공
- 빈 칸만 채우는 형태로 지시하면 파싱 오류 감소
- history 관리 주의
- RoleBasedAssistant를 재사용할 때 reset() 호출 확인
- 이전 대화가 누적되면 컨텍스트 오염 가능
끝