Class: RubyLLM::Instructor::Client

Inherits:
Object
  • Object
show all
Defined in:
lib/ruby_llm/instructor/client.rb

Constant Summary collapse

VALID_MODES =
%i[schema tools].freeze

Instance Method Summary collapse

Instance Method Details

#chat(model:, response_model:, prompt:, max_retries: 3, stream: nil, mode: :schema) ⇒ Object



8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
# File 'lib/ruby_llm/instructor/client.rb', line 8

def chat(model:, response_model:, prompt:, max_retries: 3, stream: nil, mode: :schema)
  unless VALID_MODES.include?(mode)
    raise ArgumentError, "Unknown mode #{mode.inspect}. Valid modes are: #{VALID_MODES.join(', ')}"
  end

  compiled_schema = Adapters::RubyLlmSchemaAdapter.new(response_model).build_schema
  current_prompt = prompt
  retries = 0

  begin
    session = RubyLLM.chat(model: model)
    response = mode == :tools ? via_tools(session, compiled_schema, current_prompt, stream)
                              : via_schema(session, compiled_schema, current_prompt, stream)
    parsed_data = response.content

    unless parsed_data.is_a?(Hash)
      raise ValidationError,
            "Expected a structured JSON object matching the schema, " \
            "got #{parsed_data.class} (#{parsed_data.inspect[0, 200]})"
    end

    errors = validate_payload(response_model, parsed_data)
    raise ValidationError, errors.join(", ") if errors.any?

    build_instance(response_model, parsed_data)

  rescue ValidationError => e
    if retries < max_retries
      retries += 1
      current_prompt = "Original task: #{prompt}\n\n" \
                       "Your previous response failed validation: #{e.message}. " \
                       "Please fix the data to match the schema exactly."
      retry
    else
      raise ValidationError, "ruby_llm-instructor failed validation after #{max_retries} attempts. Errors: #{e.message}"
    end
  end
end