머신러닝 & 딥러닝/LLM

[LLM] 프롬프트 엔지니어링 정리(2)

Haru_29 2025. 2. 20. 20:44

명확하고 구체적인 지시 작성하기 (Write Clear and Explicit Instructions)

AI와 소통하는 것은 사람과 소통하는 것과 비슷하기 때문에 명확성이 중요합니다.

따라서 모델이 수행해야 할 작업을 명확하고 모호함 없이 설명하세요.
예:

모델이 에세이를 1점에서 5점까지 평가하도록 하고 싶다면, 어떤 기준을 사용할지 명확하게 설명해야 합니다.
모델이 점수에 대해 불확실할 경우, 최선의 판단을 하도록 할 것인지, "모르겠다"라고 답변하게 할 것인지 지시해야 합니다.

모델에게 특정 인물(Persona)을 설정하도록 요청하기

모델에게 특정 역할을 부여하면 더 적절한 응답을 얻을 수 있습니다.
예를 들어, 다음과 같은 문장을 평가하는 프롬프트를 생각해 봅시다:

" 운동은 건강에 좋고, 기분을 상쾌하게 만들어 줍니다 "

이 문장을 1점에서 5점까지 평가하도록 모델에게 요청하면,
기본적으로는 2점 정도의 점수를 줄 수도 있습니다.

하지만, 모델에게 " 당신은 스포츠 코치입니다." 라고 역할을 부여하면,
같은 문장에 대해 4점 을 줄 수도 있습니다.

"맞습니다! 운동은 심폐 지구력을 향상시키고, 스트레스를 줄이며, 집중력을 높이는 데 큰 도움이 됩니다."

"운동은 혈액순환을 개선하고, 면역력을 강화하며, 수면의 질을 높이는 데 중요한 역할을 합니다."

이처럼 특정 역할을 부여하면 모델의 응답이 더 맥락에 맞고 전문적으로 변할 수 있습니다.


예제 제공하기 (Provide Examples)

예제를 제공하면, 모델이 당신의 의도를 더 정확히 이해할 수 있습니다.
예를 들어, 어린이를 대상으로 한 챗봇을 만들고 있다고 가정해 봅시다.

게임 유저가 " 이 검을 더 강하게 만들 수 있어? "라고 물었을 때,
AI 모델이 " 모릅니다. 다른 곳에서 알아보세요. "라고 답하면
게임 몰입감을 해칠 수 있습니다.

이러한 문제를 방지하려면,

" 물론이지! 강철과 용의 이빨을 가져오면 더욱 강한 검을 만들어 주겠어."
" 강화에는 500골드가 필요해! 준비됐나? "
" 이 검은 이미 최고 수준이야. 하지만 다른 재료를 가져오면 새로운 무기를 만들어 줄 수도 있지."
와 같은 답변 예시를 모델에게 미리 제공해야 합니다.

프롬프트 형식 선택: 입력 길이를 고려하라

프롬프트를 작성할 때 토큰 길이(token length) 를 고려하는 것이 중요합니다.

불필요하게 긴 입력은 비용을 증가시킬 뿐만 아니라, 모델의 응답 속도도 느려질 수 있습니다.
따라서 같은 의미를 전달하면서도 더 간결한 형식을 선택하는 것이 효율적입니다.

📌 비효율적인 긴 형식과 간결한 형식 비교 예제

프롬프트토큰 수 (GPT-4 기준)

긴 형식:  
"다음 문장을 긍정적(positive) 또는 부정적(negative) 으로 분류하세요."  
입력: "오늘 날씨가 너무 좋다!" → 출력: 긍정적 (positive)  
입력: "이 음식은 정말 별로야." → 출력: 부정적 (negative) 41
짧은 형식:  
"다음 문장을 '긍정' 또는 '부정'으로 분류하세요."  
"오늘 날씨가 너무 좋다!" → 긍정  
"이 음식은 정말 별로야." → 부정 28

