오랜만에 돌아왔습니다. 컨퍼런스하랴, 인턴생활하랴, 공모전하랴, 일본어 공부하랴 너무 현생이 바빠서 한 달 동안 블로그를 쓰지 못하였네요. 그래서 오랜만에 돌아왔으니 재미난 이야기를 들고 왔습니다. 그것은 바로 프롬프트 엔지니어링!
1. Prompt Engineering 이란?
프롬프트 엔지니어링은 생성형 인공 지능(생성형 AI) 솔루션을 안내하여 원하는 결과를 생성하는 프로세스입니다.(AWS 참조) 그렇다면 여기서 얘기하는 프롬프트란 무엇일까요?
LLM에게 질문을 하거나 어떤 요구사항이 있을 때 이러한 텍스트 정보를 프롬프트라고 부릅니다. 저희는 생성형 AI (이미지, 동영상, 텍스트 등) 에게 프롬프트를 입력하고 생성형 AI는 사용자의 프롬프트를 받아 무언가를 생성하죠. 특히 저는 주변에서 NLP의 남자라고 불릴만큼(제가 지은 별명이 아닙니다.) NLP 소식밖에 몰라서, 오늘은 LLM에 대한 프롬프트 얘기를 해보려고 합니다.
생성형 AI의 대표적인 예로 ChatGPT가 있습니다. GPT를 써보신 분이라면 다들 아시겠지만 매우 유용합니다. 코딩을 대신 해주기도 하고 코드의 오류를 찾아주기도 하고 요새는 멀티모달 기능까지 추가되어 이미지도 인식하고 이미지 생성도 합니다. 하지만 이런 GPT를 더 잘 쓰기 위한 논문까지 있다는 점 알고 계신가요? 바로 아래처럼 말이죠.
https://arxiv.org/abs/2312.16171
하지만 오늘은 GPT를 잘 쓰기 위한 방법보다 LLM을 사용할 때 Prompt를 어떻게 변형하고 답변을 다르게 받아볼 수 있을지 코드중심적으로 보려고 합니다.
2. 좋은 Prompt Engineering
좋은 프롬프트 엔지니어링이란 무엇일까요? 답은 누구나 다르게 생각하겠지만 저는 적어도 LLM이 이해하기에 쉽도록 하는게 가장 중요하다고 생각합니다. 한마디로 직관적이어야 한다는 거죠. 사람도 어떤 문제를 풀 때 문제 설명이 장황하고 복잡해서 이해하기가 힘들다면 그 문제를 풀기 힘들테니까요. 그 중에서도 첫번째로 소개드릴 것은 역할 부여 입니다.
1) 역할 부여
역할 부여 방법은 워낙 유명해서 다들 아실 것 같은데요. 말 그대로 우리의 Task에 필요한 역할을 부여하는 것입니다. 코드를 짜야 한다면 Code Assistant, 데이터를 만들어야 한다면 Data Engineer, 금융 도메인의 Task라면 Financial Expert 등이 되겠죠.
제가 AI를 활용해서 회의를 자동으로 요약해주는 서비스를 개발했을 때의 코드를 예로 보여드리겠습니다.
Prompt 부분 보시면 "당신은 유용한 AI 어시스턴트입니다. 사용자의 질의에 대해 친절하고 정확하게 답변해야 합니다." 라고 역할을 부여했죠. 이로 인해 LLM은 사용자의 질의에 대해 AI 도메인적 관점에서 접근하고 문제를 해결하려고 할 것입니다. 함수는 이를 딕셔너리 형태로 만들어서 좀 더 직관적으로 LLM이 받아들일 수 있게 코딩한 거구요.
또 하나의 예시를 들어보겠습니다.
위 코드는 제가 현재 진행하고 있는 업무인 Persona LLM 구축할 때의 prompt입니다. 메구밍 캐릭터처럼 이야기하는 LLM을 개발하다보니 메구밍처럼 이야기해야 한다는 프롬프트를 입력해야 합니다. 이번엔 한국어 LLM이 아니라 영어 LLM으로 학습을 시켜서, 프롬프트는 영어로 작성하였구요. 저 프롬프트가 꼭 정답이라는 건 아니지만, 요점은 역할을 부여하면 더 LLM이 직관적으로 본인이 해야 할 일을 알기 때문에 답변 생성에 도움을 줄 수 있다는 점입니다.
2) 직관적인 문장
위에서도 계속 직관적인, 이해하기 쉬운 등의 키워드를 사용한 만큼 LLM이 이해할 수 있도록 최대한 쉽고 명확한 문장을 건네줘야 합니다. 이해하기 어렵고 문장의 의미가 모호한 문장을 넣는다면 좋은 모델, 잘 학습시킨 모델이라고 할지라도 좋은 퍼포먼스를 보여주기 힘들겁니다. 그리고 이러한 현상은 모델의 크기가 작을수록 심해집니다.
## chunk별로 summary text에서 한 단어의 키워드 생성
def generate_keyword_from_summary_with_llm(data, keyword_list):
for chunk in data['chunks']:
## 키워드 추출
original_text = chunk["original_text"]
summarized_text = chunk["summarized_text"]
## 프롬프트 정의 (키워드를 한 단어로 생성하는 명령어 포함)
prompt = (
f"Original text: {original_text}\n\n"
"위 회의 텍스트의 핵심 주제를 형식 맞춰 **세 문장**으로 요약해.\n"
)
prompt_len = len(prompt)
## 텍스트를 모델이 이해할 수 있는 input_ids로 변환
input_ids = tokenizer(prompt, return_tensors="pt").to(device)
input_ids.pop("token_type_ids", None)
## 모델로 키워드 생성
outputs = model.generate(**input_ids, max_new_tokens = 100) ## 적은 토큰 수로 키워드 생성
keyword = tokenizer.decode(outputs[0], skip_special_tokens=True)[prompt_len:].strip()
## 정규표현식으로 한글, 영어, 괄호, 공백만 남기기
filtered_keyword = re.sub(r'[^ㄱ-ㅎㅏ-ㅣ가-힣a-zA-Z\s\(\)\:]', '', keyword)
## 필터링된 키워드를 리스트에 추가
keyword_list.append(filtered_keyword)
## 결과 출력
print(f"Chunk {chunk['chunk_num']} Summary:")
print(original_text)
print("\n")
print(f"Generated Keyword: {filtered_keyword}")
print("\n")
위 프롬프트는 회의 요약 Task에서 사용했던 간결한 프롬프트구요. 위 코드를 실험했던 모델이 1.3B 모델이라서 프롬프트를 한 줄로 최대한 간결하게 작성했던 겁니다. 그리고 프롬프트를 "위 회의 텍스트의 핵심 주제가 도대체 뭔지 너무 궁금하니까 형식 맞춰 **세 문장**으로 요약하도록 해." 라고 넣으니 이상하게 나오네요. (보통은 프롬프트를 이렇게 입력하지 않지만 예시를 들었을 뿐입니다 ~) 결과는 아래 표로 정리해두겠습니다.
Prompt | 답변 1 | 답변 2 |
위 회의 텍스트의 핵심 주제를 형식 맞춰 **세 문장**으로 요약해. | 구글 API: 이 회의에서는 구글 API를 사용하여 강의 영상을 인퍼런스로 활용하는 방법을 논의하고 있습니다 강의 영상: 이 회의에서는 강의 영상을 인퍼런스로 활용하는 방법에 대해 논의하고 있습니다 SK: 이 회의에서는 SK에서 진행한 강의 영상 컨퍼런스를 인퍼런스로 활용하는 방법에 대해 논의하고 있습니다 |
LLM 파트에서 청크가 너무 많아지면 HTML이 깨지는 문제가 발생한다 최소 길이를 정하여 LLM에 넣을 필요가 없다 HTML이 깨지는 형식으로 나오는 경우가 있으므로 인퍼런스 시간을 어떻게 해야 할지 고민 중이다 |
위 회의 텍스트의 핵심 주제가 도대체 뭔지 너무 궁금하니까 형식 맞춰 **세 문장**으로 요약하도록 해. | 구글 API: 이 부분은 구글에서 제공하는 API를 언급하고 있습니다 강의 영상: 이 부분은 강의 영상을 언급하고 있습니다 SK: 이 부분은 SK에서 제공한 강의 영상을 언급하고 있습니다 컨퍼런스: 이 부분은 컨퍼런스를 언급하고 있습니다 강의 영상: 이 부분은 강의 영상을 언급하고 있습니다 SK: 이 부분은 SK에서 제공한... |
LLM 파트에서 어떤 문제가 있었는지 설명해주세요 HTML이 깨지는 형식으로 나오는 경우가 있는데 어떻게 해결할 수 있을까요 LLM 파트에서 어떤 문제가 있었는지 설명해주세요 HTML이 깨지는 형식으로 나오는 경우가 있는데 어떻게 해결할 수 있을까요 |
매우 가벼운 모델이라서 더 그럴수도 있겠지만 할루시네이션이 조금 보이는 듯한 결과가 나왔습니다. 요점은 프롬프트를 입력할 때 최대한 명확하고 간결한 표현의 문장이어야 한다는 점입니다.
3. 마치며
대 AI시대라고 불릴 만큼 우리 생활에는 없어서는 안될 존재로 AI가 들어서있습니다. 제 전공인 코딩만 보더라도 단순 작업을 자동으로 실행해주고, 영어 단어도 번역해주고, 모르는 단어나 개념도 설명해주고, 심지어는 대신 코드도 작성해서 제공합니다. 꽤나 준수한 퀄리티로 말이죠. 하지만 뭐 AI가 일자리를 대체한다. AI 때문에 직업을 빼앗긴다. 이러다 AI가 세상을 지배하는 것 아니냐 등등 부정적인 얘기도 많습니다. 제 개인적인 생각이지만 아직 이 글을 쓰고 있는 현 시점에서 AI는 100을 알려주면 오직 1을 할 수 있는 애기에 불과하다고 봅니다. 저희의 역할은 이런 AI의 퍼포먼스를 내기 위해서 100이 아니라 10000을 알려주어 100을 할 수 있게 만드는 것이죠. 말이 좀 다른 길로 빠졌는데, 아무튼 앞으로는 인공지능을 제대로 활용할 줄 알아야 하고 그 중에서 LLM을 200% 활용하기 위해서는 좋은 프롬프트를 작성하는 방법을 알아야 한다는 겁니다. 그럼 오늘 포스팅은 여기서 마치고 다음 포스팅은 LLM이 답변을 줄 때 영향을 받는 인자나 요소에 대해서 얘기해보겠습니다.
'NLP' 카테고리의 다른 글
[NLP] LLM에서 할루시네이션이 발생하는 이유 (10) | 2024.11.26 |
---|---|
[NLP] Transformer의 함수 model.generate() 파라미터 (3) | 2024.11.25 |
[NLP] Korean LLM Leaderboard (3) | 2024.10.16 |
[NLP] Survey of Chatbot, Persona (7) | 2024.09.04 |
[NLP] NLP Task Review, 감정분석 (0) | 2024.07.11 |
[NLP] Similarity, 문서 유사도 측정 (0) | 2024.07.06 |
[NLP] Text Data Preprocessing (0) | 2024.07.02 |
[NLP] 정규 표현식, Regular Expression (0) | 2024.07.01 |