본문으로 건너뛰기
02. 프롬프트 실행

02. 프롬프트 실행

✎ 이 문서 수정하기 GitHub에서 수정

대화창에서 좋은 답을 한 번 얻는 것과 프로그램에서 같은 작업을 반복하는 것은 다르다. 코드에서는 입력 변수를 조립하고, 응답 객체에서 필요한 값을 꺼내며, 잘못된 출력과 호출 실패를 처리해야 한다.

2.1 프로그램에서 프롬프트 실행

프롬프트 호출은 원격 서비스 요청이다. 인증과 모델 식별자, 요청 메시지를 보내고 응답을 받는다. 모델의 작업 실패와 네트워크나 인증 실패를 같은 문제로 취급하면 원인을 찾기 어렵다.

2.1.1 실행 환경

가상환경은 프로젝트별 Python과 라이브러리 의존성을 분리한다. Jupyter 커널이 실제로 어느 환경을 사용하는지도 확인해야 한다. 터미널에 설치한 패키지와 노트북에서 실행하는 인터프리터가 다르면 import가 실패하거나 다른 버전이 실행될 수 있다.

API 키는 코드나 노트북 출력에 직접 넣지 않는다. 환경 변수나 비밀 입력으로 전달하고, 버전 관리에 포함하지 않는다. 실행 환경을 재현하려면 라이브러리 버전과 모델 설정도 함께 남겨야 한다.

2.1.2 최소 호출

최소 호출에서도 입력, 메시지, 응답을 분리해서 본다. 사용자 입력 문자열을 역할이 있는 메시지로 감싸 모델에 보내고, 응답 객체에서 생성된 내용을 읽는다.

응답 객체에는 본문 외에 종료 이유나 사용량 같은 정보가 들어갈 수 있다. 출력 토큰 제한으로 잘렸거나 도구 호출을 요청한 응답을 일반적인 최종 문장과 똑같이 처리해서는 안 된다.

모델 이름을 바꾸면 지원하는 파라미터와 출력 형태도 달라질 수 있다. 예제의 모델 식별자를 설치 환경과 제공자 문서에 맞춰 확인해야 한다.

2.2 LangChain으로 실행

LangChain은 제공자별 클라이언트 위에 공통 호출 인터페이스를 제공한다. invoke()로 한 번 실행하고, 필요하면 스트리밍이나 배치 같은 실행 방식으로 확장할 수 있다.

텍스트 모델의 출력과 채팅 모델의 출력은 구분해야 한다. 채팅 모델은 보통 AIMessage 같은 메시지 객체를 반환한다. 이를 그대로 문자열이라고 가정하면 이후 JSON 해석이나 문자열 결합이 실패할 수 있다.

prompt | model | parser처럼 연결하면 각 단계의 책임이 드러난다. 템플릿은 입력을 조립하고 모델은 응답을 만들며 파서는 다음 코드가 사용할 값으로 해석한다. 파서가 JSON 문법을 처리해도 필드의 의미와 값의 범위까지 자동으로 맞는 것은 아니다.

2.3 프롬프트 템플릿

템플릿은 고정된 지침과 요청마다 달라지는 값을 분리한다. 요약이라면 원문, 목표 길이, 문체가 변수일 수 있다.

2.3.1 Python 함수로 구성

문자열 포맷팅으로도 템플릿을 만들 수 있다. 핵심은 지침과 입력을 섞어서 임의의 문자열을 만드는 대신, 어떤 변수가 필요한지 명시하는 것이다.

예를 들어 요약 요청은 “다음 텍스트의 핵심 주장과 근거를 세 문단으로 정리한다”는 고정 지침과 실제 문서 본문으로 나눌 수 있다. 원문 안에 “앞의 지침을 무시하라”는 문장이 있어도 분석할 데이터이지 애플리케이션의 지시가 아니다.

문자열이 완성됐다는 사실과 프롬프트의 경계가 명확하다는 사실도 다르다. 문서, 질문, 출력 조건을 구분하고 외부 입력을 어떤 신뢰 수준으로 넣는지 정해야 한다.

2.3.2 PromptTemplate

PromptTemplate은 템플릿 변수와 포맷 과정을 공통 객체로 관리한다. 입력 사전에 필요한 키가 있는지, 템플릿에서 어떤 값이 사용되는지 확인하기 쉽다.

중괄호를 쓰는 JSON 예시를 템플릿에 넣을 때는 변수 자리와 JSON 중괄호를 구분해야 한다. 리터럴 중괄호의 이스케이프 방식도 템플릿 문법에 따른다.

템플릿을 버전 관리하면 모델이 달라진 것인지 지침이 달라진 것인지 비교할 수 있다. 모델 응답만 저장하고 완성된 프롬프트를 남기지 않으면 결과 차이의 원인을 찾기 어렵다. 단, 실제 입력에 개인정보가 있다면 기록 범위와 마스킹도 필요하다.

