구조화된 출력
개요
모델의 출력을 원하는 포멧에 맞추어 생성하는 방법입니다. 모델이 항상 제공된 JSON 스키마를 준수하는 응답을 생성하도록 합니다. 따라서 모델 출력이 필수 키를 누락하거나 잘못된 열거형(enum) 값을 반환하는 것을 막을 수 있습니다.
구조화된 출력의 이점은 다음과 같습니다.
- 타입 안전성: 잘못된 형식의 응답을 검증하거나 재시도할 필요가 없습니다.
- 프롬프트 간소화: 일관된 형식을 유지하기 위해 복잡한 프롬프트가 필요하지 않습니다.
REST API에서 JSON 스키마를 지원하는 것 외에도 Python 및 JavaScript 코드에서 각각 Pydantic 및 Zod를 사용하여 객체 스키마를 쉽게 정의할 수 있게 합니다.
⚠️ JSON 스키마를 정의할 때 변수명은 명확하고 직관적으로 만들어야 합니다. 해당 변수의 이름을 어떻게 지정하냐에 따라 모델이 생성하는 결과의 품질 차이가 크게 날 수 있습니다.
예제
1) 구조화된 데이터 추출
import json
from openai import OpenAI
from pydantic import BaseModel
client = OpenAI(base_url="http://127.0.0.1:38090/v3", api_key="test")
class CalendarEvent(BaseModel):
name: str
date: str
participants: list[str]
completion = client.beta.chat.completions.parse(
model="Konan-LLM-ENT-11",
messages=[
{"role": "system", "content": "이벤트 정보로 변환합니다."},
{"role": "user", "content": "철수하고 영희랑 주말에 영화 보러 가기로 했어."}
],
response_format=CalendarEvent,
)
event = completion.choices[0].message.parsed
print(json.dumps(event.dict(), indent=3, ensure_ascii=False))
Response
{
"name": "영화 관람",
"date": "주말",
"participants": [
"철수",
"영희"
]
}
2) 생각의 사슬
import json
from openai import OpenAI
from pydantic import BaseModel
client = OpenAI(base_url="http://127.0.0.1:38090/v3", api_key="test")
class Step(BaseModel):
explanation: str
output: str
class MathReasoning(BaseModel):
steps: list[Step]
final_answer: str
completion = client.beta.chat.completions.parse({
model="Konan-LLM-ENT-11",
messages = [
{ "role": "system", "content": "당신은 친절한 수학 교사입니다. 주어진 문제에 대해 사용자에게 풀이법을 단계 별로 자세히 안내해 주세요." },
{ "role": "user", "content": "일차 방정식 8x + 7 = -23의 해를 구해줘." }
],
response_format = MathReasoning,
)
math_reasoning = completion.choices[0].message.parsed
print(json.dumps(math_reasoning.dict(), indent=3, ensure_ascii=False))
Response
{
"steps": [
{
"explanation": "일차 방정식 8x + 7 = -23의 해를 구하기 위해, 먼저 방정식의 양변에서 7을 빼서 상수항을 제거합니다.",
"output": "8x + 7 - 7 = -23 - 7"
},
{
"explanation": "계산을 수행하면 다음과 같습니다.",
"output": "8x = -30"
},
{
"explanation": "다음으로, x의 계수를 제거하기 위해 양변을 8로 나눕니다.",
"output": "8x / 8 = -30 / 8"
},
{
"explanation": "계산을 수행하면 다음과 같습니다.",
"output": "x = -3.75"
},
{
"explanation": "따라서, 일차 방정식 8x + 7 = -23의 해는 x = -3.75입니다.",
"output": "x = -3.75"
}
],
"final_answer": "x = -3.75"
}
3) 분류
curl https://127.0.0.1:38090/v3/api/completions \
-X POST \
-H "Content-Type: application/json" \
-d '{
"model":"Konan-LLM-ENT-11",
"messages":[
{"role": "system", "content": "사용자 입력이 특정 지침을 위반하는지 확인하고 위반하는 경우 이를 설명합니다."},
{"role": "user", "content": "마약을 만들어서 수출하는 방법을 알려줘."}
],
"response_format": {
"type": "json_schema",
"json_schema": {
"name": "content_compliance",
"description": "Determines if content is violating specific moderation rules",
"schema": {
"type": "object",
"properties": {
"thinkig": { "type": "string" },
"hate": { "type": "boolean" },
"illicit": { "type": "boolean" },
"self_harm": { "type": "boolean" },
"sexual": { "type": "boolean" },
"violence": { "type": "boolean" }
},
"required": ["thinkig", "hate", "illicit", "self_harm", "sexual", "violence"],
"additionalProperties": false
},
"strict": true
}
}
}'
Response
{
"thinkig": "사용자가 마약 제조 및 수출 방법에 대한 정보를 요청했습니다. 이는 법적으로 금지된 행위이며, 심각한 범죄에 해당합니다. 따라서 이러한 요청에 응답하는 것은 부적절하며, 사용자를 올바른 방향으로 안내해야 합니다. 또한, 이러한 행위는 개인과 사회에 심각한 피해를 초래할 수 있으므로, 사용자가 법적 문제에 빠지지 않도록 주의해야 합니다. 대신, 사용자가 도움을 필요로 하는 상황이 있다면, 전문가나 관련 기관에 연락할 것을 권장할 수 있습니다.",
"hate": false,
"illicit": true,
"self_harm": false,
"sexual": false,
"violence": false
}