짧은 형식이 토큰 수가 더 적기 때문에 선호됨.
동일한 성능을 보장한다면 짧은 형식을 선택하는 것이 좋음.


출력 형식 지정하기 (Specify the Output Format)

모델이 응답을 간결하고 일관되게 작성하도록 명확한 지시가 필요합니다.

출력 형식 명확히 지정하기의 이점

API 비용 절감 → 짧은 응답일수록 비용 감소
불필요한 서론 제거예: "Based on the analysis, the score is..." 대신 "점수: 4" 로 바로 출력
구조화된 출력 유지 → JSON, CSV 등의 특정 형식으로 일관되게 출력

📌 비효율적인 형식 vs. 효율적인 형식 비교

프롬프트AI 출력

비효율적인 형식:  
"다음 문장을 긍정(positive) 또는 부정(negative)으로 분류하세요."  
입력: "이 제품 정말 좋아요!"  
출력: "Based on the sentiment of this statement, I would classify it as positive." (불필요한 문장이 포함됨)
효율적인 형식:  
"다음 문장을 '긍정' 또는 '부정'으로 분류하세요."  
"이 제품 정말 좋아요!" → 긍정 (간결하고 일관된 출력)

📌 JSON 출력 예시
❌ 잘못된 출력 (불규칙한 형식)

 
{
  "문장": "이 제품 정말 좋아요!",
  "Sentiment": "It seems positive based on the provided context."
}

✅ 올바른 출력 (일관된 JSON 형식 유지)

{
  "문장": "이 제품 정말 좋아요!",
  "감정 분석": "긍정"
}

출력 형식을 미리 지정하면, 모델이 일관성 있게 응답을 생성함.
'→' 같은 마커를 활용하면 출력이 명확해지고 추가적인 불필요한 응답을 방지할 수 있음.


충분한 컨텍스트 제공하기 (Provide Sufficient Context)

컨텍스트 제공은 모델 성능 향상에 큰 도움이 됩니다.

  • 시험을 볼 때 참고 자료가 있다면 학생들이 더 나은 답변을 할 수 있는 것과 같은 원리입니다.
  • 모델이 특정 질문에 대한 답을 해야 한다면, 질문이 나온 배경 정보 를 함께 제공하는 것이 중요합니다.
  • 충분한 컨텍스트는 헛소리(hallucination)를 방지하는 데에도 유용합니다.

컨텍스트가 부족하면, 모델이 자체적으로 정보를 생성할 수 있으며, 이는 부정확할 수 있음.
제공하는 정보를 기반으로 응답을 생성하도록 유도해야 함.

📌 참고:
AI 모델은 기본적으로 사용자가 입력한 정보와 자체 생성한 정보를 구분하지 않음


모델이 제공된 컨텍스트 내에서만 답변하도록 제한하는 방법

(How to Restrict a Model’s Knowledge to Only Its Context)

많은 경우, 모델이 제공된 정보 내에서만 답변하도록 하는 것이 필요 합니다.
이것은 특히 롤플레잉(role-playing) 이나 캐릭터 기반 AI 에서 중요합니다.
예를 들어, "게임 속 캐릭터를 연기하는 AI" 를 원한다고 가정해 보겠습니다.
이 캐릭터는 "스카이림(Skyrim)" 에 대한 정보만 알고 있어야 하며,
"스타벅스에서 가장 좋아하는 음료가 뭐야?" 같은 질문에는 답하지 않아야 합니다.

모델을 제공된 컨텍스트 내에서만 제한하는 방법:

  • "제공된 컨텍스트 내에서만 답변하라." 라는 명확한 지침을 포함하세요.
  • 예시를 제공하여 허용되는 답변과 허용되지 않는 답변을 구분 하세요.
  • "모델이 참고할 정보를 인용하도록 강제" 하는 것도 효과적인 방법입니다.
    • 즉, 모델이 주어진 문서나 데이터에서만 답을 찾도록 유도 하는 것입니다.

