Menu

프롬프트 반복 개선: 테스트하고 고치는 방법

프롬프트 개선은 작은 실험처럼 할 때 가장 잘 됩니다. 좋은 답의 조건을 정하고, 고정된 테스트 입력 몇 개를 두고, 한 번에 하나씩 바꾸고, 출력을 나란히 비교하세요.

이 페이지의 모든 프롬프트는 수정한 뒤 ChatGPT, Claude 등 AI 앱에서 바로 열 수 있습니다.

프롬프트의 첫 버전은 초안입니다. 원하는 것에 가까운 결과를 얻는 경우가 많고, 가까운 것과 맞는 것 사이의 틈은 반복 개선으로 메웁니다. 의도를 가지고 프롬프트를 바꾸고, 같은 입력으로 다시 실행하고, 그 변경이 도움이 됐는지 확인하는 것입니다. 대충 하면 반복 개선은 운 좋은 출력 하나가 괜찮아 보일 때까지 표현을 아무렇게나 바꾸는 일이 됩니다. 작은 실험처럼 하면 테스트한 입력 하나만이 아니라 다음 백 개의 입력에서도 통하는 프롬프트를 얻습니다.

방법은 다섯 단계입니다. 좋은 것이 무엇인지 정의하고, 테스트 입력을 고정하고, 한 번에 하나씩 바꾸고, 출력을 비교하고, 언제 멈출지 아는 것입니다.

좋은 답이 어떤 모습인지 정의하기

무엇이든 고치기 전에, 출력이 해야 할 일을 예나 아니요로 답할 수 있는 검사 항목으로 적으세요. "좋은 커밋 메시지"는 검사할 수 없습니다. 다음은 검사할 수 있습니다.

  1. 제목 줄이 50자 미만이다.
  2. Conventional Commits 형식(fix:, feat: 등)을 따른다.
  3. 본문은 diff가 이미 보여 주는 것이 아니라 변경이 필요했던 이유를 말한다.
  4. 이슈가 있으면 이슈 번호를 언급한다.

기준은 두 가지 일을 합니다. 프롬프트에 무엇을 더할지 알려 줍니다. 각 기준이 빠진 지시인 경우가 많기 때문입니다. 그리고 출력이 얼마나 듣기 좋은지로 판단하지 않게 막아 줍니다. 그것이 자신 있지만 틀린 답을 받아들이는 가장 쉬운 길입니다.

테스트 입력을 조금 모아 두기

입력을 3~10개 골라서 작업하는 동안 고정해 두세요. 전형적인 경우, 까다로운 경우 몇 개(빈 필드, 아주 긴 입력, 프롬프트가 예상하지 못한 언어), 그리고 이전에 실패했던 모든 입력을 넣으세요. 예시 하나에 맞춰 다듬은 프롬프트는 그 예시에는 맞지만 다음 예시에서 실패하기 쉽습니다.

프롬프트를 입력 자리가 있는 템플릿으로 써서, 모든 버전이 정확히 같은 자료로 실행되게 하세요.

한 번에 하나씩 바꾸기

역할, 형식, 예시를 한꺼번에 바꿨는데 출력이 좋아지면, 어떤 변경 덕분인지 알 수 없고 쓸모없는 수정 두 개를 계속 달고 갈 수도 있습니다. 하나를 바꾸고, 실행하고, 비교하세요. 아래 탭은 한 프롬프트의 세 버전이고, 각각 앞 버전에서 한 가지만 바꾼 것입니다.

이 diff에 대한 커밋 메시지를 써 줘.- if len(password) > 8: + if len(password) >= 8: return True
Try it
Example replyReplies vary between models and runs.

비밀번호 길이 검증 업데이트

이 커밋은 비교 연산자를 >에서 >=로 바꿔 비밀번호 검증 로직을 업데이트합니다. 그 결과 정확히 8자인 비밀번호도 이제 유효한 것으로 간주됩니다. 이 변경은 검증의 정확도를 높이고 계정을 만드는 사용자에게 더 나은 경험을 제공합니다.

버전 1은 기준 2와 3을 통과하지 못합니다. 제목에 타입 접두어가 없고, 본문은 diff를 더 많은 말로 다시 설명합니다. 버전 2는 형식 요구 사항을 더해서 기준 1과 2를 통과하지만, 본문은 여전히 diff를 설명합니다. 뻔한 다음 수정은 지시를 하나 더 넣는 것("이유를 설명해")이지만, 모델은 들은 적 없는 이유를 설명할 수 없습니다. 버전 3은 대신 빠진 맥락을 더했고, 요청하지 않았는데도 본문과 이슈 참조가 따라 나왔습니다. 이것이 반복 개선에서 가장 흔한 교훈입니다. 지시로 출력이 고쳐지지 않는다면, 대개 프롬프트에 빠진 것은 강조가 아니라 정보입니다.

