프롬프트 · 컨텍스트
프롬프트 엔지니어링은 LLM이 최적의 결과를 생성하도록 자연어로 구성된 입력을 설계·최적화하는 기술/방법론임.
Bedrock을 통해 Claude, GPT, Gemma를 단일 인터페이스로 호출하고, 모델별 프롬프트 전략의 차이를 실습함.
1. API 키 발급 및 연동
세 가지 LLM 벤더(Claude, OpenAI, Gemini)의 API 키를 발급하고 Bedrock을 통해 통합 연동하는 방법을 다룸.
1.1 벤더별 API 키 발급
- Gemini — Google AI Studio에서 API 키 발급, 하루 1,500 call 무료 제공
- AWS Bedrock — AWS 콘솔에서 Bearer Token 발급, 사용량 기반 과금 (토큰 제한 없음)
- Claude — Anthropic Console에서 직접 발급
1.2 Gemini 연동 확인
from google import genai
client = genai.Client(api_key=GEMINI_API_KEY)
def gemini_invoke(prompt, history):
res = client.models.generate_content(
model='gemini-2.5-flash',
contents=prompt
)
return res.text
gradio.ChatInterface(gemini_invoke, type='messages').launch()
1.3 Bedrock 연동 확인
import boto3
bedrock = boto3.client(
service_name='bedrock-runtime',
region_name='us-east-1',
)
models = {
"anthropic": "us.anthropic.claude-haiku-4-5-20251001-v1:0",
"openai": "openai.gpt-oss-120b-1:0",
"google": "google.gemma-3-27b-it"
}
Bedrock을 사용하면 벤더별 API를 각각 관리하지 않고, 동일한 AWS SDK 코드베이스에서 모델명만 바꿔 다수의 LLM을 호출할 수 있음.
2. 프롬프트 엔지니어링
효과적인 프롬프트 구성 방법과 LLM 벤더별 최적화 전략을 다룸.
2.1 공통 구성 (90% 비중)
구성 요소 설명 예시
| 페르소나/역할 (Role) | 구체적인 아이덴티티 부여 | 너는 10년차 재산 관리자야 |
| 배경/상황 (Context) | 구체적인 배경 정보 제공 | 현재 가진 자산으로 은퇴 자금 설계 |
| 지시 (Task) | 구체적인 요청/요구사항 | 10년 플랜 초안 작성, 손해비율 산정 |
| 출력 형식/제약 (Format) | 토큰 제약, 형식, 말투 지정 | 500자 이내, 표 형태, 반말 금지 |
2.2 모델 특화 구성 (10% 비중)
- Claude — XML 태그로 섹션을 명확히 구획, 논리적·긴 글 요청에 적합하여 맥락 파악이 우수함
- GPT — 대화형에 최적화, Few-Shot 프롬프트 활용을 권장하며 단계별 결과 유도 방식이 효과적임
- Gemini — 구글 검색 연동에 유리, 팩트 체크 및 트렌드 반영 지시에서 강점을 보임
2.3 모델별 프롬프트 예시 — 텀블러 SNS 초안 작성
공통 프롬프트 구성
# 역할
당신은 20년차 프로 카피라이터 입니다.
# 배경
우리 회사에서 이번에 "24시간 동안 얼음이 녹지 않는 셀럽형 텀플러"를 출시하였습니다.
타겟 고객은 하루 종일 아이스 커피를 달고 사는 20대 직장인입니다.
# 지시
타겟 고객에게 보낼 홍보용 SNS 초안을 작성해 주세요.
# 제약조건, 포맷
1. 톤앤매너: 유머러스하게, 위트 있게
2. 형식: 도입부(장점 4개) + 마무리(구매유도)
3. 분량: 400자 이내
Claude 특화 — XML 태그 구획
<role>
당신은 20년차 논리적이고 설득력 있는 프로 카피라이터입니다.
</role>
<context>
제품 : 24시간동안 얼음이 녹지 않는 셀럽형 텀블러
타겟 : 하루종일 커피를 마시는 20대 직장인
</context>
<instruction>
위 타겟에 대한 홍보용 SNS 초안을 작성하세요.
</instruction>
<constraints>
톤앤매너: 전문적이지만 너무 딱딱하지 않게
형식:
- 도입부 : 텀플러의 장점(4개 포인트)
- 마무리 : 구매유도
</constraints>
GPT 특화 — Few-Shot 샘플 제공
# few shot 제시 (샘플 제공)
"점심시간이 되면 오전에 구매한 아이스 아메리카노(아아)가 미지근한 맹물이 되지요?
이 고통에서 벗어날 수 있는 ..."
Gemini 특화 — 검색 연동
# 특별지시
현재 한국 20대 직장인들이 오피스 아이템 트렌드를 검색하여,
이 텀블러가 왜 필수템인지 설명하는 문구를 도입부에 자연스럽게 녹여줘.
모델별로 동일한 주제에 대해 결과물이 상이하게 나옴. Claude는 논리·구조 중심, GPT는 친근한 대화체, Gemini는 트렌드 반영 문구가 강점.
3. GPT · Claude · Gemma Bedrock 호출 코드
벤더별 프롬프트 구조와 응답 파싱 방식의 차이를 구체적인 코드로 비교함.
3.1 범용 호출 함수
def llm_invoke(prompt='', vender="openai", history=None):
res = bedrock.invoke_model(
modelId=models[vender],
body=json.dumps(prompt)
)
content = json.loads(res['body'].read())
return content
3.2 벤더별 프롬프트 구조 비교
| 항목 | Claude | GPT | Gemma(Google) |
| 시스템 역할 | "system" 별도 키 | messages 내 role: system | converse API의 system 파라미터 |
| few-shot | messages 배열에 직접 삽입 | messages 배열에 직접 삽입 | content에 [{"text": ...}] 형태 |
| 응답 파싱 | content['content'][0]['text'] | content['choices'][0]['message']['content'] | res['output']['message']['content'][0]['text'] |
# Claude 응답 파싱
res['content'][0]['text']
# GPT 응답 파싱
res['choices'][0]['message']['content']
# Gemma(converse API) 응답 파싱
res['output']['message']['content'][0]['text']
Bedrock을 활용하면 동일 SDK에서 모델명만 교체하여 여러 LLM을 호출할 수 있음. 다만 프롬프트 구성 방식과 응답 파싱 구조가 모델별로 다르므로, 인터페이스 클래스로 추상화하는 설계가 권장됨. sklearn에서 어떤 알고리즘을 쓰든 fit()으로 학습하는 것과 같은 패턴.
4. 제로샷 · 원샷 · 퓨샷 프롬프트
LLM에게 예시를 얼마나 제공하느냐에 따라 결과 품질과 일관성이 달라짐.
4.1 유형 비교
| 유형 예시 | 개수 | 언제 쓰는가 |
| Zero-shot | 0 | 상식적 질문, 간단한 요약 |
| One-shot | 1 | 특정 포맷(JSON 등) 준수 필요 시 |
| Few-shot | 2~5 | 복잡한 분류, 특수한 규칙 적용 시 |
4.2 퓨샷 특징
- 초기 서비스 구축 단계에서 파인튜닝 없이 활용 가능
- 예시 품질이 높으면 파인튜닝 모델보다 더 좋은 성과를 내기도 함
- 일정한 품질의 결과물 획득이 목적 — 사내 데이터를 직접 파인튜닝에 사용하면 비용·보안 이슈가 있으나, few-shot으로 동일 효과를 얻을 수 있음
4.3 리뷰 감정 분류 — 퓨샷 실습
GPT
few_shot_prompt = [
{"role": "system", "content": "당신은 커피 고객 리뷰 분석가입니다. '긍정','부정','가격민감' 중 하나로 분류하세요."},
{"role": "user", "content": "일찍와서 핫초코 샀어요~ 맛있고 좋아요👍"},
{"role": "assistant", "content": "긍정"},
{"role": "user", "content": "직원이 인사를 않 해서 기분이 나빴습니다."},
{"role": "assistant", "content": "부정"},
{"role": "user", "content": "스페셜 음료는 맛있는데 매일 사 먹기엔 가격이 너무 부담스럽네요"},
{"role": "assistant", "content": "가격민감"},
]
Claude
# Claude는 system을 messages 밖 별도 키로 분리
prompt = {
"anthropic_version": "bedrock-2023-05-31",
"max_tokens": 100,
"system": "당신은 커피 고객 리뷰 분석가입니다. '긍정','부정','가격민감' 중 하나로 분류하세요.",
"messages": few_shot_prompt # role: system 제외한 배열
}
Gemma (Google)
# content 값을 [{"text": ...}] 형태로 변환 필요
change = lambda x: [{"text": x}]
few_shot_messages = [
{"role": "user", "content": change("일찍와서 핫초코 샀어요~ 맛있고 좋아요👍")},
{"role": "assistant", "content": change("긍정")},
...
]
# converse API 사용
res = bedrock.converse(
modelId=models['google'],
messages=final_messages,
inferenceConfig={"maxTokens": 100, "temperature": 0}
)
Bedrock 기준 Claude·Gemma가 응답이 빠르고, GPT가 상대적으로 느림. 벤더 직접 API 사용 시 GPT는 Azure에서 빠른 응답 가능.
5. LangChain — LLM 오케스트레이션
여러 모델을 단일 인터페이스로 다루고, 프롬프트 템플릿·체인·메모리를 통합 관리하는 오픈소스 프레임워크.
5.1 LangChain 개요
- 정의 — LLM 기반 AI 애플리케이션 개발을 돕는 오픈소스 오케스트레이션 프레임워크
- 핵심 구성 요소
- RAG — LLM이 모르는 지식을 검색 증강으로 제공, 프롬프트에 함께 전달
- Agent — LLM이 스스로 판단하고 행동, A2A 연동 가능
- Chain / Graph — 단방향(체인) 또는 순환(그래프) 워크플로우 구성
- Memory — 단기 기억(대화 맥락)과 장기 기억(벡터 DB)으로 구분
- LangSmith — 개발·디버깅·테스트·모니터링 통합 지원 (LLMOps)
5.2 프롬프트 템플릿 종류
| 클래스 | 용도 |
| PromptTemplate | 기본형, f-string / Jinja2 변수 치환 |
| ChatPromptTemplate | 대화형 모델용, system/human/ai 역할 구조 |
| FewShotPromptTemplate | 예시 리스트 + 접두사/접미사 기능 |
| FewShotChatMessagePromptTemplate | 실제 대화 스타일로 예시 주입 |
PromptTemplate — f-string
from langchain_core.prompts import PromptTemplate
input_prompt = PromptTemplate(
input_variables=['place', 'content'],
template="{place}에서 가장 {content} 놀이기구는?"
)
input_prompt.format(place='에버랜드', content='대기줄이 가장 긴')
PromptTemplate — Jinja2
input_prompt = PromptTemplate(
input_variables=['items', 'user_q'],
template_format='jinja2',
template='''
다음 예시를 참고하여 마지막 질문에 대한 답변을 제시해줘.
{% for item in items %}
Q: {{item.q}}
A: {{item.a}}
{% endfor %}
Q : {{user_q}}
A:
'''
)
ChatPromptTemplate
from langchain_core.prompts import ChatPromptTemplate
chat_template = ChatPromptTemplate.from_messages([
("system", "당신은 {style} 스타일의 고용관리 상담사입니다."),
("human", "저는 {name}입니다."),
("system", "네.. 반갑습니다."),
("human", "제 고민은 {topic}입니다. 조언해주세요."),
])
FewShotPromptTemplate
from langchain_core.prompts import FewShotPromptTemplate
examples = [
{"input": "높다", "output": "낮다"},
{"input": "빠르다", "output": "느리다"},
{"input": "밝다", "output": "어둡다"},
]
example_format = PromptTemplate.from_template("단어:{input}\n반대말:{output}")
few_shot_prompt = FewShotPromptTemplate(
examples=examples,
example_prompt=example_format,
prefix="다음 단어의 반대말을 알려줘.",
suffix="단어:{user_input}\n반대말:",
input_variables=['user_input']
)
서비스 형태에 따라 채팅 계열(ChatPromptTemplate), 일반 처리(PromptTemplate)를 구분하여 사용하는 것이 기본 원칙임.
6. Bedrock + LangChain 결합
LangChain의 `ChatBedrock`을 통해 모델과의 인터페이스를 통일하고, 파이프라인(`chain`)으로 프롬프트 → LLM → 응답을 연결함.
from langchain_aws import ChatBedrock
from langchain_core.prompts import ChatPromptTemplate
def run_bedrock_llm(model_id, user_query, style):
llm = ChatBedrock(
client=bedrock_client,
model_id=models[model_id],
model_kwargs={"max_tokens": 1024, "temperature": 0.7}
)
prompt = ChatPromptTemplate.from_messages([
('system', '당신은 {style} 스타일의 20년차 초고수 투자자입니다.'),
('human', '{input}')
])
# chain 연결 : 프롬프트 구성 -> LLM 호출 -> 응답
chain = prompt | llm
res = chain.invoke({"input": user_query, "style": style})
return res.content # 랭체인 통해 출력 형식 통일
LangChain의 핵심은 파이프 연산자(|) 로 표현되는 체인 구조임. prompt | llm | output_parser 형태로 확장하면 응답 파싱까지 통일된 흐름으로 처리 가능. 어떤 모델을 써도 chain.invoke()로 호출하는 인터페이스가 동일하여, sklearn의 fit() 패턴처럼 모델 교체가 간편해짐.
7. 요약
| 주제 | 핵심 내용 |
| 프롬프트 공통 구성 | Role + Context + Task + Format 4요소 |
| 모델별 특화 | Claude(XML), GPT(Few-Shot), Gemini(검색 연동) |
| 퓨샷 프롬프트 | 파인튜닝 없이 고품질 분류·생성 가능 |
| Bedrock | 단일 SDK로 다수 모델 호출, 응답 파싱 구조는 모델별 상이 |
| LangChain | 프롬프트 템플릿·체인·메모리·에이전트 통합 오케스트레이션 |
| 설계 원칙 | 모델별 인터페이스 추상화 + Pydantic으로 응답 구조 통일 |
LLM 활용의 핵심은 "어떤 모델이 더 좋은가"가 아니라, "어떤 모델의 특성에 맞게 프롬프트를 설계하는가"임. 공통 구성 4요소를 기반으로 모델 특화 전략을 레이어로 얹는 구조가 실무에서 가장 안정적인 접근법이며, LangChain은 이 과정을 코드 레벨에서 추상화하는 도구임.
'SK플래닛 ai활용 데이터엔지니어 과정 2기 > ML & DL' 카테고리의 다른 글
| LangGraph 1 - 상태 그래프 기초 (0) | 2026.06.02 |
|---|---|
| LLM 2 - 서비스 구축 실습 (0) | 2026.05.29 |
| DL 6 - 트랜스포머 기반 학습 모델 가져오기 (0) | 2026.05.27 |
| DL 5 - NLP 실습 (0) | 2026.05.27 |
| DL 4 - NLP 모델 (0) | 2026.05.26 |