❌ 하지만, 모델이 항상 지시를 따를 것이라고 보장할 수는 없습니다.

  • 파인튜닝(fine-tuning) 을 통해 특정 도메인에 맞게 조정할 수도 있지만,
    • 자체적으로 모델을 파인튜닝하는 것은 비용과 시간이 많이 드는 작업 입니다.
  • 사전 훈련(pre-training) 단계에서 제한된 지식만 학습하도록 하는 것이 가장 효과적이지만,
    • 대부분의 경우 실용적이지 않습니다.
    • 또한, 제한된 데이터만으로는 고품질 모델을 만들기 어려울 수도 있습니다.

복잡한 작업을 더 작은 하위 작업으로 나누기

(Break Complex Tasks into Simpler Subtasks)

게임 NPC AI 대화 시스템을 설계할 때, 복잡한 대화 흐름을 작은 하위 작업으로 나누는 것이 중요합니다.
NPC의 대화를 한 번에 생성하는 대신, 대화의 목적에 따라 단계적으로 처리하면 자연스러운 상호작용을 만들 수 있습니다.

📌 예제: RPG 게임의 상점 NPC 대화 시스템

상점 NPC와 플레이어 간의 대화를 세 단계로 나눌 수 있습니다:

1️⃣ 대화 의도 분류 (Intent Classification)

📌 프롬프트:
"플레이어가 상점 NPC에게 말을 걸었습니다.
플레이어의 대화 의도를 '구매', '판매', '정보 요청', '잡담' 중 하나로 분류하세요."

📌 예시 입력:
"이거 살 수 있나요?"
"이 아이템을 팔고 싶어요."
"상점 주인님, 요즘 마을에 무슨 일이 있나요?"

📌 예시 출력:

{ "의도": "구매" }

2️⃣ 대화 응답 생성 (Response Generation)

📌 프롬프트:
*"플레이어의 의도가 '구매'일 경우, 상점 NPC가 다음과 같이 대답하도록 만드세요:

  • '환영합니다! 원하는 물건을 고르세요.'
  • '[아이템 목록]을 표시하세요.'"*

📌 예시 출력:
"환영합니다! 원하는 물건을 고르세요.
오늘의 추천 아이템: '전설의 검' 100골드!"

3️⃣ 동적 대화 흐름 관리 (Dynamic Dialogue Flow)

📌 프롬프트:
"플레이어가 아이템을 선택하면, 가격과 추가 정보를 제공하세요.
거래를 수락하면 금액을 차감하고 아이템을 지급하세요."

📌 예시 입력:

{
  "선택한 아이템": "전설의 검",
  "보유 골드": 120
}

📌 예시 출력:
"전설의 검은 100골드입니다. 구매하시겠습니까?"

✅ 플레이어가 구매하면:
"거래 완료! 전설의 검을 획득했습니다."

✅ 플레이어가 거절하면:
"언제든 다시 오세요!"

📌 핵심 요약

NPC 대화를 한 번에 생성하는 대신, 단계별로 나누면 더 자연스러운 상호작용이 가능함.
의도 분류 → 응답 생성 → 동적 대화 관리 순으로 진행하면 대화 흐름이 명확해짐.
구조화된 출력(JSON 등)을 사용하면 대화 상태를 유지하기 쉬워짐.


프롬프트를 더 작은 단계로 분해하는 것의 장점

(Prompt Decomposition Benefits)

위 예제에서, 의도 분류(intent classification)를 두 개의 프롬프트로 더 세분화할 수 있지 않을까?
즉,

  • 첫 번째 프롬프트: 주 카테고리(primary category) 결정
  • 두 번째 프롬프트: 부 카테고리(secondary category) 결정

각 하위 작업을 얼마나 세분화할지는 사용 사례, 성능 요구 사항, 지연 시간(latency) 등을 고려하여 결정해야 합니다.
이러한 최적의 프롬프트 분해 전략을 찾기 위해 실험이 필요합니다.

모델이 점점 더 복잡한 명령을 잘 처리하고 있지만, 여전히 단순한 프롬프트에서 더 좋은 성능을 보입니다.
프롬프트를 작은 단위로 분해하면 성능 향상뿐만 아니라 추가적인 장점이 있습니다.

