프롬프트 엔지니어링은 트랜잭션형 프롬프팅을 위한 것이다
프롬프트 엔지니어링 이야기가 나올 때마다 반복되는 혼란을 목격해 왔습니다. 제 생각에 그 혼란은 언어 모델을 사용하는 두 가지 전혀 다른 방식, 즉 대화형 프롬프팅과 트랜잭션형 프롬프팅에서 비롯됩니다. 프롬프트 엔지니어링은 주로 트랜잭션형 프롬프팅을 다루는 분야이며, 이를 대화형 프롬프팅에 그대로 적용하려 할 때 상당한 혼란과 부정적 반응이 생겨납니다.
대화형 프롬프팅은 ChatGPT처럼 언어 모델과 대화를 나누는 방식의 프롬프팅입니다. 모델이 모호한 답변을 내놓아도 기존 맥락을 활용해 추가 설명을 하거나 올바른 답변으로 유도할 수 있습니다. 또한 대화형 프롬프팅은 주로 사람이 직접 이끄는 방식입니다.
트랜잭션형 프롬프팅은 언어 모델을 프로그래밍 언어의 함수처럼 다룹니다. 입력을 주면 원하는 출력을 받는 식입니다. 단일 프롬프트에만 국한되지 않으며, 여러 프롬프트를 연결하거나 이른바 “에이전트”처럼 동작하게 할 수도 있습니다. 핵심은 매우 구체적인 문제를 해결하기 위해 언어 모델을 트랜잭션처럼 다루며, 대개 대량으로 소프트웨어가 주도한다는 점입니다.
‘프롬프팅’, ‘프롬프트’, ‘언어 모델’ 같은 용어는 이미 익숙하시다고 가정하겠습니다. 이러한 용어나 프롬프트 엔지니어링 전반에 대한 배경 지식이 필요하시면 이전 글인 Prompt Engineering vs. Blind Prompting을 참고해 주세요.
프롬프트 엔지니어링에 대한 지식은 이론상 어떤 방식이든 모델로부터 원하는 결과를 더 효과적으로 얻는 데 도움이 되므로 두 경우 모두에 도움이 될 수 있습니다. 하지만 프롬프트 엔지니어링의 가장 큰 효용은 트랜잭션형 사용 사례에 있다고 생각합니다.
프롬프트 엔지니어링은 언어 모델로부터 가장 높은 정확도와 가장 낮은 비용으로 원하는 결과를 얻어내는 것에 관한 것입니다. 이러한 목표는 트랜잭션형 사용 사례에 더 잘 부합합니다.
객관성 vs. 주관성
과정이 대화형인지 트랜잭션형인지 하는 구분만으로는 프롬프트 엔지니어링의 가치를 명확히 가르기에는 충분하지 않습니다. 또 다른 구분 축은 객관성과 주관성입니다.
객관적으로 올바르다고, 혹은 ‘대체로 올바르다’고 할 수 있는 출력이 나올 수 있는 입력이 있다면 프롬프트 엔지니어링을 성공적으로 적용할 수 있습니다. 객관적으로 정답이 존재하는 문제의 예로는 정보 추출, 분류, 제한적인 형태의 코드 생성 등이 있습니다.
반면 주관적으로만 올바르다고 할 수 있는 결과를 내는 입력이라면 프롬프트 엔지니어링의 효용은 훨씬 떨어집니다. 주관적 결과의 가장 대표적인 예는 예술 생성, 글쓰기, 시맨틱 서치와 같은 창의적 작업입니다.
예술을 객관적으로 좋다거나 나쁘다고 ‘엔지니어링’할 수 없는 것처럼, 주관적인 작업에 대해 LLM을 ‘프롬프트 엔지니어링’해서 객관적으로 좋거나 나쁘게 만드는 것 역시 불가능합니다. 주관적인 작업이라도 프롬프트 엔지니어링을 통해 결과물이 주관적으로 받아들여질 가능성을 높일 수는 있지만, 객관적인 작업에서처럼 높은 확실성이나 정확도를 기대할 수는 없습니다.
물론 주관적인 작업에서도 원하는 결과에 도달하는 데 도움이 되는 잘 알려진 ‘프롬프트 템플릿’이 많다는 점을 지적할 수도 있습니다. 예를 들어 특정 스타일의 예술을 안정적으로 생성하는 템플릿이 존재합니다. 하지만 이러한 프롬프트 템플릿에 도달하는 과정은 엔지니어링이나 과학적 실천이라기보다 창의적 글쓰기 과정에 가깝습니다.
저는 ‘코드 생성’을 객관적 작업이자 주관적 작업의 사례로 봅니다. 이론상 코드 생성은 객관적으로 올바를 수 있습니다. 소프트웨어의 동작에 대해 충분히 정확한 명세가 있다면, 해당 소프트웨어가 명세를 통과하는지 실패하는지를 객관적으로 판단할 수 있기 때문입니다. 하지만 현실에서는 거의 어떤 소프트웨어도 그 수준의 구체성을 갖추지 못합니다. 따라서 코드 생성 작업의 규모가 커질수록 더 주관적이 되고, 반대로 작업 규모가 작을수록 테스트 케이스나 입력 언어를 정확히 명세할 가능성이 높아져 더 객관적이게 됩니다1.
객관적이고 트랜잭션형인 프롬프팅
일반적으로 프롬프트 엔지니어링에 대한 지식은 어떤 작업을 하든 언어 모델로부터 원하는 정보를 추출하는 데 누구나 더 능숙해지도록 돕습니다. 다만 대화형 프롬프트에서의 프롬프트 엔지니어링은 효과적으로 구글링을 하는 사람, 즉 ‘Googler’(Google 검색 사용자)가 되는 것에 가깝다면, 트랜잭션형 프롬프트에서의 프롬프트 엔지니어링은 데이터 사이언티스트가 되는 것에 가깝습니다.
프롬프트 엔지니어링은 LLM을 결제, 프로세스 내 함수 호출, SaaS 호출 등 프로그램이 연동하는 다른 API처럼 객관적이고 예측 가능하며 트랜잭션형인 API로 만들려는 시도입니다. 물론 언어 모델은 결정론적이고 100% 신뢰할 수 있는 기계가 아니므로, 그 효용과 사용 사례는 달라야 합니다.
결론적으로 프롬프트 엔지니어링이 언어 모델과의 모든 프롬프트 상호작용에 적용되는 것은 아닙니다. 더 창의적이고 데이터 기반이나 방법론적이지 않은 상호작용도 존재합니다. 하지만 마찬가지로 언어 모델 중에는 엔지니어링 방법론을 적용해 최상의 결과를 얻을 수 있는 사용 사례도 있습니다. 두 가지는 서로를 부정하지 않고 공존합니다.
이 글 작성 시점을 기준으로 ‘에이전트’의 부상에 대해 명확히 하고 싶은 부분이 있습니다. 에이전트는 언어 모델과의 자동화된 대화형 프로세스라고 주장할 수도 있습니다. 기술적으로는 맞습니다. 하지만 제 생각에 에이전트의 용법은 주로 트랜잭션형입니다. 에이전트에게 작업을 맡기고 결과를 기다리는 형태이며, 그 결과가 객관적으로 올바른지 아닐지는 별개의 문제입니다. 에이전트는 대량으로 소프트웨어가 주도하는 트랜잭션형 특성을 가지므로 프롬프트 엔지니어링을 적용할 수 있습니다.
각주
코드 생성은 별도의 블로그 글로 다룰 만큼 큰 주제이지만, 앞으로 언어 모델을 이용해 더 크고 복잡한 소프트웨어의 코드를 생성하는 데 있어 가장 큰 과제는 명세의 부족함일 것이라고 생각합니다. 오늘날 에이전트들이 사람이 작성한 단위 테스트를 통과하기 위해 코드를 반복적으로 개선하며 동작하는 단순한 프로그램을 만들어내는 모습을 볼 수 있습니다. 어쩌면 미래에는 테스트 주도 개발(TDD) 움직임이 다시 활기를 띨지도 모릅니다. 물론 프로그램 합성, 프로그램 명세, 프로그램 증명은 학문적으로 매우 풍부한 연구 분야이므로, 그쪽에서의 사고가 융합될 가능성도 있습니다. 어쩌면 이미 그런 흐름이 있을지도 모르지만, 제가 꾸준히 지켜보는 연구 분야는 아닙니다. 어쨌든 미래는 흥미로울 것입니다! ↩
글을 무작위로 읽기