2.4 작업별 프롬프트

2.4.1 텍스트 분류

분류에서는 허용 범주와 판단 기준을 먼저 정한다. “고객 문의를 분류하라”보다 “오류 신고, 기능 요청, 결제 문의 중 하나를 반환하라”가 출력 공간을 명확하게 만든다.

범주를 고를 수 없는 입력도 있다. 여러 목적이 섞인 문의를 한 범주로 강제할지, 복수 범주를 허용할지, 검토 대상으로 넘길지 정해야 한다. 출력 예시에 없는 범주가 나왔다면 코드에서도 검증해야 한다.

2.4.2 감정 분석

감정 분석은 긍정, 중립, 부정 같은 태도를 분류하는 작업이다. 주제와 감정의 대상을 함께 봐야 한다. “배송은 늦었지만 제품은 좋다”는 문장을 전체 감정 하나로 압축하면 중요한 차이를 잃을 수 있다.

여러 문장을 한 번에 처리할 때는 입력 식별자를 결과에 유지해야 한다. 행 순서가 바뀌거나 일부 결과가 누락될 수 있으므로 텍스트만 나열한 출력보다 식별자와 범주를 가진 구조가 안전하다.

2.4.3 요약

요약은 원문에서 무엇을 남길지 결정하는 작업이다. 분량만 정하면 핵심 주장보다 눈에 띄는 예시를 남길 수도 있다. 목적, 포함할 내용, 유지할 수치와 조건을 명시해야 한다.

“세 문장”은 출력 길이의 조건이고 “결론의 적용 조건을 빠뜨리지 않는다”는 정보 보존의 조건이다. 두 조건이 충돌하면 어느 쪽을 우선할지도 중요하다. 짧고 매끄러운 문장이 원문의 의미를 보존했다는 보장은 없다.

2.4.4 글 작성

제공된 사실을 바탕으로 글을 구성하는 작업이다. 요약과 달리 문장 구조와 연결 표현을 새로 만들 수 있지만, 주어진 사실에 없는 수치나 사례까지 추가해도 된다는 뜻은 아니다.

사실 목록과 원하는 문체, 대상 독자, 출력 구조를 나누면 결과를 검토하기 쉽다. 근거가 없는 부분을 창작해도 되는 작업과 그렇지 않은 작업도 구분해야 한다.

2.4.5 질의응답

질의응답은 질문에 필요한 내용을 문맥에서 찾아 답하는 작업이다. 전체 문서를 요약하는 것과 달리 관련 정보의 위치와 조건을 정확하게 집어야 한다.

문서에 답이 없는 경우를 포함해 규칙을 정해야 한다. 답을 찾지 못했는데 일반 지식으로 메워 버리면 문서 기반 응답이라는 계약이 깨진다. 출처 위치를 함께 반환하면 사실과 근거를 비교하기 쉽다.

2.4.6 추론

추론은 주어진 정보에서 관계를 적용해 결론을 내리는 작업이다. 단순한 사실 추출보다 중간의 분류와 계산이 정확해야 한다.

예를 들어 숫자 목록에서 조건에 맞는 수를 고른 뒤 합계를 구한다면, 원소 선택 오류와 덧셈 오류는 다른 실패다. 결과 숫자 하나만 보면 어디서 틀렸는지 알기 어렵다. 선택한 항목과 계산 결과를 분리해 확인하는 편이 낫다.

2.5 예시와 단계로 작업을 구체화하기

Zero-shot은 예시 없이 지침만 제공하는 방식이다. One-shot과 few-shot은 예시를 넣어 원하는 대응 관계를 보여 준다. 여기서 learning은 현재 문맥 안의 패턴 적용이며 가중치를 재학습하는 과정이 아니다.

2.5.1 One-shot

예시 하나는 출력 모양을 보여 주는 데 유용하지만 규칙의 모든 경우를 설명하지 못할 수 있다. 회문 판별에서 121만 보여 주면 한 자리 숫자나 두 자리 숫자, 0으로 시작하는 문자열을 어떻게 처리할지 여전히 모호하다.

예시는 정답과 입력의 관계를 드러내야 한다. 원하는 결과 하나를 보여 준 것과 일반적인 판별 규칙을 정의한 것은 다르다.

2.5.2 Two-shot

두 예시는 적용 범위를 넓힐 수 있지만, 단순히 수를 늘리는 것만으로 오류가 사라지지는 않는다. 같은 형태의 쉬운 예시 두 개보다 서로 다른 경계 조건을 보여 주는 예시가 유용할 수 있다.

책의 숫자 문제도 예시를 추가해도 일부 항목을 누락한다. 모델의 자연스러운 설명과 실제 판별 결과가 일치하는지 따로 확인해야 한다는 사례다.

