Class: LittleGhost::Model

Inherits:
Object
  • Object
show all
Defined in:
lib/little_ghost/model.rb

Overview

Model is the configured connection between an agent role and a provider. It keeps provider choice and defaults out of the agent class that uses them.

It merges profile settings into every ModelRequest, validates attachment modalities declared in metadata, lets providers prepare capability-sensitive requests, and delegates the normalized stream to the provider.

Constant Summary collapse

IDENTITY_METADATA_KEYS =

:nodoc:

%w[provider model_id model_role].freeze

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(provider:, provider_name:, id: nil, model: nil, settings: {}, metadata: {}, role: nil) ⇒ Model

Wraps an object that responds to stream.

Raises:

  • (ArgumentError)


18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
# File 'lib/little_ghost/model.rb', line 18

def initialize(provider:, provider_name:, id: nil, model: nil, settings: {}, metadata: {}, role: nil)
  raise ArgumentError, "provider must respond to stream" unless provider.respond_to?(:stream)
  raise ArgumentError, "provider_name is required" if provider_name.nil? || provider_name.to_s.empty?
  raise ArgumentError, "model is required" if (id || model).nil? || (id || model).to_s.empty?

  @provider = provider
  @provider_name = provider_name.to_sym
  @id = (id || model)&.to_s
  @settings = settings.to_h.transform_keys(&:to_sym).freeze
  @role = role&.to_s
   = .to_h.reject { |key, _value| IDENTITY_METADATA_KEYS.include?(key.to_s) }
  @metadata = .merge(
    provider: @provider_name,
    model_id: @id,
    model_role: @role
  ).freeze
end

Instance Attribute Details

#idObject (readonly)

Provider object and name, provider model ID, default settings, normalized metadata, and logical application role.



15
16
17
# File 'lib/little_ghost/model.rb', line 15

def id
  @id
end

#metadataObject (readonly)

Provider object and name, provider model ID, default settings, normalized metadata, and logical application role.



15
16
17
# File 'lib/little_ghost/model.rb', line 15

def 
  @metadata
end

#providerObject (readonly)

Provider object and name, provider model ID, default settings, normalized metadata, and logical application role.



15
16
17
# File 'lib/little_ghost/model.rb', line 15

def provider
  @provider
end

#provider_nameObject (readonly)

Provider object and name, provider model ID, default settings, normalized metadata, and logical application role.



15
16
17
# File 'lib/little_ghost/model.rb', line 15

def provider_name
  @provider_name
end

#roleObject (readonly)

Provider object and name, provider model ID, default settings, normalized metadata, and logical application role.



15
16
17
# File 'lib/little_ghost/model.rb', line 15

def role
  @role
end

#settingsObject (readonly)

Provider object and name, provider model ID, default settings, normalized metadata, and logical application role.



15
16
17
# File 'lib/little_ghost/model.rb', line 15

def settings
  @settings
end

Instance Method Details

#capabilitiesObject

Uses advertised provider capabilities, falling back to the permissive legacy contract for providers that do not advertise them.



59
60
61
62
63
64
65
# File 'lib/little_ghost/model.rb', line 59

def capabilities
  @capabilities ||= if provider.respond_to?(:capabilities)
    provider.capabilities(metadata:)
  else
    ModelCapabilities.legacy
  end
end

#stream(request, &block) ⇒ Object

Streams request through the configured provider.

Profile settings are defaults; settings on request take precedence.



39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
# File 'lib/little_ghost/model.rb', line 39

def stream(request, &block)
  validate_input_modalities!(request)
  configured_request = ModelRequest.new(
    messages: request.messages,
    tools: request.tools,
    settings: settings.merge(request.settings),
    output_schema: request.output_schema,
    tool_choice: request.tool_choice,
    required_capabilities: request.required_capabilities,
    cancellation_token: request.cancellation_token,
    deadline: request.deadline
  )
  if provider.respond_to?(:prepare_request)
    configured_request = provider.prepare_request(configured_request, capabilities:)
  end
  provider.stream(configured_request, &block)
end