APIとSDKガイド
openai gemを使ったRubyでの最初のリクエスト: base_url、キー、usage
短いRubyスクリプト: 公式openai gem、カスタムbase_url、envからのキー。返信テキストとトークン使用量を出力します。

はい、公式のopenai gemはCheapTokensで動作します。base_とあなたのキーをOpenAI::Client.に渡し、client.を呼び出して、choices.からテキストを読み取ります。このページの残りは、完全なスクリプト、返ってきたものをどう読むか、そして動かないときに何を確認するかです。
サポートチケットにラベルを付けるrakeタスクや、保存前にメモを要約するバックグラウンドジョブがあるとします。手書きのHTTPではなく公式SDKを使いたいし、各呼び出しが何トークン使ったかも見たい。まさにこのスクリプトです。
始める前に必要なもの#
RubyGemsのgemページ(2026年11月8日確認)にはopenai 0.120.0が掲載されており、2026年11月5日リリース、Apache-2.0です。Ruby 3.3.0以降が必要です。Ruby 3.2で止まっている場合は、gem自体の注記が0.75.x系を指しています。パッケージはまだ0.xで動きが速いので、バージョンを固定してください。
Gemfile内で:
gem "openai", "~> 0.120.0"次にbundle install。Bundlerなしなら、gem install openai -で同じことができます。
CheapTokensアカウントのAPIキーも必要です。コードには入れず、環境変数に入れてください。.gitignoreという言葉が初めてなら、キーを安全に保つためのこのガイドは5分で読めます。
export CHEAPTOKENS_API_KEY="sk-your-key"スクリプト#
ask.rbを作成します:
require "openai"
client = OpenAI::Client.new(
api_key: ENV.fetch("CHEAPTOKENS_API_KEY"),
base_url: "https://api.cheaptokens.dev/v1"
)
completion = client.chat.completions.create(
model: "deepseek-ai/DeepSeek-V4-Flash-0731",
messages: [
{ role: "user", content: "Explain in one sentence what a token is." }
]
)
choice = completion.choices.first
puts choice.message.content
puts "finish_reason: #{choice.finish_reason}"
puts completion.usageruby ask.rbで実行します。もう一度見る価値のある点が3つあります。
ENV[...]ではなくENV.fetch。変数が欠けていると、fetchはその変数名を示すKeyErrorで即座に停止します。ENV[...]は黙ってnilを渡し、数行後に紛らわしい認証エラーが出ます。
base_url:は、gemのREADMEにあるOpenAIの例と異なる唯一の行です。それ以外はすべて同じコードで、これがOpenAI互換APIの要点です。この考えが初めてなら、base_urlとは何か、切り替え方がレストランの例えで説明しています。
モデルIDは完全なもの、deepseek-です。価格表の短い名前はAPIに受け付けられません。IDはCheapTokensのドキュメントかGET /v1/modelsから取得してください。

返ってきたものを読む#
返信はハッシュではなくオブジェクトなので、メソッドを呼び出します。テキストはcompletion.にあり、これはgemのREADMEでも使われているパスです。
初日から出力する価値のある行がもう2つあります:
finish_reasonはモデルがなぜ停止したかを示します。stopは正常な終了です。lengthは長さ制限で回答が打ち切られたことを意味します。これが出たら、回答が打ち切られる理由と修正方法を参照してください。usageには、その呼び出しで課金されたトークン、つまり送ったものとモデルが書いたものが入っています。スクリプトはputs completion.でオブジェクト全体を出力するので、APIが返した両方の数値が確認できます。usage
なぜログに残すのか?トークンが請求だからです。一文の質問に一文の回答ならごくわずかですが、1日に千回実行されるジョブはそうではありません。入力トークンと出力トークンは、2番目の数値が通常トークンあたり高くつく理由を説明しています。
このような呼び出しのコスト#
CheapTokensのDeepSeek-V4-Flashは、100万入力トークンあたり$0.015、100万出力トークンあたり$0.10で、時間帯にかかわらず同じ価格です。チケットのラベル付けジョブを例にすると、チケットあたり約300トークン入力、150トークン出力です。1チケットのコストは$0.00002です。千チケットでは次のようになり、隣の列にOpenRouterの参考価格を示します:
| モデル | 入力 $/1M | 出力 $/1M | リクエストあたり | 1,000 リクエスト | OpenRouter、1,000 リクエスト |
|---|---|---|---|---|---|
| GLM-5.3-Flash | $0.02 | $0.04 | $0.000012 | $0.012 | $0.0225 |
| DeepSeek-V4-Flash | $0.015 | $0.10 | $0.00002 | $0.0195 | $0.042 |
| MiniMax-M2.7 | $0.05 | $0.15 | $0.000038 | $0.0375 | $0.45 |
リクエストあたり 300 入力トークンと 150 出力トークン。100万トークンあたりの価格は現行のもので、当社の料金体系に合わせて変動します。OpenRouter 列は同じワークロードの参考価格を示しています。
このモデルは最大380Kトークンのコンテキストと、1回の回答で最大32,768トークンを扱えるので、要約ジョブが壁にぶつかることはほとんどありません。同じスクリプトで別のモデルを試したいなら、model:文字列をzai-に変えるだけです(390Kコンテキスト、最大8,192出力トークン)。
動かない場合#
初回実行の失敗のほとんどは5つのうちのどれかです。画面に合うものを選んでください。
ケースを選ぶ
何が見えますか?
オプションを選択して答えを表示
KeyError: key not found: "CHEAPTOKENS_API_KEY"
このターミナルで変数が設定されていません。exportの行をもう一度実行するか、新しいシェルを開いてecho $CHEAPTOKENS_で確認してください。
401 Unauthorized
キーはありますが間違っています: 余分なスペースや引用符、途中で切れた貼り付け、または古いキーです。アカウントからもう一度コピーしてください。
404 Not Found
まずbase_urlを確認してください: /v1で終わり、その後に余分なパスがないこと。次にモデルIDを確認してください: deepseek-ai/プレフィックス付きの完全なIDです。
cannot load such file -- openai
このRubyにgemがインストールされていません。bundle installを実行し、bundle exec ruby ask.でスクリプトを開始してください。
Bundler can't find a version that works
ruby -vを確認してください。0.120.x系はRuby 3.3.0以降が必要です。3.2では代わりに0.75.x系を固定してください。
401と404のケースはRubyに限らずどのSDKでも起こります。API 401または404: キー、base URL、モデルIDの誤りが順を追って説明しています。
クイックチェック
finish_reason "length"は何を教えてくれますか?
答えを表示
答え: 長さ制限で回答が打ち切られた
stopは正常な終了です。lengthはモデルが終わる前に回答が制限に達したことを意味します。
次に進む先#
これで最小限の有用なループができました: 送信し、テキストを読み、トークンをログに残す。ここから呼び出しをメソッドで包み、usageの数値をロガーに追加してください。スタックが混在しているなら、同じパターンが他の言語にもあります: Go、Java、C#。モデルと価格の完全なリストはモデルページに、APIリファレンスはドキュメントにあります。



