コンテンツにスキップ

チャット

チャットは、会話からテキストを生成します。Sakuranbo AI には、チャットのエンドポイントが 2 つあります。どちらも同じモデルを実行し、同じ方法で課金します。違いは、リクエストとレスポンスの形式だけです。

  • POST /v1/chat/completions は、OpenAI Chat Completions API と互換性があります。
  • POST /v1/messages は、Anthropic Messages API と互換性があります。

どちらのエンドポイントも、Authorization: Bearer で送る API キーが必要です。認証を参照してください。POST /v1/messages は、Anthropic SDK がキーを入れる x-api-key ヘッダでも、キーを受け取ります。

このページの例では、sakuranbo/cherrytext-1.0-flash を使います。テキストモデルを探すには、GET /v1/models を task=chat で呼び出します。モデル APIを参照してください。テキストモデルでないモデルを指定すると、404 と model_not_found を返します。

OpenAI と Anthropic の公式 SDK を使えます。SDK の接続先を Sakuranbo AI にして、Sakuranbo AI の API キーを渡します。OpenAI SDK には、/v1 を含むベース URL を指定します。Anthropic SDK は /v1/messages を自分で付け足すため、ベース URL に /v1 は含めません。

TypeScript の OpenAI SDK:

import OpenAI from "openai";
const apiKey = process.env.SAKURANBO_API_KEY;
if (!apiKey) throw new Error("Set the SAKURANBO_API_KEY environment variable.");
const client = new OpenAI({
baseURL: "https://api.sakuranbo.ai/v1",
apiKey,
});
const completion = await client.chat.completions.create({
model: "sakuranbo/cherrytext-1.0-flash",
messages: [
{
role: "system",
content: "You are a concise assistant."
},
{
role: "user",
content: "Summarize the benefits of prepaid API credits in two lines."
}
],
max_tokens: 2048
});
console.log(completion.choices[0]?.message.content);

Python の OpenAI SDK:

import os
from openai import OpenAI
client = OpenAI(
base_url="https://api.sakuranbo.ai/v1",
api_key=os.environ["SAKURANBO_API_KEY"],
)
completion = client.chat.completions.create(
model="sakuranbo/cherrytext-1.0-flash",
messages=[
{
"role": "system",
"content": "You are a concise assistant.",
},
{
"role": "user",
"content": "Summarize the benefits of prepaid API credits in two lines.",
},
],
max_tokens=2048,
)
print(completion.choices[0].message.content)

TypeScript の Anthropic SDK:

import Anthropic from "@anthropic-ai/sdk";
const apiKey = process.env.SAKURANBO_API_KEY;
if (!apiKey) throw new Error("Set the SAKURANBO_API_KEY environment variable.");
// Pass the key as authToken too, so the SDK does not send ANTHROPIC_AUTH_TOKEN from the environment.
const client = new Anthropic({
baseURL: "https://api.sakuranbo.ai",
apiKey,
authToken: apiKey,
});
const message = await client.messages.create({
model: "sakuranbo/cherrytext-1.0-flash",
max_tokens: 2048,
system: "You are a concise assistant.",
messages: [
{
role: "user",
content: "Summarize the benefits of prepaid API credits in two lines."
}
]
});
console.log(message.content);

Python の Anthropic SDK:

import os
import anthropic
api_key = os.environ["SAKURANBO_API_KEY"]
# Pass the key as auth_token too, so the SDK does not send ANTHROPIC_AUTH_TOKEN from the environment.
client = anthropic.Anthropic(
base_url="https://api.sakuranbo.ai",
api_key=api_key,
auth_token=api_key,
)
message = client.messages.create(
model="sakuranbo/cherrytext-1.0-flash",
max_tokens=2048,
system="You are a concise assistant.",
messages=[
{
"role": "user",
"content": "Summarize the benefits of prepaid API credits in two lines.",
},
],
)
print(message.content)

API はサーバーから呼び出してください。API キーを、ブラウザで動くコードに置かないでください。

POST /v1/chat/completions は、messages のリストを受け取り、モデルの次のメッセージを返します。

ターミナルウィンドウ
curl -X POST "https://api.sakuranbo.ai/v1/chat/completions" \
-H "Content-Type: application/json" \
-H "Authorization: Bearer $SAKURANBO_API_KEY" \
-d '{
"model": "sakuranbo/cherrytext-1.0-flash",
"messages": [
{
"role": "system",
"content": "You are a concise assistant."
},
{
"role": "user",
"content": "Summarize the benefits of prepaid API credits in two lines."
}
],
"max_tokens": 2048
}'

生成されたメッセージは choices[0].message に入り、usage にはトークン数と料金が入ります。使用量と料金を参照してください。

名前型必須既定値制約
modelstringはい
messagesobject[]はい1 件以上
max_tokensintegerいいえ
max_completion_tokensintegerいいえ
temperaturenumberいいえ0〜2
top_pnumberいいえ0〜1
stopstring | string[]いいえstring[]: 最大 4 件
seedintegerいいえ1 以上
userstringいいえ最大 512 文字
toolsobject[]いいえ最大 128 件
tool_choicestring | objectいいえstring: 次のいずれか: none, auto, required
response_formatobjectいいえ
nnumberいいえ次のいずれか: 1
streambooleanいいえ
stream_optionsobject | nullいいえ

