Structured Outputs는 어떻게 동작하나요?
Structured Outputs는 어떻게 동작하나요?
response_format 같은 파라미터를 사용해 Cohere 모델이 JSON, TOOLS 같은 특정 형식으로 출력을 만들게 하는 방법을 설명하는 문서예요.
출처: 문서
본문
개요(Overview)
Structured Outputs는 LLM 응답이 사용자가 지정한 스키마를 엄격히 따르도록 강제하는 기능이에요. Structured Outputs를 켜면 LLM은 사용자가 제공한 원하는 스키마를 100%의 확률로 따르는 구조화된 데이터를 생성해요. 이는 다운스트림 애플리케이션이 LLM 출력이 올바르게 포맷될 것을 기대하는 엔터프라이즈 애플리케이션에서 LLM의 신뢰성을 높여줍니다. Structured Outputs를 사용하면 구조화된 데이터의 환각(hallucinated) 필드와 항목을 확실히 제거할 수 있어요.
호환 모델(Compatible models):
- Command A+
- Command A
- Command R+ 08 2024
- Command R+
- Command R 08 2024
- Command R
Structured Outputs 사용 방법
Structured Outputs를 사용하는 방법은 두 가지가 있어요:
- Structured Outputs (JSON). 주로 텍스트 생성 사용 사례에서 사용됩니다.
- Structured Outputs (Tools). 주로 도구 사용(tool use, 또는 함수 호출)과 에이전트(agents) 사용 사례에서 사용돼요.
API 호환성(API Compatibility)
Tools와 함께 사용하는 Structured Outputs는
strict_tools파라미터를 통해 Chat API V2에서만 지원됩니다. 이 파라미터는 Chat API V1에서는 지원되지 않아요.
Structured Outputs (JSON)
여기서 Chat API를 호출해 JSON 형식의 Structured Outputs를 생성할 수 있어요. JSON은 사람이 읽고 쓰기 쉽고 기계가 파싱하기도 쉬운 경량 형식입니다.
이는 텍스트 생성 사용 사례에서 특히 유용한데, 예를 들어 응답에서 특정 정보를 추출하거나, 데이터 분석을 수행하거나, 응답을 애플리케이션에 매끄럽게 통합하고 싶을 때 그렇습니다.
JSON 출력을 지정하는 방법은 두 가지가 있어요:
- JSON mode
- JSON Schema mode
JSON mode
JSON mode에서는 API 요청을 할 때 response_format 파라미터를 지정해 응답을 JSON 객체 형식으로 원한다는 것을 나타낼 수 있어요.
PYTHON
import cohere
co = cohere.ClientV2(api_key="YOUR API KEY")
res = co.chat(
model="command-a-plus-05-2026",
messages=[
{
"role": "user",
"content": "Generate a JSON describing a person, with the fields 'name' and 'age'",
}
],
response_format={"type": "json_object"},
)
print(res.message.content[0].text)
cURL
curl --request POST \
--url https://api.cohere.ai/v2/chat \
--header 'accept: application/json' \
--header 'content-type: application/json' \
--header "Authorization: bearer ***" \
--data '{
"model": "command-a-plus-05-2026",
"messages": [
{
"role": "user",
"content": "Generate a JSON describing a person, with the fields '\''name'\'' and '\''age'\''"
}
],
"response_format": {
"type": "json_object"
}
}'
Chat API에서 response_format 유형을 "json_object"로 설정하면, 모델의 출력이 유효한 JSON 객체임이 보장됩니다.
# Example response
{
"name": "Emma Johnson",
"age": 32
}
중요(Important)
{ "type": "json_object" }를 사용할 때는message가 항상 모델에게 JSON을 생성하라고 명시적으로 지시해야 해요 (예: "Generate a JSON ..."). 그렇지 않으면 모델이 무한한 문자 스트림을 생성하다가 결국 컨텍스트 길이를 모두 소진할 수 있습니다.
참고(Note)
이 기능은 현재 RAG 모드에서는 지원되지 않아요.
JSON Schema mode
JSON Schema mode에서는 response_format 파라미터의 일부로 스키마를 선택적으로 정의할 수 있어요. JSON Schema는 LLM이 생성하길 원하는 JSON 객체의 구조를 설명하는 방법입니다.
이렇게 하면 LLM이 이 스키마에 고정되도록 강제해, 출력에 대해 더 큰 통제권을 갖게 해줘요.
예를 들어, LLM이 책에 대해 "title", "author", "publication_year" 같은 특정 키를 가진 JSON 객체를 생성하길 원한다고 가정해 보세요. API 요청은 다음과 같을 수 있습니다:
PYTHON
import cohere
co = cohere.ClientV2(api_key="YOUR API KEY")
res = co.chat(
model="command-a-plus-05-2026",
messages=[
{
"role": "user",
"content": "Generate a JSON describing a book, with the fields 'title' and 'author' and 'publication_year'",
}
],
response_format={
"type": "json_object",
"schema": {
"type": "object",
"properties": {
"title": {"type": "string"},
"author": {"type": "string"},
"publication_year": {"type": "integer"},
},
"required": ["title", "author", "publication_year"],
},
},
)
print(res.message.content[0].text)
cURL
curl --request POST \
--url https://api.cohere.ai/v2/chat \
--header 'accept: application/json' \
--header 'content-type: application/json' \
--header "Authorization: bearer ***" \
--data '{
"model": "command-a-plus-05-2026",
"messages": [
{
"role": "user",
"content": "Generate a JSON describing a book, with the fields '\''title'\'' and '\''author'\'' and '\''publication_year'\''"
}
],
"response_format": {
"type": "json_object",
"schema": {
"type": "object",
"properties": {
"title": {"type": "string"},
"author": {"type": "string"},
"publication_year": {"type": "integer"}
},
"required": ["title", "author", "publication_year"]
}
}
}'
이 스키마에서 우리는 세 개의 키("title", "author", "publication_year")와 예상 데이터 유형("string"과 "integer")을 정의했어요. LLM은 이 구조를 따르는 JSON 객체를 생성합니다.
# Example response
{
"title": "The Great Gatsby",
"author": "F. Scott Fitzgerald",
"publication_year": 1925
}
중첩 배열 스키마 JSON 예제(Nested Array Schema Json Example)
다음은 중첩 배열의 예시예요. 최상위 json 구조는 항상 json 객체여야 한다는 점에 주의하세요.
PYTHON
cohere_api_key = os.getenv("cohere_api_key")
co = cohere.ClientV2(cohere_api_key)
response = co.chat(
response_format={
"type": "json_object",
"schema": {
"type": "object",
"properties": {
"actions": {
"type": "array",
"items": {
"type": "object",
"properties": {
"japanese": {"type": "string"},
"romaji": {"type": "string"},
"english": {"type": "string"},
},
"required": ["japanese", "romaji", "english"],
},
}
},
"required": ["actions"],
},
},
model="command-a-plus-05-2026",
messages=[
{
"role": "user",
"content": "Generate a JSON array of objects with the following fields: japanese, romaji, english. These actions should be japanese verbs provided in the dictionary form.",
},
],
)
return json.loads(response.message.content[0].text)
cURL
curl --request POST \
--url https://api.cohere.ai/v2/chat \
--header 'accept: application/json' \
--header 'content-type: application/json' \
--header "Authorization: bearer ***" \
--data '{
"model": "command-a-plus-05-2026",
"messages": [
{
"role": "user",
"content": "Generate a JSON array of objects with the following fields: japanese, romaji, english. These actions should be japanese verbs provided in the dictionary form."
}
],
"response_format": {
"type": "json_object",
"schema": {
"type": "object",
"properties": {
"actions": {
"type": "array",
"items": {
"type": "object",
"properties": {
"japanese": {"type": "string"},
"romaji": {"type": "string"},
"english": {"type": "string"}
},
"required": ["japanese", "romaji", "english"]
}
}
},
"required": ["actions"]
}
}
}'
이 예시의 출력은 다음과 같아요:
{
"actions": [
{"japanese": "いこう", "romaji": "ikou", "english": "onward"},
{"japanese": "探す", "romaji": "sagasu", "english": "search"},
{"japanese": "話す", "romaji": "hanasu", "english": "talk"}
]
}
중요(Important)
참고: 제공된 각 스키마(JSON 및 Tools 모드 모두)는 스키마를 처리하는 데 필요한 지연 시간 오버헤드가 발생해요. 이는 처음 몇 개의 요청에만 적용됩니다.
Structured Outputs (Tools)
tools와 함께 Chat API를 사용할 때(자세한 내용은 도구 사용(tool use) 및 에이전트(agents) 참조), strict_tools 파라미터를 True로 설정하면 모델이 생성하는 도구 호출이 사용자가 제공한 도구 설명을 엄격히 따르도록 강제해요.
구체적으로 이는 다음을 의미합니다:
- 환각된 도구 이름 없음
- 환각된 도구 파라미터 없음
- 모든
required파라미터가 도구 호출에 포함됨 - 모든 파라미터가 요청된 데이터 유형을 생성함
strict_tools를 활성화하면 API는 도구 정의에 따라 도구 이름과 도구 파라미터가 생성되도록 보장해요. 이는 도구 이름과 파라미터 환각을 없애고, 각 파라미터가 지정된 데이터 유형과 일치하며, 모든 required 파라미터가 모델 응답에 포함되도록 합니다.
또한 이는 더 빠른 개발로 이어져요. 환각을 피하기 위해 모델을 프롬프트 엔지니어링하는 데 많은 시간을 쓸 필요가 없어요.
아래 예시에서는 주어진 위치의 날씨 데이터를 검색할 수 있는 도구를 만듭니다. 이 도구는 location이라는 파라미터를 포함하는 get_weather라고 불러요. 그런 다음 strict_tools를 True로 설정해 Chat API를 호출해 생성된 도구 호출이 항상 올바른 함수와 파라미터 이름을 포함하도록 보장합니다.
strict_tools 파라미터를 True로 설정하면 API 호출로 전달되는 모든 도구에 걸쳐 최대 200개의 필드를 정의할 수 있어요.
PYTHON
tools = [
{
"type": "function",
"function": {
"name": "get_weather",
"description" : "Gets the weather of a given location",
"parameters": {
"type": "object",
"properties": {
"location": {
"type" : "string",
"description": "The location to get weather."
}
},
"required": ["location"]
}
}
},
]
response = co.chat(model="command-r7b-12-2024",
messages=[{"role": "user", "content": "What's the weather in Toronto?"}],
tools=tools,
strict_tools=True)
print(response.message.tool_calls)
cURL
curl --request POST \
--url https://api.cohere.ai/v2/chat \
--header 'accept: application/json' \
--header 'content-type: application/json' \
--header "Authorization: bearer ***" \
--data '{
"model": "command-r7b-12-2024",
"messages": [
{
"role": "user",
"content": "What'\''s the weather in Toronto?"
}
],
"tools": [
{
"type": "function",
"function": {
"name": "get_weather",
"description": "Gets the weather of a given location",
"parameters": {
"type": "object",
"properties": {
"location": {
"type": "string",
"description": "The location to get weather."
}
},
"required": ["location"]
}
}
}
],
"strict_tools": true
}'
strict_tools 사용에 관한 중요 참고 사항
- 이 파라미터는 strict_tools 파라미터를 통해 Chat API V2에서만 지원됩니다 (API V1에서는 지원되지 않아요).
- 최소한 하나의
required파라미터를 지정해야 합니다. 선택 파라미터만 있는 도구는 이 모드에서 지원되지 않아요. - 단일 Chat API 호출에서 모든 도구에 걸쳐 최대 200개의 필드를 정의할 수 있습니다.
실험적(Experimental)
strict_tools는 현재 실험적인 파라미터예요. 이 기능을 계속 개선할 예정이며 피드백을 찾고 있습니다. discord의#api-discussions채널이나 이메일로 경험을 공유해 주세요.
Structured Outputs (JSON) vs Structured Outputs (Tools) 언제 사용할까요?
Structured Outputs (JSON)은 모델의 사용자 응답을 특정한 방식으로 포맷하고 싶은 텍스트 생성 사용 사례에 이상적이에요.
예를 들어 여행 플래너 애플리케이션을 만들 때 LLM이 특정 JSON 형식으로 일정을 생성하길 원할 수 있고, 애플리케이션이 그 출력을 애플리케이션의 다른 부분에서 사용할 수 있게 하는 거죠.
Structured Outputs (Tools)는 모델이 외부 데이터나 서비스와 상호작용해야 하는 도구 사용(tool use, 또는 함수 호출) 및 에이전트(agents) 사용 사례에 이상적이에요. 예를 들어 데이터베이스나 다른 API와 상호작용하는 함수에 모델 접근을 허용할 수 있습니다.
요약하면, 다음과 같이 선택하세요:
- 모델의 응답이 특정 구조를 따라야 할 때는 Structured Outputs (JSON).
- 모델이 외부 데이터나 서비스와 상호작용해야 할 때는 Structured Outputs (Tools).
스키마 지정하기(Specifying a schema)
중첩 객체 생성(Generating nested objects)
JSON Schema mode에서는 중첩 수준에 제한이 없어요. 하지만 JSON mode(스키마 미지정)에서는 중첩이 5 수준으로 제한됩니다.
스키마 제약(Schema constraints)
schema를 구성할 때 다음 제약을 염두에 두세요:
- 최상위 스키마의
type은object여야 합니다 - 스키마의 모든 객체는 최소한 하나의
required필드를 지정해야 해요
파라미터 유형 지원(Parameter types support)
지원되는 스키마 기능(Supported schema features)
Structured Outputs 기능(JSON 및 Tools 모드 모두)은 파라미터 정의를 위해 JSON Schema 표기법에 의존해요. JSON Schema는 개발자가 JSON 객체의 예상 형식을 지정할 수 있게 해, 데이터가 사전 정의된 규칙과 제약을 따르도록 보장합니다.
Structured Outputs는 아래 표에 상세히 설명된 JSON Schema 사양의 하위 집합을 지원해요. 이는 세 가지 범주로 나뉩니다:
- Structured Outputs (JSON)
- Structured Outputs (Tools) -
strict_tools가True로 설정된 경우 - Tool Use -
strict_tools가False로 설정된 경우
기본 유형(Basic types)
| 파라미터(Parameter) | Structured Outputs (JSON) | Structured Outputs (Tools) | Tool Use |
|---|---|---|---|
| String | Yes | Yes | Yes |
| Integer | Yes | Yes | Yes |
| Float | Yes | Yes | Yes |
| Boolean | Yes | Yes | Yes |
배열(Arrays)
| 파라미터(Parameter) | Structured Outputs (JSON) | Structured Outputs (Tools) | Tool Use |
|---|---|---|---|
| 배열 - 특정 유형 포함(With specific types) | Yes | Yes | Yes |
| 배열 - 특정 유형 없음(Without specific types) | Yes | Yes | Yes |
| 배열 - 리스트의 리스트(List of lists) | Yes | Yes | Yes |
기타(Others)
| 파라미터(Parameter) | Structured Outputs (JSON) | Structured Outputs (Tools) | Tool Use |
|---|---|---|---|
| 중첩 객체(Nested objects) | Yes | Yes | Yes |
| Enum | Yes | Yes | Yes |
| Const¹ | Yes | Yes | Yes |
| Pattern | Yes | Yes | Yes |
| Format² | Yes | Yes | Yes |
| $ref | Yes | Yes | Yes |
| $def | Yes | Yes | Yes |
| additionalProperties | Yes³ | Yes⁴ | Yes |
| uniqueItems | No | No | Yes |
| anyOf | Yes | Yes | Yes |
¹ Const는 다음 유형에서 지원됩니다: int, float, bool, type(None), str.
² Format은 다음 값에서 지원됩니다: date-time, uuid, date, time.
³ Structured Outputs (JSON)에서 additionalProperties는 required, dependencies, propertyNames, anyOf, allOf, oneOf를 강제하지 않습니다.
⁴ Structured Outputs (Tools)에서 additionalProperties는 required, dependencies, propertyNames, any Of, all Of, one Of를 강제하지 않아요.
지원되지 않는 스키마 기능(Unsupported schema features)
우리는 JSON Schema 사양 전체를 지원하지 않아요. 아래는 지원되지 않는 몇 가지 기능 목록입니다:
- 스키마 합성(Schema Composition) (
allOf,oneOf및not) - 숫자 범위(Numeric Ranges) (
maximum및minimum) - 배열 길이 범위(Array Length Ranges) (
minItems및maxItems) - 문자열 제한:
- 문자열 길이(String Length) (
maxLength및minLength) - 다음은 정규 표현식(Regular Expressions)에서 지원되지 않습니다
^$?=?!
- 다음 형식(formats)만 지원됩니다
date-timeuuiddatetime
- 문자열 길이(String Length) (
중요(Important)
참고: Structured Outputs(JSON Schema 및 Tools 모드 모두)를 사용하면 구조화된 스키마를 처리하는 데 필요한 지연 시간 오버헤드가 발생해요. 이 지연 시간 증가는 스키마가 이후에 캐시되기 때문에 처음 몇 개의 요청에만 적용됩니다.