Classic/VPC環境で利用できます。
複雑な問題解決能力を備えた HCX-007推論モデルを利用できる v3 Chat Completionsを説明します。
リクエスト
リクエスト形式を説明します。リクエスト形式は次の通りです。
| メソッド | URI |
|---|---|
| POST | /v3/chat-completions/{modelName} |
リクエストヘッダ
リクエストヘッダの説明は次の通りです。
| ヘッダ | 必須の有無 | 説明 |
|---|---|---|
Authorization |
Required | 認証用 APIキー<例> Bearer nv-************ |
X-NCP-CLOVASTUDIO-REQUEST-ID |
Optional | リクエスト ID |
Content-Type |
Required | リクエストデータの形式
|
Accept |
Conditional | レスポンスデータの形式
|
レスポンス結果は基本的に JSON形式で返されますが、Acceptをtext/event-streamに指定するとレスポンス結果をストリーム形式で返します。
リクエストパスパラメータ
リクエストパスパラメータの説明は次の通りです。
| フィールド | タイプ | 必須の有無 | 説明 |
|---|---|---|---|
modelName |
Enum | Required | モデル名
|
HCX-007推論モデルは Chat Completions v3 APIでのみ使用可能で、画像入力とチューニング学習はサポートしていません。
リクエストボディ
リクエストボディの説明は次の通りです。
| フィールド | タイプ | 必須の有無 | 説明 |
|---|---|---|---|
messages |
Array | Required | 会話メッセージ |
thinking |
Object | Optional | 推論モデルの設定情報 |
thinking.effort |
Enum | Optional | 推論の有無と思考の深さの設定
|
topP |
Double | Optional | 生成トークン候補群を累積確率に基づいてサンプリング
|
topK |
Integer | Optional | 生成トークン候補群から確率の高いトークン K個を候補に指定してサンプリング
|
maxCompletionTokens |
Integer | Optional | 最大トークン生成数 (推論内容を含む会話メッセージの長さ)
|
temperature |
Double | Optional | 生成トークンに対する多様性の程度(設定値が高いほど多様な文章を生成)
|
repetitionPenalty |
Double | Optional | 同じトークンを生成することに対するペナルティの程度(設定値が高いほど同じ結果値を繰り返し生成する確率は下がる)
|
seed |
Integer | Optional | モデルの繰り返し実行時、結果値の一貫性レベルを調整
|
includeAiFilters |
Boolean | Optional | AIフィルタ(生成された結果値に対する罵倒、蔑み/差別/嫌悪、セクハラ/わいせつなどカテゴリ別に当てはまる程度)結果を表示するかどうか
|
messages
messagesの説明は次の通りです。
| フィールド | タイプ | 必須の有無 | 説明 |
|---|---|---|---|
role |
Enum | Required | 会話メッセージのロール
|
content |
String | Array | Required | 会話メッセージ内容
|
content
contentの説明は次の通りです。
| フィールド | タイプ | 必須の有無 | 説明 |
|---|---|---|---|
type |
Enum | Required | 会話メッセージ内容の形式
|
text |
String | Conditional | 会話メッセージ内容
|
一部フィールドの入力時、下記の内容をご確認ください。
role:systemの会話メッセージは、リクエストごとに1つだけ含めることができます。role:assistantの会話メッセージの入力時、message.thinkingContentはリクエストに含めません。- 推論と Function calling、または Structured Outputsは同時にリクエストできません。
- 推論を使用すると Chat Completions V3の
stopは使用できません。 - HCX-007
- 入力トークンと出力トークンの合計は128,000トークンを超えてはいけません。
- 入力トークンの最大値は128,000トークンまでです。
- モデルにリクエスト可能な出力トークン(
maxCompletionTokens)は最大32768トークンまでです。
リクエスト例
リクエストのサンプルコードは次の通りです。
curl --location --request POST 'https://clovastudio.stream.ntruss.com/v3/chat-completions/HCX-007' \
--header 'Authorization: Bearer {CLOVA Studio API Key}' \
--header 'X-NCP-CLOVASTUDIO-REQUEST-ID: {Request ID}' \
--header 'Content-Type: application/json' \
--header 'Accept: text/event-stream' \
--data '{
"messages": [
{
"role": "system",
"content": "- 高度に体系的な分析家であり、論理に基づいた問題解決のエキスパートです。"
},
{
"role": "user",
"content": [
{
"type": "text",
"text": "n個の要素を持つ集合があるとして、この集合から作られる部分集合の数が2ⁿになることを説明しなさい。"
}
]
}
],
"thinking": {
"effort": "low"
},
"topP": 0.8,
"topK": 0,
"maxCompletionTokens": 5120,
"temperature": 0.5,
"repetitionPenalty": 1.1,
"stop": []
}'
レスポンス
レスポンス形式を説明します。
レスポンスヘッダ
レスポンスヘッダの説明は次の通りです。
| ヘッダ | 必須の有無 | 説明 |
|---|---|---|
Content-Type |
- | レスポンスデータの形式
|
レスポンスボディ
レスポンスボディの説明は次の通りです。
| フィールド | タイプ | 必須の有無 | 説明 |
|---|---|---|---|
status |
Object | - | レスポンスステータス |
result |
Object | - | レスポンス結果 |
result.message |
Object | - | 会話メッセージ |
result.message.role |
Enum | - | 会話メッセージのロール
|
result.message.content |
String | - | 会話メッセージの内容 |
result.message.thinkingContent |
String | - | 会話メッセージのうち、推論の内容 |
result.finishReason |
String | - | トークン生成停止の理由(通常、最後のイベントで渡す)
|
result.created |
Integer | - | レスポンスの日付
|
result.seed |
Integer | - | 入力 seed値(0を入力したか、未入力の場合はランダムな値を返す) |
result.usage |
Object | - | トークン使用量 |
result.usage.completionTokens |
Integer | - | 生成トークン数 |
result.usage.promptTokens |
Integer | - | 入力(プロンプト)トークン数 |
result.usage.totalTokens |
Integer | - | トークンの総数
|
result.usage.completionTokensDetails |
Object | - | 生成トークン数に関する追加情報 |
result.usage.completionTokensDetails.thinkingTokens |
Integer | - | 推論トークン数 |
result.aiFilter |
Array | - | AIフィルタの結果 |
aiFilter
aiFilterの説明は次の通りです。
| フィールド | タイプ | 必須の有無 | 説明 |
|---|---|---|---|
groupName |
String | - | AIフィルタのカテゴリ
|
name |
String | - | AIフィルタの詳細カテゴリ
|
score |
String | - | AIフィルタスコア
|
result |
String | - | AIフィルタは正常に動作しているか
|
AI Filterは最大500文字まで分析できます。ただし、分析対象テキストに異常な形式、絵文字、記号などが多い場合、正常に分析されないことがあります。
レスポンス例
レスポンスのサンプルコードは次の通りです。
成功
呼び出しに成功した場合のレスポンスのサンプルコードは次の通りです。
{
"status": {
"code": "20000",
"message": "OK"
},
"result": {
"message": {
"role": "assistant",
"content": "部分集合の数は、各要素を含めるか、含めないかという2つの選択で決まります。\n例えば、{a}の部分集合は∅、{a} → 2個(2¹)であり、
{a,b}は∅、{a}、{b}、{a,b} → 4個(2²)です。\nn個の要素からなる集合では、それぞれの要素につき2つの選択肢(含める/含めない)があるため、全体の場合の数は2 × 2 × ... × 2 (n回) = 2ⁿとなります。\nまたは、二項定理で説明することもできます。部分集合のサイズが k個である場合の数は **C(n,k)** ですので、すべての k(0 ≤ k ≤ n)について和をとると∑_{k=0}^n C(n,k) = (1+1)^n = 2ⁿとなります。\nしたがって、n個の要素を持つ集合の部分集合の数は常に2ⁿです。",
"thinkingContent": "今日ユーザーが質問した問題は、n個の要素を持つ集合から作られる部分集合の数がなぜ2ⁿになるのかのことだった。これは組合せ論や2進法と関係があるんじゃないかな。\nまず、各要素に対して選択するか、選択しないかの2つの場合があると考えてみよう。例えば、要素が1つの場合、部分集合は空集合とそれ自体で合計2つ、つまり2^1=2つとなる。要素が2つあるときはそれぞれ含まれるか含まれないかだから、2*2=4個、2^2=4になるしね。\n一般化すると各要素は2つの選択(含むか/含めないか)が可能だから、全体の場合の数は2をn回掛けたもの、つまり2^nになるわけだ。これが基本的な組合せ的な考え方なのだ。\nもしくは、部分集合のサイズが kである場合の数は C(n,k)で、これを k=0から nまで足すと、(1+1)^n = 2^nになるという二項定理でも説明できる。だから、部分集合の数は2^nという結論にたどり着くのだ。\nユーザーはこの説明を望んだだろうから、各要素の選択の有無でアプローチしたほうが簡潔でいいと思う。例を挙げて説明して、一般化する過程を短くまとめることにしよう。"
},
"finishReason": "stop",
"created": 1753362971
"seed": 1561390649,
"usage": {
"promptTokens": 58,
"completionTokens": 631,
"totalTokens": 689,
"completionTokensDetails": {
"thinkingTokens": 366
}
}
失敗
呼び出しに失敗した場合のレスポンスのサンプルコードは次の通りです。
レスポンスストリーム
生成されるトークンを1つずつ出力するようにトークンストリーミングを使用できます。トークンストリーミング形式を説明します。
レスポンスボディ
レスポンスボディの説明は次の通りです。
StreamingChatCompletionsTokenEvent
StreamingChatCompletionsTokenEventの説明は次の通りです。
| フィールド | タイプ | 必須の有無 | 説明 |
|---|---|---|---|
message |
Object | - | 会話メッセージ |
message.role |
Enum | - | 会話メッセージのロール
|
message.content |
String | - | 会話メッセージの内容 |
message.thinkingContent |
String | - | 会話メッセージのうち、推論の内容 |
finishReason |
String | - | トークン生成停止の理由(通常、最後のイベントで渡す、その他は null)
|
created |
Integer | - | レスポンス時間のタイムスタンプ |
seed |
Integer | - | 入力 seed値(0を入力したか、未入力の場合はランダムな値を返す) |
usage |
Object | - | トークン使用量 (通常、最後のイベントで渡す、その他は null) |
StreamingChatCompletionsResultEvent
StreamingChatCompletionsResultEventの説明は次の通りです。
| フィールド | タイプ | 必須の有無 | 説明 |
|---|---|---|---|
message |
Object | - | 会話メッセージ |
message.role |
Enum | - | 会話メッセージのロール
|
message.content |
String | - | 会話メッセージの内容 |
message.thinkingContent |
String | - | 会話メッセージのうち、推論の内容 |
finishReason |
String | - | トークン生成停止の理由
|
created |
Integer | - | レスポンス時間のタイムスタンプ |
seed |
Integer | - | 入力 seed値(0を入力したか、未入力の場合はランダムな値を返す) |
usage |
Object | - | トークン使用量 |
usage.completionTokens |
Integer | - | 生成トークン数 |
usage.promptTokens |
Integer | - | 入力(プロンプト)トークン数 |
usage.totalTokens |
Integer | - | トークンの総数
|
usage.completionTokensDetails |
Object | - | 生成トークン数に関する追加情報 |
usage.completionTokensDetails.thinkingTokens |
Integer | - | 推論トークン数 |
aiFilter |
Array | - | AIフィルタの結果 |
ErrorEvent
ErrorEventの説明は次の通りです。
| フィールド | タイプ | 必須の有無 | 説明 |
|---|---|---|---|
status |
Object | - | レスポンスステータス |
status.code |
Object | - | レスポンスステータスコード |
status.message |
Object | - | レスポンスステータスメッセージ |
SignalEvent
SignalEventの説明は次の通りです。
| フィールド | タイプ | 必須の有無 | 説明 |
|---|---|---|---|
data |
String | - | 渡すシグナルデータ情報 |
レスポンス例
レスポンスのサンプルコードは次の通りです。
成功
呼び出しに成功した場合のレスポンスのサンプルコードは次の通りです。
id: aabdfe-dfgwr-edf-hpqwd-f3asd-g
event: token
data: {"message": {"role": "assistant", "thinkingContent": “今日”},"finishReason": null, "created": 1744710905, "seed": 3284419119, "usage": null}
...
id: aabdfe-dfgwr-edf-hpqwd-f2asd-g
event: token
data: {"message": {"role": "assistant", "content": “部分”},"finishReason": null, "created": 1744710905, "seed": 3284419119, "usage": null}
...
id: aabdfe-dfgwr-edf-hpqwd-f1asd-g
event: result
data: {
"message": {
"role": "assistant",
"content": "部分集合の数は、各要素を**含むか含まないか**で決まります。 \n各要素は **\"含む\"または\"含まない\"** のどちらかを選択できるので、1つの要素につき2つの場合が発生します。 \n\n例えば: \n- 要素が1つの集合({a}) → ∅、{a} ( **2¹ = 2** )\n- 要素が2つの集合({a, b}) → ∅、{a}、{b}、{a,b} ( **2² = 4** ) \n\n拡張すると、**n個の要素**は、段階ごとに前の結果(2ⁿ-¹)の**2倍**ずつ増加します( **2ⁿ⁻¹ × 2 = 2ⁿ** )。 \nすなわち、部分集合の数は**2ⁿ**と表され、これは各要素の独立した選択可能性を反映したものです。 \n\n空集合と全体集合も自然に含まれるので、公式の**2ⁿ**は完全で一貫した結果を提供します。",
"thinkingContent": "今日ユーザーが質問した問題は、n個の要素からなる集合の部分集合の数がなぜ2ⁿになるのかというもの。これはどう説明したら分かりやすいのかな。\n\nまず基本的な考え方から始めよう。各要素は、部分集合に含めるか、含めないか、2つの選択肢がある。例えば、要素が1つであれば、{}、{a}の2つの部分集合があるってわけだ。2^1=2で、ちょうど当てはまる。\n\n2個目の要素 bを追加すると、それぞれの既存の部分集合に bを入れるか入れないかを決めなければならない。元々{}と{a}のそれぞれに bを追加したり、追加しなかったりするから、合計4つになる。つまり2^2=4だね。このように拡張すると、各段階で前の場合の数に2を掛けることを繰り返されるから、最終的には2×2×...×2 (n回) = 2^nになるのだ。\n\nもう1つのアプローチとして、各要素に対する独立した選択を強調するものがある。各要素を含めるか含めないかが互いに影響しないから、組み合わせの掛け算の法則を適用できる。したがって、全体の場合の数は2 × 2 × ... × 2 (n回) = 2^nとなるわけだ。\n\n空集合や全体集合も含まれることに言及すべきかな。例を示せばもっと分かりやすいだろう。しかし、簡潔に説明するには、核となる考え方である各要素の選択可能性だけ強調しても十分なのでは?\n\n最後に、数学的に厳密に証明するために帰納法を使うこともできるが、ユーザーの希望は簡単な説明のようだから、基本的なロジックを中心に答えることにしよう。この流れでよさそうだ!"
},
"finishReason": "stop",
"created": 1753363313,
"seed": 3219533885,
"usage": {
"promptTokens": 58,
"completionTokens": 588,
"totalTokens": 646,
"completionTokensDetails": {
"thinkingTokens": 361
}
}
}
失敗
呼び出しに失敗した場合のレスポンスのサンプルコードは次の通りです。
推奨事項
CLOVA Studioの推論モデルは、最終回答を直接生成せず、ユーザーの質問を分析し、必要な論理的思考を経て推論内容(トークン)を生成した後、これに基づいて最終回答を生成します。推奨事項では、最適化された最終回答を生成するために推論モデルを効果的に活用する方法を説明します。
推論の有無と長さの設定
CLOVA Studioの推論モデルは、ユーザーが直接推論の有無と長さを設定できるように学習されています。次の設定方法を参照して、リクエストの種類に合わせて推論の有無と長さを設定してください。
- 推論の有無と推論の思考の深さ
thinking.effortを介して設定します。設定値により、最大リクエストトークン生成数のデフォルト値が次のように適用されます。thinking.effortの設定値maxCompletionTokensのデフォルト値説明 none512 low5120 medium10240 high20480
- 推論の長さ(最大トークン生成数)
maxCompletionTokensを介して設定します。推論内容と最終回答トークン数をすべて含みます。- 推論では、
maxTokensではなく、maxCompletionTokensを使用します。
- 推論では、
- 値を直接設定することはできますが、設定値が十分に大きくない場合、モデルが推論中にその長さに達すると、最終回答を生成できない場合があります。したがって、デフォルト値を守るか、複数回試して適切な長さを見つけて設定してください。
比較的長い出力値を生成するには、一定時間がかかる場合がありますので、ストリーム出力の設定をお勧めします。
推論内容の確認
推論を使用した APIリクエスト時のレスポンス結果には、推論内容と最終回答がそれぞれ構成されて出力されます。推論内容とトークン数は次のように確認できます。
- 推論モデルが最終回答のために生成した思考過程を含む推論内容は、レスポンスボディの
message.thinkingContentで確認できます。 - 推論内容のトークン数は、レスポンスボディの
usage.completionTokensDetails.thinkingTokensで確認できます。
推論内容は、より良い最終回答を得るための過程であり、システムプロンプトをはじめ、モデルに渡されたコンテキストの一部が含まれる場合があります。そのため、推論内容は開発目的でのみ活用することをお勧めします。別途後処理せずにユーザーに提供することはご遠慮ください。
マルチターン会話時の入力処理
マルチターン会話を続ける場合、CLOVA Studio推論モデルの推論内容(message.thinkingContent)は除外し、最終回答であるモデルレスポンス(message.content)だけ次のターン入力に含める必要があります。次の図をご参照ください。