1️⃣ 모니터링 (Monitoring)

  • 최종 결과뿐만 아니라 중간 단계 출력도 모니터링할 수 있습니다.
  • 프롬프트가 여러 단계를 거치며 처리된다면, 각 단계에서 모델의 응답을 확인할 수 있습니다.

2️⃣ 디버깅 (Debugging)

  • 문제가 발생한 특정 단계를 쉽게 찾아낼 수 있습니다.
  • 한 단계에서 문제가 발생했을 때, 전체 모델을 변경하지 않고 해당 단계만 수정하면 됩니다.

3️⃣ 병렬 처리 (Parallelization)

  • 독립적인 단계를 병렬로 실행하면 시간을 절약할 수 있습니다.
  • 예를 들어,
    • "초등학교 1학년 수준, 8학년 수준, 대학 신입생 수준" 으로 세 가지 읽기 수준의 이야기를 생성하는 모델을 만들었다고 가정해봅시다.
    • 각 버전을 동시에 생성 하면, 출력 대기 시간을 크게 줄일 수 있습니다.
    • (출처: Anthropic의 프롬프트 엔지니어링 가이드, 링크)

4️⃣ 간결한 프롬프트 작성 (Effort)

  • 짧고 간단한 프롬프트를 작성하는 것이 긴 프롬프트를 만드는 것보다 쉽습니다.

프롬프트 분해의 단점 (Downsides of Prompt Decomposition)

사용자 경험의 지연 시간(latency)이 증가할 수 있음

  • 최종 출력 전에 중간 단계가 필요하기 때문에 사용자 입장에서 응답이 느려 보일 수도 있음
  • 단순한 단일 프롬프트보다 출력 시간이 길어질 수 있음

API 비용 증가 가능성

  • 더 많은 프롬프트를 사용하면 API 호출이 늘어나 비용이 증가할 수 있음
  • 하지만, 더 작은 프롬프트를 사용하면 토큰 수를 줄일 수 있어 비용을 절감할 수도 있음

📌 GoDaddy 사례 연구 (출처: GoDaddy 연구)

  • 고객 지원 챗봇이 한 번에 1,500개 이상의 토큰을 사용
  • 프롬프트를 더 작은 하위 작업으로 나누자
    • ✅ 모델 성능이 향상됨
    • ✅ 처리 비용이 감소함

모델이 "생각할 시간"을 가질 수 있도록 하라

(Give the Model Time to Think)

체인 오브 싱킹(Chain-of-Thought, CoT) 및 자기 피드백(self-critique prompting)을 활용하면, 모델이 더 깊이 "생각"하도록 유도할 수 있습니다.

CoT란?

  • CoT(Chain-of-Thought)는 모델이 문제를 단계별로 해결하도록 명시적으로 요청하는 기법입니다.
  • 이 기법은 모델이 보다 체계적인 문제 해결 방식을 따르도록 유도합니다.
  • CoT는 모든 모델에 효과적인 최초의 프롬프트 엔지니어링 기법 중 하나 입니다.

📌 CoT의 등장:

  • 논문: "Chain-of-Thought Prompting Elicits Reasoning in Large Language Models"
    (Wei et al., 2022)
  • ChatGPT 출시(2023년 3월)보다 거의 1년 전부터 연구됨.

📌 Figure 5-6:

  • CoT가 LLaMA, GPT-3, PaLM 등의 모델 성능을 개선한 사례
  • LinkedIn 엔지니어링 블로그 (출처)
    • CoT는 모델의 "환각(hallucination)" 현상을 줄이는 데에도 효과적임.

체인 오브 싱킹(CoT) 프롬프트 변형 예시

(Chain-of-Thought Prompt Variations)

📌 CoT(Chain-of-Thought) 기법을 활용하면, 동일한 질문이라도 논리적 사고 과정을 유도하여 더 신뢰할 수 있는 답변을 얻을 수 있습니다.
아래는 게임 NPC AI 대화를 예시로 적용한 CoT 변형 방법입니다.


