# RubyLLM 1.0

One Ruby API for OpenAI, Claude, Gemini, and more. Chat, tools, streaming, Rails integration. No ceremony.

I released [RubyLLM][rubyllm] 1.0 today.

When I started building [Chat with Work](https://chatwithwork.com), I wanted to write this:

```ruby
chat = RubyLLM.chat
chat.ask "What's the best way to learn Ruby?"
```

And have it work regardless of model or provider. No provider-specific client classes, no different response formats, no ceremony. Just a conversation.

That's RubyLLM. One API for OpenAI, Claude, Gemini, DeepSeek, and more.

## What it looks like

```ruby
chat = RubyLLM.chat
embedding = RubyLLM.embed("Ruby is elegant")
image = RubyLLM.paint("a sunset over mountains")
```

Switch models whenever you want. Don't specify one and you get a sensible default:

```ruby
chat = RubyLLM.chat(model: 'claude-3-5-sonnet')
chat.with_model('gpt-4o-mini')
```

Tool calling is a Ruby class, not JSON Schema gymnastics:

```ruby
class Search < RubyLLM::Tool
  description "Searches our knowledge base"
  param :query, desc: "Search query"
  param :limit, type: :integer, desc: "Max results", required: false

  def execute(query:, limit: 5)
    Document.search(query).limit(limit).map(&:title)
  end
end

chat.with_tool(Search).ask "Find our product documentation"
```

Streaming works the same way everywhere:

```ruby
chat.ask "Write a story about Ruby" do |chunk|
  print chunk.content
end
```

Token tracking is built in:

```ruby
response = chat.ask "Explain Ruby modules"
puts "This cost #{response.input_tokens + response.output_tokens} tokens"
```

Rails is a first-class citizen:

```ruby
class Chat < ApplicationRecord
  acts_as_chat
end

chat = Chat.create!(model_id: 'gemini-2.0-flash')
chat.ask "Hello"  # Everything persisted automatically
```

Vision, PDFs, and audio through the same interface:

```ruby
chat.ask "What's in this image?", with: { image: "photo.jpg" }
chat.ask "Summarize this document", with: { pdf: "contract.pdf" }
chat.ask "Transcribe this recording", with: { audio: "meeting.wav" }
```

Dependencies: Faraday, Zeitwerk, and a tiny event parser. That's it.

RubyLLM already powers [Chat with Work](https://chatwithwork.com) in production. `gem install ruby_llm` and [rubyllm.com][rubyllm] has the rest.

[rubyllm]: https://rubyllm.com
