ブログに戻る

APIとSDKガイド

openai gemを使ったRubyでの最初のリクエスト: base_url、キー、usage

短いRubyスクリプト: 公式openai gem、カスタムbase_url、envからのキー。返信テキストとトークン使用量を出力します。

投稿者: CheapTokens Team公開日 読了時間 6 分

OpenAI::Client.newとCheapTokensを指すカスタムbase_urlを使ったRubyスクリプト
このページの内容
  1. 始める前に必要なもの
  2. スクリプト
  3. 返ってきたものを読む
  4. このような呼び出しのコスト
  5. 動かない場合
  6. 次に進む先

はい、公式のopenai gemはCheapTokensで動作します。base_url: "https://api.cheaptokens.dev/v1"とあなたのキーをOpenAI::Client.newに渡し、client.chat.completions.createを呼び出して、choices.first.message.contentからテキストを読み取ります。このページの残りは、完全なスクリプト、返ってきたものをどう読むか、そして動かないときに何を確認するかです。

サポートチケットにラベルを付ける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内で:

ruby
gem "openai", "~> 0.120.0"

次にbundle install。Bundlerなしなら、gem install openai -v 0.120.0で同じことができます。

CheapTokensアカウントのAPIキーも必要です。コードには入れず、環境変数に入れてください。.gitignoreという言葉が初めてなら、キーを安全に保つためのこのガイドは5分で読めます。

bash
export CHEAPTOKENS_API_KEY="sk-your-key"

スクリプト#

ask.rbを作成します:

ruby
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.usage

ruby ask.rbで実行します。もう一度見る価値のある点が3つあります。

ENV[...]ではなくENV.fetch。変数が欠けていると、fetchはその変数名を示すKeyErrorで即座に停止します。ENV[...]は黙ってnilを渡し、数行後に紛らわしい認証エラーが出ます。

base_url:は、gemのREADMEにあるOpenAIの例と異なる唯一の行です。それ以外はすべて同じコードで、これがOpenAI互換APIの要点です。この考えが初めてなら、base_urlとは何か、切り替え方がレストランの例えで説明しています。

モデルIDは完全なもの、deepseek-ai/DeepSeek-V4-Flash-0731です。価格表の短い名前はAPIに受け付けられません。IDはCheapTokensのドキュメントかGET /v1/modelsから取得してください。

Gemfileの行、エクスポートしたキー、ruby ask.rbがあるターミナル
3つのコマンド: gemを固定し、キーをエクスポートし、スクリプトを実行する。

返ってきたものを読む#

返信はハッシュではなくオブジェクトなので、メソッドを呼び出します。テキストはcompletion.choices.first.message.contentにあり、これはgemのREADMEでも使われているパスです。

初日から出力する価値のある行がもう2つあります:

  • finish_reasonはモデルがなぜ停止したかを示します。stopは正常な終了です。lengthは長さ制限で回答が打ち切られたことを意味します。これが出たら、回答が打ち切られる理由と修正方法を参照してください。
  • usageには、その呼び出しで課金されたトークン、つまり送ったものとモデルが書いたものが入っています。スクリプトはputs completion.usageでオブジェクト全体を出力するので、APIが返した両方の数値が確認できます。

なぜログに残すのか?トークンが請求だからです。一文の質問に一文の回答ならごくわずかですが、1日に千回実行されるジョブはそうではありません。入力トークンと出力トークンは、2番目の数値が通常トークンあたり高くつく理由を説明しています。

このような呼び出しのコスト#

CheapTokensのDeepSeek-V4-Flashは、100万入力トークンあたり$0.015、100万出力トークンあたり$0.10で、時間帯にかかわらず同じ価格です。チケットのラベル付けジョブを例にすると、チケットあたり約300トークン入力、150トークン出力です。1チケットのコストは$0.00002です。千チケットでは次のようになり、隣の列にOpenRouterの参考価格を示します:

モデル リクエストあたり 1,000 リクエスト OpenRouter、1,000 リクエスト
GLM-5.3-Flash $0.000012 $0.012 $0.0225
DeepSeek-V4-Flash $0.00002 $0.0195 $0.042
MiniMax-M2.7 $0.000038 $0.0375 $0.45

リクエストあたり 300 入力トークンと 150 出力トークン。100万トークンあたりの価格は現行のもので、当社の料金体系に合わせて変動します。OpenRouter 列は同じワークロードの参考価格を示しています。

このモデルは最大380Kトークンのコンテキストと、1回の回答で最大32,768トークンを扱えるので、要約ジョブが壁にぶつかることはほとんどありません。同じスクリプトで別のモデルを試したいなら、model:文字列をzai-org/GLM-5.3-Flashに変えるだけです(390Kコンテキスト、最大8,192出力トークン)。

動かない場合#

初回実行の失敗のほとんどは5つのうちのどれかです。画面に合うものを選んでください。

ケースを選ぶ

何が見えますか?

KeyError: key not found: "CHEAPTOKENS_API_KEY"

このターミナルで変数が設定されていません。exportの行をもう一度実行するか、新しいシェルを開いてecho $CHEAPTOKENS_API_KEYで確認してください。

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.rbでスクリプトを開始してください。

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リファレンスはドキュメントにあります。