用 openai gem 在 Ruby 中发出第一个请求:base_url、密钥、用量
一个简短的 Ruby 脚本:官方 openai gem、自定义 base_url 和来自环境变量的密钥。打印回复文本和 token 用量。

是的,官方 openai gem 可以与 CheapTokens 配合使用:将 base_ 和你的密钥传给 OpenAI::Client.,调用 client.,然后从 choices. 读取文本。本页其余部分是完整脚本、如何解读返回内容,以及运行失败时该检查什么。
假设你有一个为支持工单打标签的 rake 任务,或者一个在保存笔记前先做摘要的后台作业。你想要官方 SDK,而不是手写 HTTP,并且想看到每次调用用了多少 token。这个脚本正是为此而写。
开始之前你需要准备什么#
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 这个词对你来说很陌生,这篇关于保护密钥安全的指南 只需五分钟阅读。
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.usage用 ruby ask.rb 运行它。有三处值得再看一眼。
用 ENV.fetch 而不是 ENV[...]。如果变量缺失,fetch 会立刻停止,并抛出一个指明该变量的 KeyError。ENV[...] 会悄悄传入 nil,几行之后你就会遇到令人困惑的认证错误。
base_url: 是唯一与 gem README 中 OpenAI 示例不同的行。其余代码完全相同,这正是 OpenAI 兼容 API 的意义所在。如果这个概念对你来说很新,base_url 是什么以及如何切换 用餐厅类比做了解释。
模型 id 要用完整的,即 deepseek-。价格表中的短名称不被 API 接受;请从 CheapTokens 文档 或 GET /v1/models 获取 id。

解读返回内容#
回复是一个对象,不是哈希,所以你要在它上面调用方法。文本位于 completion.;gem 的 README 也使用这个路径。
从第一天起就值得多打印两行:
finish_reason告诉你模型为什么停止。stop是正常结束。length表示答案被长度限制截断。如果你看到这种情况,答案为什么会被截断以及如何修复。usage保存本次调用计费的 token:你发送的和模型写出的。脚本用puts completion.打印整个对象,所以你能看到 API 返回的两个数字。usage
为什么要记录它们?因为 token 就是账单。一个一句话的问题配一句话的回答很小,但每天运行一千次的作业就不小了。输入 token 与输出 token 解释了为什么第二个数字通常每 token 更贵。
这样一次调用要花多少钱#
CheapTokens 上的 DeepSeek-V4-Flash 是每 1M 输入 token $0.015,每 1M 输出 token $0.10,一天中任何时段价格相同。以一个工单打标签作业为例:每张工单约 300 输入 token、150 输出 token。一张工单花费 $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 个输入 token 和 150 个输出 token。每 100 万 token 的价格为当前价格,会随我们的资费一同变动;OpenRouter 列显示相同工作负载的参考价格。
该模型最多支持 380K token 上下文和单次回答最多 32,768 token,所以摘要作业很少会撞墙。如果你想用同一个脚本试试第二个模型,只需把 model: 字符串改成 zai-(390K 上下文,最多 8,192 输出 token)。
如果运行不起来#
首次运行失败大多是五种情况之一。挑一个与你屏幕相符的。
选择你的情况
你看到什么?
选择一个选项以查看答案
KeyError: key not found: "CHEAPTOKENS_API_KEY"
该变量在这个终端中没有设置。再次运行 export 行,或打开新 shell 并用 echo $CHEAPTOKENS_ 检查。
401 Unauthorized
密钥存在但错误:多余的空格或引号、粘贴被截断,或旧密钥。从你的账户重新复制。
404 Not Found
先检查 base_url:它以 /v1 结尾,后面没有多余路径。然后检查模型 id:它是带 deepseek-ai/ 前缀的完整 id。
cannot load such file -- openai
该 gem 没有为这个 Ruby 安装。运行 bundle install 并用 bundle exec ruby ask. 启动脚本。
Bundler 找不到可用版本
检查 ruby -v。0.120.x 系列需要 Ruby 3.3.0 或更新版本;在 3.2 上请改为固定 0.75.x 系列。
401 和 404 情况会出现在每个 SDK 中,不只是 Ruby;API 401 或 404:密钥、base URL 或模型 id 错误 按顺序逐一讲解。
快速检查
finish_reason "length" 告诉你什么?
显示答案
答案: 答案被长度限制截断
stop 是正常结束;length 表示答案在模型完成之前就达到了限制。
接下来去哪里#
你现在有了最小可用的循环:发送、读取文本、记录 token。从这里开始,把调用包装成方法,并把 usage 数字加入你的日志记录器。如果你的技术栈是混合的,其他语言也有同样的模式:Go、Java 和 C#。完整的模型和价格列表在模型页面,API 参考在文档中。



