생성형 AI 제대로 다뤄보기 (3): Prompt-Engineering (complex NLP)

Joowon Kim
11 min readFeb 23, 2023

--

이번 글에서는 GPT-3와 Prompt-Engineering 기술만을 이용해서 거의 모든 복잡한 NLP 과제를 수행할 수 있도록 하는 내용을 담았습니다. 이것을 응용하면 GPT 모델이 파이썬 스크립트를 작성하거나 jinja2와 같은 템플릿 엔진을 위한 문서를 작성하도록 지시할 수 있습니다.

GPT-3를 단순 텍스트 생성기가 아닌 다재다능한 Assistant 로써 바라볼 수 있게 될 것입니다.

시작하기 전에…

  • 예제를 코드 형태로 사용해보실 수 있도록 github에 올려두었어요! (link)
  • 셋팅 관련한 글은 이전글을 확인해주세요. (link)
  • coxwave 블로그에 생성형 인공지능 관련 다양한 글도 업로드되고 있어요 :)

0. GPT-3 로 복잡한 자연어 처리 작업 수행하기

https://dallery.gallery/the-dalle-2-prompt-book/

Stable-Diffusion과 같은 이미지 생성물 모델은 Prompt 에 담긴 묘사(framing, film type, …)가 상세할수록 더 좋은 품질의 이미지를 그려줄 확률이 높아요. 이미지 생성 인공지능 쪽에서는 이러한 묘사를 체계화하는 것을 Prompt-Design이라 부르고, 위의 사진처럼 필요한 요소가 모두 있을 경우 좋은 Prompt로 여기죠.

만약 사용자가 입력한 Prompt에서 빠진 묘사들을 이미지 생성 전에 알려주고 적절한 단어를 미리 추천할 수 있다면, 그림에 대한 결과물을 받았을 때 사용자의 감동이 더 클 확률이 높을거에요.

이번 예시의 요구사항은 다음과 같아요. 꽤 어려워 보이죠?

- 사용자의 Prompt를 잘 분할하고 묘사 카테고리에 mapping 할 수 있는 Prompt-Parser가 필요해요.
- 빠진 카테고리에 대해 알아서 단어를 채워줄 수 있는 Prompt-Suggester 가 필요해요
- 출력은 json 형태여야 해요.

최종 입출력의 예시는 아래와 같아요.
in: “A close-up, black & white studio photographic portrait of SUBJECT, dramatic backlighting, 1973 photo from Life Magazine.”
out: {
parser: {
year&usage: [1973 photo from Life Magazine],
lighting: [dramatic backlighting],
shoot-context: [studio photographic portrait],
framing: [close-up],
film-type: [black & white],
lens&camera: [None],
subject: [SUBJECT]
},
suggestion: { lens&camera: [studio lens] }
}

1. 가볍게 Prompt 작성

이전 Case에서 배운 내용을 바탕으로 기본적인 Prompt를 작성한 다음 실행해보면 아래와 같은 결과를 얻을 수 있어요.

한번에 성공

생성물: { parser: { year&usage: [1973, Life Magazine], lighting: [dramatic backlighting], shoot-context: [studio], framing: [close-up], film-type: [black & white], lens&camera: [None], subject: [SUBJECT] }, suggestion: { lens&camera: [studio lens] } }

솔직히 생각보다 너무 잘해서 당황했어요. 다만 Prompt Engineering 만으로는 결과물이 많이 불안정해요. 예시를 하나만 더 볼게요.

생성물: { parser: { year&usage: None, lighting: None, shoot-context: indoors, framing: full-shot, film-type: None, lens&camera: None, subject: people, animal }, suggestion: { year&usage: None, lighting: None, shoot-context: None, framing: None, film-type: None, lens&camera: None, subject: None } }

2. GPT-3에 예시 제공하기

Parser의 자료형이 제가 원했던 list 형태가 아니며, Suggestion은 None 말고 뭔가 다른 것들을 추천해줘야 하는데 많이 아쉽죠. 복잡한 Task를 이렇게 명령문으로만 작업시키면 입력에 따라 결과 포맷이 바뀌고 성능이 불안정해요. 모델이 잘 작동하기 위해서는 반드시 예제를 제공해야 해요.

예제를 주는 방법은 간단해요. 본인이 생각하는 모범 질문과 답변을 적어주고 그 다음 줄에 stop sequence 를 써주면 돼요. 저같은 경우 “###” 을 stop sequence로 사용하는 편이에요. playground 환경 오른쪽 네비게이션 부분에서 추가할 수 있어요.

예제를 제공하고 다시 실행

생성물: { parser: { year&usage: [None], lighting: [None], shoot-context: [None], framing: [None], lens&camera: [None], subject: [man, dog] }, suggestion: { year&usage: [None], lighting: [None], shoot-context: [None], framing: [None], lens&camera: [None] } }

