프롬프트 엔지니어링
프롬프트 엔지니어링 (Prompt engineering)
OpenAI API로 대규모 언어 모델을 사용해 프롬프트에서 텍스트를 생성할 수 있어요. 모델은 코드, 수학식, 구조화된 JSON 데이터, 사람처럼 자연스러운 산문에 이르기까지 거의 모든 종류의 텍스트 응답을 만들어내죠. 그런데 여기에는 기술이 필요해요. 어떻게 프롬프트를 짜느냐에 따라 결과의 품질이 크게 달라지거든요. 이 문서에서는 모델을 고르는 기준부터 메시지 역할, 퓨샷 학습, 컨텍스트 주입까지, 좋은 결과를 일관되게 얻는 기법들을 살펴볼게요.
가장 간단한 예시부터 시작할게요. Responses API를 사용해요.
간단한 프롬프트로 텍스트 생성하기
import OpenAI from "openai";
const client = new OpenAI();
const response = await client.responses.create({
model: "gpt-6-astra",
input: "Write a one-sentence bedtime story about a unicorn.",
});
console.log(response.output_text);
from openai import OpenAI
client = OpenAI()
response = client.responses.create(
model="gpt-6-astra",
input="Write a one-sentence bedtime story about a unicorn.",
)
print(response.output_text)
package main
import (
"context"
"fmt"
"github.com/openai/openai-go/v3"
"github.com/openai/openai-go/v3/responses"
)
func main() {
client := openai.NewClient()
resp, err := client.Responses.New(context.TODO(), responses.ResponseNewParams{
Model: "gpt-6-astra",
Input: responses.ResponseNewParamsInputUnion{OfString: openai.String("Say this is a test")},
})
if err != nil {
panic(err.Error())
}
fmt.Println(resp.OutputText())
}
import com.openai.client.OpenAIClient;
import com.openai.client.okhttp.OpenAIOkHttpClient;
import com.openai.models.responses.Response;
import com.openai.models.responses.ResponseCreateParams;
public class Main {
public static void main(String[] args) {
OpenAIClient client = OpenAIOkHttpClient.fromEnv();
ResponseCreateParams params =
ResponseCreateParams.builder().input("Say this is a test").model("gpt-6-astra").build();
Response response = client.responses().create(params);
response.output().stream()
.flatMap(item -> item.message().stream())
.flatMap(message -> message.content().stream())
.flatMap(content -> content.outputText().stream())
.forEach(outputText -> System.out.println(outputText.text()));
}
}
using OpenAI.Responses;
#pragma warning disable OPENAI001
string key = Environment.GetEnvironmentVariable("OPENAI_API_KEY")!;
ResponsesClient client = new(key);
ResponseResult response = await client.CreateResponseAsync(
"gpt-6-astra",
"Say 'this is a test.'"
);
Console.WriteLine($"[ASSISTANT]: {response.GetOutputText()}");
require "openai"
openai = OpenAI::Client.new
response = openai.responses.create(
model: "gpt-6-astra",
input: "Write a one-sentence bedtime story about a unicorn."
)
puts(response.output_text)
openai responses create \
--model "gpt-6-astra" \
--input "Write a one-sentence bedtime story about a unicorn." \
--raw-output \
--transform 'output.#(type=="message").content.0.text'
curl "https://api.openai.com/v1/responses" \
-H "Content-Type: application/json" \
-H "Authorization: Bearer ***" \
-d '{
"model": "gpt-6-astra",
"input": "Write a one-sentence bedtime story about a unicorn."
}'
모델이 생성한 콘텐츠 배열은 응답의 output 속성에 들어 있어요. 이 단순한 예시에서는 출력이 하나뿐이고, 아래와 같은 모양이에요.
[
{
"id": "msg_67b73f697ba4819183a15cc17d011509",
"type": "message",
"role": "assistant",
"content": [
{
"type": "output_text",
"text": "Under the soft glow of the moon, Luna the unicorn danced through fields of twinkling stardust, leaving trails of dreams for every child asleep.",
"annotations": []
}
]
}
]
output 배열에는 항목이 하나 이상 들어 있는 경우가 많아요! 도구 호출, 추론 모델이 생성한 reasoning 토큰 데이터, 그 외 다른 항목들이 포함될 수 있어요. 그러니 모델 텍스트 출력이 항상 output[0].content[0].text에 있다고 단정하면 안 됩니다. 여러 공식 SDK에는 편의를 위해 모든 텍스트 출력을 하나의 문자열로 합쳐주는 output_text 속성이 있으니 빠르게 접근할 때 유용해요.
일반 텍스트 말고도 모델이 JSON 형식의 구조화된 데이터를 반환하게 할 수 있는데, 이 기능이 바로 Structured Outputs예요.
출처: 공식문서
모델 고르기 (Choosing a model)
API로 콘텐츠를 생성할 때 가장 핵심적인 선택은 어떤 모델을 쓸지예요. 바로 위 코드 샘플들의 model 파라미터죠. 사용 가능한 전체 모델 목록은 여기서 확인할 수 있어요. 텍스트 생성용 모델을 고를 때 고려할 몇 가지 요소가 있어요.
- 추론 모델 은 입력 프롬프트를 분석하기 위한 내부 사고 사슬(chain of thought)을 생성하고, 복잡한 작업 이해와 다단계 계획에 뛰어나요. 다만 일반적으로 GPT 모델보다 느리고 비싸요.
- GPT 모델 은 빠르고 비용 효율적이며 지능도 높아요. 다만 작업 수행 방법에 대해 더 명시적인 지시를 받을수록 좋아요.
- 크고 작은(미니 또는 나노) 모델 은 속도, 비용, 지능 사이에서 트레이드오프를 제공해요. 큰 모델은 도메인을 넘나들며 프롬프트를 이해하고 문제를 푸는 데 더 효과적이고, 작은 모델은 일반적으로 더 빠르고 싸요.
확실하지 않을 때는 gpt-6-astra가 범용 텍스트 생성과 프롬프트 반복에 강력한 기본값이 돼요.
프롬프트 엔지니어링 (Prompt engineering)
프롬프트 엔지니어링은 모델이 요구사항에 맞는 콘텐츠를 꾸준히 생성하도록 효과적인 지시를 작성하는 과정이에요.
모델이 만드는 콘텐츠는 비결정적이라서, 원하는 출력을 얻는 프롬프트 작성은 예술이자 과학이에요. 그래도 기법과 모범 사례를 적용하면 좋은 결과를 일관되게 얻을 수 있습니다.
메시지 역할처럼 모든 모델에서 통하는 기법도 있지만, 모델 유형(추론 모델 vs GPT 모델)에 따라 최상의 결과를 내는 프롬프트 방식이 달라질 수 있어요. 같은 계열 안에서도 모델 스냅샷이 다르면 결과가 달라질 수 있고요. 애플리케이션이 점점 복잡해질수록 다음 두 가지를 강력히 권장해요.
- 프로덕션 애플리케이션을 특정 모델 스냅샷(예:
gpt-4.1-2025-04-14)에 고정해 일관된 동작을 보장 - 프롬프트 동작을 측정하는 테스트와 평가 스위트를 만들어, 반복 중이거나 모델 버전을 바꾸거나 업그레이드할 때 성능을 모니터링
이제 프롬프트를 구성할 때 쓸 수 있는 도구와 기법을 하나씩 살펴볼게요.
메시지 역할과 지시 따르기 (Message roles)
instructions API 파라미터나 메시지 역할을 사용해 서로 다른 권한 수준으로 모델에 지시를 줄 수 있어요.
instructions 파라미터는 응답 생성 중 모델이 어떻게 행동해야 하는지 높은 수준의 지시를 내려요. 어조, 목표, 올바른 응답 예시까지 포함할 수 있어서, input 파라미터의 프롬프트보다 우선해요.
지시와 함께 텍스트 생성하기
import OpenAI from "openai";
const client = new OpenAI();
const response = await client.responses.create({
model: "gpt-6-astra",
reasoning: { effort: "low" },
instructions: "Talk like a pirate.",
input: "Are semicolons optional in JavaScript?",
});
console.log(response.output_text);
from openai import OpenAI
client = OpenAI()
response = client.responses.create(
model="gpt-6-astra",
reasoning={"effort": "low"},
instructions="Talk like a pirate.",
input="Are semicolons optional in JavaScript?",
)
print(response.output_text)
package main
import (
"context"
"fmt"
"github.com/openai/openai-go/v3"
"github.com/openai/openai-go/v3/responses"
)
func main() {
client := openai.NewClient()
response, err := client.Responses.New(context.Background(), responses.ResponseNewParams{
Model: "gpt-6-astra",
Instructions: openai.String("Talk like a pirate."),
Reasoning: responses.ReasoningParam{
Effort: responses.ReasoningEffortLow,
},
Input: responses.ResponseNewParamsInputUnion{
OfString: openai.String("Are semicolons optional in JavaScript?"),
},
})
if err != nil {
panic(err)
}
fmt.Println(response.OutputText())
}
import com.openai.client.OpenAIClient;
import com.openai.client.okhttp.OpenAIOkHttpClient;
import com.openai.models.Reasoning;
import com.openai.models.ReasoningEffort;
import com.openai.models.responses.ResponseCreateParams;
String semicolonsDevMsg = "Talk like a pirate.";
String semicolonsPrompt = "Are semicolons optional in JavaScript?";
ResponseCreateParams params =
ResponseCreateParams.builder()
.model("gpt-6-astra")
.input(semicolonsPrompt)
.instructions(semicolonsDevMsg)
.reasoning(Reasoning.builder().effort(ReasoningEffort.LOW).build())
.build();
client.responses().create(params).output().stream()
.flatMap(item -> item.message().stream())
.flatMap(message -> message.content().stream())
.flatMap(content -> content.outputText().stream())
.forEach(text -> System.out.println(text.text()));
using OpenAI.Responses;
#pragma warning disable OPENAI001
string key = Environment.GetEnvironmentVariable("OPENAI_API_KEY")!;
ResponsesClient client = new(key);
CreateResponseOptions options = new()
{
Model = "gpt-6-astra",
Instructions = "Talk like a pirate.",
ReasoningOptions = new ResponseReasoningOptions
{
ReasoningEffortLevel = ResponseReasoningEffortLevel.Low,
},
};
options.InputItems.Add(
ResponseItem.CreateUserMessageItem("Are semicolons optional in JavaScript?")
);
ResponseResult response = await client.CreateResponseAsync(options);
Console.WriteLine(response.GetOutputText());
require "openai"
client = OpenAI::Client.new
response = client.responses.create(
model: "gpt-6-astra",
instructions: "Talk like a pirate.",
reasoning: { effort: :low },
input: "Are semicolons optional in JavaScript?"
)
puts(response.output_text)
curl "https://api.openai.com/v1/responses" \
-H "Content-Type: application/json" \
-H "Authorization: Bearer ***" \
-d '{
"model": "gpt-6-astra",
"reasoning": {"effort": "low"},
"instructions": "Talk like a pirate.",
"input": "Are semicolons optional in JavaScript?"
}'
위 예시는 실질적으로 input 배열 안에 다음 메시지들을 넣은 것과 거의 같아요.
서로 다른 역할의 메시지로 텍스트 생성하기
import OpenAI from "openai";
const client = new OpenAI();
const response = await client.responses.create({
model: "gpt-6-astra",
reasoning: { effort: "low" },
input: [
{
role: "developer",
content: "Talk like a pirate.",
},
{
role: "user",
content: "Are semicolons optional in JavaScript?",
},
],
});
console.log(response.output_text);
from openai import OpenAI
client = OpenAI()
response = client.responses.create(
model="gpt-6-astra",
reasoning={"effort": "low"},
input=[
{"role": "developer", "content": "Talk like a pirate."},
{"role": "user", "content": "Are semicolons optional in JavaScript?"},
],
)
print(response.output_text)
package main
import (
"context"
"fmt"
"github.com/openai/openai-go/v3"
"github.com/openai/openai-go/v3/responses"
)
func main() {
client := openai.NewClient()
response, err := client.Responses.New(context.Background(), responses.ResponseNewParams{
Model: "gpt-6-astra",
Reasoning: responses.ReasoningParam{
Effort: responses.ReasoningEffortLow,
},
Input: responses.ResponseNewParamsInputUnion{
OfInputItemList: responses.ResponseInputParam{
responses.ResponseInputItemParamOfMessage(
"Talk like a pirate.",
responses.EasyInputMessageRoleDeveloper,
),
responses.ResponseInputItemParamOfMessage(
"Are semicolons optional in JavaScript?",
responses.EasyInputMessageRoleUser,
),
},
},
})
if err != nil {
panic(err)
}
fmt.Println(response.OutputText())
}
import com.openai.client.OpenAIClient;
import com.openai.client.okhttp.OpenAIOkHttpClient;
import com.openai.models.Reasoning;
import com.openai.models.ReasoningEffort;
import com.openai.models.responses.EasyInputMessage;
import com.openai.models.responses.ResponseCreateParams;
import com.openai.models.responses.ResponseInputItem;
import java.util.List;
String semicolonsDevMsg = "Talk like a pirate.";
String semicolonsPrompt = "Are semicolons optional in JavaScript?";
ResponseCreateParams params =
ResponseCreateParams.builder()
.model("gpt-6-astra")
.input(
ResponseCreateParams.Input.ofResponse(
List.of(
ResponseInputItem.ofEasyInputMessage(
EasyInputMessage.builder()
.role(EasyInputMessage.Role.DEVELOPER)
.content(semicolonsDevMsg)
.build()),
ResponseInputItem.ofEasyInputMessage(
EasyInputMessage.builder()
.role(EasyInputMessage.Role.USER)
.content(semicolonsPrompt)
.build()))))
.reasoning(Reasoning.builder().effort(ReasoningEffort.LOW).build())
.build();
client.responses().create(params).output().stream()
.flatMap(item -> item.message().stream())
.flatMap(message -> message.content().stream())
.flatMap(content -> content.outputText().stream())
.forEach(text -> System.out.println(text.text()));
using OpenAI.Responses;
#pragma warning disable OPENAI001
string key = Environment.GetEnvironmentVariable("OPENAI_API_KEY")!;
ResponsesClient client = new(key);
CreateResponseOptions options = new()
{
Model = "gpt-6-astra",
ReasoningOptions = new ResponseReasoningOptions
{
ReasoningEffortLevel = ResponseReasoningEffortLevel.Low,
},
};
options.InputItems.Add(
ResponseItem.CreateDeveloperMessageItem("Talk like a pirate.")
);
options.InputItems.Add(
ResponseItem.CreateUserMessageItem("Are semicolons optional in JavaScript?")
);
ResponseResult response = await client.CreateResponseAsync(options);
Console.WriteLine(response.GetOutputText());
require "openai"
client = OpenAI::Client.new
response = client.responses.create(
model: "gpt-6-astra",
reasoning: { effort: :low },
input: [
{
role: :developer,
content: "Talk like a pirate."
},
{
role: :user,
content: "Are semicolons optional in JavaScript?"
}
]
)
puts(response.output_text)
curl "https://api.openai.com/v1/responses" \
-H "Content-Type: application/json" \
-H "Authorization: Bearer ***" \
-d '{
"model": "gpt-6-astra",
"reasoning": {"effort": "low"},
"input": [
{
"role": "developer",
"content": "Talk like a pirate."
},
{
"role": "user",
"content": "Are semicolons optional in JavaScript?"
}
]
}'
instructions 파라미터는 현재 응답 생성 요청에만 적용된다는 것을 기억하세요. previous_response_id 파라미터로 대화 상태를 관리한다면, 이전 턴에서 쓴 instructions는 이후 컨텍스트에 남아 있지 않아요.
OpenAI 모델 스펙은 모델이 서로 다른 역할의 메시지에 얼마나 다른 우선순위를 두는지 설명해요.
developer |
user |
assistant |
|---|---|---|
developer 메시지는 애플리케이션 개발자가 제공한 지시로, user 메시지보다 높은 우선순위를 받아요. |
user 메시지는 최종 사용자가 제공한 지시로, developer 메시지보다 뒤에 우선해요. |
모델이 생성한 메시지는 assistant 역할을 가져요. |
여러 턴에 걸친 대화는 이런 유형의 메시지 여러 개와, 사용자와 모델이 제공하는 다른 콘텐츠 유형들로 이루어질 수 있어요. 대화 상태 관리에 대한 자세한 내용은 별도 문서에서 다룹니다.
developer 메시지와 user 메시지를 프로그래밍 언어의 함수와 그 인자처럼 생각해 볼 수도 있어요.
developer메시지는 시스템의 규칙과 비즈니스 로직을 제공해요. 마치 함수 정의와 같죠.user메시지는developer메시지 지시가 적용될 입력과 설정을 제공해요. 마치 함수에 넘기는 인자와 같아요.
코드에서 프롬프트 버전 관리
프로덕션 프롬프트는 재사용 가능한 프롬프트 객체를 만들기보다 애플리케이션 코드에 저장하는 게 좋아요. 코드로 관리하는 프롬프트는 타입 있는 입력, 코드 리뷰, 테스트, 평소의 배포 프로세스까지 그대로 활용해 모델 동작을 바꿀 수 있어요.
OpenAI는 API에서 재사용 가능한 프롬프트 객체를 폐기하고 있어요. 2026년 6월 3일부터 프롬프트 생성을 축소하고, v1/prompts는 2026년 11월 30일에 종료될 예정이에요. 현재 일정은 deprecations 페이지에서 찾을 수 있어요.
새 프롬프트 엔지니어링 작업을 시작한다면:
- 프롬프트 빌더를 그 기능을 지원하는 작은 모듈에 가까이 두기
- 고객 데이터, 파일, 작업 옵션 같은 동적 값에는 타입 있는 함수 인자나 스키마를 사용하기
- 생성된
instructions와input을 Responses API에 직접 전달하기 - 프로덕션 프롬프트를 바꾸기 전에 대표적인 픽스처, 테스트, 평가 체크를 추가하기
- 프롬프트 변경은 배포 시스템으로 롤아웃하고, 단계적 배포가 필요하면 기능 플래그나 설정을 사용하기
이미 저장된 프롬프트를 프롬프트 ID나 버전으로 호출하는 통합이라면, 프롬프트 객체 마이그레이션 가이드를 따라 그 프롬프트를 코드로 옮길 수 있어요.
Markdown과 XML로 메시지 형식 지정하기
developer·user 메시지를 작성할 때 Markdown 서식과 XML 태그를 조합하면 모델이 프롬프트와 컨텍스트 데이터의 논리적 경계를 이해하는 데 도움이 돼요.
Markdown 헤더와 목록은 프롬프트의 구분된 섹션을 표시하고 모델에 계층을 전달하는 데 유용해요. 개발 중에 프롬프트를 더 읽기 좋게 만들 수도 있고요. XML 태그는 참조용 문서 같은 한 콘텐츠 조각이 시작되고 끝나는 위치를 구분하는 데 도움이 돼요. XML 속성은 지시에서 참조할 수 있는 프롬프트 콘텐츠에 대한 메타데이터를 정의하는 데도 쓸 수 있어요.
일반적으로 developer 메시지는 보통 다음 순서로 섹션을 포함해요. 다만 최적의 정확한 내용과 순서는 어떤 모델을 쓰느냐에 따라 달라질 수 있어요.
- 정체성(Identity): 어시스턴트의 목적, 커뮤니케이션 스타일, 높은 수준의 목표를 설명해요.
- 지시(Instructions): 원하는 응답을 생성하도록 모델에 지침을 줘요. 어떤 규칙을 따라야 할까? 모델이 무엇을 해야 하고, 무엇을 절대 하면 안 될까? 사용 사례에 따라 이 섹션에 여러 하위 섹션이 들어갈 수 있어요. 예를 들어 모델이 커스텀 함수를 호출하는 방법 같은 것들이요.
- 예시(Examples): 가능한 입력과 그에 기대되는 모델 출력을 제공해요.
- 컨텍스트(Context): 응답 생성에 필요할 추가 정보를 줘요. 훈련 데이터 밖의 사유/독점 데이터나, 특히 관련성이 높다고 아는 다른 데이터가 여기에 속해요. 생성 요청마다 컨텍스트가 다를 수 있으니 보통 프롬프트 끝부분에 배치하는 게 좋아요.
아래는 Markdown과 XML 태그로 구분된 섹션과 지원 예시를 가진 developer 메시지를 구성한 예시예요.
예시 프롬프트 — 코드 생성을 위한 developer 메시지
# Identity
You are coding assistant that helps enforce the use of snake case
variables in JavaScript code, and writing code that will run in
Internet Explorer version 6.
# Instructions
* When defining variables, use snake case names (e.g. my_variable)
instead of camel case names (e.g. myVariable).
* To support old browsers, declare variables using the older
"var" keyword.
* Do not give responses with Markdown formatting, just return
the code as requested.
# Examples
<user_query>
How do I declare a string variable for a first name?
</user_query>
<assistant_response>
var first_name = "Anna";
</assistant_response>
API 요청 — API를 통해 코드 생성 프롬프트 보내기
import fs from "fs/promises";
import OpenAI from "openai";
const client = new OpenAI();
const instructions = await fs.readFile("fixtures/prompt.txt", "utf-8");
const response = await client.responses.create({
model: "gpt-6-astra",
instructions,
input: "How would I declare a variable for a last name?",
});
console.log(response.output_text);
from openai import OpenAI
client = OpenAI()
with open("prompt.txt", "r", encoding="utf-8") as f:
instructions = f.read()
response = client.responses.create(
model="gpt-6-astra",
instructions=instructions,
input="How would I declare a variable for a last name?",
)
print(response.output_text)
package main
import (
"context"
"fmt"
"os"
"github.com/openai/openai-go/v3"
"github.com/openai/openai-go/v3/responses"
)
func main() {
client := openai.NewClient()
instructions, err := os.ReadFile("prompt.txt")
if err != nil {
panic(err)
}
response, err := client.Responses.New(context.Background(), responses.ResponseNewParams{
Model: "gpt-6-astra",
Instructions: openai.String(string(instructions)),
Input: responses.ResponseNewParamsInputUnion{
OfString: openai.String("How would I declare a variable for a last name?"),
},
})
if err != nil {
panic(err)
}
fmt.Println(response.OutputText())
}
import com.openai.client.OpenAIClient;
import com.openai.client.okhttp.OpenAIOkHttpClient;
import com.openai.models.responses.ResponseCreateParams;
ResponseCreateParams params =
ResponseCreateParams.builder()
.model("gpt-6-astra")
.instructions(
"You are a coding assistant. Answer with concise JavaScript examples and use semicolons.")
.input("How would I declare a variable for a last name?")
.build();
client.responses().create(params).output().stream()
.flatMap(item -> item.message().stream())
.flatMap(message -> message.content().stream())
.flatMap(content -> content.outputText().stream())
.forEach(text -> System.out.println(text.text()));
using OpenAI.Responses;
#pragma warning disable OPENAI001
string key = Environment.GetEnvironmentVariable("OPENAI_API_KEY")!;
ResponsesClient client = new(key);
string instructions = await File.ReadAllTextAsync("prompt.txt");
CreateResponseOptions options = new()
{
Model = "gpt-6-astra",
Instructions = instructions,
};
options.InputItems.Add(
ResponseItem.CreateUserMessageItem("How would I declare a variable for a last name?")
);
ResponseResult response = await client.CreateResponseAsync(options);
Console.WriteLine(response.GetOutputText());
require "openai"
client = OpenAI::Client.new
instructions = File.read(File.join(__dir__, "prompt.txt"))
response = client.responses.create(
model: "gpt-6-astra",
instructions: instructions,
input: "How would I declare a variable for a last name?"
)
puts(response.output_text)
curl https://api.openai.com/v1/responses \
-H "Authorization: Bearer ***" \
-H "Content-Type: application/json" \
-d '{
"model": "gpt-6-astra",
"instructions": "'"$(< prompt.txt)"'",
"input": "How would I declare a variable for a last name?"
}'
프롬프트 캐싱으로 비용·지연 시간 절약
메시지를 구성할 때는 API 요청에서 반복해서 쓸 것으로 예상하는 콘텐츠를 프롬프트 시작 부분에, 그리고 Chat Completions 또는 Responses에 넘기는 JSON 요청 본문의 앞쪽 API 파라미터에도 두는 게 좋아요. 이렇게 하면 프롬프트 캐싱으로 비용과 지연 시간 절약을 최대화할 수 있어요.
퓨샷 학습 (Few-shot learning)
퓨샷 학습은 모델을 파인튜닝하는 대신, 프롬프트에 입력/출력 예시 몇 개를 넣어 대규모 언어 모델을 새 작업 쪽으로 이끄는 기법이에요. 모델은 그 예시들에서 패턴을 암묵적으로 "집어내서" 프롬프트에 적용해요. 예시를 제공할 때는 원하는 출력과 함께 가능한 입력의 다양한 범위를 보여주는 게 좋아요.
보통은 API 요청의 developer 메시지 일부로 예시를 넣어요. 아래는 고객 서비스 리뷰를 긍정/부정으로 분류하는 방법을 모델에 보여주는 예시가 담긴 developer 메시지예요.
# Identity
You are a helpful assistant that labels short product reviews as
Positive, Negative, or Neutral.
# Instructions
* Only output a single word in your response with no additional formatting
or commentary.
* Your response should only be one of the words "Positive", "Negative", or
"Neutral" depending on the sentiment of the product review you are given.
# Examples
<product_review id="example-1">
I absolutely love this headphones — sound quality is amazing!
</product_review>
<assistant_response id="example-1">
Positive
</assistant_response>
<product_review id="example-2">
Battery life is okay, but the ear pads feel cheap.
</product_review>
<assistant_response id="example-2">
Neutral
</assistant_response>
<product_review id="example-3">
Terrible customer service, I'll never buy from them again.
</product_review>
<assistant_response id="example-3">
Negative
</assistant_response>
관련 컨텍스트 정보 포함하기
모델이 응답을 생성할 때 쓸 수 있는 추가 컨텍스트 정보를 프롬프트 안에 포함하는 것이 유용한 경우가 많아요. 보통 이런 이유가 있어요.
- 모델이 훈련된 데이터셋 밖에 있는 독점 데이터나 다른 데이터에 모델이 접근할 수 있게 하기 위해.
- 모델 응답을 가장 유익하다고 판단한 특정 리소스 집합으로 제한하기 위해.
모델 생성 요청에 추가 관련 컨텍스트를 넣는 기법을 검색 증강 생성(retrieval-augmented generation, RAG) 이라고도 해요. 벡터 데이터베이스를 조회해 돌아온 텍스트를 프롬프트에 넣는 방법부터, OpenAI의 내장 파일 검색 도구로 업로드된 문서를 기반으로 콘텐츠를 생성하는 방법까지 여러 방식으로 추가 컨텍스트를 넣을 수 있어요.
컨텍스트 창 계획하기
모델은 생성 요청 동안 고려하는 컨텍스트 안에서 처리할 수 있는 데이터 양이 한정돼 있어요. 이 메모리 제한을 컨텍스트 창(context window) 이라고 하는데, 토큰(텍스트에서 이미지까지 넣는 데이터 덩어리) 단위로 정의돼요.
모델마다 컨텍스트 창 크기가 달라요. 낮은 10만 대 범위부터, 최신 GPT-4.1 모델의 백만 토큰까지 다양해요. 모델별 구체적인 컨텍스트 창 크기는 모델 문서를 참고하세요.
현재 모델 프롬프팅
gpt-6-astra 같은 GPT 모델은 작업을 완료하는 데 필요한 로직과 데이터를 프롬프트에 명시적으로 제공하는 정밀한 지시에서 가장 큰 이점을 얻어요. 최신 모델을 최대한 활용하려면 현재 프롬프팅 가이드부터 시작하세요. 최신 모델 프롬프팅 가이드에서 현재 지침, 실용 예시, 마이그레이션 노트를 확인할 수 있어요.
최신 모델 프롬프팅 모범 사례
최신 모델 프롬프팅 모범 사례에 대한 완전한 최신 처리는 최신 모델 프롬프팅 가이드를 참고하세요. 아래 실용적인 요점들은 여전히 적용돼요.
코딩
gpt-6-astra로 코딩 작업을 프롬프팅할 때는 몇 가지 모범 사례가 가장 효과적이에요: 에이전트의 역할을 정의하고, 예시로 구조화된 도구 사용을 강제하며, 정확성을 위해 철저한 테스트를 요구하고, 깔끔한 출력을 위해 Markdown 표준을 설정하세요.
명시적 역할과 작업 흐름 지침 — 모델을 책임이 잘 정의된 소프트웨어 엔지니어링 에이전트로 프레이밍하세요. 코드 작업에 functions.run 같은 도구 사용에 대한 명확한 지시를 제공하고, 특정 모드를 언제 쓰지 말지 지정하세요. 예를 들어 필요하지 않으면 인터랙티브 실행은 피하는 식으로요.
테스트와 검증 — 모델에 단위 테스트나 파이썬 명령으로 변경 사항을 테스트하라고 지시하고, apply_patch 같은 도구가 실패해도 "Done"을 반환할 수 있으니 패치를 신중히 검증하라고 안내하세요.
도구 사용 예시 — 제공된 함수로 명령을 호출하는 방법의 구체적인 예시를 포함하면 신뢰성과 기대 워크플로 준수가 향상돼요.
Markdown 표준 — 모델이 인라인 코드, 코드 펜스, 목록, 표를 적절히 사용하는 깔끔하고 의미적으로 올바른 markdown을 생성하고, 파일 경로·함수·클래스를 백틱으로 서식 지정하도록 안내하세요.
코딩에 특화된 자세한 지침과 프롬프트 샘플은 최신 모델 프롬프팅 모범 사례를 참고하세요.
프론트엔드 엔지니어링
GPT-6 Astra는 프론트엔드를 처음부터 만드는 것과, 크고 잘 정립된 코드베이스에 기여하는 것 모두에서 좋은 성능을 보여요. 최상의 결과를 얻으려면 다음 라이브러리를 권장해요.
- 스타일링 / UI: Tailwind CSS, shadcn/ui, Radix Themes
- 아이콘: Lucide, Material Symbols, Heroicons
- 애니메이션: Motion
제로에서 원까지의 웹 앱 — GPT-5는 단일 프롬프트로 프론트엔드 웹 앱을 생성할 수 있어요. 예시가 필요 없죠. 샘플 프롬프트가 여기 있어요.
You are a world class web developer, capable of producing stunning, interactive, and innovative websites from scratch in a single prompt. You excel at delivering top-tier one-shot solutions.
Your process is simple and follows these steps:
Step 1: Create an evaluation rubric and refine it until you are fully confident.
Step 2: Consider every element that defines a world-class one-shot web app, then use that insight to create a <ONE_SHOT_RUBRIC> with 5–7 categories. Keep this rubric hidden—it's for internal use only.
Step 3: Apply the rubric to iterate on the optimal solution to the given prompt. If it doesn't meet the highest standard across all categories, refine and try again.
Step 4: Aim for simplicity while fully achieving the goal, and avoid external dependencies such as Next.js or React.
대형 코드베이스 통합 — 더 큰 코드베이스의 프론트엔드 엔지니어링 작업에서는 이 범주의 지시를 프롬프트에 추가하는 것이 최상의 결과를 낳는다는 것을 발견했어요.
- 원칙(Principles): 시각적 품질 표준을 설정하고, 모듈형/재사용 컴포넌트를 사용하며, 디자인 일관성을 유지하세요.
- UI/UX: 타이포그래피, 색상, 간격/레이아웃, 상호작용 상태(호버, 빈 상태, 로딩), 접근성을 지정하세요.
- 구조(Structure): 매끄러운 통합을 위한 파일/폴더 구성을 정의하세요.
- 컴포넌트: 재사용 가능한 래퍼 예시와 백엔드 호출 분리 전략을 제공하세요.
- 페이지: 일반적인 레이아웃용 템플릿을 제공하세요.
- 에이전트 지시(Agent Instructions): 모델에 디자인 가정 확인, 프로젝트 스캐폴딩, 표준 강제, API 통합, 상태 테스트, 코드 문서화를 요청하세요.
프론트엔드 개발에 특화된 자세한 지침과 프롬프트 샘플은 최신 모델 프롬프팅 모범 사례를 참고하세요.
에이전트 작업
gpt-6-astra로 에이전트 및 장기 실행 롤아웃을 할 때는 세 가지 핵심 관행에 프롬프트를 집중하세요: 완전한 해결을 보장하도록 작업을 철저히 계획하고, 주요 도구 사용 결정에 명확한 서문을 제공하며, TODO 도구로 작업 흐름과 진행 상황을 조직적으로 추적하세요.
계획과 인내성 — 모델에 통제권을 넘기기 전에 전체 쿼리를 해결하라고 지시하고, 하위 작업으로 분해해 각 도구 호출 후 완전성을 확인하기 위해 반성하라고 안내하세요.
Remember, you are an agent - please keep going until the user's
query is completely resolved, before ending your turn and yielding
back to the user. Decompose the user's query into all required
sub-requests, and confirm that each is completed. Do not stop
after completing only part of the request. Only terminate your
turn when you are sure that the problem is solved. You must be
prepared to answer multiple queries and only finish the call once
the user has confirmed they're done.
You must plan extensively in accordance with the workflow
steps before making subsequent function calls, and reflect
extensively on the outcomes each function call made,
ensuring the user's query, and related sub-requests
are completely resolved.
투명성을 위한 서문 — 모델에 도구를 호출하는 이유를 설명하라고 요청하되, 중요한 단계에서만 하라고 하세요.
Before you call a tool explain why you are calling it
루브릭과 TODO로 진행 추적 — TODO 목록 도구나 루브릭을 사용해 구조화된 계획을 강제하고 단계 누락을 피하세요.
에이전트 구축에 특화된 자세한 지침과 프롬프트 샘플은 최신 모델 프롬프팅 모범 사례를 참고하세요.
추론 모델 프롬프팅
추론 모델을 GPT 모델과 다르게 프롬프팅할 때 고려할 차이점이 있어요. 일반적으로 추론 모델은 높은 수준의 지침만 주는 작업에서 더 나은 결과를 내요. 이는 매우 정밀한 지시에서 이점을 얻는 GPT 모델과 대조적이에요.
추론 모델과 GPT 모델의 차이를 이렇게 생각해 볼 수 있어요.
- 추론 모델은 선배 동료와 같아요. 목표를 주고 디테일을 알아서 해결하도록 신뢰할 수 있어요.
- GPT 모델은 주니어 동료와 같아요. 특정 출력을 만들라는 명시적 지시가 있을 때 가장 잘 수행해요.
추론 모델 사용 시 모범 사례에 대한 자세한 내용은 이 가이드를 참고하세요.
더 알아보기 (Learn more)
이제 텍스트 입력과 출력의 기본을 알게 됐으니, 다음 중 하나를 살펴보는 걸 추천해요.
- Playground에서 프롬프트 만들기 — Playground로 프롬프트를 개발하고 반복해 보세요.
- Structured Outputs로 JSON 데이터 생성하기 — 모델이 내보내는 JSON 데이터가 JSON 스키마를 따르도록 보장해요.
- 전체 API 참조 — API 참조에서 텍스트 생성의 모든 옵션을 확인하세요.
기타 자료 (Other resources)
더 많은 영감이 필요하다면 OpenAI Cookbook을 방문해 보세요. 예시 코드와 함께 서드파티 자료 링크도 들어 있어요.