출력을 나란히 비교하기

모든 버전을 모든 테스트 입력으로 실행하고, 각각을 여러 번 실행하세요. 채팅 모델은 단어를 샘플링하므로 같은 프롬프트도 두 번 실행하면 결과가 다릅니다. 출력을 나란히 놓고, 지난 실행에 대한 기억이 아니라 기준에 비춰 확인하세요.

기준이 정확하다면 두 번째 모델 호출로 1차 채점을 할 수 있습니다. 기준을 풀어 쓴 채점 프롬프트에 출력을 붙여 넣으세요.

고정된 기준으로 출력 채점하기
Fill in
아래 각 출력을 기준에 비춰 확인해 줘. 기준마다 통과 또는 실패로 답하고, 출력을 인용한 짧은 이유를 붙여 줘. 나열된 기준만 판단해. 길이나 문체에 점수를 주지 마. 기준: 1. 제목 줄이 50자 미만. 2. Conventional Commits를 따름. 3. 본문이 diff가 보여 주는 것이 아니라 변경이 필요했던 이유를 말함. 4. 이슈 번호를 언급함. 출력 A: """ fix: 정확히 8자인 비밀번호도 허용 정확히 8자인 비밀번호가 검증을 통과하도록 길이 검사를 >에서 >=로 변경. """ 출력 B: """ fix: 정확히 8자인 비밀번호도 허용 가입 페이지는 최소 8자를 요구하는데 검사가 정확히 그 길이의 비밀번호를 거부해서, 안내를 따른 사용자가 가입할 수 없었음. Fixes #412 """ 기준마다 한 행씩 표로 답해 줘.
Try it
Example replyReplies vary between models and runs.
기준출력 A출력 B
1. 제목 50자 미만통과: 제목이 21자통과: 같은 제목, 21자
2. Conventional Commits통과: "fix:"로 시작통과: "fix:"로 시작
3. 본문이 이유를 설명실패: "길이 검사를 >에서 >=로 변경"은 diff를 다시 말할 뿐통과: "안내를 따른 사용자가 가입할 수 없었음"
4. 이슈 언급실패: 이슈 번호 없음통과: "Fixes #412"

모델 채점자는 심판이 아니라 조수로 다루세요. Zheng 등의 2023년 논문 "Judging LLM-as-a-Judge with MT-Bench and Chatbot Arena"는 모델 심판의 편향을 기록했는데, 긴 답을 선호하고 특정 위치의 답을 선호하는 것이 포함됩니다. 기준은 확인할 수 있게 유지하고, 인용된 증거를 요청하고, 둘을 비교할 때는 A와 B의 순서를 바꾸고, 출력 일부는 직접 읽으세요. 글자 수 세기 같은 검사는 모델의 판단보다 코드 한 줄이 더 믿을 만합니다.

대화가 아니라 프롬프트를 고치기

채팅에서는 후속 메시지로 답을 고치고 싶어집니다. "더 짧게", "아니, 이슈를 언급해", "다른 형식으로". 그러면 좋은 출력 하나는 얻지만 프롬프트는 여전히 그대로 나쁩니다. 수정이 통했다면 그것을 프롬프트로 옮기고, 프롬프트를 새로 실행하세요. 다음에 결과가 필요할 때 메시지 다섯 개를 반복하는 대신 하나만 붙여 넣으면 됩니다.

예전 버전은 무엇을 바꿨고 무엇을 고쳤는지 한 줄 메모와 함께 남겨 두세요. 평범한 텍스트 파일이면 충분합니다. 나중의 수정이 상황을 나쁘게 만들면, 프롬프트가 예전에 뭐라고 했는지 기억해 내려 애쓰는 대신 되돌아갈 수 있습니다.

코드로 비교 실행하기

프롬프트를 API로 실행하게 되면, 짧은 스크립트로 모든 버전과 모든 테스트 입력의 결과를 나란히 볼 수 있습니다. 이 스크립트는 OpenAI Python SDK를 쓰고, 위에서 아래로 읽을 수 있는 마크다운 파일을 씁니다.

from openai import OpenAI

client = OpenAI()
MODEL = "your-model-id"  # e.g. from your provider's model list

