class RubyLLM::Chat
rubocop:disable Metrics/ClassLength
chat.ask “Can you elaborate on that?”
chat.ask “What’s the best way to learn Ruby?”
chat = RubyLLM.chat
Example:
streaming responses, and tool integration with a simple, conversational API.
Represents a conversation with an AI model. Handles message history,
def add_message(message_or_attributes)
def add_message(message_or_attributes) message = message_or_attributes.is_a?(Message) ? message_or_attributes : Message.new(message_or_attributes) messages << message message end
def add_tool_result(tool_use_id, result)
def add_tool_result(tool_use_id, result) add_message( role: :tool, content: result.is_a?(Hash) && result[:error] ? result[:error] : result.to_s, tool_call_id: tool_use_id ) end
def ask(message = nil, with: {}, &block)
def ask(message = nil, with: {}, &block) add_message role: :user, content: Content.new(message, with) complete(&block) end
def complete(&)
def complete(&) @on[:new_message]&.call response = @provider.complete(messages, tools: @tools, temperature: @temperature, model: @model.id, &) @on[:end_message]&.call(response) add_message response if response.tool_call? handle_tool_calls(response, &) else response end end
def each(&)
def each(&) messages.each(&) end
def execute_tool(tool_call)
def execute_tool(tool_call) tool = tools[tool_call.name.to_sym] args = tool_call.arguments tool.call(args) end
def handle_tool_calls(response, &)
def handle_tool_calls(response, &) response.tool_calls.each_value do |tool_call| @on[:new_message]&.call result = execute_tool tool_call message = add_tool_result tool_call.id, result @on[:end_message]&.call(message) end complete(&) end
def initialize(model: nil, provider: nil, assume_model_exists: false) # rubocop:disable Metrics/MethodLength
def initialize(model: nil, provider: nil, assume_model_exists: false) # rubocop:disable Metrics/MethodLength if assume_model_exists && !provider raise ArgumentError, 'Provider must be specified if assume_model_exists is true' end model_id = model || RubyLLM.config.default_model with_model(model_id, provider: provider, assume_exists: assume_model_exists) @temperature = 0.7 @messages = [] @tools = {} @on = { new_message: nil, end_message: nil } end
def on_end_message(&block)
def on_end_message(&block) @on[:end_message] = block self end
def on_new_message(&block)
def on_new_message(&block) @on[:new_message] = block self end
def with_instructions(instructions, replace: false)
def with_instructions(instructions, replace: false) @messages = @messages.reject! { |msg| msg.role == :system } if replace add_message role: :system, content: instructions self end
def with_model(model_id, provider: nil, assume_exists: false) # rubocop:disable Metrics/AbcSize,Metrics/MethodLength
def with_model(model_id, provider: nil, assume_exists: false) # rubocop:disable Metrics/AbcSize,Metrics/MethodLength if assume_exists raise ArgumentError, 'Provider must be specified if assume_exists is true' unless provider @provider = Provider.providers[provider.to_sym] || raise(Error, "Unknown provider: #{provider.to_sym}") @model = Struct.new(:id, :provider, :supports_functions, :supports_vision).new(model_id, provider, true, true) RubyLLM.logger.warn "Assuming model '#{model_id}' exists for provider '#{provider}'. " \ 'Capabilities may not be accurately reflected.' else @model = Models.find model_id, provider @provider = Provider.providers[@model.provider.to_sym] || raise(Error, "Unknown provider: #{@model.provider}") end self end
def with_temperature(temperature)
def with_temperature(temperature) @temperature = temperature self end
def with_tool(tool)
def with_tool(tool) unless @model.supports_functions raise UnsupportedFunctionsError, "Model #{@model.id} doesn't support function calling" end tool_instance = tool.is_a?(Class) ? tool.new : tool @tools[tool_instance.name.to_sym] = tool_instance self end
def with_tools(*tools)
def with_tools(*tools) tools.each { |tool| with_tool tool } self end