パラメータの範囲と既定値は、モデルごとに決まります。次の表は、例のモデルのものです。

名前型必須既定値制約説明
messagesobject[]はいOpenAI Chat Completions 形式の会話メッセージ。
max_tokensintegerいいえ40961〜131,072推論に使うトークンを含む、生成するトークン数の上限。小さすぎると、回答を書く前に応答が打ち切られることがあります。残高の仮押さえはこの値で計算します。
temperaturenumberいいえ10〜2サンプリング温度。
streambooleanいいえfalseトークンを Server-Sent Events で逐次返します。

範囲外の max_tokens を指定すると、400 と invalid_request を返します。error.details.minimum と error.details.maximum に、許容範囲が入ります。リクエストに max_tokens と max_completion_tokens の両方があるときは、max_completion_tokens を使います。

関数ツール(tools と tool_choice)と response_format に対応しています。ツール呼び出しは、choices[0].message.tool_calls に入って返ります。

メッセージに入れられるのはテキストだけです。画像など、ほかの種類のコンテンツパートを入れると 400 を返し、error.param がそのパートを指します。フィールドの表にないパラメータも 400 を返し、error.param にパラメータの名前が入ります。

assistant メッセージにテキストも tool_calls の項目もないとき、または content の配列が空のときは、400 を返します。推論の途中で出力が切れたときなど、テキストもツール呼び出しもないレスポンスが返ることがあるため、そのレスポンスは履歴に追加せず、max_tokens を増やして送り直してください。

POST /v1/messages は、Anthropic Messages API の形式で会話を受け取ります。

ターミナルウィンドウ
curl -X POST "https://api.sakuranbo.ai/v1/messages" \
-H "Content-Type: application/json" \
-H "Authorization: Bearer $SAKURANBO_API_KEY" \
-d '{
"model": "sakuranbo/cherrytext-1.0-flash",
"max_tokens": 2048,
"system": "You are a concise assistant.",
"messages": [
{
"role": "user",
"content": "Summarize the benefits of prepaid API credits in two lines."
}
]
}'
名前型必須既定値制約
modelstringはい
messagesobject[]はい1 件以上
systemstring | object[]いいえ
max_tokensintegerはい
temperaturenumberいいえ0〜1
top_pnumberいいえ0〜1
stop_sequencesstring[]いいえ最大 4 件
streambooleanいいえ
toolsobject[]いいえ最大 128 件
tool_choiceobjectいいえ

OpenAI 形式との違いは次のとおりです。

  • max_tokens は必須です。
  • system はトップレベルのフィールドです。ロールが system のメッセージを入れると、400 を返します。
  • temperature の許容範囲は Anthropic API に従うため、POST /v1/chat/completions の範囲とは異なります。
  • anthropic-version ヘッダは不要です。SDK が送ってきても、サーバーは無視します。
  • メッセージに入れられるのは、テキストとツールのブロックだけです。image ブロックを入れると 400 を返します。top_k や thinking など、フィールドの表にないパラメータも 400 を返します。
  • assistant メッセージには、空でない文字列の content、または text か tool_use のブロックを含む content の配列が必要です。推論の途中で出力が切れたときなど、content が空の配列で返ったレスポンスを履歴に追加すると 400 を返すため、max_tokens を増やして送り直してください。
  • エラーの本文はすべて Anthropic 形式です。type は error で、詳細は error に入り、request_id はトップレベルのフィールドです。401、404、405 も同じです。

stream を true にすると、レスポンスをサーバー送信イベントで受け取れます。最初のトークンは、モデルが生成するとすぐに届きます。

ターミナルウィンドウ
curl -N -X POST "https://api.sakuranbo.ai/v1/chat/completions" \
-H "Content-Type: application/json" \
-H "Authorization: Bearer $SAKURANBO_API_KEY" \
-d '{
"model": "sakuranbo/cherrytext-1.0-flash",
"messages": [
{
"role": "system",
"content": "You are a concise assistant."
},
{
"role": "user",
"content": "Summarize the benefits of prepaid API credits in two lines."
}
],
"max_tokens": 2048,
"stream": true,
"stream_options": {
"include_usage": true
}
}'

OpenAI 形式では、各イベントは chat.completion.chunk オブジェクトを持つ data: 行で、新しいテキストは choices[].delta に入ります。ストリームは data: [DONE] で終わります。料金を含む usage オブジェクトは、choices が空配列の最後のチャンクで届きます。届くのは、stream_options.include_usage を true にしたときだけです。

Anthropic 形式では、各イベントは event: 行と data: 行を持ちます。イベントは次の順で届きます。

  1. message_start
  2. コンテンツブロックごとに、content_block_start、1 つ以上の content_block_delta、content_block_stop
  3. message_delta。stop_reason と、料金を含む usage が入ります
  4. message_stop

Anthropic SDK は、自分が知っているフィールドだけから最終的なメッセージを組み立てるため、そこに usage.cost は入りません。料金を読み取るには、message_delta イベントの usage を読んでください。

