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
|