# each prompt file contains {input} where the test diff goes
PROMPTS = {
    "v2": open("prompts/commit_v2.txt").read(),
    "v3": open("prompts/commit_v3.txt").read(),
}
TESTS = [open(f"tests/diff_{i}.txt").read() for i in range(1, 6)]

with open("results.md", "w") as out:
    for i, test in enumerate(TESTS, 1):
        out.write(f"## Test {i}\n\n")
        for name, template in PROMPTS.items():
            for run in (1, 2):
                response = client.chat.completions.create(
                    model=MODEL,
                    messages=[{"role": "user", "content": template.replace("{input}", test)}],
                )
                out.write(f"### {name}, run {run}\n\n{response.choices[0].message.content}\n\n")

언제 멈출까

모든 테스트 입력에서 몇 번 실행해도 모든 기준을 통과하면 멈추세요. 그 뒤에 더하는 것은 대부분 길이만 늘리고, 지시가 하나 늘 때마다 다른 지시와 부딪칠 수 있는 것도 하나 늘어납니다.

변경이 실패를 맞바꾸기 시작할 때도 멈추세요. 한 수정이 테스트 2를 고치고 테스트 4를 망가뜨리고, 다음 수정이 그것을 뒤집는 식입니다. 이 패턴은 지시 하나로는 못 박을 수 없는 일을 프롬프트에 요구하고 있다는 뜻입니다. 흔한 해결책은 예시 몇 개로 형식을 보여 주거나(few-shot 프롬프팅), 프롬프트 체이닝으로 작업을 단계로 나누거나, 글자 수 세기나 형식 확인처럼 결정적인 부분을 출력을 검사하는 코드로 옮기는 것입니다. 아이디어가 막혔다면 메타 프롬프팅이 도움이 됩니다. 모델에게 프롬프트, 입력, 나쁜 출력을 주고, 프롬프트의 어느 부분이 원인일 가능성이 가장 높은지 물어보세요.

자주 묻는 질문

나쁜 답을 내는 프롬프트는 어떻게 개선하나요?

나쁜 답을 보고 무엇이 잘못됐는지 이름을 붙이세요. 틀린 형식, 빠진 사실, 잘못된 독자, 너무 긴 길이 같은 것입니다. 그다음 프롬프트가 무엇을 말하지 않아서 그렇게 됐는지 찾아 그 한 가지를 더하고, 같은 입력으로 새 버전을 실행하세요. 나쁜 답은 표현보다 빠진 맥락이나 빠진 형식 지시에서 나오는 경우가 더 많습니다.

프롬프트를 테스트하려면 입력이 몇 개 필요한가요?

재사용할 프롬프트라면 보통 3~10개면 충분합니다. 전형적인 경우 몇 개, 경계 사례 한두 개(아주 짧거나, 아주 길거나, 특이한 것), 그리고 이전에 틀렸던 입력 하나입니다. 개선하는 동안에는 입력을 고정해서, 출력의 변화가 다른 입력이 아니라 프롬프트에서 오게 하세요.

같은 프롬프트를 다시 실행하면 왜 다른 답이 나오나요?

채팅 모델은 각 단어를 확률 분포에서 샘플링하므로 실행할 때마다 출력이 달라집니다. 두 프롬프트 버전을 비교할 때는 같은 입력으로 각각 여러 번 실행하세요. 모든 실행에서 나타나는 차이는 아마 진짜이고, 한 번만 나타난 차이는 우연일 수 있습니다. API에서는 temperature를 낮춰 변동을 줄일 수도 있습니다.

AI로 프롬프트 출력을 채점할 수 있나요?

네, "본문이 변경이 필요했던 이유를 말한다"나 "이슈 번호를 언급한다"처럼 정확하게 말할 수 있는 기준이라면 됩니다. 채점하는 모델에게 정확한 기준을 주고, 기준마다 통과나 실패를 증거가 되는 인용과 함께 요청하세요. 모델 채점자에게는 긴 답을 선호하거나 특정 위치의 답을 선호하는 등 알려진 편향이 있으므로, 출력 일부는 직접 읽고, 둘을 비교할 때는 순서를 바꿔 보세요.

프롬프트 개선은 언제 멈춰야 하나요?

모든 테스트 입력에서 몇 번 실행해도 모든 기준을 통과하면 멈추세요. 또는 변경할 때마다 한 경우를 고치고 다른 경우를 망가뜨린다면 멈추세요. 그 시점에서는 보통 프롬프트가 문제가 아닙니다. 작업에 예시가 필요하거나, 단계로 나눠야 하거나, 코드로 확인해야 할 수 있습니다.

Coddy programming languages illustration

Coddy로 코딩 배우기

시작하기