Class: PatientLLM::Callback

Inherits:
Object
  • Object
show all
Defined in:
lib/patient_llm/callback.rb

Overview

Callback class that receives async HTTP responses from PatientHttp and dispatches to the user’s callback.

When the response contains tool calls and the global PromptBuilder tool registry has handlers for those tools, this class executes them automatically and re-issues the request until the model returns a final text response or a tool raises HaltError. Iteration is capped at MAX_TOOL_ITERATIONS to prevent runaway loops.

The user callback receives a ‘PromptBuilder::Response` object. Access the response text via `response.text`, token usage via `response.usage`, and model id via `response.model`.

Constant Summary collapse

MAX_TOOL_ITERATIONS =

Maximum number of tool-execution rounds before the loop raises.

10
CALLBACK_PARAMS =

Supported keyword parameters for each user callback method, along with the one parameter that must always be declared.

{
  on_complete: {allowed: %i[session provider llm_response callback_args http_response request_id]},
  on_tool_use: {allowed: %i[session provider llm_response callback_args http_response request_id]},
  on_error: {allowed: %i[session provider callback_args error http_response request_id], required: :error}
}.freeze

Class Method Summary collapse

Instance Method Summary collapse

Class Method Details

.validate_callback_class!(callback_class) ⇒ void

This method returns an undefined value.

Validate that a user callback class declares supported keyword parameters.

Each defined callback method must use keyword parameters drawn from the supported set for that method and must declare the required parameter (‘error` is required for on_error). A `**kwargs` splat is permitted and receives every available value.

Parameters:

  • callback_class (Class)

    The user callback class

Raises:

  • (ArgumentError)

    If a method uses positional or unsupported parameters



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
# File 'lib/patient_llm/callback.rb', line 40

def self.validate_callback_class!(callback_class)
  CALLBACK_PARAMS.each do |method_name, spec|
    next unless callback_class.method_defined?(method_name)

    params = callback_class.instance_method(method_name).parameters
    splat = params.any? { |type, _| type == :keyrest }
    declared = []
    params.each do |type, name|
      case type
      when :key, :keyreq
        declared << name
      when :keyrest, :block
        next
      else
        raise ArgumentError, "#{callback_class}##{method_name} must use keyword parameters; found positional parameter #{name.inspect}"
      end
    end

    allowed = Array(spec[:allowed])
    unknown = declared - allowed
    unless unknown.empty?
      raise ArgumentError, "#{callback_class}##{method_name} has unsupported parameter(s): #{unknown.map(&:inspect).join(", ")}. Allowed: #{allowed.map(&:inspect).join(", ")}"
    end

    required = Array(spec[:required])
    unless splat || required.empty? || (required & declared).any?
      raise ArgumentError, "#{callback_class}##{method_name} must declare the #{required.map(&:inspect).join(", ")} keyword parameter(s)"
    end
  end
end

Instance Method Details

#on_complete(response) ⇒ void

This method returns an undefined value.

Handle a successful LLM completion response.

Parameters:

  • response (PatientHttp::Response)

    The async HTTP response



75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
# File 'lib/patient_llm/callback.rb', line 75

def on_complete(response)
  callback_args = response.callback_args
  session = restore_session(callback_args)
  provider_name = callback_args[:provider]
  request_options = callback_args[:request_options] || {}
  user_callback = resolve_user_callback(callback_args)
  original_request_id = callback_args.fetch(:original_request_id, nil) || response.request_id

  serializer = resolve_serializer(provider_name, request_options)
  llm_response = PromptBuilder::Response.parse(response.json, serializer)

  if should_auto_execute_tools?(llm_response)
    continue_tool_loop(session, provider_name, llm_response, callback_args, response, user_callback, request_options, original_request_id)
  else
    session.add_response(llm_response)
    invoke_user_callback(user_callback, :on_complete, session: session, provider: provider_name, llm_response: llm_response, callback_args: user_callback_args(callback_args), http_response: response, request_id: original_request_id)
  end
end

#on_error(error) ⇒ void

This method returns an undefined value.

Handle an error during an LLM request.

Parameters:

  • error (PatientHttp::Error)

    The error



98
99
100
101
102
103
104
105
106
# File 'lib/patient_llm/callback.rb', line 98

def on_error(error)
  callback_args = error.callback_args
  session = restore_session(callback_args)
  provider_name = callback_args[:provider]
  http_response = error.respond_to?(:response) ? error.response : nil
  original_request_id = callback_args.fetch(:original_request_id, http_response&.request_id)
  user_callback = resolve_user_callback(callback_args)
  invoke_user_callback(user_callback, :on_error, session: session, provider: provider_name, callback_args: user_callback_args(callback_args), error: error, http_response: http_response, request_id: original_request_id)
end