2.5.3 처리 단계 제공

조건 확인, 대상 추출, 계산, 결과 점검처럼 작업을 분해하면 요구가 분명해진다. 실패를 분석할 단위도 생긴다.

다만 단계를 적었다고 계산 정확도가 보장되는 것은 아니다. 결정적인 규칙이나 산술은 코드로 처리하는 편이 나을 수 있다. LLM이 자연어 요구를 해석하고 코드가 검증 가능한 계산을 수행하도록 역할을 나눌 수 있다.

2.5.4 Few-shot

여러 예시로 입력과 출력의 패턴을 전달한다. 예시에는 정상 사례뿐 아니라 여러 조건이 동시에 맞는 경우, 어느 조건에도 맞지 않는 경우를 포함할 필요가 있다.

예를 들어 두 조건에 따라 서로 다른 범주를 붙인다면 첫 조건만 맞는 입력, 둘째만 맞는 입력, 둘 다 맞는 입력, 둘 다 아닌 입력이 서로 다른 역할을 한다. 모델이 이미 아는 유명한 규칙을 재현한 것인지, 제공한 새 규칙을 적용한 것인지도 구분해야 한다.

예시를 많이 넣으면 토큰 비용과 문맥 사용량이 늘어난다. 모순된 예시나 잘못된 예시가 있으면 오히려 동작이 불안정해질 수 있다.

2.5.5 LangChain의 few-shot 템플릿

예시 하나의 입력과 출력을 표현하는 템플릿을 만들고, 여러 예시와 공통 지침, 현재 질문을 조합한다. FewShotPromptTemplate은 이 구성을 관리하는 객체다.

예시 목록과 실제 사용자 입력은 분리해야 한다. 테스트할 정답을 프롬프트 예시에 잘못 포함하면 성능을 과대평가할 수 있다. 예시 선택 기준과 순서를 바꾸는 것도 프롬프트 변경에 포함된다.

2.5.6 Chain of Thought

복합 문제를 중간 단계로 나누고 그 예시를 함께 제공하는 접근이다. 단순히 최종 답만 요구할 때보다 어떤 규칙과 절차를 적용할지 구체화한다.

출력된 설명이 실제 내부 계산을 그대로 보여 준다고 가정할 수는 없다. 설명이 그럴듯해도 최종 답과 중간 값이 틀릴 수 있다. 필요한 것은 장문의 사고 과정 자체보다 선택한 항목, 계산 결과, 확인할 근거처럼 검증 가능한 산출물이다.

추론형 모델은 제공자가 권장하는 지침이 일반 채팅 모델과 다를 수 있다. 모든 모델에 같은 형식의 단계별 설명을 강제하기보다 실제 작업에서 정확도와 비용을 비교해야 한다.

2.6 프롬프트 구조

요소정하는 것예시
역할수행할 업무의 관점문서의 사실을 점검하는 편집자
문맥작업을 이해하는 데 필요한 배경문서의 목적과 적용 범위
지시수행할 동작핵심 주장과 조건 추출
입력실제 처리할 자료원문, 질문, 항목 목록
단계필요한 처리 순서분류 후 계산하고 결과 검증
문체표현 방식간결한 기술 설명
출력 형식후속 코드가 받을 구조식별자와 결과를 가진 JSON

모든 요청에 모든 요소가 필요한 것은 아니다. 단순 분류에 장문의 역할극이 항상 도움이 되는 것도 아니다. 작업에서 불확실한 부분을 줄이는 데 필요한 요소를 선택한다.

출력 형식을 JSON으로 요청해도 파싱과 스키마 검증은 필요하다. 필수 필드가 없거나 숫자 자리에 문장이 들어가면 실패로 다뤄야 한다. 유효한 JSON이더라도 내용의 사실성은 별도 평가다.

결과를 비교할 때

프롬프트를 개선하려면 대표 입력을 고정해 이전 버전과 비교해야 한다. 쉬운 예시 하나의 결과만 보고 전체 품질이 좋아졌다고 판단하면 안 된다.

분류에서는 경계 사례와 허용 범주, 요약에서는 누락된 사실과 추가된 주장, 질의응답에서는 근거와 답할 수 없는 질문을 확인한다. 모델 버전과 프롬프트, 생성 설정을 함께 기록해야 변경의 영향을 해석할 수 있다.

질문

예시가 많을수록 좋은 프롬프트일까?

예시의 대표성과 정확성이 먼저다. 서로 중복되거나 모순된 예시는 비용만 늘리거나 판단을 흐릴 수 있다.

JSON으로 응답하면 프로그램에서 바로 믿고 써도 될까?

문법, 스키마, 업무상 의미가 모두 맞아야 한다. 세 검증은 서로 다르다.

이전: AI 애플리케이션과 에이전트 / 시리즈 목차 / 다음: 문서 요약

마지막 수정 일자