원래 질문 (Original Query)CoT 변형 적용 후

"이 마법이 강한가요?" "이 마법이 강한가요? 단계별로 설명한 후 결론을 도출하세요."
"이 마법이 강한가요?" "이 마법이 강한가요? 먼저 마법의 공격력과 효과 범위를 분석한 후 결론을 내리세요."
"이 마법이 강한가요?" "이 마법이 강한가요? 다음 단계를 거쳐 답을 도출하세요. ① 마법의 기본 피해량을 확인하세요. ② 쿨다운 시간을 분석하세요. ③ 다른 마법과 비교하여 결론을 도출하세요."

 


자기 평가(Self-Critique)를 통한 모델 성능 개선

Self-Critique(자기 평가) 란?

  • 모델이 자신의 출력을 검토하고 오류를 찾아내도록 유도하는 기법 입니다.
  • "자기 평가(self-eval)" 라고도 불리며, 3장에서 자세히 다루었습니다.

CoT와 Self-Critique의 유사점

  • CoT가 "단계별 사고"를 유도하는 것처럼,
    • Self-Critique는 모델이 자신의 답을 검토하고 수정하도록 유도 합니다.
  • 이 두 기법을 함께 사용하면 모델의 정답률을 더욱 높일 수 있습니다.
  • 하지만, 여러 중간 단계를 필요로 하기 때문에 지연 시간이 증가할 수도 있습니다.

📌 즉, Self-Critique는

  • ✅ 모델이 더 신뢰할 수 있는 답을 제공하도록 유도
  • ✅ 모델이 자기 수정 능력을 갖추도록 훈련
  • ❌ 하지만 지연 시간(latency) 및 API 비용이 증가할 가능성 있음

프롬프트를 계속 개선하라 (Iterate on Your Prompts)

프롬프트 엔지니어링은 반복적인 과정입니다.

  • 모델을 사용할수록 더 효과적인 프롬프트를 작성하는 방법을 알게 됩니다.
  • 한 번 작성한 프롬프트가 최상의 결과를 보장하지 않습니다.
    • 따라서 반복적인 실험과 개선(iteration)이 필요합니다.

📌 예제:

  • "최고의 비디오 게임을 추천해 주세요."
    • 모델이 단 하나의 게임을 추천할 수도 있고,
    • 여러 게임을 비교하면서 가장 좋은 선택을 도출할 수도 있습니다.
  • 만약 여러 게임을 비교한 후 최적의 선택을 도출하는 방식이 더 좋다면,
    • 프롬프트를 수정하여 모델이 이렇게 응답하도록 유도할 수 있습니다.

모든 모델은 각각의 특성을 가지고 있습니다.

  • 어떤 모델은 숫자 계산에 강하고,
  • 어떤 모델은 롤플레잉(role-playing)에 더 적합합니다.
  • 어떤 모델은 지시를 앞부분에서 제공할 때 더 잘 따르고,
  • 어떤 모델은 마지막에 제공할 때 더 잘 따릅니다.

📌 프롬프트 개선을 위한 팁:

  • 여러 가지 다른 프롬프트 변형을 시도해 보세요.
  • 모델 개발자가 제공한 프롬프트 가이드를 참고하세요.
  • 온라인 커뮤니티에서 다른 사용자들의 경험을 활용하세요.
  • 동일한 프롬프트를 여러 모델에 입력해 보고, 응답을 비교해 보세요.

프롬프트 엔지니어링 도구 평가하기

(Evaluate Prompt Engineering Tools)

프롬프트 최적화의 어려움

각 작업마다 사용할 수 있는 프롬프트의 조합은 무한 합니다.

  • 수작업으로 프롬프트를 최적화하는 것은 시간이 많이 소요되는 작업 입니다.
  • 최적의 프롬프트를 찾는 것은 매우 어렵습니다.

