우리네 장
LLM 도입기 #1. 말 시키기 본문
최근 Open Ai가 관심을 많이 받게 되면서, 기업들에서 AI 기술에 집중하고 있는거 같아요!
아무래도 인공지능을 도입한 서비스가 화제성이 있어서 그런거 같은데..
저도 최근에 관련 프로젝트를 진행하게 되어 도입기를 간략하게 풀어보려고 합니다 . 🤓
저는 Azure의 Open AI 모델을 사용하고 있습니다. MS사의 LLM 모델은 크게 두 종류로 나눌 수 있어요.
Completion 모델과 Chat 모델입니다.
Completion 모델은 말 그대로 문장을 완성해 준다는 의미를 가지고 있어요. 그래서 LLM을 이용한 대표적인 작업들을 처리할 수 있는데, 문장 완성이라던가 요약 / 추출 / 창작 등을 위한 모델입니다. Chat 모델과 다른 점은 대화를 나누는 것이 아니라, 한 번의 질의만을 처리한다고 볼 수 있어요. 즉, stateless 입니다. 또, Completion 모델은 SystemMessage 라는 것이 별도로 존재하지 않아요. 그래서 instruction을 추가하고 싶으면 UserMessage에 포함하여 보통 작성합니다.
Chat 모델은 사용자와 semantic한 대화를 나눌 수 있는 LLM 모델 입니다.
문장의 의미를 파악할 수 있고, chat history를 통해 이전 대화 내역을 기억해서 연관성 있는 주제로 이야기 할 수 있어요.
물론 그냥 Chat 모델에게 그냥 말을 시킨다고 자동으로 chat history가 쌓이는 것은 아니고, 이전 대화부터 ~ 현재의 대화까지의 Message들을 List에 차곡차곡 담아서 넘겨주어야 합니다. 그래서 Message가 긴 경우에는 token이 모자라기도 합니다. 각 모델들은 허용 가능한 token의 범위가 있기 때문이죠. 물론 모델마다 모두 상이합니다.
Chat 모델에서 가장 우선시 되는 Message는 SystemMessage 입니다. 해당 메시지를 가장 잘 반영해서 답변을 만들어 낸다고 하죠!
오늘은 제가 SystemMessage를 구성하면서 체득한 프롬프팅 방법에 대해 공유하려고 합니다!! ❤️
프롬프팅 가이드 ⌨️
1. 역할을 지정해주자!
해당 방법은 여러 프롬프팅 가이드에서 소개하고 있는 방법입니다.
예를 들어,
역할 부여 전 | 역할 부여 후 |
출발 하기 전 패널티 값을 분석해줘. | 너는 항공권을 예약한 사람이야. 너는 출발 하기 전 항공권 취소에 대한 패널티 값을 알고 싶어. 해당 값을 분석해봐. |
2. 응답 예시를 너무 많이 적지 말자!
여러 프롬프팅 가이드에서 소개하고 있는 방법입니다.
모델에게 응답 예시를 가이드해서 우리가 원하는 대답을 하도록 답안 예시를 알려주는 것인데요.
다양하지 않고 너무 많은 응답 예시를 제공하는 것은 오히려 모델의 답변 질을 저하시키는 원인이었습니다.
예를 들어,
적정 응답예시 | 많은 응답예시 |
{ a: 0, b: 100, c: A }, { a: 23, b: 200, c: B } { a: 90, b: 300, c: C } |
{ a: 0, b: 100, c: A }, { a: 23, b: 200, c: B }, { a: 44, b: 100, c: A } { a: 90, b: 300, c: C } |
예시처럼 하나의 데이터만 추가적으로 삽입해도 답변의 질이 달라집니다.
또한 제가 어떤 부분은 ,를 넣고 어떤 부분은 ,를 넣지 않았죠?
,를 넣어서 응답을 제공하면 여러 개의 요소들을 응답으로 잘 추출합니다. 그러나 이 경우 하나의 요소만을 응답으로 주어야 하는 경우에도 여러 개의 요소들을 제공하는 경우가 있는데요.
위와 같이 에시를 제공하면 두 케이스에 모두 적절한 답변을 제공합니다.
3. , 대신 and를 사용하자.
모델에게 A와 B와 C인 경우에 ~~한 처리를 해줘. 라고 가이드를 주고 싶을 때,
저희가 영작으로 배운 문법으로는 A, B and C 가 맞습니다.
그러나 , 보다 and 로 모두 연결하는 것이 제 경우에는 더 말귀를 잘 알아듣더라구요.
A and B and C 로 질의하시는 것을 추천드립니다.
4. specific하게 가이드 하지 말자!
모델에게 너무 자세한 응답 가이드를 제공하면, 그 예시에 너무 과하게 적응해버리는 부분이 있는 거 같습니다.
예를 들면,
너무 자세한 가이드 | 러프한 가이드 |
~~면, { a:0, b:100, c: A }로 응답해줘. | ~~일 때, a는 0이고 b는 100이야. |
혹은 penalty 값을 분석해줘. 라고 했는데, 다른 user message에 service fee라는 명목으로 적혀있다면, penalty에 대한 지시문이 잘 먹지 않을 수 있습니다. 그러므로 좀 더 포괄적인 price가 더 좋은 응답을 만드는데 도움을 줍니다.
같은 맥락으로 모델에게 질의할 때 semantic하게 질의해아 합니다.
생각보다 사람과 대화하는 것처럼 명령을 주어도 알아서 잘 해독하더라구요?
오히려 요소 하나하나를 분석해서 가이드를 주면 답변의 질이 저하되었습니다.
5. instruction을 여러 문단에 배치하기.
처음에, 저는 시스템 메시지를 구성할 때 상단에 역할을 부여하고, 중간에 예시 응답, 하단에 주의해야 할 추가적인 instruction을 작성하였습니다.
그런데 하나의 프롬프트를 이용해서 여러 예시에 적용하려고 하면 점점 instruction이 늘어나게 되어있죠..
이렇게 추가된 가이드들을 계속해서 하단에 추가한다고 모델이 말을 잘 듣지 않습니다.
어떤 경우에는 스스로 우선순위가 있는지 가이드들 중 우선시 해서 적용하는 것과 무시당하는 instruction도 있었습니다.
저의 경우에는 instuction들을 여러 군데에 배치하였습니다.
배치 전 | 배치 후 |
""" {{역할 부여}} {{예시 응답}} (Hint!) instruction-1 instruction-2 instruction-3 instruction-4 instruction-5 """ |
""" {{역할 부여}} instruction-1 {{예시 응답}} instruction-2 instruction-3 (Hint!) instruction-4 instruction-5 """ |
6. 특수문자 사용하기!
이것도 여러 프롬프트 가이드에서 제시하는 방법 중 하나입니다.
제가 느끼기에는 무작정 사용하는 것은 별로 의미가 없어보이고,
프롬프트 메시지에 사용되지 않은 특수문자를 사용하는 것이 효과가 있어보였습니다.
단순히 '###' 이렇게 표시하는 것보다, 의미를 추가하는 것이 좋습니다.
예를 들어,
###예시 응답### 이라던가
(힌트!) 가 될 수 있겠습니다!
7. top-p 혹은 temperature 적절하게 조정하기.
OpenAiClient 클래스에는 다양한 설정 변수가 존재합니다.
그 중 temperature는 응답의 다양성을 결정하는데요. 값이 높을수록 창작하는 역할에 적합하고, 답이 정해져 있는 경우에는 값을 낮게 하는 것이 좋습니다.
top-p는 응답으로 적절할 것 같은 상위권 답변 중 N개를 추출하겠다는 의미인데요.
이 값 또한 다양성에 영향을 주는 값입니다.
0.1 이면 상위 1개의 응답을,
0.2이면 상위 2개의 응답을,
0.3이면 상위 3개의 응답 중에서 답을 추출하겠다는 의미에요.
답이 정해져 있는 경우는 0.1이 적합하다고 볼 수 있습니다.
또한 두 필드를 모두 수정하는 것보다, 둘 중 하나만을 설정하는 것이 좋다고 합니다.
저는 temperature보다 top-p를 0.1로 하였을 때 답변의 일관성에 도움을 많이 받았습니다.
생각보다 효과 없던 프롬프팅 기술 🥲
1. 영어 대소문자
영어 대문자를 사용한다고 해서 모델이 그 부분을 더 주의한다던가 하는 효과는 전혀 없었습니다..
2. 부정어 쓰지 말라.
부정어 말 잘 듣습니다!
아마 여러 가이드에 나와있는 '부정어 쓰지 말라'는 의미는 우리가 코끼리를 생각하지 말라고하면 바로 머리에 코끼리가 생각나는 것과 같은 의미인 것 같습니다.
그러나 부정어 가이드도 잘 듣습니다! 하지만 포함시키고 싶지 않은 단어를 여러 번 반복해서 가이드를 주는 것은 확실히 모델 응답에 좋지 않습니다.
3. 팁 준다고 하기..
어떤 프롬프팅 가이드 게시글에서 모델에게 팁을 준다고 하면 응답을 잘 준다고 하더라구요?
그러나 저는 효과가 없었습니다.. 다른 프롬프트 형식에서는 효과가 있을 수 있겠습니다!
4. COT
생각의 사슬 기법은 정말 유명한 프롬프팅 기법입니다.
자세히 생각의 흐름을 작성하지 않아도, 모델에게 think step by step 이라고 가이드 해주는 것만으로도 큰 효과가 있다고 하죠!
그러나 이는 '추론' 작업을 할 때 효과가 극대화 되는 것 같습니다.
LLM 모델은 기계이지만 계산을 할 수 없습니다. 그래서 산술 계산을 하는 것 또한 '추론'의 영역에 들어갑니다.
예를 들어, 숫자 리스트에서 홀수를 먼저 선택해 > 그 값들을 모두 곱해 > 그 값이 짝수인지 홀수인지 판단해줘.
그러나 저는 현재 모델을 '추출' 작업을 하는데 사용하기 때문에,
생각의 사슬 기법이 먹히지 않았습니다.
이렇게 프롬프팅은 어떤 가이드를 제시하면 효과가 극대화 되고 어떤 거는 영 효과가 없다가 아니고,
어떤 프롬프팅을 작성하느냐, 프롬프팅 구조를 어떻게 잡고 내용을 어떻게 구성했느냐에 따라 효과가 있는 프롬프팅 가이드가 다릅니다.
그래서 답은 여러 상황에 매우 많은 메시지를 날려보고, 본인 나름대로 형식을 잡는거 뿐이죠!
여러분에게 도움이 되셨길 바랍니다 🥳