Skip to content

Commit 032758d

Browse files
authored
Merge branch 'main' into bugfix/fix-dynamic-tool-loading
2 parents fd290a2 + d7b0dfb commit 032758d

622 files changed

Lines changed: 62954 additions & 71020 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.github/workflows/_test-matrix.yml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,9 @@ jobs:
5252
bundle install
5353
bundle exec appraisal ${{ matrix.rails-version }} bundle install
5454
55+
- name: Run eager-load guard (appraisal)
56+
run: bundle exec appraisal ${{ matrix.rails-version }} ruby -e "require 'ruby_llm'; Zeitwerk::Loader.eager_load_all"
57+
5558
- name: Run tests
5659
if: matrix.ruby-version != '4.0' || matrix.rails-version != 'rails-8.1'
5760
run: bundle exec appraisal ${{ matrix.rails-version }} bin/rspec-queue

.github/workflows/pr-fast.yml

Lines changed: 0 additions & 36 deletions
This file was deleted.

.github/workflows/pr-heavy.yml

Lines changed: 0 additions & 29 deletions
This file was deleted.

.github/workflows/pr.yml

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
name: PR
2+
3+
on:
4+
pull_request:
5+
branches: ["main"]
6+
7+
permissions:
8+
contents: read
9+
10+
concurrency:
11+
group: pr-${{ github.event.pull_request.number || github.ref }}
12+
cancel-in-progress: true
13+
14+
jobs:
15+
gitleaks:
16+
uses: ./.github/workflows/_gitleaks.yml
17+
18+
lint:
19+
name: RuboCop
20+
uses: ./.github/workflows/_lint.yml
21+
with:
22+
ruby-version: "4.0"
23+
bundler-cache: false
24+
25+
test:
26+
uses: ./.github/workflows/_test-matrix.yml
27+
with:
28+
bundler-cache: false
29+
secrets: inherit

.overcommit.yml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,12 @@ PreCommit:
66

77
Flay:
88
enabled: true
9+
include:
10+
- 'lib/ruby_llm/**/*.rb'
11+
exclude:
12+
- 'lib/ruby_llm/providers/**/*.rb'
13+
- 'lib/ruby_llm/active_record/acts_as_legacy.rb'
14+
mass_threshold: 70
915

1016
RSpec:
1117
enabled: true

README.md

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -86,9 +86,7 @@ RubyLLM.moderate "Check if this text is safe"
8686
```ruby
8787
# Let AI use your code
8888
class Weather < RubyLLM::Tool
89-
description "Get current weather"
90-
param :latitude
91-
param :longitude
89+
desc "Get current weather"
9290

9391
def execute(latitude:, longitude:)
9492
url = "https://api.open-meteo.com/v1/forecast?latitude=#{latitude}&longitude=#{longitude}&current=temperature_2m,wind_speed_10m"

docs/Gemfile

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ group :jekyll_plugins do
99
gem 'jekyll-remote-theme'
1010
gem 'jekyll-seo-tag'
1111
gem 'jekyll-sitemap'
12-
gem 'jekyll-og-image', git: 'https://github.com/crmne/jekyll-og-image'
12+
gem 'jekyll-og-image'
1313
gem 'jekyll-redirect-from'
14+
gem 'jekyll-ai-visible-content'
1415
end

docs/_advanced/models.md

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,8 @@ The registry stores crucial information about each model, including:
4646
* **`supports_functions`**: If it can use [Tools]({% link _core_features/tools.md %}).
4747
* **`input_price_per_million`**: Cost in USD per 1 million input tokens.
4848
* **`output_price_per_million`**: Cost in USD per 1 million output tokens.
49+
* **`cache_read_input_price_per_million`**: Cost in USD per 1 million cache read tokens, when available. v1.15+
50+
* **`cache_write_input_price_per_million`**: Cost in USD per 1 million cache write tokens, when available. v1.15+
4951
* **`family`**: A broader classification (e.g., `gpt4o`).
5052

5153
This registry allows RubyLLM to validate models, route requests correctly, provide capability information, and offer convenient filtering.
@@ -206,6 +208,46 @@ model_bedrock = RubyLLM.models.find('{{ site.models.anthropic_current }}', :bedr
206208

207209
When you pass a provider, RubyLLM resolves aliases first. For Bedrock, it then applies region/inference-profile resolution (for example `us.` prefixes) before falling back to an exact ID match.
208210

211+
## Calculating Costs
212+
{: .d-inline-block }
213+
214+
v1.15+
215+
{: .label .label-green }
216+
217+
Models can turn token usage into a `RubyLLM::Cost` object:
218+
219+
```ruby
220+
model = RubyLLM.models.find('{{ site.models.default_chat }}')
221+
response = RubyLLM.chat(model: model.id, provider: model.provider).ask("Summarize Ruby's object model.")
222+
223+
cost = model.cost_for(response.tokens)
224+
puts cost.input
225+
puts cost.output
226+
puts cost.cache_read
227+
puts cost.cache_write
228+
puts cost.thinking
229+
puts cost.total
230+
```
231+
232+
Costs use RubyLLM's normalized token buckets: standard input, billable output, cache read, cache write, and separately priced thinking when the model registry exposes a distinct reasoning-token price. See [Tracking Token Usage]({% link _core_features/chat.md %}#tracking-token-usage) for the provider comparison table and what RubyLLM exposes consistently across providers.
233+
234+
Most applications use the shorter helpers on messages, chats, and agents:
235+
236+
```ruby
237+
response.cost.total
238+
chat.cost.total
239+
agent.cost.total
240+
```
241+
242+
To combine several cost objects yourself, use `RubyLLM::Cost.aggregate`:
243+
244+
```ruby
245+
cost = RubyLLM::Cost.aggregate(messages.map(&:cost))
246+
cost.total
247+
```
248+
249+
If pricing is incomplete for tokens that were used, the affected cost and `cost.total` return `nil`. Cost helpers cover token-priced conversation usage; provider-specific add-ons such as search-query charges remain available in the provider's raw usage payload.
250+
209251
## Connecting to Custom Endpoints & Using Unlisted Models
210252
{: .d-inline-block }
211253

0 commit comments

Comments
 (0)