오늘은 bedrock을 이용한 llm 모델 불러오기 실습을 진행하였고
bedrock으로 불러온 각 모델들마다 다른 프롬프트의 특징과 어떤식으로 사용하면 좋은지 등등의 실습을 진행하였다.
개요
- LLM 제품, 특징 (노션)
- https://www.notion.so/LLM-2cd2e93ba716804ebb65dc013887b4da
Gemini API 키 연동확인

bedrock을 사용하기 전 gemini부터 먼저 해본다. 키를 받아오는 과정은 위의 노션으로 들어가면 있다.
키를 받아온 후 객체를 생성해준다.

GenerateContentResponse(
automatic_function_calling_history=[],
candidates=[
Candidate(
content=Content(
parts=[
Part(
text="""AWS 가입 후 무료 쿼터 종료 및 유료 전환 시 로그인 루프에 빠지는 문제는 종종 발생하는 상황입니다. 주로 브라우저의 캐시/쿠키 문제, AWS 세션 관리 문제 또는 계정 관련 특정 설정(MFA, 루트 vs IAM 사용자 혼동 등) 때문에 발생합니다.
다음 단계를 따라 문제 해결을 시도해 보세요.
---
### AWS 로그인 루프 해결 단계
**1. 브라우저 관련 기본 조치 (가장 흔한 원인)**
* **캐시 및 쿠키 삭제:**
* 현재 사용 중인 브라우저의 캐시와 쿠키를 모두 삭제한 후 다시 시도해 보세요. 손상된 세션 정보가 남아있을 때 이 문제가 발생할 수 있습니다.
* **Chrome:** 설정 > 개인 정보 보호 및 보안 > 인터넷 사용 기록 삭제 > 시간 범위 "전체 기간"으로 설정 후 "쿠키 및 기타 사이트 데이터", "캐시된 이미지 및 파일" 선택 후 삭제.
* **Firefox:** 설정 > 개인 정보 및 보안 > "쿠키 및 사이트 데이터" 섹션에서 "데이터 삭제" 클릭.
* **시크릿/개인 정보 보호 모드 사용:**
* 새 시크릿 모드(Chrome) 또는 개인 정보 보호 모드(Firefox/Edge) 창을 열어 로그인해 보세요. 이 모드에서는 확장 프로그램이나 기존 캐시/쿠키의 영향을 받지 않습니다.
* **다른 웹 브라우저 사용:**
* Chrome을 사용 중이었다면 Firefox나 Edge 등으로, 혹은 그 반대로 다른 브라우저를 사용하여 로그인해 보세요.
* **브라우저 확장 프로그램 비활성화:**
* 간혹 VPN, 광고 차단기, 보안 관련 브라우저 확장 프로그램이 AWS 콘솔의 정상적인 작동을 방해할 수 있습니다. 모든 확장 프로그램을 일시적으로 비활성화한 후 다시 로그인해 보세요.
**2. AWS 계정 관련 특정 조치**
* **루트 사용자 vs IAM 사용자 확인:**
* 무료 쿼터 종료 및 유료 전환은 주로 계정 전체 설정(결제 정보 등)과 관련이 있으므로, **루트 사용자(Root User)**로 로그인하는 것이 중요합니다.
* **루트 사용자 로그인 링크:** `https://console.aws.amazon.com/console/home` (이메일 주소로 로그인)
* IAM 사용자 계정으로 로그인하려고 시도하고 있다면, 계정 ID나 별칭, 그리고 IAM 사용자 이름으로 로그인하게 됩니다. 혹시 IAM 사용자 로그인을 시도 중이었다면, 루트 사용자로 전환하여 로그인해 보세요.
* 로그인 페이지에서 "Root user"를 선택했는지, "IAM user"를 선택했는지 다시 확인해 주세요.
* **MFA (다단계 인증) 문제:**
* MFA가 활성화되어 있는데, MFA 장치(가상 MFA 앱, 물리적 토큰)에 문제가 있거나 제대로 동기화되지 않은 경우 로그인 루프처럼 보일 수 있습니다. MFA 코드를 정확히 입력하고 있는지 확인해 주세요.
* 만약 MFA 장치를 분실했거나 접근할 수 없다면, 이 단계에서는 스스로 해결하기 어렵고 AWS Support의 도움이 필요합니다.
* **결제 정보 확인:**
* 로그인에 성공하더라도, 유료 전환이 되려면 유효한 결제 수단(신용카드 등)이 등록되어 있어야 합니다. 로그인 후 "Billing and Cost Management" 대시보드로 이동하여 결제 정보가 최신 상태인지 확인하고 필요한 경우 업데이트하세요.
* (이 단계는 로그인 후 가능하지만, 혹시 로그인 자체는 되는데 결제 화면에서 문제가 있다면 이 부분을 확인해야 합니다.)
**3. 네트워크 환경 확인**
* **VPN/프록시 사용 중단:**
* VPN이나 프록시 서버를 통해 인터넷에 접속 중이라면, 이를 끄고 일반적인 인터넷 연결로 다시 시도해 보세요. 특정 네트워크 설정이 AWS 접속을 방해할 수 있습니다.
* **인터넷 연결 상태 확인:**
* 인터넷 연결이 불안정하거나 느린 경우에도 웹 페이지 로드 오류가 발생할 수 있습니다.
**4. AWS Support에 문의 (최후의 수단)**
위의 모든 방법을 시도했는데도 여전히 로그인 루프에 갇힌다면, AWS Support에 문의해야 합니다.
* **로그인 없이 AWS Support 문의하기:**
AWS는 계정에 로그인할 수 없는 사용자를 위해 별도의 지원 채널을 제공합니다.
1. **AWS Support 문의 페이지로 이동:** `https://aws.amazon.com/ko/contact-us/`
2. 페이지 하단에 **"로그인할 수 없는 경우 계정 지원을 받으려면 여기를 클릭하세요."** 또는 **"계정에 로그인할 수 없는 경우"** 링크를 찾아서 클릭합니다.
3. 이메일 주소, 전화번호 등 연락처 정보를 입력하고 문제 상황을 자세히 설명하여 문의를 제출합니다. 이때, "로그인 시 무한 루프에 빠진다", "무료 쿼터 종료 후 유료 전환을 위해 로그인 시도 중 발생했다" 등을 명확히 기재하는 것이 좋습니다.
---
**가장 먼저 시도해 볼 것:**
1. **사용 중인 브라우저의 캐시와 쿠키를 모두 삭제.**
2. **새 시크릿(또는 개인 정보 보호) 모드 창을 열어 루트 사용자 이메일과 비밀번호로 로그인 시도.**
이 두 가지 방법이 가장 일반적인 해결책입니다. 문제가 해결되시길 바랍니다!"""
),
],
role='model'
),
finish_reason=<FinishReason.STOP: 'STOP'>,
index=0
),
],
model_version='gemini-2.5-flash',
response_id='hK5DabCsLv6v_uMP__31kAQ',
sdk_http_response=HttpResponse(
headers=<dict len=10>
),
usage_metadata=GenerateContentResponseUsageMetadata(
candidates_token_count=1241,
prompt_token_count=40,
prompt_tokens_details=[
ModalityTokenCount(
modality=<MediaModality.TEXT: 'TEXT'>,
token_count=40
),
],
thoughts_token_count=1301,
total_token_count=2582
)
)
코랩에서 제미나이 모델을 불러와서 사용하였다
프롬프트 개요
- 정의
- 대규모 언어 모델(LLM)이 사용자가 원하는 최적의 결과를 생성하도록, 자연어로된 프럼프트(명령어/질문)를 설계하고, 최적화 하는 기술/방법론
- 구성 (구성비는 가변적일 수 있음)
- 기본/공통 구성 : 90% 비중
- - 페르소나 (Role:역활)
- 너는 전문 바리스타야
- 너는 전문 마케터야
- 등등 역활을 부여/아이덴티티를 부여
- 배경/상황/환경 (Context)
- 현재 가진 자산으로 은퇴 자금을 설계하려고 해.
- 구체적인 배경에 대한 정보 제공
- (명확한)지시 (Task)
- 향후 10년간 수행할 은퇴 자금 설계 계획에 대한 초안을 작성해줘
- 구체적 요쳥/요구
- 출력 형식 지정/제약 조건 (Format/Constraints)
- 제약
- 간단하게, 500자 이내로
- 존칭/반말
- 포맷
- 표로 정리해줘
- PDF등 - 모델별 특화 구성 : 10% 비중
- claude(클로드)
- 구조화 구성을 추천
- 지시사항등 XML태그 형식빌려서 섹션 구분하면 좋은 결과 획득 가능함.
- 서비스 개념에서는 백엔드에서 세팅해서 처리 -> 고객에게는 태그로 감쌀 콘텐츠를 유도하면 됨
- 논리적, 긴 글 적절
- GPT
- 대화형 최적화 -> 딱딱한 지시는 효율성 (결과물) 떨어짐
- 한번에 많이 가는것보다 단계별 (STEP) 결과를 유도하는게 유리
- few-shot 프롬프트 사용
- 몇 개의 예시를 제공
- 백그라운드 쪽에서 few-shot 계속 삽입
- Gemini
- 구글 검색(증강) 연동
- 팩트 체크, 창의성 정보
- 구글 검색(증강) 연동
- claude(클로드)
프롬프트 예시
- 주제 (마케팅 관련 이메일 작성)
- 신제품 출시
- 텀블러 마케팅 이메일 작성
- 공통 프롬프트 구성
- 최적의 결과물을 얻기 위한 프롬프트 구성 진행 -> 템플릿 베이스로 백엔드에서 사용자의 입력에 맞춰 최적으로 재구성됨
- 사전에 직접 프롬프트를 구성
# 역할 (role) - 너는 마케팅 회사에서 인정받고 팀장까지 올라간 전문 마케터야. # 배경 (context) - 이번에 텀블러 회사에서 `24시간 얼음이 녹지 않는 셀럽형 신제품 텀블러`가 출시되어서 우리 회사에 마케팅 제의를 넣었고 너희 팀에 그 업무가 지정됐어, 고객들에게 신제품 텀블러 마케팅 이메일을 작성해서 전송하려고 해. 타겟 고객은 하루종일 아이스커피를 달고 사는 20대 직장인이야. # 지시 (task) - 신규 고객들에게 직관적으로 제품에 흥미가 생기도록 후킹하는 이메일을 전송하려 하니 타겟 고객에게 보낼 홍보용 이메일 초안을 작성해줘. 고객은 이 이메일을 읽고 `구매하기`버튼을 누르고싶게 만들어야 해. # 제약조건 (constaints), 포맷 미지정 (markdown 형태임) 1. 톤 앤 매너 : 너무 딱딱하지 않게 , 유머러스하게, 위트있게 2. 형식 : 도입부 - 텀블러의 장점(4가지포인트) - 마무리 및 구매유도 3. 분량 : 400자 이내
claude 모델 특화
# 백엔드에서 개발자가 동적 구성
# xml태글르 이용한 명확한 구획 설정
<role>
너는 마케팅 회사에서 인정받고 팀장까지 올라간 전문 마케터야.
<context>
<task>
<constaints>
GPT 모델 특화
# few shot 제시
'점심시간이 되면 아이스아메리카노가 미지근하고 연해져, 이제 그 고통을 끝낼 시간이야'
이 카피라이터와 비슷하게 구성해줘
Gemini 특화
# 검색 기능 고려, 트렌드, 구체적 정보 포함, 반영하라는 뉘앙스,지시
# 검색 => 원하는 레벨로 => 창작
현재 한국 20대 직장인들의 오피스 아이템 트렌드를 검색하여 이 텀블러가 왜 필수템인지 설명하는 문구를 도입부에 자연스럽게 녹여줘.
프롬프트 모델별 적용
공통사항
# 공통사항 구성
!pip install -q boto3
import boto3
import json
import os
from dotenv import load_dotenv
import json
import os
from dotenv import load_dotenv
# 환경변수 로드
load_dotenv()
if not os.getenv('AWS_BEARER_TOKEN_BEDROCK'):
os.environ['AWS_BEARER_TOKEN_BEDROCK']=userdata.get('AWS_BEARER_TOKEN_BEDROCK')
# 리전
REGION = 'eu-west-2' # 런던
# LLM 모델 ID
openai_id = 'openai.gpt-oss-120b-1:0'
claude_id = 'anthropic.claude-3-sonnet-20240229-v1:0'
gemma_id = 'google.gemma-3-27b-it'
# bedrock 클라이언트 객체
bedrock = boto3.client(service_name='bedrock-runtime',
region_name = REGION)
# 모델id 쉽게 뽑는 함수
'''
벤더 혹은 모델명으로 필요한 bedrock에 설정된 모델 id 획득
'''
def get_model_id(id='anthropic'):
if id == 'openai': return openai_id
# elif id == 'anthropic': return claude_id
elif id == 'google' : return gemma_id
return claude_id # 기본값으로 적용
get_model_id()
GPT
from botocore import model
# 1. prompt
# GPT 프롬프트는 서술형, 섹션 구분이 모호하므로 글 자체로 섹션을 잘 설정
prompt = {
'max_tokens' : 1000, # 최대 1000토큰으로 응답값 구성
'temperature' : 0.7, # 0 : 정답만 감, 0 -> 1.0 창작성 높아짐
'messages' : [ # 프롬프트 들어가는 내용
# 0. 공통 프롬프트에서 일단 필요한 부분만 사용
# 1. 역할 부여 (role, 페르소나)
{
"role":'system', # 페르소나 지정
'content':'너는 마케팅 회사에서 인정받고 팀장까지 올라간 유머러스있고 위트있는 전문 마케터야.'
},
# 2. few-shot prompt 기반 => 샘플 제시
{
"role":'user',
'content':'셀럽형 신체품 텀블러 홍보용 이메일 초안 문구 작성해줘'
},
# 2-1. 결과물에 대한 샘플 제시
{ "role":'assistant',
'content':'오전에 넣은 얼음, 퇴근할 때까지 살아있다면?'
},
# 3. 실제 요청할 작업 지시(Task), 편의상 배경 지식을 적절히 섞었다.
{
"role":'user',
'content':'''
# 배경
이번에 텀블러 회사에서 `24시간 얼음이 녹지 않는 셀럽형 신제품 텀블러`가 출시되어서
우리 회사에 마케팅 제의를 넣었고 너희 팀에 그 업무가 지정됐어, 고객들에게
신제품 텀블러 마케팅 이메일을 작성해서 전송하려고 해.
# 타겟
타겟 고객은 하루종일 아이스커피를 달고 사는 20대 직장인이야.
# 지시
신규 고객들에게 직관적으로 제품에 흥미가 생기도록 후킹하는 이메일을 전송하려 하니
타겟 고객에게 보낼 홍보용 이메일 초안을 작성해줘.
고객은 이 이메일을 읽고 `구매하기`버튼을 누르고싶게 만들어야 해.
'''
}
]
}
# 2. 모델 호출 => 추론/생성 등 작업 요청 => 응답
res = bedrock.invoke_model(
modelId = get_model_id('openai'),
body = json.dumps( prompt )
)
# 3. 응답 파싱 => 결과 출력
body = json.loads( res['body'].read() )
print( body )
GPT의 특징은 딕셔너리의 형태로 샘플과 요청 정보 등을 제시해주는것이다.
{'choices': [{'finish_reason': 'length', 'index': 0, 'logprobs': None, 'message': {'content': '<reasoning>The user wants a promotional email draft for a new tumbler that keeps ice from melting for 24 hours, targeting 20-something office workers who love iced coffee all day. The email should hook them and have a "Buy Now" button.\n\nWe need to produce email copy. Should be witty, humorous, marketing style, with subject line, preheader, body, CTA, maybe bullet points, social proof, limited-time offer.\n\nWe must follow policy; no disallowed content. It\'s okay.\n\nWe can produce in Korean, as user wrote Korean. Provide subject line, preview text, body with headings, product benefits, maybe a limited-time discount, CTA button.\n\nWe should ensure it\'s not overly deceptive, but it\'s promotional. That\'s fine.\n\nLet\'s produce.</reasoning>**📧 마케팅 이메일 초안 – “24시간 얼음이 녹지 않는 셀럽형 텀블러”** \n\n---\n\n### 1️⃣ 메일 헤더 \n**제목 (Subject)** \n> ❄️ “아이스 커피, 하루 종일 시원하게!” 24시간 얼음 유지 텀블러, 지금 바로 만나보세요 \n\n**프리헤더 (Pre‑header)** \n> “아침에 넣은 얼음이 퇴근 시간까지 살아있다면? 당신의 아이스 커피가 변합니다.” \n\n---\n\n### 2️⃣ 인사말 & Hook \n\n> **안녕하세요, [고객 이름]님!** \n> \n> 하루 종일 사무실에 갇혀도, **아이스 커피 한 모금**만큼은 시원하게 마시고 싶지 않으세요? \n> \n> **‘24시간 얼음이 녹지 않는다’**는 셀럽들이 애용하는 신제품 텀블러가 이제 여러분 손에! \n\n> **💡 상상해 보세요** \n> * 09:00에 넣은 얼음이 18:00에 그대로— \n> * 회의실, 점심, 퇴근길까지 **한결같은 시원함** \n> * “이거 진짜 셀럽템이네!” 라는 눈빛을 사로잡는 디자인 \n\n---\n\n### 3️⃣ 제품 핵심 포인트 (시각적 아이콘 + 짧은 문구) \n\n| ✅ | **핵심 포인트** | **왜 중요한가?** |\n|---|----------------|-------------------|\n| <img src="https://img.icons8.com/ios-filled/20/000000/snowflake.png"/> | **24시간 얼음 유지** | 아침부터 퇴근까지 온종일 시원함 |\n| <img src="https://img.icons8.com/ios-filled/20/000000/diamond.png"/> | **셀럽‑스타일 디자인** | 인스타그램 피드에 딱! 트렌디함 |\n| <img src="https://img.icons8.com/ios-filled/20/000000/leaf.png"/> | **친환경 스테인리스** | BPA 프리, 재사용으로 지구도 시원하게 |\n| <img src="https://img.icons8.com/ios-filled/20/000000/lock.png"/> | **누수·땜질 걱정 NO** | 1년 보증, 언제든 교환 가능 |\n| <img src="https://img.icons8.com/ios-filled/20/000000/discount.png"/> | **한정 15% 할인 + 무료 배송** | 오늘만! 바로 구매하면 혜택 적용 |\n\n---\n\n### 4️⃣ 스토리텔링 (짧은 고객 후기) \n\n> **“아침에 뿌린 얼음이 퇴근때까지 그대로라니, 이건 마법이죠!”** – 김민수, 27세 마케팅 대리 \n> \n> **“디자인이 너무 예뻐서 회식 자리에서도 눈에 띄었어요. 이제는 아이스 커피가 내 필수 아이템!”** – 이지은, 24세 UX 디자이너 \n\n---\n\n### 5️⃣ 제한된 혜택 & 긴박감 \n\n> **⚡️ 오늘만!** \n> - **15% 할인 쿠폰** : `ICE24NOW` (장바구니에 입력) \n> - **무료 배송** + **30일 무조건 반품** \n> - **선착순 200명**에게는 **셀럽 사인 스티커** 증정 \n\n> **⏰ 마감:** 오늘 23:59 까지, 놓치면 다음 기회는 언제일지 모릅니다! \n\n---\n\n### 6️⃣ CTA (구매하기 버튼)', 'refusal': None, 'role': 'assistant'}}], 'created': 1766043632, 'id': 'chatcmpl-0cf95fec-6b44-4a9c-bee7-4bf88e85216a', 'model': 'openai.gpt-oss-120b-1:0', 'object': 'chat.completion', 'service_tier': 'default', 'usage': {'completion_tokens': 1000, 'prompt_tokens': 345, 'total_tokens': 1345}}
위 코드를 돌린뒤 나온 결과값이다. 추후 딕셔너리의 형태에 따라 키와 값이 달라지기 때문에 원하는 값만 추출하는 제어문을 통해서 결과값을 추출해낸다.
# 4. 응답값중 세부값 추출
if 'choice' in body:
print(body['choice'][0]['message']['content'])
elif 'content' in body:
print(body['content'])
else:
print(body)
<reasoning>The user wants a promotional email draft for a new tumbler that keeps ice from melting for 24 hours, targeting 20-something office workers who love iced coffee all day. The email should hook them and have a "Buy Now" button.
We need to produce email copy. Should be witty, humorous, marketing style, with subject line, preheader, body, CTA, maybe bullet points, social proof, limited-time offer.
We must follow policy; no disallowed content. It's okay.
We can produce in Korean, as user wrote Korean. Provide subject line, preview text, body with headings, product benefits, maybe a limited-time discount, CTA button.
We should ensure it's not overly deceptive, but it's promotional. That's fine.
Let's produce.</reasoning>**📧 마케팅 이메일 초안 – “24시간 얼음이 녹지 않는 셀럽형 텀블러”**
---
### 1️⃣ 메일 헤더
**제목 (Subject)**
> ❄️ “아이스 커피, 하루 종일 시원하게!” 24시간 얼음 유지 텀블러, 지금 바로 만나보세요
**프리헤더 (Pre‑header)**
> “아침에 넣은 얼음이 퇴근 시간까지 살아있다면? 당신의 아이스 커피가 변합니다.”
---
### 2️⃣ 인사말 & Hook
> **안녕하세요, [고객 이름]님!**
>
> 하루 종일 사무실에 갇혀도, **아이스 커피 한 모금**만큼은 시원하게 마시고 싶지 않으세요?
>
> **‘24시간 얼음이 녹지 않는다’**는 셀럽들이 애용하는 신제품 텀블러가 이제 여러분 손에!
> **💡 상상해 보세요**
> * 09:00에 넣은 얼음이 18:00에 그대로—
> * 회의실, 점심, 퇴근길까지 **한결같은 시원함**
> * “이거 진짜 셀럽템이네!” 라는 눈빛을 사로잡는 디자인
---
### 3️⃣ 제품 핵심 포인트 (시각적 아이콘 + 짧은 문구)
| ✅ | **핵심 포인트** | **왜 중요한가?** |
|---|----------------|-------------------|
| <img src="https://img.icons8.com/ios-filled/20/000000/snowflake.png"/> | **24시간 얼음 유지** | 아침부터 퇴근까지 온종일 시원함 |
| <img src="https://img.icons8.com/ios-filled/20/000000/diamond.png"/> | **셀럽‑스타일 디자인** | 인스타그램 피드에 딱! 트렌디함 |
| <img src="https://img.icons8.com/ios-filled/20/000000/leaf.png"/> | **친환경 스테인리스** | BPA 프리, 재사용으로 지구도 시원하게 |
| <img src="https://img.icons8.com/ios-filled/20/000000/lock.png"/> | **누수·땜질 걱정 NO** | 1년 보증, 언제든 교환 가능 |
| <img src="https://img.icons8.com/ios-filled/20/000000/discount.png"/> | **한정 15% 할인 + 무료 배송** | 오늘만! 바로 구매하면 혜택 적용 |
---
### 4️⃣ 스토리텔링 (짧은 고객 후기)
> **“아침에 뿌린 얼음이 퇴근때까지 그대로라니, 이건 마법이죠!”** – 김민수, 27세 마케팅 대리
>
> **“디자인이 너무 예뻐서 회식 자리에서도 눈에 띄었어요. 이제는 아이스 커피가 내 필수 아이템!”** – 이지은, 24세 UX 디자이너
---
### 5️⃣ 제한된 혜택 & 긴박감
> **⚡️ 오늘만!**
> - **15% 할인 쿠폰** : `ICE24NOW` (장바구니에 입력)
> - **무료 배송** + **30일 무조건 반품**
> - **선착순 200명**에게는 **셀럽 사인 스티커** 증정
> **⏰ 마감:** 오늘 23:59 까지, 놓치면 다음 기회는 언제일지 모릅니다!
---
### 6️⃣ CTA (구매하기 버튼)
들어간 샘플을 보고 이메일 초안을 제공받았다. 마크다운 리더에 넣으면 더 제대로 볼 수 있다.
Claude
# 1. prompt
# claude, xml을 이용한 섹션 구분
prompt_detail = '''
<role>
너는 마케팅 회사에서 인정받고 팀장까지 올라간 유머러스있고 위트있는 전문 마케터야.
</role>
<context>
제품 : `24시간 얼음이 녹지 않는 셀럽형 신제품 텀블러`가 출시
타겟 : 하루종일 아이스커피를 달고 사는 20대 직장인이야.
</context>
<instruction>
타겟을 위한 직관적으로 제품에 흥미가 생기도록 후킹하는 이메일을 전송하려 하니
타겟 고객에게 보낼 홍보용 이메일 초안을 작성해줘.
고객은 이 이메일을 읽고 `구매하기`버튼을 누르고싶게 만들어야 해.
</instruction>
<constaints>
톤 앤 매너 : 너무 딱딱하지 않게 , 유머러스하게, 위트있게
형식 : 도입부 - 텀블러의 장점(4가지포인트) - 마무리 및 구매유도
</constaints>
'''
prompt = {
"anthropic_version": "bedrock-2023-05-31",
"max_tokens": 1000,
"messages": [
{
"role": "user",
"content": prompt_detail
}
]
}
# 2. 모델 호출 => 추론/생성등 작업 요청 => 응답
res = bedrock.invoke_model(
modelId = get_model_id(), # claude
body = json.dumps( prompt )
)
# 3. 응답 파싱 => 결과 출력
body = json.loads( res['body'].read() )
print( body )
클라우드는 xml태그를 이용한 명확한 구획 설정이 포인트이다.
프롬프트에 xml태그를 이용해서 role, context 등등 다양한 정보를 제공해주고 결과값을 제공받을 수 있다.
실제 받아낼 정보를 호출하는데에도 약간 다른 디테일들이 있다.
print(body['content'][0]['text'])
안녕하세요 20대 얼죽아들! 보통날 새벽 출근길에 쌀쌀한 공기를 제대로 느껴보셨나요? 아니면 더운 여름날, 땀에 절여 아이스커피 한 모금 머금었을 때의 환희를 기억하고 계시나요?
이런 피나는 순간들을 선사해드리려 합니다. 바로 신제품 셀럽형 텀블러를 소개할게요!
1. 하루종일 얼음이 녹지 않는 최고의 보냉력! 여름엔 차가운 아이스커피를, 겨울엔 뜨거운 커피를 언제 어디서나 드실 수 있죠.
2. 언제 어디서나 커피를 마시고 싶을 때 갖고 다닐 수 있는 실용성! 출퇴근길, 야외 데이트 코스 등 어디에서든 한 손에 쥐고 다닐 수 있습니다.
3. 세련된 디자인으로 당신의 멋진 스타일을 완성해드립니다. 고급스러운 외관으로 휴대성과 스타일을 모두 잡았죠.
4. 무엇보다 텀블러 이용시 일회용컵을 줄일 수 있어 친환경적이에요! 지구를 살리는 의미있는 소비 습관이죠.
이렇게 실용적이면서도 스타일리시한 셀럽 텀블러로 일상을 업그레이드해보세요. 지금 바로 주문창을 클릭하고 구매 버튼만 누르시면 됩니다!
이렇게 모델이 다르면 프롬프트가 비슷해도 다른 결과값이 나온다.
Gemini or Gamma
# gemma
# 1. prompt
# claude, xml을 이용한 섹션 구분
prompt_detail = '''
당신은 논리적이고 설득력 있는 20년 차 전문 카피라이터입니다.
[요청사항]
하루 종일 커피를 마시는 20대 직장인을 위한
24시간 얼음이 녹지 않는 셀럽형 텀플러 홍보용 이메일 초안을 작성하세요.
고객은 이 이메일을 읽고 '구매하기' 버튼을 누르고 싶게 만들어야 합니다.
[특별지시]
한국 직장인들에게 유행하는 '오피스 아이템' 트렌드를 반영하여
단순한 기능 나열이 아닌, 이 텀블러가 왜 '요즘 직장인들의 필수템'인지
트렌드와 엮어서 도입부를 작성하세여
톤앤매너: 전문적이지만 너무 딱딱하지 않게
형식: 도입부 - 텀플러의 장점(4가지 포인트) - 마무리 및 구매유도
'''
prompt = {
"max_tokens": 1000,
"messages": [
{
"role": "user",
"content": prompt_detail
}
],'temperature':0.7
}
# 2. 모델 호출 => 추론/생성등 작업 요청 => 응답
res = bedrock.invoke_model(
modelId = get_model_id('google'), # claude
body = json.dumps( prompt )
)
# 3. 응답 파싱 => 결과 출력
body = json.loads( res['body'].read() )
print( body )
제미나이 등은 검색 기반이기 때문에 검색 기능을 고려하여 트렌드, 구체적 정보등을 요청하는데에 있어 장점이 있다.
이러한 요즘 트렌드 등 사항들을 반영하라는 지시를 내리면 더욱 자세한 정보를 받을 수 있다.
# 4. 응답값중 세부값 추출
if 'choices' in body:
print(body['choices'][0]['message']['content'])
elif 'content' in body:
if isinstance(body['content'],list):
print(body['content'][0]['text']) # claude 방식
else:
print(body['content'])
else:
print(body)
## 제목: ☕️ 퇴근까지 시원하게! 24시간 얼음 보존, 당신의 워라밸을 책임질 텀블러
**[본문]**
안녕하세요. 바쁜 일상 속에서도 스타일을 놓치지 않는 당신께, 20년 차 카피라이터가 자신 있게 추천하는 특별한 텀블러를 소개합니다.
**✨ 요즘 직장인들의 필수템, '힙'한 오피스 라이프를 완성하다 ✨**
요즘 직장인들은 단순히 '일'만 하는 공간이 아닌, '나'를 위한 공간으로서의 '오피스'에 대한 관심이 높아지고 있습니다. 개인의 취향을 반영한 힙한 오피스 아이템으로 개성을 드러내고, 워라밸을 위한 투자도 아끼지 않죠. 텀블러 역시 단순한 물통을 넘어, 당신의 스타일과 라이프스타일을 보여주는 중요한 아이템으로 자리 잡았습니다. 하지만 몇 시간 지나지 않아 미지근해지는 커피, 얼음물이 금방 녹아 아쉬움을 느끼셨던 적 없으신가요?
이제 더 이상 망설이지 마세요. 당신의 워라밸을 완벽하게 책임질, 혁신적인 텀블러를 만나보세요.
**🧊 왜 이 텀블러가 당신의 '인생템'이 될까요?**
1. **24시간 얼음 보존 기술:** 뜨거운 여름에도, 지치고 힘든 야근에도, 24시간 동안 얼음이 녹지 않는 놀라운 보온/보냉 효과를 경험하세요. 아침에 넣은 얼음이 퇴근 시간까지 그대로! 시원한 음료를 오랫동안 즐길 수 있습니다.
2. **스타일리시한 디자인 & 다채로운 컬러:** 당신의 개성을 표현할 수 있는 세련된 디자인과 트렌디한 컬러를 만나보세요. 어떤 스타일의 오피스룩에도 잘 어울리며, 주변의 시선을 사로잡을 것입니다. (컬러 예시: 모던 블랙, 핑크 코랄, 세련된 네이비 등)
3. **견고한 내구성 & 편리한 휴대성:** 고품질 스테인리스 스틸 소재로 제작되어 긁힘이나 충격에 강하며, 오래도록 안심하고 사용할 수 있습니다. 또한, 가볍고 슬림한 디자인으로 가방에 쏙 들어가 휴대성이 뛰어납니다.
4. **환경을 생각하는 지속가능성:** 플라스틱 컵 사용을 줄여 환경 보호에 동참하고, 건강에도 좋은 텀블러를 사용하세요. 당신의 작은 실천이 더 나은 미래를 만듭니다.
**🎁 지금 바로 경험하세요!**
더 이상 미지근한 커피, 녹아버린 얼음물에 아쉬움을 느끼지 마세요. 당신의 워라밸을 책임지고, 스타일을 완성할 이 텀블러를 지금 바로 만나보세요!
**[구매하기]** (버튼)
**✨ 특별 혜택 ✨**
* 지금 구매하시면 무료 배송!
* 구매 고객 전원에게 고급 코스터 증정!
감사합니다.
[회사명] 드림.
힙, 워라밸,인생템 등 기존에 없던 정보들이 추가되었다
LLM으로부터 원하는 결과를 얻는 방법 - 중간 결론
- step 1
- 여러번의 테스트를 통해서 완성된 프롬프트(가장 안정적으로 결과물을 뽑아주는 구성)
- step 2 (미진행)
- 채팅등 사용자로부터 자연스럽게 프롬프트에 세팅될 값들을 획득해야함
- 질의등등 답변 획득
- step 3 (미진행)
- 사용자의 답변들을 프롬프트 템플릿(형식)에 세팅해서 개인화된 완성된 프롬프트를 구성하여 LLM에 질의
- step 4 (미진행)
- 결과 파싱 후 다음 task 연결
제로샷 - 원샷 - 퓨샷 프롬프트
- 비교유형예시개수언제 쓰는가?
Zero-shot 0 "상식적인 질문, 간단한 요약" One-shot 1 특정 포맷(JSON 등) 준수 필요 시 Few-shot 2-5 "복잡한 분류, 특수한 규칙 적용 시" - 퓨샷 특징
- 초기 서비스 구축/서비스 단계
- few-shot 구성을 잘 하면, 고비용(데이터 구축, 학습시간, 시간)의 파인튜닝한 모델을 사용하는것보다 훨씬 효울적임
- 서비스 안정화 fwe-shot 자동화 적용
- 프롬프트 구성시 강제로 few-shot을 적용하여 예시를 넣어서 응답의 퀄리티 보장
- 초기 서비스 구축/서비스 단계
리뷰 긍부정 분석 - GPT
- 이진분류
- 사내 데이터를 이용한 파인튜닝 X
- few-shot으로 예시를 제시하여 프롬프트진행
from botocore import model
# 1. prompt
few_shot_message = [
# role
{
'role' : 'system',
'content': '당신은 커피 고객 리뷰 분석기입니다. 리뷰를 `긍정`, `부정`, `가격민감`,중 하나로 분류하세요'
},
# 긍정예시
{'role' : 'user', 'content': '일찍와서 핫초코 샀어요~ 사람이 많아요~ 출근길이라 그런가봐요~ 그래도 맛있고 좋아요'},
{'role' : 'assistant', 'content': '긍정'},
# 부정예시
{'role' : 'user', 'content': '직원이 인사를 안해서 기분이 나빴습니다'},
{'role' : 'assistant', 'content': '부정'},
# 가격민감 예시
{ 'role' : 'user', 'content': '스페셜 음료는 맛은 있는데 매일 사먹기엔 가격이 너무 부담스럽네'},
{ 'role' : 'assistant', 'content': '가격민감'},
]
# 판단을 받고싶은 리뷰
target_review = '메가커피의 가성비는 인정해요'
def predict_llm_gpt(target_review):
# 2. 모델 호출 => 추론/생성 등 작업 요청 => 응답
# 메세지 최종본
final_message = few_shot_message + [{
"role" : "user",
"content" : target_review,
}]
# 프롬프트 최종본
prompt = {
'temperature' : 0, # 다중분류 형태 -> 창의성 x
'messages' : final_message
}
res = bedrock.invoke_model(
modelId = get_model_id('openai'),
body = json.dumps( prompt )
)
# 3. 응답 파싱 => 결과 출력
body = json.loads( res['body'].read() )
results = None
if 'choice' in body:
results = body['choice'][0]['message']['content']
elif 'content' in body:
results = body['content']
else:
results = body
return results
predict_llm_gpt(target_review)
{'choices': [{'finish_reason': 'stop',
'index': 0,
'logprobs': None,
'message': {'content': '<reasoning>User says "메가커피의 가성비는 인정해요" which is positive about cost performance. So classification: 긍정.</reasoning>긍정',
'refusal': None,
'role': 'assistant'}}],
'created': 1766039983,
'id': 'chatcmpl-d00c78bb-d504-4d7f-8fbe-016d4ea83275',
'model': 'openai.gpt-oss-120b-1:0',
'object': 'chat.completion',
'service_tier': 'default',
'usage': {'completion_tokens': 43,
'prompt_tokens': 222,
'prompt_tokens_details': {'audio_tokens': 0, 'cached_tokens': 192},
'total_tokens': 265}}
결과는 긍정 으로 추출되었다. few-shot 기법을 사용하여 간단한 예시들을 제공하고 타겟 리뷰를 분석하여 분류하였다.
predict_llm_gpt( '''
오피스근처라 일찍 문닫네요.8시전인데 거의 마감이라.테이크아웃만 가능했어요
''' )
위에서 정의한 함수로 다른 리뷰를 분석하도록 해보았다. 실제로 매장에 있는 리뷰다.
{'choices': [{'finish_reason': 'stop',
'index': 0,
'logprobs': None,
'message': {'content': '<reasoning>User gave a Korean review: "오피스근처라 일찍 문닫네요.8시전인데 거의 마감이라.테이크아웃만 가능했어요". This is about early closing, only takeout possible. It\'s a complaint about inconvenience, likely negative sentiment. Not about price. So classify as 부정.</reasoning>부정',
'refusal': None,
'role': 'assistant'}}],
'created': 1766039987,
'id': 'chatcmpl-33519c4b-b7c5-49d7-8808-f8ca07299e0b',
'model': 'openai.gpt-oss-120b-1:0',
'object': 'chat.completion',
'service_tier': 'default',
'usage': {'completion_tokens': 80,
'prompt_tokens': 241,
'prompt_tokens_details': {'audio_tokens': 0, 'cached_tokens': 176},
'total_tokens': 321}}
이는 '부정'으로 결론이 나왔다. 얘가 부정이라고 판단했다.
리뷰 긍부정 분석 - Claude
from botocore import model
# 1. prompt
few_shot_message = '''
<role>
'당신은 커피 고객 리뷰 분석기입니다.
</role>
<context>
리뷰를 `긍정`, `부정`, `가격민감`,중 하나로 분류하세요'
</context>
<instruction>
'일찍와서 핫초코 샀어요~ 사람이 많아요~ 출근길이라 그런가봐요~ 그래도 맛있고 좋아요'는 긍정
'직원이 인사를 안해서 기분이 나빴습니다'는 부정
'스페셜 음료는 맛은 있는데 매일 사먹기엔 가격이 너무 부담스럽네'는 가격민감
</instruction>
'''
# 판단을 받고싶은 리뷰
target_review = '메가커피의 가성비는 인정하는데, 라떼 가격이 좀 올랐어요 ㅠㅠ'
def predict_llm_claude(body):
# 2. 모델 호출 => 추론/생성 등 작업 요청 => 응답
# 메세지 최종본
final_message = few_shot_message + target_review
# 프롬프트 최종본
prompt = {
"anthropic_version": "bedrock-2023-05-31",
"max_tokens": 1000,
'temperature' : 0, # 다중분류 형태 -> 창의성 x
"messages": [
{
"role": "user",
"content": final_message
}
]
}
res = bedrock.invoke_model(
modelId = get_model_id(),
body = json.dumps( prompt )
)
# 3. 응답 파싱 => 결과 출력
body = json.loads( res['body'].read() )
results = None
if 'choice' in body:
results = body['choice'][0]['message']['content']
elif 'content' in body:
results = body['content']
else:
results = body
return results[0]['text']
predict_llm_claude(body)
요건 내가 수정해본 claude 사용 코드이다.
위에서 사용했던것처럼 xml태그를 이용하여 정보를 주었고 프롬프트 최종본에서 몇 가지 디테일의 수정을 거쳤다.
'이 리뷰는 '가격민감'으로 분류할 수 있습니다. 메가커피의 가성비는 좋다고 평가하면서도 라떼 가격이 올랐다는 점을 지적하고 있기 때문입니다. 가격 인상에 대한 아쉬움을 표현하고 있으므로 '가격민감' 범주에 속합니다.'
이런 결과값이 나왔다.
다음은 강사님이 해주신 수정코드다.
def check_review_value(review):
# 강사님 답
few_shot_message = [
# 긍정예시
{'role' : 'user', 'content': '일찍와서 핫초코 샀어요~ 사람이 많아요~ 출근길이라 그런가봐요~ 그래도 맛있고 좋아요'},
{'role' : 'assistant', 'content': '긍정'},
# 부정예시
{'role' : 'user', 'content': '직원이 인사를 안해서 기분이 나빴습니다'},
{'role' : 'assistant', 'content': '부정'},
# 가격민감 예시
{ 'role' : 'user', 'content': '스페셜 음료는 맛은 있는데 매일 사먹기엔 가격이 너무 부담스럽네'},
{ 'role' : 'assistant', 'content': '가격민감'},
# 실제 판정받을 리뷰
# 실제 판정받을 리뷰
{
"role" :"user",
"content":review
}
# assistant 응답값을 요청하는것임
]
system_prompt = "당신은 커피 고객 리뷰 분석기입니다, 리뷰를 `긍정`, `부정`, `가격만족`,중 하나로 분류하세요"
prompt = {
"anthropic_version": "bedrock-2023-05-31",
"max_tokens": 100,
"system" : system_prompt,
"messages": few_shot_message
}
# 2. 모델 호출 => 추론/생성등 작업 요청 => 응답
res = bedrock.invoke_model(
modelId = get_model_id(), # claude
body = json.dumps( prompt )
)
# 3. 응답 파싱 => 결과 출력
body = json.loads( res['body'].read() )
print( body['content'][0]['text'] )
check_review_value('메가커피의 가성비는 인정하는데, 라떼 가격이 좀 올랐어요 ㅠㅠ')
가격민감
이 코드는 메세지에서의 딕셔너리 형식은 유지하고, role을 prompt에 추가해서 system_prompt로 제공하였다,
결과값은 그냥 가격민감 만 나오지만 수정도 적고 목표는 똑같이 이루었다.
리뷰 긍부정 분석 - Gemini, Gemma
# 퓨샷 샘플값의 표현이 다른 모델과 상이함
... 'content' : [{"text":"부정"}]
change = lambda x:[{"text":x}]
def check_review_value_by_google(review):
# 강사님 답
few_shot_message = [
# 긍정예시
{'role' : 'user', 'content': change('일찍와서 핫초코 샀어요~ 사람이 많아요~ 출근길이라 그런가봐요~ 그래도 맛있고 좋아요')},
{'role' : 'assistant', 'content': change('긍정')},
# 부정예시
{'role' : 'user', 'content': change('직원이 인사를 안해서 기분이 나빴습니다')},
{'role' : 'assistant', 'content': change('부정')},
# 가격민감 예시
{ 'role' : 'user', 'content': change('스페셜 음료는 맛은 있는데 매일 사먹기엔 가격이 너무 부담스럽네')},
{ 'role' : 'assistant', 'content': change('가격민감')},
# 실제 판정받을 리뷰
{
"role" :"user",
"content":change(review)
}
# assistant 응답값을 요청하는것임
]
res = bedrock.converse(
modelId = get_model_id('google'),
messages = few_shot_message,
inferenceConfig = {
"maxTokens": 100,
'temperature' : 0
}
)
print(res['output']['message']['content'][0]['text'])
Gemini, Gamma 는 프롬프트에 text.형식을 사용해야 한다고 한다.
그래서 다 넣어주기 좀 그래서 lambda 함수를 이용해서 한번에 바꿔주었다.
check_review_value_by_google('메가커피의 가성비는 인정하는데, 라떼 가격이 좀 올랐어요 ㅠㅠ')
가격민감
하단의 res = 부분의 디테일이 많이 다르다.
이게 각 모델마다 다르다고 한다. 이것을 위해서 랭체인이 필요하고 랭체인을 사용해서 각 모델들의 디테일들을 한 개의 인터페이스로 맞춰서 실제로는 사용한다고 한다.
지금은 이렇게 모델들마다 디테일이 다른, 그런 부분들을 짚고 넘어가기 위한 수업이었다.
정리
- LLM 모델별로 제품 특성에 부합하는 Prompt 엔지니어링 전략과 형식이 존재함
- 여러 모델 사용시 따로 구축해야 하는 비용 발생
- 한개의 인터페이스에서 동일 코드로 모든 LLM에 적용하는 방식 필요하다 -> 랭체인
- 정의
- 대규모 언어 모델(LLM)을 활용한 애플리케이션 개발을 쉽게 만들어주는 오픈소스 프레임워크
- 특징
- LLM 연동: OpenAI, Google 등 다양한 언어 모델과 쉽게 연결하고 사용할 수 있도록 돕습니다.
- 1개의 단일 코드로 다양한 모델 사용 가능함
- 데이터 연결: 외부 데이터(문서, 데이터베이스 등)를 불러와 LLM이 활용할 수 있도록 처리하는 기능(RAG 등)을 제공합니다.
- 체인(Chain): 여러 단계의 작업을 순서대로 연결하여 복잡한 워크플로우를 만듭니다 (예: 질문 -> 데이터 검색 -> 답변 생성).
- 에이전트(Agent): LLM이 스스로 생각하고 행동하며 도구(검색, 계산기 등)를 사용해 문제를 해결하도록 만듭니다.
- 문맥 관리: 대화의 기록을 저장하고 기억하게 하여 맥락이 있는 대화를 가능하게 합니다. 단기기억
- 장기기억 : 벡터 디비 담당
- 예시 : 채팅 내용을 기억하여 -> 자연스러운 대화 진행
- 장기기억 : 벡터 디비 담당
- LLM 연동: OpenAI, Google 등 다양한 언어 모델과 쉽게 연결하고 사용할 수 있도록 돕습니다.
오늘의 수업은 여기까지