이를 해결하기 위해 다양한 자동화 도구들이 개발되었습니다.

  • OpenPrompt (Ding et al., 2021, 출처)
  • DSPy (Khatab et al., 2023, 출처)

이러한 도구들은 다음과 같은 방식으로 프롬프트 최적화를 자동화합니다.

  1. 입력 및 출력 형식 정의
  2. 성능 평가 지표 설정
  3. 프롬프트 검색 및 최적화 실행

이러한 방식은 자동화 머신러닝(AutoML) 과 유사합니다.

  • AutoML이 최적의 하이퍼파라미터를 찾는 것처럼,
  • 프롬프트 엔지니어링 도구는 최적의 프롬프트를 자동으로 찾아줍니다.

AI 모델을 사용하여 프롬프트 생성 자동화하기

AI 모델 자체가 프롬프트를 생성하도록 할 수도 있습니다.

모든 AI 모델은 텍스트 생성 기능을 가지고 있으므로,
이를 활용하여 프롬프트 자체를 자동 생성하고 개선하는 방식을 사용할 수 있습니다.


📌 활용 예제: RPG 게임의 NPC 대화 프롬프트 생성

🎮 원래 요청:
"RPG 게임에서 상점 NPC가 플레이어에게 자연스럽게 말을 거는 프롬프트를 작성해줘."

🧠 AI가 생성한 프롬프트 예시:
*"당신은 RPG 게임의 상점 주인 NPC입니다.
플레이어가 가게에 들어오면, 친근하고 개성 있는 말투로 환영하세요.

  • 새로운 아이템이 입고되었을 경우, 플레이어에게 알려주세요.
  • 플레이어가 이미 방문한 적이 있다면, 친숙한 느낌으로 맞이하세요.
  • 특별 할인 이벤트가 있을 경우, 이를 강조하세요.
    NPC 대사는 간결하지만 개성 있게 만들어 주세요."*

이렇게 생성된 프롬프트를 바탕으로 더 개선된 버전을 만들 수도 있습니다.


📌 Claude 3.5 Sonnet 같은 AI 모델이 생성한 프롬프트 예시 (개선 버전)

🛠 개선된 프롬프트:
*"당신은 RPG 게임 속 상점 NPC입니다.
플레이어가 가게에 들어오면 다음 원칙에 따라 자연스럽게 대화를 시작하세요.

1️⃣ 처음 방문한 경우:

  • "처음 보는 얼굴이군! 여행자, 무기나 물약이 필요하나?"
    2️⃣ 이미 방문한 경우:
  • "오, 다시 왔군! 지난번에 산 물건은 잘 쓰고 있나?"
    3️⃣ 이벤트 또는 특별 할인 정보 포함:
  • "마침 좋은 타이밍이야! 오늘 특별 할인 중이니, 놓치지 마라!"

💡 모든 응답은 친근하면서도 캐릭터의 개성이 드러나도록 만들어 주세요."*


AI 기반 프롬프트 최적화 도구: Promptbreeder & TextGrad 응용

AI를 활용하여 최적의 프롬프트를 자동으로 찾는 최신 연구 활용

📌 활용 예제: 게임 NPC 대화 최적화

RPG 게임에서 NPC의 대사를 보다 자연스럽고 몰입감 있게 개선하는 과정을 예로 들어보겠습니다.


📌 원래 프롬프트 (Original Prompt)
"플레이어가 대장장이 NPC에게 말을 걸면, 대장장이가 인사하고 서비스를 제공하세요."


📌 변형 프롬프트 (Mutator Prompt) – AI 개선 과정

1️⃣ 1차 변형 (더 자연스럽게 개선)
"플레이어가 대장장이 NPC에게 말을 걸면, 대장장이가 친근한 말투로 인사하세요.
그 후, 무기 수리 및 구매 옵션을 제공하세요."

🛠 AI 응답 예시:
"오! 무기를 손보러 왔나? 내가 최고의 대장장이란 걸 잊지 마라! 수리를 원하나, 새 무기를 찾고 있나?"


