Class: Legion::Extensions::Llm::Ollama::Helpers::Callable

Inherits:
Object
  • Object
show all
Defined in:
lib/legion/extensions/llm/ollama/helpers/callable.rb

Overview

Callable wrapper for an Ollama provider instance. Implements the fleet dispatch ops (chat/stream_chat/embed/count_tokens) by delegating to a per-instance Ollama::Provider, plus the disconnect and normalize_dispatch_error contracts required by Inventory::CallableHandle and Routing::ProviderOutcome. Dispatch errors propagate untouched so normalize_dispatch_error can classify them.

Constant Summary collapse

COMPLETION_NAMED_KEYS =

Keys the base Provider exposes as named kwargs for the completion operations. Anything else the fleet passes (sampling scalars, temperature โ€” a Canonical::Params member, 05 O4) is folded into Canonical::Params at the dispatch boundary.

%i[tools schema thinking tool_prefs headers].freeze
EMBED_NAMED_KEYS =
%i[dimensions headers].freeze

Instance Method Summary collapse

Constructor Details

#initialize(instance_cfg:, logger:, provider: nil) ⇒ Callable

Returns a new instance of Callable.



27
28
29
30
31
32
# File 'lib/legion/extensions/llm/ollama/helpers/callable.rb', line 27

def initialize(instance_cfg:, logger:, provider: nil)
  @instance_cfg = instance_cfg
  @logger = logger
  @provider = provider
  @disconnected = false
end

Instance Method Details

#chat(messages, model:, **rest) ⇒ Object

Fleet and SelectionDispatch pass model as a RAW STRING (the offering's model id). Ollama's render path is string-tolerant (model.respond_to?(:id) ? model.id : model) for chat and embed, embed places the model verbatim in the 05 ยง3 embedding artifact, and count_tokens ignores it โ€” so the model passes through UNWRAPPED on every op. 0.8.0 callable contract: chat/stream_chat take the rehydrated message array positionally (WorkerExecution dispatch shape); count_tokens takes the messages: kwarg (worker_execution.rb); the Selection-derived model is a bare String.



52
53
54
55
56
57
58
59
# File 'lib/legion/extensions/llm/ollama/helpers/callable.rb', line 52

def chat(messages, model:, **rest)
  # Canonical boundary (N x N law): pipeline dispatch delivers
  # Canonical::Message objects only. Hash shapes are the bypass
  # class โ€” reject loudly, never coerce.
  provider.enforce_canonical_messages!(messages)
  named, params = split_fleet_kwargs(rest, COMPLETION_NAMED_KEYS)
  provider.chat(messages, model: model, params: canonical_params(params), **named)
end

#count_tokens(messages:, model:, **rest) ⇒ Object



72
73
74
75
76
# File 'lib/legion/extensions/llm/ollama/helpers/callable.rb', line 72

def count_tokens(messages:, model:, **rest)
  provider.enforce_canonical_messages!(messages)
  _named, params = split_fleet_kwargs(rest, [])
  provider.count_tokens(messages: messages, model: model, params: params)
end

#disconnectObject



36
37
38
39
40
# File 'lib/legion/extensions/llm/ollama/helpers/callable.rb', line 36

def disconnect
  @disconnected = true
  @provider&.disconnect
  @logger.debug { '[ollama][callable] disconnected' }
end

#disconnected?Boolean

Returns:

  • (Boolean)


34
# File 'lib/legion/extensions/llm/ollama/helpers/callable.rb', line 34

def disconnected? = @disconnected

#embed(text:, model:, **rest) ⇒ Object



67
68
69
70
# File 'lib/legion/extensions/llm/ollama/helpers/callable.rb', line 67

def embed(text:, model:, **rest)
  named, params = split_fleet_kwargs(rest, EMBED_NAMED_KEYS)
  provider.embed(text: text, model: model, params: params, **named)
end

#normalize_dispatch_error(error:) ⇒ Object



78
79
80
81
82
83
# File 'lib/legion/extensions/llm/ollama/helpers/callable.rb', line 78

def normalize_dispatch_error(error:)
  Legion::Extensions::Llm::Routing::ProviderOutcome.new(
    kind: classify_dispatch_error(error: error),
    reason: dispatch_reason(error)
  )
end

#stream_chat(messages, model:, **rest) ⇒ Object



61
62
63
64
65
# File 'lib/legion/extensions/llm/ollama/helpers/callable.rb', line 61

def stream_chat(messages, model:, **rest, &)
  provider.enforce_canonical_messages!(messages)
  named, params = split_fleet_kwargs(rest, COMPLETION_NAMED_KEYS)
  provider.stream_chat(messages, model: model, params: canonical_params(params), **named, &)
end