Prompt Engineering에 대해서
들어가기 전에
프로젝트를 하면서 어떻게 하면 LLM의 응답을 더 잘 이끌어낼 수 있을지 고민하다가, 해결책 중 하나인 프롬프트에 대해 공부하고 그 내용을 정리하려고 합니다.
아래 표들은 프롬프트 기법들입니다.
⤷ 프롬프트 엔지니어링 기법들..
보시다시피 정말 많고, 지금도 새로운 기법들이 나오고 있습니다. 그렇기 때문에 여러 기법들에 관심을 두는것도 좋지만, 무엇보다 내가 해결해야 하는 문제에 대해서 잘 아는것이 중요하고, 그에 맞게 리서치, 적용, 테스트를 반복해나가는 능력이 가장 중요한 것 같습니다.
본 글에서는 대표적인 것들만 정리하려고 합니다.
llm 작동방식
LLM은 주어진 텍스트 시퀀스(문맥) 다음에 나올 가장 확률이 높은 토큰을 예측하는 방식으로 작동합니다. “하늘은 파랗고, 구름은” 이라는 텍스트가 주어지면, ‘하얗다’가 나올 확률이 가장 높다고 예측하여 텍스트를 생성합니다. 또한 LLM은 문장을 단어나 형태소같이 의미 있는 조각인 토큰 단위로 처리합니다.
llm 작동방식의 한계
LLM은 한 번에 처리할 수 있는 토큰의 양, 즉 컨텍스트 윈도우에 제한이 있습니다. 이 길이를 넘어서는 정보는 기억하지 못하고 누락될 수 있습니다. 또한 LLM은 확률이 높은 토큰을 예측하는 방식이기 때문에 학습 데이터에 없거나 불분명한 내용에 대해 그럴듯하지만 사실이 아닌 정보를 지어내는 할루시네이션이 나타날 수 있습니다.
그래서 이런 문제들를 인지하고, 해결책을 찾아야 합니다.
예를들어 기억누락 문제는 핵심 정보를 주기적으로 요약해 프롬프트에 다시 넣어주거나, 토큰 관리를 통해서 해결하고, 할루시네이션은 RAG기법을 사용해 해결할 수 있을 것 입니다.
프롬프트의 구성요소
구성요소라고 적어두었지만 정해진건 없습니다. 여기서는 사람들이 많이 사용하는 구성인 문맥, 입력데이터, 지시어, 출력지시자를 정리합니다. 하지만 이 밖에도 “프롬프트”라고만 검색해도 여러가지 구성, 기법들이 나옵니다. 그것들 중에서 가장 괜찮은 것을 선택하면 될 것 같습니다. 또한 반드시 정해진 틀대로 프롬프트를 작성할 필요없습니다.
문맥, 입력데이터, 지시어, 출력지시자
- 문맥 (Context): LLM이 작업을 수행하는 데 필요한 배경 정보나 맥락을 제공합니다.
- 입력 데이터 (Input Data): LLM이 처리해야 할 구체적인 정보나 질문입니다.
- 지시어 (Instruction): LLM이 수행해야 할 명확한 작업입니다.
- 출력 지시자 (Output Indicator): 원하는 결과물의 형식이나 구조를 명시합니다.
페르소나
LLM에게 특정 역할이나 정체성을 부여합니다. 페르소나를 부여하면 LLM은 해당 역할에 맞는 어조, 스타일, 전문 지식을 바탕으로 답변을 생성하여 결과의 일관성과 품질을 크게 향상시킬 수 있습니다. 아무리 바빠도 저같은 경우엔 페르소나는 꼭 포함합니다.
CO-STAR
CO-STAR라는 구성도 있습니다.
Context (맥락)
Objective (목표)
Style (스타일)
Tone (어조)
Audience (청중)
Response (응답)
In-context Learning
In-context Learning(ICL)은 LLM이 별도의 파인튜닝 없이 프롬프트 내에 제공된 예시를 통해 학습하고 수행하는 능력입니다.
- 제로샷 (Zero-shot): 모델에게 제공되는 예시가 0개입니다. 구체적인 예시 없이, 작업에 대한 설명,지시만 받고 작업 수행합니다. 단순한 작업, 또는 모델이 잘 알고 있는 작업에 적합합니다.
- 원샷 (One-shot): 모델에게 제공되는 예시가 1개입니다. 작업의 형태를 명확히 보여주고 싶을 때 유용합니다.
- 퓨샷 (Few-shot): 모델에게 제공되는 예시가 2~5개입니다. 더 복잡하거나 미묘한 작업, 여러 변형이 있는 작업에 적합합니다. 모델이 작업의 일반적 패턴을 더 확실히 파악하도록 돕습니다.
구분자 사용해서 구조화
위에 설명한 프롬프트 구성요소를 분리하기 위해 구분자를 사용하는 경우 LLM이 프롬프트의 구조를 더 잘 이해합니다. 저는 주로 ###를 사용하지만, 다른 어떤 필요에 따라서 XML 태그를 사용하기도 합니다. 예를들어 프롬프트에 마크다운이 포함되어 있다면 구분자로 ###보다는 XML를 쓰면 LLM이 혼동이 줄 것입니다.
답변 길이 제한
핵심 정보 중심의 효율적 응답 받기(작성중..)
부정적인 제약보다 긍정적인 지시를 하자.
LLM은 “~하지 마시오”와 같은 부정적인 지시보다 “~하시오”와 같은 긍정적이고 구체적인 지시를 더 잘 따르는 경향이 있습니다. 원하는 결과물을 명확하게 정의하고, 피해야 할 사항을 나열하기보다는 해야 할 일을 직접적으로 지시하는 것이 효과적입니다.
추론 기법들
더 복잡한 추론이 필요할 때, 많은 기법들이 있습니다. 많은것들이 있지만 제가 프로젝트에 적용해본 것들을 위주로 정리해보겠습니다.
CoT (Chain-of-Thought)
작성중..
Prompt Chaining
작성중..
RAG (Retrieval Augmented Generation)
작성중..
이 외에도 ToT, GoT, ReAct, CoD, APE, ART 등이 있습니다.
Temperature, Top-K, Top-P, Output Length
aistudio.google.com이나 platform.openai.com에 보면 여러가지 설정값들을 변경 할 수 있는데요. 프롬프트 뿐 아니라 LLM의 출력 결과에 영향을 미치는 파라미터입니다. 이 또한 무엇인지 잘 알고, 여러 테스트를 해보는게 중요합니다. 프롬프트를 먼저 잘 작성하고, 파라미터를 실험하면 될 것 같습니다.
- Temperature: (창의성 조절) 값이 높을수록(예: 0.7 이상) LLM은 더 다양하고 창의적이지만 예측하기 어려운 답변을 생성합니다. 값이 낮을수록(예: 0.3 이하) 더 결정론적이고 일관된, 안전한 답변을 생성합니다. 시나 소설 쓰기에는 높은 값을, 정보 요약이나 번역에는 낮은 값을 사용하는 것이 좋습니다.
- Top-P (Nucleus Sampling): (확률적 선택) 확률 분포의 누적값이 P가 될 때까지의 상위 토큰들 중에서만 다음 토큰을 선택합니다. 예를 들어 P가 0.9라면, 확률을 다 더했을 때 90%가 되는 가장 유력한 후보군 내에서만 선택합니다. 이는 Top-K보다 유연한 방식으로, 상황에 따라 후보군의 크기를 동적으로 조절하는 장점이 있습니다.
- Output Length: (출력 길이 제한) 생성되는 텍스트의 최대 길이를 토큰 수로 제한합니다. 의도치 않게 답변이 너무 길어지는 것을 막고 비용을 제어하는 데 사용됩니다.
- Top-K: (선택지 제한) LLM이 다음 토큰을 예측할 때, 확률이 가장 높은 K개의 후보 중에서만 선택하도록 제한합니다. K가 작을수록 답변은 더 예측 가능해지고 보수적으로 변합니다.
파라미터 설정 예시들
유스케이스 | Temperature | Top-P / Top-K | 주요 특징 |
---|---|---|---|
창의적 답변을 원할 때(브레인스토밍) | 높게 | 높게 | 다양성, 독창성, 예측 불가능성 |
정확한 사실을 분석할 때 | 낮게 | 낮게 | 일관성, 신뢰성있는 결과 |
일반 작업 | 중간 | 중간 | 균형적인 결과 |
통제된 다양성 | 높게 | 낮게 | 안전한 범위 내에서 다양한 결과 |
비추천 | 낮게 | 높게 | 낮은 Temp만 설정한 것과 거의 동일 |
프롬프트 버전을 관리하자.
프로젝트에서 코드를 버전 관리 하는것처럼 코드 또한 버전을 관리하면 좋습니다. 어떤 프롬프트가 어떤 결과물을 만들어냈는지 기록하고, 변경 사항을 추적해야 합니다. 이때 LLM 추론을 코드를 통해서 작동하는 방식이라면 코드와 별도로 파일을 분리해서 관리하면 더 편합니다. 이때 파라미터도 함께 관리하면 추적이 더 용이할 것 입니다.
Leave a comment