이제 포맷은 잘 잡아주는데 suggestion이 잘 작동하지 않네요. 여러가지 일을 한번에 명령하는 경우 자주 발생하는 일이에요. 예제를 다수 추가해서 방향을 잡아줄 수 있지만 훨씬 더 효율적이고 잘 먹히는 방법이 있어요. (그리고 예제를 많이 추가할수록 실행 비용이 비싸져요)

3. 중간과정 알려주기(프롬프트 연쇄)

이 기법은 Curriculum Learning, Prompt Chain 등 여러 개념이 섞여있어요. 핵심은 인공지능 모델에게 복잡한 일을 시킬 때, 지침과 예제만 제공하는 것이 아니라 의도한 출력이 나오기까지의 중간과정도 함께 보여주는 것이에요.

우리의 suggester는 빠진 묘사 카테고리에 대해 작동해야 하니, 중간 과정을 프롬프트에 한번 적어주도록 할게요. 예제의 in, out 사이에 missing 필드를 추가했어요. (사용 토큰을 줄이기 위해 필드명은 짧을수록 좋아요)

예제에 missing 정보를 줌으로써 suggestion 범위 지정

그리고 “out:” 으로 시작하는 것이 아니라 “missing:” 부터 모델이 생성하도록 해보면 아래 사진과 같은 결과가 나와요.

성공적인 결과물

요구사항대로 아주 잘 작동하는 것을 확인할 수 있어요. 이런 방식으로 아무리 복잡한 NLP 작업이라도 GPT-3를 이용해 조금은 가벼운 마음으로 시도해볼 수 있어요. 이 글에서는 json을 생성하도록 했지만, 파이썬 스크립트를 작성하거나, 템플릿 엔진과 연동하여 훨씬 다양한 작업들을 수행할 수 있어요. 특히 chatbot 쪽에서 잘 활용할 수 있는데, chatGPT API가 공개되었으니 이쪽 컨텐츠도 금방 준비해보도록 할게요.

Appendix 1) 예시를 위해 사용한 Prompt

Knowledge:
- 좋은 Prompt는 7개 category에 대한 정보를 모두 가지고 있어야 한다.
- category 1) [year&usage]: 2023 New York Times, 2019 Instagram, ...
- category 2) [lighting]: golden hour, ...
- category 3) [shoot-context]: indoors, portrait, outdoors, ...
- category 4) [framing]: full-shot, wide-shot, medium-shot, long-shot, ...
- category 5) [film-type]: colorful, ...
- category 6) [lens&camera]: wide-angle lens, ...
- category 7) [subject]: people, animal, ...

Persona:
- parser는 제공된 문장을 분해한 다음, 좋은 Prompt의 category에 맞게 mapping한다.
- parser는 mapping된 구절이 없을 경우 None이라는 단어로 mapping 한다.
- parser는 새로운 단어들을 추가하거나 문장을 변형하지 않는다.
- suggestion는 parser의 출력값 중 None이 있을 경우 적절한 단어를 추천한다.
- json 형식의 데이터를 출력한다.
- 출력값의 형태는 아래와 같다. { parser: { [list of categories]: [list of words]}, suggestion: { [list of categories]: [word] }}

in: A close-up, black & white studio photographic portrait of SUBJECT, dramatic backlighting, 1973 photo from Life Magazine.
missing: [ lens&camera ]
out: { parser: { year&usage: [1973 photo from Life Magazine], lighting: [dramatic backlighting], shoot-context: [studio photographic portrait], framing: [close-up], lens&camera: [None], subject: [SUBJECT] },
suggestion: { lens&camera: [studio lens] } }
###
in: The man is looking at the cute dog.
missing: [ year&usage, lighting, shoot-context, framing, film-type, lens&camera ]
out: { parser: { year&usage: [None], lighting: [None], shoot-context: [None], framing: [None], film-type: [None], lens&camera: [None], subject: [man, dog] },
suggestion: { year&usage: [recent], lighting: [natural], shoot-context: [outdoors], framing: [medium-shot], film-type: [black & white], lens&camera: [telephoto lens] } }

Appendix 2) 출력 포맷 제어 예제

세번째 예시는 원래 notion 에서 새로운 기능으로 등장한 notionAI 를 만드는 과정을 담으려 했는데, Prompt-Injection 공격에 Prompt가 전부 공개되었어요. 직접 보시는거로 충분할거라 생각하기 때문에 이번 케이스는 링크만 남겨두도록 할게요.

--

--

Joowon Kim

AI-Native 제품을 분석하고 개선하기 위한 Product-Analytics Tool을 만들고 있습니다.