推論(Thinking)

Prev Next

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 リクエストデータの形式
  • application/json
Accept Conditional レスポンスデータの形式
  • text/event-stream
参考

レスポンス結果は基本的に JSON形式で返されますが、Accepttext/event-streamに指定するとレスポンス結果をストリーム形式で返します。

リクエストパスパラメータ

リクエストパスパラメータの説明は次の通りです。

フィールド タイプ 必須の有無 説明
modelName Enum Required モデル名
  • <例> HCX-007
参考

HCX-007推論モデルは Chat Completions v3 APIでのみ使用可能で、画像入力とチューニング学習はサポートしていません。

リクエストボディ

リクエストボディの説明は次の通りです。

フィールド タイプ 必須の有無 説明
messages Array Required 会話メッセージ
thinking Object Optional 推論モデルの設定情報
thinking.effort Enum Optional 推論の有無と思考の深さの設定
  • none | low (デフォルト) | medium |high |
    • none: 推論しない
    • low: 短い推論
    • medium: 中間の長さの推論
    • high: 長い推論
topP Double Optional 生成トークン候補群を累積確率に基づいてサンプリング
  • 0.00 < topP ≤ 1.00 (デフォルト: 0.80)
topK Integer Optional 生成トークン候補群から確率の高いトークン K個を候補に指定してサンプリング
  • 0 ≤ topK ≤ 128 (デフォルト: 0)
maxCompletionTokens Integer Optional 最大トークン生成数 (推論内容を含む会話メッセージの長さ)
  • 1 ≤ maxCompletionTokens ≤ 32768 (デフォルト: thinking.effortによって異なる)
    • none: 512
    • low: 5120
    • medium: 10240
    • high: 20480
  • maxTokensは使用不可
temperature Double Optional 生成トークンに対する多様性の程度(設定値が高いほど多様な文章を生成)
  • 0.00 ≤ temperature ≤ 1.00 (デフォルト: 0.50)
repetitionPenalty Double Optional 同じトークンを生成することに対するペナルティの程度(設定値が高いほど同じ結果値を繰り返し生成する確率は下がる)
  • 0.0 < repetitionPenalty ≤ 2.0 (デフォルト: 1.1)
seed Integer Optional モデルの繰り返し実行時、結果値の一貫性レベルを調整
  • 0: 一貫性レベルをランダム適用 (デフォルト)
  • 1 ≤ seed ≤ 4294967295: 一貫して作成しようとする結果値のseedまたはユーザーが指定するseed
includeAiFilters Boolean Optional AIフィルタ(生成された結果値に対する罵倒、蔑み/差別/嫌悪、セクハラ/わいせつなどカテゴリ別に当てはまる程度)結果を表示するかどうか
  • true(デフォルト) | false
    • true: 表示
    • false: 表示しない

messages

messagesの説明は次の通りです。

フィールド タイプ 必須の有無 説明
role Enum Required 会話メッセージのロール
  • system | user | assistant |
    • system: ロールを規定する指示文
    • user: ユーザーの発話または質問
    • assistant: ユーザーの発話/質問に対する回答
content String | Array Required 会話メッセージ内容

content

contentの説明は次の通りです。

フィールド タイプ 必須の有無 説明
type Enum Required 会話メッセージ内容の形式
  • text (有効値)
text String Conditional 会話メッセージ内容
  • テキスト入力
    • typetextの場合、必ず入力
参考

一部フィールドの入力時、下記の内容をご確認ください。

  • 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 - レスポンスデータの形式
  • application/json

レスポンスボディ

レスポンスボディの説明は次の通りです。

フィールド タイプ 必須の有無 説明
status Object - レスポンスステータス
result Object - レスポンス結果
result.message Object - 会話メッセージ
result.message.role Enum - 会話メッセージのロール
  • system | user | assistant
    • system: ロールを規定する指示文
    • user: ユーザーの発話または質問
    • assistant: モデルの回答
result.message.content String - 会話メッセージの内容
result.message.thinkingContent String - 会話メッセージのうち、推論の内容
result.finishReason String - トークン生成停止の理由(通常、最後のイベントで渡す)
  • length | stop
    • length: 長さ制限
    • stop: 回答生成中にstopに指定した文字が登場
    • tool_calls: モデルが正常にツール呼び出しを完了
