Class: DSPy::Module

Inherits:
Object
  • Object
show all
Extended by:
T::Generic, T::Sig
Includes:
Callbacks, Dry::Configurable
Defined in:
lib/dspy/module.rb

Direct Known Subclasses

Predict

Defined Under Namespace

Modules: ForwardOverrideHooks Classes: SubcriptionScope

Constant Summary collapse

DEFAULT_MODULE_SUBSCRIPTION_SCOPE =
SubcriptionScope::Descendants

Class Method Summary collapse

Instance Method Summary collapse

Methods included from Callbacks

included

Class Method Details

.inherited(subclass) ⇒ Object



53
54
55
56
57
58
# File 'lib/dspy/module.rb', line 53

def inherited(subclass)
  super
  specs_copy = module_subscription_specs.map(&:dup)
  subclass.instance_variable_set(:@module_subscription_specs, specs_copy)
  subclass.extend(ForwardOverrideHooks)
end

.module_subscription_specsObject



72
73
74
# File 'lib/dspy/module.rb', line 72

def module_subscription_specs
  @module_subscription_specs ||= []
end

.subscribe(pattern, handler = nil, scope: DEFAULT_MODULE_SUBSCRIPTION_SCOPE, &block) ⇒ Object

Raises:

  • (ArgumentError)


60
61
62
63
64
65
66
67
68
69
70
# File 'lib/dspy/module.rb', line 60

def subscribe(pattern, handler = nil, scope: DEFAULT_MODULE_SUBSCRIPTION_SCOPE, &block)
  scope = normalize_scope(scope)
  raise ArgumentError, 'Provide a handler method or block' if handler.nil? && block.nil?

  module_subscription_specs << {
    pattern: pattern,
    handler: handler,
    block: block,
    scope: scope
  }
end

Instance Method Details

#call(**input_values) ⇒ Object



167
168
169
# File 'lib/dspy/module.rb', line 167

def call(**input_values)
  forward(**input_values)
end

#call_untyped(**input_values) ⇒ Object



173
174
175
# File 'lib/dspy/module.rb', line 173

def call_untyped(**input_values)
  forward_untyped(**input_values)
end

#configure(&block) ⇒ Object



234
235
236
237
238
# File 'lib/dspy/module.rb', line 234

def configure(&block)
  super(&block)
  propagate_lm_to_children(config.lm) if config.lm
  self
end

#configure_predictor(predictor_name, &block) ⇒ Object



251
252
253
254
255
256
257
258
259
# File 'lib/dspy/module.rb', line 251

def configure_predictor(predictor_name, &block)
  _, predictor = named_predictors.find { |name, _| name == predictor_name }
  unless predictor
    available = named_predictors.map(&:first).join(', ')
    raise ArgumentError, "Unknown predictor: #{predictor_name}. Available: #{available}"
  end
  predictor.configure(&block)
  self
end

#dup_for_threadObject



463
464
465
466
467
468
469
470
# File 'lib/dspy/module.rb', line 463

def dup_for_thread
  cloned = dup
  cloned.instance_variable_set(:@module_subscription_ids, [])
  cloned.instance_variable_set(:@module_subscriptions_registered, false)
  cloned.instance_variable_set(:@module_scope_id, SecureRandom.uuid)
  cloned.send(:reset_thread_state)
  cloned
end

#forward(**input_values) ⇒ Object



142
143
144
145
146
147
148
149
150
151
# File 'lib/dspy/module.rb', line 142

def forward(**input_values)
  result = if self.class.instance_method(:forward).owner == DSPy::Module
    instrument_forward_call([], input_values) do
      forward_untyped(**input_values)
    end
  else
    forward_untyped(**input_values)
  end
  T.cast(result, T.type_parameter(:O))
end

#forward_untyped(**input_values) ⇒ Object

Raises:

  • (NotImplementedError)


155
156
157
# File 'lib/dspy/module.rb', line 155

def forward_untyped(**input_values)
  raise NotImplementedError, "Subclasses must implement forward_untyped method"
end

#lmObject



179
180
181
# File 'lib/dspy/module.rb', line 179

def lm
  config.lm || DSPy.current_lm
end

#module_scope_idObject



436
437
438
# File 'lib/dspy/module.rb', line 436

def module_scope_id
  @module_scope_id ||= SecureRandom.uuid
end

#module_scope_labelObject



441
442
443
# File 'lib/dspy/module.rb', line 441

def module_scope_label
  @module_scope_label
end

#module_scope_label=(label) ⇒ Object



446
447
448
# File 'lib/dspy/module.rb', line 446

def module_scope_label=(label)
  @module_scope_label = label
end

#named_predictorsObject



211
212
213
# File 'lib/dspy/module.rb', line 211

def named_predictors
  []
end

#predictorsObject



216
217
218
# File 'lib/dspy/module.rb', line 216

def predictors
  named_predictors.map { |(_, predictor)| predictor }
end

#registered_module_subscriptionsObject



451
452
453
# File 'lib/dspy/module.rb', line 451

def registered_module_subscriptions
  Array(@module_subscription_ids).dup
end

#save(path) ⇒ Object



188
189
190
191
192
193
194
195
196
197
198
# File 'lib/dspy/module.rb', line 188

def save(path)
  require 'json'
  require 'fileutils'

  # Ensure parent directory exists
  dir = File.dirname(path)
  FileUtils.mkdir_p(dir) unless Dir.exist?(dir)

  # Serialize module to JSON
  File.write(path, JSON.pretty_generate(to_h))
end

#to_hObject



202
203
204
205
206
207
# File 'lib/dspy/module.rb', line 202

def to_h
  {
    class_name: self.class.name,
    state: {}
  }
end

#unsubscribe_module_eventsObject



456
457
458
459
460
# File 'lib/dspy/module.rb', line 456

def unsubscribe_module_events
  Array(@module_subscription_ids).each { |id| DSPy.events.unsubscribe(id) }
  @module_subscription_ids = []
  @module_subscriptions_registered = false
end