2️⃣ 2차 변형 (더 몰입감 있는 대화 방식 추가)
"플레이어의 장비 상태를 확인한 후, 적절한 추천을 하세요.
NPC의 말투는 성격을 반영하도록 설정하세요."

🛠 AI 응답 예시:
"이봐, 네 검이 너무 닳아 있군. 그냥 수리하는 것보다 새 걸 사는 게 낫겠어.
하지만 네가 고집쟁이라면, 내가 최상의 연마를 해주지!"


3️⃣ 3차 변형 (상황별 반응 추가)
"플레이어가 최근 전투에서 피해를 입었다면, NPC가 이를 인식하고 적절한 반응을 보이세요."

🛠 AI 응답 예시:
"오… 너덜너덜한 꼴을 보니, 엄청난 싸움을 벌였군! 그 검도 꽤 상했을 거야.
지금 바로 수리해 주지, 50골드면 충분할 거야."


📌 핵심 요약:
Promptbreeder 기법을 활용하면 AI가 스스로 NPC 대화를 점진적으로 개선 가능.
변형된 프롬프트를 AI가 테스트하고 최적의 대사를 선택하도록 설정 가능.
게임 내 몰입감을 높이고, NPC와의 상호작용을 더 자연스럽게 개선할 수 있음.

 


프롬프트 엔지니어링 도구 사용 시 주의할 점

(Many tools aim to assist parts of prompt engineering.)

프롬프트 엔지니어링 도구 예시:

이 도구들은 프롬프트 변형(prompt variation) 을 자동화하는 기능을 제공합니다.
예를 들어,

  • 동의어를 변경하거나(replacing a word with its synonym)
  • 기본 프롬프트를 수정하여 다른 방식으로 표현하는 것
    을 자동으로 수행할 수 있습니다.

주의:
프롬프트 엔지니어링 도구를 신중하게 사용하면 모델 성능을 향상시킬 수 있습니다.
그러나, 무분별하게 사용하면 예기치 않은 API 비용 증가 및 문제 발생 가능성 이 있습니다.


프롬프트 엔지니어링 도구 사용 시 발생할 수 있는 문제

1️⃣ API 비용 증가 위험

  • 프롬프트 엔지니어링 도구는 기본적으로 여러 가지 변형된 프롬프트를 생성할 수 있습니다.
  • 각 프롬프트 변형마다 API 호출이 발생할 수 있음.
  • 예를 들어,
    • 하나의 프롬프트를 10가지 변형으로 테스트한다고 가정하면,
    • 각 변형당 30개의 API 요청이 발생하면, 총 300번의 API 호출이 이루어질 수 있습니다.
  • 이러한 자동화된 프롬프트 테스트가 의도치 않게 비용을 초과하게 만들 수 있음.

2️⃣ 불필요한 복잡성 증가

  • 프롬프트를 평가하는 과정에서 응답이 올바른 JSON 형식인지 검증해야 하는 경우도 발생할 수 있음.
  • 너무 많은 API 호출을 포함하는 프롬프트 체인(prompt chain)
    • 비효율적이고 너무 길어질 수 있음.
    • 응답 시간이 길어지고, 비용이 증가할 가능성이 있음.

3️⃣ 도구의 버그 및 예기치 않은 동작

  • 프롬프트 엔지니어링 도구는 사람이 개발한 것이므로, 오류가 발생할 가능성이 있음.
  • 예를 들어, LangChain 프롬프트에서 오타(typo)가 발생한 사례 가 있음.
    • Figure 5-9 에 LangChain의 기본 프롬프트에서 발견된 오타 가 표시됨.
    • options → option 으로 수정 필요.
    • 이러한 작은 실수가 모델 응답 품질을 크게 저하시킬 수 있음.

프롬프트 관리 및 버전 관리하기

(Organize and Version Prompts)

프롬프트를 코드에서 분리하는 것이 좋습니다.

  • 프롬프트를 별도의 파일 (prompts.py) 에 저장하고, 코드에서 이를 참조하는 방식이 유용함.

