Module: Ollama::Client::Chat

Defined in:
lib/ollama/client/chat.rb,
lib/ollama/client/chat/request_preparer.rb

Overview

Chat completion endpoint — the primary method for multi-turn conversations

Defined Under Namespace

Classes: RequestPreparer

Instance Method Summary collapse

Instance Method Details

#chat(messages:, model: nil, format: nil, tools: nil, stream: nil, think: nil, keep_alive: nil, options: nil, logprobs: nil, top_logprobs: nil, hooks: {}, profile: :auto, inputs: nil) ⇒ Ollama::Response

rubocop:disable Metrics/ParameterLists

Parameters:

  • messages (Array<Hash>)

    Chat history, each with :role and :content (required)

  • model (String, nil) (defaults to: nil)

    Model name override

  • format (Hash, String, nil) (defaults to: nil)

    "json" or JSON Schema object for structured output

  • tools (Array<Hash>, nil) (defaults to: nil)

    Function tools the model may call

  • stream (Boolean, nil) (defaults to: nil)

    Stream partial responses (default: determined by hooks)

  • think (Boolean, String, nil) (defaults to: nil)

    Enable thinking output (true/false/"high"/"medium"/"low")

  • keep_alive (String, nil) (defaults to: nil)

    Model keep-alive duration (e.g. "5m", "0")

  • options (Hash, nil) (defaults to: nil)

    Runtime options (temperature, top_p, num_ctx, etc.)

  • logprobs (Boolean, nil) (defaults to: nil)

    Return log probabilities

  • top_logprobs (Integer, nil) (defaults to: nil)

    Number of top logprobs to return

  • profile (:auto, false, ModelProfile) (defaults to: :auto)

    Capability profile for model-aware behavior

  • inputs (Array<Hash>, nil) (defaults to: nil)

    Typed multimodal inputs (overrides last user message)

  • hooks (Hash) (defaults to: {})

    Streaming callbacks: :on_token ->(text, logprobs=nil) — final-answer token :on_thought ->(text) — reasoning/thinking token :on_tool_call ->(tool_call_hash) — tool call ready :on_error ->(error) — stream or connection error :on_complete -> — stream finished

Returns:

  • (Ollama::Response)

    Response wrapper with message, tool_calls, timing, etc.



33
34
35
36
37
38
39
40
41
42
43
44
# File 'lib/ollama/client/chat.rb', line 33

def chat(messages:, model: nil, format: nil, tools: nil, stream: nil,
         think: nil, keep_alive: nil, options: nil, logprobs: nil,
         top_logprobs: nil, hooks: {}, profile: :auto, inputs: nil)
  # rubocop:enable Metrics/ParameterLists
  params = Params::Chat.new(
    messages: messages, model: model, format: format, tools: tools,
    stream: stream, think: think, keep_alive: keep_alive, options: options,
    logprobs: logprobs, top_logprobs: top_logprobs, hooks: hooks,
    profile: profile, inputs: inputs
  )
  chat_with_params(params)
end

#chat_with_params(params) ⇒ Ollama::Response

rubocop:disable Metrics/AbcSize, Metrics/MethodLength

Parameters:

Returns:

  • (Ollama::Response)

    Response wrapper with message, tool_calls, timing, etc.



49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
# File 'lib/ollama/client/chat.rb', line 49

def chat_with_params(params)
  raise ArgumentError, "messages is required" if params.messages.nil? || params.messages.empty?

  preparer = RequestPreparer.new(config: @config, provider: @provider)
  request = preparer.build_request(params, self)

  serializer = Serializers::Chat.new
  transport_req = serializer.call(request)
  response_data = nil
  stream_enabled = request.stream
  config_timeout = request.[:timeout]
  target_model = request.model
  chat_uri = request.[:uri]

  begin
    with_rate_limit_key_rotation do |api_key|
      response_data = nil
      @config.apply_auth_to(transport_req, api_key: api_key) if transport_req.is_a?(Transport::Request)

      if stream_enabled
        buffer = +""
        processor = ChatStreamProcessor.new(params.hooks, provider: @provider)
        processor.send(:reset_accumulators!)

        @pipeline.stream(transport_req) do |chunk|
          processor.send(:drain_chunk, buffer, chunk)
        end

        response_data = processor.send(:build_result)
      else
        transport_response = @pipeline.call(transport_req)
        if transport_response.raw && !transport_response.raw.is_a?(Net::HTTPSuccess)
          handle_http_error(transport_response.raw,
                            requested_model: target_model)
        end

        parser = Parsers::Chat.new(provider: @provider)
        parsed_response = parser.call(transport_response)
        response_data = parsed_response.to_h
      end
    end
  rescue Net::ReadTimeout, Net::OpenTimeout => e
    params.hooks[:on_error]&.call(e)
    raise TimeoutError, "Request timed out after #{config_timeout}s"
  rescue Errno::ECONNREFUSED, Errno::EHOSTUNREACH, SocketError => e
    params.hooks[:on_error]&.call(e)
    raise Error, "Connection failed: #{e.message}"
  rescue Error => e
    params.hooks[:on_error]&.call(e)
    raise e
  end

  emit_response_hook(response_data.is_a?(Hash) ? response_data.to_json : response_data,
                     endpoint: chat_uri.path, model: target_model)

  Responses::Chat.new(response_data)
rescue JSON::ParserError => e
  raise InvalidJSONError, "Failed to parse chat response: #{e.message}"
end