dspy 0.27.4 → 0.27.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: dca273acbd2ba8ab0ab9e2980bdf8048cc9ea80b3ce1b74d6f1e911e165ae895
4
- data.tar.gz: '08177e7841275140c7f074ac3a700883f06c6610c9bfd4795d142a3c838c0b24'
3
+ metadata.gz: d8a0e5d292482730715265985f5334aa60853c2146c9dde2dc18ffa9b882ca6d
4
+ data.tar.gz: 9ae0827c01495b38b9250714254d841948a1191b74e3f7af59360f1b2e4705c1
5
5
  SHA512:
6
- metadata.gz: 1b8d4bd756ab303688366fb0bcb5e5a3e045152c5695a8cdcd5291ca6313fc8ee7bd8051c6026663cfda0ec429b7977aa2355442595ba803bfedafd3926e89b6
7
- data.tar.gz: 30efa43a8bc34708003a178d7715ae6688268b4b63e98789f011e47f7d36b8c30f292ac986c8df3767bafa517b7b73f5ff7fa92fec8013732c69952dfa79df71
6
+ metadata.gz: b7912c2a40ea8f036211bf7553cac71746cfbf0b24790cb3a69df0bf513771fbcdf7d317d5e492ea8354b46acca0b17d62bd02a3a2debaf191343ff7934df68c
7
+ data.tar.gz: cafc3cd07f94829e3aae3277630c2a875b6c2cfb982ca64fa493531b6274fe10079fca447824b42d31d8d1a7a4bb43714e5256d3ce7505e31b01a5d4b10007df
data/lib/dspy/re_act.rb CHANGED
@@ -369,13 +369,22 @@ module DSPy
369
369
  sig { params(input_kwargs: T::Hash[Symbol, T.untyped], reasoning_result: T::Hash[Symbol, T.untyped]).returns(T.untyped) }
370
370
  def create_enhanced_result(input_kwargs, reasoning_result)
371
371
  output_field_name = @original_signature_class.output_struct_class.props.keys.first
372
+ final_answer = reasoning_result[:final_answer]
372
373
 
373
374
  output_data = input_kwargs.merge({
374
375
  history: reasoning_result[:history].map(&:to_h),
375
376
  iterations: reasoning_result[:iterations],
376
377
  tools_used: reasoning_result[:tools_used]
377
378
  })
378
- output_data[output_field_name] = reasoning_result[:final_answer]
379
+
380
+ # Check if final_answer is a String but the expected type is NOT String
381
+ # This happens when max iterations is reached or the LLM generates an error message
382
+ output_field_type = @original_signature_class.output_struct_class.props[output_field_name][:type_object]
383
+ if final_answer.is_a?(String) && !string_compatible_type?(output_field_type)
384
+ output_data[output_field_name] = default_value_for_type(output_field_type)
385
+ else
386
+ output_data[output_field_name] = final_answer
387
+ end
379
388
 
380
389
  @enhanced_output_struct.new(**output_data)
381
390
  end
@@ -502,6 +511,56 @@ module DSPy
502
511
  "No answer reached within #{@max_iterations} iterations"
503
512
  end
504
513
 
514
+ # Checks if a type is String or compatible with String (e.g., T.any(String, ...) or T.nilable(String))
515
+ sig { params(type_object: T.untyped).returns(T::Boolean) }
516
+ def string_compatible_type?(type_object)
517
+ case type_object
518
+ when T::Types::Simple
519
+ type_object.raw_type == String
520
+ when T::Types::Union
521
+ # Check if any of the union types is String
522
+ type_object.types.any? { |t| t.is_a?(T::Types::Simple) && t.raw_type == String }
523
+ else
524
+ false
525
+ end
526
+ end
527
+
528
+ # Returns an appropriate default value for a given Sorbet type
529
+ # This is used when max iterations is reached without a successful completion
530
+ sig { params(type_object: T.untyped).returns(T.untyped) }
531
+ def default_value_for_type(type_object)
532
+ # Handle TypedArray (T::Array[...])
533
+ if type_object.is_a?(T::Types::TypedArray)
534
+ return []
535
+ end
536
+
537
+ # Handle TypedHash (T::Hash[...])
538
+ if type_object.is_a?(T::Types::TypedHash)
539
+ return {}
540
+ end
541
+
542
+ # Handle simple types
543
+ case type_object
544
+ when T::Types::Simple
545
+ raw_type = type_object.raw_type
546
+ case raw_type.to_s
547
+ when 'String' then ''
548
+ when 'Integer' then 0
549
+ when 'Float' then 0.0
550
+ when 'TrueClass', 'FalseClass' then false
551
+ else
552
+ # For T::Struct types, return nil as fallback
553
+ nil
554
+ end
555
+ when T::Types::Union
556
+ # For unions, return nil (assuming it's nilable) or first non-nil default
557
+ nil
558
+ else
559
+ # Default fallback for unknown types
560
+ nil
561
+ end
562
+ end
563
+
505
564
  # Tool execution method
506
565
  sig { params(action: String, action_input: T.untyped).returns(String) }
507
566
  def execute_action(action, action_input)
data/lib/dspy/version.rb CHANGED
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module DSPy
4
- VERSION = "0.27.4"
4
+ VERSION = "0.27.5"
5
5
  end
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: dspy
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.27.4
4
+ version: 0.27.5
5
5
  platform: ruby
6
6
  authors:
7
7
  - Vicente Reig Rincón de Arellano
8
8
  bindir: bin
9
9
  cert_chain: []
10
- date: 2025-09-25 00:00:00.000000000 Z
10
+ date: 2025-09-30 00:00:00.000000000 Z
11
11
  dependencies:
12
12
  - !ruby/object:Gem::Dependency
13
13
  name: dry-configurable