認証エラーや検証エラーなど、ストリームが始まる前の失敗は、通常の JSON のエラーを、その HTTP ステータスで返します。ストリームが始まったあとの失敗では、ステータスを変えられず、200 のままです。OpenAI 形式では、error オブジェクトを持つ data: 行を送り、続けて data: [DONE] を送ります。Anthropic 形式では、event: error イベントを送り、message_stop は送りません。

ストリーミングでないレスポンスは、料金を 2 か所で、トークン数を usage で伝えます。

  • usage.cost は、micro USD の金額を amount_micro_usd に、10 進文字列の金額を amount_usd に持ちます。
  • X-Usage-Cost-Usd ヘッダに、同じ USD の文字列が入ります。
  • usage にトークン数が入ります。OpenAI 形式では prompt_tokens、completion_tokens、total_tokens、prompt_tokens_details.cached_tokens です。Anthropic 形式では input_tokens、output_tokens、cache_read_input_tokens です。input_tokens に、キャッシュされたトークンは含まれません。

ストリーミングのレスポンスには、X-Usage-Cost-Usd ヘッダがありません。代わりに、最後の usage オブジェクトから料金を読み取ってください。

リクエストを実行する前に、Sakuranbo AI は残高から一定の金額を確保します。金額は、入力の大きさと max_tokens から見積もります。リクエストが終わると、実際のトークン数から請求額を計算し、確保した金額の残りを残高に戻します。出力を何も生成する前にモデル側で失敗したリクエストは、課金されません。

  • 確保する金額に max_tokens を使うため、実際の料金なら残高に収まるリクエストでも、402 で拒否されることがあります。max_tokens は、必要な長さに設定してください。
  • モデルが出力を生成し始めたあとにストリームが途切れたときは、ストリームがエラーで終わっても、そのリクエストは課金されます。出力には推論の出力を含み、利用者に届いたかどうかを問わず課金されます。Anthropic 形式は推論の出力を返さないため、テキストを何も受け取っていなくても課金されることがあります。最終的なトークン数が届かなかったときは、請求額を見積もります。入力は、確保に使った上限で数え、出力は、推論の出力とツールの呼び出しを含め、すでに生成された出力の大きさで数えるため、請求額が実際の使用量より高くなることがあります。確保した金額を超えることはありません。
  • ストリームが終わる前に接続を閉じても、リクエストは最後まで実行され、生成された出力のすべてが課金されます。
  • チャットのリクエストでは、Idempotency-Key を使いません。再試行したリクエストは新しいリクエストで、もう一度課金されます。

価格は、モデルカタログのモデルのページと料金のページで確認できます。実行する前に POST /v1/estimate で計算することもできます。見積 APIを参照してください。残高の読み取り方は、残高とキーの利用上限を参照してください。

コードHTTP ステータス種別説明
invalid_request400invalid_request_errorリクエストの形式が不正か、値が範囲外です。有効な値が分かる場合は details.allowed に入ります。
unauthorized401authentication_errorAPI キーが指定されていない、形式が不正、存在しない、失効済み、または期限切れです。レスポンスからは、どれに当たるかは分かりません。
balance_insufficient402insufficient_balance利用可能な残高が、このリクエストのために確保する金額に足りません。error.details.limit_source は balance です。
key_limit_exceeded402insufficient_balanceこのリクエストを受理すると、API キーの利用上限を超えます。error.details.limit_source は key で、error.details.resets_at にカウンターが数え直される時刻が入ります。
account_suspended403permission_errorアカウントが停止されているため、画像・動画・チャットのリクエストを受け付けません。サポートにお問い合わせください。残高、入金、API キー、ジョブは引き続き利用できます。
model_not_found404not_found_error指定したモデル ID がカタログにありません。チャットのエンドポイントは、テキストモデルでないモデルに対しても、このコードを返します。
payload_too_large413invalid_request_errorリクエスト本文が、許容サイズを超えています。error.details.max_bytes に上限が入ります。
rate_limited429rate_limit_errorモデルの提供元がリクエストを制限しています。POST /v1/reports は、同じアドレスから通報が多く送られたときにも、このコードを返します。Retry-After ヘッダの時間が過ぎてから再試行してください。
upstream_error502upstream_error上流の提供元がエラーを返しました。
upstream_unavailable503overloaded_error上流の提供元が一時的に容量不足です。時間をおいて再試行してください。

POST /v1/messages は、同じコードと HTTP ステータスを、Anthropic のエラー形式で返します。error.type は Anthropic API に従うため、表の「種別」の列と異なることがあります。balance_insufficient と key_limit_exceeded は billing_error、payload_too_large は request_too_large、content_policy_violation は invalid_request_error、upstream_error は api_error です。分岐には error.type ではなく error.code を使ってください。

429 または 503 のレスポンスでは、Retry-After ヘッダの秒数だけ待ってから再試行してください。402 のレスポンスには error.details.limit_source が入り、値は balance か key です。残高とキーの利用上限を参照してください。すべてのコードは、エラーを参照してください。