Class: Desiru::Modules::ProgramOfThought

Inherits:
Desiru::Module show all
Defined in:
lib/desiru/modules/program_of_thought.rb

Overview

ProgramOfThought module that generates executable code to solve problems Similar to ChainOfThought but produces code instead of reasoning steps Supports both Ruby and Python code generation

Constant Summary collapse

DEFAULT_SIGNATURE =
'question: string -> answer: string, code: string'

Instance Attribute Summary

Attributes inherited from Desiru::Module

#config, #demos, #metadata, #model, #signature

Instance Method Summary collapse

Methods inherited from Desiru::Module

#call, #reset, #to_h, #with_demos

Methods included from AsyncCapable

#call_async, #call_batch_async

Methods included from ErrorHandling

#safe_execute, #with_error_context, #with_retry

Methods included from Core::Traceable

#call, #disable_trace!, #enable_trace!, #trace_enabled?

Constructor Details

#initialize(signature = nil, model: nil, **kwargs) ⇒ ProgramOfThought

Returns a new instance of ProgramOfThought.



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
# File 'lib/desiru/modules/program_of_thought.rb', line 13

def initialize(signature = nil, model: nil, **kwargs)
  # Extract our specific options before passing to parent
  @max_iterations = kwargs.delete(:max_iterations) || 1
  @code_language = validate_language(kwargs.delete(:code_language) || 'ruby')
  @timeout = kwargs.delete(:timeout) || 5 # seconds
  @safe_mode = kwargs.delete(:safe_mode) != false # default true

  # Use default signature if none provided
  signature ||= DEFAULT_SIGNATURE

  # If signature is a double/mock (for testing), store it directly
  if signature.respond_to?(:output_fields) && signature.respond_to?(:input_fields) &&
     !signature.is_a?(Signature) && !signature.is_a?(String)
    @signature = signature
    @model = model || Desiru.configuration.default_model
    @config = default_config.merge(kwargs[:config] || {})
    @demos = kwargs[:demos] || []
     = kwargs[:metadata] || {}
    @call_count = 0
    validate_model! if respond_to?(:validate_model!, true)
    register_module if respond_to?(:register_module, true)
  else
    # Pass remaining kwargs to parent (config, demos, metadata)
    super
  end
end

Instance Method Details

#forward(**inputs) ⇒ Object



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
70
71
72
73
74
75
# File 'lib/desiru/modules/program_of_thought.rb', line 40

def forward(**inputs)
   = { code_language: @code_language, safe_mode: @safe_mode }

  if defined?(Desiru::TraceContext) && Desiru::TraceContext.respond_to?(:current) && Desiru::TraceContext.current
    Desiru::TraceContext.()
  elsif defined?(Desiru::Core) && Desiru::Core.respond_to?(:trace_context) &&
        Desiru::Core.trace_context.respond_to?(:current) && Desiru::Core.trace_context.current
    Desiru::Core.trace_context.()
  end

  # Enhance the prompt to request code generation
  code_prompt = build_code_prompt(inputs)

  # Get the model to generate code
  response = model.complete(
    messages: [{ role: 'user', content: code_prompt }],
    temperature: 0.3 # Lower temperature for more deterministic code
  )

  generated_code = extract_code(response[:content])

  Desiru.logger.debug("Generated #{@code_language} code: #{generated_code}")

  # Execute the generated code if safe
  result = if @safe_mode && !safe_to_execute?(generated_code)
             { error: "Generated code deemed unsafe to execute" }
           else
             execute_code(generated_code, inputs)
           end

  # Format outputs according to signature
  format_outputs(result, generated_code)
rescue StandardError => e
  Desiru.logger.error("ProgramOfThought error: #{e.message}")
  format_error_output(e, '')
end