Module: Ollama::Client::Generate

Included in:
Ollama::Client
Defined in:
lib/ollama/client/generate.rb

Overview

Generate completion endpoint with auto-pull, retries, and structured output

Instance Method Summary collapse

Instance Method Details

#generate(prompt:, schema: nil, model: nil, strict: nil, return_meta: false, system: nil, images: nil, think: nil, return_reasoning: false, keep_alive: nil, suffix: nil, raw: nil, options: nil, hooks: {}) ⇒ Object

rubocop:disable Metrics/MethodLength, Metrics/ParameterLists

Parameters:

  • prompt (String)

    Text for the model to generate a response from (required)

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

    JSON Schema for structured output; also sets format

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

    Model name override

  • strict (Boolean) (defaults to: nil)

    Enable strict JSON validation + repair retries

  • return_meta (Boolean) (defaults to: false)

    When true, wraps response with metadata

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

    System prompt

  • images (Array<String>, nil) (defaults to: nil)

    Base64-encoded images for vision models

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

    Enable thinking output (true/false/“high”/“medium”/“low”)

  • return_reasoning (Boolean) (defaults to: false)

    Whether to extract and return reasoning structured separately

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

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

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

    Fill-in-the-middle text after prompt

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

    When true, skip prompt templating

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

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

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

    Streaming callbacks (:on_token, :on_error, :on_complete)

Raises:

  • (ArgumentError)


25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
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
# File 'lib/ollama/client/generate.rb', line 25

def generate(prompt:, schema: nil, model: nil, strict: nil, return_meta: false,
             system: nil, images: nil, think: nil, return_reasoning: false, keep_alive: nil, suffix: nil, raw: nil,
             options: nil, hooks: {})
  raise ArgumentError, "prompt is required" if prompt.nil?

  strict = @config.strict_json if strict.nil?

  validate_thinking_capability!(model, think)

  attempts = 0
  started_at = monotonic_time
  current_prompt = build_prompt(prompt, think, return_reasoning)
  pulled_models = []

  begin
    attempts += 1
    raw_response = call_generate_api(
      prompt: current_prompt, schema: schema, model: model, hooks: hooks,
      system: system, images: images, think: think, keep_alive: keep_alive,
      suffix: suffix, raw: raw, options: options
    )

    emit_response_hook(raw_response,
                       endpoint: "/api/generate", model: model || @config.model, attempt: attempts)

    response_data = process_generate_response(raw_response, schema, think, return_reasoning)
    format_response(response_data, return_meta, model, attempts, started_at)
  rescue NotFoundError => e
    target_model = model || @config.model
    raise enhance_not_found_error(e) if pulled_models.include?(target_model) || attempts > @config.retries

    pull(target_model)
    pulled_models << target_model
    retry
  rescue TimeoutError => e
    raise RetryExhaustedError, "Failed after #{attempts} attempts: #{e.message}" if attempts > @config.retries

    sleep(2**attempts)
    retry
  rescue InvalidJSONError, SchemaViolationError, ThinkingFormatError => e
    raise e if strict
    raise RetryExhaustedError, "Failed after #{attempts} attempts: #{e.message}" if attempts > @config.retries

    repair_msg = "CRITICAL FIX: Your last response was invalid or violated the schema. " \
                 "Error: #{e.message}. Return ONLY valid JSON."
    current_prompt = "#{current_prompt}\n\n#{repair_msg}"
    retry
  rescue HTTPError => e
    raise e unless e.retryable?
    raise RetryExhaustedError, "Failed after #{attempts} attempts: #{e.message}" if attempts > @config.retries

    retry
  rescue Error => e
    raise RetryExhaustedError, "Failed after #{attempts} attempts: #{e.message}" if attempts > @config.retries

    retry
  end
end