result.created Integer - レスポンスの日付
  • Unix timestamp miliseconds形式
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フィルタのカテゴリ
  • curse | unsafeContents
    • curse: 蔑み、差別、嫌悪および罵倒
    • unsafeContents: セクハラ、わいせつ
name String - AIフィルタの詳細カテゴリ
  • discrimination | insult | sexualHarassment
    • discrimination: 蔑み、差別、嫌悪
    • insult: 罵倒
    • sexualHarassment: セクハラ、わいせつ
score String - AIフィルタスコア
  • -1 | 0 | 1 | 2
    • -1: AIフィルタにエラー発生
    • 0: 会話メッセージに要注意/危険な表現を含む可能性が高い
    • 1: 会話メッセージに要注意/危険な表現を含む可能性がある
    • 2: 会話メッセージに要注意/危険な表現を含む可能性が低い
result String - AIフィルタは正常に動作しているか
  • OK | ERROR
    • OK: 正常に動作
    • ERROR: エラー発生
参考

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 - 会話メッセージのロール
  • user | assistant
    • user: ユーザーの発話または質問
    • assistant: モデルの回答
message.content String - 会話メッセージの内容
message.thinkingContent String - 会話メッセージのうち、推論の内容
finishReason String - トークン生成停止の理由(通常、最後のイベントで渡す、その他は null)
  • length | stop
    • length: 長さ制限
    • stop: 回答生成中にstopに指定した文字が登場
created Integer - レスポンス時間のタイムスタンプ
seed Integer - 入力 seed値(0を入力したか、未入力の場合はランダムな値を返す)
usage Object - トークン使用量 (‭通常、最後のイベントで渡す、その他は null)

StreamingChatCompletionsResultEvent

StreamingChatCompletionsResultEventの説明は次の通りです。

フィールド タイプ 必須の有無 説明
message Object - 会話メッセージ
message.role Enum - 会話メッセージのロール
  • user | assistant
    • user: ユーザーの発話または質問
    • assistant: モデルの回答
message.content String - 会話メッセージの内容
message.thinkingContent String - 会話メッセージのうち、推論の内容
finishReason String - トークン生成停止の理由
  • length | stop
    • length: 長さ制限
    • stop: 回答生成中 stopに指定した文字が登場
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のデフォルト値 説明
      none 512
      low 5120
      medium 10240
      high 20480
  • 推論の長さ(最大トークン生成数)
    • maxCompletionTokensを介して設定します。推論内容と最終回答トークン数をすべて含みます。
      • 推論では、maxTokensではなく、maxCompletionTokensを使用します。
    • 値を直接設定することはできますが、設定値が十分に大きくない場合、モデルが推論中にその長さに達すると、最終回答を生成できない場合があります。したがって、デフォルト値を守るか、複数回試して適切な長さを見つけて設定してください。
参考

比較的長い出力値を生成するには、一定時間がかかる場合がありますので、ストリーム出力の設定をお勧めします。

推論内容の確認

推論を使用した APIリクエスト時のレスポンス結果には、推論内容と最終回答がそれぞれ構成されて出力されます。推論内容とトークン数は次のように確認できます。

  • 推論モデルが最終回答のために生成した思考過程を含む推論内容は、レスポンスボディのmessage.thinkingContentで確認できます。
  • 推論内容のトークン数は、レスポンスボディのusage.completionTokensDetails.thinkingTokensで確認できます。
注意

推論内容は、より良い最終回答を得るための過程であり、システムプロンプトをはじめ、モデルに渡されたコンテキストの一部が含まれる場合があります。そのため、推論内容は開発目的でのみ活用することをお勧めします。別途後処理せずにユーザーに提供することはご遠慮ください。

マルチターン会話時の入力処理

マルチターン会話を続ける場合、CLOVA Studio推論モデルの推論内容(message.thinkingContent)は除外し、最終回答であるモデルレスポンス(message.content)だけ次のターン入力に含める必要があります。次の図をご参照ください。

CLOVA Studio_thinking_multiturn.png