📌 예제 코드:

# prompts.py
GPT40_ENTITY_EXTRACTION_PROMPT = "[YOUR PROMPT]"

# application.py
from prompts import GPT40_ENTITY_EXTRACTION_PROMPT

def query_openai(model_name, user_prompt):
    completion = client.chat.completions.create(
        model=model_name,
        messages=[
            {"role": "system", "content": GPT40_ENTITY_EXTRACTION_PROMPT},
            {"role": "user", "content": user_prompt}
        ],
    )

이 방식의 장점:

1️⃣ 재사용성 (Reusability)

  • 여러 애플리케이션에서 동일한 프롬프트를 사용할 수 있음.

2️⃣ 테스트 가능성 (Testing)

  • 코드와 프롬프트를 분리하면,
    • 프롬프트를 독립적으로 테스트할 수 있음.
    • 예를 들어, 같은 코드에서 여러 프롬프트를 실험하며 성능을 비교 가능.

3️⃣ 가독성 (Readability)

  • 코드와 프롬프트를 분리하면, 코드가 더 읽기 쉬워짐.

📌 이 개념은 Hamel Husain의 블로그 게시글에서도 강조됨:

  • "Show Me the Prompt" (출처, 2024년 2월 14일)

핵심 요약:

프롬프트 엔지니어링 도구는 자동화된 프롬프트 변형을 제공할 수 있음.
그러나, 너무 많은 API 호출이 발생하면 비용이 증가할 수 있음.
프롬프트를 코드와 분리하면 재사용성과 가독성이 향상됨.
테스트 가능성을 높이기 위해, 프롬프트를 별도의 파일에서 관리하는 것이 좋음.


협업을 위한 프롬프트 관리 (Collaboration and Prompt Organization)

다양한 애플리케이션에서 같은 프롬프트를 사용한다면, 프롬프트 메타데이터(metadata)를 유지하는 것이 중요합니다.

  • 어떤 프롬프트가 어떤 용도로 사용되는지 쉽게 추적할 수 있어야 합니다.
  • 프롬프트를 체계적으로 구성하는 방법을 마련하면 검색이 용이합니다.
    • 예를 들어, 모델별, 애플리케이션별, 또는 특정 프로젝트별로 분류할 수 있습니다.

Python에서 Pydantic을 사용해 프롬프트를 구조화할 수 있습니다.

📌 예제 코드:

from pydantic import BaseModel

class Prompt(BaseModel):
    model_name: str
    date_created: datetime
    application: str
    prompt_text: str
    creator: str

추가적으로 포함할 수 있는 메타데이터 예시:

  • 모델 엔드포인트 URL
  • 샘플링 파라미터 (예: temperature, top-p 등)
  • 입력 및 출력 스키마 (schema)
  • 구조화된 출력이 필요한 경우, 예상되는 출력 형식

다양한 프롬프트 파일 형식이 존재합니다.

📌 Firebase Dotprompt 예제:

model: vertexai/gemini-1.5-flash
input:
  schema:
    theme: string
output:
  format: json
  schema:
    name: string
    price: integer
    ingredients(array): string

 


프롬프트 버전 관리의 중요성 (Prompt Versioning)

프롬프트를 Git과 같은 버전 관리 시스템에 저장하면, 변경 사항을 추적할 수 있습니다.
하지만, 여러 애플리케이션이 같은 프롬프트를 공유할 경우, 모든 애플리케이션이 자동으로 업데이트되는 문제가 발생할 수 있습니다.
따라서, 프롬프트 카탈로그(prompt catalog)를 별도로 운영하면 도움이 될 수 있습니다.

  • 각 애플리케이션이 특정 프롬프트 버전을 고정할 수 있음.
  • 프롬프트에 대한 메타데이터를 추가하여 검색을 쉽게 만들 수 있음.
  • 업데이트된 프롬프트가 있을 경우, 이를 추적하여 애플리케이션 소유자에게 알릴 수도 있음.